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