Bug 1186286 - Consult more than just the CN when deleting a cert so it's always clear what's being deleted. r=mgoodwin

Deleting certs via the cert manager results in a confirmation dialog popping up.
This dialog contains a list of certs that were selected for deletion.

Currently, only the Common Name of each cert is used to represent it in the list.
This is a problem for certs that don't have a CN. More jarringly, the cert
manager itself falls back to various other attributes, so for example selecting
a cert that is represented by its OU ends up popping up a dialog where an empty
list is shown.

MozReview-Commit-ID: 3z4BebW8Ucd

--HG--
extra : rebase_source : 468eb3de470e3ec42471c80183a9c48ebfb130c9
extra : histedit_source : 90e1d2fc73aaba4ded68d933b6ea3a6092d60636
This commit is contained in:
Cykesiopka 2016-10-07 20:14:27 +08:00
Родитель 77d242f817
Коммит 1d6f642d9d
16 изменённых файлов: 393 добавлений и 43 удалений

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

@ -1,19 +1,21 @@
#
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
CertPassPrompt=Please enter the Personal Security Password for the PSM Private Keys security device.
#These are for dialogs
#Download Cert dialog
# LOCALIZATION NOTE(certWithSerial): Used for semi-uniquely representing a cert.
# %1$S is the serial number of the cert in AA:BB:CC hex format.
certWithSerial=Certificate with serial number: %1$S
# Download Cert dialog
newCAMessage1=Do you want to trust “%S” for the following purposes?
unnamedCA=Certificate Authority (unnamed)
#For editing cert trust
# For editing cert trust
editTrustCA=The certificate “%S” represents a Certificate Authority.
#For Deleting Certificates
# For Deleting Certificates
deleteSslCertConfirm3=Are you sure you want to delete these server exceptions?
deleteSslCertImpact3=If you delete a server exception, you restore the usual security checks for that server and require it uses a valid certificate.
deleteSslCertTitle3=Delete Server Certificate Exceptions
@ -33,14 +35,13 @@ deleteEmailCertTitle=Delete E-Mail Certificates
deleteOrphanCertConfirm=Are you sure you want to delete these certificates?
deleteOrphanCertTitle=Delete Certificates
#PKCS#12 file dialogs
# PKCS#12 file dialogs
chooseP12RestoreFileDialog2=Certificate File to Import
chooseP12BackupFileDialog=File Name to Backup
file_browse_PKCS12_spec=PKCS12 Files
getPKCS12FilePasswordMessage=Please enter the password that was used to encrypt this certificate backup:
#Cert verification
# Cert verification
certVerified=This certificate has been verified for the following uses:
certNotVerified_CertRevoked=Could not verify this certificate because it has been revoked.
certNotVerified_CertExpired=Could not verify this certificate because it has expired.
@ -51,7 +52,7 @@ certNotVerified_CAInvalid=Could not verify this certificate because the CA certi
certNotVerified_AlgorithmDisabled=Could not verify this certificate because it was signed using a signature algorithm that was disabled because that algorithm is not secure.
certNotVerified_Unknown=Could not verify this certificate for unknown reasons.
#Client auth
# Client auth
clientAuthRemember=Remember this decision
# LOCALIZATION NOTE(clientAuthNickAndSerial): Represents a single cert when the
# user is choosing from a list of certificates.
@ -92,7 +93,7 @@ clientAuthIssuedBy=Issued by: %1$S
# the selected cert is stored on.
clientAuthStoredOn=Stored on: %1$S
#Page Info
# Page Info
pageInfo_NoEncryption=Connection Not Encrypted
pageInfo_Privacy_None1=The website %S does not support encryption for the page you are viewing.
pageInfo_Privacy_None2=Information sent over the Internet without encryption can be seen by other people while it is in transit.
@ -109,11 +110,11 @@ pageInfo_MixedContent=Connection Partially Encrypted
pageInfo_MixedContent2=Parts of the page you are viewing were not encrypted before being transmitted over the Internet.
pageInfo_WeakCipher=Your connection to this website uses weak encryption and is not private. Other people can view your information or modify the websites behavior.
#Cert Viewer
# Cert Viewer
certDetails=Certificate Viewer:
notPresent=<Not Part Of Certificate>
#Token Manager
# Token Manager
password_not_set=(not set)
failed_pw_change=Unable to change Master Password.
incorrect_pw=You did not enter the correct current Master Password. Please try again.
@ -166,7 +167,7 @@ writeFileIsLocked=File is locked
writeFileNoDeviceSpace=No space left on device
writeFileUnknownError=Unknown error
#Add Security Exception dialog
# Add Security Exception dialog
addExceptionBrandedWarning2=You are about to override how %S identifies this site.
addExceptionInvalidHeader=This site attempts to identify itself with invalid information.
addExceptionDomainMismatchShort=Wrong Site

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

@ -4,6 +4,8 @@
/* import-globals-from pippki.js */
"use strict";
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
const nsIFilePicker = Components.interfaces.nsIFilePicker;
const nsFilePicker = "@mozilla.org/filepicker;1";
const nsIX509CertDB = Components.interfaces.nsIX509CertDB;
@ -409,8 +411,6 @@ function deleteCerts()
var selTab = document.getElementById('certMgrTabbox').selectedItem;
var selTabID = selTab.getAttribute('id');
params.SetNumberStrings(numcerts + 1);
switch (selTabID) {
case "mine_tab":
case "websites_tab":
@ -423,16 +423,11 @@ function deleteCerts()
return;
}
params.SetInt(0, numcerts);
for (let t = 0; t < numcerts; t++) {
let treeItem = selected_tree_items[t];
let cert = treeItem.cert;
if (!cert) {
params.SetString(t + 1, treeItem.hostPort);
} else {
params.SetString(t + 1, cert.commonName);
}
let array = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
for (let treeItem of selected_tree_items) {
array.appendElement(treeItem, false);
}
params.objects = array;
window.openDialog('chrome://pippki/content/deletecert.xul', "",
'chrome,centerscreen,modal', params);

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

@ -4,25 +4,52 @@
/* import-globals-from pippki.js */
"use strict";
const nsIX509Cert = Components.interfaces.nsIX509Cert;
const nsX509CertDB = "@mozilla.org/security/x509certdb;1";
const nsIX509CertDB = Components.interfaces.nsIX509CertDB;
const nsIDialogParamBlock = Components.interfaces.nsIDialogParamBlock;
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
var certdb;
/**
* Param block to get passed in args and to set return values to.
* @type nsIDialogParamBlock
*/
var gParams;
/**
* Returns the most appropriate string to represent the given nsICertTreeItem.
* @param {nsICertTreeItem} certTreeItem
* The item to represent.
* @returns {String}
* A representative string.
*/
function certTreeItemToString(certTreeItem) {
let cert = certTreeItem.cert;
if (!cert) {
return certTreeItem.hostPort;
}
const attributes = [
cert.commonName,
cert.organizationalUnit,
cert.organization,
cert.subjectName,
];
for (let attribute of attributes) {
if (attribute) {
return attribute;
}
}
let bundle = document.getElementById("pippki_bundle");
return bundle.getFormattedString("certWithSerial", [cert.serialNumber]);
}
function setWindowName()
{
gParams = window.arguments[0].QueryInterface(nsIDialogParamBlock);
gParams = window.arguments[0].QueryInterface(Ci.nsIDialogParamBlock);
var typeFlag = gParams.GetString(0);
var numberOfCerts = gParams.GetInt(0);
var bundle = document.getElementById("pippki_bundle");
var title;
var confirm;
var impact;
let typeFlag = gParams.GetString(0);
let bundle = document.getElementById("pippki_bundle");
let title;
let confirm;
let impact;
switch (typeFlag) {
case "mine_tab":
@ -54,17 +81,16 @@ function setWindowName()
return;
}
var confirReference = document.getElementById('confirm');
var impactReference = document.getElementById('impact');
document.title = title;
setText("confirm", confirm);
let box = document.getElementById("certlist");
for (let x = 0; x < numberOfCerts; x++) {
var listItem = document.createElement("richlistitem");
var label = document.createElement("label");
label.setAttribute("value", gParams.GetString(x + 1));
for (let x = 0; x < gParams.objects.length; x++) {
let listItem = document.createElement("richlistitem");
let label = document.createElement("label");
let certTreeItem = gParams.objects.queryElementAt(x, Ci.nsICertTreeItem);
label.setAttribute("value", certTreeItemToString(certTreeItem));
listItem.appendChild(label);
box.appendChild(listItem);
}

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

@ -9,3 +9,4 @@ support-files =
[browser_certViewer.js]
[browser_clientAuth_connection.js]
[browser_clientAuth_ui.js]
[browser_deleteCert_ui.js]

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

@ -0,0 +1,226 @@
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/publicdomain/zero/1.0/
"use strict";
// Tests various aspects of the cert delete confirmation dialog.
// Among other things, tests that for each type of cert that can be deleted:
// 1. The various lines of explanation text are correctly set.
// 2. The implementation correctly falls back through multiple cert attributes
// to determine what to display to represent a cert.
/**
* An array of tree items corresponding to TEST_CASES.
* @type nsIMutableArray<nsICertTreeItem>
*/
var gCertArray = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
var gImportedCerts = [];
const FAKE_HOST_PORT = "Fake host and port";
/**
* @typedef {TestCase}
* @type Object
* @property {String} certFilename
* Filename of the cert, or null if we don't want to import a cert for
* this test case (i.e. we expect the hostPort attribute of
* nsICertTreeItem to be used).
* @property {String} expectedDisplayString
* The string we expect the UI to display to represent the given cert.
*/
/**
* A list of test cases representing certs that get "deleted".
* @type TestCase[]
*/
const TEST_CASES = [
{ certFilename: null,
expectedDisplayString: FAKE_HOST_PORT },
{ certFilename: "has-cn.pem",
expectedDisplayString: "Foo" },
{ certFilename: "has-ou.pem",
expectedDisplayString: "Bar" },
{ certFilename: "has-o.pem",
expectedDisplayString: "Baz" },
{ certFilename: "has-non-empty-subject.pem",
expectedDisplayString: "C=US" },
{ certFilename: "has-empty-subject.pem",
expectedDisplayString: "Certificate with serial number: 0A" },
];
/**
* Opens the cert delete confirmation dialog.
*
* @param {String} tabID
* The ID of the cert category tab the certs to delete belong to.
* @returns {Promise}
* A promise that resolves when the dialog has finished loading, with
* an array consisting of:
* 1. The window of the opened dialog.
* 2. The nsIDialogParamBlock passed to the dialog.
*/
function openDeleteCertConfirmDialog(tabID) {
let params = Cc["@mozilla.org/embedcomp/dialogparam;1"]
.createInstance(Ci.nsIDialogParamBlock);
params.SetString(0, tabID);
params.objects = gCertArray;
let win = window.openDialog("chrome://pippki/content/deletecert.xul", "", "",
params);
return new Promise((resolve, reject) => {
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad);
resolve([win, params]);
});
});
}
registerCleanupFunction(() => {
let certdb = Cc["@mozilla.org/security/x509certdb;1"]
.getService(Ci.nsIX509CertDB);
for (let cert of gImportedCerts) {
certdb.deleteCertificate(cert);
}
});
add_task(function* setup() {
for (let testCase of TEST_CASES) {
let cert = null;
if (testCase.certFilename) {
cert = yield readCertificate(testCase.certFilename, ",,", gImportedCerts);
}
let certTreeItem = {
hostPort: FAKE_HOST_PORT,
cert: cert,
QueryInterface(iid) {
if (iid.equals(Ci.nsICertTreeItem)) {
return this;
}
throw new Error(Cr.NS_ERROR_NO_INTERFACE);
}
};
gCertArray.appendElement(certTreeItem, false);
}
});
/**
* Test helper for the below test cases.
*
* @param {String} tabID
* ID of the cert category tab the certs to delete belong to.
* @param {String} expectedTitle
* Title the dialog is expected to have.
* @param {String} expectedConfirmMsg
* Confirmation message the dialog is expected to show.
* @param {String} expectedImpact
* Impact the dialog is expected to show.
*/
function* testHelper(tabID, expectedTitle, expectedConfirmMsg, expectedImpact) {
let [win, params] = yield openDeleteCertConfirmDialog(tabID);
let certList = win.document.getElementById("certlist");
Assert.equal(win.document.title, expectedTitle,
`Actual and expected titles should match for ${tabID}`);
Assert.equal(win.document.getElementById("confirm").textContent,
expectedConfirmMsg,
`Actual and expected confirm message should match for ${tabID}`);
Assert.equal(win.document.getElementById("impact").textContent,
expectedImpact,
`Actual and expected impact should match for ${tabID}`);
Assert.equal(certList.itemCount, TEST_CASES.length,
`No. of certs displayed should match for ${tabID}`);
for (let i = 0; i < certList.itemCount; i++) {
Assert.equal(certList.getItemAtIndex(i).label,
TEST_CASES[i].expectedDisplayString,
"Actual and expected display string should match for " +
`index ${i} for ${tabID}`);
}
yield BrowserTestUtils.closeWindow(win);
}
// Test deleting certs from the "Your Certificates" tab.
add_task(function* testDeletePersonalCerts() {
const expectedTitle = "Delete your Certificates";
const expectedConfirmMsg =
"Are you sure you want to delete these certificates?";
const expectedImpact =
"If you delete one of your own certificates, you can no longer use it to " +
"identify yourself.";
yield* testHelper("mine_tab", expectedTitle, expectedConfirmMsg,
expectedImpact);
});
// Test deleting certs from the "People" tab.
add_task(function* testDeleteOtherPeopleCerts() {
const expectedTitle = "Delete E-Mail Certificates";
// doesn't seem to work when embedded in the following literals, which is
// why escape codes are used instead.
const expectedConfirmMsg =
"Are you sure you want to delete these people\u2019s e-mail certificates?";
const expectedImpact =
"If you delete a person\u2019s e-mail certificate, you will no longer be " +
"able to send encrypted e-mail to that person.";
yield* testHelper("others_tab", expectedTitle, expectedConfirmMsg,
expectedImpact);
});
// Test deleting certs from the "Servers" tab.
add_task(function* testDeleteServerCerts() {
const expectedTitle = "Delete Server Certificate Exceptions";
const expectedConfirmMsg =
"Are you sure you want to delete these server exceptions?";
const expectedImpact =
"If you delete a server exception, you restore the usual security checks " +
"for that server and require it uses a valid certificate.";
yield* testHelper("websites_tab", expectedTitle, expectedConfirmMsg,
expectedImpact);
});
// Test deleting certs from the "Authorities" tab.
add_task(function* testDeleteCACerts() {
const expectedTitle = "Delete or Distrust CA Certificates";
const expectedConfirmMsg =
"You have requested to delete these CA certificates. For built-in " +
"certificates all trust will be removed, which has the same effect. Are " +
"you sure you want to delete or distrust?";
const expectedImpact =
"If you delete or distrust a certificate authority (CA) certificate, " +
"this application will no longer trust any certificates issued by that CA.";
yield* testHelper("ca_tab", expectedTitle, expectedConfirmMsg,
expectedImpact);
});
// Test deleting certs from the "Other" tab.
add_task(function* testDeleteOtherCerts() {
const expectedTitle = "Delete Certificates";
const expectedConfirmMsg =
"Are you sure you want to delete these certificates?";
const expectedImpact = "";
yield* testHelper("orphan_tab", expectedTitle, expectedConfirmMsg,
expectedImpact);
});
// Test that the right values are returned when the dialog is accepted.
add_task(function* testAcceptDialogReturnValues() {
let [win, params] = yield openDeleteCertConfirmDialog("ca_tab" /*arbitrary*/);
info("Accepting dialog");
win.document.getElementById("deleteCertificate").acceptDialog();
yield BrowserTestUtils.windowClosed(win);
Assert.equal(params.GetInt(1), 1,
"1 should be returned to signal user accepted");
});
// Test that the right values are returned when the dialog is canceled.
add_task(function* testCancelDialogReturnValues() {
let [win, params] = yield openDeleteCertConfirmDialog("ca_tab" /*arbitrary*/);
info("Canceling dialog");
win.document.getElementById("deleteCertificate").cancelDialog();
yield BrowserTestUtils.windowClosed(win);
Assert.equal(params.GetInt(1), 0,
"0 should be returned to signal user canceled");
});

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

@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC0DCCAbqgAwIBAgIUBdYRNGqgoPy8QL2qxNIAIbGiUsowCwYJKoZIhvcNAQEL
MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTQxMTI3MDAwMDAwWhgPMjAxNzAyMDQwMDAw
MDBaMDcxDDAKBgNVBAMMA0ZvbzEMMAoGA1UECwwDQmFyMQwwCgYDVQQKDANCYXox
CzAJBgNVBAYTAlVTMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuohR
qESOFtZB/W62iAY2ED08E9nq5DVKtOz1aFdsJHvBxyWo4NgfvbGcBptuGobya+Kv
WnVramRxCHqlWqdFh/cc1SScAn7NQ/weadA4ICmTqyDDSeTbuUzCa2wO7RWCD/F+
rWkasdMCOosqQe6ncOAPDY39ZgsrsCSSpH25iGF5kLFXkD3SO8XguEgfqDfTiEPv
JxbYVbdmWqp+ApAvOnsQgAYkzBxsl62WYVu34pYSwHUxowyR3bTK9/ytHSXTCe+5
Fw6naOGzey8ib2njtIqVYR3uJtYlnauRCE42yxwkBCy/Fosv5fGPmRcxuLP+SSP6
clHEMdUDrNoYCjXtjQIDAQABMAsGCSqGSIb3DQEBCwOCAQEAB1QaKkpRAhxoeSa6
vfhiJS9a3kC+ChE/0zRqu/wVaNkxlmnq6rR5e0iZ7K2Xo7FDPxfC14UolaTFs7KH
bEA4XzCvctDD7J1MTtcGZKDjH8ua4unpm8Ux6cnXqy3SpHzirshxU/cxOm8JtjmI
89Xq1BQ34fck+wNkK894d3+uniMyy4WrAiVeQHWQ6cUnzqt+8THgWXoRQSvMgEcM
ItSIylwll9pILylS5p7wI1upXkZD0V72WR+Pp/XSP07MOR13MPkAjZxXP/8hGQRR
URtLhwGrVf5Ovc9JnFhv3CqkKR/sEcGooA3VcCafVnxyucj1bmXmbkgWCE+b/zMQ
cVSPvw==
-----END CERTIFICATE-----

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

@ -0,0 +1,2 @@
issuer:ca
subject:/CN=Foo/OU=Bar/O=Baz/C=US

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

@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIIChjCCAXCgAwIBAgIBCjALBgkqhkiG9w0BAQswDTELMAkGA1UEAwwCY2EwIhgP
MjAxNDExMjcwMDAwMDBaGA8yMDE3MDIwNDAwMDAwMFowADCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBALqIUahEjhbWQf1utogGNhA9PBPZ6uQ1SrTs9WhX
bCR7wcclqODYH72xnAabbhqG8mvir1p1a2pkcQh6pVqnRYf3HNUknAJ+zUP8HmnQ
OCApk6sgw0nk27lMwmtsDu0Vgg/xfq1pGrHTAjqLKkHup3DgDw2N/WYLK7AkkqR9
uYhheZCxV5A90jvF4LhIH6g304hD7ycW2FW3ZlqqfgKQLzp7EIAGJMwcbJetlmFb
t+KWEsB1MaMMkd20yvf8rR0l0wnvuRcOp2jhs3svIm9p47SKlWEd7ibWJZ2rkQhO
NsscJAQsvxaLL+Xxj5kXMbiz/kkj+nJRxDHVA6zaGAo17Y0CAwEAATALBgkqhkiG
9w0BAQsDggEBAKAFuEA9TJ+o8myZ0AciYyCjsIcQhfPvL16vfhVmbr8IXudjeIQm
orBPLWOZWT/IVeLOYU+GecS86IFWdBjKLOMoPkZC3o6nQ95txGQrODN1uMQOQBc3
0AMQFnKbGCgoN8VtAsn7zppipvc6FcG83fh8YnrtGa8r9LBd5r2lX3npvG8qmhWD
J+2heHQp8D3NfCzad+jQy4hUhHalbH5aTky3T/1UGfgr/cXsDAcZb09Wd5tzDVpS
CP6iZyumHdH24ta5yYTHEEKDtR+/YU987crD79DcBK+7K2k4feFEzLfPDzmbtM3G
ZadO9SSf9GWHUovurJJNJaIBMYpNGeq4nT4=
-----END CERTIFICATE-----

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

@ -0,0 +1,3 @@
issuer:ca
subject:
serialNumber:10

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

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICpjCCAZCgAwIBAgIUS5/RALAav3GqFmr/hG5FumIUs/gwCwYJKoZIhvcNAQEL
MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTQxMTI3MDAwMDAwWhgPMjAxNzAyMDQwMDAw
MDBaMA0xCzAJBgNVBAYTAlVTMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEAuohRqESOFtZB/W62iAY2ED08E9nq5DVKtOz1aFdsJHvBxyWo4NgfvbGcBptu
Gobya+KvWnVramRxCHqlWqdFh/cc1SScAn7NQ/weadA4ICmTqyDDSeTbuUzCa2wO
7RWCD/F+rWkasdMCOosqQe6ncOAPDY39ZgsrsCSSpH25iGF5kLFXkD3SO8XguEgf
qDfTiEPvJxbYVbdmWqp+ApAvOnsQgAYkzBxsl62WYVu34pYSwHUxowyR3bTK9/yt
HSXTCe+5Fw6naOGzey8ib2njtIqVYR3uJtYlnauRCE42yxwkBCy/Fosv5fGPmRcx
uLP+SSP6clHEMdUDrNoYCjXtjQIDAQABMAsGCSqGSIb3DQEBCwOCAQEArANWYwZp
g5Z9sRrvPIaEjgJO4fnTf5/3nECTFljJH7YjGzFhnEGk52aRGubowhTOxAtqK1lc
cA5QRMuQ/Qrr7xZOdGfoxoMnQXONcEQNobcWbxa0Z8VZrpanAhXevlk5Z/8it96g
uLtCmgz32L6J2FpsftHI38+IAGjbgZjyOnyr4jGwgltZUKV1YRGClnMQnI6N/8TH
UrESziJ6JmVWnIwvKWvtwy68gRLvSaJ+lD1KTrqOVris0yPcR+dWlXaHovegxwDB
gkhtFOYJePK8p7op+WAyKlM922UYBC4X2h/4QeySrC2LYauGFz3ZARO2ylCJ1CsJ
ypuqIXstbO0h3g==
-----END CERTIFICATE-----

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

@ -0,0 +1,2 @@
issuer:ca
subject:/C=US

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

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICtDCCAZ6gAwIBAgIUG62RAQRi0nQBf5QEVbVQ6tS4QOwwCwYJKoZIhvcNAQEL
MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTQxMTI3MDAwMDAwWhgPMjAxNzAyMDQwMDAw
MDBaMBsxDDAKBgNVBAoMA0JhejELMAkGA1UEBhMCVVMwggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQC6iFGoRI4W1kH9braIBjYQPTwT2erkNUq07PVoV2wk
e8HHJajg2B+9sZwGm24ahvJr4q9adWtqZHEIeqVap0WH9xzVJJwCfs1D/B5p0Dgg
KZOrIMNJ5Nu5TMJrbA7tFYIP8X6taRqx0wI6iypB7qdw4A8Njf1mCyuwJJKkfbmI
YXmQsVeQPdI7xeC4SB+oN9OIQ+8nFthVt2Zaqn4CkC86exCABiTMHGyXrZZhW7fi
lhLAdTGjDJHdtMr3/K0dJdMJ77kXDqdo4bN7LyJvaeO0ipVhHe4m1iWdq5EITjbL
HCQELL8Wiy/l8Y+ZFzG4s/5JI/pyUcQx1QOs2hgKNe2NAgMBAAEwCwYJKoZIhvcN
AQELA4IBAQBKExQp1zdXXkl60yJsRcUNBPbprmHDlYLFtAcAY7s8+IKn+6kWUgNG
1wrKsaoSJUxK8MO6ULSbK8Xb9djjZ5Xcy622cOe3wk3/AIwc8nhAE6d5mtCDzOGR
MWEn+wGsCtW+eWDTlefx/+D3zBNAsb7hyW54JKDjfRADN6VtFO4ca4Ybw92G6CRf
g452KvRl90oZ2cxXyxOP3qdMOpB5a9DkUVS39n7iWgv//f3qlo3eUlHHoeygJQOM
qca5cnQbYKhat2edgK5OY4eHCFOWXpxRy83/zNywLki4zozwXnTWSmuBpe2jZEev
nOCxqVD3xceDzZ3NNkFj+c7Q2IX0ykmf
-----END CERTIFICATE-----

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

@ -0,0 +1,2 @@
issuer:ca
subject:/O=Baz/C=US

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

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICwjCCAaygAwIBAgIUI7neyiHwgLifhsVz4PP5NKkCWqIwCwYJKoZIhvcNAQEL
MA0xCzAJBgNVBAMMAmNhMCIYDzIwMTQxMTI3MDAwMDAwWhgPMjAxNzAyMDQwMDAw
MDBaMCkxDDAKBgNVBAsMA0JhcjEMMAoGA1UECgwDQmF6MQswCQYDVQQGEwJVUzCC
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALqIUahEjhbWQf1utogGNhA9
PBPZ6uQ1SrTs9WhXbCR7wcclqODYH72xnAabbhqG8mvir1p1a2pkcQh6pVqnRYf3
HNUknAJ+zUP8HmnQOCApk6sgw0nk27lMwmtsDu0Vgg/xfq1pGrHTAjqLKkHup3Dg
Dw2N/WYLK7AkkqR9uYhheZCxV5A90jvF4LhIH6g304hD7ycW2FW3ZlqqfgKQLzp7
EIAGJMwcbJetlmFbt+KWEsB1MaMMkd20yvf8rR0l0wnvuRcOp2jhs3svIm9p47SK
lWEd7ibWJZ2rkQhONsscJAQsvxaLL+Xxj5kXMbiz/kkj+nJRxDHVA6zaGAo17Y0C
AwEAATALBgkqhkiG9w0BAQsDggEBAGKpDaMHux0AWDSH/3scV6W+6ZFtsAH/kTw2
zPfPad1z7xECUDzNaLjJYdTiXplBFoB9lFNmM2pb/Z98FZPLCK7wD36jLtSrBjLm
KlDKieE3aoHHe2RANz3fEod7jV/YVuZXLNQaMEMXAdXV1qfrMOuyiYgo+Crr/EMO
ApAQvOPxOR34Z7mBPnxVwn3w85zxrpcRzbg+UFJcr1yk0yKrlawSCB1CV/itIkCJ
sdpqub2wRy6w3nCwaCmp92bmDAOS9K4UG4tCvwKFihYLBx1MiVmUZC90nrXSynh8
b1hdzFnKZxzoZgM7yNuqw06Xzx0eg8yqi4wLjj+uA3UdZHP7MAk=
-----END CERTIFICATE-----

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

@ -0,0 +1,2 @@
issuer:ca
subject:/OU=Bar/O=Baz/C=US

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

@ -18,6 +18,11 @@ BROWSER_CHROME_MANIFESTS += ['browser.ini']
# 'ee-from-untrusted-ca.pem',
# 'email-ee.pem',
# 'expired-ca.pem',
# 'has-cn.pem',
# 'has-empty-subject.pem',
# 'has-non-empty-subject.pem',
# 'has-o.pem',
# 'has-ou.pem',
# 'invalid.pem',
# 'md5-ee.pem',
# 'revoked.pem',