From ac0a24ffd90fc42a44d9e88367268f3fc0d742f0 Mon Sep 17 00:00:00 2001 From: Nalin Dahyabhai Date: Mon, 8 Nov 2010 18:03:33 -0500 Subject: [PATCH 107/150] - screen slot and certificate names - start working on passwords for pkcs12 blobs --- src/plugins/preauth/pkinit/pkinit_crypto_nss.c | 162 ++++++++++++++++-------- 1 files changed, 112 insertions(+), 50 deletions(-) diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c index 9879e33..46ca363 100644 --- a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c +++ b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -526,14 +527,14 @@ cmsdump(unsigned char *data, unsigned int length) /* A password-prompt callback for NSS that calls the libkrb5 callback. */ static char * -crypto_pwcb(PK11SlotInfo *slot, PRBool retry, void *arg) +crypto_pwfn(const char *what, PRBool retry, void *arg) { int ret; pkinit_identity_crypto_context id; krb5_prompt prompt; krb5_prompt_type prompt_types[2]; krb5_data reply; - char *name, *text, *answer; + char *text, *answer; void *data; /* We only want to be called once. */ @@ -550,10 +551,8 @@ crypto_pwcb(PK11SlotInfo *slot, PRBool retry, void *arg) } /* Set up the prompt. */ - name = PK11_GetTokenName(slot); - text = PORT_ArenaZAlloc(id->pool, strlen(name) + 100); - snprintf(text, strlen(name) + 100, "Password for %s", - PK11_GetTokenName(slot)); + text = PORT_ArenaZAlloc(id->pool, strlen(what) + 100); + snprintf(text, strlen(what) + 100, "Password for %s", what); memset(&prompt, 0, sizeof(prompt)); prompt.prompt = text; prompt.hidden = 1; @@ -561,16 +560,17 @@ crypto_pwcb(PK11SlotInfo *slot, PRBool retry, void *arg) reply.length = 256; data = malloc(reply.length); reply.data = data; - name = NULL; + what = NULL; answer = NULL; /* Call the prompter callback. */ prompt_types[0] = KRB5_PROMPT_TYPE_PREAUTH; prompt_types[1] = 0; (*k5int_set_prompt_types)(id->pwcb_args.context, prompt_types); + fflush(NULL); ret = (*id->pwcb_args.prompter)(id->pwcb_args.context, id->pwcb_args.prompter_data, - name, answer, 1, &prompt); + what, answer, 1, &prompt); answer = NULL; if ((ret == 0) && (reply.data != NULL)) { /* The result will be freed with PR_Free, so return a copy. */ @@ -593,6 +593,13 @@ crypto_pwcb(PK11SlotInfo *slot, PRBool retry, void *arg) return answer; } +/* A password-prompt callback for NSS that calls the libkrb5 callback. */ +static char * +crypto_pwcb(PK11SlotInfo *slot, PRBool retry, void *arg) +{ + return crypto_pwfn(PK11_GetTokenName(slot), retry, arg); +} + /* Make sure we're using our callback, and set up the callback data. */ static void * crypto_pwcb_prep(pkinit_identity_crypto_context id_cryptoctx, @@ -1932,7 +1939,8 @@ cert_load_ca_certs_from_slot(krb5_context context, static int cert_load_certs_with_keys_from_slot(krb5_context context, pkinit_identity_crypto_context id, - PK11SlotInfo *slot) + PK11SlotInfo *slot, + const char *label) { CERTCertificate *cert; CERTCertList *clist; @@ -1975,6 +1983,12 @@ cert_load_certs_with_keys_from_slot(krb5_context context, (cnode->cert != NULL) && !CERT_LIST_END(cnode, clist); cnode = CERT_LIST_NEXT(cnode)) { + if (label != NULL) { + if ((cnode->cert->nickname == NULL) || + (strcmp(label, cnode->cert->nickname) != 0)) { + continue; + } + } key = PK11_FindPrivateKeyFromCert(slot, cnode->cert, crypto_pwcb_prep(id, context)); if (key == NULL) { @@ -2005,32 +2019,34 @@ static SECStatus crypto_load_pkcs11(krb5_context context, pkinit_plg_crypto_context plg_cryptoctx, pkinit_req_crypto_context req_cryptoctx, - const char *name, + pkinit_identity_opts *idopts, pkinit_identity_crypto_context id_cryptoctx) { SECMODModule **id_modules, *module; PK11SlotInfo *slot; char *spec; + const char *label, *slotname, *tokenname; SECStatus status; int i, j; - if (name == NULL) { + if (idopts == NULL) { return SECFailure; } /* Build the module spec. */ spec = PORT_ArenaZAlloc(id_cryptoctx->pool, - strlen("library=''") + strlen(name) * 2 + 1); + strlen("library=''") + + strlen(idopts->p11_module_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) { + for (i = 0; idopts->p11_module_name[i] != '\0'; i++) { + if (strchr("\"", idopts->p11_module_name[i]) != NULL) { spec[j++] = '\\'; } - spec[j++] = name[i]; + spec[j++] = idopts->p11_module_name[i]; } spec[j++] = '\0'; strcat(spec, "\""); @@ -2055,11 +2071,12 @@ crypto_load_pkcs11(krb5_context context, module = SECMOD_LoadUserModule(spec, NULL, PR_FALSE); if (module == NULL) { pkiDebug("%s: error loading PKCS11 module \"%s\"", - __FUNCTION__, spec); + __FUNCTION__, idopts->p11_module_name); return SECFailure; } SECMOD_UpdateSlotList(module); - pkiDebug("%s: loaded PKCS11 module \"%s\"\n", __FUNCTION__, name); + pkiDebug("%s: loaded PKCS11 module \"%s\"\n", __FUNCTION__, + idopts->p11_module_name); /* Add us to the list and set the new list. */ id_modules[j++] = module; @@ -2071,9 +2088,21 @@ crypto_load_pkcs11(krb5_context context, for (i = 0; (i < module->slotCount) && ((slot = module->slots[i]) != NULL); i++) { + if (idopts->token_label != NULL) { + slotname = PK11_GetSlotName(slot); + tokenname = PK11_GetTokenName(slot); + if (((slotname == NULL) || + (strcmp(label, slotname) != 0)) && + ((tokenname == NULL) || + (strcmp(label, tokenname) != 0))) { + continue; + } + } /* Load private keys and their certs from this slot. */ + label = idopts->cert_label; if (cert_load_certs_with_keys_from_slot(context, id_cryptoctx, - slot) == 0) { + slot, + label) == 0) { status = SECSuccess; } } @@ -2133,7 +2162,9 @@ crypto_load_pkcs12(krb5_context context, PK11SlotInfo *slot; SEC_PKCS12DecoderContext *ctx; unsigned char emptypwd[] = {'\0'}; - SECItem tmp, empty; + SECItem tmp, password; + PRBool retry; + int attempt; if ((slot = crypto_get_p12_slot(id_cryptoctx)) == NULL) { pkiDebug("%s: skipping identity PKCS12 bundle \"%s\": " @@ -2153,34 +2184,64 @@ crypto_load_pkcs12(krb5_context context, SEC_PKCS12EnableCipher(PKCS12_DES_56, PR_TRUE); SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, PR_TRUE); /* Pass in the password. */ - memset(&empty, 0, sizeof(empty)); - empty.data = emptypwd; - empty.len = 1; - 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) { - pkiDebug("%s: skipping identity PKCS12 bundle \"%s\": " - "error passing data to decoder\n", __FUNCTION__, name); - SEC_PKCS12DecoderFinish(ctx); - return SECFailure; - } - if (SEC_PKCS12DecoderVerify(ctx) != SECSuccess) { - pkiDebug("%s: skipping identity PKCS12 bundle \"%s\": " - "error verifying data: %d\n", __FUNCTION__, name, - PORT_GetError()); - SEC_PKCS12DecoderFinish(ctx); - return SECFailure; + memset(&password, 0, sizeof(password)); + password.data = emptypwd; + password.len = 1; + attempt = 0; + do { + retry = PR_FALSE; + ctx = SEC_PKCS12DecoderStart(&password, + 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) { + pkiDebug("%s: skipping identity PKCS12 bundle \"%s\": " + "error passing data to decoder\n", __FUNCTION__, name); + SEC_PKCS12DecoderFinish(ctx); + return SECFailure; + } + if (SEC_PKCS12DecoderVerify(ctx) != SECSuccess) { + char *newpass; + switch (PORT_GetError()) { + case SEC_ERROR_BAD_PASSWORD: + pkiDebug("%s: prompting for password for %s\n", + __FUNCTION__, name); + newpass = crypto_pwfn(name, (attempt > 0), + id_cryptoctx); + attempt++; + if (newpass != NULL) { + SEC_PKCS12DecoderFinish(ctx); + password.len = strlen(newpass); + password.data = (unsigned char *) newpass; + PORT_SetError(0); + retry = PR_TRUE; + continue; + } + break; + default: + break; + } + pkiDebug("%s: skipping identity PKCS12 bundle \"%s\": " + "error verifying data: %d\n", __FUNCTION__, + name, PORT_GetError()); + SEC_PKCS12DecoderFinish(ctx); + return SECFailure; + } + } while (retry); + if (password.data != emptypwd) { + PR_Free(password.data); } if (SEC_PKCS12DecoderValidateBags(ctx, crypto_nickname_c_cb) != SECSuccess) { @@ -2200,7 +2261,7 @@ crypto_load_pkcs12(krb5_context context, pkiDebug("%s: imported PKCS12 bundle \"%s\"\n", __FUNCTION__, name); SEC_PKCS12DecoderFinish(ctx); if (cert_load_certs_with_keys_from_slot(context, id_cryptoctx, - slot) == 0) { + slot, NULL) == 0) { return SECSuccess; } else { return SECFailure; @@ -2577,7 +2638,8 @@ crypto_load_certdb(krb5_context context, cert_load_ca_certs_from_slot(context, id_cryptoctx, userdb); /* Load the keys from the database. */ - return cert_load_certs_with_keys_from_slot(context, id_cryptoctx, userdb); + return cert_load_certs_with_keys_from_slot(context, id_cryptoctx, + userdb, NULL); } /* Load up a certificate and associated key. */ @@ -2640,7 +2702,7 @@ crypto_load_certs(krb5_context context, status = crypto_load_pkcs11(context, plg_cryptoctx, req_cryptoctx, - idopts->p11_module_name, + idopts, id_cryptoctx); if (status != SECSuccess) { pkiDebug("%s: error loading module \"%s\"\n", -- 1.7.6.4