Bug 315871, In Certificate Viewer, allow to export cert or full chain Also covers Bug 161275, Support export of SSL, S/MIME, and CA certs Patch contributed by Kaspar Brand r=kengert, sr=rrelyea, a=dsicore

This commit is contained in:
kaie@kuix.de 2007-10-01 09:38:21 -07:00
Родитель 2ec86237a3
Коммит da75c056ed
15 изменённых файлов: 406 добавлений и 27 удалений

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

@ -102,21 +102,23 @@
<!ENTITY certmgr.close.label "Close">
<!ENTITY certmgr.close.accesskey "C">
<!ENTITY certmgr.view.label "View">
<!ENTITY certmgr.view2.label "View">
<!ENTITY certmgr.view.accesskey "V">
<!ENTITY certmgr.edit.label "Edit">
<!ENTITY certmgr.edit2.label "Edit">
<!ENTITY certmgr.edit.accesskey "E">
<!ENTITY certmgr.editca.label "Edit CA Trust">
<!ENTITY certmgr.editca.accesskey "d">
<!ENTITY certmgr.add.label "Add">
<!ENTITY certmgr.add.accesskey "A">
<!ENTITY certmgr.delete.label "Delete">
<!ENTITY certmgr.export.label "Export…">
<!ENTITY certmgr.export.accesskey "x">
<!ENTITY certmgr.delete2.label "Delete…">
<!ENTITY certmgr.delete.accesskey "D">
<!ENTITY certmgr.backup.label "Backup">
<!ENTITY certmgr.backup2.label "Backup">
<!ENTITY certmgr.backup.accesskey "B">
<!ENTITY certmgr.backupall.label "Backup All">
<!ENTITY certmgr.backupall2.label "Backup All">
<!ENTITY certmgr.backupall.accesskey "k">
<!ENTITY certmgr.restore.label "Import">
<!ENTITY certmgr.restore2.label "Import">
<!ENTITY certmgr.restore.accesskey "m">
<!ENTITY certmgr.details.label "Certificate Fields">
<!ENTITY certmgr.details.accesskey "F">

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

@ -195,3 +195,17 @@ file_browse_Certificate_spec=Certificate Files
# Form Signing confirmation prompt
formSigningIntro=The site '%S' has requested that you sign the following text message:
# Cert export
SaveCertAs=Save Certificate To File
CertFormatBase64=X.509 Certificate (PEM)
CertFormatBase64Chain=X.509 Certificate with chain (PEM)
CertFormatDER=X.509 Certificate (DER)
CertFormatPKCS7=X.509 Certificate (PKCS#7)
CertFormatPKCS7Chain=X.509 Certificate with chain (PKCS#7)
writeFileFailure=File Error
writeFileFailed=Can't write to file %S:\n%S.
writeFileAccessDenied=Access denied
writeFileIsLocked=File is locked
writeFileNoDeviceSpace=No space left on device
writeFileUnknownError=Unknown error

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

@ -66,19 +66,23 @@
<hbox>
<button id="ca_viewButton"
label="&certmgr.view.label;"
label="&certmgr.view2.label;"
accesskey="&certmgr.view.accesskey;"
disabled="true" oncommand="viewCerts();"/>
<button id="ca_editButton"
label="&certmgr.edit.label;"
label="&certmgr.edit2.label;"
accesskey="&certmgr.edit.accesskey;"
disabled="true" oncommand="editCerts();"/>
<button id="ca_addButton"
label="&certmgr.restore.label;"
label="&certmgr.restore2.label;"
accesskey="&certmgr.restore.accesskey;"
oncommand="addCACerts();"/>
<button id="ca_exportButton"
label="&certmgr.export.label;"
accesskey="&certmgr.export.accesskey;"
disabled="true" oncommand="exportCerts();"/>
<button id="ca_deleteButton"
label="&certmgr.delete.label;"
label="&certmgr.delete2.label;"
accesskey="&certmgr.delete.accesskey;"
disabled="true" oncommand="deleteCerts();"/>
</hbox>

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

@ -82,23 +82,23 @@
<hbox>
<button id="mine_viewButton" class="normal"
label="&certmgr.view.label;"
label="&certmgr.view2.label;"
accesskey="&certmgr.view.accesskey;"
disabled="true" oncommand="viewCerts();"/>
<button id="mine_backupButton" class="normal"
label="&certmgr.backup.label;"
label="&certmgr.backup2.label;"
accesskey="&certmgr.backup.accesskey;"
disabled="true" oncommand="backupCerts();"/>
<button id="mine_backupAllButton" class="normal"
label="&certmgr.backupall.label;"
label="&certmgr.backupall2.label;"
accesskey="&certmgr.backupall.accesskey;"
oncommand="backupAllCerts();"/>
<button id="mine_restoreButton" class="normal"
label="&certmgr.restore.label;"
label="&certmgr.restore2.label;"
accesskey="&certmgr.restore.accesskey;"
oncommand="restoreCerts();"/>
<button id="mine_deleteButton" class="normal"
label="&certmgr.delete.label;"
label="&certmgr.delete2.label;"
accesskey="&certmgr.delete.accesskey;"
disabled="true" oncommand="deleteCerts();"/>
</hbox>

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

@ -67,11 +67,15 @@
<hbox>
<button id="orphan_viewButton" class="normal"
label="&certmgr.view.label;"
label="&certmgr.view2.label;"
accesskey="&certmgr.view.accesskey;"
disabled="true" oncommand="viewCerts();"/>
<button id="orphan_exportButton" class="normal"
label="&certmgr.export.label;"
accesskey="&certmgr.export.accesskey;"
disabled="true" oncommand="exportCerts();"/>
<button id="orphan_deleteButton" class="normal"
label="&certmgr.delete.label;"
label="&certmgr.delete2.label;"
accesskey="&certmgr.delete.accesskey;"
disabled="true" oncommand="deleteCerts();"/>
</hbox>

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

@ -73,19 +73,23 @@
<hbox>
<button id="email_viewButton"
label="&certmgr.view.label;"
label="&certmgr.view2.label;"
accesskey="&certmgr.view.accesskey;"
disabled="true" oncommand="viewCerts();"/>
<button id="email_editButton"
label="&certmgr.edit.label;"
label="&certmgr.edit2.label;"
accesskey="&certmgr.edit.accesskey;"
disabled="true" oncommand="editCerts();"/>
<button id="email_addButton"
label="&certmgr.restore.label;"
label="&certmgr.restore2.label;"
accesskey="&certmgr.restore.accesskey;"
oncommand="addEmailCert();"/>
<button id="email_exportButton"
label="&certmgr.export.label;"
accesskey="&certmgr.export.accesskey;"
disabled="true" oncommand="exportCerts();"/>
<button id="email_deleteButton"
label="&certmgr.delete.label;"
label="&certmgr.delete2.label;"
accesskey="&certmgr.delete.accesskey;"
disabled="true" oncommand="deleteCerts();"/>
</hbox>

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

@ -72,19 +72,23 @@
<hbox>
<button id="websites_viewButton"
label="&certmgr.view.label;"
label="&certmgr.view2.label;"
accesskey="&certmgr.view.accesskey;"
disabled="true" oncommand="viewCerts();"/>
<button id="websites_editButton"
label="&certmgr.edit.label;"
label="&certmgr.edit2.label;"
accesskey="&certmgr.edit.accesskey;"
disabled="true" oncommand="editCerts();"/>
<button id="websites_addButton"
label="&certmgr.restore.label;"
label="&certmgr.restore2.label;"
accesskey="&certmgr.restore.accesskey;"
oncommand="addWebSiteCert();"/>
<button id="websites_exportButton"
label="&certmgr.export.label;"
accesskey="&certmgr.export.accesskey;"
disabled="true" oncommand="exportCerts();"/>
<button id="websites_deleteButton"
label="&certmgr.delete.label;"
label="&certmgr.delete2.label;"
accesskey="&certmgr.delete.accesskey;"
disabled="true" oncommand="deleteCerts();"/>
</hbox>

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

@ -65,5 +65,12 @@
<label class="header" value="&certmgr.fields.label;"/>
<textbox id="certDumpVal" multiline="true" rows="8"
readonly="true" style="font-family: -moz-fixed;"/>
<separator class="thin"/>
<hbox>
<button id="export_cert" class="normal" label="&certmgr.export.label;"
accesskey="&certmgr.export.accesskey;"
oncommand="exportToFile(window, getCurrentCert());"/>
</hbox>
</vbox>
</overlay>

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

@ -198,6 +198,8 @@ function ca_enableButtons()
enableViewButton.setAttribute("disabled",toggle);
var enableEditButton=document.getElementById('ca_editButton');
enableEditButton.setAttribute("disabled",edit_toggle);
var enableExportButton=document.getElementById('ca_exportButton');
enableExportButton.setAttribute("disabled",toggle);
var enableDeleteButton=document.getElementById('ca_deleteButton');
enableDeleteButton.setAttribute("disabled",toggle);
}
@ -228,6 +230,8 @@ function websites_enableButtons()
enableViewButton.setAttribute("disabled",toggle);
var enableEditButton=document.getElementById('websites_editButton');
enableEditButton.setAttribute("disabled",toggle);
var enableExportButton=document.getElementById('websites_exportButton');
enableExportButton.setAttribute("disabled",toggle);
var enableDeleteButton=document.getElementById('websites_deleteButton');
enableDeleteButton.setAttribute("disabled",toggle);
}
@ -243,6 +247,8 @@ function email_enableButtons()
enableViewButton.setAttribute("disabled",toggle);
var enableEditButton=document.getElementById('email_editButton');
enableEditButton.setAttribute("disabled",toggle);
var enableExportButton=document.getElementById('email_exportButton');
enableExportButton.setAttribute("disabled",toggle);
var enableDeleteButton=document.getElementById('email_deleteButton');
enableDeleteButton.setAttribute("disabled",toggle);
}
@ -256,6 +262,8 @@ function orphan_enableButtons()
}
var enableViewButton=document.getElementById('orphan_viewButton');
enableViewButton.setAttribute("disabled",toggle);
var enableExportButton=document.getElementById('orphan_exportButton');
enableExportButton.setAttribute("disabled",toggle);
var enableDeleteButton=document.getElementById('orphan_deleteButton');
enableDeleteButton.setAttribute("disabled",toggle);
}
@ -334,6 +342,18 @@ function restoreCerts()
}
}
function exportCerts()
{
getSelectedCerts();
var numcerts = selected_certs.length;
if (!numcerts)
return;
for (var t=0; t<numcerts; t++) {
exportToFile(window, selected_certs[t]);
}
}
function deleteCerts()
{
getSelectedCerts();

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

@ -97,7 +97,7 @@
accesskey="&validation.updatecrl.accesskey;"
oncommand="UpdateCRL();"/>
<button id="importCRL" class="push"
label="&certmgr.restore.label;"
label="&certmgr.restore2.label;"
accesskey="&certmgr.restore.accesskey;"
oncommand="ImportCRL();"/>
<spacer flex="2"/>

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

@ -22,6 +22,7 @@
*
* Contributor(s):
* Javier Delgadillo <javi@netscape.com>
* Kaspar Brand <mozcontrib@velox.ch>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -61,3 +62,133 @@ function viewCertHelper(parent, cert) {
var cd = Components.classes[nsCertificateDialogs].getService(nsICertificateDialogs);
cd.viewCert(parent, cert);
}
function getDERString(cert)
{
var length = {};
var derArray = cert.getRawDER(length);
var derString = '';
for (var i = 0; i < derArray.length; i++) {
derString += String.fromCharCode(derArray[i]);
}
return derString;
}
function getPKCS7String(cert, chainMode)
{
var length = {};
cert.QueryInterface(Components.interfaces.nsIX509Cert3);
var pkcs7Array = cert.exportAsCMS(chainMode, length);
var pkcs7String = '';
for (var i = 0; i < pkcs7Array.length; i++) {
pkcs7String += String.fromCharCode(pkcs7Array[i]);
}
return pkcs7String;
}
function getPEMString(cert)
{
var derb64 = btoa(getDERString(cert));
// Wrap the Base64 string into lines of 64 characters,
// with CRLF line breaks (as specified in RFC 1421).
var wrapped = derb64.replace(/(\S{64}(?!$))/g, "$1\r\n");
return "-----BEGIN CERTIFICATE-----\r\n"
+ wrapped
+ "\r\n-----END CERTIFICATE-----\r\n";
}
function alertPromptService(title, message)
{
var ps = null;
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
getService(Components.interfaces.nsIPromptService);
ps.alert(window, title, message);
}
function exportToFile(parent, cert)
{
var bundle = srGetStrBundle("chrome://pippki/locale/pippki.properties");
if (!cert)
return;
var nsIFilePicker = Components.interfaces.nsIFilePicker;
var fp = Components.classes["@mozilla.org/filepicker;1"].
createInstance(nsIFilePicker);
fp.init(parent, bundle.GetStringFromName("SaveCertAs"),
nsIFilePicker.modeSave);
var filename = cert.commonName;
if (!filename.length)
filename = cert.windowTitle;
// remove all whitespace from the default filename
fp.defaultString = filename.replace(/\s*/g,'');
fp.defaultExtension = "crt";
fp.appendFilter(bundle.GetStringFromName("CertFormatBase64"), "*.crt; *.pem");
fp.appendFilter(bundle.GetStringFromName("CertFormatBase64Chain"), "*.crt; *.pem");
fp.appendFilter(bundle.GetStringFromName("CertFormatDER"), "*.der");
fp.appendFilter(bundle.GetStringFromName("CertFormatPKCS7"), "*.p7c");
fp.appendFilter(bundle.GetStringFromName("CertFormatPKCS7Chain"), "*.p7c");
fp.appendFilters(nsIFilePicker.filterAll);
var res = fp.show();
if (res != nsIFilePicker.returnOK && res != nsIFilePicker.returnReplace)
return;
var content = '';
switch (fp.filterIndex) {
case 1:
content = getPEMString(cert);
var chain = cert.getChain();
for (var i = 1; i < chain.length; i++)
content += getPEMString(chain.queryElementAt(i, Components.interfaces.nsIX509Cert));
break;
case 2:
content = getDERString(cert);
break;
case 3:
content = getPKCS7String(cert, Components.interfaces.nsIX509Cert3.CMS_CHAIN_MODE_CertOnly);
break;
case 4:
content = getPKCS7String(cert, Components.interfaces.nsIX509Cert3.CMS_CHAIN_MODE_CertChainWithRoot);
break;
case 0:
default:
content = getPEMString(cert);
break;
}
var msg;
var written = 0;
try {
var file = Components.classes["@mozilla.org/file/local;1"].
createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(fp.file.path);
var fos = Components.classes["@mozilla.org/network/file-output-stream;1"].
createInstance(Components.interfaces.nsIFileOutputStream);
// flags: PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE
fos.init(file, 0x02 | 0x08 | 0x20, 00644, 0);
written = fos.write(content, content.length);
fos.close();
}
catch(e) {
switch (e.result) {
case Components.results.NS_ERROR_FILE_ACCESS_DENIED:
msg = bundle.GetStringFromName("writeFileAccessDenied");
break;
case Components.results.NS_ERROR_FILE_IS_LOCKED:
msg = bundle.GetStringFromName("writeFileIsLocked");
break;
case Components.results.NS_ERROR_FILE_NO_DEVICE_SPACE:
case Components.results.NS_ERROR_FILE_DISK_FULL:
msg = bundle.GetStringFromName("writeFileNoDeviceSpace");
break;
default:
msg = e.message;
break;
}
}
if (written != content.length) {
if (!msg.length)
msg = bundle.GetStringFromName("writeFileUnknownError");
alertPromptService(bundle.GetStringFromName("writeFileFailure"),
bundle.formatStringFromName("writeFileFailed",
[ fp.file.path, msg ], 2));
}
}

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

@ -23,6 +23,7 @@
* Ian McGreer <mcgreer@netscape.com>
* Javier Delgadillo <javi@netscape.com>
* Kai Engert <kengert@redhat.com>
* Kaspar Brand <mozcontrib@velox.ch>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -321,3 +322,29 @@ function getProxyOnUIThread(aObject, aInterface) {
aInterface, aObject, 5);
// 5 == NS_PROXY_ALWAYS | NS_PROXY_SYNC
}
function getCurrentCert()
{
var realIndex;
var tree = document.getElementById('treesetDump');
if (tree.view.selection.isSelected(tree.currentIndex)
&& document.getElementById('prettyprint_tab').selected) {
/* if the user manually selected a cert on the Details tab,
then take that one */
realIndex = tree.currentIndex;
} else {
/* otherwise, take the one at the bottom of the chain
(i.e. the one of the end-entity, unless we're displaying
CA certs) */
realIndex = tree.view.rowCount - 1;
}
if (realIndex >= 0) {
var item = tree.contentView.getItemAtIndex(realIndex);
var dbKey = item.firstChild.firstChild.getAttribute('display');
var certdb = Components.classes[nsX509CertDB].getService(nsIX509CertDB);
var cert = certdb.findCertByDBKey(dbKey,null);
return cert;
}
/* shouldn't really happen */
return null;
}

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

@ -46,9 +46,16 @@ interface nsICertVerificationListener;
* TODO: nsIX509Cert3 should be derived from nsIX509Cert2
* (and nsIX509Cert2 derived from nsIX509Cert)
*/
[scriptable, uuid(402aee39-653c-403f-8be1-6d1824223bf9)]
[scriptable, uuid(89d9f248-1160-4935-9f99-2bdbf67b5849)]
interface nsIX509Cert3 : nsISupports {
/**
* Constants for specifying the chain mode when exporting a certificate
*/
const unsigned long CMS_CHAIN_MODE_CertOnly = 1;
const unsigned long CMS_CHAIN_MODE_CertChain = 2;
const unsigned long CMS_CHAIN_MODE_CertChainWithRoot = 3;
/**
* Async version of nsIX509Cert::getUsagesArray()
*
@ -56,6 +63,19 @@ interface nsIX509Cert3 : nsISupports {
* availability of results will be notified.
*/
void requestUsagesArrayAsync(in nsICertVerificationListener cvl);
/**
* Obtain the certificate wrapped in a PKCS#7 SignedData structure,
* with or without the certificate chain
*
* @param chainMode Whether to include the chain (with or without the root),
see CMS_CHAIN_MODE constants.
* @param length The number of bytes of the PKCS#7 data.
* @param data The bytes representing the PKCS#7 wrapped certificate.
*/
void exportAsCMS(in unsigned long chainMode,
out unsigned long length,
[retval, array, size_is(length)] out octet data);
};
[scriptable, uuid(2fd0a785-9f2d-4327-8871-8c3e0783891d)]

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

@ -43,6 +43,7 @@
#include "prprf.h"
#include "nsNSSComponent.h" // for PIPNSS string bundle calls.
#include "nsNSSCleaner.h"
#include "nsCOMPtr.h"
#include "nsIMutableArray.h"
#include "nsNSSCertificate.h"
@ -86,6 +87,8 @@ extern "C" {
#include "ssl.h"
#include "ocsp.h"
#include "plbase64.h"
#include "cms.h"
#include "cert.h"
#ifdef PR_LOGGING
extern PRLogModuleInfo* gPIPNSSLog;
@ -93,6 +96,12 @@ extern PRLogModuleInfo* gPIPNSSLog;
static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
NSSCleanupAutoPtrClass(CERTCertificateList, CERT_DestroyCertificateList)
NSSCleanupAutoPtrClass(CERTCertificate, CERT_DestroyCertificate)
NSSCleanupAutoPtrClass(NSSCMSMessage, NSS_CMSMessage_Destroy)
NSSCleanupAutoPtrClass_WithParam(PLArenaPool, PORT_FreeArena, FalseParam, PR_FALSE)
NSSCleanupAutoPtrClass(NSSCMSSignedData, NSS_CMSSignedData_Destroy)
// This is being stored in an PRUint32 that can otherwise
// only take values from nsIX509Cert's list of cert types.
// As nsIX509Cert is frozen, we choose a value not contained
@ -967,6 +976,137 @@ nsNSSCertificate::GetRawDER(PRUint32 *aLength, PRUint8 **aArray)
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsNSSCertificate::ExportAsCMS(PRUint32 chainMode,
PRUint32 *aLength, PRUint8 **aArray)
{
NS_ENSURE_ARG(aLength);
NS_ENSURE_ARG(aArray);
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown())
return NS_ERROR_NOT_AVAILABLE;
if (!mCert)
return NS_ERROR_FAILURE;
switch (chainMode) {
case nsIX509Cert3::CMS_CHAIN_MODE_CertOnly:
case nsIX509Cert3::CMS_CHAIN_MODE_CertChain:
case nsIX509Cert3::CMS_CHAIN_MODE_CertChainWithRoot:
break;
default:
return NS_ERROR_INVALID_ARG;
};
PLArenaPool *arena = PORT_NewArena(1024);
PLArenaPoolCleanerFalseParam arenaCleaner(arena);
if (!arena) {
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
("nsNSSCertificate::ExportAsCMS - out of memory\n"));
return NS_ERROR_OUT_OF_MEMORY;
}
NSSCMSMessage *cmsg = NSS_CMSMessage_Create(nsnull);
NSSCMSMessageCleaner cmsgCleaner(cmsg);
if (!cmsg) {
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
("nsNSSCertificate::ExportAsCMS - can't create CMS message\n"));
return NS_ERROR_OUT_OF_MEMORY;
}
/*
* first, create SignedData with the certificate only (no chain)
*/
NSSCMSSignedData *sigd = NSS_CMSSignedData_CreateCertsOnly(cmsg, mCert, PR_FALSE);
NSSCMSSignedDataCleaner sigdCleaner(sigd);
if (!sigd) {
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
("nsNSSCertificate::ExportAsCMS - can't create SignedData\n"));
return NS_ERROR_FAILURE;
}
/*
* Calling NSS_CMSSignedData_CreateCertsOnly() will not allow us
* to specify the inclusion of the root, but CERT_CertChainFromCert() does.
* Since CERT_CertChainFromCert() also includes the certificate itself,
* we have to start at the issuing cert (to avoid duplicate certs
* in the SignedData).
*/
if (chainMode == nsIX509Cert3::CMS_CHAIN_MODE_CertChain ||
chainMode == nsIX509Cert3::CMS_CHAIN_MODE_CertChainWithRoot) {
CERTCertificate *issuerCert = CERT_FindCertIssuer(mCert, PR_Now(), certUsageAnyCA);
CERTCertificateCleaner issuerCertCleaner(issuerCert);
/*
* the issuerCert of a self signed root is the cert itself,
* so make sure we're not adding duplicates, again
*/
if (issuerCert && issuerCert != mCert) {
PRBool includeRoot =
(chainMode == nsIX509Cert3::CMS_CHAIN_MODE_CertChainWithRoot);
CERTCertificateList *certChain = CERT_CertChainFromCert(issuerCert, certUsageAnyCA, includeRoot);
CERTCertificateListCleaner certChainCleaner(certChain);
if (certChain) {
if (NSS_CMSSignedData_AddCertList(sigd, certChain) == SECSuccess) {
certChainCleaner.detach();
}
else {
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
("nsNSSCertificate::ExportAsCMS - can't add chain\n"));
return NS_ERROR_FAILURE;
}
}
else {
/* try to add the issuerCert, at least */
if (NSS_CMSSignedData_AddCertificate(sigd, issuerCert)
== SECSuccess) {
issuerCertCleaner.detach();
}
else {
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
("nsNSSCertificate::ExportAsCMS - can't add issuer cert\n"));
return NS_ERROR_FAILURE;
}
}
}
}
NSSCMSContentInfo *cinfo = NSS_CMSMessage_GetContentInfo(cmsg);
if (NSS_CMSContentInfo_SetContent_SignedData(cmsg, cinfo, sigd)
== SECSuccess) {
sigdCleaner.detach();
}
else {
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
("nsNSSCertificate::ExportAsCMS - can't attach SignedData\n"));
return NS_ERROR_FAILURE;
}
SECItem certP7 = { siBuffer, nsnull, 0 };
NSSCMSEncoderContext *ecx = NSS_CMSEncoder_Start(cmsg, nsnull, nsnull, &certP7, arena,
nsnull, nsnull, nsnull, nsnull, nsnull,
nsnull);
if (!ecx) {
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
("nsNSSCertificate::ExportAsCMS - can't create encoder context\n"));
return NS_ERROR_FAILURE;
}
if (NSS_CMSEncoder_Finish(ecx) != SECSuccess) {
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
("nsNSSCertificate::ExportAsCMS - failed to add encoded data\n"));
return NS_ERROR_FAILURE;
}
*aArray = (PRUint8*)nsMemory::Alloc(certP7.len);
if (!*aArray)
return NS_ERROR_OUT_OF_MEMORY;
memcpy(*aArray, certP7.data, certP7.len);
*aLength = certP7.len;
return NS_OK;
}
CERTCertificate *
nsNSSCertificate::GetCert()
{

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

@ -101,6 +101,7 @@ public: \
object = nsnull; \
} \
} \
void detach() {object=nsnull;} \
};
#define NSSCleanupAutoPtrClass_WithParam(nsstype, cleanfunc, namesuffix, paramvalue) \
@ -120,6 +121,7 @@ public: \
object = nsnull; \
} \
} \
void detach() {object=nsnull;} \
};
#endif