1 #pragma ident	"%Z%%M%	%I%	%E% SMI"
2 
3 /*
4  * kadmin/ldap_util/kdb5_ldap_policy.c
5  */
6 
7 /* Copyright (c) 2004-2005, Novell, Inc.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are met:
12  *
13  *   * Redistributions of source code must retain the above copyright notice,
14  *       this list of conditions and the following disclaimer.
15  *   * Redistributions in binary form must reproduce the above copyright
16  *       notice, this list of conditions and the following disclaimer in the
17  *       documentation and/or other materials provided with the distribution.
18  *   * The copyright holder's name is not used to endorse or promote products
19  *       derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /*
35  * Create / Delete / Modify / View / List policy objects.
36  */
37 
38 #include <stdio.h>
39 #include <time.h>
40 #include <k5-int.h>
41 #include <kadm5/admin.h>
42 #include <libintl.h>
43 #include <locale.h>
44 #include "kdb5_ldap_util.h"
45 #include "kdb5_ldap_list.h"
46 #include "ldap_tkt_policy.h"
47 extern time_t get_date(char *); /* kadmin/cli/getdate.o */
48 
49 static void print_policy_params(krb5_ldap_policy_params *policyparams, int mask);
50 static char *strdur(time_t duration);
51 
52 extern char *yes;
53 extern kadm5_config_params global_params;
54 
55 static krb5_error_code init_ldap_realm (int argc, char *argv[]) {
56     /* This operation is being performed in the context of a realm. So,
57      * initialize the realm */
58     int mask = 0;
59     krb5_error_code retval = 0;
60     kdb5_dal_handle *dal_handle = NULL;
61     krb5_ldap_context *ldap_context=NULL;
62 
63     dal_handle = (kdb5_dal_handle *) util_context->db_context;
64     ldap_context = (krb5_ldap_context *) dal_handle->db_context;
65     if (!ldap_context) {
66         retval = EINVAL;
67         goto cleanup;
68     }
69 
70     if (ldap_context->krbcontainer == NULL) {
71         retval = krb5_ldap_read_krbcontainer_params (util_context,
72                 &(ldap_context->krbcontainer));
73         if (retval != 0) {
74             com_err(argv[0], retval, gettext("while reading kerberos container information"));
75             goto cleanup;
76         }
77     }
78 
79     if (ldap_context->lrparams == NULL) {
80         retval = krb5_ldap_read_realm_params(util_context,
81                 global_params.realm,
82                 &(ldap_context->lrparams),
83                 &mask);
84 
85         if (retval != 0) {
86             goto cleanup;
87         }
88     }
89 cleanup:
90     return retval;
91 }
92 
93 /*
94  * This function will create a ticket policy object with the
95  * specified attributes.
96  */
97 void
98 kdb5_ldap_create_policy(argc, argv)
99     int argc;
100     char *argv[];
101 {
102     char *me = argv[0];
103     krb5_error_code retval = 0;
104     krb5_ldap_policy_params *policyparams = NULL;
105     krb5_boolean print_usage = FALSE;
106     krb5_boolean no_msg = FALSE;
107     int mask = 0;
108     time_t date = 0;
109     time_t now = 0;
110     int i = 0;
111 
112     /* Check for number of arguments */
113     if ((argc < 2) || (argc > 16)) {
114 	goto err_usage;
115     }
116 
117     /* Allocate memory for policy parameters structure */
118     policyparams = (krb5_ldap_policy_params*) calloc(1, sizeof(krb5_ldap_policy_params));
119     if (policyparams == NULL) {
120 	retval = ENOMEM;
121 	goto cleanup;
122     }
123 
124     /* Get current time */
125     time (&now);
126 
127     /* Parse all arguments */
128     for (i = 1; i < argc; i++) {
129 	if (!strcmp(argv[i], "-maxtktlife")) {
130 	    if (++i > argc - 1)
131 		goto err_usage;
132 
133 	    date = get_date(argv[i]);
134 	    if (date == (time_t)(-1)) {
135 		retval = EINVAL;
136 		com_err (me, retval, gettext("while providing time specification"));
137 		goto err_nomsg;
138 	    }
139 
140 	    policyparams->maxtktlife = date - now;
141 
142 	    mask |= LDAP_POLICY_MAXTKTLIFE;
143 	} else if (!strcmp(argv[i], "-maxrenewlife")) {
144 	    if (++i > argc - 1)
145 		goto err_usage;
146 
147 	    date = get_date(argv[i]);
148 	    if (date == (time_t)(-1)) {
149 		retval = EINVAL;
150 		com_err (me, retval, gettext("while providing time specification"));
151 		goto err_nomsg;
152 	    }
153 
154 	    policyparams->maxrenewlife = date - now;
155 
156 	    mask |= LDAP_POLICY_MAXRENEWLIFE;
157 	} else if (!strcmp((argv[i] + 1), "allow_postdated")) {
158 	    if (*(argv[i]) == '+')
159 		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_POSTDATED);
160 	    else if (*(argv[i]) == '-')
161 		policyparams->tktflags |= KRB5_KDB_DISALLOW_POSTDATED;
162 	    else
163 		goto err_usage;
164 
165 	    mask |= LDAP_POLICY_TKTFLAGS;
166 	} else if (!strcmp((argv[i] + 1), "allow_forwardable")) {
167 	    if (*(argv[i]) == '+')
168 		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_FORWARDABLE);
169 	    else if (*(argv[i]) == '-')
170 		policyparams->tktflags |= KRB5_KDB_DISALLOW_FORWARDABLE;
171 	    else
172 		goto err_usage;
173 
174 	    mask |= LDAP_POLICY_TKTFLAGS;
175 	} else if (!strcmp((argv[i] + 1), "allow_renewable")) {
176 	    if (*(argv[i]) == '+')
177 		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_RENEWABLE);
178 	    else if (*(argv[i]) == '-')
179 		policyparams->tktflags |= KRB5_KDB_DISALLOW_RENEWABLE;
180 	    else
181 		goto err_usage;
182 
183 	    mask |= LDAP_POLICY_TKTFLAGS;
184 	} else if (!strcmp((argv[i] + 1), "allow_proxiable")) {
185 	    if (*(argv[i]) == '+')
186 		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_PROXIABLE);
187 	    else if (*(argv[i]) == '-')
188 		policyparams->tktflags |= KRB5_KDB_DISALLOW_PROXIABLE;
189 	    else
190 		goto err_usage;
191 
192 	    mask |= LDAP_POLICY_TKTFLAGS;
193 	} else if (!strcmp((argv[i] + 1), "allow_dup_skey")) {
194 	    if (*(argv[i]) == '+')
195 		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_DUP_SKEY);
196 	    else if (*(argv[i]) == '-')
197 		policyparams->tktflags |= KRB5_KDB_DISALLOW_DUP_SKEY;
198 	    else
199 		goto err_usage;
200 
201 	    mask |= LDAP_POLICY_TKTFLAGS;
202 	} else if (!strcmp((argv[i] + 1), "requires_preauth")) {
203 	    if (*(argv[i]) == '+')
204 		policyparams->tktflags |= KRB5_KDB_REQUIRES_PRE_AUTH;
205 	    else if (*(argv[i]) == '-')
206 		policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PRE_AUTH);
207 	    else
208 		goto err_usage;
209 
210 	    mask |= LDAP_POLICY_TKTFLAGS;
211 	} else if (!strcmp((argv[i] + 1), "requires_hwauth")) {
212 	    if (*(argv[i]) == '+')
213 		policyparams->tktflags |= KRB5_KDB_REQUIRES_HW_AUTH;
214 	    else if (*(argv[i]) == '-')
215 		policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_HW_AUTH);
216 	    else
217 		goto err_usage;
218 
219 	    mask |= LDAP_POLICY_TKTFLAGS;
220 	} else if (!strcmp((argv[i] + 1), "allow_svr")) {
221 	    if (*(argv[i]) == '+')
222 		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_SVR);
223 	    else if (*(argv[i]) == '-')
224 		policyparams->tktflags |= KRB5_KDB_DISALLOW_SVR;
225 	    else
226 		goto err_usage;
227 
228 	    mask |= LDAP_POLICY_TKTFLAGS;
229 	} else if (!strcmp((argv[i] + 1), "allow_tgs_req")) {
230 	    if (*(argv[i]) == '+')
231 		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_TGT_BASED);
232 	    else if (*(argv[i]) == '-')
233 		policyparams->tktflags |= KRB5_KDB_DISALLOW_TGT_BASED;
234 	    else
235 		goto err_usage;
236 
237 	    mask |= LDAP_POLICY_TKTFLAGS;
238 	} else if (!strcmp((argv[i] + 1), "allow_tix")) {
239 	    if (*(argv[i]) == '+')
240 		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_ALL_TIX);
241 	    else if (*(argv[i]) == '-')
242 		policyparams->tktflags |= KRB5_KDB_DISALLOW_ALL_TIX;
243 	    else
244 		goto err_usage;
245 
246 	    mask |= LDAP_POLICY_TKTFLAGS;
247 	} else if (!strcmp((argv[i] + 1), "needchange")) {
248 	    if (*(argv[i]) == '+')
249 		policyparams->tktflags |= KRB5_KDB_REQUIRES_PWCHANGE;
250 	    else if (*(argv[i]) == '-')
251 		policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PWCHANGE);
252 	    else
253 		goto err_usage;
254 
255 	    mask |= LDAP_POLICY_TKTFLAGS;
256 	} else if (!strcmp((argv[i] + 1), "password_changing_service")) {
257 	    if (*(argv[i]) == '+')
258 		policyparams->tktflags |= KRB5_KDB_PWCHANGE_SERVICE;
259 	    else if (*(argv[i]) == '-')
260 		policyparams->tktflags &= (int)(~KRB5_KDB_PWCHANGE_SERVICE);
261 	    else
262 		goto err_usage;
263 
264 	    mask |= LDAP_POLICY_TKTFLAGS;
265 	} else { /* Any other argument must be policy DN */
266 	    /* First check if policy DN is already provided --
267 	       if so, there's a usage error */
268             if (policyparams->policy != NULL)
269 		goto err_usage;
270 
271 	    /* If not present already, fill up policy DN */
272             policyparams->policy = strdup(argv[i]);
273             if (policyparams->policy == NULL) {
274 		retval = ENOMEM;
275 		com_err(me, retval, gettext("while creating policy object"));
276 		goto err_nomsg;
277 	    }
278 	}
279     }
280 
281     /* policy DN is a mandatory argument. If not provided, print usage */
282     if (policyparams->policy == NULL)
283 	goto err_usage;
284 
285     if ((retval = init_ldap_realm (argc, argv))) {
286         com_err(me, retval, gettext("while reading realm information"));
287         goto err_nomsg;
288     }
289 
290     /* Create object with all attributes provided */
291     if ((retval = krb5_ldap_create_policy(util_context, policyparams, mask)) != 0)
292 	goto cleanup;
293 
294     goto cleanup;
295 
296 err_usage:
297     print_usage = TRUE;
298 
299 err_nomsg:
300     no_msg = TRUE;
301 
302 cleanup:
303     /* Clean-up structure */
304     krb5_ldap_free_policy (util_context, policyparams);
305 
306     if (print_usage)
307 	db_usage(CREATE_POLICY);
308 
309     if (retval) {
310 	if (!no_msg)
311 	    com_err(me, retval, gettext("while creating policy object"));
312 
313 	exit_status++;
314     }
315 
316     return;
317 }
318 
319 
320 /*
321  * This function will destroy the specified ticket policy
322  * object interactively, unless forced through an option.
323  */
324 void
325 kdb5_ldap_destroy_policy(argc, argv)
326     int argc;
327     char *argv[];
328 {
329     char *me = argv[0];
330     krb5_error_code retval = 0;
331     krb5_ldap_policy_params *policyparams = NULL;
332     krb5_boolean print_usage = FALSE;
333     krb5_boolean no_msg = FALSE;
334     char *policy = NULL;
335     unsigned int mask = 0;
336     int force = 0;
337     char buf[5] = {0};
338     int i = 0;
339 
340     if ((argc < 2) || (argc > 3)) {
341 	goto err_usage;
342     }
343 
344     for (i = 1; i < argc; i++) {
345 	if (strcmp(argv[i], "-force") == 0) {
346 	    force++;
347 	} else { /* Any other argument must be policy DN */
348 	    /* First check if policy DN is already provided --
349 	       if so, there's a usage error */
350             if (policy != NULL)
351 		goto err_usage;
352 
353 	    /* If not present already, fill up policy DN */
354             policy = strdup(argv[i]);
355             if (policy == NULL) {
356 		retval = ENOMEM;
357 		com_err(me, retval, gettext("while destroying policy object"));
358 		goto err_nomsg;
359 	    }
360 	}
361     }
362 
363     if (policy == NULL)
364 	goto err_usage;
365 
366     if (!force) {
367         printf(gettext("This will delete the policy object '%s', are you sure?\n"), policy);
368 	printf(gettext("(type 'yes' to confirm)? "));
369 
370 	if (fgets(buf, sizeof(buf), stdin) == NULL) {
371 	    retval = EINVAL;
372 	    goto cleanup;
373 	}
374 
375 	if (strcmp(buf, yes)) {
376 	    exit_status++;
377 	    goto cleanup;
378 	}
379     }
380 
381     if ((retval = init_ldap_realm (argc, argv)))
382         goto err_nomsg;
383 
384     if ((retval = krb5_ldap_read_policy(util_context, policy, &policyparams, &mask)))
385 	goto cleanup;
386 
387 
388     if ((retval = krb5_ldap_delete_policy(util_context, policy)))
389 	goto cleanup;
390 
391     printf(gettext("** policy object '%s' deleted.\n"), policy);
392     goto cleanup;
393 
394 
395 err_usage:
396     print_usage = TRUE;
397 
398 err_nomsg:
399     no_msg = TRUE;
400 
401 cleanup:
402     /* Clean-up structure */
403     krb5_ldap_free_policy (util_context, policyparams);
404 
405     if (policy) {
406 	free (policy);
407     }
408 
409     if (print_usage) {
410 	db_usage(DESTROY_POLICY);
411     }
412 
413     if (retval) {
414 	if (!no_msg)
415 	    com_err(me, retval, gettext("while destroying policy object"));
416 
417 	exit_status++;
418     }
419 
420     return;
421 }
422 
423 
424 /*
425  * This function will modify the attributes of a given ticket
426  * policy object.
427  */
428 void
429 kdb5_ldap_modify_policy(argc, argv)
430     int argc;
431     char *argv[];
432 {
433     char *me = argv[0];
434     krb5_error_code retval = 0;
435     krb5_ldap_policy_params *policyparams = NULL;
436     krb5_boolean print_usage = FALSE;
437     krb5_boolean no_msg = FALSE;
438     char *policy = NULL;
439     unsigned int in_mask = 0, out_mask = 0;
440     time_t date = 0;
441     time_t now = 0;
442     int i = 0;
443 
444     /* Check for number of arguments -- minimum is 3
445        since atleast one parameter should be given in
446        addition to 'modify_policy' and policy DN */
447     if ((argc < 3) || (argc > 16)) {
448 	goto err_usage;
449     }
450 
451     /* Parse all arguments, only to pick up policy DN (Pass 1) */
452     for (i = 1; i < argc; i++) {
453 	/* Skip arguments next to 'maxtktlife'
454 	   and 'maxrenewlife' arguments */
455 	if (!strcmp(argv[i], "-maxtktlife")) {
456 	    ++i;
457 	} else if (!strcmp(argv[i], "-maxrenewlife")) {
458 	    ++i;
459 	}
460 	/* Do nothing for ticket flag arguments */
461 	else if (!strcmp((argv[i] + 1), "allow_postdated") ||
462 		 !strcmp((argv[i] + 1), "allow_forwardable") ||
463 		 !strcmp((argv[i] + 1), "allow_renewable") ||
464 		 !strcmp((argv[i] + 1), "allow_proxiable") ||
465 		 !strcmp((argv[i] + 1), "allow_dup_skey") ||
466 		 !strcmp((argv[i] + 1), "requires_preauth") ||
467 		 !strcmp((argv[i] + 1), "requires_hwauth") ||
468 		 !strcmp((argv[i] + 1), "allow_svr") ||
469 		 !strcmp((argv[i] + 1), "allow_tgs_req") ||
470 		 !strcmp((argv[i] + 1), "allow_tix") ||
471 		 !strcmp((argv[i] + 1), "needchange") ||
472 		 !strcmp((argv[i] + 1), "password_changing_service")) {
473 	} else { /* Any other argument must be policy DN */
474 	    /* First check if policy DN is already provided --
475 	       if so, there's a usage error */
476             if (policy != NULL)
477 		goto err_usage;
478 
479 	    /* If not present already, fill up policy DN */
480             policy = strdup(argv[i]);
481             if (policy == NULL) {
482 		retval = ENOMEM;
483 		com_err(me, retval, gettext("while modifying policy object"));
484 		goto err_nomsg;
485 	    }
486 	}
487     }
488 
489     if (policy == NULL)
490 	goto err_usage;
491 
492     if ((retval = init_ldap_realm (argc, argv)))
493 	goto cleanup;
494 
495     retval = krb5_ldap_read_policy(util_context, policy, &policyparams, &in_mask);
496     if (retval) {
497         com_err(me, retval, gettext("while reading information of policy '%s'"), policy);
498 	goto err_nomsg;
499     }
500 
501     /* Get current time */
502     time (&now);
503 
504     /* Parse all arguments, but skip policy DN (Pass 2) */
505     for (i = 1; i < argc; i++) {
506 	if (!strcmp(argv[i], "-maxtktlife")) {
507 	    if (++i > argc - 1)
508 		goto err_usage;
509 
510 	    date = get_date(argv[i]);
511 	    if (date == (time_t)(-1)) {
512 		retval = EINVAL;
513 		com_err (me, retval, gettext("while providing time specification"));
514 		goto err_nomsg;
515 	    }
516 
517 	    policyparams->maxtktlife = date - now;
518 
519 	    out_mask |= LDAP_POLICY_MAXTKTLIFE;
520 	} else if (!strcmp(argv[i], "-maxrenewlife")) {
521 	    if (++i > argc - 1)
522 		goto err_usage;
523 
524 	    date = get_date(argv[i]);
525 	    if (date == (time_t)(-1)) {
526 		retval = EINVAL;
527 		com_err (me, retval, gettext("while providing time specification"));
528 		goto err_nomsg;
529 	    }
530 
531 	    policyparams->maxrenewlife = date - now;
532 
533 	    out_mask |= LDAP_POLICY_MAXRENEWLIFE;
534 	} else if (!strcmp((argv[i] + 1), "allow_postdated")) {
535 	    if (*(argv[i]) == '+')
536 		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_POSTDATED);
537 	    else if (*(argv[i]) == '-')
538 		policyparams->tktflags |= KRB5_KDB_DISALLOW_POSTDATED;
539 	    else
540 		goto err_usage;
541 
542 	    out_mask |= LDAP_POLICY_TKTFLAGS;
543 	} else if (!strcmp((argv[i] + 1), "allow_forwardable")) {
544 	    if (*(argv[i]) == '+')
545 		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_FORWARDABLE);
546 	    else if (*(argv[i]) == '-')
547 		policyparams->tktflags |= KRB5_KDB_DISALLOW_FORWARDABLE;
548 	    else
549 		goto err_usage;
550 
551 	    out_mask |= LDAP_POLICY_TKTFLAGS;
552 	} else if (!strcmp((argv[i] + 1), "allow_renewable")) {
553 	    if (*(argv[i]) == '+')
554 		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_RENEWABLE);
555 	    else if (*(argv[i]) == '-')
556 		policyparams->tktflags |= KRB5_KDB_DISALLOW_RENEWABLE;
557 	    else
558 		goto err_usage;
559 
560 	    out_mask |= LDAP_POLICY_TKTFLAGS;
561 	} else if (!strcmp((argv[i] + 1), "allow_proxiable")) {
562 	    if (*(argv[i]) == '+')
563 		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_PROXIABLE);
564 	    else if (*(argv[i]) == '-')
565 		policyparams->tktflags |= KRB5_KDB_DISALLOW_PROXIABLE;
566 	    else
567 		goto err_usage;
568 
569 	    out_mask |= LDAP_POLICY_TKTFLAGS;
570 	} else if (!strcmp((argv[i] + 1), "allow_dup_skey")) {
571 	    if (*(argv[i]) == '+')
572 		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_DUP_SKEY);
573 	    else if (*(argv[i]) == '-')
574 		policyparams->tktflags |= KRB5_KDB_DISALLOW_DUP_SKEY;
575 	    else
576 		goto err_usage;
577 
578 	    out_mask |= LDAP_POLICY_TKTFLAGS;
579 	} else if (!strcmp((argv[i] + 1), "requires_preauth")) {
580 	    if (*(argv[i]) == '+')
581 		policyparams->tktflags |= KRB5_KDB_REQUIRES_PRE_AUTH;
582 	    else if (*(argv[i]) == '-')
583 		policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PRE_AUTH);
584 	    else
585 		goto err_usage;
586 
587 	    out_mask |= LDAP_POLICY_TKTFLAGS;
588 	} else if (!strcmp((argv[i] + 1), "requires_hwauth")) {
589 	    if (*(argv[i]) == '+')
590 		policyparams->tktflags |= KRB5_KDB_REQUIRES_HW_AUTH;
591 	    else if (*(argv[i]) == '-')
592 		policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_HW_AUTH);
593 	    else
594 		goto err_usage;
595 
596 	    out_mask |= LDAP_POLICY_TKTFLAGS;
597 	} else if (!strcmp((argv[i] + 1), "allow_svr")) {
598 	    if (*(argv[i]) == '+')
599 		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_SVR);
600 	    else if (*(argv[i]) == '-')
601 		policyparams->tktflags |= KRB5_KDB_DISALLOW_SVR;
602 	    else
603 		goto err_usage;
604 
605 	    out_mask |= LDAP_POLICY_TKTFLAGS;
606 	} else if (!strcmp((argv[i] + 1), "allow_tgs_req")) {
607 	    if (*(argv[i]) == '+')
608 		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_TGT_BASED);
609 	    else if (*(argv[i]) == '-')
610 		policyparams->tktflags |= KRB5_KDB_DISALLOW_TGT_BASED;
611 	    else
612 		goto err_usage;
613 
614 	    out_mask |= LDAP_POLICY_TKTFLAGS;
615 	} else if (!strcmp((argv[i] + 1), "allow_tix")) {
616 	    if (*(argv[i]) == '+')
617 		policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_ALL_TIX);
618 	    else if (*(argv[i]) == '-')
619 		policyparams->tktflags |= KRB5_KDB_DISALLOW_ALL_TIX;
620 	    else
621 		goto err_usage;
622 
623 	    out_mask |= LDAP_POLICY_TKTFLAGS;
624 	} else if (!strcmp((argv[i] + 1), "needchange")) {
625 	    if (*(argv[i]) == '+')
626 		policyparams->tktflags |= KRB5_KDB_REQUIRES_PWCHANGE;
627 	    else if (*(argv[i]) == '-')
628 		policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PWCHANGE);
629 	    else
630 		goto err_usage;
631 
632 	    out_mask |= LDAP_POLICY_TKTFLAGS;
633 	} else if (!strcmp((argv[i] + 1), "password_changing_service")) {
634 	    if (*(argv[i]) == '+')
635 		policyparams->tktflags |= KRB5_KDB_PWCHANGE_SERVICE;
636 	    else if (*(argv[i]) == '-')
637 		policyparams->tktflags &= (int)(~KRB5_KDB_PWCHANGE_SERVICE);
638 	    else
639 		goto err_usage;
640 
641 	    out_mask |= LDAP_POLICY_TKTFLAGS;
642 	} else {
643 	    /* Any other argument must be policy DN
644 	       -- skip it */
645 	}
646     }
647 
648     /* Modify attributes of object */
649     if ((retval = krb5_ldap_modify_policy(util_context, policyparams, out_mask)))
650 	goto cleanup;
651 
652     goto cleanup;
653 
654 err_usage:
655     print_usage = TRUE;
656 
657 err_nomsg:
658     no_msg = TRUE;
659 
660 cleanup:
661     /* Clean-up structure */
662     krb5_ldap_free_policy (util_context, policyparams);
663 
664     if (policy)
665         free (policy);
666 
667     if (print_usage)
668 	db_usage(MODIFY_POLICY);
669 
670     if (retval) {
671 	if (!no_msg)
672 	    com_err(me, retval, gettext("while modifying policy object"));
673 
674 	exit_status++;
675     }
676 
677     return;
678 }
679 
680 
681 /*
682  * This function will display information about the given policy object,
683  * fetching the information from the LDAP Server.
684  */
685 void
686 kdb5_ldap_view_policy(argc, argv)
687     int argc;
688     char *argv[];
689 {
690     char *me = argv[0];
691     krb5_ldap_policy_params *policyparams = NULL;
692     krb5_error_code retval = 0;
693     krb5_boolean print_usage = FALSE;
694     char *policy = NULL;
695     unsigned int mask = 0;
696 
697     if (argc != 2) {
698 	goto err_usage;
699     }
700 
701     policy = strdup(argv[1]);
702     if (policy == NULL) {
703 	com_err(me, ENOMEM, gettext("while viewing policy"));
704 	exit_status++;
705 	goto cleanup;
706     }
707 
708     if ((retval = init_ldap_realm (argc, argv)))
709         goto cleanup;
710 
711     if ((retval = krb5_ldap_read_policy(util_context, policy, &policyparams, &mask))) {
712 	com_err(me, retval, gettext("while viewing policy '%s'"), policy);
713 	exit_status++;
714 	goto cleanup;
715     }
716 
717     print_policy_params (policyparams, mask);
718 
719     goto cleanup;
720 
721 err_usage:
722     print_usage = TRUE;
723 
724 cleanup:
725     krb5_ldap_free_policy (util_context, policyparams);
726 
727     if (policy)
728 	free (policy);
729 
730     if (print_usage) {
731 	db_usage(VIEW_POLICY);
732     }
733 
734     return;
735 }
736 
737 
738 /*
739  * This function will print the policy object information to the
740  * standard output.
741  */
742 static void
743 print_policy_params(policyparams, mask)
744     krb5_ldap_policy_params *policyparams;
745     int mask;
746 {
747     /* Print the policy DN */
748     printf("%25s: %s\n", gettext("Ticket policy"), policyparams->policy);
749 
750     /* Print max. ticket life and max. renewable life, if present */
751     if (mask & LDAP_POLICY_MAXTKTLIFE)
752 	printf("%25s: %s\n", gettext("Maximum ticket life"), strdur(policyparams->maxtktlife));
753     if (mask & LDAP_POLICY_MAXRENEWLIFE)
754 	printf("%25s: %s\n", gettext("Maximum renewable life"), strdur(policyparams->maxrenewlife));
755 
756     /* Service flags are printed */
757     printf("%25s: ", gettext("Ticket flags"));
758     if (mask & LDAP_POLICY_TKTFLAGS) {
759 	int ticketflags = policyparams->tktflags;
760 
761 	if (ticketflags & KRB5_KDB_DISALLOW_POSTDATED)
762 	    printf("%s ","DISALLOW_POSTDATED");
763 
764 	if (ticketflags & KRB5_KDB_DISALLOW_FORWARDABLE)
765 	    printf("%s ","DISALLOW_FORWARDABLE");
766 
767 	if (ticketflags & KRB5_KDB_DISALLOW_RENEWABLE)
768 	    printf("%s ","DISALLOW_RENEWABLE");
769 
770 	if (ticketflags & KRB5_KDB_DISALLOW_PROXIABLE)
771 	    printf("%s ","DISALLOW_PROXIABLE");
772 
773 	if (ticketflags & KRB5_KDB_DISALLOW_DUP_SKEY)
774 	    printf("%s ","DISALLOW_DUP_SKEY");
775 
776 	if (ticketflags & KRB5_KDB_REQUIRES_PRE_AUTH)
777 	    printf("%s ","REQUIRES_PRE_AUTH");
778 
779 	if (ticketflags & KRB5_KDB_REQUIRES_HW_AUTH)
780 	    printf("%s ","REQUIRES_HW_AUTH");
781 
782 	if (ticketflags & KRB5_KDB_DISALLOW_SVR)
783 	    printf("%s ","DISALLOW_SVR");
784 
785 	if (ticketflags & KRB5_KDB_DISALLOW_TGT_BASED)
786 	    printf("%s ","DISALLOW_TGT_BASED");
787 
788 	if (ticketflags & KRB5_KDB_DISALLOW_ALL_TIX)
789 	    printf("%s ","DISALLOW_ALL_TIX");
790 
791 	if (ticketflags & KRB5_KDB_REQUIRES_PWCHANGE)
792 	    printf("%s ","REQUIRES_PWCHANGE");
793 
794 	if (ticketflags & KRB5_KDB_PWCHANGE_SERVICE)
795 	    printf("%s ","PWCHANGE_SERVICE");
796     }
797     printf("\n");
798 
799     return;
800 }
801 
802 
803 /*
804  * This function will list the DNs of policy objects under a specific
805  * sub-tree (entire tree by default)
806  */
807 void kdb5_ldap_list_policies(argc, argv)
808     int argc;
809     char *argv[];
810 {
811     char *me = argv[0];
812     krb5_error_code retval = 0;
813     krb5_boolean print_usage = FALSE;
814     char *basedn = NULL;
815     char **list = NULL;
816     char **plist = NULL;
817 
818     /* Check for number of arguments */
819     if ((argc != 1) && (argc != 3)) {
820 	goto err_usage;
821     }
822 
823     if ((retval = init_ldap_realm (argc, argv)))
824 	goto cleanup;
825 
826     retval = krb5_ldap_list_policy(util_context, basedn, &list);
827     if ((retval != 0) || (list == NULL))
828 	goto cleanup;
829 
830     for (plist = list; *plist != NULL; plist++) {
831 	printf("%s\n", *plist);
832     }
833 
834     goto cleanup;
835 
836 err_usage:
837     print_usage = TRUE;
838 
839 cleanup:
840     if (list != NULL) {
841 	krb5_free_list_entries (list);
842 	free (list);
843     }
844 
845     if (basedn)
846 	free (basedn);
847 
848     if (print_usage) {
849 	db_usage(LIST_POLICY);
850     }
851 
852     if (retval) {
853 	com_err(me, retval, gettext("while listing policy objects"));
854 	exit_status++;
855     }
856 
857     return;
858 }
859 
860 
861 /* Reproduced from kadmin.c, instead of linking
862    the entire kadmin.o */
863 static char *strdur(duration)
864     time_t duration;
865 {
866     static char out[50];
867     int neg, days, hours, minutes, seconds;
868 
869     if (duration < 0) {
870 	duration *= -1;
871 	neg = 1;
872     } else
873 	neg = 0;
874     days = duration / (24 * 3600);
875     duration %= 24 * 3600;
876     hours = duration / 3600;
877     duration %= 3600;
878     minutes = duration / 60;
879     duration %= 60;
880     seconds = duration;
881     snprintf(out, sizeof(out), "%s%d %s %02d:%02d:%02d", neg ? "-" : "",
882 	    days, days == 1 ? gettext("day") : gettext("days"),
883 	    hours, minutes, seconds);
884     return out;
885 }
886