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