1 #ifndef lint 2 static char sccsid[] = "@(#)sliplogin.c 1.4 (Berkeley) 02/06/90"; 3 /* from static char *sccsid = "@(#)sliplogin.c 1.3 MS/ACF 89/04/18"; */ 4 #endif 5 6 /* 7 * sliplogin.c 8 * [MUST BE RUN SUID, SLOPEN DOES A SUSER()!] 9 * 10 * This program initializes its own tty port to be an async TCP/IP interface. 11 * It merely sets up the SLIP module all by its lonesome on the STREAMS stack, 12 * initializes the network interface, and pauses forever waiting for hangup. 13 * 14 * It is a remote descendant of several similar programs with incestuous ties: 15 * - Kirk Smith's slipconf, modified by Richard Johnsson @ DEC WRL. 16 * - slattach, probably by Rick Adams but touched by countless hordes. 17 * - the original sliplogin for 4.2bsd, Doug Kingston the mover behind it. 18 * - a simple slattach-like program used to test the STREAMS SLIP code. 19 * 20 * There are three basic forms of usage: 21 * 22 * "sliplogin" 23 * Invoked simply as "sliplogin" and a realuid != 0, the program looks up 24 * the uid in /etc/passwd, and then the username in the file /etc/hosts.slip. 25 * If and entry is found, the line on fd0 is configured for SLIP operation 26 * as specified in the file. 27 * 28 * "sliplogin IPhost1 </dev/ttyb" 29 * Invoked by root with a username, the name is looked up in the 30 * /etc/hosts.slip file and if found fd0 is configured as in case 1. 31 * 32 * "sliplogin 192.100.1.1 192.100.1.2 255.255.255.0 < /dev/ttyb" 33 * Finally, if invoked with a remote addr, local addr, and optionally 34 * a net mask, the line on fd0 is setup as specified if the user is root. 35 * 36 * Doug Kingston 8810?? - logging + first pass at adding I_STR ioctl's 37 * Rayan Zachariassen 881011 - version for SunOS STREAMS SLIP 38 */ 39 40 #include <sys/types.h> 41 #include <sys/socket.h> 42 #include <sys/termios.h> 43 #include <sys/ioctl.h> 44 #include <sys/file.h> 45 #include <sys/syslog.h> 46 47 #include <netinet/in.h> 48 #include <net/if.h> 49 #include <net/if_slvar.h> /* XXX */ 50 51 #include <stdio.h> 52 #include <errno.h> 53 #include <ctype.h> 54 #include <netdb.h> 55 56 #include <signal.h> 57 #include <strings.h> 58 #include <pwd.h> 59 #include <ttyent.h> 60 61 #define SLIPIFNAME "sl" 62 63 #define ADDR 1 64 #define MASK 2 65 66 #define DCD_CHECK_INTERVAL 0 /* if > 0, time between automatic DCD checks */ 67 #define DCD_SETTLING_TIME 1 /* time between DCD change and status check */ 68 69 int gotalarm = 0; 70 int timeleft = DCD_CHECK_INTERVAL; 71 72 #if defined(SIGDCD) && SIGDCD > 0 73 void 74 dcd_handler() 75 { 76 #if DCD_SETTLING_TIME > 0 77 timeleft = alarm(DCD_SETTLING_TIME); 78 #else 79 gotalarm = 1; 80 #endif /* DCD_SETTLING_TIME */ 81 } 82 #endif 83 84 #if DCD_CHECK_INTERVAL > 0 85 void 86 alarm_handler() 87 { 88 #ifdef SIGDCD 89 if (timeleft > DCD_SETTLING_TIME) 90 (void) alarm(timeleft-DCD_SETTLING_TIME); 91 else 92 #endif /* SIGDCD */ 93 (void) alarm(DCD_CHECK_INTERVAL); 94 gotalarm = 1; 95 timeleft = 0; 96 } 97 98 /* Use TIOCMGET to test if DCD is low on the port of the passed descriptor */ 99 100 int 101 lowdcd(fd) 102 int fd; 103 { 104 int mbits; 105 106 if (ioctl(fd, TIOCMGET, (caddr_t)&mbits) < 0) 107 return 1; /* port is dead, we die */ 108 return !(mbits & TIOCM_CAR); 109 } 110 #endif /* DCD_CHECK_INTERVAL > 0 */ 111 112 char *Accessfile = "/etc/hosts.slip"; 113 114 extern char *malloc(), *ttyname(); 115 extern struct passwd *getpwuid(); 116 117 char *dstaddr, *localaddr, *netmask; 118 int slip_mode, unit; 119 120 struct slip_modes { 121 char *sm_name; 122 int sm_value; 123 } modes[] = { 124 "normal", 0, /* slip "standard" ala Rick Adams */ 125 "compress", SC_COMPRESS, /* Van Jacobsen's tcp header comp. */ 126 "noicmp", SC_NOICMP, /* Sam's(?) ICMP suppression */ 127 } ; 128 129 void 130 hup_handler(s) 131 int s; 132 { 133 134 syslog(LOG_INFO, 135 "%s%d: connection closed: process aborted, sig %d, remote %s\n", 136 SLIPIFNAME, unit, s, dstaddr); 137 if (close(0) < 0) 138 syslog(LOG_ERR, "(hup) close: %m"); 139 else 140 syslog(LOG_INFO, "(hup) close completed"); 141 exit(1) ; 142 } 143 144 main(argc, argv) 145 int argc; 146 char *argv[]; 147 { 148 int fd, s, ldisc, odisc; 149 struct termios tios, otios; 150 struct ifreq ifr; 151 152 s = getdtablesize(); 153 for (fd = 3 ; fd < s ; fd++) 154 close(fd); 155 openlog("sliplogin", LOG_PID, LOG_DAEMON); 156 if (getuid() == 0) { 157 if (argc <= 1) { 158 fprintf(stderr, "Usage: %s loginname\n", argv[0]); 159 fprintf(stderr, " or: %s dstaddr localaddr [mask]\n", 160 argv[0]); 161 exit(1); 162 } else if (argc == 2) { 163 findid(argv[1]); 164 fprintf(stderr, "local %s remote %s mask %s\n", 165 localaddr, dstaddr, netmask); 166 } if (argc > 2) { 167 if (argc < 3 || argc > 4) { 168 fprintf(stderr, 169 "Usage: %s dstaddr localaddr [mask]\n", 170 argv[0]); 171 exit(1); 172 } 173 dstaddr = argv[1]; 174 localaddr = argv[2]; 175 if (argc == 4) 176 netmask = argv[3]; 177 else 178 netmask = "default"; 179 } 180 /* 181 * Disassociate from current controlling terminal, if any, 182 * and ensure that the slip line is our controlling terminal. 183 */ 184 #if !defined(BSD) || BSD < 198810 185 if ((fd = open("/dev/tty", O_RDONLY, 0)) >= 0) { 186 (void) ioctl(fd, TIOCNOTTY, 0); 187 (void) close(fd); 188 /* open slip tty again to acquire as controlling tty? */ 189 fd = open(ttyname(0), O_RDWR, 0); 190 if (fd >= 0) 191 (void) close(fd); 192 } 193 (void) setpgrp(0, getpid()); 194 #else 195 (void) setsid(); 196 (void) ioctl(0, TIOCSCTTY, 0); /* not sure this will work */ 197 #endif 198 } else 199 findid((char *)0); 200 fchmod(0, 0600); 201 /* set up the line parameters */ 202 if (ioctl(0, TIOCGETA, (caddr_t)&tios) < 0) { 203 syslog(LOG_ERR, "ioctl (TIOCGETA): %m"); 204 exit(1); 205 } 206 otios = tios; 207 tios.c_cflag = CS8|CREAD|HUPCL; 208 tios.c_iflag = IGNBRK; 209 tios.c_oflag = tios.c_lflag = 0; 210 if (ioctl(0, TIOCSETA, (caddr_t)&tios) < 0) { 211 syslog(LOG_ERR, "ioctl (TIOCSETA) (1): %m"); 212 exit(1); 213 } 214 /* find out what ldisc we started with */ 215 if (ioctl(0, TIOCGETD, (caddr_t)&odisc) < 0) { 216 syslog(LOG_ERR, "ioctl(TIOCGETD) (1): %m"); 217 exit(1); 218 } 219 ldisc = SLIPDISC; 220 if (ioctl(0, TIOCSETD, (caddr_t)&ldisc) < 0) { 221 syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); 222 exit(1); 223 } 224 /* find out what unit number we were assigned */ 225 if (ioctl(0, TIOCGETD, (caddr_t)&unit) < 0) { 226 syslog(LOG_ERR, "ioctl (TIOCGETD) (2): %m"); 227 exit(1); 228 } 229 syslog(LOG_INFO, "attaching %s%d: local %s remote %s mask %s\n", 230 SLIPIFNAME, unit, localaddr, dstaddr, netmask); 231 #ifdef notdef 232 /* set the local and remote interface addresses */ 233 s = socket(AF_INET, SOCK_DGRAM, 0); 234 if (getuid() != 0 || argc == 4) { 235 (void) sprintf(ifr.ifr_name, "%s%d", SLIPIFNAME, unit); 236 in_getaddr(netmask, &ifr.ifr_addr, MASK); 237 if (ioctl(s, SIOCSIFNETMASK, (caddr_t)&ifr) < 0) { 238 syslog(LOG_ERR, "ioctl (SIOCSIFNETMASK): %m"); 239 exit(1); 240 } 241 } 242 (void) sprintf(ifr.ifr_name, "%s%d", SLIPIFNAME, unit); 243 in_getaddr(dstaddr, &ifr.ifr_addr, ADDR); 244 if (ioctl(s, SIOCSIFDSTADDR, (caddr_t)&ifr) < 0) { 245 syslog(LOG_ERR, "ioctl (SIOCSIFDSTADDR): %m"); 246 exit(1); 247 } 248 (void) sprintf(ifr.ifr_name, "%s%d", SLIPIFNAME, unit); 249 in_getaddr(localaddr, &ifr.ifr_addr, ADDR); 250 /* this has the side-effect of marking the interface up */ 251 if (ioctl(s, SIOCSIFADDR, (caddr_t)&ifr) < 0) { 252 syslog(LOG_ERR, "ioctl (SIOCSIFADDR): %m"); 253 exit(1); 254 } 255 #else 256 /* XXX -- give up for now and just invoke ifconfig XXX */ 257 { char cmd[256]; 258 sprintf(cmd, "/sbin/ifconfig %s%d inet %s %s netmask %s", 259 SLIPIFNAME, unit, localaddr, dstaddr, netmask); 260 system(cmd); 261 } 262 #endif 263 if (ioctl(0, SLIOCSFLAGS, (caddr_t)&slip_mode) < 0) { 264 syslog(LOG_ERR, "ioctl (SLIOCSFLAGS): %m"); 265 exit(1); 266 } 267 268 /* set up signal handlers */ 269 #if defined(SIGDCD) && SIGDCD > 0 270 (void) signal(SIGDCD, dcd_handler); 271 #endif 272 (void) sigblock(sigmask(SIGALRM)); 273 (void) signal(SIGHUP, hup_handler); 274 (void) signal(SIGTERM, hup_handler); 275 276 #if DCD_CHECK_INTERVAL > 0 277 /* timeleft = 60 * 60 * 24 * 365 ; (void) alarm(timeleft); */ 278 (void) signal(SIGALRM, alarm_handler); 279 (void) alarm(DCD_CHECK_INTERVAL); 280 #endif 281 282 /* twiddle thumbs until we get a signal */ 283 while (1) { 284 sigpause(0); 285 #if DCD_CHECK_INTERVAL > 0 286 (void) sigblock(sigmask(SIGALRM)); 287 if (gotalarm && lowdcd(0)) 288 break; 289 gotalarm = 0; 290 #endif /* DCD_CHECK_INTERVAL > 0 */ 291 } 292 293 #ifdef notdef 294 if (lowdcd(0)) 295 syslog(LOG_NOTICE, 296 "connection closed: loss of carrier %s%d: remote %s\n", 297 SLIPIFNAME, unit, dstaddr); 298 #endif 299 300 if (ioctl(0, TIOCSETD, (caddr_t)&odisc) < 0) { 301 syslog(LOG_ERR, "ioctl(TIOCSETD) (2): %m"); 302 exit(1); 303 } 304 if (ioctl(0, TIOCSETA, (caddr_t)&otios) < 0) { 305 syslog(LOG_ERR, "ioctl (TIOCSETA) (2): %m"); 306 exit(1); 307 } 308 if (close(0) < 0) { 309 syslog(LOG_ERR, "close: %m"); 310 exit(1); 311 } 312 exit(0); 313 } 314 315 findid(name) 316 char *name; 317 { 318 char buf[BUFSIZ]; 319 static char mode[16]; 320 static char laddr[16]; 321 static char raddr[16]; 322 static char mask[16]; 323 char user[16]; 324 FILE *fp; 325 struct passwd *pw; 326 int n; 327 328 if (name == NULL && (pw = getpwuid(getuid())) == NULL) { 329 fprintf(stderr, "Your UID (%d) is unknown\n", getuid()); 330 syslog(LOG_ERR, "UID (%d) is unknown\n", getuid()); 331 exit(1); 332 } else if (name == NULL) 333 name = pw->pw_name; 334 if ((fp = fopen(Accessfile, "r")) == NULL) { 335 perror(Accessfile); 336 syslog(LOG_ERR, "%s: %m\n", Accessfile); 337 exit(3); 338 } 339 while (fgets(buf, sizeof(buf) - 1, fp)) { 340 if (ferror(fp)) 341 break; 342 n = sscanf(buf, "%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s\n", 343 user, mode, laddr, raddr, mask); 344 if (user[0] == '#' || n != 5) 345 continue; 346 if (strcmp(user, name) == 0) { 347 char *p,*q; int val, i, domore; 348 349 p = q = mode; val = 0; 350 loop: 351 while (isalnum(*p)) p++; 352 if(ispunct(*p) || *p == '\0') { 353 if(ispunct(*p)) domore = 1; else domore = 0; 354 *p++ = '\0' ; 355 for (i = 0; i < 356 sizeof(modes)/sizeof(struct slip_modes) 357 ; i++) { 358 if (strcmp(modes[i].sm_name, q) == 0) { 359 val |= modes[i].sm_value ; 360 break; 361 } ; 362 } 363 q = p; 364 if(domore)goto loop; 365 } 366 367 slip_mode = val ; 368 localaddr = laddr; 369 dstaddr = raddr; 370 netmask = mask; 371 fclose(fp); 372 return 0; 373 } 374 if (feof(fp)) 375 break; 376 } 377 fputs("SLIP access denied\n", stderr); 378 syslog(LOG_ERR, "SLIP access denied for %s\n", name); 379 exit(4); 380 } 381 382 in_getaddr(s, saddr, which) 383 char *s; 384 struct sockaddr *saddr; 385 int which; 386 { 387 register struct sockaddr_in *sin = (struct sockaddr_in *)saddr; 388 struct hostent *hp; 389 struct netent *np; 390 int val; 391 extern struct in_addr inet_makeaddr(); 392 393 bzero((caddr_t)saddr, sizeof *saddr); 394 if (which == ADDR) { 395 sin->sin_len = sizeof (*sin); 396 sin->sin_family = AF_INET; 397 } else 398 sin->sin_len = 8; 399 val = inet_addr(s); 400 if (val != -1) { 401 sin->sin_addr.s_addr = val; 402 return; 403 } 404 hp = gethostbyname(s); 405 if (hp) { 406 sin->sin_family = hp->h_addrtype; 407 bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length); 408 return; 409 } 410 np = getnetbyname(s); 411 if (np) { 412 sin->sin_family = np->n_addrtype; 413 sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); 414 return; 415 } 416 fprintf(stderr, "sliplogin: %s: bad value\n", s); 417 syslog(LOG_ERR, "%s: bad value\n", s); 418 exit(1); 419 } 420