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