|
Subject: [PATCH 2/4] IPSEC input hooks Newsgroups: gmane.comp.security.firewalls.netfilter.devel Date: 2005-02-17 19:11:35 GMT (3 years, 41 weeks, 2 days, 14 hours and 43 minutes ago)
The updated ipsec-02-input-hooks.diff
--- linux-2.6.11-rc4/net/xfrm/xfrm_input.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/xfrm/xfrm_input.c 2005-02-17 18:15:38.728620048 +0100
@@ -31,6 +31,9 @@
if (!sp)
return NULL;
+#ifdef CONFIG_NETFILTER
+ sp->decap_done = 0;
+#endif
sp->len = 0;
if (src) {
int i;
--- linux-2.6.11-rc4/net/ipv4/xfrm4_tunnel.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/xfrm4_tunnel.c 2005-02-17 18:15:39.770461664 +0100
@@ -115,6 +115,7 @@
.handler = ipip_rcv,
.err_handler = ipip_err,
.no_policy = 1,
+ .xfrm_prot = 1,
};
static int __init ipip_init(void)
--- linux-2.6.11-rc4/net/ipv4/ipip.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/ipip.c 2005-02-17 18:15:40.466355872 +0100
@@ -476,6 +476,11 @@
read_lock(&ipip_lock);
if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
+ /* IPIP packets decapsulated by IPsec missed netfilter hooks */
+ if (nf_xfrm_local_done(skb, NULL)) {
+ nf_rcv_postxfrm_local(skb);
+ return 0;
+ }
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
read_unlock(&ipip_lock);
kfree_skb(skb);
--- linux-2.6.11-rc4/net/ipv4/ipcomp.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/ipcomp.c 2005-02-17 18:15:41.048267408 +0100
@@ -503,6 +503,7 @@
.handler = xfrm4_rcv,
.err_handler = ipcomp4_err,
.no_policy = 1,
+ .xfrm_prot = 1,
};
static int __init ipcomp4_init(void)
--- linux-2.6.11-rc4/net/ipv4/ip_input.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/ip_input.c 2005-02-17 18:15:41.773157208 +0100
@@ -224,6 +224,12 @@
resubmit:
hash = protocol & (MAX_INET_PROTOS - 1);
raw_sk = sk_head(&raw_v4_htable[hash]);
+ ipprot = rcu_dereference(inet_protos[hash]);
+
+ if (nf_xfrm_local_done(skb, ipprot)) {
+ nf_rcv_postxfrm_local(skb);
+ goto out;
+ }
/* If there maybe a raw socket we must check - if not we
* don't care less
@@ -231,7 +237,7 @@
if (raw_sk)
raw_v4_input(skb, skb->nh.iph, hash);
- if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) {
+ if (ipprot != NULL) {
int ret;
if (!ipprot->no_policy &&
@@ -278,8 +284,8 @@
return 0;
}
- return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
- ip_local_deliver_finish);
+ return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
+ ip_local_deliver_finish, nf_hook_input_cond(skb));
}
static inline int ip_rcv_finish(struct sk_buff *skb)
@@ -296,6 +302,9 @@
goto drop;
}
+ if (nf_xfrm_nonlocal_done(skb))
+ return nf_rcv_postxfrm_nonlocal(skb);
+
#ifdef CONFIG_NET_CLS_ROUTE
if (skb->dst->tclassid) {
struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
@@ -417,8 +426,8 @@
}
}
- return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
- ip_rcv_finish);
+ return NF_HOOK_COND(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
+ ip_rcv_finish, nf_hook_input_cond(skb));
inhdr_error:
IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
--- linux-2.6.11-rc4/net/ipv4/esp4.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/esp4.c 2005-02-17 18:16:06.954329088 +0100
@@ -474,6 +474,7 @@
.handler = xfrm4_rcv,
.err_handler = esp4_err,
.no_policy = 1,
+ .xfrm_prot = 1,
};
static int __init esp4_init(void)
--- linux-2.6.11-rc4/net/ipv4/ah4.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/ah4.c 2005-02-17 18:16:06.951329544 +0100
@@ -308,6 +308,7 @@
.handler = xfrm4_rcv,
.err_handler = ah4_err,
.no_policy = 1,
+ .xfrm_prot = 1,
};
static int __init ah4_init(void)
--- linux-2.6.11-rc4/net/core/netfilter.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/core/netfilter.c 2005-02-17 18:20:27.782685304 +0100
@@ -27,6 +27,7 @@
#include <linux/icmp.h>
#include <net/sock.h>
#include <net/route.h>
+#include <net/xfrm.h>
#include <linux/ip.h>
/* In this code, we can be waiting indefinitely for userspace to
@@ -675,6 +676,27 @@
}
EXPORT_SYMBOL(ip_route_me_harder);
+#ifdef CONFIG_XFRM
+inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
+{
+ skb->sp->decap_done = 1;
+ dst_release(skb->dst);
+ skb->dst = NULL;
+ nf_reset(skb);
+ return netif_rx(skb);
+}
+
+int nf_rcv_postxfrm_local(struct sk_buff *skb)
+{
+ __skb_push(skb, skb->data - skb->nh.raw);
+ /* Fix header len and checksum if last xfrm was transport mode */
+ if (!skb->sp->x[skb->sp->len - 1].xvec->props.mode) {
+ skb->nh.iph->tot_len = htons(skb->len);
+ ip_send_check(skb->nh.iph);
+ }
+ return nf_rcv_postxfrm_nonlocal(skb);
+}
+
int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
{
struct sk_buff *nskb;
@@ -840,3 +862,4 @@
EXPORT_SYMBOL(nf_unregister_hook);
EXPORT_SYMBOL(nf_unregister_queue_handler);
EXPORT_SYMBOL(nf_unregister_sockopt);
+EXPORT_SYMBOL(nf_rcv_postxfrm_local);
--- linux-2.6.11-rc4/include/net/xfrm.h 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/include/net/xfrm.h 2005-02-17 18:21:47.995491104 +0100
@@ -531,6 +531,9 @@
{
atomic_t refcnt;
int len;
+#ifdef CONFIG_NETFILTER
+ int decap_done;
+#endif
struct sec_decap_state x[XFRM_MAX_DEPTH];
};
--- linux-2.6.11-rc4/include/net/protocol.h 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/include/net/protocol.h 2005-02-17 18:22:05.457836424 +0100
@@ -38,6 +38,7 @@
int (*handler)(struct sk_buff *skb);
void (*err_handler)(struct sk_buff *skb, u32 info);
int no_policy;
+ int xfrm_prot;
};
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
--- linux-2.6.11-rc4/include/linux/netfilter_ipv4.h 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/include/linux/netfilter_ipv4.h 2005-02-17 18:22:30.163080656 +0100
@@ -7,6 +7,8 @@
#include <linux/config.h>
#include <linux/netfilter.h>
+#include <linux/netdevice.h>
+#include <net/protocol.h>
/* IP Cache bits. */
/* Src IP address. */
@@ -85,6 +87,58 @@
Returns true or false. */
extern int skb_ip_make_writable(struct sk_buff **pskb,
unsigned int writable_len);
+
+#if defined(CONFIG_XFRM) && defined(CONFIG_NETFILTER)
+#include <net/route.h>
+#include <net/xfrm.h>
+
+static inline int nf_hook_input_cond(struct sk_buff *skb)
+{
+ return !skb->sp || skb->sp->decap_done;
+}
+
+static inline int
+nf_xfrm_local_done(struct sk_buff *skb, struct net_protocol *ipprot)
+{
+ return skb->sp && !skb->sp->decap_done
+ && (!ipprot || !ipprot->xfrm_prot);
+}
+
+static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
+{
+ return skb->sp && !skb->sp->decap_done
+ && !(((struct rtable *)skb->dst)->rt_flags & RTCF_LOCAL);
+}
+
+extern int nf_rcv_postxfrm_local(struct sk_buff *skb);
+extern int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb);
+#else /* CONFIG_XFRM */
+static inline int nf_hook_input_cond(struct sk_buff *skb)
+{
+ return 1;
+}
+
+static inline int
+nf_xfrm_local_done(struct sk_buff *skb, struct net_protocol *ipprot)
+{
+ return 0;
+}
+
+static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
+{
+ return 0;
+}
+
+static inline int nf_rcv_postxfrm_local(struct sk_buff *skb)
+{
+ return 0;
+}
+
+static inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
+{
+ return 0;
+}
+#endif /* CONFIG_XFRM */
#endif /*__KERNEL__*/
#endif /*__LINUX_IP_NETFILTER_H*/
|
|
|