1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* plugins/kdb/ldap/libkdb_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 2006 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
42 #define END_OF_LIST -1
43 char *realm_attributes[] = {"krbSearchScope","krbSubTrees", "krbPrincContainerRef",
44 "krbMaxTicketLife", "krbMaxRenewableAge",
45 "krbTicketFlags", "krbUpEnabled",
46 "krbLdapServers",
47 "krbKdcServers", "krbAdmServers",
48 "krbPwdServers", NULL};
49
50
51 char *policy_attributes[] = { "krbMaxTicketLife",
52 "krbMaxRenewableAge",
53 "krbTicketFlags",
54 NULL };
55
56
57
58 char *policyclass[] = { "krbTicketPolicy", NULL };
59 char *kdcclass[] = { "krbKdcService", NULL };
60 char *adminclass[] = { "krbAdmService", NULL };
61 char *pwdclass[] = { "krbPwdService", NULL };
62 char *subtreeclass[] = { "Organization", "OrganizationalUnit", "Domain", "krbContainer",
63 "krbRealmContainer", "Country", "Locality", NULL };
64
65
66 char *krbContainerRefclass[] = { "krbContainerRefAux", NULL};
67
68 /*
69 * list realms from eDirectory
70 */
71
72 /* Return a copy of in, quoting all characters which are special in an LDAP
73 * filter (RFC 4515) or DN string (RFC 4514). Return NULL on failure. */
74 char *
ldap_filter_correct(char * in)75 ldap_filter_correct (char *in)
76 {
77 size_t count;
78 const char special[] = "*()\\ #\"+,;<>";
79 struct k5buf buf;
80
81 k5_buf_init_dynamic(&buf);
82 while (TRUE) {
83 count = strcspn(in, special);
84 k5_buf_add_len(&buf, in, count);
85 in += count;
86 if (*in == '\0')
87 break;
88 k5_buf_add_fmt(&buf, "\\%2x", (unsigned char)*in++);
89 }
90 return k5_buf_cstring(&buf);
91 }
92
93 static int
principal_in_realm_2(krb5_principal principal,char * realm)94 principal_in_realm_2(krb5_principal principal, char *realm) {
95 /* Cross realm trust ... */
96 if (principal->length == 2 &&
97 principal->data[0].length == sizeof ("krbtgt") &&
98 strncasecmp (principal->data[0].data, "krbtgt", sizeof ("krbtgt")) &&
99 principal->data[1].length == strlen (realm) &&
100 strncasecmp (principal->data[1].data, realm, strlen (realm)))
101 return 0;
102
103 if (strlen(realm) != principal->realm.length)
104 return 1;
105
106 if (strncasecmp(realm, principal->realm.data, principal->realm.length) != 0)
107 return 1;
108
109 return 0;
110 }
111
112 /*
113 * Lists the realms in the Directory.
114 */
115
116 krb5_error_code
krb5_ldap_list_realm(krb5_context context,char *** realms)117 krb5_ldap_list_realm(krb5_context context, char ***realms)
118 {
119 char **values = NULL;
120 size_t i = 0;
121 int count = 0;
122 krb5_error_code st = 0, tempst = 0;
123 LDAP *ld = NULL;
124 LDAPMessage *result = NULL, *ent = NULL;
125 kdb5_dal_handle *dal_handle = NULL;
126 krb5_ldap_context *ldap_context = NULL;
127 krb5_ldap_server_handle *ldap_server_handle = NULL;
128
129 SETUP_CONTEXT ();
130
131 /* get the kerberos container DN information */
132 if (ldap_context->container_dn == NULL) {
133 if ((st = krb5_ldap_read_krbcontainer_dn(context,
134 &(ldap_context->container_dn))) != 0)
135 goto cleanup;
136 }
137
138 /* get ldap handle */
139 GET_HANDLE ();
140
141 {
142 char *cn[] = {"cn", NULL};
143 LDAP_SEARCH(ldap_context->container_dn,
144 LDAP_SCOPE_ONELEVEL,
145 "(objectclass=krbRealmContainer)",
146 cn);
147 }
148
149 *realms = NULL;
150
151 count = ldap_count_entries (ld, result);
152 if (count == -1) {
153 ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &st);
154 st = set_ldap_error (context, st, OP_SEARCH);
155 goto cleanup;
156 }
157
158 *realms = calloc((unsigned int) count+1, sizeof (char *));
159 CHECK_NULL(*realms);
160
161 for (ent = ldap_first_entry(ld, result), count = 0; ent != NULL;
162 ent = ldap_next_entry(ld, ent)) {
163
164 if ((values = ldap_get_values (ld, ent, "cn")) != NULL) {
165
166 (*realms)[count] = strdup(values[0]);
167 CHECK_NULL((*realms)[count]);
168 count += 1;
169
170 ldap_value_free(values);
171 }
172 } /* for (ent= ... */
173
174 cleanup:
175
176 /* some error, free up all the memory */
177 if (st != 0) {
178 if (*realms) {
179 for (i=0; (*realms)[i] != NULL; ++i) {
180 free ((*realms)[i]);
181 }
182 free (*realms);
183 *realms = NULL;
184 }
185 }
186
187 /* If there are no elements, still return a NULL terminated array */
188
189 ldap_msgfree(result);
190 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
191 return st;
192 }
193
194 /*
195 * Delete the realm along with the principals belonging to the realm in the Directory.
196 */
197
198 static void
delete_password_policy(krb5_pointer ptr,osa_policy_ent_t pol)199 delete_password_policy (krb5_pointer ptr, osa_policy_ent_t pol)
200 {
201 krb5_ldap_delete_password_policy ((krb5_context)ptr, pol->name);
202 }
203
204 krb5_error_code
krb5_ldap_delete_realm(krb5_context context,char * lrealm)205 krb5_ldap_delete_realm (krb5_context context, char *lrealm)
206 {
207 LDAP *ld = NULL;
208 krb5_error_code st = 0, tempst=0;
209 char **values=NULL, **subtrees=NULL, **policy=NULL;
210 LDAPMessage **result_arr=NULL, *result = NULL, *ent = NULL;
211 krb5_principal principal;
212 size_t i=0, j=0, l=0, ntree=0;
213 int mask=0;
214 kdb5_dal_handle *dal_handle = NULL;
215 krb5_ldap_context *ldap_context = NULL;
216 krb5_ldap_server_handle *ldap_server_handle = NULL;
217 krb5_ldap_realm_params *rparam=NULL;
218
219 SETUP_CONTEXT ();
220
221 if (lrealm == NULL) {
222 st = EINVAL;
223 k5_setmsg(context, st, _("Realm information not available"));
224 goto cleanup;
225 }
226
227 if ((st=krb5_ldap_read_realm_params(context, lrealm, &rparam, &mask)) != 0)
228 goto cleanup;
229
230 /* get ldap handle */
231 GET_HANDLE ();
232
233 /* delete all the principals belonging to the realm in the tree */
234 {
235 char *attr[] = {"krbprincipalname", NULL}, *realm=NULL, filter[256];
236 krb5_ldap_context lcontext;
237
238 realm = ldap_filter_correct (lrealm);
239 assert (sizeof (filter) >= sizeof ("(krbprincipalname=)") +
240 strlen (realm) + 2 /* "*@" */ + 1);
241
242 snprintf (filter, sizeof(filter), "(krbprincipalname=*@%s)", realm);
243 free (realm);
244
245 /* LDAP_SEARCH(NULL, LDAP_SCOPE_SUBTREE, filter, attr); */
246 memset(&lcontext, 0, sizeof(krb5_ldap_context));
247 lcontext.lrparams = rparam;
248 if ((st=krb5_get_subtree_info(&lcontext, &subtrees, &ntree)) != 0)
249 goto cleanup;
250
251 result_arr = (LDAPMessage **) calloc((unsigned int)ntree+1,
252 sizeof(LDAPMessage *));
253 if (result_arr == NULL) {
254 st = ENOMEM;
255 goto cleanup;
256 }
257
258 for (l=0; l < ntree; ++l) {
259 LDAP_SEARCH(subtrees[l], rparam->search_scope, filter, attr);
260 result_arr[l] = result;
261 }
262 }
263
264 /* NOTE: Here all the principals should be cached and the ldap handle should be freed,
265 * as a DAL-LDAP interface is called right down here. Caching might be constrained by
266 * availability of the memory. The caching is not done, however there would be limit
267 * on the minimum number of handles for a server and it is 2. As the DAL-LDAP is not
268 * thread-safe this should suffice.
269 */
270 for (j=0; (result=result_arr[j]) != NULL; ++j) {
271 for (ent = ldap_first_entry (ld, result); ent != NULL;
272 ent = ldap_next_entry (ld, ent)) {
273 if ((values = ldap_get_values(ld, ent, "krbPrincipalName")) != NULL) {
274 for (i = 0; values[i] != NULL && !st; ++i) {
275 krb5_parse_name(context, values[i], &principal);
276 if (principal_in_realm_2(principal, lrealm) == 0) {
277 st=krb5_ldap_delete_principal(context, principal);
278 if (st == KRB5_KDB_NOENTRY)
279 st = 0;
280 }
281 krb5_free_principal(context, principal);
282 }
283 ldap_value_free(values);
284 if (st)
285 goto cleanup;
286 }
287 }
288 }
289
290 /* Delete all password policies */
291 krb5_ldap_iterate_password_policy (context, "*", delete_password_policy, context);
292
293 /* Delete all ticket policies */
294 {
295 if ((st = krb5_ldap_list_policy (context, ldap_context->lrparams->realmdn, &policy)) != 0) {
296 k5_prependmsg(context, st, _("Error reading ticket policy"));
297 goto cleanup;
298 }
299
300 for (i = 0; policy [i] != NULL; i++)
301 krb5_ldap_delete_policy(context, policy[i]);
302 }
303
304 /* Delete the realm object */
305 if ((st=ldap_delete_ext_s(ld, ldap_context->lrparams->realmdn, NULL, NULL)) != LDAP_SUCCESS) {
306 int ost = st;
307 st = translate_ldap_error (st, OP_DEL);
308 k5_setmsg(context, st, _("Realm Delete FAILED: %s"),
309 ldap_err2string(ost));
310 }
311
312 cleanup:
313 if (subtrees) {
314 for (l=0; l < ntree; ++l) {
315 if (subtrees[l])
316 free (subtrees[l]);
317 }
318 free (subtrees);
319 }
320
321 if (result_arr != NULL) {
322 for (l = 0; l < ntree; l++)
323 ldap_msgfree(result_arr[l]);
324 free(result_arr);
325 }
326
327 if (policy != NULL) {
328 for (i = 0; policy[i] != NULL; i++)
329 free (policy[i]);
330 free (policy);
331 }
332
333 krb5_ldap_free_realm_params(rparam);
334 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
335 return st;
336 }
337
338
339 /*
340 * Modify the realm attributes in the Directory.
341 */
342
343 krb5_error_code
krb5_ldap_modify_realm(krb5_context context,krb5_ldap_realm_params * rparams,int mask)344 krb5_ldap_modify_realm(krb5_context context, krb5_ldap_realm_params *rparams,
345 int mask)
346 {
347 LDAP *ld=NULL;
348 krb5_error_code st=0;
349 char **strval=NULL, *strvalprc[5]={NULL};
350 LDAPMod **mods = NULL;
351 size_t k=0;
352 int objectmask=0;
353 kdb5_dal_handle *dal_handle=NULL;
354 krb5_ldap_context *ldap_context=NULL;
355 krb5_ldap_server_handle *ldap_server_handle=NULL;
356
357 if (mask == 0)
358 return 0;
359
360 if (rparams == NULL) {
361 st = EINVAL;
362 return st;
363 }
364
365 SETUP_CONTEXT ();
366
367 /* Check validity of arguments */
368 if (ldap_context->container_dn == NULL ||
369 rparams->tl_data == NULL ||
370 rparams->tl_data->tl_data_contents == NULL ||
371 ((mask & LDAP_REALM_SUBTREE) && rparams->subtree == NULL) ||
372 ((mask & LDAP_REALM_CONTREF) && rparams->containerref == NULL) ||
373 0) {
374 st = EINVAL;
375 goto cleanup;
376 }
377
378 /* get ldap handle */
379 GET_HANDLE ();
380
381 /* SUBTREE ATTRIBUTE */
382 if (mask & LDAP_REALM_SUBTREE) {
383 if ( rparams->subtree!=NULL) {
384 /*replace the subtrees with the present if the subtrees are present*/
385 for(k=0;k<rparams->subtreecount && rparams->subtree[k]!=NULL;k++) {
386 if (strlen(rparams->subtree[k]) != 0) {
387 st = checkattributevalue(ld, rparams->subtree[k], "Objectclass", subtreeclass,
388 &objectmask);
389 CHECK_CLASS_VALIDITY(st, objectmask, _("subtree value: "));
390 }
391 }
392 strval = rparams->subtree;
393 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbsubtrees", LDAP_MOD_REPLACE,
394 strval)) != 0) {
395 goto cleanup;
396 }
397 }
398 }
399
400 /* CONTAINERREF ATTRIBUTE */
401 if (mask & LDAP_REALM_CONTREF) {
402 if (strlen(rparams->containerref) != 0 ) {
403 st = checkattributevalue(ld, rparams->containerref, "Objectclass", subtreeclass,
404 &objectmask);
405 CHECK_CLASS_VALIDITY(st, objectmask,
406 _("container reference value: "));
407 strvalprc[0] = rparams->containerref;
408 strvalprc[1] = NULL;
409 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbPrincContainerRef", LDAP_MOD_REPLACE,
410 strvalprc)) != 0)
411 goto cleanup;
412 }
413 }
414
415 /* SEARCHSCOPE ATTRIBUTE */
416 if (mask & LDAP_REALM_SEARCHSCOPE) {
417 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbsearchscope", LDAP_MOD_REPLACE,
418 (rparams->search_scope == LDAP_SCOPE_ONELEVEL
419 || rparams->search_scope == LDAP_SCOPE_SUBTREE) ?
420 rparams->search_scope : LDAP_SCOPE_SUBTREE)) != 0)
421 goto cleanup;
422 }
423
424 if (mask & LDAP_REALM_MAXRENEWLIFE) {
425
426 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxRenewableAge", LDAP_MOD_REPLACE,
427 rparams->max_renewable_life)) != 0)
428 goto cleanup;
429 }
430
431 /* krbMaxTicketLife ATTRIBUTE */
432
433 if (mask & LDAP_REALM_MAXTICKETLIFE) {
434
435 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxTicketLife", LDAP_MOD_REPLACE,
436 rparams->max_life)) != 0)
437 goto cleanup;
438 }
439
440 /* krbTicketFlags ATTRIBUTE */
441
442 if (mask & LDAP_REALM_KRBTICKETFLAGS) {
443
444 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbTicketFlags", LDAP_MOD_REPLACE,
445 rparams->tktflags)) != 0)
446 goto cleanup;
447 }
448
449
450 /* Realm modify operation */
451 if (mods != NULL) {
452 if ((st=ldap_modify_ext_s(ld, rparams->realmdn, mods, NULL, NULL)) != LDAP_SUCCESS) {
453 st = set_ldap_error (context, st, OP_MOD);
454 goto cleanup;
455 }
456 }
457
458 cleanup:
459
460 ldap_mods_free(mods, 1);
461 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
462 return st;
463 }
464
465
466
467 /*
468 * Create the Kerberos container in the Directory if it does not exist
469 */
470
471 krb5_error_code
krb5_ldap_create_krbcontainer(krb5_context context,const char * dn)472 krb5_ldap_create_krbcontainer(krb5_context context, const char *dn)
473 {
474 LDAP *ld=NULL;
475 char *strval[2]={NULL}, **rdns=NULL;
476 LDAPMod **mods = NULL;
477 krb5_error_code st=0;
478 kdb5_dal_handle *dal_handle=NULL;
479 krb5_ldap_context *ldap_context=NULL;
480 krb5_ldap_server_handle *ldap_server_handle=NULL;
481
482 SETUP_CONTEXT ();
483
484 /* get ldap handle */
485 GET_HANDLE ();
486
487 if (dn == NULL) {
488 st = EINVAL;
489 k5_setmsg(context, st, _("Kerberos Container information is missing"));
490 goto cleanup;
491 }
492
493 strval[0] = "krbContainer";
494 strval[1] = NULL;
495 if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
496 goto cleanup;
497
498 rdns = ldap_explode_dn(dn, 1);
499 if (rdns == NULL) {
500 st = EINVAL;
501 k5_setmsg(context, st, _("Invalid Kerberos container DN"));
502 goto cleanup;
503 }
504
505 strval[0] = rdns[0];
506 strval[1] = NULL;
507 if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0)
508 goto cleanup;
509
510 /* create the kerberos container */
511 st = ldap_add_ext_s(ld, dn, mods, NULL, NULL);
512 if (st == LDAP_ALREADY_EXISTS)
513 st = LDAP_SUCCESS;
514 if (st != LDAP_SUCCESS) {
515 int ost = st;
516 st = translate_ldap_error (st, OP_ADD);
517 k5_setmsg(context, st, _("Kerberos Container create FAILED: %s"),
518 ldap_err2string(ost));
519 goto cleanup;
520 }
521
522 cleanup:
523
524 if (rdns)
525 ldap_value_free (rdns);
526
527 ldap_mods_free(mods, 1);
528 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
529 return(st);
530 }
531
532 /*
533 * Delete the Kerberos container in the Directory
534 */
535
536 krb5_error_code
krb5_ldap_delete_krbcontainer(krb5_context context,const char * dn)537 krb5_ldap_delete_krbcontainer(krb5_context context, const char *dn)
538 {
539 LDAP *ld=NULL;
540 krb5_error_code st=0;
541 kdb5_dal_handle *dal_handle=NULL;
542 krb5_ldap_context *ldap_context=NULL;
543 krb5_ldap_server_handle *ldap_server_handle=NULL;
544
545 SETUP_CONTEXT ();
546
547 /* get ldap handle */
548 GET_HANDLE ();
549
550 if (dn == NULL) {
551 st = EINVAL;
552 k5_setmsg(context, st, _("Kerberos Container information is missing"));
553 goto cleanup;
554 }
555
556 /* delete the kerberos container */
557 if ((st = ldap_delete_ext_s(ld, dn, NULL, NULL)) != LDAP_SUCCESS) {
558 int ost = st;
559 st = translate_ldap_error (st, OP_ADD);
560 k5_setmsg(context, st, _("Kerberos Container delete FAILED: %s"),
561 ldap_err2string(ost));
562 goto cleanup;
563 }
564
565 cleanup:
566
567 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
568 return(st);
569 }
570
571
572 /*
573 * Create Realm in eDirectory. This is used by kdb5_util
574 */
575
576 krb5_error_code
krb5_ldap_create_realm(krb5_context context,krb5_ldap_realm_params * rparams,int mask)577 krb5_ldap_create_realm(krb5_context context, krb5_ldap_realm_params *rparams,
578 int mask)
579 {
580 LDAP *ld=NULL;
581 krb5_error_code st=0;
582 char *dn=NULL;
583 char *strval[4]={NULL};
584 char *contref[2]={NULL};
585 LDAPMod **mods = NULL;
586 size_t i=0, subtreecount=0;
587 int objectmask=0;
588 kdb5_dal_handle *dal_handle=NULL;
589 krb5_ldap_context *ldap_context=NULL;
590 krb5_ldap_server_handle *ldap_server_handle=NULL;
591 char *realm_name;
592
593 SETUP_CONTEXT ();
594
595 /* Check input validity ... */
596 if (ldap_context->container_dn == NULL ||
597 rparams == NULL ||
598 rparams->realm_name == NULL ||
599 ((mask & LDAP_REALM_SUBTREE) && rparams->subtree == NULL) ||
600 ((mask & LDAP_REALM_CONTREF) && rparams->containerref == NULL) ||
601 0) {
602 st = EINVAL;
603 return st;
604 }
605
606 /* get ldap handle */
607 GET_HANDLE ();
608
609 realm_name = rparams->realm_name;
610
611 if (asprintf(&dn, "cn=%s,%s", realm_name, ldap_context->container_dn) < 0)
612 dn = NULL;
613 CHECK_NULL(dn);
614
615 strval[0] = realm_name;
616 strval[1] = NULL;
617 if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0)
618 goto cleanup;
619
620 strval[0] = "top";
621 strval[1] = "krbrealmcontainer";
622 strval[2] = "krbticketpolicyaux";
623 strval[3] = NULL;
624
625 if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
626 goto cleanup;
627
628 /* SUBTREE ATTRIBUTE */
629 if (mask & LDAP_REALM_SUBTREE) {
630 if ( rparams->subtree!=NULL) {
631 subtreecount = rparams->subtreecount;
632 for (i=0; rparams->subtree[i]!=NULL && i<subtreecount; i++) {
633 if (strlen(rparams->subtree[i]) != 0) {
634 st = checkattributevalue(ld, rparams->subtree[i], "Objectclass", subtreeclass,
635 &objectmask);
636 CHECK_CLASS_VALIDITY(st, objectmask,
637 _("realm object value: "));
638 }
639 }
640 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbsubtrees", LDAP_MOD_ADD,
641 rparams->subtree)) != 0) {
642 goto cleanup;
643 }
644 }
645 }
646
647 /* CONTAINER REFERENCE ATTRIBUTE */
648 if (mask & LDAP_REALM_CONTREF) {
649 if (strlen(rparams->containerref) != 0 ) {
650 st = checkattributevalue(ld, rparams->containerref, "Objectclass", subtreeclass,
651 &objectmask);
652 CHECK_CLASS_VALIDITY(st, objectmask, "realm object value: ");
653 contref[0] = rparams->containerref;
654 contref[1] = NULL;
655 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbPrincContainerRef", LDAP_MOD_ADD,
656 contref)) != 0)
657 goto cleanup;
658 }
659 }
660
661 /* SEARCHSCOPE ATTRIBUTE */
662 if (mask & LDAP_REALM_SEARCHSCOPE) {
663 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbsearchscope", LDAP_MOD_ADD,
664 (rparams->search_scope == LDAP_SCOPE_ONELEVEL
665 || rparams->search_scope == LDAP_SCOPE_SUBTREE) ?
666 rparams->search_scope : LDAP_SCOPE_SUBTREE)) != 0)
667 goto cleanup;
668 }
669 if (mask & LDAP_REALM_MAXRENEWLIFE) {
670
671 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxRenewableAge", LDAP_MOD_ADD,
672 rparams->max_renewable_life)) != 0)
673 goto cleanup;
674 }
675
676 /* krbMaxTicketLife ATTRIBUTE */
677
678 if (mask & LDAP_REALM_MAXTICKETLIFE) {
679
680 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxTicketLife", LDAP_MOD_ADD,
681 rparams->max_life)) != 0)
682 goto cleanup;
683 }
684
685 /* krbTicketFlags ATTRIBUTE */
686
687 if (mask & LDAP_REALM_KRBTICKETFLAGS) {
688
689 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbTicketFlags", LDAP_MOD_ADD,
690 rparams->tktflags)) != 0)
691 goto cleanup;
692 }
693
694
695 /* realm creation operation */
696 if ((st=ldap_add_ext_s(ld, dn, mods, NULL, NULL)) != LDAP_SUCCESS) {
697 st = set_ldap_error (context, st, OP_ADD);
698 goto cleanup;
699 }
700
701 cleanup:
702
703 if (dn)
704 free(dn);
705
706 ldap_mods_free(mods, 1);
707 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
708 return st;
709 }
710
711 /*
712 * Read the realm container configuration from eDirectory for the specified realm.
713 */
714
715 krb5_error_code
krb5_ldap_read_realm_params(krb5_context context,char * lrealm,krb5_ldap_realm_params ** rlparamp,int * mask)716 krb5_ldap_read_realm_params(krb5_context context, char *lrealm,
717 krb5_ldap_realm_params **rlparamp, int *mask)
718 {
719 char **values=NULL;
720 krb5_error_code st=0, tempst=0;
721 LDAP *ld=NULL;
722 LDAPMessage *result=NULL,*ent=NULL;
723 krb5_ldap_realm_params *rlparams=NULL;
724 kdb5_dal_handle *dal_handle=NULL;
725 krb5_ldap_context *ldap_context=NULL;
726 krb5_ldap_server_handle *ldap_server_handle=NULL;
727 size_t x=0;
728
729 SETUP_CONTEXT ();
730
731 /* validate the input parameter */
732 if (lrealm == NULL || ldap_context->container_dn == NULL) {
733 st = EINVAL;
734 goto cleanup;
735 }
736
737 /* get ldap handle */
738 GET_HANDLE ();
739
740 /* Initialize realm container structure */
741 rlparams =(krb5_ldap_realm_params *) malloc(sizeof(krb5_ldap_realm_params));
742 CHECK_NULL(rlparams);
743 memset(rlparams, 0, sizeof(krb5_ldap_realm_params));
744
745 /* allocate tl_data structure to store MASK information */
746 rlparams->tl_data = malloc (sizeof(krb5_tl_data));
747 if (rlparams->tl_data == NULL) {
748 st = ENOMEM;
749 goto cleanup;
750 }
751 memset(rlparams->tl_data, 0, sizeof(krb5_tl_data));
752 rlparams->tl_data->tl_data_type = KDB_TL_USER_INFO;
753
754 /* set the mask parameter to 0 */
755 *mask = 0;
756
757 /* set default values */
758 rlparams->search_scope = LDAP_SCOPE_SUBTREE;
759
760 if (asprintf(&rlparams->realmdn, "cn=%s,%s", lrealm,
761 ldap_context->container_dn) < 0) {
762 rlparams->realmdn = NULL;
763 st = ENOMEM;
764 goto cleanup;
765 }
766
767 /* populate the realm name in the structure */
768 rlparams->realm_name = strdup(lrealm);
769 CHECK_NULL(rlparams->realm_name);
770
771 LDAP_SEARCH(rlparams->realmdn, LDAP_SCOPE_BASE, "(objectclass=krbRealmContainer)", realm_attributes);
772
773 if ((st = ldap_count_entries(ld, result)) <= 0) {
774 /* This could happen when the DN used to bind and read the realm object
775 * does not have sufficient rights to read its attributes
776 */
777 st = KRB5_KDB_ACCESS_ERROR; /* return some other error ? */
778 goto cleanup;
779 }
780
781 ent = ldap_first_entry (ld, result);
782 if (ent == NULL) {
783 ldap_get_option (ld, LDAP_OPT_ERROR_NUMBER, (void *) &st);
784 goto cleanup;
785 }
786
787 /* Read the attributes */
788 {
789 if ((values=ldap_get_values(ld, ent, "krbSubTrees")) != NULL) {
790 rlparams->subtreecount = ldap_count_values(values);
791 rlparams->subtree = (char **) malloc(sizeof(char *) * (rlparams->subtreecount + 1));
792 if (rlparams->subtree == NULL) {
793 st = ENOMEM;
794 goto cleanup;
795 }
796 for (x=0; x<rlparams->subtreecount; x++) {
797 rlparams->subtree[x] = strdup(values[x]);
798 if (rlparams->subtree[x] == NULL) {
799 st = ENOMEM;
800 goto cleanup;
801 }
802 }
803 rlparams->subtree[rlparams->subtreecount] = NULL;
804 *mask |= LDAP_REALM_SUBTREE;
805 ldap_value_free(values);
806 }
807
808 if((values=ldap_get_values(ld, ent, "krbPrincContainerRef")) != NULL) {
809 rlparams->containerref = strdup(values[0]);
810 if(rlparams->containerref == NULL) {
811 st = ENOMEM;
812 goto cleanup;
813 }
814 *mask |= LDAP_REALM_CONTREF;
815 ldap_value_free(values);
816 }
817
818 if ((values=ldap_get_values(ld, ent, "krbSearchScope")) != NULL) {
819 rlparams->search_scope=atoi(values[0]);
820 /* searchscope can be ONE-LEVEL or SUBTREE, else default to SUBTREE */
821 if (!(rlparams->search_scope==1 || rlparams->search_scope==2))
822 rlparams->search_scope = LDAP_SCOPE_SUBTREE;
823 *mask |= LDAP_REALM_SEARCHSCOPE;
824 ldap_value_free(values);
825 }
826
827 if ((values=ldap_get_values(ld, ent, "krbMaxTicketLife")) != NULL) {
828 rlparams->max_life = atoi(values[0]);
829 *mask |= LDAP_REALM_MAXTICKETLIFE;
830 ldap_value_free(values);
831 }
832
833 if ((values=ldap_get_values(ld, ent, "krbMaxRenewableAge")) != NULL) {
834 rlparams->max_renewable_life = atoi(values[0]);
835 *mask |= LDAP_REALM_MAXRENEWLIFE;
836 ldap_value_free(values);
837 }
838
839 if ((values=ldap_get_values(ld, ent, "krbTicketFlags")) != NULL) {
840 rlparams->tktflags = atoi(values[0]);
841 *mask |= LDAP_REALM_KRBTICKETFLAGS;
842 ldap_value_free(values);
843 }
844
845 }
846
847 rlparams->mask = *mask;
848 *rlparamp = rlparams;
849 st = store_tl_data(rlparams->tl_data, KDB_TL_MASK, mask);
850
851 cleanup:
852
853 /* if there is an error, free allocated structures */
854 if (st != 0) {
855 krb5_ldap_free_realm_params(rlparams);
856 *rlparamp=NULL;
857 }
858 ldap_msgfree(result);
859 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
860 return st;
861 }
862
863
864 /*
865 Free the krb5_ldap_realm_params.
866 */
867 void
krb5_ldap_free_realm_params(krb5_ldap_realm_params * rparams)868 krb5_ldap_free_realm_params(krb5_ldap_realm_params *rparams)
869 {
870 size_t i=0;
871
872 if (rparams) {
873 if (rparams->realmdn)
874 free(rparams->realmdn);
875
876 if (rparams->realm_name)
877 free(rparams->realm_name);
878
879 if (rparams->subtree) {
880 for (i=0; i<rparams->subtreecount && rparams->subtree[i] ; i++)
881 free(rparams->subtree[i]);
882 free(rparams->subtree);
883 }
884
885 if (rparams->containerref)
886 free(rparams->containerref);
887
888 if (rparams->kdcservers) {
889 for (i=0; rparams->kdcservers[i]; ++i)
890 free(rparams->kdcservers[i]);
891 free(rparams->kdcservers);
892 }
893
894 if (rparams->adminservers) {
895 for (i=0; rparams->adminservers[i]; ++i)
896 free(rparams->adminservers[i]);
897 free(rparams->adminservers);
898 }
899
900 if (rparams->passwdservers) {
901 for (i=0; rparams->passwdservers[i]; ++i)
902 free(rparams->passwdservers[i]);
903 free(rparams->passwdservers);
904 }
905
906 if (rparams->tl_data) {
907 if (rparams->tl_data->tl_data_contents)
908 free(rparams->tl_data->tl_data_contents);
909 free(rparams->tl_data);
910 }
911
912 free(rparams);
913 }
914 return;
915 }
916
917 /*
918 * ******************************************************************************
919 * DAL functions
920 * ******************************************************************************
921 */
922
923 krb5_error_code
krb5_ldap_delete_realm_1(krb5_context kcontext,char * conf_section,char ** db_args)924 krb5_ldap_delete_realm_1(krb5_context kcontext, char *conf_section,
925 char **db_args)
926 {
927 krb5_error_code status = KRB5_PLUGIN_OP_NOTSUPP;
928 k5_setmsg(kcontext, status, "LDAP %s", error_message(status));
929 return status;
930 }
931