diff options
| author | Cy Schubert <cy@FreeBSD.org> | 2017-07-07 17:03:42 +0000 |
|---|---|---|
| committer | Cy Schubert <cy@FreeBSD.org> | 2017-07-07 17:03:42 +0000 |
| commit | 33a9b234e7087f573ef08cd7318c6497ba08b439 (patch) | |
| tree | d0ea40ad3bf5463a3c55795977c71bcb7d781b4b /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.in | 29 | ||||
| -rw-r--r-- | src/plugins/kdb/ldap/ldap_util/deps | 103 | ||||
| -rw-r--r-- | src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.c | 275 | ||||
| -rw-r--r-- | src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.h | 44 | ||||
| -rw-r--r-- | src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c | 866 | ||||
| -rw-r--r-- | src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.h | 35 | ||||
| -rw-r--r-- | src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c | 1526 | ||||
| -rw-r--r-- | src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.h | 59 | ||||
| -rw-r--r-- | src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c | 335 | ||||
| -rw-r--r-- | src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.h | 37 | ||||
| -rw-r--r-- | src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c | 604 | ||||
| -rw-r--r-- | src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.h | 69 |
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 */ |
