|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.