Added k5 password changing code for the cns program (untested, waiting for
authorKeith Vetter <keithv@fusion.com>
Wed, 31 May 1995 00:30:24 +0000 (00:30 +0000)
committerKeith Vetter <keithv@fusion.com>
Wed, 31 May 1995 00:30:24 +0000 (00:30 +0000)
a server.)

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@5918 dc483132-0cff-0310-8789-dd5450dbe970

src/windows/cns/.Sanitize
src/windows/cns/changelo
src/windows/cns/cns.c
src/windows/cns/cns.h
src/windows/cns/kpasswd.c [new file with mode: 0644]
src/windows/cns/makefile

index 0dd688f1859387a1f2b7315806336e585fba894f..a9f9a8ad5c17bd24c1d646de7e9199e1c4faf8c1 100644 (file)
@@ -44,6 +44,7 @@ cns.def
 cns.h
 cns.ico
 cns.rc
+kpasswd.c
 krbini.h
 makefile
 tktlist.c
index 9e70e5f50a794d2a87ab554371b707c39f06912b..4dee962fdb6b2906dd4383370680fda4a1cd954d 100644 (file)
@@ -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
index 844777b3bca7f8f6f4f610abe04d52fde0292dfc..d4f3249164a87d7cdcf8dd6c203043b8c75c040c 100644 (file)
@@ -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.
  *
index deac2f64c1f118d2c6f01060e582c23464c63984..35a50e94c19467e0421bdbe1ff72c8c72c916940 100644 (file)
@@ -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 (file)
index 0000000..2a79b84
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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 */
index ca67f7b6fc1bbfb63ca7e723a4e572e9e82b94ea..0f3fff350cd0f711b954ff69dcf2561f05374f00 100644 (file)
@@ -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