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 "kpasswd_locl.h" 35 36static void usage (int ret, struct getargs *a, int num_args) __attribute__((noreturn)); 37 38 39static int version_flag; 40static int help_flag; 41static char *admin_principal_str; 42static char *cred_cache_str; 43 44static struct getargs args[] = { 45 { "admin-principal", 0, arg_string, &admin_principal_str, NULL, 46 NULL }, 47 { "cache", 'c', arg_string, &cred_cache_str, NULL, NULL }, 48 { "version", 0, arg_flag, &version_flag, NULL, NULL }, 49 { "help", 0, arg_flag, &help_flag, NULL, NULL } 50}; 51 52static void 53usage (int ret, struct getargs *a, int num_args) 54{ 55 arg_printusage (a, num_args, NULL, "[principal ...]"); 56 exit (ret); 57} 58 59static int 60change_password(krb5_context context, 61 krb5_principal principal, 62 krb5_ccache id) 63{ 64 krb5_data result_code_string, result_string; 65 int result_code; 66 krb5_error_code ret; 67 char pwbuf[BUFSIZ]; 68 char *msg, *name; 69 70 krb5_data_zero (&result_code_string); 71 krb5_data_zero (&result_string); 72 73 name = msg = NULL; 74 if (principal == NULL) 75 asprintf(&msg, "New password: "); 76 else { 77 ret = krb5_unparse_name(context, principal, &name); 78 if (ret) 79 krb5_err(context, 1, ret, "krb5_unparse_name"); 80 81 asprintf(&msg, "New password for %s: ", name); 82 } 83 84 if (msg == NULL) 85 krb5_errx (context, 1, "out of memory"); 86 87 ret = UI_UTIL_read_pw_string (pwbuf, sizeof(pwbuf), msg, 1); 88 free(msg); 89 if (name) 90 free(name); 91 if (ret != 0) { 92 return 1; 93 } 94 95 ret = krb5_set_password_using_ccache(context, id, pwbuf, 96 admin_principal_str ? principal : NULL, 97 &result_code, 98 &result_code_string, 99 &result_string); 100 if (ret) { 101 krb5_warn (context, ret, "krb5_set_password_using_ccache"); 102 return 1; 103 } 104 105 printf ("%s%s%.*s\n", krb5_passwd_result_to_string(context, result_code), 106 result_string.length > 0 ? " : " : "", 107 (int)result_string.length, 108 result_string.length > 0 ? (char *)result_string.data : ""); 109 110 krb5_data_free (&result_code_string); 111 krb5_data_free (&result_string); 112 113 return ret != 0; 114} 115 116 117int 118main (int argc, char **argv) 119{ 120 krb5_error_code ret; 121 krb5_context context; 122 krb5_principal principal; 123 int optidx = 0; 124 krb5_get_init_creds_opt *opt; 125 krb5_ccache id = NULL; 126 int exit_value; 127 128 setprogname (argv[0]); 129 130 ret = krb5_init_context (&context); 131 if (ret) 132 errx(1, "krb5_init_context failed: %d", ret); 133 134 if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) 135 usage(1, args, sizeof(args) / sizeof(args[0])); 136 if (help_flag) 137 usage(0, args, sizeof(args) / sizeof(args[0])); 138 if (version_flag) { 139 print_version(NULL); 140 return 0; 141 } 142 143 argc -= optidx; 144 argv += optidx; 145 146 ret = krb5_init_context (&context); 147 if (ret) 148 errx (1, "krb5_init_context failed: %d", ret); 149 150 ret = krb5_get_init_creds_opt_alloc (context, &opt); 151 if (ret) 152 krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc"); 153 154 krb5_get_init_creds_opt_set_tkt_life (opt, 300); 155 krb5_get_init_creds_opt_set_forwardable (opt, FALSE); 156 krb5_get_init_creds_opt_set_proxiable (opt, FALSE); 157 158 if (cred_cache_str) { 159 ret = krb5_cc_resolve(context, cred_cache_str, &id); 160 if (ret) 161 krb5_err (context, 1, ret, "krb5_cc_resolve"); 162 } else { 163 ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &id); 164 if (ret) 165 krb5_err (context, 1, ret, "krb5_cc_new_unique"); 166 } 167 168 if (cred_cache_str == NULL) { 169 krb5_principal admin_principal = NULL; 170 krb5_creds cred; 171 172 if (admin_principal_str) { 173 ret = krb5_parse_name (context, admin_principal_str, 174 &admin_principal); 175 if (ret) 176 krb5_err (context, 1, ret, "krb5_parse_name"); 177 } else if (argc == 1) { 178 ret = krb5_parse_name (context, argv[0], &admin_principal); 179 if (ret) 180 krb5_err (context, 1, ret, "krb5_parse_name"); 181 } else { 182 ret = krb5_get_default_principal (context, &admin_principal); 183 if (ret) 184 krb5_err (context, 1, ret, "krb5_get_default_principal"); 185 } 186 187 ret = krb5_get_init_creds_password (context, 188 &cred, 189 admin_principal, 190 NULL, 191 krb5_prompter_posix, 192 NULL, 193 0, 194 "kadmin/changepw", 195 opt); 196 switch (ret) { 197 case 0: 198 break; 199 case KRB5_LIBOS_PWDINTR : 200 return 1; 201 case KRB5KRB_AP_ERR_BAD_INTEGRITY : 202 case KRB5KRB_AP_ERR_MODIFIED : 203 krb5_errx(context, 1, "Password incorrect"); 204 default: 205 krb5_err(context, 1, ret, "krb5_get_init_creds"); 206 } 207 208 krb5_get_init_creds_opt_free(context, opt); 209 210 ret = krb5_cc_initialize(context, id, admin_principal); 211 krb5_free_principal(context, admin_principal); 212 if (ret) 213 krb5_err(context, 1, ret, "krb5_cc_initialize"); 214 215 ret = krb5_cc_store_cred(context, id, &cred); 216 if (ret) 217 krb5_err(context, 1, ret, "krb5_cc_store_cred"); 218 219 krb5_free_cred_contents (context, &cred); 220 } 221 222 if (argc == 0) { 223 exit_value = change_password(context, NULL, id); 224 } else { 225 exit_value = 0; 226 227 while (argc-- > 0) { 228 229 ret = krb5_parse_name (context, argv[0], &principal); 230 if (ret) 231 krb5_err (context, 1, ret, "krb5_parse_name"); 232 233 ret = change_password(context, principal, id); 234 if (ret) 235 exit_value = 1; 236 krb5_free_principal(context, principal); 237 argv++; 238 } 239 } 240 241 if (cred_cache_str == NULL) { 242 ret = krb5_cc_destroy(context, id); 243 if (ret) 244 krb5_err (context, 1, ret, "krb5_cc_destroy"); 245 } else { 246 ret = krb5_cc_close(context, id); 247 if (ret) 248 krb5_err (context, 1, ret, "krb5_cc_close"); 249 } 250 251 krb5_free_context (context); 252 return exit_value; 253} 254