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