diff options
author | Ryan Thomas McBride <mcbride@cvs.openbsd.org> | 2003-12-08 07:07:37 +0000 |
---|---|---|
committer | Ryan Thomas McBride <mcbride@cvs.openbsd.org> | 2003-12-08 07:07:37 +0000 |
commit | 27292f48c8c9693222952f5d014f0d3c9de14aaf (patch) | |
tree | 84013f176779794382e2f9736cc46c1c1938ea09 /sys/net | |
parent | 4a8b62f7a064527262e43e34aa5e8de6796ba36c (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.c | 46 |
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); |