2 * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
9 * Copyright (C) 1998 by the FundsXpress, INC.
11 * All rights reserved.
13 * Export of this software from the United States of America may require
14 * a specific license from the United States Government. It is the
15 * responsibility of any person or organization contemplating export to
16 * obtain such a license before exporting.
18 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
19 * distribute this software and its documentation for any purpose and
20 * without fee is hereby granted, provided that the above copyright
21 * notice appear in all copies and that both that copyright notice and
22 * this permission notice appear in supporting documentation, and that
23 * the name of FundsXpress. not be used in advertising or publicity pertaining
24 * to distribution of the software without specific, written prior
25 * permission. FundsXpress makes no representations about the suitability of
26 * this software for any purpose. It is provided "as is" without express
27 * or implied warranty.
29 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
30 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
31 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
34 #if !defined(lint) && !defined(__CODECENTER__)
35 static char *rcsid = "$Header$";
43 #include <kadm5/admin.h>
44 #include <krb5/adm_proto.h>
47 static int add_principal(void *lhandle, char *keytab_str, krb5_keytab keytab,
49 int n_ks_tuple, krb5_key_salt_tuple *ks_tuple,
51 static int remove_principal(char *keytab_str, krb5_keytab keytab, char
52 *princ_str, char *kvno_str);
53 static char *etype_string(krb5_enctype enctype);
57 static void add_usage()
59 fprintf(stderr, "Usage: ktadd [-k[eytab] keytab] [-q] [-e keysaltlist] [principal | -glob princ-exp] [...]\n");
62 static void rem_usage()
64 fprintf(stderr, "Usage: ktremove [-k[eytab] keytab] [-q] principal [kvno|\"all\"|\"old\"]\n");
67 static int process_keytab(krb5_context my_context, char **keytab_str,
72 if (*keytab_str == NULL) {
73 /* XXX krb5_defkeyname is an internal library global and
75 if (! (*keytab_str = strdup(krb5_defkeyname))) {
76 com_err(whoami, ENOMEM, "while creating keytab name");
79 code = krb5_kt_default(my_context, keytab);
81 com_err(whoami, code, "while opening default keytab");
86 if (strchr(*keytab_str, ':') != NULL) {
87 *keytab_str = strdup(*keytab_str);
88 if (*keytab_str == NULL) {
89 com_err(whoami, ENOMEM, "while creating keytab name");
93 char *tmp = *keytab_str;
95 *keytab_str = (char *)
96 malloc(strlen("WRFILE:")+strlen(tmp)+1);
97 if (*keytab_str == NULL) {
98 com_err(whoami, ENOMEM, "while creating keytab name");
101 sprintf(*keytab_str, "WRFILE:%s", tmp);
104 code = krb5_kt_resolve(my_context, *keytab_str, keytab);
106 com_err(whoami, code, "while resolving keytab %s", *keytab_str);
116 void kadmin_keytab_add(int argc, char **argv)
118 krb5_keytab keytab = 0;
119 char *keytab_str = NULL, **princs;
121 krb5_error_code retval;
123 krb5_boolean keepold = FALSE;
124 krb5_key_salt_tuple *ks_tuple = NULL;
129 if (strncmp(*argv, "-k", 2) == 0) {
131 if (!argc || keytab_str) {
136 } else if (strcmp(*argv, "-q") == 0) {
138 } else if (strcmp(*argv, "-e") == 0) {
144 retval = krb5_string_to_keysalts(*++argv, ", \t", ":.-", 0,
145 &ks_tuple, &n_ks_tuple);
147 com_err("ktadd", retval, "while parsing keysalts %s",
162 if (process_keytab(context, &keytab_str, &keytab))
166 if (strcmp(*argv, "-glob") == 0) {
167 if (*++argv == NULL) {
172 code = kadm5_get_principals(handle, *argv, &princs, &num);
174 com_err(whoami, code, "while expanding expression \"%s\".",
180 for (i = 0; i < num; i++)
181 (void) add_principal(handle, keytab_str, keytab,
182 keepold, n_ks_tuple, ks_tuple,
184 kadm5_free_name_list(handle, princs, num);
186 (void) add_principal(handle, keytab_str, keytab,
187 keepold, n_ks_tuple, ks_tuple,
192 code = krb5_kt_close(context, keytab);
194 com_err(whoami, code, "while closing keytab");
199 void kadmin_keytab_remove(int argc, char **argv)
201 krb5_keytab keytab = 0;
202 char *keytab_str = NULL;
208 if (strncmp(*argv, "-k", 2) == 0) {
210 if (!argc || keytab_str) {
215 } else if (strcmp(*argv, "-q") == 0) {
222 if (argc != 1 && argc != 2) {
226 if (process_keytab(context, &keytab_str, &keytab))
229 (void) remove_principal(keytab_str, keytab, argv[0], argv[1]);
231 code = krb5_kt_close(context, keytab);
233 com_err(whoami, code, "while closing keytab");
239 int add_principal(void *lhandle, char *keytab_str, krb5_keytab keytab,
240 krb5_boolean keepold, int n_ks_tuple,
241 krb5_key_salt_tuple *ks_tuple,
244 kadm5_principal_ent_rec princ_rec;
245 krb5_principal princ;
246 krb5_keytab_entry new_entry;
250 (void) memset((char *)&princ_rec, 0, sizeof(princ_rec));
256 code = krb5_parse_name(context, princ_str, &princ);
258 com_err(whoami, code, "while parsing -add principal name %s",
263 if (keepold || ks_tuple != NULL) {
264 code = kadm5_randkey_principal_3(lhandle, princ,
265 keepold, n_ks_tuple, ks_tuple,
268 code = kadm5_randkey_principal(lhandle, princ, &keys, &nkeys);
271 if (code == KADM5_UNK_PRINC) {
272 fprintf(stderr, "%s: Principal %s does not exist.\n",
275 com_err(whoami, code, "while changing %s's key",
280 code = kadm5_get_principal(lhandle, princ, &princ_rec,
281 KADM5_PRINCIPAL_NORMAL_MASK);
283 com_err(whoami, code, "while retrieving principal");
287 for (i = 0; i < nkeys; i++) {
288 memset((char *) &new_entry, 0, sizeof(new_entry));
289 new_entry.principal = princ;
290 new_entry.key = keys[i];
291 new_entry.vno = princ_rec.kvno;
293 code = krb5_kt_add_entry(context, keytab, &new_entry);
295 com_err(whoami, code, "while adding key to keytab");
296 (void) kadm5_free_principal_ent(lhandle, &princ_rec);
301 printf("Entry for principal %s with kvno %d, "
302 "encryption type %s added to keytab %s.\n",
303 princ_str, princ_rec.kvno,
304 etype_string(keys[i].enctype), keytab_str);
307 code = kadm5_free_principal_ent(lhandle, &princ_rec);
309 com_err(whoami, code, "while freeing principal entry");
315 for (i = 0; i < nkeys; i++)
316 krb5_free_keyblock_contents(context, &keys[i]);
320 krb5_free_principal(context, princ);
325 int remove_principal(char *keytab_str, krb5_keytab keytab, char
326 *princ_str, char *kvno_str)
328 krb5_principal princ;
329 krb5_keytab_entry entry;
330 krb5_kt_cursor cursor;
331 enum { UNDEF, SPEC, HIGH, ALL, OLD } mode;
332 int code, did_something;
335 code = krb5_parse_name(context, princ_str, &princ);
337 com_err(whoami, code, "while parsing principal name %s",
343 if (kvno_str == NULL) {
346 } else if (strcmp(kvno_str, "all") == 0) {
349 } else if (strcmp(kvno_str, "old") == 0) {
354 kvno = atoi(kvno_str);
357 /* kvno is set to specified value for SPEC, 0 otherwise */
358 code = krb5_kt_get_entry(context, keytab, princ, kvno, 0, &entry);
360 if (code == ENOENT) {
361 fprintf(stderr, "%s: Keytab %s does not exist.\n",
363 } else if (code == KRB5_KT_NOTFOUND) {
365 fprintf(stderr, "%s: No entry for principal "
366 "%s exists in keytab %s\n",
367 whoami, princ_str, keytab_str);
369 fprintf(stderr, "%s: No entry for principal "
370 "%s with kvno %d exists in keytab "
371 "%s.\n", whoami, princ_str, kvno,
374 com_err(whoami, code, "while retrieving highest kvno "
380 /* set kvno to spec'ed value for SPEC, highest kvno otherwise */
382 krb5_kt_free_entry(context, &entry);
384 code = krb5_kt_start_seq_get(context, keytab, &cursor);
386 com_err(whoami, code, "while starting keytab scan");
391 while ((code = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0) {
392 if (krb5_principal_compare(context, princ, entry.principal) &&
394 (mode == SPEC && entry.vno == kvno) ||
395 (mode == OLD && entry.vno != kvno) ||
396 (mode == HIGH && entry.vno == kvno))) {
399 * Ack! What a kludge... the scanning functions lock
400 * the keytab so entries cannot be removed while they
403 code = krb5_kt_end_seq_get(context, keytab, &cursor);
405 com_err(whoami, code, "while temporarily ending "
409 code = krb5_kt_remove_entry(context, keytab, &entry);
411 com_err(whoami, code, "while deleting entry from keytab");
414 code = krb5_kt_start_seq_get(context, keytab, &cursor);
416 com_err(whoami, code, "while restarting keytab scan");
422 printf("Entry for principal %s with kvno %d "
423 "removed from keytab %s.\n",
424 princ_str, entry.vno, keytab_str);
426 krb5_kt_free_entry(context, &entry);
428 if (code && code != KRB5_KT_END) {
429 com_err(whoami, code, "while scanning keytab");
432 if ((code = krb5_kt_end_seq_get(context, keytab, &cursor))) {
433 com_err(whoami, code, "while ending keytab scan");
438 * If !did_someting then mode must be OLD or we would have
439 * already returned with an error. But check it anyway just to
440 * prevent unexpected error messages...
442 if (!did_something && mode == OLD) {
443 fprintf(stderr, "%s: There is only one entry for principal "
444 "%s in keytab %s\n", whoami, princ_str, keytab_str);
452 * etype_string(enctype): return a string representation of the
453 * encryption type. XXX copied from klist.c; this should be a
454 * library function, or perhaps just #defines
456 static char *etype_string(enctype)
457 krb5_enctype enctype;
459 static char buf[100];
462 if ((ret = krb5_enctype_to_string(enctype, buf, sizeof(buf))))
463 sprintf(buf, "etype %d", enctype);