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