aboutsummaryrefslogtreecommitdiff
path: root/src/lib/kdb
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/kdb')
-rw-r--r--src/lib/kdb/ChangeLog27
-rw-r--r--src/lib/kdb/Makefile.in100
-rw-r--r--src/lib/kdb/adb_err.et16
-rw-r--r--src/lib/kdb/configure.in4
-rw-r--r--src/lib/kdb/decrypt_key.c11
-rw-r--r--src/lib/kdb/encrypt_key.c13
-rw-r--r--src/lib/kdb/err_handle.c193
-rw-r--r--src/lib/kdb/err_handle.h32
-rw-r--r--src/lib/kdb/fetch_mkey.c182
-rw-r--r--src/lib/kdb/kdb5.c2051
-rw-r--r--src/lib/kdb/kdb5.h219
-rw-r--r--src/lib/kdb/kdb_cpw.c126
-rw-r--r--src/lib/kdb/kdb_db2/ChangeLog17
-rw-r--r--src/lib/kdb/kdb_db2/Makefile.in150
-rw-r--r--src/lib/kdb/kdb_db2/adb_openclose.c412
-rw-r--r--src/lib/kdb/kdb_db2/adb_policy.c389
-rw-r--r--src/lib/kdb/kdb_db2/configure.in22
-rw-r--r--src/lib/kdb/kdb_db2/db2_exp.c64
-rw-r--r--src/lib/kdb/kdb_db2/kdb_compat.h (renamed from src/lib/kdb/kdb_compat.h)0
-rw-r--r--src/lib/kdb/kdb_db2/kdb_db2.c (renamed from src/lib/kdb/kdb_db2.c)672
-rw-r--r--src/lib/kdb/kdb_db2/kdb_db2.h (renamed from src/lib/kdb/kdb_db2.h)138
-rw-r--r--src/lib/kdb/kdb_db2/kdb_xdr.c (renamed from src/lib/kdb/kdb_xdr.c)2
-rw-r--r--src/lib/kdb/kdb_db2/kdb_xdr.h32
-rw-r--r--src/lib/kdb/kdb_db2/libkdb_db2.exports1
-rw-r--r--src/lib/kdb/kdb_db2/pol_xdr.c88
-rw-r--r--src/lib/kdb/kdb_db2/policy_db.h87
-rw-r--r--src/lib/kdb/kdb_default.c329
-rw-r--r--src/lib/kdb/keytab.c13
-rw-r--r--src/lib/kdb/libkdb5.exports13
-rw-r--r--src/lib/kdb/setup_mkey.c74
-rw-r--r--src/lib/kdb/store_mkey.c106
-rw-r--r--src/lib/kdb/t_kdb.c1091
-rw-r--r--src/lib/kdb/t_krb5.conf29
-rw-r--r--src/lib/kdb/verify_mky.c81
34 files changed, 5044 insertions, 1740 deletions
diff --git a/src/lib/kdb/ChangeLog b/src/lib/kdb/ChangeLog
index 99e6b58..740cef0 100644
--- a/src/lib/kdb/ChangeLog
+++ b/src/lib/kdb/ChangeLog
@@ -1,3 +1,30 @@
+2005-06-20 Ken Raeburn <raeburn@mit.edu>
+
+ Novell merge.
+ * Makefile.in:
+ * adb_err.et:
+ * configure.in:
+ * decrypt_key.c:
+ * encrypt_key.c:
+ * err_handle.c:
+ * err_handle.h:
+ * fetch_mkey.c:
+ * kdb5.c:
+ * kdb5.h:
+ * kdb_compat.h:
+ * kdb_cpw.c:
+ * kdb_db2.c:
+ * kdb_db2.h:
+ * kdb_default.c:
+ * kdb_xdr.c:
+ * keytab.c:
+ * libkrb5.exports:
+ * setup_mkey.c:
+ * store_mkey.c:
+ * t_kdb.c:
+ * t_krb5.conf:
+ * verify_mky.c:
+
2005-06-09 Ken Raeburn <raeburn@mit.edu>
* kdb_dbm.c: Unused file deleted.
diff --git a/src/lib/kdb/Makefile.in b/src/lib/kdb/Makefile.in
index 396ce1e..84c94c2 100644
--- a/src/lib/kdb/Makefile.in
+++ b/src/lib/kdb/Makefile.in
@@ -6,6 +6,8 @@ KRB5_RUN_ENV = @KRB5_RUN_ENV@
KRB5_CONFIG_SETUP = KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf ; export KRB5_CONFIG ;
PROG_LIBPATH=-L$(TOPLIBD)
PROG_RPATH=$(KRB5_LIBDIR)
+CFLAGS=@CFLAGS@ -DKDB5_USE_LIB_KDB_DB2
+LOCALINCLUDES= -I.
LIBBASE=kdb5
LIBMAJOR=4
@@ -29,30 +31,29 @@ DBOBJLISTS-k5 = $(DBDIR)/hash/OBJS.ST $(DBDIR)/btree/OBJS.ST \
all::
+adb_err.$(OBJEXT): adb_err.c
+adb_err.c adb_err.h: $(srcdir)/adb_err.et
+
SRCS= \
- $(srcdir)/keytab.c \
+ $(srcdir)/kdb5.c \
$(srcdir)/encrypt_key.c \
$(srcdir)/decrypt_key.c \
+ $(srcdir)/kdb_default.c \
$(srcdir)/kdb_cpw.c \
- $(srcdir)/kdb_db2.c \
- $(srcdir)/kdb_xdr.c \
- $(srcdir)/verify_mky.c \
- $(srcdir)/fetch_mkey.c \
- $(srcdir)/setup_mkey.c \
- $(srcdir)/store_mkey.c
+ adb_err.c \
+ $(srcdir)/err_handle.c \
+ $(srcdir)/keytab.c
STOBJLISTS=OBJS.ST $(DBOBJLISTS)
STLIBOBJS= \
- keytab.o \
+ kdb5.o \
encrypt_key.o \
decrypt_key.o \
+ kdb_default.o \
kdb_cpw.o \
- kdb_db2.o \
- kdb_xdr.o \
- verify_mky.o \
- fetch_mkey.o \
- setup_mkey.o \
- store_mkey.o
+ adb_err.o \
+ err_handle.o \
+ keytab.o
all-unix:: all-liblinks
install-unix:: install-libs
@@ -78,14 +79,14 @@ clean::
# Makefile dependencies follow. This must be the last section in
# the Makefile.in file
#
-keytab.so keytab.po $(OUTPRE)keytab.$(OBJEXT): keytab.c \
- $(SRCTOP)/include/k5-int.h $(BUILDTOP)/include/krb5/osconf.h \
- $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-platform.h \
- $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-thread.h \
- $(BUILDTOP)/include/krb5.h $(COM_ERR_DEPS) $(BUILDTOP)/include/profile.h \
- $(SRCTOP)/include/port-sockets.h $(BUILDTOP)/include/krb5/autoconf.h \
- $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/krb5/kdb.h \
- $(SRCTOP)/include/krb5/kdb_kt.h $(SRCTOP)/include/krb5/kdb.h
+kdb5.so kdb5.po $(OUTPRE)kdb5.$(OBJEXT): kdb5.c $(SRCTOP)/include/k5-int.h \
+ $(BUILDTOP)/include/krb5/osconf.h $(BUILDTOP)/include/krb5/autoconf.h \
+ $(SRCTOP)/include/k5-platform.h $(BUILDTOP)/include/krb5/autoconf.h \
+ $(SRCTOP)/include/k5-thread.h $(BUILDTOP)/include/krb5.h \
+ $(COM_ERR_DEPS) $(BUILDTOP)/include/profile.h $(SRCTOP)/include/port-sockets.h \
+ $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/socket-utils.h \
+ $(SRCTOP)/include/krb5/kdb.h $(BUILDTOP)/include/krb5/osconf.h \
+ kdb5.h err_handle.h ./adb_err.h
encrypt_key.so encrypt_key.po $(OUTPRE)encrypt_key.$(OBJEXT): \
encrypt_key.c $(SRCTOP)/include/k5-int.h $(BUILDTOP)/include/krb5/osconf.h \
$(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-platform.h \
@@ -100,54 +101,35 @@ decrypt_key.so decrypt_key.po $(OUTPRE)decrypt_key.$(OBJEXT): \
$(BUILDTOP)/include/krb5.h $(COM_ERR_DEPS) $(BUILDTOP)/include/profile.h \
$(SRCTOP)/include/port-sockets.h $(BUILDTOP)/include/krb5/autoconf.h \
$(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/krb5/kdb.h
-kdb_cpw.so kdb_cpw.po $(OUTPRE)kdb_cpw.$(OBJEXT): kdb_cpw.c \
- $(SRCTOP)/include/k5-int.h $(BUILDTOP)/include/krb5/osconf.h \
- $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-platform.h \
- $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-thread.h \
- $(BUILDTOP)/include/krb5.h $(COM_ERR_DEPS) $(BUILDTOP)/include/profile.h \
- $(SRCTOP)/include/port-sockets.h $(BUILDTOP)/include/krb5/autoconf.h \
- $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/krb5/kdb.h \
- $(SRCTOP)/include/krb5/adm.h
-kdb_db2.so kdb_db2.po $(OUTPRE)kdb_db2.$(OBJEXT): kdb_db2.c \
- $(SRCTOP)/include/k5-int.h $(BUILDTOP)/include/krb5/osconf.h \
- $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-platform.h \
- $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-thread.h \
- $(BUILDTOP)/include/krb5.h $(COM_ERR_DEPS) $(BUILDTOP)/include/profile.h \
- $(SRCTOP)/include/port-sockets.h $(BUILDTOP)/include/krb5/autoconf.h \
- $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/krb5/kdb.h \
- $(DB_DEPS) kdb_compat.h kdb_db2.h
-kdb_xdr.so kdb_xdr.po $(OUTPRE)kdb_xdr.$(OBJEXT): kdb_xdr.c \
- $(SRCTOP)/include/k5-int.h $(BUILDTOP)/include/krb5/osconf.h \
- $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-platform.h \
- $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-thread.h \
- $(BUILDTOP)/include/krb5.h $(COM_ERR_DEPS) $(BUILDTOP)/include/profile.h \
- $(SRCTOP)/include/port-sockets.h $(BUILDTOP)/include/krb5/autoconf.h \
- $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/krb5/kdb.h
-verify_mky.so verify_mky.po $(OUTPRE)verify_mky.$(OBJEXT): \
- verify_mky.c $(SRCTOP)/include/k5-int.h $(BUILDTOP)/include/krb5/osconf.h \
- $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-platform.h \
- $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-thread.h \
- $(BUILDTOP)/include/krb5.h $(COM_ERR_DEPS) $(BUILDTOP)/include/profile.h \
- $(SRCTOP)/include/port-sockets.h $(BUILDTOP)/include/krb5/autoconf.h \
- $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/krb5/kdb.h
-fetch_mkey.so fetch_mkey.po $(OUTPRE)fetch_mkey.$(OBJEXT): \
- fetch_mkey.c $(SRCTOP)/include/k5-int.h $(BUILDTOP)/include/krb5/osconf.h \
+kdb_default.so kdb_default.po $(OUTPRE)kdb_default.$(OBJEXT): \
+ kdb_default.c $(SRCTOP)/include/k5-int.h $(BUILDTOP)/include/krb5/osconf.h \
$(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-platform.h \
$(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-thread.h \
$(BUILDTOP)/include/krb5.h $(COM_ERR_DEPS) $(BUILDTOP)/include/profile.h \
$(SRCTOP)/include/port-sockets.h $(BUILDTOP)/include/krb5/autoconf.h \
$(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/krb5/kdb.h
-setup_mkey.so setup_mkey.po $(OUTPRE)setup_mkey.$(OBJEXT): \
- setup_mkey.c $(SRCTOP)/include/k5-int.h $(BUILDTOP)/include/krb5/osconf.h \
+kdb_cpw.so kdb_cpw.po $(OUTPRE)kdb_cpw.$(OBJEXT): kdb_cpw.c \
+ $(SRCTOP)/include/k5-int.h $(BUILDTOP)/include/krb5/osconf.h \
$(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-platform.h \
$(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-thread.h \
$(BUILDTOP)/include/krb5.h $(COM_ERR_DEPS) $(BUILDTOP)/include/profile.h \
$(SRCTOP)/include/port-sockets.h $(BUILDTOP)/include/krb5/autoconf.h \
$(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/krb5/kdb.h
-store_mkey.so store_mkey.po $(OUTPRE)store_mkey.$(OBJEXT): \
- store_mkey.c $(SRCTOP)/include/k5-int.h $(BUILDTOP)/include/krb5/osconf.h \
+adb_err.so adb_err.po $(OUTPRE)adb_err.$(OBJEXT): adb_err.c \
+ $(COM_ERR_DEPS)
+err_handle.so err_handle.po $(OUTPRE)err_handle.$(OBJEXT): \
+ err_handle.c err_handle.h $(SRCTOP)/include/k5-int.h \
+ $(BUILDTOP)/include/krb5/osconf.h $(BUILDTOP)/include/krb5/autoconf.h \
+ $(SRCTOP)/include/k5-platform.h $(BUILDTOP)/include/krb5/autoconf.h \
+ $(SRCTOP)/include/k5-thread.h $(BUILDTOP)/include/krb5.h \
+ $(COM_ERR_DEPS) $(BUILDTOP)/include/profile.h $(SRCTOP)/include/port-sockets.h \
+ $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/socket-utils.h \
+ $(SRCTOP)/include/krb5/kdb.h
+keytab.so keytab.po $(OUTPRE)keytab.$(OBJEXT): keytab.c \
+ $(SRCTOP)/include/k5-int.h $(BUILDTOP)/include/krb5/osconf.h \
$(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-platform.h \
$(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-thread.h \
$(BUILDTOP)/include/krb5.h $(COM_ERR_DEPS) $(BUILDTOP)/include/profile.h \
$(SRCTOP)/include/port-sockets.h $(BUILDTOP)/include/krb5/autoconf.h \
- $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/krb5/kdb.h
+ $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/krb5/kdb.h \
+ $(SRCTOP)/include/krb5/kdb_kt.h $(SRCTOP)/include/krb5/kdb.h
diff --git a/src/lib/kdb/adb_err.et b/src/lib/kdb/adb_err.et
new file mode 100644
index 0000000..3948025
--- /dev/null
+++ b/src/lib/kdb/adb_err.et
@@ -0,0 +1,16 @@
+error_table adb
+error_code OSA_ADB_NOERR, "No Error"
+error_code OSA_ADB_DUP, "Principal or policy already exists"
+error_code OSA_ADB_NOENT, "Principal or policy does not exist"
+error_code OSA_ADB_DBINIT, "Database not initialized"
+error_code OSA_ADB_BAD_POLICY, "Invalid policy name"
+error_code OSA_ADB_BAD_PRINC, "Invalid principal name"
+error_code OSA_ADB_BAD_DB, "Database inconsistency detected"
+error_code OSA_ADB_XDR_FAILURE, "XDR encoding error"
+error_code OSA_ADB_FAILURE, "Failure!"
+error_code OSA_ADB_BADLOCKMODE, "Bad lock mode"
+error_code OSA_ADB_CANTLOCK_DB, "Cannot lock database"
+error_code OSA_ADB_NOTLOCKED, "Database not locked"
+error_code OSA_ADB_NOLOCKFILE, "KADM5 administration database lock file missing"
+error_code OSA_ADB_NOEXCL_PERM, "Insufficient permission to lock file"
+end
diff --git a/src/lib/kdb/configure.in b/src/lib/kdb/configure.in
index dc002d8..4f06b32 100644
--- a/src/lib/kdb/configure.in
+++ b/src/lib/kdb/configure.in
@@ -4,6 +4,7 @@ AC_CHECK_HEADERS(unistd.h)
AC_TYPE_MODE_T
AC_TYPE_OFF_T
+AC_CHECK_HEADERS(pthread.h)
AC_CHECK_FUNCS(srand48 srand srandom umask)
dnl AIX is unusual in that it wants all symbols resolved at link time
@@ -19,4 +20,5 @@ dnl The following is for check...
KRB5_BUILD_PROGRAM
KRB5_BUILD_LIBOBJS
KRB5_BUILD_LIBRARY_WITH_DEPS
-V5_AC_OUTPUT_MAKEFILE
+AC_CONFIG_SUBDIRS(kdb_db2)
+V5_AC_OUTPUT_MAKEFILE(. kdb_db2)
diff --git a/src/lib/kdb/decrypt_key.c b/src/lib/kdb/decrypt_key.c
index 765e6f3..53d02ff 100644
--- a/src/lib/kdb/decrypt_key.c
+++ b/src/lib/kdb/decrypt_key.c
@@ -62,12 +62,11 @@
*/
krb5_error_code
-krb5_dbekd_decrypt_key_data(context, mkey, key_data, dbkey, keysalt)
- krb5_context context;
- const krb5_keyblock * mkey;
- const krb5_key_data * key_data;
- krb5_keyblock * dbkey;
- krb5_keysalt * keysalt;
+krb5_dbekd_decrypt_key_data( krb5_context context,
+ const krb5_keyblock * mkey,
+ const krb5_key_data * key_data,
+ krb5_keyblock * dbkey,
+ krb5_keysalt * keysalt)
{
krb5_error_code retval = 0;
krb5_int16 tmplen;
diff --git a/src/lib/kdb/encrypt_key.c b/src/lib/kdb/encrypt_key.c
index aa259f9..13686a4 100644
--- a/src/lib/kdb/encrypt_key.c
+++ b/src/lib/kdb/encrypt_key.c
@@ -62,13 +62,12 @@
*/
krb5_error_code
-krb5_dbekd_encrypt_key_data(context, mkey, dbkey, keysalt, keyver, key_data)
- krb5_context context;
- const krb5_keyblock * mkey;
- const krb5_keyblock * dbkey;
- const krb5_keysalt * keysalt;
- int keyver;
- krb5_key_data * key_data;
+krb5_dbekd_encrypt_key_data( krb5_context context,
+ const krb5_keyblock * mkey,
+ const krb5_keyblock * dbkey,
+ const krb5_keysalt * keysalt,
+ int keyver,
+ krb5_key_data * key_data)
{
krb5_error_code retval;
krb5_octet * ptr;
diff --git a/src/lib/kdb/err_handle.c b/src/lib/kdb/err_handle.c
new file mode 100644
index 0000000..7d54441
--- /dev/null
+++ b/src/lib/kdb/err_handle.c
@@ -0,0 +1,193 @@
+/**********************************************************************
+*
+* C %name: err_handle.c %
+* Instance: idc_sec_1
+* Description:
+* %created_by: spradeep %
+* %date_created: Thu Apr 7 14:05:00 2005 %
+*
+**********************************************************************/
+#ifndef lint
+static char *_csrc = "@(#) %filespec: err_handle.c~1 % (%full_filespec: err_handle.c~1:csrc:idc_sec#1 %)";
+#endif
+
+/* This file should be ideally be in util/et. But, for now thread
+ safety requirement stops me from putting there. if I do, then all
+ the applications have to link to pthread. */
+
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+#include "err_handle.h"
+#include <assert.h>
+
+#ifdef NOVELL
+krb5_errcode_2_string_func old_error_2_string = NULL;
+#endif
+
+typedef struct {
+ char krb5_err_str[KRB5_MAX_ERR_STR + 1];
+ long err_code;
+ krb5_err_subsystem subsystem;
+ krb5_context kcontext;
+} krb5_err_struct_t;
+
+#ifdef HAVE_PTHREAD_H
+static void tsd_key_destructor(void *data)
+{
+ free(data);
+}
+
+static pthread_key_t krb5_err_key;
+
+static void init_err_handling( void )
+{
+ assert(!pthread_key_create(&krb5_err_key, tsd_key_destructor));
+#ifdef NOVELL
+ old_error_2_string = error_message;
+ error_message = krb5_get_err_string;
+#endif
+}
+
+static pthread_once_t krb5_key_create = PTHREAD_ONCE_INIT;
+
+krb5_error_code krb5_set_err( krb5_context kcontext, krb5_err_subsystem subsystem, long err_code, char *str )
+{
+ int ret;
+ krb5_err_struct_t *err_struct;
+ pthread_once(&krb5_key_create, init_err_handling);
+
+ err_struct = (krb5_err_struct_t*) pthread_getspecific(krb5_err_key);
+ if( err_struct == NULL )
+ {
+ err_struct = calloc(sizeof(krb5_err_struct_t), 1);
+ if( err_struct == NULL )
+ return ENOMEM;
+
+ if((ret = pthread_setspecific(krb5_err_key, err_struct)))
+ {
+ free( err_struct );
+ return ret;
+ }
+ }
+
+ err_struct->subsystem = subsystem;
+ err_struct->err_code = err_code;
+ err_struct->kcontext = kcontext;
+ if( err_struct->subsystem == krb5_err_have_str )
+ {
+ strncpy( err_struct->krb5_err_str, str, sizeof(err_struct->krb5_err_str) );
+ err_struct->krb5_err_str[KRB5_MAX_ERR_STR] = '\0';
+ }
+
+ return 0;
+}
+
+const char * KRB5_CALLCONV krb5_get_err_string(long err_code)
+{
+ krb5_err_struct_t *err_struct;
+ pthread_once(&krb5_key_create, init_err_handling);
+
+ err_struct = (krb5_err_struct_t*) pthread_getspecific(krb5_err_key);
+ if( err_struct && (err_struct->subsystem == krb5_err_have_str) && (err_code == err_struct->err_code) )
+ {
+ /* checking error code is for safety.
+ In case, the caller ignores a database error and calls other calls before doing com_err.
+ Though not perfect, caller should call krb5_clr_error before this*/
+ err_struct->subsystem = krb5_err_unknown;
+ return err_struct->krb5_err_str;
+ }
+
+ if( err_struct && (err_struct->subsystem == krb5_err_db) && (err_code == err_struct->err_code) )
+ {
+ err_struct->subsystem = krb5_err_unknown;
+ return krb5_db_errcode2string(err_struct->kcontext, err_code);
+ }
+
+ /* Error strings are not generated here. the remaining two cases are handled by the default error string convertor */
+#ifdef NOVELL
+ return old_error_2_string(err_code);
+#else
+ return error_message (err_code);
+#endif
+}
+
+void krb5_clr_error()
+{
+ krb5_err_struct_t *err_struct;
+ pthread_once(&krb5_key_create, init_err_handling);
+
+ err_struct = (krb5_err_struct_t*) pthread_getspecific(krb5_err_key);
+ if( err_struct )
+ err_struct->subsystem = krb5_err_unknown;
+}
+
+#else
+krb5_err_struct_t krb5_err = {{0}, 0, 0, 0};
+krb5_boolean krb5_init_once = TRUE;
+
+static void init_err_handling( void )
+{
+ if( krb5_init_once )
+ {
+ old_error_2_string = error_message;
+ error_message = krb5_get_err_string;
+ krb5_init_once = FALSE;
+ }
+}
+
+krb5_error_code krb5_set_err( krb5_context kcontext, krb5_err_subsystem subsystem, long err_code, char *str )
+{
+ krb5_err_struct_t *err_struct = &krb5_err;
+
+ init_err_handling(); /* takes care for multiple inits */
+
+ err_struct->subsystem = subsystem;
+ err_struct->err_code = err_code;
+ err_struct->kcontext = kcontext;
+ if( err_struct->subsystem == krb5_err_have_str )
+ {
+ strncpy( err_struct->krb5_err_str, str, sizeof(err_struct->krb5_err_str) );
+ err_struct->krb5_err_str[KRB5_MAX_ERR_STR] = '\0';
+ }
+
+ return 0;
+}
+
+const char * KRB5_CALLCONV krb5_get_err_string(long err_code)
+{
+ krb5_err_struct_t *err_struct = &krb5_err;
+
+ init_err_handling(); /* takes care for multiple inits */
+
+ if( (err_struct->subsystem == krb5_err_have_str) && (err_code == err_struct->err_code) )
+ {
+ /* checking error code is for safety.
+ In case, the caller ignores a database error and calls other calls before doing com_err.
+ Though not perfect, caller should call krb5_clr_error before this*/
+ err_struct->subsystem = krb5_err_unknown;
+ return err_struct->krb5_err_str;
+ }
+
+ if( (err_struct->subsystem == krb5_err_db) && (err_code == err_struct->err_code) )
+ {
+ err_struct->subsystem = krb5_err_unknown;
+ return krb5_db_errcode2string(err_struct->kcontext, err_code);
+ }
+
+ /* it is not generated here. the remaining two cases are handled by the default error string convertor */
+ return old_error_2_string(err_code);
+
+}
+
+void krb5_clr_error()
+{
+ krb5_err_struct_t *err_struct = &krb5_err;
+
+ init_err_handling(); /* takes care for multiple inits */
+
+ err_struct->subsystem = krb5_err_unknown;
+}
+
+
+#endif
diff --git a/src/lib/kdb/err_handle.h b/src/lib/kdb/err_handle.h
new file mode 100644
index 0000000..e123afc
--- /dev/null
+++ b/src/lib/kdb/err_handle.h
@@ -0,0 +1,32 @@
+/**********************************************************************
+*
+* C Header: err_handle.h
+* Instance: idc_sec_1
+* Description:
+* %created_by: spradeep %
+* %date_created: Thu Apr 7 14:05:33 2005 %
+*
+**********************************************************************/
+#ifndef _idc_sec_1_err_handle_h_H
+#define _idc_sec_1_err_handle_h_H
+#include <k5-int.h>
+
+/* Everything else goes here */
+
+#define KRB5_MAX_ERR_STR 1024
+typedef enum krb5_err_subsystem { krb5_err_unknown = 0, /* no error or unknown system. Has to be probed */
+ krb5_err_system, /* error in system call */
+ krb5_err_krblib, /* error in kerberos library call, should lookup in the error table */
+ krb5_err_have_str, /* error message is available in the string */
+ krb5_err_db /* error is a database error, should be handled by calling DB */
+} krb5_err_subsystem;
+
+typedef krb5_error_code (*krb5_set_err_func_t)( krb5_context, krb5_err_subsystem, long, char*);
+
+krb5_error_code krb5_set_err( krb5_context kcontext, krb5_err_subsystem subsystem, long err_code, char *str );
+
+const char * KRB5_CALLCONV krb5_get_err_string(long err_code);
+
+void krb5_clr_error(void);
+
+#endif
diff --git a/src/lib/kdb/fetch_mkey.c b/src/lib/kdb/fetch_mkey.c
deleted file mode 100644
index 5d63b8c..0000000
--- a/src/lib/kdb/fetch_mkey.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * lib/kdb/fetch_mkey.c
- *
- * Copyright 1990 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
- *
- *
- * krb5_db_fetch_mkey():
- * Fetch a database master key from somewhere.
- */
-
-/*
- * Copyright (C) 1998 by the FundsXpress, INC.
- *
- * All rights reserved.
- *
- * Export of this software from the United States of America may require
- * a specific license from the United States Government. It is the
- * responsibility of any person or organization contemplating export to
- * obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of FundsXpress. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. FundsXpress makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#include "k5-int.h"
-
-/* these are available to other funcs, and the pointers may be reassigned */
-
-char *krb5_mkey_pwd_prompt1 = KRB5_KDC_MKEY_1;
-char *krb5_mkey_pwd_prompt2 = KRB5_KDC_MKEY_2;
-
-/*
- * Get the KDC database master key from somewhere, filling it into *key.
- *
- * key->enctype should be set to the desired key type.
- *
- * if fromkeyboard is TRUE, then the master key is read as a password
- * from the user's terminal. In this case,
- * eblock should point to a block with an appropriate string_to_key function.
- * if twice is TRUE, the password is read twice for verification.
- *
- * mname is the name of the key sought; this can be used by the string_to_key
- * function or by some other method to isolate the desired key.
- *
- */
-
-#ifndef min
-#define min(a,b) (((a) < (b)) ? (a) : (b))
-#endif
-
-krb5_error_code
-krb5_db_fetch_mkey(context, mname, etype, fromkeyboard, twice, keyfile,
- salt, key)
- krb5_context context;
- krb5_principal mname;
- krb5_enctype etype;
- krb5_boolean fromkeyboard;
- krb5_boolean twice;
- char *keyfile;
- krb5_data * salt;
- krb5_keyblock * key;
-{
- krb5_error_code retval;
- char password[BUFSIZ];
- krb5_data pwd;
- unsigned int size = sizeof(password);
-
- if (fromkeyboard) {
- krb5_data scratch;
-
- if ((retval = krb5_read_password(context, krb5_mkey_pwd_prompt1,
- twice ? krb5_mkey_pwd_prompt2 : 0,
- password, &size)))
- return(retval);
-
- pwd.data = password;
- pwd.length = size;
- if (!salt) {
- retval = krb5_principal2salt(context, mname, &scratch);
- if (retval)
- return retval;
- }
- retval = krb5_c_string_to_key(context, etype, &pwd, salt?salt:&scratch,
- key);
-
- if (!salt)
- krb5_xfree(scratch.data);
- memset(password, 0, sizeof(password)); /* erase it */
- return retval;
-
- } else {
- /* from somewhere else */
- krb5_ui_2 enctype;
- char defkeyfile[MAXPATHLEN+1];
- krb5_data *realm = krb5_princ_realm(context, mname);
- FILE *kf;
-
- retval = 0;
- key->magic = KV5M_KEYBLOCK;
- (void) strcpy(defkeyfile, DEFAULT_KEYFILE_STUB);
- (void) strncat(defkeyfile, realm->data,
- min(sizeof(defkeyfile)-sizeof(DEFAULT_KEYFILE_STUB)-1,
- realm->length));
- defkeyfile[sizeof(defkeyfile) - 1] = '\0';
-
-#ifdef ANSI_STDIO
- if (!(kf = fopen((keyfile) ? keyfile : defkeyfile, "rb")))
-#else
- if (!(kf = fopen((keyfile) ? keyfile : defkeyfile, "r")))
-#endif
- return KRB5_KDB_CANTREAD_STORED;
- if (fread((krb5_pointer) &enctype, 2, 1, kf) != 1) {
- retval = KRB5_KDB_CANTREAD_STORED;
- goto errout;
- }
- if (key->enctype == ENCTYPE_UNKNOWN)
- key->enctype = enctype;
- else if (enctype != key->enctype) {
- retval = KRB5_KDB_BADSTORED_MKEY;
- goto errout;
- }
- if (fread((krb5_pointer) &key->length,
- sizeof(key->length), 1, kf) != 1) {
- retval = KRB5_KDB_CANTREAD_STORED;
- goto errout;
- }
- if (!key->length || ((int) key->length) < 0) {
- retval = KRB5_KDB_BADSTORED_MKEY;
- goto errout;
- }
-
- if (!(key->contents = (krb5_octet *)malloc(key->length))) {
- retval = ENOMEM;
- goto errout;
- }
- if (fread((krb5_pointer) key->contents,
- sizeof(key->contents[0]), key->length, kf)
- != key->length) {
- retval = KRB5_KDB_CANTREAD_STORED;
- memset(key->contents, 0, key->length);
- free(key->contents);
- key->contents = 0;
- } else
- retval = 0;
-
- errout:
- (void) fclose(kf);
- return retval;
- }
-}
diff --git a/src/lib/kdb/kdb5.c b/src/lib/kdb/kdb5.c
new file mode 100644
index 0000000..c4afa1b
--- /dev/null
+++ b/src/lib/kdb/kdb5.c
@@ -0,0 +1,2051 @@
+/*
+ * Include files
+ */
+
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <k5-int.h>
+#include <osconf.h>
+#include "kdb5.h"
+#include <assert.h>
+
+/* currently DB2 policy related errors are exported from DAL. But other databases should set_err function to return string */
+#include "adb_err.h"
+
+
+/*
+ * Type definitions
+ */
+#define KRB5_TL_DB_ARGS 0x7fff
+
+/*
+ * internal static variable
+ */
+
+#ifdef HAVE_PTHREAD_H
+/* static pthread_once_t db_inited = PTHREAD_ONCE_INIT; */
+static pthread_mutex_t db_lock = PTHREAD_MUTEX_INITIALIZER;
+#else
+/* static int db_inited = 0; */
+#endif
+
+
+#ifdef _KDB5_STATIC_LINK
+#undef _KDB5_DYNAMIC_LINK
+#else
+#undef _KDB5_DYNAMIC_LINK
+/* to avoid redefinition problem */
+#define _KDB5_DYNAMIC_LINK
+#endif
+
+
+static db_library lib_list;
+
+/*
+ * Helper Functions
+ */
+#ifdef HAVE_PTHREAD_H
+
+/*
+ * KNOWN ISSUES with locking: This code does not handle a scenario where a library is thread-safe for different DB contexts,
+ * but not with the same context. It locks the complete DB library. If this is not the scenario, then lock has to be moved from
+ * db_library to kdb5_dal_handle. For now doing a pessimistic locking.
+ *
+ * If any thread does a DB lock, all the other threads are barred from accessing DB using this context (infact library
+ * because of the previous defect).
+ * This is with the assumption that, DB's lock code will take care of excluding other processes/machines from
+ * using the DB. But there could be a scenario where access by some other thread using the same context might corrupt the database.
+ */
+
+static int kdb_lock_list()
+{
+ return pthread_mutex_lock( &db_lock );
+}
+
+static int kdb_unlock_list()
+{
+ return pthread_mutex_unlock( &db_lock );
+}
+
+static int kdb_init_lib_lock( db_library lib )
+{
+ krb5_error_code retval;
+ if( (retval= pthread_mutex_init( &lib->lib_lock, NULL )))
+ {
+ return retval;
+ }
+
+ lib->lock_holder = pthread_self();
+ lib->excl = 0;
+ lib->recursive_cnt = 0;
+
+ return pthread_cond_init( &lib->unlocked, NULL );
+}
+
+static int kdb_destroy_lib_lock ( db_library lib )
+{
+ krb5_error_code retval;
+ if( (retval = pthread_mutex_destroy( &lib->lib_lock )) )
+ {
+ return retval;
+ }
+
+ return pthread_cond_destroy( &lib->unlocked );
+}
+
+static int kdb_lock_lib_lock( db_library lib, krb5_boolean exclusive )
+{
+ /* since, handle locked by one thread should not allow another thread to continue */
+ krb5_error_code retval = 0;
+ pthread_t myid = pthread_self();
+
+ if( (retval = pthread_mutex_lock( &lib->lib_lock )) )
+ return retval;
+
+ while( (exclusive && (lib->excl || lib->recursive_cnt)) ||
+ (!pthread_equal(lib->lock_holder, myid) && !lib->vftabl.is_thread_safe && lib->recursive_cnt) )
+ {
+ /* exclusive lock held or some one using lock when exclusive is requested or library not-re-entrent */
+ if( (retval = pthread_cond_wait(&lib->unlocked, &lib->lib_lock)) )
+ return retval;
+ }
+
+ /* exclusive lock and recursive_cnt allow a thread to lock even it already holds a lock */
+ if( exclusive )
+ lib->excl++;
+
+ lib->recursive_cnt++;
+
+ lib->lock_holder = myid;
+
+ return pthread_mutex_unlock( &lib->lib_lock );
+}
+
+static int kdb_unlock_lib_lock( db_library lib, krb5_boolean exclusive )
+{
+ krb5_error_code retval = 0;
+
+ if( (retval = pthread_mutex_lock( &lib->lib_lock )) )
+ return retval;
+
+ lib->recursive_cnt--;
+ if( exclusive )
+ lib->excl--;
+
+ if( (retval = pthread_cond_broadcast( &lib->unlocked )) )
+ return retval;
+
+ return pthread_mutex_unlock( &lib->lib_lock );
+}
+
+#else /* no PTHREAD */
+
+/* program is not using pthread. So, threads wont be there. No need to lock */
+#define kdb_lock_list() 0
+#define kdb_unlock_list() 0
+#define kdb_init_lib_lock(a) 0
+#define kdb_destroy_lib_lock(a) 0
+#define kdb_lock_lib_lock(a, b) 0
+#define kdb_unlock_lib_lock(a, b) 0
+
+#endif /* end of HAVE_PTHREAD_H */
+
+
+static char * kdb_get_conf_section( krb5_context kcontext )
+{
+ krb5_error_code status = 0;
+ char *result = NULL;
+ char *value = NULL;
+
+ /* profile has to be initialized. If profile is not initialized, expect nothing less than a crash */
+ status = profile_get_string( kcontext->profile, KDB_REALM_SECTION, /* realms */
+ kcontext->default_realm, KDB_MODULE_POINTER, /* under the realm name, database_module */
+ kcontext->default_realm, /* default value is the realm name itself */
+ &value );
+
+ if( status )
+ {
+ /* some problem */
+ result = strdup( kcontext->default_realm );
+ /* let NULL be handled by the caller */
+ }
+ else
+ {
+ result = strdup( value );
+ /* free profile string */
+ profile_release_string( value );
+ }
+
+ return result;
+}
+
+static char * kdb_get_library_name( krb5_context kcontext )
+{
+ krb5_error_code status = 0;
+ char *result = NULL;
+ char *value = NULL;
+ char *lib = NULL;
+
+ status = profile_get_string( kcontext->profile, KDB_REALM_SECTION, /* realms */
+ kcontext->default_realm, KDB_MODULE_POINTER, /* under the realm name, database_module */
+ kcontext->default_realm, /* default value is the realm name itself */
+ &value );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ /* we got the module section. Get the library name from the module */
+ status = profile_get_string( kcontext->profile, KDB_MODULE_SECTION,
+ value, KDB_LIB_POINTER,
+ "kdb_db2", /* default to db2 */
+ &lib );
+
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ result = strdup( lib );
+ clean_n_exit:
+ if( value )
+ {
+ /* free profile string */
+ profile_release_string( value );
+ }
+
+ if( lib )
+ {
+ /* free profile string */
+ profile_release_string( lib );
+ }
+
+ if( status )
+ {
+ /* any error default to db2 */
+ result = strdup( "kdb_db2" );
+ }
+ return result;
+}
+
+static void kdb_setup_opt_functions ( db_library lib )
+{
+ if ( lib->vftabl.set_master_key == NULL )
+ {
+ lib->vftabl.set_master_key = kdb_def_set_mkey;
+ }
+
+ if ( lib->vftabl.get_master_key == NULL )
+ {
+ lib->vftabl.get_master_key = kdb_def_get_mkey;
+ }
+
+ if( lib->vftabl.fetch_master_key == NULL )
+ {
+ lib->vftabl.fetch_master_key = krb5_db_def_fetch_mkey;
+ }
+
+ if( lib->vftabl.verify_master_key == NULL )
+ {
+ lib->vftabl.verify_master_key = krb5_def_verify_master_key;
+ }
+
+ if( lib->vftabl.dbe_search_enctype == NULL )
+ {
+ lib->vftabl.dbe_search_enctype = krb5_dbe_def_search_enctype;
+ }
+
+ if( lib->vftabl.db_change_pwd == NULL )
+ {
+ lib->vftabl.db_change_pwd = krb5_dbe_def_cpw;
+ }
+
+ if( lib->vftabl.store_master_key == NULL )
+ {
+ lib->vftabl.store_master_key = krb5_def_store_mkey;
+ }
+}
+
+static int kdb_db2_pol_err_loaded = 0;
+#ifdef _KDB5_STATIC_LINK
+#define DEF_SYMBOL(a) extern kdb_vftabl krb5_db_vftabl_ ## a
+#define GET_SYMBOL(a) (krb5_db_vftabl_ ## a)
+static krb5_error_code kdb_load_library( krb5_context kcontext, char *lib_name, db_library *lib )
+{
+ krb5_error_code status;
+ void *vftabl_addr = NULL;
+ char buf[KRB5_MAX_ERR_STR];
+
+ if( !strcmp("kdb_db2", lib_name) && (kdb_db2_pol_err_loaded == 0) )
+ {
+ initialize_adb_error_table();
+ kdb_db2_pol_err_loaded = 1;
+ }
+
+ *lib = calloc( (size_t)1, sizeof(**lib));
+ if( *lib == NULL )
+ {
+ status = ENOMEM;
+ goto clean_n_exit;
+ }
+
+ status = kdb_init_lib_lock( *lib );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ strcpy( (*lib)->name, lib_name );
+
+#if !defined(KDB5_USE_LIB_KDB_DB2) && !defined(KDB5_USE_LIB_TEST)
+#error No database module defined
+#endif
+
+#ifdef KDB5_USE_LIB_KDB_DB2
+ if( strcmp( lib_name, "kdb_db2" ) == 0 )
+ {
+ DEF_SYMBOL(kdb_db2);
+ vftabl_addr = (void*)& GET_SYMBOL(kdb_db2);
+ }
+ else
+#endif
+#ifdef KDB5_USE_LIB_TEST
+ if( strcmp( lib_name, "test" ) == 0 )
+ {
+ DEF_SYMBOL(test);
+ vftabl_addr = (void*) &GET_SYMBOL(test);
+ } else
+#endif
+ {
+ sprintf( buf, "Program not built to support %s database type\n", lib_name );
+ status = -1;
+ krb5_db_set_err(kcontext, krb5_err_have_str, status, buf);
+ goto clean_n_exit;
+ }
+
+ memcpy( &(*lib)->vftabl, vftabl_addr, sizeof(kdb_vftabl));
+
+ kdb_setup_opt_functions( *lib );
+
+ if( (status=(*lib)->vftabl.init_library(krb5_set_err)) )
+ {
+ /* ERROR. library not initialized cleanly */
+ sprintf( buf, "%s library initialization failed, error code %ld\n", lib_name, status );
+ status = -1;
+ krb5_db_set_err(kcontext, krb5_err_have_str, status, buf);
+ goto clean_n_exit;
+ }
+
+
+ clean_n_exit:
+ if( status )
+ {
+ free(*lib), *lib = NULL;
+ }
+ return status;
+}
+
+#else
+
+static char *db_dl_location[] = DEFAULT_KDB_LIB_PATH;
+
+static krb5_error_code kdb_load_library( krb5_context kcontext, char *lib_name, db_library *lib )
+{
+ krb5_error_code status = 0;
+ char dl_name[1024];
+ int ndx;
+ void *vftabl_addr;
+ char *err_str = NULL;
+
+ if( !strcmp("kdb_db2", lib_name) && (kdb_db2_pol_err_loaded == 0) )
+ {
+ initialize_adb_error_table();
+ kdb_db2_pol_err_loaded = 1;
+ }
+
+ *lib = calloc( (size_t)1, sizeof(**lib));
+ if( *lib == NULL )
+ {
+ status = ENOMEM;
+ goto clean_n_exit;
+ }
+
+ status = kdb_init_lib_lock( *lib );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ strcpy( (*lib)->name, lib_name );
+
+ for( ndx = 0; db_dl_location[ndx]; ndx++ )
+ {
+ sprintf(dl_name, "%s/lib%s.so", db_dl_location[ndx], lib_name);
+ (*lib)->dl_handle = dlopen( dl_name, RTLD_NOW );
+ if( (*lib)->dl_handle )
+ {
+ /* found the module */
+ sprintf( dl_name, "krb5_db_vftabl_%s", lib_name );
+
+ dlerror();
+ vftabl_addr = dlsym( (*lib)->dl_handle, dl_name );
+ if( vftabl_addr )
+ {
+ memcpy( &(*lib)->vftabl, vftabl_addr, sizeof(kdb_vftabl));
+
+ kdb_setup_opt_functions( *lib );
+
+ if( (status = (*lib)->vftabl.init_library(krb5_set_err)) )
+ {
+ /* ERROR. library not initialized cleanly */
+ goto clean_n_exit;
+
+ }
+ }
+ else
+ {
+ status = -1;
+ krb5_set_err(kcontext, krb5_err_have_str, status, dlerror());
+ goto clean_n_exit;
+ }
+ break;
+ }
+ else
+ {
+ /* set the error. Later if we find everything fine.. we will reset this */
+ err_str = dlerror();
+/* fprintf(stderr, "Error loading library %s\n", t); */
+ }
+ }
+
+ if( ! (*lib)->dl_handle )
+ {
+ /* library not found in the given list. Error str is already set */
+ status = -1;
+ krb5_set_err(kcontext, krb5_err_have_str, status, err_str);
+ goto clean_n_exit;
+ }
+
+ clean_n_exit:
+ if( status )
+ {
+ if( *lib )
+ {
+ kdb_destroy_lib_lock( *lib );
+ if( (*lib)->dl_handle )
+ {
+ dlclose( (*lib)->dl_handle );
+ }
+ free(*lib);
+ *lib = NULL;
+ }
+ }
+ return status;
+}
+
+#endif /* end of _KDB5_STATIC_LINK */
+
+static krb5_error_code kdb_find_library( krb5_context kcontext, char *lib_name, db_library *lib)
+{
+ /* lock here so that no two threads try to do the same at the same time */
+ krb5_error_code status = 0;
+ int locked = 0;
+ db_library curr_elt, prev_elt = NULL;
+
+ if( (status = kdb_lock_list()) != 0 )
+ {
+ goto clean_n_exit;
+ }
+ locked = 1;
+
+ curr_elt = lib_list;
+ while ( curr_elt != NULL )
+ {
+ if( strcmp( lib_name, curr_elt->name ) == 0 )
+ {
+ *lib = curr_elt;
+ goto clean_n_exit;
+ }
+ prev_elt = curr_elt;
+ curr_elt = curr_elt->next;
+ }
+
+ /* module not found. create and add to list */
+ status = kdb_load_library( kcontext, lib_name, lib);
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ if( prev_elt )
+ {
+ /* prev_elt points to the last element in the list */
+ prev_elt->next = *lib;
+ (*lib)->prev = prev_elt;
+ }
+ else
+ {
+ lib_list = *lib;
+ }
+
+ clean_n_exit:
+ if( *lib )
+ {
+ (*lib)->reference_cnt++;
+ }
+
+ if( locked )
+ {
+ kdb_unlock_list();
+ }
+
+ return status;
+}
+
+
+static krb5_error_code kdb_free_library( db_library lib)
+{
+ krb5_error_code status = 0;
+ int locked = 0;
+
+ if( (status = kdb_lock_list()) != 0 )
+ {
+ goto clean_n_exit;
+ }
+ locked = 1;
+
+ lib->reference_cnt--;
+
+ if( lib->reference_cnt == 0 )
+ {
+ status = lib->vftabl.fini_library();
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ /* close the library */
+ if( lib->dl_handle )
+ {
+ dlclose( lib->dl_handle );
+ }
+
+ kdb_destroy_lib_lock( lib );
+
+ if( lib->prev == NULL )
+ {
+ /* first element in the list */
+ lib_list = lib->next;
+ }
+ else
+ {
+ lib->prev->next = lib->next;
+ }
+
+ if( lib->next )
+ {
+ lib->next->prev = lib->prev;
+ }
+ free(lib);
+ }
+
+ clean_n_exit:
+ if( locked )
+ {
+ kdb_unlock_list();
+ }
+
+ return status;
+}
+
+static krb5_error_code kdb_setup_lib_handle( krb5_context kcontext )
+{
+ char *library = NULL;
+ krb5_error_code status = 0;
+ db_library lib = NULL;
+ kdb5_dal_handle *dal_handle = NULL;
+
+ dal_handle = calloc( (size_t)1, sizeof(kdb5_dal_handle) );
+ if( dal_handle == NULL )
+ {
+ status = ENOMEM;
+ goto clean_n_exit;
+ }
+
+ library = kdb_get_library_name( kcontext );
+ if( library == NULL )
+ {
+ status = -1;
+ goto clean_n_exit;
+ }
+
+ status = kdb_find_library( kcontext, library, &lib );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ dal_handle->lib_handle = lib;
+ kcontext->db_context = (void *) dal_handle;
+
+ clean_n_exit:
+ free(library);
+
+ if( status )
+ {
+ free( dal_handle );
+ if( lib )
+ {
+ kdb_free_library( lib );
+ }
+ }
+
+ return status;
+}
+
+
+static krb5_error_code kdb_free_lib_handle( krb5_context kcontext )
+{
+ krb5_error_code status = 0;
+
+ status = kdb_free_library( ((kdb5_dal_handle *)kcontext->db_context)->lib_handle );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ free( kcontext->db_context );
+ kcontext->db_context = NULL;
+
+ clean_n_exit:
+ return status;
+}
+
+/*
+ * External functions... DAL API
+ */
+void krb5_db_clr_error()
+{
+ krb5_clr_error();
+}
+
+krb5_error_code krb5_db_open( krb5_context kcontext, char **db_args, int mode )
+{
+ krb5_error_code status = 0;
+ char *section = NULL;
+ kdb5_dal_handle *dal_handle;
+ char buf[KRB5_MAX_ERR_STR];
+
+ section = kdb_get_conf_section( kcontext );
+ if( section == NULL )
+ {
+ sprintf( buf, "unable to determine configuration section for realm %s\n", kcontext->default_realm );
+ status = -1;
+ krb5_set_err(kcontext, krb5_err_have_str, status, buf);
+ goto clean_n_exit;
+ }
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.init_module(kcontext, section, db_args, mode );
+
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ if( section )
+ free(section);
+ return status;
+}
+
+const char * krb5_db_errcode2string ( krb5_context kcontext, long err_code )
+{
+ const char *err_str = NULL;
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ err_str = dal_handle->lib_handle->vftabl.errcode_2_string(kcontext, err_code );
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ return err_str;
+}
+
+
+krb5_error_code krb5_db_inited ( krb5_context kcontext )
+{
+ return !(kcontext && kcontext->db_context &&
+ ((kdb5_dal_handle*)kcontext->db_context)->db_context);
+}
+
+krb5_error_code krb5_db_create ( krb5_context kcontext, char **db_args )
+{
+ krb5_error_code status = 0;
+ char *section = NULL;
+ kdb5_dal_handle *dal_handle;
+ char buf[KRB5_MAX_ERR_STR];
+
+ section = kdb_get_conf_section( kcontext );
+ if( section == NULL )
+ {
+ sprintf( buf, "unable to determine configuration section for realm %s\n", kcontext->default_realm );
+ status = -1;
+ krb5_set_err(kcontext, krb5_err_have_str, status, buf);
+ goto clean_n_exit;
+ }
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.db_create(kcontext, section, db_args );
+
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ if( section )
+ free(section);
+ return status;
+}
+
+krb5_error_code krb5_db_fini ( krb5_context kcontext )
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ /* module not loaded. So nothing to be done */
+ goto clean_n_exit;
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.fini_module( kcontext );
+
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = kdb_free_lib_handle( kcontext );
+
+ clean_n_exit:
+ return status;
+}
+
+
+krb5_error_code krb5_db_destroy ( krb5_context kcontext, char **db_args )
+{
+ krb5_error_code status = 0;
+ char * section = NULL;
+ kdb5_dal_handle *dal_handle;
+ char buf[KRB5_MAX_ERR_STR];
+
+ section = kdb_get_conf_section( kcontext );
+ if( section == NULL )
+ {
+ sprintf( buf, "unable to determine configuration section for realm %s\n", kcontext->default_realm );
+ status = -1;
+ krb5_set_err(kcontext, krb5_err_have_str, status, buf);
+ goto clean_n_exit;
+ }
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.db_destroy(kcontext, section, db_args );
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ if( section )
+ free(section);
+ return status;
+}
+
+krb5_error_code krb5_db_get_age ( krb5_context kcontext, char *db_name, time_t *t )
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.db_get_age(kcontext, db_name, t );
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ return status;
+}
+
+krb5_error_code krb5_db_set_option ( krb5_context kcontext, int option, void *value )
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.db_set_option(kcontext, option, value );
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ return status;
+}
+
+krb5_error_code krb5_db_lock ( krb5_context kcontext, int lock_mode )
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ /* acquire an exclusive lock, ensures no other thread uses this context */
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, TRUE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.db_lock(kcontext, lock_mode );
+
+ /* exclusive lock is still held, so no other thread could use this context */
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ return status;
+}
+
+krb5_error_code krb5_db_unlock ( krb5_context kcontext )
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ /* normal lock acquired and exclusive lock released */
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.db_unlock( kcontext );
+
+ kdb_unlock_lib_lock( dal_handle->lib_handle, TRUE );
+
+ clean_n_exit:
+ return status;
+}
+
+krb5_error_code krb5_db_get_principal ( krb5_context kcontext,
+ krb5_const_principal search_for,
+ krb5_db_entry *entries,
+ int *nentries,
+ krb5_boolean *more )
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.db_get_principal(kcontext, search_for,
+ entries, nentries, more);
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ return status;
+}
+
+krb5_error_code krb5_db_free_principal ( krb5_context kcontext,
+ krb5_db_entry *entry,
+ int count )
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.db_free_principal( kcontext, entry, count );
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ return status;
+}
+
+
+krb5_error_code krb5_db_put_principal ( krb5_context kcontext,
+ krb5_db_entry *entries,
+ int *nentries )
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+ char **db_args = NULL;
+ krb5_tl_data *prev, *curr, *next;
+ int db_args_size = 0;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ /* Giving db_args as part of tl data causes, db2 to store the tl_data as such.
+ To prevent this, tl_data is collated and passed as a sepearte argument. Currently supports only one principal.
+ but passing it as a seperate argument makes it difficult for kadmin remote to pass arguments to server */
+ prev=NULL, curr=entries->tl_data;
+ while(curr)
+ {
+ if( curr->tl_data_type == KRB5_TL_DB_ARGS )
+ {
+ char **t;
+ /* since this is expected to be NULL terminated string and this could come from any client, do a check
+ before passing it to db. */
+ if( ((char*) curr->tl_data_contents)[curr->tl_data_length-1] != '\0' )
+ {
+ /* not null terminated. Dangerous input */
+ status = EINVAL;
+ goto clean_n_exit;
+ }
+
+ db_args_size++;
+ t = realloc( db_args, sizeof(char*) * (db_args_size+1)); /* 1 for NULL */
+ if( t == NULL )
+ {
+ status = ENOMEM;
+ goto clean_n_exit;
+ }
+
+ db_args = t;
+ db_args[db_args_size-1] = (char*)curr->tl_data_contents;
+ db_args[db_args_size] = NULL;
+
+ next = curr->tl_data_next;
+ if( prev == NULL )
+ {
+ /* current node is the first in the linked list. remove it */
+ entries->tl_data = curr->tl_data_next;
+ }
+ else
+ {
+ prev->tl_data_next = curr->tl_data_next;
+ }
+ entries->n_tl_data--;
+ krb5_db_free( kcontext, curr );
+
+ /* previous does not change */
+ curr = next;
+ }
+ else
+ {
+ prev = curr;
+ curr = curr->tl_data_next;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.db_put_principal( kcontext, entries,
+ nentries, db_args );
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ while( db_args_size )
+ {
+ if( db_args[db_args_size-1] )
+ krb5_db_free(kcontext, db_args[db_args_size-1]);
+
+ db_args_size--;
+ }
+
+ if( db_args )
+ free(db_args);
+
+ return status;
+}
+
+krb5_error_code krb5_db_delete_principal ( krb5_context kcontext,
+ krb5_principal search_for,
+ int *nentries )
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.db_delete_principal( kcontext, search_for, nentries );
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ return status;
+}
+
+krb5_error_code krb5_db_iterate ( krb5_context kcontext,
+ char *match_entry,
+ int (*func) (krb5_pointer, krb5_db_entry *),
+ krb5_pointer func_arg )
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.db_iterate( kcontext,
+ match_entry,
+ func,
+ func_arg );
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ return status;
+}
+
+krb5_error_code krb5_supported_realms ( krb5_context kcontext,
+ char **realms )
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.db_supported_realms( kcontext, realms );
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ return status;
+}
+
+krb5_error_code krb5_free_supported_realms ( krb5_context kcontext,
+ char **realms )
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.db_free_supported_realms( kcontext, realms );
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ return status;
+}
+
+krb5_error_code krb5_db_set_master_key_ext ( krb5_context kcontext,
+ char *pwd,
+ krb5_keyblock *key )
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.set_master_key( kcontext,
+ pwd,
+ key );
+
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+
+ clean_n_exit:
+ return status;
+}
+
+krb5_error_code krb5_db_set_mkey ( krb5_context context,
+ krb5_keyblock *key)
+{
+ return krb5_db_set_master_key_ext ( context, NULL, key );
+}
+
+
+krb5_error_code krb5_db_get_mkey ( krb5_context kcontext,
+ krb5_keyblock **key )
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ /* lets use temp key and copy it later to avoid memory problems when freed by the caller */
+ status = dal_handle->lib_handle->vftabl.get_master_key( kcontext,
+ key );
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ return status;
+}
+
+krb5_error_code krb5_db_store_master_key ( krb5_context kcontext,
+ char *db_arg,
+ krb5_principal mname,
+ krb5_keyblock *key,
+ char *master_pwd)
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.store_master_key( kcontext,
+ db_arg,
+ mname,
+ key,
+ master_pwd);
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ return status;
+}
+
+
+char *krb5_mkey_pwd_prompt1 = KRB5_KDC_MKEY_1;
+char *krb5_mkey_pwd_prompt2 = KRB5_KDC_MKEY_2;
+
+
+krb5_error_code krb5_db_fetch_mkey ( krb5_context context,
+ krb5_principal mname,
+ krb5_enctype etype,
+ krb5_boolean fromkeyboard,
+ krb5_boolean twice,
+ char *db_args,
+ krb5_data *salt,
+ krb5_keyblock *key)
+{
+ krb5_error_code retval;
+ char password[BUFSIZ];
+ krb5_data pwd;
+ unsigned int size = sizeof(password);
+ int kvno;
+ krb5_keyblock tmp_key;
+
+ memset( &tmp_key, 0, sizeof(tmp_key) );
+
+ if (fromkeyboard) {
+ krb5_data scratch;
+
+ if ((retval = krb5_read_password(context, krb5_mkey_pwd_prompt1,
+ twice ? krb5_mkey_pwd_prompt2 : 0,
+ password, &size)))
+ {
+ goto clean_n_exit;
+ }
+
+ pwd.data = password;
+ pwd.length = size;
+ if (!salt) {
+ retval = krb5_principal2salt(context, mname, &scratch);
+ if (retval)
+ goto clean_n_exit;
+ }
+ retval = krb5_c_string_to_key(context, etype, &pwd, salt?salt:&scratch,
+ key);
+
+ if (!salt)
+ krb5_xfree(scratch.data);
+ memset(password, 0, sizeof(password)); /* erase it */
+
+ } else {
+ kdb5_dal_handle *dal_handle;
+
+ if( context->db_context == NULL )
+ {
+ retval = kdb_setup_lib_handle( context );
+ if( retval )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) context->db_context;
+ retval = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( retval )
+ {
+ goto clean_n_exit;
+ }
+
+ tmp_key.enctype = key->enctype;
+ retval = dal_handle->lib_handle->vftabl.fetch_master_key( context,
+ mname,
+ &tmp_key,
+ &kvno,
+ db_args);
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ if( retval )
+ {
+ goto clean_n_exit;
+ }
+
+ key->contents = malloc( tmp_key.length );
+ if( key->contents == NULL )
+ {
+ retval = ENOMEM;
+ goto clean_n_exit;
+ }
+
+ key->magic = tmp_key.magic;
+ key->enctype = tmp_key.enctype;
+ key->length = tmp_key.length;
+ memcpy(key->contents, tmp_key.contents, tmp_key.length);
+ }
+
+ clean_n_exit:
+ if( tmp_key.contents )
+ {
+ memset( tmp_key.contents, 0, tmp_key.length );
+ krb5_db_free( context, tmp_key.contents );
+ }
+ return retval;
+}
+
+
+krb5_error_code krb5_db_verify_master_key ( krb5_context kcontext,
+ krb5_principal mprinc,
+ krb5_keyblock *mkey )
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.verify_master_key( kcontext,
+ mprinc,
+ mkey );
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ return status;
+}
+
+
+void *krb5_db_alloc( krb5_context kcontext,
+ void *ptr,
+ size_t size )
+{
+ krb5_error_code status;
+ kdb5_dal_handle *dal_handle;
+ void *new_ptr = NULL;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+
+ new_ptr = dal_handle->lib_handle->vftabl.db_alloc( kcontext,
+ ptr,
+ size );
+
+ clean_n_exit:
+ return new_ptr;
+}
+
+void krb5_db_free( krb5_context kcontext,
+ void *ptr)
+{
+ krb5_error_code status;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+
+ dal_handle->lib_handle->vftabl.db_free( kcontext,
+ ptr );
+
+ clean_n_exit:
+ return;
+}
+
+/* has to be modified */
+
+krb5_error_code
+krb5_dbe_find_enctype( krb5_context kcontext,
+ krb5_db_entry *dbentp,
+ krb5_int32 ktype,
+ krb5_int32 stype,
+ krb5_int32 kvno,
+ krb5_key_data **kdatap)
+{
+ krb5_int32 start = 0;
+ return krb5_dbe_search_enctype( kcontext, dbentp, &start, ktype, stype, kvno, kdatap );
+}
+
+
+krb5_error_code krb5_dbe_search_enctype ( krb5_context kcontext,
+ krb5_db_entry *dbentp,
+ krb5_int32 *start,
+ krb5_int32 ktype,
+ krb5_int32 stype,
+ krb5_int32 kvno,
+ krb5_key_data **kdatap)
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.dbe_search_enctype( kcontext,
+ dbentp,
+ start,
+ ktype,
+ stype,
+ kvno,
+ kdatap );
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ return status;
+}
+
+
+#define REALM_SEP_STRING "@"
+
+krb5_error_code
+krb5_db_setup_mkey_name ( krb5_context context,
+ const char *keyname,
+ const char *realm,
+ char **fullname,
+ krb5_principal *principal)
+{
+ krb5_error_code retval;
+ size_t keylen;
+ size_t rlen = strlen(realm);
+ char *fname;
+
+ if (!keyname)
+ keyname = KRB5_KDB_M_NAME; /* XXX external? */
+
+ keylen = strlen(keyname);
+
+ fname = malloc(keylen+rlen+strlen(REALM_SEP_STRING)+1);
+ if (!fname)
+ return ENOMEM;
+
+ strcpy(fname, keyname);
+ strcat(fname, REALM_SEP_STRING);
+ strcat(fname, realm);
+
+ if ((retval = krb5_parse_name(context, fname, principal)))
+ return retval;
+ if (fullname)
+ *fullname = fname;
+ else
+ free(fname);
+ return 0;
+}
+
+
+
+
+krb5_error_code
+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);
+}
+
+krb5_error_code
+krb5_dbe_lookup_tl_data(context, entry, ret_tl_data)
+ krb5_context context;
+ krb5_db_entry * entry;
+ krb5_tl_data * ret_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 == ret_tl_data->tl_data_type) {
+ *ret_tl_data = *tl_data;
+ 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_create_key_data(context, entry)
+ krb5_context context;
+ krb5_db_entry * entry;
+{
+ if ((entry->key_data =
+ (krb5_key_data *) krb5_db_alloc(context, 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_update_mod_princ_data(context, entry, mod_date, mod_princ)
+ krb5_context context;
+ krb5_db_entry * entry;
+ krb5_timestamp mod_date;
+ krb5_const_principal mod_princ;
+{
+ krb5_tl_data tl_data;
+
+ krb5_error_code retval = 0;
+ krb5_octet * nextloc = 0;
+ char * unparse_mod_princ = 0;
+ unsigned int unparse_mod_princ_size;
+
+ if ((retval = krb5_unparse_name(context, mod_princ,
+ &unparse_mod_princ)))
+ return(retval);
+
+ unparse_mod_princ_size = strlen(unparse_mod_princ) + 1;
+
+ if ((nextloc = (krb5_octet *) malloc(unparse_mod_princ_size + 4))
+ == NULL) {
+ free(unparse_mod_princ);
+ return(ENOMEM);
+ }
+
+ 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_date, nextloc);
+
+ /* Mod Princ */
+ memcpy(nextloc+4, unparse_mod_princ, unparse_mod_princ_size);
+
+ retval = krb5_dbe_update_tl_data(context, entry, &tl_data);
+
+ free(unparse_mod_princ);
+ free(nextloc);
+
+ return(retval);
+}
+
+krb5_error_code
+krb5_dbe_lookup_mod_princ_data(context, entry, mod_time, mod_princ)
+ krb5_context context;
+ krb5_db_entry * entry;
+ krb5_timestamp * mod_time;
+ krb5_principal * mod_princ;
+{
+ krb5_tl_data tl_data;
+ krb5_error_code code;
+
+ tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
+
+ 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
+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_update_tl_data(context, entry, new_tl_data)
+ krb5_context context;
+ krb5_db_entry * entry;
+ krb5_tl_data * new_tl_data;
+{
+ krb5_tl_data * tl_data = NULL;
+ krb5_octet * tmp;
+
+ /* copy the new data first, so we can fail cleanly if malloc()
+ fails */
+ if ((tmp = (krb5_octet *) krb5_db_alloc(context, NULL, 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 */
+
+ if( new_tl_data->tl_data_type != KRB5_TL_DB_ARGS ) /* db_args can be multiple */
+ {
+ 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 *) krb5_db_alloc(context, NULL, sizeof(krb5_tl_data)))
+ == NULL) {
+ free(tmp);
+ return(ENOMEM);
+ }
+ memset( tl_data, 0, sizeof(krb5_tl_data));
+ tl_data->tl_data_next = entry->tl_data;
+ entry->tl_data = tl_data;
+ entry->n_tl_data++;
+ }
+
+ /* fill in the record */
+
+ if (tl_data->tl_data_contents)
+ krb5_db_free(context, 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);
+}
+
+
+
+/* change password functions */
+krb5_error_code
+krb5_dbe_cpw( krb5_context kcontext,
+ krb5_keyblock * master_key,
+ krb5_key_salt_tuple * ks_tuple,
+ int ks_tuple_count,
+ char * passwd,
+ int new_kvno,
+ krb5_boolean keepold,
+ krb5_db_entry * db_entry)
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.db_change_pwd( kcontext,
+ master_key,
+ ks_tuple,
+ ks_tuple_count,
+ passwd,
+ new_kvno,
+ keepold,
+ db_entry );
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ return status;
+}
+
+
+/* policy management functions */
+krb5_error_code krb5_db_create_policy( krb5_context kcontext, osa_policy_ent_t policy)
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.db_create_policy(kcontext, policy);
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ return status;
+}
+
+krb5_error_code krb5_db_get_policy ( krb5_context kcontext, char *name, osa_policy_ent_t *policy, int *cnt)
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.db_get_policy(kcontext, name, policy, cnt);
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ return status;
+}
+
+krb5_error_code krb5_db_put_policy( krb5_context kcontext, osa_policy_ent_t policy)
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.db_put_policy(kcontext, policy);
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ return status;
+}
+
+krb5_error_code krb5_db_iter_policy( krb5_context kcontext, char *match_entry, osa_adb_iter_policy_func func, void *data)
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.db_iter_policy(kcontext, match_entry, func, data);
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ return status;
+}
+
+krb5_error_code krb5_db_delete_policy( krb5_context kcontext, char *policy)
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ status = dal_handle->lib_handle->vftabl.db_delete_policy(kcontext, policy);
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ return status;
+}
+
+void krb5_db_free_policy( krb5_context kcontext, osa_policy_ent_t policy)
+{
+ krb5_error_code status = 0;
+ kdb5_dal_handle *dal_handle;
+
+ if( kcontext->db_context == NULL )
+ {
+ status = kdb_setup_lib_handle( kcontext );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ dal_handle = (kdb5_dal_handle *) kcontext->db_context;
+ status = kdb_lock_lib_lock( dal_handle->lib_handle, FALSE );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ dal_handle->lib_handle->vftabl.db_free_policy(kcontext, policy);
+ kdb_unlock_lib_lock( dal_handle->lib_handle, FALSE );
+
+ clean_n_exit:
+ return;
+}
+
diff --git a/src/lib/kdb/kdb5.h b/src/lib/kdb/kdb5.h
new file mode 100644
index 0000000..93b594a
--- /dev/null
+++ b/src/lib/kdb/kdb5.h
@@ -0,0 +1,219 @@
+#ifndef _KRB5_KDB5_H_
+#define _KRB5_KDB5_H_
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <errno.h>
+#include <utime.h>
+#include <utime.h>
+#include <k5-int.h>
+#include "err_handle.h"
+
+#define KDB_MAX_DB_NAME 128
+#define KDB_REALM_SECTION "realms"
+#define KDB_MODULE_POINTER "database_module"
+#define KDB_MODULE_SECTION "db_modules"
+#define KDB_LIB_POINTER "db_library"
+#define KDB_DATABASE_CONF_FILE DEFAULT_SECURE_PROFILE_PATH
+#define KDB_DATABASE_ENV_PROF KDC_PROFILE_ENV
+
+#define KRB5_KDB_OPEN_RW 0
+#define KRB5_KDB_OPEN_RO 1
+
+#define KRB5_KDB_OPT_SET_DB_NAME 0
+#define KRB5_KDB_OPT_SET_LOCK_MODE 1
+
+#define KRB5_DB_GET_DB_CONTEXT(kcontext) ( ((kdb5_dal_handle*) (kcontext)->db_context)->db_context )
+#define KRB5_DB_GET_PROFILE(kcontext) ( (kcontext)->profile )
+#define KRB5_DB_GET_REALM(kcontext) ( (kcontext)->default_realm )
+
+#ifndef KRB5_DB_LOCKMODE_SHARED
+#define KRB5_DB_LOCKMODE_SHARED 0x0001
+#endif
+
+#ifndef KRB5_DB_LOCKMODE_EXCLUSIVE
+#define KRB5_DB_LOCKMODE_EXCLUSIVE 0x0002
+#endif
+
+#ifndef KRB5_DB_LOCKMODE_DONTBLOCK
+#define KRB5_DB_LOCKMODE_DONTBLOCK 0x0004
+#endif
+
+#ifndef KRB5_DB_LOCKMODE_PERMANENT
+#define KRB5_DB_LOCKMODE_PERMANENT 0x0008
+#endif
+
+typedef struct _kdb_vftabl{
+ short int maj_ver;
+ short int min_ver;
+
+ short int is_thread_safe;
+
+ krb5_error_code (*init_library)(krb5_set_err_func_t);
+ krb5_error_code (*fini_library)();
+ krb5_error_code (*init_module) ( krb5_context kcontext,
+ char * conf_section,
+ char ** db_args,
+ int mode );
+
+ krb5_error_code (*fini_module) ( krb5_context kcontext );
+
+ krb5_error_code (*db_create) ( krb5_context kcontext,
+ char * conf_section,
+ char ** db_args );
+
+ krb5_error_code (*db_destroy) ( krb5_context kcontext,
+ char *conf_section,
+ char ** db_args );
+
+ krb5_error_code (*db_get_age) ( krb5_context kcontext,
+ char *db_name,
+ time_t *age );
+
+ krb5_error_code (*db_set_option) ( krb5_context kcontext,
+ int option,
+ void *value );
+
+ krb5_error_code (*db_lock) ( krb5_context kcontext,
+ int mode );
+
+ krb5_error_code (*db_unlock) ( krb5_context kcontext);
+
+ krb5_error_code (*db_get_principal) ( krb5_context kcontext,
+ krb5_const_principal search_for,
+ krb5_db_entry *entries,
+ int *nentries,
+ krb5_boolean *more );
+
+ krb5_error_code (*db_free_principal) ( krb5_context kcontext,
+ krb5_db_entry *entry,
+ int count );
+
+ krb5_error_code (*db_put_principal) ( krb5_context kcontext,
+ krb5_db_entry *entries,
+ int *nentries,
+ char **db_args);
+
+ krb5_error_code (*db_delete_principal) ( krb5_context kcontext,
+ krb5_const_principal search_for,
+ int *nentries );
+
+ krb5_error_code (*db_iterate) ( krb5_context kcontext,
+ char *match_entry,
+ int (*func) (krb5_pointer, krb5_db_entry *),
+ krb5_pointer func_arg );
+
+ krb5_error_code (*db_create_policy) ( krb5_context kcontext,
+ osa_policy_ent_t policy );
+
+ krb5_error_code (*db_get_policy) ( krb5_context kcontext,
+ char *name,
+ osa_policy_ent_t *policy,
+ int *cnt);
+
+ krb5_error_code (*db_put_policy) ( krb5_context kcontext,
+ osa_policy_ent_t policy );
+
+ krb5_error_code (*db_iter_policy) ( krb5_context kcontext,
+ char *match_entry,
+ osa_adb_iter_policy_func func,
+ void *data );
+
+
+ krb5_error_code (*db_delete_policy) ( krb5_context kcontext,
+ char *policy );
+
+ void (*db_free_policy) ( krb5_context kcontext,
+ osa_policy_ent_t val );
+
+ krb5_error_code (*db_supported_realms) ( krb5_context kcontext,
+ char **realms );
+
+ krb5_error_code (*db_free_supported_realms) ( krb5_context kcontext,
+ char **realms );
+
+
+ const char * (*errcode_2_string) ( krb5_context kcontext,
+ long err_code );
+
+ void * (*db_alloc) (krb5_context kcontext, void *ptr, size_t size);
+ void (*db_free) (krb5_context kcontext, void *ptr);
+
+
+
+ /* optional functions */
+ krb5_error_code (*set_master_key) ( krb5_context kcontext,
+ char *pwd,
+ krb5_keyblock *key);
+
+ krb5_error_code (*get_master_key) ( krb5_context kcontext,
+ krb5_keyblock **key);
+
+
+ krb5_error_code (*setup_master_key_name) ( krb5_context kcontext,
+ char *keyname,
+ char *realm,
+ char **fullname,
+ krb5_principal *principal);
+
+ krb5_error_code (*store_master_key) ( krb5_context kcontext,
+ char *db_arg,
+ krb5_principal mname,
+ krb5_keyblock *key,
+ char *master_pwd);
+
+ krb5_error_code (*fetch_master_key) ( krb5_context kcontext,
+ krb5_principal mname,
+ krb5_keyblock *key,
+ int *kvno,
+ char *db_args);
+
+ krb5_error_code (*verify_master_key) ( krb5_context kcontext,
+ krb5_principal mprinc,
+ krb5_keyblock *mkey );
+
+ krb5_error_code (*dbe_search_enctype) ( krb5_context kcontext,
+ krb5_db_entry *dbentp,
+ krb5_int32 *start,
+ krb5_int32 ktype,
+ krb5_int32 stype,
+ krb5_int32 kvno,
+ krb5_key_data **kdatap);
+
+
+ krb5_error_code
+ (*db_change_pwd) ( krb5_context context,
+ krb5_keyblock * master_key,
+ krb5_key_salt_tuple * ks_tuple,
+ int ks_tuple_count,
+ char * passwd,
+ int new_kvno,
+ krb5_boolean keepold,
+ krb5_db_entry * db_entry);
+
+} kdb_vftabl;
+
+typedef struct _db_library {
+ char name[KDB_MAX_DB_NAME];
+ int reference_cnt;
+#ifdef HAVE_PTHREAD_H
+ pthread_mutex_t lib_lock;
+ pthread_cond_t unlocked; /* To check whether some one has called db_unlock */
+ int recursive_cnt; /* this is used as lock to help recursive locking */
+ pthread_t lock_holder;
+ int excl;
+#endif
+ void *dl_handle;
+ kdb_vftabl vftabl;
+ struct _db_library *next, *prev;
+} *db_library;
+
+typedef struct _kdb5_dal_handle
+{
+ void *db_context; /* helps us to change db_library without affecting modules to some extend */
+ db_library lib_handle;
+} kdb5_dal_handle;
+
+#endif /* end of _KRB5_KDB5_H_ */
diff --git a/src/lib/kdb/kdb_cpw.c b/src/lib/kdb/kdb_cpw.c
index 962a2b5..f873a39 100644
--- a/src/lib/kdb/kdb_cpw.c
+++ b/src/lib/kdb/kdb_cpw.c
@@ -52,7 +52,6 @@
*/
#include "k5-int.h"
-#include "krb5/adm.h"
#include <stdio.h>
#include <errno.h>
@@ -86,11 +85,11 @@ cleanup_key_data(context, count, data)
for (i = 0; i < count; i++) {
for (j = 0; j < data[i].key_data_ver; j++) {
if (data[i].key_data_length[j]) {
- free(data[i].key_data_contents[j]);
+ krb5_db_free(context, data[i].key_data_contents[j]);
}
}
}
- free(data);
+ krb5_db_free(context, data);
}
static krb5_error_code
@@ -106,8 +105,13 @@ add_key_rnd(context, master_key, ks_tuple, ks_tuple_count, db_entry, kvno)
krb5_keyblock key;
krb5_db_entry krbtgt_entry;
krb5_boolean more;
- int max_kvno, one, i, j;
+ int max_kvno, one, i, j, k;
krb5_error_code retval;
+ krb5_key_data tmp_key_data;
+ krb5_key_data *tptr;
+
+ memset( &tmp_key_data, 0, sizeof(tmp_key_data));
+
retval = krb5_build_principal_ext(context, &krbtgt_princ,
db_entry->princ->realm.length,
@@ -176,19 +180,59 @@ add_key_rnd(context, master_key, ks_tuple, ks_tuple_count, db_entry, kvno)
&key)))
goto add_key_rnd_err;
+
+ /* db library will free this. Since, its a so, it could actually be using different memory management
+ function. So, its better if the memory is allocated by the db's malloc. So, a temporary memory is used
+ here which will later be copied to the db_entry */
retval = krb5_dbekd_encrypt_key_data(context, master_key,
&key, NULL, kvno,
- &db_entry->key_data[db_entry->n_key_data-1]);
+ &tmp_key_data);
krb5_free_keyblock_contents(context, &key);
-
- if (retval)
+ if( retval )
goto add_key_rnd_err;
+
+ tptr = &db_entry->key_data[db_entry->n_key_data-1];
+
+ tptr->key_data_ver = tmp_key_data.key_data_ver;
+ tptr->key_data_kvno = tmp_key_data.key_data_kvno;
+
+ for( k = 0; k < tmp_key_data.key_data_ver; k++ )
+ {
+ tptr->key_data_type[k] = tmp_key_data.key_data_type[k];
+ tptr->key_data_length[k] = tmp_key_data.key_data_length[k];
+ if( tmp_key_data.key_data_contents[k] )
+ {
+ tptr->key_data_contents[k] = krb5_db_alloc(context, NULL, tmp_key_data.key_data_length[k]);
+ if( tptr->key_data_contents[k] == NULL )
+ {
+ cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data);
+ db_entry->key_data = NULL;
+ db_entry->n_key_data = 0;
+ retval = ENOMEM;
+ goto add_key_rnd_err;
+ }
+ memcpy( tptr->key_data_contents[k], tmp_key_data.key_data_contents[k], tmp_key_data.key_data_length[k]);
+
+ memset( tmp_key_data.key_data_contents[k], 0, tmp_key_data.key_data_length[k]);
+ free( tmp_key_data.key_data_contents[k] );
+ tmp_key_data.key_data_contents[k] = NULL;
+ }
+ }
+
}
add_key_rnd_err:
krb5_db_free_principal(context, &krbtgt_entry, one);
+ for( i = 0; i < tmp_key_data.key_data_ver; i++ )
+ {
+ if( tmp_key_data.key_data_contents[i] )
+ {
+ memset( tmp_key_data.key_data_contents[i], 0, tmp_key_data.key_data_length[i]);
+ free( tmp_key_data.key_data_contents[i] );
+ }
+ }
return(retval);
}
@@ -242,6 +286,7 @@ krb5_dbe_crk(context, master_key, ks_tuple, ks_tuple_count, keepold, db_entry)
db_entry->key_data[i+n_new_key_data] = key_data[i];
memset(&key_data[i], 0, sizeof(krb5_key_data));
}
+ krb5_db_free(context, key_data); /* we moved the cotents to new memory. But, the original block which contained the data */
} else {
cleanup_key_data(context, key_data_count, key_data);
}
@@ -321,7 +366,11 @@ add_key_pwd(context, master_key, ks_tuple, ks_tuple_count, passwd,
krb5_keysalt key_salt;
krb5_keyblock key;
krb5_data pwd;
- int i, j;
+ int i, j, k;
+ krb5_key_data tmp_key_data;
+ krb5_key_data *tptr;
+
+ memset( &tmp_key_data, 0, sizeof(tmp_key_data));
retval = 0;
@@ -424,18 +473,56 @@ add_key_pwd(context, master_key, ks_tuple, ks_tuple_count, passwd,
key_salt.data.length =
krb5_princ_realm(context, db_entry->princ)->length;
- if ((retval = krb5_dbekd_encrypt_key_data(context, master_key, &key,
- (const krb5_keysalt *)&key_salt,
- kvno, &db_entry->key_data[db_entry->n_key_data-1]))) {
- if (key_salt.data.data)
- free(key_salt.data.data);
- krb5_xfree(key.contents);
- return(retval);
- }
+ /* memory allocation to be done by db. So, use temporary block and later copy
+ it to the memory allocated by db */
+ retval = krb5_dbekd_encrypt_key_data(context, master_key, &key,
+ (const krb5_keysalt *)&key_salt,
+ kvno, &tmp_key_data);
if (key_salt.data.data)
- free(key_salt.data.data);
+ free(key_salt.data.data);
krb5_xfree(key.contents);
+
+ if( retval )
+ return retval;
+
+ tptr = &db_entry->key_data[db_entry->n_key_data-1];
+
+ tptr->key_data_ver = tmp_key_data.key_data_ver;
+ tptr->key_data_kvno = tmp_key_data.key_data_kvno;
+
+ for( k = 0; k < tmp_key_data.key_data_ver; k++ )
+ {
+ tptr->key_data_type[k] = tmp_key_data.key_data_type[k];
+ tptr->key_data_length[k] = tmp_key_data.key_data_length[k];
+ if( tmp_key_data.key_data_contents[k] )
+ {
+ tptr->key_data_contents[k] = krb5_db_alloc(context, NULL, tmp_key_data.key_data_length[k]);
+ if( tptr->key_data_contents[k] == NULL )
+ {
+ cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data);
+ db_entry->key_data = NULL;
+ db_entry->n_key_data = 0;
+ retval = ENOMEM;
+ goto add_key_pwd_err;
+ }
+ memcpy( tptr->key_data_contents[k], tmp_key_data.key_data_contents[k], tmp_key_data.key_data_length[k]);
+
+ memset( tmp_key_data.key_data_contents[k], 0, tmp_key_data.key_data_length[k]);
+ free( tmp_key_data.key_data_contents[k] );
+ tmp_key_data.key_data_contents[k] = NULL;
+ }
+ }
+ }
+ add_key_pwd_err:
+ for( i = 0; i < tmp_key_data.key_data_ver; i++ )
+ {
+ if( tmp_key_data.key_data_contents[i] )
+ {
+ memset( tmp_key_data.key_data_contents[i], 0, tmp_key_data.key_data_length[i]);
+ free( tmp_key_data.key_data_contents[i] );
+ }
}
+
return(retval);
}
@@ -446,7 +533,7 @@ add_key_pwd(context, master_key, ks_tuple, ks_tuple_count, passwd,
* As a side effect all old keys are nuked if keepold is false.
*/
krb5_error_code
-krb5_dbe_cpw(context, master_key, ks_tuple, ks_tuple_count, passwd,
+krb5_dbe_def_cpw(context, master_key, ks_tuple, ks_tuple_count, passwd,
new_kvno, keepold, db_entry)
krb5_context context;
krb5_keyblock * master_key;
@@ -495,6 +582,7 @@ krb5_dbe_cpw(context, master_key, ks_tuple, ks_tuple_count, passwd,
db_entry->key_data[i+n_new_key_data] = key_data[i];
memset(&key_data[i], 0, sizeof(krb5_key_data));
}
+ krb5_db_free( context, key_data );
} else {
cleanup_key_data(context, key_data_count, key_data);
}
@@ -556,3 +644,5 @@ krb5_dbe_apw(context, master_key, ks_tuple, ks_tuple_count, passwd, db_entry)
}
return(retval);
}
+
+
diff --git a/src/lib/kdb/kdb_db2/ChangeLog b/src/lib/kdb/kdb_db2/ChangeLog
new file mode 100644
index 0000000..6ebc2a0
--- /dev/null
+++ b/src/lib/kdb/kdb_db2/ChangeLog
@@ -0,0 +1,17 @@
+2005-06-20 Ken Raeburn <raeburn@mit.edu>
+
+ Novell merge.
+ * Makefile.in:
+ * adb_openclose.c:
+ * adb_policy.c:
+ * configure.in:
+ * db2_exp.c:
+ * kdb_compat.h:
+ * kdb_db2.c:
+ * kdb_db2.h:
+ * kdb_xdr.c:
+ * kdb_xdr.h:
+ * libkdb_db2.exports:
+ * pol_xdr.c:
+ * policy_db.h:
+
diff --git a/src/lib/kdb/kdb_db2/Makefile.in b/src/lib/kdb/kdb_db2/Makefile.in
new file mode 100644
index 0000000..ebd39f0
--- /dev/null
+++ b/src/lib/kdb/kdb_db2/Makefile.in
@@ -0,0 +1,150 @@
+thisconfigdir=.
+myfulldir=lib/kdb/kdb_db2
+mydir=.
+BUILDTOP=$(REL)..$(S)..$(S)..
+KRB5_RUN_ENV = @KRB5_RUN_ENV@
+KRB5_CONFIG_SETUP = KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf ; export KRB5_CONFIG ;
+PROG_LIBPATH=-L$(TOPLIBD)
+PROG_RPATH=$(KRB5_LIBDIR)
+
+LOCALINCLUDES = -I..
+
+LIBBASE=kdb_db2
+LIB=$(LIBBASE)
+LIBMAJOR=4
+LIBMINOR=0
+RELDIR=kdb/kdb_db2
+SO_EXT=.so
+# Depends on libk5crypto and libkrb5
+
+SHLIB_EXPDEPS = \
+ $(TOPLIBD)/libk5crypto$(SHLIBEXT) \
+ $(TOPLIBD)/libkrb5$(SHLIBEXT)
+SHLIB_EXPLIBS=-lkrb5 -lcom_err -lk5crypto $(KDB5_DB_LIB) $(LIBS)
+SHLIB_DIRS=-L$(TOPLIBD)
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+
+DBDIR = $(BUILDTOP)/util/db2
+DBOBJLISTS = $(DBOBJLISTS-@DB_VERSION@)
+DBOBJLISTS-sys =
+DBOBJLISTS-k5 = $(DBDIR)/hash/OBJS.ST $(DBDIR)/btree/OBJS.ST \
+ $(DBDIR)/db/OBJS.ST $(DBDIR)/mpool/OBJS.ST $(DBDIR)/recno/OBJS.ST \
+ $(DBDIR)/clib/OBJS.ST
+
+all:: lib$(LIB)$(SO_EXT)
+
+SRCS= \
+ $(srcdir)/kdb_xdr.c \
+ $(srcdir)/adb_openclose.c \
+ $(srcdir)/adb_policy.c \
+ $(srcdir)/kdb_db2.c \
+ $(srcdir)/pol_xdr.c \
+ $(srcdir)/db2_exp.c
+
+STOBJLISTS=OBJS.ST $(DBOBJLISTS)
+STLIBOBJS= \
+ kdb_xdr.o \
+ adb_openclose.o \
+ adb_policy.o \
+ kdb_db2.o \
+ pol_xdr.o \
+ db2_exp.o
+
+all-unix:: all-liblinks
+install-unix:: install-libs
+clean-unix:: clean-liblinks clean-libs clean-libobjs
+
+lib$(LIB)$(SO_EXT): db2_exp.o # lib$(LIB)$(STLIBEXT)
+ $(CC) -shared -o $@ -L$(TOPLIBD) $^ -lgssrpc -ldb $(SHLIB_EXPLIBS)
+
+clean::
+ $(RM) lib$(LIB)$(SO_EXT) db2_exp.o
+
+
+t_kdb: t_kdb.o $(OBJS) $(KDB5_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+ $(CC_LINK) -o t_kdb t_kdb.o $(OBJS) $(KDB5_LIBS) $(KRB5_BASE_LIBS)
+
+check:: t_kdb
+ $(RM) test_db
+ $(KRB5_CONFIG_SETUP) $(KRB5_RUN_ENV) ./t_kdb -tcv
+ $(KRB5_CONFIG_SETUP) $(KRB5_RUN_ENV) ./t_kdb -tcvr
+
+clean::
+ $(RM) t_kdb t_kdb.o
+
+
+adb_openclose.c adb_policy.c : ../adb_err.h
+
+# @lib_frag@
+# @libobj_frag@
+
+# +++ Dependency line eater +++
+#
+# Makefile dependencies follow. This must be the last section in
+# the Makefile.in file
+#
+kdb_xdr.so kdb_xdr.po $(OUTPRE)kdb_xdr.$(OBJEXT): kdb_xdr.c \
+ $(SRCTOP)/include/k5-int.h $(BUILDTOP)/include/krb5/osconf.h \
+ $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-platform.h \
+ $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-thread.h \
+ $(BUILDTOP)/include/krb5.h $(COM_ERR_DEPS) $(BUILDTOP)/include/profile.h \
+ $(SRCTOP)/include/port-sockets.h $(BUILDTOP)/include/krb5/autoconf.h \
+ $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/krb5/kdb.h \
+ kdb_xdr.h
+adb_openclose.so adb_openclose.po $(OUTPRE)adb_openclose.$(OBJEXT): \
+ adb_openclose.c $(SRCTOP)/include/k5-int.h $(BUILDTOP)/include/krb5/osconf.h \
+ $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-platform.h \
+ $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-thread.h \
+ $(BUILDTOP)/include/krb5.h $(COM_ERR_DEPS) $(BUILDTOP)/include/profile.h \
+ $(SRCTOP)/include/port-sockets.h $(BUILDTOP)/include/krb5/autoconf.h \
+ $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/krb5/kdb.h \
+ policy_db.h $(SRCTOP)/include/krb5/kdb.h $(DB_DEPS) \
+ $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/gssrpc/rename.h \
+ $(BUILDTOP)/include/gssrpc/xdr.h ../adb_err.h
+adb_policy.so adb_policy.po $(OUTPRE)adb_policy.$(OBJEXT): \
+ adb_policy.c policy_db.h $(SRCTOP)/include/k5-int.h \
+ $(BUILDTOP)/include/krb5/osconf.h $(BUILDTOP)/include/krb5/autoconf.h \
+ $(SRCTOP)/include/k5-platform.h $(BUILDTOP)/include/krb5/autoconf.h \
+ $(SRCTOP)/include/k5-thread.h $(BUILDTOP)/include/krb5.h \
+ $(COM_ERR_DEPS) $(BUILDTOP)/include/profile.h $(SRCTOP)/include/port-sockets.h \
+ $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/socket-utils.h \
+ $(SRCTOP)/include/krb5/kdb.h $(SRCTOP)/include/krb5/kdb.h \
+ $(DB_DEPS) $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/gssrpc/rename.h \
+ $(BUILDTOP)/include/gssrpc/xdr.h ../adb_err.h
+kdb_db2.so kdb_db2.po $(OUTPRE)kdb_db2.$(OBJEXT): kdb_db2.c \
+ $(SRCTOP)/include/k5-int.h $(BUILDTOP)/include/krb5/osconf.h \
+ $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-platform.h \
+ $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-thread.h \
+ $(BUILDTOP)/include/krb5.h $(COM_ERR_DEPS) $(BUILDTOP)/include/profile.h \
+ $(SRCTOP)/include/port-sockets.h $(BUILDTOP)/include/krb5/autoconf.h \
+ $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/krb5/kdb.h \
+ $(DB_DEPS) $(srcdir)/../kdb5.h $(SRCTOP)/include/k5-int.h \
+ $(srcdir)/../err_handle.h kdb_db2.h policy_db.h $(SRCTOP)/include/krb5/kdb.h \
+ $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/gssrpc/rename.h \
+ $(BUILDTOP)/include/gssrpc/xdr.h ../adb_err.h kdb_xdr.h \
+ kdb_compat.h
+pol_xdr.so pol_xdr.po $(OUTPRE)pol_xdr.$(OBJEXT): pol_xdr.c \
+ $(BUILDTOP)/include/krb5.h $(COM_ERR_DEPS) $(BUILDTOP)/include/gssrpc/rpc.h \
+ $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/gssrpc/rename.h \
+ $(BUILDTOP)/include/gssrpc/xdr.h $(BUILDTOP)/include/gssrpc/auth.h \
+ $(BUILDTOP)/include/gssrpc/clnt.h $(BUILDTOP)/include/gssrpc/rpc_msg.h \
+ $(BUILDTOP)/include/gssrpc/auth_unix.h $(BUILDTOP)/include/gssrpc/auth_gss.h \
+ $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/svc_auth.h \
+ $(BUILDTOP)/include/gssrpc/svc.h $(SRCTOP)/include/krb5/kdb.h \
+ policy_db.h $(SRCTOP)/include/k5-int.h $(BUILDTOP)/include/krb5/osconf.h \
+ $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-platform.h \
+ $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-thread.h \
+ $(BUILDTOP)/include/profile.h $(SRCTOP)/include/port-sockets.h \
+ $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/socket-utils.h \
+ $(SRCTOP)/include/krb5/kdb.h $(DB_DEPS) ../adb_err.h
+db2_exp.so db2_exp.po $(OUTPRE)db2_exp.$(OBJEXT): db2_exp.c \
+ $(SRCTOP)/include/k5-int.h $(BUILDTOP)/include/krb5/osconf.h \
+ $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-platform.h \
+ $(BUILDTOP)/include/krb5/autoconf.h $(SRCTOP)/include/k5-thread.h \
+ $(BUILDTOP)/include/krb5.h $(COM_ERR_DEPS) $(BUILDTOP)/include/profile.h \
+ $(SRCTOP)/include/port-sockets.h $(BUILDTOP)/include/krb5/autoconf.h \
+ $(SRCTOP)/include/socket-utils.h $(SRCTOP)/include/krb5/kdb.h \
+ $(DB_DEPS) $(srcdir)/../kdb5.h $(SRCTOP)/include/k5-int.h \
+ $(srcdir)/../err_handle.h kdb_db2.h policy_db.h $(SRCTOP)/include/krb5/kdb.h \
+ $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/gssrpc/rename.h \
+ $(BUILDTOP)/include/gssrpc/xdr.h ../adb_err.h kdb_xdr.h
diff --git a/src/lib/kdb/kdb_db2/adb_openclose.c b/src/lib/kdb/kdb_db2/adb_openclose.c
new file mode 100644
index 0000000..97ce112
--- /dev/null
+++ b/src/lib/kdb/kdb_db2/adb_openclose.c
@@ -0,0 +1,412 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <sys/file.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <k5-int.h>
+#include "policy_db.h"
+#include <stdlib.h>
+#include <db.h>
+
+#define MAX_LOCK_TRIES 5
+
+struct _locklist {
+ osa_adb_lock_ent lockinfo;
+ struct _locklist *next;
+};
+
+krb5_error_code osa_adb_create_db(char *filename, char *lockfilename,
+ int magic)
+{
+ int lf;
+ DB *db;
+ BTREEINFO btinfo;
+
+ memset(&btinfo, 0, sizeof(btinfo));
+ btinfo.flags = 0;
+ btinfo.cachesize = 0;
+ btinfo.psize = 4096;
+ btinfo.lorder = 0;
+ btinfo.minkeypage = 0;
+ btinfo.compare = NULL;
+ btinfo.prefix = NULL;
+ db = dbopen(filename, O_RDWR | O_CREAT | O_EXCL, 0600, DB_BTREE, &btinfo);
+ if (db == NULL)
+ return errno;
+ if (db->close(db) < 0)
+ return errno;
+
+ /* only create the lock file if we successfully created the db */
+ lf = THREEPARAMOPEN(lockfilename, O_RDWR | O_CREAT | O_EXCL, 0600);
+ if (lf == -1)
+ return errno;
+ (void) close(lf);
+
+ return OSA_ADB_OK;
+}
+
+krb5_error_code osa_adb_destroy_db(char *filename, char *lockfilename,
+ int magic)
+{
+ /* the admin databases do not contain security-critical data */
+ if (unlink(filename) < 0 ||
+ unlink(lockfilename) < 0)
+ return errno;
+ return OSA_ADB_OK;
+}
+
+krb5_error_code osa_adb_rename_db(char *filefrom, char *lockfrom,
+ char *fileto, char *lockto, int magic)
+{
+ osa_adb_db_t fromdb, todb;
+ krb5_error_code ret;
+
+ /* make sure todb exists */
+ if ((ret = osa_adb_create_db(fileto, lockto, magic)) &&
+ ret != EEXIST)
+ return ret;
+
+ if ((ret = osa_adb_init_db(&fromdb, filefrom, lockfrom, magic)))
+ return ret;
+ if ((ret = osa_adb_init_db(&todb, fileto, lockto, magic))) {
+ (void) osa_adb_fini_db(fromdb, magic);
+ return ret;
+ }
+ if ((ret = osa_adb_get_lock(fromdb, KRB5_DB_LOCKMODE_PERMANENT))) {
+ (void) osa_adb_fini_db(fromdb, magic);
+ (void) osa_adb_fini_db(todb, magic);
+ return ret;
+ }
+ if ((ret = osa_adb_get_lock(todb, KRB5_DB_LOCKMODE_PERMANENT))) {
+ (void) osa_adb_fini_db(fromdb, magic);
+ (void) osa_adb_fini_db(todb, magic);
+ return ret;
+ }
+ if ((rename(filefrom, fileto) < 0)) {
+ (void) osa_adb_fini_db(fromdb, magic);
+ (void) osa_adb_fini_db(todb, magic);
+ return errno;
+ }
+ /*
+ * Do not release the lock on fromdb because it is being renamed
+ * out of existence; no one can ever use it again.
+ */
+ if ((ret = osa_adb_release_lock(todb))) {
+ (void) osa_adb_fini_db(fromdb, magic);
+ (void) osa_adb_fini_db(todb, magic);
+ return ret;
+ }
+
+ (void) osa_adb_fini_db(fromdb, magic);
+ (void) osa_adb_fini_db(todb, magic);
+ return 0;
+}
+
+krb5_error_code osa_adb_init_db(osa_adb_db_t *dbp, char *filename,
+ char *lockfilename, int magic)
+{
+ osa_adb_db_t db;
+ static struct _locklist *locklist = NULL;
+ struct _locklist *lockp;
+ krb5_error_code code;
+
+ if (dbp == NULL || filename == NULL)
+ return EINVAL;
+
+ db = (osa_adb_princ_t) malloc(sizeof(osa_adb_db_ent));
+ if (db == NULL)
+ return ENOMEM;
+
+ memset(db, 0, sizeof(*db));
+ db->info.hash = NULL;
+ db->info.bsize = 256;
+ db->info.ffactor = 8;
+ db->info.nelem = 25000;
+ db->info.lorder = 0;
+
+ db->btinfo.flags = 0;
+ db->btinfo.cachesize = 0;
+ db->btinfo.psize = 4096;
+ db->btinfo.lorder = 0;
+ db->btinfo.minkeypage = 0;
+ db->btinfo.compare = NULL;
+ db->btinfo.prefix = NULL;
+ /*
+ * A process is allowed to open the same database multiple times
+ * and access it via different handles. If the handles use
+ * distinct lockinfo structures, things get confused: lock(A),
+ * lock(B), release(B) will result in the kernel unlocking the
+ * lock file but handle A will still think the file is locked.
+ * Therefore, all handles using the same lock file must share a
+ * single lockinfo structure.
+ *
+ * It is not sufficient to have a single lockinfo structure,
+ * however, because a single process may also wish to open
+ * multiple different databases simultaneously, with different
+ * lock files. This code used to use a single static lockinfo
+ * structure, which means that the second database opened used
+ * the first database's lock file. This was Bad.
+ *
+ * We now maintain a linked list of lockinfo structures, keyed by
+ * lockfilename. An entry is added when this function is called
+ * with a new lockfilename, and all subsequent calls with that
+ * lockfilename use the existing entry, updating the refcnt.
+ * When the database is closed with fini_db(), the refcnt is
+ * decremented, and when it is zero the lockinfo structure is
+ * freed and reset. The entry in the linked list, however, is
+ * never removed; it will just be reinitialized the next time
+ * init_db is called with the right lockfilename.
+ */
+
+ /* find or create the lockinfo structure for lockfilename */
+ lockp = locklist;
+ while (lockp) {
+ if (strcmp(lockp->lockinfo.filename, lockfilename) == 0)
+ break;
+ else
+ lockp = lockp->next;
+ }
+ if (lockp == NULL) {
+ /* doesn't exist, create it, add to list */
+ lockp = (struct _locklist *) malloc(sizeof(*lockp));
+ if (lockp == NULL) {
+ free(db);
+ return ENOMEM;
+ }
+ memset(lockp, 0, sizeof(*lockp));
+ lockp->next = locklist;
+ locklist = lockp;
+ }
+
+ /* now initialize lockp->lockinfo if necessary */
+ if (lockp->lockinfo.lockfile == NULL) {
+ if ((code = krb5_init_context(&lockp->lockinfo.context))) {
+ free(db);
+ return((krb5_error_code) code);
+ }
+
+ /*
+ * needs be open read/write so that write locking can work with
+ * POSIX systems
+ */
+ lockp->lockinfo.filename = strdup(lockfilename);
+ if ((lockp->lockinfo.lockfile = fopen(lockfilename, "r+")) == NULL) {
+ /*
+ * maybe someone took away write permission so we could only
+ * get shared locks?
+ */
+ if ((lockp->lockinfo.lockfile = fopen(lockfilename, "r"))
+ == NULL) {
+ free(db);
+ return OSA_ADB_NOLOCKFILE;
+ }
+ }
+ lockp->lockinfo.lockmode = lockp->lockinfo.lockcnt = 0;
+ }
+
+ /* lockp is set, lockinfo is initialized, update the reference count */
+ db->lock = &lockp->lockinfo;
+ db->lock->refcnt++;
+
+ db->opencnt = 0;
+ db->filename = strdup(filename);
+ db->magic = magic;
+
+ *dbp = db;
+
+ return OSA_ADB_OK;
+}
+
+krb5_error_code osa_adb_fini_db(osa_adb_db_t db, int magic)
+{
+ if (db->magic != magic)
+ return EINVAL;
+ if (db->lock->refcnt == 0) {
+ /* barry says this can't happen */
+ return OSA_ADB_FAILURE;
+ } else {
+ db->lock->refcnt--;
+ }
+
+ if (db->lock->refcnt == 0) {
+ /*
+ * Don't free db->lock->filename, it is used as a key to
+ * find the lockinfo entry in the linked list. If the
+ * lockfile doesn't exist, we must be closing the database
+ * after trashing it. This has to be allowed, so don't
+ * generate an error.
+ */
+ if (db->lock->lockmode != KRB5_DB_LOCKMODE_PERMANENT)
+ (void) fclose(db->lock->lockfile);
+ db->lock->lockfile = NULL;
+ krb5_free_context(db->lock->context);
+ }
+
+ db->magic = 0;
+ free(db->filename);
+ free(db);
+ return OSA_ADB_OK;
+}
+
+krb5_error_code osa_adb_get_lock(osa_adb_db_t db, int mode)
+{
+ int tries, gotlock, perm, krb5_mode, ret = 0;
+
+ if (db->lock->lockmode >= mode) {
+ /* No need to upgrade lock, just incr refcnt and return */
+ db->lock->lockcnt++;
+ return(OSA_ADB_OK);
+ }
+
+ perm = 0;
+ switch (mode) {
+ case KRB5_DB_LOCKMODE_PERMANENT:
+ perm = 1;
+ case KRB5_DB_LOCKMODE_EXCLUSIVE:
+ krb5_mode = KRB5_LOCKMODE_EXCLUSIVE;
+ break;
+ case KRB5_DB_LOCKMODE_SHARED:
+ krb5_mode = KRB5_LOCKMODE_SHARED;
+ break;
+ default:
+ return(EINVAL);
+ }
+
+ for (gotlock = tries = 0; tries < MAX_LOCK_TRIES; tries++) {
+ if ((ret = krb5_lock_file(db->lock->context,
+ fileno(db->lock->lockfile),
+ krb5_mode|KRB5_LOCKMODE_DONTBLOCK)) == 0) {
+ gotlock++;
+ break;
+ } else if (ret == EBADF && mode == KRB5_DB_LOCKMODE_EXCLUSIVE)
+ /* tried to exclusive-lock something we don't have */
+ /* write access to */
+ return OSA_ADB_NOEXCL_PERM;
+
+ sleep(1);
+ }
+
+ /* test for all the likely "can't get lock" error codes */
+ if (ret == EACCES || ret == EAGAIN || ret == EWOULDBLOCK)
+ return OSA_ADB_CANTLOCK_DB;
+ else if (ret != 0)
+ return ret;
+
+ /*
+ * If the file no longer exists, someone acquired a permanent
+ * lock. If that process terminates its exclusive lock is lost,
+ * but if we already had the file open we can (probably) lock it
+ * even though it has been unlinked. So we need to insist that
+ * it exist.
+ */
+ if (access(db->lock->filename, F_OK) < 0) {
+ (void) krb5_lock_file(db->lock->context,
+ fileno(db->lock->lockfile),
+ KRB5_LOCKMODE_UNLOCK);
+ return OSA_ADB_NOLOCKFILE;
+ }
+
+ /* we have the shared/exclusive lock */
+
+ if (perm) {
+ if (unlink(db->lock->filename) < 0) {
+ /* somehow we can't delete the file, but we already */
+ /* have the lock, so release it and return */
+
+ ret = errno;
+ (void) krb5_lock_file(db->lock->context,
+ fileno(db->lock->lockfile),
+ KRB5_LOCKMODE_UNLOCK);
+
+ /* maybe we should return CANTLOCK_DB.. but that would */
+ /* look just like the db was already locked */
+ return ret;
+ }
+
+ /* this releases our exclusive lock.. which is okay because */
+ /* now no one else can get one either */
+ (void) fclose(db->lock->lockfile);
+ }
+
+ db->lock->lockmode = mode;
+ db->lock->lockcnt++;
+ return OSA_ADB_OK;
+}
+
+krb5_error_code osa_adb_release_lock(osa_adb_db_t db)
+{
+ int ret, fd;
+
+ if (!db->lock->lockcnt) /* lock already unlocked */
+ return OSA_ADB_NOTLOCKED;
+
+ if (--db->lock->lockcnt == 0) {
+ if (db->lock->lockmode == KRB5_DB_LOCKMODE_PERMANENT) {
+ /* now we need to create the file since it does not exist */
+ fd = THREEPARAMOPEN(db->lock->filename,O_RDWR | O_CREAT | O_EXCL,
+ 0600);
+ if ((db->lock->lockfile = fdopen(fd, "w+")) == NULL)
+ return OSA_ADB_NOLOCKFILE;
+ } else if ((ret = krb5_lock_file(db->lock->context,
+ fileno(db->lock->lockfile),
+ KRB5_LOCKMODE_UNLOCK)))
+ return ret;
+
+ db->lock->lockmode = 0;
+ }
+ return OSA_ADB_OK;
+}
+
+krb5_error_code osa_adb_open_and_lock(osa_adb_princ_t db, int locktype)
+{
+ int ret;
+
+ ret = osa_adb_get_lock(db, locktype);
+ if (ret != OSA_ADB_OK)
+ return ret;
+ if (db->opencnt)
+ goto open_ok;
+
+ db->db = dbopen(db->filename, O_RDWR, 0600, DB_BTREE, &db->btinfo);
+ if (db->db != NULL)
+ goto open_ok;
+ switch (errno) {
+#ifdef EFTYPE
+ case EFTYPE:
+#endif
+ case EINVAL:
+ db->db = dbopen(db->filename, O_RDWR, 0600, DB_HASH, &db->info);
+ if (db->db != NULL)
+ goto open_ok;
+ default:
+ (void) osa_adb_release_lock(db);
+ if (errno == EINVAL)
+ return OSA_ADB_BAD_DB;
+ return errno;
+ }
+open_ok:
+ db->opencnt++;
+ return OSA_ADB_OK;
+}
+
+krb5_error_code osa_adb_close_and_unlock(osa_adb_princ_t db)
+{
+ if (--db->opencnt)
+ return osa_adb_release_lock(db);
+ if(db->db != NULL && db->db->close(db->db) == -1) {
+ (void) osa_adb_release_lock(db);
+ return OSA_ADB_FAILURE;
+ }
+
+ db->db = NULL;
+
+ return(osa_adb_release_lock(db));
+}
diff --git a/src/lib/kdb/kdb_db2/adb_policy.c b/src/lib/kdb/kdb_db2/adb_policy.c
new file mode 100644
index 0000000..e338cbb
--- /dev/null
+++ b/src/lib/kdb/kdb_db2/adb_policy.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <sys/file.h>
+#include <fcntl.h>
+#include "policy_db.h"
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#define OPENLOCK(db, mode) \
+{ \
+ int olret; \
+ if (db == NULL) \
+ return EINVAL; \
+ else if (db->magic != OSA_ADB_POLICY_DB_MAGIC) \
+ return OSA_ADB_DBINIT; \
+ else if ((olret = osa_adb_open_and_lock(db, mode)) != OSA_ADB_OK) \
+ return olret; \
+ }
+
+#define CLOSELOCK(db) \
+{ \
+ int cl_ret; \
+ if ((cl_ret = osa_adb_close_and_unlock(db)) != OSA_ADB_OK) \
+ return cl_ret; \
+}
+
+
+/*
+ * Function: osa_adb_create_policy
+ *
+ * Purpose: create a policy entry in the policy db.
+ *
+ * Arguments:
+ * entry (input) pointer to the entry to be added
+ * <return value> OSA_ADB_OK on success, else error code.
+ *
+ * Requires:
+ * entry have a valid name.
+ *
+ * Effects:
+ * creates the entry in the db
+ *
+ * Modifies:
+ * the policy db.
+ *
+ */
+krb5_error_code
+osa_adb_create_policy(osa_adb_policy_t db, osa_policy_ent_t entry)
+{
+ DBT dbkey;
+ DBT dbdata;
+ XDR xdrs;
+ int ret;
+
+ OPENLOCK(db, KRB5_DB_LOCKMODE_EXCLUSIVE);
+
+ if(entry->name == NULL) {
+ ret = EINVAL;
+ goto error;
+ }
+ dbkey.data = entry->name;
+ dbkey.size = (strlen(entry->name) + 1);
+
+ switch(db->db->get(db->db, &dbkey, &dbdata, 0)) {
+ case 0:
+ ret = OSA_ADB_DUP;
+ goto error;
+ case 1:
+ break;
+ default:
+ ret = errno;
+ goto error;
+ }
+ xdralloc_create(&xdrs, XDR_ENCODE);
+ if(!xdr_osa_policy_ent_rec(&xdrs, entry)) {
+ xdr_destroy(&xdrs);
+ ret = OSA_ADB_XDR_FAILURE;
+ goto error;
+ }
+ dbdata.data = xdralloc_getdata(&xdrs);
+ dbdata.size = xdr_getpos(&xdrs);
+ switch(db->db->put(db->db, &dbkey, &dbdata, R_NOOVERWRITE)) {
+ case 0:
+ if((db->db->sync(db->db, 0)) == -1)
+ ret = OSA_ADB_FAILURE;
+ ret = OSA_ADB_OK;
+ break;
+ case 1:
+ ret = OSA_ADB_DUP;
+ break;
+ default:
+ ret = OSA_ADB_FAILURE;
+ break;
+ }
+ xdr_destroy(&xdrs);
+
+error:
+ CLOSELOCK(db);
+ return ret;
+}
+
+/*
+ * Function: osa_adb_destroy_policy
+ *
+ * Purpose: destroy a policy entry
+ *
+ * Arguments:
+ * db (input) database handle
+ * name (input) name of policy
+ * <return value> OSA_ADB_OK on success, or error code.
+ *
+ * Requires:
+ * db being valid.
+ * name being non-null.
+ * Effects:
+ * deletes policy from db.
+ *
+ * Modifies:
+ * policy db.
+ *
+ */
+krb5_error_code
+osa_adb_destroy_policy(osa_adb_policy_t db, char *name)
+{
+ DBT dbkey;
+ int status, ret;
+
+ OPENLOCK(db, KRB5_DB_LOCKMODE_EXCLUSIVE);
+
+ if(name == NULL) {
+ ret = EINVAL;
+ goto error;
+ }
+ dbkey.data = name;
+ dbkey.size = (strlen(name) + 1);
+
+ status = db->db->del(db->db, &dbkey, 0);
+ switch(status) {
+ case 1:
+ ret = OSA_ADB_NOENT;
+ goto error;
+ case 0:
+ if ((db->db->sync(db->db, 0)) == -1) {
+ ret = OSA_ADB_FAILURE;
+ goto error;
+ }
+ ret = OSA_ADB_OK;
+ break;
+ default:
+ ret = OSA_ADB_FAILURE;
+ goto error;
+ }
+
+error:
+ CLOSELOCK(db);
+ return ret;
+}
+
+/*
+ * Function: osa_adb_get_policy
+ *
+ * Purpose: retrieve policy
+ *
+ * Arguments:
+ * db (input) db handle
+ * name (input) name of policy
+ * entry (output) policy entry
+ * cnt (inout) Number of entries
+ * <return value> 0 on success, error code on failure.
+ *
+ * Requires:
+ * Effects:
+ * Modifies:
+ */
+krb5_error_code
+osa_adb_get_policy(osa_adb_policy_t db, char *name,
+ osa_policy_ent_t *entry, int *cnt)
+{
+ DBT dbkey;
+ DBT dbdata;
+ XDR xdrs;
+ int ret;
+ char *aligned_data;
+
+ OPENLOCK(db, KRB5_DB_LOCKMODE_SHARED);
+
+ *cnt = 1;
+
+ if(name == NULL) {
+ ret = EINVAL;
+ goto error;
+ }
+ dbkey.data = name;
+ dbkey.size = (strlen(dbkey.data) + 1);
+ dbdata.data = NULL;
+ dbdata.size = 0;
+ switch((db->db->get(db->db, &dbkey, &dbdata, 0))) {
+ case 1:
+ ret = 0;
+ *cnt = 0;
+ goto error;
+ case 0:
+ break;
+ default:
+ ret = OSA_ADB_FAILURE;
+ goto error;
+ }
+ if (!(*(entry) = (osa_policy_ent_t)malloc(sizeof(osa_policy_ent_rec)))) {
+ ret = ENOMEM;
+ goto error;
+ }
+ if (!(aligned_data = (char *) malloc(dbdata.size))) {
+ ret = ENOMEM;
+ goto error;
+ }
+ memcpy(aligned_data, dbdata.data, dbdata.size);
+ memset(*entry, 0, sizeof(osa_policy_ent_rec));
+ xdrmem_create(&xdrs, aligned_data, dbdata.size, XDR_DECODE);
+ if (!xdr_osa_policy_ent_rec(&xdrs, *entry))
+ ret = OSA_ADB_FAILURE;
+ else ret = OSA_ADB_OK;
+ xdr_destroy(&xdrs);
+ free(aligned_data);
+
+error:
+ CLOSELOCK(db);
+ return ret;
+}
+
+/*
+ * Function: osa_adb_put_policy
+ *
+ * Purpose: update a policy in the dababase
+ *
+ * Arguments:
+ * db (input) db handle
+ * entry (input) policy entry
+ * <return value> 0 on success error code on failure.
+ *
+ * Requires:
+ * [requires]
+ *
+ * Effects:
+ * [effects]
+ *
+ * Modifies:
+ * [modifies]
+ *
+ */
+krb5_error_code
+osa_adb_put_policy(osa_adb_policy_t db, osa_policy_ent_t entry)
+{
+ DBT dbkey;
+ DBT dbdata;
+ DBT tmpdb;
+ XDR xdrs;
+ int ret;
+
+ OPENLOCK(db, KRB5_DB_LOCKMODE_EXCLUSIVE);
+
+ if(entry->name == NULL) {
+ ret = EINVAL;
+ goto error;
+ }
+ dbkey.data = entry->name;
+ dbkey.size = (strlen(entry->name) + 1);
+ switch(db->db->get(db->db, &dbkey, &tmpdb, 0)) {
+ case 0:
+ break;
+ case 1:
+ ret = OSA_ADB_NOENT;
+ goto error;
+ default:
+ ret = OSA_ADB_FAILURE;
+ goto error;
+ }
+ xdralloc_create(&xdrs, XDR_ENCODE);
+ if(!xdr_osa_policy_ent_rec(&xdrs, entry)) {
+ xdr_destroy(&xdrs);
+ ret = OSA_ADB_XDR_FAILURE;
+ goto error;
+ }
+ dbdata.data = xdralloc_getdata(&xdrs);
+ dbdata.size = xdr_getpos(&xdrs);
+ switch(db->db->put(db->db, &dbkey, &dbdata, 0)) {
+ case 0:
+ if((db->db->sync(db->db, 0)) == -1)
+ ret = OSA_ADB_FAILURE;
+ ret = OSA_ADB_OK;
+ break;
+ default:
+ ret = OSA_ADB_FAILURE;
+ break;
+ }
+ xdr_destroy(&xdrs);
+
+error:
+ CLOSELOCK(db);
+ return ret;
+}
+
+/*
+ * Function: osa_adb_iter_policy
+ *
+ * Purpose: iterate over the policy database.
+ *
+ * Arguments:
+ * db (input) db handle
+ * func (input) fucntion pointer to call
+ * data opaque data type
+ * <return value> 0 on success error code on failure
+ *
+ * Requires:
+ * Effects:
+ * Modifies:
+ */
+krb5_error_code
+osa_adb_iter_policy(osa_adb_policy_t db, osa_adb_iter_policy_func func,
+ void *data)
+{
+ DBT dbkey,
+ dbdata;
+ XDR xdrs;
+ int ret;
+ osa_policy_ent_t entry;
+ char *aligned_data;
+
+ OPENLOCK(db, KRB5_DB_LOCKMODE_EXCLUSIVE); /* hmmm */
+
+ if((ret = db->db->seq(db->db, &dbkey, &dbdata, R_FIRST)) == -1) {
+ ret = errno;
+ goto error;
+ }
+
+ while (ret == 0) {
+ if (!(entry = (osa_policy_ent_t) malloc(sizeof(osa_policy_ent_rec)))) {
+ ret = ENOMEM;
+ goto error;
+ }
+
+ if(!(aligned_data = (char *) malloc(dbdata.size))) {
+ ret = ENOMEM;
+ goto error;
+ }
+ memcpy(aligned_data, dbdata.data, dbdata.size);
+
+ memset(entry, 0, sizeof(osa_policy_ent_rec));
+ xdrmem_create(&xdrs, aligned_data, dbdata.size, XDR_DECODE);
+ if(!xdr_osa_policy_ent_rec(&xdrs, entry)) {
+ xdr_destroy(&xdrs);
+ free(aligned_data);
+ ret = OSA_ADB_FAILURE;
+ goto error;
+ }
+ (*func)(data, entry);
+ xdr_destroy(&xdrs);
+ free(aligned_data);
+ osa_free_policy_ent(entry);
+ ret = db->db->seq(db->db, &dbkey, &dbdata, R_NEXT);
+ }
+ if(ret == -1)
+ ret = errno;
+ else ret = OSA_ADB_OK;
+
+error:
+ CLOSELOCK(db);
+ return ret;
+}
+
+void
+osa_free_policy_ent(osa_policy_ent_t val)
+{
+ XDR xdrs;
+
+ xdrmem_create(&xdrs, NULL, 0, XDR_FREE);
+
+ xdr_osa_policy_ent_rec(&xdrs, val);
+
+ free(val);
+}
diff --git a/src/lib/kdb/kdb_db2/configure.in b/src/lib/kdb/kdb_db2/configure.in
new file mode 100644
index 0000000..dc002d8
--- /dev/null
+++ b/src/lib/kdb/kdb_db2/configure.in
@@ -0,0 +1,22 @@
+AC_INIT(configure.in)
+CONFIG_RULES
+AC_CHECK_HEADERS(unistd.h)
+AC_TYPE_MODE_T
+AC_TYPE_OFF_T
+
+AC_CHECK_FUNCS(srand48 srand srandom umask)
+
+dnl AIX is unusual in that it wants all symbols resolved at link time
+dnl Fortunately, it will allow us to link the kdb library now, even if
+dnl it is linked again later.
+case $krb5_cv_host in
+*-*-aix*)
+ LIBS="$LIBS -ldb"
+ ;;
+esac
+KRB5_RUN_FLAGS
+dnl The following is for check...
+KRB5_BUILD_PROGRAM
+KRB5_BUILD_LIBOBJS
+KRB5_BUILD_LIBRARY_WITH_DEPS
+V5_AC_OUTPUT_MAKEFILE
diff --git a/src/lib/kdb/kdb_db2/db2_exp.c b/src/lib/kdb/kdb_db2/db2_exp.c
new file mode 100644
index 0000000..f511487
--- /dev/null
+++ b/src/lib/kdb/kdb_db2/db2_exp.c
@@ -0,0 +1,64 @@
+/**********************************************************************
+*
+* C %name: db2_exp.c %
+* Instance: idc_sec_2
+* Description:
+* %created_by: spradeep %
+* %date_created: Tue Apr 5 11:44:00 2005 %
+*
+**********************************************************************/
+#ifndef lint
+static char *_csrc = "@(#) %filespec: db2_exp.c~5 % (%full_filespec: db2_exp.c~5:csrc:idc_sec#2 %)";
+#endif
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "k5-int.h"
+#include <db.h>
+#include <stdio.h>
+#include <errno.h>
+#include <utime.h>
+#include "../kdb5.h"
+#include "kdb_db2.h"
+#include "kdb_xdr.h"
+#include "policy_db.h"
+
+/*
+ * Exposed API
+ */
+
+kdb_vftabl krb5_db_vftabl_kdb_db2 = {
+ 1, /* major version number 1 */
+ 0, /* minor version number 0 */
+ 0, /* TBD. Not sure whether thread safe. For now, its not */
+ /* init_library */ krb5_db2_lib_init,
+ /* fini_library */ krb5_db2_lib_cleanup,
+ /* init_module */ krb5_db2_open,
+ /* fini_module */ krb5_db2_db_fini,
+ /* db_create */ krb5_db2_create,
+ /* db_destroy */ krb5_db2_destroy,
+ /* db_get_age */ krb5_db2_db_get_age,
+ /* db_set_option */ krb5_db2_db_set_option,
+ /* db_lock */ krb5_db2_db_lock,
+ /* db_unlock */ krb5_db2_db_unlock,
+ /* db_get_principal */ krb5_db2_db_get_principal,
+ /* db_free_principal */ krb5_db2_db_free_principal,
+ /* db_put_principal */ krb5_db2_db_put_principal,
+ /* db_delete_principal */ krb5_db2_db_delete_principal,
+ /* db_iterate */ krb5_db2_db_iterate,
+ /* db_create_policy */ krb5_db2_create_policy,
+ /* db_get_policy */ krb5_db2_get_policy,
+ /* db_put_policy */ krb5_db2_put_policy,
+ /* db_iter_policy */ krb5_db2_iter_policy,
+ /* db_delete_policy */ krb5_db2_delete_policy,
+ /* db_free_policy */ krb5_db2_free_policy,
+ /* db_supported_realms */ NULL,
+ /* db_free_supported_realms */ NULL,
+ /* errcode_2_string */ NULL,
+ /* db_alloc */ krb5_db2_alloc,
+ /* db_free */ krb5_db2_free,
+ /* set_master_key */ krb5_db2_set_master_key_ext,
+ /* get_master_key */ krb5_db2_db_get_mkey
+};
diff --git a/src/lib/kdb/kdb_compat.h b/src/lib/kdb/kdb_db2/kdb_compat.h
index 540d4a2..540d4a2 100644
--- a/src/lib/kdb/kdb_compat.h
+++ b/src/lib/kdb/kdb_db2/kdb_compat.h
diff --git a/src/lib/kdb/kdb_db2.c b/src/lib/kdb/kdb_db2/kdb_db2.c
index bcd08a2..2ac462e 100644
--- a/src/lib/kdb/kdb_db2.c
+++ b/src/lib/kdb/kdb_db2/kdb_db2.c
@@ -60,6 +60,12 @@
#include <stdio.h>
#include <errno.h>
#include <utime.h>
+#include "../kdb5.h"
+#include "kdb_db2.h"
+#include "kdb_xdr.h"
+#include "policy_db.h"
+
+#define KDB_DB2_DATABASE_NAME "database_name"
#define OLD_COMPAT_VERSION_1
@@ -71,14 +77,23 @@
static char *gen_dbsuffix
(char *, char * );
-static krb5_error_code krb5_db2_db_start_update
+
+static krb5_error_code krb5_db2_db_start_update
(krb5_context);
-static krb5_error_code krb5_db2_db_end_update
+static krb5_error_code krb5_db2_db_end_update
(krb5_context);
+
+krb5_error_code
+krb5_db2_db_set_name(krb5_context,char*);
+
+krb5_error_code krb5_db2_db_lock
+( krb5_context, int );
+
static krb5_error_code krb5_db2_db_set_hashfirst
(krb5_context, int);
static char default_db_name[] = DEFAULT_KDB_FILE;
+krb5_set_err_func_t krb5_db2_dal_err_funcp = NULL;
/*
* Locking:
@@ -129,8 +144,39 @@ static char default_db_name[] = DEFAULT_KDB_FILE;
/*
* Routines to deal with context.
*/
-#define k5db2_inited(c) (c && c->db_context && \
- ((krb5_db2_context *) c->db_context)->db_inited)
+#define k5db2_inited(c) (c && c->db_context \
+ && ((kdb5_dal_handle*)c->db_context)->db_context \
+ && ((krb5_db2_context *) ((kdb5_dal_handle*)c->db_context)->db_context)->db_inited)
+
+
+static
+krb5_error_code
+krb5_db2_get_db_opt( char *input, char **opt, char **val )
+{
+ char *pos = strchr(input, '=');
+ if( pos == NULL )
+ {
+ *opt = NULL;
+ *val = strdup(input);
+ if( *val == NULL )
+ {
+ return ENOMEM;
+ }
+ }
+ else
+ {
+ *opt = malloc( (pos - input) + 1 );
+ *val = strdup( pos + 1 );
+ if( !*opt || !*val )
+ {
+ return ENOMEM;
+ }
+ memcpy( *opt, input, pos - input);
+ (*opt)[pos - input] = '\0';
+ }
+ return (0);
+
+}
/*
* Restore the default context.
@@ -155,25 +201,30 @@ k5db2_clear_context(dbctx)
dbctx->db_nb_locks = FALSE;
}
+
static krb5_error_code
k5db2_init_context(context)
krb5_context context;
{
krb5_db2_context *db_ctx;
+ kdb5_dal_handle *dal_handle;
+
+ dal_handle = (kdb5_dal_handle*) context->db_context;
- if (context->db_context == NULL) {
+ if ( dal_handle->db_context == NULL) {
db_ctx = (krb5_db2_context *) malloc(sizeof(krb5_db2_context));
if (db_ctx == NULL)
return ENOMEM;
else {
memset((char *) db_ctx, 0, sizeof(krb5_db2_context));
k5db2_clear_context((krb5_db2_context *)db_ctx);
- context->db_context = (void *) db_ctx;
+ dal_handle->db_context = (void *) db_ctx;
}
}
return(0);
}
+
/*
* Utility routine: generate name of database file.
*/
@@ -196,6 +247,7 @@ gen_dbsuffix(db_name, sfx)
return dbsuffix;
}
+
static DB *
k5db2_dbopen(dbc, fname, flags, mode)
krb5_db2_context *dbc;
@@ -248,10 +300,12 @@ krb5_db2_db_set_hashfirst(context, hashfirst)
int hashfirst;
{
krb5_db2_context *dbc;
+ kdb5_dal_handle *dal_handle;
if (k5db2_inited(context))
return KRB5_KDB_DBNOTINITED;
- dbc = (krb5_db2_context *) context->db_context;
+ dal_handle = (kdb5_dal_handle*) context->db_context;
+ dbc = (krb5_db2_context *) dal_handle->db_context;
dbc->hashfirst = hashfirst;
return 0;
}
@@ -267,6 +321,8 @@ krb5_db2_db_init(context)
char *filename = NULL;
krb5_db2_context *db_ctx;
krb5_error_code retval;
+ kdb5_dal_handle *dal_handle;
+ char policy_db_name[1024], policy_lock_name[1024];
if (k5db2_inited(context))
return 0;
@@ -275,7 +331,8 @@ krb5_db2_db_init(context)
if ((retval = k5db2_init_context(context)))
return(retval);
- db_ctx = context->db_context;
+ dal_handle = (kdb5_dal_handle*) context->db_context;
+ db_ctx = dal_handle->db_context;
db_ctx->db = NULL;
if (!(filename = gen_dbsuffix(db_ctx->db_name, KDB2_LOCK_EXT)))
@@ -297,6 +354,14 @@ krb5_db2_db_init(context)
if ((retval = krb5_db2_db_get_age(context, NULL, &db_ctx->db_lf_time)))
goto err_out;
+ sprintf( policy_db_name, "%s.kadm5", db_ctx->db_name );
+ sprintf( policy_lock_name, "%s.lock", policy_db_name );
+
+ if( (retval = osa_adb_init_db(&db_ctx->policy_db, policy_db_name,
+ policy_lock_name, OSA_ADB_POLICY_DB_MAGIC)) )
+ {
+ goto err_out;
+ }
return 0;
err_out:
@@ -305,6 +370,7 @@ err_out:
return (retval);
}
+
/*
* gracefully shut down database--must be called by ANY program that does
* a krb5_db2_db_init
@@ -315,8 +381,15 @@ krb5_db2_db_fini(context)
{
krb5_error_code retval = 0;
krb5_db2_context *db_ctx;
+ kdb5_dal_handle *dal_handle;
- db_ctx = (krb5_db2_context *) context->db_context;
+ dal_handle = (kdb5_dal_handle*) context->db_context;
+ if( dal_handle == NULL )
+ {
+ return 0;
+ }
+
+ db_ctx = (krb5_db2_context *) dal_handle->db_context;
if (k5db2_inited(context)) {
if (close(db_ctx->db_lf_file))
@@ -325,13 +398,22 @@ krb5_db2_db_fini(context)
retval = 0;
}
if (db_ctx) {
+ if( db_ctx->policy_db )
+ {
+ retval = osa_adb_fini_db(db_ctx->policy_db, OSA_ADB_POLICY_DB_MAGIC);
+ if( retval )
+ return retval;
+ }
+
k5db2_clear_context(db_ctx);
- free(context->db_context);
- context->db_context = NULL;
+ /* free(dal_handle->db_context); */
+ dal_handle->db_context = NULL;
}
return retval;
}
+#if 0 // pradx
+
krb5_error_code
krb5_db2_db_open_database(context)
krb5_context context;
@@ -350,6 +432,8 @@ krb5_db2_db_close_database(context)
return 0;
}
+#endif // 0 -pradx
+
/*
* Set/Get the master key associated with the database
*/
@@ -359,11 +443,13 @@ krb5_db2_db_set_mkey(context, key)
krb5_keyblock *key;
{
krb5_db2_context *db_ctx;
+ kdb5_dal_handle *dal_handle;
if (!k5db2_inited(context))
return(KRB5_KDB_DBNOTINITED);
- db_ctx = context->db_context;
+ dal_handle = (kdb5_dal_handle*) context->db_context;
+ db_ctx = dal_handle->db_context;
db_ctx->db_master_key = key;
return 0;
}
@@ -374,11 +460,13 @@ krb5_db2_db_get_mkey(context, key)
krb5_keyblock **key;
{
krb5_db2_context *db_ctx;
+ kdb5_dal_handle *dal_handle;
if (!k5db2_inited(context))
return(KRB5_KDB_DBNOTINITED);
- db_ctx = context->db_context;
+ dal_handle = (kdb5_dal_handle*)context->db_context;
+ db_ctx = dal_handle->db_context;
*key = db_ctx->db_master_key;
return 0;
@@ -401,6 +489,7 @@ krb5_db2_db_set_name(context, name)
DB *db;
krb5_db2_context *db_ctx;
krb5_error_code kret;
+ kdb5_dal_handle *dal_handle;
if (k5db2_inited(context))
return KRB5_KDB_DBINITED;
@@ -412,7 +501,8 @@ krb5_db2_db_set_name(context, name)
if (name == NULL)
name = default_db_name;
- db_ctx = context->db_context;
+ dal_handle = (kdb5_dal_handle*)context->db_context;
+ db_ctx = dal_handle->db_context;
db = k5db2_dbopen(db_ctx, name, O_RDONLY, 0);
if (db == NULL)
return errno;
@@ -435,11 +525,14 @@ krb5_db2_db_get_age(context, db_name, age)
time_t *age;
{
krb5_db2_context *db_ctx;
+ kdb5_dal_handle *dal_handle;
struct stat st;
if (!k5db2_inited(context))
return(KRB5_KDB_DBNOTINITED);
- db_ctx = (krb5_db2_context *) context->db_context;
+ dal_handle = (kdb5_dal_handle *) context->db_context;
+ db_ctx = (krb5_db2_context *) dal_handle->db_context;
+
if (fstat (db_ctx->db_lf_file, &st) < 0)
*age = -1;
else
@@ -468,6 +561,7 @@ krb5_db2_db_end_update(context)
{
krb5_error_code retval;
krb5_db2_context *db_ctx;
+ kdb5_dal_handle *dal_handle;
struct stat st;
time_t now;
struct utimbuf utbuf;
@@ -476,7 +570,8 @@ krb5_db2_db_end_update(context)
return(KRB5_KDB_DBNOTINITED);
retval = 0;
- db_ctx = context->db_context;
+ dal_handle = (kdb5_dal_handle*) context->db_context;
+ db_ctx = dal_handle->db_context;
now = time((time_t *) NULL);
if (fstat(db_ctx->db_lf_file, &st) == 0) {
if (st.st_mtime >= now) {
@@ -502,24 +597,43 @@ krb5_db2_db_end_update(context)
}
krb5_error_code
-krb5_db2_db_lock(context, mode)
+krb5_db2_db_lock(context, in_mode)
krb5_context context;
- int mode;
+ int in_mode;
{
krb5_db2_context *db_ctx;
int krb5_lock_mode;
DB *db;
krb5_error_code retval;
time_t mod_time;
+ kdb5_dal_handle *dal_handle;
+ int mode = in_mode & ~KRB5_DB_LOCKMODE_PERMANENT; /* permanent is not available for principal db */
+
+ switch( in_mode )
+ {
+ case KRB5_DB_LOCKMODE_PERMANENT:
+ mode = KRB5_DB_LOCKMODE_EXCLUSIVE;
+ break;
+ case KRB5_DB_LOCKMODE_EXCLUSIVE:
+ mode = KRB5_LOCKMODE_EXCLUSIVE;
+ break;
+
+ case KRB5_DB_LOCKMODE_SHARED:
+ mode = KRB5_LOCKMODE_SHARED;
+ break;
+ default:
+ return EINVAL;
+ }
if (!k5db2_inited(context))
return KRB5_KDB_DBNOTINITED;
- db_ctx = (krb5_db2_context *) context->db_context;
+ dal_handle = (kdb5_dal_handle*) context->db_context;
+ db_ctx = (krb5_db2_context *) dal_handle->db_context;
if (db_ctx->db_locks_held && (db_ctx->db_lock_mode >= mode)) {
/* No need to upgrade lock, just return */
db_ctx->db_locks_held++;
- return(0);
+ goto policy_lock;
}
if ((mode != KRB5_LOCKMODE_SHARED) && (mode != KRB5_LOCKMODE_EXCLUSIVE))
@@ -557,27 +671,42 @@ krb5_db2_db_lock(context, mode)
db_ctx->db_lock_mode = mode;
db_ctx->db_locks_held++;
- return 0;
+
+ policy_lock:
+ if((retval=osa_adb_get_lock(db_ctx->policy_db, in_mode)))
+ {
+ krb5_db2_db_unlock(context);
+ }
+ return retval;
lock_error:;
db_ctx->db_lock_mode = 0;
db_ctx->db_locks_held = 0;
- (void) krb5_db2_db_unlock(context);
+ krb5_db2_db_unlock(context);
return retval;
}
+
krb5_error_code
krb5_db2_db_unlock(context)
krb5_context context;
{
krb5_db2_context *db_ctx;
+ kdb5_dal_handle *dal_handle;
DB *db;
krb5_error_code retval;
if (!k5db2_inited(context))
return KRB5_KDB_DBNOTINITED;
- db_ctx = (krb5_db2_context *) context->db_context;
+ dal_handle = (kdb5_dal_handle*) context->db_context;
+ db_ctx = (krb5_db2_context *) dal_handle->db_context;
+
+ if( (retval = osa_adb_release_lock(db_ctx->policy_db)) )
+ {
+ return retval;
+ }
+
if (!db_ctx->db_locks_held) /* lock already unlocked */
return KRB5_KDB_NOTLOCKED;
db = db_ctx->db;
@@ -603,15 +732,18 @@ krb5_db2_db_create(context, db_name, flags)
krb5_int32 flags;
{
register krb5_error_code retval = 0;
+ kdb5_dal_handle *dal_handle;
char *okname;
int fd;
krb5_db2_context *db_ctx;
DB *db;
+ char policy_db_name[1024], policy_lock_name[1024];
if ((retval = k5db2_init_context(context)))
return(retval);
- db_ctx = (krb5_db2_context *) context->db_context;
+ dal_handle = (kdb5_dal_handle*) context->db_context;
+ db_ctx = (krb5_db2_context *) dal_handle->db_context;
switch (flags) {
case KRB5_KDB_CREATE_HASH:
if ((retval = krb5_db2_db_set_hashfirst(context, TRUE)))
@@ -643,6 +775,14 @@ krb5_db2_db_create(context, db_name, flags)
free_dbsuffix(okname);
}
}
+
+ sprintf( policy_db_name, "%s.kadm5", db_name );
+ sprintf( policy_lock_name, "%s.lock", policy_db_name );
+
+ retval = osa_adb_create_db( policy_db_name,
+ policy_lock_name, OSA_ADB_POLICY_DB_MAGIC);
+
+
return retval;
}
@@ -748,9 +888,10 @@ krb5_db2_db_destroy(context, dbname)
{
krb5_error_code retval1, retval2;
krb5_boolean tmpcontext;
+ char policy_db_name[1024], policy_lock_name[1024];
tmpcontext = 0;
- if (!context->db_context) {
+ if ( !context->db_context || !((kdb5_dal_handle*)context->db_context)->db_context ) {
tmpcontext = 1;
if ((retval1 = k5db2_init_context(context)))
return(retval1);
@@ -761,17 +902,25 @@ krb5_db2_db_destroy(context, dbname)
retval2 = destroy_file_suffix(dbname, KDB2_LOCK_EXT);
if (tmpcontext) {
- k5db2_clear_context((krb5_db2_context *) context->db_context);
- free(context->db_context);
- context->db_context = NULL;
+ k5db2_clear_context((krb5_db2_context *) ((kdb5_dal_handle*)context->db_context)->db_context );
+ free(((kdb5_dal_handle*)context->db_context)->db_context);
+ ((kdb5_dal_handle*)context->db_context)->db_context = NULL;
}
if (retval1 || retval2)
return (retval1 ? retval1 : retval2);
- else
- return 0;
+
+ sprintf( policy_db_name, "%s.kadm5", dbname );
+ sprintf( policy_lock_name, "%s.lock", policy_db_name );
+
+ retval1 = osa_adb_destroy_db( policy_db_name,
+ policy_lock_name, OSA_ADB_POLICY_DB_MAGIC);
+
+ return retval1;
}
+#if 0 // -pradx
+
/*
* "Atomically" rename the database in a way that locks out read
* access in the middle of the rename.
@@ -791,13 +940,15 @@ krb5_db2_db_rename(context, from, to)
DB *db;
char *fromok;
krb5_error_code retval;
+ kdb5_dal_handle *dal_handle;
krb5_db2_context *s_context, *db_ctx;
- s_context = context->db_context;
- context->db_context = NULL;
+ dal_handle = (kdb5_dal_handle*) context->db_context;
+ s_context = dal_handle->db_context;
+ dal_handle->db_context = NULL;
if ((retval = k5db2_init_context(context)))
return retval;
- db_ctx = (krb5_db2_context *) context->db_context;
+ db_ctx = (krb5_db2_context *) ((kdb5_dal_handle*)context->db_context)->db_context;
/*
* Create the database if it does not already exist; the
@@ -860,21 +1011,23 @@ krb5_db2_db_rename(context, from, to)
errfromok:
free_dbsuffix(fromok);
errout:
- if (context->db_context) {
+ if ( ((kdb5_dal_handle*)context->db_context)->db_context ) {
if (db_ctx->db_lf_file >= 0) {
krb5_db2_db_unlock(context);
close(db_ctx->db_lf_file);
}
- k5db2_clear_context((krb5_db2_context *) context->db_context);
- free(context->db_context);
+ k5db2_clear_context((krb5_db2_context *) ((kdb5_dal_handle*)context->db_context)->db_context);
+ free(((kdb5_dal_handle*)context->db_context)->db_context);
}
- context->db_context = s_context;
+ ((kdb5_dal_handle*)context->db_context)->db_context = s_context;
(void) krb5_db2_db_unlock(context); /* unlock saved context db */
return retval;
}
+#endif // 0 - pradx
+
/*
* look up a principal in the data base.
* returns number of entries found, and whether there were
@@ -894,7 +1047,8 @@ krb5_db2_db_get_principal(context, searchfor, entries, nentries, more)
DB *db;
DBT key, contents;
krb5_data keydata, contdata;
- int trynum, dbret;
+ int try, dbret;
+ kdb5_dal_handle *dal_handle;
*more = FALSE;
*nentries = 0;
@@ -902,8 +1056,10 @@ krb5_db2_db_get_principal(context, searchfor, entries, nentries, more)
if (!k5db2_inited(context))
return KRB5_KDB_DBNOTINITED;
- db_ctx = (krb5_db2_context *) context->db_context;
- for (trynum = 0; trynum < KRB5_DB2_MAX_RETRY; trynum++) {
+ dal_handle = (kdb5_dal_handle*) context->db_context;
+ db_ctx = (krb5_db2_context *) dal_handle->db_context;
+
+ for (try = 0; try < KRB5_DB2_MAX_RETRY; try++) {
if ((retval = krb5_db2_db_lock(context, KRB5_LOCKMODE_SHARED))) {
if (db_ctx->db_nb_locks)
return(retval);
@@ -912,7 +1068,7 @@ krb5_db2_db_get_principal(context, searchfor, entries, nentries, more)
}
break;
}
- if (trynum == KRB5_DB2_MAX_RETRY)
+ if (try == KRB5_DB2_MAX_RETRY)
return KRB5_KDB_DB_INUSE;
/* XXX deal with wildcard lookups */
@@ -950,7 +1106,7 @@ cleanup:
/*
Free stuff returned by krb5_db2_db_get_principal.
*/
-void
+krb5_error_code
krb5_db2_db_free_principal(context, entries, nentries)
krb5_context context;
krb5_db_entry *entries;
@@ -959,7 +1115,7 @@ krb5_db2_db_free_principal(context, entries, nentries)
register int i;
for (i = 0; i < nentries; i++)
krb5_dbe_free_contents(context, &entries[i]);
- return;
+ return 0;
}
/*
@@ -973,10 +1129,11 @@ krb5_db2_db_free_principal(context, entries, nentries)
*/
krb5_error_code
-krb5_db2_db_put_principal(context, entries, nentries)
+krb5_db2_db_put_principal(context, entries, nentries, db_args)
krb5_context context;
krb5_db_entry *entries;
register int *nentries; /* number of entry structs to update */
+ char **db_args;
{
int i, n, dbret;
DB *db;
@@ -984,13 +1141,24 @@ krb5_db2_db_put_principal(context, entries, nentries)
krb5_data contdata, keydata;
krb5_error_code retval;
krb5_db2_context *db_ctx;
+ kdb5_dal_handle *dal_handle;
+
+ if( db_args )
+ {
+ /* DB2 does not support db_args DB arguments for principal */
+ char buf[KRB5_MAX_ERR_STR];
+ sprintf(buf, "Unsupported argument \"%s\" for db2", db_args[0]);
+ krb5_db2_dal_err_funcp( context, krb5_err_have_str, EINVAL, buf);
+ return EINVAL;
+ }
n = *nentries;
*nentries = 0;
if (!k5db2_inited(context))
return KRB5_KDB_DBNOTINITED;
- db_ctx = (krb5_db2_context *) context->db_context;
+ dal_handle = (kdb5_dal_handle*) context->db_context;
+ db_ctx = (krb5_db2_context *) dal_handle->db_context;
if ((retval = krb5_db2_db_lock(context, KRB5_LOCKMODE_EXCLUSIVE)))
return retval;
@@ -1048,11 +1216,13 @@ krb5_db2_db_delete_principal(context, searchfor, nentries)
DBT key, contents;
krb5_data keydata, contdata;
int i, dbret;
+ kdb5_dal_handle *dal_handle;
if (!k5db2_inited(context))
return KRB5_KDB_DBNOTINITED;
- db_ctx = (krb5_db2_context *) context->db_context;
+ dal_handle = (kdb5_dal_handle*) context->db_context;
+ db_ctx = (krb5_db2_context *) dal_handle->db_context;
if ((retval = krb5_db2_db_lock(context, KRB5_LOCKMODE_EXCLUSIVE)))
return(retval);
@@ -1131,6 +1301,7 @@ krb5_db2_db_iterate_ext(context, func, func_arg, backwards, recursive)
krb5_data contdata;
krb5_db_entry entries;
krb5_error_code retval;
+ kdb5_dal_handle *dal_handle;
int dbret;
void *cookie;
@@ -1138,7 +1309,8 @@ krb5_db2_db_iterate_ext(context, func, func_arg, backwards, recursive)
if (!k5db2_inited(context))
return KRB5_KDB_DBNOTINITED;
- db_ctx = (krb5_db2_context *) context->db_context;
+ dal_handle = (kdb5_dal_handle*) context->db_context;
+ db_ctx = (krb5_db2_context *) dal_handle->db_context;
retval = krb5_db2_db_lock(context, KRB5_LOCKMODE_SHARED);
if (retval)
@@ -1198,14 +1370,15 @@ krb5_db2_db_iterate_ext(context, func, func_arg, backwards, recursive)
}
krb5_error_code
-krb5_db2_db_iterate(context, func, func_arg)
- krb5_context context;
- krb5_error_code (*func) (krb5_pointer, krb5_db_entry *);
- krb5_pointer func_arg;
+krb5_db2_db_iterate( krb5_context context,
+ char *match_expr,
+ krb5_error_code (*func) (krb5_pointer, krb5_db_entry *),
+ krb5_pointer func_arg )
{
return krb5_db2_db_iterate_ext(context, func, func_arg, 0, 0);
}
+
krb5_boolean
krb5_db2_db_set_lockmode(context, mode)
krb5_context context;
@@ -1213,15 +1386,18 @@ krb5_db2_db_set_lockmode(context, mode)
{
krb5_boolean old;
krb5_db2_context *db_ctx;
+ kdb5_dal_handle *dal_handle;
+ dal_handle = (kdb5_dal_handle*) context->db_context;
old = mode;
- if ((db_ctx = (krb5_db2_context *) context->db_context)) {
+ if ( dal_handle && (db_ctx = (krb5_db2_context *) dal_handle->db_context)) {
old = db_ctx->db_nb_locks;
db_ctx->db_nb_locks = mode;
}
return old;
}
+#if 0 // -pradx
/*
* Context serialization operations.
*
@@ -1384,7 +1560,7 @@ kdb5_context_internalize(kcontext, argp, buffer, lenremain)
dbctx = (krb5_db2_context *) tmpctx->db_context;
(void) krb5_db2_db_set_lockmode(tmpctx, 0);
if (lockmode)
- kret = krb5_db_lock(tmpctx, lockmode);
+ kret = krb5_db2_db_lock(tmpctx, lockmode);
if (!kret && lockmode)
dbctx->db_locks_held = lockcount;
nb_lock = nb_lockmode & 0xff;
@@ -1432,3 +1608,393 @@ krb5_ser_db_context_init(kcontext)
{
return(krb5_register_serializer(kcontext, &kdb5_context_ser_entry));
}
+
+#endif // 0 - pradx
+
+/*
+ * DAL API functions
+ */
+krb5_error_code krb5_db2_lib_init(krb5_set_err_func_t set_err)
+{
+ krb5_db2_dal_err_funcp = set_err;
+ return 0;
+}
+
+krb5_error_code krb5_db2_lib_cleanup()
+{
+ /* right now, no cleanup required */
+ return 0;
+}
+
+krb5_error_code krb5_db2_open( krb5_context kcontext,
+ char *conf_section,
+ char **db_args,
+ int mode )
+{
+ krb5_error_code status = 0;
+ char **t_ptr = db_args;
+ char db_name_set = 0;
+
+ if (k5db2_inited(kcontext))
+ return 0;
+
+
+ while ( t_ptr && *t_ptr )
+ {
+ char *opt = NULL, *val = NULL;
+
+ krb5_db2_get_db_opt( *t_ptr, &opt, &val );
+ if( opt && !strcmp( opt, "dbname" ) )
+ {
+ status = krb5_db2_db_set_name( kcontext, val );
+ if( status )
+ {
+ free(opt);
+ free(val);
+ goto clean_n_exit;
+ }
+ db_name_set = 1;
+ }
+ /* ignore hash argument. Might have been passed from create */
+ else if( !opt || strcmp( opt, "hash") )
+ {
+ char buf[KRB5_MAX_ERR_STR];
+ sprintf(buf, "Unsupported argument \"%s\" for db2", opt?opt:val);
+ krb5_db2_dal_err_funcp( kcontext, krb5_err_have_str, EINVAL, buf);
+ free(opt);
+ free(val);
+ return EINVAL;
+ }
+
+ free(opt);
+ free(val);
+ t_ptr++;
+ }
+
+ if( !db_name_set )
+ {
+ char *value = NULL;
+ status = profile_get_string( KRB5_DB_GET_PROFILE(kcontext), KDB_MODULE_SECTION,
+ conf_section, KDB_DB2_DATABASE_NAME, /* under given conf section */
+ NULL, &value );
+
+
+ if( value == NULL )
+ {
+ /* special case for db2. We might actually be looking at old type config file where database is specified as part of realm */
+ status = profile_get_string( KRB5_DB_GET_PROFILE(kcontext), KDB_REALM_SECTION,
+ KRB5_DB_GET_REALM(kcontext), KDB_DB2_DATABASE_NAME, /* under given realm */
+ default_db_name, &value );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ status = krb5_db2_db_set_name( kcontext, value );
+ profile_release_string( value );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ }
+
+ status = krb5_db2_db_init( kcontext );
+
+ clean_n_exit:
+ return status;
+}
+
+
+krb5_error_code krb5_db2_create( krb5_context kcontext,
+ char *conf_section,
+ char **db_args )
+{
+ krb5_error_code status = 0;
+ char **t_ptr = db_args;
+ char db_name_set = 0;
+ krb5_int32 flags = KRB5_KDB_CREATE_BTREE;
+ char *db_name = NULL;
+
+ if (k5db2_inited(kcontext))
+ return 0;
+
+
+ while ( t_ptr && *t_ptr )
+ {
+ char *opt = NULL, *val = NULL;
+
+ krb5_db2_get_db_opt( *t_ptr, &opt, &val );
+ if( opt && !strcmp( opt, "dbname" ) )
+ {
+ db_name = strdup(val);
+ status = krb5_db2_db_set_name( kcontext, val );
+ if( !status )
+ {
+ status = EEXIST;
+ free(opt);
+ free(val);
+ goto clean_n_exit;
+ }
+ db_name_set = 1;
+ }
+ /* ignore hash argument. Might have been passed from create */
+ else if( opt && !strcmp( opt, "hash") )
+ {
+ flags=KRB5_KDB_CREATE_HASH;
+ }
+ else
+ {
+ char buf[KRB5_MAX_ERR_STR];
+ sprintf(buf, "Unsupported argument \"%s\" for db2", opt?opt:val);
+ krb5_db2_dal_err_funcp( kcontext, krb5_err_have_str, EINVAL, buf);
+ free(opt);
+ free(val);
+ return EINVAL;
+ }
+
+ free(opt);
+ free(val);
+ t_ptr++;
+ }
+
+ if( !db_name_set )
+ {
+ char *value = NULL;
+ status = profile_get_string( KRB5_DB_GET_PROFILE(kcontext), KDB_MODULE_SECTION,
+ conf_section, KDB_DB2_DATABASE_NAME, /* under given conf section */
+ NULL, &value );
+
+
+ if( value == NULL )
+ {
+ /* special case for db2. We might actually be looking at old type config file where database is specified as part of realm */
+ status = profile_get_string( KRB5_DB_GET_PROFILE(kcontext), KDB_REALM_SECTION,
+ KRB5_DB_GET_REALM(kcontext), KDB_DB2_DATABASE_NAME, /* under given realm */
+ default_db_name, &value );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ db_name = strdup( value );
+ status = krb5_db2_db_set_name( kcontext, value );
+ profile_release_string( value );
+ if( !status )
+ {
+ status = EEXIST;
+ goto clean_n_exit;
+ }
+
+ }
+
+ status = krb5_db2_db_create( kcontext, db_name, flags );
+ if( status )
+ goto clean_n_exit;
+ /* db2 has a problem of needing to close and open the database again. This removes that need */
+ status = krb5_db2_db_fini(kcontext);
+ if( status )
+ goto clean_n_exit;
+
+ status = krb5_db2_open( kcontext, conf_section, db_args, KRB5_KDB_OPEN_RW );
+
+ clean_n_exit:
+ if( db_name )
+ free( db_name );
+ return status;
+}
+
+krb5_error_code krb5_db2_destroy( krb5_context kcontext,
+ char *conf_section,
+ char **db_args )
+{
+ krb5_error_code status = 0;
+ char **t_ptr = db_args;
+ char db_name_set = 0;
+ char *db_name = NULL;
+
+ while ( t_ptr && *t_ptr )
+ {
+ char *opt = NULL, *val = NULL;
+
+ krb5_db2_get_db_opt( *t_ptr, &opt, &val );
+ if( opt && !strcmp( opt, "dbname" ) )
+ {
+ db_name = strdup(val);
+ status = krb5_db2_db_set_name( kcontext, val );
+ if( status )
+ {
+ free(opt);
+ free(val);
+ goto clean_n_exit;
+ }
+ db_name_set = 1;
+ }
+ /* ignore hash argument. Might have been passed from create */
+ else if( !opt || strcmp( opt, "hash") )
+ {
+ free(opt);
+ free(val);
+ return EINVAL;
+ }
+
+ free(opt);
+ free(val);
+ t_ptr++;
+ }
+
+ if( !db_name_set )
+ {
+ char *value = NULL;
+ status = profile_get_string( KRB5_DB_GET_PROFILE(kcontext), KDB_MODULE_SECTION,
+ conf_section, KDB_DB2_DATABASE_NAME, /* under given conf section */
+ NULL, &value );
+
+
+ if( value == NULL )
+ {
+ /* special case for db2. We might actually be looking at old type config file where database is specified as part of realm */
+ status = profile_get_string( KRB5_DB_GET_PROFILE(kcontext), KDB_REALM_SECTION,
+ KRB5_DB_GET_REALM(kcontext), KDB_DB2_DATABASE_NAME, /* under given realm */
+ default_db_name, &value );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+ }
+
+ db_name = strdup(value);
+ status = krb5_db2_db_set_name( kcontext, value );
+ profile_release_string( value );
+ if( status )
+ {
+ goto clean_n_exit;
+ }
+
+ }
+
+ status = krb5_db2_db_destroy( kcontext, db_name );
+
+ clean_n_exit:
+ if( db_name )
+ free(db_name);
+ return status;
+}
+
+krb5_error_code krb5_db2_set_master_key_ext ( krb5_context kcontext,
+ char *pwd,
+ krb5_keyblock *key)
+{
+ return krb5_db2_db_set_mkey( kcontext, key );
+}
+
+krb5_error_code krb5_db2_db_set_option ( krb5_context kcontext, int option, void *value )
+{
+ krb5_error_code status = 0;
+ krb5_boolean oldval;
+
+ switch(option)
+ {
+ case KRB5_KDB_OPT_SET_DB_NAME:
+ status = krb5_db2_db_set_name( kcontext, (char *)value);
+ break;
+
+ case KRB5_KDB_OPT_SET_LOCK_MODE:
+ oldval = krb5_db2_db_set_lockmode( kcontext, *((krb5_boolean*)value) );
+ *((krb5_boolean*)value) = oldval;
+ break;
+
+ default:
+ status = -1; /* TBD */
+ break;
+ }
+
+ return status;
+}
+
+void * krb5_db2_alloc( krb5_context kcontext, void *ptr, size_t size )
+{
+ return realloc(ptr, size);
+}
+
+void krb5_db2_free( krb5_context kcontext, void *ptr )
+{
+ free(ptr);
+}
+
+
+/* policy functions */
+krb5_error_code krb5_db2_create_policy( krb5_context kcontext,
+ osa_policy_ent_t policy )
+{
+ kdb5_dal_handle *dal_handle;
+ krb5_db2_context *dbc;
+
+ dal_handle = (kdb5_dal_handle*) kcontext->db_context;
+ dbc = (krb5_db2_context*) dal_handle->db_context;
+
+ return osa_adb_create_policy( dbc->policy_db, policy );
+}
+
+krb5_error_code krb5_db2_get_policy ( krb5_context kcontext,
+ char *name,
+ osa_policy_ent_t *policy,
+ int *cnt)
+{
+ kdb5_dal_handle *dal_handle;
+ krb5_db2_context *dbc;
+
+ dal_handle = (kdb5_dal_handle*) kcontext->db_context;
+ dbc = (krb5_db2_context*) dal_handle->db_context;
+
+ return osa_adb_get_policy( dbc->policy_db, name, policy, cnt );
+}
+
+krb5_error_code krb5_db2_put_policy ( krb5_context kcontext,
+ osa_policy_ent_t policy )
+{
+ kdb5_dal_handle *dal_handle;
+ krb5_db2_context *dbc;
+
+ dal_handle = (kdb5_dal_handle*) kcontext->db_context;
+ dbc = (krb5_db2_context*) dal_handle->db_context;
+
+ return osa_adb_put_policy( dbc->policy_db, policy );
+}
+
+krb5_error_code krb5_db2_iter_policy ( krb5_context kcontext,
+ char *match_entry,
+ osa_adb_iter_policy_func func,
+ void *data )
+{
+ kdb5_dal_handle *dal_handle;
+ krb5_db2_context *dbc;
+
+ dal_handle = (kdb5_dal_handle*) kcontext->db_context;
+ dbc = (krb5_db2_context*) dal_handle->db_context;
+
+ return osa_adb_iter_policy( dbc->policy_db, func, data );
+}
+
+
+krb5_error_code krb5_db2_delete_policy ( krb5_context kcontext,
+ char *policy )
+{
+ kdb5_dal_handle *dal_handle;
+ krb5_db2_context *dbc;
+
+ dal_handle = (kdb5_dal_handle*) kcontext->db_context;
+ dbc = (krb5_db2_context*) dal_handle->db_context;
+
+ return osa_adb_destroy_policy( dbc->policy_db, policy );
+}
+
+
+void krb5_db2_free_policy( krb5_context kcontext,
+ osa_policy_ent_t entry )
+{
+ osa_free_policy_ent(entry);
+}
+
diff --git a/src/lib/kdb/kdb_db2.h b/src/lib/kdb/kdb_db2/kdb_db2.h
index 80f9495..ba03ea3 100644
--- a/src/lib/kdb/kdb_db2.h
+++ b/src/lib/kdb/kdb_db2/kdb_db2.h
@@ -27,29 +27,9 @@
* KDC Database backend definitions for Berkely DB.
*/
#ifndef KRB5_KDB_DB2_H
+#define KRB5_KDB_DB2_H
-/* renaming kludge */
-#define krb5_db2_db_set_name krb5_db_set_name
-#define krb5_db2_db_set_nonblocking krb5_db_set_nonblocking
-#define krb5_db2_db_init krb5_db_init
-#define krb5_db2_db_fini krb5_db_fini
-#define krb5_db2_db_get_age krb5_db_get_age
-#define krb5_db2_db_create krb5_db_create
-#define krb5_db2_db_destroy krb5_db_destroy
-#define krb5_db2_db_rename krb5_db_rename
-#define krb5_db2_db_get_principal krb5_db_get_principal
-#define krb5_db2_db_free_principal krb5_db_free_principal
-#define krb5_db2_db_put_principal krb5_db_put_principal
-#define krb5_db2_db_delete_principal krb5_db_delete_principal
-#define krb5_db2_db_iterate_ext krb5_db_iterate_ext
-#define krb5_db2_db_iterate krb5_db_iterate
-#define krb5_db2_db_lock krb5_db_lock
-#define krb5_db2_db_unlock krb5_db_unlock
-#define krb5_db2_db_set_lockmode krb5_db_set_lockmode
-#define krb5_db2_db_close_database krb5_db_close_database
-#define krb5_db2_db_open_database krb5_db_open_database
-#define krb5_db2_db_set_mkey krb5_db_set_mkey
-#define krb5_db2_db_get_mkey krb5_db_get_mkey
+#include "policy_db.h"
typedef struct _krb5_db2_context {
krb5_boolean db_inited; /* Context initialized */
@@ -63,6 +43,7 @@ typedef struct _krb5_db2_context {
int db_lock_mode; /* Last lock mode, e.g. greatest*/
krb5_boolean db_nb_locks; /* [Non]Blocking lock modes */
krb5_keyblock *db_master_key; /* Master key of database */
+ osa_adb_policy_t policy_db;
} krb5_db2_context;
#define KRB5_DB2_MAX_RETRY 5
@@ -97,21 +78,23 @@ krb5_error_code krb5_db2_db_get_principal
krb5_db_entry *,
int *,
krb5_boolean * );
-void krb5_db2_db_free_principal
+krb5_error_code krb5_db2_db_free_principal
(krb5_context,
krb5_db_entry *,
int );
krb5_error_code krb5_db2_db_put_principal
(krb5_context,
- krb5_db_entry *,
- int * );
+ krb5_db_entry *,
+ int *,
+ char **db_args
+ );
krb5_error_code krb5_db2_db_iterate_ext
(krb5_context,
krb5_error_code (*) (krb5_pointer,
krb5_db_entry *),
krb5_pointer, int, int );
krb5_error_code krb5_db2_db_iterate
- (krb5_context,
+(krb5_context,char *,
krb5_error_code (*) (krb5_pointer,
krb5_db_entry *),
krb5_pointer );
@@ -127,4 +110,107 @@ krb5_error_code krb5_db2_db_open_database
krb5_error_code krb5_db2_db_close_database
(krb5_context);
+krb5_error_code
+krb5_db2_set_master_key_ext ( krb5_context kcontext,
+ char *pwd,
+ krb5_keyblock *key);
+
+krb5_error_code
+krb5_db2_db_set_mkey( krb5_context context,
+ krb5_keyblock *key);
+
+krb5_error_code
+krb5_db2_db_get_mkey( krb5_context context,
+ krb5_keyblock **key);
+
+krb5_error_code
+krb5_db2_db_put_principal( krb5_context context,
+ krb5_db_entry *entries,
+ register int *nentries,
+ char **db_args);
+
+krb5_error_code
+krb5_db2_db_delete_principal(krb5_context context,
+ krb5_const_principal searchfor,
+ int *nentries);
+
+krb5_error_code krb5_db2_lib_init(krb5_set_err_func_t);
+
+krb5_error_code krb5_db2_lib_cleanup(void);
+
+krb5_error_code
+krb5_db2_db_unlock(krb5_context);
+
+krb5_error_code
+krb5_db2_db_set_option ( krb5_context kcontext,
+ int option,
+ void *value );
+
+krb5_error_code
+krb5_db2_db_lock( krb5_context context,
+ int in_mode);
+
+
+krb5_error_code
+krb5_db2_open( krb5_context kcontext,
+ char *conf_section,
+ char **db_args,
+ int mode );
+
+krb5_error_code krb5_db2_create( krb5_context kcontext,
+ char *conf_section,
+ char **db_args );
+
+krb5_error_code krb5_db2_destroy( krb5_context kcontext,
+ char *conf_section,
+ char **db_args );
+
+const char * krb5_db2_err2str( krb5_context kcontext,
+ long err_code );
+
+void *
+krb5_db2_alloc( krb5_context kcontext,
+ void *ptr,
+ size_t size );
+
+void
+krb5_db2_free( krb5_context kcontext,
+ void *ptr );
+
+
+
+
+
+/* policy management functions */
+krb5_error_code
+krb5_db2_create_policy(krb5_context context, osa_policy_ent_t entry);
+
+krb5_error_code krb5_db2_get_policy ( krb5_context kcontext,
+ char *name,
+ osa_policy_ent_t *policy,
+ int *cnt);
+
+krb5_error_code krb5_db2_get_policy ( krb5_context kcontext,
+ char *name,
+ osa_policy_ent_t *policy,
+ int *cnt);
+
+krb5_error_code krb5_db2_put_policy ( krb5_context kcontext,
+ osa_policy_ent_t policy );
+
+krb5_error_code krb5_db2_iter_policy ( krb5_context kcontext,
+ char *match_entry,
+ osa_adb_iter_policy_func func,
+ void *data );
+
+krb5_error_code krb5_db2_delete_policy ( krb5_context kcontext,
+ char *policy );
+
+void krb5_db2_free_policy( krb5_context kcontext,
+ osa_policy_ent_t entry );
+
+
+
+extern krb5_set_err_func_t krb5_db2_dal_err_funcp;
+
#endif /* KRB5_KDB_DB2_H */
diff --git a/src/lib/kdb/kdb_xdr.c b/src/lib/kdb/kdb_db2/kdb_xdr.c
index fb0a41e..a5332ea 100644
--- a/src/lib/kdb/kdb_xdr.c
+++ b/src/lib/kdb/kdb_db2/kdb_xdr.c
@@ -29,6 +29,7 @@
#include <string.h>
#include <stdio.h>
#include <errno.h>
+#include "kdb_xdr.h"
#define safe_realloc(p,n) ((p)?(realloc(p,n)):(malloc(n)))
@@ -768,6 +769,7 @@ krb5_dbe_search_enctype(kcontext, dbentp, start, ktype, stype, kvno, kdatap)
if ((ret = krb5_c_enctype_compare(kcontext, (krb5_enctype) ktype,
dbentp->key_data[i].key_data_type[0],
&similar)))
+
return(ret);
}
diff --git a/src/lib/kdb/kdb_db2/kdb_xdr.h b/src/lib/kdb/kdb_db2/kdb_xdr.h
new file mode 100644
index 0000000..2ee068f
--- /dev/null
+++ b/src/lib/kdb/kdb_db2/kdb_xdr.h
@@ -0,0 +1,32 @@
+#ifndef _KDB2_XDR_H
+#define _KDB2_XDR_H
+
+krb5_error_code
+krb5_encode_princ_dbkey( krb5_context context,
+ krb5_data *key,
+ krb5_const_principal principal);
+
+krb5_error_code
+krb5_decode_princ_contents( krb5_context context,
+ krb5_data * content,
+ krb5_db_entry * entry);
+
+void
+krb5_dbe_free_contents( krb5_context context,
+ krb5_db_entry * entry);
+
+krb5_error_code
+krb5_encode_princ_contents( krb5_context context,
+ krb5_data * content,
+ krb5_db_entry * entry);
+
+
+void
+krb5_free_princ_dbkey( krb5_context context,
+ krb5_data *key);
+
+void
+krb5_free_princ_contents( krb5_context context,
+ krb5_data *contents);
+
+#endif
diff --git a/src/lib/kdb/kdb_db2/libkdb_db2.exports b/src/lib/kdb/kdb_db2/libkdb_db2.exports
new file mode 100644
index 0000000..b6902eb
--- /dev/null
+++ b/src/lib/kdb/kdb_db2/libkdb_db2.exports
@@ -0,0 +1 @@
+krb5_db_vftabl_kdb_db2
diff --git a/src/lib/kdb/kdb_db2/pol_xdr.c b/src/lib/kdb/kdb_db2/pol_xdr.c
new file mode 100644
index 0000000..3776108
--- /dev/null
+++ b/src/lib/kdb/kdb_db2/pol_xdr.c
@@ -0,0 +1,88 @@
+#include <sys/types.h>
+#include <krb5.h>
+#include <gssrpc/rpc.h>
+#include <krb5/kdb.h>
+#include "policy_db.h"
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+
+bool_t xdr_nullstring(XDR *xdrs, char **objp)
+{
+ u_int size;
+
+ if (xdrs->x_op == XDR_ENCODE) {
+ if (*objp == NULL)
+ size = 0;
+ else
+ size = strlen(*objp) + 1;
+ }
+ if (! xdr_u_int(xdrs, &size)) {
+ return FALSE;
+ }
+ switch (xdrs->x_op) {
+ case XDR_DECODE:
+ if (size == 0) {
+ *objp = NULL;
+ return TRUE;
+ } else if (*objp == NULL) {
+ *objp = (char *) mem_alloc(size);
+ if (*objp == NULL) {
+ errno = ENOMEM;
+ return FALSE;
+ }
+ }
+ return (xdr_opaque(xdrs, *objp, size));
+
+ case XDR_ENCODE:
+ if (size != 0)
+ return (xdr_opaque(xdrs, *objp, size));
+ return TRUE;
+
+ case XDR_FREE:
+ if (*objp != NULL)
+ mem_free(*objp, size);
+ *objp = NULL;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+bool_t
+xdr_osa_policy_ent_rec(XDR *xdrs, osa_policy_ent_t objp)
+{
+ switch (xdrs->x_op) {
+ case XDR_ENCODE:
+ objp->version = OSA_ADB_POLICY_VERSION_1;
+ /* fall through */
+ case XDR_FREE:
+ if (!xdr_int(xdrs, &objp->version))
+ return FALSE;
+ break;
+ case XDR_DECODE:
+ if (!xdr_int(xdrs, &objp->version))
+ return FALSE;
+ if (objp->version != OSA_ADB_POLICY_VERSION_1)
+ return FALSE;
+ break;
+ }
+
+ if(!xdr_nullstring(xdrs, &objp->name))
+ return (FALSE);
+ if (!xdr_u_int32(xdrs, &objp->pw_min_life))
+ return (FALSE);
+ if (!xdr_u_int32(xdrs, &objp->pw_max_life))
+ return (FALSE);
+ if (!xdr_u_int32(xdrs, &objp->pw_min_length))
+ return (FALSE);
+ if (!xdr_u_int32(xdrs, &objp->pw_min_classes))
+ return (FALSE);
+ if (!xdr_u_int32(xdrs, &objp->pw_history_num))
+ return (FALSE);
+ if (!xdr_u_int32(xdrs, &objp->policy_refcnt))
+ return (FALSE);
+ return (TRUE);
+}
diff --git a/src/lib/kdb/kdb_db2/policy_db.h b/src/lib/kdb/kdb_db2/policy_db.h
new file mode 100644
index 0000000..772b24d
--- /dev/null
+++ b/src/lib/kdb/kdb_db2/policy_db.h
@@ -0,0 +1,87 @@
+/*
+ * Data Types for policy and principal information that
+ * exists in the respective databases.
+ *
+ * $Header$
+ *
+ * This file was originally created with rpcgen.
+ * It has been hacked up since then.
+ */
+
+#ifndef __ADB_H__
+#define __ADB_H__
+#include <sys/types.h>
+#include "k5-int.h"
+#include <krb5/kdb.h>
+#include <db.h>
+#include <gssrpc/types.h>
+#include <gssrpc/xdr.h>
+#include "adb_err.h"
+#include <com_err.h>
+
+typedef long osa_adb_ret_t;
+
+#define OSA_ADB_POLICY_DB_MAGIC 0x12345A00
+
+#define OSA_ADB_POLICY_VERSION_MASK 0x12345D00
+#define OSA_ADB_POLICY_VERSION_1 0x12345D01
+
+
+
+typedef struct _osa_adb_db_lock_ent_t {
+ FILE *lockfile;
+ char *filename;
+ int refcnt, lockmode, lockcnt;
+ krb5_context context;
+} osa_adb_lock_ent, *osa_adb_lock_t;
+
+typedef struct _osa_adb_db_ent_t {
+ int magic;
+ DB *db;
+ HASHINFO info;
+ BTREEINFO btinfo;
+ char *filename;
+ osa_adb_lock_t lock;
+ int opencnt;
+} osa_adb_db_ent, *osa_adb_db_t, *osa_adb_princ_t, *osa_adb_policy_t;
+
+/*
+ * Return Code (the rest are in adb_err.h)
+ */
+
+#define OSA_ADB_OK 0
+
+/*
+ * Functions
+ */
+
+krb5_error_code osa_adb_create_db(char *filename, char *lockfile, int magic);
+krb5_error_code osa_adb_destroy_db(char *filename, char *lockfile, int magic);
+krb5_error_code osa_adb_rename_db(char *filefrom, char *lockfrom,
+ char *fileto, char *lockto, int magic);
+krb5_error_code osa_adb_init_db(osa_adb_db_t *dbp, char *filename,
+ char *lockfile, int magic);
+krb5_error_code osa_adb_fini_db(osa_adb_db_t db, int magic);
+krb5_error_code osa_adb_get_lock(osa_adb_db_t db, int mode);
+krb5_error_code osa_adb_release_lock(osa_adb_db_t db);
+krb5_error_code osa_adb_open_and_lock(osa_adb_princ_t db, int locktype);
+krb5_error_code osa_adb_close_and_unlock(osa_adb_princ_t db);
+krb5_error_code osa_adb_close_policy(osa_adb_policy_t db);
+krb5_error_code osa_adb_create_policy(osa_adb_policy_t db,
+ osa_policy_ent_t entry);
+krb5_error_code osa_adb_destroy_policy(osa_adb_policy_t db,
+ char * name);
+krb5_error_code osa_adb_get_policy(osa_adb_policy_t db,
+ char * name,
+ osa_policy_ent_t *entry,
+ int *cnt);
+krb5_error_code osa_adb_put_policy(osa_adb_policy_t db,
+ osa_policy_ent_t entry);
+krb5_error_code osa_adb_iter_policy(osa_adb_policy_t db,
+ osa_adb_iter_policy_func func,
+ void * data);
+void osa_free_policy_ent(osa_policy_ent_t val);
+
+bool_t xdr_osa_policy_ent_rec(XDR *xdrs, osa_policy_ent_t objp);
+
+#endif /* __ADB_H__ */
diff --git a/src/lib/kdb/kdb_default.c b/src/lib/kdb/kdb_default.c
new file mode 100644
index 0000000..07d1cef
--- /dev/null
+++ b/src/lib/kdb/kdb_default.c
@@ -0,0 +1,329 @@
+/*
+ * lib/kdb/kdb_helper.c
+ *
+ * Copyright 1995 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+#include "k5-int.h"
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+
+/*
+ * Given a particular enctype and optional salttype and kvno, find the
+ * most appropriate krb5_key_data entry of the database entry.
+ *
+ * If stype or kvno is negative, it is ignored.
+ * If kvno is 0 get the key which is maxkvno for the princ and matches
+ * the other attributes.
+ */
+krb5_error_code
+krb5_dbe_def_search_enctype(kcontext, dbentp, start, ktype, stype, kvno, kdatap)
+ krb5_context kcontext;
+ krb5_db_entry *dbentp;
+ krb5_int32 *start;
+ krb5_int32 ktype;
+ krb5_int32 stype;
+ krb5_int32 kvno;
+ krb5_key_data **kdatap;
+{
+ int i, idx;
+ int maxkvno;
+ krb5_key_data *datap;
+ krb5_error_code ret;
+
+ ret = 0;
+ if (kvno == -1 && stype == -1 && ktype == -1)
+ kvno = 0;
+
+ if (kvno == 0) {
+ /* Get the max key version */
+ for (i = 0; i < dbentp->n_key_data; i++) {
+ if (kvno < dbentp->key_data[i].key_data_kvno) {
+ kvno = dbentp->key_data[i].key_data_kvno;
+ }
+ }
+ }
+
+ maxkvno = -1;
+ datap = (krb5_key_data *) NULL;
+ for (i = *start; i < dbentp->n_key_data; i++) {
+ krb5_boolean similar;
+ krb5_int32 db_stype;
+
+ ret = 0;
+ if (dbentp->key_data[i].key_data_ver > 1) {
+ db_stype = dbentp->key_data[i].key_data_type[1];
+ } else {
+ db_stype = KRB5_KDB_SALTTYPE_NORMAL;
+ }
+
+ /*
+ * Filter out non-permitted enctypes.
+ */
+ if (!krb5_is_permitted_enctype(kcontext,
+ dbentp->key_data[i].key_data_type[0])) {
+ ret = KRB5_KDB_NO_PERMITTED_KEY;
+ continue;
+ }
+
+
+ if (ktype > 0) {
+ if ((ret = krb5_c_enctype_compare(kcontext, (krb5_enctype) ktype,
+ dbentp->key_data[i].key_data_type[0],
+ &similar)))
+
+ return(ret);
+ }
+
+ if (((ktype <= 0) || similar) &&
+ ((db_stype == stype) || (stype < 0))) {
+ if (kvno >= 0) {
+ if (kvno == dbentp->key_data[i].key_data_kvno) {
+ datap = &dbentp->key_data[i];
+ idx = i;
+ maxkvno = kvno;
+ break;
+ }
+ } else {
+ if (dbentp->key_data[i].key_data_kvno > maxkvno) {
+ maxkvno = dbentp->key_data[i].key_data_kvno;
+ datap = &dbentp->key_data[i];
+ idx = i;
+ }
+ }
+ }
+ }
+ if (maxkvno < 0)
+ return ret ? ret : KRB5_KDB_NO_MATCHING_KEY;
+ *kdatap = datap;
+ *start = idx+1;
+ return 0;
+}
+
+/*
+ * kdb default functions. Ideally, some other file should have this functions. For now, TBD.
+ */
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+krb5_error_code
+krb5_def_store_mkey(context, keyfile, mname, key, master_pwd)
+ krb5_context context;
+ char *keyfile;
+ krb5_principal mname;
+ krb5_keyblock *key;
+ char *master_pwd;
+{
+ FILE *kf;
+ krb5_error_code retval = 0;
+ krb5_ui_2 enctype;
+ char defkeyfile[MAXPATHLEN+1];
+ krb5_data *realm = krb5_princ_realm(context, mname);
+#if HAVE_UMASK
+ mode_t oumask;
+#endif
+
+ if (!keyfile) {
+ (void) strcpy(defkeyfile, DEFAULT_KEYFILE_STUB);
+ (void) strncat(defkeyfile, realm->data,
+ min(sizeof(defkeyfile)-sizeof(DEFAULT_KEYFILE_STUB)-1,
+ realm->length));
+ defkeyfile[sizeof(defkeyfile) - 1] = '\0';
+ keyfile = defkeyfile;
+ }
+
+#if HAVE_UMASK
+ oumask = umask(077);
+#endif
+#ifdef ANSI_STDIO
+ if (!(kf = fopen(keyfile, "wb")))
+#else
+ if (!(kf = fopen(keyfile, "w")))
+#endif
+ {
+#if HAVE_UMASK
+ (void) umask(oumask);
+#endif
+ return errno;
+ }
+ enctype = key->enctype;
+ if ((fwrite((krb5_pointer) &enctype,
+ 2, 1, kf) != 1) ||
+ (fwrite((krb5_pointer) &key->length,
+ sizeof(key->length), 1, kf) != 1) ||
+ (fwrite((krb5_pointer) key->contents,
+ sizeof(key->contents[0]), (unsigned) key->length,
+ kf) != key->length)) {
+ retval = errno;
+ (void) fclose(kf);
+ }
+ if (fclose(kf) == EOF)
+ retval = errno;
+#if HAVE_UMASK
+ (void) umask(oumask);
+#endif
+ return retval;
+}
+
+
+krb5_error_code
+krb5_db_def_fetch_mkey( krb5_context context,
+ krb5_principal mname,
+ krb5_keyblock *key,
+ int *kvno,
+ char *db_args)
+{
+ krb5_error_code retval;
+ krb5_ui_2 enctype;
+ char defkeyfile[MAXPATHLEN+1];
+ krb5_data *realm = krb5_princ_realm(context, mname);
+ FILE *kf = NULL;
+
+ retval = 0;
+ key->magic = KV5M_KEYBLOCK;
+ (void) strcpy(defkeyfile, DEFAULT_KEYFILE_STUB);
+ (void) strncat(defkeyfile, realm->data,
+ min(sizeof(defkeyfile)-sizeof(DEFAULT_KEYFILE_STUB)-1,
+ realm->length));
+ defkeyfile[sizeof(defkeyfile) - 1] = '\0';
+
+#ifdef ANSI_STDIO
+ if (!(kf = fopen((db_args) ? db_args : defkeyfile, "rb")))
+#else
+ if (!(kf = fopen((db_args) ? db_args : defkeyfile, "r")))
+#endif
+ return KRB5_KDB_CANTREAD_STORED;
+
+ if (fread((krb5_pointer) &enctype, 2, 1, kf) != 1) {
+ retval = KRB5_KDB_CANTREAD_STORED;
+ goto errout;
+ }
+
+ if (key->enctype == ENCTYPE_UNKNOWN)
+ key->enctype = enctype;
+ else if (enctype != key->enctype) {
+ retval = KRB5_KDB_BADSTORED_MKEY;
+ goto errout;
+ }
+
+ if (fread((krb5_pointer) &key->length,
+ sizeof(key->length), 1, kf) != 1) {
+ retval = KRB5_KDB_CANTREAD_STORED;
+ goto errout;
+ }
+
+ if (!key->length || ((int) key->length) < 0) {
+ retval = KRB5_KDB_BADSTORED_MKEY;
+ goto errout;
+ }
+
+ if (!(key->contents = (krb5_octet *)malloc(key->length))) {
+ retval = ENOMEM;
+ goto errout;
+ }
+
+ if (fread((krb5_pointer) key->contents,
+ sizeof(key->contents[0]), key->length, kf)
+ != key->length) {
+ retval = KRB5_KDB_CANTREAD_STORED;
+ memset(key->contents, 0, key->length);
+ free(key->contents);
+ key->contents = 0;
+ } else
+ retval = 0;
+
+ *kvno = 0;
+
+ errout:
+ (void) fclose(kf);
+ return retval;
+
+}
+
+
+krb5_error_code
+krb5_def_verify_master_key(context, mprinc, mkey)
+ krb5_context context;
+ krb5_principal mprinc;
+ krb5_keyblock *mkey;
+{
+ krb5_error_code retval;
+ krb5_db_entry master_entry;
+ int nprinc;
+ krb5_boolean more;
+ krb5_keyblock tempkey;
+
+ nprinc = 1;
+ if ((retval = krb5_db_get_principal(context, mprinc,
+ &master_entry, &nprinc, &more)))
+ return(retval);
+
+ if (nprinc != 1) {
+ if (nprinc)
+ krb5_db_free_principal(context, &master_entry, nprinc);
+ return(KRB5_KDB_NOMASTERKEY);
+ } else if (more) {
+ krb5_db_free_principal(context, &master_entry, nprinc);
+ return(KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE);
+ }
+
+ if ((retval = krb5_dbekd_decrypt_key_data(context, mkey,
+ &master_entry.key_data[0],
+ &tempkey, NULL))) {
+ krb5_db_free_principal(context, &master_entry, nprinc);
+ return retval;
+ }
+
+ if (mkey->length != tempkey.length ||
+ memcmp((char *)mkey->contents,
+ (char *)tempkey.contents,mkey->length)) {
+ retval = KRB5_KDB_BADMASTERKEY;
+ }
+
+ memset((char *)tempkey.contents, 0, tempkey.length);
+ krb5_xfree(tempkey.contents);
+ krb5_db_free_principal(context, &master_entry, nprinc);
+
+ return retval;
+}
+
+
+krb5_error_code kdb_def_set_mkey ( krb5_context kcontext,
+ char *pwd,
+ krb5_keyblock *key )
+{
+ printf("default set master key\n");
+ return 0;
+}
+
+krb5_error_code kdb_def_get_mkey ( krb5_context kcontext,
+ krb5_keyblock **key )
+{
+ printf("default get master key\n");
+ return 0;
+}
+
diff --git a/src/lib/kdb/keytab.c b/src/lib/kdb/keytab.c
index 679ecad..227a42e 100644
--- a/src/lib/kdb/keytab.c
+++ b/src/lib/kdb/keytab.c
@@ -140,20 +140,19 @@ krb5_ktkdb_get_entry(in_context, id, principal, kvno, enctype, entry)
xrealm_tgt = is_xrealm_tgt(context, principal);
- /* Open database */
- /* krb5_db_init(context); */
- if ((kerror = krb5_db_open_database(context)))
+ /* Check whether database is inited. Open is commented */
+ if ((kerror = krb5_db_inited(context)))
return(kerror);
/* get_principal */
kerror = krb5_db_get_principal(context, principal, &
db_entry, &n, &more);
if (kerror) {
- krb5_db_close_database(context);
+ /* krb5_db_close_database(context); */
return(kerror);
}
if (n != 1) {
- krb5_db_close_database(context);
+ /* krb5_db_close_database(context); */
return KRB5_KT_NOTFOUND;
}
@@ -207,8 +206,8 @@ krb5_ktkdb_get_entry(in_context, id, principal, kvno, enctype, entry)
/* Close database */
error:
- krb5_dbe_free_contents(context, &db_entry);
- krb5_db_close_database(context);
+ krb5_db_free_principal(context, &db_entry, 1);
+ /* krb5_db_close_database(context); */
return(kerror);
}
diff --git a/src/lib/kdb/libkdb5.exports b/src/lib/kdb/libkdb5.exports
index 47e1f0e..c9d53fb 100644
--- a/src/lib/kdb/libkdb5.exports
+++ b/src/lib/kdb/libkdb5.exports
@@ -97,6 +97,11 @@ kdb2_mpool_put
kdb2_mpool_sync
kdb2_nextkey
kdb2_store
+krb5_db_open
+krb5_db_inited
+krb5_db_clr_error
+krb5_db_alloc
+krb5_db_free
krb5_db_close_database
krb5_db_create
krb5_db_delete_principal
@@ -120,6 +125,7 @@ krb5_db_set_name
krb5_db_setup_mkey_name
krb5_db_store_mkey
krb5_db_unlock
+krb5_db_store_master_key
krb5_db_verify_master_key
krb5_dbe_apw
krb5_dbe_ark
@@ -150,3 +156,10 @@ krb5_ktkdb_set_context
krb5_mkey_pwd_prompt1
krb5_mkey_pwd_prompt2
krb5_ser_db_context_init
+krb5_db_create_policy
+krb5_db_get_policy
+krb5_db_put_policy
+krb5_db_iter_policy
+krb5_db_delete_policy
+krb5_db_free_policy
+krb5_db_vftabl_kdb_db2
diff --git a/src/lib/kdb/setup_mkey.c b/src/lib/kdb/setup_mkey.c
deleted file mode 100644
index 61f1ef3..0000000
--- a/src/lib/kdb/setup_mkey.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * lib/kdb/setup_mkey.c
- *
- * Copyright 1990 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
- *
- *
- * krb5_kdb_setup_mkey()
- */
-
-#include "k5-int.h"
-
-/*
- * Given a key name and a realm name, construct a principal which can be used
- * to fetch the master key from the database.
- *
- * If the key name is NULL, the default key name will be used.
- */
-
-#define REALM_SEP_STRING "@"
-
-krb5_error_code
-krb5_db_setup_mkey_name(context, keyname, realm, fullname, principal)
- krb5_context context;
- const char *keyname;
- const char *realm;
- char **fullname;
- krb5_principal *principal;
-{
- krb5_error_code retval;
- size_t keylen;
- size_t rlen = strlen(realm);
- char *fname;
-
- if (!keyname)
- keyname = KRB5_KDB_M_NAME; /* XXX external? */
-
- keylen = strlen(keyname);
-
- fname = malloc(keylen+rlen+strlen(REALM_SEP_STRING)+1);
- if (!fname)
- return ENOMEM;
-
- strcpy(fname, keyname);
- strcat(fname, REALM_SEP_STRING);
- strcat(fname, realm);
-
- if ((retval = krb5_parse_name(context, fname, principal)))
- return retval;
- if (fullname)
- *fullname = fname;
- else
- free(fname);
- return 0;
-}
diff --git a/src/lib/kdb/store_mkey.c b/src/lib/kdb/store_mkey.c
deleted file mode 100644
index 587850e..0000000
--- a/src/lib/kdb/store_mkey.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * lib/kdb/store_mkey.c
- *
- * Copyright 1990 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
- *
- *
- * krb5_db_store_mkey():
- * Store a database master key in a file.
- */
-
-
-#include <errno.h>
-#include "k5-int.h"
-
-/* Just in case sysincl.h didn't get it */
-
-#ifndef MAXPATHLEN
-#define MAXPATHLEN 1024
-#endif
-
-/*
- * Put the KDC database master key into a file. If keyfile is NULL,
- * then a default name derived from the principal name mname is used.
- */
-
-#ifndef min
-#define min(a,b) (((a) < (b)) ? (a) : (b))
-#endif
-
-krb5_error_code
-krb5_db_store_mkey(context, keyfile, mname, key)
- krb5_context context;
- char *keyfile;
- krb5_principal mname;
- krb5_keyblock *key;
-{
- FILE *kf;
- krb5_error_code retval = 0;
- krb5_ui_2 enctype;
- char defkeyfile[MAXPATHLEN+1];
- krb5_data *realm = krb5_princ_realm(context, mname);
-#if HAVE_UMASK
- mode_t oumask;
-#endif
-
- if (!keyfile) {
- (void) strcpy(defkeyfile, DEFAULT_KEYFILE_STUB);
- (void) strncat(defkeyfile, realm->data,
- min(sizeof(defkeyfile)-sizeof(DEFAULT_KEYFILE_STUB)-1,
- realm->length));
- defkeyfile[sizeof(defkeyfile) - 1] = '\0';
- keyfile = defkeyfile;
- }
-
-#if HAVE_UMASK
- oumask = umask(077);
-#endif
-#ifdef ANSI_STDIO
- if (!(kf = fopen(keyfile, "wb")))
-#else
- if (!(kf = fopen(keyfile, "w")))
-#endif
- {
-#if HAVE_UMASK
- (void) umask(oumask);
-#endif
- return errno;
- }
- enctype = key->enctype;
- if ((fwrite((krb5_pointer) &enctype,
- 2, 1, kf) != 1) ||
- (fwrite((krb5_pointer) &key->length,
- sizeof(key->length), 1, kf) != 1) ||
- (fwrite((krb5_pointer) key->contents,
- sizeof(key->contents[0]), (unsigned) key->length,
- kf) != key->length)) {
- retval = errno;
- (void) fclose(kf);
- }
- if (fclose(kf) == EOF)
- retval = errno;
-#if HAVE_UMASK
- (void) umask(oumask);
-#endif
- return retval;
-}
diff --git a/src/lib/kdb/t_kdb.c b/src/lib/kdb/t_kdb.c
deleted file mode 100644
index 769d3e6..0000000
--- a/src/lib/kdb/t_kdb.c
+++ /dev/null
@@ -1,1091 +0,0 @@
-/*
- * lib/kdb/t_kdb.c
- *
- * Copyright 1995 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
- *
- */
-
-/*
- * t_kdb.c - Test [and optionally obtain timing information about] the
- * Kerberos database functions.
- */
-
-#define KDB5_DISPATCH
-#include "k5-int.h"
-#include <ctype.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include "com_err.h"
-
-#if HAVE_SRAND48
-#define RAND() lrand48()
-#define SRAND(a) srand48(a)
-#define RAND_TYPE long
-#elif HAVE_SRAND
-#define RAND() rand()
-#define SRAND(a) srand(a)
-#define RAND_TYPE int
-#elif HAVE_SRANDOM
-#define RAND() random()
-#define SRAND(a) srandom(a)
-#define RAND_TYPE long
-#else /* no random */
-need a random number generator
-#endif /* no random */
-
-#define T_KDB_N_PASSES 100
-#define T_KDB_DEF_DB "test_db"
-#define MAX_PNAME_LEN 1024
-#define MAX_PRINC_COMPS 8
-#define MAX_COMP_SIZE 32
-
-#define RANDOM(a,b) (a + (RAND() % (b-a)))
-
-enum dbtype { DB_UFO, DB_DEFAULT, DB_BERKELEY, DB_DBM };
-
-char *programname = (char *) NULL;
-krb5_data mprinc_data_entries[] = {
- { 0, sizeof("master")-1, "master"},
- { 0, sizeof("key")-1, "key"}
-};
-
-krb5_principal_data master_princ_data = {
- 0, /* Magic number */
- { 0, sizeof("test.realm")-1, "test.realm"}, /* Realm */
- mprinc_data_entries, /* Name/instance */
- sizeof(mprinc_data_entries)/
- sizeof(mprinc_data_entries[0]), /* Number */
- KRB5_NT_SRV_INST /* Type */
-};
-
-struct timeval tstart_time, tend_time;
-struct timezone dontcare;
-krb5_principal *recorded_principals = (krb5_principal *) NULL;
-char **recorded_names = (char **) NULL;
-
-#ifdef BERK_DB_DBM
-extern DBM *db_dbm_open (char *, int, int);
-extern void db_dbm_close (DBM *);
-extern datum db_dbm_fetch (DBM *, datum);
-extern datum db_dbm_firstkey (DBM *);
-extern datum db_dbm_nextkey (DBM *);
-extern int db_dbm_delete (DBM *, datum);
-extern int db_dbm_store (DBM *, datum, datum, int);
-extern int db_dbm_error (DBM *);
-extern int db_dbm_clearerr (DBM *);
-extern int db_dbm_dirfno (DBM *);
-
-static kdb5_dispatch_table berkeley_dispatch = {
- "Berkeley Hashed Database",
- ".db", /* Index file name ext */
- (char *) NULL, /* Data file name ext */
- ".ok", /* Lock file name ext */
- db_dbm_open, /* Open Database */
- db_dbm_close, /* Close Database */
- db_dbm_fetch, /* Fetch Key */
- db_dbm_firstkey, /* Fetch First Key */
- db_dbm_nextkey, /* Fetch Next Key */
- db_dbm_delete, /* Delete Key */
- db_dbm_store, /* Store Key */
- db_dbm_error, /* Get Database Error */
- db_dbm_clearerr, /* Clear Database Error */
- db_dbm_dirfno, /* Get Database FD num */
- (int (*)()) NULL /* Get Database FD num */
-};
-#endif
-
-#if defined(NDBM) || defined(ODBM)
-/*
- * The following prototypes are necessary in case dbm_error and
- * dbm_clearerr are in the library but not prototyped
- * (e.g. NetBSD-1.0)
- */
-#ifdef MISSING_ERROR_PROTO
-int dbm_error (DBM *);
-#endif
-#ifdef MISSING_CLEARERR_PROTO
-int dbm_clearerr (DBM *);
-#endif
-
-static kdb5_dispatch_table dbm_dispatch = {
- "Stock [N]DBM Database",
- ".dir", /* Index file name ext */
- ".pag", /* Data file name ext */
- ".ok", /* Lock file name ext */
- dbm_open, /* Open Database */
- dbm_close, /* Close Database */
- dbm_fetch, /* Fetch Key */
- dbm_firstkey, /* Fetch First Key */
- dbm_nextkey, /* Fetch Next Key */
- dbm_delete, /* Delete Key */
- dbm_store, /* Store Key */
- /*
- * The following are #ifdef'd because they have the potential to be
- * macros rather than functions.
- */
-#ifdef dbm_error
- (int (*)()) NULL, /* Get Database Error */
-#else /* dbm_error */
-#ifdef HAVE_DBM_ERROR
- dbm_error, /* Get Database Error */
-#else
- (int (*)()) NULL, /* Get Database Error */
-#endif
-#endif /* dbm_error */
-#ifdef dbm_clearerr
- (int (*)()) NULL, /* Clear Database Error */
-#else /* dbm_clearerr */
-#ifdef HAVE_DBM_CLEARERR
- dbm_clearerr, /* Clear Database Error */
-#else
- (int (*)()) NULL, /* Clear Database Error */
-#endif
-#endif /* dbm_clearerr */
-#ifdef dbm_dirfno
- (int (*)()) NULL, /* Get Database FD num */
-#else /* dbm_dirfno */
- dbm_dirfno, /* Get Database FD num */
-#endif /* dbm_dirfno */
-#ifdef dbm_pagfno
- (int (*)()) NULL, /* Get Database FD num */
-#else /* dbm_pagfno */
- dbm_pagfno, /* Get Database FD num */
-#endif /* dbm_pagfno */
-};
-#endif /* NDBM || ODBM */
-
-
-/*
- * Timer macros.
- */
-#define swatch_on() ((void) gettimeofday(&tstart_time, &dontcare))
-#define swatch_eltime() ((gettimeofday(&tend_time, &dontcare)) ? -1.0 : \
- (((float) (tend_time.tv_sec - \
- tstart_time.tv_sec)) + \
- (((float) (tend_time.tv_usec - \
- tstart_time.tv_usec))/1000000.0)))
-
-/*
- * Free all principals and names in the recorded names list.
- */
-static void
-free_principals(kcontext, nentries)
- krb5_context kcontext;
- int nentries;
-{
- int i;
- if (recorded_principals) {
- for (i=0; i<nentries; i++) {
- if (recorded_principals[i])
- krb5_free_principal(kcontext, recorded_principals[i]);
- }
- free(recorded_principals);
- }
- recorded_principals = (krb5_principal *) NULL;
-
- if (recorded_names) {
- for (i=0; i<nentries; i++) {
- if (recorded_names[i])
- free(recorded_names[i]);
- }
- free(recorded_names);
- }
- recorded_names = (char **) NULL;
-}
-
-/*
- * Initialize the recorded names list.
- */
-static void
-init_princ_recording(kcontext, nentries)
- krb5_context kcontext;
- int nentries;
-{
- recorded_principals = (krb5_principal *)
- malloc(nentries * sizeof(krb5_principal));
- if (!recorded_principals)
- abort();
- memset((char *) recorded_principals, 0,
- nentries * sizeof(krb5_principal));
- recorded_names = (char **) malloc(nentries * sizeof(char *));
- if (!recorded_names)
- abort();
- memset((char *) recorded_names, 0, nentries * sizeof(char *));
-}
-
-/*
- * Record a principal and name.
- */
-static void
-record_principal(slotno, princ, pname)
- int slotno;
- krb5_principal princ;
- char *pname;
-{
- recorded_principals[slotno] = princ;
- recorded_names[slotno] = (char *) malloc(strlen(pname)+1);
- if (recorded_names[slotno])
- strcpy(recorded_names[slotno], pname);
-}
-
-#define playback_principal(slotno) (recorded_principals[slotno])
-#define playback_name(slotno) (recorded_names[slotno])
-
-/*
- * See if a principal already exists.
- */
-static krb5_boolean
-principal_found(nvalid, pname)
- int nvalid;
- char *pname;
-{
- krb5_boolean found;
- int i;
-
- found = 0;
- for (i=0; i<nvalid; i++) {
- if (!strcmp(recorded_names[i], pname)) {
- found = 1;
- break;
- }
- }
- return(found);
-}
-
-/*
- * Add a principal to the database.
- */
-static krb5_error_code
-add_principal(kcontext, principal, mkey, key)
- krb5_context kcontext;
- krb5_principal principal;
- krb5_keyblock * mkey;
- krb5_keyblock * key;
-{
- krb5_error_code kret;
- krb5_db_entry dbent;
- krb5_keyblock * rkey = NULL, lkey;
- krb5_timestamp timenow;
- int nentries = 1;
-
- memset((char *) &dbent, 0, sizeof(dbent));
- dbent.len = KRB5_KDB_V1_BASE_LENGTH;
-
- dbent.attributes = KRB5_KDB_DEF_FLAGS;
- dbent.max_life = KRB5_KDB_MAX_LIFE;
- dbent.expiration = KRB5_KDB_EXPIRATION;
- dbent.max_renewable_life = KRB5_KDB_MAX_RLIFE;
-
- if ((kret = krb5_copy_principal(kcontext, principal, &dbent.princ)))
- goto out;
-
- if ((kret = krb5_timeofday(kcontext, &timenow)))
- goto out;
- if ((kret = krb5_dbe_update_mod_princ_data(kcontext, &dbent,
- timenow, principal)))
- goto out;
-
- if (!key) {
- kret = krb5_c_make_random_key (kcontext, mkey->enctype, &lkey);
- if (kret)
- goto out;
- rkey = &lkey;
- } else
- rkey = key;
-
- if ((kret = krb5_dbe_create_key_data(kcontext, &dbent)))
- goto out;
- if ((kret = krb5_dbekd_encrypt_key_data(kcontext, mkey, rkey, NULL, 1,
- &dbent.key_data[0])))
- goto out;
-
- if (!key)
- krb5_free_keyblock_contents(kcontext, rkey);
-
- kret = krb5_db_put_principal(kcontext, &dbent, &nentries);
- if ((!kret) && (nentries != 1))
- kret = KRB5_KDB_UK_SERROR;
- out:
- krb5_dbe_free_contents(kcontext, &dbent);
- return(kret);
-}
-
-/*
- * Generate a principal name.
- */
-static krb5_error_code
-gen_principal(kcontext, realm, do_rand, n, princp, namep)
- krb5_context kcontext;
- char *realm;
- int do_rand;
- int n;
- krb5_principal *princp;
- char **namep;
-{
- static char pnamebuf[MAX_PNAME_LEN];
- static char *instnames[] = {
- "instance1", "xxx2", "whereami3", "ABCDEFG4", "foofoo5" };
- static char *princnames[] = {
- "princ1", "user2", "service3" };
-
- krb5_error_code kret;
- char *instname;
- char *princbase;
- int ncomps;
- int i, complen, j;
- char *cp;
-
- if (do_rand) {
- ncomps = RANDOM(1,MAX_PRINC_COMPS);
- cp = pnamebuf;
- for (i=0; i<ncomps; i++) {
- complen = RANDOM(1,MAX_COMP_SIZE);
- for (j=0; j<complen; j++) {
- *cp = (char) RANDOM(0,256);
- while (!isalnum(*cp & 0xff))
- *cp = (char) RANDOM(0,256);
- cp++;
- if(cp + strlen(realm) >= pnamebuf + sizeof(pnamebuf))
- break;
- }
- if(cp + strlen(realm) >= pnamebuf + sizeof(pnamebuf))
- break;
- *cp = '/';
- cp++;
- }
- if(cp + strlen(realm) < pnamebuf + sizeof(pnamebuf)) {
- cp[-1] = '@';
- strcpy(cp, realm);
- } else {
- strcpy(cp , "");
- }
- }
- else {
- instname = instnames[n % (sizeof(instnames)/sizeof(instnames[0]))];
- princbase = princnames[n % (sizeof(princnames)/sizeof(princnames[0]))];
- sprintf(pnamebuf, "%s%d/%s@%s", princbase, n, instname, realm);
- }
- kret = krb5_parse_name(kcontext, pnamebuf, princp);
- *namep = (!kret) ? pnamebuf : (char *) NULL;
- return(kret);
-}
-
-/*
- * Find a principal in the database.
- */
-static krb5_error_code
-find_principal(kcontext, principal, docompare)
- krb5_context kcontext;
- krb5_principal principal;
- krb5_boolean docompare;
-{
- krb5_error_code kret;
- krb5_db_entry dbent;
- krb5_principal mod_princ;
- krb5_timestamp mod_time;
- int how_many;
- krb5_boolean more;
-
- more = 0;
- how_many = 1;
- if ((kret = krb5_db_get_principal(kcontext, principal, &dbent,
- &how_many, &more)))
- return(kret);
- if (how_many == 0)
- return(KRB5_KDB_NOENTRY);
-
- if ((kret = krb5_dbe_lookup_mod_princ_data(kcontext, &dbent,
- &mod_time, &mod_princ)))
-
- return(kret);
-
- if (docompare) {
- if ((dbent.max_life != KRB5_KDB_MAX_LIFE) ||
- (dbent.max_renewable_life != KRB5_KDB_MAX_RLIFE) ||
- (dbent.expiration != KRB5_KDB_EXPIRATION) ||
- (dbent.attributes != KRB5_KDB_DEF_FLAGS) ||
- !krb5_principal_compare(kcontext, principal, dbent.princ) ||
- !krb5_principal_compare(kcontext, principal, mod_princ))
- kret = KRB5_PRINC_NOMATCH;
- }
-
- krb5_db_free_principal(kcontext, &dbent, how_many);
- krb5_free_principal(kcontext, mod_princ);
- if (!kret)
- return(((how_many == 1) && (more == 0)) ? 0 : KRB5KRB_ERR_GENERIC);
- else
- return(kret);
-
-}
-
-/*
- * Delete a principal.
- */
-static krb5_error_code
-delete_principal(kcontext, principal)
- krb5_context kcontext;
- krb5_principal principal;
-{
- krb5_error_code kret;
- int num2delete;
-
- num2delete = 1;
- if ((kret = krb5_db_delete_principal(kcontext, principal, &num2delete)))
- return(kret);
- return((num2delete == 1) ? 0 : KRB5KRB_ERR_GENERIC);
-}
-
-static int
-do_testing(db, passes, verbose, timing, rcases, check, save_db, dontclean,
- ptest, hash)
- char *db;
- int passes;
- int verbose;
- int timing;
- int rcases;
- int check;
- int save_db;
- int dontclean;
- int ptest;
- int hash;
-{
- krb5_error_code kret;
- krb5_context kcontext;
- char *op, *linkage, *oparg;
- krb5_principal master_princ;
- int master_princ_set = 0;
- char *mkey_name;
- char *realm;
- char *mkey_fullname;
- char *master_passwd;
- krb5_data salt_data;
- krb5_encrypt_block master_encblock;
- krb5_keyblock master_keyblock;
- krb5_data passwd;
- krb5_pointer rseed;
- krb5_boolean db_open, db_created;
- int passno;
- krb5_principal principal;
- char *pname;
- float elapsed;
- krb5_keyblock stat_kb;
- krb5_int32 crflags;
-
- mkey_name = "master/key";
- realm = master_princ_data.realm.data;
- mkey_fullname = (char *) NULL;
- master_princ = (krb5_principal) NULL;
- master_passwd = "master_password";
- db_open = 0;
- db_created = 0;
- linkage = "";
- oparg = "";
- crflags = hash ? KRB5_KDB_CREATE_HASH : KRB5_KDB_CREATE_BTREE;
-
- memset(&master_keyblock, 0, sizeof(master_keyblock));
-
- /* Set up some initial context */
- op = "initializing krb5";
- kret = krb5_init_context(&kcontext);
- if (kret)
- goto goodbye;
-
- /*
- * The database had better not exist.
- */
- op = "making sure database doesn't exist";
- if (!(kret = krb5_db_set_name(kcontext, db))) {
- kret = EEXIST;
- goto goodbye;
- }
-
- /* Set up the master key name */
- op = "setting up master key name";
- if ((kret = krb5_db_setup_mkey_name(kcontext, mkey_name, realm,
- &mkey_fullname, &master_princ)))
- goto goodbye;
-
- master_princ_set = 1;
- if (verbose)
- fprintf(stdout, "%s: Initializing '%s', master key is '%s'\n",
- programname, db, mkey_fullname);
-
- free(mkey_fullname);
- mkey_fullname = 0;
-
- op = "salting master key";
- if ((kret = krb5_principal2salt(kcontext, master_princ, &salt_data)))
- goto goodbye;
-
- op = "converting master key";
- krb5_use_enctype(kcontext, &master_encblock, DEFAULT_KDC_ENCTYPE);
- master_keyblock.enctype = DEFAULT_KDC_ENCTYPE;
- passwd.length = strlen(master_passwd);
- passwd.data = master_passwd;
- if ((kret = krb5_string_to_key(kcontext, &master_encblock,
- &master_keyblock, &passwd, &salt_data)))
- goto goodbye;
- /* Clean up */
- free(salt_data.data);
-
- /* Process master key */
- op = "processing master key";
- if ((kret = krb5_process_key(kcontext, &master_encblock,
- &master_keyblock)))
- goto goodbye;
-
- /* Initialize random key generator */
- op = "initializing random key generator";
- if ((kret = krb5_init_random_key(kcontext,
- &master_encblock,
- &master_keyblock,
- &rseed)))
- goto goodbye;
-
- /* Create database */
- op = "creating database";
- if ((kret = krb5_db_create(kcontext, db, crflags)))
- goto goodbye;
-
- db_created = 1;
-
- /* Set this database as active. */
- op = "setting active database";
- if ((kret = krb5_db_set_name(kcontext, db)))
- goto goodbye;
-
- /* Initialize database */
- op = "initializing database";
- if ((kret = krb5_db_init(kcontext)))
- goto goodbye;
-
- db_open = 1;
- op = "adding master principal";
- if ((kret = add_principal(kcontext,
- master_princ,
- &master_keyblock,
- &master_keyblock)))
- goto goodbye;
-
-
- stat_kb.enctype = DEFAULT_KDC_ENCTYPE;
- stat_kb.length = 8;
- stat_kb.contents = (krb5_octet *) "helpmeee";
-
- /* We are now ready to proceed to test. */
- if (verbose)
- fprintf(stdout, "%s: Beginning %stest\n",
- programname, (rcases) ? "random " : "");
- init_princ_recording(kcontext, passes);
- if (rcases) {
- struct tacc {
- float t_time;
- int t_number;
- } accumulated[3];
- int i, nvalid, discrim, highwater, coinflip;
- krb5_keyblock *kbp;
-
- /* Generate random cases */
- for (i=0; i<3; i++) {
- accumulated[i].t_time = 0.0;
- accumulated[i].t_number = 0;
- }
-
- /*
- * Generate principal names.
- */
- if (verbose > 1)
- fprintf(stdout, "%s: generating %d names\n",
- programname, passes);
- for (passno=0; passno<passes; passno++) {
- op = "generating principal name";
- do {
- if ((kret = gen_principal(kcontext, realm, rcases,
- passno, &principal, &pname)))
- goto goodbye;
- } while (principal_found(passno-1, pname));
- record_principal(passno, principal, pname);
- }
-
- /* Prime the database with some number of entries */
- nvalid = passes/4;
- if (nvalid < 10)
- nvalid = 10;
- if (nvalid > passes)
- nvalid = passes;
-
- if (verbose > 1)
- fprintf(stdout, "%s: priming database with %d principals\n",
- programname, nvalid);
- highwater = 0;
- for (passno=0; passno<nvalid; passno++) {
- op = "adding principal";
- coinflip = RANDOM(0,2);
- kbp = (coinflip) ? &stat_kb : (krb5_keyblock *) NULL;
- if (timing) {
- swatch_on();
- }
- if ((kret = add_principal(kcontext, playback_principal(passno),
- &master_keyblock, kbp))) {
- linkage = "initially ";
- oparg = playback_name(passno);
- goto cya;
- }
- if (timing) {
- elapsed = swatch_eltime();
- accumulated[0].t_time += elapsed;
- accumulated[0].t_number++;
- }
- if (verbose > 4)
- fprintf(stderr, "*A(%s)\n", playback_name(passno));
- highwater++;
- }
-
- if (verbose > 1)
- fprintf(stderr, "%s: beginning random loop\n", programname);
- /* Loop through some number of times and pick random operations */
- for (i=0; i<3*passes; i++) {
- discrim = RANDOM(0,100);
-
- /* Add a principal 25% of the time, if possible */
- if ((discrim < 25) && (nvalid < passes)) {
- op = "adding principal";
- coinflip = RANDOM(0,2);
- kbp = (coinflip) ? &stat_kb : (krb5_keyblock *) NULL;
- if (timing) {
- swatch_on();
- }
- if ((kret = add_principal(kcontext,
- playback_principal(nvalid),
- &master_keyblock, kbp))) {
- oparg = playback_name(nvalid);
- goto cya;
- }
- if (timing) {
- elapsed = swatch_eltime();
- accumulated[0].t_time += elapsed;
- accumulated[0].t_number++;
- }
- if (verbose > 4)
- fprintf(stderr, "*A(%s)\n", playback_name(nvalid));
- nvalid++;
- if (nvalid > highwater)
- highwater = nvalid;
- }
- /* Delete a principal 15% of the time, if possible */
- else if ((discrim > 85) && (nvalid > 10)) {
- op = "deleting principal";
- if (timing) {
- swatch_on();
- }
- if ((kret = delete_principal(kcontext,
- playback_principal(nvalid-1)))) {
- oparg = playback_name(nvalid-1);
- goto cya;
- }
- if (timing) {
- elapsed = swatch_eltime();
- accumulated[2].t_time += elapsed;
- accumulated[2].t_number++;
- }
- if (verbose > 4)
- fprintf(stderr, "XD(%s)\n", playback_name(nvalid-1));
- nvalid--;
- }
- /* Otherwise, find a principal */
- else {
- op = "looking up principal";
- passno = RANDOM(0, nvalid);
- if (timing) {
- swatch_on();
- }
- if ((kret = find_principal(kcontext,
- playback_principal(passno),
- check))) {
- oparg = playback_name(passno);
- goto cya;
- }
- if (timing) {
- elapsed = swatch_eltime();
- accumulated[1].t_time += elapsed;
- accumulated[1].t_number++;
- }
- if (verbose > 4)
- fprintf(stderr, "-S(%s)\n", playback_name(passno));
- }
- }
-
- if (!dontclean) {
- /* Clean up the remaining principals */
- if (verbose > 1)
- fprintf(stdout, "%s: deleting remaining %d principals\n",
- programname, nvalid);
- for (passno=0; passno<nvalid; passno++) {
- op = "deleting principal";
- if (timing) {
- swatch_on();
- }
- if ((kret = delete_principal(kcontext,
- playback_principal(passno)))) {
- linkage = "finally ";
- oparg = playback_name(passno);
- goto cya;
- }
- if (timing) {
- elapsed = swatch_eltime();
- accumulated[2].t_time += elapsed;
- accumulated[2].t_number++;
- }
- if (verbose > 4)
- fprintf(stderr, "XD(%s)\n", playback_name(passno));
- }
- }
- cya:
- if (verbose)
- fprintf(stdout,
- "%s: highwater mark was %d principals\n",
- programname, highwater);
- if (accumulated[0].t_number && timing)
- fprintf(stdout,
- "%s: performed %8d additions in %9.4f seconds (%9.4f/add)\n",
- programname, accumulated[0].t_number,
- accumulated[0].t_time,
- accumulated[0].t_time / (float) accumulated[0].t_number);
- if (accumulated[1].t_number && timing)
- fprintf(stdout,
- "%s: performed %8d lookups in %9.4f seconds (%9.4f/search)\n",
- programname, accumulated[1].t_number,
- accumulated[1].t_time,
- accumulated[1].t_time / (float) accumulated[1].t_number);
- if (accumulated[2].t_number && timing)
- fprintf(stdout,
- "%s: performed %8d deletions in %9.4f seconds (%9.4f/delete)\n",
- programname, accumulated[2].t_number,
- accumulated[2].t_time,
- accumulated[2].t_time / (float) accumulated[2].t_number);
- if (kret)
- goto goodbye;
- }
- else {
- /*
- * Generate principal names.
- */
- for (passno=0; passno<passes; passno++) {
- op = "generating principal name";
- if ((kret = gen_principal(kcontext, realm, rcases,
- passno, &principal, &pname)))
- goto goodbye;
- record_principal(passno, principal, pname);
- }
- /*
- * Add principals.
- */
- if (timing) {
- swatch_on();
- }
- for (passno=0; passno<passes; passno++) {
- op = "adding principal";
- if ((kret = add_principal(kcontext, playback_principal(passno),
- &master_keyblock, &stat_kb)))
- goto goodbye;
- if (verbose > 4)
- fprintf(stderr, "*A(%s)\n", playback_name(passno));
- }
- if (timing) {
- elapsed = swatch_eltime();
- fprintf(stdout,
- "%s: added %d principals in %9.4f seconds (%9.4f/add)\n",
- programname, passes, elapsed, elapsed/((float) passes));
- }
-
- /*
- * Lookup principals.
- */
- if (timing) {
- swatch_on();
- }
- for (passno=0; passno<passes; passno++) {
- op = "looking up principal";
- if ((kret = find_principal(kcontext, playback_principal(passno),
- check)))
- goto goodbye;
- if (verbose > 4)
- fprintf(stderr, "-S(%s)\n", playback_name(passno));
- }
- if (timing) {
- elapsed = swatch_eltime();
- fprintf(stdout,
- "%s: found %d principals in %9.4f seconds (%9.4f/search)\n",
- programname, passes, elapsed, elapsed/((float) passes));
- }
-
- /*
- * Delete principals.
- */
- if (!dontclean) {
- if (timing) {
- swatch_on();
- }
- for (passno=passes-1; passno>=0; passno--) {
- op = "deleting principal";
- if ((kret = delete_principal(kcontext,
- playback_principal(passno))))
- goto goodbye;
- if (verbose > 4)
- fprintf(stderr, "XD(%s)\n", playback_name(passno));
- }
- if (timing) {
- elapsed = swatch_eltime();
- fprintf(stdout,
- "%s: deleted %d principals in %9.4f seconds (%9.4f/delete)\n",
- programname, passes, elapsed,
- elapsed/((float) passes));
- }
- }
-
- }
-
- goodbye:
- if(master_princ_set) {
- krb5_free_principal(kcontext, master_princ);
- }
- if (kret)
- fprintf(stderr, "%s: error while %s %s%s(%s)\n",
- programname, op, linkage, oparg, error_message(kret));
-
- if (!kret && ptest) {
- int nper;
- pid_t children[32], child;
- int nprocs, existat, i, j, fd;
-
- nprocs = ptest + 1;
- if (nprocs > 32)
- nprocs = 32;
-
- nper = passes / nprocs;
- unlink("./test.lock");
- for (i=0; i<nprocs; i++) {
- child = fork();
- if (child == 0) {
- /* Child */
- int base;
- krb5_context ccontext;
- struct stat stbuf;
-
- while (stat("./test.lock", &stbuf) == -1)
- kret = krb5_init_context(&ccontext);
- if (kret) {
- com_err(programname, kret, "while initializing krb5");
- exit(1);
- }
- if ((kret = krb5_db_set_name(ccontext, db)) ||
- (kret = krb5_db_init(ccontext)))
- exit(1);
- base = i*nper;
- for (j=0; j<nper; j++) {
- if ((kret = add_principal(ccontext,
- playback_principal(base+j),
- &master_keyblock,
- &stat_kb))) {
- fprintf(stderr,
- "%ld: (%d,%d) Failed add of %s with %s\n",
- (long) getpid(), i, j, playback_name(base+j),
- error_message(kret));
- break;
- }
- if (verbose > 4)
- fprintf(stderr, "*A[%ld](%s)\n", (long) getpid(),
- playback_name(base+j));
- }
- for (j=0; (j<nper) && (!kret); j++) {
- if ((kret = find_principal(ccontext,
- playback_principal(base+j),
- check))) {
- fprintf(stderr,
- "%ld: (%d,%d) Failed lookup of %s with %s\n",
- (long) getpid(), i, j, playback_name(base+j),
- error_message(kret));
- break;
- }
- if (verbose > 4)
- fprintf(stderr, "-S[%ld](%s)\n", (long) getpid(),
- playback_name(base+j));
- }
- for (j=0; (j<nper) && (!kret); j++) {
- if ((kret = delete_principal(ccontext,
- playback_principal(base+j)))) {
- fprintf(stderr,
- "%ld: (%d,%d) Failed delete of %s with %s\n",
- (long) getpid(), i, j, playback_name(base+j),
- error_message(kret));
- break;
- }
- if (verbose > 4)
- fprintf(stderr, "XD[%ld](%s)\n", (long) getpid(),
- playback_name(base+j));
- }
- krb5_db_fini(ccontext);
- krb5_free_context(ccontext);
- exit((kret) ? 1 : 0);
- }
- else
- children[i] = child;
- }
- fd = open("./test.lock", O_CREAT|O_RDWR|O_EXCL, 0666);
- close(fd);
- sleep(1);
- unlink("./test.lock");
- for (i=0; i<nprocs; i++) {
- if (waitpid(children[i], &existat, 0) == children[i]) {
- if (verbose)
- fprintf(stderr, "%ld finished with %d\n",
- (long) children[i], existat);
- if (existat)
- kret = KRB5KRB_ERR_GENERIC;
- }
- else
- fprintf(stderr, "Wait for %ld failed\n", (long) children[i]);
- }
- }
-
- free_principals(kcontext, passes);
- if (db_open)
- (void) krb5_db_fini(kcontext);
- if (db_created) {
- if (!kret && !save_db) {
- krb5_db_destroy(kcontext, db);
- krb5_db_fini(kcontext);
- } else {
- if (kret && verbose)
- fprintf(stderr, "%s: database not deleted because of error\n",
- programname);
- }
- }
-
- krb5_free_keyblock_contents(kcontext, &master_keyblock);
- krb5_free_context(kcontext);
-
- return((kret) ? 1 : 0);
-}
-
-/*
- * usage:
- * t_kdb [-t] - Get timing information.
- * [-r] - Generate random cases.
- * [-n <num>] - Use <num> as the number of passes.
- * [-c] - Check contents.
- * [-v] - Verbose output.
- * [-d <dbname>] - Database name.
- * [-s] - Save database even on successful completion.
- * [-D] - Leave database dirty.
- */
-int
-main(argc, argv)
- int argc;
- char *argv[];
-{
- int option;
- extern char *optarg;
-
- int do_time, do_random, num_passes, check_cont, verbose, error;
- int save_db, dont_clean, do_ptest, hash;
- char *db_name;
-
- programname = argv[0];
- if (strrchr(programname, (int) '/'))
- programname = strrchr(programname, (int) '/') + 1;
- SRAND((RAND_TYPE)time((void *) NULL));
-
- /* Default values. */
- do_time = 0;
- do_random = 0;
- num_passes = T_KDB_N_PASSES;
- check_cont = 0;
- verbose = 0;
- db_name = T_KDB_DEF_DB;
- save_db = 0;
- dont_clean = 0;
- error = 0;
- do_ptest = 0;
- hash = 0;
-
- /* Parse argument list */
- while ((option = getopt(argc, argv, "cd:n:prstvDh")) != -1) {
- switch (option) {
- case 'c':
- check_cont = 1;
- break;
- case 'd':
- db_name = optarg;
- break;
- case 'n':
- if (sscanf(optarg, "%d", &num_passes) != 1) {
- fprintf(stderr, "%s: %s is not a valid number for %c option\n",
- programname, optarg, option);
- error++;
- }
- break;
- case 'p':
- do_ptest++;
- break;
- case 'r':
- do_random = 1;
- break;
- case 's':
- save_db = 1;
- break;
- case 't':
- do_time = 1;
- break;
- case 'v':
- verbose++;
- break;
- case 'D':
- dont_clean = 1;
- break;
- case 'h':
- hash = 1;
- break;
- default:
- error++;
- break;
- }
- }
- if (error)
- fprintf(stderr, "%s: usage is %s [-cprstv] [-d <dbname>] [-n <num>]\n",
- programname, programname);
- else
- error = do_testing(db_name,
- num_passes,
- verbose,
- do_time,
- do_random,
- check_cont,
- save_db,
- dont_clean,
- do_ptest,
- hash);
- return(error);
-}
-
-
diff --git a/src/lib/kdb/t_krb5.conf b/src/lib/kdb/t_krb5.conf
deleted file mode 100644
index 5882d97..0000000
--- a/src/lib/kdb/t_krb5.conf
+++ /dev/null
@@ -1,29 +0,0 @@
-[libdefaults]
- ticket_lifetime = 600
- default_realm = ATHENA.MIT.EDU
-
-[realms]
- ATHENA.MIT.EDU = {
- kdc = KERBEROS-2.MIT.EDU:88
- kdc = KERBEROS.MIT.EDU
- kdc = KERBEROS-1.MIT.EDU
- admin_server = KERBEROS.MIT.EDU
- default_domain = MIT.EDU
- v4_instance_convert = {
- mit = mit.edu
- lithium = lithium.lcs.mit.edu
- }
- }
- CYGNUS.COM = {
- kdc = KERBEROS-1.CYGNUS.COM
- kdc = KERBEROS.CYGNUS.COM
- admin_server = KERBEROS.MIT.EDU
- }
-
-[domain_realm]
- .mit.edu = ATHENA.MIT.EDU
- mit.edu = ATHENA.MIT.EDU
- .media.mit.edu = MEDIA-LAB.MIT.EDU
- media.mit.edu = MEDIA-LAB.MIT.EDU
- .ucsc.edu = CATS.UCSC.EDU
-
diff --git a/src/lib/kdb/verify_mky.c b/src/lib/kdb/verify_mky.c
deleted file mode 100644
index 452dc45..0000000
--- a/src/lib/kdb/verify_mky.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * lib/kdb/verify_mky.c
- *
- * Copyright 1990,1991 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
- *
- *
- * krb5_db_verify_master_key();
- */
-
-#include "k5-int.h"
-
-/*
- * Verify that the master key in *mkey matches the database entry
- * for mprinc.
- */
-
-krb5_error_code
-krb5_db_verify_master_key(context, mprinc, mkey)
- krb5_context context;
- krb5_principal mprinc;
- krb5_keyblock *mkey;
-{
- krb5_error_code retval;
- krb5_db_entry master_entry;
- int nprinc;
- krb5_boolean more;
- krb5_keyblock tempkey;
-
- nprinc = 1;
- if ((retval = krb5_db_get_principal(context, mprinc,
- &master_entry, &nprinc, &more)))
- return(retval);
-
- if (nprinc != 1) {
- if (nprinc)
- krb5_db_free_principal(context, &master_entry, nprinc);
- return(KRB5_KDB_NOMASTERKEY);
- } else if (more) {
- krb5_db_free_principal(context, &master_entry, nprinc);
- return(KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE);
- }
-
- if ((retval = krb5_dbekd_decrypt_key_data(context, mkey,
- &master_entry.key_data[0],
- &tempkey, NULL))) {
- krb5_db_free_principal(context, &master_entry, nprinc);
- return retval;
- }
-
- if (mkey->length != tempkey.length ||
- memcmp((char *)mkey->contents,
- (char *)tempkey.contents,mkey->length)) {
- retval = KRB5_KDB_BADMASTERKEY;
- }
-
- memset((char *)tempkey.contents, 0, tempkey.length);
- krb5_xfree(tempkey.contents);
- krb5_db_free_principal(context, &master_entry, nprinc);
-
- return retval;
-}