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