Bug 1399867, pk12util: Make -c try different password encoding if failed, r=rrelyea, r=kaie
authorDaiki Ueno <dueno@redhat.com>
Thu, 14 Sep 2017 15:10:14 +0200
changeset 13601 3c7359ad3ce609ca7c4189c05cc05cf0fdac0db3
parent 13600 835f791a0918bea762acdb606fff8b50c9aadac7
child 13602 16eb0e48e4381bd8aa4128d75006d22215f6006f
push id2383
push userkaie@kuix.de
push dateWed, 20 Sep 2017 10:06:29 +0000
reviewersrrelyea, kaie
bugs1399867
Bug 1399867, pk12util: Make -c try different password encoding if failed, r=rrelyea, r=kaie
cmd/pk12util/pk12util.c
--- a/cmd/pk12util/pk12util.c
+++ b/cmd/pk12util/pk12util.c
@@ -18,16 +18,17 @@
 #include "secpkcs5.h"
 #include "certdb.h"
 
 #define PKCS12_IN_BUFFER_SIZE 200
 
 static char *progName;
 PRBool pk12_debugging = PR_FALSE;
 PRBool dumpRawFile;
+static PRBool pk12uForceUnicode;
 
 PRIntn pk12uErrno = 0;
 
 static void
 Usage(char *progName)
 {
 #define FPS PR_fprintf(PR_STDERR,
     FPS "Usage:	 %s -i importfile [-d certdir] [-P dbprefix] [-h tokenname]\n",
@@ -465,51 +466,84 @@ done:
  *  variables have been added for this purpose.
  */
 PRIntn
 P12U_ImportPKCS12Object(char *in_file, PK11SlotInfo *slot,
                         secuPWData *slotPw, secuPWData *p12FilePw)
 {
     SEC_PKCS12DecoderContext *p12dcx = NULL;
     SECItem uniPwitem = { 0 };
+    PRBool forceUnicode = pk12uForceUnicode;
+    PRBool trypw;
     SECStatus rv = SECFailure;
 
     rv = P12U_InitSlot(slot, slotPw);
     if (rv != SECSuccess) {
         SECU_PrintError(progName, "Failed to authenticate to \"%s\"",
                         PK11_GetSlotName(slot));
         pk12uErrno = PK12UERR_PK11GETSLOT;
         return rv;
     }
 
-    rv = SECFailure;
-    p12dcx = p12U_ReadPKCS12File(&uniPwitem, in_file, slot, slotPw, p12FilePw);
+    do {
+        trypw = PR_FALSE; /* normally we do this once */
+        rv = SECFailure;
+        p12dcx = p12U_ReadPKCS12File(&uniPwitem, in_file, slot, slotPw, p12FilePw);
+
+        if (p12dcx == NULL) {
+            goto loser;
+        }
 
-    if (p12dcx == NULL) {
-        goto loser;
-    }
+        /* make sure the bags are okey dokey -- nicknames correct, etc. */
+        rv = SEC_PKCS12DecoderValidateBags(p12dcx, P12U_NicknameCollisionCallback);
+        if (rv != SECSuccess) {
+            if (PORT_GetError() == SEC_ERROR_PKCS12_DUPLICATE_DATA) {
+                pk12uErrno = PK12UERR_CERTALREADYEXISTS;
+            } else {
+                pk12uErrno = PK12UERR_DECODEVALIBAGS;
+            }
+            SECU_PrintError(progName, "PKCS12 decode validate bags failed");
+            goto loser;
+        }
 
-    /* make sure the bags are okey dokey -- nicknames correct, etc. */
-    rv = SEC_PKCS12DecoderValidateBags(p12dcx, P12U_NicknameCollisionCallback);
-    if (rv != SECSuccess) {
-        if (PORT_GetError() == SEC_ERROR_PKCS12_DUPLICATE_DATA) {
-            pk12uErrno = PK12UERR_CERTALREADYEXISTS;
-        } else {
-            pk12uErrno = PK12UERR_DECODEVALIBAGS;
+        /* stuff 'em in */
+        if (forceUnicode != pk12uForceUnicode) {
+            rv = NSS_OptionSet(__NSS_PKCS12_DECODE_FORCE_UNICODE,
+                               forceUnicode);
+            if (rv != SECSuccess) {
+                SECU_PrintError(progName, "PKCS12 decode set option failed");
+                pk12uErrno = PK12UERR_DECODEIMPTBAGS;
+                goto loser;
+            }
         }
-        SECU_PrintError(progName, "PKCS12 decode validate bags failed");
-        goto loser;
-    }
+        rv = SEC_PKCS12DecoderImportBags(p12dcx);
+        if (rv != SECSuccess) {
+            if (PR_GetError() == SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY &&
+                forceUnicode == pk12uForceUnicode) {
+                /* try again with a different password encoding */
+                forceUnicode = !pk12uForceUnicode;
+                SEC_PKCS12DecoderFinish(p12dcx);
+                SECITEM_ZfreeItem(&uniPwitem, PR_FALSE);
+                trypw = PR_TRUE;
+            } else {
+                SECU_PrintError(progName, "PKCS12 decode import bags failed");
+                pk12uErrno = PK12UERR_DECODEIMPTBAGS;
+                goto loser;
+            }
+        }
+    } while (trypw);
 
-    /* stuff 'em in */
-    rv = SEC_PKCS12DecoderImportBags(p12dcx);
-    if (rv != SECSuccess) {
-        SECU_PrintError(progName, "PKCS12 decode import bags failed");
-        pk12uErrno = PK12UERR_DECODEIMPTBAGS;
-        goto loser;
+    /* revert the option setting */
+    if (forceUnicode != pk12uForceUnicode) {
+        rv = NSS_OptionSet(__NSS_PKCS12_DECODE_FORCE_UNICODE, pk12uForceUnicode);
+        if (rv != SECSuccess) {
+            SECU_PrintError(progName, "PKCS12 decode set option failed");
+            pk12uErrno = PK12UERR_DECODEIMPTBAGS;
+            goto loser;
+        }
     }
 
     fprintf(stdout, "%s: PKCS12 IMPORT SUCCESSFUL\n", progName);
     rv = SECSuccess;
 
 loser:
     if (p12dcx) {
         SEC_PKCS12DecoderFinish(p12dcx);
@@ -942,16 +976,17 @@ main(int argc, char **argv)
     char *dbprefix = "";
     SECStatus rv;
     SECOidTag cipher =
         SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC;
     SECOidTag certCipher;
     int keyLen = 0;
     int certKeyLen = 0;
     secuCommand pk12util;
+    PRInt32 forceUnicode;
 
 #ifdef _CRTDBG_MAP_ALLOC
     _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
 #endif
 
     pk12util.numCommands = 0;
     pk12util.commands = 0;
     pk12util.numOptions = sizeof(pk12util_options) / sizeof(secuCommandFlag);
@@ -973,16 +1008,24 @@ main(int argc, char **argv)
         Usage(progName);
     }
 
     if (pk12util.options[opt_Export].activated &&
         !pk12util.options[opt_Nickname].activated) {
         Usage(progName);
     }
 
+    rv = NSS_OptionGet(__NSS_PKCS12_DECODE_FORCE_UNICODE, &forceUnicode);
+    if (rv != SECSuccess) {
+        SECU_PrintError(progName,
+                        "Failed to get NSS_PKCS12_DECODE_FORCE_UNICODE option");
+        Usage(progName);
+    }
+    pk12uForceUnicode = forceUnicode;
+
     slotname = SECU_GetOptionArg(&pk12util, opt_TokenName);
 
     import_file = (pk12util.options[opt_List].activated) ? SECU_GetOptionArg(&pk12util, opt_List)
                                                          : SECU_GetOptionArg(&pk12util, opt_Import);
     export_file = SECU_GetOptionArg(&pk12util, opt_Export);
 
     if (pk12util.options[opt_P12FilePWFile].activated) {
         p12FilePw.source = PW_FROMFILE;