⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 key.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
//==========================================================================
//
//      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_ACQUIRE
static LIST_HEAD(_acqtree, secacq) acqtree;		/* acquiring list */
#endif
static 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_DECL
SYSCTL_DECL(_net_key);
#endif

SYSCTL_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 0
static struct mbuf *key_setsadbident __P((u_int16_t, u_int16_t, caddr_t,
	int, u_int64_t));
#endif
static 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 INET6
static 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_DOSEQCHECK
static struct secasvar *key_getsavbyseq __P((struct secashead *, u_int32_t));
#endif
static 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_ESP
static struct mbuf *key_getcomb_esp __P((void));
#endif
static 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_ACQUIRE
static struct secacq *key_newacq __P((struct secasindex *));
static struct secacq *key_getacq __P((struct secasindex *));
static struct secacq *key_getacqbyseq __P((u_int32_t));
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -