V4 kdb library
authorMark Eichin <eichin@mit.edu>
Thu, 27 Apr 1995 17:31:56 +0000 (17:31 +0000)
committerMark Eichin <eichin@mit.edu>
Thu, 27 Apr 1995 17:31:56 +0000 (17:31 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@5544 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/kdb4/.Sanitize [new file with mode: 0644]
src/lib/kdb4/.cvsignore [new file with mode: 0644]
src/lib/kdb4/ChangeLog [new file with mode: 0644]
src/lib/kdb4/Makefile.in [new file with mode: 0644]
src/lib/kdb4/configure.in [new file with mode: 0644]
src/lib/kdb4/krb_cache.c [new file with mode: 0644]
src/lib/kdb4/krb_dbl.c [new file with mode: 0644]
src/lib/kdb4/krb_dbm.c [new file with mode: 0644]
src/lib/kdb4/krb_kdb_utils.c [new file with mode: 0644]
src/lib/kdb4/krb_lib.c [new file with mode: 0644]
src/lib/kdb4/print_princ.c [new file with mode: 0644]

diff --git a/src/lib/kdb4/.Sanitize b/src/lib/kdb4/.Sanitize
new file mode 100644 (file)
index 0000000..e7c93b5
--- /dev/null
@@ -0,0 +1,41 @@
+# Sanitize.in for Kerberos V5
+
+# Each directory to survive it's way into a release will need a file
+# like this one called "./.Sanitize".  All keyword lines must exist,
+# and must exist in the order specified by this file.  Each directory
+# in the tree will be processed, top down, in the following order.
+
+# Hash started lines like this one are comments and will be deleted
+# before anything else is done.  Blank lines will also be squashed
+# out.
+
+# The lines between the "Do-first:" line and the "Things-to-keep:"
+# line are executed as a /bin/sh shell script before anything else is
+# done in this 
+
+Do-first:
+
+# All files listed between the "Things-to-keep:" line and the
+# "Files-to-sed:" line will be kept.  All other files will be removed.
+# Directories listed in this section will have their own Sanitize
+# called.  Directories not listed will be removed in their entirety
+# with rm -rf.
+
+Things-to-keep:
+
+.cvsignore
+ChangeLog
+Makefile.in
+configure.in
+krb_cache.c
+krb_dbl.c
+krb_dbm.c
+krb_kdb_utils.c
+krb_lib.c
+print_princ.c
+
+Things-to-lose:
+
+Do-last:
+
+# End of file.
diff --git a/src/lib/kdb4/.cvsignore b/src/lib/kdb4/.cvsignore
new file mode 100644 (file)
index 0000000..e8c05a6
--- /dev/null
@@ -0,0 +1 @@
+configure
diff --git a/src/lib/kdb4/ChangeLog b/src/lib/kdb4/ChangeLog
new file mode 100644 (file)
index 0000000..a9cd534
--- /dev/null
@@ -0,0 +1,68 @@
+Fri Jan 13 18:24:26 1995  Ian Lance Taylor  <ian@sanguine.cygnus.com>
+
+       * krb_kdb_utils.c (kdb_verify_master_key): Don't say ``BEWARE!'',
+       since it's not clear what to be wary of.
+
+Tue Jan 10 01:16:22 1995  Mark Eichin  <eichin@cygnus.com>
+
+       * krb_dbm.c: add macro for dbm_delete under dbm.
+       (kerb_db_del_principal): dbm_delete the key, and handle database
+       locking correctly.
+       * krb_lib.c (kerb_del_principal): get the principal, to sanity
+       check, and then delete it.
+
+Wed Jan  4 17:44:26 1995  Ian Lance Taylor  <ian@sanguine.cygnus.com>
+
+       * krb_kdb_utils.c (kdb_get_master_key_from): Add verify argument,
+       and pass it to read_password routine.
+       (kdb_get_master_key): Add verify argument, and pass it to
+       kdb_get_master_key_from.
+
+Thu Nov  3 16:33:34 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
+
+       * krb_dbm.c (kerb_db_rename): Initialize local variable ok.
+
+Tue Nov  1 16:29:32 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
+
+       * krb_lib.c: Don't bother to declare strncpy or ctime.  Declare
+       getenv only if it is needed.
+       (kerb_put_principal): Pass the address of a local time_t variable
+       to localtime, rather than principal->mod_date which has type
+       unsigned long.
+       * krb_cache.c: Don't declare strncpy.
+       * print_princ.c: Don't declare strncpy or ctime.
+
+Mon Oct 31 19:40:43 1994  Ian Lance Taylor  <ian@sanguine.cygnus.com>
+
+       * Makefile.in (CODE): Remove Imakefile.
+
+Thu Jul 21 17:40:14 1994  Mark Eichin  (eichin@cygnus.com)
+
+       * krb_kdb_utils.c (kdb_get_master_key_from): new function.
+       Modification of kdb_get_master_key (which is now only called by
+       things that force a prompt anyway, but is kept for compatibility.)
+       Takes an extra argument, optional filename to get the key from.
+
+Tue Jul  5 11:21:18 1994  Ken Raeburn  (raeburn@cujo.cygnus.com)
+
+       * print_princ.c (krb_print_principal): Arg to localtime() should
+       be time_t*.
+       * krb_lib.c (kerb_put_principal): Arg to time() should be time_t*.
+
+       * krb_kdb_utils.c: Include string.h.
+
+Tue Jun 21 00:19:04 1994  John Gilmore  (gnu@cygnus.com)
+
+       * krb_kdb_utils.c:  Lint.
+
+Fri May 20 01:31:04 1994  John Gilmore  (gnu@cygnus.com)
+
+       * Makefile.in:  Don't keep backup files of libraries.  Use LIBEXT.
+
+Fri May 13 02:01:36 1994  John Gilmore  (gnu@cygnus.com)
+
+       * krb_dbm.c:  Move <krb.h> to where it can control #if NDBM.
+
+Mon May  9 00:14:50 1994  John Gilmore  (gnu@cygnus.com)
+
+       * krb_lib.c:  Lint.
diff --git a/src/lib/kdb4/Makefile.in b/src/lib/kdb4/Makefile.in
new file mode 100644 (file)
index 0000000..02e4992
--- /dev/null
@@ -0,0 +1,39 @@
+CFLAGS = $(CCOPTS) $(DEFS) $(DEFINES)
+DEFINES=-I$(srcdir)/../../include/kerberosIV
+
+LIBNAME=libkdb4.$(LIBEXT)
+
+BUILDTOP=$(C)$(S)$(U)$(U)
+SRCS   = \
+       $(srcdir)/krb_dbm.c \
+       $(srcdir)/krb_lib.c \
+       $(srcdir)/krb_cache.c \
+       $(srcdir)/print_princ.c \
+       $(srcdir)/krb_kdb_utils.c
+
+OBJS   = \
+       krb_dbm.$(OBJEXT) \
+       krb_lib.$(OBJEXT) \
+       krb_cache.$(OBJEXT) \
+       print_princ.$(OBJEXT) \
+       krb_kdb_utils.$(OBJEXT)
+
+CODE= ${SRCS} Makefile.in
+
+all:: $(LIBNAME)
+
+$(LIBNAME): $(OBJS)
+       $(RM) $@
+       $(ARCHIVE) $@ $(OBJS)
+       $(RANLIB) $@
+
+clean::
+       $(RM) $(LIBNAME)
+       $(RM) $(OBJS)
+
+install::
+       $(INSTALL_DATA) $(LIBNAME) $(DESTDIR)$(KRB5_LIBDIR)/$(LIBNAME)
+       $(CHMOD) 644 $(DESTDIR)$(KRB5_LIBDIR)/$(LIBNAME)
+       $(RANLIB)    $(DESTDIR)$(KRB5_LIBDIR)/$(LIBNAME)
+       $(CHMOD) 444 $(DESTDIR)$(KRB5_LIBDIR)/$(LIBNAME)
+## 
diff --git a/src/lib/kdb4/configure.in b/src/lib/kdb4/configure.in
new file mode 100644 (file)
index 0000000..0f69f3b
--- /dev/null
@@ -0,0 +1,18 @@
+AC_INIT(configure.in)
+WITH_CCOPTS
+WITH_KRB5ROOT
+CONFIG_RULES
+AC_SET_BUILDTOP
+WITH_NETLIB
+AC_PROG_ARCHIVE
+AC_PROG_ARCHIVE_ADD
+AC_PROG_RANLIB
+AC_PROG_INSTALL
+AC_HEADER_CHECK(ndbm.h,AC_DEFINE(NDBM))
+AC_CONST
+CHECK_FCNTL
+AC_HEADER_CHECK(unistd.h,AC_DEFINE(HAS_UNISTD_H))
+ET_RULES
+SubdirLibraryRule([$(OBJS)])
+KRB_INCLUDE
+V5_AC_OUTPUT_MAKEFILE
diff --git a/src/lib/kdb4/krb_cache.c b/src/lib/kdb4/krb_cache.c
new file mode 100644 (file)
index 0000000..756573a
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology. 
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * This is where a cache would be implemented, if it were necessary.
+ */
+
+#include <mit-copyright.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <string.h>
+#include <des.h>
+#include <krb.h>
+#include <krb_db.h>
+
+#ifdef DEBUG
+extern int debug;
+extern long kerb_debug;
+#endif
+static  init = 0;
+
+/*
+ * initialization routine for cache 
+ */
+
+int
+kerb_cache_init()
+{
+    init = 1;
+    return (0);
+}
+
+/*
+ * look up a principal in the cache returns number of principals found 
+ */
+
+int
+kerb_cache_get_principal(serv, inst, principal, max)
+    char   *serv;              /* could have wild card */
+    char   *inst;              /* could have wild card */
+    Principal *principal;
+    unsigned int max;          /* max number of name structs to return */
+
+{
+    int     found = 0;
+
+    if (!init)
+       kerb_cache_init();
+#ifdef DEBUG
+    if (kerb_debug & 2)
+       fprintf(stderr, "cache_get_principal for %s %s max = %d\n",
+           serv, inst, max);
+#endif /* DEBUG */
+    
+#ifdef DEBUG
+    if (kerb_debug & 2) {
+       if (found) {
+           fprintf(stderr, "cache get %s %s found %s %s sid = %d\n",
+               serv, inst, principal->name, principal->instance);
+       } else {
+           fprintf(stderr, "cache %s %s not found\n", serv,
+               inst);
+       }
+    }
+#endif
+    return (found);
+}
+
+/*
+ * insert/replace a principal in the cache returns number of principals
+ * inserted 
+ */
+
+int
+kerb_cache_put_principal(principal, max)
+    Principal *principal;
+    unsigned int max;          /* max number of principal structs to
+                                * insert */
+
+{
+    u_long  i;
+    int     count = 0;
+
+    if (!init)
+       kerb_cache_init();
+
+#ifdef DEBUG
+    if (kerb_debug & 2) {
+       fprintf(stderr, "kerb_cache_put_principal  max = %d",
+           max);
+    }
+#endif
+    
+    for (i = 0; i < max; i++) {
+#ifdef DEBUG
+       if (kerb_debug & 2)
+           fprintf(stderr, "\n %s %s",
+                   principal->name, principal->instance);
+#endif 
+       /* DO IT */
+       count++;
+       principal++;
+    }
+    return count;
+}
+
+/*
+ * look up a dba in the cache returns number of dbas found 
+ */
+
+int
+kerb_cache_get_dba(serv, inst, dba, max)
+    char   *serv;              /* could have wild card */
+    char   *inst;              /* could have wild card */
+    Dba    *dba;
+    unsigned int max;          /* max number of name structs to return */
+
+{
+    int     found = 0;
+
+    if (!init)
+       kerb_cache_init();
+
+#ifdef DEBUG
+    if (kerb_debug & 2)
+       fprintf(stderr, "cache_get_dba for %s %s max = %d\n",
+           serv, inst, max);
+#endif
+
+#ifdef DEBUG
+    if (kerb_debug & 2) {
+       if (found) {
+           fprintf(stderr, "cache get %s %s found %s %s sid = %d\n",
+               serv, inst, dba->name, dba->instance);
+       } else {
+           fprintf(stderr, "cache %s %s not found\n", serv, inst);
+       }
+    }
+#endif
+    return (found);
+}
+
+/*
+ * insert/replace a dba in the cache returns number of dbas inserted 
+ */
+
+int
+kerb_cache_put_dba(dba, max)
+    Dba    *dba;
+    unsigned int max;          /* max number of dba structs to insert */
+
+{
+    u_long  i;
+    int     count = 0;
+
+    if (!init)
+       kerb_cache_init();
+#ifdef DEBUG
+    if (kerb_debug & 2) {
+       fprintf(stderr, "kerb_cache_put_dba  max = %d", max);
+    }
+#endif
+    for (i = 0; i < max; i++) {
+#ifdef DEBUG
+       if (kerb_debug & 2)
+           fprintf(stderr, "\n %s %s",
+                   dba->name, dba->instance);
+#endif 
+       /* DO IT */
+       count++;
+       dba++;
+    }
+    return count;
+}
+
diff --git a/src/lib/kdb4/krb_dbl.c b/src/lib/kdb4/krb_dbl.c
new file mode 100644 (file)
index 0000000..7776298
--- /dev/null
@@ -0,0 +1 @@
+This file is now obsolete.
diff --git a/src/lib/kdb4/krb_dbm.c b/src/lib/kdb4/krb_dbm.c
new file mode 100644 (file)
index 0000000..c67c020
--- /dev/null
@@ -0,0 +1,829 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology. 
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>. 
+ */
+
+#include <mit-copyright.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/resource.h>
+#include <sys/errno.h>
+#include <string.h>
+#include <des.h>
+#include <sys/file.h>
+/* before krb_db.h */
+#include <krb.h>
+#include <krb_db.h>
+
+#ifdef NDBM
+#include <ndbm.h>
+#else /*NDBM*/
+#include <dbm.h>
+#endif /*NDBM*/
+
+#ifdef POSIX
+#include <fcntl.h>
+#endif
+
+#define KERB_DB_MAX_RETRY 5
+
+#ifdef DEBUG
+extern int debug;
+extern long kerb_debug;
+extern char *progname;
+#endif
+extern char *malloc();
+extern int errno;
+
+static  init = 0;
+static char default_db_name[] = DBM_FILE;
+static char *current_db_name = default_db_name;
+static void encode_princ_key(), decode_princ_key();
+static void encode_princ_contents(), decode_princ_contents();
+static void kerb_dbl_fini();
+static int kerb_dbl_lock();
+static void kerb_dbl_unlock();
+
+static struct timeval timestamp;/* current time of request */
+static int non_blocking = 0;
+
+/*
+ * 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
+ * from underneath the KDC server.
+ */
+
+/*
+ * Locking:
+ * 
+ * There are two distinct locking protocols used.  One is designed to
+ * lock against processes (the admin_server, for one) which make
+ * incremental changes to the database; the other is designed to lock
+ * against utilities (kdb_util, kpropd) which replace the entire
+ * database in one fell swoop.
+ *
+ * The first locking protocol is implemented using flock() in the 
+ * krb_dbl_lock() and krb_dbl_unlock routines.
+ *
+ * The second locking protocol is necessary because DBM "files" are
+ * actually implemented as two separate files, and it is impossible to
+ * atomically rename two files simultaneously.  It assumes that the
+ * database is replaced only very infrequently in comparison to the time
+ * needed to do a database read operation.
+ *
+ * A third file is used as a "version" semaphore; the modification
+ * time of this file is the "version number" of the database.
+ * At the start of a read operation, the reader checks the version
+ * number; at the end of the read operation, it checks again.  If the
+ * version number changed, or if the semaphore was nonexistant at
+ * either time, the reader sleeps for a second to let things
+ * stabilize, and then tries again; if it does not succeed after
+ * KERB_DB_MAX_RETRY attempts, it gives up.
+ * 
+ * On update, the semaphore file is deleted (if it exists) before any
+ * update takes place; at the end of the update, it is replaced, with
+ * a version number strictly greater than the version number which
+ * existed at the start of the update.
+ * 
+ * If the system crashes in the middle of an update, the semaphore
+ * file is not automatically created on reboot; this is a feature, not
+ * a bug, since the database may be inconsistant.  Note that the
+ * absence of a semaphore file does not prevent another _update_ from
+ * taking place later.  Database replacements take place automatically
+ * only on slave servers; a crash in the middle of an update will be
+ * fixed by the next slave propagation.  A crash in the middle of an
+ * update on the master would be somewhat more serious, but this would
+ * likely be noticed by an administrator, who could fix the problem and
+ * retry the operation.
+ */
+
+/* Macros to convert ndbm names to dbm names.
+ * Note that dbm_nextkey() cannot be simply converted using a macro, since
+ * it is invoked giving the database, and nextkey() needs the previous key.
+ *
+ * Instead, all routines call "dbm_next" instead.
+ */
+
+#ifndef NDBM
+typedef char DBM;
+
+#define dbm_open(file, flags, mode) ((dbminit(file) == 0)?"":((char *)0))
+#define dbm_fetch(db, key) fetch(key)
+#define dbm_delete(db, key) delete(key)
+#define dbm_store(db, key, content, flag) store(key, content)
+#define dbm_firstkey(db) firstkey()
+#define dbm_next(db,key) nextkey(key)
+#define dbm_close(db) dbmclose()
+#else
+#define dbm_next(db,key) dbm_nextkey(db)
+#endif
+
+/*
+ * Utility routine: generate name of database file.
+ */
+
+static char *gen_dbsuffix(db_name, sfx)
+    char *db_name;
+    char *sfx;
+{
+    char *dbsuffix;
+    
+    if (sfx == NULL)
+       sfx = ".ok";
+
+    dbsuffix = malloc (strlen(db_name) + strlen(sfx) + 1);
+    strcpy(dbsuffix, db_name);
+    strcat(dbsuffix, sfx);
+    return dbsuffix;
+}
+
+/*
+ * initialization for data base routines.
+ */
+
+int kerb_db_init()
+{
+    init = 1;
+    return (0);
+}
+
+/*
+ * gracefully shut down database--must be called by ANY program that does
+ * a kerb_db_init 
+ */
+
+kerb_db_fini()
+{
+}
+
+/*
+ * Set the "name" of the current database to some alternate value.
+ *
+ * Passing a null pointer as "name" will set back to the default.
+ * If the alternate database doesn't exist, nothing is changed.
+ */
+
+int kerb_db_set_name(name)
+       char *name;
+{
+    DBM *db;
+
+    if (name == NULL)
+       name = default_db_name;
+    db = dbm_open(name, 0, 0);
+    if (db == NULL)
+       return errno;
+    dbm_close(db);
+    kerb_dbl_fini();
+    current_db_name = name;
+    return 0;
+}
+
+/*
+ * Return the last modification time of the database.
+ */
+
+long kerb_get_db_age()
+{
+    struct stat st;
+    char *okname;
+    long age;
+    
+    okname = gen_dbsuffix(current_db_name, ".ok");
+
+    if (stat (okname, &st) < 0)
+       age = 0;
+    else
+       age = st.st_mtime;
+
+    free (okname);
+    return age;
+}
+
+/*
+ * Remove the semaphore file; indicates that database is currently
+ * under renovation.
+ *
+ * This is only for use when moving the database out from underneath
+ * the server (for example, during slave updates).
+ */
+
+static long kerb_start_update(db_name)
+    char *db_name;
+{
+    char *okname = gen_dbsuffix(db_name, ".ok");
+    long age = kerb_get_db_age();
+    
+    if (unlink(okname) < 0
+       && errno != ENOENT) {
+           age = -1;
+    }
+    free (okname);
+    return age;
+}
+
+static long kerb_end_update(db_name, age)
+    char *db_name;
+    long age;
+{
+    int fd;
+    int retval = 0;
+    char *new_okname = gen_dbsuffix(db_name, ".ok#");
+    char *okname = gen_dbsuffix(db_name, ".ok");
+    
+    fd = open (new_okname, O_CREAT|O_RDWR|O_TRUNC, 0600);
+    if (fd < 0)
+       retval = errno;
+    else {
+       struct stat st;
+       struct timeval tv[2];
+       /* make sure that semaphore is "after" previous value. */
+       if (fstat (fd, &st) == 0
+           && st.st_mtime <= age) {
+           tv[0].tv_sec = st.st_atime;
+           tv[0].tv_usec = 0;
+           tv[1].tv_sec = age;
+           tv[1].tv_usec = 0;
+           /* set times.. */
+           utimes (new_okname, tv);
+#ifndef NO_FSYNC
+           fsync(fd);
+#endif
+       }
+       close(fd);
+       if (rename (new_okname, okname) < 0)
+           retval = errno;
+    }
+
+    free (new_okname);
+    free (okname);
+
+    return retval;
+}
+
+static long kerb_start_read()
+{
+    return kerb_get_db_age();
+}
+
+static long kerb_end_read(age)
+    u_long age;
+{
+    if (kerb_get_db_age() != age || age == -1) {
+       return -1;
+    }
+    return 0;
+}
+
+/*
+ * Create the database, assuming it's not there.
+ */
+
+int kerb_db_create(db_name)
+    char *db_name;
+{
+    char *okname = gen_dbsuffix(db_name, ".ok");
+    int fd;
+    register int ret = 0;
+#ifdef NDBM
+    DBM *db;
+
+    db = dbm_open(db_name, O_RDWR|O_CREAT|O_EXCL, 0600);
+    if (db == NULL)
+       ret = errno;
+    else
+       dbm_close(db);
+#else
+    char *dirname = gen_dbsuffix(db_name, ".dir");
+    char *pagname = gen_dbsuffix(db_name, ".pag");
+
+    fd = open(dirname, O_RDWR|O_CREAT|O_EXCL, 0600);
+    if (fd < 0)
+       ret = errno;
+    else {
+       close(fd);
+       fd = open (pagname, O_RDWR|O_CREAT|O_EXCL, 0600);
+       if (fd < 0)
+           ret = errno;
+       else
+           close(fd);
+    }
+    if (dbminit(db_name) < 0)
+       ret = errno;
+#endif
+    if (ret == 0) {
+       fd = open (okname, O_CREAT|O_RDWR|O_TRUNC, 0600);
+       if (fd < 0)
+           ret = errno;
+       close(fd);
+    }
+    return ret;
+}
+
+/*
+ * "Atomically" rename the database in a way that locks out read
+ * access in the middle of the rename.
+ *
+ * Not perfect; if we crash in the middle of an update, we don't
+ * necessarily know to complete the transaction the rename, but...
+ */
+
+int kerb_db_rename(from, to)
+    char *from;
+    char *to;
+{
+    char *fromdir = gen_dbsuffix (from, ".dir");
+    char *todir = gen_dbsuffix (to, ".dir");
+    char *frompag = gen_dbsuffix (from , ".pag");
+    char *topag = gen_dbsuffix (to, ".pag");
+    char *fromok = gen_dbsuffix(from, ".ok");
+    long trans = kerb_start_update(to);
+    int ok = 0;
+    
+    if ((rename (fromdir, todir) == 0)
+       && (rename (frompag, topag) == 0)) {
+       (void) unlink (fromok);
+       ok = 1;
+    }
+
+    free (fromok);
+    free (fromdir);
+    free (todir);
+    free (frompag);
+    free (topag);
+    if (ok)
+       return kerb_end_update(to, trans);
+    else
+       return -1;
+}
+
+/*
+ * look up a principal in the data base returns number of principals
+ * found, and whether there were more than requested. 
+ */
+
+int kerb_db_get_principal(name, inst, principal, max, more)
+    char   *name;              /* could have wild card */
+    char   *inst;              /* could have wild card */
+    Principal *principal;
+    unsigned int max;          /* max number of name structs to return */
+    int    *more;              /* where there more than 'max' tuples? */
+
+{
+    int     found = 0, code;
+    extern int errorproc();
+    int     wildp, wildi;
+    datum   key, contents;
+    char    testname[ANAME_SZ], testinst[INST_SZ];
+    u_long trans;
+    int try;
+    DBM    *db;
+
+    if (!init)
+       kerb_db_init();         /* initialize database routines */
+
+    for (try = 0; try < KERB_DB_MAX_RETRY; try++) {
+       trans = kerb_start_read();
+
+       if ((code = kerb_dbl_lock(KERB_DBL_SHARED)) != 0)
+           return -1;
+
+       db = dbm_open(current_db_name, O_RDONLY, 0600);
+
+       *more = 0;
+
+#ifdef DEBUG
+       if (kerb_debug & 2)
+           fprintf(stderr,
+                   "%s: db_get_principal for %s %s max = %d",
+                   progname, name, inst, max);
+#endif
+
+       wildp = !strcmp(name, "*");
+       wildi = !strcmp(inst, "*");
+
+       if (!wildi && !wildp) { /* nothing's wild */
+           encode_princ_key(&key, name, inst);
+           contents = dbm_fetch(db, key);
+           if (contents.dptr == NULL) {
+               found = 0;
+               goto done;
+           }
+           decode_princ_contents(&contents, principal);
+#ifdef DEBUG
+           if (kerb_debug & 1) {
+               fprintf(stderr, "\t found %s %s p_n length %d t_n length %d\n",
+                       principal->name, principal->instance,
+                       strlen(principal->name),
+                       strlen(principal->instance));
+           }
+#endif
+           found = 1;
+           goto done;
+       }
+       /* process wild cards by looping through entire database */
+
+       for (key = dbm_firstkey(db); key.dptr != NULL;
+            key = dbm_next(db, key)) {
+           decode_princ_key(&key, testname, testinst);
+           if ((wildp || !strcmp(testname, name)) &&
+               (wildi || !strcmp(testinst, inst))) { /* have a match */
+               if (found >= max) {
+                   *more = 1;
+                   goto done;
+               } else {
+                   found++;
+                   contents = dbm_fetch(db, key);
+                   decode_princ_contents(&contents, principal);
+#ifdef DEBUG
+                   if (kerb_debug & 1) {
+                       fprintf(stderr,
+                               "\tfound %s %s p_n length %d t_n length %d\n",
+                               principal->name, principal->instance,
+                               strlen(principal->name),
+                               strlen(principal->instance));
+                   }
+#endif
+                   principal++; /* point to next */
+               }
+           }
+       }
+
+    done:
+       kerb_dbl_unlock();      /* unlock read lock */
+       dbm_close(db);
+       if (kerb_end_read(trans) == 0)
+           break;
+       found = -1;
+       if (!non_blocking)
+           sleep(1);
+    }
+    return (found);
+}
+
+/*
+ * delete a principal from the data base returns number of principals
+ * found, and whether there were more than requested. 
+ */
+
+int kerb_db_del_principal(principal, n)
+    Principal *principal;
+    int n;                     
+{
+    int     found = 0, code;
+    DBM    *db;
+    u_long trans;
+    int try;
+    datum   key;
+
+    if (!init)
+       kerb_db_init();         /* initialize database routines */
+
+    for (try = 0; try < KERB_DB_MAX_RETRY; try++) {
+       trans = kerb_start_read();
+
+       if ((code = kerb_dbl_lock(KERB_DBL_SHARED)) != 0)
+           return -1;
+
+       db = dbm_open(current_db_name, O_RDWR, 0600);
+
+       encode_princ_key(&key, principal->name, principal->instance);
+       if (!dbm_delete(db, key)) {
+           found = 1;
+       } else {
+         krb_log("kerb_db_del_principal failed on %s %s <%s>",
+                 principal->name, principal->instance, key.dptr);
+       }
+       
+       kerb_dbl_unlock();      /* unlock read lock */
+       dbm_close(db);
+       if (kerb_end_read(trans) == 0)
+           break;
+       if (found) break;
+       found = -1;
+       if (!non_blocking)
+           sleep(1);
+    }
+    return (found);
+}
+
+/*
+ * Update a name in the data base.  Returns number of names
+ * successfully updated.
+ */
+
+int kerb_db_put_principal(principal, max)
+    Principal *principal;
+    unsigned int max;          /* number of principal structs to
+                                * update */
+
+{
+    int     found = 0, code;
+    u_long  i;
+    extern int errorproc();
+    datum   key, contents;
+    DBM    *db;
+
+    gettimeofday(&timestamp, NULL);
+
+    if (!init)
+       kerb_db_init();
+
+    if ((code = kerb_dbl_lock(KERB_DBL_EXCLUSIVE)) != 0)
+       return -1;
+
+    db = dbm_open(current_db_name, O_RDWR, 0600);
+
+#ifdef DEBUG
+    if (kerb_debug & 2)
+       fprintf(stderr, "%s: kerb_db_put_principal  max = %d",
+           progname, max);
+#endif
+
+    /* for each one, stuff temps, and do replace/append */
+    for (i = 0; i < max; i++) {
+       encode_princ_contents(&contents, principal);
+       encode_princ_key(&key, principal->name, principal->instance);
+       dbm_store(db, key, contents, DBM_REPLACE);
+#ifdef DEBUG
+       if (kerb_debug & 1) {
+           fprintf(stderr, "\n put %s %s\n",
+               principal->name, principal->instance);
+       }
+#endif
+       found++;
+       principal++;            /* bump to next struct                     */
+    }
+
+    dbm_close(db);
+    kerb_dbl_unlock();         /* unlock database */
+    return (found);
+}
+
+static void
+encode_princ_key(key, name, instance)
+    datum  *key;
+    char   *name, *instance;
+{
+    static char keystring[ANAME_SZ + INST_SZ];
+
+    memset(keystring, 0, ANAME_SZ + INST_SZ);
+    strncpy(keystring, name, ANAME_SZ);
+    strncpy(&keystring[ANAME_SZ], instance, INST_SZ);
+    key->dptr = keystring;
+    key->dsize = ANAME_SZ + INST_SZ;
+}
+
+static void
+decode_princ_key(key, name, instance)
+    datum  *key;
+    char   *name, *instance;
+{
+    strncpy(name, key->dptr, ANAME_SZ);
+    strncpy(instance, key->dptr + ANAME_SZ, INST_SZ);
+    name[ANAME_SZ - 1] = '\0';
+    instance[INST_SZ - 1] = '\0';
+}
+
+static void
+encode_princ_contents(contents, principal)
+    datum  *contents;
+    Principal *principal;
+{
+    contents->dsize = sizeof(*principal);
+    contents->dptr = (char *) principal;
+}
+
+static void
+decode_princ_contents(contents, principal)
+    datum  *contents;
+    Principal *principal;
+{
+    memcpy((char *) principal, contents->dptr, sizeof(*principal));
+}
+
+kerb_db_get_stat(s)
+    DB_stat *s;
+{
+    gettimeofday(&timestamp, NULL);
+
+
+    s->cpu = 0;
+    s->elapsed = 0;
+    s->dio = 0;
+    s->pfault = 0;
+    s->t_stamp = timestamp.tv_sec;
+    s->n_retrieve = 0;
+    s->n_replace = 0;
+    s->n_append = 0;
+    s->n_get_stat = 0;
+    s->n_put_stat = 0;
+    /* update local copy too */
+}
+
+kerb_db_put_stat(s)
+    DB_stat *s;
+{
+}
+
+delta_stat(a, b, c)
+    DB_stat *a, *b, *c;
+{
+    /* c = a - b then b = a for the next time */
+
+    c->cpu = a->cpu - b->cpu;
+    c->elapsed = a->elapsed - b->elapsed;
+    c->dio = a->dio - b->dio;
+    c->pfault = a->pfault - b->pfault;
+    c->t_stamp = a->t_stamp - b->t_stamp;
+    c->n_retrieve = a->n_retrieve - b->n_retrieve;
+    c->n_replace = a->n_replace - b->n_replace;
+    c->n_append = a->n_append - b->n_append;
+    c->n_get_stat = a->n_get_stat - b->n_get_stat;
+    c->n_put_stat = a->n_put_stat - b->n_put_stat;
+
+    memcpy(b, a, sizeof(DB_stat));
+    return;
+}
+
+/*
+ * look up a dba in the data base returns number of dbas found , and
+ * whether there were more than requested. 
+ */
+
+int kerb_db_get_dba(dba_name, dba_inst, dba, max, more)
+    char   *dba_name;          /* could have wild card */
+    char   *dba_inst;          /* could have wild card */
+    Dba    *dba;
+    unsigned int max;          /* max number of name structs to return */
+    int    *more;              /* where there more than 'max' tuples? */
+
+{
+    *more = 0;
+    return (0);
+}
+
+int kerb_db_iterate (func, arg)
+    int (*func)();
+    char *arg;                 /* void *, really */
+{
+    datum key, contents;
+    Principal *principal;
+    int code;
+    DBM *db;
+    
+    kerb_db_init();            /* initialize and open the database */
+    if ((code = kerb_dbl_lock(KERB_DBL_SHARED)) != 0)
+       return code;
+
+    db = dbm_open(current_db_name, O_RDONLY, 0600);
+
+    for (key = dbm_firstkey (db); key.dptr != NULL; key = dbm_next(db, key)) {
+       contents = dbm_fetch (db, key);
+       /* XXX may not be properly aligned */
+       principal = (Principal *) contents.dptr;
+       if ((code = (*func)(arg, principal)) != 0)
+           return code;
+    }
+    dbm_close(db);
+    kerb_dbl_unlock();
+    return 0;
+}
+
+static int dblfd = -1;
+static int mylock = 0;
+static int inited = 0;
+
+static int kerb_dbl_init()
+{
+    if (!inited) {
+       char *filename = gen_dbsuffix (current_db_name, ".ok");
+       if ((dblfd = open(filename, O_RDWR)) < 0) {
+           fprintf(stderr, "kerb_dbl_init: couldn't open %s\n", filename);
+           fflush(stderr);
+           perror("open");
+           exit(1);
+       }
+       free(filename);
+       inited++;
+    }
+    return (0);
+}
+
+static void kerb_dbl_fini()
+{
+    close(dblfd);
+    dblfd = -1;
+    inited = 0;
+    mylock = 0;
+}
+
+static int kerb_dbl_lock(mode)
+    int     mode;
+{
+#ifdef POSIX
+    struct flock f;
+    int rv;
+#else
+    int flock_mode;
+#endif
+    
+    if (!inited)
+       kerb_dbl_init();
+    if (mylock) {              /* Detect lock call when lock already
+                                * locked */
+       fprintf(stderr, "Kerberos locking error (mylock)\n");
+       fflush(stderr);
+       exit(1);
+    }
+#ifdef POSIX
+    memset(&f, 0, sizeof(f));
+#endif
+
+    switch (mode) {
+    case KERB_DBL_EXCLUSIVE:
+#ifdef POSIX
+       f.l_type = F_WRLCK;
+#else
+       flock_mode = LOCK_EX;
+#endif
+       break;
+
+    case KERB_DBL_SHARED:
+#ifdef POSIX
+       f.l_type = F_RDLCK;
+#else
+       flock_mode = LOCK_SH;
+#endif
+       break;
+
+    default:
+       fprintf(stderr, "invalid lock mode %d\n", mode);
+       abort();
+    }
+
+#ifdef POSIX
+    if (non_blocking)
+       rv = fcntl (dblfd, F_SETLK, &f);
+    else
+       rv = fcntl (dblfd, F_SETLKW, &f);
+    if (rv == -1)
+       return errno;
+#else
+    if (non_blocking)
+       flock_mode |= LOCK_NB;
+    if (flock(dblfd, flock_mode) < 0) 
+       return errno;
+#endif
+
+    mylock++;
+    return 0;
+}
+
+static void kerb_dbl_unlock()
+{
+#ifdef POSIX
+    struct flock f;
+#endif
+    
+    if (!mylock) {             /* lock already unlocked */
+       fprintf(stderr, "Kerberos database lock not locked when unlocking.\n");
+       fflush(stderr);
+       exit(1);
+    }
+#ifdef POSIX
+    memset(&f, 0, sizeof (f));
+    f.l_type = F_UNLCK;
+    if (fcntl(dblfd, F_SETLK, &f) < 0) {
+       fprintf(stderr, "Kerberos database lock error. (unlocking)\n");
+       fflush(stderr);
+       perror("fcntl");
+       exit(1);
+    }
+#else
+    if (flock(dblfd, LOCK_UN) < 0) {
+       fprintf(stderr, "Kerberos database lock error. (unlocking)\n");
+       fflush(stderr);
+       perror("flock");
+       exit(1);
+    }
+#endif
+    mylock = 0;
+}
+
+int kerb_db_set_lockmode(mode)
+    int mode;
+{
+    int old = non_blocking;
+    non_blocking = mode;
+    return old;
+}
diff --git a/src/lib/kdb4/krb_kdb_utils.c b/src/lib/kdb4/krb_kdb_utils.c
new file mode 100644 (file)
index 0000000..9421b30
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Utility routines for Kerberos programs which directly access
+ * the database.  This code was duplicated in too many places
+ * before I gathered it here.
+ *
+ * Jon Rochlis, MIT Telecom, March 1988
+ */
+
+#include <mit-copyright.h>
+#include <des.h>
+#include <krb.h>
+#include <krb_db.h>
+#include <kdc.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#ifdef NEED_SYS_FCNTL_H
+/* just for O_* for sco */
+#include <sys/fcntl.h>
+#endif
+
+long kdb_get_master_key_from(prompt, master_key, master_key_sched, verify,
+                            kfilename)
+     int prompt;
+     C_Block master_key;
+     Key_schedule master_key_sched;
+     int verify;
+     char *kfilename;
+{
+  int kfile;
+
+  if (prompt)  {
+#ifdef NOENCRYPTION
+      placebo_read_password(master_key,
+                           "Kerberos master key: ", verify);
+#else
+      des_read_password(master_key,
+                       "Kerberos master key: ", verify);
+#endif
+      printf ("\n");
+  }
+  else {
+    kfile = open(kfilename?kfilename:MKEYFILE, O_RDONLY, 0600);
+    if (kfile < 0) {
+      /* oh, for com_err_ */
+      return (-1);
+    }
+    if (read(kfile, (char *) master_key, 8) != 8) {
+      return (-1);
+    }
+    close(kfile);
+  }
+
+#ifndef NOENCRYPTION
+  key_sched(master_key, master_key_sched);
+#endif
+  return (0);
+}
+
+long kdb_get_master_key(prompt, master_key, master_key_sched, verify)
+     int prompt;
+     C_Block master_key;
+     Key_schedule master_key_sched;
+     int verify;
+{
+  return kdb_get_master_key_from(prompt, master_key, master_key_sched,
+                                verify, NULL);
+}
+
+/* The caller is reasponsible for cleaning up the master key and sched,
+   even if we can't verify the master key */
+
+/* Returns master key version if successful, otherwise -1 */
+
+long kdb_verify_master_key (master_key, master_key_sched, out)
+     C_Block master_key;
+     Key_schedule master_key_sched;
+     FILE *out;  /* setting this to non-null be do output */
+{
+  C_Block key_from_db;
+  Principal principal_data[1];
+  int n, more = 0;
+  long master_key_version;
+
+  /* lookup the master key version */
+  n = kerb_get_principal(KERB_M_NAME, KERB_M_INST, principal_data,
+                        1 /* only one please */, &more);
+  if ((n != 1) || more) {
+    if (out != (FILE *) NULL) 
+      fprintf(out,
+             "verify_master_key: %s, %d found.\n",
+             "Kerberos error on master key version lookup",
+             n);
+    return (-1);
+  }
+
+  master_key_version = (long) principal_data[0].key_version;
+
+  /* set up the master key */
+  if (out != (FILE *) NULL)  /* should we punt this? */
+    fprintf(out, "Current Kerberos master key version is %d.\n",
+           principal_data[0].kdc_key_ver);
+
+  /*
+   * now use the master key to decrypt the key in the db, had better
+   * be the same! 
+   */
+  memcpy(key_from_db, &principal_data[0].key_low, sizeof(KRB4_32));
+  memcpy(((KRB4_32 *) key_from_db) + 1, &principal_data[0].key_high, sizeof(KRB4_32));
+  kdb_encrypt_key (key_from_db, key_from_db, 
+                  master_key, master_key_sched, DECRYPT);
+
+  /* the decrypted database key had better equal the master key */
+  n = memcmp((char *) master_key, (char *) key_from_db,
+          sizeof(master_key));
+  /* this used to zero the master key here! */
+  memset(key_from_db, 0, sizeof(key_from_db));
+  memset(principal_data, 0, sizeof (principal_data));
+
+  if (n && (out != (FILE *) NULL)) {
+    fprintf(out, "\n\07\07verify_master_key: Invalid master key; ");
+    fprintf(out, "does not match database.\n");
+    return (-1);
+  }
+  if (out != (FILE *) NULL) {
+    fprintf(out, "\nMaster key entered.\n");
+    fflush(out);
+  }
+
+  return (master_key_version);
+}
+
+/* The old algorithm used the key schedule as the initial vector which
+   was byte order depedent ... */
+
+kdb_encrypt_key (in, out, master_key, master_key_sched, e_d_flag)
+     C_Block in, out, master_key;
+     Key_schedule master_key_sched;
+     int e_d_flag;
+{
+
+#ifdef NOENCRYPTION
+  memcpy(out, in, sizeof(C_Block));
+#else
+  pcbc_encrypt((C_Block *)in, (C_Block *)out, (long) sizeof(C_Block),
+              master_key_sched, (C_Block *)master_key, e_d_flag);
+#endif
+}
diff --git a/src/lib/kdb4/krb_lib.c b/src/lib/kdb4/krb_lib.c
new file mode 100644 (file)
index 0000000..3203af7
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology. 
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>. 
+ */
+
+#include <mit-copyright.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/uio.h>
+#ifdef NEED_TIME_H
+#include <time.h>
+#else
+#include <sys/time.h>
+#endif
+#ifdef NEED_SYS_TIME_H
+/* for timeval */
+#include <sys/time.h>
+#endif
+#include <sys/resource.h>
+#include <string.h>
+#include <des.h>
+#include <krb.h>
+#include <krb_db.h>
+
+#ifdef DEBUG
+extern int debug;
+extern char *progname;
+long    kerb_debug;
+#endif
+
+static  init = 0;
+
+/*
+ * initialization routine for data base 
+ */
+
+int
+kerb_init()
+{
+#ifdef DEBUG
+    if (!init) {
+        extern char *getenv ();
+       char *dbg = getenv("KERB_DBG");
+       if (dbg)
+           sscanf(dbg, "%d", &kerb_debug);
+       init = 1;
+    }
+#endif
+    kerb_db_init();
+
+#ifdef CACHE
+    kerb_cache_init();
+#endif
+
+    /* successful init, return 0, else errcode */
+    return (0);
+}
+
+/*
+ * finalization routine for database -- NOTE: MUST be called by any
+ * program using kerb_init.  ALSO will have to be modified to finalize
+ * caches, if they're ever really implemented. 
+ */
+
+int
+kerb_fini()
+{
+    kerb_db_fini();
+    return 0;
+}
+
+/*
+ * look up a principal in the cache or data base returns number of
+ * principals found 
+ */
+
+int
+kerb_get_principal(name, inst, principal, max, more)
+    char   *name;              /* could have wild card */
+    char   *inst;              /* could have wild card */
+    Principal *principal;
+    unsigned int max;          /* max number of name structs to return */
+    int    *more;              /* more tuples than room for */
+
+{
+    int     found = 0;
+#ifdef CACHE
+    static int wild = 0;
+#endif
+    if (!init)
+       kerb_init();
+
+#ifdef DEBUG
+    if (kerb_debug & 1)
+       fprintf(stderr, "\n%s: kerb_get_principal for %s %s max = %d\n",
+           progname, name, inst, max);
+#endif
+    
+    /*
+     * if this is a request including a wild card, have to go to db
+     * since the cache may not be exhaustive. 
+     */
+
+    /* clear the principal area */
+    memset((char *) principal, 0, max * sizeof(Principal));
+
+#ifdef CACHE
+    /*
+     * so check to see if the name contains a wildcard "*" or "?", not
+     * preceeded by a backslash. 
+     */
+    wild = 0;
+    if (strchr(name, '*') || strchr(name, '?') ||
+       strchr(inst, '*') || strchr(inst, '?'))
+       wild = 1;
+
+    if (!wild) {
+       /* try the cache first */
+       found = kerb_cache_get_principal(name, inst, principal, max, more);
+       if (found)
+           return (found);
+    }
+#endif
+    /* If we didn't try cache, or it wasn't there, try db */
+    found = kerb_db_get_principal(name, inst, principal, max, more);
+    /* try to insert principal(s) into cache if it was found */
+#ifdef CACHE
+    if (found) {
+       kerb_cache_put_principal(principal, found);
+    }
+#endif
+    return (found);
+}
+
+/*
+ * delete a principal from the data base returns number of
+ * principals deleted 
+ */
+
+int
+kerb_del_principal(name, inst, principal, max, more)
+    char   *name;              /* could have wild card */
+    char   *inst;              /* could have wild card */
+    Principal *principal;
+    unsigned int max;          /* max number of name structs to return */
+    int    *more;              /* more tuples than room for */
+
+{
+    int found;
+
+    if (!init)
+       kerb_init();
+
+    found = kerb_get_principal(name, inst, principal, max, more);
+
+    if (found) {
+       found = kerb_db_del_principal(principal, found);
+    }
+
+    return (found);
+}
+
+/* principals */
+int kerb_put_principal(principal, n)
+    Principal *principal;
+    unsigned int n;            /* number of principal structs to write */
+{
+    struct tm *tp, *localtime();
+    time_t mod_date;
+
+    /* set mod date */
+    principal->mod_date = mod_date = time((time_t *)0);
+    /* and mod date string */
+
+    tp = localtime(&mod_date);
+    (void) sprintf(principal->mod_date_txt, "%4d-%2d-%2d",
+                  tp->tm_year > 1900 ? tp->tm_year : tp->tm_year + 1900,
+                  tp->tm_mon + 1, tp->tm_mday); /* January is 0, not 1 */
+#ifdef DEBUG
+    if (kerb_debug & 1) {
+       int i;
+       fprintf(stderr, "\nkerb_put_principal...");
+       for (i = 0; i < n; i++) {
+           krb_print_principal(&principal[i]);
+       }
+    }
+#endif
+    /* write database */
+    if (kerb_db_put_principal(principal, n) < 0) {
+#ifdef DEBUG
+       if (kerb_debug & 1)
+           fprintf(stderr, "\n%s: kerb_db_put_principal err", progname);
+       /* watch out for cache */
+#endif
+       return -1;
+    }
+#ifdef CACHE
+    /* write cache */
+    if (!kerb_cache_put_principal(principal, n)) {
+#ifdef DEBUG
+       if (kerb_debug & 1)
+           fprintf(stderr, "\n%s: kerb_cache_put_principal err", progname);
+#endif
+       return -1;
+    }
+#endif
+    return 0;
+}
+
+int
+kerb_get_dba(name, inst, dba, max, more)
+    char   *name;              /* could have wild card */
+    char   *inst;              /* could have wild card */
+    Dba    *dba;
+    unsigned int max;          /* max number of name structs to return */
+    int    *more;              /* more tuples than room for */
+
+{
+    int     found = 0;
+#ifdef CACHE
+    static int wild = 0;
+#endif
+    if (!init)
+       kerb_init();
+
+#ifdef DEBUG
+    if (kerb_debug & 1)
+       fprintf(stderr, "\n%s: kerb_get_dba for %s %s max = %d\n",
+           progname, name, inst, max);
+#endif
+    /*
+     * if this is a request including a wild card, have to go to db
+     * since the cache may not be exhaustive. 
+     */
+
+    /* clear the dba area */
+    memset((char *) dba, 0, max * sizeof(Dba));
+
+#ifdef CACHE
+    /*
+     * so check to see if the name contains a wildcard "*" or "?", not
+     * preceeded by a backslash. 
+     */
+
+    wild = 0;
+    if (strchr(name, '*') || strchr(name, '?') ||
+       strchr(inst, '*') || strchr(inst, '?'))
+       wild = 1;
+
+    if (!wild) {
+       /* try the cache first */
+       found = kerb_cache_get_dba(name, inst, dba, max, more);
+       if (found)
+           return (found);
+    }
+#endif
+    /* If we didn't try cache, or it wasn't there, try db */
+    found = kerb_db_get_dba(name, inst, dba, max, more);
+#ifdef CACHE
+    /* try to insert dba(s) into cache if it was found */
+    if (found) {
+       kerb_cache_put_dba(dba, found);
+    }
+#endif
+    return (found);
+}
diff --git a/src/lib/kdb4/print_princ.c b/src/lib/kdb4/print_princ.c
new file mode 100644 (file)
index 0000000..9c47ddf
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright 1988 by the Massachusetts Institute of Technology. 
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>. 
+ */
+
+#include <mit-copyright.h>
+#include <stdio.h>
+#include <sys/types.h>
+#ifdef NEED_TIME_H
+#include <time.h>
+#endif
+#include <sys/time.h>
+#include <string.h>
+#include <krb.h>
+#include <krb_db.h>
+
+extern int debug;
+extern struct tm *localtime();
+struct tm *time_p;
+
+long    kerb_debug;
+
+krb_print_principal(a_n)
+    Principal *a_n;
+{
+    /* run-time database does not contain string versions */
+    time_t exp_date = a_n->exp_date;
+    time_p = localtime(&exp_date);
+
+    fprintf(stderr,
+    "\n%s %s expires %4d-%2d-%2d %2d:%2d, max_life %d*5 = %d min  attr 0x%02x",
+    a_n->name, a_n->instance,
+    time_p->tm_year > 1900 ? time_p->tm_year : time_p->tm_year + 1900,
+    time_p->tm_mon + 1, time_p->tm_mday,
+    time_p->tm_hour, time_p->tm_min,
+    a_n->max_life, 5 * a_n->max_life, a_n->attributes);
+
+    fprintf(stderr,
+    "\n\tkey_ver %d  k_low 0x%08x  k_high 0x%08x  akv %d  exists %d\n",
+    a_n->key_version, a_n->key_low, a_n->key_high,
+    a_n->kdc_key_ver, a_n->old);
+
+    fflush(stderr);
+}