Annotation of 43BSD/etc/rlogind.c, revision 1.1.1.1

1.1       root        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[] = "@(#)rlogind.c  5.11 (Berkeley) 5/23/86";
                     15: #endif not lint
                     16: 
                     17: /*
                     18:  * remote login server:
                     19:  *     remuser\0
                     20:  *     locuser\0
                     21:  *     terminal info\0
                     22:  *     data
                     23:  */
                     24: 
                     25: #include <stdio.h>
                     26: #include <sys/types.h>
                     27: #include <sys/stat.h>
                     28: #include <sys/socket.h>
                     29: #include <sys/wait.h>
                     30: #include <sys/file.h>
                     31: 
                     32: #include <netinet/in.h>
                     33: 
                     34: #include <errno.h>
                     35: #include <pwd.h>
                     36: #include <signal.h>
                     37: #include <sgtty.h>
                     38: #include <stdio.h>
                     39: #include <netdb.h>
                     40: #include <syslog.h>
                     41: #include <strings.h>
                     42: 
                     43: # ifndef TIOCPKT_WINDOW
                     44: # define TIOCPKT_WINDOW 0x80
                     45: # endif TIOCPKT_WINDOW
                     46: 
                     47: extern errno;
                     48: int    reapchild();
                     49: struct passwd *getpwnam();
                     50: char   *malloc();
                     51: 
                     52: main(argc, argv)
                     53:        int argc;
                     54:        char **argv;
                     55: {
                     56:        int on = 1, options = 0, fromlen;
                     57:        struct sockaddr_in from;
                     58: 
                     59:        openlog("rlogind", LOG_PID | LOG_AUTH, LOG_AUTH);
                     60:        fromlen = sizeof (from);
                     61:        if (getpeername(0, &from, &fromlen) < 0) {
                     62:                fprintf(stderr, "%s: ", argv[0]);
                     63:                perror("getpeername");
                     64:                _exit(1);
                     65:        }
                     66:        if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) {
                     67:                syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
                     68:        }
                     69:        doit(0, &from);
                     70: }
                     71: 
                     72: int    child;
                     73: int    cleanup();
                     74: int    netf;
                     75: extern errno;
                     76: char   *line;
                     77: extern char    *inet_ntoa();
                     78: 
                     79: struct winsize win = { 0, 0, 0, 0 };
                     80: 
                     81: 
                     82: doit(f, fromp)
                     83:        int f;
                     84:        struct sockaddr_in *fromp;
                     85: {
                     86:        int i, p, t, pid, on = 1;
                     87:        register struct hostent *hp;
                     88:        struct hostent hostent;
                     89:        char c;
                     90: 
                     91:        alarm(60);
                     92:        read(f, &c, 1);
                     93:        if (c != 0)
                     94:                exit(1);
                     95:        alarm(0);
                     96:        fromp->sin_port = ntohs((u_short)fromp->sin_port);
                     97:        hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr),
                     98:                fromp->sin_family);
                     99:        if (hp == 0) {
                    100:                /*
                    101:                 * Only the name is used below.
                    102:                 */
                    103:                hp = &hostent;
                    104:                hp->h_name = inet_ntoa(fromp->sin_addr);
                    105:        }
                    106:        if (fromp->sin_family != AF_INET ||
                    107:            fromp->sin_port >= IPPORT_RESERVED)
                    108:                fatal(f, "Permission denied");
                    109:        write(f, "", 1);
                    110:        for (c = 'p'; c <= 's'; c++) {
                    111:                struct stat stb;
                    112:                line = "/dev/ptyXX";
                    113:                line[strlen("/dev/pty")] = c;
                    114:                line[strlen("/dev/ptyp")] = '0';
                    115:                if (stat(line, &stb) < 0)
                    116:                        break;
                    117:                for (i = 0; i < 16; i++) {
                    118:                        line[strlen("/dev/ptyp")] = "0123456789abcdef"[i];
                    119:                        p = open(line, 2);
                    120:                        if (p > 0)
                    121:                                goto gotpty;
                    122:                }
                    123:        }
                    124:        fatal(f, "Out of ptys");
                    125:        /*NOTREACHED*/
                    126: gotpty:
                    127:        (void) ioctl(p, TIOCSWINSZ, &win);
                    128:        netf = f;
                    129:        line[strlen("/dev/")] = 't';
                    130: #ifdef DEBUG
                    131:        { int tt = open("/dev/tty", 2);
                    132:          if (tt > 0) {
                    133:                ioctl(tt, TIOCNOTTY, 0);
                    134:                close(tt);
                    135:          }
                    136:        }
                    137: #endif
                    138:        t = open(line, 2);
                    139:        if (t < 0)
                    140:                fatalperror(f, line, errno);
                    141:        { struct sgttyb b;
                    142:          gtty(t, &b); b.sg_flags = RAW|ANYP; stty(t, &b);
                    143:        }
                    144:        pid = fork();
                    145:        if (pid < 0)
                    146:                fatalperror(f, "", errno);
                    147:        if (pid == 0) {
                    148:                close(f), close(p);
                    149:                dup2(t, 0), dup2(t, 1), dup2(t, 2);
                    150:                close(t);
                    151:                execl("/bin/login", "login", "-r", hp->h_name, 0);
                    152:                fatalperror(2, "/bin/login", errno);
                    153:                /*NOTREACHED*/
                    154:        }
                    155:        close(t);
                    156:        ioctl(f, FIONBIO, &on);
                    157:        ioctl(p, FIONBIO, &on);
                    158:        ioctl(p, TIOCPKT, &on);
                    159:        signal(SIGTSTP, SIG_IGN);
                    160:        signal(SIGCHLD, cleanup);
                    161:        setpgrp(0, 0);
                    162:        protocol(f, p);
                    163:        cleanup();
                    164: }
                    165: 
                    166: char   magic[2] = { 0377, 0377 };
                    167: char   oobdata[] = {TIOCPKT_WINDOW};
                    168: 
                    169: /*
                    170:  * Handle a "control" request (signaled by magic being present)
                    171:  * in the data stream.  For now, we are only willing to handle
                    172:  * window size changes.
                    173:  */
                    174: control(pty, cp, n)
                    175:        int pty;
                    176:        char *cp;
                    177:        int n;
                    178: {
                    179:        struct winsize w;
                    180: 
                    181:        if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's')
                    182:                return (0);
                    183:        oobdata[0] &= ~TIOCPKT_WINDOW;  /* we know he heard */
                    184:        bcopy(cp+4, (char *)&w, sizeof(w));
                    185:        w.ws_row = ntohs(w.ws_row);
                    186:        w.ws_col = ntohs(w.ws_col);
                    187:        w.ws_xpixel = ntohs(w.ws_xpixel);
                    188:        w.ws_ypixel = ntohs(w.ws_ypixel);
                    189:        (void)ioctl(pty, TIOCSWINSZ, &w);
                    190:        return (4+sizeof (w));
                    191: }
                    192: 
                    193: /*
                    194:  * rlogin "protocol" machine.
                    195:  */
                    196: protocol(f, p)
                    197:        int f, p;
                    198: {
                    199:        char pibuf[1024], fibuf[1024], *pbp, *fbp;
                    200:        register pcc = 0, fcc = 0;
                    201:        int cc;
                    202:        char cntl;
                    203: 
                    204:        /*
                    205:         * Must ignore SIGTTOU, otherwise we'll stop
                    206:         * when we try and set slave pty's window shape
                    207:         * (our controlling tty is the master pty).
                    208:         */
                    209:        (void) signal(SIGTTOU, SIG_IGN);
                    210:        send(f, oobdata, 1, MSG_OOB);   /* indicate new rlogin */
                    211:        for (;;) {
                    212:                int ibits, obits, ebits;
                    213: 
                    214:                ibits = 0;
                    215:                obits = 0;
                    216:                if (fcc)
                    217:                        obits |= (1<<p);
                    218:                else
                    219:                        ibits |= (1<<f);
                    220:                if (pcc >= 0)
                    221:                        if (pcc)
                    222:                                obits |= (1<<f);
                    223:                        else
                    224:                                ibits |= (1<<p);
                    225:                ebits = (1<<p);
                    226:                if (select(16, &ibits, &obits, &ebits, 0) < 0) {
                    227:                        if (errno == EINTR)
                    228:                                continue;
                    229:                        fatalperror(f, "select", errno);
                    230:                }
                    231:                if (ibits == 0 && obits == 0 && ebits == 0) {
                    232:                        /* shouldn't happen... */
                    233:                        sleep(5);
                    234:                        continue;
                    235:                }
                    236: #define        pkcontrol(c)    ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))
                    237:                if (ebits & (1<<p)) {
                    238:                        cc = read(p, &cntl, 1);
                    239:                        if (cc == 1 && pkcontrol(cntl)) {
                    240:                                cntl |= oobdata[0];
                    241:                                send(f, &cntl, 1, MSG_OOB);
                    242:                                if (cntl & TIOCPKT_FLUSHWRITE) {
                    243:                                        pcc = 0;
                    244:                                        ibits &= ~(1<<p);
                    245:                                }
                    246:                        }
                    247:                }
                    248:                if (ibits & (1<<f)) {
                    249:                        fcc = read(f, fibuf, sizeof (fibuf));
                    250:                        if (fcc < 0 && errno == EWOULDBLOCK)
                    251:                                fcc = 0;
                    252:                        else {
                    253:                                register char *cp;
                    254:                                int left, n;
                    255: 
                    256:                                if (fcc <= 0)
                    257:                                        break;
                    258:                                fbp = fibuf;
                    259: 
                    260:                        top:
                    261:                                for (cp = fibuf; cp < fibuf+fcc-1; cp++)
                    262:                                        if (cp[0] == magic[0] &&
                    263:                                            cp[1] == magic[1]) {
                    264:                                                left = fcc - (cp-fibuf);
                    265:                                                n = control(p, cp, left);
                    266:                                                if (n) {
                    267:                                                        left -= n;
                    268:                                                        if (left > 0)
                    269:                                                                bcopy(cp+n, cp, left);
                    270:                                                        fcc -= n;
                    271:                                                        goto top; /* n^2 */
                    272:                                                }
                    273:                                        }
                    274:                        }
                    275:                }
                    276: 
                    277:                if ((obits & (1<<p)) && fcc > 0) {
                    278:                        cc = write(p, fbp, fcc);
                    279:                        if (cc > 0) {
                    280:                                fcc -= cc;
                    281:                                fbp += cc;
                    282:                        }
                    283:                }
                    284: 
                    285:                if (ibits & (1<<p)) {
                    286:                        pcc = read(p, pibuf, sizeof (pibuf));
                    287:                        pbp = pibuf;
                    288:                        if (pcc < 0 && errno == EWOULDBLOCK)
                    289:                                pcc = 0;
                    290:                        else if (pcc <= 0)
                    291:                                break;
                    292:                        else if (pibuf[0] == 0)
                    293:                                pbp++, pcc--;
                    294:                        else {
                    295:                                if (pkcontrol(pibuf[0])) {
                    296:                                        pibuf[0] |= oobdata[0];
                    297:                                        send(f, &pibuf[0], 1, MSG_OOB);
                    298:                                }
                    299:                                pcc = 0;
                    300:                        }
                    301:                }
                    302:                if ((obits & (1<<f)) && pcc > 0) {
                    303:                        cc = write(f, pbp, pcc);
                    304:                        if (cc < 0 && errno == EWOULDBLOCK) {
                    305:                                /* also shouldn't happen */
                    306:                                sleep(5);
                    307:                                continue;
                    308:                        }
                    309:                        if (cc > 0) {
                    310:                                pcc -= cc;
                    311:                                pbp += cc;
                    312:                        }
                    313:                }
                    314:        }
                    315: }
                    316: 
                    317: cleanup()
                    318: {
                    319: 
                    320:        rmut();
                    321:        vhangup();              /* XXX */
                    322:        shutdown(netf, 2);
                    323:        exit(1);
                    324: }
                    325: 
                    326: fatal(f, msg)
                    327:        int f;
                    328:        char *msg;
                    329: {
                    330:        char buf[BUFSIZ];
                    331: 
                    332:        buf[0] = '\01';         /* error indicator */
                    333:        (void) sprintf(buf + 1, "rlogind: %s.\r\n", msg);
                    334:        (void) write(f, buf, strlen(buf));
                    335:        exit(1);
                    336: }
                    337: 
                    338: fatalperror(f, msg, errno)
                    339:        int f;
                    340:        char *msg;
                    341:        int errno;
                    342: {
                    343:        char buf[BUFSIZ];
                    344:        extern int sys_nerr;
                    345:        extern char *sys_errlist[];
                    346: 
                    347:        if ((unsigned)errno < sys_nerr)
                    348:                (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]);
                    349:        else
                    350:                (void) sprintf(buf, "%s: Error %d", msg, errno);
                    351:        fatal(f, buf);
                    352: }
                    353: 
                    354: #include <utmp.h>
                    355: 
                    356: struct utmp wtmp;
                    357: char   wtmpf[] = "/usr/adm/wtmp";
                    358: char   utmpf[] = "/etc/utmp";
                    359: #define SCPYN(a, b)    strncpy(a, b, sizeof(a))
                    360: #define SCMPN(a, b)    strncmp(a, b, sizeof(a))
                    361: 
                    362: rmut()
                    363: {
                    364:        register f;
                    365:        int found = 0;
                    366:        struct utmp *u, *utmp;
                    367:        int nutmp;
                    368:        struct stat statbf;
                    369: 
                    370:        f = open(utmpf, O_RDWR);
                    371:        if (f >= 0) {
                    372:                fstat(f, &statbf);
                    373:                utmp = (struct utmp *)malloc(statbf.st_size);
                    374:                if (!utmp)
                    375:                        syslog(LOG_ERR, "utmp malloc failed");
                    376:                if (statbf.st_size && utmp) {
                    377:                        nutmp = read(f, utmp, statbf.st_size);
                    378:                        nutmp /= sizeof(struct utmp);
                    379:                
                    380:                        for (u = utmp ; u < &utmp[nutmp] ; u++) {
                    381:                                if (SCMPN(u->ut_line, line+5) ||
                    382:                                    u->ut_name[0]==0)
                    383:                                        continue;
                    384:                                lseek(f, ((long)u)-((long)utmp), L_SET);
                    385:                                SCPYN(u->ut_name, "");
                    386:                                SCPYN(u->ut_host, "");
                    387:                                time(&u->ut_time);
                    388:                                write(f, (char *)u, sizeof(wtmp));
                    389:                                found++;
                    390:                        }
                    391:                }
                    392:                close(f);
                    393:        }
                    394:        if (found) {
                    395:                f = open(wtmpf, O_WRONLY|O_APPEND);
                    396:                if (f >= 0) {
                    397:                        SCPYN(wtmp.ut_line, line+5);
                    398:                        SCPYN(wtmp.ut_name, "");
                    399:                        SCPYN(wtmp.ut_host, "");
                    400:                        time(&wtmp.ut_time);
                    401:                        write(f, (char *)&wtmp, sizeof(wtmp));
                    402:                        close(f);
                    403:                }
                    404:        }
                    405:        chmod(line, 0666);
                    406:        chown(line, 0, 0);
                    407:        line[strlen("/dev/")] = 'p';
                    408:        chmod(line, 0666);
                    409:        chown(line, 0, 0);
                    410: }

unix.superglobalmegacorp.com

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