prettyness police
[unix-history] / usr / src / usr.bin / passwd / krb_passwd.c
CommitLineData
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 9static 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
38static void send_update __P((int, char *, char *));
39static void recv_ack __P((int));
40static void cleanup __P((void));
41static void finish __P((void));
42
fef5a0d0
KB
43static struct timeval timeout = { CLIENT_KRB_TIMEOUT, 0 };
44static struct kpasswd_data proto_data;
45static des_cblock okey;
46static Key_schedule osched;
c09e47ff
JSP
47static KTEXT_ST ticket;
48static Key_schedule random_schedule;
49static long authopts;
50static char realm[REALM_SZ], krbhst[MAX_HSTNM];
51static int sock;
fef5a0d0 52
c09e47ff 53int
51611a4e 54krb_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 242static void
fef5a0d0
KB
243send_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 259static void
fef5a0d0
KB
260recv_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 275static void
fef5a0d0
KB
276cleanup()
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 285static void
fef5a0d0
KB
286finish()
287{
c09e47ff 288
fef5a0d0
KB
289 (void)close(sock);
290 exit(1);
291}
292
293#endif /* KERBEROS */