1 /* $NetBSD: krb5_passwd.c,v 1.20 2012/04/22 23:43:51 christos Exp $ */
4 * Copyright (c) 2000, 2005 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Johan Danielsson; and by Jason R. Thorpe.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
33 /* uses the `Kerberos Change Password Protocol' */
43 #include <openssl/ui.h>
49 pwkrb5_warn(const char *msg
, krb5_context context
, krb5_error_code ret
)
51 const char *errtxt
= krb5_get_error_message(context
, ret
);
53 warnx("%s: %s", msg
, errtxt
);
54 krb5_free_error_message(context
, errtxt
);
56 warnx("%s: %d", msg
, ret
);
62 pwkrb5_usage(const char *prefix
)
65 (void) fprintf(stderr
, "%s %s [-d krb5 | -k] [principal]\n",
66 prefix
, getprogname());
70 pwkrb5_argv0_usage(const char *prefix
)
73 (void) fprintf(stderr
, "%s %s [principal]\n",
74 prefix
, getprogname());
78 pwkrb5_process(const char *username
, int argc
, char **argv
)
82 krb5_get_init_creds_opt
*opt
;
83 krb5_principal principal
;
86 krb5_data result_code_string
, result_string
;
90 while ((ch
= getopt(argc
, argv
, "5ku:")) != -1) {
94 * Compatibility option that historically
95 * specified to use Kerberos 5. Silently
102 * Absorb the -k that may have gotten us here.
108 * Historical option to specify principal.
124 /* username already provided */
127 /* overrides -u <principal> */
135 ret
= krb5_init_context(&context
);
138 errx(1, "Kerberos 5 not in use.");
139 errx(1, "Unable to initialize Kerberos 5: %s", strerror(ret
));
142 ret
= krb5_get_init_creds_opt_alloc(context
, &opt
);
144 pwkrb5_warn("failed to allocate opts", context
, ret
);
148 krb5_get_init_creds_opt_set_tkt_life(opt
, 300L);
149 krb5_get_init_creds_opt_set_forwardable(opt
, FALSE
);
150 krb5_get_init_creds_opt_set_proxiable(opt
, FALSE
);
152 ret
= krb5_parse_name(context
, username
, &principal
);
154 krb5_get_init_creds_opt_free(context
, opt
);
155 pwkrb5_warn("failed to parse principal", context
, ret
);
159 ret
= krb5_get_init_creds_password(context
,
169 krb5_get_init_creds_opt_free(context
, opt
);
174 case KRB5_LIBOS_PWDINTR
:
178 case KRB5KRB_AP_ERR_BAD_INTEGRITY
:
179 case KRB5KRB_AP_ERR_MODIFIED
:
180 fprintf(stderr
, "Password incorrect\n");
184 pwkrb5_warn("failed to get credentials", context
, ret
);
188 krb5_data_zero(&result_code_string
);
189 krb5_data_zero(&result_string
);
191 /* XXX use getpass? It has a broken interface. */
192 if (UI_UTIL_read_pw_string(pwbuf
, sizeof(pwbuf
),
193 "New password: ", 1) != 0)
196 ret
= krb5_set_password(context
, &cred
, pwbuf
, NULL
,
201 pwkrb5_warn("unable to set password", context
, ret
);
206 krb5_passwd_result_to_string(context
, result_code
),
207 result_string
.length
> 0 ? " : " : "",
208 (int)result_string
.length
,
209 result_string
.length
> 0 ? (char *)result_string
.data
: "");
211 krb5_data_free(&result_code_string
);
212 krb5_data_free(&result_string
);
214 krb5_free_cred_contents(context
, &cred
);
215 krb5_free_context(context
);
221 krb5_free_context(context
);
225 #else /* ! USE_PAM */
227 static krb5_context defcontext
;
228 static krb5_principal defprinc
;
229 static int kusage
= PW_USE
;
232 krb5_init(const char *progname
)
234 return krb5_init_context(&defcontext
);
238 krb5_arg (char ch
, const char *opt
)
244 kusage
= PW_USE_FORCE
;
247 ret
= krb5_parse_name(defcontext
, opt
, &defprinc
);
249 krb5_warn(defcontext
, ret
, "%s", opt
);
266 if (defcontext
== NULL
)
269 krb5_free_principal(defcontext
, defprinc
);
270 krb5_free_context(defcontext
);
274 krb5_chpw(const char *username
)
277 krb5_context context
;
278 krb5_principal principal
;
279 krb5_get_init_creds_opt
*opt
;
282 krb5_data result_code_string
, result_string
;
285 ret
= krb5_init_context (&context
);
287 pwkrb5_warn("failed kerberos initialisation", context
, ret
);
291 ret
= krb5_get_init_creds_opt_alloc (context
, &opt
);
293 pwkrb5_warn("failed to allocate credential opt", context
, ret
);
297 krb5_get_init_creds_opt_set_tkt_life (opt
, 300);
298 krb5_get_init_creds_opt_set_forwardable (opt
, FALSE
);
299 krb5_get_init_creds_opt_set_proxiable (opt
, FALSE
);
301 if(username
!= NULL
) {
302 ret
= krb5_parse_name (context
, username
, &principal
);
304 krb5_get_init_creds_opt_free (context
, opt
);
305 pwkrb5_warn("failed to parse principal", context
, ret
);
309 principal
= defprinc
;
311 ret
= krb5_get_init_creds_password (context
,
321 krb5_get_init_creds_opt_free (context
, opt
);
325 case KRB5_LIBOS_PWDINTR
:
328 case KRB5KRB_AP_ERR_BAD_INTEGRITY
:
329 case KRB5KRB_AP_ERR_MODIFIED
:
330 fprintf(stderr
, "Password incorrect\n");
334 pwkrb5_warn("failed to get credentials", context
, ret
);
337 krb5_data_zero (&result_code_string
);
338 krb5_data_zero (&result_string
);
340 /* XXX use getpass? It has a broken interface. */
341 if(UI_UTIL_read_pw_string(pwbuf
, sizeof(pwbuf
), "New password: ", 1) != 0)
344 ret
= krb5_set_password (context
, &cred
, pwbuf
, NULL
,
349 krb5_err (context
, 1, ret
, "krb5_set_password");
351 printf ("%s%s%.*s\n", krb5_passwd_result_to_string(context
, result_code
),
352 result_string
.length
> 0 ? " : " : "",
353 (int)result_string
.length
,
354 result_string
.length
> 0 ? (char *)result_string
.data
: "");
356 krb5_data_free (&result_code_string
);
357 krb5_data_free (&result_string
);
359 krb5_free_cred_contents (context
, &cred
);
360 krb5_free_context (context
);