bug 1334694 - remove token arguments from nsIX509CertDB.importPKCS12File and exportPKCS12File r?Cykesiopka draft
authorDavid Keeler <dkeeler@mozilla.com>
Fri, 27 Jan 2017 15:26:20 -0800
changeset 468162 e5e0f359138e429b66c04fb6f24b121bd05a83db
parent 468005 f7e1982a2582b14c5885d787b530f879da3a040e
child 543871 fbc1748e4689606284f61544c9fc1c4364b976ae
push id43377
push userdkeeler@mozilla.com
push dateMon, 30 Jan 2017 21:10:30 +0000
reviewersCykesiopka
bugs1334694
milestone54.0a1
bug 1334694 - remove token arguments from nsIX509CertDB.importPKCS12File and exportPKCS12File r?Cykesiopka MozReview-Commit-ID: Ceo48mcF38I
security/manager/pki/resources/content/certManager.js
security/manager/ssl/nsIX509CertDB.idl
security/manager/ssl/nsNSSCertificateDB.cpp
security/manager/ssl/nsPKCS12Blob.cpp
security/manager/ssl/nsPKCS12Blob.h
security/manager/ssl/tests/unit/test_certDB_import_pkcs12.js
--- a/security/manager/pki/resources/content/certManager.js
+++ b/security/manager/pki/resources/content/certManager.js
@@ -329,18 +329,17 @@ function backupCerts()
   fp.init(window,
           bundle.getString("chooseP12BackupFileDialog"),
           nsIFilePicker.modeSave);
   fp.appendFilter(bundle.getString("file_browse_PKCS12_spec"),
                   "*.p12");
   fp.appendFilters(nsIFilePicker.filterAll);
   var rv = fp.show();
   if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
-    certdb.exportPKCS12File(null, fp.file, selected_certs.length,
-                            selected_certs);
+    certdb.exportPKCS12File(fp.file, selected_certs.length, selected_certs);
   }
 }
 
 function backupAllCerts()
 {
   // Select all rows, then call doBackup()
   var items = userTreeView.selection.selectAll();
   backupCerts();
@@ -394,17 +393,17 @@ function restoreCerts()
       let interfaceRequestor = {
         getInterface: function() {
           return prompter;
         }
       };
       certdb.importUserCertificate(dataArray, dataArray.length, interfaceRequestor);
     } else {
       // Otherwise, assume it's a PKCS12 file and import it that way.
-      certdb.importPKCS12File(null, fp.file);
+      certdb.importPKCS12File(fp.file);
     }
 
     var certcache = certdb.getCerts();
     userTreeView.loadCertsFromCache(certcache, nsIX509Cert.USER_CERT);
     userTreeView.selection.clearSelection();
     caTreeView.loadCertsFromCache(certcache, nsIX509Cert.CA_CERT);
     caTreeView.selection.clearSelection();
     enableBackupAllButton();
--- a/security/manager/ssl/nsIX509CertDB.idl
+++ b/security/manager/ssl/nsIX509CertDB.idl
@@ -185,38 +185,29 @@ interface nsIX509CertDB : nsISupports {
    *               be imported. See type constants in nsIX509Cert.
    */
   void importCertsFromFile(in nsIFile aFile,
                            in unsigned long aType);
 
   /**
    *  Import a PKCS#12 file containing cert(s) and key(s) into the database.
    *
-   *  @param aToken Optionally limits the scope of
-   *                this function to a token device.
-   *                Can be null to mean any token.
-   *  @param aFile Identifies a file that contains the data
-   *               to be imported.
+   *  @param aFile Identifies a file that contains the data to be imported.
    */
-  void importPKCS12File(in nsISupports aToken,
-                        in nsIFile aFile);
+  void importPKCS12File(in nsIFile aFile);
 
   /**
    *  Export a set of certs and keys from the database to a PKCS#12 file.
    *
-   *  @param aToken Optionally limits the scope of
-   *                this function to a token device.
-   *                Can be null to mean any token.
-   *  @param aFile Identifies a file that will be filled with the data
-   *               to be exported.
+   *  @param aFile Identifies a file that will be filled with the data to be
+   *               exported.
    *  @param count The number of certificates to be exported.
    *  @param aCerts The array of all certificates to be exported.
    */
-  void exportPKCS12File(in nsISupports aToken,
-                        in nsIFile aFile,
+  void exportPKCS12File(in nsIFile aFile,
                         in unsigned long count,
                         [array, size_is(count)] in nsIX509Cert aCerts);
 
   /*
    *  Decode a raw data presentation and instantiate an object in memory.
    *
    *  @param base64 The raw representation of a certificate,
    *                encoded as Base 64.
--- a/security/manager/ssl/nsNSSCertificateDB.cpp
+++ b/security/manager/ssl/nsNSSCertificateDB.cpp
@@ -27,17 +27,16 @@
 #include "nsIPrefService.h"
 #include "nsIPrompt.h"
 #include "nsNSSCertHelper.h"
 #include "nsNSSCertTrust.h"
 #include "nsNSSCertificate.h"
 #include "nsNSSComponent.h"
 #include "nsNSSHelper.h"
 #include "nsNSSShutDown.h"
-#include "nsPK11TokenDB.h"
 #include "nsPKCS12Blob.h"
 #include "nsPromiseFlatString.h"
 #include "nsProxyRelease.h"
 #include "nsReadableUtils.h"
 #include "nsThreadUtils.h"
 #include "nspr.h"
 #include "pkix/Time.h"
 #include "pkix/pkixnss.h"
@@ -960,57 +959,42 @@ nsNSSCertificateDB::ImportCertsFromFile(
       MOZ_ASSERT(false, "Unsupported type should have been filtered out");
       break;
   }
 
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
-nsNSSCertificateDB::ImportPKCS12File(nsISupports* aToken, nsIFile* aFile)
+nsNSSCertificateDB::ImportPKCS12File(nsIFile* aFile)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown()) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   NS_ENSURE_ARG(aFile);
   nsPKCS12Blob blob;
-  nsCOMPtr<nsIPK11Token> token = do_QueryInterface(aToken);
-  if (token) {
-    blob.SetToken(token);
-  }
   return blob.ImportFromFile(aFile);
 }
 
 NS_IMETHODIMP
-nsNSSCertificateDB::ExportPKCS12File(nsISupports* aToken,
-                                     nsIFile* aFile,
-                                     uint32_t count,
+nsNSSCertificateDB::ExportPKCS12File(nsIFile* aFile, uint32_t count,
                                      nsIX509Cert** certs)
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown()) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   NS_ENSURE_ARG(aFile);
+  if (count == 0) {
+    return NS_OK;
+  }
   nsPKCS12Blob blob;
-  if (count == 0) return NS_OK;
-  nsCOMPtr<nsIPK11Token> localRef;
-  if (!aToken) {
-    UniquePK11SlotInfo keySlot(PK11_GetInternalKeySlot());
-    if (!keySlot) {
-      return NS_ERROR_FAILURE;
-    }
-    localRef = new nsPK11Token(keySlot.get());
-  } else {
-    localRef = do_QueryInterface(aToken);
-  }
-  blob.SetToken(localRef);
   return blob.ExportToFile(aFile, certs, count);
 }
 
 NS_IMETHODIMP
 nsNSSCertificateDB::FindCertByEmailAddress(const char* aEmailAddress,
                                            nsIX509Cert** _retval)
 {
   nsNSSShutDownPreventionLock locker;
--- a/security/manager/ssl/nsPKCS12Blob.cpp
+++ b/security/manager/ssl/nsPKCS12Blob.cpp
@@ -2,30 +2,23 @@
  * 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/. */
 
 #include "nsPKCS12Blob.h"
 
 #include "ScopedNSSTypes.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Casting.h"
-#include "nsCRT.h"
-#include "nsCRTGlue.h"
-#include "nsDirectoryServiceDefs.h"
 #include "nsICertificateDialogs.h"
-#include "nsIDirectoryService.h"
 #include "nsIFile.h"
 #include "nsIInputStream.h"
-#include "nsKeygenHandler.h" // For GetSlotWithMechanism
 #include "nsNSSCertificate.h"
 #include "nsNSSComponent.h"
 #include "nsNSSHelper.h"
-#include "nsNSSShutDown.h"
 #include "nsNetUtil.h"
-#include "nsPK11TokenDB.h"
 #include "nsReadableUtils.h"
 #include "nsString.h"
 #include "nsThreadUtils.h"
 #include "pkix/pkixtypes.h"
 #include "prmem.h"
 #include "prprf.h"
 #include "secerr.h"
 
@@ -38,97 +31,50 @@ extern LazyLogModule gPIPNSSLog;
 #define PIP_PKCS12_BACKUP_OK           2
 #define PIP_PKCS12_USER_CANCELED       3
 #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(nullptr),
-                             mTmpFile(nullptr),
-                             mTokenSet(false)
+nsPKCS12Blob::nsPKCS12Blob()
+  : mCertArray(nullptr)
+  , mTmpFile(nullptr)
 {
   mUIContext = new PipUIContext();
 }
 
 // destructor
 nsPKCS12Blob::~nsPKCS12Blob()
 {
   nsNSSShutDownPreventionLock locker;
   if (isAlreadyShutDown()) {
     return;
   }
 
   shutdown(ShutdownCalledFrom::Object);
 }
 
-// nsPKCS12Blob::SetToken
-//
-// Set the token to use for import/export
-nsresult
-nsPKCS12Blob::SetToken(nsIPK11Token *token)
-{
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown()) {
-  return NS_ERROR_NOT_AVAILABLE;
- }
- nsresult rv = NS_OK;
- if (token) {
-   mToken = token;
- } else {
-   PK11SlotInfo *slot;
-   rv = GetSlotWithMechanism(CKM_RSA_PKCS, mUIContext, &slot, locker);
-   if (NS_FAILED(rv)) {
-      mToken = nullptr;
-   } else {
-     mToken = new nsPK11Token(slot);
-     PK11_FreeSlot(slot);
-   }
- }
- mTokenSet = true;
- return rv;
-}
-
 // nsPKCS12Blob::ImportFromFile
 //
-// Given a file handle, read a PKCS#12 blob from that file, decode it,
-// and import the results into the token.
+// Given a file handle, read a PKCS#12 blob from that file, decode it, and
+// import the results into the internal database.
 nsresult
 nsPKCS12Blob::ImportFromFile(nsIFile *file)
 {
   nsNSSShutDownPreventionLock locker;
   nsresult rv = NS_OK;
 
-  if (!mToken) {
-    if (!mTokenSet) {
-      rv = SetToken(nullptr); // Ask the user to pick a slot
-      if (NS_FAILED(rv)) {
-        handleError(PIP_PKCS12_USER_CANCELED);
-        return rv;
-      }
-    }
-  }
-
-  if (!mToken) {
-    handleError(PIP_PKCS12_RESTORE_FAILED);
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  // init slot
-  rv = mToken->Login(true);
-  if (NS_FAILED(rv)) return rv;
-  
   RetryReason wantRetry;
   
   do {
     rv = ImportFromFileHelper(file, im_standard_prompt, wantRetry);
     
-    if (NS_SUCCEEDED(rv) && wantRetry == rr_auto_retry_empty_password_flavors)
-    {
+    if (NS_SUCCEEDED(rv) && wantRetry == rr_auto_retry_empty_password_flavors) {
       rv = ImportFromFileHelper(file, im_try_zero_length_secitem, wantRetry);
     }
   }
   while (NS_SUCCEEDED(rv) && (wantRetry != rr_do_not_retry));
   
   return rv;
 }
 
@@ -136,49 +82,38 @@ nsresult
 nsPKCS12Blob::ImportFromFileHelper(nsIFile *file, 
                                    nsPKCS12Blob::ImportMode aImportMode,
                                    nsPKCS12Blob::RetryReason &aWantRetry)
 {
   nsNSSShutDownPreventionLock locker;
   nsresult rv = NS_OK;
   SECStatus srv = SECSuccess;
   SEC_PKCS12DecoderContext *dcx = nullptr;
-  SECItem unicodePw;
-
-  UniquePK11SlotInfo slot;
-  nsAutoCString tokenName;
-  unicodePw.data = nullptr;
+  SECItem unicodePw = { siBuffer, nullptr, 0  };
 
   aWantRetry = rr_do_not_retry;
 
-  if (aImportMode == im_try_zero_length_secitem)
-  {
+  UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
+  if (!slot) {
+    srv = SECFailure;
+    goto finish;
+  }
+
+  if (aImportMode == im_try_zero_length_secitem) {
     unicodePw.len = 0;
-  }
-  else
-  {
+  } else {
     // get file password (unicode)
     rv = getPKCS12FilePassword(&unicodePw);
     if (NS_FAILED(rv)) goto finish;
     if (!unicodePw.data) {
       handleError(PIP_PKCS12_USER_CANCELED);
       return NS_OK;
     }
   }
 
-  rv = mToken->GetTokenName(tokenName);
-  if (NS_FAILED(rv)) {
-    goto finish;
-  }
-  slot = UniquePK11SlotInfo(PK11_FindSlotByName(tokenName.get()));
-  if (!slot) {
-    srv = SECFailure;
-    goto finish;
-  }
-
   // initialize the decoder
   dcx = SEC_PKCS12DecoderStart(&unicodePw, slot.get(), nullptr, nullptr,
                                nullptr, nullptr, nullptr, nullptr);
   if (!dcx) {
     srv = SECFailure;
     goto finish;
   }
   // read input file and feed it to the decoder
@@ -249,43 +184,34 @@ isExtractable(SECKEYPrivateKey *privKey)
   }
   return isExtractable;
 }
 
 // nsPKCS12Blob::ExportToFile
 //
 // Having already loaded the certs, form them into a blob (loading the keys
 // also), encode the blob, and stuff it into the file.
-//
-// TODO: handle slots correctly
-//       mirror "slotToUse" behavior from PSM 1.x
-//       verify the cert array to start off with?
-//       open output file as nsIFileStream object?
-//       set appropriate error codes
 nsresult
 nsPKCS12Blob::ExportToFile(nsIFile *file, 
                            nsIX509Cert **certs, int numCerts)
 {
   nsNSSShutDownPreventionLock locker;
   nsresult rv;
   SECStatus srv = SECSuccess;
   SEC_PKCS12ExportContext *ecx = nullptr;
   SEC_PKCS12SafeInfo *certSafe = nullptr, *keySafe = nullptr;
   SECItem unicodePw;
   nsAutoString filePath;
   int i;
   nsCOMPtr<nsIFile> localFileRef;
-  MOZ_ASSERT(mToken, "Need to set the token before exporting");
   // init slot
 
   bool InformedUserNoSmartcardBackup = false;
   int numCertsExported = 0;
 
-  rv = mToken->Login(true);
-  if (NS_FAILED(rv)) goto finish;
   // get file password (unicode)
   unicodePw.data = nullptr;
   rv = newPKCS12FilePassword(&unicodePw);
   if (NS_FAILED(rv)) goto finish;
   if (!unicodePw.data) {
     handleError(PIP_PKCS12_USER_CANCELED);
     return NS_OK;
   }
--- a/security/manager/ssl/nsPKCS12Blob.h
+++ b/security/manager/ssl/nsPKCS12Blob.h
@@ -1,57 +1,47 @@
 /* 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/. */
 /* $Id: nsPKCS12Blob.h,v 1.16 2006/04/12 15:43:32 benjamin%smedbergs.us Exp $ */
 
-#ifndef _NS_PKCS12BLOB_H_
-#define _NS_PKCS12BLOB_H_
+#ifndef nsPKCS12Blob_h
+#define nsPKCS12Blob_h
 
 #include "nsCOMPtr.h"
-#include "nsString.h"
-#include "nsIFile.h"
-#include "nsIPK11TokenDB.h"
-#include "nsNSSHelper.h"
-#include "nsIPK11Token.h"
 #include "nsIMutableArray.h"
-
-#include "nss.h"
-
-#include "pkcs12.h"
-#include "p12plcy.h"
+#include "nsNSSShutDown.h"
+#include "p12.h"
+#include "seccomon.h"
 
 class nsIX509Cert;
+class nsIFile;
 
 //
 // nsPKCS12Blob
 //
 // Class for importing/exporting PKCS#12 blobs
 //
 class nsPKCS12Blob : public nsNSSShutDownObject
 {
 public:
   nsPKCS12Blob();
   virtual ~nsPKCS12Blob();
 
   // Nothing to release.
   virtual void virtualDestroyNSSReference() override {}
 
-  // Set the token to use (default is internal)
-  nsresult SetToken(nsIPK11Token *token);
-
   // PKCS#12 Import
   nsresult ImportFromFile(nsIFile *file);
 
   // PKCS#12 Export
   nsresult ExportToFile(nsIFile *file, nsIX509Cert **certs, int numCerts);
 
 private:
 
-  nsCOMPtr<nsIPK11Token>          mToken;
   nsCOMPtr<nsIMutableArray>       mCertArray;
   nsCOMPtr<nsIInterfaceRequestor> mUIContext;
 
   // local helper functions
   nsresult getPKCS12FilePassword(SECItem *);
   nsresult newPKCS12FilePassword(SECItem *);
   nsresult inputToDecoder(SEC_PKCS12DecoderContext *, nsIFile *);
   nsresult unicodeToItem(const char16_t *, SECItem *);
@@ -72,16 +62,13 @@ private:
   enum RetryReason { rr_do_not_retry, rr_bad_password, rr_auto_retry_empty_password_flavors };
   enum ImportMode { im_standard_prompt, im_try_zero_length_secitem };
   
   nsresult ImportFromFileHelper(nsIFile *file, ImportMode aImportMode, RetryReason &aWantRetry);
 
   // NSPR file I/O for export file
   PRFileDesc *mTmpFile;
 
-  bool        mTokenSet;
-
   static SECItem * nickname_collision(SECItem *, PRBool *, void *);
   static void write_export_file(void *arg, const char *buf, unsigned long len);
-
 };
 
-#endif /* _NS_PKCS12BLOB_H_ */
+#endif // nsPKCS12Blob_h
--- a/security/manager/ssl/tests/unit/test_certDB_import_pkcs12.js
+++ b/security/manager/ssl/tests/unit/test_certDB_import_pkcs12.js
@@ -59,17 +59,17 @@ function doesCertExist(commonName) {
 }
 
 function testImportPKCS12Cert() {
   ok(!doesCertExist(CERT_COMMON_NAME),
      "Cert should not be in the database before import");
 
   // Import and check for success.
   let certFile = do_get_file("test_certDB_import/cert_from_windows.pfx");
-  gCertDB.importPKCS12File(null, certFile);
+  gCertDB.importPKCS12File(certFile);
 
   ok(gGetPKCS12Password, "PKCS12 password should be asked");
 
   ok(doesCertExist(CERT_COMMON_NAME),
      "Cert should now be found in the database");
 }
 
 function run_test() {