krb5 commit: Move forward tokeninfo filtering

Greg Hudson ghudson at MIT.EDU
Mon Oct 15 11:08:08 EDT 2012


https://github.com/krb5/krb5/commit/404e12cbcb7a146c962c279bc7eebcc0b17a5ae2
commit 404e12cbcb7a146c962c279bc7eebcc0b17a5ae2
Author: Nathaniel McCallum <npmccallum at redhat.com>
Date:   Sun Oct 14 21:32:49 2012 -0400

    Move forward tokeninfo filtering

 src/lib/krb5/krb/preauth_otp.c |  144 ++++++++++++++++++++++-----------------
 1 files changed, 81 insertions(+), 63 deletions(-)

diff --git a/src/lib/krb5/krb/preauth_otp.c b/src/lib/krb5/krb/preauth_otp.c
index de97e0d..2ac1705 100644
--- a/src/lib/krb5/krb/preauth_otp.c
+++ b/src/lib/krb5/krb/preauth_otp.c
@@ -42,23 +42,6 @@
 static krb5_preauthtype otp_client_supported_pa_types[] =
     { KRB5_PADATA_OTP_CHALLENGE, 0 };
 
-/* Tests krb5_data to see if it is printable. */
-static krb5_boolean
-is_printable_string(const krb5_data *data)
-{
-    unsigned int i;
-
-    if (data == NULL)
-        return FALSE;
-
-    for (i = 0; i < data->length; i++) {
-        if (!isprint((unsigned char)data->data[i]))
-            return FALSE;
-    }
-
-    return TRUE;
-}
-
 /* Takes the nonce from the challenge and encrypts it into the request. */
 static krb5_error_code
 encrypt_nonce(krb5_context ctx, krb5_keyblock *key,
@@ -236,32 +219,6 @@ base64_encode_request(krb5_pa_otp_req *req)
     return ENOTSUP;
 }
 
-static int
-is_tokeninfo_supported(krb5_otp_tokeninfo *ti)
-{
-    krb5_flags supported_flags = KRB5_OTP_FLAG_COLLECT_PIN |
-                                 KRB5_OTP_FLAG_NO_COLLECT_PIN |
-                                 KRB5_OTP_FLAG_SEPARATE_PIN;
-
-    /* Flags we don't support... */
-    if (ti->flags & ~supported_flags)
-        return 0;
-
-    /* We don't currently support hashing. */
-    if (ti->supported_hash_alg != NULL || ti->iteration_count >= 0)
-        return 0;
-
-    /* Remove tokeninfos with invalid vendor strings. */
-    if (!is_printable_string(&ti->vendor))
-        return 0;
-
-    /* We don't currently support base64. */
-    if (ti->format == KRB5_OTP_FORMAT_BASE64)
-        return 0;
-
-    return 1;
-}
-
 /* Builds a challenge string from the given tokeninfo. */
 static krb5_error_code
 make_challenge(const krb5_otp_tokeninfo *ti, char **challenge)
@@ -274,14 +231,6 @@ make_challenge(const krb5_otp_tokeninfo *ti, char **challenge)
     if (ti == NULL || ti->challenge.data == NULL)
         return 0;
 
-    /*
-     * If the challenge isn't printable, then we have some kind of binary
-     * challenge which we cannot properly handle. So error out. Ideally there
-     * would be some mechanism to handle binary challenges to hardware tokens.
-     */
-    if (!is_printable_string(&ti->challenge))
-        return KRB5_PREAUTH_FAILED;
-
     if (asprintf(challenge, "%s %.*s\n",
                  _("OTP Challenge:"),
                  ti->challenge.length,
@@ -360,20 +309,10 @@ make_request(krb5_context context, krb5_prompter_fct prompter,
     if (request == NULL || tis == NULL || tis[0] == NULL)
         return EINVAL;
 
-    /* Filter out any tokeninfos we don't support. */
+    /* Count how many challenges we have. */
     for (i = 0; tis[i] != NULL; i++) {
-        if (!is_tokeninfo_supported(tis[i])) {
-            remove_tokeninfo(context, tis, i--);
-            continue;
-        }
-
         if (tis[i]->challenge.data != NULL)
-            challengers++; /* Count how many challenges we have. */
-    }
-    if (tis[0] == NULL) {
-        krb5_set_error_message(context, KRB5_PREAUTH_FAILED,
-                               _("No supported tokens"));
-        return KRB5_PREAUTH_FAILED; /* We have no supported tokeninfos. */
+            challengers++;
     }
 
     /* Setup our challenge, if present. */
@@ -487,6 +426,80 @@ error:
     return ENOMEM;
 }
 
+/* Tests krb5_data to see if it is printable. */
+static krb5_boolean
+is_printable_string(const krb5_data *data)
+{
+    unsigned int i;
+
+    if (data == NULL)
+        return FALSE;
+
+    for (i = 0; i < data->length; i++) {
+        if (!isprint((unsigned char)data->data[i]))
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+/* Returns TRUE when the given tokeninfo contains the subset of features we
+ * support. */
+static krb5_boolean
+is_tokeninfo_supported(krb5_otp_tokeninfo *ti)
+{
+    krb5_flags supported_flags = KRB5_OTP_FLAG_COLLECT_PIN |
+                                 KRB5_OTP_FLAG_NO_COLLECT_PIN |
+                                 KRB5_OTP_FLAG_SEPARATE_PIN;
+
+    /* Flags we don't support... */
+    if (ti->flags & ~supported_flags)
+        return FALSE;
+
+    /* We don't currently support hashing. */
+    if (ti->supported_hash_alg != NULL || ti->iteration_count >= 0)
+        return FALSE;
+
+    /* Remove tokeninfos with invalid vendor strings. */
+    if (!is_printable_string(&ti->vendor))
+        return FALSE;
+
+    /* Remove tokeninfos with non-printable challenges. */
+    if (!is_printable_string(&ti->challenge))
+        return FALSE;
+
+    /* We don't currently support base64. */
+    if (ti->format == KRB5_OTP_FORMAT_BASE64)
+        return FALSE;
+
+    return TRUE;
+}
+
+/* Removes unsupported tokeninfos. Returns an error if no tokeninfos remain. */
+static krb5_error_code
+filter_supported_tokeninfos(krb5_context context, krb5_otp_tokeninfo **tis)
+{
+    size_t i, j;
+
+    /* Filter out any tokeninfos we don't support. */
+    for (i = 0, j = 0; tis[i] != NULL; i++) {
+        if (!is_tokeninfo_supported(tis[i]))
+            k5_free_otp_tokeninfo(context, tis[i]);
+        else
+            tis[j++] = tis[i];
+    }
+
+    /* Terminate the array. */
+    tis[j] = NULL;
+
+    if (tis[0] != NULL)
+        return 0;
+
+    krb5_set_error_message(context, KRB5_PREAUTH_FAILED,
+                           _("No supported tokens"));
+    return KRB5_PREAUTH_FAILED; /* We have no supported tokeninfos. */
+}
+
 static int
 otp_client_get_flags(krb5_context context, krb5_preauthtype pa_type)
 {
@@ -526,6 +539,11 @@ otp_client_process(krb5_context context, krb5_clpreauth_moddata moddata,
     if (retval != 0)
         return retval;
 
+    /* Remove unsupported tokeninfos. */
+    retval = filter_supported_tokeninfos(context, chl->tokeninfo);
+    if (retval != 0)
+        goto error;
+
     /* Fill in the request info from the TokenInfo structs .*/
     retval = make_request(context, prompter, prompter_data,
                           chl->tokeninfo, &req);


More information about the cvs-krb5 mailing list