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:
parent
a09e09654c
commit
9e3bdede0f
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user