From 4a7747dce2c44e4a5edc3b269f047e4d35fa8d93 Mon Sep 17 00:00:00 2001 From: Nalin Dahyabhai Date: Mon, 4 Oct 2010 20:47:05 -0400 Subject: [PATCH 042/150] - take a stab at pkinit_create_td_trusted_certifiers() --- src/plugins/preauth/pkinit/pkinit_crypto_nss.c | 145 +++++++++++++++++++++++- 1 files changed, 144 insertions(+), 1 deletions(-) diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c index b1a3a2c..c9bf929 100644 --- a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c +++ b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -2063,7 +2064,149 @@ pkinit_create_td_trusted_certifiers(krb5_context context, pkinit_identity_crypto_context id_cryptoctx, krb5_data **edata) { - return ENOSYS; + const krb5_external_principal_identifier **ids; + krb5_external_principal_identifier *id; + struct issuer_and_serial_number isn; + krb5_data *data; + krb5_typed_data typed_datum; + SECItem item; + const krb5_typed_data *typed_data[2]; + krb5_error_code code; + int i; + unsigned int trustf; + SECStatus status; + PK11SlotList *slist; + PK11SlotListElement *sle; + CERTCertificate *cert; + CERTCertList *sclist, *clist; + CERTCertListNode *node; + + /* Build the list of trusted roots. */ + clist = CERT_NewCertList(); + if (clist == NULL) { + return ENOMEM; + } + + /* Get the list of tokens. All of them. */ + slist = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, + PR_FALSE, NULLCX); + if (slist == NULL) { + return ENOENT; + } + + /* Walk the list of tokens. */ + i = 0; + status = SECSuccess; + for (sle = slist->head; sle != NULL; sle = sle->next) { + /* Skip over slots we would need to log in 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. */ + sclist = PK11_ListCertsInSlot(sle->slot); + if (sclist == NULL) { + pkiDebug("%s: nothing found in token \"%s\"\n", + __FUNCTION__, PK11_GetTokenName(sle->slot)); + continue; + } + if (CERT_LIST_EMPTY(sclist)) { + CERT_DestroyCertList(sclist); + pkiDebug("%s: nothing found in token \"%s\"\n", + __FUNCTION__, PK11_GetTokenName(sle->slot)); + continue; + } + /* Walk the list of certs, and for each one that's a trusted + * root, add it to the list. */ + for (node = CERT_LIST_HEAD(sclist); + (node != NULL) && + (node->cert != NULL) && + !CERT_LIST_END(node, sclist); + node = CERT_LIST_NEXT(node)) { + /* If it's not a root, we can't trust it. Right? */ + if (!cert->isRoot) { + continue; + } + /* If we have no trust for it, we can't trust it. */ + if (cert->trust == NULL) { + continue; + } + /* We need to trust it to issue client certs. */ + trustf = SEC_GET_TRUST_FLAGS(cert->trust, trustSSL); + if (!(trustf & CERTDB_TRUSTED_CLIENT_CA)) { + 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); + if (CERT_AddCertToListTail(clist, cert) != SECSuccess) { + status = ENOMEM; + } else { + i++; + } + } + CERT_DestroyCertList(sclist); + } + PK11_FreeSlotList(slist); + if (status != SECSuccess) { + CERT_DestroyCertList(clist); + return ENOMEM; + } + + /* Allocate some temporary storage. */ + id = PORT_ArenaZAlloc(req_cryptoctx->pool, sizeof(**ids) * i); + ids = PORT_ArenaZAlloc(req_cryptoctx->pool, sizeof(*ids) * (i + 1)); + if ((id == NULL) || (ids == NULL)) { + CERT_DestroyCertList(clist); + return ENOMEM; + } + + /* Fill in the identifiers. */ + i = 0; + for (node = CERT_LIST_HEAD(clist); + (node != NULL) && + (node->cert != NULL) && + !CERT_LIST_END(node, clist); + node = CERT_LIST_NEXT(node)) { + if (node->cert->keyIDGenerated) { + isn.issuer = node->cert->derIssuer; + isn.serial = node->cert->serialNumber; + if (SEC_ASN1EncodeItem(req_cryptoctx->pool, &item, &isn, + issuer_and_serial_number_template) != &item) { + CERT_DestroyCertList(clist); + return ENOMEM; + } + id[i].issuerAndSerialNumber.data = item.data; + id[i].issuerAndSerialNumber.length = item.len; + } else { + item = node->cert->subjectKeyID; + id[i].subjectKeyIdentifier.data = item.data; + id[i].subjectKeyIdentifier.length = item.len; + } + ids[i] = &id[i]; + i++; + } + ids[i] = NULL; + + /* Pass the list back up. */ + data = NULL; + code = k5int_encode_krb5_td_trusted_certifiers(ids, &data); + CERT_DestroyCertList(clist); + if (code != 0) { + return code; + } + memset(&typed_datum, 0, sizeof(typed_datum)); + typed_datum.type = TD_TRUSTED_CERTIFIERS; + typed_datum.length = data->length; + typed_datum.data = (unsigned char *) data->data; + typed_data[0] = &typed_datum; + typed_data[1] = NULL; + code = k5int_encode_krb5_typed_data(typed_data, edata); + krb5_free_data(context, data); + return code; } krb5_error_code -- 1.7.6.4