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;
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) {
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))) {
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 */
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;
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)
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 };
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,