2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
7 * kadmin/ldap_util/kdb5_ldap_util.c
9 * (C) Copyright 1990,1991, 1996 by the Massachusetts Institute of Technology.
10 * All Rights Reserved.
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.
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.
32 * Edit a KDC database.
36 * Copyright (C) 1998 by the FundsXpress, INC.
38 * All rights reserved.
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.
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.
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.
61 /* Copyright (c) 2004-2005, Novell, Inc.
62 * All rights reserved.
64 * Redistribution and use in source and binary forms, with or without
65 * modification, are permitted provided that the following conditions are met:
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.
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.
92 #include <kadm5/admin.h>
93 #include <adm_proto.h>
96 #include "kdb5_ldap_util.h"
98 typedef void (*cmd_func
)(int, char **);
99 int cmd_index(char *name
);
101 char *mkey_password
= 0;
103 krb5_context util_context
;
104 kadm5_config_params global_params
;
105 krb5_boolean db_inited
= FALSE
;
108 krb5_boolean manual_mkey
= FALSE
;
111 * This function prints the usage of kdb5_ldap_util, which is
112 * the LDAP configuration utility.
116 fprintf(stderr
, "%s: "
117 "kdb5_ldap_util [-D user_dn [-w passwd]] [-H ldapuri]\n"
118 "\tcmd [cmd_options]\n"
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"
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"
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"
139 "\t\t[-maxtktlife max_ticket_life] [-maxrenewlife max_renewable_ticket_life]\n"
140 "\t\t[ticket_flags] [-r realm]\n"
145 "destroy [-f] [-r realm]\n"
150 #ifdef HAVE_EDIRECTORY
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"
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"
164 "view_service service_dn\n"
166 /* Destroy Service */
167 "destroy_service [-force] [-f stashfilename] service_dn\n"
170 "list_service [-basedn base_dn]\n"
172 /* Set Service password */
173 "setsrvpw [-randpw|-fileonly] [-f filename] service_dn\n"
177 /* Stash the service password */
178 "stashsrvpw [-f filename] service_dn\n"
183 "create_policy [-r realm] [-maxtktlife max_ticket_life]\n"
184 "\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy\n"
187 "modify_policy [-r realm] [-maxtktlife max_ticket_life]\n"
188 "\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy\n"
191 "view_policy [-r realm] policy\n"
194 "destroy_policy [-r realm] [-force] policy\n"
197 "list_policy [-r realm]\n",
201 void db_usage (int type
) {
203 * This should print usage of 'type' command. For now, we will print usage
209 /* The help messages for all sub-commands should be in the
210 * same order as listed in this table.
212 static struct _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},
230 {"stashsrvpw", kdb5_ldap_stash_service_password
, 0},
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},
242 * The function cmd_lookup returns the structure matching the
243 * command name and returns NULL if nothing matches.
245 static struct _cmd_table
*cmd_lookup(name
)
250 for (i
= 0; cmd_table
[i
].name
!= NULL
; i
++)
251 if (strcmp(cmd_table
[i
].name
, name
) == 0)
252 return &cmd_table
[i
];
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.
271 for (i
= 0; cmd_table
[i
].name
!= NULL
; i
++)
272 if (strcmp(cmd_table
[i
].name
, name
) == 0)
278 static void extended_com_err_fn (const char *myprog
, errcode_t code
,
279 const char *fmt
, va_list args
)
282 /* Solaris Kerberos: code should be like that in kdb5_util.c */
284 emsg
= krb5_get_error_message (util_context
, code
);
285 fprintf (stderr
, "%s: %s ", myprog
, emsg
);
286 krb5_free_error_message (util_context
, emsg
);
288 fprintf (stderr
, "%s: ", myprog
);
290 vfprintf (stderr
, fmt
, args
);
291 fprintf (stderr
, "\n");
298 struct _cmd_table
*cmd
= NULL
;
299 char *koptarg
= NULL
, **cmd_argv
= NULL
;
301 krb5_error_code retval
;
303 int gp_is_static
= 1;
304 krb5_error_code db_retval
= 1;
305 char *bind_dn
= NULL
;
307 char *ldap_server
= NULL
;
308 unsigned int ldapmask
= 0;
309 unsigned int passwd_len
= 0;
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
;
319 * Ensure that "progname" is set before calling com_err.
321 progname
= (strrchr(argv
[0], '/') ? strrchr(argv
[0], '/')+1 : argv
[0]);
323 retval
= krb5_init_context(&util_context
);
324 set_com_err_hook(extended_com_err_fn
);
326 com_err (progname
, retval
, gettext("while initializing Kerberos code"));
331 cmd_argv
= (char **) malloc(sizeof(char *)*argc
);
332 if (cmd_argv
== NULL
) {
333 com_err(progname
, ENOMEM
, gettext("while creating sub-command arguments"));
337 memset(cmd_argv
, 0, sizeof(char *)*argc
);
340 memset(&global_params
, 0, sizeof(kadm5_config_params
));
344 if (strcmp(*argv
, "--help") == 0) {
345 print_help_message
= TRUE
;
347 if (strcmp(*argv
, "-P") == 0 && ARG_VAL
) {
348 mkey_password
= koptarg
;
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"));
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
);
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) {
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
) {
379 if (bind_dn
== NULL
) {
380 com_err(progname
, ENOMEM
, gettext("while reading ldap parameters"));
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"));
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"));
400 ldapmask
|= CMD_LDAP_H
;
401 } else if (cmd_lookup(*argv
) != NULL
) {
402 if (cmd_argv
[0] == NULL
)
411 cmd_argv
[cmd_argc
++] = *argv
;
416 if (cmd_argv
[0] == NULL
) {
423 /* if we need to print the help message (because of --help option)
424 * we will print the help corresponding to the sub-command.
426 if (print_help_message
) {
427 char *cmd_name
= cmd_argv
[0];
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.
437 if ((strcmp(cmd_argv
[0], "list") == 0) ||
438 (strcmp(cmd_argv
[0], "stashsrvpw") == 0)) {
439 realm_name_required
= FALSE
;
442 if (!util_context
->default_realm
) {
444 retval
= krb5_get_default_realm(util_context
, &temp
);
446 if (realm_name_required
) {
447 com_err (progname
, retval
, gettext("while getting default realm"));
452 util_context
->default_realm
= temp
;
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.
458 realm_name_required
= TRUE
;
460 retval
= profile_get_string(util_context
->profile
, KDB_REALM_SECTION
,
461 util_context
->default_realm
, KDB_MODULE_POINTER
,
466 retval
= profile_get_string(util_context
->profile
, KDB_MODULE_DEF_SECTION
,
467 KDB_MODULE_POINTER
, NULL
,
471 if (util_context
->default_realm
)
472 conf_section
= strdup(util_context
->default_realm
);
474 conf_section
= strdup(value
);
478 conf_section
= strdup(value
);
482 if (realm_name_required
) {
483 retval
= kadm5_get_config_params(util_context
, 1,
484 &global_params
, &global_params
);
486 /* Solaris Kerberos */
487 com_err(progname
, retval
, gettext("while retreiving configuration parameters"));
494 if ((retval
= krb5_ldap_lib_init()) != 0) {
495 /* Solaris Kerberos */
496 com_err(progname
, retval
, gettext("while initializing error handling"));
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"));
510 ldap_context
->kcontext
= util_context
;
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"));
523 prompt
= (char *)malloc(MAX_PASSWD_PROMPT_LEN
);
524 if (prompt
== NULL
) {
527 /* Solaris Kerberos */
528 com_err(progname
, ENOMEM
, gettext("while retrieving ldap configuration"));
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
);
536 db_retval
= krb5_read_password(util_context
, prompt
, NULL
, passwd
, &passwd_len
);
538 if ((db_retval
) || (passwd_len
== 0)) {
539 /* Solaris Kerberos */
540 com_err(progname
, db_retval
, gettext("while retrieving ldap configuration"));
548 ldap_context
->bind_pwd
= passwd
;
551 /* If ldaphost is specified, release entry filled by configuration & use this */
552 if (ldapmask
& CMD_LDAP_H
) {
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"));
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"));
570 ldap_context
->server_info_list
[0]->server_status
= NOTSET
;
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"));
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"));
589 ldap_context
->bind_dn
= NULL
;
591 ldap_context
->service_type
= SERVICE_DN_TYPE_CLIENT
;
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
);
602 cmd
= cmd_lookup(cmd_argv
[0]);
604 /* Setup DAL handle to access the database */
605 dal_handle
= calloc((size_t)1, sizeof(kdb5_dal_handle
));
606 if (dal_handle
== NULL
) {
609 dal_handle
->db_context
= ldap_context
;
610 util_context
->db_context
= (void *) dal_handle
;
612 db_retval
= krb5_ldap_read_server_params(util_context
, conf_section
, KRB5_KDB_SRV_TYPE_OTHER
);
614 /* Solaris Kerberos */
615 com_err(progname
, db_retval
, gettext("while reading ldap configuration"));
621 db_retval
= krb5_ldap_db_init(util_context
, ldap_context
);
623 com_err(progname
, db_retval
, gettext("while initializing database"));
629 (*cmd
->func
)(cmd_argc
, cmd_argv
);
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
));
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
);