Commit | Line | Data |
---|---|---|
fef5a0d0 KB |
1 | /*- |
2 | * Copyright (c) 1990 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * %sccs.include.redist.c% | |
6 | */ | |
7 | ||
8 | #ifndef lint | |
2fce9a30 | 9 | static char sccsid[] = "@(#)krb_passwd.c 5.2 (Berkeley) %G%"; |
fef5a0d0 KB |
10 | #endif /* not lint */ |
11 | ||
12 | #ifdef KERBEROS | |
13 | ||
14 | #include <sys/types.h> | |
15 | #include <sys/socket.h> | |
16 | #include <sys/time.h> | |
17 | #include <sys/resource.h> | |
18 | #include <netinet/in.h> | |
19 | #include <kerberosIV/des.h> | |
20 | #include <kerberosIV/krb.h> | |
21 | #include <netdb.h> | |
22 | #include <signal.h> | |
23 | #include <pwd.h> | |
24 | #include <errno.h> | |
25 | #include <stdio.h> | |
26 | #include "kpasswd_proto.h" | |
2fce9a30 KB |
27 | #include <string.h> |
28 | #include <stdlib.h> | |
fef5a0d0 KB |
29 | |
30 | #define PROTO "tcp" | |
31 | ||
32 | static struct timeval timeout = { CLIENT_KRB_TIMEOUT, 0 }; | |
33 | static struct kpasswd_data proto_data; | |
34 | static des_cblock okey; | |
35 | static Key_schedule osched; | |
36 | KTEXT_ST ticket; | |
37 | Key_schedule random_schedule; | |
38 | long authopts; | |
39 | char realm[REALM_SZ], krbhst[MAX_HSTNM]; | |
40 | int sock; | |
41 | ||
42 | do_krb_passwd() | |
43 | { | |
44 | struct servent *se; | |
45 | struct hostent *host; | |
46 | struct sockaddr_in sin; | |
47 | CREDENTIALS cred; | |
48 | fd_set readfds; | |
49 | int rval, finish(); | |
50 | char pass[_PASSWORD_LEN], password[_PASSWORD_LEN]; | |
51 | ||
52 | static struct rlimit rl = { 0, 0 }; | |
53 | ||
54 | (void)signal(SIGHUP, SIG_IGN); | |
55 | (void)signal(SIGINT, SIG_IGN); | |
56 | (void)signal(SIGTSTP, SIG_IGN); | |
57 | ||
58 | if (setrlimit(RLIMIT_CORE, &rl) < 0) { | |
59 | (void)fprintf(stderr, | |
60 | "passwd: setrlimit: %s\n", strerror(errno)); | |
61 | return(1); | |
62 | } | |
63 | ||
64 | if ((se = getservbyname(SERVICE, PROTO)) == NULL) { | |
65 | (void)fprintf(stderr, | |
66 | "passwd: couldn't find entry for service %s/%s\n", | |
67 | SERVICE, PROTO); | |
68 | return(1); | |
69 | } | |
70 | ||
71 | if ((rval = krb_get_lrealm(realm,1)) != KSUCCESS) { | |
72 | (void)fprintf(stderr, | |
73 | "passwd: couldn't get local Kerberos realm: %s\n", | |
74 | krb_err_txt[rval]); | |
75 | return(1); | |
76 | } | |
77 | ||
78 | if ((rval = krb_get_krbhst(krbhst, realm, 1)) != KSUCCESS) { | |
79 | (void)fprintf(stderr, | |
80 | "passwd: couldn't get Kerberos host: %s\n", | |
81 | krb_err_txt[rval]); | |
82 | return(1); | |
83 | } | |
84 | ||
85 | if ((host = gethostbyname(krbhst)) == NULL) { | |
86 | (void)fprintf(stderr, | |
87 | "passwd: couldn't get host entry for krb host %s\n", | |
88 | krbhst); | |
89 | return(1); | |
90 | } | |
91 | ||
92 | sin.sin_family = host->h_addrtype; | |
93 | bcopy(host->h_addr, (char *) &sin.sin_addr, host->h_length); | |
94 | sin.sin_port = se->s_port; | |
95 | ||
96 | if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { | |
97 | (void)fprintf(stderr, "passwd: socket: %s\n", strerror(errno)); | |
98 | return(1); | |
99 | } | |
100 | ||
101 | if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) { | |
102 | (void)fprintf(stderr, "passwd: connect: %s\n", strerror(errno)); | |
103 | (void)close(sock); | |
104 | return(1); | |
105 | } | |
106 | ||
107 | rval = krb_sendauth( | |
108 | authopts, /* NOT mutual */ | |
109 | sock, | |
110 | &ticket, /* (filled in) */ | |
111 | SERVICE, | |
112 | krbhst, /* instance (krbhst) */ | |
113 | realm, /* dest realm */ | |
114 | (u_long) getpid(), /* checksum */ | |
115 | NULL, /* msg data */ | |
116 | NULL, /* credentials */ | |
117 | NULL, /* schedule */ | |
118 | NULL, /* local addr */ | |
119 | NULL, /* foreign addr */ | |
120 | "KPWDV0.1" | |
121 | ); | |
122 | ||
123 | if (rval != KSUCCESS) { | |
124 | (void)fprintf(stderr, "passwd: Kerberos sendauth error: %s\n", | |
125 | krb_err_txt[rval]); | |
126 | return(1); | |
127 | } | |
128 | ||
129 | krb_get_cred("krbtgt", realm, realm, &cred); | |
130 | ||
131 | (void)printf("Changing Kerberos password for %s.%s@%s.\n", | |
132 | cred.pname, cred.pinst, realm); | |
133 | ||
134 | if (des_read_pw_string(pass, | |
135 | sizeof(pass)-1, "Old Kerberos password:", 0)) { | |
136 | (void)fprintf(stderr, | |
137 | "passwd: error reading old Kerberos password\n"); | |
138 | return(1); | |
139 | } | |
140 | ||
141 | (void)des_string_to_key(pass, okey); | |
142 | (void)des_key_sched(okey, osched); | |
143 | (void)des_set_key(okey, osched); | |
144 | ||
145 | /* wait on the verification string */ | |
146 | ||
147 | FD_ZERO(&readfds); | |
148 | FD_SET(sock, &readfds); | |
149 | ||
150 | rval = | |
151 | select(sock + 1, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout); | |
152 | ||
153 | if ((rval < 1) || !FD_ISSET(sock, &readfds)) { | |
154 | if(rval == 0) { | |
155 | (void)fprintf(stderr, "passwd: timed out (aborted)\n"); | |
156 | cleanup(); | |
157 | return(1); | |
158 | } | |
159 | (void)fprintf(stderr, "passwd: select failed (aborted)\n"); | |
160 | cleanup(); | |
161 | return(1); | |
162 | } | |
163 | ||
164 | /* read verification string */ | |
165 | ||
166 | if (des_read(sock, &proto_data, sizeof(proto_data)) != | |
167 | sizeof(proto_data)) { | |
168 | (void)fprintf(stderr, | |
169 | "passwd: couldn't read verification string (aborted)\n"); | |
170 | cleanup(); | |
171 | return(1); | |
172 | } | |
173 | ||
174 | (void)signal(SIGHUP, finish); | |
175 | (void)signal(SIGINT, finish); | |
176 | ||
177 | if (strcmp(SECURE_STRING, proto_data.secure_msg) != 0) { | |
178 | cleanup(); | |
179 | /* don't complain loud if user just hit return */ | |
180 | if (pass == NULL || (!*pass)) | |
181 | return(0); | |
182 | (void)fprintf(stderr, "Sorry\n"); | |
183 | return(1); | |
184 | } | |
185 | ||
186 | (void)des_key_sched(proto_data.random_key, random_schedule); | |
187 | (void)des_set_key(proto_data.random_key, random_schedule); | |
188 | (void)bzero(pass, sizeof(pass)); | |
189 | ||
190 | if (des_read_pw_string(pass, | |
191 | sizeof(pass)-1, "New Kerberos password:", 0)) { | |
192 | (void)fprintf(stderr, | |
193 | "passwd: error reading new Kerberos password (aborted)\n"); | |
194 | cleanup(); | |
195 | return(1); | |
196 | } | |
197 | ||
198 | if (des_read_pw_string(password, | |
199 | sizeof(password)-1, "Retype new Kerberos password:", 0)) { | |
200 | (void)fprintf(stderr, | |
201 | "passwd: error reading new Kerberos password (aborted)\n"); | |
202 | cleanup(); | |
203 | return(1); | |
204 | } | |
205 | ||
206 | if (strcmp(password, pass) != 0) { | |
207 | (void)fprintf(stderr, | |
208 | "passwd: password mismatch (aborted)\n"); | |
209 | cleanup(); | |
210 | return(1); | |
211 | } | |
212 | ||
213 | if (strlen(pass) == 0) | |
214 | (void)printf("using NULL password\n"); | |
215 | ||
216 | send_update(sock, password, SECURE_STRING); | |
217 | ||
218 | /* wait for ACK */ | |
219 | ||
220 | FD_ZERO(&readfds); | |
221 | FD_SET(sock, &readfds); | |
222 | ||
223 | rval = | |
224 | select(sock + 1, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout); | |
225 | if ((rval < 1) || !FD_ISSET(sock, &readfds)) { | |
226 | if(rval == 0) { | |
227 | (void)fprintf(stderr, | |
228 | "passwd: timed out reading ACK (aborted)\n"); | |
229 | cleanup(); | |
230 | exit(1); | |
231 | } | |
232 | (void)fprintf(stderr, "passwd: select failed (aborted)\n"); | |
233 | cleanup(); | |
234 | exit(1); | |
235 | } | |
236 | recv_ack(sock); | |
237 | cleanup(); | |
238 | exit(0); | |
239 | } | |
240 | ||
241 | send_update(dest, pwd, str) | |
242 | int dest; | |
243 | char *pwd, *str; | |
244 | { | |
245 | static struct update_data ud; | |
246 | ||
2fce9a30 KB |
247 | (void)strncpy(ud.secure_msg, str, _PASSWORD_LEN); |
248 | (void)strncpy(ud.pw, pwd, sizeof(ud.pw)); | |
fef5a0d0 KB |
249 | if (des_write(dest, &ud, sizeof(ud)) != sizeof(ud)) { |
250 | (void)fprintf(stderr, | |
251 | "passwd: couldn't write pw update (abort)\n"); | |
2fce9a30 | 252 | bzero((char *)&ud, sizeof(ud)); |
fef5a0d0 KB |
253 | cleanup(); |
254 | exit(1); | |
255 | } | |
256 | } | |
257 | ||
258 | recv_ack(remote) | |
259 | int remote; | |
260 | { | |
261 | int cc; | |
262 | char buf[BUFSIZ]; | |
263 | ||
264 | cc = des_read(remote, buf, sizeof(buf)); | |
265 | if (cc <= 0) { | |
266 | (void)fprintf(stderr, | |
267 | "passwd: error reading acknowledgement (aborted)\n"); | |
268 | cleanup(); | |
269 | exit(1); | |
270 | } | |
271 | (void)printf("%s", buf); | |
272 | } | |
273 | ||
274 | cleanup() | |
275 | { | |
2fce9a30 KB |
276 | (void)bzero((char *)&proto_data, sizeof(proto_data)); |
277 | (void)bzero((char *)okey, sizeof(okey)); | |
278 | (void)bzero((char *)osched, sizeof(osched)); | |
279 | (void)bzero((char *)random_schedule, sizeof(random_schedule)); | |
fef5a0d0 KB |
280 | } |
281 | ||
282 | finish() | |
283 | { | |
284 | (void)close(sock); | |
285 | exit(1); | |
286 | } | |
287 | ||
288 | #endif /* KERBEROS */ |