Bug 1186072 - add trailing slash to origin referer header when policy is set, r=sworkman draft
authorFranziskus Kiefer <franziskuskiefer@gmail.com>
Wed, 24 Feb 2016 10:51:54 +0100
changeset 336108 e550b11f8208072a1c26afc5c829b179974f8737
parent 335982 eb25b90a05c194bfd4f498ff3ffee7440f85f1cd
child 515313 71b98a8e95933fbbb365bb2e171da3a75b5be9dd
push id11981
push userfranziskuskiefer@gmail.com
push dateWed, 02 Mar 2016 16:09:02 +0000
reviewerssworkman
bugs1186072
milestone47.0a1
Bug 1186072 - add trailing slash to origin referer header when policy is set, r=sworkman MozReview-Commit-ID: 3PYuODmqpbL
browser/base/content/test/referrer/head.js
dom/base/test/bug704320.sjs
dom/base/test/bug704320_counter.sjs
dom/base/test/img_referrer_testserver.sjs
dom/base/test/referrerHelper.js
dom/base/test/test_bug1091883.html
dom/security/test/csp/test_upgrade_insecure_referrer.html
netwerk/protocol/http/HttpBaseChannel.cpp
netwerk/test/unit/test_referrer.js
netwerk/test/unit/test_referrer_policy.js
--- a/browser/base/content/test/referrer/head.js
+++ b/browser/base/content/test/referrer/head.js
@@ -40,17 +40,17 @@ var _referrerTests = [
     result: ""  // no referrer when downgrade
   },
   // 2. Origin referrer policy - we expect an origin referrer,
   //    even on downgrade.  But rel=noreferrer trumps this.
   {
     fromScheme: "https://",
     toScheme: "http://",
     policy: "origin",
-    result: "https://test1.example.com"  // origin, even on downgrade
+    result: "https://test1.example.com/"  // origin, even on downgrade
   },
   {
     fromScheme: "https://",
     toScheme: "http://",
     policy: "origin",
     rel: "noreferrer",
     result: ""  // rel=noreferrer trumps meta-referrer
   },
--- a/dom/base/test/bug704320.sjs
+++ b/dom/base/test/bug704320.sjs
@@ -23,17 +23,17 @@ function create2ndLevelIframeUrl(schemeF
 //   @import
 //   font-face
 //   bg-url
 //   <script>
 //   <img>
 //   <iframe>
 //   <audio>
 //   <video>
-//   <object type="bogus"> 
+//   <object type="bogus">
 //   <object type="image/svg+xml">
 //   <a>
 //   <a ping>
 //   <form>
 //   window.location
 //   window.open
 //   XMLHttpRequest
 //   EventSource
--- a/dom/base/test/bug704320_counter.sjs
+++ b/dom/base/test/bug704320_counter.sjs
@@ -36,17 +36,17 @@ function handleRequest(request, response
     query[name] = unescape(value);
   });
 
   var referrerLevel = "none";
   if (request.hasHeader('Referer')) {
     let referrer = request.getHeader('Referer');
     if (referrer.indexOf("bug704320") > 0) {
       referrerLevel = "full";
-    } else if (referrer == "http://mochi.test:8888") {
+    } else if (referrer == "http://mochi.test:8888/") {
       referrerLevel = "origin";
     }
   }
 
   var state = getSharedState(SHARED_KEY);
   if (state === '') {
     state = DEFAULT_STATE;
   } else {
--- a/dom/base/test/img_referrer_testserver.sjs
+++ b/dom/base/test/img_referrer_testserver.sjs
@@ -135,17 +135,17 @@ function handleRequest(request, response
     }
 
     var referrerLevel = "none";
     var test = {}
     if (request.hasHeader('Referer')) {
         let referrer = request.getHeader('Referer');
       if (referrer.indexOf("img_referrer_testserver") > 0) {
         referrerLevel = "full";
-      } else if (referrer == "http://mochi.test:8888") {
+      } else if (referrer == "http://mochi.test:8888/") {
         referrerLevel = "origin";
       }
       test.referrer = request.getHeader('Referer');
     } else {
       test.referrer = '';
     }
     test.policy = referrerLevel;
     test.expected = policy;
--- a/dom/base/test/referrerHelper.js
+++ b/dom/base/test/referrerHelper.js
@@ -58,17 +58,17 @@ function checkIndividualResults(testname
 
           ok('img' in results,
               testname + " test: some image loads required in results object.");
           is(results['img'].count, 2,
             testname + " Test: Expected 2 loads for image requests.");
 
           expected.forEach(function (ref) {
             ok(results['img'].referrers.indexOf(ref) >= 0,
-                testname + " Test: Expected " + ref + " referrer policy in test, results were " + 
+                testname + " Test: Expected " + ref + " referrer policy in test, results were " +
                 JSON.stringify(results['img'].referrers) +".");
             });
           advance();
         },
         function(xhr) {
           ok(false, "Can't get results from the counter server.");
           SimpleTest.finish();
         });
@@ -114,18 +114,18 @@ var EXPECTED_RESULTS = {
       'unsafe-url': '',
       'origin': '',
       'origin-when-cross-origin': '',
       'no-referrer-when-downgrade': ''
     },
     'http-to-https': {
       'no-referrer': '',
       'unsafe-url': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=unsafe-url',
-      'origin': 'http://example.com',
-      'origin-when-cross-origin': 'http://example.com',
+      'origin': 'http://example.com/',
+      'origin-when-cross-origin': 'http://example.com/',
       'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer-when-downgrade'
     },
     // Encrypted and not same-origin
     'https-to-http': {
       'no-referrer': '',
       'unsafe-url': '',
       'origin': '',
       'origin-when-cross-origin': '',
@@ -140,96 +140,96 @@ var EXPECTED_RESULTS = {
       'no-referrer-when-downgrade': ''
     }
   },
   // form is tested in a 2nd level iframe.
   'form': {
     'http-to-http': {
       'no-referrer': '',
       'unsafe-url': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=unsafe-url&type=form',
-      'origin': 'http://example.com',
+      'origin': 'http://example.com/',
       'origin-when-cross-origin': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=origin-when-cross-origin&type=form',
       'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=no-referrer-when-downgrade&type=form'
     },
     'http-to-https': {
       'no-referrer': '',
       'unsafe-url': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=https&policy=unsafe-url&type=form',
-      'origin': 'http://example.com',
-      'origin-when-cross-origin': 'http://example.com',
+      'origin': 'http://example.com/',
+      'origin-when-cross-origin': 'http://example.com/',
       'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer-when-downgrade&type=form'
     },
     'https-to-http': {
       'no-referrer': '',
       'unsafe-url': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=http&policy=unsafe-url&type=form',
-      'origin': 'https://example.com',
-      'origin-when-cross-origin': 'https://example.com',
+      'origin': 'https://example.com/',
+      'origin-when-cross-origin': 'https://example.com/',
       'no-referrer-when-downgrade': ''
     },
     'https-to-https': {
       'no-referrer': '',
       'unsafe-url': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=unsafe-url&type=form',
-      'origin': 'https://example.com',
+      'origin': 'https://example.com/',
      'origin-when-cross-origin': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=origin-when-cross-origin&type=form',
       'no-referrer-when-downgrade': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=no-referrer-when-downgrade&type=form'
     }
   },
   // window.location is tested in a 2nd level iframe.
   'window.location': {
     'http-to-http': {
       'no-referrer': '',
       'unsafe-url': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=unsafe-url&type=window.location',
-     'origin': 'http://example.com',
+     'origin': 'http://example.com/',
       'origin-when-cross-origin': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=origin-when-cross-origin&type=window.location',
       'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=no-referrer-when-downgrade&type=window.location'
     },
     'http-to-https': {
       'no-referrer': '',
       'unsafe-url': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=https&policy=unsafe-url&type=window.location',
-      'origin': 'http://example.com',
-      'origin-when-cross-origin': 'http://example.com',
+      'origin': 'http://example.com/',
+      'origin-when-cross-origin': 'http://example.com/',
       'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer-when-downgrade&type=window.location'
     },
     'https-to-http': {
       'no-referrer': '',
       'unsafe-url': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=http&policy=unsafe-url&type=window.location',
-      'origin': 'https://example.com',
-      'origin-when-cross-origin': 'https://example.com',
+      'origin': 'https://example.com/',
+      'origin-when-cross-origin': 'https://example.com/',
       'no-referrer-when-downgrade': ''
     },
     'https-to-https': {
       'no-referrer': '',
       'unsafe-url': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=unsafe-url&type=window.location',
-      'origin': 'https://example.com',
+      'origin': 'https://example.com/',
       'origin-when-cross-origin': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=origin-when-cross-origin&type=window.location',
       'no-referrer-when-downgrade': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=no-referrer-when-downgrade&type=window.location'
     }
   },
   'default': {
     'http-to-http': {
       'no-referrer': '',
       'unsafe-url': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=unsafe-url',
-      'origin': 'http://example.com',
+      'origin': 'http://example.com/',
       'origin-when-cross-origin': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=origin-when-cross-origin',
       'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=no-referrer-when-downgrade'
     },
     'http-to-https': {
       'no-referrer': '',
       'unsafe-url': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=unsafe-url',
-      'origin': 'http://example.com',
-      'origin-when-cross-origin': 'http://example.com',
+      'origin': 'http://example.com/',
+      'origin-when-cross-origin': 'http://example.com/',
       'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer-when-downgrade'
     },
     'https-to-http': {
       'no-referrer': '',
       'unsafe-url': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=http&policy=unsafe-url',
-      'origin': 'https://example.com',
-      'origin-when-cross-origin': 'https://example.com',
+      'origin': 'https://example.com/',
+      'origin-when-cross-origin': 'https://example.com/',
       'no-referrer-when-downgrade': ''
     },
     'https-to-https': {
       'no-referrer': '',
       'unsafe-url': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=unsafe-url',
-      'origin': 'https://example.com',
+      'origin': 'https://example.com/',
       'origin-when-cross-origin': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=origin-when-cross-origin',
       'no-referrer-when-downgrade': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=no-referrer-when-downgrade'
     }
   }
 };
--- a/dom/base/test/test_bug1091883.html
+++ b/dom/base/test/test_bug1091883.html
@@ -70,17 +70,17 @@ window.addEventListener("message", funct
   var referrer = out[0];
   var testRun = +out[1];
   results[makeResultsKey(testRun)] = referrer;
   if (event.origin == "http://mochi.test:8888") {
     is(referrer,
        "http://mochi.test:8888/tests/dom/base/test/test_bug1091883.html",
        "must be full referrer");
   } else {
-    is(referrer, "http://mochi.test:8888", "must be origin referrer");
+    is(referrer, "http://mochi.test:8888/", "must be origin referrer");
   }
   if (Object.keys(results).length == numTests) {
     document.getElementById("results").textContent =
         JSON.stringify(results, null, 4);
     SimpleTest.finish();
   }
 });
 </script>
--- a/dom/security/test/csp/test_upgrade_insecure_referrer.html
+++ b/dom/security/test/csp/test_upgrade_insecure_referrer.html
@@ -18,27 +18,27 @@
  * The test makes sure the request gets upgraded to https and the
  * correct referrer gets sent.
  */
 
 var tests = [
   {
     query: "test1",
     description: "upgrade insecure request with 'referrer = origin' (CSP in header)",
-    result: "http://example.com"
+    result: "http://example.com/"
   },
   {
     query: "test2",
     description: "upgrade insecure request with 'referrer = no-referrer' (CSP in header)",
     result: ""
   },
   {
     query: "test3",
     description: "upgrade insecure request with 'referrer = origin' (Meta CSP)",
-    result: "http://example.com"
+    result: "http://example.com/"
   },
   {
     query: "test4",
     description: "upgrade insecure request with 'referrer = no-referrer' (Meta CSP)",
     result: ""
   }
 ];
 
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -1488,18 +1488,19 @@ HttpBaseChannel::SetReferrerWithPolicy(n
       break;
     }
     rv = url->GetFilePath(path);
     if (NS_FAILED(rv)) return rv;
     spec = prepath + path;
     break;
   }
   case 2:
-    // scheme+host+port
+    // scheme+host+port+/
     rv = clone->GetPrePath(spec);
+    spec.AppendLiteral("/");
     if (NS_FAILED(rv)) return rv;
     break;
 
   default:
     // full URI
     rv = clone->GetAsciiSpec(spec);
     if (NS_FAILED(rv)) return rv;
     break;
--- a/netwerk/test/unit/test_referrer.js
+++ b/netwerk/test/unit/test_referrer.js
@@ -57,19 +57,19 @@ function run_test() {
   do_check_eq(getTestReferrer(server_uri_https, referer_uri_https), referer_uri_https);
   prefs.setIntPref("network.http.referer.XOriginPolicy", 0);
   do_check_eq(getTestReferrer(server_uri, referer_uri), referer_uri);
 
   // tests for referer.trimmingPolicy
   prefs.setIntPref("network.http.referer.trimmingPolicy", 1);
   do_check_eq(getTestReferrer(server_uri, referer_uri_2), "http://bar.examplesite.com/path3");
   prefs.setIntPref("network.http.referer.trimmingPolicy", 2);
-  do_check_eq(getTestReferrer(server_uri, referer_uri_2), "http://bar.examplesite.com");
+  do_check_eq(getTestReferrer(server_uri, referer_uri_2), "http://bar.examplesite.com/");
   // https test
-  do_check_eq(getTestReferrer(server_uri_https, referer_uri_https), "https://bar.example.com");
+  do_check_eq(getTestReferrer(server_uri_https, referer_uri_https), "https://bar.example.com/");
   prefs.setIntPref("network.http.referer.trimmingPolicy", 0);
   // test that anchor is lopped off in ordinary case
   do_check_eq(getTestReferrer(server_uri, referer_uri_2_anchor), referer_uri_2);
 
   // combination test: send spoofed path-only when hosts match
   var combo_referer_uri = "http://blah.foo.com/path?q=hot";
   var dest_uri = "http://blah.foo.com:9999/spoofedpath?q=bad";
   prefs.setIntPref("network.http.referer.trimmingPolicy", 1);
--- a/netwerk/test/unit/test_referrer_policy.js
+++ b/netwerk/test/unit/test_referrer_policy.js
@@ -7,71 +7,65 @@ function test_policy(test) {
   var chan = NetUtil.newChannel({
     uri: uri,
     loadUsingSystemPrincipal: true
   });
 
   var referrer = NetUtil.newURI(test.referrer, "", null);
   chan.QueryInterface(Components.interfaces.nsIHttpChannel);
   chan.setReferrerWithPolicy(referrer, test.policy);
-  if (test.expectedHeader === undefined) {
+  if (test.expectedReferrerSpec === undefined) {
     try {
       chan.getRequestHeader("Referer");
       do_throw("Should not find a Referer header!");
     } catch(e) {
     }
     do_check_eq(chan.referrer, null);
   } else {
     var header = chan.getRequestHeader("Referer");
-    do_check_eq(header, test.expectedHeader);
+    do_check_eq(header, test.expectedReferrerSpec);
     do_check_eq(chan.referrer.spec, test.expectedReferrerSpec);
   }
 }
 
 const nsIHttpChannel = Ci.nsIHttpChannel;
 var gTests = [
   {
     policy: nsIHttpChannel.REFERRER_POLICY_DEFAULT,
     url: "https://test.example/foo",
     referrer: "https://test.example/referrer",
-    expectedHeader: "https://test.example/referrer",
     expectedReferrerSpec: "https://test.example/referrer"
   },
   {
     policy: nsIHttpChannel.REFERRER_POLICY_DEFAULT,
     url: "http://test.example/foo",
     referrer: "https://test.example/referrer",
-    expectedHeader: undefined,
     expectedReferrerSpec: undefined
   },
   {
     policy: nsIHttpChannel.REFERRER_POLICY_NO_REFERRER,
     url: "https://test.example/foo",
     referrer: "https://test.example/referrer",
-    expectedHeader: undefined,
     expectedReferrerSpec: undefined
   },
   {
     policy: nsIHttpChannel.REFERRER_POLICY_ORIGIN,
     url: "https://test.example/foo",
     referrer: "https://test.example/referrer",
-    expectedHeader: "https://test.example",
     expectedReferrerSpec: "https://test.example/"
   },
   {
     policy: nsIHttpChannel.REFERRER_POLICY_UNSAFE_URL,
     url: "https://test.example/foo",
     referrer: "https://test.example/referrer",
-    expectedHeader: "https://test.example/referrer",
     expectedReferrerSpec: "https://test.example/referrer"
   },
   {
     policy: nsIHttpChannel.REFERRER_POLICY_UNSAFE_URL,
     url: "http://test.example/foo",
     referrer: "https://test.example/referrer",
-    expectedHeader: "https://test.example/referrer",
     expectedReferrerSpec: "https://test.example/referrer"
   },
 ];
 
 function run_test() {
   gTests.forEach(test => test_policy(test));
 }