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