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