xref: /titanic_51/usr/src/cmd/krb5/kadmin/cli/keytab.c (revision 159d09a20817016f09b3ea28d1bdada4a336bb91)
17c478bd9Sstevel@tonic-gate /*
27c64d375Smp153739  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate 
77c478bd9Sstevel@tonic-gate /*
87c478bd9Sstevel@tonic-gate  * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
97c478bd9Sstevel@tonic-gate  *
1056a424ccSmp153739  * $Id: keytab.c,v 1.28 2004/05/31 12:39:16 epeisach Exp $
117c478bd9Sstevel@tonic-gate  * $Source: /cvs/krbdev/krb5/src/kadmin/cli/keytab.c,v $
127c478bd9Sstevel@tonic-gate  */
137c478bd9Sstevel@tonic-gate 
147c478bd9Sstevel@tonic-gate /*
157c478bd9Sstevel@tonic-gate  * Copyright (C) 1998 by the FundsXpress, INC.
167c478bd9Sstevel@tonic-gate  *
177c478bd9Sstevel@tonic-gate  * All rights reserved.
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may require
207c478bd9Sstevel@tonic-gate  * a specific license from the United States Government.  It is the
217c478bd9Sstevel@tonic-gate  * responsibility of any person or organization contemplating export to
227c478bd9Sstevel@tonic-gate  * obtain such a license before exporting.
237c478bd9Sstevel@tonic-gate  *
247c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
257c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
267c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
277c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
287c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
297c478bd9Sstevel@tonic-gate  * the name of FundsXpress. not be used in advertising or publicity pertaining
307c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
317c478bd9Sstevel@tonic-gate  * permission.  FundsXpress makes no representations about the suitability of
327c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
337c478bd9Sstevel@tonic-gate  * or implied warranty.
347c478bd9Sstevel@tonic-gate  *
357c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
367c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
377c478bd9Sstevel@tonic-gate  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
387c478bd9Sstevel@tonic-gate  */
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate #if !defined(lint) && !defined(__CODECENTER__)
4156a424ccSmp153739 static char *rcsid = "$Header: /cvs/krbdev/krb5/src/kadmin/cli/keytab.c,v 1.28 2004/05/31 12:39:16 epeisach Exp $";
427c478bd9Sstevel@tonic-gate #endif
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate #include <stdio.h>
457c478bd9Sstevel@tonic-gate #include <stdlib.h>
467c478bd9Sstevel@tonic-gate #include <string.h>
477c478bd9Sstevel@tonic-gate #include <libintl.h>
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate #include <kadm5/admin.h>
5056a424ccSmp153739 #include <krb5/adm_proto.h>
5156a424ccSmp153739 #include "kadmin.h"
52*159d09a2SMark Phalan #include <krb5.h>
537c478bd9Sstevel@tonic-gate 
5456a424ccSmp153739 static int add_principal(void *lhandle, char *keytab_str, krb5_keytab keytab,
5556a424ccSmp153739 			 krb5_boolean keepold,
567c478bd9Sstevel@tonic-gate 			 int n_ks_tuple, krb5_key_salt_tuple *ks_tuple,
577c478bd9Sstevel@tonic-gate 			 char *princ_str);
587c478bd9Sstevel@tonic-gate static int remove_principal(char *keytab_str, krb5_keytab keytab, char
597c478bd9Sstevel@tonic-gate 			    *princ_str, char *kvno_str);
607c478bd9Sstevel@tonic-gate static char *etype_string(krb5_enctype enctype);
617c64d375Smp153739 static char *etype_istring(krb5_enctype enctype);
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate static int quiet;
647c478bd9Sstevel@tonic-gate 
6556a424ccSmp153739 static void add_usage()
667c478bd9Sstevel@tonic-gate {
677c478bd9Sstevel@tonic-gate      fprintf(stderr, "%s: %s\n", gettext("Usage"),
687c478bd9Sstevel@tonic-gate 	"ktadd [-k[eytab] keytab] [-q] [-e keysaltlist] "
697c478bd9Sstevel@tonic-gate 	"[principal | -glob princ-exp] [...]\n");
707c478bd9Sstevel@tonic-gate }
717c478bd9Sstevel@tonic-gate 
7256a424ccSmp153739 static void rem_usage()
737c478bd9Sstevel@tonic-gate {
747c478bd9Sstevel@tonic-gate 	fprintf(stderr, "%s: %s\n",
757c478bd9Sstevel@tonic-gate 	    gettext("Usage"),
767c478bd9Sstevel@tonic-gate 	    "ktremove [-k[eytab] keytab] [-q] principal "
777c478bd9Sstevel@tonic-gate 	    "[kvno|\"all\"|\"old\"]\n");
787c478bd9Sstevel@tonic-gate }
797c478bd9Sstevel@tonic-gate 
8056a424ccSmp153739 static int process_keytab(krb5_context my_context, char **keytab_str,
817c478bd9Sstevel@tonic-gate 		   krb5_keytab *keytab)
827c478bd9Sstevel@tonic-gate {
837c478bd9Sstevel@tonic-gate      int code;
847c478bd9Sstevel@tonic-gate      char buf[BUFSIZ];
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate      if (*keytab_str == NULL) {
8756a424ccSmp153739 	if (code = krb5_kt_default(my_context, keytab)) {
887c478bd9Sstevel@tonic-gate 		com_err(whoami, code, gettext("while opening default keytab"));
8956a424ccSmp153739 		return 1;
907c478bd9Sstevel@tonic-gate 	}
9156a424ccSmp153739 	if (code = krb5_kt_get_name(my_context, *keytab, buf, BUFSIZ)) {
927c478bd9Sstevel@tonic-gate 		com_err(whoami, code, gettext("while retrieving keytab name"));
9356a424ccSmp153739 		return 1;
947c478bd9Sstevel@tonic-gate 	}
957c478bd9Sstevel@tonic-gate 	if (!(*keytab_str = strdup(buf))) {
967c478bd9Sstevel@tonic-gate 		com_err(whoami, ENOMEM, gettext("while creating keytab name"));
9756a424ccSmp153739 		return 1;
987c478bd9Sstevel@tonic-gate 	}
997c478bd9Sstevel@tonic-gate      } else {
1007c478bd9Sstevel@tonic-gate 	  if (strchr(*keytab_str, ':') != NULL) {
1017c478bd9Sstevel@tonic-gate 	       *keytab_str = strdup(*keytab_str);
1027c478bd9Sstevel@tonic-gate 	       if (*keytab_str == NULL) {
1037c478bd9Sstevel@tonic-gate 				com_err(whoami, ENOMEM,
1047c478bd9Sstevel@tonic-gate 				    gettext("while creating keytab name"));
10556a424ccSmp153739 		    return 1;
1067c478bd9Sstevel@tonic-gate 	       }
1077c478bd9Sstevel@tonic-gate 	  } else {
1087c478bd9Sstevel@tonic-gate 	       char *tmp = *keytab_str;
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 	       *keytab_str = (char *)
1117c478bd9Sstevel@tonic-gate 		    malloc(strlen("WRFILE:")+strlen(tmp)+1);
1127c478bd9Sstevel@tonic-gate 	       if (*keytab_str == NULL) {
1137c478bd9Sstevel@tonic-gate 				com_err(whoami, ENOMEM,
1147c478bd9Sstevel@tonic-gate 				    gettext("while creating keytab name"));
11556a424ccSmp153739 		    return 1;
1167c478bd9Sstevel@tonic-gate 	       }
1177c478bd9Sstevel@tonic-gate 	       sprintf(*keytab_str, "WRFILE:%s", tmp);
1187c478bd9Sstevel@tonic-gate 	  }
1197c478bd9Sstevel@tonic-gate 
12056a424ccSmp153739 	  code = krb5_kt_resolve(my_context, *keytab_str, keytab);
1217c478bd9Sstevel@tonic-gate 	  if (code != 0) {
1227c478bd9Sstevel@tonic-gate 			com_err(whoami, code,
1237c478bd9Sstevel@tonic-gate 			    gettext("while resolving keytab %s"), *keytab_str);
1247c478bd9Sstevel@tonic-gate 	       free(keytab_str);
12556a424ccSmp153739 	       return 1;
1267c478bd9Sstevel@tonic-gate 	  }
1277c478bd9Sstevel@tonic-gate      }
1287c478bd9Sstevel@tonic-gate 
12956a424ccSmp153739      return 0;
1307c478bd9Sstevel@tonic-gate }
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 
13356a424ccSmp153739 void kadmin_keytab_add(int argc, char **argv)
1347c478bd9Sstevel@tonic-gate {
1357c478bd9Sstevel@tonic-gate      krb5_keytab keytab = 0;
13656a424ccSmp153739      char *keytab_str = NULL, **princs;
1377c478bd9Sstevel@tonic-gate      int code, num, i;
1387c478bd9Sstevel@tonic-gate      krb5_error_code retval;
13956a424ccSmp153739      int n_ks_tuple = 0;
14056a424ccSmp153739      krb5_boolean keepold = FALSE;
1417c478bd9Sstevel@tonic-gate      krb5_key_salt_tuple *ks_tuple = NULL;
1427c478bd9Sstevel@tonic-gate 
14356a424ccSmp153739      argc--; argv++;
1447c478bd9Sstevel@tonic-gate      quiet = 0;
1457c478bd9Sstevel@tonic-gate      while (argc) {
1467c478bd9Sstevel@tonic-gate 	  if (strncmp(*argv, "-k", 2) == 0) {
14756a424ccSmp153739 	       argc--; argv++;
1487c478bd9Sstevel@tonic-gate 	       if (!argc || keytab_str) {
1497c478bd9Sstevel@tonic-gate 		    add_usage();
1507c478bd9Sstevel@tonic-gate 		    return;
1517c478bd9Sstevel@tonic-gate 	       }
1527c478bd9Sstevel@tonic-gate 	       keytab_str = *argv;
1537c478bd9Sstevel@tonic-gate 	  } else if (strcmp(*argv, "-q") == 0) {
1547c478bd9Sstevel@tonic-gate 	       quiet++;
1557c478bd9Sstevel@tonic-gate 	  } else if (strcmp(*argv, "-e") == 0) {
1567c478bd9Sstevel@tonic-gate 	       argc--;
1577c478bd9Sstevel@tonic-gate 	       if (argc < 1) {
1587c478bd9Sstevel@tonic-gate 		    add_usage();
1597c478bd9Sstevel@tonic-gate 		    return;
1607c478bd9Sstevel@tonic-gate 	       }
1617c478bd9Sstevel@tonic-gate 	       retval = krb5_string_to_keysalts(*++argv, ", \t", ":.-", 0,
1627c478bd9Sstevel@tonic-gate 						&ks_tuple, &n_ks_tuple);
1637c478bd9Sstevel@tonic-gate 	       if (retval) {
1647c478bd9Sstevel@tonic-gate 		    com_err("ktadd", retval,
1657c478bd9Sstevel@tonic-gate 			    gettext("while parsing keysalts %s"),
1667c478bd9Sstevel@tonic-gate 			    *argv);
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 		    return;
1697c478bd9Sstevel@tonic-gate 	       }
1707c478bd9Sstevel@tonic-gate 	  } else
1717c478bd9Sstevel@tonic-gate 	       break;
17256a424ccSmp153739 	  argc--; argv++;
1737c478bd9Sstevel@tonic-gate      }
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate      if (argc == 0) {
1767c478bd9Sstevel@tonic-gate 	  add_usage();
1777c478bd9Sstevel@tonic-gate 	  return;
1787c478bd9Sstevel@tonic-gate      }
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate      if (process_keytab(context, &keytab_str, &keytab))
1817c478bd9Sstevel@tonic-gate 	  return;
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate      while (*argv) {
1847c478bd9Sstevel@tonic-gate 	  if (strcmp(*argv, "-glob") == 0) {
1857c478bd9Sstevel@tonic-gate 	       if (*++argv == NULL) {
1867c478bd9Sstevel@tonic-gate 		    add_usage();
1877c478bd9Sstevel@tonic-gate 		    break;
1887c478bd9Sstevel@tonic-gate 	       }
18956a424ccSmp153739 
19056a424ccSmp153739 	       code = kadm5_get_principals(handle, *argv, &princs, &num);
19156a424ccSmp153739 	       if (code) {
1927c478bd9Sstevel@tonic-gate 				com_err(whoami, code,
1937c478bd9Sstevel@tonic-gate 					gettext("while expanding expression "
1947c478bd9Sstevel@tonic-gate 						"\"%s\"."),
1957c478bd9Sstevel@tonic-gate 			    *argv);
1967c478bd9Sstevel@tonic-gate 		    argv++;
1977c478bd9Sstevel@tonic-gate 		    continue;
1987c478bd9Sstevel@tonic-gate 	       }
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	       for (i = 0; i < num; i++)
2017c478bd9Sstevel@tonic-gate 		    (void) add_principal(handle, keytab_str, keytab,
2027c478bd9Sstevel@tonic-gate 					 keepold, n_ks_tuple, ks_tuple,
2037c478bd9Sstevel@tonic-gate 					 princs[i]);
2047c478bd9Sstevel@tonic-gate 	       kadm5_free_name_list(handle, princs, num);
2057c478bd9Sstevel@tonic-gate 	  } else
2067c478bd9Sstevel@tonic-gate 	       (void) add_principal(handle, keytab_str, keytab,
2077c478bd9Sstevel@tonic-gate 				    keepold, n_ks_tuple, ks_tuple,
2087c478bd9Sstevel@tonic-gate 				    *argv);
2097c478bd9Sstevel@tonic-gate 	  argv++;
2107c478bd9Sstevel@tonic-gate      }
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate      code = krb5_kt_close(context, keytab);
2137c478bd9Sstevel@tonic-gate      if (code != 0)
2147c478bd9Sstevel@tonic-gate 		com_err(whoami, code, gettext("while closing keytab"));
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate      free(keytab_str);
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate 
21956a424ccSmp153739 void kadmin_keytab_remove(int argc, char **argv)
2207c478bd9Sstevel@tonic-gate {
2217c478bd9Sstevel@tonic-gate      krb5_keytab keytab = 0;
22256a424ccSmp153739      char *keytab_str = NULL;
2237c478bd9Sstevel@tonic-gate      int code;
2247c478bd9Sstevel@tonic-gate 
22556a424ccSmp153739      argc--; argv++;
2267c478bd9Sstevel@tonic-gate      quiet = 0;
2277c478bd9Sstevel@tonic-gate      while (argc) {
2287c478bd9Sstevel@tonic-gate 	  if (strncmp(*argv, "-k", 2) == 0) {
22956a424ccSmp153739 	       argc--; argv++;
2307c478bd9Sstevel@tonic-gate 	       if (!argc || keytab_str) {
2317c478bd9Sstevel@tonic-gate 		    rem_usage();
2327c478bd9Sstevel@tonic-gate 		    return;
2337c478bd9Sstevel@tonic-gate 	       }
2347c478bd9Sstevel@tonic-gate 	       keytab_str = *argv;
2357c478bd9Sstevel@tonic-gate 	  } else if (strcmp(*argv, "-q") == 0) {
2367c478bd9Sstevel@tonic-gate 	       quiet++;
2377c478bd9Sstevel@tonic-gate 	  } else
2387c478bd9Sstevel@tonic-gate 	       break;
23956a424ccSmp153739 	  argc--; argv++;
2407c478bd9Sstevel@tonic-gate      }
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate      if (argc != 1 && argc != 2) {
2437c478bd9Sstevel@tonic-gate 	  rem_usage();
2447c478bd9Sstevel@tonic-gate 	  return;
2457c478bd9Sstevel@tonic-gate      }
2467c478bd9Sstevel@tonic-gate      if (process_keytab(context, &keytab_str, &keytab))
2477c478bd9Sstevel@tonic-gate 	  return;
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate      (void) remove_principal(keytab_str, keytab, argv[0], argv[1]);
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate      code = krb5_kt_close(context, keytab);
2527c478bd9Sstevel@tonic-gate      if (code != 0)
2537c478bd9Sstevel@tonic-gate 		com_err(whoami, code, gettext("while closing keytab"));
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate      free(keytab_str);
2567c478bd9Sstevel@tonic-gate }
2577c478bd9Sstevel@tonic-gate 
25856a424ccSmp153739 static
25956a424ccSmp153739 int add_principal(void *lhandle, char *keytab_str, krb5_keytab keytab,
26056a424ccSmp153739 		  krb5_boolean keepold, int n_ks_tuple,
2617c478bd9Sstevel@tonic-gate 		  krb5_key_salt_tuple *ks_tuple,
2627c478bd9Sstevel@tonic-gate 		  char *princ_str)
2637c478bd9Sstevel@tonic-gate {
2647c478bd9Sstevel@tonic-gate      kadm5_principal_ent_rec princ_rec;
2657c478bd9Sstevel@tonic-gate      krb5_principal princ;
2667c478bd9Sstevel@tonic-gate      krb5_keytab_entry new_entry;
2677c478bd9Sstevel@tonic-gate      krb5_keyblock *keys;
26856a424ccSmp153739      int code, nkeys, i;
2697c478bd9Sstevel@tonic-gate      int nktypes = 0;
2707c478bd9Sstevel@tonic-gate      krb5_key_salt_tuple *permitted_etypes = NULL;
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate      (void) memset((char *)&princ_rec, 0, sizeof(princ_rec));
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate      princ = NULL;
2757c478bd9Sstevel@tonic-gate      keys = NULL;
2767c478bd9Sstevel@tonic-gate      nkeys = 0;
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate      code = krb5_parse_name(context, princ_str, &princ);
2797c478bd9Sstevel@tonic-gate      if (code != 0) {
2807c478bd9Sstevel@tonic-gate 		com_err(whoami, code,
2817c478bd9Sstevel@tonic-gate 		    gettext("while parsing -add principal name %s"),
2827c478bd9Sstevel@tonic-gate 		  princ_str);
2837c478bd9Sstevel@tonic-gate 	  goto cleanup;
2847c478bd9Sstevel@tonic-gate      }
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate      if (ks_tuple == NULL) {
2877c478bd9Sstevel@tonic-gate 	krb5_enctype *ptr, *ktypes = NULL;
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	code = krb5_get_permitted_enctypes(context, &ktypes);
2907c478bd9Sstevel@tonic-gate 	if (!code && ktypes && *ktypes) {
2917c478bd9Sstevel@tonic-gate 		krb5_int32 salttype;
2927c478bd9Sstevel@tonic-gate 		/*
2937c478bd9Sstevel@tonic-gate 		 * Count the results.  This is stupid, the API above
2947c478bd9Sstevel@tonic-gate 		 * should have included an output param to indicate
2957c478bd9Sstevel@tonic-gate 	 	 * the size of the list that is returned.
2967c478bd9Sstevel@tonic-gate 		 */
2977c478bd9Sstevel@tonic-gate 		for (ptr = ktypes; *ptr; ptr++) nktypes++;
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 		/* Allocate a new key-salt tuple set */
3007c478bd9Sstevel@tonic-gate 		permitted_etypes = (krb5_key_salt_tuple *)malloc (
3017c478bd9Sstevel@tonic-gate 			sizeof (krb5_key_salt_tuple) * nktypes);
3027c478bd9Sstevel@tonic-gate 		if (permitted_etypes == NULL) {
3037c478bd9Sstevel@tonic-gate 			free(ktypes);
3047c478bd9Sstevel@tonic-gate 			return (ENOMEM);
3057c478bd9Sstevel@tonic-gate 		}
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 		/*
3087c478bd9Sstevel@tonic-gate 		 * Because the keysalt parameter doesn't matter for
3097c478bd9Sstevel@tonic-gate 		 * keys stored in the keytab, use the default "normal"
3107c478bd9Sstevel@tonic-gate 		 * salt for all keys
3117c478bd9Sstevel@tonic-gate 		 */
3127c478bd9Sstevel@tonic-gate 		(void) krb5_string_to_salttype("normal", &salttype);
3137c478bd9Sstevel@tonic-gate 		for (i = 0; i < nktypes; i++) {
3147c478bd9Sstevel@tonic-gate 			permitted_etypes[i].ks_enctype = ktypes[i];
3157c478bd9Sstevel@tonic-gate 			permitted_etypes[i].ks_salttype = salttype;
3167c478bd9Sstevel@tonic-gate 		}
3177c478bd9Sstevel@tonic-gate 		free(ktypes);
3187c478bd9Sstevel@tonic-gate 	} else {
3197c478bd9Sstevel@tonic-gate 		if (ktypes)
3207c478bd9Sstevel@tonic-gate 			free(ktypes);
3217c478bd9Sstevel@tonic-gate 		goto cleanup;
3227c478bd9Sstevel@tonic-gate 	}
3237c478bd9Sstevel@tonic-gate      } else {
3247c478bd9Sstevel@tonic-gate 	permitted_etypes = ks_tuple;
3257c478bd9Sstevel@tonic-gate 	nktypes = n_ks_tuple;
3267c478bd9Sstevel@tonic-gate      }
3277c478bd9Sstevel@tonic-gate 
32856a424ccSmp153739 	 code = kadm5_randkey_principal_3(lhandle, princ,
3297c478bd9Sstevel@tonic-gate 					  keepold, nktypes, permitted_etypes,
3307c478bd9Sstevel@tonic-gate 					  &keys, &nkeys);
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate #ifndef _KADMIN_LOCAL_
3337c478bd9Sstevel@tonic-gate 	/* this block is not needed in the kadmin.local client */
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 	/*
3367c478bd9Sstevel@tonic-gate 	 * If the above call failed, we may be talking to an older
3377c478bd9Sstevel@tonic-gate 	 * admin server, so try the older API.
3387c478bd9Sstevel@tonic-gate 	 */
3397c478bd9Sstevel@tonic-gate 	if (code == KADM5_RPC_ERROR) {
3407c478bd9Sstevel@tonic-gate 		code = kadm5_randkey_principal_old(handle, princ, &keys, &nkeys);
3417c478bd9Sstevel@tonic-gate 	}
3427c478bd9Sstevel@tonic-gate #endif /* !KADMIN_LOCAL */
3437c478bd9Sstevel@tonic-gate      if (code != 0) {
3447c478bd9Sstevel@tonic-gate 	  if (code == KADM5_UNK_PRINC) {
3457c478bd9Sstevel@tonic-gate 			fprintf(stderr,
3467c478bd9Sstevel@tonic-gate 			    gettext("%s: Principal %s does not exist.\n"),
3477c478bd9Sstevel@tonic-gate 		       whoami, princ_str);
3487c64d375Smp153739 	/* Solaris Kerberos: Better error messages */
3497c64d375Smp153739 	  } else if (code == KRB5_BAD_ENCTYPE) {
3507c64d375Smp153739 			int i, et;
3517c64d375Smp153739 			fprintf(stderr, gettext("%s: Error from the remote system: "
3527c64d375Smp153739 			    "%s while changing %s's key\n"), whoami,
3537c64d375Smp153739 			    error_message(code), princ_str);
3547c64d375Smp153739 			if (nktypes) {
3557c64d375Smp153739 				et = permitted_etypes[0].ks_enctype;
3567c64d375Smp153739 				fprintf(stderr, gettext("%s: Encryption types "
3577c64d375Smp153739 				    "requested: %s (%d)"), whoami,
3587c64d375Smp153739 				    etype_istring(et), et);
3597c64d375Smp153739 
3607c64d375Smp153739 				for (i = 1; i < nktypes; i++) {
3617c64d375Smp153739 					et = permitted_etypes[i].ks_enctype;
3627c64d375Smp153739 					fprintf(stderr, ", %s (%d)",
3637c64d375Smp153739 					    etype_istring(et), et);
3647c64d375Smp153739 				}
3657c64d375Smp153739 				fprintf(stderr, "\n");
3667c64d375Smp153739 			}
3677c64d375Smp153739 	  } else {
3687c478bd9Sstevel@tonic-gate 			com_err(whoami, code,
3697c478bd9Sstevel@tonic-gate 				gettext("while changing %s's key"),
3707c478bd9Sstevel@tonic-gate 				princ_str);
3717c64d375Smp153739 	  }
3727c478bd9Sstevel@tonic-gate 	  goto cleanup;
3737c478bd9Sstevel@tonic-gate      }
3747c478bd9Sstevel@tonic-gate 
37556a424ccSmp153739      code = kadm5_get_principal(lhandle, princ, &princ_rec,
3767c478bd9Sstevel@tonic-gate 				KADM5_PRINCIPAL_NORMAL_MASK);
3777c478bd9Sstevel@tonic-gate      if (code != 0) {
3787c478bd9Sstevel@tonic-gate 		com_err(whoami, code, gettext("while retrieving principal"));
3797c478bd9Sstevel@tonic-gate 	  goto cleanup;
3807c478bd9Sstevel@tonic-gate      }
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate      for (i = 0; i < nkeys; i++) {
3837c478bd9Sstevel@tonic-gate 	  memset((char *) &new_entry, 0, sizeof(new_entry));
3847c478bd9Sstevel@tonic-gate 	  new_entry.principal = princ;
3857c478bd9Sstevel@tonic-gate 	  new_entry.key = keys[i];
3867c478bd9Sstevel@tonic-gate 	  new_entry.vno = princ_rec.kvno;
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 	  code = krb5_kt_add_entry(context, keytab, &new_entry);
3897c478bd9Sstevel@tonic-gate 	  if (code != 0) {
3907c478bd9Sstevel@tonic-gate 			com_err(whoami, code,
3917c478bd9Sstevel@tonic-gate 				gettext("while adding key to keytab"));
39256a424ccSmp153739 	       (void) kadm5_free_principal_ent(lhandle, &princ_rec);
3937c478bd9Sstevel@tonic-gate 	       goto cleanup;
3947c478bd9Sstevel@tonic-gate 	  }
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	  if (!quiet)
3977c478bd9Sstevel@tonic-gate 			printf(gettext("Entry for principal %s with kvno %d, "
3987c478bd9Sstevel@tonic-gate 				"encryption type %s added to keytab %s.\n"),
3997c478bd9Sstevel@tonic-gate 		      princ_str, princ_rec.kvno,
4007c478bd9Sstevel@tonic-gate 		      etype_string(keys[i].enctype), keytab_str);
4017c478bd9Sstevel@tonic-gate      }
4027c478bd9Sstevel@tonic-gate 
40356a424ccSmp153739      code = kadm5_free_principal_ent(lhandle, &princ_rec);
4047c478bd9Sstevel@tonic-gate      if (code != 0) {
4057c478bd9Sstevel@tonic-gate 		com_err(whoami, code, gettext("while freeing principal entry"));
4067c478bd9Sstevel@tonic-gate 	  goto cleanup;
4077c478bd9Sstevel@tonic-gate      }
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate cleanup:
4107c478bd9Sstevel@tonic-gate      if (nkeys) {
4117c478bd9Sstevel@tonic-gate 	  for (i = 0; i < nkeys; i++)
4127c478bd9Sstevel@tonic-gate 	       krb5_free_keyblock_contents(context, &keys[i]);
4137c478bd9Sstevel@tonic-gate 	  free(keys);
4147c478bd9Sstevel@tonic-gate      }
4157c478bd9Sstevel@tonic-gate      if (princ)
4167c478bd9Sstevel@tonic-gate 	  krb5_free_principal(context, princ);
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate      if (permitted_etypes != NULL && ks_tuple == NULL)
4197c478bd9Sstevel@tonic-gate 	free(permitted_etypes);
4207c478bd9Sstevel@tonic-gate 
42156a424ccSmp153739      return code;
4227c478bd9Sstevel@tonic-gate }
4237c478bd9Sstevel@tonic-gate 
42456a424ccSmp153739 int remove_principal(char *keytab_str, krb5_keytab keytab, char
4257c478bd9Sstevel@tonic-gate 		     *princ_str, char *kvno_str)
4267c478bd9Sstevel@tonic-gate {
4277c478bd9Sstevel@tonic-gate      krb5_principal princ;
4287c478bd9Sstevel@tonic-gate      krb5_keytab_entry entry;
4297c478bd9Sstevel@tonic-gate      krb5_kt_cursor cursor;
43056a424ccSmp153739      enum { UNDEF, SPEC, HIGH, ALL, OLD } mode;
43156a424ccSmp153739      int code, did_something;
43256a424ccSmp153739      krb5_kvno kvno;
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate      code = krb5_parse_name(context, princ_str, &princ);
4357c478bd9Sstevel@tonic-gate      if (code != 0) {
4367c478bd9Sstevel@tonic-gate 		com_err(whoami, code,
4377c478bd9Sstevel@tonic-gate 			gettext("while parsing principal name %s"),
4387c478bd9Sstevel@tonic-gate 		  princ_str);
43956a424ccSmp153739 	  return code;
4407c478bd9Sstevel@tonic-gate      }
44156a424ccSmp153739 
4427c478bd9Sstevel@tonic-gate      mode = UNDEF;
4437c478bd9Sstevel@tonic-gate      if (kvno_str == NULL) {
4447c478bd9Sstevel@tonic-gate 	  mode = HIGH;
4457c478bd9Sstevel@tonic-gate 	  kvno = 0;
4467c478bd9Sstevel@tonic-gate      } else if (strcmp(kvno_str, "all") == 0) {
4477c478bd9Sstevel@tonic-gate 	  mode = ALL;
4487c478bd9Sstevel@tonic-gate 	  kvno = 0;
4497c478bd9Sstevel@tonic-gate      } else if (strcmp(kvno_str, "old") == 0) {
4507c478bd9Sstevel@tonic-gate 	  mode = OLD;
4517c478bd9Sstevel@tonic-gate 	  kvno = 0;
4527c478bd9Sstevel@tonic-gate      } else {
4537c478bd9Sstevel@tonic-gate 	  mode = SPEC;
4547c478bd9Sstevel@tonic-gate 	  kvno = atoi(kvno_str);
4557c478bd9Sstevel@tonic-gate      }
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate      /* kvno is set to specified value for SPEC, 0 otherwise */
4587c478bd9Sstevel@tonic-gate      code = krb5_kt_get_entry(context, keytab, princ, kvno, 0, &entry);
4597c478bd9Sstevel@tonic-gate      if (code != 0) {
4607c478bd9Sstevel@tonic-gate 	  if (code == ENOENT) {
4617c478bd9Sstevel@tonic-gate 			fprintf(stderr,
4627c478bd9Sstevel@tonic-gate 				gettext("%s: Keytab %s does not exist.\n"),
4637c478bd9Sstevel@tonic-gate 		       whoami, keytab_str);
4647c478bd9Sstevel@tonic-gate 	  } else if (code == KRB5_KT_NOTFOUND) {
4657c478bd9Sstevel@tonic-gate 	       if (mode != SPEC)
4667c478bd9Sstevel@tonic-gate 				fprintf(stderr,
4677c478bd9Sstevel@tonic-gate 					gettext("%s: No entry for principal "
4687c478bd9Sstevel@tonic-gate 						"%s exists in keytab %s\n"),
4697c478bd9Sstevel@tonic-gate 			    whoami, princ_str, keytab_str);
4707c478bd9Sstevel@tonic-gate 	       else
4717c478bd9Sstevel@tonic-gate 				fprintf(stderr,
4727c478bd9Sstevel@tonic-gate 					gettext("%s: No entry for principal "
4737c478bd9Sstevel@tonic-gate 						"%s with kvno %d exists in "
4747c478bd9Sstevel@tonic-gate 						"keytab %s.\n"),
4757c478bd9Sstevel@tonic-gate 					whoami, princ_str, kvno, keytab_str);
4767c478bd9Sstevel@tonic-gate 	  } else {
4777c478bd9Sstevel@tonic-gate 			com_err(whoami, code,
4787c478bd9Sstevel@tonic-gate 				gettext("while retrieving highest "
4797c478bd9Sstevel@tonic-gate 					"kvno from keytab"));
4807c478bd9Sstevel@tonic-gate 	  }
48156a424ccSmp153739 	  return code;
4827c478bd9Sstevel@tonic-gate      }
48356a424ccSmp153739 
4847c478bd9Sstevel@tonic-gate      /* set kvno to spec'ed value for SPEC, highest kvno otherwise */
4857c478bd9Sstevel@tonic-gate      kvno = entry.vno;
4867c478bd9Sstevel@tonic-gate      krb5_kt_free_entry(context, &entry);
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate      code = krb5_kt_start_seq_get(context, keytab, &cursor);
4897c478bd9Sstevel@tonic-gate      if (code != 0) {
4907c478bd9Sstevel@tonic-gate 		com_err(whoami, code, gettext("while starting keytab scan"));
49156a424ccSmp153739 	  return code;
4927c478bd9Sstevel@tonic-gate      }
49356a424ccSmp153739 
4947c478bd9Sstevel@tonic-gate      did_something = 0;
49556a424ccSmp153739      while ((code = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0) {
4967c478bd9Sstevel@tonic-gate 	  if (krb5_principal_compare(context, princ, entry.principal) &&
4977c478bd9Sstevel@tonic-gate 	      ((mode == ALL) ||
4987c478bd9Sstevel@tonic-gate 	       (mode == SPEC && entry.vno == kvno) ||
4997c478bd9Sstevel@tonic-gate 	       (mode == OLD && entry.vno != kvno) ||
5007c478bd9Sstevel@tonic-gate 	       (mode == HIGH && entry.vno == kvno))) {
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	       /*
50356a424ccSmp153739 		* Ack!  What a kludge... the scanning functions lock
50456a424ccSmp153739 		* the keytab so entries cannot be removed while they
50556a424ccSmp153739 		* are operating.
5067c478bd9Sstevel@tonic-gate 		*/
5077c478bd9Sstevel@tonic-gate 	       code = krb5_kt_end_seq_get(context, keytab, &cursor);
5087c478bd9Sstevel@tonic-gate 	       if (code != 0) {
5097c478bd9Sstevel@tonic-gate 				com_err(whoami, code,
5107c478bd9Sstevel@tonic-gate 					gettext("while temporarily "
5117c478bd9Sstevel@tonic-gate 						"ending keytab scan"));
51256a424ccSmp153739 		    return code;
5137c478bd9Sstevel@tonic-gate 	       }
5147c478bd9Sstevel@tonic-gate 	       code = krb5_kt_remove_entry(context, keytab, &entry);
5157c478bd9Sstevel@tonic-gate 	       if (code != 0) {
5167c478bd9Sstevel@tonic-gate 				com_err(whoami, code,
5177c478bd9Sstevel@tonic-gate 					gettext("while deleting entry "
5187c478bd9Sstevel@tonic-gate 						"from keytab"));
51956a424ccSmp153739 		    return code;
5207c478bd9Sstevel@tonic-gate 	       }
5217c478bd9Sstevel@tonic-gate 	       code = krb5_kt_start_seq_get(context, keytab, &cursor);
5227c478bd9Sstevel@tonic-gate 	       if (code != 0) {
5237c478bd9Sstevel@tonic-gate 				com_err(whoami, code,
5247c478bd9Sstevel@tonic-gate 				    gettext("while restarting keytab scan"));
52556a424ccSmp153739 		    return code;
5267c478bd9Sstevel@tonic-gate 	       }
52756a424ccSmp153739 
5287c478bd9Sstevel@tonic-gate 	       did_something++;
5297c478bd9Sstevel@tonic-gate 	       if (!quiet)
5307c478bd9Sstevel@tonic-gate 				printf(gettext("Entry for principal "
5317c478bd9Sstevel@tonic-gate 					    "%s with kvno %d "
5327c478bd9Sstevel@tonic-gate 					    "removed from keytab %s.\n"),
5337c478bd9Sstevel@tonic-gate 			   princ_str, entry.vno, keytab_str);
5347c478bd9Sstevel@tonic-gate 	  }
5357c478bd9Sstevel@tonic-gate 	  krb5_kt_free_entry(context, &entry);
5367c478bd9Sstevel@tonic-gate      }
5377c478bd9Sstevel@tonic-gate      if (code && code != KRB5_KT_END) {
5387c478bd9Sstevel@tonic-gate 		com_err(whoami, code, gettext("while scanning keytab"));
53956a424ccSmp153739 	  return code;
5407c478bd9Sstevel@tonic-gate      }
54156a424ccSmp153739      if ((code = krb5_kt_end_seq_get(context, keytab, &cursor))) {
5427c478bd9Sstevel@tonic-gate 		com_err(whoami, code, gettext("while ending keytab scan"));
54356a424ccSmp153739 	  return code;
5447c478bd9Sstevel@tonic-gate      }
54556a424ccSmp153739 
5467c478bd9Sstevel@tonic-gate      /*
54756a424ccSmp153739       * If !did_someting then mode must be OLD or we would have
54856a424ccSmp153739       * already returned with an error.  But check it anyway just to
54956a424ccSmp153739       * prevent unexpected error messages...
5507c478bd9Sstevel@tonic-gate       */
5517c478bd9Sstevel@tonic-gate      if (!did_something && mode == OLD) {
5527c478bd9Sstevel@tonic-gate 		fprintf(stderr,
5537c478bd9Sstevel@tonic-gate 		    gettext("%s: There is only one entry for principal "
5547c478bd9Sstevel@tonic-gate 			"%s in keytab %s\n"),
5557c478bd9Sstevel@tonic-gate 		    whoami, princ_str, keytab_str);
55656a424ccSmp153739 	  return 1;
5577c478bd9Sstevel@tonic-gate      }
55856a424ccSmp153739 
55956a424ccSmp153739      return 0;
5607c478bd9Sstevel@tonic-gate }
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate /*
5637c478bd9Sstevel@tonic-gate  * etype_string(enctype): return a string representation of the
5647c478bd9Sstevel@tonic-gate  * encryption type.  XXX copied from klist.c; this should be a
5657c478bd9Sstevel@tonic-gate  * library function, or perhaps just #defines
5667c478bd9Sstevel@tonic-gate  */
56756a424ccSmp153739 static char *etype_string(enctype)
5687c478bd9Sstevel@tonic-gate     krb5_enctype enctype;
5697c478bd9Sstevel@tonic-gate {
5707c478bd9Sstevel@tonic-gate     static char buf[100];
5717c478bd9Sstevel@tonic-gate     krb5_error_code ret;
5727c478bd9Sstevel@tonic-gate 
57356a424ccSmp153739     if ((ret = krb5_enctype_to_string(enctype, buf, sizeof(buf))))
5747c478bd9Sstevel@tonic-gate 	sprintf(buf, "etype %d", enctype);
5757c478bd9Sstevel@tonic-gate 
57656a424ccSmp153739     return buf;
5777c478bd9Sstevel@tonic-gate }
5787c64d375Smp153739 
5797c64d375Smp153739 /* Solaris Kerberos */
5807c64d375Smp153739 static char *etype_istring(krb5_enctype enctype) {
5817c64d375Smp153739     static char buf[100];
5827c64d375Smp153739     krb5_error_code ret;
5837c64d375Smp153739 
5847c64d375Smp153739     if ((ret = krb5_enctype_to_istring(enctype, buf, sizeof(buf))))
5857c64d375Smp153739 	sprintf(buf, "unknown", enctype);
5867c64d375Smp153739 
5877c64d375Smp153739     return (buf);
5887c64d375Smp153739 }
5897c64d375Smp153739 
590