diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/preauth/pkinit/pkinit_crypto_nss.c | 312 |
1 files changed, 252 insertions, 60 deletions
diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c index 56a21702d..20ac6eb67 100644 --- a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c +++ b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c @@ -126,6 +126,7 @@ struct _pkinit_identity_crypto_context { SECMODModule *pem_module; /* used for FILE: and DIR: */ struct _pkinit_identity_crypto_module { char *name; + char *spec; SECMODModule *module; } **id_modules; /* used for PKCS11: */ struct _pkinit_identity_crypto_userdb { @@ -148,9 +149,11 @@ struct _pkinit_identity_crypto_context { krb5_context context; krb5_prompter_fct prompter; void *prompter_data; + const char *identity; } pwcb_args; krb5_boolean defer_id_prompt; pkinit_deferred_id *deferred_ids; + krb5_boolean defer_with_dummy_password; }; struct _pkinit_cert_info { /* aka _pkinit_cert_handle */ @@ -575,7 +578,8 @@ cmsdump(unsigned char *data, unsigned int length) /* A password-prompt callback for NSS that calls the libkrb5 callback. */ static char * -crypto_pwfn(const char *what, PRBool is_hardware, PRBool retry, void *arg) +crypto_pwfn(const char *what, PRBool is_hardware, CK_FLAGS token_flags, + PRBool retry, void *arg) { int ret; pkinit_identity_crypto_context id; @@ -583,6 +587,7 @@ crypto_pwfn(const char *what, PRBool is_hardware, PRBool retry, void *arg) krb5_prompt_type prompt_types[2]; krb5_data reply; char *text, *answer; + const char *warning, *password; size_t text_size; void *data; @@ -593,6 +598,56 @@ crypto_pwfn(const char *what, PRBool is_hardware, PRBool retry, void *arg) if (arg == NULL) return NULL; id = arg; + + /* If we need to warn about the PIN, figure out the text. */ + if (token_flags & CKF_USER_PIN_LOCKED) + warning = "PIN locked"; + else if (token_flags & CKF_USER_PIN_FINAL_TRY) + warning = "PIN final try"; + else if (token_flags & CKF_USER_PIN_COUNT_LOW) + warning = "PIN count low"; + else + warning = NULL; + + /* + * If we have the name of an identity here, then we're either supposed to + * save its name, or attempt to use a password, if one was supplied. + */ + if (id->pwcb_args.identity != NULL) { + if (id->defer_id_prompt) { + /* If we're in the defer-prompts step, just save the identity name + * and "fail". */ + if (!is_hardware) + token_flags = 0; + pkinit_set_deferred_id(&id->deferred_ids, id->pwcb_args.identity, + token_flags, NULL); + if (id->defer_with_dummy_password) { + /* Return a useless result. */ + answer = PR_Malloc(1); + if (answer != NULL) { + *answer = '\0'; + return answer; + } + } + } else { + /* Check if we already have a password for this identity. If so, + * just return a copy of it. */ + password = pkinit_find_deferred_id(id->deferred_ids, + id->pwcb_args.identity); + if (password != NULL) { + /* The result will be freed with PR_Free, so return a copy. */ + text_size = strlen(password) + 1; + answer = PR_Malloc(text_size); + if (answer != NULL) { + memcpy(answer, password, text_size); + pkiDebug("%s: returning %ld-char answer\n", __FUNCTION__, + (long)strlen(answer)); + return answer; + } + } + } + } + if (id->pwcb_args.prompter == NULL) return NULL; @@ -603,10 +658,14 @@ crypto_pwfn(const char *what, PRBool is_hardware, PRBool retry, void *arg) pkiDebug("out of memory"); return NULL; } - if (is_hardware) - snprintf(text, text_size, "%s PIN", what); - else + if (is_hardware) { + if (warning != NULL) + snprintf(text, text_size, "%s PIN (%s)", what, warning); + else + snprintf(text, text_size, "%s PIN", what); + } else { snprintf(text, text_size, "%s %s", _("Pass phrase for"), what); + } memset(&prompt, 0, sizeof(prompt)); prompt.prompt = text; prompt.hidden = 1; @@ -651,16 +710,33 @@ crypto_pwfn(const char *what, PRBool is_hardware, PRBool retry, void *arg) static char * crypto_pwcb(PK11SlotInfo *slot, PRBool retry, void *arg) { - return crypto_pwfn(PK11_GetTokenName(slot), PK11_IsHW(slot), retry, arg); + pkinit_identity_crypto_context id; + const char *what = NULL; + CK_TOKEN_INFO tinfo; + CK_FLAGS tflags; + + if (PK11_GetTokenInfo(slot, &tinfo) == SECSuccess) + tflags = tinfo.flags; + else + tflags = 0; + if (arg != NULL) { + id = arg; + what = id->pwcb_args.identity; + } + return crypto_pwfn((what != NULL) ? what : PK11_GetTokenName(slot), + PK11_IsHW(slot), tflags, retry, arg); } -/* Make sure we're using our callback, and set up the callback data. */ +/* + * Make sure we're using our callback, and set up the callback data. + */ static void * crypto_pwcb_prep(pkinit_identity_crypto_context id_cryptoctx, - krb5_context context) + const char *identity, krb5_context context) { PK11_SetPasswordFunc(crypto_pwcb); id_cryptoctx->pwcb_args.context = context; + id_cryptoctx->pwcb_args.identity = identity; return id_cryptoctx; } @@ -804,9 +880,12 @@ pkinit_fini_identity_crypto(pkinit_identity_crypto_context id_cryptoctx) if (id_cryptoctx->id_userdbs != NULL) for (i = 0; id_cryptoctx->id_userdbs[i] != NULL; i++) PK11_FreeSlot(id_cryptoctx->id_userdbs[i]->userdb); - if (id_cryptoctx->id_modules != NULL) - for (i = 0; id_cryptoctx->id_modules[i] != NULL; i++) - SECMOD_DestroyModule(id_cryptoctx->id_modules[i]->module); + if (id_cryptoctx->id_modules != NULL) { + for (i = 0; id_cryptoctx->id_modules[i] != NULL; i++) { + if (id_cryptoctx->id_modules[i]->module != NULL) + SECMOD_DestroyModule(id_cryptoctx->id_modules[i]->module); + } + } if (id_cryptoctx->id_crls != NULL) for (i = 0; id_cryptoctx->id_crls[i] != NULL; i++) CERT_UncacheCRL(CERT_GetDefaultCertDB(), id_cryptoctx->id_crls[i]); @@ -1398,7 +1477,7 @@ client_create_dh(krb5_context context, /* Generate a public value and a private key. */ slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN, - crypto_pwcb_prep(id_cryptoctx, context)); + crypto_pwcb_prep(id_cryptoctx, NULL, context)); if (slot == NULL) { PORT_FreeArena(pool, PR_TRUE); pkiDebug("%s: error selecting slot\n", __FUNCTION__); @@ -1407,7 +1486,7 @@ client_create_dh(krb5_context context, pub = NULL; priv = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, &dh_param, &pub, PR_FALSE, PR_FALSE, - crypto_pwcb_prep(id_cryptoctx, context)); + crypto_pwcb_prep(id_cryptoctx, NULL, context)); /* Finish building the return values. */ memset(&encoded, 0, sizeof(encoded)); @@ -1487,7 +1566,7 @@ client_process_dh(krb5_context context, /* Generate the shared value using our private key and the KDC's * public key. */ slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN, - crypto_pwcb_prep(id_cryptoctx, context)); + crypto_pwcb_prep(id_cryptoctx, NULL, context)); if (slot == NULL) { SECKEY_DestroyPublicKey(pub); PORT_FreeArena(pool, PR_TRUE); @@ -1498,7 +1577,7 @@ client_process_dh(krb5_context context, CKM_DH_PKCS_DERIVE, CKM_TLS_MASTER_KEY_DERIVE_DH, CKA_DERIVE, - 0, crypto_pwcb_prep(id_cryptoctx, context)); + 0, crypto_pwcb_prep(id_cryptoctx, NULL, context)); if (sym == NULL) { PK11_FreeSlot(slot); SECKEY_DestroyPublicKey(pub); @@ -1622,7 +1701,7 @@ server_process_dh(krb5_context context, /* Generate a public value and a private key using the parameters. */ slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN, - crypto_pwcb_prep(id_cryptoctx, context)); + crypto_pwcb_prep(id_cryptoctx, NULL, context)); if (slot == NULL) { PORT_FreeArena(pool, PR_TRUE); return ENOMEM; @@ -1630,7 +1709,7 @@ server_process_dh(krb5_context context, pub = NULL; priv = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, &dh_params, &pub, PR_FALSE, PR_FALSE, - crypto_pwcb_prep(id_cryptoctx, context)); + crypto_pwcb_prep(id_cryptoctx, NULL, context)); if (priv == NULL) { PK11_FreeSlot(slot); PORT_FreeArena(pool, PR_TRUE); @@ -1657,7 +1736,7 @@ server_process_dh(krb5_context context, CKM_DH_PKCS_DERIVE, CKM_TLS_MASTER_KEY_DERIVE_DH, CKA_DERIVE, - 0, crypto_pwcb_prep(id_cryptoctx, context)); + 0, crypto_pwcb_prep(id_cryptoctx, NULL, context)); if (sym == NULL) { SECKEY_DestroyPrivateKey(priv); SECKEY_DestroyPublicKey(pub); @@ -1898,7 +1977,8 @@ cert_maybe_add_to_list(CERTCertList *list, CERTCertificate *cert) static SECStatus cert_load_ca_certs_from_slot(krb5_context context, pkinit_identity_crypto_context id, - PK11SlotInfo *slot) + PK11SlotInfo *slot, + const char *identity) { CERTCertificate *cert; CERTCertList *list; @@ -1907,12 +1987,14 @@ cert_load_ca_certs_from_slot(krb5_context context, SECStatus status; /* Log in if the slot requires it. */ - if (!PK11_IsLoggedIn(slot, crypto_pwcb_prep(id, context)) && + PK11_TokenRefresh(slot); + if (!PK11_IsLoggedIn(slot, crypto_pwcb_prep(id, identity, context)) && PK11_NeedLogin(slot)) { pkiDebug("%s: logging in to token \"%s\"\n", __FUNCTION__, PK11_GetTokenName(slot)); if (PK11_Authenticate(slot, PR_TRUE, - crypto_pwcb_prep(id, context)) != SECSuccess) { + crypto_pwcb_prep(id, identity, + context)) != SECSuccess) { pkiDebug("%s: error logging into \"%s\": %s, skipping\n", __FUNCTION__, PK11_GetTokenName(slot), PORT_ErrorToName(PORT_GetError())); @@ -1954,7 +2036,7 @@ cert_load_ca_certs_from_slot(krb5_context context, CERTDB_TRUSTED_CLIENT_CA | CERTDB_NS_TRUSTED_CA)) == 0) continue; /* DestroyCertList frees all of the certs in the list, - * so we need to create a copy that it can own. */ + * so we need to create a copy that we can own. */ cert = CERT_DupCertificate(node->cert); /* Add it to the list. */ if (cert_maybe_add_to_list(id->ca_certs, cert) != SECSuccess) @@ -1970,7 +2052,9 @@ cert_load_certs_with_keys_from_slot(krb5_context context, pkinit_identity_crypto_context id_cryptoctx, PK11SlotInfo *slot, - const char *label, const char *id) + const char *cert_label, + const char *cert_id, + const char *identity) { CERTCertificate *cert; CERTCertList *clist; @@ -1979,17 +2063,19 @@ cert_load_certs_with_keys_from_slot(krb5_context context, int status; /* Log in if the slot requires it. */ - if (!PK11_IsLoggedIn(slot, crypto_pwcb_prep(id_cryptoctx, context)) && + PK11_TokenRefresh(slot); + if (!PK11_IsLoggedIn(slot, crypto_pwcb_prep(id_cryptoctx, identity, + context)) && PK11_NeedLogin(slot)) { pkiDebug("%s: logging in to token \"%s\"\n", __FUNCTION__, PK11_GetTokenName(slot)); if (PK11_Authenticate(slot, PR_TRUE, - crypto_pwcb_prep(id_cryptoctx, + crypto_pwcb_prep(id_cryptoctx, identity, context)) != SECSuccess) { pkiDebug("%s: error logging into \"%s\": %s, skipping\n", __FUNCTION__, PK11_GetTokenName(slot), PORT_ErrorToName(PORT_GetError())); - return ENOMEM; + return id_cryptoctx->defer_id_prompt ? 0 : ENOMEM; } } /* Get the list of certs from the slot. */ @@ -2015,21 +2101,21 @@ cert_load_certs_with_keys_from_slot(krb5_context context, !CERT_LIST_END(cnode, clist); cnode = CERT_LIST_NEXT(cnode)) { if (cnode->cert->nickname != NULL) { - if ((label != NULL) && (id != NULL)) { - if ((strcmp(id, cnode->cert->nickname) != 0) && - (strcmp(label, cnode->cert->nickname) != 0)) + if ((cert_label != NULL) && (cert_id != NULL)) { + if ((strcmp(cert_id, cnode->cert->nickname) != 0) && + (strcmp(cert_label, cnode->cert->nickname) != 0)) continue; - } else if (label != NULL) { - if (strcmp(label, cnode->cert->nickname) != 0) + } else if (cert_label != NULL) { + if (strcmp(cert_label, cnode->cert->nickname) != 0) continue; - } else if (id != NULL) { - if (strcmp(id, cnode->cert->nickname) != 0) + } else if (cert_id != NULL) { + if (strcmp(cert_id, cnode->cert->nickname) != 0) continue; } } key = PK11_FindPrivateKeyFromCert(slot, cnode->cert, crypto_pwcb_prep(id_cryptoctx, - context)); + identity, context)); if (key == NULL) { pkiDebug("%s: no key for \"%s\", skipping it\n", __FUNCTION__, @@ -2053,6 +2139,10 @@ cert_load_certs_with_keys_from_slot(krb5_context context, return status; } +/* + * Reassemble the identity as it was supplied by the user or the library + * configuration. + */ static char * reassemble_pkcs11_name(PLArenaPool *pool, pkinit_identity_opts *idopts) { @@ -2091,6 +2181,43 @@ reassemble_pkcs11_name(PLArenaPool *pool, pkinit_identity_opts *idopts) return ret; } +/* + * Assemble an identity string that will distinguish this token from any other + * that is accessible through the same module, even if the user didn't specify + * a token name. + */ +static char * +reassemble_pkcs11_identity(PLArenaPool *pool, pkinit_identity_opts *idopts, + long slotid, const char *tokenname) +{ + struct k5buf buf; + int n = 0; + char *ret; + + k5_buf_init_dynamic(&buf); + k5_buf_add(&buf, "PKCS11:"); + n = 0; + if (idopts->p11_module_name != NULL) { + k5_buf_add_fmt(&buf, "%smodule_name=%s", + n++ ? ":" : "", + idopts->p11_module_name); + } + + if (slotid != PK_NOSLOT) + k5_buf_add_fmt(&buf, "%sslotid=%ld", n++ ? ":" : "", slotid); + + if (tokenname != NULL) + k5_buf_add_fmt(&buf, "%stoken=%s", n++ ? ":" : "", tokenname); + + if (k5_buf_len(&buf) >= 0) + ret = PORT_ArenaStrdup(pool, k5_buf_data(&buf)); + else + ret = NULL; + k5_free_buf(&buf); + + return ret; +} + static SECStatus crypto_load_pkcs11(krb5_context context, pkinit_plg_crypto_context plg_cryptoctx, @@ -2100,9 +2227,10 @@ crypto_load_pkcs11(krb5_context context, { struct _pkinit_identity_crypto_module **id_modules, *module; PK11SlotInfo *slot; - char *spec; + CK_TOKEN_INFO tinfo; + char *spec, *identity; size_t spec_size; - const char *label, *id, *tokenname; + const char *tokenname; SECStatus status; int i, j; @@ -2142,15 +2270,27 @@ crypto_load_pkcs11(krb5_context context, /* Allocate a bigger list. */ id_modules = PORT_ArenaZAlloc(id_cryptoctx->pool, sizeof(id_modules[0]) * (i + 2)); + if (id_modules == NULL) + return SECFailure; for (j = 0; j < i; j++) id_modules[j] = id_cryptoctx->id_modules[j]; - /* Actually load the module. */ + /* Actually load the module, or just ref an already-loaded copy. */ module = PORT_ArenaZAlloc(id_cryptoctx->pool, sizeof(*module)); if (module == NULL) return SECFailure; module->name = reassemble_pkcs11_name(id_cryptoctx->pool, idopts); - module->module = SECMOD_LoadUserModule(spec, NULL, PR_FALSE); + if (module->name == NULL) + return SECFailure; + module->spec = spec; + for (j = 0; j < i; j++) { + if (strcmp(module->spec, id_modules[j]->spec) == 0) + break; + } + if (j < i) + module->module = SECMOD_ReferenceModule(id_modules[j]->module); + else + module->module = SECMOD_LoadUserModule(spec, NULL, PR_FALSE); if (module->module == NULL) { pkiDebug("%s: error loading PKCS11 module \"%s\"", __FUNCTION__, idopts->p11_module_name); @@ -2160,6 +2300,7 @@ crypto_load_pkcs11(krb5_context context, pkiDebug("%s: error really loading PKCS11 module \"%s\"", __FUNCTION__, idopts->p11_module_name); SECMOD_DestroyModule(module->module); + module->module = NULL; return SECFailure; } SECMOD_UpdateSlotList(module->module); @@ -2177,6 +2318,7 @@ crypto_load_pkcs11(krb5_context context, (i < module->module->slotCount) && ((slot = module->module->slots[i]) != NULL); i++) { + PK11_TokenRefresh(slot); if (idopts->slotid != PK_NOSLOT) { if (idopts->slotid != PK11_GetSlotID(slot)) continue; @@ -2184,21 +2326,46 @@ crypto_load_pkcs11(krb5_context context, tokenname = PK11_GetTokenName(slot); if (tokenname == NULL || strlen(tokenname) == 0) continue; + /* If we're looking for a specific token, and this isn't it, go on. */ if (idopts->token_label != NULL) { if (strcmp(idopts->cert_label, tokenname) != 0) continue; } - /* Load private keys and their certs from this slot. */ - label = idopts->cert_label; - id = idopts->cert_id_string; + /* Assemble a useful identity string, in case of an incomplete one. */ + identity = reassemble_pkcs11_identity(id_cryptoctx->pool, idopts, + (long)PK11_GetSlotID(slot), + tokenname); + /* + * Skip past all of the loading-certificates-and-keys logic, pick up + * the token flags, and call it done for now. + */ + if (id_cryptoctx->defer_id_prompt) { + if (!PK11_IsLoggedIn(slot, crypto_pwcb_prep(id_cryptoctx, identity, + context)) && + PK11_NeedLogin(slot)) { + pkiDebug("%s: reading flags for token \"%s\"\n", + __FUNCTION__, PK11_GetTokenName(slot)); + if (PK11_GetTokenInfo(slot, &tinfo) == SECSuccess) { + pkinit_set_deferred_id(&id_cryptoctx->deferred_ids, + identity, tinfo.flags, NULL); + } + } + return SECSuccess; + } + if (!PK11_IsPresent(slot)) + continue; + /* Load private keys and their certs from this token. */ if (cert_load_certs_with_keys_from_slot(context, id_cryptoctx, - slot, label, id) == 0) + slot, idopts->cert_label, + idopts->cert_id_string, + identity) == 0) status = SECSuccess; /* If no label was specified, then we've looked at a token, so we're * done. */ if (idopts->token_label == NULL) break; } + return status; } @@ -2348,6 +2515,7 @@ crypto_load_pkcs12(krb5_context context, SECItem tmp, password; PRBool retry; int attempt; + char *identity; if ((slot = crypto_get_p12_slot(id_cryptoctx)) == NULL) { pkiDebug("%s: skipping identity PKCS12 bundle \"%s\": " @@ -2373,11 +2541,15 @@ crypto_load_pkcs12(krb5_context context, password.len = 2; attempt = 0; ctx = NULL; + identity = reassemble_pkcs12_name(id_cryptoctx->pool, name); + if (identity == NULL) + return SECFailure; + id_cryptoctx->id_p12_slot.p12name = identity; do { retry = PR_FALSE; ctx = SEC_PKCS12DecoderStart(&password, slot, - crypto_pwcb_prep(id_cryptoctx, + crypto_pwcb_prep(id_cryptoctx, identity, context), NULL, NULL, NULL, NULL, NULL); if (ctx == NULL) { @@ -2397,13 +2569,19 @@ crypto_load_pkcs12(krb5_context context, unsigned char *ucs2s; size_t i, n_ucs2s; SECErrorCodes err; + err = PORT_GetError(); SEC_PKCS12DecoderFinish(ctx); switch (err) { case SEC_ERROR_BAD_PASSWORD: + if (id_cryptoctx->defer_id_prompt) { + pkinit_set_deferred_id(&id_cryptoctx->deferred_ids, + identity, 0, NULL); + return SECSuccess; + } pkiDebug("%s: prompting for password for %s\n", __FUNCTION__, name); - newpass = crypto_pwfn(name, PR_FALSE, (attempt > 0), + newpass = crypto_pwfn(name, PR_FALSE, 0, (attempt > 0), id_cryptoctx); attempt++; if (newpass != NULL) { @@ -2451,14 +2629,12 @@ crypto_load_pkcs12(krb5_context context, free(password.data); return SECFailure; } - id_cryptoctx->id_p12_slot.p12name = - reassemble_pkcs12_name(id_cryptoctx->pool, name); pkiDebug("%s: imported PKCS12 bundle \"%s\"\n", __FUNCTION__, name); SEC_PKCS12DecoderFinish(ctx); if (password.data != emptypwd) free(password.data); if (cert_load_certs_with_keys_from_slot(context, id_cryptoctx, slot, - NULL, NULL) == 0) + NULL, NULL, identity) == 0) return SECSuccess; else return SECFailure; @@ -2551,6 +2727,8 @@ crypto_load_files(krb5_context context, return SECFailure; cobj->name = reassemble_files_name(id_cryptoctx->pool, certfile, keyfile); + if (cobj->name == NULL) + return SECFailure; cobj->obj = PK11_CreateGenericObject(slot, attrs, n_attrs, permanent); if (cobj->obj == NULL) { pkiDebug("%s: error loading %scertificate \"%s\"\n", @@ -2627,7 +2805,8 @@ crypto_load_files(krb5_context context, return SECFailure; kobj->obj = PK11_CreateGenericObject(slot, attrs, n_attrs, permanent); if (kobj->obj == NULL) { - pkiDebug("%s: error loading key \"%s\"\n", __FUNCTION__, keyfile); + pkiDebug("%s: error loading key \"%s\": %s\n", __FUNCTION__, + keyfile, PORT_ErrorToName(PORT_GetError())); status = SECFailure; } else { pkiDebug("%s: loaded key \"%s\"\n", __FUNCTION__, keyfile); @@ -2660,13 +2839,13 @@ crypto_load_files(krb5_context context, * passwords at it, but it will cause the module to clear the * needs-login flag so that we can continue importing PEM items. */ - if (!PK11_IsLoggedIn(slot, crypto_pwcb_prep(id_cryptoctx, + if (!PK11_IsLoggedIn(slot, crypto_pwcb_prep(id_cryptoctx, cobj->name, context)) && PK11_NeedLogin(slot)) { pkiDebug("%s: logging in to token \"%s\"\n", __FUNCTION__, PK11_GetTokenName(slot)); if (PK11_Authenticate(slot, PR_TRUE, - crypto_pwcb_prep(id_cryptoctx, + crypto_pwcb_prep(id_cryptoctx, cobj->name, context)) != SECSuccess) { pkiDebug("%s: error logging into \"%s\": %s, skipping\n", __FUNCTION__, PK11_GetTokenName(slot), @@ -2681,6 +2860,7 @@ crypto_load_files(krb5_context context, if (cobj != NULL && cobj->cert != NULL && kobj->obj != NULL) { key = PK11_FindPrivateKeyFromCert(slot, cobj->cert, crypto_pwcb_prep(id_cryptoctx, + cobj->name, context)); if (key == NULL) { pkiDebug("%s: no private key found for \"%s\"(%s), " @@ -2873,6 +3053,8 @@ crypto_load_nssdb(krb5_context context, if (userdb == NULL) return SECFailure; userdb->name = reassemble_nssdb_name(id_cryptoctx->pool, configdir); + if (userdb->name == NULL) + return SECFailure; userdb->userdb = SECMOD_OpenUserDB(p); if (userdb->userdb == NULL) { pkiDebug("%s: error loading NSS cert database \"%s\"\n", @@ -2887,11 +3069,13 @@ crypto_load_nssdb(krb5_context context, id_cryptoctx->id_userdbs = id_userdbs; /* Load the CAs from the database. */ - cert_load_ca_certs_from_slot(context, id_cryptoctx, userdb->userdb); + cert_load_ca_certs_from_slot(context, id_cryptoctx, userdb->userdb, + userdb->name); /* Load the keys from the database. */ return cert_load_certs_with_keys_from_slot(context, id_cryptoctx, - userdb->userdb, NULL, NULL); + userdb->userdb, NULL, NULL, + userdb->name); } /* Load up a certificate and associated key. */ @@ -2910,6 +3094,7 @@ crypto_load_certs(krb5_context context, switch (idopts->idtype) { case IDTYPE_FILE: + id_cryptoctx->defer_with_dummy_password = TRUE; status = crypto_load_files(context, plg_cryptoctx, req_cryptoctx, @@ -2920,11 +3105,12 @@ crypto_load_certs(krb5_context context, pkiDebug("%s: error loading files \"%s\" and \"%s\"\n", __FUNCTION__, idopts->cert_filename, idopts->key_filename); - return ENOMEM; + return defer_id_prompts ? 0 : ENOMEM; } return 0; break; case IDTYPE_NSS: + id_cryptoctx->defer_with_dummy_password = FALSE; status = crypto_load_nssdb(context, plg_cryptoctx, req_cryptoctx, @@ -2937,6 +3123,7 @@ crypto_load_certs(krb5_context context, return 0; break; case IDTYPE_DIR: + id_cryptoctx->defer_with_dummy_password = TRUE; status = crypto_load_dir(context, plg_cryptoctx, req_cryptoctx, @@ -2945,11 +3132,12 @@ crypto_load_certs(krb5_context context, if (status != SECSuccess) { pkiDebug("%s: error loading directory \"%s\"\n", __FUNCTION__, idopts->cert_filename); - return ENOMEM; + return defer_id_prompts ? 0 : ENOMEM; } return 0; break; case IDTYPE_PKCS11: + id_cryptoctx->defer_with_dummy_password = FALSE; status = crypto_load_pkcs11(context, plg_cryptoctx, req_cryptoctx, idopts, id_cryptoctx); @@ -2961,6 +3149,7 @@ crypto_load_certs(krb5_context context, return 0; break; case IDTYPE_PKCS12: + id_cryptoctx->defer_with_dummy_password = FALSE; status = crypto_load_pkcs12(context, plg_cryptoctx, req_cryptoctx, @@ -3636,7 +3825,7 @@ pkinit_create_td_trusted_certifiers(krb5_context context, /* Get the list of tokens. All of them. */ slist = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, - crypto_pwcb_prep(id_cryptoctx, context)); + crypto_pwcb_prep(id_cryptoctx, NULL, context)); if (slist == NULL) { CERT_DestroyCertList(clist); return ENOENT; @@ -3646,9 +3835,9 @@ pkinit_create_td_trusted_certifiers(krb5_context context, i = 0; status = SECSuccess; for (sle = slist->head; sle != NULL; sle = sle->next) { - /* Skip over slots we would still need to log in to use. */ + /* Skip over slots we would still need to log in to before using. */ if (!PK11_IsLoggedIn(sle->slot, - crypto_pwcb_prep(id_cryptoctx, context)) && + crypto_pwcb_prep(id_cryptoctx, NULL, context)) && PK11_NeedLogin(sle->slot)) { pkiDebug("%s: skipping token \"%s\"\n", __FUNCTION__, PK11_GetTokenName(sle->slot)); @@ -4975,7 +5164,7 @@ crypto_signeddata_common_verify(krb5_context context, NULL, NULL, crypto_pwcb, crypto_pwcb_prep(id_cryptoctx, - context), + NULL, context), NULL, NULL); if (ecmsg == NULL) { pkiDebug("%s: plain-data not parsable\n", __FUNCTION__); @@ -5225,7 +5414,8 @@ cms_envelopeddata_verify(krb5_context context, NULL, NULL, crypto_pwcb, crypto_pwcb_prep(id_cryptoctx, - context), NULL, NULL); + NULL, context), + NULL, NULL); if (msg == NULL) return ENOMEM; @@ -5400,7 +5590,8 @@ cms_signeddata_create(krb5_context context, if (NSS_CMSDEREncode(msg, &plain, &encoded, pool) != SECSuccess) { NSS_CMSMessage_Destroy(msg); PORT_FreeArena(pool, PR_TRUE); - pkiDebug("%s: error encoding signed-data\n", __FUNCTION__); + pkiDebug("%s: error encoding signed-data: %s\n", __FUNCTION__, + PORT_ErrorToName(PORT_GetError())); return ENOMEM; } if (secitem_to_buf_len(&encoded, signed_data, signed_data_len) != 0) { @@ -5504,7 +5695,8 @@ cms_signeddata_verify(krb5_context context, NULL, NULL, crypto_pwcb, crypto_pwcb_prep(id_cryptoctx, - context), NULL, NULL); + NULL, context), + NULL, NULL); if (msg == NULL) return ENOMEM; |