Exemplo n.º 1
0
Arquivo: nss.c Projeto: flashfoxter/sx
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;
}
Exemplo n.º 2
0
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;
}