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