Annotation of researchv9/cmd/login.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * login  [ -f  name ] [ -p passwdline ] [ command ]
                      3:  *    -f:  if su, log in with no password
                      4:  *    -p:  if su, use entire password line.
                      5:  *    command: if given, just execute command
                      6:  */
                      7: 
                      8: #include <sys/param.h>
                      9: #include <sys/ttyio.h>
                     10: #include <utmp.h>
                     11: #include <signal.h>
                     12: #include <setjmp.h>
                     13: #include <pwd.h>
                     14: #include <grp.h>
                     15: #include <stdio.h>
                     16: #include <sys/stat.h>
                     17: #include <sys/lnode.h>
                     18: #include <sys/share.h>
                     19: #include <shares.h>
                     20: #include <errno.h>
                     21: 
                     22: #define        DEFSHARES       1       /* Default number of shares for a group 0 user */
                     23: #define        SYSERROR        (-1)
                     24: #define        MINUSAGE        1e6
                     25: #ifndef        ETOOMANYU
                     26: #define        ETOOMANYU       ENOSPC  /* Must go in errno.h or lnode.h */
                     27: #endif
                     28: #define SCPYN(a, b)    strncpy(a, b, sizeof(a))
                     29: 
                     30: #define ISIZE 32
                     31: #define POSTMKSIZ sizeof "From  Sun Jan 00 00:00:00 1979"
                     32: char   maildir[30] =   "/usr/spool/mail/";
                     33: struct passwd nouser = {"", "nope"};
                     34: struct utmp utmp;
                     35: char   minusnam[16] = "-";
                     36: char   homedir[64] = "HOME=";
                     37: char   path[] = "PATH=:/bin:/usr/bin";
                     38: char   **env;
                     39: int    nenv = 0;
                     40: char   nolog[] = "/etc/nologin";
                     41: struct passwd *pwd;
                     42: struct passwd *pwdecode();
                     43: char   *cmd;
                     44: 
                     45: struct passwd *getpwnam();
                     46: char   *strcat();
                     47: int    setpwent();
                     48: char   *ttyname();
                     49: char   *crypt();
                     50: char   *getpass();
                     51: char   *strrchr(), *strchr();
                     52: extern char **environ;
                     53: 
                     54: main(argc, argv)
                     55: char **argv;
                     56: {
                     57:        register char *namep;
                     58:        char input[ISIZE];
                     59:        char pwline[128];
                     60:        int t, f, c;
                     61:        char *ttyn;
                     62:        int neednopass = 0;
                     63:        int hangitup = 0;
                     64:        int ntries = 0;
                     65:        FILE *nlfd;
                     66:        int i;
                     67:        struct ttydevb tb;
                     68: 
                     69:        alarm(60);
                     70:        signal(SIGQUIT, SIG_IGN);
                     71:        signal(SIGINT, SIG_IGN);
                     72:        signal(SIGHUP, SIG_IGN);
                     73:        nice(-100);
                     74:        nice(20);
                     75:        nice(0);
                     76: #define        ONOFILE 20
                     77:        for (t=NSYSFILE; t<ONOFILE; t++)
                     78:                close(t);
                     79:        ttyn = ttyname(0);
                     80:        if (ttyn==0)
                     81:                ttyn = "/dev/tty??";
                     82:        SCPYN(input, "");
                     83:        switch(argc) {
                     84: 
                     85:        case 0:
                     86:        case 1:
                     87:                break;
                     88: 
                     89:        case 2:
                     90:                SCPYN(input, argv[1]);
                     91:                break;
                     92: 
                     93:        default:
                     94:                if (strcmp(argv[1], "-f")==0 || strcmp(argv[1], "-p")==0) {
                     95:                        if (getuid()!=0) {
                     96:                                printf("login: not super-user\n");
                     97:                                exit(1);
                     98:                        }
                     99:                        neednopass++;
                    100:                        if (strcmp(argv[1], "-f")==0)
                    101:                                SCPYN(input, argv[2]);
                    102:                        else {
                    103:                                SCPYN(pwline, argv[2]);
                    104:                                pwd = pwdecode(pwline);
                    105:                                SCPYN(input, pwd->pw_name);
                    106:                        }
                    107:                        if (argc>3)
                    108:                                cmd = argv[3];
                    109:                } else
                    110:                        exit(1);
                    111:        }
                    112:     loop:
                    113:        if (ntries) {
                    114:                if (ntries > 5 || hangitup) {
                    115:                        ioctl(0, TIOCGDEV, &tb);
                    116:                        tb.ispeed = tb.ospeed = 0;
                    117:                        ioctl(0, TIOCSDEV, &tb);
                    118:                        sleep(5);
                    119:                        exit(1);
                    120:                }
                    121:                neednopass = 0;
                    122:                pwd = NULL;
                    123:                SCPYN(input, "");
                    124:        }
                    125:        ntries++;
                    126:        while (input[0] == '\0') {
                    127:                namep = input;
                    128:                printf("login: ");
                    129:                while ((c = getchar()) != '\n') {
                    130:                        if(c == ' ')
                    131:                                c = '_';
                    132:                        if (c == EOF)
                    133:                                exit(0);
                    134:                        if (namep < input + ISIZE - 1)
                    135:                                *namep++ = c;
                    136:                }
                    137:                *namep = NULL;
                    138:        }
                    139:        SCPYN(utmp.ut_name, input);
                    140:        utmp.ut_time = 0;
                    141:        if (pwd == NULL) {
                    142:                setpwent();
                    143:                if ((pwd = getpwnam(input)) == NULL)
                    144:                        pwd = &nouser;
                    145:                endpwent();
                    146:        }
                    147:        if (namep = strchr(utmp.ut_name, '\001'))
                    148:                if (namep[1]=='L' && namep[2]=='\002')  /* loopback? */
                    149:                        hangitup++;
                    150:        time(&utmp.ut_time);
                    151:        SCPYN(utmp.ut_line, strchr(ttyn+1, '/')+1);
                    152:        if (*pwd->pw_passwd != '\0' && !neednopass) {
                    153:                namep = crypt(getpass("Password:"), pwd->pw_passwd);
                    154:                if (strcmp(namep, pwd->pw_passwd)) {
                    155:                        /* magic string detects loopbacks */
                    156:                        printf("\001L\002ogin incorrect\n");
                    157:                        f = open("/usr/adm/xtmp", 1);
                    158:                        if (f > 0) {
                    159:                                lseek(f, 0L, 2);
                    160:                                write(f, (char *)&utmp, sizeof(utmp));
                    161:                                close(f);
                    162:                        }
                    163:                        goto loop;
                    164:                }
                    165:        }
                    166:        if(pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) != NULL){
                    167:                while((c = getc(nlfd)) != EOF)
                    168:                        putchar(c);
                    169:                exit(0);
                    170:        }
                    171:        if(setuplimits(pwd) < 0)
                    172:                goto loop;
                    173:        (void)setupgroups(pwd);
                    174:        if(chdir(pwd->pw_dir) < 0) {
                    175:                printf("No directory\n");
                    176:                if(pwd->pw_uid != 0 || (access(nolog, 0) < 0))
                    177:                        goto loop;
                    178:        }
                    179:        setlogname(utmp.ut_name);
                    180:        if (cmd) {              /* remote exec */
                    181:                t = strlen(utmp.ut_name);
                    182:                if (t < sizeof(utmp.ut_name))
                    183:                        utmp.ut_name[t] = '*';
                    184:        }
                    185:        t = ttyslot();
                    186:        if (t>0 && (f = open("/etc/utmp", 1)) >= 0) {
                    187:                lseek(f, (long)(t*sizeof(utmp)), 0);
                    188:                write(f, (char *)&utmp, sizeof(utmp));
                    189:                close(f);
                    190:        }
                    191:        if (t>0 && (f = open("/usr/adm/wtmp", 1)) >= 0) {
                    192:                lseek(f, 0L, 2);
                    193:                write(f, (char *)&utmp, sizeof(utmp));
                    194:                close(f);
                    195:        }
                    196:        chown(ttyn, pwd->pw_uid, pwd->pw_gid);
                    197:        chmod(ttyn, 0622);
                    198:        setgid(pwd->pw_gid);
                    199:        setuid(pwd->pw_uid);
                    200:        if (*pwd->pw_shell == '\0')
                    201:                pwd->pw_shell = "/bin/sh";
                    202:        strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
                    203:        nenv = 0;
                    204:        for(i = 0; environ[i]; i++)
                    205:                ;
                    206:        env = (char **) malloc(sizeof(char *) * (i + 10));
                    207:        if (env == NULL) {
                    208:                printf("No memory for environment.\n");
                    209:                exit(1);
                    210:        }
                    211:        for (i = 0; environ[i]; i++) {
                    212:                if (strncmp(environ[i], "HOME=", 5) == 0)
                    213:                        continue;
                    214:                if (strncmp(environ[i], "PATH=", 5) == 0)
                    215:                        continue;
                    216:                env[nenv++] = environ[i];
                    217:        }
                    218:        if(homedir[0])
                    219:                env[nenv++] = homedir;
                    220:        if(path[0])
                    221:                env[nenv++] = path;
                    222:        env[nenv] = NULL;
                    223:        if ((namep = strrchr(pwd->pw_shell, '/')) == NULL)
                    224:                namep = pwd->pw_shell;
                    225:        else
                    226:                namep++;
                    227:        strcat(minusnam, namep);
                    228:        alarm(0);
                    229:        umask(02);
                    230:        if (cmd==NULL) {
                    231:                showmotd();
                    232:                strcat(maildir, pwd->pw_name);
                    233:                if(access(maildir,4)==0) {
                    234:                        struct stat statb;
                    235:                        stat(maildir, &statb);
                    236:                        if (statb.st_size > POSTMKSIZ)
                    237:                                printf("You have mail.\n");
                    238:                }
                    239:        }
                    240:        signal(SIGQUIT, SIG_DFL);
                    241:        signal(SIGINT, SIG_DFL);
                    242:        signal(SIGHUP, SIG_DFL);
                    243:        environ = env;
                    244:        if (cmd==NULL)
                    245:                execlp(pwd->pw_shell, minusnam, 0);
                    246:        else {
                    247:                env[nenv++] = "REXEC=1";
                    248:                ioctl(0, TIOCEXCL, (void *)NULL);
                    249:                env[nenv] = 0;
                    250:                execlp(pwd->pw_shell, minusnam, "-c", cmd, (char *)0);
                    251:        }
                    252:        printf("No shell\n");
                    253:        exit(0);
                    254: }
                    255: 
                    256: int    stopmotd;
                    257: catch()
                    258: {
                    259:        signal(SIGINT, SIG_IGN);
                    260:        stopmotd++;
                    261: }
                    262: 
                    263: showmotd()
                    264: {
                    265:        FILE *mf;
                    266:        register c;
                    267: 
                    268:        signal(SIGINT, catch);
                    269:        if((mf = fopen("/etc/motd","r")) != NULL) {
                    270:                while((c = getc(mf)) != EOF && stopmotd == 0)
                    271:                        putchar(c);
                    272:                fclose(mf);
                    273:        }
                    274:        signal(SIGINT, SIG_IGN);
                    275: }
                    276: 
                    277: /*
                    278: **     Set up parameters for share scheduler
                    279: */
                    280: 
                    281: int    catchsys();
                    282: jmp_buf        Sigsysbuf;
                    283: 
                    284: int
                    285: setuplimits(pwd)
                    286:        register struct passwd *pwd;
                    287: {
                    288:        register int            (*oldsig)();
                    289:        register unsigned long  extime;
                    290:        struct sh_consts        shconsts;
                    291:        struct lnode            share;
                    292: 
                    293:        if ( pwd->pw_uid == 0 )
                    294:                return 0;       /* root needs no set-up */
                    295: 
                    296:        oldsig = signal(SIGSYS, catchsys);
                    297: 
                    298:        if
                    299:        (
                    300:                setjmp(Sigsysbuf)
                    301:                ||
                    302:                limits((struct lnode *)&shconsts, L_GETCOSTS) == SYSERROR
                    303:                ||
                    304:                (Shareflags & NOSHARE)
                    305:        )
                    306:        {
                    307:                (void)signal(SIGSYS, oldsig);
                    308:                return 0;       /* Share not installed/active */
                    309:        }
                    310: 
                    311:        (void)signal(SIGSYS, oldsig);
                    312: 
                    313:        if ( (extime = getshares(&share, pwd->pw_uid, 0)) == 0 )
                    314:        {
                    315:                share.l_shares = DEFSHARES;
                    316:                share.l_usage = MINUSAGE;
                    317:        }
                    318:        else
                    319:        if ( limits(&share, L_OTHLIM) == SYSERROR )
                    320:        {
                    321:                /*
                    322:                **      Decay usage by time since last access.
                    323:                */
                    324: 
                    325:                if ( (extime = (utmp.ut_time - extime) / Delta) > 0 )
                    326:                {
                    327:                        extern double   pow();
                    328: 
                    329:                        share.l_usage *= pow(DecayUsage, (float)extime);
                    330:                        if ( share.l_usage < MINUSAGE )
                    331:                                share.l_usage = MINUSAGE;
                    332:                }
                    333:        }
                    334: 
                    335:        if ( setlimits(&share) == SYSERROR )
                    336:        {
                    337:                if ( errno == ETOOMANYU )
                    338:                {
                    339:                        char * cp = "other";
                    340: 
                    341:                        share.l_uid = OTHERUID;
                    342: 
                    343:                        if ( limits(&share, L_OTHLIM) != SYSERROR )
                    344:                                (void)setlimits(&share);
                    345:                        else
                    346:                                cp = "root";
                    347: 
                    348:                        printf("Warning: system out of share structures, using \"%s\".\n", cp);
                    349:                }
                    350:                else
                    351:                        perror("setlimits");
                    352:        }
                    353: 
                    354:        closeshares();
                    355: 
                    356:        return 0;
                    357: }
                    358: 
                    359: int
                    360: catchsys(sig)
                    361: {
                    362:        longjmp(Sigsysbuf, 1);
                    363:        perror("longjmp");
                    364:        abort();
                    365: }
                    366: 
                    367: /*
                    368: **     Set up access groups.
                    369: */
                    370: 
                    371: int
                    372: setupgroups(pwd)
                    373:        register struct passwd *pwd;
                    374: {
                    375:        register char **        cpp;
                    376:        register short *        gp;
                    377:        register struct group * grp;
                    378:        register int            n;
                    379:        short                   groups[NGROUPS];
                    380: 
                    381:        if ( getgroups(NGROUPS, groups) == SYSERROR )
                    382:                return; /* Not installed */
                    383: 
                    384:        (void)setgrent();
                    385: 
                    386:        gp = groups;
                    387: 
                    388:        while ( gp < &groups[NGROUPS] && (grp = getgrent()) != (struct group *)0 )
                    389:                for ( cpp = grp->gr_mem ; *cpp != (char *)0 ; cpp++ )
                    390:                        if ( strcmp(*cpp, pwd->pw_name) == 0 && grp->gr_gid != pwd->pw_gid )
                    391:                        {
                    392:                                *gp++ = grp->gr_gid;
                    393:                                break;
                    394:                        }
                    395: 
                    396:        (void)endgrent();
                    397: 
                    398:        if ( (n = gp-groups) == 0 )
                    399:                return;
                    400: 
                    401:        if ( setgroups(n, groups) == SYSERROR )
                    402:                perror("setgroups");
                    403: }

unix.superglobalmegacorp.com

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