diff options
Diffstat (limited to 'src/lib/kdb')
| -rw-r--r-- | src/lib/kdb/ChangeLog | 40 | ||||
| -rw-r--r-- | src/lib/kdb/Makefile.in | 21 | ||||
| -rw-r--r-- | src/lib/kdb/configure.in | 3 | ||||
| -rw-r--r-- | src/lib/kdb/kdb_cpw.c | 46 | ||||
| -rw-r--r-- | src/lib/kdb/kdb_dbm.c | 138 | ||||
| -rw-r--r-- | src/lib/kdb/kdb_xdr.c | 297 |
6 files changed, 368 insertions, 177 deletions
diff --git a/src/lib/kdb/ChangeLog b/src/lib/kdb/ChangeLog index fa274c12a..4e5440cc9 100644 --- a/src/lib/kdb/ChangeLog +++ b/src/lib/kdb/ChangeLog @@ -1,3 +1,25 @@ +Fri Jul 12 15:32:26 1996 Marc Horowitz <marc@mit.edu> + + * kdb_cpw.c (add_key_pwd): initialize retval = 0, in case the + function is called with ks_tuple_count == 0. + +Wed Jul 10 16:22:14 1996 Marc Horowitz <marc@mit.edu> + + * configure.in (USE_KDB5_LIBRARY): removed. the library does not + need itself to build, and in fact fails to do so if I try. + * Makefile.in (clean-unix): remove the shared/ subdir + +Tue Jul 9 17:55:30 1996 Marc Horowitz <marc@mit.edu> + + * configure.in, Makefile.in: added rules and macros to do shared + library creation + +Mon Jul 8 17:06:00 1996 Barry Jaspan <bjaspan@mit.edu> + + * kdb_dbm.c: Create DB_OPENCLOSE, which opens and closes the + databases for each lock. This is slower than the previous method, + but unlike the previous method it works. + Tue Jun 11 19:27:22 1996 Ezra Peisach <epeisach@kangaroo.mit.edu> * keytab.c (krb5_ktkdb_close): Free memory allocated by @@ -12,6 +34,24 @@ Sat May 18 15:07:09 1996 Ezra Peisach (epeisach@paris) * kdb_dbm.c: Do not provide prototypes for dbm_error or dbm_clearerr if they are really macros. +Sun May 12 01:03:07 1996 Marc Horowitz <marc@mit.edu> + + * kdb_xdr.c: reworked all of the krb5_dbe_* tl_data functions. + This was necessary so that the admin system could store it's own + tl_data, without needing code here. This has the side-effect of + eliminating some structures which added no value, therefore + changing about a half-dozen files elsewhere in the tree. + + * kdb_cpw.c (add_key_rnd): handle kvno incrementing in the caller, + not here. + (krb5_dbe_crk): increment the kvno here, not in add_key_rnd + (krb5_dbe_ark): increment the kvno here, not in add_key_rnd + (add_key_pwd): handle kvno incrementing in the caller, not here. + (krb5_dbe_cpw): take an arg to specify the new kvno. if it's + <= the old kvno, just increment. Otherwise, pass it to add_key_pwd. + This is why all the code in this revision was changed. + (krb5_dbe_apw): increment the kvno here, not in add_key_pwd + Tue May 7 19:48:57 1996 Ezra Peisach <epeisach@dumpster.rose.brandeis.edu> * t_kdb.c (do_testing): Compile if using BERK_DB and dbm is not diff --git a/src/lib/kdb/Makefile.in b/src/lib/kdb/Makefile.in index 7b1176d89..ba683222a 100644 --- a/src/lib/kdb/Makefile.in +++ b/src/lib/kdb/Makefile.in @@ -3,6 +3,10 @@ KRB5_RUN_ENV = @KRB5_RUN_ENV@ all:: $(OBJS) +.c.o: + $(CC) $(CFLAGS) -c $(srcdir)/$*.c +@SHARED_RULE@ + SRCS= \ $(srcdir)/keytab.c \ $(srcdir)/encrypt_key.c \ @@ -27,6 +31,21 @@ OBJS= \ setup_mkey.o \ store_mkey.o +LIB_SUBDIRS= . +LIBDONE = DONE + +all-unix:: shared +shared:: + test -d shared || mkdir shared + +clean-unix:: + $(RM) shared/* + -rmdir shared + +DONE: $(OBJS) + $(RM) DONE + echo $(OBJS) > DONE + libkdb5.a: $(OBJS) $(RM) $@ $(ARADD) $@ $(OBJS) @@ -37,7 +56,7 @@ install:: libkdb5.a $(RANLIB) $(DESTDIR)$(KRB5_LIBDIR)/libkdb5.a clean:: - $(RM) libkdb5.a + $(RM) libkdb5.a DONE t_kdb: t_kdb.o $(DEPLIBS) $(LD) $(LDFLAGS) $(LDARGS) -o t_kdb t_kdb.o $(LIBS) diff --git a/src/lib/kdb/configure.in b/src/lib/kdb/configure.in index ec7f93ec1..e480603e4 100644 --- a/src/lib/kdb/configure.in +++ b/src/lib/kdb/configure.in @@ -8,8 +8,9 @@ AC_HAVE_HEADERS(unistd.h) AC_CHECK_FUNCS(srand48 srand srandom umask) KRB5_RUN_FLAGS V5_USE_SHARED_LIB -USE_KDB5_LIBRARY KRB5_LIBRARIES +V5_SHARED_LIB_OBJS +V5_MAKE_SHARED_LIB(libkdb5,0.1,.., ./kdb) LinkFileDir(../libkdb5.a, libkdb5.a, ./kdb) AppendRule([all:: libkdb5.a]) AppendRule([all-unix:: ../libkdb5.a]) diff --git a/src/lib/kdb/kdb_cpw.c b/src/lib/kdb/kdb_cpw.c index 0928eba2a..54316dde0 100644 --- a/src/lib/kdb/kdb_cpw.c +++ b/src/lib/kdb/kdb_cpw.c @@ -188,7 +188,7 @@ add_key_rnd(context, master_eblock, ks_tuple, ks_tuple_count, db_entry, kvno) krb5_finish_key(context, &krbtgt_eblock); if (retval = krb5_dbekd_encrypt_key_data(context, master_eblock, - key, NULL, kvno + 1, + key, NULL, kvno, &db_entry->key_data[db_entry->n_key_data-1])) { krb5_free_keyblock(context, key); goto add_key_rnd_err; @@ -233,6 +233,9 @@ krb5_dbe_crk(context, master_eblock, ks_tuple, ks_tuple_count, db_entry) db_entry->key_data = NULL; db_entry->n_key_data = 0; + /* increment the kvno */ + kvno++; + if (retval = add_key_rnd(context, master_eblock, ks_tuple, ks_tuple_count, db_entry, kvno)) { cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data); @@ -271,15 +274,18 @@ krb5_dbe_ark(context, master_eblock, ks_tuple, ks_tuple_count, db_entry) db_entry->key_data = NULL; db_entry->n_key_data = 0; + /* increment the kvno */ + kvno++; + if (retval = add_key_rnd(context, master_eblock, ks_tuple, ks_tuple_count, db_entry, kvno)) { cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data); db_entry->n_key_data = key_data_count; db_entry->key_data = key_data; } else { - /* Copy keys with key_data_kvno = kvno */ + /* Copy keys with key_data_kvno == kvno - 1 ( = old kvno ) */ for (i = 0; i < key_data_count; i++) { - if (key_data[i].key_data_kvno = kvno) { + if (key_data[i].key_data_kvno == (kvno - 1)) { if (retval = krb5_dbe_create_key_data(context, db_entry)) { cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data); @@ -318,6 +324,8 @@ add_key_pwd(context, master_eblock, ks_tuple, ks_tuple_count, passwd, krb5_boolean found; int i, j; + retval = 0; + for (i = 0; i < ks_tuple_count; i++) { krb5_enctype new_enctype, old_enctype; @@ -405,7 +413,7 @@ add_key_pwd(context, master_eblock, ks_tuple, ks_tuple_count, passwd, if (retval = krb5_dbekd_encrypt_key_data(context, master_eblock, &key, (const krb5_keysalt *)&key_salt, - kvno + 1, &db_entry->key_data[db_entry->n_key_data-1])) { + kvno, &db_entry->key_data[db_entry->n_key_data-1])) { krb5_xfree(key.contents); return(retval); } @@ -421,28 +429,36 @@ add_key_pwd(context, master_eblock, ks_tuple, ks_tuple_count, passwd, * As a side effect all old keys are nuked. */ krb5_error_code -krb5_dbe_cpw(context, master_eblock, ks_tuple, ks_tuple_count, passwd, db_entry) +krb5_dbe_cpw(context, master_eblock, ks_tuple, ks_tuple_count, passwd, + new_kvno, db_entry) krb5_context context; krb5_encrypt_block * master_eblock; krb5_key_salt_tuple * ks_tuple; int ks_tuple_count; char * passwd; + int new_kvno; krb5_db_entry * db_entry; { int key_data_count; krb5_key_data * key_data; krb5_error_code retval; - int kvno; + int old_kvno; /* First save the old keydata */ - kvno = get_key_data_kvno(context, db_entry->n_key_data, db_entry->key_data); + old_kvno = get_key_data_kvno(context, db_entry->n_key_data, + db_entry->key_data); key_data_count = db_entry->n_key_data; key_data = db_entry->key_data; db_entry->key_data = NULL; db_entry->n_key_data = 0; + /* increment the kvno. if the requested kvno is too small, + increment the old kvno */ + if (new_kvno < old_kvno+1) + new_kvno = old_kvno+1; + if (retval = add_key_pwd(context, master_eblock, ks_tuple, ks_tuple_count, - passwd, db_entry, kvno)) { + passwd, db_entry, new_kvno)) { cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data); db_entry->n_key_data = key_data_count; db_entry->key_data = key_data; @@ -470,25 +486,29 @@ krb5_dbe_apw(context, master_eblock, ks_tuple, ks_tuple_count, passwd, db_entry) int key_data_count; krb5_key_data * key_data; krb5_error_code retval; - int kvno; + int old_kvno, new_kvno; int i; /* First save the old keydata */ - kvno = get_key_data_kvno(context, db_entry->n_key_data, db_entry->key_data); + old_kvno = get_key_data_kvno(context, db_entry->n_key_data, + db_entry->key_data); key_data_count = db_entry->n_key_data; key_data = db_entry->key_data; db_entry->key_data = NULL; db_entry->n_key_data = 0; + /* increment the kvno */ + new_kvno = old_kvno+1; + if (retval = add_key_pwd(context, master_eblock, ks_tuple, ks_tuple_count, - passwd, db_entry, kvno)) { + passwd, db_entry, new_kvno)) { cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data); db_entry->n_key_data = key_data_count; db_entry->key_data = key_data; } else { - /* Copy keys with key_data_kvno = kvno */ + /* Copy keys with key_data_kvno == old_kvno */ for (i = 0; i < key_data_count; i++) { - if (key_data[i].key_data_kvno = kvno) { + if (key_data[i].key_data_kvno == old_kvno) { if (retval = krb5_dbe_create_key_data(context, db_entry)) { cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data); diff --git a/src/lib/kdb/kdb_dbm.c b/src/lib/kdb/kdb_dbm.c index e42e31f9d..3931389f4 100644 --- a/src/lib/kdb/kdb_dbm.c +++ b/src/lib/kdb/kdb_dbm.c @@ -22,6 +22,8 @@ * */ +#define DB_OPENCLOSE + #if HAVE_UNISTD_H #include <unistd.h> #endif @@ -341,9 +343,13 @@ krb5_dbm_db_init(context) return(retval); db_ctx = context->db_context; +#ifdef DB_OPENCLOSE + db_ctx->db_dbm_ctx = NULL; +#else if (!(db_ctx->db_dbm_ctx = (DBM *)KDBM_OPEN(db_ctx, db_ctx->db_name, O_RDWR, 0600))) return errno; +#endif if (!(filename = gen_dbsuffix (db_ctx->db_name, KDBM_LOCK_EXT(db_ctx)))) return ENOMEM; @@ -367,7 +373,9 @@ krb5_dbm_db_init(context) return 0; err_out: +#ifndef DB_OPENCLOSE KDBM_CLOSE(db_ctx, db_ctx->db_dbm_ctx); +#endif db_ctx->db_dbm_ctx = (DBM *) NULL; k5dbm_clear_context(db_ctx); return (retval); @@ -387,6 +395,7 @@ krb5_dbm_db_fini(context) db_ctx = (krb5_db_context *) context->db_context; if (k5dbm_inited(context)) { +#ifndef DB_OPENCLOSE if (db_ctx->db_dbm_ctx) { /* dbm_close returns void, but it is possible for there to be an error in close(). Possible changes to this routine: check errno @@ -395,6 +404,7 @@ krb5_dbm_db_fini(context) KDBM_CLOSE(db_ctx, db_ctx->db_dbm_ctx); db_ctx->db_dbm_ctx = NULL; } +#endif if (close(db_ctx->db_lf_file)) retval = errno; @@ -471,6 +481,8 @@ krb5_dbm_db_get_mkey(context, db_context, eblock) * * Passing a null pointer as "name" will set back to the default. * If the alternate database doesn't exist, nothing is changed. + * + * XXX rethink this */ krb5_error_code @@ -621,6 +633,17 @@ krb5_dbm_db_lock(context, mode) if ((retval = krb5_dbm_db_get_age(context, NULL, &mod_time))) goto lock_error; +#ifdef DB_OPENCLOSE + if ((db = KDBM_OPEN(db_ctx, db_ctx->db_name, + mode == KRB5_LOCKMODE_SHARED ? O_RDONLY : O_RDWR, + 0600))) { + db_ctx->db_lf_time = mod_time; + db_ctx->db_dbm_ctx = db; + } else { + retval = errno; + goto lock_error; + } +#else if (mod_time != db_ctx->db_lf_time) { KDBM_CLOSE(db_ctx, db_ctx->db_dbm_ctx); if ((db = KDBM_OPEN(db_ctx, db_ctx->db_name, O_RDWR, 0600))) { @@ -631,12 +654,15 @@ krb5_dbm_db_lock(context, mode) goto lock_error; } } +#endif db_ctx->db_lock_mode = mode; db_ctx->db_locks_held++; return 0; lock_error:; + db_ctx->db_lock_mode = 0; + db_ctx->db_locks_held = 0; (void) krb5_dbm_db_unlock(context); return retval; } @@ -655,6 +681,10 @@ krb5_dbm_db_unlock(context) if (!db_ctx->db_locks_held) /* lock already unlocked */ return KRB5_KDB_NOTLOCKED; +#ifdef DB_OPENCLOSE + KDBM_CLOSE(db_ctx, db_ctx->db_dbm_ctx); +#endif + if (--(db_ctx->db_locks_held) == 0) { retval = krb5_lock_file(context, db_ctx->db_lf_file, KRB5_LOCKMODE_UNLOCK); @@ -720,9 +750,8 @@ destroy_file_suffix(dbname, suffix) if (filename == 0) return ENOMEM; if ((fd = open(filename, O_RDWR, 0)) < 0) { - int retval = errno == ENOENT ? 0 : errno; free(filename); - return retval; + return errno; } /* fstat() will probably not fail unless using a remote filesystem (which is inappropriate for the kerberos database) so this check @@ -796,26 +825,40 @@ krb5_dbm_db_destroy(context, dbname) krb5_context context; char *dbname; { - krb5_error_code retval; + krb5_error_code retval1, retval2, retval3; krb5_boolean tmpcontext; tmpcontext = 0; if (!context->db_context) { tmpcontext = 1; - if ((retval = k5dbm_init_context(context))) - return(retval); + if ((retval1 = k5dbm_init_context(context))) + return(retval1); } - if (KDBM_DATA_EXT(context->db_context) && - (retval = destroy_file_suffix(dbname, - KDBM_DATA_EXT(context->db_context)))) - return(retval); - if (KDBM_INDEX_EXT(context->db_context) && - (retval = destroy_file_suffix(dbname, - KDBM_INDEX_EXT(context->db_context)))) - return(retval); - if ((retval = destroy_file_suffix(dbname, - KDBM_LOCK_EXT(context->db_context)))) - return(retval); + retval1 = retval2 = retval3 = 0; + if (KDBM_DATA_EXT(context->db_context)) + retval1 = destroy_file_suffix(dbname, + KDBM_DATA_EXT(context->db_context)); + if (KDBM_INDEX_EXT(context->db_context)) + retval2 = destroy_file_suffix(dbname, + KDBM_INDEX_EXT(context->db_context)); + retval3 = destroy_file_suffix(dbname, + KDBM_LOCK_EXT(context->db_context)); + /* + * This kludgery is needed because it is possible to link + * against BSD DB but use the ndbm interface. The result is + * that the dispatch table thinks the file extensions are + * .dir and .pag, but the database layer uses .db. + */ + if (retval1 == ENOENT && retval2 == ENOENT && + KDBM_INDEX_EXT(context->db_context) && + strcmp(KDBM_INDEX_EXT(context->db_context), ".dir") == 0 && + KDBM_DATA_EXT(context->db_context) && + strcmp(KDBM_DATA_EXT(context->db_context), ".pag") == 0) { + retval1 = retval2 = destroy_file_suffix(dbname, ".db"); + } + if (retval1 || retval2 || retval3) + return (retval1 ? retval1 : (retval2 ? retval2 : retval3)); + if (tmpcontext) { k5dbm_clear_context((krb5_db_context *) context->db_context); free(context->db_context); @@ -841,6 +884,7 @@ krb5_dbm_db_rename(context, from, to) char *from; char *to; { + DBM *db; char *fromdir = 0; char *todir = 0; char *frompag = 0; @@ -853,19 +897,28 @@ krb5_dbm_db_rename(context, from, to) s_context = context->db_context; context->db_context = (void *) NULL; if (!(retval = k5dbm_init_context(context))) { + db_ctx = (krb5_db_context *) context->db_context; + + /* + * Create the database, failing if it already exists; the + * files must exist because krb5_dbm_db_lock, called below, + * will fail otherwise. + */ + db = KDBM_OPEN(db_ctx, to, O_RDWR|O_CREAT|O_EXCL, 0600); + if (db == NULL) { + retval = errno; + goto errout; + } + else + KDBM_CLOSE(db_ctx, db); + /* * Set the database to the target, so that other processes sharing * the target will stop their activity, and notice the new database. */ - db_ctx = (krb5_db_context *) context->db_context; - retval = krb5_dbm_db_set_name(context, to); - if (retval) { - if (retval == ENOENT) - db_ctx->db_name = strdup(to); - else + if (retval) goto errout; - } db_ctx->db_lf_name = gen_dbsuffix(db_ctx->db_name, KDBM_LOCK_EXT(db_ctx)); @@ -931,8 +984,39 @@ krb5_dbm_db_rename(context, from, to) (void) unlink(fromok); retval = krb5_dbm_db_end_update(context); } else { - (void) krb5_dbm_db_end_update(context); - retval = errno; + /* + * This kludgery is needed because it is possible to link + * against BSD DB but use the ndbm interface. The result is + * that the dispatch table thinks the file extensions are + * .dir and .pag, but the database layer uses .db. + */ + if (errno == ENOENT && + KDBM_INDEX_EXT(context->db_context) && + strcmp(KDBM_INDEX_EXT(context->db_context), ".dir") == 0 && + KDBM_DATA_EXT(context->db_context) && + strcmp(KDBM_DATA_EXT(context->db_context), ".pag") == 0) { + free(fromdir); free(todir); free(frompag); free(topag); + + fromdir = todir = NULL; + frompag = gen_dbsuffix (from, ".db"); + topag = gen_dbsuffix (to, ".db"); + if (!frompag || !topag) { + retval = ENOMEM; + goto errout; + } + if (rename(frompag, topag) == 0) { + /* We only need to unlink the source lock file */ + if (fromok) + (void) unlink(fromok); + retval = krb5_dbm_db_end_update(context); + } else { + (void) krb5_dbm_db_end_update(context); + retval = errno; + } + } else { + (void) krb5_dbm_db_end_update(context); + retval = errno; + } } @@ -1082,6 +1166,7 @@ krb5_dbm_db_put_principal(context, entries, nentries) } if (KDBM_STORE(db_ctx, db_ctx->db_dbm_ctx, key, contents, DBM_REPLACE)) retval = errno; +#ifndef DB_OPENCLOSE else { DBM *db; @@ -1093,6 +1178,7 @@ krb5_dbm_db_put_principal(context, entries, nentries) else retval = errno; } +#endif krb5_free_princ_contents(context, &contents); krb5_free_princ_dbmkey(context, &key); if (retval) @@ -1166,6 +1252,7 @@ krb5_dbm_db_delete_principal(context, searchfor, nentries) else { if (KDBM_DELETE(db_ctx, db, key)) retval = errno; +#ifndef DB_OPENCLOSE else { DBM *db; @@ -1177,6 +1264,7 @@ krb5_dbm_db_delete_principal(context, searchfor, nentries) else retval = errno; } +#endif } krb5_free_princ_contents(context, &contents2); cleancontents: diff --git a/src/lib/kdb/kdb_xdr.c b/src/lib/kdb/kdb_xdr.c index 5953d6dd2..044ce4c7f 100644 --- a/src/lib/kdb/kdb_xdr.c +++ b/src/lib/kdb/kdb_xdr.c @@ -23,200 +23,223 @@ */ #include "k5-int.h" +#include <string.h> #include <stdio.h> #include <errno.h> +#define safe_realloc(p,n) ((p)?(realloc(p,n)):(malloc(n))) + 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; - } + if ((entry->key_data = + (krb5_key_data *) safe_realloc(entry->key_data, + (sizeof(krb5_key_data)* + (entry->n_key_data + 1)))) == NULL) + return(ENOMEM); + + + memset(entry->key_data + entry->n_key_data, 0, sizeof(krb5_key_data)); entry->n_key_data++; + return 0; } krb5_error_code -krb5_dbe_encode_last_pwd_change(context, stamp, entry) +krb5_dbe_update_tl_data(context, entry, new_tl_data) krb5_context context; - krb5_tl_last_change * stamp; krb5_db_entry * entry; + krb5_tl_data * new_tl_data; { - 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; - } - } + krb5_tl_data * tl_data; + krb5_octet * tmp; + + /* copy the new data first, so we can fail cleanly if malloc() + fails */ - 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; + if ((tmp = (krb5_octet *) malloc(new_tl_data->tl_data_length)) == NULL) + return(ENOMEM); + + /* Find an existing entry of the specified type and point at + it, or NULL if not found */ + + for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) + if (tl_data->tl_data_type == new_tl_data->tl_data_type) + break; + + /* if necessary, chain a new record in the beginning and point at it */ + + if (!tl_data) { + if ((tl_data = (krb5_tl_data *) calloc(1, sizeof(krb5_tl_data))) + == NULL) { + free(tmp); + return(ENOMEM); + } + tl_data->tl_data_next = entry->tl_data; + entry->tl_data = tl_data; + entry->n_tl_data++; } - return ENOMEM; + + /* fill in the record */ + + if (tl_data->tl_data_contents) + free(tl_data->tl_data_contents); + + tl_data->tl_data_type = new_tl_data->tl_data_type; + tl_data->tl_data_length = new_tl_data->tl_data_length; + tl_data->tl_data_contents = tmp; + memcpy(tmp, new_tl_data->tl_data_contents, tl_data->tl_data_length); + + return(0); } krb5_error_code -krb5_dbe_decode_last_pwd_change(context, entry, stamp) +krb5_dbe_lookup_tl_data(context, entry, ret_tl_data) krb5_context context; krb5_db_entry * entry; - krb5_tl_last_change * stamp; + krb5_tl_data * ret_tl_data; { - krb5_tl_data * tl_data; + 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; - } + if (tl_data->tl_data_type == ret_tl_data->tl_data_type) { + *ret_tl_data = *tl_data; + return(0); + } } - stamp->last_pwd_change = 0; - return 0; + + /* if the requested record isn't found, return zero bytes. + if it ever means something to have a zero-length tl_data, + this code and its callers will have to be changed */ + + ret_tl_data->tl_data_length = 0; + ret_tl_data->tl_data_contents = NULL; + return(0); +} + +krb5_error_code +krb5_dbe_update_last_pwd_change(context, entry, stamp) + krb5_context context; + krb5_db_entry * entry; + krb5_timestamp stamp; +{ + krb5_tl_data tl_data; + krb5_octet buf[4]; /* this is the encoded size of an int32 */ + + tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE; + tl_data.tl_data_length = sizeof(buf); + krb5_kdb_encode_int32((krb5_int32) stamp, buf); + tl_data.tl_data_contents = buf; + + return(krb5_dbe_update_tl_data(context, entry, &tl_data)); } krb5_error_code -krb5_dbe_encode_mod_princ_data(context, mod_princ, entry) +krb5_dbe_lookup_last_pwd_change(context, entry, stamp) + krb5_context context; + krb5_db_entry * entry; + krb5_timestamp * stamp; +{ + krb5_tl_data tl_data; + krb5_error_code code; + krb5_int32 tmp; + + tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE; + + if (code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)) + return(code); + + if (tl_data.tl_data_length != 4) { + *stamp = 0; + return(0); + } + + krb5_kdb_decode_int32(tl_data.tl_data_contents, tmp); + + *stamp = (krb5_timestamp) tmp; + + return(0); +} + +/* it seems odd that there's no function to remove a tl_data, but if + I need one, I'll add one */ + +krb5_error_code +krb5_dbe_update_mod_princ_data(context, entry, mod_date, mod_princ) krb5_context context; - krb5_tl_mod_princ * mod_princ; krb5_db_entry * entry; + krb5_timestamp mod_date; + krb5_principal mod_princ; { + krb5_tl_data tl_data; + krb5_error_code retval = 0; - krb5_tl_data ** tl_data; krb5_octet * nextloc = 0; char * unparse_mod_princ = 0; 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))) + if ((retval = krb5_unparse_name(context, mod_princ, + &unparse_mod_princ))) return(retval); unparse_mod_princ_size = (int) strlen(unparse_mod_princ) + 1; - if ((nextloc = malloc(unparse_mod_princ_size + 4)) == NULL) { - retval = ENOMEM; - goto cleanup; - } - - /* 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; - } + if ((nextloc = (krb5_octet *) malloc(unparse_mod_princ_size + 4)) + == NULL) { + free(unparse_mod_princ); + return(ENOMEM); } - /* Allocate a new TL_MOD_PRINC structure if necessary */ - if (*tl_data == 0) { - (*tl_data) = (krb5_tl_data *)calloc(1, sizeof(krb5_tl_data)); - if (*tl_data == 0) { - retval = ENOMEM; - goto cleanup; - } - } - - 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; + 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 */ - krb5_kdb_encode_int32(mod_princ->mod_date, nextloc); - nextloc += 4; + krb5_kdb_encode_int32(mod_date, nextloc); /* Mod Princ */ - memcpy(nextloc, unparse_mod_princ, unparse_mod_princ_size); - nextloc = 0; + memcpy(nextloc+4, unparse_mod_princ, unparse_mod_princ_size); -cleanup: - if (nextloc) - free(nextloc); - if (unparse_mod_princ) - free(unparse_mod_princ); - return retval; + retval = krb5_dbe_update_tl_data(context, entry, &tl_data); + + free(unparse_mod_princ); + free(nextloc); + + return(retval); } krb5_error_code -krb5_dbe_decode_mod_princ_data(context, entry, mod_princ) +krb5_dbe_lookup_mod_princ_data(context, entry, mod_time, mod_princ) krb5_context context; krb5_db_entry * entry; - krb5_tl_mod_princ ** mod_princ; + krb5_timestamp * mod_time; + krb5_principal * mod_princ; { - krb5_error_code retval; - krb5_tl_data * tl_data; - krb5_octet * nextloc; + krb5_tl_data tl_data; + krb5_error_code code; + krb5_int32 tmp; - retval = 0; - 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_kdb_decode_int32(nextloc, (*mod_princ)->mod_date); - nextloc += 4; - - /* Mod Princ */ - if ((retval = krb5_parse_name(context, (const char *) nextloc, - &((*mod_princ)->mod_princ)))) - break; - if ((strlen((char *) nextloc) + 1 + 4) != - (size_t) tl_data->tl_data_length) { - retval = KRB5_KDB_TRUNCATED_RECORD; - break; - } - } - } + tl_data.tl_data_type = KRB5_TL_MOD_PRINC; - if (retval && (*mod_princ)) - free(*mod_princ); - return retval; + if (code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)) + return(code); + + if ((tl_data.tl_data_length < 5) || + (tl_data.tl_data_contents[tl_data.tl_data_length-1] != '\0')) + return(KRB5_KDB_TRUNCATED_RECORD); + + /* Mod Date */ + krb5_kdb_decode_int32(tl_data.tl_data_contents, *mod_time); + + /* Mod Princ */ + if ((code = krb5_parse_name(context, + (const char *) (tl_data.tl_data_contents+4), + mod_princ))) + return(code); + + return(0); } krb5_error_code |
