diff options
Diffstat (limited to 'src/clients/kpasswd/kpasswd.c')
-rw-r--r-- | src/clients/kpasswd/kpasswd.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/src/clients/kpasswd/kpasswd.c b/src/clients/kpasswd/kpasswd.c new file mode 100644 index 000000000000..efc596edf7ce --- /dev/null +++ b/src/clients/kpasswd/kpasswd.c @@ -0,0 +1,176 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#include "k5-platform.h" +#include <locale.h> +#include <sys/types.h> + +#ifndef _WIN32 +#include <unistd.h> +#endif + +#include <krb5.h> + +#define P1 _("Enter new password") +#define P2 _("Enter it again") + +#ifdef HAVE_PWD_H +#include <pwd.h> + +static +void get_name_from_passwd_file(program_name, kcontext, me) + char * program_name; + krb5_context kcontext; + krb5_principal * me; +{ + struct passwd *pw; + krb5_error_code code; + if ((pw = getpwuid(getuid()))) { + if ((code = krb5_parse_name(kcontext, pw->pw_name, me))) { + com_err(program_name, code, _("when parsing name %s"), + pw->pw_name); + exit(1); + } + } else { + fprintf(stderr, _("Unable to identify user from password file\n")); + exit(1); + } +} +#else /* HAVE_PWD_H */ +void get_name_from_passwd_file(kcontext, me) + krb5_context kcontext; + krb5_principal * me; +{ + fprintf(stderr, _("Unable to identify user\n")); + exit(1); +} +#endif /* HAVE_PWD_H */ + +int main(int argc, char *argv[]) +{ + krb5_error_code ret; + krb5_context context; + krb5_principal princ = NULL; + char *pname; + krb5_ccache ccache; + krb5_get_init_creds_opt *opts = NULL; + krb5_creds creds; + char *message; + + char pw[1024]; + unsigned int pwlen; + int result_code; + krb5_data result_code_string, result_string; + + setlocale(LC_ALL, ""); + if (argc > 2) { + fprintf(stderr, _("usage: %s [principal]\n"), argv[0]); + exit(1); + } + + pname = argv[1]; + + ret = krb5_init_context(&context); + if (ret) { + com_err(argv[0], ret, _("initializing kerberos library")); + exit(1); + } + if ((ret = krb5_get_init_creds_opt_alloc(context, &opts))) { + com_err(argv[0], ret, _("allocating krb5_get_init_creds_opt")); + exit(1); + } + + /* in order, use the first of: + - a name specified on the command line + - the principal name from an existing ccache + - the name corresponding to the ruid of the process + + otherwise, it's an error. + We always attempt to open the default ccache in order to use FAST if + possible. + */ + ret = krb5_cc_default(context, &ccache); + if (ret != 0) { + com_err(argv[0], ret, _("opening default ccache")); + exit(1); + } + ret = krb5_cc_get_principal(context, ccache, &princ); + if (ret != 0 && ret != KRB5_CC_NOTFOUND && ret != KRB5_FCC_NOFILE) { + com_err(argv[0], ret, _("getting principal from ccache")); + exit(1); + } else { + if (princ != NULL) { + ret = krb5_get_init_creds_opt_set_fast_ccache(context, opts, + ccache); + if (ret) { + com_err(argv[0], ret, _("while setting FAST ccache")); + exit(1); + } + } + } + ret = krb5_cc_close(context, ccache); + if (ret != 0) { + com_err(argv[0], ret, _("closing ccache")); + exit(1); + } + if (pname) { + krb5_free_principal(context, princ); + princ = NULL; + if ((ret = krb5_parse_name(context, pname, &princ))) { + com_err(argv[0], ret, _("parsing client name")); + exit(1); + } + } + if (princ == NULL) + get_name_from_passwd_file(argv[0], context, &princ); + + krb5_get_init_creds_opt_set_tkt_life(opts, 5*60); + krb5_get_init_creds_opt_set_renew_life(opts, 0); + krb5_get_init_creds_opt_set_forwardable(opts, 0); + krb5_get_init_creds_opt_set_proxiable(opts, 0); + + if ((ret = krb5_get_init_creds_password(context, &creds, princ, NULL, + krb5_prompter_posix, NULL, + 0, "kadmin/changepw", opts))) { + if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) + com_err(argv[0], 0, + _("Password incorrect while getting initial ticket")); + else + com_err(argv[0], ret, _("getting initial ticket")); + krb5_get_init_creds_opt_free(context, opts); + exit(1); + } + + pwlen = sizeof(pw); + if ((ret = krb5_read_password(context, P1, P2, pw, &pwlen))) { + com_err(argv[0], ret, _("while reading password")); + krb5_get_init_creds_opt_free(context, opts); + exit(1); + } + + if ((ret = krb5_change_password(context, &creds, pw, + &result_code, &result_code_string, + &result_string))) { + com_err(argv[0], ret, _("changing password")); + krb5_get_init_creds_opt_free(context, opts); + exit(1); + } + + if (result_code) { + if (krb5_chpw_message(context, &result_string, &message) != 0) + message = NULL; + printf("%.*s%s%s\n", + (int) result_code_string.length, result_code_string.data, + message ? ": " : "", message ? message : NULL); + krb5_free_string(context, message); + krb5_get_init_creds_opt_free(context, opts); + exit(2); + } + + if (result_string.data != NULL) + free(result_string.data); + if (result_code_string.data != NULL) + free(result_code_string.data); + krb5_get_init_creds_opt_free(context, opts); + + printf(_("Password changed.\n")); + exit(0); +} |