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