diff options
Diffstat (limited to 'sys/netinet6/ah_output.c')
-rw-r--r-- | sys/netinet6/ah_output.c | 117 |
1 files changed, 72 insertions, 45 deletions
diff --git a/sys/netinet6/ah_output.c b/sys/netinet6/ah_output.c index c33dfe8..477c589 100644 --- a/sys/netinet6/ah_output.c +++ b/sys/netinet6/ah_output.c @@ -1,3 +1,6 @@ +/* $FreeBSD$ */ +/* $KAME: ah_output.c,v 1.22 2000/07/03 13:23:28 itojun Exp $ */ + /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. @@ -25,18 +28,14 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ /* * RFC1826/2402 authentication header. */ +#include "opt_inet.h" #include "opt_inet6.h" -#include "opt_ipsec.h" - -#define ahdprintf(x) printf x #include <sys/param.h> #include <sys/systm.h> @@ -57,27 +56,23 @@ #include <netinet/in_systm.h> #include <netinet/ip.h> #include <netinet/in_var.h> -#include <netinet/in_pcb.h> #ifdef INET6 -#include <netinet6/ip6.h> +#include <netinet/ip6.h> #include <netinet6/ip6_var.h> -#include <netinet6/icmp6.h> +#include <netinet/icmp6.h> #endif #include <netinet6/ipsec.h> -#include <netinet6/ah.h> #ifdef INET6 #include <netinet6/ipsec6.h> +#endif +#include <netinet6/ah.h> +#ifdef INET6 #include <netinet6/ah6.h> #endif #include <netkey/key.h> #include <netkey/keydb.h> -#ifdef IPSEC_DEBUG -#include <netkey/key_debug.h> -#else -#define KEYDEBUG(lev,arg) -#endif #include <net/net_osdep.h> @@ -103,15 +98,15 @@ ah_hdrsiz(isr) panic("unsupported mode passed to ah_hdrsiz"); if (isr->sav == NULL) - goto contrive; + goto estimate; if (isr->sav->state != SADB_SASTATE_MATURE && isr->sav->state != SADB_SASTATE_DYING) - goto contrive; + goto estimate; /* we need transport mode AH. */ algo = &ah_algorithms[isr->sav->alg_auth]; if (!algo) - goto contrive; + goto estimate; /* * XXX @@ -128,7 +123,7 @@ ah_hdrsiz(isr) return hdrsiz; - contrive: + estimate: /* ASSUMING: * sizeof(struct newah) > sizeof(struct ah). * 16 = (16 + 3) & ~(4 - 1). @@ -166,12 +161,11 @@ ah4_output(m, isr) struct ip *ip; ip = mtod(m, struct ip *); - printf("ah4_output: internal error: " - "sav->replay is null: " - "%x->%x, SPI=%u\n", + ipseclog((LOG_DEBUG, "ah4_output: internal error: " + "sav->replay is null: %x->%x, SPI=%u\n", (u_int32_t)ntohl(ip->ip_src.s_addr), (u_int32_t)ntohl(ip->ip_dst.s_addr), - (u_int32_t)ntohl(sav->spi)); + (u_int32_t)ntohl(sav->spi))); ipsecstat.out_inval++; m_freem(m); return EINVAL; @@ -209,7 +203,8 @@ ah4_output(m, isr) struct mbuf *n; MGET(n, M_DONTWAIT, MT_DATA); if (!n) { - printf("ENOBUFS in ah4_output %d\n", __LINE__); + ipseclog((LOG_DEBUG, "ENOBUFS in ah4_output %d\n", + __LINE__)); m_freem(m); return ENOBUFS; } @@ -249,6 +244,17 @@ ah4_output(m, isr) ahdr->ah_nxt = ip->ip_p; ahdr->ah_reserve = htons(0); ahdr->ah_spi = spi; + if (sav->replay->count == ~0) { + if ((sav->flags & SADB_X_EXT_CYCSEQ) == 0) { + /* XXX Is it noisy ? */ + ipseclog((LOG_WARNING, + "replay counter overflowed. %s\n", + ipsec_logsastr(sav))); + ipsecstat.out_inval++; + m_freem(m); + return EINVAL; + } + } sav->replay->count++; /* * XXX sequence number must not be cycled, if the SA is @@ -265,7 +271,7 @@ ah4_output(m, isr) if (ahlen < (IP_MAXPACKET - ntohs(ip->ip_len))) ip->ip_len = htons(ntohs(ip->ip_len) + ahlen); else { - printf("IPv4 AH output: size exceeds limit\n"); + ipseclog((LOG_ERR, "IPv4 AH output: size exceeds limit\n")); ipsecstat.out_inval++; m_freem(m); return EMSGSIZE; @@ -288,9 +294,11 @@ ah4_output(m, isr) * calcurate the checksum, based on security association * and the algorithm specified. */ - error = ah4_calccksum(m, (caddr_t)ahsumpos, algo, sav); + error = ah4_calccksum(m, (caddr_t)ahsumpos, plen, algo, sav); if (error) { - printf("error after ah4_calccksum, called from ah4_output"); + ipseclog((LOG_ERR, + "error after ah4_calccksum, called from ah4_output")); + m_freem(m); m = NULL; ipsecstat.out_inval++; return error; @@ -314,7 +322,7 @@ ah_hdrlen(sav) { struct ah_algorithm *algo; int plen, ahlen; - + algo = &ah_algorithms[sav->alg_auth]; if (sav->flags & SADB_X_EXT_OLD) { /* RFC 1826 */ @@ -352,7 +360,7 @@ ah6_output(m, nexthdrp, md, isr) struct ip6_hdr *ip6; if (m->m_len < sizeof(struct ip6_hdr)) { - printf("ah6_output: first mbuf too short\n"); + ipseclog((LOG_DEBUG, "ah6_output: first mbuf too short\n")); m_freem(m); return EINVAL; } @@ -364,7 +372,7 @@ ah6_output(m, nexthdrp, md, isr) for (mprev = m; mprev && mprev->m_next != md; mprev = mprev->m_next) ; if (!mprev || mprev->m_next != md) { - printf("ah6_output: md is not in chain\n"); + ipseclog((LOG_DEBUG, "ah6_output: md is not in chain\n")); m_freem(m); return EINVAL; } @@ -389,7 +397,8 @@ ah6_output(m, nexthdrp, md, isr) /* fix plen */ if (m->m_pkthdr.len - sizeof(struct ip6_hdr) > IPV6_MAXPACKET) { - printf("ip6_output: AH with IPv6 jumbogram is not supported\n"); + ipseclog((LOG_ERR, + "ip6_output: AH with IPv6 jumbogram is not supported\n")); m_freem(m); return EINVAL; } @@ -397,11 +406,12 @@ ah6_output(m, nexthdrp, md, isr) ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); if ((sav->flags & SADB_X_EXT_OLD) == 0 && !sav->replay) { - printf("ah6_output: internal error: " + ipseclog((LOG_DEBUG, "ah6_output: internal error: " "sav->replay is null: SPI=%u\n", - (u_int32_t)ntohl(sav->spi)); + (u_int32_t)ntohl(sav->spi))); ipsec6stat.out_inval++; - return 0; /* no change at all */ + m_freem(m); + return EINVAL; } algo = &ah_algorithms[sav->alg_auth]; @@ -431,6 +441,17 @@ ah6_output(m, nexthdrp, md, isr) ahdr->ah_len = (plen >> 2) + 1; /* plus one for seq# */ ahdr->ah_reserve = htons(0); ahdr->ah_spi = spi; + if (sav->replay->count == ~0) { + if ((sav->flags & SADB_X_EXT_CYCSEQ) == 0) { + /* XXX Is it noisy ? */ + ipseclog((LOG_WARNING, + "replay counter overflowed. %s\n", + ipsec_logsastr(sav))); + ipsecstat.out_inval++; + m_freem(m); + return EINVAL; + } + } sav->replay->count++; /* * XXX sequence number must not be cycled, if the SA is @@ -444,13 +465,15 @@ ah6_output(m, nexthdrp, md, isr) * calcurate the checksum, based on security association * and the algorithm specified. */ - error = ah6_calccksum(m, (caddr_t)ahsumpos, algo, sav); - if (error) + error = ah6_calccksum(m, (caddr_t)ahsumpos, plen, algo, sav); + if (error) { ipsec6stat.out_inval++; - else + m_freem(m); + } else { ipsec6stat.out_success++; + key_sa_recordxfer(sav, m); + } ipsec6stat.out_ahhist[sav->alg_auth]++; - key_sa_recordxfer(sav, m); return(error); } @@ -480,7 +503,8 @@ ah4_finaldst(m) hlen = (ip->ip_hl << 2); if (m->m_len < hlen) { - printf("ah4_finaldst: parameter mbuf wrong (not pulled up)\n"); + ipseclog((LOG_DEBUG, + "ah4_finaldst: parameter mbuf wrong (not pulled up)\n")); return NULL; } @@ -489,7 +513,8 @@ ah4_finaldst(m) optlen = hlen - sizeof(struct ip); if (optlen < 0) { - printf("ah4_finaldst: wrong optlen %d\n", optlen); + ipseclog((LOG_DEBUG, "ah4_finaldst: wrong optlen %d\n", + optlen)); return NULL; } @@ -507,9 +532,10 @@ ah4_finaldst(m) case IPOPT_SSRR: if (q[i + IPOPT_OLEN] <= 0 || optlen - i < q[i + IPOPT_OLEN]) { - printf("ip_finaldst: invalid IP option " - "(code=%02x len=%02x)\n", - q[i + IPOPT_OPTVAL], q[i + IPOPT_OLEN]); + ipseclog((LOG_ERR, + "ip_finaldst: invalid IP option " + "(code=%02x len=%02x)\n", + q[i + IPOPT_OPTVAL], q[i + IPOPT_OLEN])); return NULL; } i += q[i + IPOPT_OLEN] - sizeof(struct in_addr); @@ -517,9 +543,10 @@ ah4_finaldst(m) default: if (q[i + IPOPT_OLEN] <= 0 || optlen - i < q[i + IPOPT_OLEN]) { - printf("ip_finaldst: invalid IP option " - "(code=%02x len=%02x)\n", - q[i + IPOPT_OPTVAL], q[i + IPOPT_OLEN]); + ipseclog((LOG_ERR, + "ip_finaldst: invalid IP option " + "(code=%02x len=%02x)\n", + q[i + IPOPT_OPTVAL], q[i + IPOPT_OLEN])); return NULL; } i += q[i + IPOPT_OLEN]; |