diff options
author | Joy Latten <latten@austin.ibm.com> | 2006-11-27 14:11:54 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-06 23:14:22 -0500 |
commit | 161a09e737f0761ca064ee6a907313402f7a54b6 (patch) | |
tree | 80fdf6dc5de73d810ef0ec811299a5ec3c5ce23e /net/xfrm | |
parent | 95b99a670df31ca5271f503f378e5cac3aee8f5e (diff) |
audit: Add auditing to ipsec
An audit message occurs when an ipsec SA
or ipsec policy is created/deleted.
Signed-off-by: Joy Latten <latten@austin.ibm.com>
Signed-off-by: James Morris <jmorris@namei.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/xfrm')
-rw-r--r-- | net/xfrm/xfrm_policy.c | 120 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 17 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 33 |
3 files changed, 164 insertions, 6 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 4f04222698d9..47c13649bac1 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/cache.h> | 25 | #include <linux/cache.h> |
26 | #include <net/xfrm.h> | 26 | #include <net/xfrm.h> |
27 | #include <net/ip.h> | 27 | #include <net/ip.h> |
28 | #include <linux/audit.h> | ||
28 | 29 | ||
29 | #include "xfrm_hash.h" | 30 | #include "xfrm_hash.h" |
30 | 31 | ||
@@ -804,7 +805,7 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete) | |||
804 | } | 805 | } |
805 | EXPORT_SYMBOL(xfrm_policy_byid); | 806 | EXPORT_SYMBOL(xfrm_policy_byid); |
806 | 807 | ||
807 | void xfrm_policy_flush(u8 type) | 808 | void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info) |
808 | { | 809 | { |
809 | int dir; | 810 | int dir; |
810 | 811 | ||
@@ -824,6 +825,9 @@ void xfrm_policy_flush(u8 type) | |||
824 | hlist_del(&pol->byidx); | 825 | hlist_del(&pol->byidx); |
825 | write_unlock_bh(&xfrm_policy_lock); | 826 | write_unlock_bh(&xfrm_policy_lock); |
826 | 827 | ||
828 | xfrm_audit_log(audit_info->loginuid, audit_info->secid, | ||
829 | AUDIT_MAC_IPSEC_DELSPD, 1, pol, NULL); | ||
830 | |||
827 | xfrm_policy_kill(pol); | 831 | xfrm_policy_kill(pol); |
828 | killed++; | 832 | killed++; |
829 | 833 | ||
@@ -842,6 +846,11 @@ void xfrm_policy_flush(u8 type) | |||
842 | hlist_del(&pol->byidx); | 846 | hlist_del(&pol->byidx); |
843 | write_unlock_bh(&xfrm_policy_lock); | 847 | write_unlock_bh(&xfrm_policy_lock); |
844 | 848 | ||
849 | xfrm_audit_log(audit_info->loginuid, | ||
850 | audit_info->secid, | ||
851 | AUDIT_MAC_IPSEC_DELSPD, 1, | ||
852 | pol, NULL); | ||
853 | |||
845 | xfrm_policy_kill(pol); | 854 | xfrm_policy_kill(pol); |
846 | killed++; | 855 | killed++; |
847 | 856 | ||
@@ -1977,6 +1986,115 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first, | |||
1977 | 1986 | ||
1978 | EXPORT_SYMBOL(xfrm_bundle_ok); | 1987 | EXPORT_SYMBOL(xfrm_bundle_ok); |
1979 | 1988 | ||
1989 | /* Audit addition and deletion of SAs and ipsec policy */ | ||
1990 | |||
1991 | void xfrm_audit_log(uid_t auid, u32 sid, int type, int result, | ||
1992 | struct xfrm_policy *xp, struct xfrm_state *x) | ||
1993 | { | ||
1994 | |||
1995 | char *secctx; | ||
1996 | u32 secctx_len; | ||
1997 | struct xfrm_sec_ctx *sctx = NULL; | ||
1998 | struct audit_buffer *audit_buf; | ||
1999 | int family; | ||
2000 | extern int audit_enabled; | ||
2001 | |||
2002 | if (audit_enabled == 0) | ||
2003 | return; | ||
2004 | |||
2005 | audit_buf = audit_log_start(current->audit_context, GFP_ATOMIC, type); | ||
2006 | if (audit_buf == NULL) | ||
2007 | return; | ||
2008 | |||
2009 | switch(type) { | ||
2010 | case AUDIT_MAC_IPSEC_ADDSA: | ||
2011 | audit_log_format(audit_buf, "SAD add: auid=%u", auid); | ||
2012 | break; | ||
2013 | case AUDIT_MAC_IPSEC_DELSA: | ||
2014 | audit_log_format(audit_buf, "SAD delete: auid=%u", auid); | ||
2015 | break; | ||
2016 | case AUDIT_MAC_IPSEC_ADDSPD: | ||
2017 | audit_log_format(audit_buf, "SPD add: auid=%u", auid); | ||
2018 | break; | ||
2019 | case AUDIT_MAC_IPSEC_DELSPD: | ||
2020 | audit_log_format(audit_buf, "SPD delete: auid=%u", auid); | ||
2021 | break; | ||
2022 | default: | ||
2023 | return; | ||
2024 | } | ||
2025 | |||
2026 | if (sid != 0 && | ||
2027 | security_secid_to_secctx(sid, &secctx, &secctx_len) == 0) | ||
2028 | audit_log_format(audit_buf, " subj=%s", secctx); | ||
2029 | else | ||
2030 | audit_log_task_context(audit_buf); | ||
2031 | |||
2032 | if (xp) { | ||
2033 | family = xp->selector.family; | ||
2034 | if (xp->security) | ||
2035 | sctx = xp->security; | ||
2036 | } else { | ||
2037 | family = x->props.family; | ||
2038 | if (x->security) | ||
2039 | sctx = x->security; | ||
2040 | } | ||
2041 | |||
2042 | if (sctx) | ||
2043 | audit_log_format(audit_buf, | ||
2044 | " sec_alg=%u sec_doi=%u sec_obj=%s", | ||
2045 | sctx->ctx_alg, sctx->ctx_doi, sctx->ctx_str); | ||
2046 | |||
2047 | switch(family) { | ||
2048 | case AF_INET: | ||
2049 | { | ||
2050 | struct in_addr saddr, daddr; | ||
2051 | if (xp) { | ||
2052 | saddr.s_addr = xp->selector.saddr.a4; | ||
2053 | daddr.s_addr = xp->selector.daddr.a4; | ||
2054 | } else { | ||
2055 | saddr.s_addr = x->props.saddr.a4; | ||
2056 | daddr.s_addr = x->id.daddr.a4; | ||
2057 | } | ||
2058 | audit_log_format(audit_buf, | ||
2059 | " src=%u.%u.%u.%u dst=%u.%u.%u.%u", | ||
2060 | NIPQUAD(saddr), NIPQUAD(daddr)); | ||
2061 | } | ||
2062 | break; | ||
2063 | case AF_INET6: | ||
2064 | { | ||
2065 | struct in6_addr saddr6, daddr6; | ||
2066 | if (xp) { | ||
2067 | memcpy(&saddr6, xp->selector.saddr.a6, | ||
2068 | sizeof(struct in6_addr)); | ||
2069 | memcpy(&daddr6, xp->selector.daddr.a6, | ||
2070 | sizeof(struct in6_addr)); | ||
2071 | } else { | ||
2072 | memcpy(&saddr6, x->props.saddr.a6, | ||
2073 | sizeof(struct in6_addr)); | ||
2074 | memcpy(&daddr6, x->id.daddr.a6, | ||
2075 | sizeof(struct in6_addr)); | ||
2076 | } | ||
2077 | audit_log_format(audit_buf, | ||
2078 | " src=" NIP6_FMT "dst=" NIP6_FMT, | ||
2079 | NIP6(saddr6), NIP6(daddr6)); | ||
2080 | } | ||
2081 | break; | ||
2082 | } | ||
2083 | |||
2084 | if (x) | ||
2085 | audit_log_format(audit_buf, " spi=%lu(0x%lx) protocol=%s", | ||
2086 | (unsigned long)ntohl(x->id.spi), | ||
2087 | (unsigned long)ntohl(x->id.spi), | ||
2088 | x->id.proto == IPPROTO_AH ? "AH" : | ||
2089 | (x->id.proto == IPPROTO_ESP ? | ||
2090 | "ESP" : "IPCOMP")); | ||
2091 | |||
2092 | audit_log_format(audit_buf, " res=%u", result); | ||
2093 | audit_log_end(audit_buf); | ||
2094 | } | ||
2095 | |||
2096 | EXPORT_SYMBOL(xfrm_audit_log); | ||
2097 | |||
1980 | int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) | 2098 | int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) |
1981 | { | 2099 | { |
1982 | int err = 0; | 2100 | int err = 0; |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index a14c88bf17f0..d5d3a6f1f609 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/cache.h> | 21 | #include <linux/cache.h> |
22 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
23 | #include <linux/audit.h> | ||
23 | 24 | ||
24 | #include "xfrm_hash.h" | 25 | #include "xfrm_hash.h" |
25 | 26 | ||
@@ -238,6 +239,7 @@ static void xfrm_timer_handler(unsigned long data) | |||
238 | unsigned long now = (unsigned long)xtime.tv_sec; | 239 | unsigned long now = (unsigned long)xtime.tv_sec; |
239 | long next = LONG_MAX; | 240 | long next = LONG_MAX; |
240 | int warn = 0; | 241 | int warn = 0; |
242 | int err = 0; | ||
241 | 243 | ||
242 | spin_lock(&x->lock); | 244 | spin_lock(&x->lock); |
243 | if (x->km.state == XFRM_STATE_DEAD) | 245 | if (x->km.state == XFRM_STATE_DEAD) |
@@ -295,9 +297,14 @@ expired: | |||
295 | next = 2; | 297 | next = 2; |
296 | goto resched; | 298 | goto resched; |
297 | } | 299 | } |
298 | if (!__xfrm_state_delete(x) && x->id.spi) | 300 | |
301 | err = __xfrm_state_delete(x); | ||
302 | if (!err && x->id.spi) | ||
299 | km_state_expired(x, 1, 0); | 303 | km_state_expired(x, 1, 0); |
300 | 304 | ||
305 | xfrm_audit_log(audit_get_loginuid(current->audit_context), 0, | ||
306 | AUDIT_MAC_IPSEC_DELSA, err ? 0 : 1, NULL, x); | ||
307 | |||
301 | out: | 308 | out: |
302 | spin_unlock(&x->lock); | 309 | spin_unlock(&x->lock); |
303 | } | 310 | } |
@@ -384,9 +391,10 @@ int xfrm_state_delete(struct xfrm_state *x) | |||
384 | } | 391 | } |
385 | EXPORT_SYMBOL(xfrm_state_delete); | 392 | EXPORT_SYMBOL(xfrm_state_delete); |
386 | 393 | ||
387 | void xfrm_state_flush(u8 proto) | 394 | void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info) |
388 | { | 395 | { |
389 | int i; | 396 | int i; |
397 | int err = 0; | ||
390 | 398 | ||
391 | spin_lock_bh(&xfrm_state_lock); | 399 | spin_lock_bh(&xfrm_state_lock); |
392 | for (i = 0; i <= xfrm_state_hmask; i++) { | 400 | for (i = 0; i <= xfrm_state_hmask; i++) { |
@@ -400,6 +408,11 @@ restart: | |||
400 | spin_unlock_bh(&xfrm_state_lock); | 408 | spin_unlock_bh(&xfrm_state_lock); |
401 | 409 | ||
402 | xfrm_state_delete(x); | 410 | xfrm_state_delete(x); |
411 | err = xfrm_state_delete(x); | ||
412 | xfrm_audit_log(audit_info->loginuid, | ||
413 | audit_info->secid, | ||
414 | AUDIT_MAC_IPSEC_DELSA, | ||
415 | err ? 0 : 1, NULL, x); | ||
403 | xfrm_state_put(x); | 416 | xfrm_state_put(x); |
404 | 417 | ||
405 | spin_lock_bh(&xfrm_state_lock); | 418 | spin_lock_bh(&xfrm_state_lock); |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 311205ffa775..e5372b11fc8f 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 31 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
32 | #include <linux/in6.h> | 32 | #include <linux/in6.h> |
33 | #endif | 33 | #endif |
34 | #include <linux/audit.h> | ||
34 | 35 | ||
35 | static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type) | 36 | static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type) |
36 | { | 37 | { |
@@ -454,6 +455,9 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) | |||
454 | else | 455 | else |
455 | err = xfrm_state_update(x); | 456 | err = xfrm_state_update(x); |
456 | 457 | ||
458 | xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid, | ||
459 | AUDIT_MAC_IPSEC_ADDSA, err ? 0 : 1, NULL, x); | ||
460 | |||
457 | if (err < 0) { | 461 | if (err < 0) { |
458 | x->km.state = XFRM_STATE_DEAD; | 462 | x->km.state = XFRM_STATE_DEAD; |
459 | __xfrm_state_put(x); | 463 | __xfrm_state_put(x); |
@@ -523,6 +527,10 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) | |||
523 | } | 527 | } |
524 | 528 | ||
525 | err = xfrm_state_delete(x); | 529 | err = xfrm_state_delete(x); |
530 | |||
531 | xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid, | ||
532 | AUDIT_MAC_IPSEC_DELSA, err ? 0 : 1, NULL, x); | ||
533 | |||
526 | if (err < 0) | 534 | if (err < 0) |
527 | goto out; | 535 | goto out; |
528 | 536 | ||
@@ -1030,6 +1038,9 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr | |||
1030 | * a type XFRM_MSG_UPDPOLICY - JHS */ | 1038 | * a type XFRM_MSG_UPDPOLICY - JHS */ |
1031 | excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY; | 1039 | excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY; |
1032 | err = xfrm_policy_insert(p->dir, xp, excl); | 1040 | err = xfrm_policy_insert(p->dir, xp, excl); |
1041 | xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid, | ||
1042 | AUDIT_MAC_IPSEC_DELSPD, err ? 0 : 1, xp, NULL); | ||
1043 | |||
1033 | if (err) { | 1044 | if (err) { |
1034 | security_xfrm_policy_free(xp); | 1045 | security_xfrm_policy_free(xp); |
1035 | kfree(xp); | 1046 | kfree(xp); |
@@ -1257,6 +1268,10 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr | |||
1257 | xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, delete); | 1268 | xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, delete); |
1258 | security_xfrm_policy_free(&tmp); | 1269 | security_xfrm_policy_free(&tmp); |
1259 | } | 1270 | } |
1271 | if (delete) | ||
1272 | xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid, | ||
1273 | AUDIT_MAC_IPSEC_DELSPD, (xp) ? 1 : 0, xp, NULL); | ||
1274 | |||
1260 | if (xp == NULL) | 1275 | if (xp == NULL) |
1261 | return -ENOENT; | 1276 | return -ENOENT; |
1262 | 1277 | ||
@@ -1291,8 +1306,11 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma | |||
1291 | { | 1306 | { |
1292 | struct km_event c; | 1307 | struct km_event c; |
1293 | struct xfrm_usersa_flush *p = NLMSG_DATA(nlh); | 1308 | struct xfrm_usersa_flush *p = NLMSG_DATA(nlh); |
1309 | struct xfrm_audit audit_info; | ||
1294 | 1310 | ||
1295 | xfrm_state_flush(p->proto); | 1311 | audit_info.loginuid = NETLINK_CB(skb).loginuid; |
1312 | audit_info.secid = NETLINK_CB(skb).sid; | ||
1313 | xfrm_state_flush(p->proto, &audit_info); | ||
1296 | c.data.proto = p->proto; | 1314 | c.data.proto = p->proto; |
1297 | c.event = nlh->nlmsg_type; | 1315 | c.event = nlh->nlmsg_type; |
1298 | c.seq = nlh->nlmsg_seq; | 1316 | c.seq = nlh->nlmsg_seq; |
@@ -1442,12 +1460,15 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **x | |||
1442 | struct km_event c; | 1460 | struct km_event c; |
1443 | u8 type = XFRM_POLICY_TYPE_MAIN; | 1461 | u8 type = XFRM_POLICY_TYPE_MAIN; |
1444 | int err; | 1462 | int err; |
1463 | struct xfrm_audit audit_info; | ||
1445 | 1464 | ||
1446 | err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma); | 1465 | err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma); |
1447 | if (err) | 1466 | if (err) |
1448 | return err; | 1467 | return err; |
1449 | 1468 | ||
1450 | xfrm_policy_flush(type); | 1469 | audit_info.loginuid = NETLINK_CB(skb).loginuid; |
1470 | audit_info.secid = NETLINK_CB(skb).sid; | ||
1471 | xfrm_policy_flush(type, &audit_info); | ||
1451 | c.data.type = type; | 1472 | c.data.type = type; |
1452 | c.event = nlh->nlmsg_type; | 1473 | c.event = nlh->nlmsg_type; |
1453 | c.seq = nlh->nlmsg_seq; | 1474 | c.seq = nlh->nlmsg_seq; |
@@ -1502,6 +1523,9 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void * | |||
1502 | err = 0; | 1523 | err = 0; |
1503 | if (up->hard) { | 1524 | if (up->hard) { |
1504 | xfrm_policy_delete(xp, p->dir); | 1525 | xfrm_policy_delete(xp, p->dir); |
1526 | xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid, | ||
1527 | AUDIT_MAC_IPSEC_DELSPD, 1, xp, NULL); | ||
1528 | |||
1505 | } else { | 1529 | } else { |
1506 | // reset the timers here? | 1530 | // reset the timers here? |
1507 | printk("Dont know what to do with soft policy expire\n"); | 1531 | printk("Dont know what to do with soft policy expire\n"); |
@@ -1533,8 +1557,11 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void ** | |||
1533 | goto out; | 1557 | goto out; |
1534 | km_state_expired(x, ue->hard, current->pid); | 1558 | km_state_expired(x, ue->hard, current->pid); |
1535 | 1559 | ||
1536 | if (ue->hard) | 1560 | if (ue->hard) { |
1537 | __xfrm_state_delete(x); | 1561 | __xfrm_state_delete(x); |
1562 | xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid, | ||
1563 | AUDIT_MAC_IPSEC_DELSA, 1, NULL, x); | ||
1564 | } | ||
1538 | out: | 1565 | out: |
1539 | spin_unlock_bh(&x->lock); | 1566 | spin_unlock_bh(&x->lock); |
1540 | xfrm_state_put(x); | 1567 | xfrm_state_put(x); |