if (ret)
goto cleanup;
kdc_verifier.princ = NULL;
- kdc_verifier.kvno = tgt->key_data[0].key_data_kvno;
+ kdc_verifier.kvno = current_kvno(tgt);
kdc_verifier.enctype = ENCTYPE_NULL;
kdc_verifier.checksum = kdc_cksum;
/* Fetch the krbtgt key indicated by the KDC verifier. Only allow the
* first krbtgt key of the specified kvno. */
- if (ver->kvno == tgt->key_data[0].key_data_kvno) {
+ if (ver->kvno == current_kvno(tgt)) {
key = tgt_key;
} else {
if (krb5_dbe_find_enctype(context, tgt, -1, -1, ver->kvno, &kd) != 0)
static void
finish_process_as_req(struct as_req_state *state, krb5_error_code errcode)
{
- krb5_key_data *server_key;
krb5_keyblock *as_encrypting_key = NULL;
krb5_data *response = NULL;
const char *emsg = 0;
if (errcode)
goto egress;
- /*
- * Find the server key
- */
- if ((errcode = krb5_dbe_find_enctype(kdc_context, state->server,
- -1, /* ignore keytype */
- -1, /* Ignore salttype */
- 0, /* Get highest kvno */
- &server_key))) {
+ errcode = get_first_current_key(kdc_context, state->server,
+ &state->server_keyblock);
+ if (errcode) {
state->status = "FINDING_SERVER_KEY";
goto egress;
}
- /*
- * Convert server->key into a real key
- * (it may be encrypted in the database)
- *
- * server_keyblock is later used to generate auth data signatures
- */
- if ((errcode = krb5_dbe_decrypt_key_data(kdc_context, NULL,
- server_key,
- &state->server_keyblock,
- NULL))) {
- state->status = "DECRYPT_SERVER_KEY";
- goto egress;
- }
-
/* Start assembling the response */
state->reply.msg_type = KRB5_AS_REP;
state->reply.client = state->enc_tkt_reply.client; /* post canonization */
if (errcode)
goto egress;
- state->ticket_reply.enc_part.kvno = server_key->key_data_kvno;
+ state->ticket_reply.enc_part.kvno = current_kvno(state->server);
errcode = kdc_fast_response_handle_padata(state->rstate,
state->request,
&state->reply,
goto errout;
}
state->rock.local_tgt = state->local_tgt;
+ state->rock.local_tgt_key = &state->local_tgt_key;
au_state->stage = VALIDATE_POL;
krb5_timestamp kdc_time, authtime = 0;
krb5_keyblock session_key, local_tgt_key;
krb5_keyblock *reply_key = NULL;
- krb5_key_data *server_key;
krb5_principal cprinc = NULL, sprinc = NULL, altcprinc = NULL;
krb5_const_principal authdata_client;
krb5_principal stkt_authdata_client = NULL;
krb5_enc_tkt_part *t2enc = request->second_ticket[st_idx]->enc_part2;
encrypting_key = t2enc->session;
} else {
- /*
- * Find the server key
- */
- if ((errcode = krb5_dbe_find_enctype(kdc_context, server,
- -1, /* ignore keytype */
- -1, /* Ignore salttype */
- 0, /* Get highest kvno */
- &server_key))) {
+ errcode = get_first_current_key(kdc_context, server, &server_keyblock);
+ if (errcode) {
status = "FINDING_SERVER_KEY";
goto cleanup;
}
-
- /*
- * Convert server.key into a real key
- * (it may be encrypted in the database)
- */
- if ((errcode = krb5_dbe_decrypt_key_data(kdc_context, NULL,
- server_key, &server_keyblock,
- NULL))) {
- status = "DECRYPT_SERVER_KEY";
- goto cleanup;
- }
encrypting_key = &server_keyblock;
}
kau_u2u(kdc_context, TRUE, au_state);
st_idx++;
} else {
- ticket_kvno = server_key->key_data_kvno;
+ ticket_kvno = current_kvno(server);
}
errcode = krb5_encrypt_tkt_part(kdc_context, encrypting_key,
*key_out = NULL;
memset(&storage, 0, sizeof(storage));
- if (kvno == tgt->key_data[0].key_data_kvno) {
+ if (kvno == current_kvno(tgt)) {
/* Use the already-decrypted first key. */
key = tgt_key;
} else {
ret = k5_alloc_pa_data(KRB5_PADATA_FX_COOKIE, 8 + enc.ciphertext.length,
&pa);
memcpy(pa->contents, "MIT1", 4);
- store_32_be(local_tgt->key_data[0].key_data_kvno, pa->contents + 4);
+ store_32_be(current_kvno(local_tgt), pa->contents + 4);
memcpy(pa->contents + 8, enc.ciphertext.data, enc.ciphertext.length);
*cookie_out = pa;
{
krb5_error_code ret;
krb5_timestamp now;
- krb5_key_data *kd;
krb5_keyblock kb;
krb5_checksum cksum;
krb5_data d;
KRB5_PADATA_AS_FRESHNESS) == NULL)
return 0;
- /* Fetch and decrypt the current local krbtgt key. */
- ret = krb5_dbe_find_enctype(context, rock->local_tgt, -1, -1, 0, &kd);
- if (ret)
- goto cleanup;
- ret = krb5_dbe_decrypt_key_data(context, NULL, kd, &kb, NULL);
- if (ret)
- goto cleanup;
-
/* Compute a checksum over the current KDC time. */
ret = krb5_timeofday(context, &now);
if (ret)
goto cleanup;
store_32_be(now, ckbuf);
d = make_data(ckbuf, sizeof(ckbuf));
- ret = krb5_c_make_checksum(context, 0, &kb, KRB5_KEYUSAGE_PA_AS_FRESHNESS,
- &d, &cksum);
+ ret = krb5_c_make_checksum(context, 0, rock->local_tgt_key,
+ KRB5_KEYUSAGE_PA_AS_FRESHNESS, &d, &cksum);
/* Compose a freshness token from the time, krbtgt kvno, and checksum. */
ret = k5_alloc_pa_data(KRB5_PADATA_AS_FRESHNESS, 8 + cksum.length, &pa);
if (ret)
goto cleanup;
store_32_be(now, pa->contents);
- store_32_be(kd->key_data_kvno, pa->contents + 4);
+ store_32_be(current_kvno(rock->local_tgt), pa->contents + 4);
memcpy(pa->contents + 8, cksum.contents, cksum.length);
ret = k5_add_pa_data_element(pa_list, &pa);
return retval;
}
+/* Find the first key data entry (of a valid enctype) of the highest kvno in
+ * entry, and decrypt it into *key_out. */
+krb5_error_code
+get_first_current_key(krb5_context context, krb5_db_entry *entry,
+ krb5_keyblock *key_out)
+{
+ krb5_error_code ret;
+ krb5_key_data *kd;
+
+ memset(key_out, 0, sizeof(*key_out));
+ ret = krb5_dbe_find_enctype(context, entry, -1, -1, 0, &kd);
+ if (ret)
+ return ret;
+ return krb5_dbe_decrypt_key_data(context, NULL, kd, key_out, NULL);
+}
+
/*
* 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
krb5_error_code ret;
krb5_principal princ;
krb5_db_entry *storage = NULL, *tgt;
- krb5_key_data *kd;
*alias_out = NULL;
*storage_out = NULL;
tgt = candidate;
}
- /* Find and decrypt the first valid key of the current kvno. */
- ret = krb5_dbe_find_enctype(context, tgt, -1, -1, 0, &kd);
- if (ret)
- goto cleanup;
- ret = krb5_dbe_decrypt_key_data(context, NULL, kd, key_out, NULL);
+ ret = get_first_current_key(context, tgt, key_out);
if (ret)
goto cleanup;
krb5_boolean match_enctype,
krb5_db_entry **, krb5_keyblock **, krb5_kvno *);
+krb5_error_code
+get_first_current_key(krb5_context context, krb5_db_entry *entry,
+ krb5_keyblock *key_out);
+
krb5_error_code
get_local_tgt(krb5_context context, const krb5_data *realm,
krb5_db_entry *candidate, krb5_db_entry **alias_out,
krb5_data *inner_body;
krb5_db_entry *client;
krb5_db_entry *local_tgt;
+ krb5_keyblock *local_tgt_key;
krb5_key_data *client_key;
krb5_keyblock *client_keyblock;
struct kdc_request_state *rstate;
char *data2string(krb5_data *d);
+/* Return the current key version of entry, or 0 if it has no keys. */
+static inline krb5_kvno
+current_kvno(krb5_db_entry *entry)
+{
+ return (entry->n_key_data == 0) ? 0 : entry->key_data[0].key_data_kvno;
+}
+
#endif /* __KRB5_KDC_UTIL__ */