/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
* lib/kdb/kdb_ldap/ldap_realm.c
*
* Copyright (c) 2004-2005, Novell, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * The copyright holder's name is not used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
*/
#include "ldap_main.h"
#include "ldap_realm.h"
#include "ldap_principal.h"
#include "ldap_pwd_policy.h"
#include "ldap_err.h"
#include <libintl.h> /* Solaris Kerberos */
#define END_OF_LIST -1
char *realm_attributes[] = {"krbSearchScope","krbSubTrees", "krbPrincContainerRef",
"krbMaxTicketLife", "krbMaxRenewableAge",
"krbTicketFlags", "krbUpEnabled",
"krbTicketPolicyReference",
"krbLdapServers",
"krbKdcServers", "krbAdmServers",
"krbPwdServers", NULL};
char *policy_attributes[] = { "krbMaxTicketLife",
"krbMaxRenewableAge",
"krbTicketFlags",
NULL };
char *policyclass[] = { "krbTicketPolicy", NULL };
char *kdcclass[] = { "krbKdcService", NULL };
char *adminclass[] = { "krbAdmService", NULL };
char *pwdclass[] = { "krbPwdService", NULL };
char *subtreeclass[] = { "Organization", "OrganizationalUnit", "Domain", "krbContainer",
"krbRealmContainer", "Country", "Locality", NULL };
char *krbContainerRefclass[] = { "krbContainerRefAux", NULL};
/*
* list realms from eDirectory
*/
/*
* Function to remove all special characters from a string (rfc2254).
* Use whenever exact matching is to be done ...
*/
char *
ldap_filter_correct (char *in)
{
size_t i, count;
char *out, *ptr;
size_t len = strlen(in);
for (i = 0, count = 0; i < len; i++)
switch (in[i]) {
case '*':
case '(':
case ')':
case '\\':
case '\0':
count ++;
}
out = (char *)malloc((len + (count * 2) + 1) * sizeof (char));
assert (out != NULL);
memset(out, 0, len + (count * 2) + 1);
for (i = 0, ptr = out; i < len; i++)
switch (in[i]) {
case '*':
ptr[0] = '\\';
ptr[1] = '2';
ptr[2] = 'a';
ptr += 3;
break;
case '(':
ptr[0] = '\\';
ptr[1] = '2';
ptr[2] = '8';
ptr += 3;
break;
case ')':
ptr[0] = '\\';
ptr[1] = '2';
ptr[2] = '9';
ptr += 3;
break;
case '\\':
ptr[0] = '\\';
ptr[1] = '5';
ptr[2] = 'c';
ptr += 3;
break;
case '\0':
ptr[0] = '\\';
ptr[1] = '0';
ptr[2] = '0';
ptr += 3;
break;
default:
ptr[0] = in[i];
ptr += 1;
break;
}
/* ptr[count - 1] = '\0'; */
return out;
}
static int
principal_in_realm_2(krb5_principal principal, char *realm) {
/* Cross realm trust ... */
if (principal->length == 2 &&
principal->data[0].length == sizeof ("krbtgt") &&
strncasecmp (principal->data[0].data, "krbtgt", sizeof ("krbtgt")) &&
principal->data[1].length == strlen (realm) &&
strncasecmp (principal->data[1].data, realm, strlen (realm)))
return 0;
if (strlen(realm) != principal->realm.length)
return 1;
if (strncasecmp(realm, principal->realm.data, principal->realm.length) != 0)
return 1;
return 0;
}
/*
* Lists the realms in the Directory.
*/
krb5_error_code
krb5_ldap_list_realm(krb5_context context, char ***realms)
{
char **values = NULL;
unsigned int i = 0;
int count = 0;
krb5_error_code st = 0, tempst = 0;
LDAP *ld = NULL;
LDAPMessage *result = NULL, *ent = NULL;
kdb5_dal_handle *dal_handle = NULL;
krb5_ldap_context *ldap_context = NULL;
krb5_ldap_server_handle *ldap_server_handle = NULL;
SETUP_CONTEXT ();
/* get the kerberos container DN information */
if (ldap_context->krbcontainer == NULL) {
if ((st = krb5_ldap_read_krbcontainer_params(context,
&(ldap_context->krbcontainer))) != 0)
goto cleanup;
}
/* get ldap handle */
GET_HANDLE ();
{
char *cn[] = {"cn", NULL};
LDAP_SEARCH(ldap_context->krbcontainer->DN,
LDAP_SCOPE_ONELEVEL,
"(objectclass=krbRealmContainer)",
cn);
}
*realms = NULL;
count = ldap_count_entries (ld, result);
if (count == -1) {
ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &st);
st = set_ldap_error (context, st, OP_SEARCH);
goto cleanup;
}
*realms = calloc((unsigned int) count+1, sizeof (char *));
CHECK_NULL(*realms);
for (ent = ldap_first_entry(ld, result), count = 0; ent != NULL;
ent = ldap_next_entry(ld, ent)) {
if ((values = ldap_get_values (ld, ent, "cn")) != NULL) {
(*realms)[count] = strdup(values[0]);
CHECK_NULL((*realms)[count]);
count += 1;
ldap_value_free(values);
}
} /* for (ent= ... */
ldap_msgfree(result);
cleanup:
/* some error, free up all the memory */
if (st != 0) {
if (*realms) {
for (i=0; (*realms)[i] != NULL; ++i) {
free ((*realms)[i]);
}
free (*realms);
*realms = NULL;
}
}
/* If there are no elements, still return a NULL terminated array */
krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
return st;
}
/*
* Delete the realm along with the principals belonging to the realm in the Directory.
*/
static void
delete_password_policy (krb5_pointer ptr, osa_policy_ent_t pol)
{
krb5_ldap_delete_password_policy ((krb5_context)ptr, pol->name);
}
krb5_error_code
krb5_ldap_delete_realm (krb5_context context, char *lrealm)
{
LDAP *ld = NULL;
krb5_error_code st = 0, tempst=0;
char **values=NULL, **subtrees=NULL, **policy=NULL;
LDAPMessage **result_arr=NULL, *result = NULL, *ent = NULL;
krb5_principal principal;
int l=0, ntree=0, i=0, j=0, mask=0;
kdb5_dal_handle *dal_handle = NULL;
krb5_ldap_context *ldap_context = NULL;
krb5_ldap_server_handle *ldap_server_handle = NULL;
krb5_ldap_realm_params *rparam=NULL;
SETUP_CONTEXT ();
if (lrealm == NULL) {
st = EINVAL;
krb5_set_error_message (context, st, gettext("Realm information not available"));
goto cleanup;
}
if ((st=krb5_ldap_read_realm_params(context, lrealm, &rparam, &mask)) != 0)
goto cleanup;
/* get ldap handle */
GET_HANDLE ();
/* delete all the principals belonging to the realm in the tree */
{
char *attr[] = {"krbprincipalname", NULL}, *realm=NULL, filter[256];
krb5_ldap_context lcontext;
realm = ldap_filter_correct (lrealm);
assert (sizeof (filter) >= sizeof ("(krbprincipalname=)") +
strlen (realm) + 2 /* "*@" */ + 1);
snprintf (filter, sizeof(filter), "(krbprincipalname=*@%s)", realm);
free (realm);
/* LDAP_SEARCH(NULL, LDAP_SCOPE_SUBTREE, filter, attr); */
memset(&lcontext, 0, sizeof(krb5_ldap_context));
lcontext.lrparams = rparam;
if ((st=krb5_get_subtree_info(&lcontext, &subtrees, (unsigned int *)&ntree)) != 0)
goto cleanup;
result_arr = (LDAPMessage **) calloc((unsigned int)ntree+1,
sizeof(LDAPMessage *));
if (result_arr == NULL) {
st = ENOMEM;
goto cleanup;
}
for (l=0; l < ntree; ++l) {
LDAP_SEARCH(subtrees[l], rparam->search_scope, filter, attr);
result_arr[l] = result;
}
}
/* NOTE: Here all the principals should be cached and the ldap handle should be freed,
* as a DAL-LDAP interface is called right down here. Caching might be constrained by
* availability of the memory. The caching is not done, however there would be limit
* on the minimum number of handles for a server and it is 2. As the DAL-LDAP is not
* thread-safe this should suffice.
*/
for (j=0; (result=result_arr[j]) != NULL; ++j) {
for (ent = ldap_first_entry (ld, result); ent != NULL;
ent = ldap_next_entry (ld, ent)) {
if ((values = ldap_get_values(ld, ent, "krbPrincipalName")) != NULL) {
for (i = 0; values[i] != NULL; ++i) {
krb5_parse_name(context, values[i], &principal);
if (principal_in_realm_2(principal, lrealm) == 0) {
int nent = 0;
if ((st=krb5_ldap_delete_principal(context, principal,
&nent)) != LDAP_SUCCESS)
goto cleanup;
}
krb5_free_principal(context, principal);
}
ldap_value_free(values);
}
}
ldap_msgfree(result);
}
/* Delete all password policies */
krb5_ldap_iterate_password_policy (context, "*", delete_password_policy, context);
/* Delete all ticket policies */
{
if ((st = krb5_ldap_list_policy (context, ldap_context->lrparams->realmdn, &policy)) != 0) {
prepend_err_str (context, "Error reading ticket policy: ", st, st);
goto cleanup;
}
for (i = 0; policy [i] != NULL; i++)
krb5_ldap_delete_policy(context, policy[i]);
}
/* Delete the realm object */
if ((st=ldap_delete_ext_s(ld, ldap_context->lrparams->realmdn, NULL, NULL)) != LDAP_SUCCESS) {
int ost = st;
st = translate_ldap_error (st, OP_DEL);
krb5_set_error_message (context, st, gettext("Realm Delete FAILED: %s"),
ldap_err2string(ost));
}
cleanup:
/* Solaris Kerberos */
if (result_arr)
free(result_arr);
if (subtrees) {
for (l=0; l < ntree; ++l) {
if (subtrees[l])
free (subtrees[l]);
}
free (subtrees);
}
if (policy != NULL) {
for (i = 0; policy[i] != NULL; i++)
free (policy[i]);
free (policy);
}
krb5_ldap_free_realm_params(rparam);
krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
return st;
}
/*
* Modify the realm attributes in the Directory.
*/
krb5_error_code
krb5_ldap_modify_realm(krb5_context context, krb5_ldap_realm_params *rparams,
int mask)
{
LDAP *ld=NULL;
krb5_error_code st=0;
char **strval=NULL, *strvalprc[5]={NULL};
#ifdef HAVE_EDIRECTORY
char **values=NULL;
char **oldkdcservers=NULL, **oldadminservers=NULL, **oldpasswdservers=NULL;
LDAPMessage *result=NULL, *ent=NULL;
int count=0;
char errbuf[1024];
#endif
LDAPMod **mods = NULL;
#ifdef HAVE_EDIRECTORY
int i=0;
#endif
/* Solaris kerberos: oldmask isn't used */
/* int oldmask=0, objectmask=0,k=0; */
int objectmask=0,k=0;
kdb5_dal_handle *dal_handle=NULL;
krb5_ldap_context *ldap_context=NULL;
krb5_ldap_server_handle *ldap_server_handle=NULL;
if (mask == 0)
return 0;
if (rparams == NULL) {
st = EINVAL;
return st;
}
SETUP_CONTEXT ();
/* Check validity of arguments */
if (ldap_context->krbcontainer == NULL ||
rparams->tl_data == NULL ||
rparams->tl_data->tl_data_contents == NULL ||
((mask & LDAP_REALM_SUBTREE) && rparams->subtree == NULL) ||
((mask & LDAP_REALM_CONTREF) && rparams->containerref == NULL) ||
#ifdef HAVE_EDIRECTORY
((mask & LDAP_REALM_KDCSERVERS) && rparams->kdcservers == NULL) ||
((mask & LDAP_REALM_ADMINSERVERS) && rparams->adminservers == NULL) ||
((mask & LDAP_REALM_PASSWDSERVERS) && rparams->passwdservers == NULL) ||
#endif
0) {
st = EINVAL;
goto cleanup;
}
/* get ldap handle */
GET_HANDLE ();
/* Solaris kerberos: oldmask isn't used */
#if 0 /************** Begin IFDEF'ed OUT *******************************/
/* get the oldmask obtained from the krb5_ldap_read_realm_params */
{
void *voidptr=NULL;
if ((st=decode_tl_data(rparams->tl_data, KDB_TL_MASK, &voidptr)) == 0) {
oldmask = *((int *) voidptr);
free (voidptr);
} else {
st = EINVAL;
krb5_set_error_message (context, st, gettext("tl_data not available"));
return st;
}
}
#endif /**************** END IFDEF'ed OUT *******************************/
/* SUBTREE ATTRIBUTE */
if (mask & LDAP_REALM_SUBTREE) {
if ( rparams->subtree!=NULL) {
/*replace the subtrees with the present if the subtrees are present*/
for(k=0;k<rparams->subtreecount && rparams->subtree[k]!=NULL;k++) {
if (strlen(rparams->subtree[k]) != 0) {
st = checkattributevalue(ld, rparams->subtree[k], "Objectclass", subtreeclass,
&objectmask);
CHECK_CLASS_VALIDITY(st, objectmask, "subtree value: ");
}
}
strval = rparams->subtree;
if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbsubtrees", LDAP_MOD_REPLACE,
strval)) != 0) {
goto cleanup;
}
}
}
/* CONTAINERREF ATTRIBUTE */
if (mask & LDAP_REALM_CONTREF) {
if (strlen(rparams->containerref) != 0 ) {
st = checkattributevalue(ld, rparams->containerref, "Objectclass", subtreeclass,
&objectmask);
CHECK_CLASS_VALIDITY(st, objectmask, "container reference value: ");
strvalprc[0] = rparams->containerref;
strvalprc[1] = NULL;
if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbPrincContainerRef", LDAP_MOD_REPLACE,
strvalprc)) != 0)
goto cleanup;
}
}
/* SEARCHSCOPE ATTRIBUTE */
if (mask & LDAP_REALM_SEARCHSCOPE) {
if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbsearchscope", LDAP_MOD_REPLACE,
(rparams->search_scope == LDAP_SCOPE_ONELEVEL
|| rparams->search_scope == LDAP_SCOPE_SUBTREE) ?
rparams->search_scope : LDAP_SCOPE_SUBTREE)) != 0)
goto cleanup;
}
if (mask & LDAP_REALM_MAXRENEWLIFE) {
if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxRenewableAge", LDAP_MOD_REPLACE,
rparams->max_renewable_life)) != 0)
goto cleanup;
}
/* krbMaxTicketLife ATTRIBUTE */
if (mask & LDAP_REALM_MAXTICKETLIFE) {
if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxTicketLife", LDAP_MOD_REPLACE,
rparams->max_life)) != 0)
goto cleanup;
}
/* krbTicketFlags ATTRIBUTE */
if (mask & LDAP_REALM_KRBTICKETFLAGS) {
if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbTicketFlags", LDAP_MOD_REPLACE,
rparams->tktflags)) != 0)
goto cleanup;
}
#ifdef HAVE_EDIRECTORY
/* KDCSERVERS ATTRIBUTE */
if (mask & LDAP_REALM_KDCSERVERS) {
/* validate the server list */
for (i=0; rparams->kdcservers[i] != NULL; ++i) {
st = checkattributevalue(ld, rparams->kdcservers[i], "objectClass", kdcclass,
&objectmask);
CHECK_CLASS_VALIDITY(st, objectmask, "kdc service object value: ");
}
if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbkdcservers", LDAP_MOD_REPLACE,
rparams->kdcservers)) != 0)
goto cleanup;
}
/* ADMINSERVERS ATTRIBUTE */
if (mask & LDAP_REALM_ADMINSERVERS) {
/* validate the server list */
for (i=0; rparams->adminservers[i] != NULL; ++i) {
st = checkattributevalue(ld, rparams->adminservers[i], "objectClass", adminclass,
&objectmask);
CHECK_CLASS_VALIDITY(st, objectmask, "admin service object value: ");
}
if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbadmservers", LDAP_MOD_REPLACE,
rparams->adminservers)) != 0)
goto cleanup;
}
/* PASSWDSERVERS ATTRIBUTE */
if (mask & LDAP_REALM_PASSWDSERVERS) {
/* validate the server list */
for (i=0; rparams->passwdservers[i] != NULL; ++i) {
st = checkattributevalue(ld, rparams->passwdservers[i], "objectClass", pwdclass,
&objectmask);
CHECK_CLASS_VALIDITY(st, objectmask, "password service object value: ");
}
if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdservers", LDAP_MOD_REPLACE,
rparams->passwdservers)) != 0)
goto cleanup;
}
/*
* Read the old values of the krbkdcservers, krbadmservers and
* krbpwdservers. This information is later used to decided the
* deletions/additions to the list.
*/
if (mask & LDAP_REALM_KDCSERVERS || mask & LDAP_REALM_ADMINSERVERS ||
mask & LDAP_REALM_PASSWDSERVERS) {
char *servers[] = {"krbKdcServers", "krbAdmServers", "krbPwdServers", NULL};
if ((st= ldap_search_ext_s(ld,
rparams->realmdn,
LDAP_SCOPE_BASE,
0,
servers,
0,
NULL,
NULL,
NULL,
0,
&result)) != LDAP_SUCCESS) {
st = set_ldap_error (context, st, OP_SEARCH);
goto cleanup;
}
ent = ldap_first_entry(ld, result);
if (ent) {
if ((values=ldap_get_values(ld, ent, "krbKdcServers")) != NULL) {
count = ldap_count_values(values);
if ((st=copy_arrays(values, &oldkdcservers, count)) != 0)
goto cleanup;
ldap_value_free(values);
}
if ((values=ldap_get_values(ld, ent, "krbAdmServers")) != NULL) {
count = ldap_count_values(values);
if ((st=copy_arrays(values, &oldadminservers, count)) != 0)
goto cleanup;
ldap_value_free(values);
}
if ((values=ldap_get_values(ld, ent, "krbPwdServers")) != NULL) {
count = ldap_count_values(values);
if ((st=copy_arrays(values, &oldpasswdservers, count)) != 0)
goto cleanup;
ldap_value_free(values);
}
}
ldap_msgfree(result);
}
#endif
/* Realm modify opearation */
if (mods != NULL) {
if ((st=ldap_modify_ext_s(ld, rparams->realmdn, mods, NULL, NULL)) != LDAP_SUCCESS) {
st = set_ldap_error (context, st, OP_MOD);
goto cleanup;
}
}
#ifdef HAVE_EDIRECTORY
/* krbRealmReferences attribute is updated here, depending on the additions/deletions
* to the 4 servers' list.
*/
if (mask & LDAP_REALM_KDCSERVERS) {
char **newkdcservers=NULL;
count = ldap_count_values(rparams->kdcservers);
if ((st=copy_arrays(rparams->kdcservers, &newkdcservers, count)) != 0)
goto cleanup;
/* find the deletions and additions to the server list */
if (oldkdcservers && newkdcservers)
disjoint_members(oldkdcservers, newkdcservers);
/* delete the krbRealmReferences attribute from the servers that are dis-associated. */
if (oldkdcservers)
for (i=0; oldkdcservers[i]; ++i)
if ((st=deleteAttribute(ld, oldkdcservers[i], "krbRealmReferences",
rparams->realmdn)) != 0) {
snprintf (errbuf, sizeof(errbuf), "Error removing 'krbRealmReferences' from %s: ",
oldkdcservers[i]);
prepend_err_str (context, errbuf, st, st);
goto cleanup;
}
/* add the krbRealmReferences attribute from the servers that are associated. */
if (newkdcservers)
for (i=0; newkdcservers[i]; ++i)
if ((st=updateAttribute(ld, newkdcservers[i], "krbRealmReferences",
rparams->realmdn)) != 0) {
snprintf (errbuf, sizeof(errbuf), "Error adding 'krbRealmReferences' to %s: ",
newkdcservers[i]);
prepend_err_str (context, errbuf, st, st);
goto cleanup;
}
if (newkdcservers)
ldap_value_free(newkdcservers);
}
if (mask & LDAP_REALM_ADMINSERVERS) {
char **newadminservers=NULL;
count = ldap_count_values(rparams->adminservers);
if ((st=copy_arrays(rparams->adminservers, &newadminservers, count)) != 0)
goto cleanup;
/* find the deletions and additions to the server list */
if (oldadminservers && newadminservers)
disjoint_members(oldadminservers, newadminservers);
/* delete the krbRealmReferences attribute from the servers that are dis-associated. */
if (oldadminservers)
for (i=0; oldadminservers[i]; ++i)
if ((st=deleteAttribute(ld, oldadminservers[i], "krbRealmReferences",
rparams->realmdn)) != 0) {
snprintf(errbuf, sizeof(errbuf), "Error removing 'krbRealmReferences' from "
"%s: ", oldadminservers[i]);
prepend_err_str (context, errbuf, st, st);
goto cleanup;
}
/* add the krbRealmReferences attribute from the servers that are associated. */
if (newadminservers)
for (i=0; newadminservers[i]; ++i)
if ((st=updateAttribute(ld, newadminservers[i], "krbRealmReferences",
rparams->realmdn)) != 0) {
snprintf(errbuf, sizeof(errbuf), "Error adding 'krbRealmReferences' to %s: ",
newadminservers[i]);
prepend_err_str (context, errbuf, st, st);
goto cleanup;
}
if (newadminservers)
ldap_value_free(newadminservers);
}
if (mask & LDAP_REALM_PASSWDSERVERS) {
char **newpasswdservers=NULL;
count = ldap_count_values(rparams->passwdservers);
if ((st=copy_arrays(rparams->passwdservers, &newpasswdservers, count)) != 0)
goto cleanup;
/* find the deletions and additions to the server list */
if (oldpasswdservers && newpasswdservers)
disjoint_members(oldpasswdservers, newpasswdservers);
/* delete the krbRealmReferences attribute from the servers that are dis-associated. */
if (oldpasswdservers)
for (i=0; oldpasswdservers[i]; ++i)
if ((st=deleteAttribute(ld, oldpasswdservers[i], "krbRealmReferences",
rparams->realmdn)) != 0) {
snprintf(errbuf, sizeof(errbuf), "Error removing 'krbRealmReferences' from "
"%s: ", oldpasswdservers[i]);
prepend_err_str (context, errbuf, st, st);
goto cleanup;
}
/* add the krbRealmReferences attribute from the servers that are associated. */
if (newpasswdservers)
for (i=0; newpasswdservers[i]; ++i)
if ((st=updateAttribute(ld, newpasswdservers[i], "krbRealmReferences",
rparams->realmdn)) != 0) {
snprintf(errbuf, sizeof(errbuf), "Error adding 'krbRealmReferences' to %s: ",
newpasswdservers[i]);
prepend_err_str (context, errbuf, st, st);
goto cleanup;
}
if (newpasswdservers)
ldap_value_free(newpasswdservers);
}
#endif
cleanup:
#ifdef HAVE_EDIRECTORY
if (oldkdcservers) {
for (i=0; oldkdcservers[i]; ++i)
free(oldkdcservers[i]);
free(oldkdcservers);
}
if (oldadminservers) {
for (i=0; oldadminservers[i]; ++i)
free(oldadminservers[i]);
free(oldadminservers);
}
if (oldpasswdservers) {
for (i=0; oldpasswdservers[i]; ++i)
free(oldpasswdservers[i]);
free(oldpasswdservers);
}
#endif
ldap_mods_free(mods, 1);
krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
return st;
}
/*
* Create the Kerberos container in the Directory
*/
krb5_error_code
krb5_ldap_create_krbcontainer(krb5_context context,
const
krb5_ldap_krbcontainer_params *krbcontparams)
{
LDAP *ld=NULL;
char *strval[2]={NULL}, *kerberoscontdn=NULL, **rdns=NULL;
int pmask=0;
LDAPMod **mods = NULL;
krb5_error_code st=0;
kdb5_dal_handle *dal_handle=NULL;
krb5_ldap_context *ldap_context=NULL;
krb5_ldap_server_handle *ldap_server_handle=NULL;
#ifdef HAVE_EDIRECTORY
int crmask=0;
#endif
SETUP_CONTEXT ();
/* get ldap handle */
GET_HANDLE ();
if (krbcontparams != NULL && krbcontparams->DN != NULL) {
kerberoscontdn = krbcontparams->DN;
} else {
/* If the user has not given, use the default cn=Kerberos,cn=Security */
#ifdef HAVE_EDIRECTORY
kerberoscontdn = KERBEROS_CONTAINER;
#else
st = EINVAL;
krb5_set_error_message (context, st, gettext("Kerberos Container information is missing"));
goto cleanup;
#endif
}
strval[0] = "krbContainer";
strval[1] = NULL;
if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
goto cleanup;
rdns = ldap_explode_dn(kerberoscontdn, 1);
if (rdns == NULL) {
st = EINVAL;
krb5_set_error_message(context, st, gettext("Invalid Kerberos container DN"));
goto cleanup;
}
strval[0] = rdns[0];
strval[1] = NULL;
if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0)
goto cleanup;
/* check if the policy reference value exists and is of krbticketpolicyreference object class */
if (krbcontparams && krbcontparams->policyreference) {
st = checkattributevalue(ld, krbcontparams->policyreference, "objectclass", policyclass,
&pmask);
CHECK_CLASS_VALIDITY(st, pmask, "ticket policy object value: ");
strval[0] = krbcontparams->policyreference;
strval[1] = NULL;
if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbticketpolicyreference", LDAP_MOD_ADD,
strval)) != 0)
goto cleanup;
}
/* create the kerberos container */
if ((st = ldap_add_ext_s(ld, kerberoscontdn, mods, NULL, NULL)) != LDAP_SUCCESS) {
int ost = st;
st = translate_ldap_error (st, OP_ADD);
krb5_set_error_message (context, st, gettext("Kerberos Container create FAILED: %s"), ldap_err2string(ost));
goto cleanup;
}
#ifdef HAVE_EDIRECTORY
/* free the mods array */
ldap_mods_free(mods, 1);
mods=NULL;
/* check whether the security container is bound to krbcontainerrefaux object class */
if ((st=checkattributevalue(ld, SECURITY_CONTAINER, "objectClass",
krbContainerRefclass, &crmask)) != 0) {
prepend_err_str (context, "Security Container read FAILED: ", st, st);
/* delete Kerberos Container, status ignored intentionally */
ldap_delete_ext_s(ld, kerberoscontdn, NULL, NULL);
goto cleanup;
}
if (crmask == 0) {
/* Security Container is extended with krbcontainerrefaux object class */
strval[0] = "krbContainerRefAux";
if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
goto cleanup;
}
strval[0] = kerberoscontdn;
strval[1] = NULL;
if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbcontainerreference", LDAP_MOD_ADD, strval)) != 0)
goto cleanup;
/* update the security container with krbContainerReference attribute */
if ((st=ldap_modify_ext_s(ld, SECURITY_CONTAINER, mods, NULL, NULL)) != LDAP_SUCCESS) {
int ost = st;
st = translate_ldap_error (st, OP_MOD);
krb5_set_error_message (context, st, gettext("Security Container update FAILED: %s"), ldap_err2string(ost));
/* delete Kerberos Container, status ignored intentionally */
ldap_delete_ext_s(ld, kerberoscontdn, NULL, NULL);
goto cleanup;
}
#endif
cleanup:
if (rdns)
ldap_value_free (rdns);
ldap_mods_free(mods, 1);
krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
return(st);
}
/*
* Delete the Kerberos container in the Directory
*/
krb5_error_code
krb5_ldap_delete_krbcontainer(krb5_context context,
const
krb5_ldap_krbcontainer_params *krbcontparams)
{
LDAP *ld=NULL;
char *kerberoscontdn=NULL;
krb5_error_code st=0;
kdb5_dal_handle *dal_handle=NULL;
krb5_ldap_context *ldap_context=NULL;
krb5_ldap_server_handle *ldap_server_handle=NULL;
SETUP_CONTEXT ();
/* get ldap handle */
GET_HANDLE ();
if (krbcontparams != NULL && krbcontparams->DN != NULL) {
kerberoscontdn = krbcontparams->DN;
} else {
/* If the user has not given, use the default cn=Kerberos,cn=Security */
#ifdef HAVE_EDIRECTORY
kerberoscontdn = KERBEROS_CONTAINER;
#else
st = EINVAL;
krb5_set_error_message (context, st, gettext("Kerberos Container information is missing"));
goto cleanup;
#endif
}
/* delete the kerberos container */
if ((st = ldap_delete_ext_s(ld, kerberoscontdn, NULL, NULL)) != LDAP_SUCCESS) {
int ost = st;
st = translate_ldap_error (st, OP_ADD);
krb5_set_error_message (context, st, gettext("Kerberos Container delete FAILED: %s"), ldap_err2string(ost));
goto cleanup;
}
cleanup:
krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
return(st);
}
/*
* Create Realm in eDirectory. This is used by kdb5_util
*/
krb5_error_code
krb5_ldap_create_realm(krb5_context context, krb5_ldap_realm_params *rparams,
int mask)
{
LDAP *ld=NULL;
krb5_error_code st=0;
char *dn=NULL;
char *strval[4]={NULL};
char *contref[2]={NULL};
LDAPMod **mods = NULL;
int i=0, objectmask=0, subtreecount=0;
kdb5_dal_handle *dal_handle=NULL;
krb5_ldap_context *ldap_context=NULL;
krb5_ldap_server_handle *ldap_server_handle=NULL;
#ifdef HAVE_EDIRECTORY
char errbuf[1024];
#endif
char *realm_name;
SETUP_CONTEXT ();
/* Check input validity ... */
if (ldap_context->krbcontainer == NULL ||
ldap_context->krbcontainer->DN == NULL ||
rparams == NULL ||
rparams->realm_name == NULL ||
((mask & LDAP_REALM_SUBTREE) && rparams->subtree == NULL) ||
((mask & LDAP_REALM_CONTREF) && rparams->containerref == NULL) ||
((mask & LDAP_REALM_POLICYREFERENCE) && rparams->policyreference == NULL) ||
#ifdef HAVE_EDIRECTORY
((mask & LDAP_REALM_KDCSERVERS) && rparams->kdcservers == NULL) ||
((mask & LDAP_REALM_ADMINSERVERS) && rparams->adminservers == NULL) ||
((mask & LDAP_REALM_PASSWDSERVERS) && rparams->passwdservers == NULL) ||
#endif
0) {
st = EINVAL;
return st;
}
if (ldap_context->krbcontainer == NULL) {
if ((st = krb5_ldap_read_krbcontainer_params(context,
&(ldap_context->krbcontainer))) != 0)
goto cleanup;
}
/* get ldap handle */
GET_HANDLE ();
realm_name = rparams->realm_name;
if (asprintf(&dn, "cn=%s,%s", realm_name,
ldap_context->krbcontainer->DN) < 0)
dn = NULL;
CHECK_NULL(dn);
strval[0] = realm_name;
strval[1] = NULL;
if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0)
goto cleanup;
strval[0] = "top";
strval[1] = "krbrealmcontainer";
strval[2] = "krbticketpolicyaux";
strval[3] = NULL;
if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
goto cleanup;
/* SUBTREE ATTRIBUTE */
if (mask & LDAP_REALM_SUBTREE) {
if ( rparams->subtree!=NULL) {
subtreecount = rparams->subtreecount;
for (i=0; rparams->subtree[i]!=NULL && i<subtreecount; i++) {
if (strlen(rparams->subtree[i]) != 0) {
st = checkattributevalue(ld, rparams->subtree[i], "Objectclass", subtreeclass,
&objectmask);
CHECK_CLASS_VALIDITY(st, objectmask, "realm object value: ");
}
}
if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbsubtrees", LDAP_MOD_ADD,
rparams->subtree)) != 0) {
goto cleanup;
}
}
}
/* CONTAINER REFERENCE ATTRIBUTE */
if (mask & LDAP_REALM_CONTREF) {
if (strlen(rparams->containerref) != 0 ) {
st = checkattributevalue(ld, rparams->containerref, "Objectclass", subtreeclass,
&objectmask);
CHECK_CLASS_VALIDITY(st, objectmask, "realm object value: ");
contref[0] = rparams->containerref;
contref[1] = NULL;
if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbPrincContainerRef", LDAP_MOD_ADD,
contref)) != 0)
goto cleanup;
}
}
/* SEARCHSCOPE ATTRIBUTE */
if (mask & LDAP_REALM_SEARCHSCOPE) {
if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbsearchscope", LDAP_MOD_ADD,
(rparams->search_scope == LDAP_SCOPE_ONELEVEL
|| rparams->search_scope == LDAP_SCOPE_SUBTREE) ?
rparams->search_scope : LDAP_SCOPE_SUBTREE)) != 0)
goto cleanup;
}
if (mask & LDAP_REALM_MAXRENEWLIFE) {
if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxRenewableAge", LDAP_MOD_ADD,
rparams->max_renewable_life)) != 0)
goto cleanup;
}
/* krbMaxTicketLife ATTRIBUTE */
if (mask & LDAP_REALM_MAXTICKETLIFE) {
if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxTicketLife", LDAP_MOD_ADD,
rparams->max_life)) != 0)
goto cleanup;
}
/* krbTicketFlags ATTRIBUTE */
if (mask & LDAP_REALM_KRBTICKETFLAGS) {
if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbTicketFlags", LDAP_MOD_ADD,
rparams->tktflags)) != 0)
goto cleanup;
}
#ifdef HAVE_EDIRECTORY
/* KDCSERVERS ATTRIBUTE */
if (mask & LDAP_REALM_KDCSERVERS) {
/* validate the server list */
for (i=0; rparams->kdcservers[i] != NULL; ++i) {
st = checkattributevalue(ld, rparams->kdcservers[i], "objectClass", kdcclass,
&objectmask);
CHECK_CLASS_VALIDITY(st, objectmask, "kdc service object value: ");
}
if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbkdcservers", LDAP_MOD_ADD,
rparams->kdcservers)) != 0)
goto cleanup;
}
/* ADMINSERVERS ATTRIBUTE */
if (mask & LDAP_REALM_ADMINSERVERS) {
/* validate the server list */
for (i=0; rparams->adminservers[i] != NULL; ++i) {
st = checkattributevalue(ld, rparams->adminservers[i], "objectClass", adminclass,
&objectmask);
CHECK_CLASS_VALIDITY(st, objectmask, "admin service object value: ");
}
if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbadmservers", LDAP_MOD_ADD,
rparams->adminservers)) != 0)
goto cleanup;
}
/* PASSWDSERVERS ATTRIBUTE */
if (mask & LDAP_REALM_PASSWDSERVERS) {
/* validate the server list */
for (i=0; rparams->passwdservers[i] != NULL; ++i) {
st = checkattributevalue(ld, rparams->passwdservers[i], "objectClass", pwdclass,
&objectmask);
CHECK_CLASS_VALIDITY(st, objectmask, "password service object value: ");
}
if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdservers", LDAP_MOD_ADD,
rparams->passwdservers)) != 0)
goto cleanup;
}
#endif
/* realm creation operation */
if ((st=ldap_add_ext_s(ld, dn, mods, NULL, NULL)) != LDAP_SUCCESS) {
st = set_ldap_error (context, st, OP_ADD);
goto cleanup;
}
#ifdef HAVE_EDIRECTORY
if (mask & LDAP_REALM_KDCSERVERS)
for (i=0; rparams->kdcservers[i]; ++i)
if ((st=updateAttribute(ld, rparams->kdcservers[i], "krbRealmReferences", dn)) != 0) {
snprintf(errbuf, sizeof(errbuf), "Error adding 'krbRealmReferences' to %s: ",
rparams->kdcservers[i]);
prepend_err_str (context, errbuf, st, st);
/* delete Realm, status ignored intentionally */
ldap_delete_ext_s(ld, dn, NULL, NULL);
goto cleanup;
}
if (mask & LDAP_REALM_ADMINSERVERS)
for (i=0; rparams->adminservers[i]; ++i)
if ((st=updateAttribute(ld, rparams->adminservers[i], "krbRealmReferences", dn)) != 0) {
snprintf(errbuf, sizeof(errbuf), "Error adding 'krbRealmReferences' to %s: ",
rparams->adminservers[i]);
prepend_err_str (context, errbuf, st, st);
/* delete Realm, status ignored intentionally */
ldap_delete_ext_s(ld, dn, NULL, NULL);
goto cleanup;
}
if (mask & LDAP_REALM_PASSWDSERVERS)
for (i=0; rparams->passwdservers[i]; ++i)
if ((st=updateAttribute(ld, rparams->passwdservers[i], "krbRealmReferences", dn)) != 0) {
snprintf(errbuf, sizeof(errbuf), "Error adding 'krbRealmReferences' to %s: ",
rparams->passwdservers[i]);
prepend_err_str (context, errbuf, st, st);
/* delete Realm, status ignored intentionally */
ldap_delete_ext_s(ld, dn, NULL, NULL);
goto cleanup;
}
#endif
cleanup:
if (dn)
free(dn);
ldap_mods_free(mods, 1);
krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
return st;
}
/*
* Read the realm container configuration from eDirectory for the specified realm.
*/
krb5_error_code
krb5_ldap_read_realm_params(krb5_context context, char *lrealm,
krb5_ldap_realm_params **rlparamp, int *mask)
{
char **values=NULL, *krbcontDN=NULL /*, *curr=NULL */;
#ifdef HAVE_EDIRECTORY
unsigned int count=0;
#endif
krb5_error_code st=0, tempst=0;
LDAP *ld=NULL;
LDAPMessage *result=NULL,*ent=NULL;
krb5_ldap_realm_params *rlparams=NULL;
kdb5_dal_handle *dal_handle=NULL;
krb5_ldap_context *ldap_context=NULL;
krb5_ldap_server_handle *ldap_server_handle=NULL;
int x=0;
SETUP_CONTEXT ();
/* validate the input parameter */
if (lrealm == NULL ||
ldap_context->krbcontainer == NULL ||
ldap_context->krbcontainer->DN == NULL) {
st = EINVAL;
goto cleanup;
}
/* read kerberos container, if not read already */
if (ldap_context->krbcontainer == NULL) {
if ((st = krb5_ldap_read_krbcontainer_params(context,
&(ldap_context->krbcontainer))) != 0)
goto cleanup;
}
/* get ldap handle */
GET_HANDLE ();
/* Initialize realm container structure */
rlparams =(krb5_ldap_realm_params *) malloc(sizeof(krb5_ldap_realm_params));
CHECK_NULL(rlparams);
memset(rlparams, 0, sizeof(krb5_ldap_realm_params));
/* allocate tl_data structure to store MASK information */
rlparams->tl_data = malloc (sizeof(krb5_tl_data));
if (rlparams->tl_data == NULL) {
st = ENOMEM;
goto cleanup;
}
memset(rlparams->tl_data, 0, sizeof(krb5_tl_data));
rlparams->tl_data->tl_data_type = KDB_TL_USER_INFO;
/* set the mask parameter to 0 */
*mask = 0;
/* set default values */
rlparams->search_scope = LDAP_SCOPE_SUBTREE;
krbcontDN = ldap_context->krbcontainer->DN;
if (asprintf(&rlparams->realmdn, "cn=%s,%s", lrealm, krbcontDN) < 0) {
rlparams->realmdn = NULL;
st = ENOMEM;
goto cleanup;
}
/* populate the realm name in the structure */
rlparams->realm_name = strdup(lrealm);
CHECK_NULL(rlparams->realm_name);
LDAP_SEARCH(rlparams->realmdn, LDAP_SCOPE_BASE, "(objectclass=krbRealmContainer)", realm_attributes);
if ((st = ldap_count_entries(ld, result)) <= 0) {
/* This could happen when the DN used to bind and read the realm object
* does not have sufficient rights to read its attributes
*/
st = KRB5_KDB_ACCESS_ERROR; /* return some other error ? */
goto cleanup;
}
ent = ldap_first_entry (ld, result);
if (ent == NULL) {
ldap_get_option (ld, LDAP_OPT_ERROR_NUMBER, (void *) &st);
#if 0
st = translate_ldap_error(st, OP_SEARCH);
#endif
goto cleanup;
}
/* Read the attributes */
{
if ((values=ldap_get_values(ld, ent, "krbSubTrees")) != NULL) {
rlparams->subtreecount = ldap_count_values(values);
rlparams->subtree = (char **) malloc(sizeof(char *) * (rlparams->subtreecount + 1));
if (rlparams->subtree == NULL) {
st = ENOMEM;
goto cleanup;
}
for (x=0; x<rlparams->subtreecount; x++) {
rlparams->subtree[x] = strdup(values[x]);
if (rlparams->subtree[x] == NULL) {
st = ENOMEM;
goto cleanup;
}
}
rlparams->subtree[rlparams->subtreecount] = NULL;
*mask |= LDAP_REALM_SUBTREE;
ldap_value_free(values);
}
if((values=ldap_get_values(ld, ent, "krbPrincContainerRef")) != NULL) {
rlparams->containerref = strdup(values[0]);
if(rlparams->containerref == NULL) {
st = ENOMEM;
goto cleanup;
}
*mask |= LDAP_REALM_CONTREF;
ldap_value_free(values);
}
if ((values=ldap_get_values(ld, ent, "krbSearchScope")) != NULL) {
rlparams->search_scope=atoi(values[0]);
/* searchscope can be ONE-LEVEL or SUBTREE, else default to SUBTREE */
if (!(rlparams->search_scope==1 || rlparams->search_scope==2))
rlparams->search_scope = LDAP_SCOPE_SUBTREE;
*mask |= LDAP_REALM_SEARCHSCOPE;
ldap_value_free(values);
}
if ((values=ldap_get_values(ld, ent, "krbMaxTicketLife")) != NULL) {
rlparams->max_life = atoi(values[0]);
*mask |= LDAP_REALM_MAXTICKETLIFE;
ldap_value_free(values);
}
if ((values=ldap_get_values(ld, ent, "krbMaxRenewableAge")) != NULL) {
rlparams->max_renewable_life = atoi(values[0]);
*mask |= LDAP_REALM_MAXRENEWLIFE;
ldap_value_free(values);
}
if ((values=ldap_get_values(ld, ent, "krbTicketFlags")) != NULL) {
rlparams->tktflags = atoi(values[0]);
*mask |= LDAP_REALM_KRBTICKETFLAGS;
ldap_value_free(values);
}
#ifdef HAVE_EDIRECTORY
if ((values=ldap_get_values(ld, ent, "krbKdcServers")) != NULL) {
count = ldap_count_values(values);
if ((st=copy_arrays(values, &(rlparams->kdcservers), (int) count)) != 0)
goto cleanup;
*mask |= LDAP_REALM_KDCSERVERS;
ldap_value_free(values);
}
if ((values=ldap_get_values(ld, ent, "krbAdmServers")) != NULL) {
count = ldap_count_values(values);
if ((st=copy_arrays(values, &(rlparams->adminservers), (int) count)) != 0)
goto cleanup;
*mask |= LDAP_REALM_ADMINSERVERS;
ldap_value_free(values);
}
if ((values=ldap_get_values(ld, ent, "krbPwdServers")) != NULL) {
count = ldap_count_values(values);
if ((st=copy_arrays(values, &(rlparams->passwdservers), (int) count)) != 0)
goto cleanup;
*mask |= LDAP_REALM_PASSWDSERVERS;
ldap_value_free(values);
}
#endif
}
ldap_msgfree(result);
/*
* If all of maxtktlife, maxrenewlife and ticketflags are not directly
* available, use the policy dn from the policy reference attribute, if
* available, to fetch the missing.
*/
if ((!(*mask & LDAP_REALM_MAXTICKETLIFE && *mask & LDAP_REALM_MAXRENEWLIFE &&
*mask & LDAP_REALM_KRBTICKETFLAGS)) && rlparams->policyreference) {
LDAP_SEARCH_1(rlparams->policyreference, LDAP_SCOPE_BASE, NULL, policy_attributes, IGNORE_STATUS);
if (st != LDAP_SUCCESS && st != LDAP_NO_SUCH_OBJECT) {
int ost = st;
st = translate_ldap_error (st, OP_SEARCH);
krb5_set_error_message (context, st, gettext("Policy object read failed: %s"), ldap_err2string(ost));
goto cleanup;
}
ent = ldap_first_entry (ld, result);
if (ent != NULL) {
if ((*mask & LDAP_REALM_MAXTICKETLIFE) == 0) {
if ((values=ldap_get_values(ld, ent, "krbmaxticketlife")) != NULL) {
rlparams->max_life = atoi(values[0]);
*mask |= LDAP_REALM_MAXTICKETLIFE;
ldap_value_free(values);
}
}
if ((*mask & LDAP_REALM_MAXRENEWLIFE) == 0) {
if ((values=ldap_get_values(ld, ent, "krbmaxrenewableage")) != NULL) {
rlparams->max_renewable_life = atoi(values[0]);
*mask |= LDAP_REALM_MAXRENEWLIFE;
ldap_value_free(values);
}
}
if ((*mask & LDAP_REALM_KRBTICKETFLAGS) == 0) {
if ((values=ldap_get_values(ld, ent, "krbticketflags")) != NULL) {
rlparams->tktflags = atoi(values[0]);
*mask |= LDAP_REALM_KRBTICKETFLAGS;
ldap_value_free(values);
}
}
}
ldap_msgfree(result);
}
rlparams->mask = *mask;
*rlparamp = rlparams;
st = store_tl_data(rlparams->tl_data, KDB_TL_MASK, mask);
cleanup:
/* if there is an error, free allocated structures */
if (st != 0) {
krb5_ldap_free_realm_params(rlparams);
*rlparamp=NULL;
}
krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
return st;
}
/*
Free the krb5_ldap_realm_params.
*/
void
krb5_ldap_free_realm_params(krb5_ldap_realm_params *rparams)
{
int i=0;
if (rparams) {
if (rparams->realmdn)
free(rparams->realmdn);
if (rparams->realm_name)
krb5_xfree(rparams->realm_name);
if (rparams->subtree) {
for (i=0; i<rparams->subtreecount && rparams->subtree[i] ; i++)
krb5_xfree(rparams->subtree[i]);
krb5_xfree(rparams->subtree);
}
if (rparams->kdcservers) {
for (i=0; rparams->kdcservers[i]; ++i)
krb5_xfree(rparams->kdcservers[i]);
krb5_xfree(rparams->kdcservers);
}
if (rparams->adminservers) {
for (i=0; rparams->adminservers[i]; ++i)
krb5_xfree(rparams->adminservers[i]);
krb5_xfree(rparams->adminservers);
}
if (rparams->passwdservers) {
for (i=0; rparams->passwdservers[i]; ++i)
krb5_xfree(rparams->passwdservers[i]);
krb5_xfree(rparams->passwdservers);
}
if (rparams->tl_data) {
if (rparams->tl_data->tl_data_contents)
krb5_xfree(rparams->tl_data->tl_data_contents);
krb5_xfree(rparams->tl_data);
}
if (rparams->mkey.contents) {
memset(rparams->mkey.contents, 0, rparams->mkey.length);
krb5_xfree(rparams->mkey.contents);
}
krb5_xfree(rparams);
}
return;
}
/*
* ******************************************************************************
* DAL functions
* ******************************************************************************
*/
krb5_error_code
krb5_ldap_delete_realm_1(krb5_context kcontext, char *conf_section,
char **db_args)
{
krb5_error_code status = KRB5_PLUGIN_OP_NOTSUPP;
krb5_set_error_message(kcontext, status, "LDAP %s", error_message(status));
return status;
}