1 /* $NetBSD: krb5_passwd.c,v 1.12 2004/10/05 14:12:56 lha Exp $ */ 2 3 /* 4 * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to 8 * The NetBSD Foundation by Johan Danielsson. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * 3. Neither the name of The NetBSD Foundation nor the names of its 22 * contributors may be used to endorse or promote products derived 23 * from this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 /* uses the `Kerberos Change Password Protocol' */ 39 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <string.h> 43 #include <err.h> 44 #include <pwd.h> 45 46 #include <openssl/ui.h> 47 #include <krb5.h> 48 49 #include "extern.h" 50 51 static krb5_context context; 52 static krb5_principal defprinc; 53 static int usage = PW_USE; 54 55 int 56 krb5_init(const char *progname) 57 { 58 return krb5_init_context(&context); 59 } 60 61 int 62 krb5_arg (char ch, const char *optarg) 63 { 64 krb5_error_code ret; 65 switch(ch) { 66 case '5': 67 case 'k': 68 usage = PW_USE_FORCE; 69 return 1; 70 case 'u': 71 ret = krb5_parse_name(context, optarg, &defprinc); 72 if(ret) { 73 krb5_warn(context, ret, "%s", optarg); 74 return 0; 75 } 76 return 1; 77 } 78 return 0; 79 } 80 81 int 82 krb5_arg_end(void) 83 { 84 return usage; 85 } 86 87 void 88 krb5_end(void) 89 { 90 if (context == NULL) 91 return; 92 if(defprinc) 93 krb5_free_principal(context, defprinc); 94 krb5_free_context(context); 95 } 96 97 98 int 99 krb5_chpw(const char *username) 100 { 101 krb5_error_code ret; 102 krb5_context context; 103 krb5_principal principal; 104 krb5_get_init_creds_opt opt; 105 krb5_creds cred; 106 int result_code; 107 krb5_data result_code_string, result_string; 108 char pwbuf[BUFSIZ]; 109 110 ret = krb5_init_context (&context); 111 if (ret) { 112 warnx("failed kerberos initialisation: %s", 113 krb5_get_err_text(context, ret)); 114 return 1; 115 } 116 117 krb5_get_init_creds_opt_init (&opt); 118 119 krb5_get_init_creds_opt_set_tkt_life (&opt, 300); 120 krb5_get_init_creds_opt_set_forwardable (&opt, FALSE); 121 krb5_get_init_creds_opt_set_proxiable (&opt, FALSE); 122 123 if(username != NULL) { 124 ret = krb5_parse_name (context, username, &principal); 125 if (ret) { 126 warnx("failed to parse principal: %s", 127 krb5_get_err_text(context, ret)); 128 return 1; 129 } 130 } else 131 principal = defprinc; 132 133 ret = krb5_get_init_creds_password (context, 134 &cred, 135 principal, 136 NULL, 137 krb5_prompter_posix, 138 NULL, 139 0, 140 "kadmin/changepw", 141 &opt); 142 143 switch (ret) { 144 case 0: 145 break; 146 case KRB5_LIBOS_PWDINTR : 147 /* XXX */ 148 return 1; 149 case KRB5KRB_AP_ERR_BAD_INTEGRITY : 150 case KRB5KRB_AP_ERR_MODIFIED : 151 fprintf(stderr, "Password incorrect\n"); 152 return 1; 153 break; 154 default: 155 warnx("failed to get credentials: %s", 156 krb5_get_err_text(context, ret)); 157 return 1; 158 } 159 krb5_data_zero (&result_code_string); 160 krb5_data_zero (&result_string); 161 162 /* XXX use getpass? It has a broken interface. */ 163 if(UI_UTIL_read_pw_string(pwbuf, sizeof(pwbuf), "New password: ", 1) != 0) 164 return 1; 165 166 ret = krb5_set_password (context, &cred, pwbuf, NULL, 167 &result_code, 168 &result_code_string, 169 &result_string); 170 if (ret) 171 krb5_err (context, 1, ret, "krb5_set_password"); 172 173 printf ("%s%s%.*s\n", krb5_passwd_result_to_string(context, result_code), 174 result_string.length > 0 ? " : " : "", 175 (int)result_string.length, 176 result_string.length > 0 ? (char *)result_string.data : ""); 177 178 krb5_data_free (&result_code_string); 179 krb5_data_free (&result_string); 180 181 krb5_free_creds_contents (context, &cred); 182 krb5_free_context (context); 183 return result_code; 184 } 185