More IP option length validation.

Includes the following revisions from KAME (two of these were actually
committed previously but the CVS revisions weren't documented):

1.40      kame/kame/sys/netinet6/ah_core.c (committed in previous rev)
1.41      kame/kame/sys/netinet6/ah_core.c
1.28      kame/kame/sys/netinet6/ah_output.c (committed in previous rev)
1.29      kame/kame/sys/netinet6/ah_output.c
1.30      kame/kame/sys/netinet6/ah_output.c
1.129     kame/kame/sys/netinet6/nd6.c
1.130     kame/kame/sys/netinet6/nd6.c
1.24      kame/kame/sys/netinet6/dest6.c
1.25      kame/kame/sys/netinet6/dest6.c

Obtained from:	KAME
This commit is contained in:
Kris Kennaway 2001-02-26 03:41:13 +00:00
parent c33f8c177f
commit 19391949fb
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=73059
4 changed files with 41 additions and 21 deletions

View File

@ -788,6 +788,8 @@ ah4_calccksum(m, ahdat, len, algo, sav)
i = sizeof(struct ip);
while (i < hlen) {
if (i + IPOPT_OPTVAL >= hlen) {
ipseclog((LOG_ERR, "ah4_calccksum: "
"invalid IP option\n"));
error = EINVAL;
goto fail;
}
@ -796,6 +798,10 @@ ah4_calccksum(m, ahdat, len, algo, sav)
i + IPOPT_OLEN < hlen)
;
else {
ipseclog((LOG_ERR,
"ah4_calccksum: invalid IP option "
"(type=%02x)\n",
p[i + IPOPT_OPTVAL]));
error = EINVAL;
goto fail;
}
@ -813,14 +819,19 @@ ah4_calccksum(m, ahdat, len, algo, sav)
case 0x94: /* Router alert */
case 0x95: /* RFC1770 */
l = p[i + IPOPT_OLEN];
if (l < 2)
goto invalopt;
skip = 0;
break;
default:
l = p[i + IPOPT_OLEN];
if (l < 2)
goto invalopt;
skip = 1;
break;
}
if (l <= 0 || hlen - i < l) {
if (l < 1 || hlen - i < l) {
invalopt:
ipseclog((LOG_ERR,
"ah4_calccksum: invalid IP option "
"(type=%02x len=%02x)\n",

View File

@ -539,8 +539,8 @@ ah4_finaldst(m)
break;
case IPOPT_LSRR:
case IPOPT_SSRR:
if (q[i + IPOPT_OLEN] <= 0
|| optlen - i < q[i + IPOPT_OLEN]) {
if (q[i + IPOPT_OLEN] < 2 + sizeof(struct in_addr) ||
optlen - i < q[i + IPOPT_OLEN]) {
ipseclog((LOG_ERR,
"ip_finaldst: invalid IP option "
"(code=%02x len=%02x)\n",
@ -550,8 +550,8 @@ ah4_finaldst(m)
i += q[i + IPOPT_OLEN] - sizeof(struct in_addr);
return (struct in_addr *)(q + i);
default:
if (q[i + IPOPT_OLEN] <= 0
|| optlen - i < q[i + IPOPT_OLEN]) {
if (q[i + IPOPT_OLEN] < 2 ||
optlen - i < q[i + IPOPT_OLEN]) {
ipseclog((LOG_ERR,
"ip_finaldst: invalid IP option "
"(code=%02x len=%02x)\n",

View File

@ -89,22 +89,20 @@ dest6_input(mp, offp, proto)
/* search header for all options. */
for (optlen = 0; dstoptlen > 0; dstoptlen -= optlen, opt += optlen) {
switch(*opt) {
case IP6OPT_PAD1:
optlen = 1;
break;
case IP6OPT_PADN:
if (dstoptlen < IP6OPT_MINLEN) {
ip6stat.ip6s_toosmall++;
goto bad;
}
optlen = *(opt + 1) + 2;
break;
if (*opt != IP6OPT_PAD1 &&
(dstoptlen < IP6OPT_MINLEN || *(opt + 1) + 2 > dstoptlen)) {
ip6stat.ip6s_toosmall++;
goto bad;
}
switch (*opt) {
case IP6OPT_PAD1:
optlen = 1;
break;
case IP6OPT_PADN:
optlen = *(opt + 1) + 2;
break;
default: /* unknown option */
if (dstoptlen < IP6OPT_MINLEN) {
ip6stat.ip6s_toosmall++;
goto bad;
}
if ((optlen = ip6_unknown_opt(opt, m,
opt-mtod(m, u_int8_t *))) == -1)
return(IPPROTO_DONE);

View File

@ -274,6 +274,12 @@ nd6_option(ndopts)
nd_opt = ndopts->nd_opts_search;
/* make sure nd_opt_len is inside the buffer */
if ((caddr_t)&nd_opt->nd_opt_len >= (caddr_t)ndopts->nd_opts_last) {
bzero(ndopts, sizeof(*ndopts));
return NULL;
}
olen = nd_opt->nd_opt_len << 3;
if (olen == 0) {
/*
@ -285,7 +291,12 @@ nd6_option(ndopts)
}
ndopts->nd_opts_search = (struct nd_opt_hdr *)((caddr_t)nd_opt + olen);
if (!(ndopts->nd_opts_search < ndopts->nd_opts_last)) {
if (ndopts->nd_opts_search > ndopts->nd_opts_last) {
/* option overruns the end of buffer, invalid */
bzero(ndopts, sizeof(*ndopts));
return NULL;
} else if (ndopts->nd_opts_search == ndopts->nd_opts_last) {
/* reached the end of options chain */
ndopts->nd_opts_done = 1;
ndopts->nd_opts_search = NULL;
}