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