Bug 783049 - CSP : use existing/old parser for X-Content-Security-Policy header, new/CSP 1.0 spec compliant parser for Content-Security-Policy header - Part 2 (r=bz)
This commit is contained in:
@@ -2288,18 +2288,51 @@ nsDocument::InitCSP(nsIChannel* aChannel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsAutoCString tCspHeaderValue, tCspROHeaderValue;
|
nsAutoCString tCspHeaderValue, tCspROHeaderValue;
|
||||||
|
nsAutoCString tCspOldHeaderValue, tCspOldROHeaderValue;
|
||||||
|
|
||||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
|
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
|
||||||
if (httpChannel) {
|
if (httpChannel) {
|
||||||
httpChannel->GetResponseHeader(
|
httpChannel->GetResponseHeader(
|
||||||
NS_LITERAL_CSTRING("x-content-security-policy"),
|
NS_LITERAL_CSTRING("x-content-security-policy"),
|
||||||
tCspHeaderValue);
|
tCspOldHeaderValue);
|
||||||
|
|
||||||
httpChannel->GetResponseHeader(
|
httpChannel->GetResponseHeader(
|
||||||
NS_LITERAL_CSTRING("x-content-security-policy-report-only"),
|
NS_LITERAL_CSTRING("x-content-security-policy-report-only"),
|
||||||
|
tCspOldROHeaderValue);
|
||||||
|
|
||||||
|
httpChannel->GetResponseHeader(
|
||||||
|
NS_LITERAL_CSTRING("content-security-policy"),
|
||||||
|
tCspHeaderValue);
|
||||||
|
|
||||||
|
httpChannel->GetResponseHeader(
|
||||||
|
NS_LITERAL_CSTRING("content-security-policy-report-only"),
|
||||||
tCspROHeaderValue);
|
tCspROHeaderValue);
|
||||||
}
|
}
|
||||||
NS_ConvertASCIItoUTF16 cspHeaderValue(tCspHeaderValue);
|
NS_ConvertASCIItoUTF16 cspHeaderValue(tCspHeaderValue);
|
||||||
NS_ConvertASCIItoUTF16 cspROHeaderValue(tCspROHeaderValue);
|
NS_ConvertASCIItoUTF16 cspROHeaderValue(tCspROHeaderValue);
|
||||||
|
NS_ConvertASCIItoUTF16 cspOldHeaderValue(tCspOldHeaderValue);
|
||||||
|
NS_ConvertASCIItoUTF16 cspOldROHeaderValue(tCspOldROHeaderValue);
|
||||||
|
|
||||||
|
// Until we want to turn on our CSP 1.0 spec compliant support
|
||||||
|
// only use the 1.0 spec compliant headers if a pref to do so
|
||||||
|
// is set (this lets us land CSP 1.0 support with tests without
|
||||||
|
// having to turn it on before it's ready). When we turn on
|
||||||
|
// CSP 1.0 in the release, we should remove this pref check.
|
||||||
|
// This pref will never be set by default, it should only
|
||||||
|
// be created/set by the CSP tests.
|
||||||
|
if (!cspHeaderValue.IsEmpty() || !cspROHeaderValue.IsEmpty()) {
|
||||||
|
bool specCompliantEnabled =
|
||||||
|
Preferences::GetBool("security.csp.speccompliant");
|
||||||
|
|
||||||
|
// If spec compliant pref isn't set, pretend we never got
|
||||||
|
// these headers.
|
||||||
|
if (!specCompliantEnabled) {
|
||||||
|
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||||
|
("Got spec compliant CSP headers but pref was not set"));
|
||||||
|
cspHeaderValue.Truncate();
|
||||||
|
cspROHeaderValue.Truncate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ----- Figure out if we need to apply an app default CSP
|
// ----- Figure out if we need to apply an app default CSP
|
||||||
bool applyAppDefaultCSP = false;
|
bool applyAppDefaultCSP = false;
|
||||||
@@ -2333,10 +2366,12 @@ nsDocument::InitCSP(nsIChannel* aChannel)
|
|||||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("Failed to get app status from principal"));
|
PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("Failed to get app status from principal"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// If there's no CSP to apply go ahead and return early
|
// If there's no CSP to apply, go ahead and return early
|
||||||
if (!applyAppDefaultCSP &&
|
if (!applyAppDefaultCSP &&
|
||||||
cspHeaderValue.IsEmpty() &&
|
cspHeaderValue.IsEmpty() &&
|
||||||
cspROHeaderValue.IsEmpty()) {
|
cspROHeaderValue.IsEmpty() &&
|
||||||
|
cspOldHeaderValue.IsEmpty() &&
|
||||||
|
cspOldROHeaderValue.IsEmpty()) {
|
||||||
#ifdef PR_LOGGING
|
#ifdef PR_LOGGING
|
||||||
nsCOMPtr<nsIURI> chanURI;
|
nsCOMPtr<nsIURI> chanURI;
|
||||||
aChannel->GetURI(getter_AddRefs(chanURI));
|
aChannel->GetURI(getter_AddRefs(chanURI));
|
||||||
@@ -2383,18 +2418,46 @@ nsDocument::InitCSP(nsIChannel* aChannel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (appCSP)
|
if (appCSP)
|
||||||
csp->RefinePolicy(appCSP, chanURI);
|
csp->RefinePolicy(appCSP, chanURI, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// While we are supporting both CSP 1.0 and the x- headers, the 1.0 headers
|
||||||
|
// take priority. If any spec-compliant headers are present, the x- headers
|
||||||
|
// are ignored, and the spec compliant parser is used.
|
||||||
|
bool cspSpecCompliant = (!cspHeaderValue.IsEmpty() || !cspROHeaderValue.IsEmpty());
|
||||||
|
|
||||||
|
// If the old header is present, warn that it will be deprecated.
|
||||||
|
if (!cspOldHeaderValue.IsEmpty() || !cspOldROHeaderValue.IsEmpty()) {
|
||||||
|
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
||||||
|
"CSP", this,
|
||||||
|
nsContentUtils::eDOM_PROPERTIES,
|
||||||
|
"OldCSPHeaderDeprecated");
|
||||||
|
|
||||||
|
// Also, if the new headers AND the old headers were present, warn
|
||||||
|
// that the old headers will be ignored.
|
||||||
|
if (cspSpecCompliant) {
|
||||||
|
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
||||||
|
"CSP", this,
|
||||||
|
nsContentUtils::eDOM_PROPERTIES,
|
||||||
|
"BothCSPHeadersPresent");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----- if there's a full-strength CSP header, apply it.
|
// ----- if there's a full-strength CSP header, apply it.
|
||||||
if (!cspHeaderValue.IsEmpty()) {
|
bool applyCSPFromHeader =
|
||||||
|
(( cspSpecCompliant && !cspHeaderValue.IsEmpty()) ||
|
||||||
|
(!cspSpecCompliant && !cspOldHeaderValue.IsEmpty()));
|
||||||
|
|
||||||
|
if (applyCSPFromHeader) {
|
||||||
// Need to tokenize the header value since multiple headers could be
|
// Need to tokenize the header value since multiple headers could be
|
||||||
// concatenated into one comma-separated list of policies.
|
// concatenated into one comma-separated list of policies.
|
||||||
// See RFC2616 section 4.2 (last paragraph)
|
// See RFC2616 section 4.2 (last paragraph)
|
||||||
nsCharSeparatedTokenizer tokenizer(cspHeaderValue, ',');
|
nsCharSeparatedTokenizer tokenizer(cspSpecCompliant ?
|
||||||
|
cspHeaderValue :
|
||||||
|
cspOldHeaderValue, ',');
|
||||||
while (tokenizer.hasMoreTokens()) {
|
while (tokenizer.hasMoreTokens()) {
|
||||||
const nsSubstring& policy = tokenizer.nextToken();
|
const nsSubstring& policy = tokenizer.nextToken();
|
||||||
csp->RefinePolicy(policy, chanURI);
|
csp->RefinePolicy(policy, chanURI, cspSpecCompliant);
|
||||||
#ifdef PR_LOGGING
|
#ifdef PR_LOGGING
|
||||||
{
|
{
|
||||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||||
@@ -2406,11 +2469,12 @@ nsDocument::InitCSP(nsIChannel* aChannel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ----- if there's a report-only CSP header, apply it
|
// ----- if there's a report-only CSP header, apply it
|
||||||
if (!cspROHeaderValue.IsEmpty()) {
|
if (( cspSpecCompliant && !cspROHeaderValue.IsEmpty()) ||
|
||||||
|
(!cspSpecCompliant && !cspOldROHeaderValue.IsEmpty())) {
|
||||||
// post a warning and skip report-only CSP when both read only and regular
|
// post a warning and skip report-only CSP when both read only and regular
|
||||||
// CSP policies are present since CSP only allows one policy and it can't
|
// CSP policies are present since CSP only allows one policy and it can't
|
||||||
// be partially report-only.
|
// be partially report-only.
|
||||||
if (applyAppDefaultCSP || !cspHeaderValue.IsEmpty()) {
|
if (applyAppDefaultCSP || applyCSPFromHeader) {
|
||||||
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
||||||
"CSP", this,
|
"CSP", this,
|
||||||
nsContentUtils::eDOM_PROPERTIES,
|
nsContentUtils::eDOM_PROPERTIES,
|
||||||
@@ -2427,10 +2491,12 @@ nsDocument::InitCSP(nsIChannel* aChannel)
|
|||||||
// Need to tokenize the header value since multiple headers could be
|
// Need to tokenize the header value since multiple headers could be
|
||||||
// concatenated into one comma-separated list of policies.
|
// concatenated into one comma-separated list of policies.
|
||||||
// See RFC2616 section 4.2 (last paragraph)
|
// See RFC2616 section 4.2 (last paragraph)
|
||||||
nsCharSeparatedTokenizer tokenizer(cspROHeaderValue, ',');
|
nsCharSeparatedTokenizer tokenizer(cspSpecCompliant ?
|
||||||
|
cspROHeaderValue :
|
||||||
|
cspOldROHeaderValue, ',');
|
||||||
while (tokenizer.hasMoreTokens()) {
|
while (tokenizer.hasMoreTokens()) {
|
||||||
const nsSubstring& policy = tokenizer.nextToken();
|
const nsSubstring& policy = tokenizer.nextToken();
|
||||||
csp->RefinePolicy(policy, chanURI);
|
csp->RefinePolicy(policy, chanURI, cspSpecCompliant);
|
||||||
#ifdef PR_LOGGING
|
#ifdef PR_LOGGING
|
||||||
{
|
{
|
||||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||||
|
|||||||
@@ -1139,8 +1139,10 @@ GK_ATOM(withParam, "with-param")
|
|||||||
GK_ATOM(wizard, "wizard")
|
GK_ATOM(wizard, "wizard")
|
||||||
GK_ATOM(wrap, "wrap")
|
GK_ATOM(wrap, "wrap")
|
||||||
GK_ATOM(headerDNSPrefetchControl,"x-dns-prefetch-control")
|
GK_ATOM(headerDNSPrefetchControl,"x-dns-prefetch-control")
|
||||||
GK_ATOM(headerCSP, "x-content-security-policy")
|
GK_ATOM(headerOldCSP, "x-content-security-policy")
|
||||||
GK_ATOM(headerCSPReportOnly, "x-content-security-policy-report-only")
|
GK_ATOM(headerOldCSPReportOnly, "x-content-security-policy-report-only")
|
||||||
|
GK_ATOM(headerCSP, "content-security-policy")
|
||||||
|
GK_ATOM(headerCSPReportOnly, "content-security-policy-report-only")
|
||||||
GK_ATOM(headerXFO, "x-frame-options")
|
GK_ATOM(headerXFO, "x-frame-options")
|
||||||
GK_ATOM(x_western, "x-western")
|
GK_ATOM(x_western, "x-western")
|
||||||
GK_ATOM(xml, "xml")
|
GK_ATOM(xml, "xml")
|
||||||
|
|||||||
@@ -120,3 +120,7 @@ PluginHangUIWaitButton=Continue
|
|||||||
PluginHangUIStopButton=Stop plugin
|
PluginHangUIStopButton=Stop plugin
|
||||||
# LOCALIZATION NOTE: Do not translate "mozHidden", "mozVisibilityState", "hidden", or "visibilityState"
|
# LOCALIZATION NOTE: Do not translate "mozHidden", "mozVisibilityState", "hidden", or "visibilityState"
|
||||||
PrefixedVisibilityApiWarning='mozHidden' and 'mozVisibilityState' are deprecated. Please use the unprefixed 'hidden' and 'visibilityState' instead.
|
PrefixedVisibilityApiWarning='mozHidden' and 'mozVisibilityState' are deprecated. Please use the unprefixed 'hidden' and 'visibilityState' instead.
|
||||||
|
# LOCALIZATION NOTE: Do not translate "X-Content-Security-Policy", "X-Content-Security-Policy-Report-Only", "Content-Security-Policy" or "Content-Security-Policy-Report-Only"
|
||||||
|
OldCSPHeaderDeprecated=The X-Content-Security-Policy and X-Content-Security-Report-Only headers will be deprecated in the future. Please use the Content-Security-Policy and Content-Security-Report-Only headers with CSP spec compliant syntax instead.
|
||||||
|
# LOCALIZATION NOTE: Do not translate "X-Content-Security-Policy" or "Content-Security-Policy"
|
||||||
|
BothCSPHeadersPresent=This site specified both an X-Content-Security-Policy/Report-Only header and a Content-Security-Policy/Report-Only header. The X-ContentSecurityPolicy/ReportOnly header(s) will be ignored.
|
||||||
@@ -636,6 +636,10 @@ nsViewSourceChannel::GetResponseHeader(const nsACString & aHeader,
|
|||||||
nsCaseInsensitiveCStringComparator()) &&
|
nsCaseInsensitiveCStringComparator()) &&
|
||||||
!aHeader.Equals(NS_LITERAL_CSTRING("X-Content-Security-Policy-Report-Only"),
|
!aHeader.Equals(NS_LITERAL_CSTRING("X-Content-Security-Policy-Report-Only"),
|
||||||
nsCaseInsensitiveCStringComparator()) &&
|
nsCaseInsensitiveCStringComparator()) &&
|
||||||
|
!aHeader.Equals(NS_LITERAL_CSTRING("Content-Security-Policy"),
|
||||||
|
nsCaseInsensitiveCStringComparator()) &&
|
||||||
|
!aHeader.Equals(NS_LITERAL_CSTRING("Content-Security-Policy-Report-Only"),
|
||||||
|
nsCaseInsensitiveCStringComparator()) &&
|
||||||
!aHeader.Equals(NS_LITERAL_CSTRING("X-Frame-Options"),
|
!aHeader.Equals(NS_LITERAL_CSTRING("X-Frame-Options"),
|
||||||
nsCaseInsensitiveCStringComparator())) {
|
nsCaseInsensitiveCStringComparator())) {
|
||||||
aValue.Truncate();
|
aValue.Truncate();
|
||||||
|
|||||||
Reference in New Issue
Block a user