144262Sbostic /*- 244262Sbostic * Copyright (c) 1990 The Regents of the University of California. 344262Sbostic * All rights reserved. 444262Sbostic * 544262Sbostic * %sccs.include.redist.c% 644262Sbostic */ 744262Sbostic 838272Ssam #ifndef lint 944262Sbostic char copyright[] = 1044262Sbostic "@(#) Copyright (c) 1990 The Regents of the University of California.\n\ 1144262Sbostic All rights reserved.\n"; 1244262Sbostic #endif /* not lint */ 1344262Sbostic 1444262Sbostic #ifndef lint 15*46684Skarels static char sccsid[] = "@(#)sliplogin.c 5.5 (Berkeley) 02/26/91"; 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; 7244860Sbostic int slip_mode; 7344851Strent int speed; 7446400Skarels int uid; 7544851Strent char loginargs[BUFSIZ]; 7646400Skarels char loginfile[MAXPATHLEN]; 7744851Strent char loginname[BUFSIZ]; 7838272Ssam 7944851Strent struct slip_modes { 8044851Strent char *sm_name; 8144851Strent int sm_value; 8244851Strent } modes[] = { 8344851Strent "normal", 0, 8444851Strent "compress", SC_COMPRESS, 8544851Strent "noicmp", SC_NOICMP, 8644851Strent "autocomp", SC_AUTOCOMP 8744851Strent }; 8838272Ssam 8938272Ssam void 9044851Strent findid(name) 9144851Strent char *name; 9238272Ssam { 9344851Strent FILE *fp; 9444851Strent static char slopt[5][16]; 9544851Strent static char laddr[16]; 9644851Strent static char raddr[16]; 9744851Strent static char mask[16]; 9844851Strent char user[16]; 9944851Strent int i, j, n; 10038272Ssam 10144851Strent (void)strcpy(loginname, name); 10244860Sbostic if ((fp = fopen(_PATH_ACCESS, "r")) == NULL) { 10344860Sbostic (void)fprintf(stderr, "sliplogin: %s: %s\n", 10444860Sbostic _PATH_ACCESS, strerror(errno)); 10544860Sbostic syslog(LOG_ERR, "%s: %m\n", _PATH_ACCESS); 10644860Sbostic exit(1); 10744851Strent } 10844851Strent while (fgets(loginargs, sizeof(loginargs) - 1, fp)) { 10944851Strent if (ferror(fp)) 11044851Strent break; 11144851Strent n = sscanf(loginargs, "%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s\n", 11244851Strent user, laddr, raddr, mask, slopt[0], slopt[1], 11344851Strent slopt[2], slopt[3], slopt[4]); 11444851Strent if (user[0] == '#' || isspace(user[0])) 11544851Strent continue; 11644851Strent if (strcmp(user, name) != 0) 11744851Strent continue; 11838272Ssam 11944851Strent slip_mode = 0; 12044851Strent for (i = 0; i < n - 4; i++) { 12144851Strent for (j = 0; j < sizeof(modes)/sizeof(struct slip_modes); 12244851Strent j++) { 12344851Strent if (strcmp(modes[j].sm_name, slopt[i]) == 0) { 12444851Strent slip_mode |= modes[j].sm_value; 12544851Strent break; 12644851Strent } 12744851Strent } 12844851Strent } 12938272Ssam 13044851Strent /* 13144851Strent * we've found the guy we're looking for -- see if 13244851Strent * there's a login file we can use. First check for 13344851Strent * one specific to this host. If none found, try for 13444851Strent * a generic one. 13544851Strent */ 13644860Sbostic (void)sprintf(loginfile, "%s.%s", _PATH_LOGIN, name); 13746400Skarels if (access(loginfile, R_OK|X_OK) != 0) { 13844860Sbostic (void)strcpy(loginfile, _PATH_LOGIN); 13944851Strent if (access(loginfile, R_OK|X_OK)) { 14044851Strent fputs("access denied - no login file\n", 14144851Strent stderr); 14244851Strent syslog(LOG_ERR, 14344851Strent "access denied for %s - no %s\n", 14444860Sbostic name, _PATH_LOGIN); 14544851Strent exit(5); 14644851Strent } 14746400Skarels } 14844851Strent 14944851Strent (void) fclose(fp); 15044851Strent return; 15144851Strent } 15244851Strent (void)fprintf(stderr, "SLIP access denied for %s\n", name); 15344851Strent syslog(LOG_ERR, "SLIP access denied for %s\n", name); 15444851Strent exit(4); 15544851Strent /* NOTREACHED */ 15638272Ssam } 15738272Ssam 15844851Strent char * 15944851Strent sigstr(s) 16044851Strent int s; 16144851Strent { 16244851Strent static char buf[32]; 16338272Ssam 16444851Strent switch (s) { 16544851Strent case SIGHUP: return("HUP"); 16644851Strent case SIGINT: return("INT"); 16744851Strent case SIGQUIT: return("QUIT"); 16844851Strent case SIGILL: return("ILL"); 16944851Strent case SIGTRAP: return("TRAP"); 17044851Strent case SIGIOT: return("IOT"); 17144851Strent case SIGEMT: return("EMT"); 17244851Strent case SIGFPE: return("FPE"); 17344851Strent case SIGKILL: return("KILL"); 17444851Strent case SIGBUS: return("BUS"); 17544851Strent case SIGSEGV: return("SEGV"); 17644851Strent case SIGSYS: return("SYS"); 17744851Strent case SIGPIPE: return("PIPE"); 17844851Strent case SIGALRM: return("ALRM"); 17944851Strent case SIGTERM: return("TERM"); 18044851Strent case SIGURG: return("URG"); 18144851Strent case SIGSTOP: return("STOP"); 18244851Strent case SIGTSTP: return("TSTP"); 18344851Strent case SIGCONT: return("CONT"); 18444851Strent case SIGCHLD: return("CHLD"); 18544851Strent case SIGTTIN: return("TTIN"); 18644851Strent case SIGTTOU: return("TTOU"); 18744851Strent case SIGIO: return("IO"); 18844851Strent case SIGXCPU: return("XCPU"); 18944851Strent case SIGXFSZ: return("XFSZ"); 19044851Strent case SIGVTALRM: return("VTALRM"); 19144851Strent case SIGPROF: return("PROF"); 19244851Strent case SIGWINCH: return("WINCH"); 19344851Strent #ifdef SIGLOST 19444851Strent case SIGLOST: return("LOST"); 19544851Strent #endif 19644851Strent case SIGUSR1: return("USR1"); 19744851Strent case SIGUSR2: return("USR2"); 19844851Strent } 19944851Strent (void)sprintf(buf, "sig %d", s); 20044851Strent return(buf); 20144851Strent } 20238272Ssam 20344851Strent int 20440016Ssam hup_handler(s) 20540016Ssam int s; 20638373Skarels { 20746400Skarels char logoutfile[MAXPATHLEN]; 20846400Skarels 20946400Skarels (void)sprintf(logoutfile, "%s.%s", _PATH_LOGOUT, loginname); 21046400Skarels if (access(logoutfile, R_OK|X_OK) != 0) 21146400Skarels (void)strcpy(logoutfile, _PATH_LOGOUT); 21244851Strent if (access(logoutfile, R_OK|X_OK) == 0) { 21346400Skarels char logincmd[2*MAXPATHLEN+32]; 21440016Ssam 21546400Skarels (void) sprintf(logincmd, "%s %d %d %s", logoutfile, unit, speed, 21644851Strent loginargs); 21746400Skarels (void) system(logincmd); 21844851Strent } 21946400Skarels (void) close(0); 22044851Strent syslog(LOG_INFO, "closed %s slip unit %d (%s)\n", loginname, unit, 22144851Strent sigstr(s)); 22244851Strent exit(1); 22344851Strent /* NOTREACHED */ 22438373Skarels } 22538373Skarels 22638272Ssam main(argc, argv) 22738272Ssam int argc; 22838272Ssam char *argv[]; 22938272Ssam { 23046400Skarels int fd, s, ldisc, odisc; 23144851Strent char *name; 23246400Skarels #ifdef POSIX 23346400Skarels struct termios tios, otios; 23444851Strent #else 23546400Skarels struct sgttyb tty, otty; 23644851Strent #endif 23744851Strent char logincmd[2*BUFSIZ+32]; 23844851Strent extern uid_t getuid(); 23938272Ssam 24044851Strent if ((name = strrchr(argv[0], '/')) == NULL) 24144851Strent name = argv[0]; 24238272Ssam s = getdtablesize(); 24338272Ssam for (fd = 3 ; fd < s ; fd++) 24444851Strent (void) close(fd); 24544851Strent openlog(name, LOG_PID, LOG_DAEMON); 24646400Skarels uid = getuid(); 24744851Strent if (argc > 1) { 24844851Strent findid(argv[1]); 24944851Strent 25040016Ssam /* 25140016Ssam * Disassociate from current controlling terminal, if any, 25240016Ssam * and ensure that the slip line is our controlling terminal. 25340016Ssam */ 25446400Skarels #ifdef POSIX 25546400Skarels if (fork() > 0) 25646400Skarels exit(0); 25746400Skarels if (setsid() != 0) 25846400Skarels perror("setsid"); 25944851Strent #else 26040016Ssam if ((fd = open("/dev/tty", O_RDONLY, 0)) >= 0) { 26144851Strent extern char *ttyname(); 26244851Strent 26344851Strent (void) ioctl(fd, TIOCNOTTY, (caddr_t)0); 26440016Ssam (void) close(fd); 26540016Ssam /* open slip tty again to acquire as controlling tty? */ 26640016Ssam fd = open(ttyname(0), O_RDWR, 0); 26740016Ssam if (fd >= 0) 26840016Ssam (void) close(fd); 26940016Ssam } 27040016Ssam (void) setpgrp(0, getpid()); 27140016Ssam #endif 27246400Skarels if (argc > 2) { 27346400Skarels if ((fd = open(argv[2], O_RDWR)) == -1) { 27446400Skarels perror(argv[2]); 27546400Skarels exit(2); 27646400Skarels } 27746400Skarels (void) dup2(fd, 0); 27846400Skarels if (fd > 2) 27946400Skarels close(fd); 28046400Skarels } 28146400Skarels #ifdef TIOCSCTTY 28246400Skarels if (ioctl(0, TIOCSCTTY, (caddr_t)0) != 0) 28346400Skarels perror("ioctl (TIOCSCTTY)"); 28446400Skarels #endif 28544851Strent } else { 28646400Skarels extern char *getlogin(); 28744851Strent 28846400Skarels if ((name = getlogin()) == NULL) { 28944851Strent (void) fprintf(stderr, "access denied - no username\n"); 29046400Skarels syslog(LOG_ERR, "access denied - getlogin returned 0\n"); 29144851Strent exit(1); 29244851Strent } 29344851Strent findid(name); 29444851Strent } 29544851Strent (void) fchmod(0, 0600); 29644851Strent (void) fprintf(stderr, "starting slip login for %s\n", loginname); 29746400Skarels #ifdef POSIX 29838272Ssam /* set up the line parameters */ 29946400Skarels if (tcgetattr(0, &tios) < 0) { 30046400Skarels syslog(LOG_ERR, "tcgetattr: %m"); 30138272Ssam exit(1); 30238272Ssam } 30340016Ssam otios = tios; 30446400Skarels cfmakeraw(&tios); 30546400Skarels tios.c_iflag &= ~IMAXBEL; 30646400Skarels if (tcsetattr(0, TCSAFLUSH, &tios) < 0) { 30746400Skarels syslog(LOG_ERR, "tcsetattr: %m"); 30838272Ssam exit(1); 30938272Ssam } 31046400Skarels speed = cfgetispeed(&tios); 31144851Strent #else 31244851Strent /* set up the line parameters */ 31344851Strent if (ioctl(0, TIOCGETP, (caddr_t)&tty) < 0) { 31444851Strent syslog(LOG_ERR, "ioctl (TIOCGETP): %m"); 31544851Strent exit(1); 31644851Strent } 31744851Strent otty = tty; 31844851Strent speed = tty.sg_ispeed; 31944851Strent tty.sg_flags = RAW | ANYP; 32044851Strent if (ioctl(0, TIOCSETP, (caddr_t)&tty) < 0) { 32144851Strent syslog(LOG_ERR, "ioctl (TIOCSETP): %m"); 32244851Strent exit(1); 32344851Strent } 32444851Strent #endif 32538373Skarels /* find out what ldisc we started with */ 32638373Skarels if (ioctl(0, TIOCGETD, (caddr_t)&odisc) < 0) { 32738373Skarels syslog(LOG_ERR, "ioctl(TIOCGETD) (1): %m"); 32838373Skarels exit(1); 32938373Skarels } 33038372Ssam ldisc = SLIPDISC; 33138372Ssam if (ioctl(0, TIOCSETD, (caddr_t)&ldisc) < 0) { 33240016Ssam syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); 33338272Ssam exit(1); 33438272Ssam } 33538272Ssam /* find out what unit number we were assigned */ 33646400Skarels if (ioctl(0, SLIOCGUNIT, (caddr_t)&unit) < 0) { 337*46684Skarels syslog(LOG_ERR, "ioctl (SLIOCGUNIT): %m"); 33838272Ssam exit(1); 33938272Ssam } 34044851Strent (void) signal(SIGHUP, hup_handler); 34144851Strent (void) signal(SIGTERM, hup_handler); 34244851Strent 34344851Strent syslog(LOG_INFO, "attaching slip unit %d for %s\n", unit, loginname); 34444851Strent (void)sprintf(logincmd, "%s %d %d %s", loginfile, unit, speed, 34544851Strent loginargs); 34644851Strent /* 34744851Strent * aim stdout and errout at /dev/null so logincmd output won't 34844851Strent * babble into the slip tty line. 34944851Strent */ 35046400Skarels (void) close(1); 35146400Skarels if ((fd = open("/dev/null", O_WRONLY)) != 1) { 35244851Strent if (fd < 0) { 35344851Strent syslog(LOG_ERR, "open /dev/null: %m"); 35438272Ssam exit(1); 35538272Ssam } 35646400Skarels (void) dup2(fd, 1); 35746400Skarels (void) close(fd); 35838272Ssam } 35946400Skarels (void) dup2(1, 2); 36046400Skarels 36146400Skarels /* 36246400Skarels * Run login and logout scripts as root (real and effective); 36346400Skarels * current route(8) is setuid root, and checks the real uid 36446400Skarels * to see whether changes are allowed (or just "route get"). 36546400Skarels */ 36646400Skarels (void) setuid(0); 36744851Strent if (s = system(logincmd)) { 36844851Strent syslog(LOG_ERR, "%s login failed: exit status %d from %s", 36944851Strent loginname, s, loginfile); 37044851Strent (void) ioctl(0, TIOCSETD, (caddr_t)&odisc); 37144851Strent exit(6); 37238272Ssam } 37338373Skarels if (ioctl(0, SLIOCSFLAGS, (caddr_t)&slip_mode) < 0) { 37438373Skarels syslog(LOG_ERR, "ioctl (SLIOCSFLAGS): %m"); 37538373Skarels exit(1); 37638373Skarels } 37738272Ssam 37838272Ssam /* twiddle thumbs until we get a signal */ 37944851Strent while (1) 38038272Ssam sigpause(0); 38138272Ssam 38244851Strent /* NOTREACHED */ 38338272Ssam } 384