4.4BSD/usr/src/old/athena/kpasswd/kpasswd.c

Compare this file to the similar file:
Show the results in this format:


/*
 * Copyright (c) 1989 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
static char sccsid[] = "@(#)kpasswd.c	1.2 (Berkeley) 5/17/89";
#endif /* not lint */

/*
 * kpasswd - client program to update Kerberos password
 *
 * K. Fall
 * 12-Dec-88
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <netinet/in.h>
#include <netdb.h>
#include <kerberos/krb.h>
#include "kpasswd_proto.h"

KTEXT_ST	ticket;
long		authopts = 0L;
Key_schedule	random_schedule;
char		realm[REALM_SZ], krbhst[MAX_HSTNM];
static		struct	kpasswd_data	proto_data;
static		C_Block		okey;
static		Key_schedule	osched;
static struct timeval	timeout = { CLIENT_KRB_TIMEOUT, 0 };
int		sock;
char		*getpass();
int		sock;

int		finish();

#define		PROTO	"tcp"

main(argc, argv)
int	argc;
char	**argv;
{
	struct servent	*se;
	struct hostent	*host;
	struct sockaddr_in	sin;
	int		rval;
	char		password[255], *pass;
	fd_set		readfds;

	static struct	rlimit rl = { 0, 0 };

	signal(SIGHUP, SIG_IGN);
	signal(SIGINT, SIG_IGN);
	signal(SIGTSTP, SIG_IGN);

	if(setrlimit(RLIMIT_CORE, &rl) < 0) {
		perror("setrlimit");
		exit(1);
	}

	if((se = getservbyname(SERVICE, PROTO)) == NULL) {
		fprintf(stderr, "couldn't find entry for service %s/%s\n",
			SERVICE, PROTO);
		exit(1);
	}
	if((rval = krb_get_lrealm(realm,1)) != KSUCCESS) {
		fprintf(stderr, "couldn't get local Kerberos realm: %s\n",
			krb_err_txt[rval]);
		exit(1);
	}

	if((rval = krb_get_krbhst(krbhst, realm, 1)) != KSUCCESS) {
		fprintf(stderr, "couldn't get Kerberos host: %s\n",
			krb_err_txt[rval]);
		exit(1);
	}

	if((host = gethostbyname(krbhst)) == NULL) {
		fprintf(stderr, "couldn't get host entry for host %s\n",
			krbhst);
		exit(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) {
		perror("socket");
		exit(1);
	}

	if(connect(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
		perror("connect");
		close(sock);
		exit(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) {
		fprintf(stderr, "Kerberos sendauth error: %s\n",
			krb_err_txt[rval]);
		exit(1);
	}

	pass = getpass("Old Kerberos password:");
	string_to_key(pass, okey);
	key_sched(okey, osched);
	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) {
			fprintf(stderr, "Timed out\n");
			cleanup();
			exit(1);
		}
		fprintf(stderr, "select failed\n");
		cleanup();
		exit(1);
	}

	/* read verification string */

	if(des_read(sock, &proto_data, sizeof(proto_data)) != sizeof(proto_data)) {
		fprintf(stderr,
		    "%s: couldn't read verification string (aborted)\n",
		    argv[0]
		);

		cleanup();
		exit(1);
	}

	signal(SIGHUP, finish);
	signal(SIGINT, finish);

	if(strcmp(SECURE_STRING, proto_data.secure_msg)) {
		cleanup();
		fprintf(stderr, "Sorry.\n");
		exit(1);
	}
	key_sched(proto_data.random_key, random_schedule);
	des_set_key(proto_data.random_key, random_schedule);
	pass = getpass("New Kerberos password:");
	strcpy(password, pass);
	pass = getpass("Retype new Kerberos password:");
	if(strcmp(password, pass)) {
		fprintf(stderr, "Password mismatch (aborted)\n");
		cleanup();
		exit(1);
	}
	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) {
			fprintf(stderr, "Timed out reading ACK\n");
			cleanup();
			exit(1);
		}
		fprintf(stderr, "select failed\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, MSGSIZE);
	strncpy(ud.pw, pwd, sizeof(ud.pw));
	if(des_write(dest, &ud, sizeof(ud)) != sizeof(ud)) {
		fprintf(stderr, "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) {
		fprintf(stderr, "error reading acknowledgement\n");
		cleanup();
		exit(1);
	}
	printf("%s", buf);
}

cleanup()
{
	bzero(&proto_data, sizeof(proto_data));
	bzero(okey, sizeof(okey));
	bzero(osched, sizeof(osched));
	bzero(random_schedule, sizeof(random_schedule));
}

finish()
{
	close(sock);
	exit(1);
}