From f581566cc0892118a8d35a927be4ea854c80f239 Mon Sep 17 00:00:00 2001 From: Keith Vetter Date: Wed, 31 May 1995 00:30:24 +0000 Subject: [PATCH] Added k5 password changing code for the cns program (untested, waiting for a server.) git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@5918 dc483132-0cff-0310-8789-dd5450dbe970 --- src/windows/cns/.Sanitize | 1 + src/windows/cns/changelo | 7 ++ src/windows/cns/cns.c | 38 ++----- src/windows/cns/cns.h | 8 ++ src/windows/cns/kpasswd.c | 215 ++++++++++++++++++++++++++++++++++++++ src/windows/cns/makefile | 2 +- 6 files changed, 240 insertions(+), 31 deletions(-) create mode 100644 src/windows/cns/kpasswd.c diff --git a/src/windows/cns/.Sanitize b/src/windows/cns/.Sanitize index 0dd688f18..a9f9a8ad5 100644 --- a/src/windows/cns/.Sanitize +++ b/src/windows/cns/.Sanitize @@ -44,6 +44,7 @@ cns.def cns.h cns.ico cns.rc +kpasswd.c krbini.h makefile tktlist.c diff --git a/src/windows/cns/changelo b/src/windows/cns/changelo index 9e70e5f50..4dee962fd 100644 --- a/src/windows/cns/changelo +++ b/src/windows/cns/changelo @@ -1,3 +1,10 @@ +Tue May 30 17:28:04 1995 Keith Vetter (keithv@fusion.com) + + * kpasswd.c: new file for k5 password changing. + * makefile: added new file to obj list. + * cns.c: added call to kpasswd stuff. + * cns.h: added prototype for kpasswd stuff. + Thu Apr 27 11:46:42 1995 Keith Vetter (keithv@fusion.com) * cns.c, cns.rc, krbini.h: K5 no longer has conf and realms files diff --git a/src/windows/cns/cns.c b/src/windows/cns/cns.c index 844777b3b..d4f324916 100644 --- a/src/windows/cns/cns.c +++ b/src/windows/cns/cns.c @@ -493,43 +493,21 @@ change_password ( #ifdef KRB5 /* FIXME */ char *msg; // Message string krb5_error_code code; // Return value - - krb5_error_code //FIXME INTERFACE - krb5_change_password( - krb5_context context, - char *user, - char *realm, - char *old_password, - char *new_password, - char **text); - - code = krb5_change_password (k5_context, name, realm, oldpw, newpw, &msg); + code = k5_change_password (k5_context, name, realm, oldpw, newpw, &msg); if (msg != NULL) { MessageBox (NULL, msg, NULL, MB_ICONEXCLAMATION); - //WHO FREES THIS SPACE??? free (msg); - } else if (code) - com_err (NULL, code, "while changing password."); + } else if (code) { + if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) + MessageBox (NULL, "Password incorrect", NULL, MB_ICONEXCLAMATION); + else + com_err (NULL, code, "while changing password."); + } return (code == 0); -#endif -} /* change_password */ -/*+*/ -#ifdef KRB5 -krb5_error_code //FIXME INTERFACE -krb5_change_password( - krb5_context context, - char *user, - char *realm, - char *old_password, - char *new_password, - char **text) -{ - *text = "Changing passwords is not yet implemented"; - return -1; -} #endif /* KRB5 */ +} /*+ * Function: Process WM_COMMAND messages for the password dialog. * diff --git a/src/windows/cns/cns.h b/src/windows/cns/cns.h index deac2f64c..35a50e94c 100644 --- a/src/windows/cns/cns.h +++ b/src/windows/cns/cns.h @@ -153,6 +153,14 @@ time_t kwin_get_epoch(void); static int k5_get_lrealm (char *realm); static krb5_error_code k5_init_ccache (krb5_ccache *ccache); static int k5_name_from_ccache (krb5_ccache k5_ccache); + krb5_error_code k5_change_password ( + krb5_context context, + char *user, + char *realm, + char *old_password, + char *new_password, + char **text); + #endif HICON kwin_get_icon(time_t expiration); diff --git a/src/windows/cns/kpasswd.c b/src/windows/cns/kpasswd.c new file mode 100644 index 000000000..2a79b84f7 --- /dev/null +++ b/src/windows/cns/kpasswd.c @@ -0,0 +1,215 @@ +/*+************************************************************************* +** +** k5passwd +** +** Changes your password in the Kerberos V5. This should have been +** part of the kadm stuff but we're forced to build a nicer API on top +** of the calls they provide. +** +***************************************************************************/ +#ifdef KRB5 +#include +#include +#include +#include "krb5.h" +#include "com_err.h" +#include "adm.h" +#include "adm_proto.h" + +static const char *kadm_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 *kadm_replies_unknown = "UNKNOWN ERROR"; +static char errbuf[1024]; /* For response from kadm */ + +/*+************************************************************************* +** +** get_admin_response +** +** Builds into a static buffer the replies sent back by the admin server. +** +***************************************************************************/ +static char * +get_admin_response ( + krb5_int32 status, // Type of error + krb5_int32 nreplies, // Size of reply + krb5_data * reply) // Buffer of messages +{ + char *ptr; // For building the response + char *end = errbuf + sizeof (errbuf); // So we don't overflow + int i; // Index + int n; // Length + + if (status <= KRB5_ADM_LANG_NOT_SUPPORTED) // Is it of a known type??? + strcpy (errbuf, kadm_replies[status]); + else + strcpy (errbuf, kadm_replies_unknown); // Unknown error type + ptr = errbuf + strlen (errbuf); // Point at the end + + if (nreplies > 0) { // Are there more message? + *ptr++ = ':'; + *ptr = '\0'; + } + + for (i = 0; i < nreplies; ++i) { // Append additional messages + *ptr++ = '\n'; + + n = reply[i].length; // Easier to work with + if (ptr + n + 2 >= errbuf) // Check for overflow + break; + memcpy (ptr, reply[i].data, n); // Add the message + ptr += n; // Point to the end + *ptr = '\0'; + } + + return errbuf; +} +/*+************************************************************************* +** +** keyadmin_send_recieve +** +** Sends a command to the key admin and reads the reply. +** +***************************************************************************/ +static krb5_error_code +keyadmin_send_receive ( + krb5_context k5context, + int * conn_socket, + krb5_auth_context * auth_context, + krb5_int32 nargs, + krb5_data * arglist, + krb5_int32 * cmd_stat, + krb5_int32 * nreplies, + krb5_data ** reply) +{ + krb5_error_code kret; + + kret = krb5_send_adm_cmd (k5context, conn_socket, auth_context, + nargs, arglist); + + if (! kret) + kret = krb5_read_adm_reply (k5context, conn_socket, auth_context, + cmd_stat, nreplies, reply); + + return kret; +} +/*+************************************************************************* +** +** k5_change_password +** +** Bundles all the crude needed to change the password into one file. +** +***************************************************************************/ +krb5_error_code +k5_change_password ( + krb5_context k5context, + char *user, + char *realm, + char *opasswd, + char *npasswd, + char **text) +{ + krb5_error_code kret, kret2; + krb5_auth_context * auth_context; + krb5_ccache ccache; + int conn_socket; /* Socket for talking over */ + krb5_int32 nreplies; + krb5_data data[3]; + krb5_data * reply; + krb5_int32 status; + char * name; + + *text = NULL; /* Be safe */ + name = malloc (strlen (user) + strlen (realm) + 2); + if (name == NULL) + return ENOMEM; + sprintf (name, "%s@%s", user, realm); + +/* +** Establish the connection. +*/ + kret = krb5_adm_connect (k5context, name, NULL, opasswd, &conn_socket, + &auth_context, &ccache); + if (kret) + goto done; +/* +** Check to see if it's an acceptable password +*/ + data[0].data = KRB5_ADM_CHECKPW_CMD; + data[0].length = strlen (data[0].data); + data[1].data = npasswd; + data[1].length = strlen (npasswd); + + kret = keyadmin_send_receive (k5context, &conn_socket, auth_context, + 2, data, &status, &nreplies, &reply); + if (kret) /* Some external error */ + goto cleanup; + + if (status != KRB5_ADM_SUCCESS) { /* Some problem??? */ + kret = status; + *text = get_admin_response (status, nreplies, reply); + krb5_free_adm_data (k5context, nreplies, reply); + + goto quit; + } + krb5_free_adm_data (k5context, nreplies, reply); + +/* +** The new password is ok, so now actually change the password +*/ + data[0].data = KRB5_ADM_CHANGEPW_CMD; + data[0].length = strlen (data[0].data); + data[1].data = opasswd; + data[1].length = strlen (opasswd); + data[2].data = npasswd; + data[2].length = strlen (npasswd); + + kret = keyadmin_send_receive (k5context, &conn_socket, auth_context, + 3, data, &status, &nreplies, &reply); + if (kret) + goto cleanup; + + if (status != KRB5_ADM_SUCCESS) { + kret = status; + *text = get_admin_response (status, nreplies, reply); + krb5_free_adm_data (k5context, nreplies, reply); + + goto quit; + } + + krb5_free_adm_data (k5context, nreplies, reply); +/*+ +** Need to send quit command. +*/ + quit: + data[0].data = KRB5_ADM_QUIT_CMD; + data[0].length = strlen (data[0].data); + + kret2 = keyadmin_send_receive (k5context, &conn_socket, auth_context, + 1, data, &status, &nreplies, &reply); + if (kret2) { + if (! kret) + kret = kret2; + } else if (status != KRB5_ADM_SUCCESS) { + if (! kret) + kret = status; + if (*text == NULL) + *text = get_admin_response (status, nreplies, reply); + } + krb5_free_adm_data (k5context, nreplies, reply); + + cleanup: + krb5_adm_disconnect (k5context, &conn_socket, auth_context, ccache); + done: + free (name); + + return kret; +} + +#endif /* KRB5 */ diff --git a/src/windows/cns/makefile b/src/windows/cns/makefile index ca67f7b6f..0f3fff350 100644 --- a/src/windows/cns/makefile +++ b/src/windows/cns/makefile @@ -2,7 +2,7 @@ # Works for both k4 and k5 releases. # NAME = cns -OBJS = cns.obj tktlist.obj +OBJS = cns.obj tktlist.obj kpasswd.obj ##### Options DEBUG = 1 -- 2.26.2