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