Commit | Line | Data |
---|---|---|
8c5eec2f | 1 | /* |
f295ed5f | 2 | * Copyright (c) 1983, 1988, 1989 The Regents of the University of California. |
9c901b93 KB |
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[] = | |
f295ed5f | 20 | "@(#) Copyright (c) 1983, 1988, 1989 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 |
7aac2862 | 25 | static char sccsid[] = "@(#)rlogind.c 5.46 (Berkeley) %G%"; |
9c901b93 | 26 | #endif /* not lint */ |
a10a364d | 27 | |
a6449a97 MK |
28 | #ifdef KERBEROS |
29 | /* From: | |
30 | * $Source: /mit/kerberos/ucb/mit/rlogind/RCS/rlogind.c,v $ | |
31 | * $Header: rlogind.c,v 5.0 89/06/26 18:31:01 kfall Locked $ | |
32 | */ | |
a6449a97 | 33 | #endif |
27ed11f5 | 34 | |
bb933cc2 MK |
35 | /* |
36 | * remote login server: | |
e3fc62b0 | 37 | * \0 |
bb933cc2 MK |
38 | * remuser\0 |
39 | * locuser\0 | |
e3fc62b0 | 40 | * terminal_type/speed\0 |
9d5f81ab | 41 | * data |
dfd00f77 MK |
42 | * |
43 | * Automatic login protocol is done here, using login -f upon success, | |
44 | * unless OLD_LOGIN is defined (then done in login, ala 4.2/4.3BSD). | |
bb933cc2 MK |
45 | */ |
46 | ||
b4839a52 | 47 | #define FD_SETSIZE 16 /* don't need many bits for select */ |
2b08f0dd | 48 | #include <sys/param.h> |
a10a364d BJ |
49 | #include <sys/stat.h> |
50 | #include <sys/socket.h> | |
560a8855 | 51 | #include <sys/wait.h> |
6632767b | 52 | #include <sys/file.h> |
f295ed5f MK |
53 | #include <sys/ioctl.h> |
54 | #if BSD > 43 | |
55 | #include <sys/termios.h> | |
56 | #endif | |
95d03f33 KB |
57 | #include <sys/signal.h> |
58 | #include <sys/ioctl.h> | |
59 | #include <sys/termios.h> | |
c6c678f1 SL |
60 | |
61 | #include <netinet/in.h> | |
62 | ||
a10a364d BJ |
63 | #include <errno.h> |
64 | #include <pwd.h> | |
3f5b52bc | 65 | #include <netdb.h> |
3f99c0f7 | 66 | #include <syslog.h> |
6ebcb998 | 67 | #include <string.h> |
95d03f33 | 68 | #include <stdio.h> |
27ed11f5 | 69 | #include <unistd.h> |
95d03f33 | 70 | #include "pathnames.h" |
9d5f81ab MK |
71 | |
72 | #ifndef TIOCPKT_WINDOW | |
73 | #define TIOCPKT_WINDOW 0x80 | |
74 | #endif | |
e3fc62b0 | 75 | |
9d5f81ab MK |
76 | char *env[2]; |
77 | #define NMAX 30 | |
5a93e98d MK |
78 | char lusername[NMAX+1], rusername[NMAX+1]; |
79 | static char term[64] = "TERM="; | |
80 | #define ENVSIZE (sizeof("TERM=")-1) /* skip null for concatenation */ | |
81 | int keepalive = 1; | |
a6449a97 | 82 | int check_all = 0; |
f295ed5f | 83 | int check_all = 0; |
e3fc62b0 | 84 | |
312b6ead | 85 | extern int errno; |
92e31018 | 86 | int reapchild(); |
e3fc62b0 | 87 | struct passwd *getpwnam(), *pwd; |
66feb14c | 88 | char *malloc(); |
bb933cc2 | 89 | |
a10a364d BJ |
90 | main(argc, argv) |
91 | int argc; | |
92 | char **argv; | |
93 | { | |
84e161e6 | 94 | extern int opterr, optind; |
84e161e6 | 95 | extern int _check_rhosts_file; |
10869b2d | 96 | int ch; |
312b6ead | 97 | int on = 1, fromlen; |
a10a364d BJ |
98 | struct sockaddr_in from; |
99 | ||
20b6f6ce | 100 | openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH); |
10869b2d KB |
101 | |
102 | opterr = 0; | |
b3da51a3 | 103 | while ((ch = getopt(argc, argv, ARGSTR)) != EOF) |
5a93e98d | 104 | switch (ch) { |
f295ed5f MK |
105 | case 'a': |
106 | check_all = 1; | |
107 | break; | |
a6449a97 MK |
108 | case 'a': |
109 | check_all = 1; | |
110 | break; | |
10869b2d KB |
111 | case 'l': |
112 | _check_rhosts_file = 0; | |
113 | break; | |
5a93e98d MK |
114 | case 'n': |
115 | keepalive = 0; | |
116 | break; | |
b3da51a3 KF |
117 | #ifdef KERBEROS |
118 | case 'k': | |
119 | use_kerberos = 1; | |
120 | break; | |
121 | case 'v': | |
122 | vacuous = 1; | |
123 | break; | |
32d4627a KF |
124 | case 'x': |
125 | encrypt = 1; | |
126 | break; | |
b3da51a3 | 127 | #endif |
10869b2d KB |
128 | case '?': |
129 | default: | |
b3da51a3 | 130 | usage(); |
10869b2d KB |
131 | break; |
132 | } | |
133 | argc -= optind; | |
134 | argv += optind; | |
135 | ||
b3da51a3 | 136 | #ifdef KERBEROS |
c1e16073 | 137 | if (use_kerberos && vacuous) { |
b3da51a3 | 138 | usage(); |
27ed11f5 | 139 | fatal(STDERR_FILENO, "only one of -k and -v allowed", 0); |
b3da51a3 KF |
140 | } |
141 | #endif | |
bb933cc2 MK |
142 | fromlen = sizeof (from); |
143 | if (getpeername(0, &from, &fromlen) < 0) { | |
2b08f0dd | 144 | syslog(LOG_ERR, "Couldn't get peer name of remote host: %m"); |
f295ed5f | 145 | fatalperror("Can't get peer name of remote host"); |
92e31018 | 146 | } |
5a93e98d MK |
147 | if (keepalive && |
148 | setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) | |
3f99c0f7 | 149 | syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); |
bb933cc2 | 150 | doit(0, &from); |
92e31018 SL |
151 | } |
152 | ||
a10a364d BJ |
153 | int child; |
154 | int cleanup(); | |
155 | int netf; | |
a10a364d | 156 | char *line; |
b4839a52 | 157 | int confirmed; |
43368533 | 158 | extern char *inet_ntoa(); |
a10a364d | 159 | |
8210fa73 KM |
160 | struct winsize win = { 0, 0, 0, 0 }; |
161 | ||
66feb14c | 162 | |
a10a364d BJ |
163 | doit(f, fromp) |
164 | int f; | |
165 | struct sockaddr_in *fromp; | |
166 | { | |
6632767b | 167 | int i, p, t, pid, on = 1; |
dfd00f77 | 168 | #ifndef OLD_LOGIN |
c1e16073 | 169 | int authenticated = 0, hostok = 0; |
dfd00f77 | 170 | #endif |
3f5b52bc | 171 | register struct hostent *hp; |
c1e16073 | 172 | char remotehost[2 * MAXHOSTNAMELEN + 1]; |
43368533 | 173 | struct hostent hostent; |
6632767b | 174 | char c; |
a10a364d BJ |
175 | |
176 | alarm(60); | |
177 | read(f, &c, 1); | |
b4839a52 | 178 | if (c != 0) |
a10a364d | 179 | exit(1); |
32d4627a | 180 | #ifdef KERBEROS |
f295ed5f | 181 | if (vacuous) |
27ed11f5 | 182 | fatal(f, "Remote host requires Kerberos authentication", 0); |
e3fc62b0 | 183 | |
a10a364d | 184 | alarm(0); |
1227078b | 185 | fromp->sin_port = ntohs((u_short)fromp->sin_port); |
3f5b52bc SL |
186 | hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr), |
187 | fromp->sin_family); | |
8de87e4f | 188 | if (hp == 0) { |
43368533 KM |
189 | /* |
190 | * Only the name is used below. | |
191 | */ | |
192 | hp = &hostent; | |
193 | hp->h_name = inet_ntoa(fromp->sin_addr); | |
1d565c69 | 194 | #ifndef OLD_LOGIN |
40891b11 | 195 | hostok++; |
1d565c69 | 196 | #endif |
40891b11 | 197 | } |
2b08f0dd | 198 | #ifndef OLD_LOGIN |
f295ed5f | 199 | else if (check_all || local_domain(hp->h_name)) { |
2b08f0dd MK |
200 | /* |
201 | * If name returned by gethostbyaddr is in our domain, | |
202 | * attempt to verify that we haven't been fooled by someone | |
203 | * in a remote net; look up the name and check that this | |
204 | * address corresponds to the name. | |
205 | */ | |
206 | strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1); | |
207 | remotehost[sizeof(remotehost) - 1] = 0; | |
208 | hp = gethostbyname(remotehost); | |
209 | if (hp) | |
f295ed5f | 210 | #ifdef h_addr /* 4.2 hack */ |
40891b11 | 211 | for (; hp->h_addr_list[0]; hp->h_addr_list++) |
2b08f0dd MK |
212 | if (!bcmp(hp->h_addr_list[0], (caddr_t)&fromp->sin_addr, |
213 | sizeof(fromp->sin_addr))) { | |
214 | hostok++; | |
215 | break; | |
216 | } | |
f295ed5f MK |
217 | #else |
218 | if (!bcmp(hp->h_addr, (caddr_t)&fromp->sin_addr, | |
219 | sizeof(fromp->sin_addr))) | |
220 | hostok++; | |
221 | #endif | |
40891b11 MK |
222 | } else |
223 | hostok++; | |
f295ed5f | 224 | #endif /* OLD_LOGIN */ |
e3fc62b0 | 225 | |
c1e16073 | 226 | if (use_kerberos) { |
f5bb5ea0 KB |
227 | if (!hostok) |
228 | fatal(f, "krlogind: Host address mismatch.", 0); | |
b3da51a3 | 229 | retval = do_krb_login(hp->h_name, fromp, encrypt); |
f5bb5ea0 | 230 | if (retval == 0) |
b3da51a3 | 231 | authenticated++; |
c1e16073 | 232 | else if (retval > 0) |
27ed11f5 | 233 | fatal(f, krb_err_txt[retval], 0); |
b4839a52 MK |
234 | write(f, &c, 1); |
235 | confirmed = 1; /* we sent the null! */ | |
b3da51a3 | 236 | } else |
dfd00f77 | 237 | #ifndef OLD_LOGIN |
2771f96c KF |
238 | { |
239 | if (fromp->sin_family != AF_INET || | |
240 | fromp->sin_port >= IPPORT_RESERVED || | |
241 | fromp->sin_port < IPPORT_RESERVED/2) { | |
242 | syslog(LOG_NOTICE, "Connection from %s on illegal port", | |
243 | inet_ntoa(fromp->sin_addr)); | |
27ed11f5 | 244 | fatal(f, "Permission denied", 0); |
2771f96c | 245 | } |
b4839a52 MK |
246 | if (do_rlogin(hp->h_name) == 0 && hostok) |
247 | authenticated++; | |
c1e16073 | 248 | } |
b3da51a3 | 249 | |
a10a364d BJ |
250 | for (c = 'p'; c <= 's'; c++) { |
251 | struct stat stb; | |
252 | line = "/dev/ptyXX"; | |
253 | line[strlen("/dev/pty")] = c; | |
254 | line[strlen("/dev/ptyp")] = '0'; | |
255 | if (stat(line, &stb) < 0) | |
256 | break; | |
257 | for (i = 0; i < 16; i++) { | |
312b6ead KB |
258 | line[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i]; |
259 | p = open(line, O_RDWR); | |
a10a364d BJ |
260 | if (p > 0) |
261 | goto gotpty; | |
262 | } | |
263 | } | |
27ed11f5 | 264 | fatal(f, "Out of ptys", 0); |
82c973f2 | 265 | /*NOTREACHED*/ |
a10a364d | 266 | gotpty: |
8210fa73 | 267 | (void) ioctl(p, TIOCSWINSZ, &win); |
1227078b | 268 | netf = f; |
27ed11f5 | 269 | line[sizeof(_PATH_DEV) - 1] = 't'; |
312b6ead KB |
270 | t = open(line, O_RDWR); |
271 | if (t < 0) | |
27ed11f5 | 272 | fatal(f, line, 1); |
312b6ead | 273 | if (fchmod(t, 0)) |
27ed11f5 | 274 | fatal(f, line, 1); |
312b6ead | 275 | (void)signal(SIGHUP, SIG_IGN); |
7aac2862 KF |
276 | #ifdef notdef |
277 | vhangup(); | |
278 | #endif | |
312b6ead KB |
279 | (void)signal(SIGHUP, SIG_DFL); |
280 | t = open(line, O_RDWR); | |
281 | if (t < 0) | |
27ed11f5 | 282 | fatal(f, line, 1); |
e3fc62b0 | 283 | setup_term(t); |
b4839a52 MK |
284 | if (confirmed == 0) { |
285 | write(f, "", 1); | |
286 | confirmed = 1; /* we sent the null! */ | |
287 | } | |
288 | #ifdef KERBEROS | |
289 | if (encrypt) | |
290 | (void) des_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE)); | |
291 | ||
292 | if (use_kerberos == 0) | |
293 | #endif | |
294 | if (!authenticated && !hostok) | |
295 | write(f, "rlogind: Host address mismatch.\r\n", | |
296 | sizeof("rlogind: Host address mismatch.\r\n") - 1); | |
f295ed5f | 297 | |
82c973f2 SL |
298 | pid = fork(); |
299 | if (pid < 0) | |
27ed11f5 | 300 | fatal(f, "", 1); |
6632767b | 301 | if (pid == 0) { |
f295ed5f MK |
302 | #if BSD > 43 |
303 | if (setsid() < 0) | |
304 | fatalperror(f, "setsid"); | |
305 | if (ioctl(t, TIOCSCTTY, 0) < 0) | |
306 | fatalperror(f, "ioctl(sctty)"); | |
307 | #endif | |
27ed11f5 KB |
308 | fatal(f, "ioctl(sctty)", 1); |
309 | (void)close(f); | |
310 | (void)close(p); | |
311 | dup2(t, STDIN_FILENO); | |
312 | dup2(t, STDOUT_FILENO); | |
313 | dup2(t, STDERR_FILENO); | |
314 | (void)close(t); | |
84e161e6 | 315 | |
dfd00f77 MK |
316 | #ifdef OLD_LOGIN |
317 | execl("/bin/login", "login", "-r", hp->h_name, 0); | |
318 | #else /* OLD_LOGIN */ | |
7aac2862 KF |
319 | if (authenticated) { |
320 | if (use_kerberos && (pwd->pw_uid == 0)) | |
321 | syslog(LOG_INFO|LOG_AUTH, | |
322 | "ROOT Kerberos login from %s.%s@%s on %s\n", | |
323 | kdata->pname, kdata->pinst, kdata->prealm, | |
324 | hp->h_name); | |
325 | ||
95d03f33 | 326 | execl(_PATH_LOGIN, "login", "-p", |
b3da51a3 | 327 | "-h", hp->h_name, "-f", lusername, 0); |
7aac2862 | 328 | } else |
95d03f33 | 329 | execl(_PATH_LOGIN, "login", "-p", |
b3da51a3 | 330 | "-h", hp->h_name, lusername, 0); |
dfd00f77 | 331 | #endif /* OLD_LOGIN */ |
27ed11f5 | 332 | fatal(STDERR_FILENO, _PATH_LOGIN, 1); |
6632767b SL |
333 | /*NOTREACHED*/ |
334 | } | |
335 | close(t); | |
e3fc62b0 | 336 | |
754db9db | 337 | ioctl(f, FIONBIO, &on); |
6632767b SL |
338 | ioctl(p, FIONBIO, &on); |
339 | ioctl(p, TIOCPKT, &on); | |
6632767b SL |
340 | signal(SIGCHLD, cleanup); |
341 | protocol(f, p); | |
78c1c171 | 342 | signal(SIGCHLD, SIG_IGN); |
6632767b SL |
343 | cleanup(); |
344 | } | |
82c973f2 | 345 | |
6632767b | 346 | char magic[2] = { 0377, 0377 }; |
87e80234 | 347 | char oobdata[] = {TIOCPKT_WINDOW}; |
6632767b SL |
348 | |
349 | /* | |
350 | * Handle a "control" request (signaled by magic being present) | |
351 | * in the data stream. For now, we are only willing to handle | |
352 | * window size changes. | |
353 | */ | |
354 | control(pty, cp, n) | |
355 | int pty; | |
356 | char *cp; | |
357 | int n; | |
358 | { | |
cfafdcf2 | 359 | struct winsize w; |
6632767b | 360 | |
cfafdcf2 | 361 | if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's') |
6632767b | 362 | return (0); |
87e80234 | 363 | oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ |
cfafdcf2 KM |
364 | bcopy(cp+4, (char *)&w, sizeof(w)); |
365 | w.ws_row = ntohs(w.ws_row); | |
366 | w.ws_col = ntohs(w.ws_col); | |
367 | w.ws_xpixel = ntohs(w.ws_xpixel); | |
368 | w.ws_ypixel = ntohs(w.ws_ypixel); | |
369 | (void)ioctl(pty, TIOCSWINSZ, &w); | |
370 | return (4+sizeof (w)); | |
6632767b SL |
371 | } |
372 | ||
373 | /* | |
374 | * rlogin "protocol" machine. | |
375 | */ | |
376 | protocol(f, p) | |
27ed11f5 | 377 | register int f, p; |
6632767b | 378 | { |
b4839a52 | 379 | char pibuf[1024+1], fibuf[1024], *pbp, *fbp; |
6632767b | 380 | register pcc = 0, fcc = 0; |
27ed11f5 | 381 | int cc, nfd, n; |
2c360ad3 | 382 | char cntl; |
6632767b | 383 | |
ffaf1c0b | 384 | /* |
9ee4d121 SL |
385 | * Must ignore SIGTTOU, otherwise we'll stop |
386 | * when we try and set slave pty's window shape | |
87e80234 | 387 | * (our controlling tty is the master pty). |
ffaf1c0b | 388 | */ |
9ee4d121 | 389 | (void) signal(SIGTTOU, SIG_IGN); |
87e80234 | 390 | send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ |
5a93e98d MK |
391 | if (f > p) |
392 | nfd = f + 1; | |
393 | else | |
394 | nfd = p + 1; | |
b4839a52 MK |
395 | if (nfd > FD_SETSIZE) { |
396 | syslog(LOG_ERR, "select mask too small, increase FD_SETSIZE"); | |
397 | fatal(f, "internal error (select mask too small)", 0); | |
398 | } | |
6632767b | 399 | for (;;) { |
b4839a52 | 400 | fd_set ibits, obits, ebits, *omask; |
6632767b | 401 | |
d691a08a | 402 | FD_ZERO(&ebits); |
27ed11f5 KB |
403 | FD_ZERO(&ibits); |
404 | FD_ZERO(&obits); | |
b4839a52 MK |
405 | omask = (fd_set *)NULL; |
406 | if (fcc) { | |
27ed11f5 | 407 | FD_SET(p, &obits); |
b4839a52 MK |
408 | omask = &obits; |
409 | } else | |
27ed11f5 | 410 | FD_SET(f, &ibits); |
6632767b | 411 | if (pcc >= 0) |
b4839a52 | 412 | if (pcc) { |
27ed11f5 | 413 | FD_SET(f, &obits); |
b4839a52 MK |
414 | omask = &obits; |
415 | } else | |
27ed11f5 KB |
416 | FD_SET(p, &ibits); |
417 | FD_SET(p, &ebits); | |
b4839a52 | 418 | if ((n = select(nfd, &ibits, omask, &ebits, 0)) < 0) { |
6632767b | 419 | if (errno == EINTR) |
a10a364d | 420 | continue; |
27ed11f5 | 421 | fatal(f, "select", 1); |
6632767b | 422 | } |
27ed11f5 | 423 | if (n == 0) { |
6632767b SL |
424 | /* shouldn't happen... */ |
425 | sleep(5); | |
426 | continue; | |
427 | } | |
2c360ad3 | 428 | #define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) |
27ed11f5 | 429 | if (FD_ISSET(p, &ebits)) { |
2c360ad3 MK |
430 | cc = read(p, &cntl, 1); |
431 | if (cc == 1 && pkcontrol(cntl)) { | |
432 | cntl |= oobdata[0]; | |
433 | send(f, &cntl, 1, MSG_OOB); | |
434 | if (cntl & TIOCPKT_FLUSHWRITE) { | |
435 | pcc = 0; | |
27ed11f5 | 436 | FD_CLR(p, &ibits); |
2c360ad3 MK |
437 | } |
438 | } | |
439 | } | |
754db9db | 440 | fcc = read(f, fibuf, sizeof(fibuf)); |
6632767b SL |
441 | if (fcc < 0 && errno == EWOULDBLOCK) |
442 | fcc = 0; | |
443 | else { | |
444 | register char *cp; | |
445 | int left, n; | |
446 | ||
447 | if (fcc <= 0) | |
1227078b | 448 | break; |
6632767b | 449 | fbp = fibuf; |
66feb14c | 450 | |
6632767b | 451 | top: |
87e80234 | 452 | for (cp = fibuf; cp < fibuf+fcc-1; cp++) |
6632767b SL |
453 | if (cp[0] == magic[0] && |
454 | cp[1] == magic[1]) { | |
455 | left = fcc - (cp-fibuf); | |
456 | n = control(p, cp, left); | |
457 | if (n) { | |
458 | left -= n; | |
459 | if (left > 0) | |
87e80234 | 460 | bcopy(cp+n, cp, left); |
6632767b SL |
461 | fcc -= n; |
462 | goto top; /* n^2 */ | |
87e80234 MK |
463 | } |
464 | } | |
27ed11f5 | 465 | FD_SET(p, &obits); /* try write */ |
87e80234 MK |
466 | } |
467 | } | |
66feb14c | 468 | |
27ed11f5 | 469 | if (FD_ISSET(p, &obits) && fcc > 0) { |
87e80234 | 470 | cc = write(p, fbp, fcc); |
66feb14c KM |
471 | if (cc > 0) { |
472 | fcc -= cc; | |
473 | fbp += cc; | |
a10a364d | 474 | } |
6632767b | 475 | } |
66feb14c | 476 | |
27ed11f5 | 477 | if (FD_ISSET(p, &ibits)) { |
6632767b SL |
478 | pcc = read(p, pibuf, sizeof (pibuf)); |
479 | pbp = pibuf; | |
480 | if (pcc < 0 && errno == EWOULDBLOCK) | |
481 | pcc = 0; | |
482 | else if (pcc <= 0) | |
483 | break; | |
5a93e98d | 484 | else if (pibuf[0] == 0) { |
6632767b | 485 | pbp++, pcc--; |
754db9db | 486 | obits |= fmask; /* try a write */ |
5a93e98d | 487 | } else { |
6632767b | 488 | if (pkcontrol(pibuf[0])) { |
87e80234 | 489 | pibuf[0] |= oobdata[0]; |
6632767b | 490 | send(f, &pibuf[0], 1, MSG_OOB); |
a10a364d | 491 | } |
6632767b | 492 | pcc = 0; |
a10a364d | 493 | } |
6632767b | 494 | } |
754db9db | 495 | cc = write(f, pbp, pcc); |
87e80234 | 496 | if (cc < 0 && errno == EWOULDBLOCK) { |
b4839a52 MK |
497 | /* |
498 | * This happens when we try write after read | |
499 | * from p, but some old kernels balk at large | |
500 | * writes even when select returns true. | |
501 | */ | |
502 | if (!FD_ISSET(p, &ibits)) | |
503 | sleep(5); | |
87e80234 MK |
504 | continue; |
505 | } | |
6632767b SL |
506 | if (cc > 0) { |
507 | pcc -= cc; | |
508 | pbp += cc; | |
509 | } | |
510 | } | |
a10a364d | 511 | } |
a10a364d BJ |
512 | } |
513 | ||
514 | cleanup() | |
515 | { | |
6487d192 KB |
516 | char *p; |
517 | ||
27ed11f5 | 518 | p = line + sizeof(_PATH_DEV) - 1; |
6487d192 KB |
519 | if (logout(p)) |
520 | logwtmp(p, "", ""); | |
521 | (void)chmod(line, 0666); | |
522 | (void)chown(line, 0, 0); | |
523 | *p = 'p'; | |
524 | (void)chmod(line, 0666); | |
525 | (void)chown(line, 0, 0); | |
ff24c640 | 526 | shutdown(netf, 2); |
a10a364d BJ |
527 | exit(1); |
528 | } | |
529 | ||
27ed11f5 KB |
530 | fatal(f, msg, syserr) |
531 | int f, syserr; | |
82c973f2 SL |
532 | char *msg; |
533 | { | |
27ed11f5 | 534 | int len; |
b4839a52 | 535 | char buf[BUFSIZ], *bp = buf; |
82c973f2 | 536 | |
b4839a52 MK |
537 | /* |
538 | * Prepend binary one to message if we haven't sent | |
539 | * the magic null as confirmation. | |
540 | */ | |
541 | if (!confirmed) | |
542 | *bp++ = '\01'; /* error indicator */ | |
27ed11f5 | 543 | if (syserr) |
b4839a52 | 544 | len = sprintf(bp, "rlogind: %s: %s.\r\n", |
27ed11f5 | 545 | msg, strerror(errno)); |
1227078b | 546 | else |
b4839a52 MK |
547 | len = sprintf(bp, "rlogind: %s.\r\n", msg); |
548 | (void) write(f, buf, bp + len - buf); | |
27ed11f5 | 549 | exit(1); |
82c973f2 | 550 | } |
e3fc62b0 | 551 | |
dfd00f77 | 552 | #ifndef OLD_LOGIN |
e3fc62b0 | 553 | do_rlogin(host) |
9d5f81ab | 554 | char *host; |
e3fc62b0 | 555 | { |
9d5f81ab MK |
556 | getstr(rusername, sizeof(rusername), "remuser too long"); |
557 | getstr(lusername, sizeof(lusername), "locuser too long"); | |
558 | getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long"); | |
559 | ||
e3fc62b0 | 560 | pwd = getpwnam(lusername); |
9d5f81ab | 561 | if (pwd == NULL) |
e3fc62b0 | 562 | return(-1); |
f5bb5ea0 KB |
563 | if (pwd->pw_uid == 0) |
564 | return(-1); | |
565 | return(ruserok(host, 0, rusername, lusername)); | |
e3fc62b0 KF |
566 | } |
567 | ||
568 | ||
9d5f81ab MK |
569 | getstr(buf, cnt, errmsg) |
570 | char *buf; | |
571 | int cnt; | |
572 | char *errmsg; | |
e3fc62b0 | 573 | { |
9d5f81ab MK |
574 | char c; |
575 | ||
e3fc62b0 | 576 | do { |
9d5f81ab | 577 | if (read(0, &c, 1) != 1) |
e3fc62b0 | 578 | exit(1); |
9d5f81ab | 579 | if (--cnt < 0) |
27ed11f5 | 580 | fatal(STDOUT_FILENO, errmsg, 0); |
e3fc62b0 | 581 | *buf++ = c; |
9d5f81ab | 582 | } while (c != 0); |
e3fc62b0 KF |
583 | } |
584 | ||
9d5f81ab | 585 | extern char **environ; |
e3fc62b0 | 586 | |
dfd00f77 MK |
587 | char *speeds[] = { |
588 | "0", "50", "75", "110", "134", "150", "200", "300", "600", | |
589 | "1200", "1800", "2400", "4800", "9600", "19200", "38400", | |
590 | }; | |
591 | #define NSPEEDS (sizeof(speeds) / sizeof(speeds[0])) | |
592 | ||
593 | setup_term(fd) | |
594 | int fd; | |
595 | { | |
596 | register char *cp = index(term, '/'), **cpp; | |
dfd00f77 | 597 | char *speed; |
f295ed5f MK |
598 | #if BSD > 43 |
599 | struct termios tt; | |
600 | ||
601 | tcgetattr(fd, &tt); | |
602 | if (cp) { | |
603 | *cp++ = '\0'; | |
604 | speed = cp; | |
605 | cp = index(speed, '/'); | |
606 | if (cp) | |
607 | *cp++ = '\0'; | |
608 | cfsetspeed(&tt, atoi(speed)); | |
609 | } | |
610 | ||
611 | tt.c_iflag = TTYDEF_IFLAG; | |
612 | tt.c_oflag = TTYDEF_OFLAG; | |
613 | tt.c_lflag = TTYDEF_LFLAG; | |
614 | tcsetattr(fd, TCSADFLUSH, &tt); | |
615 | #else | |
616 | struct sgttyb sgttyb; | |
dfd00f77 MK |
617 | |
618 | (void)ioctl(fd, TIOCGETP, &sgttyb); | |
619 | if (cp) { | |
620 | *cp++ = '\0'; | |
621 | speed = cp; | |
622 | cp = index(speed, '/'); | |
623 | if (cp) | |
624 | *cp++ = '\0'; | |
625 | for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++) | |
626 | if (strcmp(*cpp, speed) == 0) { | |
627 | sgttyb.sg_ispeed = sgttyb.sg_ospeed = cpp - speeds; | |
628 | break; | |
629 | } | |
630 | } | |
631 | sgttyb.sg_flags = ECHO|CRMOD|ANYP|XTABS; | |
632 | (void)ioctl(fd, TIOCSETP, &sgttyb); | |
f295ed5f | 633 | #endif |
dfd00f77 MK |
634 | |
635 | env[0] = term; | |
636 | env[1] = 0; | |
637 | environ = env; | |
638 | } | |
2b08f0dd MK |
639 | |
640 | /* | |
641 | * Check whether host h is in our local domain, | |
f295ed5f MK |
642 | * defined as sharing the last two components of the domain part, |
643 | * or the entire domain part if the local domain has only one component. | |
2b08f0dd MK |
644 | * If either name is unqualified (contains no '.'), |
645 | * assume that the host is local, as it will be | |
646 | * interpreted as such. | |
647 | */ | |
648 | local_domain(h) | |
649 | char *h; | |
650 | { | |
651 | char localhost[MAXHOSTNAMELEN]; | |
f295ed5f | 652 | char *p1, *p2, *topdomain(); |
2b08f0dd | 653 | |
f295ed5f | 654 | localhost[0] = 0; |
2b08f0dd | 655 | (void) gethostname(localhost, sizeof(localhost)); |
f295ed5f MK |
656 | p1 = topdomain(localhost); |
657 | p2 = topdomain(h); | |
2b08f0dd MK |
658 | if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2)) |
659 | return(1); | |
660 | return(0); | |
661 | } | |
f295ed5f MK |
662 | |
663 | char * | |
664 | topdomain(h) | |
665 | char *h; | |
666 | { | |
667 | register char *p; | |
668 | char *maybe = NULL; | |
669 | int dots = 0; | |
670 | ||
671 | for (p = h + strlen(h); p >= h; p--) { | |
672 | if (*p == '.') { | |
673 | if (++dots == 2) | |
674 | return (p); | |
675 | maybe = p; | |
676 | } | |
677 | } | |
678 | return (maybe); | |
679 | } | |
dfd00f77 | 680 | #endif /* OLD_LOGIN */ |