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
37RCSID("$Id: cpw.c 16755 2006-02-18 23:30:32Z lha $");
38
39struct cpw_entry_data {
40    int random_key;
41    int random_password;
42    char *password;
43    krb5_key_data *key_data;
44};
45
46static int
47set_random_key (krb5_principal principal)
48{
49    krb5_error_code ret;
50    int i;
51    krb5_keyblock *keys;
52    int num_keys;
53
54    ret = kadm5_randkey_principal(kadm_handle, principal, &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)
65{
66    krb5_error_code ret;
67    char pw[128];
68
69    random_password (pw, sizeof(pw));
70    ret = kadm5_chpass_principal(kadm_handle, principal, 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)
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(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(kadm_handle, principal, password);
105    memset(pwbuf, 0, sizeof(pwbuf));
106    return ret;
107}
108
109static int
110set_key_data (krb5_principal principal, krb5_key_data *key_data)
111{
112    krb5_error_code ret;
113
114    ret = kadm5_chpass_principal_with_key (kadm_handle, principal,
115					   3, key_data);
116    return ret;
117}
118
119static int
120do_cpw_entry(krb5_principal principal, void *data)
121{
122    struct cpw_entry_data *e = data;
123
124    if (e->random_key)
125	return set_random_key (principal);
126    else if (e->random_password)
127	return set_random_password (principal);
128    else if (e->key_data)
129	return set_key_data (principal, e->key_data);
130    else
131	return set_password (principal, e->password);
132}
133
134int
135cpw_entry(struct passwd_options *opt, int argc, char **argv)
136{
137    krb5_error_code ret = 0;
138    int i;
139    struct cpw_entry_data data;
140    int num;
141    krb5_key_data key_data[3];
142
143    data.random_key = opt->random_key_flag;
144    data.random_password = opt->random_password_flag;
145    data.password = opt->password_string;
146    data.key_data	 = NULL;
147
148    num = 0;
149    if (data.random_key)
150	++num;
151    if (data.random_password)
152	++num;
153    if (data.password)
154	++num;
155    if (opt->key_string)
156	++num;
157
158    if (num > 1) {
159	fprintf (stderr, "give only one of "
160		"--random-key, --random-password, --password, --key\n");
161	return 1;
162    }
163
164    if (opt->key_string) {
165	const char *error;
166
167	if (parse_des_key (opt->key_string, key_data, &error)) {
168	    fprintf (stderr, "failed parsing key \"%s\": %s\n",
169		     opt->key_string, error);
170	    return 1;
171	}
172	data.key_data = key_data;
173    }
174
175    for(i = 0; i < argc; i++)
176	ret = foreach_principal(argv[i], do_cpw_entry, "cpw", &data);
177
178    if (data.key_data) {
179	int16_t dummy;
180	kadm5_free_key_data (kadm_handle, &dummy, key_data);
181    }
182
183    return ret != 0;
184}
185