1 /* $NetBSD: stash.c,v 1.2 2017/01/28 21:31:44 christos 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+1]; 47 krb5_error_code ret; 48 krb5_enctype enctype; 49 hdb_master_key mkey; 50 int aret; 51 52 if(!local_flag) { 53 krb5_warnx(context, "stash is only available in local (-l) mode"); 54 return 0; 55 } 56 57 ret = krb5_string_to_enctype(context, opt->enctype_string, &enctype); 58 if(ret) { 59 krb5_warn(context, ret, "%s", opt->enctype_string); 60 return 0; 61 } 62 63 if(opt->key_file_string == NULL) { 64 aret = asprintf(&opt->key_file_string, "%s/m-key", hdb_db_dir(context)); 65 if (aret == -1) 66 errx(1, "out of memory"); 67 } 68 69 ret = hdb_read_master_key(context, opt->key_file_string, &mkey); 70 if(ret && ret != ENOENT) { 71 krb5_warn(context, ret, "reading master key from %s", 72 opt->key_file_string); 73 return 0; 74 } 75 76 if (opt->convert_file_flag) { 77 if (ret) 78 krb5_warn(context, ret, "reading master key from %s", 79 opt->key_file_string); 80 hdb_free_master_key(context, mkey); 81 return 0; 82 } else { 83 krb5_keyblock key; 84 krb5_salt salt; 85 salt.salttype = KRB5_PW_SALT; 86 /* XXX better value? */ 87 salt.saltvalue.data = NULL; 88 salt.saltvalue.length = 0; 89 if(opt->master_key_fd_integer != -1) { 90 ssize_t n; 91 n = read(opt->master_key_fd_integer, buf, sizeof(buf)-1); 92 if(n == 0) 93 krb5_warnx(context, "end of file reading passphrase"); 94 else if(n < 0) { 95 krb5_warn(context, errno, "reading passphrase"); 96 n = 0; 97 } 98 buf[n] = '\0'; 99 buf[strcspn(buf, "\r\n")] = '\0'; 100 } else if (opt->random_password_flag) { 101 random_password (buf, sizeof(buf)); 102 printf("Using random master stash password: %s\n", buf); 103 } else { 104 if(UI_UTIL_read_pw_string(buf, sizeof(buf), "Master key: ", 1)) { 105 hdb_free_master_key(context, mkey); 106 return 0; 107 } 108 } 109 ret = krb5_string_to_key_salt(context, enctype, buf, salt, &key); 110 ret = hdb_add_master_key(context, &key, &mkey); 111 krb5_free_keyblock_contents(context, &key); 112 } 113 114 { 115 char *new = NULL, *old = NULL; 116 117 aret = asprintf(&old, "%s.old", opt->key_file_string); 118 if (aret == -1) { 119 ret = ENOMEM; 120 goto out; 121 } 122 aret = asprintf(&new, "%s.new", opt->key_file_string); 123 if (aret == -1) { 124 ret = ENOMEM; 125 goto out; 126 } 127 128 if(unlink(new) < 0 && errno != ENOENT) { 129 ret = errno; 130 goto out; 131 } 132 krb5_warnx(context, "writing key to \"%s\"", opt->key_file_string); 133 ret = hdb_write_master_key(context, new, mkey); 134 if(ret) 135 unlink(new); 136 else { 137 unlink(old); 138 #ifndef NO_POSIX_LINKS 139 if(link(opt->key_file_string, old) < 0 && errno != ENOENT) { 140 ret = errno; 141 unlink(new); 142 } else { 143 #endif 144 if(rename(new, opt->key_file_string) < 0) { 145 ret = errno; 146 } 147 #ifndef NO_POSIX_LINKS 148 } 149 #endif 150 } 151 out: 152 free(old); 153 free(new); 154 if(ret) 155 krb5_warn(context, errno, "writing master key file"); 156 } 157 158 hdb_free_master_key(context, mkey); 159 return 0; 160 } 161