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