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*44860Sbostic static char sccsid[] = "@(#)sliplogin.c 5.3 (Berkeley) 07/01/90"; 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" 3438272Ssam * Invoked simply as "sliplogin" and a realuid != 0, the program looks up 3538272Ssam * the uid in /etc/passwd, and then the username in the file /etc/hosts.slip. 3638272Ssam * If and entry is found, the line on fd0 is configured for SLIP operation 3738272Ssam * as specified in the file. 3838272Ssam * 3938272Ssam * "sliplogin IPhost1 </dev/ttyb" 4038272Ssam * Invoked by root with a username, the name is looked up in the 4138272Ssam * /etc/hosts.slip file and if found fd0 is configured as in case 1. 4238272Ssam */ 4338272Ssam 4444851Strent #include <sys/param.h> 4538272Ssam #include <sys/socket.h> 4638372Ssam #include <sys/ioctl.h> 47*44860Sbostic #include <sys/signal.h> 4838272Ssam #include <sys/file.h> 4938272Ssam #include <sys/syslog.h> 5038272Ssam #include <netdb.h> 51*44860Sbostic 5244851Strent #if defined(BSD4_4) 5344851Strent #define TERMIOS 5444851Strent #endif 5544851Strent #ifdef TERMIOS 5644851Strent #include <sys/termios.h> 5738272Ssam #include <ttyent.h> 5844851Strent #endif 5944851Strent #include <netinet/in.h> 6044851Strent #include <net/if.h> 6144851Strent #include <net/if_slvar.h> 6238272Ssam 63*44860Sbostic #include <stdio.h> 64*44860Sbostic #include <errno.h> 65*44860Sbostic #include <ctype.h> 66*44860Sbostic #include <string.h> 67*44860Sbostic #include "pathnames.h" 6838372Ssam 6944851Strent int unit; 70*44860Sbostic int slip_mode; 7144851Strent int speed; 7244851Strent char loginargs[BUFSIZ]; 7344851Strent char loginfile[BUFSIZ]; 7444851Strent char logoutfile[BUFSIZ]; 7544851Strent char loginname[BUFSIZ]; 7638272Ssam 7744851Strent struct slip_modes { 7844851Strent char *sm_name; 7944851Strent int sm_value; 8044851Strent } modes[] = { 8144851Strent "normal", 0, 8244851Strent "compress", SC_COMPRESS, 8344851Strent "noicmp", SC_NOICMP, 8444851Strent "autocomp", SC_AUTOCOMP 8544851Strent }; 8638272Ssam 8738272Ssam void 8844851Strent findid(name) 8944851Strent char *name; 9038272Ssam { 9144851Strent FILE *fp; 9244851Strent static char slopt[5][16]; 9344851Strent static char laddr[16]; 9444851Strent static char raddr[16]; 9544851Strent static char mask[16]; 9644851Strent char user[16]; 9744851Strent int i, j, n; 9838272Ssam 9944851Strent (void)strcpy(loginname, name); 100*44860Sbostic if ((fp = fopen(_PATH_ACCESS, "r")) == NULL) { 101*44860Sbostic (void)fprintf(stderr, "sliplogin: %s: %s\n", 102*44860Sbostic _PATH_ACCESS, strerror(errno)); 103*44860Sbostic syslog(LOG_ERR, "%s: %m\n", _PATH_ACCESS); 104*44860Sbostic exit(1); 10544851Strent } 10644851Strent while (fgets(loginargs, sizeof(loginargs) - 1, fp)) { 10744851Strent if (ferror(fp)) 10844851Strent break; 10944851Strent n = sscanf(loginargs, "%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s\n", 11044851Strent user, laddr, raddr, mask, slopt[0], slopt[1], 11144851Strent slopt[2], slopt[3], slopt[4]); 11244851Strent if (user[0] == '#' || isspace(user[0])) 11344851Strent continue; 11444851Strent if (strcmp(user, name) != 0) 11544851Strent continue; 11638272Ssam 11744851Strent slip_mode = 0; 11844851Strent for (i = 0; i < n - 4; i++) { 11944851Strent for (j = 0; j < sizeof(modes)/sizeof(struct slip_modes); 12044851Strent j++) { 12144851Strent if (strcmp(modes[j].sm_name, slopt[i]) == 0) { 12244851Strent slip_mode |= modes[j].sm_value; 12344851Strent break; 12444851Strent } 12544851Strent } 12644851Strent } 12738272Ssam 12844851Strent /* 12944851Strent * we've found the guy we're looking for -- see if 13044851Strent * there's a login file we can use. First check for 13144851Strent * one specific to this host. If none found, try for 13244851Strent * a generic one. 13344851Strent */ 134*44860Sbostic (void)sprintf(loginfile, "%s.%s", _PATH_LOGIN, name); 13544851Strent if (access(loginfile, R_OK|X_OK)) { 136*44860Sbostic (void)strcpy(loginfile, _PATH_LOGIN); 137*44860Sbostic (void)strcpy(logoutfile, _PATH_LOGOUT); 13844851Strent if (access(loginfile, R_OK|X_OK)) { 13944851Strent fputs("access denied - no login file\n", 14044851Strent stderr); 14144851Strent syslog(LOG_ERR, 14244851Strent "access denied for %s - no %s\n", 143*44860Sbostic name, _PATH_LOGIN); 14444851Strent exit(5); 14544851Strent } 14644851Strent } else 147*44860Sbostic (void)sprintf(logoutfile, "%s.%s", _PATH_LOGOUT, name); 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 { 20744851Strent if (access(logoutfile, R_OK|X_OK) == 0) { 20844851Strent char logincmd[2*BUFSIZ+32]; 20940016Ssam 21044851Strent (void)sprintf(logincmd, "%s %d %d %s", logoutfile, unit, speed, 21144851Strent loginargs); 21244851Strent (void)system(logincmd); 21344851Strent } 21444851Strent (void)close(0); 21544851Strent syslog(LOG_INFO, "closed %s slip unit %d (%s)\n", loginname, unit, 21644851Strent sigstr(s)); 21744851Strent exit(1); 21844851Strent /* NOTREACHED */ 21938373Skarels } 22038373Skarels 22138272Ssam main(argc, argv) 22238272Ssam int argc; 22338272Ssam char *argv[]; 22438272Ssam { 22538373Skarels int fd, s, ldisc, odisc; 22644851Strent char *name; 22744851Strent #ifdef TERMIOS 22838373Skarels struct termios tios, otios; 22944851Strent #else 23044851Strent struct sgttyb tty, otty; 23144851Strent #endif 23244851Strent char logincmd[2*BUFSIZ+32]; 23344851Strent extern uid_t getuid(); 23438272Ssam 23544851Strent if ((name = strrchr(argv[0], '/')) == NULL) 23644851Strent name = argv[0]; 23738272Ssam s = getdtablesize(); 23838272Ssam for (fd = 3 ; fd < s ; fd++) 23944851Strent (void) close(fd); 24044851Strent openlog(name, LOG_PID, LOG_DAEMON); 24144851Strent if (argc > 1) { 24244851Strent if (argc > 2) { 24344851Strent (void)fprintf(stderr, "Usage: %s loginname\n", argv[0]); 24438272Ssam exit(1); 24538272Ssam } 24644851Strent findid(argv[1]); 24744851Strent 24840016Ssam /* 24940016Ssam * Disassociate from current controlling terminal, if any, 25040016Ssam * and ensure that the slip line is our controlling terminal. 25140016Ssam */ 25244851Strent #ifdef TERMIOS 25344851Strent (void) setsid(); 25444851Strent (void) ioctl(0, TIOCSCTTY, (caddr_t)0); 25544851Strent #else 25640016Ssam if ((fd = open("/dev/tty", O_RDONLY, 0)) >= 0) { 25744851Strent extern char *ttyname(); 25844851Strent 25944851Strent (void) ioctl(fd, TIOCNOTTY, (caddr_t)0); 26040016Ssam (void) close(fd); 26140016Ssam /* open slip tty again to acquire as controlling tty? */ 26240016Ssam fd = open(ttyname(0), O_RDWR, 0); 26340016Ssam if (fd >= 0) 26440016Ssam (void) close(fd); 26540016Ssam } 26640016Ssam (void) setpgrp(0, getpid()); 26740016Ssam #endif 26844851Strent } else { 26944851Strent extern char *getenv(); 27044851Strent 27144851Strent if ((name = getenv("USER")) == NULL) { 27244851Strent (void) fprintf(stderr, "access denied - no username\n"); 27344851Strent syslog(LOG_ERR, "access denied - no username\n"); 27444851Strent exit(1); 27544851Strent } 27644851Strent findid(name); 27744851Strent } 27844851Strent (void) fchmod(0, 0600); 27944851Strent (void) fprintf(stderr, "starting slip login for %s\n", loginname); 28044851Strent #ifdef TERMIOS 28138272Ssam /* set up the line parameters */ 28240016Ssam if (ioctl(0, TIOCGETA, (caddr_t)&tios) < 0) { 28340016Ssam syslog(LOG_ERR, "ioctl (TIOCGETA): %m"); 28438272Ssam exit(1); 28538272Ssam } 28640016Ssam otios = tios; 28740016Ssam tios.c_cflag = CS8|CREAD|HUPCL; 28838272Ssam tios.c_iflag = IGNBRK; 28938372Ssam tios.c_oflag = tios.c_lflag = 0; 29040016Ssam if (ioctl(0, TIOCSETA, (caddr_t)&tios) < 0) { 29140016Ssam syslog(LOG_ERR, "ioctl (TIOCSETA) (1): %m"); 29238272Ssam exit(1); 29338272Ssam } 29444851Strent #else 29544851Strent /* set up the line parameters */ 29644851Strent if (ioctl(0, TIOCGETP, (caddr_t)&tty) < 0) { 29744851Strent syslog(LOG_ERR, "ioctl (TIOCGETP): %m"); 29844851Strent exit(1); 29944851Strent } 30044851Strent otty = tty; 30144851Strent speed = tty.sg_ispeed; 30244851Strent tty.sg_flags = RAW | ANYP; 30344851Strent if (ioctl(0, TIOCSETP, (caddr_t)&tty) < 0) { 30444851Strent syslog(LOG_ERR, "ioctl (TIOCSETP): %m"); 30544851Strent exit(1); 30644851Strent } 30744851Strent #endif 30838373Skarels /* find out what ldisc we started with */ 30938373Skarels if (ioctl(0, TIOCGETD, (caddr_t)&odisc) < 0) { 31038373Skarels syslog(LOG_ERR, "ioctl(TIOCGETD) (1): %m"); 31138373Skarels exit(1); 31238373Skarels } 31338372Ssam ldisc = SLIPDISC; 31438372Ssam if (ioctl(0, TIOCSETD, (caddr_t)&ldisc) < 0) { 31540016Ssam syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); 31638272Ssam exit(1); 31738272Ssam } 31838272Ssam /* find out what unit number we were assigned */ 31938372Ssam if (ioctl(0, TIOCGETD, (caddr_t)&unit) < 0) { 32038373Skarels syslog(LOG_ERR, "ioctl (TIOCGETD) (2): %m"); 32138272Ssam exit(1); 32238272Ssam } 32344851Strent (void) signal(SIGHUP, hup_handler); 32444851Strent (void) signal(SIGTERM, hup_handler); 32544851Strent 32644851Strent syslog(LOG_INFO, "attaching slip unit %d for %s\n", unit, loginname); 32744851Strent (void)sprintf(logincmd, "%s %d %d %s", loginfile, unit, speed, 32844851Strent loginargs); 32944851Strent /* 33044851Strent * aim stdout and errout at /dev/null so logincmd output won't 33144851Strent * babble into the slip tty line. 33244851Strent */ 33344851Strent (void)close(1); 33444851Strent if ((fd = open("/dev/null", O_WRONLY, 0)) != 1) { 33544851Strent if (fd < 0) { 33644851Strent syslog(LOG_ERR, "open /dev/null: %m"); 33738272Ssam exit(1); 33838272Ssam } 33944851Strent (void)dup2(fd, 1); 34044851Strent (void)close(fd); 34138272Ssam } 34244851Strent (void)dup2(1,2); 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 } 34938373Skarels if (ioctl(0, SLIOCSFLAGS, (caddr_t)&slip_mode) < 0) { 35038373Skarels syslog(LOG_ERR, "ioctl (SLIOCSFLAGS): %m"); 35138373Skarels exit(1); 35238373Skarels } 35338272Ssam 35438272Ssam /* twiddle thumbs until we get a signal */ 35544851Strent while (1) 35638272Ssam sigpause(0); 35738272Ssam 35844851Strent /* NOTREACHED */ 35938272Ssam } 360