aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_state.c
diff options
context:
space:
mode:
authorPaul Moore <paul.moore@hp.com>2007-12-21 17:58:11 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:00:01 -0500
commitafeb14b49098ba7a51c96e083a4105a0301f94c4 (patch)
tree2675451596adbea8aa261704c356d074136abbbd /net/xfrm/xfrm_state.c
parentdfd4f0ae2e111e2b93c295938c0e64ebbb69ae6e (diff)
[XFRM]: RFC4303 compliant auditing
This patch adds a number of new IPsec audit events to meet the auditing requirements of RFC4303. This includes audit hooks for the following events: * Could not find a valid SA [sections 2.1, 3.4.2] . xfrm_audit_state_notfound() . xfrm_audit_state_notfound_simple() * Sequence number overflow [section 3.3.3] . xfrm_audit_state_replay_overflow() * Replayed packet [section 3.4.3] . xfrm_audit_state_replay() * Integrity check failure [sections 3.4.4.1, 3.4.4.2] . xfrm_audit_state_icvfail() While RFC4304 deals only with ESP most of the changes in this patch apply to IPsec in general, i.e. both AH and ESP. The one case, integrity check failure, where ESP specific code had to be modified the same was done to the AH code for the sake of consistency. Signed-off-by: Paul Moore <paul.moore@hp.com> Acked-by: James Morris <jmorris@namei.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/xfrm/xfrm_state.c')
-rw-r--r--net/xfrm/xfrm_state.c153
1 files changed, 137 insertions, 16 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 9e57378c51d..6bf876c866d 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -61,6 +61,13 @@ static unsigned int xfrm_state_genid;
61static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family); 61static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family);
62static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); 62static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
63 63
64#ifdef CONFIG_AUDITSYSCALL
65static void xfrm_audit_state_replay(struct xfrm_state *x,
66 struct sk_buff *skb, __be32 net_seq);
67#else
68#define xfrm_audit_state_replay(x, s, sq) do { ; } while (0)
69#endif /* CONFIG_AUDITSYSCALL */
70
64static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr, 71static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr,
65 xfrm_address_t *saddr, 72 xfrm_address_t *saddr,
66 u32 reqid, 73 u32 reqid,
@@ -1609,13 +1616,14 @@ static void xfrm_replay_timer_handler(unsigned long data)
1609 spin_unlock(&x->lock); 1616 spin_unlock(&x->lock);
1610} 1617}
1611 1618
1612int xfrm_replay_check(struct xfrm_state *x, __be32 net_seq) 1619int xfrm_replay_check(struct xfrm_state *x,
1620 struct sk_buff *skb, __be32 net_seq)
1613{ 1621{
1614 u32 diff; 1622 u32 diff;
1615 u32 seq = ntohl(net_seq); 1623 u32 seq = ntohl(net_seq);
1616 1624
1617 if (unlikely(seq == 0)) 1625 if (unlikely(seq == 0))
1618 return -EINVAL; 1626 goto err;
1619 1627
1620 if (likely(seq > x->replay.seq)) 1628 if (likely(seq > x->replay.seq))
1621 return 0; 1629 return 0;
@@ -1624,14 +1632,18 @@ int xfrm_replay_check(struct xfrm_state *x, __be32 net_seq)
1624 if (diff >= min_t(unsigned int, x->props.replay_window, 1632 if (diff >= min_t(unsigned int, x->props.replay_window,
1625 sizeof(x->replay.bitmap) * 8)) { 1633 sizeof(x->replay.bitmap) * 8)) {
1626 x->stats.replay_window++; 1634 x->stats.replay_window++;
1627 return -EINVAL; 1635 goto err;
1628 } 1636 }
1629 1637
1630 if (x->replay.bitmap & (1U << diff)) { 1638 if (x->replay.bitmap & (1U << diff)) {
1631 x->stats.replay++; 1639 x->stats.replay++;
1632 return -EINVAL; 1640 goto err;
1633 } 1641 }
1634 return 0; 1642 return 0;
1643
1644err:
1645 xfrm_audit_state_replay(x, skb, net_seq);
1646 return -EINVAL;
1635} 1647}
1636EXPORT_SYMBOL(xfrm_replay_check); 1648EXPORT_SYMBOL(xfrm_replay_check);
1637 1649
@@ -1996,8 +2008,8 @@ void __init xfrm_state_init(void)
1996} 2008}
1997 2009
1998#ifdef CONFIG_AUDITSYSCALL 2010#ifdef CONFIG_AUDITSYSCALL
1999static inline void xfrm_audit_common_stateinfo(struct xfrm_state *x, 2011static inline void xfrm_audit_helper_sainfo(struct xfrm_state *x,
2000 struct audit_buffer *audit_buf) 2012 struct audit_buffer *audit_buf)
2001{ 2013{
2002 struct xfrm_sec_ctx *ctx = x->security; 2014 struct xfrm_sec_ctx *ctx = x->security;
2003 u32 spi = ntohl(x->id.spi); 2015 u32 spi = ntohl(x->id.spi);
@@ -2024,18 +2036,45 @@ static inline void xfrm_audit_common_stateinfo(struct xfrm_state *x,
2024 audit_log_format(audit_buf, " spi=%u(0x%x)", spi, spi); 2036 audit_log_format(audit_buf, " spi=%u(0x%x)", spi, spi);
2025} 2037}
2026 2038
2039static inline void xfrm_audit_helper_pktinfo(struct sk_buff *skb, u16 family,
2040 struct audit_buffer *audit_buf)
2041{
2042 struct iphdr *iph4;
2043 struct ipv6hdr *iph6;
2044
2045 switch (family) {
2046 case AF_INET:
2047 iph4 = ip_hdr(skb);
2048 audit_log_format(audit_buf,
2049 " src=" NIPQUAD_FMT " dst=" NIPQUAD_FMT,
2050 NIPQUAD(iph4->saddr),
2051 NIPQUAD(iph4->daddr));
2052 break;
2053 case AF_INET6:
2054 iph6 = ipv6_hdr(skb);
2055 audit_log_format(audit_buf,
2056 " src=" NIP6_FMT " dst=" NIP6_FMT
2057 " flowlbl=0x%x%x%x",
2058 NIP6(iph6->saddr),
2059 NIP6(iph6->daddr),
2060 iph6->flow_lbl[0] & 0x0f,
2061 iph6->flow_lbl[1],
2062 iph6->flow_lbl[2]);
2063 break;
2064 }
2065}
2066
2027void xfrm_audit_state_add(struct xfrm_state *x, int result, 2067void xfrm_audit_state_add(struct xfrm_state *x, int result,
2028 u32 auid, u32 secid) 2068 u32 auid, u32 secid)
2029{ 2069{
2030 struct audit_buffer *audit_buf; 2070 struct audit_buffer *audit_buf;
2031 2071
2032 if (audit_enabled == 0) 2072 audit_buf = xfrm_audit_start("SAD-add");
2033 return;
2034 audit_buf = xfrm_audit_start(auid, secid);
2035 if (audit_buf == NULL) 2073 if (audit_buf == NULL)
2036 return; 2074 return;
2037 audit_log_format(audit_buf, " op=SAD-add res=%u", result); 2075 xfrm_audit_helper_usrinfo(auid, secid, audit_buf);
2038 xfrm_audit_common_stateinfo(x, audit_buf); 2076 xfrm_audit_helper_sainfo(x, audit_buf);
2077 audit_log_format(audit_buf, " res=%u", result);
2039 audit_log_end(audit_buf); 2078 audit_log_end(audit_buf);
2040} 2079}
2041EXPORT_SYMBOL_GPL(xfrm_audit_state_add); 2080EXPORT_SYMBOL_GPL(xfrm_audit_state_add);
@@ -2045,14 +2084,96 @@ void xfrm_audit_state_delete(struct xfrm_state *x, int result,
2045{ 2084{
2046 struct audit_buffer *audit_buf; 2085 struct audit_buffer *audit_buf;
2047 2086
2048 if (audit_enabled == 0) 2087 audit_buf = xfrm_audit_start("SAD-delete");
2049 return;
2050 audit_buf = xfrm_audit_start(auid, secid);
2051 if (audit_buf == NULL) 2088 if (audit_buf == NULL)
2052 return; 2089 return;
2053 audit_log_format(audit_buf, " op=SAD-delete res=%u", result); 2090 xfrm_audit_helper_usrinfo(auid, secid, audit_buf);
2054 xfrm_audit_common_stateinfo(x, audit_buf); 2091 xfrm_audit_helper_sainfo(x, audit_buf);
2092 audit_log_format(audit_buf, " res=%u", result);
2055 audit_log_end(audit_buf); 2093 audit_log_end(audit_buf);
2056} 2094}
2057EXPORT_SYMBOL_GPL(xfrm_audit_state_delete); 2095EXPORT_SYMBOL_GPL(xfrm_audit_state_delete);
2096
2097void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
2098 struct sk_buff *skb)
2099{
2100 struct audit_buffer *audit_buf;
2101 u32 spi;
2102
2103 audit_buf = xfrm_audit_start("SA-replay-overflow");
2104 if (audit_buf == NULL)
2105 return;
2106 xfrm_audit_helper_pktinfo(skb, x->props.family, audit_buf);
2107 /* don't record the sequence number because it's inherent in this kind
2108 * of audit message */
2109 spi = ntohl(x->id.spi);
2110 audit_log_format(audit_buf, " spi=%u(0x%x)", spi, spi);
2111 audit_log_end(audit_buf);
2112}
2113EXPORT_SYMBOL_GPL(xfrm_audit_state_replay_overflow);
2114
2115static void xfrm_audit_state_replay(struct xfrm_state *x,
2116 struct sk_buff *skb, __be32 net_seq)
2117{
2118 struct audit_buffer *audit_buf;
2119 u32 spi;
2120
2121 audit_buf = xfrm_audit_start("SA-replayed-pkt");
2122 if (audit_buf == NULL)
2123 return;
2124 xfrm_audit_helper_pktinfo(skb, x->props.family, audit_buf);
2125 spi = ntohl(x->id.spi);
2126 audit_log_format(audit_buf, " spi=%u(0x%x) seqno=%u",
2127 spi, spi, ntohl(net_seq));
2128 audit_log_end(audit_buf);
2129}
2130
2131void xfrm_audit_state_notfound_simple(struct sk_buff *skb, u16 family)
2132{
2133 struct audit_buffer *audit_buf;
2134
2135 audit_buf = xfrm_audit_start("SA-notfound");
2136 if (audit_buf == NULL)
2137 return;
2138 xfrm_audit_helper_pktinfo(skb, family, audit_buf);
2139 audit_log_end(audit_buf);
2140}
2141EXPORT_SYMBOL_GPL(xfrm_audit_state_notfound_simple);
2142
2143void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
2144 __be32 net_spi, __be32 net_seq)
2145{
2146 struct audit_buffer *audit_buf;
2147 u32 spi;
2148
2149 audit_buf = xfrm_audit_start("SA-notfound");
2150 if (audit_buf == NULL)
2151 return;
2152 xfrm_audit_helper_pktinfo(skb, family, audit_buf);
2153 spi = ntohl(net_spi);
2154 audit_log_format(audit_buf, " spi=%u(0x%x) seqno=%u",
2155 spi, spi, ntohl(net_seq));
2156 audit_log_end(audit_buf);
2157}
2158EXPORT_SYMBOL_GPL(xfrm_audit_state_notfound);
2159
2160void xfrm_audit_state_icvfail(struct xfrm_state *x,
2161 struct sk_buff *skb, u8 proto)
2162{
2163 struct audit_buffer *audit_buf;
2164 __be32 net_spi;
2165 __be32 net_seq;
2166
2167 audit_buf = xfrm_audit_start("SA-icv-failure");
2168 if (audit_buf == NULL)
2169 return;
2170 xfrm_audit_helper_pktinfo(skb, x->props.family, audit_buf);
2171 if (xfrm_parse_spi(skb, proto, &net_spi, &net_seq) == 0) {
2172 u32 spi = ntohl(net_spi);
2173 audit_log_format(audit_buf, " spi=%u(0x%x) seqno=%u",
2174 spi, spi, ntohl(net_seq));
2175 }
2176 audit_log_end(audit_buf);
2177}
2178EXPORT_SYMBOL_GPL(xfrm_audit_state_icvfail);
2058#endif /* CONFIG_AUDITSYSCALL */ 2179#endif /* CONFIG_AUDITSYSCALL */