Commit | Line | Data |
---|---|---|
8c5eec2f | 1 | /* |
9c901b93 KB |
2 | * Copyright (c) 1983 The Regents of the University of California. |
3 | * All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms are permitted | |
6 | * provided that the above copyright notice and this paragraph are | |
7 | * duplicated in all such forms and that any documentation, | |
8 | * advertising materials, and other materials related to such | |
9 | * distribution and use acknowledge that the software was developed | |
10 | * by the University of California, Berkeley. The name of the | |
11 | * University may not be used to endorse or promote products derived | |
12 | * from this software without specific prior written permission. | |
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
15 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
8c5eec2f DF |
16 | */ |
17 | ||
18 | #ifndef lint | |
19 | char copyright[] = | |
9c901b93 | 20 | "@(#) Copyright (c) 1983 The Regents of the University of California.\n\ |
8c5eec2f | 21 | All rights reserved.\n"; |
9c901b93 | 22 | #endif /* not lint */ |
8c5eec2f | 23 | |
a10a364d | 24 | #ifndef lint |
9c901b93 KB |
25 | static char sccsid[] = "@(#)rlogind.c 5.17 (Berkeley) %G%"; |
26 | #endif /* not lint */ | |
a10a364d | 27 | |
bb933cc2 MK |
28 | /* |
29 | * remote login server: | |
30 | * remuser\0 | |
31 | * locuser\0 | |
6632767b | 32 | * terminal info\0 |
bb933cc2 MK |
33 | * data |
34 | */ | |
35 | ||
a10a364d BJ |
36 | #include <stdio.h> |
37 | #include <sys/types.h> | |
38 | #include <sys/stat.h> | |
39 | #include <sys/socket.h> | |
560a8855 | 40 | #include <sys/wait.h> |
6632767b | 41 | #include <sys/file.h> |
c6c678f1 SL |
42 | |
43 | #include <netinet/in.h> | |
44 | ||
a10a364d BJ |
45 | #include <errno.h> |
46 | #include <pwd.h> | |
a10a364d BJ |
47 | #include <signal.h> |
48 | #include <sgtty.h> | |
49 | #include <stdio.h> | |
3f5b52bc | 50 | #include <netdb.h> |
3f99c0f7 | 51 | #include <syslog.h> |
6632767b | 52 | #include <strings.h> |
a10a364d | 53 | |
66feb14c KM |
54 | # ifndef TIOCPKT_WINDOW |
55 | # define TIOCPKT_WINDOW 0x80 | |
56 | # endif TIOCPKT_WINDOW | |
57 | ||
312b6ead | 58 | extern int errno; |
92e31018 | 59 | int reapchild(); |
a10a364d | 60 | struct passwd *getpwnam(); |
66feb14c | 61 | char *malloc(); |
bb933cc2 | 62 | |
312b6ead | 63 | /*ARGSUSED*/ |
a10a364d BJ |
64 | main(argc, argv) |
65 | int argc; | |
66 | char **argv; | |
67 | { | |
312b6ead | 68 | int on = 1, fromlen; |
a10a364d BJ |
69 | struct sockaddr_in from; |
70 | ||
076ae92c | 71 | openlog("rlogind", LOG_PID | LOG_AUTH, LOG_AUTH); |
bb933cc2 MK |
72 | fromlen = sizeof (from); |
73 | if (getpeername(0, &from, &fromlen) < 0) { | |
74 | fprintf(stderr, "%s: ", argv[0]); | |
75 | perror("getpeername"); | |
76 | _exit(1); | |
92e31018 | 77 | } |
bcb894cb | 78 | if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) { |
3f99c0f7 | 79 | syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); |
c6c678f1 | 80 | } |
bb933cc2 | 81 | doit(0, &from); |
92e31018 SL |
82 | } |
83 | ||
a10a364d BJ |
84 | int child; |
85 | int cleanup(); | |
86 | int netf; | |
a10a364d | 87 | char *line; |
43368533 | 88 | extern char *inet_ntoa(); |
a10a364d | 89 | |
8210fa73 KM |
90 | struct winsize win = { 0, 0, 0, 0 }; |
91 | ||
66feb14c | 92 | |
a10a364d BJ |
93 | doit(f, fromp) |
94 | int f; | |
95 | struct sockaddr_in *fromp; | |
96 | { | |
6632767b | 97 | int i, p, t, pid, on = 1; |
3f5b52bc | 98 | register struct hostent *hp; |
43368533 | 99 | struct hostent hostent; |
6632767b | 100 | char c; |
a10a364d BJ |
101 | |
102 | alarm(60); | |
103 | read(f, &c, 1); | |
104 | if (c != 0) | |
105 | exit(1); | |
106 | alarm(0); | |
1227078b | 107 | fromp->sin_port = ntohs((u_short)fromp->sin_port); |
3f5b52bc SL |
108 | hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr), |
109 | fromp->sin_family); | |
8de87e4f | 110 | if (hp == 0) { |
43368533 KM |
111 | /* |
112 | * Only the name is used below. | |
113 | */ | |
114 | hp = &hostent; | |
115 | hp->h_name = inet_ntoa(fromp->sin_addr); | |
8de87e4f | 116 | } |
a10a364d | 117 | if (fromp->sin_family != AF_INET || |
fdc1cc8b MK |
118 | fromp->sin_port >= IPPORT_RESERVED || |
119 | fromp->sin_port < IPPORT_RESERVED/2) | |
82c973f2 | 120 | fatal(f, "Permission denied"); |
a10a364d BJ |
121 | write(f, "", 1); |
122 | for (c = 'p'; c <= 's'; c++) { | |
123 | struct stat stb; | |
124 | line = "/dev/ptyXX"; | |
125 | line[strlen("/dev/pty")] = c; | |
126 | line[strlen("/dev/ptyp")] = '0'; | |
127 | if (stat(line, &stb) < 0) | |
128 | break; | |
129 | for (i = 0; i < 16; i++) { | |
312b6ead KB |
130 | line[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i]; |
131 | p = open(line, O_RDWR); | |
a10a364d BJ |
132 | if (p > 0) |
133 | goto gotpty; | |
134 | } | |
135 | } | |
66feb14c | 136 | fatal(f, "Out of ptys"); |
82c973f2 | 137 | /*NOTREACHED*/ |
a10a364d | 138 | gotpty: |
8210fa73 | 139 | (void) ioctl(p, TIOCSWINSZ, &win); |
1227078b | 140 | netf = f; |
a10a364d | 141 | line[strlen("/dev/")] = 't'; |
312b6ead KB |
142 | t = open(line, O_RDWR); |
143 | if (t < 0) | |
144 | fatalperror(f, line); | |
145 | if (fchmod(t, 0)) | |
146 | fatalperror(f, line); | |
147 | (void)signal(SIGHUP, SIG_IGN); | |
148 | vhangup(); | |
149 | (void)signal(SIGHUP, SIG_DFL); | |
150 | t = open(line, O_RDWR); | |
151 | if (t < 0) | |
152 | fatalperror(f, line); | |
153 | { | |
154 | struct sgttyb b; | |
155 | ||
156 | (void)ioctl(t, TIOCGETP, &b); | |
157 | b.sg_flags = RAW|ANYP; | |
158 | (void)ioctl(t, TIOCSETP, &b); | |
159 | } | |
a10a364d | 160 | #ifdef DEBUG |
312b6ead KB |
161 | { |
162 | int tt = open("/dev/tty", O_RDWR); | |
163 | if (tt > 0) { | |
164 | (void)ioctl(tt, TIOCNOTTY, 0); | |
165 | (void)close(tt); | |
166 | } | |
a10a364d BJ |
167 | } |
168 | #endif | |
82c973f2 SL |
169 | pid = fork(); |
170 | if (pid < 0) | |
312b6ead | 171 | fatalperror(f, ""); |
6632767b SL |
172 | if (pid == 0) { |
173 | close(f), close(p); | |
174 | dup2(t, 0), dup2(t, 1), dup2(t, 2); | |
1227078b | 175 | close(t); |
6632767b | 176 | execl("/bin/login", "login", "-r", hp->h_name, 0); |
312b6ead | 177 | fatalperror(2, "/bin/login"); |
6632767b SL |
178 | /*NOTREACHED*/ |
179 | } | |
180 | close(t); | |
181 | ioctl(f, FIONBIO, &on); | |
182 | ioctl(p, FIONBIO, &on); | |
183 | ioctl(p, TIOCPKT, &on); | |
184 | signal(SIGTSTP, SIG_IGN); | |
185 | signal(SIGCHLD, cleanup); | |
ad5d2c7f | 186 | setpgrp(0, 0); |
6632767b | 187 | protocol(f, p); |
78c1c171 | 188 | signal(SIGCHLD, SIG_IGN); |
6632767b SL |
189 | cleanup(); |
190 | } | |
82c973f2 | 191 | |
6632767b | 192 | char magic[2] = { 0377, 0377 }; |
87e80234 | 193 | char oobdata[] = {TIOCPKT_WINDOW}; |
6632767b SL |
194 | |
195 | /* | |
196 | * Handle a "control" request (signaled by magic being present) | |
197 | * in the data stream. For now, we are only willing to handle | |
198 | * window size changes. | |
199 | */ | |
200 | control(pty, cp, n) | |
201 | int pty; | |
202 | char *cp; | |
203 | int n; | |
204 | { | |
cfafdcf2 | 205 | struct winsize w; |
6632767b | 206 | |
cfafdcf2 | 207 | if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's') |
6632767b | 208 | return (0); |
87e80234 | 209 | oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ |
cfafdcf2 KM |
210 | bcopy(cp+4, (char *)&w, sizeof(w)); |
211 | w.ws_row = ntohs(w.ws_row); | |
212 | w.ws_col = ntohs(w.ws_col); | |
213 | w.ws_xpixel = ntohs(w.ws_xpixel); | |
214 | w.ws_ypixel = ntohs(w.ws_ypixel); | |
215 | (void)ioctl(pty, TIOCSWINSZ, &w); | |
216 | return (4+sizeof (w)); | |
6632767b SL |
217 | } |
218 | ||
219 | /* | |
220 | * rlogin "protocol" machine. | |
221 | */ | |
222 | protocol(f, p) | |
223 | int f, p; | |
224 | { | |
225 | char pibuf[1024], fibuf[1024], *pbp, *fbp; | |
226 | register pcc = 0, fcc = 0; | |
87e80234 | 227 | int cc; |
2c360ad3 | 228 | char cntl; |
6632767b | 229 | |
ffaf1c0b | 230 | /* |
9ee4d121 SL |
231 | * Must ignore SIGTTOU, otherwise we'll stop |
232 | * when we try and set slave pty's window shape | |
87e80234 | 233 | * (our controlling tty is the master pty). |
ffaf1c0b | 234 | */ |
9ee4d121 | 235 | (void) signal(SIGTTOU, SIG_IGN); |
87e80234 | 236 | send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ |
6632767b | 237 | for (;;) { |
2c360ad3 | 238 | int ibits, obits, ebits; |
6632767b | 239 | |
2c360ad3 MK |
240 | ibits = 0; |
241 | obits = 0; | |
6632767b SL |
242 | if (fcc) |
243 | obits |= (1<<p); | |
244 | else | |
245 | ibits |= (1<<f); | |
246 | if (pcc >= 0) | |
247 | if (pcc) | |
248 | obits |= (1<<f); | |
82c973f2 | 249 | else |
6632767b | 250 | ibits |= (1<<p); |
2c360ad3 MK |
251 | ebits = (1<<p); |
252 | if (select(16, &ibits, &obits, &ebits, 0) < 0) { | |
6632767b | 253 | if (errno == EINTR) |
a10a364d | 254 | continue; |
312b6ead | 255 | fatalperror(f, "select"); |
6632767b | 256 | } |
2c360ad3 | 257 | if (ibits == 0 && obits == 0 && ebits == 0) { |
6632767b SL |
258 | /* shouldn't happen... */ |
259 | sleep(5); | |
260 | continue; | |
261 | } | |
2c360ad3 MK |
262 | #define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) |
263 | if (ebits & (1<<p)) { | |
264 | cc = read(p, &cntl, 1); | |
265 | if (cc == 1 && pkcontrol(cntl)) { | |
266 | cntl |= oobdata[0]; | |
267 | send(f, &cntl, 1, MSG_OOB); | |
268 | if (cntl & TIOCPKT_FLUSHWRITE) { | |
269 | pcc = 0; | |
270 | ibits &= ~(1<<p); | |
271 | } | |
272 | } | |
273 | } | |
6632767b SL |
274 | if (ibits & (1<<f)) { |
275 | fcc = read(f, fibuf, sizeof (fibuf)); | |
276 | if (fcc < 0 && errno == EWOULDBLOCK) | |
277 | fcc = 0; | |
278 | else { | |
279 | register char *cp; | |
280 | int left, n; | |
281 | ||
282 | if (fcc <= 0) | |
1227078b | 283 | break; |
6632767b | 284 | fbp = fibuf; |
66feb14c | 285 | |
6632767b | 286 | top: |
87e80234 | 287 | for (cp = fibuf; cp < fibuf+fcc-1; cp++) |
6632767b SL |
288 | if (cp[0] == magic[0] && |
289 | cp[1] == magic[1]) { | |
290 | left = fcc - (cp-fibuf); | |
291 | n = control(p, cp, left); | |
292 | if (n) { | |
293 | left -= n; | |
294 | if (left > 0) | |
87e80234 | 295 | bcopy(cp+n, cp, left); |
6632767b SL |
296 | fcc -= n; |
297 | goto top; /* n^2 */ | |
87e80234 MK |
298 | } |
299 | } | |
300 | } | |
301 | } | |
66feb14c KM |
302 | |
303 | if ((obits & (1<<p)) && fcc > 0) { | |
87e80234 | 304 | cc = write(p, fbp, fcc); |
66feb14c KM |
305 | if (cc > 0) { |
306 | fcc -= cc; | |
307 | fbp += cc; | |
a10a364d | 308 | } |
6632767b | 309 | } |
66feb14c | 310 | |
6632767b SL |
311 | if (ibits & (1<<p)) { |
312 | pcc = read(p, pibuf, sizeof (pibuf)); | |
313 | pbp = pibuf; | |
314 | if (pcc < 0 && errno == EWOULDBLOCK) | |
315 | pcc = 0; | |
316 | else if (pcc <= 0) | |
317 | break; | |
318 | else if (pibuf[0] == 0) | |
319 | pbp++, pcc--; | |
320 | else { | |
6632767b | 321 | if (pkcontrol(pibuf[0])) { |
87e80234 | 322 | pibuf[0] |= oobdata[0]; |
6632767b | 323 | send(f, &pibuf[0], 1, MSG_OOB); |
a10a364d | 324 | } |
6632767b | 325 | pcc = 0; |
a10a364d | 326 | } |
6632767b SL |
327 | } |
328 | if ((obits & (1<<f)) && pcc > 0) { | |
87e80234 MK |
329 | cc = write(f, pbp, pcc); |
330 | if (cc < 0 && errno == EWOULDBLOCK) { | |
331 | /* also shouldn't happen */ | |
332 | sleep(5); | |
333 | continue; | |
334 | } | |
6632767b SL |
335 | if (cc > 0) { |
336 | pcc -= cc; | |
337 | pbp += cc; | |
338 | } | |
339 | } | |
a10a364d | 340 | } |
a10a364d BJ |
341 | } |
342 | ||
343 | cleanup() | |
344 | { | |
6487d192 KB |
345 | char *p; |
346 | ||
347 | p = line + sizeof("/dev/") - 1; | |
348 | if (logout(p)) | |
349 | logwtmp(p, "", ""); | |
350 | (void)chmod(line, 0666); | |
351 | (void)chown(line, 0, 0); | |
352 | *p = 'p'; | |
353 | (void)chmod(line, 0666); | |
354 | (void)chown(line, 0, 0); | |
ff24c640 | 355 | shutdown(netf, 2); |
a10a364d BJ |
356 | exit(1); |
357 | } | |
358 | ||
82c973f2 SL |
359 | fatal(f, msg) |
360 | int f; | |
361 | char *msg; | |
362 | { | |
363 | char buf[BUFSIZ]; | |
364 | ||
365 | buf[0] = '\01'; /* error indicator */ | |
560a8855 | 366 | (void) sprintf(buf + 1, "rlogind: %s.\r\n", msg); |
82c973f2 SL |
367 | (void) write(f, buf, strlen(buf)); |
368 | exit(1); | |
369 | } | |
370 | ||
312b6ead | 371 | fatalperror(f, msg) |
82c973f2 SL |
372 | int f; |
373 | char *msg; | |
82c973f2 SL |
374 | { |
375 | char buf[BUFSIZ]; | |
1227078b | 376 | extern int sys_nerr; |
82c973f2 SL |
377 | extern char *sys_errlist[]; |
378 | ||
6632767b | 379 | if ((unsigned)errno < sys_nerr) |
1227078b MK |
380 | (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]); |
381 | else | |
382 | (void) sprintf(buf, "%s: Error %d", msg, errno); | |
82c973f2 SL |
383 | fatal(f, buf); |
384 | } |