mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
Bug#:280602 Added list option to pk12uti, test for it.
r=nelson@bolyard.com
This commit is contained in:
parent
e042c2f571
commit
a7dcc795a8
@ -59,6 +59,9 @@ Usage(char *progName)
|
||||
progName);
|
||||
FPS "\t\t [-k slotpwfile | -K slotpw] [-w p12filepwfile | -W p12filepw]\n");
|
||||
FPS "\t\t [-v]\n");
|
||||
FPS "Usage: %s -l listfile [-d certdir] [-P dbprefix] [-h tokenname]\n",
|
||||
progName);
|
||||
FPS "\t\t [-k slotpwfile | -K slotpw] [-w p12filepwfile | -W p12filepw]\n");
|
||||
FPS "Usage: %s -o exportfile -n certname [-d certdir] [-P dbprefix]\n", progName);
|
||||
FPS "\t\t [-k slotpwfile | -K slotpw] [-w p12filepwfile | -W p12filepw]\n");
|
||||
FPS "\t\t [-v]\n");
|
||||
@ -686,6 +689,140 @@ loser:
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
PRIntn
|
||||
P12U_ListPKCS12File(char *in_file, PK11SlotInfo *slot,
|
||||
secuPWData *slotPw, secuPWData *p12FilePw)
|
||||
{
|
||||
p12uContext *p12cxt = NULL;
|
||||
SEC_PKCS12DecoderContext *p12dcx = NULL;
|
||||
SECItem *pwitem = NULL, uniPwitem = { 0 };
|
||||
SECItem p12file = { 0 };
|
||||
SECStatus rv = SECFailure;
|
||||
PRBool swapUnicode = PR_FALSE;
|
||||
const SEC_PKCS12DecoderItem *dip;
|
||||
|
||||
int error;
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
swapUnicode = PR_TRUE;
|
||||
#endif
|
||||
|
||||
p12cxt = p12u_InitContext(PR_TRUE, in_file);
|
||||
if(!p12cxt) {
|
||||
SECU_PrintError(progName,"File Open failed: %s", in_file);
|
||||
pk12uErrno = PK12UERR_INIT_FILE;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* get the password */
|
||||
pwitem = P12U_GetP12FilePassword(PR_FALSE, p12FilePw);
|
||||
if (!pwitem) {
|
||||
pk12uErrno = PK12UERR_USER_CANCELLED;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
if(P12U_UnicodeConversion(NULL, &uniPwitem, pwitem, PR_TRUE,
|
||||
swapUnicode) != SECSuccess) {
|
||||
SECU_PrintError(progName,"Unicode conversion failed");
|
||||
pk12uErrno = PK12UERR_UNICODECONV;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* init the decoder context */
|
||||
p12dcx = SEC_PKCS12DecoderStart(&uniPwitem, slot, slotPw,
|
||||
NULL, NULL, NULL, NULL, NULL);
|
||||
if(!p12dcx) {
|
||||
SECU_PrintError(progName,"PKCS12 decoder start failed");
|
||||
pk12uErrno = PK12UERR_PK12DECODESTART;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* read the item */
|
||||
rv = SECU_FileToItem(&p12file, p12cxt->file);
|
||||
PR_Close(p12cxt->file);
|
||||
p12cxt->file = NULL;
|
||||
|
||||
if (rv != SECSuccess) {
|
||||
SECU_PrintError(progName,"Failed to read from import file");
|
||||
goto loser;
|
||||
}
|
||||
|
||||
rv = SEC_PKCS12DecoderUpdate(p12dcx, p12file.data, p12file.len);
|
||||
if(rv != SECSuccess) {
|
||||
error = PR_GetError();
|
||||
if(error == SEC_ERROR_DECRYPTION_DISALLOWED) {
|
||||
PR_SetError(error, 0);
|
||||
goto loser;
|
||||
}
|
||||
SECU_PrintError(progName,"PKCS12 decoding failed");
|
||||
pk12uErrno = PK12UERR_DECODE;
|
||||
}
|
||||
|
||||
/* does the blob authenticate properly? */
|
||||
if(SEC_PKCS12DecoderVerify(p12dcx) != SECSuccess) {
|
||||
SECU_PrintError(progName,"PKCS12 decode not verified");
|
||||
pk12uErrno = PK12UERR_DECODEVERIFY;
|
||||
rv = SECFailure;
|
||||
}
|
||||
else if (SEC_PKCS12DecoderIterateInit(p12dcx) != SECSuccess) {
|
||||
SECU_PrintError(progName,"PKCS12 decode iterate bags failed");
|
||||
pk12uErrno = PK12UERR_DECODEIMPTBAGS;
|
||||
rv = SECFailure;
|
||||
}
|
||||
else {
|
||||
while (SEC_PKCS12DecoderIterateNext(p12dcx, &dip) == SECSuccess) {
|
||||
switch (dip->type) {
|
||||
case SEC_OID_PKCS12_V1_CERT_BAG_ID:
|
||||
printf("Certificate");
|
||||
if (SECU_PrintSignedData(stdout, dip->der,
|
||||
(dip->hasKey) ? "(has private key)" : "",
|
||||
0, SECU_PrintCertificate) != 0) {
|
||||
SECU_PrintError(progName,"PKCS12 print cert bag failed");
|
||||
}
|
||||
if (dip->friendlyName != NULL) {
|
||||
printf(" Friendly Name: %s\n\n",
|
||||
dip->friendlyName->data);
|
||||
}
|
||||
break;
|
||||
case SEC_OID_PKCS12_V1_KEY_BAG_ID:
|
||||
case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
|
||||
printf("Key");
|
||||
if (dip->type == SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID)
|
||||
printf("(shrouded)");
|
||||
printf(":\n");
|
||||
if (dip->friendlyName != NULL) {
|
||||
printf(" Friendly Name: %s\n\n",
|
||||
dip->friendlyName->data);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("unknown bag type(%d): %s\n\n", dip->type,
|
||||
SECOID_FindOIDTagDescription(dip->type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
rv = SECSuccess;
|
||||
}
|
||||
|
||||
loser:
|
||||
|
||||
if (p12dcx) {
|
||||
SEC_PKCS12DecoderFinish(p12dcx);
|
||||
}
|
||||
p12u_DestroyContext(&p12cxt, PR_FALSE);
|
||||
|
||||
if (uniPwitem.data) {
|
||||
SECITEM_ZfreeItem(&uniPwitem, PR_FALSE);
|
||||
}
|
||||
|
||||
if (pwitem) {
|
||||
SECITEM_ZfreeItem(pwitem, PR_TRUE);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void
|
||||
p12u_EnableAllCiphers()
|
||||
{
|
||||
@ -699,13 +836,18 @@ p12u_EnableAllCiphers()
|
||||
}
|
||||
|
||||
static PRUintn
|
||||
P12U_Init(char *dir, char *dbprefix)
|
||||
P12U_Init(char *dir, char *dbprefix, PRBool listonly)
|
||||
{
|
||||
SECStatus rv;
|
||||
PK11_SetPasswordFunc(SECU_GetModulePassword);
|
||||
|
||||
PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
|
||||
rv = NSS_Initialize(dir,dbprefix,dbprefix,"secmod.db",0);
|
||||
if (listonly && NSS_NoDB_Init("") == SECSuccess) {
|
||||
rv = SECSuccess;
|
||||
}
|
||||
else {
|
||||
rv = NSS_Initialize(dir,dbprefix,dbprefix,"secmod.db",0);
|
||||
}
|
||||
if (rv != SECSuccess) {
|
||||
SECU_PrintPRandOSError(progName);
|
||||
exit(-1);
|
||||
@ -726,6 +868,7 @@ enum {
|
||||
opt_Import,
|
||||
opt_SlotPWFile,
|
||||
opt_SlotPW,
|
||||
opt_List,
|
||||
opt_Nickname,
|
||||
opt_Export,
|
||||
opt_P12FilePWFile,
|
||||
@ -741,6 +884,7 @@ static secuCommandFlag pk12util_options[] =
|
||||
{ /* opt_Import */ 'i', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_SlotPWFile */ 'k', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_SlotPW */ 'K', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_List */ 'l', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_Nickname */ 'n', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_Export */ 'o', PR_TRUE, 0, PR_FALSE },
|
||||
{ /* opt_P12FilePWFile */ 'w', PR_TRUE, 0, PR_FALSE },
|
||||
@ -778,8 +922,9 @@ main(int argc, char **argv)
|
||||
|
||||
pk12_debugging = pk12util.options[opt_Debug].activated;
|
||||
|
||||
if (pk12util.options[opt_Import].activated +
|
||||
pk12util.options[opt_Export].activated != 1) {
|
||||
if ((pk12util.options[opt_Import].activated +
|
||||
pk12util.options[opt_Export].activated +
|
||||
pk12util.options[opt_List].activated) != 1) {
|
||||
Usage(progName);
|
||||
}
|
||||
|
||||
@ -789,7 +934,10 @@ main(int argc, char **argv)
|
||||
}
|
||||
|
||||
slotname = SECU_GetOptionArg(&pk12util, opt_TokenName);
|
||||
import_file = SECU_GetOptionArg(&pk12util, opt_Import);
|
||||
|
||||
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) {
|
||||
@ -818,7 +966,8 @@ main(int argc, char **argv)
|
||||
if (pk12util.options[opt_DBPrefix].activated) {
|
||||
dbprefix = pk12util.options[opt_DBPrefix].arg;
|
||||
}
|
||||
P12U_Init(SECU_ConfigDirectory(NULL),dbprefix);
|
||||
P12U_Init(SECU_ConfigDirectory(NULL), dbprefix,
|
||||
pk12util.options[opt_List].activated);
|
||||
|
||||
if (!slotname || PL_strcmp(slotname, "internal") == 0)
|
||||
slot = PK11_GetInternalKeySlot();
|
||||
@ -832,14 +981,16 @@ main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (pk12util.options[opt_Import].activated) {
|
||||
|
||||
if ((ret = P12U_ImportPKCS12Object(import_file, slot, &slotPw,
|
||||
&p12FilePw)) != 0)
|
||||
goto done;
|
||||
P12U_ImportPKCS12Object(import_file, slot, &slotPw,
|
||||
&p12FilePw);
|
||||
|
||||
} else if (pk12util.options[opt_Export].activated) {
|
||||
P12U_ExportPKCS12Object(pk12util.options[opt_Nickname].arg,
|
||||
export_file, slot, &slotPw, &p12FilePw);
|
||||
|
||||
} else if (pk12util.options[opt_List].activated) {
|
||||
P12U_ListPKCS12File(import_file, slot, &slotPw, &p12FilePw);
|
||||
|
||||
} else {
|
||||
Usage(progName);
|
||||
pk12uErrno = PK12UERR_USAGE;
|
||||
|
@ -80,6 +80,7 @@ typedef int (PR_CALLBACK *digestIOFn)(void *arg, unsigned char *buf,
|
||||
typedef struct SEC_PKCS12ExportContextStr SEC_PKCS12ExportContext;
|
||||
typedef struct SEC_PKCS12SafeInfoStr SEC_PKCS12SafeInfo;
|
||||
typedef struct SEC_PKCS12DecoderContextStr SEC_PKCS12DecoderContext;
|
||||
typedef struct SEC_PKCS12DecoderItemStr SEC_PKCS12DecoderItem;
|
||||
|
||||
struct sec_PKCS12PasswordModeInfo {
|
||||
SECItem *password;
|
||||
@ -93,6 +94,14 @@ struct sec_PKCS12PublicKeyModeInfo {
|
||||
int keySize;
|
||||
};
|
||||
|
||||
struct SEC_PKCS12DecoderItemStr {
|
||||
SECItem *der;
|
||||
SECOidTag type;
|
||||
PRBool hasKey;
|
||||
SECItem *friendlyName; /* UTF-8 string */
|
||||
};
|
||||
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
SEC_PKCS12SafeInfo *
|
||||
@ -187,6 +196,13 @@ SEC_PKCS12DecoderImportBags(SEC_PKCS12DecoderContext *p12dcx);
|
||||
CERTCertList *
|
||||
SEC_PKCS12DecoderGetCerts(SEC_PKCS12DecoderContext *p12dcx);
|
||||
|
||||
SECStatus
|
||||
SEC_PKCS12DecoderIterateInit(SEC_PKCS12DecoderContext *p12dcx);
|
||||
|
||||
SECStatus
|
||||
SEC_PKCS12DecoderIterateNext(SEC_PKCS12DecoderContext *p12dcx,
|
||||
const SEC_PKCS12DecoderItem **ipp);
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#endif
|
||||
|
@ -146,6 +146,9 @@ struct SEC_PKCS12DecoderContextStr {
|
||||
PRInt32 allocated; /* total buffer size allocated */
|
||||
PRInt32 currentpos; /* position counter */
|
||||
SECPKCS12TargetTokenCAs tokenCAs;
|
||||
sec_PKCS12SafeBag **keyList;/* used by ...IterateNext() */
|
||||
unsigned int iteration;
|
||||
SEC_PKCS12DecoderItem decitem;
|
||||
};
|
||||
|
||||
|
||||
@ -1233,6 +1236,13 @@ SEC_PKCS12DecoderStart(SECItem *pwitem, PK11SlotInfo *slot, void *wincx,
|
||||
p12dcx->dClose = dClose;
|
||||
p12dcx->dRead = dRead;
|
||||
p12dcx->dArg = dArg;
|
||||
|
||||
p12dcx->keyList = NULL;
|
||||
p12dcx->decitem.type = 0;
|
||||
p12dcx->decitem.der = NULL;
|
||||
p12dcx->decitem.hasKey = PR_FALSE;
|
||||
p12dcx->decitem.friendlyName = NULL;
|
||||
p12dcx->iteration = 0;
|
||||
|
||||
return p12dcx;
|
||||
|
||||
@ -1523,6 +1533,13 @@ SEC_PKCS12DecoderFinish(SEC_PKCS12DecoderContext *p12dcx)
|
||||
SEC_ASN1DecoderFinish(p12dcx->hmacDcx);
|
||||
p12dcx->hmacDcx = NULL;
|
||||
}
|
||||
|
||||
if (p12dcx->decitem.type != 0 && p12dcx->decitem.der != NULL) {
|
||||
SECITEM_FreeItem(p12dcx->decitem.der, PR_TRUE);
|
||||
}
|
||||
if (p12dcx->decitem.friendlyName != NULL) {
|
||||
SECITEM_FreeItem(p12dcx->decitem.friendlyName, PR_TRUE);
|
||||
}
|
||||
|
||||
if(p12dcx->slot) {
|
||||
PK11_FreeSlot(p12dcx->slot);
|
||||
@ -2908,6 +2925,132 @@ SEC_PKCS12DecoderImportBags(SEC_PKCS12DecoderContext *p12dcx)
|
||||
return sec_pkcs12_install_bags(p12dcx->safeBags, p12dcx->wincx);
|
||||
}
|
||||
|
||||
PRBool
|
||||
sec_pkcs12_bagHasKey(SEC_PKCS12DecoderContext *p12dcx, sec_PKCS12SafeBag *bag)
|
||||
{
|
||||
int i;
|
||||
SECItem *keyId;
|
||||
SECItem *certKeyId;
|
||||
|
||||
certKeyId = sec_pkcs12_get_attribute_value(bag, SEC_OID_PKCS9_LOCAL_KEY_ID);
|
||||
if (certKeyId == NULL) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
for (i=0; p12dcx->keyList && p12dcx->keyList[i]; i++) {
|
||||
keyId = sec_pkcs12_get_attribute_value(p12dcx->keyList[i],
|
||||
SEC_OID_PKCS9_LOCAL_KEY_ID);
|
||||
if(!keyId) {
|
||||
continue;
|
||||
}
|
||||
if(SECITEM_CompareItem(certKeyId, keyId) == SECEqual) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
SECItem *
|
||||
sec_pkcs12_get_friendlyName(sec_PKCS12SafeBag *bag)
|
||||
{
|
||||
SECItem *friendlyName;
|
||||
SECItem *tempnm;
|
||||
|
||||
tempnm = sec_pkcs12_get_attribute_value(bag, SEC_OID_PKCS9_FRIENDLY_NAME);
|
||||
friendlyName = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
|
||||
if (friendlyName) {
|
||||
if (!sec_pkcs12_convert_item_to_unicode(NULL, friendlyName,
|
||||
tempnm, PR_TRUE, PR_FALSE, PR_FALSE)) {
|
||||
SECITEM_FreeItem(friendlyName, PR_TRUE);
|
||||
friendlyName = NULL;
|
||||
}
|
||||
}
|
||||
return friendlyName;
|
||||
}
|
||||
|
||||
/* Following two functions provide access to selected portions of the safe bags.
|
||||
* Iteration is implemented per decoder context and may be accessed after
|
||||
* SEC_PKCS12DecoderVerify() returns success.
|
||||
* When ...DecoderIterateNext() returns SUCCESS a decoder item has been returned
|
||||
* where item.type is always set; item.friendlyName is set if it is non-null;
|
||||
* item.der, item.hasKey are set only for SEC_OID_PKCS12_V1_CERT_BAG_ID items.
|
||||
* ...DecoderIterateNext() returns FAILURE when the list is exhausted or when
|
||||
* arguments are invalid; PORT_GetError() is 0 at end-of-list.
|
||||
* Caller has read-only access to decoder items. Any SECItems generated are
|
||||
* owned by the decoder context and are freed by ...DecoderFinish().
|
||||
*/
|
||||
SECStatus
|
||||
SEC_PKCS12DecoderIterateInit(SEC_PKCS12DecoderContext *p12dcx)
|
||||
{
|
||||
if(!p12dcx || p12dcx->error) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
p12dcx->iteration = 0;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
SEC_PKCS12DecoderIterateNext(SEC_PKCS12DecoderContext *p12dcx,
|
||||
const SEC_PKCS12DecoderItem **ipp)
|
||||
{
|
||||
sec_PKCS12SafeBag *bag;
|
||||
SECItem *tempnm;
|
||||
|
||||
if(!p12dcx || p12dcx->error) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (p12dcx->decitem.type != 0 && p12dcx->decitem.der != NULL) {
|
||||
SECITEM_FreeItem(p12dcx->decitem.der, PR_TRUE);
|
||||
}
|
||||
if (p12dcx->decitem.friendlyName != NULL) {
|
||||
SECITEM_FreeItem(p12dcx->decitem.friendlyName, PR_TRUE);
|
||||
}
|
||||
p12dcx->decitem.type = 0;
|
||||
p12dcx->decitem.der = NULL;
|
||||
p12dcx->decitem.friendlyName = NULL;
|
||||
p12dcx->decitem.hasKey = PR_FALSE;
|
||||
*ipp = NULL;
|
||||
if (p12dcx->keyList == NULL) {
|
||||
p12dcx->keyList = sec_pkcs12_get_key_bags(p12dcx->safeBags);
|
||||
}
|
||||
|
||||
|
||||
for (; p12dcx->iteration < p12dcx->safeBagCount; p12dcx->iteration++) {
|
||||
bag = p12dcx->safeBags[p12dcx->iteration];
|
||||
if(bag == NULL || bag->problem) {
|
||||
continue;
|
||||
}
|
||||
p12dcx->decitem.type = SECOID_FindOIDTag(&(bag->safeBagType));
|
||||
switch(p12dcx->decitem.type) {
|
||||
case SEC_OID_PKCS12_V1_CERT_BAG_ID:
|
||||
p12dcx->decitem.der = sec_pkcs12_get_der_cert(bag);
|
||||
p12dcx->decitem.friendlyName = sec_pkcs12_get_friendlyName(bag);
|
||||
p12dcx->decitem.hasKey = sec_pkcs12_bagHasKey(p12dcx, bag);
|
||||
break;
|
||||
case SEC_OID_PKCS12_V1_KEY_BAG_ID:
|
||||
case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
|
||||
p12dcx->decitem.friendlyName = sec_pkcs12_get_friendlyName(bag);
|
||||
break;
|
||||
default:
|
||||
/* return these even though we don't expect them */
|
||||
break;
|
||||
case SEC_OID_UNKNOWN:
|
||||
/* ignore these */
|
||||
continue;
|
||||
}
|
||||
*ipp = &p12dcx->decitem;
|
||||
p12dcx->iteration++;
|
||||
break; /* end for() */
|
||||
}
|
||||
|
||||
PORT_SetError(0); /* end-of-list is SECFailure with no PORT error */
|
||||
return ((p12dcx->decitem.type == 0) ? SECFailure : SECSuccess);
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
sec_pkcs12_decoder_append_bag_to_context(SEC_PKCS12DecoderContext *p12dcx,
|
||||
sec_PKCS12SafeBag *bag)
|
||||
|
@ -260,3 +260,10 @@ SEC_PKCS7EncodeItem;
|
||||
;+ local:
|
||||
;+ *;
|
||||
;+};
|
||||
;+NSS_3.10 { # NSS 3.10 release
|
||||
;+ global:
|
||||
SEC_PKCS12DecoderIterateInit;
|
||||
SEC_PKCS12DecoderIterateNext;
|
||||
;+ local:
|
||||
;+ *;
|
||||
;+};
|
||||
|
@ -118,6 +118,13 @@ tools_p12()
|
||||
ret=$?
|
||||
html_msg $ret 0 "Importing Alice's email cert & key (pk12util -i)"
|
||||
check_tmpfile
|
||||
|
||||
echo "$SCRIPTNAME: Listing Alice's pk12 file -----------------"
|
||||
echo "pk12util -l Alice.p12 -w ${R_PWFILE}"
|
||||
pk12util -l Alice.p12 -w ${R_PWFILE} 2>&1
|
||||
ret=$?
|
||||
html_msg $ret 0 "Listing Alice's pk12 file (pk12util -l)"
|
||||
check_tmpfile
|
||||
}
|
||||
|
||||
############################## tools_sign ##############################
|
||||
|
Loading…
Reference in New Issue
Block a user