Skip to content

Commit

Permalink
Load local TGT in KDC requests
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
greghudson committed Jun 15, 2015
1 parent 7cad84e commit 39548a5
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 0 deletions.
11 changes: 11 additions & 0 deletions src/kdc/do_as_req.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -404,6 +406,7 @@ finish_process_as_req(struct as_req_state *state, krb5_error_code errcode)
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) {
Expand Down Expand Up @@ -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))) {
Expand Down
9 changes: 9 additions & 0 deletions src/kdc/do_tgs_req.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -844,6 +852,7 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt,
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)
Expand Down
39 changes: 39 additions & 0 deletions src/kdc/kdc_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,45 @@ find_server_key(krb5_context context,
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 };
Expand Down
5 changes: 5 additions & 0 deletions src/kdc/kdc_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 39548a5

Please sign in to comment.