1*2822Swnj static char *sccsid = "@(#)login.c 4.10 (Berkeley) 81/02/28"; 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> 15*2822Swnj #ifdef UNAME 16*2822Swnj #include <sys/utsname.h> 17*2822Swnj #endif 181043Sbill 19*2822Swnj #define SCPYN(a, b) strncpy(a, b, sizeof(a)) 20*2822Swnj 211043Sbill #define NMAX sizeof(utmp.ut_name) 221043Sbill #define LMAX sizeof(utmp.ut_line) 231043Sbill 24*2822Swnj #define FALSE 0 25*2822Swnj #define TRUE -1 26*2822Swnj 27*2822Swnj char nolog[] = "/etc/nologin"; 28*2822Swnj char qlog[] = ".hushlogin"; 29*2822Swnj 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="; 39*2822Swnj char user[20] = "USER="; 40*2822Swnj 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 }; 65*2822Swnj #ifdef TIOCLSET 661365Sbill struct ltchars ltc = { 671546Sbill CTRL(z), CTRL(y), CTRL(r), CTRL(o), CTRL(w), CTRL(v) 681365Sbill }; 69*2822Swnj #endif 701365Sbill 711043Sbill main(argc, argv) 721043Sbill char **argv; 731043Sbill { 741043Sbill register char *namep; 751043Sbill int t, f, c; 76*2822Swnj int invalid; 77*2822Swnj int quietlog; 78*2822Swnj int i; 79*2822Swnj FILE *nlfd; 801043Sbill char *ttyn; 81*2822Swnj int ldisc = 0; 82*2822Swnj #ifdef UNAME 83*2822Swnj struct utsname uts; 84*2822Swnj #endif 851043Sbill 861043Sbill alarm(60); 871043Sbill signal(SIGQUIT, SIG_IGN); 881043Sbill signal(SIGINT, SIG_IGN); 891043Sbill nice(-100); 901043Sbill nice(20); 911043Sbill nice(0); 92*2822Swnj #ifdef TIOCLSET 931043Sbill ioctl(0, TIOCLSET, 0); 94*2822Swnj #endif 951547Sbill ioctl(0, TIOCNXCL, 0); 961043Sbill gtty(0, &ttyb); 97*2822Swnj ttyb.sg_erase = CERASE; 98*2822Swnj ttyb.sg_kill = CKILL; 991043Sbill stty(0, &ttyb); 1001365Sbill ioctl(0, TIOCSETC, &tc); 101*2822Swnj #ifdef TIOCLSET 1021365Sbill ioctl(0, TIOCSLTC, <c); 103*2822Swnj #endif 1041043Sbill for (t=3; t<20; t++) 1051043Sbill close(t); 1061043Sbill ttyn = ttyname(0); 107*2822Swnj if (ttyn==(char *)0) 1081043Sbill ttyn = "/dev/tty??"; 1091043Sbill 110*2822Swnj do { 111*2822Swnj ldisc = 0; 112*2822Swnj ioctl(0, TIOCSETD, &ldisc); 113*2822Swnj invalid = FALSE; 114*2822Swnj SCPYN(utmp.ut_name, ""); 115*2822Swnj if (argc>1) { 116*2822Swnj SCPYN(utmp.ut_name, argv[1]); 117*2822Swnj argc = 0; 1181043Sbill } 119*2822Swnj while (utmp.ut_name[0] == '\0') { 120*2822Swnj namep = utmp.ut_name; 121*2822Swnj #ifdef UNAME 122*2822Swnj if (uname(&uts) != -1) 123*2822Swnj printf("%s login: ", uts.nodename); 124*2822Swnj else 125*2822Swnj #endif 126*2822Swnj printf("login: "); 127*2822Swnj while ((c = getchar()) != '\n') { 128*2822Swnj if (c == ' ') 129*2822Swnj c = '_'; 130*2822Swnj if (c == EOF) 131*2822Swnj exit(0); 132*2822Swnj if (namep < utmp.ut_name+NMAX) 133*2822Swnj *namep++ = c; 134*2822Swnj } 135*2822Swnj } 136*2822Swnj setpwent(); 137*2822Swnj if ((pwd = getpwnam(utmp.ut_name)) == NULL) 138*2822Swnj pwd = &nouser; 139*2822Swnj endpwent(); 140*2822Swnj if (!strcmp(pwd->pw_shell, "/bin/csh")) { 141*2822Swnj ldisc = NTTYDISC; 142*2822Swnj ioctl(0, TIOCSETD, &ldisc); 143*2822Swnj } 144*2822Swnj if (*pwd->pw_passwd != '\0') { 145*2822Swnj nice(-4); 146*2822Swnj namep = crypt(getpass("Password:"),pwd->pw_passwd); 147*2822Swnj nice(4); 148*2822Swnj if (strcmp(namep, pwd->pw_passwd)) 149*2822Swnj invalid = TRUE; 150*2822Swnj } 151*2822Swnj if (pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) > 0) { 152*2822Swnj /* logins are disabled except for root */ 153*2822Swnj while ((c = getc(nlfd)) != EOF) 154*2822Swnj putchar(c); 155*2822Swnj fflush(stdout); 156*2822Swnj sleep(5); 157*2822Swnj exit(0); 158*2822Swnj } 159*2822Swnj if (!invalid && pwd->pw_uid == 0 && 160*2822Swnj !rootterm(ttyn+sizeof("/dev/")-1)) { 161*2822Swnj FILE *console = fopen("/dev/console", "w"); 162*2822Swnj if (console != NULL) { 163*2822Swnj fprintf(console, "\r\nROOT LOGIN REFUSED %s\r\n" 164*2822Swnj , ttyn+sizeof("/dev/")-1 165*2822Swnj ); 166*2822Swnj fclose(console); 167*2822Swnj } 168*2822Swnj invalid = TRUE; 169*2822Swnj } 170*2822Swnj if (invalid) { 1711043Sbill printf("Login incorrect\n"); 172*2822Swnj if (ttyn[sizeof("/dev/tty")-1] == 'd') { 1731043Sbill FILE *console = fopen("/dev/console", "w"); 1741043Sbill if (console != NULL) { 175*2822Swnj fprintf(console, "\r\nBADDIALUP %s %s\r\n" 176*2822Swnj , ttyn+sizeof("/dev/")-1 177*2822Swnj , utmp.ut_name); 1781043Sbill fclose(console); 1791043Sbill } 1801043Sbill } 1811043Sbill } 182*2822Swnj if (*pwd->pw_shell == '\0') 183*2822Swnj pwd->pw_shell = "/bin/sh"; 184*2822Swnj i = strlen(pwd->pw_shell); 185*2822Swnj if (chdir(pwd->pw_dir) < 0 && !invalid ) { 186*2822Swnj if (chdir("/") < 0) { 187*2822Swnj printf("No directory!\n"); 188*2822Swnj invalid = TRUE; 189*2822Swnj } else { 190*2822Swnj printf("No directory! Logging in with home=/\n"); 191*2822Swnj pwd->pw_dir = "/"; 192*2822Swnj } 1931043Sbill } 194*2822Swnj } 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 } 209*2822Swnj quietlog = FALSE; 210*2822Swnj if (access(qlog, 0) == 0) 211*2822Swnj quietlog = TRUE; 212*2822Swnj if ( !quietlog && (f = open(lastlog, 2)) >= 0 ) { 213*2822Swnj struct lastlog ll; 214*2822Swnj 215*2822Swnj lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); 216*2822Swnj if (read(f, (char *) &ll, sizeof ll) == sizeof ll && 217*2822Swnj ll.ll_time != 0) { 218*2822Swnj printf("Last login: %.*s on %.*s\n" 219*2822Swnj , 24-5 220*2822Swnj , (char *) ctime(&ll.ll_time) 221*2822Swnj , sizeof(ll.ll_line) 222*2822Swnj , ll.ll_line 223*2822Swnj ); 224*2822Swnj } 225*2822Swnj lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); 226*2822Swnj time(&ll.ll_time); 227*2822Swnj SCPYN(ll.ll_line, rindex(ttyn, '/')+1); 228*2822Swnj write(f, (char *) &ll, sizeof ll); 229*2822Swnj close(f); 230*2822Swnj } 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); 238*2822Swnj 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 246*2822Swnj if (pwd->pw_gid == 27) /* UGLY ! */ 2472111Swnj umask(2); 2482111Swnj else 249*2822Swnj #endif 2502111Swnj umask(022); 251*2822Swnj if (ttyn[sizeof("/dev/tty")-1] == 'd') { 252*2822Swnj FILE *console = fopen("/dev/console", "w"); 253*2822Swnj if (console != NULL) { 254*2822Swnj fprintf(console, "\r\nDIALUP %s %s\r\n" 255*2822Swnj , ttyn+sizeof("/dev/")-1 256*2822Swnj , pwd->pw_name 257*2822Swnj ); 258*2822Swnj fclose(console); 259*2822Swnj } 2601043Sbill } 261*2822Swnj if ( !quietlog ) { 262*2822Swnj showmotd(); 263*2822Swnj strcat(maildir, pwd->pw_name); 264*2822Swnj if (access(maildir,4)==0) { 265*2822Swnj struct stat statb; 266*2822Swnj stat(maildir, &statb); 267*2822Swnj if (statb.st_size) 268*2822Swnj printf("You have mail.\n"); 269*2822Swnj } 270*2822Swnj } 271*2822Swnj 2721043Sbill signal(SIGQUIT, SIG_DFL); 2731043Sbill signal(SIGINT, SIG_DFL); 2741043Sbill execlp(pwd->pw_shell, minusnam, 0); 275*2822Swnj perror(pwd->pw_shell); 2761043Sbill printf("No shell\n"); 2771043Sbill exit(0); 2781043Sbill } 2791043Sbill 2801043Sbill int stopmotd; 2811043Sbill catch() 2821043Sbill { 2831043Sbill signal(SIGINT, SIG_IGN); 2841043Sbill stopmotd++; 2851043Sbill } 2861043Sbill 287*2822Swnj /* 288*2822Swnj * return true if OK for root to login on this terminal 289*2822Swnj */ 290*2822Swnj rootterm(tty) 291*2822Swnj char *tty; 292*2822Swnj { 293*2822Swnj register FILE *fd; 294*2822Swnj char buf[100]; 295*2822Swnj 296*2822Swnj if ((fd = fopen(securetty, "r")) == NULL) 297*2822Swnj return(1); 298*2822Swnj while (fgets(buf, sizeof buf, fd) != NULL) { 299*2822Swnj buf[strlen(buf)-1] = '\0'; 300*2822Swnj if (strcmp(tty, buf) == 0) { 301*2822Swnj fclose(fd); 302*2822Swnj return(1); 303*2822Swnj } 304*2822Swnj } 305*2822Swnj fclose(fd); 306*2822Swnj return(0); 307*2822Swnj } 308*2822Swnj 3091043Sbill showmotd() 3101043Sbill { 3111043Sbill FILE *mf; 3121043Sbill register c; 3131043Sbill 3141043Sbill signal(SIGINT, catch); 315*2822Swnj if ((mf = fopen("/etc/motd","r")) != NULL) { 316*2822Swnj while ((c = getc(mf)) != EOF && stopmotd == 0) 3171043Sbill putchar(c); 3181043Sbill fclose(mf); 3191043Sbill } 3201043Sbill signal(SIGINT, SIG_IGN); 3211043Sbill } 3221043Sbill 323*2822Swnj #undef UNKNOWN 3241043Sbill #define UNKNOWN "su" 3251043Sbill 3261043Sbill char * 3271043Sbill stypeof(ttyid) 3281043Sbill char *ttyid; 3291043Sbill { 3301043Sbill static char typebuf[16]; 3311043Sbill char buf[50]; 3321043Sbill register FILE *f; 3331043Sbill register char *p, *t, *q; 3341043Sbill 3351043Sbill if (ttyid == NULL) 3361043Sbill return (UNKNOWN); 3371043Sbill f = fopen("/etc/ttytype", "r"); 3381043Sbill if (f == NULL) 3391043Sbill return (UNKNOWN); 3401043Sbill /* split off end of name */ 3411043Sbill for (p = q = ttyid; *p != 0; p++) 3421043Sbill if (*p == '/') 3431043Sbill q = p + 1; 3441043Sbill 3451043Sbill /* scan the file */ 3461043Sbill while (fgets(buf, sizeof buf, f) != NULL) 3471043Sbill { 348*2822Swnj for (t=buf; *t!=' ' && *t != '\t'; t++) 3491043Sbill ; 3501043Sbill *t++ = 0; 351*2822Swnj while (*t == ' ' || *t == '\t') 352*2822Swnj t++; 3531043Sbill for (p=t; *p>' '; p++) 3541043Sbill ; 3551043Sbill *p = 0; 3561043Sbill if (strcmp(q,t)==0) { 3571043Sbill strcpy(typebuf, buf); 3581043Sbill fclose(f); 3591043Sbill return (typebuf); 3601043Sbill } 3611043Sbill } 3621043Sbill fclose (f); 3631043Sbill return (UNKNOWN); 3641043Sbill } 365