* decrypt_key.c (krb5_dbekd_decrypt_key_data()) : If key salt length
authorChris Provenzano <proven@mit.edu>
Fri, 3 Nov 1995 10:15:09 +0000 (10:15 +0000)
committerChris Provenzano <proven@mit.edu>
Fri, 3 Nov 1995 10:15:09 +0000 (10:15 +0000)
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
src/lib/kdb/decrypt_key.c
src/lib/kdb/kdb_cpw.c
src/lib/kdb/kdb_xdr.c

index 8ef46b836f227d100e6ca9f9d088a81de8fe18d9..15bdd684bc24257a1fdc9448f164c7b580d75e61 100644 (file)
@@ -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  <tytso@dcl>
 
        * Makefile.in: Removed "foo:: foo-$(WHAT)" lines from the
index 4f67d519ee8193e6ca60a0ad7494ea8962b0c0d9..32891098d454f7ad387c52b0ad7916cd94c12ed6 100644 (file)
@@ -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;
        }
     }
index 4b6dcd4ba976e5f5c4a11b290a16beb4cf281d65..b88a974782457c1ea996458bc1a33632f9558523 100644 (file)
@@ -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,
index c91af0880d9e65a6fa9a7531a5f73e34d92152f1..dee44db0cb32d95d49764d4c38281eb02a837f38 100644 (file)
@@ -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; i<dbentp->n_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];