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