static CERTCertificate *load_cert_file(sxc_client_t *sx, const char *file, struct PK11_ctx *ctx) { const char *slot_name = "PEM Token #0"; CK_OBJECT_CLASS obj_class; CK_ATTRIBUTE attrs[/* max count of attributes */ 4]; unsigned attr_cnt = 0; CK_BBOOL cktrue = CK_TRUE; SECMODModule *mod; CERTCertificate *cert = NULL; if(!file || !ctx) { sxi_seterr(sx, SXE_EARG, "NULL argument"); return NULL; } memset(ctx, 0, sizeof(*ctx)); mod = SECMOD_LoadUserModule("library=libnsspem.so name=PEM", NULL, PR_FALSE); if (!mod || !mod->loaded) { if (mod) SECMOD_DestroyModule(mod); sxi_setsyserr(sx, SXE_ECFG, "Failed to load NSS PEM library"); return NULL; } sxi_crypto_check_ver(NULL); ctx->slot = PK11_FindSlotByName(slot_name); if (ctx->slot) { obj_class = CKO_CERTIFICATE; PK11_SETATTRS(attrs, attr_cnt, CKA_CLASS, &obj_class, sizeof(obj_class)); PK11_SETATTRS(attrs, attr_cnt, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); PK11_SETATTRS(attrs, attr_cnt, CKA_LABEL, (unsigned char *)file, strlen(file) + 1); if(CKO_CERTIFICATE == obj_class) { CK_BBOOL *pval = &cktrue; PK11_SETATTRS(attrs, attr_cnt, CKA_TRUST, pval, sizeof(*pval)); } ctx->obj = PK11_CreateGenericObject(ctx->slot, attrs, attr_cnt, PR_FALSE); if (!ctx->obj) { sxi_seterr(sx, SXE_ECFG, "Cannot load certificate from '%s': %s, %s", file, PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT), PR_ErrorToName(PR_GetError())); return NULL; } ctx->list = PK11_ListCertsInSlot(ctx->slot); if (ctx->list) { CERTCertListNode *node = CERT_LIST_HEAD(ctx->list); cert = node ? node->cert : NULL; } } else { sxi_seterr(sx, SXE_ECFG, "Failed to initialize NSS PEM token"); return NULL; } return cert; }
static CERTCertList *get_all_root_certs(void) { PK11SlotInfo *slot = PK11_GetInternalKeySlot(); if (slot == NULL) return NULL; if (PK11_NeedLogin(slot)) { SECStatus rv = PK11_Authenticate(slot, PR_TRUE, lsw_return_nss_password_file_info()); if (rv != SECSuccess) return NULL; } CERTCertList *allcerts = PK11_ListCertsInSlot(slot); if (allcerts == NULL) return NULL; CERTCertList *roots = CERT_NewCertList(); CERTCertListNode *node; for (node = CERT_LIST_HEAD(allcerts); !CERT_LIST_END(node, allcerts); node = CERT_LIST_NEXT(node)) { if (CERT_IsCACert(node->cert, NULL) && node->cert->isRoot) { CERT_DupCertificate(node->cert); CERT_AddCertToListTail(roots, node->cert); } } CERT_DestroyCertList(allcerts); if (roots == NULL || CERT_LIST_EMPTY(roots)) return NULL; return roots; }
/* * objectType is bitwise-OR of all the object types you want to traverse. */ static PRStatus traverseTokenObjects (JNIEnv *env, PK11SlotInfo *slot, TokenObjectTraversalCallback cb, int objectTypes, void *data) { PRStatus status = PR_FAILURE; JSSTraversalStatus travstat = INIT_TRAVSTAT; SECKEYPrivateKeyList* privkList = NULL; SECKEYPublicKeyList* pubkList = NULL; PK11SymKey *symKey = NULL; CERTCertList *certList = NULL; SECStatus secstat; /* * Get all private keys */ if( objectTypes & PRIVKEY ) { SECKEYPrivateKeyListNode *node = NULL; privkList = PK11_ListPrivKeysInSlot(slot, NULL /*nickname*/, NULL /*wincx*/); if( privkList != NULL ) { for( node = PRIVKEY_LIST_HEAD(privkList); ! PRIVKEY_LIST_END(node, privkList); node = PRIVKEY_LIST_NEXT(node) ) { travstat = cb(env, slot, PRIVKEY, (void*) node->key, data); if( travstat.status == PR_FAILURE ) { goto finish; } if( travstat.deleteIt ) { /* Setting "force" to PR_FALSE means that if there is a * matching cert, the key won't be deleted. * If the KeyStore API is being followed, the cert * should have the same nickname as the key. So * both will get deleted when we scan for matching * certs later. */ PK11_DeleteTokenPrivateKey(node->key, PR_FALSE /*force*/); node->key = NULL; PR_REMOVE_LINK(&node->links); /* we don't free node because it is allocated from * the list's arena and will get freed when the list * is freed. */ } if( travstat.stopIterating ) { goto stop_early; } } } } /* * Get all symmetric keys */ if(objectTypes & SYMKEY) { /* this function returns a chained list of symmetric keys */ symKey = PK11_ListFixedKeysInSlot(slot, NULL /*nickname*/, NULL/*wincx*/); while( symKey != NULL ) { PK11SymKey *deadKey; travstat = cb(env, slot, SYMKEY, (void*) symKey, data); if( travstat.status != PR_SUCCESS ) { goto finish; } if( travstat.deleteIt ) { /* this just deletes the PKCS #11 object. The data structure * is NOT deleted. */ PK11_DeleteTokenSymKey(symKey); } if( travstat.stopIterating ) { goto stop_early; } deadKey = symKey; symKey = PK11_GetNextSymKey(symKey); PK11_FreeSymKey(deadKey); } } /* * get all public keys */ if( objectTypes & PUBKEY ) { SECKEYPublicKeyListNode *node = NULL; pubkList = PK11_ListPublicKeysInSlot(slot, NULL /*nickname*/); if( pubkList != NULL ) { for( node = PUBKEY_LIST_HEAD(pubkList); ! PUBKEY_LIST_END(node, pubkList); node = PUBKEY_LIST_NEXT(node) ) { if( node->key == NULL ) { /* workaround NSS bug 130699: PK11_ListPublicKeysInSlot * returns NULL if slot contains token symmetric key */ continue; } travstat = cb(env, slot, PUBKEY, (void*) node->key, data); if( travstat.status != PR_SUCCESS ) { goto finish; } if( travstat.deleteIt ) { /* XXX!!! * Workaround for 125408: PK11_DeleteTokenPublic key asserts * Don't delete the public key. * PK11_DeleteTokenPublicKey(node->key); * node->key = NULL; * PR_REMOVE_LINK(&node->links); */ /* node is allocated from the list's arena, it will get * freed with the list */ } if( travstat.stopIterating ) { goto stop_early; } } /* * XXX!!! * Destroy the list before we move on. Why bother, since we'll * do it anyway in the finish block? Because of bug 125408. * If we delete the cert and private key while traversing certs, * we'll delete the public key too, and then we'll crash when * we free the same public key while destroying the list. */ SECKEY_DestroyPublicKeyList(pubkList); pubkList = NULL; } } /* * Get all certs */ if( objectTypes & CERT ) { CERTCertListNode *node = NULL; certList = PK11_ListCertsInSlot(slot); if( certList == NULL ) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to list certificates on token"); goto finish; } for( node = CERT_LIST_HEAD(certList); ! CERT_LIST_END(node, certList); node = CERT_LIST_NEXT(node) ) { travstat = cb(env, slot, CERT, (void*) node->cert, data); if( travstat.status != PR_SUCCESS ) { goto finish; } if( travstat.deleteIt ) { /* * Since, in a KeyStore, certs and private keys go together, * remove the private key too, if there is one. * * The hack here is that PK11_DeleteTokenCertAndKey will * not delete the cert if there is no matching private key. * We want to the cert to be deleted even if the key isn't * there. So we only call that function if we're sure the * key is there. Otherwise we delete the cert directly. */ SECKEYPrivateKey *privKey = PK11_FindKeyByAnyCert(node->cert, NULL /*wincx*/); PRBool keyPresent = (privKey != NULL); SECKEY_DestroyPrivateKey(privKey); if( keyPresent ) { PK11_DeleteTokenCertAndKey(node->cert, NULL /*wincx*/); } else { SEC_DeletePermCertificate(node->cert); } PR_REMOVE_LINK(&node->links); /* node is allocated from the list's arena, it will get freed * with the list */ } if( travstat.stopIterating ) { goto stop_early; } } } stop_early: status = PR_SUCCESS; finish: if( privkList != NULL ) { SECKEY_DestroyPrivateKeyList(privkList); } if( pubkList != NULL ) { SECKEY_DestroyPublicKeyList(pubkList); } while( symKey != NULL ) { PK11SymKey *deadKey; deadKey = symKey; symKey = PK11_GetNextSymKey(symKey); PK11_FreeSymKey(deadKey); } if( certList != NULL ) { CERT_DestroyCertList(certList); } return status; }