aboutsummaryrefslogtreecommitdiff
path: root/contrib/pf/authpf
diff options
context:
space:
mode:
authorMax Laier <mlaier@FreeBSD.org>2008-12-10 19:31:42 +0000
committerMax Laier <mlaier@FreeBSD.org>2008-12-10 19:31:42 +0000
commit551100331fc59409c6c0f7738ab22eb197b8df20 (patch)
tree09e9a4440c1d3bcf750c0336d5e4aa12640d2a77 /contrib/pf/authpf
parent67ecd4f3a477a0ca5b76a1694f89755df27a8679 (diff)
downloadsrc-551100331fc59409c6c0f7738ab22eb197b8df20.tar.gz
src-551100331fc59409c6c0f7738ab22eb197b8df20.zip
Flatten out the pf userland vendor area
Notes
Notes: svn path=/vendor/pf/dist/; revision=185872
Diffstat (limited to 'contrib/pf/authpf')
-rw-r--r--contrib/pf/authpf/authpf.8527
-rw-r--r--contrib/pf/authpf/authpf.c830
-rw-r--r--contrib/pf/authpf/pathnames.h38
3 files changed, 0 insertions, 1395 deletions
diff --git a/contrib/pf/authpf/authpf.8 b/contrib/pf/authpf/authpf.8
deleted file mode 100644
index ee0dcaa423b3..000000000000
--- a/contrib/pf/authpf/authpf.8
+++ /dev/null
@@ -1,527 +0,0 @@
-.\" $OpenBSD: authpf.8,v 1.43 2007/02/24 17:21:04 beck Exp $
-.\"
-.\" Copyright (c) 1998-2007 Bob Beck (beck@openbsd.org>. All rights reserved.
-.\"
-.\" Permission to use, copy, modify, and distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
-.\" copyright notice and this permission notice appear in all copies.
-.\"
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.\"
-.Dd January 10, 2002
-.Dt AUTHPF 8
-.Os
-.Sh NAME
-.Nm authpf
-.Nd authenticating gateway user shell
-.Sh SYNOPSIS
-.Nm authpf
-.Sh DESCRIPTION
-.Nm
-is 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 undo these 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 syslogd 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 filter and translation rules using the syntax described in
-.Xr pf.conf 5 .
-.Nm
-requires that the
-.Xr pf 4
-system be enabled before use.
-.Nm
-can also maintain the list of IP address of connected users
-in the "authpf_users"
-.Pa table .
-.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 template file to determine what filter and translation rules
-(if any) to add.
-On session exit the same rules that were added at startup are removed.
-.Pp
-Each
-.Nm
-process stores its rules in a separate ruleset inside a
-.Xr pf 4
-.Pa anchor
-shared by all
-.Nm
-processes.
-By default, the
-.Pa anchor
-name "authpf" is used, and the ruleset names equal the username and PID of the
-.Nm
-processes as "username(pid)".
-The following rules need to be added to the main ruleset
-.Pa /etc/pf.conf
-in order to cause evaluation of any
-.Nm
-rules:
-.Bd -literal -offset indent
-nat-anchor "authpf/*"
-rdr-anchor "authpf/*"
-binat-anchor "authpf/*"
-anchor "authpf/*"
-.Ed
-.Pp
-The "/*" at the end of the anchor name is required for
-.Xr pf 4
-to process the rulesets attached to the anchor by
-.Nm authpf .
-.Sh FILTER AND TRANSLATION RULES
-Filter and translation rules for
-.Nm
-use the same format described in
-.Xr pf.conf 5 .
-The only difference is that these rules may (and probably should) use
-the macro
-.Em user_ip ,
-which is assigned the connecting IP address whenever
-.Nm
-is run.
-Additionally, the macro
-.Em user_id
-is assigned the user name.
-.Pp
-Filter and translation rules are stored in a file called
-.Pa authpf.rules .
-This file will first be searched for in
-.Pa /etc/authpf/users/$USER/
-and then in
-.Pa /etc/authpf/ .
-Only one of these files will be used if both are present.
-.Pp
-Per-user rules from the
-.Pa /etc/authpf/users/$USER/
-directory are intended to be used when non-default rules
-are needed on an individual user basis.
-It is important to ensure that a user can not write or change
-these configuration files.
-.Pp
-The
-.Pa authpf.rules
-file must exist in one of the above locations for
-.Nm
-to run.
-.Sh CONFIGURATION
-Options are controlled by the
-.Pa /etc/authpf/authpf.conf
-file.
-If the file is empty, defaults are used for all
-configuration options.
-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 anchor=name
-Use the specified
-.Pa anchor
-name instead of "authpf".
-.It table=name
-Use the specified
-.Pa table
-name instead of "authpf_users".
-.El
-.Sh USER MESSAGES
-On successful invocation,
-.Nm
-displays a message telling the user he or she has 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 as the
-filename in
-.Pa /etc/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 syslogd 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 configure
-.Xr sshd 8
-to ensure the security of the session, and to ensure that the network
-through which users connect is secure.
-.Xr sshd 8
-should be configured to use the
-.Ar ClientAliveInterval
-and
-.Ar ClientAliveCountMax
-parameters to ensure that a 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.
-Also note that the various SSH tunnelling mechanisms,
-such as
-.Ar AllowTcpForwarding
-and
-.Ar PermitTunnel ,
-should be disabled for
-.Nm
-users to prevent them from circumventing restrictions imposed by the
-packet filter ruleset.
-.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 which typically do not 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 /etc/authpf/banned/
-facilities.
-.Pp
-.Nm
-modifies the packet filter and address translation rules, and because
-of this it needs to be configured carefully.
-.Nm
-will not run and will exit silently if the
-.Pa /etc/authpf/authpf.conf
-file does not exist.
-After considering the effect
-.Nm
-may have on the main packet filter rules, the system administrator may
-enable
-.Nm
-by creating an appropriate
-.Pa /etc/authpf/authpf.conf
-file.
-.Sh EXAMPLES
-.Sy Control Files
-\- 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 /etc/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 /etc/authpf/banned/bob
-containing a message about why he has been banned from using the network.
-Once bob has done suitable penance, his access may be restored by moving or
-removing the file
-.Pa /etc/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 /etc/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
-.Sy Distributed Authentication
-\- 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 -offset indent
-shell-default:shell=/bin/csh
-
-default:\e
- ...
- :shell=/usr/sbin/authpf
-
-daemon:\e
- ...
- :shell=/bin/csh:\e
- :tc=default:
-
-staff:\e
- ...
- :shell=/bin/csh:\e
- :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
-.Sy SSH Configuration
-\- 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
-.Xr sshd_config 5 :
-.Bd -literal -offset indent
-Protocol 2
-ClientAliveInterval 15
-ClientAliveCountMax 3
-.Ed
-.Pp
-This ensures that unresponsive or spoofed sessions are terminated within a
-minute, since a hijacker should not be able to spoof ssh keepalive messages.
-.Pp
-.Sy Banners
-\- 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 -offset indent
-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 -offset indent
-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
-.Sy Packet Filter Rules
-\- 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.
-.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"
-nat-anchor "authpf/*"
-rdr-anchor "authpf/*"
-binat-anchor "authpf/*"
-block in on $internal_if from any to any
-pass in quick on $internal_if proto tcp from any to $gateway_addr \e
- port = ssh
-pass in quick on $internal_if proto udp from any to $gateway_addr \e
- port = domain
-anchor "authpf/*"
-.Ed
-.Pp
-.Sy For a switched, wired net
-\- This example
-.Pa /etc/authpf/authpf.rules
-makes no real restrictions; it turns the IP address on and off, logging
-TCP connections.
-.Bd -literal
-external_if = "xl0"
-internal_if = "fxp0"
-
-pass in log quick on $internal_if proto tcp from $user_ip to any
-pass in quick on $internal_if from $user_ip to any
-.Ed
-.Pp
-.Sy For a wireless or shared net
-\- This example
-.Pa /etc/authpf/authpf.rules
-could be used 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"
-
-# rdr ftp for proxying by ftp-proxy(8)
-rdr on $internal_if proto tcp from $user_ip to any port 21 \e
- -> 127.0.0.1 port 8021
-
-# allow out ftp, ssh, www and https only, and allow user to negotiate
-# ipsec with the ipsec server.
-pass in log quick on $internal_if proto tcp from $user_ip to any \e
- port { 21, 22, 80, 443 }
-pass in quick on $internal_if proto tcp from $user_ip to any \e
- port { 21, 22, 80, 443 }
-pass in quick proto udp from $user_ip to $ipsec_gw port = isakmp
-pass in quick proto esp from $user_ip to $ipsec_gw
-.Ed
-.Pp
-.Sy Dealing with NAT
-\- The following
-.Pa /etc/authpf/authpf.rules
-shows how to deal with NAT, using tags:
-.Bd -literal
-ext_if = "fxp1"
-ext_addr = 129.128.11.10
-int_if = "fxp0"
-# nat and tag connections...
-nat on $ext_if from $user_ip to any tag $user_ip -> $ext_addr
-pass in quick on $int_if from $user_ip to any
-pass out log quick on $ext_if tagged $user_ip
-.Ed
-.Pp
-With the above rules added by
-.Nm ,
-outbound connections corresponding to each users NAT'ed connections
-will be logged as in the example below, where the user may be identified
-from the ruleset name.
-.Bd -literal
-# tcpdump -n -e -ttt -i pflog0
-Oct 31 19:42:30.296553 rule 0.bbeck(20267).1/0(match): pass out on fxp1: \e
-129.128.11.10.60539 > 198.137.240.92.22: S 2131494121:2131494121(0) win \e
-16384 <mss 1460,nop,nop,sackOK> (DF)
-.Ed
-.Pp
-.Sy Using the authpf_users table
-\- Simple
-.Nm
-settings can be implemented without an anchor by just using the "authpf_users"
-.Pa table .
-For example, the following
-.Xr pf.conf 5
-lines will give SMTP and IMAP access to logged in users:
-.Bd -literal
-table <authpf_users> persist
-pass in on $ext_if proto tcp from <authpf_users> \e
- to port { smtp imap }
-.Ed
-.Pp
-It is also possible to use the "authpf_users"
-.Pa table
-in combination with anchors.
-For example,
-.Xr pf 4
-processing can be sped up by looking up the anchor
-only for packets coming from logged in users:
-.Bd -literal
-table <authpf_users> persist
-anchor "authpf/*" from <authpf_users>
-rdr-anchor "authpf/*" from <authpf_users>
-.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.message
-.It Pa /etc/authpf/authpf.problem
-.El
-.Sh SEE ALSO
-.Xr pf 4 ,
-.Xr pf.conf 5 ,
-.Xr securelevel 7 ,
-.Xr ftp-proxy 8
-.Sh HISTORY
-The
-.Nm
-program first appeared in
-.Ox 3.1 .
-.Sh BUGS
-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 the 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.
diff --git a/contrib/pf/authpf/authpf.c b/contrib/pf/authpf/authpf.c
deleted file mode 100644
index 68adcd258eef..000000000000
--- a/contrib/pf/authpf/authpf.c
+++ /dev/null
@@ -1,830 +0,0 @@
-/* $OpenBSD: authpf.c,v 1.104 2007/02/24 17:35:08 beck Exp $ */
-
-/*
- * Copyright (C) 1998 - 2007 Bob Beck (beck@openbsd.org).
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#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 <sys/wait.h>
-
-#include <net/if.h>
-#include <net/pfvar.h>
-#include <arpa/inet.h>
-
-#include <err.h>
-#include <errno.h>
-#include <login_cap.h>
-#include <pwd.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#include "pathnames.h"
-
-static int read_config(FILE *);
-static void print_message(char *);
-static int allowed_luser(char *);
-static int check_luser(char *, char *);
-static int remove_stale_rulesets(void);
-static int change_filter(int, const char *, const char *);
-static int change_table(int, const char *);
-static void authpf_kill_states(void);
-
-int dev; /* pf device */
-char anchorname[PF_ANCHOR_NAME_SIZE] = "authpf";
-char rulesetname[MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 2];
-char tablename[PF_TABLE_NAME_SIZE] = "authpf_users";
-
-FILE *pidfp;
-char luser[MAXLOGNAME]; /* username */
-char ipsrc[256]; /* ip as a string */
-char pidfile[MAXPATHLEN]; /* we save pid in this file. */
-
-struct timeval Tstart, Tend; /* start and end times of session */
-
-volatile sig_atomic_t want_death;
-static void need_death(int signo);
-static __dead void do_death(int);
-
-/*
- * 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 lockcnt = 0, n, pidfd;
- FILE *config;
- struct in6_addr ina;
- struct passwd *pw;
- char *cp;
- gid_t gid;
- uid_t uid;
- char *shell;
- login_cap_t *lc;
-
- config = fopen(PATH_CONFFILE, "r");
- if (config == NULL) {
- syslog(LOG_ERR, "can not open %s (%m)", PATH_CONFFILE);
- exit(1);
- }
-
- if ((cp = getenv("SSH_TTY")) == NULL) {
- syslog(LOG_ERR, "non-interactive session connection for authpf");
- exit(1);
- }
-
- if ((cp = getenv("SSH_CLIENT")) == NULL) {
- syslog(LOG_ERR, "cannot determine connection source");
- exit(1);
- }
-
- if (strlcpy(ipsrc, cp, sizeof(ipsrc)) >= sizeof(ipsrc)) {
- syslog(LOG_ERR, "SSH_CLIENT variable too long");
- exit(1);
- }
- cp = strchr(ipsrc, ' ');
- if (!cp) {
- syslog(LOG_ERR, "corrupt SSH_CLIENT variable %s", ipsrc);
- exit(1);
- }
- *cp = '\0';
- if (inet_pton(AF_INET, ipsrc, &ina) != 1 &&
- inet_pton(AF_INET6, ipsrc, &ina) != 1) {
- syslog(LOG_ERR,
- "cannot determine IP from SSH_CLIENT %s", ipsrc);
- exit(1);
- }
- /* open the pf device */
- dev = open(PATH_DEVFILE, O_RDWR);
- if (dev == -1) {
- syslog(LOG_ERR, "cannot open packet filter device (%m)");
- goto die;
- }
-
- uid = getuid();
- pw = getpwuid(uid);
- if (pw == NULL) {
- syslog(LOG_ERR, "cannot find user for uid %u", uid);
- goto die;
- }
-
- if ((lc = login_getclass(pw->pw_class)) != NULL)
- shell = login_getcapstr(lc, "shell", pw->pw_shell,
- pw->pw_shell);
- else
- shell = pw->pw_shell;
-
- login_close(lc);
-
- if (strcmp(shell, PATH_AUTHPF_SHELL)) {
- syslog(LOG_ERR, "wrong shell for user %s, uid %u",
- pw->pw_name, pw->pw_uid);
- if (shell != pw->pw_shell)
- free(shell);
- goto die;
- }
-
- if (shell != pw->pw_shell)
- free(shell);
-
- /*
- * Paranoia, but this data _does_ come from outside authpf, and
- * truncation would be bad.
- */
- if (strlcpy(luser, pw->pw_name, sizeof(luser)) >= sizeof(luser)) {
- syslog(LOG_ERR, "username too long: %s", pw->pw_name);
- goto die;
- }
-
- if ((n = snprintf(rulesetname, sizeof(rulesetname), "%s(%ld)",
- luser, (long)getpid())) < 0 || (u_int)n >= sizeof(rulesetname)) {
- syslog(LOG_INFO, "%s(%ld) too large, ruleset name will be %ld",
- luser, (long)getpid(), (long)getpid());
- if ((n = snprintf(rulesetname, sizeof(rulesetname), "%ld",
- (long)getpid())) < 0 || (u_int)n >= sizeof(rulesetname)) {
- syslog(LOG_ERR, "pid too large for ruleset name");
- goto die;
- }
- }
-
-
- /* Make our entry in /var/authpf as /var/authpf/ipaddr */
- n = snprintf(pidfile, sizeof(pidfile), "%s/%s", PATH_PIDFILE, ipsrc);
- if (n < 0 || (u_int)n >= sizeof(pidfile)) {
- syslog(LOG_ERR, "path to pidfile too long");
- goto die;
- }
-
- /*
- * If someone else is already using this ip, then this person
- * wants to switch users - so kill the old process and exit
- * as well.
- *
- * 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.
- */
-
- do {
- int save_errno, otherpid = -1;
- char otherluser[MAXLOGNAME];
-
- if ((pidfd = open(pidfile, O_RDWR|O_CREAT, 0644)) == -1 ||
- (pidfp = fdopen(pidfd, "r+")) == NULL) {
- if (pidfd != -1)
- close(pidfd);
- syslog(LOG_ERR, "cannot open or create %s: %s", pidfile,
- strerror(errno));
- goto die;
- }
-
- if (flock(fileno(pidfp), LOCK_EX|LOCK_NB) == 0)
- break;
- save_errno = errno;
-
- /* Mark our pid, and username to our file. */
-
- rewind(pidfp);
- /* 31 == MAXLOGNAME - 1 */
- if (fscanf(pidfp, "%d\n%31s\n", &otherpid, otherluser) != 2)
- otherpid = -1;
- syslog(LOG_DEBUG, "tried to lock %s, in use by pid %d: %s",
- pidfile, otherpid, strerror(save_errno));
-
- if (otherpid > 0) {
- syslog(LOG_INFO,
- "killing prior auth (pid %d) of %s by user %s",
- otherpid, ipsrc, otherluser);
- if (kill((pid_t) otherpid, SIGTERM) == -1) {
- syslog(LOG_INFO,
- "could not kill process %d: (%m)",
- otherpid);
- }
- }
-
- /*
- * we try to kill the previous process and acquire 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, "cannot kill previous authpf (pid %d)",
- otherpid);
- fclose(pidfp);
- pidfp = NULL;
- goto dogdeath;
- }
- sleep(1);
-
- /* re-open, and try again. The previous authpf process
- * we killed above should unlink the file and release
- * it's lock, giving us a chance to get it now
- */
- fclose(pidfp);
- pidfp = NULL;
- } while (1);
-
- /* whack the group list */
- gid = getegid();
- if (setgroups(1, &gid) == -1) {
- syslog(LOG_INFO, "setgroups: %s", strerror(errno));
- do_death(0);
- }
-
- /* revoke privs */
- uid = getuid();
- if (setresuid(uid, uid, uid) == -1) {
- syslog(LOG_INFO, "setresuid: %s", strerror(errno));
- do_death(0);
- }
- openlog("authpf", LOG_PID | LOG_NDELAY, LOG_DAEMON);
-
- if (!check_luser(PATH_BAN_DIR, luser) || !allowed_luser(luser)) {
- syslog(LOG_INFO, "user %s prohibited", luser);
- do_death(0);
- }
-
- if (read_config(config)) {
- syslog(LOG_ERR, "invalid config file %s", PATH_CONFFILE);
- do_death(0);
- }
-
- if (remove_stale_rulesets()) {
- syslog(LOG_INFO, "error removing stale rulesets");
- do_death(0);
- }
-
- /* We appear to be making headway, so actually mark our pid */
- rewind(pidfp);
- fprintf(pidfp, "%ld\n%s\n", (long)getpid(), luser);
- fflush(pidfp);
- (void) ftruncate(fileno(pidfp), ftello(pidfp));
-
- if (change_filter(1, luser, ipsrc) == -1) {
- printf("Unable to modify filters\r\n");
- do_death(0);
- }
- if (change_table(1, ipsrc) == -1) {
- printf("Unable to modify table\r\n");
- change_filter(0, luser, ipsrc);
- do_death(0);
- }
-
- signal(SIGTERM, need_death);
- signal(SIGINT, need_death);
- signal(SIGALRM, need_death);
- signal(SIGPIPE, need_death);
- signal(SIGHUP, need_death);
- signal(SIGQUIT, need_death);
- signal(SIGTSTP, need_death);
- while (1) {
- printf("\r\nHello %s. ", luser);
- printf("You are authenticated from host \"%s\"\r\n", ipsrc);
- setproctitle("%s@%s", luser, ipsrc);
- print_message(PATH_MESSAGE);
- while (1) {
- sleep(10);
- if (want_death)
- do_death(1);
- }
- }
-
- /* 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 %ld) was unable to run\n",
- (long)getpid());
- sleep(180); /* them lusers read reaaaaal slow */
-die:
- do_death(0);
-}
-
-/*
- * reads config file in PATH_CONFFILE to set optional behaviours up
- */
-static int
-read_config(FILE *f)
-{
- char buf[1024];
- int i = 0;
-
- do {
- char **ap;
- char *pair[4], *cp, *tp;
- int len;
-
- if (fgets(buf, sizeof(buf), f) == NULL) {
- fclose(f);
- return (0);
- }
- i++;
- len = strlen(buf);
- if (buf[len - 1] != '\n' && !feof(f)) {
- syslog(LOG_ERR, "line %d too long in %s", i,
- PATH_CONFFILE);
- return (1);
- }
- buf[len - 1] = '\0';
-
- for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
- ; /* nothing */
-
- 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], "anchor") == 0) {
- if (!pair[1][0] || strlcpy(anchorname, pair[1],
- sizeof(anchorname)) >= sizeof(anchorname))
- goto parse_error;
- }
- if (strcasecmp(pair[0], "table") == 0) {
- if (!pair[1][0] || strlcpy(tablename, pair[1],
- sizeof(tablename)) >= sizeof(tablename))
- goto parse_error;
- }
- } while (!feof(f) && !ferror(f));
- fclose(f);
- return (0);
-
-parse_error:
- fclose(f);
- syslog(LOG_ERR, "parse error, line %d of %s", i, PATH_CONFFILE);
- return (1);
-}
-
-
-/*
- * 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));
- fflush(stdout);
- fclose(f);
-}
-
-/*
- * 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/authpf.allow .
- *
- * If /etc/authpf/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/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;
- int matched;
- size_t len;
- FILE *f;
-
- if ((f = fopen(PATH_ALLOWFILE, "r")) == NULL) {
- if (errno == ENOENT) {
- /*
- * allowfile doesn't exist, thus 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, "cannot open allowed users file %s (%s)",
- PATH_ALLOWFILE, strerror(errno));
- return (0);
- } else {
- /*
- * /etc/authpf/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;
- }
-
- matched = strcmp(luser, buf) == 0 || strcmp("*", buf) == 0;
-
- if (lbuf != NULL) {
- free(lbuf);
- lbuf = NULL;
- }
-
- if (matched)
- return (1); /* matched an allowed username */
- }
- syslog(LOG_INFO, "denied access to %s: not listed in %s",
- luser, PATH_ALLOWFILE);
-
- /* reuse buf */
- buf = "\n\nSorry, you are not allowed to use this facility!\n";
- fputs(buf, stdout);
- }
- fflush(stdout);
- return (0);
-}
-
-/*
- * 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)
-{
- FILE *f;
- int n;
- char tmp[MAXPATHLEN];
-
- n = snprintf(tmp, sizeof(tmp), "%s/%s", luserdir, luser);
- if (n < 0 || (u_int)n >= 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, "cannot 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);
- fclose(f);
- return (0);
- }
- }
- fclose(f);
- }
- fflush(stdout);
- return (0);
-}
-
-/*
- * Search for rulesets left by other authpf processes (either because they
- * died ungracefully or were terminated) and remove them.
- */
-static int
-remove_stale_rulesets(void)
-{
- struct pfioc_ruleset prs;
- u_int32_t nr, mnr;
-
- memset(&prs, 0, sizeof(prs));
- strlcpy(prs.path, anchorname, sizeof(prs.path));
- if (ioctl(dev, DIOCGETRULESETS, &prs)) {
- if (errno == EINVAL)
- return (0);
- else
- return (1);
- }
-
- mnr = prs.nr;
- nr = 0;
- while (nr < mnr) {
- char *s, *t;
- pid_t pid;
-
- prs.nr = nr;
- if (ioctl(dev, DIOCGETRULESET, &prs))
- return (1);
- errno = 0;
- if ((t = strchr(prs.name, '(')) == NULL)
- t = prs.name;
- else
- t++;
- pid = strtoul(t, &s, 10);
- if (!prs.name[0] || errno ||
- (*s && (t == prs.name || *s != ')')))
- return (1);
- if (kill(pid, 0) && errno != EPERM) {
- int i;
- struct pfioc_trans_e t_e[PF_RULESET_MAX+1];
- struct pfioc_trans t;
-
- bzero(&t, sizeof(t));
- bzero(t_e, sizeof(t_e));
- t.size = PF_RULESET_MAX+1;
- t.esize = sizeof(t_e[0]);
- t.array = t_e;
- for (i = 0; i < PF_RULESET_MAX+1; ++i) {
- t_e[i].rs_num = i;
- snprintf(t_e[i].anchor, sizeof(t_e[i].anchor),
- "%s/%s", anchorname, prs.name);
- }
- t_e[PF_RULESET_MAX].rs_num = PF_RULESET_TABLE;
- if ((ioctl(dev, DIOCXBEGIN, &t) ||
- ioctl(dev, DIOCXCOMMIT, &t)) &&
- errno != EINVAL)
- return (1);
- mnr--;
- } else
- nr++;
- }
- return (0);
-}
-
-/*
- * Add/remove filter entries for user "luser" from ip "ipsrc"
- */
-static int
-change_filter(int add, const char *luser, const char *ipsrc)
-{
- char *pargv[13] = {
- "pfctl", "-p", "/dev/pf", "-q", "-a", "anchor/ruleset",
- "-D", "user_ip=X", "-D", "user_id=X", "-f",
- "file", NULL
- };
- char *fdpath = NULL, *userstr = NULL, *ipstr = NULL;
- char *rsn = NULL, *fn = NULL;
- pid_t pid;
- gid_t gid;
- int s;
-
- if (luser == NULL || !luser[0] || ipsrc == NULL || !ipsrc[0]) {
- syslog(LOG_ERR, "invalid luser/ipsrc");
- goto error;
- }
-
- if (asprintf(&rsn, "%s/%s", anchorname, rulesetname) == -1)
- goto no_mem;
- if (asprintf(&fdpath, "/dev/fd/%d", dev) == -1)
- goto no_mem;
- if (asprintf(&ipstr, "user_ip=%s", ipsrc) == -1)
- goto no_mem;
- if (asprintf(&userstr, "user_id=%s", luser) == -1)
- goto no_mem;
-
- if (add) {
- struct stat sb;
-
- if (asprintf(&fn, "%s/%s/authpf.rules", PATH_USER_DIR, luser)
- == -1)
- goto no_mem;
- if (stat(fn, &sb) == -1) {
- free(fn);
- if ((fn = strdup(PATH_PFRULES)) == NULL)
- goto no_mem;
- }
- }
- pargv[2] = fdpath;
- pargv[5] = rsn;
- pargv[7] = userstr;
- pargv[9] = ipstr;
- if (!add)
- pargv[11] = "/dev/null";
- else
- pargv[11] = fn;
-
- switch (pid = fork()) {
- case -1:
- syslog(LOG_ERR, "fork failed");
- goto error;
- case 0:
- /* revoke group privs before exec */
- gid = getgid();
- if (setregid(gid, gid) == -1) {
- err(1, "setregid");
- }
- execvp(PATH_PFCTL, pargv);
- warn("exec of %s failed", PATH_PFCTL);
- _exit(1);
- }
-
- /* parent */
- waitpid(pid, &s, 0);
- if (s != 0) {
- syslog(LOG_ERR, "pfctl exited abnormally");
- goto error;
- }
-
- if (add) {
- gettimeofday(&Tstart, NULL);
- syslog(LOG_INFO, "allowing %s, user %s", ipsrc, luser);
- } else {
- gettimeofday(&Tend, NULL);
- syslog(LOG_INFO, "removed %s, user %s - duration %ld seconds",
- ipsrc, luser, Tend.tv_sec - Tstart.tv_sec);
- }
- return (0);
-no_mem:
- syslog(LOG_ERR, "malloc failed");
-error:
- free(fdpath);
- free(rsn);
- free(userstr);
- free(ipstr);
- free(fn);
- return (-1);
-}
-
-/*
- * Add/remove this IP from the "authpf_users" table.
- */
-static int
-change_table(int add, const char *ipsrc)
-{
- struct pfioc_table io;
- struct pfr_addr addr;
-
- bzero(&io, sizeof(io));
- strlcpy(io.pfrio_table.pfrt_name, tablename,
- sizeof(io.pfrio_table.pfrt_name));
- io.pfrio_buffer = &addr;
- io.pfrio_esize = sizeof(addr);
- io.pfrio_size = 1;
-
- bzero(&addr, sizeof(addr));
- if (ipsrc == NULL || !ipsrc[0])
- return (-1);
- if (inet_pton(AF_INET, ipsrc, &addr.pfra_ip4addr) == 1) {
- addr.pfra_af = AF_INET;
- addr.pfra_net = 32;
- } else if (inet_pton(AF_INET6, ipsrc, &addr.pfra_ip6addr) == 1) {
- addr.pfra_af = AF_INET6;
- addr.pfra_net = 128;
- } else {
- syslog(LOG_ERR, "invalid ipsrc");
- return (-1);
- }
-
- if (ioctl(dev, add ? DIOCRADDADDRS : DIOCRDELADDRS, &io) &&
- errno != ESRCH) {
- syslog(LOG_ERR, "cannot %s %s from table %s: %s",
- add ? "add" : "remove", ipsrc, tablename,
- strerror(errno));
- return (-1);
- }
- return (0);
-}
-
-/*
- * This is to kill off states that would otherwise 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(void)
-{
- struct pfioc_state_kill psk;
- struct pf_addr target;
-
- memset(&psk, 0, sizeof(psk));
- memset(&target, 0, sizeof(target));
-
- if (inet_pton(AF_INET, ipsrc, &target.v4) == 1)
- psk.psk_af = AF_INET;
- else if (inet_pton(AF_INET6, ipsrc, &target.v6) == 1)
- psk.psk_af = AF_INET6;
- else {
- syslog(LOG_ERR, "inet_pton(%s) failed", ipsrc);
- return;
- }
-
- /* Kill all states from ipsrc */
- memcpy(&psk.psk_src.addr.v.a.addr, &target,
- sizeof(psk.psk_src.addr.v.a.addr));
- memset(&psk.psk_src.addr.v.a.mask, 0xff,
- sizeof(psk.psk_src.addr.v.a.mask));
- if (ioctl(dev, DIOCKILLSTATES, &psk))
- syslog(LOG_ERR, "DIOCKILLSTATES failed (%m)");
-
- /* Kill all states to ipsrc */
- memset(&psk.psk_src, 0, sizeof(psk.psk_src));
- memcpy(&psk.psk_dst.addr.v.a.addr, &target,
- sizeof(psk.psk_dst.addr.v.a.addr));
- memset(&psk.psk_dst.addr.v.a.mask, 0xff,
- sizeof(psk.psk_dst.addr.v.a.mask));
- if (ioctl(dev, DIOCKILLSTATES, &psk))
- syslog(LOG_ERR, "DIOCKILLSTATES failed (%m)");
-}
-
-/* signal handler that makes us go away properly */
-static void
-need_death(int signo)
-{
- want_death = 1;
-}
-
-/*
- * function that removes our stuff when we go away.
- */
-static __dead void
-do_death(int active)
-{
- int ret = 0;
-
- if (active) {
- change_filter(0, luser, ipsrc);
- change_table(0, ipsrc);
- authpf_kill_states();
- remove_stale_rulesets();
- }
- if (pidfile[0] && (pidfp != NULL))
- if (unlink(pidfile) == -1)
- syslog(LOG_ERR, "cannot unlink %s (%m)", pidfile);
- exit(ret);
-}
diff --git a/contrib/pf/authpf/pathnames.h b/contrib/pf/authpf/pathnames.h
deleted file mode 100644
index 358bfd0c106d..000000000000
--- a/contrib/pf/authpf/pathnames.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* $OpenBSD: pathnames.h,v 1.7 2004/04/25 18:40:42 beck Exp $ */
-
-/*
- * 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.
- *
- * 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_PROBLEM "/etc/authpf/authpf.problem"
-#define PATH_MESSAGE "/etc/authpf/authpf.message"
-#define PATH_USER_DIR "/etc/authpf/users"
-#define PATH_BAN_DIR "/etc/authpf/banned"
-#define PATH_DEVFILE "/dev/pf"
-#define PATH_PIDFILE "/var/authpf"
-#define PATH_AUTHPF_SHELL "/usr/sbin/authpf"
-#define PATH_PFCTL "/sbin/pfctl"