1 /*- 2 * Copyright (c) 1988, 1989, 1992, 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) 1988, 1989, 1992, 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[] = "@(#)rshd.c 8.1 (Berkeley) 06/04/93"; 16 #endif /* not lint */ 17 18 /* 19 * remote shell server: 20 * [port]\0 21 * remuser\0 22 * locuser\0 23 * command\0 24 * data 25 */ 26 #include <sys/param.h> 27 #include <sys/ioctl.h> 28 #include <sys/time.h> 29 #include <sys/socket.h> 30 31 #include <netinet/in.h> 32 #include <arpa/inet.h> 33 #include <netdb.h> 34 35 #include <fcntl.h> 36 #include <signal.h> 37 #include <pwd.h> 38 #include <syslog.h> 39 #include <unistd.h> 40 #include <errno.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <paths.h> 45 46 int keepalive = 1; 47 int check_all; 48 int log_success; /* If TRUE, log all successful accesses */ 49 int sent_null; 50 51 void doit __P((struct sockaddr_in *)); 52 void error __P((const char *, ...)); 53 void getstr __P((char *, int, char *)); 54 int local_domain __P((char *)); 55 char *topdomain __P((char *)); 56 void usage __P((void)); 57 58 #ifdef KERBEROS 59 #include <kerberosIV/des.h> 60 #include <kerberosIV/krb.h> 61 #define VERSION_SIZE 9 62 #define SECURE_MESSAGE "This rsh session is using DES encryption for all transmissions.\r\n" 63 #define OPTIONS "alnkvxL" 64 char authbuf[sizeof(AUTH_DAT)]; 65 char tickbuf[sizeof(KTEXT_ST)]; 66 int doencrypt, use_kerberos, vacuous; 67 Key_schedule schedule; 68 #else 69 #define OPTIONS "alnL" 70 #endif 71 72 int 73 main(argc, argv) 74 int argc; 75 char *argv[]; 76 { 77 extern int __check_rhosts_file; 78 struct linger linger; 79 int ch, on = 1, fromlen; 80 struct sockaddr_in from; 81 82 openlog("rshd", LOG_PID | LOG_ODELAY, LOG_DAEMON); 83 84 opterr = 0; 85 while ((ch = getopt(argc, argv, OPTIONS)) != EOF) 86 switch (ch) { 87 case 'a': 88 check_all = 1; 89 break; 90 case 'l': 91 __check_rhosts_file = 0; 92 break; 93 case 'n': 94 keepalive = 0; 95 break; 96 #ifdef KERBEROS 97 case 'k': 98 use_kerberos = 1; 99 break; 100 101 case 'v': 102 vacuous = 1; 103 break; 104 105 #ifdef CRYPT 106 case 'x': 107 doencrypt = 1; 108 break; 109 #endif 110 #endif 111 case 'L': 112 log_success = 1; 113 break; 114 case '?': 115 default: 116 usage(); 117 exit(2); 118 } 119 120 argc -= optind; 121 argv += optind; 122 123 #ifdef KERBEROS 124 if (use_kerberos && vacuous) { 125 syslog(LOG_ERR, "only one of -k and -v allowed"); 126 exit(2); 127 } 128 #ifdef CRYPT 129 if (doencrypt && !use_kerberos) { 130 syslog(LOG_ERR, "-k is required for -x"); 131 exit(2); 132 } 133 #endif 134 #endif 135 136 fromlen = sizeof (from); 137 if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { 138 syslog(LOG_ERR, "getpeername: %m"); 139 _exit(1); 140 } 141 if (keepalive && 142 setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, 143 sizeof(on)) < 0) 144 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 145 linger.l_onoff = 1; 146 linger.l_linger = 60; /* XXX */ 147 if (setsockopt(0, SOL_SOCKET, SO_LINGER, (char *)&linger, 148 sizeof (linger)) < 0) 149 syslog(LOG_WARNING, "setsockopt (SO_LINGER): %m"); 150 doit(&from); 151 /* NOTREACHED */ 152 } 153 154 char username[20] = "USER="; 155 char homedir[64] = "HOME="; 156 char shell[64] = "SHELL="; 157 char path[100] = "PATH="; 158 char *envinit[] = 159 {homedir, shell, path, username, 0}; 160 char **environ; 161 162 void 163 doit(fromp) 164 struct sockaddr_in *fromp; 165 { 166 extern char *__rcmd_errstr; /* syslog hook from libc/net/rcmd.c. */ 167 struct hostent *hp; 168 struct passwd *pwd; 169 u_short port; 170 fd_set ready, readfrom; 171 int cc, nfd, pv[2], pid, s; 172 int one = 1; 173 char *hostname, *errorstr, *errorhost; 174 char *cp, sig, buf[BUFSIZ]; 175 char cmdbuf[NCARGS+1], locuser[16], remuser[16]; 176 char remotehost[2 * MAXHOSTNAMELEN + 1]; 177 178 #ifdef KERBEROS 179 AUTH_DAT *kdata = (AUTH_DAT *) NULL; 180 KTEXT ticket = (KTEXT) NULL; 181 char instance[INST_SZ], version[VERSION_SIZE]; 182 struct sockaddr_in fromaddr; 183 int rc; 184 long authopts; 185 int pv1[2], pv2[2]; 186 fd_set wready, writeto; 187 188 fromaddr = *fromp; 189 #endif 190 191 (void) signal(SIGINT, SIG_DFL); 192 (void) signal(SIGQUIT, SIG_DFL); 193 (void) signal(SIGTERM, SIG_DFL); 194 #ifdef DEBUG 195 { int t = open(_PATH_TTY, 2); 196 if (t >= 0) { 197 ioctl(t, TIOCNOTTY, (char *)0); 198 (void) close(t); 199 } 200 } 201 #endif 202 fromp->sin_port = ntohs((u_short)fromp->sin_port); 203 if (fromp->sin_family != AF_INET) { 204 syslog(LOG_ERR, "malformed \"from\" address (af %d)\n", 205 fromp->sin_family); 206 exit(1); 207 } 208 #ifdef IP_OPTIONS 209 { 210 u_char optbuf[BUFSIZ/3], *cp; 211 char lbuf[BUFSIZ], *lp; 212 int optsize = sizeof(optbuf), ipproto; 213 struct protoent *ip; 214 215 if ((ip = getprotobyname("ip")) != NULL) 216 ipproto = ip->p_proto; 217 else 218 ipproto = IPPROTO_IP; 219 if (!getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, &optsize) && 220 optsize != 0) { 221 lp = lbuf; 222 for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3) 223 sprintf(lp, " %2.2x", *cp); 224 syslog(LOG_NOTICE, 225 "Connection received from %s using IP options (ignored):%s", 226 inet_ntoa(fromp->sin_addr), lbuf); 227 if (setsockopt(0, ipproto, IP_OPTIONS, 228 (char *)NULL, optsize) != 0) { 229 syslog(LOG_ERR, "setsockopt IP_OPTIONS NULL: %m"); 230 exit(1); 231 } 232 } 233 } 234 #endif 235 236 #ifdef KERBEROS 237 if (!use_kerberos) 238 #endif 239 if (fromp->sin_port >= IPPORT_RESERVED || 240 fromp->sin_port < IPPORT_RESERVED/2) { 241 syslog(LOG_NOTICE|LOG_AUTH, 242 "Connection from %s on illegal port %u", 243 inet_ntoa(fromp->sin_addr), 244 fromp->sin_port); 245 exit(1); 246 } 247 248 (void) alarm(60); 249 port = 0; 250 for (;;) { 251 char c; 252 if ((cc = read(STDIN_FILENO, &c, 1)) != 1) { 253 if (cc < 0) 254 syslog(LOG_NOTICE, "read: %m"); 255 shutdown(0, 1+1); 256 exit(1); 257 } 258 if (c== 0) 259 break; 260 port = port * 10 + c - '0'; 261 } 262 263 (void) alarm(0); 264 if (port != 0) { 265 int lport = IPPORT_RESERVED - 1; 266 s = rresvport(&lport); 267 if (s < 0) { 268 syslog(LOG_ERR, "can't get stderr port: %m"); 269 exit(1); 270 } 271 #ifdef KERBEROS 272 if (!use_kerberos) 273 #endif 274 if (port >= IPPORT_RESERVED) { 275 syslog(LOG_ERR, "2nd port not reserved\n"); 276 exit(1); 277 } 278 fromp->sin_port = htons(port); 279 if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0) { 280 syslog(LOG_INFO, "connect second port %d: %m", port); 281 exit(1); 282 } 283 } 284 285 #ifdef KERBEROS 286 if (vacuous) { 287 error("rshd: remote host requires Kerberos authentication\n"); 288 exit(1); 289 } 290 #endif 291 292 #ifdef notdef 293 /* from inetd, socket is already on 0, 1, 2 */ 294 dup2(f, 0); 295 dup2(f, 1); 296 dup2(f, 2); 297 #endif 298 errorstr = NULL; 299 hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (struct in_addr), 300 fromp->sin_family); 301 if (hp) { 302 /* 303 * If name returned by gethostbyaddr is in our domain, 304 * attempt to verify that we haven't been fooled by someone 305 * in a remote net; look up the name and check that this 306 * address corresponds to the name. 307 */ 308 hostname = hp->h_name; 309 #ifdef KERBEROS 310 if (!use_kerberos) 311 #endif 312 if (check_all || local_domain(hp->h_name)) { 313 strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1); 314 remotehost[sizeof(remotehost) - 1] = 0; 315 errorhost = remotehost; 316 hp = gethostbyname(remotehost); 317 if (hp == NULL) { 318 syslog(LOG_INFO, 319 "Couldn't look up address for %s", 320 remotehost); 321 errorstr = 322 "Couldn't look up address for your host (%s)\n"; 323 hostname = inet_ntoa(fromp->sin_addr); 324 } else for (; ; hp->h_addr_list++) { 325 if (hp->h_addr_list[0] == NULL) { 326 syslog(LOG_NOTICE, 327 "Host addr %s not listed for host %s", 328 inet_ntoa(fromp->sin_addr), 329 hp->h_name); 330 errorstr = 331 "Host address mismatch for %s\n"; 332 hostname = inet_ntoa(fromp->sin_addr); 333 break; 334 } 335 if (!bcmp(hp->h_addr_list[0], 336 (caddr_t)&fromp->sin_addr, 337 sizeof(fromp->sin_addr))) { 338 hostname = hp->h_name; 339 break; 340 } 341 } 342 } 343 } else 344 errorhost = hostname = inet_ntoa(fromp->sin_addr); 345 346 #ifdef KERBEROS 347 if (use_kerberos) { 348 kdata = (AUTH_DAT *) authbuf; 349 ticket = (KTEXT) tickbuf; 350 authopts = 0L; 351 strcpy(instance, "*"); 352 version[VERSION_SIZE - 1] = '\0'; 353 #ifdef CRYPT 354 if (doencrypt) { 355 struct sockaddr_in local_addr; 356 rc = sizeof(local_addr); 357 if (getsockname(0, (struct sockaddr *)&local_addr, 358 &rc) < 0) { 359 syslog(LOG_ERR, "getsockname: %m"); 360 error("rlogind: getsockname: %m"); 361 exit(1); 362 } 363 authopts = KOPT_DO_MUTUAL; 364 rc = krb_recvauth(authopts, 0, ticket, 365 "rcmd", instance, &fromaddr, 366 &local_addr, kdata, "", schedule, 367 version); 368 des_set_key(kdata->session, schedule); 369 } else 370 #endif 371 rc = krb_recvauth(authopts, 0, ticket, "rcmd", 372 instance, &fromaddr, 373 (struct sockaddr_in *) 0, 374 kdata, "", (bit_64 *) 0, version); 375 if (rc != KSUCCESS) { 376 error("Kerberos authentication failure: %s\n", 377 krb_err_txt[rc]); 378 exit(1); 379 } 380 } else 381 #endif 382 getstr(remuser, sizeof(remuser), "remuser"); 383 384 getstr(locuser, sizeof(locuser), "locuser"); 385 getstr(cmdbuf, sizeof(cmdbuf), "command"); 386 setpwent(); 387 pwd = getpwnam(locuser); 388 if (pwd == NULL) { 389 syslog(LOG_INFO|LOG_AUTH, 390 "%s@%s as %s: unknown login. cmd='%.80s'", 391 remuser, hostname, locuser, cmdbuf); 392 if (errorstr == NULL) 393 errorstr = "Login incorrect.\n"; 394 goto fail; 395 } 396 if (chdir(pwd->pw_dir) < 0) { 397 (void) chdir("/"); 398 #ifdef notdef 399 syslog(LOG_INFO|LOG_AUTH, 400 "%s@%s as %s: no home directory. cmd='%.80s'", 401 remuser, hostname, locuser, cmdbuf); 402 error("No remote directory.\n"); 403 exit(1); 404 #endif 405 } 406 407 #ifdef KERBEROS 408 if (use_kerberos) { 409 if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0') { 410 if (kuserok(kdata, locuser) != 0) { 411 syslog(LOG_INFO|LOG_AUTH, 412 "Kerberos rsh denied to %s.%s@%s", 413 kdata->pname, kdata->pinst, kdata->prealm); 414 error("Permission denied.\n"); 415 exit(1); 416 } 417 } 418 } else 419 #endif 420 421 if (errorstr || 422 pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' && 423 iruserok(fromp->sin_addr.s_addr, pwd->pw_uid == 0, 424 remuser, locuser) < 0) { 425 if (__rcmd_errstr) 426 syslog(LOG_INFO|LOG_AUTH, 427 "%s@%s as %s: permission denied (%s). cmd='%.80s'", 428 remuser, hostname, locuser, __rcmd_errstr, 429 cmdbuf); 430 else 431 syslog(LOG_INFO|LOG_AUTH, 432 "%s@%s as %s: permission denied. cmd='%.80s'", 433 remuser, hostname, locuser, cmdbuf); 434 fail: 435 if (errorstr == NULL) 436 errorstr = "Permission denied.\n"; 437 error(errorstr, errorhost); 438 exit(1); 439 } 440 441 if (pwd->pw_uid && !access(_PATH_NOLOGIN, F_OK)) { 442 error("Logins currently disabled.\n"); 443 exit(1); 444 } 445 446 (void) write(STDERR_FILENO, "\0", 1); 447 sent_null = 1; 448 449 if (port) { 450 if (pipe(pv) < 0) { 451 error("Can't make pipe.\n"); 452 exit(1); 453 } 454 #ifdef CRYPT 455 #ifdef KERBEROS 456 if (doencrypt) { 457 if (pipe(pv1) < 0) { 458 error("Can't make 2nd pipe.\n"); 459 exit(1); 460 } 461 if (pipe(pv2) < 0) { 462 error("Can't make 3rd pipe.\n"); 463 exit(1); 464 } 465 } 466 #endif 467 #endif 468 pid = fork(); 469 if (pid == -1) { 470 error("Can't fork; try again.\n"); 471 exit(1); 472 } 473 if (pid) { 474 #ifdef CRYPT 475 #ifdef KERBEROS 476 if (doencrypt) { 477 static char msg[] = SECURE_MESSAGE; 478 (void) close(pv1[1]); 479 (void) close(pv2[1]); 480 des_write(s, msg, sizeof(msg) - 1); 481 482 } else 483 #endif 484 #endif 485 { 486 (void) close(0); 487 (void) close(1); 488 } 489 (void) close(2); 490 (void) close(pv[1]); 491 492 FD_ZERO(&readfrom); 493 FD_SET(s, &readfrom); 494 FD_SET(pv[0], &readfrom); 495 if (pv[0] > s) 496 nfd = pv[0]; 497 else 498 nfd = s; 499 #ifdef CRYPT 500 #ifdef KERBEROS 501 if (doencrypt) { 502 FD_ZERO(&writeto); 503 FD_SET(pv2[0], &writeto); 504 FD_SET(pv1[0], &readfrom); 505 506 nfd = MAX(nfd, pv2[0]); 507 nfd = MAX(nfd, pv1[0]); 508 } else 509 #endif 510 #endif 511 ioctl(pv[0], FIONBIO, (char *)&one); 512 513 /* should set s nbio! */ 514 nfd++; 515 do { 516 ready = readfrom; 517 #ifdef CRYPT 518 #ifdef KERBEROS 519 if (doencrypt) { 520 wready = writeto; 521 if (select(nfd, &ready, 522 &wready, (fd_set *) 0, 523 (struct timeval *) 0) < 0) 524 break; 525 } else 526 #endif 527 #endif 528 if (select(nfd, &ready, (fd_set *)0, 529 (fd_set *)0, (struct timeval *)0) < 0) 530 break; 531 if (FD_ISSET(s, &ready)) { 532 int ret; 533 #ifdef CRYPT 534 #ifdef KERBEROS 535 if (doencrypt) 536 ret = des_read(s, &sig, 1); 537 else 538 #endif 539 #endif 540 ret = read(s, &sig, 1); 541 if (ret <= 0) 542 FD_CLR(s, &readfrom); 543 else 544 killpg(pid, sig); 545 } 546 if (FD_ISSET(pv[0], &ready)) { 547 errno = 0; 548 cc = read(pv[0], buf, sizeof(buf)); 549 if (cc <= 0) { 550 shutdown(s, 1+1); 551 FD_CLR(pv[0], &readfrom); 552 } else { 553 #ifdef CRYPT 554 #ifdef KERBEROS 555 if (doencrypt) 556 (void) 557 des_write(s, buf, cc); 558 else 559 #endif 560 #endif 561 (void) 562 write(s, buf, cc); 563 } 564 } 565 #ifdef CRYPT 566 #ifdef KERBEROS 567 if (doencrypt && FD_ISSET(pv1[0], &ready)) { 568 errno = 0; 569 cc = read(pv1[0], buf, sizeof(buf)); 570 if (cc <= 0) { 571 shutdown(pv1[0], 1+1); 572 FD_CLR(pv1[0], &readfrom); 573 } else 574 (void) des_write(STDOUT_FILENO, 575 buf, cc); 576 } 577 578 if (doencrypt && FD_ISSET(pv2[0], &wready)) { 579 errno = 0; 580 cc = des_read(STDIN_FILENO, 581 buf, sizeof(buf)); 582 if (cc <= 0) { 583 shutdown(pv2[0], 1+1); 584 FD_CLR(pv2[0], &writeto); 585 } else 586 (void) write(pv2[0], buf, cc); 587 } 588 #endif 589 #endif 590 591 } while (FD_ISSET(s, &readfrom) || 592 #ifdef CRYPT 593 #ifdef KERBEROS 594 (doencrypt && FD_ISSET(pv1[0], &readfrom)) || 595 #endif 596 #endif 597 FD_ISSET(pv[0], &readfrom)); 598 exit(0); 599 } 600 setpgrp(0, getpid()); 601 (void) close(s); 602 (void) close(pv[0]); 603 #ifdef CRYPT 604 #ifdef KERBEROS 605 if (doencrypt) { 606 close(pv1[0]); close(pv2[0]); 607 dup2(pv1[1], 1); 608 dup2(pv2[1], 0); 609 close(pv1[1]); 610 close(pv2[1]); 611 } 612 #endif 613 #endif 614 dup2(pv[1], 2); 615 close(pv[1]); 616 } 617 if (*pwd->pw_shell == '\0') 618 pwd->pw_shell = _PATH_BSHELL; 619 #if BSD > 43 620 if (setlogin(pwd->pw_name) < 0) 621 syslog(LOG_ERR, "setlogin() failed: %m"); 622 #endif 623 (void) setgid((gid_t)pwd->pw_gid); 624 initgroups(pwd->pw_name, pwd->pw_gid); 625 (void) setuid((uid_t)pwd->pw_uid); 626 environ = envinit; 627 strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); 628 strcat(path, _PATH_DEFPATH); 629 strncat(shell, pwd->pw_shell, sizeof(shell)-7); 630 strncat(username, pwd->pw_name, sizeof(username)-6); 631 cp = rindex(pwd->pw_shell, '/'); 632 if (cp) 633 cp++; 634 else 635 cp = pwd->pw_shell; 636 endpwent(); 637 if (log_success || pwd->pw_uid == 0) { 638 #ifdef KERBEROS 639 if (use_kerberos) 640 syslog(LOG_INFO|LOG_AUTH, 641 "Kerberos shell from %s.%s@%s on %s as %s, cmd='%.80s'", 642 kdata->pname, kdata->pinst, kdata->prealm, 643 hostname, locuser, cmdbuf); 644 else 645 #endif 646 syslog(LOG_INFO|LOG_AUTH, "%s@%s as %s: cmd='%.80s'", 647 remuser, hostname, locuser, cmdbuf); 648 } 649 execl(pwd->pw_shell, cp, "-c", cmdbuf, 0); 650 perror(pwd->pw_shell); 651 exit(1); 652 } 653 654 /* 655 * Report error to client. Note: can't be used until second socket has 656 * connected to client, or older clients will hang waiting for that 657 * connection first. 658 */ 659 #if __STDC__ 660 #include <stdarg.h> 661 #else 662 #include <varargs.h> 663 #endif 664 665 void 666 #if __STDC__ 667 error(const char *fmt, ...) 668 #else 669 error(fmt, va_alist) 670 char *fmt; 671 va_dcl 672 #endif 673 { 674 va_list ap; 675 int len; 676 char *bp, buf[BUFSIZ]; 677 #if __STDC__ 678 va_start(ap, fmt); 679 #else 680 va_start(ap); 681 #endif 682 bp = buf; 683 if (sent_null == 0) { 684 *bp++ = 1; 685 len = 1; 686 } else 687 len = 0; 688 (void)vsnprintf(bp, sizeof(buf) - 1, fmt, ap); 689 (void)write(STDERR_FILENO, buf, len + strlen(bp)); 690 } 691 692 void 693 getstr(buf, cnt, err) 694 char *buf, *err; 695 int cnt; 696 { 697 char c; 698 699 do { 700 if (read(STDIN_FILENO, &c, 1) != 1) 701 exit(1); 702 *buf++ = c; 703 if (--cnt == 0) { 704 error("%s too long\n", err); 705 exit(1); 706 } 707 } while (c != 0); 708 } 709 710 /* 711 * Check whether host h is in our local domain, 712 * defined as sharing the last two components of the domain part, 713 * or the entire domain part if the local domain has only one component. 714 * If either name is unqualified (contains no '.'), 715 * assume that the host is local, as it will be 716 * interpreted as such. 717 */ 718 int 719 local_domain(h) 720 char *h; 721 { 722 char localhost[MAXHOSTNAMELEN]; 723 char *p1, *p2; 724 725 localhost[0] = 0; 726 (void) gethostname(localhost, sizeof(localhost)); 727 p1 = topdomain(localhost); 728 p2 = topdomain(h); 729 if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2)) 730 return (1); 731 return (0); 732 } 733 734 char * 735 topdomain(h) 736 char *h; 737 { 738 register char *p; 739 char *maybe = NULL; 740 int dots = 0; 741 742 for (p = h + strlen(h); p >= h; p--) { 743 if (*p == '.') { 744 if (++dots == 2) 745 return (p); 746 maybe = p; 747 } 748 } 749 return (maybe); 750 } 751 752 void 753 usage() 754 { 755 syslog(LOG_ERR, "usage: rshd [-%s]", OPTIONS); 756 } 757