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