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