From 680dc5d1ec3235ee9f5d7dd5b5b53543407b3c90 Mon Sep 17 00:00:00 2001 From: Nalin Dahyabhai Date: Wed, 29 Sep 2010 16:15:53 -0400 Subject: [PATCH 022/150] - allocate contexts of the right size - correctly check for the end of a cert list - dup a cert before adding it to a list, because the list wants to take ownership - make the first call to certificate_iter_next return the first cert --- src/plugins/preauth/pkinit/pkinit_crypto_nss.c | 84 +++++++++++++++++------- 1 files changed, 59 insertions(+), 25 deletions(-) diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c index d82cb4d..e358482 100644 --- a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c +++ b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c @@ -47,8 +47,8 @@ #include #include -#define CONFIGDIR "/etc/pki/nssdb" -#define NULLCX NULL +#define CONFIGDIR "/home/nalin/projects/krb5/pkinit/src/plugins/preauth/pkinit" /* FIXME */ +#define NULLCX NULL /* FIXME */ /* Forward declarations. */ static krb5_error_code cert_retrieve_cert_sans(krb5_context context, @@ -66,7 +66,7 @@ struct _pkinit_plg_crypto_context { struct _pkinit_req_crypto_context { PLArenaPool *pool; - SECKEYPrivateKey *client_seckey; /* used by clients */ + SECKEYPrivateKey *client_dh_key; /* used by clients */ CERTCertificate *peer_cert; /* used by both clients and KDCs */ }; @@ -236,7 +236,7 @@ pkinit_init_identity_crypto(pkinit_identity_crypto_context *id_cryptoctx) PLArenaPool *pool; pool = PORT_NewArena(sizeof(double)); if (pool != NULL) { - *id_cryptoctx = PORT_ArenaZAlloc(pool, sizeof(*id_cryptoctx)); + *id_cryptoctx = PORT_ArenaZAlloc(pool, sizeof(**id_cryptoctx)); if (*id_cryptoctx != NULL) { (*id_cryptoctx)->pool = pool; (*id_cryptoctx)->id_certs = CERT_NewCertList(); @@ -284,7 +284,8 @@ pkinit_init_plg_crypto(pkinit_plg_crypto_context *plg_cryptoctx) PLArenaPool *pool; pool = PORT_NewArena(sizeof(double)); if (pool != NULL) { - *plg_cryptoctx = PORT_ArenaZAlloc(pool, sizeof(*plg_cryptoctx)); + *plg_cryptoctx = PORT_ArenaZAlloc(pool, + sizeof(**plg_cryptoctx)); if (*plg_cryptoctx != NULL) { (*plg_cryptoctx)->pool = pool; (*plg_cryptoctx)->ncontext = NSS_InitContext(CONFIGDIR, @@ -315,7 +316,8 @@ pkinit_init_req_crypto(pkinit_req_crypto_context *req_cryptoctx) PLArenaPool *pool; pool = PORT_NewArena(sizeof(double)); if (pool != NULL) { - *req_cryptoctx = PORT_ArenaZAlloc(pool, sizeof(*req_cryptoctx)); + *req_cryptoctx = PORT_ArenaZAlloc(pool, + sizeof(**req_cryptoctx)); if (*req_cryptoctx != NULL) { (*req_cryptoctx)->pool = pool; return 0; @@ -328,8 +330,8 @@ pkinit_init_req_crypto(pkinit_req_crypto_context *req_cryptoctx) void pkinit_fini_req_crypto(pkinit_req_crypto_context req_cryptoctx) { - if (req_cryptoctx->client_seckey != NULL) { - SECKEY_DestroyPrivateKey(req_cryptoctx->client_seckey); + if (req_cryptoctx->client_dh_key != NULL) { + SECKEY_DestroyPrivateKey(req_cryptoctx->client_dh_key); } if (req_cryptoctx->peer_cert != NULL) { CERT_DestroyCertificate(req_cryptoctx->peer_cert); @@ -519,10 +521,10 @@ client_create_dh(krb5_context context, /* Save our private key for reuse later. */ SECKEY_DestroyPublicKey(pub); PK11_PQG_DestroyParams(pqg_params); - if (req_cryptoctx->client_seckey != NULL) { - SECKEY_DestroyPrivateKey(req_cryptoctx->client_seckey); + if (req_cryptoctx->client_dh_key != NULL) { + SECKEY_DestroyPrivateKey(req_cryptoctx->client_dh_key); } - req_cryptoctx->client_seckey = priv; + req_cryptoctx->client_dh_key = priv; PK11_FreeSlot(slot); PORT_FreeArena(pool, PR_TRUE); @@ -554,7 +556,7 @@ client_process_dh(krb5_context context, /* Rebuild the KDC's public key using our parameters and the supplied * public value (subjectPublicKey). */ - pub = SECKEY_ConvertToPublicKey(req_cryptoctx->client_seckey); + pub = SECKEY_ConvertToPublicKey(req_cryptoctx->client_dh_key); if (pub == NULL) { PORT_FreeArena(pool, PR_TRUE); return ENOMEM; @@ -575,7 +577,7 @@ client_process_dh(krb5_context context, PORT_FreeArena(pool, PR_TRUE); return ENOMEM; } - sym = PK11_PubDerive(req_cryptoctx->client_seckey, &pub2, PR_FALSE, + sym = PK11_PubDerive(req_cryptoctx->client_dh_key, &pub2, PR_FALSE, NULL, NULL, CKM_DH_PKCS_DERIVE, CKM_TLS_MASTER_KEY_DERIVE_DH, @@ -926,7 +928,9 @@ create_krb5_trustedCertifiers(krb5_context context, n = 0; if (!CERT_LIST_EMPTY(id_cryptoctx->ca_certs)) { for (n = 0, node = CERT_LIST_HEAD(id_cryptoctx->ca_certs); - (node != NULL) && (node->cert != NULL); + (node != NULL) && + (node->cert != NULL) && + !CERT_LIST_END(node, id_cryptoctx->ca_certs); node = CERT_LIST_NEXT(node)) { n++; } @@ -978,6 +982,7 @@ crypto_load_certs(krb5_context context, pkinit_identity_crypto_context id_cryptoctx, krb5_principal princ) { + return 0; /* FIXME */ switch (idopts->idtype) { case IDTYPE_FILE: return ENOSYS; @@ -1010,7 +1015,7 @@ crypto_free_cert_info(krb5_context context, return ENOSYS; } -/* Count how many "self" certificates and keys we have. */ +/* Count how many candidate "self" certificates and keys we have. */ krb5_error_code crypto_cert_get_count(krb5_context context, pkinit_plg_crypto_context plg_cryptoctx, @@ -1022,7 +1027,9 @@ crypto_cert_get_count(krb5_context context, *cert_count = 0; if (!CERT_LIST_EMPTY(id_cryptoctx->id_certs)) { for (node = CERT_LIST_HEAD(id_cryptoctx->id_certs); - (node != NULL) && (node->cert != NULL); + (node != NULL) && + (node->cert != NULL) && + !CERT_LIST_END(node, id_cryptoctx->id_certs); node = CERT_LIST_NEXT(node)) { (*cert_count)++; } @@ -1068,19 +1075,19 @@ crypto_cert_iteration_end(krb5_context context, return 0; } -/* Walk to the next "self" certificate and key. */ +/* Walk to the first/next "self" certificate and key. */ krb5_error_code crypto_cert_iteration_next(krb5_context context, pkinit_cert_iter_handle iter_handle, pkinit_cert_handle *cert_handle) { CERTCertListNode *node; - /* Find the next node. */ - node = CERT_LIST_NEXT(iter_handle->node); + node = iter_handle->node; + /* Check if we're at the last node. */ if (CERT_LIST_END(node, iter_handle->id_cryptoctx->id_certs)) { /* No more entries. */ *cert_handle = NULL; - return ENOENT; + return PKINIT_ITER_NO_MORE; } /* Try to store cert info. */ *cert_handle = PORT_ArenaZAlloc(iter_handle->pool, @@ -1088,10 +1095,11 @@ crypto_cert_iteration_next(krb5_context context, if (*cert_handle == NULL) { return ENOMEM; } - /* Record that we iterated. */ - iter_handle->node = node; + /* Return a copy of the certificate in this node, and then move on to + * the next one. */ (*cert_handle)->id_cryptoctx = iter_handle->id_cryptoctx; (*cert_handle)->cert = CERT_DupCertificate(node->cert); + iter_handle->node = CERT_LIST_NEXT(iter_handle->node); return 0; } @@ -1105,6 +1113,7 @@ cert_load_default_identity(pkinit_identity_crypto_context id) SECKEYPrivateKey *key; CERTCertList *clist; CERTCertListNode *cnode; + CERTCertificate *cert; int status; /* Get the list of tokens. All of them. */ @@ -1120,30 +1129,55 @@ cert_load_default_identity(pkinit_identity_crypto_context id) /* Skip over slots we don't want to use. */ if (!PK11_IsLoggedIn(sle->slot, NULLCX) && 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. */ clist = PK11_ListCertsInSlot(sle->slot); if (clist == NULL) { + pkiDebug("%s: nothing found in token \"%s\"\n", + __FUNCTION__, PK11_GetTokenName(sle->slot)); continue; } if (CERT_LIST_EMPTY(clist)) { CERT_DestroyCertList(clist); + pkiDebug("%s: nothing found in token \"%s\"\n", + __FUNCTION__, PK11_GetTokenName(sle->slot)); continue; } /* 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. */ for (cnode = CERT_LIST_HEAD(clist); - (cnode != NULL) && (cnode->cert != NULL); + (cnode != NULL) && + (cnode->cert != NULL) && + !CERT_LIST_END(cnode, clist); cnode = CERT_LIST_NEXT(cnode)) { - key = PK11_FindKeyByAnyCert(cnode->cert, NULLCX); + pkiDebug("%s: checking for key for \"%s\"\n", + __FUNCTION__, + cnode->cert->nickname ? + cnode->cert->nickname : "(no name)"); + key = PK11_FindPrivateKeyFromCert(sle->slot, + cnode->cert, + NULLCX); 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, - cnode->cert) != SECSuccess) { + cert) != SECSuccess) { status = ENOMEM; } if (SECKEY_AddPrivateKeyToListTail(id->id_keys, -- 1.7.6.4