1/*	$NetBSD: cpw.c,v 1.4 2023/06/19 21:41:41 christos Exp $	*/
2
3/*
4 * Copyright (c) 1997 - 2004 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 "kadmin_locl.h"
37#include "kadmin-commands.h"
38
39struct cpw_entry_data {
40    int keepold;
41    int random_key;
42    int random_password;
43    char *password;
44    krb5_key_data *key_data;
45};
46
47static int
48set_random_key (krb5_principal principal, int keepold)
49{
50    krb5_error_code ret;
51    int i;
52    krb5_keyblock *keys;
53    int num_keys;
54
55    ret = kadm5_randkey_principal_3(kadm_handle, principal, keepold, 0, NULL,
56				    &keys, &num_keys);
57    if(ret)
58	return ret;
59    for(i = 0; i < num_keys; i++)
60	krb5_free_keyblock_contents(context, &keys[i]);
61    free(keys);
62    return 0;
63}
64
65static int
66set_random_password (krb5_principal principal, int keepold)
67{
68    krb5_error_code ret;
69    char pw[128];
70
71    random_password (pw, sizeof(pw));
72    ret = kadm5_chpass_principal_3(kadm_handle, principal, keepold, 0, NULL, pw);
73    if (ret == 0) {
74	char *princ_name;
75
76	krb5_unparse_name(context, principal, &princ_name);
77
78	printf ("%s's password set to \"%s\"\n", princ_name, pw);
79	free (princ_name);
80    }
81    memset_s(pw, sizeof(pw), 0, sizeof(pw));
82    return ret;
83}
84
85static int
86set_password (krb5_principal principal, char *password, int keepold)
87{
88    krb5_error_code ret = 0;
89    char pwbuf[128];
90    int aret;
91
92    if(password == NULL) {
93	char *princ_name;
94	char *prompt;
95
96	ret = krb5_unparse_name(context, principal, &princ_name);
97	if (ret)
98	    return ret;
99	aret = asprintf(&prompt, "%s's Password: ", princ_name);
100	free (princ_name);
101	if (aret == -1)
102	    return ENOMEM;
103	ret = UI_UTIL_read_pw_string(pwbuf, sizeof(pwbuf), prompt,
104				     UI_UTIL_FLAG_VERIFY |
105				     UI_UTIL_FLAG_VERIFY_SILENT);
106	free (prompt);
107	if(ret){
108	    return 0; /* XXX error code? */
109	}
110	password = pwbuf;
111    }
112    if(ret == 0)
113	ret = kadm5_chpass_principal_3(kadm_handle, principal, keepold, 0, NULL,
114				       password);
115    memset_s(pwbuf, sizeof(pwbuf), 0, sizeof(pwbuf));
116    return ret;
117}
118
119static int
120set_key_data (krb5_principal principal, krb5_key_data *key_data, int keepold)
121{
122    krb5_error_code ret;
123
124    ret = kadm5_chpass_principal_with_key_3(kadm_handle, principal, keepold,
125					    3, key_data);
126    return ret;
127}
128
129static int
130do_cpw_entry(krb5_principal principal, void *data)
131{
132    struct cpw_entry_data *e = data;
133
134    if (e->random_key)
135	return set_random_key (principal, e->keepold);
136    else if (e->random_password)
137	return set_random_password (principal, e->keepold);
138    else if (e->key_data)
139	return set_key_data (principal, e->key_data, e->keepold);
140    else
141	return set_password (principal, e->password, e->keepold);
142}
143
144int
145cpw_entry(struct passwd_options *opt, int argc, char **argv)
146{
147    krb5_error_code ret = 0;
148    int i;
149    struct cpw_entry_data data;
150    int num;
151    krb5_key_data key_data[3];
152
153    data.keepold = opt->keepold_flag;
154    data.random_key = opt->random_key_flag;
155    data.random_password = opt->random_password_flag;
156    data.password = opt->password_string;
157    data.key_data	 = NULL;
158
159    num = 0;
160    if (data.random_key)
161	++num;
162    if (data.random_password)
163	++num;
164    if (data.password)
165	++num;
166    if (opt->key_string)
167	++num;
168
169    if (num > 1) {
170	fprintf (stderr, "give only one of "
171		"--random-key, --random-password, --password, --key\n");
172	return 1;
173    }
174
175    if (opt->key_string) {
176	const char *error;
177
178	if (parse_des_key (opt->key_string, key_data, &error)) {
179	    fprintf (stderr, "failed parsing key \"%s\": %s\n",
180		     opt->key_string, error);
181	    return 1;
182	}
183	data.key_data = key_data;
184    }
185
186    for(i = 0; i < argc; i++)
187	ret = foreach_principal(argv[i], do_cpw_entry, "cpw", &data);
188
189    if (data.key_data) {
190	int16_t dummy;
191	kadm5_free_key_data (kadm_handle, &dummy, key_data);
192    }
193
194    return ret != 0;
195}
196