summaryrefslogtreecommitdiffstats
path: root/src/kdc
diff options
context:
space:
mode:
Diffstat (limited to 'src/kdc')
-rw-r--r--src/kdc/do_as_req.c44
-rw-r--r--src/kdc/do_tgs_req.c24
-rw-r--r--src/kdc/extern.c1
-rw-r--r--src/kdc/extern.h6
-rw-r--r--src/kdc/kdc_preauth.c88
-rw-r--r--src/kdc/kdc_util.c22
-rw-r--r--src/kdc/main.c23
7 files changed, 194 insertions, 14 deletions
diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c
index 9571fb212..8db39ac4f 100644
--- a/src/kdc/do_as_req.c
+++ b/src/kdc/do_as_req.c
@@ -104,6 +104,7 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
const char *status;
krb5_key_data *server_key, *client_key;
krb5_keyblock server_keyblock, client_keyblock;
+ krb5_keyblock *mkey_ptr;
krb5_enctype useenctype;
krb5_boolean update_client = 0;
krb5_data e_data;
@@ -115,6 +116,7 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
void *pa_context = NULL;
int did_log = 0;
const char *emsg = 0;
+ krb5_keylist_node *tmp_mkey_list;
#if APPLE_PKINIT
asReqDebug("process_as_req top realm %s name %s\n",
@@ -425,9 +427,28 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
goto errout;
}
+ if ((errcode = krb5_dbe_find_mkey(kdc_context, master_keylist, &server,
+ &mkey_ptr))) {
+ /* try refreshing master key list */
+ /* XXX it would nice if we had the mkvno here for optimization */
+ if (krb5_db_fetch_mkey_list(kdc_context, master_princ,
+ &master_keyblock, 0, &tmp_mkey_list) == 0) {
+ krb5_dbe_free_key_list(kdc_context, master_keylist);
+ master_keylist = tmp_mkey_list;
+ if ((errcode = krb5_dbe_find_mkey(kdc_context, master_keylist,
+ &server, &mkey_ptr))) {
+ status = "FINDING_MASTER_KEY";
+ goto errout;
+ }
+ } else {
+ status = "FINDING_MASTER_KEY";
+ goto errout;
+ }
+ }
+
/* convert server.key into a real key (it may be encrypted
in the database) */
- if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, &master_keyblock,
+ if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, mkey_ptr,
/* server_keyblock is later used to generate auth data signatures */
server_key, &server_keyblock,
NULL))) {
@@ -456,8 +477,27 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
goto errout;
}
+ if ((errcode = krb5_dbe_find_mkey(kdc_context, master_keylist, &client,
+ &mkey_ptr))) {
+ /* try refreshing master key list */
+ /* XXX it would nice if we had the mkvno here for optimization */
+ if (krb5_db_fetch_mkey_list(kdc_context, master_princ,
+ &master_keyblock, 0, &tmp_mkey_list) == 0) {
+ krb5_dbe_free_key_list(kdc_context, master_keylist);
+ master_keylist = tmp_mkey_list;
+ if ((errcode = krb5_dbe_find_mkey(kdc_context, master_keylist,
+ &client, &mkey_ptr))) {
+ status = "FINDING_MASTER_KEY";
+ goto errout;
+ }
+ } else {
+ status = "FINDING_MASTER_KEY";
+ goto errout;
+ }
+ }
+
/* convert client.key_data into a real key */
- if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, &master_keyblock,
+ if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context, mkey_ptr,
client_key, &client_keyblock,
NULL))) {
status = "DECRYPT_CLIENT_KEY";
diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
index 084300256..a6ce704bd 100644
--- a/src/kdc/do_tgs_req.c
+++ b/src/kdc/do_tgs_req.c
@@ -105,6 +105,7 @@ process_tgs_req(krb5_data *pkt, const krb5_fulladdr *from,
krb5_keyblock session_key;
krb5_timestamp until, rtime;
krb5_keyblock encrypting_key;
+ krb5_keyblock *mkey_ptr;
krb5_key_data *server_key;
char *cname = 0, *sname = 0, *altcname = 0;
krb5_last_req_entry *nolrarray[2], nolrentry;
@@ -572,10 +573,31 @@ tgt_again:
status = "FINDING_SERVER_KEY";
goto cleanup;
}
+
+ if ((errcode = krb5_dbe_find_mkey(kdc_context, master_keylist, &server,
+ &mkey_ptr))) {
+ krb5_keylist_node *tmp_mkey_list;
+ /* try refreshing master key list */
+ /* XXX it would nice if we had the mkvno here for optimization */
+ if (krb5_db_fetch_mkey_list(kdc_context, master_princ,
+ &master_keyblock, 0, &tmp_mkey_list) == 0) {
+ krb5_dbe_free_key_list(kdc_context, master_keylist);
+ master_keylist = tmp_mkey_list;
+ if ((errcode = krb5_dbe_find_mkey(kdc_context, master_keylist,
+ &server, &mkey_ptr))) {
+ status = "FINDING_MASTER_KEY";
+ goto cleanup;
+ }
+ } else {
+ status = "FINDING_MASTER_KEY";
+ goto cleanup;
+ }
+ }
+
/* convert server.key into a real key (it may be encrypted
* in the database) */
if ((errcode = krb5_dbekd_decrypt_key_data(kdc_context,
- &master_keyblock,
+ mkey_ptr,
server_key, &encrypting_key,
NULL))) {
status = "DECRYPT_SERVER_KEY";
diff --git a/src/kdc/extern.c b/src/kdc/extern.c
index 2a2c1ae22..7ebc7bb3a 100644
--- a/src/kdc/extern.c
+++ b/src/kdc/extern.c
@@ -27,6 +27,7 @@
*/
#include "k5-int.h"
+#include "kdb.h"
#include "extern.h"
/* real declarations of KDC's externs */
diff --git a/src/kdc/extern.h b/src/kdc/extern.h
index 20cc4bc04..88e8b0dde 100644
--- a/src/kdc/extern.h
+++ b/src/kdc/extern.h
@@ -53,7 +53,12 @@ typedef struct __kdc_realm_data {
char * realm_stash; /* Stash file name for realm */
char * realm_mpname; /* Master principal name for realm */
krb5_principal realm_mprinc; /* Master principal for realm */
+ /*
+ * Note realm_mkey is mkey read from stash or keyboard and may not be the
+ * latest. The mkey_list will have all the mkeys in use.
+ */
krb5_keyblock realm_mkey; /* Master key for this realm */
+ krb5_keylist_node * mkey_list; /* list of mkeys in use for this realm */
/*
* TGS per-realm data.
*/
@@ -86,6 +91,7 @@ kdc_realm_t *find_realm_data (char *, krb5_ui_4);
#define max_life_for_realm kdc_active_realm->realm_maxlife
#define max_renewable_life_for_realm kdc_active_realm->realm_maxrlife
#define master_keyblock kdc_active_realm->realm_mkey
+#define master_keylist kdc_active_realm->mkey_list
#define master_princ kdc_active_realm->realm_mprinc
#define tgs_server kdc_active_realm->realm_tgsprinc
#define reject_bad_transit kdc_active_realm->realm_reject_bad_transit
diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c
index 6ec156440..7aacca402 100644
--- a/src/kdc/kdc_preauth.c
+++ b/src/kdc/kdc_preauth.c
@@ -665,8 +665,9 @@ get_entry_data(krb5_context context,
int i, k;
krb5_data *ret;
krb5_deltat *delta;
- krb5_keyblock *keys;
+ krb5_keyblock *keys, *mkey_ptr;
krb5_key_data *entry_key;
+ krb5_error_code error;
switch (type) {
case krb5plugin_preauth_entry_request_certificate:
@@ -700,13 +701,32 @@ get_entry_data(krb5_context context,
ret->data = (char *) keys;
ret->length = sizeof(krb5_keyblock) * (request->nktypes + 1);
memset(ret->data, 0, ret->length);
+ if ((error = krb5_dbe_find_mkey(context, master_keylist, entry,
+ &mkey_ptr))) {
+ krb5_keylist_node *tmp_mkey_list;
+ /* try refreshing the mkey list in case it's been updated */
+ if (krb5_db_fetch_mkey_list(context, master_princ,
+ &master_keyblock, 0,
+ &tmp_mkey_list) == 0) {
+ krb5_dbe_free_key_list(context, master_keylist);
+ master_keylist = tmp_mkey_list;
+ if ((error = krb5_dbe_find_mkey(context, master_keylist, entry,
+ &mkey_ptr))) {
+ free(ret);
+ return (error);
+ }
+ } else {
+ free(ret);
+ return (error);
+ }
+ }
k = 0;
for (i = 0; i < request->nktypes; i++) {
entry_key = NULL;
if (krb5_dbe_find_enctype(context, entry, request->ktype[i],
-1, 0, &entry_key) != 0)
continue;
- if (krb5_dbekd_decrypt_key_data(context, &master_keyblock,
+ if (krb5_dbekd_decrypt_key_data(context, mkey_ptr,
entry_key, &keys[k], NULL) != 0) {
if (keys[k].contents != NULL)
krb5_free_keyblock_contents(context, &keys[k]);
@@ -1337,7 +1357,7 @@ verify_enc_timestamp(krb5_context context, krb5_db_entry *client,
krb5_data scratch;
krb5_data enc_ts_data;
krb5_enc_data *enc_data = 0;
- krb5_keyblock key;
+ krb5_keyblock key, *mkey_ptr;
krb5_key_data * client_key;
krb5_int32 start;
krb5_timestamp timenow;
@@ -1355,6 +1375,24 @@ verify_enc_timestamp(krb5_context context, krb5_db_entry *client,
if ((enc_ts_data.data = (char *) malloc(enc_ts_data.length)) == NULL)
goto cleanup;
+ if ((retval = krb5_dbe_find_mkey(context, master_keylist, client,
+ &mkey_ptr))) {
+ krb5_keylist_node *tmp_mkey_list;
+ /* try refreshing the mkey list in case it's been updated */
+ if (krb5_db_fetch_mkey_list(context, master_princ,
+ &master_keyblock, 0,
+ &tmp_mkey_list) == 0) {
+ krb5_dbe_free_key_list(context, master_keylist);
+ master_keylist = tmp_mkey_list;
+ if ((retval = krb5_dbe_find_mkey(context, master_keylist, client,
+ &mkey_ptr))) {
+ goto cleanup;
+ }
+ } else {
+ goto cleanup;
+ }
+ }
+
start = 0;
decrypt_err = 0;
while (1) {
@@ -1363,7 +1401,7 @@ verify_enc_timestamp(krb5_context context, krb5_db_entry *client,
-1, 0, &client_key)))
goto cleanup;
- if ((retval = krb5_dbekd_decrypt_key_data(context, &master_keyblock,
+ if ((retval = krb5_dbekd_decrypt_key_data(context, mkey_ptr,
client_key, &key, NULL)))
goto cleanup;
@@ -1946,7 +1984,7 @@ get_sam_edata(krb5_context context, krb5_kdc_req *request,
krb5_sam_challenge sc;
krb5_predicted_sam_response psr;
krb5_data * scratch;
- krb5_keyblock encrypting_key;
+ krb5_keyblock encrypting_key, *mkey_ptr;
char response[9];
char inputblock[8];
krb5_data predict_response;
@@ -2010,6 +2048,24 @@ get_sam_edata(krb5_context context, krb5_kdc_req *request,
if (sc.sam_type) {
/* so use assoc to get the key out! */
{
+ if ((retval = krb5_dbe_find_mkey(context, master_keylist, &assoc,
+ &mkey_ptr))) {
+ krb5_keylist_node *tmp_mkey_list;
+ /* try refreshing the mkey list in case it's been updated */
+ if (krb5_db_fetch_mkey_list(context, master_princ,
+ &master_keyblock, 0,
+ &tmp_mkey_list) == 0) {
+ krb5_dbe_free_key_list(context, master_keylist);
+ master_keylist = tmp_mkey_list;
+ if ((retval = krb5_dbe_find_mkey(context, master_keylist, &assoc,
+ &mkey_ptr))) {
+ return (retval);
+ }
+ } else {
+ return (retval);
+ }
+ }
+
/* here's what do_tgs_req does */
retval = krb5_dbe_find_enctype(kdc_context, &assoc,
ENCTYPE_DES_CBC_RAW,
@@ -2026,7 +2082,7 @@ get_sam_edata(krb5_context context, krb5_kdc_req *request,
}
/* convert server.key into a real key */
retval = krb5_dbekd_decrypt_key_data(kdc_context,
- &master_keyblock,
+ mkey_ptr,
assoc_key, &encrypting_key,
NULL);
if (retval) {
@@ -2513,7 +2569,7 @@ static krb5_error_code verify_pkinit_request(
unsigned cert_hash_len;
unsigned key_dex;
unsigned cert_match = 0;
- krb5_keyblock decrypted_key;
+ krb5_keyblock decrypted_key, *mkey_ptr;
/* the data we get from the AS-REQ */
krb5_timestamp client_ctime = 0;
@@ -2657,6 +2713,22 @@ static krb5_error_code verify_pkinit_request(
goto cleanup;
}
cert_hash_len = strlen(cert_hash);
+ if ((krtn = krb5_dbe_find_mkey(context, master_keylist, &entry, &mkey_ptr))) {
+ krb5_keylist_node *tmp_mkey_list;
+ /* try refreshing the mkey list in case it's been updated */
+ if (krb5_db_fetch_mkey_list(context, master_princ,
+ &master_keyblock, 0,
+ &tmp_mkey_list) == 0) {
+ krb5_dbe_free_key_list(context, master_keylist);
+ master_keylist = tmp_mkey_list;
+ if ((krtn = krb5_dbe_find_mkey(context, master_keylist, &entry,
+ &mkey_ptr))) {
+ goto cleanup;
+ }
+ } else {
+ goto cleanup;
+ }
+ }
for(key_dex=0; key_dex<client->n_key_data; key_dex++) {
krb5_key_data *key_data = &client->key_data[key_dex];
kdcPkinitDebug("--- key %u type[0] %u length[0] %u type[1] %u length[1] %u\n",
@@ -2671,7 +2743,7 @@ static krb5_error_code verify_pkinit_request(
* Unfortunately this key is stored encrypted even though it's
* not sensitive...
*/
- krtn = krb5_dbekd_decrypt_key_data(context, &master_keyblock,
+ krtn = krb5_dbekd_decrypt_key_data(context, mkey_ptr,
key_data, &decrypted_key, NULL);
if(krtn) {
kdcPkinitDebug("verify_pkinit_request: error decrypting cert hash block\n");
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index 34a8ed0c3..28b4a37ca 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -415,6 +415,7 @@ kdc_get_server_key(krb5_ticket *ticket, unsigned int flags,
krb5_error_code retval;
krb5_boolean more, similar;
krb5_key_data * server_key;
+ krb5_keyblock * mkey_ptr;
*nprincs = 1;
@@ -445,6 +446,25 @@ kdc_get_server_key(krb5_ticket *ticket, unsigned int flags,
retval = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
goto errout;
}
+
+ if ((retval = krb5_dbe_find_mkey(kdc_context, master_keylist, server,
+ &mkey_ptr))) {
+ krb5_keylist_node *tmp_mkey_list;
+ /* try refreshing master key list */
+ /* XXX it would nice if we had the mkvno here for optimization */
+ if (krb5_db_fetch_mkey_list(kdc_context, master_princ,
+ &master_keyblock, 0, &tmp_mkey_list) == 0) {
+ krb5_dbe_free_key_list(kdc_context, master_keylist);
+ master_keylist = tmp_mkey_list;
+ if ((retval = krb5_dbe_find_mkey(kdc_context, master_keylist,
+ server, &mkey_ptr))) {
+ goto errout;
+ }
+ } else {
+ goto errout;
+ }
+ }
+
retval = krb5_dbe_find_enctype(kdc_context, server,
match_enctype ? ticket->enc_part.enctype : -1,
-1, (krb5_int32)ticket->enc_part.kvno,
@@ -456,7 +476,7 @@ kdc_get_server_key(krb5_ticket *ticket, unsigned int flags,
goto errout;
}
if ((*key = (krb5_keyblock *)malloc(sizeof **key))) {
- retval = krb5_dbekd_decrypt_key_data(kdc_context, &master_keyblock,
+ retval = krb5_dbekd_decrypt_key_data(kdc_context, mkey_ptr,
server_key,
*key, NULL);
} else
diff --git a/src/kdc/main.c b/src/kdc/main.c
index b9334680b..bb4d7584d 100644
--- a/src/kdc/main.c
+++ b/src/kdc/main.c
@@ -154,9 +154,12 @@ finish_realm(kdc_realm_t *rdp)
if (rdp->realm_mprinc)
krb5_free_principal(rdp->realm_context, rdp->realm_mprinc);
if (rdp->realm_mkey.length && rdp->realm_mkey.contents) {
+ /* XXX shouldn't memset be zap for safety? */
memset(rdp->realm_mkey.contents, 0, rdp->realm_mkey.length);
free(rdp->realm_mkey.contents);
}
+ if (rdp->mkey_list)
+ krb5_dbe_free_key_list(rdp->realm_context, rdp->mkey_list);
krb5_db_fini(rdp->realm_context);
if (rdp->realm_tgsprinc)
krb5_free_principal(rdp->realm_context, rdp->realm_tgsprinc);
@@ -242,6 +245,7 @@ init_realm(char *progname, kdc_realm_t *rdp, char *realm,
krb5_boolean manual;
krb5_realm_params *rparams;
int kdb_open_flags;
+ krb5_kvno mkvno = IGNORE_VNO;
memset((char *) rdp, 0, sizeof(kdc_realm_t));
if (!realm) {
@@ -374,18 +378,25 @@ init_realm(char *progname, kdc_realm_t *rdp, char *realm,
}
/*
- * Get the master key.
+ * Get the master key (note, may not be the most current mkey).
*/
if ((kret = krb5_db_fetch_mkey(rdp->realm_context, rdp->realm_mprinc,
rdp->realm_mkey.enctype, manual,
FALSE, rdp->realm_stash,
- NULL, NULL, &rdp->realm_mkey))) {
+ &mkvno, NULL, &rdp->realm_mkey))) {
com_err(progname, kret,
"while fetching master key %s for realm %s",
rdp->realm_mpname, realm);
goto whoops;
}
+#if 0 /************** Begin IFDEF'ed OUT *******************************/
+ /*
+ * Commenting krb5_db_verify_master_key out because it requires the most
+ * current mkey which may not be the case here. The call to
+ * krb5_db_fetch_mkey_list() will end up verifying that the mkey is viable
+ * anyway.
+ */
/* Verify the master key */
if ((kret = krb5_db_verify_master_key(rdp->realm_context,
rdp->realm_mprinc,
@@ -395,6 +406,14 @@ init_realm(char *progname, kdc_realm_t *rdp, char *realm,
"while verifying master key for realm %s", realm);
goto whoops;
}
+#endif /**************** END IFDEF'ed OUT *******************************/
+
+ if ((kret = krb5_db_fetch_mkey_list(rdp->realm_context, rdp->realm_mprinc,
+ &rdp->realm_mkey, mkvno, &rdp->mkey_list))) {
+ com_err(progname, kret,
+ "while fetching master keys list for realm %s", realm);
+ goto whoops;
+ }
if ((kret = krb5_db_set_mkey(rdp->realm_context, &rdp->realm_mkey))) {
com_err(progname, kret,