diff options
author | Nalin Dahyabhai <nalin@redhat.com> | 2012-09-27 17:20:31 -0400 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2012-10-18 23:20:25 -0400 |
commit | 4c1e02bef34df0407323b610818980c25b61c878 (patch) | |
tree | fe294ee0cc65220c4d96fbcbe429d8f95c1121fb /src/lib | |
parent | 787cc1e24117e57a9173aaaa16935f6488eb3fec (diff) | |
download | krb5-4c1e02bef34df0407323b610818980c25b61c878.tar.gz krb5-4c1e02bef34df0407323b610818980c25b61c878.tar.xz krb5-4c1e02bef34df0407323b610818980c25b61c878.zip |
Use config storage for client OTP token selection
* Save the vendor name of the token we used to create the challenge.
* If we saved the name of a token vendor previously, prune out any
tokeninfos which contain different vendor names.
ticket: 7416 (new)
target_version: 1.11
tags: pullup
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/krb5/krb/preauth_otp.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/lib/krb5/krb/preauth_otp.c b/src/lib/krb5/krb/preauth_otp.c index 83c30c7ab..ef012bd89 100644 --- a/src/lib/krb5/krb/preauth_otp.c +++ b/src/lib/krb5/krb/preauth_otp.c @@ -925,6 +925,58 @@ filter_supported_tokeninfos(krb5_context context, krb5_otp_tokeninfo **tis) return KRB5_PREAUTH_FAILED; /* We have no supported tokeninfos. */ } +/* + * Try to find tokeninfos which match configuration data recorded in the input + * ccache, and if exactly one is found, drop the rest. + */ +static krb5_error_code +filter_config_tokeninfos(krb5_context context, + krb5_clpreauth_callbacks cb, + krb5_clpreauth_rock rock, + krb5_otp_tokeninfo **tis) +{ + krb5_otp_tokeninfo *match = NULL; + size_t i, j; + const char *vendor, *alg_id, *token_id; + + /* Pull up what we know about the token we want to use. */ + vendor = cb->get_cc_config(context, rock, "vendor"); + alg_id = cb->get_cc_config(context, rock, "algID"); + token_id = cb->get_cc_config(context, rock, "tokenID"); + + /* Look for a single matching entry. */ + for (i = 0; tis[i] != NULL; i++) { + if (vendor != NULL && tis[i]->vendor.length > 0 && + !data_eq_string(tis[i]->vendor, vendor)) + continue; + if (alg_id != NULL && tis[i]->alg_id.length > 0 && + !data_eq_string(tis[i]->alg_id, alg_id)) + continue; + if (token_id != NULL && tis[i]->token_id.length > 0 && + !data_eq_string(tis[i]->token_id, token_id)) + continue; + /* Oh, we already had a matching entry. More than one -> no change. */ + if (match != NULL) + return 0; + match = tis[i]; + } + + /* No matching entry -> no change. */ + if (match == NULL) + return 0; + + /* Prune out everything except the best match. */ + for (i = 0, j = 0; tis[i] != NULL; i++) { + if (tis[i] != match) + k5_free_otp_tokeninfo(context, tis[i]); + else + tis[j++] = tis[i]; + } + tis[j] = NULL; + + return 0; +} + static int otp_client_get_flags(krb5_context context, krb5_preauthtype pa_type) { @@ -969,6 +1021,12 @@ otp_client_prep_questions(krb5_context context, krb5_clpreauth_moddata moddata, if (retval != 0) return retval; + /* Remove tokeninfos that don't match the recorded description, if that + * results in there being only one that does. */ + retval = filter_config_tokeninfos(context, cb, rock, chl->tokeninfo); + if (retval != 0) + return retval; + /* Make the JSON representation. */ retval = codec_encode_challenge(context, chl, &json); if (retval != 0) @@ -982,6 +1040,35 @@ otp_client_prep_questions(krb5_context context, krb5_clpreauth_moddata moddata, return retval; } +/* + * Save the vendor, algID, and tokenID values for the selected token to the + * out_ccache, so that later we can try to use them to select the right one + * without having ot ask the user. + */ +static void +save_config_tokeninfo(krb5_context context, + krb5_clpreauth_callbacks cb, + krb5_clpreauth_rock rock, + krb5_otp_tokeninfo *ti) +{ + char *tmp; + if (ti->vendor.length > 0 && + asprintf(&tmp, "%.*s", ti->vendor.length, ti->vendor.data) >= 0) { + cb->set_cc_config(context, rock, "vendor", tmp); + free(tmp); + } + if (ti->alg_id.length > 0 && + asprintf(&tmp, "%.*s", ti->alg_id.length, ti->alg_id.data) >= 0) { + cb->set_cc_config(context, rock, "algID", tmp); + free(tmp); + } + if (ti->token_id.length > 0 && + asprintf(&tmp, "%.*s", ti->token_id.length, ti->token_id.data) >= 0) { + cb->set_cc_config(context, rock, "tokenID", tmp); + free(tmp); + } +} + static krb5_error_code otp_client_process(krb5_context context, krb5_clpreauth_moddata moddata, krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt, @@ -1036,6 +1123,9 @@ otp_client_process(krb5_context context, krb5_clpreauth_moddata moddata, if (retval != 0) goto error; + /* Save information about the token which was used. */ + save_config_tokeninfo(context, cb, rock, ti); + /* Encrypt the challenge's nonce and set it in the request. */ retval = encrypt_nonce(context, as_key, chl, req); if (retval != 0) |