c0d2f3b
From c7047421487c0e616b881c0922937bc759114233 Mon Sep 17 00:00:00 2001
c0d2f3b
From: Nathaniel McCallum <npmccallum@redhat.com>
c0d2f3b
Date: Fri, 3 May 2013 15:44:44 -0400
c0d2f3b
Subject: [PATCH 1/3] Check for keys in encrypted timestamp/challenge
c0d2f3b
c0d2f3b
Encrypted timestamp and encrypted challenge cannot succeed if the
c0d2f3b
client has no long-term key matching the request enctypes, so do not
c0d2f3b
offer them in that case.
c0d2f3b
c0d2f3b
ticket: 7630
c0d2f3b
c0d2f3b
NPM - This is a backport from the upstream fix. See upstream commits:
c0d2f3b
  https://github.com/krb5/krb5/commit/e50482720a805ecd8c160e4a8f4a846e6327dca2
c0d2f3b
  https://github.com/krb5/krb5/commit/9593d1311fa5e6e841c429653ad35a63d17c2fdd
c0d2f3b
---
c0d2f3b
 src/kdc/kdc_preauth_ec.c    | 23 +++++++++++++++++++++--
c0d2f3b
 src/kdc/kdc_preauth_encts.c | 22 ++++++++++++++++++++--
c0d2f3b
 2 files changed, 41 insertions(+), 4 deletions(-)
c0d2f3b
c0d2f3b
diff --git a/src/kdc/kdc_preauth_ec.c b/src/kdc/kdc_preauth_ec.c
c0d2f3b
index 9d7236c..db3ad07 100644
c0d2f3b
--- a/src/kdc/kdc_preauth_ec.c
c0d2f3b
+++ b/src/kdc/kdc_preauth_ec.c
c0d2f3b
@@ -39,8 +39,27 @@ ec_edata(krb5_context context, krb5_kdc_req *request,
c0d2f3b
          krb5_kdcpreauth_moddata moddata, krb5_preauthtype pa_type,
c0d2f3b
          krb5_kdcpreauth_edata_respond_fn respond, void *arg)
c0d2f3b
 {
c0d2f3b
-    krb5_keyblock *armor_key = cb->fast_armor(context, rock);
c0d2f3b
-    (*respond)(arg, (armor_key == NULL) ? ENOENT : 0, NULL);
c0d2f3b
+    krb5_boolean have_client_keys = FALSE;
c0d2f3b
+    krb5_keyblock *armor_key;
c0d2f3b
+    krb5_key_data *kd;
c0d2f3b
+    int i;
c0d2f3b
+
c0d2f3b
+    armor_key = cb->fast_armor(context, rock);
c0d2f3b
+
c0d2f3b
+    for (i = 0; i < rock->request->nktypes; i++) {
c0d2f3b
+        if (krb5_dbe_find_enctype(context, rock->client,
c0d2f3b
+                                  rock->request->ktype[i],
c0d2f3b
+                                  -1, 0, &kd) == 0) {
c0d2f3b
+            have_client_keys = TRUE;
c0d2f3b
+            break;
c0d2f3b
+        }
c0d2f3b
+    }
c0d2f3b
+
c0d2f3b
+    /* Encrypted challenge only works with FAST, and requires a client key. */
c0d2f3b
+    if (armor_key == NULL || !have_client_keys)
c0d2f3b
+        (*respond)(arg, ENOENT, NULL);
c0d2f3b
+    else
c0d2f3b
+        (*respond)(arg, 0, NULL);
c0d2f3b
 }
c0d2f3b
 
c0d2f3b
 static void
c0d2f3b
diff --git a/src/kdc/kdc_preauth_encts.c b/src/kdc/kdc_preauth_encts.c
c0d2f3b
index d708061..adde6e2 100644
c0d2f3b
--- a/src/kdc/kdc_preauth_encts.c
c0d2f3b
+++ b/src/kdc/kdc_preauth_encts.c
c0d2f3b
@@ -34,9 +34,27 @@ enc_ts_get(krb5_context context, krb5_kdc_req *request,
c0d2f3b
            krb5_kdcpreauth_moddata moddata, krb5_preauthtype pa_type,
c0d2f3b
            krb5_kdcpreauth_edata_respond_fn respond, void *arg)
c0d2f3b
 {
c0d2f3b
-    krb5_keyblock *armor_key = cb->fast_armor(context, rock);
c0d2f3b
+    krb5_boolean have_client_keys = FALSE;
c0d2f3b
+    krb5_keyblock *armor_key;
c0d2f3b
+    krb5_key_data *kd;
c0d2f3b
+    int i;
c0d2f3b
+
c0d2f3b
+    armor_key = cb->fast_armor(context, rock);
c0d2f3b
+
c0d2f3b
+    for (i = 0; i < rock->request->nktypes; i++) {
c0d2f3b
+        if (krb5_dbe_find_enctype(context, rock->client,
c0d2f3b
+                                  rock->request->ktype[i],
c0d2f3b
+                                  -1, 0, &kd) == 0) {
c0d2f3b
+            have_client_keys = TRUE;
c0d2f3b
+            break;
c0d2f3b
+        }
c0d2f3b
+    }
c0d2f3b
 
c0d2f3b
-    (*respond)(arg, (armor_key != NULL) ? ENOENT : 0, NULL);
c0d2f3b
+    /* Encrypted timestamp must not be used with FAST, and requires a key. */
c0d2f3b
+    if (armor_key != NULL || !have_client_keys)
c0d2f3b
+        (*respond)(arg, ENOENT, NULL);
c0d2f3b
+    else
c0d2f3b
+        (*respond)(arg, 0, NULL);
c0d2f3b
 }
c0d2f3b
 
c0d2f3b
 static void
c0d2f3b
-- 
c0d2f3b
1.8.2.1
c0d2f3b
c0d2f3b
c0d2f3b
From 4d19790527e2c9d52bb05abd6048a63a1a8c222c Mon Sep 17 00:00:00 2001
c0d2f3b
From: Greg Hudson <ghudson@mit.edu>
c0d2f3b
Date: Mon, 29 Apr 2013 14:55:31 -0400
c0d2f3b
Subject: [PATCH 2/3] Don't send empty etype info from KDC
c0d2f3b
c0d2f3b
RFC 4120 prohibits empty ETYPE-INFO2 sequences (though not ETYPE-INFO
c0d2f3b
sequences), and our client errors out if it sees an empty sequence of
c0d2f3b
either.
c0d2f3b
c0d2f3b
ticket: 7630
c0d2f3b
---
c0d2f3b
 src/kdc/kdc_preauth.c | 5 +++++
c0d2f3b
 1 file changed, 5 insertions(+)
c0d2f3b
c0d2f3b
diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
c0d2f3b
index 42a37a8..5c3b615 100644
c0d2f3b
--- a/src/kdc/kdc_preauth.c
c0d2f3b
+++ b/src/kdc/kdc_preauth.c
c0d2f3b
@@ -1404,6 +1404,11 @@ etype_info_helper(krb5_context context, krb5_kdc_req *request,
c0d2f3b
             seen_des++;
c0d2f3b
         }
c0d2f3b
     }
c0d2f3b
+
c0d2f3b
+    /* If the list is empty, don't send it at all. */
c0d2f3b
+    if (i == 0)
c0d2f3b
+        goto cleanup;
c0d2f3b
+
c0d2f3b
     if (etype_info2)
c0d2f3b
         retval = encode_krb5_etype_info2(entry, &scratch);
c0d2f3b
     else
c0d2f3b
-- 
c0d2f3b
1.8.2.1
c0d2f3b
c0d2f3b
c0d2f3b
From a04cf2e89f4101eb6c2ec44ef1948976fe5fe9d3 Mon Sep 17 00:00:00 2001
c0d2f3b
From: Greg Hudson <ghudson@mit.edu>
c0d2f3b
Date: Thu, 2 May 2013 16:15:32 -0400
c0d2f3b
Subject: [PATCH 3/3] Make AS requests work with no client key
c0d2f3b
c0d2f3b
If we cannot find a client key while preparing an AS reply, give
c0d2f3b
preauth mechanisms a chance to replace the reply key before erroring
c0d2f3b
out.
c0d2f3b
c0d2f3b
ticket: 7630
c0d2f3b
---
c0d2f3b
 src/kdc/do_as_req.c   | 36 ++++++++++++++++++++----------------
c0d2f3b
 src/kdc/kdc_preauth.c |  6 ++++++
c0d2f3b
 2 files changed, 26 insertions(+), 16 deletions(-)
c0d2f3b
c0d2f3b
diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c
c0d2f3b
index 79da300..cb91803 100644
c0d2f3b
--- a/src/kdc/do_as_req.c
c0d2f3b
+++ b/src/kdc/do_as_req.c
c0d2f3b
@@ -195,23 +195,18 @@ finish_process_as_req(struct as_req_state *state, krb5_error_code errcode)
c0d2f3b
                                    useenctype, -1, 0, &client_key))
c0d2f3b
             break;
c0d2f3b
     }
c0d2f3b
-    if (!(client_key)) {
c0d2f3b
-        /* Cannot find an appropriate key */
c0d2f3b
-        state->status = "CANT_FIND_CLIENT_KEY";
c0d2f3b
-        errcode = KRB5KDC_ERR_ETYPE_NOSUPP;
c0d2f3b
-        goto egress;
c0d2f3b
-    }
c0d2f3b
-    state->rock.client_key = client_key;
c0d2f3b
 
c0d2f3b
-    /* convert client.key_data into a real key */
c0d2f3b
-    if ((errcode = krb5_dbe_decrypt_key_data(kdc_context, NULL,
c0d2f3b
-                                             client_key,
c0d2f3b
-                                             &state->client_keyblock,
c0d2f3b
-                                             NULL))) {
c0d2f3b
-        state->status = "DECRYPT_CLIENT_KEY";
c0d2f3b
-        goto egress;
c0d2f3b
+    if (client_key != NULL) {
c0d2f3b
+        /* Decrypt the client key data entry to get the real reply key. */
c0d2f3b
+        errcode = krb5_dbe_decrypt_key_data(kdc_context, NULL, client_key,
c0d2f3b
+                                            &state->client_keyblock, NULL);
c0d2f3b
+        if (errcode) {
c0d2f3b
+            state->status = "DECRYPT_CLIENT_KEY";
c0d2f3b
+            goto egress;
c0d2f3b
+        }
c0d2f3b
+        state->client_keyblock.enctype = useenctype;
c0d2f3b
+        state->rock.client_key = client_key;
c0d2f3b
     }
c0d2f3b
-    state->client_keyblock.enctype = useenctype;
c0d2f3b
 
c0d2f3b
     /* Start assembling the response */
c0d2f3b
     state->reply.msg_type = KRB5_AS_REP;
c0d2f3b
@@ -248,6 +243,14 @@ finish_process_as_req(struct as_req_state *state, krb5_error_code errcode)
c0d2f3b
         goto egress;
c0d2f3b
     }
c0d2f3b
 
c0d2f3b
+    /* If we didn't find a client long-term key and no preauth mechanism
c0d2f3b
+     * replaced the reply key, error out now. */
c0d2f3b
+    if (state->client_keyblock.enctype == ENCTYPE_NULL) {
c0d2f3b
+        state->status = "CANT_FIND_CLIENT_KEY";
c0d2f3b
+        errcode = KRB5KDC_ERR_ETYPE_NOSUPP;
c0d2f3b
+        goto egress;
c0d2f3b
+    }
c0d2f3b
+
c0d2f3b
     errcode = handle_authdata(kdc_context,
c0d2f3b
                               state->c_flags,
c0d2f3b
                               state->client,
c0d2f3b
@@ -306,7 +309,8 @@ finish_process_as_req(struct as_req_state *state, krb5_error_code errcode)
c0d2f3b
                                   &state->reply_encpart, 0,
c0d2f3b
                                   as_encrypting_key,
c0d2f3b
                                   &state->reply, &response);
c0d2f3b
-    state->reply.enc_part.kvno = client_key->key_data_kvno;
c0d2f3b
+    if (client_key != NULL)
c0d2f3b
+        state->reply.enc_part.kvno = client_key->key_data_kvno;
c0d2f3b
     if (errcode) {
c0d2f3b
         state->status = "ENCODE_KDC_REP";
c0d2f3b
         goto egress;
c0d2f3b
diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
c0d2f3b
index 5c3b615..5d12346 100644
c0d2f3b
--- a/src/kdc/kdc_preauth.c
c0d2f3b
+++ b/src/kdc/kdc_preauth.c
c0d2f3b
@@ -1473,6 +1473,9 @@ etype_info_as_rep_helper(krb5_context context, krb5_pa_data * padata,
c0d2f3b
     krb5_etype_info_entry **entry = NULL;
c0d2f3b
     krb5_data *scratch = NULL;
c0d2f3b
 
c0d2f3b
+    if (client_key == NULL)
c0d2f3b
+        return 0;
c0d2f3b
+
c0d2f3b
     /*
c0d2f3b
      * Skip PA-ETYPE-INFO completely if AS-REQ lists any "newer"
c0d2f3b
      * enctypes.
c0d2f3b
@@ -1576,6 +1579,9 @@ return_pw_salt(krb5_context context, krb5_pa_data *in_padata,
c0d2f3b
     krb5_key_data *     client_key = rock->client_key;
c0d2f3b
     int i;
c0d2f3b
 
c0d2f3b
+    if (client_key == NULL)
c0d2f3b
+        return 0;
c0d2f3b
+
c0d2f3b
     for (i = 0; i < request->nktypes; i++) {
c0d2f3b
         if (enctype_requires_etype_info_2(request->ktype[i]))
c0d2f3b
             return 0;
c0d2f3b
-- 
c0d2f3b
1.8.2.1
c0d2f3b