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