summaryrefslogtreecommitdiff
path: root/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c
diff options
context:
space:
mode:
authorCy Schubert <cy@FreeBSD.org>2017-07-07 17:03:42 +0000
committerCy Schubert <cy@FreeBSD.org>2017-07-07 17:03:42 +0000
commit33a9b234e7087f573ef08cd7318c6497ba08b439 (patch)
treed0ea40ad3bf5463a3c55795977c71bcb7d781b4b /src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c
Diffstat (limited to 'src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c')
-rw-r--r--src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c604
1 files changed, 604 insertions, 0 deletions
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;
+}