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