1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 3 #include "k5-platform.h" 4 #include <locale.h> 5 #include <sys/types.h> 6 7 #ifndef _WIN32 8 #include <unistd.h> 9 #endif 10 11 #include <krb5.h> 12 13 #define P1 _("Enter new password") 14 #define P2 _("Enter it again") 15 16 #ifdef HAVE_PWD_H 17 #include <pwd.h> 18 19 static void 20 get_name_from_passwd_file(char *program_name, krb5_context context, 21 krb5_principal *me) 22 { 23 struct passwd *pw; 24 krb5_error_code ret; 25 26 pw = getpwuid(getuid()); 27 if (pw != NULL) { 28 ret = krb5_parse_name(context, pw->pw_name, me); 29 if (ret) { 30 com_err(program_name, ret, _("when parsing name %s"), pw->pw_name); 31 exit(1); 32 } 33 } else { 34 fprintf(stderr, _("Unable to identify user from password file\n")); 35 exit(1); 36 } 37 } 38 #else /* HAVE_PWD_H */ 39 static void 40 get_name_from_passwd_file(char *program_name, krb5_context context, 41 krb5_principal *me) 42 { 43 fprintf(stderr, _("Unable to identify user\n")); 44 exit(1); 45 } 46 #endif /* HAVE_PWD_H */ 47 48 int main(int argc, char *argv[]) 49 { 50 krb5_error_code ret; 51 krb5_context context; 52 krb5_principal princ = NULL; 53 char *pname, *message; 54 char pw[1024]; 55 krb5_ccache ccache; 56 krb5_get_init_creds_opt *opts = NULL; 57 krb5_creds creds; 58 unsigned int pwlen; 59 int result_code; 60 krb5_data result_code_string, result_string; 61 62 setlocale(LC_ALL, ""); 63 if (argc > 2) { 64 fprintf(stderr, _("usage: %s [principal]\n"), argv[0]); 65 exit(1); 66 } 67 68 pname = argv[1]; 69 70 ret = krb5_init_context(&context); 71 if (ret) { 72 com_err(argv[0], ret, _("initializing kerberos library")); 73 exit(1); 74 } 75 ret = krb5_get_init_creds_opt_alloc(context, &opts); 76 if (ret) { 77 com_err(argv[0], ret, _("allocating krb5_get_init_creds_opt")); 78 exit(1); 79 } 80 81 /* 82 * In order, use the first of: 83 * - A name specified on the command line 84 * - The principal name from an existing ccache 85 * - The name corresponding to the ruid of the process 86 * 87 * Otherwise, it's an error. 88 * We always attempt to open the default ccache in order to use FAST if 89 * possible. 90 */ 91 ret = krb5_cc_default(context, &ccache); 92 if (ret) { 93 com_err(argv[0], ret, _("opening default ccache")); 94 exit(1); 95 } 96 ret = krb5_cc_get_principal(context, ccache, &princ); 97 if (ret && ret != KRB5_CC_NOTFOUND && ret != KRB5_FCC_NOFILE) { 98 com_err(argv[0], ret, _("getting principal from ccache")); 99 exit(1); 100 } else if (princ != NULL) { 101 ret = krb5_get_init_creds_opt_set_fast_ccache(context, opts, ccache); 102 if (ret) { 103 com_err(argv[0], ret, _("while setting FAST ccache")); 104 exit(1); 105 } 106 } 107 ret = krb5_cc_close(context, ccache); 108 if (ret) { 109 com_err(argv[0], ret, _("closing ccache")); 110 exit(1); 111 } 112 if (pname != NULL) { 113 krb5_free_principal(context, princ); 114 princ = NULL; 115 ret = krb5_parse_name(context, pname, &princ); 116 if (ret) { 117 com_err(argv[0], ret, _("parsing client name")); 118 exit(1); 119 } 120 } 121 if (princ == NULL) 122 get_name_from_passwd_file(argv[0], context, &princ); 123 124 krb5_get_init_creds_opt_set_tkt_life(opts, 5 * 60); 125 krb5_get_init_creds_opt_set_renew_life(opts, 0); 126 krb5_get_init_creds_opt_set_forwardable(opts, 0); 127 krb5_get_init_creds_opt_set_proxiable(opts, 0); 128 129 ret = krb5_get_init_creds_password(context, &creds, princ, NULL, 130 krb5_prompter_posix, NULL, 0, 131 "kadmin/changepw", opts); 132 if (ret) { 133 if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) { 134 com_err(argv[0], 0, 135 _("Password incorrect while getting initial ticket")); 136 } else { 137 com_err(argv[0], ret, _("getting initial ticket")); 138 } 139 140 krb5_get_init_creds_opt_free(context, opts); 141 exit(1); 142 } 143 144 pwlen = sizeof(pw); 145 ret = krb5_read_password(context, P1, P2, pw, &pwlen); 146 if (ret) { 147 com_err(argv[0], ret, _("while reading password")); 148 krb5_get_init_creds_opt_free(context, opts); 149 exit(1); 150 } 151 152 ret = krb5_change_password(context, &creds, pw, &result_code, 153 &result_code_string, &result_string); 154 if (ret) { 155 com_err(argv[0], ret, _("changing password")); 156 krb5_get_init_creds_opt_free(context, opts); 157 exit(1); 158 } 159 160 if (result_code) { 161 if (krb5_chpw_message(context, &result_string, &message) != 0) 162 message = NULL; 163 printf("%.*s%s%s\n", 164 (int)result_code_string.length, result_code_string.data, 165 message ? ": " : "", message ? message : NULL); 166 krb5_free_string(context, message); 167 krb5_get_init_creds_opt_free(context, opts); 168 exit(2); 169 } 170 171 free(result_string.data); 172 free(result_code_string.data); 173 krb5_get_init_creds_opt_free(context, opts); 174 175 printf(_("Password changed.\n")); 176 exit(0); 177 } 178