mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1139297 - Implement CSP upgrade-insecure-requests directive - csp changes (r=sstamm)
This commit is contained in:
parent
51b48936c3
commit
12f19dc2be
@ -20,7 +20,7 @@ interface nsIURI;
|
||||
|
||||
typedef unsigned short CSPDirective;
|
||||
|
||||
[scriptable, uuid(059b94e3-45c2-4794-ac2a-5b66a66b5967)]
|
||||
[scriptable, uuid(b622b0f8-ee51-4f7a-8c23-b3bce20e752e)]
|
||||
interface nsIContentSecurityPolicy : nsISerializable
|
||||
{
|
||||
/**
|
||||
@ -32,23 +32,24 @@ interface nsIContentSecurityPolicy : nsISerializable
|
||||
* NOTE: When implementing a new directive, you will need to add it here but also
|
||||
* add it to the CSPStrDirectives array in nsCSPUtils.h.
|
||||
*/
|
||||
const unsigned short NO_DIRECTIVE = 0;
|
||||
const unsigned short DEFAULT_SRC_DIRECTIVE = 1;
|
||||
const unsigned short SCRIPT_SRC_DIRECTIVE = 2;
|
||||
const unsigned short OBJECT_SRC_DIRECTIVE = 3;
|
||||
const unsigned short STYLE_SRC_DIRECTIVE = 4;
|
||||
const unsigned short IMG_SRC_DIRECTIVE = 5;
|
||||
const unsigned short MEDIA_SRC_DIRECTIVE = 6;
|
||||
const unsigned short FRAME_SRC_DIRECTIVE = 7;
|
||||
const unsigned short FONT_SRC_DIRECTIVE = 8;
|
||||
const unsigned short CONNECT_SRC_DIRECTIVE = 9;
|
||||
const unsigned short REPORT_URI_DIRECTIVE = 10;
|
||||
const unsigned short FRAME_ANCESTORS_DIRECTIVE = 11;
|
||||
const unsigned short REFLECTED_XSS_DIRECTIVE = 12;
|
||||
const unsigned short BASE_URI_DIRECTIVE = 13;
|
||||
const unsigned short FORM_ACTION_DIRECTIVE = 14;
|
||||
const unsigned short REFERRER_DIRECTIVE = 15;
|
||||
const unsigned short WEB_MANIFEST_SRC_DIRECTIVE = 16;
|
||||
const unsigned short NO_DIRECTIVE = 0;
|
||||
const unsigned short DEFAULT_SRC_DIRECTIVE = 1;
|
||||
const unsigned short SCRIPT_SRC_DIRECTIVE = 2;
|
||||
const unsigned short OBJECT_SRC_DIRECTIVE = 3;
|
||||
const unsigned short STYLE_SRC_DIRECTIVE = 4;
|
||||
const unsigned short IMG_SRC_DIRECTIVE = 5;
|
||||
const unsigned short MEDIA_SRC_DIRECTIVE = 6;
|
||||
const unsigned short FRAME_SRC_DIRECTIVE = 7;
|
||||
const unsigned short FONT_SRC_DIRECTIVE = 8;
|
||||
const unsigned short CONNECT_SRC_DIRECTIVE = 9;
|
||||
const unsigned short REPORT_URI_DIRECTIVE = 10;
|
||||
const unsigned short FRAME_ANCESTORS_DIRECTIVE = 11;
|
||||
const unsigned short REFLECTED_XSS_DIRECTIVE = 12;
|
||||
const unsigned short BASE_URI_DIRECTIVE = 13;
|
||||
const unsigned short FORM_ACTION_DIRECTIVE = 14;
|
||||
const unsigned short REFERRER_DIRECTIVE = 15;
|
||||
const unsigned short WEB_MANIFEST_SRC_DIRECTIVE = 16;
|
||||
const unsigned short UPGRADE_IF_INSECURE_DIRECTIVE = 17;
|
||||
|
||||
/**
|
||||
* Accessor method for a read-only string version of the policy at a given
|
||||
@ -62,6 +63,13 @@ interface nsIContentSecurityPolicy : nsISerializable
|
||||
*/
|
||||
readonly attribute unsigned long policyCount;
|
||||
|
||||
/**
|
||||
* Returns whether this policy uses the directive upgrade-insecure-requests.
|
||||
* Please note that upgrade-insecure-reqeusts also applies if the parent or
|
||||
* including document (context) makes use of the directive.
|
||||
*/
|
||||
readonly attribute bool upgradeInsecureRequests;
|
||||
|
||||
/**
|
||||
* Obtains the referrer policy (as integer) for this browsing context as
|
||||
* specified in CSP. If there are multiple policies and...
|
||||
|
@ -54,6 +54,11 @@ inlineStyleBlocked = An attempt to apply inline style sheets has been blocked
|
||||
# LOCALIZATION NOTE (scriptFromStringBlocked):
|
||||
# eval is a name and should not be localized.
|
||||
scriptFromStringBlocked = An attempt to call JavaScript from a string (by calling a function like eval) has been blocked
|
||||
# LOCALIZATION NOTE (upgradeInsecureRequest):
|
||||
# %1$S is the URL of the upgraded request; %2$S is the upgraded scheme.
|
||||
upgradeInsecureRequest = Upgrading insecure request '%1$S' to use '%2$S'
|
||||
# LOCALIZATION NOTE (ignoreSrcForDirective):
|
||||
ignoreSrcForDirective = Ignoring srcs for directive '%1$S'
|
||||
# LOCALIZATION NOTE (hostNameMightBeKeyword):
|
||||
# %1$S is the hostname in question and %2$S is the keyword
|
||||
hostNameMightBeKeyword = Interpreting %1$S as a hostname, not a keyword. If you intended this to be a keyword, use '%2$S' (wrapped in single quotes).
|
||||
|
@ -304,6 +304,19 @@ nsCSPContext::GetPolicyCount(uint32_t *outPolicyCount)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCSPContext::GetUpgradeInsecureRequests(bool *outUpgradeRequest)
|
||||
{
|
||||
*outUpgradeRequest = false;
|
||||
for (uint32_t i = 0; i < mPolicies.Length(); i++) {
|
||||
if (mPolicies[i]->hasDirective(nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE)) {
|
||||
*outUpgradeRequest = true;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCSPContext::GetReferrerPolicy(uint32_t* outPolicy, bool* outIsSet)
|
||||
{
|
||||
|
@ -804,10 +804,7 @@ nsCSPParser::sourceExpression()
|
||||
resetCurValue();
|
||||
|
||||
// If mCurToken does not provide a scheme (scheme-less source), we apply the scheme
|
||||
// from selfURI but we also need to remember if the protected resource is http, in
|
||||
// which case we should allow https loads, see:
|
||||
// http://www.w3.org/TR/CSP2/#match-source-expression
|
||||
bool allowHttps = false;
|
||||
// from selfURI
|
||||
if (parsedScheme.IsEmpty()) {
|
||||
// Resetting internal helpers, because we might already have parsed some of the host
|
||||
// when trying to parse a scheme.
|
||||
@ -815,14 +812,13 @@ nsCSPParser::sourceExpression()
|
||||
nsAutoCString selfScheme;
|
||||
mSelfURI->GetScheme(selfScheme);
|
||||
parsedScheme.AssignASCII(selfScheme.get());
|
||||
allowHttps = selfScheme.EqualsASCII("http");
|
||||
}
|
||||
|
||||
// At this point we are expecting a host to be parsed.
|
||||
// Trying to create a new nsCSPHost.
|
||||
if (nsCSPHostSrc *cspHost = hostSource()) {
|
||||
// Do not forget to set the parsed scheme.
|
||||
cspHost->setScheme(parsedScheme, allowHttps);
|
||||
cspHost->setScheme(parsedScheme);
|
||||
return cspHost;
|
||||
}
|
||||
// Error was reported in hostSource()
|
||||
@ -992,6 +988,12 @@ nsCSPParser::directiveName()
|
||||
params, ArrayLength(params));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// special case handling for upgrade-insecure-requests
|
||||
if (CSP_IsDirective(mCurToken, nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE)) {
|
||||
return new nsUpgradeInsecureDirective(CSP_StringToCSPDirective(mCurToken));
|
||||
}
|
||||
|
||||
return new nsCSPDirective(CSP_StringToCSPDirective(mCurToken));
|
||||
}
|
||||
|
||||
@ -1023,6 +1025,20 @@ nsCSPParser::directive()
|
||||
return;
|
||||
}
|
||||
|
||||
// special case handling for upgrade-insecure-requests, which is only specified
|
||||
// by a directive name but does not include any srcs.
|
||||
if (cspDir->equals(nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE)) {
|
||||
if (mCurDir.Length() > 1) {
|
||||
const char16_t* params[] = { NS_LITERAL_STRING("upgrade-insecure-requests").get() };
|
||||
logWarningErrorToConsole(nsIScriptError::warningFlag,
|
||||
"ignoreSrcForDirective",
|
||||
params, ArrayLength(params));
|
||||
}
|
||||
// add the directive and return
|
||||
mPolicy->addUpgradeInsecDir(static_cast<nsUpgradeInsecureDirective*>(cspDir));
|
||||
return;
|
||||
}
|
||||
|
||||
// make sure to reset cache variables when trying to invalidate unsafe-inline;
|
||||
// unsafe-inline might not only appear in script-src, but also in default-src
|
||||
mHasHashOrNonce = false;
|
||||
|
@ -255,6 +255,59 @@ CSP_IsQuotelessKeyword(const nsAString& aKey)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks whether the current directive permits a specific
|
||||
* scheme. This function is called from nsCSPSchemeSrc() and
|
||||
* also nsCSPHostSrc.
|
||||
* @param aEnforcementScheme
|
||||
* The scheme that this directive allows
|
||||
* @param aUri
|
||||
* The uri of the subresource load.
|
||||
* @param aReportOnly
|
||||
* Whether the enforced policy is report only or not.
|
||||
* @param aUpgradeInsecure
|
||||
* Whether the policy makes use of the directive
|
||||
* 'upgrade-insecure-requests'.
|
||||
*/
|
||||
|
||||
bool
|
||||
permitsScheme(const nsAString& aEnforcementScheme,
|
||||
nsIURI* aUri,
|
||||
bool aReportOnly,
|
||||
bool aUpgradeInsecure)
|
||||
{
|
||||
nsAutoCString scheme;
|
||||
nsresult rv = aUri->GetScheme(scheme);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
// no scheme to enforce, let's allow the load (e.g. script-src *)
|
||||
if (aEnforcementScheme.IsEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// if the scheme matches, all good - allow the load
|
||||
if (aEnforcementScheme.EqualsASCII(scheme.get())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// allow scheme-less sources where the protected resource is http
|
||||
// and the load is https, see:
|
||||
// http://www.w3.org/TR/CSP2/#match-source-expression
|
||||
if (aEnforcementScheme.EqualsASCII("http") &&
|
||||
scheme.EqualsASCII("https")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Allow the load when enforcing upgrade-insecure-requests with the
|
||||
// promise the request gets upgraded from http to https and ws to wss.
|
||||
// See nsHttpChannel::Connect() and also WebSocket.cpp. Please note,
|
||||
// the report only policies should not allow the load and report
|
||||
// the error back to the page.
|
||||
return ((aUpgradeInsecure && !aReportOnly) &&
|
||||
((scheme.EqualsASCII("http") && aEnforcementScheme.EqualsASCII("https")) ||
|
||||
(scheme.EqualsASCII("ws") && aEnforcementScheme.EqualsASCII("wss"))));
|
||||
}
|
||||
|
||||
/* ===== nsCSPSrc ============================ */
|
||||
|
||||
nsCSPBaseSrc::nsCSPBaseSrc()
|
||||
@ -269,7 +322,8 @@ nsCSPBaseSrc::~nsCSPBaseSrc()
|
||||
// nsCSPKeywordSrc and nsCSPHashSource fall back to this base class
|
||||
// implementation which will never allow the load.
|
||||
bool
|
||||
nsCSPBaseSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const
|
||||
nsCSPBaseSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
|
||||
bool aReportOnly, bool aUpgradeInsecure) const
|
||||
{
|
||||
if (CSPUTILSLOGENABLED()) {
|
||||
nsAutoCString spec;
|
||||
@ -304,19 +358,16 @@ nsCSPSchemeSrc::~nsCSPSchemeSrc()
|
||||
}
|
||||
|
||||
bool
|
||||
nsCSPSchemeSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const
|
||||
nsCSPSchemeSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
|
||||
bool aReportOnly, bool aUpgradeInsecure) const
|
||||
{
|
||||
if (CSPUTILSLOGENABLED()) {
|
||||
nsAutoCString spec;
|
||||
aUri->GetSpec(spec);
|
||||
CSPUTILSLOG(("nsCSPSchemeSrc::permits, aUri: %s", spec.get()));
|
||||
}
|
||||
|
||||
NS_ASSERTION((!mScheme.EqualsASCII("")), "scheme can not be the empty string");
|
||||
nsAutoCString scheme;
|
||||
nsresult rv = aUri->GetScheme(scheme);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
return mScheme.EqualsASCII(scheme.get());
|
||||
MOZ_ASSERT((!mScheme.EqualsASCII("")), "scheme can not be the empty string");
|
||||
return permitsScheme(mScheme, aUri, aReportOnly, aUpgradeInsecure);
|
||||
}
|
||||
|
||||
void
|
||||
@ -330,7 +381,6 @@ nsCSPSchemeSrc::toString(nsAString& outStr) const
|
||||
|
||||
nsCSPHostSrc::nsCSPHostSrc(const nsAString& aHost)
|
||||
: mHost(aHost)
|
||||
, mAllowHttps(false)
|
||||
{
|
||||
ToLowerCase(mHost);
|
||||
}
|
||||
@ -340,7 +390,8 @@ nsCSPHostSrc::~nsCSPHostSrc()
|
||||
}
|
||||
|
||||
bool
|
||||
nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const
|
||||
nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
|
||||
bool aReportOnly, bool aUpgradeInsecure) const
|
||||
{
|
||||
if (CSPUTILSLOGENABLED()) {
|
||||
nsAutoCString spec;
|
||||
@ -352,21 +403,8 @@ nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected
|
||||
// http://www.w3.org/TR/CSP11/#match-source-expression
|
||||
|
||||
// 4.3) scheme matching: Check if the scheme matches.
|
||||
nsAutoCString scheme;
|
||||
nsresult rv = aUri->GetScheme(scheme);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
if (!mScheme.IsEmpty() &&
|
||||
!mScheme.EqualsASCII(scheme.get())) {
|
||||
|
||||
// We should not return false for scheme-less sources where the protected resource
|
||||
// is http and the load is https, see:
|
||||
// http://www.w3.org/TR/CSP2/#match-source-expression
|
||||
bool isHttpsScheme =
|
||||
(NS_SUCCEEDED(aUri->SchemeIs("https", &isHttpsScheme)) && isHttpsScheme);
|
||||
|
||||
if (!(isHttpsScheme && mAllowHttps)) {
|
||||
return false;
|
||||
}
|
||||
if (!permitsScheme(mScheme, aUri, aReportOnly, aUpgradeInsecure)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The host in nsCSpHostSrc should never be empty. In case we are enforcing
|
||||
@ -396,7 +434,7 @@ nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected
|
||||
// Before we can check if the host matches, we have to
|
||||
// extract the host part from aUri.
|
||||
nsAutoCString uriHost;
|
||||
rv = aUri->GetHost(uriHost);
|
||||
nsresult rv = aUri->GetHost(uriHost);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
// 4.5) host matching: Check if the allowed host starts with a wilcard.
|
||||
@ -458,6 +496,11 @@ nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected
|
||||
int32_t uriPort;
|
||||
rv = aUri->GetPort(&uriPort);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
nsAutoCString scheme;
|
||||
rv = aUri->GetScheme(scheme);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
uriPort = (uriPort > 0) ? uriPort : NS_GetDefaultPort(scheme.get());
|
||||
|
||||
// 4.7) Default port matching: If mPort is empty, we have to compare default ports.
|
||||
@ -468,7 +511,7 @@ nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected
|
||||
// is http and the load is https, see: http://www.w3.org/TR/CSP2/#match-source-expression
|
||||
// BUT, we only allow scheme-less sources to be upgraded from http to https if CSP
|
||||
// does not explicitly define a port.
|
||||
if (!(uriPort == NS_GetDefaultPort("https") && mAllowHttps)) {
|
||||
if (!(uriPort == NS_GetDefaultPort("https"))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -515,11 +558,10 @@ nsCSPHostSrc::toString(nsAString& outStr) const
|
||||
}
|
||||
|
||||
void
|
||||
nsCSPHostSrc::setScheme(const nsAString& aScheme, bool aAllowHttps)
|
||||
nsCSPHostSrc::setScheme(const nsAString& aScheme)
|
||||
{
|
||||
mScheme = aScheme;
|
||||
ToLowerCase(mScheme);
|
||||
mAllowHttps = aAllowHttps;
|
||||
}
|
||||
|
||||
void
|
||||
@ -590,7 +632,8 @@ nsCSPNonceSrc::~nsCSPNonceSrc()
|
||||
}
|
||||
|
||||
bool
|
||||
nsCSPNonceSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const
|
||||
nsCSPNonceSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
|
||||
bool aReportOnly, bool aUpgradeInsecure) const
|
||||
{
|
||||
if (CSPUTILSLOGENABLED()) {
|
||||
nsAutoCString spec;
|
||||
@ -718,7 +761,8 @@ nsCSPDirective::~nsCSPDirective()
|
||||
}
|
||||
|
||||
bool
|
||||
nsCSPDirective::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const
|
||||
nsCSPDirective::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
|
||||
bool aReportOnly, bool aUpgradeInsecure) const
|
||||
{
|
||||
if (CSPUTILSLOGENABLED()) {
|
||||
nsAutoCString spec;
|
||||
@ -727,20 +771,13 @@ nsCSPDirective::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirect
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < mSrcs.Length(); i++) {
|
||||
if (mSrcs[i]->permits(aUri, aNonce, aWasRedirected)) {
|
||||
if (mSrcs[i]->permits(aUri, aNonce, aWasRedirected, aReportOnly, aUpgradeInsecure)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
nsCSPDirective::permits(nsIURI* aUri) const
|
||||
{
|
||||
nsString dummyNonce;
|
||||
return permits(aUri, dummyNonce, false);
|
||||
}
|
||||
|
||||
bool
|
||||
nsCSPDirective::allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce) const
|
||||
{
|
||||
@ -887,10 +924,29 @@ nsCSPDirective::getReportURIs(nsTArray<nsString> &outReportURIs) const
|
||||
}
|
||||
}
|
||||
|
||||
/* =============== nsUpgradeInsecureDirective ============= */
|
||||
|
||||
nsUpgradeInsecureDirective::nsUpgradeInsecureDirective(CSPDirective aDirective)
|
||||
: nsCSPDirective(aDirective)
|
||||
{
|
||||
}
|
||||
|
||||
nsUpgradeInsecureDirective::~nsUpgradeInsecureDirective()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
nsUpgradeInsecureDirective::toString(nsAString& outStr) const
|
||||
{
|
||||
outStr.AppendASCII(CSP_CSPDirectiveToString(
|
||||
nsIContentSecurityPolicy::UPGRADE_IF_INSECURE_DIRECTIVE));
|
||||
}
|
||||
|
||||
/* ===== nsCSPPolicy ========================= */
|
||||
|
||||
nsCSPPolicy::nsCSPPolicy()
|
||||
: mReportOnly(false)
|
||||
: mUpgradeInsecDir(nullptr)
|
||||
, mReportOnly(false)
|
||||
{
|
||||
CSPUTILSLOG(("nsCSPPolicy::nsCSPPolicy"));
|
||||
}
|
||||
@ -936,7 +992,7 @@ nsCSPPolicy::permits(CSPDirective aDir,
|
||||
// These directive arrays are short (1-5 elements), not worth using a hashtable.
|
||||
for (uint32_t i = 0; i < mDirectives.Length(); i++) {
|
||||
if (mDirectives[i]->equals(aDir)) {
|
||||
if (!mDirectives[i]->permits(aUri, aNonce, aWasRedirected)) {
|
||||
if (!mDirectives[i]->permits(aUri, aNonce, aWasRedirected, mReportOnly, mUpgradeInsecDir)) {
|
||||
mDirectives[i]->toString(outViolatedDirective);
|
||||
return false;
|
||||
}
|
||||
@ -950,7 +1006,7 @@ nsCSPPolicy::permits(CSPDirective aDir,
|
||||
// If the above loop runs through, we haven't found a matching directive.
|
||||
// Avoid relooping, just store the result of default-src while looping.
|
||||
if (!aSpecific && defaultDir) {
|
||||
if (!defaultDir->permits(aUri, aNonce, aWasRedirected)) {
|
||||
if (!defaultDir->permits(aUri, aNonce, aWasRedirected, mReportOnly, mUpgradeInsecDir)) {
|
||||
defaultDir->toString(outViolatedDirective);
|
||||
return false;
|
||||
}
|
||||
|
@ -70,23 +70,24 @@ void CSP_LogMessage(const nsAString& aMessage,
|
||||
// Order of elements below important! Make sure it matches the order as in
|
||||
// nsIContentSecurityPolicy.idl
|
||||
static const char* CSPStrDirectives[] = {
|
||||
"-error-", // NO_DIRECTIVE
|
||||
"default-src", // DEFAULT_SRC_DIRECTIVE
|
||||
"script-src", // SCRIPT_SRC_DIRECTIVE
|
||||
"object-src", // OBJECT_SRC_DIRECTIVE
|
||||
"style-src", // STYLE_SRC_DIRECTIVE
|
||||
"img-src", // IMG_SRC_DIRECTIVE
|
||||
"media-src", // MEDIA_SRC_DIRECTIVE
|
||||
"frame-src", // FRAME_SRC_DIRECTIVE
|
||||
"font-src", // FONT_SRC_DIRECTIVE
|
||||
"connect-src", // CONNECT_SRC_DIRECTIVE
|
||||
"report-uri", // REPORT_URI_DIRECTIVE
|
||||
"frame-ancestors", // FRAME_ANCESTORS_DIRECTIVE
|
||||
"reflected-xss", // REFLECTED_XSS_DIRECTIVE
|
||||
"base-uri", // BASE_URI_DIRECTIVE
|
||||
"form-action", // FORM_ACTION_DIRECTIVE
|
||||
"referrer", // REFERRER_DIRECTIVE
|
||||
"manifest-src" // MANIFEST_SRC_DIRECTIVE
|
||||
"-error-", // NO_DIRECTIVE
|
||||
"default-src", // DEFAULT_SRC_DIRECTIVE
|
||||
"script-src", // SCRIPT_SRC_DIRECTIVE
|
||||
"object-src", // OBJECT_SRC_DIRECTIVE
|
||||
"style-src", // STYLE_SRC_DIRECTIVE
|
||||
"img-src", // IMG_SRC_DIRECTIVE
|
||||
"media-src", // MEDIA_SRC_DIRECTIVE
|
||||
"frame-src", // FRAME_SRC_DIRECTIVE
|
||||
"font-src", // FONT_SRC_DIRECTIVE
|
||||
"connect-src", // CONNECT_SRC_DIRECTIVE
|
||||
"report-uri", // REPORT_URI_DIRECTIVE
|
||||
"frame-ancestors", // FRAME_ANCESTORS_DIRECTIVE
|
||||
"reflected-xss", // REFLECTED_XSS_DIRECTIVE
|
||||
"base-uri", // BASE_URI_DIRECTIVE
|
||||
"form-action", // FORM_ACTION_DIRECTIVE
|
||||
"referrer", // REFERRER_DIRECTIVE
|
||||
"manifest-src", // MANIFEST_SRC_DIRECTIVE
|
||||
"upgrade-insecure-requests" // UPGRADE_IF_INSECURE_DIRECTIVE
|
||||
};
|
||||
|
||||
inline const char* CSP_CSPDirectiveToString(CSPDirective aDir)
|
||||
@ -182,7 +183,8 @@ class nsCSPBaseSrc {
|
||||
nsCSPBaseSrc();
|
||||
virtual ~nsCSPBaseSrc();
|
||||
|
||||
virtual bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const;
|
||||
virtual bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
|
||||
bool aReportOnly, bool aUpgradeInsecure) const;
|
||||
virtual bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce) const;
|
||||
virtual void toString(nsAString& outStr) const = 0;
|
||||
};
|
||||
@ -194,7 +196,8 @@ class nsCSPSchemeSrc : public nsCSPBaseSrc {
|
||||
explicit nsCSPSchemeSrc(const nsAString& aScheme);
|
||||
virtual ~nsCSPSchemeSrc();
|
||||
|
||||
bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const;
|
||||
bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
|
||||
bool aReportOnly, bool aUpgradeInsecure) const;
|
||||
void toString(nsAString& outStr) const;
|
||||
|
||||
private:
|
||||
@ -208,10 +211,11 @@ class nsCSPHostSrc : public nsCSPBaseSrc {
|
||||
explicit nsCSPHostSrc(const nsAString& aHost);
|
||||
virtual ~nsCSPHostSrc();
|
||||
|
||||
bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const;
|
||||
bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
|
||||
bool aReportOnly, bool aUpgradeInsecure) const;
|
||||
void toString(nsAString& outStr) const;
|
||||
|
||||
void setScheme(const nsAString& aScheme, bool aAllowHttps = false);
|
||||
void setScheme(const nsAString& aScheme);
|
||||
void setPort(const nsAString& aPort);
|
||||
void appendPath(const nsAString &aPath);
|
||||
|
||||
@ -220,7 +224,6 @@ class nsCSPHostSrc : public nsCSPBaseSrc {
|
||||
nsString mHost;
|
||||
nsString mPort;
|
||||
nsString mPath;
|
||||
bool mAllowHttps;
|
||||
};
|
||||
|
||||
/* =============== nsCSPKeywordSrc ============ */
|
||||
@ -247,7 +250,8 @@ class nsCSPNonceSrc : public nsCSPBaseSrc {
|
||||
explicit nsCSPNonceSrc(const nsAString& aNonce);
|
||||
virtual ~nsCSPNonceSrc();
|
||||
|
||||
bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const;
|
||||
bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
|
||||
bool aReportOnly, bool aUpgradeInsecure) const;
|
||||
bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce) const;
|
||||
void toString(nsAString& outStr) const;
|
||||
|
||||
@ -287,17 +291,16 @@ class nsCSPReportURI : public nsCSPBaseSrc {
|
||||
|
||||
class nsCSPDirective {
|
||||
public:
|
||||
nsCSPDirective();
|
||||
explicit nsCSPDirective(CSPDirective aDirective);
|
||||
virtual ~nsCSPDirective();
|
||||
|
||||
bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const;
|
||||
bool permits(nsIURI* aUri) const;
|
||||
bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce) const;
|
||||
void toString(nsAString& outStr) const;
|
||||
virtual bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
|
||||
bool aReportOnly, bool aUpgradeInsecure) const;
|
||||
virtual bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce) const;
|
||||
virtual void toString(nsAString& outStr) const;
|
||||
void toDomCSPStruct(mozilla::dom::CSP& outCSP) const;
|
||||
|
||||
inline void addSrcs(const nsTArray<nsCSPBaseSrc*>& aSrcs)
|
||||
virtual void addSrcs(const nsTArray<nsCSPBaseSrc*>& aSrcs)
|
||||
{ mSrcs = aSrcs; }
|
||||
|
||||
bool restrictsContentType(nsContentPolicyType aContentType) const;
|
||||
@ -315,6 +318,58 @@ class nsCSPDirective {
|
||||
nsTArray<nsCSPBaseSrc*> mSrcs;
|
||||
};
|
||||
|
||||
/* =============== nsUpgradeInsecureDirective === */
|
||||
|
||||
/*
|
||||
* Upgrading insecure requests includes the following actors:
|
||||
* (1) CSP:
|
||||
* The CSP implementation whitelists the http-request
|
||||
* in case the policy is executed in enforcement mode.
|
||||
* The CSP implementation however does not allow http
|
||||
* requests to succeed if executed in report-only mode.
|
||||
* In such a case the CSP implementation reports the
|
||||
* error back to the page.
|
||||
*
|
||||
* (2) MixedContent:
|
||||
* The evalution of MixedContent whitelists all http
|
||||
* requests with the promise that the http requests
|
||||
* gets upgraded to https before any data is fetched
|
||||
* from the network.
|
||||
*
|
||||
* (3) CORS:
|
||||
* Does not consider the http request to be of a
|
||||
* different origin in case the scheme is the only
|
||||
* difference in otherwise matching URIs.
|
||||
*
|
||||
* (4) nsHttpChannel:
|
||||
* Before connecting, the channel gets redirected
|
||||
* to use https.
|
||||
*
|
||||
* (5) WebSocketChannel:
|
||||
* Similar to the httpChannel, the websocketchannel
|
||||
* gets upgraded from ws to wss.
|
||||
*/
|
||||
class nsUpgradeInsecureDirective : public nsCSPDirective {
|
||||
public:
|
||||
explicit nsUpgradeInsecureDirective(CSPDirective aDirective);
|
||||
~nsUpgradeInsecureDirective();
|
||||
|
||||
bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected,
|
||||
bool aReportOnly, bool aUpgradeInsecure) const
|
||||
{ return false; }
|
||||
|
||||
bool permits(nsIURI* aUri) const
|
||||
{ return false; }
|
||||
|
||||
bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce) const
|
||||
{ return false; }
|
||||
|
||||
void toString(nsAString& outStr) const;
|
||||
|
||||
void addSrcs(const nsTArray<nsCSPBaseSrc*>& aSrcs)
|
||||
{ MOZ_ASSERT(false, "upgrade-insecure-requests does not hold any srcs"); }
|
||||
};
|
||||
|
||||
/* =============== nsCSPPolicy ================== */
|
||||
|
||||
class nsCSPPolicy {
|
||||
@ -342,6 +397,12 @@ class nsCSPPolicy {
|
||||
inline void addDirective(nsCSPDirective* aDir)
|
||||
{ mDirectives.AppendElement(aDir); }
|
||||
|
||||
inline void addUpgradeInsecDir(nsUpgradeInsecureDirective* aDir)
|
||||
{
|
||||
mUpgradeInsecDir = aDir;
|
||||
addDirective(aDir);
|
||||
}
|
||||
|
||||
bool hasDirective(CSPDirective aDir) const;
|
||||
|
||||
inline void setReportOnlyFlag(bool aFlag)
|
||||
@ -367,9 +428,10 @@ class nsCSPPolicy {
|
||||
{ return mDirectives.Length(); }
|
||||
|
||||
private:
|
||||
nsTArray<nsCSPDirective*> mDirectives;
|
||||
bool mReportOnly;
|
||||
nsString mReferrerPolicy;
|
||||
nsUpgradeInsecureDirective* mUpgradeInsecDir;
|
||||
nsTArray<nsCSPDirective*> mDirectives;
|
||||
bool mReportOnly;
|
||||
nsString mReferrerPolicy;
|
||||
};
|
||||
|
||||
#endif /* nsCSPUtils_h___ */
|
||||
|
Loading…
Reference in New Issue
Block a user