From: Nalin Dahyabhai Date: Fri, 28 Jun 2013 21:12:39 +0000 (-0400) Subject: Split pkinit_identity_initialize into two phases X-Git-Tag: krb5-1.12-alpha1~97 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=60426439f672fe273ceead17910f818da1954c5b;p=thirdparty%2Fkrb5.git Split pkinit_identity_initialize into two phases Split part of pkinit_identity_initialize() into a second piece named pkinit_identity_prompt(). Have each piece pass a new boolean flag to crypto_load_certs() to indicate if it should defer prompting for a password/PIN for client identities that require one. If the flag isn't set, then crypto_load_certs() should attempt to use a responder-supplied value, or call the prompter if there isn't one. ticket: 7680 --- diff --git a/src/plugins/preauth/pkinit/pkinit.h b/src/plugins/preauth/pkinit/pkinit.h index 39d4aaaf55..b44dfe7b7b 100644 --- a/src/plugins/preauth/pkinit/pkinit.h +++ b/src/plugins/preauth/pkinit/pkinit.h @@ -281,6 +281,16 @@ char * idtype2string(int idtype); char * catype2string(int catype); krb5_error_code pkinit_identity_initialize + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_opts *idopts, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN/OUT */ + krb5_clpreauth_callbacks cb, /* IN/OUT */ + krb5_clpreauth_rock rock, /* IN/OUT */ + krb5_principal princ); /* IN (optional) */ + +krb5_error_code pkinit_identity_prompt (krb5_context context, /* IN */ pkinit_plg_crypto_context plg_cryptoctx, /* IN */ pkinit_req_crypto_context req_cryptoctx, /* IN */ diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c index 5db24dad37..748b25e52a 100644 --- a/src/plugins/preauth/pkinit/pkinit_clnt.c +++ b/src/plugins/preauth/pkinit/pkinit_clnt.c @@ -1107,15 +1107,29 @@ pkinit_client_process(krb5_context context, krb5_clpreauth_moddata moddata, if (processing_request) { pkinit_client_profile(context, plgctx, reqctx, cb, rock, &request->server->realm); + retval = pkinit_identity_initialize(context, plgctx->cryptoctx, NULL, + reqctx->idopts, reqctx->idctx, + cb, rock, request->client); + if (retval) { + TRACE_PKINIT_CLIENT_NO_IDENTITY(context); + pkiDebug("pkinit_identity_prompt returned %d (%s)\n", + retval, error_message(retval)); + return retval; + } + /* + * Load identities (again, potentially), prompting, if we can, for + * anything for which we didn't get an answer from the responder + * callback. + */ pkinit_identity_set_prompter(reqctx->idctx, prompter, prompter_data); - retval = pkinit_identity_initialize(context, plgctx->cryptoctx, - reqctx->cryptoctx, reqctx->idopts, - reqctx->idctx, cb, rock, - reqctx->do_identity_matching, - request->client); + retval = pkinit_identity_prompt(context, plgctx->cryptoctx, + reqctx->cryptoctx, reqctx->idopts, + reqctx->idctx, cb, rock, + reqctx->do_identity_matching, + request->client); if (retval) { TRACE_PKINIT_CLIENT_NO_IDENTITY(context); - pkiDebug("pkinit_identity_initialize returned %d (%s)\n", + pkiDebug("pkinit_identity_prompt returned %d (%s)\n", retval, error_message(retval)); return retval; } diff --git a/src/plugins/preauth/pkinit/pkinit_crypto.h b/src/plugins/preauth/pkinit/pkinit_crypto.h index 8b4b62b6d0..8c2b0063a8 100644 --- a/src/plugins/preauth/pkinit/pkinit_crypto.h +++ b/src/plugins/preauth/pkinit/pkinit_crypto.h @@ -433,7 +433,8 @@ krb5_error_code crypto_load_certs pkinit_req_crypto_context req_cryptoctx, /* IN */ pkinit_identity_opts *idopts, /* IN */ pkinit_identity_crypto_context id_cryptoctx, /* IN/OUT */ - krb5_principal princ); /* IN */ + krb5_principal princ, /* IN */ + krb5_boolean defer_id_prompts); /* IN */ /* * Free up information held from crypto_load_certs() diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c index 47006ec7e6..ef0e94d689 100644 --- a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c +++ b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c @@ -2890,7 +2890,8 @@ crypto_load_certs(krb5_context context, pkinit_req_crypto_context req_cryptoctx, pkinit_identity_opts *idopts, pkinit_identity_crypto_context id_cryptoctx, - krb5_principal princ) + krb5_principal princ, + krb5_boolean defer_id_prompts) { SECStatus status; diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c index 29c4f5755b..a780e7122d 100644 --- a/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c +++ b/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c @@ -4792,7 +4792,8 @@ crypto_load_certs(krb5_context context, pkinit_req_crypto_context req_cryptoctx, pkinit_identity_opts *idopts, pkinit_identity_crypto_context id_cryptoctx, - krb5_principal princ) + krb5_principal princ, + krb5_boolean defer_id_prompts) { krb5_error_code retval; diff --git a/src/plugins/preauth/pkinit/pkinit_identity.c b/src/plugins/preauth/pkinit/pkinit_identity.c index 98c0f0083a..a53810c5c9 100644 --- a/src/plugins/preauth/pkinit/pkinit_identity.c +++ b/src/plugins/preauth/pkinit/pkinit_identity.c @@ -511,6 +511,11 @@ process_option_ca_crl(krb5_context context, idtype, catype, residual); } +/* + * Load any identity information which doesn't require us to ask a controlling + * user any questions, and record the names of anything else which would + * require us to ask questions. + */ krb5_error_code pkinit_identity_initialize(krb5_context context, pkinit_plg_crypto_context plg_cryptoctx, @@ -519,15 +524,15 @@ pkinit_identity_initialize(krb5_context context, pkinit_identity_crypto_context id_cryptoctx, krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock, - int do_matching, krb5_principal princ) { krb5_error_code retval = EINVAL; - const char *signer_identity; int i; pkiDebug("%s: %p %p %p\n", __FUNCTION__, context, idopts, id_cryptoctx); - if (!(princ && krb5_principal_compare_any_realm (context, princ, krb5_anonymous_principal()))) { + if (!(princ && + krb5_principal_compare_any_realm(context, princ, + krb5_anonymous_principal()))) { if (idopts == NULL || id_cryptoctx == NULL) goto errout; @@ -561,11 +566,53 @@ pkinit_identity_initialize(krb5_context context, goto errout; retval = crypto_load_certs(context, plg_cryptoctx, req_cryptoctx, - idopts, id_cryptoctx, princ); + idopts, id_cryptoctx, princ, TRUE); + if (retval) + goto errout; + } else { + /* We're the anonymous principal. */ + retval = 0; + } + +errout: + return retval; +} + +/* + * Load identity information, including that which requires us to ask a + * controlling user any questions. If we have PIN/password values which + * correspond to a given identity, use that, otherwise, if one is available, + * we'll use the prompter callback. + */ +krb5_error_code +pkinit_identity_prompt(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_opts *idopts, + pkinit_identity_crypto_context id_cryptoctx, + krb5_clpreauth_callbacks cb, + krb5_clpreauth_rock rock, + int do_matching, + krb5_principal princ) +{ + krb5_error_code retval = EINVAL; + const char *signer_identity; + int i; + + pkiDebug("%s: %p %p %p\n", __FUNCTION__, context, idopts, id_cryptoctx); + if (!(princ && + krb5_principal_compare_any_realm(context, princ, + krb5_anonymous_principal()))) { + retval = crypto_load_certs(context, plg_cryptoctx, req_cryptoctx, + idopts, id_cryptoctx, princ, FALSE); if (retval) goto errout; if (do_matching) { + /* + * Try to select exactly one certificate based on matching + * criteria. Typical used for clients. + */ retval = pkinit_cert_matching(context, plg_cryptoctx, req_cryptoctx, id_cryptoctx, princ); if (retval) { @@ -575,7 +622,10 @@ pkinit_identity_initialize(krb5_context context, goto errout; } } else { - /* Tell crypto code to use the "default" */ + /* + * Tell crypto code to use the "default" identity. Typically used + * for KDCs. + */ retval = crypto_cert_select_default(context, plg_cryptoctx, req_cryptoctx, id_cryptoctx); if (retval) { diff --git a/src/plugins/preauth/pkinit/pkinit_srv.c b/src/plugins/preauth/pkinit/pkinit_srv.c index f3dfb501f2..640e835ca8 100644 --- a/src/plugins/preauth/pkinit/pkinit_srv.c +++ b/src/plugins/preauth/pkinit/pkinit_srv.c @@ -1299,7 +1299,12 @@ pkinit_server_plugin_init_realm(krb5_context context, const char *realmname, retval = pkinit_identity_initialize(context, plgctx->cryptoctx, NULL, plgctx->idopts, plgctx->idctx, - NULL, NULL, 0, NULL); + NULL, NULL, NULL); + if (retval) + goto errout; + retval = pkinit_identity_prompt(context, plgctx->cryptoctx, NULL, + plgctx->idopts, plgctx->idctx, + NULL, NULL, 0, NULL); if (retval) goto errout;