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 + -
显示快捷键?