From 42f8ca78a401e1104617dd28ee64865b8e2469a8 Mon Sep 17 00:00:00 2001 From: Nalin Dahyabhai Date: Thu, 28 Oct 2010 00:49:51 -0400 Subject: [PATCH 079/150] - use a helper to load keys from a certdb or a pkcs11 module's slot --- src/plugins/preauth/pkinit/pkinit_crypto_nss.c | 304 +++++++----------------- 1 files changed, 87 insertions(+), 217 deletions(-) diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c index 69934dc..ff0068f 100644 --- a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c +++ b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c @@ -76,8 +76,6 @@ static krb5_error_code cert_retrieve_cert_sans(krb5_context context, krb5_principal **pkinit_sans, krb5_principal **upn_sans, unsigned char ***kdc_hostname); -static int cert_load_default_identity(krb5_context context, - pkinit_identity_crypto_context id); /* Protocol elements. */ @@ -233,7 +231,6 @@ struct _pkinit_req_crypto_context { struct _pkinit_identity_crypto_context { PLArenaPool *pool; - PRBool default_loaded; SECMODModule *pem_module; SECMODModule **id_modules; PK11SlotInfo **id_slots; @@ -1737,6 +1734,84 @@ create_krb5_trustedCertifiers(krb5_context context, return 0; } +/* Load certificates for which we have private keys from the slot. */ +static int +cert_load_certs_with_keys_from_slot(krb5_context context, + pkinit_identity_crypto_context id, + PK11SlotInfo *slot) +{ + CERTCertificate *cert; + CERTCertList *clist; + CERTCertListNode *cnode; + SECKEYPrivateKey *key; + int status; + /* Skip over slots we've already used. */ + if (!PK11_IsLoggedIn(slot, crypto_pwcb_prep(id, context)) && + PK11_NeedLogin(slot)) { + pkiDebug("%s: skipping 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 ENOMEM; + } + } + /* Get the list of certs from the slot. */ + clist = PK11_ListCertsInSlot(slot); + if (clist == NULL) { + pkiDebug("%s: nothing found in token \"%s\"\n", + __FUNCTION__, PK11_GetTokenName(slot)); + return 0; + } + if (CERT_LIST_EMPTY(clist)) { + CERT_DestroyCertList(clist); + pkiDebug("%s: nothing found in token \"%s\"\n", + __FUNCTION__, PK11_GetTokenName(slot)); + return 0; + } + /* 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; + for (cnode = CERT_LIST_HEAD(clist); + (cnode != NULL) && + (cnode->cert != NULL) && + !CERT_LIST_END(cnode, clist); + cnode = CERT_LIST_NEXT(cnode)) { + pkiDebug("%s: checking for key for \"%s\"\n", + __FUNCTION__, + cnode->cert->nickname ? + cnode->cert->nickname : "(no name)"); + key = PK11_FindPrivateKeyFromCert(slot, cnode->cert, + crypto_pwcb_prep(id, context)); + if (key == NULL) { + pkiDebug("%s: no key for \"%s\"\n", + __FUNCTION__, + cnode->cert->nickname ? + cnode->cert->nickname : "(no name)"); + continue; + } + pkiDebug("%s: using \"%s\" and its matching key\n", + __FUNCTION__, + cnode->cert->nickname ? + cnode->cert->nickname : "(no name)"); + /* DestroyCertList frees all of the certs in the list, + * so we need to create a copy that it can own. */ + cert = CERT_DupCertificate(cnode->cert); + if (CERT_AddCertToListTail(id->id_certs, cert) != SECSuccess) { + status = ENOMEM; + } + if (SECKEY_AddPrivateKeyToListTail(id->id_keys, + key) != SECSuccess) { + status = ENOMEM; + } + } + CERT_DestroyCertList(clist); + return status; +} + static SECStatus crypto_load_pkcs11(krb5_context context, pkinit_plg_crypto_context plg_cryptoctx, @@ -1746,10 +1821,8 @@ crypto_load_pkcs11(krb5_context context, { SECMODModule **id_modules, *module; PK11SlotInfo *slot; - CERTCertificate *cert; - CERTCertList *certs; - CERTCertListNode *node; char *spec; + SECStatus status; int i, j; if (name == NULL) { @@ -1805,39 +1878,17 @@ crypto_load_pkcs11(krb5_context context, id_cryptoctx->id_modules = id_modules; /* Walk the list of slots in the module. */ + status = SECFailure; for (i = module->slotCount; (slot = module->slots[i]) != NULL; i++) { - /* If we have to log in to the token, give it a shot. */ - if (!PK11_IsLoggedIn(slot, - crypto_pwcb_prep(id_cryptoctx, context)) && - PK11_NeedLogin(slot) && - (PK11_Authenticate(slot, PR_TRUE, - crypto_pwcb_prep(id_cryptoctx, - context)) != SECSuccess)) { - pkiDebug("%s: error logging into \"%s\":\"%s\", " - "skipping\n", - __FUNCTION__, spec, PK11_GetTokenName(slot)); - continue; - } - certs = PK11_ListCertsInSlot(slot); - - /* Walk the list of certs in the slot. */ - for (node = CERT_LIST_HEAD(certs); - (node != NULL) && (node->cert != NULL) && - !CERT_LIST_END(node, certs); - node = CERT_LIST_NEXT(node)) { - /* Add the cert to our candidate cert list. */ - cert = CERT_DupCertificate(node->cert); - CERT_AddCertToListTail(id_cryptoctx->id_certs, cert); - pkiDebug("%s: loaded \"%s\" from " - "PKCS11 module \"%s\"\n", - __FUNCTION__, cert->subjectName, spec); + /* Load private keys and certs from this slot. */ + if (cert_load_certs_with_keys_from_slot(context, id_cryptoctx, + slot) == 0) { + status = SECSuccess; } - - CERT_DestroyCertList(certs); } - return SECSuccess; + return status; } static SECStatus @@ -1850,7 +1901,6 @@ crypto_load_pkcs12(krb5_context context, PK11SlotInfo *slot; SEC_PKCS12DecoderContext *ctx; SECItem tmp, empty; - SECStatus status; if ((id_cryptoctx->pem_module->slotCount == 0) || ((slot = id_cryptoctx->pem_module->slots[0]) == NULL)) { @@ -2094,9 +2144,6 @@ crypto_load_certdb(krb5_context context, const char *configdir, pkinit_identity_crypto_context id_cryptoctx) { - CERTCertificate *cert; - CERTCertList *certs; - CERTCertListNode *node; PK11SlotInfo *slot, **id_slots; char *p; int i, j; @@ -2153,35 +2200,8 @@ crypto_load_certdb(krb5_context context, id_slots[i] = NULL; id_cryptoctx->id_slots = id_slots; - /* If we have to log in to the token, give it a shot. */ - if (!PK11_IsLoggedIn(slot, - crypto_pwcb_prep(id_cryptoctx, context)) && - PK11_NeedLogin(slot) && - (PK11_Authenticate(slot, PR_TRUE, - crypto_pwcb_prep(id_cryptoctx, - context)) != SECSuccess)) { - pkiDebug("%s: error logging into \"%s\":\"%s\", " - "skipping\n", __FUNCTION__, configdir, - PK11_GetTokenName(slot)); - return 0; - } - certs = PK11_ListCertsInSlot(slot); - /* Walk the list of certs in the slot. */ - if (certs != NULL) { - for (node = CERT_LIST_HEAD(certs); - (node != NULL) && (node->cert != NULL) && - !CERT_LIST_END(node, certs); - node = CERT_LIST_NEXT(node)) { - /* Add the cert to our candidate cert list. */ - cert = CERT_DupCertificate(node->cert); - CERT_AddCertToListTail(id_cryptoctx->id_certs, cert); - pkiDebug("%s: loaded \"%s\" from " - "cert database \"%s\"\n", - __FUNCTION__, cert->subjectName, configdir); - } - CERT_DestroyCertList(certs); - } - return 0; + /* Load the keys from the database. */ + return cert_load_certs_with_keys_from_slot(context, id_cryptoctx, slot); } /* Load up a certificate and associated key. */ @@ -2291,10 +2311,6 @@ crypto_cert_get_count(krb5_context context, int *cert_count) { CERTCertListNode *node; - if (!id_cryptoctx->default_loaded) { - // cert_load_default_identity(context, id_cryptoctx); - id_cryptoctx->default_loaded = PR_TRUE; - } *cert_count = 0; if (!CERT_LIST_EMPTY(id_cryptoctx->id_certs)) { for (node = CERT_LIST_HEAD(id_cryptoctx->id_certs); @@ -2383,152 +2399,6 @@ crypto_cert_iteration_next(krb5_context context, return 0; } -/* Load certificates for which we have private keys from the slot. */ -static int -cert_load_certs_with_keys_from_slot(krb5_context context, - pkinit_identity_crypto_context id, - PK11SlotInfo *slot) -{ - CERTCertificate *cert; - CERTCertList *clist; - CERTCertListNode *cnode; - SECKEYPrivateKey *key; - int status; - /* Skip over slots we've already used. */ - if (!PK11_IsLoggedIn(slot, crypto_pwcb_prep(id, context)) && - PK11_NeedLogin(slot)) { - pkiDebug("%s: skipping 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 ENOMEM; - } - } - /* Get the list of certs from the slot. */ - clist = PK11_ListCertsInSlot(slot); - if (clist == NULL) { - pkiDebug("%s: nothing found in token \"%s\"\n", - __FUNCTION__, PK11_GetTokenName(slot)); - return 0; - } - if (CERT_LIST_EMPTY(clist)) { - CERT_DestroyCertList(clist); - pkiDebug("%s: nothing found in token \"%s\"\n", - __FUNCTION__, PK11_GetTokenName(slot)); - return 0; - } - /* 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; - for (cnode = CERT_LIST_HEAD(clist); - (cnode != NULL) && - (cnode->cert != NULL) && - !CERT_LIST_END(cnode, clist); - cnode = CERT_LIST_NEXT(cnode)) { - pkiDebug("%s: checking for key for \"%s\"\n", - __FUNCTION__, - cnode->cert->nickname ? - cnode->cert->nickname : "(no name)"); - key = PK11_FindPrivateKeyFromCert(slot, cnode->cert, - crypto_pwcb_prep(id, context)); - if (key == NULL) { - pkiDebug("%s: no key for \"%s\"\n", - __FUNCTION__, - cnode->cert->nickname ? - cnode->cert->nickname : "(no name)"); - continue; - } - pkiDebug("%s: using \"%s\" and its matching key\n", - __FUNCTION__, - cnode->cert->nickname ? - cnode->cert->nickname : "(no name)"); - /* DestroyCertList frees all of the certs in the list, - * so we need to create a copy that it can own. */ - cert = CERT_DupCertificate(cnode->cert); - if (CERT_AddCertToListTail(id->id_certs, cert) != SECSuccess) { - status = ENOMEM; - } - if (SECKEY_AddPrivateKeyToListTail(id->id_keys, - key) != SECSuccess) { - status = ENOMEM; - } - } - CERT_DestroyCertList(clist); - return status; -} - -/* Load all of the certificates in all of the tokens for which we also have - * matching secret keys. */ -static int -cert_load_default_identity(krb5_context context, - pkinit_identity_crypto_context id) -{ - PK11SlotList *slist; - PK11SlotListElement *sle; - int status; - - /* Get the list of tokens. All of them. */ - slist = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, - PR_FALSE, - crypto_pwcb_prep(id, context)); - if (slist == NULL) { - return ENOENT; - } - - /* First try logged-in/no-login-necessary slots. */ - status = 0; - for (sle = slist->head; sle != NULL; sle = sle->next) { - /* Skip over slots we don't want to use. */ - if (!PK11_IsLoggedIn(sle->slot, - crypto_pwcb_prep(id, context)) && - PK11_NeedLogin(sle->slot)) { - pkiDebug("%s: skipping token \"%s\"\n", - __FUNCTION__, PK11_GetTokenName(sle->slot)); - continue; - } - /* Get the list of certs, and skip the slot if it doesn't have - * any. */ - status = cert_load_certs_with_keys_from_slot(context, id, - sle->slot); - if (status != 0) { - PK11_FreeSlotList(slist); - return status; - } - } - /* Now try logging in to the slots that still require it. */ - for (sle = slist->head; sle != NULL; sle = sle->next) { - /* Skip over slots we've already used. */ - if (PK11_IsLoggedIn(sle->slot, - crypto_pwcb_prep(id, context)) || - !PK11_NeedLogin(sle->slot)) { - pkiDebug("%s: skipping token \"%s\"\n", - __FUNCTION__, PK11_GetTokenName(sle->slot)); - continue; - } - if (PK11_Authenticate(sle->slot, PR_TRUE, - crypto_pwcb_prep(id, - context)) != SECSuccess) { - pkiDebug("%s: error logging into \"%s\", skipping\n", - __FUNCTION__, PK11_GetTokenName(sle->slot)); - continue; - } - /* Get the list of certs, and skip the slot if it doesn't have - * any. */ - status = cert_load_certs_with_keys_from_slot(context, id, - sle->slot); - if (status != 0) { - PK11_FreeSlotList(slist); - return status; - } - } - PK11_FreeSlotList(slist); - return status; -} - /* Read names, key usage, and extended key usage from the cert. */ static SECItem * cert_get_ext_by_tag(CERTCertificate *cert, SECOidTag tag) -- 1.7.6.4