1*12678Ssam #ifndef lint 2*12678Ssam static char *sccsid = "@(#)login.c 4.24 83/05/22"; 3*12678Ssam #endif 4*12678Ssam 51043Sbill /* 61043Sbill * login [ name ] 76005Swnj * login -r 81043Sbill */ 91043Sbill 101043Sbill #include <sys/types.h> 111043Sbill #include <sgtty.h> 121043Sbill #include <utmp.h> 131043Sbill #include <signal.h> 141043Sbill #include <pwd.h> 151043Sbill #include <stdio.h> 161043Sbill #include <sys/stat.h> 171043Sbill #include <lastlog.h> 18*12678Ssam #define QUOTA 19*12678Ssam #include <sys/quota.h> 20*12678Ssam #include <errno.h> 211043Sbill 222822Swnj #define SCPYN(a, b) strncpy(a, b, sizeof(a)) 232822Swnj 246197Sroot #define NMAX sizeof(utmp.ut_name) 256197Sroot #define LMAX sizeof(utmp.ut_line) 261043Sbill 272822Swnj #define FALSE 0 282822Swnj #define TRUE -1 292822Swnj 302822Swnj char nolog[] = "/etc/nologin"; 312822Swnj char qlog[] = ".hushlogin"; 322822Swnj char securetty[] = "/etc/securetty"; 331043Sbill char maildir[30] = "/usr/spool/mail/"; 341043Sbill char lastlog[] = "/usr/adm/lastlog"; 359867Ssam struct passwd nouser = {"", "nope", -1, -1, -1, "", "", "", "" }; 361043Sbill struct sgttyb ttyb; 371043Sbill struct utmp utmp; 381043Sbill char minusnam[16] = "-"; 396005Swnj 401043Sbill char homedir[64] = "HOME="; 411043Sbill char shell[64] = "SHELL="; 421043Sbill char term[64] = "TERM="; 432822Swnj char user[20] = "USER="; 446005Swnj char *speeds[] = 456005Swnj { "0", "50", "75", "110", "134", "150", "200", "300", 466005Swnj "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" }; 476005Swnj #define NSPEEDS (sizeof (speeds) / sizeof (speeds[0])) 486005Swnj 496005Swnj char *envinit[] = 506005Swnj {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", term, user, 0}; 516005Swnj 521043Sbill struct passwd *pwd; 531043Sbill struct passwd *getpwnam(); 546005Swnj char *strcat(), *rindex(), *index(); 551043Sbill int setpwent(); 561043Sbill char *ttyname(); 571043Sbill char *crypt(); 581043Sbill char *getpass(); 591043Sbill char *stypeof(); 601043Sbill extern char **environ; 61*12678Ssam extern int errno; 621043Sbill 639867Ssam struct ttychars tc = { 649867Ssam CERASE, CKILL, CINTR, CQUIT, CSTART, 659867Ssam CSTOP, CEOF, CBRK, CSUSP, CDSUSP, 669867Ssam CRPRNT, CFLUSH, CWERASE,CLNEXT 671365Sbill }; 681365Sbill 696005Swnj int rflag; 706197Sroot char rusername[NMAX+1], lusername[NMAX+1]; 716005Swnj char rpassword[NMAX+1]; 726878Smckusick char name[NMAX+1]; 736197Sroot char *rhost; 746005Swnj 751043Sbill main(argc, argv) 761043Sbill char **argv; 771043Sbill { 781043Sbill register char *namep; 791043Sbill int t, f, c; 802822Swnj int invalid; 812822Swnj int quietlog; 822822Swnj int i; 832822Swnj FILE *nlfd; 841043Sbill char *ttyn; 856197Sroot int ldisc = 0, zero = 0; 866197Sroot FILE *hostf; int first = 1; 871043Sbill 881043Sbill alarm(60); 891043Sbill signal(SIGQUIT, SIG_IGN); 901043Sbill signal(SIGINT, SIG_IGN); 911043Sbill nice(-100); 921043Sbill nice(20); 931043Sbill nice(0); 94*12678Ssam quota(Q_SETUID, 0, 0, 0); 956329Swnj if (argc > 1 && !strcmp(argv[1], "-r")) { 966005Swnj rflag++; 976329Swnj rhost = argv[2]; 986197Sroot argc = 1; 996329Swnj getstr(rusername, sizeof (rusername), "remuser"); 1006329Swnj getstr(lusername, sizeof (lusername), "locuser"); 1016005Swnj getstr(term+5, sizeof(term)-5, "Terminal type"); 1026329Swnj if (getuid()) 1036329Swnj goto abnormal; 1046197Sroot setpwent(); 1056197Sroot pwd = getpwnam(lusername); 1066329Swnj endpwent(); 10711990Sleres if (pwd == NULL) 1086329Swnj goto abnormal; 1096466Swnj hostf = pwd->pw_uid ? fopen("/etc/hosts.equiv", "r") : 0; 1106197Sroot again: 1116197Sroot if (hostf) { 11211813Sleres char ahost[32]; 11311813Sleres 11411813Sleres while (fgets(ahost, sizeof (ahost), hostf)) { 11511813Sleres char *user; 11611813Sleres 11712560Sleres if ((user = index(ahost, '\n')) != 0) 11812560Sleres *user++ = '\0'; 11912560Sleres if ((user = index(ahost, ' ')) != 0) 12012560Sleres *user++ = '\0'; 12111813Sleres if (!strcmp(rhost, ahost) && 12211813Sleres !strcmp(rusername, user ? 12311813Sleres user : lusername)) { 12411813Sleres fclose(hostf); 12511813Sleres goto normal; 12611813Sleres } 1276329Swnj } 12811813Sleres fclose(hostf); 1296197Sroot } 1306197Sroot if (first == 1) { 13111813Sleres char *rhosts = ".rhosts"; 13211813Sleres struct stat sbuf; 13311813Sleres 1346197Sroot first = 0; 1356197Sroot if (chdir(pwd->pw_dir) < 0) 1366197Sroot goto again; 13711813Sleres if (lstat(rhosts, &sbuf) < 0) 13811813Sleres goto again; 13911813Sleres if ((sbuf.st_mode & S_IFMT) == S_IFLNK) { 14011813Sleres printf("login: .rhosts is a soft link.\r\n"); 14111813Sleres goto abnormal; 14211813Sleres } 14311813Sleres hostf = fopen(rhosts, "r"); 14411813Sleres fstat(fileno(hostf), &sbuf); 14511813Sleres if ((int) sbuf.st_uid != pwd->pw_uid && 14611813Sleres (int) sbuf.st_uid != 0) { 14711813Sleres printf("login: Bad .rhosts ownership.\r\n"); 14811813Sleres fclose(hostf); 14911813Sleres goto abnormal; 15011813Sleres } 15111813Sleres goto again; 1526197Sroot } 1536329Swnj abnormal: 1546197Sroot rhost = 0; 1556197Sroot rflag = -1; 1566005Swnj } 1576197Sroot normal: 1589867Ssam ioctl(0, TIOCLSET, &zero); /* XXX */ 1591547Sbill ioctl(0, TIOCNXCL, 0); 1606329Swnj ioctl(0, FIONBIO, &zero); 1616329Swnj ioctl(0, FIOASYNC, &zero); 1629867Ssam ioctl(0, TIOCGETP, &ttyb); /* XXX */ 1636005Swnj if (rflag) { 1646005Swnj char *cp = index(term, '/'); 1656005Swnj if (cp) { 1666005Swnj int i; 1676005Swnj *cp++ = 0; 1686005Swnj for (i = 0; i < NSPEEDS; i++) 1696005Swnj if (!strcmp(speeds[i], cp)) { 1706005Swnj ttyb.sg_ispeed = ttyb.sg_ospeed = i; 1716005Swnj break; 1726005Swnj } 1736005Swnj } 1746005Swnj ttyb.sg_flags = ECHO|CRMOD|ANYP|XTABS; 1756005Swnj } 1769867Ssam ioctl(0, TIOCSETP, &ttyb); /* XXX */ 1779867Ssam ioctl(0, TIOCCSET, &tc); 1781043Sbill for (t=3; t<20; t++) 1791043Sbill close(t); 1801043Sbill ttyn = ttyname(0); 1812822Swnj if (ttyn==(char *)0) 1821043Sbill ttyn = "/dev/tty??"; 1832822Swnj do { 1842822Swnj ldisc = 0; 1852822Swnj ioctl(0, TIOCSETD, &ldisc); 1862822Swnj invalid = FALSE; 1872822Swnj SCPYN(utmp.ut_name, ""); 1882822Swnj if (argc>1) { 1892822Swnj SCPYN(utmp.ut_name, argv[1]); 1902822Swnj argc = 0; 1911043Sbill } 1926329Swnj if (rflag) { 1939867Ssam SCPYN(utmp.ut_name, lusername); 1946329Swnj if (rflag == -1) 1956329Swnj rflag = 0; 1966329Swnj } else 1976197Sroot while (utmp.ut_name[0] == '\0') { 1986197Sroot namep = utmp.ut_name; 1996197Sroot { char hostname[32]; 2006197Sroot gethostname(hostname, sizeof (hostname)); 2016197Sroot printf("%s login: ", hostname); } 2026197Sroot while ((c = getchar()) != '\n') { 2036197Sroot if (c == ' ') 2046197Sroot c = '_'; 2056197Sroot if (c == EOF) 2066197Sroot exit(0); 2076197Sroot if (namep < utmp.ut_name+NMAX) 2086197Sroot *namep++ = c; 2096197Sroot } 2102822Swnj } 2116197Sroot if (rhost == 0) { 2126197Sroot setpwent(); 2136197Sroot if ((pwd = getpwnam(utmp.ut_name)) == NULL) 2146197Sroot pwd = &nouser; 2156197Sroot endpwent(); 2162822Swnj } 2172822Swnj if (!strcmp(pwd->pw_shell, "/bin/csh")) { 2182822Swnj ldisc = NTTYDISC; 2192822Swnj ioctl(0, TIOCSETD, &ldisc); 2202822Swnj } 2216197Sroot if (rhost == 0) { 2226197Sroot if (*pwd->pw_passwd != '\0') { 2236197Sroot char *pp; 2246197Sroot nice(-4); 2256197Sroot if (rflag == 0) 2266197Sroot pp = getpass("Password:"); 2276197Sroot else 2286197Sroot pp = rpassword; 2296197Sroot namep = crypt(pp,pwd->pw_passwd); 2306197Sroot nice(4); 2316197Sroot if (strcmp(namep, pwd->pw_passwd)) 2326197Sroot invalid = TRUE; 2336197Sroot } 2342822Swnj } 2352822Swnj if (pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) > 0) { 2362822Swnj /* logins are disabled except for root */ 2372822Swnj while ((c = getc(nlfd)) != EOF) 2382822Swnj putchar(c); 2392822Swnj fflush(stdout); 2402822Swnj sleep(5); 2412822Swnj exit(0); 2422822Swnj } 2432822Swnj if (!invalid && pwd->pw_uid == 0 && 2442822Swnj !rootterm(ttyn+sizeof("/dev/")-1)) { 2456329Swnj logerr("ROOT LOGIN REFUSED %s", 2466329Swnj ttyn+sizeof("/dev/")-1); 2472822Swnj invalid = TRUE; 2482822Swnj } 2492822Swnj if (invalid) { 2501043Sbill printf("Login incorrect\n"); 2516329Swnj if (ttyn[sizeof("/dev/tty")-1] == 'd') 2526329Swnj logerr("BADDIALUP %s %s\n", 2536329Swnj ttyn+sizeof("/dev/")-1, utmp.ut_name); 2541043Sbill } 2552822Swnj if (*pwd->pw_shell == '\0') 2562822Swnj pwd->pw_shell = "/bin/sh"; 2572822Swnj i = strlen(pwd->pw_shell); 2582822Swnj if (chdir(pwd->pw_dir) < 0 && !invalid ) { 2592822Swnj if (chdir("/") < 0) { 2602822Swnj printf("No directory!\n"); 2612822Swnj invalid = TRUE; 2622822Swnj } else { 2632822Swnj printf("No directory! Logging in with home=/\n"); 2642822Swnj pwd->pw_dir = "/"; 2652822Swnj } 2661043Sbill } 2676005Swnj if (rflag && invalid) 2686005Swnj exit(1); 2692822Swnj } while (invalid); 2701043Sbill 271*12678Ssam if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0) { 272*12678Ssam if (errno == EUSERS) 273*12678Ssam printf("%s.\n%s.\n", 274*12678Ssam "Too many users logged on already", 275*12678Ssam "Try again later"); 276*12678Ssam else if (errno == EPROCLIM) 277*12678Ssam printf("You have too many processes running.\n"); 278*12678Ssam else 279*12678Ssam perror("setuid"); 280*12678Ssam sleep(5); 281*12678Ssam exit(0); 282*12678Ssam } 2831043Sbill time(&utmp.ut_time); 2841043Sbill t = ttyslot(); 2851043Sbill if (t>0 && (f = open("/etc/utmp", 1)) >= 0) { 2861043Sbill lseek(f, (long)(t*sizeof(utmp)), 0); 2871043Sbill SCPYN(utmp.ut_line, rindex(ttyn, '/')+1); 2881043Sbill write(f, (char *)&utmp, sizeof(utmp)); 2891043Sbill close(f); 2901043Sbill } 2911043Sbill if (t>0 && (f = open("/usr/adm/wtmp", 1)) >= 0) { 2921043Sbill lseek(f, 0L, 2); 2931043Sbill write(f, (char *)&utmp, sizeof(utmp)); 2941043Sbill close(f); 2951043Sbill } 2966329Swnj quietlog = 0; 2972822Swnj if (access(qlog, 0) == 0) 2986329Swnj quietlog = 1; 2996329Swnj if ((f = open(lastlog, 2)) >= 0) { 3002822Swnj struct lastlog ll; 3012822Swnj 3022822Swnj lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); 3032822Swnj if (read(f, (char *) &ll, sizeof ll) == sizeof ll && 3042822Swnj ll.ll_time != 0) { 3056329Swnj if (quietlog == 0) 3062822Swnj printf("Last login: %.*s on %.*s\n" 3072822Swnj , 24-5 3082822Swnj , (char *) ctime(&ll.ll_time) 3092822Swnj , sizeof(ll.ll_line) 3102822Swnj , ll.ll_line 3112822Swnj ); 3122822Swnj } 3132822Swnj lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); 3142822Swnj time(&ll.ll_time); 3152822Swnj SCPYN(ll.ll_line, rindex(ttyn, '/')+1); 3162822Swnj write(f, (char *) &ll, sizeof ll); 3172822Swnj close(f); 3182822Swnj } 3191043Sbill chown(ttyn, pwd->pw_uid, pwd->pw_gid); 3209867Ssam chmod(ttyn, 0622); 3211043Sbill setgid(pwd->pw_gid); 3226878Smckusick strncpy(name, utmp.ut_name, NMAX); 3236878Smckusick name[NMAX] = '\0'; 3249224Ssam initgroups(name, pwd->pw_gid); 325*12678Ssam quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0); 3261043Sbill setuid(pwd->pw_uid); 3271043Sbill environ = envinit; 3281043Sbill strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); 3291043Sbill strncat(shell, pwd->pw_shell, sizeof(shell)-7); 3306329Swnj if (term[strlen("TERM=")] == 0) 3316005Swnj strncat(term, stypeof(ttyn), sizeof(term)-6); 3322822Swnj strncat(user, pwd->pw_name, sizeof(user)-6); 3331043Sbill if ((namep = rindex(pwd->pw_shell, '/')) == NULL) 3341043Sbill namep = pwd->pw_shell; 3351043Sbill else 3361043Sbill namep++; 3371043Sbill strcat(minusnam, namep); 3381043Sbill alarm(0); 3396197Sroot umask(022); 3406329Swnj if (ttyn[sizeof("/dev/tty")-1] == 'd') 3416329Swnj logerr("DIALUP %s %s\n", ttyn+sizeof("/dev/")-1, pwd->pw_name); 3426329Swnj if (!quietlog) { 3432822Swnj showmotd(); 3442822Swnj strcat(maildir, pwd->pw_name); 3452822Swnj if (access(maildir,4)==0) { 3462822Swnj struct stat statb; 3472822Swnj stat(maildir, &statb); 3482822Swnj if (statb.st_size) 3492822Swnj printf("You have mail.\n"); 3502822Swnj } 3512822Swnj } 3522822Swnj 3531043Sbill signal(SIGQUIT, SIG_DFL); 3541043Sbill signal(SIGINT, SIG_DFL); 3553935Sroot signal(SIGTSTP, SIG_IGN); 3561043Sbill execlp(pwd->pw_shell, minusnam, 0); 3572822Swnj perror(pwd->pw_shell); 3581043Sbill printf("No shell\n"); 3591043Sbill exit(0); 3601043Sbill } 3611043Sbill 3621043Sbill int stopmotd; 3631043Sbill catch() 3641043Sbill { 3656466Swnj 3661043Sbill signal(SIGINT, SIG_IGN); 3671043Sbill stopmotd++; 3681043Sbill } 3691043Sbill 3702822Swnj rootterm(tty) 3716466Swnj char *tty; 3722822Swnj { 3732822Swnj register FILE *fd; 3746466Swnj char buf[100]; 3752822Swnj 3762822Swnj if ((fd = fopen(securetty, "r")) == NULL) 3772822Swnj return(1); 3782822Swnj while (fgets(buf, sizeof buf, fd) != NULL) { 3792822Swnj buf[strlen(buf)-1] = '\0'; 3802822Swnj if (strcmp(tty, buf) == 0) { 3812822Swnj fclose(fd); 3822822Swnj return(1); 3832822Swnj } 3842822Swnj } 3852822Swnj fclose(fd); 3862822Swnj return(0); 3872822Swnj } 3882822Swnj 3891043Sbill showmotd() 3901043Sbill { 3911043Sbill FILE *mf; 3921043Sbill register c; 3931043Sbill 3941043Sbill signal(SIGINT, catch); 3952822Swnj if ((mf = fopen("/etc/motd","r")) != NULL) { 3962822Swnj while ((c = getc(mf)) != EOF && stopmotd == 0) 3971043Sbill putchar(c); 3981043Sbill fclose(mf); 3991043Sbill } 4001043Sbill signal(SIGINT, SIG_IGN); 4011043Sbill } 4021043Sbill 4032822Swnj #undef UNKNOWN 4041043Sbill #define UNKNOWN "su" 4051043Sbill 4061043Sbill char * 4071043Sbill stypeof(ttyid) 4081043Sbill char *ttyid; 4091043Sbill { 4101043Sbill static char typebuf[16]; 4111043Sbill char buf[50]; 4121043Sbill register FILE *f; 4131043Sbill register char *p, *t, *q; 4141043Sbill 4151043Sbill if (ttyid == NULL) 4161043Sbill return (UNKNOWN); 4171043Sbill f = fopen("/etc/ttytype", "r"); 4181043Sbill if (f == NULL) 4191043Sbill return (UNKNOWN); 4201043Sbill /* split off end of name */ 4211043Sbill for (p = q = ttyid; *p != 0; p++) 4221043Sbill if (*p == '/') 4231043Sbill q = p + 1; 4241043Sbill 4251043Sbill /* scan the file */ 4261043Sbill while (fgets(buf, sizeof buf, f) != NULL) 4271043Sbill { 4282822Swnj for (t=buf; *t!=' ' && *t != '\t'; t++) 4291043Sbill ; 4301043Sbill *t++ = 0; 4312822Swnj while (*t == ' ' || *t == '\t') 4322822Swnj t++; 4331043Sbill for (p=t; *p>' '; p++) 4341043Sbill ; 4351043Sbill *p = 0; 4361043Sbill if (strcmp(q,t)==0) { 4371043Sbill strcpy(typebuf, buf); 4381043Sbill fclose(f); 4391043Sbill return (typebuf); 4401043Sbill } 4411043Sbill } 4421043Sbill fclose (f); 4431043Sbill return (UNKNOWN); 4441043Sbill } 4456005Swnj 4466005Swnj getstr(buf, cnt, err) 4476005Swnj char *buf; 4486005Swnj int cnt; 4496005Swnj char *err; 4506005Swnj { 4516005Swnj char c; 4526005Swnj 4536005Swnj do { 4546005Swnj if (read(0, &c, 1) != 1) 4556005Swnj exit(1); 4566005Swnj if (--cnt < 0) { 4576005Swnj printf("%s too long\r\n", err); 4586005Swnj exit(1); 4596005Swnj } 4606005Swnj *buf++ = c; 4616005Swnj } while (c != 0); 4626005Swnj } 4636329Swnj 4646329Swnj logerr(fmt, a1, a2, a3) 4656329Swnj char *fmt, *a1, *a2, *a3; 4666329Swnj { 4676329Swnj 4686329Swnj } 469