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