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