1#ifndef lint 2static char *sccsid = "@(#)login.c.1 4.35 (Berkeley) 85/01/08"; 3#endif 4 5/* 6 * login [ name ] 7 * login -r hostname (for rlogind) 8 * login -h hostname (for telnetd, etc.) 9 */ 10 11#include <sys/param.h> 12#include <sys/quota.h> 13#include <sys/stat.h> 14#include <sys/time.h> 15#include <sys/resource.h> 16#include <sys/file.h> 17 18#include <sgtty.h> 19#include <utmp.h> 20#include <signal.h> 21#include <pwd.h> 22#include <stdio.h> 23#include <lastlog.h> 24#include <errno.h> 25#include <ttyent.h> 26#include <syslog.h> 27 28#define SCMPN(a, b) strncmp(a, b, sizeof(a)) 29#define SCPYN(a, b) strncpy(a, b, sizeof(a)) 30 31#define NMAX sizeof(utmp.ut_name) 32 33#define FALSE 0 34#define TRUE -1 35 36char nolog[] = "/etc/nologin"; 37char qlog[] = ".hushlogin"; 38char maildir[30] = "/usr/spool/mail/"; 39char lastlog[] = "/usr/adm/lastlog"; 40struct passwd nouser = {"", "nope", -1, -1, -1, "", "", "", "" }; 41struct sgttyb ttyb; 42struct utmp utmp; 43char minusnam[16] = "-"; 44/* 45 * This bounds the time given to login. We initialize it here 46 * so it can be patched on machines where it's too small. 47 */ 48int timeout = 60; 49 50char homedir[64] = "HOME="; 51char shell[64] = "SHELL="; 52char term[64] = "TERM="; 53char user[20] = "USER="; 54 55char *envinit[] = 56 { homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", term, user, 0 }; 57 58struct passwd *pwd; 59char *strcat(), *rindex(), *index(); 60int timedout(); 61char *ttyname(); 62char *crypt(); 63char *getpass(); 64char *stypeof(); 65extern char **environ; 66extern int errno; 67 68struct tchars tc = { 69 CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK 70}; 71struct ltchars ltc = { 72 CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT 73}; 74 75int rflag; 76char rusername[NMAX+1], lusername[NMAX+1]; 77char rpassword[NMAX+1]; 78char name[NMAX+1]; 79char *rhost; 80 81main(argc, argv) 82 char *argv[]; 83{ 84 register char *namep; 85 int t, f, c; 86 int invalid, quietlog; 87 FILE *nlfd; 88 char *ttyn, *tty; 89 int ldisc = 0, zero = 0; 90 91 signal(SIGALRM, timedout); 92 alarm(timeout); 93 signal(SIGQUIT, SIG_IGN); 94 signal(SIGINT, SIG_IGN); 95 setpriority(PRIO_PROCESS, 0, 0); 96 quota(Q_SETUID, 0, 0, 0); 97 /* 98 * -r is used by rlogind to cause the autologin protocol; 99 * -h is used by other servers to pass the name of the 100 * remote host to login so that it may be placed in utmp and wtmp 101 */ 102 if (argc > 1) { 103 if (strcmp(argv[1], "-r") == 0) { 104 rflag = doremotelogin(argv[2]); 105 SCPYN(utmp.ut_host, argv[2]); 106 argc = 0; 107 } 108 if (strcmp(argv[1], "-h") == 0 && getuid() == 0) { 109 SCPYN(utmp.ut_host, argv[2]); 110 argc = 0; 111 } 112 } 113 ioctl(0, TIOCLSET, &zero); 114 ioctl(0, TIOCNXCL, 0); 115 ioctl(0, FIONBIO, &zero); 116 ioctl(0, FIOASYNC, &zero); 117 ioctl(0, TIOCGETP, &ttyb); 118 /* 119 * If talking to an rlogin process, 120 * propagate the terminal type and 121 * baud rate across the network. 122 */ 123 if (rflag) 124 doremoteterm(term, &ttyb); 125 ioctl(0, TIOCSLTC, <c); 126 ioctl(0, TIOCSETC, &tc); 127 ioctl(0, TIOCSETP, &ttyb); 128 for (t = getdtablesize(); t > 3; t--) 129 close(t); 130 ttyn = ttyname(0); 131 if (ttyn == (char *)0) 132 ttyn = "/dev/tty??"; 133 tty = rindex(ttyn, '/'); 134 if (tty == NULL) 135 tty = ttyn; 136 else 137 tty++; 138 openlog("login", 0, 0); 139 t = 0; 140 do { 141 ldisc = 0; 142 ioctl(0, TIOCSETD, &ldisc); 143 invalid = FALSE; 144 SCPYN(utmp.ut_name, ""); 145 /* 146 * Name specified, take it. 147 */ 148 if (argc > 1) { 149 SCPYN(utmp.ut_name, argv[1]); 150 argc = 0; 151 } 152 /* 153 * If remote login take given name, 154 * otherwise prompt user for something. 155 */ 156 if (rflag) { 157 SCPYN(utmp.ut_name, lusername); 158 /* autologin failed, prompt for passwd */ 159 if (rflag == -1) 160 rflag = 0; 161 } else 162 getloginname(&utmp); 163 if (!strcmp(pwd->pw_shell, "/bin/csh")) { 164 ldisc = NTTYDISC; 165 ioctl(0, TIOCSETD, &ldisc); 166 } 167 /* 168 * If no remote login authentication and 169 * a password exists for this user, prompt 170 * for one and verify it. 171 */ 172 if (!rflag && *pwd->pw_passwd != '\0') { 173 char *pp; 174 175 setpriority(PRIO_PROCESS, 0, -4); 176 pp = getpass("Password:"); 177 namep = crypt(pp, pwd->pw_passwd); 178 setpriority(PRIO_PROCESS, 0, 0); 179 if (strcmp(namep, pwd->pw_passwd)) 180 invalid = TRUE; 181 } 182 /* 183 * If user not super-user, check for logins disabled. 184 */ 185 if (pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) > 0) { 186 while ((c = getc(nlfd)) != EOF) 187 putchar(c); 188 fflush(stdout); 189 sleep(5); 190 exit(0); 191 } 192 /* 193 * If valid so far and root is logging in, 194 * see if root logins on this terminal are permitted. 195 */ 196 if (!invalid && pwd->pw_uid == 0 && !rootterm(tty)) { 197 syslog(LOG_INFO, "ROOT LOGIN REFUSED %s", tty); 198 invalid = TRUE; 199 } 200 if (invalid) { 201 printf("Login incorrect\n"); 202 if (++t >= 5) { 203 syslog(LOG_INFO, 204 "REPEATED LOGIN FAILURES %s, %s", 205 tty, utmp.ut_name); 206 ioctl(0, TIOCHPCL, (struct sgttyb *) 0); 207 close(0); 208 close(1); 209 close(2); 210 sleep(10); 211 exit(1); 212 } 213 } 214 if (*pwd->pw_shell == '\0') 215 pwd->pw_shell = "/bin/sh"; 216 if (chdir(pwd->pw_dir) < 0 && !invalid ) { 217 if (chdir("/") < 0) { 218 printf("No directory!\n"); 219 invalid = TRUE; 220 } else { 221 printf("No directory! %s\n", 222 "Logging in with home=/"); 223 pwd->pw_dir = "/"; 224 } 225 } 226 /* 227 * Remote login invalid must have been because 228 * of a restriction of some sort, no extra chances. 229 */ 230 if (rflag && invalid) 231 exit(1); 232 } while (invalid); 233/* committed to login turn off timeout */ 234 alarm(0); 235 236 if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0) { 237 if (errno == EUSERS) 238 printf("%s.\n%s.\n", 239 "Too many users logged on already", 240 "Try again later"); 241 else if (errno == EPROCLIM) 242 printf("You have too many processes running.\n"); 243 else 244 perror("quota (Q_SETUID)"); 245 sleep(5); 246 exit(0); 247 } 248 time(&utmp.ut_time); 249 t = ttyslot(); 250 if (t > 0 && (f = open("/etc/utmp", O_WRONLY)) >= 0) { 251 lseek(f, (long)(t*sizeof(utmp)), 0); 252 SCPYN(utmp.ut_line, tty); 253 write(f, (char *)&utmp, sizeof(utmp)); 254 close(f); 255 } 256 if ((f = open("/usr/adm/wtmp", O_WRONLY|O_APPEND)) >= 0) { 257 write(f, (char *)&utmp, sizeof(utmp)); 258 close(f); 259 } 260 quietlog = access(qlog, F_OK) == 0; 261 if ((f = open(lastlog, O_RDWR)) >= 0) { 262 struct lastlog ll; 263 264 lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); 265 if (read(f, (char *) &ll, sizeof ll) == sizeof ll && 266 ll.ll_time != 0 && !quietlog) { 267 printf("Last login: %.*s ", 268 24-5, (char *)ctime(&ll.ll_time)); 269 if (*ll.ll_host != '\0') 270 printf("from %.*s\n", 271 sizeof (ll.ll_host), ll.ll_host); 272 else 273 printf("on %.*s\n", 274 sizeof (ll.ll_line), ll.ll_line); 275 } 276 lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); 277 time(&ll.ll_time); 278 SCPYN(ll.ll_line, tty); 279 SCPYN(ll.ll_host, utmp.ut_host); 280 write(f, (char *) &ll, sizeof ll); 281 close(f); 282 } 283 chown(ttyn, pwd->pw_uid, pwd->pw_gid); 284 chmod(ttyn, 0622); 285 setgid(pwd->pw_gid); 286 strncpy(name, utmp.ut_name, NMAX); 287 name[NMAX] = '\0'; 288 initgroups(name, pwd->pw_gid); 289 quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0); 290 setuid(pwd->pw_uid); 291 environ = envinit; 292 strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); 293 strncat(shell, pwd->pw_shell, sizeof(shell)-7); 294 if (term[sizeof("TERM=")-1] == 0) 295 strncat(term, stypeof(tty), sizeof(term)-6); 296 strncat(user, pwd->pw_name, sizeof(user)-6); 297 if ((namep = rindex(pwd->pw_shell, '/')) == NULL) 298 namep = pwd->pw_shell; 299 else 300 namep++; 301 strcat(minusnam, namep); 302 if (tty[sizeof("tty")-1] == 'd') 303 syslog(LOG_INFO, "DIALUP %s %s", tty, pwd->pw_name); 304 if (!quietlog) { 305 struct stat st; 306 showmotd(); 307 strcat(maildir, pwd->pw_name); 308 if (stat(maildir, &st) == 0 && st.st_size != 0) 309 printf("You have %smail.\n", 310 (st.st_mtime > st.st_atime) ? "new" : ""); 311 } 312 signal(SIGALRM, SIG_DFL); 313 signal(SIGQUIT, SIG_DFL); 314 signal(SIGINT, SIG_DFL); 315 signal(SIGTSTP, SIG_IGN); 316 execlp(pwd->pw_shell, minusnam, 0); 317 perror(pwd->pw_shell); 318 printf("No shell\n"); 319 exit(0); 320} 321 322getloginname(up) 323 register struct utmp *up; 324{ 325 register char *namep; 326 char c; 327 328 while (up->ut_name[0] == '\0') { 329 namep = up->ut_name; 330 printf("login: "); 331 while ((c = getchar()) != '\n') { 332 if (c == ' ') 333 c = '_'; 334 if (c == EOF) 335 exit(0); 336 if (namep < up->ut_name+NMAX) 337 *namep++ = c; 338 } 339 } 340 strncpy(lusername, up->ut_name, NMAX); 341 lusername[NMAX] = 0; 342 if ((pwd = getpwnam(lusername)) == NULL) 343 pwd = &nouser; 344} 345 346timedout() 347{ 348 349 printf("Login timed out after %d seconds\n", timeout); 350 exit(0); 351} 352 353int stopmotd; 354catch() 355{ 356 357 signal(SIGINT, SIG_IGN); 358 stopmotd++; 359} 360 361rootterm(tty) 362 char *tty; 363{ 364 register struct ttyent *t; 365 366 if ((t = getttynam(tty)) != NULL) { 367 if (t->ty_status & TTY_SECURE) 368 return (1); 369 } 370 return (0); 371} 372 373showmotd() 374{ 375 FILE *mf; 376 register c; 377 378 signal(SIGINT, catch); 379 if ((mf = fopen("/etc/motd", "r")) != NULL) { 380 while ((c = getc(mf)) != EOF && stopmotd == 0) 381 putchar(c); 382 fclose(mf); 383 } 384 signal(SIGINT, SIG_IGN); 385} 386 387#undef UNKNOWN 388#define UNKNOWN "su" 389 390char * 391stypeof(ttyid) 392 char *ttyid; 393{ 394 register struct ttyent *t; 395 396 if (ttyid == NULL || (t = getttynam(ttyid)) == NULL) 397 return (UNKNOWN); 398 return (t->ty_type); 399} 400 401doremotelogin(host) 402 char *host; 403{ 404 FILE *hostf; 405 int first = 1; 406 407 getstr(rusername, sizeof (rusername), "remuser"); 408 getstr(lusername, sizeof (lusername), "locuser"); 409 getstr(term+5, sizeof(term)-5, "Terminal type"); 410 if (getuid()) { 411 pwd = &nouser; 412 goto bad; 413 } 414 pwd = getpwnam(lusername); 415 if (pwd == NULL) { 416 pwd = &nouser; 417 goto bad; 418 } 419 hostf = pwd->pw_uid ? fopen("/etc/hosts.equiv", "r") : 0; 420again: 421 if (hostf) { 422 char ahost[32]; 423 424 while (fgets(ahost, sizeof (ahost), hostf)) { 425 char *user; 426 427 if ((user = index(ahost, '\n')) != 0) 428 *user++ = '\0'; 429 if ((user = index(ahost, ' ')) != 0) 430 *user++ = '\0'; 431 if (!strcmp(host, ahost) && 432 !strcmp(rusername, user ? user : lusername)) { 433 fclose(hostf); 434 return (1); 435 } 436 } 437 fclose(hostf); 438 } 439 if (first == 1) { 440 char *rhosts = ".rhosts"; 441 struct stat sbuf; 442 443 first = 0; 444 if (chdir(pwd->pw_dir) < 0) 445 goto again; 446 if (lstat(rhosts, &sbuf) < 0) 447 goto again; 448 if ((sbuf.st_mode & S_IFMT) == S_IFLNK) { 449 printf("login: .rhosts is a soft link.\r\n"); 450 goto bad; 451 } 452 hostf = fopen(rhosts, "r"); 453 fstat(fileno(hostf), &sbuf); 454 if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) { 455 printf("login: Bad .rhosts ownership.\r\n"); 456 fclose(hostf); 457 goto bad; 458 } 459 goto again; 460 } 461bad: 462 return (-1); 463} 464 465getstr(buf, cnt, err) 466 char *buf; 467 int cnt; 468 char *err; 469{ 470 char c; 471 472 do { 473 if (read(0, &c, 1) != 1) 474 exit(1); 475 if (--cnt < 0) { 476 printf("%s too long\r\n", err); 477 exit(1); 478 } 479 *buf++ = c; 480 } while (c != 0); 481} 482 483char *speeds[] = 484 { "0", "50", "75", "110", "134", "150", "200", "300", 485 "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" }; 486#define NSPEEDS (sizeof (speeds) / sizeof (speeds[0])) 487 488doremoteterm(term, tp) 489 char *term; 490 struct sgttyb *tp; 491{ 492 char *cp = index(term, '/'); 493 register int i; 494 495 if (cp) { 496 *cp++ = 0; 497 for (i = 0; i < NSPEEDS; i++) 498 if (!strcmp(speeds[i], cp)) { 499 tp->sg_ispeed = tp->sg_ospeed = i; 500 break; 501 } 502 } 503 tp->sg_flags = ECHO|CRMOD|ANYP|XTABS; 504} 505