|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)rlogind.c 4.18 83/07/01";
3: #endif
4:
5: #include <stdio.h>
6: #include <sys/types.h>
7: #include <sys/stat.h>
8: #include <sys/socket.h>
9: #include <sys/wait.h>
10:
11: #include <netinet/in.h>
12:
13: #include <errno.h>
14: #include <pwd.h>
15: #include <signal.h>
16: #include <sgtty.h>
17: #include <stdio.h>
18: #include <netdb.h>
19:
20: extern errno;
21: int reapchild();
22: struct passwd *getpwnam();
23: char *crypt(), *rindex(), *index(), *malloc(), *ntoa();
24: struct sockaddr_in sin = { AF_INET };
25: /*
26: * remote login server:
27: * remuser\0
28: * locuser\0
29: * terminal type\0
30: * data
31: *
32: * Changes:
33: * . dont time out (for 1/2 hour) if the remote host name
34: * is in /etc/keeprlogin
35: */
36: main(argc, argv)
37: int argc;
38: char **argv;
39: {
40: int f, options = 0;
41: int cnterr = 0;
42: struct sockaddr_in from;
43: struct servent *sp;
44:
45: sp = getservbyname("login", "tcp");
46: if (sp == 0) {
47: fprintf(stderr, "rlogind: tcp/rlogin: unknown service\n");
48: exit(1);
49: }
50: #ifndef DEBUG
51: if (fork())
52: exit(0);
53: /* redirect stdin, stdout, stderr to console */
54: close(0);
55: if ( open("/dev/console", 2) < 0 ) {
56: perror("rlogind:cannot open console\n");
57: exit(0);
58: }
59: (void) dup2(0, 1);
60: (void) dup2(0, 2);
61: for (f = 3; f < 10; f++)
62: (void) close(f);
63: { int tt = open("/dev/tty", 2);
64: if (tt > 0) {
65: ioctl(tt, TIOCNOTTY, 0);
66: close(tt);
67: }
68: }
69: #endif
70: sin.sin_port = sp->s_port;
71: argc--, argv++;
72: if (argc > 0 && !strcmp(argv[0], "-d")) {
73: options |= SO_DEBUG;
74: argc--, argv++;
75: }
76: if (argc > 0) {
77: int port = atoi(argv[0]);
78:
79: if (port < 0) {
80: fprintf(stderr, "%s: bad port #\n", argv[0]);
81: exit(1);
82: }
83: sin.sin_port = htons((u_short)port);
84: argv++, argc--;
85: }
86: f = socket(AF_INET, SOCK_STREAM, 0, 0);
87: if (f < 0) {
88: perror("rlogind: socket");
89: exit(1);
90: }
91: if (options & SO_DEBUG)
92: if (setsockopt(f, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
93: perror("rlogind: setsockopt (SO_DEBUG)");
94: /*
95: if (setsockopt(f, SOL_SOCKET, SO_KEEPALIVE, 0, 0) < 0)
96: perror("rlogind: setsockopt (SO_KEEPALIVE)");
97: */
98: if (bind(f, &sin, sizeof (sin), 0) < 0) {
99: perror("rlogind: bind");
100: exit(1);
101: }
102: signal(SIGCHLD, reapchild);
103: listen(f, 10);
104: for (;cnterr < 20;) {
105: int child;
106: int s, len = sizeof (from);
107:
108: s = accept(f, &from, &len, 0);
109: if (s < 0) {
110: if (errno == EINTR)
111: continue;
112: perror("rlogind: accept");
113: ++cnterr;
114: sleep(5);
115: continue;
116: }
117: child = fork();
118:
119: if (child <0) {
120: perror("rlogind: cannot fork");
121: sleep(5);
122: continue;
123: }
124: else if (child == 0) {
125: signal(SIGCHLD, SIG_IGN);
126: close(f);
127: cnterr = 0;
128: doit(s, &from);
129: }
130: /* all is well here. reset error counter */
131: cnterr = 0;
132: close(s);
133: }
134: fprintf(stderr,"rlogind terminates. too many errors\n");
135: }
136:
137: reapchild()
138: {
139: union wait status;
140:
141: while (wait3(&status, WNOHANG, 0) > 0)
142: ;
143: }
144:
145: char locuser[32], remuser[32];
146: char buf[BUFSIZ];
147: int child;
148: int cleanup();
149: int netf;
150: extern errno;
151: char *line;
152:
153: doit(f, fromp)
154: int f;
155: struct sockaddr_in *fromp;
156: {
157: char c;
158: int i, p, cc, t, pid;
159: int stop = TIOCPKT_DOSTOP;
160: register struct hostent *hp;
161:
162: alarm(60);
163: read(f, &c, 1);
164: if (c != 0)
165: exit(1);
166: alarm(0);
167: fromp->sin_port = htons((u_short)fromp->sin_port);
168: hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr),
169: fromp->sin_family);
170: if (hp == 0) {
171: char buf[BUFSIZ], *cp = (char *)&fromp->sin_addr;
172:
173: fatal(f, sprintf(buf, "Host name for your address (%s) unknown",
174: ntoa(fromp->sin_addr)));
175: }
176: if (!keeplogin(hp->h_name) &&
177: setsockopt(f, SOL_SOCKET, SO_KEEPALIVE, 0, 0) < 0)
178: perror("rlogind: setsockopt (SO_KEEPALIVE)");
179:
180: if (fromp->sin_family != AF_INET ||
181: fromp->sin_port >= IPPORT_RESERVED ||
182: hp == 0)
183: fatal(f, "Permission denied");
184: write(f, "", 1);
185: for (c = 'p'; c <= 's'; c++) {
186: struct stat stb;
187: line = "/dev/ptyXX";
188: line[strlen("/dev/pty")] = c;
189: line[strlen("/dev/ptyp")] = '0';
190: if (stat(line, &stb) < 0)
191: break;
192: for (i = 0; i < 16; i++) {
193: line[strlen("/dev/ptyp")] = "0123456789abcdef"[i];
194: p = open(line, 2);
195: if (p > 0)
196: goto gotpty;
197: }
198: }
199: fatal(f, "All network ports in use");
200: /*NOTREACHED*/
201: gotpty:
202: dup2(f, 0);
203: line[strlen("/dev/")] = 't';
204: #ifdef DEBUG
205: { int tt = open("/dev/tty", 2);
206: if (tt > 0) {
207: ioctl(tt, TIOCNOTTY, 0);
208: close(tt);
209: }
210: }
211: #endif
212: t = open(line, 2);
213: if (t < 0)
214: fatalperror(f, line, errno);
215: { struct sgttyb b;
216: gtty(t, &b); b.sg_flags = RAW|ANYP; stty(t, &b);
217: }
218: pid = fork();
219: if (pid < 0)
220: fatalperror(f, "", errno);
221: if (pid) {
222: char pibuf[1024], fibuf[1024], *pbp, *fbp;
223: int pcc = 0, fcc = 0, on = 1;
224: /* FILE *console = fopen("/dev/console", "w"); */
225: /* setbuf(console, 0); */
226:
227: /* fprintf(console, "f %d p %d\r\n", f, p); */
228: ioctl(f, FIONBIO, &on);
229: ioctl(p, FIONBIO, &on);
230: ioctl(p, TIOCPKT, &on);
231: signal(SIGTSTP, SIG_IGN);
232: signal(SIGCHLD, cleanup);
233: for (;;) {
234: int ibits = 0, obits = 0;
235:
236: if (fcc)
237: obits |= (1<<p);
238: else
239: ibits |= (1<<f);
240: if (pcc >= 0)
241: if (pcc)
242: obits |= (1<<f);
243: else
244: ibits |= (1<<p);
245: if (fcc < 0 && pcc < 0)
246: break;
247: /* fprintf(console, "ibits from %d obits from %d\r\n", ibits, obits); */
248: select(16, &ibits, &obits, 0, 0, 0);
249: /* fprintf(console, "ibits %d obits %d\r\n", ibits, obits); */
250: if (ibits == 0 && obits == 0) {
251: sleep(5);
252: continue;
253: }
254: if (ibits & (1<<f)) {
255: fcc = read(f, fibuf, sizeof (fibuf));
256: /* fprintf(console, "%d from f\r\n", fcc); */
257: if (fcc < 0 && errno == EWOULDBLOCK)
258: fcc = 0;
259: else {
260: if (fcc <= 0)
261: break;
262: fbp = fibuf;
263: }
264: }
265: if (ibits & (1<<p)) {
266: pcc = read(p, pibuf, sizeof (pibuf));
267: /* fprintf(console, "%d from p, buf[0] %x, errno %d\r\n", pcc, buf[0], errno); */
268: pbp = pibuf;
269: if (pcc < 0 && errno == EWOULDBLOCK)
270: pcc = 0;
271: else if (pcc <= 0)
272: pcc = -1;
273: else if (pibuf[0] == 0)
274: pbp++, pcc--;
275: else {
276: if (pibuf[0]&(TIOCPKT_FLUSHWRITE|
277: TIOCPKT_NOSTOP|
278: TIOCPKT_DOSTOP)) {
279: int nstop = pibuf[0] &
280: (TIOCPKT_NOSTOP|
281: TIOCPKT_DOSTOP);
282: if (nstop)
283: stop = nstop;
284: pibuf[0] |= nstop;
285: send(f,&pibuf[0],1,MSG_OOB);
286: }
287: pcc = 0;
288: }
289: }
290: if ((obits & (1<<f)) && pcc > 0) {
291: cc = write(f, pbp, pcc);
292: /* fprintf(console, "%d of %d to f\r\n", cc, pcc); */
293: if (cc > 0) {
294: pcc -= cc;
295: pbp += cc;
296: }
297: }
298: if ((obits & (1<<p)) && fcc > 0) {
299: cc = write(p, fbp, fcc);
300: /* fprintf(console, "%d of %d to p\r\n", cc, fcc); */
301: if (cc > 0) {
302: fcc -= cc;
303: fbp += cc;
304: }
305: }
306: }
307: cleanup();
308: }
309: close(f);
310: close(p);
311: dup2(t, 0);
312: dup2(t, 1);
313: dup2(t, 2);
314: close(t);
315: execl("/bin/login", "login", "-r", hp->h_name, 0);
316: fatalperror(2, "/bin/login", errno);
317: /*NOTREACHED*/
318: }
319:
320: cleanup()
321: {
322:
323: rmut();
324: vhangup(); /* XXX */
325: shutdown(netf, 2);
326: kill(0, SIGKILL);
327: exit(1);
328: }
329:
330: fatal(f, msg)
331: int f;
332: char *msg;
333: {
334: char buf[BUFSIZ];
335:
336: buf[0] = '\01'; /* error indicator */
337: (void) sprintf(buf + 1, "rlogind: %s.\r\n", msg);
338: (void) write(f, buf, strlen(buf));
339: exit(1);
340: }
341:
342: fatalperror(f, msg, errno)
343: int f;
344: char *msg;
345: int errno;
346: {
347: char buf[BUFSIZ];
348: extern char *sys_errlist[];
349:
350: (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]);
351: fatal(f, buf);
352: }
353:
354: #include <utmp.h>
355:
356: struct utmp wtmp;
357: char wtmpf[] = "/usr/adm/wtmp";
358: char utmp[] = "/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:
367: f = open(utmp, 2);
368: if (f >= 0) {
369: while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) {
370: if (SCMPN(wtmp.ut_line, line+5) || wtmp.ut_name[0]==0)
371: continue;
372: lseek(f, -(long)sizeof(wtmp), 1);
373: SCPYN(wtmp.ut_name, "");
374: SCPYN(wtmp.ut_host, "");
375: time(&wtmp.ut_time);
376: write(f, (char *)&wtmp, sizeof(wtmp));
377: found++;
378: }
379: close(f);
380: }
381: if (found) {
382: f = open(wtmpf, 1);
383: if (f >= 0) {
384: SCPYN(wtmp.ut_line, line+5);
385: SCPYN(wtmp.ut_name, "");
386: SCPYN(wtmp.ut_host, "");
387: time(&wtmp.ut_time);
388: lseek(f, (long)0, 2);
389: write(f, (char *)&wtmp, sizeof(wtmp));
390: close(f);
391: }
392: }
393: chmod(line, 0666);
394: chown(line, 0, 0);
395: line[strlen("/dev/")] = 'p';
396: chmod(line, 0666);
397: chown(line, 0, 0);
398: }
399:
400: /*
401: * Convert network-format internet address
402: * to base 256 d.d.d.d representation.
403: */
404: char *
405: ntoa(in)
406: struct in_addr in;
407: {
408: static char b[18];
409: register char *p;
410:
411: p = (char *)∈
412: #define UC(b) (((int)b)&0xff)
413: sprintf(b, "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
414: return (b);
415: }
416:
417: /*------------------------------------------------------------
418: determine if a session with remote host should be timed-out.
419: ----------------------------------------------------------*/
420: char *keeprlogin = "/etc/keeprlogin";
421: keeplogin(host)
422: char *host;
423: {
424: FILE *f;
425: char buf[200];
426:
427: f = fopen(keeprlogin, "r");
428: if (!f)
429: return(0);
430: while (fgets(buf, sizeof(buf), f)) {
431: if (index(buf,'\n'))
432: *index(buf,'\n') = 0;
433: if (strcmp(buf, host)==0) {
434: fclose(f);
435: return(1);
436: }
437: }
438: fclose(f);
439: return(0);
440: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.