summaryrefslogtreecommitdiffstats
path: root/contrib/pf/authpf
diff options
context:
space:
mode:
authormlaier <mlaier@FreeBSD.org>2004-06-16 23:26:00 +0000
committermlaier <mlaier@FreeBSD.org>2004-06-16 23:26:00 +0000
commit6a32f6ec2e479ff91d30ed651bcb24ad8d14e84e (patch)
tree91591a3c3277d8525d725da18322a0f9ba6078a2 /contrib/pf/authpf
parentc9eda2a3d0e4116e5b63faaab29f4fe0695a4dad (diff)
downloadFreeBSD-src-6a32f6ec2e479ff91d30ed651bcb24ad8d14e84e.zip
FreeBSD-src-6a32f6ec2e479ff91d30ed651bcb24ad8d14e84e.tar.gz
Import userland of pf 3.5 from OpenBSD (OPENBSD_3_5_BASE).
Diffstat (limited to 'contrib/pf/authpf')
-rw-r--r--contrib/pf/authpf/authpf.874
-rw-r--r--contrib/pf/authpf/authpf.c138
2 files changed, 142 insertions, 70 deletions
diff --git a/contrib/pf/authpf/authpf.8 b/contrib/pf/authpf/authpf.8
index 141aecf..b6977da 100644
--- a/contrib/pf/authpf/authpf.8
+++ b/contrib/pf/authpf/authpf.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: authpf.8,v 1.30 2003/08/17 23:24:47 henning Exp $
+.\" $OpenBSD: authpf.8,v 1.31 2003/12/10 04:10:37 beck Exp $
.\"
.\" Copyright (c) 2002 Bob Beck (beck@openbsd.org>. All rights reserved.
.\"
@@ -84,9 +84,9 @@ shared by all
processes.
By default, the
.Pa anchor
-name "authpf" is used, and the ruleset names equal the PIDs of the
+name "authpf" is used, and the ruleset names equal the username and PID of the
.Nm
-processes.
+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
@@ -263,7 +263,8 @@ by creating an appropriate
.Pa /etc/authpf/authpf.conf
file.
.Sh EXAMPLES
-\fBControl Files\fP - To illustrate the user-specific access control
+.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
@@ -298,7 +299,8 @@ 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
+.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
@@ -332,7 +334,8 @@ Using a default password file, all users will get
as their shell except for root who will get
.Pa /bin/csh .
.Pp
-\fBSSH Configuration\fP - As stated earlier,
+.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
@@ -346,7 +349,8 @@ ClientAliveCountMax 3
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
-\fBBanners\fP - Once authenticated, the user is shown the contents of
+.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
@@ -366,7 +370,8 @@ 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
+.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
@@ -378,15 +383,14 @@ 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\&"
+internal_if="fxp1"
+gateway_addr="10.0.1.1"
nat-anchor authpf
rdr-anchor authpf
binat-anchor authpf
@@ -398,26 +402,28 @@ pass in quick on $internal_if proto udp from any to $gateway_addr \e
anchor authpf
.Ed
.Pp
-Example
-.Pa /etc/authpf/authpf.rules :
+.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
-# no real restrictions here, basically turn the network jack off or on.
-
-external_if = \&"xl0\&"
-internal_if = \&"fxp0\&"
+external_if = "xl0"
+internal_if = "fxp0"
pass in log quick on $internal_if proto tcp from $user_ip to any \e
keep state
pass in quick on $internal_if from $user_ip to any
.Ed
.Pp
-Another example
+.Sy For a wireless or shared net
+\- This example
.Pa /etc/authpf/authpf.rules
-for an insecure network (such as a public wireless network) where
+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\&"
+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
@@ -433,6 +439,32 @@ pass in quick proto udp from $user_ip to $ipsec_gw port = isakmp \e
keep state
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 keep state
+.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
.Sh FILES
.Bl -tag -width "/etc/authpf/authpf.conf" -compact
.It Pa /etc/authpf/authpf.conf
diff --git a/contrib/pf/authpf/authpf.c b/contrib/pf/authpf/authpf.c
index 8828ffc..515cf8e 100644
--- a/contrib/pf/authpf/authpf.c
+++ b/contrib/pf/authpf/authpf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: authpf.c,v 1.68 2003/08/21 19:13:23 frantzen Exp $ */
+/* $OpenBSD: authpf.c,v 1.75 2004/01/29 01:55:10 deraadt Exp $ */
/*
* Copyright (C) 1998 - 2002 Bob Beck (beck@openbsd.org).
@@ -46,6 +46,7 @@
#include <unistd.h>
#include <pfctl_parser.h>
+#include <pfctl.h>
#include "pathnames.h"
@@ -91,12 +92,6 @@ main(int argc, char *argv[])
char *cp;
uid_t uid;
- if ((n = snprintf(rulesetname, sizeof(rulesetname), "%ld",
- (long)getpid())) < 0 || n >= sizeof(rulesetname)) {
- syslog(LOG_ERR, "pid too large for ruleset name");
- exit(1);
- }
-
config = fopen(PATH_CONFFILE, "r");
if ((cp = getenv("SSH_TTY")) == NULL) {
@@ -124,7 +119,6 @@ main(int argc, char *argv[])
"cannot determine IP from SSH_CLIENT %s", ipsrc);
exit(1);
}
-
/* open the pf device */
dev = open(PATH_DEVFILE, O_RDWR);
if (dev == -1) {
@@ -153,6 +147,18 @@ main(int argc, char *argv[])
goto die;
}
+ if ((n = snprintf(rulesetname, sizeof(rulesetname), "%s(%ld)",
+ luser, (long)getpid())) < 0 || 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 || 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)) {
@@ -235,15 +241,22 @@ main(int argc, char *argv[])
seteuid(getuid());
setuid(getuid());
- if (!check_luser(PATH_BAN_DIR, luser) || !allowed_luser(luser))
+ 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);
+ }
- openlog("authpf", LOG_PID | LOG_NDELAY, LOG_DAEMON);
- if (config == NULL || read_config(config))
+ if (config == NULL || read_config(config)) {
+ syslog(LOG_INFO, "bad or nonexistent %s", PATH_CONFFILE);
do_death(0);
+ }
- if (remove_stale_rulesets())
+ 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);
@@ -253,7 +266,7 @@ main(int argc, char *argv[])
if (change_filter(1, luser, ipsrc) == -1) {
printf("Unable to modify filters\r\n");
- do_death(1);
+ do_death(0);
}
signal(SIGTERM, need_death);
@@ -536,15 +549,20 @@ remove_stale_rulesets(void)
mnr = prs.nr;
nr = 0;
while (nr < mnr) {
- char *s;
+ char *s, *t;
pid_t pid;
prs.nr = nr;
if (ioctl(dev, DIOCGETRULESET, &prs))
return (1);
errno = 0;
- pid = strtoul(prs.name, &s, 10);
- if (!prs.name[0] || errno || *s)
+ 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;
@@ -576,14 +594,11 @@ change_filter(int add, const char *luser, const char *ipsrc)
{
char fn[MAXPATHLEN];
FILE *f = NULL;
- const int action[PF_RULESET_MAX] = { PF_SCRUB,
- PF_PASS, PF_NAT, PF_BINAT, PF_RDR };
struct pfctl pf;
- struct pfioc_rule pr[PF_RULESET_MAX];
+ struct pfr_buffer t;
int i;
- if (luser == NULL || !luser[0] || strlen(luser) >=
- PF_RULESET_NAME_SIZE || ipsrc == NULL || !ipsrc[0]) {
+ if (luser == NULL || !luser[0] || ipsrc == NULL || !ipsrc[0]) {
syslog(LOG_ERR, "invalid luser/ipsrc");
goto error;
}
@@ -615,18 +630,18 @@ change_filter(int add, const char *luser, const char *ipsrc)
syslog(LOG_ERR, "unable to load kernel's OS fingerprints");
goto error;
}
-
+ bzero(&t, sizeof(t));
+ t.pfrb_type = PFRB_TRANS;
memset(&pf, 0, sizeof(pf));
for (i = 0; i < PF_RULESET_MAX; ++i) {
- memset(&pr[i], 0, sizeof(pr[i]));
- pr[i].rule.action = action[i];
- strlcpy(pr[i].anchor, anchorname, sizeof(pr[i].anchor));
- strlcpy(pr[i].ruleset, rulesetname, sizeof(pr[i].ruleset));
- if (ioctl(dev, DIOCBEGINRULES, &pr[i])) {
- syslog(LOG_ERR, "DIOCBEGINRULES %m");
+ if (pfctl_add_trans(&t, i, anchorname, rulesetname)) {
+ syslog(LOG_ERR, "pfctl_add_trans %m");
goto error;
}
- pf.prule[i] = &pr[i];
+ }
+ if (pfctl_trans(dev, &t, DIOCXBEGIN, 0)) {
+ syslog(LOG_ERR, "DIOCXBEGIN (%s) %m", add?"add":"remove");
+ goto error;
}
if (add) {
@@ -637,6 +652,10 @@ change_filter(int add, const char *luser, const char *ipsrc)
}
pf.dev = dev;
+ pf.trans = &t;
+ pf.anchor = anchorname;
+ pf.ruleset = rulesetname;
+
infile = fn;
if (parse_rules(f, &pf) < 0) {
syslog(LOG_ERR, "syntax error in rule file: "
@@ -649,16 +668,10 @@ change_filter(int add, const char *luser, const char *ipsrc)
f = NULL;
}
- for (i = 0; i < PF_RULESET_MAX; ++i)
- /*
- * ignore EINVAL on removal, it means the anchor was
- * already automatically removed by the kernel.
- */
- if (ioctl(dev, DIOCCOMMITRULES, &pr[i]) &&
- (add || errno != EINVAL)) {
- syslog(LOG_ERR, "DIOCCOMMITRULES %m");
- goto error;
- }
+ if (pfctl_trans(dev, &t, DIOCXCOMMIT, 0)) {
+ syslog(LOG_ERR, "DIOCXCOMMIT (%s) %m", add?"add":"remove");
+ goto error;
+ }
if (add) {
gettimeofday(&Tstart, NULL);
@@ -673,6 +686,8 @@ change_filter(int add, const char *luser, const char *ipsrc)
error:
if (f != NULL)
fclose(f);
+ if (pfctl_trans(dev, &t, DIOCXROLLBACK, 0))
+ syslog(LOG_ERR, "DIOCXROLLBACK (%s) %m", add?"add":"remove");
infile = NULL;
return (-1);
@@ -748,37 +763,44 @@ do_death(int active)
int
pfctl_add_rule(struct pfctl *pf, struct pf_rule *r)
{
- struct pfioc_rule *pr;
+ u_int8_t rs_num;
+ struct pfioc_rule pr;
switch (r->action) {
case PF_PASS:
case PF_DROP:
- pr = pf->prule[PF_RULESET_FILTER];
+ rs_num = PF_RULESET_FILTER;
break;
case PF_SCRUB:
- pr = pf->prule[PF_RULESET_SCRUB];
+ rs_num = PF_RULESET_SCRUB;
break;
case PF_NAT:
case PF_NONAT:
- pr = pf->prule[PF_RULESET_NAT];
+ rs_num = PF_RULESET_NAT;
break;
case PF_RDR:
case PF_NORDR:
- pr = pf->prule[PF_RULESET_RDR];
+ rs_num = PF_RULESET_RDR;
break;
case PF_BINAT:
case PF_NOBINAT:
- pr = pf->prule[PF_RULESET_BINAT];
+ rs_num = PF_RULESET_BINAT;
break;
default:
syslog(LOG_ERR, "invalid rule action %d", r->action);
return (1);
}
+
+ bzero(&pr, sizeof(pr));
+ strlcpy(pr.anchor, pf->anchor, sizeof(pr.anchor));
+ strlcpy(pr.ruleset, pf->ruleset, sizeof(pr.ruleset));
if (pfctl_add_pool(pf, &r->rpool, r->af))
return (1);
- pr->pool_ticket = pf->paddr.ticket;
- memcpy(&pr->rule, r, sizeof(pr->rule));
- if (ioctl(pf->dev, DIOCADDRULE, pr)) {
+ pr.ticket = pfctl_get_ticket(pf->trans, rs_num, pf->anchor,
+ pf->ruleset);
+ pr.pool_ticket = pf->paddr.ticket;
+ memcpy(&pr.rule, r, sizeof(pr.rule));
+ if (ioctl(pf->dev, DIOCADDRULE, &pr)) {
syslog(LOG_ERR, "DIOCADDRULE %m");
return (1);
}
@@ -839,6 +861,13 @@ pfctl_set_logif(struct pfctl *pf, char *ifname)
}
int
+pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid)
+{
+ fprintf(stderr, "set hostid not supported in authpf\n");
+ return (1);
+}
+
+int
pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
{
fprintf(stderr, "set timeout not supported in authpf\n");
@@ -853,6 +882,13 @@ pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit)
}
int
+pfctl_set_debug(struct pfctl *pf, char *d)
+{
+ fprintf(stderr, "set debug not supported in authpf\n");
+ return (1);
+}
+
+int
pfctl_define_table(char *name, int flags, int addrs, const char *anchor,
const char *ruleset, struct pfr_buffer *ab, u_int32_t ticket)
{
@@ -862,10 +898,14 @@ pfctl_define_table(char *name, int flags, int addrs, const char *anchor,
int
pfctl_rules(int dev, char *filename, int opts, char *anchorname,
- char *rulesetname)
+ char *rulesetname, struct pfr_buffer *t)
{
/* never called, no anchors inside anchors, but we need the stub */
fprintf(stderr, "load anchor not supported from authpf\n");
return (1);
}
+void
+pfctl_print_title(char *title)
+{
+}
OpenPOWER on IntegriCloud