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