1static char *sccsid = "@(#)login.c.1 4.11 (Berkeley) 81/07/05"; 2/* 3 * login [ name ] 4 */ 5 6#include <sys/types.h> 7#include <sgtty.h> 8#include <utmp.h> 9#include <signal.h> 10#include <pwd.h> 11#include <stdio.h> 12#include <sys/stat.h> 13#include <lastlog.h> 14#include <whoami.h> 15#ifdef UNAME 16#include <sys/utsname.h> 17#endif 18 19#define SCPYN(a, b) strncpy(a, b, sizeof(a)) 20 21#define NMAX sizeof(utmp.ut_name) 22#define LMAX sizeof(utmp.ut_line) 23 24#define FALSE 0 25#define TRUE -1 26 27char nolog[] = "/etc/nologin"; 28char qlog[] = ".hushlogin"; 29char securetty[] = "/etc/securetty"; 30char maildir[30] = "/usr/spool/mail/"; 31char lastlog[] = "/usr/adm/lastlog"; 32struct passwd nouser = {"", "nope"}; 33struct sgttyb ttyb; 34struct utmp utmp; 35char minusnam[16] = "-"; 36char homedir[64] = "HOME="; 37char shell[64] = "SHELL="; 38char term[64] = "TERM="; 39char user[20] = "USER="; 40char *envinit[] = {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", term, user, 0}; 41struct passwd *pwd; 42 43struct passwd *getpwnam(); 44char *strcat(); 45int setpwent(); 46char *ttyname(); 47char *crypt(); 48char *getpass(); 49char *rindex(); 50char *stypeof(); 51extern char **environ; 52 53#define CTRL(c) ('c'&037) 54#define CERASE '#' 55#define CEOT CTRL(d) 56#define CKILL '@' 57#define CQUIT 034 /* FS, cntl shift L */ 58#define CINTR 0177 /* DEL */ 59#define CSTOP CTRL(s) 60#define CSTART CTRL(q) 61#define CBRK 0377 62struct tchars tc = { 63 CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK 64}; 65#ifdef TIOCLSET 66struct ltchars ltc = { 67 CTRL(z), CTRL(y), CTRL(r), CTRL(o), CTRL(w), CTRL(v) 68}; 69#endif 70 71main(argc, argv) 72char **argv; 73{ 74 register char *namep; 75 int t, f, c; 76 int invalid; 77 int quietlog; 78 int i; 79 FILE *nlfd; 80 char *ttyn; 81 int ldisc = 0; 82#ifdef UNAME 83 struct utsname uts; 84#endif 85 86 alarm(60); 87 signal(SIGQUIT, SIG_IGN); 88 signal(SIGINT, SIG_IGN); 89 nice(-100); 90 nice(20); 91 nice(0); 92#ifdef TIOCLSET 93 ioctl(0, TIOCLSET, 0); 94#endif 95 ioctl(0, TIOCNXCL, 0); 96 gtty(0, &ttyb); 97 ttyb.sg_erase = CERASE; 98 ttyb.sg_kill = CKILL; 99 stty(0, &ttyb); 100 ioctl(0, TIOCSETC, &tc); 101#ifdef TIOCLSET 102 ioctl(0, TIOCSLTC, <c); 103#endif 104 for (t=3; t<20; t++) 105 close(t); 106 ttyn = ttyname(0); 107 if (ttyn==(char *)0) 108 ttyn = "/dev/tty??"; 109 110 do { 111 ldisc = 0; 112 ioctl(0, TIOCSETD, &ldisc); 113 invalid = FALSE; 114 SCPYN(utmp.ut_name, ""); 115 if (argc>1) { 116 SCPYN(utmp.ut_name, argv[1]); 117 argc = 0; 118 } 119 while (utmp.ut_name[0] == '\0') { 120 namep = utmp.ut_name; 121#ifdef UNAME 122 if (uname(&uts) != -1) 123 printf("%s login: ", uts.nodename); 124 else 125#endif 126 printf("login: "); 127 while ((c = getchar()) != '\n') { 128 if (c == ' ') 129 c = '_'; 130 if (c == EOF) 131 exit(0); 132 if (namep < utmp.ut_name+NMAX) 133 *namep++ = c; 134 } 135 } 136 setpwent(); 137 if ((pwd = getpwnam(utmp.ut_name)) == NULL) 138 pwd = &nouser; 139 endpwent(); 140 if (!strcmp(pwd->pw_shell, "/bin/csh")) { 141 ldisc = NTTYDISC; 142 ioctl(0, TIOCSETD, &ldisc); 143 } 144 if (*pwd->pw_passwd != '\0') { 145 nice(-4); 146 namep = crypt(getpass("Password:"),pwd->pw_passwd); 147 nice(4); 148 if (strcmp(namep, pwd->pw_passwd)) 149 invalid = TRUE; 150 } 151 if (pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) > 0) { 152 /* logins are disabled except for root */ 153 while ((c = getc(nlfd)) != EOF) 154 putchar(c); 155 fflush(stdout); 156 sleep(5); 157 exit(0); 158 } 159 if (!invalid && pwd->pw_uid == 0 && 160 !rootterm(ttyn+sizeof("/dev/")-1)) { 161 FILE *console = fopen("/dev/console", "w"); 162 if (console != NULL) { 163 fprintf(console, "\r\nROOT LOGIN REFUSED %s\r\n" 164 , ttyn+sizeof("/dev/")-1 165 ); 166 fclose(console); 167 } 168 invalid = TRUE; 169 } 170 if (invalid) { 171 printf("Login incorrect\n"); 172 if (ttyn[sizeof("/dev/tty")-1] == 'd') { 173 FILE *console = fopen("/dev/console", "w"); 174 if (console != NULL) { 175 fprintf(console, "\r\nBADDIALUP %s %s\r\n" 176 , ttyn+sizeof("/dev/")-1 177 , utmp.ut_name); 178 fclose(console); 179 } 180 } 181 } 182 if (*pwd->pw_shell == '\0') 183 pwd->pw_shell = "/bin/sh"; 184 i = strlen(pwd->pw_shell); 185 if (chdir(pwd->pw_dir) < 0 && !invalid ) { 186 if (chdir("/") < 0) { 187 printf("No directory!\n"); 188 invalid = TRUE; 189 } else { 190 printf("No directory! Logging in with home=/\n"); 191 pwd->pw_dir = "/"; 192 } 193 } 194 } while (invalid); 195 196 time(&utmp.ut_time); 197 t = ttyslot(); 198 if (t>0 && (f = open("/etc/utmp", 1)) >= 0) { 199 lseek(f, (long)(t*sizeof(utmp)), 0); 200 SCPYN(utmp.ut_line, rindex(ttyn, '/')+1); 201 write(f, (char *)&utmp, sizeof(utmp)); 202 close(f); 203 } 204 if (t>0 && (f = open("/usr/adm/wtmp", 1)) >= 0) { 205 lseek(f, 0L, 2); 206 write(f, (char *)&utmp, sizeof(utmp)); 207 close(f); 208 } 209 quietlog = FALSE; 210 if (access(qlog, 0) == 0) 211 quietlog = TRUE; 212 if ( !quietlog && (f = open(lastlog, 2)) >= 0 ) { 213 struct lastlog ll; 214 215 lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); 216 if (read(f, (char *) &ll, sizeof ll) == sizeof ll && 217 ll.ll_time != 0) { 218 printf("Last login: %.*s on %.*s\n" 219 , 24-5 220 , (char *) ctime(&ll.ll_time) 221 , sizeof(ll.ll_line) 222 , ll.ll_line 223 ); 224 } 225 lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); 226 time(&ll.ll_time); 227 SCPYN(ll.ll_line, rindex(ttyn, '/')+1); 228 write(f, (char *) &ll, sizeof ll); 229 close(f); 230 } 231 chown(ttyn, pwd->pw_uid, pwd->pw_gid); 232 setgid(pwd->pw_gid); 233 setuid(pwd->pw_uid); 234 environ = envinit; 235 strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); 236 strncat(shell, pwd->pw_shell, sizeof(shell)-7); 237 strncat(term, stypeof(ttyn), sizeof(term)-6); 238 strncat(user, pwd->pw_name, sizeof(user)-6); 239 if ((namep = rindex(pwd->pw_shell, '/')) == NULL) 240 namep = pwd->pw_shell; 241 else 242 namep++; 243 strcat(minusnam, namep); 244 alarm(0); 245#ifdef ARPAVAX 246 if (pwd->pw_gid == 27) /* UGLY ! */ 247 umask(2); 248 else 249#endif 250 umask(022); 251 if (ttyn[sizeof("/dev/tty")-1] == 'd') { 252 FILE *console = fopen("/dev/console", "w"); 253 if (console != NULL) { 254 fprintf(console, "\r\nDIALUP %s %s\r\n" 255 , ttyn+sizeof("/dev/")-1 256 , pwd->pw_name 257 ); 258 fclose(console); 259 } 260 } 261 if ( !quietlog ) { 262 showmotd(); 263 strcat(maildir, pwd->pw_name); 264 if (access(maildir,4)==0) { 265 struct stat statb; 266 stat(maildir, &statb); 267 if (statb.st_size) 268 printf("You have mail.\n"); 269 } 270 } 271 272 signal(SIGQUIT, SIG_DFL); 273 signal(SIGINT, SIG_DFL); 274 signal(SIGTSTP, SIG_IGN); 275 execlp(pwd->pw_shell, minusnam, 0); 276 perror(pwd->pw_shell); 277 printf("No shell\n"); 278 exit(0); 279} 280 281int stopmotd; 282catch() 283{ 284 signal(SIGINT, SIG_IGN); 285 stopmotd++; 286} 287 288/* 289 * return true if OK for root to login on this terminal 290 */ 291rootterm(tty) 292 char *tty; 293{ 294 register FILE *fd; 295 char buf[100]; 296 297 if ((fd = fopen(securetty, "r")) == NULL) 298 return(1); 299 while (fgets(buf, sizeof buf, fd) != NULL) { 300 buf[strlen(buf)-1] = '\0'; 301 if (strcmp(tty, buf) == 0) { 302 fclose(fd); 303 return(1); 304 } 305 } 306 fclose(fd); 307 return(0); 308} 309 310showmotd() 311{ 312 FILE *mf; 313 register c; 314 315 signal(SIGINT, catch); 316 if ((mf = fopen("/etc/motd","r")) != NULL) { 317 while ((c = getc(mf)) != EOF && stopmotd == 0) 318 putchar(c); 319 fclose(mf); 320 } 321 signal(SIGINT, SIG_IGN); 322} 323 324#undef UNKNOWN 325#define UNKNOWN "su" 326 327char * 328stypeof(ttyid) 329char *ttyid; 330{ 331 static char typebuf[16]; 332 char buf[50]; 333 register FILE *f; 334 register char *p, *t, *q; 335 336 if (ttyid == NULL) 337 return (UNKNOWN); 338 f = fopen("/etc/ttytype", "r"); 339 if (f == NULL) 340 return (UNKNOWN); 341 /* split off end of name */ 342 for (p = q = ttyid; *p != 0; p++) 343 if (*p == '/') 344 q = p + 1; 345 346 /* scan the file */ 347 while (fgets(buf, sizeof buf, f) != NULL) 348 { 349 for (t=buf; *t!=' ' && *t != '\t'; t++) 350 ; 351 *t++ = 0; 352 while (*t == ' ' || *t == '\t') 353 t++; 354 for (p=t; *p>' '; p++) 355 ; 356 *p = 0; 357 if (strcmp(q,t)==0) { 358 strcpy(typebuf, buf); 359 fclose(f); 360 return (typebuf); 361 } 362 } 363 fclose (f); 364 return (UNKNOWN); 365} 366