tor-browser

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

browser_cert_export.js (4948B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 const { getPEMString } = ChromeUtils.importESModule(
      7  "resource://gre/modules/psm/pippki.sys.mjs"
      8 );
      9 
     10 var MockFilePicker = SpecialPowers.MockFilePicker;
     11 
     12 function createTemporarySaveDirectory() {
     13  var saveDir = Services.dirsvc.get("TmpD", Ci.nsIFile);
     14  saveDir.append("testsavedir");
     15  if (!saveDir.exists()) {
     16    info("create testsavedir!");
     17    saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
     18  }
     19  info("return from createTempSaveDir: " + saveDir.path);
     20  return saveDir;
     21 }
     22 
     23 // Create the folder the certificates will be saved into.
     24 var destDir = createTemporarySaveDirectory();
     25 registerCleanupFunction(function () {
     26  destDir.remove(true);
     27  BrowserTestUtils.removeTab(gBrowser.selectedTab);
     28 });
     29 
     30 function stringOrArrayEquals(actual, expected, message) {
     31  is(
     32    typeof actual,
     33    typeof expected,
     34    "actual, expected should have the same type"
     35  );
     36  if (typeof expected == "string") {
     37    is(actual, expected, message);
     38  } else {
     39    is(actual.toString(), expected.toString(), message);
     40  }
     41 }
     42 
     43 var dialogWin;
     44 var exportButton;
     45 var expectedCert;
     46 
     47 async function setupTest() {
     48  await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
     49  let certButton = gBrowser.selectedBrowser.contentDocument.getElementById(
     50    "viewCertificatesButton"
     51  );
     52  certButton.scrollIntoView();
     53  let certDialogLoaded = promiseLoadSubDialog(
     54    "chrome://pippki/content/certManager.xhtml"
     55  );
     56  certButton.click();
     57  dialogWin = await certDialogLoaded;
     58  let doc = dialogWin.document;
     59  doc.getElementById("certmanagertabs").selectedTab =
     60    doc.getElementById("ca_tab");
     61  let treeView = doc.getElementById("ca-tree").view;
     62  // Select any which cert. Ignore parent rows (ie rows without certs):
     63  for (let i = 0; i < treeView.rowCount; i++) {
     64    treeView.selection.select(i);
     65    dialogWin.getSelectedCerts();
     66    let certs = dialogWin.selected_certs; // yuck... but this is how the dialog works.
     67    if (certs && certs.length == 1 && certs[0]) {
     68      expectedCert = certs[0];
     69      // OK, we managed to select a cert!
     70      break;
     71    }
     72  }
     73 
     74  exportButton = doc.getElementById("ca_exportButton");
     75  is(exportButton.disabled, false, "Should enable export button");
     76 }
     77 
     78 async function checkCertExportWorks(
     79  exportType,
     80  encoding,
     81  expectedFileContents
     82 ) {
     83  MockFilePicker.displayDirectory = destDir;
     84  var destFile = destDir.clone();
     85  MockFilePicker.init(window.browsingContext);
     86  MockFilePicker.filterIndex = exportType;
     87  MockFilePicker.showCallback = function (fp) {
     88    info("showCallback");
     89    let fileName = fp.defaultString;
     90    info("fileName: " + fileName);
     91    destFile.append(fileName);
     92    MockFilePicker.setFiles([destFile]);
     93    info("done showCallback");
     94  };
     95  let finishedExporting = TestUtils.topicObserved("cert-export-finished");
     96  exportButton.click();
     97  await finishedExporting;
     98  MockFilePicker.cleanup();
     99  if (destFile && destFile.exists()) {
    100    let contents;
    101    if (encoding === "utf-8") {
    102      contents = await IOUtils.readUTF8(destFile.path);
    103    } else {
    104      is(encoding, "", "expected either utf-8 or empty string for encoding");
    105      contents = await IOUtils.read(destFile.path);
    106    }
    107    stringOrArrayEquals(
    108      contents,
    109      expectedFileContents,
    110      "Should have written correct contents"
    111    );
    112    destFile.remove(false);
    113  } else {
    114    ok(false, "No cert saved!");
    115  }
    116 }
    117 
    118 add_task(setupTest);
    119 
    120 add_task(async function checkCertPEMExportWorks() {
    121  let expectedContents = getPEMString(expectedCert);
    122  await checkCertExportWorks(0, /* 0 = PEM */ "utf-8", expectedContents);
    123 });
    124 
    125 add_task(async function checkCertPEMChainExportWorks() {
    126  let expectedContents = getPEMString(expectedCert);
    127  await checkCertExportWorks(
    128    1, // 1 = PEM chain, but the chain is of length 1
    129    "utf-8",
    130    expectedContents
    131  );
    132 });
    133 
    134 add_task(async function checkCertDERExportWorks() {
    135  let expectedContents = Uint8Array.from(expectedCert.getRawDER());
    136  await checkCertExportWorks(2, /* 2 = DER */ "", expectedContents);
    137 });
    138 
    139 function stringToTypedArray(str) {
    140  let arr = new Uint8Array(str.length);
    141  for (let i = 0; i < arr.length; i++) {
    142    arr[i] = str.charCodeAt(i);
    143  }
    144  return arr;
    145 }
    146 
    147 add_task(async function checkCertPKCS7ExportWorks() {
    148  let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
    149    Ci.nsIX509CertDB
    150  );
    151  let expectedContents = stringToTypedArray(certdb.asPKCS7Blob([expectedCert]));
    152  await checkCertExportWorks(3, /* 3 = PKCS7 */ "", expectedContents);
    153 });
    154 
    155 add_task(async function checkCertPKCS7ChainExportWorks() {
    156  let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
    157    Ci.nsIX509CertDB
    158  );
    159  let expectedContents = stringToTypedArray(certdb.asPKCS7Blob([expectedCert]));
    160  await checkCertExportWorks(
    161    4, // 4 = PKCS7 chain, but the chain is of length 1
    162    "",
    163    expectedContents
    164  );
    165 });