зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset f4964171a9c0 (bug 994320) and changeset a4655f5da435 (bug 994318) for bustage.
CLOSED TREE
This commit is contained in:
Родитель
ad46289006
Коммит
64675d893d
|
@ -26,7 +26,6 @@
|
|||
#include "nsIPrincipal.h"
|
||||
#include "nsIPropertyBag2.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsIWritablePropertyBag2.h"
|
||||
#include "nsString.h"
|
||||
#include "prlog.h"
|
||||
|
@ -46,47 +45,6 @@ GetCspContextLog()
|
|||
|
||||
#define CSPCONTEXTLOG(args) PR_LOG(GetCspContextLog(), 4, args)
|
||||
|
||||
static const uint32_t CSP_CACHE_URI_CUTOFF_SIZE = 512;
|
||||
|
||||
/**
|
||||
* Creates a key for use in the ShouldLoad cache.
|
||||
* Looks like: <uri>!<nsIContentPolicy::LOAD_TYPE>
|
||||
*/
|
||||
nsresult
|
||||
CreateCacheKey_Internal(nsIURI* aContentLocation,
|
||||
nsContentPolicyType aContentType,
|
||||
nsACString& outCacheKey)
|
||||
{
|
||||
if (!aContentLocation) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
bool isDataScheme = false;
|
||||
nsresult rv = aContentLocation->SchemeIs("data", &isDataScheme);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
outCacheKey.Truncate();
|
||||
if (aContentType != nsIContentPolicy::TYPE_SCRIPT && isDataScheme) {
|
||||
// For non-script data: URI, use ("data:", aContentType) as the cache key.
|
||||
outCacheKey.Append(NS_LITERAL_CSTRING("data:"));
|
||||
outCacheKey.AppendInt(aContentType);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoCString spec;
|
||||
rv = aContentLocation->GetSpec(spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Don't cache for a URI longer than the cutoff size.
|
||||
if (spec.Length() <= CSP_CACHE_URI_CUTOFF_SIZE) {
|
||||
outCacheKey.Append(spec);
|
||||
outCacheKey.Append(NS_LITERAL_CSTRING("!"));
|
||||
outCacheKey.AppendInt(aContentType);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* ===== nsIContentSecurityPolicy impl ====== */
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -116,16 +74,6 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
|
|||
// * Content Type is not whitelisted (CSP Reports, TYPE_DOCUMENT, etc).
|
||||
// * Fast Path for Apps
|
||||
|
||||
nsAutoCString cacheKey;
|
||||
rv = CreateCacheKey_Internal(aContentLocation, aContentType, cacheKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool isCached = mShouldLoadCache.Get(cacheKey, outDecision);
|
||||
if (isCached && cacheKey.Length() > 0) {
|
||||
// this is cached, use the cached value.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Default decision, CSP can revise it if there's a policy to enforce
|
||||
*outDecision = nsIContentPolicy::ACCEPT;
|
||||
|
||||
|
@ -189,11 +137,6 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
|
|||
// * Console error reporting, bug 994322
|
||||
}
|
||||
}
|
||||
// Done looping, cache any relevant result
|
||||
if (cacheKey.Length() > 0 && !isPreload) {
|
||||
mShouldLoadCache.Put(cacheKey, *outDecision);
|
||||
}
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
{
|
||||
nsAutoCString spec;
|
||||
|
@ -240,7 +183,6 @@ nsCSPContext::~nsCSPContext()
|
|||
for (uint32_t i = 0; i < mPolicies.Length(); i++) {
|
||||
delete mPolicies[i];
|
||||
}
|
||||
mShouldLoadCache.Clear();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -273,8 +215,6 @@ nsCSPContext::RemovePolicy(uint32_t aIndex)
|
|||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
mPolicies.RemoveElementAt(aIndex);
|
||||
// reset cache since effective policy changes
|
||||
mShouldLoadCache.Clear();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -297,8 +237,6 @@ nsCSPContext::AppendPolicy(const nsAString& aPolicyString,
|
|||
nsCSPPolicy* policy = nsCSPParser::parseContentSecurityPolicy(aPolicyString, mSelfURI, aReportOnly, 0);
|
||||
if (policy) {
|
||||
mPolicies.AppendElement(policy);
|
||||
// reset cache since effective policy changes
|
||||
mShouldLoadCache.Clear();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -440,118 +378,11 @@ nsCSPContext::SetRequestContext(nsIURI* aSelfURI,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Based on the given docshell, determines if this CSP context allows the
|
||||
* ancestry.
|
||||
*
|
||||
* In order to determine the URI of the parent document (one causing the load
|
||||
* of this protected document), this function obtains the docShellTreeItem,
|
||||
* then walks up the hierarchy until it finds a privileged (chrome) tree item.
|
||||
* Getting the parent's URI looks like this in pseudocode:
|
||||
*
|
||||
* nsIDocShell->QI(nsIInterfaceRequestor)
|
||||
* ->GI(nsIDocShellTreeItem)
|
||||
* ->QI(nsIInterfaceRequestor)
|
||||
* ->GI(nsIWebNavigation)
|
||||
* ->GetCurrentURI();
|
||||
*
|
||||
* aDocShell is the docShell for the protected document.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsCSPContext::PermitsAncestry(nsIDocShell* aDocShell, bool* outPermitsAncestry)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Can't check ancestry without a docShell.
|
||||
if (aDocShell == nullptr) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// For now, we allows permitsAncestry, this will be fixed in Bug 994320
|
||||
*outPermitsAncestry = true;
|
||||
|
||||
// extract the ancestry as an array
|
||||
nsCOMArray<nsIURI> ancestorsArray;
|
||||
|
||||
nsCOMPtr<nsIInterfaceRequestor> ir(do_QueryInterface(aDocShell));
|
||||
nsCOMPtr<nsIDocShellTreeItem> treeItem(do_GetInterface(ir));
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
|
||||
nsCOMPtr<nsIWebNavigation> webNav;
|
||||
nsCOMPtr<nsIURI> currentURI;
|
||||
nsCOMPtr<nsIURI> uriClone;
|
||||
|
||||
// iterate through each docShell parent item
|
||||
while (NS_SUCCEEDED(treeItem->GetParent(getter_AddRefs(parentTreeItem))) &&
|
||||
parentTreeItem != nullptr) {
|
||||
ir = do_QueryInterface(parentTreeItem);
|
||||
NS_ASSERTION(ir, "Could not QI docShellTreeItem to nsIInterfaceRequestor");
|
||||
|
||||
webNav = do_GetInterface(ir);
|
||||
NS_ENSURE_TRUE(webNav, NS_ERROR_FAILURE);
|
||||
|
||||
rv = webNav->GetCurrentURI(getter_AddRefs(currentURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (currentURI) {
|
||||
// stop when reaching chrome
|
||||
bool isChrome = false;
|
||||
rv = currentURI->SchemeIs("chrome", &isChrome);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (isChrome) { break; }
|
||||
|
||||
// delete the userpass from the URI.
|
||||
rv = currentURI->CloneIgnoringRef(getter_AddRefs(uriClone));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = uriClone->SetUserPass(EmptyCString());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
#ifdef PR_LOGGING
|
||||
{
|
||||
nsAutoCString spec;
|
||||
uriClone->GetSpec(spec);
|
||||
CSPCONTEXTLOG(("nsCSPContext::PermitsAncestry, found ancestor: %s", spec.get()));
|
||||
}
|
||||
#endif
|
||||
ancestorsArray.AppendElement(uriClone);
|
||||
}
|
||||
|
||||
// next ancestor
|
||||
treeItem = parentTreeItem;
|
||||
}
|
||||
|
||||
nsAutoString violatedDirective;
|
||||
|
||||
// Now that we've got the ancestry chain in ancestorsArray, time to check
|
||||
// them against any CSP.
|
||||
for (uint32_t i = 0; i < mPolicies.Length(); i++) {
|
||||
for (uint32_t a = 0; a < ancestorsArray.Length(); a++) {
|
||||
// TODO(sid) the mapping from frame-ancestors context to TYPE_DOCUMENT is
|
||||
// forced. while this works for now, we will implement something in
|
||||
// bug 999656.
|
||||
#ifdef PR_LOGGING
|
||||
{
|
||||
nsAutoCString spec;
|
||||
ancestorsArray[a]->GetSpec(spec);
|
||||
CSPCONTEXTLOG(("nsCSPContext::PermitsAncestry, checking ancestor: %s", spec.get()));
|
||||
}
|
||||
#endif
|
||||
if (!mPolicies[i]->permits(nsIContentPolicy::TYPE_DOCUMENT,
|
||||
ancestorsArray[a],
|
||||
EmptyString(), // no nonce
|
||||
violatedDirective)) {
|
||||
// Policy is violated
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
mozilla::services::GetObserverService();
|
||||
NS_ENSURE_TRUE(observerService, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
observerService->NotifyObservers(ancestorsArray[a],
|
||||
CSP_VIOLATION_TOPIC,
|
||||
violatedDirective.get());
|
||||
// TODO(sid) generate violation reports and remove NotifyObservers
|
||||
// call. (in bug 994322)
|
||||
// TODO(sid) implement logic for report-only (in bug 994322)
|
||||
*outPermitsAncestry = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#define nsCSPContext_h___
|
||||
|
||||
#include "nsCSPUtils.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
|
@ -37,9 +36,8 @@ class nsCSPContext : public nsIContentSecurityPolicy
|
|||
bool* outShouldReportViolations,
|
||||
bool* outIsAllowed) const;
|
||||
|
||||
nsTArray<nsCSPPolicy*> mPolicies;
|
||||
nsCOMPtr<nsIURI> mSelfURI;
|
||||
nsDataHashtable<nsCStringHashKey, int16_t> mShouldLoadCache;
|
||||
nsTArray<nsCSPPolicy*> mPolicies;
|
||||
nsCOMPtr<nsIURI> mSelfURI;
|
||||
};
|
||||
|
||||
#endif /* nsCSPContext_h___ */
|
||||
|
|
|
@ -636,8 +636,6 @@ CSP_DirectiveToContentType(enum CSPDirective aDir)
|
|||
case CSP_MEDIA_SRC: return nsIContentPolicy::TYPE_MEDIA;
|
||||
case CSP_OBJECT_SRC: return nsIContentPolicy::TYPE_OBJECT;
|
||||
case CSP_FRAME_SRC: return nsIContentPolicy::TYPE_SUBDOCUMENT;
|
||||
// TODO(sid): fix this mapping to be more precise (bug 999656)
|
||||
case CSP_FRAME_ANCESTORS: return nsIContentPolicy::TYPE_DOCUMENT;
|
||||
|
||||
// Fall through to error for the following Directives:
|
||||
case CSP_DEFAULT_SRC:
|
||||
|
|
|
@ -49,24 +49,22 @@ enum CSPDirective {
|
|||
CSP_FONT_SRC,
|
||||
CSP_CONNECT_SRC,
|
||||
CSP_REPORT_URI,
|
||||
CSP_FRAME_ANCESTORS,
|
||||
// CSP_LAST_DIRECTIVE_VALUE always needs to be the last element in the enum
|
||||
// because we use it to calculate the size for the char* array.
|
||||
CSP_LAST_DIRECTIVE_VALUE
|
||||
};
|
||||
|
||||
static const char* CSPStrDirectives[] = {
|
||||
"default-src", // CSP_DEFAULT_SRC = 0
|
||||
"script-src", // CSP_SCRIPT_SRC
|
||||
"object-src", // CSP_OBJECT_SRC
|
||||
"style-src", // CSP_STYLE_SRC
|
||||
"img-src", // CSP_IMG_SRC
|
||||
"media-src", // CSP_MEDIA_SRC
|
||||
"frame-src", // CSP_FRAME_SRC
|
||||
"font-src", // CSP_FONT_SRC
|
||||
"connect-src", // CSP_CONNECT_SRC
|
||||
"report-uri", // CSP_REPORT_URI
|
||||
"frame-ancestors" // CSP_FRAME_ANCESTORS
|
||||
"default-src", // CSP_DEFAULT_SRC = 0
|
||||
"script-src", // CSP_SCRIPT_SRC
|
||||
"object-src", // CSP_OBJECT_SRC
|
||||
"style-src", // CSP_STYLE_SRC
|
||||
"img-src", // CSP_IMG_SRC
|
||||
"media-src", // CSP_MEDIA_SRC
|
||||
"frame-src", // CSP_FRAME_SRC
|
||||
"font-src", // CSP_FONT_SRC
|
||||
"connect-src", // CSP_CONNECT_SRC
|
||||
"report-uri", // CSP_REPORT_URI
|
||||
};
|
||||
|
||||
inline const char* CSP_EnumToDirective(enum CSPDirective aDir)
|
||||
|
|
|
@ -667,28 +667,6 @@ nsresult TestGoodGeneratedPolicies() {
|
|||
"script-src http://policy-uri" },
|
||||
{ "img-src 'self'; ",
|
||||
"img-src http://www.selfuri.com" },
|
||||
{ "frame-ancestors foo-bar.com",
|
||||
"frame-ancestors http://foo-bar.com" },
|
||||
{ "frame-ancestors http://a.com",
|
||||
"frame-ancestors http://a.com" },
|
||||
{ "frame-ancestors 'self'",
|
||||
"frame-ancestors http://www.selfuri.com" },
|
||||
{ "frame-ancestors http://self.com:88",
|
||||
"frame-ancestors http://self.com:88" },
|
||||
{ "frame-ancestors http://a.b.c.d.e.f.g.h.i.j.k.l.x.com",
|
||||
"frame-ancestors http://a.b.c.d.e.f.g.h.i.j.k.l.x.com" },
|
||||
{ "frame-ancestors https://self.com:34",
|
||||
"frame-ancestors https://self.com:34" },
|
||||
{ "default-src 'none'; frame-ancestors 'self'",
|
||||
"default-src 'none'; frame-ancestors http://www.selfuri.com" },
|
||||
{ "frame-ancestors http://self:80",
|
||||
"frame-ancestors http://self:80" },
|
||||
{ "frame-ancestors http://self.com/bar",
|
||||
"frame-ancestors http://self.com" },
|
||||
{ "default-src 'self'; frame-ancestors 'self'",
|
||||
"default-src http://www.selfuri.com; frame-ancestors http://www.selfuri.com" },
|
||||
{ "frame-ancestors http://bar.com/foo.png",
|
||||
"frame-ancestors http://bar.com" },
|
||||
};
|
||||
|
||||
uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
|
||||
|
|
Загрузка…
Ссылка в новой задаче