summaryrefslogtreecommitdiff
path: root/net/key
diff options
context:
space:
mode:
authorAlexey Kuznetsov <kuznet@ms2.inr.ac.ru>2002-11-04 15:18:11 -0800
committerDavid S. Miller <davem@nuts.ninka.net>2002-11-04 15:18:11 -0800
commitfefd92463dfde738bce403acf35ff05cac4dc6a0 (patch)
treee46506bd7109d08aff73b401528566af3ea7b973 /net/key
parentb9346730a75d99030d15d041c2c4719780361f9f (diff)
[IPSEC]: Bug fixes and updates.
- Implement IP_IPSEC_POLICY setsockopt - Rework input policy checks to use it - dst->child destruction is repaired - Fix tunnel mode IP header building.
Diffstat (limited to 'net/key')
-rw-r--r--net/key/af_key.c103
1 files changed, 64 insertions, 39 deletions
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 4eee93ea6e91..0a953121af2a 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1080,38 +1080,6 @@ static int pfkey_acquire(struct sock *sk, struct sk_buff *skb, struct sadb_msg *
}
-static int pfkey_update(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
-{
- struct sk_buff *resp_skb;
- int err;
-
- if (!ext_hdrs[SADB_EXT_SA-1] ||
- !present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
- ext_hdrs[SADB_EXT_ADDRESS_DST-1]))
- return -EINVAL;
-
- if (hdr->sadb_msg_satype == SADB_SATYPE_ESP &&
- !ext_hdrs[SADB_EXT_KEY_ENCRYPT-1])
- return -EINVAL;
-
- if (hdr->sadb_msg_satype == SADB_SATYPE_AH &&
- !ext_hdrs[SADB_EXT_KEY_AUTH-1])
- return -EINVAL;
-
- if (!!ext_hdrs[SADB_EXT_LIFETIME_HARD-1] !=
- !!ext_hdrs[SADB_EXT_LIFETIME_SOFT-1])
- return -EINVAL;
-
- /* XXX Implement XXX */
- resp_skb = NULL;
- err = -EOPNOTSUPP;
-
- if (!err)
- pfkey_broadcast(resp_skb, GFP_KERNEL, BROADCAST_ONE, sk);
-
- return err;
-}
-
static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
{
struct sk_buff *out_skb;
@@ -1125,7 +1093,7 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
/* XXX there is race condition */
x1 = pfkey_xfrm_state_lookup(hdr, ext_hdrs);
- if (x1 != NULL) {
+ if (x1 && hdr->sadb_msg_type == SADB_ADD) {
x->km.state = XFRM_STATE_DEAD;
xfrm_state_put(x);
xfrm_state_put(x1);
@@ -1134,6 +1102,11 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
xfrm_state_insert(x);
+ if (x1 && hdr->sadb_msg_type != SADB_ADD) {
+ xfrm_state_delete(x1);
+ xfrm_state_put(x1);
+ }
+
out_skb = pfkey_xfrm_state2msg(x, 0, 3);
if (IS_ERR(out_skb))
return PTR_ERR(out_skb); /* XXX Should we return 0 here ? */
@@ -1166,7 +1139,6 @@ static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
return -ESRCH;
xfrm_state_delete(x);
-
xfrm_state_put(x);
pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL,
@@ -1382,7 +1354,7 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
struct sockaddr_in *addr;
if (xp->xfrm_nr >= XFRM_MAX_DEPTH)
- return -EINVAL;
+ return -ELOOP;
if (rq->sadb_x_ipsecrequest_mode == 0)
return -EINVAL;
@@ -1408,7 +1380,7 @@ parse_ipsecrequests(struct xfrm_policy *xp, struct sadb_x_policy *pol)
int len = pol->sadb_x_policy_len*8 - sizeof(struct sadb_x_policy);
struct sadb_x_ipsecrequest *rq = (void*)(pol+1);
- while (len > sizeof(struct sadb_x_ipsecrequest)) {
+ while (len >= sizeof(struct sadb_x_ipsecrequest)) {
if ((err = parse_ipsecrequest(xp, rq)) < 0)
return err;
len -= rq->sadb_x_ipsecrequest_len;
@@ -1647,7 +1619,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, sk);
return 0;
- out:
+out:
kfree(xp);
return err;
}
@@ -1823,7 +1795,7 @@ typedef int (*pfkey_handler)(struct sock *sk, struct sk_buff *skb,
static pfkey_handler pfkey_funcs[SADB_MAX + 1] = {
[SADB_RESERVED] = pfkey_reserved,
[SADB_GETSPI] = pfkey_getspi,
- [SADB_UPDATE] = pfkey_update,
+ [SADB_UPDATE] = pfkey_add,
[SADB_ADD] = pfkey_add,
[SADB_DELETE] = pfkey_delete,
[SADB_GET] = pfkey_get,
@@ -2084,6 +2056,58 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct
return 0;
}
+static struct xfrm_policy *pfkey_compile_policy(int opt, u8 *data, int len, int *dir)
+{
+ struct xfrm_policy *xp;
+ struct sadb_x_policy *pol = (struct sadb_x_policy*)data;
+
+ if (opt != IP_IPSEC_POLICY) {
+ *dir = -EOPNOTSUPP;
+ return NULL;
+ }
+
+ *dir = -EINVAL;
+
+ if (len < sizeof(struct sadb_x_policy) ||
+ pol->sadb_x_policy_len*8 > len ||
+ pol->sadb_x_policy_type > IPSEC_POLICY_BYPASS ||
+ (!pol->sadb_x_policy_dir || pol->sadb_x_policy_dir > IPSEC_DIR_OUTBOUND))
+ return NULL;
+
+ xp = xfrm_policy_alloc();
+ if (xp == NULL) {
+ *dir = -ENOBUFS;
+ return NULL;
+ }
+
+ xp->index = pol->sadb_x_policy_id;
+ xp->action = (pol->sadb_x_policy_type == IPSEC_POLICY_DISCARD ?
+ XFRM_POLICY_BLOCK : XFRM_POLICY_ALLOW);
+
+ xp->curlft.add_time = (unsigned long)xtime.tv_sec;
+ xp->curlft.use_time = (unsigned long)xtime.tv_sec;
+ xp->lft.soft_byte_limit = -1;
+ xp->lft.hard_byte_limit = -1;
+ xp->lft.soft_packet_limit = -1;
+ xp->lft.hard_packet_limit = -1;
+ xp->lft.soft_add_expires_seconds = -1;
+ xp->lft.hard_add_expires_seconds = -1;
+ xp->lft.soft_use_expires_seconds = -1;
+ xp->lft.hard_use_expires_seconds = -1;
+
+ xp->xfrm_nr = 0;
+ if (pol->sadb_x_policy_type == IPSEC_POLICY_IPSEC &&
+ (*dir = parse_ipsecrequests(xp, pol)) < 0)
+ goto out;
+
+ *dir = pol->sadb_x_policy_dir-1;
+ return xp;
+
+out:
+ kfree(xp);
+ return NULL;
+}
+
static int pfkey_sendmsg(struct kiocb *kiocb,
struct socket *sock, struct msghdr *msg, int len,
struct scm_cookie *scm)
@@ -2246,7 +2270,8 @@ static struct xfrm_mgr pfkeyv2_mgr =
{
.id = "pfkeyv2",
.notify = pfkey_send_notify,
- .acquire = pfkey_send_acquire
+ .acquire = pfkey_send_acquire,
+ .compile_policy = pfkey_compile_policy,
};
static void __exit ipsec_pfkey_exit(void)