Annotation of src/usr.bin/passwd/krb_passwd.c, Revision 1.2
1.1 deraadt 1: /*-
2: * Copyright (c) 1990 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: */
33:
34: #ifndef lint
35: /*static char sccsid[] = "from: @(#)krb_passwd.c 5.4 (Berkeley) 3/1/91";*/
1.2 ! tholo 36: static char rcsid[] = "$Id: krb_passwd.c,v 1.1.1.1 1995/10/18 08:45:53 deraadt Exp $";
1.1 deraadt 37: #endif /* not lint */
38:
39: #ifdef KERBEROS
40:
41: #include <sys/types.h>
42: #include <sys/socket.h>
43: #include <sys/time.h>
44: #include <sys/resource.h>
45: #include <netinet/in.h>
46: #include <kerberosIV/des.h>
47: #include <kerberosIV/krb.h>
48: #include <netdb.h>
49: #include <signal.h>
50: #include <pwd.h>
51: #include <errno.h>
52: #include <stdio.h>
53: #include "kpasswd_proto.h"
54: #include <string.h>
55: #include <stdlib.h>
56:
57: #define PROTO "tcp"
58:
59: static struct timeval timeout = { CLIENT_KRB_TIMEOUT, 0 };
60: static struct kpasswd_data proto_data;
61: static des_cblock okey;
62: static Key_schedule osched;
63: KTEXT_ST ticket;
64: Key_schedule random_schedule;
65: long authopts;
66: char realm[REALM_SZ], krbhst[MAX_HSTNM];
67: int sock;
68:
69: krb_passwd()
70: {
71: struct servent *se;
72: struct hostent *host;
73: struct sockaddr_in sin;
74: CREDENTIALS cred;
75: fd_set readfds;
76: int rval;
77: char pass[_PASSWORD_LEN], password[_PASSWORD_LEN];
78: static void finish();
79:
80: static struct rlimit rl = { 0, 0 };
81:
82: (void)signal(SIGHUP, SIG_IGN);
83: (void)signal(SIGINT, SIG_IGN);
84: (void)signal(SIGTSTP, SIG_IGN);
85:
86: if (setrlimit(RLIMIT_CORE, &rl) < 0) {
87: (void)fprintf(stderr,
88: "passwd: setrlimit: %s\n", strerror(errno));
89: return(1);
90: }
91:
92: if ((se = getservbyname(SERVICE, PROTO)) == NULL) {
93: (void)fprintf(stderr,
94: "passwd: couldn't find entry for service %s/%s\n",
95: SERVICE, PROTO);
96: return(1);
97: }
98:
99: if ((rval = krb_get_lrealm(realm,1)) != KSUCCESS) {
100: (void)fprintf(stderr,
101: "passwd: couldn't get local Kerberos realm: %s\n",
102: krb_err_txt[rval]);
103: return(1);
104: }
105:
106: if ((rval = krb_get_krbhst(krbhst, realm, 1)) != KSUCCESS) {
107: (void)fprintf(stderr,
108: "passwd: couldn't get Kerberos host: %s\n",
109: krb_err_txt[rval]);
110: return(1);
111: }
112:
113: if ((host = gethostbyname(krbhst)) == NULL) {
114: (void)fprintf(stderr,
115: "passwd: couldn't get host entry for krb host %s\n",
116: krbhst);
117: return(1);
118: }
119:
120: sin.sin_family = host->h_addrtype;
121: bcopy(host->h_addr, (char *) &sin.sin_addr, host->h_length);
122: sin.sin_port = se->s_port;
123:
124: if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
125: (void)fprintf(stderr, "passwd: socket: %s\n", strerror(errno));
126: return(1);
127: }
128:
129: if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
130: (void)fprintf(stderr, "passwd: connect: %s\n", strerror(errno));
131: (void)close(sock);
132: return(1);
133: }
134:
135: rval = krb_sendauth(
136: authopts, /* NOT mutual */
137: sock,
138: &ticket, /* (filled in) */
139: SERVICE,
140: krbhst, /* instance (krbhst) */
141: realm, /* dest realm */
142: (u_long) getpid(), /* checksum */
143: NULL, /* msg data */
144: NULL, /* credentials */
145: NULL, /* schedule */
146: NULL, /* local addr */
147: NULL, /* foreign addr */
148: "KPWDV0.1"
149: );
150:
151: if (rval != KSUCCESS) {
152: (void)fprintf(stderr, "passwd: Kerberos sendauth error: %s\n",
153: krb_err_txt[rval]);
154: return(1);
155: }
156:
157: krb_get_cred("krbtgt", realm, realm, &cred);
158:
159: (void)printf("Changing Kerberos password for %s.%s@%s.\n",
160: cred.pname, cred.pinst, realm);
161:
162: if (des_read_pw_string(pass,
163: sizeof(pass)-1, "Old Kerberos password:", 0)) {
164: (void)fprintf(stderr,
165: "passwd: error reading old Kerberos password\n");
166: return(1);
167: }
168:
1.2 ! tholo 169: (void)des_string_to_key(pass, &okey);
! 170: (void)des_key_sched(&okey, osched);
! 171: (void)des_set_key(&okey, osched);
1.1 deraadt 172:
173: /* wait on the verification string */
174:
175: FD_ZERO(&readfds);
176: FD_SET(sock, &readfds);
177:
178: rval =
179: select(sock + 1, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout);
180:
181: if ((rval < 1) || !FD_ISSET(sock, &readfds)) {
182: if(rval == 0) {
183: (void)fprintf(stderr, "passwd: timed out (aborted)\n");
184: cleanup();
185: return(1);
186: }
187: (void)fprintf(stderr, "passwd: select failed (aborted)\n");
188: cleanup();
189: return(1);
190: }
191:
192: /* read verification string */
193:
194: if (des_read(sock, &proto_data, sizeof(proto_data)) !=
195: sizeof(proto_data)) {
196: (void)fprintf(stderr,
197: "passwd: couldn't read verification string (aborted)\n");
198: cleanup();
199: return(1);
200: }
201:
202: (void)signal(SIGHUP, finish);
203: (void)signal(SIGINT, finish);
204:
205: if (strcmp(SECURE_STRING, proto_data.secure_msg) != 0) {
206: cleanup();
207: /* don't complain loud if user just hit return */
208: if (pass == NULL || (!*pass))
209: return(0);
210: (void)fprintf(stderr, "Sorry\n");
211: return(1);
212: }
213:
1.2 ! tholo 214: (void)des_key_sched(&proto_data.random_key, random_schedule);
! 215: (void)des_set_key(&proto_data.random_key, random_schedule);
1.1 deraadt 216: (void)bzero(pass, sizeof(pass));
217:
218: if (des_read_pw_string(pass,
219: sizeof(pass)-1, "New Kerberos password:", 0)) {
220: (void)fprintf(stderr,
221: "passwd: error reading new Kerberos password (aborted)\n");
222: cleanup();
223: return(1);
224: }
225:
226: if (des_read_pw_string(password,
227: sizeof(password)-1, "Retype new Kerberos password:", 0)) {
228: (void)fprintf(stderr,
229: "passwd: error reading new Kerberos password (aborted)\n");
230: cleanup();
231: return(1);
232: }
233:
234: if (strcmp(password, pass) != 0) {
235: (void)fprintf(stderr,
236: "passwd: password mismatch (aborted)\n");
237: cleanup();
238: return(1);
239: }
240:
241: if (strlen(pass) == 0)
242: (void)printf("using NULL password\n");
243:
244: send_update(sock, password, SECURE_STRING);
245:
246: /* wait for ACK */
247:
248: FD_ZERO(&readfds);
249: FD_SET(sock, &readfds);
250:
251: rval =
252: select(sock + 1, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout);
253: if ((rval < 1) || !FD_ISSET(sock, &readfds)) {
254: if(rval == 0) {
255: (void)fprintf(stderr,
256: "passwd: timed out reading ACK (aborted)\n");
257: cleanup();
258: exit(1);
259: }
260: (void)fprintf(stderr, "passwd: select failed (aborted)\n");
261: cleanup();
262: exit(1);
263: }
264: recv_ack(sock);
265: cleanup();
266: exit(0);
267: }
268:
269: send_update(dest, pwd, str)
270: int dest;
271: char *pwd, *str;
272: {
273: static struct update_data ud;
274:
275: (void)strncpy(ud.secure_msg, str, _PASSWORD_LEN);
276: (void)strncpy(ud.pw, pwd, sizeof(ud.pw));
277: if (des_write(dest, &ud, sizeof(ud)) != sizeof(ud)) {
278: (void)fprintf(stderr,
279: "passwd: couldn't write pw update (abort)\n");
280: bzero((char *)&ud, sizeof(ud));
281: cleanup();
282: exit(1);
283: }
284: }
285:
286: recv_ack(remote)
287: int remote;
288: {
289: int cc;
290: char buf[BUFSIZ];
291:
292: cc = des_read(remote, buf, sizeof(buf));
293: if (cc <= 0) {
294: (void)fprintf(stderr,
295: "passwd: error reading acknowledgement (aborted)\n");
296: cleanup();
297: exit(1);
298: }
299: (void)printf("%s", buf);
300: }
301:
302: cleanup()
303: {
304: (void)bzero((char *)&proto_data, sizeof(proto_data));
305: (void)bzero((char *)okey, sizeof(okey));
306: (void)bzero((char *)osched, sizeof(osched));
307: (void)bzero((char *)random_schedule, sizeof(random_schedule));
308: }
309:
310: static void
311: finish()
312: {
313: (void)close(sock);
314: exit(1);
315: }
316:
317: #endif /* KERBEROS */