diff --git a/security/manager/ssl/public/nsIX509CertDB.idl b/security/manager/ssl/public/nsIX509CertDB.idl index 347ce69fe23b..5e95a8a06da9 100644 --- a/security/manager/ssl/public/nsIX509CertDB.idl +++ b/security/manager/ssl/public/nsIX509CertDB.idl @@ -124,16 +124,18 @@ interface nsIX509CertDB : nsISupports { out nsISupportsArray certs); /* - * importCertificate - * - * Import a certificate into the database. - * XXX For now, this only imports into the default internal slot. - * should there be a importCertificateToSlot? Or change the sig? + * importCertificates + * Use this to import a stream sent down as a mime type into + * the default cert db. The stream may consist of one or more + * certificates. + * XXX We may want to add a parameter for a PK11 Token where + * the certs will utlimtately live. Currently, they'll + * be placed in the default token. */ - [noscript] void importCertificate(in nsIX509Cert cert, - in unsigned long type, - in unsigned long trust, - in wstring nickname); + [noscript] void importCertificates(in charPtr data, + in unsigned long length, + in unsigned long type, + in nsIInterfaceRequestor ctx); /* * importCertificate diff --git a/security/manager/ssl/resources/locale/en-US/pipnss.properties b/security/manager/ssl/resources/locale/en-US/pipnss.properties index 798861ff50e2..16d7b03a2337 100644 --- a/security/manager/ssl/resources/locale/en-US/pipnss.properties +++ b/security/manager/ssl/resources/locale/en-US/pipnss.properties @@ -129,6 +129,7 @@ PKCS12UnknownErrRestore=Failed to restore the PKCS #12 file for unknown reasons. PKCS12UnknownErrBackup=Failed to create the PKCS #12 backup file for unknown reasons. PKCS12UnknownErr=The PKCS #12 operation failed for unknown reasons. PKCS12InfoNoSmartcardBackup=It is not possible to back up certificates from a hardware security device such as a smart card. +PKCS12DupData=The certificate and private key already exist on the security device. AddModulePrompt=Are you sure you want to install this security module? AddModuleName=Module Name: %S AddModulePath=Path: %S diff --git a/security/manager/ssl/src/nsNSSCertificate.cpp b/security/manager/ssl/src/nsNSSCertificate.cpp index efae59a19d15..fc33f3e259bf 100644 --- a/security/manager/ssl/src/nsNSSCertificate.cpp +++ b/security/manager/ssl/src/nsNSSCertificate.cpp @@ -32,7 +32,7 @@ * may use your version of this file under either the MPL or the * GPL. * - * $Id: nsNSSCertificate.cpp,v 1.46 2001/08/21 01:12:38 rangansen%netscape.com Exp $ + * $Id: nsNSSCertificate.cpp,v 1.47 2001/08/22 04:05:42 javi%netscape.com Exp $ */ #include "prmem.h" @@ -2517,64 +2517,269 @@ nsNSSCertificateDB::GetCertsByType(PRUint32 aType, return PR_TRUE; } +SECStatus PR_CALLBACK +collect_certs(void *arg, SECItem **certs, int numcerts) +{ + CERTDERCerts *collectArgs; + SECItem *cert; + SECStatus rv; + + collectArgs = (CERTDERCerts *)arg; + + collectArgs->numcerts = numcerts; + collectArgs->rawCerts = (SECItem *) PORT_ArenaZAlloc(collectArgs->arena, + sizeof(SECItem) * numcerts); + if ( collectArgs->rawCerts == NULL ) + return(SECFailure); + + cert = collectArgs->rawCerts; + + while ( numcerts-- ) { + rv = SECITEM_CopyItem(collectArgs->arena, cert, *certs); + if ( rv == SECFailure ) + return(SECFailure); + cert++; + certs++; + } + + return (SECSuccess); +} + +CERTDERCerts* +nsNSSCertificateDB::getCertsFromPackage(PRArenaPool *arena, char *data, + PRUint32 length) +{ + CERTDERCerts *collectArgs = + (CERTDERCerts *)PORT_ArenaZAlloc(arena, sizeof(CERTDERCerts)); + if ( collectArgs == nsnull ) + return nsnull; + + collectArgs->arena = arena; + SECStatus sec_rv = CERT_DecodeCertPackage(data, length, collect_certs, + (void *)collectArgs); + if (sec_rv != SECSuccess) + return nsnull; + + return collectArgs; +} + +nsresult +nsNSSCertificateDB::handleCACertDownload(nsISupportsArray *x509Certs, + nsIInterfaceRequestor *ctx) +{ + // First thing we have to do is figure out which certificate we're + // gonna present to the user. The CA may have sent down a list of + // certs which may or may not be a chained list of certs. Until + // the day we can design some solid UI for the general case, we'll + // code to the > 90% case. That case is where a CA sends down a + // list that is a chain up to its root in either ascending or + // descending order. What we're gonna do is compare the first + // 2 entries, if the first was signed by the second, we assume + // the leaf cert is the first cert and display it. If the second + // cert was signed by the first cert, then we assume the first cert + // is the root and the last cert in the array is the leaf. In this + // case we display the last cert. + PRUint32 numCerts; + + x509Certs->Count(&numCerts); + NS_ASSERTION(numCerts > 0, "Didn't get any certs to import."); + if (numCerts == 0) + return NS_OK; // Nothing to import, so nothing to do. + + nsCOMPtr certToShow; + nsCOMPtr isupports; + PRUint32 selCertIndex; + if (numCerts == 1) { + // There's only one cert, so let's show it. + selCertIndex = 0; + isupports = dont_AddRef(x509Certs->ElementAt(selCertIndex)); + certToShow = do_QueryInterface(isupports); + } else { + nsCOMPtr cert0; + nsCOMPtr cert1; + + isupports = dont_AddRef(x509Certs->ElementAt(0)); + cert0 = do_QueryInterface(isupports); + + isupports = dont_AddRef(x509Certs->ElementAt(1)); + cert1 = do_QueryInterface(isupports); + + nsXPIDLString cert0SubjectName; + nsXPIDLString cert0IssuerName; + nsXPIDLString cert1SubjectName; + nsXPIDLString cert1IssuerName; + + cert0->GetIssuerName(getter_Copies(cert0IssuerName)); + cert0->GetSubjectName(getter_Copies(cert0SubjectName)); + + cert1->GetIssuerName(getter_Copies(cert1IssuerName)); + cert1->GetSubjectName(getter_Copies(cert1SubjectName)); + + if (nsCRT::strcmp(cert1IssuerName.get(), cert0SubjectName.get()) == 0) { + // In this case, the first cert in the list signed the second, + // so the first cert is the root. Let's display the last cert + // in the list. + selCertIndex = numCerts-1; + isupports = dont_AddRef(x509Certs->ElementAt(selCertIndex)); + certToShow = do_QueryInterface(isupports); + } else + if (nsCRT::strcmp(cert0IssuerName.get(), cert1SubjectName.get()) == 0) { + // In this case the second cert has signed the first cert. The + // first cert is the leaf, so let's display it. + selCertIndex = 0; + certToShow = cert0; + } else { + // It's not a chain, so let's just show the first one in the + // downloaded list. + selCertIndex = 0; + certToShow = cert0; + } + } + + if (!certToShow) + return NS_ERROR_FAILURE; + + nsCOMPtr dialogs; + nsresult rv = ::getNSSDialogs(getter_AddRefs(dialogs), + NS_GET_IID(nsICertificateDialogs)); + + if (NS_FAILED(rv)) + return rv; + + SECItem der; + rv=certToShow->GetRawDER((char **)&der.data, &der.len); + + if (NS_FAILED(rv)) + return rv; + + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Creating temp cert\n")); + CERTCertificate *tmpCert; + CERTCertDBHandle *certdb = CERT_GetDefaultCertDB(); + tmpCert = CERT_NewTempCertificate(certdb, &der, + nsnull, PR_FALSE, PR_TRUE); + if (!tmpCert) { + NS_ASSERTION(0,"Couldn't create cert from DER blob\n"); + return NS_ERROR_FAILURE; + } + + PRBool canceled; + if (tmpCert->isperm) { + dialogs->CACertExists(ctx, &canceled); + return NS_ERROR_FAILURE; + } + + PRUint32 trustBits; + rv = dialogs->DownloadCACert(ctx, certToShow, &trustBits, &canceled); + if (NS_FAILED(rv)) + return rv; + + if (canceled) + return NS_ERROR_NOT_AVAILABLE; + + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("trust is %d\n", trustBits)); + nsXPIDLCString nickname; + nickname.Adopt(CERT_MakeCANickname(tmpCert)); + + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Created nick \"%s\"\n", nickname.get())); + + nsNSSCertTrust trust; + trust.SetValidCA(); + trust.AddCATrust(trustBits & nsIX509CertDB::TRUSTED_SSL, + trustBits & nsIX509CertDB::TRUSTED_EMAIL, + trustBits & nsIX509CertDB::TRUSTED_OBJSIGN); + + SECStatus srv = CERT_AddTempCertToPerm(tmpCert, + NS_CONST_CAST(char*,nickname.get()), + trust.GetTrust()); + + if (srv != SECSuccess) + return NS_ERROR_FAILURE; + + // Now it's time to add the rest of the certs we just downloaded. + // Since we didn't prompt the user about any of these certs, we + // won't set any trust bits for them. + nsNSSCertTrust defaultTrust; + defaultTrust.SetValidCA(); + defaultTrust.AddCATrust(0,0,0); + for (PRUint32 i=0; iElementAt(i)); + certToShow = do_QueryInterface(isupports); + certToShow->GetRawDER((char **)&der.data, &der.len); + + tmpCert = CERT_NewTempCertificate(certdb, &der, + nsnull, PR_FALSE, PR_TRUE); + + if (!tmpCert) { + NS_ASSERTION(0, "Couldn't create temp cert from DER blob\n"); + continue; // Let's try to import the rest of 'em + } + nickname.Adopt(CERT_MakeCANickname(tmpCert)); + CERT_AddTempCertToPerm(tmpCert, NS_CONST_CAST(char*,nickname.get()), + defaultTrust.GetTrust()); + CERT_DestroyCertificate(tmpCert); + } + + return NS_OK; +} + /* - * [noscript] void importCertificate (in nsIX509Cert cert, - * in unsigned long type, - * in unsigned long trust, - * in wchar tokenName); + * [noscript] void importCertificates(in charPtr data, in unsigned long length, + * in unsigned long type, + * in nsIInterfaceRequestor ctx); */ NS_IMETHODIMP -nsNSSCertificateDB::ImportCertificate(nsIX509Cert *cert, - PRUint32 type, - PRUint32 trusted, - const PRUnichar *nickname) +nsNSSCertificateDB::ImportCertificates(char * data, PRUint32 length, + PRUint32 type, + nsIInterfaceRequestor *ctx) + { SECStatus srv = SECFailure; nsresult nsrv; - CERTCertificate *tmpCert = NULL; - nsNSSCertTrust trust; - char *nick; - SECItem der; + + PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (!arena) + return NS_ERROR_OUT_OF_MEMORY; + + CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length); + if (!certCollection) { + PORT_FreeArena(arena, PR_FALSE); + return NS_ERROR_FAILURE; + } + nsCOMPtr array; + nsresult rv = NS_NewISupportsArray(getter_AddRefs(array)); + if (NS_FAILED(rv)) { + PORT_FreeArena(arena, PR_FALSE); + return rv; + } + + // Now let's create some certs to work with + nsCOMPtr x509Cert; + nsNSSCertificate *nssCert; + SECItem *currItem; + for (int i=0; inumcerts; i++) { + currItem = &certCollection->rawCerts[i]; + nssCert = new nsNSSCertificate((char*)currItem->data, currItem->len); + if (!nssCert) + return NS_ERROR_OUT_OF_MEMORY; + x509Cert = do_QueryInterface(nssCert); + array->AppendElement(x509Cert); + } switch (type) { case nsIX509Cert::CA_CERT: - trust.SetValidCA(); - trust.AddCATrust(trusted & nsIX509CertDB::TRUSTED_SSL, - trusted & nsIX509CertDB::TRUSTED_EMAIL, - trusted & nsIX509CertDB::TRUSTED_OBJSIGN); + nsrv = handleCACertDownload(array, ctx); break; default: - return NS_ERROR_NOT_IMPLEMENTED; - } - nsrv = cert->GetRawDER((char **)&der.data, &der.len); - if (nsrv != NS_OK) - return NS_ERROR_FAILURE; - PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Creating temp cert\n")); - tmpCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &der, - NULL, PR_FALSE, PR_TRUE); - if (!tmpCert) goto done; - if (nickname) { - nick = NS_CONST_CAST(char*, NS_ConvertUCS2toUTF8(nickname).get()); - } else { - nick = CERT_MakeCANickname(tmpCert); - } - PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Created nick \"%s\"\n", nick)); - /* XXX check to see if cert is perm (it shouldn't be, but NSS asserts if it is */ - /* XXX this is an ugly peek into NSS */ - - //Check moved to PSMContentDownloader::OnStopRequest in nsNSSComponent.cpp - //so that the user can be informed before downloading, if cert exists - - /* - if (tmpCert->isperm) { - PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Cert was already in db %s\n", nick)); - return NS_ERROR_FAILURE; - } - */ - srv = CERT_AddTempCertToPerm(tmpCert, nick, trust.GetTrust()); -done: - if (tmpCert) - CERT_DestroyCertificate(tmpCert); - return (srv) ? NS_ERROR_FAILURE : NS_OK; + // We only deal with import CA certs in this method currently. + nsrv = NS_ERROR_FAILURE; + break; + } + PORT_FreeArena(arena, PR_FALSE); + if (srv != SECSuccess && nsrv == NS_OK) + nsrv = NS_ERROR_FAILURE; + return nsrv; } char * @@ -2714,32 +2919,7 @@ done: PR_FREEIF(tmp); return(nickname); } -static SECStatus PR_CALLBACK -collect_certs(void *arg, SECItem **certs, int numcerts) -{ - CERTDERCerts *collectArgs; - SECItem *cert; - SECStatus rv; - collectArgs = (CERTDERCerts *)arg; - - collectArgs->numcerts = numcerts; - collectArgs->rawCerts = (SECItem *) PORT_ArenaZAlloc(collectArgs->arena, - sizeof(SECItem) * numcerts); - if ( collectArgs->rawCerts == NULL ) - return(SECFailure); - cert = collectArgs->rawCerts; - - while ( numcerts-- ) { - rv = SECITEM_CopyItem(collectArgs->arena, cert, *certs); - if ( rv == SECFailure ) - return(SECFailure); - cert++; - certs++; - } - - return (SECSuccess); -} NS_IMETHODIMP nsNSSCertificateDB::ImportUserCertificate(char *data, PRUint32 length, nsIInterfaceRequestor *ctx) @@ -2748,23 +2928,17 @@ nsNSSCertificateDB::ImportUserCertificate(char *data, PRUint32 length, nsIInterf char * nickname = NULL; SECStatus sec_rv; int numCACerts; - SECItem *CACerts; - CERTDERCerts * collectArgs; - PRArenaPool *arena; - CERTCertificate * cert=NULL; + SECItem *CACerts; + CERTDERCerts * collectArgs; + PRArenaPool *arena; + CERTCertificate * cert=NULL; arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if ( arena == NULL ) goto loser; - collectArgs = (CERTDERCerts *)PORT_ArenaZAlloc(arena, sizeof(CERTDERCerts)); - if ( collectArgs == NULL ) - goto loser; - - collectArgs->arena = arena; - sec_rv = CERT_DecodeCertPackage(data, length, collect_certs, - (void *)collectArgs); - if (sec_rv != SECSuccess) + collectArgs = getCertsFromPackage(arena, data, length); + if (!collectArgs) goto loser; cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), collectArgs->rawCerts, diff --git a/security/manager/ssl/src/nsNSSCertificate.h b/security/manager/ssl/src/nsNSSCertificate.h index b9fd201ee3a7..0be34df1f66e 100644 --- a/security/manager/ssl/src/nsNSSCertificate.h +++ b/security/manager/ssl/src/nsNSSCertificate.h @@ -77,6 +77,7 @@ private: PRUint32 *_verified, PRUint32 *_count, PRUnichar **tmpUsages); + }; class nsNSSCertificateDB : public nsIX509CertDB @@ -97,6 +98,10 @@ private: PRUint32 *_count, PRUnichar ***_certNameList); + CERTDERCerts *getCertsFromPackage(PRArenaPool *arena, char *data, + PRUint32 length); + nsresult handleCACertDownload(nsISupportsArray *x509Certs, + nsIInterfaceRequestor *ctx); }; // Use this function to generate a default nickname for a user diff --git a/security/manager/ssl/src/nsNSSComponent.cpp b/security/manager/ssl/src/nsNSSComponent.cpp index 00b6ccdadd53..87b19c135034 100644 --- a/security/manager/ssl/src/nsNSSComponent.cpp +++ b/security/manager/ssl/src/nsNSSComponent.cpp @@ -1069,61 +1069,20 @@ PSMContentDownloader::OnStopRequest(nsIRequest* request, nsCOMPtr certdb = do_GetService(NS_X509CERTDB_CONTRACTID); nsresult rv; - SECItem der; - CERTCertificate *tmpCert = NULL; nsCOMPtr ctx = new PSMContentDownloaderContext(); switch (mType) { case PSMContentDownloader::X509_CA_CERT: - { - nsCOMPtr cert = new nsNSSCertificate(mByteData, mBufferOffset); - if (certdb == nsnull) - return NS_ERROR_FAILURE; - - nsCOMPtr dialogs; - PRBool canceled; - PRUint32 trust; - rv = ::getNSSDialogs(getter_AddRefs(dialogs), - NS_GET_IID(nsICertificateDialogs)); - if (NS_FAILED(rv)) goto loser; - - rv=cert->GetRawDER((char **)&der.data, &der.len); - if (rv != NS_OK) - return NS_ERROR_FAILURE; - - PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Creating temp cert\n")); - tmpCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &der, - NULL, PR_FALSE, PR_TRUE); - - //Added to check if cert exists - if (tmpCert->isperm) - { - dialogs->CACertExists(ctx, &canceled); - rv = NS_ERROR_FAILURE; - break; - } - //end added - - rv = dialogs->DownloadCACert(ctx, cert, &trust, &canceled); - if (NS_FAILED(rv)) goto loser; - if (canceled) { rv = NS_ERROR_NOT_AVAILABLE; goto loser; } - PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("trust is %d\n", trust)); - - return certdb->ImportCertificate(cert, mType, trust, nsnull); - } + return certdb->ImportCertificates(mByteData, mBufferOffset, mType, ctx); case PSMContentDownloader::X509_USER_CERT: return certdb->ImportUserCertificate(mByteData, mBufferOffset, ctx); break; case PSMContentDownloader::PKCS7_CRL: return certdb->ImportCrl(mByteData, mBufferOffset, mURI, SEC_CRL_TYPE); default: - rv = NS_ERROR_FAILURE; - break; + rv = NS_ERROR_FAILURE; + break; } -loser: - - if (tmpCert) - CERT_DestroyCertificate(tmpCert); return rv; } diff --git a/security/manager/ssl/src/nsPKCS12Blob.cpp b/security/manager/ssl/src/nsPKCS12Blob.cpp index 65374a251397..a6245a36a788 100644 --- a/security/manager/ssl/src/nsPKCS12Blob.cpp +++ b/security/manager/ssl/src/nsPKCS12Blob.cpp @@ -31,7 +31,7 @@ * may use your version of this file under either the MPL or the * GPL. * - * $Id: nsPKCS12Blob.cpp,v 1.18 2001/08/15 01:34:36 javi%netscape.com Exp $ + * $Id: nsPKCS12Blob.cpp,v 1.19 2001/08/22 04:05:45 javi%netscape.com Exp $ */ #include "prmem.h" @@ -74,6 +74,7 @@ static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID); #define PIP_PKCS12_NOSMARTCARD_EXPORT 4 #define PIP_PKCS12_RESTORE_FAILED 5 #define PIP_PKCS12_BACKUP_FAILED 6 +#define PIP_PKCS12_NSS_ERROR 7 // constructor nsPKCS12Blob::nsPKCS12Blob():mCertArray(0), @@ -182,7 +183,12 @@ nsPKCS12Blob::ImportFromFile(nsILocalFile *file) // Later - check to see if this should become default email cert handleError(PIP_PKCS12_RESTORE_OK); finish: - if (NS_FAILED(rv) || srv != SECSuccess) { + // If srv != SECSuccess, NSS probably set a specific error code. + // We should use that error code instead of inventing a new one + // for every error possible. + if (srv != SECSuccess) { + handleError(PIP_PKCS12_NSS_ERROR); + } else if (NS_FAILED(rv)) { handleError(PIP_PKCS12_RESTORE_FAILED); } // finish the decoder @@ -726,53 +732,67 @@ nsPKCS12Blob::handleError(int myerr) if (NS_FAILED(rv)) return rv; errPrompt->Alert(nsnull, errorMsg.get()); return PR_TRUE; - case 0: - default: - break; - } - switch (prerr) { - // The following errors have the potential to be "handled", by asking - // the user (via a dialog) whether s/he wishes to continue - case 0: break; - case SEC_ERROR_PKCS12_CERT_COLLISION: - /* pop a dialog saying the cert is already in the database */ - /* ask to keep going? what happens if one collision but others ok? */ - // The following errors cannot be "handled", notify the user (via an alert) - // that the operation failed. + case PIP_PKCS12_NSS_ERROR: + switch (prerr) { + // The following errors have the potential to be "handled", by asking + // the user (via a dialog) whether s/he wishes to continue + case 0: break; + case SEC_ERROR_PKCS12_CERT_COLLISION: + /* pop a dialog saying the cert is already in the database */ + /* ask to keep going? what happens if one collision but others ok? */ + // The following errors cannot be "handled", notify the user (via an alert) + // that the operation failed. #if 0 -// XXX a boy can dream... -// but the PKCS12 lib never throws this error -// but then again, how would it? anyway, convey the info below - case SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT: - rv = nssComponent->GetPIPNSSBundleString( + // XXX a boy can dream... + // but the PKCS12 lib never throws this error + // but then again, how would it? anyway, convey the info below + case SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT: + rv = nssComponent->GetPIPNSSBundleString( NS_LITERAL_STRING("PKCS12PasswordInvalid").get(), errorMsg); - if (NS_FAILED(rv)) return rv; - errPrompt->Alert(nsnull, errorMsg.get()); + if (NS_FAILED(rv)) return rv; + errPrompt->Alert(nsnull, errorMsg.get()); break; #endif - case SEC_ERROR_BAD_PASSWORD: - rv = nssComponent->GetPIPNSSBundleString( - NS_LITERAL_STRING("PK11BadPassword").get(), + case SEC_ERROR_BAD_PASSWORD: + rv = nssComponent->GetPIPNSSBundleString( + NS_LITERAL_STRING("PK11BadPassword").get(), + errorMsg); + if (NS_FAILED(rv)) return rv; + errPrompt->Alert(nsnull, errorMsg.get()); + break; + case SEC_ERROR_BAD_DER: + case SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE: + case SEC_ERROR_PKCS12_INVALID_MAC: + rv = nssComponent->GetPIPNSSBundleString( + NS_LITERAL_STRING("PKCS12DecodeErr").get(), + errorMsg); + if (NS_FAILED(rv)) return rv; + errPrompt->Alert(nsnull, errorMsg.get()); + break; + case SEC_ERROR_PKCS12_DUPLICATE_DATA: + rv = nssComponent->GetPIPNSSBundleString( + NS_LITERAL_STRING("PKCS12DupData").get(), errorMsg); - if (NS_FAILED(rv)) return rv; - errPrompt->Alert(nsnull, errorMsg.get()); - break; - case SEC_ERROR_BAD_DER: - case SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE: - case SEC_ERROR_PKCS12_INVALID_MAC: - rv = nssComponent->GetPIPNSSBundleString( - NS_LITERAL_STRING("PKCS12DecodeErr").get(), + if (NS_FAILED(rv)) return rv; + errPrompt->Alert(nsnull, errorMsg.get()); + break; + default: + rv = nssComponent->GetPIPNSSBundleString( + NS_LITERAL_STRING("PKCS12UnknownErr").get(), errorMsg); - if (NS_FAILED(rv)) return rv; - errPrompt->Alert(nsnull, errorMsg.get()); + if (NS_FAILED(rv)) return rv; + errPrompt->Alert(nsnull, errorMsg.get()); + } break; + case 0: default: rv = nssComponent->GetPIPNSSBundleString( NS_LITERAL_STRING("PKCS12UnknownErr").get(), errorMsg); if (NS_FAILED(rv)) return rv; errPrompt->Alert(nsnull, errorMsg.get()); + break; } if (NS_FAILED(rv)) return rv; return keepGoing;