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