1 /*
   2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
   3  * Use is subject to license terms.
   4  */
   5 
   6 /*
   7  * kadmin/ldap_util/kdb5_ldap_realm.c
   8  *
   9  * Copyright 1990,1991,2001, 2002 by the Massachusetts Institute of Technology.
  10  * All Rights Reserved.
  11  *
  12  * Export of this software from the United States of America may
  13  *   require a specific license from the United States Government.
  14  *   It is the responsibility of any person or organization contemplating
  15  *   export to obtain such a license before exporting.
  16  *
  17  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
  18  * distribute this software and its documentation for any purpose and
  19  * without fee is hereby granted, provided that the above copyright
  20  * notice appear in all copies and that both that copyright notice and
  21  * this permission notice appear in supporting documentation, and that
  22  * the name of M.I.T. not be used in advertising or publicity pertaining
  23  * to distribution of the software without specific, written prior
  24  * permission.  Furthermore if you modify this software you must label
  25  * your software as modified software and not distribute it in such a
  26  * fashion that it might be confused with the original M.I.T. software.
  27  * M.I.T. makes no representations about the suitability of
  28  * this software for any purpose.  It is provided "as is" without express
  29  * or implied warranty.
  30  */
  31 
  32 /*
  33  * Copyright (C) 1998 by the FundsXpress, INC.
  34  *
  35  * All rights reserved.
  36  *
  37  * Export of this software from the United States of America may require
  38  * a specific license from the United States Government.  It is the
  39  * responsibility of any person or organization contemplating export to
  40  * obtain such a license before exporting.
  41  *
  42  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
  43  * distribute this software and its documentation for any purpose and
  44  * without fee is hereby granted, provided that the above copyright
  45  * notice appear in all copies and that both that copyright notice and
  46  * this permission notice appear in supporting documentation, and that
  47  * the name of FundsXpress. not be used in advertising or publicity pertaining
  48  * to distribution of the software without specific, written prior
  49  * permission.  FundsXpress makes no representations about the suitability of
  50  * this software for any purpose.  It is provided "as is" without express
  51  * or implied warranty.
  52  *
  53  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  54  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  55  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  56  */
  57 
  58 /* Copyright (c) 2004-2005, Novell, Inc.
  59  * All rights reserved.
  60  *
  61  * Redistribution and use in source and binary forms, with or without
  62  * modification, are permitted provided that the following conditions are met:
  63  *
  64  *   * Redistributions of source code must retain the above copyright notice,
  65  *       this list of conditions and the following disclaimer.
  66  *   * Redistributions in binary form must reproduce the above copyright
  67  *       notice, this list of conditions and the following disclaimer in the
  68  *       documentation and/or other materials provided with the distribution.
  69  *   * The copyright holder's name is not used to endorse or promote products
  70  *       derived from this software without specific prior written permission.
  71  *
  72  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  73  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  74  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  75  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  76  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  77  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  78  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  79  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  80  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  81  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  82  * POSSIBILITY OF SUCH DAMAGE.
  83  */
  84 
  85 /*
  86  * Create / Modify / Destroy / View / List realm(s)
  87  */
  88 
  89 /* Needed for getting the definition of KRB5_TL_DB_ARGS */
  90 #define SECURID
  91 
  92 #include <stdio.h>
  93 #include <k5-int.h>
  94 #include <kadm5/admin.h>
  95 #include <libintl.h>
  96 #include <locale.h>
  97 #include "kdb5_ldap_util.h"
  98 #include "kdb5_ldap_list.h"
  99 #include <ldap_principal.h>
 100 #include <ldap_krbcontainer.h>
 101 extern time_t get_date(char *); /* kadmin/cli/getdate.o */
 102 
 103 char *yes = "yes\n"; /* \n to compare against result of fgets */
 104 krb5_key_salt_tuple def_kslist = {ENCTYPE_DES_CBC_CRC, KRB5_KDB_SALTTYPE_NORMAL};
 105 
 106 struct realm_info rblock = {
 107     KRB5_KDB_MAX_LIFE,
 108     KRB5_KDB_MAX_RLIFE,
 109     KRB5_KDB_EXPIRATION,
 110     KRB5_KDB_DEF_FLAGS,
 111     (krb5_keyblock *) NULL,
 112     1,
 113     &def_kslist
 114 };
 115 
 116 krb5_data tgt_princ_entries[] = {
 117     {0, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME},
 118     {0, 0, 0} };
 119 
 120 krb5_data db_creator_entries[] = {
 121     {0, sizeof("db_creation")-1, "db_creation"} };
 122 
 123 
 124 static krb5_principal_data db_create_princ = {
 125     0,                                  /* magic number */
 126     {0, 0, 0},                          /* krb5_data realm */
 127     db_creator_entries,                 /* krb5_data *data */
 128     1,                                  /* int length */
 129     KRB5_NT_SRV_INST                    /* int type */
 130 };
 131 
 132 extern char *mkey_password;
 133 extern char *progname;
 134 extern kadm5_config_params global_params;
 135 
 136 static void print_realm_params(krb5_ldap_realm_params *rparams, int mask);
 137 static int kdb_ldap_create_principal (krb5_context context, krb5_principal
 138                                       princ, enum ap_op op, struct realm_info *pblock);
 139 
 140 
 141 static char *strdur(time_t duration);
 142 static int get_ticket_policy(krb5_ldap_realm_params *rparams, int *i, char *argv[],int argc);
 143 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);
 144 static krb5_error_code krb5_dbe_update_tl_data_new ( krb5_context context, krb5_db_entry *entry, krb5_tl_data *new_tl_data);
 145 
 146 #define ADMIN_LIFETIME 60*60*3 /* 3 hours */
 147 #define CHANGEPW_LIFETIME 60*5 /* 5 minutes */
 148 
 149 static int get_ticket_policy(rparams,i,argv,argc)
 150     krb5_ldap_realm_params *rparams;
 151     int *i;
 152     char *argv[];
 153     int argc;
 154 {
 155     time_t date;
 156     time_t now;
 157     int mask = 0;
 158     krb5_error_code retval = 0;
 159     krb5_boolean no_msg = FALSE;
 160 
 161     krb5_boolean print_usage = FALSE;
 162     /* Solaris Kerberos */
 163     char *me = progname;
 164 
 165     time(&now);
 166     if (!strcmp(argv[*i], "-maxtktlife")) {
 167         if (++(*i) > argc-1)
 168             goto err_usage;
 169         date = get_date(argv[*i]);
 170         if (date == (time_t)(-1)) {
 171             retval = EINVAL;
 172             com_err (me, retval, gettext("while providing time specification"));
 173             goto err_nomsg;
 174         }
 175         rparams->max_life = date-now;
 176         mask |= LDAP_REALM_MAXTICKETLIFE;
 177     }
 178 
 179 
 180     else if (!strcmp(argv[*i], "-maxrenewlife")) {
 181         if (++(*i) > argc-1)
 182             goto err_usage;
 183 
 184         date = get_date(argv[*i]);
 185         if (date == (time_t)(-1)) {
 186             retval = EINVAL;
 187             com_err (me, retval, gettext("while providing time specification"));
 188             goto err_nomsg;
 189         }
 190         rparams->max_renewable_life = date-now;
 191         mask |= LDAP_REALM_MAXRENEWLIFE;
 192     } else if (!strcmp((argv[*i] + 1), "allow_postdated")) {
 193         if (*(argv[*i]) == '+')
 194             rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_POSTDATED);
 195         else if (*(argv[*i]) == '-')
 196             rparams->tktflags |= KRB5_KDB_DISALLOW_POSTDATED;
 197         else
 198             goto err_usage;
 199 
 200         mask |= LDAP_REALM_KRBTICKETFLAGS;
 201     } else if (!strcmp((argv[*i] + 1), "allow_forwardable")) {
 202         if (*(argv[*i]) == '+')
 203             rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_FORWARDABLE);
 204 
 205         else if (*(argv[*i]) == '-')
 206             rparams->tktflags |= KRB5_KDB_DISALLOW_FORWARDABLE;
 207         else
 208             goto err_usage;
 209 
 210         mask |= LDAP_REALM_KRBTICKETFLAGS;
 211     } else if (!strcmp((argv[*i] + 1), "allow_renewable")) {
 212         if (*(argv[*i]) == '+')
 213             rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_RENEWABLE);
 214         else if (*(argv[*i]) == '-')
 215             rparams->tktflags |= KRB5_KDB_DISALLOW_RENEWABLE;
 216         else
 217             goto err_usage;
 218 
 219         mask |= LDAP_REALM_KRBTICKETFLAGS;
 220     } else if (!strcmp((argv[*i] + 1), "allow_proxiable")) {
 221         if (*(argv[*i]) == '+')
 222             rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_PROXIABLE);
 223         else if (*(argv[*i]) == '-')
 224             rparams->tktflags |= KRB5_KDB_DISALLOW_PROXIABLE;
 225         else
 226             goto err_usage;
 227 
 228         mask |= LDAP_REALM_KRBTICKETFLAGS;
 229     } else if (!strcmp((argv[*i] + 1), "allow_dup_skey")) {
 230         if (*(argv[*i]) == '+')
 231             rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_DUP_SKEY);
 232         else if (*(argv[*i]) == '-')
 233             rparams->tktflags |= KRB5_KDB_DISALLOW_DUP_SKEY;
 234         else
 235             goto err_usage;
 236 
 237         mask |= LDAP_REALM_KRBTICKETFLAGS;
 238     }
 239 
 240     else if (!strcmp((argv[*i] + 1), "requires_preauth")) {
 241         if (*(argv[*i]) == '+')
 242             rparams->tktflags |= KRB5_KDB_REQUIRES_PRE_AUTH;
 243         else if (*(argv[*i]) == '-')
 244             rparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PRE_AUTH);
 245         else
 246             goto err_usage;
 247 
 248         mask |= LDAP_REALM_KRBTICKETFLAGS;
 249     } else if (!strcmp((argv[*i] + 1), "requires_hwauth")) {
 250         if (*(argv[*i]) == '+')
 251             rparams->tktflags |= KRB5_KDB_REQUIRES_HW_AUTH;
 252         else if (*(argv[*i]) == '-')
 253             rparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_HW_AUTH);
 254         else
 255             goto err_usage;
 256 
 257         mask |= LDAP_REALM_KRBTICKETFLAGS;
 258     } else if (!strcmp((argv[*i] + 1), "allow_svr")) {
 259         if (*(argv[*i]) == '+')
 260             rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_SVR);
 261         else if (*(argv[*i]) == '-')
 262             rparams->tktflags |= KRB5_KDB_DISALLOW_SVR;
 263         else
 264             goto err_usage;
 265 
 266         mask |= LDAP_REALM_KRBTICKETFLAGS;
 267     } else if (!strcmp((argv[*i] + 1), "allow_tgs_req")) {
 268         if (*(argv[*i]) == '+')
 269             rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_TGT_BASED);
 270         else if (*(argv[*i]) == '-')
 271             rparams->tktflags |= KRB5_KDB_DISALLOW_TGT_BASED;
 272         else
 273             goto err_usage;
 274 
 275         mask |= LDAP_REALM_KRBTICKETFLAGS;
 276     } else if (!strcmp((argv[*i] + 1), "allow_tix")) {
 277         if (*(argv[*i]) == '+')
 278             rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_ALL_TIX);
 279         else if (*(argv[*i]) == '-')
 280             rparams->tktflags |= KRB5_KDB_DISALLOW_ALL_TIX;
 281         else
 282             goto err_usage;
 283 
 284         mask |= LDAP_REALM_KRBTICKETFLAGS;
 285     } else if (!strcmp((argv[*i] + 1), "needchange")) {
 286         if (*(argv[*i]) == '+')
 287             rparams->tktflags |= KRB5_KDB_REQUIRES_PWCHANGE;
 288         else if (*(argv[*i]) == '-')
 289             rparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PWCHANGE);
 290         else
 291             goto err_usage;
 292 
 293         mask |= LDAP_REALM_KRBTICKETFLAGS;
 294     } else if (!strcmp((argv[*i] + 1), "password_changing_service")) {
 295         if (*(argv[*i]) == '+')
 296             rparams->tktflags |= KRB5_KDB_PWCHANGE_SERVICE;
 297         else if (*(argv[*i]) == '-')
 298             rparams->tktflags &= (int)(~KRB5_KDB_PWCHANGE_SERVICE);
 299         else
 300             goto err_usage;
 301 
 302         mask |=LDAP_REALM_KRBTICKETFLAGS;
 303     }
 304 err_usage:
 305     print_usage = TRUE;
 306 
 307 err_nomsg:
 308     no_msg = TRUE;
 309 
 310     return mask;
 311 }
 312 
 313 /*
 314  * This function will create a realm on the LDAP Server, with
 315  * the specified attributes.
 316  */
 317 void kdb5_ldap_create(argc, argv)
 318     int argc;
 319     char *argv[];
 320 {
 321     krb5_error_code retval = 0;
 322     krb5_keyblock master_keyblock;
 323     krb5_ldap_realm_params *rparams = NULL;
 324     krb5_principal master_princ = NULL;
 325     kdb5_dal_handle *dal_handle = NULL;
 326     krb5_ldap_context *ldap_context=NULL;
 327     krb5_boolean realm_obj_created = FALSE;
 328     krb5_boolean create_complete = FALSE;
 329     krb5_boolean print_usage = FALSE;
 330     krb5_boolean no_msg = FALSE;
 331     char *oldcontainerref=NULL;
 332     char pw_str[1024];
 333     int do_stash = 0;
 334     int i = 0;
 335     int mask = 0, ret_mask = 0;
 336     char **list = NULL;
 337 #ifdef HAVE_EDIRECTORY
 338     int rightsmask = 0;
 339 #endif
 340 
 341     memset(&master_keyblock, 0, sizeof(master_keyblock));
 342 
 343     rparams = (krb5_ldap_realm_params *)malloc(
 344         sizeof(krb5_ldap_realm_params));
 345     if (rparams == NULL) {
 346         retval = ENOMEM;
 347         goto cleanup;
 348     }
 349     memset(rparams, 0, sizeof(krb5_ldap_realm_params));
 350 
 351     /* Parse the arguments */
 352     for (i = 1; i < argc; i++) {
 353         if (!strcmp(argv[i], "-subtrees")) {
 354             if (++i > argc-1)
 355                 goto err_usage;
 356 
 357             if(strncmp(argv[i], "", strlen(argv[i]))!=0) {
 358                 list = (char **) calloc(MAX_LIST_ENTRIES, sizeof(char *));
 359                 if (list == NULL) {
 360                     retval = ENOMEM;
 361                     goto cleanup;
 362                 }
 363                 if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) {
 364                     free(list);
 365                     list = NULL;
 366                     goto cleanup;
 367                 }
 368 
 369                 rparams->subtreecount=0;
 370                 while(list[rparams->subtreecount]!=NULL)
 371                     (rparams->subtreecount)++;
 372                 rparams->subtree = list;
 373             } else if(strncmp(argv[i], "", strlen(argv[i]))==0) {
 374                  /* dont allow subtree value to be set at the root(NULL, "") of the tree */
 375                  /* Solaris Kerberos */
 376                  com_err(progname, EINVAL,
 377                           gettext("for subtree while creating realm '%s'"),
 378                            global_params.realm);
 379                  goto err_nomsg;
 380             }
 381             rparams->subtree[rparams->subtreecount] = NULL;
 382             mask |= LDAP_REALM_SUBTREE;
 383         } else if (!strcmp(argv[i], "-containerref")) {
 384             if (++i > argc-1)
 385                 goto err_usage;
 386             if(strncmp(argv[i], "", strlen(argv[i]))==0) {
 387                  /* dont allow containerref value to be set at the root(NULL, "") of the tree */
 388                  /* Solaris Kerberos */
 389                  com_err(progname, EINVAL,
 390                           gettext("for container reference while creating realm '%s'"),
 391                            global_params.realm);
 392                  goto err_nomsg;
 393             }
 394             rparams->containerref = strdup(argv[i]);
 395             if (rparams->containerref == NULL) {
 396                 retval = ENOMEM;
 397                 goto cleanup;
 398             }
 399             mask |= LDAP_REALM_CONTREF;
 400         } else if (!strcmp(argv[i], "-sscope")) {
 401             if (++i > argc-1)
 402                 goto err_usage;
 403             /* Possible values for search scope are
 404              * one (or 1) and sub (or 2)
 405              */
 406             if (!strcasecmp(argv[i], "one")) {
 407                 rparams->search_scope = 1;
 408             } else if (!strcasecmp(argv[i], "sub")) {
 409                 rparams->search_scope = 2;
 410             } else {
 411                 rparams->search_scope = atoi(argv[i]);
 412                 if ((rparams->search_scope != 1) &&
 413                     (rparams->search_scope != 2)) {
 414                     /* Solaris Kerberos */
 415                     com_err(progname, EINVAL,
 416                             gettext("invalid search scope while creating realm '%s'"),
 417                             global_params.realm);
 418                     goto err_nomsg;
 419                 }
 420             }
 421             mask |= LDAP_REALM_SEARCHSCOPE;
 422         }
 423 #ifdef HAVE_EDIRECTORY
 424         else if (!strcmp(argv[i], "-kdcdn")) {
 425             if (++i > argc-1)
 426                 goto err_usage;
 427             rparams->kdcservers = (char **)malloc(
 428                 sizeof(char *) * MAX_LIST_ENTRIES);
 429             if (rparams->kdcservers == NULL) {
 430                 retval = ENOMEM;
 431                 goto cleanup;
 432             }
 433             memset(rparams->kdcservers, 0, sizeof(char*)*MAX_LIST_ENTRIES);
 434             if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
 435                                           rparams->kdcservers))) {
 436                 goto cleanup;
 437             }
 438             mask |= LDAP_REALM_KDCSERVERS;
 439         } else if (!strcmp(argv[i], "-admindn")) {
 440             if (++i > argc-1)
 441                 goto err_usage;
 442             rparams->adminservers = (char **)malloc(
 443                 sizeof(char *) * MAX_LIST_ENTRIES);
 444             if (rparams->adminservers == NULL) {
 445                 retval = ENOMEM;
 446                 goto cleanup;
 447             }
 448             memset(rparams->adminservers, 0, sizeof(char*)*MAX_LIST_ENTRIES);
 449             if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
 450                                           rparams->adminservers))) {
 451                 goto cleanup;
 452             }
 453             mask |= LDAP_REALM_ADMINSERVERS;
 454         } else if (!strcmp(argv[i], "-pwddn")) {
 455             if (++i > argc-1)
 456                 goto err_usage;
 457             rparams->passwdservers = (char **)malloc(
 458                 sizeof(char *) * MAX_LIST_ENTRIES);
 459             if (rparams->passwdservers == NULL) {
 460                 retval = ENOMEM;
 461                 goto cleanup;
 462             }
 463             memset(rparams->passwdservers, 0, sizeof(char*)*MAX_LIST_ENTRIES);
 464             if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
 465                                           rparams->passwdservers))) {
 466                 goto cleanup;
 467             }
 468             mask |= LDAP_REALM_PASSWDSERVERS;
 469         }
 470 #endif
 471         else if (!strcmp(argv[i], "-s")) {
 472             do_stash = 1;
 473         } else if ((ret_mask= get_ticket_policy(rparams,&i,argv,argc)) !=0) {
 474             mask|=ret_mask;
 475         }
 476 
 477         else {
 478             printf(gettext("'%s' is an invalid option\n"), argv[i]);
 479             goto err_usage;
 480         }
 481     }
 482 
 483     /* If the default enctype/salttype is not provided, use the
 484      * default values and also add to the list of supported
 485      * enctypes/salttype
 486      */
 487 
 488     rblock.max_life = global_params.max_life;
 489     rblock.max_rlife = global_params.max_rlife;
 490     rblock.expiration = global_params.expiration;
 491     rblock.flags = global_params.flags;
 492     rblock.nkslist = global_params.num_keysalts;
 493     rblock.kslist = global_params.keysalts;
 494 
 495     krb5_princ_set_realm_data(util_context, &db_create_princ, global_params.realm);
 496     krb5_princ_set_realm_length(util_context, &db_create_princ, strlen(global_params.realm));
 497 
 498     printf(gettext("Initializing database for realm '%s'\n"), global_params.realm);
 499 
 500     if (!mkey_password) {
 501         unsigned int pw_size;
 502         printf(gettext("You will be prompted for the database Master Password.\n"));
 503         printf(gettext("It is important that you NOT FORGET this password.\n"));
 504         fflush(stdout);
 505 
 506         pw_size = sizeof (pw_str);
 507         memset(pw_str, 0, pw_size);
 508 
 509         retval = krb5_read_password(util_context, KRB5_KDC_MKEY_1, KRB5_KDC_MKEY_2,
 510                                     pw_str, &pw_size);
 511         if (retval) {
 512             /* Solaris Kerberos */
 513             com_err(progname, retval, gettext("while reading master key from keyboard"));
 514             goto err_nomsg;
 515         }
 516         mkey_password = pw_str;
 517     }
 518 
 519     rparams->mkey.enctype = global_params.enctype;
 520     /* We are sure that 'mkey_password' is a regular string ... */
 521     rparams->mkey.length = strlen(mkey_password) + 1;
 522     rparams->mkey.contents = (krb5_octet *)strdup(mkey_password);
 523     if (rparams->mkey.contents == NULL) {
 524         retval = ENOMEM;
 525         goto cleanup;
 526     }
 527 
 528     rparams->realm_name = strdup(global_params.realm);
 529     if (rparams->realm_name == NULL) {
 530         retval = ENOMEM;
 531         /* Solaris Kerberos */
 532         com_err(progname, ENOMEM, gettext("while creating realm '%s'"),
 533                 global_params.realm);
 534         goto err_nomsg;
 535     }
 536 
 537     dal_handle = (kdb5_dal_handle *) util_context->db_context;
 538     ldap_context = (krb5_ldap_context *) dal_handle->db_context;
 539     if (!ldap_context) {
 540         retval = EINVAL;
 541         goto cleanup;
 542     }
 543 
 544     /* read the kerberos container */
 545     if ((retval=krb5_ldap_read_krbcontainer_params (util_context,
 546                                                     &(ldap_context->krbcontainer))) == KRB5_KDB_NOENTRY) {
 547         /* Prompt the user for entering the DN of Kerberos container */
 548         char krb_location[MAX_KRB_CONTAINER_LEN];
 549         krb5_ldap_krbcontainer_params kparams;
 550         int krb_location_len = 0;
 551         memset(&kparams, 0, sizeof(kparams));
 552 
 553         /* Read the kerberos container location from configuration file */
 554         if (ldap_context->conf_section) {
 555             if ((retval=profile_get_string(util_context->profile,
 556                                            KDB_MODULE_SECTION, ldap_context->conf_section,
 557                                            "ldap_kerberos_container_dn", NULL,
 558                                            &kparams.DN)) != 0) {
 559                 goto cleanup;
 560             }
 561         }
 562         if (kparams.DN == NULL) {
 563             if ((retval=profile_get_string(util_context->profile,
 564                                            KDB_MODULE_DEF_SECTION,
 565                                            "ldap_kerberos_container_dn", NULL,
 566                                            NULL, &kparams.DN)) != 0) {
 567                 goto cleanup;
 568             }
 569         }
 570 
 571         printf(gettext("\nKerberos container is missing. Creating now...\n"));
 572         if (kparams.DN == NULL) {
 573 #ifdef HAVE_EDIRECTORY
 574             printf(gettext("Enter DN of Kerberos container [cn=Kerberos,cn=Security]: "));
 575 #else
 576             printf(gettext("Enter DN of Kerberos container: "));
 577 #endif
 578             if (fgets(krb_location, MAX_KRB_CONTAINER_LEN, stdin) != NULL) {
 579                 /* Remove the newline character at the end */
 580                 krb_location_len = strlen(krb_location);
 581                 if ((krb_location[krb_location_len - 1] == '\n') ||
 582                     (krb_location[krb_location_len - 1] == '\r')) {
 583                     krb_location[krb_location_len - 1] = '\0';
 584                     krb_location_len--;
 585                 }
 586                 /* If the user has not given any input, take the default location */
 587                 else if (krb_location[0] == '\0')
 588                     kparams.DN = NULL;
 589                 else
 590                     kparams.DN = krb_location;
 591             } else
 592                 kparams.DN = NULL;
 593         }
 594 
 595         /* create the kerberos container */
 596         retval = krb5_ldap_create_krbcontainer(util_context,
 597                                                ((kparams.DN != NULL) ? &kparams : NULL));
 598         if (retval)
 599             goto cleanup;
 600 
 601         retval = krb5_ldap_read_krbcontainer_params(util_context,
 602                                                     &(ldap_context->krbcontainer));
 603         if (retval) {
 604             /* Solaris Kerberos */
 605             com_err(progname, retval, gettext("while reading kerberos container information"));
 606             goto cleanup;
 607         }
 608     } else if (retval) {
 609         /* Solaris Kerberos */
 610         com_err(progname, retval, gettext("while reading kerberos container information"));
 611         goto cleanup;
 612     }
 613 
 614     if ((retval = krb5_ldap_create_realm(util_context,
 615                                          /* global_params.realm, */ rparams, mask))) {
 616         goto cleanup;
 617     }
 618 
 619     /* We just created the Realm container. Here starts our transaction tracking */
 620     realm_obj_created = TRUE;
 621 
 622     if ((retval = krb5_ldap_read_realm_params(util_context,
 623                                               global_params.realm,
 624                                               &(ldap_context->lrparams),
 625                                               &mask))) {
 626         /* Solaris Kerberos */
 627         com_err(progname, retval, gettext("while reading information of realm '%s'"),
 628                 global_params.realm);
 629         goto err_nomsg;
 630     }
 631     ldap_context->lrparams->realm_name = strdup(global_params.realm);
 632     if (ldap_context->lrparams->realm_name == NULL) {
 633         retval = ENOMEM;
 634         goto cleanup;
 635     }
 636 
 637     /* assemble & parse the master key name */
 638     if ((retval = krb5_db_setup_mkey_name(util_context,
 639                                           global_params.mkey_name,
 640                                           global_params.realm,
 641                                           0, &master_princ))) {
 642         /* Solaris Kerberos */
 643         com_err(progname, retval, gettext("while setting up master key name"));
 644         goto err_nomsg;
 645     }
 646 
 647     /* Obtain master key from master password */
 648     {
 649         krb5_data master_salt, pwd;
 650 
 651         pwd.data = mkey_password;
 652         pwd.length = strlen(mkey_password);
 653         retval = krb5_principal2salt(util_context, master_princ, &master_salt);
 654         if (retval) {
 655             /* Solaris Kerberos */
 656             com_err(progname, retval, gettext("while calculating master key salt"));
 657             goto err_nomsg;
 658         }
 659 
 660         retval = krb5_c_string_to_key(util_context, rparams->mkey.enctype,
 661                                       &pwd, &master_salt, &master_keyblock);
 662 
 663         if (master_salt.data)
 664             free(master_salt.data);
 665 
 666         if (retval) {
 667             /* Solaris Kerberos */
 668             com_err(progname, retval, gettext("while transforming master key from password"));
 669             goto err_nomsg;
 670         }
 671 
 672     }
 673 
 674     rblock.key = &master_keyblock;
 675     ldap_context->lrparams->mkey = master_keyblock;
 676     ldap_context->lrparams->mkey.contents = (krb5_octet *) malloc
 677         (master_keyblock.length);
 678     if (ldap_context->lrparams->mkey.contents == NULL) {
 679         retval = ENOMEM;
 680         goto cleanup;
 681     }
 682     memcpy (ldap_context->lrparams->mkey.contents, master_keyblock.contents,
 683             master_keyblock.length);
 684 
 685     /* Create special principals inside the realm subtree */
 686     {
 687         char princ_name[MAX_PRINC_SIZE];
 688         krb5_principal_data tgt_princ = {
 689             0,                                  /* magic number */
 690             {0, 0, 0},                          /* krb5_data realm */
 691             tgt_princ_entries,                  /* krb5_data *data */
 692             2,                                  /* int length */
 693             KRB5_NT_SRV_INST                    /* int type */
 694         };
 695         krb5_principal p, temp_p=NULL;
 696 
 697         krb5_princ_set_realm_data(util_context, &tgt_princ, global_params.realm);
 698         krb5_princ_set_realm_length(util_context, &tgt_princ, strlen(global_params.realm));
 699         krb5_princ_component(util_context, &tgt_princ,1)->data = global_params.realm;
 700         krb5_princ_component(util_context, &tgt_princ,1)->length = strlen(global_params.realm);
 701         /* The container reference value is set to NULL, to avoid service principals
 702          * getting created within the container reference at realm creation */
 703         if (ldap_context->lrparams->containerref != NULL) {
 704             oldcontainerref = ldap_context->lrparams->containerref;
 705             ldap_context->lrparams->containerref = NULL;
 706         }
 707 
 708         /* Create 'K/M' ... */
 709         rblock.flags |= KRB5_KDB_DISALLOW_ALL_TIX;
 710         if ((retval = kdb_ldap_create_principal(util_context, master_princ, MASTER_KEY, &rblock))) {
 711             /* Solaris Kerberos */
 712             com_err(progname, retval, gettext("while adding entries to the database"));
 713             goto err_nomsg;
 714         }
 715 
 716         /* Create 'krbtgt' ... */
 717         rblock.flags = 0; /* reset the flags */
 718         if ((retval = kdb_ldap_create_principal(util_context, &tgt_princ, TGT_KEY, &rblock))) {
 719             /* Solaris Kerberos */
 720             com_err(progname, retval, gettext("while adding entries to the database"));
 721             goto err_nomsg;
 722         }
 723         /*
 724          * Solaris Kerberos:
 725          * The kadmin/admin principal is unused on Solaris. This principal is used
 726          * in AUTH_GSSAPI but Solaris doesn't support AUTH_GSSAPI. RPCSEC_GSS can only
 727          * be used with host-based principals. 
 728          *
 729          */
 730 #if 0 /* ************ Begin IFDEF'ed OUT ***************************** */
 731         /* Create 'kadmin/admin' ... */
 732         snprintf(princ_name, sizeof(princ_name), "%s@%s", KADM5_ADMIN_SERVICE, global_params.realm);
 733         if ((retval = krb5_parse_name(util_context, princ_name, &p))) {
 734             /* Solaris Kerberos */
 735             com_err(progname, retval, gettext("while adding entries to the database"));
 736             goto err_nomsg;
 737         }
 738         rblock.max_life = ADMIN_LIFETIME;
 739         rblock.flags = KRB5_KDB_DISALLOW_TGT_BASED;
 740         if ((retval = kdb_ldap_create_principal(util_context, p, TGT_KEY, &rblock))) {
 741             krb5_free_principal(util_context, p);
 742             /* Solaris Kerberos */
 743             com_err(progname, retval, gettext("while adding entries to the database"));
 744             goto err_nomsg;
 745         }
 746         krb5_free_principal(util_context, p);
 747 #endif /* ************** END IFDEF'ed OUT ***************************** */
 748 
 749         /* Create 'kadmin/changepw' ... */
 750         snprintf(princ_name, sizeof(princ_name), "%s@%s", KADM5_CHANGEPW_SERVICE, global_params.realm);
 751         if ((retval = krb5_parse_name(util_context, princ_name, &p))) {
 752             /* Solaris Kerberos */
 753             com_err(progname, retval, gettext("while adding entries to the database"));
 754             goto err_nomsg;
 755         }
 756         rblock.max_life = CHANGEPW_LIFETIME;
 757         rblock.flags = KRB5_KDB_DISALLOW_TGT_BASED | KRB5_KDB_PWCHANGE_SERVICE;
 758         if ((retval = kdb_ldap_create_principal(util_context, p, TGT_KEY, &rblock))) {
 759             krb5_free_principal(util_context, p);
 760             /* Solaris Kerberos */
 761             com_err(progname, retval, gettext("while adding entries to the database"));
 762             goto err_nomsg;
 763         }
 764         krb5_free_principal(util_context, p);
 765 
 766         /* Create 'kadmin/history' ... */
 767         snprintf(princ_name, sizeof(princ_name), "%s@%s", KADM5_HIST_PRINCIPAL, global_params.realm);
 768         if ((retval = krb5_parse_name(util_context, princ_name, &p))) {
 769             /* Solaris Kerberos */
 770             com_err(progname, retval, gettext("while adding entries to the database"));
 771             goto err_nomsg;
 772         }
 773         rblock.max_life = global_params.max_life;
 774         rblock.flags = 0;
 775         if ((retval = kdb_ldap_create_principal(util_context, p, TGT_KEY, &rblock))) {
 776             krb5_free_principal(util_context, p);
 777             /* Solaris Kerberos */
 778             com_err(progname, retval, gettext("while adding entries to the database"));
 779             goto err_nomsg;
 780         }
 781         krb5_free_principal(util_context, p);
 782 
 783         /* Create 'kadmin/<hostname>' ... */
 784         if ((retval=krb5_sname_to_principal(util_context, NULL, KADM5_ADMIN_HOST_SERVICE, KRB5_NT_SRV_HST, &p))) {
 785             /* Solaris Kerberos */
 786             com_err(progname, retval, gettext("krb5_sname_to_principal, while adding entries to the database"));
 787             goto err_nomsg;
 788         }
 789 
 790         if ((retval=krb5_copy_principal(util_context, p, &temp_p))) {
 791             /* Solaris Kerberos */
 792             com_err(progname, retval, gettext("krb5_copy_principal, while adding entries to the database"));
 793             goto err_nomsg;
 794         }
 795 
 796         /* change the realm portion to the default realm */
 797         free(temp_p->realm.data);
 798         temp_p->realm.length = strlen(util_context->default_realm);
 799         temp_p->realm.data = strdup(util_context->default_realm);
 800         if (temp_p->realm.data == NULL) {
 801             /* Solaris Kerberos */
 802             com_err(progname, ENOMEM, gettext("while adding entries to the database"));
 803             goto err_nomsg;
 804         }
 805 
 806         rblock.max_life = ADMIN_LIFETIME;
 807         rblock.flags = KRB5_KDB_DISALLOW_TGT_BASED;
 808         if ((retval = kdb_ldap_create_principal(util_context, temp_p, TGT_KEY, &rblock))) {
 809             krb5_free_principal(util_context, p);
 810             /* Solaris Kerberos */
 811             com_err(progname, retval, gettext("while adding entries to the database"));
 812             goto err_nomsg;
 813         }
 814         krb5_free_principal(util_context, temp_p);
 815         krb5_free_principal(util_context, p);
 816 
 817         /* Solaris Kerberos: Create 'changepw/<hostname>' ... */
 818         if ((retval=krb5_sname_to_principal(util_context, NULL, KADM5_CHANGEPW_HOST_SERVICE, KRB5_NT_SRV_HST, &p))) {
 819             /* Solaris Kerberos */
 820             com_err(progname, retval, gettext("krb5_sname_to_principal, while adding entries to the database"));
 821             goto err_nomsg;
 822         }
 823 
 824         if ((retval=krb5_copy_principal(util_context, p, &temp_p))) {
 825             /* Solaris Kerberos */
 826             com_err(progname, retval, gettext("krb5_copy_principal, while adding entries to the database"));
 827             goto err_nomsg;
 828         }
 829 
 830         /* change the realm portion to the default realm */
 831         free(temp_p->realm.data);
 832         temp_p->realm.length = strlen(util_context->default_realm);
 833         temp_p->realm.data = strdup(util_context->default_realm);
 834         if (temp_p->realm.data == NULL) {
 835             /* Solaris Kerberos */
 836             com_err(progname, ENOMEM, gettext("while adding entries to the database"));
 837             goto err_nomsg;
 838         }
 839 
 840         rblock.max_life = ADMIN_LIFETIME;
 841         rblock.flags = KRB5_KDB_DISALLOW_TGT_BASED | KRB5_KDB_PWCHANGE_SERVICE;
 842         if ((retval = kdb_ldap_create_principal(util_context, temp_p, TGT_KEY, &rblock))) {
 843             krb5_free_principal(util_context, p);
 844             /* Solaris Kerberos */
 845             com_err(progname, retval, gettext("while adding entries to the database"));
 846             goto err_nomsg;
 847         }
 848         krb5_free_principal(util_context, temp_p);
 849         krb5_free_principal(util_context, p);
 850 
 851         if (oldcontainerref != NULL) {
 852             ldap_context->lrparams->containerref = oldcontainerref;
 853             oldcontainerref=NULL;
 854         }
 855     }
 856 
 857 #ifdef HAVE_EDIRECTORY
 858     if ((mask & LDAP_REALM_KDCSERVERS) || (mask & LDAP_REALM_ADMINSERVERS) ||
 859         (mask & LDAP_REALM_PASSWDSERVERS)) {
 860 
 861         printf(gettext("Changing rights for the service object. Please wait ... "));
 862         fflush(stdout);
 863 
 864         rightsmask =0;
 865         rightsmask |= LDAP_REALM_RIGHTS;
 866         rightsmask |= LDAP_SUBTREE_RIGHTS;
 867         if ((rparams != NULL) && (rparams->kdcservers != NULL)) {
 868             for (i=0; (rparams->kdcservers[i] != NULL); i++) {
 869                 if ((retval=krb5_ldap_add_service_rights(util_context,
 870                                                          LDAP_KDC_SERVICE, rparams->kdcservers[i],
 871                                                          rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
 872                     printf(gettext("failed\n"));
 873                     /* Solaris Kerberos */
 874                     com_err(progname, retval, gettext("while assigning rights to '%s'"),
 875                             rparams->realm_name);
 876                     goto err_nomsg;
 877                 }
 878             }
 879         }
 880 
 881         rightsmask = 0;
 882         rightsmask |= LDAP_REALM_RIGHTS;
 883         rightsmask |= LDAP_SUBTREE_RIGHTS;
 884         if ((rparams != NULL) && (rparams->adminservers != NULL)) {
 885             for (i=0; (rparams->adminservers[i] != NULL); i++) {
 886                 if ((retval=krb5_ldap_add_service_rights(util_context,
 887                                                          LDAP_ADMIN_SERVICE, rparams->adminservers[i],
 888                                                          rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
 889                     printf(gettext("failed\n"));
 890                     /* Solaris Kerberos */
 891                     com_err(progname, retval, gettext("while assigning rights to '%s'"),
 892                             rparams->realm_name);
 893                     goto err_nomsg;
 894                 }
 895             }
 896         }
 897 
 898         rightsmask = 0;
 899         rightsmask |= LDAP_REALM_RIGHTS;
 900         rightsmask |= LDAP_SUBTREE_RIGHTS;
 901         if ((rparams != NULL) && (rparams->passwdservers != NULL)) {
 902             for (i=0; (rparams->passwdservers[i] != NULL); i++) {
 903                 if ((retval=krb5_ldap_add_service_rights(util_context,
 904                                                          LDAP_PASSWD_SERVICE, rparams->passwdservers[i],
 905                                                          rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
 906                     printf(gettext("failed\n"));
 907                     /* Solaris Kerberos */
 908                     com_err(progname, retval, gettext("while assigning rights to '%s'"),
 909                             rparams->realm_name);
 910                     goto err_nomsg;
 911                 }
 912             }
 913         }
 914 
 915         printf(gettext("done\n"));
 916     }
 917 #endif
 918     /* The Realm creation is completed. Here is the end of transaction */
 919     create_complete = TRUE;
 920 
 921     /* Stash the master key only if '-s' option is specified */
 922     if (do_stash || global_params.mask & KADM5_CONFIG_STASH_FILE) {
 923         retval = krb5_def_store_mkey(util_context,
 924                                      global_params.stash_file,
 925                                      master_princ,
 926                                      &master_keyblock, NULL);
 927         if (retval) {
 928             /* Solaris Kerberos */
 929             com_err(progname, errno, gettext("while storing key"));
 930             printf(gettext("Warning: couldn't stash master key.\n"));
 931         }
 932     }
 933 
 934     goto cleanup;
 935 
 936 
 937 err_usage:
 938     print_usage = TRUE;
 939 
 940 err_nomsg:
 941     no_msg = TRUE;
 942 
 943 cleanup:
 944     /* If the Realm creation is not complete, do the roll-back here */
 945     if ((realm_obj_created) && (!create_complete))
 946         krb5_ldap_delete_realm(util_context, global_params.realm);
 947 
 948     if (rparams)
 949         krb5_ldap_free_realm_params(rparams);
 950 
 951     memset (pw_str, 0, sizeof (pw_str));
 952 
 953     if (print_usage)
 954         db_usage(CREATE_REALM);
 955 
 956     if (retval) {
 957         if (!no_msg) {
 958             /* Solaris Kerberos */
 959             com_err(progname, retval, gettext("while creating realm '%s'"),
 960                     global_params.realm);
 961         }
 962         exit_status++;
 963     }
 964 
 965     return;
 966 }
 967 
 968 
 969 /*
 970  * This function will modify the attributes of a given realm object
 971  */
 972 void kdb5_ldap_modify(argc, argv)
 973     int argc;
 974     char *argv[];
 975 {
 976     krb5_error_code retval = 0;
 977     krb5_ldap_realm_params *rparams = NULL;
 978     krb5_boolean print_usage = FALSE;
 979     krb5_boolean no_msg = FALSE;
 980     kdb5_dal_handle *dal_handle = NULL;
 981     krb5_ldap_context *ldap_context=NULL;
 982     int i = 0;
 983     int mask = 0, rmask = 0, ret_mask = 0;
 984     char **slist = {NULL};
 985 #ifdef HAVE_EDIRECTORY
 986     int j = 0;
 987     char *list[MAX_LIST_ENTRIES];
 988     int existing_entries = 0, list_entries = 0;
 989     int newkdcdn = 0, newadmindn = 0, newpwddn = 0;
 990     char **tempstr = NULL;
 991     char **oldkdcdns = NULL;
 992     char **oldadmindns = NULL;
 993     char **oldpwddns = NULL;
 994     char **newkdcdns = NULL;
 995     char **newsubtrees = NULL;
 996     char **newadmindns = NULL;
 997     char **newpwddns = NULL;
 998     char **oldsubtrees = {NULL};
 999     int rightsmask = 0;
1000     int subtree_changed = 0;
1001 #endif
1002 
1003     dal_handle = (kdb5_dal_handle *) util_context->db_context;
1004     ldap_context = (krb5_ldap_context *) dal_handle->db_context;
1005     if (!(ldap_context)) {
1006         retval = EINVAL;
1007         goto cleanup;
1008     }
1009 
1010     if ((retval = krb5_ldap_read_krbcontainer_params(util_context,
1011                                                      &(ldap_context->krbcontainer)))) {
1012         /* Solaris Kerberos */
1013         com_err(progname, retval, gettext("while reading Kerberos container information"));
1014         goto err_nomsg;
1015     }
1016 
1017     retval = krb5_ldap_read_realm_params(util_context,
1018                                          global_params.realm, &rparams, &rmask);
1019     if (retval)
1020         goto cleanup;
1021     /* Parse the arguments */
1022     for (i = 1; i < argc; i++) {
1023         int k = 0;
1024         if (!strcmp(argv[i], "-subtrees")) {
1025             if (++i > argc-1)
1026                 goto err_usage;
1027 
1028             if (rmask & LDAP_REALM_SUBTREE) {
1029                 if (rparams->subtree) {
1030 #ifdef HAVE_EDIRECTORY
1031                     oldsubtrees =  (char **) calloc(rparams->subtreecount+1, sizeof(char *));
1032                     if (oldsubtrees == NULL) {
1033                         retval = ENOMEM;
1034                         goto cleanup;
1035                     }
1036                     for(k=0; rparams->subtree[k]!=NULL && rparams->subtreecount; k++) {
1037                         oldsubtrees[k] = strdup(rparams->subtree[k]);
1038                         if( oldsubtrees[k] == NULL ) {
1039                             retval = ENOMEM;
1040                             goto cleanup;
1041                         }
1042                     }
1043 #endif
1044                     for(k=0; k<rparams->subtreecount && rparams->subtree[k]; k++)
1045                         free(rparams->subtree[k]);
1046                     rparams->subtreecount=0;
1047                 }
1048             }
1049             if (strncmp(argv[i] ,"", strlen(argv[i]))!=0) {
1050                 slist =  (char **) calloc(MAX_LIST_ENTRIES, sizeof(char *));
1051                 if (slist == NULL) {
1052                     retval = ENOMEM;
1053                     goto cleanup;
1054                 }
1055                 if (( retval = krb5_parse_list(argv[i], LIST_DELIMITER, slist))) {
1056                     free(slist);
1057                     slist = NULL;
1058                     goto cleanup;
1059                 }
1060 
1061                 rparams->subtreecount=0;
1062                 while(slist[rparams->subtreecount]!=NULL)
1063                     (rparams->subtreecount)++;
1064                 rparams->subtree =  slist;
1065             } else if(strncmp(argv[i], "", strlen(argv[i]))==0) {
1066                  /* dont allow subtree value to be set at the root(NULL, "") of the tree */
1067                     /* Solaris Kerberos */
1068                     com_err(progname, EINVAL,
1069                             gettext("for subtree while modifying realm '%s'"),
1070                             global_params.realm);
1071                     goto err_nomsg;
1072             }
1073             rparams->subtree[rparams->subtreecount] = NULL;
1074             mask |= LDAP_REALM_SUBTREE;
1075         } else if (!strncmp(argv[i], "-containerref", strlen(argv[i]))) {
1076             if (++i > argc-1)
1077                 goto err_usage;
1078             if(strncmp(argv[i], "", strlen(argv[i]))==0) {
1079                  /* dont allow containerref value to be set at the root(NULL, "") of the tree */
1080                  /* Solaris Kerberos */
1081                  com_err(progname, EINVAL,
1082                           gettext("for container reference while modifying realm '%s'"),
1083                            global_params.realm);
1084                  goto err_nomsg;
1085             }
1086             rparams->containerref = strdup(argv[i]);
1087             if (rparams->containerref == NULL) {
1088                 retval = ENOMEM;
1089                 goto cleanup;
1090             }
1091             mask |= LDAP_REALM_CONTREF;
1092         } else if (!strcmp(argv[i], "-sscope")) {
1093             if (++i > argc-1)
1094                 goto err_usage;
1095             /* Possible values for search scope are
1096              * one (or 1) and sub (or 2)
1097              */
1098             if (strcasecmp(argv[i], "one") == 0) {
1099                 rparams->search_scope = 1;
1100             } else if (strcasecmp(argv[i], "sub") == 0) {
1101                 rparams->search_scope = 2;
1102             } else {
1103                 rparams->search_scope = atoi(argv[i]);
1104                 if ((rparams->search_scope != 1) &&
1105                     (rparams->search_scope != 2)) {
1106                     retval = EINVAL;
1107                     /* Solaris Kerberos */
1108                     com_err(progname, retval,
1109                             gettext("specified for search scope while modifying information of realm '%s'"),
1110                             global_params.realm);
1111                     goto err_nomsg;
1112                 }
1113             }
1114             mask |= LDAP_REALM_SEARCHSCOPE;
1115         }
1116 #ifdef HAVE_EDIRECTORY
1117         else if (!strcmp(argv[i], "-kdcdn")) {
1118             if (++i > argc-1)
1119                 goto err_usage;
1120 
1121             if ((rmask & LDAP_REALM_KDCSERVERS) && (rparams->kdcservers)) {
1122                 if (!oldkdcdns) {
1123                     /* Store the old kdc dns list for removing rights */
1124                     oldkdcdns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
1125                     if (oldkdcdns == NULL) {
1126                         retval = ENOMEM;
1127                         goto cleanup;
1128                     }
1129 
1130                     for (j=0; rparams->kdcservers[j] != NULL; j++) {
1131                         oldkdcdns[j] = strdup(rparams->kdcservers[j]);
1132                         if (oldkdcdns[j] == NULL) {
1133                             retval = ENOMEM;
1134                             goto cleanup;
1135                         }
1136                     }
1137                     oldkdcdns[j] = NULL;
1138                 }
1139 
1140                 krb5_free_list_entries(rparams->kdcservers);
1141                 free(rparams->kdcservers);
1142             }
1143 
1144             rparams->kdcservers = (char **)malloc(
1145                 sizeof(char *) * MAX_LIST_ENTRIES);
1146             if (rparams->kdcservers == NULL) {
1147                 retval = ENOMEM;
1148                 goto cleanup;
1149             }
1150             memset(rparams->kdcservers, 0, sizeof(char *)*MAX_LIST_ENTRIES);
1151             if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
1152                                           rparams->kdcservers))) {
1153                 goto cleanup;
1154             }
1155             mask |= LDAP_REALM_KDCSERVERS;
1156             /* Going to replace the existing value by this new value. Hence
1157              * setting flag indicating that add or clear options will be ignored
1158              */
1159             newkdcdn = 1;
1160         } else if (!strcmp(argv[i], "-clearkdcdn")) {
1161             if (++i > argc-1)
1162                 goto err_usage;
1163             if ((!newkdcdn) && (rmask & LDAP_REALM_KDCSERVERS) && (rparams->kdcservers)) {
1164                 if (!oldkdcdns) {
1165                     /* Store the old kdc dns list for removing rights */
1166                     oldkdcdns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
1167                     if (oldkdcdns == NULL) {
1168                         retval = ENOMEM;
1169                         goto cleanup;
1170                     }
1171 
1172                     for (j=0; rparams->kdcservers[j] != NULL; j++) {
1173                         oldkdcdns[j] = strdup(rparams->kdcservers[j]);
1174                         if (oldkdcdns[j] == NULL) {
1175                             retval = ENOMEM;
1176                             goto cleanup;
1177                         }
1178                     }
1179                     oldkdcdns[j] = NULL;
1180                 }
1181 
1182                 memset(list, 0, sizeof(char *) * MAX_LIST_ENTRIES);
1183                 if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) {
1184                     goto cleanup;
1185                 }
1186                 list_modify_str_array(&rparams->kdcservers, (const char **)list,
1187                                       LIST_MODE_DELETE);
1188                 mask |= LDAP_REALM_KDCSERVERS;
1189                 krb5_free_list_entries(list);
1190             }
1191         } else if (!strcmp(argv[i], "-addkdcdn")) {
1192             if (++i > argc-1)
1193                 goto err_usage;
1194             if (!newkdcdn) {
1195                 if ((rmask & LDAP_REALM_KDCSERVERS) && (rparams->kdcservers) && (!oldkdcdns)) {
1196                     /* Store the old kdc dns list for removing rights */
1197                     oldkdcdns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
1198                     if (oldkdcdns == NULL) {
1199                         retval = ENOMEM;
1200                         goto cleanup;
1201                     }
1202 
1203                     for (j = 0; rparams->kdcservers[j] != NULL; j++) {
1204                         oldkdcdns[j] = strdup(rparams->kdcservers[j]);
1205                         if (oldkdcdns[j] == NULL) {
1206                             retval = ENOMEM;
1207                             goto cleanup;
1208                         }
1209                     }
1210                     oldkdcdns[j] = NULL;
1211                 }
1212 
1213                 memset(list, 0, sizeof(char *) * MAX_LIST_ENTRIES);
1214                 if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) {
1215                     goto cleanup;
1216                 }
1217                 existing_entries = list_count_str_array(rparams->kdcservers);
1218                 list_entries = list_count_str_array(list);
1219                 if (rmask & LDAP_REALM_KDCSERVERS) {
1220                     tempstr = (char **)realloc(
1221                         rparams->kdcservers,
1222                         sizeof(char *) * (existing_entries+list_entries+1));
1223                     if (tempstr == NULL) {
1224                         retval = ENOMEM;
1225                         goto cleanup;
1226                     }
1227                     rparams->kdcservers = tempstr;
1228                 } else {
1229                     rparams->kdcservers = (char **)malloc(sizeof(char *) * (list_entries+1));
1230                     if (rparams->kdcservers == NULL) {
1231                         retval = ENOMEM;
1232                         goto cleanup;
1233                     }
1234                     memset(rparams->kdcservers, 0, sizeof(char *) * (list_entries+1));
1235                 }
1236                 list_modify_str_array(&rparams->kdcservers, (const char **)list,
1237                                       LIST_MODE_ADD);
1238                 mask |= LDAP_REALM_KDCSERVERS;
1239             }
1240         } else if (!strcmp(argv[i], "-admindn")) {
1241             if (++i > argc-1)
1242                 goto err_usage;
1243 
1244             if ((rmask & LDAP_REALM_ADMINSERVERS) && (rparams->adminservers)) {
1245                 if (!oldadmindns) {
1246                     /* Store the old admin dns list for removing rights */
1247                     oldadmindns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
1248                     if (oldadmindns == NULL) {
1249                         retval = ENOMEM;
1250                         goto cleanup;
1251                     }
1252 
1253                     for (j=0; rparams->adminservers[j] != NULL; j++) {
1254                         oldadmindns[j] = strdup(rparams->adminservers[j]);
1255                         if (oldadmindns[j] == NULL) {
1256                             retval = ENOMEM;
1257                             goto cleanup;
1258                         }
1259                     }
1260                     oldadmindns[j] = NULL;
1261                 }
1262 
1263                 krb5_free_list_entries(rparams->adminservers);
1264                 free(rparams->adminservers);
1265             }
1266 
1267             rparams->adminservers = (char **)malloc(
1268                 sizeof(char *) * MAX_LIST_ENTRIES);
1269             if (rparams->adminservers == NULL) {
1270                 retval = ENOMEM;
1271                 goto cleanup;
1272             }
1273             memset(rparams->adminservers, 0, sizeof(char *)*MAX_LIST_ENTRIES);
1274             if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
1275                                           rparams->adminservers))) {
1276                 goto cleanup;
1277             }
1278             mask |= LDAP_REALM_ADMINSERVERS;
1279             /* Going to replace the existing value by this new value. Hence
1280              * setting flag indicating that add or clear options will be ignored
1281              */
1282             newadmindn = 1;
1283         } else if (!strcmp(argv[i], "-clearadmindn")) {
1284             if (++i > argc-1)
1285                 goto err_usage;
1286 
1287             if ((!newadmindn) && (rmask & LDAP_REALM_ADMINSERVERS) && (rparams->adminservers)) {
1288                 if (!oldadmindns) {
1289                     /* Store the old admin dns list for removing rights */
1290                     oldadmindns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
1291                     if (oldadmindns == NULL) {
1292                         retval = ENOMEM;
1293                         goto cleanup;
1294                     }
1295 
1296                     for (j=0; rparams->adminservers[j] != NULL; j++) {
1297                         oldadmindns[j] = strdup(rparams->adminservers[j]);
1298                         if (oldadmindns[j] == NULL) {
1299                             retval = ENOMEM;
1300                             goto cleanup;
1301                         }
1302                     }
1303                     oldadmindns[j] = NULL;
1304                 }
1305 
1306                 memset(list, 0, sizeof(char *) * MAX_LIST_ENTRIES);
1307                 if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) {
1308                     goto cleanup;
1309                 }
1310                 list_modify_str_array(&rparams->adminservers, (const char **)list,
1311                                       LIST_MODE_DELETE);
1312                 mask |= LDAP_REALM_ADMINSERVERS;
1313                 krb5_free_list_entries(list);
1314             }
1315         } else if (!strcmp(argv[i], "-addadmindn")) {
1316             if (++i > argc-1)
1317                 goto err_usage;
1318             if (!newadmindn) {
1319                 if ((rmask & LDAP_REALM_ADMINSERVERS) && (rparams->adminservers) && (!oldadmindns)) {
1320                     /* Store the old admin dns list for removing rights */
1321                     oldadmindns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
1322                     if (oldadmindns == NULL) {
1323                         retval = ENOMEM;
1324                         goto cleanup;
1325                     }
1326 
1327                     for (j=0; rparams->adminservers[j] != NULL; j++) {
1328                         oldadmindns[j] = strdup(rparams->adminservers[j]);
1329                         if (oldadmindns[j] == NULL) {
1330                             retval = ENOMEM;
1331                             goto cleanup;
1332                         }
1333                     }
1334                     oldadmindns[j] = NULL;
1335                 }
1336 
1337                 memset(list, 0, sizeof(char *) * MAX_LIST_ENTRIES);
1338                 if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) {
1339                     goto cleanup;
1340                 }
1341                 existing_entries = list_count_str_array(rparams->adminservers);
1342                 list_entries = list_count_str_array(list);
1343                 if (rmask & LDAP_REALM_ADMINSERVERS) {
1344                     tempstr = (char **)realloc(
1345                         rparams->adminservers,
1346                         sizeof(char *) * (existing_entries+list_entries+1));
1347                     if (tempstr == NULL) {
1348                         retval = ENOMEM;
1349                         goto cleanup;
1350                     }
1351                     rparams->adminservers = tempstr;
1352                 } else {
1353                     rparams->adminservers = (char **)malloc(sizeof(char *) * (list_entries+1));
1354                     if (rparams->adminservers == NULL) {
1355                         retval = ENOMEM;
1356                         goto cleanup;
1357                     }
1358                     memset(rparams->adminservers, 0, sizeof(char *) * (list_entries+1));
1359                 }
1360                 list_modify_str_array(&rparams->adminservers, (const char **)list,
1361                                       LIST_MODE_ADD);
1362                 mask |= LDAP_REALM_ADMINSERVERS;
1363             }
1364         } else if (!strcmp(argv[i], "-pwddn")) {
1365             if (++i > argc-1)
1366                 goto err_usage;
1367 
1368             if ((rmask & LDAP_REALM_PASSWDSERVERS) && (rparams->passwdservers)) {
1369                 if (!oldpwddns) {
1370                     /* Store the old pwd dns list for removing rights */
1371                     oldpwddns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
1372                     if (oldpwddns == NULL) {
1373                         retval = ENOMEM;
1374                         goto cleanup;
1375                     }
1376 
1377                     for (j=0; rparams->passwdservers[j] != NULL; j++) {
1378                         oldpwddns[j] = strdup(rparams->passwdservers[j]);
1379                         if (oldpwddns[j] == NULL) {
1380                             retval = ENOMEM;
1381                             goto cleanup;
1382                         }
1383                     }
1384                     oldpwddns[j] = NULL;
1385                 }
1386 
1387                 krb5_free_list_entries(rparams->passwdservers);
1388                 free(rparams->passwdservers);
1389             }
1390 
1391             rparams->passwdservers = (char **)malloc(
1392                 sizeof(char *) * MAX_LIST_ENTRIES);
1393             if (rparams->passwdservers == NULL) {
1394                 retval = ENOMEM;
1395                 goto cleanup;
1396             }
1397             memset(rparams->passwdservers, 0, sizeof(char *)*MAX_LIST_ENTRIES);
1398             if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER,
1399                                           rparams->passwdservers))) {
1400                 goto cleanup;
1401             }
1402             mask |= LDAP_REALM_PASSWDSERVERS;
1403             /* Going to replace the existing value by this new value. Hence
1404              * setting flag indicating that add or clear options will be ignored
1405              */
1406             newpwddn = 1;
1407         } else if (!strcmp(argv[i], "-clearpwddn")) {
1408             if (++i > argc-1)
1409                 goto err_usage;
1410 
1411             if ((!newpwddn) && (rmask & LDAP_REALM_PASSWDSERVERS) && (rparams->passwdservers)) {
1412                 if (!oldpwddns) {
1413                     /* Store the old pwd dns list for removing rights */
1414                     oldpwddns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
1415                     if (oldpwddns == NULL) {
1416                         retval = ENOMEM;
1417                         goto cleanup;
1418                     }
1419 
1420                     for (j=0; rparams->passwdservers[j] != NULL; j++) {
1421                         oldpwddns[j] = strdup(rparams->passwdservers[j]);
1422                         if (oldpwddns[j] == NULL) {
1423                             retval = ENOMEM;
1424                             goto cleanup;
1425                         }
1426                     }
1427                     oldpwddns[j] = NULL;
1428                 }
1429 
1430                 memset(list, 0, sizeof(char *) * MAX_LIST_ENTRIES);
1431                 if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) {
1432                     goto cleanup;
1433                 }
1434                 list_modify_str_array(&rparams->passwdservers, (const char**)list,
1435                                       LIST_MODE_DELETE);
1436                 mask |= LDAP_REALM_PASSWDSERVERS;
1437                 krb5_free_list_entries(list);
1438             }
1439         } else if (!strcmp(argv[i], "-addpwddn")) {
1440             if (++i > argc-1)
1441                 goto err_usage;
1442             if (!newpwddn) {
1443                 if ((rmask & LDAP_REALM_PASSWDSERVERS) && (rparams->passwdservers) && (!oldpwddns)) {
1444                     /* Store the old pwd dns list for removing rights */
1445                     oldpwddns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
1446                     if (oldpwddns == NULL) {
1447                         retval = ENOMEM;
1448                         goto cleanup;
1449                     }
1450 
1451                     for (j=0; rparams->passwdservers[j] != NULL; j++) {
1452                         oldpwddns[j] = strdup(rparams->passwdservers[j]);
1453                         if (oldpwddns[j] == NULL) {
1454                             retval = ENOMEM;
1455                             goto cleanup;
1456                         }
1457                     }
1458                     oldpwddns[j] = NULL;
1459                 }
1460 
1461                 memset(list, 0, sizeof(char *) * MAX_LIST_ENTRIES);
1462                 if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) {
1463                     goto cleanup;
1464                 }
1465                 existing_entries = list_count_str_array(rparams->passwdservers);
1466                 list_entries = list_count_str_array(list);
1467                 if (rmask & LDAP_REALM_PASSWDSERVERS) {
1468                     tempstr = (char **)realloc(
1469                         rparams->passwdservers,
1470                         sizeof(char *) * (existing_entries+list_entries+1));
1471                     if (tempstr == NULL) {
1472                         retval = ENOMEM;
1473                         goto cleanup;
1474                     }
1475                     rparams->passwdservers = tempstr;
1476                 } else {
1477                     rparams->passwdservers = (char **)malloc(sizeof(char *) * (list_entries+1));
1478                     if (rparams->passwdservers == NULL) {
1479                         retval = ENOMEM;
1480                         goto cleanup;
1481                     }
1482                     memset(rparams->passwdservers, 0, sizeof(char *) * (list_entries+1));
1483                 }
1484                 list_modify_str_array(&rparams->passwdservers, (const char**)list,
1485                                       LIST_MODE_ADD);
1486                 mask |= LDAP_REALM_PASSWDSERVERS;
1487             }
1488         }
1489 #endif
1490         else if ((ret_mask= get_ticket_policy(rparams,&i,argv,argc)) !=0) {
1491             mask|=ret_mask;
1492         } else {
1493             printf(gettext("'%s' is an invalid option\n"), argv[i]);
1494             goto err_usage;
1495         }
1496     }
1497 
1498     if ((retval = krb5_ldap_modify_realm(util_context,
1499                                          /* global_params.realm, */ rparams, mask))) {
1500         goto cleanup;
1501     }
1502 
1503 #ifdef HAVE_EDIRECTORY
1504     if ((mask & LDAP_REALM_SUBTREE) || (mask & LDAP_REALM_KDCSERVERS) ||
1505         (mask & LDAP_REALM_ADMINSERVERS) || (mask & LDAP_REALM_PASSWDSERVERS)) {
1506 
1507         printf(gettext("Changing rights for the service object. Please wait ... "));
1508         fflush(stdout);
1509 
1510         if (!(mask & LDAP_REALM_SUBTREE)) {
1511             if (rparams->subtree != NULL) {
1512                 for(i=0; rparams->subtree[i]!=NULL;i++) {
1513                     oldsubtrees[i] = strdup(rparams->subtree[i]);
1514                     if( oldsubtrees[i] == NULL ) {
1515                         retval = ENOMEM;
1516                         goto cleanup;
1517                     }
1518                 }
1519             }
1520         }
1521 
1522         if ((mask & LDAP_REALM_SUBTREE)) {
1523             int check_subtree = 1;
1524 
1525             newsubtrees = (char**) calloc(rparams->subtreecount, sizeof(char*));
1526 
1527             if (newsubtrees == NULL) {
1528                 retval = ENOMEM;
1529                 goto cleanup;
1530             }
1531 
1532             if ( (rparams != NULL) && (rparams->subtree != NULL) ) {
1533                 for (j=0; j<rparams->subtreecount && rparams->subtree[j]!= NULL; j++) {
1534                     newsubtrees[j] = strdup(rparams->subtree[j]);
1535                     if (newsubtrees[j] == NULL) {
1536                         retval = ENOMEM;
1537                         goto cleanup;
1538                     }
1539                 }
1540                 newsubtrees[j] = NULL;
1541             }
1542             for(j=0;oldsubtrees[j]!=NULL;j++) {
1543                 check_subtree = 1;
1544                 for(i=0; ( (oldsubtrees[j] && !rparams->subtree[i]) ||
1545                         (!oldsubtrees[j] && rparams->subtree[i])); i++) {
1546                     if(strcasecmp( oldsubtrees[j], rparams->subtree[i]) == 0) {
1547                         check_subtree = 0;
1548                         continue;
1549                     }
1550                 }
1551                 if (check_subtree != 0) {
1552                     subtree_changed=1;
1553                     break;
1554                 }
1555             }
1556             /* this will return list of the disjoint members */
1557             disjoint_members( oldsubtrees, newsubtrees);
1558         }
1559 
1560         if ((mask & LDAP_REALM_SUBTREE) || (mask & LDAP_REALM_KDCSERVERS)) {
1561 
1562             newkdcdns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
1563             if (newkdcdns == NULL) {
1564                 retval = ENOMEM;
1565                 goto cleanup;
1566             }
1567 
1568             if ((rparams != NULL) && (rparams->kdcservers != NULL)) {
1569                 for (j=0;  rparams->kdcservers[j]!= NULL; j++) {
1570                     newkdcdns[j] = strdup(rparams->kdcservers[j]);
1571                     if (newkdcdns[j] == NULL) {
1572                         retval = ENOMEM;
1573                         goto cleanup;
1574                     }
1575                 }
1576                 newkdcdns[j] = NULL;
1577             }
1578 
1579             if (!subtree_changed) {
1580                 disjoint_members(oldkdcdns, newkdcdns);
1581             } else { /* Only the subtrees was changed. Remove the rights on the old subtrees. */
1582                 if (!(mask & LDAP_REALM_KDCSERVERS)) {
1583 
1584                     oldkdcdns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
1585                     if (oldkdcdns == NULL) {
1586                         retval = ENOMEM;
1587                         goto cleanup;
1588                     }
1589 
1590                     if ((rparams != NULL) && (rparams->kdcservers != NULL)) {
1591                         for (j=0;  rparams->kdcservers[j]!= NULL; j++) {
1592                             oldkdcdns[j] = strdup(rparams->kdcservers[j]);
1593                             if (oldkdcdns[j] == NULL) {
1594                                 retval = ENOMEM;
1595                                 goto cleanup;
1596                             }
1597                         }
1598                         oldkdcdns[j] = NULL;
1599                     }
1600                 }
1601             }
1602 
1603             rightsmask =0;
1604             rightsmask |= LDAP_REALM_RIGHTS;
1605             rightsmask |= LDAP_SUBTREE_RIGHTS;
1606             /* Remove the rights on the old subtrees */
1607             if (oldkdcdns) {
1608                 for (i=0; (oldkdcdns[i] != NULL); i++) {
1609                     if ((retval=krb5_ldap_delete_service_rights(util_context,
1610                                                                 LDAP_KDC_SERVICE, oldkdcdns[i],
1611                                                                 rparams->realm_name, oldsubtrees, rightsmask)) != 0) {
1612                         printf(gettext("failed\n"));
1613                         /* Solaris Kerberos */
1614                         com_err(progname, retval, gettext("while assigning rights '%s'"),
1615                                 rparams->realm_name);
1616                         goto err_nomsg;
1617                     }
1618                 }
1619             }
1620 
1621             rightsmask =0;
1622             rightsmask |= LDAP_REALM_RIGHTS;
1623             rightsmask |= LDAP_SUBTREE_RIGHTS;
1624             if (newkdcdns) {
1625                 for (i=0; (newkdcdns[i] != NULL); i++) {
1626 
1627                     if ((retval=krb5_ldap_add_service_rights(util_context,
1628                                                              LDAP_KDC_SERVICE, newkdcdns[i], rparams->realm_name,
1629                                                              rparams->subtree, rightsmask)) != 0) {
1630                         printf(gettext("failed\n"));
1631                         /* Solaris Kerberos */
1632                         com_err(progname, retval, gettext("while assigning rights to '%s'"),
1633                                 rparams->realm_name);
1634                         goto err_nomsg;
1635                     }
1636                 }
1637             }
1638         }
1639 
1640         if ((mask & LDAP_REALM_SUBTREE) || (mask & LDAP_REALM_ADMINSERVERS)) {
1641 
1642             newadmindns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
1643             if (newadmindns == NULL) {
1644                 retval = ENOMEM;
1645                 goto cleanup;
1646             }
1647 
1648             if ((rparams != NULL) && (rparams->adminservers != NULL)) {
1649                 for (j=0;  rparams->adminservers[j]!= NULL; j++) {
1650                     newadmindns[j] = strdup(rparams->adminservers[j]);
1651                     if (newadmindns[j] == NULL) {
1652                         retval = ENOMEM;
1653                         goto cleanup;
1654                     }
1655                 }
1656                 newadmindns[j] = NULL;
1657             }
1658 
1659             if (!subtree_changed) {
1660                 disjoint_members(oldadmindns, newadmindns);
1661             } else { /* Only the subtrees was changed. Remove the rights on the old subtrees. */
1662                 if (!(mask & LDAP_REALM_ADMINSERVERS)) {
1663 
1664                     oldadmindns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
1665                     if (oldadmindns == NULL) {
1666                         retval = ENOMEM;
1667                         goto cleanup;
1668                     }
1669 
1670                     if ((rparams != NULL) && (rparams->adminservers != NULL)) {
1671                         for (j=0;  rparams->adminservers[j]!= NULL; j++) {
1672                             oldadmindns[j] = strdup(rparams->adminservers[j]);
1673                             if (oldadmindns[j] == NULL) {
1674                                 retval = ENOMEM;
1675                                 goto cleanup;
1676                             }
1677                         }
1678                         oldadmindns[j] = NULL;
1679                     }
1680                 }
1681             }
1682 
1683             rightsmask = 0;
1684             rightsmask |= LDAP_REALM_RIGHTS;
1685             rightsmask |= LDAP_SUBTREE_RIGHTS;
1686             /* Remove the rights on the old subtrees */
1687             if (oldadmindns) {
1688                 for (i=0; (oldadmindns[i] != NULL); i++) {
1689 
1690                     if ((retval=krb5_ldap_delete_service_rights(util_context,
1691                                                                 LDAP_ADMIN_SERVICE, oldadmindns[i],
1692                                                                 rparams->realm_name, oldsubtrees, rightsmask)) != 0) {
1693                         printf(gettext("failed\n"));
1694                         /* Solaris Kerberos */
1695                         com_err(progname, retval, gettext("while assigning rights '%s'"),
1696                                 rparams->realm_name);
1697                         goto err_nomsg;
1698                     }
1699                 }
1700             }
1701 
1702             rightsmask = 0;
1703             rightsmask |= LDAP_REALM_RIGHTS;
1704             rightsmask |= LDAP_SUBTREE_RIGHTS;
1705             /* Add rights on the new subtree for all the kdc dns */
1706             if (newadmindns) {
1707                 for (i=0; (newadmindns[i] != NULL); i++) {
1708 
1709                     if ((retval=krb5_ldap_add_service_rights(util_context,
1710                                                              LDAP_ADMIN_SERVICE, newadmindns[i],
1711                                                              rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
1712                         printf(gettext("failed\n"));
1713                         /* Solaris Kerberos */
1714                         com_err(progname, retval, gettext("while assigning rights to '%s'"),
1715                                 rparams->realm_name);
1716                         goto err_nomsg;
1717                     }
1718                 }
1719             }
1720         }
1721 
1722 
1723         if ((mask & LDAP_REALM_SUBTREE) || (mask & LDAP_REALM_PASSWDSERVERS)) {
1724 
1725             newpwddns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
1726             if (newpwddns == NULL) {
1727                 retval = ENOMEM;
1728                 goto cleanup;
1729             }
1730 
1731             if ((rparams != NULL) && (rparams->passwdservers != NULL)) {
1732                 for (j=0;  rparams->passwdservers[j]!= NULL; j++) {
1733                     newpwddns[j] = strdup(rparams->passwdservers[j]);
1734                     if (newpwddns[j] == NULL) {
1735                         retval = ENOMEM;
1736                         goto cleanup;
1737                     }
1738                 }
1739                 newpwddns[j] = NULL;
1740             }
1741 
1742             if (!subtree_changed) {
1743                 disjoint_members(oldpwddns, newpwddns);
1744             } else { /* Only the subtrees was changed. Remove the rights on the old subtrees. */
1745                 if (!(mask & LDAP_REALM_ADMINSERVERS)) {
1746 
1747                     oldpwddns = (char**) calloc(MAX_LIST_ENTRIES, sizeof(char*));
1748                     if (oldpwddns == NULL) {
1749                         retval = ENOMEM;
1750                         goto cleanup;
1751                     }
1752 
1753                     if ((rparams != NULL) && (rparams->passwdservers != NULL)) {
1754                         for (j=0;  rparams->passwdservers[j]!= NULL; j++) {
1755                             oldpwddns[j] = strdup(rparams->passwdservers[j]);
1756                             if (oldpwddns[j] == NULL) {
1757                                 retval = ENOMEM;
1758                                 goto cleanup;
1759                             }
1760                         }
1761                         oldpwddns[j] = NULL;
1762                     }
1763                 }
1764             }
1765 
1766             rightsmask =0;
1767             rightsmask |= LDAP_REALM_RIGHTS;
1768             rightsmask |= LDAP_SUBTREE_RIGHTS;
1769             /* Remove the rights on the old subtrees */
1770             if (oldpwddns) {
1771                 for (i=0; (oldpwddns[i] != NULL); i++) {
1772                     if ((retval = krb5_ldap_delete_service_rights(util_context,
1773                                                                   LDAP_PASSWD_SERVICE, oldpwddns[i],
1774                                                                   rparams->realm_name, oldsubtrees, rightsmask))) {
1775                         printf(gettext("failed\n"));
1776                         /* Solaris Kerberos */
1777                         com_err(progname, retval, gettext("while assigning rights '%s'"),
1778                                 rparams->realm_name);
1779                         goto err_nomsg;
1780                     }
1781                 }
1782             }
1783 
1784             rightsmask =0;
1785             rightsmask |= LDAP_REALM_RIGHTS;
1786             rightsmask |= LDAP_SUBTREE_RIGHTS;
1787             /* Add rights on the new subtree for all the kdc dns */
1788             if (newpwddns) {
1789                 for (i=0; (newpwddns[i] != NULL); i++) {
1790                     if ((retval = krb5_ldap_add_service_rights(util_context,
1791                                                                LDAP_PASSWD_SERVICE, newpwddns[i],
1792                                                                rparams->realm_name, rparams->subtree, rightsmask))) {
1793                         printf(gettext("failed\n"));
1794                         /* Solaris Kerberos */
1795                         com_err(progname, retval, gettext("while assigning rights to '%s'"),
1796                                 rparams->realm_name);
1797                         goto err_nomsg;
1798                     }
1799                 }
1800             }
1801         }
1802 
1803         printf(gettext("done\n"));
1804     }
1805 #endif
1806 
1807     goto cleanup;
1808 
1809 err_usage:
1810     print_usage = TRUE;
1811 
1812 err_nomsg:
1813     no_msg = TRUE;
1814 
1815 cleanup:
1816     krb5_ldap_free_realm_params(rparams);
1817 
1818 
1819 #ifdef HAVE_EDIRECTORY
1820     if (oldkdcdns) {
1821         for (i=0; oldkdcdns[i] != NULL; i++)
1822             free(oldkdcdns[i]);
1823         free(oldkdcdns);
1824     }
1825     if (oldpwddns) {
1826         for (i=0; oldpwddns[i] != NULL; i++)
1827             free(oldpwddns[i]);
1828         free(oldpwddns);
1829     }
1830     if (oldadmindns) {
1831         for (i=0; oldadmindns[i] != NULL; i++)
1832             free(oldadmindns[i]);
1833         free(oldadmindns);
1834     }
1835     if (newkdcdns) {
1836         for (i=0; newkdcdns[i] != NULL; i++)
1837             free(newkdcdns[i]);
1838         free(newkdcdns);
1839     }
1840     if (newpwddns) {
1841         for (i=0; newpwddns[i] != NULL; i++)
1842             free(newpwddns[i]);
1843         free(newpwddns);
1844     }
1845     if (newadmindns) {
1846         for (i=0; newadmindns[i] != NULL; i++)
1847             free(newadmindns[i]);
1848         free(newadmindns);
1849     }
1850     if (oldsubtrees) {
1851         for (i=0;oldsubtrees[i]!=NULL; i++)
1852             free(oldsubtrees[i]);
1853         free(oldsubtrees);
1854     }
1855     if (newsubtrees) {
1856         for (i=0;newsubtrees[i]!=NULL; i++)
1857             free(newsubtrees[i]);
1858         free(oldsubtrees);
1859     }
1860 #endif
1861     if (print_usage) {
1862         db_usage(MODIFY_REALM);
1863     }
1864 
1865     if (retval) {
1866         if (!no_msg) {
1867             /* Solaris Kerberos */
1868             com_err(progname, retval, gettext("while modifying information of realm '%s'"),
1869                     global_params.realm);
1870         }
1871         exit_status++;
1872     }
1873 
1874     return;
1875 }
1876 
1877 
1878 
1879 /*
1880  * This function displays the attributes of a Realm
1881  */
1882 void kdb5_ldap_view(argc, argv)
1883     int argc;
1884     char *argv[];
1885 {
1886     krb5_ldap_realm_params *rparams = NULL;
1887     krb5_error_code retval = 0;
1888     kdb5_dal_handle *dal_handle=NULL;
1889     krb5_ldap_context *ldap_context=NULL;
1890     int mask = 0;
1891 
1892     dal_handle = (kdb5_dal_handle *) util_context->db_context;
1893     ldap_context = (krb5_ldap_context *) dal_handle->db_context;
1894     if (!(ldap_context)) {
1895         retval = EINVAL;
1896         /* Solaris Kerberos */
1897         com_err(progname, retval, gettext("while initializing database"));
1898         exit_status++;
1899         return;
1900     }
1901 
1902     /* Read the kerberos container information */
1903     if ((retval = krb5_ldap_read_krbcontainer_params(util_context,
1904                                                      &(ldap_context->krbcontainer))) != 0) {
1905         /* Solaris Kerberos */
1906         com_err(progname, retval, gettext("while reading kerberos container information"));
1907         exit_status++;
1908         return;
1909     }
1910 
1911     if ((retval = krb5_ldap_read_realm_params(util_context,
1912                                               global_params.realm, &rparams, &mask)) || (!rparams)) {
1913         /* Solaris Kerberos */
1914         com_err(progname, retval, gettext("while reading information of realm '%s'"),
1915                 global_params.realm);
1916         exit_status++;
1917         return;
1918     }
1919     print_realm_params(rparams, mask);
1920     krb5_ldap_free_realm_params(rparams);
1921 
1922     return;
1923 }
1924 
1925 static char *strdur(duration)
1926     time_t duration;
1927 {
1928     static char out[50];
1929     int neg, days, hours, minutes, seconds;
1930 
1931     if (duration < 0) {
1932         duration *= -1;
1933         neg = 1;
1934     } else
1935         neg = 0;
1936     days = duration / (24 * 3600);
1937     duration %= 24 * 3600;
1938     hours = duration / 3600;
1939     duration %= 3600;
1940     minutes = duration / 60;
1941     duration %= 60;
1942     seconds = duration;
1943     snprintf(out, sizeof(out), "%s%d %s %02d:%02d:%02d", neg ? "-" : "",
1944             days, days == 1 ? gettext("day") : gettext("days"),
1945             hours, minutes, seconds);
1946     return out;
1947 }
1948 
1949 /*
1950  * This function prints the attributes of a given realm to the
1951  * standard output.
1952  */
1953 static void print_realm_params(krb5_ldap_realm_params *rparams, int mask)
1954 {
1955     char **slist = NULL;
1956     int num_entry_printed = 0, i = 0;
1957 
1958     /* Print the Realm Attributes on the standard output */
1959     printf("%25s: %-50s\n", gettext("Realm Name"), global_params.realm);
1960     if (mask & LDAP_REALM_SUBTREE) {
1961         for (i=0; rparams->subtree[i]!=NULL; i++)
1962             printf("%25s: %-50s\n", gettext("Subtree"), rparams->subtree[i]);
1963     }
1964     if (mask & LDAP_REALM_CONTREF)
1965         printf("%25s: %-50s\n", gettext("Principal Container Reference"), rparams->containerref);
1966     if (mask & LDAP_REALM_SEARCHSCOPE) {
1967         if ((rparams->search_scope != 1) &&
1968             (rparams->search_scope != 2)) {
1969             printf("%25s: %-50s\n", gettext("SearchScope"), gettext("Invalid !"));
1970         } else {
1971             printf("%25s: %-50s\n", gettext("SearchScope"),
1972                    (rparams->search_scope == 1) ? gettext("ONE") : gettext("SUB"));
1973         }
1974     }
1975     if (mask & LDAP_REALM_KDCSERVERS) {
1976         printf("%25s:", gettext("KDC Services"));
1977         if (rparams->kdcservers != NULL) {
1978             num_entry_printed = 0;
1979             for (slist = rparams->kdcservers; *slist != NULL; slist++) {
1980                 if (num_entry_printed)
1981                     printf(" %25s %-50s\n", " ", *slist);
1982                 else
1983                     printf(" %-50s\n", *slist);
1984                 num_entry_printed++;
1985             }
1986         }
1987         if (num_entry_printed == 0)
1988             printf("\n");
1989     }
1990     if (mask & LDAP_REALM_ADMINSERVERS) {
1991         printf("%25s:", gettext("Admin Services"));
1992         if (rparams->adminservers != NULL) {
1993             num_entry_printed = 0;
1994             for (slist = rparams->adminservers; *slist != NULL; slist++) {
1995                 if (num_entry_printed)
1996                     printf(" %25s %-50s\n", " ", *slist);
1997                 else
1998                     printf(" %-50s\n", *slist);
1999                 num_entry_printed++;
2000             }
2001         }
2002         if (num_entry_printed == 0)
2003             printf("\n");
2004     }
2005     if (mask & LDAP_REALM_PASSWDSERVERS) {
2006         printf("%25s:", gettext("Passwd Services"));
2007         if (rparams->passwdservers != NULL) {
2008             num_entry_printed = 0;
2009             for (slist = rparams->passwdservers; *slist != NULL; slist++) {
2010                 if (num_entry_printed)
2011                     printf(" %25s %-50s\n", " ", *slist);
2012                 else
2013                     printf(" %-50s\n", *slist);
2014                 num_entry_printed++;
2015             }
2016         }
2017         if (num_entry_printed == 0)
2018             printf("\n");
2019     }
2020     if (mask & LDAP_REALM_MAXTICKETLIFE) {
2021         printf("%25s:", gettext("Maximum Ticket Life"));
2022         printf(" %s \n", strdur(rparams->max_life));
2023     }
2024 
2025     if (mask & LDAP_REALM_MAXRENEWLIFE) {
2026         printf("%25s:", gettext("Maximum Renewable Life"));
2027         printf(" %s \n", strdur(rparams->max_renewable_life));
2028     }
2029 
2030     if (mask & LDAP_REALM_KRBTICKETFLAGS) {
2031         int ticketflags = rparams->tktflags;
2032 
2033         printf("%25s: ", gettext("Ticket flags"));
2034         if (ticketflags & KRB5_KDB_DISALLOW_POSTDATED)
2035             printf("%s ","DISALLOW_POSTDATED");
2036 
2037         if (ticketflags & KRB5_KDB_DISALLOW_FORWARDABLE)
2038             printf("%s ","DISALLOW_FORWARDABLE");
2039 
2040         if (ticketflags & KRB5_KDB_DISALLOW_RENEWABLE)
2041             printf("%s ","DISALLOW_RENEWABLE");
2042 
2043         if (ticketflags & KRB5_KDB_DISALLOW_PROXIABLE)
2044             printf("%s ","DISALLOW_PROXIABLE");
2045 
2046         if (ticketflags & KRB5_KDB_DISALLOW_DUP_SKEY)
2047             printf("%s ","DISALLOW_DUP_SKEY");
2048 
2049         if (ticketflags & KRB5_KDB_REQUIRES_PRE_AUTH)
2050             printf("%s ","REQUIRES_PRE_AUTH");
2051 
2052         if (ticketflags & KRB5_KDB_REQUIRES_HW_AUTH)
2053             printf("%s ","REQUIRES_HW_AUTH");
2054 
2055         if (ticketflags & KRB5_KDB_DISALLOW_SVR)
2056             printf("%s ","DISALLOW_SVR");
2057 
2058         if (ticketflags & KRB5_KDB_DISALLOW_TGT_BASED)
2059             printf("%s ","DISALLOW_TGT_BASED");
2060 
2061         if (ticketflags & KRB5_KDB_DISALLOW_ALL_TIX)
2062             printf("%s ","DISALLOW_ALL_TIX");
2063 
2064         if (ticketflags & KRB5_KDB_REQUIRES_PWCHANGE)
2065             printf("%s ","REQUIRES_PWCHANGE");
2066 
2067         if (ticketflags & KRB5_KDB_PWCHANGE_SERVICE)
2068             printf("%s ","PWCHANGE_SERVICE");
2069 
2070         printf("\n");
2071     }
2072 
2073 
2074     return;
2075 }
2076 
2077 
2078 
2079 /*
2080  * This function lists the Realm(s) present under the Kerberos container
2081  * on the LDAP Server.
2082  */
2083 void kdb5_ldap_list(argc, argv)
2084     int argc;
2085     char *argv[];
2086 {
2087     char **list = NULL;
2088     char **plist = NULL;
2089     krb5_error_code retval = 0;
2090     kdb5_dal_handle *dal_handle=NULL;
2091     krb5_ldap_context *ldap_context=NULL;
2092 
2093     dal_handle = (kdb5_dal_handle *)util_context->db_context;
2094     ldap_context = (krb5_ldap_context *) dal_handle->db_context;
2095     if (!(ldap_context)) {
2096         retval = EINVAL;
2097         exit_status++;
2098         return;
2099     }
2100 
2101     /* Read the kerberos container information */
2102     if ((retval = krb5_ldap_read_krbcontainer_params(util_context,
2103                                                      &(ldap_context->krbcontainer))) != 0) {
2104         /* Solaris Kerberos */
2105         com_err(progname, retval, gettext("while reading kerberos container information"));
2106         exit_status++;
2107         return;
2108     }
2109 
2110     retval = krb5_ldap_list_realm(util_context, &list);
2111     if (retval != 0) {
2112         krb5_ldap_free_krbcontainer_params(ldap_context->krbcontainer);
2113         ldap_context->krbcontainer = NULL;
2114         /* Solaris Kerberos */
2115         com_err (progname, retval, gettext("while listing realms"));
2116         exit_status++;
2117         return;
2118     }
2119     /* This is to handle the case of realm not present */
2120     if (list == NULL) {
2121         krb5_ldap_free_krbcontainer_params(ldap_context->krbcontainer);
2122         ldap_context->krbcontainer = NULL;
2123         return;
2124     }
2125 
2126     for (plist = list; *plist != NULL; plist++) {
2127         printf("%s\n", *plist);
2128     }
2129     krb5_ldap_free_krbcontainer_params(ldap_context->krbcontainer);
2130     ldap_context->krbcontainer = NULL;
2131     krb5_free_list_entries(list);
2132     free(list);
2133 
2134     return;
2135 }
2136 
2137 /*
2138  * Duplicating the following two functions here because
2139  * 'krb5_dbe_update_tl_data' uses backend specific memory allocation. The catch
2140  * here is that the backend is not initialized - kdb5_ldap_util doesn't go
2141  * through DAL.
2142  * 1. krb5_dbe_update_tl_data
2143  * 2. krb5_dbe_update_mod_princ_data
2144  */
2145 
2146 /* Start duplicate code ... */
2147 
2148 static krb5_error_code
2149 krb5_dbe_update_tl_data_new(context, entry, new_tl_data)
2150     krb5_context context;
2151     krb5_db_entry *entry;
2152     krb5_tl_data *new_tl_data;
2153 {
2154     krb5_tl_data *tl_data = NULL;
2155     krb5_octet *tmp;
2156 
2157     /* copy the new data first, so we can fail cleanly if malloc()
2158      * fails */
2159 /*
2160     if ((tmp =
2161          (krb5_octet *) krb5_db_alloc(context, NULL,
2162                                       new_tl_data->tl_data_length)) == NULL)
2163 */
2164     if ((tmp = (krb5_octet *) malloc (new_tl_data->tl_data_length)) == NULL)
2165         return (ENOMEM);
2166 
2167     /* Find an existing entry of the specified type and point at
2168      * it, or NULL if not found */
2169 
2170     if (new_tl_data->tl_data_type != KRB5_TL_DB_ARGS) {      /* db_args can be multiple */
2171         for (tl_data = entry->tl_data; tl_data;
2172              tl_data = tl_data->tl_data_next)
2173             if (tl_data->tl_data_type == new_tl_data->tl_data_type)
2174                 break;
2175     }
2176 
2177     /* if necessary, chain a new record in the beginning and point at it */
2178 
2179     if (!tl_data) {
2180 /*
2181         if ((tl_data =
2182              (krb5_tl_data *) krb5_db_alloc(context, NULL,
2183                                             sizeof(krb5_tl_data)))
2184             == NULL) {
2185 */
2186         if ((tl_data = (krb5_tl_data *) malloc (sizeof(krb5_tl_data))) == NULL) {
2187             free(tmp);
2188             return (ENOMEM);
2189         }
2190         memset(tl_data, 0, sizeof(krb5_tl_data));
2191         tl_data->tl_data_next = entry->tl_data;
2192         entry->tl_data = tl_data;
2193         entry->n_tl_data++;
2194     }
2195 
2196     /* fill in the record */
2197 
2198     if (tl_data->tl_data_contents)
2199         krb5_db_free(context, tl_data->tl_data_contents);
2200 
2201     tl_data->tl_data_type = new_tl_data->tl_data_type;
2202     tl_data->tl_data_length = new_tl_data->tl_data_length;
2203     tl_data->tl_data_contents = tmp;
2204     memcpy(tmp, new_tl_data->tl_data_contents, tl_data->tl_data_length);
2205 
2206     return (0);
2207 }
2208 
2209 static krb5_error_code
2210 krb5_dbe_update_mod_princ_data_new(context, entry, mod_date, mod_princ)
2211     krb5_context          context;
2212     krb5_db_entry       * entry;
2213     krb5_timestamp        mod_date;
2214     krb5_const_principal  mod_princ;
2215 {
2216     krb5_tl_data          tl_data;
2217 
2218     krb5_error_code       retval = 0;
2219     krb5_octet          * nextloc = 0;
2220     char                * unparse_mod_princ = 0;
2221     unsigned int        unparse_mod_princ_size;
2222 
2223     if ((retval = krb5_unparse_name(context, mod_princ,
2224                                     &unparse_mod_princ)))
2225         return(retval);
2226 
2227     unparse_mod_princ_size = strlen(unparse_mod_princ) + 1;
2228 
2229     if ((nextloc = (krb5_octet *) malloc(unparse_mod_princ_size + 4))
2230         == NULL) {
2231         free(unparse_mod_princ);
2232         return(ENOMEM);
2233     }
2234 
2235     tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
2236     tl_data.tl_data_length = unparse_mod_princ_size + 4;
2237     tl_data.tl_data_contents = nextloc;
2238 
2239     /* Mod Date */
2240     krb5_kdb_encode_int32(mod_date, nextloc);
2241 
2242     /* Mod Princ */
2243     memcpy(nextloc+4, unparse_mod_princ, unparse_mod_princ_size);
2244 
2245     retval = krb5_dbe_update_tl_data_new(context, entry, &tl_data);
2246 
2247     free(unparse_mod_princ);
2248     free(nextloc);
2249 
2250     return(retval);
2251 }
2252 
2253 static krb5_error_code
2254 kdb_ldap_tgt_keysalt_iterate(ksent, ptr)
2255     krb5_key_salt_tuple *ksent;
2256     krb5_pointer        ptr;
2257 {
2258     krb5_context        context;
2259     krb5_error_code     kret;
2260     struct iterate_args *iargs;
2261     krb5_keyblock       key;
2262     krb5_int32          ind;
2263     krb5_data   pwd;
2264     krb5_db_entry       *entry;
2265 
2266     iargs = (struct iterate_args *) ptr;
2267     kret = 0;
2268 
2269     context = iargs->ctx;
2270     entry = iargs->dbentp;
2271 
2272     /*
2273      * Convert the master key password into a key for this particular
2274      * encryption system.
2275      */
2276     pwd.data = mkey_password;
2277     pwd.length = strlen(mkey_password);
2278     kret = krb5_c_random_seed(context, &pwd);
2279     if (kret)
2280         return kret;
2281 
2282     /*if (!(kret = krb5_dbe_create_key_data(iargs->ctx, iargs->dbentp))) {*/
2283     if ((entry->key_data =
2284              (krb5_key_data *) realloc(entry->key_data,
2285                                             (sizeof(krb5_key_data) *
2286                                             (entry->n_key_data + 1)))) == NULL)
2287         return (ENOMEM);
2288 
2289     memset(entry->key_data + entry->n_key_data, 0, sizeof(krb5_key_data));
2290     ind = entry->n_key_data++;
2291 
2292     if (!(kret = krb5_c_make_random_key(context, ksent->ks_enctype,
2293                                         &key))) {
2294         kret = krb5_dbekd_encrypt_key_data(context,
2295                                            iargs->rblock->key,
2296                                            &key,
2297                                            NULL,
2298                                            1,
2299                                            &entry->key_data[ind]);
2300         krb5_free_keyblock_contents(context, &key);
2301     }
2302     /*}*/
2303 
2304     return(kret);
2305 }
2306 /* End duplicate code */
2307 
2308 /*
2309  * This function creates service principals when
2310  * creating the realm object.
2311  */
2312 static int
2313 kdb_ldap_create_principal (context, princ, op, pblock)
2314     krb5_context context;
2315     krb5_principal princ;
2316     enum ap_op op;
2317     struct realm_info *pblock;
2318 {
2319     int              retval=0, currlen=0, princtype = 2 /* Service Principal */;
2320     unsigned char    *curr=NULL;
2321     krb5_tl_data     *tl_data=NULL;
2322     krb5_db_entry    entry;
2323     int              nentry=1;
2324     long             mask = 0;
2325     krb5_keyblock    key;
2326     int              kvno = 0;
2327     kdb5_dal_handle *dal_handle = NULL;
2328     krb5_ldap_context *ldap_context=NULL;
2329     struct iterate_args   iargs;
2330     krb5_data       *pdata;
2331 
2332     if ((pblock == NULL) || (context == NULL)) {
2333         retval = EINVAL;
2334         goto cleanup;
2335     }
2336     dal_handle = (kdb5_dal_handle *) context->db_context;
2337     ldap_context = (krb5_ldap_context *) dal_handle->db_context;
2338     if (!(ldap_context)) {
2339         retval = EINVAL;
2340         goto cleanup;
2341     }
2342 
2343     memset(&entry, 0, sizeof(entry));
2344 
2345     tl_data = malloc(sizeof(*tl_data));
2346     if (tl_data == NULL) {
2347         retval = ENOMEM;
2348         goto cleanup;
2349     }
2350     memset(tl_data, 0, sizeof(*tl_data));
2351     tl_data->tl_data_length = 1 + 2 + 2 + 1 + 2 + 4;
2352     tl_data->tl_data_type = 7; /* KDB_TL_USER_INFO */
2353     curr = tl_data->tl_data_contents = malloc(tl_data->tl_data_length);
2354     if (tl_data->tl_data_contents == NULL) {
2355         retval = ENOMEM;
2356         goto cleanup;
2357     }
2358 
2359     memset(curr, 1, 1); /* Passing the mask as principal type */
2360     curr += 1;
2361     currlen = 2;
2362     STORE16_INT(curr, currlen);
2363     curr += currlen;
2364     STORE16_INT(curr, princtype);
2365     curr += currlen;
2366 
2367     mask |= KADM5_PRINCIPAL;
2368     mask |= KADM5_ATTRIBUTES ;
2369     mask |= KADM5_MAX_LIFE ;
2370     mask |= KADM5_MAX_RLIFE ;
2371     mask |= KADM5_PRINC_EXPIRE_TIME ;
2372     mask |= KADM5_KEY_DATA;
2373 
2374     entry.tl_data = tl_data;
2375     entry.n_tl_data += 1;
2376     /* Set the creator's name */
2377     {
2378         krb5_timestamp now;
2379         if ((retval = krb5_timeofday(context, &now)))
2380             goto cleanup;
2381         if ((retval = krb5_dbe_update_mod_princ_data_new(context, &entry,
2382                         now, &db_create_princ)))
2383             goto cleanup;
2384     }
2385     entry.attributes = pblock->flags;
2386     entry.max_life = pblock->max_life;
2387     entry.max_renewable_life = pblock->max_rlife;
2388     entry.expiration = pblock->expiration;
2389     entry.mask = mask;
2390     if ((retval = krb5_copy_principal(context, princ, &entry.princ)))
2391         goto cleanup;
2392 
2393 
2394     switch (op) {
2395     case TGT_KEY:
2396         if ((pdata = krb5_princ_component(context, princ, 1)) &&
2397             pdata->length == strlen("history") &&
2398             !memcmp(pdata->data, "history", strlen("history"))) {
2399 
2400             /* Allocate memory for storing the key */
2401             if ((entry.key_data = (krb5_key_data *) malloc(
2402                                               sizeof(krb5_key_data))) == NULL) {
2403                 retval = ENOMEM;
2404                 goto cleanup;
2405             }
2406 
2407             memset(entry.key_data, 0, sizeof(krb5_key_data));
2408             entry.n_key_data++;
2409 
2410             retval = krb5_c_make_random_key(context, global_params.enctype, &key);
2411             if (retval) {
2412                 goto cleanup;
2413             }
2414             kvno = 1; /* New key is getting set */
2415             retval = krb5_dbekd_encrypt_key_data(context,
2416                                         &ldap_context->lrparams->mkey,
2417                                         &key, NULL, kvno,
2418                                         &entry.key_data[entry.n_key_data - 1]);
2419             krb5_free_keyblock_contents(context, &key);
2420             if (retval) {
2421                 goto cleanup;
2422             }
2423         } else {
2424             /*retval = krb5_c_make_random_key(context, 16, &key) ;*/
2425             iargs.ctx = context;
2426             iargs.rblock = pblock;
2427             iargs.dbentp = &entry;
2428 
2429             /*
2430              * create a set of random keys by iterating through the key/salt
2431              * list, ignoring salt types.
2432              */
2433             if ((retval = krb5_keysalt_iterate(pblock->kslist,
2434                                                pblock->nkslist,
2435                                                1,
2436                                                kdb_ldap_tgt_keysalt_iterate,
2437                                                (krb5_pointer) &iargs)))
2438                 return retval;
2439         }
2440         break;
2441 
2442     case MASTER_KEY:
2443         /* Allocate memory for storing the key */
2444         if ((entry.key_data = (krb5_key_data *) malloc(
2445                                               sizeof(krb5_key_data))) == NULL) {
2446             retval = ENOMEM;
2447             goto cleanup;
2448         }
2449 
2450         memset(entry.key_data, 0, sizeof(krb5_key_data));
2451         entry.n_key_data++;
2452         kvno = 1; /* New key is getting set */
2453         retval = krb5_dbekd_encrypt_key_data(context, pblock->key,
2454                                          &ldap_context->lrparams->mkey,
2455                                          NULL, kvno,
2456                                          &entry.key_data[entry.n_key_data - 1]);
2457         if (retval) {
2458             goto cleanup;
2459         }
2460         break;
2461 
2462     case NULL_KEY:
2463     default:
2464         break;
2465     } /* end of switch */
2466 
2467     retval = krb5_ldap_put_principal(context, &entry, &nentry, NULL);
2468     if (retval) {
2469         com_err(NULL, retval, gettext("while adding entries to database"));
2470         goto cleanup;
2471     }
2472 
2473 cleanup:
2474     krb5_dbe_free_contents(context, &entry);
2475     return retval;
2476 }
2477 
2478 
2479 /*
2480  * This function destroys the realm object and the associated principals
2481  */
2482 void
2483 kdb5_ldap_destroy(argc, argv)
2484     int argc;
2485     char *argv[];
2486 {
2487     extern char *optarg;
2488     extern int optind;
2489     int optchar = 0;
2490     char buf[5] = {0};
2491     krb5_error_code retval = 0;
2492     int force = 0;
2493     int mask = 0;
2494     kdb5_dal_handle *dal_handle = NULL;
2495     krb5_ldap_context *ldap_context = NULL;
2496 #ifdef HAVE_EDIRECTORY
2497     int i = 0, rightsmask = 0;
2498     krb5_ldap_realm_params *rparams = NULL;
2499 #endif
2500     /* Solaris Kerberos: to remove stash file */
2501     char *stash_file = NULL;
2502     struct stat stb;
2503 
2504     optind = 1;
2505     while ((optchar = getopt(argc, argv, "f")) != -1) {
2506         switch (optchar) {
2507         case 'f':
2508             force++;
2509             break;
2510         case '?':
2511         default:
2512             db_usage(DESTROY_REALM);
2513             return;
2514             /*NOTREACHED*/
2515         }
2516     }
2517 
2518     if (!force) {
2519         printf(gettext("Deleting KDC database of '%s', are you sure?\n"), global_params.realm);
2520         printf(gettext("(type 'yes' to confirm)? "));
2521         if (fgets(buf, sizeof(buf), stdin) == NULL) {
2522             exit_status++;
2523             return;
2524         }
2525         if (strcmp(buf, yes)) {
2526             exit_status++;
2527             return;
2528         }
2529         printf(gettext("OK, deleting database of '%s'...\n"), global_params.realm);
2530     }
2531 
2532     dal_handle = (kdb5_dal_handle *)util_context->db_context;
2533     ldap_context = (krb5_ldap_context *) dal_handle->db_context;
2534     if (!(ldap_context)) {
2535         /* Solaris Kerberos */
2536         com_err(progname, EINVAL, gettext("while initializing database"));
2537         exit_status++;
2538         return;
2539     }
2540 
2541     /* Read the kerberos container from the LDAP Server */
2542     if ((retval = krb5_ldap_read_krbcontainer_params(util_context,
2543                                                      &(ldap_context->krbcontainer))) != 0) {
2544         /* Solaris Kerberos */
2545         com_err(progname, retval, gettext("while reading kerberos container information"));
2546         exit_status++;
2547         return;
2548     }
2549 
2550     /* Read the Realm information from the LDAP Server */
2551     if ((retval = krb5_ldap_read_realm_params(util_context, global_params.realm,
2552                                               &(ldap_context->lrparams), &mask)) != 0) {
2553         /* Solaris Kerberos */
2554         com_err(progname, retval, gettext("while reading realm information"));
2555         exit_status++;
2556         return;
2557     }
2558 
2559 #ifdef HAVE_EDIRECTORY
2560     if ((mask & LDAP_REALM_KDCSERVERS) || (mask & LDAP_REALM_ADMINSERVERS) ||
2561         (mask & LDAP_REALM_PASSWDSERVERS)) {
2562 
2563         printf(gettext("Changing rights for the service object. Please wait ... "));
2564         fflush(stdout);
2565 
2566         rparams = ldap_context->lrparams;
2567         rightsmask = 0;
2568         rightsmask |= LDAP_REALM_RIGHTS;
2569         rightsmask |= LDAP_SUBTREE_RIGHTS;
2570         if ((rparams != NULL) && (rparams->kdcservers != NULL)) {
2571             for (i=0; (rparams->kdcservers[i] != NULL); i++) {
2572                 if ((retval = krb5_ldap_delete_service_rights(util_context,
2573                                                               LDAP_KDC_SERVICE, rparams->kdcservers[i],
2574                                                               rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
2575                     printf(gettext("failed\n"));
2576                     /* Solaris Kerberos */
2577                     com_err(progname, retval, gettext("while assigning rights to '%s'"),
2578                             rparams->realm_name);
2579                     return;
2580                 }
2581             }
2582         }
2583         rightsmask = 0;
2584         rightsmask |= LDAP_REALM_RIGHTS;
2585         rightsmask |= LDAP_SUBTREE_RIGHTS;
2586         if ((rparams != NULL) && (rparams->adminservers != NULL)) {
2587             for (i=0; (rparams->adminservers[i] != NULL); i++) {
2588                 if ((retval = krb5_ldap_delete_service_rights(util_context,
2589                                                               LDAP_ADMIN_SERVICE, rparams->adminservers[i],
2590                                                               rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
2591                     printf(gettext("failed\n"));
2592                     /* Solaris Kerberos */
2593                     com_err(progname, retval, gettext("while assigning rights to '%s'"),
2594                             rparams->realm_name);
2595                     return;
2596                 }
2597             }
2598         }
2599         rightsmask = 0;
2600         rightsmask |= LDAP_REALM_RIGHTS;
2601         rightsmask |= LDAP_SUBTREE_RIGHTS;
2602         if ((rparams != NULL) && (rparams->passwdservers != NULL)) {
2603             for (i=0; (rparams->passwdservers[i] != NULL); i++) {
2604                 if ((retval = krb5_ldap_delete_service_rights(util_context,
2605                                                               LDAP_PASSWD_SERVICE, rparams->passwdservers[i],
2606                                                               rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
2607                     printf(gettext("failed\n"));
2608                     /* Solaris Kerberos */
2609                     com_err(progname, retval, gettext("while assigning rights to '%s'"),
2610                             rparams->realm_name);
2611                     return;
2612                 }
2613             }
2614         }
2615         printf(gettext("done\n"));
2616     }
2617 #endif
2618     /* Delete the realm container and all the associated principals */
2619     retval = krb5_ldap_delete_realm(util_context, global_params.realm);
2620     if (retval) {
2621         /* Solaris Kerberos */
2622         com_err(progname, retval, gettext("deleting database of '%s'"), global_params.realm);
2623         exit_status++;
2624         return;
2625     }
2626 
2627     /*
2628      * Solaris Kerberos: check for a stash file and delete it if necessary
2629      * This behavior exists in the Solaris version of kdb5_util destroy.
2630      */
2631     if (global_params.stash_file == NULL) {
2632         char stashbuf[MAXPATHLEN+1];
2633         int realm_len = strlen(global_params.realm);
2634 
2635         (void) strlcpy(stashbuf, DEFAULT_KEYFILE_STUB, sizeof (stashbuf)); 
2636 
2637         if (realm_len <= (MAXPATHLEN-strlen(stashbuf))) {
2638             (void) strncat(stashbuf, global_params.realm,
2639                 (MAXPATHLEN-strlen(stashbuf)));
2640         } else {
2641             /* Solaris Kerberos */
2642             com_err(progname, EINVAL,
2643                 gettext("can not determine stash file name for '%s'"),
2644                 global_params.realm);
2645             exit_status++;
2646             return;
2647         }
2648         stash_file = stashbuf;
2649     } else {
2650         stash_file = global_params.stash_file;
2651     }
2652     /* Make sure stash_file is a regular file before unlinking */
2653     if (stat(stash_file, &stb) == 0) {
2654         if ((stb.st_mode & S_IFMT) == S_IFREG) {
2655             (void)unlink(stash_file);
2656         } else {
2657             /* Solaris Kerberos */
2658             com_err(progname, EINVAL,
2659                 gettext("stash file '%s' not a regular file, can not delete"),
2660                 stash_file);
2661             exit_status++;
2662             return;
2663         }
2664     } else if (errno != ENOENT) {
2665         /*
2666          * If the error is something other than the file doesn't exist set an
2667          * error.
2668          */
2669         /* Solaris Kerberos */
2670         com_err(progname, EINVAL,
2671             gettext("could not stat stash file '%s', could not delete"),
2672             stash_file);
2673         exit_status++;
2674         return;
2675     }
2676 
2677     printf(gettext("** Database of '%s' destroyed.\n"), global_params.realm);
2678 
2679     return;
2680 }