xref: /csrg-svn/libexec/rlogind/rlogind.c (revision 6446)
1*6446Swnj #ifndef lint
2*6446Swnj static char sccsid[] = "@(#)rlogind.c	4.1 82/04/02";
3*6446Swnj #endif
4*6446Swnj 
5*6446Swnj #include <stdio.h>
6*6446Swnj #include <sys/types.h>
7*6446Swnj #include <sys/stat.h>
8*6446Swnj #include <sys/socket.h>
9*6446Swnj #include <net/in.h>
10*6446Swnj #include <errno.h>
11*6446Swnj #include <pwd.h>
12*6446Swnj #include <wait.h>
13*6446Swnj #include <signal.h>
14*6446Swnj #include <sgtty.h>
15*6446Swnj #include <stdio.h>
16*6446Swnj 
17*6446Swnj extern	errno;
18*6446Swnj struct	passwd *getpwnam();
19*6446Swnj char	*crypt(), *rindex(), *index(), *malloc(), *raddr();
20*6446Swnj int	options = SO_ACCEPTCONN|SO_KEEPALIVE;
21*6446Swnj struct	sockaddr_in sin = { AF_INET, IPPORT_LOGINSERVER };
22*6446Swnj /*
23*6446Swnj  * remote login server:
24*6446Swnj  *	remuser\0
25*6446Swnj  *	locuser\0
26*6446Swnj  *	terminal type\0
27*6446Swnj  *	data
28*6446Swnj  */
29*6446Swnj main(argc, argv)
30*6446Swnj 	int argc;
31*6446Swnj 	char **argv;
32*6446Swnj {
33*6446Swnj 	union wait status;
34*6446Swnj 	int f, debug = 0;
35*6446Swnj 	struct sockaddr_in from;
36*6446Swnj 
37*6446Swnj #ifndef DEBUG
38*6446Swnj 	if (fork())
39*6446Swnj 		exit(0);
40*6446Swnj 	for (f = 0; f < 10; f++)
41*6446Swnj 		(void) close(f);
42*6446Swnj 	(void) open("/", 0);
43*6446Swnj 	(void) dup2(0, 1);
44*6446Swnj 	(void) dup2(0, 2);
45*6446Swnj 	{ int tt = open("/dev/tty", 2);
46*6446Swnj 	  if (tt > 0) {
47*6446Swnj 		ioctl(tt, TIOCNOTTY, 0);
48*6446Swnj 		close(tt);
49*6446Swnj 	  }
50*6446Swnj 	}
51*6446Swnj #endif
52*6446Swnj #if vax
53*6446Swnj 	sin.sin_port = htons(sin.sin_port);
54*6446Swnj #endif
55*6446Swnj 	argc--, argv++;
56*6446Swnj 	if (argc > 0 && !strcmp(argv[0], "-d"))
57*6446Swnj 		options |= SO_DEBUG;
58*6446Swnj 	for (;;) {
59*6446Swnj 		f = socket(SOCK_STREAM, 0, &sin, options);
60*6446Swnj 		if (f < 0) {
61*6446Swnj 			perror("socket");
62*6446Swnj 			sleep(5);
63*6446Swnj 			continue;
64*6446Swnj 		}
65*6446Swnj 		if (accept(f, &from) < 0) {
66*6446Swnj 			perror("accept");
67*6446Swnj 			close(f);
68*6446Swnj 			sleep(1);
69*6446Swnj 			continue;
70*6446Swnj 		}
71*6446Swnj 		if (fork() == 0)
72*6446Swnj 			doit(f, &from);
73*6446Swnj 		close(f);
74*6446Swnj 		while (wait3(status, WNOHANG, 0) > 0)
75*6446Swnj 			continue;
76*6446Swnj 	}
77*6446Swnj }
78*6446Swnj 
79*6446Swnj char	locuser[32], remuser[32];
80*6446Swnj char	buf[BUFSIZ];
81*6446Swnj int	child;
82*6446Swnj int	cleanup();
83*6446Swnj int	netf;
84*6446Swnj extern	errno;
85*6446Swnj char	*line;
86*6446Swnj 
87*6446Swnj doit(f, fromp)
88*6446Swnj 	int f;
89*6446Swnj 	struct sockaddr_in *fromp;
90*6446Swnj {
91*6446Swnj 	char c, *rhost;
92*6446Swnj 	int i, p, cc, t;
93*6446Swnj 	int stop = TIOCPKT_DOSTOP;
94*6446Swnj 
95*6446Swnj 	alarm(60);
96*6446Swnj 	read(f, &c, 1);
97*6446Swnj 	if (c != 0)
98*6446Swnj 		exit(1);
99*6446Swnj 	alarm(0);
100*6446Swnj #if vax
101*6446Swnj 	fromp->sin_port = htons(fromp->sin_port);
102*6446Swnj #endif
103*6446Swnj 	rhost = raddr(fromp->sin_addr.s_addr);
104*6446Swnj 	if (fromp->sin_family != AF_INET ||
105*6446Swnj 	    fromp->sin_port >= IPPORT_RESERVED ||
106*6446Swnj 	    rhost == 0) {
107*6446Swnj 		write(f, "\01Permission denied.\n", 20);
108*6446Swnj 		exit(1);
109*6446Swnj 	}
110*6446Swnj 	write(f, "", 1);
111*6446Swnj 	for (c = 'p'; c <= 's'; c++) {
112*6446Swnj 		struct stat stb;
113*6446Swnj 		line = "/dev/ptyXX";
114*6446Swnj 		line[strlen("/dev/pty")] = c;
115*6446Swnj 		line[strlen("/dev/ptyp")] = '0';
116*6446Swnj 		if (stat(line, &stb) < 0)
117*6446Swnj 			break;
118*6446Swnj 		for (i = 0; i < 16; i++) {
119*6446Swnj 			line[strlen("/dev/ptyp")] = "0123456789abcdef"[i];
120*6446Swnj 			p = open(line, 2);
121*6446Swnj 			if (p > 0)
122*6446Swnj 				goto gotpty;
123*6446Swnj 		}
124*6446Swnj 	}
125*6446Swnj 	dup2(f, 1);
126*6446Swnj 	printf("All network ports in use.\r\n");
127*6446Swnj 	exit(1);
128*6446Swnj gotpty:
129*6446Swnj 	dup2(f, 0);
130*6446Swnj 	line[strlen("/dev/")] = 't';
131*6446Swnj #ifdef DEBUG
132*6446Swnj 	{ int tt = open("/dev/tty", 2);
133*6446Swnj 	  if (tt > 0) {
134*6446Swnj 		ioctl(tt, TIOCNOTTY, 0);
135*6446Swnj 		close(tt);
136*6446Swnj 	  }
137*6446Swnj 	}
138*6446Swnj #endif
139*6446Swnj 	t = open(line, 2);
140*6446Swnj 	if (t < 0) {
141*6446Swnj 		dup2(f, 2);
142*6446Swnj 		perror(line);
143*6446Swnj 		exit(1);
144*6446Swnj 	}
145*6446Swnj 	{ struct sgttyb b;
146*6446Swnj 	  gtty(t, &b); b.sg_flags = RAW|ANYP; stty(t, &b);
147*6446Swnj 	}
148*6446Swnj 	if (fork()) {
149*6446Swnj 		char pibuf[1024], fibuf[1024], *pbp, *fbp;
150*6446Swnj 		int pcc = 0, fcc = 0, on = 1;
151*6446Swnj /* FILE *console = fopen("/dev/console", "w");  */
152*6446Swnj /* setbuf(console, 0); */
153*6446Swnj 
154*6446Swnj /* fprintf(console, "f %d p %d\r\n", f, p); */
155*6446Swnj 		ioctl(f, FIONBIO, &on);
156*6446Swnj 		ioctl(p, FIONBIO, &on);
157*6446Swnj 		ioctl(p, TIOCPKT, &on);
158*6446Swnj 		signal(SIGTSTP, SIG_IGN);
159*6446Swnj 		sigset(SIGCHLD, cleanup);
160*6446Swnj 		for (;;) {
161*6446Swnj 			int ibits = 0, obits = 0;
162*6446Swnj 			if (fcc) obits |= (1<<p); else ibits |= (1<<f);
163*6446Swnj 			if (pcc >= 0)
164*6446Swnj 			if (pcc) obits |= (1<<f); else ibits |= (1<<p);
165*6446Swnj 			if (fcc < 0 && pcc < 0) break;
166*6446Swnj /* fprintf(console, "ibits from %d obits from %d\r\n", ibits, obits); */
167*6446Swnj 			select(32, &ibits, &obits, 10000000);
168*6446Swnj /* fprintf(console, "ibits %d obits %d\r\n", ibits, obits); */
169*6446Swnj 			if (ibits == 0 && obits == 0) {
170*6446Swnj 				sleep(5);
171*6446Swnj 				continue;
172*6446Swnj 			}
173*6446Swnj 			if (ibits & (1<<f)) {
174*6446Swnj 				fcc = read(f, fibuf, sizeof (fibuf));
175*6446Swnj /* fprintf(console, "%d from f\r\n", fcc); */
176*6446Swnj 				if (fcc < 0 && errno == EWOULDBLOCK)
177*6446Swnj 					fcc = 0;
178*6446Swnj 				else {
179*6446Swnj 					if (fcc <= 0)
180*6446Swnj 						break;
181*6446Swnj 					fbp = fibuf;
182*6446Swnj 				}
183*6446Swnj 			}
184*6446Swnj 			if (ibits & (1<<p)) {
185*6446Swnj 				pcc = read(p, pibuf, sizeof (pibuf));
186*6446Swnj /* fprintf(console, "%d from p, buf[0] %x, errno %d\r\n", pcc, buf[0], errno); */
187*6446Swnj 				pbp = pibuf;
188*6446Swnj 				if (pcc < 0 && errno == EWOULDBLOCK)
189*6446Swnj 					pcc = 0;
190*6446Swnj 				else if (pcc <= 0)
191*6446Swnj 					pcc = -1;
192*6446Swnj 				else if (pibuf[0] == 0)
193*6446Swnj 					pbp++, pcc--;
194*6446Swnj 				else {
195*6446Swnj 					if (pibuf[0]&(TIOCPKT_FLUSHWRITE|
196*6446Swnj 						      TIOCPKT_NOSTOP|
197*6446Swnj 						      TIOCPKT_DOSTOP)) {
198*6446Swnj 						int nstop = pibuf[0] &
199*6446Swnj 						    (TIOCPKT_NOSTOP|
200*6446Swnj 						     TIOCPKT_DOSTOP);
201*6446Swnj 						if (nstop)
202*6446Swnj 							stop = nstop;
203*6446Swnj 						pibuf[0] |= nstop;
204*6446Swnj 						ioctl(f,SIOCSENDOOB,&pibuf[0]);
205*6446Swnj 					}
206*6446Swnj 					pcc = 0;
207*6446Swnj 				}
208*6446Swnj 			}
209*6446Swnj 			if ((obits & (1<<f)) && pcc > 0) {
210*6446Swnj 				cc = write(f, pbp, pcc);
211*6446Swnj /* fprintf(console, "%d of %d to f\r\n", cc, pcc); */
212*6446Swnj 				if (cc > 0) {
213*6446Swnj 					pcc -= cc;
214*6446Swnj 					pbp += cc;
215*6446Swnj 				}
216*6446Swnj 			}
217*6446Swnj 			if ((obits & (1<<p)) && fcc > 0) {
218*6446Swnj 				cc = write(p, fbp, fcc);
219*6446Swnj /* fprintf(console, "%d of %d to p\r\n", cc, fcc); */
220*6446Swnj 				if (cc > 0) {
221*6446Swnj 					fcc -= cc;
222*6446Swnj 					fbp += cc;
223*6446Swnj 				}
224*6446Swnj 			}
225*6446Swnj 		}
226*6446Swnj 		cleanup();
227*6446Swnj 	}
228*6446Swnj 	close(f);
229*6446Swnj 	close(p);
230*6446Swnj 	dup2(t, 0);
231*6446Swnj 	dup2(t, 1);
232*6446Swnj 	dup2(t, 2);
233*6446Swnj 	close(t);
234*6446Swnj 	execl("/bin/login", "login", "-r", rhost, 0);
235*6446Swnj 	perror("/bin/login");
236*6446Swnj 	exit(1);
237*6446Swnj }
238*6446Swnj 
239*6446Swnj cleanup()
240*6446Swnj {
241*6446Swnj 	int how = 2;
242*6446Swnj 
243*6446Swnj 	rmut();
244*6446Swnj 	ioctl(netf, SIOCDONE, &how);
245*6446Swnj 	kill(0, SIGKILL);
246*6446Swnj 	exit(1);
247*6446Swnj }
248*6446Swnj 
249*6446Swnj #include <utmp.h>
250*6446Swnj 
251*6446Swnj struct	utmp wtmp;
252*6446Swnj char	wtmpf[]	= "/usr/adm/wtmp";
253*6446Swnj char	utmp[] = "/etc/utmp";
254*6446Swnj #define SCPYN(a, b)	strncpy(a, b, sizeof(a))
255*6446Swnj #define SCMPN(a, b)	strncmp(a, b, sizeof(a))
256*6446Swnj 
257*6446Swnj rmut()
258*6446Swnj {
259*6446Swnj 	register f;
260*6446Swnj 	int found = 0;
261*6446Swnj 
262*6446Swnj 	f = open(utmp, 2);
263*6446Swnj 	if (f >= 0) {
264*6446Swnj 		while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) {
265*6446Swnj 			if (SCMPN(wtmp.ut_line, line+5) || wtmp.ut_name[0]==0)
266*6446Swnj 				continue;
267*6446Swnj 			lseek(f, -(long)sizeof(wtmp), 1);
268*6446Swnj 			SCPYN(wtmp.ut_name, "");
269*6446Swnj 			time(&wtmp.ut_time);
270*6446Swnj 			write(f, (char *)&wtmp, sizeof(wtmp));
271*6446Swnj 			found++;
272*6446Swnj 		}
273*6446Swnj 		close(f);
274*6446Swnj 	}
275*6446Swnj 	if (found) {
276*6446Swnj 		f = open(wtmpf, 1);
277*6446Swnj 		if (f >= 0) {
278*6446Swnj 			SCPYN(wtmp.ut_line, line+5);
279*6446Swnj 			SCPYN(wtmp.ut_name, "");
280*6446Swnj 			time(&wtmp.ut_time);
281*6446Swnj 			lseek(f, (long)0, 2);
282*6446Swnj 			write(f, (char *)&wtmp, sizeof(wtmp));
283*6446Swnj 			close(f);
284*6446Swnj 		}
285*6446Swnj 	}
286*6446Swnj 	chmod(line, 0666);
287*6446Swnj 	chown(line, 0, 0);
288*6446Swnj 	line[strlen("/dev/")] = 'p';
289*6446Swnj 	chmod(line, 0666);
290*6446Swnj 	chown(line, 0, 0);
291*6446Swnj }
292