xref: /illumos-gate/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c (revision 54925bf60766fbb4f1f2d7c843721406a7b7a3fb)
1*54925bf6Swillf #pragma ident	"%Z%%M%	%I%	%E% SMI"
2*54925bf6Swillf 
3*54925bf6Swillf /*
4*54925bf6Swillf  * lib/kdb/kdb_ldap/ldap_pwd_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  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
34*54925bf6Swillf  * Use is subject to license terms.
35*54925bf6Swillf  */
36*54925bf6Swillf 
37*54925bf6Swillf #include "ldap_main.h"
38*54925bf6Swillf #include "kdb_ldap.h"
39*54925bf6Swillf #include "ldap_pwd_policy.h"
40*54925bf6Swillf #include "ldap_err.h"
41*54925bf6Swillf #include <libintl.h>
42*54925bf6Swillf 
43*54925bf6Swillf static char *password_policy_attributes[] = { "cn", "krbmaxpwdlife", "krbminpwdlife",
44*54925bf6Swillf 					      "krbpwdmindiffchars", "krbpwdminlength",
45*54925bf6Swillf 					      "krbpwdhistorylength", NULL };
46*54925bf6Swillf 
47*54925bf6Swillf /*
48*54925bf6Swillf  * Function to create password policy object.
49*54925bf6Swillf  */
50*54925bf6Swillf 
51*54925bf6Swillf krb5_error_code
52*54925bf6Swillf krb5_ldap_create_password_policy (context, policy)
53*54925bf6Swillf     krb5_context                context;
54*54925bf6Swillf     osa_policy_ent_t            policy;
55*54925bf6Swillf {
56*54925bf6Swillf     krb5_error_code 	        st=0;
57*54925bf6Swillf     LDAP  		        *ld=NULL;
58*54925bf6Swillf     LDAPMod 		        **mods={NULL};
59*54925bf6Swillf     kdb5_dal_handle             *dal_handle=NULL;
60*54925bf6Swillf     krb5_ldap_context           *ldap_context=NULL;
61*54925bf6Swillf     krb5_ldap_server_handle     *ldap_server_handle=NULL;
62*54925bf6Swillf     char                        **rdns=NULL, *strval[2]={NULL}, *policy_dn;
63*54925bf6Swillf 
64*54925bf6Swillf     /* Clear the global error string */
65*54925bf6Swillf     krb5_clear_error_message(context);
66*54925bf6Swillf 
67*54925bf6Swillf     /* validate the input parameters */
68*54925bf6Swillf     if (policy == NULL || policy->name == NULL)
69*54925bf6Swillf 	return EINVAL;
70*54925bf6Swillf 
71*54925bf6Swillf     SETUP_CONTEXT();
72*54925bf6Swillf     GET_HANDLE();
73*54925bf6Swillf 
74*54925bf6Swillf     st = krb5_ldap_name_to_policydn (context, policy->name, &policy_dn);
75*54925bf6Swillf     if (st != 0)
76*54925bf6Swillf 	goto cleanup;
77*54925bf6Swillf 
78*54925bf6Swillf     /* get the first component of the dn to set the cn attribute */
79*54925bf6Swillf     rdns = ldap_explode_dn(policy_dn, 1);
80*54925bf6Swillf     if (rdns == NULL) {
81*54925bf6Swillf 	st = EINVAL;
82*54925bf6Swillf 	krb5_set_error_message(context, st, gettext("Invalid password policy DN syntax"));
83*54925bf6Swillf 	goto cleanup;
84*54925bf6Swillf     }
85*54925bf6Swillf 
86*54925bf6Swillf     strval[0] = rdns[0];
87*54925bf6Swillf     if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0)
88*54925bf6Swillf 	goto cleanup;
89*54925bf6Swillf 
90*54925bf6Swillf     strval[0] = "krbPwdPolicy";
91*54925bf6Swillf     if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
92*54925bf6Swillf 	goto cleanup;
93*54925bf6Swillf 
94*54925bf6Swillf     if (((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxpwdlife", LDAP_MOD_ADD,
95*54925bf6Swillf 				       (signed) policy->pw_max_life)) != 0)
96*54925bf6Swillf 	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbminpwdlife", LDAP_MOD_ADD,
97*54925bf6Swillf 					  (signed) policy->pw_min_life)) != 0)
98*54925bf6Swillf 	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdmindiffchars", LDAP_MOD_ADD,
99*54925bf6Swillf 					  (signed) policy->pw_min_classes)) != 0)
100*54925bf6Swillf 	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdminlength", LDAP_MOD_ADD,
101*54925bf6Swillf 					  (signed) policy->pw_min_length)) != 0)
102*54925bf6Swillf 	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdhistorylength", LDAP_MOD_ADD,
103*54925bf6Swillf 					  (signed) policy->pw_history_num)) != 0))
104*54925bf6Swillf 	goto cleanup;
105*54925bf6Swillf 
106*54925bf6Swillf     /* password policy object creation */
107*54925bf6Swillf     if ((st=ldap_add_ext_s(ld, policy_dn, mods, NULL, NULL)) != LDAP_SUCCESS) {
108*54925bf6Swillf 	st = set_ldap_error (context, st, OP_ADD);
109*54925bf6Swillf 	goto cleanup;
110*54925bf6Swillf     }
111*54925bf6Swillf 
112*54925bf6Swillf cleanup:
113*54925bf6Swillf     if (rdns)
114*54925bf6Swillf 	ldap_value_free(rdns);
115*54925bf6Swillf 
116*54925bf6Swillf     if (policy_dn != NULL)
117*54925bf6Swillf 	free (policy_dn);
118*54925bf6Swillf     ldap_mods_free(mods, 1);
119*54925bf6Swillf     krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
120*54925bf6Swillf     return(st);
121*54925bf6Swillf }
122*54925bf6Swillf 
123*54925bf6Swillf /*
124*54925bf6Swillf  * Function to modify password policy object.
125*54925bf6Swillf  */
126*54925bf6Swillf 
127*54925bf6Swillf krb5_error_code
128*54925bf6Swillf krb5_ldap_put_password_policy (context, policy)
129*54925bf6Swillf     krb5_context                context;
130*54925bf6Swillf     osa_policy_ent_t            policy;
131*54925bf6Swillf {
132*54925bf6Swillf     char                        *policy_dn;
133*54925bf6Swillf     krb5_error_code 	        st=0;
134*54925bf6Swillf     LDAP  		        *ld=NULL;
135*54925bf6Swillf     LDAPMod 		        **mods=NULL;
136*54925bf6Swillf     kdb5_dal_handle             *dal_handle=NULL;
137*54925bf6Swillf     krb5_ldap_context           *ldap_context=NULL;
138*54925bf6Swillf     krb5_ldap_server_handle     *ldap_server_handle=NULL;
139*54925bf6Swillf 
140*54925bf6Swillf     /* Clear the global error string */
141*54925bf6Swillf     krb5_clear_error_message(context);
142*54925bf6Swillf 
143*54925bf6Swillf     /* validate the input parameters */
144*54925bf6Swillf     if (policy == NULL || policy->name == NULL)
145*54925bf6Swillf 	return EINVAL;
146*54925bf6Swillf 
147*54925bf6Swillf     SETUP_CONTEXT();
148*54925bf6Swillf     GET_HANDLE();
149*54925bf6Swillf 
150*54925bf6Swillf     st = krb5_ldap_name_to_policydn (context, policy->name, &policy_dn);
151*54925bf6Swillf     if (st != 0)
152*54925bf6Swillf 	goto cleanup;
153*54925bf6Swillf 
154*54925bf6Swillf     if (((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxpwdlife", LDAP_MOD_REPLACE,
155*54925bf6Swillf 				       (signed) policy->pw_max_life)) != 0)
156*54925bf6Swillf 	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbminpwdlife", LDAP_MOD_REPLACE,
157*54925bf6Swillf 					  (signed) policy->pw_min_life)) != 0)
158*54925bf6Swillf 	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdmindiffchars", LDAP_MOD_REPLACE,
159*54925bf6Swillf 					  (signed) policy->pw_min_classes)) != 0)
160*54925bf6Swillf 	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdminlength", LDAP_MOD_REPLACE,
161*54925bf6Swillf 					  (signed) policy->pw_min_length)) != 0)
162*54925bf6Swillf 	|| ((st=krb5_add_int_mem_ldap_mod(&mods, "krbpwdhistorylength", LDAP_MOD_REPLACE,
163*54925bf6Swillf 					  (signed) policy->pw_history_num)) != 0))
164*54925bf6Swillf 	goto cleanup;
165*54925bf6Swillf 
166*54925bf6Swillf     /* modify the password policy object. */
167*54925bf6Swillf     /*
168*54925bf6Swillf      * This will fail if the 'policy_dn' is anywhere other than under the realm
169*54925bf6Swillf      * container. This is correct behaviour. 'kdb5_ldap_util' will support
170*54925bf6Swillf      * management of only such policy objects.
171*54925bf6Swillf      */
172*54925bf6Swillf     if ((st=ldap_modify_ext_s(ld, policy_dn, mods, NULL, NULL)) != LDAP_SUCCESS) {
173*54925bf6Swillf 	st = set_ldap_error (context, st, OP_MOD);
174*54925bf6Swillf 	goto cleanup;
175*54925bf6Swillf     }
176*54925bf6Swillf 
177*54925bf6Swillf cleanup:
178*54925bf6Swillf     if (policy_dn != NULL)
179*54925bf6Swillf 	free (policy_dn);
180*54925bf6Swillf     ldap_mods_free(mods, 1);
181*54925bf6Swillf     krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
182*54925bf6Swillf     return(st);
183*54925bf6Swillf }
184*54925bf6Swillf 
185*54925bf6Swillf krb5_error_code
186*54925bf6Swillf populate_policy(krb5_context context,
187*54925bf6Swillf     LDAP *ld,
188*54925bf6Swillf     LDAPMessage *ent,
189*54925bf6Swillf     char *pol_name,
190*54925bf6Swillf     osa_policy_ent_t pol_entry)
191*54925bf6Swillf {
192*54925bf6Swillf     int st = 0;
193*54925bf6Swillf     char *pol_dn;
194*54925bf6Swillf 
195*54925bf6Swillf     pol_entry->name = strdup(pol_name);
196*54925bf6Swillf     CHECK_NULL(pol_entry->name);
197*54925bf6Swillf     pol_entry->version = 1;
198*54925bf6Swillf 
199*54925bf6Swillf     krb5_ldap_get_value(ld, ent, "krbmaxpwdlife", (int *)&(pol_entry->pw_max_life));
200*54925bf6Swillf     krb5_ldap_get_value(ld, ent, "krbminpwdlife", (int *)&(pol_entry->pw_min_life));
201*54925bf6Swillf     krb5_ldap_get_value(ld, ent, "krbpwdmindiffchars", (int *)&(pol_entry->pw_min_classes));
202*54925bf6Swillf     krb5_ldap_get_value(ld, ent, "krbpwdminlength", (int *)&(pol_entry->pw_min_length));
203*54925bf6Swillf     krb5_ldap_get_value(ld, ent, "krbpwdhistorylength", (int *)&(pol_entry->pw_history_num));
204*54925bf6Swillf 
205*54925bf6Swillf     /* Get the reference count */
206*54925bf6Swillf     pol_dn = ldap_get_dn(ld, ent);
207*54925bf6Swillf     st = krb5_ldap_get_reference_count (context, pol_dn, "krbPwdPolicyReference",
208*54925bf6Swillf 	    (int *)&(pol_entry->policy_refcnt), ld);
209*54925bf6Swillf     ldap_memfree(pol_dn);
210*54925bf6Swillf 
211*54925bf6Swillf cleanup:
212*54925bf6Swillf     /* Solaris Kerberos: trying to avoid memory leaks */
213*54925bf6Swillf     if (st != 0) {
214*54925bf6Swillf 	free(pol_entry->name);
215*54925bf6Swillf 	pol_entry->name = NULL;
216*54925bf6Swillf     }
217*54925bf6Swillf     return st;
218*54925bf6Swillf }
219*54925bf6Swillf 
220*54925bf6Swillf krb5_error_code
221*54925bf6Swillf krb5_ldap_get_password_policy_from_dn (krb5_context context,
222*54925bf6Swillf     char *pol_name,
223*54925bf6Swillf     char *pol_dn,
224*54925bf6Swillf     osa_policy_ent_t *policy,
225*54925bf6Swillf     int *cnt)
226*54925bf6Swillf {
227*54925bf6Swillf     krb5_error_code             st=0, tempst=0;
228*54925bf6Swillf     LDAP  		        *ld=NULL;
229*54925bf6Swillf     LDAPMessage                 *result=NULL,*ent=NULL;
230*54925bf6Swillf     kdb5_dal_handle             *dal_handle=NULL;
231*54925bf6Swillf     krb5_ldap_context           *ldap_context=NULL;
232*54925bf6Swillf     krb5_ldap_server_handle     *ldap_server_handle=NULL;
233*54925bf6Swillf 
234*54925bf6Swillf     /* Clear the global error string */
235*54925bf6Swillf     krb5_clear_error_message(context);
236*54925bf6Swillf 
237*54925bf6Swillf     /* validate the input parameters */
238*54925bf6Swillf     if (pol_dn == NULL)
239*54925bf6Swillf 	return EINVAL;
240*54925bf6Swillf 
241*54925bf6Swillf     *policy = NULL;
242*54925bf6Swillf     SETUP_CONTEXT();
243*54925bf6Swillf     GET_HANDLE();
244*54925bf6Swillf 
245*54925bf6Swillf     *cnt = 0;
246*54925bf6Swillf     *(policy) = (osa_policy_ent_t) malloc(sizeof(osa_policy_ent_rec));
247*54925bf6Swillf     if (*policy == NULL) {
248*54925bf6Swillf 	st = ENOMEM;
249*54925bf6Swillf 	goto cleanup;
250*54925bf6Swillf     }
251*54925bf6Swillf     memset(*policy, 0, sizeof(osa_policy_ent_rec));
252*54925bf6Swillf 
253*54925bf6Swillf     LDAP_SEARCH(pol_dn, LDAP_SCOPE_BASE, "(objectclass=krbPwdPolicy)", password_policy_attributes);
254*54925bf6Swillf     *cnt = 1;
255*54925bf6Swillf #if 0 /************** Begin IFDEF'ed OUT *******************************/
256*54925bf6Swillf     (*policy)->name = strdup(name);
257*54925bf6Swillf     CHECK_NULL((*policy)->name);
258*54925bf6Swillf     (*policy)->version = 1;
259*54925bf6Swillf #endif /**************** END IFDEF'ed OUT *******************************/
260*54925bf6Swillf 
261*54925bf6Swillf     ent=ldap_first_entry(ld, result);
262*54925bf6Swillf     if (ent != NULL) {
263*54925bf6Swillf 	if ((st = populate_policy(context, ld, ent, pol_name, *policy)) != 0)
264*54925bf6Swillf 	    goto cleanup;
265*54925bf6Swillf #if 0 /************** Begin IFDEF'ed OUT *******************************/
266*54925bf6Swillf 	krb5_ldap_get_value(ld, ent, "krbmaxpwdlife", &((*policy)->pw_max_life));
267*54925bf6Swillf 	krb5_ldap_get_value(ld, ent, "krbminpwdlife", &((*policy)->pw_min_life));
268*54925bf6Swillf 	krb5_ldap_get_value(ld, ent, "krbpwdmindiffchars", &((*policy)->pw_min_classes));
269*54925bf6Swillf 	krb5_ldap_get_value(ld, ent, "krbpwdminlength", &((*policy)->pw_min_length));
270*54925bf6Swillf 	krb5_ldap_get_value(ld, ent, "krbpwdhistorylength", &((*policy)->pw_history_num));
271*54925bf6Swillf 
272*54925bf6Swillf 	/* Get the reference count */
273*54925bf6Swillf 	st = krb5_ldap_get_reference_count (context,
274*54925bf6Swillf 					    name,
275*54925bf6Swillf 					    "krbPwdPolicyReference",
276*54925bf6Swillf 					    &(*policy)->policy_refcnt,
277*54925bf6Swillf 					    ld);
278*54925bf6Swillf #endif /**************** END IFDEF'ed OUT *******************************/
279*54925bf6Swillf     }
280*54925bf6Swillf 
281*54925bf6Swillf cleanup:
282*54925bf6Swillf     ldap_msgfree(result);
283*54925bf6Swillf     if (st != 0) {
284*54925bf6Swillf 	if (*policy != NULL) {
285*54925bf6Swillf 	    krb5_ldap_free_password_policy(context, *policy);
286*54925bf6Swillf 	    *policy = NULL;
287*54925bf6Swillf 	}
288*54925bf6Swillf     }
289*54925bf6Swillf 
290*54925bf6Swillf     krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
291*54925bf6Swillf     return st;
292*54925bf6Swillf }
293*54925bf6Swillf 
294*54925bf6Swillf /*
295*54925bf6Swillf  * Convert 'name' into a directory DN and call
296*54925bf6Swillf  * 'krb5_ldap_get_password_policy_from_dn'
297*54925bf6Swillf  */
298*54925bf6Swillf krb5_error_code
299*54925bf6Swillf krb5_ldap_get_password_policy (context, name, policy, cnt)
300*54925bf6Swillf     krb5_context                context;
301*54925bf6Swillf     char                        *name;
302*54925bf6Swillf     osa_policy_ent_t            *policy;
303*54925bf6Swillf     int                         *cnt;
304*54925bf6Swillf {
305*54925bf6Swillf     krb5_error_code             st = 0;
306*54925bf6Swillf     char                        *policy_dn = NULL;
307*54925bf6Swillf 
308*54925bf6Swillf     /* Clear the global error string */
309*54925bf6Swillf     krb5_clear_error_message(context);
310*54925bf6Swillf 
311*54925bf6Swillf     /* validate the input parameters */
312*54925bf6Swillf     if (name == NULL) {
313*54925bf6Swillf 	st = EINVAL;
314*54925bf6Swillf 	goto cleanup;
315*54925bf6Swillf     }
316*54925bf6Swillf 
317*54925bf6Swillf     st = krb5_ldap_name_to_policydn(context, name, &policy_dn);
318*54925bf6Swillf     if (st != 0)
319*54925bf6Swillf 	goto cleanup;
320*54925bf6Swillf 
321*54925bf6Swillf     st = krb5_ldap_get_password_policy_from_dn(context, name, policy_dn, policy, cnt);
322*54925bf6Swillf 
323*54925bf6Swillf cleanup:
324*54925bf6Swillf     if (policy_dn != NULL)
325*54925bf6Swillf 	free (policy_dn);
326*54925bf6Swillf     return st;
327*54925bf6Swillf }
328*54925bf6Swillf 
329*54925bf6Swillf krb5_error_code
330*54925bf6Swillf krb5_ldap_delete_password_policy (context, policy)
331*54925bf6Swillf     krb5_context                context;
332*54925bf6Swillf     char                        *policy;
333*54925bf6Swillf {
334*54925bf6Swillf     int                         mask = 0;
335*54925bf6Swillf     char                        *policy_dn = NULL, *class[] = {"krbpwdpolicy", NULL};
336*54925bf6Swillf     krb5_error_code             st=0;
337*54925bf6Swillf     LDAP                        *ld=NULL;
338*54925bf6Swillf     kdb5_dal_handle             *dal_handle=NULL;
339*54925bf6Swillf     krb5_ldap_context           *ldap_context=NULL;
340*54925bf6Swillf     krb5_ldap_server_handle     *ldap_server_handle=NULL;
341*54925bf6Swillf 
342*54925bf6Swillf     /* Clear the global error string */
343*54925bf6Swillf     krb5_clear_error_message(context);
344*54925bf6Swillf 
345*54925bf6Swillf     /* validate the input parameters */
346*54925bf6Swillf     if (policy == NULL)
347*54925bf6Swillf 	return EINVAL;
348*54925bf6Swillf 
349*54925bf6Swillf     SETUP_CONTEXT();
350*54925bf6Swillf     GET_HANDLE();
351*54925bf6Swillf 
352*54925bf6Swillf     st = krb5_ldap_name_to_policydn (context, policy, &policy_dn);
353*54925bf6Swillf     if (st != 0)
354*54925bf6Swillf 	goto cleanup;
355*54925bf6Swillf 
356*54925bf6Swillf     /* Ensure that the object is a password policy */
357*54925bf6Swillf     if ((st=checkattributevalue(ld, policy_dn, "objectclass", class, &mask)) != 0)
358*54925bf6Swillf 	goto cleanup;
359*54925bf6Swillf 
360*54925bf6Swillf     if (mask == 0) {
361*54925bf6Swillf 	st = KRB5_KDB_NOENTRY;
362*54925bf6Swillf 	goto cleanup;
363*54925bf6Swillf     }
364*54925bf6Swillf 
365*54925bf6Swillf     if ((st=ldap_delete_ext_s(ld, policy_dn, NULL, NULL)) != LDAP_SUCCESS) {
366*54925bf6Swillf 	st = set_ldap_error (context, st, OP_DEL);
367*54925bf6Swillf 	goto cleanup;
368*54925bf6Swillf     }
369*54925bf6Swillf 
370*54925bf6Swillf cleanup:
371*54925bf6Swillf     krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
372*54925bf6Swillf     if (policy_dn != NULL)
373*54925bf6Swillf 	free (policy_dn);
374*54925bf6Swillf 
375*54925bf6Swillf     return st;
376*54925bf6Swillf }
377*54925bf6Swillf 
378*54925bf6Swillf krb5_error_code
379*54925bf6Swillf krb5_ldap_iterate_password_policy(context, match_expr, func, func_arg)
380*54925bf6Swillf     krb5_context                context;
381*54925bf6Swillf     char                        *match_expr;
382*54925bf6Swillf     void                        (*func) (krb5_pointer, osa_policy_ent_t);
383*54925bf6Swillf     krb5_pointer                func_arg;
384*54925bf6Swillf {
385*54925bf6Swillf     osa_policy_ent_rec          *entry=NULL;
386*54925bf6Swillf     char		        *policy=NULL;
387*54925bf6Swillf     krb5_error_code             st=0, tempst=0;
388*54925bf6Swillf     LDAP		        *ld=NULL;
389*54925bf6Swillf     LDAPMessage	                *result=NULL, *ent=NULL;
390*54925bf6Swillf     kdb5_dal_handle             *dal_handle=NULL;
391*54925bf6Swillf     krb5_ldap_context           *ldap_context=NULL;
392*54925bf6Swillf     krb5_ldap_server_handle     *ldap_server_handle=NULL;
393*54925bf6Swillf 
394*54925bf6Swillf     /* Clear the global error string */
395*54925bf6Swillf     krb5_clear_error_message(context);
396*54925bf6Swillf 
397*54925bf6Swillf     SETUP_CONTEXT();
398*54925bf6Swillf     GET_HANDLE();
399*54925bf6Swillf 
400*54925bf6Swillf     if (ldap_context->lrparams->realmdn == NULL) {
401*54925bf6Swillf 	st = EINVAL;
402*54925bf6Swillf 	goto cleanup;
403*54925bf6Swillf     }
404*54925bf6Swillf 
405*54925bf6Swillf     LDAP_SEARCH(ldap_context->lrparams->realmdn, LDAP_SCOPE_ONELEVEL, "(objectclass=krbpwdpolicy)", password_policy_attributes);
406*54925bf6Swillf     for (ent=ldap_first_entry(ld, result); ent != NULL; ent=ldap_next_entry(ld, ent)) {
407*54925bf6Swillf 	krb5_boolean attr_present;
408*54925bf6Swillf 
409*54925bf6Swillf 	st = krb5_ldap_get_string(ld, ent, "cn", &policy, &attr_present);
410*54925bf6Swillf 	if (st != 0)
411*54925bf6Swillf 	    goto cleanup;
412*54925bf6Swillf 	if (attr_present == FALSE)
413*54925bf6Swillf 	    continue;
414*54925bf6Swillf 
415*54925bf6Swillf 	entry = (osa_policy_ent_t) malloc(sizeof(osa_policy_ent_rec));
416*54925bf6Swillf 	CHECK_NULL(entry);
417*54925bf6Swillf 	memset(entry, 0, sizeof(osa_policy_ent_rec));
418*54925bf6Swillf 	if ((st = populate_policy(context, ld, ent, policy, entry)) != 0)
419*54925bf6Swillf 	    goto cleanup;
420*54925bf6Swillf #if 0 /************** Begin IFDEF'ed OUT *******************************/
421*54925bf6Swillf 	entry->name = policy;
422*54925bf6Swillf 	entry->version = 1;
423*54925bf6Swillf 
424*54925bf6Swillf 	krb5_ldap_get_value(ld, ent, "krbmaxpwdlife", &(entry->pw_max_life));
425*54925bf6Swillf 	krb5_ldap_get_value(ld, ent, "krbminpwdlife", &(entry->pw_min_life));
426*54925bf6Swillf 	krb5_ldap_get_value(ld, ent, "krbpwdmindiffchars", &(entry->pw_min_classes));
427*54925bf6Swillf 	krb5_ldap_get_value(ld, ent, "krbpwdminlength", &(entry->pw_min_length));
428*54925bf6Swillf 	krb5_ldap_get_value(ld, ent, "krbpwdhistorylength", &(entry->pw_history_num));
429*54925bf6Swillf 
430*54925bf6Swillf 	/* Get the reference count */
431*54925bf6Swillf 	st = krb5_ldap_get_reference_count (context,
432*54925bf6Swillf 					    policy,
433*54925bf6Swillf 					    "krbPwdPolicyReference",
434*54925bf6Swillf 					    &(entry->policy_refcnt),
435*54925bf6Swillf 					    ld);
436*54925bf6Swillf #endif /**************** END IFDEF'ed OUT *******************************/
437*54925bf6Swillf 
438*54925bf6Swillf 	(*func)(func_arg, entry);
439*54925bf6Swillf 	/* XXX this will free policy so don't free it */
440*54925bf6Swillf 	krb5_ldap_free_password_policy(context, entry);
441*54925bf6Swillf 	entry = NULL;
442*54925bf6Swillf     }
443*54925bf6Swillf     ldap_msgfree(result);
444*54925bf6Swillf 
445*54925bf6Swillf cleanup:
446*54925bf6Swillf     if (entry)
447*54925bf6Swillf 	free (entry);
448*54925bf6Swillf 
449*54925bf6Swillf     krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
450*54925bf6Swillf     return st;
451*54925bf6Swillf }
452*54925bf6Swillf 
453*54925bf6Swillf void
454*54925bf6Swillf krb5_ldap_free_password_policy (context, entry)
455*54925bf6Swillf     krb5_context                context;
456*54925bf6Swillf     osa_policy_ent_t            entry;
457*54925bf6Swillf {
458*54925bf6Swillf     if (entry) {
459*54925bf6Swillf 	if (entry->name)
460*54925bf6Swillf 	    free(entry->name);
461*54925bf6Swillf 	free(entry);
462*54925bf6Swillf     }
463*54925bf6Swillf     return;
464*54925bf6Swillf }
465