Hi, Fixes (of my faults): - logical expressions - skb ( :( ) - skb->cb dropped (not valid on output hook) - fixed header-chain iteration (All test passed with the example packets.)
Regards, kisza -- Andras Kis-Szabo Security Development, Design and Audit -------------------------/ Zorp, NetFilter and IPv6 [EMAIL PROTECTED] /---------------------------------------------->
diff -urN netfilter/userspace/patch-o-matic/base.old/ahesp6.patch.ipv6 netfilter/userspace/patch-o-matic/base/ahesp6.patch.ipv6 --- netfilter/userspace/patch-o-matic/base.old/ahesp6.patch.ipv6 Mon Mar 25 19:41:12 2002 +++ netfilter/userspace/patch-o-matic/base/ahesp6.patch.ipv6 Mon Mar 25 19:45:33 2002 @@ -1,7 +1,7 @@ diff -urN linux/net/ipv6/netfilter/ip6t_ah.c linux.dev/net/ipv6/netfilter/ip6t_ah.c --- linux/net/ipv6/netfilter/ip6t_ah.c Thu Jan 1 01:00:00 1970 +++ linux.dev/net/ipv6/netfilter/ip6t_ah.c Thu Mar 21 21:58:56 2002 -@@ -0,0 +1,121 @@ +@@ -0,0 +1,209 @@ +/* Kernel module to match AH parameters. */ +#include <linux/module.h> +#include <linux/skbuff.h> @@ -18,11 +18,11 @@ +MODULE_DESCRIPTION("IPv6 AH match"); +MODULE_AUTHOR("Andras Kis-Szabo <[EMAIL PROTECTED]>"); + -+/*#if 0*/ ++#if 0 +#define DEBUGP printk -+/*#else ++#else +#define DEBUGP(format, args...) -+#endif*/ ++#endif + +struct ahhdr { + __u8 nexthdr; @@ -31,6 +31,17 @@ + __u32 spi; +}; + ++int ipv6_ext_hdr(u8 nexthdr) ++{ ++ return ( (nexthdr == NEXTHDR_HOP) || ++ (nexthdr == NEXTHDR_ROUTING) || ++ (nexthdr == NEXTHDR_FRAGMENT) || ++ (nexthdr == NEXTHDR_AUTH) || ++ (nexthdr == NEXTHDR_ESP) || ++ (nexthdr == NEXTHDR_NONE) || ++ (nexthdr == NEXTHDR_DEST) ); ++} ++ +/* Returns 1 if the spi is matched by the range, 0 otherwise */ +static inline int +spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert) @@ -53,23 +64,100 @@ + u_int16_t datalen, + int *hotdrop) +{ -+ const struct ip6t_ah *ahinfo = matchinfo; -+ struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb; -+ __u32 hdrlen = 0x0L; + struct ahhdr *ah = NULL; ++ const struct ip6t_ah *ahinfo = matchinfo; ++ unsigned int temp; ++ int len; ++ u8 nexthdr; ++ unsigned int ptr; ++ unsigned int hdrlen = 0; + + /*DEBUGP("IPv6 AH entered\n");*/ -+ if (opt->auth == 0) return 0; ++ /* if (opt->auth == 0) return 0; ++ * It does not filled on output */ ++ ++ /* type of the 1st exthdr */ ++ nexthdr = skb->nh.ipv6h->nexthdr; ++ /* pointer to the 1st exthdr */ ++ ptr = sizeof(struct ipv6hdr); ++ /* available length */ ++ len = skb->len - ptr; ++ temp = 0; ++ ++ while (ipv6_ext_hdr(nexthdr)) { ++ struct ipv6_opt_hdr *hdr; + -+ DEBUGP("IPv6 AH ext hdr found\n"); -+ if (skb_copy_bits(skb, opt->auth, &ah, sizeof(struct ahhdr))) -+ BUG(); ++ DEBUGP("ipv6_ah header iteration \n"); + -+ hdrlen = (ah->hdrlen+2)<<2; ++ /* Is there enough space for the next ext header? */ ++ if (len < (int)sizeof(struct ipv6_opt_hdr)) ++ return 0; ++ /* No more exthdr -> evaluate */ ++ if (nexthdr == NEXTHDR_NONE) { ++ break; ++ } ++ /* ESP -> evaluate */ ++ if (nexthdr == NEXTHDR_ESP) { ++ break; ++ } + -+ DEBUGP("IPv6 AH LEN %u %u\n", hdrlen, ah->hdrlen); -+ DEBUGP("IPv6 AH RES %04X\n", ah->reserved); -+ DEBUGP("IPv6 AH SPI %u\n", ah->spi); ++ hdr=skb->data+ptr; ++ ++ /* Calculate the header length */ ++ if (nexthdr == NEXTHDR_FRAGMENT) { ++ hdrlen = 8; ++ } else if (nexthdr == NEXTHDR_AUTH) ++ hdrlen = (hdr->hdrlen+2)<<2; ++ else ++ hdrlen = ipv6_optlen(hdr); ++ ++ /* AH -> evaluate */ ++ if (nexthdr == NEXTHDR_AUTH) { ++ temp |= MASK_AH; ++ break; ++ } ++ ++ ++ /* set the flag */ ++ switch (nexthdr){ ++ case NEXTHDR_HOP: ++ case NEXTHDR_ROUTING: ++ case NEXTHDR_FRAGMENT: ++ case NEXTHDR_AUTH: ++ case NEXTHDR_DEST: ++ break; ++ default: ++ DEBUGP("ipv6_ah match: unknown nextheader %u\n",nexthdr); ++ return 0; ++ break; ++ } ++ ++ nexthdr = hdr->nexthdr; ++ len -= hdrlen; ++ ptr += hdrlen; ++ } ++ ++ /* AH header not found */ ++ if ( temp != MASK_AH ) return 0; ++ ++ ah=skb->data+ptr; ++ ++ DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen); ++ DEBUGP("RES %04X ", ah->reserved); ++ DEBUGP("SPI %u %08X\n", ntohl(ah->spi), ntohl(ah->spi)); ++ ++ DEBUGP("IPv6 AH spi %02X ", ++ (spi_match(ahinfo->spis[0], ahinfo->spis[1], ++ ntohl(ah->spi), ++ !!(ahinfo->invflags & IP6T_AH_INV_SPI)))); ++ DEBUGP("len %02X %04X %02X ", ++ ahinfo->hdrlen, hdrlen, ++ (!ahinfo->hdrlen || ++ (ahinfo->hdrlen == hdrlen) ^ ++ !!(ahinfo->invflags & IP6T_AH_INV_LEN))); ++ DEBUGP("res %02X %04X %02X\n", ++ ahinfo->hdrres, ah->reserved, ++ !(ahinfo->hdrres && ah->reserved)); + + return (ah != NULL) + && @@ -77,11 +165,11 @@ + ntohl(ah->spi), + !!(ahinfo->invflags & IP6T_AH_INV_SPI))) + && -+ (ahinfo->hdrlen && ++ (!ahinfo->hdrlen || + (ahinfo->hdrlen == hdrlen) ^ + !!(ahinfo->invflags & IP6T_AH_INV_LEN)) + && -+ (ahinfo->hdrres && !(ah->reserved)); ++ !(ahinfo->hdrres && ah->reserved); +} + +/* Called when user tries to insert an entry of this type. */ @@ -126,7 +214,7 @@ diff -urN linux/net/ipv6/netfilter/ip6t_esp.c linux.dev/net/ipv6/netfilter/ip6t_esp.c --- linux/net/ipv6/netfilter/ip6t_esp.c Thu Jan 1 01:00:00 1970 +++ linux.dev/net/ipv6/netfilter/ip6t_esp.c Thu Mar 21 21:59:11 2002 -@@ -0,0 +1,178 @@ +@@ -0,0 +1,177 @@ +/* Kernel module to match ESP parameters. */ +#include <linux/module.h> +#include <linux/skbuff.h> @@ -143,11 +231,11 @@ +MODULE_DESCRIPTION("IPv6 ESP match"); +MODULE_AUTHOR("Andras Kis-Szabo <[EMAIL PROTECTED]>"); + -+/*#if 0*/ ++#if 0 +#define DEBUGP printk -+/*#else ++#else +#define DEBUGP(format, args...) -+#endif*/ ++#endif + +struct esphdr { + __u32 spi; @@ -191,7 +279,7 @@ + unsigned int temp; + int len; + u8 nexthdr; -+ int ptr; ++ unsigned int ptr; + + /* Make sure this isn't an evil packet */ + /*DEBUGP("ipv6_esp entered \n");*/ @@ -199,7 +287,7 @@ + /* type of the 1st exthdr */ + nexthdr = skb->nh.ipv6h->nexthdr; + /* pointer to the 1st exthdr */ -+ ptr = (u8*)(skb->nh.ipv6h+1) - skb->data; ++ ptr = sizeof(struct ipv6hdr); + /* available length */ + len = skb->len - ptr; + temp = 0; @@ -222,8 +310,8 @@ + temp |= MASK_ESP; + break; + } -+ if (skb_copy_bits(skb, ptr, &hdr, sizeof(struct ipv6_opt_hdr))) -+ BUG(); ++ ++ hdr=skb->data+ptr; + + /* Calculate the header length */ + if (nexthdr == NEXTHDR_FRAGMENT) { @@ -255,10 +343,9 @@ + /* ESP header not found */ + if ( temp != MASK_ESP ) return 0; + -+ if (skb_copy_bits(skb, ptr, &esp, sizeof(esp))) -+ BUG(); ++ esp=skb->data+ptr; + -+ DEBUGP("IPv6 ESP SPI %u", esp->spi); ++ DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(esp->spi), ntohl(esp->spi)); + + return (esp != NULL) + && spi_match(espinfo->spis[0], espinfo->spis[1], @@ -308,7 +395,7 @@ diff -urN linux/include/linux/netfilter_ipv6/ip6t_ah.h linux.dev/include/linux/netfilter_ipv6/ip6t_ah.h --- linux/include/linux/netfilter_ipv6/ip6t_ah.h Thu Jan 1 01:00:00 1970 +++ linux.dev/include/linux/netfilter_ipv6/ip6t_ah.h Thu Mar 21 21:12:40 2002 -@@ -0,0 +1,21 @@ +@@ -0,0 +1,30 @@ +#ifndef _IP6T_AH_H +#define _IP6T_AH_H + @@ -328,6 +415,15 @@ +#define IP6T_AH_INV_SPI 0x01 /* Invert the sense of spi. */ +#define IP6T_AH_INV_LEN 0x02 /* Invert the sense of length. */ +#define IP6T_AH_INV_MASK 0x03 /* All possible flags. */ ++ ++#define MASK_HOPOPTS 128 ++#define MASK_DSTOPTS 64 ++#define MASK_ROUTING 32 ++#define MASK_FRAGMENT 16 ++#define MASK_AH 8 ++#define MASK_ESP 4 ++#define MASK_NONE 2 ++#define MASK_PROTO 1 + +#endif /*_IP6T_AH_H*/ diff -urN linux/include/linux/netfilter_ipv6/ip6t_esp.h linux.dev/include/linux/netfilter_ipv6/ip6t_esp.h diff -urN netfilter/userspace/patch-o-matic/base.old/ahesp6.patch.ipv6.help netfilter/userspace/patch-o-matic/base/ahesp6.patch.ipv6.help --- netfilter/userspace/patch-o-matic/base.old/ahesp6.patch.ipv6.help Mon Mar 25 19:41:12 2002 +++ netfilter/userspace/patch-o-matic/base/ahesp6.patch.ipv6.help Mon Mar 25 19:42:03 2002 @@ -1,5 +1,5 @@ Author: Andras Kis-Szabo <[EMAIL PROTECTED]> -Status: Under development, please test it! +Status: It works 4 me! These two match extensions (`ah' and `esp') allow you to match a range of SPIs inside AH or ESP headers of IPv6 packets.