date and time created 91/02/03 13:36:55 by bostic
authorKeith Bostic <bostic@ucbvax.Berkeley.EDU>
Mon, 4 Feb 1991 05:36:55 +0000 (21:36 -0800)
committerKeith Bostic <bostic@ucbvax.Berkeley.EDU>
Mon, 4 Feb 1991 05:36:55 +0000 (21:36 -0800)
SCCS-vsn: usr.bin/passwd/krb_passwd.c 5.1

usr/src/usr.bin/passwd/krb_passwd.c [new file with mode: 0644]

diff --git a/usr/src/usr.bin/passwd/krb_passwd.c b/usr/src/usr.bin/passwd/krb_passwd.c
new file mode 100644 (file)
index 0000000..53e8546
--- /dev/null
@@ -0,0 +1,286 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)krb_passwd.c       5.1 (Berkeley) %G%";
+#endif /* not lint */
+
+#ifdef KERBEROS
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <netinet/in.h>
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+#include <netdb.h>
+#include <signal.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdio.h>
+#include "kpasswd_proto.h"
+
+#define        PROTO   "tcp"
+
+static struct timeval timeout = { CLIENT_KRB_TIMEOUT, 0 };
+static struct kpasswd_data proto_data;
+static des_cblock okey;
+static Key_schedule osched;
+KTEXT_ST ticket;
+Key_schedule random_schedule;
+long authopts;
+char realm[REALM_SZ], krbhst[MAX_HSTNM];
+int sock;
+
+do_krb_passwd()
+{
+       struct servent *se;
+       struct hostent *host;
+       struct sockaddr_in sin;
+       CREDENTIALS cred;
+       fd_set readfds;
+       int rval, finish();
+       char pass[_PASSWORD_LEN], password[_PASSWORD_LEN];
+
+       static struct rlimit rl = { 0, 0 };
+
+       (void)signal(SIGHUP, SIG_IGN);
+       (void)signal(SIGINT, SIG_IGN);
+       (void)signal(SIGTSTP, SIG_IGN);
+
+       if (setrlimit(RLIMIT_CORE, &rl) < 0) {
+               (void)fprintf(stderr,
+                   "passwd: setrlimit: %s\n", strerror(errno));
+               return(1);
+       }
+
+       if ((se = getservbyname(SERVICE, PROTO)) == NULL) {
+               (void)fprintf(stderr,
+                   "passwd: couldn't find entry for service %s/%s\n",
+                   SERVICE, PROTO);
+               return(1);
+       }
+
+       if ((rval = krb_get_lrealm(realm,1)) != KSUCCESS) {
+               (void)fprintf(stderr,
+                   "passwd: couldn't get local Kerberos realm: %s\n",
+                   krb_err_txt[rval]);
+               return(1);
+       }
+
+       if ((rval = krb_get_krbhst(krbhst, realm, 1)) != KSUCCESS) {
+               (void)fprintf(stderr,
+                   "passwd: couldn't get Kerberos host: %s\n",
+                   krb_err_txt[rval]);
+               return(1);
+       }
+
+       if ((host = gethostbyname(krbhst)) == NULL) {
+               (void)fprintf(stderr,
+                   "passwd: couldn't get host entry for krb host %s\n",
+                   krbhst);
+               return(1);
+       }
+
+       sin.sin_family = host->h_addrtype;
+       bcopy(host->h_addr, (char *) &sin.sin_addr, host->h_length);
+       sin.sin_port = se->s_port;
+
+       if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+               (void)fprintf(stderr, "passwd: socket: %s\n", strerror(errno));
+               return(1);
+       }
+
+       if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
+               (void)fprintf(stderr, "passwd: connect: %s\n", strerror(errno));
+               (void)close(sock);
+               return(1);
+       }
+
+       rval = krb_sendauth(
+               authopts,               /* NOT mutual */
+               sock,
+               &ticket,                /* (filled in) */
+               SERVICE,
+               krbhst,                 /* instance (krbhst) */
+               realm,                  /* dest realm */
+               (u_long) getpid(),      /* checksum */
+               NULL,                   /* msg data */
+               NULL,                   /* credentials */ 
+               NULL,                   /* schedule */
+               NULL,                   /* local addr */
+               NULL,                   /* foreign addr */
+               "KPWDV0.1"
+       );
+
+       if (rval != KSUCCESS) {
+               (void)fprintf(stderr, "passwd: Kerberos sendauth error: %s\n",
+                   krb_err_txt[rval]);
+               return(1);
+       }
+
+       krb_get_cred("krbtgt", realm, realm, &cred);
+
+       (void)printf("Changing Kerberos password for %s.%s@%s.\n",
+           cred.pname, cred.pinst, realm);
+
+       if (des_read_pw_string(pass,
+           sizeof(pass)-1, "Old Kerberos password:", 0)) {
+               (void)fprintf(stderr,
+                   "passwd: error reading old Kerberos password\n");
+               return(1);
+       }
+
+       (void)des_string_to_key(pass, okey);
+       (void)des_key_sched(okey, osched);
+       (void)des_set_key(okey, osched);
+
+       /* wait on the verification string */
+
+       FD_ZERO(&readfds);
+       FD_SET(sock, &readfds);
+
+       rval =
+           select(sock + 1, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout);
+
+       if ((rval < 1) || !FD_ISSET(sock, &readfds)) {
+               if(rval == 0) {
+                       (void)fprintf(stderr, "passwd: timed out (aborted)\n");
+                       cleanup();
+                       return(1);
+               }
+               (void)fprintf(stderr, "passwd: select failed (aborted)\n");
+               cleanup();
+               return(1);
+       }
+
+       /* read verification string */
+
+       if (des_read(sock, &proto_data, sizeof(proto_data)) !=
+           sizeof(proto_data)) {
+               (void)fprintf(stderr,
+                   "passwd: couldn't read verification string (aborted)\n");
+               cleanup();
+               return(1);
+       }
+
+       (void)signal(SIGHUP, finish);
+       (void)signal(SIGINT, finish);
+
+       if (strcmp(SECURE_STRING, proto_data.secure_msg) != 0) {
+               cleanup();
+               /* don't complain loud if user just hit return */
+               if (pass == NULL || (!*pass))
+                       return(0);
+               (void)fprintf(stderr, "Sorry\n");
+               return(1);
+       }
+
+       (void)des_key_sched(proto_data.random_key, random_schedule);
+       (void)des_set_key(proto_data.random_key, random_schedule);
+       (void)bzero(pass, sizeof(pass));
+
+       if (des_read_pw_string(pass,
+           sizeof(pass)-1, "New Kerberos password:", 0)) {
+               (void)fprintf(stderr,
+                   "passwd: error reading new Kerberos password (aborted)\n");
+               cleanup();
+               return(1);
+       }
+
+       if (des_read_pw_string(password,
+           sizeof(password)-1, "Retype new Kerberos password:", 0)) {
+               (void)fprintf(stderr,
+                   "passwd: error reading new Kerberos password (aborted)\n");
+               cleanup();
+               return(1);
+       }
+
+       if (strcmp(password, pass) != 0) {
+               (void)fprintf(stderr,
+                   "passwd: password mismatch (aborted)\n");
+               cleanup();
+               return(1);
+       }
+
+       if (strlen(pass) == 0)
+               (void)printf("using NULL password\n");
+
+       send_update(sock, password, SECURE_STRING);
+
+       /* wait for ACK */
+
+       FD_ZERO(&readfds);
+       FD_SET(sock, &readfds);
+
+       rval =
+           select(sock + 1, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout);
+       if ((rval < 1) || !FD_ISSET(sock, &readfds)) {
+               if(rval == 0) {
+                       (void)fprintf(stderr,
+                           "passwd: timed out reading ACK (aborted)\n");
+                       cleanup();
+                       exit(1);
+               }
+               (void)fprintf(stderr, "passwd: select failed (aborted)\n");
+               cleanup();
+               exit(1);
+       }
+       recv_ack(sock);
+       cleanup();
+       exit(0);
+}
+
+send_update(dest, pwd, str)
+       int dest;
+       char *pwd, *str;
+{
+       static struct update_data ud;
+
+       strncpy(ud.secure_msg, str, _PASSWORD_LEN);
+       strncpy(ud.pw, pwd, sizeof(ud.pw));
+       if (des_write(dest, &ud, sizeof(ud)) != sizeof(ud)) {
+               (void)fprintf(stderr,
+                   "passwd: couldn't write pw update (abort)\n");
+               bzero(ud, sizeof(ud));
+               cleanup();
+               exit(1);
+       }
+}
+
+recv_ack(remote)
+       int remote;
+{
+       int cc;
+       char buf[BUFSIZ];
+
+       cc = des_read(remote, buf, sizeof(buf));
+       if (cc <= 0) {
+               (void)fprintf(stderr,
+                   "passwd: error reading acknowledgement (aborted)\n");
+               cleanup();
+               exit(1);
+       }
+       (void)printf("%s", buf);
+}
+
+cleanup()
+{
+       (void)bzero(&proto_data, sizeof(proto_data));
+       (void)bzero(okey, sizeof(okey));
+       (void)bzero(osched, sizeof(osched));
+       (void)bzero(random_schedule, sizeof(random_schedule));
+}
+
+finish()
+{
+       (void)close(sock);
+       exit(1);
+}
+
+#endif /* KERBEROS */