* decrypt_key.c, encrypt_key.c, kdb_dbm.c, kdb_xdr.c:
authorChris Provenzano <proven@mit.edu>
Thu, 27 Jul 1995 08:44:02 +0000 (08:44 +0000)
committerChris Provenzano <proven@mit.edu>
Thu, 27 Jul 1995 08:44:02 +0000 (08:44 +0000)
Rewritten for new kdb format.
* kdb_cpw.c : New password changing routines for new kdb format.
* verify_mky.c, t_kdb.c : Use new kdb format.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@6328 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/kdb/ChangeLog
src/lib/kdb/Makefile.in
src/lib/kdb/decrypt_key.c
src/lib/kdb/encrypt_key.c
src/lib/kdb/kdb_cpw.c [new file with mode: 0644]
src/lib/kdb/kdb_dbm.c
src/lib/kdb/kdb_xdr.c [new file with mode: 0644]
src/lib/kdb/t_kdb.c
src/lib/kdb/verify_mky.c

index fcebad85d74ccb86c2ad405be0eb8e46268d0128..5cb3bf91449d09e0633e51f024f911e5f0f7c97f 100644 (file)
@@ -1,3 +1,11 @@
+
+Thu Jul 27 02:59:05 1995        Chris Provenzano (proven@mit.edu)
+        * decrypt_key.c, encrypt_key.c, kdb_dbm.c, kdb_xdr.c:
+               Rewritten for new kdb format.
+       * kdb_cpw.c : New password changing routines for new kdb format.
+       * verify_mky.c, t_kdb.c : Use new kdb format.
+
+
 Tue Jul 25 14:06:50 1995  Tom Yu  <tlyu@lothlorien.MIT.EDU>
 
        * kdb_dbm.c, t_kdb.c: Add prototype for dbm_error and dbm_clearerr
index afb8fe31e7c56a860e0da2cded66bf0b3b1cf697..fad482eecbfc17608588cbb460b7a9d58f215217 100644 (file)
@@ -8,6 +8,7 @@ SRCS= \
        $(srcdir)/encrypt_key.c \
        $(srcdir)/decrypt_key.c \
        $(srcdir)/kdb_dbm.c \
+       $(srcdir)/kdb_xdr.c \
        $(srcdir)/verify_mky.c \
        $(srcdir)/fetch_mkey.c \
        $(srcdir)/setup_mkey.c \
@@ -17,6 +18,7 @@ OBJS= \
        encrypt_key.o \
        decrypt_key.o \
        kdb_dbm.o \
+       kdb_xdr.o \
        verify_mky.o \
        fetch_mkey.o \
        setup_mkey.o \
index cb901b677c69fb64955ce8780436baf1988a0171..cc0503f8f85bbf3a36b54a9f37d9fa62f01cf7c4 100644 (file)
  */
 
 krb5_error_code
-krb5_kdb_decrypt_key(context, eblock, in, out)
-    krb5_context context;
-    krb5_encrypt_block *eblock;
-    const krb5_encrypted_keyblock *in;
-    krb5_keyblock *out;
+krb5_dbekd_decrypt_key_data(context, eblock, key_data, keyblock, keysalt)
+    krb5_context         context;
+    krb5_encrypt_block         * eblock;
+    const krb5_key_data        * key_data;
+    krb5_keyblock      * keyblock;
+    krb5_keysalt       * keysalt;
 {
-    krb5_error_code retval;
+    krb5_error_code      retval;
+    krb5_octet         * ptr;
 
-    /* the encrypted version is stored as the unencrypted key length
-       (4 bytes, MSB first) followed by the encrypted key. */
-    out->magic = KV5M_KEYBLOCK;
-    out->etype = ETYPE_UNKNOWN;
-    out->keytype = in->keytype;
-    out->length = krb5_encrypt_size(in->length-sizeof(in->length),
-                                   eblock->crypto_entry);
-    out->contents = (krb5_octet *)malloc(out->length);
-    if (!out->contents) {
-       out->contents = 0;
-       out->length = 0;
-       return ENOMEM;
-    }
+    keyblock->magic = KV5M_KEYBLOCK;
+    keyblock->etype = ETYPE_UNKNOWN;
+    keyblock->keytype = key_data->key_data_type[0];
 
-    /* copy out the real length count */
-    out->length  = (((unsigned char *)in->contents)[0] << 24)
-                + (((unsigned char *)in->contents)[1] << 16)
-                + (((unsigned char *)in->contents)[2] << 8)
-                +  ((unsigned char *)in->contents)[3];
+    /* Decrypt key_data_contents */
+    if ((keyblock->contents = (krb5_octet *)malloc(krb5_encrypt_size(
+      key_data->key_data_length[0] - 2, eblock->crypto_entry))) == NULL)
+       return ENOMEM;
 
-    /* remember the contents of the encrypted version has a 4 byte
-       integer length of the real embedded key, followed by the
-       encrypted key, so the offset here is needed */
-    if (retval = krb5_decrypt(context, (krb5_pointer) (
-                             (char *) in->contents + 4),
-                             (krb5_pointer) out->contents,
-                             in->length-sizeof(in->length), eblock, 0)) {
-       krb5_xfree(out->contents);
-       out->contents = 0;
-       out->length = 0;
+    keyblock->length = 0;
+    ptr = key_data->key_data_contents[0];
+    *(((krb5_octet *)(&keyblock->length))) = *ptr++;
+    *(((krb5_octet *)(&keyblock->length)) + 1) = *ptr++;
+    if (retval = krb5_decrypt(context, (krb5_pointer) ptr,
+                             (krb5_pointer)keyblock->contents,
+                             key_data->key_data_length[0] - 2, 
+                             eblock, 0)) {
+       krb5_xfree(keyblock->contents);
        return retval;
     }
-    if (out->length < 0) {
-       krb5_xfree(out->contents);
-       out->contents = 0;
-       out->length = 0;
-       return KRB5_KDB_INVALIDKEYSIZE;
+
+    /* Decode salt data */
+    if (keysalt) {
+       if (key_data->key_data_ver == 2) {
+           keysalt->type = key_data->key_data_type[1];
+           keysalt->data.length = key_data->key_data_length[1];
+           if (!(keysalt->data.data = (krb5_octet *)malloc(keysalt->data.length))){
+               krb5_xfree(keyblock->contents);
+               return ENOMEM;
+           }
+       } else {
+           keysalt->type = KRB5_KDB_SALTTYPE_NORMAL;
+           keysalt->data.length = 0;
+       }
     }
     return retval;
 }
index 277983e345b673c2222a97daa59ea4413179e4af..272280a00923193d5ab980874b32830b5dda1d19 100644 (file)
  */
 
 krb5_error_code
-krb5_kdb_encrypt_key(context, eblock, in, out)
-    krb5_context context;
-    krb5_encrypt_block *eblock;
-    const krb5_keyblock *in;
-    register krb5_encrypted_keyblock *out;
+krb5_dbekd_encrypt_key_data(context, eblock, keyblock, keysalt, keyver,key_data)
+    krb5_context                 context;
+    krb5_encrypt_block                 * eblock;
+    const krb5_keyblock        * keyblock;
+    const krb5_keysalt         * keysalt;
+    int                                  keyver;
+    krb5_key_data              * key_data;
 {
-    /* Encrypted rep has the real (unencrypted) key length stored
-       along with the encrypted key.  The length is stored as a 4
-       byte integer, MSB first.  */
+    krb5_error_code              retval;
+    krb5_keyblock                tmp;
+    krb5_octet                 * ptr;
+    krb5_int16                   len;
+    int                                  i;
 
-    krb5_error_code retval;
-    krb5_keyblock tmpin;
-    unsigned int length;
+    for (i = 0; i < key_data->key_data_ver; i++)
+       if (key_data->key_data_contents[i])
+           krb5_xfree(key_data->key_data_contents[i]);
 
-    out->keytype = in->keytype;
-    out->length = krb5_encrypt_size(in->length, eblock->crypto_entry);
+    key_data->key_data_ver = 1;
+    key_data->key_data_kvno = keyver;
 
-    /* because of checksum space requirements imposed by the encryption
-       interface, we need to copy the input key into a larger area. */
-    tmpin.length = in->length;
-    tmpin.contents = (krb5_octet *)malloc(out->length);
-    if (!tmpin.contents) {
-       out->length = 0;
+    /* 
+     * The First element of the type/length/contents 
+     * fields is the key type/length/contents
+     */
+    key_data->key_data_type[0] = keyblock->keytype;
+    key_data->key_data_length[0] = krb5_encrypt_size(keyblock->length, 
+                                                    eblock->crypto_entry) + 2;
+
+    /* 
+     * because of checksum space requirements imposed by the encryption
+     * interface, we need to copy the input key into a larger area. 
+     */
+    tmp.contents = (krb5_octet *)malloc(key_data->key_data_length[0] - 2);
+    len = tmp.length = keyblock->length;
+    if (tmp.contents == NULL)
        return ENOMEM;
-    }
-    memcpy((char *)tmpin.contents, (const char *)in->contents, tmpin.length);
 
-    out->length += sizeof(out->length);
-    out->contents = (krb5_octet *)malloc(out->length);
-    if (!out->contents) {
-       krb5_xfree(tmpin.contents);
-       out->contents = 0;
-       out->length = 0;
+    memcpy((char *)tmp.contents, (const char *)keyblock->contents, tmp.length);
+    key_data->key_data_contents[0] = ptr = (krb5_octet *)malloc(
+                                       key_data->key_data_length[0] - 2);
+    if (key_data->key_data_contents[0] == NULL) {
+       krb5_xfree(tmp.contents);
        return ENOMEM;
     }
 
-    length = tmpin.length;
-    ((char *)out->contents)[0] = length >> 24;
-    ((char *)out->contents)[1] = length >> 16;
-    ((char *)out->contents)[2] = length >> 8;
-    ((char *)out->contents)[3] = length;
-    
-    retval = krb5_encrypt(context, (krb5_pointer) tmpin.contents,
-                         (krb5_pointer) ((char *) out->contents + 4),
-                         tmpin.length, eblock, 0);
-    krb5_xfree(tmpin.contents);
-    if (retval) {
-       krb5_xfree(out->contents);
-       out->contents = 0;
-       out->length = 0;
+    *ptr++ = len & 0xff;
+    *ptr++ = (len >> 8) & 0xff;
+    if (retval = krb5_encrypt(context, (krb5_pointer) tmp.contents,
+                            (krb5_pointer)(ptr), tmp.length, eblock, 0)) {
+       krb5_xfree(key_data->key_data_contents[0]);
+       krb5_xfree(tmp.contents);
+       return retval;
     }
 
+    krb5_xfree(tmp.contents);
+
+    /* After key comes the salt in necessary */
+    if (keysalt) {
+       key_data->key_data_contents[1] =
+         (krb5_octet *)malloc(keysalt->data.length);
+       if (key_data->key_data_contents[1] == NULL) {
+           krb5_xfree(key_data->key_data_contents[0]);
+           return ENOMEM;
+       }
+       key_data->key_data_length[1] = keysalt->data.length;
+       key_data->key_data_type[1] = keysalt->type;
+        key_data->key_data_ver++;
+    }
     return retval;
 }
diff --git a/src/lib/kdb/kdb_cpw.c b/src/lib/kdb/kdb_cpw.c
new file mode 100644 (file)
index 0000000..7376c22
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * lib/kdb/kdb_cpw.c
+ *
+ * Copyright 1995 by the Massachusetts Institute of Technology. 
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+#include "k5-int.h"
+#include <stdio.h>
+#include <errno.h>
+
+/*
+ * Change password for a krb5_db_entry for a specific key version number
+ */
+krb5_error_code
+krb5_kdb_cpw_dbe_for_kvno(context, db_entry, password, kvno) 
+    krb5_context         context;
+    krb5_db_entry      * db_entry;
+    char               * password;
+    int                          kvno;
+{
+    krb5_error_code      retval;
+    int                          key;
+
+    for (key = 0; key < db_entry.n_key_data; key++) {
+       if (db_entry.key_data[key] == kvno) {
+       }
+    }
+    return retval;
+}
+
+/*
+ * Change password for a krb5_db_entry 
+ * Assumes the max kvno
+ */
+krb5_error_code
+krb5_kdb_cpw_dbe_for_kvno(context, db_entry, password) 
+    krb5_context         context;
+    krb5_db_entry      * db_entry;
+    char               * password;
+    int                          kvno;
+{
+    int                          key, kvno;
+
+    for (kvno = key = 0; key < db_entry.n_key_data; key++) {
+       if (kvno < db_entry.key_data[key].key_data_kvno) {
+           kvno = db_entry.key_data[key].key_data_kvno;
+       }
+    }
+    return(krb5_kdb_cpw_dbe_for_kvno(context, db_entry, password, kvno));
+}
index 88ebb55b0ed2ccd5f37f55bf762cdf7b0080fd3b..9cb02a36e05b3c78fd75fa92bafd93b497d90392 100644 (file)
@@ -87,35 +87,6 @@ static krb5_error_code krb5_dbm_db_start_read
 static krb5_error_code krb5_dbm_db_end_read 
        PROTOTYPE((krb5_context,
                   time_t  ));
-static krb5_error_code encode_princ_dbmkey 
-       PROTOTYPE((krb5_context,
-                  datum *,
-                  krb5_principal ));
-static void free_encode_princ_dbmkey 
-       PROTOTYPE((krb5_context,
-                  datum * ));
-static krb5_error_code encode_princ_contents
-       PROTOTYPE((krb5_context,
-                  datum *,
-                  krb5_db_entry * ));
-static void free_encode_princ_contents 
-       PROTOTYPE((datum * ));
-static krb5_error_code decode_princ_contents
-       PROTOTYPE((krb5_context,
-                  datum *,
-                  krb5_db_entry * ));
-static void free_decode_princ_contents 
-       PROTOTYPE((krb5_context,
-                  krb5_db_entry * ));
-
-#if 0
-/* not used */
-static krb5_error_code decode_princ_dbmkey 
-       PROTOTYPE((datum *,
-                  krb5_principal * ));
-static void free_decode_princ_dbmkey 
-       PROTOTYPE((krb5_principal ));
-#endif
 
 
 #ifdef BERK_DB_DBM
@@ -170,9 +141,8 @@ int dbm_clearerr PROTOTYPE((DBM *));
 /*
  * This module contains all of the code which directly interfaces to
  * the underlying representation of the Kerberos database; this
- * implementation uses a DBM or NDBM indexed "file" (actually
- * implemented as two separate files) to store the relations, plus a
- * third file as a semaphore to allow the database to be replaced out
+ * implementation uses the Berkeley hash db to store the relations, plus a
+ * second file as a semaphore to allow the database to be replaced out
  * from underneath the KDC server.
  */
 static kdb5_dispatch_table kdb5_default_dispatch = {
@@ -693,402 +663,6 @@ krb5_dbm_db_end_read(context, age)
     return 0;
 }
 
-
-static krb5_error_code
-encode_princ_dbmkey(context, key, principal)
-    krb5_context context;
-    datum  *key;
-    krb5_principal principal;
-{
-    char *princ_name;
-    krb5_error_code retval;
-
-    if (retval = krb5_unparse_name(context, principal, &princ_name))
-       return(retval);
-    key->dptr = princ_name;
-    key->dsize = strlen(princ_name)+1; /* need to store the NULL for
-                                          decoding */
-    return 0;
-}
-
-static void
-free_encode_princ_dbmkey(context, key)
-    krb5_context context;
-    datum  *key;
-{
-    (void) free(key->dptr);
-    key->dptr = 0;
-    key->dsize = 0;
-    return;
-}
-
-#if 0
-/* these aren't used, but if they ever should be... */
-static krb5_error_code
-decode_princ_dbmkey(context, key, principal)
-    datum  *key;
-    krb5_principal *principal;
-{
-    return(krb5_parse_name(context, key->dptr, principal));
-}
-
-static void
-free_decode_princ_dbmkey(context, principal)
-    krb5_context context;
-    krb5_principal principal;
-{
-    krb5_free_principal(context, principal);
-    return;
-}
-#endif
-
-static krb5_error_code
-encode_princ_contents(context, contents, entry)
-    krb5_context context;
-    register datum  *contents;
-    krb5_db_entry *entry;
-{
-    krb5_db_entry copy_princ;
-    char *unparse_princ, *unparse_mod_princ;
-    register char *nextloc;
-    int princ_size, mod_size;
-
-    krb5_error_code retval;
-
-    /* since there is some baggage pointing off of the entry
-       structure, we'll encode it by writing the structure, with nulled
-       pointers, followed by the unparsed principal name, then the key, and
-       then the unparsed mod_princ name, and then the salt (if any).
-       */
-    copy_princ = *entry;
-    copy_princ.principal = 0;
-    copy_princ.mod_name = 0;
-    copy_princ.salt = 0;
-    copy_princ.alt_salt = 0;
-    if (!entry->salt)
-       copy_princ.salt_length = 0; /* Safety measures.... */
-    if (!entry->alt_salt)
-       copy_princ.alt_salt_length = 0;
-
-    if (retval = krb5_unparse_name(context, entry->principal, &unparse_princ))
-       return(retval);
-    if (retval = krb5_unparse_name(context, entry->mod_name, &unparse_mod_princ)) {
-       free(unparse_princ);
-       return(retval);
-    }
-    princ_size = strlen(unparse_princ)+1;
-    mod_size = strlen(unparse_mod_princ)+1;
-    contents->dsize = (2 + sizeof(copy_princ) + princ_size
-                      + sizeof(entry->principal->type) + mod_size
-                      + sizeof(copy_princ.key.length) 
-                      + copy_princ.key.length + copy_princ.salt_length
-                      + sizeof(copy_princ.alt_key.length)
-                      + copy_princ.alt_key.length
-                      + copy_princ.alt_salt_length);
-    contents->dptr = malloc(contents->dsize);
-    if (!contents->dptr) {
-       free(unparse_princ);
-       free(unparse_mod_princ);
-       contents->dsize = 0;
-       contents->dptr = 0;
-       return(ENOMEM);
-    }
-    nextloc = contents->dptr;
-    *nextloc++ = 2;            /* Version number 2.0 */
-    *nextloc++ = 0;
-    (void) memcpy(nextloc, (char *)&copy_princ, sizeof(copy_princ));
-    nextloc += sizeof(copy_princ);
-
-    (void) memcpy(nextloc, unparse_princ, princ_size);
-    nextloc += princ_size;
-    (void) memcpy(nextloc, (char *)&entry->principal->type,
-                 sizeof(entry->principal->type));
-    nextloc +=  sizeof(entry->principal->type);
-    (void) memcpy(nextloc, unparse_mod_princ, mod_size);
-    nextloc += mod_size;
-    if (copy_princ.key.length) {
-       (void) memcpy(nextloc, (char *)entry->key.contents, entry->key.length);
-       nextloc += entry->key.length;
-    }
-    if (copy_princ.salt_length) {
-       (void) memcpy(nextloc, (char *)entry->salt, entry->salt_length);
-       nextloc += entry->salt_length;
-    }
-    if (copy_princ.alt_key.length) {
-       (void) memcpy(nextloc, (char *)entry->alt_key.contents,
-                     entry->alt_key.length);
-       nextloc += entry->alt_key.length;
-    }
-    if (copy_princ.alt_salt_length) {
-       (void) memcpy(nextloc, (char *)entry->alt_salt,
-                     entry->alt_salt_length);
-       nextloc += entry->alt_salt_length;
-    }
-    free(unparse_princ);
-    free(unparse_mod_princ);
-    return 0;
-}
-
-static void
-free_encode_princ_contents(contents)
-    datum *contents;
-{
-    free(contents->dptr);
-    contents->dsize = 0;
-    contents->dptr = 0;
-    return;
-}
-
-static krb5_error_code
-decode_princ_contents(context, contents, entry)
-    krb5_context context;
-    datum  *contents;
-    krb5_db_entry *entry;
-{
-    register char *nextloc;
-    krb5_principal princ, mod_princ;
-    krb5_error_code retval;
-    int        sizeleft;
-    int major_version = 0, minor_version = 0;
-
-    /*
-     * undo the effects of encode_princ_contents.
-     */
-    sizeleft = contents->dsize;
-    nextloc = contents->dptr;
-    if (sizeleft <= 0)
-       return KRB5_KDB_TRUNCATED_RECORD;
-
-    /*
-     * First, check the version number.  If the major version number is
-     * greater than zero, then the version number is explicitly
-     * allocated; otherwise, it is part of the zeroed principal pointer.
-     */
-    major_version = *nextloc;
-    if (major_version) {
-       nextloc++; sizeleft--;
-       minor_version = *nextloc;
-       nextloc++; sizeleft--;
-    }
-#ifdef OLD_COMPAT_VERSION_1
-    if (major_version == 0 || major_version == 1) {
-       old_krb5_db_entry old_entry;
-
-       /*
-        * Copy in structure to old-style structure, and then copy it
-        * to the new structure.
-        */
-       sizeleft -= sizeof(old_entry);
-       if (sizeleft < 0) 
-           return KRB5_KDB_TRUNCATED_RECORD;
-
-       memcpy((char *) &old_entry, nextloc, sizeof(old_entry));
-       nextloc += sizeof(old_entry);   /* Skip past structure */
-       
-       entry->key.keytype = old_entry.key.keytype;
-       entry->key.length = old_entry.key.length;
-
-       entry->kvno = old_entry.kvno;
-       entry->max_life = old_entry.max_life;
-       entry->max_renewable_life = old_entry.max_renewable_life;
-       entry->mkvno = old_entry.mkvno;
-       
-       entry->expiration = old_entry.expiration;
-       entry->pw_expiration = old_entry.pw_expiration;
-       entry->last_pwd_change = old_entry.last_pwd_change;
-       entry->last_success = old_entry.last_success;
-    
-       entry->last_failed = old_entry.last_failed;
-       entry->fail_auth_count = old_entry.fail_auth_count;
-    
-       entry->mod_date = old_entry.mod_date;
-       entry->attributes = old_entry.attributes;
-       entry->salt_type = old_entry.salt_type;
-       entry->salt_length = old_entry.salt_length;
-       
-       entry->alt_key.keytype = old_entry.alt_key.keytype;
-       entry->alt_key.length = old_entry.alt_key.length;
-       entry->alt_salt_type = old_entry.alt_salt_type;
-       entry->alt_salt_length = old_entry.alt_salt_length;
-
-       goto resume_processing;
-    }
-#endif
-    if (major_version != 2)
-       return KRB5_KDB_BAD_VERSION;
-    
-    sizeleft -= sizeof(*entry);
-    if (sizeleft < 0) 
-       return KRB5_KDB_TRUNCATED_RECORD;
-
-    memcpy((char *) entry, nextloc, sizeof(*entry));
-    nextloc += sizeof(*entry); /* Skip past structure */
-
-#ifdef OLD_COMPAT_VERSION_1
-resume_processing:
-#endif
-    
-    /*
-     * These values should be zero if they are not in use, but just in
-     * case, we clear them to make sure nothing bad happens if we need
-     * to call free_decode_princ_contents().  (What me, paranoid?)
-     */
-    entry->principal = 0;
-    entry->mod_name = 0;
-    entry->salt = 0;
-    entry->alt_salt = 0;
-    entry->key.contents = 0;
-    entry->alt_key.contents = 0;
-
-    /*
-     * Get the principal name for the entry (stored as a string which
-     * gets unparsed.)
-     */
-    sizeleft -= strlen(nextloc)+1;
-    if (sizeleft < 0) {
-       retval = KRB5_KDB_TRUNCATED_RECORD;
-       goto error_out;
-    }
-    retval = krb5_parse_name(context, nextloc, &princ);
-    if (retval)
-       goto error_out;
-    entry->principal = princ;
-    nextloc += strlen(nextloc)+1;      /* advance past 1st string */
-
-    if (major_version >= 1) {          /* Get principal type */
-       sizeleft -= sizeof(entry->principal->type);
-       if (sizeleft < 0) {
-           retval = KRB5_KDB_TRUNCATED_RECORD;
-           goto error_out;
-       }
-       memcpy((char *)&entry->principal->type,nextloc,
-              sizeof(entry->principal->type));
-       nextloc += sizeof(princ->type);
-    }
-    
-    /*
-     * Get the last modified principal for the entry (again stored as
-     * string which gets unparased.)
-     */
-    sizeleft -= strlen(nextloc)+1;     /* check size for 2nd string */
-    if (sizeleft < 0) {
-       retval = KRB5_KDB_TRUNCATED_RECORD;
-       goto error_out;
-    }
-    retval = krb5_parse_name(context, nextloc, &mod_princ);
-    if (retval)
-       goto error_out;
-    entry->mod_name = mod_princ;
-    nextloc += strlen(nextloc)+1;      /* advance past 2nd string */
-    
-    /*
-     * Get the primary key...
-     */
-    if (entry->key.length) {
-       sizeleft -= entry->key.length;  /* check size for key */
-       if (sizeleft < 0) {
-           retval = KRB5_KDB_TRUNCATED_RECORD;
-           goto error_out;
-       }
-       entry->key.contents = (unsigned char *)malloc(entry->key.length);
-       if (!entry->key.contents) {
-           retval = ENOMEM;
-           goto error_out;
-       }
-       (void) memcpy((char *)entry->key.contents, nextloc, entry->key.length);
-       nextloc += entry->key.length;   /* advance past key */
-    }
-       
-    /*
-     * ...and the salt, if present...
-     */
-    if (entry->salt_length) {
-       sizeleft -= entry->salt_length;
-       if (sizeleft < 0) {
-           retval = KRB5_KDB_TRUNCATED_RECORD;
-           goto error_out;
-       }
-       entry->salt = (krb5_octet *)malloc(entry->salt_length);
-       if (!entry->salt) {
-           retval = KRB5_KDB_TRUNCATED_RECORD;
-           goto error_out;
-       }
-       (void) memcpy((char *)entry->salt, nextloc, entry->salt_length);
-       nextloc += entry->salt_length; /* advance past salt */
-    }
-
-    /*
-     * ... and the alternate key, if present...
-     */
-    if (entry->alt_key.length) {
-       sizeleft -= entry->alt_key.length;      /* check size for alt_key */
-       if (sizeleft < 0) {
-           retval = KRB5_KDB_TRUNCATED_RECORD;
-           goto error_out;
-       }
-       entry->alt_key.contents = (unsigned char *) malloc(entry->alt_key.length);
-       if (!entry->alt_key.contents) {
-           retval = ENOMEM;
-           goto error_out;
-       }
-       (void) memcpy((char *)entry->alt_key.contents, nextloc,
-                     entry->alt_key.length);
-       nextloc += entry->alt_key.length;       /* advance past alt_key */
-    }
-       
-    /*
-     * ...and the alternate key's salt, if present.
-     */
-    if (entry->alt_salt_length) {
-       sizeleft -= entry->alt_salt_length;
-       if (sizeleft < 0) {
-           retval = KRB5_KDB_TRUNCATED_RECORD;
-           goto error_out;
-       }
-       entry->alt_salt = (krb5_octet *)malloc(entry->alt_salt_length);
-       if (!entry->alt_salt) {
-           retval = KRB5_KDB_TRUNCATED_RECORD;
-           goto error_out;
-       }
-       (void) memcpy((char *)entry->alt_salt, nextloc,
-                     entry->alt_salt_length);
-       nextloc += entry->alt_salt_length; /* advance past salt */
-    }
-    
-    return 0;
-error_out:
-    free_decode_princ_contents(context, entry);
-    return retval;
-}
-
-static void
-free_decode_princ_contents(context, entry)
-     krb5_context context; 
-     krb5_db_entry *entry;
-{
-    /* erase the key */
-    if (entry->key.contents) {
-       memset((char *)entry->key.contents, 0, entry->key.length);
-       krb5_xfree(entry->key.contents);
-    }
-    if (entry->salt)
-       krb5_xfree(entry->salt);
-    
-    if (entry->alt_key.contents) {
-       memset((char *)entry->alt_key.contents, 0, entry->alt_key.length);
-       krb5_xfree(entry->alt_key.contents);
-    }
-    if (entry->alt_salt)
-       krb5_xfree(entry->alt_salt);
-    
-    if (entry->principal)
-       krb5_free_principal(context, entry->principal);
-    if (entry->mod_name)
-       krb5_free_principal(context, entry->mod_name);
-    (void) memset((char *)entry, 0, sizeof(*entry));
-    return;
-}
-
 krb5_error_code
 krb5_dbm_db_lock(context, mode)
     krb5_context context;
@@ -1431,7 +1005,7 @@ errout:
        free_dbsuffix (fromdir);
 
     if (retval == 0)
-       retval = krb5_dbm_db_end_update(context, to, trans);
+       return krb5_dbm_db_end_update(context, to, trans);
 
     if (tmpcontext) {
        k5dbm_clear_context((db_context_t *) context->db_context);
@@ -1488,15 +1062,15 @@ krb5_boolean *more;                     /* are there more? */
        *more = FALSE;
 
        /* XXX deal with wildcard lookups */
-       if (retval = encode_princ_dbmkey(context, &key, searchfor))
+       if (retval = krb5_encode_princ_dbmkey(context, &key, searchfor))
            goto cleanup;
 
        contents = KDBM_FETCH(db_ctx, db, key);
-       free_encode_princ_dbmkey(context, &key);
+       krb5_free_princ_dbmkey(context, &key);
 
        if (contents.dptr == NULL)
            found = 0;
-       else if (retval = decode_princ_contents(context, &contents, entries))
+       else if (retval = krb5_decode_princ_contents(context,&contents,entries))
            goto cleanup;
        else found = 1;
 
@@ -1534,7 +1108,7 @@ krb5_dbm_db_free_principal(context, entries, nentries)
 {
     register int i;
     for (i = 0; i < nentries; i++)
-       free_decode_princ_contents(context, &entries[i]);
+       krb5_dbe_free_contents(context, &entries[i]);
     return;
 }
 
@@ -1587,19 +1161,19 @@ krb5_dbm_db_put_principal(context, entries, nentries)
 
     /* for each one, stuff temps, and do replace/append */
     for (i = 0; i < *nentries; i++) {
-       if (retval = encode_princ_contents(context, &contents, entries))
+       if (retval = krb5_encode_princ_contents(context, &contents, entries))
            break;
 
-       if (retval = encode_princ_dbmkey(context, &key, entries->principal)) {
-           free_encode_princ_contents(&contents);
+       if (retval = krb5_encode_princ_dbmkey(context, &key, entries->princ)) {
+           krb5_free_princ_contents(context, &contents);
            break;
        }
        if (KDBM_STORE(db_ctx, db, key, contents, DBM_REPLACE))
            retval = errno;
        else
            retval = 0;
-       free_encode_princ_contents(&contents);
-       free_encode_princ_dbmkey(context, &key);
+       krb5_free_princ_contents(context, &contents);
+       krb5_free_princ_dbmkey(context, &key);
        if (retval)
            break;
        entries++;                      /* bump to next struct */
@@ -1619,16 +1193,16 @@ krb5_dbm_db_put_principal(context, entries, nentries)
 
 krb5_error_code
 krb5_dbm_db_delete_principal(context, searchfor, nentries)
-    krb5_context context;
-krb5_principal searchfor;
-int *nentries;                         /* how many found & deleted */
+    krb5_context         context;
+    krb5_principal       searchfor;
+    int                * nentries;     /* how many found & deleted */
 {
-    int     found = 0;
-    datum   key, contents, contents2;
-    krb5_db_entry entry;
-    DBM    *db;
-    krb5_error_code retval;
-    db_context_t *db_ctx;
+    krb5_error_code      retval;
+    krb5_db_entry        entry;
+    db_context_t       * db_ctx;
+    datum                key, contents, contents2;
+    DBM                * db;
+    int                          i;
 
     if (!k5dbm_inited(context))
        return KRB5_KDB_DBNOTINITED;
@@ -1648,19 +1222,26 @@ int *nentries;                          /* how many found & deleted */
        }
     }
 
-    if (retval = encode_princ_dbmkey(context, &key, searchfor))
+    if (retval = krb5_encode_princ_dbmkey(context, &key, searchfor))
        goto cleanup;
 
     contents = KDBM_FETCH(db_ctx, db, key);
     if (contents.dptr == NULL) {
-       found = 0;
        retval = KRB5_KDB_NOENTRY;
+       *nentries = 0;
     } else {
-       if (retval = decode_princ_contents(context, &contents, &entry))
+       memset((char *)&entry, 0, sizeof(entry));
+       if (retval = krb5_decode_princ_contents(context, &contents, &entry))
            goto cleankey;
-       found = 1;
-       memset((char *)entry.key.contents, 0, entry.key.length);
-       if (retval = encode_princ_contents(context, &contents2, &entry))
+       *nentries = 1;
+       /* Clear encrypted key contents */
+       for (i = 0; i < entry.n_key_data; i++) {
+           if (entry.key_data[i].key_data_length[0]) {
+               memset((char *)entry.key_data[i].key_data_contents[0], 0, 
+                      entry.key_data[i].key_data_length[0]); 
+           }
+       }
+       if (retval = krb5_encode_princ_contents(context, &contents2, &entry))
            goto cleancontents;
 
        if (KDBM_STORE(db_ctx, db, key, contents2, DBM_REPLACE))
@@ -1671,18 +1252,17 @@ int *nentries;                          /* how many found & deleted */
            else
                retval = 0;
        }
-       free_encode_princ_contents(&contents2);
+       krb5_free_princ_contents(context, &contents2);
     cleancontents:
-       free_decode_princ_contents(context, &entry);
+       krb5_dbe_free_contents(context, &entry);
     cleankey:
-       free_encode_princ_dbmkey(context, &key);
+       krb5_free_princ_dbmkey(context, &key);
     }
 
  cleanup:
     if (db_ctx->db_dbm_ctx == 0)
        KDBM_CLOSE(db_ctx, db);
     (void) krb5_dbm_db_unlock(context);        /* unlock write lock */
-    *nentries = found;
     return retval;
 }
 
@@ -1719,10 +1299,10 @@ krb5_dbm_db_iterate (context, func, func_arg)
     for (key = KDBM_FIRSTKEY (db_ctx, db);
         key.dptr != NULL; key = KDBM_NEXTKEY(db_ctx, db)) {
        contents = KDBM_FETCH (db_ctx, db, key);
-       if (retval = decode_princ_contents(context, &contents, &entries))
+       if (retval = krb5_decode_princ_contents(context, &contents, &entries))
            break;
        retval = (*func)(func_arg, &entries);
-       free_decode_princ_contents(context, &entries);
+       krb5_dbe_free_contents(context, &entries);
        if (retval)
            break;
     }
diff --git a/src/lib/kdb/kdb_xdr.c b/src/lib/kdb/kdb_xdr.c
new file mode 100644 (file)
index 0000000..84ad28d
--- /dev/null
@@ -0,0 +1,652 @@
+/*
+ * lib/kdb/kdb_xdr.c
+ *
+ * Copyright 1995 by the Massachusetts Institute of Technology. 
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ * 
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ * 
+ */
+
+#include "k5-int.h"
+#include <stdio.h>
+#include <errno.h>
+
+krb5_error_code
+krb5_dbe_create_key_data(context, entry) 
+    krb5_context         context;
+    krb5_db_entry      * entry;
+{
+    if (entry->n_key_data) {
+       if (entry->key_data = (krb5_key_data *)realloc(entry->key_data, 
+                               sizeof(krb5_key_data) * entry->n_key_data + 1))
+           memset(entry->key_data + entry->n_key_data,0,sizeof(krb5_key_data));
+       else 
+           return ENOMEM;
+    } else { 
+       if (entry->key_data = (krb5_key_data *)malloc(sizeof(krb5_key_data))) 
+           memset(entry->key_data, 0, sizeof(krb5_key_data));
+       else 
+           return ENOMEM;
+    }
+    entry->n_key_data++;
+    return 0;
+}
+
+krb5_dbe_encode_mod_princ_data(context, mod_princ, entry)
+    krb5_context         context;
+    krb5_tl_mod_princ  * mod_princ;
+    krb5_db_entry      * entry;
+{
+    krb5_error_code      retval;
+    krb5_tl_data       ** tl_data;
+    krb5_octet         * nextloc;
+    char               * unparse_mod_princ;
+    int                          unparse_mod_princ_size;
+
+    /* 
+     * Allocate *tl_data if necessary otherwise reuse it 
+     * Need 04 bytes for date
+     * Need XX bytes for string
+     */
+    if (retval = krb5_unparse_name(context, mod_princ->mod_princ, 
+                                  &unparse_mod_princ))
+       return(retval);
+
+    if ((nextloc = malloc(unparse_mod_princ_size + 4)) == NULL)
+       return ENOMEM;
+
+    /* 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_MOD_PRINC) {
+           free((*tl_data)->tl_data_contents);
+           entry->n_tl_data--;
+           break;
+       }
+    }
+
+    unparse_mod_princ_size = strlen(unparse_mod_princ) + 1;
+
+    if ((*tl_data) || 
+       /* Only zero data if it is freshly allocated */
+       ((*tl_data) = (krb5_tl_data *)calloc(1, sizeof(krb5_tl_data)))) {
+       entry->n_tl_data++;
+       (*tl_data)->tl_data_type = KRB5_TL_MOD_PRINC;
+       (*tl_data)->tl_data_length = unparse_mod_princ_size + 4;
+       (*tl_data)->tl_data_contents = nextloc;
+
+       /* Mod Date */
+       *nextloc++ = (krb5_octet)(mod_princ->mod_date & 0xff);
+       *nextloc++ = (krb5_octet)((mod_princ->mod_date >> 8) & 0xff);
+       *nextloc++ = (krb5_octet)((mod_princ->mod_date >> 16) & 0xff);
+       *nextloc++ = (krb5_octet)((mod_princ->mod_date >> 24) & 0xff);
+
+       /* Mod Princ */
+       memcpy(nextloc, unparse_mod_princ, unparse_mod_princ_size);
+       return 0;
+    }
+
+    free(nextloc);
+    return ENOMEM;
+}
+
+krb5_dbe_decode_mod_princ_data(context, entry, mod_princ)
+    krb5_context         context;
+    krb5_db_entry      * entry;
+    krb5_tl_mod_princ  ** mod_princ;
+{
+    krb5_error_code      retval;
+    krb5_tl_data        * tl_data;
+    krb5_octet         * nextloc;
+
+    for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) {
+       if (tl_data->tl_data_type == KRB5_TL_MOD_PRINC) {
+           if ((*mod_princ = malloc(sizeof(krb5_tl_mod_princ))) == NULL)
+               return ENOMEM;
+
+           nextloc = tl_data->tl_data_contents;
+
+           /* Mod Date */
+           *(((krb5_octet *)(&(*mod_princ)->mod_date))) = *nextloc++;
+           *(((krb5_octet *)(&(*mod_princ)->mod_date)) + 1) = *nextloc++;
+           *(((krb5_octet *)(&(*mod_princ)->mod_date)) + 2) = *nextloc++;
+           *(((krb5_octet *)(&(*mod_princ)->mod_date)) + 3) = *nextloc++;
+
+           /* Mod Princ */
+           if (retval = krb5_parse_name(context, nextloc, 
+                                        &((*mod_princ)->mod_princ))) 
+               break;
+           if ((strlen(nextloc) + 1 + 4) != tl_data->tl_data_length) {
+               retval = KRB5_KDB_TRUNCATED_RECORD;
+               break;
+           }
+       }
+    }
+
+    if (retval) 
+       free(*mod_princ);
+    return retval;
+}
+
+krb5_encode_princ_dbmkey(context, key, principal)
+    krb5_context context;
+    datum  *key;
+    krb5_principal principal;
+{
+    char *princ_name;
+    krb5_error_code retval;
+
+    if (!(retval = krb5_unparse_name(context, principal, &princ_name))) {
+        /* need to store the NULL for decoding */
+        key->dsize = strlen(princ_name)+1;     
+        key->dptr = princ_name;
+    }
+    return(retval);
+}
+
+void
+krb5_free_princ_dbmkey(context, key)
+    krb5_context context;
+    datum  *key;
+{
+    (void) free(key->dptr);
+    key->dsize = 0;
+    key->dptr = 0;
+    return;
+}
+
+krb5_error_code
+krb5_encode_princ_contents(context, content, entry)
+    krb5_context         context;
+    datum              * content;
+    krb5_db_entry      * entry;
+{
+    int                  unparse_princ_size, i, j;
+    char               * unparse_princ;
+    char               * nextloc;
+    krb5_tl_data       * tl_data;
+    krb5_error_code      retval;
+
+    krb5_db_entry copy_princ;
+
+    /*
+     * Generate one lump of data from the krb5_db_entry.
+     * This data must be independent of byte order of the machine,
+     * compact and extensible.
+     */
+
+    /* 
+     * First allocate enough space for all the data. 
+     * Need  2 bytes for the length of the base structure
+     * then 40 [9 * 4 + 2 * 2] bytes for the base information
+     *         [ mkvno, attributes, max_life, max_renewable_life, expiration,
+     *          pw_expiration, last_success, last_failed, fail_auth_count ]
+     *         [ n_key_data, n_tl_data ]
+     * then XX bytes [ e_length ] for the extra data [ e_data ]
+     * then XX bytes [ 2 for length + length for string ] for the principal,
+     * then (4 [type + length] + tl_data_length) bytes per tl_data
+     * then (4 + (4 + key_data_length) per key_data_contents) bytes per key_data
+     */
+    content->dsize = entry->len + entry->e_length;
+
+    if (retval = krb5_unparse_name(context, entry->princ, &unparse_princ))
+       return(retval);
+
+    unparse_princ_size = strlen(unparse_princ) + 1;
+    content->dsize += unparse_princ_size;
+    content->dsize += 2;               
+
+    i = 0;
+    /* tl_data is a linked list */
+    for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) {
+       content->dsize += tl_data->tl_data_length;
+       content->dsize += 4; /* type, length */
+       i++;
+    }
+
+    if (i != entry->n_tl_data) {
+       retval = KRB5_KDB_TRUNCATED_RECORD;
+       goto epc_error;
+    }
+
+    /* key_data is an array */
+    for (i = 0; i < entry->n_key_data; i++) {
+       content->dsize += 4; /* Version, KVNO */
+       for (j = 0; j < entry->key_data[i].key_data_ver; j++) {
+           content->dsize += entry->key_data[i].key_data_length[j];
+           content->dsize += 4; /* type + length */
+       }
+    }
+       
+    if ((content->dptr = malloc(content->dsize)) == NULL) {
+       retval = ENOMEM;
+       goto epc_error;
+    }
+
+    /* 
+     * Now we go through entry again, this time copying data 
+     * These first entries are always saved regaurdless of version
+     */
+    nextloc = content->dptr;
+
+       /* Base Length */
+    *nextloc++ = (krb5_octet)(entry->len & 0xff);
+    *nextloc++ = (krb5_octet)((entry->len >> 8) & 0xff);
+
+       /* Master Key Version */
+    *nextloc++ = (krb5_octet)(entry->mkvno & 0xff);
+    *nextloc++ = (krb5_octet)((entry->mkvno >> 8) & 0xff);
+    *nextloc++ = (krb5_octet)((entry->mkvno >> 16) & 0xff);
+    *nextloc++ = (krb5_octet)((entry->mkvno >> 24) & 0xff);
+
+       /* Attributes */
+    *nextloc++ = (krb5_octet)(entry->attributes & 0xff);
+    *nextloc++ = (krb5_octet)((entry->attributes >> 8) & 0xff);
+    *nextloc++ = (krb5_octet)((entry->attributes >> 16) & 0xff);
+    *nextloc++ = (krb5_octet)((entry->attributes >> 24) & 0xff);
+  
+       /* Max Life */
+    *nextloc++ = (krb5_octet)(entry->max_life & 0xff);
+    *nextloc++ = (krb5_octet)((entry->max_life >> 8) & 0xff);
+    *nextloc++ = (krb5_octet)((entry->max_life >> 16) & 0xff);
+    *nextloc++ = (krb5_octet)((entry->max_life >> 24) & 0xff);
+  
+       /* Max Renewable Life */
+    *nextloc++ = (krb5_octet)(entry->max_renewable_life & 0xff);
+    *nextloc++ = (krb5_octet)((entry->max_renewable_life >> 8) & 0xff);
+    *nextloc++ = (krb5_octet)((entry->max_renewable_life >> 16) & 0xff);
+    *nextloc++ = (krb5_octet)((entry->max_renewable_life >> 24) & 0xff);
+  
+       /* When the client expires */
+    *nextloc++ = (krb5_octet)(entry->expiration & 0xff);
+    *nextloc++ = (krb5_octet)((entry->expiration >> 8) & 0xff);
+    *nextloc++ = (krb5_octet)((entry->expiration >> 16) & 0xff);
+    *nextloc++ = (krb5_octet)((entry->expiration >> 24) & 0xff);
+  
+       /* When its passwd expires */
+    *nextloc++ = (krb5_octet)(entry->pw_expiration & 0xff);
+    *nextloc++ = (krb5_octet)((entry->pw_expiration >> 8) & 0xff);
+    *nextloc++ = (krb5_octet)((entry->pw_expiration >> 16) & 0xff);
+    *nextloc++ = (krb5_octet)((entry->pw_expiration >> 24) & 0xff);
+  
+       /* Last successful passwd */
+    *nextloc++ = (krb5_octet)(entry->last_success & 0xff);
+    *nextloc++ = (krb5_octet)((entry->last_success >> 8) & 0xff);
+    *nextloc++ = (krb5_octet)((entry->last_success >> 16) & 0xff);
+    *nextloc++ = (krb5_octet)((entry->last_success >> 24) & 0xff);
+  
+       /* Last failed passwd attempt */
+    *nextloc++ = (krb5_octet)(entry->last_failed & 0xff);
+    *nextloc++ = (krb5_octet)((entry->last_failed >> 8) & 0xff);
+    *nextloc++ = (krb5_octet)((entry->last_failed >> 16) & 0xff);
+    *nextloc++ = (krb5_octet)((entry->last_failed >> 24) & 0xff);
+  
+       /* # of failed passwd attempt */
+    *nextloc++ = (krb5_octet)(entry->fail_auth_count & 0xff);
+    *nextloc++ = (krb5_octet)((entry->fail_auth_count >> 8) & 0xff);
+    *nextloc++ = (krb5_octet)((entry->fail_auth_count >> 16) & 0xff);
+    *nextloc++ = (krb5_octet)((entry->fail_auth_count >> 24) & 0xff);
+
+       /* # tl_data strutures */
+    *nextloc++ = (krb5_octet)(entry->n_tl_data & 0xff);
+    *nextloc++ = (krb5_octet)((entry->n_tl_data >> 8) & 0xff);
+  
+       /* # key_data strutures */
+    *nextloc++ = (krb5_octet)(entry->n_key_data & 0xff);
+    *nextloc++ = (krb5_octet)((entry->n_key_data >> 8) & 0xff);
+  
+       /* Put extended fields here */
+    if (entry->len != KRB5_KDB_V1_BASE_LENGTH)
+       abort();
+
+       /* Any extra data that this version doesn't understand. */
+    if (entry->e_length) {
+       memcpy(nextloc, entry->e_data, entry->e_length);
+       nextloc += entry->e_length;
+    }
+  
+       /* 
+        * Now we get to the principal.
+        * To squeze a few extra bytes out it is always assumed to come
+        * after the base type.
+        */
+    *nextloc++ = (krb5_octet)(unparse_princ_size & 0xff);
+    *nextloc++ = (krb5_octet)((unparse_princ_size >> 8) & 0xff);
+    (void) memcpy(nextloc, unparse_princ, unparse_princ_size);
+    nextloc += unparse_princ_size;
+
+       /* tl_data is a linked list, of type, legth, contents */
+    for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) {
+       *nextloc++ = (krb5_octet)(tl_data->tl_data_type & 0xff);
+       *nextloc++ = (krb5_octet)((tl_data->tl_data_type >> 8) & 0xff);
+
+       *nextloc++ = (krb5_octet)(tl_data->tl_data_length & 0xff);
+       *nextloc++ = (krb5_octet)((tl_data->tl_data_length >> 8) & 0xff);
+
+       memcpy(nextloc, tl_data->tl_data_contents, tl_data->tl_data_length);
+       nextloc += tl_data->tl_data_length;
+    }
+
+       /* key_data is an array */
+    for (i = 0; i < entry->n_key_data; i++) {
+       *nextloc++ = (krb5_octet)(entry->key_data[i].key_data_ver & 0xff);
+       *nextloc++ = (krb5_octet)((entry->key_data[i].key_data_ver >> 8)&0xff);
+       *nextloc++ = (krb5_octet)(entry->key_data[i].key_data_kvno & 0xff);
+       *nextloc++ = (krb5_octet)((entry->key_data[i].key_data_kvno >> 8)&0xff);
+
+       for (j = 0; j < entry->key_data[i].key_data_ver; j++) {
+           krb5_int16 type = entry->key_data[i].key_data_type[j];
+           krb5_int16 length = entry->key_data[i].key_data_length[j];
+
+           *nextloc++ = (krb5_octet)(type & 0xff);
+           *nextloc++ = (krb5_octet)((type >> 8) & 0xff);
+
+           *nextloc++ = (krb5_octet)(length & 0xff);
+           *nextloc++ = (krb5_octet)((length >> 8) & 0xff);
+
+           if (length) {
+               memcpy(nextloc, entry->key_data[i].key_data_contents[j],length);
+               nextloc += length;
+           }
+       }
+    }
+       
+epc_error:;
+    free(unparse_princ);
+    return retval;
+}
+
+void
+krb5_free_princ_contents(context, contents)
+    krb5_context         context;
+    datum *contents;
+{
+    free(contents->dptr);
+    contents->dsize = 0;
+    contents->dptr = 0;
+    return;
+}
+
+krb5_error_code
+krb5_decode_princ_contents(context, content, entry)
+    krb5_context         context;
+    datum              * content;
+    krb5_db_entry      * entry;
+{
+    int                          sizeleft, i;
+    char               * nextloc;
+    krb5_tl_data       ** tl_data;
+
+    krb5_principal princ;
+    krb5_error_code retval;
+    int major_version = 0, minor_version = 0;
+
+    /* Zero out entry and NULL pointers */
+    memset(entry, 0, sizeof(krb5_db_entry));
+
+    /*
+     * undo the effects of encode_princ_contents.
+     *
+     * The first part is decoding the base type. If the base type is
+     * bigger than the original base type then the additional fields
+     * need to be filled in. If the base type is larger than any
+     * known base type the additional data goes in e_data.
+     */
+
+    /* First do the easy stuff */
+    nextloc = content->dptr;
+    sizeleft = content->dsize;
+    if ((sizeleft -= KRB5_KDB_V1_BASE_LENGTH) < 0) 
+       return KRB5_KDB_TRUNCATED_RECORD;
+
+       /* Base Length */
+    *(((krb5_octet *)(&entry->len))) = *nextloc++;
+    *(((krb5_octet *)(&entry->len)) + 1) = *nextloc++;
+
+       /* Master Key Version */
+    *(((krb5_octet *)(&entry->mkvno))) = *nextloc++;
+    *(((krb5_octet *)(&entry->mkvno)) + 1) = *nextloc++;
+    *(((krb5_octet *)(&entry->mkvno)) + 2) = *nextloc++;
+    *(((krb5_octet *)(&entry->mkvno)) + 3) = *nextloc++;
+
+       /* Attributes */
+    *(((krb5_octet *)(&entry->attributes))) = *nextloc++;
+    *(((krb5_octet *)(&entry->attributes)) + 1) = *nextloc++;
+    *(((krb5_octet *)(&entry->attributes)) + 2) = *nextloc++;
+    *(((krb5_octet *)(&entry->attributes)) + 3) = *nextloc++;
+
+       /* Max Life */
+    *(((krb5_octet *)(&entry->max_life))) = *nextloc++;
+    *(((krb5_octet *)(&entry->max_life)) + 1) = *nextloc++;
+    *(((krb5_octet *)(&entry->max_life)) + 2) = *nextloc++;
+    *(((krb5_octet *)(&entry->max_life)) + 3) = *nextloc++;
+
+       /* Max Renewable Life */
+    *(((krb5_octet *)(&entry->max_renewable_life))) = *nextloc++;
+    *(((krb5_octet *)(&entry->max_renewable_life)) + 1) = *nextloc++;
+    *(((krb5_octet *)(&entry->max_renewable_life)) + 2) = *nextloc++;
+    *(((krb5_octet *)(&entry->max_renewable_life)) + 3) = *nextloc++;
+
+       /* When the client expires */
+    *(((krb5_octet *)(&entry->expiration))) = *nextloc++;
+    *(((krb5_octet *)(&entry->expiration)) + 1) = *nextloc++;
+    *(((krb5_octet *)(&entry->expiration)) + 2) = *nextloc++;
+    *(((krb5_octet *)(&entry->expiration)) + 3) = *nextloc++;
+
+       /* When its passwd expires */
+    *(((krb5_octet *)(&entry->pw_expiration))) = *nextloc++;
+    *(((krb5_octet *)(&entry->pw_expiration)) + 1) = *nextloc++;
+    *(((krb5_octet *)(&entry->pw_expiration)) + 2) = *nextloc++;
+    *(((krb5_octet *)(&entry->pw_expiration)) + 3) = *nextloc++;
+
+       /* Last successful passwd */
+    *(((krb5_octet *)(&entry->last_success))) = *nextloc++;
+    *(((krb5_octet *)(&entry->last_success)) + 1) = *nextloc++;
+    *(((krb5_octet *)(&entry->last_success)) + 2) = *nextloc++;
+    *(((krb5_octet *)(&entry->last_success)) + 3) = *nextloc++;
+
+       /* Last failed passwd attempt */
+    *(((krb5_octet *)(&entry->last_failed))) = *nextloc++;
+    *(((krb5_octet *)(&entry->last_failed)) + 1) = *nextloc++;
+    *(((krb5_octet *)(&entry->last_failed)) + 2) = *nextloc++;
+    *(((krb5_octet *)(&entry->last_failed)) + 3) = *nextloc++;
+
+       /* # of failed passwd attempt */
+    *(((krb5_octet *)(&entry->fail_auth_count))) = *nextloc++;
+    *(((krb5_octet *)(&entry->fail_auth_count)) + 1) = *nextloc++;
+    *(((krb5_octet *)(&entry->fail_auth_count)) + 2) = *nextloc++;
+    *(((krb5_octet *)(&entry->fail_auth_count)) + 3) = *nextloc++;
+
+       /* # tl_data strutures */
+    *(((krb5_octet *)(&entry->n_tl_data))) = *nextloc++;
+    *(((krb5_octet *)(&entry->n_tl_data)) + 1) = *nextloc++;
+
+    if (entry->n_tl_data < 0)
+       return KRB5_KDB_TRUNCATED_RECORD;
+
+       /* # key_data strutures */
+    *(((krb5_octet *)(&entry->n_key_data))) = *nextloc++;
+    *(((krb5_octet *)(&entry->n_key_data)) + 1) = *nextloc++;
+
+    if (entry->n_key_data < 0)
+       return KRB5_KDB_TRUNCATED_RECORD;
+
+       /* Check for extra data */
+    if (entry->len > KRB5_KDB_V1_BASE_LENGTH) {
+       entry->e_length = entry->len - KRB5_KDB_V1_BASE_LENGTH;
+       if (entry->e_data = (krb5_octet *)malloc(entry->e_length)) {
+           memcpy(entry->e_data, nextloc, entry->e_length);
+           nextloc += entry->e_length;
+       } else {
+           return ENOMEM;
+       }
+    }
+
+    /*
+     * Get the principal name for the entry 
+     * (stored as a string which gets unparsed.)
+     */
+    if ((sizeleft -= 2) < 0) {
+       retval = KRB5_KDB_TRUNCATED_RECORD;
+       goto error_out;
+    }
+
+    i = 0;
+    *(((krb5_octet *)(&i))) = *nextloc++;
+    *(((krb5_octet *)(&i)) + 1) = *nextloc++;
+
+    if (retval = krb5_parse_name(context, nextloc, &(entry->princ))) 
+       goto error_out;
+    if ((i != (strlen(nextloc) + 1)) || (sizeleft < i)) {
+       retval = KRB5_KDB_TRUNCATED_RECORD;
+       goto error_out;
+    }
+    sizeleft -= i;
+    nextloc += i;
+
+       /* tl_data is a linked list */
+    tl_data = &entry->tl_data;
+    for (i = 0; i < entry->n_tl_data; i++) {
+       if ((sizeleft -= 4) < 0) {
+           retval = KRB5_KDB_TRUNCATED_RECORD;
+           goto error_out;
+       }
+       if ((*tl_data = (krb5_tl_data *)
+         malloc(sizeof(krb5_tl_data))) == NULL) {
+           retval = ENOMEM;
+           goto error_out;
+       }
+       (*tl_data)->tl_data_next = NULL;
+       (*tl_data)->tl_data_contents = NULL;
+       *(((krb5_octet *)(&(*tl_data)->tl_data_type))) = *nextloc++;
+       *(((krb5_octet *)(&(*tl_data)->tl_data_type)) + 1) = *nextloc++;
+       *(((krb5_octet *)(&(*tl_data)->tl_data_length))) = *nextloc++;
+       *(((krb5_octet *)(&(*tl_data)->tl_data_length)) + 1) = *nextloc++;
+
+       if ((sizeleft -= (*tl_data)->tl_data_length) < 0) {
+           retval = KRB5_KDB_TRUNCATED_RECORD;
+           goto error_out;
+       }
+       if (((*tl_data)->tl_data_contents = (krb5_octet *)
+         malloc((*tl_data)->tl_data_length)) == NULL) {
+           retval = ENOMEM;
+           goto error_out;
+       }
+       memcpy((*tl_data)->tl_data_contents,nextloc,(*tl_data)->tl_data_length);
+       nextloc += (*tl_data)->tl_data_length;
+    }
+
+       /* key_data is an array */
+    if ((entry->key_data = (krb5_key_data *)
+      malloc(sizeof(krb5_key_data) * entry->n_key_data)) == NULL) {
+        retval = ENOMEM;
+       goto error_out;
+    }
+    for (i = 0; i < entry->n_key_data; i++) {
+       krb5_key_data * key_data;
+        int j;
+
+       if ((sizeleft -= 4) < 0) {
+           retval = KRB5_KDB_TRUNCATED_RECORD;
+           goto error_out;
+       }
+       key_data = entry->key_data + i;
+       *(((krb5_octet *)(&key_data->key_data_ver))) = *nextloc++;
+       *(((krb5_octet *)(&key_data->key_data_ver)) + 1) = *nextloc++;
+       *(((krb5_octet *)(&key_data->key_data_kvno))) = *nextloc++;
+       *(((krb5_octet *)(&key_data->key_data_kvno)) + 1) = *nextloc++;
+
+       /* key_data_ver determins number of elements and how to unparse them. */
+       if (key_data->key_data_ver < KRB5_KDB_V1_KEY_DATA_ARRAY) {
+           for (j = 0; j < key_data->key_data_ver; j++) {
+               if ((sizeleft -= 4) < 0) {
+                   retval = KRB5_KDB_TRUNCATED_RECORD;
+                   goto error_out;
+               }
+               *(((krb5_octet *)(&key_data->key_data_type[j]))) = *nextloc++;
+               *(((krb5_octet *)(&key_data->key_data_type[j]))+1) = *nextloc++;
+               *(((krb5_octet *)(&key_data->key_data_length[j]))) = *nextloc++;
+               *(((krb5_octet *)(&key_data->key_data_length[j]))+1)=*nextloc++;
+
+               if ((sizeleft -= key_data->key_data_length[j]) < 0) {
+                   retval = KRB5_KDB_TRUNCATED_RECORD;
+                   goto error_out;
+               }
+               if (key_data->key_data_length[j]) {
+                   if ((key_data->key_data_contents[j] = (krb5_octet *)
+                     malloc(key_data->key_data_length[j])) == NULL) {
+                       retval = ENOMEM;
+                       goto error_out;
+                   }
+                   memcpy(key_data->key_data_contents[j], nextloc, 
+                          key_data->key_data_length[j]);
+                   nextloc += key_data->key_data_length[j];
+               }
+           }
+       } else {
+           /* This isn't right. I'll fix it later */
+           abort();
+       }
+    }
+    return 0;
+
+error_out:;
+    krb5_dbe_free_contents(context, entry);
+    return retval;
+}
+           
+void
+krb5_dbe_free_contents(context, entry)
+     krb5_context        context; 
+     krb5_db_entry     * entry;
+{
+    krb5_tl_data       * tl_data_next;
+    krb5_tl_data       * tl_data;
+    int i, j;
+
+    if (entry->e_data)
+       free(entry->e_data);
+    if (entry->princ)
+       krb5_free_principal(context, entry->princ);
+    for (tl_data = entry->tl_data; tl_data; tl_data = tl_data_next) {
+       tl_data_next = tl_data->tl_data_next;
+       if (tl_data->tl_data_contents)
+           free(tl_data->tl_data_contents);
+       free(tl_data);
+    }
+    if (entry->key_data) {
+       for (i = 0; i < entry->n_key_data; i++) {
+           for (j = 0; j < entry->key_data[i].key_data_ver; j++) {
+               if (entry->key_data[i].key_data_length[j]) {
+                   if (entry->key_data[i].key_data_contents[j]) {
+                       memset(entry->key_data[i].key_data_contents[j], 
+                              0, entry->key_data[i].key_data_length[j]);
+                       free (entry->key_data[i].key_data_contents[j]);
+                   }
+               }
+               entry->key_data[i].key_data_contents[j] = NULL;
+               entry->key_data[i].key_data_length[j] = 0;
+               entry->key_data[i].key_data_type[j] = 0;
+           }
+       }
+       free(entry->key_data);
+    }
+    memset(entry, 0, sizeof(*entry));
+    return;
+}
+
index 1010b65dd34caa03949429266563feb47f2ed28d..f067f58dc95a9b8297897d350b26067e1feb20d4 100644 (file)
@@ -137,12 +137,20 @@ static kdb5_dispatch_table dbm_dispatch = {
 #ifdef dbm_error
     (int (*)()) NULL,          /* Get Database Error   */
 #else  /* dbm_error */
+#ifdef HAVE_DBM_ERROR
     dbm_error,                 /* Get Database Error   */
+#else
+    (int (*)()) NULL,          /* Get Database Error   */
+#endif
 #endif /* dbm_error */
 #ifdef dbm_clearerr
     (int (*)()) NULL,          /* Clear Database Error */
 #else  /* dbm_clearerr */
+#ifdef HAVE_DBM_CLEARERR
     dbm_clearerr,              /* Clear Database Error */
+#else
+    (int (*)()) NULL,          /* Clear Database Error */
+#endif
 #endif /* dbm_clearerr */
 #ifdef dbm_dirfno
     (int (*)()) NULL,          /* Get Database FD num  */
@@ -255,54 +263,56 @@ principal_found(nvalid, pname)
  */
 krb5_error_code
 add_principal(kcontext, principal, eblock, key, rseed)
-    krb5_context       kcontext;
-    krb5_principal     principal;
-    krb5_encrypt_block *eblock;
-    krb5_keyblock      *key;
-    krb5_pointer       rseed;
+    krb5_context         kcontext;
+    krb5_principal       principal;
+    krb5_encrypt_block * eblock;
+    krb5_keyblock      * key;
+    krb5_pointer         rseed;
 {
-    krb5_error_code            kret;
-    krb5_db_entry              dbent;
-    krb5_keyblock              *rkey;
-    krb5_keyblock              *kp;
-    int                                nentries = 1;
+    krb5_error_code      kret;
+    krb5_db_entry        dbent;
+    krb5_tl_mod_princ    mod_princ;
+    krb5_keyblock      * rkey = NULL;
+    int                          nentries = 1;
 
     memset((char *) &dbent, 0, sizeof(dbent));
-    rkey = (krb5_keyblock *) NULL;
-    dbent.principal = principal;
-    dbent.kvno = 1;
-    dbent.max_life = KRB5_KDB_MAX_LIFE;
-    dbent.max_renewable_life = KRB5_KDB_MAX_RLIFE;
-    dbent.mkvno = 1;
-    dbent.expiration = KRB5_KDB_EXPIRATION;
-    dbent.mod_name = principal;
-    dbent.attributes = KRB5_KDB_DEF_FLAGS;
-    if (kret = krb5_timeofday(kcontext, &dbent.mod_date))
-       return(kret);
+    dbent.len                  = KRB5_KDB_V1_BASE_LENGTH;
+
+    dbent.mkvno                = 1;
+    dbent.attributes           = KRB5_KDB_DEF_FLAGS;
+    dbent.max_life             = KRB5_KDB_MAX_LIFE;
+    dbent.expiration           = KRB5_KDB_EXPIRATION;
+    dbent.max_renewable_life   = KRB5_KDB_MAX_RLIFE;
+
+    if (kret = krb5_copy_principal(kcontext, principal, &dbent.princ))
+       goto out;
+
+    mod_princ.mod_princ = principal;
+    if (kret = krb5_timeofday(kcontext, &mod_princ.mod_date))
+       goto out;
+    if (kret = krb5_dbe_encode_mod_princ_data(kcontext, &mod_princ, &dbent))
+       goto out;
 
     if (!key) {
        if (kret = krb5_random_key(kcontext, eblock, rseed, &rkey))
-           return(kret);
-       kp = rkey;
-    }
-    else
-       kp = key;
+           goto out;
+    } else
+       rkey = key;
 
-    if (kret = krb5_kdb_encrypt_key(kcontext, eblock, kp, &dbent.key))
+    if (kret = krb5_dbe_create_key_data(kcontext, &dbent))
+       goto out;
+    if (kret = krb5_dbekd_encrypt_key_data(kcontext, eblock, rkey, NULL, 1,
+                                          &dbent.key_data[0]))
        goto out;
 
-    if (rkey)
+    if (!key)
        krb5_free_keyblock(kcontext, rkey);
 
-    dbent.salt_type = KRB5_KDB_SALTTYPE_NORMAL;
-    dbent.salt_length = 0;
-    dbent.salt = (krb5_octet *) NULL;
     kret = krb5_db_put_principal(kcontext, &dbent, &nentries);
-    if (!kret && (nentries != 1))
+    if ((!kret) && (nentries != 1))
        kret = KRB5KRB_ERR_GENERIC;
  out:
-    if (dbent.key.contents)
-       free(dbent.key.contents);
+    krb5_dbe_free_contents(kcontext, &dbent);
     return(kret);
 }
 
@@ -369,32 +379,42 @@ find_principal(kcontext, principal, docompare)
 {
     krb5_error_code    kret;
     krb5_db_entry      dbent;
+    krb5_tl_mod_princ *        mod_princ;
     int                        how_many;
     krb5_boolean       more;
 
-    how_many = 1;
     more = 0;
-    if (kret = krb5_db_get_principal(kcontext,
-                                    principal,
-                                    &dbent,
-                                    &how_many,
-                                    &more))
+    how_many = 1;
+    if (kret = krb5_db_get_principal(kcontext, principal, &dbent,
+                                    &how_many, &more))
+       return(kret);
+    if (how_many == 0) 
+       return(KRB5KRB_ERR_GENERIC);
+
+    if (kret = krb5_dbe_decode_mod_princ_data(kcontext, &dbent, &mod_princ)) {
+       krb5_db_free_principal(kcontext, &dbent, how_many);
        return(kret);
+    }
+
     if (docompare) {
-       if ((dbent.kvno != 1) ||
+       if ((dbent.mkvno != 1) ||
            (dbent.max_life != KRB5_KDB_MAX_LIFE) ||
            (dbent.max_renewable_life != KRB5_KDB_MAX_RLIFE) ||
-           (dbent.mkvno != 1) ||
            (dbent.expiration != KRB5_KDB_EXPIRATION) ||
            (dbent.attributes != KRB5_KDB_DEF_FLAGS) ||
-           !krb5_principal_compare(kcontext, principal, dbent.principal) ||
-           !krb5_principal_compare(kcontext, principal, dbent.mod_name))
+           !krb5_principal_compare(kcontext, principal, dbent.princ) ||
+           !krb5_principal_compare(kcontext, principal, mod_princ->mod_princ))
            kret = KRB5_PRINC_NOMATCH;
-       krb5_db_free_principal(kcontext, &dbent, how_many);
     }
-    if (!kret && how_many)
-       krb5_db_free_principal(kcontext, &dbent, how_many);
-    return(((how_many == 1) && (more == 0)) ? 0 : KRB5KRB_ERR_GENERIC);
+
+    krb5_db_free_principal(kcontext, &dbent, how_many);
+    krb5_free_principal(kcontext, mod_princ->mod_princ);
+    krb5_xfree(mod_princ);
+    if (!kret) 
+        return(((how_many == 1) && (more == 0)) ? 0 : KRB5KRB_ERR_GENERIC);
+    else
+        return(kret);
+
 }
 
 /*
index 4ef8304e3c189f02a614060258302367a15e602f..dbac6ff353d428d97f4e70296328422d880fbaae 100644 (file)
@@ -64,7 +64,9 @@ krb5_db_verify_master_key(context, mprinc, mkey, eblock)
        krb5_db_free_principal(context, &master_entry, nprinc);
        return(retval);
     }
-    if (retval = krb5_kdb_decrypt_key(context, eblock, &master_entry.key, &tempkey)) {
+    if (retval = krb5_dbekd_decrypt_key_data(context, eblock, 
+                                            &master_entry.key_data[0],
+                                            &tempkey, NULL)) {
        (void) krb5_finish_key(context, eblock);
        krb5_db_free_principal(context, &master_entry, nprinc);
        return retval;