| /* 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/. */ |
| |
| #ifdef _CRTDBG_MAP_ALLOC |
| #include <stdlib.h> |
| #include <crtdbg.h> |
| #endif |
| |
| #include "nspr.h" |
| #include "secutil.h" |
| #include "pk11func.h" |
| #include "nss.h" |
| #include "secport.h" |
| #include "secpkcs5.h" |
| #include "sechash.h" |
| #include "certdb.h" |
| #include "secmod.h" |
| |
| static char *progName; |
| PRBool debug = PR_FALSE; |
| |
| #define ERR_USAGE 2 |
| #define ERR_PK11GETSLOT 13 |
| |
| static void |
| Usage() |
| { |
| #define FPS PR_fprintf(PR_STDERR, |
| FPS "Usage: %s [-d certdir] [-P dbprefix] [-h tokenname]\n", |
| progName); |
| FPS "\t\t [-k slotpwfile | -K slotpw] [-v]\n"); |
| |
| exit(ERR_USAGE); |
| } |
| |
| typedef enum { |
| tagULong, |
| tagVersion, |
| tagUtf8 |
| } tagType; |
| |
| typedef struct { |
| const char *attributeName; |
| tagType attributeStorageType; |
| } attributeTag; |
| |
| enum { |
| opt_CertDir = 0, |
| opt_TokenName, |
| opt_SlotPWFile, |
| opt_SlotPW, |
| opt_DBPrefix, |
| opt_Debug |
| }; |
| |
| static secuCommandFlag validation_options[] = |
| { |
| { /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE }, |
| { /* opt_TokenName */ 'h', PR_TRUE, 0, PR_FALSE }, |
| { /* opt_SlotPWFile */ 'k', PR_TRUE, 0, PR_FALSE }, |
| { /* opt_SlotPW */ 'K', PR_TRUE, 0, PR_FALSE }, |
| { /* opt_DBPrefix */ 'P', PR_TRUE, 0, PR_FALSE }, |
| { /* opt_Debug */ 'v', PR_FALSE, 0, PR_FALSE } |
| }; |
| |
| void |
| dump_Raw(char *label, CK_ATTRIBUTE *attr) |
| { |
| int i; |
| unsigned char *value = (unsigned char *)attr->pValue; |
| printf("0x"); |
| for (i = 0; i < attr->ulValueLen; i++) { |
| printf("%02x", value[i]); |
| } |
| printf("<%s>\n", label); |
| } |
| |
| SECStatus |
| dump_validations(CK_OBJECT_CLASS objc, CK_ATTRIBUTE *template, int count, |
| attributeTag *tags, PK11SlotInfo *slot) |
| { |
| PK11GenericObject *objs, *obj; |
| |
| objs = PK11_FindGenericObjects(slot, objc); |
| |
| for (obj = objs; obj != NULL; obj = PK11_GetNextGenericObject(obj)) { |
| int i; |
| printf("Validation Object:\n"); |
| PK11_ReadRawAttributes(NULL, PK11_TypeGeneric, obj, template, count); |
| for (i = 0; i < count; i++) { |
| CK_ULONG ulong; |
| CK_VERSION version; |
| int len = template[i].ulValueLen; |
| printf(" %s: ", tags[i].attributeName); |
| if (len < 0) { |
| printf("<failed>\n"); |
| } else if (len == 0) { |
| printf("<empty>\n"); |
| } else |
| switch (tags[i].attributeStorageType) { |
| case tagULong: |
| if (len != sizeof(CK_ULONG)) { |
| dump_Raw("bad ulong", &template[i]); |
| break; |
| } |
| ulong = *(CK_ULONG *)template[i].pValue; |
| printf("%ld\n", ulong); |
| break; |
| case tagVersion: |
| if (len != sizeof(CK_VERSION)) { |
| dump_Raw("bad version", &template[i]); |
| break; |
| } |
| version = *(CK_VERSION *)template[i].pValue; |
| printf("%d.%d\n", version.major, version.minor); |
| break; |
| case tagUtf8: |
| printf("%.*s\n", len, (char *)template[i].pValue); |
| break; |
| default: |
| dump_Raw("unknown tag", &template[i]); |
| break; |
| } |
| PORT_Free(template[i].pValue); |
| template[i].pValue = NULL; |
| template[i].ulValueLen = 0; |
| } |
| } |
| PK11_DestroyGenericObjects(objs); |
| return SECSuccess; |
| } |
| |
| int |
| main(int argc, char **argv) |
| { |
| secuPWData slotPw = { PW_NONE, NULL }; |
| secuPWData p12FilePw = { PW_NONE, NULL }; |
| PK11SlotInfo *slot = NULL; |
| char *slotname = NULL; |
| char *dbprefix = ""; |
| char *nssdir = NULL; |
| SECStatus rv; |
| secuCommand validation; |
| int local_errno = 0; |
| |
| CK_ATTRIBUTE validation_template[] = { |
| { CKA_NSS_VALIDATION_TYPE, NULL, 0 }, |
| { CKA_NSS_VALIDATION_VERSION, NULL, 0 }, |
| { CKA_NSS_VALIDATION_LEVEL, NULL, 0 }, |
| { CKA_NSS_VALIDATION_MODULE_ID, NULL, 0 } |
| }; |
| attributeTag validation_tags[] = { |
| { "Validation Type", tagULong }, |
| { "Validation Version", tagVersion }, |
| { "Validation Level", tagULong }, |
| { "Validation Module ID", tagUtf8 }, |
| }; |
| |
| #ifdef _CRTDBG_MAP_ALLOC |
| _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); |
| #endif |
| |
| validation.numCommands = 0; |
| validation.commands = 0; |
| validation.numOptions = PR_ARRAY_SIZE(validation_options); |
| validation.options = validation_options; |
| |
| progName = strrchr(argv[0], '/'); |
| progName = progName ? progName + 1 : argv[0]; |
| |
| rv = SECU_ParseCommandLine(argc, argv, progName, &validation); |
| |
| if (rv != SECSuccess) |
| Usage(); |
| |
| debug = validation.options[opt_Debug].activated; |
| |
| slotname = SECU_GetOptionArg(&validation, opt_TokenName); |
| |
| if (validation.options[opt_SlotPWFile].activated) { |
| slotPw.source = PW_FROMFILE; |
| slotPw.data = PORT_Strdup(validation.options[opt_SlotPWFile].arg); |
| } |
| |
| if (validation.options[opt_SlotPW].activated) { |
| slotPw.source = PW_PLAINTEXT; |
| slotPw.data = PORT_Strdup(validation.options[opt_SlotPW].arg); |
| } |
| |
| if (validation.options[opt_CertDir].activated) { |
| nssdir = validation.options[opt_CertDir].arg; |
| } |
| if (validation.options[opt_DBPrefix].activated) { |
| dbprefix = validation.options[opt_DBPrefix].arg; |
| } |
| |
| PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); |
| if (nssdir == NULL && NSS_NoDB_Init("") == SECSuccess) { |
| rv = SECSuccess; |
| /* if the system isn't already in FIPS mode, we need |
| * to switch to FIPS mode */ |
| if (!PK11_IsFIPS()) { |
| /* flip to FIPS mode */ |
| SECMODModule *module = SECMOD_GetInternalModule(); |
| rv = SECMOD_DeleteInternalModule(module->commonName); |
| } |
| } else if (nssdir != NULL) { |
| rv = NSS_Initialize(nssdir, dbprefix, dbprefix, "secmod.db", 0); |
| } |
| if (rv != SECSuccess) { |
| SECU_PrintPRandOSError(progName); |
| local_errno = -1; |
| goto done; |
| } |
| |
| if (!slotname || PL_strcmp(slotname, "internal") == 0) |
| slot = PK11_GetInternalKeySlot(); |
| else |
| slot = PK11_FindSlotByName(slotname); |
| |
| if (!slot) { |
| SECU_PrintError(progName, "Invalid slot \"%s\"", |
| slotname ? "internal" : slotname); |
| local_errno = ERR_PK11GETSLOT; |
| goto done; |
| } |
| |
| rv = dump_validations(CKO_NSS_VALIDATION, |
| validation_template, |
| PR_ARRAY_SIZE(validation_template), |
| validation_tags, |
| slot); |
| |
| done: |
| if (slotPw.data != NULL) |
| PORT_ZFree(slotPw.data, PL_strlen(slotPw.data)); |
| if (p12FilePw.data != NULL) |
| PORT_ZFree(p12FilePw.data, PL_strlen(p12FilePw.data)); |
| if (slotname) { |
| PORT_Free(slotname); |
| } |
| if (slot) |
| PK11_FreeSlot(slot); |
| if (NSS_Shutdown() != SECSuccess) { |
| local_errno = 1; |
| } |
| PL_ArenaFinish(); |
| PR_Cleanup(); |
| return local_errno; |
| } |