[Bug 291384] certutil -K behavior doesn't match usage. r=rrelyea

This commit is contained in:
nelson%bolyard.com 2008-02-07 19:05:16 +00:00
Родитель 94cd3fb8f5
Коммит bcc5a811f7
1 изменённых файлов: 127 добавлений и 33 удалений

Просмотреть файл

@ -539,7 +539,7 @@ listCerts(CERTCertDBHandle *handle, char *name, PK11SlotInfo *slot,
} }
static SECStatus static SECStatus
ListCerts(CERTCertDBHandle *handle, char *name, PK11SlotInfo *slot, ListCerts(CERTCertDBHandle *handle, char *nickname, PK11SlotInfo *slot,
PRBool raw, PRBool ascii, PRFileDesc *outfile, secuPWData *pwdata) PRBool raw, PRBool ascii, PRFileDesc *outfile, secuPWData *pwdata)
{ {
SECStatus rv; SECStatus rv;
@ -557,7 +557,7 @@ ListCerts(CERTCertDBHandle *handle, char *name, PK11SlotInfo *slot,
CERT_DestroyCertList(list); CERT_DestroyCertList(list);
return SECSuccess; return SECSuccess;
} else { } else {
rv = listCerts(handle,name,slot,raw,ascii,outfile,pwdata); rv = listCerts(handle,nickname,slot,raw,ascii,outfile,pwdata);
} }
return rv; return rv;
} }
@ -697,67 +697,158 @@ ValidateCert(CERTCertDBHandle *handle, char *name, char *date,
return (rv); return (rv);
} }
/* callback for listing certs through pkcs11 */ static PRBool
static SECStatus ItemIsPrintableASCII(const SECItem * item)
secu_PrintKey(FILE *out, int count, SECKEYPrivateKey *key)
{ {
char *name; unsigned char *src = item->data;
unsigned int len = item->len;
name = PK11_GetPrivateKeyNickname(key); while (len-- > 0) {
if (name == NULL) { unsigned char uc = *src++;
/* should look up associated cert */ if (uc < 0x20 || uc > 0x7e)
name = PORT_Strdup("< orphaned >"); return PR_FALSE;
} }
fprintf(out, "<%d> %s\n", count, name); return PR_TRUE;
PORT_Free(name); }
/* Caller ensures that dst is at least item->len*2+1 bytes long */
static void
SECItemToHex(const SECItem * item, char * dst)
{
if (dst && item && item->data) {
unsigned char * src = item->data;
unsigned int len = item->len;
for (; len > 0; --len, dst += 2) {
sprintf(dst, "%02x", *src++);
}
*dst = '\0';
}
}
static const char * const keyTypeName[] = {
"null", "rsa", "dsa", "fortezza", "dh", "kea", "ec" };
#define MAX_CKA_ID_BIN_LEN 20
#define MAX_CKA_ID_STR_LEN 40
/* print key number, key ID (in hex or ASCII), key label (nickname) */
static SECStatus
PrintKey(PRFileDesc *out, const char *nickName, int count,
SECKEYPrivateKey *key, void *pwarg)
{
SECItem * ckaID;
char ckaIDbuf[MAX_CKA_ID_STR_LEN + 4];
pwarg = NULL;
ckaID = PK11_GetLowLevelKeyIDForPrivateKey(key);
if (!ckaID) {
strcpy(ckaIDbuf, "(no CKA_ID)");
} else if (ItemIsPrintableASCII(ckaID)) {
int len = PR_MIN(MAX_CKA_ID_STR_LEN, ckaID->len);
ckaIDbuf[0] = '"';
memcpy(ckaIDbuf + 1, ckaID->data, len);
ckaIDbuf[1 + len] = '"';
ckaIDbuf[2 + len] = '\0';
} else {
/* print ckaid in hex */
SECItem idItem = *ckaID;
if (idItem.len > MAX_CKA_ID_BIN_LEN)
idItem.len = MAX_CKA_ID_BIN_LEN;
SECItemToHex(&idItem, ckaIDbuf);
}
PR_fprintf(out, "<%2d> %-8.8s %-42.42s %s\n", count,
keyTypeName[key->keyType], ckaIDbuf, nickName);
SECITEM_ZfreeItem(ckaID, PR_TRUE);
return SECSuccess; return SECSuccess;
} }
static SECStatus static SECStatus
listKeys(PK11SlotInfo *slot, KeyType keyType, void *pwarg) ListKeysInSlot(PK11SlotInfo *slot, const char *nickName, KeyType keyType,
void *pwarg)
{ {
SECKEYPrivateKeyList *list; SECKEYPrivateKeyList *list;
SECKEYPrivateKeyListNode *node; SECKEYPrivateKeyListNode *node;
int count; int count = 0;
if (PK11_NeedLogin(slot)) if (PK11_NeedLogin(slot))
PK11_Authenticate(slot, PR_TRUE, pwarg); PK11_Authenticate(slot, PR_TRUE, pwarg);
list = PK11_ListPrivateKeysInSlot(slot); if (nickName && nickName[0])
list = PK11_ListPrivKeysInSlot(slot, (char *)nickName, pwarg);
else
list = PK11_ListPrivateKeysInSlot(slot);
if (list == NULL) { if (list == NULL) {
SECU_PrintError(progName, "problem listing keys"); SECU_PrintError(progName, "problem listing keys");
return SECFailure; return SECFailure;
} }
for (count=0, node=PRIVKEY_LIST_HEAD(list) ; !PRIVKEY_LIST_END(node,list); for (node=PRIVKEY_LIST_HEAD(list);
node= PRIVKEY_LIST_NEXT(node),count++) { !PRIVKEY_LIST_END(node,list);
secu_PrintKey(stdout, count, node->key); node=PRIVKEY_LIST_NEXT(node)) {
char * keyName;
static const char orphan[] = { "(orphan)" };
if (keyType != nullKey && keyType != node->key->keyType)
continue;
keyName = PK11_GetPrivateKeyNickname(node->key);
if (!keyName || !keyName[0]) {
/* Try extra hard to find nicknames for keys that lack them. */
CERTCertificate * cert;
PORT_Free((void *)keyName);
keyName = NULL;
cert = PK11_GetCertFromPrivateKey(node->key);
if (cert) {
if (cert->nickname && !cert->nickname[0]) {
keyName = PORT_Strdup(cert->nickname);
} else if (cert->emailAddr && cert->emailAddr[0]) {
keyName = PORT_Strdup(cert->emailAddr);
}
CERT_DestroyCertificate(cert);
}
}
if (nickName) {
if (!keyName || PL_strcmp(keyName,nickName)) {
/* PKCS#11 module returned unwanted keys */
PORT_Free((void *)keyName);
continue;
}
}
if (!keyName)
keyName = (char *)orphan;
PrintKey(PR_STDOUT, keyName, count, node->key, pwarg);
if (keyName != (char *)orphan)
PORT_Free((void *)keyName);
count++;
} }
SECKEY_DestroyPrivateKeyList(list); SECKEY_DestroyPrivateKeyList(list);
if (count == 0) { if (count == 0) {
fprintf(stderr, "%s: no keys found\n", progName); PR_fprintf(PR_STDOUT, "%s: no keys found\n", progName);
return SECFailure; return SECFailure;
} }
return SECSuccess; return SECSuccess;
} }
static SECStatus static SECStatus
ListKeys(PK11SlotInfo *slot, char *keyname, int index, ListKeys(PK11SlotInfo *slot, const char *nickName, int index,
KeyType keyType, PRBool dopriv, secuPWData *pwdata) KeyType keyType, PRBool dopriv, secuPWData *pwdata)
{ {
SECStatus rv = SECSuccess; SECStatus rv = SECFailure;
if (slot == NULL) { if (slot == NULL) {
PK11SlotList *list; PK11SlotList *list;
PK11SlotListElement *le; PK11SlotListElement *le;
list= PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_FALSE,pwdata); list= PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_FALSE,pwdata);
if (list) for (le = list->head; le; le = le->next) { if (list) {
rv = listKeys(le->slot,keyType,pwdata); for (le = list->head; le; le = le->next) {
rv &= ListKeysInSlot(le->slot,nickName,keyType,pwdata);
}
} }
} else { } else {
rv = listKeys(slot,keyType,pwdata); rv = ListKeysInSlot(slot,nickName,keyType,pwdata);
} }
return rv; return rv;
} }
@ -1019,18 +1110,19 @@ static void LongUsage(char *progName)
" -X"); " -X");
FPS "\n"); FPS "\n");
FPS "%-15s List all keys\n", /*, or print out a single named key\n",*/ FPS "%-15s List all private keys\n",
"-K"); "-K");
FPS "%-20s Name of token in which to look for keys (default is internal," FPS "%-20s Name of token to search (\"all\" for all tokens)\n",
" use \"all\" to list keys on all tokens)\n",
" -h token-name "); " -h token-name ");
FPS "%-20s Key type (\"all\" (default), \"dsa\","
#ifdef NSS_ENABLE_ECC #ifdef NSS_ENABLE_ECC
FPS "%-20s Type of key pair to list (\"all\", \"dsa\", \"ec\", \"rsa\" (default))\n", " \"ec\","
" -k key-type");
#else
FPS "%-20s Type of key pair to list (\"all\", \"dsa\", \"rsa\" (default))\n",
" -k key-type");
#endif #endif
" \"rsa\")\n",
" -k key-type");
FPS "%-20s The nickname of the key or associated certificate\n",
" -n name");
FPS "%-20s Specify the password file\n", FPS "%-20s Specify the password file\n",
" -f password-file"); " -f password-file");
FPS "%-20s Key database directory (default is ~/.netscape)\n", FPS "%-20s Key database directory (default is ~/.netscape)\n",
@ -1737,6 +1829,8 @@ certutil_main(int argc, char **argv, PRBool initialize)
/* use an existing private/public key pair */ /* use an existing private/public key pair */
keysource = arg; keysource = arg;
} }
} else if (certutil.commands[cmd_ListKeys].activated) {
keytype = nullKey;
} }
/* -m serial number */ /* -m serial number */