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