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