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