1*54925bf6Swillf #pragma ident	"%Z%%M%	%I%	%E% SMI"
2*54925bf6Swillf 
3*54925bf6Swillf /*
4*54925bf6Swillf  * lib/kdb/kdb_ldap/ldap_tkt_policy.c
5*54925bf6Swillf  *
6*54925bf6Swillf  * Copyright (c) 2004-2005, Novell, Inc.
7*54925bf6Swillf  * All rights reserved.
8*54925bf6Swillf  *
9*54925bf6Swillf  * Redistribution and use in source and binary forms, with or without
10*54925bf6Swillf  * modification, are permitted provided that the following conditions are met:
11*54925bf6Swillf  *
12*54925bf6Swillf  *   * Redistributions of source code must retain the above copyright notice,
13*54925bf6Swillf  *       this list of conditions and the following disclaimer.
14*54925bf6Swillf  *   * Redistributions in binary form must reproduce the above copyright
15*54925bf6Swillf  *       notice, this list of conditions and the following disclaimer in the
16*54925bf6Swillf  *       documentation and/or other materials provided with the distribution.
17*54925bf6Swillf  *   * The copyright holder's name is not used to endorse or promote products
18*54925bf6Swillf  *       derived from this software without specific prior written permission.
19*54925bf6Swillf  *
20*54925bf6Swillf  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21*54925bf6Swillf  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22*54925bf6Swillf  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23*54925bf6Swillf  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24*54925bf6Swillf  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25*54925bf6Swillf  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26*54925bf6Swillf  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27*54925bf6Swillf  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28*54925bf6Swillf  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29*54925bf6Swillf  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30*54925bf6Swillf  * POSSIBILITY OF SUCH DAMAGE.
31*54925bf6Swillf  */
32*54925bf6Swillf 
33*54925bf6Swillf #include "ldap_main.h"
34*54925bf6Swillf #include "kdb_ldap.h"
35*54925bf6Swillf #include "ldap_tkt_policy.h"
36*54925bf6Swillf #include "ldap_err.h"
37*54925bf6Swillf #include <libintl.h>
38*54925bf6Swillf 
39*54925bf6Swillf /* Ticket policy object management */
40*54925bf6Swillf 
41*54925bf6Swillf /*
42*54925bf6Swillf  * create the Ticket policy object in Directory.
43*54925bf6Swillf  */
44*54925bf6Swillf krb5_error_code
45*54925bf6Swillf krb5_ldap_create_policy(context, policy, mask)
46*54925bf6Swillf     krb5_context	        context;
47*54925bf6Swillf     krb5_ldap_policy_params     *policy;
48*54925bf6Swillf     int                         mask;
49*54925bf6Swillf {
50*54925bf6Swillf     krb5_error_code             st=0;
51*54925bf6Swillf     LDAP                        *ld=NULL;
52*54925bf6Swillf     char                        *strval[3]={NULL}, *policy_dn = NULL;
53*54925bf6Swillf     LDAPMod                     **mods=NULL;
54*54925bf6Swillf     kdb5_dal_handle             *dal_handle=NULL;
55*54925bf6Swillf     krb5_ldap_context           *ldap_context=NULL;
56*54925bf6Swillf     krb5_ldap_server_handle     *ldap_server_handle=NULL;
57*54925bf6Swillf 
58*54925bf6Swillf     /* validate the input parameters */
59*54925bf6Swillf     if (policy == NULL || policy->policy == NULL) {
60*54925bf6Swillf 	st = EINVAL;
61*54925bf6Swillf 	krb5_set_error_message (context, st, gettext("Ticket Policy Name missing"));
62*54925bf6Swillf 	goto cleanup;
63*54925bf6Swillf     }
64*54925bf6Swillf 
65*54925bf6Swillf     SETUP_CONTEXT();
66*54925bf6Swillf     GET_HANDLE();
67*54925bf6Swillf 
68*54925bf6Swillf     if ((st = krb5_ldap_name_to_policydn (context, policy->policy, &policy_dn)) != 0)
69*54925bf6Swillf 	goto cleanup;
70*54925bf6Swillf 
71*54925bf6Swillf     memset(strval, 0, sizeof(strval));
72*54925bf6Swillf     strval[0] = policy->policy;
73*54925bf6Swillf     if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0)
74*54925bf6Swillf 	goto cleanup;
75*54925bf6Swillf 
76*54925bf6Swillf     memset(strval, 0, sizeof(strval));
77*54925bf6Swillf     strval[0] = "krbTicketPolicy";
78*54925bf6Swillf     strval[1] = "krbTicketPolicyaux";
79*54925bf6Swillf     if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
80*54925bf6Swillf 	goto cleanup;
81*54925bf6Swillf 
82*54925bf6Swillf     if (mask & LDAP_POLICY_MAXTKTLIFE) {
83*54925bf6Swillf 	if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxticketlife", LDAP_MOD_ADD,
84*54925bf6Swillf 					  policy->maxtktlife)) != 0)
85*54925bf6Swillf 	    goto cleanup;
86*54925bf6Swillf     }
87*54925bf6Swillf 
88*54925bf6Swillf     if (mask & LDAP_POLICY_MAXRENEWLIFE) {
89*54925bf6Swillf 	if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxrenewableage", LDAP_MOD_ADD,
90*54925bf6Swillf 					  policy->maxrenewlife)) != 0)
91*54925bf6Swillf 	    goto cleanup;
92*54925bf6Swillf     }
93*54925bf6Swillf 
94*54925bf6Swillf     if (mask & LDAP_POLICY_TKTFLAGS) {
95*54925bf6Swillf 	if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbticketflags", LDAP_MOD_ADD,
96*54925bf6Swillf 					  policy->tktflags)) != 0)
97*54925bf6Swillf 	    goto cleanup;
98*54925bf6Swillf     }
99*54925bf6Swillf 
100*54925bf6Swillf     /* ldap add operation */
101*54925bf6Swillf     if ((st=ldap_add_ext_s(ld, policy_dn, mods, NULL, NULL)) != LDAP_SUCCESS) {
102*54925bf6Swillf 	st = set_ldap_error (context, st, OP_ADD);
103*54925bf6Swillf 	goto cleanup;
104*54925bf6Swillf     }
105*54925bf6Swillf 
106*54925bf6Swillf cleanup:
107*54925bf6Swillf     if (policy_dn != NULL)
108*54925bf6Swillf 	free(policy_dn);
109*54925bf6Swillf 
110*54925bf6Swillf     ldap_mods_free(mods, 1);
111*54925bf6Swillf     krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
112*54925bf6Swillf     return st;
113*54925bf6Swillf }
114*54925bf6Swillf 
115*54925bf6Swillf 
116*54925bf6Swillf /*
117*54925bf6Swillf  * modify the Ticket policy object in Directory.
118*54925bf6Swillf  */
119*54925bf6Swillf 
120*54925bf6Swillf krb5_error_code
121*54925bf6Swillf krb5_ldap_modify_policy(context, policy, mask)
122*54925bf6Swillf     krb5_context	        context;
123*54925bf6Swillf     krb5_ldap_policy_params     *policy;
124*54925bf6Swillf     int                         mask;
125*54925bf6Swillf {
126*54925bf6Swillf     int                         objectmask=0;
127*54925bf6Swillf     krb5_error_code             st=0;
128*54925bf6Swillf     LDAP                        *ld=NULL;
129*54925bf6Swillf     char                        *attrvalues[]={"krbTicketPolicy", "krbTicketPolicyAux", NULL}, *strval[2]={NULL};
130*54925bf6Swillf     char                        *policy_dn = NULL;
131*54925bf6Swillf     LDAPMod                     **mods=NULL;
132*54925bf6Swillf     kdb5_dal_handle             *dal_handle=NULL;
133*54925bf6Swillf     krb5_ldap_context           *ldap_context=NULL;
134*54925bf6Swillf     krb5_ldap_server_handle     *ldap_server_handle=NULL;
135*54925bf6Swillf 
136*54925bf6Swillf     /* validate the input parameters */
137*54925bf6Swillf     if (policy == NULL || policy->policy==NULL) {
138*54925bf6Swillf 	st = EINVAL;
139*54925bf6Swillf 	krb5_set_error_message (context, st, gettext("Ticket Policy Name missing"));
140*54925bf6Swillf 	goto cleanup;
141*54925bf6Swillf     }
142*54925bf6Swillf 
143*54925bf6Swillf     SETUP_CONTEXT();
144*54925bf6Swillf     GET_HANDLE();
145*54925bf6Swillf 
146*54925bf6Swillf     if ((st = krb5_ldap_name_to_policydn (context, policy->policy, &policy_dn)) != 0)
147*54925bf6Swillf 	goto cleanup;
148*54925bf6Swillf 
149*54925bf6Swillf     /* the policydn object should be of the krbTicketPolicy object class */
150*54925bf6Swillf     st = checkattributevalue(ld, policy_dn, "objectClass", attrvalues, &objectmask);
151*54925bf6Swillf     CHECK_CLASS_VALIDITY(st, objectmask, "ticket policy object: ");
152*54925bf6Swillf 
153*54925bf6Swillf     if ((objectmask & 0x02) == 0) { /* add krbticketpolicyaux to the object class list */
154*54925bf6Swillf 	memset(strval, 0, sizeof(strval));
155*54925bf6Swillf 	strval[0] = "krbTicketPolicyAux";
156*54925bf6Swillf 	if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
157*54925bf6Swillf 	    goto cleanup;
158*54925bf6Swillf     }
159*54925bf6Swillf 
160*54925bf6Swillf     if (mask & LDAP_POLICY_MAXTKTLIFE) {
161*54925bf6Swillf 	if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxticketlife", LDAP_MOD_REPLACE,
162*54925bf6Swillf 					  policy->maxtktlife)) != 0)
163*54925bf6Swillf 	    goto cleanup;
164*54925bf6Swillf     }
165*54925bf6Swillf 
166*54925bf6Swillf     if (mask & LDAP_POLICY_MAXRENEWLIFE) {
167*54925bf6Swillf 	if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxrenewableage", LDAP_MOD_REPLACE,
168*54925bf6Swillf 					  policy->maxrenewlife)) != 0)
169*54925bf6Swillf 	    goto cleanup;
170*54925bf6Swillf     }
171*54925bf6Swillf 
172*54925bf6Swillf     if (mask & LDAP_POLICY_TKTFLAGS) {
173*54925bf6Swillf 	if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbticketflags", LDAP_MOD_REPLACE,
174*54925bf6Swillf 					  policy->tktflags)) != 0)
175*54925bf6Swillf 	    goto cleanup;
176*54925bf6Swillf     }
177*54925bf6Swillf 
178*54925bf6Swillf     if ((st=ldap_modify_ext_s(ld, policy_dn, mods, NULL, NULL)) != LDAP_SUCCESS) {
179*54925bf6Swillf 	st = set_ldap_error (context, st, OP_MOD);
180*54925bf6Swillf 	goto cleanup;
181*54925bf6Swillf     }
182*54925bf6Swillf 
183*54925bf6Swillf cleanup:
184*54925bf6Swillf     if (policy_dn != NULL)
185*54925bf6Swillf         free(policy_dn);
186*54925bf6Swillf 
187*54925bf6Swillf     ldap_mods_free(mods, 1);
188*54925bf6Swillf     krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
189*54925bf6Swillf     return st;
190*54925bf6Swillf }
191*54925bf6Swillf 
192*54925bf6Swillf 
193*54925bf6Swillf /*
194*54925bf6Swillf  * Read the policy object from the Directory and populate the krb5_ldap_policy_params
195*54925bf6Swillf  * structure.
196*54925bf6Swillf  */
197*54925bf6Swillf 
198*54925bf6Swillf krb5_error_code
199*54925bf6Swillf krb5_ldap_read_policy(context, policyname, policy, omask)
200*54925bf6Swillf     krb5_context	        context;
201*54925bf6Swillf     char                        *policyname;
202*54925bf6Swillf     krb5_ldap_policy_params     **policy;
203*54925bf6Swillf     unsigned int                *omask; /* Solaris kerberos: unsigned better for mask */
204*54925bf6Swillf {
205*54925bf6Swillf     krb5_error_code             st=0, tempst=0;
206*54925bf6Swillf     int                         objectmask=0;
207*54925bf6Swillf     LDAP                        *ld=NULL;
208*54925bf6Swillf     LDAPMessage                 *result=NULL,*ent=NULL;
209*54925bf6Swillf     char                        *attributes[] = { "krbMaxTicketLife", "krbMaxRenewableAge", "krbTicketFlags", NULL};
210*54925bf6Swillf     char                        *attrvalues[] = { "krbTicketPolicy", NULL}, *policy_dn = NULL;
211*54925bf6Swillf     krb5_ldap_policy_params     *lpolicy=NULL;
212*54925bf6Swillf     kdb5_dal_handle             *dal_handle=NULL;
213*54925bf6Swillf     krb5_ldap_context           *ldap_context=NULL;
214*54925bf6Swillf     krb5_ldap_server_handle     *ldap_server_handle=NULL;
215*54925bf6Swillf 
216*54925bf6Swillf     /* validate the input parameters */
217*54925bf6Swillf     if (policyname == NULL  || policy == NULL) {
218*54925bf6Swillf 	st = EINVAL;
219*54925bf6Swillf 	krb5_set_error_message(context, st, gettext("Ticket Policy Object information missing"));
220*54925bf6Swillf 	goto cleanup;
221*54925bf6Swillf     }
222*54925bf6Swillf 
223*54925bf6Swillf     SETUP_CONTEXT();
224*54925bf6Swillf     GET_HANDLE();
225*54925bf6Swillf 
226*54925bf6Swillf     if ((st = krb5_ldap_name_to_policydn (context, policyname, &policy_dn)) != 0)
227*54925bf6Swillf 	goto cleanup;
228*54925bf6Swillf 
229*54925bf6Swillf     /* the policydn object should be of the krbTicketPolicy object class */
230*54925bf6Swillf     st = checkattributevalue(ld, policy_dn, "objectClass", attrvalues, &objectmask);
231*54925bf6Swillf     CHECK_CLASS_VALIDITY(st, objectmask, "ticket policy object: ");
232*54925bf6Swillf 
233*54925bf6Swillf     /* Initialize ticket policy structure */
234*54925bf6Swillf     lpolicy =(krb5_ldap_policy_params *) malloc(sizeof(krb5_ldap_policy_params));
235*54925bf6Swillf     CHECK_NULL(lpolicy);
236*54925bf6Swillf     memset(lpolicy, 0, sizeof(krb5_ldap_policy_params));
237*54925bf6Swillf 
238*54925bf6Swillf     if ((lpolicy->policy = strdup (policyname)) == NULL) {
239*54925bf6Swillf 	st = ENOMEM;
240*54925bf6Swillf 	goto cleanup;
241*54925bf6Swillf     }
242*54925bf6Swillf 
243*54925bf6Swillf     lpolicy->tl_data = calloc (1, sizeof(*lpolicy->tl_data));
244*54925bf6Swillf     CHECK_NULL(lpolicy->tl_data);
245*54925bf6Swillf     lpolicy->tl_data->tl_data_type = KDB_TL_USER_INFO;
246*54925bf6Swillf 
247*54925bf6Swillf     LDAP_SEARCH(policy_dn, LDAP_SCOPE_BASE, "(objectclass=krbTicketPolicy)", attributes);
248*54925bf6Swillf 
249*54925bf6Swillf     *omask = 0;
250*54925bf6Swillf 
251*54925bf6Swillf     ent=ldap_first_entry(ld, result);
252*54925bf6Swillf     if (ent != NULL) {
253*54925bf6Swillf 	if (krb5_ldap_get_value(ld, ent, "krbmaxticketlife", (int *) &(lpolicy->maxtktlife)) == 0)
254*54925bf6Swillf 	    *omask |= LDAP_POLICY_MAXTKTLIFE;
255*54925bf6Swillf 
256*54925bf6Swillf 	if (krb5_ldap_get_value(ld, ent, "krbmaxrenewableage", (int *) &(lpolicy->maxrenewlife)) == 0)
257*54925bf6Swillf 	    *omask |= LDAP_POLICY_MAXRENEWLIFE;
258*54925bf6Swillf 
259*54925bf6Swillf 	if (krb5_ldap_get_value(ld, ent, "krbticketflags", (int *) &(lpolicy->tktflags)) == 0)
260*54925bf6Swillf 	    *omask |= LDAP_POLICY_TKTFLAGS;
261*54925bf6Swillf     }
262*54925bf6Swillf     ldap_msgfree(result);
263*54925bf6Swillf 
264*54925bf6Swillf     lpolicy->mask = *omask;
265*54925bf6Swillf     store_tl_data(lpolicy->tl_data, KDB_TL_MASK, omask);
266*54925bf6Swillf     *policy = lpolicy;
267*54925bf6Swillf 
268*54925bf6Swillf cleanup:
269*54925bf6Swillf     if (st != 0) {
270*54925bf6Swillf 	krb5_ldap_free_policy(context, lpolicy);
271*54925bf6Swillf 	*policy = NULL;
272*54925bf6Swillf     }
273*54925bf6Swillf     krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
274*54925bf6Swillf     return st;
275*54925bf6Swillf }
276*54925bf6Swillf 
277*54925bf6Swillf 
278*54925bf6Swillf /*
279*54925bf6Swillf  * Function to delete ticket policy object from the directory.  Before
280*54925bf6Swillf  * calling this function krb5_ldap_read_policy should be called to
281*54925bf6Swillf  * check the existence of the object.  This serves one major purpose,
282*54925bf6Swillf  * i.e., if the object to be is anything other than the ticket policy
283*54925bf6Swillf  * object then the krb5_ldap_read_policy returns an error and thus is
284*54925bf6Swillf  * not accidently deleted in this function.
285*54925bf6Swillf  *
286*54925bf6Swillf  * NOTE: Other kerberos objects (user/realm object) might be having
287*54925bf6Swillf  * references to the policy object to be deleted. This situation is
288*54925bf6Swillf  * not handled here, instead is taken care of at all the places where
289*54925bf6Swillf  * the deleted policy object is read, to ignore a return status of
290*54925bf6Swillf  * LDAP_NO_SUCH_OBJECT and continue.
291*54925bf6Swillf  */
292*54925bf6Swillf 
293*54925bf6Swillf krb5_error_code
294*54925bf6Swillf krb5_ldap_delete_policy(context, policyname)
295*54925bf6Swillf     krb5_context                context;
296*54925bf6Swillf     char                        *policyname;
297*54925bf6Swillf {
298*54925bf6Swillf 	int                         refcount = 0;
299*54925bf6Swillf 	char                        *policy_dn = NULL;
300*54925bf6Swillf     krb5_error_code             st = 0;
301*54925bf6Swillf     LDAP                        *ld = NULL;
302*54925bf6Swillf     kdb5_dal_handle             *dal_handle=NULL;
303*54925bf6Swillf     krb5_ldap_context           *ldap_context=NULL;
304*54925bf6Swillf     krb5_ldap_server_handle     *ldap_server_handle=NULL;
305*54925bf6Swillf 
306*54925bf6Swillf     if (policyname == NULL) {
307*54925bf6Swillf 	st = EINVAL;
308*54925bf6Swillf 	prepend_err_str (context, gettext("Ticket Policy Object DN missing"),st,st);
309*54925bf6Swillf 	goto cleanup;
310*54925bf6Swillf     }
311*54925bf6Swillf 
312*54925bf6Swillf 
313*54925bf6Swillf     SETUP_CONTEXT();
314*54925bf6Swillf     GET_HANDLE();
315*54925bf6Swillf 
316*54925bf6Swillf     if ((st = krb5_ldap_name_to_policydn (context, policyname, &policy_dn)) != 0)
317*54925bf6Swillf         goto cleanup;
318*54925bf6Swillf 
319*54925bf6Swillf     /* Checking for policy count for 0 and will not permit delete if
320*54925bf6Swillf      * it is greater than 0.  */
321*54925bf6Swillf 
322*54925bf6Swillf     if ((st = krb5_ldap_get_reference_count (context, policy_dn,
323*54925bf6Swillf                     "krbTicketPolicyReference", &refcount, ld)) != 0)
324*54925bf6Swillf         goto cleanup;
325*54925bf6Swillf 
326*54925bf6Swillf     if (refcount == 0) {
327*54925bf6Swillf 	if ((st=ldap_delete_ext_s(ld, policy_dn, NULL, NULL)) != 0) {
328*54925bf6Swillf 	    prepend_err_str (context,ldap_err2string(st),st,st);
329*54925bf6Swillf 
330*54925bf6Swillf 	    goto cleanup;
331*54925bf6Swillf 	}
332*54925bf6Swillf     } else {
333*54925bf6Swillf 	st = EINVAL;
334*54925bf6Swillf 	prepend_err_str (context, gettext("Delete Failed: One or more Principals associated with the Ticket Policy"),st,st);
335*54925bf6Swillf 	goto cleanup;
336*54925bf6Swillf     }
337*54925bf6Swillf 
338*54925bf6Swillf cleanup:
339*54925bf6Swillf     if (policy_dn != NULL)
340*54925bf6Swillf         free (policy_dn);
341*54925bf6Swillf     krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
342*54925bf6Swillf     return st;
343*54925bf6Swillf }
344*54925bf6Swillf 
345*54925bf6Swillf 
346*54925bf6Swillf /*
347*54925bf6Swillf  * list policy objects from Directory
348*54925bf6Swillf  */
349*54925bf6Swillf 
350*54925bf6Swillf krb5_error_code
351*54925bf6Swillf krb5_ldap_list_policy(context, containerdn, policy)
352*54925bf6Swillf     krb5_context	        context;
353*54925bf6Swillf     char                        *containerdn;
354*54925bf6Swillf     char                        ***policy;
355*54925bf6Swillf {
356*54925bf6Swillf     int                         i, j, count;
357*54925bf6Swillf     char                        **list = NULL;
358*54925bf6Swillf     char                        *policycontainerdn = containerdn;
359*54925bf6Swillf     kdb5_dal_handle             *dal_handle=NULL;
360*54925bf6Swillf     krb5_ldap_context           *ldap_context=NULL;
361*54925bf6Swillf     krb5_error_code             st=0;
362*54925bf6Swillf 
363*54925bf6Swillf     SETUP_CONTEXT();
364*54925bf6Swillf     if (policycontainerdn == NULL) {
365*54925bf6Swillf         policycontainerdn = ldap_context->lrparams->realmdn;
366*54925bf6Swillf     }
367*54925bf6Swillf 
368*54925bf6Swillf     if ((st = krb5_ldap_list(context, &list, "krbTicketPolicy", policycontainerdn)) != 0)
369*54925bf6Swillf 	goto cleanup;
370*54925bf6Swillf 
371*54925bf6Swillf     for (i = 0; list[i] != NULL; i++);
372*54925bf6Swillf 
373*54925bf6Swillf     count = i;
374*54925bf6Swillf 
375*54925bf6Swillf     *policy = (char **) calloc ((unsigned) count + 1, sizeof(char *));
376*54925bf6Swillf     if (*policy == NULL) {
377*54925bf6Swillf 	st = ENOMEM;
378*54925bf6Swillf 	goto cleanup;
379*54925bf6Swillf     }
380*54925bf6Swillf 
381*54925bf6Swillf     for (i = 0, j = 0; list[i] != NULL; i++, j++) {
382*54925bf6Swillf 	int ret;
383*54925bf6Swillf 	ret = krb5_ldap_policydn_to_name (context, list[i], &(*policy)[i]);
384*54925bf6Swillf 	if (ret != 0)
385*54925bf6Swillf 	    j--;
386*54925bf6Swillf     }
387*54925bf6Swillf 
388*54925bf6Swillf cleanup:
389*54925bf6Swillf     return st;
390*54925bf6Swillf }
391*54925bf6Swillf 
392*54925bf6Swillf /*
393*54925bf6Swillf  * Function to free the ticket policy object structure.
394*54925bf6Swillf  * Note: this function assumes that memory of the policy structure is dynamically allocated and hence the whole
395*54925bf6Swillf  * structure is freed up. Care should be taken not to call this function on a static structure
396*54925bf6Swillf  */
397*54925bf6Swillf 
398*54925bf6Swillf krb5_error_code
399*54925bf6Swillf krb5_ldap_free_policy(context, policy)
400*54925bf6Swillf     krb5_context                context;
401*54925bf6Swillf     krb5_ldap_policy_params    *policy;
402*54925bf6Swillf {
403*54925bf6Swillf 
404*54925bf6Swillf     krb5_error_code st=0;
405*54925bf6Swillf 
406*54925bf6Swillf     if (policy == NULL)
407*54925bf6Swillf 	return st;
408*54925bf6Swillf 
409*54925bf6Swillf     if (policy->policy)
410*54925bf6Swillf 	free (policy->policy);
411*54925bf6Swillf 
412*54925bf6Swillf     if (policy->tl_data) {
413*54925bf6Swillf 	if (policy->tl_data->tl_data_contents)
414*54925bf6Swillf 	    free (policy->tl_data->tl_data_contents);
415*54925bf6Swillf 	free (policy->tl_data);
416*54925bf6Swillf     }
417*54925bf6Swillf     free (policy);
418*54925bf6Swillf 
419*54925bf6Swillf     return st;
420*54925bf6Swillf }
421*54925bf6Swillf 
422*54925bf6Swillf /*
423*54925bf6Swillf  * This function is general object listing routine.  It is currently
424*54925bf6Swillf  * used for ticket policy object listing.
425*54925bf6Swillf  */
426*54925bf6Swillf 
427*54925bf6Swillf krb5_error_code
428*54925bf6Swillf krb5_ldap_list(context, list, objectclass, containerdn)
429*54925bf6Swillf     krb5_context	        context;
430*54925bf6Swillf     char                        ***list;
431*54925bf6Swillf     char                        *objectclass;
432*54925bf6Swillf     char                        *containerdn;
433*54925bf6Swillf {
434*54925bf6Swillf     char                        *filter=NULL, *dn=NULL;
435*54925bf6Swillf     krb5_error_code             st=0, tempst=0;
436*54925bf6Swillf     int                         i=0, count=0, filterlen=0;
437*54925bf6Swillf     LDAP                        *ld=NULL;
438*54925bf6Swillf     LDAPMessage                 *result=NULL,*ent=NULL;
439*54925bf6Swillf     kdb5_dal_handle             *dal_handle=NULL;
440*54925bf6Swillf     krb5_ldap_context           *ldap_context=NULL;
441*54925bf6Swillf     krb5_ldap_server_handle     *ldap_server_handle=NULL;
442*54925bf6Swillf 
443*54925bf6Swillf     SETUP_CONTEXT();
444*54925bf6Swillf     GET_HANDLE();
445*54925bf6Swillf 
446*54925bf6Swillf     /* check if the containerdn exists */
447*54925bf6Swillf     if (containerdn) {
448*54925bf6Swillf 	if ((st=checkattributevalue(ld, containerdn, NULL, NULL, NULL)) != 0) {
449*54925bf6Swillf 	    prepend_err_str (context, gettext("Error reading container object: "), st, st);
450*54925bf6Swillf 	    goto cleanup;
451*54925bf6Swillf 	}
452*54925bf6Swillf     }
453*54925bf6Swillf 
454*54925bf6Swillf     /* set the filter for the search operation */
455*54925bf6Swillf     filterlen = strlen("(objectclass=") + strlen(objectclass) + 1 + 1;
456*54925bf6Swillf     filter = malloc ((unsigned) filterlen);
457*54925bf6Swillf     if (filter == NULL) {
458*54925bf6Swillf 	st = ENOMEM;
459*54925bf6Swillf 	goto cleanup;
460*54925bf6Swillf     }
461*54925bf6Swillf     snprintf(filter, (unsigned) filterlen,"(objectclass=%s)",objectclass);
462*54925bf6Swillf 
463*54925bf6Swillf     LDAP_SEARCH(containerdn, LDAP_SCOPE_SUBTREE, filter, NULL);
464*54925bf6Swillf 
465*54925bf6Swillf     count = ldap_count_entries(ld, result);
466*54925bf6Swillf     if (count == -1) {
467*54925bf6Swillf 	ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &st);
468*54925bf6Swillf 	st = set_ldap_error(context, st, OP_SEARCH);
469*54925bf6Swillf 	goto cleanup;
470*54925bf6Swillf     }
471*54925bf6Swillf     *list = (char **) calloc ((unsigned) count+1, sizeof(char *));
472*54925bf6Swillf     if (*list == NULL) {
473*54925bf6Swillf 	st = ENOMEM;
474*54925bf6Swillf 	goto cleanup;
475*54925bf6Swillf     }
476*54925bf6Swillf 
477*54925bf6Swillf     for (ent=ldap_first_entry(ld, result), count=0; ent != NULL; ent=ldap_next_entry(ld, ent), ++count) {
478*54925bf6Swillf 	if ((dn=ldap_get_dn(ld, ent)) == NULL)
479*54925bf6Swillf 	    continue;
480*54925bf6Swillf 	if (((*list)[count] = strdup(dn)) == NULL) {
481*54925bf6Swillf 	    ldap_memfree (dn);
482*54925bf6Swillf 	    st = ENOMEM;
483*54925bf6Swillf 	    goto cleanup;
484*54925bf6Swillf 	}
485*54925bf6Swillf 	ldap_memfree(dn);
486*54925bf6Swillf     }
487*54925bf6Swillf     ldap_msgfree(result);
488*54925bf6Swillf 
489*54925bf6Swillf cleanup:
490*54925bf6Swillf     if (filter)
491*54925bf6Swillf 	free (filter);
492*54925bf6Swillf 
493*54925bf6Swillf     /* some error, free up all the memory */
494*54925bf6Swillf     if (st != 0) {
495*54925bf6Swillf 	if (*list) {
496*54925bf6Swillf 	    for (i=0; (*list)[i]; ++i)
497*54925bf6Swillf 		free ((*list)[i]);
498*54925bf6Swillf 	    free (*list);
499*54925bf6Swillf 	    *list = NULL;
500*54925bf6Swillf 	}
501*54925bf6Swillf     }
502*54925bf6Swillf     krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
503*54925bf6Swillf     return st;
504*54925bf6Swillf }
505