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