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