#include <stdio.h>
#include <time.h>
#include <k5-int.h>
#include <kadm5/admin.h>
#include <adm_proto.h>
#include "kdb5_ldap_util.h"
typedef void (*cmd_func)(int, char **);
int cmd_index(char *name);
char *mkey_password = 0;
int exit_status = 0;
krb5_context util_context;
kadm5_config_params global_params;
krb5_boolean db_inited = FALSE;
char *progname;
krb5_boolean manual_mkey = FALSE;
void usage()
{
fprintf(stderr, "Usage: "
"kdb5_ldap_util [-D user_dn [-w passwd]] [-H ldapuri]\n"
"\tcmd [cmd_options]\n"
"create [-subtrees subtree_dn_list] [-sscope search_scope] [-containerref container_reference_dn]\n"
#ifdef HAVE_EDIRECTORY
"\t\t[-kdcdn kdc_service_list] [-admindn admin_service_list]\n"
"\t\t[-pwddn passwd_service_list]\n"
#endif
"\t\t[-m|-P password|-sf stashfilename] [-k mkeytype] [-s]\n"
"\t\t[-maxtktlife max_ticket_life] [-maxrenewlife max_renewable_ticket_life]\n"
"\t\t[ticket_flags] [-r realm]\n"
"modify [-subtrees subtree_dn_list] [-sscope search_scope] [-containerref container_reference_dn]\n"
#ifdef HAVE_EDIRECTORY
"\t\t[-kdcdn kdc_service_list |\n"
"\t\t[-clearkdcdn kdc_service_list] [-addkdcdn kdc_service_list]]\n"
"\t\t[-admindn admin_service_list | [-clearadmindn admin_service_list]\n"
"\t\t[-addadmindn admin_service_list]] [-pwddn passwd_service_list |\n"
"\t\t[-clearpwddn passwd_service_list] [-addpwddn passwd_service_list]]\n"
#endif
"\t\t[-maxtktlife max_ticket_life] [-maxrenewlife max_renewable_ticket_life]\n"
"\t\t[ticket_flags] [-r realm]\n"
"view [-r realm]\n"
"destroy [-f] [-r realm]\n"
"list\n"
#ifdef HAVE_EDIRECTORY
"create_service {-kdc|-admin|-pwd} [-servicehost service_host_list]\n"
"\t\t[-realm realm_list] \n"
"\t\t[-randpw|-fileonly] [-f filename] service_dn\n"
"modify_service [-servicehost service_host_list |\n"
"\t\t[-clearservicehost service_host_list]\n"
"\t\t[-addservicehost service_host_list]]\n"
"\t\t[-realm realm_list | [-clearrealm realm_list]\n"
"\t\t[-addrealm realm_list]] service_dn\n"
"view_service service_dn\n"
"destroy_service [-force] [-f stashfilename] service_dn\n"
"list_service [-basedn base_dn]\n"
"setsrvpw [-randpw|-fileonly] [-f filename] service_dn\n"
#else
"stashsrvpw [-f filename] service_dn\n"
#endif
"create_policy [-r realm] [-maxtktlife max_ticket_life]\n"
"\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy\n"
"modify_policy [-r realm] [-maxtktlife max_ticket_life]\n"
"\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy\n"
"view_policy [-r realm] policy\n"
"destroy_policy [-r realm] [-force] policy\n"
"list_policy [-r realm]\n"
);
}
void db_usage (int type) {
usage ();
}
static struct _cmd_table {
char *name;
cmd_func func;
int opendb;
} cmd_table[] = {
{"create", kdb5_ldap_create, 1},
{"modify", kdb5_ldap_modify, 1},
{"view", kdb5_ldap_view, 1},
{"destroy", kdb5_ldap_destroy, 1},
{"list", kdb5_ldap_list, 1},
#ifdef HAVE_EDIRECTORY
{"create_service", kdb5_ldap_create_service, 1},
{"modify_service", kdb5_ldap_modify_service, 1},
{"view_service", kdb5_ldap_view_service, 1},
{"destroy_service", kdb5_ldap_destroy_service, 1},
{"list_service",kdb5_ldap_list_services,1},
{"setsrvpw", kdb5_ldap_set_service_password, 0},
#else
{"stashsrvpw", kdb5_ldap_stash_service_password, 0},
#endif
{"create_policy", kdb5_ldap_create_policy, 1},
{"modify_policy", kdb5_ldap_modify_policy, 1},
{"view_policy", kdb5_ldap_view_policy, 1},
{"destroy_policy", kdb5_ldap_destroy_policy, 1},
{"list_policy", kdb5_ldap_list_policies, 1},
{NULL, NULL, 0},
};
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;
}
int cmd_index(name)
char *name;
{
int i;
if (name == NULL)
return -1;
for (i = 0; cmd_table[i].name != NULL; i++)
if (strcmp(cmd_table[i].name, name) == 0)
return i;
return -1;
}
static void extended_com_err_fn (const char *myprog, errcode_t code,
const char *fmt, va_list args)
{
const char *emsg;
emsg = krb5_get_error_message (util_context, code);
fprintf (stderr, "%s: %s ", myprog, emsg);
krb5_free_error_message (util_context, emsg);
vfprintf (stderr, fmt, args);
fprintf (stderr, "\n");
}
int main(argc, argv)
int argc;
char *argv[];
{
struct _cmd_table *cmd = NULL;
char *koptarg = NULL, **cmd_argv = NULL;
int cmd_argc = 0;
krb5_error_code retval;
int usage_print = 0;
int gp_is_static = 1;
krb5_error_code db_retval = 1;
char *bind_dn = NULL;
char *passwd = NULL;
char *ldap_server = NULL;
unsigned int ldapmask = 0;
unsigned int passwd_len = 0;
char *prompt = NULL;
kdb5_dal_handle *dal_handle = NULL;
krb5_ldap_context *ldap_context=NULL;
char *value = NULL, *conf_section = NULL;
krb5_boolean realm_name_required = TRUE;
krb5_boolean print_help_message = FALSE;
retval = krb5_init_context(&util_context);
set_com_err_hook(extended_com_err_fn);
if (retval) {
com_err (progname, retval, "while initializing Kerberos code");
exit_status++;
goto cleanup;
}
progname = (strrchr(argv[0], '/') ? strrchr(argv[0], '/')+1 : argv[0]);
cmd_argv = (char **) malloc(sizeof(char *)*argc);
if (cmd_argv == NULL) {
com_err(progname, ENOMEM, "while creating sub-command arguments");
exit_status++;
goto cleanup;
}
memset(cmd_argv, 0, sizeof(char *)*argc);
cmd_argc = 1;
memset(&global_params, 0, sizeof(kadm5_config_params));
argv++; argc--;
while (*argv) {
if (strcmp(*argv, "--help") == 0) {
print_help_message = TRUE;
}
if (strcmp(*argv, "-P") == 0 && ARG_VAL) {
mkey_password = koptarg;
manual_mkey = TRUE;
} else if (strcmp(*argv, "-r") == 0 && ARG_VAL) {
global_params.realm = koptarg;
global_params.mask |= KADM5_CONFIG_REALM;
if ((retval = krb5_set_default_realm(util_context,
global_params.realm))) {
com_err(progname, retval, "while setting default realm name");
exit_status++;
goto cleanup;
}
} else if (strcmp(*argv, "-k") == 0 && ARG_VAL) {
if (krb5_string_to_enctype(koptarg, &global_params.enctype))
com_err(argv[0], 0, "%s is an invalid enctype", koptarg);
else
global_params.mask |= KADM5_CONFIG_ENCTYPE;
} else if (strcmp(*argv, "-M") == 0 && ARG_VAL) {
global_params.mkey_name = koptarg;
global_params.mask |= KADM5_CONFIG_MKEY_NAME;
} else if (strcmp(*argv, "-sf") == 0 && ARG_VAL) {
global_params.stash_file = koptarg;
global_params.mask |= KADM5_CONFIG_STASH_FILE;
} else if (strcmp(*argv, "-m") == 0) {
manual_mkey = TRUE;
global_params.mkey_from_kbd = 1;
global_params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
} else if (strcmp(*argv, "-D") == 0 && ARG_VAL) {
bind_dn = koptarg;
if (bind_dn == NULL) {
com_err(progname, ENOMEM, "while reading ldap parameters");
exit_status++;
goto cleanup;
}
ldapmask |= CMD_LDAP_D;
} else if (strcmp(*argv, "-w") == 0 && ARG_VAL) {
passwd = strdup(koptarg);
if (passwd == NULL) {
com_err(progname, ENOMEM, "while reading ldap parameters");
exit_status++;
goto cleanup;
}
ldapmask |= CMD_LDAP_W;
} else if (strcmp(*argv, "-H") == 0 && ARG_VAL) {
ldap_server = koptarg;
if (ldap_server == NULL) {
com_err(progname, ENOMEM, "while reading ldap parameters");
exit_status++;
goto cleanup;
}
ldapmask |= CMD_LDAP_H;
} else if (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 (print_help_message) {
char *cmd_name = cmd_argv[0];
free(cmd_argv);
cmd_argv = NULL;
usage();
goto cleanup;
}
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;
}
} else
util_context->default_realm = temp;
}
else
realm_name_required = TRUE;
retval = profile_get_string(util_context->profile, KDB_REALM_SECTION,
util_context->default_realm, KDB_MODULE_POINTER,
NULL,
&value);
if (!(value)) {
retval = profile_get_string(util_context->profile, KDB_MODULE_DEF_SECTION,
KDB_MODULE_POINTER, NULL,
NULL,
&value);
if (!(value)) {
if (util_context->default_realm)
conf_section = strdup(util_context->default_realm);
} else {
conf_section = strdup(value);
free(value);
}
} else {
conf_section = strdup(value);
free(value);
}
if (realm_name_required) {
retval = kadm5_get_config_params(util_context, 1,
&global_params, &global_params);
if (retval) {
com_err(argv[0], retval, "while retreiving configuration parameters");
exit_status++;
goto cleanup;
}
gp_is_static = 0;
}
if ((retval = krb5_ldap_lib_init()) != 0) {
com_err(argv[0], retval, "while initializing error handling");
exit_status++;
goto cleanup;
}
ldap_context = calloc(sizeof(krb5_ldap_context), 1);
if (ldap_context == NULL) {
com_err(argv[0], ENOMEM, "while initializing ldap handle");
exit_status++;
goto cleanup;
}
ldap_context->kcontext = util_context;
if (ldapmask & CMD_LDAP_D) {
if (passwd == NULL) {
passwd = (char *)malloc(MAX_PASSWD_LEN);
if (passwd == NULL) {
com_err(argv[0], ENOMEM, "while retrieving ldap configuration");
exit_status++;
goto cleanup;
}
prompt = (char *)malloc(MAX_PASSWD_PROMPT_LEN);
if (prompt == NULL) {
free(passwd);
passwd = NULL;
com_err(argv[0], ENOMEM, "while retrieving ldap configuration");
exit_status++;
goto cleanup;
}
memset(passwd, 0, sizeof(passwd));
passwd_len = MAX_PASSWD_LEN - 1;
snprintf(prompt, MAX_PASSWD_PROMPT_LEN, "Password for \"%s\"", bind_dn);
db_retval = krb5_read_password(util_context, prompt, NULL, passwd, &passwd_len);
if ((db_retval) || (passwd_len == 0)) {
com_err(argv[0], ENOMEM, "while retrieving ldap configuration");
free(passwd);
passwd = NULL;
exit_status++;
goto cleanup;
}
}
ldap_context->bind_pwd = passwd;
}
if (ldapmask & CMD_LDAP_H) {
ldap_context->server_info_list = (krb5_ldap_server_info **) calloc (2, sizeof (krb5_ldap_server_info *)) ;
if (ldap_context->server_info_list == NULL) {
com_err(argv[0], ENOMEM, "while initializing server list");
exit_status++;
goto cleanup;
}
ldap_context->server_info_list[0] = (krb5_ldap_server_info *) calloc (1, sizeof (krb5_ldap_server_info));
if (ldap_context->server_info_list[0] == NULL) {
com_err(argv[0], ENOMEM, "while initializing server list");
exit_status++;
goto cleanup;
}
ldap_context->server_info_list[0]->server_status = NOTSET;
ldap_context->server_info_list[0]->server_name = strdup(ldap_server);
if (ldap_context->server_info_list[0]->server_name == NULL) {
com_err(argv[0], ENOMEM, "while initializing server list");
exit_status++;
goto cleanup;
}
}
if (bind_dn) {
ldap_context->bind_dn = strdup(bind_dn);
if (ldap_context->bind_dn == NULL) {
com_err(argv[0], ENOMEM, "while retrieving ldap configuration");
exit_status++;
goto cleanup;
}
} else
ldap_context->bind_dn = NULL;
ldap_context->service_type = SERVICE_DN_TYPE_CLIENT;
if (realm_name_required) {
if ((global_params.enctype != ENCTYPE_UNKNOWN) &&
(!krb5_c_valid_enctype(global_params.enctype))) {
com_err(argv[0], KRB5_PROG_KEYTYPE_NOSUPP,
"while setting up enctype %d", global_params.enctype);
}
}
cmd = cmd_lookup(cmd_argv[0]);
dal_handle = calloc((size_t)1, sizeof(kdb5_dal_handle));
if (dal_handle == NULL) {
goto cleanup;
}
dal_handle->db_context = ldap_context;
util_context->db_context = (void *) dal_handle;
db_retval = krb5_ldap_read_server_params(util_context, conf_section, KRB5_KDB_SRV_TYPE_OTHER);
if (db_retval) {
com_err(argv[0], db_retval, "while reading ldap configuration");
exit_status++;
goto cleanup;
}
if (cmd->opendb) {
db_retval = krb5_ldap_db_init(util_context, ldap_context);
if (db_retval) {
com_err(progname, db_retval, "while initializing database");
exit_status++;
goto cleanup;
}
db_inited = TRUE;
}
(*cmd->func)(cmd_argc, cmd_argv);
goto cleanup;
cleanup:
if (passwd)
memset(passwd, 0, sizeof(passwd));
if (ldap_context && ldap_context->bind_pwd)
memset(ldap_context->bind_pwd, 0, sizeof(ldap_context->bind_pwd));
if (util_context) {
if (gp_is_static == 0)
kadm5_free_config_params(util_context, &global_params);
krb5_ldap_close(util_context);
krb5_free_context(util_context);
}
if (cmd_argv)
free(cmd_argv);
if (prompt)
free(prompt);
if (conf_section)
free(conf_section);
if (dal_handle)
free(dal_handle);
if (usage_print) {
usage();
}
return exit_status;
}