]> git.hungrycats.org Git - linux/commitdiff
[IPSEC]: Strengthen policy checks.
authorHerbert Xu <herbert@gondor.apana.org.au>
Thu, 23 Oct 2003 21:57:11 +0000 (14:57 -0700)
committerDavid S. Miller <davem@nuts.ninka.net>
Thu, 23 Oct 2003 21:57:11 +0000 (14:57 -0700)
net/xfrm/xfrm_policy.c

index b12fb6b5b33750a18a1409fe31cd02f991395b4b..f2bfc4c2e0728a7d348de5d534a7ec2c40ba60b4 100644 (file)
@@ -853,6 +853,8 @@ static inline int
 xfrm_state_ok(struct xfrm_tmpl *tmpl, struct xfrm_state *x, 
              unsigned short family)
 {
+       if (xfrm_state_kern(x))
+               return tmpl->optional && !xfrm_state_addr_cmp(tmpl, x, family);
        return  x->id.proto == tmpl->id.proto &&
                (x->id.spi == tmpl->id.spi || !tmpl->id.spi) &&
                (x->props.reqid == tmpl->reqid || !tmpl->reqid) &&
@@ -862,14 +864,23 @@ xfrm_state_ok(struct xfrm_tmpl *tmpl, struct xfrm_state *x,
 }
 
 static inline int
-xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int idx,
+xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int start,
               unsigned short family)
 {
+       int idx = start;
+
+       if (tmpl->optional) {
+               if (!tmpl->mode)
+                       return start;
+       } else
+               start = -1;
        for (; idx < sp->len; idx++) {
                if (xfrm_state_ok(tmpl, sp->x[idx].xvec, family))
                        return ++idx;
+               if (sp->x[idx].xvec->props.mode)
+                       break;
        }
-       return -1;
+       return start;
 }
 
 static int
@@ -922,32 +933,35 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
                                        xfrm_policy_lookup);
 
        if (!pol)
-               return 1;
+               return !skb->sp;
 
        pol->curlft.use_time = (unsigned long)xtime.tv_sec;
 
        if (pol->action == XFRM_POLICY_ALLOW) {
-               if (pol->xfrm_nr != 0) {
-                       struct sec_path *sp;
-                       static struct sec_path dummy;
-                       int i, k;
-
-                       if ((sp = skb->sp) == NULL)
-                               sp = &dummy;
-
-                       /* For each tmpl search corresponding xfrm.
-                        * Order is _important_. Later we will implement
-                        * some barriers, but at the moment barriers
-                        * are implied between each two transformations.
-                        */
-                       for (i = pol->xfrm_nr-1, k = 0; i >= 0; i--) {
-                               if (pol->xfrm_vec[i].optional)
-                                       continue;
-                               k = xfrm_policy_ok(pol->xfrm_vec+i, sp, k, family);
-                               if (k < 0)
-                                       goto reject;
-                       }
+               struct sec_path *sp;
+               static struct sec_path dummy;
+               int i, k;
+
+               if ((sp = skb->sp) == NULL)
+                       sp = &dummy;
+
+               /* For each tunnel xfrm, find the first matching tmpl.
+                * For each tmpl before that, find corresponding xfrm.
+                * Order is _important_. Later we will implement
+                * some barriers, but at the moment barriers
+                * are implied between each two transformations.
+                */
+               for (i = pol->xfrm_nr-1, k = 0; i >= 0; i--) {
+                       k = xfrm_policy_ok(pol->xfrm_vec+i, sp, k, family);
+                       if (k < 0)
+                               goto reject;
+               }
+
+               for (; k < sp->len; k++) {
+                       if (sp->x[k].xvec->props.mode)
+                               goto reject;
                }
+
                xfrm_pol_put(pol);
                return 1;
        }