Fix the regression introduced in r275710.
When a security policy should match TCP connection with specific ports, the SYN+ACK segment send by syncache_respond() is considered as forwarded packet, because at this moment TCP connection does not have PCB structure, and ip_output() is called without inpcb pointer. In this case SPIDX filled for SP lookup will not contain TCP ports and security policy will not be found. This can lead to unencrypted SYN+ACK on the wire. This patch restores the old behavior, when ports will not be filled only for forwarded packets. Reported by: Dewayne Geraghty <dewayne.geraghty at heuristicsystems.com.au> MFC after: 1 week
This commit is contained in:
parent
7e5308db2e
commit
22bbefb2c9
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=322750
@ -563,7 +563,8 @@ ipsec4_setspidx_ipaddr(const struct mbuf *m, struct secpolicyindex *spidx)
|
||||
}
|
||||
|
||||
static struct secpolicy *
|
||||
ipsec4_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir)
|
||||
ipsec4_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir,
|
||||
int needport)
|
||||
{
|
||||
struct secpolicyindex spidx;
|
||||
struct secpolicy *sp;
|
||||
@ -573,7 +574,7 @@ ipsec4_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir)
|
||||
/* Make an index to look for a policy. */
|
||||
ipsec4_setspidx_ipaddr(m, &spidx);
|
||||
/* Fill ports in spidx if we have inpcb. */
|
||||
ipsec4_get_ulp(m, &spidx, inp != NULL);
|
||||
ipsec4_get_ulp(m, &spidx, needport);
|
||||
spidx.dir = dir;
|
||||
sp = key_allocsp(&spidx, dir);
|
||||
}
|
||||
@ -586,12 +587,13 @@ ipsec4_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir)
|
||||
* Check security policy for *OUTBOUND* IPv4 packet.
|
||||
*/
|
||||
struct secpolicy *
|
||||
ipsec4_checkpolicy(const struct mbuf *m, struct inpcb *inp, int *error)
|
||||
ipsec4_checkpolicy(const struct mbuf *m, struct inpcb *inp, int *error,
|
||||
int needport)
|
||||
{
|
||||
struct secpolicy *sp;
|
||||
|
||||
*error = 0;
|
||||
sp = ipsec4_getpolicy(m, inp, IPSEC_DIR_OUTBOUND);
|
||||
sp = ipsec4_getpolicy(m, inp, IPSEC_DIR_OUTBOUND, needport);
|
||||
if (sp != NULL)
|
||||
sp = ipsec_checkpolicy(sp, inp, error);
|
||||
if (sp == NULL) {
|
||||
@ -623,7 +625,7 @@ ipsec4_in_reject(const struct mbuf *m, struct inpcb *inp)
|
||||
struct secpolicy *sp;
|
||||
int result;
|
||||
|
||||
sp = ipsec4_getpolicy(m, inp, IPSEC_DIR_INBOUND);
|
||||
sp = ipsec4_getpolicy(m, inp, IPSEC_DIR_INBOUND, 0);
|
||||
result = ipsec_in_reject(sp, inp, m);
|
||||
key_freesp(&sp);
|
||||
if (result != 0)
|
||||
@ -731,7 +733,8 @@ ipsec6_setspidx_ipaddr(const struct mbuf *m, struct secpolicyindex *spidx)
|
||||
}
|
||||
|
||||
static struct secpolicy *
|
||||
ipsec6_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir)
|
||||
ipsec6_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir,
|
||||
int needport)
|
||||
{
|
||||
struct secpolicyindex spidx;
|
||||
struct secpolicy *sp;
|
||||
@ -741,7 +744,7 @@ ipsec6_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir)
|
||||
/* Make an index to look for a policy. */
|
||||
ipsec6_setspidx_ipaddr(m, &spidx);
|
||||
/* Fill ports in spidx if we have inpcb. */
|
||||
ipsec6_get_ulp(m, &spidx, inp != NULL);
|
||||
ipsec6_get_ulp(m, &spidx, needport);
|
||||
spidx.dir = dir;
|
||||
sp = key_allocsp(&spidx, dir);
|
||||
}
|
||||
@ -754,12 +757,13 @@ ipsec6_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir)
|
||||
* Check security policy for *OUTBOUND* IPv6 packet.
|
||||
*/
|
||||
struct secpolicy *
|
||||
ipsec6_checkpolicy(const struct mbuf *m, struct inpcb *inp, int *error)
|
||||
ipsec6_checkpolicy(const struct mbuf *m, struct inpcb *inp, int *error,
|
||||
int needport)
|
||||
{
|
||||
struct secpolicy *sp;
|
||||
|
||||
*error = 0;
|
||||
sp = ipsec6_getpolicy(m, inp, IPSEC_DIR_OUTBOUND);
|
||||
sp = ipsec6_getpolicy(m, inp, IPSEC_DIR_OUTBOUND, needport);
|
||||
if (sp != NULL)
|
||||
sp = ipsec_checkpolicy(sp, inp, error);
|
||||
if (sp == NULL) {
|
||||
@ -791,7 +795,7 @@ ipsec6_in_reject(const struct mbuf *m, struct inpcb *inp)
|
||||
struct secpolicy *sp;
|
||||
int result;
|
||||
|
||||
sp = ipsec6_getpolicy(m, inp, IPSEC_DIR_INBOUND);
|
||||
sp = ipsec6_getpolicy(m, inp, IPSEC_DIR_INBOUND, 0);
|
||||
result = ipsec_in_reject(sp, inp, m);
|
||||
key_freesp(&sp);
|
||||
if (result)
|
||||
|
@ -320,7 +320,7 @@ int ipsec_if_input(struct mbuf *, struct secasvar *, uint32_t);
|
||||
struct ipsecrequest *ipsec_newisr(void);
|
||||
void ipsec_delisr(struct ipsecrequest *);
|
||||
struct secpolicy *ipsec4_checkpolicy(const struct mbuf *, struct inpcb *,
|
||||
int *);
|
||||
int *, int);
|
||||
|
||||
u_int ipsec_get_reqlevel(struct secpolicy *, u_int);
|
||||
|
||||
|
@ -60,7 +60,7 @@ VNET_DECLARE(int, ip6_ipsec_ecn);
|
||||
|
||||
struct inpcb;
|
||||
struct secpolicy *ipsec6_checkpolicy(const struct mbuf *,
|
||||
struct inpcb *, int *);
|
||||
struct inpcb *, int *, int);
|
||||
|
||||
void ipsec6_setsockaddrs(const struct mbuf *, union sockaddr_union *,
|
||||
union sockaddr_union *);
|
||||
|
@ -297,7 +297,7 @@ ipsec4_common_output(struct mbuf *m, struct inpcb *inp, int forwarding)
|
||||
int error;
|
||||
|
||||
/* Lookup for the corresponding outbound security policy */
|
||||
sp = ipsec4_checkpolicy(m, inp, &error);
|
||||
sp = ipsec4_checkpolicy(m, inp, &error, !forwarding);
|
||||
if (sp == NULL) {
|
||||
if (error == -EINVAL) {
|
||||
/* Discarded by policy. */
|
||||
@ -599,7 +599,7 @@ ipsec6_common_output(struct mbuf *m, struct inpcb *inp, int forwarding)
|
||||
int error;
|
||||
|
||||
/* Lookup for the corresponding outbound security policy */
|
||||
sp = ipsec6_checkpolicy(m, inp, &error);
|
||||
sp = ipsec6_checkpolicy(m, inp, &error, !forwarding);
|
||||
if (sp == NULL) {
|
||||
if (error == -EINVAL) {
|
||||
/* Discarded by policy. */
|
||||
|
Loading…
Reference in New Issue
Block a user