From e330b7e28e7b37d06b7efbe42ccee0b59dc0ca09 Mon Sep 17 00:00:00 2001 From: Nalin Dahyabhai Date: Thu, 28 Oct 2010 00:42:31 -0400 Subject: [PATCH 078/150] - also open a certdb when we look at a directory - stop looking at a default location --- src/plugins/preauth/pkinit/pkinit_crypto_nss.c | 197 ++++++++++++++++++++---- 1 files changed, 169 insertions(+), 28 deletions(-) diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c index c69c0f4..69934dc 100644 --- a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c +++ b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c @@ -65,7 +65,7 @@ * unless we can be sure that the list of trusted roots isn't being shared with * general-purpose SSL/TLS configuration, even though we're leaning on SSL/TLS * trust settings. */ -#define CONFIGDIR "/home/nalin/projects/krb5/pkinit/src/plugins/preauth/pkinit" /* FIXME */ +#define CONFIGDIR "/etc/pki/nssdb" #define NSS_CMSContentInfo_SetDontStream(a, b) (SECSuccess) /* FIXME once this API works */ /* #define DEBUG_DER "/usr/lib64/nss/unsupported-tools/derdump" */ @@ -236,6 +236,7 @@ struct _pkinit_identity_crypto_context { PRBool default_loaded; SECMODModule *pem_module; SECMODModule **id_modules; + PK11SlotInfo **id_slots; CERTCertList *id_certs, *ca_certs, *other_certs; SECKEYPrivateKeyList *id_keys; CERTCertificate *id_cert; @@ -673,6 +674,12 @@ pkinit_fini_identity_crypto(pkinit_identity_crypto_context id_cryptoctx) SECMOD_DestroyModule(id_cryptoctx->id_modules[i]); } } + if (id_cryptoctx->id_slots != NULL) { + int i; + for (i = 0; id_cryptoctx->id_slots[i] != NULL; i++) { + PK11_FreeSlot(id_cryptoctx->id_slots[i]); + } + } PORT_FreeArena(id_cryptoctx->pool, PR_TRUE); } @@ -711,7 +718,7 @@ pkinit_init_plg_crypto(pkinit_plg_crypto_context *plg_cryptoctx) NULL, NULL, NULL, - 0); + NSS_INIT_READONLY); if ((*plg_cryptoctx)->ncontext != NULL) { tag = get_pkinit_data_auth_data_tag(); if (crypto_register_any(tag) != SECSuccess) { @@ -1739,7 +1746,6 @@ crypto_load_pkcs11(krb5_context context, { SECMODModule **id_modules, *module; PK11SlotInfo *slot; - CERTCertDBHandle *certdb; CERTCertificate *cert; CERTCertList *certs; CERTCertListNode *node; @@ -1750,7 +1756,23 @@ crypto_load_pkcs11(krb5_context context, return SECFailure; } - certdb = CERT_GetDefaultCertDB(); + /* Build the module spec. */ + spec = PORT_ArenaZAlloc(id_cryptoctx->pool, + strlen("library=''") + strlen(name) * 2 + 1); + if (spec == NULL) { + return SECFailure; + } + strcpy(spec, "library=\""); + j = strlen(spec); + for (i = 0; name[i] != '\0'; i++) { + if (strchr("\"", name[i]) != NULL) { + spec[j++] = '\\'; + } + spec[j++] = name[i]; + } + spec[j++] = '\0'; + strcat(spec, "\""); + /* Count the number of modules we've already loaded. */ if (id_cryptoctx->id_modules != NULL) { for (i = 0; id_cryptoctx->id_modules[i] != NULL; i++) { @@ -1759,39 +1781,29 @@ crypto_load_pkcs11(krb5_context context, } else { i = 0; } + /* Allocate a bigger list. */ id_modules = PORT_ArenaZAlloc(id_cryptoctx->pool, sizeof(id_modules[0]) * (i + 2)); for (j = 0; j < i; j++) { - id_modules[j] = id_cryptoctx->id_modules[i]; + id_modules[j] = id_cryptoctx->id_modules[j]; } + /* Actually load the module. */ - spec = PORT_Alloc(strlen("library=\"\" ") + strlen(name) * 2); - if (spec == NULL) { - return SECFailure; - } - strcpy(spec, "library=\""); - j = strlen(spec); - for (i = 0; name[i] != '\0'; i++) { - if (name[i] == '\"') { - spec[j++] = '\\'; - } - spec[j++] = name[i]; - } - spec[j++] = '\0'; - strcat(spec, "\""); module = SECMOD_LoadUserModule(spec, NULL, PR_FALSE); - PORT_Free(spec); if (module == NULL) { pkiDebug("%s: error loading PKCS11 module \"%s\"", __FUNCTION__, spec); return SECFailure; } - pkiDebug("%s: loaded PKCS11 module \"%s\"\n", __FUNCTION__, spec); + SECMOD_UpdateSlotList(module); + pkiDebug("%s: loaded PKCS11 module \"%s\"\n", __FUNCTION__, name); + /* Add us to the list and set the new list. */ id_modules[j++] = module; id_modules[j] = NULL; id_cryptoctx->id_modules = id_modules; + /* Walk the list of slots in the module. */ for (i = module->slotCount; (slot = module->slots[i]) != NULL; @@ -1806,10 +1818,10 @@ crypto_load_pkcs11(krb5_context context, pkiDebug("%s: error logging into \"%s\":\"%s\", " "skipping\n", __FUNCTION__, spec, PK11_GetTokenName(slot)); - PK11_FreeSlot(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) && @@ -1822,8 +1834,8 @@ crypto_load_pkcs11(krb5_context context, "PKCS11 module \"%s\"\n", __FUNCTION__, cert->subjectName, spec); } + CERT_DestroyCertList(certs); - PK11_FreeSlot(slot); } return SECSuccess; } @@ -2024,9 +2036,8 @@ crypto_load_dir(krb5_context context, return SECFailure; } status = SECFailure; + pkiDebug("%s: scanning directory \"%s\"\n", __FUNCTION__, dirname); while ((ent = readdir(dir)) != NULL) { - pkiDebug("%s: scanning directory \"%s\"\n", - __FUNCTION__, dirname); i = strlen(ent->d_name); /* Skip over anything that isn't named ".crt" or * ".crl", whichever we want. */ @@ -2075,6 +2086,104 @@ crypto_load_dir(krb5_context context, return status; } +/* Load up a certificate database. */ +static krb5_error_code +crypto_load_certdb(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + const char *configdir, + pkinit_identity_crypto_context id_cryptoctx) +{ + CERTCertificate *cert; + CERTCertList *certs; + CERTCertListNode *node; + PK11SlotInfo *slot, **id_slots; + char *p; + int i, j; + + if (configdir == NULL) { + return ENOENT; + } + + /* Build the spec. */ + p = PORT_ArenaZAlloc(id_cryptoctx->pool, + strlen("configDir='' flags=readOnly") + + strlen(configdir) * 2 + 1); + if (p == NULL) { + return ENOMEM; + } + strcpy(p, "configDir='"); + j = strlen(p); + for (i = 0; configdir[i] != '\0'; i++) { + if (configdir[i] == '\'') { + p[j++] = '\''; + } + p[j++] = configdir[i]; + } + p[j++] = '\0'; + strcat(p, "' flags=readOnly"); + + /* Count the number of modules we've already loaded. */ + if (id_cryptoctx->id_slots != NULL) { + for (i = 0; id_cryptoctx->id_slots[i] != NULL; i++) { + continue; + } + } else { + i = 0; + } + + /* Allocate a bigger list. */ + id_slots = PORT_ArenaZAlloc(id_cryptoctx->pool, + sizeof(id_slots[0]) * (i + 2)); + for (j = 0; j < i; j++) { + id_slots[j] = id_cryptoctx->id_slots[j]; + } + + /* Actually load the module. */ + slot = SECMOD_OpenUserDB(p); + if (slot == NULL) { + pkiDebug("%s: error loading NSS cert database \"%s\"", + __FUNCTION__, configdir); + return ENOENT; + } + pkiDebug("%s: opened NSS database \"%s\"\n", __FUNCTION__, configdir); + + /* Add us to the list and set the new list. */ + id_slots[i++] = slot; + 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 up a certificate and associated key. */ krb5_error_code crypto_load_certs(krb5_context context, @@ -2107,6 +2216,15 @@ crypto_load_certs(krb5_context context, return 0; break; case IDTYPE_DIR: + status = crypto_load_certdb(context, + plg_cryptoctx, + req_cryptoctx, + idopts->cert_filename, + id_cryptoctx); + if (status != SECSuccess) { + pkiDebug("%s: error loading certdb \"%s\"\n", + __FUNCTION__, idopts->cert_filename); + } status = crypto_load_dir(context, plg_cryptoctx, req_cryptoctx, @@ -2142,6 +2260,7 @@ 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; @@ -2173,7 +2292,7 @@ crypto_cert_get_count(krb5_context context, { CERTCertListNode *node; if (!id_cryptoctx->default_loaded) { - cert_load_default_identity(context, id_cryptoctx); + // cert_load_default_identity(context, id_cryptoctx); id_cryptoctx->default_loaded = PR_TRUE; } *cert_count = 0; @@ -2264,6 +2383,7 @@ 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, @@ -2274,8 +2394,20 @@ cert_load_certs_with_keys_from_slot(krb5_context context, CERTCertListNode *cnode; SECKEYPrivateKey *key; int status; - /* Get the list of certs, and skip the slot if it doesn't have - * any. */ + /* 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", @@ -2675,6 +2807,15 @@ crypto_load_cas_and_crls(krb5_context context, return 0; break; case IDTYPE_DIR: + status = crypto_load_certdb(context, + plg_cryptoctx, + req_cryptoctx, + idopts->cert_filename, + id_cryptoctx); + if (status != SECSuccess) { + pkiDebug("%s: error loading CA certdb \"%s\"\n", + __FUNCTION__, idopts->cert_filename); + } status = crypto_load_dir(context, plg_cryptoctx, req_cryptoctx, -- 1.7.6.4