1 /* $NetBSD: authpf.c,v 1.2 2004/06/25 00:06:09 itojun Exp $ */ 2 /* $OpenBSD: authpf.c,v 1.75 2004/01/29 01:55:10 deraadt 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/types.h> 30 #include <sys/file.h> 31 #include <sys/ioctl.h> 32 #include <sys/socket.h> 33 #include <sys/time.h> 34 #include <sys/param.h> 35 36 #include <net/if.h> 37 #include <netinet/in.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 static __dead void do_death(int); 81 82 /* 83 * User shell for authenticating gateways. Sole purpose is to allow 84 * a user to ssh to a gateway, and have the gateway modify packet 85 * filters to allow access, then remove access when the user finishes 86 * up. Meant to be used only from ssh(1) connections. 87 */ 88 int 89 main(int argc, char *argv[]) 90 { 91 int lockcnt = 0, n, pidfd; 92 FILE *config; 93 struct in_addr ina; 94 struct passwd *pw; 95 char *cp; 96 uid_t uid; 97 98 config = fopen(PATH_CONFFILE, "r"); 99 100 if ((cp = getenv("SSH_TTY")) == NULL) { 101 syslog(LOG_ERR, "non-interactive session connection for authpf"); 102 exit(1); 103 } 104 105 if ((cp = getenv("SSH_CLIENT")) == NULL) { 106 syslog(LOG_ERR, "cannot determine connection source"); 107 exit(1); 108 } 109 110 if (strlcpy(ipsrc, cp, sizeof(ipsrc)) >= sizeof(ipsrc)) { 111 syslog(LOG_ERR, "SSH_CLIENT variable too long"); 112 exit(1); 113 } 114 cp = strchr(ipsrc, ' '); 115 if (!cp) { 116 syslog(LOG_ERR, "corrupt SSH_CLIENT variable %s", ipsrc); 117 exit(1); 118 } 119 *cp = '\0'; 120 if (inet_pton(AF_INET, ipsrc, &ina) != 1) { 121 syslog(LOG_ERR, 122 "cannot determine IP from SSH_CLIENT %s", ipsrc); 123 exit(1); 124 } 125 /* open the pf device */ 126 dev = open(PATH_DEVFILE, O_RDWR); 127 if (dev == -1) { 128 syslog(LOG_ERR, "cannot open packet filter device (%m)"); 129 goto die; 130 } 131 132 uid = getuid(); 133 pw = getpwuid(uid); 134 if (pw == NULL) { 135 syslog(LOG_ERR, "cannot find user for uid %u", uid); 136 goto die; 137 } 138 if (strcmp(pw->pw_shell, PATH_AUTHPF_SHELL)) { 139 syslog(LOG_ERR, "wrong shell for user %s, uid %u", 140 pw->pw_name, pw->pw_uid); 141 goto die; 142 } 143 144 /* 145 * Paranoia, but this data _does_ come from outside authpf, and 146 * truncation would be bad. 147 */ 148 if (strlcpy(luser, pw->pw_name, sizeof(luser)) >= sizeof(luser)) { 149 syslog(LOG_ERR, "username too long: %s", pw->pw_name); 150 goto die; 151 } 152 153 if ((n = snprintf(rulesetname, sizeof(rulesetname), "%s(%ld)", 154 luser, (long)getpid())) < 0 || n >= sizeof(rulesetname)) { 155 syslog(LOG_INFO, "%s(%ld) too large, ruleset name will be %ld", 156 luser, (long)getpid(), (long)getpid()); 157 if ((n = snprintf(rulesetname, sizeof(rulesetname), "%ld", 158 (long)getpid())) < 0 || n >= sizeof(rulesetname)) { 159 syslog(LOG_ERR, "pid too large for ruleset name"); 160 goto die; 161 } 162 } 163 164 165 /* Make our entry in /var/authpf as /var/authpf/ipaddr */ 166 n = snprintf(pidfile, sizeof(pidfile), "%s/%s", PATH_PIDFILE, ipsrc); 167 if (n < 0 || (u_int)n >= sizeof(pidfile)) { 168 syslog(LOG_ERR, "path to pidfile too long"); 169 goto die; 170 } 171 172 /* 173 * If someone else is already using this ip, then this person 174 * wants to switch users - so kill the old process and exit 175 * as well. 176 * 177 * Note, we could print a message and tell them to log out, but the 178 * usual case of this is that someone has left themselves logged in, 179 * with the authenticated connection iconized and someone else walks 180 * up to use and automatically logs in before using. If this just 181 * gets rid of the old one silently, the new user never knows they 182 * could have used someone else's old authentication. If we 183 * tell them to log out before switching users it is an invitation 184 * for abuse. 185 */ 186 187 do { 188 int save_errno, otherpid = -1; 189 char otherluser[MAXLOGNAME]; 190 191 if ((pidfd = open(pidfile, O_RDWR|O_CREAT, 0644)) == -1 || 192 (pidfp = fdopen(pidfd, "r+")) == NULL) { 193 if (pidfd != -1) 194 close(pidfd); 195 syslog(LOG_ERR, "cannot open or create %s: %s", pidfile, 196 strerror(errno)); 197 goto die; 198 } 199 200 if (flock(fileno(pidfp), LOCK_EX|LOCK_NB) == 0) 201 break; 202 save_errno = errno; 203 204 /* Mark our pid, and username to our file. */ 205 206 rewind(pidfp); 207 /* 31 == MAXLOGNAME - 1 */ 208 if (fscanf(pidfp, "%d\n%31s\n", &otherpid, otherluser) != 2) 209 otherpid = -1; 210 syslog(LOG_DEBUG, "tried to lock %s, in use by pid %d: %s", 211 pidfile, otherpid, strerror(save_errno)); 212 213 if (otherpid > 0) { 214 syslog(LOG_INFO, 215 "killing prior auth (pid %d) of %s by user %s", 216 otherpid, ipsrc, otherluser); 217 if (kill((pid_t) otherpid, SIGTERM) == -1) { 218 syslog(LOG_INFO, 219 "could not kill process %d: (%m)", 220 otherpid); 221 } 222 } 223 224 /* 225 * we try to kill the previous process and acquire the lock 226 * for 10 seconds, trying once a second. if we can't after 227 * 10 attempts we log an error and give up 228 */ 229 if (++lockcnt > 10) { 230 syslog(LOG_ERR, "cannot kill previous authpf (pid %d)", 231 otherpid); 232 goto dogdeath; 233 } 234 sleep(1); 235 236 /* re-open, and try again. The previous authpf process 237 * we killed above should unlink the file and release 238 * it's lock, giving us a chance to get it now 239 */ 240 fclose(pidfp); 241 } while (1); 242 243 /* revoke privs */ 244 seteuid(getuid()); 245 setuid(getuid()); 246 247 openlog("authpf", LOG_PID | LOG_NDELAY, LOG_DAEMON); 248 249 if (!check_luser(PATH_BAN_DIR, luser) || !allowed_luser(luser)) { 250 syslog(LOG_INFO, "user %s prohibited", luser); 251 do_death(0); 252 } 253 254 if (config == NULL || read_config(config)) { 255 syslog(LOG_INFO, "bad or nonexistent %s", PATH_CONFFILE); 256 do_death(0); 257 } 258 259 if (remove_stale_rulesets()) { 260 syslog(LOG_INFO, "error removing stale rulesets"); 261 do_death(0); 262 } 263 264 /* We appear to be making headway, so actually mark our pid */ 265 rewind(pidfp); 266 fprintf(pidfp, "%ld\n%s\n", (long)getpid(), luser); 267 fflush(pidfp); 268 (void) ftruncate(fileno(pidfp), ftell(pidfp)); 269 270 if (change_filter(1, luser, ipsrc) == -1) { 271 printf("Unable to modify filters\r\n"); 272 do_death(0); 273 } 274 275 signal(SIGTERM, need_death); 276 signal(SIGINT, need_death); 277 signal(SIGALRM, need_death); 278 signal(SIGPIPE, need_death); 279 signal(SIGHUP, need_death); 280 signal(SIGSTOP, need_death); 281 signal(SIGTSTP, need_death); 282 while (1) { 283 printf("\r\nHello %s, ", luser); 284 printf("You are authenticated from host \"%s\"\r\n", ipsrc); 285 setproctitle("%s@%s", luser, ipsrc); 286 print_message(PATH_MESSAGE); 287 while (1) { 288 sleep(10); 289 if (want_death) 290 do_death(1); 291 } 292 } 293 294 /* NOTREACHED */ 295 dogdeath: 296 printf("\r\n\r\nSorry, this service is currently unavailable due to "); 297 printf("technical difficulties\r\n\r\n"); 298 print_message(PATH_PROBLEM); 299 printf("\r\nYour authentication process (pid %ld) was unable to run\n", 300 (long)getpid()); 301 sleep(180); /* them lusers read reaaaaal slow */ 302 die: 303 do_death(0); 304 return (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(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(char *luser) 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 * luser 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(luser, 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 luser, PATH_ALLOWFILE); 461 462 /* reuse buf */ 463 buf = "\n\nSorry, you are not allowed to use this facility!\n"; 464 fputs(buf, stdout); 465 } 466 fflush(stdout); 467 return (0); 468 } 469 470 /* 471 * check_luser checks to see if user "luser" has been banned 472 * from using us by virtue of having an file of the same name 473 * in the "luserdir" directory. 474 * 475 * If the user has been banned, we copy the contents of the file 476 * to the user's screen. (useful for telling the user what to 477 * do to get un-banned, or just to tell them they aren't 478 * going to be un-banned.) 479 */ 480 static int 481 check_luser(char *luserdir, char *luser) 482 { 483 FILE *f; 484 int n; 485 char tmp[MAXPATHLEN]; 486 487 n = snprintf(tmp, sizeof(tmp), "%s/%s", luserdir, luser); 488 if (n < 0 || (u_int)n >= sizeof(tmp)) { 489 syslog(LOG_ERR, "provided banned directory line too long (%s)", 490 luserdir); 491 return (0); 492 } 493 if ((f = fopen(tmp, "r")) == NULL) { 494 if (errno == ENOENT) { 495 /* 496 * file or dir doesn't exist, so therefore 497 * this luser isn't banned.. all is well 498 */ 499 return (1); 500 } else { 501 /* 502 * luser may in fact be banned, but we can't open the 503 * file even though it's there. probably a config 504 * problem. 505 */ 506 syslog(LOG_ERR, "cannot open banned file %s (%s)", 507 tmp, strerror(errno)); 508 return (0); 509 } 510 } else { 511 /* 512 * luser is banned - spit the file at them to 513 * tell what they can do and where they can go. 514 */ 515 syslog(LOG_INFO, "denied access to %s: %s exists", 516 luser, tmp); 517 518 /* reuse tmp */ 519 strlcpy(tmp, "\n\n-**- Sorry, you have been banned! -**-\n\n", 520 sizeof(tmp)); 521 while (fputs(tmp, stdout) != EOF && !feof(f)) { 522 if (fgets(tmp, sizeof(tmp), f) == NULL) { 523 fflush(stdout); 524 return (0); 525 } 526 } 527 } 528 fflush(stdout); 529 return (0); 530 } 531 532 /* 533 * Search for rulesets left by other authpf processes (either because they 534 * died ungracefully or were terminated) and remove them. 535 */ 536 static int 537 remove_stale_rulesets(void) 538 { 539 struct pfioc_ruleset prs; 540 const int action[PF_RULESET_MAX] = { PF_SCRUB, 541 PF_PASS, PF_NAT, PF_BINAT, PF_RDR }; 542 u_int32_t nr, mnr; 543 544 memset(&prs, 0, sizeof(prs)); 545 strlcpy(prs.anchor, anchorname, sizeof(prs.anchor)); 546 if (ioctl(dev, DIOCGETRULESETS, &prs)) { 547 if (errno == EINVAL) 548 return (0); 549 else 550 return (1); 551 } 552 553 mnr = prs.nr; 554 nr = 0; 555 while (nr < mnr) { 556 char *s, *t; 557 pid_t pid; 558 559 prs.nr = nr; 560 if (ioctl(dev, DIOCGETRULESET, &prs)) 561 return (1); 562 errno = 0; 563 if ((t = strchr(prs.name, '(')) == NULL) 564 t = prs.name; 565 else 566 t++; 567 pid = strtoul(t, &s, 10); 568 if (!prs.name[0] || errno || 569 (*s && (t == prs.name || *s != ')'))) 570 return (1); 571 if (kill(pid, 0) && errno != EPERM) { 572 int i; 573 574 for (i = 0; i < PF_RULESET_MAX; ++i) { 575 struct pfioc_rule pr; 576 577 memset(&pr, 0, sizeof(pr)); 578 memcpy(pr.anchor, prs.anchor, sizeof(pr.anchor)); 579 memcpy(pr.ruleset, prs.name, sizeof(pr.ruleset)); 580 pr.rule.action = action[i]; 581 if ((ioctl(dev, DIOCBEGINRULES, &pr) || 582 ioctl(dev, DIOCCOMMITRULES, &pr)) && 583 errno != EINVAL) 584 return (1); 585 } 586 mnr--; 587 } else 588 nr++; 589 } 590 return (0); 591 } 592 593 /* 594 * Add/remove filter entries for user "luser" from ip "ipsrc" 595 */ 596 static int 597 change_filter(int add, const char *luser, const char *ipsrc) 598 { 599 char fn[MAXPATHLEN]; 600 FILE *f = NULL; 601 struct pfctl pf; 602 struct pfr_buffer t; 603 int i; 604 605 if (luser == NULL || !luser[0] || ipsrc == NULL || !ipsrc[0]) { 606 syslog(LOG_ERR, "invalid luser/ipsrc"); 607 goto error; 608 } 609 610 if (add) { 611 if ((i = snprintf(fn, sizeof(fn), "%s/%s/authpf.rules", 612 PATH_USER_DIR, luser)) < 0 || i >= sizeof(fn)) { 613 syslog(LOG_ERR, "user rule path too long"); 614 goto error; 615 } 616 if ((f = fopen(fn, "r")) == NULL && errno != ENOENT) { 617 syslog(LOG_ERR, "cannot open %s (%m)", fn); 618 goto error; 619 } 620 if (f == NULL) { 621 if (strlcpy(fn, PATH_PFRULES, sizeof(fn)) >= 622 sizeof(fn)) { 623 syslog(LOG_ERR, "rule path too long"); 624 goto error; 625 } 626 if ((f = fopen(fn, "r")) == NULL) { 627 syslog(LOG_ERR, "cannot open %s (%m)", fn); 628 goto error; 629 } 630 } 631 } 632 633 if (pfctl_load_fingerprints(dev, 0)) { 634 syslog(LOG_ERR, "unable to load kernel's OS fingerprints"); 635 goto error; 636 } 637 bzero(&t, sizeof(t)); 638 t.pfrb_type = PFRB_TRANS; 639 memset(&pf, 0, sizeof(pf)); 640 for (i = 0; i < PF_RULESET_MAX; ++i) { 641 if (pfctl_add_trans(&t, i, anchorname, rulesetname)) { 642 syslog(LOG_ERR, "pfctl_add_trans %m"); 643 goto error; 644 } 645 } 646 if (pfctl_trans(dev, &t, DIOCXBEGIN, 0)) { 647 syslog(LOG_ERR, "DIOCXBEGIN (%s) %m", add?"add":"remove"); 648 goto error; 649 } 650 651 if (add) { 652 if (symset("user_ip", ipsrc, 0) || 653 symset("user_id", luser, 0)) { 654 syslog(LOG_ERR, "symset"); 655 goto error; 656 } 657 658 pf.dev = dev; 659 pf.trans = &t; 660 pf.anchor = anchorname; 661 pf.ruleset = rulesetname; 662 663 infile = fn; 664 if (parse_rules(f, &pf) < 0) { 665 syslog(LOG_ERR, "syntax error in rule file: " 666 "authpf rules not loaded"); 667 goto error; 668 } 669 670 infile = NULL; 671 fclose(f); 672 f = NULL; 673 } 674 675 if (pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) { 676 syslog(LOG_ERR, "DIOCXCOMMIT (%s) %m", add?"add":"remove"); 677 goto error; 678 } 679 680 if (add) { 681 gettimeofday(&Tstart, NULL); 682 syslog(LOG_INFO, "allowing %s, user %s", ipsrc, luser); 683 } else { 684 gettimeofday(&Tend, NULL); 685 syslog(LOG_INFO, "removed %s, user %s - duration %ld seconds", 686 ipsrc, luser, Tend.tv_sec - Tstart.tv_sec); 687 } 688 return (0); 689 690 error: 691 if (f != NULL) 692 fclose(f); 693 if (pfctl_trans(dev, &t, DIOCXROLLBACK, 0)) 694 syslog(LOG_ERR, "DIOCXROLLBACK (%s) %m", add?"add":"remove"); 695 696 infile = NULL; 697 return (-1); 698 } 699 700 /* 701 * This is to kill off states that would otherwise be left behind stateful 702 * rules. This means we don't need to allow in more traffic than we really 703 * want to, since we don't have to worry about any luser sessions lasting 704 * longer than their ssh session. This function is based on 705 * pfctl_kill_states from pfctl. 706 */ 707 static void 708 authpf_kill_states(void) 709 { 710 struct pfioc_state_kill psk; 711 struct in_addr target; 712 713 memset(&psk, 0, sizeof(psk)); 714 psk.psk_af = AF_INET; 715 716 inet_pton(AF_INET, ipsrc, &target); 717 718 /* Kill all states from ipsrc */ 719 psk.psk_src.addr.v.a.addr.v4 = target; 720 memset(&psk.psk_src.addr.v.a.mask, 0xff, 721 sizeof(psk.psk_src.addr.v.a.mask)); 722 if (ioctl(dev, DIOCKILLSTATES, &psk)) 723 syslog(LOG_ERR, "DIOCKILLSTATES failed (%m)"); 724 725 /* Kill all states to ipsrc */ 726 psk.psk_af = AF_INET; 727 memset(&psk.psk_src, 0, sizeof(psk.psk_src)); 728 psk.psk_dst.addr.v.a.addr.v4 = target; 729 memset(&psk.psk_dst.addr.v.a.mask, 0xff, 730 sizeof(psk.psk_dst.addr.v.a.mask)); 731 if (ioctl(dev, DIOCKILLSTATES, &psk)) 732 syslog(LOG_ERR, "DIOCKILLSTATES failed (%m)"); 733 } 734 735 /* signal handler that makes us go away properly */ 736 static void 737 need_death(int signo) 738 { 739 want_death = 1; 740 } 741 742 /* 743 * function that removes our stuff when we go away. 744 */ 745 static __dead void 746 do_death(int active) 747 { 748 int ret = 0; 749 750 if (active) { 751 change_filter(0, luser, ipsrc); 752 authpf_kill_states(); 753 remove_stale_rulesets(); 754 } 755 if (pidfp) 756 ftruncate(fileno(pidfp), 0); 757 if (pidfile[0]) 758 if (unlink(pidfile) == -1) 759 syslog(LOG_ERR, "cannot unlink %s (%m)", pidfile); 760 exit(ret); 761 } 762 763 /* 764 * callbacks for parse_rules(void) 765 */ 766 767 int 768 pfctl_add_rule(struct pfctl *pf, struct pf_rule *r) 769 { 770 u_int8_t rs_num; 771 struct pfioc_rule pr; 772 773 switch (r->action) { 774 case PF_PASS: 775 case PF_DROP: 776 rs_num = PF_RULESET_FILTER; 777 break; 778 case PF_SCRUB: 779 rs_num = PF_RULESET_SCRUB; 780 break; 781 case PF_NAT: 782 case PF_NONAT: 783 rs_num = PF_RULESET_NAT; 784 break; 785 case PF_RDR: 786 case PF_NORDR: 787 rs_num = PF_RULESET_RDR; 788 break; 789 case PF_BINAT: 790 case PF_NOBINAT: 791 rs_num = PF_RULESET_BINAT; 792 break; 793 default: 794 syslog(LOG_ERR, "invalid rule action %d", r->action); 795 return (1); 796 } 797 798 bzero(&pr, sizeof(pr)); 799 strlcpy(pr.anchor, pf->anchor, sizeof(pr.anchor)); 800 strlcpy(pr.ruleset, pf->ruleset, sizeof(pr.ruleset)); 801 if (pfctl_add_pool(pf, &r->rpool, r->af)) 802 return (1); 803 pr.ticket = pfctl_get_ticket(pf->trans, rs_num, pf->anchor, 804 pf->ruleset); 805 pr.pool_ticket = pf->paddr.ticket; 806 memcpy(&pr.rule, r, sizeof(pr.rule)); 807 if (ioctl(pf->dev, DIOCADDRULE, &pr)) { 808 syslog(LOG_ERR, "DIOCADDRULE %m"); 809 return (1); 810 } 811 pfctl_clear_pool(&r->rpool); 812 return (0); 813 } 814 815 int 816 pfctl_add_pool(struct pfctl *pf, struct pf_pool *p, sa_family_t af) 817 { 818 struct pf_pooladdr *pa; 819 820 if (ioctl(pf->dev, DIOCBEGINADDRS, &pf->paddr)) { 821 syslog(LOG_ERR, "DIOCBEGINADDRS %m"); 822 return (1); 823 } 824 pf->paddr.af = af; 825 TAILQ_FOREACH(pa, &p->list, entries) { 826 memcpy(&pf->paddr.addr, pa, sizeof(struct pf_pooladdr)); 827 if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr)) { 828 syslog(LOG_ERR, "DIOCADDADDR %m"); 829 return (1); 830 } 831 } 832 return (0); 833 } 834 835 void 836 pfctl_clear_pool(struct pf_pool *pool) 837 { 838 struct pf_pooladdr *pa; 839 840 while ((pa = TAILQ_FIRST(&pool->list)) != NULL) { 841 TAILQ_REMOVE(&pool->list, pa, entries); 842 free(pa); 843 } 844 } 845 846 int 847 pfctl_add_altq(struct pfctl *pf, struct pf_altq *a) 848 { 849 fprintf(stderr, "altq rules not supported in authpf\n"); 850 return (1); 851 } 852 853 int 854 pfctl_set_optimization(struct pfctl *pf, const char *opt) 855 { 856 fprintf(stderr, "set optimization not supported in authpf\n"); 857 return (1); 858 } 859 860 int 861 pfctl_set_logif(struct pfctl *pf, char *ifname) 862 { 863 fprintf(stderr, "set loginterface not supported in authpf\n"); 864 return (1); 865 } 866 867 int 868 pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid) 869 { 870 fprintf(stderr, "set hostid not supported in authpf\n"); 871 return (1); 872 } 873 874 int 875 pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet) 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, const char *opt, unsigned int limit) 883 { 884 fprintf(stderr, "set limit not supported in authpf\n"); 885 return (1); 886 } 887 888 int 889 pfctl_set_debug(struct pfctl *pf, char *d) 890 { 891 fprintf(stderr, "set debug not supported in authpf\n"); 892 return (1); 893 } 894 895 int 896 pfctl_define_table(char *name, int flags, int addrs, const char *anchor, 897 const char *ruleset, struct pfr_buffer *ab, u_int32_t ticket) 898 { 899 fprintf(stderr, "table definitions not yet supported in authpf\n"); 900 return (1); 901 } 902 903 int 904 pfctl_rules(int dev, char *filename, int opts, char *anchorname, 905 char *rulesetname, struct pfr_buffer *t) 906 { 907 /* never called, no anchors inside anchors, but we need the stub */ 908 fprintf(stderr, "load anchor not supported from authpf\n"); 909 return (1); 910 } 911 912 void 913 pfctl_print_title(char *title) 914 { 915 } 916