1 /* $NetBSD: sliplogin.c,v 1.18 2002/11/16 04:29:01 itojun Exp $ */ 2 3 /*- 4 * Copyright (c) 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/cdefs.h> 37 #ifndef lint 38 __COPYRIGHT("@(#) Copyright (c) 1990, 1993\n\ 39 The Regents of the University of California. All rights reserved.\n"); 40 #endif /* not lint */ 41 42 #ifndef lint 43 #if 0 44 static char sccsid[] = "@(#)sliplogin.c 8.2 (Berkeley) 2/1/94"; 45 #else 46 __RCSID("$NetBSD: sliplogin.c,v 1.18 2002/11/16 04:29:01 itojun Exp $"); 47 #endif 48 #endif /* not lint */ 49 50 /* 51 * sliplogin.c 52 * [MUST BE RUN SUID, SLOPEN DOES A SUSER()!] 53 * 54 * This program initializes its own tty port to be an async TCP/IP interface. 55 * It sets the line discipline to slip, invokes a shell script to initialize 56 * the network interface, then pauses forever waiting for hangup. 57 * 58 * It is a remote descendant of several similar programs with incestuous ties: 59 * - Kirk Smith's slipconf, modified by Richard Johnsson @ DEC WRL. 60 * - slattach, probably by Rick Adams but touched by countless hordes. 61 * - the original sliplogin for 4.2bsd, Doug Kingston the mover behind it. 62 * 63 * There are two forms of usage: 64 * 65 * "sliplogin" 66 * Invoked simply as "sliplogin", the program looks up the username 67 * in the file /etc/slip.hosts. 68 * If an entry is found, the line on fd0 is configured for SLIP operation 69 * as specified in the file. 70 * 71 * "sliplogin IPhostlogin </dev/ttyb" 72 * Invoked by root with a username, the name is looked up in the 73 * /etc/slip.hosts file and if found fd0 is configured as in case 1. 74 */ 75 76 #include <sys/types.h> 77 #include <sys/file.h> 78 #include <sys/param.h> 79 #include <sys/socket.h> 80 #include <sys/stat.h> 81 #include <sys/syslog.h> 82 83 #if BSD >= 199006 84 #define POSIX 85 #endif 86 #ifdef POSIX 87 #include <termios.h> 88 #include <sys/ioctl.h> 89 #include <ttyent.h> 90 #else 91 #include <sgtty.h> 92 #endif 93 #include <net/slip.h> 94 95 #include <ctype.h> 96 #include <err.h> 97 #include <errno.h> 98 #include <netdb.h> 99 #include <signal.h> 100 #include <stdio.h> 101 #include <stdlib.h> 102 #include <string.h> 103 #include <unistd.h> 104 105 #include "pathnames.h" 106 107 int unit; 108 int speed; 109 int uid; 110 char loginargs[BUFSIZ]; 111 char loginfile[MAXPATHLEN]; 112 char loginname[BUFSIZ]; 113 114 void findid __P((char *)); 115 void hup_handler __P((int)); 116 int main __P((int, char **)); 117 const char *sigstr __P((int)); 118 119 void 120 findid(name) 121 char *name; 122 { 123 FILE *fp; 124 static char slopt[5][16]; 125 static char laddr[16]; 126 static char raddr[16]; 127 static char mask[16]; 128 char user[16]; 129 int n; 130 131 (void)strlcpy(loginname, name, sizeof(loginname)); 132 if ((fp = fopen(_PATH_ACCESS, "r")) == NULL) { 133 syslog(LOG_ERR, "%s: %m\n", _PATH_ACCESS); 134 err(1, "%s", _PATH_ACCESS); 135 } 136 while (fgets(loginargs, sizeof(loginargs) - 1, fp)) { 137 if (ferror(fp)) 138 break; 139 n = sscanf(loginargs, "%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s\n", 140 user, laddr, raddr, mask, slopt[0], slopt[1], 141 slopt[2], slopt[3], slopt[4]); 142 if (user[0] == '#' || isspace(user[0])) 143 continue; 144 if (strcmp(user, name) != 0) 145 continue; 146 147 /* 148 * we've found the guy we're looking for -- see if 149 * there's a login file we can use. First check for 150 * one specific to this host. If none found, try for 151 * a generic one. 152 */ 153 (void)snprintf(loginfile, sizeof loginfile, "%s.%s", 154 _PATH_LOGIN, name); 155 if (access(loginfile, R_OK|X_OK) != 0) { 156 (void)strlcpy(loginfile, _PATH_LOGIN, sizeof(loginfile)); 157 if (access(loginfile, R_OK|X_OK)) { 158 fputs("access denied - no login file\n", 159 stderr); 160 syslog(LOG_ERR, 161 "access denied for %s - no %s\n", 162 name, _PATH_LOGIN); 163 exit(5); 164 } 165 } 166 167 (void)fclose(fp); 168 return; 169 } 170 syslog(LOG_ERR, "SLIP access denied for %s\n", name); 171 errx(1, "SLIP access denied for %s", name); 172 /* NOTREACHED */ 173 } 174 175 const char * 176 sigstr(s) 177 int s; 178 { 179 180 if (s > 0 && s < NSIG) 181 return (sys_signame[s]); 182 else { 183 static char buf[32]; 184 185 (void)snprintf(buf, sizeof buf, "sig %d", s); 186 return (buf); 187 } 188 } 189 190 void 191 hup_handler(s) 192 int s; 193 { 194 char logoutfile[MAXPATHLEN]; 195 196 (void)snprintf(logoutfile, sizeof logoutfile, "%s.%s", _PATH_LOGOUT, 197 loginname); 198 if (access(logoutfile, R_OK|X_OK) != 0) 199 (void)strlcpy(logoutfile, _PATH_LOGOUT, sizeof(logoutfile)); 200 if (access(logoutfile, R_OK|X_OK) == 0) { 201 char logincmd[2*MAXPATHLEN+32]; 202 203 (void)snprintf(logincmd, sizeof logincmd, "%s %d %d %s", 204 logoutfile, unit, speed, loginargs); 205 (void)system(logincmd); 206 } 207 (void)close(0); 208 syslog(LOG_INFO, "closed %s slip unit %d (%s)\n", loginname, unit, 209 sigstr(s)); 210 exit(1); 211 /* NOTREACHED */ 212 } 213 214 int 215 main(argc, argv) 216 int argc; 217 char *argv[]; 218 { 219 int fd, s, ldisc, odisc; 220 char *name; 221 #ifdef POSIX 222 struct termios tios, otios; 223 #else 224 struct sgttyb tty, otty; 225 #endif 226 char logincmd[2*BUFSIZ+32]; 227 228 if (strlen(argv[0]) > MAXLOGNAME) 229 errx(1, "login %s too long", argv[0]); 230 if ((name = strrchr(argv[0], '/')) == NULL) 231 name = argv[0]; 232 else 233 name++; 234 s = getdtablesize(); 235 for (fd = 3 ; fd < s ; fd++) 236 (void)close(fd); 237 openlog(name, LOG_PID, LOG_DAEMON); 238 uid = getuid(); 239 if (argc > 1) { 240 findid(argv[1]); 241 242 /* 243 * Disassociate from current controlling terminal, if any, 244 * and ensure that the slip line is our controlling terminal. 245 */ 246 #ifdef POSIX 247 switch (fork()) { 248 case -1: 249 perror("fork"); 250 syslog(LOG_ERR, "could not fork: %m"); 251 exit(1); 252 case 0: 253 break; 254 default: 255 exit(0); 256 } 257 if (setsid() < 0) 258 perror("setsid"); 259 #else 260 if ((fd = open("/dev/tty", O_RDONLY, 0)) >= 0) { 261 extern char *ttyname(); 262 263 (void)ioctl(fd, TIOCNOTTY, (caddr_t)0); 264 (void)close(fd); 265 /* open slip tty again to acquire as controlling tty? */ 266 fd = open(ttyname(0), O_RDWR, 0); 267 if (fd >= 0) 268 (void)close(fd); 269 } 270 (void)setpgrp(0, getpid()); 271 #endif 272 if (argc > 2) { 273 if ((fd = open(argv[2], O_RDWR)) == -1) { 274 perror(argv[2]); 275 exit(2); 276 } 277 (void)dup2(fd, 0); 278 if (fd > 2) 279 close(fd); 280 } 281 #ifdef TIOCSCTTY 282 if (ioctl(STDIN_FILENO, TIOCSCTTY, (caddr_t)0) != 0) 283 perror("ioctl (TIOCSCTTY)"); 284 #endif 285 } else { 286 if ((name = getlogin()) == NULL) { 287 syslog(LOG_ERR, 288 "access denied - getlogin returned 0\n"); 289 errx(1, "access denied - no username"); 290 } 291 findid(name); 292 } 293 if (!isatty(STDIN_FILENO)) { 294 syslog(LOG_ERR, "stdin not a tty"); 295 errx(1, "stdin not a tty"); 296 } 297 (void)fchmod(STDIN_FILENO, 0600); 298 warnx("starting slip login for %s", loginname); 299 #ifdef POSIX 300 /* set up the line parameters */ 301 if (tcgetattr(STDIN_FILENO, &tios) < 0) { 302 syslog(LOG_ERR, "tcgetattr: %m"); 303 exit(1); 304 } 305 otios = tios; 306 cfmakeraw(&tios); 307 tios.c_iflag &= ~IMAXBEL; 308 if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tios) < 0) { 309 syslog(LOG_ERR, "tcsetattr: %m"); 310 exit(1); 311 } 312 speed = cfgetispeed(&tios); 313 #else 314 /* set up the line parameters */ 315 if (ioctl(STDIN_FILENO, TIOCGETP, (caddr_t)&tty) < 0) { 316 syslog(LOG_ERR, "ioctl (TIOCGETP): %m"); 317 exit(1); 318 } 319 otty = tty; 320 speed = tty.sg_ispeed; 321 tty.sg_flags = RAW | ANYP; 322 if (ioctl(STDIN_FILENO, TIOCSETP, (caddr_t)&tty) < 0) { 323 syslog(LOG_ERR, "ioctl (TIOCSETP): %m"); 324 exit(1); 325 } 326 #endif 327 /* find out what ldisc we started with */ 328 if (ioctl(STDIN_FILENO, TIOCGETD, (caddr_t)&odisc) < 0) { 329 syslog(LOG_ERR, "ioctl(TIOCGETD) (1): %m"); 330 exit(1); 331 } 332 ldisc = SLIPDISC; 333 if (ioctl(STDIN_FILENO, TIOCSETD, (caddr_t)&ldisc) < 0) { 334 syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); 335 exit(1); 336 } 337 /* find out what unit number we were assigned */ 338 if (ioctl(STDIN_FILENO, SLIOCGUNIT, (caddr_t)&unit) < 0) { 339 syslog(LOG_ERR, "ioctl (SLIOCGUNIT): %m"); 340 exit(1); 341 } 342 (void)signal(SIGHUP, hup_handler); 343 (void)signal(SIGTERM, hup_handler); 344 345 syslog(LOG_INFO, "attaching slip unit %d for %s\n", unit, loginname); 346 (void)snprintf(logincmd, sizeof logincmd, "%s %d %d %s", loginfile, 347 unit, speed, loginargs); 348 /* 349 * aim stdout and errout at /dev/null so logincmd output won't 350 * babble into the slip tty line. 351 */ 352 (void)close(1); 353 if ((fd = open(_PATH_DEVNULL, O_WRONLY)) != 1) { 354 if (fd < 0) { 355 syslog(LOG_ERR, "open /dev/null: %m"); 356 exit(1); 357 } 358 (void)dup2(fd, 1); 359 (void)close(fd); 360 } 361 (void)dup2(1, 2); 362 363 /* 364 * Run login and logout scripts as root (real and effective); 365 * current route(8) is setuid root, and checks the real uid 366 * to see whether changes are allowed (or just "route get"). 367 */ 368 (void)setuid(0); 369 if ((s = system(logincmd)) != NULL) { 370 syslog(LOG_ERR, "%s login failed: exit status %d from %s", 371 loginname, s, loginfile); 372 (void)ioctl(STDIN_FILENO, TIOCSETD, (caddr_t)&odisc); 373 #ifdef POSIX 374 (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &otios); 375 #else 376 (void)ioctl(STDIN_FILENO, TIOCSETP, (caddr_t)&otty); 377 #endif 378 exit(6); 379 } 380 381 /* twiddle thumbs until we get a signal */ 382 while (1) 383 sigpause(0); 384 385 /* NOTREACHED */ 386 } 387