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 buf.data;
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 unsigned int 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 unsigned int l=0, ntree=0;
213 int i=0, j=0, 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; ++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 && st != KRB5_KDB_NOENTRY)
279 goto cleanup;
280 }
281 krb5_free_principal(context, principal);
282 }
283 ldap_value_free(values);
284 }
285 }
286 }
287
288 /* Delete all password policies */
289 krb5_ldap_iterate_password_policy (context, "*", delete_password_policy, context);
290
291 /* Delete all ticket policies */
292 {
293 if ((st = krb5_ldap_list_policy (context, ldap_context->lrparams->realmdn, &policy)) != 0) {
294 k5_prependmsg(context, st, _("Error reading ticket policy"));
295 goto cleanup;
296 }
297
298 for (i = 0; policy [i] != NULL; i++)
299 krb5_ldap_delete_policy(context, policy[i]);
300 }
301
302 /* Delete the realm object */
303 if ((st=ldap_delete_ext_s(ld, ldap_context->lrparams->realmdn, NULL, NULL)) != LDAP_SUCCESS) {
304 int ost = st;
305 st = translate_ldap_error (st, OP_DEL);
306 k5_setmsg(context, st, _("Realm Delete FAILED: %s"),
307 ldap_err2string(ost));
308 }
309
310 cleanup:
311 if (subtrees) {
312 for (l=0; l < ntree; ++l) {
313 if (subtrees[l])
314 free (subtrees[l]);
315 }
316 free (subtrees);
317 }
318
319 if (result_arr != NULL) {
320 for (l = 0; l < ntree; l++)
321 ldap_msgfree(result_arr[l]);
322 free(result_arr);
323 }
324
325 if (policy != NULL) {
326 for (i = 0; policy[i] != NULL; i++)
327 free (policy[i]);
328 free (policy);
329 }
330
331 krb5_ldap_free_realm_params(rparam);
332 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
333 return st;
334 }
335
336
337 /*
338 * Modify the realm attributes in the Directory.
339 */
340
341 krb5_error_code
krb5_ldap_modify_realm(krb5_context context,krb5_ldap_realm_params * rparams,int mask)342 krb5_ldap_modify_realm(krb5_context context, krb5_ldap_realm_params *rparams,
343 int mask)
344 {
345 LDAP *ld=NULL;
346 krb5_error_code st=0;
347 char **strval=NULL, *strvalprc[5]={NULL};
348 LDAPMod **mods = NULL;
349 int objectmask=0,k=0;
350 kdb5_dal_handle *dal_handle=NULL;
351 krb5_ldap_context *ldap_context=NULL;
352 krb5_ldap_server_handle *ldap_server_handle=NULL;
353
354 if (mask == 0)
355 return 0;
356
357 if (rparams == NULL) {
358 st = EINVAL;
359 return st;
360 }
361
362 SETUP_CONTEXT ();
363
364 /* Check validity of arguments */
365 if (ldap_context->container_dn == NULL ||
366 rparams->tl_data == NULL ||
367 rparams->tl_data->tl_data_contents == NULL ||
368 ((mask & LDAP_REALM_SUBTREE) && rparams->subtree == NULL) ||
369 ((mask & LDAP_REALM_CONTREF) && rparams->containerref == NULL) ||
370 0) {
371 st = EINVAL;
372 goto cleanup;
373 }
374
375 /* get ldap handle */
376 GET_HANDLE ();
377
378 /* SUBTREE ATTRIBUTE */
379 if (mask & LDAP_REALM_SUBTREE) {
380 if ( rparams->subtree!=NULL) {
381 /*replace the subtrees with the present if the subtrees are present*/
382 for(k=0;k<rparams->subtreecount && rparams->subtree[k]!=NULL;k++) {
383 if (strlen(rparams->subtree[k]) != 0) {
384 st = checkattributevalue(ld, rparams->subtree[k], "Objectclass", subtreeclass,
385 &objectmask);
386 CHECK_CLASS_VALIDITY(st, objectmask, _("subtree value: "));
387 }
388 }
389 strval = rparams->subtree;
390 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbsubtrees", LDAP_MOD_REPLACE,
391 strval)) != 0) {
392 goto cleanup;
393 }
394 }
395 }
396
397 /* CONTAINERREF ATTRIBUTE */
398 if (mask & LDAP_REALM_CONTREF) {
399 if (strlen(rparams->containerref) != 0 ) {
400 st = checkattributevalue(ld, rparams->containerref, "Objectclass", subtreeclass,
401 &objectmask);
402 CHECK_CLASS_VALIDITY(st, objectmask,
403 _("container reference value: "));
404 strvalprc[0] = rparams->containerref;
405 strvalprc[1] = NULL;
406 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbPrincContainerRef", LDAP_MOD_REPLACE,
407 strvalprc)) != 0)
408 goto cleanup;
409 }
410 }
411
412 /* SEARCHSCOPE ATTRIBUTE */
413 if (mask & LDAP_REALM_SEARCHSCOPE) {
414 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbsearchscope", LDAP_MOD_REPLACE,
415 (rparams->search_scope == LDAP_SCOPE_ONELEVEL
416 || rparams->search_scope == LDAP_SCOPE_SUBTREE) ?
417 rparams->search_scope : LDAP_SCOPE_SUBTREE)) != 0)
418 goto cleanup;
419 }
420
421 if (mask & LDAP_REALM_MAXRENEWLIFE) {
422
423 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxRenewableAge", LDAP_MOD_REPLACE,
424 rparams->max_renewable_life)) != 0)
425 goto cleanup;
426 }
427
428 /* krbMaxTicketLife ATTRIBUTE */
429
430 if (mask & LDAP_REALM_MAXTICKETLIFE) {
431
432 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxTicketLife", LDAP_MOD_REPLACE,
433 rparams->max_life)) != 0)
434 goto cleanup;
435 }
436
437 /* krbTicketFlags ATTRIBUTE */
438
439 if (mask & LDAP_REALM_KRBTICKETFLAGS) {
440
441 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbTicketFlags", LDAP_MOD_REPLACE,
442 rparams->tktflags)) != 0)
443 goto cleanup;
444 }
445
446
447 /* Realm modify opearation */
448 if (mods != NULL) {
449 if ((st=ldap_modify_ext_s(ld, rparams->realmdn, mods, NULL, NULL)) != LDAP_SUCCESS) {
450 st = set_ldap_error (context, st, OP_MOD);
451 goto cleanup;
452 }
453 }
454
455 cleanup:
456
457 ldap_mods_free(mods, 1);
458 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
459 return st;
460 }
461
462
463
464 /*
465 * Create the Kerberos container in the Directory if it does not exist
466 */
467
468 krb5_error_code
krb5_ldap_create_krbcontainer(krb5_context context,const char * dn)469 krb5_ldap_create_krbcontainer(krb5_context context, const char *dn)
470 {
471 LDAP *ld=NULL;
472 char *strval[2]={NULL}, **rdns=NULL;
473 LDAPMod **mods = NULL;
474 krb5_error_code st=0;
475 kdb5_dal_handle *dal_handle=NULL;
476 krb5_ldap_context *ldap_context=NULL;
477 krb5_ldap_server_handle *ldap_server_handle=NULL;
478
479 SETUP_CONTEXT ();
480
481 /* get ldap handle */
482 GET_HANDLE ();
483
484 if (dn == NULL) {
485 st = EINVAL;
486 k5_setmsg(context, st, _("Kerberos Container information is missing"));
487 goto cleanup;
488 }
489
490 strval[0] = "krbContainer";
491 strval[1] = NULL;
492 if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
493 goto cleanup;
494
495 rdns = ldap_explode_dn(dn, 1);
496 if (rdns == NULL) {
497 st = EINVAL;
498 k5_setmsg(context, st, _("Invalid Kerberos container DN"));
499 goto cleanup;
500 }
501
502 strval[0] = rdns[0];
503 strval[1] = NULL;
504 if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0)
505 goto cleanup;
506
507 /* create the kerberos container */
508 st = ldap_add_ext_s(ld, dn, mods, NULL, NULL);
509 if (st == LDAP_ALREADY_EXISTS)
510 st = LDAP_SUCCESS;
511 if (st != LDAP_SUCCESS) {
512 int ost = st;
513 st = translate_ldap_error (st, OP_ADD);
514 k5_setmsg(context, st, _("Kerberos Container create FAILED: %s"),
515 ldap_err2string(ost));
516 goto cleanup;
517 }
518
519 cleanup:
520
521 if (rdns)
522 ldap_value_free (rdns);
523
524 ldap_mods_free(mods, 1);
525 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
526 return(st);
527 }
528
529 /*
530 * Delete the Kerberos container in the Directory
531 */
532
533 krb5_error_code
krb5_ldap_delete_krbcontainer(krb5_context context,const char * dn)534 krb5_ldap_delete_krbcontainer(krb5_context context, const char *dn)
535 {
536 LDAP *ld=NULL;
537 krb5_error_code st=0;
538 kdb5_dal_handle *dal_handle=NULL;
539 krb5_ldap_context *ldap_context=NULL;
540 krb5_ldap_server_handle *ldap_server_handle=NULL;
541
542 SETUP_CONTEXT ();
543
544 /* get ldap handle */
545 GET_HANDLE ();
546
547 if (dn == NULL) {
548 st = EINVAL;
549 k5_setmsg(context, st, _("Kerberos Container information is missing"));
550 goto cleanup;
551 }
552
553 /* delete the kerberos container */
554 if ((st = ldap_delete_ext_s(ld, dn, NULL, NULL)) != LDAP_SUCCESS) {
555 int ost = st;
556 st = translate_ldap_error (st, OP_ADD);
557 k5_setmsg(context, st, _("Kerberos Container delete FAILED: %s"),
558 ldap_err2string(ost));
559 goto cleanup;
560 }
561
562 cleanup:
563
564 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
565 return(st);
566 }
567
568
569 /*
570 * Create Realm in eDirectory. This is used by kdb5_util
571 */
572
573 krb5_error_code
krb5_ldap_create_realm(krb5_context context,krb5_ldap_realm_params * rparams,int mask)574 krb5_ldap_create_realm(krb5_context context, krb5_ldap_realm_params *rparams,
575 int mask)
576 {
577 LDAP *ld=NULL;
578 krb5_error_code st=0;
579 char *dn=NULL;
580 char *strval[4]={NULL};
581 char *contref[2]={NULL};
582 LDAPMod **mods = NULL;
583 int i=0, objectmask=0, subtreecount=0;
584 kdb5_dal_handle *dal_handle=NULL;
585 krb5_ldap_context *ldap_context=NULL;
586 krb5_ldap_server_handle *ldap_server_handle=NULL;
587 char *realm_name;
588
589 SETUP_CONTEXT ();
590
591 /* Check input validity ... */
592 if (ldap_context->container_dn == NULL ||
593 rparams == NULL ||
594 rparams->realm_name == NULL ||
595 ((mask & LDAP_REALM_SUBTREE) && rparams->subtree == NULL) ||
596 ((mask & LDAP_REALM_CONTREF) && rparams->containerref == NULL) ||
597 0) {
598 st = EINVAL;
599 return st;
600 }
601
602 /* get ldap handle */
603 GET_HANDLE ();
604
605 realm_name = rparams->realm_name;
606
607 if (asprintf(&dn, "cn=%s,%s", realm_name, ldap_context->container_dn) < 0)
608 dn = NULL;
609 CHECK_NULL(dn);
610
611 strval[0] = realm_name;
612 strval[1] = NULL;
613 if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0)
614 goto cleanup;
615
616 strval[0] = "top";
617 strval[1] = "krbrealmcontainer";
618 strval[2] = "krbticketpolicyaux";
619 strval[3] = NULL;
620
621 if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
622 goto cleanup;
623
624 /* SUBTREE ATTRIBUTE */
625 if (mask & LDAP_REALM_SUBTREE) {
626 if ( rparams->subtree!=NULL) {
627 subtreecount = rparams->subtreecount;
628 for (i=0; rparams->subtree[i]!=NULL && i<subtreecount; i++) {
629 if (strlen(rparams->subtree[i]) != 0) {
630 st = checkattributevalue(ld, rparams->subtree[i], "Objectclass", subtreeclass,
631 &objectmask);
632 CHECK_CLASS_VALIDITY(st, objectmask,
633 _("realm object value: "));
634 }
635 }
636 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbsubtrees", LDAP_MOD_ADD,
637 rparams->subtree)) != 0) {
638 goto cleanup;
639 }
640 }
641 }
642
643 /* CONTAINER REFERENCE ATTRIBUTE */
644 if (mask & LDAP_REALM_CONTREF) {
645 if (strlen(rparams->containerref) != 0 ) {
646 st = checkattributevalue(ld, rparams->containerref, "Objectclass", subtreeclass,
647 &objectmask);
648 CHECK_CLASS_VALIDITY(st, objectmask, "realm object value: ");
649 contref[0] = rparams->containerref;
650 contref[1] = NULL;
651 if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbPrincContainerRef", LDAP_MOD_ADD,
652 contref)) != 0)
653 goto cleanup;
654 }
655 }
656
657 /* SEARCHSCOPE ATTRIBUTE */
658 if (mask & LDAP_REALM_SEARCHSCOPE) {
659 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbsearchscope", LDAP_MOD_ADD,
660 (rparams->search_scope == LDAP_SCOPE_ONELEVEL
661 || rparams->search_scope == LDAP_SCOPE_SUBTREE) ?
662 rparams->search_scope : LDAP_SCOPE_SUBTREE)) != 0)
663 goto cleanup;
664 }
665 if (mask & LDAP_REALM_MAXRENEWLIFE) {
666
667 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxRenewableAge", LDAP_MOD_ADD,
668 rparams->max_renewable_life)) != 0)
669 goto cleanup;
670 }
671
672 /* krbMaxTicketLife ATTRIBUTE */
673
674 if (mask & LDAP_REALM_MAXTICKETLIFE) {
675
676 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxTicketLife", LDAP_MOD_ADD,
677 rparams->max_life)) != 0)
678 goto cleanup;
679 }
680
681 /* krbTicketFlags ATTRIBUTE */
682
683 if (mask & LDAP_REALM_KRBTICKETFLAGS) {
684
685 if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbTicketFlags", LDAP_MOD_ADD,
686 rparams->tktflags)) != 0)
687 goto cleanup;
688 }
689
690
691 /* realm creation operation */
692 if ((st=ldap_add_ext_s(ld, dn, mods, NULL, NULL)) != LDAP_SUCCESS) {
693 st = set_ldap_error (context, st, OP_ADD);
694 goto cleanup;
695 }
696
697 cleanup:
698
699 if (dn)
700 free(dn);
701
702 ldap_mods_free(mods, 1);
703 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
704 return st;
705 }
706
707 /*
708 * Read the realm container configuration from eDirectory for the specified realm.
709 */
710
711 krb5_error_code
krb5_ldap_read_realm_params(krb5_context context,char * lrealm,krb5_ldap_realm_params ** rlparamp,int * mask)712 krb5_ldap_read_realm_params(krb5_context context, char *lrealm,
713 krb5_ldap_realm_params **rlparamp, int *mask)
714 {
715 char **values=NULL;
716 krb5_error_code st=0, tempst=0;
717 LDAP *ld=NULL;
718 LDAPMessage *result=NULL,*ent=NULL;
719 krb5_ldap_realm_params *rlparams=NULL;
720 kdb5_dal_handle *dal_handle=NULL;
721 krb5_ldap_context *ldap_context=NULL;
722 krb5_ldap_server_handle *ldap_server_handle=NULL;
723 int x=0;
724
725 SETUP_CONTEXT ();
726
727 /* validate the input parameter */
728 if (lrealm == NULL || ldap_context->container_dn == NULL) {
729 st = EINVAL;
730 goto cleanup;
731 }
732
733 /* get ldap handle */
734 GET_HANDLE ();
735
736 /* Initialize realm container structure */
737 rlparams =(krb5_ldap_realm_params *) malloc(sizeof(krb5_ldap_realm_params));
738 CHECK_NULL(rlparams);
739 memset(rlparams, 0, sizeof(krb5_ldap_realm_params));
740
741 /* allocate tl_data structure to store MASK information */
742 rlparams->tl_data = malloc (sizeof(krb5_tl_data));
743 if (rlparams->tl_data == NULL) {
744 st = ENOMEM;
745 goto cleanup;
746 }
747 memset(rlparams->tl_data, 0, sizeof(krb5_tl_data));
748 rlparams->tl_data->tl_data_type = KDB_TL_USER_INFO;
749
750 /* set the mask parameter to 0 */
751 *mask = 0;
752
753 /* set default values */
754 rlparams->search_scope = LDAP_SCOPE_SUBTREE;
755
756 if (asprintf(&rlparams->realmdn, "cn=%s,%s", lrealm,
757 ldap_context->container_dn) < 0) {
758 rlparams->realmdn = NULL;
759 st = ENOMEM;
760 goto cleanup;
761 }
762
763 /* populate the realm name in the structure */
764 rlparams->realm_name = strdup(lrealm);
765 CHECK_NULL(rlparams->realm_name);
766
767 LDAP_SEARCH(rlparams->realmdn, LDAP_SCOPE_BASE, "(objectclass=krbRealmContainer)", realm_attributes);
768
769 if ((st = ldap_count_entries(ld, result)) <= 0) {
770 /* This could happen when the DN used to bind and read the realm object
771 * does not have sufficient rights to read its attributes
772 */
773 st = KRB5_KDB_ACCESS_ERROR; /* return some other error ? */
774 goto cleanup;
775 }
776
777 ent = ldap_first_entry (ld, result);
778 if (ent == NULL) {
779 ldap_get_option (ld, LDAP_OPT_ERROR_NUMBER, (void *) &st);
780 goto cleanup;
781 }
782
783 /* Read the attributes */
784 {
785 if ((values=ldap_get_values(ld, ent, "krbSubTrees")) != NULL) {
786 rlparams->subtreecount = ldap_count_values(values);
787 rlparams->subtree = (char **) malloc(sizeof(char *) * (rlparams->subtreecount + 1));
788 if (rlparams->subtree == NULL) {
789 st = ENOMEM;
790 goto cleanup;
791 }
792 for (x=0; x<rlparams->subtreecount; x++) {
793 rlparams->subtree[x] = strdup(values[x]);
794 if (rlparams->subtree[x] == NULL) {
795 st = ENOMEM;
796 goto cleanup;
797 }
798 }
799 rlparams->subtree[rlparams->subtreecount] = NULL;
800 *mask |= LDAP_REALM_SUBTREE;
801 ldap_value_free(values);
802 }
803
804 if((values=ldap_get_values(ld, ent, "krbPrincContainerRef")) != NULL) {
805 rlparams->containerref = strdup(values[0]);
806 if(rlparams->containerref == NULL) {
807 st = ENOMEM;
808 goto cleanup;
809 }
810 *mask |= LDAP_REALM_CONTREF;
811 ldap_value_free(values);
812 }
813
814 if ((values=ldap_get_values(ld, ent, "krbSearchScope")) != NULL) {
815 rlparams->search_scope=atoi(values[0]);
816 /* searchscope can be ONE-LEVEL or SUBTREE, else default to SUBTREE */
817 if (!(rlparams->search_scope==1 || rlparams->search_scope==2))
818 rlparams->search_scope = LDAP_SCOPE_SUBTREE;
819 *mask |= LDAP_REALM_SEARCHSCOPE;
820 ldap_value_free(values);
821 }
822
823 if ((values=ldap_get_values(ld, ent, "krbMaxTicketLife")) != NULL) {
824 rlparams->max_life = atoi(values[0]);
825 *mask |= LDAP_REALM_MAXTICKETLIFE;
826 ldap_value_free(values);
827 }
828
829 if ((values=ldap_get_values(ld, ent, "krbMaxRenewableAge")) != NULL) {
830 rlparams->max_renewable_life = atoi(values[0]);
831 *mask |= LDAP_REALM_MAXRENEWLIFE;
832 ldap_value_free(values);
833 }
834
835 if ((values=ldap_get_values(ld, ent, "krbTicketFlags")) != NULL) {
836 rlparams->tktflags = atoi(values[0]);
837 *mask |= LDAP_REALM_KRBTICKETFLAGS;
838 ldap_value_free(values);
839 }
840
841 }
842
843 rlparams->mask = *mask;
844 *rlparamp = rlparams;
845 st = store_tl_data(rlparams->tl_data, KDB_TL_MASK, mask);
846
847 cleanup:
848
849 /* if there is an error, free allocated structures */
850 if (st != 0) {
851 krb5_ldap_free_realm_params(rlparams);
852 *rlparamp=NULL;
853 }
854 ldap_msgfree(result);
855 krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
856 return st;
857 }
858
859
860 /*
861 Free the krb5_ldap_realm_params.
862 */
863 void
krb5_ldap_free_realm_params(krb5_ldap_realm_params * rparams)864 krb5_ldap_free_realm_params(krb5_ldap_realm_params *rparams)
865 {
866 int i=0;
867
868 if (rparams) {
869 if (rparams->realmdn)
870 free(rparams->realmdn);
871
872 if (rparams->realm_name)
873 free(rparams->realm_name);
874
875 if (rparams->subtree) {
876 for (i=0; i<rparams->subtreecount && rparams->subtree[i] ; i++)
877 free(rparams->subtree[i]);
878 free(rparams->subtree);
879 }
880
881 if (rparams->containerref)
882 free(rparams->containerref);
883
884 if (rparams->kdcservers) {
885 for (i=0; rparams->kdcservers[i]; ++i)
886 free(rparams->kdcservers[i]);
887 free(rparams->kdcservers);
888 }
889
890 if (rparams->adminservers) {
891 for (i=0; rparams->adminservers[i]; ++i)
892 free(rparams->adminservers[i]);
893 free(rparams->adminservers);
894 }
895
896 if (rparams->passwdservers) {
897 for (i=0; rparams->passwdservers[i]; ++i)
898 free(rparams->passwdservers[i]);
899 free(rparams->passwdservers);
900 }
901
902 if (rparams->tl_data) {
903 if (rparams->tl_data->tl_data_contents)
904 free(rparams->tl_data->tl_data_contents);
905 free(rparams->tl_data);
906 }
907
908 free(rparams);
909 }
910 return;
911 }
912
913 /*
914 * ******************************************************************************
915 * DAL functions
916 * ******************************************************************************
917 */
918
919 krb5_error_code
krb5_ldap_delete_realm_1(krb5_context kcontext,char * conf_section,char ** db_args)920 krb5_ldap_delete_realm_1(krb5_context kcontext, char *conf_section,
921 char **db_args)
922 {
923 krb5_error_code status = KRB5_PLUGIN_OP_NOTSUPP;
924 k5_setmsg(kcontext, status, "LDAP %s", error_message(status));
925 return status;
926 }
927