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 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 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 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 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 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 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 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 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 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 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 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 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 * 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