xref: /csrg-svn/old/athena/kpasswd/kpasswd.c (revision 38050)
1*38050Skfall 
236330Skfall /*
3*38050Skfall  * Copyright (c) 1989 The Regents of the University of California.
4*38050Skfall  * All rights reserved.
536330Skfall  *
6*38050Skfall  * Redistribution and use in source and binary forms are permitted
7*38050Skfall  * provided that the above copyright notice and this paragraph are
8*38050Skfall  * duplicated in all such forms and that any documentation,
9*38050Skfall  * advertising materials, and other materials related to such
10*38050Skfall  * distribution and use acknowledge that the software was developed
11*38050Skfall  * by the University of California, Berkeley.  The name of the
12*38050Skfall  * University may not be used to endorse or promote products derived
13*38050Skfall  * from this software without specific prior written permission.
14*38050Skfall  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15*38050Skfall  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16*38050Skfall  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17*38050Skfall  */
18*38050Skfall 
19*38050Skfall #ifndef lint
20*38050Skfall static char sccsid[] = "@(#)kpasswd.c	1.2 (Berkeley) 05/17/89";
21*38050Skfall #endif /* not lint */
22*38050Skfall 
23*38050Skfall /*
24*38050Skfall  * kpasswd - client program to update Kerberos password
25*38050Skfall  *
2636330Skfall  * K. Fall
2736330Skfall  * 12-Dec-88
2836330Skfall  */
2936330Skfall 
3036330Skfall #include <stdio.h>
3136330Skfall #include <sys/types.h>
3236330Skfall #include <sys/time.h>
3336330Skfall #include <sys/resource.h>
3436330Skfall #include <sys/socket.h>
3536330Skfall #include <sys/signal.h>
3636330Skfall #include <netinet/in.h>
3736330Skfall #include <netdb.h>
3836330Skfall #include <kerberos/krb.h>
3936330Skfall #include "kpasswd_proto.h"
4036330Skfall 
4136330Skfall KTEXT_ST	ticket;
4236330Skfall long		authopts = 0L;
4336330Skfall Key_schedule	random_schedule;
4436330Skfall char		realm[REALM_SZ], krbhst[MAX_HSTNM];
4536330Skfall static		struct	kpasswd_data	proto_data;
4636330Skfall static		C_Block		okey;
4736330Skfall static		Key_schedule	osched;
4836330Skfall static struct timeval	timeout = { CLIENT_KRB_TIMEOUT, 0 };
4936330Skfall int		sock;
5036330Skfall char		*getpass();
5136330Skfall int		sock;
5236330Skfall 
5336330Skfall int		finish();
5436330Skfall 
5536330Skfall #define		PROTO	"tcp"
5636330Skfall 
main(argc,argv)5736330Skfall main(argc, argv)
5836330Skfall int	argc;
5936330Skfall char	**argv;
6036330Skfall {
6136330Skfall 	struct servent	*se;
6236330Skfall 	struct hostent	*host;
6336330Skfall 	struct sockaddr_in	sin;
6436330Skfall 	int		rval;
6536330Skfall 	char		password[255], *pass;
6636330Skfall 	fd_set		readfds;
6736330Skfall 
6836330Skfall 	static struct	rlimit rl = { 0, 0 };
6936330Skfall 
7036330Skfall 	signal(SIGHUP, SIG_IGN);
7136330Skfall 	signal(SIGINT, SIG_IGN);
7236330Skfall 	signal(SIGTSTP, SIG_IGN);
7336330Skfall 
7436330Skfall 	if(setrlimit(RLIMIT_CORE, &rl) < 0) {
7536330Skfall 		perror("setrlimit");
7636330Skfall 		exit(1);
7736330Skfall 	}
7836330Skfall 
7936330Skfall 	if((se = getservbyname(SERVICE, PROTO)) == NULL) {
8036330Skfall 		fprintf(stderr, "couldn't find entry for service %s/%s\n",
8136330Skfall 			SERVICE, PROTO);
8236330Skfall 		exit(1);
8336330Skfall 	}
84*38050Skfall 	if((rval = krb_get_lrealm(realm,1)) != KSUCCESS) {
8536330Skfall 		fprintf(stderr, "couldn't get local Kerberos realm: %s\n",
8636330Skfall 			krb_err_txt[rval]);
8736330Skfall 		exit(1);
8836330Skfall 	}
8936330Skfall 
90*38050Skfall 	if((rval = krb_get_krbhst(krbhst, realm, 1)) != KSUCCESS) {
9136330Skfall 		fprintf(stderr, "couldn't get Kerberos host: %s\n",
9236330Skfall 			krb_err_txt[rval]);
9336330Skfall 		exit(1);
9436330Skfall 	}
9536330Skfall 
9636330Skfall 	if((host = gethostbyname(krbhst)) == NULL) {
9736330Skfall 		fprintf(stderr, "couldn't get host entry for host %s\n",
9836330Skfall 			krbhst);
9936330Skfall 		exit(1);
10036330Skfall 	}
10136330Skfall 
10236330Skfall 	sin.sin_family = host->h_addrtype;
10336330Skfall 	bcopy(host->h_addr, (char *) &sin.sin_addr, host->h_length);
10436330Skfall 	sin.sin_port = se->s_port;
10536330Skfall 
10636330Skfall 	if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
10736330Skfall 		perror("socket");
10836330Skfall 		exit(1);
10936330Skfall 	}
11036330Skfall 
11136330Skfall 	if(connect(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
11236330Skfall 		perror("connect");
11336330Skfall 		close(sock);
11436330Skfall 		exit(1);
11536330Skfall 	}
11636330Skfall 
11736330Skfall 	rval = krb_sendauth(
11836330Skfall 		authopts,		/* NOT mutual */
11936330Skfall 		sock,
12036330Skfall 		&ticket,		/* (filled in) */
12136330Skfall 		SERVICE,
12236330Skfall 		krbhst,			/* instance (krbhst) */
12336330Skfall 		realm,			/* dest realm */
12436330Skfall 		(u_long) getpid(),	/* checksum */
12536330Skfall 		NULL,			/* msg data */
12636330Skfall 		NULL,			/* credentials */
12736330Skfall 		NULL,			/* schedule */
12836330Skfall 		NULL,			/* local addr */
12936330Skfall 		NULL,			/* foreign addr */
13036330Skfall 		"KPWDV0.1"
13136330Skfall 	);
13236330Skfall 
13336330Skfall 	if(rval != KSUCCESS) {
13436330Skfall 		fprintf(stderr, "Kerberos sendauth error: %s\n",
13536330Skfall 			krb_err_txt[rval]);
13636330Skfall 		exit(1);
13736330Skfall 	}
13836330Skfall 
13936330Skfall 	pass = getpass("Old Kerberos password:");
14036330Skfall 	string_to_key(pass, okey);
14136330Skfall 	key_sched(okey, osched);
14236330Skfall 	des_set_key(okey, osched);
14336330Skfall 
14436330Skfall 	/* wait on the verification string */
14536330Skfall 
14636330Skfall 	FD_ZERO(&readfds);
14736330Skfall 	FD_SET(sock, &readfds);
14836330Skfall 
14936330Skfall 	rval =
15036330Skfall 	  select(sock + 1, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout);
15136330Skfall 	if((rval < 1) || !FD_ISSET(sock, &readfds)) {
15236330Skfall 		if(rval == 0) {
15336330Skfall 			fprintf(stderr, "Timed out\n");
15436330Skfall 			cleanup();
15536330Skfall 			exit(1);
15636330Skfall 		}
15736330Skfall 		fprintf(stderr, "select failed\n");
15836330Skfall 		cleanup();
15936330Skfall 		exit(1);
16036330Skfall 	}
16136330Skfall 
16236330Skfall 	/* read verification string */
16336330Skfall 
16436330Skfall 	if(des_read(sock, &proto_data, sizeof(proto_data)) != sizeof(proto_data)) {
16536330Skfall 		fprintf(stderr,
16636330Skfall 		    "%s: couldn't read verification string (aborted)\n",
16736330Skfall 		    argv[0]
16836330Skfall 		);
16936330Skfall 
17036330Skfall 		cleanup();
17136330Skfall 		exit(1);
17236330Skfall 	}
17336330Skfall 
17436330Skfall 	signal(SIGHUP, finish);
17536330Skfall 	signal(SIGINT, finish);
17636330Skfall 
17736330Skfall 	if(strcmp(SECURE_STRING, proto_data.secure_msg)) {
17836330Skfall 		cleanup();
17936330Skfall 		fprintf(stderr, "Sorry.\n");
18036330Skfall 		exit(1);
18136330Skfall 	}
18236330Skfall 	key_sched(proto_data.random_key, random_schedule);
18336330Skfall 	des_set_key(proto_data.random_key, random_schedule);
18436330Skfall 	pass = getpass("New Kerberos password:");
18536330Skfall 	strcpy(password, pass);
18636330Skfall 	pass = getpass("Retype new Kerberos password:");
18736330Skfall 	if(strcmp(password, pass)) {
18836330Skfall 		fprintf(stderr, "Password mismatch (aborted)\n");
18936330Skfall 		cleanup();
19036330Skfall 		exit(1);
19136330Skfall 	}
19236330Skfall 	send_update(sock, password, SECURE_STRING);
19336330Skfall 
19436330Skfall 	/* wait for ACK */
19536330Skfall 
19636330Skfall 	FD_ZERO(&readfds);
19736330Skfall 	FD_SET(sock, &readfds);
19836330Skfall 
19936330Skfall 	rval =
20036330Skfall 	  select(sock + 1, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout);
20136330Skfall 	if((rval < 1) || !FD_ISSET(sock, &readfds)) {
20236330Skfall 		if(rval == 0) {
20336330Skfall 			fprintf(stderr, "Timed out reading ACK\n");
20436330Skfall 			cleanup();
20536330Skfall 			exit(1);
20636330Skfall 		}
20736330Skfall 		fprintf(stderr, "select failed\n");
20836330Skfall 		cleanup();
20936330Skfall 		exit(1);
21036330Skfall 	}
21136330Skfall 
21236330Skfall 	recv_ack(sock);
21336330Skfall 	cleanup();
21436330Skfall 	exit(0);
21536330Skfall }
21636330Skfall 
send_update(dest,pwd,str)21736330Skfall send_update(dest, pwd, str)
21836330Skfall 	int	dest;
21936330Skfall 	char	*pwd, *str;
22036330Skfall {
22136330Skfall 	static struct	update_data	ud;
22236330Skfall 	strncpy(ud.secure_msg, str, MSGSIZE);
22336330Skfall 	strncpy(ud.pw, pwd, sizeof(ud.pw));
22436330Skfall 	if(des_write(dest, &ud, sizeof(ud)) != sizeof(ud)) {
22536330Skfall 		fprintf(stderr, "couldn't write pw update (abort)\n");
22636330Skfall 		bzero(ud, sizeof(ud));
22736330Skfall 		cleanup();
22836330Skfall 		exit(1);
22936330Skfall 	}
23036330Skfall }
23136330Skfall 
recv_ack(remote)23236330Skfall recv_ack(remote)
23336330Skfall 	int	remote;
23436330Skfall {
23536330Skfall 	int	cc;
23636330Skfall 	char	buf[BUFSIZ];
23736330Skfall 	cc = des_read(remote, buf, sizeof(buf));
23836330Skfall 	if(cc <= 0) {
23936330Skfall 		fprintf(stderr, "error reading acknowledgement\n");
24036330Skfall 		cleanup();
24136330Skfall 		exit(1);
24236330Skfall 	}
24336330Skfall 	printf("%s", buf);
24436330Skfall }
24536330Skfall 
cleanup()24636330Skfall cleanup()
24736330Skfall {
24836330Skfall 	bzero(&proto_data, sizeof(proto_data));
24936330Skfall 	bzero(okey, sizeof(okey));
25036330Skfall 	bzero(osched, sizeof(osched));
25136330Skfall 	bzero(random_schedule, sizeof(random_schedule));
25236330Skfall }
25336330Skfall 
finish()25436330Skfall finish()
25536330Skfall {
25636330Skfall 	close(sock);
25736330Skfall 	exit(1);
25836330Skfall }
259