xref: /illumos-gate/usr/src/cmd/krb5/ldap_util/kdb5_ldap_policy.c (revision 4fe85d41bb4eb0db41934722f4b06c8acec2d25a)
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