krb5 commit: Load local TGT in KDC requests

Greg Hudson ghudson at mit.edu
Mon Jun 15 16:43:59 EDT 2015


https://github.com/krb5/krb5/commit/39548a5b17bbda9eeb63625a201cfd19b9de1c5b
commit 39548a5b17bbda9eeb63625a201cfd19b9de1c5b
Author: Greg Hudson <ghudson at mit.edu>
Date:   Wed Feb 11 13:40:44 2015 -0500

    Load local TGT in KDC requests
    
    Ensure that we have the server realm TGT principal entry at hand for
    AS and TGS requests.  In the common case, this is the same as the AS
    server or TGS header server principal, but in less common cases
    (direct AS requests for service tickets, cross-realm TGS requests) we
    will need to explicitly load it.
    
    The local TGT entry is not used in this commit.  In the short term, it
    will be used to verify and sign CAMMACs and to shore up some edge
    cases in AD-SIGNTICKET.  In the longer term, we might allow realm
    configuration variables to be stored in local TGT tl-data.

 src/kdc/do_as_req.c  |   11 +++++++++++
 src/kdc/do_tgs_req.c |    9 +++++++++
 src/kdc/kdc_util.c   |   39 +++++++++++++++++++++++++++++++++++++++
 src/kdc/kdc_util.h   |    5 +++++
 4 files changed, 64 insertions(+), 0 deletions(-)

diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c
index 6653126..24231bb 100644
--- a/src/kdc/do_as_req.c
+++ b/src/kdc/do_as_req.c
@@ -102,6 +102,8 @@ struct as_req_state {
     krb5_keyblock client_keyblock;
     krb5_db_entry *client;
     krb5_db_entry *server;
+    krb5_db_entry *local_tgt;
+    krb5_db_entry *local_tgt_storage;
     krb5_kdc_req *request;
     struct krb5_kdcpreauth_rock_st rock;
     const char *status;
@@ -404,6 +406,7 @@ egress:
         free(state->sname);
     krb5_db_free_principal(kdc_context, state->client);
     krb5_db_free_principal(kdc_context, state->server);
+    krb5_db_free_principal(kdc_context, state->local_tgt_storage);
     if (state->session_key.contents != NULL)
         krb5_free_keyblock_contents(kdc_context, &state->session_key);
     if (state->ticket_reply.enc_part.ciphertext.data != NULL) {
@@ -635,6 +638,14 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
         goto errout;
     }
 
+    errcode = get_local_tgt(kdc_context, &state->request->server->realm,
+                            state->server, &state->local_tgt,
+                            &state->local_tgt_storage);
+    if (errcode) {
+        state->status = "GET_LOCAL_TGT";
+        goto errout;
+    }
+
     au_state->stage = VALIDATE_POL;
 
     if ((errcode = krb5_timeofday(kdc_context, &state->kdc_time))) {
diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
index c8cd80d..73b39e0 100644
--- a/src/kdc/do_tgs_req.c
+++ b/src/kdc/do_tgs_req.c
@@ -125,6 +125,7 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt,
     krb5_enc_tkt_part *header_enc_tkt = NULL; /* TGT */
     krb5_enc_tkt_part *subject_tkt = NULL; /* TGT or evidence ticket */
     krb5_db_entry *client = NULL, *header_server = NULL;
+    krb5_db_entry *local_tgt, *local_tgt_storage = NULL;
     krb5_pa_s4u_x509_user *s4u_x509_user = NULL; /* protocol transition request */
     krb5_authdata **kdc_issued_auth_data = NULL; /* auth data issued by KDC */
     unsigned int c_flags = 0, s_flags = 0;       /* client/server KDB flags */
@@ -214,6 +215,13 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt,
         goto cleanup;
     }
 
+    errcode = get_local_tgt(kdc_context, &sprinc->realm, header_server,
+                            &local_tgt, &local_tgt_storage);
+    if (errcode) {
+        status = "GET_LOCAL_TGT";
+        goto cleanup;
+    }
+
     /* Ignore (for now) the request modification due to FAST processing. */
     au_state->request = request;
 
@@ -844,6 +852,7 @@ cleanup:
     krb5_db_free_principal(kdc_context, server);
     krb5_db_free_principal(kdc_context, header_server);
     krb5_db_free_principal(kdc_context, client);
+    krb5_db_free_principal(kdc_context, local_tgt_storage);
     if (session_key.contents != NULL)
         krb5_free_keyblock_contents(kdc_context, &session_key);
     if (newtransited)
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index bf6f17b..ec36510 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -540,6 +540,45 @@ errout:
     return retval;
 }
 
+/*
+ * If candidate is the local TGT for realm, set *alias_out to candidate and
+ * *storage_out to NULL.  Otherwise, load the local TGT into *storage_out and
+ * set *alias_out to *storage_out.
+ *
+ * In the future we might generalize this to a small per-request principal
+ * cache.  For now, it saves a load operation in the common case where the AS
+ * server or TGS header ticket server is the local TGT.
+ */
+krb5_error_code
+get_local_tgt(krb5_context context, const krb5_data *realm,
+              krb5_db_entry *candidate, krb5_db_entry **alias_out,
+              krb5_db_entry **storage_out)
+{
+    krb5_error_code ret;
+    krb5_principal princ;
+    krb5_db_entry *tgt;
+
+    *alias_out = NULL;
+    *storage_out = NULL;
+
+    ret = krb5_build_principal_ext(context, &princ, realm->length, realm->data,
+                                   KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
+                                   realm->length, realm->data, 0);
+    if (ret)
+        return ret;
+
+    if (!krb5_principal_compare(context, candidate->princ, princ)) {
+        ret = krb5_db_get_principal(context, princ, 0, &tgt);
+        if (!ret)
+            *storage_out = *alias_out = tgt;
+    } else {
+        *alias_out = candidate;
+    }
+
+    krb5_free_principal(context, princ);
+    return ret;
+}
+
 /* This probably wants to be updated if you support last_req stuff */
 
 static krb5_last_req_entry nolrentry = { KV5M_LAST_REQ_ENTRY, KRB5_LRQ_NONE, 0 };
diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
index c522f0b..ac86806 100644
--- a/src/kdc/kdc_util.h
+++ b/src/kdc/kdc_util.h
@@ -75,6 +75,11 @@ kdc_get_server_key (krb5_context, krb5_ticket *, unsigned int,
                     krb5_boolean match_enctype,
                     krb5_db_entry **, krb5_keyblock **, krb5_kvno *);
 
+krb5_error_code
+get_local_tgt(krb5_context context, const krb5_data *realm,
+              krb5_db_entry *candidate, krb5_db_entry **alias_out,
+              krb5_db_entry **storage_out);
+
 int
 validate_as_request (kdc_realm_t *, krb5_kdc_req *, krb5_db_entry,
                      krb5_db_entry, krb5_timestamp,


More information about the cvs-krb5 mailing list