/*
- * Copyright (c) 2008-2014 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2016 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#include <netkey/keysock.h>
#include <netkey/key_debug.h>
#include <stdarg.h>
-
+#include <libkern/crypto/rand.h>
#include <netinet6/ipsec.h>
#if INET6
static u_int32_t acq_seq = 0;
static int key_tick_init_random = 0;
-__private_extern__ u_int32_t natt_now = 0;
+static u_int64_t up_time = 0;
+__private_extern__ u_int64_t natt_now = 0;
static LIST_HEAD(_sptree, secpolicy) sptree[IPSEC_DIR_MAX]; /* SPD */
static LIST_HEAD(_sahtree, secashead) sahtree; /* SAD */
u_int32_t pid,
struct sadb_lifetime *lifetime_hard,
struct sadb_lifetime *lifetime_soft);
+static void bzero_keys(const struct sadb_msghdr *);
extern int ipsec_bypass;
extern int esp_udp_encap_port;
int ipsec_send_natt_keepalive(struct secasvar *sav);
bool ipsec_fill_offload_frame(ifnet_t ifp, struct secasvar *sav, struct ifnet_keepalive_offload_frame *frame, size_t frame_data_offset);
-u_int32_t key_fill_offload_frames_for_savs (ifnet_t ifp, struct ifnet_keepalive_offload_frame *frames_array, u_int32_t frames_array_count, size_t frame_data_offset);
void key_init(struct protosw *, struct domain *);
key_start_timehandler(void)
{
/* must be called while locked */
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
if (key_timehandler_running == 0) {
key_timehandler_running = 1;
(void)timeout((void *)key_timehandler, (void *)0, hz);
struct secpolicy *sp;
struct timeval tv;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
/* sanity check */
if (spidx == NULL)
panic("key_allocsp: NULL pointer is passed.\n");
if (interface == NULL)
return NULL;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
lck_mtx_lock(sadb_mutex);
LIST_FOREACH(sah, &sahtree, chain) {
+ if (sah->state == SADB_SASTATE_DEAD) {
+ continue;
+ }
if (sah->ipsec_if == interface &&
(family == AF_INET6 || family == AF_INET) &&
sah->dir == IPSEC_DIR_OUTBOUND) {
int error;
struct sockaddr_in *sin;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
*sav = NULL;
{
struct secasvar *sav, *nextsav, *candidate, *natt_candidate, *no_natt_candidate, *d;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
/* initialize */
candidate = NULL;
caddr_t dst,
u_int proto,
u_int32_t spi)
+{
+ return key_allocsa_extended(family, src, dst, proto, spi, NULL);
+}
+
+struct secasvar *
+key_allocsa_extended(u_int family,
+ caddr_t src,
+ caddr_t dst,
+ u_int proto,
+ u_int32_t spi,
+ ifnet_t interface)
{
struct secasvar *sav, *match;
u_int stateidx, state, tmpidx, matchidx;
const u_int *saorder_state_valid;
int arraysize;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
/* sanity check */
if (src == NULL || dst == NULL)
LIST_FOREACH(sav, &spihash[SPIHASH(spi)], spihash) {
if (sav->spi != spi)
continue;
+ if (interface != NULL &&
+ sav->sah->ipsec_if != interface) {
+ continue;
+ }
if (proto != sav->sah->saidx.proto)
continue;
if (family != sav->sah->saidx.src.ss_family ||
struct secasvar *currsav, *nextsav, *candidate;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
/* initilize */
candidate = NULL;
if (!locked)
lck_mtx_lock(sadb_mutex);
else
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
sp->refcnt--;
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP freesp cause refcnt--:%d SP:0x%llx\n",
if (!locked)
lck_mtx_lock(sadb_mutex);
else
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
sav->refcnt--;
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP freesav cause refcnt--:%d SA:0x%llx SPI %u\n",
if (sp == NULL)
panic("key_delsp: NULL pointer is passed.\n");
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
sp->state = IPSEC_SPSTATE_DEAD;
if (sp->refcnt > 0)
{
struct secpolicy *sp;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
/* sanity check */
if (spidx == NULL)
{
struct secpolicy *sp;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
lck_mtx_lock(sadb_mutex);
sp = __key_getspbyid(id);
{
struct secpolicy *sp;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
LIST_FOREACH(sp, &sptree[IPSEC_DIR_INBOUND], chain) {
if (sp->state == IPSEC_SPSTATE_DEAD)
{
struct secpolicy *newsp = NULL;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
newsp = keydb_newsecpolicy();
if (!newsp)
return newsp;
{
struct secpolicy *newsp;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
/* sanity check */
if (xpl0 == NULL)
xisr = (struct sadb_x_ipsecrequest *)(xpl0 + 1);
while (tlen > 0) {
+ if (tlen < sizeof(*xisr)) {
+ ipseclog((LOG_DEBUG, "key_msg2sp: "
+ "invalid ipsecrequest.\n"));
+ key_freesp(newsp, KEY_SADB_UNLOCKED);
+ *error = EINVAL;
+ return NULL;
+ }
/* length check */
if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr)) {
/* set IP addresses if there */
if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) {
struct sockaddr *paddr;
+
+ if (tlen < xisr->sadb_x_ipsecrequest_len) {
+ ipseclog((LOG_DEBUG, "key_msg2sp: invalid request "
+ "address length.\n"));
+ key_freesp(newsp, KEY_SADB_UNLOCKED);
+ *error = EINVAL;
+ return NULL;
+ }
paddr = (struct sockaddr *)(xisr + 1);
+ uint8_t src_len = paddr->sa_len;
+
+ if (xisr->sadb_x_ipsecrequest_len < src_len) {
+ ipseclog((LOG_DEBUG, "key_msg2sp: invalid request "
+ "invalid source address length.\n"));
+ key_freesp(newsp, KEY_SADB_UNLOCKED);
+ *error = EINVAL;
+ return NULL;
+ }
/* validity check */
if (paddr->sa_len
*error = EINVAL;
return NULL;
}
+
bcopy(paddr, &(*p_isr)->saidx.src,
- paddr->sa_len);
+ MIN(paddr->sa_len, sizeof((*p_isr)->saidx.src)));
- paddr = (struct sockaddr *)((caddr_t)paddr
- + paddr->sa_len);
+ paddr = (struct sockaddr *)((caddr_t)paddr + paddr->sa_len);
+ uint8_t dst_len = paddr->sa_len;
+
+ if (xisr->sadb_x_ipsecrequest_len < (src_len + dst_len)) {
+ ipseclog((LOG_DEBUG, "key_msg2sp: invalid request "
+ "invalid dest address length.\n"));
+ key_freesp(newsp, KEY_SADB_UNLOCKED);
+ *error = EINVAL;
+ return NULL;
+ }
/* validity check */
if (paddr->sa_len
*error = EINVAL;
return NULL;
}
+
bcopy(paddr, &(*p_isr)->saidx.dst,
- paddr->sa_len);
+ MIN(paddr->sa_len, sizeof((*p_isr)->saidx.dst)));
}
(*p_isr)->sp = newsp;
struct mbuf *m,
const struct sadb_msghdr *mhp)
{
- struct sadb_address *src0, *dst0, *src1, *dst1;
+ struct sadb_address *src0, *dst0, *src1 = NULL, *dst1 = NULL;
struct sadb_x_policy *xpl0, *xpl;
struct sadb_lifetime *lft = NULL;
struct secpolicyindex spidx;
int init_disabled = 0;
int address_family, address_len;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
/* sanity check */
if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
struct mbuf *m,
const struct sadb_msghdr *mhp)
{
- struct sadb_address *src0, *dst0, *src1, *dst1;
+ struct sadb_address *src0, *dst0, *src1 = NULL, *dst1 = NULL;
struct sadb_x_policy *xpl0;
struct secpolicyindex spidx;
struct secpolicy *sp;
int use_src_range = 0;
int use_dst_range = 0;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
/* sanity check */
if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
u_int32_t id;
struct secpolicy *sp;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
/* sanity check */
if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
u_int32_t id;
struct secpolicy *sp;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
/* sanity check */
if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
u_int32_t id;
struct secpolicy *sp;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
/* sanity check */
if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
struct secpolicy *sp;
struct mbuf *n;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
/* sanity check */
if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
struct secspacq *newspacq;
int error;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
/* sanity check */
if (sp == NULL)
int error = EINVAL;
struct sadb_lifetime *lt;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
/* sanity check */
if (sp == NULL)
u_int stateidx, state;
int zombie = 0;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
/* sanity check */
if (sah == NULL)
struct secasvar *newsav;
const struct sadb_sa *xsa;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
/* sanity check */
if (m == NULL || mhp == NULL || mhp->msg == NULL || sah == NULL)
{
struct secasvar *newsav;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
/* sanity check */
if (sah == NULL)
struct secasvar *sav)
{
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
/* sanity check */
if (sav == NULL)
{
struct secashead *sah;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
LIST_FOREACH(sah, &sahtree, chain) {
if (sah->state == SADB_SASTATE_DEAD)
{
struct secashead *sah;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
sah = key_getsah(saidx);
if (!sah) {
struct secasvar *sav;
u_int stateidx, state;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
/* check address family */
if (saidx->src.ss_family != saidx->dst.ss_family) {
struct secasvar *sav,
u_int32_t spi)
{
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
sav->spi = spi;
if (sav->spihash.le_prev || sav->spihash.le_next)
LIST_REMOVE(sav, spihash);
struct secasvar *sav, *match;
u_int stateidx, state, matchidx;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
match = NULL;
matchidx = _ARRAYLEN(saorder_state_alive);
LIST_FOREACH(sav, &spihash[SPIHASH(spi)], spihash) {
int error = 0;
struct timeval tv;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
/* sanity check */
if (m == NULL || mhp == NULL || mhp->msg == NULL)
}
/* initialize */
- key_randomfill(sav->iv, sav->ivlen);
+ if (sav->alg_enc == SADB_X_EALG_AES_GCM) {
+ bzero(sav->iv, sav->ivlen);
+ } else {
+ key_randomfill(sav->iv, sav->ivlen);
+ }
#endif
break;
case SADB_SATYPE_AH:
int error = 0;
struct timeval tv;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
/* initialization */
sav->replay = NULL;
}
}
/* initialize */
- key_randomfill(sav->iv, sav->ivlen);
+ if (sav->alg_enc == SADB_X_EALG_AES_GCM) {
+ bzero(sav->iv, sav->ivlen);
+ } else {
+ key_randomfill(sav->iv, sav->ivlen);
+ }
}
#endif
}
mature = 0;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
/* check SPI value */
switch (sav->sah->saidx.proto) {
{
caddr_t new;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
KMALLOC_NOWAIT(new, caddr_t, len);
if (new == NULL) {
lck_mtx_unlock(sadb_mutex);
key_tick_init_random = 0;
key_srandom();
}
-
- natt_now++;
+
+ uint64_t acc_sleep_time = 0;
+ absolutetime_to_nanoseconds(mach_absolutetime_asleep, &acc_sleep_time);
+ natt_now = ++up_time + (acc_sleep_time / NSEC_PER_SEC);
lck_mtx_unlock(sadb_mutex);
size_t l)
{
#ifdef __APPLE__
-
- read_random(p, (u_int)l);
+ cc_rand_generate(p, l);
#else
size_t n;
u_int32_t v;
return IPPROTO_ESP;
case SADB_X_SATYPE_IPCOMP:
return IPPROTO_IPCOMP;
- break;
default:
return 0;
}
return SADB_SATYPE_ESP;
case IPPROTO_IPCOMP:
return SADB_X_SATYPE_IPCOMP;
- break;
default:
return 0;
}
u_int32_t reqid;
int error;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
/* sanity check */
if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
u_int32_t spi;
struct secasindex saidx;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
/* XXX boundary check against sa_len */
KEY_SETSECASIDX(proto, mode, reqid, src, dst, 0, &saidx);
u_int32_t keymin, keymax;
int count = key_spi_trycnt;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
/* set spi range to allocate */
if (spirange != NULL) {
u_int16_t flags2;
int error;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
/* sanity check */
if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
struct secasvar *sav = NULL;
u_int16_t proto;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
/* sanity check */
if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
sav->natt_interval = ((const struct sadb_sa_2*)(sa0))->sadb_sa_natt_interval;
sav->natt_offload_interval = ((const struct sadb_sa_2*)(sa0))->sadb_sa_natt_offload_interval;
sav->natt_last_activity = natt_now;
-
+
/*
* Verify if SADB_X_EXT_NATT_MULTIPLEUSERS flag is set that
* SADB_X_EXT_NATT is set and SADB_X_EXT_NATT_KEEPALIVE is not
struct secasvar *sav;
u_int state;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
state = SADB_SASTATE_LARVAL;
u_int32_t reqid;
int error;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
/* sanity check */
if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
/* map satype to proto */
if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) {
ipseclog((LOG_DEBUG, "key_add: invalid satype is passed.\n"));
+ bzero_keys(mhp);
return key_senderror(so, m, EINVAL);
}
(mhp->ext[SADB_EXT_LIFETIME_HARD] == NULL &&
mhp->ext[SADB_EXT_LIFETIME_SOFT] != NULL)) {
ipseclog((LOG_DEBUG, "key_add: invalid message is passed.\n"));
+ bzero_keys(mhp);
return key_senderror(so, m, EINVAL);
}
if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) ||
mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) {
/* XXX need more */
ipseclog((LOG_DEBUG, "key_add: invalid message is passed.\n"));
+ bzero_keys(mhp);
return key_senderror(so, m, EINVAL);
}
if (mhp->ext[SADB_X_EXT_SA2] != NULL) {
if ((newsah = key_newsah(&saidx, ipsec_if, key_get_outgoing_ifindex_from_message(mhp, SADB_X_EXT_IPSECIF), IPSEC_DIR_OUTBOUND)) == NULL) {
lck_mtx_unlock(sadb_mutex);
ipseclog((LOG_DEBUG, "key_add: No more memory.\n"));
+ bzero_keys(mhp);
return key_senderror(so, m, ENOBUFS);
}
}
error = key_setident(newsah, m, mhp);
if (error) {
lck_mtx_unlock(sadb_mutex);
+ bzero_keys(mhp);
return key_senderror(so, m, error);
}
if (key_getsavbyspi(newsah, sa0->sadb_sa_spi)) {
lck_mtx_unlock(sadb_mutex);
ipseclog((LOG_DEBUG, "key_add: SA already exists.\n"));
+ bzero_keys(mhp);
return key_senderror(so, m, EEXIST);
}
newsav = key_newsav(m, mhp, newsah, &error, so);
if (newsav == NULL) {
lck_mtx_unlock(sadb_mutex);
+ bzero_keys(mhp);
return key_senderror(so, m, error);
}
if ((error = key_mature(newsav)) != 0) {
key_freesav(newsav, KEY_SADB_LOCKED);
lck_mtx_unlock(sadb_mutex);
+ bzero_keys(mhp);
return key_senderror(so, m, error);
}
n = key_getmsgbuf_x1(m, mhp);
if (n == NULL) {
ipseclog((LOG_DEBUG, "key_update: No more memory.\n"));
+ bzero_keys(mhp);
return key_senderror(so, m, ENOBUFS);
}
+ // mh.ext points to the mbuf content.
+ // Zero out Encryption and Integrity keys if present.
+ bzero_keys(mhp);
m_freem(m);
return key_sendup_mbuf(so, n, KEY_SENDUP_ALL);
}
const struct sadb_ident *idsrc, *iddst;
int idsrclen, iddstlen;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
/* sanity check */
if (sah == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
struct secasvar *sav = NULL;
u_int16_t proto;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
/* sanity check */
if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
struct secasvar *sav, *nextsav;
u_int stateidx, state;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]);
dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]);
struct secasvar *sav = NULL;
u_int16_t proto;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
/* sanity check */
if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
int error = -1;
u_int32_t seq;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
/* sanity check */
if (saidx == NULL)
{
struct secacq *acq;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
LIST_FOREACH(acq, &acqtree, chain) {
if (key_cmpsaidx(saidx, &acq->saidx, CMP_EXACTLY))
{
struct secacq *acq;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
LIST_FOREACH(acq, &acqtree, chain) {
if (acq->seq == seq)
{
struct secspacq *acq;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
LIST_FOREACH(acq, &spacqtree, chain) {
if (key_cmpspidx_exactly(spidx, &acq->spidx))
int error = -1;
struct sadb_lifetime *lt;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
/* sanity check */
if (sav == NULL)
struct mbuf *n;
int error = 0;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
/* sanity check */
if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
}
static void
-bzero_keys(struct sadb_msghdr *mh)
+bzero_keys(const struct sadb_msghdr *mh)
{
int extlen = 0;
int offset = 0;
}
}
+static int
+key_validate_address_pair(struct sadb_address *src0,
+ struct sadb_address *dst0)
+{
+ u_int plen = 0;
+
+ /* check upper layer protocol */
+ if (src0->sadb_address_proto != dst0->sadb_address_proto) {
+ ipseclog((LOG_DEBUG, "key_parse: upper layer protocol mismatched.\n"));
+ PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr);
+ return (EINVAL);
+ }
+
+ /* check family */
+ if (PFKEY_ADDR_SADDR(src0)->sa_family !=
+ PFKEY_ADDR_SADDR(dst0)->sa_family) {
+ ipseclog((LOG_DEBUG, "key_parse: address family mismatched.\n"));
+ PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr);
+ return (EINVAL);
+ }
+ if (PFKEY_ADDR_SADDR(src0)->sa_len !=
+ PFKEY_ADDR_SADDR(dst0)->sa_len) {
+ ipseclog((LOG_DEBUG,
+ "key_parse: address struct size mismatched.\n"));
+ PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr);
+ return (EINVAL);
+ }
+
+ switch (PFKEY_ADDR_SADDR(src0)->sa_family) {
+ case AF_INET:
+ if (PFKEY_ADDR_SADDR(src0)->sa_len != sizeof(struct sockaddr_in)) {
+ PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr);
+ return (EINVAL);
+ }
+ break;
+ case AF_INET6:
+ if (PFKEY_ADDR_SADDR(src0)->sa_len != sizeof(struct sockaddr_in6)) {
+ PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr);
+ return (EINVAL);
+ }
+ break;
+ default:
+ ipseclog((LOG_DEBUG,
+ "key_parse: unsupported address family.\n"));
+ PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr);
+ return (EAFNOSUPPORT);
+ }
+
+ switch (PFKEY_ADDR_SADDR(src0)->sa_family) {
+ case AF_INET:
+ plen = sizeof(struct in_addr) << 3;
+ break;
+ case AF_INET6:
+ plen = sizeof(struct in6_addr) << 3;
+ break;
+ default:
+ plen = 0; /*fool gcc*/
+ break;
+ }
+
+ /* check max prefix length */
+ if (src0->sadb_address_prefixlen > plen ||
+ dst0->sadb_address_prefixlen > plen) {
+ ipseclog((LOG_DEBUG,
+ "key_parse: illegal prefixlen.\n"));
+ PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr);
+ return (EINVAL);
+ }
+
+ /*
+ * prefixlen == 0 is valid because there can be a case when
+ * all addresses are matched.
+ */
+ return (0);
+}
+
/*
* parse sadb_msg buffer to process PFKEYv2,
* and create a data to response if needed.
int target;
Boolean keyAligned = FALSE;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
/* sanity check */
if (m == NULL || so == NULL)
goto senderror;
}
- /* check field of upper layer protocol and address family */
- if (mh.ext[SADB_EXT_ADDRESS_SRC] != NULL
- && mh.ext[SADB_EXT_ADDRESS_DST] != NULL) {
- struct sadb_address *src0, *dst0;
- u_int plen;
-
- src0 = (struct sadb_address *)(mh.ext[SADB_EXT_ADDRESS_SRC]);
- dst0 = (struct sadb_address *)(mh.ext[SADB_EXT_ADDRESS_DST]);
-
- /* check upper layer protocol */
- if (src0->sadb_address_proto != dst0->sadb_address_proto) {
- ipseclog((LOG_DEBUG, "key_parse: upper layer protocol mismatched.\n"));
- PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr);
- error = EINVAL;
+ /* Validate address fields for matching families, lengths, etc. */
+ void *src0 = mh.ext[SADB_EXT_ADDRESS_SRC];
+ void *dst0 = mh.ext[SADB_EXT_ADDRESS_DST];
+ if (mh.ext[SADB_X_EXT_ADDR_RANGE_SRC_START] != NULL &&
+ mh.ext[SADB_X_EXT_ADDR_RANGE_SRC_END] != NULL) {
+
+ error = key_validate_address_pair((struct sadb_address *)(mh.ext[SADB_X_EXT_ADDR_RANGE_SRC_START]),
+ (struct sadb_address *)(mh.ext[SADB_X_EXT_ADDR_RANGE_SRC_END]));
+ if (error != 0) {
goto senderror;
}
-
- /* check family */
- if (PFKEY_ADDR_SADDR(src0)->sa_family !=
- PFKEY_ADDR_SADDR(dst0)->sa_family) {
- ipseclog((LOG_DEBUG, "key_parse: address family mismatched.\n"));
- PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr);
- error = EINVAL;
- goto senderror;
+
+ if (src0 == NULL) {
+ src0 = mh.ext[SADB_X_EXT_ADDR_RANGE_SRC_START];
}
- if (PFKEY_ADDR_SADDR(src0)->sa_len !=
- PFKEY_ADDR_SADDR(dst0)->sa_len) {
- ipseclog((LOG_DEBUG,
- "key_parse: address struct size mismatched.\n"));
- PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr);
- error = EINVAL;
+ }
+ if (mh.ext[SADB_X_EXT_ADDR_RANGE_DST_START] != NULL &&
+ mh.ext[SADB_X_EXT_ADDR_RANGE_DST_END] != NULL) {
+
+ error = key_validate_address_pair((struct sadb_address *)(mh.ext[SADB_X_EXT_ADDR_RANGE_DST_START]),
+ (struct sadb_address *)(mh.ext[SADB_X_EXT_ADDR_RANGE_DST_END]));
+ if (error != 0) {
goto senderror;
}
-
- switch (PFKEY_ADDR_SADDR(src0)->sa_family) {
- case AF_INET:
- if (PFKEY_ADDR_SADDR(src0)->sa_len !=
- sizeof(struct sockaddr_in)) {
- PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr);
- error = EINVAL;
- goto senderror;
- }
- break;
- case AF_INET6:
- if (PFKEY_ADDR_SADDR(src0)->sa_len !=
- sizeof(struct sockaddr_in6)) {
- PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr);
- error = EINVAL;
- goto senderror;
- }
- break;
- default:
- ipseclog((LOG_DEBUG,
- "key_parse: unsupported address family.\n"));
- PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr);
- error = EAFNOSUPPORT;
- goto senderror;
- }
-
- switch (PFKEY_ADDR_SADDR(src0)->sa_family) {
- case AF_INET:
- plen = sizeof(struct in_addr) << 3;
- break;
- case AF_INET6:
- plen = sizeof(struct in6_addr) << 3;
- break;
- default:
- plen = 0; /*fool gcc*/
- break;
+
+ if (dst0 == NULL) {
+ dst0 = mh.ext[SADB_X_EXT_ADDR_RANGE_DST_START];
}
-
- /* check max prefix length */
- if (src0->sadb_address_prefixlen > plen ||
- dst0->sadb_address_prefixlen > plen) {
- ipseclog((LOG_DEBUG,
- "key_parse: illegal prefixlen.\n"));
- PFKEY_STAT_INCREMENT(pfkeystat.out_invaddr);
- error = EINVAL;
+ }
+ if (src0 != NULL && dst0 != NULL) {
+ error = key_validate_address_pair((struct sadb_address *)(src0),
+ (struct sadb_address *)(dst0));
+ if (error != 0) {
goto senderror;
}
-
- /*
- * prefixlen == 0 is valid because there can be a case when
- * all addresses are matched.
- */
}
if (msg->sadb_msg_type >= sizeof(key_typesw)/sizeof(key_typesw[0]) ||
error = (*key_typesw[msg->sadb_msg_type])(so, m, &mh);
- // mh.ext points to the mbuf content.
- // Zero out Encryption and Integrity keys if present.
- bzero_keys(&mh);
-
return error;
senderror:
{
struct sadb_msg *msg;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
if (m->m_len < sizeof(struct sadb_msg))
panic("invalid mbuf passed to key_senderror");
{
struct sockaddr *sa;
enum { NONE, ADDR } checktype = NONE;
- int baselen;
+ int baselen = 0;
const int sal = offsetof(struct sockaddr, sa_len) + sizeof(sa->sa_len);
if (len != PFKEY_UNUNIT64(ext->sadb_ext_len))
lck_mtx_lock(sadb_mutex);
LIST_FOREACH(sah, &sahtree, chain) {
- ro = &sah->sa_route;
+ ro = (struct route *)&sah->sa_route;
if (ro->ro_rt && dst->sa_len == ro->ro_dst.sa_len
&& bcmp(dst, &ro->ro_dst, dst->sa_len) == 0) {
ROUTE_RELEASE(ro);
if (sav->state == state)
return;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
if (__LIST_CHAINED(sav))
LIST_REMOVE(sav, chain);
return key_senderror(so, m, EINVAL);
}
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
// exit early if there are no active SAs
if (ipsec_sav_count <= 0) {
if (ipsec_if == NULL)
return;
- lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
+ LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
lck_mtx_lock(sadb_mutex);