/* 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 #include #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("\n"); } else if (len == 0) { printf("\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; }