Avoid looping when preauth can't be generated
authorGreg Hudson <ghudson@mit.edu>
Fri, 11 Nov 2011 17:01:12 +0000 (17:01 +0000)
committerGreg Hudson <ghudson@mit.edu>
Fri, 11 Nov 2011 17:01:12 +0000 (17:01 +0000)
If we receive a PREAUTH_REQUIRED error and fail to generate any real
preauthentication, error out immediately instead of continuing to
generate non-preauthenticated requests until we hit the loop count.

There is a lot of room to generate a more meaningful error about why
we failed to generate preauth (although in many cases the answer may
be too complicated to explain in an error message), but that requires
more radical restructuring of the preauth framework.

ticket: 6430
target_version: 1.10
tags: pullup

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25469 dc483132-0cff-0310-8789-dd5450dbe970

src/include/k5-int.h
src/lib/krb5/krb/get_in_tkt.c
src/lib/krb5/krb/init_creds_ctx.h
src/lib/krb5/krb/preauth2.c

index fec4a7f80713c21a01c95d3672ff397e4169f5fa..b82fe5b6f91aab74d5d19b12b5cae29725461983 100644 (file)
@@ -1098,7 +1098,7 @@ krb5_do_preauth(krb5_context context, krb5_kdc_req *request,
                 krb5_data *encoded_previous_request, krb5_pa_data **in_padata,
                 krb5_pa_data ***out_padata, krb5_prompter_fct prompter,
                 void *prompter_data, krb5_clpreauth_rock preauth_rock,
-                krb5_gic_opt_ext *opte);
+                krb5_gic_opt_ext *opte, krb5_boolean *got_real_out);
 
 krb5_error_code KRB5_CALLCONV
 krb5_do_preauth_tryagain(krb5_context context, krb5_kdc_req *request,
index 6794986d4842bb00c698daea72eaf69cd6f8cb84..f39f2184e84c9c878036526881caaeb6dd3c947a 100644 (file)
@@ -1102,6 +1102,7 @@ init_creds_step_request(krb5_context context,
                         krb5_data *out)
 {
     krb5_error_code code;
+    krb5_boolean got_real;
 
     if (ctx->loopcount >= MAX_IN_TKT_LOOPS) {
         code = KRB5_GET_IN_TKT_LOOP;
@@ -1119,7 +1120,10 @@ init_creds_step_request(krb5_context context,
                                ctx->prompter,
                                ctx->prompter_data,
                                &ctx->preauth_rock,
-                               ctx->opte);
+                               ctx->opte,
+                               &got_real);
+        if (code == 0 && !got_real && ctx->preauth_required)
+            code = KRB5_PREAUTH_FAILED;
         if (code != 0)
             goto cleanup;
     } else {
@@ -1257,7 +1261,7 @@ init_creds_step_reply(krb5_context context,
     int canon_flag = 0;
     krb5_keyblock *strengthen_key = NULL;
     krb5_keyblock encrypting_key;
-    krb5_boolean fast_avail;
+    krb5_boolean fast_avail, got_real;
 
     encrypting_key.length = 0;
     encrypting_key.contents = NULL;
@@ -1296,6 +1300,7 @@ init_creds_step_reply(krb5_context context,
             code = sort_krb5_padata_sequence(context,
                                              &ctx->request->client->realm,
                                              ctx->preauth_to_use);
+            ctx->preauth_required = TRUE;
 
         } else if (canon_flag && ctx->err_reply->error == KDC_ERR_WRONG_REALM) {
             if (ctx->err_reply->client == NULL ||
@@ -1364,7 +1369,8 @@ init_creds_step_reply(krb5_context context,
                            ctx->prompter,
                            ctx->prompter_data,
                            &ctx->preauth_rock,
-                           ctx->opte);
+                           ctx->opte,
+                           &got_real);
     if (code != 0)
         goto cleanup;
 
index de43163d85f134f61cf142cb44d827c4929c3e6f..aa3129d7af474d9972100d91c23a91e0966ee4bd 100644 (file)
@@ -33,6 +33,7 @@ struct _krb5_init_creds_context {
     krb5_boolean enc_pa_rep_permitted;
     krb5_boolean have_restarted;
     krb5_boolean sent_nontrivial_preauth;
+    krb5_boolean preauth_required;
 };
 
 krb5_error_code
index fd5c63536b9a851c8cf164c3facb431ce80cf153..810096a09cae82ccf73096d7066a9a1ed3a43f64 100644 (file)
@@ -1434,7 +1434,8 @@ krb5_do_preauth(krb5_context context, krb5_kdc_req *request,
                 krb5_data *encoded_previous_request,
                 krb5_pa_data **in_padata, krb5_pa_data ***out_padata,
                 krb5_prompter_fct prompter, void *prompter_data,
-                krb5_clpreauth_rock rock, krb5_gic_opt_ext *opte)
+                krb5_clpreauth_rock rock, krb5_gic_opt_ext *opte,
+                krb5_boolean *got_real_out)
 {
     unsigned int h;
     int i, j, out_pa_list_size;
@@ -1446,6 +1447,8 @@ krb5_do_preauth(krb5_context context, krb5_kdc_req *request,
     static const int paorder[] = { PA_INFO, PA_REAL };
     int realdone;
 
+    *got_real_out = FALSE;
+
     if (in_padata == NULL) {
         *out_padata = NULL;
         return(0);
@@ -1640,6 +1643,7 @@ krb5_do_preauth(krb5_context context, krb5_kdc_req *request,
     if (etype_info)
         krb5_free_etype_info(context, etype_info);
 
+    *got_real_out = realdone;
     return(0);
 cleanup:
     if (out_pa_list) {