Annotation of coherent/d/bin/login.c, revision 1.1

1.1     ! root        1: static char _version[]="login version 3.2.1";
        !             2: /*                    
        !             3:  * Rec'd from Lauren Weinstein, 7-16-84.
        !             4:  * Hacked by rec to enable remote kludge on pdp11 10-84.
        !             5:  * Hacked extensively by rec 84-11-02.
        !             6:  * Added terminal locking and version number October 1991 by piggy.
        !             7:  *
        !             8:  * login connects a user terminal:
        !             9:  *     1) unless executed by /etc/getty, the terminal is set back to
        !            10:  *             default modes and characters while preserving the speeds
        !            11:  *             and the parity.
        !            12:  *     2) The user name supplied or prompted for is located in the
        !            13:  *             password file, and the password, if any is specified,
        !            14:  *             is prompted for, encrypted, and compared to the specified
        !            15:  *             password.
        !            16:  *     3) If the user name did not exist, or the password was wrong, the
        !            17:  *             login is reported as incorrect and the procedure repeats.
        !            18:  *     4) If the tty is identified as 'remote' then:
        !            19:  *             a) at most MAXFAIL attempts are permitted before the tty
        !            20:  *             is hung up.
        !            21:  *             b) at most MAXTIME seconds are permitted for a successful
        !            22:  *             login before the tty is hung up.
        !            23:  *             c) if the user has no password, and the REMACC user in
        !            24:  *             /etc/passwd does have a password, then the REMACC password
        !            25:  *             must be supplied.  If this program is compiled with
        !            26:  *             "BBS" defined, then a valid serial number must be supplied
        !            27:  *             at the remote access password prompt.
        !            28:  *     5) An unsuccessful login appends a utmp record to the file
        !            29:  *             /usr/adm/failed if it exists.
        !            30:  *             It also removes the tty lock from /usr/spool/uucp.
        !            31:  *     6) A successful login:
        !            32:  *             a-1) Locks the tty in /usr/spool/uucp.
        !            33:  *             a) chdir's to the home directory specified by /etc/passwd
        !            34:  *             b) writes utmp records to /usr/adm/wtmp and /etc/utmp if.
        !            35:  *                     possible.
        !            36:  *             c) chowns the tty to be owned by the user.
        !            37:  *             d) chmods the tty to TTYMODE mode.
        !            38:  *             e) sets the user and group id's as specified by /etc/passwd.
        !            39:  *             f) sets USER to the user name matched in /etc/passwd.
        !            40:  *             g) sets HOME to the home directory specified in /etc/passwd.
        !            41:  *             h) sets SHELL to the shell specified in /etc/passwd.
        !            42:  *             i) exec's /bin/sh as "-sh" if and only if the shell
        !            43:  *                specified in /etc/passwd is either blank or /bin/sh,
        !            44:  *                otherwise as "+sh"; the "+/-" is for the benefit of /bin/sh.
        !            45:  *
        !            46:  * All other connect procedures and initializations should be performed by
        !            47:  * including them in /etc/profile or $HOME/.profile which the shell will
        !            48:  * perform before exec'ing the command interpreter specified by $SHELL.
        !            49:  * The shell will exit if any signals are received during /etc/profile.
        !            50:  */
        !            51: #include <stdio.h>
        !            52: #include <pwd.h>
        !            53: #include <signal.h>
        !            54: #include <utmp.h>
        !            55: #include <sys/dir.h>
        !            56: #include <sys/stat.h>
        !            57: #include <sgtty.h>
        !            58: #if NEWTTYS
        !            59: #include <sys/tty.h>
        !            60: #endif
        !            61: #include <sys/deftty.h>
        !            62: #ifdef BBS
        !            63: #include <sys/types.h>
        !            64: #endif
        !            65: 
        !            66: extern long lseek();
        !            67: #ifdef BBS
        !            68: extern int chk_srlno();
        !            69: extern time_t time();
        !            70: #endif
        !            71: 
        !            72: #define FALSE  0
        !            73: #define TRUE   1
        !            74: 
        !            75: #define        TTYMODE (S_IREAD|S_IWRITE|S_IEXEC)
        !            76: #define MAXFAIL        3               /* Maximum permitted failed login attempts */
        !            77: #define MAXTIME 60             /* Maximum seconds permitted for login */
        !            78: #define PASSLEN 13             /* Length of encrypted passwords */
        !            79: #define ACCNAME "remacc"       /* Remote access password dummy username */
        !            80: #define        NBUF    128             /* Assorted buffers */
        !            81: #define        LOGMSG  "/etc/logmsg"   /* Login message file */
        !            82: #define        DEFMSG  "Login: "       /* Default login message */
        !            83: 
        !            84: /*
        !            85:  * Default sgtty and tchars settings.
        !            86:  */
        !            87: 
        !            88: struct sgttyb  defsgt = {              /* Initial sgtty */
        !            89:        DEF_SG_ISPEED,
        !            90:        DEF_SG_OSPEED,
        !            91:        DEF_SG_ERASE,
        !            92:        DEF_SG_KILL,
        !            93:        DEF_SG_FLAGS
        !            94: };
        !            95:        
        !            96: struct tchars  deftch = {              /* Initial tchars */
        !            97:        DEF_T_INTRC,
        !            98:        DEF_T_QUITC,
        !            99:        DEF_T_STARTC,
        !           100:        DEF_T_STOPC,
        !           101:        DEF_T_EOFC,
        !           102:        DEF_T_BRKC
        !           103: };
        !           104: 
        !           105: /*
        !           106:  * Default environment list for shell.
        !           107:  */
        !           108: #define NDENV  64
        !           109: char   euser[NDENV]    = "USER=root";
        !           110: char   ehome[NDENV]    = "HOME=/etc";
        !           111: char   eshell[NDENV]   = "SHELL=";
        !           112: char *defenv0[] = {            /* Default environment for super user */
        !           113:        euser, ehome, "PATH=/bin:/usr/bin:/etc:", "PS1=# ", eshell, NULL
        !           114: };
        !           115: char *defenvn[] = {            /* Default environment for other user */
        !           116:        euser, ehome, "PATH=:/bin:/usr/bin", "PS1=$ ", eshell, NULL
        !           117: };
        !           118: 
        !           119: /*
        !           120:  * Assorted data.
        !           121:  */
        !           122: char   faillog[] = "/usr/adm/failed";  /* failed login attempt log */
        !           123: char   wholog[] = "/etc/utmp";         /* current login log */
        !           124: char   motd[] = "/etc/motd";           /* message of the day */
        !           125: char    goodlog[] = "/usr/adm/wtmp";    /* successful login log */       
        !           126: #ifdef BBS
        !           127: char    goodsrl[] = "/usr/adm/wsrl";    /* successful login log */       
        !           128: #endif
        !           129: char   *prompt[] = {
        !           130:        "Password: ",                   /* password msg 1 */
        !           131: #ifdef BBS
        !           132:        "BBS access password: "         /* password msg 2 */
        !           133: #else
        !           134:        "Remote access password: "      /* password msg 2 */
        !           135: #endif
        !           136: };
        !           137: char   buff[NBUF];                     /* I/O buffer */
        !           138: char   *argv0 = "login";               /* Command name */
        !           139: 
        !           140: #ifdef BBS
        !           141: static int     good_serialno;
        !           142: FILE * fp_srl;
        !           143: time_t tnum;
        !           144: #endif
        !           145: 
        !           146: main(argc, argv) int argc; char *argv[];
        !           147: {
        !           148:        register char *cp;              /* Password pointer */
        !           149:        register struct passwd *pwp;
        !           150:        int i, fd;
        !           151:        int oldtime;                    /* Alarm temporary */
        !           152:        int failed = TRUE;              /* Assume cracker */
        !           153:        int remote = FALSE;             /* Assume not remote tty line */
        !           154:        int passcount = 0;              /* Password pass */
        !           155:        int logcount = 0;               /* Login attempt count */
        !           156:        char *s_tty;                    /* tty name */
        !           157:        char *s_user;                   /* user name, saved in euser[] */
        !           158:        char *s_dir;                    /* user directory, saved in ehome[] */
        !           159:        char *s_shell;                  /* user shell, saved in eshell[] */
        !           160:        int s_uid;                      /* user id */
        !           161:        int s_gid;                      /* group id */
        !           162:        extern int timeout();           /* Login attempt alarm function */
        !           163:        extern char *crypt();
        !           164:        extern char *getpass();
        !           165:        extern char *ttyname();
        !           166:        extern char *strcpy();
        !           167:        extern char *index();
        !           168: 
        !           169:        if (argc > 0)
        !           170:                argv0 = argv[0];
        !           171: 
        !           172:        /* Usage check */
        !           173:        if (argc < 1 || argc > 2) {
        !           174:                fprintf(stderr, "Usage: %s [username]\n", argv0);
        !           175:                slowexit(1);
        !           176:        }
        !           177: 
        !           178:        /* Login no args, let getty start us from scratch */
        !           179:        if (argc == 1 && argv0[0] != '-')
        !           180:                exit(0);
        !           181: 
        !           182:        /* Default signals */
        !           183:        for (i=1; i<=NSIG; i++)
        !           184:                signal(i, SIG_DFL);
        !           185: 
        !           186:        /* Default file descriptors */
        !           187:        for (i=3; close(i)>=0; i++)
        !           188:                ;
        !           189: 
        !           190:        /* Locate buffers */
        !           191:        s_dir = index(ehome, '=') + 1;
        !           192:        s_user = index(euser, '=') + 1;
        !           193:        s_shell = index(eshell, '=') + 1;
        !           194: 
        !           195:        /* Find out tty, and reset if necessary */
        !           196:        if ((s_tty = ttyname(2)) == NULL) {
        !           197:                fprintf(stderr, "%s: cannot find terminal.\n", argv0);
        !           198:                slowexit(1);
        !           199:        }
        !           200: 
        !           201:        /*
        !           202:         * If login has been exec()'d by a login shell, there will
        !           203:         * already be a lock file.  Fortunately, this lock file belongs
        !           204:         * to us, so we can remove it.  If there is a lock file that
        !           205:         * doesn't belong to us, unlocktty() won't remove it, and the
        !           206:         * subsequent locktty() will fail, as it should.  We are
        !           207:         * explicitly ignoring the return value of unlocktty().
        !           208:         */
        !           209:        (void) unlocktty(strrchr(s_tty, '/') + 1);
        !           210: 
        !           211:        /* Let's lock this tty, so nobody else grabs it until we log out.  */
        !           212:        if (-1 == locktty(strrchr(s_tty, '/') + 1) ){
        !           213:                fprintf(stderr, "%s: cannot lock terminal.\n", argv0);
        !           214:                slowexit(1);
        !           215:        }
        !           216: 
        !           217:        if (argv0[0] != '-'             /* Not called from /etc/getty */
        !           218:         && settty(2) != 0) {           /* Reset terminal failed */
        !           219:                perror(s_tty);
        !           220:                slowexit(1);
        !           221:        }
        !           222: 
        !           223:        if (argv0[0] == '-' && argv0[1] == 'r') /* Isolate remote determination */
        !           224:        {  remote = TRUE;
        !           225:           signal(SIGALRM, &timeout);   /* catch login timeout */
        !           226:           alarm(MAXTIME);              /* set timeout alarm */
        !           227:        }
        !           228: 
        !           229: again: failed = TRUE;  /* assume attempt will fail */
        !           230:        setpwent();     /* rewind password file */
        !           231:        if (remote && (++logcount > MAXFAIL))  /* count remote attempts */
        !           232:           slowexit(1);  /* exit (and try force hangup) if too many attempts */
        !           233: 
        !           234:        if (passcount == 0)     /* first pass?, user name and password */
        !           235:        {  if (argc > 1)
        !           236:            {  strcpy(buff, argv[1]);   /* Use argument once */
        !           237:              argc  = 0;
        !           238:           } 
        !           239:           else 
        !           240:           {
        !           241:              do {
        !           242:                 printprompt();
        !           243:                 if (fgets(buff, NBUF-1, stdin) == NULL)
        !           244:                 {  putchar('\n');
        !           245:                    slowexit(1);
        !           246:                 }
        !           247:              } while (buff[0] == '\n' && buff[1] == 0);
        !           248:              buff[strlen(buff)-1] = 0;  /* null terminate over newline */
        !           249:           }
        !           250:           pwp = getpwnam(buff);        /* get name entry */
        !           251:           if (pwp != NULL)             /* if entry found */
        !           252:           {
        !           253:              if (strcmp(pwp->pw_name, ACCNAME) == 0) {
        !           254:                printf("Login incorrect\n");    /* disallow remacc logins */
        !           255:                goto again;
        !           256:              }
        !           257:              strcpy(s_user, pwp->pw_name);     /* save name */
        !           258:              s_uid = pwp->pw_uid;              /* save uid */
        !           259:              s_gid = pwp->pw_gid;              /* save gid */  
        !           260:              strcpy(s_dir, pwp->pw_dir);       /* save directory */
        !           261:              strcpy(s_shell, (*pwp->pw_shell == '\0') ? "/bin/sh"
        !           262:                                                       : pwp->pw_shell);
        !           263:           }
        !           264:        }
        !           265:        else                    /* second pass, remote access password */
        !           266:        {
        !           267: #ifdef BBS
        !           268:          pwp = NULL;
        !           269: #else
        !           270:           pwp = getpwnam(ACCNAME);  /* check for remote access entry */
        !           271:           if (pwp == NULL || pwp->pw_passwd[0] == 0)  /* no access pass? */
        !           272:              goto ok;  /* all done */
        !           273: #endif
        !           274:        }
        !           275: 
        !           276:        if (pwp == NULL                 /* Not a user name */
        !           277:         || pwp->pw_passwd[0] != 0)     /* Password present */
        !           278:        {   if ((cp = getpass(prompt[passcount])) != NULL && cp[0] != '\0') {
        !           279: #ifdef BBS
        !           280:            if (passcount == 0) {
        !           281: #endif
        !           282:               cp = crypt(cp, pwp==NULL ? "xx" : pwp->pw_passwd);
        !           283:               if (pwp != NULL
        !           284:                  && strcmp(cp, pwp->pw_passwd) == 0
        !           285:                  && strcmp(s_user, ACCNAME) != 0
        !           286:                  && strlen(pwp->pw_passwd) == PASSLEN)
        !           287:                        failed = FALSE;  /* success */
        !           288: #ifdef BBS
        !           289:            } else { /* for BBS, second password is a serial # */
        !           290:                if (chk_srlno(cp)) {
        !           291:                        failed = FALSE;  /* success */
        !           292:                        good_serialno = TRUE;
        !           293:                }
        !           294:            }
        !           295: #endif
        !           296:            }
        !           297: 
        !           298:            if (failed)  /* failed attempt? */
        !           299:            {  oldtime = alarm(0);  /* turn off alarm */
        !           300:               passcount = 0;       /* reset pass count */
        !           301:               setutmp(s_tty, buff, faillog, FALSE);  /* failed attempt */
        !           302:               alarm(oldtime);       /* continue timeout */
        !           303:               printf("Login incorrect\n");  /* incorrect */
        !           304:               goto again;
        !           305:            }
        !           306:        }
        !           307: 
        !           308:        if (remote && passcount++ == 0)  /* need another pass? */
        !           309:        {  logcount--;       /* don't count as login attempt */
        !           310:           goto again;       /* yes */  
        !           311:        }
        !           312: 
        !           313: ok:    alarm(0);       /* turn off login alarm timeout */
        !           314:        endpwent();     /* close password file */
        !           315:        if (chdir(s_dir) < 0) { /* cd to $HOME */
        !           316:                perror(s_dir);
        !           317:                slowexit(1);
        !           318:        }
        !           319:        setutmp(s_tty, buff, goodlog, TRUE);    /* successful login */
        !           320: #ifdef BBS
        !           321: /*
        !           322:  * for BBS users, write "xxxxxxxxx time tty" to /usr/adm/wsrl
        !           323:  * where       xxxxxxxxx is the serial number
        !           324:  *             time is decimal long value of clock time at login
        !           325:  *             tty is login device minus "/dev/"
        !           326:  */
        !           327:        if (good_serialno) {
        !           328:                good_serialno = FALSE;
        !           329:                if (fp_srl = fopen(goodsrl, "a")) {
        !           330:                        time(&tnum);
        !           331:                        fprintf(fp_srl, "%s %10ld %s\n", cp, tnum, s_tty+5);
        !           332:                        fclose(fp_srl);
        !           333:                }
        !           334:        }
        !           335: #endif
        !           336:        chown(s_tty, s_uid, s_gid);             /* grab the terminal */
        !           337:        chmod(s_tty, TTYMODE);                  /* initialize its modes */
        !           338:        setgid(s_gid);                          /* set group */
        !           339:        setuid(s_uid);                          /* set user */
        !           340:        if ((fd = open(motd, 0)) >= 0) {        /* list message of day */
        !           341:                while ((i = read(fd, buff, NBUF)) > 0)
        !           342:                        write(2, buff, i);
        !           343:                close(fd);
        !           344:        }
        !           345:        execle("/bin/sh",
        !           346:                strcmp(s_shell, "/bin/sh") ? "+sh" : "-sh",
        !           347:                NULL,
        !           348:                s_uid == 0 ? defenv0 : defenvn);
        !           349:        fprintf(stderr, "No /bin/sh.\n");
        !           350:        slowexit(1);
        !           351: }
        !           352: 
        !           353: /*
        !           354:  * Write out an accounting entry for
        !           355:  * 'tty' and 'username' into filename pointed to by "filep".
        !           356:  * If "success" is TRUE (indicating a good login) also write 'utmp' entry.
        !           357:  */
        !           358: setutmp(tty, username, filep, success)
        !           359: char *tty, *username, *filep;
        !           360: {
        !           361:        time_t time();
        !           362:        struct utmp utmp;
        !           363:        struct utmp spare;
        !           364:        fsize_t freeslot = -1, slot = 0;
        !           365:        register ufd;
        !           366: 
        !           367:        utmp.ut_time = time(NULL);
        !           368:        strncpy(utmp.ut_line, tty+5, 8);
        !           369:        strncpy(utmp.ut_name, username, DIRSIZ);
        !           370:        if ((ufd = open(filep, 1)) >= 0) {
        !           371:                lseek(ufd, 0L, 2);
        !           372:                write(ufd, &utmp, sizeof (utmp));
        !           373:                close(ufd);
        !           374:        }
        !           375:        if (!success)  /* failed login attempt? */
        !           376:           return;     /* all done */
        !           377: 
        !           378:        if ((ufd = open("/etc/utmp", 2)) >= 0) {
        !           379:                while (read(ufd, &spare, sizeof (spare)) == sizeof (spare)) {
        !           380:                        if (spare.ut_line[0] == '\0')
        !           381:                                freeslot = slot;
        !           382:                        else if (strncmp(spare.ut_line, utmp.ut_line, 8) == 0) {
        !           383:                                freeslot = slot;
        !           384:                                break;
        !           385:                        }
        !           386:                        slot += sizeof (utmp);
        !           387:                }
        !           388:                if (freeslot >= 0)
        !           389:                        lseek(ufd, freeslot, 0);
        !           390:                write(ufd, &utmp, sizeof (utmp));
        !           391:                close (ufd);
        !           392:        }
        !           393: }
        !           394: 
        !           395: /* login alarm timeout routine */
        !           396: timeout()
        !           397: {      
        !           398:        printf("\n");  /* neatness */
        !           399:        slowexit(1);  /* exit (and try force hangup for remote line) */
        !           400: }
        !           401: 
        !           402: /*
        !           403:  * Set the characters for the terminal to the defaults.
        !           404:  * Return non-zero on error.
        !           405:  */
        !           406: settty(fd)
        !           407: {
        !           408:        struct sgttyb sgp;
        !           409: 
        !           410:        if (ioctl(fd, TIOCGETP, &sgp) < 0)
        !           411:                return (1);
        !           412:        defsgt.sg_ispeed = sgp.sg_ispeed;
        !           413:        defsgt.sg_ospeed = sgp.sg_ospeed;
        !           414:        defsgt.sg_flags &= ~(EVENP|ODDP);
        !           415:        defsgt.sg_flags |= sgp.sg_flags&(EVENP|ODDP);
        !           416:        if (ioctl(fd, TIOCSETN, &defsgt) < 0)
        !           417:                return(1);
        !           418:        if (ioctl(fd, TIOCSETC, &deftch) < 0)
        !           419:                return(1);
        !           420:        return(0);
        !           421: }
        !           422: 
        !           423: /* sleep for 2 seconds to make sure output has flushed, then exit */
        !           424: slowexit(status)
        !           425: {
        !           426:     char *s_tty;
        !           427: 
        !           428:     if ((s_tty = ttyname(2)) != NULL) {
        !           429:        if (-1 == unlocktty(strrchr(s_tty, '/') + 1)) {
        !           430:                fprintf(stderr, "Trouble unlocking tty %s.\n", s_tty);
        !           431:        }
        !           432:     }
        !           433: 
        !           434:     sleep(2);
        !           435:     exit(status);
        !           436: }
        !           437: 
        !           438: /*
        !           439:  * Initial attempt failed, print a new prompt.
        !           440:  * The prompt is the last line of file LOGMSG or DEFMSG.
        !           441:  */
        !           442: printprompt()
        !           443: {
        !           444: #define        BSIZE   128
        !           445:        static char     *msg;
        !           446:        int             msgfd, count;
        !           447:        long            n;
        !           448:        static char     msgbuf[BSIZE+1];    /* login msg buffer */
        !           449: 
        !           450:        if (msg != NULL) {                      /* Prompt already known. */
        !           451:                printf("\r\n%s", msg);
        !           452:                return;
        !           453:        }
        !           454:        if ((msgfd = open(LOGMSG, 0)) < 0) {    /* try for login msg file */
        !           455:                printf(DEFMSG);
        !           456:                msg = DEFMSG;
        !           457:                return;
        !           458:        }
        !           459:        n = lseek(msgfd, 0L, 2);
        !           460:        if (n > BSIZE)
        !           461:                lseek(msgfd, -(long)BSIZE, 2);
        !           462:        else
        !           463:                lseek(msgfd, 0L, 0);
        !           464:        count = read(msgfd, msgbuf, BSIZE);     /* read from file */
        !           465:        close(msgfd);
        !           466:        while (count > 0 && msgbuf[count-1] == '\n')
        !           467:                 --count;                       /* skip trailing newlines */
        !           468:        msgbuf[count] = '\0';
        !           469:        if (count == 0) {
        !           470:                printf(DEFMSG);
        !           471:                msg = DEFMSG;
        !           472:                return;
        !           473:        }
        !           474:        /* Reprint only the last line of the message file. */
        !           475:        for (msg = &msgbuf[count]; msg >= msgbuf && *msg != '\n'; msg--)
        !           476:                ;
        !           477:        ++msg;
        !           478:        printf("\r\n%s", msg);
        !           479: }

unix.superglobalmegacorp.com

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