rshd.c revision 41445
1/*- 2 * Copyright (c) 1988, 1989, 1992, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#ifndef lint 35static const char copyright[] = 36"@(#) Copyright (c) 1988, 1989, 1992, 1993, 1994\n\ 37 The Regents of the University of California. All rights reserved.\n"; 38#endif /* not lint */ 39 40#ifndef lint 41#if 0 42static const char sccsid[] = "@(#)rshd.c 8.2 (Berkeley) 4/6/94"; 43#endif 44static const char rcsid[] = 45 "$Id: rshd.c,v 1.21 1998/05/05 00:28:51 rnordier Exp $"; 46#endif /* not lint */ 47 48/* 49 * remote shell server: 50 * [port]\0 51 * remuser\0 52 * locuser\0 53 * command\0 54 * data 55 */ 56#include <sys/param.h> 57#include <sys/ioctl.h> 58#include <sys/time.h> 59#include <sys/socket.h> 60 61#include <netinet/in_systm.h> 62#include <netinet/in.h> 63#include <netinet/ip.h> 64#include <netinet/tcp.h> 65#include <arpa/inet.h> 66#include <netdb.h> 67 68#include <errno.h> 69#include <fcntl.h> 70#include <paths.h> 71#include <pwd.h> 72#include <signal.h> 73#include <stdio.h> 74#include <stdlib.h> 75#include <string.h> 76#include <syslog.h> 77#include <unistd.h> 78#ifdef LOGIN_CAP 79#include <login_cap.h> 80#endif 81 82int keepalive = 1; 83int check_all; 84int log_success; /* If TRUE, log all successful accesses */ 85int sent_null; 86int no_delay; 87 88void doit __P((struct sockaddr_in *)); 89void error __P((const char *, ...)); 90void getstr __P((char *, int, char *)); 91int local_domain __P((char *)); 92char *topdomain __P((char *)); 93void usage __P((void)); 94 95#ifdef KERBEROS 96#include <des.h> 97#include <krb.h> 98#define VERSION_SIZE 9 99#define SECURE_MESSAGE "This rsh session is using DES encryption for all transmissions.\r\n" 100#define OPTIONS "alnkvxDL" 101char authbuf[sizeof(AUTH_DAT)]; 102char tickbuf[sizeof(KTEXT_ST)]; 103int doencrypt, use_kerberos, vacuous; 104Key_schedule schedule; 105#else 106#define OPTIONS "alnDL" 107#endif 108 109int 110main(argc, argv) 111 int argc; 112 char *argv[]; 113{ 114 extern int __check_rhosts_file; 115 struct linger linger; 116 int ch, on = 1, fromlen; 117 struct sockaddr_in from; 118 119 openlog("rshd", LOG_PID | LOG_ODELAY, LOG_DAEMON); 120 121 opterr = 0; 122 while ((ch = getopt(argc, argv, OPTIONS)) != -1) 123 switch (ch) { 124 case 'a': 125 check_all = 1; 126 break; 127 case 'l': 128 __check_rhosts_file = 0; 129 break; 130 case 'n': 131 keepalive = 0; 132 break; 133#ifdef KERBEROS 134 case 'k': 135 use_kerberos = 1; 136 break; 137 138 case 'v': 139 vacuous = 1; 140 break; 141 142#ifdef CRYPT 143 case 'x': 144 doencrypt = 1; 145 break; 146#endif 147#endif 148 case 'D': 149 no_delay = 1; 150 break; 151 case 'L': 152 log_success = 1; 153 break; 154 case '?': 155 default: 156 usage(); 157 break; 158 } 159 160 argc -= optind; 161 argv += optind; 162 163#ifdef KERBEROS 164 if (use_kerberos && vacuous) { 165 syslog(LOG_ERR, "only one of -k and -v allowed"); 166 exit(2); 167 } 168#ifdef CRYPT 169 if (doencrypt && !use_kerberos) { 170 syslog(LOG_ERR, "-k is required for -x"); 171 exit(2); 172 } 173#endif 174#endif 175 176 fromlen = sizeof (from); 177 if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { 178 syslog(LOG_ERR, "getpeername: %m"); 179 exit(1); 180 } 181 if (keepalive && 182 setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, 183 sizeof(on)) < 0) 184 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 185 linger.l_onoff = 1; 186 linger.l_linger = 60; /* XXX */ 187 if (setsockopt(0, SOL_SOCKET, SO_LINGER, (char *)&linger, 188 sizeof (linger)) < 0) 189 syslog(LOG_WARNING, "setsockopt (SO_LINGER): %m"); 190 if (no_delay && 191 setsockopt(0, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) 192 syslog(LOG_WARNING, "setsockopt (TCP_NODELAY): %m"); 193 doit(&from); 194 /* NOTREACHED */ 195 return(0); 196} 197 198char username[20] = "USER="; 199char homedir[64] = "HOME="; 200char shell[64] = "SHELL="; 201char path[100] = "PATH="; 202char *envinit[] = 203 {homedir, shell, path, username, 0}; 204char **environ; 205 206void 207doit(fromp) 208 struct sockaddr_in *fromp; 209{ 210 extern char *__rcmd_errstr; /* syslog hook from libc/net/rcmd.c. */ 211 struct hostent *hp; 212 struct passwd *pwd; 213 u_short port; 214 fd_set ready, readfrom; 215 int cc, nfd, pv[2], pid, s; 216 int one = 1; 217 char *hostname, *errorstr, *errorhost; 218 char *cp, sig, buf[BUFSIZ]; 219 char cmdbuf[NCARGS+1], locuser[16], remuser[16]; 220 char remotehost[2 * MAXHOSTNAMELEN + 1]; 221 char fromhost[2 * MAXHOSTNAMELEN + 1]; 222#ifdef LOGIN_CAP 223 login_cap_t *lc; 224#endif 225 226#ifdef KERBEROS 227 AUTH_DAT *kdata = (AUTH_DAT *) NULL; 228 KTEXT ticket = (KTEXT) NULL; 229 char instance[INST_SZ], version[VERSION_SIZE]; 230 struct sockaddr_in fromaddr; 231 int rc; 232 long authopts; 233 int pv1[2], pv2[2]; 234 fd_set wready, writeto; 235 236 fromaddr = *fromp; 237#endif 238 239 (void) signal(SIGINT, SIG_DFL); 240 (void) signal(SIGQUIT, SIG_DFL); 241 (void) signal(SIGTERM, SIG_DFL); 242#ifdef DEBUG 243 { int t = open(_PATH_TTY, 2); 244 if (t >= 0) { 245 ioctl(t, TIOCNOTTY, (char *)0); 246 (void) close(t); 247 } 248 } 249#endif 250 fromp->sin_port = ntohs((u_short)fromp->sin_port); 251 if (fromp->sin_family != AF_INET) { 252 syslog(LOG_ERR, "malformed \"from\" address (af %d)", 253 fromp->sin_family); 254 exit(1); 255 } 256#ifdef IP_OPTIONS 257 { 258 u_char optbuf[BUFSIZ/3]; 259 int optsize = sizeof(optbuf), ipproto, i; 260 struct protoent *ip; 261 262 if ((ip = getprotobyname("ip")) != NULL) 263 ipproto = ip->p_proto; 264 else 265 ipproto = IPPROTO_IP; 266 if (!getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, &optsize) && 267 optsize != 0) { 268 for (i = 0; i < optsize; ) { 269 u_char c = optbuf[i]; 270 if (c == IPOPT_LSRR || c == IPOPT_SSRR) { 271 syslog(LOG_NOTICE, 272 "connection refused from %s with IP option %s", 273 inet_ntoa(fromp->sin_addr), 274 c == IPOPT_LSRR ? "LSRR" : "SSRR"); 275 exit(1); 276 } 277 if (c == IPOPT_EOL) 278 break; 279 i += (c == IPOPT_NOP) ? 1 : optbuf[i+1]; 280 } 281 } 282 } 283#endif 284 285#ifdef KERBEROS 286 if (!use_kerberos) 287#endif 288 if (fromp->sin_port >= IPPORT_RESERVED || 289 fromp->sin_port < IPPORT_RESERVED/2) { 290 syslog(LOG_NOTICE|LOG_AUTH, 291 "connection from %s on illegal port %u", 292 inet_ntoa(fromp->sin_addr), 293 fromp->sin_port); 294 exit(1); 295 } 296 297 (void) alarm(60); 298 port = 0; 299 for (;;) { 300 char c; 301 if ((cc = read(STDIN_FILENO, &c, 1)) != 1) { 302 if (cc < 0) 303 syslog(LOG_NOTICE, "read: %m"); 304 shutdown(0, 1+1); 305 exit(1); 306 } 307 if (c== 0) 308 break; 309 port = port * 10 + c - '0'; 310 } 311 312 (void) alarm(0); 313 if (port != 0) { 314 int lport = IPPORT_RESERVED - 1; 315 s = rresvport(&lport); 316 if (s < 0) { 317 syslog(LOG_ERR, "can't get stderr port: %m"); 318 exit(1); 319 } 320#ifdef KERBEROS 321 if (!use_kerberos) 322#endif 323 if (port >= IPPORT_RESERVED || 324 port < IPPORT_RESERVED/2) { 325 syslog(LOG_NOTICE|LOG_AUTH, 326 "2nd socket from %s on unreserved port %u", 327 inet_ntoa(fromp->sin_addr), 328 port); 329 exit(1); 330 } 331 fromp->sin_port = htons(port); 332 if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0) { 333 syslog(LOG_INFO, "connect second port %d: %m", port); 334 exit(1); 335 } 336 } 337 338#ifdef KERBEROS 339 if (vacuous) { 340 error("rshd: remote host requires Kerberos authentication\n"); 341 exit(1); 342 } 343#endif 344 345#ifdef notdef 346 /* from inetd, socket is already on 0, 1, 2 */ 347 dup2(f, 0); 348 dup2(f, 1); 349 dup2(f, 2); 350#endif 351 errorstr = NULL; 352 hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (struct in_addr), 353 fromp->sin_family); 354 if (hp) { 355 /* 356 * If name returned by gethostbyaddr is in our domain, 357 * attempt to verify that we haven't been fooled by someone 358 * in a remote net; look up the name and check that this 359 * address corresponds to the name. 360 */ 361 strncpy(fromhost, hp->h_name, sizeof(fromhost) - 1); 362 fromhost[sizeof(fromhost) - 1] = 0; 363 hostname = fromhost; 364#ifdef KERBEROS 365 if (!use_kerberos) 366#endif 367 if (check_all || local_domain(hp->h_name)) { 368 strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1); 369 remotehost[sizeof(remotehost) - 1] = 0; 370 errorhost = remotehost; 371 hp = gethostbyname(remotehost); 372 if (hp == NULL) { 373 syslog(LOG_INFO, 374 "couldn't look up address for %s", 375 remotehost); 376 errorstr = 377 "Couldn't look up address for your host (%s)\n"; 378 strncpy(fromhost, inet_ntoa(fromp->sin_addr), 379 sizeof(fromhost) - 1); 380 fromhost[sizeof(fromhost) - 1] = 0; 381 hostname = fromhost; 382 } else for (; ; hp->h_addr_list++) { 383 if (hp->h_addr_list[0] == NULL) { 384 syslog(LOG_NOTICE, 385 "host addr %s not listed for host %s", 386 inet_ntoa(fromp->sin_addr), 387 hp->h_name); 388 errorstr = 389 "Host address mismatch for %s\n"; 390 strncpy(fromhost, inet_ntoa(fromp->sin_addr), 391 sizeof(fromhost) - 1); 392 fromhost[sizeof(fromhost) - 1] = 0; 393 hostname = fromhost; 394 break; 395 } 396 if (!bcmp(hp->h_addr_list[0], 397 (caddr_t)&fromp->sin_addr, 398 sizeof(fromp->sin_addr))) { 399 hostname = remotehost; 400 break; 401 } 402 } 403 } 404 } else { 405 strncpy(fromhost, inet_ntoa(fromp->sin_addr), 406 sizeof(fromhost) - 1); 407 fromhost[sizeof(fromhost) - 1] = 0; 408 errorhost = hostname = fromhost; 409 } 410 411#ifdef KERBEROS 412 if (use_kerberos) { 413 kdata = (AUTH_DAT *) authbuf; 414 ticket = (KTEXT) tickbuf; 415 authopts = 0L; 416 strcpy(instance, "*"); 417 version[VERSION_SIZE - 1] = '\0'; 418#ifdef CRYPT 419 if (doencrypt) { 420 struct sockaddr_in local_addr; 421 rc = sizeof(local_addr); 422 if (getsockname(0, (struct sockaddr *)&local_addr, 423 &rc) < 0) { 424 syslog(LOG_ERR, "getsockname: %m"); 425 error("rlogind: getsockname: %m"); 426 exit(1); 427 } 428 authopts = KOPT_DO_MUTUAL; 429 rc = krb_recvauth(authopts, 0, ticket, 430 "rcmd", instance, &fromaddr, 431 &local_addr, kdata, "", schedule, 432 version); 433 des_set_key(&kdata->session, schedule); 434 } else 435#endif 436 rc = krb_recvauth(authopts, 0, ticket, "rcmd", 437 instance, &fromaddr, 438 (struct sockaddr_in *) 0, 439 kdata, "", NULL, version); 440 if (rc != KSUCCESS) { 441 error("Kerberos authentication failure: %s\n", 442 krb_err_txt[rc]); 443 exit(1); 444 } 445 } else 446#endif 447 getstr(remuser, sizeof(remuser), "remuser"); 448 449 getstr(locuser, sizeof(locuser), "locuser"); 450 getstr(cmdbuf, sizeof(cmdbuf), "command"); 451 setpwent(); 452 pwd = getpwnam(locuser); 453 if (pwd == NULL) { 454 syslog(LOG_INFO|LOG_AUTH, 455 "%s@%s as %s: unknown login. cmd='%.80s'", 456 remuser, hostname, locuser, cmdbuf); 457 if (errorstr == NULL) 458 errorstr = "Login incorrect.\n"; 459 goto fail; 460 } 461#ifdef LOGIN_CAP 462 lc = login_getpwclass(pwd); 463#endif 464 if (chdir(pwd->pw_dir) < 0) { 465#ifdef LOGIN_CAP 466 if (chdir("/") < 0 || 467 login_getcapbool(lc, "requirehome", !!pwd->pw_uid)) { 468 syslog(LOG_INFO|LOG_AUTH, 469 "%s@%s as %s: no home directory. cmd='%.80s'", 470 remuser, hostname, locuser, cmdbuf); 471 error("No remote home directory.\n"); 472 exit(0); 473 } 474#else 475 (void) chdir("/"); 476#ifdef notdef 477 syslog(LOG_INFO|LOG_AUTH, 478 "%s@%s as %s: no home directory. cmd='%.80s'", 479 remuser, hostname, locuser, cmdbuf); 480 error("No remote directory.\n"); 481 exit(1); 482#endif 483#endif 484 pwd->pw_dir = "/"; 485 } 486 487#ifdef KERBEROS 488 if (use_kerberos) { 489 if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0') { 490 if (kuserok(kdata, locuser) != 0) { 491 syslog(LOG_INFO|LOG_AUTH, 492 "Kerberos rsh denied to %s.%s@%s", 493 kdata->pname, kdata->pinst, kdata->prealm); 494 error("Login incorrect.\n"); 495 exit(1); 496 } 497 } 498 } else 499#endif 500 501 if (errorstr || 502 (pwd->pw_expire && time(NULL) >= pwd->pw_expire) || 503 (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' && 504 iruserok(fromp->sin_addr.s_addr, pwd->pw_uid == 0, 505 remuser, locuser) < 0)) { 506 if (__rcmd_errstr) 507 syslog(LOG_INFO|LOG_AUTH, 508 "%s@%s as %s: permission denied (%s). cmd='%.80s'", 509 remuser, hostname, locuser, __rcmd_errstr, 510 cmdbuf); 511 else 512 syslog(LOG_INFO|LOG_AUTH, 513 "%s@%s as %s: permission denied. cmd='%.80s'", 514 remuser, hostname, locuser, cmdbuf); 515fail: 516 if (errorstr == NULL) 517 errorstr = "Login incorrect.\n"; 518 error(errorstr, errorhost); 519 exit(1); 520 } 521 522 if (pwd->pw_uid && !access(_PATH_NOLOGIN, F_OK)) { 523 error("Logins currently disabled.\n"); 524 exit(1); 525 } 526#ifdef LOGIN_CAP 527 if (lc != NULL) { 528 char remote_ip[MAXHOSTNAMELEN]; 529 530 strncpy(remote_ip, inet_ntoa(fromp->sin_addr), 531 sizeof(remote_ip) - 1); 532 remote_ip[sizeof(remote_ip) - 1] = 0; 533 if (!auth_hostok(lc, fromhost, remote_ip)) { 534 syslog(LOG_INFO|LOG_AUTH, 535 "%s@%s as %s: permission denied (%s). cmd='%.80s'", 536 remuser, hostname, locuser, __rcmd_errstr, 537 cmdbuf); 538 error("Login incorrect.\n"); 539 exit(1); 540 } 541 if (!auth_timeok(lc, time(NULL))) { 542 error("Logins not available right now\n"); 543 exit(1); 544 } 545 } 546#endif /* !LOGIN_CAP */ 547#if BSD > 43 548 /* before fork, while we're session leader */ 549 if (setlogin(pwd->pw_name) < 0) 550 syslog(LOG_ERR, "setlogin() failed: %m"); 551#endif 552 553 (void) write(STDERR_FILENO, "\0", 1); 554 sent_null = 1; 555 556 if (port) { 557 if (pipe(pv) < 0) { 558 error("Can't make pipe.\n"); 559 exit(1); 560 } 561#ifdef CRYPT 562#ifdef KERBEROS 563 if (doencrypt) { 564 if (pipe(pv1) < 0) { 565 error("Can't make 2nd pipe.\n"); 566 exit(1); 567 } 568 if (pipe(pv2) < 0) { 569 error("Can't make 3rd pipe.\n"); 570 exit(1); 571 } 572 } 573#endif 574#endif 575 pid = fork(); 576 if (pid == -1) { 577 error("Can't fork; try again.\n"); 578 exit(1); 579 } 580 if (pid) { 581#ifdef CRYPT 582#ifdef KERBEROS 583 if (doencrypt) { 584 static char msg[] = SECURE_MESSAGE; 585 (void) close(pv1[1]); 586 (void) close(pv2[1]); 587 des_enc_write(s, msg, sizeof(msg) - 1, 588 schedule, &kdata->session); 589 590 } else 591#endif 592#endif 593 { 594 (void) close(0); 595 (void) close(1); 596 } 597 (void) close(2); 598 (void) close(pv[1]); 599 600 FD_ZERO(&readfrom); 601 FD_SET(s, &readfrom); 602 FD_SET(pv[0], &readfrom); 603 if (pv[0] > s) 604 nfd = pv[0]; 605 else 606 nfd = s; 607#ifdef CRYPT 608#ifdef KERBEROS 609 if (doencrypt) { 610 FD_ZERO(&writeto); 611 FD_SET(pv2[0], &writeto); 612 FD_SET(pv1[0], &readfrom); 613 614 nfd = MAX(nfd, pv2[0]); 615 nfd = MAX(nfd, pv1[0]); 616 } else 617#endif 618#endif 619 ioctl(pv[0], FIONBIO, (char *)&one); 620 621 /* should set s nbio! */ 622 nfd++; 623 do { 624 ready = readfrom; 625#ifdef CRYPT 626#ifdef KERBEROS 627 if (doencrypt) { 628 wready = writeto; 629 if (select(nfd, &ready, 630 &wready, (fd_set *) 0, 631 (struct timeval *) 0) < 0) 632 break; 633 } else 634#endif 635#endif 636 if (select(nfd, &ready, (fd_set *)0, 637 (fd_set *)0, (struct timeval *)0) < 0) 638 break; 639 if (FD_ISSET(s, &ready)) { 640 int ret; 641#ifdef CRYPT 642#ifdef KERBEROS 643 if (doencrypt) 644 ret = des_enc_read(s, &sig, 1, 645 schedule, &kdata->session); 646 else 647#endif 648#endif 649 ret = read(s, &sig, 1); 650 if (ret <= 0) 651 FD_CLR(s, &readfrom); 652 else 653 killpg(pid, sig); 654 } 655 if (FD_ISSET(pv[0], &ready)) { 656 errno = 0; 657 cc = read(pv[0], buf, sizeof(buf)); 658 if (cc <= 0) { 659 shutdown(s, 1+1); 660 FD_CLR(pv[0], &readfrom); 661 } else { 662#ifdef CRYPT 663#ifdef KERBEROS 664 if (doencrypt) 665 (void) 666 des_enc_write(s, buf, cc, 667 schedule, &kdata->session); 668 else 669#endif 670#endif 671 (void) 672 write(s, buf, cc); 673 } 674 } 675#ifdef CRYPT 676#ifdef KERBEROS 677 if (doencrypt && FD_ISSET(pv1[0], &ready)) { 678 errno = 0; 679 cc = read(pv1[0], buf, sizeof(buf)); 680 if (cc <= 0) { 681 shutdown(pv1[0], 1+1); 682 FD_CLR(pv1[0], &readfrom); 683 } else 684 (void) des_enc_write(STDOUT_FILENO, 685 buf, cc, 686 schedule, &kdata->session); 687 } 688 689 if (doencrypt && FD_ISSET(pv2[0], &wready)) { 690 errno = 0; 691 cc = des_enc_read(STDIN_FILENO, 692 buf, sizeof(buf), 693 schedule, &kdata->session); 694 if (cc <= 0) { 695 shutdown(pv2[0], 1+1); 696 FD_CLR(pv2[0], &writeto); 697 } else 698 (void) write(pv2[0], buf, cc); 699 } 700#endif 701#endif 702 703 } while (FD_ISSET(s, &readfrom) || 704#ifdef CRYPT 705#ifdef KERBEROS 706 (doencrypt && FD_ISSET(pv1[0], &readfrom)) || 707#endif 708#endif 709 FD_ISSET(pv[0], &readfrom)); 710 exit(0); 711 } 712 setpgrp(0, getpid()); 713 (void) close(s); 714 (void) close(pv[0]); 715#ifdef CRYPT 716#ifdef KERBEROS 717 if (doencrypt) { 718 close(pv1[0]); close(pv2[0]); 719 dup2(pv1[1], 1); 720 dup2(pv2[1], 0); 721 close(pv1[1]); 722 close(pv2[1]); 723 } 724#endif 725#endif 726 dup2(pv[1], 2); 727 close(pv[1]); 728 } 729 if (*pwd->pw_shell == '\0') 730 pwd->pw_shell = _PATH_BSHELL; 731 environ = envinit; 732 strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); 733 strcat(path, _PATH_DEFPATH); 734 strncat(shell, pwd->pw_shell, sizeof(shell)-7); 735 strncat(username, pwd->pw_name, sizeof(username)-6); 736 cp = strrchr(pwd->pw_shell, '/'); 737 if (cp) 738 cp++; 739 else 740 cp = pwd->pw_shell; 741#ifdef LOGIN_CAP 742 if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETALL) != 0) { 743 syslog(LOG_ERR, "setusercontext: %m"); 744 exit(1); 745 } 746 login_close(lc); 747#else 748 (void) setgid((gid_t)pwd->pw_gid); 749 initgroups(pwd->pw_name, pwd->pw_gid); 750 (void) setuid((uid_t)pwd->pw_uid); 751#endif 752 endpwent(); 753 if (log_success || pwd->pw_uid == 0) { 754#ifdef KERBEROS 755 if (use_kerberos) 756 syslog(LOG_INFO|LOG_AUTH, 757 "Kerberos shell from %s.%s@%s on %s as %s, cmd='%.80s'", 758 kdata->pname, kdata->pinst, kdata->prealm, 759 hostname, locuser, cmdbuf); 760 else 761#endif 762 syslog(LOG_INFO|LOG_AUTH, "%s@%s as %s: cmd='%.80s'", 763 remuser, hostname, locuser, cmdbuf); 764 } 765 execl(pwd->pw_shell, cp, "-c", cmdbuf, 0); 766 perror(pwd->pw_shell); 767 exit(1); 768} 769 770/* 771 * Report error to client. Note: can't be used until second socket has 772 * connected to client, or older clients will hang waiting for that 773 * connection first. 774 */ 775#if __STDC__ 776#include <stdarg.h> 777#else 778#include <varargs.h> 779#endif 780 781void 782#if __STDC__ 783error(const char *fmt, ...) 784#else 785error(fmt, va_alist) 786 char *fmt; 787 va_dcl 788#endif 789{ 790 va_list ap; 791 int len; 792 char *bp, buf[BUFSIZ]; 793#if __STDC__ 794 va_start(ap, fmt); 795#else 796 va_start(ap); 797#endif 798 bp = buf; 799 if (sent_null == 0) { 800 *bp++ = 1; 801 len = 1; 802 } else 803 len = 0; 804 (void)vsnprintf(bp, sizeof(buf) - 1, fmt, ap); 805 (void)write(STDERR_FILENO, buf, len + strlen(bp)); 806} 807 808void 809getstr(buf, cnt, err) 810 char *buf, *err; 811 int cnt; 812{ 813 char c; 814 815 do { 816 if (read(STDIN_FILENO, &c, 1) != 1) 817 exit(1); 818 *buf++ = c; 819 if (--cnt == 0) { 820 error("%s too long\n", err); 821 exit(1); 822 } 823 } while (c != 0); 824} 825 826/* 827 * Check whether host h is in our local domain, 828 * defined as sharing the last two components of the domain part, 829 * or the entire domain part if the local domain has only one component. 830 * If either name is unqualified (contains no '.'), 831 * assume that the host is local, as it will be 832 * interpreted as such. 833 */ 834int 835local_domain(h) 836 char *h; 837{ 838 char localhost[MAXHOSTNAMELEN]; 839 char *p1, *p2; 840 841 localhost[0] = 0; 842 (void) gethostname(localhost, sizeof(localhost)); 843 p1 = topdomain(localhost); 844 p2 = topdomain(h); 845 if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2)) 846 return (1); 847 return (0); 848} 849 850char * 851topdomain(h) 852 char *h; 853{ 854 char *p, *maybe = NULL; 855 int dots = 0; 856 857 for (p = h + strlen(h); p >= h; p--) { 858 if (*p == '.') { 859 if (++dots == 2) 860 return (p); 861 maybe = p; 862 } 863 } 864 return (maybe); 865} 866 867void 868usage() 869{ 870 871 syslog(LOG_ERR, "usage: rshd [-%s]", OPTIONS); 872 exit(2); 873} 874