tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

browser_checkloaduri.js (12759B)


      1 "use strict";
      2 
      3 let ssm = Services.scriptSecurityManager;
      4 // This will show a directory listing, but we never actually load these so that's OK.
      5 const kDummyPage = getRootDirectory(gTestPath);
      6 
      7 const kAboutPagesRegistered = Promise.all([
      8  BrowserTestUtils.registerAboutPage(
      9    registerCleanupFunction,
     10    "test-chrome-privs",
     11    kDummyPage,
     12    Ci.nsIAboutModule.ALLOW_SCRIPT
     13  ),
     14  BrowserTestUtils.registerAboutPage(
     15    registerCleanupFunction,
     16    "test-chrome-privs2",
     17    kDummyPage,
     18    Ci.nsIAboutModule.ALLOW_SCRIPT
     19  ),
     20  BrowserTestUtils.registerAboutPage(
     21    registerCleanupFunction,
     22    "test-unknown-linkable",
     23    kDummyPage,
     24    Ci.nsIAboutModule.MAKE_LINKABLE | Ci.nsIAboutModule.ALLOW_SCRIPT
     25  ),
     26  BrowserTestUtils.registerAboutPage(
     27    registerCleanupFunction,
     28    "test-unknown-linkable2",
     29    kDummyPage,
     30    Ci.nsIAboutModule.MAKE_LINKABLE | Ci.nsIAboutModule.ALLOW_SCRIPT
     31  ),
     32  BrowserTestUtils.registerAboutPage(
     33    registerCleanupFunction,
     34    "test-unknown-unlinkable",
     35    kDummyPage,
     36    Ci.nsIAboutModule.ALLOW_SCRIPT
     37  ),
     38  BrowserTestUtils.registerAboutPage(
     39    registerCleanupFunction,
     40    "test-unknown-unlinkable2",
     41    kDummyPage,
     42    Ci.nsIAboutModule.ALLOW_SCRIPT
     43  ),
     44  BrowserTestUtils.registerAboutPage(
     45    registerCleanupFunction,
     46    "test-content-unlinkable",
     47    kDummyPage,
     48    Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT |
     49      Ci.nsIAboutModule.ALLOW_SCRIPT
     50  ),
     51  BrowserTestUtils.registerAboutPage(
     52    registerCleanupFunction,
     53    "test-content-unlinkable2",
     54    kDummyPage,
     55    Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT |
     56      Ci.nsIAboutModule.ALLOW_SCRIPT
     57  ),
     58  BrowserTestUtils.registerAboutPage(
     59    registerCleanupFunction,
     60    "test-content-linkable",
     61    kDummyPage,
     62    Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT |
     63      Ci.nsIAboutModule.MAKE_LINKABLE |
     64      Ci.nsIAboutModule.ALLOW_SCRIPT
     65  ),
     66  BrowserTestUtils.registerAboutPage(
     67    registerCleanupFunction,
     68    "test-content-linkable2",
     69    kDummyPage,
     70    Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT |
     71      Ci.nsIAboutModule.MAKE_LINKABLE |
     72      Ci.nsIAboutModule.ALLOW_SCRIPT
     73  ),
     74 ]);
     75 
     76 const URLs = new Map([
     77  [
     78    "http://www.example.com",
     79    [
     80      // For each of these entries, the booleans represent whether the parent URI can:
     81      // - load them
     82      // - load them without principal inheritance
     83      // - whether the URI can be created at all (some protocol handlers will
     84      //   refuse to create certain variants)
     85      ["http://www.example2.com", true, true, true],
     86      ["https://www.example2.com", true, true, true],
     87      ["moz-icon:file:///foo/bar/baz.exe", false, false, true],
     88      ["moz-icon://.exe", false, false, true],
     89      ["chrome://foo/content/bar.xul", false, false, true],
     90      ["view-source:http://www.example2.com", false, false, true],
     91      ["view-source:https://www.example2.com", false, false, true],
     92      ["data:text/html,Hi", true, false, true],
     93      ["view-source:data:text/html,Hi", false, false, true],
     94      ["javascript:alert('hi')", true, false, true],
     95      ["moz://a", false, false, true],
     96      ["about:test-chrome-privs", false, false, true],
     97      ["about:test-unknown-unlinkable", false, false, true],
     98      ["about:test-content-unlinkable", false, false, true],
     99      ["about:test-content-linkable", true, true, true],
    100      // Because this page doesn't have SAFE_FOR_UNTRUSTED, the web can't link to it:
    101      ["about:test-unknown-linkable", false, false, true],
    102    ],
    103  ],
    104  [
    105    "view-source:http://www.example.com",
    106    [
    107      ["http://www.example2.com", true, true, true],
    108      ["https://www.example2.com", true, true, true],
    109      ["moz-icon:file:///foo/bar/baz.exe", false, false, true],
    110      ["moz-icon://.exe", false, false, true],
    111      ["chrome://foo/content/bar.xul", false, false, true],
    112      ["view-source:http://www.example2.com", true, true, true],
    113      ["view-source:https://www.example2.com", true, true, true],
    114      ["data:text/html,Hi", true, false, true],
    115      ["view-source:data:text/html,Hi", true, false, true],
    116      ["javascript:alert('hi')", true, false, true],
    117      ["moz://a", false, false, true],
    118      ["about:test-chrome-privs", false, false, true],
    119      ["about:test-unknown-unlinkable", false, false, true],
    120      ["about:test-content-unlinkable", false, false, true],
    121      ["about:test-content-linkable", true, true, true],
    122      // Because this page doesn't have SAFE_FOR_UNTRUSTED, the web can't link to it:
    123      ["about:test-unknown-linkable", false, false, true],
    124    ],
    125  ],
    126  // about: related tests.
    127  [
    128    "about:test-chrome-privs",
    129    [
    130      ["about:test-chrome-privs", true, true, true],
    131      ["about:test-chrome-privs2", true, true, true],
    132      ["about:test-chrome-privs2?foo#bar", true, true, true],
    133      ["about:test-chrome-privs2?foo", true, true, true],
    134      ["about:test-chrome-privs2#bar", true, true, true],
    135 
    136      ["about:test-unknown-unlinkable", true, true, true],
    137 
    138      ["about:test-content-unlinkable", true, true, true],
    139      ["about:test-content-unlinkable?foo", true, true, true],
    140      ["about:test-content-unlinkable?foo#bar", true, true, true],
    141      ["about:test-content-unlinkable#bar", true, true, true],
    142 
    143      ["about:test-content-linkable", true, true, true],
    144 
    145      ["about:test-unknown-linkable", true, true, true],
    146      ["moz-icon:file:///foo/bar/baz.exe", true, true, true],
    147      ["moz-icon://.exe", true, true, true],
    148    ],
    149  ],
    150  [
    151    "about:test-unknown-unlinkable",
    152    [
    153      ["about:test-chrome-privs", false, false, true],
    154 
    155      // Can link to ourselves:
    156      ["about:test-unknown-unlinkable", true, true, true],
    157      // Can't link to unlinkable content if we're not sure it's privileged:
    158      ["about:test-unknown-unlinkable2", false, false, true],
    159 
    160      ["about:test-content-unlinkable", true, true, true],
    161      ["about:test-content-unlinkable2", true, true, true],
    162      ["about:test-content-unlinkable2?foo", true, true, true],
    163      ["about:test-content-unlinkable2?foo#bar", true, true, true],
    164      ["about:test-content-unlinkable2#bar", true, true, true],
    165 
    166      ["about:test-content-linkable", true, true, true],
    167 
    168      // Because this page doesn't have SAFE_FOR_UNTRUSTED, the web can't link to it:
    169      ["about:test-unknown-linkable", false, false, true],
    170    ],
    171  ],
    172  [
    173    "about:test-content-unlinkable",
    174    [
    175      ["about:test-chrome-privs", false, false, true],
    176 
    177      // Can't link to unlinkable content if we're not sure it's privileged:
    178      ["about:test-unknown-unlinkable", false, false, true],
    179 
    180      ["about:test-content-unlinkable", true, true, true],
    181      ["about:test-content-unlinkable2", true, true, true],
    182      ["about:test-content-unlinkable2?foo", true, true, true],
    183      ["about:test-content-unlinkable2?foo#bar", true, true, true],
    184      ["about:test-content-unlinkable2#bar", true, true, true],
    185 
    186      ["about:test-content-linkable", true, true, true],
    187      ["about:test-unknown-linkable", false, false, true],
    188    ],
    189  ],
    190  [
    191    "about:test-unknown-linkable",
    192    [
    193      ["about:test-chrome-privs", false, false, true],
    194 
    195      // Linkable content can't link to unlinkable content.
    196      ["about:test-unknown-unlinkable", false, false, true],
    197 
    198      ["about:test-content-unlinkable", false, false, true],
    199      ["about:test-content-unlinkable2", false, false, true],
    200      ["about:test-content-unlinkable2?foo", false, false, true],
    201      ["about:test-content-unlinkable2?foo#bar", false, false, true],
    202      ["about:test-content-unlinkable2#bar", false, false, true],
    203 
    204      // ... but it can link to other linkable content.
    205      ["about:test-content-linkable", true, true, true],
    206 
    207      // Can link to ourselves:
    208      ["about:test-unknown-linkable", true, true, true],
    209 
    210      // Because this page doesn't have SAFE_FOR_UNTRUSTED, the web can't link to it:
    211      ["about:test-unknown-linkable2", false, false, true],
    212    ],
    213  ],
    214  [
    215    "about:test-content-linkable",
    216    [
    217      ["about:test-chrome-privs", false, false, true],
    218 
    219      // Linkable content can't link to unlinkable content.
    220      ["about:test-unknown-unlinkable", false, false, true],
    221 
    222      ["about:test-content-unlinkable", false, false, true],
    223 
    224      // ... but it can link to itself and other linkable content.
    225      ["about:test-content-linkable", true, true, true],
    226      ["about:test-content-linkable2", true, true, true],
    227 
    228      // Because this page doesn't have SAFE_FOR_UNTRUSTED, the web can't link to it:
    229      ["about:test-unknown-linkable", false, false, true],
    230    ],
    231  ],
    232 ]);
    233 
    234 function testURL(
    235  source,
    236  target,
    237  canLoad,
    238  canLoadWithoutInherit,
    239  canCreate,
    240  flags
    241 ) {
    242  function getPrincipalDesc(principal) {
    243    if (principal.spec != "") {
    244      return principal.spec;
    245    }
    246    if (principal.isSystemPrincipal) {
    247      return "system principal";
    248    }
    249    if (principal.isNullPrincipal) {
    250      return "null principal";
    251    }
    252    return "unknown principal";
    253  }
    254  let threw = false;
    255  let targetURI;
    256  try {
    257    targetURI = Services.io.newURI(target);
    258  } catch (ex) {
    259    ok(
    260      !canCreate,
    261      "Shouldn't be passing URIs that we can't create. Failed to create: " +
    262        target
    263    );
    264    return;
    265  }
    266  ok(
    267    canCreate,
    268    "Created a URI for " +
    269      target +
    270      " which should " +
    271      (canCreate ? "" : "not ") +
    272      "be possible."
    273  );
    274  try {
    275    ssm.checkLoadURIWithPrincipal(source, targetURI, flags);
    276  } catch (ex) {
    277    info(ex.message);
    278    threw = true;
    279  }
    280  let inheritDisallowed = flags & ssm.DISALLOW_INHERIT_PRINCIPAL;
    281  let shouldThrow = inheritDisallowed ? !canLoadWithoutInherit : !canLoad;
    282  Assert.equal(
    283    threw,
    284    shouldThrow,
    285    "Should " +
    286      (shouldThrow ? "" : "not ") +
    287      "throw an error when loading " +
    288      target +
    289      " from " +
    290      getPrincipalDesc(source) +
    291      (inheritDisallowed ? " without" : " with") +
    292      " principal inheritance."
    293  );
    294 }
    295 
    296 add_task(async function () {
    297  // In this test we want to verify both http and https load
    298  // restrictions, hence we explicitly switch off the https-first
    299  // upgrading mechanism.
    300  await SpecialPowers.pushPrefEnv({
    301    set: [
    302      ["dom.security.https_first", false],
    303      ["security.allow_eval_with_system_principal", true],
    304    ],
    305  });
    306 
    307  await kAboutPagesRegistered;
    308  let baseFlags = ssm.STANDARD | ssm.DONT_REPORT_ERRORS;
    309  for (let [sourceString, targetsAndExpectations] of URLs) {
    310    let source;
    311    if (sourceString.startsWith("about:test-chrome-privs")) {
    312      source = ssm.getSystemPrincipal();
    313    } else {
    314      source = ssm.createContentPrincipal(Services.io.newURI(sourceString), {});
    315    }
    316    for (let [
    317      target,
    318      canLoad,
    319      canLoadWithoutInherit,
    320      canCreate,
    321    ] of targetsAndExpectations) {
    322      testURL(
    323        source,
    324        target,
    325        canLoad,
    326        canLoadWithoutInherit,
    327        canCreate,
    328        baseFlags
    329      );
    330      testURL(
    331        source,
    332        target,
    333        canLoad,
    334        canLoadWithoutInherit,
    335        canCreate,
    336        baseFlags | ssm.DISALLOW_INHERIT_PRINCIPAL
    337      );
    338    }
    339  }
    340 
    341  // Now test blob URIs, which we need to do in-content.
    342  await BrowserTestUtils.withNewTab(
    343    "http://www.example.com/",
    344    async function (browser) {
    345      await SpecialPowers.spawn(
    346        browser,
    347        [testURL.toString()],
    348        async function (testURLFn) {
    349          // eslint-disable-next-line no-shadow , no-eval
    350          let testURL = eval("(" + testURLFn + ")");
    351          // eslint-disable-next-line no-shadow
    352          let ssm = Services.scriptSecurityManager;
    353          // eslint-disable-next-line no-shadow
    354          let baseFlags = ssm.STANDARD | ssm.DONT_REPORT_ERRORS;
    355          // eslint-disable-next-line no-unused-vars
    356          let b = new content.Blob(["I am a blob"]);
    357          let contentBlobURI = content.URL.createObjectURL(b);
    358          let contentPrincipal = content.document.nodePrincipal;
    359          // Loading this blob URI from the content page should work:
    360          testURL(
    361            contentPrincipal,
    362            contentBlobURI,
    363            true,
    364            true,
    365            true,
    366            baseFlags
    367          );
    368          testURL(
    369            contentPrincipal,
    370            contentBlobURI,
    371            true,
    372            true,
    373            true,
    374            baseFlags | ssm.DISALLOW_INHERIT_PRINCIPAL
    375          );
    376 
    377          testURL(
    378            contentPrincipal,
    379            "view-source:" + contentBlobURI,
    380            false,
    381            false,
    382            true,
    383            baseFlags
    384          );
    385          testURL(
    386            contentPrincipal,
    387            "view-source:" + contentBlobURI,
    388            false,
    389            false,
    390            true,
    391            baseFlags | ssm.DISALLOW_INHERIT_PRINCIPAL
    392          );
    393        }
    394      );
    395    }
    396  );
    397 });