144262Sbostic /*- 2*61877Sbostic * Copyright (c) 1990, 1993 3*61877Sbostic * The Regents of the University of California. All rights reserved. 444262Sbostic * 544262Sbostic * %sccs.include.redist.c% 644262Sbostic */ 744262Sbostic 838272Ssam #ifndef lint 9*61877Sbostic static char copyright[] = 10*61877Sbostic "@(#) Copyright (c) 1990, 1993\n\ 11*61877Sbostic The Regents of the University of California. All rights reserved.\n"; 1244262Sbostic #endif /* not lint */ 1344262Sbostic 1444262Sbostic #ifndef lint 15*61877Sbostic static char sccsid[] = "@(#)sliplogin.c 8.1 (Berkeley) 06/06/93"; 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 6144851Strent #include <netinet/in.h> 6244851Strent #include <net/if.h> 6344851Strent #include <net/if_slvar.h> 6438272Ssam 6544860Sbostic #include <stdio.h> 6644860Sbostic #include <errno.h> 6744860Sbostic #include <ctype.h> 6844860Sbostic #include <string.h> 6944860Sbostic #include "pathnames.h" 7038372Ssam 7144851Strent int unit; 7244851Strent int speed; 7346400Skarels int uid; 7444851Strent char loginargs[BUFSIZ]; 7546400Skarels char loginfile[MAXPATHLEN]; 7644851Strent char loginname[BUFSIZ]; 7738272Ssam 7838272Ssam void 7944851Strent findid(name) 8044851Strent char *name; 8138272Ssam { 8244851Strent FILE *fp; 8344851Strent static char slopt[5][16]; 8444851Strent static char laddr[16]; 8544851Strent static char raddr[16]; 8644851Strent static char mask[16]; 8744851Strent char user[16]; 8844851Strent int i, j, n; 8938272Ssam 9044851Strent (void)strcpy(loginname, name); 9144860Sbostic if ((fp = fopen(_PATH_ACCESS, "r")) == NULL) { 9244860Sbostic (void)fprintf(stderr, "sliplogin: %s: %s\n", 9344860Sbostic _PATH_ACCESS, strerror(errno)); 9444860Sbostic syslog(LOG_ERR, "%s: %m\n", _PATH_ACCESS); 9544860Sbostic exit(1); 9644851Strent } 9744851Strent while (fgets(loginargs, sizeof(loginargs) - 1, fp)) { 9844851Strent if (ferror(fp)) 9944851Strent break; 10044851Strent n = sscanf(loginargs, "%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s\n", 10144851Strent user, laddr, raddr, mask, slopt[0], slopt[1], 10244851Strent slopt[2], slopt[3], slopt[4]); 10344851Strent if (user[0] == '#' || isspace(user[0])) 10444851Strent continue; 10544851Strent if (strcmp(user, name) != 0) 10644851Strent continue; 10738272Ssam 10844851Strent /* 10944851Strent * we've found the guy we're looking for -- see if 11044851Strent * there's a login file we can use. First check for 11144851Strent * one specific to this host. If none found, try for 11244851Strent * a generic one. 11344851Strent */ 11444860Sbostic (void)sprintf(loginfile, "%s.%s", _PATH_LOGIN, name); 11546400Skarels if (access(loginfile, R_OK|X_OK) != 0) { 11644860Sbostic (void)strcpy(loginfile, _PATH_LOGIN); 11744851Strent if (access(loginfile, R_OK|X_OK)) { 11844851Strent fputs("access denied - no login file\n", 11944851Strent stderr); 12044851Strent syslog(LOG_ERR, 12144851Strent "access denied for %s - no %s\n", 12244860Sbostic name, _PATH_LOGIN); 12344851Strent exit(5); 12444851Strent } 12546400Skarels } 12644851Strent 12744851Strent (void) fclose(fp); 12844851Strent return; 12944851Strent } 13044851Strent (void)fprintf(stderr, "SLIP access denied for %s\n", name); 13144851Strent syslog(LOG_ERR, "SLIP access denied for %s\n", name); 13244851Strent exit(4); 13344851Strent /* NOTREACHED */ 13438272Ssam } 13538272Ssam 13644851Strent char * 13744851Strent sigstr(s) 13844851Strent int s; 13944851Strent { 14044851Strent static char buf[32]; 14138272Ssam 14244851Strent switch (s) { 14344851Strent case SIGHUP: return("HUP"); 14444851Strent case SIGINT: return("INT"); 14544851Strent case SIGQUIT: return("QUIT"); 14644851Strent case SIGILL: return("ILL"); 14744851Strent case SIGTRAP: return("TRAP"); 14844851Strent case SIGIOT: return("IOT"); 14944851Strent case SIGEMT: return("EMT"); 15044851Strent case SIGFPE: return("FPE"); 15144851Strent case SIGKILL: return("KILL"); 15244851Strent case SIGBUS: return("BUS"); 15344851Strent case SIGSEGV: return("SEGV"); 15444851Strent case SIGSYS: return("SYS"); 15544851Strent case SIGPIPE: return("PIPE"); 15644851Strent case SIGALRM: return("ALRM"); 15744851Strent case SIGTERM: return("TERM"); 15844851Strent case SIGURG: return("URG"); 15944851Strent case SIGSTOP: return("STOP"); 16044851Strent case SIGTSTP: return("TSTP"); 16144851Strent case SIGCONT: return("CONT"); 16244851Strent case SIGCHLD: return("CHLD"); 16344851Strent case SIGTTIN: return("TTIN"); 16444851Strent case SIGTTOU: return("TTOU"); 16544851Strent case SIGIO: return("IO"); 16644851Strent case SIGXCPU: return("XCPU"); 16744851Strent case SIGXFSZ: return("XFSZ"); 16844851Strent case SIGVTALRM: return("VTALRM"); 16944851Strent case SIGPROF: return("PROF"); 17044851Strent case SIGWINCH: return("WINCH"); 17144851Strent #ifdef SIGLOST 17244851Strent case SIGLOST: return("LOST"); 17344851Strent #endif 17444851Strent case SIGUSR1: return("USR1"); 17544851Strent case SIGUSR2: return("USR2"); 17644851Strent } 17744851Strent (void)sprintf(buf, "sig %d", s); 17844851Strent return(buf); 17944851Strent } 18038272Ssam 18146929Sbostic void 18240016Ssam hup_handler(s) 18340016Ssam int s; 18438373Skarels { 18546400Skarels char logoutfile[MAXPATHLEN]; 18646400Skarels 18746400Skarels (void)sprintf(logoutfile, "%s.%s", _PATH_LOGOUT, loginname); 18846400Skarels if (access(logoutfile, R_OK|X_OK) != 0) 18946400Skarels (void)strcpy(logoutfile, _PATH_LOGOUT); 19044851Strent if (access(logoutfile, R_OK|X_OK) == 0) { 19146400Skarels char logincmd[2*MAXPATHLEN+32]; 19240016Ssam 19346400Skarels (void) sprintf(logincmd, "%s %d %d %s", logoutfile, unit, speed, 19444851Strent loginargs); 19546400Skarels (void) system(logincmd); 19644851Strent } 19746400Skarels (void) close(0); 19844851Strent syslog(LOG_INFO, "closed %s slip unit %d (%s)\n", loginname, unit, 19944851Strent sigstr(s)); 20044851Strent exit(1); 20144851Strent /* NOTREACHED */ 20238373Skarels } 20338373Skarels 20438272Ssam main(argc, argv) 20538272Ssam int argc; 20638272Ssam char *argv[]; 20738272Ssam { 20846400Skarels int fd, s, ldisc, odisc; 20944851Strent char *name; 21046400Skarels #ifdef POSIX 21146400Skarels struct termios tios, otios; 21244851Strent #else 21346400Skarels struct sgttyb tty, otty; 21444851Strent #endif 21544851Strent char logincmd[2*BUFSIZ+32]; 21644851Strent extern uid_t getuid(); 21738272Ssam 21844851Strent if ((name = strrchr(argv[0], '/')) == NULL) 21944851Strent name = argv[0]; 22038272Ssam s = getdtablesize(); 22138272Ssam for (fd = 3 ; fd < s ; fd++) 22244851Strent (void) close(fd); 22344851Strent openlog(name, LOG_PID, LOG_DAEMON); 22446400Skarels uid = getuid(); 22544851Strent if (argc > 1) { 22644851Strent findid(argv[1]); 22744851Strent 22840016Ssam /* 22940016Ssam * Disassociate from current controlling terminal, if any, 23040016Ssam * and ensure that the slip line is our controlling terminal. 23140016Ssam */ 23246400Skarels #ifdef POSIX 23346400Skarels if (fork() > 0) 23446400Skarels exit(0); 23546400Skarels if (setsid() != 0) 23646400Skarels perror("setsid"); 23744851Strent #else 23840016Ssam if ((fd = open("/dev/tty", O_RDONLY, 0)) >= 0) { 23944851Strent extern char *ttyname(); 24044851Strent 24144851Strent (void) ioctl(fd, TIOCNOTTY, (caddr_t)0); 24240016Ssam (void) close(fd); 24340016Ssam /* open slip tty again to acquire as controlling tty? */ 24440016Ssam fd = open(ttyname(0), O_RDWR, 0); 24540016Ssam if (fd >= 0) 24640016Ssam (void) close(fd); 24740016Ssam } 24840016Ssam (void) setpgrp(0, getpid()); 24940016Ssam #endif 25046400Skarels if (argc > 2) { 25146400Skarels if ((fd = open(argv[2], O_RDWR)) == -1) { 25246400Skarels perror(argv[2]); 25346400Skarels exit(2); 25446400Skarels } 25546400Skarels (void) dup2(fd, 0); 25646400Skarels if (fd > 2) 25746400Skarels close(fd); 25846400Skarels } 25946400Skarels #ifdef TIOCSCTTY 26046400Skarels if (ioctl(0, TIOCSCTTY, (caddr_t)0) != 0) 26146400Skarels perror("ioctl (TIOCSCTTY)"); 26246400Skarels #endif 26344851Strent } else { 26446400Skarels extern char *getlogin(); 26544851Strent 26646400Skarels if ((name = getlogin()) == NULL) { 26744851Strent (void) fprintf(stderr, "access denied - no username\n"); 26846400Skarels syslog(LOG_ERR, "access denied - getlogin returned 0\n"); 26944851Strent exit(1); 27044851Strent } 27144851Strent findid(name); 27244851Strent } 27344851Strent (void) fchmod(0, 0600); 27444851Strent (void) fprintf(stderr, "starting slip login for %s\n", loginname); 27546400Skarels #ifdef POSIX 27638272Ssam /* set up the line parameters */ 27746400Skarels if (tcgetattr(0, &tios) < 0) { 27846400Skarels syslog(LOG_ERR, "tcgetattr: %m"); 27938272Ssam exit(1); 28038272Ssam } 28140016Ssam otios = tios; 28246400Skarels cfmakeraw(&tios); 28346400Skarels tios.c_iflag &= ~IMAXBEL; 28446400Skarels if (tcsetattr(0, TCSAFLUSH, &tios) < 0) { 28546400Skarels syslog(LOG_ERR, "tcsetattr: %m"); 28638272Ssam exit(1); 28738272Ssam } 28846400Skarels speed = cfgetispeed(&tios); 28944851Strent #else 29044851Strent /* set up the line parameters */ 29144851Strent if (ioctl(0, TIOCGETP, (caddr_t)&tty) < 0) { 29244851Strent syslog(LOG_ERR, "ioctl (TIOCGETP): %m"); 29344851Strent exit(1); 29444851Strent } 29544851Strent otty = tty; 29644851Strent speed = tty.sg_ispeed; 29744851Strent tty.sg_flags = RAW | ANYP; 29844851Strent if (ioctl(0, TIOCSETP, (caddr_t)&tty) < 0) { 29944851Strent syslog(LOG_ERR, "ioctl (TIOCSETP): %m"); 30044851Strent exit(1); 30144851Strent } 30244851Strent #endif 30338373Skarels /* find out what ldisc we started with */ 30438373Skarels if (ioctl(0, TIOCGETD, (caddr_t)&odisc) < 0) { 30538373Skarels syslog(LOG_ERR, "ioctl(TIOCGETD) (1): %m"); 30638373Skarels exit(1); 30738373Skarels } 30838372Ssam ldisc = SLIPDISC; 30938372Ssam if (ioctl(0, TIOCSETD, (caddr_t)&ldisc) < 0) { 31040016Ssam syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); 31138272Ssam exit(1); 31238272Ssam } 31338272Ssam /* find out what unit number we were assigned */ 31446400Skarels if (ioctl(0, SLIOCGUNIT, (caddr_t)&unit) < 0) { 31546684Skarels syslog(LOG_ERR, "ioctl (SLIOCGUNIT): %m"); 31638272Ssam exit(1); 31738272Ssam } 31844851Strent (void) signal(SIGHUP, hup_handler); 31944851Strent (void) signal(SIGTERM, hup_handler); 32044851Strent 32144851Strent syslog(LOG_INFO, "attaching slip unit %d for %s\n", unit, loginname); 32244851Strent (void)sprintf(logincmd, "%s %d %d %s", loginfile, unit, speed, 32344851Strent loginargs); 32444851Strent /* 32544851Strent * aim stdout and errout at /dev/null so logincmd output won't 32644851Strent * babble into the slip tty line. 32744851Strent */ 32846400Skarels (void) close(1); 32946929Sbostic if ((fd = open(_PATH_DEVNULL, O_WRONLY)) != 1) { 33044851Strent if (fd < 0) { 33144851Strent syslog(LOG_ERR, "open /dev/null: %m"); 33238272Ssam exit(1); 33338272Ssam } 33446400Skarels (void) dup2(fd, 1); 33546400Skarels (void) close(fd); 33638272Ssam } 33746400Skarels (void) dup2(1, 2); 33846400Skarels 33946400Skarels /* 34046400Skarels * Run login and logout scripts as root (real and effective); 34146400Skarels * current route(8) is setuid root, and checks the real uid 34246400Skarels * to see whether changes are allowed (or just "route get"). 34346400Skarels */ 34446400Skarels (void) setuid(0); 34544851Strent if (s = system(logincmd)) { 34644851Strent syslog(LOG_ERR, "%s login failed: exit status %d from %s", 34744851Strent loginname, s, loginfile); 34844851Strent (void) ioctl(0, TIOCSETD, (caddr_t)&odisc); 34944851Strent exit(6); 35038272Ssam } 35138272Ssam 35238272Ssam /* twiddle thumbs until we get a signal */ 35344851Strent while (1) 35438272Ssam sigpause(0); 35538272Ssam 35644851Strent /* NOTREACHED */ 35738272Ssam } 358