key.c
来自「eCos操作系统源码」· C语言 代码 · 共 2,476 行 · 第 1/5 页
C
2,476 行
//==========================================================================//// src/sys/netkey/key.c////==========================================================================//####BSDCOPYRIGHTBEGIN####//// -------------------------------------------//// Portions of this software may have been derived from OpenBSD, // FreeBSD or other sources, and are covered by the appropriate// copyright disclaimers included herein.//// Portions created by Red Hat are// Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.//// -------------------------------------------////####BSDCOPYRIGHTEND####//==========================================================================/* $KAME: key.c,v 1.221 2001/11/06 05:14:30 itojun Exp $ *//* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *//* * This code is referd to RFC 2367 */#include <sys/types.h>#include <sys/param.h>#ifdef __NetBSD__#include <sys/callout.h>#endif#include <sys/mbuf.h>#include <sys/domain.h>#include <sys/protosw.h>#include <sys/malloc.h>#include <sys/socket.h>#include <sys/socketvar.h>#ifdef __FreeBSD__#include <sys/sysctl.h>#endif#include <sys/errno.h>#include <sys/queue.h>#include <net/if.h>#include <net/route.h>#include <net/raw_cb.h>#include <net/if_sec.h>#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <netinet/in_var.h>#ifdef INET6#include <netinet/ip6.h>#include <netinet6/in6_var.h>#include <netinet6/ip6_var.h>#endif /* INET6 */#ifdef INET#include <netinet/in_pcb.h>#endif#ifdef INET6#if !(defined(__bsdi__) && _BSDI_VERSION >= 199802)#include <netinet6/in6_pcb.h>#endif#endif /* INET6 */#include <net/pfkeyv2.h>#include <netkey/keydb.h>#include <netkey/key.h>#include <netkey/keysock.h>#include <netkey/key_debug.h>#include <netinet6/ipsec.h>#include <netinet6/ah.h>#ifdef IPSEC_ESP#include <netinet6/esp.h>#endif#include <netinet6/ipcomp.h>#ifndef offsetof#define offsetof(type, member) ((size_t)(&((type *)0)->member))#endif#ifndef satosin#define satosin(s) ((struct sockaddr_in *)s)#endif#define FULLMASK 0xff/* * Note on SA reference counting: * - SAs that are not in DEAD state will have (total external reference + 1) * following value in reference count field. they cannot be freed and are * referenced from SA header. * - SAs that are in DEAD state will have (total external reference) * in reference count field. they are ready to be freed. reference from * SA header will be removed in key_delsav(), when the reference count * field hits 0 (= no external reference other than from SA header. */u_int32_t key_debug_level = 0;static u_int key_spi_trycnt = 1000;static u_int32_t key_spi_minval = 0x100;static u_int32_t key_spi_maxval = 0x0fffffff; /* XXX */static u_int32_t policy_id = 0;static u_int key_int_random = 60; /*interval to initialize randseed,1(m)*/static u_int key_larval_lifetime = 30; /* interval to expire acquiring, 30(s)*/static int key_blockacq_count = 10; /* counter for blocking SADB_ACQUIRE.*/static int key_blockacq_lifetime = 20; /* lifetime for blocking SADB_ACQUIRE.*/static int key_preferred_oldsa = 1; /*preferred old sa rather than new sa.*/static u_int32_t acq_seq = 0;static int key_tick_init_random = 0;static LIST_HEAD(_sptree, secpolicy) sptree[IPSEC_DIR_MAX]; /* SPD */static LIST_HEAD(_sahtree, secashead) sahtree; /* SAD */static LIST_HEAD(_regtree, secreg) regtree[SADB_SATYPE_MAX + 1]; /* registed list */#ifndef IPSEC_NONBLOCK_ACQUIREstatic LIST_HEAD(_acqtree, secacq) acqtree; /* acquiring list */#endifstatic LIST_HEAD(_spacqtree, secspacq) spacqtree; /* SP acquiring list */struct key_cb key_cb;/* search order for SAs */static u_int saorder_state_valid[] = { SADB_SASTATE_DYING, SADB_SASTATE_MATURE, /* * This order is important because we must select a oldest SA * for outbound processing. For inbound, This is not important. */};static u_int saorder_state_alive[] = { /* except DEAD */ SADB_SASTATE_MATURE, SADB_SASTATE_DYING, SADB_SASTATE_LARVAL};static u_int saorder_state_any[] = { SADB_SASTATE_MATURE, SADB_SASTATE_DYING, SADB_SASTATE_LARVAL, SADB_SASTATE_DEAD};static const int minsize[] = { sizeof(struct sadb_msg), /* SADB_EXT_RESERVED */ sizeof(struct sadb_sa), /* SADB_EXT_SA */ sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_CURRENT */ sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_HARD */ sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_SOFT */ sizeof(struct sadb_address), /* SADB_EXT_ADDRESS_SRC */ sizeof(struct sadb_address), /* SADB_EXT_ADDRESS_DST */ sizeof(struct sadb_address), /* SADB_EXT_ADDRESS_PROXY */ sizeof(struct sadb_key), /* SADB_EXT_KEY_AUTH */ sizeof(struct sadb_key), /* SADB_EXT_KEY_ENCRYPT */ sizeof(struct sadb_ident), /* SADB_EXT_IDENTITY_SRC */ sizeof(struct sadb_ident), /* SADB_EXT_IDENTITY_DST */ sizeof(struct sadb_sens), /* SADB_EXT_SENSITIVITY */ sizeof(struct sadb_prop), /* SADB_EXT_PROPOSAL */ sizeof(struct sadb_supported), /* SADB_EXT_SUPPORTED_AUTH */ sizeof(struct sadb_supported), /* SADB_EXT_SUPPORTED_ENCRYPT */ sizeof(struct sadb_spirange), /* SADB_EXT_SPIRANGE */ 0, /* SADB_X_EXT_KMPRIVATE */ sizeof(struct sadb_x_policy), /* SADB_X_EXT_POLICY */ sizeof(struct sadb_x_sa2), /* SADB_X_SA2 */};static const int maxsize[] = { sizeof(struct sadb_msg), /* SADB_EXT_RESERVED */ sizeof(struct sadb_sa), /* SADB_EXT_SA */ sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_CURRENT */ sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_HARD */ sizeof(struct sadb_lifetime), /* SADB_EXT_LIFETIME_SOFT */ 0, /* SADB_EXT_ADDRESS_SRC */ 0, /* SADB_EXT_ADDRESS_DST */ 0, /* SADB_EXT_ADDRESS_PROXY */ 0, /* SADB_EXT_KEY_AUTH */ 0, /* SADB_EXT_KEY_ENCRYPT */ 0, /* SADB_EXT_IDENTITY_SRC */ 0, /* SADB_EXT_IDENTITY_DST */ 0, /* SADB_EXT_SENSITIVITY */ 0, /* SADB_EXT_PROPOSAL */ 0, /* SADB_EXT_SUPPORTED_AUTH */ 0, /* SADB_EXT_SUPPORTED_ENCRYPT */ sizeof(struct sadb_spirange), /* SADB_EXT_SPIRANGE */ 0, /* SADB_X_EXT_KMPRIVATE */ 0, /* SADB_X_EXT_POLICY */ sizeof(struct sadb_x_sa2), /* SADB_X_SA2 */};static int ipsec_esp_keymin = 256;static int ipsec_esp_auth = 0;static int ipsec_ah_keymin = 128;#ifdef __FreeBSD__#ifdef SYSCTL_DECLSYSCTL_DECL(_net_key);#endifSYSCTL_INT(_net_key, KEYCTL_DEBUG_LEVEL, debug, CTLFLAG_RW, \ &key_debug_level, 0, "");/* max count of trial for the decision of spi value */SYSCTL_INT(_net_key, KEYCTL_SPI_TRY, spi_trycnt, CTLFLAG_RW, \ &key_spi_trycnt, 0, "");/* minimum spi value to allocate automatically. */SYSCTL_INT(_net_key, KEYCTL_SPI_MIN_VALUE, spi_minval, CTLFLAG_RW, \ &key_spi_minval, 0, "");/* maximun spi value to allocate automatically. */SYSCTL_INT(_net_key, KEYCTL_SPI_MAX_VALUE, spi_maxval, CTLFLAG_RW, \ &key_spi_maxval, 0, "");/* interval to initialize randseed */SYSCTL_INT(_net_key, KEYCTL_RANDOM_INT, int_random, CTLFLAG_RW, \ &key_int_random, 0, "");/* lifetime for larval SA */SYSCTL_INT(_net_key, KEYCTL_LARVAL_LIFETIME, larval_lifetime, CTLFLAG_RW, \ &key_larval_lifetime, 0, "");/* counter for blocking to send SADB_ACQUIRE to IKEd */SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_COUNT, blockacq_count, CTLFLAG_RW, \ &key_blockacq_count, 0, "");/* lifetime for blocking to send SADB_ACQUIRE to IKEd */SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_LIFETIME, blockacq_lifetime, CTLFLAG_RW, \ &key_blockacq_lifetime, 0, "");/* minimum ESP key length */SYSCTL_INT(_net_key, KEYCTL_ESP_KEYMIN, esp_keymin, CTLFLAG_RW, \ &ipsec_esp_keymin, 0, "");/* minimum AH key length */SYSCTL_INT(_net_key, KEYCTL_AH_KEYMIN, ah_keymin, CTLFLAG_RW, \ &ipsec_ah_keymin, 0, "");/* perfered old SA rather than new SA */SYSCTL_INT(_net_key, KEYCTL_PREFERED_OLDSA, preferred_oldsa, CTLFLAG_RW,\ &key_preferred_oldsa, 0, "");#endif /* __FreeBSD__ */#ifndef LIST_FOREACH#define LIST_FOREACH(elm, head, field) \ for (elm = LIST_FIRST(head); elm; elm = LIST_NEXT(elm, field))#endif#define __LIST_CHAINED(elm) \ (!((elm)->chain.le_next == NULL && (elm)->chain.le_prev == NULL))#define LIST_INSERT_TAIL(head, elm, type, field) \do {\ struct type *curelm = LIST_FIRST(head); \ if (curelm == NULL) {\ LIST_INSERT_HEAD(head, elm, field); \ } else { \ while (LIST_NEXT(curelm, field)) \ curelm = LIST_NEXT(curelm, field);\ LIST_INSERT_AFTER(curelm, elm, field);\ }\} while (0)#define KEY_CHKSASTATE(head, sav, name) \do { \ if ((head) != (sav)) { \ ipseclog((LOG_DEBUG, "%s: state mismatched (TREE=%d SA=%d)\n", \ (name), (head), (sav))); \ continue; \ } \} while (0)#define KEY_CHKSPDIR(head, sp, name) \do { \ if ((head) != (sp)) { \ ipseclog((LOG_DEBUG, "%s: direction mismatched (TREE=%d SP=%d), " \ "anyway continue.\n", \ (name), (head), (sp))); \ } \} while (0)#if 1#define KMALLOC(p, t, n) \ ((p) = (t) malloc((unsigned long)(n), M_SECA, M_NOWAIT))#define KFREE(p) \ free((caddr_t)(p), M_SECA)#else#define KMALLOC(p, t, n) \do { \ ((p) = (t)malloc((unsigned long)(n), M_SECA, M_NOWAIT)); \ printf("%s %d: %p <- KMALLOC(%s, %d)\n", \ __FILE__, __LINE__, (p), #t, n); \} while (0)#define KFREE(p) \ do { \ printf("%s %d: %p -> KFREE()\n", __FILE__, __LINE__, (p)); \ free((caddr_t)(p), M_SECA); \ } while (0)#endif/* * set parameters into secpolicyindex buffer. * Must allocate secpolicyindex buffer passed to this function. */#define KEY_SETSECSPIDX(_dir, s, d, ps, pd, ulp, idx) \do { \ bzero((idx), sizeof(struct secpolicyindex)); \ (idx)->dir = (_dir); \ (idx)->prefs = (ps); \ (idx)->prefd = (pd); \ (idx)->ul_proto = (ulp); \ bcopy((s), &(idx)->src, ((struct sockaddr *)(s))->sa_len); \ bcopy((d), &(idx)->dst, ((struct sockaddr *)(d))->sa_len); \} while (0)/* * set parameters into secasindex buffer. * Must allocate secasindex buffer before calling this function. */#define KEY_SETSECASIDX(p, m, r, s, d, idx) \do { \ bzero((idx), sizeof(struct secasindex)); \ (idx)->proto = (p); \ (idx)->mode = (m); \ (idx)->reqid = (r); \ bcopy((s), &(idx)->src, ((struct sockaddr *)(s))->sa_len); \ bcopy((d), &(idx)->dst, ((struct sockaddr *)(d))->sa_len); \} while (0)/* key statistics */struct _keystat { u_long getspi_count; /* the avarage of count to try to get new SPI */} keystat;struct sadb_msghdr { struct sadb_msg *msg; struct sadb_ext *ext[SADB_EXT_MAX + 1]; int extoff[SADB_EXT_MAX + 1]; int extlen[SADB_EXT_MAX + 1];};static struct secasvar *key_allocsa_policy __P((struct secasindex *));static void key_freesp_so __P((struct secpolicy **));static struct secasvar *key_do_allocsa_policy __P((struct secashead *, u_int));static void key_delsp __P((struct secpolicy *));static struct secpolicy *key_getsp __P((struct secpolicyindex *));static struct secpolicy *key_getspbyid __P((u_int32_t));static u_int32_t key_newreqid __P((void));static struct mbuf *key_gather_mbuf __P((struct mbuf *, const struct sadb_msghdr *, int, int, ...));static int key_spdadd __P((struct socket *, struct mbuf *, const struct sadb_msghdr *));static u_int32_t key_getnewspid __P((void));static int key_spddelete __P((struct socket *, struct mbuf *, const struct sadb_msghdr *));static int key_spddelete2 __P((struct socket *, struct mbuf *, const struct sadb_msghdr *));static int key_spdget __P((struct socket *, struct mbuf *, const struct sadb_msghdr *));static int key_spdflush __P((struct socket *, struct mbuf *, const struct sadb_msghdr *));static int key_spddump __P((struct socket *, struct mbuf *, const struct sadb_msghdr *));static struct mbuf *key_setdumpsp __P((struct secpolicy *, u_int8_t, u_int32_t, u_int32_t));static u_int key_getspreqmsglen __P((struct secpolicy *));static int key_spdexpire __P((struct secpolicy *));static struct secashead *key_newsah __P((struct secasindex *));static void key_delsah __P((struct secashead *));static struct secasvar *key_newsav __P((struct mbuf *, const struct sadb_msghdr *, struct secashead *, int *));static void key_delsav __P((struct secasvar *));static struct secashead *key_getsah __P((struct secasindex *));static struct secasvar *key_checkspidup __P((struct secasindex *, u_int32_t));static struct secasvar *key_getsavbyspi __P((struct secashead *, u_int32_t));static int key_setsaval __P((struct secasvar *, struct mbuf *, const struct sadb_msghdr *));static int key_mature __P((struct secasvar *));static struct mbuf *key_setdumpsa __P((struct secasvar *, u_int8_t, u_int8_t, u_int32_t, u_int32_t));static struct mbuf *key_setsadbmsg __P((u_int8_t, u_int16_t, u_int8_t, u_int32_t, pid_t, u_int16_t));static struct mbuf *key_setsadbsa __P((struct secasvar *));static struct mbuf *key_setsadbaddr __P((u_int16_t, struct sockaddr *, u_int8_t, u_int16_t));#if 0static struct mbuf *key_setsadbident __P((u_int16_t, u_int16_t, caddr_t, int, u_int64_t));#endifstatic struct mbuf *key_setsadbxsa2 __P((u_int8_t, u_int32_t, u_int32_t));static struct mbuf *key_setsadblifetime __P((u_int16_t, u_int32_t, u_int64_t, u_int64_t, u_int64_t));static struct mbuf *key_setsadbxpolicy __P((u_int16_t, u_int8_t, u_int32_t));static void *key_newbuf __P((const void *, u_int));#ifdef INET6static int key_ismyaddr6 __P((struct sockaddr_in6 *));#endif/* flags for key_cmpsaidx() */#define CMP_HEAD 1 /* protocol, addresses. */#define CMP_MODE_REQID 2 /* additionally HEAD, reqid, mode. */#define CMP_REQID 3 /* additionally HEAD, reaid. */#define CMP_EXACTLY 4 /* all elements. */static int key_cmpsaidx __P((struct secasindex *, struct secasindex *, int));static int key_sockaddrcmp __P((struct sockaddr *, struct sockaddr *, int));static int key_bbcmp __P((caddr_t, caddr_t, u_int));static void key_srandom __P((void));static u_int16_t key_satype2proto __P((u_int8_t));static u_int8_t key_proto2satype __P((u_int16_t));static int key_getspi __P((struct socket *, struct mbuf *, const struct sadb_msghdr *));static u_int32_t key_do_getnewspi __P((struct sadb_spirange *, struct secasindex *));static int key_update __P((struct socket *, struct mbuf *, const struct sadb_msghdr *));#ifdef IPSEC_DOSEQCHECKstatic struct secasvar *key_getsavbyseq __P((struct secashead *, u_int32_t));#endifstatic int key_add __P((struct socket *, struct mbuf *, const struct sadb_msghdr *));static int key_setident __P((struct secashead *, struct mbuf *, const struct sadb_msghdr *));static struct mbuf *key_getmsgbuf_x1 __P((struct mbuf *, const struct sadb_msghdr *));static int key_delete __P((struct socket *, struct mbuf *, const struct sadb_msghdr *));static int key_get __P((struct socket *, struct mbuf *, const struct sadb_msghdr *));static void key_getcomb_setlifetime __P((struct sadb_comb *));#ifdef IPSEC_ESPstatic struct mbuf *key_getcomb_esp __P((void));#endifstatic struct mbuf *key_getcomb_ah __P((void));static struct mbuf *key_getcomb_ipcomp __P((void));static struct mbuf *key_getprop __P((const struct secasindex *));static int key_acquire __P((struct secasindex *, struct secpolicy *));#ifndef IPSEC_NONBLOCK_ACQUIREstatic struct secacq *key_newacq __P((struct secasindex *));static struct secacq *key_getacq __P((struct secasindex *));static struct secacq *key_getacqbyseq __P((u_int32_t));#endifstatic struct secspacq *key_newspacq __P((struct secpolicyindex *));static struct secspacq *key_getspacq __P((struct secpolicyindex *));static int key_acquire2 __P((struct socket *, struct mbuf *, const struct sadb_msghdr *));static int key_register __P((struct socket *, struct mbuf *, const struct sadb_msghdr *));static int key_expire __P((struct secasvar *));static int key_flush __P((struct socket *, struct mbuf *, const struct sadb_msghdr *));static int key_dump __P((struct socket *, struct mbuf *, const struct sadb_msghdr *));static int key_promisc __P((struct socket *, struct mbuf *, const struct sadb_msghdr *));static int key_senderror __P((struct socket *, struct mbuf *, int));static int key_validate_ext __P((const struct sadb_ext *, int));static int key_align __P((struct mbuf *, struct sadb_msghdr *));#if 0static const char *key_getfqdn __P((void));static const char *key_getuserfqdn __P((void));#endifstatic void key_sa_chgstate __P((struct secasvar *, u_int8_t));static struct mbuf *key_alloc_mbuf __P((int));
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?