summaryrefslogtreecommitdiffstats
path: root/src/lib/kdb
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/kdb')
-rw-r--r--src/lib/kdb/ChangeLog40
-rw-r--r--src/lib/kdb/Makefile.in21
-rw-r--r--src/lib/kdb/configure.in3
-rw-r--r--src/lib/kdb/kdb_cpw.c46
-rw-r--r--src/lib/kdb/kdb_dbm.c138
-rw-r--r--src/lib/kdb/kdb_xdr.c297
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