summaryrefslogtreecommitdiffstats
path: root/src/plugins/kdb/ldap
diff options
context:
space:
mode:
authorKen Raeburn <raeburn@mit.edu>2006-07-18 00:40:19 +0000
committerKen Raeburn <raeburn@mit.edu>2006-07-18 00:40:19 +0000
commit42d9d6ab320ee3a661fe21472be542acd542d5be (patch)
treeab3049772f6c2cceaf8956cf0a1172e0f6ddc12a /src/plugins/kdb/ldap
parent6eb696bf5669ec60b55927d974b48bbadc62bc66 (diff)
downloadkrb5-42d9d6ab320ee3a661fe21472be542acd542d5be.tar.gz
krb5-42d9d6ab320ee3a661fe21472be542acd542d5be.tar.xz
krb5-42d9d6ab320ee3a661fe21472be542acd542d5be.zip
Merge remaining changes from LDAP integration branch
svn+ssh://svn.mit.edu/krb5/branches/ldap-integ@18333. * plugins/kdb/ldap: New directory. * aclocal.m4 (WITH_LDAP): New macro. (CONFIG_RULES): Invoke it. * configure.in: Test ldap option, maybe configure and generate makefiles for new directories, and set and substitute ldap_plugin_dir. * Makefile.in (SUBDIRS): Add @ldap_plugin_dir@. * kdc/krb5kdc.M, kadmin/server/kadmind.M, kadmin/cli/kadmin.M, config-files/krb5.conf.M: Document LDAP changes (new options, config file entries, etc). * lib/kdb/kdb5.c (kdb_load_library): Put more info in error message. * lib/kadm5/admin.h (KADM5_CPW_FUNCTION, KADM5_RANDKEY_USED, KADM5_CONFIG_PASSWD_SERVER): New macros, disabled for now. (struct _kadm5_config_params): New field kpasswd_server, commented out for now. * lib/krb5/error_tables/kdb5_err.et: Add error codes KRB5_KDB_ACCESS_ERROR, KRB5_KDB_INTERNAL_ERROR, KRB5_KDB_CONSTRAINT_VIOLATION. ticket: 2935 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@18334 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/plugins/kdb/ldap')
-rw-r--r--src/plugins/kdb/ldap/ChangeLog51
-rw-r--r--src/plugins/kdb/ldap/Makefile.in64
-rw-r--r--src/plugins/kdb/ldap/kldap.exports1
-rw-r--r--src/plugins/kdb/ldap/ldap_exp.c85
-rw-r--r--src/plugins/kdb/ldap/ldap_util/ChangeLog12
-rw-r--r--src/plugins/kdb/ldap/ldap_util/Makefile.in28
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.c289
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.h47
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c870
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.h37
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c2609
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.h63
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c2181
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.h71
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.M977
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c655
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.h78
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ChangeLog37
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/Makefile.in280
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/configure.in26
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c490
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h262
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c355
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/kdb_xdr.c229
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/kdb_xdr.h34
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif888
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema695
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_err.c168
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_err.h12
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_fetch_mkey.c100
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.c274
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.h46
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c203
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.h54
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_main.h38
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c1471
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.h125
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c514
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.h126
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c1296
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c307
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.h54
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c1650
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.h99
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_service_rights.c801
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c253
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.h50
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_services.c595
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_services.h97
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c526
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.h76
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports41
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.c231
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.h61
54 files changed, 20682 insertions, 0 deletions
diff --git a/src/plugins/kdb/ldap/ChangeLog b/src/plugins/kdb/ldap/ChangeLog
new file mode 100644
index 000000000..9766515e0
--- /dev/null
+++ b/src/plugins/kdb/ldap/ChangeLog
@@ -0,0 +1,51 @@
+2006-04-08 Ken Raeburn <raeburn@mit.edu>
+
+ * ldap_exp.c: Include k5-int.h before testing HAVE_UNISTD_H.
+
+2006-03-21 Ken Raeburn <raeburn@mit.edu>
+
+ * Makefile.in (SHLIB_EXPDEPS, SHLIB_EXPLIBS): Add kdb_ldap
+ and support libraries.
+
+2006-03-17 Ken Raeburn <raeburn@mit.edu>
+
+ * Most files moved to lib/kdb_ldap.
+ * Makefile.in: Updated.
+ * kldap.exports: Only export the one symbol now defined.
+
+ * ldap_misc.c (format_d): New function.
+ (krb5_add_int_arr_mem_ldap_mod, krb5_add_int_mem_ldap_mod): Use it
+ instead of asprintf.
+
+ * Makefile.in: Remove all references to DB library.
+ (MODULE_INSTALL_DIR): Define.
+
+2006-03-16 Ken Raeburn <raeburn@mit.edu>
+
+ * ldap_exp.c: Wrap all functions with mutex protection.
+
+ * configure.in: Don't link against db library on AIX. If the
+ "lber" library is not found, then warn about that, not about the
+ ldap library.
+
+2006-03-14 Ken Raeburn <raeburn@mit.edu>
+
+ * ldap_err.h (LDAP_ERR_BASE, MAX_NEG, LDAP_TO_KDB_ERR): Unused
+ macros deleted.
+
+2006-03-07 Ken Raeburn <raeburn@mit.edu>
+
+ * kdb_ldap.h (HNDL_LOCK, HNDL_UNLOCK): Remove unneeded trailing
+ semicolon.
+ (timezone): Remove unused declaration.
+ (STORE16_INT, STORE32_INT, UNSTORE16_INT, UNSTORE32_INT): Use
+ inline functions already defined in k5-int.h.
+
+2006-01-29 Sam Hartman <hartmans@mit.edu>
+
+ * ldap_exp.c (krb5_db_vftabl_kldap): Remove thread safe flag
+
+ * ldap_err.c: Ignore LDAP_X_ERROR if not supported by version of OpenLDAP in use
+
+ * ldap_principal2.c: Accept LDAP_OPT_ERROR_NUMBER as a less-preferred synonym for LDAP_OPT_RESULT_CODE
+
diff --git a/src/plugins/kdb/ldap/Makefile.in b/src/plugins/kdb/ldap/Makefile.in
new file mode 100644
index 000000000..b7378bd5b
--- /dev/null
+++ b/src/plugins/kdb/ldap/Makefile.in
@@ -0,0 +1,64 @@
+thisconfigdir=../../..
+myfulldir=plugins/kdb/ldap
+mydir=plugins/kdb/ldap
+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)
+DEFS =
+MODULE_INSTALL_DIR = $(KRB5_DB_MODULE_DIR)
+
+LOCAL_SUBDIRS= libkdb_ldap ldap_util
+
+LOCALINCLUDES = -I../../../lib/kdb -I$(srcdir)/../../../lib/kdb \
+ -I$(srcdir)/libkdb_ldap
+
+LIBBASE=kldap
+LIBMAJOR=0
+LIBMINOR=0
+SO_EXT=.so
+RELDIR=../plugins/kdb/ldap
+# Depends on libk5crypto and libkrb5
+# Also on gssrpc, for xdr stuff.
+SHLIB_EXPDEPS = \
+ $(TOPLIBD)/libkdb_ldap$(SHLIBEXT) \
+ $(GSSRPC_DEPLIBS) \
+ $(TOPLIBD)/libk5crypto$(SHLIBEXT) \
+ $(TOPLIBD)/libkrb5$(SHLIBEXT) \
+ $(TOPLIBD)/lib$(SUPPORT_LIBNAME)$(SHLIBEXT)
+SHLIB_EXPLIBS= -lkdb_ldap $(GSSRPC_LIBS) -lkrb5 -lcom_err -lk5crypto -lkrb5support $(LIBS)
+SHLIB_DIRS=-L$(TOPLIBD)
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+
+$(TOPLIBD)/libkdb_ldap$(SHLIBEXT): all-recurse
+
+SRCS= $(srcdir)/ldap_exp.c
+
+STOBJLISTS=OBJS.ST
+STLIBOBJS= ldap_exp.o
+
+all-unix:: $(LIBBASE)$(SO_EXT)
+install-unix:: install-libs
+clean-unix:: clean-libs clean-libobjs
+
+# @libnover_frag@
+# @libobj_frag@
+
+# +++ Dependency line eater +++
+#
+# Makefile dependencies follow. This must be the last section in
+# the Makefile.in file
+#
+ldap_exp.so ldap_exp.po $(OUTPRE)ldap_exp.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+ $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+ $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+ $(SRCTOP)/lib/kdb/kdb5.h $(srcdir)/libkdb_ldap/kdb_ldap.h \
+ $(srcdir)/libkdb_ldap/ldap_krbcontainer.h $(srcdir)/libkdb_ldap/ldap_principal.h \
+ $(srcdir)/libkdb_ldap/ldap_pwd_policy.h $(srcdir)/libkdb_ldap/ldap_realm.h \
+ $(srcdir)/libkdb_ldap/ldap_tkt_policy.h ldap_exp.c
diff --git a/src/plugins/kdb/ldap/kldap.exports b/src/plugins/kdb/ldap/kldap.exports
new file mode 100644
index 000000000..f2b7c1119
--- /dev/null
+++ b/src/plugins/kdb/ldap/kldap.exports
@@ -0,0 +1 @@
+kdb_function_table
diff --git a/src/plugins/kdb/ldap/ldap_exp.c b/src/plugins/kdb/ldap/ldap_exp.c
new file mode 100644
index 000000000..15aea0a60
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_exp.c
@@ -0,0 +1,85 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_exp.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "k5-int.h"
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <errno.h>
+#include <utime.h>
+#include <kdb5.h>
+#include "kdb_ldap.h"
+#include "ldap_principal.h"
+#include "ldap_pwd_policy.h"
+
+/*
+ * Exposed API
+ */
+
+kdb_vftabl kdb_function_table = {
+ 1, /* major version number 1 */
+ 0, /* minor version number 0 */
+ /* init_library */ krb5_ldap_lib_init,
+ /* fini_library */ krb5_ldap_lib_cleanup,
+ /* init_module */ krb5_ldap_open,
+ /* fini_module */ krb5_ldap_close,
+ /* db_create */ NULL,
+ /* db_destroy */ NULL,
+ /* db_get_age */ krb5_ldap_db_get_age,
+ /* db_set_option */ NULL,
+ /* db_lock */ NULL,
+ /* db_unlock */ NULL,
+ /* db_get_principal */ krb5_ldap_get_principal,
+ /* db_free_principal */ krb5_ldap_free_principal,
+ /* db_put_principal */ krb5_ldap_put_principal,
+ /* db_delete_principal */ krb5_ldap_delete_principal,
+ /* db_iterate */ krb5_ldap_iterate,
+ /* db_create_policy */ krb5_ldap_create_password_policy,
+ /* db_get_policy */ krb5_ldap_get_password_policy,
+ /* db_put_policy */ krb5_ldap_put_password_policy,
+ /* db_iter_policy */ krb5_ldap_iterate_password_policy,
+ /* db_delete_policy */ krb5_ldap_delete_password_policy,
+ /* db_free_policy */ krb5_ldap_free_password_policy,
+ /* db_supported_realms */ NULL,
+ /* db_free_supported_realms */ NULL,
+ /* errcode_2_string */ NULL,
+ /* db_alloc */ krb5_ldap_alloc,
+ /* db_free */ krb5_ldap_free,
+ /* set_master_key */ krb5_ldap_set_mkey,
+ /* get_master_key */ krb5_ldap_get_mkey,
+ /* setup_master_key_name */ NULL,
+ /* store_master_key */ NULL,
+ /* fetch_master_key */ NULL /* krb5_ldap_fetch_mkey */,
+ /* verify_master_key */ NULL /* krb5_ldap_verify_master_key */,
+ /* Search enc type */ NULL,
+ /* Change pwd */ NULL
+
+};
diff --git a/src/plugins/kdb/ldap/ldap_util/ChangeLog b/src/plugins/kdb/ldap/ldap_util/ChangeLog
new file mode 100644
index 000000000..b72a851c2
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/ChangeLog
@@ -0,0 +1,12 @@
+2006-04-08 Ken Raeburn <raeburn@mit.edu>
+
+ * getdate.c: Deleted.
+ * Makefile.in ($(PROG)): Link against getdate.o from cli
+ directory.
+
+2006-03-17 Ken Raeburn <raeburn@mit.edu>
+
+ * Makefile.in (LOCALINCLUDES): Look for kdb ldap headers in new
+ location.
+ (KDB_DEP_LIB): Refer to kdb ldap library under new name.
+
diff --git a/src/plugins/kdb/ldap/ldap_util/Makefile.in b/src/plugins/kdb/ldap/ldap_util/Makefile.in
new file mode 100644
index 000000000..7d3956f7a
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/Makefile.in
@@ -0,0 +1,28 @@
+thisconfigdir=../../../..
+myfulldir=plugins/kdb/ldap/ldap_util
+mydir=plugins/kdb/ldap/ldap_util
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+DEFINES = -DKDB4_DISABLE
+DEFS=
+LOCALINCLUDES = -I. @KRB4_INCLUDES@ -I$(srcdir)/../libkdb_ldap -I$(SRCTOP)/lib/kdb
+PROG_LIBPATH=-L$(TOPLIBD) $(KRB4_LIBPATH)
+PROG_RPATH=$(KRB5_LIBDIR)
+#KDB_DEP_LIB=$(DL_LIB) $(THREAD_LINKOPTS)
+KDB_DEP_LIB=$(DL_LIB) -lkdb_ldap $(THREAD_LINKOPTS)
+
+PROG = kdb5_ldap_util
+OBJS = kdb5_ldap_util.o kdb5_ldap_list.o kdb5_ldap_realm.o kdb5_ldap_policy.o kdb5_ldap_services.o
+
+GETDATE = ../../../../kadmin/cli/getdate.o
+
+all:: $(PROG)
+
+$(PROG): $(OBJS) $(KADMSRV_DEPLIBS) $(KRB4COMPAT_DEPLIBS) $(GETDATE)
+ $(CC_LINK) -o $(PROG) $(OBJS) $(GETDATE) \
+ $(KADMSRV_LIBS) $(KDB_DEP_LIB) $(KRB4COMPAT_LIBS)
+
+install::
+ $(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(ADMIN_BINDIR)/$(PROG)
+
+clean::
+ $(RM) $(PROG) $(OBJS)
diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.c b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.c
new file mode 100644
index 000000000..733b7ab81
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.c
@@ -0,0 +1,289 @@
+/*
+ * kadmin/ldap_util/kdb5_ldap_list.c
+ */
+
+/* Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Miscellaneous functions for managing the string and integer lists
+ */
+
+#include <k5-int.h>
+#include "kdb5_ldap_list.h"
+
+/*
+ * Counts the number of entries in the given array of strings
+ */
+int list_count_str_array(char **list)
+{
+ int i = 0;
+
+ if (list == NULL)
+ return 0;
+
+ for (i = 0; *list != NULL; list++) {
+ i++;
+ }
+
+ return i;
+}
+
+
+/*
+ * Counts the number of entries in the given array of integers
+ */
+int list_count_int_array(int *list)
+{
+ int i = 0;
+
+ if (list == NULL)
+ return 0;
+
+ for (i = 0; *list != END_OF_LIST; list++) {
+ i++;
+ }
+
+ return i;
+}
+
+
+/*
+ * Frees the entries in a given list and not the list pointer
+ */
+void krb5_free_list_entries(list)
+ char **list;
+{
+ if (list == NULL)
+ return;
+ for(; *list != NULL; list++) {
+ free(*list);
+ *list = NULL;
+ }
+
+ return;
+}
+
+
+/*
+ * Tokenize the given string based on the delimiter provided
+ * and return the result as a list
+ */
+krb5_error_code
+krb5_parse_list(buffer, delimiter, list)
+ char *buffer;
+ char *delimiter;
+ char **list;
+{
+ char *str = NULL;
+ char *token = NULL;
+ char *ptrptr = NULL;
+ char **plist = list;
+ krb5_error_code retval = 0;
+ int count = 0;
+
+ if ((buffer == NULL) || (list == NULL) || (delimiter == NULL)) {
+ return EINVAL;
+ }
+
+ str = strdup(buffer);
+ if (str == NULL)
+ return ENOMEM;
+
+ token = strtok_r(str, delimiter, &ptrptr);
+ for (count = 1; ((token != NULL) && (count < MAX_LIST_ENTRIES));
+ plist++, count++) {
+ *plist = strdup(token);
+ if (*plist == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ token = strtok_r(NULL, delimiter, &ptrptr);
+ }
+ *plist = NULL;
+
+cleanup:
+ if(str) {
+ free(str);
+ str = NULL;
+ }
+ if (retval)
+ krb5_free_list_entries(list);
+
+ return retval;
+}
+
+
+int compare_int(m1, m2)
+ const void *m1;
+ const void *m2;
+{
+ int mi1 = *(const int *)m1;
+ int mi2 = *(const int *)m2;
+
+ return (mi1 - mi2);
+}
+
+
+/*
+ * Modifies the destination list to contain or not to contain the
+ * entries present in the source list, depending on the mode
+ * (ADD or DELETE).
+ */
+void list_modify_str_array(destlist, sourcelist, mode)
+ char ***destlist;
+ const char **sourcelist;
+ int mode;
+{
+ char **dlist = NULL, **tmplist = NULL;
+ const char **slist = NULL;
+ int dcount = 0, scount = 0, copycount = 0;
+ int found = 0;
+
+ if ((destlist == NULL) || (*destlist == NULL) || (sourcelist == NULL))
+ return;
+
+ /* We need to add every entry present in the source list to
+ * the destination list */
+ if (mode == LIST_MODE_ADD) {
+ /* Traverse throught the end of destlist for appending */
+ for(dlist = *destlist, dcount = 0; *dlist != NULL;
+ dlist++, dcount++) {
+ ; /* NULL statement */
+ }
+ /* Count the number of entries in the source list */
+ for(slist = sourcelist, scount = 0; *slist != NULL;
+ slist++, scount++) {
+ ; /* NULL statement */
+ }
+ /* Reset the slist pointer to the start of source list */
+ slist = sourcelist;
+
+ /* Now append the source list to the existing destlist */
+ if ((dcount + scount) < MAX_LIST_ENTRIES)
+ copycount = scount;
+ else
+ /* Leave the last entry for list terminator(=NULL) */
+ copycount = (MAX_LIST_ENTRIES -1) - dcount;
+
+ memcpy(dlist, slist, (sizeof(char *) * copycount));
+ dlist += copycount;
+ *dlist = NULL;
+ }
+ else if (mode == LIST_MODE_DELETE) {
+ /* We need to delete every entry present in the source list
+ * from the destination list */
+ for(slist = sourcelist; *slist != NULL; slist++) {
+ for(dlist = *destlist; *dlist != NULL; dlist++) {
+ found = 0; /* value not found */
+ /* DN is case insensitive string */
+ if (strcasecmp(*dlist, *slist) == 0) {
+ found = 1;
+ free(*dlist);
+ /* Advance the rest of the entries by one */
+ for(tmplist = dlist; *tmplist != NULL; tmplist++) {
+ *tmplist = *(tmplist+1);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ return;
+}
+
+
+/*
+ * Modifies the destination list to contain or not to contain the
+ * entries present in the source list, depending on the mode
+ * (ADD or DELETE). where the list is array of integers.
+ */
+int list_modify_int_array(destlist, sourcelist, mode)
+ int *destlist;
+ const int *sourcelist;
+ int mode;
+{
+ int *dlist = NULL, *tmplist = NULL;
+ const int *slist = NULL;
+ int dcount = 0, scount = 0, copycount = 0;
+ int tcount = 0;
+
+ if ((destlist == NULL) || (sourcelist == NULL))
+ return 0;
+
+ /* We need to add every entry present in the source list to the
+ * destination list */
+ if (mode == LIST_MODE_ADD) {
+ /* Traverse throught the end of destlist for appending */
+ for(dlist = destlist, dcount = 0; *dlist != END_OF_LIST;
+ dlist++, dcount++)
+ ; /* NULL statement */
+
+ /* Count the number of entries in the source list */
+ for(slist = sourcelist, scount = 0; *slist != END_OF_LIST;
+ slist++, scount++)
+ ; /* NULL statement */
+
+ /* Reset the slist pointer to the start of source list */
+ slist = sourcelist;
+
+ /* Now append the source list to the existing destlist */
+ if ((dcount + scount) < MAX_LIST_ENTRIES)
+ copycount = scount;
+ else
+ /* Leave the last entry for list terminator(=NULL) */
+ copycount = (MAX_LIST_ENTRIES -1) - dcount;
+
+ memcpy(dlist, slist, (sizeof(int) * copycount));
+ dlist += copycount;
+ *dlist = END_OF_LIST;
+ tcount = dcount + copycount;
+ }
+ else if (mode == LIST_MODE_DELETE) {
+ /* We need to delete every entry present in the source list from
+ * the destination list */
+ for(slist = sourcelist; *slist != END_OF_LIST; slist++) {
+ for(dlist = destlist; *dlist != END_OF_LIST; dlist++) {
+ if (*dlist == *slist) {
+ /* Advance the rest of the entries by one */
+ for(tmplist = dlist; *tmplist != END_OF_LIST; tmplist++) {
+ *tmplist = *(tmplist+1);
+ }
+ break;
+ }
+ }
+ }
+ /* count the number of entries */
+ for(dlist = destlist, tcount = 0; *dlist != END_OF_LIST; dlist++) {
+ tcount++;
+ }
+ }
+
+ return tcount;
+}
+
diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.h b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.h
new file mode 100644
index 000000000..b6402e592
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.h
@@ -0,0 +1,47 @@
+
+/*
+ * kadmin/ldap_util/kdb5_ldap_list.h
+ */
+
+/* Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#define MAX_LIST_ENTRIES 64
+#define END_OF_LIST -1 /* End of List */
+#define LIST_DELIMITER ":" /* List entry separator */
+#define LIST_MODE_ADD 0x701 /* Add to the List */
+#define LIST_MODE_DELETE 0x702 /* Delete from the list */
+#define MAX_LEN_LIST_ENTRY 512 /* Max len of an entry */
+
+extern krb5_error_code krb5_parse_list(char *buffer, char *delimiter, char **list);
+extern void krb5_free_list_entries(char **list);
+extern void list_modify_str_array(char ***destlist, const char **sourcelist, int mode);
+extern int list_modify_int_array(int *destlist, const int *sourcelist, int mode);
+extern int list_count_str_array(char **list);
+extern int list_count_int_array(int *list);
+extern int compare_int(const void*, const void *);
diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c
new file mode 100644
index 000000000..71d4863aa
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c
@@ -0,0 +1,870 @@
+/*
+ * kadmin/ldap_util/kdb5_ldap_policy.c
+ */
+
+/* Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Create / Delete / Modify / View / List policy objects.
+ */
+
+#include <stdio.h>
+#include <time.h>
+#include <k5-int.h>
+#include "kdb5_ldap_util.h"
+#include "kdb5_ldap_list.h"
+#include "ldap_tkt_policy.h"
+
+static void print_policy_params(krb5_ldap_policy_params *policyparams, int mask);
+static char *strdur(time_t duration);
+
+/* get_date() function used from src/kadmin/ldap_util/getdate.c */
+
+extern char *yes;
+
+
+/*
+ * This function will create a ticket policy object with the
+ * specified attributes.
+ */
+void
+kdb5_ldap_create_policy(argc, argv)
+ int argc;
+ char *argv[];
+{
+ char *me = argv[0];
+ krb5_error_code retval = 0;
+ krb5_ldap_policy_params *policyparams = NULL;
+ krb5_boolean print_usage = FALSE;
+ krb5_boolean no_msg = FALSE;
+ int mask = 0;
+ time_t date = 0;
+ time_t now = 0;
+ int i = 0;
+
+ /* Check for number of arguments */
+ if ((argc < 2) || (argc > 16)) {
+ goto err_usage;
+ }
+
+ /* Allocate memory for policy parameters structure */
+ policyparams = (krb5_ldap_policy_params*) calloc(1, sizeof(krb5_ldap_policy_params));
+ if (policyparams == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ /* Get current time */
+ time (&now);
+
+ /* Parse all arguments */
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-maxtktlife")) {
+ if (++i > argc - 1)
+ goto err_usage;
+
+ date = get_date(argv[i], NULL);
+ if (date == (time_t)(-1)) {
+ retval = EINVAL;
+ com_err (me, retval, "while providing time specification");
+ goto err_nomsg;
+ }
+
+ policyparams->maxtktlife = date - now;
+
+ mask |= LDAP_POLICY_MAXTKTLIFE;
+ }
+ else if (!strcmp(argv[i], "-maxrenewlife")) {
+ if (++i > argc - 1)
+ goto err_usage;
+
+ date = get_date(argv[i], NULL);
+ if (date == (time_t)(-1)) {
+ retval = EINVAL;
+ com_err (me, retval, "while providing time specification");
+ goto err_nomsg;
+ }
+
+ policyparams->maxrenewlife = date - now;
+
+ mask |= LDAP_POLICY_MAXRENEWLIFE;
+ }
+ else if (!strcmp((argv[i] + 1), "allow_postdated")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_POSTDATED);
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags |= KRB5_KDB_DISALLOW_POSTDATED;
+ else
+ goto err_usage;
+
+ mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else if (!strcmp((argv[i] + 1), "allow_forwardable")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_FORWARDABLE);
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags |= KRB5_KDB_DISALLOW_FORWARDABLE;
+ else
+ goto err_usage;
+
+ mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else if (!strcmp((argv[i] + 1), "allow_renewable")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_RENEWABLE);
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags |= KRB5_KDB_DISALLOW_RENEWABLE;
+ else
+ goto err_usage;
+
+ mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else if (!strcmp((argv[i] + 1), "allow_proxiable")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_PROXIABLE);
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags |= KRB5_KDB_DISALLOW_PROXIABLE;
+ else
+ goto err_usage;
+
+ mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else if (!strcmp((argv[i] + 1), "allow_dup_skey")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_DUP_SKEY);
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags |= KRB5_KDB_DISALLOW_DUP_SKEY;
+ else
+ goto err_usage;
+
+ mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else if (!strcmp((argv[i] + 1), "requires_preauth")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags |= KRB5_KDB_REQUIRES_PRE_AUTH;
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PRE_AUTH);
+ else
+ goto err_usage;
+
+ mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else if (!strcmp((argv[i] + 1), "requires_hwauth")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags |= KRB5_KDB_REQUIRES_HW_AUTH;
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_HW_AUTH);
+ else
+ goto err_usage;
+
+ mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else if (!strcmp((argv[i] + 1), "allow_svr")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_SVR);
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags |= KRB5_KDB_DISALLOW_SVR;
+ else
+ goto err_usage;
+
+ mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else if (!strcmp((argv[i] + 1), "allow_tgs_req")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_TGT_BASED);
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags |= KRB5_KDB_DISALLOW_TGT_BASED;
+ else
+ goto err_usage;
+
+ mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else if (!strcmp((argv[i] + 1), "allow_tix")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_ALL_TIX);
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags |= KRB5_KDB_DISALLOW_ALL_TIX;
+ else
+ goto err_usage;
+
+ mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else if (!strcmp((argv[i] + 1), "needchange")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags |= KRB5_KDB_REQUIRES_PWCHANGE;
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PWCHANGE);
+ else
+ goto err_usage;
+
+ mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else if (!strcmp((argv[i] + 1), "password_changing_service")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags |= KRB5_KDB_PWCHANGE_SERVICE;
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags &= (int)(~KRB5_KDB_PWCHANGE_SERVICE);
+ else
+ goto err_usage;
+
+ mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else { /* Any other argument must be policy DN */
+ /* First check if policy DN is already provided --
+ if so, there's a usage error */
+ if (policyparams->policydn != NULL)
+ goto err_usage;
+
+ /* If not present already, fill up policy DN */
+ policyparams->policydn = strdup(argv[i]);
+ if (policyparams->policydn == NULL) {
+ retval = ENOMEM;
+ com_err(me, retval, "while creating policy object");
+ goto err_nomsg;
+ }
+ }
+ }
+
+ /* policy DN is a mandatory argument. If not provided, print usage */
+ if (policyparams->policydn == NULL)
+ goto err_usage;
+
+ /* Create object with all attributes provided */
+ if ((retval = krb5_ldap_create_policy(util_context, policyparams, mask)) != 0)
+ goto cleanup;
+
+ goto cleanup;
+
+err_usage:
+ print_usage = TRUE;
+
+err_nomsg:
+ no_msg = TRUE;
+
+cleanup:
+ /* Clean-up structure */
+ krb5_ldap_free_policy (util_context, policyparams);
+
+ if (print_usage)
+ db_usage(CREATE_POLICY);
+
+ if (retval) {
+ if (!no_msg)
+ com_err(me, retval, "while creating policy object");
+
+ exit_status++;
+ }
+
+ return;
+}
+
+
+/*
+ * This function will destroy the specified ticket policy
+ * object interactively, unless forced through an option.
+ */
+void
+kdb5_ldap_destroy_policy(argc, argv)
+ int argc;
+ char *argv[];
+{
+ char *me = argv[0];
+ krb5_error_code retval = 0;
+ krb5_ldap_policy_params *policyparams = NULL;
+ krb5_boolean print_usage = FALSE;
+ krb5_boolean no_msg = FALSE;
+ char *policydn = NULL;
+ int mask = 0;
+ int force = 0;
+ char buf[5] = {0};
+ int i = 0;
+
+ if ((argc < 2) || (argc > 3)) {
+ goto err_usage;
+ }
+
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-force") == 0) {
+ force++;
+ }
+ else { /* Any other argument must be policy DN */
+ /* First check if policy DN is already provided --
+ if so, there's a usage error */
+ if (policydn != NULL)
+ goto err_usage;
+
+ /* If not present already, fill up policy DN */
+ policydn = strdup(argv[i]);
+ if (policydn == NULL) {
+ retval = ENOMEM;
+ com_err(me, retval, "while destroying policy object");
+ goto err_nomsg;
+ }
+ }
+ }
+
+ if (policydn == NULL)
+ goto err_usage;
+
+ if (!force) {
+ printf("This will delete the policy object '%s', are you sure?\n", policydn);
+ printf("(type 'yes' to confirm)? ");
+
+ if (fgets(buf, sizeof(buf), stdin) == NULL) {
+ retval = EINVAL;
+ goto cleanup;
+ }
+
+ if (strcmp(buf, yes)) {
+ exit_status++;
+ goto cleanup;
+ }
+ }
+
+ if ((retval = krb5_ldap_read_policy(util_context, policydn, &policyparams, &mask)))
+ goto cleanup;
+
+
+ if ((retval = krb5_ldap_delete_policy(util_context, policydn, policyparams,&mask)))
+ goto cleanup;
+
+ printf("** policy object '%s' deleted.\n", policydn);
+ goto cleanup;
+
+
+err_usage:
+ print_usage = TRUE;
+
+err_nomsg:
+ no_msg = TRUE;
+
+cleanup:
+ /* Clean-up structure */
+ krb5_ldap_free_policy (util_context, policyparams);
+
+ if (policydn) {
+ free (policydn);
+ }
+
+ if (print_usage) {
+ db_usage(DESTROY_POLICY);
+ }
+
+ if (retval) {
+ if (!no_msg)
+ com_err(me, retval, "while destroying policy object");
+
+ exit_status++;
+ }
+
+ return;
+}
+
+
+/*
+ * This function will modify the attributes of a given ticket
+ * policy object.
+ */
+void
+kdb5_ldap_modify_policy(argc, argv)
+ int argc;
+ char *argv[];
+{
+ char *me = argv[0];
+ krb5_error_code retval = 0;
+ krb5_ldap_policy_params *policyparams = NULL;
+ krb5_boolean print_usage = FALSE;
+ krb5_boolean no_msg = FALSE;
+ char *policydn = NULL;
+ int in_mask = 0, out_mask = 0;
+ time_t date = 0;
+ time_t now = 0;
+ int i = 0;
+
+ /* Check for number of arguments -- minimum is 3
+ since atleast one parameter should be given in
+ addition to 'modify_policy' and policy DN */
+ if ((argc < 3) || (argc > 16)) {
+ goto err_usage;
+ }
+
+ /* Parse all arguments, only to pick up policy DN (Pass 1) */
+ for (i = 1; i < argc; i++) {
+ /* Skip arguments next to 'maxtktlife'
+ and 'maxrenewlife' arguments */
+ if (!strcmp(argv[i], "-maxtktlife")) {
+ ++i;
+ }
+ else if (!strcmp(argv[i], "-maxrenewlife")) {
+ ++i;
+ }
+ /* Do nothing for ticket flag arguments */
+ else if (!strcmp((argv[i] + 1), "allow_postdated") ||
+ !strcmp((argv[i] + 1), "allow_forwardable") ||
+ !strcmp((argv[i] + 1), "allow_renewable") ||
+ !strcmp((argv[i] + 1), "allow_proxiable") ||
+ !strcmp((argv[i] + 1), "allow_dup_skey") ||
+ !strcmp((argv[i] + 1), "requires_preauth") ||
+ !strcmp((argv[i] + 1), "requires_hwauth") ||
+ !strcmp((argv[i] + 1), "allow_svr") ||
+ !strcmp((argv[i] + 1), "allow_tgs_req") ||
+ !strcmp((argv[i] + 1), "allow_tix") ||
+ !strcmp((argv[i] + 1), "needchange") ||
+ !strcmp((argv[i] + 1), "password_changing_service")) {
+ }
+ else { /* Any other argument must be policy DN */
+ /* First check if policy DN is already provided --
+ if so, there's a usage error */
+ if (policydn != NULL)
+ goto err_usage;
+
+ /* If not present already, fill up policy DN */
+ policydn = strdup(argv[i]);
+ if (policydn == NULL) {
+ retval = ENOMEM;
+ com_err(me, retval, "while modifying policy object");
+ goto err_nomsg;
+ }
+ }
+ }
+
+ if (policydn == NULL)
+ goto err_usage;
+
+ retval = krb5_ldap_read_policy(util_context, policydn, &policyparams, &in_mask);
+ if (retval) {
+ com_err(me, retval, "while reading information of policy '%s'", policydn);
+ goto err_nomsg;
+ }
+
+ /* Get current time */
+ time (&now);
+
+ /* Parse all arguments, but skip policy DN (Pass 2) */
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-maxtktlife")) {
+ if (++i > argc - 1)
+ goto err_usage;
+
+ date = get_date(argv[i], NULL);
+ if (date == (time_t)(-1)) {
+ retval = EINVAL;
+ com_err (me, retval, "while providing time specification");
+ goto err_nomsg;
+ }
+
+ policyparams->maxtktlife = date - now;
+
+ out_mask |= LDAP_POLICY_MAXTKTLIFE;
+ }
+ else if (!strcmp(argv[i], "-maxrenewlife")) {
+ if (++i > argc - 1)
+ goto err_usage;
+
+ date = get_date(argv[i], NULL);
+ if (date == (time_t)(-1)) {
+ retval = EINVAL;
+ com_err (me, retval, "while providing time specification");
+ goto err_nomsg;
+ }
+
+ policyparams->maxrenewlife = date - now;
+
+ out_mask |= LDAP_POLICY_MAXRENEWLIFE;
+ }
+ else if (!strcmp((argv[i] + 1), "allow_postdated")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_POSTDATED);
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags |= KRB5_KDB_DISALLOW_POSTDATED;
+ else
+ goto err_usage;
+
+ out_mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else if (!strcmp((argv[i] + 1), "allow_forwardable")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_FORWARDABLE);
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags |= KRB5_KDB_DISALLOW_FORWARDABLE;
+ else
+ goto err_usage;
+
+ out_mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else if (!strcmp((argv[i] + 1), "allow_renewable")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_RENEWABLE);
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags |= KRB5_KDB_DISALLOW_RENEWABLE;
+ else
+ goto err_usage;
+
+ out_mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else if (!strcmp((argv[i] + 1), "allow_proxiable")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_PROXIABLE);
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags |= KRB5_KDB_DISALLOW_PROXIABLE;
+ else
+ goto err_usage;
+
+ out_mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else if (!strcmp((argv[i] + 1), "allow_dup_skey")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_DUP_SKEY);
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags |= KRB5_KDB_DISALLOW_DUP_SKEY;
+ else
+ goto err_usage;
+
+ out_mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else if (!strcmp((argv[i] + 1), "requires_preauth")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags |= KRB5_KDB_REQUIRES_PRE_AUTH;
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PRE_AUTH);
+ else
+ goto err_usage;
+
+ out_mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else if (!strcmp((argv[i] + 1), "requires_hwauth")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags |= KRB5_KDB_REQUIRES_HW_AUTH;
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_HW_AUTH);
+ else
+ goto err_usage;
+
+ out_mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else if (!strcmp((argv[i] + 1), "allow_svr")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_SVR);
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags |= KRB5_KDB_DISALLOW_SVR;
+ else
+ goto err_usage;
+
+ out_mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else if (!strcmp((argv[i] + 1), "allow_tgs_req")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_TGT_BASED);
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags |= KRB5_KDB_DISALLOW_TGT_BASED;
+ else
+ goto err_usage;
+
+ out_mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else if (!strcmp((argv[i] + 1), "allow_tix")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_ALL_TIX);
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags |= KRB5_KDB_DISALLOW_ALL_TIX;
+ else
+ goto err_usage;
+
+ out_mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else if (!strcmp((argv[i] + 1), "needchange")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags |= KRB5_KDB_REQUIRES_PWCHANGE;
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PWCHANGE);
+ else
+ goto err_usage;
+
+ out_mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else if (!strcmp((argv[i] + 1), "password_changing_service")) {
+ if (*(argv[i]) == '+')
+ policyparams->tktflags |= KRB5_KDB_PWCHANGE_SERVICE;
+ else if (*(argv[i]) == '-')
+ policyparams->tktflags &= (int)(~KRB5_KDB_PWCHANGE_SERVICE);
+ else
+ goto err_usage;
+
+ out_mask |= LDAP_POLICY_TKTFLAGS;
+ }
+ else {
+ /* Any other argument must be policy DN
+ -- skip it */
+ }
+ }
+
+ /* Modify attributes of object */
+ if ((retval = krb5_ldap_modify_policy(util_context, policyparams, out_mask)))
+ goto cleanup;
+
+ goto cleanup;
+
+err_usage:
+ print_usage = TRUE;
+
+err_nomsg:
+ no_msg = TRUE;
+
+cleanup:
+ /* Clean-up structure */
+ krb5_ldap_free_policy (util_context, policyparams);
+
+ if (policydn)
+ free (policydn);
+
+ if (print_usage)
+ db_usage(MODIFY_POLICY);
+
+ if (retval) {
+ if (!no_msg)
+ com_err(me, retval, "while modifying policy object");
+
+ exit_status++;
+ }
+
+ return;
+}
+
+
+/*
+ * This function will display information about the given policy object,
+ * fetching the information from the LDAP Server.
+ */
+void
+kdb5_ldap_view_policy(argc, argv)
+ int argc;
+ char *argv[];
+{
+ char *me = argv[0];
+ krb5_ldap_policy_params *policyparams = NULL;
+ krb5_error_code retval = 0;
+ krb5_boolean print_usage = FALSE;
+ char *policydn = NULL;
+ int mask = 0;
+
+ if (argc != 2) {
+ goto err_usage;
+ }
+
+ policydn = strdup(argv[1]);
+ if (policydn == NULL) {
+ com_err(me, ENOMEM, "while viewing policy");
+ exit_status++;
+ goto cleanup;
+ }
+
+ if ((retval = krb5_ldap_read_policy(util_context, policydn, &policyparams, &mask))) {
+ com_err(me, retval, "while viewing policy '%s'", policydn );
+ exit_status++;
+ goto cleanup;
+ }
+
+ print_policy_params (policyparams, mask);
+
+ goto cleanup;
+
+err_usage:
+ print_usage = TRUE;
+
+cleanup:
+ krb5_ldap_free_policy (util_context, policyparams);
+
+ if (policydn)
+ free (policydn);
+
+ if (print_usage) {
+ db_usage(VIEW_POLICY);
+ }
+
+ return;
+}
+
+
+/*
+ * This function will print the policy object information to the
+ * standard output.
+ */
+static void
+print_policy_params(policyparams, mask)
+ krb5_ldap_policy_params *policyparams;
+ int mask;
+{
+ /* Print the policy DN */
+ printf("%25s: %s\n", "Ticket policy", policyparams->policydn);
+
+ /* Print max. ticket life and max. renewable life, if present */
+ if (mask & LDAP_POLICY_MAXTKTLIFE)
+ printf("%25s: %s\n", "Maximum ticket life", strdur(policyparams->maxtktlife));
+ if (mask & LDAP_POLICY_MAXRENEWLIFE)
+ printf("%25s: %s\n", "Maximum renewable life", strdur(policyparams->maxrenewlife));
+
+ /* Service flags are printed */
+ printf("%25s: ", "Ticket flags");
+ if (mask & LDAP_POLICY_TKTFLAGS) {
+ int ticketflags = policyparams->tktflags;
+
+ if (ticketflags & KRB5_KDB_DISALLOW_POSTDATED)
+ printf("%s ","DISALLOW_POSTDATED");
+
+ if (ticketflags & KRB5_KDB_DISALLOW_FORWARDABLE)
+ printf("%s ","DISALLOW_FORWARDABLE");
+
+ if (ticketflags & KRB5_KDB_DISALLOW_RENEWABLE)
+ printf("%s ","DISALLOW_RENEWABLE");
+
+ if (ticketflags & KRB5_KDB_DISALLOW_PROXIABLE)
+ printf("%s ","DISALLOW_PROXIABLE");
+
+ if (ticketflags & KRB5_KDB_DISALLOW_DUP_SKEY)
+ printf("%s ","DISALLOW_DUP_SKEY");
+
+ if (ticketflags & KRB5_KDB_REQUIRES_PRE_AUTH)
+ printf("%s ","REQUIRES_PRE_AUTH");
+
+ if (ticketflags & KRB5_KDB_REQUIRES_HW_AUTH)
+ printf("%s ","REQUIRES_HW_AUTH");
+
+ if (ticketflags & KRB5_KDB_DISALLOW_SVR)
+ printf("%s ","DISALLOW_SVR");
+
+ if (ticketflags & KRB5_KDB_DISALLOW_TGT_BASED)
+ printf("%s ","DISALLOW_TGT_BASED");
+
+ if (ticketflags & KRB5_KDB_DISALLOW_ALL_TIX)
+ printf("%s ","DISALLOW_ALL_TIX");
+
+ if (ticketflags & KRB5_KDB_REQUIRES_PWCHANGE)
+ printf("%s ","REQUIRES_PWCHANGE");
+
+ if (ticketflags & KRB5_KDB_PWCHANGE_SERVICE)
+ printf("%s ","PWCHANGE_SERVICE");
+ }
+ printf("\n");
+
+ return;
+}
+
+
+/*
+ * This function will list the DNs of policy objects under a specific
+ * sub-tree (entire tree by default)
+ */
+void kdb5_ldap_list_policies(argc, argv)
+ int argc;
+ char *argv[];
+{
+ char *me = argv[0];
+ krb5_error_code retval = 0;
+ krb5_boolean print_usage = FALSE;
+ char *basedn = NULL;
+ char **list = NULL;
+ char **plist = NULL;
+
+ /* Check for number of arguments */
+ if ((argc != 1) && (argc != 3)) {
+ goto err_usage;
+ }
+
+ /* Parse base DN argument if present */
+ if (argc == 3) {
+ if (strcmp(argv[1], "-basedn"))
+ goto err_usage;
+
+ basedn = strdup(argv[2]);
+ if (basedn == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+
+ retval = krb5_ldap_list_policy(util_context, basedn, &list);
+ if ((retval != 0) || (list == NULL))
+ goto cleanup;
+
+ for (plist = list; *plist != NULL; plist++) {
+ printf("%s\n", *plist);
+ }
+
+ goto cleanup;
+
+err_usage:
+ print_usage = TRUE;
+
+cleanup:
+ if (list != NULL) {
+ krb5_free_list_entries (list);
+ free (list);
+ }
+
+ if (basedn)
+ free (basedn);
+
+ if (print_usage) {
+ db_usage(LIST_POLICY);
+ }
+
+ if (retval) {
+ com_err(me, retval, "while listing policy objects");
+ exit_status++;
+ }
+
+ return;
+}
+
+
+/* Reproduced from kadmin.c, instead of linking
+ the entire kadmin.o */
+static char *strdur(duration)
+ time_t duration;
+{
+ static char out[50];
+ int neg, days, hours, minutes, seconds;
+
+ if (duration < 0) {
+ duration *= -1;
+ neg = 1;
+ } else
+ neg = 0;
+ days = duration / (24 * 3600);
+ duration %= 24 * 3600;
+ hours = duration / 3600;
+ duration %= 3600;
+ minutes = duration / 60;
+ duration %= 60;
+ seconds = duration;
+ sprintf(out, "%s%d %s %02d:%02d:%02d", neg ? "-" : "",
+ days, days == 1 ? "day" : "days",
+ hours, minutes, seconds);
+ return out;
+}
+
diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.h b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.h
new file mode 100644
index 000000000..105b0a06b
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.h
@@ -0,0 +1,37 @@
+/*
+ * kadmin/ldap_util/kdb5_ldap_policy.h
+ */
+
+/* Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+extern void kdb5_ldap_create_policy(int argc, char **argv);
+extern void kdb5_ldap_destroy_policy(int argc, char **argv);
+extern void kdb5_ldap_modify_policy(int argc, char **argv);
+extern void kdb5_ldap_view_policy(int argc, char **argv);
+extern void kdb5_ldap_list_policies(int argc, char **argv);
diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c
new file mode 100644
index 000000000..1e597b7c5
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c
@@ -0,0 +1,2609 @@
+/*
+ * kadmin/ldap_util/kdb5_ldap_realm.c
+ *
+ * Copyright 1990,1991,2001, 2002 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.
+ */
+
+/*
+ * 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.
+ */
+
+/* Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Create / Modify / Destroy / View / List realm(s)
+ */
+
+#include <stdio.h>
+#include <k5-int.h>
+#include <kadm5/admin.h>
+#include "kdb5_ldap_util.h"
+#include "kdb5_ldap_list.h"
+#include <ldap_principal.h>
+
+char *yes = "yes\n"; /* \n to compare against result of fgets */
+krb5_key_salt_tuple def_kslist = {ENCTYPE_DES_CBC_CRC, KRB5_KDB_SALTTYPE_NORMAL};
+
+struct realm_info rblock = {
+ KRB5_KDB_MAX_LIFE,
+ KRB5_KDB_MAX_RLIFE,
+ KRB5_KDB_EXPIRATION,
+ KRB5_KDB_DEF_FLAGS,
+ (krb5_keyblock *) NULL,
+ 1,
+ &def_kslist
+};
+
+krb5_data tgt_princ_entries[] = {
+ {0, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME},
+ {0, 0, 0} };
+
+krb5_data db_creator_entries[] = {
+ {0, sizeof("db_creation")-1, "db_creation"} };
+
+
+static krb5_principal_data db_create_princ = {
+ 0, /* magic number */
+ {0, 0, 0}, /* krb5_data realm */
+ db_creator_entries, /* krb5_data *data */
+ 1, /* int length */
+ KRB5_NT_SRV_INST /* int type */
+};
+
+extern char *mkey_password;
+extern char *progname;
+extern kadm5_config_params global_params;
+
+static void print_realm_params(krb5_ldap_realm_params *rparams, int mask);
+static int kdb_ldap_create_principal (krb5_context context, krb5_principal
+ princ, enum ap_op op, struct realm_info *pblock);
+
+
+static char *strdur(time_t duration);
+static int get_ticket_policy(krb5_ldap_realm_params *rparams, int *i, char *argv[],int argc);
+
+
+static int get_ticket_policy(rparams,i,argv,argc)
+ krb5_ldap_realm_params *rparams;
+ int *i;
+ char *argv[];
+ int argc;
+{
+ time_t date;
+ time_t now;
+ time(&now);
+ int mask = 0;
+ krb5_error_code retval = 0;
+ krb5_boolean no_msg = FALSE;
+
+ krb5_boolean print_usage = FALSE;
+ char *me = argv[0];
+ if (!strcmp(argv[*i], "-maxtktlife")) {
+ if (++(*i) > argc-1)
+ goto err_usage;
+ date = get_date(argv[*i], NULL);
+ if (date == (time_t)(-1)) {
+ retval = EINVAL;
+ com_err (me, retval, "while providing time specification");
+ goto err_nomsg;
+ }
+ rparams->max_life = date-now;
+ mask |= LDAP_REALM_MAXTICKETLIFE;
+ }
+
+
+ else if (!strcmp(argv[*i], "-maxrenewlife")) {
+ if (++(*i) > argc-1)
+ goto err_usage;
+
+ date = get_date(argv[*i], NULL);
+ if (date == (time_t)(-1)) {
+ retval = EINVAL;
+ com_err (me, retval, "while providing time specification");
+ goto err_nomsg;
+ }
+ rparams->max_renewable_life = date-now;
+ mask |= LDAP_REALM_MAXRENEWLIFE;
+ }
+ else if (!strcmp((argv[*i] + 1), "allow_postdated")) {
+ if (*(argv[*i]) == '+')
+ rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_POSTDATED);
+ else if (*(argv[*i]) == '-')
+ rparams->tktflags |= KRB5_KDB_DISALLOW_POSTDATED;
+ else
+ goto err_usage;
+
+ mask |= LDAP_REALM_KRBTICKETFLAGS;
+ }
+ else if (!strcmp((argv[*i] + 1), "allow_forwardable")) {
+ if (*(argv[*i]) == '+')
+ rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_FORWARDABLE);
+
+ else if (*(argv[*i]) == '-')
+ rparams->tktflags |= KRB5_KDB_DISALLOW_FORWARDABLE;
+ else
+ goto err_usage;
+
+ mask |= LDAP_REALM_KRBTICKETFLAGS;
+ }
+ else if (!strcmp((argv[*i] + 1), "allow_renewable")) {
+ if (*(argv[*i]) == '+')
+ rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_RENEWABLE);
+ else if (*(argv[*i]) == '-')
+ rparams->tktflags |= KRB5_KDB_DISALLOW_RENEWABLE;
+ else
+ goto err_usage;
+
+ mask |= LDAP_REALM_KRBTICKETFLAGS;
+ }
+ else if (!strcmp((argv[*i] + 1), "allow_proxiable")) {
+ if (*(argv[*i]) == '+')
+ rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_PROXIABLE);
+ else if (*(argv[*i]) == '-')
+ rparams->tktflags |= KRB5_KDB_DISALLOW_PROXIABLE;
+ else
+ goto err_usage;
+
+ mask |= LDAP_REALM_KRBTICKETFLAGS;
+ }
+ else if (!strcmp((argv[*i] + 1), "allow_dup_skey")) {
+ if (*(argv[*i]) == '+')
+ rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_DUP_SKEY);
+ else if (*(argv[*i]) == '-')
+ rparams->tktflags |= KRB5_KDB_DISALLOW_DUP_SKEY;
+ else
+ goto err_usage;
+
+ mask |= LDAP_REALM_KRBTICKETFLAGS;
+ }
+
+ else if (!strcmp((argv[*i] + 1), "requires_preauth")) {
+ if (*(argv[*i]) == '+')
+ rparams->tktflags |= KRB5_KDB_REQUIRES_PRE_AUTH;
+ else if (*(argv[*i]) == '-')
+ rparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PRE_AUTH);
+ else
+ goto err_usage;
+
+ mask |= LDAP_REALM_KRBTICKETFLAGS;
+ }
+ else if (!strcmp((argv[*i] + 1), "requires_hwauth")) {
+ if (*(argv[*i]) == '+')
+ rparams->tktflags |= KRB5_KDB_REQUIRES_HW_AUTH;
+ else if (*(argv[*i]) == '-')
+ rparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_HW_AUTH);
+ else
+ goto err_usage;
+
+ mask |= LDAP_REALM_KRBTICKETFLAGS;
+ }
+ else if (!strcmp((argv[*i] + 1), "allow_svr")) {
+ if (*(argv[*i]) == '+')
+ rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_SVR);
+ else if (*(argv[*i]) == '-')
+ rparams->tktflags |= KRB5_KDB_DISALLOW_SVR;
+ else
+ goto err_usage;
+
+ mask |= LDAP_REALM_KRBTICKETFLAGS;
+ }
+ else if (!strcmp((argv[*i] + 1), "allow_tgs_req")) {
+ if (*(argv[*i]) == '+')
+ rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_TGT_BASED);
+ else if (*(argv[*i]) == '-')
+ rparams->tktflags |= KRB5_KDB_DISALLOW_TGT_BASED;
+ else
+ goto err_usage;
+
+ mask |= LDAP_REALM_KRBTICKETFLAGS;
+ }
+ else if (!strcmp((argv[*i] + 1), "allow_tix")) {
+ if (*(argv[*i]) == '+')
+ rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_ALL_TIX);
+ else if (*(argv[*i]) == '-')
+ rparams->tktflags |= KRB5_KDB_DISALLOW_ALL_TIX;
+ else
+ goto err_usage;
+
+ mask |= LDAP_REALM_KRBTICKETFLAGS;
+ }
+ else if (!strcmp((argv[*i] + 1), "needchange")) {
+ if (*(argv[*i]) == '+')
+ rparams->tktflags |= KRB5_KDB_REQUIRES_PWCHANGE;
+ else if (*(argv[*i]) == '-')
+ rparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PWCHANGE);
+ else
+ goto err_usage;
+
+ mask |= LDAP_REALM_KRBTICKETFLAGS;
+ }
+ else if (!strcmp((argv[*i] + 1), "password_changing_service")) {
+ if (*(argv[*i]) == '+')
+ rparams->tktflags |= KRB5_KDB_PWCHANGE_SERVICE;
+ else if (*(argv[*i]) == '-')
+ rparams->tktflags &= (int)(~KRB5_KDB_PWCHANGE_SERVICE);
+ else
+ goto err_usage;
+
+ mask |=LDAP_REALM_KRBTICKETFLAGS;
+ }
+err_usage:
+ print_usage = TRUE;
+
+err_nomsg:
+ no_msg = TRUE;
+
+ return mask;
+}
+
+/*
+ * This function will create a realm on the LDAP Server, with
+ * the specified attributes.
+ */
+void kdb5_ldap_create(argc, argv)
+ int argc;
+ char *argv[];
+{
+ krb5_error_code retval = 0;
+ krb5_keyblock master_keyblock;
+ krb5_ldap_realm_params *rparams = NULL;
+ krb5_principal master_princ = NULL;
+ kdb5_dal_handle *dal_handle = NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_boolean realm_obj_created = FALSE;
+ krb5_boolean create_complete = FALSE;
+ krb5_boolean print_usage = FALSE;
+ krb5_boolean no_msg = FALSE;
+ char *oldsubtree = NULL;
+ char pw_str[1024];
+ int do_stash = 0;
+ int i = 0, j = 0;
+ int mask = 0, ret_mask = 0;
+ char *me = argv[0];
+#ifdef HAVE_EDIRECTORY
+ int rightsmask = 0;
+#endif
+
+ memset(&master_keyblock, 0, sizeof(master_keyblock));
+
+ rparams = (krb5_ldap_realm_params *)malloc(
+ sizeof(krb5_ldap_realm_params));
+ if (rparams == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ memset(rparams, 0, sizeof(krb5_ldap_realm_params));
+
+ /* Parse the arguments */
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-subtree")) {
+ if (++i > argc-1)
+ goto err_usage;
+ rparams->subtree = strdup(argv[i]);
+ if (rparams->subtree == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ mask |= LDAP_REALM_SUBTREE;
+ }
+ else if (!strcmp(argv[i], "-sscope")) {
+ if (++i > argc-1)
+ goto err_usage;
+ /* Possible values for search scope are
+ * one (or 1) and sub (or 2)
+ */
+ if (!strcasecmp(argv[i], "one")) {
+ rparams->search_scope = 1;
+ }
+ else if (!strcasecmp(argv[i], "sub")) {
+ rparams->search_scope = 2;
+ }
+ else {
+ rparams->search_scope = atoi(argv[i]);
+ if ((rparams->search_scope != 1) &&
+ (rparams->search_scope != 2)) {
+ com_err(argv[0], EINVAL,
+ "invalid search scope while creating realm '%s'",
+ global_params.realm);
+ goto err_nomsg;
+ }
+ }
+ mask |= LDAP_REALM_SEARCHSCOPE;
+ }
+#ifdef HAVE_EDIRECTORY
+ else if (!strcmp(argv[i], "-kdcdn")) {
+ if (++i > argc-1)
+ goto err_usage;
+ rparams->kdcservers = (char **)malloc(
+ sizeof(char *) * MAX_LIST_ENTRIES);
+ if (rparams->kdcservers == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ memset(rparams->kdcservers, 0, sizeof(char*)*MAX_LIST_ENTRIES);
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
+ rparams->kdcservers))) {
+ goto cleanup;
+ }
+ mask |= LDAP_REALM_KDCSERVERS;
+ }
+ else if (!strcmp(argv[i], "-admindn")) {
+ if (++i > argc-1)
+ goto err_usage;
+ rparams->adminservers = (char **)malloc(
+ sizeof(char *) * MAX_LIST_ENTRIES);
+ if (rparams->adminservers == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ memset(rparams->adminservers, 0, sizeof(char*)*MAX_LIST_ENTRIES);
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
+ rparams->adminservers))) {
+ goto cleanup;
+ }
+ mask |= LDAP_REALM_ADMINSERVERS;
+ }
+ else if (!strcmp(argv[i], "-pwddn")) {
+ if (++i > argc-1)
+ goto err_usage;
+ rparams->passwdservers = (char **)malloc(
+ sizeof(char *) * MAX_LIST_ENTRIES);
+ if (rparams->passwdservers == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ memset(rparams->passwdservers, 0, sizeof(char*)*MAX_LIST_ENTRIES);
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
+ rparams->passwdservers))) {
+ goto cleanup;
+ }
+ mask |= LDAP_REALM_PASSWDSERVERS;
+ }
+#endif
+ else if (!strcmp(argv[i], "-enctypes")) {
+ char *tlist[MAX_LIST_ENTRIES] = {NULL};
+
+ if (++i > argc-1)
+ goto err_usage;
+ rparams->suppenctypes = (krb5_enctype *)malloc(
+ sizeof(krb5_enctype) * MAX_LIST_ENTRIES);
+ if (rparams->suppenctypes == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ memset(rparams->suppenctypes, 0, sizeof(krb5_enctype) * MAX_LIST_ENTRIES);
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, tlist)) != 0) {
+ goto cleanup;
+ }
+ for(j = 0; tlist[j] != NULL; j++) {
+ if ((retval = krb5_string_to_enctype(tlist[j],
+ &rparams->suppenctypes[j]))) {
+ com_err(argv[0], retval, "Invalid encryption type '%s'",
+ tlist[j]);
+ krb5_free_list_entries(tlist);
+ goto err_nomsg;
+ }
+ }
+ rparams->suppenctypes[j] = END_OF_LIST;
+ qsort(rparams->suppenctypes, (size_t)j, sizeof(krb5_enctype),
+ compare_int);
+ mask |= LDAP_REALM_SUPPENCTYPE;
+ krb5_free_list_entries(tlist);
+ }
+ else if (!strcmp(argv[i], "-defenctype")) {
+ if (++i > argc-1)
+ goto err_usage;
+ if ((retval = krb5_string_to_enctype(argv[i],
+ &rparams->defenctype))) {
+ com_err(argv[0], retval, "'%s' specified for defenctype, "
+ "while creating realm '%s'",
+ argv[i], global_params.realm);
+ goto err_nomsg;
+ }
+ mask |= LDAP_REALM_DEFENCTYPE;
+ }
+ else if (!strcmp(argv[i], "-salttypes")) {
+ char *tlist[MAX_LIST_ENTRIES] = {NULL};
+
+ if (++i > argc-1)
+ goto err_usage;
+ rparams->suppsalttypes = (krb5_int32 *)malloc(
+ sizeof(krb5_int32) * MAX_LIST_ENTRIES);
+ if (rparams->suppsalttypes == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ memset(rparams->suppsalttypes, 0, sizeof(krb5_int32) * MAX_LIST_ENTRIES);
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, tlist))) {
+ goto cleanup;
+ }
+ for(j = 0; tlist[j] != NULL; j++) {
+ if ((retval = krb5_string_to_salttype(tlist[j],
+ &rparams->suppsalttypes[j]))) {
+ com_err(argv[0], retval, "'%s' specified for salttypes, "
+ "while creating realm '%s'",
+ tlist[j], global_params.realm);
+ krb5_free_list_entries(tlist);
+ goto err_nomsg;
+ }
+ }
+ rparams->suppsalttypes[j] = END_OF_LIST;
+ qsort(rparams->suppsalttypes, (size_t)j, sizeof(krb5_int32),
+ compare_int);
+ mask |= LDAP_REALM_SUPPSALTTYPE;
+ krb5_free_list_entries(tlist);
+ }
+ else if (!strcmp(argv[i], "-defsalttype")) {
+ if (++i > argc-1)
+ goto err_usage;
+ if ((retval = krb5_string_to_salttype(argv[i],
+ &rparams->defsalttype))) {
+ com_err(argv[0], retval, "'%s' specified for defsalttype, "
+ "while creating realm '%s'",
+ argv[i], global_params.realm);
+ goto err_nomsg;
+ }
+ mask |= LDAP_REALM_DEFSALTTYPE;
+ }
+ else if (!strcmp(argv[i], "-s")) {
+ do_stash = 1;
+ }
+ else if ((ret_mask= get_ticket_policy(rparams,&i,argv,argc)) !=0)
+ {
+ mask|=ret_mask;
+ }
+
+ else {
+ printf("'%s' is an invalid option\n", argv[i]);
+ goto err_usage;
+ }
+ }
+
+ /* If the default enctype/salttype is not provided, use the
+ * default values and also add to the list of supported
+ * enctypes/salttype
+ */
+ if ( !(mask & LDAP_REALM_DEFENCTYPE) && (rparams != NULL)) {
+ rparams->defenctype = ENCTYPE_DES3_CBC_SHA1;
+ mask |= LDAP_REALM_DEFENCTYPE;
+ printf("Default enctype not specified: \"des3-cbc-sha1\" "
+ "will be added as the default enctype and to the "
+ "list of supported enctypes.\n");
+
+ /* Now, add this to the list of supported enctypes. The
+ * duplicate values will be removed in DAL-LDAP
+ */
+ if (mask & LDAP_REALM_SUPPENCTYPE) {
+ for (i=0; rparams->suppenctypes[i] != END_OF_LIST; i++)
+ ;
+ assert (i < END_OF_LIST - 1);
+ rparams->suppenctypes[i] = ENCTYPE_DES3_CBC_SHA1;
+ rparams->suppenctypes[i + 1] = END_OF_LIST;
+ }
+ }
+
+ if ( !(mask & LDAP_REALM_DEFSALTTYPE) && (rparams != NULL)) {
+ rparams->defsalttype = KRB5_KDB_SALTTYPE_NORMAL;
+ mask |= LDAP_REALM_DEFSALTTYPE;
+ printf("Default salttype not specified: \"normal\" will be "
+ "added as the default salttype and to the list of "
+ "supported salttypes.\n");
+
+ /* Now, add this to the list of supported salttypes. The
+ * duplicate values will be removed in DAL-LDAP
+ */
+ if (mask & LDAP_REALM_SUPPSALTTYPE) {
+ for (i=0; rparams->suppsalttypes[i] != END_OF_LIST; i++)
+ ;
+ assert (i < END_OF_LIST - 1);
+ rparams->suppsalttypes[i] = KRB5_KDB_SALTTYPE_NORMAL;
+ rparams->suppsalttypes[i + 1] = END_OF_LIST;
+ }
+ }
+
+ rblock.max_life = global_params.max_life;
+ rblock.max_rlife = global_params.max_rlife;
+ rblock.expiration = global_params.expiration;
+ rblock.flags = global_params.flags;
+ rblock.nkslist = global_params.num_keysalts;
+ rblock.kslist = global_params.keysalts;
+
+ krb5_princ_set_realm_data(util_context, &db_create_princ, global_params.realm);
+ krb5_princ_set_realm_length(util_context, &db_create_princ, strlen(global_params.realm));
+
+ printf("Initializing database for realm '%s'\n", global_params.realm);
+
+ if (!mkey_password) {
+ unsigned int pw_size;
+ printf("You will be prompted for the database Master Password.\n");
+ printf("It is important that you NOT FORGET this password.\n");
+ fflush(stdout);
+
+ pw_size = sizeof (pw_str);
+ memset(pw_str, 0, pw_size);
+
+ retval = krb5_read_password(util_context, KRB5_KDC_MKEY_1, KRB5_KDC_MKEY_2,
+ pw_str, &pw_size);
+ if (retval) {
+ com_err(argv[0], retval, "while reading master key from keyboard");
+ goto err_nomsg;
+ }
+ mkey_password = pw_str;
+ }
+
+ rparams->mkey.enctype = global_params.enctype;
+ /* We are sure that 'mkey_password' is a regular string ... */
+ rparams->mkey.length = strlen(mkey_password) + 1;
+ rparams->mkey.contents = (krb5_octet *)strdup(mkey_password);
+ if (rparams->mkey.contents == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ rparams->realm_name = strdup(global_params.realm);
+ if (rparams->realm_name == NULL) {
+ retval = ENOMEM;
+ com_err(argv[0], ENOMEM, "while creating realm '%s'",
+ global_params.realm);
+ goto err_nomsg;
+ }
+
+ dal_handle = (kdb5_dal_handle *) util_context->db_context;
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+ if (!ldap_context) {
+ retval = EINVAL;
+ goto cleanup;
+ }
+
+ /* read the kerberos container */
+ if ((retval=krb5_ldap_read_krbcontainer_params (util_context,
+ &(ldap_context->krbcontainer))) == KRB5_KDB_NOENTRY) {
+ /* Prompt the user for entering the DN of Kerberos container */
+ char krb_location[MAX_KRB_CONTAINER_LEN];
+ krb5_ldap_krbcontainer_params kparams;
+ int krb_location_len = 0;
+ memset(&kparams, 0, sizeof(kparams));
+
+ /* Read the kerberos container location from configuration file */
+ if (ldap_context->conf_section) {
+ if ((retval=profile_get_string(util_context->profile,
+ KDB_MODULE_SECTION, ldap_context->conf_section,
+ "ldap_kerberos_container_dn", NULL,
+ &kparams.DN)) != 0) {
+ goto cleanup;
+ }
+ }
+ if (kparams.DN == NULL) {
+ if ((retval=profile_get_string(util_context->profile,
+ KDB_MODULE_DEF_SECTION,
+ "ldap_kerberos_container_dn", NULL,
+ NULL, &kparams.DN)) != 0) {
+ goto cleanup;
+ }
+ }
+
+ printf("\nKerberos container is missing. Creating now...\n");
+ if (kparams.DN == NULL) {
+#ifdef HAVE_EDIRECTORY
+ printf("Enter DN of Kerberos container [cn=Kerberos,cn=Security]: ");
+#else
+ printf("Enter DN of Kerberos container: ");
+#endif
+ if (fgets(krb_location, MAX_KRB_CONTAINER_LEN, stdin) != NULL) {
+ /* Remove the newline character at the end */
+ krb_location_len = strlen(krb_location);
+ if ((krb_location[krb_location_len - 1] == '\n') ||
+ (krb_location[krb_location_len - 1] == '\r')) {
+ krb_location[krb_location_len - 1] = '\0';
+ krb_location_len--;
+ }
+ /* If the user has not given any input, take the default location */
+ else if (krb_location[0] == '\0')
+ kparams.DN = NULL;
+ else
+ kparams.DN = krb_location;
+ }
+ else
+ kparams.DN = NULL;
+ }
+
+ /* create the kerberos container */
+ retval = krb5_ldap_create_krbcontainer(util_context,
+ ((kparams.DN != NULL) ? &kparams : NULL));
+ if (retval)
+ goto cleanup;
+
+ retval = krb5_ldap_read_krbcontainer_params(util_context,
+ &(ldap_context->krbcontainer));
+ if (retval) {
+ com_err(argv[0], retval, "while reading kerberos container information");
+ goto cleanup;
+ }
+ }
+ else if (retval) {
+ com_err(argv[0], retval, "while reading kerberos container information");
+ goto cleanup;
+ }
+
+ if ((retval = krb5_ldap_create_realm(util_context,
+ /* global_params.realm, */ rparams, mask))) {
+ goto cleanup;
+ }
+
+ /* We just created the Realm container. Here starts our transaction tracking */
+ realm_obj_created = TRUE;
+
+ if ((retval = krb5_ldap_read_realm_params(util_context,
+ global_params.realm,
+ &(ldap_context->lrparams),
+ &mask))) {
+ com_err(argv[0], retval, "while reading information of realm '%s'",
+ global_params.realm);
+ goto err_nomsg;
+ }
+ ldap_context->lrparams->realm_name = strdup(global_params.realm);
+ if (ldap_context->lrparams->realm_name == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ /* assemble & parse the master key name */
+ if ((retval = krb5_db_setup_mkey_name(util_context,
+ global_params.mkey_name,
+ global_params.realm,
+ 0, &master_princ))) {
+ com_err(argv[0], retval, "while setting up master key name");
+ goto err_nomsg;
+ }
+
+ /* Obtain master key from master password */
+ {
+ krb5_data master_salt, pwd;
+
+ pwd.data = mkey_password;
+ pwd.length = strlen(mkey_password);
+ retval = krb5_principal2salt(util_context, master_princ, &master_salt);
+ if (retval) {
+ com_err(argv[0], retval, "while calculating master key salt");
+ goto err_nomsg;
+ }
+
+ retval = krb5_c_string_to_key(util_context, rparams->mkey.enctype,
+ &pwd, &master_salt, &master_keyblock);
+
+ if (master_salt.data)
+ free(master_salt.data);
+
+ if (retval) {
+ com_err(argv[0], retval, "while transforming master key from password");
+ goto err_nomsg;
+ }
+
+ }
+
+ rblock.key = &master_keyblock;
+ ldap_context->lrparams->mkey = master_keyblock;
+ ldap_context->lrparams->mkey.contents = (krb5_octet *) malloc
+ (master_keyblock.length);
+ if (ldap_context->lrparams->mkey.contents == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ memcpy (ldap_context->lrparams->mkey.contents, master_keyblock.contents,
+ master_keyblock.length);
+
+ /* Create special principals inside the realm subtree */
+ {
+ char princ_name[MAX_PRINC_SIZE], localname[MAXHOSTNAMELEN];
+ struct hostent *hp = NULL;
+ krb5_principal_data tgt_princ = {
+ 0, /* magic number */
+ {0, 0, 0}, /* krb5_data realm */
+ tgt_princ_entries, /* krb5_data *data */
+ 2, /* int length */
+ KRB5_NT_SRV_INST /* int type */
+ };
+ krb5_principal p;
+
+ krb5_princ_set_realm_data(util_context, &tgt_princ, global_params.realm);
+ krb5_princ_set_realm_length(util_context, &tgt_princ, strlen(global_params.realm));
+ krb5_princ_component(util_context, &tgt_princ,1)->data = global_params.realm;
+ krb5_princ_component(util_context, &tgt_princ,1)->length = strlen(global_params.realm);
+
+ oldsubtree = ldap_context->lrparams->subtree;
+ ldap_context->lrparams->subtree = strdup(ldap_context->lrparams->realmdn);
+ if (ldap_context->lrparams->subtree == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ /* Create 'K/M' ... */
+ rblock.flags |= KRB5_KDB_DISALLOW_ALL_TIX;
+ if ((retval = kdb_ldap_create_principal(util_context, master_princ, MASTER_KEY, &rblock))) {
+ com_err(argv[0], retval, "while adding entries to the database");
+ goto err_nomsg;
+ }
+
+ /* Create 'krbtgt' ... */
+ rblock.flags = 0; /* reset the flags */
+ if ((retval = kdb_ldap_create_principal(util_context, &tgt_princ, TGT_KEY, &rblock))) {
+ com_err(argv[0], retval, "while adding entries to the database");
+ goto err_nomsg;
+ }
+
+ /* Create 'kadmin/admin' ... */
+ snprintf(princ_name, sizeof(princ_name), "%s@%s", KADM5_ADMIN_SERVICE, global_params.realm);
+ if ((retval = krb5_parse_name(util_context, princ_name, &p))) {
+ com_err(argv[0], retval, "while adding entries to the database");
+ goto err_nomsg;
+ }
+ rblock.flags = KRB5_KDB_DISALLOW_TGT_BASED;
+ if ((retval = kdb_ldap_create_principal(util_context, p, TGT_KEY, &rblock))) {
+ krb5_free_principal(util_context, p);
+ com_err(argv[0], retval, "while adding entries to the database");
+ goto err_nomsg;
+ }
+ krb5_free_principal(util_context, p);
+
+ /* Create 'kadmin/changepw' ... */
+ snprintf(princ_name, sizeof(princ_name), "%s@%s", KADM5_CHANGEPW_SERVICE, global_params.realm);
+ if ((retval = krb5_parse_name(util_context, princ_name, &p))) {
+ com_err(argv[0], retval, "while adding entries to the database");
+ goto err_nomsg;
+ }
+ rblock.flags = KRB5_KDB_DISALLOW_TGT_BASED |
+ KRB5_KDB_PWCHANGE_SERVICE;
+ if ((retval = kdb_ldap_create_principal(util_context, p, TGT_KEY, &rblock))) {
+ krb5_free_principal(util_context, p);
+ com_err(argv[0], retval, "while adding entries to the database");
+ goto err_nomsg;
+ }
+ krb5_free_principal(util_context, p);
+
+ /* Create 'kadmin/history' ... */
+ snprintf(princ_name, sizeof(princ_name), "%s@%s", KADM5_HIST_PRINCIPAL, global_params.realm);
+ if ((retval = krb5_parse_name(util_context, princ_name, &p))) {
+ com_err(argv[0], retval, "while adding entries to the database");
+ goto err_nomsg;
+ }
+ rblock.flags = 0;
+ if ((retval = kdb_ldap_create_principal(util_context, p, TGT_KEY, &rblock))) {
+ krb5_free_principal(util_context, p);
+ com_err(argv[0], retval, "while adding entries to the database");
+ goto err_nomsg;
+ }
+ krb5_free_principal(util_context, p);
+
+ /* Create 'kadmin/<hostname>' ... */
+ if (gethostname(localname, sizeof(localname))) {
+ retval = errno;
+ com_err(argv[0], retval, "gethostname, while adding entries to the database");
+ goto err_nomsg;
+ }
+ hp = gethostbyname(localname);
+ if (hp == NULL) {
+ retval = errno;
+ com_err(argv[0], retval, "gethostbyname, while adding entries to the database");
+ goto err_nomsg;
+ }
+ assert (sizeof(princ_name) >= MAXHOSTNAMELEN + 8);
+ /* snprintf(princ_name, MAXHOSTNAMELEN + 8, "kadmin/%s", hp->h_name); */
+ snprintf(princ_name, sizeof(princ_name), "kadmin/%s@%s", hp->h_name, global_params.realm);
+ if ((retval = krb5_parse_name(util_context, princ_name, &p))) {
+ com_err(argv[0], retval, "while adding entries to the database");
+ goto err_nomsg;
+ }
+
+ rblock.flags = KRB5_KDB_DISALLOW_TGT_BASED;
+ if ((retval = kdb_ldap_create_principal(util_context, p, TGT_KEY, &rblock))) {
+ krb5_free_principal(util_context, p);
+ com_err(argv[0], retval, "while adding entries to the database");
+ goto err_nomsg;
+ }
+ krb5_free_principal(util_context, p);
+
+ if (ldap_context->lrparams->subtree != NULL)
+ free(ldap_context->lrparams->subtree);
+ ldap_context->lrparams->subtree = oldsubtree;
+ oldsubtree = NULL;
+ }
+
+#ifdef HAVE_EDIRECTORY
+ if( (mask & LDAP_REALM_KDCSERVERS) || (mask & LDAP_REALM_ADMINSERVERS) ||
+ (mask & LDAP_REALM_PASSWDSERVERS) ) {
+
+ printf("Changing rights for the service object. Please wait ... ");
+ fflush(stdout);
+
+ rightsmask =0;
+ rightsmask |= LDAP_REALM_RIGHTS;
+ rightsmask |= LDAP_SUBTREE_RIGHTS;
+ if ( (rparams != NULL) && (rparams->kdcservers != NULL) ) {
+ for ( i=0; (rparams->kdcservers[i] != NULL); i++) {
+ if((retval=krb5_ldap_add_service_rights( util_context,
+ LDAP_KDC_SERVICE, rparams->kdcservers[i],
+ rparams->realm_name, rparams->subtree, rightsmask )) != 0) {
+ printf("failed\n");
+ com_err(argv[0], retval, "while assigning rights to '%s'",
+ rparams->realm_name);
+ goto err_nomsg;
+ }
+ }
+ }
+
+ rightsmask = 0;
+ rightsmask |= LDAP_REALM_RIGHTS;
+ rightsmask |= LDAP_SUBTREE_RIGHTS;
+ if ( (rparams != NULL) && (rparams->adminservers != NULL) ) {
+ for ( i=0; (rparams->adminservers[i] != NULL); i++) {
+ if((retval=krb5_ldap_add_service_rights( util_context,
+ LDAP_ADMIN_SERVICE, rparams->adminservers[i],
+ rparams->realm_name, rparams->subtree, rightsmask )) != 0) {
+ printf("failed\n");
+ com_err(argv[0], retval, "while assigning rights to '%s'",
+ rparams->realm_name);
+ goto err_nomsg;
+ }
+ }
+ }
+
+ rightsmask = 0;
+ rightsmask |= LDAP_REALM_RIGHTS;
+ rightsmask |= LDAP_SUBTREE_RIGHTS;
+ if( (rparams != NULL) && (rparams->passwdservers != NULL) ) {
+ for ( i=0; (rparams->passwdservers[i] != NULL); i++) {
+ if((retval=krb5_ldap_add_service_rights( util_context,
+ LDAP_PASSWD_SERVICE, rparams->passwdservers[i],
+ rparams->realm_name, rparams->subtree, rightsmask )) != 0) {
+ printf("failed\n");
+ com_err(argv[0], retval, "while assigning rights to '%s'",
+ rparams->realm_name);
+ goto err_nomsg;
+ }
+ }
+ }
+
+ printf("done\n");
+ }
+#endif
+ /* The Realm creation is completed. Here is the end of transaction */
+ create_complete = TRUE;
+
+ /* Stash the master key only if '-s' option is specified */
+ if (do_stash || global_params.mask & KADM5_CONFIG_STASH_FILE) {
+ retval = krb5_def_store_mkey(util_context,
+ global_params.stash_file,
+ master_princ,
+ &master_keyblock, NULL);
+ if (retval) {
+ com_err(argv[0], errno, "while storing key");
+ printf("Warning: couldn't stash master key.\n");
+ }
+ }
+
+ goto cleanup;
+
+
+err_usage:
+ print_usage = TRUE;
+
+err_nomsg:
+ no_msg = TRUE;
+
+cleanup:
+ /* If the Realm creation is not complete, do the roll-back here */
+ if ((realm_obj_created) && (!create_complete))
+ krb5_ldap_delete_realm(util_context, global_params.realm);
+
+ if (rparams)
+ krb5_ldap_free_realm_params(rparams);
+
+ memset (pw_str, 0, sizeof (pw_str));
+
+ if (oldsubtree)
+ ldap_context->lrparams->subtree = oldsubtree;
+
+ if (print_usage)
+ db_usage(CREATE_REALM);
+
+ if (retval) {
+ if (!no_msg) {
+ com_err(argv[0], retval, "while creating realm '%s'",
+ global_params.realm);
+ }
+ exit_status++;
+ }
+
+ return;
+}
+
+
+/*
+ * This function will modify the attributes of a given realm object
+ */
+void kdb5_ldap_modify(argc, argv)
+ int argc;
+ char *argv[];
+{
+ krb5_error_code retval;
+ krb5_ldap_realm_params *rparams = NULL;
+ krb5_boolean print_usage = FALSE;
+ krb5_boolean no_msg = FALSE;
+ kdb5_dal_handle *dal_handle = NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ int i = 0, j = 0;
+ int mask = 0, rmask = 0, ret_mask = 0;
+ char *list[MAX_LIST_ENTRIES];
+ int tlist[MAX_LIST_ENTRIES] = {0};
+ int newenctypes = 0, newsalttypes = 0;
+ int existing_entries = 0, list_entries = 0;
+#ifdef HAVE_EDIRECTORY
+ int newkdcdn = 0, newadmindn = 0, newpwddn = 0;
+ char **tempstr = NULL;
+ char **oldkdcdns = NULL;
+ char **oldadmindns = NULL;
+ char **oldpwddns = NULL;
+ char **newkdcdns = NULL;
+ char **newadmindns = NULL;
+ char **newpwddns = NULL;
+ char *oldsubtree = NULL;
+ int rightsmask = 0;
+ int subtree_changed = 0;
+#endif
+ char *me = argv[0];
+
+ dal_handle = (kdb5_dal_handle *) util_context->db_context;
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+ if (!(ldap_context)) {
+ retval = EINVAL;
+ goto cleanup;
+ }
+
+ if((retval = krb5_ldap_read_krbcontainer_params(util_context,
+ &(ldap_context->krbcontainer)))) {
+ com_err(argv[0], retval, "while reading Kerberos container information");
+ goto err_nomsg;
+ }
+
+ retval = krb5_ldap_read_realm_params(util_context,
+ global_params.realm, &rparams, &rmask);
+ if (retval)
+ goto cleanup;
+
+ /* Parse the arguments */
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-subtree")) {
+ if (++i > argc-1)
+ goto err_usage;
+
+ if (rmask & LDAP_REALM_SUBTREE) {
+ if( rparams->subtree ) {
+#ifdef HAVE_EDIRECTORY
+ oldsubtree = strdup(rparams->subtree);
+ if( oldsubtree == NULL ) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+#endif
+ free(rparams->subtree);
+ }
+ }
+ rparams->subtree = strdup(argv[i]);
+ if (rparams->subtree == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ mask |= LDAP_REALM_SUBTREE;
+ }
+ else if (!strcmp(argv[i], "-sscope")) {
+ if (++i > argc-1)
+ goto err_usage;
+ /* Possible values for search scope are
+ * one (or 1) and sub (or 2)
+ */
+ if (strcasecmp(argv[i], "one") == 0) {
+ rparams->search_scope = 1;
+ }
+ else if (strcasecmp(argv[i], "sub") == 0) {
+ rparams->search_scope = 2;
+ }
+ else {
+ rparams->search_scope = atoi(argv[i]);
+ if ((rparams->search_scope != 1) &&
+ (rparams->search_scope != 2)) {
+ retval = EINVAL;
+ com_err(argv[0], retval,
+ "specified for search scope while modifying information of realm '%s'",
+ global_params.realm);
+ goto err_nomsg;
+ }
+ }
+ mask |= LDAP_REALM_SEARCHSCOPE;
+ }
+#ifdef HAVE_EDIRECTORY
+ else if (!strcmp(argv[i], "-kdcdn")) {
+ if (++i > argc-1)
+ goto err_usage;
+
+ if ((rmask & LDAP_REALM_KDCSERVERS) && (rparams->kdcservers)) {
+ if (!oldkdcdns) {
+ /* Store the old kdc dns list for removing rights */
+ oldkdcdns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (oldkdcdns == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ for (j=0; rparams->kdcservers[j] != NULL; j++) {
+ oldkdcdns[j] = strdup(rparams->kdcservers[j]);
+ if (oldkdcdns[j] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ oldkdcdns[j] = NULL;
+ }
+
+ krb5_free_list_entries(rparams->kdcservers);
+ free(rparams->kdcservers);
+ }
+
+ rparams->kdcservers = (char **)malloc(
+ sizeof(char *) * MAX_LIST_ENTRIES);
+ if (rparams->kdcservers == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ memset(rparams->kdcservers, 0, sizeof(char *)*MAX_LIST_ENTRIES);
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
+ rparams->kdcservers))) {
+ goto cleanup;
+ }
+ mask |= LDAP_REALM_KDCSERVERS;
+ /* Going to replace the existing value by this new value. Hence
+ * setting flag indicating that add or clear options will be ignored
+ */
+ newkdcdn = 1;
+ }
+ else if (!strcmp(argv[i], "-clearkdcdn")) {
+ if (++i > argc-1)
+ goto err_usage;
+ if ((!newkdcdn) && (rmask & LDAP_REALM_KDCSERVERS) && (rparams->kdcservers)) {
+ if (!oldkdcdns) {
+ /* Store the old kdc dns list for removing rights */
+ oldkdcdns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (oldkdcdns == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ for (j=0; rparams->kdcservers[j] != NULL; j++) {
+ oldkdcdns[j] = strdup(rparams->kdcservers[j]);
+ if (oldkdcdns[j] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ oldkdcdns[j] = NULL;
+ }
+
+ memset(list, 0, sizeof(char *) * MAX_LIST_ENTRIES);
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) {
+ goto cleanup;
+ }
+ list_modify_str_array(&rparams->kdcservers, (const char **)list,
+ LIST_MODE_DELETE);
+ mask |= LDAP_REALM_KDCSERVERS;
+ krb5_free_list_entries(list);
+ }
+ }
+ else if (!strcmp(argv[i], "-addkdcdn")) {
+ if (++i > argc-1)
+ goto err_usage;
+ if (!newkdcdn) {
+ if ((rmask & LDAP_REALM_KDCSERVERS) && (rparams->kdcservers) && (!oldkdcdns)) {
+ /* Store the old kdc dns list for removing rights */
+ oldkdcdns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (oldkdcdns == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ for (j = 0; rparams->kdcservers[j] != NULL; j++) {
+ oldkdcdns[j] = strdup(rparams->kdcservers[j]);
+ if (oldkdcdns[j] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ oldkdcdns[j] = NULL;
+ }
+
+ memset(list, 0, sizeof(char *) * MAX_LIST_ENTRIES);
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) {
+ goto cleanup;
+ }
+ existing_entries = list_count_str_array(rparams->kdcservers);
+ list_entries = list_count_str_array(list);
+ if (rmask & LDAP_REALM_KDCSERVERS) {
+ tempstr = (char **)realloc(
+ rparams->kdcservers,
+ sizeof(char *) * (existing_entries+list_entries+1));
+ if (tempstr == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ rparams->kdcservers = tempstr;
+ }
+ else {
+ rparams->kdcservers = (char **)malloc(sizeof(char *) * (list_entries+1));
+ if (rparams->kdcservers == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ memset(rparams->kdcservers, 0, sizeof(char *) * (list_entries+1));
+ }
+ list_modify_str_array(&rparams->kdcservers, (const char **)list,
+ LIST_MODE_ADD);
+ mask |= LDAP_REALM_KDCSERVERS;
+ }
+ }
+ else if (!strcmp(argv[i], "-admindn")) {
+ if (++i > argc-1)
+ goto err_usage;
+
+ if ((rmask & LDAP_REALM_ADMINSERVERS) && (rparams->adminservers)) {
+ if (!oldadmindns) {
+ /* Store the old admin dns list for removing rights */
+ oldadmindns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (oldadmindns == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ for (j=0; rparams->adminservers[j] != NULL; j++) {
+ oldadmindns[j] = strdup(rparams->adminservers[j]);
+ if (oldadmindns[j] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ oldadmindns[j] = NULL;
+ }
+
+ krb5_free_list_entries(rparams->adminservers);
+ free(rparams->adminservers);
+ }
+
+ rparams->adminservers = (char **)malloc(
+ sizeof(char *) * MAX_LIST_ENTRIES);
+ if (rparams->adminservers == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ memset(rparams->adminservers, 0, sizeof(char *)*MAX_LIST_ENTRIES);
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
+ rparams->adminservers))) {
+ goto cleanup;
+ }
+ mask |= LDAP_REALM_ADMINSERVERS;
+ /* Going to replace the existing value by this new value. Hence
+ * setting flag indicating that add or clear options will be ignored
+ */
+ newadmindn = 1;
+ }
+ else if (!strcmp(argv[i], "-clearadmindn")) {
+ if (++i > argc-1)
+ goto err_usage;
+
+ if ((!newadmindn) && (rmask & LDAP_REALM_ADMINSERVERS) && (rparams->adminservers)) {
+ if (!oldadmindns) {
+ /* Store the old admin dns list for removing rights */
+ oldadmindns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (oldadmindns == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ for (j=0; rparams->adminservers[j] != NULL; j++) {
+ oldadmindns[j] = strdup(rparams->adminservers[j]);
+ if (oldadmindns[j] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ oldadmindns[j] = NULL;
+ }
+
+ memset(list, 0, sizeof(char *) * MAX_LIST_ENTRIES);
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) {
+ goto cleanup;
+ }
+ list_modify_str_array(&rparams->adminservers, (const char **)list,
+ LIST_MODE_DELETE);
+ mask |= LDAP_REALM_ADMINSERVERS;
+ krb5_free_list_entries(list);
+ }
+ }
+ else if (!strcmp(argv[i], "-addadmindn")) {
+ if (++i > argc-1)
+ goto err_usage;
+ if (!newadmindn) {
+ if ((rmask & LDAP_REALM_ADMINSERVERS) && (rparams->adminservers) && (!oldadmindns)) {
+ /* Store the old admin dns list for removing rights */
+ oldadmindns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (oldadmindns == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ for (j=0; rparams->adminservers[j] != NULL; j++) {
+ oldadmindns[j] = strdup(rparams->adminservers[j]);
+ if (oldadmindns[j] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ oldadmindns[j] = NULL;
+ }
+
+ memset(list, 0, sizeof(char *) * MAX_LIST_ENTRIES);
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) {
+ goto cleanup;
+ }
+ existing_entries = list_count_str_array(rparams->adminservers);
+ list_entries = list_count_str_array(list);
+ if (rmask & LDAP_REALM_ADMINSERVERS) {
+ tempstr = (char **)realloc(
+ rparams->adminservers,
+ sizeof(char *) * (existing_entries+list_entries+1));
+ if (tempstr == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ rparams->adminservers = tempstr;
+ }
+ else {
+ rparams->adminservers = (char **)malloc(sizeof(char *) * (list_entries+1));
+ if (rparams->adminservers == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ memset(rparams->adminservers, 0, sizeof(char *) * (list_entries+1));
+ }
+ list_modify_str_array(&rparams->adminservers, (const char **)list,
+ LIST_MODE_ADD);
+ mask |= LDAP_REALM_ADMINSERVERS;
+ }
+ }
+ else if (!strcmp(argv[i], "-pwddn")) {
+ if (++i > argc-1)
+ goto err_usage;
+
+ if ((rmask & LDAP_REALM_PASSWDSERVERS) && (rparams->passwdservers)) {
+ if (!oldpwddns) {
+ /* Store the old pwd dns list for removing rights */
+ oldpwddns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (oldpwddns == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ for (j=0; rparams->passwdservers[j] != NULL; j++) {
+ oldpwddns[j] = strdup(rparams->passwdservers[j]);
+ if (oldpwddns[j] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ oldpwddns[j] = NULL;
+ }
+
+ krb5_free_list_entries(rparams->passwdservers);
+ free(rparams->passwdservers);
+ }
+
+ rparams->passwdservers = (char **)malloc(
+ sizeof(char *) * MAX_LIST_ENTRIES);
+ if (rparams->passwdservers == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ memset(rparams->passwdservers, 0, sizeof(char *)*MAX_LIST_ENTRIES);
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
+ rparams->passwdservers))) {
+ goto cleanup;
+ }
+ mask |= LDAP_REALM_PASSWDSERVERS;
+ /* Going to replace the existing value by this new value. Hence
+ * setting flag indicating that add or clear options will be ignored
+ */
+ newpwddn = 1;
+ }
+ else if (!strcmp(argv[i], "-clearpwddn")) {
+ if (++i > argc-1)
+ goto err_usage;
+
+ if ((!newpwddn) && (rmask & LDAP_REALM_PASSWDSERVERS) && (rparams->passwdservers)) {
+ if (!oldpwddns) {
+ /* Store the old pwd dns list for removing rights */
+ oldpwddns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (oldpwddns == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ for (j=0; rparams->passwdservers[j] != NULL; j++) {
+ oldpwddns[j] = strdup(rparams->passwdservers[j]);
+ if (oldpwddns[j] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ oldpwddns[j] = NULL;
+ }
+
+ memset(list, 0, sizeof(char *) * MAX_LIST_ENTRIES);
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) {
+ goto cleanup;
+ }
+ list_modify_str_array(&rparams->passwdservers, (const char**)list,
+ LIST_MODE_DELETE);
+ mask |= LDAP_REALM_PASSWDSERVERS;
+ krb5_free_list_entries(list);
+ }
+ }
+ else if (!strcmp(argv[i], "-addpwddn")) {
+ if (++i > argc-1)
+ goto err_usage;
+ if (!newpwddn) {
+ if ((rmask & LDAP_REALM_PASSWDSERVERS) && (rparams->passwdservers) && (!oldpwddns)) {
+ /* Store the old pwd dns list for removing rights */
+ oldpwddns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (oldpwddns == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ for (j=0; rparams->passwdservers[j] != NULL; j++) {
+ oldpwddns[j] = strdup(rparams->passwdservers[j]);
+ if (oldpwddns[j] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ oldpwddns[j] = NULL;
+ }
+
+ memset(list, 0, sizeof(char *) * MAX_LIST_ENTRIES);
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) {
+ goto cleanup;
+ }
+ existing_entries = list_count_str_array(rparams->passwdservers);
+ list_entries = list_count_str_array(list);
+ if (rmask & LDAP_REALM_PASSWDSERVERS) {
+ tempstr = (char **)realloc(
+ rparams->passwdservers,
+ sizeof(char *) * (existing_entries+list_entries+1));
+ if (tempstr == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ rparams->passwdservers = tempstr;
+ }
+ else {
+ rparams->passwdservers = (char **)malloc(sizeof(char *) * (list_entries+1));
+ if (rparams->passwdservers == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ memset(rparams->passwdservers, 0, sizeof(char *) * (list_entries+1));
+ }
+ list_modify_str_array(&rparams->passwdservers, (const char**)list,
+ LIST_MODE_ADD);
+ mask |= LDAP_REALM_PASSWDSERVERS;
+ }
+ }
+#endif
+ else if (!strcmp(argv[i], "-enctypes")) {
+ if (++i > argc-1)
+ goto err_usage;
+ if (rmask & LDAP_REALM_SUPPENCTYPE)
+ free(rparams->suppenctypes);
+ rparams->suppenctypes = (krb5_enctype *)malloc(
+ sizeof(krb5_enctype) * MAX_LIST_ENTRIES);
+ if (rparams->suppenctypes == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list)))
+ goto cleanup;
+
+ for(j = 0; list[j] != NULL; j++) {
+ if ((retval = krb5_string_to_enctype(list[j],
+ &rparams->suppenctypes[j]))) {
+ com_err(argv[0], retval, "'%s' specified for enctypes, "
+ "while modifying information of realm '%s'",
+ list[j], global_params.realm);
+ goto err_nomsg;
+ }
+ }
+ rparams->suppenctypes[j] = END_OF_LIST;
+ qsort(rparams->suppenctypes, (size_t)j, sizeof(krb5_enctype),
+ compare_int);
+ mask |= LDAP_REALM_SUPPENCTYPE;
+ /* Going to replace the existing value by this new value. Hence
+ * setting flag indicating that add or clear options will be ignored
+ */
+ newenctypes = 1;
+ krb5_free_list_entries(list);
+ }
+ else if (!strcmp(argv[i], "-clearenctypes")) {
+ if (++i > argc-1)
+ goto err_usage;
+ if ((!newenctypes) && (rparams->suppenctypes != NULL)) {
+
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list)))
+ goto cleanup;
+
+ memset(tlist, END_OF_LIST, sizeof(int) * MAX_LIST_ENTRIES);
+ for(j = 0; list[j] != NULL; j++) {
+ if ((retval = krb5_string_to_enctype(list[j], &tlist[j]))) {
+ com_err(argv[0], retval, "'%s' specified for clearenctypes, "
+ "while modifying information of realm '%s'",
+ list[j], global_params.realm);
+ goto err_nomsg;
+ }
+ }
+ tlist[j] = END_OF_LIST;
+ j = list_modify_int_array(rparams->suppenctypes, (const int*)tlist,
+ LIST_MODE_DELETE);
+ qsort(rparams->suppenctypes, (size_t)j, sizeof(krb5_enctype),
+ compare_int);
+ mask |= LDAP_REALM_SUPPENCTYPE;
+ krb5_free_list_entries(list);
+ }
+ }
+ else if (!strcmp(argv[i], "-addenctypes")) {
+ if (++i > argc-1)
+ goto err_usage;
+ if (!newenctypes) {
+ int *tmp;
+
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list)))
+ goto cleanup;
+
+ existing_entries = list_count_int_array(rparams->suppenctypes);
+ list_entries = list_count_str_array(list);
+
+ tmp = (krb5_enctype *) realloc (rparams->suppenctypes,
+ sizeof(krb5_enctype) * (existing_entries+list_entries+1));
+ if (tmp == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ rparams->suppenctypes = tmp;
+
+ for(j = 0; list[j] != NULL; j++) {
+ if ((retval = krb5_string_to_enctype(list[j], &tlist[j]))) {
+ com_err(argv[0], retval, "'%s' specified for addenctypes, "
+ "while modifying information of realm '%s'",
+ list[j], global_params.realm);
+ goto err_nomsg;
+ }
+ }
+ tlist[j] = END_OF_LIST;
+
+ j = list_modify_int_array(rparams->suppenctypes, (const int*)tlist,
+ LIST_MODE_ADD);
+ qsort(rparams->suppenctypes, (size_t)j, sizeof(krb5_enctype),
+ compare_int);
+ mask |= LDAP_REALM_SUPPENCTYPE;
+ krb5_free_list_entries(list);
+ }
+ }
+ else if (!strcmp(argv[i], "-defenctype")) {
+ if (++i > argc-1)
+ goto err_usage;
+ if ((retval = krb5_string_to_enctype(argv[i],
+ &rparams->defenctype))) {
+ com_err(argv[0], retval, "'%s' specified for defenctype, "
+ "while modifying information of realm '%s'",
+ argv[i], global_params.realm);
+ goto err_nomsg;
+ }
+ mask |= LDAP_REALM_DEFENCTYPE;
+ }
+ else if (!strcmp(argv[i], "-salttypes")) {
+ if (++i > argc-1)
+ goto err_usage;
+ if (rmask & LDAP_REALM_SUPPSALTTYPE)
+ free(rparams->suppsalttypes);
+ rparams->suppsalttypes = (krb5_int32 *)malloc(
+ sizeof(krb5_int32) * MAX_LIST_ENTRIES);
+ if (rparams->suppsalttypes == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list)))
+ goto cleanup;
+
+ for(j = 0; list[j] != NULL; j++) {
+ if ((retval = krb5_string_to_salttype(list[j],
+ &rparams->suppsalttypes[j]))) {
+ com_err(argv[0], retval, "'%s' specified for salttypes, "
+ "while modifying information of realm '%s'",
+ list[j], global_params.realm);
+ goto err_nomsg;
+ }
+ }
+ rparams->suppsalttypes[j] = END_OF_LIST;
+ qsort(rparams->suppsalttypes, (size_t)j, sizeof(krb5_int32),
+ compare_int);
+ mask |= LDAP_REALM_SUPPSALTTYPE;
+ /* Going to replace the existing value by this new value. Hence
+ * setting flag indicating that add or clear options will be ignored
+ */
+ newsalttypes = 1;
+ krb5_free_list_entries(list);
+ }
+ else if (!strcmp(argv[i], "-clearsalttypes")) {
+ if (++i > argc-1)
+ goto err_usage;
+ if ((!newsalttypes) && (rparams->suppsalttypes != NULL)) {
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list)))
+ goto cleanup;
+
+ for(j = 0; list[j] != NULL; j++) {
+ if ((retval = krb5_string_to_salttype(list[j], &tlist[j]))) {
+ com_err(argv[0], retval, "'%s' specified for clearsalttypes, "
+ "while modifying information of realm '%s'",
+ list[j], global_params.realm);
+ goto err_nomsg;
+ }
+ }
+ tlist[j] = END_OF_LIST;
+ j = list_modify_int_array(rparams->suppsalttypes, (const int*)tlist,
+ LIST_MODE_DELETE);
+ qsort(rparams->suppsalttypes, (size_t)j, sizeof(krb5_int32),
+ compare_int);
+ mask |= LDAP_REALM_SUPPSALTTYPE;
+ krb5_free_list_entries(list);
+ }
+ }
+ else if (!strcmp(argv[i], "-addsalttypes")) {
+ if (++i > argc-1)
+ goto err_usage;
+ if (!newsalttypes) {
+ int *tmp;
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list)))
+ goto cleanup;
+
+ existing_entries = list_count_int_array(rparams->suppsalttypes);
+ list_entries = list_count_str_array(list);
+
+ tmp = (krb5_int32 *) realloc (rparams->suppsalttypes,
+ sizeof(krb5_int32) * (existing_entries+list_entries+1));
+ if (tmp == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ rparams->suppsalttypes = tmp;
+
+ for(j = 0; list[j] != NULL; j++) {
+ if ((retval = krb5_string_to_salttype(list[j], &tlist[j]))) {
+ com_err(argv[0], retval, "'%s' specified for addsalttypes, "
+ "while modifying information of realm '%s'",
+ list[j], global_params.realm);
+ goto err_nomsg;
+ }
+ }
+ tlist[j] = END_OF_LIST;
+ j = list_modify_int_array(rparams->suppsalttypes, (const int*)tlist,
+ LIST_MODE_ADD);
+ qsort(rparams->suppsalttypes, (size_t)j, sizeof(krb5_int32),
+ compare_int);
+ mask |= LDAP_REALM_SUPPSALTTYPE;
+ krb5_free_list_entries(list);
+ }
+ }
+ else if (!strcmp(argv[i], "-defsalttype")) {
+ if (++i > argc-1)
+ goto err_usage;
+ if ((retval = krb5_string_to_salttype(argv[i],
+ &rparams->defsalttype))) {
+ com_err(argv[0], retval, "'%s' specified for defsalttype, "
+ "while modifying information of realm '%s'",
+ argv[i], global_params.realm);
+ goto err_nomsg;
+ }
+ mask |= LDAP_REALM_DEFSALTTYPE;
+ }
+ else if ((ret_mask= get_ticket_policy(rparams,&i,argv,argc)) !=0)
+ {
+ mask|=ret_mask;
+ }
+ else {
+ printf("'%s' is an invalid option\n", argv[i]);
+ goto err_usage;
+ }
+ }
+
+ if ((retval = krb5_ldap_modify_realm(util_context,
+ /* global_params.realm, */ rparams, mask))) {
+ goto cleanup;
+ }
+
+#ifdef HAVE_EDIRECTORY
+ if( (mask & LDAP_REALM_SUBTREE) || (mask & LDAP_REALM_KDCSERVERS) ||
+ (mask & LDAP_REALM_ADMINSERVERS) || (mask & LDAP_REALM_PASSWDSERVERS)) {
+
+ printf("Changing rights for the service object. Please wait ... ");
+ fflush(stdout);
+
+ if( !(mask & LDAP_REALM_SUBTREE) ) {
+ if( rparams->subtree != NULL ) {
+ oldsubtree = strdup(rparams->subtree);
+ if( oldsubtree == NULL ) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ }
+
+ if( (mask & LDAP_REALM_SUBTREE) ) {
+ if( (oldsubtree && !rparams->subtree) ||
+ (!oldsubtree && rparams->subtree) ||
+ (strcmp( oldsubtree, rparams->subtree) != 0) ) {
+ subtree_changed = 1;
+ }
+ }
+
+ if( (mask & LDAP_REALM_SUBTREE) || (mask & LDAP_REALM_KDCSERVERS) ) {
+
+ newkdcdns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (newkdcdns == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ if ( (rparams != NULL) && (rparams->kdcservers != NULL) ) {
+ for (j=0; rparams->kdcservers[j]!= NULL; j++) {
+ newkdcdns[j] = strdup(rparams->kdcservers[j]);
+ if (newkdcdns[j] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ newkdcdns[j] = NULL;
+ }
+
+ if( !subtree_changed ) {
+ disjoint_members( oldkdcdns, newkdcdns);
+ }
+ else { /* Only the subtree was changed. Remove the rights on the old subtree. */
+ if (!(mask & LDAP_REALM_KDCSERVERS)) {
+
+ oldkdcdns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (oldkdcdns == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ if ( (rparams != NULL) && (rparams->kdcservers != NULL) ) {
+ for (j=0; rparams->kdcservers[j]!= NULL; j++) {
+ oldkdcdns[j] = strdup(rparams->kdcservers[j]);
+ if (oldkdcdns[j] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ oldkdcdns[j] = NULL;
+ }
+ }
+ }
+
+ rightsmask =0;
+ rightsmask |= LDAP_REALM_RIGHTS;
+ rightsmask |= LDAP_SUBTREE_RIGHTS;
+ /* Remove the rights on the old subtree */
+ if ( oldkdcdns ) {
+ for ( i=0; (oldkdcdns[i] != NULL); i++) {
+ if((retval=krb5_ldap_delete_service_rights(util_context,
+ LDAP_KDC_SERVICE, oldkdcdns[i],
+ rparams->realm_name, oldsubtree, rightsmask )) != 0) {
+ printf("failed\n");
+ com_err(argv[0], retval, "while assigning rights '%s'",
+ rparams->realm_name);
+ goto err_nomsg;
+ }
+ }
+ }
+
+ rightsmask =0;
+ rightsmask |= LDAP_REALM_RIGHTS;
+ rightsmask |= LDAP_SUBTREE_RIGHTS;
+ if ( newkdcdns ) {
+ for ( i=0; (newkdcdns[i] != NULL); i++) {
+
+ if((retval=krb5_ldap_add_service_rights(util_context,
+ LDAP_KDC_SERVICE, newkdcdns[i], rparams->realm_name,
+ rparams->subtree, rightsmask )) != 0) {
+ printf("failed\n");
+ com_err(argv[0], retval, "while assigning rights to '%s'",
+ rparams->realm_name);
+ goto err_nomsg;
+ }
+ }
+ }
+ }
+
+ if( (mask & LDAP_REALM_SUBTREE) || (mask & LDAP_REALM_ADMINSERVERS) ) {
+
+ newadmindns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (newadmindns == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ if ( (rparams != NULL) && (rparams->adminservers != NULL) ) {
+ for (j=0; rparams->adminservers[j]!= NULL; j++) {
+ newadmindns[j] = strdup(rparams->adminservers[j]);
+ if (newadmindns[j] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ newadmindns[j] = NULL;
+ }
+
+ if( !subtree_changed ) {
+ disjoint_members( oldadmindns, newadmindns);
+ }
+ else { /* Only the subtree was changed. Remove the rights on the old subtree. */
+ if (!(mask & LDAP_REALM_ADMINSERVERS)) {
+
+ oldadmindns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (oldadmindns == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ if ( (rparams != NULL) && (rparams->adminservers != NULL) ) {
+ for (j=0; rparams->adminservers[j]!= NULL; j++) {
+ oldadmindns[j] = strdup(rparams->adminservers[j]);
+ if (oldadmindns[j] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ oldadmindns[j] = NULL;
+ }
+ }
+ }
+
+ rightsmask = 0;
+ rightsmask |= LDAP_REALM_RIGHTS;
+ rightsmask |= LDAP_SUBTREE_RIGHTS;
+ /* Remove the rights on the old subtree */
+ if ( oldadmindns ) {
+ for ( i=0; (oldadmindns[i] != NULL); i++) {
+
+ if((retval=krb5_ldap_delete_service_rights( util_context,
+ LDAP_ADMIN_SERVICE, oldadmindns[i],
+ rparams->realm_name, oldsubtree, rightsmask )) != 0) {
+ printf("failed\n");
+ com_err(argv[0], retval, "while assigning rights '%s'",
+ rparams->realm_name);
+ goto err_nomsg;
+ }
+ }
+ }
+
+ rightsmask = 0;
+ rightsmask |= LDAP_REALM_RIGHTS;
+ rightsmask |= LDAP_SUBTREE_RIGHTS;
+ /* Add rights on the new subtree for all the kdc dns */
+ if ( newadmindns ) {
+ for ( i=0; (newadmindns[i] != NULL); i++) {
+
+ if((retval=krb5_ldap_add_service_rights( util_context,
+ LDAP_ADMIN_SERVICE, newadmindns[i],
+ rparams->realm_name, rparams->subtree, rightsmask )) != 0) {
+ printf("failed\n");
+ com_err(argv[0], retval, "while assigning rights to '%s'",
+ rparams->realm_name);
+ goto err_nomsg;
+ }
+ }
+ }
+ }
+
+
+ if( (mask & LDAP_REALM_SUBTREE) || (mask & LDAP_REALM_PASSWDSERVERS) ) {
+
+ newpwddns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (newpwddns == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ if ( (rparams != NULL) && (rparams->passwdservers != NULL) ) {
+ for (j=0; rparams->passwdservers[j]!= NULL; j++) {
+ newpwddns[j] = strdup(rparams->passwdservers[j]);
+ if (newpwddns[j] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ newpwddns[j] = NULL;
+ }
+
+ if( !subtree_changed ) {
+ disjoint_members( oldpwddns, newpwddns);
+ }
+ else { /* Only the subtree was changed. Remove the rights on the old subtree. */
+ if (!(mask & LDAP_REALM_ADMINSERVERS)) {
+
+ oldpwddns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (oldpwddns == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ if ( (rparams != NULL) && (rparams->passwdservers != NULL) ) {
+ for (j=0; rparams->passwdservers[j]!= NULL; j++) {
+ oldpwddns[j] = strdup(rparams->passwdservers[j]);
+ if (oldpwddns[j] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ oldpwddns[j] = NULL;
+ }
+ }
+ }
+
+ rightsmask =0;
+ rightsmask |= LDAP_REALM_RIGHTS;
+ rightsmask |= LDAP_SUBTREE_RIGHTS;
+ /* Remove the rights on the old subtree */
+ if ( oldpwddns ) {
+ for ( i=0; (oldpwddns[i] != NULL); i++) {
+ if((retval = krb5_ldap_delete_service_rights( util_context,
+ LDAP_PASSWD_SERVICE, oldpwddns[i],
+ rparams->realm_name, oldsubtree, rightsmask))) {
+ printf("failed\n");
+ com_err(argv[0], retval, "while assigning rights '%s'",
+ rparams->realm_name);
+ goto err_nomsg;
+ }
+ }
+ }
+
+ rightsmask =0;
+ rightsmask |= LDAP_REALM_RIGHTS;
+ rightsmask |= LDAP_SUBTREE_RIGHTS;
+ /* Add rights on the new subtree for all the kdc dns */
+ if ( newpwddns ) {
+ for ( i=0; (newpwddns[i] != NULL); i++) {
+ if((retval = krb5_ldap_add_service_rights( util_context,
+ LDAP_PASSWD_SERVICE, newpwddns[i],
+ rparams->realm_name, rparams->subtree, rightsmask))) {
+ printf("failed\n");
+ com_err(argv[0], retval, "while assigning rights to '%s'",
+ rparams->realm_name);
+ goto err_nomsg;
+ }
+ }
+ }
+ }
+
+ printf("done\n");
+ }
+#endif
+
+ goto cleanup;
+
+err_usage:
+ print_usage = TRUE;
+
+err_nomsg:
+ no_msg = TRUE;
+
+cleanup:
+ krb5_ldap_free_realm_params(rparams);
+
+#ifdef HAVE_EDIRECTORY
+ if (oldkdcdns) {
+ for ( i=0; oldkdcdns[i] != NULL; i++)
+ free(oldkdcdns[i]);
+ free(oldkdcdns);
+ }
+ if (oldpwddns) {
+ for ( i=0; oldpwddns[i] != NULL; i++)
+ free(oldpwddns[i]);
+ free(oldpwddns);
+ }
+ if (oldadmindns) {
+ for ( i=0; oldadmindns[i] != NULL; i++)
+ free(oldadmindns[i]);
+ free(oldadmindns);
+ }
+ if (newkdcdns) {
+ for ( i=0; newkdcdns[i] != NULL; i++)
+ free(newkdcdns[i]);
+ free(newkdcdns);
+ }
+ if (newpwddns) {
+ for ( i=0; newpwddns[i] != NULL; i++)
+ free(newpwddns[i]);
+ free(newpwddns);
+ }
+ if (newadmindns) {
+ for ( i=0; newadmindns[i] != NULL; i++)
+ free(newadmindns[i]);
+ free(newadmindns);
+ }
+ if (oldsubtree)
+ free(oldsubtree);
+#endif
+ if (print_usage) {
+ db_usage(MODIFY_REALM);
+ }
+
+ if (retval) {
+ if (!no_msg)
+ com_err(argv[0], retval, "while modifying information of realm '%s'",
+ global_params.realm);
+ exit_status++;
+ }
+
+ return;
+}
+
+
+
+/*
+ * This function displays the attributes of a Realm
+ */
+void kdb5_ldap_view(argc, argv)
+ int argc;
+ char *argv[];
+{
+ krb5_ldap_realm_params *rparams = NULL;
+ krb5_error_code retval = 0;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ int mask = 0;
+
+ dal_handle = (kdb5_dal_handle *) util_context->db_context;
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+ if (!(ldap_context)) {
+ retval = EINVAL;
+ com_err(argv[0], retval, "while initializing database");
+ exit_status++;
+ return;
+ }
+
+ /* Read the kerberos container information */
+ if ((retval = krb5_ldap_read_krbcontainer_params(util_context,
+ &(ldap_context->krbcontainer))) != 0) {
+ com_err(argv[0], retval, "while reading kerberos container information");
+ exit_status++;
+ return;
+ }
+
+ if ((retval = krb5_ldap_read_realm_params(util_context,
+ global_params.realm, &rparams, &mask)) || (!rparams)) {
+ com_err(argv[0], retval, "while reading information of realm '%s'",
+ global_params.realm);
+ exit_status++;
+ return;
+ }
+ print_realm_params(rparams, mask);
+ krb5_ldap_free_realm_params(rparams);
+
+ return;
+}
+
+static char *strdur(duration)
+ time_t duration;
+{
+ static char out[50];
+ int neg, days, hours, minutes, seconds;
+
+ if (duration < 0) {
+ duration *= -1;
+ neg = 1;
+ } else
+ neg = 0;
+ days = duration / (24 * 3600);
+ duration %= 24 * 3600;
+ hours = duration / 3600;
+ duration %= 3600;
+ minutes = duration / 60;
+ duration %= 60;
+ seconds = duration;
+ sprintf(out, "%s%d %s %02d:%02d:%02d", neg ? "-" : "",
+ days, days == 1 ? "day" : "days",
+ hours, minutes, seconds);
+ return out;
+}
+
+/*
+ * This function prints the attributes of a given realm to the
+ * standard output.
+ */
+static void print_realm_params(krb5_ldap_realm_params *rparams, int mask)
+{
+ char buff[BUFF_LEN] = {0};
+ char **slist = NULL;
+ int *tmplist = NULL;
+ krb5_error_code retval = 0;
+ int num_entry_printed = 0;
+
+ /* Print the Realm Attributes on the standard output */
+ printf("%25s: %-50s\n", "Realm Name", global_params.realm);
+ if (mask & LDAP_REALM_SUBTREE)
+ printf("%25s: %-50s\n", "Subtree", rparams->subtree);
+ if (mask & LDAP_REALM_SEARCHSCOPE) {
+ if ((rparams->search_scope != 1) &&
+ (rparams->search_scope != 2)) {
+ printf("%25s: %-50s\n", "SearchScope", "Invalid !");
+ }
+ else {
+ printf("%25s: %-50s\n", "SearchScope",
+ (rparams->search_scope == 1) ? "ONE" : "SUB");
+ }
+ }
+ if (mask & LDAP_REALM_KDCSERVERS) {
+ printf("%25s:", "KDC Services");
+ if (rparams->kdcservers != NULL) {
+ num_entry_printed = 0;
+ for(slist = rparams->kdcservers; *slist != NULL; slist++) {
+ if (num_entry_printed)
+ printf(" %25s %-50s\n", " ", *slist);
+ else
+ printf(" %-50s\n", *slist);
+ num_entry_printed++;
+ }
+ }
+ if (num_entry_printed == 0)
+ printf("\n");
+ }
+ if (mask & LDAP_REALM_ADMINSERVERS) {
+ printf("%25s:", "Admin Services");
+ if (rparams->adminservers != NULL) {
+ num_entry_printed = 0;
+ for(slist = rparams->adminservers; *slist != NULL; slist++) {
+ if (num_entry_printed)
+ printf(" %25s %-50s\n", " ", *slist);
+ else
+ printf(" %-50s\n", *slist);
+ num_entry_printed++;
+ }
+ }
+ if (num_entry_printed == 0)
+ printf("\n");
+ }
+ if (mask & LDAP_REALM_PASSWDSERVERS) {
+ printf("%25s:", "Passwd Services");
+ if (rparams->passwdservers != NULL) {
+ num_entry_printed = 0;
+ for(slist = rparams->passwdservers; *slist != NULL; slist++) {
+ if (num_entry_printed)
+ printf(" %25s %-50s\n", " ", *slist);
+ else
+ printf(" %-50s\n", *slist);
+ num_entry_printed++;
+ }
+ }
+ if (num_entry_printed == 0)
+ printf("\n");
+ }
+ if (mask & LDAP_REALM_SUPPENCTYPE) {
+ printf("%25s:", "Supported Enc Types");
+ if (rparams->suppenctypes != NULL) {
+ num_entry_printed = 0;
+ for(tmplist = rparams->suppenctypes; *tmplist != END_OF_LIST;
+ tmplist++) {
+ retval = krb5_enctype_to_string(*tmplist, buff, BUFF_LEN);
+ if (retval == 0) {
+ if (num_entry_printed)
+ printf(" %25s %-50s\n", " ", buff);
+ else
+ printf(" %-50s\n", buff);
+ num_entry_printed++;
+ }
+ }
+ }
+ if (num_entry_printed == 0)
+ printf("\n");
+ }
+ if (mask & LDAP_REALM_DEFENCTYPE) {
+ retval = krb5_enctype_to_string(rparams->defenctype, buff, BUFF_LEN);
+ if (retval == 0) {
+ printf("%25s: %-50s\n", "Default Enc Type", buff);
+ }
+ }
+ if (mask & LDAP_REALM_SUPPSALTTYPE) {
+ printf("%25s:", "Supported Salt Types");
+ if (rparams->suppsalttypes != NULL) {
+ num_entry_printed = 0;
+ for(tmplist = rparams->suppsalttypes; *tmplist != END_OF_LIST;
+ tmplist++) {
+ retval = krb5_salttype_to_string(*tmplist, buff, BUFF_LEN);
+ if (retval == 0) {
+ if (num_entry_printed)
+ printf(" %25s %-50s\n", " ", buff);
+ else
+ printf(" %-50s\n", buff);
+ num_entry_printed++;
+ }
+ }
+ }
+ if (num_entry_printed == 0)
+ printf("\n");
+ }
+ if (mask & LDAP_REALM_MAXTICKETLIFE) {
+ printf("%25s:", "Maximum Ticket Life");
+ printf(" %s \n", strdur(rparams->max_life));
+ }
+
+ if (mask & LDAP_REALM_MAXRENEWLIFE) {
+ printf("%25s:", "Maximum Renewable Life");
+ printf(" %s \n", strdur(rparams->max_renewable_life));
+ }
+ printf("%25s: ", "Ticket flags");
+ if (mask & LDAP_POLICY_TKTFLAGS) {
+ int ticketflags = rparams->tktflags;
+
+ if (ticketflags & KRB5_KDB_DISALLOW_POSTDATED)
+ printf("%s ","DISALLOW_POSTDATED");
+
+ if (ticketflags & KRB5_KDB_DISALLOW_FORWARDABLE)
+ printf("%s ","DISALLOW_FORWARDABLE");
+
+ if (ticketflags & KRB5_KDB_DISALLOW_RENEWABLE)
+ printf("%s ","DISALLOW_RENEWABLE");
+
+ if (ticketflags & KRB5_KDB_DISALLOW_PROXIABLE)
+ printf("%s ","DISALLOW_PROXIABLE");
+
+ if (ticketflags & KRB5_KDB_DISALLOW_DUP_SKEY)
+ printf("%s ","DISALLOW_DUP_SKEY");
+
+ if (ticketflags & KRB5_KDB_REQUIRES_PRE_AUTH)
+ printf("%s ","REQUIRES_PRE_AUTH");
+
+ if (ticketflags & KRB5_KDB_REQUIRES_HW_AUTH)
+ printf("%s ","REQUIRES_HW_AUTH");
+
+ if (ticketflags & KRB5_KDB_DISALLOW_SVR)
+ printf("%s ","DISALLOW_SVR");
+
+ if (ticketflags & KRB5_KDB_DISALLOW_TGT_BASED)
+ printf("%s ","DISALLOW_TGT_BASED");
+
+ if (ticketflags & KRB5_KDB_DISALLOW_ALL_TIX)
+ printf("%s ","DISALLOW_ALL_TIX");
+
+ if (ticketflags & KRB5_KDB_REQUIRES_PWCHANGE)
+ printf("%s ","REQUIRES_PWCHANGE");
+
+ if (ticketflags & KRB5_KDB_PWCHANGE_SERVICE)
+ printf("%s ","PWCHANGE_SERVICE");
+ }
+
+ if (mask & LDAP_REALM_DEFSALTTYPE) {
+ retval = krb5_salttype_to_string(rparams->defsalttype, buff, BUFF_LEN);
+ if (retval == 0) {
+ printf("\n%25s: %-50s\n", "Default Salt Type", buff);
+ }
+ }
+ /* if (mask & LDAP_REALM_POLICYREFERENCE)
+ printf("%25s: %-50s\n", "Policy Reference", rparams->policyreference);*/
+
+
+ return;
+}
+
+
+
+/*
+ * This function lists the Realm(s) present under the Kerberos container
+ * on the LDAP Server.
+ */
+void kdb5_ldap_list(argc, argv)
+ int argc;
+ char *argv[];
+{
+ char **list = NULL;
+ char **plist = NULL;
+ krb5_error_code retval = 0;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+
+ dal_handle = (kdb5_dal_handle *)util_context->db_context;
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+ if (!(ldap_context)) {
+ retval = EINVAL;
+ exit_status++;
+ return;
+ }
+
+ /* Read the kerberos container information */
+ if ((retval = krb5_ldap_read_krbcontainer_params(util_context,
+ &(ldap_context->krbcontainer))) != 0) {
+ com_err(argv[0], retval, "while reading kerberos container information");
+ exit_status++;
+ return;
+ }
+
+ retval = krb5_ldap_list_realm(util_context, &list);
+ if (retval != 0) {
+ krb5_ldap_free_krbcontainer_params(ldap_context->krbcontainer);
+ ldap_context->krbcontainer = NULL;
+ com_err (argv[0], retval, "while listing realms");
+ exit_status++;
+ return;
+ }
+ /* This is to handle the case of realm not present */
+ if (list == NULL) {
+ krb5_ldap_free_krbcontainer_params(ldap_context->krbcontainer);
+ ldap_context->krbcontainer = NULL;
+ return;
+ }
+
+ for(plist = list; *plist != NULL; plist++) {
+ printf("%s\n", *plist);
+ }
+ krb5_ldap_free_krbcontainer_params(ldap_context->krbcontainer);
+ ldap_context->krbcontainer = NULL;
+ krb5_free_list_entries(list);
+ free(list);
+
+ return;
+}
+
+
+/*
+ * This function creates service principals when
+ * creating the realm object.
+ */
+static int
+kdb_ldap_create_principal (context, princ, op, pblock)
+ krb5_context context;
+ krb5_principal princ;
+ enum ap_op op;
+ struct realm_info *pblock;
+{
+ int retval=0, currlen=0, princtype = 2 /* Service Principal */;
+ unsigned char *curr=NULL;
+ krb5_tl_data *tl_data=NULL;
+ krb5_db_entry entry;
+ int nentry=1;
+ long mask = 0;
+ krb5_keyblock key;
+ int kvno = 0;
+ kdb5_dal_handle *dal_handle = NULL;
+ krb5_ldap_context *ldap_context=NULL;
+
+ if ((pblock == NULL) || (context == NULL)) {
+ retval = EINVAL;
+ goto cleanup;
+ }
+ dal_handle = (kdb5_dal_handle *) context->db_context;
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+ if (!(ldap_context)) {
+ retval = EINVAL;
+ goto cleanup;
+ }
+
+ memset(&entry, 0, sizeof(entry));
+
+ tl_data = malloc(sizeof(*tl_data));
+ if (tl_data == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ memset(tl_data, 0, sizeof(*tl_data));
+ tl_data->tl_data_length = 1 + 2 + 2 + 1 + 2 + 4;
+ tl_data->tl_data_type = 7; /* KDB_TL_USER_INFO */
+ curr = tl_data->tl_data_contents = malloc(tl_data->tl_data_length);
+ if (tl_data->tl_data_contents == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ memset(curr, 1, 1); /* Passing the mask as principal type */
+ curr += 1;
+ currlen = 2;
+ STORE16_INT(curr, currlen);
+ curr += currlen;
+ STORE16_INT(curr, princtype);
+ curr += currlen;
+
+ mask |= KDB_PRINCIPAL;
+ mask |= KDB_ATTRIBUTES ;
+ mask |= KDB_MAX_LIFE ;
+ mask |= KDB_MAX_RLIFE ;
+ mask |= KDB_PRINC_EXPIRE_TIME ;
+ mask |= KDB_KEY_DATA;
+
+ entry.tl_data = tl_data;
+ entry.n_tl_data += 1;
+ entry.attributes = pblock->flags;
+ entry.max_life = pblock->max_life;
+ entry.max_renewable_life = pblock->max_rlife;
+ entry.expiration = pblock->expiration;
+ entry.mask = mask;
+ if ((retval = krb5_copy_principal(context, princ, &entry.princ)))
+ goto cleanup;
+
+ /* Allocate memory for storing the key */
+ if ((entry.key_data = (krb5_key_data *) malloc(
+ (sizeof(krb5_key_data)*(entry.n_key_data + 1)))) == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ memset(entry.key_data + entry.n_key_data, 0, sizeof(krb5_key_data));
+ entry.n_key_data++;
+
+ switch (op)
+ {
+ case TGT_KEY:
+ retval = krb5_c_make_random_key(context, 16, &key) ;
+ if( retval ) {
+ goto cleanup;
+ }
+
+ kvno = 1; /* New key is getting set */
+ retval = krb5_dbekd_encrypt_key_data(context,
+ &ldap_context->lrparams->mkey,
+ &key, NULL, kvno,
+ &entry.key_data[entry.n_key_data - 1]);
+ if( retval ) {
+ goto cleanup;
+ }
+ krb5_free_keyblock_contents(context, &key);
+ break;
+
+ case MASTER_KEY:
+ kvno = 1; /* New key is getting set */
+ retval = krb5_dbekd_encrypt_key_data(context, pblock->key,
+ &ldap_context->lrparams->mkey, NULL, kvno,
+ &entry.key_data[entry.n_key_data - 1]);
+ if( retval ) {
+ goto cleanup;
+ }
+ break;
+
+ case NULL_KEY:
+ default:
+ break;
+ } /* end of switch */
+
+ retval = krb5_ldap_put_principal(context, &entry, &nentry, NULL);
+ if( retval ) {
+ com_err(NULL, retval, "while adding entries to database");
+ goto cleanup;
+ }
+
+ cleanup:
+ krb5_dbe_free_contents( context, &entry);
+ return retval;
+}
+
+
+/*
+ * This function destroys the realm object and the associated principals
+ */
+void
+kdb5_ldap_destroy(argc, argv)
+ int argc;
+ char *argv[];
+{
+ extern char *optarg;
+ extern int optind;
+ int optchar = 0;
+ char buf[5] = {0};
+ krb5_error_code retval = 0;
+ int force = 0;
+ int mask = 0;
+ kdb5_dal_handle *dal_handle = NULL;
+ krb5_ldap_context *ldap_context = NULL;
+#ifdef HAVE_EDIRECTORY
+ int i = 0, rightsmask = 0;
+ krb5_ldap_realm_params *rparams = NULL;
+#endif
+
+ optind = 1;
+ while ((optchar = getopt(argc, argv, "f")) != -1) {
+ switch(optchar) {
+ case 'f':
+ force++;
+ break;
+ case '?':
+ default:
+ db_usage(DESTROY_REALM);
+ return;
+ /*NOTREACHED*/
+ }
+ }
+
+ if (!force) {
+ printf("Deleting KDC database of '%s', are you sure?\n", global_params.realm);
+ printf("(type 'yes' to confirm)? ");
+ if (fgets(buf, sizeof(buf), stdin) == NULL) {
+ exit_status++;
+ return;
+ }
+ if (strcmp(buf, yes)) {
+ exit_status++;
+ return;
+ }
+ printf("OK, deleting database of '%s'...\n", global_params.realm);
+ }
+
+ dal_handle = (kdb5_dal_handle *)util_context->db_context;
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+ if (!(ldap_context)) {
+ com_err(argv[0], EINVAL, "while initializing database");
+ exit_status++;
+ return;
+ }
+
+ /* Read the kerberos container from the LDAP Server */
+ if ((retval = krb5_ldap_read_krbcontainer_params(util_context,
+ &(ldap_context->krbcontainer))) != 0) {
+ com_err(argv[0], retval, "while reading kerberos container information");
+ exit_status++;
+ return;
+ }
+
+ /* Read the Realm information from the LDAP Server */
+ if ((retval = krb5_ldap_read_realm_params(util_context, global_params.realm,
+ &(ldap_context->lrparams), &mask)) != 0) {
+ com_err(argv[0], retval, "while reading realm information");
+ exit_status++;
+ return;
+ }
+
+#ifdef HAVE_EDIRECTORY
+ if( (mask & LDAP_REALM_KDCSERVERS) || (mask & LDAP_REALM_ADMINSERVERS) ||
+ (mask & LDAP_REALM_PASSWDSERVERS) ) {
+
+ printf("Changing rights for the service object. Please wait ... ");
+ fflush(stdout);
+
+ rparams = ldap_context->lrparams;
+ rightsmask = 0;
+ rightsmask |= LDAP_REALM_RIGHTS;
+ rightsmask |= LDAP_SUBTREE_RIGHTS;
+ if ( (rparams != NULL) && (rparams->kdcservers != NULL) ) {
+ for ( i=0; (rparams->kdcservers[i] != NULL); i++) {
+ if((retval = krb5_ldap_delete_service_rights( util_context,
+ LDAP_KDC_SERVICE, rparams->kdcservers[i],
+ rparams->realm_name, rparams->subtree, rightsmask )) != 0) {
+ printf("failed\n");
+ com_err(argv[0], retval, "while assigning rights to '%s'",
+ rparams->realm_name);
+ return;
+ }
+ }
+ }
+ rightsmask = 0;
+ rightsmask |= LDAP_REALM_RIGHTS;
+ rightsmask |= LDAP_SUBTREE_RIGHTS;
+ if ( (rparams != NULL) && (rparams->adminservers != NULL) ) {
+ for ( i=0; (rparams->adminservers[i] != NULL); i++) {
+ if((retval = krb5_ldap_delete_service_rights( util_context,
+ LDAP_ADMIN_SERVICE, rparams->adminservers[i],
+ rparams->realm_name, rparams->subtree, rightsmask )) != 0) {
+ printf("failed\n");
+ com_err(argv[0], retval, "while assigning rights to '%s'",
+ rparams->realm_name);
+ return;
+ }
+ }
+ }
+ rightsmask = 0;
+ rightsmask |= LDAP_REALM_RIGHTS;
+ rightsmask |= LDAP_SUBTREE_RIGHTS;
+ if( (rparams != NULL) && (rparams->passwdservers != NULL) ) {
+ for ( i=0; (rparams->passwdservers[i] != NULL); i++) {
+ if((retval = krb5_ldap_delete_service_rights( util_context,
+ LDAP_PASSWD_SERVICE, rparams->passwdservers[i],
+ rparams->realm_name, rparams->subtree, rightsmask )) != 0) {
+ printf("failed\n");
+ com_err(argv[0], retval, "while assigning rights to '%s'",
+ rparams->realm_name);
+ return;
+ }
+ }
+ }
+ printf("done\n");
+ }
+#endif
+ /* Delete the realm container and all the associated principals */
+ retval = krb5_ldap_delete_realm(util_context, global_params.realm);
+ if (retval) {
+ com_err(argv[0], retval, "deleting database of '%s'", global_params.realm);
+ exit_status++;
+ return;
+ }
+
+ printf("** Database of '%s' destroyed.\n", global_params.realm);
+
+ return;
+}
diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.h b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.h
new file mode 100644
index 000000000..1a0ea9ccb
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.h
@@ -0,0 +1,63 @@
+/*
+ * kadmin/ldap_util/kdb5_ldap_realm.h
+ */
+
+/* Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define MAX_KRB_CONTAINER_LEN 256
+
+#define BUFF_LEN 64 /* Max len of enctype string */
+#define MAX_PRINC_SIZE 256
+
+enum ap_op {
+ NULL_KEY, /* setup null keys */
+ MASTER_KEY, /* use master key as new key */
+ TGT_KEY /* special handling for tgt key */
+};
+
+struct realm_info {
+ krb5_deltat max_life;
+ krb5_deltat max_rlife;
+ krb5_timestamp expiration;
+ krb5_flags flags;
+ krb5_keyblock *key;
+ krb5_int32 nkslist;
+ krb5_key_salt_tuple *kslist;
+};
+
+struct iterate_args {
+ krb5_context ctx;
+ struct realm_info *rblock;
+ krb5_db_entry *dbentp;
+};
+
+extern void kdb5_ldap_create (int argc, char **argv);
+extern void kdb5_ldap_destroy (int argc, char **argv);
+extern void kdb5_ldap_modify (int argc, char **argv);
+extern void kdb5_ldap_view (int argc, char **argv);
+extern void kdb5_ldap_list (int argc, char **argv);
diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
new file mode 100644
index 000000000..69e3b7694
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
@@ -0,0 +1,2181 @@
+/*
+ * kadmin/ldap_util/kdb5_ldap_services.c
+ */
+
+/* Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Create / Delete / Modify / View / List service objects.
+ */
+
+/*
+ * Service objects have rights over realm objects and principals. The following
+ * functions manage the service objects.
+ */
+
+#include <stdio.h>
+#include <k5-int.h>
+#include "kdb5_ldap_util.h"
+#include "kdb5_ldap_list.h"
+
+#ifdef HAVE_EDIRECTORY
+
+krb5_error_code
+rem_service_entry_from_file( int argc,
+ char *argv[],
+ char *file_name,
+ char *service_object );
+
+extern char *yes;
+extern krb5_boolean db_inited;
+
+static int process_host_list(char **host_list, int servicetype)
+{
+ krb5_error_code retval = 0;
+ char *pchr = NULL;
+ char host_str[MAX_LEN_LIST_ENTRY] = "", proto_str[PROTOCOL_STR_LEN + 1] = "", port_str[PORT_STR_LEN + 1] = "";
+ int j = 0;
+
+ /* Protocol and port number processing */
+ for (j = 0; host_list[j]; j++) {
+ /* Look for one hash */
+ if ((pchr = strchr(host_list[j], HOST_INFO_DELIMITER))) {
+ unsigned int hostname_len = pchr - host_list[j];
+
+ /* Check input for buffer overflow */
+ if (hostname_len >= MAX_LEN_LIST_ENTRY) {
+ retval = EINVAL;
+ goto cleanup;
+ }
+
+ /* First copy off the host name portion */
+ strncpy (host_str, host_list[j], hostname_len);
+
+ /* Parse for the protocol string and translate to number */
+ strncpy (proto_str, pchr + 1, PROTOCOL_STR_LEN);
+ if (!strcmp(proto_str, "udp"))
+ sprintf (proto_str, "%d", PROTOCOL_NUM_UDP);
+ else if (!strcmp(proto_str, "tcp"))
+ sprintf (proto_str, "%d", PROTOCOL_NUM_TCP);
+ else
+ proto_str[0] = '\0'; /* Make the string null if invalid */
+
+ /* Look for one more hash */
+ if ((pchr = strchr(pchr + 1, HOST_INFO_DELIMITER))) {
+ /* Parse for the port string and check if it is numeric */
+ strncpy (port_str, pchr + 1, PORT_STR_LEN);
+ if (!strtol(port_str, NULL, 10)) /* Not a valid number */
+ port_str[0] = '\0';
+ }
+ else
+ port_str[0] = '\0';
+ }
+ else { /* We have only host name */
+ strncpy (host_str, host_list[j], MAX_LEN_LIST_ENTRY - 1);
+ proto_str[0] = '\0';
+ port_str[0] = '\0';
+ }
+
+ /* Now, based on service type, fill in suitable protocol
+ and port values if they are absent or not matching */
+ if (servicetype == LDAP_KDC_SERVICE) {
+ if (proto_str[0] == '\0')
+ sprintf (proto_str, "%d", PROTOCOL_DEFAULT_KDC);
+
+ if (port_str[0] == '\0')
+ sprintf (port_str, "%d", PORT_DEFAULT_KDC);
+ }
+ else if (servicetype == LDAP_ADMIN_SERVICE) {
+ if (proto_str[0] == '\0')
+ sprintf (proto_str, "%d", PROTOCOL_DEFAULT_ADM);
+ else if (strcmp(proto_str, "1")) {
+ sprintf (proto_str, "%d", PROTOCOL_DEFAULT_ADM);
+
+ /* Print warning message */
+ printf ("Admin Server supports only TCP protocol, hence setting that\n");
+ }
+
+ if (port_str[0] == '\0')
+ sprintf (port_str, "%d", PORT_DEFAULT_ADM);
+ }
+ else if (servicetype == LDAP_PASSWD_SERVICE) {
+ if (proto_str[0] == '\0')
+ sprintf (proto_str, "%d", PROTOCOL_DEFAULT_PWD);
+ else if (strcmp(proto_str, "0")) {
+ sprintf (proto_str, "%d", PROTOCOL_DEFAULT_PWD);
+
+ /* Print warning message */
+ printf ("Password Server supports only UDP protocol, hence setting that\n");
+ }
+
+ if (port_str[0] == '\0')
+ sprintf (port_str, "%d", PORT_DEFAULT_PWD);
+ }
+
+ /* Finally form back the string */
+ free (host_list[j]);
+ host_list[j] = (char*) malloc(sizeof(char) *
+ (strlen(host_str) + strlen(proto_str) + strlen(port_str) + 2 + 1));
+ if (host_list[j] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ snprintf (host_list[j], strlen(host_str) + strlen(proto_str) + strlen(port_str) + 2 + 1,
+ "%s#%s#%s", host_str, proto_str, port_str);
+ }
+
+cleanup:
+ return retval;
+}
+
+
+/*
+ * Given a realm name, this function will convert it to a DN by appending the
+ * Kerberos container location.
+ */
+static krb5_error_code
+convert_realm_name2dn_list(list, krbcontainer_loc)
+ char **list;
+ const char *krbcontainer_loc;
+{
+ krb5_error_code retval = 0;
+ char temp_str[MAX_DN_CHARS] = "\0";
+ char *temp_node = NULL;
+ int i = 0;
+
+ if (list == NULL) {
+ return EINVAL;
+ }
+
+ for (i = 0; (list[i] != NULL) && (i < MAX_LIST_ENTRIES); i++) {
+ /* Restrict copying to max. length to avoid buffer overflow */
+ snprintf (temp_str, MAX_DN_CHARS, "cn=%s,%s", list[i], krbcontainer_loc);
+
+ /* Make copy of string to temporary node */
+ temp_node = strdup(temp_str);
+ if (list[i] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ /* On success, free list node and attach new one */
+ free (list[i]);
+ list[i] = temp_node;
+ temp_node = NULL;
+ }
+
+cleanup:
+ return retval;
+}
+
+
+/*
+ * This function will create a service object on the LDAP Server, with the
+ * specified attributes.
+ */
+void kdb5_ldap_create_service(argc, argv)
+ int argc;
+ char *argv[];
+{
+ char *me = argv[0];
+ krb5_error_code retval = 0;
+ krb5_ldap_service_params *srvparams = NULL;
+ krb5_boolean print_usage = FALSE;
+ krb5_boolean no_msg = FALSE;
+ int mask = 0;
+ char **extra_argv = NULL;
+ int extra_argc = 0;
+ int i = 0;
+ krb5_ldap_realm_params *rparams = NULL;
+ int rmask = 0;
+ int rightsmask =0;
+ char **temprdns = NULL;
+ char *realmName = NULL;
+ kdb5_dal_handle *dal_handle = NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_boolean service_obj_created = FALSE;
+
+ /* Check for number of arguments */
+ if ((argc < 3) || (argc > 10)) {
+ exit_status++;
+ goto err_usage;
+ }
+
+ /* Allocate memory for service parameters structure */
+ srvparams = (krb5_ldap_service_params*) calloc(1, sizeof(krb5_ldap_service_params));
+ if (srvparams == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ dal_handle = (kdb5_dal_handle *) util_context->db_context;
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+
+ /* Allocate memory for extra arguments to be used for setting
+ password -- it's OK to allocate as much as the total number
+ of arguments */
+ extra_argv = (char **) calloc((unsigned int)argc, sizeof(char*));
+ if (extra_argv == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ /* Set first of the extra arguments as the program name */
+ extra_argv[0] = me;
+ extra_argc++;
+
+ /* Read Kerberos container info, to construct realm DN from name
+ * and for assigning rights
+ */
+ if ((retval = krb5_ldap_read_krbcontainer_params(util_context,
+ &(ldap_context->krbcontainer)))) {
+ com_err(me, retval, "while reading Kerberos container information");
+ goto cleanup;
+ }
+
+ /* Parse all arguments */
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-kdc")) {
+ srvparams->servicetype = LDAP_KDC_SERVICE;
+ }
+ else if (!strcmp(argv[i], "-admin")) {
+ srvparams->servicetype = LDAP_ADMIN_SERVICE;
+ }
+ else if (!strcmp(argv[i], "-pwd")) {
+ srvparams->servicetype = LDAP_PASSWD_SERVICE;
+ }
+ else if (!strcmp(argv[i], "-servicehost")) {
+ if (++i > argc - 1)
+ goto err_usage;
+
+ srvparams->krbhostservers = (char **)calloc(MAX_LIST_ENTRIES,
+ sizeof(char *));
+ if (srvparams->krbhostservers == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
+ srvparams->krbhostservers))) {
+ goto cleanup;
+ }
+
+ if ((retval = process_host_list (srvparams->krbhostservers,
+ srvparams->servicetype))) {
+ goto cleanup;
+ }
+
+ mask |= LDAP_SERVICE_HOSTSERVER;
+ }
+ else if (!strcmp(argv[i], "-realm")) {
+ if (++i > argc - 1)
+ goto err_usage;
+
+ srvparams->krbrealmreferences = (char **)calloc(MAX_LIST_ENTRIES,
+ sizeof(char *));
+ if (srvparams->krbrealmreferences == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
+ srvparams->krbrealmreferences))) {
+ goto cleanup;
+ }
+
+ /* Convert realm names to realm DNs */
+ if ((retval = convert_realm_name2dn_list(
+ srvparams->krbrealmreferences,
+ ldap_context->krbcontainer->DN))) {
+ goto cleanup;
+ }
+
+ mask |= LDAP_SERVICE_REALMREFERENCE;
+ }
+ /* If argument is none of the above and beginning with '-',
+ * it must be related to password -- collect it
+ * to pass onto kdb5_ldap_set_service_password()
+ */
+ else if (*(argv[i]) == '-') {
+ /* Checking for options of setting the password for the
+ * service (by using 'setsrvpw') is not modular. --need to
+ * have a common function that can be shared with 'setsrvpw'
+ */
+ if (!strcmp(argv[i], "-randpw")) {
+ extra_argv[extra_argc] = argv[i];
+ extra_argc++;
+ }
+ else if (!strcmp(argv[i], "-fileonly")) {
+ extra_argv[extra_argc] = argv[i];
+ extra_argc++;
+ }
+ /* For '-f' option alone, pick up the following argument too */
+ else if (!strcmp(argv[i], "-f")) {
+ extra_argv[extra_argc] = argv[i];
+ extra_argc++;
+
+ if (++i > argc - 1)
+ goto err_usage;
+
+ extra_argv[extra_argc] = argv[i];
+ extra_argc++;
+ }
+ else { /* Any other option is invalid */
+ exit_status++;
+ goto err_usage;
+ }
+ }
+ else { /* Any other argument must be service DN */
+ /* First check if service DN is already provided --
+ * if so, there's a usage error
+ */
+ if (srvparams->servicedn != NULL) {
+ com_err(me, EINVAL, "while creating service object");
+ goto err_usage;
+ }
+
+ /* If not present already, fill up service DN */
+ srvparams->servicedn = strdup(argv[i]);
+ if (srvparams->servicedn == NULL) {
+ com_err(me, ENOMEM, "while creating service object");
+ goto err_nomsg;
+ }
+ }
+ }
+
+ /* No point in proceeding further if service DN value is not available */
+ if (srvparams->servicedn == NULL) {
+ com_err(me, EINVAL, "while creating service object");
+ goto err_usage;
+ }
+
+ if (srvparams->servicetype == 0) { /* Not provided and hence not set */
+ com_err(me, EINVAL, "while creating service object");
+ goto err_usage;
+ }
+
+ /* Create object with all attributes provided */
+ if ((retval = krb5_ldap_create_service(util_context, srvparams, mask)))
+ goto cleanup;
+
+ service_obj_created = TRUE;
+
+ /* ** NOTE ** srvparams structure should not be modified, as it is
+ * used for deletion of the service object in case of any failures
+ * from now on.
+ */
+
+ /* Set password too */
+ if (extra_argc >= 1) {
+ /* Set service DN as the last argument */
+ extra_argv[extra_argc] = strdup(srvparams->servicedn);
+ extra_argc++;
+
+ if( (retval = kdb5_ldap_set_service_password(extra_argc, extra_argv)) != 0 )
+ {
+ goto err_nomsg;
+ }
+ }
+ /* Rights assignment */
+ if( mask & LDAP_SERVICE_REALMREFERENCE ) {
+
+ printf("%s","Changing rights for the service object. Please wait ... ");
+ fflush(stdout);
+
+ rightsmask =0;
+ rightsmask |= LDAP_REALM_RIGHTS;
+ rightsmask |= LDAP_SUBTREE_RIGHTS;
+
+ if( (srvparams != NULL) && (srvparams->krbrealmreferences != NULL) ) {
+ for ( i=0; (srvparams->krbrealmreferences[i] != NULL); i++) {
+
+ /* Get the realm name, not the dn */
+ temprdns = ldap_explode_dn(srvparams->krbrealmreferences[i], 1);
+
+ if( temprdns[0] == NULL ) {
+ retval = EINVAL;
+ goto cleanup;
+ }
+
+ realmName = strdup(temprdns[0]);
+ if( realmName == NULL ) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ if((retval = krb5_ldap_read_realm_params(util_context,
+ realmName, &rparams, &rmask))) {
+ com_err(me, retval, "while reading information of realm '%s'",
+ realmName);
+ goto cleanup;
+ }
+
+ if((retval = krb5_ldap_add_service_rights(util_context,
+ srvparams->servicetype, srvparams->servicedn,
+ realmName, rparams->subtree, rightsmask))) {
+ printf("failed\n");
+ com_err(me, retval, "while assigning rights '%s'",
+ srvparams->servicedn);
+ goto cleanup;
+ }
+
+ if( rparams )
+ krb5_ldap_free_realm_params(rparams);
+ }
+ }
+ printf("done\n");
+ }
+ goto cleanup;
+
+err_usage:
+ print_usage = TRUE;
+
+err_nomsg:
+ no_msg = TRUE;
+
+cleanup:
+
+ if ((retval != 0) && (service_obj_created == TRUE))
+ {
+ /* This is for deleting the service object if something goes
+ * wrong in creating the service object
+ */
+
+ /* srvparams is populated from the user input and should be correct as
+ * we were successful in creating a service object. Reusing the same
+ */
+ krb5_ldap_delete_service(util_context, srvparams, srvparams->servicedn);
+ }
+
+ /* Clean-up structure */
+ krb5_ldap_free_service (util_context, srvparams);
+
+ if (extra_argv) {
+ free (extra_argv);
+ extra_argv = NULL;
+ }
+ if ( realmName ) {
+ free(realmName);
+ realmName = NULL;
+ }
+ if (print_usage)
+ db_usage (CREATE_SERVICE);
+
+ if (retval) {
+ if (!no_msg)
+ com_err(me, retval, "while creating service object");
+
+ exit_status++;
+ }
+
+ return;
+}
+
+
+/*
+ * This function will modify the attributes of a given service
+ * object on the LDAP Server
+ */
+void kdb5_ldap_modify_service(argc, argv)
+ int argc;
+ char *argv[];
+{
+ char *me = argv[0];
+ krb5_error_code retval = 0;
+ krb5_ldap_service_params *srvparams = NULL;
+ krb5_boolean print_usage = FALSE;
+ krb5_boolean no_msg = FALSE;
+ char *servicedn = NULL;
+ int i = 0;
+ int in_mask = 0, out_mask = 0;
+ int srvhost_flag = 0, realmdn_flag = 0;
+ char **list = NULL;
+ int existing_entries = 0, new_entries = 0;
+ char **temp_ptr = NULL;
+ krb5_ldap_realm_params *rparams = NULL;
+ int j = 0;
+ int rmask = 0;
+ int rightsmask =0;
+ char **oldrealmrefs = NULL;
+ char **newrealmrefs = NULL;
+ char **temprdns = NULL;
+ char *realmName = NULL;
+ kdb5_dal_handle *dal_handle = NULL;
+ krb5_ldap_context *ldap_context=NULL;
+
+ /* Check for number of arguments */
+ if ((argc < 3) || (argc > 10)) {
+ exit_status++;
+ goto err_usage;
+ }
+
+ dal_handle = (kdb5_dal_handle *) util_context->db_context;
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+
+ /* Parse all arguments, only to pick up service DN (Pass 1) */
+ for (i = 1; i < argc; i++) {
+ /* Skip arguments next to 'servicehost'
+ and 'realmdn' arguments */
+ if (!strcmp(argv[i], "-servicehost")) {
+ ++i;
+ }
+ else if (!strcmp(argv[i], "-clearservicehost")) {
+ ++i;
+ }
+ else if (!strcmp(argv[i], "-addservicehost")) {
+ ++i;
+ }
+ else if (!strcmp(argv[i], "-realm")) {
+ ++i;
+ }
+ else if (!strcmp(argv[i], "-clearrealm")) {
+ ++i;
+ }
+ else if (!strcmp(argv[i], "-addrealm")) {
+ ++i;
+ }
+ else { /* Any other argument must be service DN */
+ /* First check if service DN is already provided --
+ if so, there's a usage error */
+ if (servicedn != NULL) {
+ com_err(me, EINVAL, "while modifying service object");
+ goto err_usage;
+ }
+
+ /* If not present already, fill up service DN */
+ servicedn = strdup(argv[i]);
+ if (servicedn == NULL) {
+ com_err(me, ENOMEM, "while modifying service object");
+ goto err_nomsg;
+ }
+ }
+ }
+
+ /* No point in proceeding further if service DN value is not available */
+ if (servicedn == NULL) {
+ com_err(me, EINVAL, "while modifying service object");
+ goto err_usage;
+ }
+
+ retval = krb5_ldap_read_service(util_context, servicedn, &srvparams, &in_mask);
+ if (retval) {
+ com_err(argv[0], retval, "while reading information of service '%s'",
+ servicedn);
+ goto err_nomsg;
+ }
+
+ /* Read Kerberos container info, to construct realm DN from name
+ * and for assigning rights
+ */
+ if ((retval = krb5_ldap_read_krbcontainer_params(util_context,
+ &(ldap_context->krbcontainer)))) {
+ com_err(me, retval, "while reading Kerberos container information");
+ goto cleanup;
+ }
+
+ /* Parse all arguments, but skip the service DN (Pass 2) */
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-servicehost")) {
+ if (++i > argc - 1)
+ goto err_usage;
+
+ /* Free the old list if available */
+ if (srvparams->krbhostservers) {
+ krb5_free_list_entries (srvparams->krbhostservers);
+ free (srvparams->krbhostservers);
+ }
+
+ srvparams->krbhostservers = (char **)calloc(MAX_LIST_ENTRIES,
+ sizeof(char *));
+ if (srvparams->krbhostservers == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
+ srvparams->krbhostservers))) {
+ goto cleanup;
+ }
+
+ if ((retval = process_host_list (srvparams->krbhostservers,
+ srvparams->servicetype))) {
+ goto cleanup;
+ }
+
+ out_mask |= LDAP_SERVICE_HOSTSERVER;
+
+ /* Set flag to ignore 'add' and 'clear' */
+ srvhost_flag = 1;
+ }
+ else if (!strcmp(argv[i], "-clearservicehost")) {
+ if (++i > argc - 1)
+ goto err_usage;
+
+ if (!srvhost_flag) {
+ /* If attribute doesn't exist, don't permit 'clear' option */
+ if ((in_mask & LDAP_SERVICE_HOSTSERVER) == 0) {
+ /* Send out some proper error message here */
+ com_err(me, EINVAL, "service host list is empty\n");
+ goto err_nomsg;
+ }
+
+ /* Allocate list for processing */
+ list = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (list == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list)))
+ goto cleanup;
+
+ if ((retval = process_host_list (list, srvparams->servicetype))) {
+ goto cleanup;
+ }
+
+ list_modify_str_array(&(srvparams->krbhostservers),
+ (const char**)list, LIST_MODE_DELETE);
+
+ out_mask |= LDAP_SERVICE_HOSTSERVER;
+
+ /* Clean up */
+ free (list);
+ list = NULL;
+ }
+ }
+ else if (!strcmp(argv[i], "-addservicehost")) {
+ if (++i > argc - 1)
+ goto err_usage;
+
+ if (!srvhost_flag) {
+ /* Allocate list for processing */
+ list = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (list == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list)))
+ goto cleanup;
+
+ if ((retval = process_host_list (list, srvparams->servicetype))) {
+ goto cleanup;
+ }
+
+ /* Call list_modify_str_array() only if host server attribute
+ * exists already --Actually, it's better to handle this
+ * within list_modify_str_array()
+ */
+ if (in_mask & LDAP_SERVICE_HOSTSERVER) {
+ /* Re-size existing list */
+ existing_entries = list_count_str_array(srvparams->krbhostservers);
+ new_entries = list_count_str_array(list);
+ temp_ptr = (char **) realloc(srvparams->krbhostservers,
+ sizeof(char *) * (existing_entries + new_entries + 1));
+ if (temp_ptr == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ srvparams->krbhostservers = temp_ptr;
+
+ list_modify_str_array(&(srvparams->krbhostservers),
+ (const char**)list, LIST_MODE_ADD);
+
+ /* Clean up */
+ free (list);
+ list = NULL;
+ }
+ else
+ srvparams->krbhostservers = list;
+
+ out_mask |= LDAP_SERVICE_HOSTSERVER;
+ }
+ }
+ else if (!strcmp(argv[i], "-realm")) {
+ if (++i > argc - 1)
+ goto err_usage;
+
+ if ((in_mask & LDAP_SERVICE_REALMREFERENCE) && (srvparams->krbrealmreferences)) {
+ if (!oldrealmrefs) {
+ /* Store the old realm list for removing rights */
+ oldrealmrefs = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (oldrealmrefs == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ for (j = 0; srvparams->krbrealmreferences[j] != NULL; j++) {
+ oldrealmrefs[j] = strdup(srvparams->krbrealmreferences[j]);
+ if (oldrealmrefs[j] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ oldrealmrefs[j] = NULL;
+ }
+
+ /* Free the old list if available */
+ krb5_free_list_entries (srvparams->krbrealmreferences);
+ free (srvparams->krbrealmreferences);
+ }
+
+ srvparams->krbrealmreferences = (char **)calloc(MAX_LIST_ENTRIES,
+ sizeof(char *));
+ if (srvparams->krbrealmreferences == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
+ srvparams->krbrealmreferences))) {
+ goto cleanup;
+ }
+
+ /* Convert realm names to realm DNs */
+ if ((retval = convert_realm_name2dn_list(
+ srvparams->krbrealmreferences,
+ ldap_context->krbcontainer->DN))) {
+ goto cleanup;
+ }
+
+ out_mask |= LDAP_SERVICE_REALMREFERENCE;
+
+ /* Set flag to ignore 'add' and 'clear' */
+ realmdn_flag = 1;
+ }
+ else if (!strcmp(argv[i], "-clearrealm")) {
+ if (++i > argc - 1)
+ goto err_usage;
+
+ if (!realmdn_flag) {
+ /* If attribute doesn't exist, don't permit 'clear' option */
+ if (((in_mask & LDAP_SERVICE_REALMREFERENCE) == 0) || (srvparams->krbrealmreferences == NULL)) {
+ /* Send out some proper error message here */
+ goto err_nomsg;
+ }
+
+ if (!oldrealmrefs) {
+ /* Store the old realm list for removing rights */
+ oldrealmrefs = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (oldrealmrefs == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ for (j = 0; srvparams->krbrealmreferences[j] != NULL; j++) {
+ oldrealmrefs[j] = strdup(srvparams->krbrealmreferences[j]);
+ if (oldrealmrefs[j] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ oldrealmrefs[j] = NULL;
+ }
+
+ /* Allocate list for processing */
+ list = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (list == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list)))
+ goto cleanup;
+
+ /* Convert realm names to realm DNs */
+ if ((retval = convert_realm_name2dn_list(list,
+ ldap_context->krbcontainer->DN))) {
+ goto cleanup;
+ }
+
+ list_modify_str_array(&(srvparams->krbrealmreferences),
+ (const char**)list, LIST_MODE_DELETE);
+
+ out_mask |= LDAP_SERVICE_REALMREFERENCE;
+
+ /* Clean up */
+ free (list);
+ list = NULL;
+ }
+ }
+ else if (!strcmp(argv[i], "-addrealm")) {
+ if (++i > argc - 1)
+ goto err_usage;
+
+ if (!realmdn_flag) {
+ /* Allocate list for processing */
+ list = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (list == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list)))
+ goto cleanup;
+
+ /* Convert realm names to realm DNs */
+ if ((retval = convert_realm_name2dn_list(list,
+ ldap_context->krbcontainer->DN))) {
+ goto cleanup;
+ }
+
+ if ((in_mask & LDAP_SERVICE_REALMREFERENCE) && (srvparams->krbrealmreferences) && (!oldrealmrefs)) {
+ /* Store the old realm list for removing rights */
+ oldrealmrefs = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (oldrealmrefs == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ for (j = 0; srvparams->krbrealmreferences[j] != NULL; j++) {
+ oldrealmrefs[j] = strdup(srvparams->krbrealmreferences[j]);
+ if (oldrealmrefs[j] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ oldrealmrefs[j] = NULL;
+ }
+
+ /* Call list_modify_str_array() only if realm DN attribute
+ * exists already -- Actually, it's better to handle this
+ * within list_modify_str_array() */
+ if (in_mask & LDAP_SERVICE_REALMREFERENCE) {
+ /* Re-size existing list */
+ existing_entries = list_count_str_array(
+ srvparams->krbrealmreferences);
+ new_entries = list_count_str_array(list);
+ temp_ptr = (char **) realloc(srvparams->krbrealmreferences,
+ sizeof(char *) * (existing_entries + new_entries + 1));
+ if (temp_ptr == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ srvparams->krbrealmreferences = temp_ptr;
+
+ list_modify_str_array(&(srvparams->krbrealmreferences),
+ (const char**)list, LIST_MODE_ADD);
+
+ /* Clean up */
+ free (list);
+ list = NULL;
+ }
+ else
+ srvparams->krbrealmreferences = list;
+
+ out_mask |= LDAP_SERVICE_REALMREFERENCE;
+ }
+ }
+ else {
+ /* Any other argument must be service DN
+ -- skip it */
+ }
+ }
+
+ /* Modify attributes of object */
+ if ((retval = krb5_ldap_modify_service(util_context, srvparams, out_mask)))
+ goto cleanup;
+
+ /* Service rights modification code */
+ if (out_mask & LDAP_SERVICE_REALMREFERENCE) {
+
+ printf("%s","Changing rights for the service object. Please wait ... ");
+ fflush(stdout);
+
+ newrealmrefs = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
+ if (newrealmrefs == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ if ((srvparams != NULL) && (srvparams->krbrealmreferences != NULL)) {
+ for (j = 0; srvparams->krbrealmreferences[j] != NULL; j++) {
+ newrealmrefs[j] = strdup(srvparams->krbrealmreferences[j]);
+ if (newrealmrefs[j] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ newrealmrefs[j] = NULL;
+ }
+ disjoint_members(oldrealmrefs, newrealmrefs);
+
+ /* Delete the rights for the given service, on each of the realm
+ * container & subtree in the old realm reference list.
+ */
+ if (oldrealmrefs) {
+ rightsmask = 0;
+ rightsmask |= LDAP_REALM_RIGHTS;
+ rightsmask |= LDAP_SUBTREE_RIGHTS;
+
+ for (i = 0; (oldrealmrefs[i] != NULL); i++) {
+ /* Get the realm name, not the dn */
+ temprdns = ldap_explode_dn(oldrealmrefs[i], 1);
+
+ if (temprdns[0] == NULL) {
+ retval = EINVAL;
+ goto cleanup;
+ }
+
+ realmName = strdup(temprdns[0]);
+ if (realmName == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ if ((retval = krb5_ldap_read_realm_params(util_context,
+ realmName, &rparams, &rmask))) {
+ com_err(me, retval, "while reading information of realm '%s'",
+ realmName);
+ goto err_nomsg;
+ }
+
+ if ((retval = krb5_ldap_delete_service_rights(util_context,
+ srvparams->servicetype, srvparams->servicedn,
+ realmName, rparams->subtree, rightsmask))) {
+ printf("failed\n");
+ com_err(me, retval, "while assigning rights '%s'",
+ srvparams->servicedn);
+ goto err_nomsg;
+ }
+
+ if (rparams)
+ krb5_ldap_free_realm_params(rparams);
+ }
+ }
+
+ /* Add the rights for the given service, on each of the realm
+ * container & subtree in the new realm reference list.
+ */
+ if (newrealmrefs) {
+ rightsmask = 0;
+ rightsmask |= LDAP_REALM_RIGHTS;
+ rightsmask |= LDAP_SUBTREE_RIGHTS;
+
+ for (i = 0; (newrealmrefs[i] != NULL); i++) {
+ /* Get the realm name, not the dn */
+ temprdns = ldap_explode_dn(newrealmrefs[i], 1);
+
+ if (temprdns[0] == NULL) {
+ retval = EINVAL;
+ goto cleanup;
+ }
+
+ realmName = strdup(temprdns[0]);
+ if (realmName == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ if ((retval = krb5_ldap_read_krbcontainer_params(util_context,
+ &(ldap_context->krbcontainer)))) {
+ com_err(me, retval,
+ "while reading Kerberos container information");
+ goto cleanup;
+ }
+
+ if ((retval = krb5_ldap_read_realm_params(util_context,
+ realmName, &rparams, &rmask))) {
+ com_err(me, retval, "while reading information of realm '%s'",
+ realmName);
+ goto err_nomsg;
+ }
+
+ if ((retval = krb5_ldap_add_service_rights(util_context,
+ srvparams->servicetype, srvparams->servicedn,
+ realmName, rparams->subtree, rightsmask))) {
+ printf("failed\n");
+ com_err(me, retval, "while assigning rights '%s'",
+ srvparams->servicedn);
+ goto err_nomsg;
+ }
+
+ if (rparams) {
+ krb5_ldap_free_realm_params(rparams);
+ rparams = NULL;
+ }
+ }
+ printf("done\n");
+ }
+ }
+ goto cleanup;
+
+err_usage:
+ print_usage = TRUE;
+
+err_nomsg:
+ no_msg = TRUE;
+
+cleanup:
+ /* Clean-up structure */
+ krb5_ldap_free_service(util_context, srvparams);
+
+ if (servicedn)
+ free(servicedn);
+
+ if (list) {
+ free(list);
+ list = NULL;
+ }
+
+ if (oldrealmrefs) {
+ for (i = 0; oldrealmrefs[i] != NULL; i++)
+ free(oldrealmrefs[i]);
+ free(oldrealmrefs);
+ }
+
+ if (newrealmrefs) {
+ for (i = 0; newrealmrefs[i] != NULL; i++)
+ free(newrealmrefs[i]);
+ free(newrealmrefs);
+ }
+ if (realmName) {
+ free(realmName);
+ realmName = NULL;
+ }
+
+ if (print_usage)
+ db_usage(MODIFY_SERVICE);
+
+ if (retval) {
+ if (!no_msg)
+ com_err(me, retval, "while modifying service object");
+ exit_status++;
+ }
+
+ return;
+}
+
+
+/*
+ * This function will delete the entry corresponding to the service object
+ * from the service password file.
+ */
+static krb5_error_code
+rem_service_entry_from_file(argc, argv, file_name, service_object)
+int argc;
+char *argv[];
+char *file_name;
+char *service_object;
+{
+ int st = EINVAL;
+ char *me = argv[0];
+ char *tmp_file = NULL;
+ int tmpfd = -1;
+ FILE *pfile = NULL;
+ unsigned int len = 0;
+ char line[MAX_LEN]={0};
+ mode_t omask = umask(077);
+
+ /* Check for permissions on the password file */
+ if (access(file_name, W_OK) == -1) {
+ /* If the specified file itself is not there, no need to show error */
+ if (errno == ENOENT) {
+ st=0;
+ goto cleanup;
+ }
+ else {
+ com_err(me, errno, "while deleting entry from file %s", file_name);
+ goto cleanup;
+ }
+ }
+
+ /* Create a temporary file which contains all the entries except the
+ entry for the given service dn */
+ pfile = fopen(file_name, "r+");
+ if (pfile == NULL) {
+ com_err(me, errno, "while deleting entry from file %s", file_name);
+ goto cleanup;
+ }
+
+ /* Create a new file with the extension .tmp */
+ tmp_file = (char *)malloc(strlen(file_name) + 4 + 1);
+ if (tmp_file == NULL) {
+ com_err(me, ENOMEM, "while deleting entry from file");
+ fclose(pfile);
+ goto cleanup;
+ }
+ snprintf (tmp_file, strlen(file_name) + 4 + 1, "%s%s", file_name, ".tmp");
+
+
+ tmpfd = creat(tmp_file, S_IRUSR|S_IWUSR);
+ umask(omask);
+ if (tmpfd == -1) {
+ com_err(me, errno, "while deleting entry from file\n");
+ fclose(pfile);
+ goto cleanup;
+ }
+
+ /* Copy only those lines which donot have the specified service dn */
+ while(fgets(line, MAX_LEN, pfile) != NULL) {
+ if (( strstr(line, service_object) != NULL ) &&
+ ( line[strlen(service_object)] == '#')) {
+ continue;
+ }
+ else {
+ len = strlen(line);
+ if (write(tmpfd, line, len) != len) {
+ com_err(me, errno, "while deleting entry from file\n");
+ close(tmpfd);
+ unlink(tmp_file);
+ fclose(pfile);
+ goto cleanup;
+ }
+ }
+ }
+
+ fclose(pfile);
+ if (unlink(file_name) == 0) {
+ link(tmp_file, file_name);
+ }
+ else {
+ com_err(me, errno, "while deleting entry from file\n");
+ }
+ unlink(tmp_file);
+
+ st=0;
+
+ cleanup:
+
+ if(tmp_file)
+ free(tmp_file);
+
+ return st;
+}
+
+
+/*
+ * This function will delete the service object from the LDAP Server
+ * and unlink the references to the Realm objects (if any)
+ */
+void
+kdb5_ldap_destroy_service(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int i = 0;
+ char buf[5] = {0};
+ krb5_error_code retval = EINVAL;
+ int force = 0;
+ char *servicedn = NULL;
+ char *stashfilename = NULL;
+ int mask = 0;
+ krb5_ldap_service_params *lserparams = NULL;
+ krb5_boolean print_usage = FALSE;
+
+ if ((argc < 2) || (argc > 5)) {
+ exit_status++;
+ goto err_usage;
+ }
+
+ for( i=1; i < argc; i++) {
+
+ if(strcmp(argv[i],"-force")==0) {
+ force++;
+ }
+ else if(strcmp(argv[i],"-f")==0) {
+ if(argv[i+1]) {
+ stashfilename=strdup(argv[i+1]);
+ if(stashfilename == NULL) {
+ com_err(argv[0], ENOMEM, "while destroying service");
+ exit_status++;
+ goto cleanup;
+ }
+ i++;
+ }
+ else {
+ exit_status++;
+ goto err_usage;
+ }
+ }
+ else {
+ if((argv[i]) && ( servicedn == NULL) ){
+ servicedn=strdup(argv[i]);
+ if(servicedn == NULL) {
+ com_err(argv[0], ENOMEM, "while destroying service");
+ exit_status++;
+ goto cleanup;
+ }
+ }
+ else {
+ exit_status++;
+ goto err_usage;
+ }
+ }
+ }
+
+ if(!servicedn) {
+ exit_status++;
+ goto err_usage;
+ }
+
+ if (!force) {
+ printf("This will delete the service object '%s', are you sure?\n", servicedn);
+ printf("(type 'yes' to confirm)? ");
+ if (fgets(buf, sizeof(buf), stdin) == NULL) {
+ exit_status++;
+ goto cleanup;;
+ }
+ if (strcmp(buf, yes)) {
+ exit_status++;
+ goto cleanup;
+ }
+ }
+
+ if ((retval = krb5_ldap_read_service( util_context, servicedn,
+ &lserparams, &mask))) {
+ com_err(argv[0], retval, "while destroying service '%s'",servicedn );
+ exit_status++;
+ goto cleanup;
+ }
+
+ retval = krb5_ldap_delete_service(util_context, lserparams, servicedn);
+
+ if (retval) {
+ com_err(argv[0], retval, "while destroying service '%s'", servicedn);
+ exit_status++;
+ goto cleanup;
+ }
+
+ if(stashfilename == NULL) {
+ stashfilename = strdup(DEF_SERVICE_PASSWD_FILE);
+ if(stashfilename == NULL) {
+ com_err(argv[0], ENOMEM, "while destroying service");
+ exit_status++;
+ goto cleanup;
+ }
+ }
+ printf("** service object '%s' deleted.\n", servicedn);
+ retval = rem_service_entry_from_file(argc, argv, stashfilename, servicedn );
+
+ if(retval)
+ printf("** error removing service object entry '%s' from password file.\n",
+ servicedn);
+
+ goto cleanup;
+
+
+ err_usage:
+ print_usage = TRUE;
+
+ cleanup:
+
+ if(lserparams) {
+ krb5_ldap_free_service(util_context, lserparams);
+ }
+
+ if(servicedn) {
+ free(servicedn);
+ }
+
+ if(stashfilename) {
+ free(stashfilename);
+ }
+
+ if(print_usage) {
+ db_usage(DESTROY_SERVICE);
+ }
+
+ return;
+}
+
+
+/*
+ * This function will display information about the given service object
+ */
+void kdb5_ldap_view_service(argc, argv)
+ int argc;
+ char *argv[];
+{
+ krb5_ldap_service_params *lserparams = NULL;
+ krb5_error_code retval = 0;
+ char *servicedn = NULL;
+ int mask = 0;
+ krb5_boolean print_usage = FALSE;
+
+ if (!(argc == 2)) {
+ exit_status++;
+ goto err_usage;
+ }
+
+ servicedn=strdup(argv[1]);
+ if(servicedn == NULL) {
+ com_err(argv[0], ENOMEM, "while viewing service");
+ exit_status++;
+ goto cleanup;
+ }
+
+ if ((retval = krb5_ldap_read_service( util_context, servicedn, &lserparams, &mask))) {
+ com_err(argv[0], retval, "while viewing service '%s'",servicedn );
+ exit_status++;
+ goto cleanup;
+ }
+
+ print_service_params(lserparams, mask);
+
+ goto cleanup;
+
+ err_usage:
+ print_usage = TRUE;
+
+ cleanup:
+
+ if(lserparams) {
+ krb5_ldap_free_service(util_context, lserparams);
+ }
+
+ if(servicedn)
+ free(servicedn);
+
+ if(print_usage) {
+ db_usage(VIEW_SERVICE);
+ }
+
+ return;
+}
+
+
+/*
+ * This function will list the DNs of kerberos services present on
+ * the LDAP Server under a specific sub-tree (entire tree by default)
+ */
+void kdb5_ldap_list_services(argc, argv)
+ int argc;
+ char *argv[];
+{
+ char *me = argv[0];
+ krb5_error_code retval = 0;
+ char *basedn = NULL;
+ char **list = NULL;
+ char **plist = NULL;
+ krb5_boolean print_usage = FALSE;
+
+ /* Check for number of arguments */
+ if ((argc != 1) && (argc != 3)) {
+ exit_status++;
+ goto err_usage;
+ }
+
+ /* Parse base DN argument if present */
+ if (argc == 3) {
+ if (strcmp(argv[1], "-basedn")) {
+ retval = EINVAL;
+ goto err_usage;
+ }
+
+ basedn = strdup(argv[2]);
+ if (basedn == NULL) {
+ com_err(me, ENOMEM, "while listing services");
+ exit_status++;
+ goto cleanup;
+ }
+ }
+
+ retval = krb5_ldap_list_services(util_context, basedn, &list);
+ if((retval != 0) || (list == NULL)) {
+ exit_status++;
+ goto cleanup;
+ }
+
+ for(plist = list; *plist != NULL; plist++) {
+ printf("%s\n", *plist);
+ }
+
+ goto cleanup;
+
+err_usage:
+ print_usage = TRUE;
+
+cleanup:
+ if (list != NULL) {
+ krb5_free_list_entries (list);
+ free (list);
+ }
+
+ if (basedn)
+ free (basedn);
+
+ if (print_usage) {
+ db_usage(LIST_SERVICE);
+ }
+
+ if (retval) {
+ com_err(me, retval, "while listing policy objects");
+ exit_status++;
+ }
+
+ return;
+}
+
+
+/*
+ * This function will print the service object information
+ * to the standard output
+ */
+static void
+print_service_params(lserparams, mask)
+ krb5_ldap_service_params *lserparams;
+ int mask;
+{
+ int i=0;
+
+ /* Print the service dn */
+ printf("%20s%-20s\n","Service dn: ",lserparams->servicedn);
+
+ /* Print the service type of the object to be read */
+ if( lserparams->servicetype == LDAP_KDC_SERVICE ) {
+ printf("%20s%-20s\n","Service type: ","kdc");
+ }
+ else if( lserparams->servicetype == LDAP_ADMIN_SERVICE ) {
+ printf("%20s%-20s\n","Service type: ","admin");
+ }
+ else if( lserparams->servicetype == LDAP_PASSWD_SERVICE ) {
+ printf("%20s%-20s\n","Service type: ","pwd");
+ }
+
+ /* Print the host server values */
+ printf("%20s\n","Service host list: ");
+ if ( mask & LDAP_SERVICE_HOSTSERVER ) {
+ for ( i=0; lserparams->krbhostservers[i] != NULL; ++i ) {
+ printf("%20s%-50s\n","",lserparams->krbhostservers[i]);
+ }
+ }
+
+ /* Print the realm reference dn values */
+ printf("%20s\n","Realm DN list: ");
+ if ( mask & LDAP_SERVICE_REALMREFERENCE ) {
+ for ( i=0; lserparams && lserparams->krbrealmreferences && lserparams->krbrealmreferences[i] != NULL; ++i ) {
+ printf("%20s%-50s\n","",lserparams->krbrealmreferences[i]);
+ }
+ }
+
+ return;
+}
+
+
+/*
+ * This function will generate random password of length(RANDOM_PASSWD_LEN)
+ *
+ *
+ * INPUT:
+ * ctxt - context
+ *
+ * OUTPUT:
+ * RANDOM_PASSWD_LEN length random password
+ */
+static int generate_random_password(krb5_context ctxt, char **randpwd, unsigned int *passlen)
+{
+ char *random_pwd = NULL;
+ int ret = 0;
+ krb5_data data;
+ int i=0;
+ /*int len = 0;*/
+
+ /* setting random password length in the range 16-32 */
+ srand((unsigned int)(time(0) ^ getpid()));
+
+ data.length = RANDOM_PASSWD_LEN;
+ random_pwd = (char *)malloc(data.length + 1);
+ if (random_pwd == NULL) {
+ com_err("setsrvpw", ENOMEM, "while generating random password");
+ return ENOMEM;
+ }
+ memset(random_pwd, 0, data.length + 1);
+ data.data = random_pwd;
+
+ ret = krb5_c_random_make_octets(ctxt, &data);
+ if(ret) {
+ com_err("setsrvpw", ret, "Error generating random password");
+ free(random_pwd);
+ return ret;
+ }
+
+ for (i=0; i<data.length; i++)
+ {
+ /* restricting to ascii chars. Need to change this when 8.8 supports */
+ if ((unsigned char)random_pwd[i] > 127)
+ {
+ random_pwd[i] = (unsigned char)random_pwd[i] % 128;
+ }
+ else if (random_pwd[i] == 0)
+ {
+ random_pwd[i] = (rand()/(RAND_MAX/127 + 1))+1;
+ }
+ }
+
+ *randpwd = random_pwd;
+ *passlen = data.length;
+
+ return 0;
+}
+
+
+/*
+ * This function will set the password of the service object in the directory
+ * and/or the specified service password file.
+ *
+ *
+ * INPUT:
+ * argc - contains the number of arguments for this sub-command
+ * argv - array of arguments for this sub-command
+ *
+ * OUTPUT:
+ * void
+ */
+int
+kdb5_ldap_set_service_password(argc, argv)
+ int argc;
+ char **argv;
+{
+ krb5_ldap_context *lparams = NULL;
+ char *file_name = NULL;
+ char *tmp_file = NULL;
+ char *me = argv[0];
+ int filelen = 0;
+ int random_passwd = 0;
+ int set_dir_pwd = 1;
+ krb5_boolean db_init_local = FALSE;
+ char *service_object = NULL;
+ char *passwd = NULL;
+ char *prompt1 = NULL;
+ char *prompt2 = NULL;
+ unsigned int passwd_len = 0;
+ krb5_error_code errcode = -1;
+ int retval = 0, i = 0;
+ unsigned int len = 0;
+ krb5_boolean print_usage = FALSE;
+ FILE *pfile = NULL;
+ char *str = NULL;
+ char line[MAX_LEN];
+ kdb5_dal_handle *dal_handle = NULL;
+ struct data encrypted_passwd = {0, NULL};
+
+ /* The arguments for setsrv password should contain the service object DN
+ * and options to specify whether the password should be updated in file only
+ * or both file and directory. So the possible combination of arguments are:
+ * setsrvpw servicedn wherein argc is 2
+ * setsrvpw -fileonly servicedn wherein argc is 3
+ * setsrvpw -randpw servicedn wherein argc is 3
+ * setsrvpw -f filename servicedn wherein argc is 4
+ * setsrvpw -fileonly -f filename servicedn wherein argc is 5
+ * setsrvpw -randpw -f filename servicedn wherein argc is 5
+ */
+ if ((argc < 2) || (argc > 5)) {
+ print_usage = TRUE;
+ goto cleanup;
+ }
+
+ dal_handle = (kdb5_dal_handle *)util_context->db_context;
+ lparams = (krb5_ldap_context *) dal_handle->db_context;
+
+ if (lparams == NULL) {
+ printf("%s: Invalid LDAP handle\n", me);
+ goto cleanup;
+ }
+
+ /* Parse the arguments */
+ for(i = 1; i < argc -1 ; i++) {
+ if (strcmp(argv[i], "-randpw") == 0) {
+ random_passwd = 1;
+ }
+ else if (strcmp(argv[i], "-fileonly") == 0) {
+ set_dir_pwd = 0;
+ }
+ else if (strcmp(argv[i], "-f") == 0) {
+ if (argv[++i] == NULL) {
+ print_usage = TRUE;
+ goto cleanup;
+ }
+
+ file_name = strdup(argv[i]);
+ if (file_name == NULL) {
+ com_err(me, ENOMEM, "while setting service object password");
+ goto cleanup;
+ }
+ /* Verify if the file location has the proper file name
+ * for eg, if the file location is a directory like /home/temp/,
+ * we reject it.
+ */
+ filelen = strlen(file_name);
+ if ((filelen == 0) || (file_name[filelen-1] == '/')) {
+ printf("%s: Filename not specified for setting service object password\n", me);
+ print_usage = TRUE;
+ goto cleanup;
+ }
+ }
+ else {
+ printf("%s: Invalid option specified for \"setsrvpw\" command\n", me);
+ print_usage = TRUE;
+ goto cleanup;
+ }
+ }
+
+ if (i != argc-1) {
+ print_usage = TRUE;
+ goto cleanup;
+ }
+
+ service_object = strdup(argv[i]);
+ if (service_object == NULL) {
+ com_err(me, ENOMEM, "while setting service object password");
+ goto cleanup;
+ }
+
+ if (strlen(service_object) == 0) {
+ printf("%s: Service object not specified for \"setsrvpw\" command\n", me);
+ print_usage = TRUE;
+ goto cleanup;
+ }
+
+ if (service_object[0] == '-') {
+ print_usage = TRUE;
+ goto cleanup;
+ }
+
+ if (file_name == NULL) {
+ file_name = strdup(DEF_SERVICE_PASSWD_FILE);
+ if (file_name == NULL) {
+ com_err(me, ENOMEM, "while setting service object password");
+ goto cleanup;
+ }
+ }
+
+ if (set_dir_pwd) {
+ if ( db_inited == FALSE ) {
+ if ((errcode = krb5_ldap_db_init(util_context, lparams))) {
+ com_err(me, errcode, "while initializing database");
+ goto cleanup;
+ }
+ db_init_local = TRUE;
+ }
+ }
+
+ if (random_passwd) {
+ if (!set_dir_pwd) {
+ printf("%s: Invalid option specified for \"setsrvpw\" command\n", me);
+ print_usage = TRUE;
+ goto cleanup;
+ }
+ else {
+ /* Generate random password */
+
+ if ((errcode = generate_random_password(util_context, &passwd, &passwd_len))) {
+ printf("%s: Failed to set service object password\n", me);
+ goto cleanup;
+ }
+ passwd_len = strlen(passwd);
+ }
+ }
+ else {
+ /* Get the service object password from the terminal */
+ passwd = (char *)malloc(MAX_SERVICE_PASSWD_LEN + 1);
+ if (passwd == NULL) {
+ com_err(me, ENOMEM, "while setting service object password");
+ goto cleanup;
+ }
+ memset(passwd, 0, MAX_SERVICE_PASSWD_LEN + 1);
+ passwd_len = MAX_SERVICE_PASSWD_LEN;
+
+ len = strlen(service_object);
+ /* size of allocation=strlen of servicedn + strlen("Password for \" \"")=20 */
+ prompt1 = (char *)malloc(len + 20);
+ if (prompt1 == NULL) {
+ com_err(me, ENOMEM, "while setting service object password");
+ goto cleanup;
+ }
+ sprintf(prompt1, "Password for \"%s\"", service_object);
+
+ /* size of allocation=strlen of servicedn + strlen("Re-enter Password for \" \"")=30 */
+ prompt2 = (char *)malloc(len + 30);
+ if (prompt2 == NULL) {
+ com_err(me, ENOMEM, "while setting service object password");
+ free(prompt1);
+ goto cleanup;
+ }
+ sprintf(prompt2, "Re-enter password for \"%s\"", service_object);
+
+ retval = krb5_read_password(util_context, prompt1, prompt2, passwd, &passwd_len);
+ free(prompt1);
+ free(prompt2);
+ if (retval) {
+ com_err(me, retval, "while setting service object password");
+ memset(passwd, 0, MAX_SERVICE_PASSWD_LEN);
+ goto cleanup;
+ }
+ if (passwd_len == 0) {
+ printf("%s: Invalid password\n", me);
+ memset(passwd, 0, MAX_SERVICE_PASSWD_LEN);
+ goto cleanup;
+ }
+ passwd_len = strlen(passwd);
+ }
+
+ /* Hex the password */
+ {
+ krb5_data pwd, hex;
+ pwd.length = passwd_len;
+ pwd.data = passwd;
+
+ errcode = tohex(pwd, &hex);
+ if (errcode != 0) {
+ if(hex.length != 0)
+ free(hex.data);
+ com_err(me, errcode, "Failed to convert the password to hex");
+ goto cleanup;
+ }
+ /* Password = {CRYPT}<encrypted password>:<encrypted key> */
+ encrypted_passwd.value = (unsigned char *)malloc(strlen(service_object) +
+ 1 + 5 + hex.length + 2);
+ if (encrypted_passwd.value == NULL) {
+ com_err(me, ENOMEM, "while setting service object password");
+ memset(passwd, 0, passwd_len);
+ free(hex.data);
+ goto cleanup;
+ }
+ encrypted_passwd.value[strlen(service_object) +
+ 1 + 5 + hex.length + 1] = '\0';
+ sprintf((char *)encrypted_passwd.value, "%s#{HEX}%s\n", service_object, hex.data);
+ encrypted_passwd.len = strlen((char *)encrypted_passwd.value);
+ }
+
+ /* We should check if the file exists and we have permission to write into that file */
+ if (access(file_name, W_OK) == -1) {
+ if (errno == ENOENT) {
+ mode_t omask;
+ int fd = -1;
+
+ printf("File does not exist. Creating the file %s...\n", file_name );
+ omask = umask(077);
+ fd = creat(file_name, S_IRUSR|S_IWUSR);
+ umask(omask);
+ if (fd == -1) {
+ com_err(me, errno, "Error creating file %s", file_name);
+ memset(passwd, 0, passwd_len);
+ goto cleanup;
+ }
+ close(fd);
+ }
+ else {
+ com_err(me, errno, "Unable to access the file %s", file_name);
+ memset(passwd, 0, passwd_len);
+ goto cleanup;
+ }
+ }
+
+ if (set_dir_pwd) {
+ if ((errcode = krb5_ldap_set_service_passwd(util_context, service_object, passwd)) != 0) {
+ com_err(me, errcode, "Failed to set password for service object %s", service_object);
+ memset(passwd, 0, passwd_len);
+ goto cleanup;
+ }
+ }
+
+ memset(passwd, 0, passwd_len);
+
+
+ /* TODO: file lock for the service password file */
+ /* set password in the file */
+ pfile = fopen(file_name, "r+");
+ if (pfile == NULL) {
+ com_err(me, errno, "Failed to open file %s", file_name);
+ goto cleanup;
+ }
+
+ while(fgets(line, MAX_LEN, pfile) != NULL) {
+ if ((str = strstr(line, service_object)) != NULL) {
+ if(line[strlen(service_object)] == '#') {
+ break;
+ }
+ str = NULL;
+ }
+ }
+ if (str == NULL) {
+ if(feof(pfile)) {
+ /* If the service object dn is not present in the service password file */
+ if (fwrite(encrypted_passwd.value, (unsigned int)encrypted_passwd.len, 1, pfile) != 1) {
+ com_err(me, errno, "Failed to write service object password to file");
+ goto cleanup;
+ }
+ }
+ else {
+ com_err(me, errno, "Error reading service object password file");
+ goto cleanup;
+ }
+ fclose(pfile);
+ pfile = NULL;
+ }
+ else {
+ /* Password entry for the service object is already present in the file */
+ /* Delete the existing entry and add the new entry */
+ FILE *newfile = NULL;
+ mode_t omask;
+
+ /* Create a new file with the extension .tmp */
+ tmp_file = (char *) malloc(sizeof(char) * (strlen(file_name) + 4 + 1));
+ if (tmp_file == NULL) {
+ com_err(me, ENOMEM, "while setting service object password");
+ goto cleanup;
+ }
+ sprintf(tmp_file,"%s.%s",file_name,"tmp");
+
+ omask = umask(077);
+ newfile = fopen(tmp_file, "w+");
+ umask(omask);
+ if (newfile == NULL) {
+ com_err(me, errno, "Error creating file %s", tmp_file);
+ goto cleanup;
+ }
+
+
+ fseek(pfile, 0, SEEK_SET);
+ while(fgets(line, MAX_LEN, pfile) != NULL) {
+ if (((str = strstr(line, service_object)) != NULL) && (line[strlen(service_object)] == '#')) {
+ if (fprintf(newfile, "%s", encrypted_passwd.value) < 0) {
+ com_err(me, errno, "Failed to write service object password to file");
+ fclose(newfile);
+ unlink(tmp_file);
+ goto cleanup;
+ }
+ }
+ else {
+ len = strlen(line);
+ if (fprintf(newfile, "%s", line) < 0) {
+ com_err(me, errno, "Failed to write service object password to file");
+ fclose(newfile);
+ unlink(tmp_file);
+ goto cleanup;
+ }
+ }
+ }
+
+ if(!feof(pfile)) {
+ com_err(me, errno, "Error reading service object password file");
+ fclose(newfile);
+ unlink(tmp_file);
+ goto cleanup;
+ }
+
+ /* TODO: file lock for the service password file */
+ fclose(pfile);
+ pfile = NULL;
+
+ fclose(newfile);
+ newfile = NULL;
+
+ if (unlink(file_name) == 0) {
+ link(tmp_file, file_name);
+ }
+ else {
+ com_err(me, errno, "Failed to write service object password to file");
+ unlink(tmp_file);
+ goto cleanup;
+ }
+ unlink(tmp_file);
+ }
+ errcode = 0;
+
+cleanup:
+ if (db_init_local)
+ krb5_ldap_close(util_context);
+
+ if (service_object)
+ free(service_object);
+
+ if (file_name)
+ free(file_name);
+
+ if (passwd)
+ free(passwd);
+
+ if (encrypted_passwd.value)
+ free(encrypted_passwd.value);
+
+ if (pfile)
+ fclose(pfile);
+
+ if (tmp_file)
+ free(tmp_file);
+
+ if (print_usage)
+ db_usage(SET_SRV_PW);
+
+ return errcode;
+}
+
+#else /* #ifdef HAVE_EDIRECTORY */
+
+/*
+ * Convert the user supplied password into hexadecimal and stash it. Only a
+ * little more secure than storing plain password in the file ...
+ */
+int
+kdb5_ldap_stash_service_password(argc, argv)
+ int argc;
+ char **argv;
+{
+ int ret = 0;
+ unsigned int passwd_len = 0;
+ char *me = argv[0];
+ char *service_object = NULL;
+ char *file_name = NULL, *tmp_file = NULL;
+ char passwd[MAX_SERVICE_PASSWD_LEN];
+ char *str = NULL;
+ char line[MAX_LEN];
+ FILE *pfile = NULL;
+ krb5_boolean print_usage = FALSE;
+ krb5_data hexpasswd = {0, 0, NULL};
+
+ /*
+ * Format:
+ * stashsrvpw [-f filename] service_dn
+ * where
+ * 'service_dn' is the DN of the service object
+ * 'filename' is the path of the stash file
+ */
+ if (argc != 2 && argc != 4) {
+ print_usage = TRUE;
+ goto cleanup;
+ }
+
+ if (argc == 4) {
+ /* Find the stash file name */
+ if (strcmp (argv[1], "-f") == 0) {
+ file_name = strdup (argv[2]);
+ service_object = strdup (argv[3]);
+ } else if (strcmp (argv[2], "-f") == 0) {
+ file_name = strdup (argv[3]);
+ service_object = strdup (argv[1]);
+ } else {
+ print_usage = TRUE;
+ goto cleanup;
+ }
+ if (file_name == NULL) {
+ com_err(me, ENOMEM, "while setting service object password");
+ goto cleanup;
+ }
+ } else { /* argc == 2 */
+ char *section;
+
+ service_object = strdup (argv[1]);
+ if (service_object == NULL) {
+ com_err(me, ENOMEM, "while setting service object password");
+ goto cleanup;
+ }
+
+ /* Pick up the stash-file name from krb5.conf */
+ profile_get_string( util_context->profile, KDB_REALM_SECTION,
+ util_context->default_realm, KDB_MODULE_POINTER, NULL, &section );
+
+ if(section == NULL) {
+ profile_get_string( util_context->profile, KDB_MODULE_DEF_SECTION,
+ KDB_MODULE_POINTER, NULL, NULL, &section);
+ if(section == NULL) {
+ /* Stash file path neither in krb5.conf nor on command line */
+ file_name = strdup(DEF_SERVICE_PASSWD_FILE);
+ goto done;
+ }
+ }
+
+ profile_get_string (util_context->profile, KDB_MODULE_SECTION, section,
+ "ldap_service_password_file", NULL, &file_name);
+ }
+done:
+
+ /* Get password from user */
+ {
+ char prompt1[256], prompt2[256];
+
+ /* Get the service object password from the terminal */
+ memset(passwd, 0, sizeof (passwd));
+ passwd_len = sizeof (passwd);
+
+ /* size of prompt = strlen of servicedn + strlen("Password for \" \"") */
+ assert (sizeof (prompt1) > (strlen (service_object)
+ + sizeof ("Password for \" \"")));
+ sprintf(prompt1, "Password for \"%s\"", service_object);
+
+ /* size of prompt = strlen of servicedn + strlen("Re-enter Password for \" \"") */
+ assert (sizeof (prompt2) > (strlen (service_object)
+ + sizeof ("Re-enter Password for \" \"")));
+ sprintf(prompt2, "Re-enter password for \"%s\"", service_object);
+
+ ret = krb5_read_password(util_context, prompt1, prompt2, passwd, &passwd_len);
+ if (ret != 0) {
+ com_err(me, ret, "while setting service object password");
+ memset(passwd, 0, sizeof (passwd));
+ goto cleanup;
+ }
+
+ if (passwd_len == 0) {
+ printf("%s: Invalid password\n", me);
+ memset(passwd, 0, MAX_SERVICE_PASSWD_LEN);
+ goto cleanup;
+ }
+ }
+
+ /* Convert the password to hexadecimal */
+ {
+ krb5_data pwd;
+
+ pwd.length = passwd_len;
+ pwd.data = passwd;
+
+ ret = tohex(pwd, &hexpasswd);
+ if(ret != 0){
+ if(hexpasswd.length != 0)
+ free(hexpasswd.data);
+ com_err(me, ret, "Failed to convert the password to hexadecimal");
+ goto cleanup;
+ }
+ }
+
+ /* TODO: file lock for the service passowrd file */
+
+ /* set password in the file */
+ pfile = fopen(file_name, "a+");
+ if (pfile == NULL) {
+ com_err(me, errno, "Failed to open file %s: %s", file_name,
+ strerror (errno));
+ goto cleanup;
+ }
+ rewind (pfile);
+
+ while (fgets (line, MAX_LEN, pfile) != NULL) {
+ if ((str = strstr (line, service_object)) != NULL) {
+ /* White spaces not allowed */
+ if (line [strlen (service_object)] == '#')
+ break;
+ str = NULL;
+ }
+ }
+
+ if (str == NULL) {
+ if(feof(pfile)) {
+ /* If the service object dn is not present in the service password file */
+ if (fprintf(pfile, "%s#{HEX}%s\n", service_object, hexpasswd.data) < 0) {
+ com_err(me, errno, "Failed to write service object password to file");
+ fclose(pfile);
+ goto cleanup;
+ }
+ }
+ else {
+ com_err(me, errno, "Error reading service object password file");
+ fclose(pfile);
+ goto cleanup;
+ }
+ fclose(pfile);
+ } else {
+ /*
+ * Password entry for the service object is already present in the file
+ * Delete the existing entry and add the new entry
+ */
+ FILE *newfile;
+
+ mode_t omask;
+
+ /* Create a new file with the extension .tmp */
+ tmp_file = (char *) malloc(sizeof(char) * (strlen(file_name) + 4 + 1));
+ if (tmp_file == NULL) {
+ com_err(me, ENOMEM, "while setting service object password");
+ fclose(pfile);
+ goto cleanup;
+ }
+ sprintf(tmp_file,"%s.%s",file_name,"tmp");
+
+ omask = umask(077);
+ newfile = fopen(tmp_file, "w");
+ umask (omask);
+ if (newfile == NULL) {
+ com_err(me, errno, "Error creating file %s", tmp_file);
+ fclose(pfile);
+ goto cleanup;
+ }
+
+ fseek(pfile, 0, SEEK_SET);
+ while(fgets(line, MAX_LEN, pfile) != NULL) {
+ if (((str = strstr(line, service_object)) != NULL) &&
+ (line[strlen(service_object)] == '#')) {
+ if (fprintf(newfile, "%s#{HEX}%s\n", service_object, hexpasswd.data) < 0) {
+ com_err(me, errno, "Failed to write service object password to file");
+ fclose(newfile);
+ unlink(tmp_file);
+ fclose(pfile);
+ goto cleanup;
+ }
+ } else {
+ if (fprintf (newfile, "%s", line) < 0) {
+ com_err(me, errno, "Failed to write service object password to file");
+ fclose(newfile);
+ unlink(tmp_file);
+ fclose(pfile);
+ goto cleanup;
+ }
+ }
+ }
+
+ if(!feof(pfile)) {
+ com_err(me, errno, "Error reading service object password file");
+ fclose(newfile);
+ unlink(tmp_file);
+ fclose(pfile);
+ goto cleanup;
+ }
+
+ /* TODO: file lock for the service passowrd file */
+
+ fclose(pfile);
+ fclose(newfile);
+
+ ret = rename(tmp_file, file_name);
+ if (ret != 0) {
+ com_err(me, errno, "Failed to write service object password to "
+ "file");
+ goto cleanup;
+ }
+ }
+ ret = 0;
+
+cleanup:
+
+ if (service_object)
+ free(service_object);
+
+ if (file_name)
+ free(file_name);
+
+ if (tmp_file)
+ free(tmp_file);
+
+ if (print_usage)
+ usage();
+/* db_usage(STASH_SRV_PW); */
+
+ return ret;
+}
+
+#endif /* #ifdef HAVE_EDIRECTORY */
diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.h b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.h
new file mode 100644
index 000000000..e10a055bc
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.h
@@ -0,0 +1,71 @@
+/*
+ * kadmin/ldap_util/kdb5_services.h
+ */
+
+/* Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ldap_misc.h"
+
+#define MAX_DN_CHARS 256
+#define HOST_INFO_DELIMITER '#'
+#define PROTOCOL_STR_LEN 3
+#define PROTOCOL_NUM_UDP 0
+#define PROTOCOL_NUM_TCP 1
+#define PROTOCOL_DEFAULT_KDC PROTOCOL_NUM_UDP
+#define PROTOCOL_DEFAULT_ADM PROTOCOL_NUM_TCP
+#define PROTOCOL_DEFAULT_PWD PROTOCOL_NUM_UDP
+#define PORT_STR_LEN 5
+#define PORT_DEFAULT_KDC 88
+#define PORT_DEFAULT_ADM 749
+#define PORT_DEFAULT_PWD 464
+
+#define MAX_LEN 1024
+#define MAX_SERVICE_PASSWD_LEN 256
+#define RANDOM_PASSWD_LEN 128
+
+#define DEF_SERVICE_PASSWD_FILE "/usr/local/var/service_passwd"
+
+struct data{
+ int len;
+ unsigned char *value;
+};
+
+extern int enc_password(struct data pwd, struct data *enc_key, struct data *enc_pass);
+extern int tohex(krb5_data, krb5_data *);
+
+extern void kdb5_ldap_create_service (int argc, char **argv);
+extern void kdb5_ldap_modify_service (int argc, char **argv);
+extern void kdb5_ldap_destroy_service(int argc, char **argv);
+extern void kdb5_ldap_list_services(int argc, char **argv);
+extern void kdb5_ldap_view_service(int argc, char **argv);
+extern int kdb5_ldap_set_service_password(int argc, char **argv);
+extern void kdb5_ldap_set_service_certificate(int argc, char **argv);
+extern void print_service_params(krb5_ldap_service_params *lserparams, int mask);
+extern krb5_error_code convert_realm_name2dn_list(char **list, const char *krbcontainer_loc);
+extern int kdb5_ldap_stash_service_password(int argc, char **argv);
+
diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.M b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.M
new file mode 100644
index 000000000..20dc3e726
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.M
@@ -0,0 +1,977 @@
+.TH KDB5_LDAP_UTIL 8
+.SH NAME
+kdb5_ldap_util \- Kerberos Configuration Utility
+.SH SYNOPSIS
+.B kdb5_ldap_util
+[\fB\-D\fP\ \fIuser_dn\fP [\fB\-w\fP\ \fIpasswd\fP]]
+[\fB\-h\fP\ \fIldap_server\fP] [\fB\-p\fP\ \fIldap_port\fP]
+.I command
+.I [command_options]
+.SH DESCRIPTION
+.B kdb5_ldap_util
+allows an administrator to manage realms, Kerberos services and ticket policies.
+.SH COMMAND-LINE OPTIONS
+.TP
+\fB\-D\fP\ \fIuser_dn\fP
+Specifies the Distinguished name (DN) of the user who has sufficient rights to
+perform the operation on the LDAP server.
+.TP
+\fB\-w\fP\ \fIpasswd\fP
+Specifies the password of
+.IR user_dn .
+This option is not recommended.
+.TP
+\fB\-h\fP\ \fIldap_server\fP
+Specifies the hostname or IP address of the server hosting the LDAP service for
+a Kerberos realm.
+.TP
+\fB\-p\fP\ \fIldap_port\fP
+Specifies the SSL port number of the LDAP server.
+.SH COMMANDS
+.TP
+\fBcreate\fP [\fB\-subtree\fP\ \fIsubtree_dn\fP] [\fB\-sscope\fP\ \fIsearch_scope\fP] [\fB\-enctypes\fP\ \fIsupported_enc_types\fP] [\fB\-defenctype\fP\ \fIdefault_enc_type\fP] [\fB\-salttypes\fP\ \fIsupported_salt_types\fP] [\fB\-defsalttype\fP\ \fIdefault_salt_type\fP] [\fB\-k\fP\ \fImkeytype\fP] [\fB\-m\fP|\fB\-P\fP\ \fIpassword\fP|\fB\-sf\fP\ \fIstashfilename\fP] [\fB\-r\fP\ \fIrealm\fP] [\fB\-kdcdn\fP\ \fIkdc_service_list\fP] [\fB\-admindn\fP\ \fIadmin_service_list\fP] [\fB\-pwddn\fP\ \fIpasswd_service_list\fP] [\fB\-maxtktlife\fP\ \fImax_ticket_life\fP] [\fB\-maxrenewlife\fP\ \fImax_renewable_ticket_life\fP] [\fIticket_flags\fP]
+Creates realm in directory. Options:
+.RS
+.TP
+\fB\-subtree\fP\ \fIsubtree_dn\fP
+Specifies the subtree where principals and other Kerberos objects in the realm are placed.
+.TP
+\fB\-sscope\fP\ \fIsearch_scope\fP
+Specifies the scope for searching the principals under the
+.IR subtree .
+The possible values are 1 or one (one level), 2 or sub (subtree).
+.TP
+\fB\-enctypes\fP\ \fIsupported_enc_types\fP
+Specifies the encryption types supported by the realm. This is a colon-separated list.
+.TP
+\fB\-defenctype\fP\ \fIdefault_enc_type\fP
+Specifies the default encryption type for the realm. This is also a part of supported enctypes list.
+.TP
+\fB\-salttypes\fP\ \fIsupported_salt_types\fP
+Specifies the salt types supported by the realm. This is a colon-separated list.
+.TP
+\fB\-defsalttype\fP\ \fIdefault_salt_type\fP
+Specifies the default salt types for the realm.
+.TP
+\fB\-k\fP\ \fImkeytype\fP
+Specifies the key type of the master key in the database; the default is
+that given in
+.IR kdc.conf .
+.TP
+\fB\-m\fP
+Specifies that the master database password should be read from the TTY
+rather than fetched from a file on the disk.
+.TP
+\fB\-P\fP\ \fIpassword\fP
+Specifies the master database password. This option is not recommended.
+.TP
+\fB\-sf\fP\ \fIstashfilename\fP
+Specifies the stash file of the master database password.
+.TP
+\fB\-maxtktlife\fP\ \fImax_ticket_life\fP
+Specifies maximum ticket life for principals in this realm.
+.TP
+\fB\-maxrenewlife\fP\ \fImax_renewable_ticket_life\fP
+Specifies maximum renewable life of tickets for principals in this realm.
+.TP
+\fIticket_flags\fP
+Specifies the ticket flags. If this option is not specified, by default, none of the flags are
+set. This means all the ticket options will be allowed and no restriction will be set.
+
+The various flags are:
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_postdated\fP
+.B -allow_postdated
+prohibits principals from obtaining postdated tickets. (Sets the
+.SM KRB5_KDB_DISALLOW_POSTDATED
+flag.)
+.B +allow_postdated
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_forwardable\fP
+.B -allow_forwardable
+prohibits principals from obtaining forwardable tickets. (Sets the
+.SM KRB5_KDB_DISALLOW_FORWARDABLE
+flag.)
+.B +allow_forwardable
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_renewable\fP
+.B -allow_renewable
+prohibits principals from obtaining renewable tickets. (Sets the
+.SM KRB5_KDB_DISALLOW_RENEWABLE
+flag.)
+.B +allow_renewable
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_proxiable\fP
+.B -allow_proxiable
+prohibits principals from obtaining proxiable tickets. (Sets the
+.SM KRB5_KDB_DISALLOW_PROXIABLE
+flag.)
+.B +allow_proxiable
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_dup_skey\fP
+.B -allow_dup_skey
+Disables user-to-user authentication for principals by prohibiting
+principals from obtaining a session key for another user. (Sets the
+.SM KRB5_KDB_DISALLOW_DUP_SKEY
+flag.)
+.B +allow_dup_skey
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBrequires_preauth\fP
+.B +requires_preauth
+requires principals to preauthenticate before being allowed to
+kinit. (Sets the
+.SM KRB5_KDB_REQUIRES_PRE_AUTH
+flag.)
+.B -requires_preauth
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBrequires_hwauth\fP
+.B +requires_hwauth
+requires principals to preauthenticate using a hardware device
+before being allowed to kinit. (Sets the
+.SM KRB5_KDB_REQUIRES_HW_AUTH
+flag.)
+.B -requires_hwauth
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_svr\fP
+.B -allow_svr
+prohibits the issuance of service tickets for principals. (Sets the
+.SM KRB5_KDB_DISALLOW_SVR
+flag.)
+.B +allow_svr
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_tgs_req\fP
+.B \-allow_tgs_req
+specifies that a Ticket-Granting Service (TGS) request for a service
+ticket for principals is not permitted. This option is useless for
+most things.
+.B +allow_tgs_req
+clears this flag. The default is
+.BR +allow_tgs_req .
+In effect,
+.B \-allow_tgs_req
+sets the
+.SM KRB5_KDB_DISALLOW_TGT_BASED
+flag on principals in the database.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_tix\fP
+.B \-allow_tix
+forbids the issuance of any tickets for principals.
+.B +allow_tix
+clears this flag. The default is
+.BR +allow_tix .
+In effect,
+.B \-allow_tix
+sets the
+.SM KRB5_KDB_DISALLOW_ALL_TIX
+flag on principals in the database.
+.TP
+{\fB\-\fP|\fB+\fP}\fBneedchange\fP
+.B +needchange
+sets a flag in attributes field to force a password change;
+.B \-needchange
+clears it. The default is
+.BR \-needchange .
+In effect,
+.B +needchange
+sets the
+.SM KRB5_KDB_REQUIRES_PWCHANGE
+flag on principals in the database.
+.TP
+{\fB\-\fP|\fB+\fP}\fBpassword_changing_service\fP
+.B +password_changing_service
+sets a flag in the attributes field marking principal as a password change
+service principal (useless for most things).
+.B \-password_changing_service
+clears the flag. This flag intentionally has a long name. The default
+is
+.BR \-password_changing_service .
+In effect,
+.B +password_changing_service
+sets the
+.SM KRB5_KDB_PWCHANGE_SERVICE
+flag on principals in the database.
+.TP
+\fB\-r\fP\ \fIrealm\fP
+Specifies the Kerberos realm of the database; by default the realm
+returned by
+.IR krb5_default_local_realm (3)
+is used.
+.TP
+.B Command Options Specific to eDirectory
+.TP
+\fB\-kdcdn\fP\ \fIkdc_service_list\fP
+Specifies the list of KDC service objects serving the realm. The list contains the DNs of the KDC
+service objects separated by colon(:).
+.TP
+\fB\-admindn\fP\ \fIadmin_service_list\fP
+Specifies the list of Administration service objects serving the realm. The list contains the DNs
+of the Administration service objects separated by colon(:).
+.TP
+\fB\-pwddn\fP\ \fIpasswd_service_list\fP
+Specifies the list of Password service objects serving the realm. The list contains the DNs of the
+Password service objects separated by colon(:).
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org -h ldap-server1.mit.edu
+create -sscope SUB -enctypes des-cbc-crc:des3-cbc-sha1
+-defenctype des3-cbc-sha1 -salttypes normal:afs3 -defsalttype normal
+-r ATHENA.MIT.EDU\fP
+.nf
+Password for "cn=admin,o=org":
+Initializing database for realm 'ATHENA.MIT.EDU'
+You will be prompted for the database Master Password.
+It is important that you NOT FORGET this password.
+Enter KDC database master key:
+Re-enter KDC database master key to verify:
+.fi
+.RE
+
+.TP
+\fBmodify\fP [\fB\-subtree\fP\ \fIsubtree_dn\fP] [\fB\-sscope\fP\ \fIsearch_scope\fP] [\fB\-enctypes\fP\ \fIsupported_enc_types\fP | [\fB\-clearenctypes\fP\ \fIenc_type_list\fP] [\fB\-addenctypes\fP\ \fIenc_type_list\fP]] [\fB\-defenctype\fP\ \fIdefault_enc_type\fP] [\fB\-salttypes\fP\ \fIsupported_salt_types\fP | [\fB\-clearsalttypes\fP\ \fIsalt_type_list\fP] [\fB\-addsalttypes\fP\ \fIsalt_type_list\fP]] [\fB\-defsalttype\fP\ \fIdefault_salt_type\fP] [\fB\-r\fP\ \fIrealm\fP] [\fB\-kdcdn\fP\ \fIkdc_service_list\fP | [\fB\-clearkdcdn\fP\ \fIkdc_service_list\fP] [\fB\-addkdcdn\fP\ \fIkdc_service_list\fP]] [\fB\-admindn\fP\ \fIadmin_service_list\fP | [\fB\-clearadmindn\fP\ \fIadmin_service_list\fP] [\fB\-addadmindn\fP\ \fIadmin_service_list\fP]] [\fB\-pwddn\fP\ \fIpasswd_service_list\fP | [\fB\-clearpwddn\fP\ \fIpasswd_service_list\fP] [\fB\-addpwddn\fP\ \fIpasswd_service_list\fP]] [\fB\-maxtktlife\fP\ \fImax_ticket_life\fP] [\fB\-maxrenewlife\fP\ \fImax_renewable_ticket_life\fP] [\fIticket_flags\fP]
+
+Modifies the attributes of a realm. Options:
+.RS
+.TP
+\fB\-subtree\fP\ \fIsubtree_dn\fP
+Specifies the subtree containing principals and other Kerberos objects in the realm.
+.TP
+\fB\-sscope\fP\ \fIsearch_scope\fP
+Specifies the scope for searching the principals under the
+.IR subtree .
+The possible values are 1 or one (one level), 2 or sub (subtree).
+.TP
+\fB\-enctypes\fP\ \fIsupported_enc_types\fP
+Specifies the encryption types supported by the realm. This is a colon-separated list.
+.TP
+\fB\-clearenctypes\fP\ \fIenc_type_list\fP
+Specifies the encryption types that need to be removed from the supported encryption types
+of the realm. This is a colon-separated list.
+.TP
+\fB\-addenctypes\fP\ \fIenc_type_list\fP
+Specifies the encryption types that need to be added to the supported encryption types of the
+realm. This is a colon-separated list.
+.TP
+\fB\-defenctype\fP\ \fIdefault_enc_type\fP
+Specifies the default encryption type for the realm.
+.TP
+\fB\-salttypes\fP\ \fIsupported_salt_types\fP
+Specifies the salt types supported by the realm. This is a colon-separated list.
+.TP
+\fB\-clearsalttypes\fP\ \fIsalt_type_list\fP
+Specifies the salt types that need to be removed from the supported salt types of the realm.
+This is a colon-separated list.
+.TP
+\fB\-addsalttypes\fP\ \fIsalt_type_list\fP
+Specifies the salt types that need to be added to the supported salt types of the realm. This
+is a colon-separated list.
+.TP
+\fB\-defsalttype\fP\ \fIdefault_salt_type\fP
+Specifies the default salt type for the realm.
+.TP
+\fB\-maxtktlife\fP\ \fImax_ticket_life\fP
+Specifies maximum ticket life for principals in this realm.
+.TP
+\fB\-maxrenewlife\fP\ \fImax_renewable_ticket_life\fP
+Specifies maximum renewable life of tickets for principals in this realm.
+.TP
+\fIticket_flags\fP
+Specifies the ticket flags. If this option is not specified, by default, none of the flags are
+set. This means all the ticket options will be allowed and no restriction will be set.
+
+The various flags are:
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_postdated\fP
+.B -allow_postdated
+prohibits principals from obtaining postdated tickets. (Sets the
+.SM KRB5_KDB_DISALLOW_POSTDATED
+flag.)
+.B +allow_postdated
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_forwardable\fP
+.B -allow_forwardable
+prohibits principals from obtaining forwardable tickets. (Sets the
+.SM KRB5_KDB_DISALLOW_FORWARDABLE
+flag.)
+.B +allow_forwardable
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_renewable\fP
+.B -allow_renewable
+prohibits principals from obtaining renewable tickets. (Sets the
+.SM KRB5_KDB_DISALLOW_RENEWABLE
+flag.)
+.B +allow_renewable
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_proxiable\fP
+.B -allow_proxiable
+prohibits principals from obtaining proxiable tickets. (Sets the
+.SM KRB5_KDB_DISALLOW_PROXIABLE
+flag.)
+.B +allow_proxiable
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_dup_skey\fP
+.B -allow_dup_skey
+Disables user-to-user authentication for principals by prohibiting
+principals from obtaining a session key for another user. (Sets the
+.SM KRB5_KDB_DISALLOW_DUP_SKEY
+flag.)
+.B +allow_dup_skey
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBrequires_preauth\fP
+.B +requires_preauth
+requires principals to preauthenticate before being allowed to
+kinit. (Sets the
+.SM KRB5_KDB_REQUIRES_PRE_AUTH
+flag.)
+.B -requires_preauth
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBrequires_hwauth\fP
+.B +requires_hwauth
+requires principals to preauthenticate using a hardware device
+before being allowed to kinit. (Sets the
+.SM KRB5_KDB_REQUIRES_HW_AUTH
+flag.)
+.B -requires_hwauth
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_svr\fP
+.B -allow_svr
+prohibits the issuance of service tickets for principals. (Sets the
+.SM KRB5_KDB_DISALLOW_SVR
+flag.)
+.B +allow_svr
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_tgs_req\fP
+.B \-allow_tgs_req
+specifies that a Ticket-Granting Service (TGS) request for a service
+ticket for principals is not permitted. This option is useless for
+most things.
+.B +allow_tgs_req
+clears this flag. The default is
+.BR +allow_tgs_req .
+In effect,
+.B \-allow_tgs_req
+sets the
+.SM KRB5_KDB_DISALLOW_TGT_BASED
+flag on principals in the database.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_tix\fP
+.B \-allow_tix
+forbids the issuance of any tickets for principals.
+.B +allow_tix
+clears this flag. The default is
+.BR +allow_tix .
+In effect,
+.B \-allow_tix
+sets the
+.SM KRB5_KDB_DISALLOW_ALL_TIX
+flag on principals in the database.
+.TP
+{\fB\-\fP|\fB+\fP}\fBneedchange\fP
+.B +needchange
+sets a flag in attributes field to force a password change;
+.B \-needchange
+clears it. The default is
+.BR \-needchange .
+In effect,
+.B +needchange
+sets the
+.SM KRB5_KDB_REQUIRES_PWCHANGE
+flag on principals in the database.
+.TP
+{\fB\-\fP|\fB+\fP}\fBpassword_changing_service\fP
+.B +password_changing_service
+sets a flag in the attributes field marking principal as a password change
+service principal (useless for most things).
+.B \-password_changing_service
+clears the flag. This flag intentionally has a long name. The default
+is
+.BR \-password_changing_service .
+In effect,
+.B +password_changing_service
+sets the
+.SM KRB5_KDB_PWCHANGE_SERVICE
+flag on principals in the database.
+.TP
+\fB\-r\fP\ \fIrealm\fP
+Specifies the Kerberos realm of the database; by default the realm
+returned by
+.IR krb5_default_local_realm (3)
+is used.
+.TP
+.B Command Options Specific to eDirectory
+.TP
+\fB\-kdcdn\fP\ \fIkdc_service_list\fP
+Specifies the list of KDC service objects serving the realm. The list contains the DNs of the KDC
+service objects separated by a colon (:).
+.TP
+\fB\-clearkdcdn\fP\ \fIkdc_service_list\fP
+Specifies the list of KDC service objects that need to be removed from the existing list. The list contains
+the DNs of the KDC service objects separated by a colon (:).
+.TP
+\fB\-addkdcdn\fP\ \fIkdc_service_list\fP
+Specifies the list of KDC service objects that need to be added to the existing list. The list contains the
+DNs of the KDC service objects separated by a colon (:).
+.TP
+\fB\-admindn\fP\ \fIadmin_service_list\fP
+Specifies the list of Administration service objects serving the realm. The list contains the DNs
+of the Administration service objects separated by a colon (:).
+.TP
+\fB\-clearadmindn\fP\ \fIadmin_service_list\fP
+Specifies the list of Administration service objects that need to be removed from the existing list. The list
+contains the DNs of the Administration service objects separated by a colon (:).
+.TP
+\fB\-addadmindn\fP\ \fIadmin_service_list\fP
+Specifies the list of Administration service objects that need to be added to the existing list. The list
+contains the DNs of the Administration service objects separated by a colon (:).
+.TP
+\fB\-pwddn\fP\ \fIpasswd_service_list\fP
+Specifies the list of Password service objects serving the realm. The list contains the DNs of the
+Password service objects separated by a colon (:).
+.TP
+\fB\-clearpwddn\fP\ \fIpasswd_service_list\fP
+Specifies the list of Password service objects that need to be removed from the existing list. The list
+contains the DNs of the Password service objects separated by a colon (:).
+.TP
+\fB\-addpwddn\fP\ \fIpasswd_service_list\fP
+Specifies the list of Password service objects that need to be added to the existing list. The list contains
+the DNs of the Password service objects separated by a colon (:).
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org modify -sscope ONE -enctypes
+des3-hmac-sha1:des-cbc-md5 -defenctype des3-hmac-sha1 -addsalttypes v4:special
+-r ATHENA.MIT.EDU \fP
+.nf
+Password for "cn=admin,o=org":
+.fi
+.RE
+.TP
+\fBview\fP [\fB\-r\fP\ \fIrealm\fP]
+Displays the attributes of a realm. Options:
+.RS
+.TP
+\fB\-r\fP\ \fIrealm\fP
+Specifies the Kerberos realm of the database; by default the realm returned by
+.IR krb5_default_local_realm (3)
+is used.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org view -r ATHENA.MIT.EDU\fP
+.nf
+Password for "cn=admin,o=org":
+ Realm Name: ATHENA.MIT.EDU
+ Subtree: ou=users,o=org
+ SearchScope: ONE
+ Supported Enc Types: DES cbc mode with RSA-MD5
+ Triple DES cbc mode with HMAC/sha1
+ Default Enc Type: Triple DES cbc mode with HMAC/sha1
+ Supported Salt Types: Version 5
+ Version 4
+ Special
+ AFS version 3
+ Default Salt Type: Version 5
+ Maximum ticket life: 0 days 01:00:00
+ Maximum renewable life: 0 days 10:00:00
+ Ticket flags: DISALLOW_FORWARDABLE REQUIRES_PWCHANGE
+.fi
+.RE
+.TP
+\fBdestroy\fP [\fB-f\fP] [\fB\-r\fP\ \fIrealm\fP]
+Destroys an existing realm. Options:
+.RS
+.TP
+\fB\-f\fP
+If specified, will not prompt the user for confirmation.
+.TP
+\fB\-r\fP\ \fIrealm\fP
+Specifies the Kerberos realm of the database; by default the realm returned by
+.IR krb5_default_local_realm (3)
+is used.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org -h ldap-server1.mit.edu destroy -r ATHENA.MIT.EDU\fP
+.nf
+Password for "cn=admin,o=org":
+Deleting KDC database of 'ATHENA.MIT.EDU', are you sure?
+(type 'yes' to confirm)? yes
+OK, deleting database of 'ATHENA.MIT.EDU'...
+.fi
+.RE
+.TP
+\fBlist\fP
+
+Lists the name of realms.
+.RS
+.nf
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org list\fP
+Password for "cn=admin,o=org":
+ATHENA.MIT.EDU
+MYREALM
+MEDIA-LAB.MIT.EDU
+.fi
+.RE
+.TP
+\fBstashsrvpw\fP [\fB\-f\fP\ \fIfilename\fP] \fIservicedn\fP
+Allows an administrator to store the password for service object in a file so that KDC, Administration, and
+Password server can use it to authenticate to the LDAP server. Options:
+.RS
+.TP
+\fB\-f\fP\ \fIfilename\fP
+Specifies the complete path of the service password file. By default, /usr/local/var/service_passwd is used.
+.TP
+\fIservicedn\fP
+Specifies Distinguished name (DN) of the service object whose password is to be stored in file.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util stashsrvpw -f /home/andrew/conf_keyfile cn=service-kdc,o=org\fP
+.nf
+Password for "cn=service-kdc,o=org":
+Re-enter password for "cn=service-kdc,o=org":
+.fi
+.RE
+.TP
+\fBcreate_policy\fP [\fB\-maxtktlife\fP\ \fImax_ticket_life\fP] [\fB\-maxrenewlife\fP\ \fImax_renewable_ticket_life\fP] [\fIticket_flags\fP] \fIpolicy_dn\fP
+Creates a ticket policy in directory. Options:
+.RS
+.TP
+\fB\-maxtktlife\fP\ \fImax_ticket_life\fP
+Specifies maximum ticket life for principals.
+.TP
+\fB\-maxrenewlife\fP\ \fImax_renewable_ticket_life\fP
+Specifies maximum renewable life of tickets for principals.
+.TP
+\fIticket_flags\fP
+Specifies the ticket flags. If this option is not specified, by default, none of the flags are
+set. This means all the ticket options will be allowed and no restriction will be set.
+
+The various flags are:
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_postdated\fP
+.B -allow_postdated
+prohibits principals from obtaining postdated tickets. (Sets the
+.SM KRB5_KDB_DISALLOW_POSTDATED
+flag.)
+.B +allow_postdated
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_forwardable\fP
+.B -allow_forwardable
+prohibits principals from obtaining forwardable tickets. (Sets the
+.SM KRB5_KDB_DISALLOW_FORWARDABLE
+flag.)
+.B +allow_forwardable
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_renewable\fP
+.B -allow_renewable
+prohibits principals from obtaining renewable tickets. (Sets the
+.SM KRB5_KDB_DISALLOW_RENEWABLE
+flag.)
+.B +allow_renewable
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_proxiable\fP
+.B -allow_proxiable
+prohibits principals from obtaining proxiable tickets. (Sets the
+.SM KRB5_KDB_DISALLOW_PROXIABLE
+flag.)
+.B +allow_proxiable
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_dup_skey\fP
+.B -allow_dup_skey
+Disables user-to-user authentication for principals by prohibiting
+principals from obtaining a session key for another user. (Sets the
+.SM KRB5_KDB_DISALLOW_DUP_SKEY
+flag.)
+.B +allow_dup_skey
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBrequires_preauth\fP
+.B +requires_preauth
+requires principals to preauthenticate before being allowed to
+kinit. (Sets the
+.SM KRB5_KDB_REQUIRES_PRE_AUTH
+flag.)
+.B -requires_preauth
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBrequires_hwauth\fP
+.B +requires_hwauth
+requires principals to preauthenticate using a hardware device
+before being allowed to kinit. (Sets the
+.SM KRB5_KDB_REQUIRES_HW_AUTH
+flag.)
+.B -requires_hwauth
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_svr\fP
+.B -allow_svr
+prohibits the issuance of service tickets for principals. (Sets the
+.SM KRB5_KDB_DISALLOW_SVR
+flag.)
+.B +allow_svr
+clears this flag.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_tgs_req\fP
+.B \-allow_tgs_req
+specifies that a Ticket-Granting Service (TGS) request for a service
+ticket for principals is not permitted. This option is useless for
+most things.
+.B +allow_tgs_req
+clears this flag. The default is
+.BR +allow_tgs_req .
+In effect,
+.B \-allow_tgs_req
+sets the
+.SM KRB5_KDB_DISALLOW_TGT_BASED
+flag on principals in the database.
+.TP
+{\fB\-\fP|\fB+\fP}\fBallow_tix\fP
+.B \-allow_tix
+forbids the issuance of any tickets for principals.
+.B +allow_tix
+clears this flag. The default is
+.BR +allow_tix .
+In effect,
+.B \-allow_tix
+sets the
+.SM KRB5_KDB_DISALLOW_ALL_TIX
+flag on principals in the database.
+.TP
+{\fB\-\fP|\fB+\fP}\fBneedchange\fP
+.B +needchange
+sets a flag in attributes field to force a password change;
+.B \-needchange
+clears it. The default is
+.BR \-needchange .
+In effect,
+.B +needchange
+sets the
+.SM KRB5_KDB_REQUIRES_PWCHANGE
+flag on principals in the database.
+.TP
+{\fB\-\fP|\fB+\fP}\fBpassword_changing_service\fP
+.B +password_changing_service
+sets a flag in the attributes field marking principal as a password change
+service principal (useless for most things).
+.B \-password_changing_service
+clears the flag. This flag intentionally has a long name. The default
+is
+.BR \-password_changing_service .
+In effect,
+.B +password_changing_service
+sets the
+.SM KRB5_KDB_PWCHANGE_SERVICE
+flag on principals in the database.
+.TP
+\fIpolicy_dn\fP
+Specifies Distinguished name (DN) of the policy.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org -h ldap-server1.mit.edu -p 636 create_policy -maxtktlife "1 day" -maxrenewlife "1 week" -allow_postdated +needchange -allow_forwardable cn=tktpolicy,o=org\fP
+.nf
+Password for "cn=admin,o=org":
+.fi
+.RE
+.TP
+\fBmodify_policy\fP [\fB\-maxtktlife\fP\ \fImax_ticket_life\fP] [\fB\-maxrenewlife\fP\ \fImax_renewable_ticket_life\fP] [\fIticket_flags\fP] \fIpolicy_dn\fP
+Modifies the attributes of a ticket policy. Options are same as
+.B create_policy.
+.RS
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org -h ldap-server1.mit.edu -p 636 modify_policy -maxtktlife "60 minutes" -maxrenewlife "10 hours" +allow_postdated -requires_preauth cn=tktpolicy,o=org\fP
+.nf
+Password for "cn=admin,o=org":
+.fi
+.RE
+.TP
+\fBview_policy\fP \fIpolicy_dn\fP
+Displays the attributes of a ticket policy. Options:
+.RS
+.TP
+\fIpolicy_dn\fP
+Specifies Distinguished name (DN) of the policy.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org -h ldap-server1.mit.edu -p 636 view_policy cn=tktpolicy,o=org\fP
+.nf
+Password for "cn=admin,o=org":
+ Ticket policy: cn=tktpolicy,o=org
+ Maximum ticket life: 0 days 01:00:00
+ Maximum renewable life: 0 days 10:00:00
+ Ticket flags: DISALLOW_FORWARDABLE REQUIRES_PWCHANGE
+.fi
+.RE
+.TP
+\fBdestroy_policy\fP [\fB\-force\fP] \fIpolicy_dn\fP
+Destroys an existing ticket policy. Options:
+.RS
+.TP
+\fB\-force\fP
+Forces the deletion of the policy object. If not specified, will be prompted for confirmation while deleting the policy. Enter
+.B yes
+to confirm the deletion.
+.TP
+\fIpolicy_dn\fP
+Specifies Distinguished name (DN) of the policy.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org -h ldap-server1.mit.edu -p 636 destroy_policy cn=tktpolicy,o=org\fP
+.nf
+Password for "cn=admin,o=org":
+This will delete the policy object 'cn=tktpolicy,o=org', are you sure?
+(type 'yes' to confirm)? yes
+** policy object 'cn=tktpolicy,o=org' deleted.
+.fi
+.RE
+.TP
+\fBlist_policy\fP [\fB\-basedn\fP\ \fIbase_dn\fP]
+Lists the name of ticket policies under a given base in directory. Options:
+.RS
+.TP
+\fI\-basedn\fP\ \fIbase_dn\fP
+Specifies the base DN for searching the policies, limiting the search to a particular subtree. If this option
+is not provided, LDAP Server specific search base will be used.
+For eg, in the case of OpenLDAP, value of
+.B defaultsearchbase
+from
+.I slapd.conf
+file will be used, where as in the case of eDirectory, the default value
+for the base DN is
+.B Root.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org -h ldap-server1.mit.edu -p 636 list_policy
+-basedn o=org\fP
+.nf
+Password for "cn=admin,o=org":
+cn=tktpolicy,o=org
+cn=tktpolicy2,o=org
+cn=tktpolicy3,o=org
+.fi
+.RE
+
+.TP
+.B Commands Specific to eDirectory
+.TP
+\fBsetsrvpw\fP [\fB\-randpw\fP|\fB\-fileonly\fP] [\fB\-f\fP\ \fIfilename\fP] \fIservice_dn\fP
+Allows an administrator to set password for service objects such as KDC, Administration, and Password server in
+eDirectory and store them in a file. The
+.I -fileonly
+option stores the password in a file and not in the eDirectory object. Options:
+.RS
+.TP
+\fB\-randpw \fP
+Generates and sets a random password. This options can be specified to store the password both in eDirectory and a file. The
+.I -fileonly
+option can not be used if
+.I -randpw
+option is already specified.
+.TP
+\fB\-fileonly\fP
+Stores the password only in a file and not in eDirectory. The
+.I -randpw
+option can not be used when
+.I -fileonly
+options is specified.
+.TP
+\fB\-f\fP\ \fIfilename\fP
+Specifies complete path of the service password file. By default, /usr/local/var/service_passwd is used.
+.TP
+\fIservice_dn\fP
+Specifies Distinguished name (DN) of the service object whose password is to be set.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util setsrvpw -D cn=admin,o=org setsrvpw -fileonly -f /home/andrew/conf_keyfile
+cn=service-kdc,o=org\fP
+.nf
+Password for "cn=admin,o=org":
+Password for "cn=service-kdc,o=org":
+Re-enter password for "cn=service-kdc,o=org":
+.fi
+.RE
+.TP
+\fBcreate_service\fP {\fB\-kdc|\-admin|\-pwd\fP} [\fB\-servicehost\fP\ \fIservice_host_list\fP] [\fB\-realm\fP\ \fIrealm_list\fP] [\fB\-randpw|\-fileonly\fP] [\fB\-f\fP\ \fIfilename\fP] \fIservice_dn\fP
+Creates a service in directory and assigns appropriate rights. Options:
+.RS
+.TP
+\fB\-kdc\fP
+Specifies the service is a KDC service
+.TP
+\fB\-admin\fP
+Specifies the service is a Administration service
+.TP
+\fB\-pwd\fP
+Specifies the service is a Password service
+.TP
+\fB\-servicehost\fP\ \fIservice_host_list\fP
+Specifies the list of entries separated by a colon (:). Each entry consists of the hostname or IP
+address of the server hosting the service, transport protocol, and the port number of
+the service separated by a pound sign (#).
+For example,
+server1#tcp#88:server2#udp#89.
+.TP
+\fB\-realm\fP\ \fIrealm_list\fP
+Specifies the list of realms that can be serviced by Kerberos. The list contains the name of the realms
+separated by a colon (:).
+.TP
+\fB\-randpw \fP
+Generates and sets a random password. This options can be specified to store the password both in eDirectory and a file. The
+.I -fileonly
+option can not be used if
+.I -randpw
+option is already specified.
+.TP
+\fB\-fileonly\fP
+Stores the password only in a file and not in eDirectory. The
+.I -randpw
+option can not be used when
+.I -fileonly
+options is specified.
+.TP
+\fB\-f\fP\ \fIfilename\fP
+Specifies the complete path of the file where the service object password is stashed.
+.TP
+\fIservice_dn\fP
+Specifies Distinguished name (DN) of the Kerberos service to be created.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org create_service -kdc -randpw -f /home/andrew/conf_keyfile cn=service-kdc,o=org\fP
+.nf
+Password for "cn=admin,o=org":
+File does not exist. Creating the file /home/andrew/conf_keyfile...
+.fi
+.RE
+.TP
+\fBmodify_service\fP [\fB\-servicehost\fP\ \fIservice_host_list\fP | [\fB\-clearservicehost\fP\ \fIservice_host_list\fP] [\fB\-addservicehost\fP\ \fIservice_host_list\fP]] [\fB\-realm\fP\ \fIrealm_list\fP | [\fB\-clearrealm\fP\ \fIrealm_list\fP] [\fB\-addrealm\fP\ \fIrealm_list\fP]] \fIservice_dn\fP
+Modifies the attributes of a service and assigns appropriate rights. Options:
+.RS
+.TP
+\fB\-servicehost\fP\ \fIservice_host_list\fP
+Specifies the list of entries separated by a colon (:). Each entry consists of a host name
+or IP Address of the Server hosting the service, transport protocol, and port
+number of the service separated by a pound sign (#).
+For example,
+server1#tcp#88:server2#udp#89
+.TP
+\fB\-clearservicehost\fP\ \fIservice_host_list\fP
+Specifies the list of servicehost entries to be removed from the existing list separated by colon (:). Each entry consists of a host name or IP Address of the server
+hosting the service, transport protocol, and port number of the service separated
+by a pound sign (#).
+.TP
+\fB\-addservicehost\fP\ \fIservice_host_list\fP
+Specifies the list of servicehost entries to be added to the existing list separated by colon (:). Each entry consists of a host name or IP Address of the
+server hosting the service, transport protocol, and port number of the service
+separated by a pound sign (#).
+.TP
+\fB\-realm\fP\ \fIrealm_list\fP
+Specifies the list of realms that are associated with this service. The list contains the name of
+the realms separated by a colon (:).
+.TP
+\fB\-clearrealm\fP\ \fIrealm_list\fP
+Specifies the list of realms to be removed from the existing list. The list contains the name of
+the realms separated by a colon (:).
+.TP
+\fB\-addrealm\fP\ \fIrealm_list\fP
+Specifies the list of realms to be added to the existing list. The list contains the name of the
+realms separated by a colon (:).
+.TP
+\fIservice_dn\fP
+Specifies Distinguished name (DN) of the Kerberos service to be modified.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org modify_service -realm ATHENA.MIT.EDU
+cn=service-kdc,o=org\fP
+.nf
+Password for "cn=admin,o=org":
+Changing rights for the service object. Please wait ... done
+.fi
+.RE
+.TP
+\fBview_service\fP \fIservice_dn\fP
+Displays the attributes of a service. Options:
+.RS
+.TP
+\fIservice_dn\fP
+Specifies Distinguished name (DN) of the Kerberos service to be viewed.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org view_service cn=service-kdc,o=org\fP
+.nf
+Password for "cn=admin,o=org":
+ Service dn: cn=service-kdc,o=org
+ Service type: kdc
+ Service host list:
+ Realm DN list: cn=ATHENA.MIT.EDU,cn=Kerberos,cn=Security
+.fi
+.RE
+.TP
+\fBdestroy_service\fP [\fB\-force\fP] [\fB\-f\fP\ \fIstashfilename\fP] \fIservice_dn\fP
+Destroys an existing service. Options:
+.RS
+.TP
+\fB\-force\fP
+If specified, will not prompt for user's confirmation, instead will force destruction of the service.
+.TP
+\fB\-f\fP\ \fIstashfilename\fP
+Specifies the complete path of the service password file from where the entry corresponding to the
+.I service_dn
+needs to be removed.
+.TP
+\fIservice_dn\fP
+Specifies Distinguished name (DN) of the Kerberos service to be destroyed.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org destroy_service cn=service-kdc,o=org\fP
+.nf
+Password for "cn=admin,o=org":
+This will delete the service object 'cn=service-kdc,o=org', are you sure?
+(type 'yes' to confirm)? yes
+** service object 'cn=service-kdc,o=org' deleted.
+.fi
+.RE
+.TP
+\fBlist_service\fP [\fB\-basedn\fP\ \fIbase_dn\fP]
+Lists the name of services under a given base in directory. Options:
+.RS
+.TP
+\fB\-basedn\fP\ \fIbase_dn\fP
+Specifies the base DN for searching the policies, limiting the search to a particular subtree. If this option
+is not provided, LDAP Server specific search base will be used.
+For eg, in the case of OpenLDAP, value of
+.B defaultsearchbase
+from
+.I slapd.conf
+file will be used, where as in the case of eDirectory, the default value
+for the base DN is
+.B Root.
+.TP
+EXAMPLE:
+\fBkdb5_ldap_util -D cn=admin,o=org list_service\fP
+.nf
+Password for "cn=admin,o=org":
+cn=service-kdc,o=org
+cn=service-adm,o=org
+cn=service-pwd,o=org
+.fi
+.RE
+.SH SEE ALSO
+kadmin(8)
diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c
new file mode 100644
index 000000000..889151531
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c
@@ -0,0 +1,655 @@
+/*
+ * kadmin/ldap_util/kdb5_ldap_util.c
+ *
+ * (C) Copyright 1990,1991, 1996 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.
+ *
+ *
+ * Edit a KDC database.
+ */
+
+/*
+ * 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.
+ */
+
+/* Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <time.h>
+
+#include <k5-int.h>
+#include <kadm5/admin.h>
+#include <adm_proto.h>
+#include "kdb5_ldap_util.h"
+
+typedef void (*cmd_func)(int, char **);
+int cmd_index(char *name);
+
+char *mkey_password = 0;
+int exit_status = 0;
+krb5_context util_context;
+kadm5_config_params global_params;
+krb5_boolean db_inited = FALSE;
+
+char *progname;
+krb5_boolean manual_mkey = FALSE;
+
+/*
+ * This function prints the usage of kdb5_ldap_util, which is
+ * the LDAP configuration utility.
+ */
+void usage()
+{
+ fprintf(stderr, "Usage: "
+"kdb5_util [-D user_dn [-w passwd]] [-h ldap_server] [-p ldap_port]\n"
+"\tcmd [cmd_options]\n"
+
+/* Create realm */
+"create [-subtree subtree_dn] [-sscope search_scope]\n"
+#ifdef HAVE_EDIRECTORY
+"\t\t[-kdcdn kdc_service_list] [-admindn admin_service_list]\n"
+"\t\t[-pwddn passwd_service_list]\n"
+#endif
+"\t\t[-enctypes supported_enc_types] [-defenctype default_enc_type]\n"
+"\t\t[-salttypes supported_salt_types] [-defsalttype default_salt_type]\n"
+"\t\t[-m|-P password|-sf stashfilename] [-k mkeytype]\n"
+"\t\t[-maxtktlife max_ticket_life] [-maxrenewlife max_renewable_ticket_life]\n"
+"\t\t[ticket_flags] [-r realm]\n"
+
+/* modify realm */
+"modify [-subtree subtree_dn] [-sscope search_scope]\n"
+#ifdef HAVE_EDIRECTORY
+"\t\t[-kdcdn kdc_service_list |\n"
+"\t\t[-clearkdcdn kdc_service_list] [-addkdcdn kdc_service_list]]\n"
+"\t\t[-admindn admin_service_list | [-clearadmindn admin_service_list]\n"
+"\t\t[-addadmindn admin_service_list]] [-pwddn passwd_service_list |\n"
+"\t\t[-clearpwddn passwd_service_list] [-addpwddn passwd_service_list]]\n"
+#endif
+"\t\t[-enctypes supported_enc_types | [-clearenctypes enc_type_list]\n"
+"\t\t[-addenctypes enc_type_list]] [-defenctype default_enc_type]\n"
+"\t\t[-salttypes supported_salt_types | [-clearsalttypes salt_type_list]\n"
+"\t\t[-addsalttypes salt_type_list]] [-defsalttype default_salt_type]\n"
+"\t\t[-maxtktlife max_ticket_life] [-maxrenewlife max_renewable_ticket_life]\n"
+"\t\t[ticket_flags] [-r realm]\n"
+/* View realm */
+"view [-r realm]\n"
+
+/* Destroy realm */
+"destroy [-f] [-r realm]\n"
+
+/* List realms */
+"list\n"
+
+#ifdef HAVE_EDIRECTORY
+/* Create Service */
+"create_service {-kdc|-admin|-pwd} [-servicehost service_host_list]\n"
+"\t\t[-realm realm_list] \n"
+"\t\t[-randpw|-fileonly] [-f filename] service_dn\n"
+
+/* Modify service */
+"modify_service [-servicehost service_host_list |\n"
+"\t\t[-clearservicehost service_host_list]\n"
+"\t\t[-addservicehost service_host_list]]\n"
+"\t\t[-realm realm_list | [-clearrealm realm_list]\n"
+"\t\t[-addrealm realm_list]] service_dn\n"
+
+/* View Service */
+"view_service service_dn\n"
+
+/* Destroy Service */
+"destroy_service [-force] [-f stashfilename] service_dn\n"
+
+/* List services */
+"list_service [-basedn base_dn]\n"
+
+/* Set Service password */
+"setsrvpw [-randpw|-fileonly] [-f filename] service_dn\n"
+
+#else
+
+/* Stash the service password */
+"stashsrvpw [-f filename] service_dn\n"
+
+#endif
+
+/* Create policy */
+"create_policy [-maxtktlife max_ticket_life]\n"
+"\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy_dn\n"
+
+/* Modify policy */
+"modify_policy [-maxtktlife max_ticket_life]\n"
+"\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy_dn\n"
+
+/* View policy */
+"view_policy policy_dn\n"
+
+/* Destroy policy */
+"destroy_policy [-force] policy_dn\n"
+
+/* List policies */
+"list_policy [-basedn base_dn]\n"
+
+);
+}
+
+void db_usage (int type) {
+ /*
+ * This should print usage of 'type' command. For now, we will print usage
+ * of all commands.
+ */
+ usage ();
+}
+
+/* The help messages for all sub-commands should be in the
+ * same order as listed in this table.
+ */
+static struct _cmd_table {
+ char *name;
+ cmd_func func;
+ int opendb;
+} cmd_table[] = {
+ {"create", kdb5_ldap_create, 1},
+ {"modify", kdb5_ldap_modify, 1},
+ {"view", kdb5_ldap_view, 1},
+ {"destroy", kdb5_ldap_destroy, 1},
+ {"list", kdb5_ldap_list, 1},
+#ifdef HAVE_EDIRECTORY
+ {"create_service", kdb5_ldap_create_service, 1},
+ {"modify_service", kdb5_ldap_modify_service, 1},
+ {"view_service", kdb5_ldap_view_service, 1},
+ {"destroy_service", kdb5_ldap_destroy_service, 1},
+ {"list_service",kdb5_ldap_list_services,1},
+ {"setsrvpw", kdb5_ldap_set_service_password, 0},
+#else
+ {"stashsrvpw", kdb5_ldap_stash_service_password, 0},
+#endif
+ {"create_policy", kdb5_ldap_create_policy, 1},
+ {"modify_policy", kdb5_ldap_modify_policy, 1},
+ {"view_policy", kdb5_ldap_view_policy, 1},
+ {"destroy_policy", kdb5_ldap_destroy_policy, 1},
+ {"list_policy", kdb5_ldap_list_policies, 1},
+ {NULL, NULL, 0},
+};
+
+
+/*
+ * The function cmd_lookup returns the structure matching the
+ * command name and returns NULL if nothing matches.
+ */
+static struct _cmd_table *cmd_lookup(name)
+ char *name;
+{
+ int i;
+
+ for (i = 0; cmd_table[i].name != NULL; i++)
+ if (strcmp(cmd_table[i].name, name) == 0)
+ return &cmd_table[i];
+
+ return NULL;
+}
+
+
+/*
+ * The function cmd_index provides the offset of the command
+ * in the command table, which can be used to get the corresponding
+ * help from the help message table.
+ */
+int cmd_index(name)
+ char *name;
+{
+ int i;
+
+ if (name == NULL)
+ return -1;
+
+ for (i = 0; cmd_table[i].name != NULL; i++)
+ if (strcmp(cmd_table[i].name, name) == 0)
+ return i;
+
+ return -1;
+}
+
+static void extended_com_err_fn (const char *myprog, errcode_t code,
+ const char *fmt, va_list args)
+{
+ const char *emsg;
+ emsg = krb5_get_error_message (util_context, code);
+ fprintf (stderr, "%s: %s ", myprog, emsg);
+ krb5_free_error_message (util_context, emsg);
+ vfprintf (stderr, fmt, args);
+ fprintf (stderr, "\n");
+}
+
+int main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ struct _cmd_table *cmd = NULL;
+ char *koptarg = NULL, **cmd_argv = NULL;
+ int cmd_argc = 0;
+ krb5_error_code retval;
+ int usage_print = 0;
+ int gp_is_static = 1;
+ krb5_error_code db_retval = 1;
+ char *bind_dn = NULL;
+ char *passwd = NULL;
+ char *ldap_server = NULL;
+ char *ldap_port = NULL;
+ unsigned int ldapmask = 0;
+ unsigned int passwd_len = 0;
+ char *prompt = NULL;
+ kdb5_dal_handle *dal_handle = NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ char *value = NULL, *conf_section = NULL;
+ krb5_boolean realm_name_required = FALSE;
+ krb5_boolean print_help_message = FALSE;
+
+ retval = krb5_init_context(&util_context);
+ set_com_err_hook(extended_com_err_fn);
+ if (retval) {
+ com_err (progname, retval, "while initializing Kerberos code");
+ exit_status++;
+ goto cleanup;
+ }
+
+ progname = (strrchr(argv[0], '/') ? strrchr(argv[0], '/')+1 : argv[0]);
+
+ cmd_argv = (char **) malloc(sizeof(char *)*argc);
+ if (cmd_argv == NULL) {
+ com_err(progname, ENOMEM, "while creating sub-command arguments");
+ exit_status++;
+ goto cleanup;
+ }
+ memset(cmd_argv, 0, sizeof(char *)*argc);
+ cmd_argc = 1;
+
+ memset(&global_params, 0, sizeof(kadm5_config_params));
+
+ argv++; argc--;
+ while (*argv) {
+ if (strcmp(*argv, "--help") == 0) {
+ print_help_message = TRUE;
+ }
+ if (strcmp(*argv, "-P") == 0 && ARG_VAL) {
+ mkey_password = koptarg;
+ manual_mkey = TRUE;
+ } else if (strcmp(*argv, "-r") == 0 && ARG_VAL) {
+ global_params.realm = koptarg;
+ global_params.mask |= KADM5_CONFIG_REALM;
+ /* not sure this is really necessary */
+ if ((retval = krb5_set_default_realm(util_context,
+ global_params.realm))) {
+ com_err(progname, retval, "while setting default realm name");
+ exit_status++;
+ goto cleanup;
+ }
+ } else if (strcmp(*argv, "-k") == 0 && ARG_VAL) {
+ if (krb5_string_to_enctype(koptarg, &global_params.enctype))
+ com_err(argv[0], 0, "%s is an invalid enctype", koptarg);
+ else
+ global_params.mask |= KADM5_CONFIG_ENCTYPE;
+ } else if (strcmp(*argv, "-M") == 0 && ARG_VAL) {
+ global_params.mkey_name = koptarg;
+ global_params.mask |= KADM5_CONFIG_MKEY_NAME;
+ } else if (strcmp(*argv, "-sf") == 0 && ARG_VAL) {
+ global_params.stash_file = koptarg;
+ global_params.mask |= KADM5_CONFIG_STASH_FILE;
+ } else if (strcmp(*argv, "-m") == 0) {
+ manual_mkey = TRUE;
+ global_params.mkey_from_kbd = 1;
+ global_params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
+ } else if (strcmp(*argv, "-D") == 0 && ARG_VAL) {
+ bind_dn = koptarg;
+ if (bind_dn == NULL) {
+ com_err(progname, ENOMEM, "while reading ldap parameters");
+ exit_status++;
+ goto cleanup;
+ }
+ ldapmask |= CMD_LDAP_D;
+ } else if (strcmp(*argv, "-w") == 0 && ARG_VAL) {
+ passwd = strdup(koptarg);
+ if (passwd == NULL) {
+ com_err(progname, ENOMEM, "while reading ldap parameters");
+ exit_status++;
+ goto cleanup;
+ }
+ ldapmask |= CMD_LDAP_W;
+ } else if (strcmp(*argv, "-h") == 0 && ARG_VAL) {
+ ldap_server = koptarg;
+ if (ldap_server == NULL) {
+ com_err(progname, ENOMEM, "while reading ldap parameters");
+ exit_status++;
+ goto cleanup;
+ }
+ ldapmask |= CMD_LDAP_H;
+ } else if (strcmp(*argv, "-p") == 0 && ARG_VAL) {
+ ldap_port = koptarg;
+ if (ldap_port == NULL) {
+ com_err(progname, ENOMEM, "while reading ldap parameters");
+ exit_status++;
+ goto cleanup;
+ }
+ ldapmask |= CMD_LDAP_P;
+ } else if (cmd_lookup(*argv) != NULL) {
+ if (cmd_argv[0] == NULL)
+ cmd_argv[0] = *argv;
+ else {
+ free(cmd_argv);
+ cmd_argv = NULL;
+ usage();
+ goto cleanup;
+ }
+ } else {
+ cmd_argv[cmd_argc++] = *argv;
+ }
+ argv++; argc--;
+ }
+
+ if (cmd_argv[0] == NULL) {
+ free(cmd_argv);
+ cmd_argv = NULL;
+ usage();
+ goto cleanup;
+ }
+
+ /* if we need to print the help message (because of --help option)
+ * we will print the help corresponding to the sub-command.
+ */
+ if (print_help_message) {
+ char *cmd_name = cmd_argv[0];
+ free(cmd_argv);
+ cmd_argv = NULL;
+ usage();
+ goto cleanup;
+ }
+
+ /* We need to check for the presence of default realm name only in
+ * the case of realm related operations like create, destroy etc.
+ */
+ if ((strcmp(cmd_argv[0], "create") == 0) ||
+ (strcmp(cmd_argv[0], "destroy") == 0) ||
+ (strcmp(cmd_argv[0], "modify") == 0) ||
+ (strcmp(cmd_argv[0], "view") == 0)
+ ) {
+ realm_name_required = TRUE;
+ }
+
+ if( !util_context->default_realm ) {
+ char *temp = NULL;
+ retval = krb5_get_default_realm(util_context, &temp);
+ if( retval ) {
+ if (realm_name_required) {
+ com_err (progname, retval, "while getting default realm");
+ exit_status++;
+ goto cleanup;
+ }
+ }
+ else
+ util_context->default_realm = temp;
+ }
+ /* If we have the realm name, we can safely say that
+ * realm_name is required so that we don't neglect any information.
+ */
+ else
+ realm_name_required = TRUE;
+
+ retval = profile_get_string( util_context->profile, KDB_REALM_SECTION,
+ util_context->default_realm, KDB_MODULE_POINTER,
+ NULL,
+ &value );
+
+ if(!(value)) {
+ retval = profile_get_string( util_context->profile, KDB_MODULE_DEF_SECTION,
+ KDB_MODULE_POINTER, NULL,
+ NULL,
+ &value );
+ if(!(value)) {
+ if (util_context->default_realm)
+ conf_section = strdup( util_context->default_realm );
+ }
+ else {
+ conf_section = strdup(value);
+ free(value);
+ }
+ }
+ else {
+ conf_section = strdup(value);
+ free(value);
+ }
+
+ if (realm_name_required) {
+ retval = kadm5_get_config_params(util_context, 1,
+ &global_params, &global_params);
+ if (retval) {
+ com_err(argv[0], retval, "while retreiving configuration parameters");
+ exit_status++;
+ goto cleanup;
+ }
+ gp_is_static = 0;
+ }
+
+ if ((retval = krb5_ldap_lib_init()) != 0) {
+ com_err(argv[0], retval, "while initializing error handling");
+ exit_status++;
+ goto cleanup;
+ }
+
+ /* Initialize the ldap context */
+ ldap_context = calloc(sizeof(krb5_ldap_context), 1);
+ if (ldap_context == NULL) {
+ com_err(argv[0], ENOMEM, "while initializing ldap handle");
+ exit_status++;
+ goto cleanup;
+ }
+
+ /* If LDAP parameters are specified, replace them with the values from config */
+ if (ldapmask & CMD_LDAP_D) {
+ /* If password is not specified, prompt for it */
+ if (passwd == NULL) {
+ passwd = (char *)malloc(MAX_PASSWD_LEN);
+ if (passwd == NULL) {
+ com_err(argv[0], ENOMEM, "while retrieving ldap configuration");
+ exit_status++;
+ goto cleanup;
+ }
+ prompt = (char *)malloc(MAX_PASSWD_PROMPT_LEN);
+ if (prompt == NULL) {
+ free(passwd);
+ passwd = NULL;
+ com_err(argv[0], ENOMEM, "while retrieving ldap configuration");
+ exit_status++;
+ goto cleanup;
+ }
+ memset(passwd, 0, sizeof(passwd));
+ passwd_len = MAX_PASSWD_LEN - 1;
+ snprintf(prompt, MAX_PASSWD_PROMPT_LEN, "Password for \"%s\"", bind_dn);
+
+ db_retval = krb5_read_password(util_context, prompt, NULL, passwd, &passwd_len);
+
+ if ((db_retval) || (passwd_len == 0)) {
+ com_err(argv[0], ENOMEM, "while retrieving ldap configuration");
+ free(passwd);
+ passwd = NULL;
+ exit_status++;
+ goto cleanup;
+ }
+ }
+
+ ldap_context->bind_pwd = passwd;
+ }
+
+ /* If ldaphost is specified, release entry filled by configuration & use this */
+ if (ldapmask & CMD_LDAP_H) {
+
+ ldap_context->server_info_list = (krb5_ldap_server_info **) calloc (2, sizeof (krb5_ldap_server_info *)) ;
+ if (ldap_context->server_info_list == NULL) {
+ com_err(argv[0], ENOMEM, "while initializing server list");
+ exit_status++;
+ goto cleanup;
+ }
+
+ ldap_context->server_info_list[0] = (krb5_ldap_server_info *) calloc (1, sizeof (krb5_ldap_server_info));
+ if (ldap_context->server_info_list[0] == NULL) {
+ com_err(argv[0], ENOMEM, "while initializing server list");
+ exit_status++;
+ goto cleanup;
+ }
+
+ ldap_context->server_info_list[0]->server_status = NOTSET;
+
+ ldap_context->server_info_list[0]->server_name = strdup(ldap_server);
+ if (ldap_context->server_info_list[0]->server_name == NULL) {
+ com_err(argv[0], ENOMEM, "while initializing server list");
+ exit_status++;
+ goto cleanup;
+ }
+ }
+ /* If ldapport is specified, release entry filled by configuration & use this*/
+ if (ldapmask & CMD_LDAP_P) {
+ ldap_context->port = atoi(ldap_port);
+ }
+ if (bind_dn) {
+ ldap_context->bind_dn = strdup(bind_dn);
+ if (ldap_context->bind_dn == NULL) {
+ com_err(argv[0], ENOMEM, "while retrieving ldap configuration");
+ exit_status++;
+ goto cleanup;
+ }
+ } else
+ ldap_context->bind_dn = NULL;
+
+ ldap_context->service_type = SERVICE_DN_TYPE_CLIENT;
+
+ if(realm_name_required) {
+ if ((global_params.enctype != ENCTYPE_UNKNOWN) &&
+ (!krb5_c_valid_enctype(global_params.enctype))) {
+ com_err(argv[0], KRB5_PROG_KEYTYPE_NOSUPP,
+ "while setting up enctype %d", global_params.enctype);
+ }
+ }
+
+ cmd = cmd_lookup(cmd_argv[0]);
+
+ /* Setup DAL handle to access the database */
+ dal_handle = calloc( (size_t)1, sizeof(kdb5_dal_handle) );
+ if( dal_handle == NULL ) {
+ goto cleanup;
+ }
+ dal_handle->db_context = ldap_context;
+ util_context->db_context = (void *) dal_handle;
+
+ db_retval = krb5_ldap_read_server_params(util_context, conf_section, KRB5_KDB_SRV_TYPE_OTHER);
+ if (db_retval) {
+ com_err(argv[0], db_retval, "while reading ldap configuration");
+ exit_status++;
+ goto cleanup;
+ }
+
+ if (cmd->opendb) {
+ db_retval = krb5_ldap_db_init( util_context, ldap_context);
+ if (db_retval) {
+ com_err(progname, db_retval, "while initializing database");
+ exit_status++;
+ goto cleanup;
+ }
+ db_inited = TRUE;
+ }
+ (*cmd->func)(cmd_argc, cmd_argv);
+
+ goto cleanup;
+
+cleanup:
+ if (passwd)
+ memset(passwd, 0, sizeof(passwd));
+ if (ldap_context && ldap_context->bind_pwd)
+ memset(ldap_context->bind_pwd, 0, sizeof(ldap_context->bind_pwd));
+
+ if (util_context) {
+ if (gp_is_static == 0)
+ kadm5_free_config_params(util_context, &global_params);
+ krb5_ldap_close(util_context);
+ krb5_free_context(util_context);
+ }
+
+ if (cmd_argv)
+ free(cmd_argv);
+ if (prompt)
+ free(prompt);
+ if (conf_section)
+ free(conf_section);
+ if (dal_handle)
+ free(dal_handle);
+
+ if (usage_print) {
+ usage();
+ }
+
+ return exit_status;
+}
+
diff --git a/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.h b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.h
new file mode 100644
index 000000000..f2c49a57e
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.h
@@ -0,0 +1,78 @@
+/*
+ * kadmin/ldap_util/kdb5_ldap_util.h
+ */
+
+/* Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "kdb_ldap.h"
+#include "kdb5_ldap_realm.h"
+#include "kdb5_ldap_services.h"
+#include "kdb5_ldap_policy.h"
+
+#define MAIN_HELP -1
+#define CREATE_REALM 1
+#define MODIFY_REALM 2
+#define VIEW_REALM 3
+#define DESTROY_REALM 4
+#define LIST_REALM 5
+
+#ifdef HAVE_EDIRECTORY
+# define CREATE_SERVICE 6
+# define MODIFY_SERVICE 7
+# define VIEW_SERVICE 8
+# define DESTROY_SERVICE 9
+# define LIST_SERVICE 10
+# define SET_SRV_PW 16
+#else
+# define STASH_SRV_PW 17
+#endif
+
+#define CREATE_POLICY 11
+#define MODIFY_POLICY 12
+#define VIEW_POLICY 13
+#define DESTROY_POLICY 14
+#define LIST_POLICY 15
+
+extern int exit_status;
+extern krb5_context util_context;
+
+extern void usage();
+extern void db_usage(int);
+
+#define ARG_VAL (--argc > 0 ? (koptarg = *(++argv)) : (char *)(usage(MAIN_HELP), NULL))
+
+/* Following are the bitmaps that indicate which of the options among -D, -w, -h, -p & -t
+ * were specified on the command line.
+ */
+#define CMD_LDAP_D 0x1 /* set if -D option is specified */
+#define CMD_LDAP_W 0x2 /* set if -w option is specified */
+#define CMD_LDAP_H 0x4 /* set if -h option is specified */
+#define CMD_LDAP_P 0x8 /* set if -p option is specified */
+
+#define MAX_PASSWD_LEN 1024
+#define MAX_PASSWD_PROMPT_LEN 276 /* max_dn_size(=256) + strlen("Password for \" \"")=20 */
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ChangeLog b/src/plugins/kdb/ldap/libkdb_ldap/ChangeLog
new file mode 100644
index 000000000..d8553db18
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ChangeLog
@@ -0,0 +1,37 @@
+2006-04-08 Ken Raeburn <raeburn@mit.edu>
+
+ * kdb_ldap.c, kdb_ldap_conn.c: Include autoconf.h before testing
+ HAVE_UNISTD_H.
+
+2006-03-22 Ken Raeburn <raeburn@mit.edu>
+
+ * Makefile.in (DEFS): Define a bunch of macros for local renaming
+ of symbol names duplicated in libkdb5 and exported from there.
+
+2006-03-21 Ken Raeburn <raeburn@mit.edu>
+
+ * Makefile.in (SHLIB_EXPDEPS, SHLIB_EXPLIBS): Add kdb5 library.
+ (LIBMAJOR): Bump to 1.
+
+2006-03-20 Ken Raeburn <raeburn@mit.edu>
+
+ * ldap_misc.c (krb5_ldap_get_keysalt_tuples): Unused function
+ deleted.
+ (LDAP_DEFAULT_ENCTYPE, LDAP_DEFAULT_SALTTYPE): Macros deleted.
+ * kdb_ldap.h (krb5_ldap_get_keysalt_tuples): Don't declare it.
+
+2006-03-17 Ken Raeburn <raeburn@mit.edu>
+
+ * configure.in, kdb_ldap.c, kdb_ldap_conn.c, kdb_xdr.c, kdb_xdr.h,
+ kerberos.ldif, kerberos.schema, ldap_err.c, ldap_err.h,
+ ldap_fetch_mkey.c, ldap_handle.c, ldap_handle.h,
+ ldap_krbcontainer.c, ldap_krbcontainer.h, ldap_main.h,
+ ldap_misc.c, ldap_misc.h, ldap_principal2.c, ldap_principal.c,
+ ldap_principal.h, ldap_pwd_policy.c, ldap_pwd_policy.h,
+ ldap_realm.c, ldap_realm.h, ldap_service_rights.c,
+ ldap_services.c, ldap_services.h, ldap_service_stash.c,
+ ldap_service_stash.h, ldap_tkt_policy.c, ldap_tkt_policy.h,
+ princ_xdr.c, princ_xdr.h: Moved from plugins/kdb/kdb_ldap.
+ * libkdb_ldap.exports: Copied and updated.
+ * Makefile.in: Copied and updated to build a shared library.
+
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/Makefile.in b/src/plugins/kdb/ldap/libkdb_ldap/Makefile.in
new file mode 100644
index 000000000..1b650c530
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/Makefile.in
@@ -0,0 +1,280 @@
+thisconfigdir=.
+myfulldir=plugins/kdb/ldap/libkdb_ldap
+mydir=.
+BUILDTOP=$(REL)..$(S)..$(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)
+# Lots of ugliness here because of duplicated symbol names.
+# Can I just punt the duplicates and import from libkdb5, or
+# is keeping them separate important?
+DEFINES = \
+ -Dkrb5_dbe_lookup_last_pwd_change=kdb_ldap_dbe_lookup_last_pwd_change \
+ -Dkrb5_dbe_lookup_mod_princ_data=kdb_ldap_dbe_lookup_mod_princ_data \
+ -Dkrb5_dbe_lookup_tl_data=kdb_ldap_dbe_lookup_tl_data \
+ -Dkrb5_dbe_update_last_pwd_change=kdb_ldap_dbe_update_last_pwd_change \
+ -Dkrb5_dbe_update_mod_princ_data=kdb_ldap_dbe_update_mod_princ_data \
+ -Dkrb5_dbe_update_tl_data=kdb_ldap_dbe_update_tl_data
+DEFS=
+
+LOCALINCLUDES = -I$(SRCTOP)/lib/kdb
+
+LIBBASE=kdb_ldap
+LIBMAJOR=1
+LIBMINOR=0
+RELDIR=../plugins/kdb/ldap/libkdb_ldap
+# Depends on libk5crypto and libkrb5
+# Also on gssrpc, for xdr stuff.
+SHLIB_EXPDEPS = \
+ $(GSSRPC_DEPLIBS) \
+ $(TOPLIBD)/libk5crypto$(SHLIBEXT) \
+ $(SUPPORT_DEPLIB) \
+ $(TOPLIBD)/libkrb5$(SHLIBEXT)
+SHLIB_EXPLIBS= $(GSSRPC_LIBS) -lkrb5 -lk5crypto $(SUPPORT_LIB) -lldap -llber $(LIBS)
+SHLIB_DIRS=-L$(TOPLIBD)
+SHLIB_RDIRS=$(KRB5_LIBDIR)
+
+SRCS= $(srcdir)/kdb_ldap.c \
+ $(srcdir)/kdb_ldap_conn.c \
+ $(srcdir)/ldap_realm.c \
+ $(srcdir)/ldap_krbcontainer.c \
+ $(srcdir)/ldap_principal.c \
+ $(srcdir)/ldap_principal2.c \
+ $(srcdir)/ldap_pwd_policy.c \
+ $(srcdir)/ldap_misc.c \
+ $(srcdir)/ldap_handle.c \
+ $(srcdir)/ldap_tkt_policy.c \
+ $(srcdir)/ldap_services.c \
+ $(srcdir)/ldap_service_rights.c \
+ $(srcdir)/princ_xdr.c \
+ $(srcdir)/ldap_fetch_mkey.c \
+ $(srcdir)/ldap_service_stash.c \
+ $(srcdir)/kdb_xdr.c \
+ $(srcdir)/ldap_err.c
+
+STOBJLISTS=OBJS.ST
+STLIBOBJS= kdb_ldap.o \
+ kdb_ldap_conn.o \
+ ldap_realm.o \
+ ldap_krbcontainer.o \
+ ldap_principal.o \
+ ldap_principal2.o \
+ ldap_pwd_policy.o \
+ ldap_misc.o \
+ ldap_handle.o \
+ ldap_tkt_policy.o \
+ ldap_services.o \
+ ldap_service_rights.o \
+ princ_xdr.o \
+ ldap_fetch_mkey.o \
+ ldap_service_stash.o \
+ kdb_xdr.o \
+ ldap_err.o
+
+all-unix:: all-liblinks
+install-unix:: install-libs
+clean-unix:: clean-liblinks clean-libobjs clean-libs
+
+# @lib_frag@
+# @libobj_frag@
+
+# +++ Dependency line eater +++
+#
+# Makefile dependencies follow. This must be the last section in
+# the Makefile.in file
+#
+kdb_ldap.so kdb_ldap.po $(OUTPRE)kdb_ldap.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+ $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+ $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+ $(SRCTOP)/lib/kdb/kdb5.h kdb_ldap.c kdb_ldap.h ldap_err.h \
+ ldap_krbcontainer.h ldap_misc.h ldap_realm.h ldap_services.h
+kdb_ldap_conn.so kdb_ldap_conn.po $(OUTPRE)kdb_ldap_conn.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+ $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+ $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+ $(SRCTOP)/lib/kdb/kdb5.h kdb_ldap.h kdb_ldap_conn.c \
+ ldap_handle.h ldap_krbcontainer.h ldap_main.h ldap_misc.h \
+ ldap_realm.h ldap_service_stash.h ldap_services.h
+ldap_realm.so ldap_realm.po $(OUTPRE)ldap_realm.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+ $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+ $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+ $(SRCTOP)/lib/kdb/kdb5.h kdb_ldap.h ldap_err.h ldap_handle.h \
+ ldap_krbcontainer.h ldap_main.h ldap_misc.h ldap_principal.h \
+ ldap_realm.c ldap_realm.h ldap_services.h ldap_tkt_policy.h
+ldap_krbcontainer.so ldap_krbcontainer.po $(OUTPRE)ldap_krbcontainer.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+ $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+ $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+ $(SRCTOP)/lib/kdb/kdb5.h kdb_ldap.h ldap_err.h ldap_handle.h \
+ ldap_krbcontainer.c ldap_krbcontainer.h ldap_main.h \
+ ldap_misc.h ldap_realm.h ldap_services.h
+ldap_principal.so ldap_principal.po $(OUTPRE)ldap_principal.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+ $(BUILDTOP)/include/gssrpc/auth.h $(BUILDTOP)/include/gssrpc/auth_gss.h \
+ $(BUILDTOP)/include/gssrpc/auth_unix.h $(BUILDTOP)/include/gssrpc/clnt.h \
+ $(BUILDTOP)/include/gssrpc/rename.h $(BUILDTOP)/include/gssrpc/rpc.h \
+ $(BUILDTOP)/include/gssrpc/rpc_msg.h $(BUILDTOP)/include/gssrpc/svc.h \
+ $(BUILDTOP)/include/gssrpc/svc_auth.h $(BUILDTOP)/include/gssrpc/types.h \
+ $(BUILDTOP)/include/gssrpc/xdr.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+ $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+ $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+ $(SRCTOP)/lib/kdb/kdb5.h kdb_ldap.h ldap_err.h ldap_handle.h \
+ ldap_krbcontainer.h ldap_main.h ldap_misc.h ldap_principal.c \
+ ldap_principal.h ldap_realm.h ldap_services.h ldap_tkt_policy.h \
+ princ_xdr.h
+ldap_principal2.so ldap_principal2.po $(OUTPRE)ldap_principal2.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+ $(BUILDTOP)/include/gssrpc/auth.h $(BUILDTOP)/include/gssrpc/auth_gss.h \
+ $(BUILDTOP)/include/gssrpc/auth_unix.h $(BUILDTOP)/include/gssrpc/clnt.h \
+ $(BUILDTOP)/include/gssrpc/rename.h $(BUILDTOP)/include/gssrpc/rpc.h \
+ $(BUILDTOP)/include/gssrpc/rpc_msg.h $(BUILDTOP)/include/gssrpc/svc.h \
+ $(BUILDTOP)/include/gssrpc/svc_auth.h $(BUILDTOP)/include/gssrpc/types.h \
+ $(BUILDTOP)/include/gssrpc/xdr.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+ $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+ $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+ $(SRCTOP)/lib/kdb/kdb5.h kdb_ldap.h ldap_err.h ldap_handle.h \
+ ldap_krbcontainer.h ldap_main.h ldap_misc.h ldap_principal.h \
+ ldap_principal2.c ldap_pwd_policy.h ldap_realm.h ldap_services.h \
+ ldap_tkt_policy.h princ_xdr.h
+ldap_pwd_policy.so ldap_pwd_policy.po $(OUTPRE)ldap_pwd_policy.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+ $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+ $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+ $(SRCTOP)/lib/kdb/kdb5.h kdb_ldap.h ldap_err.h ldap_handle.h \
+ ldap_krbcontainer.h ldap_main.h ldap_misc.h ldap_pwd_policy.c \
+ ldap_pwd_policy.h ldap_realm.h ldap_services.h
+ldap_misc.so ldap_misc.po $(OUTPRE)ldap_misc.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+ $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+ $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+ $(SRCTOP)/lib/kdb/kdb5.h kdb_ldap.h ldap_err.h ldap_krbcontainer.h \
+ ldap_misc.c ldap_misc.h ldap_realm.h ldap_services.h
+ldap_handle.so ldap_handle.po $(OUTPRE)ldap_handle.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+ $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+ $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+ $(SRCTOP)/lib/kdb/kdb5.h kdb_ldap.h ldap_handle.c ldap_handle.h \
+ ldap_krbcontainer.h ldap_main.h ldap_misc.h ldap_realm.h \
+ ldap_services.h
+ldap_tkt_policy.so ldap_tkt_policy.po $(OUTPRE)ldap_tkt_policy.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+ $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+ $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+ $(SRCTOP)/lib/kdb/kdb5.h kdb_ldap.h ldap_err.h ldap_handle.h \
+ ldap_krbcontainer.h ldap_main.h ldap_misc.h ldap_realm.h \
+ ldap_services.h ldap_tkt_policy.c ldap_tkt_policy.h
+ldap_services.so ldap_services.po $(OUTPRE)ldap_services.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+ $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+ $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+ $(SRCTOP)/lib/kdb/kdb5.h kdb_ldap.h ldap_err.h ldap_handle.h \
+ ldap_krbcontainer.h ldap_main.h ldap_misc.h ldap_realm.h \
+ ldap_services.c ldap_services.h
+ldap_service_rights.so ldap_service_rights.po $(OUTPRE)ldap_service_rights.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+ $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+ $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+ $(SRCTOP)/lib/kdb/kdb5.h kdb_ldap.h ldap_err.h ldap_handle.h \
+ ldap_krbcontainer.h ldap_main.h ldap_misc.h ldap_realm.h \
+ ldap_service_rights.c ldap_services.h
+princ_xdr.so princ_xdr.po $(OUTPRE)princ_xdr.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+ $(BUILDTOP)/include/gssrpc/auth.h $(BUILDTOP)/include/gssrpc/auth_gss.h \
+ $(BUILDTOP)/include/gssrpc/auth_unix.h $(BUILDTOP)/include/gssrpc/clnt.h \
+ $(BUILDTOP)/include/gssrpc/rename.h $(BUILDTOP)/include/gssrpc/rpc.h \
+ $(BUILDTOP)/include/gssrpc/rpc_msg.h $(BUILDTOP)/include/gssrpc/svc.h \
+ $(BUILDTOP)/include/gssrpc/svc_auth.h $(BUILDTOP)/include/gssrpc/types.h \
+ $(BUILDTOP)/include/gssrpc/xdr.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+ $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+ $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+ $(SRCTOP)/lib/kdb/kdb5.h kdb_ldap.h ldap_krbcontainer.h \
+ ldap_principal.h ldap_realm.h ldap_tkt_policy.h princ_xdr.c \
+ princ_xdr.h
+ldap_fetch_mkey.so ldap_fetch_mkey.po $(OUTPRE)ldap_fetch_mkey.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+ $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+ $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+ $(SRCTOP)/lib/kdb/kdb5.h kdb_ldap.h ldap_fetch_mkey.c \
+ ldap_handle.h ldap_krbcontainer.h ldap_main.h ldap_misc.h \
+ ldap_realm.h ldap_services.h
+ldap_service_stash.so ldap_service_stash.po $(OUTPRE)ldap_service_stash.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-int.h \
+ $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \
+ $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \
+ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+ $(SRCTOP)/lib/kdb/kdb5.h kdb_ldap.h ldap_handle.h ldap_krbcontainer.h \
+ ldap_main.h ldap_misc.h ldap_realm.h ldap_service_stash.c \
+ ldap_service_stash.h ldap_services.h
+kdb_xdr.so kdb_xdr.po $(OUTPRE)kdb_xdr.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-err.h \
+ $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \
+ $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \
+ $(SRCTOP)/include/kdb.h $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \
+ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \
+ kdb_xdr.c kdb_xdr.h
+ldap_err.so ldap_err.po $(OUTPRE)ldap_err.$(OBJEXT): \
+ $(BUILDTOP)/include/kdb5_err.h $(COM_ERR_DEPS) ldap_err.c \
+ ldap_err.h
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/configure.in b/src/plugins/kdb/ldap/libkdb_ldap/configure.in
new file mode 100644
index 000000000..6e280232e
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/configure.in
@@ -0,0 +1,26 @@
+K5_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)
+
+OPENLDAP=1
+AC_CHECK_HEADERS([ldap.h], :, [OPENLDAP=0; AC_MSG_WARN([ldap.h not found])])
+AC_CHECK_HEADERS([lber.h], :, [OPENLDAP=0; AC_MSG_WARN([lber.h not found])])
+AC_CHECK_LIB(ldap, ldap_init, :, [OPENLDAP=0; AC_MSG_WARN([libldap not found])])
+AC_CHECK_LIB(lber, ber_init, :, [OPENLDAP=0; AC_MSG_WARN([liblber not found])])
+
+if test "$OPENLDAP" = "0"; then
+ AC_ERROR("OPENLDAP libraries missing Skipping openldap database module")
+fi
+
+
+KRB5_RUN_FLAGS
+dnl The following is for check...
+KRB5_BUILD_PROGRAM
+KRB5_BUILD_LIBOBJS
+KRB5_BUILD_LIBRARY_WITH_DEPS
+dnl
+V5_AC_OUTPUT_MAKEFILE
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c
new file mode 100644
index 000000000..358bf152f
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c
@@ -0,0 +1,490 @@
+/*
+ * lib/kdb/kdb_ldap/kdb_ldap.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "autoconf.h"
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <ctype.h>
+#include "kdb_ldap.h"
+#include "ldap_misc.h"
+#include <kdb5.h>
+
+static krb5_error_code
+krb5_ldap_get_db_opt( char *input, char **opt, char **val )
+{
+ char *pos = strchr(input, '=');
+
+ *val = NULL;
+ if (pos == NULL)
+ {
+ *opt = strdup(input);
+ if (*opt == NULL)
+ {
+ return ENOMEM;
+ }
+ }
+ else
+ {
+ int len = pos - input;
+ *opt = malloc((unsigned) len + 1);
+ if (!*opt)
+ {
+ return ENOMEM;
+ }
+ memcpy(*opt, input, (unsigned) len);
+ /* ignore trailing blanks */
+ while (isblank((*opt)[len-1]))
+ --len;
+ (*opt)[len] = '\0';
+
+ pos += 1; /* move past '=' */
+ while (isblank(*pos)) /* ignore leading blanks */
+ pos += 1;
+ if (*pos != '\0') {
+ *val = strdup (pos);
+ if (!*val)
+ {
+ free (*opt);
+ return ENOMEM;
+ }
+ }
+ }
+ return (0);
+
+}
+
+
+/*
+ * ldap get age
+ */
+krb5_error_code
+krb5_ldap_db_get_age(context, db_name, age)
+ krb5_context context;
+ char *db_name;
+ time_t *age;
+{
+ time (age);
+ return 0;
+}
+
+/*
+ * read startup information - kerberos and realm container
+ */
+krb5_error_code
+krb5_ldap_read_startup_information(krb5_context context)
+{
+ krb5_error_code retval = 0;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ int mask=0;
+
+ SETUP_CONTEXT();
+ if ((retval=krb5_ldap_read_krbcontainer_params(context, &(ldap_context->krbcontainer)))) {
+ prepend_err_str (context, "Unable to read Kerberos container", retval, retval);
+ goto cleanup;
+ }
+
+ if ((retval=krb5_ldap_read_realm_params(context, context->default_realm, &(ldap_context->lrparams), &mask))) {
+ prepend_err_str (context, "Unable to read Realm", retval, retval);
+ goto cleanup;
+ }
+
+ cleanup:
+ return retval;
+}
+
+
+/* Function to check if a LDAP server supports the SASL external mechanism
+ *Return values:
+ * 0 => supports
+ * 1 => does not support
+ * 2 => don't know
+ */
+#define ERR_MSG1 "Unable to check if SASL EXTERNAL mechanism is supported by LDAP server. Proceeding anyway ..."
+#define ERR_MSG2 "SASL EXTERNAL mechanism not supported by LDAP server. Can't perform certificate-based bind."
+
+int
+has_sasl_external_mech(context, ldap_server)
+ krb5_context context;
+ char *ldap_server;
+{
+ int i=0, flag=0, ret=0, retval=0;
+ char *attrs[]={"supportedSASLMechanisms", NULL}, **values=NULL;
+ LDAP *ld=NULL;
+ LDAPMessage *msg=NULL, *res=NULL;
+
+ ld = ldap_open(ldap_server, 389); /* Should the port number be configurable ? */
+ if(ld == NULL){
+ krb5_set_error_message(context, 2, "%s", ERR_MSG1);
+ ret = 2; /* Don't know */
+ goto cleanup;
+ }
+
+ /* Anonymous bind */
+ retval = ldap_simple_bind_s(ld, NULL, NULL);
+ if(retval != LDAP_SUCCESS){
+ krb5_set_error_message(context, 2, "%s", ERR_MSG1);
+ ret = 2; /* Don't know */
+ goto cleanup;
+ }
+
+ retval = ldap_search_s(ld, "", LDAP_SCOPE_BASE, NULL, attrs, 0, &res);
+ if(retval != LDAP_SUCCESS){
+ krb5_set_error_message(context, 2, "%s", ERR_MSG1);
+ ret = 2; /* Don't know */
+ goto cleanup;
+ }
+
+ msg = ldap_first_message(ld, res);
+ if(msg == NULL){
+ krb5_set_error_message(context, 2, "%s", ERR_MSG1);
+ ret = 2; /* Don't know */
+ goto cleanup;
+ }
+
+ values = ldap_get_values(ld, msg, "supportedSASLMechanisms");
+ if(values == NULL){
+ krb5_set_error_message(context, 1, "%s", ERR_MSG2);
+ ret = 1; /* Not supported */
+ goto cleanup;
+ }
+
+ for(i = 0; values[i] != NULL; i++){
+ if(strcmp(values[i], "EXTERNAL"))
+ continue;
+ flag = 1;
+ }
+
+ if(flag != 1){
+ krb5_set_error_message(context, 1, "%s", ERR_MSG2);
+ ret = 1; /* Not supported */
+ goto cleanup;
+ }
+
+cleanup:
+
+ if(values != NULL)
+ ldap_value_free(values);
+
+ if(res != NULL)
+ ldap_msgfree(res);
+
+ if(ld != NULL)
+ ldap_unbind_s(ld);
+
+ return ret;
+}
+
+void * krb5_ldap_alloc( krb5_context context, void *ptr, size_t size )
+{
+ return realloc(ptr, size);
+}
+
+void krb5_ldap_free( krb5_context context, void *ptr )
+
+{
+ free(ptr);
+}
+
+krb5_error_code krb5_ldap_open( krb5_context context,
+ char *conf_section,
+ char **db_args,
+ int mode )
+{
+ krb5_error_code status = 0;
+ char **t_ptr = db_args;
+ krb5_ldap_context *ldap_context=NULL;
+ int srv_cnt = 0;
+ kdb5_dal_handle *dal_handle=NULL;
+
+ /* Clear the global error string */
+ krb5_clear_error_message(context);
+
+ ldap_context = calloc(1, sizeof(krb5_ldap_context));
+ if (ldap_context == NULL)
+ {
+ status = ENOMEM;
+ goto clean_n_exit;
+ }
+
+
+ while ( t_ptr && *t_ptr )
+ {
+ char *opt = NULL, *val = NULL;
+
+ if( (status = krb5_ldap_get_db_opt( *t_ptr, &opt, &val )) != 0 )
+ {
+ goto clean_n_exit;
+ }
+ if( opt && !strcmp( opt, "binddn" ) )
+ {
+ if( ldap_context->bind_dn )
+ {
+ free (opt);
+ free (val);
+ status = EINVAL;
+ krb5_set_error_message (context, status, "'binddn' missing");
+ goto clean_n_exit;
+ }
+ if( val == NULL )
+ {
+ status = EINVAL;
+ krb5_set_error_message (context, status, "'binddn' value missing");
+ free(opt);
+ goto clean_n_exit;
+ }
+ ldap_context->bind_dn = strdup(val);
+ if (ldap_context->bind_dn == NULL) {
+ free (opt);
+ free (val);
+ status = ENOMEM;
+ goto clean_n_exit;
+ }
+ }
+ else if( opt && !strcmp( opt, "nconns" ) )
+ {
+ if( ldap_context->max_server_conns )
+ {
+ free (opt);
+ free (val);
+ status = EINVAL;
+ krb5_set_error_message (context, status, "'nconns' missing");
+ goto clean_n_exit;
+ }
+ if( val == NULL )
+ {
+ status = EINVAL;
+ krb5_set_error_message (context, status, "'nconns' value missing");
+ free(opt);
+ goto clean_n_exit;
+ }
+ ldap_context->max_server_conns = atoi(val) ? atoi(val) : DEFAULT_CONNS_PER_SERVER;
+ }
+ else if( opt && !strcmp( opt, "bindpwd" ) )
+ {
+ if( ldap_context->bind_pwd )
+ {
+ free (opt);
+ free (val);
+ status = EINVAL;
+ krb5_set_error_message (context, status, "'bindpwd' missing");
+ goto clean_n_exit;
+ }
+ if( val == NULL )
+ {
+ status = EINVAL;
+ krb5_set_error_message (context, status, "'bindpwd' value missing");
+ free(opt);
+ goto clean_n_exit;
+ }
+ ldap_context->bind_pwd = strdup(val);
+ if (ldap_context->bind_pwd == NULL) {
+ free (opt);
+ free (val);
+ status = ENOMEM;
+ goto clean_n_exit;
+ }
+ }
+ else if( opt && !strcmp( opt, "host" ) )
+ {
+ char *port = NULL;
+
+ if( val == NULL )
+ {
+ status = EINVAL;
+ krb5_set_error_message (context, status, "'host' value missing");
+ free(opt);
+ goto clean_n_exit;
+ }
+ if (ldap_context->server_info_list == NULL)
+ ldap_context->server_info_list = (krb5_ldap_server_info **) calloc (SERV_COUNT+1, sizeof (krb5_ldap_server_info *)) ;
+
+ if (ldap_context->server_info_list == NULL) {
+ free (opt);
+ free (val);
+ status = ENOMEM;
+ goto clean_n_exit;
+ }
+
+ ldap_context->server_info_list[srv_cnt] = (krb5_ldap_server_info *) calloc (1, sizeof (krb5_ldap_server_info));
+ if (ldap_context->server_info_list[srv_cnt] == NULL) {
+ free (opt);
+ free (val);
+ status = ENOMEM;
+ goto clean_n_exit;
+ }
+
+ ldap_context->server_info_list[srv_cnt]->server_status = NOTSET;
+
+ val = strtok_r(val, ":", &port);
+ ldap_context->server_info_list[srv_cnt]->server_name = strdup(val);
+ if (ldap_context->server_info_list[srv_cnt]->server_name == NULL) {
+ free (opt);
+ free (val);
+ status = ENOMEM;
+ goto clean_n_exit;
+ }
+
+ if (port) {
+ ldap_context->server_info_list[srv_cnt]->port = atoi(port);
+ }
+ srv_cnt++;
+ }
+ else if( opt && !strcmp( opt, "port" ) )
+ {
+ if( ldap_context->port )
+ {
+ free (opt);
+ free (val);
+ status = EINVAL;
+ krb5_set_error_message (context, status, "'port' missing");
+ goto clean_n_exit;
+ }
+ if( val == NULL )
+ {
+ status = EINVAL;
+ krb5_set_error_message (context, status, "'port' value missing");
+ free(opt);
+ goto clean_n_exit;
+ }
+ ldap_context->port = atoi(val);
+ }
+ else if( opt && !strcmp( opt, "cert" ) )
+ {
+ if( val == NULL )
+ {
+ status = EINVAL;
+ krb5_set_error_message (context, status, "'cert' value missing");
+ free(opt);
+ goto clean_n_exit;
+ }
+
+ if( ldap_context->root_certificate_file == NULL )
+ {
+ ldap_context->root_certificate_file = strdup(val);
+ if (ldap_context->root_certificate_file == NULL) {
+ free (opt);
+ free (val);
+ status = ENOMEM;
+ goto clean_n_exit;
+ }
+ }
+ else
+ {
+ void *tmp=NULL;
+ char *oldstr = NULL;
+ unsigned int len=0;
+
+ oldstr = strdup(ldap_context->root_certificate_file);
+ if (oldstr == NULL)
+ {
+ free (opt);
+ free (val);
+ status = ENOMEM;
+ goto clean_n_exit;
+ }
+
+ tmp = ldap_context->root_certificate_file;
+ len = strlen(ldap_context->root_certificate_file) + 2 + strlen(val);
+ ldap_context->root_certificate_file = realloc(ldap_context->root_certificate_file,
+ len);
+ if (ldap_context->root_certificate_file == NULL) {
+ free (tmp);
+ free (opt);
+ free (val);
+ status = ENOMEM;
+ goto clean_n_exit;
+ }
+ memset(ldap_context->root_certificate_file, 0, len);
+ sprintf(ldap_context->root_certificate_file,"%s %s", oldstr, val);
+ free (oldstr);
+ }
+ }
+ /* ignore hash argument. Might have been passed from create */
+ else
+ {
+ status = EINVAL;
+ krb5_set_error_message (context, status, "unknown option \'%s\'",
+ opt?opt:val);
+ free(opt);
+ free(val);
+ goto clean_n_exit;
+ }
+
+ free(opt);
+ free(val);
+ t_ptr++;
+ }
+
+ dal_handle = (kdb5_dal_handle *) context->db_context;
+ dal_handle->db_context = ldap_context;
+ status = krb5_ldap_read_server_params(context, conf_section, mode & 0x0300);
+ if (status) {
+ ldap_context = NULL;
+ dal_handle->db_context = NULL;
+ prepend_err_str (context, "Error reading LDAP server params: ", status, status);
+ goto clean_n_exit;
+ }
+ if ((status=krb5_ldap_db_init( context, ldap_context)) != 0) {
+ goto clean_n_exit;
+ }
+
+ if ((status=krb5_ldap_read_startup_information(context)) != 0) {
+ goto clean_n_exit;
+ }
+
+ clean_n_exit:
+ /* may be clearing up is not required db_fini might do it for us, check out */
+ if (status) {
+ krb5_ldap_close(context);
+ }
+ return status;
+}
+
+#include "ldap_err.h"
+int
+set_ldap_error (krb5_context ctx, int st, int op)
+{
+ int translated_st = translate_ldap_error(st, op);
+ krb5_set_error_message(ctx, translated_st, "%s", ldap_err2string(st));
+ return translated_st;
+}
+
+void
+prepend_err_str (krb5_context ctx, const char *str, krb5_error_code err,
+ krb5_error_code oerr)
+{
+ const char *omsg;
+ if (oerr == 0) oerr = err;
+ omsg = krb5_get_error_message (ctx, err);
+ krb5_set_error_message (ctx, err, "%s %s", str, omsg);
+}
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
new file mode 100644
index 000000000..888fed0c5
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
@@ -0,0 +1,262 @@
+/*
+ * lib/kdb/kdb_ldap/kdb_ldap.h
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* */
+#ifndef _KDB_LDAP_H
+#define _KDB_LDAP_H 1
+
+#include <ldap.h>
+#include <k5-thread.h>
+#include <kdb5.h>
+#include "k5-int.h"
+#include "ldap_krbcontainer.h"
+#include "ldap_realm.h"
+
+extern struct timeval timelimit;
+
+#define SERV_COUNT 100
+#define DEFAULT_CONNS_PER_SERVER 5
+#define REALM_READ_REFRESH_INTERVAL (5 * 60)
+
+#ifdef HAVE_EDIRECTORY
+#define SECURITY_CONTAINER "cn=Security"
+#define KERBEROS_CONTAINER "cn=Kerberos,cn=Security"
+#endif
+
+#define NEG(val) (val <0) ? abs(val) : -val ;
+#define MAXINTLEN 10
+
+#define IGNORE_STATUS 0
+#define CHECK_STATUS 1
+
+#define SETUP_CONTEXT() if (context == NULL || context->db_context == NULL \
+ || ((kdb5_dal_handle *)context->db_context)->db_context == NULL) { \
+ return EINVAL; \
+ } \
+ dal_handle = (kdb5_dal_handle *)context->db_context; \
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context; \
+ if (ldap_context == NULL || ldap_context->server_info_list == NULL) \
+ return KRB5_KDB_DBNOTINITED;
+
+#define GET_HANDLE() ld = NULL; \
+ st = krb5_ldap_request_handle_from_pool(ldap_context, &ldap_server_handle); \
+ if (st != 0) { \
+ prepend_err_str(context, "LDAP handle unavailable: ", KRB5_KDB_ACCESS_ERROR, st); \
+ st = KRB5_KDB_ACCESS_ERROR; \
+ goto cleanup; \
+ } \
+ ld = ldap_server_handle->ldap_handle;
+
+extern int set_ldap_error (krb5_context ctx, int st, int op);
+extern void prepend_err_str (krb5_context ctx, const char *s, krb5_error_code err, krb5_error_code oerr);
+
+#define LDAP_SEARCH(base, scope, filter, attrs) LDAP_SEARCH_1(base, scope, filter, attrs, CHECK_STATUS)
+
+#define LDAP_SEARCH_1(base, scope, filter, attrs, status_check) \
+ do { \
+ st = ldap_search_ext_s(ld, base, scope, filter, attrs, 0, NULL, NULL, &timelimit, LDAP_NO_LIMIT, &result); \
+ if (translate_ldap_error(st, OP_SEARCH) == KRB5_KDB_ACCESS_ERROR) { \
+ tempst = krb5_ldap_rebind(ldap_context, &ldap_server_handle); \
+ if (ldap_server_handle) \
+ ld = ldap_server_handle->ldap_handle; \
+ } \
+ }while (translate_ldap_error(st, OP_SEARCH) == KRB5_KDB_ACCESS_ERROR && tempst == 0); \
+ \
+ if (status_check != IGNORE_STATUS) { \
+ if (tempst != 0) { \
+ prepend_err_str(context, "LDAP handle unavailable: ", KRB5_KDB_ACCESS_ERROR, st); \
+ st = KRB5_KDB_ACCESS_ERROR; \
+ goto cleanup; \
+ } \
+ if (st != LDAP_SUCCESS) { \
+ st = set_ldap_error(context, st, OP_SEARCH); \
+ goto cleanup; \
+ } \
+ }
+
+
+#define CHECK_CLASS_VALIDITY(st, mask, str) \
+ if (st != 0 || mask == 0) { \
+ if (st == 0 && mask == 0) { \
+ st = set_ldap_error(context, LDAP_OBJECT_CLASS_VIOLATION, OP_SEARCH); \
+ } \
+ prepend_err_str(context, str, st, st); \
+ goto cleanup; \
+ }
+
+#define CHECK_NULL(ptr) if (ptr == NULL) { \
+ st = ENOMEM; \
+ goto cleanup; \
+ }
+
+#define STORE16_INT(ptr, val) store_16_be(val, ptr)
+#define STORE32_INT(ptr, val) store_32_be(val, ptr)
+#define UNSTORE16_INT(ptr, val) (val = load_16_be(ptr))
+#define UNSTORE32_INT(ptr, val) (val = load_32_be(ptr))
+
+#define KRB5_CONF_KDC_BIND_DN "ldap_kdc_dn"
+#define KRB5_CONF_ADMIN_BIND_DN "ldap_kadmind_dn"
+#define KRB5_CONF_PWD_BIND_DN "ldap_passwd_dn"
+
+#define KDB_TL_USER_INFO 0x7ffe
+
+#define KDB_TL_PRINCTYPE 0x01
+#define KDB_TL_PRINCCOUNT 0x02
+#define KDB_TL_USERDN 0x03
+#define KDB_TL_KEYINFO 0x04
+#define KDB_TL_MASK 0x05
+#define KDB_TL_CONTAINERDN 0x06
+#define KDB_TL_TKTPOLICYDN 0x07
+
+
+#define CHECK_LDAP_HANDLE(lcontext) if (!(ldap_context \
+ && ldap_context->server_info_list)) { \
+ return KRB5_KDB_DBNOTINITED; \
+ }
+
+#define HNDL_LOCK(lcontext) k5_mutex_lock(&lcontext->hndl_lock)
+#define HNDL_UNLOCK(lcontext) k5_mutex_unlock(&lcontext->hndl_lock)
+
+/* To be used later */
+typedef struct _krb5_ldap_certificates{
+ char *certificate;
+ int certtype;
+}krb5_ldap_certificates;
+
+/* ldap server info structure */
+
+typedef enum _server_type {PRIMARY, SECONDARY} krb5_ldap_server_type;
+
+typedef enum _server_status {OFF, ON, NOTSET} krb5_ldap_server_status;
+
+typedef struct _krb5_ldap_server_info krb5_ldap_server_info;
+
+typedef struct _krb5_ldap_server_handle{
+ int msgid;
+ LDAP *ldap_handle;
+ krb5_boolean server_info_update_pending;
+ krb5_ldap_server_info *server_info;
+ struct _krb5_ldap_server_handle *next;
+
+}krb5_ldap_server_handle;
+
+struct _krb5_ldap_server_info {
+ krb5_ldap_server_type server_type;
+ krb5_ldap_server_status server_status;
+ krb5_ui_4 num_conns;
+ krb5_ldap_server_handle *ldap_server_handles;
+ time_t downtime;
+ char *server_name;
+ krb5_ui_4 port;
+ char *root_certificate_file;
+ struct _krb5_ldap_server_info *next;
+};
+
+
+/* ldap server structure */
+
+typedef enum {SERVICE_DN_TYPE_SERVER, SERVICE_DN_TYPE_CLIENT} krb5_ldap_servicetype;
+
+typedef struct _krb5_ldap_context {
+ krb5_ldap_servicetype service_type;
+ krb5_ldap_server_info **server_info_list;
+ krb5_ui_4 max_server_conns;
+ krb5_ui_4 port;
+ char *conf_section;
+ char *bind_dn;
+ char *bind_pwd;
+ char *service_password_file;
+ char *root_certificate_file;
+ char *service_cert_path;
+ char *service_cert_pass;
+ krb5_ldap_certificates **certificates;
+ krb5_ui_4 cert_count; /* certificate count */
+ k5_mutex_t hndl_lock;
+ krb5_ldap_krbcontainer_params *krbcontainer;
+ krb5_ldap_realm_params *lrparams;
+} krb5_ldap_context;
+
+
+typedef struct {
+ int nkey;
+ struct berval **keys;
+}KEY;
+
+#define k5ldap_inited(c) (c && c->db_context \
+ && ((kdb5_dal_handle*)c->db_context)->db_context \
+ && ((krb5_ldap_context *) ((kdb5_dal_handle*)c->db_context)->db_context))
+
+
+/* misc functions */
+
+krb5_error_code
+krb5_ldap_db_init(krb5_context, krb5_ldap_context *);
+
+krb5_error_code
+krb5_ldap_db_single_init(krb5_ldap_context *);
+
+krb5_error_code
+krb5_ldap_rebind(krb5_ldap_context *, krb5_ldap_server_handle **);
+
+krb5_error_code
+krb5_ldap_db_get_age(krb5_context, char *, time_t *);
+
+krb5_error_code
+krb5_ldap_lib_init();
+
+krb5_error_code
+krb5_ldap_lib_cleanup(void);
+
+void *
+krb5_ldap_alloc( krb5_context kcontext, void *ptr, size_t size );
+
+void
+krb5_ldap_free( krb5_context kcontext, void *ptr );
+
+krb5_error_code
+krb5_ldap_get_mkey(krb5_context, krb5_keyblock **);
+
+krb5_error_code
+krb5_ldap_set_mkey(krb5_context, char *, krb5_keyblock *);
+
+krb5_error_code
+krb5_ldap_open( krb5_context , char *,
+ char **db_args,
+ int mode );
+krb5_error_code
+krb5_ldap_close( krb5_context );
+
+krb5_error_code
+krb5_ldap_read_startup_information(krb5_context );
+
+int
+has_sasl_external_mech(krb5_context, char *);
+
+#endif
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c
new file mode 100644
index 000000000..b0902d23c
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c
@@ -0,0 +1,355 @@
+/*
+ * lib/kdb/kdb_ldap/kdb_ldap_conn.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "autoconf.h"
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ldap_main.h"
+#include "ldap_service_stash.h"
+#include <kdb5.h>
+
+static krb5_error_code
+krb5_validate_ldap_context(krb5_context context, krb5_ldap_context *ldap_context)
+{
+ krb5_error_code st=0;
+ unsigned char *password=NULL;
+
+ if (ldap_context->bind_dn == NULL) {
+ st = EINVAL;
+ krb5_set_error_message(context, st, "LDAP bind dn value missing ");
+ goto err_out;
+ }
+
+ if (ldap_context->bind_pwd == NULL && ldap_context->service_password_file == NULL) {
+ st = EINVAL;
+ krb5_set_error_message(context, st, "LDAP bind password value missing ");
+ goto err_out;
+ }
+
+ if (ldap_context->bind_pwd == NULL && ldap_context->service_password_file !=
+ NULL && ldap_context->service_cert_path == NULL) {
+ if ((st=krb5_ldap_readpassword(context, ldap_context, &password)) != 0) {
+ prepend_err_str(context, "Error reading password from stash: ", st, st);
+ goto err_out;
+ }
+
+ /* Check if the returned 'password' is actually the path of a certificate */
+ if (!strncmp("{FILE}", (char *)password, 6)) {
+ /* 'password' format: <path>\0<password> */
+ ldap_context->service_cert_path = strdup((char *)password + strlen("{FILE}"));
+ if (password[strlen((char *)password) + 1] == '\0')
+ ldap_context->service_cert_pass = NULL;
+ else
+ ldap_context->service_cert_pass = strdup((char *)password +
+ strlen((char *)password) + 1);
+ free(password);
+ } else {
+ ldap_context->bind_pwd = (char *)password;
+ if (ldap_context->bind_pwd == NULL) {
+ st = EINVAL;
+ krb5_set_error_message(context, st, "Error reading password from stash");
+ goto err_out;
+ }
+ }
+ }
+
+ /* NULL password not allowed */
+ if (ldap_context->bind_pwd != NULL && strlen(ldap_context->bind_pwd) == 0) {
+ st = EINVAL;
+ krb5_set_error_message(context, st, "Service password length is zero");
+ goto err_out;
+ }
+
+err_out:
+ return st;
+}
+
+/*
+ * Internal Functions called by init functions.
+ */
+
+static krb5_error_code
+krb5_ldap_bind(ldap_context, ldap_server_handle)
+ krb5_ldap_context *ldap_context;
+ krb5_ldap_server_handle *ldap_server_handle;
+{
+ krb5_error_code st=0;
+ struct berval bv={0, NULL}, *servercreds=NULL;
+
+ if(ldap_context->service_cert_path != NULL){
+ /* Certificate based bind (SASL EXTERNAL mechanism) */
+
+ st = ldap_sasl_bind_s(ldap_server_handle->ldap_handle,
+ NULL, /* Authenticating dn */
+ "EXTERNAL", /* Method used for authentication */
+ &bv,
+ NULL,
+ NULL,
+ &servercreds);
+
+ if (st == LDAP_SASL_BIND_IN_PROGRESS) {
+ st = ldap_sasl_bind_s( ldap_server_handle->ldap_handle,
+ NULL,
+ "EXTERNAL",
+ servercreds,
+ NULL,
+ NULL,
+ &servercreds);
+ }
+ } else {
+ /* password based simple bind */
+ st = ldap_simple_bind_s(ldap_server_handle->ldap_handle,
+ ldap_context->bind_dn,
+ ldap_context->bind_pwd);
+ }
+ return st;
+}
+
+static krb5_error_code
+krb5_ldap_initialize(ldap_context, server_info)
+ krb5_ldap_context *ldap_context;
+ krb5_ldap_server_info *server_info;
+{
+ int port=0;
+ krb5_error_code st=0;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+
+ if (server_info->port)
+ port = server_info->port;
+ else if (ldap_context->port)
+ port = ldap_context->port;
+ else
+ port = LDAPS_PORT;
+
+
+ ldap_server_handle = calloc(1, sizeof(krb5_ldap_server_handle));
+ if (ldap_server_handle == NULL) {
+ st = ENOMEM;
+ goto err_out;
+ }
+
+ /* ldap init */
+ if((ldap_server_handle->ldap_handle=ldap_init(server_info->server_name,
+ port)) == NULL) {
+ st = KRB5_KDB_ACCESS_ERROR;
+ krb5_set_error_message (0, st, "%s", strerror(errno));
+ goto err_out;
+ }
+
+ if ((st=krb5_ldap_bind(ldap_context, ldap_server_handle)) == 0) {
+ ldap_server_handle->server_info_update_pending = FALSE;
+ server_info->server_status = ON;
+ krb5_update_ldap_handle(ldap_server_handle, server_info);
+ } else {
+ krb5_set_error_message (0, KRB5_KDB_ACCESS_ERROR, "%s",
+ ldap_err2string(st));
+ st = KRB5_KDB_ACCESS_ERROR;
+ server_info->server_status = OFF;
+ time(&server_info->downtime);
+ /* ldap_unbind_s(ldap_server_handle->ldap_handle); */
+ free(ldap_server_handle);
+ }
+
+err_out:
+ return st;
+}
+
+/*
+ * initialization for data base routines.
+ */
+
+krb5_error_code
+krb5_ldap_db_init(krb5_context context, krb5_ldap_context *ldap_context)
+{
+ krb5_error_code st=0;
+ krb5_boolean sasl_mech_supported=TRUE;
+ int cnt=0, version=LDAP_VERSION3, tlsoption=LDAP_OPT_X_TLS_HARD;
+ struct timeval local_timelimit = {10,0};
+
+ if ((st=krb5_validate_ldap_context(context, ldap_context)) != 0)
+ goto err_out;
+
+ ldap_set_option(NULL, LDAP_OPT_PROTOCOL_VERSION, &version);
+ ldap_set_option(NULL, LDAP_OPT_NETWORK_TIMEOUT, &local_timelimit);
+ ldap_set_option(NULL, LDAP_OPT_X_TLS, &tlsoption);
+
+ HNDL_LOCK(ldap_context);
+ while (ldap_context->server_info_list[cnt] != NULL) {
+ krb5_ldap_server_info *server_info=NULL;
+
+ server_info = ldap_context->server_info_list[cnt];
+
+ if (server_info->server_status == NOTSET) {
+ int conns=0;
+
+ /*
+ * Check if the server has to perform certificate-based authentication
+ */
+ if(ldap_context->service_cert_path != NULL){
+ /* Find out if the server supports SASL EXTERNAL mechanism */
+ if(has_sasl_external_mech(context, server_info->server_name) == 1){
+ cnt++;
+ sasl_mech_supported = FALSE;
+ continue; /* Check the next LDAP server */
+ }
+ sasl_mech_supported = TRUE;
+ }
+
+ krb5_clear_error_message(context);
+
+ for (conns=0; conns < ldap_context->max_server_conns; ++conns) {
+ if ((st=krb5_ldap_initialize(ldap_context, server_info)) != 0)
+ break;
+ } /* for (conn= ... */
+
+ if (server_info->server_status == ON)
+ break; /* server init successful, so break */
+ }
+ ++cnt;
+ }
+ HNDL_UNLOCK(ldap_context);
+
+ err_out:
+ if (sasl_mech_supported == FALSE) {
+ st = KRB5_KDB_ACCESS_ERROR;
+ krb5_set_error_message (context, st, "Certificate based authentication requested but "
+ "not supported by LDAP servers");
+ }
+ return (st);
+}
+
+
+/*
+ * get a single handle. Do not lock the mutex
+ */
+
+krb5_error_code
+krb5_ldap_db_single_init(krb5_ldap_context *ldap_context)
+{
+ krb5_error_code st=0;
+ int cnt=0;
+ krb5_ldap_server_info *server_info=NULL;
+
+ while (ldap_context->server_info_list[cnt] != NULL) {
+ server_info = ldap_context->server_info_list[cnt];
+ if ((server_info->server_status == NOTSET || server_info->server_status == ON)) {
+ if (server_info->num_conns < ldap_context->max_server_conns-1) {
+ st = krb5_ldap_initialize(ldap_context, server_info);
+ if (st == LDAP_SUCCESS)
+ goto cleanup;
+ }
+ }
+ ++cnt;
+ }
+
+ /* If we are here, try to connect to all the servers */
+
+ cnt = 0;
+ while (ldap_context->server_info_list[cnt] != NULL) {
+ server_info = ldap_context->server_info_list[cnt];
+ st = krb5_ldap_initialize(ldap_context, server_info);
+ if (st == LDAP_SUCCESS)
+ goto cleanup;
+ ++cnt;
+ }
+ cleanup:
+ return (st);
+}
+
+krb5_error_code
+krb5_ldap_rebind(ldap_context, ldap_server_handle)
+ krb5_ldap_context *ldap_context;
+ krb5_ldap_server_handle **ldap_server_handle;
+{
+ krb5_ldap_server_handle *handle = *ldap_server_handle;
+ int port=0;
+
+ if (handle->server_info->port)
+ port = handle->server_info->port;
+ else if (ldap_context->port)
+ port = ldap_context->port;
+ else
+ port = LDAPS_PORT;
+
+ if ((handle->ldap_handle=ldap_init(handle->server_info->server_name, port)) == NULL
+ || krb5_ldap_bind(ldap_context, handle) != LDAP_SUCCESS)
+ return krb5_ldap_request_next_handle_from_pool(ldap_context, ldap_server_handle);
+ return LDAP_SUCCESS;
+}
+
+/*
+ * DAL API functions
+ */
+krb5_error_code krb5_ldap_lib_init()
+{
+ return 0;
+}
+
+krb5_error_code krb5_ldap_lib_cleanup()
+{
+ /* right now, no cleanup required */
+ return 0;
+}
+
+
+
+krb5_error_code
+krb5_ldap_close( krb5_context context)
+{
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+
+ if (context == NULL ||
+ context->db_context == NULL ||
+ ((kdb5_dal_handle *)context->db_context)->db_context == NULL)
+ return 0;
+
+ dal_handle = (kdb5_dal_handle *) context->db_context;
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+ dal_handle->db_context = NULL;
+
+ if (ldap_context == NULL)
+ return 0;
+
+ krb5_ldap_free_krbcontainer_params(ldap_context->krbcontainer);
+ ldap_context->krbcontainer = NULL;
+
+ krb5_ldap_free_realm_params(ldap_context->lrparams);
+ ldap_context->lrparams = NULL;
+
+ krb5_ldap_free_server_params(ldap_context);
+
+ return 0;
+}
+
+
+
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/kdb_xdr.c b/src/plugins/kdb/ldap/libkdb_ldap/kdb_xdr.c
new file mode 100644
index 000000000..1f0462967
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/kdb_xdr.c
@@ -0,0 +1,229 @@
+/*
+ * lib/kdb/kdb_ldap/kdb_xdr.c
+ *
+ * Copyright 1995 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. 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>
+#include "kdb_xdr.h"
+
+#define safe_realloc(p,n) ((p)?(realloc(p,n)):(malloc(n)))
+
+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;
+ krb5_octet * tmp;
+
+ /* copy the new data first, so we can fail cleanly if malloc()
+ fails */
+
+ if ((tmp = (krb5_octet *) malloc(new_tl_data->tl_data_length)) == NULL)
+ return(ENOMEM);
+
+ /* Find an existing entry of the specified type and point at
+ it, or NULL if not found */
+
+ for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next)
+ if (tl_data->tl_data_type == new_tl_data->tl_data_type)
+ break;
+
+ /* if necessary, chain a new record in the beginning and point at it */
+
+ if (!tl_data) {
+ if ((tl_data = (krb5_tl_data *) calloc(1, sizeof(krb5_tl_data)))
+ == NULL) {
+ free(tmp);
+ return(ENOMEM);
+ }
+ tl_data->tl_data_next = entry->tl_data;
+ entry->tl_data = tl_data;
+ entry->n_tl_data++;
+ }
+
+ /* fill in the record */
+
+ if (tl_data->tl_data_contents)
+ free(tl_data->tl_data_contents);
+
+ tl_data->tl_data_type = new_tl_data->tl_data_type;
+ tl_data->tl_data_length = new_tl_data->tl_data_length;
+ tl_data->tl_data_contents = tmp;
+ memcpy(tmp, new_tl_data->tl_data_contents, tl_data->tl_data_length);
+
+ return(0);
+}
+
+krb5_error_code
+krb5_dbe_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_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_lookup_last_pwd_change(context, entry, stamp)
+ krb5_context context;
+ krb5_db_entry * entry;
+ krb5_timestamp * stamp;
+{
+ krb5_tl_data tl_data;
+ krb5_error_code code;
+ krb5_int32 tmp;
+
+ tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
+
+ if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data)))
+ return(code);
+
+ if (tl_data.tl_data_length != 4) {
+ *stamp = 0;
+ return(0);
+ }
+
+ krb5_kdb_decode_int32(tl_data.tl_data_contents, tmp);
+
+ *stamp = (krb5_timestamp) tmp;
+
+ return(0);
+}
+
+/* it seems odd that there's no function to remove a tl_data, but if
+ I need one, I'll add one */
+
+krb5_error_code
+krb5_dbe_update_mod_princ_data(context, entry, mod_date, mod_princ)
+ krb5_context context;
+ krb5_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);
+}
+
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/kdb_xdr.h b/src/plugins/kdb/ldap/libkdb_ldap/kdb_xdr.h
new file mode 100644
index 000000000..bd01ead27
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/kdb_xdr.h
@@ -0,0 +1,34 @@
+#ifndef _KDB2_XDR_H
+#define _KDB2_XDR_H
+
+#include "kdb.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/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif b/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif
new file mode 100644
index 000000000..258eeaba8
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif
@@ -0,0 +1,888 @@
+# Novell Kerberos Schema Definitions
+# Novell Inc.
+# 1800 South Novell Place
+# Provo, UT 84606
+#
+# VeRsIoN=1.3
+# CoPyRiGhT=(c) Copyright 2005, Novell, Inc. All rights reserved
+#
+# OIDs:
+# joint-iso-ccitt(2)
+# country(16)
+# us(840)
+# organization(1)
+# Novell(113719)
+# applications(1)
+# kerberos(301)
+# Kerberos Attribute Type(4)
+# specific attribute definitions
+# Kerberos Attribute Syntax(5)
+# specific syntax definitions
+# Kerberos Object Class(6)
+# specific class definitions
+# Kerberos LDAP Extensions (100)
+# specific extensions
+
+########################################################################
+# Revision History #
+########################################################################
+#
+# 1.0 - 04/2004
+#
+# - First version
+#
+# 1.1 - 01/2005
+#
+# - Added 3 new attributes:
+# krbContainerReference
+# krbPrincNamingAttr
+# krbAdmServers
+#
+# - Added 2 new classes:
+# krbContainerRefAux
+# krbAdmService
+#
+# - Removed 2 attributes:
+# krbLogFile (2.16.840.1.113719.1.301.4.12)
+# krbReplayCacheFile (2.16.840.1.113719.1.301.4.13)
+#
+# - Added 'organization', 'organizationalUnit', 'country',
+# 'locality' and 'domain' to the containment list for
+# "krbContainer". Earlier, it had only 'SASSecurity'.
+#
+# - Removed the optional attributes "krbLogFile" and
+# "krbReplayCacheFile" from "krbService" class.
+#
+# - Added "krbAdmServers" and "krbPrincNamingAttr" as
+# optional attributes to "krbRealmContainer" class.
+#
+# - Removed the flag "X-NDS_NOT_SCHED_SYNC_IMMEDIATE" for
+# "krbPrincipalExpiration"
+#
+# - Removed the flags "X-NDS_NOT_SCHED_SYNC_IMMEDIATE" and
+# "X-NDS_PUBLIC_READ" for "krbTicketFlags"
+#
+# - Removed the flag "X-NDS_PUBLIC_READ" for "krbServiceFlags"
+#
+# - Modified the comments for:
+# krbPrincipalType
+# krbSecretKey
+# krbUPEnabled
+# krbRealmReferences
+# krbSubTree
+# krbKdcServers
+# krbPwdServers
+# krbSupportedEncTypes
+# krbSupportedSaltTypes
+# krbMasterKey
+# krbHostServer
+# krbSearchScope
+# krbService
+# krbPolicyAux
+# krbTicketFlags
+# krbServiceFlags
+#
+# 1.2 - 04/2005
+#
+# - Removed the flag "X-NDS_PUBLIC_READ" for:
+# krbMaxTicketLife
+# krbMaxRenewableAge
+# krbRealmReferences
+# krbLdapServers
+# krbKdcServers
+# krbPwdServers
+# krbSupportedEncTypes
+# krbSupportedSaltTypes
+# krbDefaultEncType
+# krbDefaultSaltType
+# krbHostServer
+# krbContainerReference
+# krbAdmServers
+#
+# - Changed the syntax for "krbLdapServers" from
+# 1.3.6.1.4.1.1466.115.121.1.12 (Distinguished Name) to
+# 1.3.6.1.4.1.1466.115.121.1.15 (Case Ignore String)
+#
+# 1.3 - 04/2005
+#
+# - Added 6 new attributes:
+# krbMaxPwdLife
+# krbMinPwdLife
+# krbPwdMinDiffChars
+# krbPwdMinLength
+# krbPwdHistoryLength
+# krbPwdPolicyRefCount
+# krbPwdPolicyReference
+#
+# - Added 2 new classes:
+# krbPwdPolicy
+# krbPwdPolicyRefAux
+########################################################################
+
+
+########################################################################
+# Attribute Type Definitions #
+########################################################################
+
+##### This is the principal name in the RFC 1510 specified format
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.1
+ NAME 'krbPrincipalName'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### This is the foreign principal name in the RFC 1510 specified format
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.2
+ NAME 'krbForeignPrincipalName'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### This specifies the type of the principal, the types could be any of
+##### the following, (refer RFC 1510)
+##### NT_UNKNOWN 0
+##### NT_PRINCIPAL 1
+##### NT_SRV_INST 2
+##### NT_SRV_HST 3
+##### NT_SRV_XHST 4
+##### NT_UID 5
+##### The following is a special principal type as explained,
+##### This is used for X.500 principal names, coded as a Base-64 encoding of the
+##### ASN.1 representation of the distinguished X.500 name. This Base-64 encoding
+##### should be the first element of the principal name (that has only one element)
+##### This constant corresponds to the NT-X500-PRINCIPAL principal type that is
+##### specified in the latest PK INIT IETF draft.
+##### X500_PRINCIPAL 6
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.3
+ NAME 'krbPrincipalType'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### This attribute holds the principal's secret key that is encrypted with
+##### the master key.
+##### The attribute holds data as follows,
+##### First 2 bytes Length of principal name (princNameLength)
+##### Next 2 bytes Current version of the principal key
+##### Next 2 bytes Version of the master key used to encrypt this principal key
+##### Next 4 bytes Time when password was last chaged
+##### Next 2 bytes Number of keys for the principal (noOfKeys)
+##### Next 2 bytes Key type of the first key
+##### Next 2 bytes Length of the first key (keyLength[1])
+##### Next 2 bytes Salt type of the first key
+##### Next 2 bytes Salt Length of the first key (saltLength[1])
+##### ... ... (other principals...)
+##### Next 2 bytes Key type of the last key (There will be "noOfKeys" keys)
+##### Next 2 bytes Length of the last key (keyLength[noOfKeys])
+##### Next 2 bytes Salt type of the last key (There will be "noOfKeys" keys)
+##### Next 2 bytes Salt Length of the last key (saltLength[noOfKeys])
+##### Principal name (of princNameLength)
+##### Principal's first key (of keyLength[1])
+##### Principal's first salt (of saltLength[1])
+##### ... ... (other principals...)
+##### Principal's last key (of keyLength[noOfKeys])
+##### Principal's last salt (saltLength[noOfKeys])
+##### The byte encoding is in the big endian format.
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.4
+ NAME 'krbSecretKey'
+ EQUALITY octetStringMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40)
+
+
+##### This flag is used to find whether Universal Password is to be used
+##### as kerberos password.
+##### TRUE, if UP is to be used as the kerberos password.
+##### FALSE, if UP and the kerberos password are different.
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.5
+ NAME 'krbUPEnabled'
+ DESC 'Boolean'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
+ SINGLE-VALUE
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### The time at which the principal expires
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.6
+ NAME 'krbPrincipalExpiration'
+ EQUALITY generalizedTimeMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+ SINGLE-VALUE)
+
+
+##### FDN pointing to a Kerberos Policy object
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.7
+ NAME 'krbPolicyReference'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ SINGLE-VALUE
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### The krbTicketFlags attribute holds information about the kerberos flags for a principal
+##### The flags as per RFC 1510 are,
+##### DISALLOW_POSTDATED 0x00000001
+##### DISALLOW_FORWARDABLE 0x00000002
+##### DISALLOW_TGT_BASED 0x00000004
+##### DISALLOW_RENEWABLE 0x00000008
+##### DISALLOW_PROXIABLE 0x00000010
+##### DISALLOW_DUP_SKEY 0x00000020
+##### DISALLOW_ALL_TIX 0x00000040
+##### REQUIRES_PRE_AUTH 0x00000080
+##### REQUIRES_HW_AUTH 0x00000100
+##### REQUIRES_PWCHANGE 0x00000200
+##### DISALLOW_SVR 0x00001000
+##### PWCHANGE_SERVICE 0x00002000
+
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.8
+ NAME 'krbTicketFlags'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE)
+
+
+##### The maximum ticket lifetime for a principal in seconds
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.9
+ NAME 'krbMaxTicketLife'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### Maximum renewable lifetime for a principal's ticket in seconds
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.10
+ NAME 'krbMaxRenewableAge'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### This is a set of flags that a Kerberos server requires to enable/disable
+##### support of certain features.
+##### The flags are as follows,
+##### AUTO_RESTART (1 << 0)
+##### CHECK_ADDRESSES (1 << 1)
+##### SUPPORT_V4 (1 << 2)
+##### USE_PRI_PORT (1 << 3)
+##### USE_SEC_PORT (1 << 4)
+##### USE_TCP (1 << 5)
+##### UNIXTIME_OLD_PATYPE (1 << 6)
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.11
+ NAME 'krbServiceFlags'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### Forward reference to the Realm object.
+##### (FDN of the krbRealmContainer object).
+##### Example: cn=ACME.COM, cn=Kerberos, cn=Security
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.14
+ NAME 'krbRealmReferences'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### List of LDAP servers that kerberos servers can contact.
+##### The attribute holds data in the following format,
+##### HostName-or-IPAddress#Port
+##### Where, "#" is a delimiter.
+##### Examples: acme.com#636, 164.164.164.164#1636
+#####
+##### The values of this attribute need to be updated, when
+##### the LDAP servers listed here are renamed, moved or deleted.
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.15
+ NAME 'krbLdapServers'
+ EQUALITY caseIgnoreIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### Forward reference to an entry that starts a sub-tree
+##### where principals and other kerberos objects in the realm are configured.
+##### Example: ou=acme, ou=pq, o=xyz
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.16
+ NAME 'krbSubTree'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ SINGLE-VALUE
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### A set of forward references to the KDC Service objects.
+##### (FDNs of the krbKdcService objects).
+##### Example: cn=kdc - server 1, ou=uvw, o=xyz
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.17
+ NAME 'krbKdcServers'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### A set of forward references to the Password Service objects.
+##### (FDNs of the krbPwdService objects).
+##### Example: cn=kpasswdd - server 1, ou=uvw, o=xyz
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.18
+ NAME 'krbPwdServers'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### List of encryption types supported by the Realm.
+##### The supported encryption types are,
+##### DES_CBC_CRC 0x0001
+##### DES_CBC_MD4 0x0002
+##### DES_CBC_MD5 0x0003
+##### DES_CBC_RAW 0x0004
+##### DES3_CBC_SHA 0x0005
+##### DES3_CBC_RAW 0x0006
+##### DES_HMAC_SHA1 0x0008
+##### DES3_CBC_SHA1 0x0010
+##### AES128_CTS_HMAC_SHA1_96 0x0011
+##### AES256_CTS_HMAC_SHA1_96 0x0012
+##### ARCFOUR_HMAC 0x0017
+##### ARCFOUR_HMAC_EXP 0x0018
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.19
+ NAME 'krbSupportedEncTypes'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### List of salt types supported by the Realm.
+##### The supported salt types are,
+##### NORMAL 0
+##### V4 1
+##### NOREALM 2
+##### ONLYREALM 3
+##### SPECIAL 4
+##### AFS3 5
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.20
+ NAME 'krbSupportedSaltTypes'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### Default encryption type supported by the Realm.
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.21
+ NAME 'krbDefaultEncType'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### Default salt type supported by the Realm.
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.22
+ NAME 'krbDefaultSaltType'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### This attribute holds the kerberos master key.
+##### The encryption type used for generating the key will be the strongest available with NICI.
+##### This attribute will be encrypted with Tree Key and stored.
+##### The attribute holds data as follows,
+##### First 2 bytes holds the version of the master key,
+##### Next 2 bytes holds the encryption type,
+##### Next 4 bytes holds the key length,
+##### Followed by the key.
+##### The byte encoding is in the big endian format.
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.23
+ NAME 'krbMasterKey'
+ EQUALITY octetStringMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40)
+
+
+##### This attribute holds the Host Name or the ip address,
+##### transport protocol and ports of the kerberos service host
+##### The format is host_name-or-ip_address#protocol#port
+##### Protocol can be 0 or 1. 0 is for UDP. 1 is for TCP.
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.24
+ NAME 'krbHostServer'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### This attribute holds the scope for searching the principals
+##### under krbSubTree attribute of krbRealmContainer
+##### The value can either be 1 (ONE) or 2 (SUB_TREE).
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.25
+ NAME 'krbSearchScope'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### FDNs pointing to Kerberos Service principals
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.26
+ NAME 'krbPrincipalReferences'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12)
+
+
+##### FDN pointing to the Kerberos container in the tree
+##### If this attribute is not present, then the default
+##### value is cn=Kerberos,cn=Security
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.27
+ NAME 'krbContainerReference'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ SINGLE-VALUE
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### This attribute specifies which attribute of the user objects
+##### be used as the principal name component for Kerberos.
+##### The allowed values are cn, sn, uid, givenname, fullname.
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.28
+ NAME 'krbPrincNamingAttr'
+ DESC 'String'
+ EQUALITY caseIgnoreIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+ SINGLE-VALUE
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### A set of forward references to the Administration Service objects.
+##### (FDNs of the krbAdmService objects).
+##### Example: cn=kadmindd - server 1, ou=uvw, o=xyz
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.29
+ NAME 'krbAdmServers'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### Maximum lifetime of a principal's password
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.30
+ NAME 'krbMaxPwdLife'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### Minimum lifetime of a principal's password
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.31
+ NAME 'krbMinPwdLife'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### Minimum number of character clases allowed in a password
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.32
+ NAME 'krbPwdMinDiffChars'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### Minimum length of the password
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.33
+ NAME 'krbPwdMinLength'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### Number of previous versions of passwords that are stored
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.34
+ NAME 'krbPwdHistoryLength'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### Number of principals that refer to this policy
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.35
+ NAME 'krbPwdPolicyRefCount'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### FDN pointing to a Kerberos Password Policy object
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.36
+ NAME 'krbPwdPolicyReference'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ SINGLE-VALUE
+ X-NDS_NOT_SCHED_SYNC_IMMEDIATE '1')
+
+
+##### The time at which the principal's password expires
+
+dn: cn=schema
+changetype: modify
+add: attributetypes
+attributetypes: ( 2.16.840.1.113719.1.301.4.37
+ NAME 'krbPasswordExpiration'
+ EQUALITY generalizedTimeMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+ SINGLE-VALUE)
+
+
+########################################################################
+# Object Class Definitions #
+########################################################################
+
+#### This is a kerberos container for all the realms in a tree.
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.1
+ NAME 'krbContainer'
+ SUP top
+ MUST ( cn )
+ MAY ( krbPolicyReference)
+ X-NDS_NAMING ( 'cn' )
+ X-NDS_CONTAINMENT ( 'SASSecurity' 'organization' 'organizationalUnit' 'country' 'locality' 'domain' ))
+
+
+##### The krbRealmContainer is created per realm and holds realm specific data.
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.2
+ NAME 'krbRealmContainer'
+ SUP top
+ MUST ( cn )
+ MAY ( krbMasterKey $ krbUPEnabled $ krbSubTree $ krbSearchScope $ krbLdapServers $ krbSupportedEncTypes $ krbSupportedSaltTypes $ krbDefaultEncType $ krbDefaultSaltType $ krbPolicyReference $ krbKdcServers $ krbPwdServers $ krbAdmServers $ krbPrincNamingAttr )
+ X-NDS_NAMING ( 'cn' )
+ X-NDS_CONTAINMENT ( 'krbContainer' ))
+
+
+##### An instance of a class derived from krbService is created per
+##### kerberos authentication or administration server in an realm and holds
+##### references to the realm objects. These references is used to further read
+##### realm specific data to service AS/TGS requests. Additionally this object
+##### contains some server specific data like pathnames and ports that the
+##### server uses. This is the identity the kerberos server logs in with. A key
+##### pair for the same is created and the kerberos server logs in with the same.
+#####
+##### krbKdcService, krbAdmService and krbPwdService derive from this class.
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.3
+ NAME 'krbService'
+ ABSTRACT
+ SUP ( top $ Server $ ndsLoginProperties )
+ MUST ( cn )
+ MAY ( krbHostServer $ krbServiceFlags $ krbRealmReferences )
+ X-NDS_NAMING 'cn'
+ X-NDS_CONTAINMENT ( 'organization' 'organizationalUnit' 'country' 'locality' 'domain' 'krbRealmContainer' )
+ X-NDS_NOT_CONTAINER '1')
+
+
+##### Representative object for the KDC server to log onto eDirectory
+##### and have a connection Id to access Kerberos data and have the required ACL's
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.4
+ NAME 'krbKdcService'
+ SUP ( krbService )
+ X-NDS_NOT_CONTAINER '1')
+
+
+##### Representative object for the Kerberos Password server to log into eDirectory
+##### and have a connection Id to access Kerberos data and have the required ACL's
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.5
+ NAME 'krbPwdService'
+ SUP ( krbService )
+ X-NDS_NOT_CONTAINER '1')
+
+
+##### The krbPolicyAux holds Kerberos ticket policy attributes.
+##### This class can be attached to a principal object or realm object.
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.6
+ NAME 'krbPolicyAux'
+ AUXILIARY
+ MAY ( krbTicketFlags $ krbMaxTicketLife $ krbMaxRenewableAge ))
+
+
+##### The krbPolicy object is an effective policy that is associated with a realm or a principal
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.7
+ NAME 'krbPolicy'
+ SUP top
+ MUST ( cn )
+ X-NDS_NAMING 'cn'
+ X-NDS_CONTAINMENT ( 'organization' 'organizationalUnit' 'domain' 'country' 'locality' )
+ X-NDS_NOT_CONTAINER '1')
+
+###### The principal data auxiliary class. Holds principal information
+###### and is used to store principal information for Users and any services.
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.8
+ NAME 'krbPrincipalAux'
+ AUXILIARY
+ MAY ( krbPrincipalName $ krbUPEnabled $ krbSecretKey $ krbPolicyReference $ krbPrincipalExpiration $ krbPasswordExpiration ) )
+
+
+###### This object is created to hold principals of type other than USER.
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.9
+ NAME 'krbPrincipal'
+ SUP ( top )
+ MUST ( krbPrincipalName )
+ MAY ( krbPrincipalType )
+ X-NDS_NAMING 'krbPrincipalName'
+ X-NDS_CONTAINMENT ( 'organization' 'organizationalUnit' 'domain' 'krbRealmContainer' 'country' 'locality' )
+ X-NDS_NOT_CONTAINER '1')
+
+
+###### The foreign principal data auxiliary class. Holds all foreign principal information
+###### and is used to store foreign principal information for Users.
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.10
+ NAME 'krbForeignPrincipalAux'
+ AUXILIARY
+ MAY krbForeignPrincipalName )
+
+###### The principal references auxiliary class. Holds all principals referred
+###### from a service
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.11
+ NAME 'krbPrincRefAux'
+ AUXILIARY
+ MAY krbPrincipalReferences )
+
+
+###### Kerberos container references auxiliary class. Holds the location
+###### of the Kerberos container object within an eDirectory tree.
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.12
+ NAME 'krbContainerRefAux'
+ AUXILIARY
+ MAY krbContainerReference )
+
+
+##### Representative object for the Kerberos Administration server to log into eDirectory
+##### and have a connection Id to access Kerberos data and have the required ACL's
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.13
+ NAME 'krbAdmService'
+ SUP ( krbService )
+ X-NDS_NOT_CONTAINER '1')
+
+
+##### The krbPwdPolicy object is a template password policy that
+##### can be applied to principals when they are created.
+##### These policy attributes will be in effect, when the Kerberos
+##### passwords are different from users' passwords (UP).
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.14
+ NAME 'krbPwdPolicy'
+ SUP top
+ MUST ( cn )
+ X-NDS_NAMING 'cn'
+ X-NDS_CONTAINMENT ( 'organization' 'organizationalUnit' 'domain' 'country' 'locality' )
+ MAY ( krbMaxPwdLife $ krbMinPwdLife $ krbPwdMinDiffChars $ krbPwdMinLength $ krbPwdHistoryLength $ krbPwdPolicyRefCount)
+ X-NDS_NOT_CONTAINER '1')
+
+
+###### The password policy reference auxiliary class.
+###### Holds the DN of the password policy object. This is to be attached to principals.
+
+dn: cn=schema
+changetype: modify
+add: objectclasses
+objectClasses: ( 2.16.840.1.113719.1.301.6.15
+ NAME 'krbPwdPolicyRefAux'
+ AUXILIARY
+ MAY ( krbPwdPolicyReference ) )
+
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema b/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema
new file mode 100644
index 000000000..4f3a0fb9d
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema
@@ -0,0 +1,695 @@
+# Novell Kerberos Schema Definitions
+# Novell Inc.
+# 1800 South Novell Place
+# Provo, UT 84606
+#
+# VeRsIoN=1.3
+# CoPyRiGhT=(c) Copyright 2005, Novell, Inc. All rights reserved
+#
+# OIDs:
+# joint-iso-ccitt(2)
+# country(16)
+# us(840)
+# organization(1)
+# Novell(113719)
+# applications(1)
+# kerberos(301)
+# Kerberos Attribute Type(4)
+# specific attribute definitions
+# Kerberos Attribute Syntax(5)
+# specific syntax definitions
+# Kerberos Object Class(6)
+# specific class definitions
+# Kerberos LDAP Extensions (100)
+# specific extensions
+
+########################################################################
+# Attribute Type Definitions #
+########################################################################
+
+##### This is the principal name in the RFC 1510 specified format
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.1
+ NAME 'krbPrincipalName'
+ EQUALITY caseExactIA5Match
+ SUBSTR caseExactSubstringsMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+ )
+
+##### This is the foreign principal name in the RFC 1510 specified format
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.2
+ NAME 'krbForeignPrincipalName'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+ )
+
+
+##### This specifies the type of the principal, the types could be any of
+##### the following, (refer RFC 1510)
+##### NT_UNKNOWN 0
+##### NT_PRINCIPAL 1
+##### NT_SRV_INST 2
+##### NT_SRV_HST 3
+##### NT_SRV_XHST 4
+##### NT_UID 5
+##### The following is a special principal type as explained,
+##### This is used for X.500 principal names, coded as a Base-64 encoding of the
+##### ASN.1 representation of the distinguished X.500 name. This Base-64 encoding
+##### should be the first element of the principal name (that has only one element)
+##### This constant corresponds to the NT-X500-PRINCIPAL principal type that is
+##### specified in the latest PK INIT IETF draft.
+##### X500_PRINCIPAL 6
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.3
+ NAME 'krbPrincipalType'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ )
+
+
+##### This attribute holds the principal's secret key that is encrypted with
+##### the master key.
+##### The attribute holds data as follows,
+##### First 2 bytes Length of principal name (princNameLength)
+##### Next 2 bytes Current version of the principal key
+##### Next 2 bytes Version of the master key used to encrypt this principal key
+##### Next 4 bytes Time when password was last chaged
+##### Next 2 bytes Number of keys for the principal (noOfKeys)
+##### Next 2 bytes Key type of the first key
+##### Next 2 bytes Length of the first key (keyLength[1])
+##### Next 2 bytes Salt type of the first key
+##### Next 2 bytes Salt Length of the first key (saltLength[1])
+##### ... ... (other principals...)
+##### Next 2 bytes Key type of the last key (There will be "noOfKeys" keys)
+##### Next 2 bytes Length of the last key (keyLength[noOfKeys])
+##### Next 2 bytes Salt type of the last key (There will be "noOfKeys" keys)
+##### Next 2 bytes Salt Length of the last key (saltLength[noOfKeys])
+##### Principal name (of princNameLength)
+##### Principal's first key (of keyLength[1])
+##### Principal's first salt (of saltLength[1])
+##### ... ... (other principals...)
+##### Principal's last key (of keyLength[noOfKeys])
+##### Principal's last salt (saltLength[noOfKeys])
+##### The byte encoding is in the big endian format.
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.4
+ NAME 'krbSecretKey'
+ EQUALITY octetStringMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
+ )
+
+
+##### This flag is used to find whether Universal Password is to be used
+##### as kerberos password.
+##### TRUE, if UP is to be used as the kerberos password.
+##### FALSE, if UP and the kerberos password are different.
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.5
+ NAME 'krbUPEnabled'
+ DESC 'Boolean'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
+ SINGLE-VALUE
+ )
+
+
+##### The time at which the principal expires
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.6
+ NAME 'krbPrincipalExpiration'
+ EQUALITY generalizedTimeMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+ SINGLE-VALUE
+ )
+
+
+##### FDN pointing to a Kerberos Policy object
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.7
+ NAME 'krbPolicyReference'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ SINGLE-VALUE
+ )
+
+##### The time at which the principal's password expires
+# should be moved to the end of the attributes' list
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.37
+ NAME 'krbPasswordExpiration'
+ EQUALITY generalizedTimeMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+ SINGLE-VALUE
+ )
+
+##### The krbTicketFlags attribute holds information about the kerberos flags for a principal
+##### The flags as per RFC 1510 are,
+##### DISALLOW_POSTDATED 0x00000001
+##### DISALLOW_FORWARDABLE 0x00000002
+##### DISALLOW_TGT_BASED 0x00000004
+##### DISALLOW_RENEWABLE 0x00000008
+##### DISALLOW_PROXIABLE 0x00000010
+##### DISALLOW_DUP_SKEY 0x00000020
+##### DISALLOW_ALL_TIX 0x00000040
+##### REQUIRES_PRE_AUTH 0x00000080
+##### REQUIRES_HW_AUTH 0x00000100
+##### REQUIRES_PWCHANGE 0x00000200
+##### DISALLOW_SVR 0x00001000
+##### PWCHANGE_SERVICE 0x00002000
+
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.8
+ NAME 'krbTicketFlags'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ )
+
+
+##### The maximum ticket lifetime for a principal in seconds
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.9
+ NAME 'krbMaxTicketLife'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ )
+
+
+##### Maximum renewable lifetime for a principal's ticket in seconds
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.10
+ NAME 'krbMaxRenewableAge'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ )
+
+
+##### This is a set of flags that a Kerberos server requires to enable/disable
+##### support of certain features.
+##### The flags are as follows,
+##### AUTO_RESTART (1 << 0)
+##### CHECK_ADDRESSES (1 << 1)
+##### SUPPORT_V4 (1 << 2)
+##### USE_PRI_PORT (1 << 3)
+##### USE_SEC_PORT (1 << 4)
+##### USE_TCP (1 << 5)
+##### UNIXTIME_OLD_PATYPE (1 << 6)
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.11
+ NAME 'krbServiceFlags'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ )
+
+
+##### Forward reference to the Realm object.
+##### (FDN of the krbRealmContainer object).
+##### Example: cn=ACME.COM, cn=Kerberos, cn=Security
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.14
+ NAME 'krbRealmReferences'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ )
+
+
+##### List of LDAP servers that kerberos servers can contact.
+##### The attribute holds data in the following format,
+##### HostName-or-IPAddress#Port
+##### Where, "#" is a delimiter.
+##### Examples: acme.com#636, 164.164.164.164#1636
+#####
+##### The values of this attribute need to be updated, when
+##### the LDAP servers listed here are renamed, moved or deleted.
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.15
+ NAME 'krbLdapServers'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+ )
+
+
+##### Forward reference to an entry that starts a sub-tree
+##### where principals and other kerberos objects in the realm are configured.
+##### Example: ou=acme, ou=pq, o=xyz
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.16
+ NAME 'krbSubTree'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ SINGLE-VALUE
+ )
+
+
+##### A set of forward references to the KDC Service objects.
+##### (FDNs of the krbKdcService objects).
+##### Example: cn=kdc - server 1, ou=uvw, o=xyz
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.17
+ NAME 'krbKdcServers'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ )
+
+
+##### A set of forward references to the Password Service objects.
+##### (FDNs of the krbPwdService objects).
+##### Example: cn=kpasswdd - server 1, ou=uvw, o=xyz
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.18
+ NAME 'krbPwdServers'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ )
+
+
+##### List of encryption types supported by the Realm.
+##### The supported encryption types are,
+##### DES_CBC_CRC 0x0001
+##### DES_CBC_MD4 0x0002
+##### DES_CBC_MD5 0x0003
+##### DES_CBC_RAW 0x0004
+##### DES3_CBC_SHA 0x0005
+##### DES3_CBC_RAW 0x0006
+##### DES_HMAC_SHA1 0x0008
+##### DES3_CBC_SHA1 0x0010
+##### AES128_CTS_HMAC_SHA1_96 0x0011
+##### AES256_CTS_HMAC_SHA1_96 0x0012
+##### ARCFOUR_HMAC 0x0017
+##### ARCFOUR_HMAC_EXP 0x0018
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.19
+ NAME 'krbSupportedEncTypes'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ )
+
+
+##### List of salt types supported by the Realm.
+##### The supported salt types are,
+##### NORMAL 0
+##### V4 1
+##### NOREALM 2
+##### ONLYREALM 3
+##### SPECIAL 4
+##### AFS3 5
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.20
+ NAME 'krbSupportedSaltTypes'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ )
+
+
+##### Default encryption type supported by the Realm.
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.21
+ NAME 'krbDefaultEncType'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ )
+
+
+##### Default salt type supported by the Realm.
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.22
+ NAME 'krbDefaultSaltType'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ )
+
+
+##### This attribute holds the kerberos master key.
+##### The encryption type used for generating the key will be the strongest available with NICI.
+##### This attribute will be encrypted with Tree Key and stored.
+##### The attribute holds data as follows,
+##### First 2 bytes holds the version of the master key,
+##### Next 2 bytes holds the encryption type,
+##### Next 4 bytes holds the key length,
+##### Followed by the key.
+##### The byte encoding is in the big endian format.
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.23
+ NAME 'krbMasterKey'
+ EQUALITY octetStringMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
+ )
+
+
+##### This attribute holds the Host Name or the ip address,
+##### transport protocol and ports of the kerberos service host
+##### The format is host_name-or-ip_address#protocol#port
+##### Protocol can be 0 or 1. 0 is for UDP. 1 is for TCP.
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.24
+ NAME 'krbHostServer'
+ EQUALITY caseExactIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+ )
+
+
+##### This attribute holds the scope for searching the principals
+##### under krbSubTree attribute of krbRealmContainer
+##### The value can either be 1 (ONE) or 2 (SUB_TREE).
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.25
+ NAME 'krbSearchScope'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ )
+
+
+##### FDNs pointing to Kerberos Service principals
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.26
+ NAME 'krbPrincipalReferences'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ )
+
+
+##### FDN pointing to the Kerberos container in the tree
+##### If this attribute is not present, then the default
+##### value is cn=Kerberos,cn=Security
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.27
+ NAME 'krbContainerReference'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ SINGLE-VALUE
+ )
+
+
+##### This attribute specifies which attribute of the user objects
+##### be used as the principal name component for Kerberos.
+##### The allowed values are cn, sn, uid, givenname, fullname.
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.28
+ NAME 'krbPrincNamingAttr'
+ DESC 'String'
+ EQUALITY caseIgnoreMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+ SINGLE-VALUE
+ )
+
+
+##### A set of forward references to the Administration Service objects.
+##### (FDNs of the krbAdmService objects).
+##### Example: cn=kadmindd - server 1, ou=uvw, o=xyz
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.29
+ NAME 'krbAdmServers'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ )
+
+
+##### Maximum lifetime of a principal's password
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.30
+ NAME 'krbMaxPwdLife'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ )
+
+
+##### Minimum lifetime of a principal's password
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.31
+ NAME 'krbMinPwdLife'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ )
+
+
+##### Minimum number of character clases allowed in a password
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.32
+ NAME 'krbPwdMinDiffChars'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ )
+
+
+##### Minimum length of the password
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.33
+ NAME 'krbPwdMinLength'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ )
+
+
+##### Number of previous versions of passwords that are stored
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.34
+ NAME 'krbPwdHistoryLength'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ )
+
+
+##### Number of principals that refer to this policy
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.35
+ NAME 'krbPwdPolicyRefCount'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ )
+
+
+##### FDN pointing to a Kerberos Password Policy object
+
+attributetype (
+ 2.16.840.1.113719.1.301.4.36
+ NAME 'krbPwdPolicyReference'
+ EQUALITY distinguishedNameMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+ SINGLE-VALUE
+ )
+
+##### Ticket Policy Reference Count
+
+attributetype ( 2.16.840.1.113719.1.301.4.38
+ NAME 'krbPolicyRefCount'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+ SINGLE-VALUE
+ )
+
+########################################################################
+# Object Class Definitions #
+########################################################################
+
+#### This is a kerberos container for all the realms in a tree.
+
+objectClass (
+ 2.16.840.1.113719.1.301.6.1
+ NAME 'krbContainer'
+ SUP top
+ MUST ( cn )
+ MAY ( krbPolicyReference)
+ )
+
+##### The krbRealmContainer is created per realm and holds realm specific data.
+
+objectClass (
+ 2.16.840.1.113719.1.301.6.2
+ NAME 'krbRealmContainer'
+ SUP top
+ MUST ( cn )
+ MAY ( krbMasterKey $ krbUPEnabled $ krbSubTree $ krbSearchScope $ krbLdapServers $ krbSupportedEncTypes $ krbSupportedSaltTypes $ krbDefaultEncType $ krbDefaultSaltType $ krbPolicyReference $ krbKdcServers $ krbPwdServers $ krbAdmServers $ krbPrincNamingAttr )
+ )
+
+
+##### An instance of a class derived from krbService is created per
+##### kerberos authentication or administration server in an realm and holds
+##### references to the realm objects. These references is used to further read
+##### realm specific data to service AS/TGS requests. Additionally this object
+##### contains some server specific data like pathnames and ports that the
+##### server uses. This is the identity the kerberos server logs in with. A key
+##### pair for the same is created and the kerberos server logs in with the same.
+#####
+##### krbKdcService, krbAdmService and krbPwdService derive from this class.
+
+objectClass (
+ 2.16.840.1.113719.1.301.6.3
+ NAME 'krbService'
+ ABSTRACT
+ SUP ( top )
+ MUST ( cn )
+ MAY ( krbHostServer $ krbServiceFlags $ krbRealmReferences $ userPassword )
+ )
+
+##### Representative object for the KDC server to log onto eDirectory
+##### and have a connection Id to access Kerberos data and have the required ACL's
+
+objectClass (
+ 2.16.840.1.113719.1.301.6.4
+ NAME 'krbKdcService'
+ SUP ( krbService )
+ )
+
+
+##### Representative object for the Kerberos Password server to log into eDirectory
+##### and have a connection Id to access Kerberos data and have the required ACL's
+
+objectClass (
+ 2.16.840.1.113719.1.301.6.5
+ NAME 'krbPwdService'
+ SUP ( krbService )
+ )
+
+##### The krbPolicyAux holds Kerberos ticket policy attributes.
+##### This class can be attached to a principal object or realm object.
+
+objectClass (
+ 2.16.840.1.113719.1.301.6.6
+ NAME 'krbPolicyAux'
+ AUXILIARY
+ MAY ( krbTicketFlags $ krbMaxTicketLife $ krbMaxRenewableAge )
+ )
+
+
+##### The krbPolicy object is an effective policy that is associated with a realm or a principal
+
+objectClass (
+ 2.16.840.1.113719.1.301.6.7
+ NAME 'krbPolicy'
+ SUP top
+ MUST ( cn )
+ MAY ( krbPolicyRefCount )
+ )
+
+###### The principal data auxiliary class. Holds principal information
+###### and is used to store principal information for Users and any services.
+
+objectClass (
+ 2.16.840.1.113719.1.301.6.8
+ NAME 'krbPrincipalAux'
+ AUXILIARY
+ MAY ( krbPrincipalName $ krbUPEnabled $ krbSecretKey $ krbPolicyReference $ krbPrincipalExpiration $ krbPasswordExpiration )
+ )
+
+
+###### This object is created to hold principals of type other than USER.
+
+objectClass (
+ 2.16.840.1.113719.1.301.6.9
+ NAME 'krbPrincipal'
+ SUP ( top )
+ MUST ( krbPrincipalName )
+ MAY ( krbPrincipalType )
+ )
+
+###### The foreign principal data auxiliary class. Holds all foreign principal information
+###### and is used to store foreign principal information for Users.
+
+objectClass (
+ 2.16.840.1.113719.1.301.6.10
+ NAME 'krbForeignPrincipalAux'
+ AUXILIARY
+ MAY krbForeignPrincipalName
+ )
+
+###### The principal references auxiliary class. Holds all principals referred
+###### from a service
+
+objectClass (
+ 2.16.840.1.113719.1.301.6.11
+ NAME 'krbPrincRefAux'
+ AUXILIARY
+ MAY krbPrincipalReferences
+ )
+
+
+###### Kerberos container references auxiliary class. Holds the location
+###### of the Kerberos container object within an eDirectory tree.
+
+objectClass (
+ 2.16.840.1.113719.1.301.6.12
+ NAME 'krbContainerRefAux'
+ AUXILIARY
+ MAY krbContainerReference
+ )
+
+
+##### Representative object for the Kerberos Administration server to log into eDirectory
+##### and have a connection Id to access Kerberos data and have the required ACL's
+
+objectClass (
+ 2.16.840.1.113719.1.301.6.13
+ NAME 'krbAdmService'
+ SUP ( krbService )
+ )
+
+##### The krbPwdPolicy object is a template password policy that
+##### can be applied to principals when they are created.
+##### These policy attributes will be in effect, when the Kerberos
+##### passwords are different from users' passwords (UP).
+
+objectClass (
+ 2.16.840.1.113719.1.301.6.14
+ NAME 'krbPwdPolicy'
+ SUP top
+ MUST ( cn )
+ MAY ( krbMaxPwdLife $ krbMinPwdLife $ krbPwdMinDiffChars $ krbPwdMinLength $ krbPwdHistoryLength $ krbPwdPolicyRefCount)
+ )
+
+###### The password policy reference auxiliary class.
+###### Holds the DN of the password policy object. This is to be attached to principals.
+
+objectClass (
+ 2.16.840.1.113719.1.301.6.15
+ NAME 'krbPwdPolicyRefAux'
+ AUXILIARY
+ MAY ( krbPwdPolicyReference )
+ )
+
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.c
new file mode 100644
index 000000000..e10c5dbf0
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.c
@@ -0,0 +1,168 @@
+#include <ldap.h>
+#include <errno.h>
+#include <kdb5_err.h>
+#include "ldap_err.h"
+#ifndef LDAP_X_ERROR
+#define LDAP_X_ERROR(x) (0)
+#endif
+
+
+/*
+ * The possible KDB errors are
+ * 1. KRB5_KDB_UK_RERROR
+ * 2. KRB5_KDB_UK_SERROR
+ * 3. KRB5_KDB_NOENTRY
+ * 4. KRB5_KDB_TRUNCATED_RECORD
+ * 5. KRB5_KDB_UNAUTH
+ * 6. KRB5_KDB_DB_CORRUPT
+ * 7. KRB5_KDB_ACCESS_ERROR (NEW)
+ * 8. KRB5_KDB_INTERNAL_ERROR (NEW)
+ * 9. KRB5_KDB_SERVER_INTERNAL_ERR (NEW)
+ * 10. KRB5_KDB_CONSTRAINT_VIOLATION (NEW)
+ *
+ */
+
+/*
+ * op :
+ * 0 => not specified
+ * OP_INIT => ldap_init
+ * OP_BIND => ldap_bind
+ * OP_UNBIND => ldap_unbind
+ * OP_ADD => ldap_add
+ * OP_MOD => ldap_modify
+ * OP_DEL => ldap_delete
+ * OP_SEARCH => ldap_search
+ * OP_CMP => ldap_compare
+ * OP_ABANDON => ldap_abandon
+ */
+
+int translate_ldap_error(int err, int op){
+
+ switch (err) {
+ case LDAP_SUCCESS:
+ return 0;
+
+ case LDAP_OPERATIONS_ERROR:
+ /* LDAP_OPERATIONS_ERROR: Indicates an internal error. The server is
+ * unable to respond with a more specific error and is also unable
+ * to properly respond to a request */
+ case LDAP_UNAVAILABLE_CRITICAL_EXTENSION:
+ /* LDAP server was unable to satisfy a request because one or more
+ * critical extensions were not available */
+ /* This might mean that the schema was not extended ... */
+ case LDAP_UNDEFINED_TYPE:
+ /* The attribute specified in the modify or add operation does not
+ * exist in the LDAP server's schema. */
+ return KRB5_KDB_INTERNAL_ERROR;
+
+
+ case LDAP_INAPPROPRIATE_MATCHING:
+ /* The matching rule specified in the search filter does not match a
+ * rule defined for the attribute's syntax */
+ return KRB5_KDB_UK_RERROR;
+
+ case LDAP_CONSTRAINT_VIOLATION:
+ /* The attribute value specified in a modify, add, or modify DN
+ * operation violates constraints placed on the attribute */
+ case LDAP_TYPE_OR_VALUE_EXISTS:
+ /* The attribute value specified in a modify or add operation
+ * already exists as a value for that attribute */
+ return KRB5_KDB_UK_SERROR;
+
+ case LDAP_INVALID_SYNTAX:
+ /* The attribute value specified in an add, compare, or modify
+ * operation is an unrecognized or invalid syntax for the attribute */
+ if (op == OP_ADD || op == OP_MOD)
+ return KRB5_KDB_UK_SERROR;
+ else /* OP_CMP */
+ return KRB5_KDB_UK_RERROR;
+
+ /* Ensure that the following don't occur in the DAL-LDAP code.
+ * Don't rely on the LDAP server to catch it */
+ case LDAP_SASL_BIND_IN_PROGRESS:
+ /* This is not an error. So, this function should not be called */
+ case LDAP_COMPARE_FALSE:
+ case LDAP_COMPARE_TRUE:
+ /* LDAP_COMPARE_FALSE and LDAP_COMPARE_TRUE are not errors. This
+ * function should not be invoked for them */
+ case LDAP_RESULTS_TOO_LARGE: /* CLDAP */
+ case LDAP_TIMELIMIT_EXCEEDED:
+ case LDAP_SIZELIMIT_EXCEEDED:
+ return KRB5_KDB_SERVER_INTERNAL_ERR;
+
+ case LDAP_INVALID_DN_SYNTAX:
+ /* The syntax of the DN is incorrect */
+ return EINVAL;
+
+ case LDAP_PROTOCOL_ERROR:
+ /* LDAP_PROTOCOL_ERROR: Indicates that the server has received an
+ * invalid or malformed request from the client */
+ case LDAP_CONFIDENTIALITY_REQUIRED:
+
+ /* Bind problems ... */
+ case LDAP_AUTH_METHOD_NOT_SUPPORTED:
+// case LDAP_STRONG_AUTH_NOT_SUPPORTED: // Is this a bind error ?
+ case LDAP_INAPPROPRIATE_AUTH:
+ case LDAP_INVALID_CREDENTIALS:
+ case LDAP_UNAVAILABLE:
+ return KRB5_KDB_ACCESS_ERROR;
+
+ case LDAP_STRONG_AUTH_REQUIRED:
+ if (op == OP_BIND) /* the LDAP server accepts only strong authentication. */
+ return KRB5_KDB_ACCESS_ERROR;
+ else /* Client requested an operation such that requires strong authentication */
+ return KRB5_KDB_CONSTRAINT_VIOLATION;
+
+ case LDAP_REFERRAL:
+ return KRB5_KDB_NOENTRY;
+
+ case LDAP_ADMINLIMIT_EXCEEDED:
+ /* An LDAP server limit set by an administrative authority has been
+ * exceeded */
+ return KRB5_KDB_CONSTRAINT_VIOLATION;
+ case LDAP_UNWILLING_TO_PERFORM:
+ /* The LDAP server cannot process the request because of
+ * server-defined restrictions */
+ return KRB5_KDB_CONSTRAINT_VIOLATION;
+
+
+ case LDAP_NO_SUCH_ATTRIBUTE:
+ /* Indicates that the attribute specified in the modify or compare
+ * operation does not exist in the entry */
+ if (op == OP_MOD)
+ return KRB5_KDB_UK_SERROR;
+ else /* OP_CMP */
+ return KRB5_KDB_TRUNCATED_RECORD;
+
+
+ case LDAP_ALIAS_DEREF_PROBLEM:
+ /* Either the client does not have access rights to read the aliased
+ * object's name or dereferencing is not allowed */
+ case LDAP_PROXY_AUTHZ_FAILURE: // Is this correct ?
+ case LDAP_INSUFFICIENT_ACCESS:
+ /* Caller does not have sufficient rights to perform the requested
+ * operation */
+ return KRB5_KDB_UNAUTH;
+
+ case LDAP_LOOP_DETECT:
+ /* Client discovered an alias or referral loop */
+ return KRB5_KDB_DB_CORRUPT;
+
+ default:
+
+ if (LDAP_NAME_ERROR (err))
+ return KRB5_KDB_NOENTRY;
+
+ if (LDAP_SECURITY_ERROR (err))
+ return KRB5_KDB_UNAUTH;
+
+ if (LDAP_SERVICE_ERROR (err) || LDAP_API_ERROR (err) || LDAP_X_ERROR (err))
+ return KRB5_KDB_ACCESS_ERROR;
+
+ if (LDAP_UPDATE_ERROR(err))
+ return KRB5_KDB_UK_SERROR;
+
+ /* LDAP_OTHER */
+ return KRB5_KDB_SERVER_INTERNAL_ERR;
+ }
+}
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.h b/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.h
new file mode 100644
index 000000000..f83e583dd
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.h
@@ -0,0 +1,12 @@
+#define OP_INIT 1
+#define OP_BIND 2
+#define OP_UNBIND 3
+#define OP_ADD 4
+#define OP_MOD 5
+#define OP_DEL 6
+#define OP_SEARCH 7
+#define OP_CMP 8
+#define OP_ABANDON 9
+
+
+int translate_ldap_error(int err, int op);
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_fetch_mkey.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_fetch_mkey.c
new file mode 100644
index 000000000..795358296
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_fetch_mkey.c
@@ -0,0 +1,100 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_fetch_mkey.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ldap_main.h"
+#include "kdb_ldap.h"
+
+/*
+ * get the master key from the database specific context
+ */
+
+krb5_error_code
+krb5_ldap_get_mkey (context, key)
+ krb5_context context;
+ krb5_keyblock **key;
+
+{
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+
+ /* Clear the global error string */
+ krb5_clear_error_message(context);
+
+ dal_handle = (kdb5_dal_handle *) context->db_context;
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+
+ if ( ldap_context == NULL || ldap_context->lrparams == NULL)
+ return KRB5_KDB_DBNOTINITED;
+
+ *key = &ldap_context->lrparams->mkey;
+ return 0;
+}
+
+
+/*
+ * set the master key into the database specific context
+ */
+
+krb5_error_code
+krb5_ldap_set_mkey (context, pwd, key)
+ krb5_context context;
+ char *pwd;
+ krb5_keyblock *key;
+{
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_realm_params *r_params = NULL;
+
+ /* Clear the global error string */
+ krb5_clear_error_message(context);
+
+ dal_handle = (kdb5_dal_handle *) context->db_context;
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+
+ if ( ldap_context == NULL || ldap_context->lrparams == NULL)
+ return KRB5_KDB_DBNOTINITED;
+
+ r_params = ldap_context->lrparams;
+
+ if (r_params->mkey.contents) {
+ free (r_params->mkey.contents);
+ r_params->mkey.contents=NULL;
+ }
+
+ r_params->mkey.magic = key->magic;
+ r_params->mkey.enctype = key->enctype;
+ r_params->mkey.length = key->length;
+ r_params->mkey.contents = malloc(key->length);
+ if (r_params->mkey.contents == NULL)
+ return ENOMEM;
+
+ memcpy(r_params->mkey.contents, key->contents, key->length);
+ return 0;
+}
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.c
new file mode 100644
index 000000000..4cc945f4a
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.c
@@ -0,0 +1,274 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_handle.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ldap_main.h"
+
+
+#ifdef ASYNC_BIND
+
+/*
+ * Update the server info structure. In case of an asynchronous bind,
+ * this function is called to check the bind status. A flag
+ * server_info_upate_pending is refered before calling this function.
+ * This function sets the server_status to either ON or OFF and
+ * sets the server_info_udpate_pending to OFF.
+ * Do not lock the mutex here. The caller should lock it
+ */
+
+static krb5_error_code
+krb5_update_server_info(ldap_server_handle, server_info)
+ krb5_ldap_server_handle *ldap_server_handle;
+ krb5_ldap_server_info *server_info;
+{
+ krb5_error_code st=0;
+ struct timeval ztime={0, 0};
+ LDAPMessage *result=NULL;
+
+ if (ldap_server_handle == NULL || server_info == NULL)
+ return -1;
+
+ while (st == 0) {
+ st = ldap_result(ldap_server_handle->ldap_handle, ldap_server_handle->msgid,
+ LDAP_MSG_ALL, &ztime, &result);
+ switch (st) {
+ case -1:
+ server_info->server_status = OFF;
+ time(&server_info->downtime);
+ break;
+
+ case 0:
+ continue;
+ break;
+
+ case LDAP_RES_BIND:
+ if ((st=ldap_result2error(ldap_server_handle->ldap_handle, result, 1)) == LDAP_SUCCESS) {
+ server_info->server_status = ON;
+ } else {
+/* ?? */ krb5_set_error_message(0, 0, "%s", ldap_err2string(st));
+ server_info->server_status = OFF;
+ time(&server_info->downtime);
+ }
+ ldap_msgfree(result);
+ break;
+ default:
+ ldap_msgfree(result);
+ continue;
+ break;
+ }
+ }
+ ldap_server_handle->server_info_update_pending = FALSE;
+ return 0;
+}
+#endif
+
+/*
+ * Return ldap server handle from the pool. If the pool is exhausted return NULL.
+ * Do not lock the mutex, caller should lock it
+ */
+
+static krb5_ldap_server_handle *
+krb5_get_ldap_handle(ldap_context)
+ krb5_ldap_context *ldap_context;
+{
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+ krb5_ldap_server_info *ldap_server_info=NULL;
+ int cnt=0;
+
+ while (ldap_context->server_info_list[cnt] != NULL) {
+ ldap_server_info = ldap_context->server_info_list[cnt];
+ if (ldap_server_info->server_status != OFF) {
+ if (ldap_server_info->ldap_server_handles != NULL) {
+ ldap_server_handle = ldap_server_info->ldap_server_handles;
+ ldap_server_info->ldap_server_handles = ldap_server_handle->next;
+ break;
+#ifdef ASYNC_BIND
+ if (ldap_server_handle->server_info_update_pending == TRUE) {
+ krb5_update_server_info(context, ldap_server_handle,
+ ldap_server_info);
+ }
+
+ if (ldap_server_info->server_status == ON) {
+ ldap_server_info->ldap_server_handles = ldap_server_handle->next;
+ break;
+ } else
+ ldap_server_handle = NULL;
+#endif
+ }
+ }
+ ++cnt;
+ }
+ return ldap_server_handle;
+}
+
+/*
+ * This is called incase krb5_get_ldap_handle returns NULL.
+ * Try getting a single connection (handle) and return the same by
+ * calling krb5_get_ldap_handle function.
+ * Do not lock the mutex here. The caller should lock it
+ */
+
+static krb5_ldap_server_handle *
+krb5_retry_get_ldap_handle(ldap_context, st)
+ krb5_ldap_context *ldap_context;
+ krb5_error_code *st;
+{
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+
+ if ((*st=krb5_ldap_db_single_init(ldap_context)) != 0)
+ return NULL;
+
+ ldap_server_handle = krb5_get_ldap_handle(ldap_context);
+ return ldap_server_handle;
+}
+
+/*
+ * Put back the ldap server handle to the front of the list of handles of the
+ * ldap server info structure.
+ * Do not lock the mutex here. The caller should lock it.
+ */
+
+static krb5_error_code
+krb5_put_ldap_handle(ldap_server_handle)
+ krb5_ldap_server_handle *ldap_server_handle;
+{
+
+ if (ldap_server_handle == NULL)
+ return 0;
+
+ ldap_server_handle->next = ldap_server_handle->server_info->ldap_server_handles;
+ ldap_server_handle->server_info->ldap_server_handles = ldap_server_handle;
+ return 0;
+}
+
+/*
+ * Add a new ldap server handle structure to the server info structure.
+ * This function name can be changed to krb5_insert_ldap_handle.
+ * Do not lock the mutex here. The caller should lock it
+ */
+
+krb5_error_code
+krb5_update_ldap_handle(ldap_server_handle, server_info)
+ krb5_ldap_server_handle *ldap_server_handle;
+ krb5_ldap_server_info *server_info;
+{
+
+ if (ldap_server_handle == NULL || server_info == NULL)
+ return 0;
+
+ ldap_server_handle->next = server_info->ldap_server_handles;
+ server_info->ldap_server_handles = ldap_server_handle;
+ server_info->num_conns++;
+ ldap_server_handle->server_info = server_info;
+ return 0;
+}
+
+/*
+ * Free up all the ldap server handles of the server info.
+ * This function is called when the ldap server returns LDAP_SERVER_DOWN.
+ */
+
+static krb5_error_code
+krb5_ldap_cleanup_handles(ldap_server_info)
+ krb5_ldap_server_info *ldap_server_info;
+{
+ krb5_ldap_server_handle *ldap_server_handle = NULL;
+
+ while (ldap_server_info->ldap_server_handles != NULL) {
+ ldap_server_handle = ldap_server_info->ldap_server_handles;
+ ldap_server_info->ldap_server_handles = ldap_server_handle->next;
+ /* ldap_unbind_s(ldap_server_handle); */
+ free (ldap_server_handle);
+ ldap_server_handle = NULL;
+ }
+ return 0;
+}
+
+/*
+ * wrapper function called from outside to get a handle.
+ */
+
+krb5_error_code
+krb5_ldap_request_handle_from_pool(ldap_context, ldap_server_handle)
+ krb5_ldap_context *ldap_context;
+ krb5_ldap_server_handle **ldap_server_handle;
+{
+ krb5_error_code st=0;
+
+ *ldap_server_handle = NULL;
+
+ HNDL_LOCK(ldap_context);
+ if (((*ldap_server_handle)=krb5_get_ldap_handle(ldap_context)) == NULL)
+ (*ldap_server_handle)=krb5_retry_get_ldap_handle(ldap_context, &st);
+ HNDL_UNLOCK(ldap_context);
+ return st;
+}
+
+/*
+ * wrapper function wrapper called to get the next ldap server handle, when the current
+ * ldap server handle returns LDAP_SERVER_DOWN.
+ */
+
+krb5_error_code
+krb5_ldap_request_next_handle_from_pool(ldap_context, ldap_server_handle)
+ krb5_ldap_context *ldap_context;
+ krb5_ldap_server_handle **ldap_server_handle;
+{
+ krb5_error_code st=0;
+
+ HNDL_LOCK(ldap_context);
+ (*ldap_server_handle)->server_info->server_status = OFF;
+ time(&(*ldap_server_handle)->server_info->downtime);
+ krb5_put_ldap_handle(*ldap_server_handle);
+ krb5_ldap_cleanup_handles((*ldap_server_handle)->server_info);
+
+ if (((*ldap_server_handle)=krb5_get_ldap_handle(ldap_context)) == NULL)
+ (*ldap_server_handle)=krb5_retry_get_ldap_handle(ldap_context, &st);
+ HNDL_UNLOCK(ldap_context);
+ return st;
+}
+
+/*
+ * wrapper function to call krb5_put_ldap_handle.
+ */
+
+void
+krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle)
+ krb5_ldap_context *ldap_context;
+ krb5_ldap_server_handle *ldap_server_handle;
+{
+
+ if (ldap_server_handle != NULL) {
+ HNDL_LOCK(ldap_context);
+ krb5_put_ldap_handle(ldap_server_handle);
+ HNDL_UNLOCK(ldap_context);
+ }
+ return;
+}
+
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.h b/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.h
new file mode 100644
index 000000000..a3b0885f4
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.h
@@ -0,0 +1,46 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_handle.h
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LDAP_HANDLE_H_
+#define _LDAP_HANDLE_H_
+
+krb5_error_code
+krb5_update_ldap_handle(krb5_ldap_server_handle *, krb5_ldap_server_info *);
+
+krb5_error_code
+krb5_ldap_request_handle_from_pool(krb5_ldap_context *, krb5_ldap_server_handle **);
+
+krb5_error_code
+krb5_ldap_request_next_handle_from_pool(krb5_ldap_context *, krb5_ldap_server_handle **);
+
+void
+krb5_ldap_put_handle_to_pool(krb5_ldap_context *, krb5_ldap_server_handle *);
+
+#endif
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c
new file mode 100644
index 000000000..35e81cd4e
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c
@@ -0,0 +1,203 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_krbcontainer.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ldap_main.h"
+#include "kdb_ldap.h"
+#include "ldap_err.h"
+
+char *policyrefattribute[] = {"krbPolicyReference",NULL};
+char *krbcontainerrefattr[] = {"krbContainerReference", NULL};
+
+/*
+ * Free the krb5_ldap_krbcontainer_params
+ */
+
+void
+krb5_ldap_free_krbcontainer_params(krb5_ldap_krbcontainer_params *cparams)
+{
+ if(cparams == NULL)
+ return;
+
+ if (cparams->policyreference)
+ krb5_xfree(cparams->policyreference);
+
+ if (cparams->parent)
+ krb5_xfree(cparams->parent);
+
+ if (cparams->DN)
+ krb5_xfree(cparams->DN);
+
+ krb5_xfree(cparams);
+
+ return;
+}
+
+/*
+ * Read the kerberos container. Kerberos container dn is read from the krb5.conf file.
+ * In case of eDirectory, if the dn is not present in the conf file, refer Security Container
+ * to fetch the dn information.
+ *
+ * Reading kerberos container includes reading the policyreference attribute and the policy
+ * object to read the attributes associated with it.
+ */
+
+krb5_error_code
+krb5_ldap_read_krbcontainer_params( krb5_context context,
+ krb5_ldap_krbcontainer_params **cparamp)
+
+{
+ krb5_error_code st=0, tempst=0;
+ LDAP *ld=NULL;
+ LDAPMessage *result=NULL, *ent=NULL;
+ krb5_ldap_krbcontainer_params *cparams=NULL;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+
+ SETUP_CONTEXT();
+ GET_HANDLE();
+
+ cparams =(krb5_ldap_krbcontainer_params *) malloc(sizeof(krb5_ldap_krbcontainer_params));
+ CHECK_NULL(cparams);
+ memset((char *) cparams, 0, sizeof(krb5_ldap_krbcontainer_params));
+
+ /* read kerberos containter location from [dbmodules] section of krb5.conf file */
+ if (ldap_context->conf_section) {
+ if ((st=profile_get_string(context->profile, KDB_MODULE_SECTION, ldap_context->conf_section,
+ "ldap_kerberos_container_dn", NULL,
+ &cparams->DN)) != 0) {
+ krb5_set_error_message(context, st, "Error reading kerberos container location "
+ "from krb5.conf");
+ goto cleanup;
+ }
+ }
+
+ /* read kerberos containter location from [dbdefaults] section of krb5.conf file */
+ if (cparams->DN == NULL) {
+ if ((st=profile_get_string(context->profile, KDB_MODULE_DEF_SECTION,
+ "ldap_kerberos_container_dn", NULL,
+ NULL, &cparams->DN)) != 0) {
+ krb5_set_error_message(context, st, "Error reading kerberos container location "
+ "from krb5.conf");
+ goto cleanup;
+ }
+ }
+
+#ifndef HAVE_EDIRECTORY
+/*
+ * In case eDirectory, we can fall back to security container if the kerberos container location
+ * is missing in the conf file. In openldap we will have to return an error.
+ */
+ if (cparams->DN == NULL) {
+ st = KRB5_KDB_SERVER_INTERNAL_ERR;
+ krb5_set_error_message(context, st, "Kerberos container location not specified");
+ goto cleanup;
+ }
+#endif
+
+ if (cparams->DN != NULL) {
+ /* NOTE: krbmaxtktlife, krbmaxrenewableage ... present on Kerberos Container is
+ * not read
+ */
+ LDAP_SEARCH_1(cparams->DN, LDAP_SCOPE_BASE, "(objectclass=krbContainer)", policyrefattribute, IGNORE_STATUS);
+ if (st != LDAP_SUCCESS && st != LDAP_NO_SUCH_OBJECT) {
+ st = set_ldap_error(context, st, OP_SEARCH);
+ goto cleanup;
+ }
+
+ if (st == LDAP_NO_SUCH_OBJECT) {
+ st = KRB5_KDB_NOENTRY;
+ goto cleanup;
+ }
+ }
+
+#ifdef HAVE_EDIRECTORY
+ /*
+ * If the kerberos location in the conf file is missing or invalid, fall back to the
+ * security container. If the kerberos location in the security container is also missing
+ * then fall back to the default value
+ */
+ if ((cparams->DN == NULL) || (st == LDAP_NO_SUCH_OBJECT)) {
+ /*
+ * kerberos container can be anywhere. locate it by reading the security
+ * container to find the location.
+ */
+ LDAP_SEARCH(SECURITY_CONTAINER, LDAP_SCOPE_BASE, NULL, krbcontainerrefattr);
+ if ((ent = ldap_first_entry(ld, result)) != NULL) {
+ if ((st=krb5_ldap_get_string(ld, ent, "krbcontainerreference",
+ &(cparams->DN), NULL)) != 0)
+ goto cleanup;
+ if (cparams->DN == NULL) {
+ cparams->DN = strdup(KERBEROS_CONTAINER);
+ CHECK_NULL(cparams->DN);
+ }
+ }
+ ldap_msgfree(result);
+
+ /* NOTE: krbmaxtktlife, krbmaxrenewableage ... attributes present on
+ * Kerberos Container is not read
+ */
+ LDAP_SEARCH(cparams->DN, LDAP_SCOPE_BASE, "(objectclass=krbContainer)", policyrefattribute);
+ }
+#endif
+
+ if ((ent = ldap_first_entry(ld, result))) {
+ if ((st=krb5_ldap_get_string(ld, ent, "krbpolicyreference",
+ &(cparams->policyreference), NULL)) != 0)
+ goto cleanup;
+ }
+ ldap_msgfree(result);
+
+ if (cparams->policyreference != NULL) {
+ LDAP_SEARCH_1(cparams->policyreference, LDAP_SCOPE_BASE, NULL, policy_attributes, IGNORE_STATUS);
+ if (st != LDAP_SUCCESS && st!= LDAP_NO_SUCH_OBJECT) {
+ st = set_ldap_error(context, st, OP_SEARCH);
+ goto cleanup;
+ }
+ st = LDAP_SUCCESS; /* reset the return status in case it is LDAP_NO_SUCH_OBJECT */
+
+ ent=ldap_first_entry(ld, result);
+ if (ent != NULL) {
+ krb5_ldap_get_value(ld, ent, "krbmaxtktlife", &(cparams->max_life));
+ krb5_ldap_get_value(ld, ent, "krbmaxrenewableage", &(cparams->max_renewable_life));
+ krb5_ldap_get_value(ld, ent, "krbticketflags", &(cparams->tktflags));
+ }
+ ldap_msgfree(result);
+ }
+ *cparamp=cparams;
+
+ cleanup:
+ if(st != 0) {
+ krb5_ldap_free_krbcontainer_params(cparams);
+ *cparamp=NULL;
+ }
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.h b/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.h
new file mode 100644
index 000000000..4d1b4e4e5
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.h
@@ -0,0 +1,54 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_krbcontainer.h
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LDAP_KRBCONTAINER_H_
+#define _LDAP_KRBCONTAINER_H_ 1
+
+/* kerberos container structure */
+
+typedef struct _krb5_ldap_krbcontainer_params {
+ char *parent;
+ char *DN;
+ char *policyreference;
+ krb5_int32 max_life;
+ krb5_int32 max_renewable_life;
+ krb5_int32 tktflags;
+} krb5_ldap_krbcontainer_params;
+
+void
+krb5_ldap_free_krbcontainer_params(krb5_ldap_krbcontainer_params *);
+
+krb5_error_code
+krb5_ldap_read_krbcontainer_params(krb5_context , krb5_ldap_krbcontainer_params **);
+
+krb5_error_code
+krb5_ldap_create_krbcontainer(krb5_context, const krb5_ldap_krbcontainer_params *);
+
+#endif
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_main.h b/src/plugins/kdb/ldap/libkdb_ldap/ldap_main.h
new file mode 100644
index 000000000..95a837929
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_main.h
@@ -0,0 +1,38 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_main.h
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LDAP_MAIN_H
+#define LDAP_MAIN_H 1
+
+#include "kdb_ldap.h"
+#include "ldap_misc.h"
+#include "ldap_handle.h"
+
+#endif
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
new file mode 100644
index 000000000..153a3c63e
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
@@ -0,0 +1,1471 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_misc.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <string.h>
+#include <time.h>
+#include "kdb_ldap.h"
+#include "ldap_misc.h"
+#include "ldap_err.h"
+
+/*
+ * This function reads the parameters from the krb5.conf file. The parameters read here are
+ * DAL-LDAP specific attributes. Some of these are ldap_port, ldap_server ....
+ *
+ */
+krb5_error_code
+krb5_ldap_read_server_params(context, conf_section, srv_type)
+ krb5_context context;
+ char *conf_section;
+ int srv_type;
+{
+ char *tempval=NULL, *save_ptr=NULL;
+ const char *delims="\t\n\f\v\r ,";
+ krb5_error_code st=0;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_info ***server_info=NULL;
+
+ dal_handle = (kdb5_dal_handle *) context->db_context;
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+
+ /* copy the conf_section into ldap_context for later use */
+ if (conf_section) {
+ ldap_context->conf_section = strdup (conf_section);
+ if (ldap_context->conf_section == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ }
+
+ /* initialize the mutexs and condition variable */
+ /* this portion logically doesn't fit here should be moved appropriately */
+
+ /* this mutex is used in ldap reconnection pool */
+ if (k5_mutex_init(&(ldap_context->hndl_lock)) != 0) {
+ st = KRB5_KDB_SERVER_INTERNAL_ERR;
+// st = -1;
+// krb5_ldap_dal_err_funcp(context, krb5_err_have_str, st,
+// "k5_mutex_init failed");
+ goto cleanup;
+ }
+
+ /* if max_server_conns is not set read it from database module section of conf file
+ * this parameter defines maximum ldap connections per ldap server
+ */
+ if (ldap_context->max_server_conns == 0) {
+ if ((st=profile_get_integer(context->profile, KDB_MODULE_SECTION, conf_section,
+ "ldap_conns_per_server", 0,
+ (int *) &ldap_context->max_server_conns)) != 0) {
+ krb5_set_error_message (context, st, "Error reading 'ldap_conns_per_server' "
+ "attribute");
+ goto cleanup;
+ }
+ }
+
+ /* if ldap port is not set read it from database module section of conf file */
+ if (ldap_context->port == 0) {
+ if ((st=profile_get_integer(context->profile, KDB_MODULE_SECTION, conf_section,
+ "ldap_ssl_port", 0,
+ (int *) &ldap_context->port)) != 0) {
+ krb5_set_error_message (context, st, "Error reading 'ldap_ssl_port' attribute");
+ goto cleanup;
+ }
+ }
+
+ /* if the bind dn is not set read it from the database module section of conf file
+ * this paramter is populated by one of the KDC, ADMIN or PASSWD dn to be used to connect
+ * to LDAP server. the srv_type decides which dn to read.
+ */
+ if( ldap_context->bind_dn == NULL ) {
+
+ if (srv_type == KRB5_KDB_SRV_TYPE_KDC) {
+ if ((st=profile_get_string(context->profile, KDB_MODULE_SECTION, conf_section,
+ "ldap_kdc_dn", NULL, &ldap_context->bind_dn)) != 0) {
+ krb5_set_error_message (context, st, "Error reading 'ldap_kdc_dn' attribute");
+ goto cleanup;
+ }
+ }
+ else if (srv_type == KRB5_KDB_SRV_TYPE_ADMIN) {
+ if ((st=profile_get_string(context->profile, KDB_MODULE_SECTION, conf_section,
+ "ldap_kadmind_dn", NULL, &ldap_context->bind_dn)) != 0) {
+ krb5_set_error_message (context, st, "Error reading 'ldap_kadmind_dn' attribute");
+ goto cleanup;
+ }
+ }
+ else if (srv_type == KRB5_KDB_SRV_TYPE_PASSWD) {
+ if ((st=profile_get_string(context->profile, KDB_MODULE_SECTION, conf_section,
+ "ldap_kpasswdd_dn", NULL, &ldap_context->bind_dn)) != 0) {
+ krb5_set_error_message (context, st, "Error reading 'ldap_kpasswdd_dn' attribute");
+ goto cleanup;
+ }
+ }
+ }
+
+ /* read service_password_file parameter from database module section of conf file
+ * this file contains stashed passwords of the KDC, ADMIN and PASSWD dns.
+ */
+ if (ldap_context->service_password_file == NULL) {
+ if ((st=profile_get_string(context->profile, KDB_MODULE_SECTION, conf_section,
+ "ldap_service_password_file", NULL,
+ &ldap_context->service_password_file)) != 0) {
+ krb5_set_error_message (context, st, "Error reading 'ldap_service_password_file' attribute");
+ goto cleanup;
+ }
+ }
+
+ /* if root certificate file is not set read it from database module section of conf file
+ * this is the trusted root certificate of the Directory.
+ */
+ if (ldap_context->root_certificate_file == NULL) {
+ if ((st=profile_get_string(context->profile, KDB_MODULE_SECTION, conf_section,
+ "ldap_root_certificate_file", NULL,
+ &ldap_context->root_certificate_file)) != 0) {
+ krb5_set_error_message (context, st, "Error reading 'ldap_root_certificate_file' attribute");
+ goto cleanup;
+ }
+ }
+
+ /* if the ldap server parameter is not set read the list of ldap servers:port from the
+ * database module section of the conf file
+ */
+
+ if (ldap_context->server_info_list == NULL) {
+ unsigned int ele=0;
+
+ server_info = &(ldap_context->server_info_list);
+ *server_info = (krb5_ldap_server_info **) calloc (SERV_COUNT+1,
+ sizeof (krb5_ldap_server_info *));
+
+ if (*server_info == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+
+ if ((st=profile_get_string(context->profile, KDB_MODULE_SECTION, conf_section,
+ "ldap_servers", NULL, &tempval)) != 0) {
+ krb5_set_error_message (context, st, "Error reading 'ldap_servers' attribute");
+ goto cleanup;
+ }
+
+ if (tempval == NULL) {
+
+ (*server_info)[ele] = (krb5_ldap_server_info *)calloc(1,
+ sizeof(krb5_ldap_server_info));
+
+ (*server_info)[ele]->server_name = strdup("localhost");
+ if ((*server_info)[ele]->server_name == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ (*server_info)[ele]->server_status = NOTSET;
+ } else {
+ char *port=NULL, *server=NULL, *item=NULL;
+
+ item = strtok_r(tempval,delims,&save_ptr);
+ while(item != NULL && ele<SERV_COUNT){
+ (*server_info)[ele] = (krb5_ldap_server_info *)calloc(1,
+ sizeof(krb5_ldap_server_info));
+ if ((*server_info)[ele] == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ server=strtok_r(item, ":", &port);
+
+ (*server_info)[ele]->server_name = strdup(server);
+ if ((*server_info)[ele]->server_name == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+
+ if (port) {
+ (*server_info)[ele]->port = atoi(port);
+ }
+ (*server_info)[ele]->server_status = NOTSET;
+ item = strtok_r(NULL,delims,&save_ptr);
+ ++ele;
+ }
+ profile_release_string(tempval);
+ }
+ }
+
+ /* the same set of all the above parameters can be obtained from the dbdefaults section of
+ * conf file. Here read the missing parameters from [dbdefaults] section */
+
+ if (ldap_context->max_server_conns == 0) {
+ if ((st=profile_get_integer(context->profile, KDB_MODULE_DEF_SECTION,
+ "ldap_conns_per_server", NULL, DEFAULT_CONNS_PER_SERVER,
+ (int *) &ldap_context->max_server_conns)) != 0) {
+ krb5_set_error_message (context, st, "Error reading 'ldap_conns_per_server' attribute");
+ goto cleanup;
+ }
+ }
+
+ if (ldap_context->max_server_conns < 2) {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "Minimum connections required per server is 2");
+ goto cleanup;
+ }
+
+ if (ldap_context->port == 0) {
+ if ((st=profile_get_integer(context->profile, KDB_MODULE_DEF_SECTION, "ldap_ssl_port",
+ NULL, LDAPS_PORT, &ldap_context->port)) != 0) {
+ krb5_set_error_message (context, st, "Error reading 'ldap_ssl_port' attribute");
+ goto cleanup;
+ }
+ }
+
+ if( ldap_context->bind_dn == NULL ) {
+ if (srv_type == KRB5_KDB_SRV_TYPE_KDC) {
+ if ((st=profile_get_string(context->profile, KDB_MODULE_DEF_SECTION, "ldap_kdc_dn",
+ NULL, NULL, &ldap_context->bind_dn)) != 0) {
+ krb5_set_error_message (context, st, "Error reading 'ldap_kdc_dn' attribute");
+ goto cleanup;
+ }
+ }
+ else if (srv_type == KRB5_KDB_SRV_TYPE_ADMIN) {
+ if ((st=profile_get_string(context->profile, KDB_MODULE_DEF_SECTION,
+ "ldap_kadmind_dn", NULL, NULL,
+ &ldap_context->bind_dn)) != 0) {
+ krb5_set_error_message (context, st, "Error reading 'ldap_kadmind_dn' attribute");
+ goto cleanup;
+ }
+ }
+ else if (srv_type == KRB5_KDB_SRV_TYPE_PASSWD) {
+ if ((st=profile_get_string(context->profile, KDB_MODULE_DEF_SECTION,
+ "ldap_kpasswdd_dn", NULL, NULL,
+ &ldap_context->bind_dn)) != 0) {
+ krb5_set_error_message (context, st, "Error reading 'ldap_kpasswdd_dn' attribute");
+ goto cleanup;
+ }
+ }
+ }
+
+ /* read service_password_file value */
+ if (ldap_context->service_password_file == NULL) {
+ if ((st=profile_get_string(context->profile, KDB_MODULE_DEF_SECTION,
+ "ldap_service_password_file", NULL, NULL,
+ &ldap_context->service_password_file)) != 0) {
+ krb5_set_error_message (context, st, "Error reading 'ldap_service_passwd_file' attribute");
+ goto cleanup;
+ }
+ }
+
+ /* read root certificate file value */
+ if (ldap_context->root_certificate_file == NULL) {
+ if ((st=profile_get_string(context->profile, KDB_MODULE_DEF_SECTION,
+ "ldap_root_certificate_file", NULL, NULL,
+ &ldap_context->root_certificate_file)) != 0) {
+ krb5_set_error_message (context, st, "Error reading 'ldap_root_certificate_file' attribute");
+ goto cleanup;
+ }
+ }
+
+ cleanup:
+ return(st);
+}
+
+/*
+ * This function frees the krb5_ldap_context structure members.
+ */
+
+krb5_error_code
+krb5_ldap_free_server_params(ldap_context)
+ krb5_ldap_context *ldap_context;
+{
+ int i=0;
+ krb5_ldap_server_handle *ldap_server_handle=NULL, *next_ldap_server_handle=NULL;
+
+ if (ldap_context == NULL)
+ return 0;
+
+ /* free all ldap servers list and the ldap handles associated with the ldap server */
+ if(ldap_context->server_info_list) {
+ while (ldap_context->server_info_list[i]) {
+ if (ldap_context->server_info_list[i]->server_name) {
+ free (ldap_context->server_info_list[i]->server_name);
+ }
+ if (ldap_context->server_info_list[i]->root_certificate_file) {
+ free (ldap_context->server_info_list[i]->root_certificate_file);
+ }
+ if (ldap_context->server_info_list[i]->ldap_server_handles) {
+ ldap_server_handle = ldap_context->server_info_list[i]->ldap_server_handles;
+ while (ldap_server_handle) {
+ ldap_unbind_s(ldap_server_handle->ldap_handle);
+ ldap_server_handle->ldap_handle = NULL;
+ next_ldap_server_handle = ldap_server_handle->next;
+ krb5_xfree(ldap_server_handle);
+ ldap_server_handle = next_ldap_server_handle;
+ }
+ }
+ krb5_xfree(ldap_context->server_info_list[i]);
+ i++;
+ }
+ krb5_xfree(ldap_context->server_info_list);
+ }
+
+ if (ldap_context->conf_section != NULL) {
+ krb5_xfree(ldap_context->conf_section);
+ ldap_context->conf_section = NULL;
+ }
+
+ if (ldap_context->bind_dn != NULL) {
+ krb5_xfree(ldap_context->bind_dn);
+ ldap_context->bind_dn = NULL;
+ }
+
+ if (ldap_context->bind_pwd != NULL) {
+ krb5_xfree(ldap_context->bind_pwd);
+ ldap_context->bind_pwd = NULL;
+ }
+
+ if (ldap_context->service_password_file != NULL) {
+ krb5_xfree(ldap_context->service_password_file);
+ ldap_context->service_password_file = NULL;
+ }
+
+ if (ldap_context->root_certificate_file != NULL) {
+ krb5_xfree(ldap_context->root_certificate_file);
+ ldap_context->root_certificate_file = NULL;
+ }
+
+ if (ldap_context->service_cert_path != NULL) {
+ krb5_xfree(ldap_context->service_cert_path);
+ ldap_context->service_cert_path = NULL;
+ }
+
+ if (ldap_context->service_cert_pass != NULL) {
+ krb5_xfree(ldap_context->service_cert_pass);
+ ldap_context->service_cert_pass = NULL;
+ }
+
+ if (ldap_context->certificates) {
+ i=0;
+ while (ldap_context->certificates[i] != NULL) {
+ krb5_xfree(ldap_context->certificates[i]->certificate);
+ krb5_xfree(ldap_context->certificates[i]);
+ ++i;
+ }
+ krb5_xfree(ldap_context->certificates);
+ }
+
+ k5_mutex_destroy(&ldap_context->hndl_lock);
+
+ krb5_xfree(ldap_context);
+ return(0);
+}
+
+
+/*
+ * check to see if the principal belongs to the default realm.
+ * The default realm is present in the krb5_ldap_context structure.
+ * The principal has a realm portion. This realm portion is compared with the default realm
+ * to check whether the principal belong to the default realm.
+ * Return 0 if principal belongs to default realm else 1.
+ */
+
+krb5_error_code
+is_principal_in_realm(ldap_context, searchfor)
+ krb5_ldap_context *ldap_context;
+ krb5_const_principal searchfor;
+{
+ int defrealmlen=0;
+ char *defrealm=NULL;
+
+#define FIND_MAX(a,b) ((a) > (b) ? (a) : (b))
+
+ defrealmlen = strlen(ldap_context->lrparams->realm_name);
+ defrealm = ldap_context->lrparams->realm_name;
+
+ /* care should be taken for inter-realm principals as the default realm can exist in the
+ * realm part of the principal name or can also exist in the second portion of the name part.
+ * However, if the default realm exist in the second part of the principal portion, then the
+ * first portion of the principal name SHOULD be "krbtgt". All this check is done in the
+ * immediate block.
+ */
+ if (searchfor->length == 2)
+ if ((strncasecmp(searchfor->data[0].data, "krbtgt",
+ FIND_MAX(searchfor->data[0].length, strlen("krbtgt"))) == 0) &&
+ (strncasecmp(searchfor->data[1].data, defrealm,
+ FIND_MAX(searchfor->data[1].length, defrealmlen)) == 0))
+ return 0;
+
+ /* first check the length, if they are not equal, then they are not same */
+ if (strlen(defrealm) != searchfor->realm.length)
+ return 1;
+
+ /* if the length is equal, check for the contents */
+ if (strncmp(defrealm, searchfor->realm.data,
+ searchfor->realm.length) != 0)
+ return 1;
+ /* if we are here, then the realm portions match, return 0 */
+ return 0;
+}
+
+
+/*
+ * Deduce the subtree information from the context. A realm can have atmost 2 subtrees.
+ * 1. the Realm container
+ * 2. the actual subtree associated with the Realm
+ *
+ * However, there are some conditions to be considered to deduce the actual subtree/s associated
+ * with the realm. The conditions are as follows
+ * 1. If the subtree information of the Realm is [Root] or NULL (that is internal a [Root]) then
+ * the realm has only one subtree i.e [Root], i.e. whole of the tree.
+ * 2. If the subtree information of the Realm is missing/absent, then the realm has only one
+ * i.e. the Realm container. NOTE: In call cases Realm container SHOULD be the one among the
+ * subtrees or the only one subtree.
+ * 3. The subtree information of the realm is overlapping the realm container of the realm, then
+ * the realm has only one subtree and it is the subtree information associated with the realm.
+ */
+krb5_error_code
+krb5_get_subtree_info(ldap_context, subtreearr, ntree)
+ krb5_ldap_context *ldap_context;
+ char **subtreearr;
+ unsigned int *ntree;
+{
+ int lendiff=0;
+ char *subtree=NULL, *realm_cont_dn=NULL;
+
+ subtree = ldap_context->lrparams->subtree;
+ realm_cont_dn = ldap_context->lrparams->realmdn;
+
+ /*
+ * if subtree attribute value is [Root] of the tree which is represented by a ""
+ * (null) string, set the ntree value as 1 and do not fill the subtreearr value.
+ * In eDirectory the [Root] can be represented as a "" (null) string, however this
+ * representation throws a "No such object" error in OpenLDAP.
+ * Representing [Root] of the tree as NULL pointer (i.e. no value) works in both case.
+ */
+ if (subtree == NULL || strcasecmp(subtree, "") == 0) {
+ *ntree = 1;
+ return 0;
+ }
+
+ /*
+ * the subtree attribute value of the realm can be same as the realm container or can
+ * even overlap. If the check is successful, then the subtree attribute value alone is
+ * copied to the subtreearr array and the ntree value is set to 1.
+ */
+ lendiff = strlen(realm_cont_dn) - strlen(subtree);
+ if (lendiff >= 0 && (strcasecmp(realm_cont_dn+lendiff, subtree)==0)) {
+ subtreearr[0] = strdup(subtree);
+ if (subtreearr[0] == NULL)
+ return ENOMEM;
+ *ntree = 1;
+ return 0;
+ }
+
+ /*
+ * if the subtree attribute value of the realm and the realm container are different,
+ * then both of the values are copied to subtreearr and ntree value is set to 2.
+ */
+ subtreearr[0] = strdup(realm_cont_dn);
+ if (subtreearr[0] == NULL)
+ return ENOMEM;
+ subtreearr[1] = strdup(subtree);
+ if (subtreearr[1] == NULL) {
+ if (subtreearr[0])
+ free (subtreearr[0]);
+ return ENOMEM;
+ }
+ *ntree = 2;
+ return 0;
+}
+
+/*
+ * This function appends the content with a type into the tl_data structure. Based on the type
+ * the length of the content is either pre-defined or computed from the content.
+ * Returns 0 in case of success and 1 if the type associated with the content is undefined.
+ */
+
+krb5_error_code
+store_tl_data(tl_data, tl_type, value)
+ krb5_tl_data *tl_data;
+ int tl_type;
+ void *value;
+{
+ unsigned int currlen=0, tldatalen=0;
+ char *curr=NULL;
+ void *reallocptr=NULL;
+
+ tl_data->tl_data_type = KDB_TL_USER_INFO;
+ switch(tl_type)
+ {
+ case KDB_TL_PRINCCOUNT:
+ case KDB_TL_PRINCTYPE:
+ case KDB_TL_MASK:
+ {
+ int *iptr = (int *)value;
+ int ivalue = *iptr;
+
+ currlen = tl_data->tl_data_length;
+ tl_data->tl_data_length += 1 + 2 + 2;
+ /* allocate required memory */
+ reallocptr = tl_data->tl_data_contents;
+ tl_data->tl_data_contents = realloc(tl_data->tl_data_contents,
+ tl_data->tl_data_length);
+ if (tl_data->tl_data_contents == NULL) {
+ if (reallocptr)
+ free (reallocptr);
+ return ENOMEM;
+ }
+ curr = (char *) (tl_data->tl_data_contents + currlen);
+
+ /* store the tl_type value */
+ memset(curr, tl_type, 1);
+ curr += 1;
+ /* store the content length */
+ tldatalen = 2;
+ STORE16_INT(curr, tldatalen);
+ curr += 2;
+ /* store the content */
+ STORE16_INT(curr, ivalue);
+ curr += 2;
+ break;
+ }
+
+ case KDB_TL_USERDN:
+ case KDB_TL_TKTPOLICYDN:
+ {
+ char *cptr = (char *)value;
+
+ currlen = tl_data->tl_data_length;
+ tl_data->tl_data_length += 1 + 2 + strlen(cptr);
+ /* allocate required memory */
+ reallocptr = tl_data->tl_data_contents;
+ tl_data->tl_data_contents = realloc(tl_data->tl_data_contents,
+ tl_data->tl_data_length);
+ if (tl_data->tl_data_contents == NULL) {
+ if (reallocptr)
+ free (reallocptr);
+ return ENOMEM;
+ }
+ curr = (char *) (tl_data->tl_data_contents + currlen);
+
+ /* store the tl_type value */
+ memset(curr, tl_type, 1);
+ curr += 1;
+ /* store the content length */
+ tldatalen = strlen(cptr);
+ STORE16_INT(curr, tldatalen);
+ curr += 2;
+ /* store the content */
+ memcpy(curr, cptr, tldatalen);
+ curr += tldatalen;
+ break;
+ }
+
+ case KDB_TL_KEYINFO:
+ {
+ struct berval *key = (struct berval *)value;
+
+ currlen = tl_data->tl_data_length;
+ tl_data->tl_data_length += 1 + 2 + key->bv_len;
+ /* allocate required memory */
+ reallocptr = tl_data->tl_data_contents;
+ tl_data->tl_data_contents = realloc(tl_data->tl_data_contents,
+ tl_data->tl_data_length);
+ if (tl_data->tl_data_contents == NULL) {
+ if (reallocptr)
+ free (reallocptr);
+ return ENOMEM;
+ }
+ curr = (char *) (tl_data->tl_data_contents + currlen);
+
+ /* store the tl_type value */
+ memset(curr, tl_type, 1);
+ curr += 1;
+ /* store the content length */
+ tldatalen = key->bv_len;
+ STORE16_INT(curr, tldatalen);
+ curr += 2;
+ /* store the content */
+ memcpy(curr, key->bv_val, key->bv_len);
+ curr += tldatalen;
+ break;
+ }
+
+ default:
+ return 1;
+
+ }
+ return 0;
+}
+
+/*
+ * This function scans the tl_data structure to get the value of a type defined by the tl_type
+ * (second parameter). The tl_data structure has all the data in the tl_data_contents member.
+ * The format of the tl_data_contents is as follows.
+ * The first byte defines the type of the content that follows. The next 2 bytes define the
+ * size n (in terms of bytes) of the content that follows. The next n bytes define the content
+ * itself.
+ */
+
+krb5_error_code
+decode_tl_data(tl_data, tl_type, data)
+ krb5_tl_data *tl_data;
+ int tl_type;
+ void **data;
+{
+ int subtype=0, i=0, limit=10;
+ unsigned int sublen=0;
+ unsigned char *curr=NULL;
+ int *intptr=NULL;
+ long *longptr=NULL;
+ char *DN=NULL;
+ krb5_boolean keyfound=FALSE;
+ KEY *secretkey = NULL;
+
+ *data = NULL;
+
+ curr = tl_data->tl_data_contents;
+ while(curr < (tl_data->tl_data_contents + tl_data->tl_data_length)) {
+
+ /* get the type of the content */
+ subtype = (int) curr[0];
+ /* forward by 1 byte*/
+ curr += 1;
+
+ if (subtype == tl_type) {
+ switch(subtype) {
+
+ case KDB_TL_PRINCCOUNT:
+ case KDB_TL_PRINCTYPE:
+ case KDB_TL_MASK:
+ /* get the length of the content */
+ UNSTORE16_INT(curr, sublen);
+ /* forward by 2 bytes */
+ curr += 2;
+ /* get the actual content */
+ if (sublen == 2) {
+ /* intptr = malloc(sublen); */
+ intptr = malloc(sizeof(krb5_int32));
+ if (intptr == NULL)
+ return ENOMEM;
+ memset(intptr, 0, sublen);
+ UNSTORE16_INT(curr, (*intptr));
+ *data = intptr;
+ } else {
+ longptr = malloc(sublen);
+ if (longptr == NULL)
+ return ENOMEM;
+ memset(longptr, 0, sublen);
+ UNSTORE32_INT(curr, (*longptr));
+ *data = longptr;
+ }
+ curr += sublen;
+ return 0;
+ break;
+
+ case KDB_TL_CONTAINERDN:
+ case KDB_TL_USERDN:
+ case KDB_TL_TKTPOLICYDN:
+ /* get the length of the content */
+ UNSTORE16_INT(curr, sublen);
+ /* forward by 2 bytes */
+ curr += 2;
+ DN = malloc (sublen + 1);
+ if (DN == NULL)
+ return ENOMEM;
+ memcpy(DN, curr, sublen);
+ DN[sublen] = 0;
+ *data = DN;
+ curr += sublen;
+ return 0;
+ break;
+
+ case KDB_TL_KEYINFO:
+ /* get the length of the content */
+ keyfound = TRUE;
+ UNSTORE16_INT(curr, sublen);
+ /* forward by 2 bytes */
+ curr += 2;
+ if (secretkey == NULL) {
+ secretkey = malloc(sizeof(*secretkey));
+ if (secretkey == NULL)
+ return ENOMEM;
+ secretkey->nkey = 0;
+ secretkey->keys = NULL;
+ secretkey->keys = realloc(secretkey->keys,
+ sizeof(*(secretkey->keys)) * (limit));
+ if (secretkey->keys == NULL)
+ return ENOMEM;
+ memset(secretkey->keys, 0, sizeof (*(secretkey->keys)) * (limit));
+ }
+ if ( i == limit-1) {
+ limit *= 2;
+ secretkey->keys = realloc(secretkey->keys,
+ sizeof(*(secretkey->keys)) * (limit));
+ if (secretkey->keys == NULL)
+ return ENOMEM;
+ memset(secretkey->keys+i, 0, sizeof (*(secretkey->keys)) * (limit-i));
+ }
+
+ secretkey->keys[i] = malloc (sizeof(struct berval));
+ if (secretkey->keys[i] == NULL)
+ return ENOMEM;
+
+ secretkey->keys[i]->bv_len = sublen;
+ secretkey->keys[i]->bv_val = malloc (sublen);
+ if (secretkey->keys[i]->bv_val == NULL)
+ return ENOMEM;
+
+ memcpy(secretkey->keys[i]->bv_val, curr, sublen);
+ secretkey->nkey = ++i;
+ *data = secretkey;
+ curr += sublen;
+ break;
+ }
+ } else {
+ /* move to the current content block */
+ UNSTORE16_INT(curr, sublen);
+ curr += 2 + sublen;
+ }
+ }
+ if (tl_type == KDB_TL_KEYINFO) {
+ if (keyfound)
+ return 0;
+ else
+ return EINVAL;
+ }
+ return EINVAL;
+}
+
+/*
+ * wrapper routines for decode_tl_data
+ */
+static krb5_error_code
+krb5_get_int_from_tl_data(context, entries, type, intval)
+ krb5_context context;
+ krb5_db_entry *entries;
+ int type;
+ int *intval;
+{
+ krb5_error_code st=0;
+ krb5_tl_data tl_data;
+ void *voidptr=NULL;
+ int *intptr=NULL;
+
+ tl_data.tl_data_type = KDB_TL_USER_INFO;
+ if (((st=krb5_dbe_lookup_tl_data(context, entries, &tl_data)) != 0) || tl_data.tl_data_length == 0)
+ goto cleanup;
+
+ if (decode_tl_data(&tl_data, type, &voidptr) == 0) {
+ intptr = (int *) voidptr;
+ *intval = *intptr;
+ free(intptr);
+ }
+
+ cleanup:
+ return st;
+}
+
+/*
+ * get the mask representing the attributes set on the directory object (user, policy ...)
+ */
+krb5_error_code
+krb5_get_attributes_mask(context, entries, mask)
+ krb5_context context;
+ krb5_db_entry *entries;
+ int *mask;
+{
+ return krb5_get_int_from_tl_data(context, entries, KDB_TL_MASK, mask);
+}
+
+krb5_error_code
+krb5_get_princ_type(context, entries, ptype)
+ krb5_context context;
+ krb5_db_entry *entries;
+ int *ptype;
+{
+ return krb5_get_int_from_tl_data(context, entries, KDB_TL_PRINCTYPE, ptype);
+}
+
+krb5_error_code
+krb5_get_princ_count(context, entries, pcount)
+ krb5_context context;
+ krb5_db_entry *entries;
+ int *pcount;
+{
+ return krb5_get_int_from_tl_data(context, entries, KDB_TL_PRINCCOUNT, pcount);
+}
+
+krb5_error_code
+krb5_get_secretkeys(context, entries, secretkey)
+ krb5_context context;
+ krb5_db_entry *entries;
+ KEY **secretkey;
+{
+ krb5_error_code st=0;
+ krb5_tl_data tl_data;
+ void *voidptr=NULL;
+
+ tl_data.tl_data_type = KDB_TL_USER_INFO;
+ if (((st=krb5_dbe_lookup_tl_data(context, entries, &tl_data)) != 0) || tl_data.tl_data_length == 0)
+ goto cleanup;
+
+ if (decode_tl_data(&tl_data, KDB_TL_KEYINFO, &voidptr) == 0) {
+ *secretkey = (KEY *) voidptr;
+ }
+
+ cleanup:
+ return st;
+}
+
+static krb5_error_code
+krb5_get_str_from_tl_data(context, entries, type, strval)
+ krb5_context context;
+ krb5_db_entry *entries;
+ int type;
+ char **strval;
+{
+ krb5_error_code st=0;
+ krb5_tl_data tl_data;
+ void *voidptr=NULL;
+
+ if (type != KDB_TL_USERDN && type != KDB_TL_CONTAINERDN && type != KDB_TL_TKTPOLICYDN) {
+ st = EINVAL;
+ goto cleanup;
+ }
+
+ tl_data.tl_data_type = KDB_TL_USER_INFO;
+ if (((st=krb5_dbe_lookup_tl_data(context, entries, &tl_data)) != 0) || tl_data.tl_data_length == 0)
+ goto cleanup;
+
+ if (decode_tl_data(&tl_data, type, &voidptr) == 0) {
+ *strval = (char *) voidptr;
+ }
+
+ cleanup:
+ return st;
+}
+
+krb5_error_code
+krb5_get_userdn(context, entries, userdn)
+ krb5_context context;
+ krb5_db_entry *entries;
+ char **userdn;
+{
+ *userdn = NULL;
+ return krb5_get_str_from_tl_data(context, entries, KDB_TL_USERDN, userdn);
+}
+
+krb5_error_code
+krb5_get_containerdn(context, entries, containerdn)
+ krb5_context context;
+ krb5_db_entry *entries;
+ char **containerdn;
+{
+ *containerdn = NULL;
+ return krb5_get_str_from_tl_data(context, entries, KDB_TL_CONTAINERDN, containerdn);
+}
+
+krb5_error_code
+krb5_get_policydn(context, entries, policydn)
+ krb5_context context;
+ krb5_db_entry *entries;
+ char **policydn;
+{
+ *policydn = NULL;
+ return krb5_get_str_from_tl_data(context, entries, KDB_TL_TKTPOLICYDN, policydn);
+}
+/*
+ * This function reads the attribute values (if the attribute is non-null) from the dn.
+ * The read attribute values is compared aganist the attrvalues passed to the function
+ * and a bit mask is set for all the matching attributes (attributes existing in both list).
+ * The bit to be set is selected such that the index of the attribute in the attrvalues
+ * parameter is the position of the bit.
+ * For ex: the first element in the attrvalues is present in both list shall set the LSB of the
+ * bit mask.
+ *
+ * In case if either the attribute or the attrvalues parameter to the function is NULL, then
+ * the existence of the object is considered and appropriate status is returned back
+ */
+
+krb5_error_code
+checkattributevalue (ld, dn, attribute, attrvalues, mask)
+ LDAP *ld;
+ char *dn;
+ char *attribute;
+ char **attrvalues;
+ int *mask;
+{
+ int st=0, one=1;
+ char **values=NULL, *attributes[2] = {NULL};
+ LDAPMessage *result=NULL, *entry=NULL;
+
+ if (strlen(dn) == 0)
+ return LDAP_NO_SUCH_OBJECT;
+
+ attributes[0] = attribute;
+
+ /* read the attribute values from the dn */
+ if((st = ldap_search_ext_s( ld,
+ dn,
+ LDAP_SCOPE_BASE,
+ 0,
+ attributes,
+ 0,
+ NULL,
+ NULL,
+ &timelimit,
+ LDAP_NO_LIMIT,
+ &result)) != LDAP_SUCCESS) {
+ st = set_ldap_error(0, st, OP_SEARCH);
+ return st;
+ }
+
+ /*
+ * If the attribute/attrvalues is NULL, then check for the existence of the object alone
+ */
+ if (attribute == NULL || attrvalues == NULL)
+ goto cleanup;
+
+ /* reset the bit mask */
+ *mask = 0;
+
+ if((entry=ldap_first_entry(ld, result)) != NULL) {
+ /* read the attribute values */
+ if((values=ldap_get_values(ld, entry, attribute)) != NULL) {
+ int i,j;
+
+ /* compare the read attribute values with the attrvalues array and set the
+ * appropriate bit mask
+ */
+ for(j=0; attrvalues[j]; ++j) {
+ for(i=0; values[i]; ++i) {
+ if(strcasecmp(values[i], attrvalues[j]) == 0) {
+ *mask |= (one<<j);
+ break;
+ }
+ }
+ }
+ ldap_value_free(values);
+ }
+ }
+
+ cleanup:
+ ldap_msgfree(result);
+ return st;
+}
+
+
+/*
+ * This function updates a single attribute with a single value of a specified dn.
+ * This function is mainly used to update krbRealmReferences, krbKdcServers, krbAdminServers...
+ * when KDC, ADMIN, PASSWD servers are associated with some realms or vice versa.
+ */
+
+krb5_error_code
+updateAttribute (ld, dn, attribute, value)
+ LDAP *ld;
+ char *dn;
+ char *attribute;
+ char *value;
+{
+ int st=0;
+ LDAPMod modAttr, *mods[2]={NULL};
+ char *values[2]={NULL};
+
+ values[0] = value;
+
+ /* data to update the {attr,attrval} combination */
+ memset(&modAttr, 0, sizeof(modAttr));
+ modAttr.mod_type = attribute;
+ modAttr.mod_op = LDAP_MOD_ADD;
+ modAttr.mod_values = values;
+ mods[0] = &modAttr;
+
+ /* ldap modify operation */
+ st = ldap_modify_s(ld, dn, mods);
+
+ /* if the {attr,attrval} combination is already present return a success
+ * LDAP_ALREADY_EXISTS is for single-valued attribute
+ * LDAP_TYPE_OR_VALUE_EXISTS is for multi-valued attribute
+ */
+ if (st == LDAP_ALREADY_EXISTS || st == LDAP_TYPE_OR_VALUE_EXISTS)
+ st = 0;
+
+ if (st != 0) {
+ st = set_ldap_error (0, st, OP_MOD);
+ }
+
+ return st;
+}
+
+/*
+ * This function deletes a single attribute with a single value of a specified dn.
+ * This function is mainly used to delete krbRealmReferences, krbKdcServers, krbAdminServers...
+ * when KDC, ADMIN, PASSWD servers are disassociated with some realms or vice versa.
+ */
+
+krb5_error_code
+deleteAttribute (ld, dn, attribute, value)
+ LDAP *ld;
+ char *dn;
+ char *attribute;
+ char *value;
+{
+ krb5_error_code st=0;
+ LDAPMod modAttr, *mods[2]={NULL};
+ char *values[2]={NULL};
+
+ values[0] = value;
+
+ /* data to delete the {attr,attrval} combination */
+ memset(&modAttr, 0, sizeof(modAttr));
+ modAttr.mod_type = attribute;
+ modAttr.mod_op = LDAP_MOD_DELETE;
+ modAttr.mod_values = values;
+ mods[0] = &modAttr;
+
+ /* ldap modify operation */
+ st = ldap_modify_s(ld, dn, mods);
+
+ /* if either the attribute or the attribute value is missing return a success */
+ if (st == LDAP_NO_SUCH_ATTRIBUTE || st == LDAP_UNDEFINED_TYPE)
+ st = 0;
+
+ if (st != 0) {
+ st = set_ldap_error (0, st, OP_MOD);
+ }
+
+ return st;
+}
+
+
+/*
+ * This function takes in 2 string arrays, compares them to remove the matching entries.
+ * The first array is the original list and the second array is the modified list. Removing
+ * the matching entries will result in a reduced array, where the left over first array elements
+ * are the deleted entries and the left over second array elements are the added entries.
+ * These additions and deletions has resulted in the modified second array.
+ */
+
+krb5_error_code
+disjoint_members(src, dest)
+ char **src;
+ char **dest;
+{
+ int i=0, j=0, slen=0, dlen=0;
+
+ /* validate the input parameters */
+ if (src == NULL || dest == NULL)
+ return 0;
+
+ /* compute the first array length */
+ for (i=0;src[i]; ++i)
+ ;
+
+ /* return if the length is 0 */
+ if (i==0)
+ return 0;
+
+ /* index of the last element and also the length of the array */
+ slen = i-1;
+
+ /* compute the second array length */
+ for (i=0;dest[i]; ++i)
+ ;
+
+ /* return if the length is 0 */
+ if (i==0)
+ return 0;
+
+ /* index of the last element and also the length of the array */
+ dlen = i-1;
+
+ /* check for the similar elements and delete them from both the arrays */
+ for(i=0; src[i]; ++i) {
+
+ for(j=0; dest[j]; ++j) {
+
+ /* if the element are same */
+ if (strcasecmp(src[i], dest[j]) == 0) {
+ /* if the matched element is in the middle, then copy the last element to
+ * the matched index.
+ */
+ if (i != slen) {
+ free (src[i]);
+ src[i] = src[slen];
+ src[slen] = NULL;
+ } else {
+ /* if the matched element is the last, free it and set it to NULL */
+ free (src[i]);
+ src[i] = NULL;
+ }
+ /* reduce the array length by 1 */
+ slen -= 1;
+
+ /* repeat the same processing for the second array too */
+ if (j != dlen) {
+ free(dest[j]);
+ dest[j] = dest[dlen];
+ dest[dlen] = NULL;
+ } else {
+ free(dest[j]);
+ dest[j] = NULL;
+ }
+ dlen -=1;
+
+ /* the source array is reduced by 1, so reduce the index variable used for
+ * source array by 1. No need to adjust the second array index variable as
+ * it is reset while entering the inner loop
+ */
+ i -= 1;
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+ * This function replicates the contents of the src array for later use. Mostly the contents
+ * of the src array is obtained from a ldap_search operation and the contents are required
+ * for later use.
+ */
+
+krb5_error_code
+copy_arrays(src, dest, count)
+ char **src;
+ char ***dest;
+ int count;
+{
+ krb5_error_code st=0;
+ int i=0;
+
+ /* validate the input parameters */
+ if (src == NULL || dest == NULL)
+ return 0;
+
+ /* allocate memory for the dest array */
+ *dest = (char **) calloc((unsigned) count+1, sizeof(char *));
+ if (*dest == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+
+ /* copy the members from src to dest array. */
+ for (i=0; i < count && src[i] != NULL; ++i) {
+ (*dest)[i] = strdup(src[i]);
+ if ((*dest)[i] == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ }
+
+ cleanup:
+ /* in case of error free up everything and return */
+ if (st != 0) {
+ if (*dest != NULL) {
+ for(i=0; (*dest)[i]; ++i) {
+ free ((*dest)[i]);
+ (*dest)[i] = NULL;
+ }
+ free (*dest);
+ *dest = NULL;
+ }
+ }
+ return st;
+}
+
+static krb5_error_code
+getepochtime(strtime, epochtime)
+ char *strtime;
+ krb5_timestamp *epochtime;
+{
+ struct tm tme;
+
+ memset(&tme, 0, sizeof(tme));
+ if (strptime(strtime,"%Y%m%d%H%M%SZ", &tme) == NULL) {
+ *epochtime = 0;
+ return EINVAL;
+ }
+ *epochtime = krb5int_gmt_mktime(&tme);
+ return 0;
+}
+
+/*
+ * krb5_ldap_get_value() - get the integer value of the attribute
+ * Returns, 0 if the attribute is present, 1 if the attribute is missing.
+ * The retval is 0 if the attribute is missing.
+ */
+
+krb5_error_code
+krb5_ldap_get_value(ld, ent, attribute, retval)
+ LDAP *ld;
+ LDAPMessage *ent;
+ char *attribute;
+ int *retval;
+{
+ char **values=NULL;
+
+ *retval = 0;
+ values=ldap_get_values(ld, ent, attribute);
+ if (values != NULL) {
+ if (values[0] != NULL)
+ *retval = atoi(values[0]);
+ ldap_value_free(values);
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * krb5_ldap_get_string() - Returns the first string of the attribute. Intended to
+ *
+ *
+ */
+krb5_error_code
+krb5_ldap_get_string(ld, ent, attribute, retstr, attr_present)
+ LDAP *ld;
+ LDAPMessage *ent;
+ char *attribute;
+ char **retstr;
+ krb5_boolean *attr_present;
+{
+ char **values=NULL;
+ krb5_error_code st=0;
+
+ *retstr = NULL;
+ if (attr_present != NULL)
+ *attr_present = FALSE;
+
+ values=ldap_get_values(ld, ent, attribute);
+ if (values != NULL) {
+ if (values[0] != NULL) {
+ if (attr_present!= NULL)
+ *attr_present = TRUE;
+ *retstr = strdup(values[0]);
+ if (*retstr == NULL)
+ st = ENOMEM;
+ }
+ ldap_value_free(values);
+ }
+ return st;
+}
+
+krb5_error_code
+krb5_ldap_get_time(ld, ent, attribute, rettime, attr_present)
+ LDAP *ld;
+ LDAPMessage *ent;
+ char *attribute;
+ krb5_timestamp *rettime;
+ krb5_boolean *attr_present;
+{
+ char **values=NULL;
+ krb5_error_code st=0;
+
+ *rettime = 0;
+ *attr_present = FALSE;
+
+ values=ldap_get_values(ld, ent, attribute);
+ if (values != NULL) {
+ if (values[0] != NULL) {
+ *attr_present = TRUE;
+ st = getepochtime(values[0], rettime);
+ }
+ ldap_value_free(values);
+ }
+ return st;
+}
+
+/*
+ * Function to allocate, set the values of LDAPMod structure. The LDAPMod structure is then
+ * added to the array at the ind
+ */
+
+krb5_error_code
+krb5_add_member(mods, count)
+ LDAPMod ***mods;
+ int *count;
+{
+ int i=0;
+ LDAPMod **lmods=NULL;
+
+ if ((*mods) != NULL) {
+ for (;(*mods)[i] != NULL; ++i)
+ ;
+ }
+ lmods = (LDAPMod **) realloc((*mods), (2+i) * sizeof(LDAPMod *));
+ if (lmods == NULL)
+ return ENOMEM;
+
+ *mods = lmods;
+ (*mods)[i+1] = NULL;
+ (*mods)[i] = (LDAPMod *) calloc(1, sizeof (LDAPMod));
+ if ((*mods)[i] == NULL)
+ return ENOMEM;
+ *count = i;
+ return 0;
+}
+
+krb5_error_code
+krb5_add_str_mem_ldap_mod(mods, attribute, op, values)
+ LDAPMod ***mods;
+ char *attribute;
+ int op;
+ char **values;
+
+{
+ int i=0, j=0;
+ krb5_error_code st=0;
+
+ if ((st=krb5_add_member(mods, &i)) != 0)
+ return st;
+
+ (*mods)[i]->mod_type = strdup(attribute);
+ if ((*mods)[i]->mod_type == NULL)
+ return ENOMEM;
+ (*mods)[i]->mod_op = op;
+
+ if (values != NULL) {
+ for (j=0; values[j] != NULL; ++j)
+ ;
+ (*mods)[i]->mod_values = malloc (sizeof(char *) * (j+1));
+ if ((*mods)[i]->mod_values == NULL)
+ return ENOMEM;
+
+ for (j=0; values[j] != NULL; ++j) {
+ (*mods)[i]->mod_values[j] = strdup(values[j]);
+ if ((*mods)[i]->mod_values[j] == NULL)
+ return ENOMEM;
+ }
+ (*mods)[i]->mod_values[j] = NULL;
+ }
+ return 0;
+}
+
+krb5_error_code
+krb5_add_ber_mem_ldap_mod(mods, attribute, op, ber_values)
+ LDAPMod ***mods;
+ char *attribute;
+ int op;
+ struct berval **ber_values;
+
+{
+ int i=0, j=0;
+ krb5_error_code st=0;
+
+ if ((st=krb5_add_member(mods, &i)) != 0)
+ return st;
+
+ (*mods)[i]->mod_type = strdup(attribute);
+ if ((*mods)[i]->mod_type == NULL)
+ return ENOMEM;
+ (*mods)[i]->mod_op = op;
+
+ for (j=0; ber_values[j] != NULL; ++j)
+ ;
+ (*mods)[i]->mod_bvalues = malloc (sizeof(struct berval *) * (j+1));
+ if ((*mods)[i]->mod_bvalues == NULL)
+ return ENOMEM;
+
+ for (j=0; ber_values[j] != NULL; ++j) {
+ (*mods)[i]->mod_bvalues[j] = calloc(1, sizeof(struct berval));
+ if ((*mods)[i]->mod_bvalues[j] == NULL)
+ return ENOMEM;
+
+ (*mods)[i]->mod_bvalues[j]->bv_len = ber_values[j]->bv_len;
+ (*mods)[i]->mod_bvalues[j]->bv_val = malloc((*mods)[i]->mod_bvalues[j]->bv_len);
+ if ((*mods)[i]->mod_bvalues[j]->bv_val == NULL)
+ return ENOMEM;
+
+ memcpy((*mods)[i]->mod_bvalues[j]->bv_val, ber_values[j]->bv_val,
+ ber_values[j]->bv_len);
+ }
+ (*mods)[i]->mod_bvalues[j] = NULL;
+ return 0;
+}
+
+static inline char *
+format_d (int val)
+{
+ char tmpbuf[2+3*sizeof(val)];
+ sprintf(tmpbuf, "%d", val);
+ return strdup(tmpbuf);
+}
+
+krb5_error_code
+krb5_add_int_arr_mem_ldap_mod(mods, attribute, op, value)
+ LDAPMod ***mods;
+ char *attribute;
+ int op;
+ int *value;
+
+{
+ int i=0, j=0;
+ krb5_error_code st=0;
+
+ if ((st=krb5_add_member(mods, &i)) != 0)
+ return st;
+
+ (*mods)[i]->mod_type = strdup(attribute);
+ if ((*mods)[i]->mod_type == NULL)
+ return ENOMEM;
+ (*mods)[i]->mod_op = op;
+
+ for (j=0; value[j] != -1; ++j)
+ ;
+
+ (*mods)[i]->mod_values = malloc(sizeof(char *) * (j+1));
+
+ for (j=0; value[j] != -1; ++j) {
+ if (((*mods)[i]->mod_values[j] = format_d(value[j])) == NULL)
+ return ENOMEM;
+ }
+ (*mods)[i]->mod_values[j] = NULL;
+ return 0;
+}
+
+krb5_error_code
+krb5_add_int_mem_ldap_mod(mods, attribute, op, value)
+ LDAPMod ***mods;
+ char *attribute;
+ int op;
+ int value;
+
+{
+ int i=0;
+ krb5_error_code st=0;
+
+ if ((st=krb5_add_member(mods, &i)) != 0)
+ return st;
+
+ (*mods)[i]->mod_type = strdup(attribute);
+ if ((*mods)[i]->mod_type == NULL)
+ return ENOMEM;
+
+ (*mods)[i]->mod_op = op;
+ (*mods)[i]->mod_values = calloc (2, sizeof(char *));
+ if (((*mods)[i]->mod_values[0] = format_d(value)) == NULL)
+ return ENOMEM;
+ return 0;
+}
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.h b/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.h
new file mode 100644
index 000000000..d15b7c70f
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.h
@@ -0,0 +1,125 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_misc.h
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _HAVE_LDAP_MISC_H
+#define _HAVE_LDAP_MISC_H 1
+
+#include "ldap_services.h"
+
+/* misc functions */
+
+krb5_error_code
+updateAttribute (LDAP *, char *, char *, char *);
+
+krb5_error_code
+deleteAttribute (LDAP *, char *, char *, char *);
+
+krb5_error_code
+populateServers(LDAP *, char **, char ***, char *, char **);
+
+krb5_error_code
+disjoint_members(char **, char **);
+
+krb5_error_code
+is_principal_in_realm(krb5_ldap_context *, krb5_const_principal);
+
+krb5_error_code
+checkattributevalue(LDAP *, char *, char *, char **, int *);
+
+krb5_error_code
+krb5_get_attributes_mask(krb5_context, krb5_db_entry *, int *);
+
+krb5_error_code
+krb5_get_princ_type(krb5_context, krb5_db_entry *, int *);
+
+krb5_error_code
+krb5_get_princ_count(krb5_context, krb5_db_entry *, int *);
+
+krb5_error_code
+krb5_get_secretkeys(krb5_context, krb5_db_entry *, KEY **);
+
+krb5_error_code
+krb5_get_userdn(krb5_context, krb5_db_entry *, char **);
+
+krb5_error_code
+krb5_get_containerdn(krb5_context, krb5_db_entry *, char **);
+
+krb5_error_code
+store_tl_data(krb5_tl_data *, int, void *);
+
+krb5_error_code
+decode_tl_data(krb5_tl_data *, int, void **);
+
+krb5_error_code
+is_principal_in_realm(krb5_ldap_context *, krb5_const_principal);
+
+krb5_error_code
+krb5_get_subtree_info(krb5_ldap_context *, char **, unsigned int *);
+
+krb5_error_code
+krb5_ldap_read_server_params(krb5_context , char *, int);
+
+krb5_error_code
+krb5_ldap_free_server_params(krb5_ldap_context *);
+
+krb5_error_code
+copy_arrays(char **, char ***, int);
+
+krb5_error_code
+krb5_ldap_list(krb5_context, char ***, char *, char *);
+
+krb5_error_code
+krb5_ldap_get_value(LDAP *, LDAPMessage *, char *, int *);
+
+krb5_error_code
+krb5_ldap_get_string(LDAP *, LDAPMessage *, char *, char **, krb5_boolean *);
+
+krb5_error_code
+krb5_ldap_get_time(LDAP *, LDAPMessage *, char *, krb5_timestamp *, krb5_boolean *);
+
+krb5_error_code
+krb5_add_member(LDAPMod ***, int *);
+
+krb5_error_code
+krb5_add_str_mem_ldap_mod(LDAPMod ***, char *, int, char **);
+
+krb5_error_code
+krb5_add_ber_mem_ldap_mod(LDAPMod ***, char *, int, struct berval **);
+
+krb5_error_code
+krb5_add_int_arr_mem_ldap_mod(LDAPMod ***, char *, int, int *);
+
+krb5_error_code
+krb5_add_int_mem_ldap_mod(LDAPMod ***, char *, int , int);
+
+krb5_error_code
+krb5_ldap_free_mod_array(LDAPMod **);
+
+#endif
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
new file mode 100644
index 000000000..15dcd8dc7
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
@@ -0,0 +1,514 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_principal.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ldap_main.h"
+#include "kdb_ldap.h"
+#include "ldap_principal.h"
+#include "princ_xdr.h"
+#include "ldap_err.h"
+
+struct timeval timelimit = {300, 0}; /* 5 minutes */
+char *principal_attributes[] = { "krbprincipalname",
+ "objectclass",
+ "krbsecretkey",
+ "krbmaxrenewableage",
+ "krbmaxticketlife",
+ "krbticketflags",
+ "krbprincipalexpiration",
+ "krbpolicyreference",
+ "krbUpEnabled",
+ "krbpwdpolicyreference",
+ "krbpasswordexpiration",
+#ifdef HAVE_EDIRECTORY
+ "loginexpirationtime",
+ "logindisabled",
+#endif
+ "loginexpirationtime",
+ "logindisabled",
+ "modifiersname",
+ "modifytimestamp",
+ NULL };
+
+static char *attributes_set[] = { "krbmaxrenewableage",
+ "krbmaxticketlife",
+ "krbticketflags",
+ "krbprincipalexpiration",
+ "krbpolicyreference",
+ "krbUpEnabled",
+ "krbpwdpolicyreference",
+ "krbpasswordexpiration",
+ "krbsecretkey",
+ NULL };
+
+void
+krb5_dbe_free_contents(context, entry)
+ krb5_context context;
+ krb5_db_entry *entry;
+{
+ krb5_tl_data *tl_data_next=NULL;
+ krb5_tl_data *tl_data=NULL;
+ int i, j;
+
+ if (entry->e_data)
+ free(entry->e_data);
+ if (entry->princ)
+ krb5_free_principal(context, entry->princ);
+ for (tl_data = entry->tl_data; tl_data; tl_data = tl_data_next) {
+ tl_data_next = tl_data->tl_data_next;
+ if (tl_data->tl_data_contents)
+ free(tl_data->tl_data_contents);
+ free(tl_data);
+ }
+ if (entry->key_data) {
+ for (i = 0; i < entry->n_key_data; i++) {
+ for (j = 0; j < entry->key_data[i].key_data_ver; j++) {
+ if (entry->key_data[i].key_data_length[j]) {
+ if (entry->key_data[i].key_data_contents[j]) {
+ memset(entry->key_data[i].key_data_contents[j],
+ 0,
+ (unsigned) entry->key_data[i].key_data_length[j]);
+ free (entry->key_data[i].key_data_contents[j]);
+ }
+ }
+ entry->key_data[i].key_data_contents[j] = NULL;
+ entry->key_data[i].key_data_length[j] = 0;
+ entry->key_data[i].key_data_type[j] = 0;
+ }
+ }
+ free(entry->key_data);
+ }
+ memset(entry, 0, sizeof(*entry));
+ return;
+}
+
+
+krb5_error_code
+krb5_ldap_free_principal(kcontext , entries, nentries)
+ krb5_context kcontext;
+ krb5_db_entry *entries;
+ int nentries;
+{
+ register int i;
+ for (i = 0; i < nentries; i++)
+ krb5_dbe_free_contents(kcontext, &entries[i]);
+ return 0;
+}
+
+
+krb5_error_code
+krb5_ldap_iterate(context, match_expr, func, func_arg)
+ krb5_context context;
+ char *match_expr;
+ krb5_error_code (*func) (krb5_pointer, krb5_db_entry *);
+ krb5_pointer func_arg;
+{
+ krb5_db_entry entry;
+ krb5_principal principal;
+ char *subtree[2]={NULL}, *princ_name=NULL, *realm=NULL, **values=NULL, *filter=NULL;
+ char *krbprincipal_attr[] = { "krbPrincipalName", NULL };
+ unsigned int filterlen=0, tree=0, ntree=1, i=0;
+ krb5_error_code st=0, tempst=0;
+ LDAP *ld=NULL;
+ LDAPMessage *result=NULL, *ent=NULL;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+
+ /* Clear the global error string */
+ krb5_clear_error_message(context);
+
+ memset(&entry, 0, sizeof(krb5_db_entry));
+ SETUP_CONTEXT();
+
+ realm = ldap_context->lrparams->realm_name;
+ if (realm == NULL) {
+ realm = context->default_realm;
+ if (realm == NULL) {
+ st = EINVAL;
+ krb5_set_error_message(context, st, "Default realm not set");
+ goto cleanup;
+ }
+ }
+
+ filterlen = strlen(FILTER) + strlen(match_expr) + 2 + 1; /* 2 for closing brackets */
+ filter = malloc (filterlen);
+ CHECK_NULL(filter);
+ memset(filter, 0, filterlen);
+ sprintf(filter, FILTER"%s))", match_expr);
+
+ if ((st = krb5_get_subtree_info(ldap_context, subtree, &ntree)) != 0)
+ goto cleanup;
+
+ GET_HANDLE();
+
+ for (tree=0; tree<ntree; ++tree) {
+
+ LDAP_SEARCH(subtree[tree], ldap_context->lrparams->search_scope, filter, krbprincipal_attr);
+ for(ent=ldap_first_entry(ld, result); ent != NULL; ent=ldap_next_entry(ld, ent)) {
+ if ((values=ldap_get_values(ld, ent, "krbprincipalname")) != NULL) {
+ for(i=0; values[i] != NULL; ++i) {
+ if (krb5_ldap_parse_principal_name(values[i], &princ_name) != 0)
+ continue;
+ if (krb5_parse_name(context, princ_name, &principal) != 0)
+ continue;
+ if (is_principal_in_realm(ldap_context, principal) == 0) {
+ entry.princ = principal;
+ (*func)(func_arg, &entry);
+ }
+ krb5_free_principal(context, principal);
+ if (princ_name)
+ free(princ_name);
+ }
+ ldap_value_free(values);
+ }
+ } /* end of for(ent= ... */
+ ldap_msgfree(result);
+ } /* end of for(tree= ... */
+
+ cleanup:
+ if (filter)
+ free (filter);
+
+ for ( ;ntree; --ntree)
+ if (subtree[ntree-1])
+ free (subtree[ntree-1]);
+
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
+
+
+/*
+ * delete a principal from the directory.
+ */
+krb5_error_code
+krb5_ldap_delete_principal(context, searchfor, nentries)
+ krb5_context context;
+ krb5_const_principal searchfor;
+ int *nentries; /* how many found & deleted */
+{
+ char *user=NULL, *DN=NULL, *strval[10] = {NULL};
+ LDAPMod **mods=NULL;
+ LDAP *ld=NULL;
+ int j=0, ptype=KDB_USER_PRINCIPAL, pcount=0, attrsetmask=0;
+ krb5_error_code st=0;
+ krb5_boolean singleentry=FALSE;
+ KEY *secretkey=NULL;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+ krb5_db_entry entries;
+ krb5_boolean more=0;
+ char * policydn = NULL;
+
+ /* Clear the global error string */
+ krb5_clear_error_message(context);
+
+ SETUP_CONTEXT();
+ /* get the principal info */
+ if ((st=krb5_ldap_get_principal(context, searchfor, &entries, nentries, &more)) != 0 || *nentries == 0)
+ goto cleanup;
+
+ if (((st=krb5_get_princ_type(context, &entries, &(ptype))) != 0) ||
+ ((st=krb5_get_attributes_mask(context, &entries, &(attrsetmask))) != 0) ||
+ ((st=krb5_get_princ_count(context, &entries, &(pcount))) != 0) ||
+ ((st=krb5_get_userdn(context, &entries, &(DN))) != 0) ||
+ ((st=krb5_get_policydn(context, &entries, &policydn)) != 0) ||
+ ((st=krb5_get_secretkeys(context, &entries, &secretkey)) != 0))
+ goto cleanup;
+
+ if (DN == NULL) {
+ st = EINVAL;
+ krb5_set_error_message(context, st, "DN information missing");
+ goto cleanup;
+ }
+
+ GET_HANDLE();
+
+ if (ptype == KDB_USER_PRINCIPAL) {
+
+ if(((st=krb5_unparse_name(context, searchfor, &user)) != 0)
+ || ((st=krb5_ldap_unparse_principal_name(user)) != 0))
+ goto cleanup;
+
+ memset(strval, 0, sizeof(strval));
+ strval[0] = user;
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbprincipalname", LDAP_MOD_DELETE,
+ strval)) != 0)
+ goto cleanup;
+
+ singleentry = (pcount == 1) ? TRUE: FALSE;
+ if (singleentry == FALSE) {
+ if (secretkey != NULL) {
+ if ((st=krb5_add_ber_mem_ldap_mod(&mods, "krbsecretkey", LDAP_MOD_DELETE | LDAP_MOD_BVALUES,
+ secretkey->keys)) != 0)
+ goto cleanup;
+ }
+ } else {
+ /*
+ * If the Kerberos user principal to be deleted happens to be the last one associated
+ * with the directory user object, then it is time to delete the other kerberos
+ * specific attributes like krbmaxticketlife, i.e, unkerberize the directory user.
+ * From the attrsetmask value, identify the attributes set on the directory user
+ * object and delete them.
+ * NOTE: krbsecretkey attribute has per principal entries. There can be chances that the
+ * other principals' keys are exisiting/left-over. So delete all the values.
+ */
+ while (attrsetmask) {
+ if (attrsetmask & 1) {
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, attributes_set[j], LDAP_MOD_DELETE,
+ NULL)) != 0)
+ goto cleanup;
+ }
+ attrsetmask >>= 1;
+ ++j;
+ }
+ if(policydn != NULL)
+ {
+ if ((st = krb5_ldap_change_count(context, policydn,2 )))
+ goto cleanup;
+
+ }
+
+ /* the same should be done with the objectclass attributes */
+ {
+ char *attrvalues[] = {"krbpwdpolicyrefaux", "krbpolicyaux", "krbprincipalaux", NULL};
+ int p, q, r=0, amask=0;
+
+ if ((st=checkattributevalue(ld, DN, "objectclass", attrvalues, &amask)) != 0)
+ goto cleanup;
+ memset(strval, 0, sizeof(strval));
+ for(p=1, q=0; p<=4; p<<=1, ++q)
+ if (p & amask)
+ strval[r++] = attrvalues[q];
+ strval[r] = NULL;
+ if (r > 0) {
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_DELETE,
+ strval)) != 0)
+ goto cleanup;
+ }
+ }
+ }
+ st=ldap_modify_s(ld, DN, mods);
+ if (st != LDAP_SUCCESS) {
+ st = set_ldap_error(context, st, OP_MOD);
+ goto cleanup;
+ }
+ }
+ else if (ptype == KDB_SERVICE_PRINCIPAL) {
+ st = ldap_delete_s(ld, DN);
+ if (st != LDAP_SUCCESS) {
+ st = set_ldap_error (context, st, OP_DEL);
+ goto cleanup;
+ }
+ }
+
+ cleanup:
+ if (user)
+ free (user);
+
+ if (DN)
+ free (DN);
+
+ if (secretkey != NULL) {
+ int i=0;
+ while (i < secretkey->nkey) {
+ free (secretkey->keys[i]->bv_val);
+ free (secretkey->keys[i]);
+ ++i;
+ }
+ free (secretkey->keys);
+ free (secretkey);
+ }
+
+ if (st == 0)
+ krb5_ldap_free_principal(context, &entries, *nentries);
+
+ ldap_mods_free(mods, 1);
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
+
+
+/*
+ * Function: krb5_ldap_unparse_principal_name
+ *
+ * Purpose: Removes '\\' that comes before every occurence of '@'
+ * in the principal name component.
+ *
+ * Arguments:
+ * user_name (input/output) Principal name
+ *
+ */
+
+krb5_error_code
+krb5_ldap_unparse_principal_name(char *user_name)
+{
+ char *tmp_princ_name=NULL, *princ_name=NULL, *tmp=NULL;
+ int l=0;
+ krb5_error_code st=0;
+
+ if(strstr(user_name, "\\@"))
+ {
+
+ tmp_princ_name = strdup(user_name);
+ if( !tmp_princ_name )
+ {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ tmp = tmp_princ_name;
+
+ princ_name = (char *) malloc (strlen(user_name));
+ if( !princ_name )
+ {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ memset(princ_name, 0, strlen(user_name));
+
+ l = 0;
+ while(*tmp_princ_name)
+ {
+ if((*tmp_princ_name == '\\') && (*(tmp_princ_name+1) == '@'))
+ {
+ tmp_princ_name += 1;
+ }
+ else
+ {
+ *(princ_name + l) = *tmp_princ_name++;
+ l++;
+ }
+ }
+
+ memset(user_name, 0, strlen(user_name));
+ sprintf(user_name, "%s", princ_name);
+ }
+
+ cleanup:
+ if (tmp) {
+ free(tmp);
+ tmp = NULL;
+ }
+
+ if (princ_name) {
+ free(princ_name);
+ princ_name = NULL;
+ }
+
+ return st;
+}
+
+
+/*
+ * Function: krb5_ldap_parse_principal_name
+ *
+ * Purpose: Inserts '\\' before every occurence of '@'
+ * in the principal name component.
+ *
+ * Arguments:
+ * i_princ_name (input) Principal name without '\\'
+ * o_princ_name (output) Principal name with '\\'
+ *
+ * Note: The caller has to free the memory allocated for o_princ_name.
+ */
+
+krb5_error_code
+krb5_ldap_parse_principal_name(i_princ_name, o_princ_name)
+ char *i_princ_name;
+ char **o_princ_name;
+{
+ char *tmp_princ_name = NULL, *princ_name = NULL, *at_rlm_name = NULL;
+ int l = 0, m = 0, tmp_princ_name_len = 0, princ_name_len = 0, at_count = 0;
+ krb5_error_code st = 0;
+
+ at_rlm_name = strrchr(i_princ_name, '@');
+
+ if(!at_rlm_name)
+ {
+ *o_princ_name = strdup(i_princ_name);
+ if( !o_princ_name )
+ {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ }
+ else
+ {
+ tmp_princ_name_len = at_rlm_name - i_princ_name;
+
+ tmp_princ_name = (char *) malloc ((unsigned) tmp_princ_name_len + 1);
+ if( !tmp_princ_name )
+ {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ memset(tmp_princ_name, 0, (unsigned) tmp_princ_name_len + 1);
+ memcpy( tmp_princ_name, i_princ_name, (unsigned) tmp_princ_name_len);
+
+ l = 0;
+ while(tmp_princ_name[l])
+ {
+ if(tmp_princ_name[l++] == '@')
+ at_count++;
+ }
+
+ princ_name_len = strlen(i_princ_name) + at_count + 1;
+ princ_name = (char *) malloc ((unsigned) princ_name_len);
+ if( !princ_name )
+ {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ memset(princ_name, 0, (unsigned) princ_name_len);
+
+ l = 0;
+ m = 0;
+ while(tmp_princ_name[l])
+ {
+ if(tmp_princ_name[l] == '@'){
+ princ_name[m++]='\\';
+ }
+ princ_name[m++]=tmp_princ_name[l++];
+ }
+ strcat(princ_name, at_rlm_name);
+
+ *o_princ_name = princ_name;
+ }
+
+ cleanup:
+
+ if (tmp_princ_name) {
+ free(tmp_princ_name);
+ tmp_princ_name = NULL;
+ }
+
+ return st;
+}
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.h b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.h
new file mode 100644
index 000000000..65224c8d3
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.h
@@ -0,0 +1,126 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_principal.h
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LDAP_PRINCIPAL_H
+#define _LDAP_PRINCIPAL_H 1
+
+#include "ldap_tkt_policy.h"
+
+#define KEYHEADER 12
+
+#define NOOFKEYS(ptr) ((ptr[10]<<8) | ptr[11])
+
+#define PRINCIPALLEN(ptr) ((ptr[0]<<8) | ptr[1])
+#define PRINCIPALNAME(ptr) (ptr + KEYHEADER + (NOOFKEYS(ptr) *8))
+
+#define KEYBODY(ptr) PRINCIPALNAME(ptr) + PRINCIPALLEN(ptr)
+
+#define PKEYVER(ptr) ((ptr[2]<<8) | ptr[3])
+#define MKEYVER(ptr) ((ptr[4]<<8) | ptr[5])
+
+#define KEYTYPE(ptr,j) ((ptr[KEYHEADER+(j*8)]<<8) | ptr[KEYHEADER+1+(j*8)])
+#define KEYLENGTH(ptr,j) ((ptr[KEYHEADER+2+(j*8)]<<8) | ptr[KEYHEADER+3+(j*8)])
+#define SALTTYPE(ptr,j) ((ptr[KEYHEADER+4+(j*8)]<<8) | ptr[KEYHEADER+5+(j*8)])
+#define SALTLENGTH(ptr,j) ((ptr[KEYHEADER+6+(j*8)]<<8) | ptr[KEYHEADER+7+(j*8)])
+
+#define MAX_KEY_LENGTH 1024
+#define CONTAINERDN_ARG "containerdn"
+#define USERDN_ARG "userdn"
+#define TKTPOLICYDN_ARG "tktpolicydn"
+
+#define FILTER "(&(objectclass=krbprincipalaux)(krbprincipalname="
+#define KDB_USER_PRINCIPAL 0x01
+#define KDB_SERVICE_PRINCIPAL 0x02
+
+/* krb5_db_entry */
+#define KDB_PRINCIPAL 0x000001
+#define KDB_PRINC_EXPIRE_TIME 0x000002
+#define KDB_PW_EXPIRATION 0x000004
+#define KDB_LAST_PWD_CHANGE 0x000008
+#define KDB_ATTRIBUTES 0x000010
+#define KDB_MAX_LIFE 0x000020
+#define KDB_MOD_TIME 0x000040
+#define KDB_MOD_NAME 0x000080
+#define KDB_KVNO 0x000100
+#define KDB_MKVNO 0x000200
+#define KDB_AUX_ATTRIBUTES 0x000400
+#define KDB_POLICY 0x000800
+#define KDB_POLICY_CLR 0x001000
+#define KDB_MAX_RLIFE 0x002000
+#define KDB_LAST_SUCCESS 0x004000
+#define KDB_LAST_FAILED 0x008000
+#define KDB_FAIL_AUTH_COUNT 0x010000
+#define KDB_KEY_DATA 0x020000
+#define KDB_TL_DATA 0x040000
+#define KDB_CPW_FUNCTION 0x080000
+#define KDB_RANDKEY_USED 0x100000
+
+/* these will be consumed only by krb5_ldap_delete_principal*/
+/* these will be set by krb5_ldap_get_principal and fed into the tl_data */
+
+#define KDB_MAX_LIFE_ATTR 0x000001
+#define KDB_MAX_RLIFE_ATTR 0x000002
+#define KDB_TKT_FLAGS_ATTR 0x000004
+#define KDB_PRINC_EXPIRE_TIME_ATTR 0x000008
+#define KDB_POL_REF_ATTR 0x000010
+#define KDB_UP_FLAG_ATTR 0x000020
+#define KDB_PWD_POL_REF_ATTR 0x000040
+#define KDB_PWD_EXPIRE_TIME_ATTR 0x000080
+#define KDB_SECRET_KEY 0x000100
+extern struct timeval timeout;
+extern char *policyclass[];
+
+krb5_error_code
+krb5_ldap_put_principal(krb5_context, krb5_db_entry *, int *, char **);
+
+krb5_error_code
+krb5_ldap_get_principal(krb5_context , krb5_const_principal ,
+ krb5_db_entry *,int *, krb5_boolean *);
+
+krb5_error_code
+krb5_ldap_delete_principal(krb5_context, krb5_const_principal, int *);
+
+krb5_error_code
+krb5_ldap_free_principal(krb5_context, krb5_db_entry *, int );
+
+krb5_error_code
+krb5_ldap_iterate(krb5_context, char *, krb5_error_code (*) (krb5_pointer, krb5_db_entry *),
+ krb5_pointer/*, int */);
+
+void
+krb5_dbe_free_contents(krb5_context, krb5_db_entry *);
+
+krb5_error_code
+krb5_ldap_unparse_principal_name(char *);
+
+krb5_error_code
+krb5_ldap_parse_principal_name(char *, char **);
+
+#endif
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
new file mode 100644
index 000000000..6509ff9e7
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
@@ -0,0 +1,1296 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_principal2.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <time.h>
+#include "ldap_main.h"
+#include "kdb_ldap.h"
+#include "ldap_principal.h"
+#include "princ_xdr.h"
+#include "ldap_tkt_policy.h"
+#include "ldap_pwd_policy.h"
+#include "ldap_err.h"
+
+extern char* principal_attributes[];
+extern char* max_pwd_life_attr[];
+#if !defined( LDAP_OPT_RESULT_CODE) && defined(LDAP_OPT_ERROR_NUMBER)
+#define LDAP_OPT_RESULT_CODE LDAP_OPT_ERROR_NUMBER
+#endif
+
+static krb5_error_code
+krb5_decode_krbsecretkey(krb5_context, krb5_db_entry *, struct berval **, krb5_tl_data *);
+
+static krb5_error_code
+krb5_read_tkt_policyreference(krb5_context, krb5_ldap_context *, krb5_db_entry *, char *);
+
+static char *
+getstringtime(krb5_timestamp );
+
+/*
+ * look up a principal in the directory.
+ */
+
+krb5_error_code
+krb5_ldap_get_principal(context, searchfor, entries, nentries, more)
+ krb5_context context;
+ krb5_const_principal searchfor;
+ krb5_db_entry *entries; /* filled in */
+ int *nentries; /* how much room/how many found */
+ krb5_boolean *more; /* are there more? */
+{
+ char *user=NULL, *DN=NULL, *filter=NULL, *subtree[2]={NULL};
+ unsigned int tree=0, ntrees=1, mask=0, princlen=0;
+ krb5_error_code tempst=0, st=0;
+ char **values=NULL, *policydn=NULL, *pwdpolicydn=NULL, *modname=NULL;
+ krb5_tl_data userinfo_tl_data={0};
+ krb5_timestamp modtime=0;
+ struct berval **bvalues=NULL;
+ LDAP *ld=NULL;
+ LDAPMessage *result=NULL, *ent=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+ krb5_principal parsed_mod_name=NULL;
+ krb5_boolean attr_present=FALSE;
+
+ /* Clear the global error string */
+ krb5_clear_error_message(context);
+
+ /* set initial values */
+ *nentries = 0;
+ *more = 0;
+ memset(entries, 0, sizeof(*entries));
+
+ if (searchfor == NULL)
+ return EINVAL;
+
+ dal_handle = (kdb5_dal_handle *) context->db_context;
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+
+ CHECK_LDAP_HANDLE(ldap_context);
+
+ if (is_principal_in_realm(ldap_context, searchfor) != 0) {
+ *more = 0;
+ krb5_set_error_message (context, st, "Principal does not belong to realm");
+ goto cleanup;
+ }
+
+ if ((st=krb5_unparse_name(context, searchfor, &user)) != 0)
+ goto cleanup;
+
+ if ((st=krb5_ldap_unparse_principal_name(user)) != 0)
+ goto cleanup;
+
+ princlen = strlen(FILTER) + strlen(user) + 2 + 1; /* 2 for closing brackets */
+ if ((filter=malloc(princlen)) == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ snprintf(filter, princlen, FILTER"%s))", user);
+
+ if ((st = krb5_get_subtree_info(ldap_context, subtree, &ntrees)) != 0)
+ goto cleanup;
+
+ GET_HANDLE();
+ for (tree=0; tree<ntrees && *nentries==0; ++tree) {
+
+ LDAP_SEARCH(subtree[tree], ldap_context->lrparams->search_scope, filter, principal_attributes);
+ for (ent=ldap_first_entry(ld, result); ent != NULL && *nentries == 0; ent=ldap_next_entry(ld, ent)) {
+
+ /* get the associated directory user information */
+ if ((values=ldap_get_values(ld, ent, "krbprincipalname")) != NULL) {
+ int i=0, pcount=0, ptype=KDB_USER_PRINCIPAL;
+
+ /* a wild-card in a principal name can return a list of kerberos principals.
+ * Make sure that the correct principal is returned.
+ * NOTE: a principalname k* in ldap server will return all the principals starting with a k
+ */
+ for (i=0; values[i] != NULL; ++i) {
+ if (strcasecmp(values[i], user) == 0) {
+ *nentries = 1;
+ pcount = ldap_count_values(values);
+ break;
+ }
+ }
+ ldap_value_free(values);
+
+ if (*nentries == 0) /* no matching principal found */
+ continue;
+
+ if ((DN = ldap_get_dn(ld, ent)) == NULL) {
+ ldap_get_option (ld, LDAP_OPT_RESULT_CODE, &st);
+ st = set_ldap_error (context, st, 0);
+ goto cleanup;
+ }
+
+ if ((values=ldap_get_values(ld, ent, "objectclass")) != NULL) {
+ for(i=0; values[i] != NULL; ++i)
+ if (strcasecmp(values[i], "krbprincipal") == 0) {
+ ptype = KDB_SERVICE_PRINCIPAL;
+ break;
+ }
+ ldap_value_free(values);
+ }
+
+ /* add principalcount, DN and principaltype user information to tl_data */
+ if (((st=store_tl_data(&userinfo_tl_data, KDB_TL_PRINCCOUNT, &pcount)) != 0) ||
+ ((st=store_tl_data(&userinfo_tl_data, KDB_TL_USERDN, DN)) != 0) ||
+ ((st=store_tl_data(&userinfo_tl_data, KDB_TL_PRINCTYPE, &ptype)) != 0))
+ goto cleanup;
+ }
+
+ /* populate entries->princ with searchfor value */
+ if ((st=krb5_copy_principal(context, searchfor, &(entries->princ))) != 0)
+ goto cleanup;
+
+ /* read all the kerberos attributes */
+
+ /* KRBMAXTICKETLIFE */
+ if (krb5_ldap_get_value(ld, ent, "krbmaxticketlife", &(entries->max_life)) == 0)
+ mask |= KDB_MAX_LIFE_ATTR;
+
+ /* KRBMAXRENEWABLEAGE */
+ if (krb5_ldap_get_value(ld, ent, "krbmaxrenewableage", &(entries->max_renewable_life)) == 0)
+ mask |= KDB_MAX_RLIFE_ATTR;
+
+ /* KRBTICKETFLAGS */
+ if (krb5_ldap_get_value(ld, ent, "krbticketflags", &(entries->attributes)) == 0)
+ mask |= KDB_TKT_FLAGS_ATTR;
+
+ /* PRINCIPAL EXPIRATION TIME */
+ if ((st=krb5_ldap_get_time(ld, ent, "krbprincipalexpiration", &(entries->expiration),
+ &attr_present)) != 0)
+ goto cleanup;
+ if (attr_present == TRUE)
+ mask |= KDB_PRINC_EXPIRE_TIME_ATTR;
+
+ /* PASSWORD EXPIRATION TIME */
+ if ((st=krb5_ldap_get_time(ld, ent, "krbpasswordexpiration", &(entries->pw_expiration),
+ &attr_present)) != 0)
+ goto cleanup;
+ if (attr_present == TRUE)
+ mask |= KDB_PWD_EXPIRE_TIME_ATTR;
+
+ /* KRBPOLICYREFERENCE */
+
+ if ((st=krb5_ldap_get_string(ld, ent, "krbpolicyreference", &policydn, &attr_present)) != 0)
+ goto cleanup;
+
+ if(attr_present == TRUE){
+ if ((st=store_tl_data(&userinfo_tl_data, KDB_TL_TKTPOLICYDN, policydn)) != 0)
+ goto cleanup;
+ }
+ if(!(mask & KDB_MAX_LIFE_ATTR) && !(mask & KDB_MAX_RLIFE_ATTR) && !(mask & KDB_TKT_FLAGS_ATTR)){
+ if (attr_present == TRUE)
+ mask |= KDB_POL_REF_ATTR;
+ }
+
+ /* KRBPWDPOLICYREFERENCE */
+ if ((st=krb5_ldap_get_string(ld, ent, "krbpwdpolicyreference", &pwdpolicydn, &attr_present)) != 0)
+ goto cleanup;
+ if (attr_present == TRUE) {
+ krb5_tl_data kadm_tl_data;
+
+ mask |= KDB_PWD_POL_REF_ATTR;
+ if((st = krb5_update_tl_kadm_data(pwdpolicydn, &kadm_tl_data)) != 0){
+ goto cleanup;
+ }
+ krb5_dbe_update_tl_data(context, entries, &kadm_tl_data);
+ }
+
+ /* KRBSECRETKEY */
+ if((bvalues=ldap_get_values_len(ld, ent, "krbsecretkey")) != NULL) {
+ mask |= KDB_SECRET_KEY;
+ if ((st=krb5_decode_krbsecretkey(context, entries, bvalues, &userinfo_tl_data)) != 0)
+ goto cleanup;
+ }
+
+ /* MODIFY TIMESTAMP */
+ if ((st=krb5_ldap_get_time(ld, ent, "modifytimestamp", &modtime, &attr_present)) != 0)
+ goto cleanup;
+
+ /* MODIFIER'S NAME */
+ if ((st=krb5_ldap_get_string(ld, ent, "modifiersname", &modname, &attr_present)) != 0)
+ goto cleanup;
+ if (attr_present == TRUE) {
+ if ((st=krb5_parse_name(context, modname, &parsed_mod_name)) != 0)
+ goto cleanup;
+
+ if ((st=krb5_dbe_update_mod_princ_data(context, entries, modtime, parsed_mod_name)) != 0)
+ goto cleanup;
+ }
+
+ /* update the mask of attributes present on the directory object to the tl_data */
+ if ((st=store_tl_data(&userinfo_tl_data, KDB_TL_MASK, &mask)) != 0)
+ goto cleanup;
+ if ((st=krb5_dbe_update_tl_data(context, entries, &userinfo_tl_data)) != 0)
+ goto cleanup;
+
+#ifdef HAVE_EDIRECTORY
+ {
+ krb5_timestamp expiretime=0;
+ char *is_login_disabled=NULL;
+
+ /* LOGIN EXPIRATION TIME */
+ if ((st=krb5_ldap_get_time(ld, ent, "loginexpirationtime", &expiretime,
+ &attr_present)) != 0)
+ goto cleanup;
+
+ if (attr_present == TRUE) {
+ if ((mask & KDB_PRINC_EXPIRE_TIME_ATTR) == 1) {
+ if (expiretime < entries->expiration)
+ entries->expiration = expiretime;
+ } else {
+ entries->expiration = expiretime;
+ }
+ }
+
+ /* LOGIN DISABLED */
+ if ((st=krb5_ldap_get_string(ld, ent, "logindisabled", &is_login_disabled, &attr_present)) != 0)
+ goto cleanup;
+ if (attr_present == TRUE) {
+ if (strcasecmp(is_login_disabled,"TRUE")== 0)
+ entries->attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
+ free (is_login_disabled);
+ }
+ }
+#endif
+ }
+ ldap_msgfree(result);
+ result = NULL;
+ } /* for(tree=0 ... */
+
+ /* once done, put back the ldap handle */
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ ldap_server_handle = NULL;
+
+ /* if principal not found */
+ if (*nentries == 0)
+ goto cleanup;
+
+ if ((st=krb5_read_tkt_policyreference(context, ldap_context, entries, policydn)) !=0)
+ goto cleanup;
+
+ if (pwdpolicydn) {
+ osa_policy_ent_t pwdpol;
+ int cnt=0;
+ krb5_timestamp last_pw_changed;
+ krb5_ui_4 pw_max_life;
+
+ memset(&pwdpol, 0, sizeof(pwdpol));
+
+ if ((st=krb5_ldap_get_password_policy(context, pwdpolicydn, &pwdpol, &cnt)) != 0)
+ goto cleanup;
+ pw_max_life = pwdpol->pw_max_life;
+ free (pwdpol);
+
+ if (pw_max_life > 0) {
+ if ((st=krb5_dbe_lookup_last_pwd_change(context, entries, &last_pw_changed)) != 0)
+ goto cleanup;
+
+ if ((mask & KDB_PWD_EXPIRE_TIME_ATTR) == 1) {
+ if ((last_pw_changed + pw_max_life) < entries->pw_expiration)
+ entries->pw_expiration = last_pw_changed + pw_max_life;
+ } else
+ entries->pw_expiration = last_pw_changed + pw_max_life;
+ }
+ }
+
+ cleanup:
+ ldap_msgfree(result);
+
+ if (*nentries == 0 || st != 0)
+ krb5_dbe_free_contents(context, entries);
+
+ if (filter)
+ free (filter);
+
+ if (DN)
+ ldap_memfree (DN);
+
+ for (; ntrees; --ntrees)
+ if (subtree[ntrees-1])
+ free (subtree[ntrees-1]);
+
+ if (userinfo_tl_data.tl_data_contents)
+ free(userinfo_tl_data.tl_data_contents);
+
+ if (ldap_server_handle)
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+
+ if (user)
+ free(user);
+
+ if (modname)
+ free(modname);
+
+ if (parsed_mod_name)
+ krb5_free_principal(context, parsed_mod_name);
+
+ if (pwdpolicydn)
+ free(pwdpolicydn);
+
+ if (policydn)
+ free(policydn);
+
+ return st;
+}
+
+typedef struct _xargs_t {
+ int ptype;
+ char *dn;
+ krb5_boolean dn_from_kbd;
+ char *containerdn;
+ char *tktpolicydn;
+}xargs_t;
+
+static void
+free_xargs(xargs)
+ xargs_t xargs;
+{
+ if (xargs.dn)
+ free (xargs.dn);
+ if (xargs.containerdn)
+ free (xargs.containerdn);
+ if (xargs.tktpolicydn)
+ free (xargs.tktpolicydn);
+}
+
+static krb5_error_code
+process_db_args(context, db_args, xargs)
+ krb5_context context;
+ char **db_args;
+ xargs_t *xargs;
+{
+ int i=0;
+ krb5_error_code st=0;
+ char errbuf[1024];
+ char *arg=NULL, *arg_val=NULL;
+ unsigned int arg_val_len=0;
+ krb5_boolean uflag=FALSE, cflag=FALSE;
+
+ if (db_args)
+ {
+ for (i=0; db_args[i]; ++i) {
+ arg = strtok_r(db_args[i], "=", &arg_val);
+ if(strcmp(arg, USERDN_ARG) == 0) {
+ if (cflag == TRUE) {
+ st = EINVAL;
+ krb5_set_error_message(context, st, "'containerdn' and 'userdn' can not both "
+ "be specified");
+ goto cleanup;
+ }
+ if (xargs->dn != NULL || xargs->containerdn != NULL) {
+ st = EINVAL;
+ snprintf(errbuf, sizeof(errbuf), "%s option not supported", arg);
+ krb5_set_error_message(context, st, "%s", errbuf);
+ goto cleanup;
+ }
+ if (strcmp(arg_val, "") == 0 || arg_val == NULL) {
+ st = EINVAL;
+ snprintf(errbuf, sizeof(errbuf), "%s option value missing", arg);
+ krb5_set_error_message(context, st, "%s", errbuf);
+ goto cleanup;
+ }
+ arg_val_len = strlen(arg_val) + 1;
+ xargs->dn = calloc (1, arg_val_len);
+ if (xargs->dn == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ uflag = TRUE;
+ xargs->ptype = KDB_USER_PRINCIPAL;
+ xargs->dn_from_kbd = TRUE;
+ memcpy(xargs->dn, arg_val, arg_val_len);
+ } else if (strcmp(arg, CONTAINERDN_ARG) == 0) {
+ if (uflag == TRUE) {
+ st = EINVAL;
+ krb5_set_error_message(context, st, "'containerdn' and 'userdn' can not both "
+ "be specified");
+ goto cleanup;
+ }
+ if (xargs->dn != NULL || xargs->containerdn != NULL) {
+ st = EINVAL;
+ snprintf(errbuf, sizeof(errbuf), "%s option not supported", arg);
+ krb5_set_error_message(context, st, "%s", errbuf);
+ goto cleanup;
+ }
+ if (strcmp(arg_val, "") == 0 || arg_val == NULL) {
+ st = EINVAL;
+ snprintf(errbuf, sizeof(errbuf), "%s option value missing", arg);
+ krb5_set_error_message(context, st, "%s", errbuf);
+ goto cleanup;
+ }
+ arg_val_len = strlen(arg_val) + 1;
+ xargs->containerdn = calloc (1, arg_val_len);
+ if (xargs->containerdn == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ cflag = TRUE;
+ xargs->ptype = KDB_SERVICE_PRINCIPAL;
+ xargs->dn_from_kbd = TRUE;
+ memcpy(xargs->containerdn, arg_val, arg_val_len);
+ } else if (strcmp(arg, TKTPOLICYDN_ARG) == 0) {
+ if (arg_val == NULL) {
+ st = EINVAL;
+ snprintf(errbuf, sizeof(errbuf), "%s option value missing", arg);
+ krb5_set_error_message(context, st, "%s", errbuf);
+ goto cleanup;
+ }
+ arg_val_len = strlen(arg_val) + 1;
+ xargs->tktpolicydn = calloc (1, arg_val_len);
+ if (xargs->tktpolicydn == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ memcpy(xargs->tktpolicydn, arg_val, arg_val_len);
+
+ } else {
+ st = EINVAL;
+ snprintf(errbuf, sizeof(errbuf), "unknown option: %s", arg);
+ krb5_set_error_message(context, st, "%s", errbuf);
+ goto cleanup;
+ }
+ }
+ }
+ cleanup:
+ return st;
+}
+
+krb5_error_code
+krb5_ldap_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=0, l=0, plen=0;
+ krb5_error_code st=0, tempst=0;
+ LDAP *ld=NULL;
+ LDAPMessage *result=NULL, *ent=NULL;
+ char *user=NULL, *subtree=NULL;
+ char **values=NULL, *strval[10]={NULL}, errbuf[1024];
+ struct berval **bersecretkey=NULL;
+ LDAPMod **mods=NULL;
+ krb5_boolean dnfound=TRUE, tktpolicy_set=FALSE;
+ krb5_tl_data *tl_data=NULL;
+ krb5_key_data **keys=NULL;
+ KEY *oldkeys=NULL;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+ osa_princ_ent_rec princ_ent;
+ xargs_t xargs={0};
+ char *oldpolicydn = NULL;
+
+ /* Clear the global error string */
+ krb5_clear_error_message(context);
+
+ SETUP_CONTEXT();
+ if (ldap_context->lrparams == NULL || ldap_context->krbcontainer == NULL)
+ return EINVAL;
+
+ /* get ldap handle */
+ GET_HANDLE();
+
+ for (i=0; i < *nentries; ++i, ++entries) {
+ if (is_principal_in_realm(ldap_context, entries->princ) != 0) {
+ st = EINVAL;
+ krb5_set_error_message(context, st, "Principal does not belong to the default realm");
+ goto cleanup;
+ }
+
+ /* get the principal information to act on */
+ if (entries->princ) {
+ if (((st=krb5_unparse_name(context,entries->princ, &user)) !=0) ||
+ ((st=krb5_ldap_unparse_principal_name(user)) != 0))
+ goto cleanup;
+ plen = strlen(user);
+ }
+ xargs.ptype = KDB_SERVICE_PRINCIPAL;
+ if (((st=krb5_get_princ_type(context, entries, &(xargs.ptype))) != 0) ||
+ ((st=krb5_get_userdn(context, entries, &(xargs.dn))) != 0) ||
+ ((st=krb5_get_secretkeys(context, entries, &oldkeys)) != 0))
+ goto cleanup;
+
+ if ((st=process_db_args(context, db_args, &xargs)) != 0)
+ goto cleanup;
+
+ if (xargs.dn == NULL) { /* creation of service principal */
+ if (xargs.ptype == KDB_USER_PRINCIPAL) {
+ st = EINVAL;
+ krb5_set_error_message(context, st, "User DN is missing");
+ goto cleanup;
+ }
+
+ /* get the subtree information */
+ if (entries->princ->length == 2 && entries->princ->data[0].length == strlen("krbtgt") &&
+ strncmp(entries->princ->data[0].data, "krbtgt", entries->princ->data[0].length) == 0) {
+ /* if the principal is a inter-realm principal, always created in the realm container */
+ subtree = strdup(ldap_context->lrparams->realmdn);
+ } else if (xargs.containerdn) {
+ if ((st=checkattributevalue(ld, xargs.containerdn, NULL, NULL, NULL)) != 0) {
+ if (st == KRB5_KDB_NOENTRY || st == KRB5_KDB_CONSTRAINT_VIOLATION) {
+ int ost = st;
+ st = EINVAL;
+ sprintf(errbuf, "'%s' not found: ", xargs.containerdn);
+ prepend_err_str(context, errbuf, st, ost);
+ }
+ goto cleanup;
+ }
+ subtree = strdup(xargs.containerdn);
+ } else if (ldap_context->lrparams->subtree && strlen(ldap_context->lrparams->subtree) != 0) {
+ subtree = strdup(ldap_context->lrparams->subtree);
+ } else {
+ subtree = strdup(ldap_context->lrparams->realmdn);
+ }
+ CHECK_NULL(subtree);
+
+ xargs.dn = malloc(strlen("krbprincipalname=") + strlen(user) + strlen(",") +
+ strlen(subtree) + 1);
+ CHECK_NULL(xargs.dn);
+ sprintf(xargs.dn, "krbprincipalname=%s,%s", user, subtree);
+
+ }
+
+ if (xargs.dn_from_kbd == TRUE) {
+ /* make sure the DN falls in the subtree */
+ int tre=0, dnlen=0, subtreelen=0, ntrees=0;
+ char *subtreelist[2]={NULL};
+ krb5_boolean outofsubtree=TRUE;
+
+ /* get the current subtree list */
+ if ((st = krb5_get_subtree_info(ldap_context, subtreelist, &ntrees)) != 0)
+ goto cleanup;
+
+ for( tre=0; tre<ntrees; ++tre ) {
+ if( subtreelist[tre] == NULL || strlen(subtreelist[tre]) == 0 ) {
+ outofsubtree = FALSE;
+ break;
+ } else {
+ dnlen = strlen (xargs.dn);
+ subtreelen = strlen(subtreelist[tre]);
+ if ((dnlen > subtreelen) && (strcasecmp((xargs.dn + dnlen - subtreelen), subtreelist[tre]) == 0)) {
+ outofsubtree = FALSE;
+ break;
+ }
+ }
+ }
+
+ for( tre=0; tre < ntrees; ++tre ) {
+ free( subtreelist[tre] );
+ }
+
+ if( outofsubtree == TRUE ) {
+ st = EINVAL;
+ krb5_set_error_message(context, st, "DN is out of the realm subtree");
+ goto cleanup;
+ }
+ }
+
+ /* check if the DN exists */
+ {
+ char *attributes[]={"krbpolicyreference", NULL};
+
+ LDAP_SEARCH_1(xargs.dn, LDAP_SCOPE_BASE, 0, attributes,IGNORE_STATUS);
+ if (st == LDAP_NO_SUCH_OBJECT) {
+ dnfound = FALSE;
+ st = LDAP_SUCCESS;
+ } else if (st == LDAP_SUCCESS) {
+ ent = ldap_first_entry(ld, result);
+ if (ent != NULL) {
+ if ((values=ldap_get_values(ld, ent, "krbpolicyreference")) != NULL) {
+ tktpolicy_set = TRUE;
+ ldap_value_free(values);
+ }
+ }
+ ldap_msgfree(result);
+ } else {
+ st = set_ldap_error(context, st, OP_SEARCH);
+ goto cleanup;
+ }
+ }
+
+ if (dnfound == FALSE) { /* create a new object */
+ if (xargs.ptype == KDB_USER_PRINCIPAL) {
+ memset(strval, 0, sizeof(strval));
+ strval[0] = "inetorgperson";
+ strval[1] = "Person";
+ strval[2] = "krbprincipalaux";
+ strval[3] = "krbpolicyaux";
+ strval[4] = "krbpwdpolicyrefaux";
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
+ goto cleanup;
+ values = ldap_explode_dn(xargs.dn, 1);
+ if (values == NULL) {
+ st = EINVAL;
+ krb5_set_error_message(context, st, "Invalid DN");
+ goto cleanup;
+ }
+ memset(strval, 0, sizeof(strval));
+ strval[0] = values[0];
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0) {
+ ldap_value_free(values);
+ goto cleanup;
+ }
+ /* surname is set same as the cn */
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "Surname", LDAP_MOD_ADD, strval)) != 0) {
+ ldap_value_free(values);
+ goto cleanup;
+ }
+ ldap_value_free(values);
+ } else {
+ memset(strval, 0, sizeof(strval));
+ strval[0] = "krbprincipal";
+ strval[1] = "krbprincipalaux";
+ strval[2] = "krbpolicyaux";
+ strval[3] = "krbpwdpolicyrefaux";
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
+ goto cleanup;
+ }
+ } else { /* update the objectclass attribute if any of these is missing */
+ char *attrvalues[] = {"krbprincipalaux", "krbpolicyaux", "krbpwdpolicyrefaux", NULL};
+ int p, q, r=0, amask=0;
+
+ if ((st=checkattributevalue(ld, xargs.dn, "objectclass", attrvalues, &amask)) != 0) {
+ st = KRB5_KDB_UK_RERROR;
+ goto cleanup;
+ }
+ memset(strval, 0, sizeof(strval));
+ for(p=1, q=0; p<=4; p<<=1, ++q) {
+ if ((p & amask) == 0)
+ strval[r++] = attrvalues[q];
+ }
+ if (r != 0) {
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
+ goto cleanup;
+ }
+ }
+
+ if (entries->mask & KDB_MAX_LIFE) {
+ if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxticketlife", LDAP_MOD_REPLACE, entries->max_life)) != 0)
+ goto cleanup;
+ }
+
+ if (entries->mask & KDB_MAX_RLIFE) {
+ if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxrenewableage", LDAP_MOD_REPLACE,
+ entries->max_renewable_life)) != 0)
+ goto cleanup;
+ }
+
+ if (entries->mask & KDB_ATTRIBUTES) {
+ if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbticketflags", LDAP_MOD_REPLACE,
+ entries->attributes)) != 0)
+ goto cleanup;
+ }
+
+ if (entries->mask & KDB_PRINCIPAL) {
+ memset(strval, 0, sizeof(strval));
+ strval[0] = user;
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbprincipalname", LDAP_MOD_ADD, strval)) != 0)
+ goto cleanup;
+ }
+
+ if (entries->mask & KDB_PRINC_EXPIRE_TIME) {
+ memset(strval, 0, sizeof(strval));
+ if ((strval[0]=getstringtime(entries->expiration)) == NULL)
+ goto cleanup;
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbprincipalexpiration", LDAP_MOD_REPLACE, strval)) != 0) {
+ free (strval[0]);
+ goto cleanup;
+ }
+ free (strval[0]);
+ }
+
+ if (entries->mask & KDB_PW_EXPIRATION) {
+ memset(strval, 0, sizeof(strval));
+ if ((strval[0]=getstringtime(entries->pw_expiration)) == NULL)
+ goto cleanup;
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpasswordexpiration",
+ LDAP_MOD_REPLACE,
+ strval)) != 0) {
+ free (strval[0]);
+ goto cleanup;
+ }
+ free (strval[0]);
+ }
+
+ if (entries->mask & KDB_POLICY) {
+ for(tl_data=entries->tl_data; tl_data; tl_data=tl_data->tl_data_next) {
+ if (tl_data->tl_data_type == KRB5_TL_KADM_DATA) {
+ memset(&princ_ent, 0, sizeof(princ_ent));
+ /* FIX ME: I guess the princ_ent should be freed after this call */
+ if((st = krb5_lookup_tl_kadm_data(tl_data, &princ_ent)) != 0) {
+ goto cleanup;
+ }
+ }
+ }
+
+ if(princ_ent.aux_attributes & KDB_POLICY) {
+ memset(strval, 0, sizeof(strval));
+ strval[0] = princ_ent.policy;
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdpolicyreference", LDAP_MOD_REPLACE, strval)) != 0)
+ goto cleanup;
+ } else {
+ st = EINVAL;
+ krb5_set_error_message(context, st, "Password policy value null");
+ goto cleanup;
+ }
+ }
+
+ if (entries->mask & KDB_POLICY_CLR) {
+ memset(strval, 0, sizeof(strval));
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdpolicyreference", LDAP_MOD_DELETE, strval)) != 0)
+ goto cleanup;
+ }
+
+ if (entries->mask & KDB_KEY_DATA || entries->mask & KDB_KVNO) {
+ int kcount=0, zero=0, salttype=0, totalkeys=0;
+ char *currpos=NULL, *krbsecretkey=NULL;
+
+ /* delete the old keys */
+ if (oldkeys) {
+ if ((st=krb5_add_ber_mem_ldap_mod(&mods, "krbsecretkey", LDAP_MOD_DELETE | LDAP_MOD_BVALUES,
+ oldkeys->keys)) != 0)
+ goto cleanup;
+ }
+
+ bersecretkey = malloc (sizeof(struct berval *) * (entries->n_key_data + 1));
+ CHECK_NULL(bersecretkey);
+ memset(bersecretkey, 0, sizeof(struct berval *) * (entries->n_key_data + 1));
+
+ keys = malloc (sizeof (krb5_key_data *) * entries->n_key_data + 1);
+ CHECK_NULL(keys);
+ memset(keys, 0, (sizeof (krb5_key_data *) * entries->n_key_data + 1));
+ for (kcount=0; kcount < entries->n_key_data; ++kcount)
+ keys[kcount] = entries->key_data+kcount;
+ totalkeys = entries->n_key_data;
+
+ kcount = 0;
+ while (totalkeys) {
+ int noofkeys=0, currkvno=0, currkvno_org=0, rlen=0;
+ krb5_timestamp last_pw_changed=0;
+
+ krbsecretkey = malloc (MAX_KEY_LENGTH);
+ CHECK_NULL(krbsecretkey);
+ memset(krbsecretkey, 0, MAX_KEY_LENGTH);
+ currpos = krbsecretkey;
+ rlen = MAX_KEY_LENGTH;
+
+ STORE16_INT(currpos, plen); /* principal len */
+ currpos +=2;
+ rlen -=2;
+
+ for (l=0; l < entries->n_key_data; ++l)
+ if (keys[l] != NULL) {
+ currkvno = keys[l]->key_data_kvno;
+ break;
+ }
+
+ currkvno_org = currkvno;
+ STORE16_INT(currpos, currkvno); /* principal key version */
+ currpos +=2;
+ rlen -=2;
+
+ memset(currpos, 0, 2); /* master key version */
+ currpos +=2;
+ rlen -=2;
+
+ if ((st=krb5_dbe_lookup_last_pwd_change(context, entries, &last_pw_changed)) != 0)
+ goto cleanup;
+ STORE32_INT(currpos, last_pw_changed); /* last pwd change */
+ currpos += 4;
+ rlen -=4;
+
+ for (noofkeys=0; l < entries->n_key_data; ++l)
+ if (keys[l] && keys[l]->key_data_kvno == currkvno_org)
+ ++noofkeys;
+
+ STORE16_INT(currpos, noofkeys); /* number of keys */
+ currpos +=2;
+ rlen -=2;
+
+ /* key type, key length, salt type and salt type */
+ for (l=0; l<entries->n_key_data; ++l) {
+ if ( keys[l] && keys[l]->key_data_kvno == currkvno_org) {
+ STORE16_INT(currpos, keys[l]->key_data_type[0]);
+ currpos +=2;
+ rlen -=2;
+ STORE16_INT(currpos, keys[l]->key_data_length[0]);
+ currpos +=2;
+ rlen -=2;
+
+ STORE16_INT(currpos, keys[l]->key_data_type[1]);
+ currpos +=2;
+ rlen -=2;
+ salttype = keys[l]->key_data_type[1];
+ if (salttype==KRB5_KDB_SALTTYPE_NOREALM || salttype==KRB5_KDB_SALTTYPE_ONLYREALM) {
+ STORE16_INT(currpos, zero);
+ } else {
+ STORE16_INT(currpos, keys[l]->key_data_length[1]);
+ }
+ currpos +=2;
+ rlen -=2;
+ }
+ }
+ if (plen > rlen) {
+ st = EINVAL;
+ snprintf(errbuf, sizeof(errbuf), "Insufficient buffer while storing the key of principal %s", user);
+ krb5_set_error_message(context, st, "%s", errbuf);
+ goto cleanup;
+ }
+ memcpy(currpos, user, (unsigned int)plen); /* principal name */
+ currpos +=plen;
+ rlen -=plen;
+
+ /* key value, salt value */
+ for(l=0; l<entries->n_key_data; ++l) {
+ if (keys[l] && keys[l]->key_data_kvno == currkvno_org) {
+ if (keys[l]->key_data_length[0]) {
+ if (keys[l]->key_data_length[0] > rlen) {
+ st = EINVAL;
+ snprintf(errbuf, sizeof(errbuf), "Insufficient buffer while storing the key of principal %s", user);
+ krb5_set_error_message(context, st, "%s", errbuf);
+ goto cleanup;
+ }
+ memcpy(currpos, keys[l]->key_data_contents[0], keys[l]->key_data_length[0]);
+ currpos += keys[l]->key_data_length[0];
+ rlen -= keys[l]->key_data_length[0];
+ }
+
+ salttype = keys[l]->key_data_type[1];
+ if (keys[l]->key_data_length[1] && (!(salttype==KRB5_KDB_SALTTYPE_NOREALM
+ || salttype==KRB5_KDB_SALTTYPE_ONLYREALM))) {
+ if (keys[l]->key_data_length[1] > rlen) {
+ st = EINVAL;
+ snprintf(errbuf, sizeof(errbuf), "Insufficient buffer while storing the key of principal %s", user);
+ krb5_set_error_message(context, st, "%s", errbuf);
+ goto cleanup;
+ }
+ memcpy(currpos, keys[l]->key_data_contents[1], keys[l]->key_data_length[1]);
+ currpos += keys[l]->key_data_length[1];
+ rlen -= keys[l]->key_data_length[1];
+ }
+ keys[l] = NULL;
+ }
+ }
+ bersecretkey[kcount] = malloc (sizeof (struct berval));
+ CHECK_NULL(bersecretkey[kcount]);
+ bersecretkey[kcount]->bv_len = currpos - krbsecretkey;
+ bersecretkey[kcount++]->bv_val = krbsecretkey;
+ totalkeys = totalkeys - noofkeys;
+ }
+ if ((st=krb5_add_ber_mem_ldap_mod(&mods, "krbsecretkey",
+ LDAP_MOD_ADD | LDAP_MOD_BVALUES, bersecretkey)) != 0)
+ goto cleanup;
+
+ if (!(entries->mask & KDB_PRINCIPAL)){
+ memset(strval, 0, sizeof(strval));
+ if ((strval[0]=getstringtime(entries->pw_expiration)) == NULL)
+ goto cleanup;
+ if ((st=krb5_add_str_mem_ldap_mod(&mods,
+ "krbpasswordexpiration",
+ LDAP_MOD_REPLACE, strval)) != 0) {
+ free (strval[0]);
+ goto cleanup;
+ }
+ free (strval[0]);
+ }
+ } /* Modify Key data ends here */
+
+ /* Directory specific attribute */
+ if (xargs.tktpolicydn != NULL) {
+ int tmask=0, tkttree = 0, subtreednlen = 0, ntre = 0, tktdnlen = 0;
+
+ char *subtreednlist[2]={NULL};
+ krb5_boolean dnoutofsubtree=TRUE;
+
+ if ((st=krb5_get_policydn(context, entries, &oldpolicydn)) != 0)
+ goto cleanup;
+
+ if (strlen(xargs.tktpolicydn) != 0) {
+ st = checkattributevalue(ld, xargs.tktpolicydn, "objectclass", policyclass, &tmask);
+ CHECK_CLASS_VALIDITY(st, tmask, "ticket policy object value: ");
+
+ memset(strval, 0, sizeof(strval));
+ strval[0] = xargs.tktpolicydn;
+ if ((st = krb5_get_subtree_info(ldap_context, subtreednlist, &ntre)) != 0)
+ goto cleanup;
+
+ for( tkttree=0; tkttree<ntre; ++tkttree ) {
+ if( subtreednlist[tkttree] == NULL || strlen(subtreednlist[tkttree]) == 0 ) {
+ dnoutofsubtree = FALSE;
+ break;
+ } else {
+ tktdnlen = strlen (xargs.tktpolicydn);
+ subtreednlen = strlen(subtreednlist[tkttree]);
+
+ if ((tktdnlen > subtreednlen) && (strcasecmp((xargs.tktpolicydn + tktdnlen - subtreednlen), subtreednlist[tkttree]) == 0)) {
+ dnoutofsubtree = FALSE;
+ break;
+ }
+ }
+ }
+ for( tkttree=0; tkttree < ntre; ++tkttree ) {
+ free( subtreednlist[tkttree] );
+ }
+ if( dnoutofsubtree == TRUE ) {
+ st = EINVAL;
+ prepend_err_str(context,"Ticket Policy DN is out of the realm subtree",st,st);
+ goto cleanup;
+ }
+
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpolicyreference", LDAP_MOD_REPLACE, strval)) != 0)
+ goto cleanup;
+ if(oldpolicydn != NULL){
+ if(strncmp(xargs.tktpolicydn,oldpolicydn,strlen(xargs.tktpolicydn)) != 0)
+ {
+ if ((st = krb5_ldap_change_count(context, oldpolicydn,2 )))
+ goto cleanup;
+ }
+ }
+
+ if ((st = krb5_ldap_change_count(context, xargs.tktpolicydn,1 )))
+ goto cleanup;
+ } else {
+ /* if xargs.tktpolicydn is a empty string, then delete already existing krbpolicyreference attr */
+ if (tktpolicy_set == FALSE) { /* if the attribute is not present then abort */
+ st = EINVAL;
+ prepend_err_str(context,"'ticketpolicydn' empty",st,st);
+ goto cleanup;
+ } else {
+ memset(strval, 0, sizeof(strval));
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpolicyreference", LDAP_MOD_DELETE, strval)) != 0)
+ goto cleanup;
+ }
+ }
+
+ }
+ if (dnfound == TRUE) {
+ if (mods == NULL) {
+ goto cleanup;
+ }
+ st=ldap_modify_s(ld, xargs.dn, mods);
+ if (st != LDAP_SUCCESS) {
+ sprintf(errbuf, "User modification failed: %s", ldap_err2string(st));
+ st = translate_ldap_error (st, OP_MOD);
+ krb5_set_error_message(context, st, "%s", errbuf);
+ goto cleanup;
+ }
+ }
+ else {
+ st=ldap_add_s(ld, xargs.dn, mods);
+ if (st != LDAP_SUCCESS) {
+ sprintf(errbuf, "Principal add failed: %s", ldap_err2string(st));
+ st = translate_ldap_error (st, OP_ADD);
+ krb5_set_error_message(context, st, "%s", errbuf);
+ goto cleanup;
+ }
+ }
+
+ }
+
+ cleanup:
+ if (user)
+ free(user);
+
+ free_xargs(xargs);
+
+ if (subtree)
+ free (subtree);
+
+ if (bersecretkey) {
+ for (l=0; bersecretkey[l]; ++l) {
+ if (bersecretkey[l]->bv_val)
+ free (bersecretkey[l]->bv_val);
+ free (bersecretkey[l]);
+ }
+ free (bersecretkey);
+ }
+
+ if (keys)
+ free (keys);
+
+ if (oldkeys) {
+ for (l=0; l < oldkeys->nkey; ++l) {
+ if (oldkeys->keys[l]->bv_val)
+ free (oldkeys->keys[l]->bv_val);
+ free (oldkeys->keys[l]);
+ }
+ free (oldkeys->keys);
+ free (oldkeys);
+ }
+ ldap_mods_free(mods, 1);
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ *nentries = i;
+ return(st);
+}
+
+static krb5_error_code
+krb5_read_tkt_policyreference(context, ldap_context, entries, policydn)
+ krb5_context context;
+ krb5_ldap_context *ldap_context;
+ krb5_db_entry *entries;
+ char *policydn;
+{
+ krb5_error_code st=0;
+ unsigned int mask=0, omask=0;
+ int tkt_mask=(KDB_MAX_LIFE_ATTR | KDB_MAX_RLIFE_ATTR | KDB_TKT_FLAGS_ATTR);
+ krb5_ldap_policy_params *tktpoldnparam=NULL;
+
+ if ((st=krb5_get_attributes_mask(context, entries, &mask)) != 0)
+ goto cleanup;
+
+ if ((mask & tkt_mask) != tkt_mask) {
+ if (policydn != NULL) {
+ st = krb5_ldap_read_policy(context, policydn, &tktpoldnparam, &omask);
+ if (st && st != KRB5_KDB_NOENTRY) {
+ prepend_err_str(context, "Error reading ticket policy. ", st, st);
+ goto cleanup;
+ }
+
+ st = 0; /* reset the return status */
+ }
+
+ if ((mask & KDB_MAX_LIFE_ATTR) == 0) {
+ if ((omask & KDB_MAX_LIFE_ATTR) == KDB_MAX_LIFE_ATTR)
+ entries->max_life = tktpoldnparam->maxtktlife;
+ else if (ldap_context->lrparams->max_life)
+ entries->max_life = ldap_context->lrparams->max_life;
+ else if(ldap_context->krbcontainer->max_life)
+ entries->max_life = ldap_context->krbcontainer->max_life;
+ else
+ entries->max_life = KRB5_KDB_MAX_LIFE;
+ }
+
+ if ((mask & KDB_MAX_RLIFE_ATTR) == 0) {
+ if ((omask & KDB_MAX_RLIFE_ATTR) == KDB_MAX_RLIFE_ATTR)
+ entries->max_renewable_life = tktpoldnparam->maxrenewlife;
+ else if (ldap_context->lrparams->max_renewable_life)
+ entries->max_renewable_life = ldap_context->lrparams->max_renewable_life;
+ else if(ldap_context->krbcontainer->max_renewable_life)
+ entries->max_renewable_life = ldap_context->krbcontainer->max_renewable_life;
+ else
+ entries->max_renewable_life = KRB5_KDB_MAX_RLIFE;
+ }
+
+ if ((mask & KDB_TKT_FLAGS_ATTR) == 0) {
+ if ((omask & KDB_TKT_FLAGS_ATTR) == KDB_TKT_FLAGS_ATTR)
+ entries->attributes = tktpoldnparam->tktflags;
+ else if (ldap_context->lrparams->tktflags)
+ entries->attributes |= ldap_context->lrparams->tktflags;
+ else if(ldap_context->krbcontainer->tktflags)
+ entries->attributes |= ldap_context->krbcontainer->tktflags;
+ }
+ krb5_ldap_free_policy(context, tktpoldnparam);
+ }
+
+ cleanup:
+ return st;
+}
+
+static krb5_error_code
+krb5_decode_krbsecretkey(context, entries, bvalues, userinfo_tl_data)
+ krb5_context context;
+ krb5_db_entry *entries;
+ struct berval **bvalues;
+ krb5_tl_data *userinfo_tl_data;
+{
+ char *user=NULL, *ptr=NULL, *pname=NULL, *currentkey=NULL, *currentsalt=NULL;
+ void *reallocptr=NULL;
+ int i=0, j=0, k=0, plen=0, noofkeys=0, ist_pkeyver=0, pkeyver=0, mkeyver=0, keylen=0;
+ krb5_key_data *key_data=NULL;
+ krb5_error_code st=0;
+ krb5_timestamp last_pw_changed=0;
+
+ if ((st=krb5_unparse_name(context, entries->princ, &user)) != 0)
+ goto cleanup;
+
+ for(i=0; bvalues[i] != NULL; ++i) {
+
+ ptr = (char *) bvalues[i]->bv_val;
+
+ /* check the consistency of the key */
+
+ if(bvalues[i]->bv_len < KEYHEADER) /* key smaller than the header size */
+ continue;
+
+ plen = PRINCIPALLEN(ptr);
+ if (NOOFKEYS(ptr) == 0)
+ continue;
+
+ keylen = KEYHEADER + (8 * NOOFKEYS(ptr));
+ if (bvalues[i]->bv_len < keylen) /* key or salt header info corrupted*/
+ continue;
+
+ keylen += plen;
+ if (bvalues[i]->bv_len < keylen) /* principal info corrupted */
+ continue;
+
+ for(k=0; k<NOOFKEYS(ptr); ++k)
+ keylen += KEYLENGTH(ptr, k) + SALTLENGTH(ptr, k);
+
+ if (bvalues[i]->bv_len < keylen) /* key or salt values corrupted */
+ continue;
+
+ pname = PRINCIPALNAME(ptr); /* set pname to principalName field */
+
+ /* key doesn't belong to the principal */
+ if (strncmp(user, pname, (unsigned) plen) != 0)
+ continue;
+
+ /* Number of Principal Keys */
+ noofkeys += NOOFKEYS(ptr);
+
+ if ((st=store_tl_data(userinfo_tl_data, KDB_TL_KEYINFO, bvalues[i])) != 0)
+ goto cleanup;
+
+ pkeyver = PKEYVER(ptr); /* Principal Key Version */
+ mkeyver = MKEYVER(ptr); /* Master Key Version */
+
+ if (ist_pkeyver == 0 || pkeyver >= ist_pkeyver) {
+ ist_pkeyver = pkeyver;
+ /* last password changed */
+ last_pw_changed = 0;
+ last_pw_changed += (ptr[6] & 0xFF) << 24;
+ last_pw_changed += (ptr[7] & 0xFF) << 16;
+ last_pw_changed += (ptr[8] & 0xFF) << 8;
+ last_pw_changed += (ptr[9] & 0xFF) << 0;
+
+ if ((st=krb5_dbe_update_last_pwd_change(context, entries,
+ last_pw_changed)) != 0)
+ goto cleanup;
+ }
+
+ reallocptr = key_data;
+ key_data = realloc(key_data, (sizeof(*key_data) * noofkeys));
+ if (key_data == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+
+ currentkey = KEYBODY(ptr);
+ for (k=0; j<noofkeys; ++k, ++j) {
+
+ key_data[j].key_data_ver = 1;
+ key_data[j].key_data_kvno = pkeyver;
+
+ key_data[j].key_data_type[0] = KEYTYPE(ptr,k); /* get key type */
+ key_data[j].key_data_length[0] = KEYLENGTH(ptr,k); /* get key length */
+ key_data[j].key_data_type[1] = SALTTYPE(ptr,k); /* get salt type */
+ key_data[j].key_data_length[1] = SALTLENGTH(ptr,k); /* get salt length */
+
+ key_data[j].key_data_contents[0] = malloc(key_data[j].key_data_length[0]);
+ if (key_data[j].key_data_contents[0] == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ memcpy(key_data[j].key_data_contents[0], currentkey,
+ key_data[j].key_data_length[0]);
+
+ currentsalt = currentkey + key_data[j].key_data_length[0];
+ if (key_data[j].key_data_length[1] != 0) {
+
+ key_data[j].key_data_ver = 2;
+ key_data[j].key_data_contents[1] = malloc(key_data[j].key_data_length[1]);
+ if (key_data[j].key_data_contents[1] == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ memcpy(key_data[j].key_data_contents[1], currentsalt,
+ key_data[j].key_data_length[1]);
+
+ } else if (key_data[j].key_data_type[1] == KRB5_KDB_SALTTYPE_NOREALM ||
+ key_data[j].key_data_type[1] == KRB5_KDB_SALTTYPE_ONLYREALM) {
+ char *def_realm = NULL;
+ krb5_data norealmval;
+
+ key_data[j].key_data_ver = 2;
+ switch(key_data[j].key_data_type[1]) {
+ case KRB5_KDB_SALTTYPE_ONLYREALM:
+ def_realm = entries->princ->realm.data;
+ key_data[j].key_data_length[1] = strlen (def_realm);
+ key_data[j].key_data_contents[1] = malloc (key_data[j].key_data_length[1]);
+ if (key_data[j].key_data_contents[1] == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ memcpy(key_data[j].key_data_contents[1],
+ def_realm, key_data[j].key_data_length[1]);
+ break;
+
+ case KRB5_KDB_SALTTYPE_NOREALM:
+ memset(&norealmval, 0, sizeof(krb5_data));
+ if ((st = krb5_principal2salt_norealm(context, entries->princ,
+ &norealmval)) != 0) {
+ goto cleanup;
+ }
+
+ key_data[j].key_data_length[1] = norealmval.length;
+ key_data[j].key_data_contents[1] = (unsigned char *)norealmval.data;
+ break;
+ }
+ } else if (key_data[j].key_data_type[1] == KRB5_KDB_SALTTYPE_V4) {
+ key_data[j].key_data_contents[1] = NULL;
+ key_data[j].key_data_ver = 2;
+ } else {
+ key_data[j].key_data_contents[1] = NULL;
+ }
+ currentkey = currentsalt + key_data[j].key_data_length[1];
+ }
+ entries->n_key_data = noofkeys;
+ entries->key_data = key_data;
+ }
+
+ cleanup:
+ ldap_value_free_len(bvalues);
+ free (user);
+ return st;
+}
+
+static char *
+getstringtime(epochtime)
+ krb5_timestamp epochtime;
+{
+ struct tm tme;
+ char *strtime=NULL;
+ time_t posixtime = epochtime;
+
+ strtime = calloc (50, 1);
+ if (strtime == NULL)
+ return NULL;
+
+ if (gmtime_r(&posixtime, &tme) == NULL)
+ return NULL;
+
+ strftime(strtime, 50, "%Y%m%d%H%M%SZ", &tme);
+ return strtime;
+}
+
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c
new file mode 100644
index 000000000..2cbb444e7
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c
@@ -0,0 +1,307 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_pwd_policy.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ldap_main.h"
+#include "kdb_ldap.h"
+#include "ldap_pwd_policy.h"
+#include "ldap_err.h"
+
+static char *password_policy_attributes[] = { "krbmaxpwdlife", "krbminpwdlife", "krbpwdmindiffchars",
+ "krbpwdminlength", "krbpwdhistorylength", "krbpwdpolicyrefcount",
+ NULL };
+
+/*
+ * Function to create password policy object.
+ */
+
+krb5_error_code
+krb5_ldap_create_password_policy (context, policy)
+ krb5_context context;
+ osa_policy_ent_t policy;
+{
+ krb5_error_code st=0;
+ LDAP *ld=NULL;
+ LDAPMod **mods={NULL};
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+ char **rdns=NULL, *strval[2]={NULL};
+
+ /* Clear the global error string */
+ krb5_clear_error_message(context);
+
+ /* validate the input parameters */
+ if (policy == NULL || policy->name == NULL)
+ return EINVAL;
+
+ SETUP_CONTEXT();
+ GET_HANDLE();
+
+ /* get the first component of the dn to set the cn attribute */
+ rdns = ldap_explode_dn(policy->name, 1);
+ if (rdns == NULL) {
+ st = EINVAL;
+ krb5_set_error_message(context, st, "Invalid password policy DN syntax");
+ goto cleanup;
+ }
+
+ strval[0] = rdns[0];
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0)
+ goto cleanup;
+
+ strval[0] = "krbPwdPolicy";
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
+ goto cleanup;
+
+ if (((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxpwdlife", LDAP_MOD_ADD,
+ (signed) policy->pw_max_life)) != 0)
+ || ((st=krb5_add_int_mem_ldap_mod(&mods, "krbminpwdlife", LDAP_MOD_ADD,
+ (signed) policy->pw_min_life)) != 0)
+ || ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdmindiffchars", LDAP_MOD_ADD,
+ (signed) policy->pw_min_classes)) != 0)
+ || ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdminlength", LDAP_MOD_ADD,
+ (signed) policy->pw_min_length)) != 0)
+ || ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdhistorylength", LDAP_MOD_ADD,
+ (signed) policy->pw_history_num)) != 0)
+ || ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdpolicyrefcount", LDAP_MOD_ADD,
+ (signed) policy->policy_refcnt)) != 0))
+ goto cleanup;
+
+ /* password policy object creation */
+ if ((st=ldap_add_s(ld, policy->name, mods)) != LDAP_SUCCESS) {
+ st = set_ldap_error (context, st, OP_ADD);
+ goto cleanup;
+ }
+
+ cleanup:
+ if (rdns)
+ ldap_value_free(rdns);
+
+ ldap_mods_free(mods, 1);
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return(st);
+}
+
+/*
+ * Function to modify password policy object.
+ */
+
+krb5_error_code
+krb5_ldap_put_password_policy (context, policy)
+ krb5_context context;
+ osa_policy_ent_t policy;
+{
+ krb5_error_code st=0;
+ LDAP *ld=NULL;
+ LDAPMod **mods=NULL;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+
+ /* Clear the global error string */
+ krb5_clear_error_message(context);
+
+ /* validate the input parameters */
+ if (policy == NULL || policy->name == NULL)
+ return EINVAL;
+
+ SETUP_CONTEXT();
+ GET_HANDLE();
+
+ if (((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxpwdlife", LDAP_MOD_REPLACE,
+ (signed) policy->pw_max_life)) != 0)
+ || ((st=krb5_add_int_mem_ldap_mod(&mods, "krbminpwdlife", LDAP_MOD_REPLACE,
+ (signed) policy->pw_min_life)) != 0)
+ || ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdmindiffchars", LDAP_MOD_REPLACE,
+ (signed) policy->pw_min_classes)) != 0)
+ || ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdminlength", LDAP_MOD_REPLACE,
+ (signed) policy->pw_min_length)) != 0)
+ || ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdhistorylength", LDAP_MOD_REPLACE,
+ (signed) policy->pw_history_num)) != 0)
+ || ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdpolicyrefcount", LDAP_MOD_REPLACE,
+ (signed) policy->policy_refcnt)) != 0))
+ goto cleanup;
+
+ /* modify the password policy object. */
+ if ((st=ldap_modify_s(ld, policy->name, mods)) != LDAP_SUCCESS) {
+ st = set_ldap_error (context, st, OP_MOD);
+ goto cleanup;
+ }
+
+ cleanup:
+ ldap_mods_free(mods, 1);
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return(st);
+}
+
+krb5_error_code
+krb5_ldap_get_password_policy (context, name, policy, cnt)
+ krb5_context context;
+ char *name;
+ osa_policy_ent_t *policy;
+ int *cnt;
+{
+ krb5_error_code st=0, tempst=0;
+ LDAP *ld=NULL;
+ LDAPMessage *result=NULL,*ent=NULL;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+
+ /* Clear the global error string */
+ krb5_clear_error_message(context);
+
+ /* validate the input parameters */
+ if(name == NULL)
+ return EINVAL;
+
+ SETUP_CONTEXT();
+ GET_HANDLE();
+
+ *cnt = 0;
+ *(policy) = (osa_policy_ent_t) malloc(sizeof(osa_policy_ent_rec));
+ if (*policy == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ memset(*policy, 0, sizeof(osa_policy_ent_rec));
+
+ LDAP_SEARCH(name, LDAP_SCOPE_BASE, "(objectclass=krbPwdPolicy)", password_policy_attributes);
+ *cnt = 1;
+ (*policy)->name = name;
+ (*policy)->version = 1;
+
+ ent=ldap_first_entry(ld, result);
+ if (ent != NULL) {
+ krb5_ldap_get_value(ld, ent, "krbmaxpwdlife", &((*policy)->pw_max_life));
+ krb5_ldap_get_value(ld, ent, "krbminpwdlife", &((*policy)->pw_min_life));
+ krb5_ldap_get_value(ld, ent, "krbpwdmindiffchars", &((*policy)->pw_min_classes));
+ krb5_ldap_get_value(ld, ent, "krbpwdminlength", &((*policy)->pw_min_length));
+ krb5_ldap_get_value(ld, ent, "krbpwdhistorylength", &((*policy)->pw_history_num));
+ krb5_ldap_get_value(ld, ent, "krbpwdpolicyrefcount", &((*policy)->policy_refcnt));
+ }
+
+cleanup:
+ ldap_msgfree(result);
+ if (st != 0) {
+ if (*policy != NULL) {
+ free (*policy);
+ *policy = NULL;
+ }
+ }
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
+
+krb5_error_code
+krb5_ldap_delete_password_policy (context, policy)
+ krb5_context context;
+ char *policy;
+{
+ krb5_error_code st=0;
+ LDAP *ld=NULL;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+
+ /* Clear the global error string */
+ krb5_clear_error_message(context);
+
+ /* validate the input parameters */
+ if(policy == NULL)
+ return EINVAL;
+
+ SETUP_CONTEXT();
+ GET_HANDLE();
+
+ if((st=ldap_delete_s(ld, policy)) != LDAP_SUCCESS) {
+ st = set_ldap_error (context, st, OP_DEL);
+ goto cleanup;
+ }
+
+cleanup:
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
+
+krb5_error_code
+krb5_ldap_iterate_password_policy(context, match_expr, func, func_arg)
+ krb5_context context;
+ char *match_expr;
+ void (*func) (krb5_pointer, osa_policy_ent_t );
+ krb5_pointer func_arg;
+{
+ osa_policy_ent_rec *entry=NULL;
+ char *attrs[] = { "cn", NULL };
+ krb5_error_code st=0, tempst=0;
+ LDAP *ld=NULL;
+ LDAPMessage *result=NULL, *ent=NULL;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+ char *policy_dn=NULL;
+
+ /* Clear the global error string */
+ krb5_clear_error_message(context);
+
+ SETUP_CONTEXT();
+ GET_HANDLE();
+
+ entry = (osa_policy_ent_t) malloc(sizeof(osa_policy_ent_rec));
+ CHECK_NULL(entry);
+ memset(entry, 0, sizeof(osa_policy_ent_rec));
+
+ LDAP_SEARCH(NULL, LDAP_SCOPE_SUBTREE, "(objectclass=krbpwdpolicy)", attrs);
+ for(ent=ldap_first_entry(ld, result); ent != NULL; ent=ldap_next_entry(ld, ent)) {
+ if ((policy_dn=ldap_get_dn(ld, ent)) == NULL)
+ continue;
+ entry->name = policy_dn;
+ (*func)(func_arg, entry);
+ ldap_memfree(policy_dn);
+ }
+ ldap_msgfree(result);
+
+ cleanup:
+ if (entry)
+ free (entry);
+
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
+
+void
+krb5_ldap_free_password_policy (context, entry)
+ krb5_context context;
+ osa_policy_ent_t entry;
+{
+ if(entry)
+ free(entry);
+ return;
+}
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.h b/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.h
new file mode 100644
index 000000000..49fa85ecb
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.h
@@ -0,0 +1,54 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_pwd_policy.h
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LDAP_KRBPWDPOLICY_H_
+#define _LDAP_KRBPWDPOLICY_H_
+
+krb5_error_code
+krb5_ldap_get_password_policy (krb5_context , char *, osa_policy_ent_t *, int *);
+
+krb5_error_code
+krb5_ldap_create_password_policy (krb5_context , osa_policy_ent_t );
+
+krb5_error_code
+krb5_ldap_put_password_policy ( krb5_context kcontext, osa_policy_ent_t policy );
+
+krb5_error_code
+krb5_ldap_delete_password_policy ( krb5_context kcontext, char *policy );
+
+krb5_error_code
+krb5_ldap_iterate_password_policy(krb5_context, char *,
+ void (*) (krb5_pointer, osa_policy_ent_t ),
+ krb5_pointer);
+
+void
+krb5_ldap_free_password_policy( krb5_context kcontext, osa_policy_ent_t entry );
+
+#endif
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c
new file mode 100644
index 000000000..2ac8219c1
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c
@@ -0,0 +1,1650 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_realm.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ldap_main.h"
+#include "ldap_realm.h"
+#include "ldap_principal.h"
+#include "ldap_err.h"
+
+#define END_OF_LIST -1
+char *realm_attributes[] = {"krbSearchScope","krbSubTree",
+ "krbMaxTicketLife", "krbMaxRenewableAge",
+ "krbTicketFlags", "krbDefaultEncType",
+ "krbDefaultSaltType", "krbUpEnabled",
+ "krbPolicyReference", "krbSupportedEncTypes",
+ "krbSupportedSaltTypes", "krbLdapServers",
+ "krbKdcServers", "krbAdmServers",
+ "krbPwdServers", NULL};
+
+
+char *policy_attributes[] = { "krbMaxTicketLife",
+ "krbMaxRenewableAge",
+ "krbTicketFlags",
+ NULL };
+
+
+
+char *policyclass[] = { "krbPolicy", NULL };
+char *kdcclass[] = { "krbKdcService", NULL };
+char *adminclass[] = { "krbAdmService", NULL };
+char *pwdclass[] = { "krbPwdService", NULL };
+char *subtreeclass[] = { "Organization", "OrganizationalUnit", "Domain",
+ "Country", "Locality", NULL };
+
+int supportedenctypes[] = { ENCTYPE_DES_CBC_CRC, ENCTYPE_DES_CBC_MD4, ENCTYPE_DES_CBC_MD5,
+ ENCTYPE_DES3_CBC_SHA1, ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+ ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_ARCFOUR_HMAC, -1};
+
+int supportedsalttypes[] = { KRB5_KDB_SALTTYPE_NORMAL, KRB5_KDB_SALTTYPE_V4,
+ KRB5_KDB_SALTTYPE_NOREALM, KRB5_KDB_SALTTYPE_ONLYREALM,
+ KRB5_KDB_SALTTYPE_SPECIAL, -1};
+
+
+char *krbContainerRefclass[] = { "krbContainerRefAux", NULL};
+
+
+static void
+ignore_duplicates(int_list)
+ int *int_list;
+{
+ int i=0, j=0, scount=0;
+
+ for (i=0; int_list[i] != END_OF_LIST; scount=i++)
+ ;
+
+ for (i=0; i <= scount; ++i) {
+ if (i > 0 && int_list[i] == int_list[i-1]) {
+ for (j=i; j<=scount; ++j)
+ int_list[j-1] = int_list[j];
+ int_list[scount] = END_OF_LIST;
+ --scount;
+ --i;
+ continue;
+ }
+ }
+}
+
+/*
+ * list realms from eDirectory
+ */
+
+/*
+ * Function to remove all special characters from a string (rfc2254).
+ * Use whenever exact matching is to be done ...
+ */
+static char *
+ldap_filter_correct (unsigned char *in, unsigned int len)
+{
+ int i, count;
+ char *out, *ptr;
+
+ for (i = 0, count = 0; i < len; i++)
+ switch (in[i]) {
+ case '*':
+ case '(':
+ case ')':
+ case '\\':
+ case '\0':
+ count ++;
+ }
+
+ out = (char *)malloc((len + (count * 2) + 1) * sizeof (char));
+ assert (out != NULL);
+ memset(out, 0, len + (count * 2) + 1);
+
+ for (i = 0, ptr = out; i < len; i++)
+ switch (in[i]) {
+ case '*':
+ ptr[0] = '\\';
+ ptr[1] = '2';
+ ptr[2] = 'a';
+ ptr += 3;
+ break;
+ case '(':
+ ptr[0] = '\\';
+ ptr[1] = '2';
+ ptr[2] = '8';
+ ptr += 3;
+ break;
+ case ')':
+ ptr[0] = '\\';
+ ptr[1] = '2';
+ ptr[2] = '9';
+ ptr += 3;
+ break;
+ case '\\':
+ ptr[0] = '\\';
+ ptr[1] = '5';
+ ptr[2] = 'c';
+ ptr += 3;
+ break;
+ case '\0':
+ ptr[0] = '\\';
+ ptr[1] = '0';
+ ptr[2] = '0';
+ ptr += 3;
+ break;
+ default:
+ ptr[0] = in[i];
+ ptr += 1;
+ break;
+ }
+
+ /* ptr[count - 1] = '\0'; */
+
+ return out;
+}
+
+static int principal_in_realm_2(krb5_principal principal, char *realm) {
+ /* Cross realm trust ... */
+ if (principal->length == 2 &&
+ principal->data[0].length == sizeof ("krbtgt") &&
+ strncasecmp (principal->data[0].data, "krbtgt", sizeof ("krbtgt")) &&
+ principal->data[1].length == strlen (realm) &&
+ strncasecmp (principal->data[1].data, realm, strlen (realm)))
+ return 0;
+
+ if (strlen(realm) != principal->realm.length)
+ return 1;
+
+ if (strncasecmp(realm, principal->realm.data, principal->realm.length) != 0)
+ return 1;
+
+ return 0;
+}
+
+/*
+ * Lists the realms in the Directory.
+ */
+
+krb5_error_code
+krb5_ldap_list_realm(context, realms)
+ krb5_context context;
+ char ***realms;
+{
+ char **values = NULL;
+ unsigned int i = 0, count = 0;
+ krb5_error_code st = 0, tempst = 0;
+ LDAP *ld = NULL;
+ LDAPMessage *result = NULL, *ent = NULL;
+ kdb5_dal_handle *dal_handle = NULL;
+ krb5_ldap_context *ldap_context = NULL;
+ krb5_ldap_server_handle *ldap_server_handle = NULL;
+
+ SETUP_CONTEXT ();
+
+ /* get the kerberos container DN information */
+ if (ldap_context->krbcontainer == NULL) {
+ if ((st = krb5_ldap_read_krbcontainer_params(context,
+ &(ldap_context->krbcontainer))) != 0)
+ goto cleanup;
+ }
+
+ /* get ldap handle */
+ GET_HANDLE ();
+
+ {
+ char *cn[] = {"cn", NULL};
+ LDAP_SEARCH(ldap_context->krbcontainer->DN,
+ LDAP_SCOPE_ONELEVEL,
+ "(objectclass=krbRealmContainer)",
+ cn);
+ }
+
+ *realms = NULL;
+
+ count = ldap_count_entries (ld, result);
+ if(count == -1){
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &st);
+ st = set_ldap_error (context, st, OP_SEARCH);
+ goto cleanup;
+ }
+
+ *realms = calloc(count+1, sizeof (char *));
+ CHECK_NULL(*realms);
+
+ for (ent = ldap_first_entry(ld, result), count = 0; ent != NULL;
+ ent = ldap_next_entry(ld, ent)) {
+
+ if ((values = ldap_get_values (ld, ent, "cn")) != NULL) {
+
+ (*realms)[count] = strdup(values[0]);
+ CHECK_NULL((*realms)[count]);
+ count += 1;
+
+ ldap_value_free(values);
+ }
+ } /* for (ent= ... */
+ ldap_msgfree(result);
+
+ cleanup:
+
+ /* some error, free up all the memory */
+ if (st != 0) {
+ if (*realms) {
+ for (i=0; (*realms)[i] != NULL; ++i) {
+ free ((*realms)[i]);
+ }
+ free (*realms);
+ *realms = NULL;
+ }
+ }
+
+ /* If there are no elements, still return a NULL terminated array */
+
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
+
+
+/*
+ * Delete the realm along with the principals belonging to the realm in the Directory.
+ */
+
+krb5_error_code
+krb5_ldap_delete_realm (context, lrealm)
+ krb5_context context;
+ char *lrealm;
+{
+ LDAP *ld = NULL;
+ krb5_error_code st = 0, tempst=0;
+ char **values=NULL, *subtrees[2]={NULL};;
+ LDAPMessage *result_arr[3]={NULL}, *result = NULL, *ent = NULL;
+ krb5_principal principal;
+ int l=0, ntree=0, i=0, j=0, mask=0;
+ kdb5_dal_handle *dal_handle = NULL;
+ krb5_ldap_context *ldap_context = NULL;
+ krb5_ldap_server_handle *ldap_server_handle = NULL;
+ krb5_ldap_realm_params *rparam=NULL;
+
+ SETUP_CONTEXT ();
+
+ if (lrealm == NULL) {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "Realm information not available");
+ goto cleanup;
+ }
+
+ if ((st=krb5_ldap_read_realm_params(context, lrealm, &rparam, &mask)) != 0)
+ goto cleanup;
+
+ /* get ldap handle */
+ GET_HANDLE ();
+
+ /* delete all the principals belonging to the realm in the tree */
+ {
+ char *attr[] = {"krbprincipalname", NULL}, *realm=NULL, filter[256];
+ krb5_ldap_context lcontext;
+
+ realm = ldap_filter_correct (lrealm, strlen (lrealm));
+ assert (sizeof (filter) >= sizeof ("(krbprincipalname=)") +
+ strlen (realm) + 2 /* "*@" */ + 1);
+
+ sprintf (filter, "(krbprincipalname=*@%s)", realm);
+ free (realm);
+
+ /* LDAP_SEARCH(NULL, LDAP_SCOPE_SUBTREE, filter, attr); */
+ memset(&lcontext, 0, sizeof(krb5_ldap_context));
+ lcontext.lrparams = rparam;
+ if ((st=krb5_get_subtree_info(&lcontext, subtrees, &ntree)) != 0)
+ goto cleanup;
+
+ for (l=0; l < ntree; ++l) {
+ LDAP_SEARCH(subtrees[l], rparam->search_scope, filter, attr);
+ result_arr[l] = result;
+ }
+ }
+
+ /* NOTE: Here all the principals should be cached and the ldap handle should be freed,
+ * as a DAL-LDAP interface is called right down here. Caching might be constrained by
+ * availability of the memory. The caching is not done, however there would be limit
+ * on the minimum number of handles for a server and it is 2. As the DAL-LDAP is not
+ * thread-safe this should suffice.
+ */
+ for (j=0; (result=result_arr[j]) != NULL; ++j) {
+ for(ent = ldap_first_entry (ld, result); ent != NULL;
+ ent = ldap_next_entry (ld, ent)) {
+ if ((values = ldap_get_values(ld, ent, "krbPrincipalName")) != NULL) {
+ for (i = 0; values[i] != NULL; ++i) {
+ krb5_parse_name(context, values[i], &principal);
+ if (principal_in_realm_2(principal, lrealm) == 0) {
+ int nent = 0;
+ if ((st=krb5_ldap_delete_principal(context, principal,
+ &nent)) != LDAP_SUCCESS)
+ goto cleanup;
+ }
+ krb5_free_principal(context, principal);
+ }
+ ldap_value_free(values);
+ }
+ }
+ ldap_msgfree(result);
+ }
+
+ /* Delete the realm object */
+ if ((st=ldap_delete_s(ld, ldap_context->lrparams->realmdn)) != LDAP_SUCCESS) {
+ int ost = st;
+ st = translate_ldap_error (st, OP_DEL);
+ krb5_set_error_message (context, st, "Realm Delete FAILED: %s",
+ ldap_err2string(ost));
+ }
+
+ cleanup:
+ for (l=0; l < ntree; ++l) {
+ if (subtrees[l])
+ free (subtrees[l]);
+ }
+ krb5_ldap_free_realm_params(rparam);
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
+
+static int compare (const void *i, const void *j) {
+ if (*(const krb5_int32 *)i > *(const krb5_int32 *)j)
+ return 1;
+
+ if (*(const krb5_int32 *)i < *(const krb5_int32 *)j)
+ return -1;
+
+ return 0;
+}
+
+
+/*
+ * Modify the realm attributes in the Directory.
+ */
+
+krb5_error_code
+krb5_ldap_modify_realm(context, rparams, mask)
+ krb5_context context;
+ krb5_ldap_realm_params *rparams;
+ int mask;
+{
+ LDAP *ld=NULL;
+ krb5_error_code st=0;
+ char *strval[5]={NULL};
+#ifdef HAVE_EDIRECTORY
+ char **values=NULL;
+ char **oldkdcservers=NULL, **oldadminservers=NULL, **oldpasswdservers=NULL;
+ LDAPMessage *result=NULL, *ent=NULL;
+ int count=0;
+ char errbuf[1024];
+#endif
+ LDAPMod **mods = NULL;
+ int i=0, oldmask=0, objectmask=0;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+
+ if (mask == 0)
+ return 0;
+
+ if (rparams == NULL) {
+ st = EINVAL;
+ return st;
+ }
+
+ SETUP_CONTEXT ();
+
+ /* Check validity of arguments */
+ if (ldap_context->krbcontainer == NULL ||
+ rparams->tl_data == NULL ||
+ rparams->tl_data->tl_data_contents == NULL ||
+ ((mask & LDAP_REALM_SUBTREE) && rparams->subtree == NULL) ||
+ /* This has to be fixed ... */
+ ((mask & LDAP_REALM_DEFENCTYPE) && rparams->suppenctypes == NULL) ||
+ ((mask & LDAP_REALM_DEFSALTTYPE) && rparams->suppsalttypes == NULL) ||
+#ifdef HAVE_EDIRECTORY
+ ((mask & LDAP_REALM_KDCSERVERS) && rparams->kdcservers == NULL) ||
+ ((mask & LDAP_REALM_ADMINSERVERS) && rparams->adminservers == NULL) ||
+ ((mask & LDAP_REALM_PASSWDSERVERS) && rparams->passwdservers == NULL) ||
+#endif
+ 0) {
+ st = EINVAL;
+ goto cleanup;
+ }
+
+ /* get ldap handle */
+ GET_HANDLE ();
+
+ /* get the oldmask obtained from the krb5_ldap_read_realm_params */
+ {
+ void *voidptr=NULL;
+
+ if ((st=decode_tl_data(rparams->tl_data, KDB_TL_MASK, &voidptr)) == 0) {
+ oldmask = *((int *) voidptr);
+ free (voidptr);
+ } else {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "tl_data not available");
+ return st;
+ }
+ }
+
+ /*
+ * Sort the list of salt-types / enc-types ... just to eliminate duplicates
+ * later.
+ */
+ {
+ if ((mask & LDAP_REALM_SUPPENCTYPE) && rparams->suppenctypes) {
+ for (i = 0; rparams->suppenctypes [i] != END_OF_LIST; i++){
+ }
+ qsort ((void *)rparams->suppenctypes, (unsigned) i, sizeof(krb5_int32), compare);
+ }
+ if ((mask & LDAP_REALM_SUPPSALTTYPE) && rparams->suppsalttypes) {
+ for (i = 0; rparams->suppenctypes [i] != END_OF_LIST; i++){
+ }
+ qsort ((void *)rparams->suppsalttypes, (unsigned) i, sizeof(krb5_int32), compare);
+ }
+ }
+
+ /* SUBTREE ATTRIBUTE */
+ if (mask & LDAP_REALM_SUBTREE) {
+ if (strlen(rparams->subtree) != 0) {
+ st = checkattributevalue(ld, rparams->subtree, "Objectclass", subtreeclass,
+ &objectmask);
+ CHECK_CLASS_VALIDITY(st, objectmask, "subtree value: ");
+ }
+ memset(strval, 0, sizeof(strval));
+ strval[0] = rparams->subtree;
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbsubtree", LDAP_MOD_REPLACE,
+ strval)) != 0)
+ goto cleanup;
+ }
+
+ /* SEARCHSCOPE ATTRIBUTE */
+ if (mask & LDAP_REALM_SEARCHSCOPE) {
+ if((st=krb5_add_int_mem_ldap_mod(&mods, "krbsearchscope", LDAP_MOD_REPLACE,
+ (rparams->search_scope == LDAP_SCOPE_ONELEVEL
+ || rparams->search_scope == LDAP_SCOPE_SUBTREE) ?
+ rparams->search_scope : LDAP_SCOPE_SUBTREE)) != 0)
+ goto cleanup;
+ }
+
+ if (mask & LDAP_REALM_MAXRENEWLIFE) {
+
+ if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxRenewableAge", LDAP_MOD_REPLACE,
+ rparams->max_renewable_life)) != 0)
+ goto cleanup;
+ }
+
+ /* krbMaxTicketLife ATTRIBUTE */
+
+ if (mask & LDAP_REALM_MAXTICKETLIFE) {
+
+ if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxTicketLife", LDAP_MOD_REPLACE,
+ rparams->max_life)) != 0)
+ goto cleanup;
+ }
+
+ /* krbTicketFlags ATTRIBUTE */
+
+ if (mask & LDAP_REALM_KRBTICKETFLAGS) {
+
+ if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbTicketFlags", LDAP_MOD_REPLACE,
+ rparams->tktflags)) != 0)
+ goto cleanup;
+ }
+
+
+ /* DEFENCTYPE ATTRIBUTE */
+ if (mask & LDAP_REALM_DEFENCTYPE) {
+ /* check if the entered enctype is valid */
+ if (krb5_c_valid_enctype(rparams->defenctype)) {
+
+ /* check if the defenctype exists in the suppenctypes list */
+ for(i = 0; rparams->suppenctypes[i] != END_OF_LIST; ++i)
+ if (rparams->defenctype == rparams->suppenctypes[i])
+ break;
+
+ /* touching the end of list means defenctype is missing */
+ if (rparams->suppenctypes[i] == END_OF_LIST) {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "Default enctype not in the supported list");
+ goto cleanup;
+ }
+
+ if((st=krb5_add_int_mem_ldap_mod(&mods, "krbdefaultenctype", LDAP_MOD_REPLACE,
+ rparams->defenctype)) != 0)
+ goto cleanup;
+ } else {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "Invalid default enctype");
+ goto cleanup;
+ }
+ }
+
+ /* DEFSALTTYPE ATTRIBUTE */
+ if (mask & LDAP_REALM_DEFSALTTYPE) {
+ /* check if the entered salttype is valid */
+ if (rparams->defsalttype>=0 && rparams->defsalttype<6) {
+
+ /* check if the defsalttype exists in the suppsalttypes list */
+ for(i = 0; rparams->suppsalttypes[i] != END_OF_LIST; ++i)
+ if (rparams->defsalttype == rparams->suppsalttypes[i])
+ break;
+
+ /* touching the end of the list means defsalttype is missing */
+ if (rparams->suppsalttypes[i] == END_OF_LIST) {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "Default salttype not in the supported list");
+ goto cleanup;
+ }
+
+ if((st=krb5_add_int_mem_ldap_mod(&mods, "krbdefaultsalttype",
+ LDAP_MOD_REPLACE, rparams->defsalttype)) != 0)
+ goto cleanup;
+
+ } else {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "Invalid default salttype");
+ goto cleanup;
+ }
+ }
+
+ /* SUPPSALTTYPE ATTRIBUTE */
+ if (mask & LDAP_REALM_SUPPSALTTYPE) {
+ krb5_boolean flag=FALSE;
+
+ for (i = 0; rparams->suppsalttypes[i] != END_OF_LIST; ++i) {
+ /* check if the salttypes entered is valid */
+ if (!(rparams->suppsalttypes[i]>=0 && rparams->suppsalttypes[i]<6)) {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "salttype %d not valid", rparams->suppsalttypes[i]);
+ goto cleanup;
+ }
+
+ /* Ensure that the default salt type is supported */
+ if ((oldmask & LDAP_REALM_DEFSALTTYPE ||
+ mask & LDAP_REALM_DEFSALTTYPE) &&
+ rparams->defsalttype == rparams->suppsalttypes[i])
+ flag = TRUE;
+ }
+
+ if (flag == FALSE) { /* Default salt type is not supported */
+ st = EINVAL;
+ krb5_set_error_message (context, st, "Default salttype not in the supported list");
+ goto cleanup;
+ }
+ ignore_duplicates(rparams->suppsalttypes);
+
+ if((st=krb5_add_int_arr_mem_ldap_mod(&mods, "krbsupportedsalttypes",
+ LDAP_MOD_REPLACE, rparams->suppsalttypes)) != 0)
+ goto cleanup;
+ }
+
+ /* SUPPENCTYPE ATTRIBUTE */
+ if (mask & LDAP_REALM_SUPPENCTYPE) {
+ krb5_boolean flag=FALSE;
+
+ for(i=0; rparams->suppenctypes[i] != END_OF_LIST; ++i) {
+
+ /* check if the enctypes entered is valid */
+ if (krb5_c_valid_enctype(rparams->suppenctypes[i]) == 0) {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "Enctype %d not valid", rparams->suppenctypes[i]);
+ goto cleanup;
+ }
+
+ /* Ensure that the default encryption type is supported */
+ if ((oldmask & LDAP_REALM_DEFENCTYPE ||
+ mask & LDAP_REALM_DEFENCTYPE) &&
+ rparams->defenctype == rparams->suppenctypes[i])
+ flag = TRUE;
+ }
+
+ if (flag == FALSE) { /* Default encryption type is not supported */
+ st = EINVAL;
+ krb5_set_error_message(context, st, "Default enctype not in the supported list");
+ goto cleanup;
+ }
+ ignore_duplicates(rparams->suppenctypes);
+
+ if((st=krb5_add_int_arr_mem_ldap_mod(&mods, "krbsupportedenctypes",
+ LDAP_MOD_REPLACE, rparams->suppenctypes)) != 0)
+ goto cleanup;
+ }
+
+#ifdef HAVE_EDIRECTORY
+
+ /* KDCSERVERS ATTRIBUTE */
+ if (mask & LDAP_REALM_KDCSERVERS) {
+ /* validate the server list */
+ for (i=0; rparams->kdcservers[i] != NULL; ++i) {
+ st = checkattributevalue(ld, rparams->kdcservers[i], "objectClass", kdcclass,
+ &objectmask);
+ CHECK_CLASS_VALIDITY(st, objectmask, "kdc service object value: ");
+ }
+
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbkdcservers", LDAP_MOD_REPLACE,
+ rparams->kdcservers)) != 0)
+ goto cleanup;
+ }
+
+ /* ADMINSERVERS ATTRIBUTE */
+ if (mask & LDAP_REALM_ADMINSERVERS) {
+ /* validate the server list */
+ for (i=0; rparams->adminservers[i] != NULL; ++i) {
+ st = checkattributevalue(ld, rparams->adminservers[i], "objectClass", adminclass,
+ &objectmask);
+ CHECK_CLASS_VALIDITY(st, objectmask, "admin service object value: ");
+ }
+
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbadmservers", LDAP_MOD_REPLACE,
+ rparams->adminservers)) != 0)
+ goto cleanup;
+ }
+
+ /* PASSWDSERVERS ATTRIBUTE */
+ if (mask & LDAP_REALM_PASSWDSERVERS) {
+ /* validate the server list */
+ for (i=0; rparams->passwdservers[i] != NULL; ++i) {
+ st = checkattributevalue(ld, rparams->passwdservers[i], "objectClass", pwdclass,
+ &objectmask);
+ CHECK_CLASS_VALIDITY(st, objectmask, "password service object value: ");
+ }
+
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdservers", LDAP_MOD_REPLACE,
+ rparams->passwdservers)) != 0)
+ goto cleanup;
+ }
+
+ /*
+ * Read the old values of the krbkdcservers, krbadmservers and
+ * krbpwdservers. This information is later used to decided the
+ * deletions/additions to the list.
+ */
+ if (mask & LDAP_REALM_KDCSERVERS || mask & LDAP_REALM_ADMINSERVERS ||
+ mask & LDAP_REALM_PASSWDSERVERS) {
+ char *servers[] = {"krbKdcServers", "krbAdmServers", "krbPwdServers", NULL};
+
+ if ((st= ldap_search_s(ld,
+ rparams->realmdn,
+ LDAP_SCOPE_BASE,
+ 0,
+ servers,
+ 0,
+ &result)) != LDAP_SUCCESS) {
+ st = set_ldap_error (context, st, OP_SEARCH);
+ goto cleanup;
+ }
+
+ ent = ldap_first_entry(ld, result);
+ if (ent) {
+ if ((values=ldap_get_values(ld, ent, "krbKdcServers")) != NULL) {
+ count = ldap_count_values(values);
+ if ((st=copy_arrays(values, &oldkdcservers, count)) != 0)
+ goto cleanup;
+ ldap_value_free(values);
+ }
+
+ if ((values=ldap_get_values(ld, ent, "krbAdmServers")) != NULL) {
+ count = ldap_count_values(values);
+ if ((st=copy_arrays(values, &oldadminservers, count)) != 0)
+ goto cleanup;
+ ldap_value_free(values);
+ }
+
+ if ((values=ldap_get_values(ld, ent, "krbPwdServers")) != NULL) {
+ count = ldap_count_values(values);
+ if ((st=copy_arrays(values, &oldpasswdservers, count)) != 0)
+ goto cleanup;
+ ldap_value_free(values);
+ }
+ }
+ ldap_msgfree(result);
+ }
+#endif
+
+ /* Realm modify opearation */
+ if ((st=ldap_modify_s(ld, rparams->realmdn, mods)) != LDAP_SUCCESS) {
+ st = set_ldap_error (context, st, OP_MOD);
+ goto cleanup;
+ }
+
+#ifdef HAVE_EDIRECTORY
+ /* krbRealmReferences attribute is updated here, depending on the additions/deletions
+ * to the 4 servers' list.
+ */
+ if (mask & LDAP_REALM_KDCSERVERS) {
+ char **newkdcservers=NULL;
+
+ count = ldap_count_values(rparams->kdcservers);
+ if ((st=copy_arrays(rparams->kdcservers, &newkdcservers, count)) != 0)
+ goto cleanup;
+
+ /* find the deletions and additions to the server list */
+ if (oldkdcservers && newkdcservers)
+ disjoint_members(oldkdcservers, newkdcservers);
+
+ /* delete the krbRealmReferences attribute from the servers that are dis-associated. */
+ if (oldkdcservers)
+ for (i=0; oldkdcservers[i]; ++i)
+ if ((st=deleteAttribute(ld, oldkdcservers[i], "krbRealmReferences",
+ rparams->realmdn)) != 0)
+ {
+ sprintf (errbuf, "Error removing 'krbRealmReferences' from %s: ",
+ oldkdcservers[i]);
+ prepend_err_str (context, errbuf, st, st);
+ goto cleanup;
+ }
+
+ /* add the krbRealmReferences attribute from the servers that are associated. */
+ if (newkdcservers)
+ for (i=0; newkdcservers[i]; ++i)
+ if ((st=updateAttribute(ld, newkdcservers[i], "krbRealmReferences",
+ rparams->realmdn)) != 0)
+ {
+ sprintf (errbuf, "Error adding 'krbRealmReferences' to %s: ",
+ newkdcservers[i]);
+ prepend_err_str (context, errbuf, st, st);
+ goto cleanup;
+ }
+
+ if (newkdcservers)
+ ldap_value_free(newkdcservers);
+ }
+
+ if (mask & LDAP_REALM_ADMINSERVERS) {
+ char **newadminservers=NULL;
+
+ count = ldap_count_values(rparams->adminservers);
+ if ((st=copy_arrays(rparams->adminservers, &newadminservers, count)) != 0)
+ goto cleanup;
+
+ /* find the deletions and additions to the server list */
+ if (oldadminservers && newadminservers)
+ disjoint_members(oldadminservers, newadminservers);
+
+ /* delete the krbRealmReferences attribute from the servers that are dis-associated. */
+ if (oldadminservers)
+ for (i=0; oldadminservers[i]; ++i)
+ if ((st=deleteAttribute(ld, oldadminservers[i], "krbRealmReferences",
+ rparams->realmdn)) != 0)
+ {
+ sprintf(errbuf, "Error removing 'krbRealmReferences' from "
+ "%s: ", oldadminservers[i]);
+ prepend_err_str (context, errbuf, st, st);
+ goto cleanup;
+ }
+
+ /* add the krbRealmReferences attribute from the servers that are associated. */
+ if (newadminservers)
+ for (i=0; newadminservers[i]; ++i)
+ if ((st=updateAttribute(ld, newadminservers[i], "krbRealmReferences",
+ rparams->realmdn)) != 0)
+ {
+ sprintf(errbuf, "Error adding 'krbRealmReferences' to %s: ",
+ newadminservers[i]);
+ prepend_err_str (context, errbuf, st, st);
+ goto cleanup;
+ }
+ if (newadminservers)
+ ldap_value_free(newadminservers);
+ }
+
+ if (mask & LDAP_REALM_PASSWDSERVERS) {
+ char **newpasswdservers=NULL;
+
+ count = ldap_count_values(rparams->passwdservers);
+ if ((st=copy_arrays(rparams->passwdservers, &newpasswdservers, count)) != 0)
+ goto cleanup;
+
+ /* find the deletions and additions to the server list */
+ if (oldpasswdservers && newpasswdservers)
+ disjoint_members(oldpasswdservers, newpasswdservers);
+
+ /* delete the krbRealmReferences attribute from the servers that are dis-associated. */
+ if (oldpasswdservers)
+ for (i=0; oldpasswdservers[i]; ++i)
+ if ((st=deleteAttribute(ld, oldpasswdservers[i], "krbRealmReferences",
+ rparams->realmdn)) != 0)
+ {
+ sprintf(errbuf, "Error removing 'krbRealmReferences' from "
+ "%s: ", oldpasswdservers[i]);
+ prepend_err_str (context, errbuf, st, st);
+ goto cleanup;
+ }
+
+ /* add the krbRealmReferences attribute from the servers that are associated. */
+ if (newpasswdservers)
+ for (i=0; newpasswdservers[i]; ++i)
+ if ((st=updateAttribute(ld, newpasswdservers[i], "krbRealmReferences",
+ rparams->realmdn)) != 0)
+ {
+ sprintf(errbuf, "Error adding 'krbRealmReferences' to %s: ",
+ newpasswdservers[i]);
+ prepend_err_str (context, errbuf, st, st);
+ goto cleanup;
+ }
+ if (newpasswdservers)
+ ldap_value_free(newpasswdservers);
+ }
+#endif
+
+ cleanup:
+
+#ifdef HAVE_EDIRECTORY
+ if (oldkdcservers) {
+ for(i=0; oldkdcservers[i]; ++i)
+ free(oldkdcservers[i]);
+ free(oldkdcservers);
+ }
+
+ if (oldadminservers) {
+ for(i=0; oldadminservers[i]; ++i)
+ free(oldadminservers[i]);
+ free(oldadminservers);
+ }
+
+ if (oldpasswdservers) {
+ for(i=0; oldpasswdservers[i]; ++i)
+ free(oldpasswdservers[i]);
+ free(oldpasswdservers);
+ }
+#endif
+
+ ldap_mods_free(mods, 1);
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
+
+
+
+/*
+ * Create the Kerberos container in the Directory
+ */
+
+krb5_error_code
+krb5_ldap_create_krbcontainer(context, krbcontparams)
+ krb5_context context;
+ const krb5_ldap_krbcontainer_params *krbcontparams;
+{
+ LDAP *ld=NULL;
+ char *strval[2]={NULL}, *kerberoscontdn=NULL, **rdns=NULL;
+ int pmask=0;
+ LDAPMod **mods = NULL;
+ krb5_error_code st=0;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+#ifdef HAVE_EDIRECTORY
+ int crmask=0;
+#endif
+
+ SETUP_CONTEXT ();
+
+ /* get ldap handle */
+ GET_HANDLE ();
+
+ if (krbcontparams != NULL && krbcontparams->DN != NULL) {
+ kerberoscontdn = krbcontparams->DN;
+ } else {
+ /* If the user has not given, use the default cn=Kerberos,cn=Security */
+#ifdef HAVE_EDIRECTORY
+ kerberoscontdn = KERBEROS_CONTAINER;
+#else
+ st = EINVAL;
+ krb5_set_error_message (context, st, "Kerberos Container information is missing");
+ goto cleanup;
+#endif
+ }
+
+ strval[0] = "krbContainer";
+ strval[1] = NULL;
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
+ goto cleanup;
+
+ rdns = ldap_explode_dn(kerberoscontdn, 1);
+ if (rdns == NULL) {
+ st = EINVAL;
+ krb5_set_error_message(context, st, "Invalid Kerberos container DN");
+ goto cleanup;
+ }
+
+ strval[0] = rdns[0];
+ strval[1] = NULL;
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0)
+ goto cleanup;
+
+ /* check if the policy reference value exists and is of krbpolicyreference object class */
+ if (krbcontparams && krbcontparams->policyreference) {
+ st = checkattributevalue(ld, krbcontparams->policyreference, "objectclass", policyclass,
+ &pmask);
+ CHECK_CLASS_VALIDITY(st, pmask, "ticket policy object value: ");
+
+ strval[0] = krbcontparams->policyreference;
+ strval[1] = NULL;
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpolicyreference", LDAP_MOD_ADD,
+ strval)) != 0)
+ goto cleanup;
+ }
+
+ /* create the kerberos container */
+ if ((st = ldap_add_s(ld, kerberoscontdn, mods)) != LDAP_SUCCESS) {
+ int ost = st;
+ st = translate_ldap_error (st, OP_ADD);
+ krb5_set_error_message (context, st, "Kerberos Container create FAILED: %s", ldap_err2string(ost));
+ goto cleanup;
+ }
+
+#ifdef HAVE_EDIRECTORY
+
+ /* free the mods array */
+ ldap_mods_free(mods, 1);
+ mods=NULL;
+
+ /* check whether the security container is bound to krbcontainerrefaux object class */
+ if ((st=checkattributevalue(ld, SECURITY_CONTAINER, "objectClass",
+ krbContainerRefclass, &crmask)) != 0)
+ {
+ prepend_err_str (context, "Security Container read FAILED: ", st, st);
+ /* delete Kerberos Container, status ignored intentionally */
+ ldap_delete_s(ld, kerberoscontdn);
+ goto cleanup;
+ }
+
+ if (crmask == 0) {
+ /* Security Container is extended with krbcontainerrefaux object class */
+ strval[0] = "krbContainerRefAux";
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
+ goto cleanup;
+ }
+
+ strval[0] = kerberoscontdn;
+ strval[1] = NULL;
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbcontainerreference", LDAP_MOD_ADD, strval)) != 0)
+ goto cleanup;
+
+ /* update the security container with krbContainerReference attribute */
+ if ((st=ldap_modify_s(ld, SECURITY_CONTAINER, mods)) != LDAP_SUCCESS) {
+ int ost = st;
+ st = translate_ldap_error (st, OP_MOD);
+ krb5_set_error_message (context, st, "Security Container update FAILED: %s", ldap_err2string(ost));
+ /* delete Kerberos Container, status ignored intentionally */
+ ldap_delete_s(ld, kerberoscontdn);
+ goto cleanup;
+ }
+#endif
+
+ cleanup:
+
+ if (rdns)
+ ldap_value_free (rdns);
+
+ ldap_mods_free(mods, 1);
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return(st);
+}
+
+
+/*
+ * Create Realm in eDirectory. This is used by kdb5_util
+ */
+
+krb5_error_code
+krb5_ldap_create_realm(context, rparams, mask)
+ krb5_context context;
+ krb5_ldap_realm_params *rparams;
+ int mask;
+{
+ LDAP *ld=NULL;
+ krb5_error_code st=0;
+ char *dn=NULL;
+ char *strval[4]={NULL};
+ LDAPMod **mods = NULL;
+ int i=0, objectmask=0;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+#ifdef HAVE_EDIRECTORY
+ char errbuf[1024];
+#endif
+ char *realm_name;
+
+ SETUP_CONTEXT ();
+
+ /* Check input validity ... */
+ if (ldap_context->krbcontainer == NULL ||
+ ldap_context->krbcontainer->DN == NULL ||
+ rparams == NULL ||
+ rparams->realm_name == NULL ||
+ ((mask & LDAP_REALM_SUBTREE) && rparams->subtree == NULL) ||
+ ((mask & LDAP_REALM_POLICYREFERENCE) && rparams->policyreference == NULL) ||
+ ((mask & LDAP_REALM_SUPPSALTTYPE) && rparams->suppsalttypes == NULL) ||
+ ((mask & LDAP_REALM_SUPPENCTYPE) && rparams->suppenctypes == NULL) ||
+#ifdef HAVE_EDIRECTORY
+ ((mask & LDAP_REALM_KDCSERVERS) && rparams->kdcservers == NULL) ||
+ ((mask & LDAP_REALM_ADMINSERVERS) && rparams->adminservers == NULL) ||
+ ((mask & LDAP_REALM_PASSWDSERVERS) && rparams->passwdservers == NULL) ||
+#endif
+ 0) {
+ st = EINVAL;
+ return st;
+ }
+
+ if (ldap_context->krbcontainer == NULL) {
+ if ((st = krb5_ldap_read_krbcontainer_params(context,
+ &(ldap_context->krbcontainer))) != 0)
+ goto cleanup;
+ }
+
+ /* get ldap handle */
+ GET_HANDLE ();
+
+ realm_name = rparams->realm_name;
+
+ dn = malloc(strlen("cn=") + strlen(realm_name) + strlen(ldap_context->krbcontainer->DN) + 2);
+ CHECK_NULL(dn);
+ sprintf(dn, "cn=%s,%s", realm_name, ldap_context->krbcontainer->DN);
+
+ strval[0] = realm_name;
+ strval[1] = NULL;
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0)
+ goto cleanup;
+
+ strval[0] = "top";
+ strval[1] = "krbrealmcontainer";
+ strval[2] = "krbpolicyaux";
+ strval[3] = NULL;
+
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
+ goto cleanup;
+
+ /* SUBTREE ATTRIBUTE */
+ if (mask & LDAP_REALM_SUBTREE) {
+ if (strlen(rparams->subtree) != 0) {
+ st = checkattributevalue(ld, rparams->subtree, "Objectclass", subtreeclass,
+ &objectmask);
+ CHECK_CLASS_VALIDITY(st, objectmask, "realm object value: ");
+
+ }
+ strval[0] = rparams->subtree;
+ strval[1] = NULL;
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbsubtree", LDAP_MOD_ADD,
+ strval)) != 0)
+ goto cleanup;
+ }
+
+ /* SEARCHSCOPE ATTRIBUTE */
+ if (mask & LDAP_REALM_SEARCHSCOPE) {
+ if((st=krb5_add_int_mem_ldap_mod(&mods, "krbsearchscope", LDAP_MOD_ADD,
+ (rparams->search_scope == LDAP_SCOPE_ONELEVEL
+ || rparams->search_scope == LDAP_SCOPE_SUBTREE) ?
+ rparams->search_scope : LDAP_SCOPE_SUBTREE)) != 0)
+ goto cleanup;
+ }
+ if (mask & LDAP_REALM_MAXRENEWLIFE) {
+
+ if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxRenewableAge", LDAP_MOD_ADD,
+ rparams->max_renewable_life)) != 0)
+ goto cleanup;
+ }
+
+ /* krbMaxTicketLife ATTRIBUTE */
+
+ if (mask & LDAP_REALM_MAXTICKETLIFE) {
+
+ if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxTicketLife", LDAP_MOD_ADD,
+ rparams->max_life)) != 0)
+ goto cleanup;
+ }
+
+ /* krbTicketFlags ATTRIBUTE */
+
+ if (mask & LDAP_REALM_KRBTICKETFLAGS) {
+
+ if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbTicketFlags", LDAP_MOD_ADD,
+ rparams->tktflags)) != 0)
+ goto cleanup;
+ }
+
+
+ /* DEFAULTENCTYPE ATTRIBUTE */
+ if (mask & LDAP_REALM_DEFENCTYPE) {
+ /* check if the entered enctype is valid */
+ if (krb5_c_valid_enctype(rparams->defenctype)) {
+
+ /* check if the defenctype exists in the suppenctypes list */
+ if (mask & LDAP_REALM_SUPPENCTYPE) {
+ for(i=0; rparams->suppenctypes[i] != END_OF_LIST; ++i)
+ if (rparams->defenctype == rparams->suppenctypes[i])
+ break;
+
+ if (rparams->suppenctypes[i] == END_OF_LIST) {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "Default enctype not in the "
+ "supported list");
+ goto cleanup;
+ }
+ }
+ if((st=krb5_add_int_mem_ldap_mod(&mods, "krbdefaultenctype", LDAP_MOD_ADD,
+ rparams->defenctype)) != 0)
+ goto cleanup;
+ } else {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "Default enctype not valid");
+ goto cleanup;
+ }
+ }
+
+ /* DEFAULTSALTTYPE ATTRIBUTE */
+ if (mask & LDAP_REALM_DEFSALTTYPE) {
+ /* check if the entered salttype is valid */
+ if (rparams->defsalttype >=0 && rparams->defsalttype<6) {
+
+ /* check if the defsalttype exists in the suppsalttypes list */
+ if (mask & LDAP_REALM_SUPPSALTTYPE) {
+ for(i=0; rparams->suppsalttypes[i] != END_OF_LIST; ++i)
+ if (rparams->defsalttype == rparams->suppsalttypes[i])
+ break;
+
+ if (rparams->suppsalttypes[i] == END_OF_LIST) {
+ st = EINVAL;
+ krb5_set_error_message (context, st,
+ "Default salttype not in the supported list");
+ goto cleanup;
+ }
+ }
+
+ if((st=krb5_add_int_mem_ldap_mod(&mods, "krbdefaultsalttype", LDAP_MOD_ADD,
+ rparams->defsalttype)) != 0)
+ goto cleanup;
+ } else {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "Default salttype not valid");
+ goto cleanup;
+ }
+ }
+
+ /* SUPPORTEDSALTTYPE ATTRIBUTE */
+ if (mask & LDAP_REALM_SUPPSALTTYPE) {
+ for(i=0; rparams->suppsalttypes[i] != END_OF_LIST; ++i) {
+ /* check if the salttypes entered is valid */
+ if (!(rparams->suppsalttypes[i]>=0 && rparams->suppsalttypes[i]<6)) {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "Salttype %d not valid",
+ rparams->suppsalttypes[i]);
+ goto cleanup;
+ }
+ }
+ ignore_duplicates(rparams->suppsalttypes);
+
+ if((st=krb5_add_int_arr_mem_ldap_mod(&mods, "krbsupportedsalttypes", LDAP_MOD_ADD,
+ rparams->suppsalttypes)) != 0)
+ goto cleanup;
+ } else {
+ /* set all the salt types as the suppsalttypes */
+ if((st=krb5_add_int_arr_mem_ldap_mod(&mods, "krbsupportedsalttypes", LDAP_MOD_ADD,
+ supportedsalttypes)) != 0)
+ goto cleanup;
+ }
+
+ /* SUPPORTEDENCTYPE ATTRIBUTE */
+ if (mask & LDAP_REALM_SUPPENCTYPE) {
+ for(i=0; rparams->suppenctypes[i] != -1; ++i) {
+
+ /* check if the enctypes entered is valid */
+ if (krb5_c_valid_enctype(rparams->suppenctypes[i]) == 0) {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "Enctype %d not valid",
+ rparams->suppenctypes[i]);
+ goto cleanup;
+ }
+ }
+ ignore_duplicates(rparams->suppenctypes);
+
+ if((st=krb5_add_int_arr_mem_ldap_mod(&mods, "krbsupportedenctypes", LDAP_MOD_ADD,
+ rparams->suppenctypes)) != 0)
+ goto cleanup;
+ } else {
+ /* set all the enc types as the suppenctypes */
+ if((st=krb5_add_int_arr_mem_ldap_mod(&mods, "krbsupportedenctypes", LDAP_MOD_ADD,
+ supportedenctypes)) != 0)
+ goto cleanup;
+ }
+
+#ifdef HAVE_EDIRECTORY
+
+ /* KDCSERVERS ATTRIBUTE */
+ if (mask & LDAP_REALM_KDCSERVERS) {
+ /* validate the server list */
+ for (i=0; rparams->kdcservers[i] != NULL; ++i) {
+ st = checkattributevalue(ld, rparams->kdcservers[i], "objectClass", kdcclass,
+ &objectmask);
+ CHECK_CLASS_VALIDITY(st, objectmask, "kdc service object value: ");
+
+ }
+
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbkdcservers", LDAP_MOD_ADD,
+ rparams->kdcservers)) != 0)
+ goto cleanup;
+ }
+
+ /* ADMINSERVERS ATTRIBUTE */
+ if (mask & LDAP_REALM_ADMINSERVERS) {
+ /* validate the server list */
+ for (i=0; rparams->adminservers[i] != NULL; ++i) {
+ st = checkattributevalue(ld, rparams->adminservers[i], "objectClass", adminclass,
+ &objectmask);
+ CHECK_CLASS_VALIDITY(st, objectmask, "admin service object value: ");
+
+ }
+
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbadmservers", LDAP_MOD_ADD,
+ rparams->adminservers)) != 0)
+ goto cleanup;
+ }
+
+ /* PASSWDSERVERS ATTRIBUTE */
+ if (mask & LDAP_REALM_PASSWDSERVERS) {
+ /* validate the server list */
+ for (i=0; rparams->passwdservers[i] != NULL; ++i) {
+ st = checkattributevalue(ld, rparams->passwdservers[i], "objectClass", pwdclass,
+ &objectmask);
+ CHECK_CLASS_VALIDITY(st, objectmask, "password service object value: ");
+
+ }
+
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdservers", LDAP_MOD_ADD,
+ rparams->passwdservers)) != 0)
+ goto cleanup;
+ }
+#endif
+
+ /* realm creation operation */
+ if ((st=ldap_add_s(ld, dn, mods)) != LDAP_SUCCESS) {
+ st = set_ldap_error (context, st, OP_ADD);
+ goto cleanup;
+ }
+
+#ifdef HAVE_EDIRECTORY
+ if (mask & LDAP_REALM_KDCSERVERS)
+ for (i=0; rparams->kdcservers[i]; ++i)
+ if ((st=updateAttribute(ld, rparams->kdcservers[i], "krbRealmReferences", dn)) != 0)
+ {
+ sprintf(errbuf, "Error adding 'krbRealmReferences' to %s: ",
+ rparams->kdcservers[i]);
+ prepend_err_str (context, errbuf, st, st);
+ /* delete Realm, status ignored intentionally */
+ ldap_delete_s(ld, dn);
+ goto cleanup;
+ }
+
+ if (mask & LDAP_REALM_ADMINSERVERS)
+ for (i=0; rparams->adminservers[i]; ++i)
+ if ((st=updateAttribute(ld, rparams->adminservers[i], "krbRealmReferences", dn)) != 0)
+ {
+ sprintf(errbuf, "Error adding 'krbRealmReferences' to %s: ",
+ rparams->adminservers[i]);
+ prepend_err_str (context, errbuf, st, st);
+ /* delete Realm, status ignored intentionally */
+ ldap_delete_s(ld, dn);
+ goto cleanup;
+ }
+
+ if (mask & LDAP_REALM_PASSWDSERVERS)
+ for (i=0; rparams->passwdservers[i]; ++i)
+ if ((st=updateAttribute(ld, rparams->passwdservers[i], "krbRealmReferences", dn)) != 0)
+ {
+ sprintf(errbuf, "Error adding 'krbRealmReferences' to %s: ",
+ rparams->passwdservers[i]);
+ prepend_err_str (context, errbuf, st, st);
+ /* delete Realm, status ignored intentionally */
+ ldap_delete_s(ld, dn);
+ goto cleanup;
+ }
+#endif
+
+ cleanup:
+
+ if (dn)
+ free(dn);
+
+ ldap_mods_free(mods, 1);
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
+
+/*
+ * Read the realm container configuration from eDirectory for the specified realm.
+ */
+
+krb5_error_code
+krb5_ldap_read_realm_params(context, lrealm, rlparamp, mask)
+ krb5_context context;
+ char *lrealm;
+ krb5_ldap_realm_params **rlparamp;
+ int *mask;
+{
+ char **values=NULL, *krbcontDN=NULL /*, *curr=NULL */;
+ unsigned int i=0, /* masklen=4, */ count=0;
+ krb5_error_code st=0, tempst=0;
+ LDAP *ld=NULL;
+ LDAPMessage *result=NULL,*ent=NULL;
+ krb5_ldap_realm_params *rlparams=NULL;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+
+ SETUP_CONTEXT ();
+
+ /* validate the input parameter */
+ if (lrealm == NULL ||
+ ldap_context->krbcontainer == NULL ||
+ ldap_context->krbcontainer->DN == NULL) {
+ st = EINVAL;
+ goto cleanup;
+ }
+
+ /* read kerberos container, if not read already */
+ if (ldap_context->krbcontainer == NULL) {
+ if ((st = krb5_ldap_read_krbcontainer_params(context,
+ &(ldap_context->krbcontainer))) != 0)
+ goto cleanup;
+ }
+ /* get ldap handle */
+ GET_HANDLE ();
+
+ /* Initialize realm container structure */
+ rlparams =(krb5_ldap_realm_params *) malloc(sizeof(krb5_ldap_realm_params));
+ CHECK_NULL(rlparams);
+ memset((char *) rlparams, 0, sizeof(krb5_ldap_realm_params));
+
+ /* allocate tl_data structure to store MASK information */
+ rlparams->tl_data = malloc (sizeof(krb5_tl_data));
+ if (rlparams->tl_data == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ memset((char *) rlparams->tl_data, 0, sizeof(krb5_tl_data));
+ rlparams->tl_data->tl_data_type = KDB_TL_USER_INFO;
+
+ /* set the mask parameter to 0 */
+ *mask = 0;
+
+ /* set default values */
+ rlparams->search_scope = LDAP_SCOPE_SUBTREE;
+
+ krbcontDN = ldap_context->krbcontainer->DN;
+
+ rlparams->realmdn = (char *) malloc(strlen("cn=") + strlen(lrealm) + strlen(krbcontDN) + 2);
+ if (rlparams->realmdn == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ sprintf(rlparams->realmdn, "cn=%s,%s", lrealm, krbcontDN);
+
+ /* populate the realm name in the structure */
+ rlparams->realm_name = strdup(lrealm);
+ CHECK_NULL(rlparams->realm_name);
+
+ LDAP_SEARCH(rlparams->realmdn, LDAP_SCOPE_BASE, "(objectclass=krbRealmContainer)", realm_attributes);
+
+ ent = ldap_first_entry (ld, result);
+ if (ent == NULL) {
+ ldap_get_option (ld, LDAP_OPT_ERROR_NUMBER, (void *) &st);
+#if 0
+ st = translate_ldap_error(st, OP_SEARCH);
+#endif
+ goto cleanup;
+ }
+
+ /* Read the attributes */
+ {
+
+ if((values=ldap_get_values(ld, ent, "krbSubTree")) != NULL) {
+ rlparams->subtree = strdup(values[0]);
+ if(rlparams->subtree==NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ *mask |= LDAP_REALM_SUBTREE;
+ ldap_value_free(values);
+ }
+
+ if((values=ldap_get_values(ld, ent, "krbSearchScope")) != NULL) {
+ rlparams->search_scope=atoi(values[0]);
+ /* searchscope can be ONE-LEVEL or SUBTREE, else default to SUBTREE */
+ if (!(rlparams->search_scope==1 || rlparams->search_scope==2))
+ rlparams->search_scope = LDAP_SCOPE_SUBTREE;
+ *mask |= LDAP_REALM_SEARCHSCOPE;
+ ldap_value_free(values);
+ }
+
+ if((values=ldap_get_values(ld, ent, "krbMaxTicketLife")) != NULL) {
+ rlparams->max_life = atoi(values[0]);
+ *mask |= LDAP_REALM_MAXTICKETLIFE;
+ ldap_value_free(values);
+ }
+
+ if((values=ldap_get_values(ld, ent, "krbMaxRenewableAge")) != NULL) {
+ rlparams->max_renewable_life = atoi(values[0]);
+ *mask |= LDAP_REALM_MAXRENEWLIFE;
+ ldap_value_free(values);
+ }
+
+ if((values=ldap_get_values(ld, ent, "krbTicketFlags")) != NULL) {
+ rlparams->tktflags = atoi(values[0]);
+ *mask |= LDAP_REALM_KRBTICKETFLAGS;
+ ldap_value_free(values);
+ }
+
+ if((values=ldap_get_values(ld, ent, "krbDefaultEncType")) != NULL) {
+ rlparams->defenctype = atoi(values[0]);
+ if (krb5_c_valid_enctype(rlparams->defenctype) == 0)
+ rlparams->defenctype = ENCTYPE_DES3_CBC_SHA1;
+ *mask |= LDAP_REALM_DEFENCTYPE;
+ ldap_value_free(values);
+ }
+
+ if((values=ldap_get_values(ld, ent, "krbDefaultSaltType")) != NULL) {
+ rlparams->defsalttype = atoi(values[0]);
+ if (!(rlparams->defsalttype>=0 && rlparams->defsalttype<6))
+ rlparams->defsalttype = KRB5_KDB_SALTTYPE_NORMAL;
+ *mask |= LDAP_REALM_DEFSALTTYPE;
+ ldap_value_free(values);
+ }
+ if((values=ldap_get_values(ld, ent, "krbSupportedEncTypes")) != NULL) {
+ count = ldap_count_values(values);
+ rlparams->suppenctypes = malloc (sizeof(krb5_int32) * (count + 1));
+ if (rlparams->suppenctypes == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ for(i=0; i<count; ++i)
+ rlparams->suppenctypes[i] = atoi(values[i]);
+ rlparams->suppenctypes[count] = -1;
+ *mask |= LDAP_REALM_SUPPENCTYPE;
+ ldap_value_free(values);
+ }
+
+ if((values=ldap_get_values(ld, ent, "krbSupportedSaltTypes")) != NULL) {
+ count = ldap_count_values(values);
+ rlparams->suppsalttypes = malloc (sizeof(krb5_int32) * (count + 1));
+ if (rlparams->suppsalttypes == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ for(i=0; i<count; ++i)
+ rlparams->suppsalttypes[i] = atoi(values[i]);
+ rlparams->suppsalttypes[count] = -1;
+ *mask |= LDAP_REALM_SUPPSALTTYPE;
+ ldap_value_free(values);
+ }
+
+#ifdef HAVE_EDIRECTORY
+
+ if((values=ldap_get_values(ld, ent, "krbKdcServers")) != NULL) {
+ count = ldap_count_values(values);
+ if ((st=copy_arrays(values, &(rlparams->kdcservers), (int) count)) != 0)
+ goto cleanup;
+ *mask |= LDAP_REALM_KDCSERVERS;
+ ldap_value_free(values);
+ }
+
+ if((values=ldap_get_values(ld, ent, "krbAdmServers")) != NULL) {
+ count = ldap_count_values(values);
+ if ((st=copy_arrays(values, &(rlparams->adminservers), (int) count)) != 0)
+ goto cleanup;
+ *mask |= LDAP_REALM_ADMINSERVERS;
+ ldap_value_free(values);
+ }
+
+ if((values=ldap_get_values(ld, ent, "krbPwdServers")) != NULL) {
+ count = ldap_count_values(values);
+ if ((st=copy_arrays(values, &(rlparams->passwdservers), (int) count)) != 0)
+ goto cleanup;
+ *mask |= LDAP_REALM_PASSWDSERVERS;
+ ldap_value_free(values);
+ }
+#endif
+ }
+ ldap_msgfree(result);
+
+ /*
+ * If all of maxtktlife, maxrenewlife and ticketflags are not directly
+ * available, use the policy dn from the policy reference attribute, if
+ * available, to fetch the missing.
+ */
+
+ if ((!(*mask & LDAP_REALM_MAXTICKETLIFE && *mask & LDAP_REALM_MAXRENEWLIFE &&
+ *mask & LDAP_REALM_KRBTICKETFLAGS)) && rlparams->policyreference) {
+
+ LDAP_SEARCH_1(rlparams->policyreference, LDAP_SCOPE_BASE, NULL, policy_attributes, IGNORE_STATUS);
+ if (st != LDAP_SUCCESS && st != LDAP_NO_SUCH_OBJECT) {
+ int ost = st;
+ st = translate_ldap_error (st, OP_SEARCH);
+ krb5_set_error_message (context, st, "Policy object read failed: %s", ldap_err2string(ost));
+ goto cleanup;
+ }
+ ent = ldap_first_entry (ld, result);
+ if (ent != NULL) {
+ if ((*mask & LDAP_REALM_MAXTICKETLIFE) == 0) {
+ if((values=ldap_get_values(ld, ent, "krbmaxticketlife")) != NULL) {
+ rlparams->max_life = atoi(values[0]);
+ *mask |= LDAP_REALM_MAXTICKETLIFE;
+ ldap_value_free(values);
+ }
+ }
+
+ if ((*mask & LDAP_REALM_MAXRENEWLIFE) == 0) {
+ if((values=ldap_get_values(ld, ent, "krbmaxrenewableage")) != NULL) {
+ rlparams->max_renewable_life = atoi(values[0]);
+ *mask |= LDAP_REALM_MAXRENEWLIFE;
+ ldap_value_free(values);
+ }
+ }
+
+ if ((*mask & LDAP_REALM_KRBTICKETFLAGS) == 0) {
+ if((values=ldap_get_values(ld, ent, "krbticketflags")) != NULL) {
+ rlparams->tktflags = atoi(values[0]);
+ *mask |= LDAP_REALM_KRBTICKETFLAGS;
+ ldap_value_free(values);
+ }
+ }
+ }
+ ldap_msgfree(result);
+ }
+
+ rlparams->mask = *mask;
+ *rlparamp = rlparams;
+ st = store_tl_data(rlparams->tl_data, KDB_TL_MASK, mask);
+
+ cleanup:
+
+ /* if there is an error, free allocated structures */
+ if(st != 0) {
+ krb5_ldap_free_realm_params(rlparams);
+ *rlparamp=NULL;
+ }
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
+
+
+/*
+ Free the krb5_ldap_realm_params.
+*/
+void
+krb5_ldap_free_realm_params(rparams)
+ krb5_ldap_realm_params *rparams;
+{
+ int i=0;
+
+ if(rparams) {
+ if (rparams->realmdn)
+ free(rparams->realmdn);
+
+ if (rparams->realm_name)
+ krb5_xfree(rparams->realm_name);
+
+ if (rparams->subtree)
+ krb5_xfree(rparams->subtree);
+
+ if (rparams->suppenctypes)
+ krb5_xfree(rparams->suppenctypes);
+
+ if (rparams->suppsalttypes)
+ krb5_xfree(rparams->suppsalttypes);
+
+ if (rparams->kdcservers){
+ for (i=0; rparams->kdcservers[i]; ++i)
+ krb5_xfree(rparams->kdcservers[i]);
+ krb5_xfree(rparams->kdcservers);
+ }
+
+ if (rparams->adminservers){
+ for (i=0; rparams->adminservers[i]; ++i)
+ krb5_xfree(rparams->adminservers[i]);
+ krb5_xfree(rparams->adminservers);
+ }
+
+ if (rparams->passwdservers){
+ for (i=0; rparams->passwdservers[i]; ++i)
+ krb5_xfree(rparams->passwdservers[i]);
+ krb5_xfree(rparams->passwdservers);
+ }
+
+ if (rparams->tl_data) {
+ if (rparams->tl_data->tl_data_contents)
+ krb5_xfree(rparams->tl_data->tl_data_contents);
+ krb5_xfree(rparams->tl_data);
+ }
+
+ if (rparams->mkey.contents) {
+ memset(rparams->mkey.contents, 0, rparams->mkey.length);
+ krb5_xfree(rparams->mkey.contents);
+ }
+
+ krb5_xfree(rparams);
+ }
+ return;
+}
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.h b/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.h
new file mode 100644
index 000000000..fabc316ca
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.h
@@ -0,0 +1,99 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_realm.h
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LDAP_REALM_H
+#define _LDAP_REALM_H 1
+
+/* realm specific mask */
+#define LDAP_REALM_SUBTREE 0x0001
+#define LDAP_REALM_SEARCHSCOPE 0x0002
+#define LDAP_REALM_DEFENCTYPE 0x0004
+#define LDAP_REALM_DEFSALTTYPE 0x0008
+#define LDAP_REALM_SUPPENCTYPE 0x0010
+#define LDAP_REALM_SUPPSALTTYPE 0x0020
+#define LDAP_REALM_POLICYREFERENCE 0x0040
+#define LDAP_REALM_UPENABLED 0x0080
+#define LDAP_REALM_LDAPSERVERS 0x0100
+#define LDAP_REALM_KDCSERVERS 0x0200
+#define LDAP_REALM_ADMINSERVERS 0x0400
+#define LDAP_REALM_PASSWDSERVERS 0x0800
+#define LDAP_REALM_MAXTICKETLIFE 0x1000
+#define LDAP_REALM_MAXRENEWLIFE 0x2000
+#define LDAP_REALM_KRBTICKETFLAGS 0x4000
+
+extern char *policy_attributes[];
+
+extern char *realm_attributes[];
+
+/* realm container structure */
+
+typedef struct _krb5_ldap_realm_params {
+ char *realmdn;
+ char *realm_name;
+ char *subtree;
+ char *policyreference;
+ int search_scope;
+ int upenabled;
+ krb5_int32 max_life;
+ krb5_int32 max_renewable_life;
+ krb5_int32 tktflags;
+ krb5_enctype defenctype;
+ krb5_int32 defsalttype;
+ krb5_enctype *suppenctypes;
+ krb5_int32 *suppsalttypes;
+ char **ldapservers;
+ char **kdcservers;
+ char **adminservers;
+ char **passwdservers;
+ krb5_tl_data *tl_data;
+ krb5_keyblock mkey;
+ long mask;
+} krb5_ldap_realm_params;
+
+
+krb5_error_code
+krb5_ldap_list_realm(krb5_context , char ***);
+
+krb5_error_code
+krb5_ldap_delete_realm(krb5_context, char *);
+
+krb5_error_code
+krb5_ldap_modify_realm(krb5_context, krb5_ldap_realm_params *, int);
+
+krb5_error_code
+krb5_ldap_create_realm(krb5_context, krb5_ldap_realm_params *, int);
+
+krb5_error_code
+krb5_ldap_read_realm_params(krb5_context , char *, krb5_ldap_realm_params **, int *);
+
+void
+krb5_ldap_free_realm_params(krb5_ldap_realm_params *);
+
+#endif
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_rights.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_rights.c
new file mode 100644
index 000000000..296e36d2d
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_rights.c
@@ -0,0 +1,801 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_service_rights.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ldap_main.h"
+#include "ldap_services.h"
+#include "ldap_err.h"
+
+/* NOTE: add appropriate rights for krbpasswordexpiration attribute */
+
+#ifdef HAVE_EDIRECTORY
+
+static char *kdcrights_subtree[][2] = {
+ {"1#subtree#","#[Entry Rights]"},
+ {"2#subtree#","#CN"},
+ {"6#subtree#","#ObjectClass"},
+ {"2#subtree#","#krbPolicyReference"},
+ {"2#subtree#","#krbUPEnabled"},
+ {"2#subtree#","#krbHostServer"},
+ {"2#subtree#","#krbServiceFlags"},
+ {"2#subtree#","#krbRealmReferences"},
+ {"2#subtree#","#krbTicketFlags"},
+ {"2#subtree#","#krbMaxTicketLife"},
+ {"2#subtree#","#krbMaxRenewableAge"},
+ {"2#subtree#","#krbPrincipalName"},
+ {"6#subtree#","#krbSecretKey"},
+ {"2#subtree#","#krbPrincipalExpiration"},
+ {"2#subtree#","#krbPwdPolicyReference"},
+ {"2#subtree#","#krbMaxPwdLife"},
+ {"6#subtree#","#ModifiersName"},
+ {"2#subtree#","#PasswordExpirationTime"},
+ {"2#subtree#","#PasswordExpirationInterval"},
+ {"2#subtree#","#PasswordMinimumLength"},
+ {"2#subtree#","#PasswordAllowChange"},
+ {"2#subtree#","#LoginDisabled"},
+ {"6#subtree#","#LastLoginTime"},
+ {"2#subtree#","#LoginExpirationTime"},
+ {"6#subtree#","#LoginIntruderAttempts"},
+ {"2#subtree#","#IntruderAttemptResetInterval"},
+ {"2#subtree#","#LoginIntruderLimit"},
+ {"6#subtree#","#LoginIntruderResetTime"},
+ {"2#subtree#","#DetectIntruder"},
+ {"2#subtree#","#LockoutAfterDetection"},
+ {"6#subtree#","#LockedByIntruder"},
+ {"2#subtree#","#krbPrincipalReferences"},
+ { "", "" }
+};
+
+static char *adminrights_subtree[][2]={
+ {"15#subtree#","#[Entry Rights]"},
+ {"6#subtree#","#CN"},
+ {"6#subtree#","#ObjectClass"},
+ {"6#subtree#","#krbPolicyReference"},
+ {"6#subtree#","#krbUPEnabled"},
+ {"2#subtree#","#krbHostServer"},
+ {"2#subtree#","#krbServiceFlags"},
+ {"2#subtree#","#krbRealmReferences"},
+ {"6#subtree#","#krbTicketFlags"},
+ {"6#subtree#","#krbMaxTicketLife"},
+ {"6#subtree#","#krbMaxRenewableAge"},
+ {"6#subtree#","#krbPrincipalName"},
+ {"6#subtree#","#krbSecretKey"},
+ {"6#subtree#","#krbPrincipalExpiration"},
+ {"6#subtree#","#ModifiersName"},
+ {"6#subtree#","#PasswordExpirationTime"},
+ {"2#subtree#","#PasswordExpirationInterval"},
+ {"6#subtree#","#PasswordMinimumLength"},
+ {"6#subtree#","#PasswordAllowChange"},
+ {"6#subtree#","#LoginDisabled"},
+ {"2#subtree#","#LastLoginTime"},
+ {"2#subtree#","#LoginExpirationTime"},
+ {"2#subtree#","#LoginIntruderAttempts"},
+ {"6#subtree#","#IntruderAttemptResetInterval"},
+ {"6#subtree#","#LoginIntruderLimit"},
+ {"6#subtree#","#LoginIntruderResetTime"},
+ {"6#subtree#","#DetectIntruder"},
+ {"6#subtree#","#LockoutAfterDetection"},
+ {"2#subtree#","#LockedByIntruder"},
+ {"2#subtree#","#krbPrincipalReferences"},
+ {"6#subtree#","#Surname"},
+ {"4#subtree#","#passwordManagement"},
+ {"6#subtree#","#krbPwdHistoryLength"},
+ {"6#subtree#","#krbMinPwdLife"},
+ {"6#subtree#","#krbMaxPwdLife"},
+ {"6#subtree#","#krbPwdMinDiffChars"},
+ {"6#subtree#","#krbPwdMinLength"},
+ {"6#subtree#","#krbPwdPolicyRefCount"},
+ {"6#subtree#","#krbPwdPolicyReference"},
+ { "","" }
+};
+
+static char *pwdrights_subtree[][2] = {
+ {"1#subtree#","#[Entry Rights]"},
+ {"2#subtree#","#CN"},
+ {"2#subtree#","#ObjectClass"},
+ {"2#subtree#","#krbPolicyReference"},
+ {"2#subtree#","#krbUPEnabled"},
+ {"2#subtree#","#krbHostServer"},
+ {"2#subtree#","#krbServiceFlags"},
+ {"2#subtree#","#krbRealmReferences"},
+ {"6#subtree#","#krbTicketFlags"},
+ {"2#subtree#","#krbMaxTicketLife"},
+ {"2#subtree#","#krbMaxRenewableAge"},
+ {"2#subtree#","#krbPrincipalName"},
+ {"6#subtree#","#krbSecretKey"},
+ {"2#subtree#","#krbPrincipalExpiration"},
+ {"4#subtree#","#passwordManagement"},
+ {"6#subtree#","#ModifiersName"},
+ {"2#subtree#","#krbPwdHistoryLength"},
+ {"2#subtree#","#krbMinPwdLife"},
+ {"2#subtree#","#krbMaxPwdLife"},
+ {"2#subtree#","#krbPwdMinDiffChars"},
+ {"2#subtree#","#krbPwdMinLength"},
+ {"2#subtree#","#krbPwdPolicyRefCount"},
+ {"2#subtree#","#krbPwdPolicyReference"},
+ { "", "" }
+};
+
+static char *kdcrights_realmcontainer[][2]={
+ {"1#subtree#","#[Entry Rights]"},
+ {"2#subtree#","#CN"},
+ {"6#subtree#","#ObjectClass"},
+ {"2#subtree#","#krbPolicyReference"},
+ {"2#subtree#","#krbMasterKey"},
+ {"2#subtree#","#krbUPEnabled"},
+ {"2#subtree#","#krbSubTree"},
+ {"2#subtree#","#krbSearchScope"},
+ {"2#subtree#","#krbLdapServers"},
+ {"2#subtree#","#krbSupportedEncTypes"},
+ {"2#subtree#","#krbSupportedSaltTypes"},
+ {"2#subtree#","#krbDefaultEncType"},
+ {"2#subtree#","#krbDefaultSaltType"},
+ {"2#subtree#","#krbKdcServers"},
+ {"2#subtree#","#krbPwdServers"},
+ {"2#subtree#","#krbTicketFlags"},
+ {"2#subtree#","#krbMaxTicketLife"},
+ {"2#subtree#","#krbMaxRenewableAge"},
+ {"2#subtree#","#krbPrincipalName"},
+ {"6#subtree#","#krbSecretKey"},
+ {"2#subtree#","#krbPrincipalExpiration"},
+ {"2#subtree#","#krbPwdPolicyReference"},
+ {"2#subtree#","#krbMaxPwdLife"},
+ {"6#subtree#","#ModifiersName"},
+ {"2#subtree#","#PasswordExpirationTime"},
+ {"2#subtree#","#PasswordExpirationInterval"},
+ {"2#subtree#","#PasswordMinimumLength"},
+ {"2#subtree#","#PasswordAllowChange"},
+ {"2#subtree#","#LoginDisabled"},
+ {"6#subtree#","#LastLoginTime"},
+ {"2#subtree#","#LoginExpirationTime"},
+ {"6#subtree#","#LoginIntruderAttempts"},
+ {"2#subtree#","#IntruderAttemptResetInterval"},
+ {"2#subtree#","#LoginIntruderLimit"},
+ {"6#subtree#","#LoginIntruderResetTime"},
+ {"2#subtree#","#DetectIntruder"},
+ {"2#subtree#","#LockoutAfterDetection"},
+ {"6#subtree#","#LockedByIntruder"},
+ { "", "" }
+};
+
+
+static char *adminrights_realmcontainer[][2]={
+ {"15#subtree#","#[Entry Rights]"},
+ {"6#subtree#","#CN"},
+ {"6#subtree#","#ObjectClass"},
+ {"6#subtree#","#krbPolicyReference"},
+ {"2#subtree#","#krbMasterKey"},
+ {"6#subtree#","#krbUPEnabled"},
+ {"2#subtree#","#krbSubTree"},
+ {"2#subtree#","#krbSearchScope"},
+ {"2#subtree#","#krbLdapServers"},
+ {"2#subtree#","#krbSupportedEncTypes"},
+ {"2#subtree#","#krbSupportedSaltTypes"},
+ {"2#subtree#","#krbDefaultEncType"},
+ {"2#subtree#","#krbDefaultSaltType"},
+ {"2#subtree#","#krbKdcServers"},
+ {"2#subtree#","#krbPwdServers"},
+ {"6#subtree#","#krbTicketFlags"},
+ {"6#subtree#","#krbMaxTicketLife"},
+ {"6#subtree#","#krbMaxRenewableAge"},
+ {"6#subtree#","#krbPrincipalName"},
+ {"6#subtree#","#krbSecretKey"},
+ {"6#subtree#","#krbPrincipalExpiration"},
+ {"6#subtree#","#ModifiersName"},
+ {"6#subtree#","#PasswordExpirationTime"},
+ {"2#subtree#","#PasswordExpirationInterval"},
+ {"6#subtree#","#PasswordMinimumLength"},
+ {"6#subtree#","#PasswordAllowChange"},
+ {"6#subtree#","#LoginDisabled"},
+ {"2#subtree#","#LastLoginTime"},
+ {"2#subtree#","#LoginExpirationTime"},
+ {"2#subtree#","#LoginIntruderAttempts"},
+ {"6#subtree#","#IntruderAttemptResetInterval"},
+ {"6#subtree#","#LoginIntruderLimit"},
+ {"6#subtree#","#LoginIntruderResetTime"},
+ {"6#subtree#","#DetectIntruder"},
+ {"6#subtree#","#LockoutAfterDetection"},
+ {"2#subtree#","#LockedByIntruder"},
+ {"6#subtree#","#Surname"},
+ {"6#subtree#","#krbPwdHistoryLength"},
+ {"6#subtree#","#krbMinPwdLife"},
+ {"6#subtree#","#krbMaxPwdLife"},
+ {"6#subtree#","#krbPwdMinDiffChars"},
+ {"6#subtree#","#krbPwdMinLength"},
+ {"6#subtree#","#krbPwdPolicyRefCount"},
+ {"6#subtree#","#krbPwdPolicyReference"},
+ { "","" }
+};
+
+
+static char *pwdrights_realmcontainer[][2]={
+ {"1#subtree#","#[Entry Rights]"},
+ {"2#subtree#","#CN"},
+ {"2#subtree#","#ObjectClass"},
+ {"2#subtree#","#krbPolicyReference"},
+ {"2#subtree#","#krbMasterKey"},
+ {"2#subtree#","#krbUPEnabled"},
+ {"2#subtree#","#krbSubTree"},
+ {"2#subtree#","#krbSearchScope"},
+ {"2#subtree#","#krbLdapServers"},
+ {"2#subtree#","#krbSupportedEncTypes"},
+ {"2#subtree#","#krbSupportedSaltTypes"},
+ {"2#subtree#","#krbDefaultEncType"},
+ {"2#subtree#","#krbDefaultSaltType"},
+ {"2#subtree#","#krbKdcServers"},
+ {"2#subtree#","#krbPwdServers"},
+ {"6#subtree#","#krbTicketFlags"},
+ {"2#subtree#","#krbMaxTicketLife"},
+ {"2#subtree#","#krbMaxRenewableAge"},
+ {"2#subtree#","#krbPrincipalName"},
+ {"6#subtree#","#krbSecretKey"},
+ {"2#subtree#","#krbPrincipalExpiration"},
+ {"6#subtree#","#ModifiersName"},
+ {"2#subtree#","#krbPwdHistoryLength"},
+ {"2#subtree#","#krbMinPwdLife"},
+ {"2#subtree#","#krbMaxPwdLife"},
+ {"2#subtree#","#krbPwdMinDiffChars"},
+ {"2#subtree#","#krbPwdMinLength"},
+ {"2#subtree#","#krbPwdPolicyRefCount"},
+ {"2#subtree#","#krbPwdPolicyReference"},
+ { "", "" }
+};
+
+static char *security_container[][2] = {
+ {"1#subtree#","#[Entry Rights]"},
+ {"2#subtree#","#krbContainerReference"},
+ { "", "" }
+};
+
+static char *kerberos_container[][2] = {
+ {"1#subtree#","#[Entry Rights]"},
+ {"2#subtree#","#krbPolicyReference"},
+ { "", "" }
+};
+
+
+/*
+ * This will set the rights for the Kerberos service objects.
+ * The function will read the subtree attribute from the specified
+ * realm name and will the appropriate rights on both the realm
+ * container and the subtree. The kerberos context passed should
+ * have a valid ldap handle, with appropriate rights to write acl
+ * attributes.
+ *
+ * krb5_context - IN The Kerberos context with valid ldap handle
+ *
+ */
+
+krb5_error_code
+krb5_ldap_add_service_rights( context, servicetype, serviceobjdn, realmname, subtreeparam, mask)
+ krb5_context context;
+ int servicetype;
+ char *serviceobjdn;
+ char *realmname;
+ char *subtreeparam;
+ int mask;
+{
+
+ int st=0,i=0;
+ char *realmacls[2]={NULL}, *subtreeacls[2]={NULL}, *seccontacls[2]={NULL}, *krbcontacls[2]={NULL};
+ LDAP *ld;
+ LDAPMod realmclass, subtreeclass, seccontclass, krbcontclass;
+ LDAPMod *realmarr[3]={NULL}, *subtreearr[3]={NULL}, *seccontarr[3]={NULL}, *krbcontarr[3]={NULL};
+ char *realmdn=NULL, *subtree=NULL;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+
+ SETUP_CONTEXT();
+ GET_HANDLE();
+
+ if ((serviceobjdn == NULL) || (realmname == NULL) || (servicetype < 0) || (servicetype > 4)
+ || (ldap_context->krbcontainer->DN == NULL) ) {
+ st=-1;
+ goto cleanup;
+ }
+
+ /* If the subtree is null, set the value to root */
+ if(subtreeparam== NULL)
+ subtree=strdup("");
+ else
+ subtree=strdup(subtreeparam);
+
+ if( subtree == NULL ) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+
+ /* Set the rights for the service object on the security container */
+ seccontclass.mod_op = LDAP_MOD_ADD;
+ seccontclass.mod_type = "ACL";
+
+ for (i=0; strcmp(security_container[i][0], "") != 0; i++) {
+
+ seccontacls[0] = (char *)malloc( strlen(security_container[i][0]) +
+ strlen(serviceobjdn) +
+ strlen(security_container[i][1]) + 1);
+
+ sprintf( seccontacls[0], "%s%s%s", security_container[i][0], serviceobjdn,
+ security_container[i][1]);
+ seccontclass.mod_values = seccontacls;
+
+ seccontarr[0] = &seccontclass;
+
+ st = ldap_modify_ext_s(ld,
+ SECURITY_CONTAINER,
+ seccontarr,
+ NULL,
+ NULL);
+ if (st != LDAP_SUCCESS && st != LDAP_TYPE_OR_VALUE_EXISTS && st != LDAP_OTHER) {
+ free(seccontacls[0]);
+ st = set_ldap_error (context, st, OP_MOD);
+ goto cleanup;
+ }
+ free(seccontacls[0]);
+ }
+
+
+ /* Set the rights for the service object on the kerberos container */
+ krbcontclass.mod_op = LDAP_MOD_ADD;
+ krbcontclass.mod_type = "ACL";
+
+ for (i=0; strcmp(kerberos_container[i][0], "") != 0; i++) {
+ krbcontacls[0] = (char *)malloc( strlen(kerberos_container[i][0]) + strlen(serviceobjdn)
+ + strlen(kerberos_container[i][1]) + 1);
+ sprintf(krbcontacls[0], "%s%s%s", kerberos_container[i][0], serviceobjdn,
+ kerberos_container[i][1]);
+ krbcontclass.mod_values = krbcontacls;
+
+ krbcontarr[0] = &krbcontclass;
+
+ st = ldap_modify_ext_s(ld,
+ ldap_context->krbcontainer->DN,
+ krbcontarr,
+ NULL,
+ NULL);
+ if (st != LDAP_SUCCESS && st != LDAP_TYPE_OR_VALUE_EXISTS && st != LDAP_OTHER) {
+ free(krbcontacls[0]);
+ st = set_ldap_error (context, st, OP_MOD);
+ goto cleanup;
+ }
+ free(krbcontacls[0]);
+ }
+
+ /* Set the rights for the realm */
+ if (mask & LDAP_REALM_RIGHTS) {
+
+ /* Construct the realm dn from realm name */
+ realmdn = (char * )malloc(strlen("cn=") + strlen(realmname) +
+ strlen(ldap_context->krbcontainer->DN) + 2);
+ sprintf(realmdn,"cn=%s,%s", realmname, ldap_context->krbcontainer->DN);
+
+ realmclass.mod_op = LDAP_MOD_ADD;
+ realmclass.mod_type = "ACL";
+
+ if (servicetype == LDAP_KDC_SERVICE) {
+ for (i=0; strcmp(kdcrights_realmcontainer[i][0], "") != 0; i++) {
+ realmacls[0] = (char *)malloc(strlen(kdcrights_realmcontainer[i][0])
+ + strlen(serviceobjdn) +
+ strlen(kdcrights_realmcontainer[i][1]) + 1);
+ sprintf(realmacls[0], "%s%s%s", kdcrights_realmcontainer[i][0], serviceobjdn,
+ kdcrights_realmcontainer[i][1]);
+ realmclass.mod_values = realmacls;
+
+ realmarr[0] = &realmclass;
+
+ st = ldap_modify_ext_s(ld,
+ realmdn,
+ realmarr,
+ NULL,
+ NULL);
+ if (st != LDAP_SUCCESS && st != LDAP_TYPE_OR_VALUE_EXISTS && st != LDAP_OTHER) {
+ free(realmacls[0]);
+ st = set_ldap_error (context, st, OP_MOD);
+ goto cleanup;
+ }
+ free(realmacls[0]);
+ }
+ } else if(servicetype == LDAP_ADMIN_SERVICE){
+ for( i=0; strcmp(adminrights_realmcontainer[i][0], "") != 0; i++) {
+ realmacls[0] = (char *) malloc(strlen(adminrights_realmcontainer[i][0]) +
+ strlen(serviceobjdn) +
+ strlen(adminrights_realmcontainer[i][1]) + 1);
+ sprintf(realmacls[0], "%s%s%s", adminrights_realmcontainer[i][0], serviceobjdn,
+ adminrights_realmcontainer[i][1]);
+ realmclass.mod_values = realmacls;
+
+ realmarr[0] = &realmclass;
+
+ st = ldap_modify_ext_s(ld,
+ realmdn,
+ realmarr,
+ NULL,
+ NULL);
+ if (st != LDAP_SUCCESS && st != LDAP_TYPE_OR_VALUE_EXISTS && st != LDAP_OTHER) {
+ free(realmacls[0]);
+ st = set_ldap_error (context, st, OP_MOD);
+ goto cleanup;
+ }
+ free(realmacls[0]);
+ }
+ } else if (servicetype == LDAP_PASSWD_SERVICE) {
+ for (i=0; strcmp(pwdrights_realmcontainer[i][0], "")!=0; i++) {
+ realmacls[0] = (char *) malloc( strlen(pwdrights_realmcontainer[i][0]) +
+ strlen(serviceobjdn) +
+ strlen(pwdrights_realmcontainer[i][1]) + 1);
+ sprintf( realmacls[0], "%s%s%s", pwdrights_realmcontainer[i][0], serviceobjdn,
+ pwdrights_realmcontainer[i][1]);
+ realmclass.mod_values = realmacls;
+
+ realmarr[0] = &realmclass;
+
+
+ st = ldap_modify_ext_s(ld,
+ realmdn,
+ realmarr,
+ NULL,
+ NULL);
+ if (st != LDAP_SUCCESS && st != LDAP_TYPE_OR_VALUE_EXISTS && st != LDAP_OTHER) {
+ free(realmacls[0]);
+ st = set_ldap_error (context, st, OP_MOD);
+ goto cleanup;
+ }
+ free(realmacls[0]);
+ }
+ }
+ } /* Realm rights settings ends here */
+
+
+ /* Subtree rights to be set */
+ if (mask & LDAP_SUBTREE_RIGHTS) {
+ /* Populate the acl data to be added to the subtree */
+ subtreeclass.mod_op = LDAP_MOD_ADD;
+ subtreeclass.mod_type = "ACL";
+
+ if (servicetype == LDAP_KDC_SERVICE) {
+ for (i=0; strcmp(kdcrights_subtree[i][0], "")!=0; i++) {
+ subtreeacls[0] = (char *) malloc( strlen(kdcrights_subtree[i][0]) +
+ strlen(serviceobjdn) +
+ strlen(kdcrights_subtree[i][1]) + 1);
+ sprintf( subtreeacls[0], "%s%s%s", kdcrights_subtree[i][0], serviceobjdn,
+ kdcrights_subtree[i][1]);
+ subtreeclass.mod_values = subtreeacls;
+
+ subtreearr[0] = &subtreeclass;
+
+ st = ldap_modify_ext_s(ld,
+ subtree,
+ subtreearr,
+ NULL,
+ NULL);
+ if (st != LDAP_SUCCESS && st != LDAP_TYPE_OR_VALUE_EXISTS && st != LDAP_OTHER) {
+ free(subtreeacls[0]);
+ st = set_ldap_error (context, st, OP_MOD);
+ goto cleanup;
+ }
+ free(subtreeacls[0]);
+ }
+ } else if (servicetype == LDAP_ADMIN_SERVICE) {
+ for (i=0; strcmp(adminrights_subtree[i][0], "")!=0; i++) {
+ subtreeacls[0] = (char *) malloc(strlen(adminrights_subtree[i][0])
+ + strlen(serviceobjdn)
+ + strlen(adminrights_subtree[i][1]) + 1);
+ sprintf( subtreeacls[0], "%s%s%s", adminrights_subtree[i][0], serviceobjdn,
+ adminrights_subtree[i][1]);
+ subtreeclass.mod_values = subtreeacls;
+
+ subtreearr[0] = &subtreeclass;
+
+ st = ldap_modify_ext_s(ld,
+ subtree,
+ subtreearr,
+ NULL,
+ NULL);
+ if (st != LDAP_SUCCESS && st !=LDAP_TYPE_OR_VALUE_EXISTS && st != LDAP_OTHER) {
+ free(subtreeacls[0]);
+ st = set_ldap_error (context, st, OP_MOD);
+ goto cleanup;
+ }
+ free(subtreeacls[0]);
+ }
+ } else if (servicetype == LDAP_PASSWD_SERVICE) {
+ for (i=0; strcmp(pwdrights_subtree[i][0], "") != 0; i++) {
+ subtreeacls[0] = (char *)malloc( strlen(pwdrights_subtree[i][0])
+ + strlen(serviceobjdn)
+ + strlen(pwdrights_subtree[i][1]) + 1);
+ sprintf( subtreeacls[0], "%s%s%s", pwdrights_subtree[i][0], serviceobjdn,
+ pwdrights_subtree[i][1]);
+ subtreeclass.mod_values = subtreeacls;
+
+ subtreearr[0] = &subtreeclass;
+
+ st = ldap_modify_ext_s(ld,
+ subtree,
+ subtreearr,
+ NULL,
+ NULL);
+ if (st != LDAP_SUCCESS && st != LDAP_TYPE_OR_VALUE_EXISTS && st != LDAP_OTHER) {
+ free(subtreeacls[0]);
+ st = set_ldap_error (context, st, OP_MOD);
+ goto cleanup;
+ }
+ free(subtreeacls[0]);
+ }
+ }
+ } /* Subtree rights settings ends here */
+ st = 0;
+
+ cleanup:
+
+ if(realmdn)
+ free(realmdn);
+
+ if(subtree)
+ free(subtree);
+
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
+
+
+/*
+ This will set the rights for the Kerberos service objects.
+ The function will read the subtree attribute from the specified
+ realm name and will the appropriate rights on both the realm
+ container and the subtree. The kerberos context passed should
+ have a valid ldap handle, with appropriate rights to write acl
+ attributes.
+
+ krb5_context - IN The Kerberos context with valid ldap handle
+
+*/
+
+krb5_error_code
+krb5_ldap_delete_service_rights( context, servicetype, serviceobjdn, realmname, subtreeparam, mask)
+ krb5_context context;
+ int servicetype;
+ char *serviceobjdn;
+ char *realmname;
+ char *subtreeparam;
+ int mask;
+{
+
+ int st=0,i=0;
+ char *realmacls[2] = { NULL }, *subtreeacls[2] = { NULL };
+ LDAP *ld;
+ LDAPMod realmclass, subtreeclass;
+ LDAPMod *realmarr[3] = { NULL }, *subtreearr[3] = { NULL };
+ char *realmdn=NULL;
+ char *subtree=NULL;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+
+ SETUP_CONTEXT();
+ GET_HANDLE();
+
+ if((serviceobjdn == NULL) || (realmname == NULL) || (servicetype < 0) || (servicetype > 4)
+ || (ldap_context->krbcontainer->DN == NULL) ) {
+ st=-1;
+ goto cleanup;
+ }
+
+ /* If the subtree is null, set the value to root */
+ if(subtreeparam== NULL)
+ subtree=strdup("");
+ else
+ subtree=strdup(subtreeparam);
+
+ if( subtree == NULL ) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+
+
+ /* Set the rights for the realm */
+ if( mask & LDAP_REALM_RIGHTS ) {
+
+ /* Construct the realm dn from realm name */
+ realmdn = (char *) malloc( strlen("cn=") + strlen(realmname) +
+ strlen(ldap_context->krbcontainer->DN) + 2 );
+ sprintf(realmdn,"cn=%s,%s", realmname, ldap_context->krbcontainer->DN);
+
+ realmclass.mod_op=LDAP_MOD_DELETE;
+ realmclass.mod_type="ACL";
+
+ if (servicetype == LDAP_KDC_SERVICE) {
+ for (i=0; strcmp(kdcrights_realmcontainer[i][0], "") != 0; i++) {
+ realmacls[0] = (char *) malloc(strlen(kdcrights_realmcontainer[i][0])
+ + strlen(serviceobjdn) +
+ strlen(kdcrights_realmcontainer[i][1]) + 1);
+ sprintf( realmacls[0], "%s%s%s", kdcrights_realmcontainer[i][0], serviceobjdn,
+ kdcrights_realmcontainer[i][1]);
+ realmclass.mod_values= realmacls;
+
+ realmarr[0]=&realmclass;
+
+ st = ldap_modify_ext_s(ld,
+ realmdn,
+ realmarr,
+ NULL,
+ NULL);
+ if (st != LDAP_SUCCESS && st != LDAP_NO_SUCH_ATTRIBUTE) {
+ free(realmacls[0]);
+ st = set_ldap_error (context, st, OP_MOD);
+ goto cleanup;
+ }
+ free(realmacls[0]);
+ }
+ } else if (servicetype == LDAP_ADMIN_SERVICE) {
+ for (i=0; strcmp(adminrights_realmcontainer[i][0], "") != 0; i++) {
+ realmacls[0] = (char *) malloc( strlen(adminrights_realmcontainer[i][0]) +
+ strlen(serviceobjdn) +
+ strlen(adminrights_realmcontainer[i][1]) + 1);
+ sprintf(realmacls[0], "%s%s%s", adminrights_realmcontainer[i][0], serviceobjdn,
+ adminrights_realmcontainer[i][1]);
+ realmclass.mod_values= realmacls;
+
+ realmarr[0]=&realmclass;
+
+ st = ldap_modify_ext_s(ld,
+ realmdn,
+ realmarr,
+ NULL,
+ NULL);
+ if (st != LDAP_SUCCESS && st != LDAP_NO_SUCH_ATTRIBUTE) {
+ free(realmacls[0]);
+ st = set_ldap_error (context, st, OP_MOD);
+ goto cleanup;
+ }
+ free(realmacls[0]);
+ }
+ } else if (servicetype == LDAP_PASSWD_SERVICE) {
+ for (i=0; strcmp(pwdrights_realmcontainer[i][0], "") != 0; i++) {
+ realmacls[0]=(char *)malloc( strlen(pwdrights_realmcontainer[i][0])
+ + strlen(serviceobjdn)
+ + strlen(pwdrights_realmcontainer[i][1]) + 1);
+ sprintf( realmacls[0], "%s%s%s", pwdrights_realmcontainer[i][0], serviceobjdn,
+ pwdrights_realmcontainer[i][1]);
+ realmclass.mod_values= realmacls;
+
+ realmarr[0]=&realmclass;
+
+ st = ldap_modify_ext_s(ld,
+ realmdn,
+ realmarr,
+ NULL,
+ NULL);
+ if (st != LDAP_SUCCESS && st != LDAP_NO_SUCH_ATTRIBUTE) {
+ free(realmacls[0]);
+ st = set_ldap_error (context, st, OP_MOD);
+ goto cleanup;
+ }
+ free(realmacls[0]);
+ }
+ }
+
+ } /* Realm rights setting ends here */
+
+
+ /* Set the rights for the subtree */
+ if (mask & LDAP_SUBTREE_RIGHTS) {
+
+ /* Populate the acl data to be added to the subtree */
+ subtreeclass.mod_op=LDAP_MOD_DELETE;
+ subtreeclass.mod_type="ACL";
+
+ if(servicetype == LDAP_KDC_SERVICE){
+ for (i=0; strcmp(kdcrights_subtree[i][0], "")!=0; i++) {
+ subtreeacls[0] = (char *) malloc( strlen(kdcrights_subtree[i][0])
+ + strlen(serviceobjdn)
+ + strlen(kdcrights_subtree[i][1]) + 1);
+ sprintf( subtreeacls[0], "%s%s%s", kdcrights_subtree[i][0], serviceobjdn,
+ kdcrights_subtree[i][1]);
+ subtreeclass.mod_values= subtreeacls;
+
+ subtreearr[0]=&subtreeclass;
+
+ st = ldap_modify_ext_s(ld,
+ subtree,
+ subtreearr,
+ NULL,
+ NULL);
+ if (st != LDAP_SUCCESS && st != LDAP_NO_SUCH_ATTRIBUTE) {
+ free(subtreeacls[0]);
+ st = set_ldap_error (context, st, OP_MOD);
+ goto cleanup;
+ }
+ free(subtreeacls[0]);
+ }
+ } else if (servicetype == LDAP_ADMIN_SERVICE) {
+ for (i=0; strcmp(adminrights_subtree[i][0], "") != 0; i++) {
+ subtreeacls[0] = (char *) malloc(strlen(adminrights_subtree[i][0])
+ + strlen(serviceobjdn)
+ + strlen(adminrights_subtree[i][1]) + 1);
+ sprintf(subtreeacls[0], "%s%s%s", adminrights_subtree[i][0], serviceobjdn,
+ adminrights_subtree[i][1]);
+ subtreeclass.mod_values= subtreeacls;
+
+ subtreearr[0]=&subtreeclass;
+
+ st = ldap_modify_ext_s(ld,
+ subtree,
+ subtreearr,
+ NULL,
+ NULL);
+ if ( st != LDAP_SUCCESS && st != LDAP_NO_SUCH_ATTRIBUTE) {
+ free(subtreeacls[0]);
+ st = set_ldap_error (context, st, OP_MOD);
+ goto cleanup;
+ }
+ free(subtreeacls[0]);
+ }
+ }
+ else if (servicetype == LDAP_PASSWD_SERVICE) {
+ for (i=0; strcmp(pwdrights_subtree[i][0], "") != 0; i++) {
+ subtreeacls[0] = (char *) malloc(strlen(pwdrights_subtree[i][0])
+ + strlen(serviceobjdn)
+ + strlen(pwdrights_subtree[i][1]) + 1);
+ sprintf(subtreeacls[0], "%s%s%s", pwdrights_subtree[i][0], serviceobjdn,
+ pwdrights_subtree[i][1]);
+ subtreeclass.mod_values= subtreeacls;
+
+ subtreearr[0]=&subtreeclass;
+
+ st = ldap_modify_ext_s(ld,
+ subtree,
+ subtreearr,
+ NULL,
+ NULL);
+ if (st != LDAP_SUCCESS && st != LDAP_NO_SUCH_ATTRIBUTE) {
+ free(subtreeacls[0]);
+ st = set_ldap_error (context, st, OP_MOD);
+ goto cleanup;
+ }
+ free(subtreeacls[0]);
+ }
+ }
+ } /* Subtree rights setting ends here */
+
+ st = 0;
+
+ cleanup:
+
+ if(realmdn)
+ free(realmdn);
+
+ if(subtree)
+ free(subtree);
+
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
+
+#endif
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c
new file mode 100644
index 000000000..99e7821ce
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c
@@ -0,0 +1,253 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_service_stash.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <ctype.h>
+#include "ldap_main.h"
+#include "kdb_ldap.h"
+#include "ldap_service_stash.h"
+
+krb5_error_code
+krb5_ldap_readpassword(context, ldap_context, password)
+ krb5_context context;
+ krb5_ldap_context *ldap_context;
+ unsigned char **password;
+{
+ int entryfound=0;
+ krb5_error_code st=0;
+ char line[RECORDLEN]="0", *start=NULL, *file=NULL;
+ char errbuf[1024];
+ FILE *fptr=NULL;
+
+ *password = NULL;
+
+ if (ldap_context->service_password_file)
+ file = ldap_context->service_password_file;
+
+ /* check whether file exists */
+ if (access(file, F_OK) < 0) {
+ st = errno;
+ strerror_r(errno, errbuf, sizeof(errbuf));
+ krb5_set_error_message (context, st, "%s", errbuf);
+ goto rp_exit;
+ }
+
+ /* check read access */
+ if (access(file, R_OK) < 0) {
+ st = errno;
+ strerror_r(errno, errbuf, sizeof(errbuf));
+ krb5_set_error_message (context, st, "%s", errbuf);
+ goto rp_exit;
+ }
+
+ if((fptr=fopen(file, "r")) == NULL) {
+ st = errno;
+ strerror_r(errno, errbuf, sizeof(errbuf));
+ krb5_set_error_message (context, st, "%s", errbuf);
+ goto rp_exit;
+ }
+
+ /* get the record from the file */
+ while(fgets(line, RECORDLEN, fptr)!= NULL) {
+ char tmp[RECORDLEN];
+
+ tmp[0] = '\0';
+ /* Handle leading white-spaces */
+ for(start = line; isspace(*start); ++start);
+
+ /* Handle comment lines */
+ if (*start == '!' || *start == '#')
+ continue;
+ sscanf(line, "%*[ \t]%[^#]", tmp);
+ if(tmp[0] == '\0')
+ sscanf(line, "%[^#]", tmp);
+ if(strcasecmp(tmp, ldap_context->bind_dn) == 0) {
+ entryfound = 1; /* service_dn record found !!! */
+ break;
+ }
+ }
+ fclose (fptr);
+
+ if (entryfound == 0) {
+ st = KRB5_KDB_SERVER_INTERNAL_ERR;
+ krb5_set_error_message (context, st, "Bind DN entry missing in stash file");
+ goto rp_exit;
+ }
+ /* replace the \n with \0 */
+ start = strchr(line, '\n');
+ if (start)
+ *start = '\0';
+
+ start = strchr(line, '#');
+ if (start == NULL ) {
+ /* password field missing */
+ st = KRB5_KDB_SERVER_INTERNAL_ERR;
+ krb5_set_error_message (context, st, "Stash file entry corrupt");
+ goto rp_exit;
+ }
+ ++ start;
+ /* Extract the plain password / certificate file information */
+ {
+ struct data PT, CT;
+
+ /* Check if the entry has the path of a certificate */
+ if(!strncmp(start, "{FILE}", strlen("{FILE}"))) {
+ /* Set *password = {FILE}<path to cert>\0<cert password> */
+ /*ptr = strchr(start, ':');
+ if(ptr == NULL){ */
+ *password = (unsigned char *)malloc(strlen(start) + 2);
+ (*password)[strlen(start) + 1] = '\0';
+ (*password)[strlen(start)] = '\0';
+ strcpy((char *)(*password), start);
+ goto got_password;
+ } else {
+ CT.value = (unsigned char *)start;
+ CT.len = strlen((char *)CT.value);
+ st = dec_password(CT, &PT);
+ if(st != 0){
+ goto rp_exit;
+ }
+ *password = PT.value;
+ }
+ }
+ got_password:
+
+ rp_exit:
+ if (st) {
+ if (*password)
+ free (*password);
+ *password = NULL;
+ }
+ return st;
+}
+
+/* Encodes a sequence of bytes in hexadecimal */
+
+int
+tohex(in, ret)
+ krb5_data in;
+ krb5_data *ret;
+{
+ int i=0, j=0, err = 0;
+
+ ret->length = 0;
+ ret->data = NULL;
+
+ ret->data = (unsigned char *)malloc((unsigned int)in.length * 2 + 1 /*Null termination */);
+ if (ret->data == NULL) {
+ err = ENOMEM;
+ goto cleanup;
+ }
+ ret->length = in.length * 2;
+ ret->data[ret->length] = 0;
+
+ for (i = 0, j = 0; i < in.length; i++, j += 2) {
+ sprintf((char *)ret->data + j, "%x", in.data[i] >> 4);
+ sprintf((char *)ret->data + j + 1, "%x", in.data[i] & 0xf);
+ }
+
+ cleanup:
+
+ if (ret->length == 0) {
+ free(ret->data);
+ ret->data = NULL;
+ }
+
+ return err;
+}
+
+/* The entry in the password file will have the following format
+ * <FQDN of service> = <secret>
+ * <secret> := {HEX}<password in hexadecimal>
+ *
+ * <password> is the actual eDirectory password of the service
+ */
+
+int dec_password(struct data pwd, struct data *ret){
+ int err=0;
+ int i=0, j=0;
+
+ ret->len = 0;
+ ret->value = NULL;
+
+ if (pwd.len == 0) {
+ err = EINVAL;
+ krb5_set_error_message (0, err, "Password has zero length");
+ ret->len = 0;
+ goto cleanup;
+ }
+
+ /* Check if it is a hexadecimal encoded password */
+ if (pwd.len >= strlen("{HEX}") &&
+ strncmp((char *)pwd.value, "{HEX}", strlen("{HEX}")) == 0) {
+
+ if((pwd.len - strlen("{HEX}")) % 2 != 0){
+ /* A hexadecimal encoded password should have even length */
+ err = EINVAL;
+ krb5_set_error_message (0, err, "Password corrupted");
+ ret->len = 0;
+ goto cleanup;
+ }
+ ret->value = (unsigned char *)malloc((pwd.len - strlen("{HEX}")) / 2 + 1);
+ if(ret->value == NULL){
+ err = ENOMEM;
+ ret->len = 0;
+ goto cleanup;
+ }
+ ret->len = (pwd.len - strlen("{HEX}")) / 2;
+ ret->value[ret->len] = '\0';
+ for (i = strlen("{HEX}"), j = 0; i < pwd.len; i += 2, j++) {
+ int k;
+ /* Check if it is a hexadecimal number */
+ if (isxdigit(pwd.value[i]) == 0 || isxdigit(pwd.value[i + 1]) == 0) {
+ err = EINVAL;
+ krb5_set_error_message (0, err, "Not a hexadecimal password");
+ ret->len = 0;
+ goto cleanup;
+ }
+ sscanf((char *)pwd.value + i, "%2x", &k);
+ ret->value[j] = k;
+ }
+ goto cleanup;
+ } else {
+ err = EINVAL;
+ krb5_set_error_message (0, err, "Not a hexadecimal password");
+ ret->len = 0;
+ goto cleanup;
+ }
+
+ cleanup:
+
+ if(ret->len == 0) {
+ free(ret->value);
+ ret->value = NULL;
+ }
+ return(err);
+}
+
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.h b/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.h
new file mode 100644
index 000000000..c51d1a172
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.h
@@ -0,0 +1,50 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_service_stash.h
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LDAP_SERVICE_STASH_H
+#define LDAP_SERVICE_STASH_H 1
+
+#define RECORDLEN 1024
+struct data{
+ int len;
+ unsigned char *value;
+};
+
+int
+dec_password(struct data, struct data *);
+
+krb5_error_code
+krb5_ldap_readpassword(krb5_context, krb5_ldap_context *, unsigned char **);
+
+int
+tohex(krb5_data, krb5_data *);
+
+#endif
+
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_services.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_services.c
new file mode 100644
index 000000000..fa1bdd7b3
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_services.c
@@ -0,0 +1,595 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_services.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ldap_main.h"
+#include "kdb_ldap.h"
+#include "ldap_services.h"
+#include "ldap_err.h"
+
+#if defined(HAVE_EDIRECTORY)
+
+static char *realmcontclass[] = {"krbRealmContainer", NULL};
+
+/*
+ * create the service object from Directory
+ */
+
+krb5_error_code
+krb5_ldap_create_service(context, service, mask)
+ krb5_context context;
+ krb5_ldap_service_params *service;
+ int mask;
+{
+ int i=0, j=0;
+ krb5_error_code st=0;
+ LDAP *ld=NULL;
+ char **rdns=NULL, *realmattr=NULL, *strval[3]={NULL};
+ LDAPMod **mods=NULL;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+ char errbuf[1024];
+
+ /* validate the input parameter */
+ if (service == NULL || service->servicedn == NULL) {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "Service DN NULL");
+ goto cleanup;
+ }
+
+ SETUP_CONTEXT();
+ GET_HANDLE();
+
+ /* identify the class that the object should belong to. This depends on the servicetype */
+ memset(strval, 0, sizeof(strval));
+ strval[0] = "krbService";
+ if (service->servicetype == LDAP_KDC_SERVICE) {
+ strval[1] = "krbKdcService";
+ realmattr = "krbKdcServers";
+ } else if (service->servicetype == LDAP_ADMIN_SERVICE) {
+ strval[1] = "krbAdmService";
+ realmattr = "krbAdmServers";
+ } else if (service->servicetype == LDAP_PASSWD_SERVICE) {
+ strval[1] = "krbPwdService";
+ realmattr = "krbPwdServers";
+ } else {
+ strval[1] = "krbKdcService";
+ realmattr = "krbKdcServers";
+ }
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
+ goto cleanup;
+
+ rdns = ldap_explode_dn(service->servicedn, 1);
+ if (rdns == NULL) {
+ st = LDAP_INVALID_DN_SYNTAX;
+ goto cleanup;
+ }
+ memset(strval, 0, sizeof(strval));
+ strval[0] = rdns[0];
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0)
+ goto cleanup;
+
+ if (mask & LDAP_SERVICE_SERVICEFLAG) {
+ if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbserviceflags", LDAP_MOD_ADD,
+ service->krbserviceflags)) != 0)
+ goto cleanup;
+ }
+
+ if (mask & LDAP_SERVICE_HOSTSERVER) {
+ if (service->krbhostservers != NULL) {
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbhostserver", LDAP_MOD_ADD,
+ service->krbhostservers)) != 0)
+ goto cleanup;
+ } else {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "'krbhostserver' argument invalid");
+ goto cleanup;
+ }
+ }
+
+ if (mask & LDAP_SERVICE_REALMREFERENCE) {
+ if (service->krbrealmreferences != NULL) {
+ unsigned int realmmask=0;
+
+ /* check for the validity of the values */
+ for (j=0; service->krbrealmreferences[j] != NULL; ++j) {
+ st = checkattributevalue(ld, service->krbrealmreferences[j], "ObjectClass",
+ realmcontclass, &realmmask);
+ CHECK_CLASS_VALIDITY(st, realmmask, "realm object value: ");
+ }
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbrealmreferences", LDAP_MOD_ADD,
+ service->krbrealmreferences)) != 0)
+ goto cleanup;
+ } else {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "Server has no 'krbrealmreferences'");
+ goto cleanup;
+ }
+ }
+
+ /* ldap add operation */
+ if ((st=ldap_add_s(ld, service->servicedn, mods)) != LDAP_SUCCESS) {
+ st = set_ldap_error (context, st, OP_ADD);
+ goto cleanup;
+ }
+
+ /*
+ * If the service created has realm/s associated with it, then the realm should be updated
+ * to have a reference to the service object just created.
+ */
+ if (mask & LDAP_SERVICE_REALMREFERENCE) {
+ for (i=0; service->krbrealmreferences[i]; ++i) {
+ if((st=updateAttribute(ld, service->krbrealmreferences[i], realmattr,
+ service->servicedn)) != 0) {
+ sprintf (errbuf, "Error adding 'krbRealmReferences' to %s: ",
+ service->krbrealmreferences[i]);
+ prepend_err_str (context, errbuf, st, st);
+ /* delete service object, status ignored intentionally */
+ ldap_delete_s(ld, service->servicedn);
+ goto cleanup;
+ }
+ }
+ }
+
+ cleanup:
+
+ if (rdns)
+ ldap_value_free (rdns);
+
+ ldap_mods_free(mods, 1);
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
+
+
+/*
+ * modify the service object from Directory
+ */
+
+krb5_error_code
+krb5_ldap_modify_service(context, service, mask)
+ krb5_context context;
+ krb5_ldap_service_params *service;
+ int mask;
+{
+ int i=0, j=0, count=0;
+ krb5_error_code st=0;
+ LDAP *ld=NULL;
+ char **values=NULL, *attr[] = { "krbRealmReferences", NULL};
+ char *realmattr=NULL;
+ char **oldrealmrefs=NULL, **newrealmrefs=NULL;
+ LDAPMod **mods=NULL;
+ LDAPMessage *result=NULL, *ent=NULL;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+
+ /* validate the input parameter */
+ if (service == NULL || service->servicedn == NULL) {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "Service DN is NULL");
+ goto cleanup;
+ }
+
+ SETUP_CONTEXT();
+ GET_HANDLE();
+
+ if (mask & LDAP_SERVICE_SERVICEFLAG) {
+ if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbserviceflags", LDAP_MOD_REPLACE,
+ service->krbserviceflags)) != 0)
+ goto cleanup;
+ }
+
+ if (mask & LDAP_SERVICE_HOSTSERVER) {
+ if (service->krbhostservers != NULL) {
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbhostserver", LDAP_MOD_REPLACE,
+ service->krbhostservers)) != 0)
+ goto cleanup;
+ } else {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "'krbhostserver' value invalid");
+ goto cleanup;
+ }
+ }
+
+ if (mask & LDAP_SERVICE_REALMREFERENCE) {
+ if (service->krbrealmreferences != NULL) {
+ unsigned int realmmask=0;
+
+ /* check for the validity of the values */
+ for (j=0; service->krbrealmreferences[j]; ++j) {
+ st = checkattributevalue(ld, service->krbrealmreferences[j], "ObjectClass",
+ realmcontclass, &realmmask);
+ CHECK_CLASS_VALIDITY(st, realmmask, "realm object value: ");
+ }
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbrealmreferences", LDAP_MOD_REPLACE,
+ service->krbrealmreferences)) != 0)
+ goto cleanup;
+
+
+ /* get the attribute of the realm to be set */
+ if (service->servicetype == LDAP_KDC_SERVICE)
+ realmattr = "krbKdcServers";
+ else if (service->servicetype == LDAP_ADMIN_SERVICE)
+ realmattr = "krbAdmservers";
+ else if (service->servicetype == LDAP_PASSWD_SERVICE)
+ realmattr = "krbPwdServers";
+ else
+ realmattr = "krbKdcServers";
+
+ /* read the existing list of krbRealmreferences. this will needed */
+ if ((st = ldap_search_s (ld,
+ service->servicedn,
+ LDAP_SCOPE_BASE,
+ 0,
+ attr,
+ 0,
+ &result)) != LDAP_SUCCESS) {
+ st = set_ldap_error (context, st, OP_SEARCH);
+ goto cleanup;
+ }
+
+ ent = ldap_first_entry(ld, result);
+ if (ent) {
+ if ((values=ldap_get_values(ld, ent, "krbRealmReferences")) != NULL) {
+ count = ldap_count_values(values);
+ if ((st=copy_arrays(values, &oldrealmrefs, count)) != 0)
+ goto cleanup;
+ ldap_value_free(values);
+ }
+ }
+ ldap_msgfree(result);
+ } else {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "'krbRealmReferences' value invalid");
+ goto cleanup;
+ }
+ }
+
+ /* ldap modify operation */
+ if ((st=ldap_modify_s(ld, service->servicedn, mods)) != LDAP_SUCCESS) {
+ st = set_ldap_error (context, st, OP_MOD);
+ goto cleanup;
+ }
+
+ /*
+ * If the service modified had realm/s associations changed, then the realm should be
+ * updated to reflect the changes.
+ */
+
+ if (mask & LDAP_SERVICE_REALMREFERENCE) {
+ /* get the count of the new list of krbrealmreferences */
+ for (i=0; service->krbrealmreferences[i]; ++i)
+ ;
+
+ /* make a new copy of the krbrealmreferences */
+ if ((st=copy_arrays(service->krbrealmreferences, &newrealmrefs, i)) != 0)
+ goto cleanup;
+
+ /* find the deletions/additions to the list of krbrealmreferences */
+ if (disjoint_members(oldrealmrefs, newrealmrefs) != 0)
+ goto cleanup;
+
+ /* see if some of the attributes have to be deleted */
+ if (oldrealmrefs) {
+
+ /* update the dn represented by the attribute that is to be deleted */
+ for (i=0; oldrealmrefs[i]; ++i)
+ if((st=deleteAttribute(ld, oldrealmrefs[i], realmattr, service->servicedn)) != 0)
+ {
+ prepend_err_str (context, "Error deleting realm attribute:", st, st);
+ goto cleanup;
+ }
+ }
+
+ /* see if some of the attributes have to be added */
+ for (i=0; newrealmrefs[i]; ++i)
+ if((st=updateAttribute(ld, newrealmrefs[i], realmattr, service->servicedn)) != 0)
+ {
+ prepend_err_str (context, "Error updating realm attribute: ", st, st);
+ goto cleanup;
+ }
+ }
+
+ cleanup:
+
+ if (oldrealmrefs) {
+ for (i=0; oldrealmrefs[i]; ++i)
+ free (oldrealmrefs[i]);
+ free (oldrealmrefs);
+ }
+
+ if (newrealmrefs) {
+ for (i=0; newrealmrefs[i]; ++i)
+ free (newrealmrefs[i]);
+ free (newrealmrefs);
+ }
+
+ ldap_mods_free(mods, 1);
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
+
+
+krb5_error_code
+krb5_ldap_delete_service(context, service, servicedn)
+ krb5_context context;
+ krb5_ldap_service_params *service;
+ char *servicedn;
+{
+ krb5_error_code st = 0;
+ LDAP *ld=NULL;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+
+ SETUP_CONTEXT();
+ GET_HANDLE();
+
+ st = ldap_delete_s(ld, servicedn);
+ if (st != 0) {
+ st = set_ldap_error (context, st, OP_DEL);
+ }
+
+ /* NOTE: This should be removed now as the backlinks are going off in OpenLDAP */
+ /* time to delete krbrealmreferences. This is only for OpenLDAP */
+#ifndef HAVE_EDIRECTORY
+ {
+ int i=0;
+ char *attr=NULL;
+
+ if (service) {
+ if (service->krbrealmreferences) {
+ if (service->servicetype == LDAP_KDC_SERVICE)
+ attr = "krbkdcservers";
+ else if (service->servicetype == LDAP_ADMIN_SERVICE)
+ attr = "krbadmservers";
+ else if (service->servicetype == LDAP_PASSWD_SERVICE)
+ attr = "krbpwdservers";
+
+ for (i=0; service->krbrealmreferences[i]; ++i) {
+ deleteAttribute(ld, service->krbrealmreferences[i], attr, servicedn);
+ }
+ }
+ }
+ }
+#endif
+
+ cleanup:
+
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
+
+
+/*
+ * This function lists service objects from Directory
+ */
+
+krb5_error_code
+krb5_ldap_list_services(context, containerdn, services)
+ krb5_context context;
+ char *containerdn;
+ char ***services;
+{
+ return (krb5_ldap_list(context, services, "krbService", containerdn));
+}
+
+/*
+ * This function reads the service object from Directory
+ */
+krb5_error_code
+krb5_ldap_read_service(context, servicedn, service, omask)
+ krb5_context context;
+ char *servicedn;
+ krb5_ldap_service_params **service;
+ int *omask;
+{
+ char **values=NULL;
+ int i=0, count=0, objectmask=0;
+ krb5_error_code st=0, tempst=0;
+ LDAPMessage *result=NULL,*ent=NULL;
+ char *attributes[] = {"krbHostServer", "krbServiceflags",
+ "krbRealmReferences", "objectclass", NULL};
+ char *attrvalues[] = {"krbService", NULL};
+ krb5_ldap_service_params *lservice=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+ LDAP *ld = NULL;
+
+ /* validate the input parameter */
+ if (servicedn == NULL) {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "Service DN NULL");
+ goto cleanup;
+ }
+
+ SETUP_CONTEXT();
+ GET_HANDLE();
+
+ *omask = 0;
+
+ /* the policydn object should be of the krbService object class */
+ st = checkattributevalue(ld, servicedn, "objectClass", attrvalues, &objectmask);
+ CHECK_CLASS_VALIDITY(st, objectmask, "service object value: ");
+
+ /* Initialize service structure */
+ lservice =(krb5_ldap_service_params *) calloc(1, sizeof(krb5_ldap_service_params));
+ if (lservice == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+
+ /* allocate tl_data structure to store MASK information */
+ lservice->tl_data = calloc (1, sizeof(*lservice->tl_data));
+ if (lservice->tl_data == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ lservice->tl_data->tl_data_type = KDB_TL_USER_INFO;
+
+ LDAP_SEARCH(servicedn, LDAP_SCOPE_BASE, "(objectclass=krbService)", attributes);
+
+ lservice->servicedn = strdup(servicedn);
+ CHECK_NULL(lservice->servicedn);
+
+ ent=ldap_first_entry(ld, result);
+ if (ent != NULL) {
+
+ if((values=ldap_get_values(ld, ent, "krbServiceFlags")) != NULL) {
+ lservice->krbserviceflags = atoi(values[0]);
+ *omask |= LDAP_SERVICE_SERVICEFLAG;
+ ldap_value_free(values);
+ }
+
+ if((values=ldap_get_values(ld, ent, "krbHostServer")) != NULL) {
+ count = ldap_count_values(values);
+ if ((st=copy_arrays(values, &(lservice->krbhostservers), count)) != 0)
+ goto cleanup;
+ *omask |= LDAP_SERVICE_HOSTSERVER;
+ ldap_value_free(values);
+ }
+
+ if((values=ldap_get_values(ld, ent, "krbRealmReferences")) != NULL) {
+ count = ldap_count_values(values);
+ if ((st=copy_arrays(values, &(lservice->krbrealmreferences), count)) != 0)
+ goto cleanup;
+ *omask |= LDAP_SERVICE_REALMREFERENCE;
+ ldap_value_free(values);
+ }
+
+ if((values=ldap_get_values(ld, ent, "objectClass")) != NULL) {
+ for (i=0; values[i]; ++i){
+ if (strcasecmp(values[i], "krbKdcService") == 0) {
+ lservice->servicetype = LDAP_KDC_SERVICE;
+ break;
+ }
+
+ if (strcasecmp(values[i], "krbAdmService") == 0) {
+ lservice->servicetype = LDAP_ADMIN_SERVICE;
+ break;
+ }
+
+ if (strcasecmp(values[i], "krbPwdService") == 0) {
+ lservice->servicetype = LDAP_PASSWD_SERVICE;
+ break;
+ }
+ }
+ ldap_value_free(values);
+ }
+ }
+ ldap_msgfree(result);
+
+ cleanup:
+ if(st != 0) {
+ krb5_ldap_free_service(context, lservice);
+ *service = NULL;
+ } else {
+ store_tl_data(lservice->tl_data, KDB_TL_MASK, omask);
+ *service = lservice;
+ }
+
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
+
+/*
+ * This function frees the krb5_ldap_service_params structure members.
+ */
+
+krb5_error_code
+krb5_ldap_free_service(context, service)
+ krb5_context context;
+ krb5_ldap_service_params *service;
+{
+ int i=0;
+
+ if (service == NULL)
+ return 0;
+
+ if (service->servicedn)
+ free (service->servicedn);
+
+ if (service->krbrealmreferences) {
+ for (i=0; service->krbrealmreferences[i]; ++i)
+ free (service->krbrealmreferences[i]);
+ free (service->krbrealmreferences);
+ }
+
+ if (service->krbhostservers) {
+ for (i=0; service->krbhostservers[i]; ++i)
+ free (service->krbhostservers[i]);
+ free (service->krbhostservers);
+ }
+
+ if (service->tl_data) {
+ if (service->tl_data->tl_data_contents)
+ free (service->tl_data->tl_data_contents);
+ free (service->tl_data);
+ }
+
+ free (service);
+ return 0;
+}
+
+krb5_error_code
+krb5_ldap_set_service_passwd(context, service, passwd)
+ krb5_context context;
+ char *service;
+ char *passwd;
+{
+ krb5_error_code st=0;
+ LDAPMod **mods=NULL;
+ char *password[2] = {NULL};
+ LDAP *ld=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+
+ password[0] = passwd;
+
+ SETUP_CONTEXT();
+ GET_HANDLE();
+
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "userPassword", LDAP_MOD_REPLACE, password)) != 0)
+ goto cleanup;
+
+ st = ldap_modify_s(ld, service, mods);
+ if (st) {
+ st = set_ldap_error (context, st, OP_MOD);
+ }
+
+ cleanup:
+ ldap_mods_free(mods, 1);
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
+#endif
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_services.h b/src/plugins/kdb/ldap/libkdb_ldap/ldap_services.h
new file mode 100644
index 000000000..d2676a3d4
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_services.h
@@ -0,0 +1,97 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_services.h
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LDAP_SERVICE_H
+#define _LDAP_SERVICE_H 1
+
+/* service specific mask */
+#define LDAP_SERVICE_SERVICEFLAG 0x0001
+#define LDAP_SERVICE_HOSTSERVER 0x0002
+#define LDAP_SERVICE_REALMREFERENCE 0x0004
+
+/* service type mask */
+#define LDAP_KDC_SERVICE 0x0001
+#define LDAP_ADMIN_SERVICE 0x0002
+#define LDAP_PASSWD_SERVICE 0x0004
+
+/* rights mask */
+#define LDAP_SUBTREE_RIGHTS 0x0001
+#define LDAP_REALM_RIGHTS 0x0002
+
+/* Types of service flags */
+#define SERVICE_FLAGS_AUTO_RESTART 0x0001
+#define SERVICE_FLAGS_CHECK_ADDRESSES 0x0002
+#define SERVICE_FLAGS_UNIXTIME_OLD_PATYPE 0x0004
+
+/* Service protocol type */
+#define SERVICE_PROTOCOL_TYPE_UDP "0"
+#define SERVICE_PROTOCOL_TYPE_TCP "1"
+
+typedef struct _krb5_ldap_service_params {
+ char *servicedn;
+ int servicetype;
+ int krbserviceflags;
+ char **krbhostservers;
+ char **krbrealmreferences;
+ krb5_tl_data *tl_data;
+} krb5_ldap_service_params;
+
+#ifdef HAVE_EDIRECTORY
+
+krb5_error_code
+krb5_ldap_read_service( krb5_context, char *, krb5_ldap_service_params **, int *);
+
+krb5_error_code
+krb5_ldap_create_service( krb5_context, krb5_ldap_service_params *,int);
+
+krb5_error_code
+krb5_ldap_modify_service( krb5_context, krb5_ldap_service_params *, int);
+
+krb5_error_code
+krb5_ldap_delete_service( krb5_context, krb5_ldap_service_params *, char *);
+
+krb5_error_code
+krb5_ldap_list_services( krb5_context, char *, char ***);
+
+krb5_error_code
+krb5_ldap_free_service( krb5_context, krb5_ldap_service_params *);
+
+
+krb5_error_code
+krb5_ldap_set_service_passwd( krb5_context, char *, char *);
+
+krb5_error_code
+krb5_ldap_add_service_rights( krb5_context, int, char *, char *, char *, int);
+
+krb5_error_code
+krb5_ldap_delete_service_rights( krb5_context, int, char *, char *, char *, int);
+#endif
+
+#endif
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c
new file mode 100644
index 000000000..f5948786f
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c
@@ -0,0 +1,526 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_tkt_policy.c
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ldap_main.h"
+#include "kdb_ldap.h"
+#include "ldap_tkt_policy.h"
+#include "ldap_err.h"
+
+/* Ticket policy object management */
+
+/*
+* This function changes the value of policyreference count for a particular ticket policy. if flag is 1 it will increment else it will reduce by one
+*/
+
+krb5_error_code
+krb5_ldap_change_count(context ,policydn ,flag)
+ krb5_context context;
+ char *policydn;
+ int flag;
+{
+
+ krb5_error_code st=0;
+ int objectmask=0;
+ LDAP *ld=NULL;
+ char *attrvalues[] = { "krbPolicy", NULL};
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+ krb5_ldap_policy_params *policyparams=NULL;
+ int mask = 0;
+
+ /* validate the input parameters */
+ if (policydn == NULL) {
+ st = EINVAL;
+ prepend_err_str(context,"Ticket Policy Object information missing",st,st);
+ goto cleanup;
+ }
+
+ SETUP_CONTEXT();
+ GET_HANDLE();
+
+ /* the policydn object should be of the krbPolicy object class */
+ st = checkattributevalue(ld, policydn, "objectClass", attrvalues, &objectmask);
+ CHECK_CLASS_VALIDITY(st, objectmask, "ticket policy object: ");
+
+ /* Initialize ticket policy structure */
+
+ if ((st = krb5_ldap_read_policy(context, policydn, &policyparams, &mask)))
+ goto cleanup;
+ if(flag == 1){
+ /*Increment*/
+ policyparams->polrefcount +=1;
+ }
+ else{
+ /*Decrement*/
+ if(policyparams->polrefcount >0)
+ {
+ policyparams->polrefcount-=1;
+ }
+ }
+ mask |= LDAP_POLICY_COUNT;
+
+ if ((st = krb5_ldap_modify_policy(context, policyparams, mask)))
+ goto cleanup;
+
+cleanup:
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
+
+/*
+ * create the Ticket policy object in Directory.
+ */
+krb5_error_code
+krb5_ldap_create_policy(context, policy, mask)
+ krb5_context context;
+ krb5_ldap_policy_params *policy;
+ int mask;
+{
+ krb5_error_code st=0;
+ LDAP *ld=NULL;
+ char **rdns=NULL, *strval[3]={NULL};
+ LDAPMod **mods=NULL;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+
+ /* validate the input parameters */
+ if (policy == NULL || policy->policydn==NULL) {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "Ticket Policy Object DN missing");
+ goto cleanup;
+ }
+
+ SETUP_CONTEXT();
+ GET_HANDLE();
+
+ rdns = ldap_explode_dn(policy->policydn, 1);
+ if (rdns == NULL) {
+ st = LDAP_INVALID_DN_SYNTAX;
+ goto cleanup;
+ }
+
+ memset(strval, 0, sizeof(strval));
+ strval[0] = rdns[0];
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0)
+ goto cleanup;
+
+ memset(strval, 0, sizeof(strval));
+ strval[0] = "krbPolicy";
+ strval[1] = "krbPolicyaux";
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
+ goto cleanup;
+
+ if (mask & LDAP_POLICY_MAXTKTLIFE) {
+ if((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxticketlife", LDAP_MOD_ADD,
+ policy->maxtktlife)) != 0)
+ goto cleanup;
+ }
+
+ if (mask & LDAP_POLICY_MAXRENEWLIFE) {
+ if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxrenewableage", LDAP_MOD_ADD,
+ policy->maxrenewlife)) != 0)
+ goto cleanup;
+ }
+
+ if (mask & LDAP_POLICY_TKTFLAGS) {
+ if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbticketflags", LDAP_MOD_ADD,
+ policy->tktflags)) != 0)
+ goto cleanup;
+ }
+ /*ticket policy reference count attribute added with value 0 */
+
+ if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbPolicyRefCount", LDAP_MOD_ADD,
+ 0)) != 0)
+ goto cleanup;
+
+ /* ldap add operation */
+ if ((st=ldap_add_s(ld, policy->policydn, mods)) != LDAP_SUCCESS) {
+ st = set_ldap_error (context, st, OP_ADD);
+ goto cleanup;
+ }
+
+ cleanup:
+ if (rdns)
+ ldap_value_free(rdns);
+
+ ldap_mods_free(mods, 1);
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
+
+
+/*
+ * modify the Ticket policy object in Directory.
+ */
+
+krb5_error_code
+krb5_ldap_modify_policy(context, policy, mask)
+ krb5_context context;
+ krb5_ldap_policy_params *policy;
+ int mask;
+{
+ int objectmask=0;
+ krb5_error_code st=0;
+ LDAP *ld=NULL;
+ char *attrvalues[]={"krbPolicy", "krbPolicyAux", NULL}, *strval[2]={NULL};
+ LDAPMod **mods=NULL;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+
+ /* validate the input parameters */
+ if (policy == NULL || policy->policydn==NULL) {
+ st = EINVAL;
+ krb5_set_error_message (context, st, "Ticket Policy Object DN missing");
+ goto cleanup;
+ }
+
+ SETUP_CONTEXT();
+ GET_HANDLE();
+
+ /* the policydn object should be of the krbPolicy object class */
+ st = checkattributevalue(ld, policy->policydn, "objectClass", attrvalues, &objectmask);
+ CHECK_CLASS_VALIDITY(st, objectmask, "ticket policy object: ");
+
+ if ((objectmask & 0x02) == 0) { /* add krbpolicyaux to the object class list */
+ memset(strval, 0, sizeof(strval));
+ strval[0] = "krbPolicyAux";
+ if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
+ goto cleanup;
+ }
+
+ if (mask & LDAP_POLICY_MAXTKTLIFE) {
+ if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxticketlife", LDAP_MOD_REPLACE,
+ policy->maxtktlife)) != 0)
+ goto cleanup;
+ }
+
+ if (mask & LDAP_POLICY_MAXRENEWLIFE) {
+ if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxrenewableage", LDAP_MOD_REPLACE,
+ policy->maxrenewlife)) != 0)
+ goto cleanup;
+ }
+
+ if (mask & LDAP_POLICY_TKTFLAGS) {
+ if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbticketflags", LDAP_MOD_REPLACE,
+ policy->tktflags)) != 0)
+ goto cleanup;
+ }
+
+ if (mask & LDAP_POLICY_COUNT) {
+ if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpolicyrefcount", LDAP_MOD_REPLACE,
+ policy->polrefcount)) != 0)
+ goto cleanup;
+ }
+ if ((st=ldap_modify_s(ld, policy->policydn, mods)) != LDAP_SUCCESS) {
+ st = set_ldap_error (context, st, OP_MOD);
+ goto cleanup;
+ }
+
+ cleanup:
+ ldap_mods_free(mods, 1);
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
+
+
+/*
+ * Read the policy object from the Directory and populate the krb5_ldap_policy_params
+ * structure.
+ */
+
+krb5_error_code
+krb5_ldap_read_policy(context, policydn, policy, omask)
+ krb5_context context;
+ char *policydn;
+ krb5_ldap_policy_params **policy;
+ int *omask;
+{
+ krb5_error_code st=0, tempst=0;
+ int objectmask=0;
+ LDAP *ld=NULL;
+ LDAPMessage *result=NULL,*ent=NULL;
+ char *attributes[] = { "krbMaxTicketLife", "krbMaxRenewableAge", "krbTicketFlags", "krbPolicyRefCount", NULL};
+ char *attrvalues[] = { "krbPolicy", NULL};
+ krb5_ldap_policy_params *lpolicy=NULL;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+
+ /* validate the input parameters */
+ if (policydn == NULL || policy == NULL) {
+ st = EINVAL;
+ krb5_set_error_message(context, st, "Ticket Policy Object information missing");
+ goto cleanup;
+ }
+
+ SETUP_CONTEXT();
+ GET_HANDLE();
+
+ /* the policydn object should be of the krbPolicy object class */
+ st = checkattributevalue(ld, policydn, "objectClass", attrvalues, &objectmask);
+ CHECK_CLASS_VALIDITY(st, objectmask, "ticket policy object: ");
+
+ /* Initialize ticket policy structure */
+ lpolicy =(krb5_ldap_policy_params *) malloc(sizeof(krb5_ldap_policy_params));
+ CHECK_NULL(lpolicy);
+ memset(lpolicy, 0, sizeof(krb5_ldap_policy_params));
+
+ lpolicy->tl_data = calloc (1, sizeof(*lpolicy->tl_data));
+ CHECK_NULL(lpolicy->tl_data);
+ lpolicy->tl_data->tl_data_type = KDB_TL_USER_INFO;
+
+ LDAP_SEARCH(policydn, LDAP_SCOPE_BASE, "(objectclass=krbPolicy)", attributes);
+
+ *omask = 0;
+ lpolicy->policydn = strdup(policydn);
+ CHECK_NULL(lpolicy->policydn);
+
+ ent=ldap_first_entry(ld, result);
+ if (ent != NULL) {
+ if (krb5_ldap_get_value(ld, ent, "krbmaxticketlife", (int *) &(lpolicy->maxtktlife)) == 0)
+ *omask |= LDAP_POLICY_MAXTKTLIFE;
+
+ if (krb5_ldap_get_value(ld, ent, "krbmaxrenewableage", (int *) &(lpolicy->maxrenewlife)) == 0)
+ *omask |= LDAP_POLICY_MAXRENEWLIFE;
+
+ if (krb5_ldap_get_value(ld, ent, "krbticketflags", (int *) &(lpolicy->tktflags)) == 0)
+ *omask |= LDAP_POLICY_TKTFLAGS;
+ if (krb5_ldap_get_value(ld, ent, "krbPolicyRefCount", (int *) &(lpolicy->polrefcount)) == 0)
+ *omask |= LDAP_POLICY_COUNT;
+
+ }
+ ldap_msgfree(result);
+
+ lpolicy->mask = *omask;
+ store_tl_data(lpolicy->tl_data, KDB_TL_MASK, omask);
+ *policy = lpolicy;
+
+ cleanup:
+ if (st != 0) {
+ krb5_ldap_free_policy(context, lpolicy);
+ *policy = NULL;
+ }
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
+
+
+/*
+ * function to delete ticket policy object from the directory. Before calling this function krb5_ldap_read_policy
+ * should be called to check the existence of the object. This serves one major purpose, i.e. if the object to be
+ * is anything other than the ticket policy object then the krb5_ldap_read_policy returns an error and thus is not
+ * accidently deleted in this function.
+ *
+ * NOTE: Other kerberos objects (user/realm object) might be having references to the
+ * policy object to be deleted. This situation is not handled here, instead is taken care
+ * of at all the places where the deleted policy object is read, to ignore a return status
+ * of LDAP_NO_SUCH_OBJECT and continue.
+ */
+
+krb5_error_code
+krb5_ldap_delete_policy(context, policydn, policy, mask)
+ krb5_context context;
+ char *policydn;
+ krb5_ldap_policy_params *policy;
+ int mask;
+{
+ krb5_error_code st = 0;
+ LDAP *ld = NULL;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+
+ if (policy == NULL || policydn==NULL) {
+ st = EINVAL;
+ prepend_err_str (context,"Ticket Policy Object DN missing",st,st);
+ goto cleanup;
+ }
+
+
+ SETUP_CONTEXT();
+ GET_HANDLE();
+
+
+ /*checking for policy count for 0 and will not permit delete if it is greater than 0*/
+
+ if(policy->polrefcount == 0){
+
+ if ((st=ldap_delete_s(ld, policydn)) != 0)
+ {
+ prepend_err_str (context,ldap_err2string(st),st,st);
+
+ goto cleanup;
+ }
+ }
+ else {
+ st = EINVAL;
+ prepend_err_str (context,"Delete Failed: One or more Principals associated with the Ticket Policy",st,st);
+ goto cleanup;
+ }
+
+cleanup:
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
+
+
+/*
+ * list policy objects from Directory
+ */
+
+krb5_error_code
+krb5_ldap_list_policy(context, containerdn, policy)
+ krb5_context context;
+ char *containerdn;
+ char ***policy;
+{
+ krb5_error_code st=0;
+
+ st = krb5_ldap_list(context, policy, "krbPolicy", containerdn);
+
+ return st;
+}
+
+/*
+ * Function to free the ticket policy object structure.
+ * Note: this function assumes that memory of the policy structure is dynamically allocated and hence the whole
+ * structure is freed up. Care should be taken not to call this function on a static structure
+ */
+
+krb5_error_code
+krb5_ldap_free_policy(context, policy)
+ krb5_context context;
+ krb5_ldap_policy_params *policy;
+{
+
+ krb5_error_code st=0;
+
+ if (policy == NULL)
+ return st;
+
+ if (policy->policydn)
+ free (policy->policydn);
+
+ if (policy->tl_data) {
+ if (policy->tl_data->tl_data_contents)
+ free (policy->tl_data->tl_data_contents);
+ free (policy->tl_data);
+ }
+ free (policy);
+
+ return st;
+}
+
+/*
+ * This function is general object listing routine. It is currently used for ticket policy
+ * object listing.
+ */
+
+krb5_error_code
+krb5_ldap_list(context, list, objectclass, containerdn)
+ krb5_context context;
+ char ***list;
+ char *objectclass;
+ char *containerdn;
+{
+ char *filter=NULL, *dn=NULL;
+ krb5_error_code st=0, tempst=0;
+ int i=0, count=0, filterlen=0;
+ LDAP *ld=NULL;
+ LDAPMessage *result=NULL,*ent=NULL;
+ kdb5_dal_handle *dal_handle=NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ krb5_ldap_server_handle *ldap_server_handle=NULL;
+
+ SETUP_CONTEXT();
+ GET_HANDLE();
+
+ /* check if the containerdn exists */
+ if (containerdn) {
+ if ((st=checkattributevalue(ld, containerdn, NULL, NULL, NULL)) != 0) {
+ prepend_err_str (context, "Error reading container object: ", st, st);
+ goto cleanup;
+ }
+ }
+
+ /* set the filter for the search operation */
+ filterlen = strlen("(objectclass=") + strlen(objectclass) + 1 + 1;
+ filter = malloc ((unsigned) filterlen);
+ if (filter == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+ snprintf(filter, (unsigned) filterlen,"(objectclass=%s)",objectclass);
+
+ LDAP_SEARCH(containerdn, LDAP_SCOPE_SUBTREE, filter, NULL);
+
+ count = ldap_count_entries(ld, result);
+ if (count == -1) {
+ ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &st);
+ st = set_ldap_error(context, st, OP_SEARCH);
+ goto cleanup;
+ }
+ *list = (char **) calloc ((unsigned) count+1, sizeof(char *));
+ if (*list == NULL) {
+ st = ENOMEM;
+ goto cleanup;
+ }
+
+ for(ent=ldap_first_entry(ld, result), count=0; ent != NULL; ent=ldap_next_entry(ld, ent), ++count) {
+ if ((dn=ldap_get_dn(ld, ent)) == NULL)
+ continue;
+ if (((*list)[count] = strdup(dn)) == NULL) {
+ ldap_memfree (dn);
+ st = ENOMEM;
+ goto cleanup;
+ }
+ ldap_memfree(dn);
+ }
+ ldap_msgfree(result);
+
+ cleanup:
+ if (filter)
+ free (filter);
+
+ /* some error, free up all the memory */
+ if (st != 0) {
+ if (*list) {
+ for (i=0; (*list)[i]; ++i)
+ free ((*list)[i]);
+ free (*list);
+ *list = NULL;
+ }
+ }
+ krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
+ return st;
+}
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.h b/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.h
new file mode 100644
index 000000000..a5d198777
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.h
@@ -0,0 +1,76 @@
+/*
+ * lib/kdb/kdb_ldap/ldap_tkt_policy.h
+ *
+ * Copyright (c) 2004-2005, Novell, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LDAP_POLICY_H
+#define _LDAP_POLICY_H 1
+
+/* policy specific mask */
+
+#define LDAP_POLICY_MAXTKTLIFE 0x0001
+#define LDAP_POLICY_MAXRENEWLIFE 0x0002
+#define LDAP_POLICY_TKTFLAGS 0x0004
+#define LDAP_POLICY_COUNT 0x0008
+/* policy object structure */
+
+typedef struct _krb5_ldap_policy_params {
+ char *policydn;
+ long mask;
+ long maxtktlife;
+ long maxrenewlife;
+ long tktflags;
+ long polrefcount;
+ krb5_tl_data *tl_data;
+}krb5_ldap_policy_params;
+
+krb5_error_code
+krb5_ldap_create_policy(krb5_context, krb5_ldap_policy_params *, int);
+
+krb5_error_code
+krb5_ldap_modify_policy(krb5_context, krb5_ldap_policy_params *, int);
+
+krb5_error_code
+krb5_ldap_read_policy(krb5_context, char *, krb5_ldap_policy_params **, int *);
+
+krb5_error_code
+krb5_ldap_delete_policy(krb5_context, char *, krb5_ldap_policy_params *, int);
+
+krb5_error_code
+krb5_ldap_clear_policy(krb5_context, char *);
+
+krb5_error_code
+krb5_ldap_list_policy(krb5_context, char *, char ***);
+
+krb5_error_code
+krb5_ldap_free_policy(krb5_context, krb5_ldap_policy_params *);
+
+krb5_error_code
+krb5_ldap_change_count(krb5_context ,char * , int);
+
+#endif
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports b/src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports
new file mode 100644
index 000000000..2e75b7eae
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports
@@ -0,0 +1,41 @@
+tohex
+krb5_ldap_open
+krb5_ldap_close
+krb5_ldap_db_init
+krb5_ldap_lib_init
+krb5_ldap_lib_cleanup
+krb5_ldap_db_get_age
+krb5_ldap_read_server_params
+krb5_ldap_put_principal
+krb5_ldap_get_principal
+krb5_ldap_delete_principal
+krb5_ldap_free_principal
+krb5_ldap_iterate
+krb5_ldap_read_krbcontainer_params
+krb5_ldap_list_realm
+krb5_ldap_read_realm_params
+krb5_ldap_free_realm_params
+krb5_ldap_modify_realm
+krb5_ldap_create_krbcontainer
+krb5_ldap_create_realm
+krb5_ldap_delete_realm
+krb5_ldap_list_policy
+krb5_ldap_free_policy
+krb5_ldap_read_policy
+krb5_ldap_modify_policy
+krb5_ldap_delete_policy
+krb5_ldap_create_policy
+krb5_ldap_create_password_policy
+krb5_ldap_put_password_policy
+krb5_ldap_get_password_policy
+krb5_ldap_delete_password_policy
+krb5_ldap_free_password_policy
+krb5_ldap_iterate_password_policy
+krb5_dbe_free_contents
+krb5_ldap_free_server_params
+krb5_ldap_free_krbcontainer_params
+krb5_ldap_alloc
+krb5_ldap_free
+krb5_ldap_set_mkey
+krb5_ldap_get_mkey
+disjoint_members
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.c b/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.c
new file mode 100644
index 000000000..e089c8f7d
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.c
@@ -0,0 +1,231 @@
+#include "kdb_ldap.h"
+#include "ldap_principal.h"
+#include "princ_xdr.h"
+
+bool_t
+ldap_xdr_krb5_ui_2(XDR *xdrs, krb5_ui_2 *objp)
+{
+ unsigned int tmp;
+
+ tmp = (unsigned int) *objp;
+
+ if (!xdr_u_int(xdrs, &tmp))
+ return(FALSE);
+
+ *objp = (krb5_ui_2) tmp;
+ return(TRUE);
+}
+
+bool_t
+ldap_xdr_krb5_int16(XDR *xdrs, krb5_int16 *objp)
+{
+ int tmp;
+
+ tmp = (int) *objp;
+
+ if (!xdr_int(xdrs, &tmp))
+ return(FALSE);
+
+ *objp = (krb5_int16) tmp;
+ return(TRUE);
+}
+
+bool_t
+ldap_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
+ldap_xdr_krb5_kvno(XDR *xdrs, krb5_kvno *objp)
+{
+ unsigned char tmp;
+
+ tmp = '\0'; /* for purify, else xdr_u_char performs a umr */
+
+ if (xdrs->x_op == XDR_ENCODE)
+ tmp = (unsigned char) *objp;
+
+ if (!xdr_u_char(xdrs, &tmp))
+ return (FALSE);
+
+ if (xdrs->x_op == XDR_DECODE)
+ *objp = (krb5_kvno) tmp;
+ return (TRUE);
+}
+
+bool_t
+ldap_xdr_krb5_key_data(XDR *xdrs, krb5_key_data *objp)
+{
+ unsigned int tmp;
+
+ if (!ldap_xdr_krb5_int16(xdrs, &objp->key_data_ver))
+ return(FALSE);
+ if (!ldap_xdr_krb5_int16(xdrs, &objp->key_data_kvno))
+ return(FALSE);
+ if (!ldap_xdr_krb5_int16(xdrs, &objp->key_data_type[0]))
+ return(FALSE);
+ if (!ldap_xdr_krb5_int16(xdrs, &objp->key_data_type[1]))
+ return(FALSE);
+ if (!ldap_xdr_krb5_ui_2(xdrs, &objp->key_data_length[0]))
+ return(FALSE);
+ if (!ldap_xdr_krb5_ui_2(xdrs, &objp->key_data_length[1]))
+ return(FALSE);
+
+ tmp = (unsigned int) objp->key_data_length[0];
+ if (!xdr_bytes(xdrs, (char **) &objp->key_data_contents[0],
+ &tmp, (unsigned int) ~0))
+ return FALSE;
+
+ tmp = (unsigned int) objp->key_data_length[1];
+ if (!xdr_bytes(xdrs, (char **) &objp->key_data_contents[1],
+ &tmp, (unsigned int) ~0))
+ return FALSE;
+
+ /* don't need to copy tmp out, since key_data_length will be set
+ by the above encoding. */
+ return(TRUE);
+}
+
+bool_t
+ldap_xdr_osa_pw_hist_ent(XDR *xdrs, osa_pw_hist_ent *objp)
+{
+ if (!xdr_array(xdrs, (caddr_t *) &objp->key_data,
+ (u_int *) &objp->n_key_data, (unsigned int) ~0,
+ sizeof(krb5_key_data),
+ ldap_xdr_krb5_key_data))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+ldap_xdr_osa_princ_ent_rec(XDR *xdrs, osa_princ_ent_t objp)
+{
+ switch (xdrs->x_op) {
+ case XDR_ENCODE:
+ objp->version = OSA_ADB_PRINC_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_PRINC_VERSION_1)
+ return FALSE;
+ break;
+ }
+
+ if (!ldap_xdr_nullstring(xdrs, &objp->policy))
+ return (FALSE);
+ if (!xdr_long(xdrs, &objp->aux_attributes))
+ return (FALSE);
+ if (!xdr_u_int(xdrs, &objp->old_key_next))
+ return (FALSE);
+ if (!ldap_xdr_krb5_kvno(xdrs, &objp->admin_history_kvno))
+ return (FALSE);
+ if (!xdr_array(xdrs, (caddr_t *) &objp->old_keys,
+ (unsigned int *) &objp->old_key_len, (unsigned int) ~0,
+ sizeof(osa_pw_hist_ent),
+ ldap_xdr_osa_pw_hist_ent))
+ return (FALSE);
+ return (TRUE);
+}
+
+void
+ldap_osa_free_princ_ent(osa_princ_ent_t val)
+{
+ XDR xdrs;
+
+ xdrmem_create(&xdrs, NULL, 0, XDR_FREE);
+
+ ldap_xdr_osa_princ_ent_rec(&xdrs, val);
+ free(val);
+}
+
+krb5_error_code
+krb5_lookup_tl_kadm_data(krb5_tl_data *tl_data, osa_princ_ent_rec *princ_entry)
+{
+
+ XDR xdrs;
+
+ xdrmem_create(&xdrs, tl_data->tl_data_contents,
+ tl_data->tl_data_length, XDR_DECODE);
+ if (! ldap_xdr_osa_princ_ent_rec(&xdrs, princ_entry)) {
+ xdr_destroy(&xdrs);
+ return(KADM5_XDR_FAILURE);
+ }
+ xdr_destroy(&xdrs);
+
+ return 0;
+
+}
+
+krb5_error_code
+krb5_update_tl_kadm_data(policy_dn, new_tl_data)
+ char * policy_dn;
+ krb5_tl_data * new_tl_data;
+{
+ XDR xdrs;
+ osa_princ_ent_t princ_entry;
+
+ if((princ_entry = (osa_princ_ent_t) malloc(sizeof(osa_princ_ent_rec))) == NULL)
+ return ENOMEM;
+
+ memset(princ_entry, 0, sizeof(osa_princ_ent_rec));
+ princ_entry->admin_history_kvno = 2;
+ princ_entry->aux_attributes = KDB_POLICY;
+ princ_entry->policy = policy_dn;
+
+ xdralloc_create(&xdrs, XDR_ENCODE);
+ if(! ldap_xdr_osa_princ_ent_rec(&xdrs, princ_entry)) {
+ xdr_destroy(&xdrs);
+ return(KADM5_XDR_FAILURE);
+ }
+ new_tl_data->tl_data_type = KRB5_TL_KADM_DATA;
+ new_tl_data->tl_data_length = xdr_getpos(&xdrs);
+ new_tl_data->tl_data_contents = (krb5_octet *)xdralloc_getdata(&xdrs);
+
+ /*
+ xdr_destroy(&xdrs);
+ ldap_osa_free_princ_ent(princ_entry);
+ */
+ return(0);
+}
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.h b/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.h
new file mode 100644
index 000000000..65a03f7dd
--- /dev/null
+++ b/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.h
@@ -0,0 +1,61 @@
+#ifndef _PRINC_XDR_H
+#define _PRINC_XDR_H 1
+
+#include <sys/types.h>
+#include <krb5.h>
+#include <kdb.h>
+#include <gssrpc/rpc.h>
+
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+
+#define OSA_ADB_PRINC_VERSION_1 0x12345C01
+#define KADM5_XDR_FAILURE (43787575L)
+
+typedef struct _osa_pw_hist_t {
+ int n_key_data;
+ krb5_key_data *key_data;
+} osa_pw_hist_ent, *osa_pw_hist_t;
+
+typedef struct _osa_princ_ent_t {
+ int version;
+ char *policy;
+ long aux_attributes;
+ unsigned int old_key_len;
+ unsigned int old_key_next;
+ krb5_kvno admin_history_kvno;
+ osa_pw_hist_ent *old_keys;
+} osa_princ_ent_rec, *osa_princ_ent_t;
+
+bool_t
+ldap_xdr_krb5_ui_2(XDR *xdrs, krb5_ui_2 *objp);
+
+bool_t
+ldap_xdr_krb5_int16(XDR *xdrs, krb5_int16 *objp);
+
+bool_t
+ldap_xdr_nullstring(XDR *xdrs, char **objp);
+
+bool_t
+ldap_xdr_krb5_kvno(XDR *xdrs, krb5_kvno *objp);
+
+bool_t
+ldap_xdr_krb5_key_data(XDR *xdrs, krb5_key_data *objp);
+
+bool_t
+ldap_xdr_osa_pw_hist_ent(XDR *xdrs, osa_pw_hist_ent *objp);
+
+bool_t
+ldap_xdr_osa_princ_ent_rec(XDR *xdrs, osa_princ_ent_t objp);
+
+void
+ldap_osa_free_princ_ent(osa_princ_ent_t val);
+
+krb5_error_code
+krb5_lookup_tl_kadm_data(krb5_tl_data *tl_data, osa_princ_ent_rec *princ_entry);
+
+krb5_error_code
+krb5_update_tl_kadm_data(char *, krb5_tl_data *);
+
+#endif