summaryrefslogtreecommitdiff
path: root/usr.sbin/authpf
diff options
context:
space:
mode:
authorBob Beck <beck@cvs.openbsd.org>2002-04-01 17:43:43 +0000
committerBob Beck <beck@cvs.openbsd.org>2002-04-01 17:43:43 +0000
commitaa2ec0d4377ea46798a91e0652e00dc623479dbb (patch)
tree487bc7ec557790af0bc6c7d437585a2a508d5a76 /usr.sbin/authpf
parent876a6ac37a64aece433f7a7271db46862b83a39a (diff)
authpf - authenticating gateway shell for use with ssh(1) to make
authenticating gateway type firewalls. caveats - needs to be setuid to opertate (but does not install that way) consult the man page for configuration issues.
Diffstat (limited to 'usr.sbin/authpf')
-rw-r--r--usr.sbin/authpf/Makefile9
-rw-r--r--usr.sbin/authpf/authpf.8424
-rw-r--r--usr.sbin/authpf/authpf.c924
-rw-r--r--usr.sbin/authpf/pathnames.h38
4 files changed, 1395 insertions, 0 deletions
diff --git a/usr.sbin/authpf/Makefile b/usr.sbin/authpf/Makefile
new file mode 100644
index 00000000000..d99167a52d1
--- /dev/null
+++ b/usr.sbin/authpf/Makefile
@@ -0,0 +1,9 @@
+# $OpenBSD: Makefile,v 1.1 2002/04/01 17:43:42 beck Exp $
+
+PROG= authpf
+MAN= authpf.8
+SRCS= authpf.c parse.y pfctl_parser.c
+CFLAGS+= -I${.CURDIR}/../../sbin/pfctl -Wall -Werror
+.PATH: ${.CURDIR}/../../sbin/pfctl
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/authpf/authpf.8 b/usr.sbin/authpf/authpf.8
new file mode 100644
index 00000000000..f3e49281665
--- /dev/null
+++ b/usr.sbin/authpf/authpf.8
@@ -0,0 +1,424 @@
+\" $OpenBSD: authpf.8,v 1.1 2002/04/01 17:43:42 beck Exp $
+.\"
+.\" Copyright (c) 2002 Bob Beck (beck@openbsd.org>. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd Jan 10, 2002
+.Dt AUTHPF 8
+.Os
+.Sh NAME
+.Nm authpf
+.Nd authenticating gateway user shell
+.Sh SYNOPSIS
+.Nm authpf
+.Sh DESCRIPTION
+.Nm
+is used as a user shell for authenticating gateways. It is used to
+change
+.Xr pf 4
+rules when a user authenticates and starts a session with
+.Xr sshd 8
+and to then undo the changes when the user's session exits. It is designed
+for changing filter and translation rules for an individual source IP address
+as long as a user maintains an active
+.Xr ssh 1
+session. Typical use would be for a gateway that authenticates users before
+allowing them Internet use, or a gateway that allows different users into
+different places.
+.Nm
+logs the successful start and end of a session to
+.Xr syslog 8 .
+This, combined with properly set up filter rules and secure switches
+can be used to ensure users are held accountable for their network traffic.
+.Pp
+.Nm
+can add and filter rules using the syntax of
+.Xr pf.conf 5
+and translation rules using the syntax of
+.Xr nat.conf 5 .
+.Nm
+requires that the
+.Xr pf 4
+system be enabled before use.
+.Pp
+.Nm
+is meant to be used with users who can connect via
+.Xr ssh 1
+only. On startup,
+.Nm
+retrieves the client's connecting IP address via the
+.Ev SSH_CLIENT
+environment variable, and after performing additional access checks, reads
+a filter rule template file is read to determine what filter rules to add.
+Optionally, a translation rule template file is read to determine translation
+rules to add. On session exit the same rules that were added at startup are
+removed. By default, filter rules are added at the end of the active
+.Xr pf 4
+filter list, and translation rules are added at the start of the active
+.Xr pf 4
+nat and rdr lists.
+.Sh FILTER AND TRANSLATION RULES
+Filter and Translation rules for
+.Nm
+use the same format described in
+.Xr pf.conf 5
+and
+.Xr nat.conf 5 .
+The only difference is that these rules may (and probably should) use
+the macro
+.Em user_ip
+which is defined to the connecting ip address whenever
+.Nm
+is run.
+.Pp
+Filter rules are loaded from the file
+.Pa $HOME/.authpf/authpf.rules .
+If this file does not exist the file
+.Pa /etc/authpf/authpf.rules
+is used. The
+.Pa authpf.rules
+file must exist in either the user's
+.Pa $HOME/.authpf/
+directory, or in
+.Pa /etc/authpf ,
+for
+.Nm
+to run.
+.Pp
+Translation rules are loaded from the file
+.Pa $HOME/.authpf/authpf.nat .
+If this file does not exist the file
+.Pa /etc/authpf/authpf.nat
+is used. The use of translation rules in an
+.Pa authpf.nat
+file is optional.
+.Sh OPTIONS
+Options are controlled by the
+.Pa /etc/authpf/authpf.conf
+file. This file is optional, is not needed unless the default behavior
+needs to be changed. The file consists of pairs of the form
+.Li name=value
+one per line. Currently, the allowed values are as follows:
+.Bl -tag -width Ds
+.It rule_action=[head|tail]
+controls where filter rules are added, the default behavior is "tail"
+meaning filter rules are added to the end of the active filter list.
+.It Dv nat_action=[head|tail]
+controls where nat rules are added, the default behavior is "head"
+meaning filter rules are added to the start of the active nat list.
+.It Dv rdr_action=[head|tail]
+controls where rdr rules are added, the default behavior is "head"
+meaning filter rules are added to the start of the active rdr list.
+.El
+.Sh USER MESSAGES
+On successful invocation,
+.Nm
+displays a message telling the user they have been authenticated. It will
+additionally display the contents of the file
+.Pa /etc/authpf/authpf.message
+if the file exists and is readable.
+.Pp
+There exist two methods for providing additional granularity to the control
+offered by
+.Nm
+- it is possible to set the gateway to explicitly allow users who have
+authenticated to
+.Xr ssh 1
+and deny access to only a few troublesome individuals. This is done by
+creating a file with the banned user's login name in
+.Pa /var/authpf/banned .
+The contents of this file will be displayed to a banned user, thus providing
+a method for informing the user that they have been banned, and where they can
+go and how to get there if they want to have their service restored. This is
+the default behaviour.
+.Pp
+It is also possible to configure
+.Nm
+to only allow specific users access. This is done by listing their login
+names, one per line, in
+.Pa /etc/authpf/authpf.allow .
+If "*" is found on a line, then all usernames match. If
+.Nm
+is unable to verify the user's permission to use the gateway, it will
+print a brief message and die. It should be noted that a ban takes precedence
+over an allow.
+.Pp
+On failure, messages will be logged to
+.Xr syslog 8
+for the system administrator. The user does not see these, but
+will be told the system is unavailable due to technical difficulties.
+The contents of the file
+.Pa /etc/authpf/authpf.problem
+will also be displayed if the file exists and is readable.
+.Sh CONFIGURATION ISSUES
+.Nm
+maintains the changed filter rules as long as the user maintains an
+active session. It is important to remember however, that the existence
+of this session means the user is authenticated. Because of this, it
+is important to both configure
+.Xr sshd 8
+to ensure the security of the session, and to ensure that the network
+by which users connect to use.
+.Xr sshd 8
+should be configured to use the
+.Dv ClientAliveInterval
+and
+.Dv ClientAliveCountMax
+parameters to ensure than an ssh session is terminated quickly if
+it becomes unresponsive, or if arp or address spoofing is used to
+hijack the session. Note that TCP keepalives are not sufficient for
+this, since they are not secure.
+.Pp
+.Nm
+will remove state table entries that were created during a user's
+session. This ensures that there will be no unauthenticated traffic
+allowed to pass after the controlling
+.Xr ssh 1
+session has been closed.
+.Pp
+.Nm
+is designed for gateway machines with don't typically have regular
+(non-administrative) users using the machine. An administrator
+must remember that
+.Nm
+can be used to modify the filter rules through the environment in
+which it is run, and as such could be used to modify the filter rules
+(based on the contents of the configuration files) by regular
+users. In the case where a machine has regular users using it, as well
+as users with
+.Nm
+as their shell, the regular users should be prevented from running
+.Nm
+by using the
+.Pa /etc/authpf/authpf.allow
+or
+.Pa /var/authpf/banned/
+facilities.
+.Pp
+.Nm
+must be setuid-root in order to modify the packet filter and translation
+rules, though it is not installed with the setuid bit turned on. After
+considering the effect
+.Nm
+may have on the main packet filter rules, the system administrator may run
+the following command to enable
+.Nm
+: "chmod +s /usr/sbin/authpf" .
+.Sh EXAMPLES
+\fBControl Files\fP - To illustrate the user-specific access control
+mechanisms, let us consider a typical user named bob. Normally, as long as
+bob can authenticate himself, the
+.Nm
+program will load the appropriate rules. Enter the
+.Pa /var/authpf/banned/
+directory. If bob has somehow fallen from grace in the eyes of the
+powers-that-be, they can prohibit him from using the gateway by creating
+the file
+.Pa /var/authpf/banned/bob
+containing a message about why he has been banned from using the network.
+Once bob has done suitable pennance, his access may be restored by moving or
+removing the file
+.Pa /var/authpf/banned/bob.
+.Pp
+Now consider a workgroup containing alice, bob, carol and dave. They have a
+wireless network which they would like to protect from unauthorized use. To
+accomplish this, they create the file
+.Pa /etc/authpf/authpf.allow
+which lists their login ids, one per line. At this point, even if eve could
+authenticate to
+.Xr sshd 8 ,
+she would not be allowed to use the gateway. Adding and removing users from
+the work group is a simple matter of maintaining a list of allowed userids.
+If bob once again manages to annoy the powers-that-be, they can ban him from
+using the gateway by creating the familiar
+.Pa /var/authpf/banned/bob
+file. Though bob is listed in the allow file, he is prevented from using
+this gateway due to the existence of a ban file.
+.Pp
+\fBDistributed Authentication\fP - It is often desirable to interface with a
+distributed password system rather than forcing the sysadmins to keep a large
+number of local password files in sync. The
+.Xr login.conf 5
+mechanism in
+.Ox
+can be used to fork the right shell. To make that happen,
+.Xr login.conf 5
+should have entries that look something like this:
+.Bd -literal
+shell-default:shell=/bin/csh
+
+default:\\
+ ...
+ :shell=/usr/sbin/authpf
+
+daemon:\\
+ ...
+ :shell=/bin/csh:\\
+ :tc=default:
+
+staff:\\
+ ...
+ :shell=/bin/csh:\\
+ :tc=default:
+.Ed
+.Pp
+Using a default password file, all users will get
+.Nm
+as their shell except for root who will get
+.Pa /bin/csh.
+.Pp
+\fBSSH Configuration\fP - As stated earlier,
+.Xr sshd 8
+must be properly configured to detect and defeat network attacks. To that end,
+the following options should be added to
+.Pa sshd_config :
+.Bd -literal
+ClientAliveInterval 15
+ClientAliveCountMax 3
+
+.Ed
+This ensures that unresponsive or spoofed session are terminated in under a
+minute, since a hijacker should not be able to spoof ssh keepalive messages.
+.Pp
+.Pp
+\fBBanners\fP - Once authenticated, the user is shown the contents of
+.Pa /etc/authpf/authpf.message.
+This message may be a screen-full of the appropriate use policy, the contents
+of
+.Pa /etc/motd
+or something as simple as the following:
+.Bd -literal
+
+ This means you will be held accountable by the powers that be
+ for traffic originating from your machine, so please play nice.
+.Ed
+.Pp
+To tell the user where to go when the system is broken,
+.Pa /etc/authpf/authpf.problem
+could contain something like this:
+.Bd -literal
+
+ Sorry, there appears to be some system problem. To report this
+ problem so we can fix it, please phone 1-900-314-1597 or send
+ an email to remove@bulkmailerz.net.
+.Ed
+.Pp
+\fBPacket Filter Rules\fP - In areas where this gateway is used to protect a
+wireless network (a hub with several hundred ports) the default rule set as
+well as the per-user rules should probably allow very few things beyond
+encrypted protocols like
+.Xr ssh 1 ,
+.Xr ssl 8 ,
+or
+.Xr ipsec 4 .
+On a securely switched network, with plug-in jacks for visitors who are
+given authentication accounts, you might want to allow out everything. In
+this context, a secure switch is one that tries to prevent address table
+overflow attacks. The examples below assume a switched wired net.
+.Pp
+Example
+.Pa /etc/pf.conf :
+.Bd -literal
+# by default we allow internal clients to talk to us using
+# ssh and use us as a dns server.
+internal_if="fxp1"
+gateway_addr="10.0.1.1"
+block in on $internal_if from any to any
+pass in quick on $internal_if proto tcp from any to $gateway_addr/32 \\
+ port = ssh
+pass in quick on $internal_if proto udp from any to $gateway_addr/32 \\
+ port = domain
+.Ed
+.Pp
+Example
+.Pa /etc/authpf/authpf.rules :
+.Bd -literal
+# no real restrictions here, basically turn the network jack off or on.
+
+external_if = "xl0"
+internal_if = "fxp0"
+
+pass in quick log on $internal_if proto tcp from $user_ip/32 to any \\
+ keep state
+pass in quick on $internal_if from $user_ip/32 to any
+.Ed
+.Pp
+Example
+.Pa /etc/authpf/authpf.nat :
+.Bd -literal
+# When the user authenticates, rdr ftp for proxying by ftp-proxy(8)
+internal_if="fxp1"
+rdr on $internal_if proto tcp from $user_ip/32 to any port 21 \\
+ -> 127.0.0.1 port 8081
+.Ed
+.Pp
+Another example
+.Pa /etc/authpf/authpf.rules
+for an insecure network (such as a public wireless network) where
+we might need to be a bit more restrictive.
+.Bd -literal
+internal_if="fxp1"
+ipsec_gw="10.2.3.4"
+# allow out ftp, ssh, www and https only, and allow user to negotiate
+# ipsec with the ipsec server.
+pass in quick log on $internal_if proto tcp from $user_ip/32 to any \\
+ { port 21, 22, 80, 443 } flags S/SA
+pass in quick on $internal_if proto tcp from $user_ip/32 to any \\
+ { port 21, 22, 80, 443 }
+pass in quick proto udp from $user_ip/32 to $ipsec_gw/32 port = isakmp \\
+ keep-state
+pass in quick proto esp from $user_ip/32 to $ipsec_gw/32
+.Ed
+.Sh FILES
+.Bl -tag -width "/etc/authpf/authpf.conf" -compact
+.It Pa /etc/authpf/authpf.conf
+.It Pa /etc/authpf/authpf.allow
+.It Pa /etc/authpf/authpf.rules
+.It Pa /etc/authpf/authpf.nat
+.It Pa /etc/authpf/authpf.message
+.It Pa /etc/authpf/authpf.problem
+.El
+.Sh SEE ALSO
+.Xr pf 4 ,
+.Xr nat.conf 5 ,
+.Xr pf.conf 5 ,
+.Xr ftp-proxy 8
+.Sh BUGS
+.Pp
+.Nm
+does not support binat translation rules.
+.Pp
+Configuration issues are tricky. The authenticating
+.Xr ssh 1
+connection may be secured, but if the network is not secured the user may
+expose insecure protocols to attackers on the same network, or enable other
+attackers on network to pretend to be the user by spoofing their IP address.
+.Pp
+.Nm
+is not designed to prevent users from denying service to other users.
+.Sh HISTORY
+The
+.Nm
+program first appeared in
+.Ox 3.1 .
diff --git a/usr.sbin/authpf/authpf.c b/usr.sbin/authpf/authpf.c
new file mode 100644
index 00000000000..f065343f1a2
--- /dev/null
+++ b/usr.sbin/authpf/authpf.c
@@ -0,0 +1,924 @@
+/*
+ * Copyright (C) 1998 - 2002 Bob Beck (beck@openbsd.org).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <net/pfvar.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <strings.h>
+#include <sysexits.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <resolv.h>
+
+#include <pfctl_parser.h>
+
+#include "pathnames.h"
+
+int Rule_Action = PF_CHANGE_ADD_TAIL;
+int Nat_Action = PF_CHANGE_ADD_HEAD;
+int Rdr_Action = PF_CHANGE_ADD_HEAD;
+int dev; /* pf device */
+int Delete_Rules; /* for parse_rules callbacks */
+
+char *infile; /* infile name needed by parse_[rules|nat] */
+char luser[MAXLOGNAME] = ""; /* username */
+char ipsrc[256] = ""; /* ip as a string */
+char pidfile[MAXPATHLEN]; /* we save pid in this file. */
+char userfile[MAXPATHLEN]; /* we save username in this file */
+char configfile[] = PATH_CONFFILE;
+char allowfile[] = PATH_ALLOWFILE;
+
+struct timeval Tstart, Tend; /* start and end times of session */
+static volatile sig_atomic_t hasta_la_vista;
+
+int pfctl_add_rule(struct pfctl *, struct pf_rule *);
+int pfctl_add_nat(struct pfctl *, struct pf_nat *);
+int pfctl_add_rdr(struct pfctl *, struct pf_rdr *);
+int pfctl_add_binat(struct pfctl *, struct pf_binat *);
+
+static void read_config(void);
+static void print_message(char *);
+static int allowed_luser(char *);
+static int check_luser(char *, char *);
+static int changefilter(int, char *, char *);
+static void authpf_kill_states(void);
+static void terminator(int s);
+static __dead void go_away(void);
+
+/*
+ * authpf:
+ * User shell for authenticating gateways. sole purpose is to allow
+ * a user to ssh to a gateway, and have the gateway modify packet
+ * filters to allow access, then remove access when the user finishes
+ * up. Meant to be used only from ssh(1) connections.
+ */
+int
+main(int argc, char *argv[])
+{
+ int pidfd, ufd, namelen;
+ int lockcnt = 0;
+ char *foo, *cp;
+ FILE *fp = NULL;
+ struct sockaddr *namep;
+ struct sockaddr_in peer;
+ char bannedir[] = PATH_BAN_DIR;
+
+ namep = (struct sockaddr *)&peer;
+ namelen = sizeof(peer);
+ memset(namep, 0, namelen);
+
+ openlog("authpf", LOG_PID | LOG_NDELAY, LOG_DAEMON);
+
+ read_config();
+
+ if ((foo = getenv("LOGNAME")) != NULL)
+ strlcpy(luser, foo, sizeof(luser));
+ else if ((foo = getenv("USER")) != NULL)
+ strlcpy(luser, foo, sizeof(luser));
+ else {
+ syslog(LOG_ERR, "No user given!");
+ exit(EX_CONFIG);
+ }
+
+ if ((foo = getenv("SSH_CLIENT")) != NULL) {
+ strlcpy(ipsrc, foo, sizeof(ipsrc));
+ cp = ipsrc;
+ while (*cp != '\0') {
+ if (*cp == ' ')
+ *cp = '\0';
+ else
+ cp++;
+ }
+ } else {
+ syslog(LOG_ERR, "Can't determine connection source");
+ exit(EX_CONFIG);
+ }
+ if (!check_luser(bannedir, luser) || !allowed_luser(luser)) {
+ /* give the luser time to read our nastygram on the screen */
+ sleep(180);
+ exit(EX_NOPERM);
+ }
+
+ /*
+ * make ourselves an entry in /var/run as /var/run/authpf-ipaddr,
+ * so that things may find us easily to kill us if necessary.
+ */
+
+ if (snprintf(pidfile, sizeof pidfile, "%s-%s", PATH_PIDFILE, ipsrc) >=
+ sizeof pidfile) {
+ fprintf(stderr, "Sorry, host too long for me to handle..\n");
+ syslog(LOG_ERR, "snprintf pidfile bogosity - exiting");
+ goto dogdeath;
+ }
+
+ if ((pidfd = open(pidfile, O_RDWR|O_CREAT, 0644)) == -1 ||
+ (fp = fdopen(pidfd, "r+")) == NULL) {
+ syslog(LOG_ERR, "can't open or create %s: %s",
+ pidfile, strerror(errno));
+ goto dogdeath;
+ }
+
+ /*
+ * If someone else is already using this ip, then this person
+ * wants to switch users - so kill the old process and we
+ * exit as well. Of course, this will only work if we are
+ * running with priviledge.
+ *
+ * Note, we could print a message and tell them to log out, but the
+ * usual case of this is that someone has left themselves logged in,
+ * with the authenticated connection iconized and someone else walks
+ * up to use and automatically logs in before using. If this just
+ * gets rid of the old one silently, the new user never knows they
+ * could have used someone else's old authentication. If we
+ * tell them to log out before switching users it is an invitation
+ * for abuse.
+ */
+
+ while (flock(pidfd, LOCK_EX|LOCK_NB) == -1 && errno != EBADF) {
+ int otherpid = -1;
+ int save_errno = errno;
+
+ lockcnt++;
+ fscanf(fp, "%d", &otherpid);
+ syslog (LOG_DEBUG, "Tried to lock %s, in use by pid %d: %s",
+ pidfile, otherpid, strerror(save_errno));
+ fclose(fp);
+
+ close(pidfd);
+ if (otherpid > 0) {
+ syslog(LOG_INFO,
+ "killing prior auth (pid %d) of %s by user %s",
+ otherpid, ipsrc, luser);
+ if (kill((pid_t) otherpid, SIGTERM) == -1) {
+ syslog (LOG_INFO,
+ "Couldn't kill process %d: (%m)",
+ otherpid);
+ }
+ }
+
+ /* we try to kill the previous process and aquire the lock
+ * for 10 seconds, trying once a second. if we can't after
+ * 10 attempts we log an error and give up
+ */
+
+ if (lockcnt > 10) {
+ syslog(LOG_ERR, "Can't kill previous authpf (pid %d)",
+ otherpid);
+ goto dogdeath;
+ }
+ sleep(1);
+ }
+
+ fp = fopen(pidfile, "w+");
+ rewind(fp);
+ fprintf(fp, "%d\n", getpid());
+ fflush(fp);
+ (void) ftruncate(fileno(fp), ftell(fp));
+
+ /* open the pf device */
+
+ dev = open (PATH_DEVFILE, O_RDWR);
+ if (dev == -1) {
+ syslog(LOG_ERR, "Can't open filter device (%m)");
+ goto dogdeath;
+ }
+
+ /*
+ * make an entry in file /var/authpf/ipaddr, containing the username.
+ * this lets external applications check for authentication by looking
+ * for the ipaddress in that directory, and retrieving the username
+ * from it.
+ */
+
+ snprintf(userfile, sizeof(userfile), "%s/%s", PATH_USERFILE, ipsrc);
+ if ((ufd = open(userfile, O_CREAT|O_WRONLY, 0640)) == -1) {
+ syslog(LOG_ERR, "Can't open \"%s\" ! (%m)", userfile);
+ goto dogdeath;
+ }
+
+ write(ufd, luser, strlen(luser));
+ write(ufd, "\n", 1);
+ close(ufd);
+
+ if (changefilter(1, luser, ipsrc) == -1) {
+ /* XXX */
+ }
+
+ signal(SIGTERM, terminator);
+ signal(SIGINT, terminator);
+ signal(SIGALRM, terminator);
+ signal(SIGPIPE, terminator);
+ signal(SIGHUP, terminator);
+ signal(SIGSTOP, terminator);
+ signal(SIGTSTP, terminator);
+ while(1) {
+ printf("\r\nHello %s, ", luser);
+ printf("You are authenticated from host \"%s\"\r\n", ipsrc);
+ print_message(PATH_MESSAGE);
+ while (1) {
+ sleep(10);
+ if (hasta_la_vista)
+ go_away();
+ }
+ }
+ /* NOTREACHED */
+ dogdeath:
+ printf("\r\n\r\nSorry, this service is currently unavailable due to ");
+ printf("technical difficulties\r\n\r\n");
+ print_message(PATH_PROBLEM);
+ printf("\r\nYour authentication process (pid %d) was unable to run\n",
+ getpid());
+ sleep(180); /* them lusers read reaaaaal slow */
+ if (pidfile[0] != '\0')
+ unlink(pidfile); /* fail silently */
+ if (userfile[0] != '\0')
+ unlink(userfile); /* fail silently */
+ exit(EX_CONFIG);
+}
+
+/* read_config:
+ * reads config file in PATH_CONFILE to set optional behaviours up
+ */
+
+static void
+read_config(void)
+{
+ char buf[1024];
+ int i = 0;
+ FILE *f;
+
+ f = fopen(configfile, "r");
+ if (f == NULL)
+ return; /* fail silently, run with defaults */
+
+ do {
+ char **ap, *pair[4], *cp, *tp;
+ int len;
+
+ if (fgets(buf, sizeof(buf), f) == NULL) {
+ fclose(f);
+ return;
+ }
+ i++;
+ len = strlen(buf);
+ if (buf[len - 1] != '\n' && !feof(f)) {
+ syslog(LOG_ERR, "line %d too long in %s", i,
+ configfile);
+ exit(EX_CONFIG);
+ }
+ buf[len - 1] = '\0';
+
+ for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
+ ;
+
+ if (!*cp || *cp == '#' || *cp == '\n')
+ continue;
+
+ for (ap = pair; ap < &pair[3] &&
+ (*ap = strsep(&cp, "=")) != NULL; ) {
+ if (**ap != '\0')
+ ap++;
+ }
+ if (ap != &pair[2])
+ goto parse_error;
+
+ tp = pair[1]+strlen(pair[1]);
+ while ((*tp == ' ' || *tp == '\t') && tp >= pair[1])
+ *tp-- = '\0';
+
+ if (strcasecmp(pair[0], "rule_action") == 0) {
+ if (strcasecmp(pair[1], "head") == 0)
+ Rule_Action = PF_CHANGE_ADD_HEAD;
+ else if (strcasecmp(pair[1], "tail") == 0)
+ Rule_Action = PF_CHANGE_ADD_TAIL;
+ else
+ goto parse_error;
+ } else if (strcasecmp(pair[0], "nat_action") == 0) {
+ if (strcasecmp(pair[1], "head") == 0)
+ Nat_Action = PF_CHANGE_ADD_HEAD;
+ else if (strcasecmp(pair[1], "tail") == 0)
+ Nat_Action = PF_CHANGE_ADD_TAIL;
+ else
+ goto parse_error;
+
+ } else if (strcasecmp(pair[0], "rdr_action") == 0) {
+ if (strcasecmp(pair[1], "head") == 0)
+ Rdr_Action = PF_CHANGE_ADD_HEAD;
+ else if (strcasecmp(pair[1], "tail") == 0)
+ Rdr_Action = PF_CHANGE_ADD_TAIL;
+ else
+ goto parse_error;
+ }
+ } while (!feof(f) && !ferror(f));
+ fclose(f);
+ return;
+ parse_error:
+ fclose(f);
+ syslog(LOG_ERR, "parse error, line %d of %s", i, configfile);
+ exit(EX_CONFIG);
+}
+
+
+/*
+ * print_message:
+ * splatter a file to stdout - max line length of 1024,
+ * used for spitting message files at users to tell them
+ * they've been bad or we're unavailable.
+ */
+static void
+print_message(char *filename)
+{
+ char buf[1024];
+ FILE *f;
+
+ if ((f = fopen(filename, "r")) == NULL)
+ return; /* fail silently, we don't care if it isn't there */
+
+ do {
+ if (fgets(buf, sizeof(buf), f) == NULL) {
+ fflush(stdout);
+ fclose(f);
+ return;
+ }
+ } while (fputs(buf, stdout) != EOF && !feof(f));
+ fclose(f);
+}
+
+/*
+ * allowed_luser:
+ * allowed_luser checks to see if user "luser" is allowed to
+ * use this gateway by virtue of being listed in an allowed
+ * users file, namely /etc/authpf.allow .
+ *
+ * If /etc/authpf.allow does not exist, then we assume that
+ * all users who are allowed in by sshd(8) are permitted to
+ * use this gateway. If /etc/authpf.allow does exist, then a
+ * user must be listed if the connection is to continue, else
+ * the session terminates in the same manner as being banned.
+ *
+ */
+static int
+allowed_luser(char *luser)
+{
+ char *buf, *lbuf;
+ size_t len;
+ FILE *f;
+
+ if ((f = fopen(allowfile, "r")) == NULL) {
+ if (errno == ENOENT) {
+ /*
+ * allowfile doesn't exist, this this gateway
+ * isn't restricted to certain users...
+ */
+ return(1);
+ }
+
+ /*
+ * luser may in fact be allowed, but we can't open
+ * the file even though it's there. probably a config
+ * problem.
+ */
+ syslog(LOG_ERR, "Can't open allowed users file %s (%s)",
+ allowfile, strerror(errno));
+ return(0);
+ } else {
+ /*
+ * /etc/authpf.allow exists, thus we do a linear
+ * search to see if they are allowed.
+ * also, if username "*" exists, then this is a
+ * "public" gateway, such as it is, so let
+ * everyone use it.
+ */
+
+ lbuf = NULL;
+ while ((buf = fgetln(f, &len))) {
+ if (buf[len - 1] == '\n')
+ buf[len - 1] = '\0';
+ else {
+ if ((lbuf = (char *)malloc(len + 1)) == NULL)
+ err(1, NULL);
+ memcpy(lbuf, buf, len);
+ lbuf[len] = '\0';
+ buf = lbuf;
+ }
+
+ if (strcmp(luser, buf) == 0 || strcmp("*", buf) == 0)
+ return(1); /* matched an allowed username */
+
+ if (lbuf != NULL) {
+ free(lbuf);
+ lbuf = NULL;
+ }
+ }
+ syslog(LOG_INFO, "Denied access to %s: not listed in %s",
+ luser, allowfile);
+
+ /* reuse buf */
+ buf = "\n\nSorry, you aren't allowed to use this facility!\n";
+ fputs(buf, stdout);
+ }
+ fflush(stdout);
+ return(0);
+}
+
+/*
+ * check_luser:
+ * check_luser checks to see if user "luser" has been banned
+ * from using us by virtue of having an file of the same name
+ * in the "luserdir" directory.
+ *
+ * If the user has been banned, we copy the contents of the file
+ * to the user's screen. (useful for telling the user what to
+ * do to get un-banned, or just to tell them they aren't
+ * going to be un-banned.)
+ */
+static int
+check_luser(char *luserdir, char *luser)
+{
+ char tmp[1024];
+ FILE *f;
+
+ if (snprintf(tmp, sizeof(tmp), "%s/%s", luserdir, luser) >=
+ sizeof(tmp)) {
+ syslog(LOG_ERR, "Provided banned directory line too long (%s)",
+ luserdir);
+ return(0);
+ }
+ if ((f = fopen(tmp, "r")) == NULL) {
+ if (errno == ENOENT) {
+ /*
+ * file or dir doesn't exist, so therefore
+ * this luser isn't banned.. all is well
+ */
+ return(1);
+ } else {
+ /*
+ * luser may in fact be banned, but we can't open the
+ * file even though it's there. probably a config
+ * problem.
+ */
+ syslog (LOG_ERR, "Can't open banned file %s (%s)",
+ tmp, strerror(errno));
+ return(0);
+ }
+ } else {
+ /*
+ * luser is banned - spit the file at them to
+ * tell what they can do and where they can go.
+ */
+
+ syslog(LOG_INFO, "Denied access to %s: %s exists",
+ luser, tmp);
+
+ /* reuse tmp */
+ strlcpy(tmp, "\n\n-**- Sorry, you have been banned! -**-\n\n",
+ sizeof(tmp));
+ while((fputs(tmp, stdout) != EOF) && !feof(f)) {
+ if (fgets(tmp, sizeof(tmp), f) == NULL) {
+ fflush(stdout);
+ return(0);
+ }
+ }
+ }
+ fflush(stdout);
+ return(0);
+}
+
+
+/*
+ * changefilter:
+ * Add/remove filter entries for user "luser" from ip "ipsrc"
+ */
+static int
+changefilter(int add, char *luser, char *ipsrc)
+{
+ char rulesfile[MAXPATHLEN], natfile[MAXPATHLEN], buf[1024];
+ char template[] = "/tmp/authpfrules.XXXXXXX";
+ char template2[] = "/tmp/authpfnat.XXXXXXX";
+ int tmpfile = -1, from_fd = -1, ret = -1;
+ struct pfioc_nat pn;
+ struct pfioc_binat pb;
+ struct pfioc_rdr pd;
+ struct pfioc_rule pr;
+ struct pfctl pf;
+ int rcount, wcount;
+ FILE *fin = NULL;
+ char *cp;
+
+ memset (&pf, 0, sizeof(pf));
+ memset (&pr, 0, sizeof(pr));
+
+ syslog (LOG_DEBUG, "%s filter for ip=%s, user %s",
+ add ? "Adding" : "Removing", ipsrc, luser);
+
+ /* add filter rules */
+
+ if (add)
+ Delete_Rules = 0;
+ else
+ Delete_Rules = 1;
+
+ tmpfile = mkstemp(template);
+ if (tmpfile == -1) {
+ syslog(LOG_ERR, "Can't open temp file %s (%m)",
+ template);
+ goto error;
+ }
+
+ fin = fdopen(tmpfile, "r+");
+ if (fin == NULL) {
+ syslog(LOG_ERR, "can't open %s (%m)", template);
+ goto error;
+ }
+
+ /* write the variable to the start of the file */
+
+ fprintf(fin, "user_ip = \"%s\"\n", ipsrc);
+
+ fflush(fin);
+
+ if ((cp = getenv("HOME")) == NULL) {
+ syslog(LOG_ERR, "No Home Directory!");
+ goto error;
+ }
+ if (snprintf(rulesfile, sizeof rulesfile, "%s/.authpf/authpf.rules",
+ cp) >= sizeof rulesfile) {
+ syslog(LOG_ERR, "homedir path too long, exiting");
+ goto error;
+ }
+ if ((from_fd = open(rulesfile, O_RDONLY, 0)) == -1) {
+ /* if home dir rules do not exist, we try PATH_PFRULES */
+ if (errno != ENOENT) {
+ syslog(LOG_ERR, "can't open %s (%m)", rulesfile);
+ if (unlink(template) == -1)
+ syslog(LOG_ERR, "can't unlink %s", template);
+ goto error;
+ }
+ }
+ snprintf(rulesfile, sizeof rulesfile, PATH_PFRULES);
+ if (from_fd == -1 &&
+ (from_fd = open(rulesfile, O_RDONLY, 0)) == -1) {
+ syslog(LOG_ERR, "can't open %s (%m)", rulesfile);
+ if (unlink(template) == -1)
+ syslog(LOG_ERR, "can't unlink %s", template);
+ goto error;
+ }
+
+ while ((rcount = read(from_fd, buf, sizeof(buf))) > 0) {
+ wcount = write(tmpfile, buf, rcount);
+ if (rcount != wcount || wcount == -1) {
+ syslog(LOG_ERR, "rules template copy failed");
+ if (unlink(template) == -1)
+ syslog(LOG_ERR, "can't unlink %s", template);
+ goto error;
+ }
+ }
+ if (rcount == -1) {
+ syslog(LOG_ERR, "read of rules template failed");
+ if (unlink(template) == -1)
+ syslog(LOG_ERR, "can't unlink %s", template);
+ goto error;
+ }
+
+ fclose(fin);
+ fin = NULL;
+ close(tmpfile);
+ tmpfile = -1;
+ close(from_fd);
+ from_fd = -1;
+
+ fin = fopen(template, "r");
+ if (fin == NULL) {
+ syslog(LOG_ERR, "can't open %s (%m)", template);
+ if (unlink(template) == -1)
+ syslog(LOG_ERR, "can't unlink %s", template);
+ goto error;
+ }
+
+ infile = template;
+
+ if (unlink(template) == -1) {
+ syslog(LOG_ERR, "can't unlink %s", template);
+ goto error;
+ }
+
+ /* add/delete rules, using parse_rule */
+ memset(&pf, 0, sizeof(pf));
+ pf.dev = dev;
+ pf.prule = &pr;
+ if (parse_rules(fin, &pf) < 0) {
+ syslog(LOG_ERR,
+ "syntax error in rule file: authpf rules not loaded");
+ goto error;
+ }
+
+ /* now, for NAT, if we have some */
+
+ if ((cp = getenv("HOME")) == NULL) {
+ syslog(LOG_ERR, "No Home Directory!");
+ goto error;
+ }
+ if (snprintf(natfile, sizeof natfile, "%s/.authpf/authpf.nat", cp) >=
+ sizeof natfile) {
+ syslog(LOG_ERR, "homedir path too long, exiting");
+ goto error;
+ }
+ if ((from_fd = open(natfile, O_RDONLY, 0)) == -1) {
+ /* if it doesn't exist, we try /etc */
+ if (errno != ENOENT) {
+ syslog(LOG_ERR, "can't open %s (%m)", natfile);
+ if (unlink(template) == -1)
+ syslog(LOG_ERR, "can't unlink %s", template);
+ goto error;
+ }
+ }
+ snprintf(natfile, sizeof natfile, PATH_NATRULES);
+ if (from_fd == -1 &&
+ (from_fd = open(natfile, O_RDONLY, 0)) == -1) {
+ if (errno == ENOENT)
+ goto out; /* NAT is optional */
+ else {
+ syslog(LOG_ERR, "can't open %s (%m)", natfile);
+ if (unlink(template) == -1)
+ syslog(LOG_ERR, "can't unlink %s", template);
+ goto error;
+ }
+ }
+ tmpfile = mkstemp(template2);
+ if (tmpfile == -1) {
+ syslog(LOG_ERR, "Can't open temp file %s (%m)",
+ template2);
+ goto error;
+ }
+
+ fin = fdopen(tmpfile, "r+");
+ if (fin == NULL) {
+ syslog(LOG_ERR, "Can't open %s (%m)", template2);
+ goto error;
+ }
+
+ /* write the variable to the start of the file */
+ fprintf(fin, "user_ip = \"%s\"\n", ipsrc);
+ fflush(fin);
+
+ while ((rcount = read(from_fd, buf, sizeof(buf))) > 0) {
+ wcount = write(tmpfile, buf, rcount);
+ if (rcount != wcount || wcount == -1) {
+ syslog(LOG_INFO, "nat copy failed");
+ goto error;
+ }
+ }
+
+ if (rcount == -1) {
+ syslog(LOG_INFO, "read for nat copy failed");
+ goto error;
+ }
+
+ fclose(fin);
+ fin = NULL;
+ close(tmpfile);
+ tmpfile = -1;
+ close(from_fd);
+ from_fd = -1;
+
+ fin = fopen(template2, "r");
+
+ if (fin == NULL) {
+ syslog(LOG_INFO, "can't open %s (%m)", template2);
+ goto error;
+ }
+
+ infile = template;
+
+ if (unlink(template2) == -1) {
+ syslog(LOG_INFO, "can't unlink %s (%m)", template2);
+ goto error;
+ }
+ /* add/delete rules, using parse_nat */
+
+ memset(&pf, 0, sizeof(pf));
+ pf.dev = dev;
+ pf.pnat = &pn;
+ pf.pbinat = &pb;
+ pf.prdr = &pd;
+ if (parse_nat(fin, &pf) < 0) {
+ syslog(LOG_INFO,
+ "syntax error in nat file: nat rules not loaded");
+ goto error;
+ }
+ ret = 0;
+ goto out;
+ error:
+ ret = -1;
+ out:
+ if (fin != NULL)
+ fclose(fin);
+ if (tmpfile != -1)
+ close(tmpfile);
+ if (from_fd != -1)
+ close(from_fd);
+ if (add) {
+ (void)gettimeofday(&Tstart, NULL);
+ syslog (LOG_INFO, "Allowing %s, user %s", ipsrc, luser);
+ } else {
+ (void)gettimeofday(&Tend, NULL);
+ syslog (LOG_INFO, "Removed %s, user %s - duration %ld seconds",
+ ipsrc, luser, Tend.tv_sec - Tstart.tv_sec);
+ }
+ return(ret);
+}
+
+/*
+ * authpf_kill_states:
+ * This is to kill off states that would otherwide be left behind stateful
+ * rules. This means we don't need to allow in more traffic than we really
+ * want to, since we don't have to worry about any luser sessions lasting
+ * longer than their ssh session. This function is based on
+ * pfctl_kill_states from pfctl.
+ */
+static void
+authpf_kill_states()
+{
+ struct pfioc_state_kill psk;
+ struct in_addr target, temp;
+
+ memset(&psk, 0, sizeof(psk));
+ memset(&psk.psk_src.mask, 0xff, sizeof(psk.psk_src.mask));
+ memset(&target, 0xff, sizeof(target));
+ memset(&temp, 0xff, sizeof(temp));
+
+ inet_pton(AF_INET, "255.255.255.255", &temp);
+ inet_pton(AF_INET, ipsrc, &target);
+
+ psk.psk_src.addr.v4 = target;
+ psk.psk_dst.addr.v4 = temp;
+ if (ioctl(dev, DIOCKILLSTATES, &psk))
+ syslog(LOG_ERR, "DIOCKILLSTATES failed (%m)");
+
+ psk.psk_dst.addr.v4 = target;
+ psk.psk_src.addr.v4 = temp;
+ if (ioctl(dev, DIOCKILLSTATES, &psk))
+ syslog(LOG_ERR, "DIOCKILLSTATES failed (%m)");
+}
+
+/* signal handler that makes us go away properly */
+static void
+terminator(int s)
+{
+ hasta_la_vista = 1;
+}
+
+/*
+ * go_away:
+ * function that removes our stuff when we go away.
+ */
+static __dead void
+go_away(void)
+{
+ int ret = EX_OK;
+
+ changefilter(0, luser, ipsrc);
+ authpf_kill_states();
+ if (unlink(pidfile) != 0) {
+ syslog(LOG_ERR, "Couldn't unlink %s! (%m)", pidfile);
+ ret = EX_OSERR;
+ }
+ if (unlink(userfile) != 0) {
+ syslog(LOG_ERR, "Couldn't unlink %s! (%m)", userfile);
+ ret = EX_OSERR;
+ }
+ exit(ret);
+}
+
+/*
+ * pfctl_add_rules:
+ * callback for rule add, used by parser in parse_rules
+ */
+int
+pfctl_add_rule(struct pfctl *pf, struct pf_rule *r)
+{
+ struct pfioc_changerule pcr;
+
+ memset(&pcr, 0, sizeof(pcr));
+ if (Delete_Rules) {
+ pcr.action = PF_CHANGE_REMOVE;
+ memcpy(&pcr.oldrule, r, sizeof(pcr.oldrule));
+ } else {
+ pcr.action = Rule_Action;
+ memcpy(&pcr.newrule, r, sizeof(pcr.newrule));
+ }
+ if ((pf->opts & PF_OPT_NOACTION) == 0) {
+ if (ioctl(pf->dev, DIOCCHANGERULE, &pcr))
+ syslog(LOG_INFO, "DIOCCHANGERULE %m");
+ }
+
+ return 0;
+}
+
+/*
+ * pfctl_add_nat:
+ * callback for nat add, used by parser in parse_nat
+ */
+int
+pfctl_add_nat(struct pfctl *pf, struct pf_nat *n)
+{
+ struct pfioc_changenat pcr;
+
+ memset(&pcr, 0, sizeof(pcr));
+ if (Delete_Rules) {
+ pcr.action = PF_CHANGE_REMOVE;
+ memcpy(&pcr.oldnat, n, sizeof(pcr.oldnat));
+ } else {
+ pcr.action = Nat_Action;
+ memcpy(&pcr.newnat, n, sizeof(pcr.newnat));
+ }
+ if ((pf->opts & PF_OPT_NOACTION) == 0) {
+ if (ioctl(pf->dev, DIOCCHANGENAT, &pcr))
+ syslog(LOG_INFO, "DIOCCHANGENAT %m");
+ }
+ return 0;
+}
+
+/*
+ * pfctl_add_rdr:
+ * callback for rdr add, used by parser in parse_nat
+ */
+int
+pfctl_add_rdr(struct pfctl *pf, struct pf_rdr *r)
+{
+ struct pfioc_changerdr pcr;
+
+ memset(&pcr, 0, sizeof(pcr));
+ if (Delete_Rules) {
+ pcr.action = PF_CHANGE_REMOVE;
+ memcpy(&pcr.oldrdr, r, sizeof(pcr.oldrdr));
+ } else {
+ pcr.action = Rdr_Action;
+ memcpy(&pcr.newrdr, r, sizeof(pcr.newrdr));
+ }
+ if ((pf->opts & PF_OPT_NOACTION) == 0) {
+ if (ioctl(pf->dev, DIOCCHANGERDR, &pcr))
+ syslog(LOG_INFO, "DIOCCHANGERDR %m");
+ }
+ return 0;
+}
+
+/*
+ * pfctl_add_binat:
+ * We don't support adding binat's, since pf doesn't,
+ * and I can't for the life of me think of a sane situation where it
+ * might be useful. This is here only because the pfctl parse
+ * routines need this defined.
+ */
+int
+pfctl_add_binat(struct pfctl *pf, struct pf_binat *b)
+{
+ return 0;
+}
diff --git a/usr.sbin/authpf/pathnames.h b/usr.sbin/authpf/pathnames.h
new file mode 100644
index 00000000000..719c0850f86
--- /dev/null
+++ b/usr.sbin/authpf/pathnames.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2002 Chris Kuethe (ckuethe@ualberta.ca)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define PATH_CONFFILE "/etc/authpf/authpf.conf"
+#define PATH_ALLOWFILE "/etc/authpf/authpf.allow"
+#define PATH_PFRULES "/etc/authpf/authpf.rules"
+#define PATH_NATRULES "/etc/authpf/authpf.nat"
+#define PATH_PROBLEM "/etc/authpf/authpf.problem"
+#define PATH_MESSAGE "/etc/authpf/authpf.message"
+#define PATH_BAN_DIR "/var/authpf/banned"
+#define PATH_DEVFILE "/dev/pf"
+#define PATH_PIDFILE "/var/run/authpf"
+#define PATH_USERFILE "/var/authpf"