1b528cefcSMark Murray /* 2*ae771770SStanislav Sedov * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan 3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden). 4b528cefcSMark Murray * All rights reserved. 5b528cefcSMark Murray * 6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without 7b528cefcSMark Murray * modification, are permitted provided that the following conditions 8b528cefcSMark Murray * are met: 9b528cefcSMark Murray * 10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright 11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer. 12b528cefcSMark Murray * 13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright 14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the 15b528cefcSMark Murray * documentation and/or other materials provided with the distribution. 16b528cefcSMark Murray * 17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors 18b528cefcSMark Murray * may be used to endorse or promote products derived from this software 19b528cefcSMark Murray * without specific prior written permission. 20b528cefcSMark Murray * 21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31b528cefcSMark Murray * SUCH DAMAGE. 32b528cefcSMark Murray */ 33b528cefcSMark Murray 34b528cefcSMark Murray #include "ktutil_locl.h" 35b528cefcSMark Murray 36*ae771770SStanislav Sedov RCSID("$Id$"); 37c19800e8SDoug Rabson 38c19800e8SDoug Rabson static char * 39c19800e8SDoug Rabson readstring(const char *prompt, char *buf, size_t len) 40c19800e8SDoug Rabson { 41c19800e8SDoug Rabson printf("%s", prompt); 42c19800e8SDoug Rabson if (fgets(buf, len, stdin) == NULL) 43c19800e8SDoug Rabson return NULL; 44c19800e8SDoug Rabson buf[strcspn(buf, "\r\n")] = '\0'; 45c19800e8SDoug Rabson return buf; 46c19800e8SDoug Rabson } 47b528cefcSMark Murray 48b528cefcSMark Murray int 49c19800e8SDoug Rabson kt_add(struct add_options *opt, int argc, char **argv) 50b528cefcSMark Murray { 51b528cefcSMark Murray krb5_error_code ret; 52adb0ddaeSAssar Westerlund krb5_keytab keytab; 53b528cefcSMark Murray krb5_keytab_entry entry; 54c19800e8SDoug Rabson char buf[1024]; 55b528cefcSMark Murray krb5_enctype enctype; 56b528cefcSMark Murray 574137ff4cSJacques Vidrine if((keytab = ktutil_open_keytab()) == NULL) 58adb0ddaeSAssar Westerlund return 1; 59adb0ddaeSAssar Westerlund 60adb0ddaeSAssar Westerlund memset(&entry, 0, sizeof(entry)); 61c19800e8SDoug Rabson if(opt->principal_string == NULL) { 62c19800e8SDoug Rabson if(readstring("Principal: ", buf, sizeof(buf)) == NULL) 63adb0ddaeSAssar Westerlund return 1; 64c19800e8SDoug Rabson opt->principal_string = buf; 65b528cefcSMark Murray } 66c19800e8SDoug Rabson ret = krb5_parse_name(context, opt->principal_string, &entry.principal); 67b528cefcSMark Murray if(ret) { 68c19800e8SDoug Rabson krb5_warn(context, ret, "%s", opt->principal_string); 69adb0ddaeSAssar Westerlund goto out; 70b528cefcSMark Murray } 71c19800e8SDoug Rabson if(opt->enctype_string == NULL) { 72c19800e8SDoug Rabson if(readstring("Encryption type: ", buf, sizeof(buf)) == NULL) { 73c19800e8SDoug Rabson ret = 1; 74adb0ddaeSAssar Westerlund goto out; 75b528cefcSMark Murray } 76c19800e8SDoug Rabson opt->enctype_string = buf; 77c19800e8SDoug Rabson } 78c19800e8SDoug Rabson ret = krb5_string_to_enctype(context, opt->enctype_string, &enctype); 79b528cefcSMark Murray if(ret) { 80b528cefcSMark Murray int t; 81c19800e8SDoug Rabson if(sscanf(opt->enctype_string, "%d", &t) == 1) 82b528cefcSMark Murray enctype = t; 83b528cefcSMark Murray else { 84c19800e8SDoug Rabson krb5_warn(context, ret, "%s", opt->enctype_string); 85adb0ddaeSAssar Westerlund goto out; 86b528cefcSMark Murray } 87b528cefcSMark Murray } 88c19800e8SDoug Rabson if(opt->kvno_integer == -1) { 89c19800e8SDoug Rabson if(readstring("Key version: ", buf, sizeof(buf)) == NULL) { 90c19800e8SDoug Rabson ret = 1; 91adb0ddaeSAssar Westerlund goto out; 92b528cefcSMark Murray } 93c19800e8SDoug Rabson if(sscanf(buf, "%u", &opt->kvno_integer) != 1) 94adb0ddaeSAssar Westerlund goto out; 95b528cefcSMark Murray } 96c19800e8SDoug Rabson if(opt->password_string == NULL && opt->random_flag == 0) { 97c19800e8SDoug Rabson if(UI_UTIL_read_pw_string(buf, sizeof(buf), "Password: ", 1)) { 98c19800e8SDoug Rabson ret = 1; 99c19800e8SDoug Rabson goto out; 100c19800e8SDoug Rabson } 101c19800e8SDoug Rabson opt->password_string = buf; 102c19800e8SDoug Rabson } 103c19800e8SDoug Rabson if(opt->password_string) { 104c19800e8SDoug Rabson if (opt->hex_flag) { 105c19800e8SDoug Rabson size_t len; 106c19800e8SDoug Rabson void *data; 107c19800e8SDoug Rabson 108c19800e8SDoug Rabson len = (strlen(opt->password_string) + 1) / 2; 109c19800e8SDoug Rabson 110c19800e8SDoug Rabson data = malloc(len); 111c19800e8SDoug Rabson if (data == NULL) { 112c19800e8SDoug Rabson krb5_warn(context, ENOMEM, "malloc"); 113c19800e8SDoug Rabson goto out; 114c19800e8SDoug Rabson } 115c19800e8SDoug Rabson 116*ae771770SStanislav Sedov if ((size_t)hex_decode(opt->password_string, data, len) != len) { 117c19800e8SDoug Rabson free(data); 118c19800e8SDoug Rabson krb5_warn(context, ENOMEM, "hex decode failed"); 119c19800e8SDoug Rabson goto out; 120c19800e8SDoug Rabson } 121c19800e8SDoug Rabson 122c19800e8SDoug Rabson ret = krb5_keyblock_init(context, enctype, 123c19800e8SDoug Rabson data, len, &entry.keyblock); 124c19800e8SDoug Rabson free(data); 125c19800e8SDoug Rabson } else if (!opt->salt_flag) { 126b528cefcSMark Murray krb5_salt salt; 127b528cefcSMark Murray krb5_data pw; 128b528cefcSMark Murray 129b528cefcSMark Murray salt.salttype = KRB5_PW_SALT; 130b528cefcSMark Murray salt.saltvalue.data = NULL; 131b528cefcSMark Murray salt.saltvalue.length = 0; 132c19800e8SDoug Rabson pw.data = (void*)opt->password_string; 133c19800e8SDoug Rabson pw.length = strlen(opt->password_string); 134c19800e8SDoug Rabson ret = krb5_string_to_key_data_salt(context, enctype, pw, salt, 135b528cefcSMark Murray &entry.keyblock); 136b528cefcSMark Murray } else { 137c19800e8SDoug Rabson ret = krb5_string_to_key(context, enctype, opt->password_string, 138b528cefcSMark Murray entry.principal, &entry.keyblock); 139b528cefcSMark Murray } 140c19800e8SDoug Rabson memset (opt->password_string, 0, strlen(opt->password_string)); 141b528cefcSMark Murray } else { 142c19800e8SDoug Rabson ret = krb5_generate_random_keyblock(context, enctype, &entry.keyblock); 143b528cefcSMark Murray } 144c19800e8SDoug Rabson if(ret) { 145c19800e8SDoug Rabson krb5_warn(context, ret, "add"); 146c19800e8SDoug Rabson goto out; 147c19800e8SDoug Rabson } 148c19800e8SDoug Rabson entry.vno = opt->kvno_integer; 149b528cefcSMark Murray entry.timestamp = time (NULL); 150b528cefcSMark Murray ret = krb5_kt_add_entry(context, keytab, &entry); 151b528cefcSMark Murray if(ret) 152b528cefcSMark Murray krb5_warn(context, ret, "add"); 153adb0ddaeSAssar Westerlund out: 154b528cefcSMark Murray krb5_kt_free_entry(context, &entry); 155adb0ddaeSAssar Westerlund krb5_kt_close(context, keytab); 156c19800e8SDoug Rabson return ret != 0; 157b528cefcSMark Murray } 158