rework the password subsystem
[unix-history] / usr / src / usr.bin / passwd / krb_passwd.c
CommitLineData
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 9static 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
32static struct timeval timeout = { CLIENT_KRB_TIMEOUT, 0 };
33static struct kpasswd_data proto_data;
34static des_cblock okey;
35static Key_schedule osched;
36KTEXT_ST ticket;
37Key_schedule random_schedule;
38long authopts;
39char realm[REALM_SZ], krbhst[MAX_HSTNM];
40int sock;
41
42do_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
241send_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
258recv_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
274cleanup()
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
282finish()
283{
284 (void)close(sock);
285 exit(1);
286}
287
288#endif /* KERBEROS */