date and time created 88/09/27 22:18:46 by bostic
[unix-history] / usr / src / libexec / rlogind / rlogind.c
CommitLineData
8c5eec2f 1/*
9c901b93
KB
2 * Copyright (c) 1983 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
8c5eec2f
DF
16 */
17
18#ifndef lint
19char copyright[] =
9c901b93 20"@(#) Copyright (c) 1983 The Regents of the University of California.\n\
8c5eec2f 21 All rights reserved.\n";
9c901b93 22#endif /* not lint */
8c5eec2f 23
a10a364d 24#ifndef lint
9c901b93
KB
25static char sccsid[] = "@(#)rlogind.c 5.17 (Berkeley) %G%";
26#endif /* not lint */
a10a364d 27
bb933cc2
MK
28/*
29 * remote login server:
30 * remuser\0
31 * locuser\0
6632767b 32 * terminal info\0
bb933cc2
MK
33 * data
34 */
35
a10a364d
BJ
36#include <stdio.h>
37#include <sys/types.h>
38#include <sys/stat.h>
39#include <sys/socket.h>
560a8855 40#include <sys/wait.h>
6632767b 41#include <sys/file.h>
c6c678f1
SL
42
43#include <netinet/in.h>
44
a10a364d
BJ
45#include <errno.h>
46#include <pwd.h>
a10a364d
BJ
47#include <signal.h>
48#include <sgtty.h>
49#include <stdio.h>
3f5b52bc 50#include <netdb.h>
3f99c0f7 51#include <syslog.h>
6632767b 52#include <strings.h>
a10a364d 53
66feb14c
KM
54# ifndef TIOCPKT_WINDOW
55# define TIOCPKT_WINDOW 0x80
56# endif TIOCPKT_WINDOW
57
312b6ead 58extern int errno;
92e31018 59int reapchild();
a10a364d 60struct passwd *getpwnam();
66feb14c 61char *malloc();
bb933cc2 62
312b6ead 63/*ARGSUSED*/
a10a364d
BJ
64main(argc, argv)
65 int argc;
66 char **argv;
67{
312b6ead 68 int on = 1, fromlen;
a10a364d
BJ
69 struct sockaddr_in from;
70
076ae92c 71 openlog("rlogind", LOG_PID | LOG_AUTH, LOG_AUTH);
bb933cc2
MK
72 fromlen = sizeof (from);
73 if (getpeername(0, &from, &fromlen) < 0) {
74 fprintf(stderr, "%s: ", argv[0]);
75 perror("getpeername");
76 _exit(1);
92e31018 77 }
bcb894cb 78 if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) {
3f99c0f7 79 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
c6c678f1 80 }
bb933cc2 81 doit(0, &from);
92e31018
SL
82}
83
a10a364d
BJ
84int child;
85int cleanup();
86int netf;
a10a364d 87char *line;
43368533 88extern char *inet_ntoa();
a10a364d 89
8210fa73
KM
90struct winsize win = { 0, 0, 0, 0 };
91
66feb14c 92
a10a364d
BJ
93doit(f, fromp)
94 int f;
95 struct sockaddr_in *fromp;
96{
6632767b 97 int i, p, t, pid, on = 1;
3f5b52bc 98 register struct hostent *hp;
43368533 99 struct hostent hostent;
6632767b 100 char c;
a10a364d
BJ
101
102 alarm(60);
103 read(f, &c, 1);
104 if (c != 0)
105 exit(1);
106 alarm(0);
1227078b 107 fromp->sin_port = ntohs((u_short)fromp->sin_port);
3f5b52bc
SL
108 hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr),
109 fromp->sin_family);
8de87e4f 110 if (hp == 0) {
43368533
KM
111 /*
112 * Only the name is used below.
113 */
114 hp = &hostent;
115 hp->h_name = inet_ntoa(fromp->sin_addr);
8de87e4f 116 }
a10a364d 117 if (fromp->sin_family != AF_INET ||
fdc1cc8b
MK
118 fromp->sin_port >= IPPORT_RESERVED ||
119 fromp->sin_port < IPPORT_RESERVED/2)
82c973f2 120 fatal(f, "Permission denied");
a10a364d
BJ
121 write(f, "", 1);
122 for (c = 'p'; c <= 's'; c++) {
123 struct stat stb;
124 line = "/dev/ptyXX";
125 line[strlen("/dev/pty")] = c;
126 line[strlen("/dev/ptyp")] = '0';
127 if (stat(line, &stb) < 0)
128 break;
129 for (i = 0; i < 16; i++) {
312b6ead
KB
130 line[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i];
131 p = open(line, O_RDWR);
a10a364d
BJ
132 if (p > 0)
133 goto gotpty;
134 }
135 }
66feb14c 136 fatal(f, "Out of ptys");
82c973f2 137 /*NOTREACHED*/
a10a364d 138gotpty:
8210fa73 139 (void) ioctl(p, TIOCSWINSZ, &win);
1227078b 140 netf = f;
a10a364d 141 line[strlen("/dev/")] = 't';
312b6ead
KB
142 t = open(line, O_RDWR);
143 if (t < 0)
144 fatalperror(f, line);
145 if (fchmod(t, 0))
146 fatalperror(f, line);
147 (void)signal(SIGHUP, SIG_IGN);
148 vhangup();
149 (void)signal(SIGHUP, SIG_DFL);
150 t = open(line, O_RDWR);
151 if (t < 0)
152 fatalperror(f, line);
153 {
154 struct sgttyb b;
155
156 (void)ioctl(t, TIOCGETP, &b);
157 b.sg_flags = RAW|ANYP;
158 (void)ioctl(t, TIOCSETP, &b);
159 }
a10a364d 160#ifdef DEBUG
312b6ead
KB
161 {
162 int tt = open("/dev/tty", O_RDWR);
163 if (tt > 0) {
164 (void)ioctl(tt, TIOCNOTTY, 0);
165 (void)close(tt);
166 }
a10a364d
BJ
167 }
168#endif
82c973f2
SL
169 pid = fork();
170 if (pid < 0)
312b6ead 171 fatalperror(f, "");
6632767b
SL
172 if (pid == 0) {
173 close(f), close(p);
174 dup2(t, 0), dup2(t, 1), dup2(t, 2);
1227078b 175 close(t);
6632767b 176 execl("/bin/login", "login", "-r", hp->h_name, 0);
312b6ead 177 fatalperror(2, "/bin/login");
6632767b
SL
178 /*NOTREACHED*/
179 }
180 close(t);
181 ioctl(f, FIONBIO, &on);
182 ioctl(p, FIONBIO, &on);
183 ioctl(p, TIOCPKT, &on);
184 signal(SIGTSTP, SIG_IGN);
185 signal(SIGCHLD, cleanup);
ad5d2c7f 186 setpgrp(0, 0);
6632767b 187 protocol(f, p);
78c1c171 188 signal(SIGCHLD, SIG_IGN);
6632767b
SL
189 cleanup();
190}
82c973f2 191
6632767b 192char magic[2] = { 0377, 0377 };
87e80234 193char oobdata[] = {TIOCPKT_WINDOW};
6632767b
SL
194
195/*
196 * Handle a "control" request (signaled by magic being present)
197 * in the data stream. For now, we are only willing to handle
198 * window size changes.
199 */
200control(pty, cp, n)
201 int pty;
202 char *cp;
203 int n;
204{
cfafdcf2 205 struct winsize w;
6632767b 206
cfafdcf2 207 if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's')
6632767b 208 return (0);
87e80234 209 oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */
cfafdcf2
KM
210 bcopy(cp+4, (char *)&w, sizeof(w));
211 w.ws_row = ntohs(w.ws_row);
212 w.ws_col = ntohs(w.ws_col);
213 w.ws_xpixel = ntohs(w.ws_xpixel);
214 w.ws_ypixel = ntohs(w.ws_ypixel);
215 (void)ioctl(pty, TIOCSWINSZ, &w);
216 return (4+sizeof (w));
6632767b
SL
217}
218
219/*
220 * rlogin "protocol" machine.
221 */
222protocol(f, p)
223 int f, p;
224{
225 char pibuf[1024], fibuf[1024], *pbp, *fbp;
226 register pcc = 0, fcc = 0;
87e80234 227 int cc;
2c360ad3 228 char cntl;
6632767b 229
ffaf1c0b 230 /*
9ee4d121
SL
231 * Must ignore SIGTTOU, otherwise we'll stop
232 * when we try and set slave pty's window shape
87e80234 233 * (our controlling tty is the master pty).
ffaf1c0b 234 */
9ee4d121 235 (void) signal(SIGTTOU, SIG_IGN);
87e80234 236 send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */
6632767b 237 for (;;) {
2c360ad3 238 int ibits, obits, ebits;
6632767b 239
2c360ad3
MK
240 ibits = 0;
241 obits = 0;
6632767b
SL
242 if (fcc)
243 obits |= (1<<p);
244 else
245 ibits |= (1<<f);
246 if (pcc >= 0)
247 if (pcc)
248 obits |= (1<<f);
82c973f2 249 else
6632767b 250 ibits |= (1<<p);
2c360ad3
MK
251 ebits = (1<<p);
252 if (select(16, &ibits, &obits, &ebits, 0) < 0) {
6632767b 253 if (errno == EINTR)
a10a364d 254 continue;
312b6ead 255 fatalperror(f, "select");
6632767b 256 }
2c360ad3 257 if (ibits == 0 && obits == 0 && ebits == 0) {
6632767b
SL
258 /* shouldn't happen... */
259 sleep(5);
260 continue;
261 }
2c360ad3
MK
262#define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))
263 if (ebits & (1<<p)) {
264 cc = read(p, &cntl, 1);
265 if (cc == 1 && pkcontrol(cntl)) {
266 cntl |= oobdata[0];
267 send(f, &cntl, 1, MSG_OOB);
268 if (cntl & TIOCPKT_FLUSHWRITE) {
269 pcc = 0;
270 ibits &= ~(1<<p);
271 }
272 }
273 }
6632767b
SL
274 if (ibits & (1<<f)) {
275 fcc = read(f, fibuf, sizeof (fibuf));
276 if (fcc < 0 && errno == EWOULDBLOCK)
277 fcc = 0;
278 else {
279 register char *cp;
280 int left, n;
281
282 if (fcc <= 0)
1227078b 283 break;
6632767b 284 fbp = fibuf;
66feb14c 285
6632767b 286 top:
87e80234 287 for (cp = fibuf; cp < fibuf+fcc-1; cp++)
6632767b
SL
288 if (cp[0] == magic[0] &&
289 cp[1] == magic[1]) {
290 left = fcc - (cp-fibuf);
291 n = control(p, cp, left);
292 if (n) {
293 left -= n;
294 if (left > 0)
87e80234 295 bcopy(cp+n, cp, left);
6632767b
SL
296 fcc -= n;
297 goto top; /* n^2 */
87e80234
MK
298 }
299 }
300 }
301 }
66feb14c
KM
302
303 if ((obits & (1<<p)) && fcc > 0) {
87e80234 304 cc = write(p, fbp, fcc);
66feb14c
KM
305 if (cc > 0) {
306 fcc -= cc;
307 fbp += cc;
a10a364d 308 }
6632767b 309 }
66feb14c 310
6632767b
SL
311 if (ibits & (1<<p)) {
312 pcc = read(p, pibuf, sizeof (pibuf));
313 pbp = pibuf;
314 if (pcc < 0 && errno == EWOULDBLOCK)
315 pcc = 0;
316 else if (pcc <= 0)
317 break;
318 else if (pibuf[0] == 0)
319 pbp++, pcc--;
320 else {
6632767b 321 if (pkcontrol(pibuf[0])) {
87e80234 322 pibuf[0] |= oobdata[0];
6632767b 323 send(f, &pibuf[0], 1, MSG_OOB);
a10a364d 324 }
6632767b 325 pcc = 0;
a10a364d 326 }
6632767b
SL
327 }
328 if ((obits & (1<<f)) && pcc > 0) {
87e80234
MK
329 cc = write(f, pbp, pcc);
330 if (cc < 0 && errno == EWOULDBLOCK) {
331 /* also shouldn't happen */
332 sleep(5);
333 continue;
334 }
6632767b
SL
335 if (cc > 0) {
336 pcc -= cc;
337 pbp += cc;
338 }
339 }
a10a364d 340 }
a10a364d
BJ
341}
342
343cleanup()
344{
6487d192
KB
345 char *p;
346
347 p = line + sizeof("/dev/") - 1;
348 if (logout(p))
349 logwtmp(p, "", "");
350 (void)chmod(line, 0666);
351 (void)chown(line, 0, 0);
352 *p = 'p';
353 (void)chmod(line, 0666);
354 (void)chown(line, 0, 0);
ff24c640 355 shutdown(netf, 2);
a10a364d
BJ
356 exit(1);
357}
358
82c973f2
SL
359fatal(f, msg)
360 int f;
361 char *msg;
362{
363 char buf[BUFSIZ];
364
365 buf[0] = '\01'; /* error indicator */
560a8855 366 (void) sprintf(buf + 1, "rlogind: %s.\r\n", msg);
82c973f2
SL
367 (void) write(f, buf, strlen(buf));
368 exit(1);
369}
370
312b6ead 371fatalperror(f, msg)
82c973f2
SL
372 int f;
373 char *msg;
82c973f2
SL
374{
375 char buf[BUFSIZ];
1227078b 376 extern int sys_nerr;
82c973f2
SL
377 extern char *sys_errlist[];
378
6632767b 379 if ((unsigned)errno < sys_nerr)
1227078b
MK
380 (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]);
381 else
382 (void) sprintf(buf, "%s: Error %d", msg, errno);
82c973f2
SL
383 fatal(f, buf);
384}