xref: /original-bsd/old/athena/kpasswd/kpasswd.c (revision e59fb703)
1 
2 /*
3  * Copyright (c) 1989 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms are permitted
7  * provided that the above copyright notice and this paragraph are
8  * duplicated in all such forms and that any documentation,
9  * advertising materials, and other materials related to such
10  * distribution and use acknowledge that the software was developed
11  * by the University of California, Berkeley.  The name of the
12  * University may not be used to endorse or promote products derived
13  * from this software without specific prior written permission.
14  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17  */
18 
19 #ifndef lint
20 static char sccsid[] = "@(#)kpasswd.c	1.2 (Berkeley) 05/17/89";
21 #endif /* not lint */
22 
23 /*
24  * kpasswd - client program to update Kerberos password
25  *
26  * K. Fall
27  * 12-Dec-88
28  */
29 
30 #include <stdio.h>
31 #include <sys/types.h>
32 #include <sys/time.h>
33 #include <sys/resource.h>
34 #include <sys/socket.h>
35 #include <sys/signal.h>
36 #include <netinet/in.h>
37 #include <netdb.h>
38 #include <kerberos/krb.h>
39 #include "kpasswd_proto.h"
40 
41 KTEXT_ST	ticket;
42 long		authopts = 0L;
43 Key_schedule	random_schedule;
44 char		realm[REALM_SZ], krbhst[MAX_HSTNM];
45 static		struct	kpasswd_data	proto_data;
46 static		C_Block		okey;
47 static		Key_schedule	osched;
48 static struct timeval	timeout = { CLIENT_KRB_TIMEOUT, 0 };
49 int		sock;
50 char		*getpass();
51 int		sock;
52 
53 int		finish();
54 
55 #define		PROTO	"tcp"
56 
57 main(argc, argv)
58 int	argc;
59 char	**argv;
60 {
61 	struct servent	*se;
62 	struct hostent	*host;
63 	struct sockaddr_in	sin;
64 	int		rval;
65 	char		password[255], *pass;
66 	fd_set		readfds;
67 
68 	static struct	rlimit rl = { 0, 0 };
69 
70 	signal(SIGHUP, SIG_IGN);
71 	signal(SIGINT, SIG_IGN);
72 	signal(SIGTSTP, SIG_IGN);
73 
74 	if(setrlimit(RLIMIT_CORE, &rl) < 0) {
75 		perror("setrlimit");
76 		exit(1);
77 	}
78 
79 	if((se = getservbyname(SERVICE, PROTO)) == NULL) {
80 		fprintf(stderr, "couldn't find entry for service %s/%s\n",
81 			SERVICE, PROTO);
82 		exit(1);
83 	}
84 	if((rval = krb_get_lrealm(realm,1)) != KSUCCESS) {
85 		fprintf(stderr, "couldn't get local Kerberos realm: %s\n",
86 			krb_err_txt[rval]);
87 		exit(1);
88 	}
89 
90 	if((rval = krb_get_krbhst(krbhst, realm, 1)) != KSUCCESS) {
91 		fprintf(stderr, "couldn't get Kerberos host: %s\n",
92 			krb_err_txt[rval]);
93 		exit(1);
94 	}
95 
96 	if((host = gethostbyname(krbhst)) == NULL) {
97 		fprintf(stderr, "couldn't get host entry for host %s\n",
98 			krbhst);
99 		exit(1);
100 	}
101 
102 	sin.sin_family = host->h_addrtype;
103 	bcopy(host->h_addr, (char *) &sin.sin_addr, host->h_length);
104 	sin.sin_port = se->s_port;
105 
106 	if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
107 		perror("socket");
108 		exit(1);
109 	}
110 
111 	if(connect(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
112 		perror("connect");
113 		close(sock);
114 		exit(1);
115 	}
116 
117 	rval = krb_sendauth(
118 		authopts,		/* NOT mutual */
119 		sock,
120 		&ticket,		/* (filled in) */
121 		SERVICE,
122 		krbhst,			/* instance (krbhst) */
123 		realm,			/* dest realm */
124 		(u_long) getpid(),	/* checksum */
125 		NULL,			/* msg data */
126 		NULL,			/* credentials */
127 		NULL,			/* schedule */
128 		NULL,			/* local addr */
129 		NULL,			/* foreign addr */
130 		"KPWDV0.1"
131 	);
132 
133 	if(rval != KSUCCESS) {
134 		fprintf(stderr, "Kerberos sendauth error: %s\n",
135 			krb_err_txt[rval]);
136 		exit(1);
137 	}
138 
139 	pass = getpass("Old Kerberos password:");
140 	string_to_key(pass, okey);
141 	key_sched(okey, osched);
142 	des_set_key(okey, osched);
143 
144 	/* wait on the verification string */
145 
146 	FD_ZERO(&readfds);
147 	FD_SET(sock, &readfds);
148 
149 	rval =
150 	  select(sock + 1, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout);
151 	if((rval < 1) || !FD_ISSET(sock, &readfds)) {
152 		if(rval == 0) {
153 			fprintf(stderr, "Timed out\n");
154 			cleanup();
155 			exit(1);
156 		}
157 		fprintf(stderr, "select failed\n");
158 		cleanup();
159 		exit(1);
160 	}
161 
162 	/* read verification string */
163 
164 	if(des_read(sock, &proto_data, sizeof(proto_data)) != sizeof(proto_data)) {
165 		fprintf(stderr,
166 		    "%s: couldn't read verification string (aborted)\n",
167 		    argv[0]
168 		);
169 
170 		cleanup();
171 		exit(1);
172 	}
173 
174 	signal(SIGHUP, finish);
175 	signal(SIGINT, finish);
176 
177 	if(strcmp(SECURE_STRING, proto_data.secure_msg)) {
178 		cleanup();
179 		fprintf(stderr, "Sorry.\n");
180 		exit(1);
181 	}
182 	key_sched(proto_data.random_key, random_schedule);
183 	des_set_key(proto_data.random_key, random_schedule);
184 	pass = getpass("New Kerberos password:");
185 	strcpy(password, pass);
186 	pass = getpass("Retype new Kerberos password:");
187 	if(strcmp(password, pass)) {
188 		fprintf(stderr, "Password mismatch (aborted)\n");
189 		cleanup();
190 		exit(1);
191 	}
192 	send_update(sock, password, SECURE_STRING);
193 
194 	/* wait for ACK */
195 
196 	FD_ZERO(&readfds);
197 	FD_SET(sock, &readfds);
198 
199 	rval =
200 	  select(sock + 1, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout);
201 	if((rval < 1) || !FD_ISSET(sock, &readfds)) {
202 		if(rval == 0) {
203 			fprintf(stderr, "Timed out reading ACK\n");
204 			cleanup();
205 			exit(1);
206 		}
207 		fprintf(stderr, "select failed\n");
208 		cleanup();
209 		exit(1);
210 	}
211 
212 	recv_ack(sock);
213 	cleanup();
214 	exit(0);
215 }
216 
217 send_update(dest, pwd, str)
218 	int	dest;
219 	char	*pwd, *str;
220 {
221 	static struct	update_data	ud;
222 	strncpy(ud.secure_msg, str, MSGSIZE);
223 	strncpy(ud.pw, pwd, sizeof(ud.pw));
224 	if(des_write(dest, &ud, sizeof(ud)) != sizeof(ud)) {
225 		fprintf(stderr, "couldn't write pw update (abort)\n");
226 		bzero(ud, sizeof(ud));
227 		cleanup();
228 		exit(1);
229 	}
230 }
231 
232 recv_ack(remote)
233 	int	remote;
234 {
235 	int	cc;
236 	char	buf[BUFSIZ];
237 	cc = des_read(remote, buf, sizeof(buf));
238 	if(cc <= 0) {
239 		fprintf(stderr, "error reading acknowledgement\n");
240 		cleanup();
241 		exit(1);
242 	}
243 	printf("%s", buf);
244 }
245 
246 cleanup()
247 {
248 	bzero(&proto_data, sizeof(proto_data));
249 	bzero(okey, sizeof(okey));
250 	bzero(osched, sizeof(osched));
251 	bzero(random_schedule, sizeof(random_schedule));
252 }
253 
254 finish()
255 {
256 	close(sock);
257 	exit(1);
258 }
259