key.c revision 194062
1251881Speter/* $FreeBSD: head/sys/netipsec/key.c 194062 2009-06-12 15:44:35Z vanhu $ */ 2251881Speter/* $KAME: key.c,v 1.191 2001/06/27 10:46:49 sakane Exp $ */ 3251881Speter 4251881Speter/*- 5251881Speter * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6251881Speter * All rights reserved. 7251881Speter * 8251881Speter * Redistribution and use in source and binary forms, with or without 9251881Speter * modification, are permitted provided that the following conditions 10251881Speter * are met: 11251881Speter * 1. Redistributions of source code must retain the above copyright 12251881Speter * notice, this list of conditions and the following disclaimer. 13251881Speter * 2. Redistributions in binary form must reproduce the above copyright 14251881Speter * notice, this list of conditions and the following disclaimer in the 15251881Speter * documentation and/or other materials provided with the distribution. 16251881Speter * 3. Neither the name of the project nor the names of its contributors 17251881Speter * may be used to endorse or promote products derived from this software 18251881Speter * without specific prior written permission. 19251881Speter * 20251881Speter * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21251881Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22251881Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23251881Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24251881Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25251881Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26251881Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27251881Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28251881Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29251881Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30251881Speter * SUCH DAMAGE. 31251881Speter */ 32251881Speter 33251881Speter/* 34251881Speter * This code is referd to RFC 2367 35251881Speter */ 36251881Speter 37251881Speter#include "opt_inet.h" 38251881Speter#include "opt_inet6.h" 39251881Speter#include "opt_ipsec.h" 40251881Speter 41251881Speter#include <sys/types.h> 42251881Speter#include <sys/param.h> 43251881Speter#include <sys/systm.h> 44251881Speter#include <sys/kernel.h> 45251881Speter#include <sys/lock.h> 46251881Speter#include <sys/mutex.h> 47251881Speter#include <sys/mbuf.h> 48251881Speter#include <sys/domain.h> 49251881Speter#include <sys/protosw.h> 50251881Speter#include <sys/malloc.h> 51251881Speter#include <sys/socket.h> 52251881Speter#include <sys/socketvar.h> 53251881Speter#include <sys/sysctl.h> 54251881Speter#include <sys/errno.h> 55251881Speter#include <sys/proc.h> 56251881Speter#include <sys/queue.h> 57251881Speter#include <sys/refcount.h> 58251881Speter#include <sys/syslog.h> 59251881Speter#include <sys/vimage.h> 60251881Speter 61251881Speter#include <net/if.h> 62251881Speter#include <net/route.h> 63251881Speter#include <net/raw_cb.h> 64251881Speter 65251881Speter#include <netinet/in.h> 66251881Speter#include <netinet/in_systm.h> 67251881Speter#include <netinet/ip.h> 68251881Speter#include <netinet/in_var.h> 69251881Speter 70251881Speter#ifdef INET6 71251881Speter#include <netinet/ip6.h> 72251881Speter#include <netinet6/in6_var.h> 73251881Speter#include <netinet6/ip6_var.h> 74251881Speter#endif /* INET6 */ 75251881Speter 76251881Speter#ifdef INET 77251881Speter#include <netinet/in_pcb.h> 78251881Speter#include <netinet/vinet.h> 79251881Speter#endif 80251881Speter#ifdef INET6 81251881Speter#include <netinet6/in6_pcb.h> 82251881Speter#include <netinet6/vinet6.h> 83251881Speter#endif /* INET6 */ 84251881Speter 85251881Speter#include <net/pfkeyv2.h> 86251881Speter#include <netipsec/keydb.h> 87251881Speter#include <netipsec/key.h> 88251881Speter#include <netipsec/keysock.h> 89251881Speter#include <netipsec/key_debug.h> 90251881Speter 91251881Speter#include <netipsec/ipsec.h> 92251881Speter#ifdef INET6 93251881Speter#include <netipsec/ipsec6.h> 94251881Speter#endif 95251881Speter 96251881Speter#include <netipsec/xform.h> 97251881Speter 98251881Speter#include <machine/stdarg.h> 99251881Speter 100251881Speter/* randomness */ 101251881Speter#include <sys/random.h> 102251881Speter#include <sys/vimage.h> 103251881Speter 104251881Speter#define FULLMASK 0xff 105251881Speter#define _BITS(bytes) ((bytes) << 3) 106251881Speter 107251881Speter/* 108251881Speter * Note on SA reference counting: 109251881Speter * - SAs that are not in DEAD state will have (total external reference + 1) 110251881Speter * following value in reference count field. they cannot be freed and are 111251881Speter * referenced from SA header. 112251881Speter * - SAs that are in DEAD state will have (total external reference) 113251881Speter * in reference count field. they are ready to be freed. reference from 114251881Speter * SA header will be removed in key_delsav(), when the reference count 115251881Speter * field hits 0 (= no external reference other than from SA header. 116251881Speter */ 117251881Speter 118251881Speter#ifdef VIMAGE_GLOBALS 119251881Speteru_int32_t key_debug_level; 120251881Speterstatic u_int key_spi_trycnt; 121251881Speterstatic u_int32_t key_spi_minval; 122251881Speterstatic u_int32_t key_spi_maxval; 123251881Speterstatic u_int32_t policy_id; 124251881Speterstatic u_int key_int_random; 125251881Speterstatic u_int key_larval_lifetime; 126251881Speterstatic int key_blockacq_count; 127251881Speterstatic int key_blockacq_lifetime; 128251881Speterstatic int key_preferred_oldsa; 129251881Speter 130251881Speterstatic u_int32_t acq_seq; 131251881Speter 132251881Speterstatic int ipsec_esp_keymin; 133251881Speterstatic int ipsec_esp_auth; 134251881Speterstatic int ipsec_ah_keymin; 135251881Speter 136251881Speterstatic LIST_HEAD(_sptree, secpolicy) sptree[IPSEC_DIR_MAX]; /* SPD */ 137251881Speterstatic LIST_HEAD(_sahtree, secashead) sahtree; /* SAD */ 138251881Speterstatic LIST_HEAD(_regtree, secreg) regtree[SADB_SATYPE_MAX + 1]; 139251881Speterstatic LIST_HEAD(_acqtree, secacq) acqtree; /* acquiring list */ 140251881Speterstatic LIST_HEAD(_spacqtree, secspacq) spacqtree; /* SP acquiring list */ 141251881Speter#endif /* VIMAGE_GLOBALS */ 142251881Speter 143251881Speterstatic struct mtx sptree_lock; 144251881Speter#define SPTREE_LOCK_INIT() \ 145251881Speter mtx_init(&sptree_lock, "sptree", \ 146251881Speter "fast ipsec security policy database", MTX_DEF) 147251881Speter#define SPTREE_LOCK_DESTROY() mtx_destroy(&sptree_lock) 148251881Speter#define SPTREE_LOCK() mtx_lock(&sptree_lock) 149251881Speter#define SPTREE_UNLOCK() mtx_unlock(&sptree_lock) 150251881Speter#define SPTREE_LOCK_ASSERT() mtx_assert(&sptree_lock, MA_OWNED) 151251881Speter 152251881Speterstatic struct mtx sahtree_lock; 153251881Speter#define SAHTREE_LOCK_INIT() \ 154251881Speter mtx_init(&sahtree_lock, "sahtree", \ 155251881Speter "fast ipsec security association database", MTX_DEF) 156251881Speter#define SAHTREE_LOCK_DESTROY() mtx_destroy(&sahtree_lock) 157251881Speter#define SAHTREE_LOCK() mtx_lock(&sahtree_lock) 158251881Speter#define SAHTREE_UNLOCK() mtx_unlock(&sahtree_lock) 159251881Speter#define SAHTREE_LOCK_ASSERT() mtx_assert(&sahtree_lock, MA_OWNED) 160251881Speter 161251881Speter /* registed list */ 162251881Speterstatic struct mtx regtree_lock; 163251881Speter#define REGTREE_LOCK_INIT() \ 164251881Speter mtx_init(®tree_lock, "regtree", "fast ipsec regtree", MTX_DEF) 165251881Speter#define REGTREE_LOCK_DESTROY() mtx_destroy(®tree_lock) 166251881Speter#define REGTREE_LOCK() mtx_lock(®tree_lock) 167251881Speter#define REGTREE_UNLOCK() mtx_unlock(®tree_lock) 168251881Speter#define REGTREE_LOCK_ASSERT() mtx_assert(®tree_lock, MA_OWNED) 169251881Speter 170251881Speterstatic struct mtx acq_lock; 171251881Speter#define ACQ_LOCK_INIT() \ 172251881Speter mtx_init(&acq_lock, "acqtree", "fast ipsec acquire list", MTX_DEF) 173251881Speter#define ACQ_LOCK_DESTROY() mtx_destroy(&acq_lock) 174251881Speter#define ACQ_LOCK() mtx_lock(&acq_lock) 175251881Speter#define ACQ_UNLOCK() mtx_unlock(&acq_lock) 176251881Speter#define ACQ_LOCK_ASSERT() mtx_assert(&acq_lock, MA_OWNED) 177251881Speter 178251881Speterstatic struct mtx spacq_lock; 179251881Speter#define SPACQ_LOCK_INIT() \ 180251881Speter mtx_init(&spacq_lock, "spacqtree", \ 181251881Speter "fast ipsec security policy acquire list", MTX_DEF) 182251881Speter#define SPACQ_LOCK_DESTROY() mtx_destroy(&spacq_lock) 183251881Speter#define SPACQ_LOCK() mtx_lock(&spacq_lock) 184251881Speter#define SPACQ_UNLOCK() mtx_unlock(&spacq_lock) 185251881Speter#define SPACQ_LOCK_ASSERT() mtx_assert(&spacq_lock, MA_OWNED) 186251881Speter 187251881Speter/* search order for SAs */ 188251881Speterstatic const u_int saorder_state_valid_prefer_old[] = { 189251881Speter SADB_SASTATE_DYING, SADB_SASTATE_MATURE, 190251881Speter}; 191251881Speterstatic const u_int saorder_state_valid_prefer_new[] = { 192251881Speter SADB_SASTATE_MATURE, SADB_SASTATE_DYING, 193251881Speter}; 194251881Speterstatic const u_int saorder_state_alive[] = { 195251881Speter /* except DEAD */ 196251881Speter SADB_SASTATE_MATURE, SADB_SASTATE_DYING, SADB_SASTATE_LARVAL 197251881Speter}; 198251881Speterstatic const u_int saorder_state_any[] = { 199251881Speter SADB_SASTATE_MATURE, SADB_SASTATE_DYING, 200251881Speter SADB_SASTATE_LARVAL, SADB_SASTATE_DEAD 201251881Speter}; 202251881Speter 203251881Speterstatic const int minsize[] = { 204251881Speter sizeof(struct sadb_msg), /* SADB_EXT_RESERVED */ 205251881Speter sizeof(struct sadb_sa), /* SADB_EXT_SA */ 206251881Speter sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_CURRENT */ 207251881Speter sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_HARD */ 208251881Speter sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_SOFT */ 209251881Speter sizeof(struct sadb_address), /* SADB_EXT_ADDRESS_SRC */ 210251881Speter sizeof(struct sadb_address), /* SADB_EXT_ADDRESS_DST */ 211251881Speter sizeof(struct sadb_address), /* SADB_EXT_ADDRESS_PROXY */ 212251881Speter sizeof(struct sadb_key), /* SADB_EXT_KEY_AUTH */ 213251881Speter sizeof(struct sadb_key), /* SADB_EXT_KEY_ENCRYPT */ 214251881Speter sizeof(struct sadb_ident), /* SADB_EXT_IDENTITY_SRC */ 215251881Speter sizeof(struct sadb_ident), /* SADB_EXT_IDENTITY_DST */ 216251881Speter sizeof(struct sadb_sens), /* SADB_EXT_SENSITIVITY */ 217251881Speter sizeof(struct sadb_prop), /* SADB_EXT_PROPOSAL */ 218251881Speter sizeof(struct sadb_supported), /* SADB_EXT_SUPPORTED_AUTH */ 219251881Speter sizeof(struct sadb_supported), /* SADB_EXT_SUPPORTED_ENCRYPT */ 220251881Speter sizeof(struct sadb_spirange), /* SADB_EXT_SPIRANGE */ 221251881Speter 0, /* SADB_X_EXT_KMPRIVATE */ 222251881Speter sizeof(struct sadb_x_policy), /* SADB_X_EXT_POLICY */ 223251881Speter sizeof(struct sadb_x_sa2), /* SADB_X_SA2 */ 224251881Speter sizeof(struct sadb_x_nat_t_type),/* SADB_X_EXT_NAT_T_TYPE */ 225251881Speter sizeof(struct sadb_x_nat_t_port),/* SADB_X_EXT_NAT_T_SPORT */ 226251881Speter sizeof(struct sadb_x_nat_t_port),/* SADB_X_EXT_NAT_T_DPORT */ 227251881Speter sizeof(struct sadb_address), /* SADB_X_EXT_NAT_T_OAI */ 228251881Speter sizeof(struct sadb_address), /* SADB_X_EXT_NAT_T_OAR */ 229251881Speter sizeof(struct sadb_x_nat_t_frag),/* SADB_X_EXT_NAT_T_FRAG */ 230251881Speter}; 231251881Speterstatic const int maxsize[] = { 232251881Speter sizeof(struct sadb_msg), /* SADB_EXT_RESERVED */ 233251881Speter sizeof(struct sadb_sa), /* SADB_EXT_SA */ 234251881Speter sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_CURRENT */ 235251881Speter sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_HARD */ 236251881Speter sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_SOFT */ 237251881Speter 0, /* SADB_EXT_ADDRESS_SRC */ 238251881Speter 0, /* SADB_EXT_ADDRESS_DST */ 239251881Speter 0, /* SADB_EXT_ADDRESS_PROXY */ 240251881Speter 0, /* SADB_EXT_KEY_AUTH */ 241251881Speter 0, /* SADB_EXT_KEY_ENCRYPT */ 242251881Speter 0, /* SADB_EXT_IDENTITY_SRC */ 243251881Speter 0, /* SADB_EXT_IDENTITY_DST */ 244251881Speter 0, /* SADB_EXT_SENSITIVITY */ 245251881Speter 0, /* SADB_EXT_PROPOSAL */ 246251881Speter 0, /* SADB_EXT_SUPPORTED_AUTH */ 247251881Speter 0, /* SADB_EXT_SUPPORTED_ENCRYPT */ 248251881Speter sizeof(struct sadb_spirange), /* SADB_EXT_SPIRANGE */ 249251881Speter 0, /* SADB_X_EXT_KMPRIVATE */ 250251881Speter 0, /* SADB_X_EXT_POLICY */ 251251881Speter sizeof(struct sadb_x_sa2), /* SADB_X_SA2 */ 252251881Speter sizeof(struct sadb_x_nat_t_type),/* SADB_X_EXT_NAT_T_TYPE */ 253251881Speter sizeof(struct sadb_x_nat_t_port),/* SADB_X_EXT_NAT_T_SPORT */ 254251881Speter sizeof(struct sadb_x_nat_t_port),/* SADB_X_EXT_NAT_T_DPORT */ 255251881Speter 0, /* SADB_X_EXT_NAT_T_OAI */ 256251881Speter 0, /* SADB_X_EXT_NAT_T_OAR */ 257251881Speter sizeof(struct sadb_x_nat_t_frag),/* SADB_X_EXT_NAT_T_FRAG */ 258251881Speter}; 259251881Speter 260251881Speter#ifdef SYSCTL_DECL 261251881SpeterSYSCTL_DECL(_net_key); 262251881Speter#endif 263251881Speter 264251881SpeterSYSCTL_V_INT(V_NET, vnet_ipsec,_net_key, KEYCTL_DEBUG_LEVEL, debug, 265251881Speter CTLFLAG_RW, key_debug_level, 0, ""); 266251881Speter 267251881Speter/* max count of trial for the decision of spi value */ 268251881SpeterSYSCTL_V_INT(V_NET, vnet_ipsec,_net_key, KEYCTL_SPI_TRY, spi_trycnt, 269251881Speter CTLFLAG_RW, key_spi_trycnt, 0, ""); 270251881Speter 271251881Speter/* minimum spi value to allocate automatically. */ 272251881SpeterSYSCTL_V_INT(V_NET, vnet_ipsec, _net_key, KEYCTL_SPI_MIN_VALUE, 273251881Speter spi_minval, CTLFLAG_RW, key_spi_minval, 0, ""); 274251881Speter 275251881Speter/* maximun spi value to allocate automatically. */ 276251881SpeterSYSCTL_V_INT(V_NET, vnet_ipsec, _net_key, KEYCTL_SPI_MAX_VALUE, 277251881Speter spi_maxval, CTLFLAG_RW, key_spi_maxval, 0, ""); 278251881Speter 279251881Speter/* interval to initialize randseed */ 280251881SpeterSYSCTL_V_INT(V_NET, vnet_ipsec, _net_key, KEYCTL_RANDOM_INT, 281251881Speter int_random, CTLFLAG_RW, key_int_random, 0, ""); 282251881Speter 283251881Speter/* lifetime for larval SA */ 284251881SpeterSYSCTL_V_INT(V_NET, vnet_ipsec, _net_key, KEYCTL_LARVAL_LIFETIME, 285251881Speter larval_lifetime, CTLFLAG_RW, key_larval_lifetime, 0, ""); 286251881Speter 287251881Speter/* counter for blocking to send SADB_ACQUIRE to IKEd */ 288251881SpeterSYSCTL_V_INT(V_NET, vnet_ipsec, _net_key, KEYCTL_BLOCKACQ_COUNT, 289251881Speter blockacq_count, CTLFLAG_RW, key_blockacq_count, 0, ""); 290251881Speter 291251881Speter/* lifetime for blocking to send SADB_ACQUIRE to IKEd */ 292251881SpeterSYSCTL_V_INT(V_NET, vnet_ipsec, _net_key, KEYCTL_BLOCKACQ_LIFETIME, 293251881Speter blockacq_lifetime, CTLFLAG_RW, key_blockacq_lifetime, 0, ""); 294251881Speter 295251881Speter/* ESP auth */ 296251881SpeterSYSCTL_V_INT(V_NET, vnet_ipsec, _net_key, KEYCTL_ESP_AUTH, esp_auth, 297251881Speter CTLFLAG_RW, ipsec_esp_auth, 0, ""); 298251881Speter 299251881Speter/* minimum ESP key length */ 300251881SpeterSYSCTL_V_INT(V_NET, vnet_ipsec, _net_key, KEYCTL_ESP_KEYMIN, 301251881Speter esp_keymin, CTLFLAG_RW, ipsec_esp_keymin, 0, ""); 302251881Speter 303251881Speter/* minimum AH key length */ 304251881SpeterSYSCTL_V_INT(V_NET, vnet_ipsec, _net_key, KEYCTL_AH_KEYMIN, ah_keymin, 305251881Speter CTLFLAG_RW, ipsec_ah_keymin, 0, ""); 306251881Speter 307251881Speter/* perfered old SA rather than new SA */ 308251881SpeterSYSCTL_V_INT(V_NET, vnet_ipsec, _net_key, KEYCTL_PREFERED_OLDSA, 309251881Speter preferred_oldsa, CTLFLAG_RW, key_preferred_oldsa, 0, ""); 310251881Speter 311251881Speter#define __LIST_CHAINED(elm) \ 312251881Speter (!((elm)->chain.le_next == NULL && (elm)->chain.le_prev == NULL)) 313251881Speter#define LIST_INSERT_TAIL(head, elm, type, field) \ 314251881Speterdo {\ 315251881Speter struct type *curelm = LIST_FIRST(head); \ 316251881Speter if (curelm == NULL) {\ 317251881Speter LIST_INSERT_HEAD(head, elm, field); \ 318251881Speter } else { \ 319251881Speter while (LIST_NEXT(curelm, field)) \ 320251881Speter curelm = LIST_NEXT(curelm, field);\ 321251881Speter LIST_INSERT_AFTER(curelm, elm, field);\ 322251881Speter }\ 323251881Speter} while (0) 324251881Speter 325251881Speter#define KEY_CHKSASTATE(head, sav, name) \ 326251881Speterdo { \ 327251881Speter if ((head) != (sav)) { \ 328251881Speter ipseclog((LOG_DEBUG, "%s: state mismatched (TREE=%d SA=%d)\n", \ 329251881Speter (name), (head), (sav))); \ 330251881Speter continue; \ 331251881Speter } \ 332251881Speter} while (0) 333251881Speter 334251881Speter#define KEY_CHKSPDIR(head, sp, name) \ 335251881Speterdo { \ 336251881Speter if ((head) != (sp)) { \ 337251881Speter ipseclog((LOG_DEBUG, "%s: direction mismatched (TREE=%d SP=%d), " \ 338251881Speter "anyway continue.\n", \ 339251881Speter (name), (head), (sp))); \ 340251881Speter } \ 341251881Speter} while (0) 342251881Speter 343251881SpeterMALLOC_DEFINE(M_IPSEC_SA, "secasvar", "ipsec security association"); 344251881SpeterMALLOC_DEFINE(M_IPSEC_SAH, "sahead", "ipsec sa head"); 345251881SpeterMALLOC_DEFINE(M_IPSEC_SP, "ipsecpolicy", "ipsec security policy"); 346251881SpeterMALLOC_DEFINE(M_IPSEC_SR, "ipsecrequest", "ipsec security request"); 347251881SpeterMALLOC_DEFINE(M_IPSEC_MISC, "ipsec-misc", "ipsec miscellaneous"); 348251881SpeterMALLOC_DEFINE(M_IPSEC_SAQ, "ipsec-saq", "ipsec sa acquire"); 349251881SpeterMALLOC_DEFINE(M_IPSEC_SAR, "ipsec-reg", "ipsec sa acquire"); 350251881Speter 351251881Speter/* 352251881Speter * set parameters into secpolicyindex buffer. 353251881Speter * Must allocate secpolicyindex buffer passed to this function. 354251881Speter */ 355251881Speter#define KEY_SETSECSPIDX(_dir, s, d, ps, pd, ulp, idx) \ 356251881Speterdo { \ 357251881Speter bzero((idx), sizeof(struct secpolicyindex)); \ 358251881Speter (idx)->dir = (_dir); \ 359251881Speter (idx)->prefs = (ps); \ 360251881Speter (idx)->prefd = (pd); \ 361251881Speter (idx)->ul_proto = (ulp); \ 362251881Speter bcopy((s), &(idx)->src, ((const struct sockaddr *)(s))->sa_len); \ 363251881Speter bcopy((d), &(idx)->dst, ((const struct sockaddr *)(d))->sa_len); \ 364251881Speter} while (0) 365251881Speter 366251881Speter/* 367251881Speter * set parameters into secasindex buffer. 368251881Speter * Must allocate secasindex buffer before calling this function. 369251881Speter */ 370251881Speter#define KEY_SETSECASIDX(p, m, r, s, d, idx) \ 371251881Speterdo { \ 372251881Speter bzero((idx), sizeof(struct secasindex)); \ 373251881Speter (idx)->proto = (p); \ 374251881Speter (idx)->mode = (m); \ 375251881Speter (idx)->reqid = (r); \ 376251881Speter bcopy((s), &(idx)->src, ((const struct sockaddr *)(s))->sa_len); \ 377251881Speter bcopy((d), &(idx)->dst, ((const struct sockaddr *)(d))->sa_len); \ 378251881Speter} while (0) 379251881Speter 380251881Speter/* key statistics */ 381251881Speterstruct _keystat { 382251881Speter u_long getspi_count; /* the avarage of count to try to get new SPI */ 383251881Speter} keystat; 384251881Speter 385251881Speterstruct sadb_msghdr { 386251881Speter struct sadb_msg *msg; 387251881Speter struct sadb_ext *ext[SADB_EXT_MAX + 1]; 388251881Speter int extoff[SADB_EXT_MAX + 1]; 389251881Speter int extlen[SADB_EXT_MAX + 1]; 390251881Speter}; 391251881Speter 392251881Speterstatic struct secasvar *key_allocsa_policy __P((const struct secasindex *)); 393251881Speterstatic void key_freesp_so __P((struct secpolicy **)); 394251881Speterstatic struct secasvar *key_do_allocsa_policy __P((struct secashead *, u_int)); 395251881Speterstatic void key_delsp __P((struct secpolicy *)); 396251881Speterstatic struct secpolicy *key_getsp __P((struct secpolicyindex *)); 397251881Speterstatic void _key_delsp(struct secpolicy *sp); 398251881Speterstatic struct secpolicy *key_getspbyid __P((u_int32_t)); 399251881Speterstatic u_int32_t key_newreqid __P((void)); 400251881Speterstatic struct mbuf *key_gather_mbuf __P((struct mbuf *, 401251881Speter const struct sadb_msghdr *, int, int, ...)); 402251881Speterstatic int key_spdadd __P((struct socket *, struct mbuf *, 403251881Speter const struct sadb_msghdr *)); 404251881Speterstatic u_int32_t key_getnewspid __P((void)); 405251881Speterstatic int key_spddelete __P((struct socket *, struct mbuf *, 406251881Speter const struct sadb_msghdr *)); 407251881Speterstatic int key_spddelete2 __P((struct socket *, struct mbuf *, 408251881Speter const struct sadb_msghdr *)); 409251881Speterstatic int key_spdget __P((struct socket *, struct mbuf *, 410251881Speter const struct sadb_msghdr *)); 411251881Speterstatic int key_spdflush __P((struct socket *, struct mbuf *, 412251881Speter const struct sadb_msghdr *)); 413251881Speterstatic int key_spddump __P((struct socket *, struct mbuf *, 414251881Speter const struct sadb_msghdr *)); 415251881Speterstatic struct mbuf *key_setdumpsp __P((struct secpolicy *, 416251881Speter u_int8_t, u_int32_t, u_int32_t)); 417251881Speterstatic u_int key_getspreqmsglen __P((struct secpolicy *)); 418251881Speterstatic int key_spdexpire __P((struct secpolicy *)); 419251881Speterstatic struct secashead *key_newsah __P((struct secasindex *)); 420251881Speterstatic void key_delsah __P((struct secashead *)); 421251881Speterstatic struct secasvar *key_newsav __P((struct mbuf *, 422251881Speter const struct sadb_msghdr *, struct secashead *, int *, 423251881Speter const char*, int)); 424251881Speter#define KEY_NEWSAV(m, sadb, sah, e) \ 425251881Speter key_newsav(m, sadb, sah, e, __FILE__, __LINE__) 426251881Speterstatic void key_delsav __P((struct secasvar *)); 427251881Speterstatic struct secashead *key_getsah __P((struct secasindex *)); 428251881Speterstatic struct secasvar *key_checkspidup __P((struct secasindex *, u_int32_t)); 429251881Speterstatic struct secasvar *key_getsavbyspi __P((struct secashead *, u_int32_t)); 430251881Speterstatic int key_setsaval __P((struct secasvar *, struct mbuf *, 431251881Speter const struct sadb_msghdr *)); 432251881Speterstatic int key_mature __P((struct secasvar *)); 433251881Speterstatic struct mbuf *key_setdumpsa __P((struct secasvar *, u_int8_t, 434251881Speter u_int8_t, u_int32_t, u_int32_t)); 435251881Speterstatic struct mbuf *key_setsadbmsg __P((u_int8_t, u_int16_t, u_int8_t, 436251881Speter u_int32_t, pid_t, u_int16_t)); 437251881Speterstatic struct mbuf *key_setsadbsa __P((struct secasvar *)); 438251881Speterstatic struct mbuf *key_setsadbaddr __P((u_int16_t, 439251881Speter const struct sockaddr *, u_int8_t, u_int16_t)); 440251881Speter#ifdef IPSEC_NAT_T 441251881Speterstatic struct mbuf *key_setsadbxport(u_int16_t, u_int16_t); 442251881Speterstatic struct mbuf *key_setsadbxtype(u_int16_t); 443251881Speter#endif 444251881Speterstatic void key_porttosaddr(struct sockaddr *, u_int16_t); 445251881Speter#define KEY_PORTTOSADDR(saddr, port) \ 446251881Speter key_porttosaddr((struct sockaddr *)(saddr), (port)) 447251881Speterstatic struct mbuf *key_setsadbxsa2 __P((u_int8_t, u_int32_t, u_int32_t)); 448251881Speterstatic struct mbuf *key_setsadbxpolicy __P((u_int16_t, u_int8_t, 449251881Speter u_int32_t)); 450251881Speterstatic struct seckey *key_dup_keymsg(const struct sadb_key *, u_int, 451251881Speter struct malloc_type *); 452251881Speterstatic struct seclifetime *key_dup_lifemsg(const struct sadb_lifetime *src, 453251881Speter struct malloc_type *type); 454251881Speter#ifdef INET6 455251881Speterstatic int key_ismyaddr6 __P((struct sockaddr_in6 *)); 456251881Speter#endif 457251881Speter 458251881Speter/* flags for key_cmpsaidx() */ 459251881Speter#define CMP_HEAD 1 /* protocol, addresses. */ 460251881Speter#define CMP_MODE_REQID 2 /* additionally HEAD, reqid, mode. */ 461251881Speter#define CMP_REQID 3 /* additionally HEAD, reaid. */ 462251881Speter#define CMP_EXACTLY 4 /* all elements. */ 463251881Speterstatic int key_cmpsaidx 464251881Speter __P((const struct secasindex *, const struct secasindex *, int)); 465251881Speter 466251881Speterstatic int key_cmpspidx_exactly 467251881Speter __P((struct secpolicyindex *, struct secpolicyindex *)); 468251881Speterstatic int key_cmpspidx_withmask 469251881Speter __P((struct secpolicyindex *, struct secpolicyindex *)); 470251881Speterstatic int key_sockaddrcmp __P((const struct sockaddr *, const struct sockaddr *, int)); 471251881Speterstatic int key_bbcmp __P((const void *, const void *, u_int)); 472251881Speterstatic u_int16_t key_satype2proto __P((u_int8_t)); 473251881Speterstatic u_int8_t key_proto2satype __P((u_int16_t)); 474251881Speter 475251881Speterstatic int key_getspi __P((struct socket *, struct mbuf *, 476251881Speter const struct sadb_msghdr *)); 477251881Speterstatic u_int32_t key_do_getnewspi __P((struct sadb_spirange *, 478251881Speter struct secasindex *)); 479251881Speterstatic int key_update __P((struct socket *, struct mbuf *, 480251881Speter const struct sadb_msghdr *)); 481251881Speter#ifdef IPSEC_DOSEQCHECK 482251881Speterstatic struct secasvar *key_getsavbyseq __P((struct secashead *, u_int32_t)); 483251881Speter#endif 484251881Speterstatic int key_add __P((struct socket *, struct mbuf *, 485251881Speter const struct sadb_msghdr *)); 486251881Speterstatic int key_setident __P((struct secashead *, struct mbuf *, 487251881Speter const struct sadb_msghdr *)); 488251881Speterstatic struct mbuf *key_getmsgbuf_x1 __P((struct mbuf *, 489251881Speter const struct sadb_msghdr *)); 490251881Speterstatic int key_delete __P((struct socket *, struct mbuf *, 491251881Speter const struct sadb_msghdr *)); 492251881Speterstatic int key_get __P((struct socket *, struct mbuf *, 493251881Speter const struct sadb_msghdr *)); 494251881Speter 495251881Speterstatic void key_getcomb_setlifetime __P((struct sadb_comb *)); 496251881Speterstatic struct mbuf *key_getcomb_esp __P((void)); 497251881Speterstatic struct mbuf *key_getcomb_ah __P((void)); 498251881Speterstatic struct mbuf *key_getcomb_ipcomp __P((void)); 499251881Speterstatic struct mbuf *key_getprop __P((const struct secasindex *)); 500251881Speter 501251881Speterstatic int key_acquire __P((const struct secasindex *, struct secpolicy *)); 502251881Speterstatic struct secacq *key_newacq __P((const struct secasindex *)); 503251881Speterstatic struct secacq *key_getacq __P((const struct secasindex *)); 504251881Speterstatic struct secacq *key_getacqbyseq __P((u_int32_t)); 505251881Speterstatic struct secspacq *key_newspacq __P((struct secpolicyindex *)); 506251881Speterstatic struct secspacq *key_getspacq __P((struct secpolicyindex *)); 507251881Speterstatic int key_acquire2 __P((struct socket *, struct mbuf *, 508251881Speter const struct sadb_msghdr *)); 509251881Speterstatic int key_register __P((struct socket *, struct mbuf *, 510251881Speter const struct sadb_msghdr *)); 511251881Speterstatic int key_expire __P((struct secasvar *)); 512251881Speterstatic int key_flush __P((struct socket *, struct mbuf *, 513251881Speter const struct sadb_msghdr *)); 514251881Speterstatic int key_dump __P((struct socket *, struct mbuf *, 515251881Speter const struct sadb_msghdr *)); 516251881Speterstatic int key_promisc __P((struct socket *, struct mbuf *, 517251881Speter const struct sadb_msghdr *)); 518251881Speterstatic int key_senderror __P((struct socket *, struct mbuf *, int)); 519251881Speterstatic int key_validate_ext __P((const struct sadb_ext *, int)); 520251881Speterstatic int key_align __P((struct mbuf *, struct sadb_msghdr *)); 521251881Speterstatic struct mbuf *key_setlifetime(struct seclifetime *src, 522251881Speter u_int16_t exttype); 523251881Speterstatic struct mbuf *key_setkey(struct seckey *src, u_int16_t exttype); 524251881Speter 525251881Speter#if 0 526251881Speterstatic const char *key_getfqdn __P((void)); 527251881Speterstatic const char *key_getuserfqdn __P((void)); 528251881Speter#endif 529251881Speterstatic void key_sa_chgstate __P((struct secasvar *, u_int8_t)); 530251881Speterstatic struct mbuf *key_alloc_mbuf __P((int)); 531251881Speter 532251881Speterstatic __inline void 533251881Spetersa_initref(struct secasvar *sav) 534251881Speter{ 535251881Speter 536251881Speter refcount_init(&sav->refcnt, 1); 537251881Speter} 538251881Speterstatic __inline void 539251881Spetersa_addref(struct secasvar *sav) 540251881Speter{ 541251881Speter 542251881Speter refcount_acquire(&sav->refcnt); 543251881Speter IPSEC_ASSERT(sav->refcnt != 0, ("SA refcnt overflow")); 544251881Speter} 545251881Speterstatic __inline int 546251881Spetersa_delref(struct secasvar *sav) 547251881Speter{ 548251881Speter 549251881Speter IPSEC_ASSERT(sav->refcnt > 0, ("SA refcnt underflow")); 550251881Speter return (refcount_release(&sav->refcnt)); 551251881Speter} 552251881Speter 553251881Speter#define SP_ADDREF(p) do { \ 554251881Speter (p)->refcnt++; \ 555251881Speter IPSEC_ASSERT((p)->refcnt != 0, ("SP refcnt overflow")); \ 556251881Speter} while (0) 557251881Speter#define SP_DELREF(p) do { \ 558251881Speter IPSEC_ASSERT((p)->refcnt > 0, ("SP refcnt underflow")); \ 559251881Speter (p)->refcnt--; \ 560251881Speter} while (0) 561251881Speter 562251881Speter 563251881Speter/* 564251881Speter * Update the refcnt while holding the SPTREE lock. 565251881Speter */ 566251881Spetervoid 567251881Speterkey_addref(struct secpolicy *sp) 568251881Speter{ 569251881Speter SPTREE_LOCK(); 570251881Speter SP_ADDREF(sp); 571251881Speter SPTREE_UNLOCK(); 572251881Speter} 573251881Speter 574251881Speter/* 575251881Speter * Return 0 when there are known to be no SP's for the specified 576251881Speter * direction. Otherwise return 1. This is used by IPsec code 577251881Speter * to optimize performance. 578251881Speter */ 579251881Speterint 580251881Speterkey_havesp(u_int dir) 581251881Speter{ 582251881Speter INIT_VNET_IPSEC(curvnet); 583251881Speter 584251881Speter return (dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND ? 585251881Speter LIST_FIRST(&V_sptree[dir]) != NULL : 1); 586251881Speter} 587251881Speter 588251881Speter/* %%% IPsec policy management */ 589251881Speter/* 590251881Speter * allocating a SP for OUTBOUND or INBOUND packet. 591251881Speter * Must call key_freesp() later. 592251881Speter * OUT: NULL: not found 593251881Speter * others: found and return the pointer. 594251881Speter */ 595251881Speterstruct secpolicy * 596251881Speterkey_allocsp(struct secpolicyindex *spidx, u_int dir, const char* where, int tag) 597251881Speter{ 598251881Speter INIT_VNET_IPSEC(curvnet); 599251881Speter struct secpolicy *sp; 600251881Speter 601251881Speter IPSEC_ASSERT(spidx != NULL, ("null spidx")); 602251881Speter IPSEC_ASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND, 603251881Speter ("invalid direction %u", dir)); 604251881Speter 605251881Speter KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 606251881Speter printf("DP %s from %s:%u\n", __func__, where, tag)); 607251881Speter 608251881Speter /* get a SP entry */ 609251881Speter KEYDEBUG(KEYDEBUG_IPSEC_DATA, 610251881Speter printf("*** objects\n"); 611251881Speter kdebug_secpolicyindex(spidx)); 612251881Speter 613251881Speter SPTREE_LOCK(); 614251881Speter LIST_FOREACH(sp, &V_sptree[dir], chain) { 615251881Speter KEYDEBUG(KEYDEBUG_IPSEC_DATA, 616251881Speter printf("*** in SPD\n"); 617251881Speter kdebug_secpolicyindex(&sp->spidx)); 618251881Speter 619251881Speter if (sp->state == IPSEC_SPSTATE_DEAD) 620251881Speter continue; 621251881Speter if (key_cmpspidx_withmask(&sp->spidx, spidx)) 622251881Speter goto found; 623251881Speter } 624251881Speter sp = NULL; 625251881Speterfound: 626251881Speter if (sp) { 627251881Speter /* sanity check */ 628251881Speter KEY_CHKSPDIR(sp->spidx.dir, dir, __func__); 629251881Speter 630251881Speter /* found a SPD entry */ 631251881Speter sp->lastused = time_second; 632251881Speter SP_ADDREF(sp); 633251881Speter } 634251881Speter SPTREE_UNLOCK(); 635251881Speter 636251881Speter KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 637251881Speter printf("DP %s return SP:%p (ID=%u) refcnt %u\n", __func__, 638251881Speter sp, sp ? sp->id : 0, sp ? sp->refcnt : 0)); 639251881Speter return sp; 640251881Speter} 641251881Speter 642251881Speter/* 643251881Speter * allocating a SP for OUTBOUND or INBOUND packet. 644251881Speter * Must call key_freesp() later. 645251881Speter * OUT: NULL: not found 646251881Speter * others: found and return the pointer. 647251881Speter */ 648251881Speterstruct secpolicy * 649251881Speterkey_allocsp2(u_int32_t spi, 650251881Speter union sockaddr_union *dst, 651251881Speter u_int8_t proto, 652251881Speter u_int dir, 653251881Speter const char* where, int tag) 654251881Speter{ 655251881Speter INIT_VNET_IPSEC(curvnet); 656251881Speter struct secpolicy *sp; 657251881Speter 658251881Speter IPSEC_ASSERT(dst != NULL, ("null dst")); 659251881Speter IPSEC_ASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND, 660251881Speter ("invalid direction %u", dir)); 661251881Speter 662251881Speter KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 663251881Speter printf("DP %s from %s:%u\n", __func__, where, tag)); 664251881Speter 665251881Speter /* get a SP entry */ 666251881Speter KEYDEBUG(KEYDEBUG_IPSEC_DATA, 667251881Speter printf("*** objects\n"); 668251881Speter printf("spi %u proto %u dir %u\n", spi, proto, dir); 669251881Speter kdebug_sockaddr(&dst->sa)); 670251881Speter 671251881Speter SPTREE_LOCK(); 672251881Speter LIST_FOREACH(sp, &V_sptree[dir], chain) { 673251881Speter KEYDEBUG(KEYDEBUG_IPSEC_DATA, 674251881Speter printf("*** in SPD\n"); 675251881Speter kdebug_secpolicyindex(&sp->spidx)); 676251881Speter 677251881Speter if (sp->state == IPSEC_SPSTATE_DEAD) 678251881Speter continue; 679251881Speter /* compare simple values, then dst address */ 680251881Speter if (sp->spidx.ul_proto != proto) 681251881Speter continue; 682251881Speter /* NB: spi's must exist and match */ 683251881Speter if (!sp->req || !sp->req->sav || sp->req->sav->spi != spi) 684251881Speter continue; 685251881Speter if (key_sockaddrcmp(&sp->spidx.dst.sa, &dst->sa, 1) == 0) 686251881Speter goto found; 687251881Speter } 688251881Speter sp = NULL; 689251881Speterfound: 690251881Speter if (sp) { 691251881Speter /* sanity check */ 692251881Speter KEY_CHKSPDIR(sp->spidx.dir, dir, __func__); 693251881Speter 694251881Speter /* found a SPD entry */ 695251881Speter sp->lastused = time_second; 696251881Speter SP_ADDREF(sp); 697251881Speter } 698251881Speter SPTREE_UNLOCK(); 699251881Speter 700251881Speter KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 701251881Speter printf("DP %s return SP:%p (ID=%u) refcnt %u\n", __func__, 702251881Speter sp, sp ? sp->id : 0, sp ? sp->refcnt : 0)); 703251881Speter return sp; 704251881Speter} 705251881Speter 706251881Speter#if 0 707251881Speter/* 708251881Speter * return a policy that matches this particular inbound packet. 709251881Speter * XXX slow 710251881Speter */ 711251881Speterstruct secpolicy * 712251881Speterkey_gettunnel(const struct sockaddr *osrc, 713251881Speter const struct sockaddr *odst, 714251881Speter const struct sockaddr *isrc, 715251881Speter const struct sockaddr *idst, 716251881Speter const char* where, int tag) 717251881Speter{ 718251881Speter INIT_VNET_IPSEC(curvnet); 719251881Speter struct secpolicy *sp; 720251881Speter const int dir = IPSEC_DIR_INBOUND; 721251881Speter struct ipsecrequest *r1, *r2, *p; 722251881Speter struct secpolicyindex spidx; 723251881Speter 724251881Speter KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 725251881Speter printf("DP %s from %s:%u\n", __func__, where, tag)); 726251881Speter 727251881Speter if (isrc->sa_family != idst->sa_family) { 728251881Speter ipseclog((LOG_ERR, "%s: protocol family mismatched %d != %d\n.", 729251881Speter __func__, isrc->sa_family, idst->sa_family)); 730251881Speter sp = NULL; 731251881Speter goto done; 732251881Speter } 733251881Speter 734251881Speter SPTREE_LOCK(); 735251881Speter LIST_FOREACH(sp, &V_sptree[dir], chain) { 736251881Speter if (sp->state == IPSEC_SPSTATE_DEAD) 737251881Speter continue; 738251881Speter 739251881Speter r1 = r2 = NULL; 740251881Speter for (p = sp->req; p; p = p->next) { 741251881Speter if (p->saidx.mode != IPSEC_MODE_TUNNEL) 742251881Speter continue; 743251881Speter 744251881Speter r1 = r2; 745251881Speter r2 = p; 746251881Speter 747251881Speter if (!r1) { 748251881Speter /* here we look at address matches only */ 749251881Speter spidx = sp->spidx; 750251881Speter if (isrc->sa_len > sizeof(spidx.src) || 751251881Speter idst->sa_len > sizeof(spidx.dst)) 752251881Speter continue; 753251881Speter bcopy(isrc, &spidx.src, isrc->sa_len); 754251881Speter bcopy(idst, &spidx.dst, idst->sa_len); 755251881Speter if (!key_cmpspidx_withmask(&sp->spidx, &spidx)) 756251881Speter continue; 757251881Speter } else { 758251881Speter if (key_sockaddrcmp(&r1->saidx.src.sa, isrc, 0) || 759251881Speter key_sockaddrcmp(&r1->saidx.dst.sa, idst, 0)) 760251881Speter continue; 761251881Speter } 762251881Speter 763251881Speter if (key_sockaddrcmp(&r2->saidx.src.sa, osrc, 0) || 764251881Speter key_sockaddrcmp(&r2->saidx.dst.sa, odst, 0)) 765251881Speter continue; 766251881Speter 767251881Speter goto found; 768251881Speter } 769251881Speter } 770251881Speter sp = NULL; 771251881Speterfound: 772251881Speter if (sp) { 773251881Speter sp->lastused = time_second; 774251881Speter SP_ADDREF(sp); 775251881Speter } 776251881Speter SPTREE_UNLOCK(); 777251881Speterdone: 778251881Speter KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 779251881Speter printf("DP %s return SP:%p (ID=%u) refcnt %u\n", __func__, 780251881Speter sp, sp ? sp->id : 0, sp ? sp->refcnt : 0)); 781251881Speter return sp; 782251881Speter} 783251881Speter#endif 784251881Speter 785251881Speter/* 786251881Speter * allocating an SA entry for an *OUTBOUND* packet. 787251881Speter * checking each request entries in SP, and acquire an SA if need. 788251881Speter * OUT: 0: there are valid requests. 789251881Speter * ENOENT: policy may be valid, but SA with REQUIRE is on acquiring. 790251881Speter */ 791251881Speterint 792251881Speterkey_checkrequest(struct ipsecrequest *isr, const struct secasindex *saidx) 793251881Speter{ 794251881Speter INIT_VNET_IPSEC(curvnet); 795251881Speter u_int level; 796251881Speter int error; 797251881Speter 798251881Speter IPSEC_ASSERT(isr != NULL, ("null isr")); 799251881Speter IPSEC_ASSERT(saidx != NULL, ("null saidx")); 800251881Speter IPSEC_ASSERT(saidx->mode == IPSEC_MODE_TRANSPORT || 801251881Speter saidx->mode == IPSEC_MODE_TUNNEL, 802251881Speter ("unexpected policy %u", saidx->mode)); 803251881Speter 804251881Speter /* 805251881Speter * XXX guard against protocol callbacks from the crypto 806251881Speter * thread as they reference ipsecrequest.sav which we 807251881Speter * temporarily null out below. Need to rethink how we 808251881Speter * handle bundled SA's in the callback thread. 809251881Speter */ 810251881Speter IPSECREQUEST_LOCK_ASSERT(isr); 811251881Speter 812251881Speter /* get current level */ 813251881Speter level = ipsec_get_reqlevel(isr); 814251881Speter#if 0 815251881Speter /* 816251881Speter * We do allocate new SA only if the state of SA in the holder is 817251881Speter * SADB_SASTATE_DEAD. The SA for outbound must be the oldest. 818251881Speter */ 819251881Speter if (isr->sav != NULL) { 820251881Speter if (isr->sav->sah == NULL) 821251881Speter panic("%s: sah is null.\n", __func__); 822251881Speter if (isr->sav == (struct secasvar *)LIST_FIRST( 823251881Speter &isr->sav->sah->savtree[SADB_SASTATE_DEAD])) { 824251881Speter KEY_FREESAV(&isr->sav); 825251881Speter isr->sav = NULL; 826251881Speter } 827251881Speter } 828251881Speter#else 829251881Speter /* 830251881Speter * we free any SA stashed in the IPsec request because a different 831251881Speter * SA may be involved each time this request is checked, either 832251881Speter * because new SAs are being configured, or this request is 833251881Speter * associated with an unconnected datagram socket, or this request 834251881Speter * is associated with a system default policy. 835251881Speter * 836251881Speter * The operation may have negative impact to performance. We may 837251881Speter * want to check cached SA carefully, rather than picking new SA 838251881Speter * every time. 839251881Speter */ 840251881Speter if (isr->sav != NULL) { 841251881Speter KEY_FREESAV(&isr->sav); 842251881Speter isr->sav = NULL; 843251881Speter } 844251881Speter#endif 845251881Speter 846251881Speter /* 847251881Speter * new SA allocation if no SA found. 848251881Speter * key_allocsa_policy should allocate the oldest SA available. 849251881Speter * See key_do_allocsa_policy(), and draft-jenkins-ipsec-rekeying-03.txt. 850251881Speter */ 851251881Speter if (isr->sav == NULL) 852251881Speter isr->sav = key_allocsa_policy(saidx); 853251881Speter 854251881Speter /* When there is SA. */ 855251881Speter if (isr->sav != NULL) { 856251881Speter if (isr->sav->state != SADB_SASTATE_MATURE && 857251881Speter isr->sav->state != SADB_SASTATE_DYING) 858251881Speter return EINVAL; 859251881Speter return 0; 860251881Speter } 861251881Speter 862251881Speter /* there is no SA */ 863251881Speter error = key_acquire(saidx, isr->sp); 864251881Speter if (error != 0) { 865251881Speter /* XXX What should I do ? */ 866251881Speter ipseclog((LOG_DEBUG, "%s: error %d returned from key_acquire\n", 867251881Speter __func__, error)); 868251881Speter return error; 869251881Speter } 870251881Speter 871251881Speter if (level != IPSEC_LEVEL_REQUIRE) { 872251881Speter /* XXX sigh, the interface to this routine is botched */ 873251881Speter IPSEC_ASSERT(isr->sav == NULL, ("unexpected SA")); 874251881Speter return 0; 875251881Speter } else { 876251881Speter return ENOENT; 877251881Speter } 878251881Speter} 879251881Speter 880251881Speter/* 881251881Speter * allocating a SA for policy entry from SAD. 882251881Speter * NOTE: searching SAD of aliving state. 883251881Speter * OUT: NULL: not found. 884251881Speter * others: found and return the pointer. 885251881Speter */ 886251881Speterstatic struct secasvar * 887251881Speterkey_allocsa_policy(const struct secasindex *saidx) 888251881Speter{ 889251881Speter#define N(a) _ARRAYLEN(a) 890251881Speter INIT_VNET_IPSEC(curvnet); 891251881Speter struct secashead *sah; 892251881Speter struct secasvar *sav; 893251881Speter u_int stateidx, arraysize; 894251881Speter const u_int *state_valid; 895251881Speter 896251881Speter SAHTREE_LOCK(); 897251881Speter LIST_FOREACH(sah, &V_sahtree, chain) { 898251881Speter if (sah->state == SADB_SASTATE_DEAD) 899251881Speter continue; 900251881Speter if (key_cmpsaidx(&sah->saidx, saidx, CMP_MODE_REQID)) { 901251881Speter if (V_key_preferred_oldsa) { 902251881Speter state_valid = saorder_state_valid_prefer_old; 903251881Speter arraysize = N(saorder_state_valid_prefer_old); 904251881Speter } else { 905251881Speter state_valid = saorder_state_valid_prefer_new; 906251881Speter arraysize = N(saorder_state_valid_prefer_new); 907251881Speter } 908251881Speter SAHTREE_UNLOCK(); 909251881Speter goto found; 910251881Speter } 911251881Speter } 912251881Speter SAHTREE_UNLOCK(); 913251881Speter 914251881Speter return NULL; 915251881Speter 916251881Speter found: 917251881Speter /* search valid state */ 918251881Speter for (stateidx = 0; stateidx < arraysize; stateidx++) { 919251881Speter sav = key_do_allocsa_policy(sah, state_valid[stateidx]); 920251881Speter if (sav != NULL) 921251881Speter return sav; 922251881Speter } 923251881Speter 924251881Speter return NULL; 925251881Speter#undef N 926251881Speter} 927251881Speter 928251881Speter/* 929251881Speter * searching SAD with direction, protocol, mode and state. 930251881Speter * called by key_allocsa_policy(). 931251881Speter * OUT: 932251881Speter * NULL : not found 933251881Speter * others : found, pointer to a SA. 934251881Speter */ 935251881Speterstatic struct secasvar * 936251881Speterkey_do_allocsa_policy(struct secashead *sah, u_int state) 937251881Speter{ 938251881Speter INIT_VNET_IPSEC(curvnet); 939251881Speter struct secasvar *sav, *nextsav, *candidate, *d; 940251881Speter 941251881Speter /* initilize */ 942251881Speter candidate = NULL; 943251881Speter 944251881Speter SAHTREE_LOCK(); 945251881Speter for (sav = LIST_FIRST(&sah->savtree[state]); 946251881Speter sav != NULL; 947251881Speter sav = nextsav) { 948251881Speter 949251881Speter nextsav = LIST_NEXT(sav, chain); 950251881Speter 951251881Speter /* sanity check */ 952251881Speter KEY_CHKSASTATE(sav->state, state, __func__); 953251881Speter 954251881Speter /* initialize */ 955251881Speter if (candidate == NULL) { 956251881Speter candidate = sav; 957251881Speter continue; 958251881Speter } 959251881Speter 960251881Speter /* Which SA is the better ? */ 961251881Speter 962251881Speter IPSEC_ASSERT(candidate->lft_c != NULL, 963251881Speter ("null candidate lifetime")); 964251881Speter IPSEC_ASSERT(sav->lft_c != NULL, ("null sav lifetime")); 965251881Speter 966251881Speter /* What the best method is to compare ? */ 967251881Speter if (V_key_preferred_oldsa) { 968251881Speter if (candidate->lft_c->addtime > 969251881Speter sav->lft_c->addtime) { 970251881Speter candidate = sav; 971251881Speter } 972251881Speter continue; 973251881Speter /*NOTREACHED*/ 974251881Speter } 975251881Speter 976251881Speter /* preferred new sa rather than old sa */ 977251881Speter if (candidate->lft_c->addtime < 978251881Speter sav->lft_c->addtime) { 979251881Speter d = candidate; 980251881Speter candidate = sav; 981251881Speter } else 982251881Speter d = sav; 983251881Speter 984251881Speter /* 985251881Speter * prepared to delete the SA when there is more 986251881Speter * suitable candidate and the lifetime of the SA is not 987251881Speter * permanent. 988251881Speter */ 989251881Speter if (d->lft_h->addtime != 0) { 990251881Speter struct mbuf *m, *result; 991251881Speter u_int8_t satype; 992251881Speter 993251881Speter key_sa_chgstate(d, SADB_SASTATE_DEAD); 994251881Speter 995251881Speter IPSEC_ASSERT(d->refcnt > 0, ("bogus ref count")); 996251881Speter 997251881Speter satype = key_proto2satype(d->sah->saidx.proto); 998251881Speter if (satype == 0) 999251881Speter goto msgfail; 1000251881Speter 1001251881Speter m = key_setsadbmsg(SADB_DELETE, 0, 1002251881Speter satype, 0, 0, d->refcnt - 1); 1003251881Speter if (!m) 1004251881Speter goto msgfail; 1005251881Speter result = m; 1006251881Speter 1007251881Speter /* set sadb_address for saidx's. */ 1008251881Speter m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, 1009251881Speter &d->sah->saidx.src.sa, 1010251881Speter d->sah->saidx.src.sa.sa_len << 3, 1011251881Speter IPSEC_ULPROTO_ANY); 1012251881Speter if (!m) 1013251881Speter goto msgfail; 1014251881Speter m_cat(result, m); 1015251881Speter 1016251881Speter /* set sadb_address for saidx's. */ 1017251881Speter m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, 1018251881Speter &d->sah->saidx.dst.sa, 1019251881Speter d->sah->saidx.dst.sa.sa_len << 3, 1020251881Speter IPSEC_ULPROTO_ANY); 1021251881Speter if (!m) 1022251881Speter goto msgfail; 1023251881Speter m_cat(result, m); 1024251881Speter 1025251881Speter /* create SA extension */ 1026251881Speter m = key_setsadbsa(d); 1027251881Speter if (!m) 1028251881Speter goto msgfail; 1029251881Speter m_cat(result, m); 1030251881Speter 1031251881Speter if (result->m_len < sizeof(struct sadb_msg)) { 1032251881Speter result = m_pullup(result, 1033251881Speter sizeof(struct sadb_msg)); 1034251881Speter if (result == NULL) 1035251881Speter goto msgfail; 1036251881Speter } 1037251881Speter 1038251881Speter result->m_pkthdr.len = 0; 1039251881Speter for (m = result; m; m = m->m_next) 1040251881Speter result->m_pkthdr.len += m->m_len; 1041251881Speter mtod(result, struct sadb_msg *)->sadb_msg_len = 1042251881Speter PFKEY_UNIT64(result->m_pkthdr.len); 1043251881Speter 1044251881Speter if (key_sendup_mbuf(NULL, result, 1045251881Speter KEY_SENDUP_REGISTERED)) 1046251881Speter goto msgfail; 1047251881Speter msgfail: 1048251881Speter KEY_FREESAV(&d); 1049251881Speter } 1050251881Speter } 1051251881Speter if (candidate) { 1052251881Speter sa_addref(candidate); 1053251881Speter KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 1054251881Speter printf("DP %s cause refcnt++:%d SA:%p\n", 1055251881Speter __func__, candidate->refcnt, candidate)); 1056251881Speter } 1057251881Speter SAHTREE_UNLOCK(); 1058251881Speter 1059251881Speter return candidate; 1060251881Speter} 1061251881Speter 1062251881Speter/* 1063251881Speter * allocating a usable SA entry for a *INBOUND* packet. 1064251881Speter * Must call key_freesav() later. 1065251881Speter * OUT: positive: pointer to a usable sav (i.e. MATURE or DYING state). 1066251881Speter * NULL: not found, or error occured. 1067251881Speter * 1068251881Speter * In the comparison, no source address is used--for RFC2401 conformance. 1069251881Speter * To quote, from section 4.1: 1070251881Speter * A security association is uniquely identified by a triple consisting 1071251881Speter * of a Security Parameter Index (SPI), an IP Destination Address, and a 1072251881Speter * security protocol (AH or ESP) identifier. 1073251881Speter * Note that, however, we do need to keep source address in IPsec SA. 1074251881Speter * IKE specification and PF_KEY specification do assume that we 1075251881Speter * keep source address in IPsec SA. We see a tricky situation here. 1076251881Speter */ 1077251881Speterstruct secasvar * 1078251881Speterkey_allocsa( 1079251881Speter union sockaddr_union *dst, 1080251881Speter u_int proto, 1081251881Speter u_int32_t spi, 1082251881Speter const char* where, int tag) 1083251881Speter{ 1084251881Speter INIT_VNET_IPSEC(curvnet); 1085251881Speter struct secashead *sah; 1086251881Speter struct secasvar *sav; 1087251881Speter u_int stateidx, arraysize, state; 1088251881Speter const u_int *saorder_state_valid; 1089251881Speter int chkport; 1090251881Speter 1091251881Speter IPSEC_ASSERT(dst != NULL, ("null dst address")); 1092251881Speter 1093251881Speter KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 1094251881Speter printf("DP %s from %s:%u\n", __func__, where, tag)); 1095251881Speter 1096251881Speter#ifdef IPSEC_NAT_T 1097251881Speter chkport = (dst->sa.sa_family == AF_INET && 1098251881Speter dst->sa.sa_len == sizeof(struct sockaddr_in) && 1099251881Speter dst->sin.sin_port != 0); 1100251881Speter#else 1101251881Speter chkport = 0; 1102251881Speter#endif 1103251881Speter 1104251881Speter /* 1105251881Speter * searching SAD. 1106251881Speter * XXX: to be checked internal IP header somewhere. Also when 1107251881Speter * IPsec tunnel packet is received. But ESP tunnel mode is 1108251881Speter * encrypted so we can't check internal IP header. 1109251881Speter */ 1110251881Speter SAHTREE_LOCK(); 1111251881Speter if (V_key_preferred_oldsa) { 1112251881Speter saorder_state_valid = saorder_state_valid_prefer_old; 1113251881Speter arraysize = _ARRAYLEN(saorder_state_valid_prefer_old); 1114251881Speter } else { 1115251881Speter saorder_state_valid = saorder_state_valid_prefer_new; 1116251881Speter arraysize = _ARRAYLEN(saorder_state_valid_prefer_new); 1117251881Speter } 1118251881Speter LIST_FOREACH(sah, &V_sahtree, chain) { 1119251881Speter /* search valid state */ 1120251881Speter for (stateidx = 0; stateidx < arraysize; stateidx++) { 1121251881Speter state = saorder_state_valid[stateidx]; 1122251881Speter LIST_FOREACH(sav, &sah->savtree[state], chain) { 1123251881Speter /* sanity check */ 1124251881Speter KEY_CHKSASTATE(sav->state, state, __func__); 1125251881Speter /* do not return entries w/ unusable state */ 1126251881Speter if (sav->state != SADB_SASTATE_MATURE && 1127251881Speter sav->state != SADB_SASTATE_DYING) 1128251881Speter continue; 1129251881Speter if (proto != sav->sah->saidx.proto) 1130251881Speter continue; 1131251881Speter if (spi != sav->spi) 1132251881Speter continue; 1133251881Speter#if 0 /* don't check src */ 1134251881Speter /* check src address */ 1135251881Speter if (key_sockaddrcmp(&src->sa, &sav->sah->saidx.src.sa, chkport) != 0) 1136251881Speter continue; 1137251881Speter#endif 1138251881Speter /* check dst address */ 1139251881Speter if (key_sockaddrcmp(&dst->sa, &sav->sah->saidx.dst.sa, chkport) != 0) 1140251881Speter continue; 1141251881Speter sa_addref(sav); 1142251881Speter goto done; 1143251881Speter } 1144251881Speter } 1145251881Speter } 1146251881Speter sav = NULL; 1147251881Speterdone: 1148251881Speter SAHTREE_UNLOCK(); 1149251881Speter 1150251881Speter KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 1151251881Speter printf("DP %s return SA:%p; refcnt %u\n", __func__, 1152251881Speter sav, sav ? sav->refcnt : 0)); 1153251881Speter return sav; 1154251881Speter} 1155251881Speter 1156251881Speter/* 1157251881Speter * Must be called after calling key_allocsp(). 1158251881Speter * For both the packet without socket and key_freeso(). 1159251881Speter */ 1160251881Spetervoid 1161251881Speter_key_freesp(struct secpolicy **spp, const char* where, int tag) 1162251881Speter{ 1163251881Speter INIT_VNET_IPSEC(curvnet); 1164251881Speter struct secpolicy *sp = *spp; 1165251881Speter 1166251881Speter IPSEC_ASSERT(sp != NULL, ("null sp")); 1167251881Speter 1168251881Speter SPTREE_LOCK(); 1169251881Speter SP_DELREF(sp); 1170251881Speter 1171251881Speter KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 1172251881Speter printf("DP %s SP:%p (ID=%u) from %s:%u; refcnt now %u\n", 1173251881Speter __func__, sp, sp->id, where, tag, sp->refcnt)); 1174251881Speter 1175251881Speter if (sp->refcnt == 0) { 1176251881Speter *spp = NULL; 1177251881Speter key_delsp(sp); 1178251881Speter } 1179251881Speter SPTREE_UNLOCK(); 1180251881Speter} 1181251881Speter 1182251881Speter/* 1183251881Speter * Must be called after calling key_allocsp(). 1184251881Speter * For the packet with socket. 1185251881Speter */ 1186251881Spetervoid 1187251881Speterkey_freeso(struct socket *so) 1188251881Speter{ 1189251881Speter INIT_VNET_IPSEC(curvnet); 1190251881Speter IPSEC_ASSERT(so != NULL, ("null so")); 1191251881Speter 1192251881Speter switch (so->so_proto->pr_domain->dom_family) { 1193251881Speter#if defined(INET) || defined(INET6) 1194251881Speter#ifdef INET 1195251881Speter case PF_INET: 1196251881Speter#endif 1197251881Speter#ifdef INET6 1198251881Speter case PF_INET6: 1199251881Speter#endif 1200251881Speter { 1201251881Speter struct inpcb *pcb = sotoinpcb(so); 1202251881Speter 1203251881Speter /* Does it have a PCB ? */ 1204251881Speter if (pcb == NULL) 1205251881Speter return; 1206251881Speter key_freesp_so(&pcb->inp_sp->sp_in); 1207251881Speter key_freesp_so(&pcb->inp_sp->sp_out); 1208251881Speter } 1209251881Speter break; 1210251881Speter#endif /* INET || INET6 */ 1211251881Speter default: 1212251881Speter ipseclog((LOG_DEBUG, "%s: unknown address family=%d.\n", 1213251881Speter __func__, so->so_proto->pr_domain->dom_family)); 1214251881Speter return; 1215251881Speter } 1216251881Speter} 1217251881Speter 1218251881Speterstatic void 1219251881Speterkey_freesp_so(struct secpolicy **sp) 1220251881Speter{ 1221251881Speter IPSEC_ASSERT(sp != NULL && *sp != NULL, ("null sp")); 1222251881Speter 1223251881Speter if ((*sp)->policy == IPSEC_POLICY_ENTRUST || 1224251881Speter (*sp)->policy == IPSEC_POLICY_BYPASS) 1225251881Speter return; 1226251881Speter 1227251881Speter IPSEC_ASSERT((*sp)->policy == IPSEC_POLICY_IPSEC, 1228251881Speter ("invalid policy %u", (*sp)->policy)); 1229251881Speter KEY_FREESP(sp); 1230251881Speter} 1231251881Speter 1232251881Speter/* 1233251881Speter * Must be called after calling key_allocsa(). 1234251881Speter * This function is called by key_freesp() to free some SA allocated 1235251881Speter * for a policy. 1236251881Speter */ 1237251881Spetervoid 1238251881Speterkey_freesav(struct secasvar **psav, const char* where, int tag) 1239251881Speter{ 1240251881Speter INIT_VNET_IPSEC(curvnet); 1241251881Speter struct secasvar *sav = *psav; 1242251881Speter 1243251881Speter IPSEC_ASSERT(sav != NULL, ("null sav")); 1244251881Speter 1245251881Speter if (sa_delref(sav)) { 1246251881Speter KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 1247251881Speter printf("DP %s SA:%p (SPI %u) from %s:%u; refcnt now %u\n", 1248251881Speter __func__, sav, ntohl(sav->spi), where, tag, sav->refcnt)); 1249251881Speter *psav = NULL; 1250251881Speter key_delsav(sav); 1251251881Speter } else { 1252251881Speter KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 1253251881Speter printf("DP %s SA:%p (SPI %u) from %s:%u; refcnt now %u\n", 1254251881Speter __func__, sav, ntohl(sav->spi), where, tag, sav->refcnt)); 1255251881Speter } 1256251881Speter} 1257251881Speter 1258251881Speter/* %%% SPD management */ 1259251881Speter/* 1260251881Speter * free security policy entry. 1261251881Speter */ 1262251881Speterstatic void 1263251881Speterkey_delsp(struct secpolicy *sp) 1264251881Speter{ 1265251881Speter struct ipsecrequest *isr, *nextisr; 1266251881Speter 1267251881Speter IPSEC_ASSERT(sp != NULL, ("null sp")); 1268251881Speter SPTREE_LOCK_ASSERT(); 1269251881Speter 1270251881Speter sp->state = IPSEC_SPSTATE_DEAD; 1271251881Speter 1272251881Speter IPSEC_ASSERT(sp->refcnt == 0, 1273251881Speter ("SP with references deleted (refcnt %u)", sp->refcnt)); 1274251881Speter 1275251881Speter /* remove from SP index */ 1276251881Speter if (__LIST_CHAINED(sp)) 1277251881Speter LIST_REMOVE(sp, chain); 1278251881Speter 1279251881Speter for (isr = sp->req; isr != NULL; isr = nextisr) { 1280251881Speter if (isr->sav != NULL) { 1281251881Speter KEY_FREESAV(&isr->sav); 1282251881Speter isr->sav = NULL; 1283251881Speter } 1284251881Speter 1285251881Speter nextisr = isr->next; 1286251881Speter ipsec_delisr(isr); 1287251881Speter } 1288251881Speter _key_delsp(sp); 1289251881Speter} 1290251881Speter 1291251881Speter/* 1292251881Speter * search SPD 1293251881Speter * OUT: NULL : not found 1294251881Speter * others : found, pointer to a SP. 1295251881Speter */ 1296251881Speterstatic struct secpolicy * 1297251881Speterkey_getsp(struct secpolicyindex *spidx) 1298251881Speter{ 1299251881Speter INIT_VNET_IPSEC(curvnet); 1300251881Speter struct secpolicy *sp; 1301251881Speter 1302251881Speter IPSEC_ASSERT(spidx != NULL, ("null spidx")); 1303251881Speter 1304251881Speter SPTREE_LOCK(); 1305251881Speter LIST_FOREACH(sp, &V_sptree[spidx->dir], chain) { 1306251881Speter if (sp->state == IPSEC_SPSTATE_DEAD) 1307251881Speter continue; 1308251881Speter if (key_cmpspidx_exactly(spidx, &sp->spidx)) { 1309251881Speter SP_ADDREF(sp); 1310251881Speter break; 1311251881Speter } 1312251881Speter } 1313251881Speter SPTREE_UNLOCK(); 1314251881Speter 1315251881Speter return sp; 1316251881Speter} 1317251881Speter 1318251881Speter/* 1319251881Speter * get SP by index. 1320251881Speter * OUT: NULL : not found 1321251881Speter * others : found, pointer to a SP. 1322251881Speter */ 1323251881Speterstatic struct secpolicy * 1324251881Speterkey_getspbyid(u_int32_t id) 1325251881Speter{ 1326251881Speter INIT_VNET_IPSEC(curvnet); 1327251881Speter struct secpolicy *sp; 1328251881Speter 1329251881Speter SPTREE_LOCK(); 1330251881Speter LIST_FOREACH(sp, &V_sptree[IPSEC_DIR_INBOUND], chain) { 1331251881Speter if (sp->state == IPSEC_SPSTATE_DEAD) 1332251881Speter continue; 1333251881Speter if (sp->id == id) { 1334251881Speter SP_ADDREF(sp); 1335251881Speter goto done; 1336251881Speter } 1337251881Speter } 1338251881Speter 1339251881Speter LIST_FOREACH(sp, &V_sptree[IPSEC_DIR_OUTBOUND], chain) { 1340251881Speter if (sp->state == IPSEC_SPSTATE_DEAD) 1341251881Speter continue; 1342251881Speter if (sp->id == id) { 1343251881Speter SP_ADDREF(sp); 1344251881Speter goto done; 1345251881Speter } 1346251881Speter } 1347251881Speterdone: 1348251881Speter SPTREE_UNLOCK(); 1349251881Speter 1350251881Speter return sp; 1351251881Speter} 1352251881Speter 1353251881Speterstruct secpolicy * 1354251881Speterkey_newsp(const char* where, int tag) 1355251881Speter{ 1356251881Speter INIT_VNET_IPSEC(curvnet); 1357251881Speter struct secpolicy *newsp = NULL; 1358251881Speter 1359251881Speter newsp = (struct secpolicy *) 1360251881Speter malloc(sizeof(struct secpolicy), M_IPSEC_SP, M_NOWAIT|M_ZERO); 1361251881Speter if (newsp) { 1362251881Speter SECPOLICY_LOCK_INIT(newsp); 1363251881Speter newsp->refcnt = 1; 1364251881Speter newsp->req = NULL; 1365251881Speter } 1366251881Speter 1367251881Speter KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 1368251881Speter printf("DP %s from %s:%u return SP:%p\n", __func__, 1369251881Speter where, tag, newsp)); 1370251881Speter return newsp; 1371251881Speter} 1372251881Speter 1373251881Speterstatic void 1374251881Speter_key_delsp(struct secpolicy *sp) 1375251881Speter{ 1376251881Speter SECPOLICY_LOCK_DESTROY(sp); 1377251881Speter free(sp, M_IPSEC_SP); 1378251881Speter} 1379251881Speter 1380251881Speter/* 1381251881Speter * create secpolicy structure from sadb_x_policy structure. 1382251881Speter * NOTE: `state', `secpolicyindex' in secpolicy structure are not set, 1383251881Speter * so must be set properly later. 1384251881Speter */ 1385251881Speterstruct secpolicy * 1386251881Speterkey_msg2sp(xpl0, len, error) 1387251881Speter struct sadb_x_policy *xpl0; 1388251881Speter size_t len; 1389251881Speter int *error; 1390251881Speter{ 1391251881Speter INIT_VNET_IPSEC(curvnet); 1392251881Speter struct secpolicy *newsp; 1393251881Speter 1394251881Speter IPSEC_ASSERT(xpl0 != NULL, ("null xpl0")); 1395251881Speter IPSEC_ASSERT(len >= sizeof(*xpl0), ("policy too short: %zu", len)); 1396251881Speter 1397251881Speter if (len != PFKEY_EXTLEN(xpl0)) { 1398251881Speter ipseclog((LOG_DEBUG, "%s: Invalid msg length.\n", __func__)); 1399251881Speter *error = EINVAL; 1400251881Speter return NULL; 1401251881Speter } 1402251881Speter 1403251881Speter if ((newsp = KEY_NEWSP()) == NULL) { 1404251881Speter *error = ENOBUFS; 1405251881Speter return NULL; 1406251881Speter } 1407251881Speter 1408251881Speter newsp->spidx.dir = xpl0->sadb_x_policy_dir; 1409251881Speter newsp->policy = xpl0->sadb_x_policy_type; 1410251881Speter 1411251881Speter /* check policy */ 1412251881Speter switch (xpl0->sadb_x_policy_type) { 1413251881Speter case IPSEC_POLICY_DISCARD: 1414251881Speter case IPSEC_POLICY_NONE: 1415251881Speter case IPSEC_POLICY_ENTRUST: 1416251881Speter case IPSEC_POLICY_BYPASS: 1417251881Speter newsp->req = NULL; 1418251881Speter break; 1419251881Speter 1420251881Speter case IPSEC_POLICY_IPSEC: 1421251881Speter { 1422251881Speter int tlen; 1423251881Speter struct sadb_x_ipsecrequest *xisr; 1424251881Speter struct ipsecrequest **p_isr = &newsp->req; 1425251881Speter 1426251881Speter /* validity check */ 1427251881Speter if (PFKEY_EXTLEN(xpl0) < sizeof(*xpl0)) { 1428251881Speter ipseclog((LOG_DEBUG, "%s: Invalid msg length.\n", 1429251881Speter __func__)); 1430251881Speter KEY_FREESP(&newsp); 1431251881Speter *error = EINVAL; 1432251881Speter return NULL; 1433251881Speter } 1434251881Speter 1435251881Speter tlen = PFKEY_EXTLEN(xpl0) - sizeof(*xpl0); 1436251881Speter xisr = (struct sadb_x_ipsecrequest *)(xpl0 + 1); 1437251881Speter 1438251881Speter while (tlen > 0) { 1439251881Speter /* length check */ 1440251881Speter if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr)) { 1441251881Speter ipseclog((LOG_DEBUG, "%s: invalid ipsecrequest " 1442251881Speter "length.\n", __func__)); 1443251881Speter KEY_FREESP(&newsp); 1444251881Speter *error = EINVAL; 1445251881Speter return NULL; 1446251881Speter } 1447251881Speter 1448251881Speter /* allocate request buffer */ 1449251881Speter /* NB: data structure is zero'd */ 1450251881Speter *p_isr = ipsec_newisr(); 1451251881Speter if ((*p_isr) == NULL) { 1452251881Speter ipseclog((LOG_DEBUG, 1453251881Speter "%s: No more memory.\n", __func__)); 1454251881Speter KEY_FREESP(&newsp); 1455251881Speter *error = ENOBUFS; 1456251881Speter return NULL; 1457251881Speter } 1458251881Speter 1459251881Speter /* set values */ 1460251881Speter switch (xisr->sadb_x_ipsecrequest_proto) { 1461251881Speter case IPPROTO_ESP: 1462251881Speter case IPPROTO_AH: 1463251881Speter case IPPROTO_IPCOMP: 1464251881Speter break; 1465251881Speter default: 1466251881Speter ipseclog((LOG_DEBUG, 1467251881Speter "%s: invalid proto type=%u\n", __func__, 1468251881Speter xisr->sadb_x_ipsecrequest_proto)); 1469251881Speter KEY_FREESP(&newsp); 1470251881Speter *error = EPROTONOSUPPORT; 1471251881Speter return NULL; 1472251881Speter } 1473251881Speter (*p_isr)->saidx.proto = xisr->sadb_x_ipsecrequest_proto; 1474251881Speter 1475251881Speter switch (xisr->sadb_x_ipsecrequest_mode) { 1476251881Speter case IPSEC_MODE_TRANSPORT: 1477251881Speter case IPSEC_MODE_TUNNEL: 1478251881Speter break; 1479251881Speter case IPSEC_MODE_ANY: 1480251881Speter default: 1481251881Speter ipseclog((LOG_DEBUG, 1482251881Speter "%s: invalid mode=%u\n", __func__, 1483251881Speter xisr->sadb_x_ipsecrequest_mode)); 1484251881Speter KEY_FREESP(&newsp); 1485251881Speter *error = EINVAL; 1486251881Speter return NULL; 1487251881Speter } 1488251881Speter (*p_isr)->saidx.mode = xisr->sadb_x_ipsecrequest_mode; 1489251881Speter 1490251881Speter switch (xisr->sadb_x_ipsecrequest_level) { 1491251881Speter case IPSEC_LEVEL_DEFAULT: 1492251881Speter case IPSEC_LEVEL_USE: 1493251881Speter case IPSEC_LEVEL_REQUIRE: 1494251881Speter break; 1495251881Speter case IPSEC_LEVEL_UNIQUE: 1496251881Speter /* validity check */ 1497251881Speter /* 1498251881Speter * If range violation of reqid, kernel will 1499251881Speter * update it, don't refuse it. 1500251881Speter */ 1501251881Speter if (xisr->sadb_x_ipsecrequest_reqid 1502251881Speter > IPSEC_MANUAL_REQID_MAX) { 1503251881Speter ipseclog((LOG_DEBUG, 1504251881Speter "%s: reqid=%d range " 1505251881Speter "violation, updated by kernel.\n", 1506251881Speter __func__, 1507251881Speter xisr->sadb_x_ipsecrequest_reqid)); 1508251881Speter xisr->sadb_x_ipsecrequest_reqid = 0; 1509251881Speter } 1510251881Speter 1511251881Speter /* allocate new reqid id if reqid is zero. */ 1512251881Speter if (xisr->sadb_x_ipsecrequest_reqid == 0) { 1513251881Speter u_int32_t reqid; 1514251881Speter if ((reqid = key_newreqid()) == 0) { 1515251881Speter KEY_FREESP(&newsp); 1516251881Speter *error = ENOBUFS; 1517251881Speter return NULL; 1518251881Speter } 1519251881Speter (*p_isr)->saidx.reqid = reqid; 1520251881Speter xisr->sadb_x_ipsecrequest_reqid = reqid; 1521251881Speter } else { 1522251881Speter /* set it for manual keying. */ 1523251881Speter (*p_isr)->saidx.reqid = 1524251881Speter xisr->sadb_x_ipsecrequest_reqid; 1525251881Speter } 1526251881Speter break; 1527251881Speter 1528251881Speter default: 1529251881Speter ipseclog((LOG_DEBUG, "%s: invalid level=%u\n", 1530251881Speter __func__, 1531251881Speter xisr->sadb_x_ipsecrequest_level)); 1532251881Speter KEY_FREESP(&newsp); 1533251881Speter *error = EINVAL; 1534251881Speter return NULL; 1535251881Speter } 1536251881Speter (*p_isr)->level = xisr->sadb_x_ipsecrequest_level; 1537251881Speter 1538251881Speter /* set IP addresses if there */ 1539251881Speter if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) { 1540251881Speter struct sockaddr *paddr; 1541251881Speter 1542251881Speter paddr = (struct sockaddr *)(xisr + 1); 1543251881Speter 1544251881Speter /* validity check */ 1545251881Speter if (paddr->sa_len 1546251881Speter > sizeof((*p_isr)->saidx.src)) { 1547251881Speter ipseclog((LOG_DEBUG, "%s: invalid " 1548251881Speter "request address length.\n", 1549251881Speter __func__)); 1550251881Speter KEY_FREESP(&newsp); 1551251881Speter *error = EINVAL; 1552251881Speter return NULL; 1553251881Speter } 1554251881Speter bcopy(paddr, &(*p_isr)->saidx.src, 1555251881Speter paddr->sa_len); 1556251881Speter 1557251881Speter paddr = (struct sockaddr *)((caddr_t)paddr 1558251881Speter + paddr->sa_len); 1559251881Speter 1560251881Speter /* validity check */ 1561251881Speter if (paddr->sa_len 1562251881Speter > sizeof((*p_isr)->saidx.dst)) { 1563251881Speter ipseclog((LOG_DEBUG, "%s: invalid " 1564251881Speter "request address length.\n", 1565251881Speter __func__)); 1566251881Speter KEY_FREESP(&newsp); 1567251881Speter *error = EINVAL; 1568251881Speter return NULL; 1569251881Speter } 1570251881Speter bcopy(paddr, &(*p_isr)->saidx.dst, 1571251881Speter paddr->sa_len); 1572251881Speter } 1573251881Speter 1574251881Speter (*p_isr)->sp = newsp; 1575251881Speter 1576251881Speter /* initialization for the next. */ 1577251881Speter p_isr = &(*p_isr)->next; 1578251881Speter tlen -= xisr->sadb_x_ipsecrequest_len; 1579251881Speter 1580251881Speter /* validity check */ 1581251881Speter if (tlen < 0) { 1582251881Speter ipseclog((LOG_DEBUG, "%s: becoming tlen < 0.\n", 1583251881Speter __func__)); 1584251881Speter KEY_FREESP(&newsp); 1585251881Speter *error = EINVAL; 1586251881Speter return NULL; 1587251881Speter } 1588251881Speter 1589251881Speter xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xisr 1590251881Speter + xisr->sadb_x_ipsecrequest_len); 1591251881Speter } 1592251881Speter } 1593251881Speter break; 1594251881Speter default: 1595251881Speter ipseclog((LOG_DEBUG, "%s: invalid policy type.\n", __func__)); 1596251881Speter KEY_FREESP(&newsp); 1597251881Speter *error = EINVAL; 1598251881Speter return NULL; 1599251881Speter } 1600251881Speter 1601251881Speter *error = 0; 1602251881Speter return newsp; 1603251881Speter} 1604251881Speter 1605251881Speterstatic u_int32_t 1606251881Speterkey_newreqid() 1607251881Speter{ 1608251881Speter static u_int32_t auto_reqid = IPSEC_MANUAL_REQID_MAX + 1; 1609251881Speter 1610251881Speter auto_reqid = (auto_reqid == ~0 1611251881Speter ? IPSEC_MANUAL_REQID_MAX + 1 : auto_reqid + 1); 1612251881Speter 1613251881Speter /* XXX should be unique check */ 1614251881Speter 1615251881Speter return auto_reqid; 1616251881Speter} 1617251881Speter 1618251881Speter/* 1619251881Speter * copy secpolicy struct to sadb_x_policy structure indicated. 1620251881Speter */ 1621251881Speterstruct mbuf * 1622251881Speterkey_sp2msg(sp) 1623251881Speter struct secpolicy *sp; 1624251881Speter{ 1625251881Speter struct sadb_x_policy *xpl; 1626251881Speter int tlen; 1627251881Speter caddr_t p; 1628251881Speter struct mbuf *m; 1629251881Speter 1630251881Speter IPSEC_ASSERT(sp != NULL, ("null policy")); 1631251881Speter 1632251881Speter tlen = key_getspreqmsglen(sp); 1633251881Speter 1634251881Speter m = key_alloc_mbuf(tlen); 1635251881Speter if (!m || m->m_next) { /*XXX*/ 1636251881Speter if (m) 1637251881Speter m_freem(m); 1638251881Speter return NULL; 1639251881Speter } 1640251881Speter 1641251881Speter m->m_len = tlen; 1642251881Speter m->m_next = NULL; 1643251881Speter xpl = mtod(m, struct sadb_x_policy *); 1644251881Speter bzero(xpl, tlen); 1645251881Speter 1646251881Speter xpl->sadb_x_policy_len = PFKEY_UNIT64(tlen); 1647251881Speter xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY; 1648251881Speter xpl->sadb_x_policy_type = sp->policy; 1649251881Speter xpl->sadb_x_policy_dir = sp->spidx.dir; 1650251881Speter xpl->sadb_x_policy_id = sp->id; 1651251881Speter p = (caddr_t)xpl + sizeof(*xpl); 1652251881Speter 1653251881Speter /* if is the policy for ipsec ? */ 1654251881Speter if (sp->policy == IPSEC_POLICY_IPSEC) { 1655251881Speter struct sadb_x_ipsecrequest *xisr; 1656251881Speter struct ipsecrequest *isr; 1657251881Speter 1658251881Speter for (isr = sp->req; isr != NULL; isr = isr->next) { 1659251881Speter 1660251881Speter xisr = (struct sadb_x_ipsecrequest *)p; 1661251881Speter 1662251881Speter xisr->sadb_x_ipsecrequest_proto = isr->saidx.proto; 1663251881Speter xisr->sadb_x_ipsecrequest_mode = isr->saidx.mode; 1664251881Speter xisr->sadb_x_ipsecrequest_level = isr->level; 1665251881Speter xisr->sadb_x_ipsecrequest_reqid = isr->saidx.reqid; 1666251881Speter 1667251881Speter p += sizeof(*xisr); 1668251881Speter bcopy(&isr->saidx.src, p, isr->saidx.src.sa.sa_len); 1669251881Speter p += isr->saidx.src.sa.sa_len; 1670251881Speter bcopy(&isr->saidx.dst, p, isr->saidx.dst.sa.sa_len); 1671251881Speter p += isr->saidx.src.sa.sa_len; 1672251881Speter 1673251881Speter xisr->sadb_x_ipsecrequest_len = 1674251881Speter PFKEY_ALIGN8(sizeof(*xisr) 1675251881Speter + isr->saidx.src.sa.sa_len 1676251881Speter + isr->saidx.dst.sa.sa_len); 1677251881Speter } 1678251881Speter } 1679251881Speter 1680251881Speter return m; 1681251881Speter} 1682251881Speter 1683251881Speter/* m will not be freed nor modified */ 1684251881Speterstatic struct mbuf * 1685251881Speter#ifdef __STDC__ 1686251881Speterkey_gather_mbuf(struct mbuf *m, const struct sadb_msghdr *mhp, 1687251881Speter int ndeep, int nitem, ...) 1688251881Speter#else 1689251881Speterkey_gather_mbuf(m, mhp, ndeep, nitem, va_alist) 1690251881Speter struct mbuf *m; 1691251881Speter const struct sadb_msghdr *mhp; 1692251881Speter int ndeep; 1693251881Speter int nitem; 1694251881Speter va_dcl 1695251881Speter#endif 1696251881Speter{ 1697251881Speter va_list ap; 1698251881Speter int idx; 1699251881Speter int i; 1700251881Speter struct mbuf *result = NULL, *n; 1701251881Speter int len; 1702251881Speter 1703251881Speter IPSEC_ASSERT(m != NULL, ("null mbuf")); 1704251881Speter IPSEC_ASSERT(mhp != NULL, ("null msghdr")); 1705251881Speter 1706251881Speter va_start(ap, nitem); 1707251881Speter for (i = 0; i < nitem; i++) { 1708251881Speter idx = va_arg(ap, int); 1709251881Speter if (idx < 0 || idx > SADB_EXT_MAX) 1710251881Speter goto fail; 1711251881Speter /* don't attempt to pull empty extension */ 1712251881Speter if (idx == SADB_EXT_RESERVED && mhp->msg == NULL) 1713251881Speter continue; 1714251881Speter if (idx != SADB_EXT_RESERVED && 1715251881Speter (mhp->ext[idx] == NULL || mhp->extlen[idx] == 0)) 1716251881Speter continue; 1717251881Speter 1718251881Speter if (idx == SADB_EXT_RESERVED) { 1719251881Speter len = PFKEY_ALIGN8(sizeof(struct sadb_msg)); 1720251881Speter 1721251881Speter IPSEC_ASSERT(len <= MHLEN, ("header too big %u", len)); 1722251881Speter 1723251881Speter MGETHDR(n, M_DONTWAIT, MT_DATA); 1724251881Speter if (!n) 1725251881Speter goto fail; 1726251881Speter n->m_len = len; 1727251881Speter n->m_next = NULL; 1728251881Speter m_copydata(m, 0, sizeof(struct sadb_msg), 1729251881Speter mtod(n, caddr_t)); 1730251881Speter } else if (i < ndeep) { 1731251881Speter len = mhp->extlen[idx]; 1732251881Speter n = key_alloc_mbuf(len); 1733251881Speter if (!n || n->m_next) { /*XXX*/ 1734251881Speter if (n) 1735251881Speter m_freem(n); 1736251881Speter goto fail; 1737251881Speter } 1738251881Speter m_copydata(m, mhp->extoff[idx], mhp->extlen[idx], 1739251881Speter mtod(n, caddr_t)); 1740251881Speter } else { 1741251881Speter n = m_copym(m, mhp->extoff[idx], mhp->extlen[idx], 1742251881Speter M_DONTWAIT); 1743251881Speter } 1744251881Speter if (n == NULL) 1745251881Speter goto fail; 1746251881Speter 1747251881Speter if (result) 1748251881Speter m_cat(result, n); 1749251881Speter else 1750251881Speter result = n; 1751251881Speter } 1752251881Speter va_end(ap); 1753251881Speter 1754251881Speter if ((result->m_flags & M_PKTHDR) != 0) { 1755251881Speter result->m_pkthdr.len = 0; 1756251881Speter for (n = result; n; n = n->m_next) 1757251881Speter result->m_pkthdr.len += n->m_len; 1758251881Speter } 1759251881Speter 1760251881Speter return result; 1761251881Speter 1762251881Speterfail: 1763251881Speter m_freem(result); 1764251881Speter return NULL; 1765251881Speter} 1766251881Speter 1767251881Speter/* 1768251881Speter * SADB_X_SPDADD, SADB_X_SPDSETIDX or SADB_X_SPDUPDATE processing 1769251881Speter * add an entry to SP database, when received 1770251881Speter * <base, address(SD), (lifetime(H),) policy> 1771251881Speter * from the user(?). 1772251881Speter * Adding to SP database, 1773251881Speter * and send 1774251881Speter * <base, address(SD), (lifetime(H),) policy> 1775251881Speter * to the socket which was send. 1776251881Speter * 1777251881Speter * SPDADD set a unique policy entry. 1778251881Speter * SPDSETIDX like SPDADD without a part of policy requests. 1779251881Speter * SPDUPDATE replace a unique policy entry. 1780251881Speter * 1781251881Speter * m will always be freed. 1782251881Speter */ 1783251881Speterstatic int 1784251881Speterkey_spdadd(so, m, mhp) 1785251881Speter struct socket *so; 1786251881Speter struct mbuf *m; 1787251881Speter const struct sadb_msghdr *mhp; 1788251881Speter{ 1789251881Speter INIT_VNET_IPSEC(curvnet); 1790251881Speter struct sadb_address *src0, *dst0; 1791251881Speter struct sadb_x_policy *xpl0, *xpl; 1792251881Speter struct sadb_lifetime *lft = NULL; 1793251881Speter struct secpolicyindex spidx; 1794251881Speter struct secpolicy *newsp; 1795251881Speter int error; 1796251881Speter 1797251881Speter IPSEC_ASSERT(so != NULL, ("null socket")); 1798251881Speter IPSEC_ASSERT(m != NULL, ("null mbuf")); 1799251881Speter IPSEC_ASSERT(mhp != NULL, ("null msghdr")); 1800251881Speter IPSEC_ASSERT(mhp->msg != NULL, ("null msg")); 1801251881Speter 1802251881Speter if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || 1803251881Speter mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || 1804251881Speter mhp->ext[SADB_X_EXT_POLICY] == NULL) { 1805251881Speter ipseclog((LOG_DEBUG, "key_spdadd: invalid message is passed.\n")); 1806251881Speter return key_senderror(so, m, EINVAL); 1807251881Speter } 1808251881Speter if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || 1809251881Speter mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address) || 1810251881Speter mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) { 1811251881Speter ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", 1812251881Speter __func__)); 1813251881Speter return key_senderror(so, m, EINVAL); 1814251881Speter } 1815251881Speter if (mhp->ext[SADB_EXT_LIFETIME_HARD] != NULL) { 1816251881Speter if (mhp->extlen[SADB_EXT_LIFETIME_HARD] 1817251881Speter < sizeof(struct sadb_lifetime)) { 1818251881Speter ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", 1819251881Speter __func__)); 1820251881Speter return key_senderror(so, m, EINVAL); 1821251881Speter } 1822251881Speter lft = (struct sadb_lifetime *)mhp->ext[SADB_EXT_LIFETIME_HARD]; 1823251881Speter } 1824251881Speter 1825251881Speter src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC]; 1826251881Speter dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST]; 1827251881Speter xpl0 = (struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY]; 1828251881Speter 1829251881Speter /* 1830251881Speter * Note: do not parse SADB_X_EXT_NAT_T_* here: 1831251881Speter * we are processing traffic endpoints. 1832251881Speter */ 1833251881Speter 1834251881Speter /* make secindex */ 1835251881Speter /* XXX boundary check against sa_len */ 1836251881Speter KEY_SETSECSPIDX(xpl0->sadb_x_policy_dir, 1837251881Speter src0 + 1, 1838251881Speter dst0 + 1, 1839251881Speter src0->sadb_address_prefixlen, 1840251881Speter dst0->sadb_address_prefixlen, 1841251881Speter src0->sadb_address_proto, 1842251881Speter &spidx); 1843251881Speter 1844251881Speter /* checking the direciton. */ 1845251881Speter switch (xpl0->sadb_x_policy_dir) { 1846251881Speter case IPSEC_DIR_INBOUND: 1847251881Speter case IPSEC_DIR_OUTBOUND: 1848251881Speter break; 1849251881Speter default: 1850251881Speter ipseclog((LOG_DEBUG, "%s: Invalid SP direction.\n", __func__)); 1851251881Speter mhp->msg->sadb_msg_errno = EINVAL; 1852251881Speter return 0; 1853251881Speter } 1854251881Speter 1855251881Speter /* check policy */ 1856251881Speter /* key_spdadd() accepts DISCARD, NONE and IPSEC. */ 1857251881Speter if (xpl0->sadb_x_policy_type == IPSEC_POLICY_ENTRUST 1858251881Speter || xpl0->sadb_x_policy_type == IPSEC_POLICY_BYPASS) { 1859251881Speter ipseclog((LOG_DEBUG, "%s: Invalid policy type.\n", __func__)); 1860251881Speter return key_senderror(so, m, EINVAL); 1861251881Speter } 1862251881Speter 1863251881Speter /* policy requests are mandatory when action is ipsec. */ 1864251881Speter if (mhp->msg->sadb_msg_type != SADB_X_SPDSETIDX 1865251881Speter && xpl0->sadb_x_policy_type == IPSEC_POLICY_IPSEC 1866251881Speter && mhp->extlen[SADB_X_EXT_POLICY] <= sizeof(*xpl0)) { 1867251881Speter ipseclog((LOG_DEBUG, "%s: some policy requests part required\n", 1868251881Speter __func__)); 1869251881Speter return key_senderror(so, m, EINVAL); 1870251881Speter } 1871251881Speter 1872251881Speter /* 1873251881Speter * checking there is SP already or not. 1874251881Speter * SPDUPDATE doesn't depend on whether there is a SP or not. 1875251881Speter * If the type is either SPDADD or SPDSETIDX AND a SP is found, 1876251881Speter * then error. 1877251881Speter */ 1878251881Speter newsp = key_getsp(&spidx); 1879251881Speter if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) { 1880251881Speter if (newsp) { 1881251881Speter newsp->state = IPSEC_SPSTATE_DEAD; 1882251881Speter KEY_FREESP(&newsp); 1883251881Speter } 1884251881Speter } else { 1885251881Speter if (newsp != NULL) { 1886251881Speter KEY_FREESP(&newsp); 1887251881Speter ipseclog((LOG_DEBUG, "%s: a SP entry exists already.\n", 1888251881Speter __func__)); 1889251881Speter return key_senderror(so, m, EEXIST); 1890251881Speter } 1891251881Speter } 1892251881Speter 1893251881Speter /* allocation new SP entry */ 1894251881Speter if ((newsp = key_msg2sp(xpl0, PFKEY_EXTLEN(xpl0), &error)) == NULL) { 1895251881Speter return key_senderror(so, m, error); 1896251881Speter } 1897251881Speter 1898251881Speter if ((newsp->id = key_getnewspid()) == 0) { 1899251881Speter _key_delsp(newsp); 1900251881Speter return key_senderror(so, m, ENOBUFS); 1901251881Speter } 1902251881Speter 1903251881Speter /* XXX boundary check against sa_len */ 1904251881Speter KEY_SETSECSPIDX(xpl0->sadb_x_policy_dir, 1905251881Speter src0 + 1, 1906251881Speter dst0 + 1, 1907251881Speter src0->sadb_address_prefixlen, 1908251881Speter dst0->sadb_address_prefixlen, 1909251881Speter src0->sadb_address_proto, 1910251881Speter &newsp->spidx); 1911251881Speter 1912251881Speter /* sanity check on addr pair */ 1913251881Speter if (((struct sockaddr *)(src0 + 1))->sa_family != 1914251881Speter ((struct sockaddr *)(dst0+ 1))->sa_family) { 1915251881Speter _key_delsp(newsp); 1916251881Speter return key_senderror(so, m, EINVAL); 1917251881Speter } 1918251881Speter if (((struct sockaddr *)(src0 + 1))->sa_len != 1919251881Speter ((struct sockaddr *)(dst0+ 1))->sa_len) { 1920251881Speter _key_delsp(newsp); 1921251881Speter return key_senderror(so, m, EINVAL); 1922251881Speter } 1923251881Speter#if 1 1924251881Speter if (newsp->req && newsp->req->saidx.src.sa.sa_family) { 1925251881Speter struct sockaddr *sa; 1926251881Speter sa = (struct sockaddr *)(src0 + 1); 1927251881Speter if (sa->sa_family != newsp->req->saidx.src.sa.sa_family) { 1928251881Speter _key_delsp(newsp); 1929251881Speter return key_senderror(so, m, EINVAL); 1930251881Speter } 1931251881Speter } 1932251881Speter if (newsp->req && newsp->req->saidx.dst.sa.sa_family) { 1933251881Speter struct sockaddr *sa; 1934251881Speter sa = (struct sockaddr *)(dst0 + 1); 1935251881Speter if (sa->sa_family != newsp->req->saidx.dst.sa.sa_family) { 1936251881Speter _key_delsp(newsp); 1937251881Speter return key_senderror(so, m, EINVAL); 1938251881Speter } 1939251881Speter } 1940251881Speter#endif 1941251881Speter 1942251881Speter newsp->created = time_second; 1943251881Speter newsp->lastused = newsp->created; 1944251881Speter newsp->lifetime = lft ? lft->sadb_lifetime_addtime : 0; 1945251881Speter newsp->validtime = lft ? lft->sadb_lifetime_usetime : 0; 1946251881Speter 1947251881Speter newsp->refcnt = 1; /* do not reclaim until I say I do */ 1948251881Speter newsp->state = IPSEC_SPSTATE_ALIVE; 1949251881Speter LIST_INSERT_TAIL(&V_sptree[newsp->spidx.dir], newsp, secpolicy, chain); 1950251881Speter 1951251881Speter /* delete the entry in spacqtree */ 1952251881Speter if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) { 1953251881Speter struct secspacq *spacq = key_getspacq(&spidx); 1954251881Speter if (spacq != NULL) { 1955251881Speter /* reset counter in order to deletion by timehandler. */ 1956251881Speter spacq->created = time_second; 1957251881Speter spacq->count = 0; 1958251881Speter SPACQ_UNLOCK(); 1959251881Speter } 1960251881Speter } 1961251881Speter 1962251881Speter { 1963251881Speter struct mbuf *n, *mpolicy; 1964251881Speter struct sadb_msg *newmsg; 1965251881Speter int off; 1966251881Speter 1967251881Speter /* 1968251881Speter * Note: do not send SADB_X_EXT_NAT_T_* here: 1969251881Speter * we are sending traffic endpoints. 1970251881Speter */ 1971251881Speter 1972251881Speter /* create new sadb_msg to reply. */ 1973251881Speter if (lft) { 1974251881Speter n = key_gather_mbuf(m, mhp, 2, 5, SADB_EXT_RESERVED, 1975251881Speter SADB_X_EXT_POLICY, SADB_EXT_LIFETIME_HARD, 1976251881Speter SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST); 1977251881Speter } else { 1978251881Speter n = key_gather_mbuf(m, mhp, 2, 4, SADB_EXT_RESERVED, 1979251881Speter SADB_X_EXT_POLICY, 1980251881Speter SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST); 1981251881Speter } 1982251881Speter if (!n) 1983251881Speter return key_senderror(so, m, ENOBUFS); 1984251881Speter 1985251881Speter if (n->m_len < sizeof(*newmsg)) { 1986251881Speter n = m_pullup(n, sizeof(*newmsg)); 1987251881Speter if (!n) 1988251881Speter return key_senderror(so, m, ENOBUFS); 1989251881Speter } 1990251881Speter newmsg = mtod(n, struct sadb_msg *); 1991251881Speter newmsg->sadb_msg_errno = 0; 1992251881Speter newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); 1993251881Speter 1994251881Speter off = 0; 1995251881Speter mpolicy = m_pulldown(n, PFKEY_ALIGN8(sizeof(struct sadb_msg)), 1996251881Speter sizeof(*xpl), &off); 1997251881Speter if (mpolicy == NULL) { 1998251881Speter /* n is already freed */ 1999251881Speter return key_senderror(so, m, ENOBUFS); 2000251881Speter } 2001251881Speter xpl = (struct sadb_x_policy *)(mtod(mpolicy, caddr_t) + off); 2002251881Speter if (xpl->sadb_x_policy_exttype != SADB_X_EXT_POLICY) { 2003251881Speter m_freem(n); 2004251881Speter return key_senderror(so, m, EINVAL); 2005251881Speter } 2006251881Speter xpl->sadb_x_policy_id = newsp->id; 2007251881Speter 2008251881Speter m_freem(m); 2009251881Speter return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); 2010251881Speter } 2011251881Speter} 2012251881Speter 2013251881Speter/* 2014251881Speter * get new policy id. 2015251881Speter * OUT: 2016251881Speter * 0: failure. 2017251881Speter * others: success. 2018251881Speter */ 2019251881Speterstatic u_int32_t 2020251881Speterkey_getnewspid() 2021251881Speter{ 2022251881Speter INIT_VNET_IPSEC(curvnet); 2023251881Speter u_int32_t newid = 0; 2024251881Speter int count = V_key_spi_trycnt; /* XXX */ 2025251881Speter struct secpolicy *sp; 2026251881Speter 2027251881Speter /* when requesting to allocate spi ranged */ 2028251881Speter while (count--) { 2029251881Speter newid = (V_policy_id = (V_policy_id == ~0 ? 1 : V_policy_id + 1)); 2030251881Speter 2031251881Speter if ((sp = key_getspbyid(newid)) == NULL) 2032251881Speter break; 2033251881Speter 2034251881Speter KEY_FREESP(&sp); 2035251881Speter } 2036251881Speter 2037251881Speter if (count == 0 || newid == 0) { 2038251881Speter ipseclog((LOG_DEBUG, "%s: to allocate policy id is failed.\n", 2039251881Speter __func__)); 2040251881Speter return 0; 2041251881Speter } 2042251881Speter 2043251881Speter return newid; 2044251881Speter} 2045251881Speter 2046251881Speter/* 2047251881Speter * SADB_SPDDELETE processing 2048251881Speter * receive 2049251881Speter * <base, address(SD), policy(*)> 2050251881Speter * from the user(?), and set SADB_SASTATE_DEAD, 2051251881Speter * and send, 2052251881Speter * <base, address(SD), policy(*)> 2053251881Speter * to the ikmpd. 2054251881Speter * policy(*) including direction of policy. 2055251881Speter * 2056251881Speter * m will always be freed. 2057251881Speter */ 2058251881Speterstatic int 2059251881Speterkey_spddelete(so, m, mhp) 2060251881Speter struct socket *so; 2061251881Speter struct mbuf *m; 2062251881Speter const struct sadb_msghdr *mhp; 2063251881Speter{ 2064251881Speter INIT_VNET_IPSEC(curvnet); 2065251881Speter struct sadb_address *src0, *dst0; 2066251881Speter struct sadb_x_policy *xpl0; 2067251881Speter struct secpolicyindex spidx; 2068251881Speter struct secpolicy *sp; 2069251881Speter 2070251881Speter IPSEC_ASSERT(so != NULL, ("null so")); 2071251881Speter IPSEC_ASSERT(m != NULL, ("null mbuf")); 2072251881Speter IPSEC_ASSERT(mhp != NULL, ("null msghdr")); 2073251881Speter IPSEC_ASSERT(mhp->msg != NULL, ("null msg")); 2074251881Speter 2075251881Speter if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || 2076251881Speter mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || 2077251881Speter mhp->ext[SADB_X_EXT_POLICY] == NULL) { 2078251881Speter ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", 2079251881Speter __func__)); 2080251881Speter return key_senderror(so, m, EINVAL); 2081251881Speter } 2082251881Speter if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || 2083251881Speter mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address) || 2084251881Speter mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) { 2085251881Speter ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", 2086251881Speter __func__)); 2087251881Speter return key_senderror(so, m, EINVAL); 2088251881Speter } 2089251881Speter 2090251881Speter src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC]; 2091251881Speter dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST]; 2092251881Speter xpl0 = (struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY]; 2093251881Speter 2094251881Speter /* 2095251881Speter * Note: do not parse SADB_X_EXT_NAT_T_* here: 2096251881Speter * we are processing traffic endpoints. 2097251881Speter */ 2098251881Speter 2099251881Speter /* make secindex */ 2100251881Speter /* XXX boundary check against sa_len */ 2101251881Speter KEY_SETSECSPIDX(xpl0->sadb_x_policy_dir, 2102251881Speter src0 + 1, 2103251881Speter dst0 + 1, 2104251881Speter src0->sadb_address_prefixlen, 2105251881Speter dst0->sadb_address_prefixlen, 2106251881Speter src0->sadb_address_proto, 2107251881Speter &spidx); 2108251881Speter 2109251881Speter /* checking the direciton. */ 2110251881Speter switch (xpl0->sadb_x_policy_dir) { 2111251881Speter case IPSEC_DIR_INBOUND: 2112251881Speter case IPSEC_DIR_OUTBOUND: 2113251881Speter break; 2114251881Speter default: 2115251881Speter ipseclog((LOG_DEBUG, "%s: Invalid SP direction.\n", __func__)); 2116251881Speter return key_senderror(so, m, EINVAL); 2117251881Speter } 2118251881Speter 2119251881Speter /* Is there SP in SPD ? */ 2120251881Speter if ((sp = key_getsp(&spidx)) == NULL) { 2121251881Speter ipseclog((LOG_DEBUG, "%s: no SP found.\n", __func__)); 2122251881Speter return key_senderror(so, m, EINVAL); 2123251881Speter } 2124251881Speter 2125251881Speter /* save policy id to buffer to be returned. */ 2126251881Speter xpl0->sadb_x_policy_id = sp->id; 2127251881Speter 2128251881Speter sp->state = IPSEC_SPSTATE_DEAD; 2129251881Speter KEY_FREESP(&sp); 2130251881Speter 2131251881Speter { 2132251881Speter struct mbuf *n; 2133251881Speter struct sadb_msg *newmsg; 2134251881Speter 2135251881Speter /* 2136251881Speter * Note: do not send SADB_X_EXT_NAT_T_* here: 2137251881Speter * we are sending traffic endpoints. 2138251881Speter */ 2139251881Speter 2140251881Speter /* create new sadb_msg to reply. */ 2141251881Speter n = key_gather_mbuf(m, mhp, 1, 4, SADB_EXT_RESERVED, 2142251881Speter SADB_X_EXT_POLICY, SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST); 2143251881Speter if (!n) 2144251881Speter return key_senderror(so, m, ENOBUFS); 2145251881Speter 2146251881Speter newmsg = mtod(n, struct sadb_msg *); 2147251881Speter newmsg->sadb_msg_errno = 0; 2148251881Speter newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); 2149251881Speter 2150251881Speter m_freem(m); 2151251881Speter return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); 2152251881Speter } 2153251881Speter} 2154251881Speter 2155251881Speter/* 2156251881Speter * SADB_SPDDELETE2 processing 2157251881Speter * receive 2158251881Speter * <base, policy(*)> 2159251881Speter * from the user(?), and set SADB_SASTATE_DEAD, 2160251881Speter * and send, 2161251881Speter * <base, policy(*)> 2162251881Speter * to the ikmpd. 2163251881Speter * policy(*) including direction of policy. 2164251881Speter * 2165251881Speter * m will always be freed. 2166251881Speter */ 2167251881Speterstatic int 2168251881Speterkey_spddelete2(so, m, mhp) 2169251881Speter struct socket *so; 2170251881Speter struct mbuf *m; 2171251881Speter const struct sadb_msghdr *mhp; 2172251881Speter{ 2173251881Speter INIT_VNET_IPSEC(curvnet); 2174251881Speter u_int32_t id; 2175251881Speter struct secpolicy *sp; 2176251881Speter 2177251881Speter IPSEC_ASSERT(so != NULL, ("null socket")); 2178251881Speter IPSEC_ASSERT(m != NULL, ("null mbuf")); 2179251881Speter IPSEC_ASSERT(mhp != NULL, ("null msghdr")); 2180251881Speter IPSEC_ASSERT(mhp->msg != NULL, ("null msg")); 2181251881Speter 2182251881Speter if (mhp->ext[SADB_X_EXT_POLICY] == NULL || 2183251881Speter mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) { 2184251881Speter ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", __func__)); 2185251881Speter return key_senderror(so, m, EINVAL); 2186251881Speter } 2187251881Speter 2188251881Speter id = ((struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY])->sadb_x_policy_id; 2189251881Speter 2190251881Speter /* Is there SP in SPD ? */ 2191251881Speter if ((sp = key_getspbyid(id)) == NULL) { 2192251881Speter ipseclog((LOG_DEBUG, "%s: no SP found id:%u.\n", __func__, id)); 2193251881Speter return key_senderror(so, m, EINVAL); 2194251881Speter } 2195251881Speter 2196251881Speter sp->state = IPSEC_SPSTATE_DEAD; 2197251881Speter KEY_FREESP(&sp); 2198251881Speter 2199251881Speter { 2200251881Speter struct mbuf *n, *nn; 2201251881Speter struct sadb_msg *newmsg; 2202251881Speter int off, len; 2203251881Speter 2204251881Speter /* create new sadb_msg to reply. */ 2205251881Speter len = PFKEY_ALIGN8(sizeof(struct sadb_msg)); 2206251881Speter 2207251881Speter MGETHDR(n, M_DONTWAIT, MT_DATA); 2208251881Speter if (n && len > MHLEN) { 2209251881Speter MCLGET(n, M_DONTWAIT); 2210251881Speter if ((n->m_flags & M_EXT) == 0) { 2211251881Speter m_freem(n); 2212251881Speter n = NULL; 2213251881Speter } 2214251881Speter } 2215251881Speter if (!n) 2216251881Speter return key_senderror(so, m, ENOBUFS); 2217251881Speter 2218251881Speter n->m_len = len; 2219251881Speter n->m_next = NULL; 2220251881Speter off = 0; 2221251881Speter 2222251881Speter m_copydata(m, 0, sizeof(struct sadb_msg), mtod(n, caddr_t) + off); 2223251881Speter off += PFKEY_ALIGN8(sizeof(struct sadb_msg)); 2224251881Speter 2225251881Speter IPSEC_ASSERT(off == len, ("length inconsistency (off %u len %u)", 2226251881Speter off, len)); 2227251881Speter 2228251881Speter n->m_next = m_copym(m, mhp->extoff[SADB_X_EXT_POLICY], 2229251881Speter mhp->extlen[SADB_X_EXT_POLICY], M_DONTWAIT); 2230251881Speter if (!n->m_next) { 2231251881Speter m_freem(n); 2232251881Speter return key_senderror(so, m, ENOBUFS); 2233251881Speter } 2234251881Speter 2235251881Speter n->m_pkthdr.len = 0; 2236251881Speter for (nn = n; nn; nn = nn->m_next) 2237251881Speter n->m_pkthdr.len += nn->m_len; 2238251881Speter 2239251881Speter newmsg = mtod(n, struct sadb_msg *); 2240251881Speter newmsg->sadb_msg_errno = 0; 2241251881Speter newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); 2242251881Speter 2243251881Speter m_freem(m); 2244251881Speter return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); 2245251881Speter } 2246251881Speter} 2247251881Speter 2248251881Speter/* 2249251881Speter * SADB_X_GET processing 2250251881Speter * receive 2251251881Speter * <base, policy(*)> 2252251881Speter * from the user(?), 2253251881Speter * and send, 2254251881Speter * <base, address(SD), policy> 2255251881Speter * to the ikmpd. 2256251881Speter * policy(*) including direction of policy. 2257251881Speter * 2258251881Speter * m will always be freed. 2259251881Speter */ 2260251881Speterstatic int 2261251881Speterkey_spdget(so, m, mhp) 2262251881Speter struct socket *so; 2263251881Speter struct mbuf *m; 2264251881Speter const struct sadb_msghdr *mhp; 2265251881Speter{ 2266251881Speter INIT_VNET_IPSEC(curvnet); 2267251881Speter u_int32_t id; 2268251881Speter struct secpolicy *sp; 2269251881Speter struct mbuf *n; 2270251881Speter 2271251881Speter IPSEC_ASSERT(so != NULL, ("null socket")); 2272251881Speter IPSEC_ASSERT(m != NULL, ("null mbuf")); 2273251881Speter IPSEC_ASSERT(mhp != NULL, ("null msghdr")); 2274251881Speter IPSEC_ASSERT(mhp->msg != NULL, ("null msg")); 2275251881Speter 2276251881Speter if (mhp->ext[SADB_X_EXT_POLICY] == NULL || 2277251881Speter mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) { 2278251881Speter ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", 2279251881Speter __func__)); 2280251881Speter return key_senderror(so, m, EINVAL); 2281251881Speter } 2282251881Speter 2283251881Speter id = ((struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY])->sadb_x_policy_id; 2284251881Speter 2285251881Speter /* Is there SP in SPD ? */ 2286251881Speter if ((sp = key_getspbyid(id)) == NULL) { 2287251881Speter ipseclog((LOG_DEBUG, "%s: no SP found id:%u.\n", __func__, id)); 2288251881Speter return key_senderror(so, m, ENOENT); 2289251881Speter } 2290251881Speter 2291251881Speter n = key_setdumpsp(sp, SADB_X_SPDGET, 0, mhp->msg->sadb_msg_pid); 2292251881Speter if (n != NULL) { 2293251881Speter m_freem(m); 2294251881Speter return key_sendup_mbuf(so, n, KEY_SENDUP_ONE); 2295251881Speter } else 2296251881Speter return key_senderror(so, m, ENOBUFS); 2297251881Speter} 2298251881Speter 2299251881Speter/* 2300251881Speter * SADB_X_SPDACQUIRE processing. 2301251881Speter * Acquire policy and SA(s) for a *OUTBOUND* packet. 2302251881Speter * send 2303251881Speter * <base, policy(*)> 2304251881Speter * to KMD, and expect to receive 2305251881Speter * <base> with SADB_X_SPDACQUIRE if error occured, 2306251881Speter * or 2307251881Speter * <base, policy> 2308251881Speter * with SADB_X_SPDUPDATE from KMD by PF_KEY. 2309251881Speter * policy(*) is without policy requests. 2310251881Speter * 2311251881Speter * 0 : succeed 2312251881Speter * others: error number 2313251881Speter */ 2314251881Speterint 2315251881Speterkey_spdacquire(sp) 2316251881Speter struct secpolicy *sp; 2317251881Speter{ 2318251881Speter INIT_VNET_IPSEC(curvnet); 2319251881Speter struct mbuf *result = NULL, *m; 2320251881Speter struct secspacq *newspacq; 2321251881Speter 2322251881Speter IPSEC_ASSERT(sp != NULL, ("null secpolicy")); 2323251881Speter IPSEC_ASSERT(sp->req == NULL, ("policy exists")); 2324251881Speter IPSEC_ASSERT(sp->policy == IPSEC_POLICY_IPSEC, 2325251881Speter ("policy not IPSEC %u", sp->policy)); 2326251881Speter 2327251881Speter /* Get an entry to check whether sent message or not. */ 2328251881Speter newspacq = key_getspacq(&sp->spidx); 2329251881Speter if (newspacq != NULL) { 2330251881Speter if (V_key_blockacq_count < newspacq->count) { 2331251881Speter /* reset counter and do send message. */ 2332251881Speter newspacq->count = 0; 2333251881Speter } else { 2334251881Speter /* increment counter and do nothing. */ 2335251881Speter newspacq->count++; 2336251881Speter return 0; 2337251881Speter } 2338251881Speter SPACQ_UNLOCK(); 2339251881Speter } else { 2340251881Speter /* make new entry for blocking to send SADB_ACQUIRE. */ 2341251881Speter newspacq = key_newspacq(&sp->spidx); 2342251881Speter if (newspacq == NULL) 2343251881Speter return ENOBUFS; 2344251881Speter } 2345251881Speter 2346251881Speter /* create new sadb_msg to reply. */ 2347251881Speter m = key_setsadbmsg(SADB_X_SPDACQUIRE, 0, 0, 0, 0, 0); 2348251881Speter if (!m) 2349251881Speter return ENOBUFS; 2350251881Speter 2351251881Speter result = m; 2352251881Speter 2353251881Speter result->m_pkthdr.len = 0; 2354251881Speter for (m = result; m; m = m->m_next) 2355251881Speter result->m_pkthdr.len += m->m_len; 2356251881Speter 2357251881Speter mtod(result, struct sadb_msg *)->sadb_msg_len = 2358251881Speter PFKEY_UNIT64(result->m_pkthdr.len); 2359251881Speter 2360251881Speter return key_sendup_mbuf(NULL, m, KEY_SENDUP_REGISTERED); 2361251881Speter} 2362251881Speter 2363251881Speter/* 2364251881Speter * SADB_SPDFLUSH processing 2365251881Speter * receive 2366251881Speter * <base> 2367251881Speter * from the user, and free all entries in secpctree. 2368251881Speter * and send, 2369251881Speter * <base> 2370251881Speter * to the user. 2371251881Speter * NOTE: what to do is only marking SADB_SASTATE_DEAD. 2372251881Speter * 2373251881Speter * m will always be freed. 2374251881Speter */ 2375251881Speterstatic int 2376251881Speterkey_spdflush(so, m, mhp) 2377251881Speter struct socket *so; 2378251881Speter struct mbuf *m; 2379251881Speter const struct sadb_msghdr *mhp; 2380251881Speter{ 2381251881Speter INIT_VNET_IPSEC(curvnet); 2382251881Speter struct sadb_msg *newmsg; 2383251881Speter struct secpolicy *sp; 2384251881Speter u_int dir; 2385251881Speter 2386251881Speter IPSEC_ASSERT(so != NULL, ("null socket")); 2387251881Speter IPSEC_ASSERT(m != NULL, ("null mbuf")); 2388251881Speter IPSEC_ASSERT(mhp != NULL, ("null msghdr")); 2389251881Speter IPSEC_ASSERT(mhp->msg != NULL, ("null msg")); 2390251881Speter 2391251881Speter if (m->m_len != PFKEY_ALIGN8(sizeof(struct sadb_msg))) 2392251881Speter return key_senderror(so, m, EINVAL); 2393251881Speter 2394251881Speter for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { 2395251881Speter SPTREE_LOCK(); 2396251881Speter LIST_FOREACH(sp, &V_sptree[dir], chain) 2397251881Speter sp->state = IPSEC_SPSTATE_DEAD; 2398251881Speter SPTREE_UNLOCK(); 2399251881Speter } 2400251881Speter 2401251881Speter if (sizeof(struct sadb_msg) > m->m_len + M_TRAILINGSPACE(m)) { 2402251881Speter ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__)); 2403251881Speter return key_senderror(so, m, ENOBUFS); 2404251881Speter } 2405251881Speter 2406251881Speter if (m->m_next) 2407251881Speter m_freem(m->m_next); 2408251881Speter m->m_next = NULL; 2409251881Speter m->m_pkthdr.len = m->m_len = PFKEY_ALIGN8(sizeof(struct sadb_msg)); 2410251881Speter newmsg = mtod(m, struct sadb_msg *); 2411251881Speter newmsg->sadb_msg_errno = 0; 2412251881Speter newmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); 2413251881Speter 2414251881Speter return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); 2415251881Speter} 2416251881Speter 2417251881Speter/* 2418251881Speter * SADB_SPDDUMP processing 2419251881Speter * receive 2420251881Speter * <base> 2421251881Speter * from the user, and dump all SP leaves 2422251881Speter * and send, 2423251881Speter * <base> ..... 2424251881Speter * to the ikmpd. 2425251881Speter * 2426251881Speter * m will always be freed. 2427251881Speter */ 2428251881Speterstatic int 2429251881Speterkey_spddump(so, m, mhp) 2430251881Speter struct socket *so; 2431251881Speter struct mbuf *m; 2432251881Speter const struct sadb_msghdr *mhp; 2433251881Speter{ 2434251881Speter INIT_VNET_IPSEC(curvnet); 2435251881Speter struct secpolicy *sp; 2436251881Speter int cnt; 2437251881Speter u_int dir; 2438251881Speter struct mbuf *n; 2439251881Speter 2440251881Speter IPSEC_ASSERT(so != NULL, ("null socket")); 2441251881Speter IPSEC_ASSERT(m != NULL, ("null mbuf")); 2442251881Speter IPSEC_ASSERT(mhp != NULL, ("null msghdr")); 2443251881Speter IPSEC_ASSERT(mhp->msg != NULL, ("null msg")); 2444251881Speter 2445251881Speter /* search SPD entry and get buffer size. */ 2446251881Speter cnt = 0; 2447251881Speter SPTREE_LOCK(); 2448251881Speter for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { 2449251881Speter LIST_FOREACH(sp, &V_sptree[dir], chain) { 2450251881Speter cnt++; 2451251881Speter } 2452251881Speter } 2453251881Speter 2454251881Speter if (cnt == 0) { 2455251881Speter SPTREE_UNLOCK(); 2456251881Speter return key_senderror(so, m, ENOENT); 2457251881Speter } 2458251881Speter 2459251881Speter for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { 2460251881Speter LIST_FOREACH(sp, &V_sptree[dir], chain) { 2461251881Speter --cnt; 2462251881Speter n = key_setdumpsp(sp, SADB_X_SPDDUMP, cnt, 2463251881Speter mhp->msg->sadb_msg_pid); 2464251881Speter 2465251881Speter if (n) 2466251881Speter key_sendup_mbuf(so, n, KEY_SENDUP_ONE); 2467251881Speter } 2468251881Speter } 2469251881Speter 2470251881Speter SPTREE_UNLOCK(); 2471251881Speter m_freem(m); 2472251881Speter return 0; 2473251881Speter} 2474251881Speter 2475251881Speterstatic struct mbuf * 2476251881Speterkey_setdumpsp(struct secpolicy *sp, u_int8_t type, u_int32_t seq, u_int32_t pid) 2477251881Speter{ 2478251881Speter struct mbuf *result = NULL, *m; 2479251881Speter struct seclifetime lt; 2480251881Speter 2481251881Speter m = key_setsadbmsg(type, 0, SADB_SATYPE_UNSPEC, seq, pid, sp->refcnt); 2482251881Speter if (!m) 2483251881Speter goto fail; 2484251881Speter result = m; 2485251881Speter 2486251881Speter /* 2487251881Speter * Note: do not send SADB_X_EXT_NAT_T_* here: 2488251881Speter * we are sending traffic endpoints. 2489251881Speter */ 2490251881Speter m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, 2491251881Speter &sp->spidx.src.sa, sp->spidx.prefs, 2492251881Speter sp->spidx.ul_proto); 2493251881Speter if (!m) 2494251881Speter goto fail; 2495251881Speter m_cat(result, m); 2496251881Speter 2497251881Speter m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, 2498251881Speter &sp->spidx.dst.sa, sp->spidx.prefd, 2499251881Speter sp->spidx.ul_proto); 2500251881Speter if (!m) 2501251881Speter goto fail; 2502251881Speter m_cat(result, m); 2503251881Speter 2504251881Speter m = key_sp2msg(sp); 2505251881Speter if (!m) 2506251881Speter goto fail; 2507251881Speter m_cat(result, m); 2508251881Speter 2509251881Speter if(sp->lifetime){ 2510251881Speter lt.addtime=sp->created; 2511251881Speter lt.usetime= sp->lastused; 2512251881Speter m = key_setlifetime(<, SADB_EXT_LIFETIME_CURRENT); 2513251881Speter if (!m) 2514251881Speter goto fail; 2515251881Speter m_cat(result, m); 2516251881Speter 2517251881Speter lt.addtime=sp->lifetime; 2518251881Speter lt.usetime= sp->validtime; 2519251881Speter m = key_setlifetime(<, SADB_EXT_LIFETIME_HARD); 2520251881Speter if (!m) 2521251881Speter goto fail; 2522251881Speter m_cat(result, m); 2523251881Speter } 2524251881Speter 2525251881Speter if ((result->m_flags & M_PKTHDR) == 0) 2526251881Speter goto fail; 2527251881Speter 2528251881Speter if (result->m_len < sizeof(struct sadb_msg)) { 2529251881Speter result = m_pullup(result, sizeof(struct sadb_msg)); 2530251881Speter if (result == NULL) 2531251881Speter goto fail; 2532251881Speter } 2533251881Speter 2534251881Speter result->m_pkthdr.len = 0; 2535251881Speter for (m = result; m; m = m->m_next) 2536251881Speter result->m_pkthdr.len += m->m_len; 2537251881Speter 2538251881Speter mtod(result, struct sadb_msg *)->sadb_msg_len = 2539251881Speter PFKEY_UNIT64(result->m_pkthdr.len); 2540251881Speter 2541251881Speter return result; 2542251881Speter 2543251881Speterfail: 2544251881Speter m_freem(result); 2545251881Speter return NULL; 2546251881Speter} 2547251881Speter 2548251881Speter/* 2549251881Speter * get PFKEY message length for security policy and request. 2550251881Speter */ 2551251881Speterstatic u_int 2552251881Speterkey_getspreqmsglen(sp) 2553251881Speter struct secpolicy *sp; 2554251881Speter{ 2555251881Speter u_int tlen; 2556251881Speter 2557251881Speter tlen = sizeof(struct sadb_x_policy); 2558251881Speter 2559251881Speter /* if is the policy for ipsec ? */ 2560251881Speter if (sp->policy != IPSEC_POLICY_IPSEC) 2561251881Speter return tlen; 2562251881Speter 2563251881Speter /* get length of ipsec requests */ 2564251881Speter { 2565251881Speter struct ipsecrequest *isr; 2566251881Speter int len; 2567251881Speter 2568251881Speter for (isr = sp->req; isr != NULL; isr = isr->next) { 2569251881Speter len = sizeof(struct sadb_x_ipsecrequest) 2570251881Speter + isr->saidx.src.sa.sa_len 2571251881Speter + isr->saidx.dst.sa.sa_len; 2572251881Speter 2573251881Speter tlen += PFKEY_ALIGN8(len); 2574251881Speter } 2575251881Speter } 2576251881Speter 2577251881Speter return tlen; 2578251881Speter} 2579251881Speter 2580251881Speter/* 2581251881Speter * SADB_SPDEXPIRE processing 2582251881Speter * send 2583251881Speter * <base, address(SD), lifetime(CH), policy> 2584251881Speter * to KMD by PF_KEY. 2585251881Speter * 2586251881Speter * OUT: 0 : succeed 2587251881Speter * others : error number 2588251881Speter */ 2589251881Speterstatic int 2590251881Speterkey_spdexpire(sp) 2591251881Speter struct secpolicy *sp; 2592251881Speter{ 2593251881Speter struct mbuf *result = NULL, *m; 2594251881Speter int len; 2595251881Speter int error = -1; 2596251881Speter struct sadb_lifetime *lt; 2597251881Speter 2598251881Speter /* XXX: Why do we lock ? */ 2599251881Speter 2600251881Speter IPSEC_ASSERT(sp != NULL, ("null secpolicy")); 2601251881Speter 2602251881Speter /* set msg header */ 2603251881Speter m = key_setsadbmsg(SADB_X_SPDEXPIRE, 0, 0, 0, 0, 0); 2604251881Speter if (!m) { 2605251881Speter error = ENOBUFS; 2606251881Speter goto fail; 2607251881Speter } 2608251881Speter result = m; 2609251881Speter 2610251881Speter /* create lifetime extension (current and hard) */ 2611251881Speter len = PFKEY_ALIGN8(sizeof(*lt)) * 2; 2612251881Speter m = key_alloc_mbuf(len); 2613251881Speter if (!m || m->m_next) { /*XXX*/ 2614251881Speter if (m) 2615251881Speter m_freem(m); 2616251881Speter error = ENOBUFS; 2617251881Speter goto fail; 2618251881Speter } 2619251881Speter bzero(mtod(m, caddr_t), len); 2620251881Speter lt = mtod(m, struct sadb_lifetime *); 2621251881Speter lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime)); 2622251881Speter lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT; 2623251881Speter lt->sadb_lifetime_allocations = 0; 2624251881Speter lt->sadb_lifetime_bytes = 0; 2625251881Speter lt->sadb_lifetime_addtime = sp->created; 2626251881Speter lt->sadb_lifetime_usetime = sp->lastused; 2627251881Speter lt = (struct sadb_lifetime *)(mtod(m, caddr_t) + len / 2); 2628251881Speter lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime)); 2629251881Speter lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD; 2630251881Speter lt->sadb_lifetime_allocations = 0; 2631251881Speter lt->sadb_lifetime_bytes = 0; 2632251881Speter lt->sadb_lifetime_addtime = sp->lifetime; 2633251881Speter lt->sadb_lifetime_usetime = sp->validtime; 2634251881Speter m_cat(result, m); 2635251881Speter 2636251881Speter /* 2637251881Speter * Note: do not send SADB_X_EXT_NAT_T_* here: 2638251881Speter * we are sending traffic endpoints. 2639251881Speter */ 2640251881Speter 2641251881Speter /* set sadb_address for source */ 2642251881Speter m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, 2643251881Speter &sp->spidx.src.sa, 2644251881Speter sp->spidx.prefs, sp->spidx.ul_proto); 2645251881Speter if (!m) { 2646251881Speter error = ENOBUFS; 2647251881Speter goto fail; 2648251881Speter } 2649251881Speter m_cat(result, m); 2650251881Speter 2651251881Speter /* set sadb_address for destination */ 2652251881Speter m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, 2653251881Speter &sp->spidx.dst.sa, 2654251881Speter sp->spidx.prefd, sp->spidx.ul_proto); 2655251881Speter if (!m) { 2656251881Speter error = ENOBUFS; 2657251881Speter goto fail; 2658251881Speter } 2659251881Speter m_cat(result, m); 2660251881Speter 2661251881Speter /* set secpolicy */ 2662251881Speter m = key_sp2msg(sp); 2663251881Speter if (!m) { 2664251881Speter error = ENOBUFS; 2665251881Speter goto fail; 2666251881Speter } 2667251881Speter m_cat(result, m); 2668251881Speter 2669251881Speter if ((result->m_flags & M_PKTHDR) == 0) { 2670251881Speter error = EINVAL; 2671251881Speter goto fail; 2672251881Speter } 2673251881Speter 2674251881Speter if (result->m_len < sizeof(struct sadb_msg)) { 2675251881Speter result = m_pullup(result, sizeof(struct sadb_msg)); 2676251881Speter if (result == NULL) { 2677251881Speter error = ENOBUFS; 2678251881Speter goto fail; 2679251881Speter } 2680251881Speter } 2681251881Speter 2682251881Speter result->m_pkthdr.len = 0; 2683251881Speter for (m = result; m; m = m->m_next) 2684251881Speter result->m_pkthdr.len += m->m_len; 2685251881Speter 2686251881Speter mtod(result, struct sadb_msg *)->sadb_msg_len = 2687251881Speter PFKEY_UNIT64(result->m_pkthdr.len); 2688251881Speter 2689251881Speter return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED); 2690251881Speter 2691251881Speter fail: 2692251881Speter if (result) 2693251881Speter m_freem(result); 2694251881Speter return error; 2695251881Speter} 2696251881Speter 2697251881Speter/* %%% SAD management */ 2698251881Speter/* 2699251881Speter * allocating a memory for new SA head, and copy from the values of mhp. 2700251881Speter * OUT: NULL : failure due to the lack of memory. 2701251881Speter * others : pointer to new SA head. 2702251881Speter */ 2703251881Speterstatic struct secashead * 2704251881Speterkey_newsah(saidx) 2705251881Speter struct secasindex *saidx; 2706251881Speter{ 2707251881Speter INIT_VNET_IPSEC(curvnet); 2708251881Speter struct secashead *newsah; 2709251881Speter 2710251881Speter IPSEC_ASSERT(saidx != NULL, ("null saidx")); 2711251881Speter 2712251881Speter newsah = malloc(sizeof(struct secashead), M_IPSEC_SAH, M_NOWAIT|M_ZERO); 2713251881Speter if (newsah != NULL) { 2714251881Speter int i; 2715251881Speter for (i = 0; i < sizeof(newsah->savtree)/sizeof(newsah->savtree[0]); i++) 2716251881Speter LIST_INIT(&newsah->savtree[i]); 2717251881Speter newsah->saidx = *saidx; 2718251881Speter 2719251881Speter /* add to saidxtree */ 2720251881Speter newsah->state = SADB_SASTATE_MATURE; 2721251881Speter 2722251881Speter SAHTREE_LOCK(); 2723251881Speter LIST_INSERT_HEAD(&V_sahtree, newsah, chain); 2724251881Speter SAHTREE_UNLOCK(); 2725251881Speter } 2726251881Speter return(newsah); 2727251881Speter} 2728251881Speter 2729251881Speter/* 2730251881Speter * delete SA index and all SA registerd. 2731251881Speter */ 2732251881Speterstatic void 2733251881Speterkey_delsah(sah) 2734251881Speter struct secashead *sah; 2735251881Speter{ 2736251881Speter INIT_VNET_IPSEC(curvnet); 2737251881Speter struct secasvar *sav, *nextsav; 2738251881Speter u_int stateidx; 2739251881Speter int zombie = 0; 2740251881Speter 2741251881Speter IPSEC_ASSERT(sah != NULL, ("NULL sah")); 2742251881Speter SAHTREE_LOCK_ASSERT(); 2743251881Speter 2744251881Speter /* searching all SA registerd in the secindex. */ 2745251881Speter for (stateidx = 0; 2746251881Speter stateidx < _ARRAYLEN(saorder_state_any); 2747251881Speter stateidx++) { 2748251881Speter u_int state = saorder_state_any[stateidx]; 2749251881Speter LIST_FOREACH_SAFE(sav, &sah->savtree[state], chain, nextsav) { 2750251881Speter if (sav->refcnt == 0) { 2751251881Speter /* sanity check */ 2752251881Speter KEY_CHKSASTATE(state, sav->state, __func__); 2753251881Speter /* 2754251881Speter * do NOT call KEY_FREESAV here: 2755251881Speter * it will only delete the sav if refcnt == 1, 2756251881Speter * where we already know that refcnt == 0 2757251881Speter */ 2758251881Speter key_delsav(sav); 2759251881Speter } else { 2760251881Speter /* give up to delete this sa */ 2761251881Speter zombie++; 2762251881Speter } 2763251881Speter } 2764251881Speter } 2765251881Speter if (!zombie) { /* delete only if there are savs */ 2766251881Speter /* remove from tree of SA index */ 2767251881Speter if (__LIST_CHAINED(sah)) 2768251881Speter LIST_REMOVE(sah, chain); 2769251881Speter if (sah->sa_route.ro_rt) { 2770251881Speter RTFREE(sah->sa_route.ro_rt); 2771251881Speter sah->sa_route.ro_rt = (struct rtentry *)NULL; 2772251881Speter } 2773251881Speter free(sah, M_IPSEC_SAH); 2774251881Speter } 2775251881Speter} 2776251881Speter 2777251881Speter/* 2778251881Speter * allocating a new SA with LARVAL state. key_add() and key_getspi() call, 2779251881Speter * and copy the values of mhp into new buffer. 2780251881Speter * When SAD message type is GETSPI: 2781251881Speter * to set sequence number from acq_seq++, 2782251881Speter * to set zero to SPI. 2783251881Speter * not to call key_setsava(). 2784251881Speter * OUT: NULL : fail 2785251881Speter * others : pointer to new secasvar. 2786251881Speter * 2787251881Speter * does not modify mbuf. does not free mbuf on error. 2788251881Speter */ 2789251881Speterstatic struct secasvar * 2790251881Speterkey_newsav(m, mhp, sah, errp, where, tag) 2791251881Speter struct mbuf *m; 2792251881Speter const struct sadb_msghdr *mhp; 2793251881Speter struct secashead *sah; 2794251881Speter int *errp; 2795251881Speter const char* where; 2796251881Speter int tag; 2797251881Speter{ 2798251881Speter INIT_VNET_IPSEC(curvnet); 2799251881Speter struct secasvar *newsav; 2800251881Speter const struct sadb_sa *xsa; 2801251881Speter 2802251881Speter IPSEC_ASSERT(m != NULL, ("null mbuf")); 2803251881Speter IPSEC_ASSERT(mhp != NULL, ("null msghdr")); 2804251881Speter IPSEC_ASSERT(mhp->msg != NULL, ("null msg")); 2805251881Speter IPSEC_ASSERT(sah != NULL, ("null secashead")); 2806251881Speter 2807251881Speter newsav = malloc(sizeof(struct secasvar), M_IPSEC_SA, M_NOWAIT|M_ZERO); 2808251881Speter if (newsav == NULL) { 2809251881Speter ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__)); 2810251881Speter *errp = ENOBUFS; 2811251881Speter goto done; 2812251881Speter } 2813251881Speter 2814251881Speter switch (mhp->msg->sadb_msg_type) { 2815251881Speter case SADB_GETSPI: 2816251881Speter newsav->spi = 0; 2817251881Speter 2818251881Speter#ifdef IPSEC_DOSEQCHECK 2819251881Speter /* sync sequence number */ 2820251881Speter if (mhp->msg->sadb_msg_seq == 0) 2821251881Speter newsav->seq = 2822251881Speter (V_acq_seq = (V_acq_seq == ~0 ? 1 : ++V_acq_seq)); 2823251881Speter else 2824251881Speter#endif 2825251881Speter newsav->seq = mhp->msg->sadb_msg_seq; 2826251881Speter break; 2827251881Speter 2828251881Speter case SADB_ADD: 2829251881Speter /* sanity check */ 2830251881Speter if (mhp->ext[SADB_EXT_SA] == NULL) { 2831251881Speter free(newsav, M_IPSEC_SA); 2832251881Speter newsav = NULL; 2833251881Speter ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", 2834251881Speter __func__)); 2835251881Speter *errp = EINVAL; 2836251881Speter goto done; 2837251881Speter } 2838251881Speter xsa = (const struct sadb_sa *)mhp->ext[SADB_EXT_SA]; 2839251881Speter newsav->spi = xsa->sadb_sa_spi; 2840251881Speter newsav->seq = mhp->msg->sadb_msg_seq; 2841251881Speter break; 2842251881Speter default: 2843251881Speter free(newsav, M_IPSEC_SA); 2844251881Speter newsav = NULL; 2845251881Speter *errp = EINVAL; 2846251881Speter goto done; 2847251881Speter } 2848251881Speter 2849251881Speter 2850251881Speter /* copy sav values */ 2851251881Speter if (mhp->msg->sadb_msg_type != SADB_GETSPI) { 2852251881Speter *errp = key_setsaval(newsav, m, mhp); 2853251881Speter if (*errp) { 2854251881Speter free(newsav, M_IPSEC_SA); 2855251881Speter newsav = NULL; 2856251881Speter goto done; 2857251881Speter } 2858251881Speter } 2859251881Speter 2860251881Speter SECASVAR_LOCK_INIT(newsav); 2861251881Speter 2862251881Speter /* reset created */ 2863251881Speter newsav->created = time_second; 2864251881Speter newsav->pid = mhp->msg->sadb_msg_pid; 2865251881Speter 2866251881Speter /* add to satree */ 2867251881Speter newsav->sah = sah; 2868251881Speter sa_initref(newsav); 2869251881Speter newsav->state = SADB_SASTATE_LARVAL; 2870251881Speter 2871251881Speter /* XXX locking??? */ 2872251881Speter LIST_INSERT_TAIL(&sah->savtree[SADB_SASTATE_LARVAL], newsav, 2873251881Speter secasvar, chain); 2874251881Speterdone: 2875251881Speter KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 2876251881Speter printf("DP %s from %s:%u return SP:%p\n", __func__, 2877251881Speter where, tag, newsav)); 2878251881Speter 2879251881Speter return newsav; 2880251881Speter} 2881251881Speter 2882251881Speter/* 2883251881Speter * free() SA variable entry. 2884251881Speter */ 2885251881Speterstatic void 2886251881Speterkey_cleansav(struct secasvar *sav) 2887251881Speter{ 2888251881Speter /* 2889251881Speter * Cleanup xform state. Note that zeroize'ing causes the 2890251881Speter * keys to be cleared; otherwise we must do it ourself. 2891251881Speter */ 2892251881Speter if (sav->tdb_xform != NULL) { 2893251881Speter sav->tdb_xform->xf_zeroize(sav); 2894251881Speter sav->tdb_xform = NULL; 2895251881Speter } else { 2896251881Speter KASSERT(sav->iv == NULL, ("iv but no xform")); 2897251881Speter if (sav->key_auth != NULL) 2898251881Speter bzero(sav->key_auth->key_data, _KEYLEN(sav->key_auth)); 2899251881Speter if (sav->key_enc != NULL) 2900251881Speter bzero(sav->key_enc->key_data, _KEYLEN(sav->key_enc)); 2901251881Speter } 2902251881Speter if (sav->key_auth != NULL) { 2903251881Speter if (sav->key_auth->key_data != NULL) 2904251881Speter free(sav->key_auth->key_data, M_IPSEC_MISC); 2905251881Speter free(sav->key_auth, M_IPSEC_MISC); 2906251881Speter sav->key_auth = NULL; 2907251881Speter } 2908251881Speter if (sav->key_enc != NULL) { 2909251881Speter if (sav->key_enc->key_data != NULL) 2910251881Speter free(sav->key_enc->key_data, M_IPSEC_MISC); 2911251881Speter free(sav->key_enc, M_IPSEC_MISC); 2912251881Speter sav->key_enc = NULL; 2913251881Speter } 2914251881Speter if (sav->sched) { 2915251881Speter bzero(sav->sched, sav->schedlen); 2916251881Speter free(sav->sched, M_IPSEC_MISC); 2917251881Speter sav->sched = NULL; 2918251881Speter } 2919251881Speter if (sav->replay != NULL) { 2920251881Speter free(sav->replay, M_IPSEC_MISC); 2921251881Speter sav->replay = NULL; 2922251881Speter } 2923251881Speter if (sav->lft_c != NULL) { 2924251881Speter free(sav->lft_c, M_IPSEC_MISC); 2925251881Speter sav->lft_c = NULL; 2926251881Speter } 2927251881Speter if (sav->lft_h != NULL) { 2928251881Speter free(sav->lft_h, M_IPSEC_MISC); 2929251881Speter sav->lft_h = NULL; 2930251881Speter } 2931251881Speter if (sav->lft_s != NULL) { 2932251881Speter free(sav->lft_s, M_IPSEC_MISC); 2933251881Speter sav->lft_s = NULL; 2934251881Speter } 2935251881Speter} 2936251881Speter 2937251881Speter/* 2938251881Speter * free() SA variable entry. 2939251881Speter */ 2940251881Speterstatic void 2941251881Speterkey_delsav(sav) 2942251881Speter struct secasvar *sav; 2943251881Speter{ 2944251881Speter IPSEC_ASSERT(sav != NULL, ("null sav")); 2945251881Speter IPSEC_ASSERT(sav->refcnt == 0, ("reference count %u > 0", sav->refcnt)); 2946251881Speter 2947251881Speter /* remove from SA header */ 2948251881Speter if (__LIST_CHAINED(sav)) 2949251881Speter LIST_REMOVE(sav, chain); 2950251881Speter key_cleansav(sav); 2951251881Speter SECASVAR_LOCK_DESTROY(sav); 2952251881Speter free(sav, M_IPSEC_SA); 2953251881Speter} 2954251881Speter 2955251881Speter/* 2956251881Speter * search SAD. 2957251881Speter * OUT: 2958251881Speter * NULL : not found 2959251881Speter * others : found, pointer to a SA. 2960251881Speter */ 2961251881Speterstatic struct secashead * 2962251881Speterkey_getsah(saidx) 2963251881Speter struct secasindex *saidx; 2964251881Speter{ 2965251881Speter INIT_VNET_IPSEC(curvnet); 2966251881Speter struct secashead *sah; 2967251881Speter 2968251881Speter SAHTREE_LOCK(); 2969251881Speter LIST_FOREACH(sah, &V_sahtree, chain) { 2970251881Speter if (sah->state == SADB_SASTATE_DEAD) 2971251881Speter continue; 2972251881Speter if (key_cmpsaidx(&sah->saidx, saidx, CMP_REQID)) 2973251881Speter break; 2974251881Speter } 2975251881Speter SAHTREE_UNLOCK(); 2976251881Speter 2977251881Speter return sah; 2978251881Speter} 2979251881Speter 2980251881Speter/* 2981251881Speter * check not to be duplicated SPI. 2982251881Speter * NOTE: this function is too slow due to searching all SAD. 2983251881Speter * OUT: 2984251881Speter * NULL : not found 2985251881Speter * others : found, pointer to a SA. 2986251881Speter */ 2987251881Speterstatic struct secasvar * 2988251881Speterkey_checkspidup(saidx, spi) 2989251881Speter struct secasindex *saidx; 2990251881Speter u_int32_t spi; 2991251881Speter{ 2992251881Speter INIT_VNET_IPSEC(curvnet); 2993251881Speter struct secashead *sah; 2994251881Speter struct secasvar *sav; 2995251881Speter 2996251881Speter /* check address family */ 2997251881Speter if (saidx->src.sa.sa_family != saidx->dst.sa.sa_family) { 2998251881Speter ipseclog((LOG_DEBUG, "%s: address family mismatched.\n", 2999251881Speter __func__)); 3000251881Speter return NULL; 3001251881Speter } 3002251881Speter 3003251881Speter sav = NULL; 3004251881Speter /* check all SAD */ 3005251881Speter SAHTREE_LOCK(); 3006251881Speter LIST_FOREACH(sah, &V_sahtree, chain) { 3007251881Speter if (!key_ismyaddr((struct sockaddr *)&sah->saidx.dst)) 3008251881Speter continue; 3009251881Speter sav = key_getsavbyspi(sah, spi); 3010251881Speter if (sav != NULL) 3011251881Speter break; 3012251881Speter } 3013251881Speter SAHTREE_UNLOCK(); 3014251881Speter 3015251881Speter return sav; 3016251881Speter} 3017251881Speter 3018251881Speter/* 3019251881Speter * search SAD litmited alive SA, protocol, SPI. 3020251881Speter * OUT: 3021251881Speter * NULL : not found 3022251881Speter * others : found, pointer to a SA. 3023251881Speter */ 3024251881Speterstatic struct secasvar * 3025251881Speterkey_getsavbyspi(sah, spi) 3026251881Speter struct secashead *sah; 3027251881Speter u_int32_t spi; 3028251881Speter{ 3029251881Speter INIT_VNET_IPSEC(curvnet); 3030251881Speter struct secasvar *sav; 3031251881Speter u_int stateidx, state; 3032251881Speter 3033251881Speter sav = NULL; 3034251881Speter SAHTREE_LOCK_ASSERT(); 3035251881Speter /* search all status */ 3036251881Speter for (stateidx = 0; 3037251881Speter stateidx < _ARRAYLEN(saorder_state_alive); 3038251881Speter stateidx++) { 3039251881Speter 3040251881Speter state = saorder_state_alive[stateidx]; 3041251881Speter LIST_FOREACH(sav, &sah->savtree[state], chain) { 3042251881Speter 3043251881Speter /* sanity check */ 3044251881Speter if (sav->state != state) { 3045251881Speter ipseclog((LOG_DEBUG, "%s: " 3046251881Speter "invalid sav->state (queue: %d SA: %d)\n", 3047251881Speter __func__, state, sav->state)); 3048251881Speter continue; 3049251881Speter } 3050251881Speter 3051251881Speter if (sav->spi == spi) 3052251881Speter return sav; 3053251881Speter } 3054251881Speter } 3055251881Speter 3056251881Speter return NULL; 3057251881Speter} 3058251881Speter 3059251881Speter/* 3060251881Speter * copy SA values from PF_KEY message except *SPI, SEQ, PID, STATE and TYPE*. 3061251881Speter * You must update these if need. 3062251881Speter * OUT: 0: success. 3063251881Speter * !0: failure. 3064251881Speter * 3065251881Speter * does not modify mbuf. does not free mbuf on error. 3066251881Speter */ 3067251881Speterstatic int 3068251881Speterkey_setsaval(sav, m, mhp) 3069251881Speter struct secasvar *sav; 3070251881Speter struct mbuf *m; 3071251881Speter const struct sadb_msghdr *mhp; 3072251881Speter{ 3073251881Speter INIT_VNET_IPSEC(curvnet); 3074251881Speter int error = 0; 3075251881Speter 3076251881Speter IPSEC_ASSERT(m != NULL, ("null mbuf")); 3077251881Speter IPSEC_ASSERT(mhp != NULL, ("null msghdr")); 3078251881Speter IPSEC_ASSERT(mhp->msg != NULL, ("null msg")); 3079251881Speter 3080251881Speter /* initialization */ 3081251881Speter sav->replay = NULL; 3082251881Speter sav->key_auth = NULL; 3083251881Speter sav->key_enc = NULL; 3084251881Speter sav->sched = NULL; 3085251881Speter sav->schedlen = 0; 3086251881Speter sav->iv = NULL; 3087251881Speter sav->lft_c = NULL; 3088251881Speter sav->lft_h = NULL; 3089251881Speter sav->lft_s = NULL; 3090251881Speter sav->tdb_xform = NULL; /* transform */ 3091251881Speter sav->tdb_encalgxform = NULL; /* encoding algorithm */ 3092251881Speter sav->tdb_authalgxform = NULL; /* authentication algorithm */ 3093251881Speter sav->tdb_compalgxform = NULL; /* compression algorithm */ 3094251881Speter /* Initialize even if NAT-T not compiled in: */ 3095251881Speter sav->natt_type = 0; 3096251881Speter sav->natt_esp_frag_len = 0; 3097251881Speter 3098251881Speter /* SA */ 3099251881Speter if (mhp->ext[SADB_EXT_SA] != NULL) { 3100251881Speter const struct sadb_sa *sa0; 3101251881Speter 3102251881Speter sa0 = (const struct sadb_sa *)mhp->ext[SADB_EXT_SA]; 3103251881Speter if (mhp->extlen[SADB_EXT_SA] < sizeof(*sa0)) { 3104251881Speter error = EINVAL; 3105251881Speter goto fail; 3106251881Speter } 3107251881Speter 3108251881Speter sav->alg_auth = sa0->sadb_sa_auth; 3109251881Speter sav->alg_enc = sa0->sadb_sa_encrypt; 3110251881Speter sav->flags = sa0->sadb_sa_flags; 3111251881Speter 3112251881Speter /* replay window */ 3113251881Speter if ((sa0->sadb_sa_flags & SADB_X_EXT_OLD) == 0) { 3114251881Speter sav->replay = (struct secreplay *) 3115251881Speter malloc(sizeof(struct secreplay)+sa0->sadb_sa_replay, M_IPSEC_MISC, M_NOWAIT|M_ZERO); 3116251881Speter if (sav->replay == NULL) { 3117251881Speter ipseclog((LOG_DEBUG, "%s: No more memory.\n", 3118251881Speter __func__)); 3119251881Speter error = ENOBUFS; 3120251881Speter goto fail; 3121251881Speter } 3122251881Speter if (sa0->sadb_sa_replay != 0) 3123251881Speter sav->replay->bitmap = (caddr_t)(sav->replay+1); 3124251881Speter sav->replay->wsize = sa0->sadb_sa_replay; 3125251881Speter } 3126251881Speter } 3127251881Speter 3128251881Speter /* Authentication keys */ 3129251881Speter if (mhp->ext[SADB_EXT_KEY_AUTH] != NULL) { 3130251881Speter const struct sadb_key *key0; 3131251881Speter int len; 3132251881Speter 3133251881Speter key0 = (const struct sadb_key *)mhp->ext[SADB_EXT_KEY_AUTH]; 3134251881Speter len = mhp->extlen[SADB_EXT_KEY_AUTH]; 3135251881Speter 3136251881Speter error = 0; 3137251881Speter if (len < sizeof(*key0)) { 3138251881Speter error = EINVAL; 3139251881Speter goto fail; 3140251881Speter } 3141251881Speter switch (mhp->msg->sadb_msg_satype) { 3142251881Speter case SADB_SATYPE_AH: 3143251881Speter case SADB_SATYPE_ESP: 3144251881Speter case SADB_X_SATYPE_TCPSIGNATURE: 3145251881Speter if (len == PFKEY_ALIGN8(sizeof(struct sadb_key)) && 3146251881Speter sav->alg_auth != SADB_X_AALG_NULL) 3147251881Speter error = EINVAL; 3148251881Speter break; 3149251881Speter case SADB_X_SATYPE_IPCOMP: 3150251881Speter default: 3151251881Speter error = EINVAL; 3152251881Speter break; 3153251881Speter } 3154251881Speter if (error) { 3155251881Speter ipseclog((LOG_DEBUG, "%s: invalid key_auth values.\n", 3156251881Speter __func__)); 3157251881Speter goto fail; 3158251881Speter } 3159251881Speter 3160251881Speter sav->key_auth = (struct seckey *)key_dup_keymsg(key0, len, 3161251881Speter M_IPSEC_MISC); 3162251881Speter if (sav->key_auth == NULL ) { 3163251881Speter ipseclog((LOG_DEBUG, "%s: No more memory.\n", 3164251881Speter __func__)); 3165251881Speter error = ENOBUFS; 3166251881Speter goto fail; 3167251881Speter } 3168251881Speter } 3169251881Speter 3170251881Speter /* Encryption key */ 3171251881Speter if (mhp->ext[SADB_EXT_KEY_ENCRYPT] != NULL) { 3172251881Speter const struct sadb_key *key0; 3173251881Speter int len; 3174251881Speter 3175251881Speter key0 = (const struct sadb_key *)mhp->ext[SADB_EXT_KEY_ENCRYPT]; 3176251881Speter len = mhp->extlen[SADB_EXT_KEY_ENCRYPT]; 3177251881Speter 3178251881Speter error = 0; 3179251881Speter if (len < sizeof(*key0)) { 3180251881Speter error = EINVAL; 3181251881Speter goto fail; 3182251881Speter } 3183251881Speter switch (mhp->msg->sadb_msg_satype) { 3184251881Speter case SADB_SATYPE_ESP: 3185251881Speter if (len == PFKEY_ALIGN8(sizeof(struct sadb_key)) && 3186251881Speter sav->alg_enc != SADB_EALG_NULL) { 3187251881Speter error = EINVAL; 3188251881Speter break; 3189251881Speter } 3190251881Speter sav->key_enc = (struct seckey *)key_dup_keymsg(key0, 3191251881Speter len, 3192251881Speter M_IPSEC_MISC); 3193251881Speter if (sav->key_enc == NULL) { 3194251881Speter ipseclog((LOG_DEBUG, "%s: No more memory.\n", 3195251881Speter __func__)); 3196251881Speter error = ENOBUFS; 3197251881Speter goto fail; 3198251881Speter } 3199251881Speter break; 3200251881Speter case SADB_X_SATYPE_IPCOMP: 3201251881Speter if (len != PFKEY_ALIGN8(sizeof(struct sadb_key))) 3202251881Speter error = EINVAL; 3203251881Speter sav->key_enc = NULL; /*just in case*/ 3204251881Speter break; 3205251881Speter case SADB_SATYPE_AH: 3206251881Speter case SADB_X_SATYPE_TCPSIGNATURE: 3207251881Speter default: 3208251881Speter error = EINVAL; 3209251881Speter break; 3210251881Speter } 3211251881Speter if (error) { 3212251881Speter ipseclog((LOG_DEBUG, "%s: invalid key_enc value.\n", 3213251881Speter __func__)); 3214251881Speter goto fail; 3215251881Speter } 3216251881Speter } 3217251881Speter 3218251881Speter /* set iv */ 3219251881Speter sav->ivlen = 0; 3220251881Speter 3221251881Speter switch (mhp->msg->sadb_msg_satype) { 3222251881Speter case SADB_SATYPE_AH: 3223251881Speter error = xform_init(sav, XF_AH); 3224251881Speter break; 3225251881Speter case SADB_SATYPE_ESP: 3226251881Speter error = xform_init(sav, XF_ESP); 3227251881Speter break; 3228251881Speter case SADB_X_SATYPE_IPCOMP: 3229251881Speter error = xform_init(sav, XF_IPCOMP); 3230251881Speter break; 3231251881Speter case SADB_X_SATYPE_TCPSIGNATURE: 3232251881Speter error = xform_init(sav, XF_TCPSIGNATURE); 3233251881Speter break; 3234251881Speter } 3235251881Speter if (error) { 3236251881Speter ipseclog((LOG_DEBUG, "%s: unable to initialize SA type %u.\n", 3237251881Speter __func__, mhp->msg->sadb_msg_satype)); 3238251881Speter goto fail; 3239251881Speter } 3240251881Speter 3241251881Speter /* reset created */ 3242251881Speter sav->created = time_second; 3243251881Speter 3244251881Speter /* make lifetime for CURRENT */ 3245251881Speter sav->lft_c = malloc(sizeof(struct seclifetime), M_IPSEC_MISC, M_NOWAIT); 3246251881Speter if (sav->lft_c == NULL) { 3247251881Speter ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__)); 3248251881Speter error = ENOBUFS; 3249251881Speter goto fail; 3250251881Speter } 3251251881Speter 3252251881Speter sav->lft_c->allocations = 0; 3253251881Speter sav->lft_c->bytes = 0; 3254251881Speter sav->lft_c->addtime = time_second; 3255251881Speter sav->lft_c->usetime = 0; 3256251881Speter 3257251881Speter /* lifetimes for HARD and SOFT */ 3258251881Speter { 3259251881Speter const struct sadb_lifetime *lft0; 3260251881Speter 3261251881Speter lft0 = (struct sadb_lifetime *)mhp->ext[SADB_EXT_LIFETIME_HARD]; 3262251881Speter if (lft0 != NULL) { 3263251881Speter if (mhp->extlen[SADB_EXT_LIFETIME_HARD] < sizeof(*lft0)) { 3264251881Speter error = EINVAL; 3265251881Speter goto fail; 3266251881Speter } 3267251881Speter sav->lft_h = key_dup_lifemsg(lft0, M_IPSEC_MISC); 3268251881Speter if (sav->lft_h == NULL) { 3269251881Speter ipseclog((LOG_DEBUG, "%s: No more memory.\n",__func__)); 3270251881Speter error = ENOBUFS; 3271251881Speter goto fail; 3272251881Speter } 3273251881Speter /* to be initialize ? */ 3274251881Speter } 3275251881Speter 3276251881Speter lft0 = (struct sadb_lifetime *)mhp->ext[SADB_EXT_LIFETIME_SOFT]; 3277251881Speter if (lft0 != NULL) { 3278251881Speter if (mhp->extlen[SADB_EXT_LIFETIME_SOFT] < sizeof(*lft0)) { 3279251881Speter error = EINVAL; 3280251881Speter goto fail; 3281251881Speter } 3282251881Speter sav->lft_s = key_dup_lifemsg(lft0, M_IPSEC_MISC); 3283251881Speter if (sav->lft_s == NULL) { 3284251881Speter ipseclog((LOG_DEBUG, "%s: No more memory.\n",__func__)); 3285251881Speter error = ENOBUFS; 3286251881Speter goto fail; 3287251881Speter } 3288251881Speter /* to be initialize ? */ 3289251881Speter } 3290251881Speter } 3291251881Speter 3292251881Speter return 0; 3293251881Speter 3294251881Speter fail: 3295251881Speter /* initialization */ 3296251881Speter key_cleansav(sav); 3297251881Speter 3298251881Speter return error; 3299251881Speter} 3300251881Speter 3301251881Speter/* 3302251881Speter * validation with a secasvar entry, and set SADB_SATYPE_MATURE. 3303251881Speter * OUT: 0: valid 3304251881Speter * other: errno 3305251881Speter */ 3306251881Speterstatic int 3307251881Speterkey_mature(struct secasvar *sav) 3308251881Speter{ 3309251881Speter INIT_VNET_IPSEC(curvnet); 3310251881Speter int error; 3311251881Speter 3312251881Speter /* check SPI value */ 3313251881Speter switch (sav->sah->saidx.proto) { 3314251881Speter case IPPROTO_ESP: 3315251881Speter case IPPROTO_AH: 3316251881Speter /* 3317251881Speter * RFC 4302, 2.4. Security Parameters Index (SPI), SPI values 3318251881Speter * 1-255 reserved by IANA for future use, 3319251881Speter * 0 for implementation specific, local use. 3320251881Speter */ 3321251881Speter if (ntohl(sav->spi) <= 255) { 3322251881Speter ipseclog((LOG_DEBUG, "%s: illegal range of SPI %u.\n", 3323251881Speter __func__, (u_int32_t)ntohl(sav->spi))); 3324251881Speter return EINVAL; 3325251881Speter } 3326251881Speter break; 3327251881Speter } 3328251881Speter 3329251881Speter /* check satype */ 3330251881Speter switch (sav->sah->saidx.proto) { 3331251881Speter case IPPROTO_ESP: 3332251881Speter /* check flags */ 3333251881Speter if ((sav->flags & (SADB_X_EXT_OLD|SADB_X_EXT_DERIV)) == 3334251881Speter (SADB_X_EXT_OLD|SADB_X_EXT_DERIV)) { 3335251881Speter ipseclog((LOG_DEBUG, "%s: invalid flag (derived) " 3336251881Speter "given to old-esp.\n", __func__)); 3337251881Speter return EINVAL; 3338251881Speter } 3339251881Speter error = xform_init(sav, XF_ESP); 3340251881Speter break; 3341251881Speter case IPPROTO_AH: 3342251881Speter /* check flags */ 3343251881Speter if (sav->flags & SADB_X_EXT_DERIV) { 3344251881Speter ipseclog((LOG_DEBUG, "%s: invalid flag (derived) " 3345251881Speter "given to AH SA.\n", __func__)); 3346251881Speter return EINVAL; 3347251881Speter } 3348251881Speter if (sav->alg_enc != SADB_EALG_NONE) { 3349251881Speter ipseclog((LOG_DEBUG, "%s: protocol and algorithm " 3350251881Speter "mismated.\n", __func__)); 3351251881Speter return(EINVAL); 3352251881Speter } 3353251881Speter error = xform_init(sav, XF_AH); 3354251881Speter break; 3355251881Speter case IPPROTO_IPCOMP: 3356251881Speter if (sav->alg_auth != SADB_AALG_NONE) { 3357251881Speter ipseclog((LOG_DEBUG, "%s: protocol and algorithm " 3358251881Speter "mismated.\n", __func__)); 3359251881Speter return(EINVAL); 3360251881Speter } 3361251881Speter if ((sav->flags & SADB_X_EXT_RAWCPI) == 0 3362251881Speter && ntohl(sav->spi) >= 0x10000) { 3363251881Speter ipseclog((LOG_DEBUG, "%s: invalid cpi for IPComp.\n", 3364251881Speter __func__)); 3365251881Speter return(EINVAL); 3366251881Speter } 3367251881Speter error = xform_init(sav, XF_IPCOMP); 3368251881Speter break; 3369251881Speter case IPPROTO_TCP: 3370251881Speter if (sav->alg_enc != SADB_EALG_NONE) { 3371251881Speter ipseclog((LOG_DEBUG, "%s: protocol and algorithm " 3372251881Speter "mismated.\n", __func__)); 3373251881Speter return(EINVAL); 3374251881Speter } 3375251881Speter error = xform_init(sav, XF_TCPSIGNATURE); 3376251881Speter break; 3377251881Speter default: 3378251881Speter ipseclog((LOG_DEBUG, "%s: Invalid satype.\n", __func__)); 3379251881Speter error = EPROTONOSUPPORT; 3380251881Speter break; 3381251881Speter } 3382251881Speter if (error == 0) { 3383251881Speter SAHTREE_LOCK(); 3384251881Speter key_sa_chgstate(sav, SADB_SASTATE_MATURE); 3385251881Speter SAHTREE_UNLOCK(); 3386251881Speter } 3387251881Speter return (error); 3388251881Speter} 3389251881Speter 3390251881Speter/* 3391251881Speter * subroutine for SADB_GET and SADB_DUMP. 3392251881Speter */ 3393251881Speterstatic struct mbuf * 3394251881Speterkey_setdumpsa(struct secasvar *sav, u_int8_t type, u_int8_t satype, 3395251881Speter u_int32_t seq, u_int32_t pid) 3396251881Speter{ 3397251881Speter struct mbuf *result = NULL, *tres = NULL, *m; 3398251881Speter int i; 3399251881Speter int dumporder[] = { 3400251881Speter SADB_EXT_SA, SADB_X_EXT_SA2, 3401251881Speter SADB_EXT_LIFETIME_HARD, SADB_EXT_LIFETIME_SOFT, 3402251881Speter SADB_EXT_LIFETIME_CURRENT, SADB_EXT_ADDRESS_SRC, 3403251881Speter SADB_EXT_ADDRESS_DST, SADB_EXT_ADDRESS_PROXY, SADB_EXT_KEY_AUTH, 3404251881Speter SADB_EXT_KEY_ENCRYPT, SADB_EXT_IDENTITY_SRC, 3405251881Speter SADB_EXT_IDENTITY_DST, SADB_EXT_SENSITIVITY, 3406251881Speter#ifdef IPSEC_NAT_T 3407251881Speter SADB_X_EXT_NAT_T_TYPE, 3408251881Speter SADB_X_EXT_NAT_T_SPORT, SADB_X_EXT_NAT_T_DPORT, 3409251881Speter SADB_X_EXT_NAT_T_OAI, SADB_X_EXT_NAT_T_OAR, 3410251881Speter SADB_X_EXT_NAT_T_FRAG, 3411251881Speter#endif 3412251881Speter }; 3413251881Speter 3414251881Speter m = key_setsadbmsg(type, 0, satype, seq, pid, sav->refcnt); 3415251881Speter if (m == NULL) 3416251881Speter goto fail; 3417251881Speter result = m; 3418251881Speter 3419251881Speter for (i = sizeof(dumporder)/sizeof(dumporder[0]) - 1; i >= 0; i--) { 3420251881Speter m = NULL; 3421251881Speter switch (dumporder[i]) { 3422251881Speter case SADB_EXT_SA: 3423251881Speter m = key_setsadbsa(sav); 3424251881Speter if (!m) 3425251881Speter goto fail; 3426251881Speter break; 3427251881Speter 3428251881Speter case SADB_X_EXT_SA2: 3429251881Speter m = key_setsadbxsa2(sav->sah->saidx.mode, 3430251881Speter sav->replay ? sav->replay->count : 0, 3431251881Speter sav->sah->saidx.reqid); 3432251881Speter if (!m) 3433251881Speter goto fail; 3434251881Speter break; 3435251881Speter 3436251881Speter case SADB_EXT_ADDRESS_SRC: 3437251881Speter m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, 3438251881Speter &sav->sah->saidx.src.sa, 3439251881Speter FULLMASK, IPSEC_ULPROTO_ANY); 3440251881Speter if (!m) 3441251881Speter goto fail; 3442251881Speter break; 3443251881Speter 3444251881Speter case SADB_EXT_ADDRESS_DST: 3445251881Speter m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, 3446251881Speter &sav->sah->saidx.dst.sa, 3447251881Speter FULLMASK, IPSEC_ULPROTO_ANY); 3448251881Speter if (!m) 3449251881Speter goto fail; 3450251881Speter break; 3451251881Speter 3452251881Speter case SADB_EXT_KEY_AUTH: 3453251881Speter if (!sav->key_auth) 3454251881Speter continue; 3455251881Speter m = key_setkey(sav->key_auth, SADB_EXT_KEY_AUTH); 3456251881Speter if (!m) 3457251881Speter goto fail; 3458251881Speter break; 3459251881Speter 3460251881Speter case SADB_EXT_KEY_ENCRYPT: 3461251881Speter if (!sav->key_enc) 3462251881Speter continue; 3463251881Speter m = key_setkey(sav->key_enc, SADB_EXT_KEY_ENCRYPT); 3464251881Speter if (!m) 3465251881Speter goto fail; 3466251881Speter break; 3467251881Speter 3468251881Speter case SADB_EXT_LIFETIME_CURRENT: 3469251881Speter if (!sav->lft_c) 3470251881Speter continue; 3471251881Speter m = key_setlifetime(sav->lft_c, 3472251881Speter SADB_EXT_LIFETIME_CURRENT); 3473251881Speter if (!m) 3474251881Speter goto fail; 3475251881Speter break; 3476251881Speter 3477251881Speter case SADB_EXT_LIFETIME_HARD: 3478251881Speter if (!sav->lft_h) 3479251881Speter continue; 3480251881Speter m = key_setlifetime(sav->lft_h, 3481251881Speter SADB_EXT_LIFETIME_HARD); 3482251881Speter if (!m) 3483251881Speter goto fail; 3484251881Speter break; 3485251881Speter 3486251881Speter case SADB_EXT_LIFETIME_SOFT: 3487251881Speter if (!sav->lft_s) 3488251881Speter continue; 3489251881Speter m = key_setlifetime(sav->lft_s, 3490251881Speter SADB_EXT_LIFETIME_SOFT); 3491251881Speter 3492251881Speter if (!m) 3493251881Speter goto fail; 3494251881Speter break; 3495251881Speter 3496251881Speter#ifdef IPSEC_NAT_T 3497251881Speter case SADB_X_EXT_NAT_T_TYPE: 3498251881Speter m = key_setsadbxtype(sav->natt_type); 3499251881Speter if (!m) 3500251881Speter goto fail; 3501251881Speter break; 3502251881Speter 3503251881Speter case SADB_X_EXT_NAT_T_DPORT: 3504251881Speter m = key_setsadbxport( 3505251881Speter KEY_PORTFROMSADDR(&sav->sah->saidx.dst), 3506251881Speter SADB_X_EXT_NAT_T_DPORT); 3507251881Speter if (!m) 3508251881Speter goto fail; 3509251881Speter break; 3510251881Speter 3511251881Speter case SADB_X_EXT_NAT_T_SPORT: 3512251881Speter m = key_setsadbxport( 3513251881Speter KEY_PORTFROMSADDR(&sav->sah->saidx.src), 3514251881Speter SADB_X_EXT_NAT_T_SPORT); 3515251881Speter if (!m) 3516251881Speter goto fail; 3517251881Speter break; 3518251881Speter 3519251881Speter case SADB_X_EXT_NAT_T_OAI: 3520251881Speter case SADB_X_EXT_NAT_T_OAR: 3521251881Speter case SADB_X_EXT_NAT_T_FRAG: 3522251881Speter /* We do not (yet) support those. */ 3523251881Speter continue; 3524251881Speter#endif 3525251881Speter 3526251881Speter case SADB_EXT_ADDRESS_PROXY: 3527251881Speter case SADB_EXT_IDENTITY_SRC: 3528251881Speter case SADB_EXT_IDENTITY_DST: 3529251881Speter /* XXX: should we brought from SPD ? */ 3530251881Speter case SADB_EXT_SENSITIVITY: 3531251881Speter default: 3532251881Speter continue; 3533251881Speter } 3534251881Speter 3535251881Speter if (!m) 3536251881Speter goto fail; 3537251881Speter if (tres) 3538251881Speter m_cat(m, tres); 3539251881Speter tres = m; 3540251881Speter 3541251881Speter } 3542251881Speter 3543251881Speter m_cat(result, tres); 3544251881Speter if (result->m_len < sizeof(struct sadb_msg)) { 3545251881Speter result = m_pullup(result, sizeof(struct sadb_msg)); 3546251881Speter if (result == NULL) 3547251881Speter goto fail; 3548251881Speter } 3549251881Speter 3550251881Speter result->m_pkthdr.len = 0; 3551251881Speter for (m = result; m; m = m->m_next) 3552251881Speter result->m_pkthdr.len += m->m_len; 3553251881Speter 3554251881Speter mtod(result, struct sadb_msg *)->sadb_msg_len = 3555251881Speter PFKEY_UNIT64(result->m_pkthdr.len); 3556251881Speter 3557251881Speter return result; 3558251881Speter 3559251881Speterfail: 3560251881Speter m_freem(result); 3561251881Speter m_freem(tres); 3562251881Speter return NULL; 3563251881Speter} 3564251881Speter 3565251881Speter/* 3566251881Speter * set data into sadb_msg. 3567251881Speter */ 3568251881Speterstatic struct mbuf * 3569251881Speterkey_setsadbmsg(u_int8_t type, u_int16_t tlen, u_int8_t satype, u_int32_t seq, 3570251881Speter pid_t pid, u_int16_t reserved) 3571251881Speter{ 3572251881Speter struct mbuf *m; 3573251881Speter struct sadb_msg *p; 3574251881Speter int len; 3575251881Speter 3576251881Speter len = PFKEY_ALIGN8(sizeof(struct sadb_msg)); 3577251881Speter if (len > MCLBYTES) 3578251881Speter return NULL; 3579251881Speter MGETHDR(m, M_DONTWAIT, MT_DATA); 3580251881Speter if (m && len > MHLEN) { 3581251881Speter MCLGET(m, M_DONTWAIT); 3582251881Speter if ((m->m_flags & M_EXT) == 0) { 3583251881Speter m_freem(m); 3584251881Speter m = NULL; 3585251881Speter } 3586251881Speter } 3587251881Speter if (!m) 3588251881Speter return NULL; 3589251881Speter m->m_pkthdr.len = m->m_len = len; 3590251881Speter m->m_next = NULL; 3591251881Speter 3592251881Speter p = mtod(m, struct sadb_msg *); 3593251881Speter 3594251881Speter bzero(p, len); 3595251881Speter p->sadb_msg_version = PF_KEY_V2; 3596251881Speter p->sadb_msg_type = type; 3597251881Speter p->sadb_msg_errno = 0; 3598251881Speter p->sadb_msg_satype = satype; 3599251881Speter p->sadb_msg_len = PFKEY_UNIT64(tlen); 3600251881Speter p->sadb_msg_reserved = reserved; 3601251881Speter p->sadb_msg_seq = seq; 3602251881Speter p->sadb_msg_pid = (u_int32_t)pid; 3603251881Speter 3604251881Speter return m; 3605251881Speter} 3606251881Speter 3607251881Speter/* 3608251881Speter * copy secasvar data into sadb_address. 3609251881Speter */ 3610251881Speterstatic struct mbuf * 3611251881Speterkey_setsadbsa(sav) 3612251881Speter struct secasvar *sav; 3613251881Speter{ 3614251881Speter struct mbuf *m; 3615251881Speter struct sadb_sa *p; 3616251881Speter int len; 3617251881Speter 3618251881Speter len = PFKEY_ALIGN8(sizeof(struct sadb_sa)); 3619251881Speter m = key_alloc_mbuf(len); 3620251881Speter if (!m || m->m_next) { /*XXX*/ 3621251881Speter if (m) 3622251881Speter m_freem(m); 3623251881Speter return NULL; 3624251881Speter } 3625251881Speter 3626251881Speter p = mtod(m, struct sadb_sa *); 3627251881Speter 3628251881Speter bzero(p, len); 3629251881Speter p->sadb_sa_len = PFKEY_UNIT64(len); 3630251881Speter p->sadb_sa_exttype = SADB_EXT_SA; 3631251881Speter p->sadb_sa_spi = sav->spi; 3632251881Speter p->sadb_sa_replay = (sav->replay != NULL ? sav->replay->wsize : 0); 3633251881Speter p->sadb_sa_state = sav->state; 3634251881Speter p->sadb_sa_auth = sav->alg_auth; 3635251881Speter p->sadb_sa_encrypt = sav->alg_enc; 3636251881Speter p->sadb_sa_flags = sav->flags; 3637251881Speter 3638251881Speter return m; 3639251881Speter} 3640251881Speter 3641251881Speter/* 3642251881Speter * set data into sadb_address. 3643251881Speter */ 3644251881Speterstatic struct mbuf * 3645251881Speterkey_setsadbaddr(u_int16_t exttype, const struct sockaddr *saddr, u_int8_t prefixlen, u_int16_t ul_proto) 3646251881Speter{ 3647251881Speter struct mbuf *m; 3648251881Speter struct sadb_address *p; 3649251881Speter size_t len; 3650251881Speter 3651251881Speter len = PFKEY_ALIGN8(sizeof(struct sadb_address)) + 3652251881Speter PFKEY_ALIGN8(saddr->sa_len); 3653251881Speter m = key_alloc_mbuf(len); 3654251881Speter if (!m || m->m_next) { /*XXX*/ 3655251881Speter if (m) 3656251881Speter m_freem(m); 3657251881Speter return NULL; 3658251881Speter } 3659251881Speter 3660251881Speter p = mtod(m, struct sadb_address *); 3661251881Speter 3662251881Speter bzero(p, len); 3663251881Speter p->sadb_address_len = PFKEY_UNIT64(len); 3664251881Speter p->sadb_address_exttype = exttype; 3665251881Speter p->sadb_address_proto = ul_proto; 3666251881Speter if (prefixlen == FULLMASK) { 3667251881Speter switch (saddr->sa_family) { 3668251881Speter case AF_INET: 3669251881Speter prefixlen = sizeof(struct in_addr) << 3; 3670251881Speter break; 3671251881Speter case AF_INET6: 3672251881Speter prefixlen = sizeof(struct in6_addr) << 3; 3673251881Speter break; 3674251881Speter default: 3675251881Speter ; /*XXX*/ 3676251881Speter } 3677251881Speter } 3678251881Speter p->sadb_address_prefixlen = prefixlen; 3679251881Speter p->sadb_address_reserved = 0; 3680251881Speter 3681251881Speter bcopy(saddr, 3682251881Speter mtod(m, caddr_t) + PFKEY_ALIGN8(sizeof(struct sadb_address)), 3683251881Speter saddr->sa_len); 3684251881Speter 3685251881Speter return m; 3686251881Speter} 3687251881Speter 3688251881Speter/* 3689251881Speter * set data into sadb_x_sa2. 3690251881Speter */ 3691251881Speterstatic struct mbuf * 3692251881Speterkey_setsadbxsa2(u_int8_t mode, u_int32_t seq, u_int32_t reqid) 3693251881Speter{ 3694251881Speter struct mbuf *m; 3695251881Speter struct sadb_x_sa2 *p; 3696251881Speter size_t len; 3697251881Speter 3698251881Speter len = PFKEY_ALIGN8(sizeof(struct sadb_x_sa2)); 3699251881Speter m = key_alloc_mbuf(len); 3700251881Speter if (!m || m->m_next) { /*XXX*/ 3701251881Speter if (m) 3702251881Speter m_freem(m); 3703251881Speter return NULL; 3704251881Speter } 3705251881Speter 3706251881Speter p = mtod(m, struct sadb_x_sa2 *); 3707251881Speter 3708251881Speter bzero(p, len); 3709251881Speter p->sadb_x_sa2_len = PFKEY_UNIT64(len); 3710251881Speter p->sadb_x_sa2_exttype = SADB_X_EXT_SA2; 3711251881Speter p->sadb_x_sa2_mode = mode; 3712251881Speter p->sadb_x_sa2_reserved1 = 0; 3713251881Speter p->sadb_x_sa2_reserved2 = 0; 3714251881Speter p->sadb_x_sa2_sequence = seq; 3715251881Speter p->sadb_x_sa2_reqid = reqid; 3716251881Speter 3717251881Speter return m; 3718251881Speter} 3719251881Speter 3720251881Speter#ifdef IPSEC_NAT_T 3721251881Speter/* 3722251881Speter * Set a type in sadb_x_nat_t_type. 3723251881Speter */ 3724251881Speterstatic struct mbuf * 3725251881Speterkey_setsadbxtype(u_int16_t type) 3726251881Speter{ 3727251881Speter struct mbuf *m; 3728251881Speter size_t len; 3729251881Speter struct sadb_x_nat_t_type *p; 3730251881Speter 3731251881Speter len = PFKEY_ALIGN8(sizeof(struct sadb_x_nat_t_type)); 3732251881Speter 3733251881Speter m = key_alloc_mbuf(len); 3734251881Speter if (!m || m->m_next) { /*XXX*/ 3735251881Speter if (m) 3736251881Speter m_freem(m); 3737251881Speter return (NULL); 3738251881Speter } 3739251881Speter 3740251881Speter p = mtod(m, struct sadb_x_nat_t_type *); 3741251881Speter 3742251881Speter bzero(p, len); 3743251881Speter p->sadb_x_nat_t_type_len = PFKEY_UNIT64(len); 3744251881Speter p->sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE; 3745251881Speter p->sadb_x_nat_t_type_type = type; 3746251881Speter 3747251881Speter return (m); 3748251881Speter} 3749251881Speter/* 3750251881Speter * Set a port in sadb_x_nat_t_port. 3751251881Speter * In contrast to default RFC 2367 behaviour, port is in network byte order. 3752251881Speter */ 3753251881Speterstatic struct mbuf * 3754251881Speterkey_setsadbxport(u_int16_t port, u_int16_t type) 3755251881Speter{ 3756251881Speter struct mbuf *m; 3757251881Speter size_t len; 3758251881Speter struct sadb_x_nat_t_port *p; 3759251881Speter 3760251881Speter len = PFKEY_ALIGN8(sizeof(struct sadb_x_nat_t_port)); 3761251881Speter 3762251881Speter m = key_alloc_mbuf(len); 3763251881Speter if (!m || m->m_next) { /*XXX*/ 3764251881Speter if (m) 3765251881Speter m_freem(m); 3766251881Speter return (NULL); 3767251881Speter } 3768251881Speter 3769251881Speter p = mtod(m, struct sadb_x_nat_t_port *); 3770251881Speter 3771251881Speter bzero(p, len); 3772251881Speter p->sadb_x_nat_t_port_len = PFKEY_UNIT64(len); 3773251881Speter p->sadb_x_nat_t_port_exttype = type; 3774251881Speter p->sadb_x_nat_t_port_port = port; 3775251881Speter 3776251881Speter return (m); 3777251881Speter} 3778251881Speter 3779251881Speter/* 3780251881Speter * Get port from sockaddr. Port is in network byte order. 3781251881Speter */ 3782251881Speteru_int16_t 3783251881Speterkey_portfromsaddr(struct sockaddr *sa) 3784251881Speter{ 3785251881Speter INIT_VNET_IPSEC(curvnet); 3786251881Speter 3787251881Speter switch (sa->sa_family) { 3788251881Speter#ifdef INET 3789251881Speter case AF_INET: 3790251881Speter return ((struct sockaddr_in *)sa)->sin_port; 3791251881Speter#endif 3792251881Speter#ifdef INET6 3793251881Speter case AF_INET6: 3794251881Speter return ((struct sockaddr_in6 *)sa)->sin6_port; 3795251881Speter#endif 3796251881Speter } 3797251881Speter KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 3798251881Speter printf("DP %s unexpected address family %d\n", 3799251881Speter __func__, sa->sa_family)); 3800251881Speter return (0); 3801251881Speter} 3802251881Speter#endif /* IPSEC_NAT_T */ 3803251881Speter 3804251881Speter/* 3805251881Speter * Set port in struct sockaddr. Port is in network byte order. 3806251881Speter */ 3807251881Speterstatic void 3808251881Speterkey_porttosaddr(struct sockaddr *sa, u_int16_t port) 3809251881Speter{ 3810251881Speter INIT_VNET_IPSEC(curvnet); 3811251881Speter 3812251881Speter switch (sa->sa_family) { 3813251881Speter#ifdef INET 3814251881Speter case AF_INET: 3815251881Speter ((struct sockaddr_in *)sa)->sin_port = port; 3816251881Speter break; 3817251881Speter#endif 3818251881Speter#ifdef INET6 3819251881Speter case AF_INET6: 3820251881Speter ((struct sockaddr_in6 *)sa)->sin6_port = port; 3821251881Speter break; 3822251881Speter#endif 3823251881Speter default: 3824251881Speter ipseclog((LOG_DEBUG, "%s: unexpected address family %d.\n", 3825251881Speter __func__, sa->sa_family)); 3826251881Speter break; 3827251881Speter } 3828251881Speter} 3829251881Speter 3830251881Speter/* 3831251881Speter * set data into sadb_x_policy 3832251881Speter */ 3833251881Speterstatic struct mbuf * 3834251881Speterkey_setsadbxpolicy(u_int16_t type, u_int8_t dir, u_int32_t id) 3835251881Speter{ 3836251881Speter struct mbuf *m; 3837251881Speter struct sadb_x_policy *p; 3838251881Speter size_t len; 3839251881Speter 3840251881Speter len = PFKEY_ALIGN8(sizeof(struct sadb_x_policy)); 3841251881Speter m = key_alloc_mbuf(len); 3842251881Speter if (!m || m->m_next) { /*XXX*/ 3843251881Speter if (m) 3844251881Speter m_freem(m); 3845251881Speter return NULL; 3846251881Speter } 3847251881Speter 3848251881Speter p = mtod(m, struct sadb_x_policy *); 3849251881Speter 3850251881Speter bzero(p, len); 3851251881Speter p->sadb_x_policy_len = PFKEY_UNIT64(len); 3852251881Speter p->sadb_x_policy_exttype = SADB_X_EXT_POLICY; 3853251881Speter p->sadb_x_policy_type = type; 3854251881Speter p->sadb_x_policy_dir = dir; 3855251881Speter p->sadb_x_policy_id = id; 3856251881Speter 3857251881Speter return m; 3858251881Speter} 3859251881Speter 3860251881Speter/* %%% utilities */ 3861251881Speter/* Take a key message (sadb_key) from the socket and turn it into one 3862251881Speter * of the kernel's key structures (seckey). 3863251881Speter * 3864251881Speter * IN: pointer to the src 3865251881Speter * OUT: NULL no more memory 3866251881Speter */ 3867251881Speterstruct seckey * 3868251881Speterkey_dup_keymsg(const struct sadb_key *src, u_int len, 3869251881Speter struct malloc_type *type) 3870251881Speter{ 3871251881Speter INIT_VNET_IPSEC(curvnet); 3872251881Speter struct seckey *dst; 3873251881Speter dst = (struct seckey *)malloc(sizeof(struct seckey), type, M_NOWAIT); 3874251881Speter if (dst != NULL) { 3875251881Speter dst->bits = src->sadb_key_bits; 3876251881Speter dst->key_data = (char *)malloc(len, type, M_NOWAIT); 3877251881Speter if (dst->key_data != NULL) { 3878251881Speter bcopy((const char *)src + sizeof(struct sadb_key), 3879251881Speter dst->key_data, len); 3880251881Speter } else { 3881251881Speter ipseclog((LOG_DEBUG, "%s: No more memory.\n", 3882251881Speter __func__)); 3883251881Speter free(dst, type); 3884251881Speter dst = NULL; 3885251881Speter } 3886251881Speter } else { 3887251881Speter ipseclog((LOG_DEBUG, "%s: No more memory.\n", 3888251881Speter __func__)); 3889251881Speter 3890251881Speter } 3891251881Speter return dst; 3892251881Speter} 3893251881Speter 3894251881Speter/* Take a lifetime message (sadb_lifetime) passed in on a socket and 3895251881Speter * turn it into one of the kernel's lifetime structures (seclifetime). 3896251881Speter * 3897251881Speter * IN: pointer to the destination, source and malloc type 3898251881Speter * OUT: NULL, no more memory 3899251881Speter */ 3900251881Speter 3901251881Speterstatic struct seclifetime * 3902251881Speterkey_dup_lifemsg(const struct sadb_lifetime *src, 3903251881Speter struct malloc_type *type) 3904251881Speter{ 3905251881Speter INIT_VNET_IPSEC(curvnet); 3906251881Speter struct seclifetime *dst = NULL; 3907251881Speter 3908251881Speter dst = (struct seclifetime *)malloc(sizeof(struct seclifetime), 3909251881Speter type, M_NOWAIT); 3910251881Speter if (dst == NULL) { 3911251881Speter /* XXX counter */ 3912251881Speter ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__)); 3913251881Speter } else { 3914251881Speter dst->allocations = src->sadb_lifetime_allocations; 3915251881Speter dst->bytes = src->sadb_lifetime_bytes; 3916251881Speter dst->addtime = src->sadb_lifetime_addtime; 3917251881Speter dst->usetime = src->sadb_lifetime_usetime; 3918251881Speter } 3919251881Speter return dst; 3920251881Speter} 3921251881Speter 3922251881Speter/* compare my own address 3923251881Speter * OUT: 1: true, i.e. my address. 3924251881Speter * 0: false 3925251881Speter */ 3926251881Speterint 3927251881Speterkey_ismyaddr(sa) 3928251881Speter struct sockaddr *sa; 3929251881Speter{ 3930251881Speter#ifdef INET 3931251881Speter INIT_VNET_INET(curvnet); 3932251881Speter struct sockaddr_in *sin; 3933251881Speter struct in_ifaddr *ia; 3934251881Speter#endif 3935251881Speter 3936251881Speter IPSEC_ASSERT(sa != NULL, ("null sockaddr")); 3937251881Speter 3938251881Speter switch (sa->sa_family) { 3939251881Speter#ifdef INET 3940251881Speter case AF_INET: 3941251881Speter sin = (struct sockaddr_in *)sa; 3942251881Speter for (ia = V_in_ifaddrhead.tqh_first; ia; 3943251881Speter ia = ia->ia_link.tqe_next) 3944251881Speter { 3945251881Speter if (sin->sin_family == ia->ia_addr.sin_family && 3946251881Speter sin->sin_len == ia->ia_addr.sin_len && 3947251881Speter sin->sin_addr.s_addr == ia->ia_addr.sin_addr.s_addr) 3948251881Speter { 3949251881Speter return 1; 3950251881Speter } 3951251881Speter } 3952251881Speter break; 3953251881Speter#endif 3954251881Speter#ifdef INET6 3955251881Speter case AF_INET6: 3956251881Speter return key_ismyaddr6((struct sockaddr_in6 *)sa); 3957251881Speter#endif 3958251881Speter } 3959251881Speter 3960251881Speter return 0; 3961251881Speter} 3962251881Speter 3963251881Speter#ifdef INET6 3964251881Speter/* 3965251881Speter * compare my own address for IPv6. 3966251881Speter * 1: ours 3967251881Speter * 0: other 3968251881Speter * NOTE: derived ip6_input() in KAME. This is necessary to modify more. 3969251881Speter */ 3970251881Speter#include <netinet6/in6_var.h> 3971251881Speter 3972251881Speterstatic int 3973251881Speterkey_ismyaddr6(sin6) 3974251881Speter struct sockaddr_in6 *sin6; 3975251881Speter{ 3976251881Speter INIT_VNET_INET6(curvnet); 3977251881Speter struct in6_ifaddr *ia; 3978251881Speter#if 0 3979251881Speter struct in6_multi *in6m; 3980251881Speter#endif 3981251881Speter 3982251881Speter for (ia = V_in6_ifaddr; ia; ia = ia->ia_next) { 3983251881Speter if (key_sockaddrcmp((struct sockaddr *)&sin6, 3984251881Speter (struct sockaddr *)&ia->ia_addr, 0) == 0) 3985251881Speter return 1; 3986251881Speter 3987251881Speter#if 0 3988251881Speter /* 3989251881Speter * XXX Multicast 3990251881Speter * XXX why do we care about multlicast here while we don't care 3991251881Speter * about IPv4 multicast?? 3992251881Speter * XXX scope 3993251881Speter */ 3994251881Speter in6m = NULL; 3995251881Speter IN6_LOOKUP_MULTI(sin6->sin6_addr, ia->ia_ifp, in6m); 3996251881Speter if (in6m) 3997251881Speter return 1; 3998251881Speter#endif 3999251881Speter } 4000251881Speter 4001251881Speter /* loopback, just for safety */ 4002251881Speter if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) 4003251881Speter return 1; 4004251881Speter 4005251881Speter return 0; 4006251881Speter} 4007251881Speter#endif /*INET6*/ 4008251881Speter 4009251881Speter/* 4010251881Speter * compare two secasindex structure. 4011251881Speter * flag can specify to compare 2 saidxes. 4012251881Speter * compare two secasindex structure without both mode and reqid. 4013251881Speter * don't compare port. 4014251881Speter * IN: 4015251881Speter * saidx0: source, it can be in SAD. 4016251881Speter * saidx1: object. 4017251881Speter * OUT: 4018251881Speter * 1 : equal 4019251881Speter * 0 : not equal 4020251881Speter */ 4021251881Speterstatic int 4022251881Speterkey_cmpsaidx( 4023251881Speter const struct secasindex *saidx0, 4024251881Speter const struct secasindex *saidx1, 4025251881Speter int flag) 4026251881Speter{ 4027251881Speter int chkport = 0; 4028251881Speter 4029251881Speter /* sanity */ 4030251881Speter if (saidx0 == NULL && saidx1 == NULL) 4031251881Speter return 1; 4032251881Speter 4033251881Speter if (saidx0 == NULL || saidx1 == NULL) 4034251881Speter return 0; 4035251881Speter 4036251881Speter if (saidx0->proto != saidx1->proto) 4037251881Speter return 0; 4038251881Speter 4039251881Speter if (flag == CMP_EXACTLY) { 4040251881Speter if (saidx0->mode != saidx1->mode) 4041251881Speter return 0; 4042251881Speter if (saidx0->reqid != saidx1->reqid) 4043251881Speter return 0; 4044251881Speter if (bcmp(&saidx0->src, &saidx1->src, saidx0->src.sa.sa_len) != 0 || 4045251881Speter bcmp(&saidx0->dst, &saidx1->dst, saidx0->dst.sa.sa_len) != 0) 4046251881Speter return 0; 4047251881Speter } else { 4048251881Speter 4049251881Speter /* CMP_MODE_REQID, CMP_REQID, CMP_HEAD */ 4050251881Speter if (flag == CMP_MODE_REQID 4051251881Speter ||flag == CMP_REQID) { 4052251881Speter /* 4053251881Speter * If reqid of SPD is non-zero, unique SA is required. 4054251881Speter * The result must be of same reqid in this case. 4055251881Speter */ 4056251881Speter if (saidx1->reqid != 0 && saidx0->reqid != saidx1->reqid) 4057251881Speter return 0; 4058251881Speter } 4059251881Speter 4060251881Speter if (flag == CMP_MODE_REQID) { 4061251881Speter if (saidx0->mode != IPSEC_MODE_ANY 4062251881Speter && saidx0->mode != saidx1->mode) 4063251881Speter return 0; 4064251881Speter } 4065251881Speter 4066251881Speter#ifdef IPSEC_NAT_T 4067251881Speter /* 4068251881Speter * If NAT-T is enabled, check ports for tunnel mode. 4069251881Speter * Do not check ports if they are set to zero in the SPD. 4070251881Speter * Also do not do it for transport mode, as there is no 4071251881Speter * port information available in the SP. 4072251881Speter */ 4073251881Speter if (saidx1->mode == IPSEC_MODE_TUNNEL && 4074251881Speter saidx1->src.sa.sa_family == AF_INET && 4075251881Speter saidx1->dst.sa.sa_family == AF_INET && 4076251881Speter ((const struct sockaddr_in *)(&saidx1->src))->sin_port && 4077251881Speter ((const struct sockaddr_in *)(&saidx1->dst))->sin_port) 4078251881Speter chkport = 1; 4079251881Speter#endif /* IPSEC_NAT_T */ 4080251881Speter 4081251881Speter if (key_sockaddrcmp(&saidx0->src.sa, &saidx1->src.sa, chkport) != 0) { 4082251881Speter return 0; 4083251881Speter } 4084251881Speter if (key_sockaddrcmp(&saidx0->dst.sa, &saidx1->dst.sa, chkport) != 0) { 4085251881Speter return 0; 4086251881Speter } 4087251881Speter } 4088251881Speter 4089251881Speter return 1; 4090251881Speter} 4091251881Speter 4092251881Speter/* 4093251881Speter * compare two secindex structure exactly. 4094251881Speter * IN: 4095251881Speter * spidx0: source, it is often in SPD. 4096251881Speter * spidx1: object, it is often from PFKEY message. 4097251881Speter * OUT: 4098251881Speter * 1 : equal 4099251881Speter * 0 : not equal 4100251881Speter */ 4101251881Speterstatic int 4102251881Speterkey_cmpspidx_exactly( 4103251881Speter struct secpolicyindex *spidx0, 4104251881Speter struct secpolicyindex *spidx1) 4105251881Speter{ 4106251881Speter /* sanity */ 4107251881Speter if (spidx0 == NULL && spidx1 == NULL) 4108251881Speter return 1; 4109251881Speter 4110251881Speter if (spidx0 == NULL || spidx1 == NULL) 4111251881Speter return 0; 4112251881Speter 4113251881Speter if (spidx0->prefs != spidx1->prefs 4114251881Speter || spidx0->prefd != spidx1->prefd 4115251881Speter || spidx0->ul_proto != spidx1->ul_proto) 4116251881Speter return 0; 4117251881Speter 4118251881Speter return key_sockaddrcmp(&spidx0->src.sa, &spidx1->src.sa, 1) == 0 && 4119251881Speter key_sockaddrcmp(&spidx0->dst.sa, &spidx1->dst.sa, 1) == 0; 4120251881Speter} 4121251881Speter 4122251881Speter/* 4123251881Speter * compare two secindex structure with mask. 4124251881Speter * IN: 4125251881Speter * spidx0: source, it is often in SPD. 4126251881Speter * spidx1: object, it is often from IP header. 4127251881Speter * OUT: 4128251881Speter * 1 : equal 4129251881Speter * 0 : not equal 4130251881Speter */ 4131251881Speterstatic int 4132251881Speterkey_cmpspidx_withmask( 4133251881Speter struct secpolicyindex *spidx0, 4134251881Speter struct secpolicyindex *spidx1) 4135251881Speter{ 4136251881Speter /* sanity */ 4137251881Speter if (spidx0 == NULL && spidx1 == NULL) 4138251881Speter return 1; 4139251881Speter 4140251881Speter if (spidx0 == NULL || spidx1 == NULL) 4141251881Speter return 0; 4142251881Speter 4143251881Speter if (spidx0->src.sa.sa_family != spidx1->src.sa.sa_family || 4144251881Speter spidx0->dst.sa.sa_family != spidx1->dst.sa.sa_family || 4145251881Speter spidx0->src.sa.sa_len != spidx1->src.sa.sa_len || 4146251881Speter spidx0->dst.sa.sa_len != spidx1->dst.sa.sa_len) 4147251881Speter return 0; 4148251881Speter 4149251881Speter /* if spidx.ul_proto == IPSEC_ULPROTO_ANY, ignore. */ 4150251881Speter if (spidx0->ul_proto != (u_int16_t)IPSEC_ULPROTO_ANY 4151251881Speter && spidx0->ul_proto != spidx1->ul_proto) 4152251881Speter return 0; 4153251881Speter 4154251881Speter switch (spidx0->src.sa.sa_family) { 4155251881Speter case AF_INET: 4156251881Speter if (spidx0->src.sin.sin_port != IPSEC_PORT_ANY 4157251881Speter && spidx0->src.sin.sin_port != spidx1->src.sin.sin_port) 4158251881Speter return 0; 4159251881Speter if (!key_bbcmp(&spidx0->src.sin.sin_addr, 4160251881Speter &spidx1->src.sin.sin_addr, spidx0->prefs)) 4161251881Speter return 0; 4162251881Speter break; 4163251881Speter case AF_INET6: 4164251881Speter if (spidx0->src.sin6.sin6_port != IPSEC_PORT_ANY 4165251881Speter && spidx0->src.sin6.sin6_port != spidx1->src.sin6.sin6_port) 4166251881Speter return 0; 4167251881Speter /* 4168251881Speter * scope_id check. if sin6_scope_id is 0, we regard it 4169251881Speter * as a wildcard scope, which matches any scope zone ID. 4170251881Speter */ 4171251881Speter if (spidx0->src.sin6.sin6_scope_id && 4172251881Speter spidx1->src.sin6.sin6_scope_id && 4173251881Speter spidx0->src.sin6.sin6_scope_id != spidx1->src.sin6.sin6_scope_id) 4174251881Speter return 0; 4175251881Speter if (!key_bbcmp(&spidx0->src.sin6.sin6_addr, 4176251881Speter &spidx1->src.sin6.sin6_addr, spidx0->prefs)) 4177251881Speter return 0; 4178251881Speter break; 4179251881Speter default: 4180251881Speter /* XXX */ 4181251881Speter if (bcmp(&spidx0->src, &spidx1->src, spidx0->src.sa.sa_len) != 0) 4182251881Speter return 0; 4183251881Speter break; 4184251881Speter } 4185251881Speter 4186251881Speter switch (spidx0->dst.sa.sa_family) { 4187251881Speter case AF_INET: 4188251881Speter if (spidx0->dst.sin.sin_port != IPSEC_PORT_ANY 4189251881Speter && spidx0->dst.sin.sin_port != spidx1->dst.sin.sin_port) 4190251881Speter return 0; 4191251881Speter if (!key_bbcmp(&spidx0->dst.sin.sin_addr, 4192251881Speter &spidx1->dst.sin.sin_addr, spidx0->prefd)) 4193251881Speter return 0; 4194251881Speter break; 4195251881Speter case AF_INET6: 4196251881Speter if (spidx0->dst.sin6.sin6_port != IPSEC_PORT_ANY 4197251881Speter && spidx0->dst.sin6.sin6_port != spidx1->dst.sin6.sin6_port) 4198251881Speter return 0; 4199251881Speter /* 4200251881Speter * scope_id check. if sin6_scope_id is 0, we regard it 4201251881Speter * as a wildcard scope, which matches any scope zone ID. 4202251881Speter */ 4203251881Speter if (spidx0->dst.sin6.sin6_scope_id && 4204251881Speter spidx1->dst.sin6.sin6_scope_id && 4205251881Speter spidx0->dst.sin6.sin6_scope_id != spidx1->dst.sin6.sin6_scope_id) 4206251881Speter return 0; 4207251881Speter if (!key_bbcmp(&spidx0->dst.sin6.sin6_addr, 4208251881Speter &spidx1->dst.sin6.sin6_addr, spidx0->prefd)) 4209251881Speter return 0; 4210251881Speter break; 4211251881Speter default: 4212251881Speter /* XXX */ 4213251881Speter if (bcmp(&spidx0->dst, &spidx1->dst, spidx0->dst.sa.sa_len) != 0) 4214251881Speter return 0; 4215251881Speter break; 4216251881Speter } 4217251881Speter 4218251881Speter /* XXX Do we check other field ? e.g. flowinfo */ 4219251881Speter 4220251881Speter return 1; 4221251881Speter} 4222251881Speter 4223251881Speter/* returns 0 on match */ 4224251881Speterstatic int 4225251881Speterkey_sockaddrcmp( 4226251881Speter const struct sockaddr *sa1, 4227251881Speter const struct sockaddr *sa2, 4228251881Speter int port) 4229251881Speter{ 4230251881Speter#ifdef satosin 4231251881Speter#undef satosin 4232251881Speter#endif 4233251881Speter#define satosin(s) ((const struct sockaddr_in *)s) 4234251881Speter#ifdef satosin6 4235251881Speter#undef satosin6 4236251881Speter#endif 4237251881Speter#define satosin6(s) ((const struct sockaddr_in6 *)s) 4238251881Speter if (sa1->sa_family != sa2->sa_family || sa1->sa_len != sa2->sa_len) 4239251881Speter return 1; 4240251881Speter 4241251881Speter switch (sa1->sa_family) { 4242251881Speter case AF_INET: 4243251881Speter if (sa1->sa_len != sizeof(struct sockaddr_in)) 4244251881Speter return 1; 4245251881Speter if (satosin(sa1)->sin_addr.s_addr != 4246251881Speter satosin(sa2)->sin_addr.s_addr) { 4247251881Speter return 1; 4248251881Speter } 4249251881Speter if (port && satosin(sa1)->sin_port != satosin(sa2)->sin_port) 4250251881Speter return 1; 4251251881Speter break; 4252251881Speter case AF_INET6: 4253251881Speter if (sa1->sa_len != sizeof(struct sockaddr_in6)) 4254251881Speter return 1; /*EINVAL*/ 4255251881Speter if (satosin6(sa1)->sin6_scope_id != 4256251881Speter satosin6(sa2)->sin6_scope_id) { 4257251881Speter return 1; 4258251881Speter } 4259251881Speter if (!IN6_ARE_ADDR_EQUAL(&satosin6(sa1)->sin6_addr, 4260251881Speter &satosin6(sa2)->sin6_addr)) { 4261251881Speter return 1; 4262251881Speter } 4263251881Speter if (port && 4264251881Speter satosin6(sa1)->sin6_port != satosin6(sa2)->sin6_port) { 4265251881Speter return 1; 4266251881Speter } 4267251881Speter break; 4268251881Speter default: 4269251881Speter if (bcmp(sa1, sa2, sa1->sa_len) != 0) 4270251881Speter return 1; 4271251881Speter break; 4272251881Speter } 4273251881Speter 4274251881Speter return 0; 4275251881Speter#undef satosin 4276251881Speter#undef satosin6 4277251881Speter} 4278251881Speter 4279251881Speter/* 4280251881Speter * compare two buffers with mask. 4281251881Speter * IN: 4282251881Speter * addr1: source 4283251881Speter * addr2: object 4284251881Speter * bits: Number of bits to compare 4285251881Speter * OUT: 4286251881Speter * 1 : equal 4287251881Speter * 0 : not equal 4288251881Speter */ 4289251881Speterstatic int 4290251881Speterkey_bbcmp(const void *a1, const void *a2, u_int bits) 4291251881Speter{ 4292251881Speter const unsigned char *p1 = a1; 4293251881Speter const unsigned char *p2 = a2; 4294251881Speter 4295251881Speter /* XXX: This could be considerably faster if we compare a word 4296251881Speter * at a time, but it is complicated on LSB Endian machines */ 4297251881Speter 4298251881Speter /* Handle null pointers */ 4299251881Speter if (p1 == NULL || p2 == NULL) 4300251881Speter return (p1 == p2); 4301251881Speter 4302251881Speter while (bits >= 8) { 4303251881Speter if (*p1++ != *p2++) 4304251881Speter return 0; 4305251881Speter bits -= 8; 4306251881Speter } 4307251881Speter 4308251881Speter if (bits > 0) { 4309251881Speter u_int8_t mask = ~((1<<(8-bits))-1); 4310251881Speter if ((*p1 & mask) != (*p2 & mask)) 4311251881Speter return 0; 4312251881Speter } 4313251881Speter return 1; /* Match! */ 4314251881Speter} 4315251881Speter 4316251881Speterstatic void 4317251881Speterkey_flush_spd(time_t now) 4318251881Speter{ 4319251881Speter INIT_VNET_IPSEC(curvnet); 4320251881Speter static u_int16_t sptree_scangen = 0; 4321251881Speter u_int16_t gen = sptree_scangen++; 4322251881Speter struct secpolicy *sp; 4323251881Speter u_int dir; 4324251881Speter 4325251881Speter /* SPD */ 4326251881Speter for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { 4327251881Speterrestart: 4328251881Speter SPTREE_LOCK(); 4329251881Speter LIST_FOREACH(sp, &V_sptree[dir], chain) { 4330251881Speter if (sp->scangen == gen) /* previously handled */ 4331251881Speter continue; 4332251881Speter sp->scangen = gen; 4333251881Speter if (sp->state == IPSEC_SPSTATE_DEAD && 4334251881Speter sp->refcnt == 1) { 4335251881Speter /* 4336251881Speter * Ensure that we only decrease refcnt once, 4337251881Speter * when we're the last consumer. 4338251881Speter * Directly call SP_DELREF/key_delsp instead 4339251881Speter * of KEY_FREESP to avoid unlocking/relocking 4340251881Speter * SPTREE_LOCK before key_delsp: may refcnt 4341251881Speter * be increased again during that time ? 4342251881Speter * NB: also clean entries created by 4343251881Speter * key_spdflush 4344251881Speter */ 4345251881Speter SP_DELREF(sp); 4346251881Speter key_delsp(sp); 4347251881Speter SPTREE_UNLOCK(); 4348251881Speter goto restart; 4349251881Speter } 4350251881Speter if (sp->lifetime == 0 && sp->validtime == 0) 4351251881Speter continue; 4352251881Speter if ((sp->lifetime && now - sp->created > sp->lifetime) 4353251881Speter || (sp->validtime && now - sp->lastused > sp->validtime)) { 4354251881Speter sp->state = IPSEC_SPSTATE_DEAD; 4355251881Speter SPTREE_UNLOCK(); 4356251881Speter key_spdexpire(sp); 4357251881Speter goto restart; 4358251881Speter } 4359251881Speter } 4360251881Speter SPTREE_UNLOCK(); 4361251881Speter } 4362251881Speter} 4363251881Speter 4364251881Speterstatic void 4365251881Speterkey_flush_sad(time_t now) 4366251881Speter{ 4367251881Speter INIT_VNET_IPSEC(curvnet); 4368251881Speter struct secashead *sah, *nextsah; 4369251881Speter struct secasvar *sav, *nextsav; 4370251881Speter 4371251881Speter /* SAD */ 4372251881Speter SAHTREE_LOCK(); 4373251881Speter LIST_FOREACH_SAFE(sah, &V_sahtree, chain, nextsah) { 4374251881Speter /* if sah has been dead, then delete it and process next sah. */ 4375251881Speter if (sah->state == SADB_SASTATE_DEAD) { 4376251881Speter key_delsah(sah); 4377251881Speter continue; 4378251881Speter } 4379251881Speter 4380251881Speter /* if LARVAL entry doesn't become MATURE, delete it. */ 4381251881Speter LIST_FOREACH_SAFE(sav, &sah->savtree[SADB_SASTATE_LARVAL], chain, nextsav) { 4382251881Speter /* Need to also check refcnt for a larval SA ??? */ 4383251881Speter if (now - sav->created > V_key_larval_lifetime) 4384251881Speter KEY_FREESAV(&sav); 4385251881Speter } 4386251881Speter 4387251881Speter /* 4388251881Speter * check MATURE entry to start to send expire message 4389251881Speter * whether or not. 4390251881Speter */ 4391251881Speter LIST_FOREACH_SAFE(sav, &sah->savtree[SADB_SASTATE_MATURE], chain, nextsav) { 4392251881Speter /* we don't need to check. */ 4393251881Speter if (sav->lft_s == NULL) 4394251881Speter continue; 4395251881Speter 4396251881Speter /* sanity check */ 4397251881Speter if (sav->lft_c == NULL) { 4398251881Speter ipseclog((LOG_DEBUG,"%s: there is no CURRENT " 4399251881Speter "time, why?\n", __func__)); 4400251881Speter continue; 4401251881Speter } 4402251881Speter 4403251881Speter /* check SOFT lifetime */ 4404251881Speter if (sav->lft_s->addtime != 0 && 4405251881Speter now - sav->created > sav->lft_s->addtime) { 4406251881Speter key_sa_chgstate(sav, SADB_SASTATE_DYING); 4407251881Speter /* 4408251881Speter * Actually, only send expire message if 4409251881Speter * SA has been used, as it was done before, 4410251881Speter * but should we always send such message, 4411251881Speter * and let IKE daemon decide if it should be 4412251881Speter * renegotiated or not ? 4413251881Speter * XXX expire message will actually NOT be 4414251881Speter * sent if SA is only used after soft 4415251881Speter * lifetime has been reached, see below 4416251881Speter * (DYING state) 4417251881Speter */ 4418251881Speter if (sav->lft_c->usetime != 0) 4419251881Speter key_expire(sav); 4420251881Speter } 4421251881Speter /* check SOFT lifetime by bytes */ 4422251881Speter /* 4423251881Speter * XXX I don't know the way to delete this SA 4424251881Speter * when new SA is installed. Caution when it's 4425251881Speter * installed too big lifetime by time. 4426251881Speter */ 4427251881Speter else if (sav->lft_s->bytes != 0 && 4428251881Speter sav->lft_s->bytes < sav->lft_c->bytes) { 4429251881Speter 4430251881Speter key_sa_chgstate(sav, SADB_SASTATE_DYING); 4431251881Speter /* 4432251881Speter * XXX If we keep to send expire 4433251881Speter * message in the status of 4434251881Speter * DYING. Do remove below code. 4435251881Speter */ 4436251881Speter key_expire(sav); 4437251881Speter } 4438251881Speter } 4439251881Speter 4440251881Speter /* check DYING entry to change status to DEAD. */ 4441251881Speter LIST_FOREACH_SAFE(sav, &sah->savtree[SADB_SASTATE_DYING], chain, nextsav) { 4442251881Speter /* we don't need to check. */ 4443251881Speter if (sav->lft_h == NULL) 4444251881Speter continue; 4445251881Speter 4446251881Speter /* sanity check */ 4447251881Speter if (sav->lft_c == NULL) { 4448251881Speter ipseclog((LOG_DEBUG, "%s: there is no CURRENT " 4449251881Speter "time, why?\n", __func__)); 4450251881Speter continue; 4451251881Speter } 4452251881Speter 4453251881Speter if (sav->lft_h->addtime != 0 && 4454251881Speter now - sav->created > sav->lft_h->addtime) { 4455251881Speter key_sa_chgstate(sav, SADB_SASTATE_DEAD); 4456251881Speter KEY_FREESAV(&sav); 4457251881Speter } 4458251881Speter#if 0 /* XXX Should we keep to send expire message until HARD lifetime ? */ 4459251881Speter else if (sav->lft_s != NULL 4460251881Speter && sav->lft_s->addtime != 0 4461251881Speter && now - sav->created > sav->lft_s->addtime) { 4462251881Speter /* 4463251881Speter * XXX: should be checked to be 4464251881Speter * installed the valid SA. 4465251881Speter */ 4466251881Speter 4467251881Speter /* 4468251881Speter * If there is no SA then sending 4469251881Speter * expire message. 4470251881Speter */ 4471251881Speter key_expire(sav); 4472251881Speter } 4473251881Speter#endif 4474251881Speter /* check HARD lifetime by bytes */ 4475251881Speter else if (sav->lft_h->bytes != 0 && 4476251881Speter sav->lft_h->bytes < sav->lft_c->bytes) { 4477251881Speter key_sa_chgstate(sav, SADB_SASTATE_DEAD); 4478251881Speter KEY_FREESAV(&sav); 4479251881Speter } 4480251881Speter } 4481251881Speter 4482251881Speter /* delete entry in DEAD */ 4483251881Speter LIST_FOREACH_SAFE(sav, &sah->savtree[SADB_SASTATE_DEAD], chain, nextsav) { 4484251881Speter /* sanity check */ 4485251881Speter if (sav->state != SADB_SASTATE_DEAD) { 4486251881Speter ipseclog((LOG_DEBUG, "%s: invalid sav->state " 4487251881Speter "(queue: %d SA: %d): kill it anyway\n", 4488251881Speter __func__, 4489251881Speter SADB_SASTATE_DEAD, sav->state)); 4490251881Speter } 4491251881Speter /* 4492251881Speter * do not call key_freesav() here. 4493251881Speter * sav should already be freed, and sav->refcnt 4494251881Speter * shows other references to sav 4495251881Speter * (such as from SPD). 4496251881Speter */ 4497251881Speter } 4498251881Speter } 4499251881Speter SAHTREE_UNLOCK(); 4500251881Speter} 4501251881Speter 4502251881Speterstatic void 4503251881Speterkey_flush_acq(time_t now) 4504251881Speter{ 4505251881Speter INIT_VNET_IPSEC(curvnet); 4506251881Speter struct secacq *acq, *nextacq; 4507251881Speter 4508251881Speter /* ACQ tree */ 4509251881Speter ACQ_LOCK(); 4510251881Speter for (acq = LIST_FIRST(&V_acqtree); acq != NULL; acq = nextacq) { 4511251881Speter nextacq = LIST_NEXT(acq, chain); 4512251881Speter if (now - acq->created > V_key_blockacq_lifetime 4513251881Speter && __LIST_CHAINED(acq)) { 4514251881Speter LIST_REMOVE(acq, chain); 4515251881Speter free(acq, M_IPSEC_SAQ); 4516251881Speter } 4517251881Speter } 4518251881Speter ACQ_UNLOCK(); 4519251881Speter} 4520251881Speter 4521251881Speterstatic void 4522251881Speterkey_flush_spacq(time_t now) 4523251881Speter{ 4524251881Speter INIT_VNET_IPSEC(curvnet); 4525251881Speter struct secspacq *acq, *nextacq; 4526251881Speter 4527251881Speter /* SP ACQ tree */ 4528251881Speter SPACQ_LOCK(); 4529251881Speter for (acq = LIST_FIRST(&V_spacqtree); acq != NULL; acq = nextacq) { 4530251881Speter nextacq = LIST_NEXT(acq, chain); 4531251881Speter if (now - acq->created > V_key_blockacq_lifetime 4532251881Speter && __LIST_CHAINED(acq)) { 4533251881Speter LIST_REMOVE(acq, chain); 4534251881Speter free(acq, M_IPSEC_SAQ); 4535251881Speter } 4536251881Speter } 4537251881Speter SPACQ_UNLOCK(); 4538251881Speter} 4539251881Speter 4540251881Speter/* 4541251881Speter * time handler. 4542251881Speter * scanning SPD and SAD to check status for each entries, 4543251881Speter * and do to remove or to expire. 4544251881Speter * XXX: year 2038 problem may remain. 4545251881Speter */ 4546251881Spetervoid 4547251881Speterkey_timehandler(void) 4548251881Speter{ 4549251881Speter VNET_ITERATOR_DECL(vnet_iter); 4550251881Speter time_t now = time_second; 4551251881Speter 4552251881Speter VNET_LIST_RLOCK(); 4553251881Speter VNET_FOREACH(vnet_iter) { 4554251881Speter CURVNET_SET(vnet_iter); 4555251881Speter key_flush_spd(now); 4556251881Speter key_flush_sad(now); 4557251881Speter key_flush_acq(now); 4558251881Speter key_flush_spacq(now); 4559251881Speter CURVNET_RESTORE(); 4560251881Speter } 4561251881Speter VNET_LIST_RUNLOCK(); 4562251881Speter 4563251881Speter#ifndef IPSEC_DEBUG2 4564251881Speter /* do exchange to tick time !! */ 4565251881Speter (void)timeout((void *)key_timehandler, (void *)0, hz); 4566251881Speter#endif /* IPSEC_DEBUG2 */ 4567251881Speter} 4568251881Speter 4569251881Speteru_long 4570251881Speterkey_random() 4571251881Speter{ 4572251881Speter u_long value; 4573251881Speter 4574251881Speter key_randomfill(&value, sizeof(value)); 4575251881Speter return value; 4576251881Speter} 4577251881Speter 4578251881Spetervoid 4579251881Speterkey_randomfill(p, l) 4580251881Speter void *p; 4581251881Speter size_t l; 4582251881Speter{ 4583251881Speter size_t n; 4584251881Speter u_long v; 4585251881Speter static int warn = 1; 4586251881Speter 4587251881Speter n = 0; 4588251881Speter n = (size_t)read_random(p, (u_int)l); 4589251881Speter /* last resort */ 4590251881Speter while (n < l) { 4591251881Speter v = random(); 4592251881Speter bcopy(&v, (u_int8_t *)p + n, 4593251881Speter l - n < sizeof(v) ? l - n : sizeof(v)); 4594251881Speter n += sizeof(v); 4595251881Speter 4596251881Speter if (warn) { 4597251881Speter printf("WARNING: pseudo-random number generator " 4598251881Speter "used for IPsec processing\n"); 4599251881Speter warn = 0; 4600251881Speter } 4601251881Speter } 4602251881Speter} 4603251881Speter 4604251881Speter/* 4605251881Speter * map SADB_SATYPE_* to IPPROTO_*. 4606251881Speter * if satype == SADB_SATYPE then satype is mapped to ~0. 4607251881Speter * OUT: 4608251881Speter * 0: invalid satype. 4609251881Speter */ 4610251881Speterstatic u_int16_t 4611251881Speterkey_satype2proto(u_int8_t satype) 4612251881Speter{ 4613251881Speter switch (satype) { 4614251881Speter case SADB_SATYPE_UNSPEC: 4615251881Speter return IPSEC_PROTO_ANY; 4616251881Speter case SADB_SATYPE_AH: 4617251881Speter return IPPROTO_AH; 4618251881Speter case SADB_SATYPE_ESP: 4619251881Speter return IPPROTO_ESP; 4620251881Speter case SADB_X_SATYPE_IPCOMP: 4621251881Speter return IPPROTO_IPCOMP; 4622251881Speter case SADB_X_SATYPE_TCPSIGNATURE: 4623251881Speter return IPPROTO_TCP; 4624251881Speter default: 4625251881Speter return 0; 4626251881Speter } 4627251881Speter /* NOTREACHED */ 4628251881Speter} 4629251881Speter 4630251881Speter/* 4631251881Speter * map IPPROTO_* to SADB_SATYPE_* 4632251881Speter * OUT: 4633251881Speter * 0: invalid protocol type. 4634251881Speter */ 4635251881Speterstatic u_int8_t 4636251881Speterkey_proto2satype(u_int16_t proto) 4637251881Speter{ 4638251881Speter switch (proto) { 4639251881Speter case IPPROTO_AH: 4640251881Speter return SADB_SATYPE_AH; 4641251881Speter case IPPROTO_ESP: 4642251881Speter return SADB_SATYPE_ESP; 4643251881Speter case IPPROTO_IPCOMP: 4644251881Speter return SADB_X_SATYPE_IPCOMP; 4645251881Speter case IPPROTO_TCP: 4646251881Speter return SADB_X_SATYPE_TCPSIGNATURE; 4647251881Speter default: 4648251881Speter return 0; 4649251881Speter } 4650251881Speter /* NOTREACHED */ 4651251881Speter} 4652251881Speter 4653251881Speter/* %%% PF_KEY */ 4654251881Speter/* 4655251881Speter * SADB_GETSPI processing is to receive 4656251881Speter * <base, (SA2), src address, dst address, (SPI range)> 4657251881Speter * from the IKMPd, to assign a unique spi value, to hang on the INBOUND 4658251881Speter * tree with the status of LARVAL, and send 4659251881Speter * <base, SA(*), address(SD)> 4660251881Speter * to the IKMPd. 4661251881Speter * 4662251881Speter * IN: mhp: pointer to the pointer to each header. 4663251881Speter * OUT: NULL if fail. 4664251881Speter * other if success, return pointer to the message to send. 4665251881Speter */ 4666251881Speterstatic int 4667251881Speterkey_getspi(so, m, mhp) 4668251881Speter struct socket *so; 4669251881Speter struct mbuf *m; 4670251881Speter const struct sadb_msghdr *mhp; 4671251881Speter{ 4672251881Speter INIT_VNET_IPSEC(curvnet); 4673251881Speter struct sadb_address *src0, *dst0; 4674251881Speter struct secasindex saidx; 4675251881Speter struct secashead *newsah; 4676251881Speter struct secasvar *newsav; 4677251881Speter u_int8_t proto; 4678251881Speter u_int32_t spi; 4679251881Speter u_int8_t mode; 4680251881Speter u_int32_t reqid; 4681251881Speter int error; 4682251881Speter 4683251881Speter IPSEC_ASSERT(so != NULL, ("null socket")); 4684251881Speter IPSEC_ASSERT(m != NULL, ("null mbuf")); 4685251881Speter IPSEC_ASSERT(mhp != NULL, ("null msghdr")); 4686251881Speter IPSEC_ASSERT(mhp->msg != NULL, ("null msg")); 4687251881Speter 4688251881Speter if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || 4689251881Speter mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) { 4690251881Speter ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", 4691251881Speter __func__)); 4692251881Speter return key_senderror(so, m, EINVAL); 4693251881Speter } 4694251881Speter if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || 4695251881Speter mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) { 4696251881Speter ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", 4697251881Speter __func__)); 4698251881Speter return key_senderror(so, m, EINVAL); 4699251881Speter } 4700251881Speter if (mhp->ext[SADB_X_EXT_SA2] != NULL) { 4701251881Speter mode = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_mode; 4702251881Speter reqid = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_reqid; 4703251881Speter } else { 4704251881Speter mode = IPSEC_MODE_ANY; 4705251881Speter reqid = 0; 4706251881Speter } 4707251881Speter 4708251881Speter src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]); 4709251881Speter dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]); 4710251881Speter 4711251881Speter /* map satype to proto */ 4712251881Speter if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { 4713251881Speter ipseclog((LOG_DEBUG, "%s: invalid satype is passed.\n", 4714251881Speter __func__)); 4715251881Speter return key_senderror(so, m, EINVAL); 4716251881Speter } 4717251881Speter 4718251881Speter /* 4719251881Speter * Make sure the port numbers are zero. 4720251881Speter * In case of NAT-T we will update them later if needed. 4721251881Speter */ 4722251881Speter switch (((struct sockaddr *)(src0 + 1))->sa_family) { 4723251881Speter case AF_INET: 4724251881Speter if (((struct sockaddr *)(src0 + 1))->sa_len != 4725251881Speter sizeof(struct sockaddr_in)) 4726251881Speter return key_senderror(so, m, EINVAL); 4727251881Speter ((struct sockaddr_in *)(src0 + 1))->sin_port = 0; 4728251881Speter break; 4729251881Speter case AF_INET6: 4730251881Speter if (((struct sockaddr *)(src0 + 1))->sa_len != 4731251881Speter sizeof(struct sockaddr_in6)) 4732251881Speter return key_senderror(so, m, EINVAL); 4733251881Speter ((struct sockaddr_in6 *)(src0 + 1))->sin6_port = 0; 4734251881Speter break; 4735251881Speter default: 4736251881Speter ; /*???*/ 4737251881Speter } 4738251881Speter switch (((struct sockaddr *)(dst0 + 1))->sa_family) { 4739251881Speter case AF_INET: 4740251881Speter if (((struct sockaddr *)(dst0 + 1))->sa_len != 4741251881Speter sizeof(struct sockaddr_in)) 4742251881Speter return key_senderror(so, m, EINVAL); 4743251881Speter ((struct sockaddr_in *)(dst0 + 1))->sin_port = 0; 4744251881Speter break; 4745251881Speter case AF_INET6: 4746251881Speter if (((struct sockaddr *)(dst0 + 1))->sa_len != 4747251881Speter sizeof(struct sockaddr_in6)) 4748251881Speter return key_senderror(so, m, EINVAL); 4749251881Speter ((struct sockaddr_in6 *)(dst0 + 1))->sin6_port = 0; 4750251881Speter break; 4751251881Speter default: 4752251881Speter ; /*???*/ 4753251881Speter } 4754251881Speter 4755251881Speter /* XXX boundary check against sa_len */ 4756251881Speter KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx); 4757251881Speter 4758251881Speter#ifdef IPSEC_NAT_T 4759251881Speter /* 4760251881Speter * Handle NAT-T info if present. 4761251881Speter * We made sure the port numbers are zero above, so we do 4762251881Speter * not have to worry in case we do not update them. 4763251881Speter */ 4764251881Speter if (mhp->ext[SADB_X_EXT_NAT_T_OAI] != NULL) 4765251881Speter ipseclog((LOG_DEBUG, "%s: NAT-T OAi present\n", __func__)); 4766251881Speter if (mhp->ext[SADB_X_EXT_NAT_T_OAR] != NULL) 4767251881Speter ipseclog((LOG_DEBUG, "%s: NAT-T OAr present\n", __func__)); 4768251881Speter 4769251881Speter if (mhp->ext[SADB_X_EXT_NAT_T_TYPE] != NULL && 4770251881Speter mhp->ext[SADB_X_EXT_NAT_T_SPORT] != NULL && 4771251881Speter mhp->ext[SADB_X_EXT_NAT_T_DPORT] != NULL) { 4772251881Speter struct sadb_x_nat_t_type *type; 4773251881Speter struct sadb_x_nat_t_port *sport, *dport; 4774251881Speter 4775251881Speter if (mhp->extlen[SADB_X_EXT_NAT_T_TYPE] < sizeof(*type) || 4776251881Speter mhp->extlen[SADB_X_EXT_NAT_T_SPORT] < sizeof(*sport) || 4777251881Speter mhp->extlen[SADB_X_EXT_NAT_T_DPORT] < sizeof(*dport)) { 4778251881Speter ipseclog((LOG_DEBUG, "%s: invalid nat-t message " 4779251881Speter "passed.\n", __func__)); 4780251881Speter return key_senderror(so, m, EINVAL); 4781251881Speter } 4782251881Speter 4783251881Speter sport = (struct sadb_x_nat_t_port *) 4784251881Speter mhp->ext[SADB_X_EXT_NAT_T_SPORT]; 4785251881Speter dport = (struct sadb_x_nat_t_port *) 4786251881Speter mhp->ext[SADB_X_EXT_NAT_T_DPORT]; 4787251881Speter 4788251881Speter if (sport) 4789251881Speter KEY_PORTTOSADDR(&saidx.src, sport->sadb_x_nat_t_port_port); 4790251881Speter if (dport) 4791251881Speter KEY_PORTTOSADDR(&saidx.dst, dport->sadb_x_nat_t_port_port); 4792251881Speter } 4793251881Speter#endif 4794251881Speter 4795251881Speter /* SPI allocation */ 4796251881Speter spi = key_do_getnewspi((struct sadb_spirange *)mhp->ext[SADB_EXT_SPIRANGE], 4797251881Speter &saidx); 4798251881Speter if (spi == 0) 4799251881Speter return key_senderror(so, m, EINVAL); 4800251881Speter 4801251881Speter /* get a SA index */ 4802251881Speter if ((newsah = key_getsah(&saidx)) == NULL) { 4803251881Speter /* create a new SA index */ 4804251881Speter if ((newsah = key_newsah(&saidx)) == NULL) { 4805251881Speter ipseclog((LOG_DEBUG, "%s: No more memory.\n",__func__)); 4806251881Speter return key_senderror(so, m, ENOBUFS); 4807251881Speter } 4808251881Speter } 4809251881Speter 4810251881Speter /* get a new SA */ 4811251881Speter /* XXX rewrite */ 4812251881Speter newsav = KEY_NEWSAV(m, mhp, newsah, &error); 4813251881Speter if (newsav == NULL) { 4814251881Speter /* XXX don't free new SA index allocated in above. */ 4815251881Speter return key_senderror(so, m, error); 4816251881Speter } 4817251881Speter 4818251881Speter /* set spi */ 4819251881Speter newsav->spi = htonl(spi); 4820251881Speter 4821251881Speter /* delete the entry in acqtree */ 4822251881Speter if (mhp->msg->sadb_msg_seq != 0) { 4823251881Speter struct secacq *acq; 4824251881Speter if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq)) != NULL) { 4825251881Speter /* reset counter in order to deletion by timehandler. */ 4826251881Speter acq->created = time_second; 4827251881Speter acq->count = 0; 4828251881Speter } 4829251881Speter } 4830251881Speter 4831251881Speter { 4832251881Speter struct mbuf *n, *nn; 4833251881Speter struct sadb_sa *m_sa; 4834251881Speter struct sadb_msg *newmsg; 4835251881Speter int off, len; 4836251881Speter 4837251881Speter /* create new sadb_msg to reply. */ 4838251881Speter len = PFKEY_ALIGN8(sizeof(struct sadb_msg)) + 4839251881Speter PFKEY_ALIGN8(sizeof(struct sadb_sa)); 4840251881Speter 4841251881Speter MGETHDR(n, M_DONTWAIT, MT_DATA); 4842251881Speter if (len > MHLEN) { 4843251881Speter MCLGET(n, M_DONTWAIT); 4844251881Speter if ((n->m_flags & M_EXT) == 0) { 4845251881Speter m_freem(n); 4846251881Speter n = NULL; 4847251881Speter } 4848251881Speter } 4849251881Speter if (!n) 4850251881Speter return key_senderror(so, m, ENOBUFS); 4851251881Speter 4852251881Speter n->m_len = len; 4853251881Speter n->m_next = NULL; 4854251881Speter off = 0; 4855251881Speter 4856251881Speter m_copydata(m, 0, sizeof(struct sadb_msg), mtod(n, caddr_t) + off); 4857251881Speter off += PFKEY_ALIGN8(sizeof(struct sadb_msg)); 4858251881Speter 4859251881Speter m_sa = (struct sadb_sa *)(mtod(n, caddr_t) + off); 4860251881Speter m_sa->sadb_sa_len = PFKEY_UNIT64(sizeof(struct sadb_sa)); 4861251881Speter m_sa->sadb_sa_exttype = SADB_EXT_SA; 4862251881Speter m_sa->sadb_sa_spi = htonl(spi); 4863251881Speter off += PFKEY_ALIGN8(sizeof(struct sadb_sa)); 4864251881Speter 4865251881Speter IPSEC_ASSERT(off == len, 4866251881Speter ("length inconsistency (off %u len %u)", off, len)); 4867251881Speter 4868251881Speter n->m_next = key_gather_mbuf(m, mhp, 0, 2, SADB_EXT_ADDRESS_SRC, 4869251881Speter SADB_EXT_ADDRESS_DST); 4870251881Speter if (!n->m_next) { 4871251881Speter m_freem(n); 4872251881Speter return key_senderror(so, m, ENOBUFS); 4873251881Speter } 4874251881Speter 4875251881Speter if (n->m_len < sizeof(struct sadb_msg)) { 4876251881Speter n = m_pullup(n, sizeof(struct sadb_msg)); 4877251881Speter if (n == NULL) 4878251881Speter return key_sendup_mbuf(so, m, KEY_SENDUP_ONE); 4879251881Speter } 4880251881Speter 4881251881Speter n->m_pkthdr.len = 0; 4882251881Speter for (nn = n; nn; nn = nn->m_next) 4883251881Speter n->m_pkthdr.len += nn->m_len; 4884251881Speter 4885251881Speter newmsg = mtod(n, struct sadb_msg *); 4886251881Speter newmsg->sadb_msg_seq = newsav->seq; 4887251881Speter newmsg->sadb_msg_errno = 0; 4888251881Speter newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); 4889251881Speter 4890251881Speter m_freem(m); 4891251881Speter return key_sendup_mbuf(so, n, KEY_SENDUP_ONE); 4892251881Speter } 4893251881Speter} 4894251881Speter 4895251881Speter/* 4896251881Speter * allocating new SPI 4897251881Speter * called by key_getspi(). 4898251881Speter * OUT: 4899251881Speter * 0: failure. 4900251881Speter * others: success. 4901251881Speter */ 4902251881Speterstatic u_int32_t 4903251881Speterkey_do_getnewspi(spirange, saidx) 4904251881Speter struct sadb_spirange *spirange; 4905251881Speter struct secasindex *saidx; 4906251881Speter{ 4907251881Speter INIT_VNET_IPSEC(curvnet); 4908251881Speter u_int32_t newspi; 4909251881Speter u_int32_t min, max; 4910251881Speter int count = V_key_spi_trycnt; 4911251881Speter 4912251881Speter /* set spi range to allocate */ 4913251881Speter if (spirange != NULL) { 4914251881Speter min = spirange->sadb_spirange_min; 4915251881Speter max = spirange->sadb_spirange_max; 4916251881Speter } else { 4917251881Speter min = V_key_spi_minval; 4918251881Speter max = V_key_spi_maxval; 4919251881Speter } 4920251881Speter /* IPCOMP needs 2-byte SPI */ 4921251881Speter if (saidx->proto == IPPROTO_IPCOMP) { 4922251881Speter u_int32_t t; 4923251881Speter if (min >= 0x10000) 4924251881Speter min = 0xffff; 4925251881Speter if (max >= 0x10000) 4926251881Speter max = 0xffff; 4927251881Speter if (min > max) { 4928251881Speter t = min; min = max; max = t; 4929251881Speter } 4930251881Speter } 4931251881Speter 4932251881Speter if (min == max) { 4933251881Speter if (key_checkspidup(saidx, min) != NULL) { 4934251881Speter ipseclog((LOG_DEBUG, "%s: SPI %u exists already.\n", 4935251881Speter __func__, min)); 4936251881Speter return 0; 4937251881Speter } 4938251881Speter 4939251881Speter count--; /* taking one cost. */ 4940251881Speter newspi = min; 4941251881Speter 4942251881Speter } else { 4943251881Speter 4944251881Speter /* init SPI */ 4945251881Speter newspi = 0; 4946251881Speter 4947251881Speter /* when requesting to allocate spi ranged */ 4948251881Speter while (count--) { 4949251881Speter /* generate pseudo-random SPI value ranged. */ 4950251881Speter newspi = min + (key_random() % (max - min + 1)); 4951251881Speter 4952251881Speter if (key_checkspidup(saidx, newspi) == NULL) 4953251881Speter break; 4954251881Speter } 4955251881Speter 4956251881Speter if (count == 0 || newspi == 0) { 4957251881Speter ipseclog((LOG_DEBUG, "%s: to allocate spi is failed.\n", 4958251881Speter __func__)); 4959251881Speter return 0; 4960251881Speter } 4961251881Speter } 4962251881Speter 4963251881Speter /* statistics */ 4964251881Speter keystat.getspi_count = 4965251881Speter (keystat.getspi_count + V_key_spi_trycnt - count) / 2; 4966251881Speter 4967251881Speter return newspi; 4968251881Speter} 4969251881Speter 4970251881Speter/* 4971251881Speter * SADB_UPDATE processing 4972251881Speter * receive 4973251881Speter * <base, SA, (SA2), (lifetime(HSC),) address(SD), (address(P),) 4974251881Speter * key(AE), (identity(SD),) (sensitivity)> 4975251881Speter * from the ikmpd, and update a secasvar entry whose status is SADB_SASTATE_LARVAL. 4976251881Speter * and send 4977251881Speter * <base, SA, (SA2), (lifetime(HSC),) address(SD), (address(P),) 4978251881Speter * (identity(SD),) (sensitivity)> 4979251881Speter * to the ikmpd. 4980251881Speter * 4981251881Speter * m will always be freed. 4982251881Speter */ 4983251881Speterstatic int 4984251881Speterkey_update(so, m, mhp) 4985251881Speter struct socket *so; 4986251881Speter struct mbuf *m; 4987251881Speter const struct sadb_msghdr *mhp; 4988251881Speter{ 4989251881Speter INIT_VNET_IPSEC(curvnet); 4990251881Speter struct sadb_sa *sa0; 4991251881Speter struct sadb_address *src0, *dst0; 4992251881Speter#ifdef IPSEC_NAT_T 4993251881Speter struct sadb_x_nat_t_type *type; 4994251881Speter struct sadb_address *iaddr, *raddr; 4995251881Speter struct sadb_x_nat_t_frag *frag; 4996251881Speter#endif 4997251881Speter struct secasindex saidx; 4998251881Speter struct secashead *sah; 4999251881Speter struct secasvar *sav; 5000251881Speter u_int16_t proto; 5001251881Speter u_int8_t mode; 5002251881Speter u_int32_t reqid; 5003251881Speter int error; 5004251881Speter 5005251881Speter IPSEC_ASSERT(so != NULL, ("null socket")); 5006251881Speter IPSEC_ASSERT(m != NULL, ("null mbuf")); 5007251881Speter IPSEC_ASSERT(mhp != NULL, ("null msghdr")); 5008251881Speter IPSEC_ASSERT(mhp->msg != NULL, ("null msg")); 5009251881Speter 5010251881Speter /* map satype to proto */ 5011251881Speter if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { 5012251881Speter ipseclog((LOG_DEBUG, "%s: invalid satype is passed.\n", 5013251881Speter __func__)); 5014251881Speter return key_senderror(so, m, EINVAL); 5015251881Speter } 5016251881Speter 5017251881Speter if (mhp->ext[SADB_EXT_SA] == NULL || 5018251881Speter mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || 5019251881Speter mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || 5020251881Speter (mhp->msg->sadb_msg_satype == SADB_SATYPE_ESP && 5021251881Speter mhp->ext[SADB_EXT_KEY_ENCRYPT] == NULL) || 5022251881Speter (mhp->msg->sadb_msg_satype == SADB_SATYPE_AH && 5023251881Speter mhp->ext[SADB_EXT_KEY_AUTH] == NULL) || 5024251881Speter (mhp->ext[SADB_EXT_LIFETIME_HARD] != NULL && 5025251881Speter mhp->ext[SADB_EXT_LIFETIME_SOFT] == NULL) || 5026251881Speter (mhp->ext[SADB_EXT_LIFETIME_HARD] == NULL && 5027251881Speter mhp->ext[SADB_EXT_LIFETIME_SOFT] != NULL)) { 5028251881Speter ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", 5029251881Speter __func__)); 5030251881Speter return key_senderror(so, m, EINVAL); 5031251881Speter } 5032251881Speter if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) || 5033251881Speter mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || 5034251881Speter mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) { 5035251881Speter ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", 5036251881Speter __func__)); 5037251881Speter return key_senderror(so, m, EINVAL); 5038251881Speter } 5039251881Speter if (mhp->ext[SADB_X_EXT_SA2] != NULL) { 5040251881Speter mode = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_mode; 5041251881Speter reqid = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_reqid; 5042251881Speter } else { 5043251881Speter mode = IPSEC_MODE_ANY; 5044251881Speter reqid = 0; 5045251881Speter } 5046251881Speter /* XXX boundary checking for other extensions */ 5047251881Speter 5048251881Speter sa0 = (struct sadb_sa *)mhp->ext[SADB_EXT_SA]; 5049251881Speter src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]); 5050251881Speter dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]); 5051251881Speter 5052251881Speter /* XXX boundary check against sa_len */ 5053251881Speter KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx); 5054251881Speter 5055251881Speter /* 5056251881Speter * Make sure the port numbers are zero. 5057251881Speter * In case of NAT-T we will update them later if needed. 5058251881Speter */ 5059251881Speter KEY_PORTTOSADDR(&saidx.src, 0); 5060251881Speter KEY_PORTTOSADDR(&saidx.dst, 0); 5061251881Speter 5062251881Speter#ifdef IPSEC_NAT_T 5063251881Speter /* 5064251881Speter * Handle NAT-T info if present. 5065251881Speter */ 5066251881Speter if (mhp->ext[SADB_X_EXT_NAT_T_TYPE] != NULL && 5067251881Speter mhp->ext[SADB_X_EXT_NAT_T_SPORT] != NULL && 5068251881Speter mhp->ext[SADB_X_EXT_NAT_T_DPORT] != NULL) { 5069251881Speter struct sadb_x_nat_t_port *sport, *dport; 5070251881Speter 5071251881Speter if (mhp->extlen[SADB_X_EXT_NAT_T_TYPE] < sizeof(*type) || 5072251881Speter mhp->extlen[SADB_X_EXT_NAT_T_SPORT] < sizeof(*sport) || 5073251881Speter mhp->extlen[SADB_X_EXT_NAT_T_DPORT] < sizeof(*dport)) { 5074251881Speter ipseclog((LOG_DEBUG, "%s: invalid message.\n", 5075251881Speter __func__)); 5076251881Speter return key_senderror(so, m, EINVAL); 5077251881Speter } 5078251881Speter 5079251881Speter type = (struct sadb_x_nat_t_type *) 5080251881Speter mhp->ext[SADB_X_EXT_NAT_T_TYPE]; 5081251881Speter sport = (struct sadb_x_nat_t_port *) 5082251881Speter mhp->ext[SADB_X_EXT_NAT_T_SPORT]; 5083251881Speter dport = (struct sadb_x_nat_t_port *) 5084251881Speter mhp->ext[SADB_X_EXT_NAT_T_DPORT]; 5085251881Speter 5086251881Speter if (sport) 5087251881Speter KEY_PORTTOSADDR(&saidx.src, 5088251881Speter sport->sadb_x_nat_t_port_port); 5089251881Speter if (dport) 5090251881Speter KEY_PORTTOSADDR(&saidx.dst, 5091251881Speter dport->sadb_x_nat_t_port_port); 5092251881Speter } else { 5093251881Speter type = 0; 5094251881Speter } 5095251881Speter if (mhp->ext[SADB_X_EXT_NAT_T_OAI] != NULL && 5096251881Speter mhp->ext[SADB_X_EXT_NAT_T_OAR] != NULL) { 5097251881Speter if (mhp->extlen[SADB_X_EXT_NAT_T_OAI] < sizeof(*iaddr) || 5098251881Speter mhp->extlen[SADB_X_EXT_NAT_T_OAR] < sizeof(*raddr)) { 5099251881Speter ipseclog((LOG_DEBUG, "%s: invalid message\n", 5100251881Speter __func__)); 5101251881Speter return key_senderror(so, m, EINVAL); 5102251881Speter } 5103251881Speter iaddr = (struct sadb_address *)mhp->ext[SADB_X_EXT_NAT_T_OAI]; 5104251881Speter raddr = (struct sadb_address *)mhp->ext[SADB_X_EXT_NAT_T_OAR]; 5105251881Speter ipseclog((LOG_DEBUG, "%s: NAT-T OAi/r present\n", __func__)); 5106251881Speter } else { 5107251881Speter iaddr = raddr = NULL; 5108251881Speter } 5109251881Speter if (mhp->ext[SADB_X_EXT_NAT_T_FRAG] != NULL) { 5110251881Speter if (mhp->extlen[SADB_X_EXT_NAT_T_FRAG] < sizeof(*frag)) { 5111251881Speter ipseclog((LOG_DEBUG, "%s: invalid message\n", 5112251881Speter __func__)); 5113251881Speter return key_senderror(so, m, EINVAL); 5114251881Speter } 5115251881Speter frag = (struct sadb_x_nat_t_frag *) 5116251881Speter mhp->ext[SADB_X_EXT_NAT_T_FRAG]; 5117251881Speter } else { 5118251881Speter frag = 0; 5119251881Speter } 5120251881Speter#endif 5121251881Speter 5122251881Speter /* get a SA header */ 5123251881Speter if ((sah = key_getsah(&saidx)) == NULL) { 5124251881Speter ipseclog((LOG_DEBUG, "%s: no SA index found.\n", __func__)); 5125251881Speter return key_senderror(so, m, ENOENT); 5126251881Speter } 5127251881Speter 5128251881Speter /* set spidx if there */ 5129251881Speter /* XXX rewrite */ 5130251881Speter error = key_setident(sah, m, mhp); 5131251881Speter if (error) 5132251881Speter return key_senderror(so, m, error); 5133251881Speter 5134251881Speter /* find a SA with sequence number. */ 5135251881Speter#ifdef IPSEC_DOSEQCHECK 5136251881Speter if (mhp->msg->sadb_msg_seq != 0 5137251881Speter && (sav = key_getsavbyseq(sah, mhp->msg->sadb_msg_seq)) == NULL) { 5138251881Speter ipseclog((LOG_DEBUG, "%s: no larval SA with sequence %u " 5139251881Speter "exists.\n", __func__, mhp->msg->sadb_msg_seq)); 5140251881Speter return key_senderror(so, m, ENOENT); 5141251881Speter } 5142251881Speter#else 5143251881Speter SAHTREE_LOCK(); 5144251881Speter sav = key_getsavbyspi(sah, sa0->sadb_sa_spi); 5145251881Speter SAHTREE_UNLOCK(); 5146251881Speter if (sav == NULL) { 5147251881Speter ipseclog((LOG_DEBUG, "%s: no such a SA found (spi:%u)\n", 5148251881Speter __func__, (u_int32_t)ntohl(sa0->sadb_sa_spi))); 5149251881Speter return key_senderror(so, m, EINVAL); 5150251881Speter } 5151251881Speter#endif 5152251881Speter 5153251881Speter /* validity check */ 5154251881Speter if (sav->sah->saidx.proto != proto) { 5155251881Speter ipseclog((LOG_DEBUG, "%s: protocol mismatched " 5156251881Speter "(DB=%u param=%u)\n", __func__, 5157251881Speter sav->sah->saidx.proto, proto)); 5158251881Speter return key_senderror(so, m, EINVAL); 5159251881Speter } 5160251881Speter#ifdef IPSEC_DOSEQCHECK 5161251881Speter if (sav->spi != sa0->sadb_sa_spi) { 5162251881Speter ipseclog((LOG_DEBUG, "%s: SPI mismatched (DB:%u param:%u)\n", 5163251881Speter __func__, 5164251881Speter (u_int32_t)ntohl(sav->spi), 5165251881Speter (u_int32_t)ntohl(sa0->sadb_sa_spi))); 5166251881Speter return key_senderror(so, m, EINVAL); 5167251881Speter } 5168251881Speter#endif 5169251881Speter if (sav->pid != mhp->msg->sadb_msg_pid) { 5170251881Speter ipseclog((LOG_DEBUG, "%s: pid mismatched (DB:%u param:%u)\n", 5171251881Speter __func__, sav->pid, mhp->msg->sadb_msg_pid)); 5172251881Speter return key_senderror(so, m, EINVAL); 5173251881Speter } 5174251881Speter 5175251881Speter /* copy sav values */ 5176251881Speter error = key_setsaval(sav, m, mhp); 5177251881Speter if (error) { 5178251881Speter KEY_FREESAV(&sav); 5179251881Speter return key_senderror(so, m, error); 5180251881Speter } 5181251881Speter 5182251881Speter /* check SA values to be mature. */ 5183251881Speter if ((mhp->msg->sadb_msg_errno = key_mature(sav)) != 0) { 5184251881Speter KEY_FREESAV(&sav); 5185251881Speter return key_senderror(so, m, 0); 5186251881Speter } 5187251881Speter 5188251881Speter#ifdef IPSEC_NAT_T 5189251881Speter /* 5190251881Speter * Handle more NAT-T info if present, 5191251881Speter * now that we have a sav to fill. 5192251881Speter */ 5193251881Speter if (type) 5194251881Speter sav->natt_type = type->sadb_x_nat_t_type_type; 5195251881Speter 5196251881Speter#if 0 5197251881Speter /* 5198251881Speter * In case SADB_X_EXT_NAT_T_FRAG was not given, leave it at 0. 5199251881Speter * We should actually check for a minimum MTU here, if we 5200251881Speter * want to support it in ip_output. 5201251881Speter */ 5202251881Speter if (frag) 5203251881Speter sav->natt_esp_frag_len = frag->sadb_x_nat_t_frag_fraglen; 5204251881Speter#endif 5205251881Speter#endif 5206251881Speter 5207251881Speter { 5208251881Speter struct mbuf *n; 5209251881Speter 5210251881Speter /* set msg buf from mhp */ 5211251881Speter n = key_getmsgbuf_x1(m, mhp); 5212251881Speter if (n == NULL) { 5213251881Speter ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__)); 5214251881Speter return key_senderror(so, m, ENOBUFS); 5215251881Speter } 5216251881Speter 5217251881Speter m_freem(m); 5218251881Speter return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); 5219251881Speter } 5220251881Speter} 5221251881Speter 5222251881Speter/* 5223251881Speter * search SAD with sequence for a SA which state is SADB_SASTATE_LARVAL. 5224251881Speter * only called by key_update(). 5225251881Speter * OUT: 5226251881Speter * NULL : not found 5227251881Speter * others : found, pointer to a SA. 5228251881Speter */ 5229251881Speter#ifdef IPSEC_DOSEQCHECK 5230251881Speterstatic struct secasvar * 5231251881Speterkey_getsavbyseq(sah, seq) 5232251881Speter struct secashead *sah; 5233251881Speter u_int32_t seq; 5234251881Speter{ 5235251881Speter struct secasvar *sav; 5236251881Speter u_int state; 5237251881Speter 5238251881Speter state = SADB_SASTATE_LARVAL; 5239251881Speter 5240251881Speter /* search SAD with sequence number ? */ 5241251881Speter LIST_FOREACH(sav, &sah->savtree[state], chain) { 5242251881Speter 5243251881Speter KEY_CHKSASTATE(state, sav->state, __func__); 5244251881Speter 5245251881Speter if (sav->seq == seq) { 5246251881Speter sa_addref(sav); 5247251881Speter KEYDEBUG(KEYDEBUG_IPSEC_STAMP, 5248251881Speter printf("DP %s cause refcnt++:%d SA:%p\n", 5249251881Speter __func__, sav->refcnt, sav)); 5250251881Speter return sav; 5251251881Speter } 5252251881Speter } 5253251881Speter 5254251881Speter return NULL; 5255251881Speter} 5256251881Speter#endif 5257251881Speter 5258251881Speter/* 5259251881Speter * SADB_ADD processing 5260251881Speter * add an entry to SA database, when received 5261251881Speter * <base, SA, (SA2), (lifetime(HSC),) address(SD), (address(P),) 5262251881Speter * key(AE), (identity(SD),) (sensitivity)> 5263251881Speter * from the ikmpd, 5264251881Speter * and send 5265251881Speter * <base, SA, (SA2), (lifetime(HSC),) address(SD), (address(P),) 5266251881Speter * (identity(SD),) (sensitivity)> 5267251881Speter * to the ikmpd. 5268251881Speter * 5269251881Speter * IGNORE identity and sensitivity messages. 5270251881Speter * 5271251881Speter * m will always be freed. 5272251881Speter */ 5273251881Speterstatic int 5274251881Speterkey_add(so, m, mhp) 5275251881Speter struct socket *so; 5276251881Speter struct mbuf *m; 5277251881Speter const struct sadb_msghdr *mhp; 5278251881Speter{ 5279251881Speter INIT_VNET_IPSEC(curvnet); 5280251881Speter struct sadb_sa *sa0; 5281251881Speter struct sadb_address *src0, *dst0; 5282251881Speter#ifdef IPSEC_NAT_T 5283251881Speter struct sadb_x_nat_t_type *type; 5284251881Speter struct sadb_address *iaddr, *raddr; 5285251881Speter struct sadb_x_nat_t_frag *frag; 5286251881Speter#endif 5287251881Speter struct secasindex saidx; 5288251881Speter struct secashead *newsah; 5289251881Speter struct secasvar *newsav; 5290251881Speter u_int16_t proto; 5291251881Speter u_int8_t mode; 5292251881Speter u_int32_t reqid; 5293251881Speter int error; 5294251881Speter 5295251881Speter IPSEC_ASSERT(so != NULL, ("null socket")); 5296251881Speter IPSEC_ASSERT(m != NULL, ("null mbuf")); 5297251881Speter IPSEC_ASSERT(mhp != NULL, ("null msghdr")); 5298251881Speter IPSEC_ASSERT(mhp->msg != NULL, ("null msg")); 5299251881Speter 5300251881Speter /* map satype to proto */ 5301251881Speter if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { 5302251881Speter ipseclog((LOG_DEBUG, "%s: invalid satype is passed.\n", 5303251881Speter __func__)); 5304251881Speter return key_senderror(so, m, EINVAL); 5305251881Speter } 5306251881Speter 5307251881Speter if (mhp->ext[SADB_EXT_SA] == NULL || 5308251881Speter mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || 5309251881Speter mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || 5310251881Speter (mhp->msg->sadb_msg_satype == SADB_SATYPE_ESP && 5311251881Speter mhp->ext[SADB_EXT_KEY_ENCRYPT] == NULL) || 5312251881Speter (mhp->msg->sadb_msg_satype == SADB_SATYPE_AH && 5313251881Speter mhp->ext[SADB_EXT_KEY_AUTH] == NULL) || 5314251881Speter (mhp->ext[SADB_EXT_LIFETIME_HARD] != NULL && 5315251881Speter mhp->ext[SADB_EXT_LIFETIME_SOFT] == NULL) || 5316251881Speter (mhp->ext[SADB_EXT_LIFETIME_HARD] == NULL && 5317251881Speter mhp->ext[SADB_EXT_LIFETIME_SOFT] != NULL)) { 5318251881Speter ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", 5319251881Speter __func__)); 5320251881Speter return key_senderror(so, m, EINVAL); 5321251881Speter } 5322251881Speter if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) || 5323251881Speter mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || 5324251881Speter mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) { 5325251881Speter /* XXX need more */ 5326251881Speter ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", 5327251881Speter __func__)); 5328251881Speter return key_senderror(so, m, EINVAL); 5329251881Speter } 5330251881Speter if (mhp->ext[SADB_X_EXT_SA2] != NULL) { 5331251881Speter mode = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_mode; 5332251881Speter reqid = ((struct sadb_x_sa2 *)mhp->ext[SADB_X_EXT_SA2])->sadb_x_sa2_reqid; 5333251881Speter } else { 5334251881Speter mode = IPSEC_MODE_ANY; 5335251881Speter reqid = 0; 5336251881Speter } 5337251881Speter 5338251881Speter sa0 = (struct sadb_sa *)mhp->ext[SADB_EXT_SA]; 5339251881Speter src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC]; 5340251881Speter dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST]; 5341251881Speter 5342251881Speter /* XXX boundary check against sa_len */ 5343251881Speter KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx); 5344251881Speter 5345251881Speter /* 5346251881Speter * Make sure the port numbers are zero. 5347251881Speter * In case of NAT-T we will update them later if needed. 5348251881Speter */ 5349251881Speter KEY_PORTTOSADDR(&saidx.src, 0); 5350251881Speter KEY_PORTTOSADDR(&saidx.dst, 0); 5351251881Speter 5352251881Speter#ifdef IPSEC_NAT_T 5353251881Speter /* 5354251881Speter * Handle NAT-T info if present. 5355251881Speter */ 5356251881Speter if (mhp->ext[SADB_X_EXT_NAT_T_TYPE] != NULL && 5357251881Speter mhp->ext[SADB_X_EXT_NAT_T_SPORT] != NULL && 5358251881Speter mhp->ext[SADB_X_EXT_NAT_T_DPORT] != NULL) { 5359251881Speter struct sadb_x_nat_t_port *sport, *dport; 5360251881Speter 5361251881Speter if (mhp->extlen[SADB_X_EXT_NAT_T_TYPE] < sizeof(*type) || 5362251881Speter mhp->extlen[SADB_X_EXT_NAT_T_SPORT] < sizeof(*sport) || 5363251881Speter mhp->extlen[SADB_X_EXT_NAT_T_DPORT] < sizeof(*dport)) { 5364251881Speter ipseclog((LOG_DEBUG, "%s: invalid message.\n", 5365251881Speter __func__)); 5366251881Speter return key_senderror(so, m, EINVAL); 5367251881Speter } 5368251881Speter 5369251881Speter type = (struct sadb_x_nat_t_type *) 5370251881Speter mhp->ext[SADB_X_EXT_NAT_T_TYPE]; 5371251881Speter sport = (struct sadb_x_nat_t_port *) 5372251881Speter mhp->ext[SADB_X_EXT_NAT_T_SPORT]; 5373251881Speter dport = (struct sadb_x_nat_t_port *) 5374251881Speter mhp->ext[SADB_X_EXT_NAT_T_DPORT]; 5375251881Speter 5376251881Speter if (sport) 5377251881Speter KEY_PORTTOSADDR(&saidx.src, 5378251881Speter sport->sadb_x_nat_t_port_port); 5379251881Speter if (dport) 5380251881Speter KEY_PORTTOSADDR(&saidx.dst, 5381251881Speter dport->sadb_x_nat_t_port_port); 5382251881Speter } else { 5383251881Speter type = 0; 5384251881Speter } 5385251881Speter if (mhp->ext[SADB_X_EXT_NAT_T_OAI] != NULL && 5386251881Speter mhp->ext[SADB_X_EXT_NAT_T_OAR] != NULL) { 5387251881Speter if (mhp->extlen[SADB_X_EXT_NAT_T_OAI] < sizeof(*iaddr) || 5388251881Speter mhp->extlen[SADB_X_EXT_NAT_T_OAR] < sizeof(*raddr)) { 5389251881Speter ipseclog((LOG_DEBUG, "%s: invalid message\n", 5390251881Speter __func__)); 5391251881Speter return key_senderror(so, m, EINVAL); 5392251881Speter } 5393251881Speter iaddr = (struct sadb_address *)mhp->ext[SADB_X_EXT_NAT_T_OAI]; 5394251881Speter raddr = (struct sadb_address *)mhp->ext[SADB_X_EXT_NAT_T_OAR]; 5395251881Speter ipseclog((LOG_DEBUG, "%s: NAT-T OAi/r present\n", __func__)); 5396251881Speter } else { 5397251881Speter iaddr = raddr = NULL; 5398251881Speter } 5399251881Speter if (mhp->ext[SADB_X_EXT_NAT_T_FRAG] != NULL) { 5400251881Speter if (mhp->extlen[SADB_X_EXT_NAT_T_FRAG] < sizeof(*frag)) { 5401251881Speter ipseclog((LOG_DEBUG, "%s: invalid message\n", 5402251881Speter __func__)); 5403251881Speter return key_senderror(so, m, EINVAL); 5404251881Speter } 5405251881Speter frag = (struct sadb_x_nat_t_frag *) 5406251881Speter mhp->ext[SADB_X_EXT_NAT_T_FRAG]; 5407251881Speter } else { 5408251881Speter frag = 0; 5409251881Speter } 5410251881Speter#endif 5411251881Speter 5412251881Speter /* get a SA header */ 5413251881Speter if ((newsah = key_getsah(&saidx)) == NULL) { 5414251881Speter /* create a new SA header */ 5415251881Speter if ((newsah = key_newsah(&saidx)) == NULL) { 5416251881Speter ipseclog((LOG_DEBUG, "%s: No more memory.\n",__func__)); 5417251881Speter return key_senderror(so, m, ENOBUFS); 5418251881Speter } 5419251881Speter } 5420251881Speter 5421251881Speter /* set spidx if there */ 5422251881Speter /* XXX rewrite */ 5423251881Speter error = key_setident(newsah, m, mhp); 5424251881Speter if (error) { 5425251881Speter return key_senderror(so, m, error); 5426251881Speter } 5427251881Speter 5428251881Speter /* create new SA entry. */ 5429251881Speter /* We can create new SA only if SPI is differenct. */ 5430251881Speter SAHTREE_LOCK(); 5431251881Speter newsav = key_getsavbyspi(newsah, sa0->sadb_sa_spi); 5432251881Speter SAHTREE_UNLOCK(); 5433251881Speter if (newsav != NULL) { 5434251881Speter ipseclog((LOG_DEBUG, "%s: SA already exists.\n", __func__)); 5435251881Speter return key_senderror(so, m, EEXIST); 5436251881Speter } 5437251881Speter newsav = KEY_NEWSAV(m, mhp, newsah, &error); 5438251881Speter if (newsav == NULL) { 5439251881Speter return key_senderror(so, m, error); 5440251881Speter } 5441251881Speter 5442251881Speter /* check SA values to be mature. */ 5443251881Speter if ((error = key_mature(newsav)) != 0) { 5444251881Speter KEY_FREESAV(&newsav); 5445251881Speter return key_senderror(so, m, error); 5446251881Speter } 5447251881Speter 5448251881Speter#ifdef IPSEC_NAT_T 5449251881Speter /* 5450251881Speter * Handle more NAT-T info if present, 5451251881Speter * now that we have a sav to fill. 5452251881Speter */ 5453251881Speter if (type) 5454251881Speter newsav->natt_type = type->sadb_x_nat_t_type_type; 5455251881Speter 5456251881Speter#if 0 5457251881Speter /* 5458251881Speter * In case SADB_X_EXT_NAT_T_FRAG was not given, leave it at 0. 5459251881Speter * We should actually check for a minimum MTU here, if we 5460251881Speter * want to support it in ip_output. 5461251881Speter */ 5462251881Speter if (frag) 5463251881Speter newsav->natt_esp_frag_len = frag->sadb_x_nat_t_frag_fraglen; 5464251881Speter#endif 5465251881Speter#endif 5466251881Speter 5467251881Speter /* 5468251881Speter * don't call key_freesav() here, as we would like to keep the SA 5469251881Speter * in the database on success. 5470251881Speter */ 5471251881Speter 5472251881Speter { 5473251881Speter struct mbuf *n; 5474251881Speter 5475251881Speter /* set msg buf from mhp */ 5476251881Speter n = key_getmsgbuf_x1(m, mhp); 5477251881Speter if (n == NULL) { 5478251881Speter ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__)); 5479251881Speter return key_senderror(so, m, ENOBUFS); 5480251881Speter } 5481251881Speter 5482251881Speter m_freem(m); 5483251881Speter return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); 5484251881Speter } 5485251881Speter} 5486251881Speter 5487251881Speter/* m is retained */ 5488251881Speterstatic int 5489251881Speterkey_setident(sah, m, mhp) 5490251881Speter struct secashead *sah; 5491251881Speter struct mbuf *m; 5492251881Speter const struct sadb_msghdr *mhp; 5493251881Speter{ 5494251881Speter INIT_VNET_IPSEC(curvnet); 5495251881Speter const struct sadb_ident *idsrc, *iddst; 5496251881Speter int idsrclen, iddstlen; 5497251881Speter 5498251881Speter IPSEC_ASSERT(sah != NULL, ("null secashead")); 5499251881Speter IPSEC_ASSERT(m != NULL, ("null mbuf")); 5500251881Speter IPSEC_ASSERT(mhp != NULL, ("null msghdr")); 5501251881Speter IPSEC_ASSERT(mhp->msg != NULL, ("null msg")); 5502251881Speter 5503251881Speter /* don't make buffer if not there */ 5504251881Speter if (mhp->ext[SADB_EXT_IDENTITY_SRC] == NULL && 5505251881Speter mhp->ext[SADB_EXT_IDENTITY_DST] == NULL) { 5506251881Speter sah->idents = NULL; 5507251881Speter sah->identd = NULL; 5508251881Speter return 0; 5509251881Speter } 5510251881Speter 5511251881Speter if (mhp->ext[SADB_EXT_IDENTITY_SRC] == NULL || 5512251881Speter mhp->ext[SADB_EXT_IDENTITY_DST] == NULL) { 5513251881Speter ipseclog((LOG_DEBUG, "%s: invalid identity.\n", __func__)); 5514251881Speter return EINVAL; 5515251881Speter } 5516251881Speter 5517251881Speter idsrc = (const struct sadb_ident *)mhp->ext[SADB_EXT_IDENTITY_SRC]; 5518251881Speter iddst = (const struct sadb_ident *)mhp->ext[SADB_EXT_IDENTITY_DST]; 5519251881Speter idsrclen = mhp->extlen[SADB_EXT_IDENTITY_SRC]; 5520251881Speter iddstlen = mhp->extlen[SADB_EXT_IDENTITY_DST]; 5521251881Speter 5522251881Speter /* validity check */ 5523251881Speter if (idsrc->sadb_ident_type != iddst->sadb_ident_type) { 5524251881Speter ipseclog((LOG_DEBUG, "%s: ident type mismatch.\n", __func__)); 5525251881Speter return EINVAL; 5526251881Speter } 5527251881Speter 5528251881Speter switch (idsrc->sadb_ident_type) { 5529251881Speter case SADB_IDENTTYPE_PREFIX: 5530251881Speter case SADB_IDENTTYPE_FQDN: 5531251881Speter case SADB_IDENTTYPE_USERFQDN: 5532251881Speter default: 5533251881Speter /* XXX do nothing */ 5534251881Speter sah->idents = NULL; 5535251881Speter sah->identd = NULL; 5536251881Speter return 0; 5537251881Speter } 5538251881Speter 5539251881Speter /* make structure */ 5540251881Speter sah->idents = malloc(sizeof(struct secident), M_IPSEC_MISC, M_NOWAIT); 5541251881Speter if (sah->idents == NULL) { 5542251881Speter ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__)); 5543251881Speter return ENOBUFS; 5544251881Speter } 5545251881Speter sah->identd = malloc(sizeof(struct secident), M_IPSEC_MISC, M_NOWAIT); 5546251881Speter if (sah->identd == NULL) { 5547251881Speter free(sah->idents, M_IPSEC_MISC); 5548251881Speter sah->idents = NULL; 5549251881Speter ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__)); 5550251881Speter return ENOBUFS; 5551251881Speter } 5552251881Speter sah->idents->type = idsrc->sadb_ident_type; 5553251881Speter sah->idents->id = idsrc->sadb_ident_id; 5554251881Speter 5555251881Speter sah->identd->type = iddst->sadb_ident_type; 5556251881Speter sah->identd->id = iddst->sadb_ident_id; 5557251881Speter 5558251881Speter return 0; 5559251881Speter} 5560251881Speter 5561251881Speter/* 5562251881Speter * m will not be freed on return. 5563251881Speter * it is caller's responsibility to free the result. 5564251881Speter */ 5565251881Speterstatic struct mbuf * 5566251881Speterkey_getmsgbuf_x1(m, mhp) 5567251881Speter struct mbuf *m; 5568251881Speter const struct sadb_msghdr *mhp; 5569251881Speter{ 5570251881Speter struct mbuf *n; 5571251881Speter 5572251881Speter IPSEC_ASSERT(m != NULL, ("null mbuf")); 5573251881Speter IPSEC_ASSERT(mhp != NULL, ("null msghdr")); 5574251881Speter IPSEC_ASSERT(mhp->msg != NULL, ("null msg")); 5575251881Speter 5576251881Speter /* create new sadb_msg to reply. */ 5577251881Speter n = key_gather_mbuf(m, mhp, 1, 9, SADB_EXT_RESERVED, 5578251881Speter SADB_EXT_SA, SADB_X_EXT_SA2, 5579251881Speter SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST, 5580251881Speter SADB_EXT_LIFETIME_HARD, SADB_EXT_LIFETIME_SOFT, 5581251881Speter SADB_EXT_IDENTITY_SRC, SADB_EXT_IDENTITY_DST); 5582251881Speter if (!n) 5583251881Speter return NULL; 5584251881Speter 5585251881Speter if (n->m_len < sizeof(struct sadb_msg)) { 5586251881Speter n = m_pullup(n, sizeof(struct sadb_msg)); 5587251881Speter if (n == NULL) 5588251881Speter return NULL; 5589251881Speter } 5590251881Speter mtod(n, struct sadb_msg *)->sadb_msg_errno = 0; 5591251881Speter mtod(n, struct sadb_msg *)->sadb_msg_len = 5592251881Speter PFKEY_UNIT64(n->m_pkthdr.len); 5593251881Speter 5594251881Speter return n; 5595251881Speter} 5596251881Speter 5597251881Speterstatic int key_delete_all __P((struct socket *, struct mbuf *, 5598251881Speter const struct sadb_msghdr *, u_int16_t)); 5599251881Speter 5600251881Speter/* 5601251881Speter * SADB_DELETE processing 5602251881Speter * receive 5603251881Speter * <base, SA(*), address(SD)> 5604251881Speter * from the ikmpd, and set SADB_SASTATE_DEAD, 5605251881Speter * and send, 5606251881Speter * <base, SA(*), address(SD)> 5607251881Speter * to the ikmpd. 5608251881Speter * 5609251881Speter * m will always be freed. 5610251881Speter */ 5611251881Speterstatic int 5612251881Speterkey_delete(so, m, mhp) 5613251881Speter struct socket *so; 5614251881Speter struct mbuf *m; 5615251881Speter const struct sadb_msghdr *mhp; 5616251881Speter{ 5617251881Speter INIT_VNET_IPSEC(curvnet); 5618251881Speter struct sadb_sa *sa0; 5619251881Speter struct sadb_address *src0, *dst0; 5620251881Speter struct secasindex saidx; 5621251881Speter struct secashead *sah; 5622251881Speter struct secasvar *sav = NULL; 5623251881Speter u_int16_t proto; 5624251881Speter 5625251881Speter IPSEC_ASSERT(so != NULL, ("null socket")); 5626251881Speter IPSEC_ASSERT(m != NULL, ("null mbuf")); 5627251881Speter IPSEC_ASSERT(mhp != NULL, ("null msghdr")); 5628251881Speter IPSEC_ASSERT(mhp->msg != NULL, ("null msg")); 5629251881Speter 5630251881Speter /* map satype to proto */ 5631251881Speter if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { 5632251881Speter ipseclog((LOG_DEBUG, "%s: invalid satype is passed.\n", 5633251881Speter __func__)); 5634251881Speter return key_senderror(so, m, EINVAL); 5635251881Speter } 5636251881Speter 5637251881Speter if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || 5638251881Speter mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) { 5639251881Speter ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", 5640251881Speter __func__)); 5641251881Speter return key_senderror(so, m, EINVAL); 5642251881Speter } 5643251881Speter 5644251881Speter if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || 5645251881Speter mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) { 5646251881Speter ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", 5647251881Speter __func__)); 5648251881Speter return key_senderror(so, m, EINVAL); 5649251881Speter } 5650251881Speter 5651251881Speter if (mhp->ext[SADB_EXT_SA] == NULL) { 5652251881Speter /* 5653251881Speter * Caller wants us to delete all non-LARVAL SAs 5654251881Speter * that match the src/dst. This is used during 5655251881Speter * IKE INITIAL-CONTACT. 5656251881Speter */ 5657251881Speter ipseclog((LOG_DEBUG, "%s: doing delete all.\n", __func__)); 5658251881Speter return key_delete_all(so, m, mhp, proto); 5659251881Speter } else if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa)) { 5660251881Speter ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", 5661251881Speter __func__)); 5662251881Speter return key_senderror(so, m, EINVAL); 5663251881Speter } 5664251881Speter 5665251881Speter sa0 = (struct sadb_sa *)mhp->ext[SADB_EXT_SA]; 5666251881Speter src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]); 5667251881Speter dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]); 5668251881Speter 5669251881Speter /* XXX boundary check against sa_len */ 5670251881Speter KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); 5671251881Speter 5672251881Speter /* 5673251881Speter * Make sure the port numbers are zero. 5674251881Speter * In case of NAT-T we will update them later if needed. 5675251881Speter */ 5676251881Speter KEY_PORTTOSADDR(&saidx.src, 0); 5677251881Speter KEY_PORTTOSADDR(&saidx.dst, 0); 5678251881Speter 5679251881Speter#ifdef IPSEC_NAT_T 5680251881Speter /* 5681251881Speter * Handle NAT-T info if present. 5682251881Speter */ 5683251881Speter if (mhp->ext[SADB_X_EXT_NAT_T_SPORT] != NULL && 5684251881Speter mhp->ext[SADB_X_EXT_NAT_T_DPORT] != NULL) { 5685251881Speter struct sadb_x_nat_t_port *sport, *dport; 5686251881Speter 5687251881Speter if (mhp->extlen[SADB_X_EXT_NAT_T_SPORT] < sizeof(*sport) || 5688251881Speter mhp->extlen[SADB_X_EXT_NAT_T_DPORT] < sizeof(*dport)) { 5689251881Speter ipseclog((LOG_DEBUG, "%s: invalid message.\n", 5690251881Speter __func__)); 5691251881Speter return key_senderror(so, m, EINVAL); 5692251881Speter } 5693251881Speter 5694251881Speter sport = (struct sadb_x_nat_t_port *) 5695251881Speter mhp->ext[SADB_X_EXT_NAT_T_SPORT]; 5696251881Speter dport = (struct sadb_x_nat_t_port *) 5697251881Speter mhp->ext[SADB_X_EXT_NAT_T_DPORT]; 5698251881Speter 5699251881Speter if (sport) 5700251881Speter KEY_PORTTOSADDR(&saidx.src, 5701251881Speter sport->sadb_x_nat_t_port_port); 5702251881Speter if (dport) 5703251881Speter KEY_PORTTOSADDR(&saidx.dst, 5704251881Speter dport->sadb_x_nat_t_port_port); 5705251881Speter } 5706251881Speter#endif 5707251881Speter 5708251881Speter /* get a SA header */ 5709251881Speter SAHTREE_LOCK(); 5710251881Speter LIST_FOREACH(sah, &V_sahtree, chain) { 5711251881Speter if (sah->state == SADB_SASTATE_DEAD) 5712251881Speter continue; 5713251881Speter if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0) 5714251881Speter continue; 5715251881Speter 5716251881Speter /* get a SA with SPI. */ 5717251881Speter sav = key_getsavbyspi(sah, sa0->sadb_sa_spi); 5718251881Speter if (sav) 5719251881Speter break; 5720251881Speter } 5721251881Speter if (sah == NULL) { 5722251881Speter SAHTREE_UNLOCK(); 5723251881Speter ipseclog((LOG_DEBUG, "%s: no SA found.\n", __func__)); 5724251881Speter return key_senderror(so, m, ENOENT); 5725251881Speter } 5726251881Speter 5727251881Speter key_sa_chgstate(sav, SADB_SASTATE_DEAD); 5728251881Speter SAHTREE_UNLOCK(); 5729251881Speter KEY_FREESAV(&sav); 5730251881Speter 5731251881Speter { 5732251881Speter struct mbuf *n; 5733251881Speter struct sadb_msg *newmsg; 5734251881Speter 5735251881Speter /* create new sadb_msg to reply. */ 5736251881Speter /* XXX-BZ NAT-T extensions? */ 5737251881Speter n = key_gather_mbuf(m, mhp, 1, 4, SADB_EXT_RESERVED, 5738251881Speter SADB_EXT_SA, SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST); 5739251881Speter if (!n) 5740251881Speter return key_senderror(so, m, ENOBUFS); 5741251881Speter 5742251881Speter if (n->m_len < sizeof(struct sadb_msg)) { 5743251881Speter n = m_pullup(n, sizeof(struct sadb_msg)); 5744251881Speter if (n == NULL) 5745251881Speter return key_senderror(so, m, ENOBUFS); 5746251881Speter } 5747251881Speter newmsg = mtod(n, struct sadb_msg *); 5748251881Speter newmsg->sadb_msg_errno = 0; 5749251881Speter newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); 5750251881Speter 5751251881Speter m_freem(m); 5752251881Speter return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); 5753251881Speter } 5754251881Speter} 5755251881Speter 5756251881Speter/* 5757251881Speter * delete all SAs for src/dst. Called from key_delete(). 5758251881Speter */ 5759251881Speterstatic int 5760251881Speterkey_delete_all(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp, 5761251881Speter u_int16_t proto) 5762251881Speter{ 5763251881Speter INIT_VNET_IPSEC(curvnet); 5764251881Speter struct sadb_address *src0, *dst0; 5765251881Speter struct secasindex saidx; 5766251881Speter struct secashead *sah; 5767251881Speter struct secasvar *sav, *nextsav; 5768251881Speter u_int stateidx, state; 5769251881Speter 5770251881Speter src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]); 5771251881Speter dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]); 5772251881Speter 5773251881Speter /* XXX boundary check against sa_len */ 5774251881Speter KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); 5775251881Speter 5776251881Speter /* 5777251881Speter * Make sure the port numbers are zero. 5778251881Speter * In case of NAT-T we will update them later if needed. 5779251881Speter */ 5780251881Speter KEY_PORTTOSADDR(&saidx.src, 0); 5781251881Speter KEY_PORTTOSADDR(&saidx.dst, 0); 5782251881Speter 5783251881Speter#ifdef IPSEC_NAT_T 5784251881Speter /* 5785251881Speter * Handle NAT-T info if present. 5786251881Speter */ 5787251881Speter 5788251881Speter if (mhp->ext[SADB_X_EXT_NAT_T_SPORT] != NULL && 5789251881Speter mhp->ext[SADB_X_EXT_NAT_T_DPORT] != NULL) { 5790251881Speter struct sadb_x_nat_t_port *sport, *dport; 5791251881Speter 5792251881Speter if (mhp->extlen[SADB_X_EXT_NAT_T_SPORT] < sizeof(*sport) || 5793251881Speter mhp->extlen[SADB_X_EXT_NAT_T_DPORT] < sizeof(*dport)) { 5794251881Speter ipseclog((LOG_DEBUG, "%s: invalid message.\n", 5795251881Speter __func__)); 5796251881Speter return key_senderror(so, m, EINVAL); 5797251881Speter } 5798251881Speter 5799251881Speter sport = (struct sadb_x_nat_t_port *) 5800251881Speter mhp->ext[SADB_X_EXT_NAT_T_SPORT]; 5801251881Speter dport = (struct sadb_x_nat_t_port *) 5802251881Speter mhp->ext[SADB_X_EXT_NAT_T_DPORT]; 5803251881Speter 5804251881Speter if (sport) 5805251881Speter KEY_PORTTOSADDR(&saidx.src, 5806251881Speter sport->sadb_x_nat_t_port_port); 5807251881Speter if (dport) 5808251881Speter KEY_PORTTOSADDR(&saidx.dst, 5809251881Speter dport->sadb_x_nat_t_port_port); 5810251881Speter } 5811251881Speter#endif 5812251881Speter 5813251881Speter SAHTREE_LOCK(); 5814251881Speter LIST_FOREACH(sah, &V_sahtree, chain) { 5815251881Speter if (sah->state == SADB_SASTATE_DEAD) 5816251881Speter continue; 5817251881Speter if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0) 5818251881Speter continue; 5819251881Speter 5820251881Speter /* Delete all non-LARVAL SAs. */ 5821251881Speter for (stateidx = 0; 5822251881Speter stateidx < _ARRAYLEN(saorder_state_alive); 5823251881Speter stateidx++) { 5824251881Speter state = saorder_state_alive[stateidx]; 5825251881Speter if (state == SADB_SASTATE_LARVAL) 5826251881Speter continue; 5827251881Speter for (sav = LIST_FIRST(&sah->savtree[state]); 5828251881Speter sav != NULL; sav = nextsav) { 5829251881Speter nextsav = LIST_NEXT(sav, chain); 5830251881Speter /* sanity check */ 5831251881Speter if (sav->state != state) { 5832251881Speter ipseclog((LOG_DEBUG, "%s: invalid " 5833251881Speter "sav->state (queue %d SA %d)\n", 5834251881Speter __func__, state, sav->state)); 5835251881Speter continue; 5836251881Speter } 5837251881Speter 5838251881Speter key_sa_chgstate(sav, SADB_SASTATE_DEAD); 5839251881Speter KEY_FREESAV(&sav); 5840251881Speter } 5841251881Speter } 5842251881Speter } 5843251881Speter SAHTREE_UNLOCK(); 5844251881Speter { 5845251881Speter struct mbuf *n; 5846251881Speter struct sadb_msg *newmsg; 5847251881Speter 5848251881Speter /* create new sadb_msg to reply. */ 5849251881Speter /* XXX-BZ NAT-T extensions? */ 5850251881Speter n = key_gather_mbuf(m, mhp, 1, 3, SADB_EXT_RESERVED, 5851251881Speter SADB_EXT_ADDRESS_SRC, SADB_EXT_ADDRESS_DST); 5852251881Speter if (!n) 5853251881Speter return key_senderror(so, m, ENOBUFS); 5854251881Speter 5855251881Speter if (n->m_len < sizeof(struct sadb_msg)) { 5856251881Speter n = m_pullup(n, sizeof(struct sadb_msg)); 5857251881Speter if (n == NULL) 5858251881Speter return key_senderror(so, m, ENOBUFS); 5859251881Speter } 5860251881Speter newmsg = mtod(n, struct sadb_msg *); 5861251881Speter newmsg->sadb_msg_errno = 0; 5862251881Speter newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); 5863251881Speter 5864251881Speter m_freem(m); 5865251881Speter return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); 5866251881Speter } 5867251881Speter} 5868251881Speter 5869251881Speter/* 5870251881Speter * SADB_GET processing 5871251881Speter * receive 5872251881Speter * <base, SA(*), address(SD)> 5873251881Speter * from the ikmpd, and get a SP and a SA to respond, 5874251881Speter * and send, 5875251881Speter * <base, SA, (lifetime(HSC),) address(SD), (address(P),) key(AE), 5876251881Speter * (identity(SD),) (sensitivity)> 5877251881Speter * to the ikmpd. 5878251881Speter * 5879251881Speter * m will always be freed. 5880251881Speter */ 5881251881Speterstatic int 5882251881Speterkey_get(so, m, mhp) 5883251881Speter struct socket *so; 5884251881Speter struct mbuf *m; 5885251881Speter const struct sadb_msghdr *mhp; 5886251881Speter{ 5887251881Speter INIT_VNET_IPSEC(curvnet); 5888251881Speter struct sadb_sa *sa0; 5889251881Speter struct sadb_address *src0, *dst0; 5890251881Speter struct secasindex saidx; 5891251881Speter struct secashead *sah; 5892251881Speter struct secasvar *sav = NULL; 5893251881Speter u_int16_t proto; 5894251881Speter 5895251881Speter IPSEC_ASSERT(so != NULL, ("null socket")); 5896251881Speter IPSEC_ASSERT(m != NULL, ("null mbuf")); 5897251881Speter IPSEC_ASSERT(mhp != NULL, ("null msghdr")); 5898251881Speter IPSEC_ASSERT(mhp->msg != NULL, ("null msg")); 5899251881Speter 5900251881Speter /* map satype to proto */ 5901251881Speter if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { 5902251881Speter ipseclog((LOG_DEBUG, "%s: invalid satype is passed.\n", 5903251881Speter __func__)); 5904251881Speter return key_senderror(so, m, EINVAL); 5905251881Speter } 5906251881Speter 5907251881Speter if (mhp->ext[SADB_EXT_SA] == NULL || 5908251881Speter mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || 5909251881Speter mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) { 5910251881Speter ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", 5911251881Speter __func__)); 5912251881Speter return key_senderror(so, m, EINVAL); 5913251881Speter } 5914251881Speter if (mhp->extlen[SADB_EXT_SA] < sizeof(struct sadb_sa) || 5915251881Speter mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || 5916251881Speter mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address)) { 5917251881Speter ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", 5918251881Speter __func__)); 5919251881Speter return key_senderror(so, m, EINVAL); 5920251881Speter } 5921251881Speter 5922251881Speter sa0 = (struct sadb_sa *)mhp->ext[SADB_EXT_SA]; 5923251881Speter src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC]; 5924251881Speter dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST]; 5925251881Speter 5926251881Speter /* XXX boundary check against sa_len */ 5927251881Speter KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); 5928251881Speter 5929251881Speter /* 5930251881Speter * Make sure the port numbers are zero. 5931251881Speter * In case of NAT-T we will update them later if needed. 5932251881Speter */ 5933251881Speter KEY_PORTTOSADDR(&saidx.src, 0); 5934251881Speter KEY_PORTTOSADDR(&saidx.dst, 0); 5935251881Speter 5936251881Speter#ifdef IPSEC_NAT_T 5937251881Speter /* 5938251881Speter * Handle NAT-T info if present. 5939251881Speter */ 5940251881Speter 5941251881Speter if (mhp->ext[SADB_X_EXT_NAT_T_SPORT] != NULL && 5942251881Speter mhp->ext[SADB_X_EXT_NAT_T_DPORT] != NULL) { 5943251881Speter struct sadb_x_nat_t_port *sport, *dport; 5944251881Speter 5945251881Speter if (mhp->extlen[SADB_X_EXT_NAT_T_SPORT] < sizeof(*sport) || 5946251881Speter mhp->extlen[SADB_X_EXT_NAT_T_DPORT] < sizeof(*dport)) { 5947251881Speter ipseclog((LOG_DEBUG, "%s: invalid message.\n", 5948251881Speter __func__)); 5949251881Speter return key_senderror(so, m, EINVAL); 5950251881Speter } 5951251881Speter 5952251881Speter sport = (struct sadb_x_nat_t_port *) 5953251881Speter mhp->ext[SADB_X_EXT_NAT_T_SPORT]; 5954251881Speter dport = (struct sadb_x_nat_t_port *) 5955251881Speter mhp->ext[SADB_X_EXT_NAT_T_DPORT]; 5956251881Speter 5957251881Speter if (sport) 5958251881Speter KEY_PORTTOSADDR(&saidx.src, 5959251881Speter sport->sadb_x_nat_t_port_port); 5960251881Speter if (dport) 5961251881Speter KEY_PORTTOSADDR(&saidx.dst, 5962251881Speter dport->sadb_x_nat_t_port_port); 5963251881Speter } 5964251881Speter#endif 5965251881Speter 5966251881Speter /* get a SA header */ 5967251881Speter SAHTREE_LOCK(); 5968251881Speter LIST_FOREACH(sah, &V_sahtree, chain) { 5969251881Speter if (sah->state == SADB_SASTATE_DEAD) 5970251881Speter continue; 5971251881Speter if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0) 5972251881Speter continue; 5973251881Speter 5974251881Speter /* get a SA with SPI. */ 5975251881Speter sav = key_getsavbyspi(sah, sa0->sadb_sa_spi); 5976251881Speter if (sav) 5977251881Speter break; 5978251881Speter } 5979251881Speter SAHTREE_UNLOCK(); 5980251881Speter if (sah == NULL) { 5981251881Speter ipseclog((LOG_DEBUG, "%s: no SA found.\n", __func__)); 5982251881Speter return key_senderror(so, m, ENOENT); 5983251881Speter } 5984251881Speter 5985251881Speter { 5986251881Speter struct mbuf *n; 5987251881Speter u_int8_t satype; 5988251881Speter 5989251881Speter /* map proto to satype */ 5990251881Speter if ((satype = key_proto2satype(sah->saidx.proto)) == 0) { 5991251881Speter ipseclog((LOG_DEBUG, "%s: there was invalid proto in SAD.\n", 5992251881Speter __func__)); 5993251881Speter return key_senderror(so, m, EINVAL); 5994251881Speter } 5995251881Speter 5996251881Speter /* create new sadb_msg to reply. */ 5997251881Speter n = key_setdumpsa(sav, SADB_GET, satype, mhp->msg->sadb_msg_seq, 5998251881Speter mhp->msg->sadb_msg_pid); 5999251881Speter if (!n) 6000251881Speter return key_senderror(so, m, ENOBUFS); 6001251881Speter 6002251881Speter m_freem(m); 6003251881Speter return key_sendup_mbuf(so, n, KEY_SENDUP_ONE); 6004251881Speter } 6005251881Speter} 6006251881Speter 6007251881Speter/* XXX make it sysctl-configurable? */ 6008251881Speterstatic void 6009251881Speterkey_getcomb_setlifetime(comb) 6010251881Speter struct sadb_comb *comb; 6011251881Speter{ 6012251881Speter 6013251881Speter comb->sadb_comb_soft_allocations = 1; 6014251881Speter comb->sadb_comb_hard_allocations = 1; 6015251881Speter comb->sadb_comb_soft_bytes = 0; 6016251881Speter comb->sadb_comb_hard_bytes = 0; 6017251881Speter comb->sadb_comb_hard_addtime = 86400; /* 1 day */ 6018251881Speter comb->sadb_comb_soft_addtime = comb->sadb_comb_soft_addtime * 80 / 100; 6019251881Speter comb->sadb_comb_soft_usetime = 28800; /* 8 hours */ 6020251881Speter comb->sadb_comb_hard_usetime = comb->sadb_comb_hard_usetime * 80 / 100; 6021251881Speter} 6022251881Speter 6023251881Speter/* 6024251881Speter * XXX reorder combinations by preference 6025251881Speter * XXX no idea if the user wants ESP authentication or not 6026251881Speter */ 6027251881Speterstatic struct mbuf * 6028251881Speterkey_getcomb_esp() 6029251881Speter{ 6030251881Speter INIT_VNET_IPSEC(curvnet); 6031251881Speter struct sadb_comb *comb; 6032251881Speter struct enc_xform *algo; 6033251881Speter struct mbuf *result = NULL, *m, *n; 6034251881Speter int encmin; 6035251881Speter int i, off, o; 6036251881Speter int totlen; 6037251881Speter const int l = PFKEY_ALIGN8(sizeof(struct sadb_comb)); 6038251881Speter 6039251881Speter m = NULL; 6040251881Speter for (i = 1; i <= SADB_EALG_MAX; i++) { 6041251881Speter algo = esp_algorithm_lookup(i); 6042251881Speter if (algo == NULL) 6043251881Speter continue; 6044251881Speter 6045251881Speter /* discard algorithms with key size smaller than system min */ 6046251881Speter if (_BITS(algo->maxkey) < V_ipsec_esp_keymin) 6047251881Speter continue; 6048251881Speter if (_BITS(algo->minkey) < V_ipsec_esp_keymin) 6049251881Speter encmin = V_ipsec_esp_keymin; 6050251881Speter else 6051251881Speter encmin = _BITS(algo->minkey); 6052251881Speter 6053251881Speter if (V_ipsec_esp_auth) 6054251881Speter m = key_getcomb_ah(); 6055251881Speter else { 6056251881Speter IPSEC_ASSERT(l <= MLEN, 6057251881Speter ("l=%u > MLEN=%lu", l, (u_long) MLEN)); 6058251881Speter MGET(m, M_DONTWAIT, MT_DATA); 6059251881Speter if (m) { 6060251881Speter M_ALIGN(m, l); 6061251881Speter m->m_len = l; 6062251881Speter m->m_next = NULL; 6063251881Speter bzero(mtod(m, caddr_t), m->m_len); 6064251881Speter } 6065251881Speter } 6066251881Speter if (!m) 6067251881Speter goto fail; 6068251881Speter 6069251881Speter totlen = 0; 6070251881Speter for (n = m; n; n = n->m_next) 6071251881Speter totlen += n->m_len; 6072251881Speter IPSEC_ASSERT((totlen % l) == 0, ("totlen=%u, l=%u", totlen, l)); 6073251881Speter 6074251881Speter for (off = 0; off < totlen; off += l) { 6075251881Speter n = m_pulldown(m, off, l, &o); 6076251881Speter if (!n) { 6077251881Speter /* m is already freed */ 6078251881Speter goto fail; 6079251881Speter } 6080251881Speter comb = (struct sadb_comb *)(mtod(n, caddr_t) + o); 6081251881Speter bzero(comb, sizeof(*comb)); 6082251881Speter key_getcomb_setlifetime(comb); 6083251881Speter comb->sadb_comb_encrypt = i; 6084251881Speter comb->sadb_comb_encrypt_minbits = encmin; 6085251881Speter comb->sadb_comb_encrypt_maxbits = _BITS(algo->maxkey); 6086251881Speter } 6087251881Speter 6088251881Speter if (!result) 6089251881Speter result = m; 6090251881Speter else 6091251881Speter m_cat(result, m); 6092251881Speter } 6093251881Speter 6094251881Speter return result; 6095251881Speter 6096251881Speter fail: 6097251881Speter if (result) 6098251881Speter m_freem(result); 6099251881Speter return NULL; 6100251881Speter} 6101251881Speter 6102251881Speterstatic void 6103251881Speterkey_getsizes_ah( 6104251881Speter const struct auth_hash *ah, 6105251881Speter int alg, 6106251881Speter u_int16_t* min, 6107251881Speter u_int16_t* max) 6108251881Speter{ 6109251881Speter INIT_VNET_IPSEC(curvnet); 6110251881Speter 6111251881Speter *min = *max = ah->keysize; 6112251881Speter if (ah->keysize == 0) { 6113251881Speter /* 6114251881Speter * Transform takes arbitrary key size but algorithm 6115251881Speter * key size is restricted. Enforce this here. 6116251881Speter */ 6117251881Speter switch (alg) { 6118251881Speter case SADB_X_AALG_MD5: *min = *max = 16; break; 6119251881Speter case SADB_X_AALG_SHA: *min = *max = 20; break; 6120251881Speter case SADB_X_AALG_NULL: *min = 1; *max = 256; break; 6121251881Speter default: 6122251881Speter DPRINTF(("%s: unknown AH algorithm %u\n", 6123251881Speter __func__, alg)); 6124251881Speter break; 6125251881Speter } 6126251881Speter } 6127251881Speter} 6128251881Speter 6129251881Speter/* 6130251881Speter * XXX reorder combinations by preference 6131251881Speter */ 6132251881Speterstatic struct mbuf * 6133251881Speterkey_getcomb_ah() 6134251881Speter{ 6135251881Speter INIT_VNET_IPSEC(curvnet); 6136251881Speter struct sadb_comb *comb; 6137251881Speter struct auth_hash *algo; 6138251881Speter struct mbuf *m; 6139251881Speter u_int16_t minkeysize, maxkeysize; 6140251881Speter int i; 6141251881Speter const int l = PFKEY_ALIGN8(sizeof(struct sadb_comb)); 6142251881Speter 6143251881Speter m = NULL; 6144251881Speter for (i = 1; i <= SADB_AALG_MAX; i++) { 6145251881Speter#if 1 6146251881Speter /* we prefer HMAC algorithms, not old algorithms */ 6147251881Speter if (i != SADB_AALG_SHA1HMAC && i != SADB_AALG_MD5HMAC) 6148251881Speter continue; 6149251881Speter#endif 6150251881Speter algo = ah_algorithm_lookup(i); 6151251881Speter if (!algo) 6152251881Speter continue; 6153251881Speter key_getsizes_ah(algo, i, &minkeysize, &maxkeysize); 6154251881Speter /* discard algorithms with key size smaller than system min */ 6155251881Speter if (_BITS(minkeysize) < V_ipsec_ah_keymin) 6156251881Speter continue; 6157251881Speter 6158251881Speter if (!m) { 6159251881Speter IPSEC_ASSERT(l <= MLEN, 6160251881Speter ("l=%u > MLEN=%lu", l, (u_long) MLEN)); 6161251881Speter MGET(m, M_DONTWAIT, MT_DATA); 6162251881Speter if (m) { 6163251881Speter M_ALIGN(m, l); 6164251881Speter m->m_len = l; 6165251881Speter m->m_next = NULL; 6166251881Speter } 6167251881Speter } else 6168251881Speter M_PREPEND(m, l, M_DONTWAIT); 6169251881Speter if (!m) 6170251881Speter return NULL; 6171251881Speter 6172251881Speter comb = mtod(m, struct sadb_comb *); 6173251881Speter bzero(comb, sizeof(*comb)); 6174251881Speter key_getcomb_setlifetime(comb); 6175251881Speter comb->sadb_comb_auth = i; 6176251881Speter comb->sadb_comb_auth_minbits = _BITS(minkeysize); 6177251881Speter comb->sadb_comb_auth_maxbits = _BITS(maxkeysize); 6178251881Speter } 6179251881Speter 6180251881Speter return m; 6181251881Speter} 6182251881Speter 6183251881Speter/* 6184251881Speter * not really an official behavior. discussed in pf_key@inner.net in Sep2000. 6185251881Speter * XXX reorder combinations by preference 6186251881Speter */ 6187251881Speterstatic struct mbuf * 6188251881Speterkey_getcomb_ipcomp() 6189251881Speter{ 6190251881Speter struct sadb_comb *comb; 6191251881Speter struct comp_algo *algo; 6192251881Speter struct mbuf *m; 6193251881Speter int i; 6194251881Speter const int l = PFKEY_ALIGN8(sizeof(struct sadb_comb)); 6195251881Speter 6196251881Speter m = NULL; 6197251881Speter for (i = 1; i <= SADB_X_CALG_MAX; i++) { 6198251881Speter algo = ipcomp_algorithm_lookup(i); 6199251881Speter if (!algo) 6200251881Speter continue; 6201251881Speter 6202251881Speter if (!m) { 6203251881Speter IPSEC_ASSERT(l <= MLEN, 6204251881Speter ("l=%u > MLEN=%lu", l, (u_long) MLEN)); 6205251881Speter MGET(m, M_DONTWAIT, MT_DATA); 6206251881Speter if (m) { 6207251881Speter M_ALIGN(m, l); 6208251881Speter m->m_len = l; 6209251881Speter m->m_next = NULL; 6210251881Speter } 6211251881Speter } else 6212251881Speter M_PREPEND(m, l, M_DONTWAIT); 6213251881Speter if (!m) 6214251881Speter return NULL; 6215251881Speter 6216251881Speter comb = mtod(m, struct sadb_comb *); 6217251881Speter bzero(comb, sizeof(*comb)); 6218251881Speter key_getcomb_setlifetime(comb); 6219251881Speter comb->sadb_comb_encrypt = i; 6220251881Speter /* what should we set into sadb_comb_*_{min,max}bits? */ 6221251881Speter } 6222251881Speter 6223251881Speter return m; 6224251881Speter} 6225251881Speter 6226251881Speter/* 6227251881Speter * XXX no way to pass mode (transport/tunnel) to userland 6228251881Speter * XXX replay checking? 6229251881Speter * XXX sysctl interface to ipsec_{ah,esp}_keymin 6230251881Speter */ 6231251881Speterstatic struct mbuf * 6232251881Speterkey_getprop(saidx) 6233251881Speter const struct secasindex *saidx; 6234251881Speter{ 6235251881Speter struct sadb_prop *prop; 6236251881Speter struct mbuf *m, *n; 6237251881Speter const int l = PFKEY_ALIGN8(sizeof(struct sadb_prop)); 6238251881Speter int totlen; 6239251881Speter 6240251881Speter switch (saidx->proto) { 6241251881Speter case IPPROTO_ESP: 6242251881Speter m = key_getcomb_esp(); 6243251881Speter break; 6244251881Speter case IPPROTO_AH: 6245251881Speter m = key_getcomb_ah(); 6246251881Speter break; 6247251881Speter case IPPROTO_IPCOMP: 6248251881Speter m = key_getcomb_ipcomp(); 6249251881Speter break; 6250251881Speter default: 6251251881Speter return NULL; 6252251881Speter } 6253251881Speter 6254251881Speter if (!m) 6255251881Speter return NULL; 6256251881Speter M_PREPEND(m, l, M_DONTWAIT); 6257251881Speter if (!m) 6258251881Speter return NULL; 6259251881Speter 6260251881Speter totlen = 0; 6261251881Speter for (n = m; n; n = n->m_next) 6262251881Speter totlen += n->m_len; 6263251881Speter 6264251881Speter prop = mtod(m, struct sadb_prop *); 6265251881Speter bzero(prop, sizeof(*prop)); 6266251881Speter prop->sadb_prop_len = PFKEY_UNIT64(totlen); 6267251881Speter prop->sadb_prop_exttype = SADB_EXT_PROPOSAL; 6268251881Speter prop->sadb_prop_replay = 32; /* XXX */ 6269251881Speter 6270251881Speter return m; 6271251881Speter} 6272251881Speter 6273251881Speter/* 6274251881Speter * SADB_ACQUIRE processing called by key_checkrequest() and key_acquire2(). 6275251881Speter * send 6276251881Speter * <base, SA, address(SD), (address(P)), x_policy, 6277251881Speter * (identity(SD),) (sensitivity,) proposal> 6278251881Speter * to KMD, and expect to receive 6279251881Speter * <base> with SADB_ACQUIRE if error occured, 6280251881Speter * or 6281251881Speter * <base, src address, dst address, (SPI range)> with SADB_GETSPI 6282251881Speter * from KMD by PF_KEY. 6283251881Speter * 6284251881Speter * XXX x_policy is outside of RFC2367 (KAME extension). 6285251881Speter * XXX sensitivity is not supported. 6286251881Speter * XXX for ipcomp, RFC2367 does not define how to fill in proposal. 6287251881Speter * see comment for key_getcomb_ipcomp(). 6288251881Speter * 6289251881Speter * OUT: 6290251881Speter * 0 : succeed 6291251881Speter * others: error number 6292251881Speter */ 6293251881Speterstatic int 6294251881Speterkey_acquire(const struct secasindex *saidx, struct secpolicy *sp) 6295251881Speter{ 6296251881Speter INIT_VNET_IPSEC(curvnet); 6297251881Speter struct mbuf *result = NULL, *m; 6298251881Speter struct secacq *newacq; 6299251881Speter u_int8_t satype; 6300251881Speter int error = -1; 6301251881Speter u_int32_t seq; 6302251881Speter 6303251881Speter IPSEC_ASSERT(saidx != NULL, ("null saidx")); 6304251881Speter satype = key_proto2satype(saidx->proto); 6305251881Speter IPSEC_ASSERT(satype != 0, ("null satype, protocol %u", saidx->proto)); 6306251881Speter 6307251881Speter /* 6308251881Speter * We never do anything about acquirng SA. There is anather 6309251881Speter * solution that kernel blocks to send SADB_ACQUIRE message until 6310251881Speter * getting something message from IKEd. In later case, to be 6311251881Speter * managed with ACQUIRING list. 6312251881Speter */ 6313251881Speter /* Get an entry to check whether sending message or not. */ 6314251881Speter if ((newacq = key_getacq(saidx)) != NULL) { 6315251881Speter if (V_key_blockacq_count < newacq->count) { 6316251881Speter /* reset counter and do send message. */ 6317251881Speter newacq->count = 0; 6318251881Speter } else { 6319251881Speter /* increment counter and do nothing. */ 6320251881Speter newacq->count++; 6321251881Speter return 0; 6322251881Speter } 6323251881Speter } else { 6324251881Speter /* make new entry for blocking to send SADB_ACQUIRE. */ 6325251881Speter if ((newacq = key_newacq(saidx)) == NULL) 6326251881Speter return ENOBUFS; 6327251881Speter } 6328251881Speter 6329251881Speter 6330251881Speter seq = newacq->seq; 6331251881Speter m = key_setsadbmsg(SADB_ACQUIRE, 0, satype, seq, 0, 0); 6332251881Speter if (!m) { 6333251881Speter error = ENOBUFS; 6334251881Speter goto fail; 6335251881Speter } 6336251881Speter result = m; 6337251881Speter 6338251881Speter /* 6339251881Speter * No SADB_X_EXT_NAT_T_* here: we do not know 6340251881Speter * anything related to NAT-T at this time. 6341251881Speter */ 6342251881Speter 6343251881Speter /* set sadb_address for saidx's. */ 6344251881Speter m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, 6345251881Speter &saidx->src.sa, FULLMASK, IPSEC_ULPROTO_ANY); 6346251881Speter if (!m) { 6347251881Speter error = ENOBUFS; 6348251881Speter goto fail; 6349251881Speter } 6350251881Speter m_cat(result, m); 6351251881Speter 6352251881Speter m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, 6353251881Speter &saidx->dst.sa, FULLMASK, IPSEC_ULPROTO_ANY); 6354251881Speter if (!m) { 6355251881Speter error = ENOBUFS; 6356251881Speter goto fail; 6357251881Speter } 6358251881Speter m_cat(result, m); 6359251881Speter 6360251881Speter /* XXX proxy address (optional) */ 6361251881Speter 6362251881Speter /* set sadb_x_policy */ 6363251881Speter if (sp) { 6364251881Speter m = key_setsadbxpolicy(sp->policy, sp->spidx.dir, sp->id); 6365251881Speter if (!m) { 6366251881Speter error = ENOBUFS; 6367251881Speter goto fail; 6368251881Speter } 6369251881Speter m_cat(result, m); 6370251881Speter } 6371251881Speter 6372251881Speter /* XXX identity (optional) */ 6373251881Speter#if 0 6374251881Speter if (idexttype && fqdn) { 6375251881Speter /* create identity extension (FQDN) */ 6376251881Speter struct sadb_ident *id; 6377251881Speter int fqdnlen; 6378251881Speter 6379251881Speter fqdnlen = strlen(fqdn) + 1; /* +1 for terminating-NUL */ 6380251881Speter id = (struct sadb_ident *)p; 6381251881Speter bzero(id, sizeof(*id) + PFKEY_ALIGN8(fqdnlen)); 6382251881Speter id->sadb_ident_len = PFKEY_UNIT64(sizeof(*id) + PFKEY_ALIGN8(fqdnlen)); 6383251881Speter id->sadb_ident_exttype = idexttype; 6384251881Speter id->sadb_ident_type = SADB_IDENTTYPE_FQDN; 6385251881Speter bcopy(fqdn, id + 1, fqdnlen); 6386251881Speter p += sizeof(struct sadb_ident) + PFKEY_ALIGN8(fqdnlen); 6387251881Speter } 6388251881Speter 6389251881Speter if (idexttype) { 6390251881Speter /* create identity extension (USERFQDN) */ 6391251881Speter struct sadb_ident *id; 6392251881Speter int userfqdnlen; 6393251881Speter 6394251881Speter if (userfqdn) { 6395251881Speter /* +1 for terminating-NUL */ 6396251881Speter userfqdnlen = strlen(userfqdn) + 1; 6397251881Speter } else 6398251881Speter userfqdnlen = 0; 6399251881Speter id = (struct sadb_ident *)p; 6400251881Speter bzero(id, sizeof(*id) + PFKEY_ALIGN8(userfqdnlen)); 6401251881Speter id->sadb_ident_len = PFKEY_UNIT64(sizeof(*id) + PFKEY_ALIGN8(userfqdnlen)); 6402251881Speter id->sadb_ident_exttype = idexttype; 6403251881Speter id->sadb_ident_type = SADB_IDENTTYPE_USERFQDN; 6404251881Speter /* XXX is it correct? */ 6405251881Speter if (curproc && curproc->p_cred) 6406251881Speter id->sadb_ident_id = curproc->p_cred->p_ruid; 6407251881Speter if (userfqdn && userfqdnlen) 6408251881Speter bcopy(userfqdn, id + 1, userfqdnlen); 6409251881Speter p += sizeof(struct sadb_ident) + PFKEY_ALIGN8(userfqdnlen); 6410251881Speter } 6411251881Speter#endif 6412251881Speter 6413251881Speter /* XXX sensitivity (optional) */ 6414251881Speter 6415251881Speter /* create proposal/combination extension */ 6416251881Speter m = key_getprop(saidx); 6417251881Speter#if 0 6418251881Speter /* 6419251881Speter * spec conformant: always attach proposal/combination extension, 6420251881Speter * the problem is that we have no way to attach it for ipcomp, 6421251881Speter * due to the way sadb_comb is declared in RFC2367. 6422251881Speter */ 6423251881Speter if (!m) { 6424251881Speter error = ENOBUFS; 6425251881Speter goto fail; 6426251881Speter } 6427251881Speter m_cat(result, m); 6428251881Speter#else 6429251881Speter /* 6430251881Speter * outside of spec; make proposal/combination extension optional. 6431251881Speter */ 6432251881Speter if (m) 6433251881Speter m_cat(result, m); 6434251881Speter#endif 6435251881Speter 6436251881Speter if ((result->m_flags & M_PKTHDR) == 0) { 6437251881Speter error = EINVAL; 6438251881Speter goto fail; 6439251881Speter } 6440251881Speter 6441251881Speter if (result->m_len < sizeof(struct sadb_msg)) { 6442251881Speter result = m_pullup(result, sizeof(struct sadb_msg)); 6443251881Speter if (result == NULL) { 6444251881Speter error = ENOBUFS; 6445251881Speter goto fail; 6446251881Speter } 6447251881Speter } 6448251881Speter 6449251881Speter result->m_pkthdr.len = 0; 6450251881Speter for (m = result; m; m = m->m_next) 6451251881Speter result->m_pkthdr.len += m->m_len; 6452251881Speter 6453251881Speter mtod(result, struct sadb_msg *)->sadb_msg_len = 6454251881Speter PFKEY_UNIT64(result->m_pkthdr.len); 6455251881Speter 6456251881Speter return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED); 6457251881Speter 6458251881Speter fail: 6459251881Speter if (result) 6460251881Speter m_freem(result); 6461251881Speter return error; 6462251881Speter} 6463251881Speter 6464251881Speterstatic struct secacq * 6465251881Speterkey_newacq(const struct secasindex *saidx) 6466251881Speter{ 6467251881Speter INIT_VNET_IPSEC(curvnet); 6468251881Speter struct secacq *newacq; 6469251881Speter 6470251881Speter /* get new entry */ 6471251881Speter newacq = malloc(sizeof(struct secacq), M_IPSEC_SAQ, M_NOWAIT|M_ZERO); 6472251881Speter if (newacq == NULL) { 6473251881Speter ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__)); 6474251881Speter return NULL; 6475251881Speter } 6476 6477 /* copy secindex */ 6478 bcopy(saidx, &newacq->saidx, sizeof(newacq->saidx)); 6479 newacq->seq = (V_acq_seq == ~0 ? 1 : ++V_acq_seq); 6480 newacq->created = time_second; 6481 newacq->count = 0; 6482 6483 /* add to acqtree */ 6484 ACQ_LOCK(); 6485 LIST_INSERT_HEAD(&V_acqtree, newacq, chain); 6486 ACQ_UNLOCK(); 6487 6488 return newacq; 6489} 6490 6491static struct secacq * 6492key_getacq(const struct secasindex *saidx) 6493{ 6494 INIT_VNET_IPSEC(curvnet); 6495 struct secacq *acq; 6496 6497 ACQ_LOCK(); 6498 LIST_FOREACH(acq, &V_acqtree, chain) { 6499 if (key_cmpsaidx(saidx, &acq->saidx, CMP_EXACTLY)) 6500 break; 6501 } 6502 ACQ_UNLOCK(); 6503 6504 return acq; 6505} 6506 6507static struct secacq * 6508key_getacqbyseq(seq) 6509 u_int32_t seq; 6510{ 6511 INIT_VNET_IPSEC(curvnet); 6512 struct secacq *acq; 6513 6514 ACQ_LOCK(); 6515 LIST_FOREACH(acq, &V_acqtree, chain) { 6516 if (acq->seq == seq) 6517 break; 6518 } 6519 ACQ_UNLOCK(); 6520 6521 return acq; 6522} 6523 6524static struct secspacq * 6525key_newspacq(spidx) 6526 struct secpolicyindex *spidx; 6527{ 6528 INIT_VNET_IPSEC(curvnet); 6529 struct secspacq *acq; 6530 6531 /* get new entry */ 6532 acq = malloc(sizeof(struct secspacq), M_IPSEC_SAQ, M_NOWAIT|M_ZERO); 6533 if (acq == NULL) { 6534 ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__)); 6535 return NULL; 6536 } 6537 6538 /* copy secindex */ 6539 bcopy(spidx, &acq->spidx, sizeof(acq->spidx)); 6540 acq->created = time_second; 6541 acq->count = 0; 6542 6543 /* add to spacqtree */ 6544 SPACQ_LOCK(); 6545 LIST_INSERT_HEAD(&V_spacqtree, acq, chain); 6546 SPACQ_UNLOCK(); 6547 6548 return acq; 6549} 6550 6551static struct secspacq * 6552key_getspacq(spidx) 6553 struct secpolicyindex *spidx; 6554{ 6555 INIT_VNET_IPSEC(curvnet); 6556 struct secspacq *acq; 6557 6558 SPACQ_LOCK(); 6559 LIST_FOREACH(acq, &V_spacqtree, chain) { 6560 if (key_cmpspidx_exactly(spidx, &acq->spidx)) { 6561 /* NB: return holding spacq_lock */ 6562 return acq; 6563 } 6564 } 6565 SPACQ_UNLOCK(); 6566 6567 return NULL; 6568} 6569 6570/* 6571 * SADB_ACQUIRE processing, 6572 * in first situation, is receiving 6573 * <base> 6574 * from the ikmpd, and clear sequence of its secasvar entry. 6575 * 6576 * In second situation, is receiving 6577 * <base, address(SD), (address(P),) (identity(SD),) (sensitivity,) proposal> 6578 * from a user land process, and return 6579 * <base, address(SD), (address(P),) (identity(SD),) (sensitivity,) proposal> 6580 * to the socket. 6581 * 6582 * m will always be freed. 6583 */ 6584static int 6585key_acquire2(so, m, mhp) 6586 struct socket *so; 6587 struct mbuf *m; 6588 const struct sadb_msghdr *mhp; 6589{ 6590 INIT_VNET_IPSEC(curvnet); 6591 const struct sadb_address *src0, *dst0; 6592 struct secasindex saidx; 6593 struct secashead *sah; 6594 u_int16_t proto; 6595 int error; 6596 6597 IPSEC_ASSERT(so != NULL, ("null socket")); 6598 IPSEC_ASSERT(m != NULL, ("null mbuf")); 6599 IPSEC_ASSERT(mhp != NULL, ("null msghdr")); 6600 IPSEC_ASSERT(mhp->msg != NULL, ("null msg")); 6601 6602 /* 6603 * Error message from KMd. 6604 * We assume that if error was occured in IKEd, the length of PFKEY 6605 * message is equal to the size of sadb_msg structure. 6606 * We do not raise error even if error occured in this function. 6607 */ 6608 if (mhp->msg->sadb_msg_len == PFKEY_UNIT64(sizeof(struct sadb_msg))) { 6609 struct secacq *acq; 6610 6611 /* check sequence number */ 6612 if (mhp->msg->sadb_msg_seq == 0) { 6613 ipseclog((LOG_DEBUG, "%s: must specify sequence " 6614 "number.\n", __func__)); 6615 m_freem(m); 6616 return 0; 6617 } 6618 6619 if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq)) == NULL) { 6620 /* 6621 * the specified larval SA is already gone, or we got 6622 * a bogus sequence number. we can silently ignore it. 6623 */ 6624 m_freem(m); 6625 return 0; 6626 } 6627 6628 /* reset acq counter in order to deletion by timehander. */ 6629 acq->created = time_second; 6630 acq->count = 0; 6631 m_freem(m); 6632 return 0; 6633 } 6634 6635 /* 6636 * This message is from user land. 6637 */ 6638 6639 /* map satype to proto */ 6640 if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { 6641 ipseclog((LOG_DEBUG, "%s: invalid satype is passed.\n", 6642 __func__)); 6643 return key_senderror(so, m, EINVAL); 6644 } 6645 6646 if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || 6647 mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || 6648 mhp->ext[SADB_EXT_PROPOSAL] == NULL) { 6649 /* error */ 6650 ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", 6651 __func__)); 6652 return key_senderror(so, m, EINVAL); 6653 } 6654 if (mhp->extlen[SADB_EXT_ADDRESS_SRC] < sizeof(struct sadb_address) || 6655 mhp->extlen[SADB_EXT_ADDRESS_DST] < sizeof(struct sadb_address) || 6656 mhp->extlen[SADB_EXT_PROPOSAL] < sizeof(struct sadb_prop)) { 6657 /* error */ 6658 ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", 6659 __func__)); 6660 return key_senderror(so, m, EINVAL); 6661 } 6662 6663 src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC]; 6664 dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST]; 6665 6666 /* XXX boundary check against sa_len */ 6667 KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); 6668 6669 /* 6670 * Make sure the port numbers are zero. 6671 * In case of NAT-T we will update them later if needed. 6672 */ 6673 KEY_PORTTOSADDR(&saidx.src, 0); 6674 KEY_PORTTOSADDR(&saidx.dst, 0); 6675 6676#ifndef IPSEC_NAT_T 6677 /* 6678 * Handle NAT-T info if present. 6679 */ 6680 6681 if (mhp->ext[SADB_X_EXT_NAT_T_SPORT] != NULL && 6682 mhp->ext[SADB_X_EXT_NAT_T_DPORT] != NULL) { 6683 struct sadb_x_nat_t_port *sport, *dport; 6684 6685 if (mhp->extlen[SADB_X_EXT_NAT_T_SPORT] < sizeof(*sport) || 6686 mhp->extlen[SADB_X_EXT_NAT_T_DPORT] < sizeof(*dport)) { 6687 ipseclog((LOG_DEBUG, "%s: invalid message.\n", 6688 __func__)); 6689 return key_senderror(so, m, EINVAL); 6690 } 6691 6692 sport = (struct sadb_x_nat_t_port *) 6693 mhp->ext[SADB_X_EXT_NAT_T_SPORT]; 6694 dport = (struct sadb_x_nat_t_port *) 6695 mhp->ext[SADB_X_EXT_NAT_T_DPORT]; 6696 6697 if (sport) 6698 KEY_PORTTOSADDR(&saidx.src, 6699 sport->sadb_x_nat_t_port_port); 6700 if (dport) 6701 KEY_PORTTOSADDR(&saidx.dst, 6702 dport->sadb_x_nat_t_port_port); 6703 } 6704#endif 6705 6706 /* get a SA index */ 6707 SAHTREE_LOCK(); 6708 LIST_FOREACH(sah, &V_sahtree, chain) { 6709 if (sah->state == SADB_SASTATE_DEAD) 6710 continue; 6711 if (key_cmpsaidx(&sah->saidx, &saidx, CMP_MODE_REQID)) 6712 break; 6713 } 6714 SAHTREE_UNLOCK(); 6715 if (sah != NULL) { 6716 ipseclog((LOG_DEBUG, "%s: a SA exists already.\n", __func__)); 6717 return key_senderror(so, m, EEXIST); 6718 } 6719 6720 error = key_acquire(&saidx, NULL); 6721 if (error != 0) { 6722 ipseclog((LOG_DEBUG, "%s: error %d returned from key_acquire\n", 6723 __func__, mhp->msg->sadb_msg_errno)); 6724 return key_senderror(so, m, error); 6725 } 6726 6727 return key_sendup_mbuf(so, m, KEY_SENDUP_REGISTERED); 6728} 6729 6730/* 6731 * SADB_REGISTER processing. 6732 * If SATYPE_UNSPEC has been passed as satype, only return sabd_supported. 6733 * receive 6734 * <base> 6735 * from the ikmpd, and register a socket to send PF_KEY messages, 6736 * and send 6737 * <base, supported> 6738 * to KMD by PF_KEY. 6739 * If socket is detached, must free from regnode. 6740 * 6741 * m will always be freed. 6742 */ 6743static int 6744key_register(so, m, mhp) 6745 struct socket *so; 6746 struct mbuf *m; 6747 const struct sadb_msghdr *mhp; 6748{ 6749 INIT_VNET_IPSEC(curvnet); 6750 struct secreg *reg, *newreg = 0; 6751 6752 IPSEC_ASSERT(so != NULL, ("null socket")); 6753 IPSEC_ASSERT(m != NULL, ("null mbuf")); 6754 IPSEC_ASSERT(mhp != NULL, ("null msghdr")); 6755 IPSEC_ASSERT(mhp->msg != NULL, ("null msg")); 6756 6757 /* check for invalid register message */ 6758 if (mhp->msg->sadb_msg_satype >= sizeof(V_regtree)/sizeof(V_regtree[0])) 6759 return key_senderror(so, m, EINVAL); 6760 6761 /* When SATYPE_UNSPEC is specified, only return sabd_supported. */ 6762 if (mhp->msg->sadb_msg_satype == SADB_SATYPE_UNSPEC) 6763 goto setmsg; 6764 6765 /* check whether existing or not */ 6766 REGTREE_LOCK(); 6767 LIST_FOREACH(reg, &V_regtree[mhp->msg->sadb_msg_satype], chain) { 6768 if (reg->so == so) { 6769 REGTREE_UNLOCK(); 6770 ipseclog((LOG_DEBUG, "%s: socket exists already.\n", 6771 __func__)); 6772 return key_senderror(so, m, EEXIST); 6773 } 6774 } 6775 6776 /* create regnode */ 6777 newreg = malloc(sizeof(struct secreg), M_IPSEC_SAR, M_NOWAIT|M_ZERO); 6778 if (newreg == NULL) { 6779 REGTREE_UNLOCK(); 6780 ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__)); 6781 return key_senderror(so, m, ENOBUFS); 6782 } 6783 6784 newreg->so = so; 6785 ((struct keycb *)sotorawcb(so))->kp_registered++; 6786 6787 /* add regnode to regtree. */ 6788 LIST_INSERT_HEAD(&V_regtree[mhp->msg->sadb_msg_satype], newreg, chain); 6789 REGTREE_UNLOCK(); 6790 6791 setmsg: 6792 { 6793 struct mbuf *n; 6794 struct sadb_msg *newmsg; 6795 struct sadb_supported *sup; 6796 u_int len, alen, elen; 6797 int off; 6798 int i; 6799 struct sadb_alg *alg; 6800 6801 /* create new sadb_msg to reply. */ 6802 alen = 0; 6803 for (i = 1; i <= SADB_AALG_MAX; i++) { 6804 if (ah_algorithm_lookup(i)) 6805 alen += sizeof(struct sadb_alg); 6806 } 6807 if (alen) 6808 alen += sizeof(struct sadb_supported); 6809 elen = 0; 6810 for (i = 1; i <= SADB_EALG_MAX; i++) { 6811 if (esp_algorithm_lookup(i)) 6812 elen += sizeof(struct sadb_alg); 6813 } 6814 if (elen) 6815 elen += sizeof(struct sadb_supported); 6816 6817 len = sizeof(struct sadb_msg) + alen + elen; 6818 6819 if (len > MCLBYTES) 6820 return key_senderror(so, m, ENOBUFS); 6821 6822 MGETHDR(n, M_DONTWAIT, MT_DATA); 6823 if (len > MHLEN) { 6824 MCLGET(n, M_DONTWAIT); 6825 if ((n->m_flags & M_EXT) == 0) { 6826 m_freem(n); 6827 n = NULL; 6828 } 6829 } 6830 if (!n) 6831 return key_senderror(so, m, ENOBUFS); 6832 6833 n->m_pkthdr.len = n->m_len = len; 6834 n->m_next = NULL; 6835 off = 0; 6836 6837 m_copydata(m, 0, sizeof(struct sadb_msg), mtod(n, caddr_t) + off); 6838 newmsg = mtod(n, struct sadb_msg *); 6839 newmsg->sadb_msg_errno = 0; 6840 newmsg->sadb_msg_len = PFKEY_UNIT64(len); 6841 off += PFKEY_ALIGN8(sizeof(struct sadb_msg)); 6842 6843 /* for authentication algorithm */ 6844 if (alen) { 6845 sup = (struct sadb_supported *)(mtod(n, caddr_t) + off); 6846 sup->sadb_supported_len = PFKEY_UNIT64(alen); 6847 sup->sadb_supported_exttype = SADB_EXT_SUPPORTED_AUTH; 6848 off += PFKEY_ALIGN8(sizeof(*sup)); 6849 6850 for (i = 1; i <= SADB_AALG_MAX; i++) { 6851 struct auth_hash *aalgo; 6852 u_int16_t minkeysize, maxkeysize; 6853 6854 aalgo = ah_algorithm_lookup(i); 6855 if (!aalgo) 6856 continue; 6857 alg = (struct sadb_alg *)(mtod(n, caddr_t) + off); 6858 alg->sadb_alg_id = i; 6859 alg->sadb_alg_ivlen = 0; 6860 key_getsizes_ah(aalgo, i, &minkeysize, &maxkeysize); 6861 alg->sadb_alg_minbits = _BITS(minkeysize); 6862 alg->sadb_alg_maxbits = _BITS(maxkeysize); 6863 off += PFKEY_ALIGN8(sizeof(*alg)); 6864 } 6865 } 6866 6867 /* for encryption algorithm */ 6868 if (elen) { 6869 sup = (struct sadb_supported *)(mtod(n, caddr_t) + off); 6870 sup->sadb_supported_len = PFKEY_UNIT64(elen); 6871 sup->sadb_supported_exttype = SADB_EXT_SUPPORTED_ENCRYPT; 6872 off += PFKEY_ALIGN8(sizeof(*sup)); 6873 6874 for (i = 1; i <= SADB_EALG_MAX; i++) { 6875 struct enc_xform *ealgo; 6876 6877 ealgo = esp_algorithm_lookup(i); 6878 if (!ealgo) 6879 continue; 6880 alg = (struct sadb_alg *)(mtod(n, caddr_t) + off); 6881 alg->sadb_alg_id = i; 6882 alg->sadb_alg_ivlen = ealgo->blocksize; 6883 alg->sadb_alg_minbits = _BITS(ealgo->minkey); 6884 alg->sadb_alg_maxbits = _BITS(ealgo->maxkey); 6885 off += PFKEY_ALIGN8(sizeof(struct sadb_alg)); 6886 } 6887 } 6888 6889 IPSEC_ASSERT(off == len, 6890 ("length assumption failed (off %u len %u)", off, len)); 6891 6892 m_freem(m); 6893 return key_sendup_mbuf(so, n, KEY_SENDUP_REGISTERED); 6894 } 6895} 6896 6897/* 6898 * free secreg entry registered. 6899 * XXX: I want to do free a socket marked done SADB_RESIGER to socket. 6900 */ 6901void 6902key_freereg(struct socket *so) 6903{ 6904 INIT_VNET_IPSEC(curvnet); 6905 struct secreg *reg; 6906 int i; 6907 6908 IPSEC_ASSERT(so != NULL, ("NULL so")); 6909 6910 /* 6911 * check whether existing or not. 6912 * check all type of SA, because there is a potential that 6913 * one socket is registered to multiple type of SA. 6914 */ 6915 REGTREE_LOCK(); 6916 for (i = 0; i <= SADB_SATYPE_MAX; i++) { 6917 LIST_FOREACH(reg, &V_regtree[i], chain) { 6918 if (reg->so == so && __LIST_CHAINED(reg)) { 6919 LIST_REMOVE(reg, chain); 6920 free(reg, M_IPSEC_SAR); 6921 break; 6922 } 6923 } 6924 } 6925 REGTREE_UNLOCK(); 6926} 6927 6928/* 6929 * SADB_EXPIRE processing 6930 * send 6931 * <base, SA, SA2, lifetime(C and one of HS), address(SD)> 6932 * to KMD by PF_KEY. 6933 * NOTE: We send only soft lifetime extension. 6934 * 6935 * OUT: 0 : succeed 6936 * others : error number 6937 */ 6938static int 6939key_expire(struct secasvar *sav) 6940{ 6941 int s; 6942 int satype; 6943 struct mbuf *result = NULL, *m; 6944 int len; 6945 int error = -1; 6946 struct sadb_lifetime *lt; 6947 6948 /* XXX: Why do we lock ? */ 6949 s = splnet(); /*called from softclock()*/ 6950 6951 IPSEC_ASSERT (sav != NULL, ("null sav")); 6952 IPSEC_ASSERT (sav->sah != NULL, ("null sa header")); 6953 6954 /* set msg header */ 6955 satype = key_proto2satype(sav->sah->saidx.proto); 6956 IPSEC_ASSERT(satype != 0, ("invalid proto, satype %u", satype)); 6957 m = key_setsadbmsg(SADB_EXPIRE, 0, satype, sav->seq, 0, sav->refcnt); 6958 if (!m) { 6959 error = ENOBUFS; 6960 goto fail; 6961 } 6962 result = m; 6963 6964 /* create SA extension */ 6965 m = key_setsadbsa(sav); 6966 if (!m) { 6967 error = ENOBUFS; 6968 goto fail; 6969 } 6970 m_cat(result, m); 6971 6972 /* create SA extension */ 6973 m = key_setsadbxsa2(sav->sah->saidx.mode, 6974 sav->replay ? sav->replay->count : 0, 6975 sav->sah->saidx.reqid); 6976 if (!m) { 6977 error = ENOBUFS; 6978 goto fail; 6979 } 6980 m_cat(result, m); 6981 6982 /* create lifetime extension (current and soft) */ 6983 len = PFKEY_ALIGN8(sizeof(*lt)) * 2; 6984 m = key_alloc_mbuf(len); 6985 if (!m || m->m_next) { /*XXX*/ 6986 if (m) 6987 m_freem(m); 6988 error = ENOBUFS; 6989 goto fail; 6990 } 6991 bzero(mtod(m, caddr_t), len); 6992 lt = mtod(m, struct sadb_lifetime *); 6993 lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime)); 6994 lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT; 6995 lt->sadb_lifetime_allocations = sav->lft_c->allocations; 6996 lt->sadb_lifetime_bytes = sav->lft_c->bytes; 6997 lt->sadb_lifetime_addtime = sav->lft_c->addtime; 6998 lt->sadb_lifetime_usetime = sav->lft_c->usetime; 6999 lt = (struct sadb_lifetime *)(mtod(m, caddr_t) + len / 2); 7000 lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime)); 7001 lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT; 7002 lt->sadb_lifetime_allocations = sav->lft_s->allocations; 7003 lt->sadb_lifetime_bytes = sav->lft_s->bytes; 7004 lt->sadb_lifetime_addtime = sav->lft_s->addtime; 7005 lt->sadb_lifetime_usetime = sav->lft_s->usetime; 7006 m_cat(result, m); 7007 7008 /* set sadb_address for source */ 7009 m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, 7010 &sav->sah->saidx.src.sa, 7011 FULLMASK, IPSEC_ULPROTO_ANY); 7012 if (!m) { 7013 error = ENOBUFS; 7014 goto fail; 7015 } 7016 m_cat(result, m); 7017 7018 /* set sadb_address for destination */ 7019 m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, 7020 &sav->sah->saidx.dst.sa, 7021 FULLMASK, IPSEC_ULPROTO_ANY); 7022 if (!m) { 7023 error = ENOBUFS; 7024 goto fail; 7025 } 7026 m_cat(result, m); 7027 7028 /* 7029 * XXX-BZ Handle NAT-T extensions here. 7030 */ 7031 7032 if ((result->m_flags & M_PKTHDR) == 0) { 7033 error = EINVAL; 7034 goto fail; 7035 } 7036 7037 if (result->m_len < sizeof(struct sadb_msg)) { 7038 result = m_pullup(result, sizeof(struct sadb_msg)); 7039 if (result == NULL) { 7040 error = ENOBUFS; 7041 goto fail; 7042 } 7043 } 7044 7045 result->m_pkthdr.len = 0; 7046 for (m = result; m; m = m->m_next) 7047 result->m_pkthdr.len += m->m_len; 7048 7049 mtod(result, struct sadb_msg *)->sadb_msg_len = 7050 PFKEY_UNIT64(result->m_pkthdr.len); 7051 7052 splx(s); 7053 return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED); 7054 7055 fail: 7056 if (result) 7057 m_freem(result); 7058 splx(s); 7059 return error; 7060} 7061 7062/* 7063 * SADB_FLUSH processing 7064 * receive 7065 * <base> 7066 * from the ikmpd, and free all entries in secastree. 7067 * and send, 7068 * <base> 7069 * to the ikmpd. 7070 * NOTE: to do is only marking SADB_SASTATE_DEAD. 7071 * 7072 * m will always be freed. 7073 */ 7074static int 7075key_flush(so, m, mhp) 7076 struct socket *so; 7077 struct mbuf *m; 7078 const struct sadb_msghdr *mhp; 7079{ 7080 INIT_VNET_IPSEC(curvnet); 7081 struct sadb_msg *newmsg; 7082 struct secashead *sah, *nextsah; 7083 struct secasvar *sav, *nextsav; 7084 u_int16_t proto; 7085 u_int8_t state; 7086 u_int stateidx; 7087 7088 IPSEC_ASSERT(so != NULL, ("null socket")); 7089 IPSEC_ASSERT(mhp != NULL, ("null msghdr")); 7090 IPSEC_ASSERT(mhp->msg != NULL, ("null msg")); 7091 7092 /* map satype to proto */ 7093 if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { 7094 ipseclog((LOG_DEBUG, "%s: invalid satype is passed.\n", 7095 __func__)); 7096 return key_senderror(so, m, EINVAL); 7097 } 7098 7099 /* no SATYPE specified, i.e. flushing all SA. */ 7100 SAHTREE_LOCK(); 7101 for (sah = LIST_FIRST(&V_sahtree); 7102 sah != NULL; 7103 sah = nextsah) { 7104 nextsah = LIST_NEXT(sah, chain); 7105 7106 if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC 7107 && proto != sah->saidx.proto) 7108 continue; 7109 7110 for (stateidx = 0; 7111 stateidx < _ARRAYLEN(saorder_state_alive); 7112 stateidx++) { 7113 state = saorder_state_any[stateidx]; 7114 for (sav = LIST_FIRST(&sah->savtree[state]); 7115 sav != NULL; 7116 sav = nextsav) { 7117 7118 nextsav = LIST_NEXT(sav, chain); 7119 7120 key_sa_chgstate(sav, SADB_SASTATE_DEAD); 7121 KEY_FREESAV(&sav); 7122 } 7123 } 7124 7125 sah->state = SADB_SASTATE_DEAD; 7126 } 7127 SAHTREE_UNLOCK(); 7128 7129 if (m->m_len < sizeof(struct sadb_msg) || 7130 sizeof(struct sadb_msg) > m->m_len + M_TRAILINGSPACE(m)) { 7131 ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__)); 7132 return key_senderror(so, m, ENOBUFS); 7133 } 7134 7135 if (m->m_next) 7136 m_freem(m->m_next); 7137 m->m_next = NULL; 7138 m->m_pkthdr.len = m->m_len = sizeof(struct sadb_msg); 7139 newmsg = mtod(m, struct sadb_msg *); 7140 newmsg->sadb_msg_errno = 0; 7141 newmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); 7142 7143 return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); 7144} 7145 7146/* 7147 * SADB_DUMP processing 7148 * dump all entries including status of DEAD in SAD. 7149 * receive 7150 * <base> 7151 * from the ikmpd, and dump all secasvar leaves 7152 * and send, 7153 * <base> ..... 7154 * to the ikmpd. 7155 * 7156 * m will always be freed. 7157 */ 7158static int 7159key_dump(so, m, mhp) 7160 struct socket *so; 7161 struct mbuf *m; 7162 const struct sadb_msghdr *mhp; 7163{ 7164 INIT_VNET_IPSEC(curvnet); 7165 struct secashead *sah; 7166 struct secasvar *sav; 7167 u_int16_t proto; 7168 u_int stateidx; 7169 u_int8_t satype; 7170 u_int8_t state; 7171 int cnt; 7172 struct sadb_msg *newmsg; 7173 struct mbuf *n; 7174 7175 IPSEC_ASSERT(so != NULL, ("null socket")); 7176 IPSEC_ASSERT(m != NULL, ("null mbuf")); 7177 IPSEC_ASSERT(mhp != NULL, ("null msghdr")); 7178 IPSEC_ASSERT(mhp->msg != NULL, ("null msg")); 7179 7180 /* map satype to proto */ 7181 if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { 7182 ipseclog((LOG_DEBUG, "%s: invalid satype is passed.\n", 7183 __func__)); 7184 return key_senderror(so, m, EINVAL); 7185 } 7186 7187 /* count sav entries to be sent to the userland. */ 7188 cnt = 0; 7189 SAHTREE_LOCK(); 7190 LIST_FOREACH(sah, &V_sahtree, chain) { 7191 if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC 7192 && proto != sah->saidx.proto) 7193 continue; 7194 7195 for (stateidx = 0; 7196 stateidx < _ARRAYLEN(saorder_state_any); 7197 stateidx++) { 7198 state = saorder_state_any[stateidx]; 7199 LIST_FOREACH(sav, &sah->savtree[state], chain) { 7200 cnt++; 7201 } 7202 } 7203 } 7204 7205 if (cnt == 0) { 7206 SAHTREE_UNLOCK(); 7207 return key_senderror(so, m, ENOENT); 7208 } 7209 7210 /* send this to the userland, one at a time. */ 7211 newmsg = NULL; 7212 LIST_FOREACH(sah, &V_sahtree, chain) { 7213 if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC 7214 && proto != sah->saidx.proto) 7215 continue; 7216 7217 /* map proto to satype */ 7218 if ((satype = key_proto2satype(sah->saidx.proto)) == 0) { 7219 SAHTREE_UNLOCK(); 7220 ipseclog((LOG_DEBUG, "%s: there was invalid proto in " 7221 "SAD.\n", __func__)); 7222 return key_senderror(so, m, EINVAL); 7223 } 7224 7225 for (stateidx = 0; 7226 stateidx < _ARRAYLEN(saorder_state_any); 7227 stateidx++) { 7228 state = saorder_state_any[stateidx]; 7229 LIST_FOREACH(sav, &sah->savtree[state], chain) { 7230 n = key_setdumpsa(sav, SADB_DUMP, satype, 7231 --cnt, mhp->msg->sadb_msg_pid); 7232 if (!n) { 7233 SAHTREE_UNLOCK(); 7234 return key_senderror(so, m, ENOBUFS); 7235 } 7236 key_sendup_mbuf(so, n, KEY_SENDUP_ONE); 7237 } 7238 } 7239 } 7240 SAHTREE_UNLOCK(); 7241 7242 m_freem(m); 7243 return 0; 7244} 7245 7246/* 7247 * SADB_X_PROMISC processing 7248 * 7249 * m will always be freed. 7250 */ 7251static int 7252key_promisc(so, m, mhp) 7253 struct socket *so; 7254 struct mbuf *m; 7255 const struct sadb_msghdr *mhp; 7256{ 7257 int olen; 7258 7259 IPSEC_ASSERT(so != NULL, ("null socket")); 7260 IPSEC_ASSERT(m != NULL, ("null mbuf")); 7261 IPSEC_ASSERT(mhp != NULL, ("null msghdr")); 7262 IPSEC_ASSERT(mhp->msg != NULL, ("null msg")); 7263 7264 olen = PFKEY_UNUNIT64(mhp->msg->sadb_msg_len); 7265 7266 if (olen < sizeof(struct sadb_msg)) { 7267#if 1 7268 return key_senderror(so, m, EINVAL); 7269#else 7270 m_freem(m); 7271 return 0; 7272#endif 7273 } else if (olen == sizeof(struct sadb_msg)) { 7274 /* enable/disable promisc mode */ 7275 struct keycb *kp; 7276 7277 if ((kp = (struct keycb *)sotorawcb(so)) == NULL) 7278 return key_senderror(so, m, EINVAL); 7279 mhp->msg->sadb_msg_errno = 0; 7280 switch (mhp->msg->sadb_msg_satype) { 7281 case 0: 7282 case 1: 7283 kp->kp_promisc = mhp->msg->sadb_msg_satype; 7284 break; 7285 default: 7286 return key_senderror(so, m, EINVAL); 7287 } 7288 7289 /* send the original message back to everyone */ 7290 mhp->msg->sadb_msg_errno = 0; 7291 return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); 7292 } else { 7293 /* send packet as is */ 7294 7295 m_adj(m, PFKEY_ALIGN8(sizeof(struct sadb_msg))); 7296 7297 /* TODO: if sadb_msg_seq is specified, send to specific pid */ 7298 return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); 7299 } 7300} 7301 7302static int (*key_typesw[]) __P((struct socket *, struct mbuf *, 7303 const struct sadb_msghdr *)) = { 7304 NULL, /* SADB_RESERVED */ 7305 key_getspi, /* SADB_GETSPI */ 7306 key_update, /* SADB_UPDATE */ 7307 key_add, /* SADB_ADD */ 7308 key_delete, /* SADB_DELETE */ 7309 key_get, /* SADB_GET */ 7310 key_acquire2, /* SADB_ACQUIRE */ 7311 key_register, /* SADB_REGISTER */ 7312 NULL, /* SADB_EXPIRE */ 7313 key_flush, /* SADB_FLUSH */ 7314 key_dump, /* SADB_DUMP */ 7315 key_promisc, /* SADB_X_PROMISC */ 7316 NULL, /* SADB_X_PCHANGE */ 7317 key_spdadd, /* SADB_X_SPDUPDATE */ 7318 key_spdadd, /* SADB_X_SPDADD */ 7319 key_spddelete, /* SADB_X_SPDDELETE */ 7320 key_spdget, /* SADB_X_SPDGET */ 7321 NULL, /* SADB_X_SPDACQUIRE */ 7322 key_spddump, /* SADB_X_SPDDUMP */ 7323 key_spdflush, /* SADB_X_SPDFLUSH */ 7324 key_spdadd, /* SADB_X_SPDSETIDX */ 7325 NULL, /* SADB_X_SPDEXPIRE */ 7326 key_spddelete2, /* SADB_X_SPDDELETE2 */ 7327}; 7328 7329/* 7330 * parse sadb_msg buffer to process PFKEYv2, 7331 * and create a data to response if needed. 7332 * I think to be dealed with mbuf directly. 7333 * IN: 7334 * msgp : pointer to pointer to a received buffer pulluped. 7335 * This is rewrited to response. 7336 * so : pointer to socket. 7337 * OUT: 7338 * length for buffer to send to user process. 7339 */ 7340int 7341key_parse(m, so) 7342 struct mbuf *m; 7343 struct socket *so; 7344{ 7345 INIT_VNET_IPSEC(curvnet); 7346 struct sadb_msg *msg; 7347 struct sadb_msghdr mh; 7348 u_int orglen; 7349 int error; 7350 int target; 7351 7352 IPSEC_ASSERT(so != NULL, ("null socket")); 7353 IPSEC_ASSERT(m != NULL, ("null mbuf")); 7354 7355#if 0 /*kdebug_sadb assumes msg in linear buffer*/ 7356 KEYDEBUG(KEYDEBUG_KEY_DUMP, 7357 ipseclog((LOG_DEBUG, "%s: passed sadb_msg\n", __func__)); 7358 kdebug_sadb(msg)); 7359#endif 7360 7361 if (m->m_len < sizeof(struct sadb_msg)) { 7362 m = m_pullup(m, sizeof(struct sadb_msg)); 7363 if (!m) 7364 return ENOBUFS; 7365 } 7366 msg = mtod(m, struct sadb_msg *); 7367 orglen = PFKEY_UNUNIT64(msg->sadb_msg_len); 7368 target = KEY_SENDUP_ONE; 7369 7370 if ((m->m_flags & M_PKTHDR) == 0 || 7371 m->m_pkthdr.len != m->m_pkthdr.len) { 7372 ipseclog((LOG_DEBUG, "%s: invalid message length.\n",__func__)); 7373 V_pfkeystat.out_invlen++; 7374 error = EINVAL; 7375 goto senderror; 7376 } 7377 7378 if (msg->sadb_msg_version != PF_KEY_V2) { 7379 ipseclog((LOG_DEBUG, "%s: PF_KEY version %u is mismatched.\n", 7380 __func__, msg->sadb_msg_version)); 7381 V_pfkeystat.out_invver++; 7382 error = EINVAL; 7383 goto senderror; 7384 } 7385 7386 if (msg->sadb_msg_type > SADB_MAX) { 7387 ipseclog((LOG_DEBUG, "%s: invalid type %u is passed.\n", 7388 __func__, msg->sadb_msg_type)); 7389 V_pfkeystat.out_invmsgtype++; 7390 error = EINVAL; 7391 goto senderror; 7392 } 7393 7394 /* for old-fashioned code - should be nuked */ 7395 if (m->m_pkthdr.len > MCLBYTES) { 7396 m_freem(m); 7397 return ENOBUFS; 7398 } 7399 if (m->m_next) { 7400 struct mbuf *n; 7401 7402 MGETHDR(n, M_DONTWAIT, MT_DATA); 7403 if (n && m->m_pkthdr.len > MHLEN) { 7404 MCLGET(n, M_DONTWAIT); 7405 if ((n->m_flags & M_EXT) == 0) { 7406 m_free(n); 7407 n = NULL; 7408 } 7409 } 7410 if (!n) { 7411 m_freem(m); 7412 return ENOBUFS; 7413 } 7414 m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t)); 7415 n->m_pkthdr.len = n->m_len = m->m_pkthdr.len; 7416 n->m_next = NULL; 7417 m_freem(m); 7418 m = n; 7419 } 7420 7421 /* align the mbuf chain so that extensions are in contiguous region. */ 7422 error = key_align(m, &mh); 7423 if (error) 7424 return error; 7425 7426 msg = mh.msg; 7427 7428 /* check SA type */ 7429 switch (msg->sadb_msg_satype) { 7430 case SADB_SATYPE_UNSPEC: 7431 switch (msg->sadb_msg_type) { 7432 case SADB_GETSPI: 7433 case SADB_UPDATE: 7434 case SADB_ADD: 7435 case SADB_DELETE: 7436 case SADB_GET: 7437 case SADB_ACQUIRE: 7438 case SADB_EXPIRE: 7439 ipseclog((LOG_DEBUG, "%s: must specify satype " 7440 "when msg type=%u.\n", __func__, 7441 msg->sadb_msg_type)); 7442 V_pfkeystat.out_invsatype++; 7443 error = EINVAL; 7444 goto senderror; 7445 } 7446 break; 7447 case SADB_SATYPE_AH: 7448 case SADB_SATYPE_ESP: 7449 case SADB_X_SATYPE_IPCOMP: 7450 case SADB_X_SATYPE_TCPSIGNATURE: 7451 switch (msg->sadb_msg_type) { 7452 case SADB_X_SPDADD: 7453 case SADB_X_SPDDELETE: 7454 case SADB_X_SPDGET: 7455 case SADB_X_SPDDUMP: 7456 case SADB_X_SPDFLUSH: 7457 case SADB_X_SPDSETIDX: 7458 case SADB_X_SPDUPDATE: 7459 case SADB_X_SPDDELETE2: 7460 ipseclog((LOG_DEBUG, "%s: illegal satype=%u\n", 7461 __func__, msg->sadb_msg_type)); 7462 V_pfkeystat.out_invsatype++; 7463 error = EINVAL; 7464 goto senderror; 7465 } 7466 break; 7467 case SADB_SATYPE_RSVP: 7468 case SADB_SATYPE_OSPFV2: 7469 case SADB_SATYPE_RIPV2: 7470 case SADB_SATYPE_MIP: 7471 ipseclog((LOG_DEBUG, "%s: type %u isn't supported.\n", 7472 __func__, msg->sadb_msg_satype)); 7473 V_pfkeystat.out_invsatype++; 7474 error = EOPNOTSUPP; 7475 goto senderror; 7476 case 1: /* XXX: What does it do? */ 7477 if (msg->sadb_msg_type == SADB_X_PROMISC) 7478 break; 7479 /*FALLTHROUGH*/ 7480 default: 7481 ipseclog((LOG_DEBUG, "%s: invalid type %u is passed.\n", 7482 __func__, msg->sadb_msg_satype)); 7483 V_pfkeystat.out_invsatype++; 7484 error = EINVAL; 7485 goto senderror; 7486 } 7487 7488 /* check field of upper layer protocol and address family */ 7489 if (mh.ext[SADB_EXT_ADDRESS_SRC] != NULL 7490 && mh.ext[SADB_EXT_ADDRESS_DST] != NULL) { 7491 struct sadb_address *src0, *dst0; 7492 u_int plen; 7493 7494 src0 = (struct sadb_address *)(mh.ext[SADB_EXT_ADDRESS_SRC]); 7495 dst0 = (struct sadb_address *)(mh.ext[SADB_EXT_ADDRESS_DST]); 7496 7497 /* check upper layer protocol */ 7498 if (src0->sadb_address_proto != dst0->sadb_address_proto) { 7499 ipseclog((LOG_DEBUG, "%s: upper layer protocol " 7500 "mismatched.\n", __func__)); 7501 V_pfkeystat.out_invaddr++; 7502 error = EINVAL; 7503 goto senderror; 7504 } 7505 7506 /* check family */ 7507 if (PFKEY_ADDR_SADDR(src0)->sa_family != 7508 PFKEY_ADDR_SADDR(dst0)->sa_family) { 7509 ipseclog((LOG_DEBUG, "%s: address family mismatched.\n", 7510 __func__)); 7511 V_pfkeystat.out_invaddr++; 7512 error = EINVAL; 7513 goto senderror; 7514 } 7515 if (PFKEY_ADDR_SADDR(src0)->sa_len != 7516 PFKEY_ADDR_SADDR(dst0)->sa_len) { 7517 ipseclog((LOG_DEBUG, "%s: address struct size " 7518 "mismatched.\n", __func__)); 7519 V_pfkeystat.out_invaddr++; 7520 error = EINVAL; 7521 goto senderror; 7522 } 7523 7524 switch (PFKEY_ADDR_SADDR(src0)->sa_family) { 7525 case AF_INET: 7526 if (PFKEY_ADDR_SADDR(src0)->sa_len != 7527 sizeof(struct sockaddr_in)) { 7528 V_pfkeystat.out_invaddr++; 7529 error = EINVAL; 7530 goto senderror; 7531 } 7532 break; 7533 case AF_INET6: 7534 if (PFKEY_ADDR_SADDR(src0)->sa_len != 7535 sizeof(struct sockaddr_in6)) { 7536 V_pfkeystat.out_invaddr++; 7537 error = EINVAL; 7538 goto senderror; 7539 } 7540 break; 7541 default: 7542 ipseclog((LOG_DEBUG, "%s: unsupported address family\n", 7543 __func__)); 7544 V_pfkeystat.out_invaddr++; 7545 error = EAFNOSUPPORT; 7546 goto senderror; 7547 } 7548 7549 switch (PFKEY_ADDR_SADDR(src0)->sa_family) { 7550 case AF_INET: 7551 plen = sizeof(struct in_addr) << 3; 7552 break; 7553 case AF_INET6: 7554 plen = sizeof(struct in6_addr) << 3; 7555 break; 7556 default: 7557 plen = 0; /*fool gcc*/ 7558 break; 7559 } 7560 7561 /* check max prefix length */ 7562 if (src0->sadb_address_prefixlen > plen || 7563 dst0->sadb_address_prefixlen > plen) { 7564 ipseclog((LOG_DEBUG, "%s: illegal prefixlen.\n", 7565 __func__)); 7566 V_pfkeystat.out_invaddr++; 7567 error = EINVAL; 7568 goto senderror; 7569 } 7570 7571 /* 7572 * prefixlen == 0 is valid because there can be a case when 7573 * all addresses are matched. 7574 */ 7575 } 7576 7577 if (msg->sadb_msg_type >= sizeof(key_typesw)/sizeof(key_typesw[0]) || 7578 key_typesw[msg->sadb_msg_type] == NULL) { 7579 V_pfkeystat.out_invmsgtype++; 7580 error = EINVAL; 7581 goto senderror; 7582 } 7583 7584 return (*key_typesw[msg->sadb_msg_type])(so, m, &mh); 7585 7586senderror: 7587 msg->sadb_msg_errno = error; 7588 return key_sendup_mbuf(so, m, target); 7589} 7590 7591static int 7592key_senderror(so, m, code) 7593 struct socket *so; 7594 struct mbuf *m; 7595 int code; 7596{ 7597 struct sadb_msg *msg; 7598 7599 IPSEC_ASSERT(m->m_len >= sizeof(struct sadb_msg), 7600 ("mbuf too small, len %u", m->m_len)); 7601 7602 msg = mtod(m, struct sadb_msg *); 7603 msg->sadb_msg_errno = code; 7604 return key_sendup_mbuf(so, m, KEY_SENDUP_ONE); 7605} 7606 7607/* 7608 * set the pointer to each header into message buffer. 7609 * m will be freed on error. 7610 * XXX larger-than-MCLBYTES extension? 7611 */ 7612static int 7613key_align(m, mhp) 7614 struct mbuf *m; 7615 struct sadb_msghdr *mhp; 7616{ 7617 INIT_VNET_IPSEC(curvnet); 7618 struct mbuf *n; 7619 struct sadb_ext *ext; 7620 size_t off, end; 7621 int extlen; 7622 int toff; 7623 7624 IPSEC_ASSERT(m != NULL, ("null mbuf")); 7625 IPSEC_ASSERT(mhp != NULL, ("null msghdr")); 7626 IPSEC_ASSERT(m->m_len >= sizeof(struct sadb_msg), 7627 ("mbuf too small, len %u", m->m_len)); 7628 7629 /* initialize */ 7630 bzero(mhp, sizeof(*mhp)); 7631 7632 mhp->msg = mtod(m, struct sadb_msg *); 7633 mhp->ext[0] = (struct sadb_ext *)mhp->msg; /*XXX backward compat */ 7634 7635 end = PFKEY_UNUNIT64(mhp->msg->sadb_msg_len); 7636 extlen = end; /*just in case extlen is not updated*/ 7637 for (off = sizeof(struct sadb_msg); off < end; off += extlen) { 7638 n = m_pulldown(m, off, sizeof(struct sadb_ext), &toff); 7639 if (!n) { 7640 /* m is already freed */ 7641 return ENOBUFS; 7642 } 7643 ext = (struct sadb_ext *)(mtod(n, caddr_t) + toff); 7644 7645 /* set pointer */ 7646 switch (ext->sadb_ext_type) { 7647 case SADB_EXT_SA: 7648 case SADB_EXT_ADDRESS_SRC: 7649 case SADB_EXT_ADDRESS_DST: 7650 case SADB_EXT_ADDRESS_PROXY: 7651 case SADB_EXT_LIFETIME_CURRENT: 7652 case SADB_EXT_LIFETIME_HARD: 7653 case SADB_EXT_LIFETIME_SOFT: 7654 case SADB_EXT_KEY_AUTH: 7655 case SADB_EXT_KEY_ENCRYPT: 7656 case SADB_EXT_IDENTITY_SRC: 7657 case SADB_EXT_IDENTITY_DST: 7658 case SADB_EXT_SENSITIVITY: 7659 case SADB_EXT_PROPOSAL: 7660 case SADB_EXT_SUPPORTED_AUTH: 7661 case SADB_EXT_SUPPORTED_ENCRYPT: 7662 case SADB_EXT_SPIRANGE: 7663 case SADB_X_EXT_POLICY: 7664 case SADB_X_EXT_SA2: 7665#ifdef IPSEC_NAT_T 7666 case SADB_X_EXT_NAT_T_TYPE: 7667 case SADB_X_EXT_NAT_T_SPORT: 7668 case SADB_X_EXT_NAT_T_DPORT: 7669 case SADB_X_EXT_NAT_T_OAI: 7670 case SADB_X_EXT_NAT_T_OAR: 7671 case SADB_X_EXT_NAT_T_FRAG: 7672#endif 7673 /* duplicate check */ 7674 /* 7675 * XXX Are there duplication payloads of either 7676 * KEY_AUTH or KEY_ENCRYPT ? 7677 */ 7678 if (mhp->ext[ext->sadb_ext_type] != NULL) { 7679 ipseclog((LOG_DEBUG, "%s: duplicate ext_type " 7680 "%u\n", __func__, ext->sadb_ext_type)); 7681 m_freem(m); 7682 V_pfkeystat.out_dupext++; 7683 return EINVAL; 7684 } 7685 break; 7686 default: 7687 ipseclog((LOG_DEBUG, "%s: invalid ext_type %u\n", 7688 __func__, ext->sadb_ext_type)); 7689 m_freem(m); 7690 V_pfkeystat.out_invexttype++; 7691 return EINVAL; 7692 } 7693 7694 extlen = PFKEY_UNUNIT64(ext->sadb_ext_len); 7695 7696 if (key_validate_ext(ext, extlen)) { 7697 m_freem(m); 7698 V_pfkeystat.out_invlen++; 7699 return EINVAL; 7700 } 7701 7702 n = m_pulldown(m, off, extlen, &toff); 7703 if (!n) { 7704 /* m is already freed */ 7705 return ENOBUFS; 7706 } 7707 ext = (struct sadb_ext *)(mtod(n, caddr_t) + toff); 7708 7709 mhp->ext[ext->sadb_ext_type] = ext; 7710 mhp->extoff[ext->sadb_ext_type] = off; 7711 mhp->extlen[ext->sadb_ext_type] = extlen; 7712 } 7713 7714 if (off != end) { 7715 m_freem(m); 7716 V_pfkeystat.out_invlen++; 7717 return EINVAL; 7718 } 7719 7720 return 0; 7721} 7722 7723static int 7724key_validate_ext(ext, len) 7725 const struct sadb_ext *ext; 7726 int len; 7727{ 7728 const struct sockaddr *sa; 7729 enum { NONE, ADDR } checktype = NONE; 7730 int baselen = 0; 7731 const int sal = offsetof(struct sockaddr, sa_len) + sizeof(sa->sa_len); 7732 7733 if (len != PFKEY_UNUNIT64(ext->sadb_ext_len)) 7734 return EINVAL; 7735 7736 /* if it does not match minimum/maximum length, bail */ 7737 if (ext->sadb_ext_type >= sizeof(minsize) / sizeof(minsize[0]) || 7738 ext->sadb_ext_type >= sizeof(maxsize) / sizeof(maxsize[0])) 7739 return EINVAL; 7740 if (!minsize[ext->sadb_ext_type] || len < minsize[ext->sadb_ext_type]) 7741 return EINVAL; 7742 if (maxsize[ext->sadb_ext_type] && len > maxsize[ext->sadb_ext_type]) 7743 return EINVAL; 7744 7745 /* more checks based on sadb_ext_type XXX need more */ 7746 switch (ext->sadb_ext_type) { 7747 case SADB_EXT_ADDRESS_SRC: 7748 case SADB_EXT_ADDRESS_DST: 7749 case SADB_EXT_ADDRESS_PROXY: 7750 baselen = PFKEY_ALIGN8(sizeof(struct sadb_address)); 7751 checktype = ADDR; 7752 break; 7753 case SADB_EXT_IDENTITY_SRC: 7754 case SADB_EXT_IDENTITY_DST: 7755 if (((const struct sadb_ident *)ext)->sadb_ident_type == 7756 SADB_X_IDENTTYPE_ADDR) { 7757 baselen = PFKEY_ALIGN8(sizeof(struct sadb_ident)); 7758 checktype = ADDR; 7759 } else 7760 checktype = NONE; 7761 break; 7762 default: 7763 checktype = NONE; 7764 break; 7765 } 7766 7767 switch (checktype) { 7768 case NONE: 7769 break; 7770 case ADDR: 7771 sa = (const struct sockaddr *)(((const u_int8_t*)ext)+baselen); 7772 if (len < baselen + sal) 7773 return EINVAL; 7774 if (baselen + PFKEY_ALIGN8(sa->sa_len) != len) 7775 return EINVAL; 7776 break; 7777 } 7778 7779 return 0; 7780} 7781 7782void 7783key_init(void) 7784{ 7785 INIT_VNET_IPSEC(curvnet); 7786 int i; 7787 7788 V_key_debug_level = 0; 7789 V_key_spi_trycnt = 1000; 7790 V_key_spi_minval = 0x100; 7791 V_key_spi_maxval = 0x0fffffff; /* XXX */ 7792 V_policy_id = 0; 7793 V_key_int_random = 60; /*interval to initialize randseed,1(m)*/ 7794 V_key_larval_lifetime = 30; /* interval to expire acquiring, 30(s)*/ 7795 V_key_blockacq_count = 10; /* counter for blocking SADB_ACQUIRE.*/ 7796 V_key_blockacq_lifetime = 20; /* lifetime for blocking SADB_ACQUIRE.*/ 7797 V_key_preferred_oldsa = 1; /* preferred old sa rather than new sa*/ 7798 7799 V_acq_seq = 0; 7800 7801 V_ipsec_esp_keymin = 256; 7802 V_ipsec_esp_auth = 0; 7803 V_ipsec_ah_keymin = 128; 7804 7805 for (i = 0; i < IPSEC_DIR_MAX; i++) 7806 LIST_INIT(&V_sptree[i]); 7807 7808 LIST_INIT(&V_sahtree); 7809 7810 for (i = 0; i <= SADB_SATYPE_MAX; i++) 7811 LIST_INIT(&V_regtree[i]); 7812 7813 LIST_INIT(&V_acqtree); 7814 LIST_INIT(&V_spacqtree); 7815 7816 /* system default */ 7817 V_ip4_def_policy.policy = IPSEC_POLICY_NONE; 7818 V_ip4_def_policy.refcnt++; /*never reclaim this*/ 7819 7820 if (!IS_DEFAULT_VNET(curvnet)) 7821 return; 7822 7823 SPTREE_LOCK_INIT(); 7824 REGTREE_LOCK_INIT(); 7825 SAHTREE_LOCK_INIT(); 7826 ACQ_LOCK_INIT(); 7827 SPACQ_LOCK_INIT(); 7828 7829#ifndef IPSEC_DEBUG2 7830 timeout((void *)key_timehandler, (void *)0, hz); 7831#endif /*IPSEC_DEBUG2*/ 7832 7833 /* initialize key statistics */ 7834 keystat.getspi_count = 1; 7835 7836 printf("IPsec: Initialized Security Association Processing.\n"); 7837} 7838 7839#ifdef VIMAGE 7840void 7841key_destroy(void) 7842{ 7843 INIT_VNET_IPSEC(curvnet); 7844 struct secpolicy *sp, *nextsp; 7845 struct secspacq *acq, *nextacq; 7846 struct secashead *sah, *nextsah; 7847 struct secreg *reg; 7848 int i; 7849 7850 SPTREE_LOCK(); 7851 for (i = 0; i < IPSEC_DIR_MAX; i++) { 7852 for (sp = LIST_FIRST(&V_sptree[i]); 7853 sp != NULL; sp = nextsp) { 7854 nextsp = LIST_NEXT(sp, chain); 7855 if (__LIST_CHAINED(sp)) { 7856 LIST_REMOVE(sp, chain); 7857 free(sp, M_IPSEC_SP); 7858 } 7859 } 7860 } 7861 SPTREE_UNLOCK(); 7862 7863 SAHTREE_LOCK(); 7864 for (sah = LIST_FIRST(&V_sahtree); sah != NULL; sah = nextsah) { 7865 nextsah = LIST_NEXT(sah, chain); 7866 if (__LIST_CHAINED(sah)) { 7867 LIST_REMOVE(sah, chain); 7868 free(sah, M_IPSEC_SAH); 7869 } 7870 } 7871 SAHTREE_UNLOCK(); 7872 7873 REGTREE_LOCK(); 7874 for (i = 0; i <= SADB_SATYPE_MAX; i++) { 7875 LIST_FOREACH(reg, &V_regtree[i], chain) { 7876 if (__LIST_CHAINED(reg)) { 7877 LIST_REMOVE(reg, chain); 7878 free(reg, M_IPSEC_SAR); 7879 break; 7880 } 7881 } 7882 } 7883 REGTREE_UNLOCK(); 7884 7885 ACQ_LOCK(); 7886 for (acq = LIST_FIRST(&V_spacqtree); acq != NULL; acq = nextacq) { 7887 nextacq = LIST_NEXT(acq, chain); 7888 if (__LIST_CHAINED(acq)) { 7889 LIST_REMOVE(acq, chain); 7890 free(acq, M_IPSEC_SAQ); 7891 } 7892 } 7893 ACQ_UNLOCK(); 7894 7895 SPACQ_LOCK(); 7896 for (acq = LIST_FIRST(&V_spacqtree); acq != NULL; acq = nextacq) { 7897 nextacq = LIST_NEXT(acq, chain); 7898 if (__LIST_CHAINED(acq)) { 7899 LIST_REMOVE(acq, chain); 7900 free(acq, M_IPSEC_SAQ); 7901 } 7902 } 7903 SPACQ_UNLOCK(); 7904} 7905#endif 7906 7907/* 7908 * XXX: maybe This function is called after INBOUND IPsec processing. 7909 * 7910 * Special check for tunnel-mode packets. 7911 * We must make some checks for consistency between inner and outer IP header. 7912 * 7913 * xxx more checks to be provided 7914 */ 7915int 7916key_checktunnelsanity(sav, family, src, dst) 7917 struct secasvar *sav; 7918 u_int family; 7919 caddr_t src; 7920 caddr_t dst; 7921{ 7922 IPSEC_ASSERT(sav->sah != NULL, ("null SA header")); 7923 7924 /* XXX: check inner IP header */ 7925 7926 return 1; 7927} 7928 7929/* record data transfer on SA, and update timestamps */ 7930void 7931key_sa_recordxfer(sav, m) 7932 struct secasvar *sav; 7933 struct mbuf *m; 7934{ 7935 IPSEC_ASSERT(sav != NULL, ("Null secasvar")); 7936 IPSEC_ASSERT(m != NULL, ("Null mbuf")); 7937 if (!sav->lft_c) 7938 return; 7939 7940 /* 7941 * XXX Currently, there is a difference of bytes size 7942 * between inbound and outbound processing. 7943 */ 7944 sav->lft_c->bytes += m->m_pkthdr.len; 7945 /* to check bytes lifetime is done in key_timehandler(). */ 7946 7947 /* 7948 * We use the number of packets as the unit of 7949 * allocations. We increment the variable 7950 * whenever {esp,ah}_{in,out}put is called. 7951 */ 7952 sav->lft_c->allocations++; 7953 /* XXX check for expires? */ 7954 7955 /* 7956 * NOTE: We record CURRENT usetime by using wall clock, 7957 * in seconds. HARD and SOFT lifetime are measured by the time 7958 * difference (again in seconds) from usetime. 7959 * 7960 * usetime 7961 * v expire expire 7962 * -----+-----+--------+---> t 7963 * <--------------> HARD 7964 * <-----> SOFT 7965 */ 7966 sav->lft_c->usetime = time_second; 7967 /* XXX check for expires? */ 7968 7969 return; 7970} 7971 7972/* dumb version */ 7973void 7974key_sa_routechange(dst) 7975 struct sockaddr *dst; 7976{ 7977 INIT_VNET_IPSEC(curvnet); 7978 struct secashead *sah; 7979 struct route *ro; 7980 7981 SAHTREE_LOCK(); 7982 LIST_FOREACH(sah, &V_sahtree, chain) { 7983 ro = &sah->sa_route; 7984 if (ro->ro_rt && dst->sa_len == ro->ro_dst.sa_len 7985 && bcmp(dst, &ro->ro_dst, dst->sa_len) == 0) { 7986 RTFREE(ro->ro_rt); 7987 ro->ro_rt = (struct rtentry *)NULL; 7988 } 7989 } 7990 SAHTREE_UNLOCK(); 7991} 7992 7993static void 7994key_sa_chgstate(struct secasvar *sav, u_int8_t state) 7995{ 7996 IPSEC_ASSERT(sav != NULL, ("NULL sav")); 7997 SAHTREE_LOCK_ASSERT(); 7998 7999 if (sav->state != state) { 8000 if (__LIST_CHAINED(sav)) 8001 LIST_REMOVE(sav, chain); 8002 sav->state = state; 8003 LIST_INSERT_HEAD(&sav->sah->savtree[state], sav, chain); 8004 } 8005} 8006 8007void 8008key_sa_stir_iv(sav) 8009 struct secasvar *sav; 8010{ 8011 8012 IPSEC_ASSERT(sav->iv != NULL, ("null IV")); 8013 key_randomfill(sav->iv, sav->ivlen); 8014} 8015 8016/* XXX too much? */ 8017static struct mbuf * 8018key_alloc_mbuf(l) 8019 int l; 8020{ 8021 struct mbuf *m = NULL, *n; 8022 int len, t; 8023 8024 len = l; 8025 while (len > 0) { 8026 MGET(n, M_DONTWAIT, MT_DATA); 8027 if (n && len > MLEN) 8028 MCLGET(n, M_DONTWAIT); 8029 if (!n) { 8030 m_freem(m); 8031 return NULL; 8032 } 8033 8034 n->m_next = NULL; 8035 n->m_len = 0; 8036 n->m_len = M_TRAILINGSPACE(n); 8037 /* use the bottom of mbuf, hoping we can prepend afterwards */ 8038 if (n->m_len > len) { 8039 t = (n->m_len - len) & ~(sizeof(long) - 1); 8040 n->m_data += t; 8041 n->m_len = len; 8042 } 8043 8044 len -= n->m_len; 8045 8046 if (m) 8047 m_cat(m, n); 8048 else 8049 m = n; 8050 } 8051 8052 return m; 8053} 8054 8055/* 8056 * Take one of the kernel's security keys and convert it into a PF_KEY 8057 * structure within an mbuf, suitable for sending up to a waiting 8058 * application in user land. 8059 * 8060 * IN: 8061 * src: A pointer to a kernel security key. 8062 * exttype: Which type of key this is. Refer to the PF_KEY data structures. 8063 * OUT: 8064 * a valid mbuf or NULL indicating an error 8065 * 8066 */ 8067 8068static struct mbuf * 8069key_setkey(struct seckey *src, u_int16_t exttype) 8070{ 8071 struct mbuf *m; 8072 struct sadb_key *p; 8073 int len; 8074 8075 if (src == NULL) 8076 return NULL; 8077 8078 len = PFKEY_ALIGN8(sizeof(struct sadb_key) + _KEYLEN(src)); 8079 m = key_alloc_mbuf(len); 8080 if (m == NULL) 8081 return NULL; 8082 p = mtod(m, struct sadb_key *); 8083 bzero(p, len); 8084 p->sadb_key_len = PFKEY_UNIT64(len); 8085 p->sadb_key_exttype = exttype; 8086 p->sadb_key_bits = src->bits; 8087 bcopy(src->key_data, _KEYBUF(p), _KEYLEN(src)); 8088 8089 return m; 8090} 8091 8092/* 8093 * Take one of the kernel's lifetime data structures and convert it 8094 * into a PF_KEY structure within an mbuf, suitable for sending up to 8095 * a waiting application in user land. 8096 * 8097 * IN: 8098 * src: A pointer to a kernel lifetime structure. 8099 * exttype: Which type of lifetime this is. Refer to the PF_KEY 8100 * data structures for more information. 8101 * OUT: 8102 * a valid mbuf or NULL indicating an error 8103 * 8104 */ 8105 8106static struct mbuf * 8107key_setlifetime(struct seclifetime *src, u_int16_t exttype) 8108{ 8109 struct mbuf *m = NULL; 8110 struct sadb_lifetime *p; 8111 int len = PFKEY_ALIGN8(sizeof(struct sadb_lifetime)); 8112 8113 if (src == NULL) 8114 return NULL; 8115 8116 m = key_alloc_mbuf(len); 8117 if (m == NULL) 8118 return m; 8119 p = mtod(m, struct sadb_lifetime *); 8120 8121 bzero(p, len); 8122 p->sadb_lifetime_len = PFKEY_UNIT64(len); 8123 p->sadb_lifetime_exttype = exttype; 8124 p->sadb_lifetime_allocations = src->allocations; 8125 p->sadb_lifetime_bytes = src->bytes; 8126 p->sadb_lifetime_addtime = src->addtime; 8127 p->sadb_lifetime_usetime = src->usetime; 8128 8129 return m; 8130 8131} 8132