]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Load local TGT in KDC requests
authorGreg Hudson <ghudson@mit.edu>
Wed, 11 Feb 2015 18:40:44 +0000 (13:40 -0500)
committerGreg Hudson <ghudson@mit.edu>
Mon, 15 Jun 2015 20:33:33 +0000 (16:33 -0400)
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
src/kdc/do_tgs_req.c
src/kdc/kdc_util.c
src/kdc/kdc_util.h

index 66531268d9c9d32a5a2019f52bf7ce1f4c26dc28..24231bb4db35442c98df68dea30986e5463b8e64 100644 (file)
@@ -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))) {
index c8cd80df5c1ff05403b7d2a1218b548b25f685ab..73b39e0da0c471be9f8aaaca78e56ac00bbdbd94 100644 (file)
@@ -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)
index bf6f17b0ac61990c608047ca96eb39ecd4c0e2e7..ec36510daef2a173fdd2415db72a9638395901a9 100644 (file)
@@ -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 };
index c522f0bd2e1eacb3d13c2b2af859cb11ccad7fac..ac868065d1a51066984183d36256265d870d3219 100644 (file)
@@ -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,