Annotation of 42BSD/etc/rshd.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char sccsid[] = "@(#)rshd.c     4.17 (Berkeley) 83/07/02";
                      3: #endif
                      4: 
                      5: #include <sys/ioctl.h>
                      6: #include <sys/param.h>
                      7: #include <sys/socket.h>
                      8: #include <sys/wait.h>
                      9: 
                     10: #include <netinet/in.h>
                     11: 
                     12: #include <stdio.h>
                     13: #include <errno.h>
                     14: #include <pwd.h>
                     15: #include <signal.h>
                     16: #include <netdb.h>
                     17: 
                     18: int    errno;
                     19: int    reapchild();
                     20: struct sockaddr_in sin = { AF_INET };
                     21: struct passwd *getpwnam();
                     22: char   *index(), *rindex(), *sprintf();
                     23: int    options;
                     24: /* VARARGS 1 */
                     25: int    error();
                     26: /*
                     27:  * remote shell server:
                     28:  *     remuser\0
                     29:  *     locuser\0
                     30:  *     command\0
                     31:  *     data
                     32:  */
                     33: main(argc, argv)
                     34:        int argc;
                     35:        char **argv;
                     36: {
                     37:        int f, linger;
                     38:        struct sockaddr_in from;
                     39:        struct servent *sp;
                     40: 
                     41:        sp = getservbyname("shell", "tcp");
                     42:        if (sp == 0) {
                     43:                fprintf(stderr, "rshd: tcp/shell: unknown service\n");
                     44:                exit(1);
                     45:        }
                     46: #ifndef DEBUG
                     47:        if (fork())
                     48:                exit(0);
                     49:        for (f = 0; f < 10; f++)
                     50:                (void) close(f);
                     51:        (void) open("/", 0);
                     52:        (void) dup2(0, 1);
                     53:        (void) dup2(0, 2);
                     54:        { int t = open("/dev/tty", 2);
                     55:          if (t >= 0) {
                     56:                ioctl(t, TIOCNOTTY, (char *)0);
                     57:                (void) close(t);
                     58:          }
                     59:        }
                     60: #endif
                     61:        sin.sin_port = sp->s_port;
                     62:        argc--, argv++;
                     63:        if (argc > 0 && !strcmp(argv[0], "-d")) {
                     64:                options |= SO_DEBUG;
                     65:                argc--, argv++;
                     66:        }
                     67:        if (argc > 0) {
                     68:                int port = atoi(argv[0]);
                     69: 
                     70:                if (port < 0) {
                     71:                        fprintf(stderr, "%s: bad port #\n", argv[0]);
                     72:                        exit(1);
                     73:                }
                     74:                sin.sin_port = htons((u_short)port);
                     75:                argc--, argv++;
                     76:        }
                     77:        f = socket(AF_INET, SOCK_STREAM, 0, 0);
                     78:        if (f < 0) {
                     79:                perror("rshd: socket");
                     80:                exit(1);
                     81:        }
                     82:        if (options & SO_DEBUG && setsockopt(f, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
                     83:                perror("rshd: setsockopt (SO_DEBUG)");
                     84:        if (setsockopt(f, SOL_SOCKET, SO_KEEPALIVE, 0, 0) < 0)
                     85:                perror("rshd: setsockopt (SO_KEEPALIVE)");
                     86:        linger = 60;                    /* XXX */
                     87:        if (setsockopt(f, SOL_SOCKET, SO_LINGER, &linger, 0) < 0)
                     88:                perror("rshd: setsockopt (SO_LINGER)");
                     89:        if (bind(f, (caddr_t)&sin, sizeof (sin), 0) < 0) {
                     90:                perror("rshd: bind");
                     91:                exit(1);
                     92:        }
                     93:        signal(SIGCHLD, reapchild);
                     94:        listen(f, 10);
                     95:        for (;;) {
                     96:                int g, len = sizeof (from);
                     97: 
                     98:                g = accept(f, &from, &len, 0);
                     99:                if (g < 0) {
                    100:                        if (errno == EINTR)
                    101:                                continue;
                    102:                        perror("rshd: accept");
                    103:                        continue;
                    104:                }
                    105:                if (fork() == 0) {
                    106:                        signal(SIGCHLD, SIG_IGN);
                    107:                        close(f);
                    108:                        doit(g, &from);
                    109:                }
                    110:                close(g);
                    111:        }
                    112: }
                    113: 
                    114: reapchild()
                    115: {
                    116:        union wait status;
                    117: 
                    118:        while (wait3(&status, WNOHANG, 0) > 0)
                    119:                ;
                    120: }
                    121: 
                    122: char   username[20] = "USER=";
                    123: char   homedir[64] = "HOME=";
                    124: char   shell[64] = "SHELL=";
                    125: char   *envinit[] =
                    126:            {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", username, 0};
                    127: char   **environ;
                    128: 
                    129: doit(f, fromp)
                    130:        int f;
                    131:        struct sockaddr_in *fromp;
                    132: {
                    133:        char cmdbuf[NCARGS+1], *cp;
                    134:        char locuser[16], remuser[16];
                    135:        struct passwd *pwd;
                    136:        int s, backoff;
                    137:        struct hostent *hp;
                    138:        short port;
                    139:        int pv[2], pid, ready, readfrom, cc;
                    140:        char buf[BUFSIZ], sig;
                    141:        int one = 1;
                    142: 
                    143:        (void) signal(SIGINT, SIG_DFL);
                    144:        (void) signal(SIGQUIT, SIG_DFL);
                    145:        (void) signal(SIGTERM, SIG_DFL);
                    146: #ifdef DEBUG
                    147:        { int t = open("/dev/tty", 2);
                    148:          if (t >= 0) {
                    149:                ioctl(t, TIOCNOTTY, (char *)0);
                    150:                (void) close(t);
                    151:          }
                    152:        }
                    153: #endif
                    154:        fromp->sin_port = ntohs((u_short)fromp->sin_port);
                    155:        if (fromp->sin_family != AF_INET ||
                    156:            fromp->sin_port >= IPPORT_RESERVED) {
                    157:                fprintf(stderr, "rshd: malformed from address\n");
                    158:                exit(1);
                    159:        }
                    160:        (void) alarm(60);
                    161:        port = 0;
                    162:        for (;;) {
                    163:                char c;
                    164:                if (read(f, &c, 1) != 1) {
                    165:                        perror("rshd: read");
                    166:                        shutdown(f, 1+1);
                    167:                        exit(1);
                    168:                }
                    169:                if (c == 0)
                    170:                        break;
                    171:                port = port * 10 + c - '0';
                    172:        }
                    173:        (void) alarm(0);
                    174:        if (port != 0) {
                    175:                int lport = IPPORT_RESERVED - 1, retryshift;
                    176:                s = rresvport(&lport);
                    177:                if (s < 0) {
                    178:                        perror("rshd: can't get stderr port");
                    179:                        exit(1);
                    180:                }
                    181:                if (port >= IPPORT_RESERVED) {
                    182:                        fprintf(stderr, "rshd: 2nd port not reserved\n");
                    183:                        exit(1);
                    184:                }
                    185:                fromp->sin_port = htons((u_short)port);
                    186:                if (connect(s, fromp, sizeof (*fromp), 0) < 0) {
                    187:                        perror("rshd: connect");
                    188:                        exit(1);
                    189:                }
                    190:        }
                    191:        dup2(f, 0);
                    192:        dup2(f, 1);
                    193:        dup2(f, 2);
                    194:        hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr),
                    195:                fromp->sin_family);
                    196:        if (hp == 0) {
                    197:                error("Host name for your address unknown\n");
                    198:                exit(1);
                    199:        }
                    200:        getstr(remuser, sizeof(remuser), "remuser");
                    201:        getstr(locuser, sizeof(locuser), "locuser");
                    202:        getstr(cmdbuf, sizeof(cmdbuf), "command");
                    203:        setpwent();
                    204:        pwd = getpwnam(locuser);
                    205:        if (pwd == NULL) {
                    206:                error("Login incorrect.\n");
                    207:                exit(1);
                    208:        }
                    209:        endpwent();
                    210:        if (chdir(pwd->pw_dir) < 0) {
                    211:                error("No remote directory.\n");
                    212:                exit(1);
                    213:        }
                    214:        if (ruserok(hp->h_name, pwd->pw_uid == 0, remuser, locuser) < 0) {
                    215:                error("Permission denied.\n");
                    216:                exit(1);
                    217:        }
                    218:        (void) write(2, "\0", 1);
                    219:        if (port) {
                    220:                if (pipe(pv) < 0) {
                    221:                        error("Can't make pipe.\n");
                    222:                        exit(1);
                    223:                }
                    224:                pid = fork();
                    225:                if (pid == -1)  {
                    226:                        error("Try again.\n");
                    227:                        exit(1);
                    228:                }
                    229:                if (pid) {
                    230:                        (void) close(0); (void) close(1); (void) close(2);
                    231:                        (void) close(f); (void) close(pv[1]);
                    232:                        readfrom = (1<<s) | (1<<pv[0]);
                    233:                        ioctl(pv[1], FIONBIO, (char *)&one);
                    234:                        /* should set s nbio! */
                    235:                        do {
                    236:                                ready = readfrom;
                    237:                                if (select(16, &ready, 0, 0, 0) < 0)
                    238:                                        break;
                    239:                                if (ready & (1<<s)) {
                    240:                                        if (read(s, &sig, 1) <= 0)
                    241:                                                readfrom &= ~(1<<s);
                    242:                                        else
                    243:                                                killpg(pid, sig);
                    244:                                }
                    245:                                if (ready & (1<<pv[0])) {
                    246:                                        errno = 0;
                    247:                                        cc = read(pv[0], buf, sizeof (buf));
                    248:                                        if (cc <= 0) {
                    249:                                                shutdown(s, 1+1);
                    250:                                                readfrom &= ~(1<<pv[0]);
                    251:                                        } else
                    252:                                                (void) write(s, buf, cc);
                    253:                                }
                    254:                        } while (readfrom);
                    255:                        exit(0);
                    256:                }
                    257:                setpgrp(0, getpid());
                    258:                (void) close(s); (void) close(pv[0]);
                    259:                dup2(pv[1], 2);
                    260:        }
                    261:        if (*pwd->pw_shell == '\0')
                    262:                pwd->pw_shell = "/bin/sh";
                    263:        (void) close(f);
                    264:        initgroups(pwd->pw_name, pwd->pw_gid);
                    265:        (void) setgid(pwd->pw_gid);
                    266:        (void) setuid(pwd->pw_uid);
                    267:        environ = envinit;
                    268:        strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
                    269:        strncat(shell, pwd->pw_shell, sizeof(shell)-7);
                    270:        strncat(username, pwd->pw_name, sizeof(username)-6);
                    271:        cp = rindex(pwd->pw_shell, '/');
                    272:        if (cp)
                    273:                cp++;
                    274:        else
                    275:                cp = pwd->pw_shell;
                    276:        execl(pwd->pw_shell, cp, "-c", cmdbuf, 0);
                    277:        perror(pwd->pw_shell);
                    278:        exit(1);
                    279: protofail:
                    280:        error("rsh: protocol failure detected by remote\n");
                    281:        exit(1);
                    282: }
                    283: 
                    284: /* VARARGS 1 */
                    285: error(fmt)
                    286:        char *fmt;
                    287: {
                    288:        char buf[BUFSIZ];
                    289: 
                    290:        buf[0] = 1;
                    291:        (void) sprintf(buf+1, fmt);
                    292:        (void) write(2, buf, strlen(buf));
                    293: }
                    294: 
                    295: getstr(buf, cnt, err)
                    296:        char *buf;
                    297:        int cnt;
                    298:        char *err;
                    299: {
                    300:        char c;
                    301: 
                    302:        do {
                    303:                if (read(0, &c, 1) != 1)
                    304:                        exit(1);
                    305:                *buf++ = c;
                    306:                if (--cnt == 0) {
                    307:                        error("%s too long\n", err);
                    308:                        exit(1);
                    309:                }
                    310:        } while (c != 0);
                    311: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.