Bug 1034157 - Fix CSP's internal calls to AsyncReportViolation so they use mSelfURI, and the right load context is checked in the report sending logic
authorSid Stamm <sstamm@mozilla.com>
Thu, 03 Jul 2014 10:36:53 -0700
changeset 192160 a6a8770eb49daae3e9f5bb6c3391f491e1cdf3cd
parent 192159 72447c230e0ef80d7dc8e3ce358ac32c0d28b507
child 192161 2d1cf59ba9a752a2bea057a4606a2b32d95bd9ad
push id45767
push usermozilla@christophkerschbaumer.com
push dateThu, 03 Jul 2014 17:51:32 +0000
treeherdermozilla-inbound@2d1cf59ba9a7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1034157
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1034157 - Fix CSP's internal calls to AsyncReportViolation so they use mSelfURI, and the right load context is checked in the report sending logic
content/base/src/nsCSPContext.cpp
content/base/test/unit/test_cspreports.js
--- a/content/base/src/nsCSPContext.cpp
+++ b/content/base/src/nsCSPContext.cpp
@@ -179,17 +179,17 @@ nsCSPContext::ShouldLoad(nsContentPolicy
         *outDecision = nsIContentPolicy::REJECT_SERVER;
       }
 
       // Do not send a report or notify observers if this is a preload - the
       // decision may be wrong due to the inability to get the nonce, and will
       // incorrectly fail the unit tests.
       if (!isPreload) {
         this->AsyncReportViolation(aContentLocation,
-                                   aRequestOrigin,
+                                   mSelfURI,
                                    violatedDirective,
                                    p,             /* policy index        */
                                    EmptyString(), /* no observer subject */
                                    EmptyString(), /* no source file      */
                                    EmptyString(), /* no script sample    */
                                    0);            /* no line number      */
       }
     }
@@ -436,17 +436,17 @@ nsCSPContext::GetAllowsHash(const nsAStr
     PR_BEGIN_MACRO                                                             \
     if (!mPolicies[p]->allows(nsIContentPolicy::TYPE_ ## contentPolicyType,    \
                               keyword, nonceOrHash))                           \
     {                                                                          \
       nsAutoString violatedDirective;                                          \
       mPolicies[p]->getDirectiveStringForContentType(                          \
                         nsIContentPolicy::TYPE_ ## contentPolicyType,          \
                         violatedDirective);                                    \
-      this->AsyncReportViolation(selfISupports, nullptr, violatedDirective, p, \
+      this->AsyncReportViolation(selfISupports, mSelfURI, violatedDirective, p, \
                                  NS_LITERAL_STRING(observerTopic),             \
                                  aSourceFile, aScriptSample, aLineNum);        \
     }                                                                          \
     PR_END_MACRO;                                                              \
     break
 
 /**
  * For each policy, log any violation on the Error Console and send a report
@@ -687,50 +687,51 @@ nsCSPContext::SendReports(nsISupports* a
   if (!aScriptSample.IsEmpty()) {
     csp_report.AppendASCII(", \"script-sample\": \"");
     csp_report.Append(aScriptSample);
     csp_report.AppendASCII("\"");
   }
 
   // line-number
   if (aLineNum != 0) {
-    csp_report.AppendASCII(", \"script-sample\": \"");
+    csp_report.AppendASCII(", \"line-number\": \"");
     csp_report.AppendInt(aLineNum);
     csp_report.AppendASCII("\"");
   }
 
   csp_report.AppendASCII("}}\n\n");
 
   // ---------- Assembled, now send it to all the report URIs ----------- //
 
   nsTArray<nsString> reportURIs;
   mPolicies[aViolatedPolicyIndex]->getReportURIs(reportURIs);
 
   nsCOMPtr<nsIURI> reportURI;
   nsCOMPtr<nsIChannel> reportChannel;
 
   for (uint32_t r = 0; r < reportURIs.Length(); r++) {
+    nsAutoCString reportURICstring = NS_ConvertUTF16toUTF8(reportURIs[r]);
     // try to create a new uri from every report-uri string
     rv = NS_NewURI(getter_AddRefs(reportURI), reportURIs[r]);
     if (NS_FAILED(rv)) {
       const char16_t* params[] = { reportURIs[r].get() };
       CSPCONTEXTLOG(("Could not create nsIURI for report URI %s",
-                     reportURIs[r].get()));
+                     reportURICstring.get()));
       CSP_LogLocalizedStr(NS_LITERAL_STRING("triedToSendReport").get(),
                           params, ArrayLength(params),
                           aSourceFile, aScriptSample, aLineNum, 0,
                           nsIScriptError::errorFlag, "CSP", mInnerWindowID);
       continue; // don't return yet, there may be more URIs
     }
 
     // try to create a new channel for every report-uri
     rv = NS_NewChannel(getter_AddRefs(reportChannel), reportURI);
     if (NS_FAILED(rv)) {
       CSPCONTEXTLOG(("Could not create new channel for report URI %s",
-                     reportURIs[r].get()));
+                     reportURICstring.get()));
       continue; // don't return yet, there may be more URIs
     }
 
     // make sure this is an anonymous request (no cookies) so in case the
     // policy URI is injected, it can't be abused for CSRF.
     nsLoadFlags flags;
     rv = reportChannel->GetLoadFlags(&flags);
     NS_ENSURE_SUCCESS(rv, rv);
@@ -766,17 +767,17 @@ nsCSPContext::SendReports(nsISupports* a
                         &shouldLoad);
 
     // refuse to load if we can't do a security check
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (NS_CP_REJECTED(shouldLoad)) {
       // skip unauthorized URIs
       CSPCONTEXTLOG(("nsIContentPolicy blocked sending report to %s",
-                     reportURIs[r].get()));
+                     reportURICstring.get()));
       continue; // don't return yet, there may be more URIs
     }
 
     // wire in the string input stream to send the report
     nsCOMPtr<nsIStringInputStream> sis(do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID));
     NS_ASSERTION(sis, "nsIStringInputStream is needed but not available to send CSP violation reports");
     rv = sis->SetData(NS_ConvertUTF16toUTF8(csp_report).get(), csp_report.Length());
     NS_ENSURE_SUCCESS(rv, rv);
@@ -802,16 +803,18 @@ nsCSPContext::SendReports(nsISupports* a
 
     if (NS_FAILED(rv)) {
       const char16_t* params[] = { reportURIs[r].get() };
       CSPCONTEXTLOG(("AsyncOpen failed for report URI %s", params[0]));
       CSP_LogLocalizedStr(NS_LITERAL_STRING("triedToSendReport").get(),
                           params, ArrayLength(params),
                           aSourceFile, aScriptSample, aLineNum, 0,
                           nsIScriptError::errorFlag, "CSP", mInnerWindowID);
+    } else {
+      CSPCONTEXTLOG(("Sent violation report to URI %s", reportURICstring.get()));
     }
   }
   return NS_OK;
 }
 
 /**
  * Dispatched from the main thread to send reports for one CSP violation.
  */
@@ -825,18 +828,17 @@ class CSPReportSenderRunnable MOZ_FINAL 
                             const nsAString& aViolatedDirective,
                             const nsAString& aObserverSubject,
                             const nsAString& aSourceFile,
                             const nsAString& aScriptSample,
                             uint32_t aLineNum,
                             uint64_t aInnerWindowID,
                             nsCSPContext* aCSPContext)
       : mBlockedContentSource(aBlockedContentSource)
-      , mOriginalURI(aOriginalURI)
-      , mViolatedPolicyIndex(aViolatedPolicyIndex)
+      , mOriginalURI(aOriginalURI) , mViolatedPolicyIndex(aViolatedPolicyIndex)
       , mReportOnlyFlag(aReportOnlyFlag)
       , mViolatedDirective(aViolatedDirective)
       , mSourceFile(aSourceFile)
       , mScriptSample(aScriptSample)
       , mLineNum(aLineNum)
       , mInnerWindowID(aInnerWindowID)
       , mCSPContext(aCSPContext)
     {
--- a/content/base/test/unit/test_cspreports.js
+++ b/content/base/test/unit/test_cspreports.js
@@ -2,17 +2,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
-Cu.import('resource://gre/modules/CSPUtils.jsm');
 Cu.import('resource://gre/modules/NetUtil.jsm');
 
 var httpServer = new HttpServer();
 httpServer.start(-1);
 var testsToFinish = 0;
 
 const REPORT_SERVER_PORT = httpServer.identity.primaryPort;
 const REPORT_SERVER_URI = "http://localhost";
@@ -57,18 +56,17 @@ function makeReportHandler(testpath, mes
  * add a test here that will *not* cause a report to go out, you're gonna have
  * to make sure the test cleans up after itself.
  */
 function makeTest(id, expectedJSON, useReportOnlyPolicy, callback) {
   testsToFinish++;
   do_test_pending();
 
   // set up a new CSP instance for each test.
-  var csp = Cc["@mozilla.org/contentsecuritypolicy;1"]
-  //var csp = Cc["@mozilla.org/cspcontext;1"]
+  var csp = Cc["@mozilla.org/cspcontext;1"]
               .createInstance(Ci.nsIContentSecurityPolicy);
   var policy = "default-src 'none'; " +
                "report-uri " + REPORT_SERVER_URI +
                                ":" + REPORT_SERVER_PORT +
                                "/test" + id;
   var selfuri = NetUtil.newURI(REPORT_SERVER_URI +
                                ":" + REPORT_SERVER_PORT +
                                "/foo/self");