1*3935Sroot static char *sccsid = "@(#)login.c 4.11 (Berkeley) 81/07/05"; 21043Sbill /* 31043Sbill * login [ name ] 41043Sbill */ 51043Sbill 61043Sbill #include <sys/types.h> 71043Sbill #include <sgtty.h> 81043Sbill #include <utmp.h> 91043Sbill #include <signal.h> 101043Sbill #include <pwd.h> 111043Sbill #include <stdio.h> 121043Sbill #include <sys/stat.h> 131043Sbill #include <lastlog.h> 141804Sbill #include <whoami.h> 152822Swnj #ifdef UNAME 162822Swnj #include <sys/utsname.h> 172822Swnj #endif 181043Sbill 192822Swnj #define SCPYN(a, b) strncpy(a, b, sizeof(a)) 202822Swnj 211043Sbill #define NMAX sizeof(utmp.ut_name) 221043Sbill #define LMAX sizeof(utmp.ut_line) 231043Sbill 242822Swnj #define FALSE 0 252822Swnj #define TRUE -1 262822Swnj 272822Swnj char nolog[] = "/etc/nologin"; 282822Swnj char qlog[] = ".hushlogin"; 292822Swnj char securetty[] = "/etc/securetty"; 301043Sbill char maildir[30] = "/usr/spool/mail/"; 311043Sbill char lastlog[] = "/usr/adm/lastlog"; 321043Sbill struct passwd nouser = {"", "nope"}; 331043Sbill struct sgttyb ttyb; 341043Sbill struct utmp utmp; 351043Sbill char minusnam[16] = "-"; 361043Sbill char homedir[64] = "HOME="; 371043Sbill char shell[64] = "SHELL="; 381043Sbill char term[64] = "TERM="; 392822Swnj char user[20] = "USER="; 402822Swnj char *envinit[] = {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", term, user, 0}; 411043Sbill struct passwd *pwd; 421043Sbill 431043Sbill struct passwd *getpwnam(); 441043Sbill char *strcat(); 451043Sbill int setpwent(); 461043Sbill char *ttyname(); 471043Sbill char *crypt(); 481043Sbill char *getpass(); 491043Sbill char *rindex(); 501043Sbill char *stypeof(); 511043Sbill extern char **environ; 521043Sbill 531365Sbill #define CTRL(c) ('c'&037) 541365Sbill #define CERASE '#' 551365Sbill #define CEOT CTRL(d) 561365Sbill #define CKILL '@' 571365Sbill #define CQUIT 034 /* FS, cntl shift L */ 581365Sbill #define CINTR 0177 /* DEL */ 591365Sbill #define CSTOP CTRL(s) 601365Sbill #define CSTART CTRL(q) 611365Sbill #define CBRK 0377 621365Sbill struct tchars tc = { 631365Sbill CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK 641365Sbill }; 652822Swnj #ifdef TIOCLSET 661365Sbill struct ltchars ltc = { 671546Sbill CTRL(z), CTRL(y), CTRL(r), CTRL(o), CTRL(w), CTRL(v) 681365Sbill }; 692822Swnj #endif 701365Sbill 711043Sbill main(argc, argv) 721043Sbill char **argv; 731043Sbill { 741043Sbill register char *namep; 751043Sbill int t, f, c; 762822Swnj int invalid; 772822Swnj int quietlog; 782822Swnj int i; 792822Swnj FILE *nlfd; 801043Sbill char *ttyn; 812822Swnj int ldisc = 0; 822822Swnj #ifdef UNAME 832822Swnj struct utsname uts; 842822Swnj #endif 851043Sbill 861043Sbill alarm(60); 871043Sbill signal(SIGQUIT, SIG_IGN); 881043Sbill signal(SIGINT, SIG_IGN); 891043Sbill nice(-100); 901043Sbill nice(20); 911043Sbill nice(0); 922822Swnj #ifdef TIOCLSET 931043Sbill ioctl(0, TIOCLSET, 0); 942822Swnj #endif 951547Sbill ioctl(0, TIOCNXCL, 0); 961043Sbill gtty(0, &ttyb); 972822Swnj ttyb.sg_erase = CERASE; 982822Swnj ttyb.sg_kill = CKILL; 991043Sbill stty(0, &ttyb); 1001365Sbill ioctl(0, TIOCSETC, &tc); 1012822Swnj #ifdef TIOCLSET 1021365Sbill ioctl(0, TIOCSLTC, <c); 1032822Swnj #endif 1041043Sbill for (t=3; t<20; t++) 1051043Sbill close(t); 1061043Sbill ttyn = ttyname(0); 1072822Swnj if (ttyn==(char *)0) 1081043Sbill ttyn = "/dev/tty??"; 1091043Sbill 1102822Swnj do { 1112822Swnj ldisc = 0; 1122822Swnj ioctl(0, TIOCSETD, &ldisc); 1132822Swnj invalid = FALSE; 1142822Swnj SCPYN(utmp.ut_name, ""); 1152822Swnj if (argc>1) { 1162822Swnj SCPYN(utmp.ut_name, argv[1]); 1172822Swnj argc = 0; 1181043Sbill } 1192822Swnj while (utmp.ut_name[0] == '\0') { 1202822Swnj namep = utmp.ut_name; 1212822Swnj #ifdef UNAME 1222822Swnj if (uname(&uts) != -1) 1232822Swnj printf("%s login: ", uts.nodename); 1242822Swnj else 1252822Swnj #endif 1262822Swnj printf("login: "); 1272822Swnj while ((c = getchar()) != '\n') { 1282822Swnj if (c == ' ') 1292822Swnj c = '_'; 1302822Swnj if (c == EOF) 1312822Swnj exit(0); 1322822Swnj if (namep < utmp.ut_name+NMAX) 1332822Swnj *namep++ = c; 1342822Swnj } 1352822Swnj } 1362822Swnj setpwent(); 1372822Swnj if ((pwd = getpwnam(utmp.ut_name)) == NULL) 1382822Swnj pwd = &nouser; 1392822Swnj endpwent(); 1402822Swnj if (!strcmp(pwd->pw_shell, "/bin/csh")) { 1412822Swnj ldisc = NTTYDISC; 1422822Swnj ioctl(0, TIOCSETD, &ldisc); 1432822Swnj } 1442822Swnj if (*pwd->pw_passwd != '\0') { 1452822Swnj nice(-4); 1462822Swnj namep = crypt(getpass("Password:"),pwd->pw_passwd); 1472822Swnj nice(4); 1482822Swnj if (strcmp(namep, pwd->pw_passwd)) 1492822Swnj invalid = TRUE; 1502822Swnj } 1512822Swnj if (pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) > 0) { 1522822Swnj /* logins are disabled except for root */ 1532822Swnj while ((c = getc(nlfd)) != EOF) 1542822Swnj putchar(c); 1552822Swnj fflush(stdout); 1562822Swnj sleep(5); 1572822Swnj exit(0); 1582822Swnj } 1592822Swnj if (!invalid && pwd->pw_uid == 0 && 1602822Swnj !rootterm(ttyn+sizeof("/dev/")-1)) { 1612822Swnj FILE *console = fopen("/dev/console", "w"); 1622822Swnj if (console != NULL) { 1632822Swnj fprintf(console, "\r\nROOT LOGIN REFUSED %s\r\n" 1642822Swnj , ttyn+sizeof("/dev/")-1 1652822Swnj ); 1662822Swnj fclose(console); 1672822Swnj } 1682822Swnj invalid = TRUE; 1692822Swnj } 1702822Swnj if (invalid) { 1711043Sbill printf("Login incorrect\n"); 1722822Swnj if (ttyn[sizeof("/dev/tty")-1] == 'd') { 1731043Sbill FILE *console = fopen("/dev/console", "w"); 1741043Sbill if (console != NULL) { 1752822Swnj fprintf(console, "\r\nBADDIALUP %s %s\r\n" 1762822Swnj , ttyn+sizeof("/dev/")-1 1772822Swnj , utmp.ut_name); 1781043Sbill fclose(console); 1791043Sbill } 1801043Sbill } 1811043Sbill } 1822822Swnj if (*pwd->pw_shell == '\0') 1832822Swnj pwd->pw_shell = "/bin/sh"; 1842822Swnj i = strlen(pwd->pw_shell); 1852822Swnj if (chdir(pwd->pw_dir) < 0 && !invalid ) { 1862822Swnj if (chdir("/") < 0) { 1872822Swnj printf("No directory!\n"); 1882822Swnj invalid = TRUE; 1892822Swnj } else { 1902822Swnj printf("No directory! Logging in with home=/\n"); 1912822Swnj pwd->pw_dir = "/"; 1922822Swnj } 1931043Sbill } 1942822Swnj } while (invalid); 1951043Sbill 1961043Sbill time(&utmp.ut_time); 1971043Sbill t = ttyslot(); 1981043Sbill if (t>0 && (f = open("/etc/utmp", 1)) >= 0) { 1991043Sbill lseek(f, (long)(t*sizeof(utmp)), 0); 2001043Sbill SCPYN(utmp.ut_line, rindex(ttyn, '/')+1); 2011043Sbill write(f, (char *)&utmp, sizeof(utmp)); 2021043Sbill close(f); 2031043Sbill } 2041043Sbill if (t>0 && (f = open("/usr/adm/wtmp", 1)) >= 0) { 2051043Sbill lseek(f, 0L, 2); 2061043Sbill write(f, (char *)&utmp, sizeof(utmp)); 2071043Sbill close(f); 2081043Sbill } 2092822Swnj quietlog = FALSE; 2102822Swnj if (access(qlog, 0) == 0) 2112822Swnj quietlog = TRUE; 2122822Swnj if ( !quietlog && (f = open(lastlog, 2)) >= 0 ) { 2132822Swnj struct lastlog ll; 2142822Swnj 2152822Swnj lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); 2162822Swnj if (read(f, (char *) &ll, sizeof ll) == sizeof ll && 2172822Swnj ll.ll_time != 0) { 2182822Swnj printf("Last login: %.*s on %.*s\n" 2192822Swnj , 24-5 2202822Swnj , (char *) ctime(&ll.ll_time) 2212822Swnj , sizeof(ll.ll_line) 2222822Swnj , ll.ll_line 2232822Swnj ); 2242822Swnj } 2252822Swnj lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); 2262822Swnj time(&ll.ll_time); 2272822Swnj SCPYN(ll.ll_line, rindex(ttyn, '/')+1); 2282822Swnj write(f, (char *) &ll, sizeof ll); 2292822Swnj close(f); 2302822Swnj } 2311043Sbill chown(ttyn, pwd->pw_uid, pwd->pw_gid); 2321043Sbill setgid(pwd->pw_gid); 2331043Sbill setuid(pwd->pw_uid); 2341043Sbill environ = envinit; 2351043Sbill strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); 2361043Sbill strncat(shell, pwd->pw_shell, sizeof(shell)-7); 2371043Sbill strncat(term, stypeof(ttyn), sizeof(term)-6); 2382822Swnj strncat(user, pwd->pw_name, sizeof(user)-6); 2391043Sbill if ((namep = rindex(pwd->pw_shell, '/')) == NULL) 2401043Sbill namep = pwd->pw_shell; 2411043Sbill else 2421043Sbill namep++; 2431043Sbill strcat(minusnam, namep); 2441043Sbill alarm(0); 2452111Swnj #ifdef ARPAVAX 2462822Swnj if (pwd->pw_gid == 27) /* UGLY ! */ 2472111Swnj umask(2); 2482111Swnj else 2492822Swnj #endif 2502111Swnj umask(022); 2512822Swnj if (ttyn[sizeof("/dev/tty")-1] == 'd') { 2522822Swnj FILE *console = fopen("/dev/console", "w"); 2532822Swnj if (console != NULL) { 2542822Swnj fprintf(console, "\r\nDIALUP %s %s\r\n" 2552822Swnj , ttyn+sizeof("/dev/")-1 2562822Swnj , pwd->pw_name 2572822Swnj ); 2582822Swnj fclose(console); 2592822Swnj } 2601043Sbill } 2612822Swnj if ( !quietlog ) { 2622822Swnj showmotd(); 2632822Swnj strcat(maildir, pwd->pw_name); 2642822Swnj if (access(maildir,4)==0) { 2652822Swnj struct stat statb; 2662822Swnj stat(maildir, &statb); 2672822Swnj if (statb.st_size) 2682822Swnj printf("You have mail.\n"); 2692822Swnj } 2702822Swnj } 2712822Swnj 2721043Sbill signal(SIGQUIT, SIG_DFL); 2731043Sbill signal(SIGINT, SIG_DFL); 274*3935Sroot signal(SIGTSTP, SIG_IGN); 2751043Sbill execlp(pwd->pw_shell, minusnam, 0); 2762822Swnj perror(pwd->pw_shell); 2771043Sbill printf("No shell\n"); 2781043Sbill exit(0); 2791043Sbill } 2801043Sbill 2811043Sbill int stopmotd; 2821043Sbill catch() 2831043Sbill { 2841043Sbill signal(SIGINT, SIG_IGN); 2851043Sbill stopmotd++; 2861043Sbill } 2871043Sbill 2882822Swnj /* 2892822Swnj * return true if OK for root to login on this terminal 2902822Swnj */ 2912822Swnj rootterm(tty) 2922822Swnj char *tty; 2932822Swnj { 2942822Swnj register FILE *fd; 2952822Swnj char buf[100]; 2962822Swnj 2972822Swnj if ((fd = fopen(securetty, "r")) == NULL) 2982822Swnj return(1); 2992822Swnj while (fgets(buf, sizeof buf, fd) != NULL) { 3002822Swnj buf[strlen(buf)-1] = '\0'; 3012822Swnj if (strcmp(tty, buf) == 0) { 3022822Swnj fclose(fd); 3032822Swnj return(1); 3042822Swnj } 3052822Swnj } 3062822Swnj fclose(fd); 3072822Swnj return(0); 3082822Swnj } 3092822Swnj 3101043Sbill showmotd() 3111043Sbill { 3121043Sbill FILE *mf; 3131043Sbill register c; 3141043Sbill 3151043Sbill signal(SIGINT, catch); 3162822Swnj if ((mf = fopen("/etc/motd","r")) != NULL) { 3172822Swnj while ((c = getc(mf)) != EOF && stopmotd == 0) 3181043Sbill putchar(c); 3191043Sbill fclose(mf); 3201043Sbill } 3211043Sbill signal(SIGINT, SIG_IGN); 3221043Sbill } 3231043Sbill 3242822Swnj #undef UNKNOWN 3251043Sbill #define UNKNOWN "su" 3261043Sbill 3271043Sbill char * 3281043Sbill stypeof(ttyid) 3291043Sbill char *ttyid; 3301043Sbill { 3311043Sbill static char typebuf[16]; 3321043Sbill char buf[50]; 3331043Sbill register FILE *f; 3341043Sbill register char *p, *t, *q; 3351043Sbill 3361043Sbill if (ttyid == NULL) 3371043Sbill return (UNKNOWN); 3381043Sbill f = fopen("/etc/ttytype", "r"); 3391043Sbill if (f == NULL) 3401043Sbill return (UNKNOWN); 3411043Sbill /* split off end of name */ 3421043Sbill for (p = q = ttyid; *p != 0; p++) 3431043Sbill if (*p == '/') 3441043Sbill q = p + 1; 3451043Sbill 3461043Sbill /* scan the file */ 3471043Sbill while (fgets(buf, sizeof buf, f) != NULL) 3481043Sbill { 3492822Swnj for (t=buf; *t!=' ' && *t != '\t'; t++) 3501043Sbill ; 3511043Sbill *t++ = 0; 3522822Swnj while (*t == ' ' || *t == '\t') 3532822Swnj t++; 3541043Sbill for (p=t; *p>' '; p++) 3551043Sbill ; 3561043Sbill *p = 0; 3571043Sbill if (strcmp(q,t)==0) { 3581043Sbill strcpy(typebuf, buf); 3591043Sbill fclose(f); 3601043Sbill return (typebuf); 3611043Sbill } 3621043Sbill } 3631043Sbill fclose (f); 3641043Sbill return (UNKNOWN); 3651043Sbill } 366