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