summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin@redhat.com>2013-06-28 17:12:39 -0400
committerGreg Hudson <ghudson@mit.edu>2013-07-17 12:24:20 -0400
commit60426439f672fe273ceead17910f818da1954c5b (patch)
treeca0ec66872d66f87f055b09aaded03ce5927790c /src
parentacb490bd01235511294ecb6b23750e648e48f7dc (diff)
downloadkrb5-60426439f672fe273ceead17910f818da1954c5b.tar.gz
krb5-60426439f672fe273ceead17910f818da1954c5b.tar.xz
krb5-60426439f672fe273ceead17910f818da1954c5b.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/plugins/preauth/pkinit/pkinit.h10
-rw-r--r--src/plugins/preauth/pkinit/pkinit_clnt.c26
-rw-r--r--src/plugins/preauth/pkinit/pkinit_crypto.h3
-rw-r--r--src/plugins/preauth/pkinit/pkinit_crypto_nss.c3
-rw-r--r--src/plugins/preauth/pkinit/pkinit_crypto_openssl.c3
-rw-r--r--src/plugins/preauth/pkinit/pkinit_identity.c60
-rw-r--r--src/plugins/preauth/pkinit/pkinit_srv.c7
7 files changed, 97 insertions, 15 deletions
diff --git a/src/plugins/preauth/pkinit/pkinit.h b/src/plugins/preauth/pkinit/pkinit.h
index 39d4aaaf5..b44dfe7b7 100644
--- a/src/plugins/preauth/pkinit/pkinit.h
+++ b/src/plugins/preauth/pkinit/pkinit.h
@@ -288,6 +288,16 @@ krb5_error_code pkinit_identity_initialize
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 */
+ 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 */
int do_matching, /* IN */
krb5_principal princ); /* IN (optional) */
diff --git a/src/plugins/preauth/pkinit/pkinit_clnt.c b/src/plugins/preauth/pkinit/pkinit_clnt.c
index 5db24dad3..748b25e52 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 8b4b62b6d..8c2b0063a 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 47006ec7e..ef0e94d68 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 29c4f5755..a780e7122 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 98c0f0083..a53810c5c 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 f3dfb501f..640e835ca 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;