summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--security/nss/cmd/pk12util/pk12util.c180
-rw-r--r--security/nss/lib/nss/nss.def1
2 files changed, 126 insertions, 55 deletions
diff --git a/security/nss/cmd/pk12util/pk12util.c b/security/nss/cmd/pk12util/pk12util.c
index 95a51422a..ddeaa1a7c 100644
--- a/security/nss/cmd/pk12util/pk12util.c
+++ b/security/nss/cmd/pk12util/pk12util.c
@@ -39,6 +39,7 @@
#include "pk12util.h"
#include "nss.h"
#include "secport.h"
+#include "certdb.h"
#define PKCS12_IN_BUFFER_SIZE 200
@@ -551,6 +552,38 @@ p12u_WriteToExportFile(void *arg, const char *buf, unsigned long len)
}
}
+static SECStatus
+cert_UserCertsOnly(CERTCertList *certList)
+{
+ CERTCertListNode *node, *freenode;
+ CERTCertificate *cert;
+ PRUint32 numusercerts = 0;
+
+ node = CERT_LIST_HEAD(certList);
+
+ while ( ! CERT_LIST_END(node, certList) ) {
+ cert = node->cert;
+ if ( !( cert->trust->sslFlags & CERTDB_USER ) &&
+ !( cert->trust->emailFlags & CERTDB_USER ) &&
+ !( cert->trust->objectSigningFlags & CERTDB_USER ) ) {
+ /* Not a User Cert, so remove this cert from the list */
+ freenode = node;
+ node = CERT_LIST_NEXT(node);
+ CERT_RemoveCertListNode(freenode);
+ } else {
+ /* Is a User cert, so leave it in the list */
+ node = CERT_LIST_NEXT(node);
+ numusercerts ++;
+ }
+ }
+
+ if (numusercerts) {
+ return(SECSuccess);
+ } else {
+ return(SECFailure);
+ }
+}
+
void
P12U_ExportPKCS12Object(char *nn, char *outfile, PK11SlotInfo *inSlot,
secuPWData *slotPw, secuPWData *p12FilePw)
@@ -559,7 +592,9 @@ P12U_ExportPKCS12Object(char *nn, char *outfile, PK11SlotInfo *inSlot,
SEC_PKCS12SafeInfo *keySafe = NULL, *certSafe = NULL;
SECItem *pwitem = NULL;
p12uContext *p12cxt = NULL;
- CERTCertificate *cert = NULL;
+ CERTCertList* certlist = NULL;
+ CERTCertListNode* node = NULL;
+ PK11SlotInfo* slot = NULL;
if (P12U_InitSlot(inSlot, slotPw) != SECSuccess) {
SECU_PrintError(progName,"Failed to authenticate to \"%s\"",
@@ -567,17 +602,17 @@ P12U_ExportPKCS12Object(char *nn, char *outfile, PK11SlotInfo *inSlot,
pk12uErrno = PK12UERR_PK11GETSLOT;
goto loser;
}
- cert = PK11_FindCertFromNickname(nn, slotPw);
- if(!cert) {
- SECU_PrintError(progName,"find cert by nickname failed");
+ certlist = PK11_FindCertsFromNickname(nn, slotPw);
+ if(!certlist) {
+ SECU_PrintError(progName,"find user certs from nickname failed");
pk12uErrno = PK12UERR_FINDCERTBYNN;
return;
}
- if (!cert->slot) {
- SECU_PrintError(progName,"cert does not have a slot");
- pk12uErrno = PK12UERR_FINDCERTBYNN;
- goto loser;
+ if (SECSuccess != cert_UserCertsOnly(certlist)) {
+ SECU_PrintError(progName,"find user certs from nickname failed");
+ pk12uErrno = PK12UERR_FINDCERTBYNN;
+ return;
}
/* Password to use for PKCS12 file. */
@@ -586,61 +621,87 @@ P12U_ExportPKCS12Object(char *nn, char *outfile, PK11SlotInfo *inSlot,
goto loser;
}
- p12ecx = SEC_PKCS12CreateExportContext(NULL, NULL, cert->slot, slotPw);
- if(!p12ecx) {
- SECU_PrintError(progName,"export context creation failed");
- pk12uErrno = PK12UERR_EXPORTCXCREATE;
- goto loser;
- }
-
- if(SEC_PKCS12AddPasswordIntegrity(p12ecx, pwitem, SEC_OID_SHA1)
- != SECSuccess) {
- SECU_PrintError(progName,"PKCS12 add password integrity failed");
- pk12uErrno = PK12UERR_PK12ADDPWDINTEG;
+ p12cxt = p12u_InitFile(PR_FALSE, outfile);
+ if(!p12cxt) {
+ SECU_PrintError(progName,"Initialization failed: %s", outfile);
+ pk12uErrno = PK12UERR_INIT_FILE;
goto loser;
}
- keySafe = SEC_PKCS12CreateUnencryptedSafe(p12ecx);
- if(/*!SEC_PKCS12IsEncryptionAllowed() || */ PK11_IsFIPS()) {
- certSafe = keySafe;
- } else {
- certSafe = SEC_PKCS12CreatePasswordPrivSafe(p12ecx, pwitem,
- SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC);
+ if (certlist) {
+ CERTCertificate* cert = NULL;
+ node = CERT_LIST_HEAD(certlist);
+ if (node) {
+ cert = node->cert;
+ }
+ if (cert) {
+ slot = cert->slot; /* use the slot from the first matching
+ certificate to create the context . This is for keygen */
+ }
}
-
- if(!certSafe || !keySafe) {
- SECU_PrintError(progName,"key or cert safe creation failed");
- pk12uErrno = PK12UERR_CERTKEYSAFE;
- goto loser;
+ if (!slot) {
+ SECU_PrintError(progName,"cert does not have a slot");
+ pk12uErrno = PK12UERR_FINDCERTBYNN;
+ goto loser;
}
-
- if(SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL, cert,
- CERT_GetDefaultCertDB(), keySafe, NULL, PR_TRUE, pwitem,
- SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC)
- != SECSuccess) {
- SECU_PrintError(progName,"add cert and key failed");
- pk12uErrno = PK12UERR_ADDCERTKEY;
- goto loser;
+ p12ecx = SEC_PKCS12CreateExportContext(NULL, NULL, slot, slotPw);
+ if(!p12ecx) {
+ SECU_PrintError(progName,"export context creation failed");
+ pk12uErrno = PK12UERR_EXPORTCXCREATE;
+ goto loser;
}
- p12cxt = p12u_InitFile(PR_FALSE, outfile);
- if(!p12cxt) {
- SECU_PrintError(progName,"Initialization failed: %s", outfile);
- pk12uErrno = PK12UERR_INIT_FILE;
- goto loser;
+ if(SEC_PKCS12AddPasswordIntegrity(p12ecx, pwitem, SEC_OID_SHA1)
+ != SECSuccess) {
+ SECU_PrintError(progName,"PKCS12 add password integrity failed");
+ pk12uErrno = PK12UERR_PK12ADDPWDINTEG;
+ goto loser;
+ }
+
+ for (node = CERT_LIST_HEAD(certlist);!CERT_LIST_END(node,certlist);node=CERT_LIST_NEXT(node))
+ {
+ CERTCertificate* cert = node->cert;
+ if (!cert->slot) {
+ SECU_PrintError(progName,"cert does not have a slot");
+ pk12uErrno = PK12UERR_FINDCERTBYNN;
+ goto loser;
+ }
+
+ keySafe = SEC_PKCS12CreateUnencryptedSafe(p12ecx);
+ if(/*!SEC_PKCS12IsEncryptionAllowed() || */ PK11_IsFIPS()) {
+ certSafe = keySafe;
+ } else {
+ certSafe = SEC_PKCS12CreatePasswordPrivSafe(p12ecx, pwitem,
+ SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC);
+ }
+
+ if(!certSafe || !keySafe) {
+ SECU_PrintError(progName,"key or cert safe creation failed");
+ pk12uErrno = PK12UERR_CERTKEYSAFE;
+ goto loser;
+ }
+
+ if(SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL, cert,
+ CERT_GetDefaultCertDB(), keySafe, NULL, PR_TRUE, pwitem,
+ SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC)
+ != SECSuccess) {
+ SECU_PrintError(progName,"add cert and key failed");
+ pk12uErrno = PK12UERR_ADDCERTKEY;
+ goto loser;
+ }
+ CERT_DestroyCertificate(cert);
+ node->cert = NULL;
}
if(SEC_PKCS12Encode(p12ecx, p12u_WriteToExportFile, p12cxt)
- != SECSuccess) {
- SECU_PrintError(progName,"PKCS12 encode failed");
- pk12uErrno = PK12UERR_ENCODE;
- goto loser;
+ != SECSuccess) {
+ SECU_PrintError(progName,"PKCS12 encode failed");
+ pk12uErrno = PK12UERR_ENCODE;
+ goto loser;
}
p12u_DestroyExportFileInfo(&p12cxt, PR_FALSE);
SECITEM_ZfreeItem(pwitem, PR_TRUE);
- CERT_DestroyCertificate(cert);
-
fprintf(stdout, "%s: PKCS12 EXPORT SUCCESSFUL\n", progName);
SEC_PKCS12DestroyExportContext(p12ecx);
@@ -649,18 +710,27 @@ P12U_ExportPKCS12Object(char *nn, char *outfile, PK11SlotInfo *inSlot,
loser:
SEC_PKCS12DestroyExportContext(p12ecx);
+ for (node = CERT_LIST_HEAD(certlist);!CERT_LIST_END(node,certlist);node=CERT_LIST_NEXT(node))
+ {
+ CERTCertificate* cert = node->cert;
+ if (!node->cert) {
+ continue;
+ }
+
+ if(cert) {
+ CERT_DestroyCertificate(cert);
+ }
+ }
+
if (slotPw)
- PR_Free(slotPw->data);
+ PR_Free(slotPw->data);
if (p12FilePw)
- PR_Free(p12FilePw->data);
+ PR_Free(p12FilePw->data);
- if(cert) {
- CERT_DestroyCertificate(cert);
- }
p12u_DestroyExportFileInfo(&p12cxt, PR_TRUE);
if(pwitem) {
- SECITEM_ZfreeItem(pwitem, PR_TRUE);
+ SECITEM_ZfreeItem(pwitem, PR_TRUE);
}
p12u_DoPKCS12ExportErrors();
return;
diff --git a/security/nss/lib/nss/nss.def b/security/nss/lib/nss/nss.def
index 61a631c4f..6d19fcaf9 100644
--- a/security/nss/lib/nss/nss.def
+++ b/security/nss/lib/nss/nss.def
@@ -693,6 +693,7 @@ CERT_DestroyOCSPRequest;
CERT_EncodeOCSPRequest;
CERT_GetOCSPResponseStatus;
CERT_GetOCSPStatusForCertID;
+CERT_RemoveCertListNode;
CERT_VerifyCACertForUsage;
CERT_VerifyCertificate;
CERT_VerifyCertificateNow;