|
|
1.1 root 1: /*
2: * Copyright (c) 1983 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: char copyright[] =
9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
10: All rights reserved.\n";
11: #endif not lint
12:
13: #ifndef lint
14: static char sccsid[] = "@(#)rlogind.c 5.15 (Berkeley) 5/23/88";
15: #endif not lint
16:
17: /*
18: * remote login server:
19: * remuser\0
20: * locuser\0
21: * terminal info\0
22: * data
23: */
24:
25: #include <stdio.h>
26: #include <sys/types.h>
27: #include <sys/stat.h>
28: #include <sys/socket.h>
29: #include <sys/wait.h>
30: #include <sys/file.h>
31:
32: #include <netinet/in.h>
33:
34: #include <errno.h>
35: #include <pwd.h>
36: #include <signal.h>
37: #include <sgtty.h>
38: #include <stdio.h>
39: #include <netdb.h>
40: #include <syslog.h>
41: #include <strings.h>
42:
43: # ifndef TIOCPKT_WINDOW
44: # define TIOCPKT_WINDOW 0x80
45: # endif TIOCPKT_WINDOW
46:
47: extern int errno;
48: int reapchild();
49: struct passwd *getpwnam();
50: char *malloc();
51:
52: /*ARGSUSED*/
53: main(argc, argv)
54: int argc;
55: char **argv;
56: {
57: int on = 1, fromlen;
58: struct sockaddr_in from;
59:
60: openlog("rlogind", LOG_PID | LOG_AUTH, LOG_AUTH);
61: fromlen = sizeof (from);
62: if (getpeername(0, &from, &fromlen) < 0) {
63: fprintf(stderr, "%s: ", argv[0]);
64: perror("getpeername");
65: _exit(1);
66: }
67: if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) {
68: syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
69: }
70: doit(0, &from);
71: }
72:
73: int child;
74: int cleanup();
75: int netf;
76: char *line;
77: extern char *inet_ntoa();
78:
79: struct winsize win = { 0, 0, 0, 0 };
80:
81:
82: doit(f, fromp)
83: int f;
84: struct sockaddr_in *fromp;
85: {
86: int i, p, t, pid, on = 1;
87: register struct hostent *hp;
88: struct hostent hostent;
89: char c;
90:
91: alarm(60);
92: read(f, &c, 1);
93: if (c != 0)
94: exit(1);
95: alarm(0);
96: fromp->sin_port = ntohs((u_short)fromp->sin_port);
97: hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr),
98: fromp->sin_family);
99: if (hp == 0) {
100: /*
101: * Only the name is used below.
102: */
103: hp = &hostent;
104: hp->h_name = inet_ntoa(fromp->sin_addr);
105: }
106: if (fromp->sin_family != AF_INET ||
107: fromp->sin_port >= IPPORT_RESERVED ||
108: fromp->sin_port < IPPORT_RESERVED/2)
109: fatal(f, "Permission denied");
110: write(f, "", 1);
111: for (c = 'p'; c <= 's'; c++) {
112: struct stat stb;
113: line = "/dev/ptyXX";
114: line[strlen("/dev/pty")] = c;
115: line[strlen("/dev/ptyp")] = '0';
116: if (stat(line, &stb) < 0)
117: break;
118: for (i = 0; i < 16; i++) {
119: line[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i];
120: p = open(line, O_RDWR);
121: if (p > 0)
122: goto gotpty;
123: }
124: }
125: fatal(f, "Out of ptys");
126: /*NOTREACHED*/
127: gotpty:
128: (void) ioctl(p, TIOCSWINSZ, &win);
129: netf = f;
130: line[strlen("/dev/")] = 't';
131: t = open(line, O_RDWR);
132: if (t < 0)
133: fatalperror(f, line);
134: if (fchmod(t, 0))
135: fatalperror(f, line);
136: (void)signal(SIGHUP, SIG_IGN);
137: vhangup();
138: (void)signal(SIGHUP, SIG_DFL);
139: t = open(line, O_RDWR);
140: if (t < 0)
141: fatalperror(f, line);
142: {
143: struct sgttyb b;
144:
145: (void)ioctl(t, TIOCGETP, &b);
146: b.sg_flags = RAW|ANYP;
147: (void)ioctl(t, TIOCSETP, &b);
148: }
149: #ifdef DEBUG
150: {
151: int tt = open("/dev/tty", O_RDWR);
152: if (tt > 0) {
153: (void)ioctl(tt, TIOCNOTTY, 0);
154: (void)close(tt);
155: }
156: }
157: #endif
158: pid = fork();
159: if (pid < 0)
160: fatalperror(f, "");
161: if (pid == 0) {
162: close(f), close(p);
163: dup2(t, 0), dup2(t, 1), dup2(t, 2);
164: close(t);
165: execl("/bin/login", "login", "-r", hp->h_name, 0);
166: fatalperror(2, "/bin/login");
167: /*NOTREACHED*/
168: }
169: close(t);
170: ioctl(f, FIONBIO, &on);
171: ioctl(p, FIONBIO, &on);
172: ioctl(p, TIOCPKT, &on);
173: signal(SIGTSTP, SIG_IGN);
174: signal(SIGCHLD, cleanup);
175: setpgrp(0, 0);
176: protocol(f, p);
177: signal(SIGCHLD, SIG_IGN);
178: cleanup();
179: }
180:
181: char magic[2] = { 0377, 0377 };
182: char oobdata[] = {TIOCPKT_WINDOW};
183:
184: /*
185: * Handle a "control" request (signaled by magic being present)
186: * in the data stream. For now, we are only willing to handle
187: * window size changes.
188: */
189: control(pty, cp, n)
190: int pty;
191: char *cp;
192: int n;
193: {
194: struct winsize w;
195:
196: if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's')
197: return (0);
198: oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */
199: bcopy(cp+4, (char *)&w, sizeof(w));
200: w.ws_row = ntohs(w.ws_row);
201: w.ws_col = ntohs(w.ws_col);
202: w.ws_xpixel = ntohs(w.ws_xpixel);
203: w.ws_ypixel = ntohs(w.ws_ypixel);
204: (void)ioctl(pty, TIOCSWINSZ, &w);
205: return (4+sizeof (w));
206: }
207:
208: /*
209: * rlogin "protocol" machine.
210: */
211: protocol(f, p)
212: int f, p;
213: {
214: char pibuf[1024], fibuf[1024], *pbp, *fbp;
215: register pcc = 0, fcc = 0;
216: int cc;
217: char cntl;
218:
219: /*
220: * Must ignore SIGTTOU, otherwise we'll stop
221: * when we try and set slave pty's window shape
222: * (our controlling tty is the master pty).
223: */
224: (void) signal(SIGTTOU, SIG_IGN);
225: send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */
226: for (;;) {
227: int ibits, obits, ebits;
228:
229: ibits = 0;
230: obits = 0;
231: if (fcc)
232: obits |= (1<<p);
233: else
234: ibits |= (1<<f);
235: if (pcc >= 0)
236: if (pcc)
237: obits |= (1<<f);
238: else
239: ibits |= (1<<p);
240: ebits = (1<<p);
241: if (select(16, &ibits, &obits, &ebits, 0) < 0) {
242: if (errno == EINTR)
243: continue;
244: fatalperror(f, "select");
245: }
246: if (ibits == 0 && obits == 0 && ebits == 0) {
247: /* shouldn't happen... */
248: sleep(5);
249: continue;
250: }
251: #define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))
252: if (ebits & (1<<p)) {
253: cc = read(p, &cntl, 1);
254: if (cc == 1 && pkcontrol(cntl)) {
255: cntl |= oobdata[0];
256: send(f, &cntl, 1, MSG_OOB);
257: if (cntl & TIOCPKT_FLUSHWRITE) {
258: pcc = 0;
259: ibits &= ~(1<<p);
260: }
261: }
262: }
263: if (ibits & (1<<f)) {
264: fcc = read(f, fibuf, sizeof (fibuf));
265: if (fcc < 0 && errno == EWOULDBLOCK)
266: fcc = 0;
267: else {
268: register char *cp;
269: int left, n;
270:
271: if (fcc <= 0)
272: break;
273: fbp = fibuf;
274:
275: top:
276: for (cp = fibuf; cp < fibuf+fcc-1; cp++)
277: if (cp[0] == magic[0] &&
278: cp[1] == magic[1]) {
279: left = fcc - (cp-fibuf);
280: n = control(p, cp, left);
281: if (n) {
282: left -= n;
283: if (left > 0)
284: bcopy(cp+n, cp, left);
285: fcc -= n;
286: goto top; /* n^2 */
287: }
288: }
289: }
290: }
291:
292: if ((obits & (1<<p)) && fcc > 0) {
293: cc = write(p, fbp, fcc);
294: if (cc > 0) {
295: fcc -= cc;
296: fbp += cc;
297: }
298: }
299:
300: if (ibits & (1<<p)) {
301: pcc = read(p, pibuf, sizeof (pibuf));
302: pbp = pibuf;
303: if (pcc < 0 && errno == EWOULDBLOCK)
304: pcc = 0;
305: else if (pcc <= 0)
306: break;
307: else if (pibuf[0] == 0)
308: pbp++, pcc--;
309: else {
310: if (pkcontrol(pibuf[0])) {
311: pibuf[0] |= oobdata[0];
312: send(f, &pibuf[0], 1, MSG_OOB);
313: }
314: pcc = 0;
315: }
316: }
317: if ((obits & (1<<f)) && pcc > 0) {
318: cc = write(f, pbp, pcc);
319: if (cc < 0 && errno == EWOULDBLOCK) {
320: /* also shouldn't happen */
321: sleep(5);
322: continue;
323: }
324: if (cc > 0) {
325: pcc -= cc;
326: pbp += cc;
327: }
328: }
329: }
330: }
331:
332: cleanup()
333: {
334: rmut();
335: shutdown(netf, 2);
336: exit(1);
337: }
338:
339: fatal(f, msg)
340: int f;
341: char *msg;
342: {
343: char buf[BUFSIZ];
344:
345: buf[0] = '\01'; /* error indicator */
346: (void) sprintf(buf + 1, "rlogind: %s.\r\n", msg);
347: (void) write(f, buf, strlen(buf));
348: exit(1);
349: }
350:
351: fatalperror(f, msg)
352: int f;
353: char *msg;
354: {
355: char buf[BUFSIZ];
356: extern int sys_nerr;
357: extern char *sys_errlist[];
358:
359: if ((unsigned)errno < sys_nerr)
360: (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]);
361: else
362: (void) sprintf(buf, "%s: Error %d", msg, errno);
363: fatal(f, buf);
364: }
365:
366: #include <utmp.h>
367:
368: struct utmp wtmp;
369: char wtmpf[] = "/usr/adm/wtmp";
370: char utmpf[] = "/etc/utmp";
371: #define SCPYN(a, b) strncpy(a, b, sizeof(a))
372: #define SCMPN(a, b) strncmp(a, b, sizeof(a))
373:
374: rmut()
375: {
376: register f;
377: int found = 0;
378: struct utmp *u, *utmp;
379: int nutmp;
380: struct stat statbf;
381:
382: f = open(utmpf, O_RDWR);
383: if (f >= 0) {
384: fstat(f, &statbf);
385: utmp = (struct utmp *)malloc(statbf.st_size);
386: if (!utmp)
387: syslog(LOG_ERR, "utmp malloc failed");
388: if (statbf.st_size && utmp) {
389: nutmp = read(f, utmp, statbf.st_size);
390: nutmp /= sizeof(struct utmp);
391:
392: for (u = utmp ; u < &utmp[nutmp] ; u++) {
393: if (SCMPN(u->ut_line, line+5) ||
394: u->ut_name[0]==0)
395: continue;
396: lseek(f, ((long)u)-((long)utmp), L_SET);
397: SCPYN(u->ut_name, "");
398: SCPYN(u->ut_host, "");
399: time(&u->ut_time);
400: write(f, (char *)u, sizeof(wtmp));
401: found++;
402: }
403: }
404: close(f);
405: }
406: if (found) {
407: f = open(wtmpf, O_WRONLY|O_APPEND);
408: if (f >= 0) {
409: SCPYN(wtmp.ut_line, line+5);
410: SCPYN(wtmp.ut_name, "");
411: SCPYN(wtmp.ut_host, "");
412: time(&wtmp.ut_time);
413: write(f, (char *)&wtmp, sizeof(wtmp));
414: close(f);
415: }
416: }
417: chmod(line, 0666);
418: chown(line, 0, 0);
419: line[strlen("/dev/")] = 'p';
420: chmod(line, 0666);
421: chown(line, 0, 0);
422: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.