On Tue, Sep 30, 2003 at 10:41:00PM +1000, herbert wrote: > > Here is the patch to strengthen the policy check as was discussed > previously. The idea is to require the tunnel mode SAs in the > security path to match the tunnels specified by the template, > including the optional ones. The optional tunnels are allowed to > match xfrm tunnels. I've modified it slightly to allow incoming packets to skip optional tunnel templates. Please let me know if you have any remaining objections. -- Debian GNU/Linux 3.0 is out! ( http://www.debian.org/ ) Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Index: kernel-source-2.5/net/xfrm/xfrm_policy.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/xfrm/xfrm_policy.c,v retrieving revision 1.1.1.8 diff -u -r1.1.1.8 xfrm_policy.c --- kernel-source-2.5/net/xfrm/xfrm_policy.c 9 Aug 2003 08:12:04 -0000 1.1.1.8 +++ kernel-source-2.5/net/xfrm/xfrm_policy.c 18 Oct 2003 01:34:21 -0000 @@ -853,6 +858,8 @@ 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 +869,23 @@ } 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 +938,35 @@ 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; }