xref: /original-bsd/usr.bin/login/login.c (revision 6c57d260)
1 static	char *sccsid = "@(#)login.c	4.10 (Berkeley) 81/02/28";
2 /*
3  * login [ name ]
4  */
5 
6 #include <sys/types.h>
7 #include <sgtty.h>
8 #include <utmp.h>
9 #include <signal.h>
10 #include <pwd.h>
11 #include <stdio.h>
12 #include <sys/stat.h>
13 #include <lastlog.h>
14 #include <whoami.h>
15 #ifdef	UNAME
16 #include <sys/utsname.h>
17 #endif
18 
19 #define	SCPYN(a, b)	strncpy(a, b, sizeof(a))
20 
21 #define NMAX sizeof(utmp.ut_name)
22 #define LMAX sizeof(utmp.ut_line)
23 
24 #define	FALSE	0
25 #define	TRUE	-1
26 
27 char	nolog[] =	"/etc/nologin";
28 char	qlog[]  =	".hushlogin";
29 char	securetty[] =	"/etc/securetty";
30 char	maildir[30] =	"/usr/spool/mail/";
31 char	lastlog[] =	"/usr/adm/lastlog";
32 struct	passwd nouser = {"", "nope"};
33 struct	sgttyb ttyb;
34 struct	utmp utmp;
35 char	minusnam[16] = "-";
36 char	homedir[64] = "HOME=";
37 char	shell[64] = "SHELL=";
38 char	term[64] = "TERM=";
39 char	user[20] = "USER=";
40 char	*envinit[] = {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", term, user, 0};
41 struct	passwd *pwd;
42 
43 struct	passwd *getpwnam();
44 char	*strcat();
45 int	setpwent();
46 char	*ttyname();
47 char	*crypt();
48 char	*getpass();
49 char	*rindex();
50 char	*stypeof();
51 extern	char **environ;
52 
53 #define	CTRL(c)	('c'&037)
54 #define	CERASE	'#'
55 #define	CEOT	CTRL(d)
56 #define	CKILL	'@'
57 #define	CQUIT	034		/* FS, cntl shift L */
58 #define	CINTR	0177		/* DEL */
59 #define	CSTOP	CTRL(s)
60 #define	CSTART	CTRL(q)
61 #define	CBRK	0377
62 struct	tchars tc = {
63 	CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK
64 };
65 #ifdef	TIOCLSET
66 struct	ltchars ltc = {
67 	CTRL(z), CTRL(y), CTRL(r), CTRL(o), CTRL(w), CTRL(v)
68 };
69 #endif
70 
71 main(argc, argv)
72 char **argv;
73 {
74 	register char *namep;
75 	int t, f, c;
76 	int invalid;
77 	int quietlog;
78 	int i;
79 	FILE *nlfd;
80 	char *ttyn;
81 	int	ldisc = 0;
82 #ifdef	UNAME
83 	struct utsname uts;
84 #endif
85 
86 	alarm(60);
87 	signal(SIGQUIT, SIG_IGN);
88 	signal(SIGINT, SIG_IGN);
89 	nice(-100);
90 	nice(20);
91 	nice(0);
92 #ifdef	TIOCLSET
93 	ioctl(0, TIOCLSET, 0);
94 #endif
95 	ioctl(0, TIOCNXCL, 0);
96 	gtty(0, &ttyb);
97 	ttyb.sg_erase = CERASE;
98 	ttyb.sg_kill = CKILL;
99 	stty(0, &ttyb);
100 	ioctl(0, TIOCSETC, &tc);
101 #ifdef	TIOCLSET
102 	ioctl(0, TIOCSLTC, &ltc);
103 #endif
104 	for (t=3; t<20; t++)
105 		close(t);
106 	ttyn = ttyname(0);
107 	if (ttyn==(char *)0)
108 		ttyn = "/dev/tty??";
109 
110 	do {
111 		ldisc = 0;
112 		ioctl(0, TIOCSETD, &ldisc);
113 		invalid = FALSE;
114 		SCPYN(utmp.ut_name, "");
115 		if (argc>1) {
116 			SCPYN(utmp.ut_name, argv[1]);
117 			argc = 0;
118 		}
119 		while (utmp.ut_name[0] == '\0') {
120 			namep = utmp.ut_name;
121 #ifdef	UNAME
122 			if (uname(&uts) != -1)
123 				printf("%s login: ", uts.nodename);
124 			else
125 #endif
126 				printf("login: ");
127 			while ((c = getchar()) != '\n') {
128 				if (c == ' ')
129 					c = '_';
130 				if (c == EOF)
131 					exit(0);
132 				if (namep < utmp.ut_name+NMAX)
133 					*namep++ = c;
134 			}
135 		}
136 		setpwent();
137 		if ((pwd = getpwnam(utmp.ut_name)) == NULL)
138 			pwd = &nouser;
139 		endpwent();
140 		if (!strcmp(pwd->pw_shell, "/bin/csh")) {
141 			ldisc = NTTYDISC;
142 			ioctl(0, TIOCSETD, &ldisc);
143 		}
144 		if (*pwd->pw_passwd != '\0') {
145 			nice(-4);
146 			namep = crypt(getpass("Password:"),pwd->pw_passwd);
147 			nice(4);
148 			if (strcmp(namep, pwd->pw_passwd))
149 				invalid = TRUE;
150 		}
151 		if (pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) > 0) {
152 			/* logins are disabled except for root */
153 			while ((c = getc(nlfd)) != EOF)
154 				putchar(c);
155 			fflush(stdout);
156 			sleep(5);
157 			exit(0);
158 		}
159 		if (!invalid && pwd->pw_uid == 0 &&
160 		    !rootterm(ttyn+sizeof("/dev/")-1)) {
161 			FILE *console = fopen("/dev/console", "w");
162 			if (console != NULL) {
163 				fprintf(console, "\r\nROOT LOGIN REFUSED %s\r\n"
164 				    , ttyn+sizeof("/dev/")-1
165 				);
166 				fclose(console);
167 			}
168 			invalid = TRUE;
169 		}
170 		if (invalid) {
171 			printf("Login incorrect\n");
172 			if (ttyn[sizeof("/dev/tty")-1] == 'd') {
173 				FILE *console = fopen("/dev/console", "w");
174 				if (console != NULL) {
175 					fprintf(console, "\r\nBADDIALUP %s %s\r\n"
176 					    , ttyn+sizeof("/dev/")-1
177 					    , utmp.ut_name);
178 					fclose(console);
179 				}
180 			}
181 		}
182 		if (*pwd->pw_shell == '\0')
183 			pwd->pw_shell = "/bin/sh";
184 		i = strlen(pwd->pw_shell);
185 		if (chdir(pwd->pw_dir) < 0 && !invalid ) {
186 			if (chdir("/") < 0) {
187 				printf("No directory!\n");
188 				invalid = TRUE;
189 			} else {
190 				printf("No directory!  Logging in with home=/\n");
191 				pwd->pw_dir = "/";
192 			}
193 		}
194 	} while (invalid);
195 
196 	time(&utmp.ut_time);
197 	t = ttyslot();
198 	if (t>0 && (f = open("/etc/utmp", 1)) >= 0) {
199 		lseek(f, (long)(t*sizeof(utmp)), 0);
200 		SCPYN(utmp.ut_line, rindex(ttyn, '/')+1);
201 		write(f, (char *)&utmp, sizeof(utmp));
202 		close(f);
203 	}
204 	if (t>0 && (f = open("/usr/adm/wtmp", 1)) >= 0) {
205 		lseek(f, 0L, 2);
206 		write(f, (char *)&utmp, sizeof(utmp));
207 		close(f);
208 	}
209 	quietlog = FALSE;
210 	if (access(qlog, 0) == 0)
211 		quietlog = TRUE;
212 	if ( !quietlog && (f = open(lastlog, 2)) >= 0 ) {
213 		struct lastlog ll;
214 
215 		lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0);
216 		if (read(f, (char *) &ll, sizeof ll) == sizeof ll &&
217 		    ll.ll_time != 0) {
218 			printf("Last login: %.*s on %.*s\n"
219 			    , 24-5
220 			    , (char *) ctime(&ll.ll_time)
221 			    , sizeof(ll.ll_line)
222 			    , ll.ll_line
223 			);
224 		}
225 		lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0);
226 		time(&ll.ll_time);
227 		SCPYN(ll.ll_line, rindex(ttyn, '/')+1);
228 		write(f, (char *) &ll, sizeof ll);
229 		close(f);
230 	}
231 	chown(ttyn, pwd->pw_uid, pwd->pw_gid);
232 	setgid(pwd->pw_gid);
233 	setuid(pwd->pw_uid);
234 	environ = envinit;
235 	strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
236 	strncat(shell, pwd->pw_shell, sizeof(shell)-7);
237 	strncat(term, stypeof(ttyn), sizeof(term)-6);
238 	strncat(user, pwd->pw_name, sizeof(user)-6);
239 	if ((namep = rindex(pwd->pw_shell, '/')) == NULL)
240 		namep = pwd->pw_shell;
241 	else
242 		namep++;
243 	strcat(minusnam, namep);
244 	alarm(0);
245 #ifdef ARPAVAX
246 	if (pwd->pw_gid == 27)			/* UGLY ! */
247 		umask(2);
248 	else
249 #endif
250 		umask(022);
251 	if (ttyn[sizeof("/dev/tty")-1] == 'd') {
252 		FILE *console = fopen("/dev/console", "w");
253 		if (console != NULL) {
254 			fprintf(console, "\r\nDIALUP %s %s\r\n"
255 			    , ttyn+sizeof("/dev/")-1
256 			    , pwd->pw_name
257 			);
258 			fclose(console);
259 		}
260 	}
261 	if ( !quietlog ) {
262 		showmotd();
263 		strcat(maildir, pwd->pw_name);
264 		if (access(maildir,4)==0) {
265 			struct stat statb;
266 			stat(maildir, &statb);
267 			if (statb.st_size)
268 				printf("You have mail.\n");
269 		}
270 	}
271 
272 	signal(SIGQUIT, SIG_DFL);
273 	signal(SIGINT, SIG_DFL);
274 	execlp(pwd->pw_shell, minusnam, 0);
275 	perror(pwd->pw_shell);
276 	printf("No shell\n");
277 	exit(0);
278 }
279 
280 int	stopmotd;
281 catch()
282 {
283 	signal(SIGINT, SIG_IGN);
284 	stopmotd++;
285 }
286 
287 /*
288  * return true if OK for root to login on this terminal
289  */
290 rootterm(tty)
291 	char	*tty;
292 {
293 	register FILE *fd;
294 	char	buf[100];
295 
296 	if ((fd = fopen(securetty, "r")) == NULL)
297 		return(1);
298 	while (fgets(buf, sizeof buf, fd) != NULL) {
299 		buf[strlen(buf)-1] = '\0';
300 		if (strcmp(tty, buf) == 0) {
301 			fclose(fd);
302 			return(1);
303 		}
304 	}
305 	fclose(fd);
306 	return(0);
307 }
308 
309 showmotd()
310 {
311 	FILE *mf;
312 	register c;
313 
314 	signal(SIGINT, catch);
315 	if ((mf = fopen("/etc/motd","r")) != NULL) {
316 		while ((c = getc(mf)) != EOF && stopmotd == 0)
317 			putchar(c);
318 		fclose(mf);
319 	}
320 	signal(SIGINT, SIG_IGN);
321 }
322 
323 #undef	UNKNOWN
324 #define UNKNOWN "su"
325 
326 char *
327 stypeof(ttyid)
328 char	*ttyid;
329 {
330 	static char	typebuf[16];
331 	char		buf[50];
332 	register FILE	*f;
333 	register char	*p, *t, *q;
334 
335 	if (ttyid == NULL)
336 		return (UNKNOWN);
337 	f = fopen("/etc/ttytype", "r");
338 	if (f == NULL)
339 		return (UNKNOWN);
340 	/* split off end of name */
341 	for (p = q = ttyid; *p != 0; p++)
342 		if (*p == '/')
343 			q = p + 1;
344 
345 	/* scan the file */
346 	while (fgets(buf, sizeof buf, f) != NULL)
347 	{
348 		for (t=buf; *t!=' ' && *t != '\t'; t++)
349 			;
350 		*t++ = 0;
351 		while (*t == ' ' || *t == '\t')
352 			t++;
353 		for (p=t; *p>' '; p++)
354 			;
355 		*p = 0;
356 		if (strcmp(q,t)==0) {
357 			strcpy(typebuf, buf);
358 			fclose(f);
359 			return (typebuf);
360 		}
361 	}
362 	fclose (f);
363 	return (UNKNOWN);
364 }
365