1 /*-
2 * Copyright (c) 1983, 1988, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1983, 1988, 1989, 1993\n\
11 The Regents of the University of California. All rights reserved.\n";
12 #endif /* not lint */
13
14 #ifndef lint
15 static char sccsid[] = "@(#)rlogind.c 8.2 (Berkeley) 04/28/95";
16 #endif /* not lint */
17
18 /*
19 * remote login server:
20 * \0
21 * remuser\0
22 * locuser\0
23 * terminal_type/speed\0
24 * data
25 */
26
27 #define FD_SETSIZE 16 /* don't need many bits for select */
28 #include <sys/param.h>
29 #include <sys/stat.h>
30 #include <sys/ioctl.h>
31 #include <signal.h>
32 #include <termios.h>
33
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <netinet/in_systm.h>
37 #include <netinet/ip.h>
38 #include <arpa/inet.h>
39 #include <netdb.h>
40
41 #include <pwd.h>
42 #include <syslog.h>
43 #include <errno.h>
44 #include <stdio.h>
45 #include <unistd.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include "pathnames.h"
49
50 #ifndef TIOCPKT_WINDOW
51 #define TIOCPKT_WINDOW 0x80
52 #endif
53
54 #ifdef KERBEROS
55 #include <kerberosIV/des.h>
56 #include <kerberosIV/krb.h>
57 #define SECURE_MESSAGE "This rlogin session is using DES encryption for all transmissions.\r\n"
58
59 AUTH_DAT *kdata;
60 KTEXT ticket;
61 u_char auth_buf[sizeof(AUTH_DAT)];
62 u_char tick_buf[sizeof(KTEXT_ST)];
63 Key_schedule schedule;
64 int doencrypt, retval, use_kerberos, vacuous;
65
66 #define ARGSTR "alnkvx"
67 #else
68 #define ARGSTR "aln"
69 #endif /* KERBEROS */
70
71 char *env[2];
72 #define NMAX 30
73 char lusername[NMAX+1], rusername[NMAX+1];
74 static char term[64] = "TERM=";
75 #define ENVSIZE (sizeof("TERM=")-1) /* skip null for concatenation */
76 int keepalive = 1;
77 int check_all = 0;
78
79 struct passwd *pwd;
80
81 void doit __P((int, struct sockaddr_in *));
82 int control __P((int, char *, int));
83 void protocol __P((int, int));
84 void cleanup __P((int));
85 void fatal __P((int, char *, int));
86 int do_rlogin __P((struct sockaddr_in *));
87 void getstr __P((char *, int, char *));
88 void setup_term __P((int));
89 int do_krb_login __P((struct sockaddr_in *));
90 void usage __P((void));
91 int local_domain __P((char *));
92 char *topdomain __P((char *));
93
94 int
main(argc,argv)95 main(argc, argv)
96 int argc;
97 char *argv[];
98 {
99 extern int __check_rhosts_file;
100 struct sockaddr_in from;
101 int ch, fromlen, on;
102
103 openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH);
104
105 opterr = 0;
106 while ((ch = getopt(argc, argv, ARGSTR)) != EOF)
107 switch (ch) {
108 case 'a':
109 check_all = 1;
110 break;
111 case 'l':
112 __check_rhosts_file = 0;
113 break;
114 case 'n':
115 keepalive = 0;
116 break;
117 #ifdef KERBEROS
118 case 'k':
119 use_kerberos = 1;
120 break;
121 case 'v':
122 vacuous = 1;
123 break;
124 #ifdef CRYPT
125 case 'x':
126 doencrypt = 1;
127 break;
128 #endif
129 #endif
130 case '?':
131 default:
132 usage();
133 break;
134 }
135 argc -= optind;
136 argv += optind;
137
138 #ifdef KERBEROS
139 if (use_kerberos && vacuous) {
140 usage();
141 fatal(STDERR_FILENO, "only one of -k and -v allowed", 0);
142 }
143 #endif
144 fromlen = sizeof (from);
145 if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
146 syslog(LOG_ERR,"Can't get peer name of remote host: %m");
147 fatal(STDERR_FILENO, "Can't get peer name of remote host", 1);
148 }
149 on = 1;
150 if (keepalive &&
151 setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0)
152 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
153 on = IPTOS_LOWDELAY;
154 if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
155 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
156 doit(0, &from);
157 }
158
159 int child;
160 int netf;
161 char line[MAXPATHLEN];
162 int confirmed;
163
164 struct winsize win = { 0, 0, 0, 0 };
165
166
167 void
doit(f,fromp)168 doit(f, fromp)
169 int f;
170 struct sockaddr_in *fromp;
171 {
172 int master, pid, on = 1;
173 int authenticated = 0;
174 register struct hostent *hp;
175 char hostname[2 * MAXHOSTNAMELEN + 1];
176 char c;
177
178 alarm(60);
179 read(f, &c, 1);
180
181 if (c != 0)
182 exit(1);
183 #ifdef KERBEROS
184 if (vacuous)
185 fatal(f, "Remote host requires Kerberos authentication", 0);
186 #endif
187
188 alarm(0);
189 fromp->sin_port = ntohs((u_short)fromp->sin_port);
190 hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof(struct in_addr),
191 fromp->sin_family);
192 if (hp)
193 (void)strcpy(hostname, hp->h_name);
194 else
195 (void)strcpy(hostname, inet_ntoa(fromp->sin_addr));
196
197 #ifdef KERBEROS
198 if (use_kerberos) {
199 retval = do_krb_login(fromp);
200 if (retval == 0)
201 authenticated++;
202 else if (retval > 0)
203 fatal(f, krb_err_txt[retval], 0);
204 write(f, &c, 1);
205 confirmed = 1; /* we sent the null! */
206 } else
207 #endif
208 {
209 if (fromp->sin_family != AF_INET ||
210 fromp->sin_port >= IPPORT_RESERVED ||
211 fromp->sin_port < IPPORT_RESERVED/2) {
212 syslog(LOG_NOTICE, "Connection from %s on illegal port",
213 inet_ntoa(fromp->sin_addr));
214 fatal(f, "Permission denied", 0);
215 }
216 #ifdef IP_OPTIONS
217 {
218 u_char optbuf[BUFSIZ/3], *cp;
219 char lbuf[BUFSIZ], *lp;
220 int optsize = sizeof(optbuf), ipproto;
221 struct protoent *ip;
222
223 if ((ip = getprotobyname("ip")) != NULL)
224 ipproto = ip->p_proto;
225 else
226 ipproto = IPPROTO_IP;
227 if (getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf,
228 &optsize) == 0 && optsize != 0) {
229 lp = lbuf;
230 for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3)
231 sprintf(lp, " %2.2x", *cp);
232 syslog(LOG_NOTICE,
233 "Connection received using IP options (ignored):%s",
234 lbuf);
235 if (setsockopt(0, ipproto, IP_OPTIONS,
236 (char *)NULL, optsize) != 0) {
237 syslog(LOG_ERR,
238 "setsockopt IP_OPTIONS NULL: %m");
239 exit(1);
240 }
241 }
242 }
243 #endif
244 if (do_rlogin(fromp) == 0)
245 authenticated++;
246 }
247 if (confirmed == 0) {
248 write(f, "", 1);
249 confirmed = 1; /* we sent the null! */
250 }
251 #ifdef KERBEROS
252 #ifdef CRYPT
253 if (doencrypt)
254 (void) des_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE) - 1);
255 #endif
256 #endif
257 netf = f;
258
259 pid = forkpty(&master, line, NULL, &win);
260 if (pid < 0) {
261 if (errno == ENOENT)
262 fatal(f, "Out of ptys", 0);
263 else
264 fatal(f, "Forkpty", 1);
265 }
266 if (pid == 0) {
267 if (f > 2) /* f should always be 0, but... */
268 (void) close(f);
269 setup_term(0);
270 if (authenticated) {
271 #ifdef KERBEROS
272 if (use_kerberos && (pwd->pw_uid == 0))
273 syslog(LOG_INFO|LOG_AUTH,
274 "ROOT Kerberos login from %s.%s@%s on %s\n",
275 kdata->pname, kdata->pinst, kdata->prealm,
276 hostname);
277 #endif
278
279 execle(_PATH_LOGIN, "login", "-p",
280 "-h", hostname, "-f", "--", lusername, NULL, env);
281 } else
282 execle(_PATH_LOGIN, "login", "-p",
283 "-h", hostname, "--", lusername, NULL, env);
284 fatal(STDERR_FILENO, _PATH_LOGIN, 1);
285 /*NOTREACHED*/
286 }
287 #ifdef CRYPT
288 #ifdef KERBEROS
289 /*
290 * If encrypted, don't turn on NBIO or the des read/write
291 * routines will croak.
292 */
293
294 if (!doencrypt)
295 #endif
296 #endif
297 ioctl(f, FIONBIO, &on);
298 ioctl(master, FIONBIO, &on);
299 ioctl(master, TIOCPKT, &on);
300 signal(SIGCHLD, cleanup);
301 protocol(f, master);
302 signal(SIGCHLD, SIG_IGN);
303 cleanup(0);
304 }
305
306 char magic[2] = { 0377, 0377 };
307 char oobdata[] = {TIOCPKT_WINDOW};
308
309 /*
310 * Handle a "control" request (signaled by magic being present)
311 * in the data stream. For now, we are only willing to handle
312 * window size changes.
313 */
314 int
control(pty,cp,n)315 control(pty, cp, n)
316 int pty;
317 char *cp;
318 int n;
319 {
320 struct winsize w;
321
322 if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's')
323 return (0);
324 oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */
325 memmove(&w, cp+4, sizeof(w));
326 w.ws_row = ntohs(w.ws_row);
327 w.ws_col = ntohs(w.ws_col);
328 w.ws_xpixel = ntohs(w.ws_xpixel);
329 w.ws_ypixel = ntohs(w.ws_ypixel);
330 (void)ioctl(pty, TIOCSWINSZ, &w);
331 return (4+sizeof (w));
332 }
333
334 /*
335 * rlogin "protocol" machine.
336 */
337 void
protocol(f,p)338 protocol(f, p)
339 register int f, p;
340 {
341 char pibuf[1024+1], fibuf[1024], *pbp, *fbp;
342 register pcc = 0, fcc = 0;
343 int cc, nfd, n;
344 char cntl;
345
346 /*
347 * Must ignore SIGTTOU, otherwise we'll stop
348 * when we try and set slave pty's window shape
349 * (our controlling tty is the master pty).
350 */
351 (void) signal(SIGTTOU, SIG_IGN);
352 send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */
353 if (f > p)
354 nfd = f + 1;
355 else
356 nfd = p + 1;
357 if (nfd > FD_SETSIZE) {
358 syslog(LOG_ERR, "select mask too small, increase FD_SETSIZE");
359 fatal(f, "internal error (select mask too small)", 0);
360 }
361 for (;;) {
362 fd_set ibits, obits, ebits, *omask;
363
364 FD_ZERO(&ebits);
365 FD_ZERO(&ibits);
366 FD_ZERO(&obits);
367 omask = (fd_set *)NULL;
368 if (fcc) {
369 FD_SET(p, &obits);
370 omask = &obits;
371 } else
372 FD_SET(f, &ibits);
373 if (pcc >= 0)
374 if (pcc) {
375 FD_SET(f, &obits);
376 omask = &obits;
377 } else
378 FD_SET(p, &ibits);
379 FD_SET(p, &ebits);
380 if ((n = select(nfd, &ibits, omask, &ebits, 0)) < 0) {
381 if (errno == EINTR)
382 continue;
383 fatal(f, "select", 1);
384 }
385 if (n == 0) {
386 /* shouldn't happen... */
387 sleep(5);
388 continue;
389 }
390 #define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))
391 if (FD_ISSET(p, &ebits)) {
392 cc = read(p, &cntl, 1);
393 if (cc == 1 && pkcontrol(cntl)) {
394 cntl |= oobdata[0];
395 send(f, &cntl, 1, MSG_OOB);
396 if (cntl & TIOCPKT_FLUSHWRITE) {
397 pcc = 0;
398 FD_CLR(p, &ibits);
399 }
400 }
401 }
402 if (FD_ISSET(f, &ibits)) {
403 #ifdef CRYPT
404 #ifdef KERBEROS
405 if (doencrypt)
406 fcc = des_read(f, fibuf, sizeof(fibuf));
407 else
408 #endif
409 #endif
410 fcc = read(f, fibuf, sizeof(fibuf));
411 if (fcc < 0 && errno == EWOULDBLOCK)
412 fcc = 0;
413 else {
414 register char *cp;
415 int left, n;
416
417 if (fcc <= 0)
418 break;
419 fbp = fibuf;
420
421 top:
422 for (cp = fibuf; cp < fibuf+fcc-1; cp++)
423 if (cp[0] == magic[0] &&
424 cp[1] == magic[1]) {
425 left = fcc - (cp-fibuf);
426 n = control(p, cp, left);
427 if (n) {
428 left -= n;
429 if (left > 0)
430 bcopy(cp+n, cp, left);
431 fcc -= n;
432 goto top; /* n^2 */
433 }
434 }
435 FD_SET(p, &obits); /* try write */
436 }
437 }
438
439 if (FD_ISSET(p, &obits) && fcc > 0) {
440 cc = write(p, fbp, fcc);
441 if (cc > 0) {
442 fcc -= cc;
443 fbp += cc;
444 }
445 }
446
447 if (FD_ISSET(p, &ibits)) {
448 pcc = read(p, pibuf, sizeof (pibuf));
449 pbp = pibuf;
450 if (pcc < 0 && errno == EWOULDBLOCK)
451 pcc = 0;
452 else if (pcc <= 0)
453 break;
454 else if (pibuf[0] == 0) {
455 pbp++, pcc--;
456 #ifdef CRYPT
457 #ifdef KERBEROS
458 if (!doencrypt)
459 #endif
460 #endif
461 FD_SET(f, &obits); /* try write */
462 } else {
463 if (pkcontrol(pibuf[0])) {
464 pibuf[0] |= oobdata[0];
465 send(f, &pibuf[0], 1, MSG_OOB);
466 }
467 pcc = 0;
468 }
469 }
470 if ((FD_ISSET(f, &obits)) && pcc > 0) {
471 #ifdef CRYPT
472 #ifdef KERBEROS
473 if (doencrypt)
474 cc = des_write(f, pbp, pcc);
475 else
476 #endif
477 #endif
478 cc = write(f, pbp, pcc);
479 if (cc < 0 && errno == EWOULDBLOCK) {
480 /*
481 * This happens when we try write after read
482 * from p, but some old kernels balk at large
483 * writes even when select returns true.
484 */
485 if (!FD_ISSET(p, &ibits))
486 sleep(5);
487 continue;
488 }
489 if (cc > 0) {
490 pcc -= cc;
491 pbp += cc;
492 }
493 }
494 }
495 }
496
497 void
cleanup(signo)498 cleanup(signo)
499 int signo;
500 {
501 char *p;
502
503 p = line + sizeof(_PATH_DEV) - 1;
504 if (logout(p))
505 logwtmp(p, "", "");
506 (void)chmod(line, 0666);
507 (void)chown(line, 0, 0);
508 *p = 'p';
509 (void)chmod(line, 0666);
510 (void)chown(line, 0, 0);
511 shutdown(netf, 2);
512 exit(1);
513 }
514
515 void
fatal(f,msg,syserr)516 fatal(f, msg, syserr)
517 int f;
518 char *msg;
519 int syserr;
520 {
521 int len;
522 char buf[BUFSIZ], *bp = buf;
523
524 /*
525 * Prepend binary one to message if we haven't sent
526 * the magic null as confirmation.
527 */
528 if (!confirmed)
529 *bp++ = '\01'; /* error indicator */
530 if (syserr)
531 len = sprintf(bp, "rlogind: %s: %s.\r\n",
532 msg, strerror(errno));
533 else
534 len = sprintf(bp, "rlogind: %s.\r\n", msg);
535 (void) write(f, buf, bp + len - buf);
536 exit(1);
537 }
538
539 int
do_rlogin(dest)540 do_rlogin(dest)
541 struct sockaddr_in *dest;
542 {
543 getstr(rusername, sizeof(rusername), "remuser too long");
544 getstr(lusername, sizeof(lusername), "locuser too long");
545 getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long");
546
547 pwd = getpwnam(lusername);
548 if (pwd == NULL)
549 return (-1);
550 if (pwd->pw_uid == 0)
551 return (-1);
552 /* XXX why don't we syslog() failure? */
553 return (iruserok(dest->sin_addr.s_addr, 0, rusername, lusername));
554 }
555
556 void
getstr(buf,cnt,errmsg)557 getstr(buf, cnt, errmsg)
558 char *buf;
559 int cnt;
560 char *errmsg;
561 {
562 char c;
563
564 do {
565 if (read(0, &c, 1) != 1)
566 exit(1);
567 if (--cnt < 0)
568 fatal(STDOUT_FILENO, errmsg, 0);
569 *buf++ = c;
570 } while (c != 0);
571 }
572
573 void
setup_term(fd)574 setup_term(fd)
575 int fd;
576 {
577 register char *cp = index(term+ENVSIZE, '/');
578 char *speed;
579 struct termios tt;
580
581 #ifndef notyet
582 tcgetattr(fd, &tt);
583 if (cp) {
584 *cp++ = '\0';
585 speed = cp;
586 cp = index(speed, '/');
587 if (cp)
588 *cp++ = '\0';
589 cfsetspeed(&tt, atoi(speed));
590 }
591
592 tt.c_iflag = TTYDEF_IFLAG;
593 tt.c_oflag = TTYDEF_OFLAG;
594 tt.c_lflag = TTYDEF_LFLAG;
595 tcsetattr(fd, TCSAFLUSH, &tt);
596 #else
597 if (cp) {
598 *cp++ = '\0';
599 speed = cp;
600 cp = index(speed, '/');
601 if (cp)
602 *cp++ = '\0';
603 tcgetattr(fd, &tt);
604 cfsetspeed(&tt, atoi(speed));
605 tcsetattr(fd, TCSAFLUSH, &tt);
606 }
607 #endif
608
609 env[0] = term;
610 env[1] = 0;
611 }
612
613 #ifdef KERBEROS
614 #define VERSION_SIZE 9
615
616 /*
617 * Do the remote kerberos login to the named host with the
618 * given inet address
619 *
620 * Return 0 on valid authorization
621 * Return -1 on valid authentication, no authorization
622 * Return >0 for error conditions
623 */
624 int
do_krb_login(dest)625 do_krb_login(dest)
626 struct sockaddr_in *dest;
627 {
628 int rc;
629 char instance[INST_SZ], version[VERSION_SIZE];
630 long authopts = 0L; /* !mutual */
631 struct sockaddr_in faddr;
632
633 kdata = (AUTH_DAT *) auth_buf;
634 ticket = (KTEXT) tick_buf;
635
636 instance[0] = '*';
637 instance[1] = '\0';
638
639 #ifdef CRYPT
640 if (doencrypt) {
641 rc = sizeof(faddr);
642 if (getsockname(0, (struct sockaddr *)&faddr, &rc))
643 return (-1);
644 authopts = KOPT_DO_MUTUAL;
645 rc = krb_recvauth(
646 authopts, 0,
647 ticket, "rcmd",
648 instance, dest, &faddr,
649 kdata, "", schedule, version);
650 des_set_key(kdata->session, schedule);
651
652 } else
653 #endif
654 rc = krb_recvauth(
655 authopts, 0,
656 ticket, "rcmd",
657 instance, dest, (struct sockaddr_in *) 0,
658 kdata, "", (bit_64 *) 0, version);
659
660 if (rc != KSUCCESS)
661 return (rc);
662
663 getstr(lusername, sizeof(lusername), "locuser");
664 /* get the "cmd" in the rcmd protocol */
665 getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type");
666
667 pwd = getpwnam(lusername);
668 if (pwd == NULL)
669 return (-1);
670
671 /* returns nonzero for no access */
672 if (kuserok(kdata, lusername) != 0)
673 return (-1);
674
675 return (0);
676
677 }
678 #endif /* KERBEROS */
679
680 void
usage()681 usage()
682 {
683 #ifdef KERBEROS
684 syslog(LOG_ERR, "usage: rlogind [-aln] [-k | -v]");
685 #else
686 syslog(LOG_ERR, "usage: rlogind [-aln]");
687 #endif
688 }
689
690 /*
691 * Check whether host h is in our local domain,
692 * defined as sharing the last two components of the domain part,
693 * or the entire domain part if the local domain has only one component.
694 * If either name is unqualified (contains no '.'),
695 * assume that the host is local, as it will be
696 * interpreted as such.
697 */
698 int
local_domain(h)699 local_domain(h)
700 char *h;
701 {
702 char localhost[MAXHOSTNAMELEN];
703 char *p1, *p2;
704
705 localhost[0] = 0;
706 (void) gethostname(localhost, sizeof(localhost));
707 p1 = topdomain(localhost);
708 p2 = topdomain(h);
709 if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2))
710 return (1);
711 return (0);
712 }
713
714 char *
topdomain(h)715 topdomain(h)
716 char *h;
717 {
718 register char *p;
719 char *maybe = NULL;
720 int dots = 0;
721
722 for (p = h + strlen(h); p >= h; p--) {
723 if (*p == '.') {
724 if (++dots == 2)
725 return (p);
726 maybe = p;
727 }
728 }
729 return (maybe);
730 }
731