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