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*44851Strent static char sccsid[] = "@(#)sliplogin.c 5.2 (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. 23*44851Strent * It sets the line discipline to slip, invokes a shell script to initialize 24*44851Strent * 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 * 31*44851Strent * 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 4438272Ssam #include <sys/types.h> 45*44851Strent #include <sys/param.h> 4638272Ssam #include <sys/socket.h> 4738372Ssam #include <sys/ioctl.h> 4838272Ssam #include <sys/file.h> 4938272Ssam #include <sys/syslog.h> 5038272Ssam #include <stdio.h> 5138272Ssam #include <errno.h> 5238272Ssam #include <ctype.h> 5338272Ssam #include <netdb.h> 5438272Ssam #include <signal.h> 55*44851Strent #include <string.h> 56*44851Strent #if defined(BSD4_4) 57*44851Strent #define TERMIOS 58*44851Strent #endif 59*44851Strent #ifdef TERMIOS 60*44851Strent #include <sys/termios.h> 6138272Ssam #include <ttyent.h> 62*44851Strent #endif 63*44851Strent #include <netinet/in.h> 64*44851Strent #include <net/if.h> 65*44851Strent #include <net/if_slvar.h> 6638272Ssam 67*44851Strent #ifndef ACCESSFILE 68*44851Strent #define ACCESSFILE "/etc/slip.hosts" 69*44851Strent #endif 70*44851Strent #ifndef LOGINFILE 71*44851Strent #define LOGINFILE "/etc/slip.login" 72*44851Strent #define LOGOUTFILE "/etc/slip.logout" 73*44851Strent #endif 7438372Ssam 7538372Ssam 76*44851Strent int unit; 77*44851Strent int slip_mode; 78*44851Strent int speed; 79*44851Strent char loginargs[BUFSIZ]; 80*44851Strent char loginfile[BUFSIZ]; 81*44851Strent char logoutfile[BUFSIZ]; 82*44851Strent char loginname[BUFSIZ]; 8338272Ssam 84*44851Strent struct slip_modes { 85*44851Strent char *sm_name; 86*44851Strent int sm_value; 87*44851Strent } modes[] = { 88*44851Strent "normal", 0, 89*44851Strent "compress", SC_COMPRESS, 90*44851Strent "noicmp", SC_NOICMP, 91*44851Strent "autocomp", SC_AUTOCOMP 92*44851Strent }; 9338272Ssam 9438272Ssam void 95*44851Strent findid(name) 96*44851Strent char *name; 9738272Ssam { 98*44851Strent FILE *fp; 99*44851Strent static char slopt[5][16]; 100*44851Strent static char laddr[16]; 101*44851Strent static char raddr[16]; 102*44851Strent static char mask[16]; 103*44851Strent char user[16]; 104*44851Strent int i, j, n; 10538272Ssam 106*44851Strent (void)strcpy(loginname, name); 107*44851Strent if ((fp = fopen(ACCESSFILE, "r")) == NULL) { 108*44851Strent perror(ACCESSFILE); 109*44851Strent syslog(LOG_ERR, "%s: %m\n", ACCESSFILE); 110*44851Strent exit(3); 111*44851Strent } 112*44851Strent while (fgets(loginargs, sizeof(loginargs) - 1, fp)) { 11340016Ssam 114*44851Strent if (ferror(fp)) 115*44851Strent break; 116*44851Strent n = sscanf(loginargs, "%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s\n", 117*44851Strent user, laddr, raddr, mask, slopt[0], slopt[1], 118*44851Strent slopt[2], slopt[3], slopt[4]); 119*44851Strent if (user[0] == '#' || isspace(user[0])) 120*44851Strent continue; 121*44851Strent if (strcmp(user, name) != 0) 122*44851Strent continue; 12338272Ssam 124*44851Strent slip_mode = 0; 125*44851Strent for (i = 0; i < n - 4; i++) { 126*44851Strent for (j = 0; j < sizeof(modes)/sizeof(struct slip_modes); 127*44851Strent j++) { 128*44851Strent if (strcmp(modes[j].sm_name, slopt[i]) == 0) { 129*44851Strent slip_mode |= modes[j].sm_value; 130*44851Strent break; 131*44851Strent } 132*44851Strent } 133*44851Strent } 13438272Ssam 135*44851Strent /* 136*44851Strent * we've found the guy we're looking for -- see if 137*44851Strent * there's a login file we can use. First check for 138*44851Strent * one specific to this host. If none found, try for 139*44851Strent * a generic one. 140*44851Strent */ 141*44851Strent (void)sprintf(loginfile, "%s.%s", LOGINFILE, name); 142*44851Strent if (access(loginfile, R_OK|X_OK)) { 143*44851Strent (void)strcpy(loginfile, LOGINFILE); 144*44851Strent (void)strcpy(logoutfile, LOGOUTFILE); 145*44851Strent if (access(loginfile, R_OK|X_OK)) { 146*44851Strent fputs("access denied - no login file\n", 147*44851Strent stderr); 148*44851Strent syslog(LOG_ERR, 149*44851Strent "access denied for %s - no %s\n", 150*44851Strent name, LOGINFILE); 151*44851Strent exit(5); 152*44851Strent } 153*44851Strent } else 154*44851Strent (void)sprintf(logoutfile, "%s.%s", LOGOUTFILE, name); 155*44851Strent 156*44851Strent (void) fclose(fp); 157*44851Strent return; 158*44851Strent } 159*44851Strent (void)fprintf(stderr, "SLIP access denied for %s\n", name); 160*44851Strent syslog(LOG_ERR, "SLIP access denied for %s\n", name); 161*44851Strent exit(4); 162*44851Strent /* NOTREACHED */ 16338272Ssam } 16438272Ssam 165*44851Strent char * 166*44851Strent sigstr(s) 167*44851Strent int s; 168*44851Strent { 169*44851Strent static char buf[32]; 17038272Ssam 171*44851Strent switch (s) { 172*44851Strent case SIGHUP: return("HUP"); 173*44851Strent case SIGINT: return("INT"); 174*44851Strent case SIGQUIT: return("QUIT"); 175*44851Strent case SIGILL: return("ILL"); 176*44851Strent case SIGTRAP: return("TRAP"); 177*44851Strent case SIGIOT: return("IOT"); 178*44851Strent case SIGEMT: return("EMT"); 179*44851Strent case SIGFPE: return("FPE"); 180*44851Strent case SIGKILL: return("KILL"); 181*44851Strent case SIGBUS: return("BUS"); 182*44851Strent case SIGSEGV: return("SEGV"); 183*44851Strent case SIGSYS: return("SYS"); 184*44851Strent case SIGPIPE: return("PIPE"); 185*44851Strent case SIGALRM: return("ALRM"); 186*44851Strent case SIGTERM: return("TERM"); 187*44851Strent case SIGURG: return("URG"); 188*44851Strent case SIGSTOP: return("STOP"); 189*44851Strent case SIGTSTP: return("TSTP"); 190*44851Strent case SIGCONT: return("CONT"); 191*44851Strent case SIGCHLD: return("CHLD"); 192*44851Strent case SIGTTIN: return("TTIN"); 193*44851Strent case SIGTTOU: return("TTOU"); 194*44851Strent case SIGIO: return("IO"); 195*44851Strent case SIGXCPU: return("XCPU"); 196*44851Strent case SIGXFSZ: return("XFSZ"); 197*44851Strent case SIGVTALRM: return("VTALRM"); 198*44851Strent case SIGPROF: return("PROF"); 199*44851Strent case SIGWINCH: return("WINCH"); 200*44851Strent #ifdef SIGLOST 201*44851Strent case SIGLOST: return("LOST"); 202*44851Strent #endif 203*44851Strent case SIGUSR1: return("USR1"); 204*44851Strent case SIGUSR2: return("USR2"); 205*44851Strent } 206*44851Strent (void)sprintf(buf, "sig %d", s); 207*44851Strent return(buf); 208*44851Strent } 20938272Ssam 210*44851Strent int 21140016Ssam hup_handler(s) 21240016Ssam int s; 21338373Skarels { 214*44851Strent if (access(logoutfile, R_OK|X_OK) == 0) { 215*44851Strent char logincmd[2*BUFSIZ+32]; 21640016Ssam 217*44851Strent (void)sprintf(logincmd, "%s %d %d %s", logoutfile, unit, speed, 218*44851Strent loginargs); 219*44851Strent (void)system(logincmd); 220*44851Strent } 221*44851Strent (void)close(0); 222*44851Strent syslog(LOG_INFO, "closed %s slip unit %d (%s)\n", loginname, unit, 223*44851Strent sigstr(s)); 224*44851Strent exit(1); 225*44851Strent /* NOTREACHED */ 22638373Skarels } 22738373Skarels 22838272Ssam main(argc, argv) 22938272Ssam int argc; 23038272Ssam char *argv[]; 23138272Ssam { 23238373Skarels int fd, s, ldisc, odisc; 233*44851Strent char *name; 234*44851Strent #ifdef TERMIOS 23538373Skarels struct termios tios, otios; 236*44851Strent #else 237*44851Strent struct sgttyb tty, otty; 238*44851Strent #endif 239*44851Strent char logincmd[2*BUFSIZ+32]; 240*44851Strent extern uid_t getuid(); 24138272Ssam 242*44851Strent if ((name = strrchr(argv[0], '/')) == NULL) 243*44851Strent name = argv[0]; 24438272Ssam s = getdtablesize(); 24538272Ssam for (fd = 3 ; fd < s ; fd++) 246*44851Strent (void) close(fd); 247*44851Strent openlog(name, LOG_PID, LOG_DAEMON); 248*44851Strent if (argc > 1) { 249*44851Strent if (argc > 2) { 250*44851Strent (void)fprintf(stderr, "Usage: %s loginname\n", argv[0]); 25138272Ssam exit(1); 25238272Ssam } 253*44851Strent findid(argv[1]); 254*44851Strent 25540016Ssam /* 25640016Ssam * Disassociate from current controlling terminal, if any, 25740016Ssam * and ensure that the slip line is our controlling terminal. 25840016Ssam */ 259*44851Strent #ifdef TERMIOS 260*44851Strent (void) setsid(); 261*44851Strent (void) ioctl(0, TIOCSCTTY, (caddr_t)0); 262*44851Strent #else 26340016Ssam if ((fd = open("/dev/tty", O_RDONLY, 0)) >= 0) { 264*44851Strent extern char *ttyname(); 265*44851Strent 266*44851Strent (void) ioctl(fd, TIOCNOTTY, (caddr_t)0); 26740016Ssam (void) close(fd); 26840016Ssam /* open slip tty again to acquire as controlling tty? */ 26940016Ssam fd = open(ttyname(0), O_RDWR, 0); 27040016Ssam if (fd >= 0) 27140016Ssam (void) close(fd); 27240016Ssam } 27340016Ssam (void) setpgrp(0, getpid()); 27440016Ssam #endif 275*44851Strent } else { 276*44851Strent extern char *getenv(); 277*44851Strent 278*44851Strent if ((name = getenv("USER")) == NULL) { 279*44851Strent (void) fprintf(stderr, "access denied - no username\n"); 280*44851Strent syslog(LOG_ERR, "access denied - no username\n"); 281*44851Strent exit(1); 282*44851Strent } 283*44851Strent findid(name); 284*44851Strent } 285*44851Strent (void) fchmod(0, 0600); 286*44851Strent (void) fprintf(stderr, "starting slip login for %s\n", loginname); 287*44851Strent #ifdef TERMIOS 28838272Ssam /* set up the line parameters */ 28940016Ssam if (ioctl(0, TIOCGETA, (caddr_t)&tios) < 0) { 29040016Ssam syslog(LOG_ERR, "ioctl (TIOCGETA): %m"); 29138272Ssam exit(1); 29238272Ssam } 29340016Ssam otios = tios; 29440016Ssam tios.c_cflag = CS8|CREAD|HUPCL; 29538272Ssam tios.c_iflag = IGNBRK; 29638372Ssam tios.c_oflag = tios.c_lflag = 0; 29740016Ssam if (ioctl(0, TIOCSETA, (caddr_t)&tios) < 0) { 29840016Ssam syslog(LOG_ERR, "ioctl (TIOCSETA) (1): %m"); 29938272Ssam exit(1); 30038272Ssam } 301*44851Strent #else 302*44851Strent /* set up the line parameters */ 303*44851Strent if (ioctl(0, TIOCGETP, (caddr_t)&tty) < 0) { 304*44851Strent syslog(LOG_ERR, "ioctl (TIOCGETP): %m"); 305*44851Strent exit(1); 306*44851Strent } 307*44851Strent otty = tty; 308*44851Strent speed = tty.sg_ispeed; 309*44851Strent tty.sg_flags = RAW | ANYP; 310*44851Strent if (ioctl(0, TIOCSETP, (caddr_t)&tty) < 0) { 311*44851Strent syslog(LOG_ERR, "ioctl (TIOCSETP): %m"); 312*44851Strent exit(1); 313*44851Strent } 314*44851Strent #endif 31538373Skarels /* find out what ldisc we started with */ 31638373Skarels if (ioctl(0, TIOCGETD, (caddr_t)&odisc) < 0) { 31738373Skarels syslog(LOG_ERR, "ioctl(TIOCGETD) (1): %m"); 31838373Skarels exit(1); 31938373Skarels } 32038372Ssam ldisc = SLIPDISC; 32138372Ssam if (ioctl(0, TIOCSETD, (caddr_t)&ldisc) < 0) { 32240016Ssam syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); 32338272Ssam exit(1); 32438272Ssam } 32538272Ssam /* find out what unit number we were assigned */ 32638372Ssam if (ioctl(0, TIOCGETD, (caddr_t)&unit) < 0) { 32738373Skarels syslog(LOG_ERR, "ioctl (TIOCGETD) (2): %m"); 32838272Ssam exit(1); 32938272Ssam } 330*44851Strent (void) signal(SIGHUP, hup_handler); 331*44851Strent (void) signal(SIGTERM, hup_handler); 332*44851Strent 333*44851Strent syslog(LOG_INFO, "attaching slip unit %d for %s\n", unit, loginname); 334*44851Strent (void)sprintf(logincmd, "%s %d %d %s", loginfile, unit, speed, 335*44851Strent loginargs); 336*44851Strent /* 337*44851Strent * aim stdout and errout at /dev/null so logincmd output won't 338*44851Strent * babble into the slip tty line. 339*44851Strent */ 340*44851Strent (void)close(1); 341*44851Strent if ((fd = open("/dev/null", O_WRONLY, 0)) != 1) { 342*44851Strent if (fd < 0) { 343*44851Strent syslog(LOG_ERR, "open /dev/null: %m"); 34438272Ssam exit(1); 34538272Ssam } 346*44851Strent (void)dup2(fd, 1); 347*44851Strent (void)close(fd); 34838272Ssam } 349*44851Strent (void)dup2(1,2); 350*44851Strent if (s = system(logincmd)) { 351*44851Strent syslog(LOG_ERR, "%s login failed: exit status %d from %s", 352*44851Strent loginname, s, loginfile); 353*44851Strent (void) ioctl(0, TIOCSETD, (caddr_t)&odisc); 354*44851Strent exit(6); 35538272Ssam } 35638373Skarels if (ioctl(0, SLIOCSFLAGS, (caddr_t)&slip_mode) < 0) { 35738373Skarels syslog(LOG_ERR, "ioctl (SLIOCSFLAGS): %m"); 35838373Skarels exit(1); 35938373Skarels } 36038272Ssam 36138272Ssam /* twiddle thumbs until we get a signal */ 362*44851Strent while (1) 36338272Ssam sigpause(0); 36438272Ssam 365*44851Strent /* NOTREACHED */ 36638272Ssam } 367