+++ /dev/null
-/*
- * kadmin/kpasswd/kpasswd.c
- *
- * Copyright 1995 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
- *
- */
-
-/*
- * kpasswd
- * change your password with Version 5 Kerberos using the new password
- * changing protocol.
- */
-\f
-/*
- * Include files.
- */
-#include "k5-int.h"
-#include "adm_defs.h"
-#include "adm.h"
-
-#ifdef USE_STRING_H
-#include <string.h>
-#else /* USE_STRING_H */
-#include <strings.h>
-#endif /* USE_STRING_H */
-
-\f
-/*
- * Local definitions.
- */
-#define KPWD_MAX_TRIES 4
-\f
-/*
- * Local data.
- */
-static const char *kpwd_serror_head = "server";
-static const char *kpwd_change_prompt_1 = " Enter new password: ";
-static const char *kpwd_change_prompt_2 = "Re-enter new password: ";
-static const char *kpwd_old_password_prompt = " Enter old password: ";
-static const char *kpwd_old_pwd_name_fmt = "Enter old password for %s: ";
-
-#ifdef LANGUAGES_SUPPORTED
-static const char *kpwd_usage_error_fmt = "%s: usage is %s [-u user] [-l language]\n";
-static const char *kpwd_getoptstring = "l:u:";
-#else /* LANGUAGES_SUPPORTED */
-static const char *kpwd_usage_error_fmt = "%s: usage is %s [-u user]\n";
-static const char *kpwd_getoptstring = "u:";
-#endif /* LANGUAGES_SUPPORTED */
-static const char *kpwd_extra_args = "extra arguments";
-static const char *kpwd_bad_option_fmt = "%s: unrecognized option -%c.\n";
-static const char *kpwd_no_memory_fmt = "%s: not enough resources to allocate %d bytes for %s.\n";
-static const char *kpwd_bad_client_fmt = "%s: %s%s%s %s not recognized by the server.\n";
-static const char *kpwd_no_server_fmt = "%s: cannot find server for %s.\n";
-static const char *kpwd_incorrect_fmt = "%s: incorrect password\n";
-static const char *kpwd_cant_connect_fmt = "%s: cannot contact server (%s).\n";
-static const char *kpwd_proto_error_fmt = "%s: protocol error during %s request (%s).\n";
-static const char *kpwd_pwproto_unsupp_fmt = "%s: %s request not supported by server.\n";
-static const char *kpwd_pwproto_error = "%s: server error (%s) during %s request.\n";
-static const char *kpwd_pwd_unacceptable = "%s: your new password is unacceptable to the server, %s.\n";
-static const char *kpwd_read_pass_error = "%s: error (%s) reading passwords.\n";
-
-static const char *kpwd_password_text = "passwords";
-static const char *kpwd_realm_text = "realm name";
-static const char *kpwd_args_text = "arguments";
-
-static const char *kpwd_try_again_text = "try again";
-static const char *kpwd_seeyalater_text = "password not changed";
-
-static const char *kpwd_mime_text = "MIME-enable";
-static const char *kpwd_language_text = "set language";
-static const char *kpwd_check_pwd_text = "check password";
-static const char *kpwd_change_pwd_text = "change password";
-static const char *kpwd_quit_text = "quit";
-
-static const char *kpwd_you = "you";
-static const char *kpwd_is_second = "are";
-static const char *kpwd_is_third = "is";
-static const char *kpwd_quote = "'";
-static const char *kpwd_null = "";
-
-static const char *kpwd_this_realm = "this realm";
-
-static const char *kpwd_replies[] = {
- "Operation successful", /* KRB5_ADM_SUCCESS */
- "Command not recognized", /* KRB5_ADM_CMD_UNKNOWN */
- "Password unacceptable to server", /* KRB5_ADM_PW_UNACCEPT */
- "Old password incorrect", /* KRB5_ADM_BAD_PW */
- "Invalid ticket (TKT_FLAG_INITIAL not set)",/* KRB5_ADM_NOT_IN_TKT */
- "Server refused password change", /* KRB5_ADM_CANT_CHANGE */
- "Language not supported", /* KRB5_ADM_LANG_NOT_SUPPORTED */
-};
-static const char *kpwd_replies_unknown = "UNKNOWN ERROR";
-\f
-static void
-usage(invocation, more_info)
- char *invocation;
- char *more_info;
-{
- if (more_info)
- fprintf(stderr, "%s: %s\n", invocation, more_info);
- fprintf(stderr, kpwd_usage_error_fmt, invocation, invocation);
-}
-
-static const char *
-kpwd_reply_to_string(stat)
- krb5_int32 stat;
-{
- int index;
- const char *rval;
-
- switch (stat) {
- case KRB5_ADM_SUCCESS:
- case KRB5_ADM_CMD_UNKNOWN:
- case KRB5_ADM_PW_UNACCEPT:
- case KRB5_ADM_BAD_PW:
- case KRB5_ADM_NOT_IN_TKT:
- case KRB5_ADM_CANT_CHANGE:
- case KRB5_ADM_LANG_NOT_SUPPORTED:
- index = (int) stat;
- rval = kpwd_replies[index];
- break;
- default:
- rval = kpwd_replies_unknown;
- break;
- }
- return(rval);
-}
-
-static void
-kpwd_print_sreply(progname, ncomps, complist)
- char *progname;
- krb5_int32 ncomps;
- krb5_data *complist;
-{
- krb5_int32 i;
- /*
- * If language/mime suporrt enabled, need to have mime-decoder here.
- */
- if (ncomps > 0) {
- fprintf(stderr, "%s - %s: %s\n", progname, kpwd_serror_head,
- complist[0].data);
- for (i=1; i<ncomps; i++)
- fprintf(stderr, "\t%s\n", complist[i].data);
- }
-}
-\f
-main(argc, argv)
- int argc;
- char *argv[];
-{
- int option;
- extern int optind;
- extern char *optarg;
- int error;
-
- char *name;
- int mflag;
- int lflag;
- char *language;
-
- krb5_error_code kret;
- krb5_context kcontext;
- krb5_auth_context auth_context;
- krb5_ccache ccache;
- char *opassword;
- char *npassword;
- char *opwd_prompt;
-
- int conn_socket = -1;
-
- int npass_tries;
- int send_quit;
-
- /*
- * Initialize.
- */
- language = name = opwd_prompt = (char *) NULL;
- mflag = lflag = error = 0;
- send_quit = 0;
- ccache = (krb5_ccache) NULL;
-
- /*
- * Usage is:
- * kpasswd [-u user] [-l language]
- */
- while ((option = getopt(argc, argv, kpwd_getoptstring)) != EOF) {
- switch (option) {
- case 'u':
- if ((name = (char *) malloc(strlen(optarg)+1)) == NULL) {
- fprintf(stderr, kpwd_no_memory_fmt, argv[0],
- strlen(optarg)+1, kpwd_args_text);
- error = ENOMEM;
- break;
- }
- strcpy(name, optarg);
- break;
-#ifdef LANGUAGES_SUPPORTED
- case 'l':
- lflag++;
- mflag++;
- if ((language = (char *) malloc(strlen(optarg)+1)) == NULL) {
- fprintf(stderr, kpwd_no_memory_fmt, argv[0],
- strlen(optarg)+1, kpwd_args_text);
- error = ENOMEM;
- break;
- }
- strcpy(language, optarg);
- break;
-#endif /* LANGUAGES_SUPPORTED */
- default:
- error++;
- break;
- }
- if (error)
- break;
- }
- if (error || ((argc - optind) > 0)) {
- usage(argv[0], (error) ? (char *) NULL: kpwd_extra_args);
- error++;
- if (name)
- free(name);
- if (language)
- free(language);
- return(error);
- }
-
- /* Get space for passwords */
- if (
- ((npassword = (char *) malloc(KRB5_ADM_MAX_PASSWORD_LEN))
- == (char *) NULL) ||
- ((opassword = (char *) malloc(KRB5_ADM_MAX_PASSWORD_LEN))
- == (char *) NULL)) {
- fprintf(stderr, kpwd_no_memory_fmt, argv[0], KRB5_ADM_MAX_PASSWORD_LEN,
- kpwd_password_text);
- if (npassword)
- free(npassword);
- return(ENOMEM);
- }
-
- /*
- * Initialize Kerberos
- */
- krb5_init_context(&kcontext);
- krb5_init_ets(kcontext);
-
- /* From now on, all error legs via 'goto cleanup' */
-
- if (name) {
- size_t prompt_len;
-
- prompt_len = strlen(kpwd_old_pwd_name_fmt) - 2 + strlen(name) + 1;
- opwd_prompt = (char *) malloc(prompt_len);
- if (opwd_prompt)
- sprintf(opwd_prompt, kpwd_old_pwd_name_fmt, name);
- }
- /*
- * Establish the connection.
- */
- if (kret = krb5_adm_connect(kcontext,
- name,
- (opwd_prompt) ?
- opwd_prompt : kpwd_old_password_prompt,
- opassword,
- &conn_socket,
- &auth_context,
- &ccache,
- (char *) NULL,
- 0)) {
- switch (kret) {
- case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
- fprintf(stderr, kpwd_bad_client_fmt, argv[0],
- (name) ? kpwd_quote : kpwd_null,
- (name) ? name : kpwd_you,
- (name) ? kpwd_quote : kpwd_null,
- (name) ? kpwd_is_third : kpwd_is_second);
- break;
- case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN:
- fprintf(stderr, kpwd_no_server_fmt, argv[0],
- (name) ? name : kpwd_this_realm);
- break;
- case KRB5KRB_AP_ERR_BAD_INTEGRITY:
- fprintf(stderr, kpwd_incorrect_fmt, argv[0]);
- break;
- default:
- fprintf(stderr, kpwd_cant_connect_fmt, argv[0],
- error_message(kret));
- break;
- }
- goto cleanup;
- }
-
- if (opwd_prompt)
- free(opwd_prompt);
- send_quit = 1;
-
-#ifdef LANGUAGES_SUPPORTED
- /*
- * We have the connection - see if we have to send some precursory data.
- */
- if (mflag) {
- /*
- * Need to engage in protocol for MIME setting
- */
- krb5_data mime_data;
- krb5_int32 mime_status;
- krb5_int32 mime_ncomps;
- krb5_data *mime_reply;
-
- mime_data.data = KRB5_ADM_MIME_CMD;
- mime_data.length = strlen(mime_data.data);
- if ((kret = krb5_send_adm_cmd(kcontext,
- &conn_socket,
- auth_context,
- 1,
- &mime_data)) ||
- (kret = krb5_read_adm_reply(kcontext,
- &conn_socket,
- auth_context,
- &mime_status,
- &mime_ncomps,
- &mime_reply))) {
- fprintf(stderr, kpwd_proto_error_fmt, argv[0], kpwd_mime_text,
- error_message(kret));
- send_quit = 0;
- goto cleanup;
- }
- switch (mime_status) {
- case KRB5_ADM_SUCCESS:
- break;
- case KRB5_ADM_CMD_UNKNOWN:
- fprintf(stderr, kpwd_pwproto_unsupp_fmt, argv[0], kpwd_mime_text);
- if (mime_ncomps > 0)
- kpwd_print_sreply(argv[0], mime_ncomps, mime_reply);
- break;
- default:
- fprintf(stderr, kpwd_pwproto_error, argv[0],
- kpwd_reply_to_string(mime_status), kpwd_mime_text);
- if (mime_ncomps > 0)
- kpwd_print_sreply(argv[0], mime_ncomps, mime_reply);
- goto cleanup;
- }
- krb5_free_adm_data(kcontext, mime_ncomps, mime_reply);
- }
- if (lflag && language) {
- /*
- * Need to engage in protocol for language setting
- */
- krb5_data lang_data[2];
- krb5_int32 lang_status;
- krb5_int32 lang_ncomps;
- krb5_data *lang_reply;
-
- lang_data[0].data = KRB5_ADM_LANGUAGE_CMD;
- lang_data[0].length = strlen(lang_data[0].data);
- lang_data[1].data = language;
- lang_data[1].length = strlen(language);
- if ((kret = krb5_send_adm_cmd(kcontext,
- &conn_socket,
- auth_context,
- 2,
- lang_data)) ||
- (kret = krb5_read_adm_reply(kcontext,
- &conn_socket,
- auth_context,
- &lang_status,
- &lang_ncomps,
- &lang_reply))) {
- fprintf(stderr, kpwd_proto_error_fmt, argv[0], kpwd_language_text,
- error_message(kret));
- send_quit = 0;
- goto cleanup;
- }
- switch (lang_status) {
- case KRB5_ADM_SUCCESS:
- break;
- case KRB5_ADM_CMD_UNKNOWN:
- fprintf(stderr, kpwd_pwproto_unsupp_fmt, argv[0],
- kpwd_language_text);
- if (lang_ncomps > 0)
- kpwd_print_sreply(argv[0], lang_ncomps, lang_reply);
- break;
- default:
- fprintf(stderr, kpwd_pwproto_error, argv[0],
- kpwd_reply_to_string(lang_status), kpwd_language_text);
- if (lang_ncomps > 0)
- kpwd_print_sreply(argv[0], lang_ncomps, lang_reply);
- goto cleanup;
- }
- krb5_free_adm_data(kcontext, lang_ncomps, lang_reply);
- }
-#endif /* LANGUAGES_SUPPORTED */
-
- /* Now - Actually change the password. */
- for (npass_tries = 1; npass_tries <= KPWD_MAX_TRIES; npass_tries++) {
- int npass_len;
-
- npass_len = KRB5_ADM_MAX_PASSWORD_LEN;
- if (!(kret = krb5_read_password(kcontext,
- (char *) kpwd_change_prompt_1,
- (char *) kpwd_change_prompt_2,
- npassword,
- &npass_len))) {
- krb5_data check_data[2];
- krb5_int32 check_status;
- krb5_int32 check_ncomps;
- krb5_data *check_reply;
- krb5_data set_data[3];
- krb5_int32 set_status;
- krb5_int32 set_ncomps;
- krb5_int32 *set_reply;
-
- check_data[0].data = KRB5_ADM_CHECKPW_CMD;
- check_data[0].length = strlen(check_data[0].data);
- check_data[1].data = npassword;
- check_data[1].length = npass_len;
- if ((kret = krb5_send_adm_cmd(kcontext,
- &conn_socket,
- auth_context,
- 2,
- check_data)) ||
- (kret = krb5_read_adm_reply(kcontext,
- &conn_socket,
- auth_context,
- &check_status,
- &check_ncomps,
- &check_reply))) {
- fprintf(stderr, kpwd_proto_error_fmt, argv[0],
- kpwd_check_pwd_text, error_message(kret));
- send_quit = 0;
- error++;
- break;
- }
- if ((check_status != KRB5_ADM_SUCCESS) &&
- (check_status != KRB5_ADM_PW_UNACCEPT)) {
- error++;
- fprintf(stderr, kpwd_pwproto_error, argv[0],
- kpwd_reply_to_string(check_status),
- kpwd_check_pwd_text);
- if (check_ncomps > 0)
- kpwd_print_sreply(argv[0], check_ncomps, check_reply);
- }
-
- if (check_status == KRB5_ADM_PW_UNACCEPT) {
- fprintf(stderr, kpwd_pwd_unacceptable, argv[0],
- (npass_tries < KPWD_MAX_TRIES) ?
- kpwd_try_again_text : kpwd_seeyalater_text);
- if (check_ncomps > 0)
- kpwd_print_sreply(argv[0], check_ncomps, check_reply);
- if (npass_tries == KPWD_MAX_TRIES)
- kret = check_status;
- continue;
- }
- krb5_free_adm_data(kcontext, check_ncomps, check_reply);
- if (error)
- break;
-
- /* Now actually change the password */
- set_data[0].data = KRB5_ADM_CHANGEPW_CMD;
- set_data[0].length = strlen(set_data[0].data);
- set_data[1].data = opassword;
- set_data[1].length = strlen(opassword);
- set_data[2].data = npassword;
- set_data[2].length = npass_len;
- if ((kret = krb5_send_adm_cmd(kcontext,
- &conn_socket,
- auth_context,
- 3,
- set_data)) ||
- (kret = krb5_read_adm_reply(kcontext,
- &conn_socket,
- auth_context,
- &set_status,
- &set_ncomps,
- &set_reply))) {
- fprintf(stderr, kpwd_proto_error_fmt, argv[0],
- kpwd_change_pwd_text, error_message(kret));
- send_quit = 0;
- error++;
- break;
- }
- if (set_status != KRB5_ADM_SUCCESS) {
- fprintf(stderr, kpwd_pwproto_error, argv[0],
- kpwd_reply_to_string(set_status),
- kpwd_change_pwd_text);
- if (set_ncomps > 0)
- kpwd_print_sreply(argv[0], set_ncomps, set_reply);
- error++;
- }
- krb5_free_adm_data(kcontext, set_ncomps, set_reply);
- break;
- }
- else {
- fprintf(stderr, kpwd_read_pass_error, argv[0],
- error_message(kret));
- error++;
- break;
- }
- }
-
- cleanup:
- if (kret)
- error = kret;
- if (language)
- free(language);
- if (name)
- free(name);
-
- /* Clear and free password storage */
- if (opassword) {
- memset(opassword, 0, KRB5_ADM_MAX_PASSWORD_LEN);
- krb5_xfree(opassword);
- }
- if (npassword) {
- memset(npassword, 0, KRB5_ADM_MAX_PASSWORD_LEN);
- free(npassword);
- }
-
- if (send_quit) {
- /*
- * Need to send quit command.
- */
- krb5_data quit_data;
- krb5_int32 quit_status;
- krb5_int32 quit_ncomps;
- krb5_data *quit_reply;
-
- quit_data.data = KRB5_ADM_QUIT_CMD;
- quit_data.length = strlen(quit_data.data);
- if ((kret = krb5_send_adm_cmd(kcontext,
- &conn_socket,
- auth_context,
- 1,
- &quit_data)) ||
- (kret = krb5_read_adm_reply(kcontext,
- &conn_socket,
- auth_context,
- &quit_status,
- &quit_ncomps,
- &quit_reply))) {
- fprintf(stderr, kpwd_proto_error_fmt, argv[0], kpwd_quit_text,
- error_message(kret));
- goto done;
- }
- switch (quit_status) {
- case KRB5_ADM_SUCCESS:
- break;
- case KRB5_ADM_CMD_UNKNOWN:
- fprintf(stderr, kpwd_pwproto_unsupp_fmt, argv[0], kpwd_quit_text);
- if (quit_ncomps > 0)
- kpwd_print_sreply(argv[0], quit_ncomps, quit_reply);
- break;
- default:
- fprintf(stderr, kpwd_pwproto_error, argv[0],
- kpwd_reply_to_string(quit_status), kpwd_quit_text);
- if (quit_ncomps > 0)
- kpwd_print_sreply(argv[0], quit_ncomps, quit_reply);
- }
- krb5_free_adm_data(kcontext, quit_ncomps, quit_reply);
- }
-
- done:
- krb5_adm_disconnect(kcontext, &conn_socket, auth_context, ccache);
- krb5_xfree(kcontext);
- return(error);
-}