1 #pragma ident "%Z%%M% %I% %E% SMI" 2 /* 3 * lib/kdb/kdb_ldap/ldap_realm.c 4 * 5 * Copyright (c) 2004-2005, Novell, Inc. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are met: 10 * 11 * * Redistributions of source code must retain the above copyright notice, 12 * this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * * The copyright holder's name is not used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 34 * Use is subject to license terms. 35 */ 36 37 #include "ldap_main.h" 38 #include "ldap_realm.h" 39 #include "ldap_principal.h" 40 #include "ldap_pwd_policy.h" 41 #include "ldap_err.h" 42 #include <libintl.h> 43 44 #define END_OF_LIST -1 45 char *realm_attributes[] = {"krbSearchScope","krbSubTrees", "krbPrincContainerRef", 46 "krbMaxTicketLife", "krbMaxRenewableAge", 47 "krbTicketFlags", "krbUpEnabled", 48 "krbTicketPolicyReference", 49 "krbLdapServers", 50 "krbKdcServers", "krbAdmServers", 51 "krbPwdServers", NULL}; 52 53 54 char *policy_attributes[] = { "krbMaxTicketLife", 55 "krbMaxRenewableAge", 56 "krbTicketFlags", 57 NULL }; 58 59 60 61 char *policyclass[] = { "krbTicketPolicy", NULL }; 62 char *kdcclass[] = { "krbKdcService", NULL }; 63 char *adminclass[] = { "krbAdmService", NULL }; 64 char *pwdclass[] = { "krbPwdService", NULL }; 65 char *subtreeclass[] = { "Organization", "OrganizationalUnit", "Domain", "krbContainer", 66 "krbRealmContainer", "Country", "Locality", NULL }; 67 68 69 char *krbContainerRefclass[] = { "krbContainerRefAux", NULL}; 70 71 /* 72 * list realms from eDirectory 73 */ 74 75 /* 76 * Function to remove all special characters from a string (rfc2254). 77 * Use whenever exact matching is to be done ... 78 */ 79 char *ldap_filter_correct (char *in) 80 { 81 size_t i, count; 82 char *out, *ptr; 83 size_t len = strlen(in); 84 85 for (i = 0, count = 0; i < len; i++) 86 switch (in[i]) { 87 case '*': 88 case '(': 89 case ')': 90 case '\\': 91 case '\0': 92 count ++; 93 } 94 95 out = (char *)malloc((len + (count * 2) + 1) * sizeof (char)); 96 assert (out != NULL); 97 memset(out, 0, len + (count * 2) + 1); 98 99 for (i = 0, ptr = out; i < len; i++) 100 switch (in[i]) { 101 case '*': 102 ptr[0] = '\\'; 103 ptr[1] = '2'; 104 ptr[2] = 'a'; 105 ptr += 3; 106 break; 107 case '(': 108 ptr[0] = '\\'; 109 ptr[1] = '2'; 110 ptr[2] = '8'; 111 ptr += 3; 112 break; 113 case ')': 114 ptr[0] = '\\'; 115 ptr[1] = '2'; 116 ptr[2] = '9'; 117 ptr += 3; 118 break; 119 case '\\': 120 ptr[0] = '\\'; 121 ptr[1] = '5'; 122 ptr[2] = 'c'; 123 ptr += 3; 124 break; 125 case '\0': 126 ptr[0] = '\\'; 127 ptr[1] = '0'; 128 ptr[2] = '0'; 129 ptr += 3; 130 break; 131 default: 132 ptr[0] = in[i]; 133 ptr += 1; 134 break; 135 } 136 137 /* ptr[count - 1] = '\0'; */ 138 139 return out; 140 } 141 142 static int principal_in_realm_2(krb5_principal principal, char *realm) { 143 /* Cross realm trust ... */ 144 if (principal->length == 2 && 145 principal->data[0].length == sizeof ("krbtgt") && 146 strncasecmp (principal->data[0].data, "krbtgt", sizeof ("krbtgt")) && 147 principal->data[1].length == strlen (realm) && 148 strncasecmp (principal->data[1].data, realm, strlen (realm))) 149 return 0; 150 151 if (strlen(realm) != principal->realm.length) 152 return 1; 153 154 if (strncasecmp(realm, principal->realm.data, principal->realm.length) != 0) 155 return 1; 156 157 return 0; 158 } 159 160 /* 161 * Lists the realms in the Directory. 162 */ 163 164 krb5_error_code 165 krb5_ldap_list_realm(context, realms) 166 krb5_context context; 167 char ***realms; 168 { 169 char **values = NULL; 170 unsigned int i = 0; 171 int count = 0; 172 krb5_error_code st = 0, tempst = 0; 173 LDAP *ld = NULL; 174 LDAPMessage *result = NULL, *ent = NULL; 175 kdb5_dal_handle *dal_handle = NULL; 176 krb5_ldap_context *ldap_context = NULL; 177 krb5_ldap_server_handle *ldap_server_handle = NULL; 178 179 SETUP_CONTEXT (); 180 181 /* get the kerberos container DN information */ 182 if (ldap_context->krbcontainer == NULL) { 183 if ((st = krb5_ldap_read_krbcontainer_params(context, 184 &(ldap_context->krbcontainer))) != 0) 185 goto cleanup; 186 } 187 188 /* get ldap handle */ 189 GET_HANDLE (); 190 191 { 192 char *cn[] = {"cn", NULL}; 193 LDAP_SEARCH(ldap_context->krbcontainer->DN, 194 LDAP_SCOPE_ONELEVEL, 195 "(objectclass=krbRealmContainer)", 196 cn); 197 } 198 199 *realms = NULL; 200 201 count = ldap_count_entries (ld, result); 202 if (count == -1) { 203 ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &st); 204 st = set_ldap_error (context, st, OP_SEARCH); 205 goto cleanup; 206 } 207 208 *realms = calloc(count+1, sizeof (char *)); 209 CHECK_NULL(*realms); 210 211 for (ent = ldap_first_entry(ld, result), count = 0; ent != NULL; 212 ent = ldap_next_entry(ld, ent)) { 213 214 if ((values = ldap_get_values (ld, ent, "cn")) != NULL) { 215 216 (*realms)[count] = strdup(values[0]); 217 CHECK_NULL((*realms)[count]); 218 count += 1; 219 220 ldap_value_free(values); 221 } 222 } /* for (ent= ... */ 223 ldap_msgfree(result); 224 225 cleanup: 226 227 /* some error, free up all the memory */ 228 if (st != 0) { 229 if (*realms) { 230 for (i=0; (*realms)[i] != NULL; ++i) { 231 free ((*realms)[i]); 232 } 233 free (*realms); 234 *realms = NULL; 235 } 236 } 237 238 /* If there are no elements, still return a NULL terminated array */ 239 240 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); 241 return st; 242 } 243 244 /* 245 * Delete the realm along with the principals belonging to the realm in the Directory. 246 */ 247 248 static void 249 delete_password_policy (krb5_pointer ptr, osa_policy_ent_t pol) 250 { 251 krb5_ldap_delete_password_policy ((krb5_context)ptr, pol->name); 252 } 253 254 krb5_error_code 255 krb5_ldap_delete_realm (context, lrealm) 256 krb5_context context; 257 char *lrealm; 258 { 259 LDAP *ld = NULL; 260 krb5_error_code st = 0, tempst=0; 261 char **values=NULL, **subtrees=NULL, **policy=NULL; 262 LDAPMessage **result_arr=NULL, *result = NULL, *ent = NULL; 263 krb5_principal principal; 264 int l=0, i=0, j=0, mask=0; 265 unsigned int ntree=0; 266 kdb5_dal_handle *dal_handle = NULL; 267 krb5_ldap_context *ldap_context = NULL; 268 krb5_ldap_server_handle *ldap_server_handle = NULL; 269 krb5_ldap_realm_params *rparam=NULL; 270 271 SETUP_CONTEXT (); 272 273 if (lrealm == NULL) { 274 st = EINVAL; 275 krb5_set_error_message (context, st, gettext("Realm information not available")); 276 goto cleanup; 277 } 278 279 if ((st=krb5_ldap_read_realm_params(context, lrealm, &rparam, &mask)) != 0) 280 goto cleanup; 281 282 /* get ldap handle */ 283 GET_HANDLE (); 284 285 /* delete all the principals belonging to the realm in the tree */ 286 { 287 char *attr[] = {"krbprincipalname", NULL}, *realm=NULL, filter[256]; 288 krb5_ldap_context lcontext; 289 290 realm = ldap_filter_correct (lrealm); 291 assert (sizeof (filter) >= sizeof ("(krbprincipalname=)") + 292 strlen (realm) + 2 /* "*@" */ + 1); 293 294 /*LINTED*/ 295 sprintf (filter, "(krbprincipalname=*@%s)", realm); 296 free (realm); 297 298 /* LDAP_SEARCH(NULL, LDAP_SCOPE_SUBTREE, filter, attr); */ 299 memset(&lcontext, 0, sizeof(krb5_ldap_context)); 300 lcontext.lrparams = rparam; 301 if ((st=krb5_get_subtree_info(&lcontext, &subtrees, &ntree)) != 0) 302 goto cleanup; 303 304 result_arr = (LDAPMessage **) calloc(ntree+1, sizeof(LDAPMessage *)); 305 if (result_arr == NULL) { 306 st = ENOMEM; 307 goto cleanup; 308 } 309 310 for (l=0; l < ntree; ++l) { 311 LDAP_SEARCH(subtrees[l], rparam->search_scope, filter, attr); 312 result_arr[l] = result; 313 } 314 } 315 316 /* NOTE: Here all the principals should be cached and the ldap handle should be freed, 317 * as a DAL-LDAP interface is called right down here. Caching might be constrained by 318 * availability of the memory. The caching is not done, however there would be limit 319 * on the minimum number of handles for a server and it is 2. As the DAL-LDAP is not 320 * thread-safe this should suffice. 321 */ 322 for (j=0; (result=result_arr[j]) != NULL; ++j) { 323 for (ent = ldap_first_entry (ld, result); ent != NULL; 324 ent = ldap_next_entry (ld, ent)) { 325 if ((values = ldap_get_values(ld, ent, "krbPrincipalName")) != NULL) { 326 for (i = 0; values[i] != NULL; ++i) { 327 krb5_parse_name(context, values[i], &principal); 328 if (principal_in_realm_2(principal, lrealm) == 0) { 329 int nent = 0; 330 if ((st=krb5_ldap_delete_principal(context, principal, 331 &nent)) != LDAP_SUCCESS) 332 goto cleanup; 333 } 334 krb5_free_principal(context, principal); 335 } 336 ldap_value_free(values); 337 } 338 } 339 ldap_msgfree(result); 340 } 341 342 /* Delete all password policies */ 343 krb5_ldap_iterate_password_policy (context, "*", delete_password_policy, context); 344 345 /* Delete all ticket policies */ 346 { 347 if ((st = krb5_ldap_list_policy (context, ldap_context->lrparams->realmdn, &policy)) != 0) { 348 prepend_err_str (context, gettext("Error reading ticket policy: "), st, st); 349 goto cleanup; 350 } 351 352 for (i = 0; policy [i] != NULL; i++) 353 krb5_ldap_delete_policy(context, policy[i]); 354 } 355 356 /* Delete the realm object */ 357 if ((st=ldap_delete_ext_s(ld, ldap_context->lrparams->realmdn, NULL, NULL)) != LDAP_SUCCESS) { 358 int ost = st; 359 st = translate_ldap_error (st, OP_DEL); 360 krb5_set_error_message (context, st, gettext("Realm Delete FAILED: %s"), 361 ldap_err2string(ost)); 362 } 363 364 cleanup: 365 if (subtrees) { 366 for (l=0; l < ntree; ++l) { 367 if (subtrees[l]) 368 free (subtrees[l]); 369 } 370 free (subtrees); 371 } 372 373 if (policy != NULL) { 374 for (i = 0; policy[i] != NULL; i++) 375 free (policy[i]); 376 free (policy); 377 } 378 379 krb5_ldap_free_realm_params(rparam); 380 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); 381 return st; 382 } 383 384 385 /* 386 * Modify the realm attributes in the Directory. 387 */ 388 389 krb5_error_code 390 krb5_ldap_modify_realm(context, rparams, mask) 391 krb5_context context; 392 krb5_ldap_realm_params *rparams; 393 int mask; 394 { 395 LDAP *ld=NULL; 396 krb5_error_code st=0; 397 char **strval=NULL, *strvalprc[5]={NULL}; 398 #ifdef HAVE_EDIRECTORY 399 char **values=NULL; 400 char **oldkdcservers=NULL, **oldadminservers=NULL, **oldpasswdservers=NULL; 401 LDAPMessage *result=NULL, *ent=NULL; 402 int count=0; 403 char errbuf[1024]; 404 #endif 405 LDAPMod **mods = NULL; 406 #ifdef HAVE_EDIRECTORY 407 int i=0; 408 #endif 409 /* Solaris kerberos: oldmask isn't used */ 410 /* int oldmask=0, objectmask=0,k=0; */ 411 int objectmask=0,k=0; 412 kdb5_dal_handle *dal_handle=NULL; 413 krb5_ldap_context *ldap_context=NULL; 414 krb5_ldap_server_handle *ldap_server_handle=NULL; 415 416 if (mask == 0) 417 return 0; 418 419 if (rparams == NULL) { 420 st = EINVAL; 421 return st; 422 } 423 424 SETUP_CONTEXT (); 425 426 /* Check validity of arguments */ 427 if (ldap_context->krbcontainer == NULL || 428 rparams->tl_data == NULL || 429 rparams->tl_data->tl_data_contents == NULL || 430 ((mask & LDAP_REALM_SUBTREE) && rparams->subtree == NULL) || 431 ((mask & LDAP_REALM_CONTREF) && rparams->containerref == NULL) || 432 #ifdef HAVE_EDIRECTORY 433 ((mask & LDAP_REALM_KDCSERVERS) && rparams->kdcservers == NULL) || 434 ((mask & LDAP_REALM_ADMINSERVERS) && rparams->adminservers == NULL) || 435 ((mask & LDAP_REALM_PASSWDSERVERS) && rparams->passwdservers == NULL) || 436 #endif 437 0) { 438 st = EINVAL; 439 goto cleanup; 440 } 441 442 /* get ldap handle */ 443 GET_HANDLE (); 444 /* Solaris kerberos: oldmask isn't used */ 445 #if 0 /************** Begin IFDEF'ed OUT *******************************/ 446 /* get the oldmask obtained from the krb5_ldap_read_realm_params */ 447 { 448 void *voidptr=NULL; 449 450 if ((st=decode_tl_data(rparams->tl_data, KDB_TL_MASK, &voidptr)) == 0) { 451 oldmask = *((int *) voidptr); 452 free (voidptr); 453 } else { 454 st = EINVAL; 455 krb5_set_error_message (context, st, gettext("'tl_data' not available")); 456 goto cleanup; 457 } 458 } 459 #endif /**************** END IFDEF'ed OUT *******************************/ 460 461 462 /* SUBTREE ATTRIBUTE */ 463 if (mask & LDAP_REALM_SUBTREE) { 464 if ( rparams->subtree!=NULL) { 465 /*replace the subtrees with the present if the subtrees are present*/ 466 for(k=0;k<rparams->subtreecount && rparams->subtree[k]!=NULL;k++) { 467 if (strlen(rparams->subtree[k]) != 0) { 468 st = checkattributevalue(ld, rparams->subtree[k], "Objectclass", subtreeclass, 469 &objectmask); 470 CHECK_CLASS_VALIDITY(st, objectmask, "subtree value: "); 471 } 472 } 473 strval = rparams->subtree; 474 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbsubtrees", LDAP_MOD_REPLACE, 475 strval)) != 0) { 476 goto cleanup; 477 } 478 } 479 } 480 481 /* CONTAINERREF ATTRIBUTE */ 482 if (mask & LDAP_REALM_CONTREF) { 483 if (strlen(rparams->containerref) != 0 ) { 484 st = checkattributevalue(ld, rparams->containerref, "Objectclass", subtreeclass, 485 &objectmask); 486 CHECK_CLASS_VALIDITY(st, objectmask, "container reference value: "); 487 strvalprc[0] = rparams->containerref; 488 strvalprc[1] = NULL; 489 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbPrincContainerRef", LDAP_MOD_REPLACE, 490 strvalprc)) != 0) 491 goto cleanup; 492 } 493 } 494 495 /* SEARCHSCOPE ATTRIBUTE */ 496 if (mask & LDAP_REALM_SEARCHSCOPE) { 497 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbsearchscope", LDAP_MOD_REPLACE, 498 (rparams->search_scope == LDAP_SCOPE_ONELEVEL 499 || rparams->search_scope == LDAP_SCOPE_SUBTREE) ? 500 rparams->search_scope : LDAP_SCOPE_SUBTREE)) != 0) 501 goto cleanup; 502 } 503 504 if (mask & LDAP_REALM_MAXRENEWLIFE) { 505 506 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxRenewableAge", LDAP_MOD_REPLACE, 507 rparams->max_renewable_life)) != 0) 508 goto cleanup; 509 } 510 511 /* krbMaxTicketLife ATTRIBUTE */ 512 513 if (mask & LDAP_REALM_MAXTICKETLIFE) { 514 515 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxTicketLife", LDAP_MOD_REPLACE, 516 rparams->max_life)) != 0) 517 goto cleanup; 518 } 519 520 /* krbTicketFlags ATTRIBUTE */ 521 522 if (mask & LDAP_REALM_KRBTICKETFLAGS) { 523 524 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbTicketFlags", LDAP_MOD_REPLACE, 525 rparams->tktflags)) != 0) 526 goto cleanup; 527 } 528 529 530 #ifdef HAVE_EDIRECTORY 531 532 /* KDCSERVERS ATTRIBUTE */ 533 if (mask & LDAP_REALM_KDCSERVERS) { 534 /* validate the server list */ 535 for (i=0; rparams->kdcservers[i] != NULL; ++i) { 536 st = checkattributevalue(ld, rparams->kdcservers[i], "objectClass", kdcclass, 537 &objectmask); 538 CHECK_CLASS_VALIDITY(st, objectmask, "kdc service object value: "); 539 } 540 541 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbkdcservers", LDAP_MOD_REPLACE, 542 rparams->kdcservers)) != 0) 543 goto cleanup; 544 } 545 546 /* ADMINSERVERS ATTRIBUTE */ 547 if (mask & LDAP_REALM_ADMINSERVERS) { 548 /* validate the server list */ 549 for (i=0; rparams->adminservers[i] != NULL; ++i) { 550 st = checkattributevalue(ld, rparams->adminservers[i], "objectClass", adminclass, 551 &objectmask); 552 CHECK_CLASS_VALIDITY(st, objectmask, "admin service object value: "); 553 } 554 555 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbadmservers", LDAP_MOD_REPLACE, 556 rparams->adminservers)) != 0) 557 goto cleanup; 558 } 559 560 /* PASSWDSERVERS ATTRIBUTE */ 561 if (mask & LDAP_REALM_PASSWDSERVERS) { 562 /* validate the server list */ 563 for (i=0; rparams->passwdservers[i] != NULL; ++i) { 564 st = checkattributevalue(ld, rparams->passwdservers[i], "objectClass", pwdclass, 565 &objectmask); 566 CHECK_CLASS_VALIDITY(st, objectmask, "password service object value: "); 567 } 568 569 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdservers", LDAP_MOD_REPLACE, 570 rparams->passwdservers)) != 0) 571 goto cleanup; 572 } 573 574 /* 575 * Read the old values of the krbkdcservers, krbadmservers and 576 * krbpwdservers. This information is later used to decided the 577 * deletions/additions to the list. 578 */ 579 if (mask & LDAP_REALM_KDCSERVERS || mask & LDAP_REALM_ADMINSERVERS || 580 mask & LDAP_REALM_PASSWDSERVERS) { 581 char *servers[] = {"krbKdcServers", "krbAdmServers", "krbPwdServers", NULL}; 582 583 if ((st= ldap_search_ext_s(ld, 584 rparams->realmdn, 585 LDAP_SCOPE_BASE, 586 0, 587 servers, 588 0, 589 NULL, 590 NULL, 591 NULL, 592 0, 593 &result)) != LDAP_SUCCESS) { 594 st = set_ldap_error (context, st, OP_SEARCH); 595 goto cleanup; 596 } 597 598 ent = ldap_first_entry(ld, result); 599 if (ent) { 600 if ((values=ldap_get_values(ld, ent, "krbKdcServers")) != NULL) { 601 count = ldap_count_values(values); 602 if ((st=copy_arrays(values, &oldkdcservers, count)) != 0) 603 goto cleanup; 604 ldap_value_free(values); 605 } 606 607 if ((values=ldap_get_values(ld, ent, "krbAdmServers")) != NULL) { 608 count = ldap_count_values(values); 609 if ((st=copy_arrays(values, &oldadminservers, count)) != 0) 610 goto cleanup; 611 ldap_value_free(values); 612 } 613 614 if ((values=ldap_get_values(ld, ent, "krbPwdServers")) != NULL) { 615 count = ldap_count_values(values); 616 if ((st=copy_arrays(values, &oldpasswdservers, count)) != 0) 617 goto cleanup; 618 ldap_value_free(values); 619 } 620 } 621 ldap_msgfree(result); 622 } 623 #endif 624 625 /* Realm modify opearation */ 626 if (mods != NULL) { 627 if ((st=ldap_modify_ext_s(ld, rparams->realmdn, mods, NULL, NULL)) != LDAP_SUCCESS) { 628 st = set_ldap_error (context, st, OP_MOD); 629 goto cleanup; 630 } 631 } 632 633 #ifdef HAVE_EDIRECTORY 634 /* krbRealmReferences attribute is updated here, depending on the additions/deletions 635 * to the 4 servers' list. 636 */ 637 if (mask & LDAP_REALM_KDCSERVERS) { 638 char **newkdcservers=NULL; 639 640 count = ldap_count_values(rparams->kdcservers); 641 if ((st=copy_arrays(rparams->kdcservers, &newkdcservers, count)) != 0) 642 goto cleanup; 643 644 /* find the deletions and additions to the server list */ 645 if (oldkdcservers && newkdcservers) 646 disjoint_members(oldkdcservers, newkdcservers); 647 648 /* delete the krbRealmReferences attribute from the servers that are dis-associated. */ 649 if (oldkdcservers) 650 for (i=0; oldkdcservers[i]; ++i) 651 if ((st=deleteAttribute(ld, oldkdcservers[i], "krbRealmReferences", 652 rparams->realmdn)) != 0) { 653 snprintf (errbuf, sizeof(errbuf), gettext("Error removing 'krbRealmReferences' from %s: "), 654 oldkdcservers[i]); 655 prepend_err_str (context, errbuf, st, st); 656 goto cleanup; 657 } 658 659 /* add the krbRealmReferences attribute from the servers that are associated. */ 660 if (newkdcservers) 661 for (i=0; newkdcservers[i]; ++i) 662 if ((st=updateAttribute(ld, newkdcservers[i], "krbRealmReferences", 663 rparams->realmdn)) != 0) { 664 snprintf (errbuf, sizeof(errbuf), gettext("Error adding 'krbRealmReferences' to %s: "), 665 newkdcservers[i]); 666 prepend_err_str (context, errbuf, st, st); 667 goto cleanup; 668 } 669 670 if (newkdcservers) 671 ldap_value_free(newkdcservers); 672 } 673 674 if (mask & LDAP_REALM_ADMINSERVERS) { 675 char **newadminservers=NULL; 676 677 count = ldap_count_values(rparams->adminservers); 678 if ((st=copy_arrays(rparams->adminservers, &newadminservers, count)) != 0) 679 goto cleanup; 680 681 /* find the deletions and additions to the server list */ 682 if (oldadminservers && newadminservers) 683 disjoint_members(oldadminservers, newadminservers); 684 685 /* delete the krbRealmReferences attribute from the servers that are dis-associated. */ 686 if (oldadminservers) 687 for (i=0; oldadminservers[i]; ++i) 688 if ((st=deleteAttribute(ld, oldadminservers[i], "krbRealmReferences", 689 rparams->realmdn)) != 0) { 690 snprintf(errbuf, sizeof(errbuf), gettext("Error removing 'krbRealmReferences' from " 691 "%s: "), oldadminservers[i]); 692 prepend_err_str (context, errbuf, st, st); 693 goto cleanup; 694 } 695 696 /* add the krbRealmReferences attribute from the servers that are associated. */ 697 if (newadminservers) 698 for (i=0; newadminservers[i]; ++i) 699 if ((st=updateAttribute(ld, newadminservers[i], "krbRealmReferences", 700 rparams->realmdn)) != 0) { 701 snprintf(errbuf, sizeof(errbuf), gettext("Error adding 'krbRealmReferences' to %s: "), 702 newadminservers[i]); 703 prepend_err_str (context, errbuf, st, st); 704 goto cleanup; 705 } 706 if (newadminservers) 707 ldap_value_free(newadminservers); 708 } 709 710 if (mask & LDAP_REALM_PASSWDSERVERS) { 711 char **newpasswdservers=NULL; 712 713 count = ldap_count_values(rparams->passwdservers); 714 if ((st=copy_arrays(rparams->passwdservers, &newpasswdservers, count)) != 0) 715 goto cleanup; 716 717 /* find the deletions and additions to the server list */ 718 if (oldpasswdservers && newpasswdservers) 719 disjoint_members(oldpasswdservers, newpasswdservers); 720 721 /* delete the krbRealmReferences attribute from the servers that are dis-associated. */ 722 if (oldpasswdservers) 723 for (i=0; oldpasswdservers[i]; ++i) 724 if ((st=deleteAttribute(ld, oldpasswdservers[i], "krbRealmReferences", 725 rparams->realmdn)) != 0) { 726 snprintf(errbuf, sizeof(errbuf), gettext("Error removing 'krbRealmReferences' from " 727 "%s: "), oldpasswdservers[i]); 728 prepend_err_str (context, errbuf, st, st); 729 goto cleanup; 730 } 731 732 /* add the krbRealmReferences attribute from the servers that are associated. */ 733 if (newpasswdservers) 734 for (i=0; newpasswdservers[i]; ++i) 735 if ((st=updateAttribute(ld, newpasswdservers[i], "krbRealmReferences", 736 rparams->realmdn)) != 0) { 737 snprintf(errbuf, sizeof(errbuf), gettext("Error adding 'krbRealmReferences' to %s: "), 738 newpasswdservers[i]); 739 prepend_err_str (context, errbuf, st, st); 740 goto cleanup; 741 } 742 if (newpasswdservers) 743 ldap_value_free(newpasswdservers); 744 } 745 #endif 746 747 cleanup: 748 749 #ifdef HAVE_EDIRECTORY 750 if (oldkdcservers) { 751 for (i=0; oldkdcservers[i]; ++i) 752 free(oldkdcservers[i]); 753 free(oldkdcservers); 754 } 755 756 if (oldadminservers) { 757 for (i=0; oldadminservers[i]; ++i) 758 free(oldadminservers[i]); 759 free(oldadminservers); 760 } 761 762 if (oldpasswdservers) { 763 for (i=0; oldpasswdservers[i]; ++i) 764 free(oldpasswdservers[i]); 765 free(oldpasswdservers); 766 } 767 #endif 768 769 ldap_mods_free(mods, 1); 770 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); 771 return st; 772 } 773 774 775 776 /* 777 * Create the Kerberos container in the Directory 778 */ 779 780 krb5_error_code 781 krb5_ldap_create_krbcontainer(context, krbcontparams) 782 krb5_context context; 783 const krb5_ldap_krbcontainer_params *krbcontparams; 784 { 785 LDAP *ld=NULL; 786 char *strval[2]={NULL}, *kerberoscontdn=NULL, **rdns=NULL; 787 int pmask=0; 788 LDAPMod **mods = NULL; 789 krb5_error_code st=0; 790 kdb5_dal_handle *dal_handle=NULL; 791 krb5_ldap_context *ldap_context=NULL; 792 krb5_ldap_server_handle *ldap_server_handle=NULL; 793 #ifdef HAVE_EDIRECTORY 794 int crmask=0; 795 #endif 796 797 SETUP_CONTEXT (); 798 799 /* get ldap handle */ 800 GET_HANDLE (); 801 802 if (krbcontparams != NULL && krbcontparams->DN != NULL) { 803 kerberoscontdn = krbcontparams->DN; 804 } else { 805 /* If the user has not given, use the default cn=Kerberos,cn=Security */ 806 #ifdef HAVE_EDIRECTORY 807 kerberoscontdn = KERBEROS_CONTAINER; 808 #else 809 st = EINVAL; 810 krb5_set_error_message (context, st, gettext("Kerberos Container information is missing")); 811 goto cleanup; 812 #endif 813 } 814 815 strval[0] = "krbContainer"; 816 strval[1] = NULL; 817 if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0) 818 goto cleanup; 819 820 rdns = ldap_explode_dn(kerberoscontdn, 1); 821 if (rdns == NULL) { 822 st = EINVAL; 823 krb5_set_error_message(context, st, gettext("Invalid Kerberos container DN")); 824 goto cleanup; 825 } 826 827 strval[0] = rdns[0]; 828 strval[1] = NULL; 829 if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0) 830 goto cleanup; 831 832 /* check if the policy reference value exists and is of krbticketpolicyreference object class */ 833 if (krbcontparams && krbcontparams->policyreference) { 834 st = checkattributevalue(ld, krbcontparams->policyreference, "objectclass", policyclass, 835 &pmask); 836 CHECK_CLASS_VALIDITY(st, pmask, "ticket policy object value: "); 837 838 strval[0] = krbcontparams->policyreference; 839 strval[1] = NULL; 840 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbticketpolicyreference", LDAP_MOD_ADD, 841 strval)) != 0) 842 goto cleanup; 843 } 844 845 /* create the kerberos container */ 846 if ((st = ldap_add_ext_s(ld, kerberoscontdn, mods, NULL, NULL)) != LDAP_SUCCESS) { 847 int ost = st; 848 st = translate_ldap_error (st, OP_ADD); 849 krb5_set_error_message (context, st, gettext("Kerberos Container create FAILED: %s"), ldap_err2string(ost)); 850 goto cleanup; 851 } 852 853 #ifdef HAVE_EDIRECTORY 854 855 /* free the mods array */ 856 ldap_mods_free(mods, 1); 857 mods=NULL; 858 859 /* check whether the security container is bound to krbcontainerrefaux object class */ 860 if ((st=checkattributevalue(ld, SECURITY_CONTAINER, "objectClass", 861 krbContainerRefclass, &crmask)) != 0) { 862 prepend_err_str (context, gettext("Security Container read FAILED: "), st, st); 863 /* delete Kerberos Container, status ignored intentionally */ 864 ldap_delete_ext_s(ld, kerberoscontdn, NULL, NULL); 865 goto cleanup; 866 } 867 868 if (crmask == 0) { 869 /* Security Container is extended with krbcontainerrefaux object class */ 870 strval[0] = "krbContainerRefAux"; 871 if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0) 872 goto cleanup; 873 } 874 875 strval[0] = kerberoscontdn; 876 strval[1] = NULL; 877 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbcontainerreference", LDAP_MOD_ADD, strval)) != 0) 878 goto cleanup; 879 880 /* update the security container with krbContainerReference attribute */ 881 if ((st=ldap_modify_ext_s(ld, SECURITY_CONTAINER, mods, NULL, NULL)) != LDAP_SUCCESS) { 882 int ost = st; 883 st = translate_ldap_error (st, OP_MOD); 884 krb5_set_error_message (context, st, gettext("Security Container update FAILED: %s"), ldap_err2string(ost)); 885 /* delete Kerberos Container, status ignored intentionally */ 886 ldap_delete_ext_s(ld, kerberoscontdn, NULL, NULL); 887 goto cleanup; 888 } 889 #endif 890 891 cleanup: 892 893 if (rdns) 894 ldap_value_free (rdns); 895 896 ldap_mods_free(mods, 1); 897 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); 898 return(st); 899 } 900 901 /* 902 * Delete the Kerberos container in the Directory 903 */ 904 905 krb5_error_code 906 krb5_ldap_delete_krbcontainer(krb5_context context, 907 const krb5_ldap_krbcontainer_params *krbcontparams) 908 { 909 LDAP *ld=NULL; 910 char *kerberoscontdn=NULL; 911 krb5_error_code st=0; 912 kdb5_dal_handle *dal_handle=NULL; 913 krb5_ldap_context *ldap_context=NULL; 914 krb5_ldap_server_handle *ldap_server_handle=NULL; 915 916 SETUP_CONTEXT (); 917 918 /* get ldap handle */ 919 GET_HANDLE (); 920 921 if (krbcontparams != NULL && krbcontparams->DN != NULL) { 922 kerberoscontdn = krbcontparams->DN; 923 } else { 924 /* If the user has not given, use the default cn=Kerberos,cn=Security */ 925 #ifdef HAVE_EDIRECTORY 926 kerberoscontdn = KERBEROS_CONTAINER; 927 #else 928 st = EINVAL; 929 krb5_set_error_message (context, st, gettext("Kerberos Container information is missing")); 930 goto cleanup; 931 #endif 932 } 933 934 /* delete the kerberos container */ 935 if ((st = ldap_delete_ext_s(ld, kerberoscontdn, NULL, NULL)) != LDAP_SUCCESS) { 936 int ost = st; 937 st = translate_ldap_error (st, OP_ADD); 938 krb5_set_error_message (context, st, gettext("Kerberos Container delete FAILED: %s"), ldap_err2string(ost)); 939 goto cleanup; 940 } 941 942 cleanup: 943 944 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); 945 return(st); 946 } 947 948 949 /* 950 * Create Realm in eDirectory. This is used by kdb5_util 951 */ 952 953 krb5_error_code 954 krb5_ldap_create_realm(context, rparams, mask) 955 krb5_context context; 956 krb5_ldap_realm_params *rparams; 957 int mask; 958 { 959 LDAP *ld=NULL; 960 krb5_error_code st=0; 961 char *dn=NULL; 962 char *strval[4]={NULL}; 963 char *contref[2]={NULL}; 964 LDAPMod **mods = NULL; 965 int i=0, objectmask=0, subtreecount=0; 966 kdb5_dal_handle *dal_handle=NULL; 967 krb5_ldap_context *ldap_context=NULL; 968 krb5_ldap_server_handle *ldap_server_handle=NULL; 969 #ifdef HAVE_EDIRECTORY 970 char errbuf[1024]; 971 #endif 972 char *realm_name; 973 974 SETUP_CONTEXT (); 975 976 /* Check input validity ... */ 977 if (ldap_context->krbcontainer == NULL || 978 ldap_context->krbcontainer->DN == NULL || 979 rparams == NULL || 980 rparams->realm_name == NULL || 981 ((mask & LDAP_REALM_SUBTREE) && rparams->subtree == NULL) || 982 ((mask & LDAP_REALM_CONTREF) && rparams->containerref == NULL) || 983 ((mask & LDAP_REALM_POLICYREFERENCE) && rparams->policyreference == NULL) || 984 #ifdef HAVE_EDIRECTORY 985 ((mask & LDAP_REALM_KDCSERVERS) && rparams->kdcservers == NULL) || 986 ((mask & LDAP_REALM_ADMINSERVERS) && rparams->adminservers == NULL) || 987 ((mask & LDAP_REALM_PASSWDSERVERS) && rparams->passwdservers == NULL) || 988 #endif 989 0) { 990 st = EINVAL; 991 return st; 992 } 993 994 if (ldap_context->krbcontainer == NULL) { 995 if ((st = krb5_ldap_read_krbcontainer_params(context, 996 &(ldap_context->krbcontainer))) != 0) 997 goto cleanup; 998 } 999 1000 /* get ldap handle */ 1001 GET_HANDLE (); 1002 1003 realm_name = rparams->realm_name; 1004 1005 dn = malloc(strlen("cn=") + strlen(realm_name) + strlen(ldap_context->krbcontainer->DN) + 2); 1006 CHECK_NULL(dn); 1007 /*LINTED*/ 1008 sprintf(dn, "cn=%s,%s", realm_name, ldap_context->krbcontainer->DN); 1009 1010 strval[0] = realm_name; 1011 strval[1] = NULL; 1012 if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0) 1013 goto cleanup; 1014 1015 strval[0] = "top"; 1016 strval[1] = "krbrealmcontainer"; 1017 strval[2] = "krbticketpolicyaux"; 1018 strval[3] = NULL; 1019 1020 if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0) 1021 goto cleanup; 1022 1023 /* SUBTREE ATTRIBUTE */ 1024 if (mask & LDAP_REALM_SUBTREE) { 1025 if ( rparams->subtree!=NULL) { 1026 subtreecount = rparams->subtreecount; 1027 for (i=0; rparams->subtree[i]!=NULL && i<subtreecount; i++) { 1028 if (strlen(rparams->subtree[i]) != 0) { 1029 st = checkattributevalue(ld, rparams->subtree[i], "Objectclass", subtreeclass, 1030 &objectmask); 1031 CHECK_CLASS_VALIDITY(st, objectmask, "realm object value: "); 1032 } 1033 } 1034 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbsubtrees", LDAP_MOD_ADD, 1035 rparams->subtree)) != 0) { 1036 goto cleanup; 1037 } 1038 } 1039 } 1040 1041 /* CONTAINER REFERENCE ATTRIBUTE */ 1042 if (mask & LDAP_REALM_CONTREF) { 1043 if (strlen(rparams->containerref) != 0 ) { 1044 st = checkattributevalue(ld, rparams->containerref, "Objectclass", subtreeclass, 1045 &objectmask); 1046 CHECK_CLASS_VALIDITY(st, objectmask, "realm object value: "); 1047 contref[0] = rparams->containerref; 1048 contref[1] = NULL; 1049 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbPrincContainerRef", LDAP_MOD_ADD, 1050 contref)) != 0) 1051 goto cleanup; 1052 } 1053 } 1054 1055 /* SEARCHSCOPE ATTRIBUTE */ 1056 if (mask & LDAP_REALM_SEARCHSCOPE) { 1057 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbsearchscope", LDAP_MOD_ADD, 1058 (rparams->search_scope == LDAP_SCOPE_ONELEVEL 1059 || rparams->search_scope == LDAP_SCOPE_SUBTREE) ? 1060 rparams->search_scope : LDAP_SCOPE_SUBTREE)) != 0) 1061 goto cleanup; 1062 } 1063 if (mask & LDAP_REALM_MAXRENEWLIFE) { 1064 1065 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxRenewableAge", LDAP_MOD_ADD, 1066 rparams->max_renewable_life)) != 0) 1067 goto cleanup; 1068 } 1069 1070 /* krbMaxTicketLife ATTRIBUTE */ 1071 1072 if (mask & LDAP_REALM_MAXTICKETLIFE) { 1073 1074 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxTicketLife", LDAP_MOD_ADD, 1075 rparams->max_life)) != 0) 1076 goto cleanup; 1077 } 1078 1079 /* krbTicketFlags ATTRIBUTE */ 1080 1081 if (mask & LDAP_REALM_KRBTICKETFLAGS) { 1082 1083 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbTicketFlags", LDAP_MOD_ADD, 1084 rparams->tktflags)) != 0) 1085 goto cleanup; 1086 } 1087 1088 1089 #ifdef HAVE_EDIRECTORY 1090 1091 /* KDCSERVERS ATTRIBUTE */ 1092 if (mask & LDAP_REALM_KDCSERVERS) { 1093 /* validate the server list */ 1094 for (i=0; rparams->kdcservers[i] != NULL; ++i) { 1095 st = checkattributevalue(ld, rparams->kdcservers[i], "objectClass", kdcclass, 1096 &objectmask); 1097 CHECK_CLASS_VALIDITY(st, objectmask, "kdc service object value: "); 1098 1099 } 1100 1101 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbkdcservers", LDAP_MOD_ADD, 1102 rparams->kdcservers)) != 0) 1103 goto cleanup; 1104 } 1105 1106 /* ADMINSERVERS ATTRIBUTE */ 1107 if (mask & LDAP_REALM_ADMINSERVERS) { 1108 /* validate the server list */ 1109 for (i=0; rparams->adminservers[i] != NULL; ++i) { 1110 st = checkattributevalue(ld, rparams->adminservers[i], "objectClass", adminclass, 1111 &objectmask); 1112 CHECK_CLASS_VALIDITY(st, objectmask, "admin service object value: "); 1113 1114 } 1115 1116 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbadmservers", LDAP_MOD_ADD, 1117 rparams->adminservers)) != 0) 1118 goto cleanup; 1119 } 1120 1121 /* PASSWDSERVERS ATTRIBUTE */ 1122 if (mask & LDAP_REALM_PASSWDSERVERS) { 1123 /* validate the server list */ 1124 for (i=0; rparams->passwdservers[i] != NULL; ++i) { 1125 st = checkattributevalue(ld, rparams->passwdservers[i], "objectClass", pwdclass, 1126 &objectmask); 1127 CHECK_CLASS_VALIDITY(st, objectmask, "password service object value: "); 1128 1129 } 1130 1131 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdservers", LDAP_MOD_ADD, 1132 rparams->passwdservers)) != 0) 1133 goto cleanup; 1134 } 1135 #endif 1136 1137 /* realm creation operation */ 1138 if ((st=ldap_add_ext_s(ld, dn, mods, NULL, NULL)) != LDAP_SUCCESS) { 1139 st = set_ldap_error (context, st, OP_ADD); 1140 goto cleanup; 1141 } 1142 1143 #ifdef HAVE_EDIRECTORY 1144 if (mask & LDAP_REALM_KDCSERVERS) 1145 for (i=0; rparams->kdcservers[i]; ++i) 1146 if ((st=updateAttribute(ld, rparams->kdcservers[i], "krbRealmReferences", dn)) != 0) { 1147 snprintf(errbuf, sizeof(errbuf), gettext("Error adding 'krbRealmReferences' to %s: "), 1148 rparams->kdcservers[i]); 1149 prepend_err_str (context, errbuf, st, st); 1150 /* delete Realm, status ignored intentionally */ 1151 ldap_delete_ext_s(ld, dn, NULL, NULL); 1152 goto cleanup; 1153 } 1154 1155 if (mask & LDAP_REALM_ADMINSERVERS) 1156 for (i=0; rparams->adminservers[i]; ++i) 1157 if ((st=updateAttribute(ld, rparams->adminservers[i], "krbRealmReferences", dn)) != 0) { 1158 snprintf(errbuf, sizeof(errbuf), gettext("Error adding 'krbRealmReferences' to %s: "), 1159 rparams->adminservers[i]); 1160 prepend_err_str (context, errbuf, st, st); 1161 /* delete Realm, status ignored intentionally */ 1162 ldap_delete_ext_s(ld, dn, NULL, NULL); 1163 goto cleanup; 1164 } 1165 1166 if (mask & LDAP_REALM_PASSWDSERVERS) 1167 for (i=0; rparams->passwdservers[i]; ++i) 1168 if ((st=updateAttribute(ld, rparams->passwdservers[i], "krbRealmReferences", dn)) != 0) { 1169 snprintf(errbuf, sizeof(errbuf), gettext("Error adding 'krbRealmReferences' to %s: "), 1170 rparams->passwdservers[i]); 1171 prepend_err_str (context, errbuf, st, st); 1172 /* delete Realm, status ignored intentionally */ 1173 ldap_delete_ext_s(ld, dn, NULL, NULL); 1174 goto cleanup; 1175 } 1176 #endif 1177 1178 cleanup: 1179 1180 if (dn) 1181 free(dn); 1182 1183 ldap_mods_free(mods, 1); 1184 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); 1185 return st; 1186 } 1187 1188 /* 1189 * Read the realm container configuration from eDirectory for the specified realm. 1190 */ 1191 1192 krb5_error_code 1193 krb5_ldap_read_realm_params(context, lrealm, rlparamp, mask) 1194 krb5_context context; 1195 char *lrealm; 1196 krb5_ldap_realm_params **rlparamp; 1197 int *mask; 1198 { 1199 char **values=NULL, *krbcontDN=NULL /*, *curr=NULL */; 1200 #ifdef HAVE_EDIRECTORY 1201 unsigned int count=0; 1202 #endif 1203 krb5_error_code st=0, tempst=0; 1204 LDAP *ld=NULL; 1205 LDAPMessage *result=NULL,*ent=NULL; 1206 krb5_ldap_realm_params *rlparams=NULL; 1207 kdb5_dal_handle *dal_handle=NULL; 1208 krb5_ldap_context *ldap_context=NULL; 1209 krb5_ldap_server_handle *ldap_server_handle=NULL; 1210 int x=0; 1211 1212 SETUP_CONTEXT (); 1213 1214 /* validate the input parameter */ 1215 if (lrealm == NULL || 1216 ldap_context->krbcontainer == NULL || 1217 ldap_context->krbcontainer->DN == NULL) { 1218 st = EINVAL; 1219 goto cleanup; 1220 } 1221 1222 /* read kerberos container, if not read already */ 1223 if (ldap_context->krbcontainer == NULL) { 1224 if ((st = krb5_ldap_read_krbcontainer_params(context, 1225 &(ldap_context->krbcontainer))) != 0) 1226 goto cleanup; 1227 } 1228 /* get ldap handle */ 1229 GET_HANDLE (); 1230 1231 /* Initialize realm container structure */ 1232 rlparams =(krb5_ldap_realm_params *) malloc(sizeof(krb5_ldap_realm_params)); 1233 CHECK_NULL(rlparams); 1234 memset((char *) rlparams, 0, sizeof(krb5_ldap_realm_params)); 1235 1236 /* allocate tl_data structure to store MASK information */ 1237 rlparams->tl_data = malloc (sizeof(krb5_tl_data)); 1238 if (rlparams->tl_data == NULL) { 1239 st = ENOMEM; 1240 goto cleanup; 1241 } 1242 memset((char *) rlparams->tl_data, 0, sizeof(krb5_tl_data)); 1243 rlparams->tl_data->tl_data_type = KDB_TL_USER_INFO; 1244 1245 /* set the mask parameter to 0 */ 1246 *mask = 0; 1247 1248 /* set default values */ 1249 rlparams->search_scope = LDAP_SCOPE_SUBTREE; 1250 1251 krbcontDN = ldap_context->krbcontainer->DN; 1252 1253 rlparams->realmdn = (char *) malloc(strlen("cn=") + strlen(lrealm) + strlen(krbcontDN) + 2); 1254 if (rlparams->realmdn == NULL) { 1255 st = ENOMEM; 1256 goto cleanup; 1257 } 1258 /*LINTED*/ 1259 sprintf(rlparams->realmdn, "cn=%s,%s", lrealm, krbcontDN); 1260 1261 /* populate the realm name in the structure */ 1262 rlparams->realm_name = strdup(lrealm); 1263 CHECK_NULL(rlparams->realm_name); 1264 1265 LDAP_SEARCH(rlparams->realmdn, LDAP_SCOPE_BASE, "(objectclass=krbRealmContainer)", realm_attributes); 1266 1267 if ((st = ldap_count_entries(ld, result)) <= 0) { 1268 /* This could happen when the DN used to bind and read the realm object 1269 * does not have sufficient rights to read its attributes 1270 */ 1271 st = KRB5_KDB_ACCESS_ERROR; /* return some other error ? */ 1272 goto cleanup; 1273 } 1274 1275 ent = ldap_first_entry (ld, result); 1276 if (ent == NULL) { 1277 ldap_get_option (ld, LDAP_OPT_ERROR_NUMBER, (void *) &st); 1278 #if 0 1279 st = translate_ldap_error(st, OP_SEARCH); 1280 #endif 1281 goto cleanup; 1282 } 1283 1284 /* Read the attributes */ 1285 { 1286 if ((values=ldap_get_values(ld, ent, "krbSubTrees")) != NULL) { 1287 rlparams->subtreecount = ldap_count_values(values); 1288 rlparams->subtree = (char **) malloc(sizeof(char *) * (rlparams->subtreecount + 1)); 1289 if (rlparams->subtree == NULL) { 1290 st = ENOMEM; 1291 goto cleanup; 1292 } 1293 for (x=0; x<rlparams->subtreecount; x++) { 1294 rlparams->subtree[x] = strdup(values[x]); 1295 if (rlparams->subtree[x] == NULL) { 1296 st = ENOMEM; 1297 goto cleanup; 1298 } 1299 } 1300 rlparams->subtree[rlparams->subtreecount] = NULL; 1301 *mask |= LDAP_REALM_SUBTREE; 1302 ldap_value_free(values); 1303 } 1304 1305 if((values=ldap_get_values(ld, ent, "krbPrincContainerRef")) != NULL) { 1306 rlparams->containerref = strdup(values[0]); 1307 if(rlparams->containerref == NULL) { 1308 st = ENOMEM; 1309 goto cleanup; 1310 } 1311 *mask |= LDAP_REALM_CONTREF; 1312 ldap_value_free(values); 1313 } 1314 1315 if ((values=ldap_get_values(ld, ent, "krbSearchScope")) != NULL) { 1316 rlparams->search_scope=atoi(values[0]); 1317 /* searchscope can be ONE-LEVEL or SUBTREE, else default to SUBTREE */ 1318 if (!(rlparams->search_scope==1 || rlparams->search_scope==2)) 1319 rlparams->search_scope = LDAP_SCOPE_SUBTREE; 1320 *mask |= LDAP_REALM_SEARCHSCOPE; 1321 ldap_value_free(values); 1322 } 1323 1324 if ((values=ldap_get_values(ld, ent, "krbMaxTicketLife")) != NULL) { 1325 rlparams->max_life = atoi(values[0]); 1326 *mask |= LDAP_REALM_MAXTICKETLIFE; 1327 ldap_value_free(values); 1328 } 1329 1330 if ((values=ldap_get_values(ld, ent, "krbMaxRenewableAge")) != NULL) { 1331 rlparams->max_renewable_life = atoi(values[0]); 1332 *mask |= LDAP_REALM_MAXRENEWLIFE; 1333 ldap_value_free(values); 1334 } 1335 1336 if ((values=ldap_get_values(ld, ent, "krbTicketFlags")) != NULL) { 1337 rlparams->tktflags = atoi(values[0]); 1338 *mask |= LDAP_REALM_KRBTICKETFLAGS; 1339 ldap_value_free(values); 1340 } 1341 1342 #ifdef HAVE_EDIRECTORY 1343 1344 if ((values=ldap_get_values(ld, ent, "krbKdcServers")) != NULL) { 1345 count = ldap_count_values(values); 1346 if ((st=copy_arrays(values, &(rlparams->kdcservers), (int) count)) != 0) 1347 goto cleanup; 1348 *mask |= LDAP_REALM_KDCSERVERS; 1349 ldap_value_free(values); 1350 } 1351 1352 if ((values=ldap_get_values(ld, ent, "krbAdmServers")) != NULL) { 1353 count = ldap_count_values(values); 1354 if ((st=copy_arrays(values, &(rlparams->adminservers), (int) count)) != 0) 1355 goto cleanup; 1356 *mask |= LDAP_REALM_ADMINSERVERS; 1357 ldap_value_free(values); 1358 } 1359 1360 if ((values=ldap_get_values(ld, ent, "krbPwdServers")) != NULL) { 1361 count = ldap_count_values(values); 1362 if ((st=copy_arrays(values, &(rlparams->passwdservers), (int) count)) != 0) 1363 goto cleanup; 1364 *mask |= LDAP_REALM_PASSWDSERVERS; 1365 ldap_value_free(values); 1366 } 1367 #endif 1368 } 1369 ldap_msgfree(result); 1370 1371 /* 1372 * If all of maxtktlife, maxrenewlife and ticketflags are not directly 1373 * available, use the policy dn from the policy reference attribute, if 1374 * available, to fetch the missing. 1375 */ 1376 1377 if ((!(*mask & LDAP_REALM_MAXTICKETLIFE && *mask & LDAP_REALM_MAXRENEWLIFE && 1378 *mask & LDAP_REALM_KRBTICKETFLAGS)) && rlparams->policyreference) { 1379 1380 LDAP_SEARCH_1(rlparams->policyreference, LDAP_SCOPE_BASE, NULL, policy_attributes, IGNORE_STATUS); 1381 if (st != LDAP_SUCCESS && st != LDAP_NO_SUCH_OBJECT) { 1382 int ost = st; 1383 st = translate_ldap_error (st, OP_SEARCH); 1384 krb5_set_error_message (context, st, gettext("Policy object read failed: %s"), ldap_err2string(ost)); 1385 goto cleanup; 1386 } 1387 ent = ldap_first_entry (ld, result); 1388 if (ent != NULL) { 1389 if ((*mask & LDAP_REALM_MAXTICKETLIFE) == 0) { 1390 if ((values=ldap_get_values(ld, ent, "krbmaxticketlife")) != NULL) { 1391 rlparams->max_life = atoi(values[0]); 1392 *mask |= LDAP_REALM_MAXTICKETLIFE; 1393 ldap_value_free(values); 1394 } 1395 } 1396 1397 if ((*mask & LDAP_REALM_MAXRENEWLIFE) == 0) { 1398 if ((values=ldap_get_values(ld, ent, "krbmaxrenewableage")) != NULL) { 1399 rlparams->max_renewable_life = atoi(values[0]); 1400 *mask |= LDAP_REALM_MAXRENEWLIFE; 1401 ldap_value_free(values); 1402 } 1403 } 1404 1405 if ((*mask & LDAP_REALM_KRBTICKETFLAGS) == 0) { 1406 if ((values=ldap_get_values(ld, ent, "krbticketflags")) != NULL) { 1407 rlparams->tktflags = atoi(values[0]); 1408 *mask |= LDAP_REALM_KRBTICKETFLAGS; 1409 ldap_value_free(values); 1410 } 1411 } 1412 } 1413 ldap_msgfree(result); 1414 } 1415 1416 rlparams->mask = *mask; 1417 *rlparamp = rlparams; 1418 st = store_tl_data(rlparams->tl_data, KDB_TL_MASK, mask); 1419 1420 cleanup: 1421 1422 /* if there is an error, free allocated structures */ 1423 if (st != 0) { 1424 krb5_ldap_free_realm_params(rlparams); 1425 *rlparamp=NULL; 1426 } 1427 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); 1428 return st; 1429 } 1430 1431 1432 /* 1433 Free the krb5_ldap_realm_params. 1434 */ 1435 void 1436 krb5_ldap_free_realm_params(rparams) 1437 krb5_ldap_realm_params *rparams; 1438 { 1439 int i=0; 1440 1441 if (rparams) { 1442 if (rparams->realmdn) 1443 free(rparams->realmdn); 1444 1445 if (rparams->realm_name) 1446 krb5_xfree(rparams->realm_name); 1447 1448 if (rparams->subtree) { 1449 for (i=0; i<rparams->subtreecount && rparams->subtree[i] ; i++) 1450 krb5_xfree(rparams->subtree[i]); 1451 krb5_xfree(rparams->subtree); 1452 } 1453 1454 if (rparams->kdcservers) { 1455 for (i=0; rparams->kdcservers[i]; ++i) 1456 krb5_xfree(rparams->kdcservers[i]); 1457 krb5_xfree(rparams->kdcservers); 1458 } 1459 1460 if (rparams->adminservers) { 1461 for (i=0; rparams->adminservers[i]; ++i) 1462 krb5_xfree(rparams->adminservers[i]); 1463 krb5_xfree(rparams->adminservers); 1464 } 1465 1466 if (rparams->passwdservers) { 1467 for (i=0; rparams->passwdservers[i]; ++i) 1468 krb5_xfree(rparams->passwdservers[i]); 1469 krb5_xfree(rparams->passwdservers); 1470 } 1471 1472 if (rparams->tl_data) { 1473 if (rparams->tl_data->tl_data_contents) 1474 krb5_xfree(rparams->tl_data->tl_data_contents); 1475 krb5_xfree(rparams->tl_data); 1476 } 1477 1478 if (rparams->mkey.contents) { 1479 memset(rparams->mkey.contents, 0, rparams->mkey.length); 1480 krb5_xfree(rparams->mkey.contents); 1481 } 1482 1483 krb5_xfree(rparams); 1484 } 1485 return; 1486 } 1487 1488 /* 1489 * ****************************************************************************** 1490 * DAL functions 1491 * ****************************************************************************** 1492 */ 1493 1494 krb5_error_code 1495 krb5_ldap_delete_realm_1(krb5_context kcontext, char *conf_section, char **db_args) 1496 { 1497 krb5_error_code status = KRB5_PLUGIN_OP_NOTSUPP; 1498 krb5_set_error_message(kcontext, status, "LDAP %s", error_message(status)); 1499 return status; 1500 } 1501