1/*
2 * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the Institute nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "kadmin_locl.h"
35#include "kadmin-commands.h"
36
37struct cpw_entry_data {
38    int keepold;
39    int random_key;
40    int random_password;
41    char *password;
42    krb5_key_data *key_data;
43};
44
45static int
46set_random_key (krb5_principal principal, int keepold)
47{
48    krb5_error_code ret;
49    int i;
50    krb5_keyblock *keys;
51    int num_keys;
52
53    ret = kadm5_randkey_principal_3(kadm_handle, principal, keepold, 0, NULL,
54				    &keys, &num_keys);
55    if(ret)
56	return ret;
57    for(i = 0; i < num_keys; i++)
58	krb5_free_keyblock_contents(context, &keys[i]);
59    free(keys);
60    return 0;
61}
62
63static int
64set_random_password (krb5_principal principal, int keepold)
65{
66    krb5_error_code ret;
67    char pw[128];
68
69    random_password (pw, sizeof(pw));
70    ret = kadm5_chpass_principal_3(kadm_handle, principal, keepold, 0, NULL, pw);
71    if (ret == 0) {
72	char *princ_name;
73
74	krb5_unparse_name(context, principal, &princ_name);
75
76	printf ("%s's password set to \"%s\"\n", princ_name, pw);
77	free (princ_name);
78    }
79    memset (pw, 0, sizeof(pw));
80    return ret;
81}
82
83static int
84set_password (krb5_principal principal, char *password, int keepold)
85{
86    krb5_error_code ret = 0;
87    char pwbuf[128];
88
89    if(password == NULL) {
90	char *princ_name;
91	char *prompt;
92
93	krb5_unparse_name(context, principal, &princ_name);
94	asprintf(&prompt, "%s's Password: ", princ_name);
95	free (princ_name);
96	ret = UI_UTIL_read_pw_string_stdio(pwbuf, sizeof(pwbuf), prompt, 1);
97	free (prompt);
98	if(ret){
99	    return 0; /* XXX error code? */
100	}
101	password = pwbuf;
102    }
103    if(ret == 0)
104	ret = kadm5_chpass_principal_3(kadm_handle, principal, keepold, 0, NULL,
105				       password);
106    memset(pwbuf, 0, sizeof(pwbuf));
107    return ret;
108}
109
110static int
111set_key_data (krb5_principal principal, krb5_key_data *key_data, int keepold)
112{
113    krb5_error_code ret;
114
115    ret = kadm5_chpass_principal_with_key_3(kadm_handle, principal, keepold,
116					    3, key_data);
117    return ret;
118}
119
120static int
121do_cpw_entry(krb5_principal principal, void *data)
122{
123    struct cpw_entry_data *e = data;
124
125    if (e->random_key)
126	return set_random_key (principal, e->keepold);
127    else if (e->random_password)
128	return set_random_password (principal, e->keepold);
129    else if (e->key_data)
130	return set_key_data (principal, e->key_data, e->keepold);
131    else
132	return set_password (principal, e->password, e->keepold);
133}
134
135int
136cpw_entry(struct passwd_options *opt, int argc, char **argv)
137{
138    krb5_error_code ret = 0;
139    int i;
140    struct cpw_entry_data data;
141    int num;
142    krb5_key_data key_data[3];
143
144    data.keepold = opt->keepold_flag;
145    data.random_key = opt->random_key_flag;
146    data.random_password = opt->random_password_flag;
147    data.password = opt->password_string;
148    data.key_data	 = NULL;
149
150    num = 0;
151    if (data.random_key)
152	++num;
153    if (data.random_password)
154	++num;
155    if (data.password)
156	++num;
157    if (opt->key_string)
158	++num;
159
160    if (num > 1) {
161	fprintf (stderr, "give only one of "
162		"--random-key, --random-password, --password, --key\n");
163	return 1;
164    }
165
166    if (opt->key_string) {
167	const char *error;
168
169	if (parse_des_key (opt->key_string, key_data, &error)) {
170	    fprintf (stderr, "failed parsing key \"%s\": %s\n",
171		     opt->key_string, error);
172	    return 1;
173	}
174	data.key_data = key_data;
175    }
176
177    for(i = 0; i < argc; i++)
178	ret = foreach_principal(argv[i], do_cpw_entry, "cpw", &data);
179
180    if (data.key_data) {
181	int16_t dummy;
182	kadm5_free_key_data (kadm_handle, &dummy, key_data);
183    }
184
185    return ret != 0;
186}
187