summaryrefslogtreecommitdiff
path: root/src/plugins/kdb/ldap/ldap_util
diff options
context:
space:
mode:
authorCy Schubert <cy@FreeBSD.org>2017-07-07 17:03:42 +0000
committerCy Schubert <cy@FreeBSD.org>2017-07-07 17:03:42 +0000
commit33a9b234e7087f573ef08cd7318c6497ba08b439 (patch)
treed0ea40ad3bf5463a3c55795977c71bcb7d781b4b /src/plugins/kdb/ldap/ldap_util
Diffstat (limited to 'src/plugins/kdb/ldap/ldap_util')
-rw-r--r--src/plugins/kdb/ldap/ldap_util/Makefile.in29
-rw-r--r--src/plugins/kdb/ldap/ldap_util/deps103
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.c275
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.h44
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c866
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.h35
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c1526
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.h59
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c335
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.h37
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c604
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.h69
12 files changed, 3982 insertions, 0 deletions
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 000000000000..8669c2436c14
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/Makefile.in
@@ -0,0 +1,29 @@
+mydir=plugins$(S)kdb$(S)ldap$(S)ldap_util
+BUILDTOP=$(REL)..$(S)..$(S)..$(S)..
+DEFINES = -DKDB4_DISABLE
+LOCALINCLUDES = -I. -I$(srcdir)/../libkdb_ldap -I$(top_srcdir)/lib/kdb
+#KDB_DEP_LIB=$(DL_LIB) $(THREAD_LINKOPTS)
+KDB_DEP_LIB=$(DL_LIB) -lkdb_ldap $(THREAD_LINKOPTS)
+
+PROG = kdb5_ldap_util
+SRCS = kdb5_ldap_util.c kdb5_ldap_list.c kdb5_ldap_realm.c kdb5_ldap_policy.c kdb5_ldap_services.c getdate.c
+OBJS = kdb5_ldap_util.o kdb5_ldap_list.o kdb5_ldap_realm.o kdb5_ldap_policy.o kdb5_ldap_services.o getdate.o
+
+GETDATE = $(srcdir)/../../../../kadmin/cli/getdate.y
+
+all: $(PROG)
+
+$(PROG): $(OBJS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIB) $(GETDATE)
+ $(CC_LINK) -o $(PROG) $(OBJS) \
+ $(KADMSRV_LIBS) $(KDB_DEP_LIB) $(KRB5_BASE_LIBS)
+
+getdate.c: $(GETDATE)
+ $(RM) getdate.c y.tab.c
+ $(YACC) $(GETDATE)
+ $(MV) y.tab.c getdate.c
+
+install:
+ $(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(ADMIN_BINDIR)/$(PROG)
+
+clean:
+ $(RM) $(PROG) $(OBJS) getdate.c
diff --git a/src/plugins/kdb/ldap/ldap_util/deps b/src/plugins/kdb/ldap/ldap_util/deps
new file mode 100644
index 000000000000..75d4dd0cf2dd
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/deps
@@ -0,0 +1,103 @@
+#
+# Generated makefile dependencies follow.
+#
+$(OUTPRE)kdb5_ldap_util.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+ $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+ $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../libkdb_ldap/kdb_ldap.h \
+ $(srcdir)/../libkdb_ldap/ldap_krbcontainer.h $(srcdir)/../libkdb_ldap/ldap_misc.h \
+ $(srcdir)/../libkdb_ldap/ldap_realm.h $(top_srcdir)/include/adm_proto.h \
+ $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \
+ $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \
+ $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \
+ $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \
+ $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h $(top_srcdir)/lib/kdb/kdb5.h \
+ kdb5_ldap_policy.h kdb5_ldap_realm.h kdb5_ldap_services.h \
+ kdb5_ldap_util.c kdb5_ldap_util.h
+$(OUTPRE)kdb5_ldap_list.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h kdb5_ldap_list.c \
+ kdb5_ldap_list.h
+$(OUTPRE)kdb5_ldap_realm.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+ $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+ $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../libkdb_ldap/kdb_ldap.h \
+ $(srcdir)/../libkdb_ldap/ldap_krbcontainer.h $(srcdir)/../libkdb_ldap/ldap_misc.h \
+ $(srcdir)/../libkdb_ldap/ldap_principal.h $(srcdir)/../libkdb_ldap/ldap_realm.h \
+ $(srcdir)/../libkdb_ldap/ldap_tkt_policy.h $(srcdir)/../libkdb_ldap/princ_xdr.h \
+ $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/gssrpc/auth.h \
+ $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \
+ $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \
+ $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \
+ $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \
+ $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ $(top_srcdir)/lib/kdb/kdb5.h kdb5_ldap_list.h kdb5_ldap_policy.h \
+ kdb5_ldap_realm.c kdb5_ldap_realm.h kdb5_ldap_services.h \
+ kdb5_ldap_util.h
+$(OUTPRE)kdb5_ldap_policy.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \
+ $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \
+ $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(srcdir)/../libkdb_ldap/kdb_ldap.h \
+ $(srcdir)/../libkdb_ldap/ldap_krbcontainer.h $(srcdir)/../libkdb_ldap/ldap_misc.h \
+ $(srcdir)/../libkdb_ldap/ldap_realm.h $(srcdir)/../libkdb_ldap/ldap_tkt_policy.h \
+ $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \
+ $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \
+ $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \
+ $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \
+ $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h $(top_srcdir)/lib/kdb/kdb5.h \
+ kdb5_ldap_list.h kdb5_ldap_policy.c kdb5_ldap_policy.h \
+ kdb5_ldap_realm.h kdb5_ldap_services.h kdb5_ldap_util.h
+$(OUTPRE)kdb5_ldap_services.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../libkdb_ldap/kdb_ldap.h \
+ $(srcdir)/../libkdb_ldap/ldap_krbcontainer.h $(srcdir)/../libkdb_ldap/ldap_misc.h \
+ $(srcdir)/../libkdb_ldap/ldap_realm.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ $(top_srcdir)/lib/kdb/kdb5.h kdb5_ldap_list.h kdb5_ldap_policy.h \
+ kdb5_ldap_realm.h kdb5_ldap_services.c kdb5_ldap_services.h \
+ kdb5_ldap_util.h
+$(OUTPRE)getdate.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \
+ getdate.c
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 000000000000..940281378bd1
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.c
@@ -0,0 +1,275 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* plugins/kdb/ldap/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(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(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(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(char ***destlist, const char **sourcelist, int mode)
+{
+ char **dlist = NULL, **tmplist = NULL;
+ const char **slist = NULL;
+ int dcount = 0, scount = 0, copycount = 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++) {
+ /* DN is case insensitive string */
+ if (strcasecmp(*dlist, *slist) == 0) {
+ 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(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 000000000000..a729318b9cf1
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.h
@@ -0,0 +1,44 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* plugins/kdb/ldap/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 000000000000..02cb05991184
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c
@@ -0,0 +1,866 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* plugins/kdb/ldap/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 <k5-int.h>
+#include <kadm5/admin.h>
+#include "kdb5_ldap_util.h"
+#include "kdb5_ldap_list.h"
+#include "ldap_tkt_policy.h"
+extern time_t get_date(char *); /* kadmin/cli/getdate.o */
+
+static void print_policy_params(krb5_ldap_policy_params *policyparams, int mask);
+static char *strdur(time_t duration);
+
+extern char *yes;
+extern kadm5_config_params global_params;
+
+static krb5_error_code
+init_ldap_realm(int argc, char *argv[])
+{
+ /* This operation is being performed in the context of a realm. So,
+ * initialize the realm */
+ int mask = 0;
+ krb5_error_code retval = 0;
+ kdb5_dal_handle *dal_handle = NULL;
+ krb5_ldap_context *ldap_context=NULL;
+
+ dal_handle = util_context->dal_handle;
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+ if (!ldap_context) {
+ retval = EINVAL;
+ goto cleanup;
+ }
+
+ if (ldap_context->container_dn == NULL) {
+ retval = krb5_ldap_read_krbcontainer_dn(util_context,
+ &ldap_context->container_dn);
+ if (retval != 0) {
+ com_err(progname, retval,
+ _("while reading kerberos container information"));
+ goto cleanup;
+ }
+ }
+
+ if (ldap_context->lrparams == NULL) {
+ retval = krb5_ldap_read_realm_params(util_context,
+ global_params.realm,
+ &(ldap_context->lrparams),
+ &mask);
+
+ if (retval != 0) {
+ goto cleanup;
+ }
+ }
+cleanup:
+ return retval;
+}
+
+/*
+ * This function will create a ticket policy object with the
+ * specified attributes.
+ */
+void
+kdb5_ldap_create_policy(int argc, char *argv[])
+{
+ char *me = progname;
+ 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]);
+ 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]);
+ 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->policy != NULL)
+ goto err_usage;
+
+ /* If not present already, fill up policy DN */
+ policyparams->policy = strdup(argv[i]);
+ if (policyparams->policy == 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->policy == NULL)
+ goto err_usage;
+
+ if ((retval = init_ldap_realm (argc, argv))) {
+ com_err(me, retval, _("while reading realm information"));
+ goto err_nomsg;
+ }
+
+ /* 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(int argc, char *argv[])
+{
+ char *me = progname;
+ krb5_error_code retval = 0;
+ krb5_ldap_policy_params *policyparams = NULL;
+ krb5_boolean print_usage = FALSE;
+ krb5_boolean no_msg = FALSE;
+ char *policy = 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 (policy != NULL)
+ goto err_usage;
+
+ /* If not present already, fill up policy DN */
+ policy = strdup(argv[i]);
+ if (policy == NULL) {
+ retval = ENOMEM;
+ com_err(me, retval, _("while destroying policy object"));
+ goto err_nomsg;
+ }
+ }
+ }
+
+ if (policy == NULL)
+ goto err_usage;
+
+ if (!force) {
+ printf(_("This will delete the policy object '%s', are you sure?\n"),
+ policy);
+ 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 = init_ldap_realm (argc, argv)))
+ goto err_nomsg;
+
+ if ((retval = krb5_ldap_read_policy(util_context, policy, &policyparams, &mask)))
+ goto cleanup;
+
+
+ if ((retval = krb5_ldap_delete_policy(util_context, policy)))
+ goto cleanup;
+
+ printf("** policy object '%s' deleted.\n", policy);
+ goto cleanup;
+
+
+err_usage:
+ print_usage = TRUE;
+
+err_nomsg:
+ no_msg = TRUE;
+
+cleanup:
+ /* Clean-up structure */
+ krb5_ldap_free_policy (util_context, policyparams);
+
+ if (policy) {
+ free (policy);
+ }
+
+ 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(int argc, char *argv[])
+{
+ char *me = progname;
+ krb5_error_code retval = 0;
+ krb5_ldap_policy_params *policyparams = NULL;
+ krb5_boolean print_usage = FALSE;
+ krb5_boolean no_msg = FALSE;
+ char *policy = 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 (policy != NULL)
+ goto err_usage;
+
+ /* If not present already, fill up policy DN */
+ policy = strdup(argv[i]);
+ if (policy == NULL) {
+ retval = ENOMEM;
+ com_err(me, retval, _("while modifying policy object"));
+ goto err_nomsg;
+ }
+ }
+ }
+
+ if (policy == NULL)
+ goto err_usage;
+
+ if ((retval = init_ldap_realm (argc, argv)))
+ goto cleanup;
+
+ retval = krb5_ldap_read_policy(util_context, policy, &policyparams, &in_mask);
+ if (retval) {
+ com_err(me, retval, _("while reading information of policy '%s'"),
+ policy);
+ 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]);
+ 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]);
+ 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 (policy)
+ free (policy);
+
+ 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(int argc, char *argv[])
+{
+ char *me = progname;
+ krb5_ldap_policy_params *policyparams = NULL;
+ krb5_error_code retval = 0;
+ krb5_boolean print_usage = FALSE;
+ char *policy = NULL;
+ int mask = 0;
+
+ if (argc != 2) {
+ goto err_usage;
+ }
+
+ policy = strdup(argv[1]);
+ if (policy == NULL) {
+ com_err(me, ENOMEM, _("while viewing policy"));
+ exit_status++;
+ goto cleanup;
+ }
+
+ if ((retval = init_ldap_realm (argc, argv)))
+ goto cleanup;
+
+ if ((retval = krb5_ldap_read_policy(util_context, policy, &policyparams, &mask))) {
+ com_err(me, retval, _("while viewing policy '%s'"), policy);
+ 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 (policy)
+ free (policy);
+
+ 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(krb5_ldap_policy_params *policyparams, int mask)
+{
+ /* Print the policy DN */
+ printf("%25s: %s\n", "Ticket policy", policyparams->policy);
+
+ /* 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(int argc, char *argv[])
+{
+ char *me = progname;
+ krb5_error_code retval = 0;
+ krb5_boolean print_usage = FALSE;
+ char **list = NULL;
+ char **plist = NULL;
+
+ /* Check for number of arguments */
+ if ((argc != 1) && (argc != 3)) {
+ goto err_usage;
+ }
+
+ if ((retval = init_ldap_realm (argc, argv)))
+ goto cleanup;
+
+ retval = krb5_ldap_list_policy(util_context, NULL, &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 (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(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;
+ snprintf(out, sizeof(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 000000000000..0d3948dea5b4
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.h
@@ -0,0 +1,35 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* plugins/kdb/ldap/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 000000000000..5a745e21d9ec
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c
@@ -0,0 +1,1526 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c */
+/*
+ * Copyright 1990,1991,2001, 2002, 2008 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 <k5-int.h>
+#include <kadm5/admin.h>
+#include <adm_proto.h>
+#include "kdb5_ldap_util.h"
+#include "kdb5_ldap_list.h"
+#include <ldap_principal.h>
+#include <ldap_krbcontainer.h>
+extern time_t get_date(char *); /* kadmin/cli/getdate.o */
+
+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};
+
+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,
+ const krb5_keyblock *master_keyblock);
+
+
+static char *strdur(time_t duration);
+static int get_ticket_policy(krb5_ldap_realm_params *rparams, int *i, char *argv[],int argc);
+static krb5_error_code krb5_dbe_update_mod_princ_data_new (krb5_context context, krb5_db_entry *entry, krb5_timestamp mod_date, krb5_const_principal mod_princ);
+static krb5_error_code krb5_dbe_update_tl_data_new ( krb5_context context, krb5_db_entry *entry, krb5_tl_data *new_tl_data);
+
+#define ADMIN_LIFETIME 60*60*3 /* 3 hours */
+#define CHANGEPW_LIFETIME 60*5 /* 5 minutes */
+
+static int
+get_ticket_policy(krb5_ldap_realm_params *rparams, int *i, char *argv[],
+ int argc)
+{
+ time_t date;
+ time_t now;
+ int mask = 0;
+ krb5_error_code retval = 0;
+ krb5_boolean no_msg = FALSE;
+
+ krb5_boolean print_usage = FALSE;
+ char *me = progname;
+
+ time(&now);
+ if (!strcmp(argv[*i], "-maxtktlife")) {
+ if (++(*i) > argc-1)
+ goto err_usage;
+ date = get_date(argv[*i]);
+ 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]);
+ 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;
+}
+
+/* Create a special principal using two specified components. */
+static krb5_error_code
+create_fixed_special(krb5_context context, struct realm_info *rinfo,
+ krb5_keyblock *mkey, const char *comp1, const char *comp2)
+{
+ krb5_error_code ret;
+ krb5_principal princ;
+ const char *realm = global_params.realm;
+
+ ret = krb5_build_principal(context, &princ, strlen(realm), realm, comp1,
+ comp2, (const char *)NULL);
+ if (ret)
+ return ret;
+ ret = kdb_ldap_create_principal(context, princ, TGT_KEY, rinfo, mkey);
+ krb5_free_principal(context, princ);
+ return ret;
+
+}
+
+/* Create a special principal using one specified component and the
+ * canonicalized local hostname. */
+static krb5_error_code
+create_hostbased_special(krb5_context context, struct realm_info *rinfo,
+ krb5_keyblock *mkey, const char *comp1)
+{
+ krb5_error_code ret;
+ krb5_principal princ = NULL;
+
+ ret = krb5_sname_to_principal(context, NULL, comp1, KRB5_NT_SRV_HST,
+ &princ);
+ if (ret)
+ goto cleanup;
+ ret = krb5_set_principal_realm(context, princ, global_params.realm);
+ if (ret)
+ goto cleanup;
+ ret = kdb_ldap_create_principal(context, princ, TGT_KEY, rinfo, mkey);
+
+cleanup:
+ krb5_free_principal(context, princ);
+ return ret;
+}
+
+/* Create all special principals for the realm. */
+static krb5_error_code
+create_special_princs(krb5_context context, krb5_principal master_princ,
+ krb5_keyblock *mkey)
+{
+ krb5_error_code ret;
+ struct realm_info rblock;
+
+ 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.key = mkey;
+ rblock.nkslist = global_params.num_keysalts;
+ rblock.kslist = global_params.keysalts;
+
+ /* Create master principal. */
+ rblock.flags |= KRB5_KDB_DISALLOW_ALL_TIX;
+ ret = kdb_ldap_create_principal(context, master_princ, MASTER_KEY, &rblock,
+ mkey);
+ if (ret)
+ return ret;
+
+ /* Create local krbtgt principal. */
+ rblock.flags = 0;
+ ret = create_fixed_special(context, &rblock, mkey, KRB5_TGS_NAME,
+ global_params.realm);
+ if (ret)
+ return ret;
+
+ /* Create kadmin/admin and kadmin/<hostname>. */
+ rblock.max_life = ADMIN_LIFETIME;
+ rblock.flags = KRB5_KDB_DISALLOW_TGT_BASED;
+ ret = create_fixed_special(context, &rblock, mkey, "kadmin", "admin");
+ if (ret)
+ return ret;
+ ret = create_hostbased_special(context, &rblock, mkey, "kadmin");
+ if (ret)
+ return ret;
+
+ /* Create kiprop/<hostname>. */
+ rblock.max_life = global_params.max_life;
+ rblock.flags = 0;
+ ret = create_hostbased_special(context, &rblock, mkey, "kiprop");
+ if (ret)
+ return ret;
+
+ /* Create kadmin/changepw. */
+ rblock.max_life = CHANGEPW_LIFETIME;
+ rblock.flags = KRB5_KDB_DISALLOW_TGT_BASED | KRB5_KDB_PWCHANGE_SERVICE;
+ ret = create_fixed_special(context, &rblock, mkey, "kadmin", "changepw");
+ if (ret)
+ return ret;
+
+ /* Create kadmin/history. */
+ rblock.max_life = global_params.max_life;
+ rblock.flags = 0;
+ return create_fixed_special(context, &rblock, mkey, "kadmin", "history");
+}
+
+/*
+ * This function will create a realm on the LDAP Server, with
+ * the specified attributes.
+ */
+void
+kdb5_ldap_create(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 *oldcontainerref=NULL;
+ char pw_str[1024];
+ int do_stash = 0;
+ int i = 0;
+ int mask = 0, ret_mask = 0;
+ char **list = NULL;
+
+ 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], "-subtrees")) {
+ if (++i > argc-1)
+ goto err_usage;
+
+ if (strncmp(argv[i], "", strlen(argv[i]))!=0) {
+ 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))) {
+ free(list);
+ list = NULL;
+ goto cleanup;
+ }
+
+ rparams->subtreecount=0;
+ while (list[rparams->subtreecount]!=NULL)
+ (rparams->subtreecount)++;
+ rparams->subtree = list;
+ } else if (strncmp(argv[i], "", strlen(argv[i]))==0) {
+ /* dont allow subtree value to be set at the root(NULL, "") of the tree */
+ com_err(progname, EINVAL,
+ _("for subtree while creating realm '%s'"),
+ global_params.realm);
+ goto err_nomsg;
+ }
+ rparams->subtree[rparams->subtreecount] = NULL;
+ mask |= LDAP_REALM_SUBTREE;
+ } else if (!strcmp(argv[i], "-containerref")) {
+ if (++i > argc-1)
+ goto err_usage;
+ if (strncmp(argv[i], "", strlen(argv[i]))==0) {
+ /* dont allow containerref value to be set at the root(NULL, "") of the tree */
+ com_err(progname, EINVAL,
+ _("for container reference while creating realm '%s'"),
+ global_params.realm);
+ goto err_nomsg;
+ }
+ free(rparams->containerref);
+ rparams->containerref = strdup(argv[i]);
+ if (rparams->containerref == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ mask |= LDAP_REALM_CONTREF;
+ } 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(progname, EINVAL, _("invalid search scope while "
+ "creating realm '%s'"),
+ global_params.realm);
+ goto err_nomsg;
+ }
+ }
+ mask |= LDAP_REALM_SEARCHSCOPE;
+ }
+ 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;
+ }
+ }
+
+ 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(progname, retval,
+ _("while reading master key from keyboard"));
+ goto err_nomsg;
+ }
+ mkey_password = pw_str;
+ }
+
+ rparams->realm_name = strdup(global_params.realm);
+ if (rparams->realm_name == NULL) {
+ retval = ENOMEM;
+ com_err(progname, ENOMEM, _("while creating realm '%s'"),
+ global_params.realm);
+ goto err_nomsg;
+ }
+
+ dal_handle = util_context->dal_handle;
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+ if (!ldap_context) {
+ retval = EINVAL;
+ goto cleanup;
+ }
+
+ /* read the kerberos container */
+ retval = krb5_ldap_read_krbcontainer_dn(util_context,
+ &ldap_context->container_dn);
+ if (retval) {
+ /* Prompt the user for entering the DN of Kerberos container */
+ char krb_location[MAX_KRB_CONTAINER_LEN];
+ int krb_location_len = 0;
+
+ printf(_("Enter DN of Kerberos container: "));
+ 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--;
+ }
+ ldap_context->container_dn = strdup(krb_location);
+ if (ldap_context->container_dn == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ }
+
+ /* create the kerberos container if it doesn't exist */
+ retval = krb5_ldap_create_krbcontainer(util_context,
+ ldap_context->container_dn);
+ if (retval)
+ 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(progname, retval, _("while reading information of realm '%s'"),
+ global_params.realm);
+ goto err_nomsg;
+ }
+ free(ldap_context->lrparams->realm_name);
+ 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(progname, 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(progname, retval, _("while calculating master key salt"));
+ goto err_nomsg;
+ }
+
+ retval = krb5_c_string_to_key(util_context, global_params.enctype,
+ &pwd, &master_salt, &master_keyblock);
+
+ if (master_salt.data)
+ free(master_salt.data);
+
+ if (retval) {
+ com_err(progname, retval,
+ _("while transforming master key from password"));
+ goto err_nomsg;
+ }
+ }
+
+ /* Create special principals (not in the container reference). */
+ oldcontainerref = ldap_context->lrparams->containerref;
+ ldap_context->lrparams->containerref = NULL;
+ retval = create_special_princs(util_context, master_princ,
+ &master_keyblock);
+ ldap_context->lrparams->containerref = oldcontainerref;
+ if (retval) {
+ com_err(progname, retval, _("while adding entries to the database"));
+ goto err_nomsg;
+ }
+
+ /* 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) {
+ krb5_kvno mkey_kvno;
+ /*
+ * Determine the kvno to use, it must be that used to create the master
+ * key princ.
+ */
+ if (global_params.mask & KADM5_CONFIG_KVNO)
+ mkey_kvno = global_params.kvno; /* user specified */
+ else
+ mkey_kvno = 1; /* Default */
+
+ retval = krb5_db_store_master_key(util_context,
+ global_params.stash_file,
+ master_princ,
+ mkey_kvno,
+ &master_keyblock, NULL);
+ if (retval) {
+ com_err(progname, 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 (print_usage)
+ db_usage(CREATE_REALM);
+
+ if (retval) {
+ if (!no_msg) {
+ com_err(progname, retval, _("while creating realm '%s'"),
+ global_params.realm);
+ }
+ exit_status++;
+ }
+
+ krb5_free_keyblock_contents(util_context, &master_keyblock);
+ krb5_free_principal(util_context, master_princ);
+}
+
+
+/*
+ * This function will modify the attributes of a given realm object
+ */
+void
+kdb5_ldap_modify(int argc, char *argv[])
+{
+ krb5_error_code retval = 0;
+ 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;
+ int mask = 0, rmask = 0, ret_mask = 0;
+ char **slist = {NULL};
+
+ dal_handle = util_context->dal_handle;
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+ if (!(ldap_context)) {
+ retval = EINVAL;
+ goto cleanup;
+ }
+
+ retval = krb5_ldap_read_krbcontainer_dn(util_context,
+ &ldap_context->container_dn);
+ if (retval) {
+ com_err(progname, 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++) {
+ int k = 0;
+ if (!strcmp(argv[i], "-subtrees")) {
+ if (++i > argc-1)
+ goto err_usage;
+
+ if (rmask & LDAP_REALM_SUBTREE) {
+ if (rparams->subtree) {
+ for (k=0; k<rparams->subtreecount && rparams->subtree[k]; k++)
+ free(rparams->subtree[k]);
+ free(rparams->subtree);
+ rparams->subtreecount=0;
+ rparams->subtree = NULL;
+ }
+ }
+ if (strncmp(argv[i] ,"", strlen(argv[i]))!=0) {
+ slist = (char **) calloc(MAX_LIST_ENTRIES, sizeof(char *));
+ if (slist == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, slist))) {
+ free(slist);
+ slist = NULL;
+ goto cleanup;
+ }
+
+ rparams->subtreecount=0;
+ while (slist[rparams->subtreecount]!=NULL)
+ (rparams->subtreecount)++;
+ rparams->subtree = slist;
+ } else if (strncmp(argv[i], "", strlen(argv[i]))==0) {
+ /* dont allow subtree value to be set at the root(NULL, "") of the tree */
+ com_err(progname, EINVAL,
+ _("for subtree while modifying realm '%s'"),
+ global_params.realm);
+ goto err_nomsg;
+ }
+ rparams->subtree[rparams->subtreecount] = NULL;
+ mask |= LDAP_REALM_SUBTREE;
+ } else if (!strncmp(argv[i], "-containerref", strlen(argv[i]))) {
+ if (++i > argc-1)
+ goto err_usage;
+ if (strncmp(argv[i], "", strlen(argv[i]))==0) {
+ /* dont allow containerref value to be set at the root(NULL, "") of the tree */
+ com_err(progname, EINVAL, _("for container reference while "
+ "modifying realm '%s'"),
+ global_params.realm);
+ goto err_nomsg;
+ }
+ free(rparams->containerref);
+ rparams->containerref = strdup(argv[i]);
+ if (rparams->containerref == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ mask |= LDAP_REALM_CONTREF;
+ } 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(progname, retval,
+ _("specified for search scope while modifying "
+ "information of realm '%s'"),
+ global_params.realm);
+ goto err_nomsg;
+ }
+ }
+ mask |= LDAP_REALM_SEARCHSCOPE;
+ }
+ 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;
+ }
+
+ goto cleanup;
+
+err_usage:
+ print_usage = TRUE;
+
+err_nomsg:
+ no_msg = TRUE;
+
+cleanup:
+ krb5_ldap_free_realm_params(rparams);
+
+ if (print_usage) {
+ db_usage(MODIFY_REALM);
+ }
+
+ if (retval) {
+ if (!no_msg)
+ com_err(progname, 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(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 = util_context->dal_handle;
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+ if (!(ldap_context)) {
+ retval = EINVAL;
+ com_err(progname, retval, _("while initializing database"));
+ exit_status++;
+ return;
+ }
+
+ /* Read the kerberos container information */
+ retval = krb5_ldap_read_krbcontainer_dn(util_context,
+ &ldap_context->container_dn);
+ if (retval) {
+ com_err(progname, 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(progname, 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(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;
+ snprintf(out, sizeof(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 **slist = NULL;
+ unsigned int num_entry_printed = 0, i = 0;
+
+ /* Print the Realm Attributes on the standard output */
+ printf("%25s: %-50s\n", _("Realm Name"), global_params.realm);
+ if (mask & LDAP_REALM_SUBTREE) {
+ for (i=0; rparams->subtree[i]!=NULL; i++)
+ printf("%25s: %-50s\n", _("Subtree"), rparams->subtree[i]);
+ }
+ if (mask & LDAP_REALM_CONTREF)
+ printf("%25s: %-50s\n", _("Principal Container Reference"),
+ rparams->containerref);
+ 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_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));
+ }
+
+ if (mask & LDAP_REALM_KRBTICKETFLAGS) {
+ int ticketflags = rparams->tktflags;
+
+ printf("%25s: ", _("Ticket flags"));
+ 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 lists the Realm(s) present under the Kerberos container
+ * on the LDAP Server.
+ */
+void
+kdb5_ldap_list(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 = util_context->dal_handle;
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+ if (!(ldap_context)) {
+ retval = EINVAL;
+ exit_status++;
+ return;
+ }
+
+ /* Read the kerberos container information */
+ retval = krb5_ldap_read_krbcontainer_dn(util_context,
+ &ldap_context->container_dn);
+ if (retval) {
+ com_err(progname, retval,
+ _("while reading kerberos container information"));
+ exit_status++;
+ return;
+ }
+
+ retval = krb5_ldap_list_realm(util_context, &list);
+ if (retval != 0) {
+ com_err(progname, retval, _("while listing realms"));
+ exit_status++;
+ return;
+ }
+ /* This is to handle the case of realm not present */
+ if (list == NULL)
+ return;
+
+ for (plist = list; *plist != NULL; plist++) {
+ printf("%s\n", *plist);
+ }
+ krb5_free_list_entries(list);
+ free(list);
+
+ return;
+}
+
+/*
+ * Duplicating the following two functions here because
+ * 'krb5_dbe_update_tl_data' uses backend specific memory allocation. The catch
+ * here is that the backend is not initialized - kdb5_ldap_util doesn't go
+ * through DAL.
+ * 1. krb5_dbe_update_tl_data
+ * 2. krb5_dbe_update_mod_princ_data
+ */
+
+/* Start duplicate code ... */
+
+static krb5_error_code
+krb5_dbe_update_tl_data_new(krb5_context context, krb5_db_entry *entry,
+ krb5_tl_data *new_tl_data)
+{
+ krb5_tl_data *tl_data = NULL;
+ krb5_octet *tmp;
+
+ /* copy the new data first, so we can fail cleanly if malloc()
+ * fails */
+ if ((tmp = (krb5_octet *) 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 */
+
+ if (new_tl_data->tl_data_type != KRB5_TL_DB_ARGS) { /* db_args can be multiple */
+ for (tl_data = entry->tl_data; tl_data;
+ tl_data = tl_data->tl_data_next)
+ if (tl_data->tl_data_type == new_tl_data->tl_data_type)
+ break;
+ }
+
+ /* if necessary, chain a new record in the beginning and point at it */
+
+ if (!tl_data) {
+ if ((tl_data = (krb5_tl_data *) malloc (sizeof(krb5_tl_data))) == NULL) {
+ free(tmp);
+ return (ENOMEM);
+ }
+ memset(tl_data, 0, sizeof(krb5_tl_data));
+ tl_data->tl_data_next = entry->tl_data;
+ entry->tl_data = tl_data;
+ entry->n_tl_data++;
+ }
+
+ /* fill in the record */
+
+ 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);
+}
+
+static krb5_error_code
+krb5_dbe_update_mod_princ_data_new(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_new(context, entry, &tl_data);
+
+ free(unparse_mod_princ);
+ free(nextloc);
+
+ return(retval);
+}
+
+static krb5_error_code
+kdb_ldap_tgt_keysalt_iterate(krb5_key_salt_tuple *ksent, krb5_pointer ptr)
+{
+ krb5_context context;
+ krb5_error_code kret;
+ struct iterate_args *iargs;
+ krb5_keyblock key;
+ krb5_int32 ind;
+ krb5_data pwd;
+ krb5_db_entry *entry;
+
+ iargs = (struct iterate_args *) ptr;
+ kret = 0;
+
+ context = iargs->ctx;
+ entry = iargs->dbentp;
+
+ /*
+ * Convert the master key password into a key for this particular
+ * encryption system.
+ */
+ pwd.data = mkey_password;
+ pwd.length = strlen(mkey_password);
+ kret = krb5_c_random_seed(context, &pwd);
+ if (kret)
+ return kret;
+
+ /*if (!(kret = krb5_dbe_create_key_data(iargs->ctx, iargs->dbentp))) {*/
+ if ((entry->key_data =
+ (krb5_key_data *) realloc(entry->key_data,
+ (sizeof(krb5_key_data) *
+ (entry->n_key_data + 1)))) == NULL)
+ return (ENOMEM);
+
+ memset(entry->key_data + entry->n_key_data, 0, sizeof(krb5_key_data));
+ ind = entry->n_key_data++;
+
+ if (!(kret = krb5_c_make_random_key(context, ksent->ks_enctype,
+ &key))) {
+ kret = krb5_dbe_encrypt_key_data(context, iargs->rblock->key, &key,
+ NULL, 1, &entry->key_data[ind]);
+ krb5_free_keyblock_contents(context, &key);
+ }
+ /*}*/
+
+ return(kret);
+}
+/* End duplicate code */
+
+/*
+ * This function creates service principals when
+ * creating the realm object.
+ */
+static int
+kdb_ldap_create_principal(krb5_context context, krb5_principal princ,
+ enum ap_op op, struct realm_info *pblock,
+ const krb5_keyblock *master_keyblock)
+{
+ int retval=0, currlen=0, princtype = 2 /* Service Principal */;
+ unsigned char *curr=NULL;
+ krb5_tl_data *tl_data=NULL;
+ krb5_db_entry entry;
+ long mask = 0;
+ krb5_keyblock key;
+ int kvno = 0;
+ kdb5_dal_handle *dal_handle = NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ struct iterate_args iargs;
+ krb5_data *pdata;
+ krb5_timestamp now;
+ krb5_actkvno_node actkvno;
+
+ memset(&entry, 0, sizeof(entry));
+
+ if ((pblock == NULL) || (context == NULL)) {
+ retval = EINVAL;
+ goto cleanup;
+ }
+ dal_handle = context->dal_handle;
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+ if (!(ldap_context)) {
+ retval = EINVAL;
+ goto cleanup;
+ }
+
+ 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 |= KADM5_PRINCIPAL;
+ mask |= KADM5_ATTRIBUTES ;
+ mask |= KADM5_MAX_LIFE ;
+ mask |= KADM5_MAX_RLIFE ;
+ mask |= KADM5_PRINC_EXPIRE_TIME ;
+ mask |= KADM5_KEY_DATA;
+
+ entry.tl_data = tl_data;
+ entry.n_tl_data += 1;
+ /* Set the creator's name */
+ if ((retval = krb5_timeofday(context, &now)))
+ goto cleanup;
+ if ((retval = krb5_dbe_update_mod_princ_data_new(context, &entry,
+ now, &db_create_princ)))
+ goto cleanup;
+
+ 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;
+
+
+ switch (op) {
+ case TGT_KEY:
+ if ((pdata = krb5_princ_component(context, princ, 1)) &&
+ pdata->length == strlen("history") &&
+ !memcmp(pdata->data, "history", strlen("history"))) {
+
+ /* Allocate memory for storing the key */
+ if ((entry.key_data = (krb5_key_data *) malloc(
+ sizeof(krb5_key_data))) == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ memset(entry.key_data, 0, sizeof(krb5_key_data));
+ entry.n_key_data++;
+
+ retval = krb5_c_make_random_key(context, global_params.enctype, &key);
+ if (retval) {
+ goto cleanup;
+ }
+ kvno = 1; /* New key is getting set */
+ retval = krb5_dbe_encrypt_key_data(context, master_keyblock,
+ &key, NULL, kvno,
+ &entry.key_data[entry.n_key_data - 1]);
+ krb5_free_keyblock_contents(context, &key);
+ if (retval) {
+ goto cleanup;
+ }
+ } else {
+ /*retval = krb5_c_make_random_key(context, 16, &key) ;*/
+ iargs.ctx = context;
+ iargs.rblock = pblock;
+ iargs.dbentp = &entry;
+
+ /*
+ * Iterate through the key/salt list, ignoring salt types.
+ */
+ if ((retval = krb5_keysalt_iterate(pblock->kslist,
+ pblock->nkslist,
+ 1,
+ kdb_ldap_tgt_keysalt_iterate,
+ (krb5_pointer) &iargs)))
+ return retval;
+ }
+ break;
+
+ case MASTER_KEY:
+ /* Allocate memory for storing the key */
+ if ((entry.key_data = (krb5_key_data *) malloc(
+ sizeof(krb5_key_data))) == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ memset(entry.key_data, 0, sizeof(krb5_key_data));
+ entry.n_key_data++;
+ kvno = 1; /* New key is getting set */
+ retval = krb5_dbe_encrypt_key_data(context, pblock->key,
+ master_keyblock, NULL, kvno,
+ &entry.key_data[entry.n_key_data - 1]);
+ if (retval) {
+ goto cleanup;
+ }
+ /*
+ * There should always be at least one "active" mkey so creating the
+ * KRB5_TL_ACTKVNO entry now so the initial mkey is active.
+ */
+ actkvno.next = NULL;
+ actkvno.act_kvno = kvno;
+ actkvno.act_time = now;
+ retval = krb5_dbe_update_actkvno(context, &entry, &actkvno);
+ if (retval)
+ goto cleanup;
+
+ break;
+
+ case NULL_KEY:
+ default:
+ break;
+ } /* end of switch */
+
+ retval = krb5_ldap_put_principal(context, &entry, 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(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;
+
+ 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 = util_context->dal_handle;
+ ldap_context = (krb5_ldap_context *) dal_handle->db_context;
+ if (!(ldap_context)) {
+ com_err(progname, EINVAL, _("while initializing database"));
+ exit_status++;
+ return;
+ }
+
+ /* Read the kerberos container DN */
+ retval = krb5_ldap_read_krbcontainer_dn(util_context,
+ &ldap_context->container_dn);
+ if (retval) {
+ com_err(progname, 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(progname, retval, _("while reading realm information"));
+ exit_status++;
+ return;
+ }
+
+ /* Delete the realm container and all the associated principals */
+ retval = krb5_ldap_delete_realm(util_context, global_params.realm);
+ if (retval) {
+ com_err(progname, 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 000000000000..aa086fe62d6a
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.h
@@ -0,0 +1,59 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* plugins/kdb/ldap/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 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 000000000000..022156a5e03a
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c
@@ -0,0 +1,335 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* plugins/kdb/ldap/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 <k5-int.h>
+#include "kdb5_ldap_util.h"
+#include "kdb5_ldap_list.h"
+
+/* Get the configured LDAP service password file. The caller should free the
+ * result with profile_release_string(). */
+static krb5_error_code
+get_conf_service_file(profile_t profile, const char *realm, char **path_out)
+{
+ char *subsection, *path;
+ long ret;
+
+ *path_out = NULL;
+
+ /* Get the [dbmodules] subsection for realm. */
+ ret = profile_get_string(profile, KDB_REALM_SECTION, realm,
+ KDB_MODULE_POINTER, realm, &subsection);
+ if (ret)
+ return ret;
+
+ /* Look up the password file in the [dbmodules] subsection. */
+ ret = profile_get_string(profile, KDB_MODULE_SECTION, subsection,
+ KRB5_CONF_LDAP_SERVICE_PASSWORD_FILE, NULL,
+ &path);
+ profile_release_string(subsection);
+ if (ret)
+ return ret;
+
+ if (path == NULL) {
+ /* Look up the password file in [dbdefaults] as a fallback. */
+ ret = profile_get_string(profile, KDB_MODULE_DEF_SECTION,
+ KRB5_CONF_LDAP_SERVICE_PASSWORD_FILE, NULL,
+ NULL, &path);
+ if (ret)
+ return ret;
+ }
+
+ if (path == NULL) {
+ k5_setmsg(util_context, ENOENT,
+ _("ldap_service_password_file not configured"));
+ return ENOENT;
+ }
+
+ *path_out = path;
+ return 0;
+}
+
+/*
+ * Convert the user supplied password into hexadecimal and stash it. Only a
+ * little more secure than storing plain password in the file ...
+ */
+void
+kdb5_ldap_stash_service_password(int argc, char **argv)
+{
+ int ret = 0;
+ unsigned int passwd_len = 0;
+ char *me = progname;
+ 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};
+ mode_t old_mode = 0;
+
+ /*
+ * 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) {
+ if (((file_name = strdup (argv[2])) == NULL) ||
+ ((service_object = strdup (argv[3])) == NULL)) {
+ com_err(me, ENOMEM,
+ _("while setting service object password"));
+ goto cleanup;
+ }
+ } else if (strcmp (argv[2], "-f") == 0) {
+ if (((file_name = strdup (argv[3])) == NULL) ||
+ ((service_object = strdup (argv[1])) == NULL)) {
+ com_err(me, ENOMEM,
+ _("while setting service object password"));
+ goto cleanup;
+ }
+ } else {
+ print_usage = TRUE;
+ goto cleanup;
+ }
+ if (file_name == NULL) {
+ com_err(me, ENOMEM, _("while setting service object password"));
+ goto cleanup;
+ }
+ } else { /* argc == 2 */
+ service_object = strdup (argv[1]);
+ if (service_object == NULL) {
+ com_err(me, ENOMEM, _("while setting service object password"));
+ goto cleanup;
+ }
+
+ ret = get_conf_service_file(util_context->profile,
+ util_context->default_realm, &file_name);
+ if (ret) {
+ com_err(me, ret, _("while getting service password filename"));
+ goto cleanup;
+ }
+ }
+
+ /* 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);
+
+ snprintf(prompt1, sizeof(prompt1), _("Password for \"%s\""),
+ service_object);
+
+ snprintf(prompt2, sizeof(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) {
+ com_err(me, ret,
+ _("Failed to convert the password to hexadecimal"));
+ 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 */
+ old_mode = umask(0177);
+ pfile = fopen(file_name, "a+");
+ if (pfile == NULL) {
+ com_err(me, errno, _("Failed to open file %s: %s"), file_name,
+ strerror (errno));
+ goto cleanup;
+ }
+ set_cloexec_file(pfile);
+ rewind (pfile);
+ umask(old_mode);
+
+ 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 */
+ if (asprintf(&tmp_file,"%s.tmp",file_name) < 0) {
+ com_err(me, ENOMEM, _("while setting service object password"));
+ fclose(pfile);
+ goto cleanup;
+ }
+
+ 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;
+ }
+ set_cloexec_file(newfile);
+
+ 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 (hexpasswd.length != 0) {
+ memset(hexpasswd.data, 0, hexpasswd.length);
+ free(hexpasswd.data);
+ }
+
+ if (service_object)
+ free(service_object);
+
+ profile_release_string(file_name);
+
+ if (tmp_file)
+ free(tmp_file);
+
+ if (print_usage)
+ usage();
+/* db_usage(STASH_SRV_PW); */
+
+ if (ret)
+ exit_status++;
+}
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 000000000000..cf652c57837e
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.h
@@ -0,0 +1,37 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* plugins/kdb/ldap/ldap_util/kdb5_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.
+ */
+
+#include "ldap_misc.h"
+
+#define MAX_LEN 1024
+#define MAX_SERVICE_PASSWD_LEN 256
+
+extern int tohex(krb5_data, krb5_data *);
+
+extern void kdb5_ldap_stash_service_password(int argc, char **argv);
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 000000000000..818ff62b6b95
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c
@@ -0,0 +1,604 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c */
+/*
+ * (C) Copyright 1990,1991, 1996, 2008 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.
+ */
+
+#include <k5-int.h>
+#include <locale.h>
+#include <time.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(void)
+{
+ fprintf(stderr,
+ _("Usage: kdb5_ldap_util [-D user_dn [-w passwd]] [-H ldapuri]\n"
+ "\tcmd [cmd_options]\n"
+
+/* Create realm */
+ "create [-subtrees subtree_dn_list] [-sscope search_scope] [-containerref container_reference_dn]\n"
+ "\t\t[-m|-P password|-sf stashfilename] [-k mkeytype] [-kv mkeyVNO] [-s]\n"
+ "\t\t[-maxtktlife max_ticket_life] [-maxrenewlife max_renewable_ticket_life]\n"
+ "\t\t[ticket_flags] [-r realm]\n"
+
+/* modify realm */
+ "modify [-subtrees subtree_dn_list] [-sscope search_scope] [-containerref container_reference_dn]\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"
+
+/* Stash the service password */
+ "stashsrvpw [-f filename] service_dn\n"
+
+/* Create policy */
+ "create_policy [-r realm] [-maxtktlife max_ticket_life]\n"
+ "\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy\n"
+
+/* Modify policy */
+ "modify_policy [-r realm] [-maxtktlife max_ticket_life]\n"
+ "\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy\n"
+
+/* View policy */
+ "view_policy [-r realm] policy\n"
+
+/* Destroy policy */
+ "destroy_policy [-r realm] [-force] policy\n"
+
+/* List policies */
+ "list_policy [-r realm]\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},
+ {"stashsrvpw", kdb5_ldap_stash_service_password, 0},
+ {"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(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(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;
+ unsigned int ldapmask = 0;
+ unsigned int passwd_len = 0;
+ char *prompt = NULL;
+ krb5_ldap_context *ldap_context=NULL;
+ char *value = NULL, *conf_section = NULL;
+ krb5_boolean realm_name_required = TRUE;
+ krb5_boolean print_help_message = FALSE;
+
+ /*
+ * Ensure that "progname" is set before calling com_err.
+ */
+ setlocale(LC_ALL, "");
+ progname = (strrchr(argv[0], '/') ? strrchr(argv[0], '/')+1 : argv[0]);
+
+ retval = kadm5_init_krb5_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;
+ }
+
+ 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(progname, EINVAL,
+ _(": %s is an invalid enctype"), koptarg);
+ exit_status++;
+ goto cleanup;
+ } else
+ global_params.mask |= KADM5_CONFIG_ENCTYPE;
+ } else if (strcmp(*argv, "-kv") == 0 && ARG_VAL) {
+ global_params.kvno = (krb5_kvno) atoi(koptarg);
+ if (global_params.kvno == IGNORE_VNO) {
+ com_err(progname, EINVAL,
+ _(": %s is an invalid mkeyVNO"), koptarg);
+ exit_status++;
+ goto cleanup;
+ } else
+ global_params.mask |= KADM5_CONFIG_KVNO;
+ } 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 (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) {
+ 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], "list") == 0) ||
+ (strcmp(cmd_argv[0], "stashsrvpw") == 0)) {
+ realm_name_required = FALSE;
+ }
+
+ 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;
+ }
+ }
+ krb5_free_default_realm(util_context, 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(progname, retval,
+ _("while retreiving configuration parameters"));
+ exit_status++;
+ goto cleanup;
+ }
+ gp_is_static = 0;
+ }
+
+ if ((retval = krb5_ldap_lib_init()) != 0) {
+ com_err(progname, 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(progname, ENOMEM, _("while initializing ldap handle"));
+ exit_status++;
+ goto cleanup;
+ }
+
+ ldap_context->kcontext = util_context;
+
+ /* 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(progname, 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(progname, ENOMEM,
+ _("while retrieving ldap configuration"));
+ exit_status++;
+ goto cleanup;
+ }
+ memset(passwd, 0, MAX_PASSWD_LEN);
+ 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(progname, ENOMEM,
+ _("while retrieving ldap configuration"));
+ free(passwd);
+ passwd = NULL;
+ exit_status++;
+ goto cleanup;
+ }
+ }
+
+ ldap_context->bind_pwd = passwd;
+ passwd = NULL;
+ }
+
+ /* 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(progname, 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(progname, 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(progname, ENOMEM, _("while initializing server list"));
+ exit_status++;
+ goto cleanup;
+ }
+ }
+ if (bind_dn) {
+ ldap_context->bind_dn = strdup(bind_dn);
+ if (ldap_context->bind_dn == NULL) {
+ com_err(progname, 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(progname, 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 */
+ db_retval = krb5_db_setup_lib_handle(util_context);
+ if (db_retval) {
+ com_err(progname, db_retval, _("while setting up lib handle"));
+ exit_status++;
+ goto cleanup;
+ }
+ util_context->dal_handle->db_context = ldap_context;
+ ldap_context = NULL;
+
+ db_retval = krb5_ldap_read_server_params(util_context, conf_section, KRB5_KDB_SRV_TYPE_OTHER);
+ if (db_retval) {
+ com_err(progname, db_retval, _("while reading ldap configuration"));
+ exit_status++;
+ goto cleanup;
+ }
+
+ if (cmd->opendb) {
+ db_retval = krb5_ldap_db_init(util_context, (krb5_ldap_context *)util_context->dal_handle->db_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, strlen(passwd));
+ free(passwd);
+ }
+
+ if (ldap_context) {
+ krb5_ldap_free_server_context_params(ldap_context);
+ free(ldap_context);
+ }
+
+ if (util_context) {
+ if (gp_is_static == 0)
+ kadm5_free_config_params(util_context, &global_params);
+ krb5_db_fini(util_context);
+ krb5_free_context(util_context);
+ }
+
+ if (cmd_argv)
+ free(cmd_argv);
+ if (prompt)
+ free(prompt);
+ if (conf_section)
+ free(conf_section);
+
+ 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 000000000000..dd6263149421
--- /dev/null
+++ b/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.h
@@ -0,0 +1,69 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* plugins/kdb/ldap/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
+
+#define STASH_SRV_PW 17
+
+#define CREATE_POLICY 11
+#define MODIFY_POLICY 12
+#define VIEW_POLICY 13
+#define DESTROY_POLICY 14
+#define LIST_POLICY 15
+
+extern char *progname;
+
+extern int exit_status;
+extern krb5_context util_context;
+
+extern void usage(void);
+extern void db_usage(int);
+
+#define ARG_VAL (--argc > 0 ? (koptarg = *(++argv)) : (char *)(db_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 */