1 /* $OpenBSD: authpf.c,v 1.75 2004/01/29 01:55:10 deraadt Exp $ */ 2 3 /* 4 * Copyright (C) 1998 - 2002 Bob Beck (beck@openbsd.org). 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include <sys/param.h> 32 #include <sys/file.h> 33 #include <sys/ioctl.h> 34 #include <sys/socket.h> 35 #include <sys/time.h> 36 37 #include <net/if.h> 38 #include <net/pfvar.h> 39 #include <arpa/inet.h> 40 41 #include <err.h> 42 #include <errno.h> 43 #include <pwd.h> 44 #include <signal.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <syslog.h> 49 #include <unistd.h> 50 51 #include <pfctl_parser.h> 52 #include <pfctl.h> 53 54 #include "pathnames.h" 55 56 extern int symset(const char *, const char *, int); 57 58 static int read_config(FILE *); 59 static void print_message(char *); 60 static int allowed_luser(char *); 61 static int check_luser(char *, char *); 62 static int remove_stale_rulesets(void); 63 static int change_filter(int, const char *, const char *); 64 static void authpf_kill_states(void); 65 66 int dev; /* pf device */ 67 char anchorname[PF_ANCHOR_NAME_SIZE] = "authpf"; 68 char rulesetname[PF_RULESET_NAME_SIZE]; 69 70 FILE *pidfp; 71 char *infile; /* file name printed by yyerror() in parse.y */ 72 char luser[MAXLOGNAME]; /* username */ 73 char ipsrc[256]; /* ip as a string */ 74 char pidfile[MAXPATHLEN]; /* we save pid in this file. */ 75 76 struct timeval Tstart, Tend; /* start and end times of session */ 77 78 volatile sig_atomic_t want_death; 79 static void need_death(int signo); 80 #ifdef __FreeBSD__ 81 static __dead2 void do_death(int); 82 #else 83 static __dead void do_death(int); 84 #endif 85 86 /* 87 * User shell for authenticating gateways. Sole purpose is to allow 88 * a user to ssh to a gateway, and have the gateway modify packet 89 * filters to allow access, then remove access when the user finishes 90 * up. Meant to be used only from ssh(1) connections. 91 */ 92 int 93 main(int argc, char *argv[]) 94 { 95 int lockcnt = 0, n, pidfd; 96 FILE *config; 97 struct in_addr ina; 98 struct passwd *pw; 99 char *cp; 100 uid_t uid; 101 102 config = fopen(PATH_CONFFILE, "r"); 103 104 if ((cp = getenv("SSH_TTY")) == NULL) { 105 syslog(LOG_ERR, "non-interactive session connection for authpf"); 106 exit(1); 107 } 108 109 if ((cp = getenv("SSH_CLIENT")) == NULL) { 110 syslog(LOG_ERR, "cannot determine connection source"); 111 exit(1); 112 } 113 114 if (strlcpy(ipsrc, cp, sizeof(ipsrc)) >= sizeof(ipsrc)) { 115 syslog(LOG_ERR, "SSH_CLIENT variable too long"); 116 exit(1); 117 } 118 cp = strchr(ipsrc, ' '); 119 if (!cp) { 120 syslog(LOG_ERR, "corrupt SSH_CLIENT variable %s", ipsrc); 121 exit(1); 122 } 123 *cp = '\0'; 124 if (inet_pton(AF_INET, ipsrc, &ina) != 1) { 125 syslog(LOG_ERR, 126 "cannot determine IP from SSH_CLIENT %s", ipsrc); 127 exit(1); 128 } 129 /* open the pf device */ 130 dev = open(PATH_DEVFILE, O_RDWR); 131 if (dev == -1) { 132 syslog(LOG_ERR, "cannot open packet filter device (%m)"); 133 goto die; 134 } 135 136 uid = getuid(); 137 pw = getpwuid(uid); 138 if (pw == NULL) { 139 syslog(LOG_ERR, "cannot find user for uid %u", uid); 140 goto die; 141 } 142 if (strcmp(pw->pw_shell, PATH_AUTHPF_SHELL)) { 143 syslog(LOG_ERR, "wrong shell for user %s, uid %u", 144 pw->pw_name, pw->pw_uid); 145 goto die; 146 } 147 148 /* 149 * Paranoia, but this data _does_ come from outside authpf, and 150 * truncation would be bad. 151 */ 152 if (strlcpy(luser, pw->pw_name, sizeof(luser)) >= sizeof(luser)) { 153 syslog(LOG_ERR, "username too long: %s", pw->pw_name); 154 goto die; 155 } 156 157 if ((n = snprintf(rulesetname, sizeof(rulesetname), "%s(%ld)", 158 luser, (long)getpid())) < 0 || n >= sizeof(rulesetname)) { 159 syslog(LOG_INFO, "%s(%ld) too large, ruleset name will be %ld", 160 luser, (long)getpid(), (long)getpid()); 161 if ((n = snprintf(rulesetname, sizeof(rulesetname), "%ld", 162 (long)getpid())) < 0 || n >= sizeof(rulesetname)) { 163 syslog(LOG_ERR, "pid too large for ruleset name"); 164 goto die; 165 } 166 } 167 168 169 /* Make our entry in /var/authpf as /var/authpf/ipaddr */ 170 n = snprintf(pidfile, sizeof(pidfile), "%s/%s", PATH_PIDFILE, ipsrc); 171 if (n < 0 || (u_int)n >= sizeof(pidfile)) { 172 syslog(LOG_ERR, "path to pidfile too long"); 173 goto die; 174 } 175 176 /* 177 * If someone else is already using this ip, then this person 178 * wants to switch users - so kill the old process and exit 179 * as well. 180 * 181 * Note, we could print a message and tell them to log out, but the 182 * usual case of this is that someone has left themselves logged in, 183 * with the authenticated connection iconized and someone else walks 184 * up to use and automatically logs in before using. If this just 185 * gets rid of the old one silently, the new user never knows they 186 * could have used someone else's old authentication. If we 187 * tell them to log out before switching users it is an invitation 188 * for abuse. 189 */ 190 191 do { 192 int save_errno, otherpid = -1; 193 char otherluser[MAXLOGNAME]; 194 195 if ((pidfd = open(pidfile, O_RDWR|O_CREAT, 0644)) == -1 || 196 (pidfp = fdopen(pidfd, "r+")) == NULL) { 197 if (pidfd != -1) 198 close(pidfd); 199 syslog(LOG_ERR, "cannot open or create %s: %s", pidfile, 200 strerror(errno)); 201 goto die; 202 } 203 204 if (flock(fileno(pidfp), LOCK_EX|LOCK_NB) == 0) 205 break; 206 save_errno = errno; 207 208 /* Mark our pid, and username to our file. */ 209 210 rewind(pidfp); 211 /* 31 == MAXLOGNAME - 1 */ 212 if (fscanf(pidfp, "%d\n%31s\n", &otherpid, otherluser) != 2) 213 otherpid = -1; 214 syslog(LOG_DEBUG, "tried to lock %s, in use by pid %d: %s", 215 pidfile, otherpid, strerror(save_errno)); 216 217 if (otherpid > 0) { 218 syslog(LOG_INFO, 219 "killing prior auth (pid %d) of %s by user %s", 220 otherpid, ipsrc, otherluser); 221 if (kill((pid_t) otherpid, SIGTERM) == -1) { 222 syslog(LOG_INFO, 223 "could not kill process %d: (%m)", 224 otherpid); 225 } 226 } 227 228 /* 229 * we try to kill the previous process and acquire the lock 230 * for 10 seconds, trying once a second. if we can't after 231 * 10 attempts we log an error and give up 232 */ 233 if (++lockcnt > 10) { 234 syslog(LOG_ERR, "cannot kill previous authpf (pid %d)", 235 otherpid); 236 goto dogdeath; 237 } 238 sleep(1); 239 240 /* re-open, and try again. The previous authpf process 241 * we killed above should unlink the file and release 242 * it's lock, giving us a chance to get it now 243 */ 244 fclose(pidfp); 245 } while (1); 246 247 /* revoke privs */ 248 seteuid(getuid()); 249 setuid(getuid()); 250 251 openlog("authpf", LOG_PID | LOG_NDELAY, LOG_DAEMON); 252 253 if (!check_luser(PATH_BAN_DIR, luser) || !allowed_luser(luser)) { 254 syslog(LOG_INFO, "user %s prohibited", luser); 255 do_death(0); 256 } 257 258 if (config == NULL || read_config(config)) { 259 syslog(LOG_INFO, "bad or nonexistent %s", PATH_CONFFILE); 260 do_death(0); 261 } 262 263 if (remove_stale_rulesets()) { 264 syslog(LOG_INFO, "error removing stale rulesets"); 265 do_death(0); 266 } 267 268 /* We appear to be making headway, so actually mark our pid */ 269 rewind(pidfp); 270 fprintf(pidfp, "%ld\n%s\n", (long)getpid(), luser); 271 fflush(pidfp); 272 (void) ftruncate(fileno(pidfp), ftell(pidfp)); 273 274 if (change_filter(1, luser, ipsrc) == -1) { 275 printf("Unable to modify filters\r\n"); 276 do_death(0); 277 } 278 279 signal(SIGTERM, need_death); 280 signal(SIGINT, need_death); 281 signal(SIGALRM, need_death); 282 signal(SIGPIPE, need_death); 283 signal(SIGHUP, need_death); 284 signal(SIGSTOP, need_death); 285 signal(SIGTSTP, need_death); 286 while (1) { 287 printf("\r\nHello %s, ", luser); 288 printf("You are authenticated from host \"%s\"\r\n", ipsrc); 289 setproctitle("%s@%s", luser, ipsrc); 290 print_message(PATH_MESSAGE); 291 while (1) { 292 sleep(10); 293 if (want_death) 294 do_death(1); 295 } 296 } 297 298 /* NOTREACHED */ 299 dogdeath: 300 printf("\r\n\r\nSorry, this service is currently unavailable due to "); 301 printf("technical difficulties\r\n\r\n"); 302 print_message(PATH_PROBLEM); 303 printf("\r\nYour authentication process (pid %ld) was unable to run\n", 304 (long)getpid()); 305 sleep(180); /* them lusers read reaaaaal slow */ 306 die: 307 do_death(0); 308 309 /* NOTREACHED */ 310 } 311 312 /* 313 * reads config file in PATH_CONFFILE to set optional behaviours up 314 */ 315 static int 316 read_config(FILE *f) 317 { 318 char buf[1024]; 319 int i = 0; 320 321 do { 322 char **ap; 323 char *pair[4], *cp, *tp; 324 int len; 325 326 if (fgets(buf, sizeof(buf), f) == NULL) { 327 fclose(f); 328 return (0); 329 } 330 i++; 331 len = strlen(buf); 332 if (buf[len - 1] != '\n' && !feof(f)) { 333 syslog(LOG_ERR, "line %d too long in %s", i, 334 PATH_CONFFILE); 335 return (1); 336 } 337 buf[len - 1] = '\0'; 338 339 for (cp = buf; *cp == ' ' || *cp == '\t'; cp++) 340 ; /* nothing */ 341 342 if (!*cp || *cp == '#' || *cp == '\n') 343 continue; 344 345 for (ap = pair; ap < &pair[3] && 346 (*ap = strsep(&cp, "=")) != NULL; ) { 347 if (**ap != '\0') 348 ap++; 349 } 350 if (ap != &pair[2]) 351 goto parse_error; 352 353 tp = pair[1] + strlen(pair[1]); 354 while ((*tp == ' ' || *tp == '\t') && tp >= pair[1]) 355 *tp-- = '\0'; 356 357 if (strcasecmp(pair[0], "anchor") == 0) { 358 if (!pair[1][0] || strlcpy(anchorname, pair[1], 359 sizeof(anchorname)) >= sizeof(anchorname)) 360 goto parse_error; 361 } 362 } while (!feof(f) && !ferror(f)); 363 fclose(f); 364 return (0); 365 366 parse_error: 367 fclose(f); 368 syslog(LOG_ERR, "parse error, line %d of %s", i, PATH_CONFFILE); 369 return (1); 370 } 371 372 373 /* 374 * splatter a file to stdout - max line length of 1024, 375 * used for spitting message files at users to tell them 376 * they've been bad or we're unavailable. 377 */ 378 static void 379 print_message(char *filename) 380 { 381 char buf[1024]; 382 FILE *f; 383 384 if ((f = fopen(filename, "r")) == NULL) 385 return; /* fail silently, we don't care if it isn't there */ 386 387 do { 388 if (fgets(buf, sizeof(buf), f) == NULL) { 389 fflush(stdout); 390 fclose(f); 391 return; 392 } 393 } while (fputs(buf, stdout) != EOF && !feof(f)); 394 fflush(stdout); 395 fclose(f); 396 } 397 398 /* 399 * allowed_luser checks to see if user "luser" is allowed to 400 * use this gateway by virtue of being listed in an allowed 401 * users file, namely /etc/authpf/authpf.allow . 402 * 403 * If /etc/authpf/authpf.allow does not exist, then we assume that 404 * all users who are allowed in by sshd(8) are permitted to 405 * use this gateway. If /etc/authpf/authpf.allow does exist, then a 406 * user must be listed if the connection is to continue, else 407 * the session terminates in the same manner as being banned. 408 */ 409 static int 410 allowed_luser(char *luser) 411 { 412 char *buf, *lbuf; 413 int matched; 414 size_t len; 415 FILE *f; 416 417 if ((f = fopen(PATH_ALLOWFILE, "r")) == NULL) { 418 if (errno == ENOENT) { 419 /* 420 * allowfile doesn't exist, thus this gateway 421 * isn't restricted to certain users... 422 */ 423 return (1); 424 } 425 426 /* 427 * luser may in fact be allowed, but we can't open 428 * the file even though it's there. probably a config 429 * problem. 430 */ 431 syslog(LOG_ERR, "cannot open allowed users file %s (%s)", 432 PATH_ALLOWFILE, strerror(errno)); 433 return (0); 434 } else { 435 /* 436 * /etc/authpf/authpf.allow exists, thus we do a linear 437 * search to see if they are allowed. 438 * also, if username "*" exists, then this is a 439 * "public" gateway, such as it is, so let 440 * everyone use it. 441 */ 442 lbuf = NULL; 443 while ((buf = fgetln(f, &len))) { 444 if (buf[len - 1] == '\n') 445 buf[len - 1] = '\0'; 446 else { 447 if ((lbuf = (char *)malloc(len + 1)) == NULL) 448 err(1, NULL); 449 memcpy(lbuf, buf, len); 450 lbuf[len] = '\0'; 451 buf = lbuf; 452 } 453 454 matched = strcmp(luser, buf) == 0 || strcmp("*", buf) == 0; 455 456 if (lbuf != NULL) { 457 free(lbuf); 458 lbuf = NULL; 459 } 460 461 if (matched) 462 return (1); /* matched an allowed username */ 463 } 464 syslog(LOG_INFO, "denied access to %s: not listed in %s", 465 luser, PATH_ALLOWFILE); 466 467 /* reuse buf */ 468 buf = "\n\nSorry, you are not allowed to use this facility!\n"; 469 fputs(buf, stdout); 470 } 471 fflush(stdout); 472 return (0); 473 } 474 475 /* 476 * check_luser checks to see if user "luser" has been banned 477 * from using us by virtue of having an file of the same name 478 * in the "luserdir" directory. 479 * 480 * If the user has been banned, we copy the contents of the file 481 * to the user's screen. (useful for telling the user what to 482 * do to get un-banned, or just to tell them they aren't 483 * going to be un-banned.) 484 */ 485 static int 486 check_luser(char *luserdir, char *luser) 487 { 488 FILE *f; 489 int n; 490 char tmp[MAXPATHLEN]; 491 492 n = snprintf(tmp, sizeof(tmp), "%s/%s", luserdir, luser); 493 if (n < 0 || (u_int)n >= sizeof(tmp)) { 494 syslog(LOG_ERR, "provided banned directory line too long (%s)", 495 luserdir); 496 return (0); 497 } 498 if ((f = fopen(tmp, "r")) == NULL) { 499 if (errno == ENOENT) { 500 /* 501 * file or dir doesn't exist, so therefore 502 * this luser isn't banned.. all is well 503 */ 504 return (1); 505 } else { 506 /* 507 * luser may in fact be banned, but we can't open the 508 * file even though it's there. probably a config 509 * problem. 510 */ 511 syslog(LOG_ERR, "cannot open banned file %s (%s)", 512 tmp, strerror(errno)); 513 return (0); 514 } 515 } else { 516 /* 517 * luser is banned - spit the file at them to 518 * tell what they can do and where they can go. 519 */ 520 syslog(LOG_INFO, "denied access to %s: %s exists", 521 luser, tmp); 522 523 /* reuse tmp */ 524 strlcpy(tmp, "\n\n-**- Sorry, you have been banned! -**-\n\n", 525 sizeof(tmp)); 526 while (fputs(tmp, stdout) != EOF && !feof(f)) { 527 if (fgets(tmp, sizeof(tmp), f) == NULL) { 528 fflush(stdout); 529 return (0); 530 } 531 } 532 } 533 fflush(stdout); 534 return (0); 535 } 536 537 /* 538 * Search for rulesets left by other authpf processes (either because they 539 * died ungracefully or were terminated) and remove them. 540 */ 541 static int 542 remove_stale_rulesets(void) 543 { 544 struct pfioc_ruleset prs; 545 const int action[PF_RULESET_MAX] = { PF_SCRUB, 546 PF_PASS, PF_NAT, PF_BINAT, PF_RDR }; 547 u_int32_t nr, mnr; 548 549 memset(&prs, 0, sizeof(prs)); 550 strlcpy(prs.anchor, anchorname, sizeof(prs.anchor)); 551 if (ioctl(dev, DIOCGETRULESETS, &prs)) { 552 if (errno == EINVAL) 553 return (0); 554 else 555 return (1); 556 } 557 558 mnr = prs.nr; 559 nr = 0; 560 while (nr < mnr) { 561 char *s, *t; 562 pid_t pid; 563 564 prs.nr = nr; 565 if (ioctl(dev, DIOCGETRULESET, &prs)) 566 return (1); 567 errno = 0; 568 if ((t = strchr(prs.name, '(')) == NULL) 569 t = prs.name; 570 else 571 t++; 572 pid = strtoul(t, &s, 10); 573 if (!prs.name[0] || errno || 574 (*s && (t == prs.name || *s != ')'))) 575 return (1); 576 if (kill(pid, 0) && errno != EPERM) { 577 int i; 578 579 for (i = 0; i < PF_RULESET_MAX; ++i) { 580 struct pfioc_rule pr; 581 582 memset(&pr, 0, sizeof(pr)); 583 memcpy(pr.anchor, prs.anchor, sizeof(pr.anchor)); 584 memcpy(pr.ruleset, prs.name, sizeof(pr.ruleset)); 585 pr.rule.action = action[i]; 586 if ((ioctl(dev, DIOCBEGINRULES, &pr) || 587 ioctl(dev, DIOCCOMMITRULES, &pr)) && 588 errno != EINVAL) 589 return (1); 590 } 591 mnr--; 592 } else 593 nr++; 594 } 595 return (0); 596 } 597 598 /* 599 * Add/remove filter entries for user "luser" from ip "ipsrc" 600 */ 601 static int 602 change_filter(int add, const char *luser, const char *ipsrc) 603 { 604 char fn[MAXPATHLEN]; 605 FILE *f = NULL; 606 struct pfctl pf; 607 struct pfr_buffer t; 608 int i; 609 610 if (luser == NULL || !luser[0] || ipsrc == NULL || !ipsrc[0]) { 611 syslog(LOG_ERR, "invalid luser/ipsrc"); 612 goto error; 613 } 614 615 if (add) { 616 if ((i = snprintf(fn, sizeof(fn), "%s/%s/authpf.rules", 617 PATH_USER_DIR, luser)) < 0 || i >= sizeof(fn)) { 618 syslog(LOG_ERR, "user rule path too long"); 619 goto error; 620 } 621 if ((f = fopen(fn, "r")) == NULL && errno != ENOENT) { 622 syslog(LOG_ERR, "cannot open %s (%m)", fn); 623 goto error; 624 } 625 if (f == NULL) { 626 if (strlcpy(fn, PATH_PFRULES, sizeof(fn)) >= 627 sizeof(fn)) { 628 syslog(LOG_ERR, "rule path too long"); 629 goto error; 630 } 631 if ((f = fopen(fn, "r")) == NULL) { 632 syslog(LOG_ERR, "cannot open %s (%m)", fn); 633 goto error; 634 } 635 } 636 } 637 638 if (pfctl_load_fingerprints(dev, 0)) { 639 syslog(LOG_ERR, "unable to load kernel's OS fingerprints"); 640 goto error; 641 } 642 bzero(&t, sizeof(t)); 643 t.pfrb_type = PFRB_TRANS; 644 memset(&pf, 0, sizeof(pf)); 645 for (i = 0; i < PF_RULESET_MAX; ++i) { 646 if (pfctl_add_trans(&t, i, anchorname, rulesetname)) { 647 syslog(LOG_ERR, "pfctl_add_trans %m"); 648 goto error; 649 } 650 } 651 if (pfctl_trans(dev, &t, DIOCXBEGIN, 0)) { 652 syslog(LOG_ERR, "DIOCXBEGIN (%s) %m", add?"add":"remove"); 653 goto error; 654 } 655 656 if (add) { 657 if (symset("user_ip", ipsrc, 0) || 658 symset("user_id", luser, 0)) { 659 syslog(LOG_ERR, "symset"); 660 goto error; 661 } 662 663 pf.dev = dev; 664 pf.trans = &t; 665 pf.anchor = anchorname; 666 pf.ruleset = rulesetname; 667 668 infile = fn; 669 if (parse_rules(f, &pf) < 0) { 670 syslog(LOG_ERR, "syntax error in rule file: " 671 "authpf rules not loaded"); 672 goto error; 673 } 674 675 infile = NULL; 676 fclose(f); 677 f = NULL; 678 } 679 680 if (pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) { 681 syslog(LOG_ERR, "DIOCXCOMMIT (%s) %m", add?"add":"remove"); 682 goto error; 683 } 684 685 if (add) { 686 gettimeofday(&Tstart, NULL); 687 syslog(LOG_INFO, "allowing %s, user %s", ipsrc, luser); 688 } else { 689 gettimeofday(&Tend, NULL); 690 syslog(LOG_INFO, "removed %s, user %s - duration %ld seconds", 691 ipsrc, luser, Tend.tv_sec - Tstart.tv_sec); 692 } 693 return (0); 694 695 error: 696 if (f != NULL) 697 fclose(f); 698 if (pfctl_trans(dev, &t, DIOCXROLLBACK, 0)) 699 syslog(LOG_ERR, "DIOCXROLLBACK (%s) %m", add?"add":"remove"); 700 701 infile = NULL; 702 return (-1); 703 } 704 705 /* 706 * This is to kill off states that would otherwise be left behind stateful 707 * rules. This means we don't need to allow in more traffic than we really 708 * want to, since we don't have to worry about any luser sessions lasting 709 * longer than their ssh session. This function is based on 710 * pfctl_kill_states from pfctl. 711 */ 712 static void 713 authpf_kill_states(void) 714 { 715 struct pfioc_state_kill psk; 716 struct in_addr target; 717 718 memset(&psk, 0, sizeof(psk)); 719 psk.psk_af = AF_INET; 720 721 inet_pton(AF_INET, ipsrc, &target); 722 723 /* Kill all states from ipsrc */ 724 psk.psk_src.addr.v.a.addr.v4 = target; 725 memset(&psk.psk_src.addr.v.a.mask, 0xff, 726 sizeof(psk.psk_src.addr.v.a.mask)); 727 if (ioctl(dev, DIOCKILLSTATES, &psk)) 728 syslog(LOG_ERR, "DIOCKILLSTATES failed (%m)"); 729 730 /* Kill all states to ipsrc */ 731 psk.psk_af = AF_INET; 732 memset(&psk.psk_src, 0, sizeof(psk.psk_src)); 733 psk.psk_dst.addr.v.a.addr.v4 = target; 734 memset(&psk.psk_dst.addr.v.a.mask, 0xff, 735 sizeof(psk.psk_dst.addr.v.a.mask)); 736 if (ioctl(dev, DIOCKILLSTATES, &psk)) 737 syslog(LOG_ERR, "DIOCKILLSTATES failed (%m)"); 738 } 739 740 /* signal handler that makes us go away properly */ 741 static void 742 need_death(int signo) 743 { 744 want_death = 1; 745 } 746 747 /* 748 * function that removes our stuff when we go away. 749 */ 750 #ifdef __FreeBSD__ 751 static __dead2 void 752 #else 753 static __dead void 754 #endif 755 do_death(int active) 756 { 757 int ret = 0; 758 759 if (active) { 760 change_filter(0, luser, ipsrc); 761 authpf_kill_states(); 762 remove_stale_rulesets(); 763 } 764 if (pidfp) 765 ftruncate(fileno(pidfp), 0); 766 if (pidfile[0]) 767 if (unlink(pidfile) == -1) 768 syslog(LOG_ERR, "cannot unlink %s (%m)", pidfile); 769 exit(ret); 770 } 771 772 /* 773 * callbacks for parse_rules(void) 774 */ 775 776 int 777 pfctl_add_rule(struct pfctl *pf, struct pf_rule *r) 778 { 779 u_int8_t rs_num; 780 struct pfioc_rule pr; 781 782 switch (r->action) { 783 case PF_PASS: 784 case PF_DROP: 785 rs_num = PF_RULESET_FILTER; 786 break; 787 case PF_SCRUB: 788 rs_num = PF_RULESET_SCRUB; 789 break; 790 case PF_NAT: 791 case PF_NONAT: 792 rs_num = PF_RULESET_NAT; 793 break; 794 case PF_RDR: 795 case PF_NORDR: 796 rs_num = PF_RULESET_RDR; 797 break; 798 case PF_BINAT: 799 case PF_NOBINAT: 800 rs_num = PF_RULESET_BINAT; 801 break; 802 default: 803 syslog(LOG_ERR, "invalid rule action %d", r->action); 804 return (1); 805 } 806 807 bzero(&pr, sizeof(pr)); 808 strlcpy(pr.anchor, pf->anchor, sizeof(pr.anchor)); 809 strlcpy(pr.ruleset, pf->ruleset, sizeof(pr.ruleset)); 810 if (pfctl_add_pool(pf, &r->rpool, r->af)) 811 return (1); 812 pr.ticket = pfctl_get_ticket(pf->trans, rs_num, pf->anchor, 813 pf->ruleset); 814 pr.pool_ticket = pf->paddr.ticket; 815 memcpy(&pr.rule, r, sizeof(pr.rule)); 816 if (ioctl(pf->dev, DIOCADDRULE, &pr)) { 817 syslog(LOG_ERR, "DIOCADDRULE %m"); 818 return (1); 819 } 820 pfctl_clear_pool(&r->rpool); 821 return (0); 822 } 823 824 int 825 pfctl_add_pool(struct pfctl *pf, struct pf_pool *p, sa_family_t af) 826 { 827 struct pf_pooladdr *pa; 828 829 if (ioctl(pf->dev, DIOCBEGINADDRS, &pf->paddr)) { 830 syslog(LOG_ERR, "DIOCBEGINADDRS %m"); 831 return (1); 832 } 833 pf->paddr.af = af; 834 TAILQ_FOREACH(pa, &p->list, entries) { 835 memcpy(&pf->paddr.addr, pa, sizeof(struct pf_pooladdr)); 836 if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr)) { 837 syslog(LOG_ERR, "DIOCADDADDR %m"); 838 return (1); 839 } 840 } 841 return (0); 842 } 843 844 void 845 pfctl_clear_pool(struct pf_pool *pool) 846 { 847 struct pf_pooladdr *pa; 848 849 while ((pa = TAILQ_FIRST(&pool->list)) != NULL) { 850 TAILQ_REMOVE(&pool->list, pa, entries); 851 free(pa); 852 } 853 } 854 855 int 856 pfctl_add_altq(struct pfctl *pf, struct pf_altq *a) 857 { 858 fprintf(stderr, "altq rules not supported in authpf\n"); 859 return (1); 860 } 861 862 int 863 pfctl_set_optimization(struct pfctl *pf, const char *opt) 864 { 865 fprintf(stderr, "set optimization not supported in authpf\n"); 866 return (1); 867 } 868 869 int 870 pfctl_set_logif(struct pfctl *pf, char *ifname) 871 { 872 fprintf(stderr, "set loginterface not supported in authpf\n"); 873 return (1); 874 } 875 876 int 877 pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid) 878 { 879 fprintf(stderr, "set hostid not supported in authpf\n"); 880 return (1); 881 } 882 883 int 884 pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet) 885 { 886 fprintf(stderr, "set timeout not supported in authpf\n"); 887 return (1); 888 } 889 890 int 891 pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit) 892 { 893 fprintf(stderr, "set limit not supported in authpf\n"); 894 return (1); 895 } 896 897 int 898 pfctl_set_debug(struct pfctl *pf, char *d) 899 { 900 fprintf(stderr, "set debug not supported in authpf\n"); 901 return (1); 902 } 903 904 int 905 pfctl_define_table(char *name, int flags, int addrs, const char *anchor, 906 const char *ruleset, struct pfr_buffer *ab, u_int32_t ticket) 907 { 908 fprintf(stderr, "table definitions not yet supported in authpf\n"); 909 return (1); 910 } 911 912 int 913 pfctl_rules(int dev, char *filename, int opts, char *anchorname, 914 char *rulesetname, struct pfr_buffer *t) 915 { 916 /* never called, no anchors inside anchors, but we need the stub */ 917 fprintf(stderr, "load anchor not supported from authpf\n"); 918 return (1); 919 } 920 921 void 922 pfctl_print_title(char *title) 923 { 924 } 925