X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/490019cf9519204c5fb36b2fba54ceb983bb6b72..5c9f46613a83ebfc29a5b1f099448259e96a98f0:/bsd/netkey/key.c diff --git a/bsd/netkey/key.c b/bsd/netkey/key.c index 2d91aa70b..a7935a5f2 100644 --- a/bsd/netkey/key.c +++ b/bsd/netkey/key.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2014 Apple Inc. All rights reserved. + * Copyright (c) 2008-2016 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -103,7 +103,7 @@ #include #include #include - +#include #include #if INET6 @@ -172,7 +172,8 @@ static int ipsec_sav_count = 0; 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 */ @@ -588,12 +589,12 @@ static int key_setsaval2(struct secasvar *sav, 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 *); @@ -676,7 +677,7 @@ static void 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); @@ -702,7 +703,7 @@ key_allocsp( 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"); @@ -851,11 +852,14 @@ struct secasvar *key_alloc_outbound_sav_for_interface(ifnet_t interface, int fam 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) { @@ -906,7 +910,7 @@ key_checkrequest( 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; @@ -1100,7 +1104,7 @@ key_do_allocsa_policy( { 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; @@ -1229,6 +1233,17 @@ key_allocsa( 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; @@ -1237,7 +1252,7 @@ key_allocsa( 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) @@ -1271,6 +1286,10 @@ key_allocsa( 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 || @@ -1444,7 +1463,7 @@ key_do_get_translated_port( 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; @@ -1514,7 +1533,7 @@ key_freesp( 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", @@ -1545,7 +1564,7 @@ key_freesav( 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", @@ -1572,7 +1591,7 @@ key_delsp( 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) @@ -1624,7 +1643,7 @@ key_getsp( { 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) @@ -1653,7 +1672,7 @@ key_getspbyid( { 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); @@ -1667,7 +1686,7 @@ __key_getspbyid(u_int32_t 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) @@ -1695,7 +1714,7 @@ key_newsp(void) { 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; @@ -1719,7 +1738,7 @@ key_msg2sp( { 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) @@ -1769,6 +1788,13 @@ key_msg2sp( 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)) { @@ -1872,8 +1898,25 @@ key_msg2sp( /* 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 @@ -1884,11 +1927,20 @@ key_msg2sp( *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 @@ -1899,8 +1951,9 @@ key_msg2sp( *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; @@ -2133,7 +2186,7 @@ key_spdadd( 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; @@ -2149,7 +2202,7 @@ key_spdadd( 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) @@ -2535,7 +2588,7 @@ key_spddelete( 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; @@ -2544,7 +2597,7 @@ key_spddelete( 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) @@ -2689,7 +2742,7 @@ key_spddelete2( 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) @@ -2779,7 +2832,7 @@ key_spdenable( 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) @@ -2839,7 +2892,7 @@ key_spddisable( 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) @@ -2912,7 +2965,7 @@ key_spdget( 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) @@ -2966,7 +3019,7 @@ key_spdacquire( 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) @@ -3304,7 +3357,7 @@ key_spdexpire( 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) @@ -3511,7 +3564,7 @@ key_delsah( 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) @@ -3597,7 +3650,7 @@ key_newsav( 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) @@ -3762,7 +3815,7 @@ key_newsav2(struct secashead *sah, { 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) @@ -3860,7 +3913,7 @@ key_delsav( 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) @@ -3929,7 +3982,7 @@ key_getsah(struct secasindex *saidx) { 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) @@ -3947,7 +4000,7 @@ key_newsah2 (struct secasindex *saidx, { 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) { @@ -3971,7 +4024,7 @@ key_checkspidup( 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) { @@ -4001,7 +4054,7 @@ key_setspi( 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); @@ -4023,7 +4076,7 @@ key_getsavbyspi( 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) { @@ -4064,7 +4117,7 @@ key_setsaval( 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) @@ -4244,7 +4297,11 @@ key_setsaval( } /* 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: @@ -4401,7 +4458,7 @@ key_setsaval2(struct secasvar *sav, 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; @@ -4494,7 +4551,11 @@ key_setsaval2(struct secasvar *sav, } } /* 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 } @@ -4602,7 +4663,7 @@ key_mature( 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) { @@ -5287,7 +5348,7 @@ key_newbuf( { 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); @@ -6213,8 +6274,10 @@ key_timehandler(void) 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); @@ -6312,8 +6375,7 @@ key_randomfill( size_t l) { #ifdef __APPLE__ - - read_random(p, (u_int)l); + cc_rand_generate(p, l); #else size_t n; u_int32_t v; @@ -6356,7 +6418,6 @@ key_satype2proto( return IPPROTO_ESP; case SADB_X_SATYPE_IPCOMP: return IPPROTO_IPCOMP; - break; default: return 0; } @@ -6379,7 +6440,6 @@ key_proto2satype( return SADB_SATYPE_ESP; case IPPROTO_IPCOMP: return SADB_X_SATYPE_IPCOMP; - break; default: return 0; } @@ -6448,7 +6508,7 @@ key_getspi( 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) @@ -6650,7 +6710,7 @@ key_getspi2(struct sockaddr *src, 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); @@ -6711,7 +6771,7 @@ key_do_getnewspi( 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) { @@ -6804,7 +6864,7 @@ key_update( 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) @@ -6985,7 +7045,7 @@ key_migrate(struct socket *so, 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) @@ -7074,7 +7134,7 @@ key_migrate(struct socket *so, 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 @@ -7128,7 +7188,7 @@ key_getsavbyseq( 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; @@ -7183,7 +7243,7 @@ key_add( 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) @@ -7192,6 +7252,7 @@ key_add( /* 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); } @@ -7207,6 +7268,7 @@ key_add( (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) || @@ -7214,6 +7276,7 @@ key_add( 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) { @@ -7242,6 +7305,7 @@ key_add( 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); } } @@ -7251,6 +7315,7 @@ key_add( error = key_setident(newsah, m, mhp); if (error) { lck_mtx_unlock(sadb_mutex); + bzero_keys(mhp); return key_senderror(so, m, error); } @@ -7259,11 +7324,13 @@ key_add( 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); } @@ -7280,6 +7347,7 @@ key_add( 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); } @@ -7297,9 +7365,13 @@ key_add( 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); } @@ -7315,7 +7387,7 @@ key_setident( 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) @@ -7453,7 +7525,7 @@ key_delete( 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) @@ -7568,7 +7640,7 @@ key_delete_all( 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]); @@ -7660,7 +7732,7 @@ key_get( 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) @@ -8101,7 +8173,7 @@ key_acquire( 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) @@ -8310,7 +8382,7 @@ key_getacq( { 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)) @@ -8326,7 +8398,7 @@ key_getacqbyseq( { 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) @@ -8372,7 +8444,7 @@ key_getspacq( { 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)) @@ -8776,7 +8848,7 @@ key_expire( 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) @@ -9000,7 +9072,7 @@ key_dump( 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) @@ -9214,7 +9286,7 @@ bzero_mbuf(struct mbuf *m) } static void -bzero_keys(struct sadb_msghdr *mh) +bzero_keys(const struct sadb_msghdr *mh) { int extlen = 0; int offset = 0; @@ -9246,6 +9318,82 @@ bzero_keys(struct sadb_msghdr *mh) } } +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. @@ -9269,7 +9417,7 @@ key_parse( 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) @@ -9418,91 +9566,41 @@ key_parse( 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]) || @@ -9514,10 +9612,6 @@ key_parse( 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: @@ -9538,7 +9632,7 @@ key_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"); @@ -9679,7 +9773,7 @@ key_validate_ext( { 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)) @@ -9826,7 +9920,7 @@ key_sa_routechange( 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); @@ -9849,7 +9943,7 @@ key_sa_chgstate( 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); @@ -10007,7 +10101,7 @@ key_getsastat (struct socket *so, 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) { @@ -10214,7 +10308,7 @@ key_delsp_for_ipsec_if (ifnet_t ipsec_if) 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);