From 5ba48df3024a775d774a31ba182f9e2a9b7b0839 Mon Sep 17 00:00:00 2001 From: Nalin Dahyabhai Date: Mon, 1 Nov 2010 14:34:54 -0400 Subject: [PATCH 088/150] - load CA certs from slots so that we can tell clients which ones we trust - don't bother tracking keys or "other" certs -- so long as they're in a slot, the library will find them --- src/plugins/preauth/pkinit/pkinit_crypto_nss.c | 112 +++++++++++++++++------- 1 files changed, 82 insertions(+), 30 deletions(-) diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c index f401de8..0e92bcd 100644 --- a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c +++ b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c @@ -234,8 +234,7 @@ struct _pkinit_identity_crypto_context { SECMODModule *pem_module; SECMODModule **id_modules; PK11SlotInfo **id_userdbs; - CERTCertList *id_certs, *ca_certs, *other_certs; - SECKEYPrivateKeyList *id_keys; + CERTCertList *id_certs, *ca_certs; CERTCertificate *id_cert; struct { krb5_context context; @@ -622,13 +621,8 @@ pkinit_init_identity_crypto(pkinit_identity_crypto_context *id_cryptoctx) } id->pool = pool; id->id_certs = CERT_NewCertList(); - id->id_keys = SECKEY_NewPrivateKeyList(); id->ca_certs = CERT_NewCertList(); - id->other_certs = CERT_NewCertList(); - if ((id->id_certs != NULL) && - (id->id_keys != NULL) && - (id->ca_certs != NULL) && - (id->other_certs != NULL)) { + if ((id->id_certs != NULL) && (id->ca_certs != NULL)) { id->pem_module = SECMOD_LoadUserModule("library=libnsspem.so", NULL, PR_FALSE); if (id->pem_module == NULL) { @@ -640,15 +634,9 @@ pkinit_init_identity_crypto(pkinit_identity_crypto_context *id_cryptoctx) *id_cryptoctx = id; return 0; } - if (id->other_certs != NULL) { - CERT_DestroyCertList(id->other_certs); - } if (id->ca_certs != NULL) { CERT_DestroyCertList(id->ca_certs); } - if (id->id_keys != NULL) { - SECKEY_DestroyPrivateKeyList(id->id_keys); - } if (id->id_certs != NULL) { CERT_DestroyCertList(id->id_certs); } @@ -659,9 +647,7 @@ pkinit_init_identity_crypto(pkinit_identity_crypto_context *id_cryptoctx) void pkinit_fini_identity_crypto(pkinit_identity_crypto_context id_cryptoctx) { - CERT_DestroyCertList(id_cryptoctx->other_certs); CERT_DestroyCertList(id_cryptoctx->ca_certs); - SECKEY_DestroyPrivateKeyList(id_cryptoctx->id_keys); CERT_DestroyCertList(id_cryptoctx->id_certs); if (id_cryptoctx->id_userdbs != NULL) { int i; @@ -1757,6 +1743,78 @@ cert_maybe_add_to_list(CERTCertList *list, CERTCertificate *cert) return CERT_AddCertToListTail(list, cert); } +/* Load CA certificates from the slot. */ +static SECStatus +cert_load_ca_certs_from_slot(krb5_context context, + pkinit_identity_crypto_context id, + PK11SlotInfo *slot) +{ + CERTCertificate *cert; + CERTCertList *list; + CERTCertListNode *node; + CERTCertTrust trust; + SECStatus status; + + /* Log in if the slot requires it. */ + if (!PK11_IsLoggedIn(slot, crypto_pwcb_prep(id, context)) && + PK11_NeedLogin(slot)) { + pkiDebug("%s: logging in to token \"%s\"\n", + __FUNCTION__, PK11_GetTokenName(slot)); + if (PK11_Authenticate(slot, PR_TRUE, + crypto_pwcb_prep(id, + context)) != SECSuccess) { + pkiDebug("%s: error logging into \"%s\", skipping\n", + __FUNCTION__, PK11_GetTokenName(slot)); + return SECFailure; + } + } + /* Get the list of certs from the slot. */ + list = PK11_ListCertsInSlot(slot); + if (list == NULL) { + pkiDebug("%s: nothing found in token \"%s\"\n", + __FUNCTION__, PK11_GetTokenName(slot)); + return SECSuccess; + } + if (CERT_LIST_EMPTY(list)) { + CERT_DestroyCertList(list); + pkiDebug("%s: nothing found in token \"%s\"\n", + __FUNCTION__, PK11_GetTokenName(slot)); + return SECSuccess; + } + /* Walk the list of certs, and for each one that's a CA, add + * it to our CA cert list. */ + status = SECSuccess; + for (node = CERT_LIST_HEAD(list); + (node != NULL) && + (node->cert != NULL) && + !CERT_LIST_END(node, list); + node = CERT_LIST_NEXT(node)) { +#if 0 + /* Skip it if it's not a root. */ + if (!node->cert->isRoot) { + continue; + } +#endif + /* Skip it if we don't trust it to issue certificates. */ + if (CERT_GetCertTrust(node->cert, &trust) != SECSuccess) { + continue; + } + if ((SEC_GET_TRUST_FLAGS(&trust, trustSSL) & + (CERTDB_TRUSTED_CA | CERTDB_TRUSTED_CLIENT_CA)) == 0) { + continue; + } + /* DestroyCertList frees all of the certs in the list, + * so we need to create a copy that it can own. */ + cert = CERT_DupCertificate(node->cert); + /* Add it to the list. */ + if (cert_maybe_add_to_list(id->ca_certs, cert) != SECSuccess) { + status = SECFailure; + } + } + CERT_DestroyCertList(list); + return status; +} + /* Load certificates for which we have private keys from the slot. */ static int cert_load_certs_with_keys_from_slot(krb5_context context, @@ -1798,7 +1856,7 @@ cert_load_certs_with_keys_from_slot(krb5_context context, /* Walk the list of certs, and for each one for which we can * find the matching private key, add it and the keys to the * lists. */ - status = SECSuccess; + status = 0; for (cnode = CERT_LIST_HEAD(clist); (cnode != NULL) && (cnode->cert != NULL) && @@ -1827,10 +1885,8 @@ cert_load_certs_with_keys_from_slot(krb5_context context, if (cert_maybe_add_to_list(id->id_certs, cert) != SECSuccess) { status = ENOMEM; } - if (SECKEY_AddPrivateKeyToListTail(id->id_keys, - key) != SECSuccess) { - status = ENOMEM; - } + /* We don't need this reference to the key. */ + SECKEY_DestroyPrivateKey(key); } CERT_DestroyCertList(clist); return status; @@ -2112,17 +2168,12 @@ crypto_load_files(krb5_context context, if (cert_maybe_add_to_list(id_cryptoctx->id_certs, cert) != SECSuccess) { status = SECFailure; } - } else + } if (cert_mark_trusted) { /* Add to the CA list. */ if (cert_maybe_add_to_list(id_cryptoctx->ca_certs, cert) != SECSuccess) { status = SECFailure; } - } else { - /* Add to the "other" list. */ - if (cert_maybe_add_to_list(id_cryptoctx->other_certs, cert) != SECSuccess) { - status = SECFailure; - } } } } @@ -2280,6 +2331,9 @@ crypto_load_certdb(krb5_context context, id_userdbs[i] = NULL; id_cryptoctx->id_userdbs = id_userdbs; + /* Load the CAs from the database. */ + cert_load_ca_certs_from_slot(context, id_cryptoctx, userdb); + /* Load the keys from the database. */ return cert_load_certs_with_keys_from_slot(context, id_cryptoctx, userdb); } @@ -2364,7 +2418,6 @@ crypto_load_certs(krb5_context context, if (status != SECSuccess) { pkiDebug("%s: error loading PKCS12 bundle \"%s\"\n", __FUNCTION__, idopts->cert_filename); - return 0; /* FIXME */ return ENOMEM; } return 0; @@ -2733,7 +2786,7 @@ crypto_load_cas_and_crls(krb5_context context, load_crl = PR_FALSE; break; case CATYPE_CRLS: - /* Load CRLs. */ + /* FIXME: Load CRLs. */ cert_self = PR_FALSE; cert_mark_trusted = PR_FALSE; load_crl = PR_TRUE; @@ -2790,7 +2843,6 @@ crypto_load_cas_and_crls(krb5_context context, case IDTYPE_PKCS12: pkiDebug("%s: skipping CA PKCS12 bundle \"%s\"\n", __FUNCTION__, id); - return 0; /* FIXME */ return ENOSYS; default: return EINVAL; -- 1.7.6.4