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 */
ldap_filter_correct(char * in)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
principal_in_realm_2(krb5_principal principal,char * realm)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
krb5_ldap_list_realm(context,realms)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
delete_password_policy(krb5_pointer ptr,osa_policy_ent_t pol)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
krb5_ldap_delete_realm(context,lrealm)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
krb5_ldap_modify_realm(context,rparams,mask)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
krb5_ldap_create_krbcontainer(context,krbcontparams)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
krb5_ldap_delete_krbcontainer(krb5_context context,const krb5_ldap_krbcontainer_params * krbcontparams)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
krb5_ldap_create_realm(context,rparams,mask)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
krb5_ldap_read_realm_params(context,lrealm,rlparamp,mask)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
krb5_ldap_free_realm_params(rparams)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
krb5_ldap_delete_realm_1(krb5_context kcontext,char * conf_section,char ** db_args)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