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