Correct IPsec behaviour with a 'use' level in SP but no SA available.

In that case return an continue processing the packet without IPsec.

PR:		121384
MFC after:	5 days
Reported by:	Cyrus Rahman (crahman gmail.com)
Tested by:	Cyrus Rahman (crahman gmail.com) [slightly older version]
This commit is contained in:
Bjoern A. Zeeb 2008-03-14 16:38:11 +00:00
parent a09e09654c
commit 9e3bdede0f
3 changed files with 61 additions and 24 deletions

View File

@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
@ -329,6 +330,17 @@ ip_ipsec_output(struct mbuf **m, struct inpcb *inp, int *flags, int *error,
/* NB: callee frees mbuf */
*error = ipsec4_process_packet(*m, sp->req, *flags, 0);
if (*error == EJUSTRETURN) {
/*
* We had a SP with a level of 'use' and no SA. We
* will just continue to process the packet without
* IPsec processing and return without error.
*/
*error = 0;
ip->ip_len = ntohs(ip->ip_len);
ip->ip_off = ntohs(ip->ip_off);
goto done;
}
/*
* Preserve KAME behaviour: ENOENT can be returned
* when an SA acquire is in progress. Don't propagate

View File

@ -384,7 +384,14 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
error = ipsec6_output_trans(&state, nexthdrp, mprev, sp, flags,
&needipsectun);
m = state.m;
if (error) {
if (error == EJUSTRETURN) {
/*
* We had a SP with a level of 'use' and no SA. We
* will just continue to process the packet without
* IPsec processing.
*/
;
} else if (error) {
/* mbuf is already reclaimed in ipsec6_output_trans. */
m = NULL;
switch (error) {
@ -551,7 +558,14 @@ skip_ipsec2:;
m = state.m;
ro = (struct route_in6 *)state.ro;
dst = (struct sockaddr_in6 *)state.dst;
if (error) {
if (error == EJUSTRETURN) {
/*
* We had a SP with a level of 'use' and no SA. We
* will just continue to process the packet without
* IPsec processing.
*/
;
} else if (error) {
/* mbuf is already reclaimed in ipsec6_output_tunnel. */
m0 = m = NULL;
m = NULL;

View File

@ -286,17 +286,19 @@ ipsec_nextisr(
goto bad;
}
sav = isr->sav;
if (sav == NULL) { /* XXX valid return */
if (sav == NULL) {
IPSEC_ASSERT(ipsec_get_reqlevel(isr) == IPSEC_LEVEL_USE,
("no SA found, but required; level %u",
ipsec_get_reqlevel(isr)));
IPSECREQUEST_UNLOCK(isr);
isr = isr->next;
if (isr == NULL) {
/*XXXstatistic??*/
*error = EINVAL; /*XXX*/
/*
* If isr is NULL, we found a 'use' policy w/o SA.
* Return w/o error and w/o isr so we can drop out
* and continue w/o IPsec processing.
*/
if (isr == NULL)
return isr;
}
IPSECREQUEST_LOCK(isr);
goto again;
}
@ -356,8 +358,11 @@ ipsec4_process_packet(
IPSECREQUEST_LOCK(isr); /* insure SA contents don't change */
isr = ipsec_nextisr(m, isr, AF_INET, &saidx, &error);
if (isr == NULL)
goto bad;
if (isr == NULL) {
if (error != 0)
goto bad;
return EJUSTRETURN;
}
sav = isr->sav;
@ -581,21 +586,24 @@ ipsec6_output_trans(
IPSECREQUEST_LOCK(isr); /* insure SA contents don't change */
isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error);
if (isr == NULL) {
if (error != 0) {
#ifdef notdef
/* XXX should notification be done for all errors ? */
/*
* Notify the fact that the packet is discarded
* to ourselves. I believe this is better than
* just silently discarding. (jinmei@kame.net)
* XXX: should we restrict the error to TCP packets?
* XXX: should we directly notify sockets via
* pfctlinputs?
*/
icmp6_error(m, ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_ADMIN, 0);
m = NULL; /* NB: icmp6_error frees mbuf */
/* XXX should notification be done for all errors ? */
/*
* Notify the fact that the packet is discarded
* to ourselves. I believe this is better than
* just silently discarding. (jinmei@kame.net)
* XXX: should we restrict the error to TCP packets?
* XXX: should we directly notify sockets via
* pfctlinputs?
*/
icmp6_error(m, ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_ADMIN, 0);
m = NULL; /* NB: icmp6_error frees mbuf */
#endif
goto bad;
goto bad;
}
return EJUSTRETURN;
}
error = (*isr->sav->tdb_xform->xf_output)(m, isr, NULL,
@ -712,8 +720,11 @@ ipsec6_output_tunnel(struct ipsec_output_state *state, struct secpolicy *sp, int
IPSECREQUEST_LOCK(isr); /* insure SA contents don't change */
isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error);
if (isr == NULL)
goto bad;
if (isr == NULL) {
if (error != 0)
goto bad;
return EJUSTRETURN;
}
#ifdef DEV_ENC
/* pass the mbuf to enc0 for bpf processing */