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