1b528cefcSMark Murray /*
2*ae771770SStanislav Sedov * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray * All rights reserved.
5b528cefcSMark Murray *
6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray * modification, are permitted provided that the following conditions
8b528cefcSMark Murray * are met:
9b528cefcSMark Murray *
10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray *
13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray * documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray *
17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray * may be used to endorse or promote products derived from this software
19b528cefcSMark Murray * without specific prior written permission.
20b528cefcSMark Murray *
21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray * SUCH DAMAGE.
32b528cefcSMark Murray */
33b528cefcSMark Murray
34b528cefcSMark Murray #include "kpasswd_locl.h"
35*ae771770SStanislav Sedov RCSID("$Id$");
36b528cefcSMark Murray
37b528cefcSMark Murray static int version_flag;
38b528cefcSMark Murray static int help_flag;
39c19800e8SDoug Rabson static char *admin_principal_str;
40c19800e8SDoug Rabson static char *cred_cache_str;
41b528cefcSMark Murray
42b528cefcSMark Murray static struct getargs args[] = {
43*ae771770SStanislav Sedov { "admin-principal", 0, arg_string, &admin_principal_str, NULL,
44*ae771770SStanislav Sedov NULL },
45*ae771770SStanislav Sedov { "cache", 'c', arg_string, &cred_cache_str, NULL, NULL },
46*ae771770SStanislav Sedov { "version", 0, arg_flag, &version_flag, NULL, NULL },
47*ae771770SStanislav Sedov { "help", 0, arg_flag, &help_flag, NULL, NULL }
48b528cefcSMark Murray };
49b528cefcSMark Murray
50b528cefcSMark Murray static void
usage(int ret,struct getargs * a,int num_args)515e9cd1aeSAssar Westerlund usage (int ret, struct getargs *a, int num_args)
52b528cefcSMark Murray {
53c19800e8SDoug Rabson arg_printusage (a, num_args, NULL, "[principal ...]");
54b528cefcSMark Murray exit (ret);
55b528cefcSMark Murray }
56b528cefcSMark Murray
57c19800e8SDoug Rabson static int
change_password(krb5_context context,krb5_principal principal,krb5_ccache id)58c19800e8SDoug Rabson change_password(krb5_context context,
59c19800e8SDoug Rabson krb5_principal principal,
60c19800e8SDoug Rabson krb5_ccache id)
61c19800e8SDoug Rabson {
62c19800e8SDoug Rabson krb5_data result_code_string, result_string;
63c19800e8SDoug Rabson int result_code;
64c19800e8SDoug Rabson krb5_error_code ret;
65c19800e8SDoug Rabson char pwbuf[BUFSIZ];
66c19800e8SDoug Rabson char *msg, *name;
67c19800e8SDoug Rabson
68c19800e8SDoug Rabson krb5_data_zero (&result_code_string);
69c19800e8SDoug Rabson krb5_data_zero (&result_string);
70c19800e8SDoug Rabson
71c19800e8SDoug Rabson name = msg = NULL;
72c19800e8SDoug Rabson if (principal == NULL)
73c19800e8SDoug Rabson asprintf(&msg, "New password: ");
74c19800e8SDoug Rabson else {
75c19800e8SDoug Rabson ret = krb5_unparse_name(context, principal, &name);
76c19800e8SDoug Rabson if (ret)
77c19800e8SDoug Rabson krb5_err(context, 1, ret, "krb5_unparse_name");
78c19800e8SDoug Rabson
79c19800e8SDoug Rabson asprintf(&msg, "New password for %s: ", name);
80c19800e8SDoug Rabson }
81c19800e8SDoug Rabson
82c19800e8SDoug Rabson if (msg == NULL)
83c19800e8SDoug Rabson krb5_errx (context, 1, "out of memory");
84c19800e8SDoug Rabson
85c19800e8SDoug Rabson ret = UI_UTIL_read_pw_string (pwbuf, sizeof(pwbuf), msg, 1);
86c19800e8SDoug Rabson free(msg);
87c19800e8SDoug Rabson if (name)
88c19800e8SDoug Rabson free(name);
89c19800e8SDoug Rabson if (ret != 0) {
90c19800e8SDoug Rabson return 1;
91c19800e8SDoug Rabson }
92c19800e8SDoug Rabson
93c19800e8SDoug Rabson ret = krb5_set_password_using_ccache (context, id, pwbuf,
94c19800e8SDoug Rabson principal,
95c19800e8SDoug Rabson &result_code,
96c19800e8SDoug Rabson &result_code_string,
97c19800e8SDoug Rabson &result_string);
98c19800e8SDoug Rabson if (ret) {
99c19800e8SDoug Rabson krb5_warn (context, ret, "krb5_set_password_using_ccache");
100c19800e8SDoug Rabson return 1;
101c19800e8SDoug Rabson }
102c19800e8SDoug Rabson
103c19800e8SDoug Rabson printf ("%s%s%.*s\n", krb5_passwd_result_to_string(context, result_code),
104c19800e8SDoug Rabson result_string.length > 0 ? " : " : "",
105c19800e8SDoug Rabson (int)result_string.length,
106c19800e8SDoug Rabson result_string.length > 0 ? (char *)result_string.data : "");
107c19800e8SDoug Rabson
108c19800e8SDoug Rabson krb5_data_free (&result_code_string);
109c19800e8SDoug Rabson krb5_data_free (&result_string);
110c19800e8SDoug Rabson
111c19800e8SDoug Rabson return ret != 0;
112c19800e8SDoug Rabson }
113c19800e8SDoug Rabson
114c19800e8SDoug Rabson
115b528cefcSMark Murray int
main(int argc,char ** argv)116b528cefcSMark Murray main (int argc, char **argv)
117b528cefcSMark Murray {
118b528cefcSMark Murray krb5_error_code ret;
119b528cefcSMark Murray krb5_context context;
120b528cefcSMark Murray krb5_principal principal;
121c19800e8SDoug Rabson krb5_get_init_creds_opt *opt;
122c19800e8SDoug Rabson krb5_ccache id = NULL;
123c19800e8SDoug Rabson int exit_value;
124*ae771770SStanislav Sedov int optidx = 0;
125b528cefcSMark Murray
126*ae771770SStanislav Sedov setprogname(argv[0]);
127b528cefcSMark Murray
128*ae771770SStanislav Sedov if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
129*ae771770SStanislav Sedov usage(1, args, sizeof(args) / sizeof(args[0]));
130b528cefcSMark Murray if (help_flag)
1315e9cd1aeSAssar Westerlund usage(0, args, sizeof(args) / sizeof(args[0]));
132b528cefcSMark Murray if (version_flag) {
133b528cefcSMark Murray print_version(NULL);
134*ae771770SStanislav Sedov return 0;
135b528cefcSMark Murray }
136*ae771770SStanislav Sedov argc -= optidx;
137*ae771770SStanislav Sedov argv += optidx;
138b528cefcSMark Murray
139b528cefcSMark Murray ret = krb5_init_context (&context);
140b528cefcSMark Murray if (ret)
1415e9cd1aeSAssar Westerlund errx (1, "krb5_init_context failed: %d", ret);
142b528cefcSMark Murray
143c19800e8SDoug Rabson ret = krb5_get_init_creds_opt_alloc (context, &opt);
144c19800e8SDoug Rabson if (ret)
145c19800e8SDoug Rabson krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc");
146c19800e8SDoug Rabson
147c19800e8SDoug Rabson krb5_get_init_creds_opt_set_tkt_life (opt, 300);
148c19800e8SDoug Rabson krb5_get_init_creds_opt_set_forwardable (opt, FALSE);
149c19800e8SDoug Rabson krb5_get_init_creds_opt_set_proxiable (opt, FALSE);
150c19800e8SDoug Rabson
151c19800e8SDoug Rabson if (cred_cache_str) {
152c19800e8SDoug Rabson ret = krb5_cc_resolve(context, cred_cache_str, &id);
153c19800e8SDoug Rabson if (ret)
154c19800e8SDoug Rabson krb5_err (context, 1, ret, "krb5_cc_resolve");
155c19800e8SDoug Rabson } else {
156*ae771770SStanislav Sedov ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &id);
157c19800e8SDoug Rabson if (ret)
158*ae771770SStanislav Sedov krb5_err (context, 1, ret, "krb5_cc_new_unique");
159c19800e8SDoug Rabson }
160c19800e8SDoug Rabson
161c19800e8SDoug Rabson if (cred_cache_str == NULL) {
162c19800e8SDoug Rabson krb5_principal admin_principal = NULL;
163c19800e8SDoug Rabson krb5_creds cred;
164c19800e8SDoug Rabson
165c19800e8SDoug Rabson if (admin_principal_str) {
166c19800e8SDoug Rabson ret = krb5_parse_name (context, admin_principal_str,
167c19800e8SDoug Rabson &admin_principal);
168b528cefcSMark Murray if (ret)
169b528cefcSMark Murray krb5_err (context, 1, ret, "krb5_parse_name");
170c19800e8SDoug Rabson } else if (argc == 1) {
171c19800e8SDoug Rabson ret = krb5_parse_name (context, argv[0], &admin_principal);
172c19800e8SDoug Rabson if (ret)
173c19800e8SDoug Rabson krb5_err (context, 1, ret, "krb5_parse_name");
174c19800e8SDoug Rabson } else {
175c19800e8SDoug Rabson ret = krb5_get_default_principal (context, &admin_principal);
176c19800e8SDoug Rabson if (ret)
177c19800e8SDoug Rabson krb5_err (context, 1, ret, "krb5_get_default_principal");
178c19800e8SDoug Rabson }
179b528cefcSMark Murray
180b528cefcSMark Murray ret = krb5_get_init_creds_password (context,
181b528cefcSMark Murray &cred,
182c19800e8SDoug Rabson admin_principal,
183b528cefcSMark Murray NULL,
184b528cefcSMark Murray krb5_prompter_posix,
185b528cefcSMark Murray NULL,
186b528cefcSMark Murray 0,
187b528cefcSMark Murray "kadmin/changepw",
188c19800e8SDoug Rabson opt);
189b528cefcSMark Murray switch (ret) {
190b528cefcSMark Murray case 0:
191b528cefcSMark Murray break;
192b528cefcSMark Murray case KRB5_LIBOS_PWDINTR :
193b528cefcSMark Murray return 1;
194b528cefcSMark Murray case KRB5KRB_AP_ERR_BAD_INTEGRITY :
195b528cefcSMark Murray case KRB5KRB_AP_ERR_MODIFIED :
196b528cefcSMark Murray krb5_errx(context, 1, "Password incorrect");
197b528cefcSMark Murray break;
198b528cefcSMark Murray default:
199b528cefcSMark Murray krb5_err(context, 1, ret, "krb5_get_init_creds");
200b528cefcSMark Murray }
201b528cefcSMark Murray
202c19800e8SDoug Rabson krb5_get_init_creds_opt_free(context, opt);
203b528cefcSMark Murray
204c19800e8SDoug Rabson ret = krb5_cc_initialize(context, id, admin_principal);
205c19800e8SDoug Rabson krb5_free_principal(context, admin_principal);
206b528cefcSMark Murray if (ret)
207c19800e8SDoug Rabson krb5_err(context, 1, ret, "krb5_cc_initialize");
208b528cefcSMark Murray
209c19800e8SDoug Rabson ret = krb5_cc_store_cred(context, id, &cred);
210c19800e8SDoug Rabson if (ret)
211c19800e8SDoug Rabson krb5_err(context, 1, ret, "krb5_cc_store_cred");
212b528cefcSMark Murray
213c19800e8SDoug Rabson krb5_free_cred_contents (context, &cred);
214c19800e8SDoug Rabson }
215b528cefcSMark Murray
216c19800e8SDoug Rabson if (argc == 0) {
217c19800e8SDoug Rabson exit_value = change_password(context, NULL, id);
218c19800e8SDoug Rabson } else {
219c19800e8SDoug Rabson exit_value = 0;
220c19800e8SDoug Rabson
221c19800e8SDoug Rabson while (argc-- > 0) {
222c19800e8SDoug Rabson
223c19800e8SDoug Rabson ret = krb5_parse_name (context, argv[0], &principal);
224c19800e8SDoug Rabson if (ret)
225c19800e8SDoug Rabson krb5_err (context, 1, ret, "krb5_parse_name");
226c19800e8SDoug Rabson
227c19800e8SDoug Rabson ret = change_password(context, principal, id);
228c19800e8SDoug Rabson if (ret)
229c19800e8SDoug Rabson exit_value = 1;
230c19800e8SDoug Rabson krb5_free_principal(context, principal);
231c19800e8SDoug Rabson argv++;
232c19800e8SDoug Rabson }
233c19800e8SDoug Rabson }
234c19800e8SDoug Rabson
235c19800e8SDoug Rabson if (cred_cache_str == NULL) {
236c19800e8SDoug Rabson ret = krb5_cc_destroy(context, id);
237c19800e8SDoug Rabson if (ret)
238c19800e8SDoug Rabson krb5_err (context, 1, ret, "krb5_cc_destroy");
239c19800e8SDoug Rabson } else {
240c19800e8SDoug Rabson ret = krb5_cc_close(context, id);
241c19800e8SDoug Rabson if (ret)
242c19800e8SDoug Rabson krb5_err (context, 1, ret, "krb5_cc_close");
243c19800e8SDoug Rabson }
244c19800e8SDoug Rabson
245b528cefcSMark Murray krb5_free_context (context);
246*ae771770SStanislav Sedov return exit_value;
247b528cefcSMark Murray }
248