1 /*
2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * kadmin/ldap_util/kdb5_ldap_util.c
8  *
9  * (C) Copyright 1990,1991, 1996 by the Massachusetts Institute of Technology.
10  * All Rights Reserved.
11  *
12  * Export of this software from the United States of America may
13  *   require a specific license from the United States Government.
14  *   It is the responsibility of any person or organization contemplating
15  *   export to obtain such a license before exporting.
16  *
17  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
18  * distribute this software and its documentation for any purpose and
19  * without fee is hereby granted, provided that the above copyright
20  * notice appear in all copies and that both that copyright notice and
21  * this permission notice appear in supporting documentation, and that
22  * the name of M.I.T. not be used in advertising or publicity pertaining
23  * to distribution of the software without specific, written prior
24  * permission.  Furthermore if you modify this software you must label
25  * your software as modified software and not distribute it in such a
26  * fashion that it might be confused with the original M.I.T. software.
27  * M.I.T. makes no representations about the suitability of
28  * this software for any purpose.  It is provided "as is" without express
29  * or implied warranty.
30  *
31  *
32  * Edit a KDC database.
33  */
34 
35 /*
36  * Copyright (C) 1998 by the FundsXpress, INC.
37  *
38  * All rights reserved.
39  *
40  * Export of this software from the United States of America may require
41  * a specific license from the United States Government.  It is the
42  * responsibility of any person or organization contemplating export to
43  * obtain such a license before exporting.
44  *
45  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
46  * distribute this software and its documentation for any purpose and
47  * without fee is hereby granted, provided that the above copyright
48  * notice appear in all copies and that both that copyright notice and
49  * this permission notice appear in supporting documentation, and that
50  * the name of FundsXpress. not be used in advertising or publicity pertaining
51  * to distribution of the software without specific, written prior
52  * permission.  FundsXpress makes no representations about the suitability of
53  * this software for any purpose.  It is provided "as is" without express
54  * or implied warranty.
55  *
56  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
57  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
58  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
59  */
60 
61 /* Copyright (c) 2004-2005, Novell, Inc.
62  * All rights reserved.
63  *
64  * Redistribution and use in source and binary forms, with or without
65  * modification, are permitted provided that the following conditions are met:
66  *
67  *   * Redistributions of source code must retain the above copyright notice,
68  *       this list of conditions and the following disclaimer.
69  *   * Redistributions in binary form must reproduce the above copyright
70  *       notice, this list of conditions and the following disclaimer in the
71  *       documentation and/or other materials provided with the distribution.
72  *   * The copyright holder's name is not used to endorse or promote products
73  *       derived from this software without specific prior written permission.
74  *
75  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
76  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
77  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
78  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
79  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
80  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
81  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
82  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
83  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
84  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
85  * POSSIBILITY OF SUCH DAMAGE.
86  */
87 
88 #include <stdio.h>
89 #include <time.h>
90 
91 #include <k5-int.h>
92 #include <kadm5/admin.h>
93 #include <adm_proto.h>
94 #include <libintl.h>
95 #include <locale.h>
96 #include "kdb5_ldap_util.h"
97 
98 typedef void (*cmd_func)(int, char **);
99 int cmd_index(char *name);
100 
101 char *mkey_password = 0;
102 int exit_status = 0;
103 krb5_context util_context;
104 kadm5_config_params global_params;
105 krb5_boolean db_inited = FALSE;
106 
107 char *progname;
108 krb5_boolean manual_mkey = FALSE;
109 
110 /*
111  * This function prints the usage of kdb5_ldap_util, which is
112  * the LDAP configuration utility.
113  */
usage()114 void usage()
115 {
116     fprintf(stderr, "%s: "
117 "kdb5_ldap_util [-D user_dn [-w passwd]] [-H ldapuri]\n"
118 "\tcmd [cmd_options]\n"
119 
120 /* Create realm */
121 "create          [-subtrees subtree_dn_list] [-sscope search_scope] [-containerref container_reference_dn]\n"
122 #ifdef HAVE_EDIRECTORY
123 "\t\t[-kdcdn kdc_service_list] [-admindn admin_service_list]\n"
124 "\t\t[-pwddn passwd_service_list]\n"
125 #endif
126 "\t\t[-m|-P password|-sf stashfilename] [-k mkeytype] [-s]\n"
127 "\t\t[-maxtktlife max_ticket_life] [-maxrenewlife max_renewable_ticket_life]\n"
128 "\t\t[ticket_flags] [-r realm]\n"
129 
130 /* modify realm */
131 "modify          [-subtrees subtree_dn_list] [-sscope search_scope] [-containerref container_reference_dn]\n"
132 #ifdef HAVE_EDIRECTORY
133 "\t\t[-kdcdn kdc_service_list |\n"
134 "\t\t[-clearkdcdn kdc_service_list] [-addkdcdn kdc_service_list]]\n"
135 "\t\t[-admindn admin_service_list | [-clearadmindn admin_service_list]\n"
136 "\t\t[-addadmindn admin_service_list]] [-pwddn passwd_service_list |\n"
137 "\t\t[-clearpwddn passwd_service_list] [-addpwddn passwd_service_list]]\n"
138 #endif
139 "\t\t[-maxtktlife max_ticket_life] [-maxrenewlife max_renewable_ticket_life]\n"
140 "\t\t[ticket_flags] [-r realm]\n"
141 /* View realm */
142 "view            [-r realm]\n"
143 
144 /* Destroy realm */
145 "destroy	        [-f] [-r realm]\n"
146 
147 /* List realms */
148 "list\n"
149 
150 #ifdef HAVE_EDIRECTORY
151 /* Create Service */
152 "create_service  {-kdc|-admin|-pwd} [-servicehost service_host_list]\n"
153 "\t\t[-realm realm_list] \n"
154 "\t\t[-randpw|-fileonly] [-f filename] service_dn\n"
155 
156 /* Modify service */
157 "modify_service  [-servicehost service_host_list |\n"
158 "\t\t[-clearservicehost service_host_list]\n"
159 "\t\t[-addservicehost service_host_list]]\n"
160 "\t\t[-realm realm_list | [-clearrealm realm_list]\n"
161 "\t\t[-addrealm realm_list]] service_dn\n"
162 
163 /* View Service */
164 "view_service    service_dn\n"
165 
166 /* Destroy Service */
167 "destroy_service [-force] [-f stashfilename] service_dn\n"
168 
169 /* List services */
170 "list_service    [-basedn base_dn]\n"
171 
172 /* Set Service password */
173 "setsrvpw        [-randpw|-fileonly] [-f filename] service_dn\n"
174 
175 #else
176 
177 /* Stash the service password */
178 "stashsrvpw      [-f filename] service_dn\n"
179 
180 #endif
181 
182 /* Create policy */
183 "create_policy   [-r realm] [-maxtktlife max_ticket_life]\n"
184 "\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy\n"
185 
186 /* Modify policy */
187 "modify_policy   [-r realm] [-maxtktlife max_ticket_life]\n"
188 "\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy\n"
189 
190 /* View policy */
191 "view_policy     [-r realm] policy\n"
192 
193 /* Destroy policy */
194 "destroy_policy  [-r realm] [-force] policy\n"
195 
196 /* List policies */
197 "list_policy     [-r realm]\n",
198     gettext("Usage"));
199 }
200 
db_usage(int type)201 void db_usage (int type) {
202     /*
203      * This should print usage of 'type' command. For now, we will print usage
204      * of all commands.
205      */
206     usage ();
207 }
208 
209 /* The help messages for all sub-commands should be in the
210  * same order as listed in this table.
211  */
212 static struct _cmd_table {
213     char *name;
214     cmd_func func;
215     int opendb;
216 } cmd_table[] = {
217     {"create", kdb5_ldap_create, 1},
218     {"modify", kdb5_ldap_modify, 1},
219     {"view", kdb5_ldap_view, 1},
220     {"destroy", kdb5_ldap_destroy, 1},
221     {"list", kdb5_ldap_list, 1},
222 #ifdef HAVE_EDIRECTORY
223     {"create_service", kdb5_ldap_create_service, 1},
224     {"modify_service", kdb5_ldap_modify_service, 1},
225     {"view_service", kdb5_ldap_view_service, 1},
226     {"destroy_service", kdb5_ldap_destroy_service, 1},
227     {"list_service",kdb5_ldap_list_services,1},
228     {"setsrvpw", kdb5_ldap_set_service_password, 0},
229 #else
230     {"stashsrvpw", kdb5_ldap_stash_service_password, 0},
231 #endif
232     {"create_policy", kdb5_ldap_create_policy, 1},
233     {"modify_policy", kdb5_ldap_modify_policy, 1},
234     {"view_policy", kdb5_ldap_view_policy, 1},
235     {"destroy_policy", kdb5_ldap_destroy_policy, 1},
236     {"list_policy", kdb5_ldap_list_policies, 1},
237     {NULL, NULL, 0},
238 };
239 
240 
241 /*
242  * The function cmd_lookup returns the structure matching the
243  * command name and returns NULL if nothing matches.
244  */
cmd_lookup(name)245 static struct _cmd_table *cmd_lookup(name)
246     char *name;
247 {
248     int i;
249 
250     for (i = 0; cmd_table[i].name != NULL; i++)
251 	if (strcmp(cmd_table[i].name, name) == 0)
252 	    return &cmd_table[i];
253 
254     return NULL;
255 }
256 
257 
258 /*
259  * The function cmd_index provides the offset of the command
260  * in the command table, which can be used to get the corresponding
261  * help from the help message table.
262  */
cmd_index(name)263 int cmd_index(name)
264     char *name;
265 {
266     int i;
267 
268     if (name == NULL)
269 	return -1;
270 
271     for (i = 0; cmd_table[i].name != NULL; i++)
272 	if (strcmp(cmd_table[i].name, name) == 0)
273 	    return i;
274 
275     return -1;
276 }
277 
extended_com_err_fn(const char * myprog,errcode_t code,const char * fmt,va_list args)278 static void extended_com_err_fn (const char *myprog, errcode_t code,
279 				 const char *fmt, va_list args)
280 {
281     const char *emsg;
282     /* Solaris Kerberos: code should be like that in kdb5_util.c */
283     if (code) {
284 	emsg = krb5_get_error_message (util_context, code);
285 	fprintf (stderr, "%s: %s ", myprog, emsg);
286 	krb5_free_error_message (util_context, emsg);
287     } else {
288 	fprintf (stderr, "%s: ", myprog);
289     }
290     vfprintf (stderr, fmt, args);
291     fprintf (stderr, "\n");
292 }
293 
main(argc,argv)294 int main(argc, argv)
295     int argc;
296     char *argv[];
297 {
298     struct _cmd_table *cmd = NULL;
299     char *koptarg = NULL, **cmd_argv = NULL;
300     int cmd_argc = 0;
301     krb5_error_code retval;
302     int usage_print = 0;
303     int gp_is_static = 1;
304     krb5_error_code db_retval = 1;
305     char *bind_dn = NULL;
306     char *passwd = NULL;
307     char *ldap_server = NULL;
308     unsigned int ldapmask = 0;
309     unsigned int passwd_len = 0;
310     char *prompt = NULL;
311     kdb5_dal_handle *dal_handle = NULL;
312     krb5_ldap_context *ldap_context=NULL;
313     char *value = NULL, *conf_section = NULL;
314     krb5_boolean realm_name_required = TRUE;
315     krb5_boolean print_help_message = FALSE;
316 
317     /*
318      * Solaris Kerberos:
319      * Ensure that "progname" is set before calling com_err.
320      */
321     progname = (strrchr(argv[0], '/') ? strrchr(argv[0], '/')+1 : argv[0]);
322 
323     retval = krb5_init_context(&util_context);
324     set_com_err_hook(extended_com_err_fn);
325     if (retval) {
326 	com_err (progname, retval, gettext("while initializing Kerberos code"));
327 	exit_status++;
328 	goto cleanup;
329     }
330 
331     cmd_argv = (char **) malloc(sizeof(char *)*argc);
332     if (cmd_argv == NULL) {
333 	com_err(progname, ENOMEM, gettext("while creating sub-command arguments"));
334 	exit_status++;
335 	goto cleanup;
336     }
337     memset(cmd_argv, 0, sizeof(char *)*argc);
338     cmd_argc = 1;
339 
340     memset(&global_params, 0, sizeof(kadm5_config_params));
341 
342     argv++; argc--;
343     while (*argv) {
344 	if (strcmp(*argv, "--help") == 0) {
345 	    print_help_message = TRUE;
346 	}
347 	if (strcmp(*argv, "-P") == 0 && ARG_VAL) {
348 	    mkey_password = koptarg;
349 	    manual_mkey = TRUE;
350 	} else if (strcmp(*argv, "-r") == 0 && ARG_VAL) {
351 	    global_params.realm = koptarg;
352 	    global_params.mask |= KADM5_CONFIG_REALM;
353 	    /* not sure this is really necessary */
354 	    if ((retval = krb5_set_default_realm(util_context,
355 						 global_params.realm))) {
356 		com_err(progname, retval, gettext("while setting default realm name"));
357 		exit_status++;
358 		goto cleanup;
359 	    }
360 	} else if (strcmp(*argv, "-k") == 0 && ARG_VAL) {
361 	    if (krb5_string_to_enctype(koptarg, &global_params.enctype)) {
362 		/* Solaris Kerberos */
363 		com_err(progname, 0, gettext("%s is an invalid enctype"), koptarg);
364 	    }
365 	    else
366 		global_params.mask |= KADM5_CONFIG_ENCTYPE;
367 	} else if (strcmp(*argv, "-M") == 0 && ARG_VAL) {
368 	    global_params.mkey_name = koptarg;
369 	    global_params.mask |= KADM5_CONFIG_MKEY_NAME;
370 	} else if (strcmp(*argv, "-sf") == 0 && ARG_VAL) {
371 	    global_params.stash_file = koptarg;
372 	    global_params.mask |= KADM5_CONFIG_STASH_FILE;
373 	} else if (strcmp(*argv, "-m") == 0) {
374 	    manual_mkey = TRUE;
375 	    global_params.mkey_from_kbd = 1;
376 	    global_params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
377 	} else if (strcmp(*argv, "-D") == 0 && ARG_VAL) {
378 	    bind_dn = koptarg;
379 	    if (bind_dn == NULL) {
380 		com_err(progname, ENOMEM, gettext("while reading ldap parameters"));
381 		exit_status++;
382 		goto cleanup;
383 	    }
384 	    ldapmask |= CMD_LDAP_D;
385 	} else if (strcmp(*argv, "-w") == 0 && ARG_VAL) {
386 	    passwd = strdup(koptarg);
387 	    if (passwd == NULL) {
388 		com_err(progname, ENOMEM, gettext("while reading ldap parameters"));
389 		exit_status++;
390 		goto cleanup;
391 	    }
392 	    ldapmask |= CMD_LDAP_W;
393 	} else if (strcmp(*argv, "-H") == 0 && ARG_VAL) {
394 	    ldap_server = koptarg;
395 	    if (ldap_server == NULL) {
396 		com_err(progname, ENOMEM, gettext("while reading ldap parameters"));
397 		exit_status++;
398 		goto cleanup;
399 	    }
400 	    ldapmask |= CMD_LDAP_H;
401 	} else if (cmd_lookup(*argv) != NULL) {
402 	    if (cmd_argv[0] == NULL)
403 		cmd_argv[0] = *argv;
404 	    else {
405 		free(cmd_argv);
406 		cmd_argv = NULL;
407 		usage();
408 		goto cleanup;
409 	    }
410 	} else {
411 	    cmd_argv[cmd_argc++] = *argv;
412 	}
413 	argv++; argc--;
414     }
415 
416     if (cmd_argv[0] == NULL) {
417 	free(cmd_argv);
418 	cmd_argv = NULL;
419 	usage();
420 	goto cleanup;
421     }
422 
423     /* if we need to print the help message (because of --help option)
424      * we will print the help corresponding to the sub-command.
425      */
426     if (print_help_message) {
427 	char *cmd_name = cmd_argv[0];
428 	free(cmd_argv);
429 	cmd_argv = NULL;
430 	usage();
431 	goto cleanup;
432     }
433 
434     /* We need to check for the presence of default realm name only in
435      * the case of realm related operations like create, destroy etc.
436      */
437     if ((strcmp(cmd_argv[0], "list") == 0) ||
438         (strcmp(cmd_argv[0], "stashsrvpw") == 0)) {
439         realm_name_required = FALSE;
440     }
441 
442     if (!util_context->default_realm) {
443 	char *temp = NULL;
444 	retval = krb5_get_default_realm(util_context, &temp);
445 	if (retval) {
446 	    if (realm_name_required) {
447 		com_err (progname, retval, gettext("while getting default realm"));
448 		exit_status++;
449 		goto cleanup;
450 	    }
451 	} else
452 	    util_context->default_realm = temp;
453     }
454     /* If we have the realm name, we can safely say that
455      * realm_name is required so that we don't neglect any information.
456      */
457     else
458 	realm_name_required = TRUE;
459 
460     retval = profile_get_string(util_context->profile, KDB_REALM_SECTION,
461 				util_context->default_realm, KDB_MODULE_POINTER,
462 				NULL,
463 				&value);
464 
465     if (!(value)) {
466 	retval = profile_get_string(util_context->profile, KDB_MODULE_DEF_SECTION,
467 				    KDB_MODULE_POINTER, NULL,
468 				    NULL,
469 				    &value);
470 	if (!(value)) {
471 	    if (util_context->default_realm)
472 		conf_section = strdup(util_context->default_realm);
473 	} else {
474 	    conf_section = strdup(value);
475 	    free(value);
476 	}
477     } else {
478 	conf_section = strdup(value);
479 	free(value);
480     }
481 
482     if (realm_name_required) {
483 	retval = kadm5_get_config_params(util_context, 1,
484 					 &global_params, &global_params);
485 	if (retval) {
486 	    /* Solaris Kerberos */
487 	    com_err(progname, retval, gettext("while retreiving configuration parameters"));
488 	    exit_status++;
489 	    goto cleanup;
490 	}
491 	gp_is_static = 0;
492     }
493 
494     if ((retval = krb5_ldap_lib_init()) != 0) {
495 	/* Solaris Kerberos */
496 	com_err(progname, retval, gettext("while initializing error handling"));
497 	exit_status++;
498 	goto cleanup;
499     }
500 
501     /* Initialize the ldap context */
502     ldap_context = calloc(sizeof(krb5_ldap_context), 1);
503     if (ldap_context == NULL) {
504 	/* Solaris Kerberos */
505 	com_err(progname, ENOMEM, gettext("while initializing ldap handle"));
506 	exit_status++;
507 	goto cleanup;
508     }
509 
510     ldap_context->kcontext = util_context;
511 
512     /* If LDAP parameters are specified, replace them with the values from config */
513     if (ldapmask & CMD_LDAP_D) {
514 	/* If password is not specified, prompt for it */
515 	if (passwd == NULL) {
516 	    passwd = (char *)malloc(MAX_PASSWD_LEN);
517 	    if (passwd == NULL) {
518 		/* Solaris Kerberos */
519 		com_err(progname, ENOMEM, gettext("while retrieving ldap configuration"));
520 		exit_status++;
521 		goto cleanup;
522 	    }
523 	    prompt = (char *)malloc(MAX_PASSWD_PROMPT_LEN);
524 	    if (prompt == NULL) {
525 		free(passwd);
526 		passwd = NULL;
527 		/* Solaris Kerberos */
528 		com_err(progname, ENOMEM, gettext("while retrieving ldap configuration"));
529 		exit_status++;
530 		goto cleanup;
531 	    }
532 	    memset(passwd, 0, sizeof(passwd));
533 	    passwd_len = MAX_PASSWD_LEN - 1;
534 	    snprintf(prompt, MAX_PASSWD_PROMPT_LEN, gettext("Password for \"%s\""), bind_dn);
535 
536 	    db_retval = krb5_read_password(util_context, prompt, NULL, passwd, &passwd_len);
537 
538 	    if ((db_retval) || (passwd_len == 0)) {
539 		/* Solaris Kerberos */
540 		com_err(progname, db_retval, gettext("while retrieving ldap configuration"));
541 		free(passwd);
542 		passwd = NULL;
543 		exit_status++;
544 		goto cleanup;
545 	    }
546 	}
547 
548 	ldap_context->bind_pwd = passwd;
549     }
550 
551     /* If ldaphost is specified, release entry filled by configuration & use this */
552     if (ldapmask & CMD_LDAP_H) {
553 
554 	ldap_context->server_info_list = (krb5_ldap_server_info **) calloc (2, sizeof (krb5_ldap_server_info *)) ;
555 	if (ldap_context->server_info_list == NULL) {
556 	    /* Solaris Kerberos */
557 	    com_err(progname, ENOMEM, gettext("while initializing server list"));
558 	    exit_status++;
559 	    goto cleanup;
560 	}
561 
562 	ldap_context->server_info_list[0] = (krb5_ldap_server_info *) calloc (1, sizeof (krb5_ldap_server_info));
563 	if (ldap_context->server_info_list[0] == NULL) {
564 	    /* Solaris Kerberos */
565 	    com_err(progname, ENOMEM, gettext("while initializing server list"));
566 	    exit_status++;
567 	    goto cleanup;
568 	}
569 
570 	ldap_context->server_info_list[0]->server_status = NOTSET;
571 
572 	ldap_context->server_info_list[0]->server_name = strdup(ldap_server);
573 	if (ldap_context->server_info_list[0]->server_name == NULL) {
574 	    /* Solaris Kerberos */
575 	    com_err(progname, ENOMEM, gettext("while initializing server list"));
576 	    exit_status++;
577 	    goto cleanup;
578 	}
579     }
580     if (bind_dn) {
581 	ldap_context->bind_dn = strdup(bind_dn);
582 	if (ldap_context->bind_dn == NULL) {
583 	    /* Solaris Kerberos */
584 	    com_err(progname, ENOMEM, gettext("while retrieving ldap configuration"));
585 	    exit_status++;
586 	    goto cleanup;
587 	}
588     } else
589 	ldap_context->bind_dn = NULL;
590 
591     ldap_context->service_type = SERVICE_DN_TYPE_CLIENT;
592 
593     if (realm_name_required) {
594 	if ((global_params.enctype != ENCTYPE_UNKNOWN) &&
595 	    (!krb5_c_valid_enctype(global_params.enctype))) {
596 	    /* Solaris Kerberos */
597 	    com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP,
598 		    gettext("while setting up enctype %d"), global_params.enctype);
599 	}
600     }
601 
602     cmd = cmd_lookup(cmd_argv[0]);
603 
604     /* Setup DAL handle to access the database */
605     dal_handle = calloc((size_t)1, sizeof(kdb5_dal_handle));
606     if (dal_handle == NULL) {
607 	goto cleanup;
608     }
609     dal_handle->db_context = ldap_context;
610     util_context->db_context = (void *) dal_handle;
611 
612     db_retval = krb5_ldap_read_server_params(util_context, conf_section, KRB5_KDB_SRV_TYPE_OTHER);
613     if (db_retval) {
614 	/* Solaris Kerberos */
615 	com_err(progname, db_retval, gettext("while reading ldap configuration"));
616 	exit_status++;
617 	goto cleanup;
618     }
619 
620     if (cmd->opendb) {
621 	db_retval = krb5_ldap_db_init(util_context, ldap_context);
622 	if (db_retval) {
623 	    com_err(progname, db_retval, gettext("while initializing database"));
624 	    exit_status++;
625 	    goto cleanup;
626 	}
627 	db_inited = TRUE;
628     }
629     (*cmd->func)(cmd_argc, cmd_argv);
630 
631     goto cleanup;
632 
633 cleanup:
634     if (passwd)
635 	memset(passwd, 0, sizeof(passwd));
636     if (ldap_context && ldap_context->bind_pwd)
637 	memset(ldap_context->bind_pwd, 0, sizeof(ldap_context->bind_pwd));
638 
639     if (util_context) {
640 	if (gp_is_static == 0)
641 	    kadm5_free_config_params(util_context, &global_params);
642 	krb5_ldap_close(util_context);
643 	krb5_free_context(util_context);
644     }
645 
646     if (cmd_argv)
647 	free(cmd_argv);
648     if (prompt)
649 	free(prompt);
650     if (conf_section)
651 	free(conf_section);
652     if (dal_handle)
653 	free(dal_handle);
654 
655     if (usage_print) {
656 	usage();
657     }
658 
659     return exit_status;
660 }
661