1: /*
   2:  * Copyright (c) 1983 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #ifndef lint
   8: char copyright[] =
   9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
  10:  All rights reserved.\n";
  11: #endif not lint
  12: 
  13: #ifndef lint
  14: static char sccsid[] = "@(#)rshd.c	5.7 (Berkeley) 5/9/86";
  15: #endif not lint
  16: 
  17: /*
  18:  * remote shell server:
  19:  *	remuser\0
  20:  *	locuser\0
  21:  *	command\0
  22:  *	data
  23:  */
  24: #include <sys/ioctl.h>
  25: #include <sys/param.h>
  26: #include <sys/socket.h>
  27: #include <sys/time.h>
  28: 
  29: #include <netinet/in.h>
  30: 
  31: #include <arpa/inet.h>
  32: 
  33: #include <stdio.h>
  34: #include <errno.h>
  35: #include <pwd.h>
  36: #include <signal.h>
  37: #include <netdb.h>
  38: #include <syslog.h>
  39: 
  40: int errno;
  41: char    *index(), *rindex(), *strncat();
  42: /*VARARGS1*/
  43: int error();
  44: 
  45: /*ARGSUSED*/
  46: main(argc, argv)
  47:     int argc;
  48:     char **argv;
  49: {
  50:     struct linger linger;
  51:     int on = 1, fromlen;
  52:     struct sockaddr_in from;
  53: 
  54:     openlog("rsh", LOG_PID | LOG_ODELAY, LOG_DAEMON);
  55:     fromlen = sizeof (from);
  56:     if (getpeername(0, &from, &fromlen) < 0) {
  57:         fprintf(stderr, "%s: ", argv[0]);
  58:         perror("getpeername");
  59:         _exit(1);
  60:     }
  61:     if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
  62:         sizeof (on)) < 0)
  63:         syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
  64:     linger.l_onoff = 1;
  65:     linger.l_linger = 60;           /* XXX */
  66:     if (setsockopt(0, SOL_SOCKET, SO_LINGER, (char *)&linger,
  67:         sizeof (linger)) < 0)
  68:         syslog(LOG_WARNING, "setsockopt (SO_LINGER): %m");
  69:     doit(dup(0), &from);
  70: }
  71: 
  72: char    username[20] = "USER=";
  73: char    homedir[64] = "HOME=";
  74: char    shell[64] = "SHELL=";
  75: char    *envinit[] =
  76:         {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", username, 0};
  77: char    **environ;
  78: 
  79: doit(f, fromp)
  80:     int f;
  81:     struct sockaddr_in *fromp;
  82: {
  83:     char cmdbuf[NCARGS+1], *cp;
  84:     char locuser[16], remuser[16];
  85:     struct passwd *pwd;
  86:     int s;
  87:     struct hostent *hp;
  88:     char *hostname;
  89:     short port;
  90:     int pv[2], pid, ready, readfrom, cc;
  91:     char buf[BUFSIZ], sig;
  92:     int one = 1;
  93: 
  94:     (void) signal(SIGINT, SIG_DFL);
  95:     (void) signal(SIGQUIT, SIG_DFL);
  96:     (void) signal(SIGTERM, SIG_DFL);
  97: #ifdef DEBUG
  98:     { int t = open("/dev/tty", 2);
  99:       if (t >= 0) {
 100:         ioctl(t, TIOCNOTTY, (char *)0);
 101:         (void) close(t);
 102:       }
 103:     }
 104: #endif
 105:     fromp->sin_port = ntohs((u_short)fromp->sin_port);
 106:     if (fromp->sin_family != AF_INET ||
 107:         fromp->sin_port >= IPPORT_RESERVED) {
 108:         syslog(LOG_ERR, "malformed from address\n");
 109:         exit(1);
 110:     }
 111:     (void) alarm(60);
 112:     port = 0;
 113:     for (;;) {
 114:         char c;
 115:         if (read(f, &c, 1) != 1) {
 116:             syslog(LOG_ERR, "read: %m");
 117:             shutdown(f, 1+1);
 118:             exit(1);
 119:         }
 120:         if (c == 0)
 121:             break;
 122:         port = port * 10 + c - '0';
 123:     }
 124:     (void) alarm(0);
 125:     if (port != 0) {
 126:         int lport = IPPORT_RESERVED - 1;
 127:         s = rresvport(&lport);
 128:         if (s < 0) {
 129:             syslog(LOG_ERR, "can't get stderr port: %m");
 130:             exit(1);
 131:         }
 132:         if (port >= IPPORT_RESERVED) {
 133:             syslog(LOG_ERR, "2nd port not reserved\n");
 134:             exit(1);
 135:         }
 136:         fromp->sin_port = htons((u_short)port);
 137:         if (connect(s, fromp, sizeof (*fromp)) < 0) {
 138:             syslog(LOG_INFO, "connect second port: %m");
 139:             exit(1);
 140:         }
 141:     }
 142:     dup2(f, 0);
 143:     dup2(f, 1);
 144:     dup2(f, 2);
 145:     hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (struct in_addr),
 146:         fromp->sin_family);
 147:     if (hp)
 148:         hostname = hp->h_name;
 149:     else
 150:         hostname = inet_ntoa(fromp->sin_addr);
 151:     getstr(remuser, sizeof(remuser), "remuser");
 152:     getstr(locuser, sizeof(locuser), "locuser");
 153:     getstr(cmdbuf, sizeof(cmdbuf), "command");
 154:     setpwent();
 155:     pwd = getpwnam(locuser);
 156:     if (pwd == NULL) {
 157:         error("Login incorrect.\n");
 158:         exit(1);
 159:     }
 160:     endpwent();
 161:     if (chdir(pwd->pw_dir) < 0) {
 162:         (void) chdir("/");
 163: #ifdef notdef
 164:         error("No remote directory.\n");
 165:         exit(1);
 166: #endif
 167:     }
 168:     if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' &&
 169:         ruserok(hostname, pwd->pw_uid == 0, remuser, locuser) < 0) {
 170:         error("Permission denied.\n");
 171:         exit(1);
 172:     }
 173:     (void) write(2, "\0", 1);
 174:     if (port) {
 175:         if (pipe(pv) < 0) {
 176:             error("Can't make pipe.\n");
 177:             exit(1);
 178:         }
 179:         pid = fork();
 180:         if (pid == -1)  {
 181:             error("Try again.\n");
 182:             exit(1);
 183:         }
 184:         if (pid) {
 185:             (void) close(0); (void) close(1); (void) close(2);
 186:             (void) close(f); (void) close(pv[1]);
 187:             readfrom = (1<<s) | (1<<pv[0]);
 188:             ioctl(pv[1], FIONBIO, (char *)&one);
 189:             /* should set s nbio! */
 190:             do {
 191:                 ready = readfrom;
 192:                 if (select(16, &ready, (fd_set *)0,
 193:                     (fd_set *)0, (struct timeval *)0) < 0)
 194:                     break;
 195:                 if (ready & (1<<s)) {
 196:                     if (read(s, &sig, 1) <= 0)
 197:                         readfrom &= ~(1<<s);
 198:                     else
 199:                         killpg(pid, sig);
 200:                 }
 201:                 if (ready & (1<<pv[0])) {
 202:                     errno = 0;
 203:                     cc = read(pv[0], buf, sizeof (buf));
 204:                     if (cc <= 0) {
 205:                         shutdown(s, 1+1);
 206:                         readfrom &= ~(1<<pv[0]);
 207:                     } else
 208:                         (void) write(s, buf, cc);
 209:                 }
 210:             } while (readfrom);
 211:             exit(0);
 212:         }
 213:         setpgrp(0, getpid());
 214:         (void) close(s); (void) close(pv[0]);
 215:         dup2(pv[1], 2);
 216:     }
 217:     if (*pwd->pw_shell == '\0')
 218:         pwd->pw_shell = "/bin/sh";
 219:     (void) close(f);
 220:     (void) setgid((gid_t)pwd->pw_gid);
 221:     initgroups(pwd->pw_name, pwd->pw_gid);
 222:     (void) setuid((uid_t)pwd->pw_uid);
 223:     environ = envinit;
 224:     strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
 225:     strncat(shell, pwd->pw_shell, sizeof(shell)-7);
 226:     strncat(username, pwd->pw_name, sizeof(username)-6);
 227:     cp = rindex(pwd->pw_shell, '/');
 228:     if (cp)
 229:         cp++;
 230:     else
 231:         cp = pwd->pw_shell;
 232:     execl(pwd->pw_shell, cp, "-c", cmdbuf, 0);
 233:     perror(pwd->pw_shell);
 234:     exit(1);
 235: }
 236: 
 237: /*VARARGS1*/
 238: error(fmt, a1, a2, a3)
 239:     char *fmt;
 240:     int a1, a2, a3;
 241: {
 242:     char buf[BUFSIZ];
 243: 
 244:     buf[0] = 1;
 245:     (void) sprintf(buf+1, fmt, a1, a2, a3);
 246:     (void) write(2, buf, strlen(buf));
 247: }
 248: 
 249: getstr(buf, cnt, err)
 250:     char *buf;
 251:     int cnt;
 252:     char *err;
 253: {
 254:     char c;
 255: 
 256:     do {
 257:         if (read(0, &c, 1) != 1)
 258:             exit(1);
 259:         *buf++ = c;
 260:         if (--cnt == 0) {
 261:             error("%s too long\n", err);
 262:             exit(1);
 263:         }
 264:     } while (c != 0);
 265: }

Defined functions

doit defined in line 79; used 1 times
  • in line 69
error defined in line 238; used 7 times
getstr defined in line 249; used 3 times
main defined in line 46; never used

Defined variables

copyright defined in line 8; never used
envinit defined in line 75; used 1 times
environ defined in line 77; used 1 times
errno defined in line 40; used 68 times
homedir defined in line 73; used 3 times
sccsid defined in line 14; never used
shell defined in line 74; used 3 times
username defined in line 72; used 3 times
Last modified: 1986-05-09
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1480
Valid CSS Valid XHTML 1.0 Strict