From d358c8891d719b5266e4ac7646e4e6e60e0658fa Mon Sep 17 00:00:00 2001 From: Nalin Dahyabhai Date: Wed, 27 Oct 2010 22:40:16 -0400 Subject: [PATCH 077/150] - if we're loading both a key and a cert, skip the cert if we can't load the key - first cut at loading pkcs12 bundles (doesn't work yet) --- src/plugins/preauth/pkinit/pkinit_crypto_nss.c | 152 ++++++++++++++++++++--- 1 files changed, 132 insertions(+), 20 deletions(-) diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c index a4745a2..c69c0f4 100644 --- a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c +++ b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c @@ -41,11 +41,12 @@ #include #include #include -#include #include #include #include #include +#include +#include #include #include #include @@ -850,6 +851,44 @@ secitem_from_dh_pubval(PLArenaPool *pool, return 0; } +/* Load the contents of a file into a SECitem. */ +static int +secitem_from_file(PLArenaPool *pool, const char *filename, SECItem *item) +{ + SECItem tmp; + struct stat st; + int fd, i, n; + fd = open(filename, O_RDONLY); + if (fd == -1) { + return errno; + } + if (fstat(fd, &st) == -1) { + i = errno; + close(fd); + return i; + } + tmp.data = PORT_ArenaZAlloc(pool, st.st_size); + if (tmp.data == NULL) { + close(fd); + return ENOMEM; + } + n = 0; + while (n < st.st_size) { + i = read(fd, tmp.data + n, st.st_size - n); + if (i <= 0) { + break; + } + n += i; + } + close(fd); + if (n < st.st_size) { + return ENOMEM; + } + tmp.len = n; + *item = tmp; + return 0; +} + static struct oakley_group { int identifier; int bits; /* shortest prime first, so that a sequential search will @@ -1789,6 +1828,72 @@ crypto_load_pkcs11(krb5_context context, return SECSuccess; } +static SECStatus +crypto_load_pkcs12(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + const char *name, + pkinit_identity_crypto_context id_cryptoctx) +{ + 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)) { + pkiDebug("%s: skipping identity PKCS12 bundle \"%s\": " + "no slot found\n", __FUNCTION__, name); + return SECFailure; + } + if (secitem_from_file(id_cryptoctx->pool, name, &tmp) != 0) { + pkiDebug("%s: skipping identity PKCS12 bundle \"%s\": " + "error reading from file\n", __FUNCTION__, name); + return SECFailure; + } + memset(&empty, 0, sizeof(empty)); + ctx = SEC_PKCS12DecoderStart(&empty, + slot, + crypto_pwcb_prep(id_cryptoctx, context), + NULL, + NULL, + NULL, + NULL, + NULL); + if (ctx == NULL) { + pkiDebug("%s: skipping identity PKCS12 bundle \"%s\": " + "error setting up decoder\n", __FUNCTION__, name); + return SECFailure; + } + if (SEC_PKCS12DecoderUpdate(ctx, tmp.data, tmp.len) != SECSuccess) { + SEC_PKCS12DecoderFinish(ctx); + pkiDebug("%s: skipping identity PKCS12 bundle \"%s\": " + "error passing data to decoder\n", __FUNCTION__, name); + return SECFailure; + } + if (SEC_PKCS12DecoderVerify(ctx) != SECSuccess) { + SEC_PKCS12DecoderFinish(ctx); + pkiDebug("%s: skipping identity PKCS12 bundle \"%s\": " + "error verifying data\n", __FUNCTION__, name); + return SECFailure; + } + if (SEC_PKCS12DecoderValidateBags(ctx, NULL) != SECSuccess) { + SEC_PKCS12DecoderFinish(ctx); + pkiDebug("%s: skipping identity PKCS12 bundle \"%s\": " + "error validating bags\n", __FUNCTION__, name); + return SECFailure; + } + if (SEC_PKCS12DecoderImportBags(ctx) != SECSuccess) { + SEC_PKCS12DecoderFinish(ctx); + pkiDebug("%s: skipping identity PKCS12 bundle \"%s\": " + "error importing data\n", __FUNCTION__, name); + return SECFailure; + } + pkiDebug("%s: imported PKCS12 bundle \"%s\"\n", __FUNCTION__, name); + SEC_PKCS12DecoderFinish(ctx); + return SECSuccess; +} + static void crypto_set_attributes(CK_ATTRIBUTE *attr, CK_ATTRIBUTE_TYPE type, @@ -1847,40 +1952,40 @@ crypto_load_files(krb5_context context, return SECFailure; } status = SECSuccess; - if (certfile != NULL) { + if (keyfile != NULL) { n_attrs = 0; crypto_set_attributes(&attrs[n_attrs++], CKA_CLASS, - &certclass, sizeof(certclass)); + &keyclass, sizeof(keyclass)); crypto_set_attributes(&attrs[n_attrs++], CKA_TOKEN, &cktrue, sizeof(cktrue)); crypto_set_attributes(&attrs[n_attrs++], CKA_LABEL, - (char *) certfile, strlen(certfile) + 1); - cktrust = cert_mark_trusted ? CK_TRUE : CK_FALSE; - crypto_set_attributes(&attrs[n_attrs++], CKA_TRUST, - &cktrust, sizeof(cktrust)); + (char *) keyfile, strlen(keyfile) + 1); permanent = PR_FALSE; obj = PK11_CreateGenericObject(slot, attrs, n_attrs, permanent); if (obj != NULL) { - pkiDebug("%s: loaded %scertificate \"%s\"\n", - __FUNCTION__, - cert_mark_trusted ? "CA " : "", - certfile); + pkiDebug("%s: loaded key \"%s\"\n", + __FUNCTION__, keyfile); status = SECFailure; } } - if (keyfile != NULL) { + if ((status == SECSuccess) && (certfile != NULL)) { n_attrs = 0; crypto_set_attributes(&attrs[n_attrs++], CKA_CLASS, - &keyclass, sizeof(keyclass)); + &certclass, sizeof(certclass)); crypto_set_attributes(&attrs[n_attrs++], CKA_TOKEN, &cktrue, sizeof(cktrue)); crypto_set_attributes(&attrs[n_attrs++], CKA_LABEL, - (char *) keyfile, strlen(keyfile) + 1); + (char *) certfile, strlen(certfile) + 1); + cktrust = cert_mark_trusted ? CK_TRUE : CK_FALSE; + crypto_set_attributes(&attrs[n_attrs++], CKA_TRUST, + &cktrust, sizeof(cktrust)); permanent = PR_FALSE; obj = PK11_CreateGenericObject(slot, attrs, n_attrs, permanent); if (obj != NULL) { - pkiDebug("%s: loaded key \"%s\"\n", - __FUNCTION__, keyfile); + pkiDebug("%s: loaded %scertificate \"%s\"\n", + __FUNCTION__, + cert_mark_trusted ? "CA " : "", + certfile); status = SECFailure; } } @@ -2029,10 +2134,17 @@ crypto_load_certs(krb5_context context, return 0; break; case IDTYPE_PKCS12: - pkiDebug("%s: skipping identity PKCS12 bundle \"%s\"\n", - __FUNCTION__, idopts->cert_filename); - return 0; /* FIXME */ - return ENOSYS; + status = crypto_load_pkcs12(context, + plg_cryptoctx, + req_cryptoctx, + idopts->cert_filename, + id_cryptoctx); + if (status != SECSuccess) { + pkiDebug("%s: error loading PKCS12 bundle \"%s\"\n", + __FUNCTION__, idopts->cert_filename); + return ENOMEM; + } + return 0; break; default: return EINVAL; -- 1.7.6.4