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