From 6bd0d822f59f21c60680141846861883413bb2df Mon Sep 17 00:00:00 2001 From: Chris Provenzano Date: Fri, 3 Nov 1995 10:15:09 +0000 Subject: [PATCH] * decrypt_key.c (krb5_dbekd_decrypt_key_data()) : If key salt length is 0 then set keysalt->data.data to NULL. * kdb_cpw.c (add_key_rnd(), add_key_pwd()) : When creating new keys for a new kvno and there are multiple enctypes that use a common keytype, then set the enctype in the key to the first specified enctype and skip all other enctypes that use the same keytype. (This assumes the salt type is the same too.) This way when the kdc needs to get the server key it doesn't need to gues what enctypes the server supports. * kdb_xdr.c (krb5_dbe_find_enctype()): Match keys that use common keytypes but different enctypes. Eg. ENCTYPE_DES_CBC_MD5 matches ENCTYPE_DES_CBC_CRC and vice versa. * kdb_xdr.c krb5_dbe_find_enctype()): If kvno = 0 then determine maxkvno for all the keys and then search keys for a key that matches enctype salttype and has kvno == maxkvno. This is different than when kvno = -1 which searches the keys for THE key with the greatest kvno which also matches enctype and salttype. * kdb_kdr.c (krb5_dbe_find_enctype()): If kvno = ktype = stype = -1 then set kvno = 0. The first doesn't make a lot of sense. * kdb_xdr.c (krb5_dbe_encode_last_pwd_change(), krb5_dbe_decode_last_pwd_change()) : Added. * kdb_xdr.c (krb5_decode_princ_contents()) : Don't try to allocate space for keys if n_key_data = 0. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@7012 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/kdb/ChangeLog | 28 +++++++++ src/lib/kdb/decrypt_key.c | 1 + src/lib/kdb/kdb_cpw.c | 91 +++++++++++++++++---------- src/lib/kdb/kdb_xdr.c | 125 +++++++++++++++++++++++++++++++++++--- 4 files changed, 205 insertions(+), 40 deletions(-) diff --git a/src/lib/kdb/ChangeLog b/src/lib/kdb/ChangeLog index 8ef46b836..15bdd684b 100644 --- a/src/lib/kdb/ChangeLog +++ b/src/lib/kdb/ChangeLog @@ -1,3 +1,31 @@ + +Fri Nov 03 04:49:58 1995 Chris Provenzano (proven@mit.edu) + + * decrypt_key.c (krb5_dbekd_decrypt_key_data()) : If key salt length + is 0 then set keysalt->data.data to NULL. + * kdb_cpw.c (add_key_rnd(), add_key_pwd()) : When creating new keys + for a new kvno and there are multiple enctypes that use a + common keytype, then set the enctype in the key to the first + specified enctype and skip all other enctypes that use + the same keytype. (This assumes the salt type is the same too.) + This way when the kdc needs to get the server key it doesn't + need to gues what enctypes the server supports. + * kdb_xdr.c (krb5_dbe_find_enctype()): Match keys that use common + keytypes but different enctypes. Eg. ENCTYPE_DES_CBC_MD5 + matches ENCTYPE_DES_CBC_CRC and vice versa. + * kdb_xdr.c krb5_dbe_find_enctype()): If kvno = 0 then determine + maxkvno for all the keys and then search keys for a key that + matches enctype salttype and has kvno == maxkvno. This + is different than when kvno = -1 which searches the keys + for THE key with the greatest kvno which also matches enctype + and salttype. + * kdb_kdr.c (krb5_dbe_find_enctype()): If kvno = ktype = stype = -1 + then set kvno = 0. The first doesn't make a lot of sense. + * kdb_xdr.c (krb5_dbe_encode_last_pwd_change(), + krb5_dbe_decode_last_pwd_change()) : Added. + * kdb_xdr.c (krb5_decode_princ_contents()) : Don't try to allocate + space for keys if n_key_data = 0. + Mon Sep 25 17:31:02 1995 Theodore Y. Ts'o * Makefile.in: Removed "foo:: foo-$(WHAT)" lines from the diff --git a/src/lib/kdb/decrypt_key.c b/src/lib/kdb/decrypt_key.c index 4f67d519e..32891098d 100644 --- a/src/lib/kdb/decrypt_key.c +++ b/src/lib/kdb/decrypt_key.c @@ -84,6 +84,7 @@ krb5_dbekd_decrypt_key_data(context, eblock, key_data, keyblock, keysalt) keysalt->data.data = (char *) NULL; } else { keysalt->type = KRB5_KDB_SALTTYPE_NORMAL; + keysalt->data.data = (char *) NULL; keysalt->data.length = 0; } } diff --git a/src/lib/kdb/kdb_cpw.c b/src/lib/kdb/kdb_cpw.c index 4b6dcd4ba..b88a97478 100644 --- a/src/lib/kdb/kdb_cpw.c +++ b/src/lib/kdb/kdb_cpw.c @@ -76,15 +76,16 @@ add_key_rnd(context, master_eblock, ks_tuple, ks_tuple_count, db_entry, kvno) int kvno; { krb5_principal krbtgt_princ; - krb5_keyblock krbtgt_keyblock, * key; + krb5_keyblock krbtgt_key, * key; krb5_pointer krbtgt_seed; krb5_encrypt_block krbtgt_eblock; krb5_db_entry krbtgt_entry; + krb5_key_data * krbtgt_kdata; krb5_boolean more, found; int max_kvno, one, i, j; krb5_error_code retval; - memset(&krbtgt_keyblock, 0, sizeof(krbtgt_keyblock)); + memset(&krbtgt_key, 0, sizeof(krbtgt_key)); retval = krb5_build_principal_ext(context, &krbtgt_princ, db_entry->princ->realm.length, db_entry->princ->realm.data, @@ -117,14 +118,33 @@ add_key_rnd(context, master_eblock, ks_tuple, ks_tuple_count, db_entry, kvno) } for (i = 0; i < ks_tuple_count; i++) { + krb5_enctype new_enctype, old_enctype; + + switch (new_enctype = ks_tuple[i].ks_enctype) { + case ENCTYPE_DES_CBC_MD4: + case ENCTYPE_DES_CBC_MD5: + case ENCTYPE_DES_CBC_RAW: + new_enctype = ENCTYPE_DES_CBC_CRC; + default: + break; + } + found = 0; + /* * We could use krb5_keysalt_iterate to replace this loop, or use * krb5_keysalt_is_present for the loop below, but we want to avoid * circular library dependencies. */ - found = 0; for (j = 0; j < i; j++) { - if (ks_tuple[j].ks_enctype == ks_tuple[i].ks_enctype) { + switch (old_enctype = ks_tuple[j].ks_enctype) { + case ENCTYPE_DES_CBC_MD4: + case ENCTYPE_DES_CBC_MD5: + case ENCTYPE_DES_CBC_RAW: + old_enctype = ENCTYPE_DES_CBC_CRC; + default: + break; + } + if (old_enctype == new_enctype) { found = 1; break; } @@ -134,35 +154,26 @@ add_key_rnd(context, master_eblock, ks_tuple, ks_tuple_count, db_entry, kvno) if (retval = krb5_dbe_create_key_data(context, db_entry)) goto add_key_rnd_err; - for (j = 0; j < krbtgt_entry.n_key_data; j++) { - if ((krbtgt_entry.key_data[j].key_data_kvno == max_kvno) && - (krbtgt_entry.key_data[j].key_data_type[0] == - ks_tuple[i].ks_enctype)) { - break; - } - } - - if (j == krbtgt_entry.n_key_data) { - retval = KRB5_KDB_BAD_ENCTYPE; + if (retval = krb5_dbe_find_enctype(context, &krbtgt_entry, + ks_tuple[i].ks_enctype, + -1, 0, &krbtgt_kdata)) goto add_key_rnd_err; - } /* Decrypt key */ if (retval = krb5_dbekd_decrypt_key_data(context, master_eblock, - &krbtgt_entry.key_data[j], - &krbtgt_keyblock, NULL)) { + krbtgt_kdata,&krbtgt_key,NULL)) goto add_key_rnd_err; - } /* Init key */ + krbtgt_key.enctype = ks_tuple[i].ks_enctype; krb5_use_enctype(context, &krbtgt_eblock, ks_tuple[i].ks_enctype); - if (retval = krb5_process_key(context,&krbtgt_eblock,&krbtgt_keyblock)){ + if (retval = krb5_process_key(context, &krbtgt_eblock, &krbtgt_key)) { goto add_key_rnd_err; } /* Init random generator */ if (retval = krb5_init_random_key(context, &krbtgt_eblock, - &krbtgt_keyblock, &krbtgt_seed)) { + &krbtgt_key, &krbtgt_seed)) { krb5_finish_key(context, &krbtgt_eblock); goto add_key_rnd_err; } @@ -189,9 +200,9 @@ add_key_rnd(context, master_eblock, ks_tuple, ks_tuple_count, db_entry, kvno) add_key_rnd_err:; krb5_db_free_principal(context, &krbtgt_entry, one); - if (krbtgt_keyblock.contents && krbtgt_keyblock.length) { - memset(krbtgt_keyblock.contents, 0, krbtgt_keyblock.length); - krb5_xfree(krbtgt_keyblock.contents); + if (krbtgt_key.contents && krbtgt_key.length) { + memset(krbtgt_key.contents, 0, krbtgt_key.length); + krb5_xfree(krbtgt_key.contents); } return(retval); } @@ -308,17 +319,35 @@ add_key_pwd(context, master_eblock, ks_tuple, ks_tuple_count, passwd, int i, j; for (i = 0; i < ks_tuple_count; i++) { + krb5_enctype new_enctype, old_enctype; + + switch (new_enctype = ks_tuple[i].ks_enctype) { + case ENCTYPE_DES_CBC_MD4: + case ENCTYPE_DES_CBC_MD5: + case ENCTYPE_DES_CBC_RAW: + new_enctype = ENCTYPE_DES_CBC_CRC; + default: + break; + } /* * We could use krb5_keysalt_iterate to replace this loop, or use * krb5_keysalt_is_present for the loop below, but we want to avoid * circular library dependencies. */ - found = 0; - for (j = 0; j < i; j++) { - if ((ks_tuple[j].ks_enctype == ks_tuple[i].ks_enctype) && - (ks_tuple[j].ks_salttype == ks_tuple[i].ks_salttype)) { - found = 1; - break; + for (found = j = 0; j < i; j++) { + if (ks_tuple[j].ks_salttype == ks_tuple[i].ks_salttype) { + switch (old_enctype = ks_tuple[j].ks_enctype) { + case ENCTYPE_DES_CBC_MD4: + case ENCTYPE_DES_CBC_MD5: + case ENCTYPE_DES_CBC_RAW: + old_enctype = ENCTYPE_DES_CBC_CRC; + default: + break; + } + if (old_enctype == new_enctype) { + found = 1; + break; + } } } if (found) @@ -360,8 +389,8 @@ add_key_pwd(context, master_eblock, ks_tuple, ks_tuple_count, passwd, pwd.data = passwd; pwd.length = strlen(passwd); if (retval = krb5_string_to_key(context, &key_eblock, - ks_tuple[i].ks_enctype, &key, - &pwd, &key_salt.data)) + ks_tuple[i].ks_enctype, + &key, &pwd, &key_salt.data)) return(retval); if (retval = krb5_dbekd_encrypt_key_data(context, master_eblock, &key, diff --git a/src/lib/kdb/kdb_xdr.c b/src/lib/kdb/kdb_xdr.c index c91af0880..dee44db0c 100644 --- a/src/lib/kdb/kdb_xdr.c +++ b/src/lib/kdb/kdb_xdr.c @@ -47,6 +47,71 @@ krb5_dbe_create_key_data(context, entry) return 0; } +krb5_error_code +krb5_dbe_encode_last_pwd_change(context, stamp, entry) + krb5_context context; + krb5_tl_last_change * stamp; + krb5_db_entry * entry; +{ + krb5_error_code retval; + krb5_tl_data ** tl_data; + krb5_octet * nextloc; + + /* Find any old versions and delete them. */ + for (tl_data = &(entry->tl_data); *tl_data; + tl_data = &((*tl_data)->tl_data_next)) { + if ((*tl_data)->tl_data_type == KRB5_TL_LAST_PWD_CHANGE) { + break; + } + } + + if ((*tl_data) || + /* Only zero data if it is freshly allocated */ + ((*tl_data) = (krb5_tl_data *)calloc(1, sizeof(krb5_tl_data)))) { + if (!(*tl_data)->tl_data_type) { + if ((nextloc = (*tl_data)->tl_data_contents = + (krb5_octet *)malloc(sizeof(krb5_timestamp))) == NULL) { + krb5_xfree(*tl_data); + (*tl_data) = NULL; + return ENOMEM; + } + (*tl_data)->tl_data_type = KRB5_TL_LAST_PWD_CHANGE; + (*tl_data)->tl_data_length = sizeof(krb5_timestamp); + entry->n_tl_data++; + } + + *nextloc++ = (krb5_octet)(stamp->last_pwd_change & 0xff); + *nextloc++ = (krb5_octet)((stamp->last_pwd_change >> 8) & 0xff); + *nextloc++ = (krb5_octet)((stamp->last_pwd_change >> 16) & 0xff); + *nextloc++ = (krb5_octet)((stamp->last_pwd_change >> 24) & 0xff); + + return 0; + } + return ENOMEM; +} + +krb5_error_code +krb5_dbe_decode_last_pwd_change(context, entry, stamp) + krb5_context context; + krb5_db_entry * entry; + krb5_tl_last_change * stamp; +{ + krb5_tl_data * tl_data; + + for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) { + if (tl_data->tl_data_type == KRB5_TL_LAST_PWD_CHANGE) { + krb5_octet * nextloc = tl_data->tl_data_contents; + + stamp->last_pwd_change = *nextloc++; + stamp->last_pwd_change += (*nextloc++ << 8); + stamp->last_pwd_change += (*nextloc++ << 16); + stamp->last_pwd_change += (*nextloc++ << 24); + return 0; + } + } + stamp->last_pwd_change = 0; +} + krb5_error_code krb5_dbe_encode_mod_princ_data(context, mod_princ, entry) krb5_context context; @@ -527,8 +592,8 @@ krb5_decode_princ_contents(context, content, entry) } /* key_data is an array */ - if ((entry->key_data = (krb5_key_data *) - malloc(sizeof(krb5_key_data) * entry->n_key_data)) == NULL) { + if (entry->n_key_data && ((entry->key_data = (krb5_key_data *) + malloc(sizeof(krb5_key_data) * entry->n_key_data)) == NULL)) { retval = ENOMEM; goto error_out; } @@ -631,6 +696,8 @@ krb5_dbe_free_contents(context, entry) * most appropriate krb5_key_data entry of the database entry. * * If stype or kvno is negative, it is ignored. + * If kvno is 0 get the key which is maxkvno for the princ and matches + * the other attributes. */ krb5_error_code krb5_dbe_find_enctype(kcontext, dbentp, ktype, stype, kvno, kdatap) @@ -645,20 +712,60 @@ krb5_dbe_find_enctype(kcontext, dbentp, ktype, stype, kvno, kdatap) int maxkvno; krb5_key_data *datap; + if (kvno == stype == ktype == -1) + kvno = 0; + + if (kvno == 0) { + /* Get the max key version */ + for (i = 0; i < dbentp->n_key_data; i++) { + if (kvno < dbentp->key_data[i].key_data_kvno) { + kvno = dbentp->key_data[i].key_data_kvno; + } + } + } + + /* + * ENCTYPE_DES_CBC_CRC, ENCTYPE_DES_CBC_MD4, ENCTYPE_DES_CBC_MD5, + * ENCTYPE_DES_CBC_RAW all use the same key. + */ + switch (ktype) { + case ENCTYPE_DES_CBC_MD4: + case ENCTYPE_DES_CBC_MD5: + case ENCTYPE_DES_CBC_RAW: + ktype = ENCTYPE_DES_CBC_CRC; + break; + default: + break; + } + maxkvno = -1; datap = (krb5_key_data *) NULL; - for (i=0; in_key_data; i++) { - if (((krb5_enctype) dbentp->key_data[i].key_data_type[0]) == ktype && - ((dbentp->key_data[i].key_data_type[1] == stype) || - (stype < 0))) { + for (i = 0; i < dbentp->n_key_data; i++) { + krb5_enctype db_ktype; + krb5_int32 db_stype; + + switch (db_ktype = dbentp->key_data[i].key_data_type[0]) { + case ENCTYPE_DES_CBC_MD4: + case ENCTYPE_DES_CBC_MD5: + case ENCTYPE_DES_CBC_RAW: + db_ktype = ENCTYPE_DES_CBC_CRC; + defualt: + break; + } + if (dbentp->key_data[i].key_data_ver > 1) { + db_stype = dbentp->key_data[i].key_data_type[1]; + } else { + db_stype = KRB5_KDB_SALTTYPE_NORMAL; + } + if (((db_ktype == ktype) || (ktype < 0)) && + ((db_stype == stype) || (stype < 0))) { if (kvno >= 0) { if (kvno == dbentp->key_data[i].key_data_kvno) { - maxkvno = kvno; datap = &dbentp->key_data[i]; + maxkvno = kvno; break; } - } - else { + } else { if (dbentp->key_data[i].key_data_kvno > maxkvno) { maxkvno = dbentp->key_data[i].key_data_kvno; datap = &dbentp->key_data[i]; -- 2.26.2