1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c */
3 /*
4 * Copyright 1990,1991,2001, 2002, 2008 by the Massachusetts Institute of Technology.
5 * All Rights Reserved.
6 *
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
11 *
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
25 */
26
27 /*
28 * Copyright (C) 1998 by the FundsXpress, INC.
29 *
30 * All rights reserved.
31 *
32 * Export of this software from the United States of America may require
33 * a specific license from the United States Government. It is the
34 * responsibility of any person or organization contemplating export to
35 * obtain such a license before exporting.
36 *
37 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
38 * distribute this software and its documentation for any purpose and
39 * without fee is hereby granted, provided that the above copyright
40 * notice appear in all copies and that both that copyright notice and
41 * this permission notice appear in supporting documentation, and that
42 * the name of FundsXpress. not be used in advertising or publicity pertaining
43 * to distribution of the software without specific, written prior
44 * permission. FundsXpress makes no representations about the suitability of
45 * this software for any purpose. It is provided "as is" without express
46 * or implied warranty.
47 *
48 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
49 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
50 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
51 */
52
53 /* Copyright (c) 2004-2005, Novell, Inc.
54 * All rights reserved.
55 *
56 * Redistribution and use in source and binary forms, with or without
57 * modification, are permitted provided that the following conditions are met:
58 *
59 * * Redistributions of source code must retain the above copyright notice,
60 * this list of conditions and the following disclaimer.
61 * * Redistributions in binary form must reproduce the above copyright
62 * notice, this list of conditions and the following disclaimer in the
63 * documentation and/or other materials provided with the distribution.
64 * * The copyright holder's name is not used to endorse or promote products
65 * derived from this software without specific prior written permission.
66 *
67 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
68 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
69 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
70 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
71 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
72 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
73 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
74 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
75 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
76 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
77 * POSSIBILITY OF SUCH DAMAGE.
78 */
79
80 /*
81 * Create / Modify / Destroy / View / List realm(s)
82 */
83
84 #include <k5-int.h>
85 #include <kadm5/admin.h>
86 #include <adm_proto.h>
87 #include "kdb5_ldap_util.h"
88 #include "kdb5_ldap_list.h"
89 #include <ldap_principal.h>
90 #include <ldap_krbcontainer.h>
91 extern time_t get_date(char *); /* kadmin/cli/getdate.o */
92
93 char *yes = "yes\n"; /* \n to compare against result of fgets */
94
95 krb5_data tgt_princ_entries[] = {
96 {0, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME},
97 {0, 0, 0} };
98
99 krb5_data db_creator_entries[] = {
100 {0, sizeof("db_creation")-1, "db_creation"} };
101
102
103 static krb5_principal_data db_create_princ = {
104 0, /* magic number */
105 {0, 0, 0}, /* krb5_data realm */
106 db_creator_entries, /* krb5_data *data */
107 1, /* int length */
108 KRB5_NT_SRV_INST /* int type */
109 };
110
111 extern char *mkey_password;
112 extern char *progname;
113 extern kadm5_config_params global_params;
114
115 static void print_realm_params(krb5_ldap_realm_params *rparams, int mask);
116 static int kdb_ldap_create_principal (krb5_context context, krb5_principal
117 princ, enum ap_op op,
118 struct realm_info *pblock,
119 const krb5_keyblock *master_keyblock);
120
121
122 static char *strdur(time_t duration);
123 static int get_ticket_policy(krb5_ldap_realm_params *rparams, int *i, char *argv[],int argc);
124 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);
125 static krb5_error_code krb5_dbe_update_tl_data_new ( krb5_context context, krb5_db_entry *entry, krb5_tl_data *new_tl_data);
126
127 #define ADMIN_LIFETIME 60*60*3 /* 3 hours */
128 #define CHANGEPW_LIFETIME 60*5 /* 5 minutes */
129
130 static int
get_ticket_policy(krb5_ldap_realm_params * rparams,int * i,char * argv[],int argc)131 get_ticket_policy(krb5_ldap_realm_params *rparams, int *i, char *argv[],
132 int argc)
133 {
134 time_t date;
135 time_t now;
136 int mask = 0;
137 krb5_error_code retval = 0;
138 char *me = progname;
139
140 time(&now);
141 if (!strcmp(argv[*i], "-maxtktlife")) {
142 if (++(*i) > argc-1)
143 return 0;
144 date = get_date(argv[*i]);
145 if (date == (time_t)(-1)) {
146 retval = EINVAL;
147 com_err(me, retval, _("while providing time specification"));
148 return 0;
149 }
150 rparams->max_life = date-now;
151 mask |= LDAP_REALM_MAXTICKETLIFE;
152 }
153
154
155 else if (!strcmp(argv[*i], "-maxrenewlife")) {
156 if (++(*i) > argc-1)
157 return 0;
158
159 date = get_date(argv[*i]);
160 if (date == (time_t)(-1)) {
161 retval = EINVAL;
162 com_err(me, retval, _("while providing time specification"));
163 return 0;
164 }
165 rparams->max_renewable_life = date-now;
166 mask |= LDAP_REALM_MAXRENEWLIFE;
167 } else if (!strcmp((argv[*i] + 1), "allow_postdated")) {
168 if (*(argv[*i]) == '+')
169 rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_POSTDATED);
170 else if (*(argv[*i]) == '-')
171 rparams->tktflags |= KRB5_KDB_DISALLOW_POSTDATED;
172 else
173 return 0;
174
175 mask |= LDAP_REALM_KRBTICKETFLAGS;
176 } else if (!strcmp((argv[*i] + 1), "allow_forwardable")) {
177 if (*(argv[*i]) == '+')
178 rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_FORWARDABLE);
179
180 else if (*(argv[*i]) == '-')
181 rparams->tktflags |= KRB5_KDB_DISALLOW_FORWARDABLE;
182 else
183 return 0;
184
185 mask |= LDAP_REALM_KRBTICKETFLAGS;
186 } else if (!strcmp((argv[*i] + 1), "allow_renewable")) {
187 if (*(argv[*i]) == '+')
188 rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_RENEWABLE);
189 else if (*(argv[*i]) == '-')
190 rparams->tktflags |= KRB5_KDB_DISALLOW_RENEWABLE;
191 else
192 return 0;
193
194 mask |= LDAP_REALM_KRBTICKETFLAGS;
195 } else if (!strcmp((argv[*i] + 1), "allow_proxiable")) {
196 if (*(argv[*i]) == '+')
197 rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_PROXIABLE);
198 else if (*(argv[*i]) == '-')
199 rparams->tktflags |= KRB5_KDB_DISALLOW_PROXIABLE;
200 else
201 return 0;
202
203 mask |= LDAP_REALM_KRBTICKETFLAGS;
204 } else if (!strcmp((argv[*i] + 1), "allow_dup_skey")) {
205 if (*(argv[*i]) == '+')
206 rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_DUP_SKEY);
207 else if (*(argv[*i]) == '-')
208 rparams->tktflags |= KRB5_KDB_DISALLOW_DUP_SKEY;
209 else
210 return 0;
211
212 mask |= LDAP_REALM_KRBTICKETFLAGS;
213 }
214
215 else if (!strcmp((argv[*i] + 1), "requires_preauth")) {
216 if (*(argv[*i]) == '+')
217 rparams->tktflags |= KRB5_KDB_REQUIRES_PRE_AUTH;
218 else if (*(argv[*i]) == '-')
219 rparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PRE_AUTH);
220 else
221 return 0;
222
223 mask |= LDAP_REALM_KRBTICKETFLAGS;
224 } else if (!strcmp((argv[*i] + 1), "requires_hwauth")) {
225 if (*(argv[*i]) == '+')
226 rparams->tktflags |= KRB5_KDB_REQUIRES_HW_AUTH;
227 else if (*(argv[*i]) == '-')
228 rparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_HW_AUTH);
229 else
230 return 0;
231
232 mask |= LDAP_REALM_KRBTICKETFLAGS;
233 } else if (!strcmp((argv[*i] + 1), "allow_svr")) {
234 if (*(argv[*i]) == '+')
235 rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_SVR);
236 else if (*(argv[*i]) == '-')
237 rparams->tktflags |= KRB5_KDB_DISALLOW_SVR;
238 else
239 return 0;
240
241 mask |= LDAP_REALM_KRBTICKETFLAGS;
242 } else if (!strcmp((argv[*i] + 1), "allow_tgs_req")) {
243 if (*(argv[*i]) == '+')
244 rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_TGT_BASED);
245 else if (*(argv[*i]) == '-')
246 rparams->tktflags |= KRB5_KDB_DISALLOW_TGT_BASED;
247 else
248 return 0;
249
250 mask |= LDAP_REALM_KRBTICKETFLAGS;
251 } else if (!strcmp((argv[*i] + 1), "allow_tix")) {
252 if (*(argv[*i]) == '+')
253 rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_ALL_TIX);
254 else if (*(argv[*i]) == '-')
255 rparams->tktflags |= KRB5_KDB_DISALLOW_ALL_TIX;
256 else
257 return 0;
258
259 mask |= LDAP_REALM_KRBTICKETFLAGS;
260 } else if (!strcmp((argv[*i] + 1), "needchange")) {
261 if (*(argv[*i]) == '+')
262 rparams->tktflags |= KRB5_KDB_REQUIRES_PWCHANGE;
263 else if (*(argv[*i]) == '-')
264 rparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PWCHANGE);
265 else
266 return 0;
267
268 mask |= LDAP_REALM_KRBTICKETFLAGS;
269 } else if (!strcmp((argv[*i] + 1), "password_changing_service")) {
270 if (*(argv[*i]) == '+')
271 rparams->tktflags |= KRB5_KDB_PWCHANGE_SERVICE;
272 else if (*(argv[*i]) == '-')
273 rparams->tktflags &= (int)(~KRB5_KDB_PWCHANGE_SERVICE);
274 else
275 return 0;
276
277 mask |=LDAP_REALM_KRBTICKETFLAGS;
278 }
279
280 return mask;
281 }
282
283 /* Create a special principal using two specified components. */
284 static krb5_error_code
create_fixed_special(krb5_context context,struct realm_info * rinfo,krb5_keyblock * mkey,const char * comp1,const char * comp2)285 create_fixed_special(krb5_context context, struct realm_info *rinfo,
286 krb5_keyblock *mkey, const char *comp1, const char *comp2)
287 {
288 krb5_error_code ret;
289 krb5_principal princ;
290 const char *realm = global_params.realm;
291
292 ret = krb5_build_principal(context, &princ, strlen(realm), realm, comp1,
293 comp2, (const char *)NULL);
294 if (ret)
295 return ret;
296 ret = kdb_ldap_create_principal(context, princ, TGT_KEY, rinfo, mkey);
297 krb5_free_principal(context, princ);
298 return ret;
299
300 }
301
302 /* Create all special principals for the realm. */
303 static krb5_error_code
create_special_princs(krb5_context context,krb5_principal master_princ,krb5_keyblock * mkey)304 create_special_princs(krb5_context context, krb5_principal master_princ,
305 krb5_keyblock *mkey)
306 {
307 krb5_error_code ret;
308 struct realm_info rblock;
309
310 rblock.max_life = global_params.max_life;
311 rblock.max_rlife = global_params.max_rlife;
312 rblock.expiration = global_params.expiration;
313 rblock.flags = global_params.flags;
314 rblock.key = mkey;
315 rblock.nkslist = global_params.num_keysalts;
316 rblock.kslist = global_params.keysalts;
317
318 /* Create master principal. */
319 rblock.flags |= KRB5_KDB_DISALLOW_ALL_TIX;
320 ret = kdb_ldap_create_principal(context, master_princ, MASTER_KEY, &rblock,
321 mkey);
322 if (ret)
323 return ret;
324
325 /* Create local krbtgt principal. */
326 rblock.flags = 0;
327 ret = create_fixed_special(context, &rblock, mkey, KRB5_TGS_NAME,
328 global_params.realm);
329 if (ret)
330 return ret;
331
332 /* Create kadmin/admin. */
333 rblock.max_life = ADMIN_LIFETIME;
334 rblock.flags = KRB5_KDB_DISALLOW_TGT_BASED;
335 ret = create_fixed_special(context, &rblock, mkey, "kadmin", "admin");
336 if (ret)
337 return ret;
338
339 /* Create kadmin/changepw. */
340 rblock.max_life = CHANGEPW_LIFETIME;
341 rblock.flags = KRB5_KDB_DISALLOW_TGT_BASED | KRB5_KDB_PWCHANGE_SERVICE;
342 ret = create_fixed_special(context, &rblock, mkey, "kadmin", "changepw");
343 if (ret)
344 return ret;
345
346 /* Create kadmin/history. */
347 rblock.max_life = global_params.max_life;
348 rblock.flags = 0;
349 return create_fixed_special(context, &rblock, mkey, "kadmin", "history");
350 }
351
352 /*
353 * This function will create a realm on the LDAP Server, with
354 * the specified attributes.
355 */
356 void
kdb5_ldap_create(int argc,char * argv[])357 kdb5_ldap_create(int argc, char *argv[])
358 {
359 krb5_error_code retval = 0;
360 krb5_keyblock master_keyblock;
361 krb5_ldap_realm_params *rparams = NULL;
362 krb5_principal master_princ = NULL;
363 kdb5_dal_handle *dal_handle = NULL;
364 krb5_ldap_context *ldap_context=NULL;
365 krb5_boolean realm_obj_created = FALSE;
366 krb5_boolean create_complete = FALSE;
367 krb5_boolean print_usage = FALSE;
368 krb5_boolean no_msg = FALSE;
369 char *oldcontainerref=NULL;
370 char pw_str[1024];
371 int do_stash = 0;
372 int i = 0;
373 int mask = 0, ret_mask = 0;
374 char **list = NULL;
375
376 memset(&master_keyblock, 0, sizeof(master_keyblock));
377
378 rparams = (krb5_ldap_realm_params *)malloc(
379 sizeof(krb5_ldap_realm_params));
380 if (rparams == NULL) {
381 retval = ENOMEM;
382 goto cleanup;
383 }
384 memset(rparams, 0, sizeof(krb5_ldap_realm_params));
385
386 /* Parse the arguments */
387 for (i = 1; i < argc; i++) {
388 if (!strcmp(argv[i], "-subtrees")) {
389 if (++i > argc-1)
390 goto err_usage;
391
392 if (strncmp(argv[i], "", strlen(argv[i]))!=0) {
393 list = (char **) calloc(MAX_LIST_ENTRIES, sizeof(char *));
394 if (list == NULL) {
395 retval = ENOMEM;
396 goto cleanup;
397 }
398 if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) {
399 free(list);
400 list = NULL;
401 goto cleanup;
402 }
403
404 rparams->subtreecount=0;
405 while (list[rparams->subtreecount]!=NULL)
406 (rparams->subtreecount)++;
407 rparams->subtree = list;
408 } else if (strncmp(argv[i], "", strlen(argv[i]))==0) {
409 /* dont allow subtree value to be set at the root(NULL, "") of the tree */
410 com_err(progname, EINVAL,
411 _("for subtree while creating realm '%s'"),
412 global_params.realm);
413 goto err_nomsg;
414 }
415 rparams->subtree[rparams->subtreecount] = NULL;
416 mask |= LDAP_REALM_SUBTREE;
417 } else if (!strcmp(argv[i], "-containerref")) {
418 if (++i > argc-1)
419 goto err_usage;
420 if (strncmp(argv[i], "", strlen(argv[i]))==0) {
421 /* dont allow containerref value to be set at the root(NULL, "") of the tree */
422 com_err(progname, EINVAL,
423 _("for container reference while creating realm '%s'"),
424 global_params.realm);
425 goto err_nomsg;
426 }
427 free(rparams->containerref);
428 rparams->containerref = strdup(argv[i]);
429 if (rparams->containerref == NULL) {
430 retval = ENOMEM;
431 goto cleanup;
432 }
433 mask |= LDAP_REALM_CONTREF;
434 } else if (!strcmp(argv[i], "-sscope")) {
435 if (++i > argc-1)
436 goto err_usage;
437 /* Possible values for search scope are
438 * one (or 1) and sub (or 2)
439 */
440 if (!strcasecmp(argv[i], "one")) {
441 rparams->search_scope = 1;
442 } else if (!strcasecmp(argv[i], "sub")) {
443 rparams->search_scope = 2;
444 } else {
445 rparams->search_scope = atoi(argv[i]);
446 if ((rparams->search_scope != 1) &&
447 (rparams->search_scope != 2)) {
448 com_err(progname, EINVAL, _("invalid search scope while "
449 "creating realm '%s'"),
450 global_params.realm);
451 goto err_nomsg;
452 }
453 }
454 mask |= LDAP_REALM_SEARCHSCOPE;
455 }
456 else if (!strcmp(argv[i], "-s")) {
457 do_stash = 1;
458 } else if ((ret_mask= get_ticket_policy(rparams,&i,argv,argc)) !=0) {
459 mask|=ret_mask;
460 }
461
462 else {
463 printf(_("'%s' is an invalid option\n"), argv[i]);
464 goto err_usage;
465 }
466 }
467
468 krb5_princ_set_realm_data(util_context, &db_create_princ, global_params.realm);
469 krb5_princ_set_realm_length(util_context, &db_create_princ, strlen(global_params.realm));
470
471 printf(_("Initializing database for realm '%s'\n"), global_params.realm);
472
473 if (!mkey_password) {
474 unsigned int pw_size;
475 printf(_("You will be prompted for the database Master Password.\n"));
476 printf(_("It is important that you NOT FORGET this password.\n"));
477 fflush(stdout);
478
479 pw_size = sizeof (pw_str);
480 memset(pw_str, 0, pw_size);
481
482 retval = krb5_read_password(util_context, KRB5_KDC_MKEY_1, KRB5_KDC_MKEY_2,
483 pw_str, &pw_size);
484 if (retval) {
485 com_err(progname, retval,
486 _("while reading master key from keyboard"));
487 goto err_nomsg;
488 }
489 mkey_password = pw_str;
490 }
491
492 rparams->realm_name = strdup(global_params.realm);
493 if (rparams->realm_name == NULL) {
494 retval = ENOMEM;
495 com_err(progname, ENOMEM, _("while creating realm '%s'"),
496 global_params.realm);
497 goto err_nomsg;
498 }
499
500 dal_handle = util_context->dal_handle;
501 ldap_context = (krb5_ldap_context *) dal_handle->db_context;
502 if (!ldap_context) {
503 retval = EINVAL;
504 goto cleanup;
505 }
506
507 /* read the kerberos container */
508 retval = krb5_ldap_read_krbcontainer_dn(util_context,
509 &ldap_context->container_dn);
510 if (retval) {
511 /* Prompt the user for entering the DN of Kerberos container */
512 char krb_location[MAX_KRB_CONTAINER_LEN];
513 int krb_location_len = 0;
514
515 printf(_("Enter DN of Kerberos container: "));
516 if (fgets(krb_location, MAX_KRB_CONTAINER_LEN, stdin) != NULL) {
517 /* Remove the newline character at the end */
518 krb_location_len = strlen(krb_location);
519 if ((krb_location[krb_location_len - 1] == '\n') ||
520 (krb_location[krb_location_len - 1] == '\r')) {
521 krb_location[krb_location_len - 1] = '\0';
522 krb_location_len--;
523 }
524 ldap_context->container_dn = strdup(krb_location);
525 if (ldap_context->container_dn == NULL) {
526 retval = ENOMEM;
527 goto cleanup;
528 }
529 }
530 }
531
532 /* create the kerberos container if it doesn't exist */
533 retval = krb5_ldap_create_krbcontainer(util_context,
534 ldap_context->container_dn);
535 if (retval)
536 goto cleanup;
537
538 if ((retval = krb5_ldap_create_realm(util_context,
539 /* global_params.realm, */ rparams, mask))) {
540 goto cleanup;
541 }
542
543 /* We just created the Realm container. Here starts our transaction tracking */
544 realm_obj_created = TRUE;
545
546 if ((retval = krb5_ldap_read_realm_params(util_context,
547 global_params.realm,
548 &(ldap_context->lrparams),
549 &mask))) {
550 com_err(progname, retval, _("while reading information of realm '%s'"),
551 global_params.realm);
552 goto err_nomsg;
553 }
554 free(ldap_context->lrparams->realm_name);
555 ldap_context->lrparams->realm_name = strdup(global_params.realm);
556 if (ldap_context->lrparams->realm_name == NULL) {
557 retval = ENOMEM;
558 goto cleanup;
559 }
560
561 /* assemble & parse the master key name */
562 if ((retval = krb5_db_setup_mkey_name(util_context,
563 global_params.mkey_name,
564 global_params.realm,
565 0, &master_princ))) {
566 com_err(progname, retval, _("while setting up master key name"));
567 goto err_nomsg;
568 }
569
570 /* Obtain master key from master password */
571 {
572 krb5_data master_salt, pwd;
573
574 pwd.data = mkey_password;
575 pwd.length = strlen(mkey_password);
576 retval = krb5_principal2salt(util_context, master_princ, &master_salt);
577 if (retval) {
578 com_err(progname, retval, _("while calculating master key salt"));
579 goto err_nomsg;
580 }
581
582 retval = krb5_c_string_to_key(util_context, global_params.enctype,
583 &pwd, &master_salt, &master_keyblock);
584
585 if (master_salt.data)
586 free(master_salt.data);
587
588 if (retval) {
589 com_err(progname, retval,
590 _("while transforming master key from password"));
591 goto err_nomsg;
592 }
593 }
594
595 /* Create special principals (not in the container reference). */
596 oldcontainerref = ldap_context->lrparams->containerref;
597 ldap_context->lrparams->containerref = NULL;
598 retval = create_special_princs(util_context, master_princ,
599 &master_keyblock);
600 ldap_context->lrparams->containerref = oldcontainerref;
601 if (retval) {
602 com_err(progname, retval, _("while adding entries to the database"));
603 goto err_nomsg;
604 }
605
606 /* The Realm creation is completed. Here is the end of transaction */
607 create_complete = TRUE;
608
609 /* Stash the master key only if '-s' option is specified */
610 if (do_stash || global_params.mask & KADM5_CONFIG_STASH_FILE) {
611 krb5_kvno mkey_kvno;
612 /*
613 * Determine the kvno to use, it must be that used to create the master
614 * key princ.
615 */
616 if (global_params.mask & KADM5_CONFIG_KVNO)
617 mkey_kvno = global_params.kvno; /* user specified */
618 else
619 mkey_kvno = 1; /* Default */
620
621 retval = krb5_db_store_master_key(util_context,
622 global_params.stash_file,
623 master_princ,
624 mkey_kvno,
625 &master_keyblock, NULL);
626 if (retval) {
627 com_err(progname, errno, _("while storing key"));
628 printf(_("Warning: couldn't stash master key.\n"));
629 }
630 }
631
632 goto cleanup;
633
634
635 err_usage:
636 print_usage = TRUE;
637
638 err_nomsg:
639 no_msg = TRUE;
640
641 cleanup:
642 /* If the Realm creation is not complete, do the roll-back here */
643 if ((realm_obj_created) && (!create_complete))
644 krb5_ldap_delete_realm(util_context, global_params.realm);
645
646 if (rparams)
647 krb5_ldap_free_realm_params(rparams);
648
649 memset (pw_str, 0, sizeof (pw_str));
650
651 if (print_usage)
652 db_usage(CREATE_REALM);
653
654 if (retval) {
655 if (!no_msg) {
656 com_err(progname, retval, _("while creating realm '%s'"),
657 global_params.realm);
658 }
659 exit_status++;
660 }
661
662 krb5_free_keyblock_contents(util_context, &master_keyblock);
663 krb5_free_principal(util_context, master_princ);
664 }
665
666
667 /*
668 * This function will modify the attributes of a given realm object
669 */
670 void
kdb5_ldap_modify(int argc,char * argv[])671 kdb5_ldap_modify(int argc, char *argv[])
672 {
673 krb5_error_code retval = 0;
674 krb5_ldap_realm_params *rparams = NULL;
675 krb5_boolean print_usage = FALSE;
676 krb5_boolean no_msg = FALSE;
677 kdb5_dal_handle *dal_handle = NULL;
678 krb5_ldap_context *ldap_context=NULL;
679 int i = 0;
680 int mask = 0, rmask = 0, ret_mask = 0;
681 char **slist = {NULL};
682
683 dal_handle = util_context->dal_handle;
684 ldap_context = (krb5_ldap_context *) dal_handle->db_context;
685 if (!(ldap_context)) {
686 retval = EINVAL;
687 goto cleanup;
688 }
689
690 retval = krb5_ldap_read_krbcontainer_dn(util_context,
691 &ldap_context->container_dn);
692 if (retval) {
693 com_err(progname, retval,
694 _("while reading Kerberos container information"));
695 goto err_nomsg;
696 }
697
698 retval = krb5_ldap_read_realm_params(util_context,
699 global_params.realm, &rparams, &rmask);
700 if (retval)
701 goto cleanup;
702 /* Parse the arguments */
703 for (i = 1; i < argc; i++) {
704 size_t k = 0;
705 if (!strcmp(argv[i], "-subtrees")) {
706 if (++i > argc-1)
707 goto err_usage;
708
709 if (rmask & LDAP_REALM_SUBTREE) {
710 if (rparams->subtree) {
711 for (k=0; k<rparams->subtreecount && rparams->subtree[k]; k++)
712 free(rparams->subtree[k]);
713 free(rparams->subtree);
714 rparams->subtreecount=0;
715 rparams->subtree = NULL;
716 }
717 }
718 if (strncmp(argv[i] ,"", strlen(argv[i]))!=0) {
719 slist = (char **) calloc(MAX_LIST_ENTRIES, sizeof(char *));
720 if (slist == NULL) {
721 retval = ENOMEM;
722 goto cleanup;
723 }
724 if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, slist))) {
725 free(slist);
726 slist = NULL;
727 goto cleanup;
728 }
729
730 rparams->subtreecount=0;
731 while (slist[rparams->subtreecount]!=NULL)
732 (rparams->subtreecount)++;
733 rparams->subtree = slist;
734 } else if (strncmp(argv[i], "", strlen(argv[i]))==0) {
735 /* dont allow subtree value to be set at the root(NULL, "") of the tree */
736 com_err(progname, EINVAL,
737 _("for subtree while modifying realm '%s'"),
738 global_params.realm);
739 goto err_nomsg;
740 }
741 rparams->subtree[rparams->subtreecount] = NULL;
742 mask |= LDAP_REALM_SUBTREE;
743 } else if (!strncmp(argv[i], "-containerref", strlen(argv[i]))) {
744 if (++i > argc-1)
745 goto err_usage;
746 if (strncmp(argv[i], "", strlen(argv[i]))==0) {
747 /* dont allow containerref value to be set at the root(NULL, "") of the tree */
748 com_err(progname, EINVAL, _("for container reference while "
749 "modifying realm '%s'"),
750 global_params.realm);
751 goto err_nomsg;
752 }
753 free(rparams->containerref);
754 rparams->containerref = strdup(argv[i]);
755 if (rparams->containerref == NULL) {
756 retval = ENOMEM;
757 goto cleanup;
758 }
759 mask |= LDAP_REALM_CONTREF;
760 } else if (!strcmp(argv[i], "-sscope")) {
761 if (++i > argc-1)
762 goto err_usage;
763 /* Possible values for search scope are
764 * one (or 1) and sub (or 2)
765 */
766 if (strcasecmp(argv[i], "one") == 0) {
767 rparams->search_scope = 1;
768 } else if (strcasecmp(argv[i], "sub") == 0) {
769 rparams->search_scope = 2;
770 } else {
771 rparams->search_scope = atoi(argv[i]);
772 if ((rparams->search_scope != 1) &&
773 (rparams->search_scope != 2)) {
774 retval = EINVAL;
775 com_err(progname, retval,
776 _("specified for search scope while modifying "
777 "information of realm '%s'"),
778 global_params.realm);
779 goto err_nomsg;
780 }
781 }
782 mask |= LDAP_REALM_SEARCHSCOPE;
783 }
784 else if ((ret_mask= get_ticket_policy(rparams,&i,argv,argc)) !=0) {
785 mask|=ret_mask;
786 } else {
787 printf(_("'%s' is an invalid option\n"), argv[i]);
788 goto err_usage;
789 }
790 }
791
792 if ((retval = krb5_ldap_modify_realm(util_context,
793 /* global_params.realm, */ rparams, mask))) {
794 goto cleanup;
795 }
796
797 goto cleanup;
798
799 err_usage:
800 print_usage = TRUE;
801
802 err_nomsg:
803 no_msg = TRUE;
804
805 cleanup:
806 krb5_ldap_free_realm_params(rparams);
807
808 if (print_usage) {
809 db_usage(MODIFY_REALM);
810 }
811
812 if (retval) {
813 if (!no_msg)
814 com_err(progname, retval,
815 _("while modifying information of realm '%s'"),
816 global_params.realm);
817 exit_status++;
818 }
819
820 return;
821 }
822
823
824
825 /*
826 * This function displays the attributes of a Realm
827 */
828 void
kdb5_ldap_view(int argc,char * argv[])829 kdb5_ldap_view(int argc, char *argv[])
830 {
831 krb5_ldap_realm_params *rparams = NULL;
832 krb5_error_code retval = 0;
833 kdb5_dal_handle *dal_handle=NULL;
834 krb5_ldap_context *ldap_context=NULL;
835 int mask = 0;
836
837 dal_handle = util_context->dal_handle;
838 ldap_context = (krb5_ldap_context *) dal_handle->db_context;
839 if (!(ldap_context)) {
840 retval = EINVAL;
841 com_err(progname, retval, _("while initializing database"));
842 exit_status++;
843 return;
844 }
845
846 /* Read the kerberos container information */
847 retval = krb5_ldap_read_krbcontainer_dn(util_context,
848 &ldap_context->container_dn);
849 if (retval) {
850 com_err(progname, retval,
851 _("while reading kerberos container information"));
852 exit_status++;
853 return;
854 }
855
856 if ((retval = krb5_ldap_read_realm_params(util_context,
857 global_params.realm, &rparams, &mask)) || (!rparams)) {
858 com_err(progname, retval, _("while reading information of realm '%s'"),
859 global_params.realm);
860 exit_status++;
861 return;
862 }
863 print_realm_params(rparams, mask);
864 krb5_ldap_free_realm_params(rparams);
865
866 return;
867 }
868
869 static char *
strdur(time_t duration)870 strdur(time_t duration)
871 {
872 static char out[50];
873 int neg, days, hours, minutes, seconds;
874
875 if (duration < 0) {
876 duration *= -1;
877 neg = 1;
878 } else
879 neg = 0;
880 days = duration / (24 * 3600);
881 duration %= 24 * 3600;
882 hours = duration / 3600;
883 duration %= 3600;
884 minutes = duration / 60;
885 duration %= 60;
886 seconds = duration;
887 snprintf(out, sizeof(out), "%s%d %s %02d:%02d:%02d", neg ? "-" : "",
888 days, days == 1 ? "day" : "days",
889 hours, minutes, seconds);
890 return out;
891 }
892
893 /*
894 * This function prints the attributes of a given realm to the
895 * standard output.
896 */
897 static void
print_realm_params(krb5_ldap_realm_params * rparams,int mask)898 print_realm_params(krb5_ldap_realm_params *rparams, int mask)
899 {
900 char **slist = NULL;
901 unsigned int num_entry_printed = 0, i = 0;
902
903 /* Print the Realm Attributes on the standard output */
904 printf("%25s: %-50s\n", _("Realm Name"), global_params.realm);
905 if (mask & LDAP_REALM_SUBTREE) {
906 for (i=0; rparams->subtree[i]!=NULL; i++)
907 printf("%25s: %-50s\n", _("Subtree"), rparams->subtree[i]);
908 }
909 if (mask & LDAP_REALM_CONTREF)
910 printf("%25s: %-50s\n", _("Principal Container Reference"),
911 rparams->containerref);
912 if (mask & LDAP_REALM_SEARCHSCOPE) {
913 if ((rparams->search_scope != 1) &&
914 (rparams->search_scope != 2)) {
915 printf("%25s: %-50s\n", _("SearchScope"), _("Invalid !"));
916 } else {
917 printf("%25s: %-50s\n", _("SearchScope"),
918 (rparams->search_scope == 1) ? "ONE" : "SUB");
919 }
920 }
921 if (mask & LDAP_REALM_KDCSERVERS) {
922 printf("%25s:", _("KDC Services"));
923 if (rparams->kdcservers != NULL) {
924 num_entry_printed = 0;
925 for (slist = rparams->kdcservers; *slist != NULL; slist++) {
926 if (num_entry_printed)
927 printf(" %25s %-50s\n", " ", *slist);
928 else
929 printf(" %-50s\n", *slist);
930 num_entry_printed++;
931 }
932 }
933 if (num_entry_printed == 0)
934 printf("\n");
935 }
936 if (mask & LDAP_REALM_ADMINSERVERS) {
937 printf("%25s:", _("Admin Services"));
938 if (rparams->adminservers != NULL) {
939 num_entry_printed = 0;
940 for (slist = rparams->adminservers; *slist != NULL; slist++) {
941 if (num_entry_printed)
942 printf(" %25s %-50s\n", " ", *slist);
943 else
944 printf(" %-50s\n", *slist);
945 num_entry_printed++;
946 }
947 }
948 if (num_entry_printed == 0)
949 printf("\n");
950 }
951 if (mask & LDAP_REALM_PASSWDSERVERS) {
952 printf("%25s:", _("Passwd Services"));
953 if (rparams->passwdservers != NULL) {
954 num_entry_printed = 0;
955 for (slist = rparams->passwdservers; *slist != NULL; slist++) {
956 if (num_entry_printed)
957 printf(" %25s %-50s\n", " ", *slist);
958 else
959 printf(" %-50s\n", *slist);
960 num_entry_printed++;
961 }
962 }
963 if (num_entry_printed == 0)
964 printf("\n");
965 }
966
967 if (mask & LDAP_REALM_MAXTICKETLIFE) {
968 printf("%25s:", _("Maximum Ticket Life"));
969 printf(" %s \n", strdur(rparams->max_life));
970 }
971
972 if (mask & LDAP_REALM_MAXRENEWLIFE) {
973 printf("%25s:", _("Maximum Renewable Life"));
974 printf(" %s \n", strdur(rparams->max_renewable_life));
975 }
976
977 if (mask & LDAP_REALM_KRBTICKETFLAGS) {
978 int ticketflags = rparams->tktflags;
979
980 printf("%25s: ", _("Ticket flags"));
981 if (ticketflags & KRB5_KDB_DISALLOW_POSTDATED)
982 printf("%s ","DISALLOW_POSTDATED");
983
984 if (ticketflags & KRB5_KDB_DISALLOW_FORWARDABLE)
985 printf("%s ","DISALLOW_FORWARDABLE");
986
987 if (ticketflags & KRB5_KDB_DISALLOW_RENEWABLE)
988 printf("%s ","DISALLOW_RENEWABLE");
989
990 if (ticketflags & KRB5_KDB_DISALLOW_PROXIABLE)
991 printf("%s ","DISALLOW_PROXIABLE");
992
993 if (ticketflags & KRB5_KDB_DISALLOW_DUP_SKEY)
994 printf("%s ","DISALLOW_DUP_SKEY");
995
996 if (ticketflags & KRB5_KDB_REQUIRES_PRE_AUTH)
997 printf("%s ","REQUIRES_PRE_AUTH");
998
999 if (ticketflags & KRB5_KDB_REQUIRES_HW_AUTH)
1000 printf("%s ","REQUIRES_HW_AUTH");
1001
1002 if (ticketflags & KRB5_KDB_DISALLOW_SVR)
1003 printf("%s ","DISALLOW_SVR");
1004
1005 if (ticketflags & KRB5_KDB_DISALLOW_TGT_BASED)
1006 printf("%s ","DISALLOW_TGT_BASED");
1007
1008 if (ticketflags & KRB5_KDB_DISALLOW_ALL_TIX)
1009 printf("%s ","DISALLOW_ALL_TIX");
1010
1011 if (ticketflags & KRB5_KDB_REQUIRES_PWCHANGE)
1012 printf("%s ","REQUIRES_PWCHANGE");
1013
1014 if (ticketflags & KRB5_KDB_PWCHANGE_SERVICE)
1015 printf("%s ","PWCHANGE_SERVICE");
1016
1017 printf("\n");
1018 }
1019
1020
1021 return;
1022 }
1023
1024
1025
1026 /*
1027 * This function lists the Realm(s) present under the Kerberos container
1028 * on the LDAP Server.
1029 */
1030 void
kdb5_ldap_list(int argc,char * argv[])1031 kdb5_ldap_list(int argc, char *argv[])
1032 {
1033 char **list = NULL;
1034 char **plist = NULL;
1035 krb5_error_code retval = 0;
1036 kdb5_dal_handle *dal_handle=NULL;
1037 krb5_ldap_context *ldap_context=NULL;
1038
1039 dal_handle = util_context->dal_handle;
1040 ldap_context = (krb5_ldap_context *) dal_handle->db_context;
1041 if (!(ldap_context)) {
1042 retval = EINVAL;
1043 exit_status++;
1044 return;
1045 }
1046
1047 /* Read the kerberos container information */
1048 retval = krb5_ldap_read_krbcontainer_dn(util_context,
1049 &ldap_context->container_dn);
1050 if (retval) {
1051 com_err(progname, retval,
1052 _("while reading kerberos container information"));
1053 exit_status++;
1054 return;
1055 }
1056
1057 retval = krb5_ldap_list_realm(util_context, &list);
1058 if (retval != 0) {
1059 com_err(progname, retval, _("while listing realms"));
1060 exit_status++;
1061 return;
1062 }
1063 /* This is to handle the case of realm not present */
1064 if (list == NULL)
1065 return;
1066
1067 for (plist = list; *plist != NULL; plist++) {
1068 printf("%s\n", *plist);
1069 }
1070 krb5_free_list_entries(list);
1071 free(list);
1072
1073 return;
1074 }
1075
1076 /*
1077 * Duplicating the following two functions here because
1078 * 'krb5_dbe_update_tl_data' uses backend specific memory allocation. The catch
1079 * here is that the backend is not initialized - kdb5_ldap_util doesn't go
1080 * through DAL.
1081 * 1. krb5_dbe_update_tl_data
1082 * 2. krb5_dbe_update_mod_princ_data
1083 */
1084
1085 /* Start duplicate code ... */
1086
1087 static krb5_error_code
krb5_dbe_update_tl_data_new(krb5_context context,krb5_db_entry * entry,krb5_tl_data * new_tl_data)1088 krb5_dbe_update_tl_data_new(krb5_context context, krb5_db_entry *entry,
1089 krb5_tl_data *new_tl_data)
1090 {
1091 krb5_tl_data *tl_data = NULL;
1092 krb5_octet *tmp;
1093
1094 /* copy the new data first, so we can fail cleanly if malloc()
1095 * fails */
1096 if ((tmp = (krb5_octet *) malloc (new_tl_data->tl_data_length)) == NULL)
1097 return (ENOMEM);
1098
1099 /* Find an existing entry of the specified type and point at
1100 * it, or NULL if not found */
1101
1102 if (new_tl_data->tl_data_type != KRB5_TL_DB_ARGS) { /* db_args can be multiple */
1103 for (tl_data = entry->tl_data; tl_data;
1104 tl_data = tl_data->tl_data_next)
1105 if (tl_data->tl_data_type == new_tl_data->tl_data_type)
1106 break;
1107 }
1108
1109 /* if necessary, chain a new record in the beginning and point at it */
1110
1111 if (!tl_data) {
1112 if ((tl_data = (krb5_tl_data *) malloc (sizeof(krb5_tl_data))) == NULL) {
1113 free(tmp);
1114 return (ENOMEM);
1115 }
1116 memset(tl_data, 0, sizeof(krb5_tl_data));
1117 tl_data->tl_data_next = entry->tl_data;
1118 entry->tl_data = tl_data;
1119 entry->n_tl_data++;
1120 }
1121
1122 /* fill in the record */
1123
1124 free(tl_data->tl_data_contents);
1125
1126 tl_data->tl_data_type = new_tl_data->tl_data_type;
1127 tl_data->tl_data_length = new_tl_data->tl_data_length;
1128 tl_data->tl_data_contents = tmp;
1129 memcpy(tmp, new_tl_data->tl_data_contents, tl_data->tl_data_length);
1130
1131 return (0);
1132 }
1133
1134 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)1135 krb5_dbe_update_mod_princ_data_new(krb5_context context, krb5_db_entry *entry,
1136 krb5_timestamp mod_date,
1137 krb5_const_principal mod_princ)
1138 {
1139 krb5_tl_data tl_data;
1140
1141 krb5_error_code retval = 0;
1142 krb5_octet * nextloc = 0;
1143 char * unparse_mod_princ = 0;
1144 unsigned int unparse_mod_princ_size;
1145
1146 if ((retval = krb5_unparse_name(context, mod_princ,
1147 &unparse_mod_princ)))
1148 return(retval);
1149
1150 unparse_mod_princ_size = strlen(unparse_mod_princ) + 1;
1151
1152 if ((nextloc = (krb5_octet *) malloc(unparse_mod_princ_size + 4))
1153 == NULL) {
1154 free(unparse_mod_princ);
1155 return(ENOMEM);
1156 }
1157
1158 tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
1159 tl_data.tl_data_length = unparse_mod_princ_size + 4;
1160 tl_data.tl_data_contents = nextloc;
1161
1162 /* Mod Date */
1163 krb5_kdb_encode_int32(mod_date, nextloc);
1164
1165 /* Mod Princ */
1166 memcpy(nextloc+4, unparse_mod_princ, unparse_mod_princ_size);
1167
1168 retval = krb5_dbe_update_tl_data_new(context, entry, &tl_data);
1169
1170 free(unparse_mod_princ);
1171 free(nextloc);
1172
1173 return(retval);
1174 }
1175
1176 static krb5_error_code
kdb_ldap_tgt_keysalt_iterate(krb5_key_salt_tuple * ksent,krb5_pointer ptr)1177 kdb_ldap_tgt_keysalt_iterate(krb5_key_salt_tuple *ksent, krb5_pointer ptr)
1178 {
1179 krb5_context context;
1180 krb5_error_code kret;
1181 struct iterate_args *iargs;
1182 krb5_keyblock key;
1183 krb5_int32 ind;
1184 krb5_data pwd;
1185 krb5_db_entry *entry;
1186
1187 iargs = (struct iterate_args *) ptr;
1188 kret = 0;
1189
1190 context = iargs->ctx;
1191 entry = iargs->dbentp;
1192
1193 /*
1194 * Convert the master key password into a key for this particular
1195 * encryption system.
1196 */
1197 pwd.data = mkey_password;
1198 pwd.length = strlen(mkey_password);
1199 kret = krb5_c_random_seed(context, &pwd);
1200 if (kret)
1201 return kret;
1202
1203 /*if (!(kret = krb5_dbe_create_key_data(iargs->ctx, iargs->dbentp))) {*/
1204 if ((entry->key_data =
1205 (krb5_key_data *) realloc(entry->key_data,
1206 (sizeof(krb5_key_data) *
1207 (entry->n_key_data + 1)))) == NULL)
1208 return (ENOMEM);
1209
1210 memset(entry->key_data + entry->n_key_data, 0, sizeof(krb5_key_data));
1211 ind = entry->n_key_data++;
1212
1213 if (!(kret = krb5_c_make_random_key(context, ksent->ks_enctype,
1214 &key))) {
1215 kret = krb5_dbe_encrypt_key_data(context, iargs->rblock->key, &key,
1216 NULL, 1, &entry->key_data[ind]);
1217 krb5_free_keyblock_contents(context, &key);
1218 }
1219 /*}*/
1220
1221 return(kret);
1222 }
1223 /* End duplicate code */
1224
1225 /*
1226 * This function creates service principals when
1227 * creating the realm object.
1228 */
1229 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)1230 kdb_ldap_create_principal(krb5_context context, krb5_principal princ,
1231 enum ap_op op, struct realm_info *pblock,
1232 const krb5_keyblock *master_keyblock)
1233 {
1234 int retval=0, currlen=0, princtype = 2 /* Service Principal */;
1235 unsigned char *curr=NULL;
1236 krb5_tl_data *tl_data=NULL;
1237 krb5_db_entry entry;
1238 long mask = 0;
1239 krb5_keyblock key;
1240 int kvno = 0;
1241 kdb5_dal_handle *dal_handle = NULL;
1242 krb5_ldap_context *ldap_context=NULL;
1243 struct iterate_args iargs;
1244 krb5_data *pdata;
1245 krb5_timestamp now;
1246 krb5_actkvno_node actkvno;
1247
1248 memset(&entry, 0, sizeof(entry));
1249
1250 if ((pblock == NULL) || (context == NULL)) {
1251 retval = EINVAL;
1252 goto cleanup;
1253 }
1254 dal_handle = context->dal_handle;
1255 ldap_context = (krb5_ldap_context *) dal_handle->db_context;
1256 if (!(ldap_context)) {
1257 retval = EINVAL;
1258 goto cleanup;
1259 }
1260
1261 tl_data = malloc(sizeof(*tl_data));
1262 if (tl_data == NULL) {
1263 retval = ENOMEM;
1264 goto cleanup;
1265 }
1266 memset(tl_data, 0, sizeof(*tl_data));
1267 tl_data->tl_data_length = 1 + 2 + 2 + 1 + 2 + 4;
1268 tl_data->tl_data_type = 7; /* KDB_TL_USER_INFO */
1269 curr = tl_data->tl_data_contents = malloc(tl_data->tl_data_length);
1270 if (tl_data->tl_data_contents == NULL) {
1271 retval = ENOMEM;
1272 goto cleanup;
1273 }
1274
1275 memset(curr, 1, 1); /* Passing the mask as principal type */
1276 curr += 1;
1277 currlen = 2;
1278 STORE16_INT(curr, currlen);
1279 curr += currlen;
1280 STORE16_INT(curr, princtype);
1281 curr += currlen;
1282
1283 mask |= KADM5_PRINCIPAL;
1284 mask |= KADM5_ATTRIBUTES ;
1285 mask |= KADM5_MAX_LIFE ;
1286 mask |= KADM5_MAX_RLIFE ;
1287 mask |= KADM5_PRINC_EXPIRE_TIME ;
1288 mask |= KADM5_KEY_DATA;
1289
1290 entry.tl_data = tl_data;
1291 entry.n_tl_data += 1;
1292 /* Set the creator's name */
1293 if ((retval = krb5_timeofday(context, &now)))
1294 goto cleanup;
1295 if ((retval = krb5_dbe_update_mod_princ_data_new(context, &entry,
1296 now, &db_create_princ)))
1297 goto cleanup;
1298
1299 entry.attributes = pblock->flags | KRB5_KDB_LOCKDOWN_KEYS;
1300 entry.max_life = pblock->max_life;
1301 entry.max_renewable_life = pblock->max_rlife;
1302 entry.expiration = pblock->expiration;
1303 entry.mask = mask;
1304 if ((retval = krb5_copy_principal(context, princ, &entry.princ)))
1305 goto cleanup;
1306
1307
1308 switch (op) {
1309 case TGT_KEY:
1310 if ((pdata = krb5_princ_component(context, princ, 1)) &&
1311 pdata->length == strlen("history") &&
1312 !memcmp(pdata->data, "history", strlen("history"))) {
1313
1314 /* Allocate memory for storing the key */
1315 if ((entry.key_data = (krb5_key_data *) malloc(
1316 sizeof(krb5_key_data))) == NULL) {
1317 retval = ENOMEM;
1318 goto cleanup;
1319 }
1320
1321 memset(entry.key_data, 0, sizeof(krb5_key_data));
1322 entry.n_key_data++;
1323
1324 retval = krb5_c_make_random_key(context, global_params.enctype, &key);
1325 if (retval) {
1326 goto cleanup;
1327 }
1328 kvno = 1; /* New key is getting set */
1329 retval = krb5_dbe_encrypt_key_data(context, master_keyblock,
1330 &key, NULL, kvno,
1331 &entry.key_data[entry.n_key_data - 1]);
1332 krb5_free_keyblock_contents(context, &key);
1333 if (retval) {
1334 goto cleanup;
1335 }
1336 } else {
1337 /*retval = krb5_c_make_random_key(context, 16, &key) ;*/
1338 iargs.ctx = context;
1339 iargs.rblock = pblock;
1340 iargs.dbentp = &entry;
1341
1342 /*
1343 * Iterate through the key/salt list, ignoring salt types.
1344 */
1345 if ((retval = krb5_keysalt_iterate(pblock->kslist,
1346 pblock->nkslist,
1347 1,
1348 kdb_ldap_tgt_keysalt_iterate,
1349 (krb5_pointer) &iargs)))
1350 return retval;
1351 }
1352 break;
1353
1354 case MASTER_KEY:
1355 /* Allocate memory for storing the key */
1356 if ((entry.key_data = (krb5_key_data *) malloc(
1357 sizeof(krb5_key_data))) == NULL) {
1358 retval = ENOMEM;
1359 goto cleanup;
1360 }
1361
1362 memset(entry.key_data, 0, sizeof(krb5_key_data));
1363 entry.n_key_data++;
1364 kvno = 1; /* New key is getting set */
1365 retval = krb5_dbe_encrypt_key_data(context, pblock->key,
1366 master_keyblock, NULL, kvno,
1367 &entry.key_data[entry.n_key_data - 1]);
1368 if (retval) {
1369 goto cleanup;
1370 }
1371 /*
1372 * There should always be at least one "active" mkey so creating the
1373 * KRB5_TL_ACTKVNO entry now so the initial mkey is active.
1374 */
1375 actkvno.next = NULL;
1376 actkvno.act_kvno = kvno;
1377 actkvno.act_time = now;
1378 retval = krb5_dbe_update_actkvno(context, &entry, &actkvno);
1379 if (retval)
1380 goto cleanup;
1381
1382 break;
1383
1384 case NULL_KEY:
1385 default:
1386 break;
1387 } /* end of switch */
1388
1389 retval = krb5_ldap_put_principal(context, &entry, NULL);
1390 if (retval) {
1391 com_err(NULL, retval, _("while adding entries to database"));
1392 goto cleanup;
1393 }
1394
1395 cleanup:
1396 krb5_dbe_free_contents(context, &entry);
1397 return retval;
1398 }
1399
1400
1401 /*
1402 * This function destroys the realm object and the associated principals
1403 */
1404 void
kdb5_ldap_destroy(int argc,char * argv[])1405 kdb5_ldap_destroy(int argc, char *argv[])
1406 {
1407 extern char *optarg;
1408 extern int optind;
1409 int optchar = 0;
1410 char buf[5] = {0};
1411 krb5_error_code retval = 0;
1412 int force = 0;
1413 int mask = 0;
1414 kdb5_dal_handle *dal_handle = NULL;
1415 krb5_ldap_context *ldap_context = NULL;
1416
1417 optind = 1;
1418 while ((optchar = getopt(argc, argv, "f")) != -1) {
1419 switch (optchar) {
1420 case 'f':
1421 force++;
1422 break;
1423 case '?':
1424 default:
1425 db_usage(DESTROY_REALM);
1426 return;
1427 /*NOTREACHED*/
1428 }
1429 }
1430
1431 if (!force) {
1432 printf(_("Deleting KDC database of '%s', are you sure?\n"),
1433 global_params.realm);
1434 printf(_("(type 'yes' to confirm)? "));
1435 if (fgets(buf, sizeof(buf), stdin) == NULL) {
1436 exit_status++;
1437 return;
1438 }
1439 if (strcmp(buf, yes)) {
1440 exit_status++;
1441 return;
1442 }
1443 printf(_("OK, deleting database of '%s'...\n"), global_params.realm);
1444 }
1445
1446 dal_handle = util_context->dal_handle;
1447 ldap_context = (krb5_ldap_context *) dal_handle->db_context;
1448 if (!(ldap_context)) {
1449 com_err(progname, EINVAL, _("while initializing database"));
1450 exit_status++;
1451 return;
1452 }
1453
1454 /* Read the kerberos container DN */
1455 retval = krb5_ldap_read_krbcontainer_dn(util_context,
1456 &ldap_context->container_dn);
1457 if (retval) {
1458 com_err(progname, retval,
1459 _("while reading kerberos container information"));
1460 exit_status++;
1461 return;
1462 }
1463
1464 /* Read the Realm information from the LDAP Server */
1465 if ((retval = krb5_ldap_read_realm_params(util_context, global_params.realm,
1466 &(ldap_context->lrparams), &mask)) != 0) {
1467 com_err(progname, retval, _("while reading realm information"));
1468 exit_status++;
1469 return;
1470 }
1471
1472 /* Delete the realm container and all the associated principals */
1473 retval = krb5_ldap_delete_realm(util_context, global_params.realm);
1474 if (retval) {
1475 com_err(progname, retval,
1476 _("deleting database of '%s'"), global_params.realm);
1477 exit_status++;
1478 return;
1479 }
1480
1481 printf(_("** Database of '%s' destroyed.\n"), global_params.realm);
1482
1483 return;
1484 }
1485