summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorRyan Thomas McBride <mcbride@cvs.openbsd.org>2003-12-08 07:07:37 +0000
committerRyan Thomas McBride <mcbride@cvs.openbsd.org>2003-12-08 07:07:37 +0000
commit27292f48c8c9693222952f5d014f0d3c9de14aaf (patch)
tree84013f176779794382e2f9736cc46c1c1938ea09 /sys/net
parent4a8b62f7a064527262e43e34aa5e8de6796ba36c (diff)
Mbuf tag tcp and udp packets which are translated to localhost, and
use the the presence of this tag to reverse the match order in in{6}_pcblookup_listen(). Some daemons (such as portmap) do a double bind, binding to both * and localhost in order to differentiate local from non-local connections, and potentially granting more privilege to local ones. This change ensures that redirected connections to localhost do not appear local to such a daemon. Bulk of changes from dhartmei@, some changes markus@ ok dhartmei@ deraadt@
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/pf.c46
1 files changed, 43 insertions, 3 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 95765175c08..57bc51437dc 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.404 2003/11/28 01:06:59 mcbride Exp $ */
+/* $OpenBSD: pf.c,v 1.405 2003/12/08 07:07:35 mcbride Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -204,6 +204,7 @@ int pf_check_proto_cksum(struct mbuf *, int, int,
u_int8_t, sa_family_t);
int pf_addr_wrap_neq(struct pf_addr_wrap *,
struct pf_addr_wrap *);
+static int pf_add_mbuf_tag(struct mbuf *, u_int);
struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] =
@@ -2001,7 +2002,7 @@ pf_socket_lookup(uid_t *uid, gid_t *gid, int direction, struct pf_pdesc *pd)
case AF_INET:
inp = in_pcbhashlookup(tb, saddr->v4, sport, daddr->v4, dport);
if (inp == NULL) {
- inp = in_pcblookup_listen(tb, daddr->v4, dport);
+ inp = in_pcblookup_listen(tb, daddr->v4, dport, 0);
if (inp == NULL)
return (0);
}
@@ -2011,7 +2012,7 @@ pf_socket_lookup(uid_t *uid, gid_t *gid, int direction, struct pf_pdesc *pd)
inp = in6_pcbhashlookup(tb, &saddr->v6, sport, &daddr->v6,
dport);
if (inp == NULL) {
- inp = in6_pcblookup_listen(tb, &daddr->v6, dport);
+ inp = in6_pcblookup_listen(tb, &daddr->v6, dport, 0);
if (inp == NULL)
return (0);
}
@@ -4829,6 +4830,20 @@ pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p, sa_family_t a
return (0);
}
+static int
+pf_add_mbuf_tag(struct mbuf *m, u_int tag)
+{
+ struct m_tag *mtag;
+
+ if (m_tag_find(m, tag, NULL) != NULL)
+ return (0);
+ mtag = m_tag_get(tag, 0, M_NOWAIT);
+ if (mtag == NULL)
+ return (1);
+ m_tag_prepend(m, mtag);
+ return (0);
+}
+
#ifdef INET
int
pf_test(int dir, struct ifnet *ifp, struct mbuf **m0)
@@ -5016,6 +5031,21 @@ done:
}
#endif
+ /*
+ * connections redirected to loopback should not match sockets
+ * bound specifically to loopback due to security implications,
+ * see tcp_input() and in_pcblookup_listen().
+ */
+ if (dir == PF_IN && action == PF_PASS && (pd.proto == IPPROTO_TCP ||
+ pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
+ (s->nat_rule.ptr->action == PF_RDR ||
+ s->nat_rule.ptr->action == PF_BINAT) &&
+ (ntohl(pd.dst->v4.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET &&
+ pf_add_mbuf_tag(m, PACKET_TAG_PF_TRANSLATE_LOCALHOST)) {
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_MEMORY);
+ }
+
if (log)
PFLOG_PACKET(ifp, h, m, AF_INET, dir, reason, r, a, ruleset);
@@ -5271,6 +5301,16 @@ done:
}
#endif
+ if (dir == PF_IN && action == PF_PASS && (pd.proto == IPPROTO_TCP ||
+ pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
+ (s->nat_rule.ptr->action == PF_RDR ||
+ s->nat_rule.ptr->action == PF_BINAT) &&
+ IN6_IS_ADDR_LOOPBACK(&pd.dst->v6) &&
+ pf_add_mbuf_tag(m, PACKET_TAG_PF_TRANSLATE_LOCALHOST)) {
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_MEMORY);
+ }
+
if (log)
PFLOG_PACKET(ifp, h, m, AF_INET6, dir, reason, r, a, ruleset);