155682Smarkm/* 2233294Sstas * Copyright (c) 1997-2004 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 955682Smarkm * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 1655682Smarkm * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 2055682Smarkm * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "headers.h" 3555682Smarkm 3655682Smarkmkrb5_context context; 3755682Smarkm 38178825Sdfrstatic char *keyfile; 39178825Sdfrstatic int convert_flag; 40178825Sdfrstatic int help_flag; 41178825Sdfrstatic int version_flag; 4255682Smarkm 43178825Sdfrstatic int master_key_fd = -1; 44178825Sdfrstatic int random_key_flag; 4572445Sassar 46178825Sdfrstatic const char *enctype_str = "des3-cbc-sha1"; 4772445Sassar 48178825Sdfrstatic struct getargs args[] = { 49233294Sstas { "enctype", 'e', arg_string, rk_UNCONST(&enctype_str), "encryption type", 50233294Sstas NULL }, 5155682Smarkm { "key-file", 'k', arg_string, &keyfile, "master key file", "file" }, 52233294Sstas { "convert-file", 0, arg_flag, &convert_flag, 53233294Sstas "just convert keyfile to new format", NULL }, 54233294Sstas { "master-key-fd", 0, arg_integer, &master_key_fd, 5572445Sassar "filedescriptor to read passphrase from", "fd" }, 56233294Sstas { "random-key", 0, arg_flag, &random_key_flag, 57233294Sstas "generate a random master key", NULL }, 58233294Sstas { "help", 'h', arg_flag, &help_flag, NULL, NULL }, 59233294Sstas { "version", 0, arg_flag, &version_flag, NULL, NULL } 6055682Smarkm}; 6155682Smarkm 6255682Smarkmint num_args = sizeof(args) / sizeof(args[0]); 6355682Smarkm 6455682Smarkmint 6555682Smarkmmain(int argc, char **argv) 6655682Smarkm{ 6755682Smarkm char buf[1024]; 6872445Sassar krb5_error_code ret; 69233294Sstas 7072445Sassar krb5_enctype enctype; 7172445Sassar 7272445Sassar hdb_master_key mkey; 73233294Sstas 7455682Smarkm krb5_program_setup(&context, argc, argv, args, num_args, NULL); 7555682Smarkm 7655682Smarkm if(help_flag) 7755682Smarkm krb5_std_usage(0, args, num_args); 7855682Smarkm if(version_flag){ 7955682Smarkm print_version(NULL); 8055682Smarkm exit(0); 8155682Smarkm } 8255682Smarkm 83178825Sdfr if (master_key_fd != -1 && random_key_flag) 84178825Sdfr krb5_errx(context, 1, "random-key and master-key-fd " 85178825Sdfr "is mutual exclusive"); 86178825Sdfr 87178825Sdfr if (keyfile == NULL) 88178825Sdfr asprintf(&keyfile, "%s/m-key", hdb_db_dir(context)); 89178825Sdfr 9072445Sassar ret = krb5_string_to_enctype(context, enctype_str, &enctype); 9172445Sassar if(ret) 9272445Sassar krb5_err(context, 1, ret, "krb5_string_to_enctype"); 9355682Smarkm 9472445Sassar ret = hdb_read_master_key(context, keyfile, &mkey); 9572445Sassar if(ret && ret != ENOENT) 9672445Sassar krb5_err(context, 1, ret, "reading master key from %s", keyfile); 9772445Sassar 9872445Sassar if (convert_flag) { 9972445Sassar if (ret) 10072445Sassar krb5_err(context, 1, ret, "reading master key from %s", keyfile); 10155682Smarkm } else { 10272445Sassar krb5_keyblock key; 10355682Smarkm krb5_salt salt; 10455682Smarkm salt.salttype = KRB5_PW_SALT; 10555682Smarkm /* XXX better value? */ 10655682Smarkm salt.saltvalue.data = NULL; 10755682Smarkm salt.saltvalue.length = 0; 108178825Sdfr if (random_key_flag) { 109178825Sdfr ret = krb5_generate_random_keyblock(context, enctype, &key); 110178825Sdfr if (ret) 111178825Sdfr krb5_err(context, 1, ret, "krb5_generate_random_keyblock"); 112178825Sdfr 11372445Sassar } else { 114178825Sdfr if(master_key_fd != -1) { 115178825Sdfr ssize_t n; 116178825Sdfr n = read(master_key_fd, buf, sizeof(buf)); 117178825Sdfr if(n <= 0) 118178825Sdfr krb5_err(context, 1, errno, "failed to read passphrase"); 119178825Sdfr buf[n] = '\0'; 120178825Sdfr buf[strcspn(buf, "\r\n")] = '\0'; 121233294Sstas 122178825Sdfr } else { 123178825Sdfr if(UI_UTIL_read_pw_string(buf, sizeof(buf), "Master key: ", 1)) 124178825Sdfr exit(1); 125178825Sdfr } 126178825Sdfr krb5_string_to_key_salt(context, enctype, buf, salt, &key); 12772445Sassar } 12872445Sassar ret = hdb_add_master_key(context, &key, &mkey); 129233294Sstas 13072445Sassar krb5_free_keyblock_contents(context, &key); 13172445Sassar 13255682Smarkm } 133233294Sstas 13472445Sassar { 13572445Sassar char *new, *old; 13672445Sassar asprintf(&old, "%s.old", keyfile); 13772445Sassar asprintf(&new, "%s.new", keyfile); 13872445Sassar if(unlink(new) < 0 && errno != ENOENT) { 13972445Sassar ret = errno; 14072445Sassar goto out; 14172445Sassar } 14272445Sassar krb5_warnx(context, "writing key to `%s'", keyfile); 14372445Sassar ret = hdb_write_master_key(context, new, mkey); 14472445Sassar if(ret) 14572445Sassar unlink(new); 14672445Sassar else { 147233294Sstas#ifndef NO_POSIX_LINKS 14872445Sassar unlink(old); 14972445Sassar if(link(keyfile, old) < 0 && errno != ENOENT) { 15072445Sassar ret = errno; 15172445Sassar unlink(new); 152233294Sstas } else { 153233294Sstas#endif 154233294Sstas if(rename(new, keyfile) < 0) { 155233294Sstas ret = errno; 156233294Sstas } 157233294Sstas#ifndef NO_POSIX_LINKS 15872445Sassar } 159233294Sstas#endif 16072445Sassar } 16172445Sassar out: 16272445Sassar free(old); 16372445Sassar free(new); 16472445Sassar if(ret) 16572445Sassar krb5_warn(context, errno, "writing master key file"); 16672445Sassar } 16772445Sassar 16872445Sassar hdb_free_master_key(context, mkey); 16972445Sassar 17072445Sassar exit(ret != 0); 17155682Smarkm} 172