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