summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netipsec
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-08-09 13:04:41 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-09-21 10:29:37 +0200
commite4a8065910cd6b2e7e0448cc6431ca2906322389 (patch)
tree73492991cfa40f994c20d761d476e6bc16304536 /freebsd/sys/netipsec
parentUpdate to FreeBSD head 2017-08-01 (diff)
downloadrtems-libbsd-e4a8065910cd6b2e7e0448cc6431ca2906322389.tar.bz2
Update to FreeBSD head 2017-10-01
Git mirror commit b2f0376b45428f13151d229c5ae9d4d8f74acbd1. Update #3472.
Diffstat (limited to 'freebsd/sys/netipsec')
-rw-r--r--freebsd/sys/netipsec/ipsec.c26
-rw-r--r--freebsd/sys/netipsec/ipsec.h2
-rw-r--r--freebsd/sys/netipsec/ipsec6.h2
-rw-r--r--freebsd/sys/netipsec/ipsec_output.c4
-rw-r--r--freebsd/sys/netipsec/key.c26
-rw-r--r--freebsd/sys/netipsec/udpencap.c7
-rw-r--r--freebsd/sys/netipsec/xform_ah.c4
7 files changed, 43 insertions, 28 deletions
diff --git a/freebsd/sys/netipsec/ipsec.c b/freebsd/sys/netipsec/ipsec.c
index 4b44a8ce..79c9519c 100644
--- a/freebsd/sys/netipsec/ipsec.c
+++ b/freebsd/sys/netipsec/ipsec.c
@@ -565,7 +565,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;
@@ -574,8 +575,7 @@ ipsec4_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir)
if (sp == NULL && key_havesp(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);
}
@@ -588,12 +588,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) {
@@ -625,7 +626,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)
@@ -733,7 +734,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;
@@ -742,8 +744,7 @@ ipsec6_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir)
if (sp == NULL && key_havesp(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);
}
@@ -756,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) {
@@ -793,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)
diff --git a/freebsd/sys/netipsec/ipsec.h b/freebsd/sys/netipsec/ipsec.h
index a4c3f3d2..a61730ef 100644
--- a/freebsd/sys/netipsec/ipsec.h
+++ b/freebsd/sys/netipsec/ipsec.h
@@ -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);
diff --git a/freebsd/sys/netipsec/ipsec6.h b/freebsd/sys/netipsec/ipsec6.h
index a5fae4d1..33aa30f3 100644
--- a/freebsd/sys/netipsec/ipsec6.h
+++ b/freebsd/sys/netipsec/ipsec6.h
@@ -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 *);
diff --git a/freebsd/sys/netipsec/ipsec_output.c b/freebsd/sys/netipsec/ipsec_output.c
index 07e39a8a..ac9529d5 100644
--- a/freebsd/sys/netipsec/ipsec_output.c
+++ b/freebsd/sys/netipsec/ipsec_output.c
@@ -299,7 +299,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. */
@@ -601,7 +601,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. */
diff --git a/freebsd/sys/netipsec/key.c b/freebsd/sys/netipsec/key.c
index 0dfab7bd..ef5d8419 100644
--- a/freebsd/sys/netipsec/key.c
+++ b/freebsd/sys/netipsec/key.c
@@ -1405,7 +1405,8 @@ key_msg2sp(struct sadb_x_policy *xpl0, size_t len, int *error)
while (tlen > 0) {
/* length check */
- if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr)) {
+ if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr) ||
+ xisr->sadb_x_ipsecrequest_len > tlen) {
ipseclog((LOG_DEBUG, "%s: invalid ipsecrequest "
"length.\n", __func__));
key_freesp(&newsp);
@@ -1519,10 +1520,12 @@ key_msg2sp(struct sadb_x_policy *xpl0, size_t len, int *error)
if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) {
struct sockaddr *paddr;
+ len = tlen - sizeof(*xisr);
paddr = (struct sockaddr *)(xisr + 1);
/* validity check */
- if (paddr->sa_len
- > sizeof(isr->saidx.src)) {
+ if (len < sizeof(struct sockaddr) ||
+ len < 2 * paddr->sa_len ||
+ paddr->sa_len > sizeof(isr->saidx.src)) {
ipseclog((LOG_DEBUG, "%s: invalid "
"request address length.\n",
__func__));
@@ -1530,13 +1533,26 @@ key_msg2sp(struct sadb_x_policy *xpl0, size_t len, int *error)
*error = EINVAL;
return NULL;
}
+ /*
+ * Request length should be enough to keep
+ * source and destination addresses.
+ */
+ if (xisr->sadb_x_ipsecrequest_len <
+ sizeof(*xisr) + 2 * paddr->sa_len) {
+ ipseclog((LOG_DEBUG, "%s: invalid "
+ "ipsecrequest length.\n",
+ __func__));
+ key_freesp(&newsp);
+ *error = EINVAL;
+ return (NULL);
+ }
bcopy(paddr, &isr->saidx.src, paddr->sa_len);
paddr = (struct sockaddr *)((caddr_t)paddr +
paddr->sa_len);
/* validity check */
- if (paddr->sa_len
- > sizeof(isr->saidx.dst)) {
+ if (paddr->sa_len !=
+ isr->saidx.src.sa.sa_len) {
ipseclog((LOG_DEBUG, "%s: invalid "
"request address length.\n",
__func__));
diff --git a/freebsd/sys/netipsec/udpencap.c b/freebsd/sys/netipsec/udpencap.c
index 265461cd..3eb106b2 100644
--- a/freebsd/sys/netipsec/udpencap.c
+++ b/freebsd/sys/netipsec/udpencap.c
@@ -122,7 +122,7 @@ udp_ipsec_input(struct mbuf *m, int off, int af)
struct udphdr *udp;
struct ip *ip;
uint32_t spi;
- int error, hlen;
+ int hlen;
/*
* Just return if packet doesn't have enough data.
@@ -207,10 +207,7 @@ udp_ipsec_input(struct mbuf *m, int off, int af)
* will do this anyway, so don't touch them here.
*/
ESPSTAT_INC(esps_input);
- error = (*sav->tdb_xform->xf_input)(m, sav, hlen, off);
- if (error != 0)
- key_freesav(&sav);
-
+ (*sav->tdb_xform->xf_input)(m, sav, hlen, off);
return (EINPROGRESS); /* Consumed by IPsec. */
}
diff --git a/freebsd/sys/netipsec/xform_ah.c b/freebsd/sys/netipsec/xform_ah.c
index 9c2620f4..6e9baa1f 100644
--- a/freebsd/sys/netipsec/xform_ah.c
+++ b/freebsd/sys/netipsec/xform_ah.c
@@ -195,9 +195,9 @@ ah_init0(struct secasvar *sav, struct xformsw *xsp, struct cryptoini *cria)
return EINVAL;
}
keylen = _KEYLEN(sav->key_auth);
- if (keylen != thash->keysize && thash->keysize != 0) {
+ if (keylen > thash->keysize && thash->keysize != 0) {
DPRINTF(("%s: invalid keylength %d, algorithm %s requires "
- "keysize %d\n", __func__,
+ "keysize less than %d\n", __func__,
keylen, thash->name, thash->keysize));
return EINVAL;
}