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