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