krb5 commit [krb5-1.11]: Use config storage for client OTP token selection

Tom Yu tlyu at MIT.EDU
Tue Oct 30 10:25:07 EDT 2012


https://github.com/krb5/krb5/commit/2d5d2532627144688768cea34be8a43cc397901a
commit 2d5d2532627144688768cea34be8a43cc397901a
Author: Nalin Dahyabhai <nalin at redhat.com>
Date:   Thu Sep 27 17:20:31 2012 -0400

    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.
    
    (cherry picked from commit 4c1e02bef34df0407323b610818980c25b61c878)
    
    ticket: 7416
    version_fixed: 1.11
    status: resolved

 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 83c30c7..ef012bd 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)


More information about the cvs-krb5 mailing list