Bug 808292 - CSP: Implement path-level host-source matching, utils modifications (r=grobinson,sstamm)

This commit is contained in:
Christoph Kerschbaumer 2014-08-12 12:55:08 -07:00
Родитель 84be8e5bca
Коммит 6745b594df
3 изменённых файлов: 53 добавлений и 28 удалений

Просмотреть файл

@ -173,6 +173,9 @@ nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
if (!mPolicies[p]->permits(aContentType,
aContentLocation,
nonce,
// aExtra is only non-null if
// the channel got redirected.
(aExtra != nullptr),
violatedDirective)) {
// If the policy is violated and not report-only, reject the load and
// report to the console
@ -792,7 +795,8 @@ class CSPReportSenderRunnable MOZ_FINAL : public nsRunnable
uint64_t aInnerWindowID,
nsCSPContext* aCSPContext)
: mBlockedContentSource(aBlockedContentSource)
, mOriginalURI(aOriginalURI) , mViolatedPolicyIndex(aViolatedPolicyIndex)
, mOriginalURI(aOriginalURI)
, mViolatedPolicyIndex(aViolatedPolicyIndex)
, mReportOnlyFlag(aReportOnlyFlag)
, mViolatedDirective(aViolatedDirective)
, mSourceFile(aSourceFile)
@ -1024,6 +1028,7 @@ nsCSPContext::PermitsAncestry(nsIDocShell* aDocShell, bool* outPermitsAncestry)
if (!mPolicies[i]->permits(nsIContentPolicy::TYPE_DOCUMENT,
ancestorsArray[a],
EmptyString(), // no nonce
false, // no redirect
violatedDirective)) {
// Policy is violated
// Send reports, but omit the ancestor URI if cross-origin as per spec

Просмотреть файл

@ -214,7 +214,7 @@ 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) const
nsCSPBaseSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const
{
#ifdef PR_LOGGING
{
@ -251,7 +251,7 @@ nsCSPSchemeSrc::~nsCSPSchemeSrc()
}
bool
nsCSPSchemeSrc::permits(nsIURI* aUri, const nsAString& aNonce) const
nsCSPSchemeSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const
{
#ifdef PR_LOGGING
{
@ -288,7 +288,7 @@ nsCSPHostSrc::~nsCSPHostSrc()
}
bool
nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce) const
nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const
{
#ifdef PR_LOGGING
{
@ -342,6 +342,34 @@ nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce) const
return false;
}
// If there is a path, we have to enforce path-level matching,
// unless the channel got redirected, see:
// http://www.w3.org/TR/CSP11/#source-list-paths-and-redirects
if (!aWasRedirected && !mPath.IsEmpty()) {
// cloning uri so we can ignore the ref
nsCOMPtr<nsIURI> uri;
aUri->CloneIgnoringRef(getter_AddRefs(uri));
nsAutoCString uriPath;
rv = uri->GetPath(uriPath);
NS_ENSURE_SUCCESS(rv, false);
// check if the last character of mPath is '/'; if so
// we just have to check loading resource is within
// the allowed path.
if (mPath.Last() == '/') {
if (!StringBeginsWith(NS_ConvertUTF8toUTF16(uriPath), mPath)) {
return false;
}
}
// otherwise mPath whitelists a specific file, and we have to
// check if the loading resource matches that whitelisted file.
else {
if (!mPath.Equals(NS_ConvertUTF8toUTF16(uriPath))) {
return false;
}
}
}
// If port uses wildcard, allow the load.
if (mPort.EqualsASCII("*")) {
return true;
@ -369,7 +397,7 @@ nsCSPHostSrc::permits(nsIURI* aUri, const nsAString& aNonce) const
}
}
// At the end: scheme, host, port, match; allow the load.
// At the end: scheme, host, path, and port match -> allow the load.
return true;
}
@ -397,9 +425,8 @@ nsCSPHostSrc::toString(nsAString& outStr) const
outStr.Append(mPort);
}
// in CSP 1.1, paths are ignoed
// outStr.Append(mPath);
// outStr.Append(mFileAndArguments);
// append path
outStr.Append(mPath);
}
void
@ -423,13 +450,6 @@ nsCSPHostSrc::appendPath(const nsAString& aPath)
ToLowerCase(mPath);
}
void
nsCSPHostSrc::setFileAndArguments(const nsAString& aFile)
{
mFileAndArguments = aFile;
ToLowerCase(mFileAndArguments);
}
/* ===== nsCSPKeywordSrc ===================== */
nsCSPKeywordSrc::nsCSPKeywordSrc(CSPKeyword aKeyword)
@ -469,7 +489,7 @@ nsCSPNonceSrc::~nsCSPNonceSrc()
}
bool
nsCSPNonceSrc::permits(nsIURI* aUri, const nsAString& aNonce) const
nsCSPNonceSrc::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const
{
#ifdef PR_LOGGING
{
@ -599,7 +619,7 @@ nsCSPDirective::~nsCSPDirective()
}
bool
nsCSPDirective::permits(nsIURI* aUri, const nsAString& aNonce) const
nsCSPDirective::permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const
{
#ifdef PR_LOGGING
{
@ -610,7 +630,7 @@ nsCSPDirective::permits(nsIURI* aUri, const nsAString& aNonce) const
#endif
for (uint32_t i = 0; i < mSrcs.Length(); i++) {
if (mSrcs[i]->permits(aUri, aNonce)) {
if (mSrcs[i]->permits(aUri, aNonce, aWasRedirected)) {
return true;
}
}
@ -621,7 +641,7 @@ bool
nsCSPDirective::permits(nsIURI* aUri) const
{
nsString dummyNonce;
return permits(aUri, dummyNonce);
return permits(aUri, dummyNonce, false);
}
bool
@ -754,6 +774,7 @@ bool
nsCSPPolicy::permits(nsContentPolicyType aContentType,
nsIURI* aUri,
const nsAString& aNonce,
bool aWasRedirected,
nsAString& outViolatedDirective) const
{
#ifdef PR_LOGGING
@ -774,7 +795,7 @@ nsCSPPolicy::permits(nsContentPolicyType aContentType,
for (uint32_t i = 0; i < mDirectives.Length(); i++) {
// Check if the directive name matches
if (mDirectives[i]->restrictsContentType(aContentType)) {
if (!mDirectives[i]->permits(aUri, aNonce)) {
if (!mDirectives[i]->permits(aUri, aNonce, aWasRedirected)) {
mDirectives[i]->toString(outViolatedDirective);
return false;
}
@ -795,7 +816,7 @@ nsCSPPolicy::permits(nsContentPolicyType aContentType,
// 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 (defaultDir) {
if (!defaultDir->permits(aUri, aNonce)) {
if (!defaultDir->permits(aUri, aNonce, aWasRedirected)) {
defaultDir->toString(outViolatedDirective);
return false;
}

Просмотреть файл

@ -191,7 +191,7 @@ class nsCSPBaseSrc {
nsCSPBaseSrc();
virtual ~nsCSPBaseSrc();
virtual bool permits(nsIURI* aUri, const nsAString& aNonce) const;
virtual bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const;
virtual bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce) const;
virtual void toString(nsAString& outStr) const = 0;
};
@ -203,7 +203,7 @@ class nsCSPSchemeSrc : public nsCSPBaseSrc {
explicit nsCSPSchemeSrc(const nsAString& aScheme);
virtual ~nsCSPSchemeSrc();
bool permits(nsIURI* aUri, const nsAString& aNonce) const;
bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const;
void toString(nsAString& outStr) const;
private:
@ -217,20 +217,18 @@ class nsCSPHostSrc : public nsCSPBaseSrc {
explicit nsCSPHostSrc(const nsAString& aHost);
virtual ~nsCSPHostSrc();
bool permits(nsIURI* aUri, const nsAString& aNonce) const;
bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const;
void toString(nsAString& outStr) const;
void setScheme(const nsAString& aScheme);
void setPort(const nsAString& aPort);
void appendPath(const nsAString &aPath);
void setFileAndArguments(const nsAString& aFile);
private:
nsString mScheme;
nsString mHost;
nsString mPort;
nsString mPath;
nsString mFileAndArguments;
};
/* =============== nsCSPKeywordSrc ============ */
@ -254,7 +252,7 @@ class nsCSPNonceSrc : public nsCSPBaseSrc {
explicit nsCSPNonceSrc(const nsAString& aNonce);
virtual ~nsCSPNonceSrc();
bool permits(nsIURI* aUri, const nsAString& aNonce) const;
bool permits(nsIURI* aUri, const nsAString& aNonce, bool aWasRedirected) const;
bool allows(enum CSPKeyword aKeyword, const nsAString& aHashOrNonce) const;
void toString(nsAString& outStr) const;
@ -298,7 +296,7 @@ class nsCSPDirective {
explicit nsCSPDirective(enum CSPDirective aDirective);
virtual ~nsCSPDirective();
bool permits(nsIURI* aUri, const nsAString& aNonce) const;
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;
@ -331,6 +329,7 @@ class nsCSPPolicy {
bool permits(nsContentPolicyType aContentType,
nsIURI* aUri,
const nsAString& aNonce,
bool aWasRedirected,
nsAString& outViolatedDirective) const;
bool permitsBaseURI(nsIURI* aUri) const;
bool allows(nsContentPolicyType aContentType,