Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 16 Sep 2004 04:08:50 -0000
From:      Max Laier <max@love2party.net>
To:        pf4freebsd@freelists.org
Cc:        tech@openbsd.org
Subject:   [pf4freebsd] Comments? FreeBSD-only change (group -> groupmember)
Message-ID:  <200407210045.06274.max@love2party.net>

next in thread | raw e-mail | index | archive | help

--Boundary-03=_yBa/Av/NmIRhcls
Content-Type: multipart/mixed;
  boundary="Boundary-01=_qBa/AZ1dqu+XxAS"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

--Boundary-01=_qBa/AZ1dqu+XxAS
Content-Type: text/plain;
  charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Hi,

during a discussion about ipfw's user/group filter capabilities and it's=20
implementation with Christian S.J. Peron we found that pf only applies grou=
p=20
filter based on the primary (effective) group of the user, rather than taki=
ng=20
all member groups into account. This is a major backdraw for multiuser=20
environments, where you want to allow/deny a large group of people certain=
=20
network access, say:
    pass out on $dmz from $dmz to $cvsserver port 22 group cvsuser keep sta=
te

In FreeBSD it's quite easy to change the behavior to check for member-group=
s=20
(see attachment). For OpenBSD, however, this is not possible as it does not=
=20
store/reference full credentials on the socket pcb, but rather just copies=
=20
uid/gid and euid/egid.

A patch to the same effect as what was done in FreeBSD:
http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/kern/uipc_socket.c.diff?r1=3D=
1.59&r2=3D1.62
would change the situation and provide a couple of benefits (imo):
Not only would it allow pf to check groupmembership, but it will also give=
=20
*everything* that has to enforce per-socket permissions access to the *full=
*=20
credentials. Moreover, it will simply provide any future extensions of the=
=20
credentials to everything that might be interested.

I plan to commit the "fix" for FreeBSD unless you tell me, that you (=3Dthe=
=20
=46reeBSD pf-userbase) prefer to old behavior (and give me valid reasons wh=
y).=20
Other than that I am willing to help with the conversion in OpenBSD if you=
=20
(=3Dthe OpenBSD users/developers^W^W^WTheo) are interested.

Looking forward to your feedback. Thanks.

=46inal note on the patch: You will see a new cache variable "jid" that see=
ms to=20
have no sense or application. This will turn into a "jailed" filter, which=
=20
allows you to check whether a given socket was created inside a jail or not=
=20
This is FreeBSD-specific as well and will follow in a bit.

=2D-=20
/"\  Best regards,			| mlaier@freebsd.org
\ /  Max Laier				| ICQ #67774661
 X   http://pf4freebsd.love2party.net/	| mlaier@EFnet
/ \  ASCII Ribbon Campaign		| Against HTML Mail and News

--Boundary-01=_qBa/AZ1dqu+XxAS
Content-Type: text/x-diff;
  charset="us-ascii";
  name="pf_groupmember.patch"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="pf_groupmember.patch"

Index: pf.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /usr/store/mlaier/fcvs/src/sys/contrib/pf/net/pf.c,v
retrieving revision 1.15
diff -u -r1.15 pf.c
=2D-- pf.c	18 Jul 2004 14:25:48 -0000	1.15
+++ pf.c	20 Jul 2004 22:07:46 -0000
@@ -64,6 +64,8 @@
 #ifdef __FreeBSD__
 #include <sys/sysctl.h>
 #include <sys/endian.h>
+#include <sys/ucred.h>
+#include <sys/jail.h>
 #else
 #include <sys/pool.h>
 #endif
@@ -230,8 +232,13 @@
 			    struct ifnet *, struct pf_state *);
 void			 pf_route6(struct mbuf **, struct pf_rule *, int,
 			    struct ifnet *, struct pf_state *);
+#ifdef __FreeBSD__
+int			 pf_socket_lookup(struct xucred *, int *, int,
+			    struct pf_pdesc *);
+#else
 int			 pf_socket_lookup(uid_t *, gid_t *,
 			    int, struct pf_pdesc *);
+#endif
 u_int8_t		 pf_get_wscale(struct mbuf *, int, u_int16_t,
 			    sa_family_t);
 u_int16_t		 pf_get_mss(struct mbuf *, int, u_int16_t,
@@ -1703,9 +1710,40 @@
 	return (pf_match(op, a1, a2, p));
 }
=20
+#ifdef __FreeBSD__
 int
=2Dpf_match_uid(u_int8_t op, uid_t a1, uid_t a2, uid_t u)
+pf_match_uid(u_int8_t op, uid_t a1, uid_t a2, struct xucred *cr)
 {
+	if (cr->cr_uid =3D=3D UID_MAX && op !=3D PF_OP_EQ && op !=3D PF_OP_NE)
+		return (0);
+	return (pf_match(op, a1, a2, cr->cr_uid));
+}
+
+int
+pf_match_gid(u_int8_t op, gid_t a1, gid_t a2, struct xucred *cr)
+{
+	gid_t *gp, *lg =3D &(cr->cr_groups[cr->cr_ngroups]);
+
+	switch (op) {
+	case PF_OP_EQ:
+	case PF_OP_NE:
+		for (gp =3D cr->cr_groups; gp < lg; gp++)
+			if (a1 =3D=3D *gp)
+				return ((op =3D=3D PF_OP_NE)? 0 : 1);
+		break;
+	default:
+		if (cr->cr_gid =3D=3D GID_MAX)
+			return (0);
+		for (gp =3D cr->cr_groups; gp < lg; gp++)
+			if (!pf_match(op, a1, a2, *gp))
+				return (0); /* all groups must be in range */
+	}
+
+	return (1);
+}
+#else
+int
+pf_match_uid(u_int8_t op, uid_t a1, uid_t a2, uid_t u)
 	if (u =3D=3D UID_MAX && op !=3D PF_OP_EQ && op !=3D PF_OP_NE)
 		return (0);
 	return (pf_match(op, a1, a2, u));
@@ -1718,6 +1756,7 @@
 		return (0);
 	return (pf_match(op, a1, a2, g));
 }
+#endif
=20
 struct pf_tag *
 pf_get_tag(struct mbuf *m)
@@ -2367,7 +2406,12 @@
 }
=20
 int
+#ifdef __FreeBSD__
+pf_socket_lookup(struct xucred *cred_cache, int *jid, int direction,
+    struct pf_pdesc *pd)
+#else
 pf_socket_lookup(uid_t *uid, gid_t *gid, int direction, struct pf_pdesc *p=
d)
+#endif
 {
 	struct pf_addr		*saddr, *daddr;
 	u_int16_t		 sport, dport;
@@ -2378,8 +2422,15 @@
 #endif
 	struct inpcb		*inp;
=20
+#ifdef __FreeBSD__
+	cred_cache->cr_uid =3D UID_MAX;
+	cred_cache->cr_gid =3D GID_MAX;
+	cred_cache->cr_ngroups =3D 1;
+	*jid =3D 0;
+#else
 	*uid =3D UID_MAX;
 	*gid =3D GID_MAX;
+#endif
 	switch (pd->proto) {
 	case IPPROTO_TCP:
 		sport =3D pd->hdr.tcp->th_sport;
@@ -2468,8 +2519,9 @@
 	}
 #ifdef __FreeBSD__
 	INP_LOCK(inp);
=2D	*uid =3D inp->inp_socket->so_cred->cr_uid;
=2D	*gid =3D inp->inp_socket->so_cred->cr_groups[0];
+	if (jailed(inp->inp_socket->so_cred))
+		*jid =3D inp->inp_socket->so_cred->cr_prison->pr_id;
+	cru2x(inp->inp_socket->so_cred, cred_cache);
 	INP_UNLOCK(inp);
 	INP_INFO_RUNLOCK(pi);
 #else
@@ -2662,8 +2714,13 @@
 	u_int16_t		 bport, nport =3D 0;
 	sa_family_t		 af =3D pd->af;
 	int			 lookup =3D -1;
+#ifdef __FreeBSD__
+	struct xucred		 cred_cache;
+	int			 jid;
+#else
 	uid_t			 uid;
 	gid_t			 gid;
+#endif
 	struct pf_rule		*r, *a =3D NULL;
 	struct pf_ruleset	*ruleset =3D NULL;
 	struct pf_src_node	*nsn =3D NULL;
@@ -2733,14 +2790,26 @@
 		else if ((r->flagset & th->th_flags) !=3D r->flags)
 			r =3D TAILQ_NEXT(r, entries);
 		else if (r->uid.op && (lookup !=3D -1 || (lookup =3D
+#ifdef __FreeBSD__
+		    pf_socket_lookup(&cred_cache, &jid, direction, pd), 1))
+		    && !pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1],
+		    &cred_cache))
+#else
 		    pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
 		    !pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1],
 		    uid))
+#endif
 			r =3D TAILQ_NEXT(r, entries);
 		else if (r->gid.op && (lookup !=3D -1 || (lookup =3D
+#ifdef __FreeBSD__
+		    pf_socket_lookup(&cred_cache, &jid, direction, pd), 1))
+		    && !pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
+		    &cred_cache))
+#else
 		    pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
 		    !pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
 		    gid))
+#endif
 			r =3D TAILQ_NEXT(r, entries);
 		else if (r->match_tag && !pf_match_tag(m, r, nr, pftag, &tag))
 			r =3D TAILQ_NEXT(r, entries);
@@ -3022,8 +3091,13 @@
 	u_int16_t		 bport, nport =3D 0;
 	sa_family_t		 af =3D pd->af;
 	int			 lookup =3D -1;
+#ifdef __FreeBSD__
+	struct xucred		 cred_cache;
+	int			 jid;
+#else
 	uid_t			 uid;
 	gid_t			 gid;
+#endif
 	struct pf_rule		*r, *a =3D NULL;
 	struct pf_ruleset	*ruleset =3D NULL;
 	struct pf_src_node	*nsn =3D NULL;
@@ -3090,14 +3164,26 @@
 		else if (r->rule_flag & PFRULE_FRAGMENT)
 			r =3D TAILQ_NEXT(r, entries);
 		else if (r->uid.op && (lookup !=3D -1 || (lookup =3D
+#ifdef __FreeBSD__
+		    pf_socket_lookup(&cred_cache, &jid, direction, pd), 1))
+		    && !pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1],
+		    &cred_cache))
+#else
 		    pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
 		    !pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1],
 		    uid))
+#endif
 			r =3D TAILQ_NEXT(r, entries);
 		else if (r->gid.op && (lookup !=3D -1 || (lookup =3D
+#ifdef __FreeBSD__
+		    pf_socket_lookup(&cred_cache, &jid, direction, pd), 1))
+		    && !pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
+		    &cred_cache))
+#else
 		    pf_socket_lookup(&uid, &gid, direction, pd), 1)) &&
 		    !pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
 		    gid))
+#endif
 			r =3D TAILQ_NEXT(r, entries);
 		else if (r->match_tag && !pf_match_tag(m, r, nr, pftag, &tag))
 			r =3D TAILQ_NEXT(r, entries);
Index: pfvar.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /usr/store/mlaier/fcvs/src/sys/contrib/pf/net/pfvar.h,v
retrieving revision 1.7
diff -u -r1.7 pfvar.h
=2D-- pfvar.h	22 Jun 2004 20:13:25 -0000	1.7
+++ pfvar.h	19 Jul 2004 00:56:59 -0000
@@ -58,6 +58,8 @@
 	struct sockaddr_in	sin;
 	struct sockaddr_in6	sin6;
 };
+
+struct xucred;
 #endif
=20
 #include <netinet/tcp_fsm.h>
@@ -1470,8 +1472,13 @@
 	    struct pf_addr *, sa_family_t);
 int	pf_match(u_int8_t, u_int32_t, u_int32_t, u_int32_t);
 int	pf_match_port(u_int8_t, u_int16_t, u_int16_t, u_int16_t);
+#ifdef __FreeBSD__
+int	pf_match_uid(u_int8_t, uid_t, uid_t, struct xucred *);
+int	pf_match_gid(u_int8_t, gid_t, gid_t, struct xucred *);
+#else
 int	pf_match_uid(u_int8_t, uid_t, uid_t, uid_t);
 int	pf_match_gid(u_int8_t, gid_t, gid_t, gid_t);
+#endif
=20
 void	pf_normalize_init(void);
 int	pf_normalize_ip(struct mbuf **, int, struct pfi_kif *, u_short *);

--Boundary-01=_qBa/AZ1dqu+XxAS--

--Boundary-03=_yBa/Av/NmIRhcls
Content-Type: application/pgp-signature
Content-Description: signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (FreeBSD)

iD8DBQBA/aByXyyEoT62BG0RAuKRAJ9iQKwlrRRtl8pj3NlJmlhz2z1KVgCfa9p4
bDl5Gt009rjImO0b9c+fUiY=
=H9EW
-----END PGP SIGNATURE-----

--Boundary-03=_yBa/Av/NmIRhcls--




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200407210045.06274.max>