1 /*-
2  * Copyright (c) 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 char copyright[] =
10 "@(#) Copyright (c) 1990 The Regents of the University of California.\n\
11  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)sliplogin.c	5.3 (Berkeley) 07/01/90";
16 #endif /* not lint */
17 
18 /*
19  * sliplogin.c
20  * [MUST BE RUN SUID, SLOPEN DOES A SUSER()!]
21  *
22  * This program initializes its own tty port to be an async TCP/IP interface.
23  * It sets the line discipline to slip, invokes a shell script to initialize
24  * the network interface, then pauses forever waiting for hangup.
25  *
26  * It is a remote descendant of several similar programs with incestuous ties:
27  * - Kirk Smith's slipconf, modified by Richard Johnsson @ DEC WRL.
28  * - slattach, probably by Rick Adams but touched by countless hordes.
29  * - the original sliplogin for 4.2bsd, Doug Kingston the mover behind it.
30  *
31  * There are two forms of usage:
32  *
33  * "sliplogin"
34  * Invoked simply as "sliplogin" and a realuid != 0, the program looks up
35  * the uid in /etc/passwd, and then the username in the file /etc/hosts.slip.
36  * If and entry is found, the line on fd0 is configured for SLIP operation
37  * as specified in the file.
38  *
39  * "sliplogin IPhost1 </dev/ttyb"
40  * Invoked by root with a username, the name is looked up in the
41  * /etc/hosts.slip file and if found fd0 is configured as in case 1.
42  */
43 
44 #include <sys/param.h>
45 #include <sys/socket.h>
46 #include <sys/ioctl.h>
47 #include <sys/signal.h>
48 #include <sys/file.h>
49 #include <sys/syslog.h>
50 #include <netdb.h>
51 
52 #if defined(BSD4_4)
53 #define TERMIOS
54 #endif
55 #ifdef TERMIOS
56 #include <sys/termios.h>
57 #include <ttyent.h>
58 #endif
59 #include <netinet/in.h>
60 #include <net/if.h>
61 #include <net/if_slvar.h>
62 
63 #include <stdio.h>
64 #include <errno.h>
65 #include <ctype.h>
66 #include <string.h>
67 #include "pathnames.h"
68 
69 int	unit;
70 int	slip_mode;
71 int	speed;
72 char	loginargs[BUFSIZ];
73 char	loginfile[BUFSIZ];
74 char	logoutfile[BUFSIZ];
75 char	loginname[BUFSIZ];
76 
77 struct slip_modes {
78 	char	*sm_name;
79 	int	sm_value;
80 }	 modes[] = {
81 	"normal",	0,
82 	"compress",	SC_COMPRESS,
83 	"noicmp",	SC_NOICMP,
84 	"autocomp",	SC_AUTOCOMP
85 };
86 
87 void
88 findid(name)
89 	char *name;
90 {
91 	FILE *fp;
92 	static char slopt[5][16];
93 	static char laddr[16];
94 	static char raddr[16];
95 	static char mask[16];
96 	char user[16];
97 	int i, j, n;
98 
99 	(void)strcpy(loginname, name);
100 	if ((fp = fopen(_PATH_ACCESS, "r")) == NULL) {
101 		(void)fprintf(stderr, "sliplogin: %s: %s\n",
102 		    _PATH_ACCESS, strerror(errno));
103 		syslog(LOG_ERR, "%s: %m\n", _PATH_ACCESS);
104 		exit(1);
105 	}
106 	while (fgets(loginargs, sizeof(loginargs) - 1, fp)) {
107 		if (ferror(fp))
108 			break;
109 		n = sscanf(loginargs, "%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s\n",
110                         user, laddr, raddr, mask, slopt[0], slopt[1],
111 			slopt[2], slopt[3], slopt[4]);
112 		if (user[0] == '#' || isspace(user[0]))
113 			continue;
114 		if (strcmp(user, name) != 0)
115 			continue;
116 
117 		slip_mode = 0;
118 		for (i = 0; i < n - 4; i++) {
119 			for (j = 0; j < sizeof(modes)/sizeof(struct slip_modes);
120 				j++) {
121 				if (strcmp(modes[j].sm_name, slopt[i]) == 0) {
122 					slip_mode |= modes[j].sm_value;
123 					break;
124 				}
125 			}
126 		}
127 
128 		/*
129 		 * we've found the guy we're looking for -- see if
130 		 * there's a login file we can use.  First check for
131 		 * one specific to this host.  If none found, try for
132 		 * a generic one.
133 		 */
134 		(void)sprintf(loginfile, "%s.%s", _PATH_LOGIN, name);
135 		if (access(loginfile, R_OK|X_OK)) {
136 			(void)strcpy(loginfile, _PATH_LOGIN);
137 			(void)strcpy(logoutfile, _PATH_LOGOUT);
138 			if (access(loginfile, R_OK|X_OK)) {
139 				fputs("access denied - no login file\n",
140 				      stderr);
141 				syslog(LOG_ERR,
142 				       "access denied for %s - no %s\n",
143 				       name, _PATH_LOGIN);
144 				exit(5);
145 			}
146 		} else
147 			(void)sprintf(logoutfile, "%s.%s", _PATH_LOGOUT, name);
148 
149 		(void) fclose(fp);
150 		return;
151 	}
152 	(void)fprintf(stderr, "SLIP access denied for %s\n", name);
153 	syslog(LOG_ERR, "SLIP access denied for %s\n", name);
154 	exit(4);
155 	/* NOTREACHED */
156 }
157 
158 char *
159 sigstr(s)
160 	int s;
161 {
162 	static char buf[32];
163 
164 	switch (s) {
165 	case SIGHUP:	return("HUP");
166 	case SIGINT:	return("INT");
167 	case SIGQUIT:	return("QUIT");
168 	case SIGILL:	return("ILL");
169 	case SIGTRAP:	return("TRAP");
170 	case SIGIOT:	return("IOT");
171 	case SIGEMT:	return("EMT");
172 	case SIGFPE:	return("FPE");
173 	case SIGKILL:	return("KILL");
174 	case SIGBUS:	return("BUS");
175 	case SIGSEGV:	return("SEGV");
176 	case SIGSYS:	return("SYS");
177 	case SIGPIPE:	return("PIPE");
178 	case SIGALRM:	return("ALRM");
179 	case SIGTERM:	return("TERM");
180 	case SIGURG:	return("URG");
181 	case SIGSTOP:	return("STOP");
182 	case SIGTSTP:	return("TSTP");
183 	case SIGCONT:	return("CONT");
184 	case SIGCHLD:	return("CHLD");
185 	case SIGTTIN:	return("TTIN");
186 	case SIGTTOU:	return("TTOU");
187 	case SIGIO:	return("IO");
188 	case SIGXCPU:	return("XCPU");
189 	case SIGXFSZ:	return("XFSZ");
190 	case SIGVTALRM:	return("VTALRM");
191 	case SIGPROF:	return("PROF");
192 	case SIGWINCH:	return("WINCH");
193 #ifdef SIGLOST
194 	case SIGLOST:	return("LOST");
195 #endif
196 	case SIGUSR1:	return("USR1");
197 	case SIGUSR2:	return("USR2");
198 	}
199 	(void)sprintf(buf, "sig %d", s);
200 	return(buf);
201 }
202 
203 int
204 hup_handler(s)
205 	int s;
206 {
207 	if (access(logoutfile, R_OK|X_OK) == 0) {
208 		char logincmd[2*BUFSIZ+32];
209 
210 		(void)sprintf(logincmd, "%s %d %d %s", logoutfile, unit, speed,
211 			      loginargs);
212 		(void)system(logincmd);
213 	}
214 	(void)close(0);
215 	syslog(LOG_INFO, "closed %s slip unit %d (%s)\n", loginname, unit,
216 	       sigstr(s));
217 	exit(1);
218 	/* NOTREACHED */
219 }
220 
221 main(argc, argv)
222 	int argc;
223 	char *argv[];
224 {
225 	int	fd, s, ldisc, odisc;
226 	char *name;
227 #ifdef TERMIOS
228 	struct	termios tios, otios;
229 #else
230 	struct	sgttyb tty, otty;
231 #endif
232 	char logincmd[2*BUFSIZ+32];
233 	extern uid_t getuid();
234 
235 	if ((name = strrchr(argv[0], '/')) == NULL)
236 		name = argv[0];
237 	s = getdtablesize();
238 	for (fd = 3 ; fd < s ; fd++)
239 		(void) close(fd);
240 	openlog(name, LOG_PID, LOG_DAEMON);
241 	if (argc > 1) {
242 		if (argc > 2) {
243 			(void)fprintf(stderr, "Usage: %s loginname\n", argv[0]);
244 			exit(1);
245 		}
246 		findid(argv[1]);
247 
248 		/*
249 		 * Disassociate from current controlling terminal, if any,
250 		 * and ensure that the slip line is our controlling terminal.
251 		 */
252 #ifdef TERMIOS
253 		(void) setsid();
254 		(void) ioctl(0, TIOCSCTTY, (caddr_t)0);
255 #else
256 		if ((fd = open("/dev/tty", O_RDONLY, 0)) >= 0) {
257 			extern char *ttyname();
258 
259 			(void) ioctl(fd, TIOCNOTTY, (caddr_t)0);
260 			(void) close(fd);
261 			/* open slip tty again to acquire as controlling tty? */
262 			fd = open(ttyname(0), O_RDWR, 0);
263 			if (fd >= 0)
264 				(void) close(fd);
265 		}
266 		(void) setpgrp(0, getpid());
267 #endif
268 	} else {
269 		extern char *getenv();
270 
271 		if ((name = getenv("USER")) == NULL) {
272 			(void) fprintf(stderr, "access denied - no username\n");
273 			syslog(LOG_ERR, "access denied - no username\n");
274 			exit(1);
275 		}
276 		findid(name);
277 	}
278 	(void) fchmod(0, 0600);
279 	(void) fprintf(stderr, "starting slip login for %s\n", loginname);
280 #ifdef TERMIOS
281 	/* set up the line parameters */
282 	if (ioctl(0, TIOCGETA, (caddr_t)&tios) < 0) {
283 		syslog(LOG_ERR, "ioctl (TIOCGETA): %m");
284 		exit(1);
285 	}
286 	otios = tios;
287 	tios.c_cflag = CS8|CREAD|HUPCL;
288 	tios.c_iflag = IGNBRK;
289 	tios.c_oflag = tios.c_lflag = 0;
290 	if (ioctl(0, TIOCSETA, (caddr_t)&tios) < 0) {
291 		syslog(LOG_ERR, "ioctl (TIOCSETA) (1): %m");
292 		exit(1);
293 	}
294 #else
295 	/* set up the line parameters */
296 	if (ioctl(0, TIOCGETP, (caddr_t)&tty) < 0) {
297 		syslog(LOG_ERR, "ioctl (TIOCGETP): %m");
298 		exit(1);
299 	}
300 	otty = tty;
301 	speed = tty.sg_ispeed;
302 	tty.sg_flags = RAW | ANYP;
303 	if (ioctl(0, TIOCSETP, (caddr_t)&tty) < 0) {
304 		syslog(LOG_ERR, "ioctl (TIOCSETP): %m");
305 		exit(1);
306 	}
307 #endif
308 	/* find out what ldisc we started with */
309 	if (ioctl(0, TIOCGETD, (caddr_t)&odisc) < 0) {
310 		syslog(LOG_ERR, "ioctl(TIOCGETD) (1): %m");
311 		exit(1);
312 	}
313 	ldisc = SLIPDISC;
314 	if (ioctl(0, TIOCSETD, (caddr_t)&ldisc) < 0) {
315 		syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
316 		exit(1);
317 	}
318 	/* find out what unit number we were assigned */
319 	if (ioctl(0, TIOCGETD, (caddr_t)&unit) < 0) {
320 		syslog(LOG_ERR, "ioctl (TIOCGETD) (2): %m");
321 		exit(1);
322 	}
323 	(void) signal(SIGHUP, hup_handler);
324 	(void) signal(SIGTERM, hup_handler);
325 
326 	syslog(LOG_INFO, "attaching slip unit %d for %s\n", unit, loginname);
327 	(void)sprintf(logincmd, "%s %d %d %s", loginfile, unit, speed,
328 		      loginargs);
329 	/*
330 	 * aim stdout and errout at /dev/null so logincmd output won't
331 	 * babble into the slip tty line.
332 	 */
333 	(void)close(1);
334 	if ((fd = open("/dev/null", O_WRONLY, 0)) != 1) {
335 		if (fd < 0) {
336 			syslog(LOG_ERR, "open /dev/null: %m");
337 			exit(1);
338 		}
339 		(void)dup2(fd, 1);
340 		(void)close(fd);
341 	}
342 	(void)dup2(1,2);
343 	if (s = system(logincmd)) {
344 		syslog(LOG_ERR, "%s login failed: exit status %d from %s",
345 		       loginname, s, loginfile);
346 		(void) ioctl(0, TIOCSETD, (caddr_t)&odisc);
347 		exit(6);
348 	}
349 	if (ioctl(0, SLIOCSFLAGS, (caddr_t)&slip_mode) < 0) {
350 		syslog(LOG_ERR, "ioctl (SLIOCSFLAGS): %m");
351 		exit(1);
352 	}
353 
354 	/* twiddle thumbs until we get a signal */
355 	while (1)
356 		sigpause(0);
357 
358 	/* NOTREACHED */
359 }
360