xref: /netbsd/crypto/external/bsd/heimdal/dist/admin/add.c (revision 25596981)
1 /*	$NetBSD: add.c,v 1.3 2023/06/19 21:41:38 christos 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: add.c,v 1.3 2023/06/19 21:41:38 christos Exp $");
39 
40 static char *
readstring(const char * prompt,char * buf,size_t len)41 readstring(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 
50 int
kt_add(struct add_options * opt,int argc,char ** argv)51 kt_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: ",
100 				  UI_UTIL_FLAG_VERIFY)) {
101 	    ret = 1;
102 	    goto out;
103 	}
104 	opt->password_string = buf;
105     }
106     if(opt->password_string) {
107 	if (opt->hex_flag) {
108 	    size_t len;
109 	    void *data;
110 
111 	    len = (strlen(opt->password_string) + 1) / 2;
112 
113 	    data = malloc(len);
114 	    if (data == NULL) {
115 		krb5_warn(context, ENOMEM, "malloc");
116 		goto out;
117 	    }
118 
119 	    if ((size_t)hex_decode(opt->password_string, data, len) != len) {
120 		free(data);
121 		krb5_warn(context, ENOMEM, "hex decode failed");
122 		goto out;
123 	    }
124 
125 	    ret = krb5_keyblock_init(context, enctype,
126 				     data, len, &entry.keyblock);
127 	    free(data);
128 	} else if (!opt->salt_flag) {
129 	    krb5_salt salt;
130 	    krb5_data pw;
131 
132 	    salt.salttype         = KRB5_PW_SALT;
133 	    salt.saltvalue.data   = NULL;
134 	    salt.saltvalue.length = 0;
135 	    pw.data = (void*)opt->password_string;
136 	    pw.length = strlen(opt->password_string);
137 	    ret = krb5_string_to_key_data_salt(context, enctype, pw, salt,
138 					       &entry.keyblock);
139         } else {
140 	    ret = krb5_string_to_key(context, enctype, opt->password_string,
141 				     entry.principal, &entry.keyblock);
142 	}
143 	memset (opt->password_string, 0, strlen(opt->password_string));
144     } else {
145 	ret = krb5_generate_random_keyblock(context, enctype, &entry.keyblock);
146     }
147     if(ret) {
148 	krb5_warn(context, ret, "add");
149 	goto out;
150     }
151     entry.vno = opt->kvno_integer;
152     entry.timestamp = time (NULL);
153     ret = krb5_kt_add_entry(context, keytab, &entry);
154     if(ret)
155 	krb5_warn(context, ret, "add");
156  out:
157     krb5_kt_free_entry(context, &entry);
158     krb5_kt_close(context, keytab);
159     return ret != 0;
160 }
161