/* * Copyright (c) 1997, 1998 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Kungliga Tekniska * Högskolan and its contributors. * * 4. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "ktutil_locl.h" RCSID("$Id$"); static int kt_list(int argc, char **argv) { krb5_error_code ret; krb5_kt_cursor cursor; krb5_keytab_entry entry; ret = krb5_kt_start_seq_get(context, keytab, &cursor); if(ret){ krb5_warn(context, ret, "krb5_kt_start_seq_get"); return 1; } printf("%s", "Version"); printf(" "); printf("%-6s", "Type"); printf(" "); printf("%s", "Principal"); printf("\n"); while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0){ char *p; printf(" %3d ", entry.vno); printf(" "); krb5_keytype_to_string(context, entry.keyblock.keytype, &p); printf("%-6s", p); free(p); printf(" "); krb5_unparse_name(context, entry.principal, &p); printf("%s ", p); free(p); printf("\n"); krb5_kt_free_entry(context, &entry); } ret = krb5_kt_end_seq_get(context, keytab, &cursor); return 0; } static int kt_remove(int argc, char **argv) { krb5_error_code ret; krb5_keytab_entry entry; char *principal_string = NULL; krb5_principal principal; int kvno = 0; char *keytype_string = NULL; krb5_keytype keytype = 0; int help_flag = 0; struct getargs args[] = { { "principal", 'p', arg_string, NULL, "principal to remove" }, { "kvno", 'V', arg_integer, NULL, "key version to remove" }, { "keytype", 't', arg_string, NULL, "key type to remove" }, { "help", 'h', arg_flag, NULL } }; int num_args = sizeof(args) / sizeof(args[0]); int optind = 0; int i = 0; args[i++].value = &principal_string; args[i++].value = &kvno; args[i++].value = &keytype_string; args[i++].value = &help_flag; if(getarg(args, num_args, argc, argv, &optind)) { arg_printusage(args, num_args, ""); return 0; } if(help_flag) { arg_printusage(args, num_args, ""); return 0; } if(principal_string) { ret = krb5_parse_name(context, principal_string, &principal); if(ret) { krb5_warn(context, ret, "%s", principal_string); return 0; } } if(keytype_string) { ret = krb5_string_to_keytype(context, keytype_string, &keytype); if(ret) { int t; if(sscanf(keytype_string, "%d", &t) == 1) keytype = t; else { krb5_warn(context, ret, "%s", keytype_string); if(principal) krb5_free_principal(context, principal); return 0; } } } entry.principal = principal; entry.keyblock.keytype = keytype; entry.vno = kvno; ret = krb5_kt_remove_entry(context, keytab, &entry); if(ret) krb5_warn(context, ret, "remove"); if(principal) krb5_free_principal(context, principal); return 0; } static int kt_add(int argc, char **argv) { krb5_error_code ret; krb5_keytab_entry entry; char buf[128]; char *principal_string = NULL; int kvno = -1; char *keytype_string = NULL; krb5_keytype keytype; char *password_string = NULL; int random_flag = 0; int help_flag = 0; struct getargs args[] = { { "principal", 'p', arg_string, NULL, "principal of key", "principal"}, { "kvno", 'V', arg_integer, NULL, "key version of key" }, { "keytype", 't', arg_string, NULL, "key type of key" }, { "password", 'w', arg_string, NULL, "password for key"}, { "random", 'r', arg_flag, NULL, "generate random key" }, { "help", 'h', arg_flag, NULL } }; int num_args = sizeof(args) / sizeof(args[0]); int optind = 0; int i = 0; args[i++].value = &principal_string; args[i++].value = &kvno; args[i++].value = &keytype_string; args[i++].value = &password_string; args[i++].value = &random_flag; args[i++].value = &help_flag; if(getarg(args, num_args, argc, argv, &optind)) { arg_printusage(args, num_args, ""); return 0; } if(help_flag) { arg_printusage(args, num_args, ""); return 0; } if(principal_string == NULL) { printf("Principal: "); fgets(buf, sizeof(buf), stdin); buf[strcspn(buf, "\r\n")] = '\0'; principal_string = buf; } ret = krb5_parse_name(context, principal_string, &entry.principal); if(ret) { krb5_warn(context, ret, "%s", principal_string); return 0; } if(keytype_string == NULL) { printf("Keytype: "); fgets(buf, sizeof(buf), stdin); buf[strcspn(buf, "\r\n")] = '\0'; keytype_string = buf; } ret = krb5_string_to_keytype(context, keytype_string, &keytype); if(ret) { int t; if(sscanf(keytype_string, "%d", &t) == 1) keytype = t; else { krb5_warn(context, ret, "%s", keytype_string); if(entry.principal) krb5_free_principal(context, entry.principal); return 0; } } if(kvno == -1) { printf("Key version: "); fgets(buf, sizeof(buf), stdin); buf[strcspn(buf, "\r\n")] = '\0'; kvno = atoi(buf); } if(password_string == NULL && random_flag == 0) { des_read_pw_string(buf, sizeof(buf), "Password: ", 1); password_string = buf; } if(password_string) { krb5_data salt; krb5_get_salt(entry.principal, &salt); krb5_string_to_key(password_string, &salt, keytype, &entry.keyblock); krb5_data_free(&salt); } else { krb5_generate_random_keyblock(context, keytype, &entry.keyblock); } entry.vno = kvno; ret = krb5_kt_add_entry(context, keytab, &entry); if(ret) krb5_warn(context, ret, "add"); krb5_kt_free_entry(context, &entry); return 0; } static int help(int argc, char **argv); static SL_cmd cmds[] = { { "list", kt_list, "list", "" }, { "srvconvert", srvconv, "srvconvert [flags]", "" }, { "srv2keytab" }, { "add", kt_add, "add", "" }, { "remove", kt_remove, "remove", "" }, { "help", help, "help", "" }, { NULL, NULL, NULL, NULL } }; static int help_flag; static int version_flag; static char *keytab_string; static struct getargs args[] = { { "version", 0, arg_flag, &version_flag, NULL, NULL }, { "help", 'h', arg_flag, &help_flag, NULL, NULL }, { "keytab", 'k', arg_string, &keytab_string, "keytab", "keytab to operate on" }, }; static int num_args = sizeof(args) / sizeof(args[0]); krb5_context context; krb5_keytab keytab; static int help(int argc, char **argv) { sl_help(cmds, argc, argv); return 0; } static void usage(int status) { arg_printusage(args, num_args, "command"); exit(status); } int main(int argc, char **argv) { int optind = 0; krb5_error_code ret; set_progname(argv[0]); krb5_init_context(&context); if(getarg(args, num_args, argc, argv, &optind)) usage(1); if(help_flag) usage(0); if(version_flag) krb5_errx(context, 0, "%s", heimdal_version); argc -= optind; argv += optind; if(argc == 0) usage(1); if(keytab_string) { ret = krb5_kt_resolve(context, keytab_string, &keytab); } else { ret = krb5_kt_default(context, &keytab); } if(ret) krb5_err(context, 1, ret, "resolving keytab"); ret = sl_command(cmds, argc, argv); krb5_kt_close(context, keytab); return ret; }