144262Sbostic /*-
261877Sbostic * Copyright (c) 1990, 1993
361877Sbostic * The Regents of the University of California. All rights reserved.
444262Sbostic *
544262Sbostic * %sccs.include.redist.c%
644262Sbostic */
744262Sbostic
838272Ssam #ifndef lint
961877Sbostic static char copyright[] =
1061877Sbostic "@(#) Copyright (c) 1990, 1993\n\
1161877Sbostic The Regents of the University of California. All rights reserved.\n";
1244262Sbostic #endif /* not lint */
1344262Sbostic
1444262Sbostic #ifndef lint
15*65967Scgd static char sccsid[] = "@(#)sliplogin.c 8.2 (Berkeley) 02/01/94";
1644262Sbostic #endif /* not lint */
1744262Sbostic
1838272Ssam /*
1938272Ssam * sliplogin.c
2038373Skarels * [MUST BE RUN SUID, SLOPEN DOES A SUSER()!]
2138272Ssam *
2238272Ssam * This program initializes its own tty port to be an async TCP/IP interface.
2344851Strent * It sets the line discipline to slip, invokes a shell script to initialize
2444851Strent * the network interface, then pauses forever waiting for hangup.
2538272Ssam *
2638272Ssam * It is a remote descendant of several similar programs with incestuous ties:
2738272Ssam * - Kirk Smith's slipconf, modified by Richard Johnsson @ DEC WRL.
2838272Ssam * - slattach, probably by Rick Adams but touched by countless hordes.
2938272Ssam * - the original sliplogin for 4.2bsd, Doug Kingston the mover behind it.
3038272Ssam *
3144851Strent * There are two forms of usage:
3238272Ssam *
3338272Ssam * "sliplogin"
3446400Skarels * Invoked simply as "sliplogin", the program looks up the username
3546400Skarels * in the file /etc/slip.hosts.
3646400Skarels * If an entry is found, the line on fd0 is configured for SLIP operation
3738272Ssam * as specified in the file.
3838272Ssam *
3946400Skarels * "sliplogin IPhostlogin </dev/ttyb"
4038272Ssam * Invoked by root with a username, the name is looked up in the
4146400Skarels * /etc/slip.hosts file and if found fd0 is configured as in case 1.
4238272Ssam */
4338272Ssam
4444851Strent #include <sys/param.h>
4538272Ssam #include <sys/socket.h>
4644860Sbostic #include <sys/signal.h>
4738272Ssam #include <sys/file.h>
4838272Ssam #include <sys/syslog.h>
4938272Ssam #include <netdb.h>
5044860Sbostic
5146400Skarels #if BSD >= 199006
5246400Skarels #define POSIX
5344851Strent #endif
5446400Skarels #ifdef POSIX
5544851Strent #include <sys/termios.h>
5646400Skarels #include <sys/ioctl.h>
5738272Ssam #include <ttyent.h>
5846400Skarels #else
5946400Skarels #include <sgtty.h>
6044851Strent #endif
61*65967Scgd #include <net/slip.h>
6238272Ssam
6344860Sbostic #include <stdio.h>
6444860Sbostic #include <errno.h>
6544860Sbostic #include <ctype.h>
6644860Sbostic #include <string.h>
6744860Sbostic #include "pathnames.h"
6838372Ssam
6944851Strent int unit;
7044851Strent int speed;
7146400Skarels int uid;
7244851Strent char loginargs[BUFSIZ];
7346400Skarels char loginfile[MAXPATHLEN];
7444851Strent char loginname[BUFSIZ];
7538272Ssam
7638272Ssam void
findid(name)7744851Strent findid(name)
7844851Strent char *name;
7938272Ssam {
8044851Strent FILE *fp;
8144851Strent static char slopt[5][16];
8244851Strent static char laddr[16];
8344851Strent static char raddr[16];
8444851Strent static char mask[16];
8544851Strent char user[16];
8644851Strent int i, j, n;
8738272Ssam
8844851Strent (void)strcpy(loginname, name);
8944860Sbostic if ((fp = fopen(_PATH_ACCESS, "r")) == NULL) {
9044860Sbostic (void)fprintf(stderr, "sliplogin: %s: %s\n",
9144860Sbostic _PATH_ACCESS, strerror(errno));
9244860Sbostic syslog(LOG_ERR, "%s: %m\n", _PATH_ACCESS);
9344860Sbostic exit(1);
9444851Strent }
9544851Strent while (fgets(loginargs, sizeof(loginargs) - 1, fp)) {
9644851Strent if (ferror(fp))
9744851Strent break;
9844851Strent n = sscanf(loginargs, "%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s\n",
9944851Strent user, laddr, raddr, mask, slopt[0], slopt[1],
10044851Strent slopt[2], slopt[3], slopt[4]);
10144851Strent if (user[0] == '#' || isspace(user[0]))
10244851Strent continue;
10344851Strent if (strcmp(user, name) != 0)
10444851Strent continue;
10538272Ssam
10644851Strent /*
10744851Strent * we've found the guy we're looking for -- see if
10844851Strent * there's a login file we can use. First check for
10944851Strent * one specific to this host. If none found, try for
11044851Strent * a generic one.
11144851Strent */
11244860Sbostic (void)sprintf(loginfile, "%s.%s", _PATH_LOGIN, name);
11346400Skarels if (access(loginfile, R_OK|X_OK) != 0) {
11444860Sbostic (void)strcpy(loginfile, _PATH_LOGIN);
11544851Strent if (access(loginfile, R_OK|X_OK)) {
11644851Strent fputs("access denied - no login file\n",
11744851Strent stderr);
11844851Strent syslog(LOG_ERR,
11944851Strent "access denied for %s - no %s\n",
12044860Sbostic name, _PATH_LOGIN);
12144851Strent exit(5);
12244851Strent }
12346400Skarels }
12444851Strent
12544851Strent (void) fclose(fp);
12644851Strent return;
12744851Strent }
12844851Strent (void)fprintf(stderr, "SLIP access denied for %s\n", name);
12944851Strent syslog(LOG_ERR, "SLIP access denied for %s\n", name);
13044851Strent exit(4);
13144851Strent /* NOTREACHED */
13238272Ssam }
13338272Ssam
13444851Strent char *
sigstr(s)13544851Strent sigstr(s)
13644851Strent int s;
13744851Strent {
13844851Strent static char buf[32];
13938272Ssam
14044851Strent switch (s) {
14144851Strent case SIGHUP: return("HUP");
14244851Strent case SIGINT: return("INT");
14344851Strent case SIGQUIT: return("QUIT");
14444851Strent case SIGILL: return("ILL");
14544851Strent case SIGTRAP: return("TRAP");
14644851Strent case SIGIOT: return("IOT");
14744851Strent case SIGEMT: return("EMT");
14844851Strent case SIGFPE: return("FPE");
14944851Strent case SIGKILL: return("KILL");
15044851Strent case SIGBUS: return("BUS");
15144851Strent case SIGSEGV: return("SEGV");
15244851Strent case SIGSYS: return("SYS");
15344851Strent case SIGPIPE: return("PIPE");
15444851Strent case SIGALRM: return("ALRM");
15544851Strent case SIGTERM: return("TERM");
15644851Strent case SIGURG: return("URG");
15744851Strent case SIGSTOP: return("STOP");
15844851Strent case SIGTSTP: return("TSTP");
15944851Strent case SIGCONT: return("CONT");
16044851Strent case SIGCHLD: return("CHLD");
16144851Strent case SIGTTIN: return("TTIN");
16244851Strent case SIGTTOU: return("TTOU");
16344851Strent case SIGIO: return("IO");
16444851Strent case SIGXCPU: return("XCPU");
16544851Strent case SIGXFSZ: return("XFSZ");
16644851Strent case SIGVTALRM: return("VTALRM");
16744851Strent case SIGPROF: return("PROF");
16844851Strent case SIGWINCH: return("WINCH");
16944851Strent #ifdef SIGLOST
17044851Strent case SIGLOST: return("LOST");
17144851Strent #endif
17244851Strent case SIGUSR1: return("USR1");
17344851Strent case SIGUSR2: return("USR2");
17444851Strent }
17544851Strent (void)sprintf(buf, "sig %d", s);
17644851Strent return(buf);
17744851Strent }
17838272Ssam
17946929Sbostic void
hup_handler(s)18040016Ssam hup_handler(s)
18140016Ssam int s;
18238373Skarels {
18346400Skarels char logoutfile[MAXPATHLEN];
18446400Skarels
18546400Skarels (void)sprintf(logoutfile, "%s.%s", _PATH_LOGOUT, loginname);
18646400Skarels if (access(logoutfile, R_OK|X_OK) != 0)
18746400Skarels (void)strcpy(logoutfile, _PATH_LOGOUT);
18844851Strent if (access(logoutfile, R_OK|X_OK) == 0) {
18946400Skarels char logincmd[2*MAXPATHLEN+32];
19040016Ssam
19146400Skarels (void) sprintf(logincmd, "%s %d %d %s", logoutfile, unit, speed,
19244851Strent loginargs);
19346400Skarels (void) system(logincmd);
19444851Strent }
19546400Skarels (void) close(0);
19644851Strent syslog(LOG_INFO, "closed %s slip unit %d (%s)\n", loginname, unit,
19744851Strent sigstr(s));
19844851Strent exit(1);
19944851Strent /* NOTREACHED */
20038373Skarels }
20138373Skarels
main(argc,argv)20238272Ssam main(argc, argv)
20338272Ssam int argc;
20438272Ssam char *argv[];
20538272Ssam {
20646400Skarels int fd, s, ldisc, odisc;
20744851Strent char *name;
20846400Skarels #ifdef POSIX
20946400Skarels struct termios tios, otios;
21044851Strent #else
21146400Skarels struct sgttyb tty, otty;
21244851Strent #endif
21344851Strent char logincmd[2*BUFSIZ+32];
21444851Strent extern uid_t getuid();
21538272Ssam
21644851Strent if ((name = strrchr(argv[0], '/')) == NULL)
21744851Strent name = argv[0];
21838272Ssam s = getdtablesize();
21938272Ssam for (fd = 3 ; fd < s ; fd++)
22044851Strent (void) close(fd);
22144851Strent openlog(name, LOG_PID, LOG_DAEMON);
22246400Skarels uid = getuid();
22344851Strent if (argc > 1) {
22444851Strent findid(argv[1]);
22544851Strent
22640016Ssam /*
22740016Ssam * Disassociate from current controlling terminal, if any,
22840016Ssam * and ensure that the slip line is our controlling terminal.
22940016Ssam */
23046400Skarels #ifdef POSIX
23146400Skarels if (fork() > 0)
23246400Skarels exit(0);
23346400Skarels if (setsid() != 0)
23446400Skarels perror("setsid");
23544851Strent #else
23640016Ssam if ((fd = open("/dev/tty", O_RDONLY, 0)) >= 0) {
23744851Strent extern char *ttyname();
23844851Strent
23944851Strent (void) ioctl(fd, TIOCNOTTY, (caddr_t)0);
24040016Ssam (void) close(fd);
24140016Ssam /* open slip tty again to acquire as controlling tty? */
24240016Ssam fd = open(ttyname(0), O_RDWR, 0);
24340016Ssam if (fd >= 0)
24440016Ssam (void) close(fd);
24540016Ssam }
24640016Ssam (void) setpgrp(0, getpid());
24740016Ssam #endif
24846400Skarels if (argc > 2) {
24946400Skarels if ((fd = open(argv[2], O_RDWR)) == -1) {
25046400Skarels perror(argv[2]);
25146400Skarels exit(2);
25246400Skarels }
25346400Skarels (void) dup2(fd, 0);
25446400Skarels if (fd > 2)
25546400Skarels close(fd);
25646400Skarels }
25746400Skarels #ifdef TIOCSCTTY
25846400Skarels if (ioctl(0, TIOCSCTTY, (caddr_t)0) != 0)
25946400Skarels perror("ioctl (TIOCSCTTY)");
26046400Skarels #endif
26144851Strent } else {
26246400Skarels extern char *getlogin();
26344851Strent
26446400Skarels if ((name = getlogin()) == NULL) {
26544851Strent (void) fprintf(stderr, "access denied - no username\n");
26646400Skarels syslog(LOG_ERR, "access denied - getlogin returned 0\n");
26744851Strent exit(1);
26844851Strent }
26944851Strent findid(name);
27044851Strent }
27144851Strent (void) fchmod(0, 0600);
27244851Strent (void) fprintf(stderr, "starting slip login for %s\n", loginname);
27346400Skarels #ifdef POSIX
27438272Ssam /* set up the line parameters */
27546400Skarels if (tcgetattr(0, &tios) < 0) {
27646400Skarels syslog(LOG_ERR, "tcgetattr: %m");
27738272Ssam exit(1);
27838272Ssam }
27940016Ssam otios = tios;
28046400Skarels cfmakeraw(&tios);
28146400Skarels tios.c_iflag &= ~IMAXBEL;
28246400Skarels if (tcsetattr(0, TCSAFLUSH, &tios) < 0) {
28346400Skarels syslog(LOG_ERR, "tcsetattr: %m");
28438272Ssam exit(1);
28538272Ssam }
28646400Skarels speed = cfgetispeed(&tios);
28744851Strent #else
28844851Strent /* set up the line parameters */
28944851Strent if (ioctl(0, TIOCGETP, (caddr_t)&tty) < 0) {
29044851Strent syslog(LOG_ERR, "ioctl (TIOCGETP): %m");
29144851Strent exit(1);
29244851Strent }
29344851Strent otty = tty;
29444851Strent speed = tty.sg_ispeed;
29544851Strent tty.sg_flags = RAW | ANYP;
29644851Strent if (ioctl(0, TIOCSETP, (caddr_t)&tty) < 0) {
29744851Strent syslog(LOG_ERR, "ioctl (TIOCSETP): %m");
29844851Strent exit(1);
29944851Strent }
30044851Strent #endif
30138373Skarels /* find out what ldisc we started with */
30238373Skarels if (ioctl(0, TIOCGETD, (caddr_t)&odisc) < 0) {
30338373Skarels syslog(LOG_ERR, "ioctl(TIOCGETD) (1): %m");
30438373Skarels exit(1);
30538373Skarels }
30638372Ssam ldisc = SLIPDISC;
30738372Ssam if (ioctl(0, TIOCSETD, (caddr_t)&ldisc) < 0) {
30840016Ssam syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
30938272Ssam exit(1);
31038272Ssam }
31138272Ssam /* find out what unit number we were assigned */
31246400Skarels if (ioctl(0, SLIOCGUNIT, (caddr_t)&unit) < 0) {
31346684Skarels syslog(LOG_ERR, "ioctl (SLIOCGUNIT): %m");
31438272Ssam exit(1);
31538272Ssam }
31644851Strent (void) signal(SIGHUP, hup_handler);
31744851Strent (void) signal(SIGTERM, hup_handler);
31844851Strent
31944851Strent syslog(LOG_INFO, "attaching slip unit %d for %s\n", unit, loginname);
32044851Strent (void)sprintf(logincmd, "%s %d %d %s", loginfile, unit, speed,
32144851Strent loginargs);
32244851Strent /*
32344851Strent * aim stdout and errout at /dev/null so logincmd output won't
32444851Strent * babble into the slip tty line.
32544851Strent */
32646400Skarels (void) close(1);
32746929Sbostic if ((fd = open(_PATH_DEVNULL, O_WRONLY)) != 1) {
32844851Strent if (fd < 0) {
32944851Strent syslog(LOG_ERR, "open /dev/null: %m");
33038272Ssam exit(1);
33138272Ssam }
33246400Skarels (void) dup2(fd, 1);
33346400Skarels (void) close(fd);
33438272Ssam }
33546400Skarels (void) dup2(1, 2);
33646400Skarels
33746400Skarels /*
33846400Skarels * Run login and logout scripts as root (real and effective);
33946400Skarels * current route(8) is setuid root, and checks the real uid
34046400Skarels * to see whether changes are allowed (or just "route get").
34146400Skarels */
34246400Skarels (void) setuid(0);
34344851Strent if (s = system(logincmd)) {
34444851Strent syslog(LOG_ERR, "%s login failed: exit status %d from %s",
34544851Strent loginname, s, loginfile);
34644851Strent (void) ioctl(0, TIOCSETD, (caddr_t)&odisc);
34744851Strent exit(6);
34838272Ssam }
34938272Ssam
35038272Ssam /* twiddle thumbs until we get a signal */
35144851Strent while (1)
35238272Ssam sigpause(0);
35338272Ssam
35444851Strent /* NOTREACHED */
35538272Ssam }
356