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