1 /* $NetBSD: stash.c,v 1.1.1.2 2014/04/24 12:45:27 pettai Exp $ */ 2 3 /* 4 * Copyright (c) 2004 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * 3. Neither the name of the Institute nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 26 * 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 INSTITUTE OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 */ 37 38 #include "kadmin_locl.h" 39 #include "kadmin-commands.h" 40 41 extern int local_flag; 42 43 int 44 stash(struct stash_options *opt, int argc, char **argv) 45 { 46 char buf[1024]; 47 krb5_error_code ret; 48 krb5_enctype enctype; 49 hdb_master_key mkey; 50 51 if(!local_flag) { 52 krb5_warnx(context, "stash is only available in local (-l) mode"); 53 return 0; 54 } 55 56 ret = krb5_string_to_enctype(context, opt->enctype_string, &enctype); 57 if(ret) { 58 krb5_warn(context, ret, "%s", opt->enctype_string); 59 return 0; 60 } 61 62 if(opt->key_file_string == NULL) { 63 asprintf(&opt->key_file_string, "%s/m-key", hdb_db_dir(context)); 64 if (opt->key_file_string == NULL) 65 errx(1, "out of memory"); 66 } 67 68 ret = hdb_read_master_key(context, opt->key_file_string, &mkey); 69 if(ret && ret != ENOENT) { 70 krb5_warn(context, ret, "reading master key from %s", 71 opt->key_file_string); 72 return 0; 73 } 74 75 if (opt->convert_file_flag) { 76 if (ret) 77 krb5_warn(context, ret, "reading master key from %s", 78 opt->key_file_string); 79 return 0; 80 } else { 81 krb5_keyblock key; 82 krb5_salt salt; 83 salt.salttype = KRB5_PW_SALT; 84 /* XXX better value? */ 85 salt.saltvalue.data = NULL; 86 salt.saltvalue.length = 0; 87 if(opt->master_key_fd_integer != -1) { 88 ssize_t n; 89 n = read(opt->master_key_fd_integer, buf, sizeof(buf)); 90 if(n == 0) 91 krb5_warnx(context, "end of file reading passphrase"); 92 else if(n < 0) { 93 krb5_warn(context, errno, "reading passphrase"); 94 n = 0; 95 } 96 buf[n] = '\0'; 97 buf[strcspn(buf, "\r\n")] = '\0'; 98 } else if (opt->random_password_flag) { 99 random_password (buf, sizeof(buf)); 100 printf("Using random master stash password: %s\n", buf); 101 } else { 102 if(UI_UTIL_read_pw_string(buf, sizeof(buf), "Master key: ", 1)) { 103 hdb_free_master_key(context, mkey); 104 return 0; 105 } 106 } 107 ret = krb5_string_to_key_salt(context, enctype, buf, salt, &key); 108 ret = hdb_add_master_key(context, &key, &mkey); 109 krb5_free_keyblock_contents(context, &key); 110 } 111 112 { 113 char *new, *old; 114 asprintf(&old, "%s.old", opt->key_file_string); 115 asprintf(&new, "%s.new", opt->key_file_string); 116 if(old == NULL || new == NULL) { 117 ret = ENOMEM; 118 goto out; 119 } 120 121 if(unlink(new) < 0 && errno != ENOENT) { 122 ret = errno; 123 goto out; 124 } 125 krb5_warnx(context, "writing key to \"%s\"", opt->key_file_string); 126 ret = hdb_write_master_key(context, new, mkey); 127 if(ret) 128 unlink(new); 129 else { 130 unlink(old); 131 #ifndef NO_POSIX_LINKS 132 if(link(opt->key_file_string, old) < 0 && errno != ENOENT) { 133 ret = errno; 134 unlink(new); 135 } else { 136 #endif 137 if(rename(new, opt->key_file_string) < 0) { 138 ret = errno; 139 } 140 #ifndef NO_POSIX_LINKS 141 } 142 #endif 143 } 144 out: 145 free(old); 146 free(new); 147 if(ret) 148 krb5_warn(context, errno, "writing master key file"); 149 } 150 151 hdb_free_master_key(context, mkey); 152 return 0; 153 } 154