mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-31 06:05:44 +00:00
858957f033
In general, any code that was using nsIX509Cert.nickname should be able to use the attribute displayName (if using nickname for display purposes) or the attribute dbKey (if using nickname as a unique identifier for a certificate). MozReview-Commit-ID: G9CfMJDfLqe --HG-- extra : rebase_source : 1c464dab8f028568cedd5a42cf87428b8bb63fc0
277 lines
10 KiB
JavaScript
277 lines
10 KiB
JavaScript
/* 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/. */
|
|
|
|
const Ci = Components.interfaces;
|
|
const Cu = Components.utils;
|
|
const Cc = Components.classes;
|
|
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "Prompt",
|
|
"resource://gre/modules/Prompt.jsm");
|
|
|
|
// -----------------------------------------------------------------------
|
|
// NSS Dialog Service
|
|
// -----------------------------------------------------------------------
|
|
|
|
function NSSDialogs() { }
|
|
|
|
NSSDialogs.prototype = {
|
|
classID: Components.ID("{cbc08081-49b6-4561-9c18-a7707a50bda1}"),
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsICertificateDialogs, Ci.nsIClientAuthDialogs]),
|
|
|
|
/**
|
|
* Escapes the given input via HTML entity encoding. Used to prevent HTML
|
|
* injection when the input is to be placed inside an HTML body, but not in
|
|
* any other context.
|
|
*
|
|
* @param {String} input The input to interpret as a plain string.
|
|
* @returns {String} The escaped input.
|
|
*/
|
|
escapeHTML: function(input) {
|
|
return input.replace(/&/g, "&")
|
|
.replace(/</g, "<")
|
|
.replace(/>/g, ">")
|
|
.replace(/"/g, """)
|
|
.replace(/'/g, "'")
|
|
.replace(/\//g, "/");
|
|
},
|
|
|
|
getString: function(aName) {
|
|
if (!this.bundle) {
|
|
this.bundle = Services.strings.createBundle("chrome://browser/locale/pippki.properties");
|
|
}
|
|
return this.bundle.GetStringFromName(aName);
|
|
},
|
|
|
|
formatString: function(aName, argList) {
|
|
if (!this.bundle) {
|
|
this.bundle =
|
|
Services.strings.createBundle("chrome://browser/locale/pippki.properties");
|
|
}
|
|
let escapedArgList = Array.from(argList, x => this.escapeHTML(x));
|
|
return this.bundle.formatStringFromName(aName, escapedArgList,
|
|
escapedArgList.length);
|
|
},
|
|
|
|
getPrompt: function(aTitle, aText, aButtons) {
|
|
return new Prompt({
|
|
title: aTitle,
|
|
text: aText,
|
|
buttons: aButtons,
|
|
});
|
|
},
|
|
|
|
showPrompt: function(aPrompt) {
|
|
let response = null;
|
|
aPrompt.show(function(data) {
|
|
response = data;
|
|
});
|
|
|
|
// Spin this thread while we wait for a result
|
|
let thread = Services.tm.currentThread;
|
|
while (response === null)
|
|
thread.processNextEvent(true);
|
|
|
|
return response;
|
|
},
|
|
|
|
confirmDownloadCACert: function(aCtx, aCert, aTrust) {
|
|
while (true) {
|
|
let prompt = this.getPrompt(this.getString("downloadCert.title"),
|
|
this.getString("downloadCert.message1"),
|
|
[ this.getString("nssdialogs.ok.label"),
|
|
this.getString("downloadCert.viewCert.label"),
|
|
this.getString("nssdialogs.cancel.label")
|
|
]);
|
|
|
|
prompt.addCheckbox({ id: "trustSSL", label: this.getString("downloadCert.trustSSL"), checked: false })
|
|
.addCheckbox({ id: "trustEmail", label: this.getString("downloadCert.trustEmail"), checked: false })
|
|
.addCheckbox({ id: "trustSign", label: this.getString("downloadCert.trustObjSign"), checked: false });
|
|
let response = this.showPrompt(prompt);
|
|
|
|
// they hit the "view cert" button, so show the cert and try again
|
|
if (response.button == 1) {
|
|
this.viewCert(aCtx, aCert);
|
|
continue;
|
|
} else if (response.button != 0) {
|
|
return false;
|
|
}
|
|
|
|
aTrust.value = Ci.nsIX509CertDB.UNTRUSTED;
|
|
if (response.trustSSL) aTrust.value |= Ci.nsIX509CertDB.TRUSTED_SSL;
|
|
if (response.trustEmail) aTrust.value |= Ci.nsIX509CertDB.TRUSTED_EMAIL;
|
|
if (response.trustSign) aTrust.value |= Ci.nsIX509CertDB.TRUSTED_OBJSIGN;
|
|
return true;
|
|
}
|
|
},
|
|
|
|
setPKCS12FilePassword: function(aCtx, aPassword) {
|
|
// this dialog is never shown in Fennec; in Desktop it is shown while backing up a personal
|
|
// certificate to a file via Preferences->Advanced->Encryption->View Certificates->Your Certificates
|
|
throw "Unimplemented";
|
|
},
|
|
|
|
getPKCS12FilePassword: function(aCtx, aPassword) {
|
|
let prompt = this.getPrompt(this.getString("pkcs12.getpassword.title"),
|
|
this.getString("pkcs12.getpassword.message"),
|
|
[ this.getString("nssdialogs.ok.label"),
|
|
this.getString("nssdialogs.cancel.label")
|
|
]).addPassword({id: "pw"});
|
|
let response = this.showPrompt(prompt);
|
|
if (response.button != 0) {
|
|
return false;
|
|
}
|
|
|
|
aPassword.value = response.pw;
|
|
return true;
|
|
},
|
|
|
|
certInfoSection: function(aHeading, aDataPairs, aTrailingNewline = true) {
|
|
let certInfoStrings = [
|
|
"<big>" + this.getString(aHeading) + "</big>",
|
|
];
|
|
|
|
for (let i = 0; i < aDataPairs.length; i += 2) {
|
|
let key = aDataPairs[i];
|
|
let value = aDataPairs[i + 1];
|
|
certInfoStrings.push(this.formatString(key, [value]));
|
|
}
|
|
|
|
if (aTrailingNewline) {
|
|
certInfoStrings.push("<br/>");
|
|
}
|
|
|
|
return certInfoStrings.join("<br/>");
|
|
},
|
|
|
|
viewCert: function(aCtx, aCert) {
|
|
let p = this.getPrompt(this.getString("certmgr.title"), "", [
|
|
this.getString("nssdialogs.ok.label"),
|
|
]);
|
|
p.addLabel({ label: this.certInfoSection("certmgr.subjectinfo.label",
|
|
["certdetail.cn", aCert.commonName,
|
|
"certdetail.o", aCert.organization,
|
|
"certdetail.ou", aCert.organizationalUnit,
|
|
"certdetail.serialnumber", aCert.serialNumber])})
|
|
.addLabel({ label: this.certInfoSection("certmgr.issuerinfo.label",
|
|
["certdetail.cn", aCert.issuerCommonName,
|
|
"certdetail.o", aCert.issuerOrganization,
|
|
"certdetail.ou", aCert.issuerOrganizationUnit])})
|
|
.addLabel({ label: this.certInfoSection("certmgr.periodofvalidity.label",
|
|
["certdetail.notBefore", aCert.validity.notBeforeLocalDay,
|
|
"certdetail.notAfter", aCert.validity.notAfterLocalDay])})
|
|
.addLabel({ label: this.certInfoSection("certmgr.fingerprints.label",
|
|
["certdetail.sha256fingerprint", aCert.sha256Fingerprint,
|
|
"certdetail.sha1fingerprint", aCert.sha1Fingerprint],
|
|
false) });
|
|
this.showPrompt(p);
|
|
},
|
|
|
|
/**
|
|
* Returns a list of details of the given cert relevant for TLS client
|
|
* authentication.
|
|
*
|
|
* @param {nsIX509Cert} cert Cert to get the details of.
|
|
* @returns {String} <br/> delimited list of details.
|
|
*/
|
|
getCertDetails: function(cert) {
|
|
let detailLines = [
|
|
this.formatString("clientAuthAsk.issuedTo", [cert.subjectName]),
|
|
this.formatString("clientAuthAsk.serial", [cert.serialNumber]),
|
|
this.formatString("clientAuthAsk.validityPeriod",
|
|
[cert.validity.notBeforeLocalTime,
|
|
cert.validity.notAfterLocalTime]),
|
|
];
|
|
let keyUsages = cert.keyUsages;
|
|
if (keyUsages) {
|
|
detailLines.push(this.formatString("clientAuthAsk.keyUsages",
|
|
[keyUsages]));
|
|
}
|
|
let emailAddresses = cert.getEmailAddresses({});
|
|
if (emailAddresses.length > 0) {
|
|
let joinedAddresses = emailAddresses.join(", ");
|
|
detailLines.push(this.formatString("clientAuthAsk.emailAddresses",
|
|
[joinedAddresses]));
|
|
}
|
|
detailLines.push(this.formatString("clientAuthAsk.issuedBy",
|
|
[cert.issuerName]));
|
|
detailLines.push(this.formatString("clientAuthAsk.storedOn",
|
|
[cert.tokenName]));
|
|
|
|
return detailLines.join("<br/>");
|
|
},
|
|
|
|
viewCertDetails: function(details) {
|
|
let p = this.getPrompt(this.getString("clientAuthAsk.message3"),
|
|
'',
|
|
[ this.getString("nssdialogs.ok.label") ]);
|
|
p.addLabel({ label: details });
|
|
this.showPrompt(p);
|
|
},
|
|
|
|
chooseCertificate: function(ctx, hostname, port, organization, issuerOrg,
|
|
certList, selectedIndex) {
|
|
let rememberSetting =
|
|
Services.prefs.getBoolPref("security.remember_cert_checkbox_default_setting");
|
|
|
|
let serverRequestedDetails = [
|
|
this.formatString("clientAuthAsk.hostnameAndPort",
|
|
[hostname, port.toString()]),
|
|
this.formatString("clientAuthAsk.organization", [organization]),
|
|
this.formatString("clientAuthAsk.issuer", [issuerOrg]),
|
|
].join("<br/>");
|
|
|
|
let certNickList = [];
|
|
let certDetailsList = [];
|
|
for (let i = 0; i < certList.length; i++) {
|
|
let cert = certList.queryElementAt(i, Ci.nsIX509Cert);
|
|
certNickList.push(this.formatString("clientAuthAsk.nickAndSerial",
|
|
[cert.displayName, cert.serialNumber]));
|
|
certDetailsList.push(this.getCertDetails(cert));
|
|
}
|
|
|
|
selectedIndex.value = 0;
|
|
while (true) {
|
|
let buttons = [
|
|
this.getString("nssdialogs.ok.label"),
|
|
this.getString("clientAuthAsk.viewCert.label"),
|
|
this.getString("nssdialogs.cancel.label"),
|
|
];
|
|
let prompt = this.getPrompt(this.getString("clientAuthAsk.title"),
|
|
this.getString("clientAuthAsk.message1"),
|
|
buttons)
|
|
.addLabel({ id: "requestedDetails", label: serverRequestedDetails } )
|
|
.addMenulist({
|
|
id: "nicknames",
|
|
label: this.getString("clientAuthAsk.message2"),
|
|
values: certNickList,
|
|
selected: selectedIndex.value,
|
|
}).addCheckbox({
|
|
id: "rememberBox",
|
|
label: this.getString("clientAuthAsk.remember.label"),
|
|
checked: rememberSetting
|
|
});
|
|
let response = this.showPrompt(prompt);
|
|
selectedIndex.value = response.nicknames;
|
|
if (response.button == 1 /* buttons[1] */) {
|
|
this.viewCertDetails(certDetailsList[selectedIndex.value]);
|
|
continue;
|
|
} else if (response.button == 0 /* buttons[0] */) {
|
|
if (response.rememberBox == true) {
|
|
let caud = ctx.QueryInterface(Ci.nsIClientAuthUserDecision);
|
|
if (caud) {
|
|
caud.rememberClientAuthCertificate = true;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
};
|
|
|
|
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NSSDialogs]);
|