[Midnightbsd-cvs] src: sys/netipsec: Sync with FreeBSD 7 enhancements.
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Mon Sep 15 20:25:01 EDT 2008
Log Message:
-----------
Sync with FreeBSD 7 enhancements.
Modified Files:
--------------
src/sys/netipsec:
ipsec.c (r1.1.1.1 -> r1.2)
ipsec.h (r1.2 -> r1.3)
ipsec6.h (r1.1.1.1 -> r1.2)
ipsec_input.c (r1.1.1.1 -> r1.2)
ipsec_mbuf.c (r1.2 -> r1.3)
ipsec_osdep.h (r1.1.1.1 -> r1.2)
ipsec_output.c (r1.1.1.1 -> r1.2)
key.c (r1.1.1.1 -> r1.2)
key_debug.c (r1.1.1.1 -> r1.2)
key_var.h (r1.1.1.1 -> r1.2)
keydb.h (r1.1.1.1 -> r1.2)
keysock.c (r1.1.1.2 -> r1.2)
keysock.h (r1.1.1.2 -> r1.2)
xform.h (r1.2 -> r1.3)
xform_ah.c (r1.2 -> r1.3)
xform_esp.c (r1.3 -> r1.4)
xform_ipcomp.c (r1.2 -> r1.3)
xform_ipip.c (r1.2 -> r1.3)
xform_tcp.c (r1.1.1.1 -> r1.2)
-------------- next part --------------
Index: key.c
===================================================================
RCS file: /home/cvs/src/sys/netipsec/key.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipsec/key.c -L sys/netipsec/key.c -u -r1.1.1.1 -r1.2
--- sys/netipsec/key.c
+++ sys/netipsec/key.c
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/netipsec/key.c,v 1.20 2005/01/07 01:45:46 imp Exp $ */
+/* $FreeBSD: src/sys/netipsec/key.c,v 1.28 2007/07/01 11:38:29 gnn Exp $ */
/* $KAME: key.c,v 1.191 2001/06/27 10:46:49 sakane Exp $ */
/*-
@@ -54,6 +54,7 @@
#include <sys/errno.h>
#include <sys/proc.h>
#include <sys/queue.h>
+#include <sys/refcount.h>
#include <sys/syslog.h>
#include <net/if.h>
@@ -420,7 +421,10 @@
static struct mbuf *key_setsadbxsa2 __P((u_int8_t, u_int32_t, u_int32_t));
static struct mbuf *key_setsadbxpolicy __P((u_int16_t, u_int8_t,
u_int32_t));
-static void *key_dup(const void *, u_int, struct malloc_type *);
+static struct seckey *key_dup_keymsg(const struct sadb_key *, u_int,
+ struct malloc_type *);
+static struct seclifetime *key_dup_lifemsg(const struct sadb_lifetime *src,
+ struct malloc_type *type);
#ifdef INET6
static int key_ismyaddr6 __P((struct sockaddr_in6 *));
#endif
@@ -488,6 +492,10 @@
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 *));
+static struct mbuf *key_setlifetime(struct seclifetime *src,
+ u_int16_t exttype);
+static struct mbuf *key_setkey(struct seckey *src, u_int16_t exttype);
+
#if 0
static const char *key_getfqdn __P((void));
static const char *key_getuserfqdn __P((void));
@@ -495,14 +503,26 @@
static void key_sa_chgstate __P((struct secasvar *, u_int8_t));
static struct mbuf *key_alloc_mbuf __P((int));
-#define SA_ADDREF(p) do { \
- (p)->refcnt++; \
- IPSEC_ASSERT((p)->refcnt != 0, ("SA refcnt overflow")); \
-} while (0)
-#define SA_DELREF(p) do { \
- IPSEC_ASSERT((p)->refcnt > 0, ("SA refcnt underflow")); \
- (p)->refcnt--; \
-} while (0)
+static __inline void
+sa_initref(struct secasvar *sav)
+{
+
+ refcount_init(&sav->refcnt, 1);
+}
+static __inline void
+sa_addref(struct secasvar *sav)
+{
+
+ refcount_acquire(&sav->refcnt);
+ IPSEC_ASSERT(sav->refcnt != 0, ("SA refcnt overflow"));
+}
+static __inline int
+sa_delref(struct secasvar *sav)
+{
+
+ IPSEC_ASSERT(sav->refcnt > 0, ("SA refcnt underflow"));
+ return (refcount_release(&sav->refcnt));
+}
#define SP_ADDREF(p) do { \
(p)->refcnt++; \
@@ -909,8 +929,8 @@
/* What the best method is to compare ? */
if (key_preferred_oldsa) {
- if (candidate->lft_c->sadb_lifetime_addtime >
- sav->lft_c->sadb_lifetime_addtime) {
+ if (candidate->lft_c->addtime >
+ sav->lft_c->addtime) {
candidate = sav;
}
continue;
@@ -918,8 +938,8 @@
}
/* preferred new sa rather than old sa */
- if (candidate->lft_c->sadb_lifetime_addtime <
- sav->lft_c->sadb_lifetime_addtime) {
+ if (candidate->lft_c->addtime <
+ sav->lft_c->addtime) {
d = candidate;
candidate = sav;
} else
@@ -930,7 +950,7 @@
* suitable candidate and the lifetime of the SA is not
* permanent.
*/
- if (d->lft_c->sadb_lifetime_addtime != 0) {
+ if (d->lft_c->addtime != 0) {
struct mbuf *m, *result;
u_int8_t satype;
@@ -993,7 +1013,7 @@
}
}
if (candidate) {
- SA_ADDREF(candidate);
+ sa_addref(candidate);
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP %s cause refcnt++:%d SA:%p\n",
__func__, candidate->refcnt, candidate));
@@ -1072,7 +1092,7 @@
/* check dst address */
if (key_sockaddrcmp(&dst->sa, &sav->sah->saidx.dst.sa, 0) != 0)
continue;
- SA_ADDREF(sav);
+ sa_addref(sav);
goto done;
}
}
@@ -1191,16 +1211,16 @@
IPSEC_ASSERT(sav != NULL, ("null sav"));
- /* XXX unguarded? */
- SA_DELREF(sav);
-
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP %s SA:%p (SPI %u) from %s:%u; refcnt now %u\n",
- __func__, sav, ntohl(sav->spi), where, tag, sav->refcnt));
-
- if (sav->refcnt == 0) {
+ if (sa_delref(sav)) {
+ KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
+ printf("DP %s SA:%p (SPI %u) from %s:%u; refcnt now %u\n",
+ __func__, sav, ntohl(sav->spi), where, tag, sav->refcnt));
*psav = NULL;
key_delsav(sav);
+ } else {
+ KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
+ printf("DP %s SA:%p (SPI %u) from %s:%u; refcnt now %u\n",
+ __func__, sav, ntohl(sav->spi), where, tag, sav->refcnt));
}
}
@@ -2103,8 +2123,7 @@
if (mhp->ext[SADB_X_EXT_POLICY] == NULL ||
mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) {
ipseclog((LOG_DEBUG, "%s: invalid message is passed.\n", __func__));
- key_senderror(so, m, EINVAL);
- return 0;
+ return key_senderror(so, m, EINVAL);
}
id = ((struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY])->sadb_x_policy_id;
@@ -2112,7 +2131,7 @@
/* Is there SP in SPD ? */
if ((sp = key_getspbyid(id)) == NULL) {
ipseclog((LOG_DEBUG, "%s: no SP found id:%u.\n", __func__, id));
- key_senderror(so, m, EINVAL);
+ return key_senderror(so, m, EINVAL);
}
sp->state = IPSEC_SPSTATE_DEAD;
@@ -2126,8 +2145,6 @@
/* create new sadb_msg to reply. */
len = PFKEY_ALIGN8(sizeof(struct sadb_msg));
- if (len > MCLBYTES)
- return key_senderror(so, m, ENOBUFS);
MGETHDR(n, M_DONTWAIT, MT_DATA);
if (n && len > MHLEN) {
MCLGET(n, M_DONTWAIT);
@@ -2240,7 +2257,6 @@
{
struct mbuf *result = NULL, *m;
struct secspacq *newspacq;
- int error;
IPSEC_ASSERT(sp != NULL, ("null secpolicy"));
IPSEC_ASSERT(sp->req == NULL, ("policy exists"));
@@ -2268,10 +2284,9 @@
/* create new sadb_msg to reply. */
m = key_setsadbmsg(SADB_X_SPDACQUIRE, 0, 0, 0, 0, 0);
- if (!m) {
- error = ENOBUFS;
- goto fail;
- }
+ if (!m)
+ return ENOBUFS;
+
result = m;
result->m_pkthdr.len = 0;
@@ -2282,11 +2297,6 @@
PFKEY_UNIT64(result->m_pkthdr.len);
return key_sendup_mbuf(NULL, m, KEY_SENDUP_REGISTERED);
-
-fail:
- if (result)
- m_freem(result);
- return error;
}
/*
@@ -2757,7 +2767,7 @@
/* add to satree */
newsav->sah = sah;
- newsav->refcnt = 1;
+ sa_initref(newsav);
newsav->state = SADB_SASTATE_LARVAL;
/* XXX locking??? */
@@ -2787,15 +2797,19 @@
} else {
KASSERT(sav->iv == NULL, ("iv but no xform"));
if (sav->key_auth != NULL)
- bzero(_KEYBUF(sav->key_auth), _KEYLEN(sav->key_auth));
+ bzero(sav->key_auth->key_data, _KEYLEN(sav->key_auth));
if (sav->key_enc != NULL)
- bzero(_KEYBUF(sav->key_enc), _KEYLEN(sav->key_enc));
+ bzero(sav->key_enc->key_data, _KEYLEN(sav->key_enc));
}
if (sav->key_auth != NULL) {
+ if (sav->key_auth->key_data != NULL)
+ free(sav->key_auth->key_data, M_IPSEC_MISC);
free(sav->key_auth, M_IPSEC_MISC);
sav->key_auth = NULL;
}
if (sav->key_enc != NULL) {
+ if (sav->key_enc->key_data != NULL)
+ free(sav->key_enc->key_data, M_IPSEC_MISC);
free(sav->key_enc, M_IPSEC_MISC);
sav->key_enc = NULL;
}
@@ -3038,9 +3052,11 @@
goto fail;
}
- sav->key_auth = key_dup(key0, len, M_IPSEC_MISC);
- if (sav->key_auth == NULL) {
- ipseclog((LOG_DEBUG, "%s: No more memory.\n",__func__));
+ sav->key_auth = (struct seckey *)key_dup_keymsg(key0, len,
+ M_IPSEC_MISC);
+ if (sav->key_auth == NULL ) {
+ ipseclog((LOG_DEBUG, "%s: No more memory.\n",
+ __func__));
error = ENOBUFS;
goto fail;
}
@@ -3066,7 +3082,9 @@
error = EINVAL;
break;
}
- sav->key_enc = key_dup(key0, len, M_IPSEC_MISC);
+ sav->key_enc = (struct seckey *)key_dup_keymsg(key0,
+ len,
+ M_IPSEC_MISC);
if (sav->key_enc == NULL) {
ipseclog((LOG_DEBUG, "%s: No more memory.\n",
__func__));
@@ -3126,13 +3144,10 @@
goto fail;
}
- sav->lft_c->sadb_lifetime_len =
- PFKEY_UNIT64(sizeof(struct sadb_lifetime));
- sav->lft_c->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT;
- sav->lft_c->sadb_lifetime_allocations = 0;
- sav->lft_c->sadb_lifetime_bytes = 0;
- sav->lft_c->sadb_lifetime_addtime = time_second;
- sav->lft_c->sadb_lifetime_usetime = 0;
+ sav->lft_c->allocations = 0;
+ sav->lft_c->bytes = 0;
+ sav->lft_c->addtime = time_second;
+ sav->lft_c->usetime = 0;
/* lifetimes for HARD and SOFT */
{
@@ -3144,7 +3159,7 @@
error = EINVAL;
goto fail;
}
- sav->lft_h = key_dup(lft0, sizeof(*lft0), M_IPSEC_MISC);
+ sav->lft_h = key_dup_lifemsg(lft0, M_IPSEC_MISC);
if (sav->lft_h == NULL) {
ipseclog((LOG_DEBUG, "%s: No more memory.\n",__func__));
error = ENOBUFS;
@@ -3159,7 +3174,7 @@
error = EINVAL;
goto fail;
}
- sav->lft_s = key_dup(lft0, sizeof(*lft0), M_IPSEC_MISC);
+ sav->lft_s = key_dup_lifemsg(lft0, M_IPSEC_MISC);
if (sav->lft_s == NULL) {
ipseclog((LOG_DEBUG, "%s: No more memory.\n",__func__));
error = ENOBUFS;
@@ -3192,7 +3207,12 @@
switch (sav->sah->saidx.proto) {
case IPPROTO_ESP:
case IPPROTO_AH:
- if (ntohl(sav->spi) >= 0 && ntohl(sav->spi) <= 255) {
+ /*
+ * RFC 4302, 2.4. Security Parameters Index (SPI), SPI values
+ * 1-255 reserved by IANA for future use,
+ * 0 for implementation specific, local use.
+ */
+ if (ntohl(sav->spi) <= 255) {
ipseclog((LOG_DEBUG, "%s: illegal range of SPI %u.\n",
__func__, (u_int32_t)ntohl(sav->spi)));
return EINVAL;
@@ -3271,9 +3291,7 @@
u_int32_t seq, pid;
{
struct mbuf *result = NULL, *tres = NULL, *m;
- int l = 0;
int i;
- void *p;
int dumporder[] = {
SADB_EXT_SA, SADB_X_EXT_SA2,
SADB_EXT_LIFETIME_HARD, SADB_EXT_LIFETIME_SOFT,
@@ -3290,7 +3308,6 @@
for (i = sizeof(dumporder)/sizeof(dumporder[0]) - 1; i >= 0; i--) {
m = NULL;
- p = NULL;
switch (dumporder[i]) {
case SADB_EXT_SA:
m = key_setsadbsa(sav);
@@ -3325,36 +3342,45 @@
case SADB_EXT_KEY_AUTH:
if (!sav->key_auth)
continue;
- l = PFKEY_UNUNIT64(sav->key_auth->sadb_key_len);
- p = sav->key_auth;
+ m = key_setkey(sav->key_auth, SADB_EXT_KEY_AUTH);
+ if (!m)
+ goto fail;
break;
case SADB_EXT_KEY_ENCRYPT:
if (!sav->key_enc)
continue;
- l = PFKEY_UNUNIT64(sav->key_enc->sadb_key_len);
- p = sav->key_enc;
+ m = key_setkey(sav->key_enc, SADB_EXT_KEY_ENCRYPT);
+ if (!m)
+ goto fail;
break;
case SADB_EXT_LIFETIME_CURRENT:
if (!sav->lft_c)
continue;
- l = PFKEY_UNUNIT64(((struct sadb_ext *)sav->lft_c)->sadb_ext_len);
- p = sav->lft_c;
+ m = key_setlifetime(sav->lft_c,
+ SADB_EXT_LIFETIME_CURRENT);
+ if (!m)
+ goto fail;
break;
case SADB_EXT_LIFETIME_HARD:
if (!sav->lft_h)
continue;
- l = PFKEY_UNUNIT64(((struct sadb_ext *)sav->lft_h)->sadb_ext_len);
- p = sav->lft_h;
+ m = key_setlifetime(sav->lft_h,
+ SADB_EXT_LIFETIME_HARD);
+ if (!m)
+ goto fail;
break;
case SADB_EXT_LIFETIME_SOFT:
if (!sav->lft_s)
continue;
- l = PFKEY_UNUNIT64(((struct sadb_ext *)sav->lft_s)->sadb_ext_len);
- p = sav->lft_s;
+ m = key_setlifetime(sav->lft_h,
+ SADB_EXT_LIFETIME_SOFT);
+
+ if (!m)
+ goto fail;
break;
case SADB_EXT_ADDRESS_PROXY:
@@ -3366,29 +3392,15 @@
continue;
}
- if ((!m && !p) || (m && p))
+ if (!m)
goto fail;
- if (p && tres) {
- M_PREPEND(tres, l, M_DONTWAIT);
- if (!tres)
- goto fail;
- bcopy(p, mtod(tres, caddr_t), l);
- continue;
- }
- if (p) {
- m = key_alloc_mbuf(l);
- if (!m)
- goto fail;
- m_copyback(m, 0, l, p);
- }
-
if (tres)
m_cat(m, tres);
tres = m;
+
}
m_cat(result, tres);
-
if (result->m_len < sizeof(struct sadb_msg)) {
result = m_pullup(result, sizeof(struct sadb_msg));
if (result == NULL)
@@ -3609,21 +3621,63 @@
}
/* %%% utilities */
-/*
- * copy a buffer into the new buffer allocated.
+/* Take a key message (sadb_key) from the socket and turn it into one
+ * of the kernel's key structures (seckey).
+ *
+ * IN: pointer to the src
+ * OUT: NULL no more memory
*/
-static void *
-key_dup(const void *src, u_int len, struct malloc_type *type)
+struct seckey *
+key_dup_keymsg(const struct sadb_key *src, u_int len,
+ struct malloc_type *type)
+{
+ struct seckey *dst;
+ dst = (struct seckey *)malloc(sizeof(struct seckey), type, M_NOWAIT);
+ if (dst != NULL) {
+ dst->bits = src->sadb_key_bits;
+ dst->key_data = (char *)malloc(len, type, M_NOWAIT);
+ if (dst->key_data != NULL) {
+ bcopy((const char *)src + sizeof(struct sadb_key),
+ dst->key_data, len);
+ } else {
+ ipseclog((LOG_DEBUG, "%s: No more memory.\n",
+ __func__));
+ free(dst, type);
+ dst = NULL;
+ }
+ } else {
+ ipseclog((LOG_DEBUG, "%s: No more memory.\n",
+ __func__));
+
+ }
+ return dst;
+}
+
+/* Take a lifetime message (sadb_lifetime) passed in on a socket and
+ * turn it into one of the kernel's lifetime structures (seclifetime).
+ *
+ * IN: pointer to the destination, source and malloc type
+ * OUT: NULL, no more memory
+ */
+
+static struct seclifetime *
+key_dup_lifemsg(const struct sadb_lifetime *src,
+ struct malloc_type *type)
{
- void *copy;
+ struct seclifetime *dst = NULL;
- copy = malloc(len, type, M_NOWAIT);
- if (copy == NULL) {
+ dst = (struct seclifetime *)malloc(sizeof(struct seclifetime),
+ type, M_NOWAIT);
+ if (dst == NULL) {
/* XXX counter */
ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__));
- } else
- bcopy(src, copy, len);
- return copy;
+ } else {
+ dst->allocations = src->sadb_lifetime_allocations;
+ dst->bytes = src->sadb_lifetime_bytes;
+ dst->addtime = src->sadb_lifetime_addtime;
+ dst->usetime = src->sadb_lifetime_usetime;
+ }
+ return dst;
}
/* compare my own address
@@ -3948,6 +4002,7 @@
satosin6(sa1)->sin6_port != satosin6(sa2)->sin6_port) {
return 1;
}
+ break;
default:
if (bcmp(sa1, sa2, sa1->sa_len) != 0)
return 1;
@@ -4071,13 +4126,13 @@
}
/* check SOFT lifetime */
- if (sav->lft_s->sadb_lifetime_addtime != 0 &&
- now - sav->created > sav->lft_s->sadb_lifetime_addtime) {
+ if (sav->lft_s->addtime != 0 &&
+ now - sav->created > sav->lft_s->addtime) {
/*
* check SA to be used whether or not.
* when SA hasn't been used, delete it.
*/
- if (sav->lft_c->sadb_lifetime_usetime == 0) {
+ if (sav->lft_c->usetime == 0) {
key_sa_chgstate(sav, SADB_SASTATE_DEAD);
KEY_FREESAV(&sav);
} else {
@@ -4096,8 +4151,8 @@
* when new SA is installed. Caution when it's
* installed too big lifetime by time.
*/
- else if (sav->lft_s->sadb_lifetime_bytes != 0 &&
- sav->lft_s->sadb_lifetime_bytes < sav->lft_c->sadb_lifetime_bytes) {
+ else if (sav->lft_s->bytes != 0 &&
+ sav->lft_s->bytes < sav->lft_c->bytes) {
key_sa_chgstate(sav, SADB_SASTATE_DYING);
/*
@@ -4122,15 +4177,15 @@
continue;
}
- if (sav->lft_h->sadb_lifetime_addtime != 0 &&
- now - sav->created > sav->lft_h->sadb_lifetime_addtime) {
+ if (sav->lft_h->addtime != 0 &&
+ now - sav->created > sav->lft_h->addtime) {
key_sa_chgstate(sav, SADB_SASTATE_DEAD);
KEY_FREESAV(&sav);
}
#if 0 /* XXX Should we keep to send expire message until HARD lifetime ? */
else if (sav->lft_s != NULL
- && sav->lft_s->sadb_lifetime_addtime != 0
- && now - sav->created > sav->lft_s->sadb_lifetime_addtime) {
+ && sav->lft_s->addtime != 0
+ && now - sav->created > sav->lft_s->addtime) {
/*
* XXX: should be checked to be
* installed the valid SA.
@@ -4144,8 +4199,8 @@
}
#endif
/* check HARD lifetime by bytes */
- else if (sav->lft_h->sadb_lifetime_bytes != 0 &&
- sav->lft_h->sadb_lifetime_bytes < sav->lft_c->sadb_lifetime_bytes) {
+ else if (sav->lft_h->bytes != 0 &&
+ sav->lft_h->bytes < sav->lft_c->bytes) {
key_sa_chgstate(sav, SADB_SASTATE_DEAD);
KEY_FREESAV(&sav);
}
@@ -4461,8 +4516,6 @@
/* create new sadb_msg to reply. */
len = PFKEY_ALIGN8(sizeof(struct sadb_msg)) +
PFKEY_ALIGN8(sizeof(struct sadb_sa));
- if (len > MCLBYTES)
- return key_senderror(so, m, ENOBUFS);
MGETHDR(n, M_DONTWAIT, MT_DATA);
if (len > MHLEN) {
@@ -4776,7 +4829,7 @@
KEY_CHKSASTATE(state, sav->state, __func__);
if (sav->seq == seq) {
- SA_ADDREF(sav);
+ sa_addref(sav);
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
printf("DP %s cause refcnt++:%d SA:%p\n",
__func__, sav->refcnt, sav));
@@ -4977,20 +5030,23 @@
}
/* make structure */
- sah->idents = malloc(idsrclen, M_IPSEC_MISC, M_NOWAIT);
+ sah->idents = malloc(sizeof(struct secident), M_IPSEC_MISC, M_NOWAIT);
if (sah->idents == NULL) {
ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__));
return ENOBUFS;
}
- sah->identd = malloc(iddstlen, M_IPSEC_MISC, M_NOWAIT);
+ sah->identd = malloc(sizeof(struct secident), M_IPSEC_MISC, M_NOWAIT);
if (sah->identd == NULL) {
free(sah->idents, M_IPSEC_MISC);
sah->idents = NULL;
ipseclog((LOG_DEBUG, "%s: No more memory.\n", __func__));
return ENOBUFS;
}
- bcopy(idsrc, sah->idents, idsrclen);
- bcopy(iddst, sah->identd, iddstlen);
+ sah->idents->type = idsrc->sadb_ident_type;
+ sah->idents->id = idsrc->sadb_ident_id;
+
+ sah->identd->type = iddst->sadb_ident_type;
+ sah->identd->id = iddst->sadb_ident_id;
return 0;
}
@@ -6262,10 +6318,10 @@
lt = mtod(m, struct sadb_lifetime *);
lt->sadb_lifetime_len = PFKEY_UNIT64(sizeof(struct sadb_lifetime));
lt->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT;
- lt->sadb_lifetime_allocations = sav->lft_c->sadb_lifetime_allocations;
- lt->sadb_lifetime_bytes = sav->lft_c->sadb_lifetime_bytes;
- lt->sadb_lifetime_addtime = sav->lft_c->sadb_lifetime_addtime;
- lt->sadb_lifetime_usetime = sav->lft_c->sadb_lifetime_usetime;
+ lt->sadb_lifetime_allocations = sav->lft_c->allocations;
+ lt->sadb_lifetime_bytes = sav->lft_c->bytes;
+ lt->sadb_lifetime_addtime = sav->lft_c->addtime;
+ lt->sadb_lifetime_usetime = sav->lft_c->usetime;
lt = (struct sadb_lifetime *)(mtod(m, caddr_t) + len / 2);
bcopy(sav->lft_s, lt, sizeof(*lt));
m_cat(result, m);
@@ -7103,21 +7159,21 @@
* XXX Currently, there is a difference of bytes size
* between inbound and outbound processing.
*/
- sav->lft_c->sadb_lifetime_bytes += m->m_pkthdr.len;
+ sav->lft_c->bytes += m->m_pkthdr.len;
/* to check bytes lifetime is done in key_timehandler(). */
/*
* We use the number of packets as the unit of
- * sadb_lifetime_allocations. We increment the variable
+ * allocations. We increment the variable
* whenever {esp,ah}_{in,out}put is called.
*/
- sav->lft_c->sadb_lifetime_allocations++;
+ sav->lft_c->allocations++;
/* XXX check for expires? */
/*
- * NOTE: We record CURRENT sadb_lifetime_usetime by using wall clock,
+ * NOTE: We record CURRENT usetime by using wall clock,
* in seconds. HARD and SOFT lifetime are measured by the time
- * difference (again in seconds) from sadb_lifetime_usetime.
+ * difference (again in seconds) from usetime.
*
* usetime
* v expire expire
@@ -7125,7 +7181,7 @@
* <--------------> HARD
* <-----> SOFT
*/
- sav->lft_c->sadb_lifetime_usetime = time_second;
+ sav->lft_c->usetime = time_second;
/* XXX check for expires? */
return;
@@ -7214,3 +7270,81 @@
return m;
}
+
+/*
+ * Take one of the kernel's security keys and convert it into a PF_KEY
+ * structure within an mbuf, suitable for sending up to a waiting
+ * application in user land.
+ *
+ * IN:
+ * src: A pointer to a kernel security key.
+ * exttype: Which type of key this is. Refer to the PF_KEY data structures.
+ * OUT:
+ * a valid mbuf or NULL indicating an error
+ *
+ */
+
+static struct mbuf *
+key_setkey(struct seckey *src, u_int16_t exttype)
+{
+ struct mbuf *m;
+ struct sadb_key *p;
+ int len;
+
+ if (src == NULL)
+ return NULL;
+
+ len = PFKEY_ALIGN8(sizeof(struct sadb_key) + _KEYLEN(src));
+ m = key_alloc_mbuf(len);
+ if (m == NULL)
+ return NULL;
+ p = mtod(m, struct sadb_key *);
+ bzero(p, len);
+ p->sadb_key_len = PFKEY_UNIT64(len);
+ p->sadb_key_exttype = exttype;
+ p->sadb_key_bits = src->bits;
+ bcopy(src->key_data, _KEYBUF(p), _KEYLEN(src));
+
+ return m;
+}
+
+/*
+ * Take one of the kernel's lifetime data structures and convert it
+ * into a PF_KEY structure within an mbuf, suitable for sending up to
+ * a waiting application in user land.
+ *
+ * IN:
+ * src: A pointer to a kernel lifetime structure.
+ * exttype: Which type of lifetime this is. Refer to the PF_KEY
+ * data structures for more information.
+ * OUT:
+ * a valid mbuf or NULL indicating an error
+ *
+ */
+
+static struct mbuf *
+key_setlifetime(struct seclifetime *src, u_int16_t exttype)
+{
+ struct mbuf *m = NULL;
+ struct sadb_lifetime *p;
+ int len = PFKEY_ALIGN8(sizeof(struct sadb_lifetime));
+
+ if (src == NULL)
+ return NULL;
+
+ m = key_alloc_mbuf(len);
+ if (m == NULL)
+ return m;
+ p = mtod(m, struct sadb_lifetime *);
+
+ bzero(p, len);
+ p->sadb_lifetime_len = PFKEY_UNIT64(len);
+ p->sadb_lifetime_exttype = exttype;
+ p->sadb_lifetime_allocations = src->allocations;
+ p->sadb_lifetime_bytes = src->bytes;
+ p->sadb_lifetime_addtime = src->addtime;
+ p->sadb_lifetime_usetime = src->usetime;
+
+ return m;
+
+}
Index: ipsec_input.c
===================================================================
RCS file: /home/cvs/src/sys/netipsec/ipsec_input.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipsec/ipsec_input.c -L sys/netipsec/ipsec_input.c -u -r1.1.1.1 -r1.2
--- sys/netipsec/ipsec_input.c
+++ sys/netipsec/ipsec_input.c
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/netipsec/ipsec_input.c,v 1.9 2005/01/07 01:45:46 imp Exp $ */
+/* $FreeBSD: src/sys/netipsec/ipsec_input.c,v 1.19 2007/09/12 05:54:53 gnn Exp $ */
/* $OpenBSD: ipsec_input.c,v 1.63 2003/02/20 18:35:43 deraadt Exp $ */
/*-
* The authors of this code are John Ioannidis (ji at tla.org),
@@ -43,6 +43,7 @@
#include "opt_inet.h"
#include "opt_inet6.h"
#include "opt_ipsec.h"
+#include "opt_enc.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -55,6 +56,7 @@
#include <sys/syslog.h>
#include <net/if.h>
+#include <net/pfil.h>
#include <net/route.h>
#include <net/netisr.h>
@@ -99,7 +101,7 @@
/*
* ipsec_common_input gets called when an IPsec-protected packet
* is received by IPv4 or IPv6. It's job is to find the right SA
- # and call the appropriate transform. The transform callback
+ * and call the appropriate transform. The transform callback
* takes care of further processing (like ingress filtering).
*/
static int
@@ -115,6 +117,10 @@
IPSEC_ASSERT(m != NULL, ("null packet"));
+ IPSEC_ASSERT(sproto == IPPROTO_ESP || sproto == IPPROTO_AH ||
+ sproto == IPPROTO_IPCOMP,
+ ("unexpected security protocol %u", sproto));
+
if ((sproto == IPPROTO_ESP && !esp_enable) ||
(sproto == IPPROTO_AH && !ah_enable) ||
(sproto == IPPROTO_IPCOMP && !ipcomp_enable)) {
@@ -276,6 +282,11 @@
struct tdb_ident *tdbi;
struct secasindex *saidx;
int error;
+#ifdef INET6
+#ifdef notyet
+ char ip6buf[INET6_ADDRSTRLEN];
+#endif
+#endif
IPSEC_SPLASSERT_SOFTNET(__func__);
@@ -321,6 +332,7 @@
}
prot = ip->ip_p;
+#ifdef notyet
/* IP-in-IP encapsulation */
if (prot == IPPROTO_IPIP) {
struct ip ipn;
@@ -336,7 +348,6 @@
m_copydata(m, ip->ip_hl << 2, sizeof(struct ip),
(caddr_t) &ipn);
-#ifdef notyet
/* XXX PROXY address isn't recorded in SAH */
/*
* Check that the inner source address is the same as
@@ -364,9 +375,8 @@
error = EACCES;
goto bad;
}
-#endif /*XXX*/
}
-#if INET6
+#ifdef INET6
/* IPv6-in-IP encapsulation. */
if (prot == IPPROTO_IPV6) {
struct ip6_hdr ip6n;
@@ -382,7 +392,6 @@
m_copydata(m, ip->ip_hl << 2, sizeof(struct ip6_hdr),
(caddr_t) &ip6n);
-#ifdef notyet
/*
* Check that the inner source address is the same as
* the proxy address, if available.
@@ -397,7 +406,7 @@
DPRINTF(("%s: inner source address %s doesn't "
"correspond to expected proxy source %s, "
"SA %s/%08lx\n", __func__,
- ip6_sprintf(&ip6n.ip6_src),
+ ip6_sprintf(ip6buf, &ip6n.ip6_src),
ipsec_address(&saidx->proxy),
ipsec_address(&saidx->dst),
(u_long) ntohl(sav->spi)));
@@ -408,9 +417,9 @@
error = EACCES;
goto bad;
}
-#endif /*XXX*/
}
#endif /* INET6 */
+#endif /*XXX*/
/*
* Record what we've done to the packet (under what SA it was
@@ -437,13 +446,25 @@
tdbi->spi = sav->spi;
m_tag_prepend(m, mtag);
- } else {
+ } else if (mt != NULL) {
mt->m_tag_id = PACKET_TAG_IPSEC_IN_DONE;
/* XXX do we need to mark m_flags??? */
}
key_sa_recordxfer(sav, m); /* record data transfer */
+#ifdef DEV_ENC
+ /*
+ * Pass the mbuf to enc0 for bpf and pfil. We will filter the IPIP
+ * packet later after it has been decapsulated.
+ */
+ ipsec_bpf(m, sav, AF_INET);
+
+ if (prot != IPPROTO_IPIP)
+ if ((error = ipsec_filter(&m, PFIL_IN)) != 0)
+ return (error);
+#endif
+
/*
* Re-dispatch via software interrupt.
*/
@@ -531,6 +552,9 @@
int nxt;
u_int8_t nxt8;
int error, nest;
+#ifdef notyet
+ char ip6buf[INET6_ADDRSTRLEN];
+#endif
IPSEC_ASSERT(m != NULL, ("null mbuf"));
IPSEC_ASSERT(sav != NULL, ("null SA"));
@@ -572,6 +596,7 @@
/* Save protocol */
m_copydata(m, protoff, 1, (unsigned char *) &prot);
+#ifdef notyet
#ifdef INET
/* IP-in-IP encapsulation */
if (prot == IPPROTO_IPIP) {
@@ -587,7 +612,6 @@
/* ipn will now contain the inner IPv4 header */
m_copydata(m, skip, sizeof(struct ip), (caddr_t) &ipn);
-#ifdef notyet
/*
* Check that the inner source address is the same as
* the proxy address, if available.
@@ -611,7 +635,6 @@
error = EACCES;
goto bad;
}
-#endif /*XXX*/
}
#endif /* INET */
@@ -630,7 +653,6 @@
m_copydata(m, skip, sizeof(struct ip6_hdr),
(caddr_t) &ip6n);
-#ifdef notyet
/*
* Check that the inner source address is the same as
* the proxy address, if available.
@@ -645,7 +667,7 @@
DPRINTF(("%s: inner source address %s doesn't "
"correspond to expected proxy source %s, "
"SA %s/%08lx\n", __func__,
- ip6_sprintf(&ip6n.ip6_src),
+ ip6_sprintf(ip6buf, &ip6n.ip6_src),
ipsec_address(&saidx->proxy),
ipsec_address(&saidx->dst),
(u_long) ntohl(sav->spi)));
@@ -655,8 +677,8 @@
error = EACCES;
goto bad;
}
-#endif /*XXX*/
}
+#endif /*XXX*/
/*
* Record what we've done to the packet (under what SA it was
@@ -739,6 +761,11 @@
void
esp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
{
+ struct ip6ctlparam *ip6cp = NULL;
+ struct mbuf *m = NULL;
+ struct ip6_hdr *ip6;
+ int off;
+
if (sa->sa_family != AF_INET6 ||
sa->sa_len != sizeof(struct sockaddr_in6))
return;
@@ -746,10 +773,18 @@
return;
/* if the parameter is from icmp6, decode it. */
- if (d != NULL) {
- struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d;
- struct mbuf *m = ip6cp->ip6c_m;
- int off = ip6cp->ip6c_off;
+ if (d != NULL) {
+ ip6cp = (struct ip6ctlparam *)d;
+ m = ip6cp->ip6c_m;
+ ip6 = ip6cp->ip6c_ip6;
+ off = ip6cp->ip6c_off;
+ } else {
+ m = NULL;
+ ip6 = NULL;
+ off = 0; /* calm gcc */
+ }
+
+ if (ip6 != NULL) {
struct ip6ctlparam ip6cp1;
Index: xform_ipip.c
===================================================================
RCS file: /home/cvs/src/sys/netipsec/xform_ipip.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/netipsec/xform_ipip.c -L sys/netipsec/xform_ipip.c -u -r1.2 -r1.3
--- sys/netipsec/xform_ipip.c
+++ sys/netipsec/xform_ipip.c
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/netipsec/xform_ipip.c,v 1.11.2.1 2006/04/01 15:22:44 bz Exp $ */
+/* $FreeBSD: src/sys/netipsec/xform_ipip.c,v 1.15 2007/07/19 09:57:54 bz Exp $ */
/* $OpenBSD: ip_ipip.c,v 1.25 2002/06/10 18:04:55 itojun Exp $ */
/*-
* The authors of this code are John Ioannidis (ji at tla.org),
@@ -41,6 +41,7 @@
*/
#include "opt_inet.h"
#include "opt_inet6.h"
+#include "opt_enc.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -51,6 +52,7 @@
#include <sys/sysctl.h>
#include <net/if.h>
+#include <net/pfil.h>
#include <net/route.h>
#include <net/netisr.h>
@@ -345,6 +347,12 @@
/* Statistics */
ipipstat.ipips_ibytes += m->m_pkthdr.len - iphlen;
+#ifdef DEV_ENC
+ /* pass the mbuf to enc0 for packet filtering */
+ if (ipsec_filter(&m, PFIL_IN) != 0)
+ return;
+#endif
+
/*
* Interface pointer stays the same; if no IPsec processing has
* been done (or will be done), this will point to a normal
@@ -599,7 +607,7 @@
return (error);
}
-#ifdef FAST_IPSEC
+#ifdef IPSEC
static int
ipe4_init(struct secasvar *sav, struct xformsw *xsp)
{
@@ -678,4 +686,4 @@
#endif
}
SYSINIT(ipe4_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ipe4_attach, NULL);
-#endif /* FAST_IPSEC */
+#endif /* IPSEC */
Index: ipsec.c
===================================================================
RCS file: /home/cvs/src/sys/netipsec/ipsec.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipsec/ipsec.c -L sys/netipsec/ipsec.c -u -r1.1.1.1 -r1.2
--- sys/netipsec/ipsec.c
+++ sys/netipsec/ipsec.c
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/netipsec/ipsec.c,v 1.12 2005/06/02 23:56:10 hmp Exp $ */
+/* $FreeBSD: src/sys/netipsec/ipsec.c,v 1.24 2007/07/01 11:38:29 gnn Exp $ */
/* $KAME: ipsec.c,v 1.103 2001/05/24 07:14:18 sakane Exp $ */
/*-
@@ -43,6 +43,7 @@
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/domain.h>
+#include <sys/priv.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
@@ -75,6 +76,7 @@
#include <netinet/icmp6.h>
#endif
+#include <sys/types.h>
#include <netipsec/ipsec.h>
#ifdef INET6
#include <netipsec/ipsec6.h>
@@ -92,6 +94,8 @@
#include <machine/in_cksum.h>
+#include <opencrypto/cryptodev.h>
+
#ifdef IPSEC_DEBUG
int ipsec_debug = 1;
#else
@@ -99,7 +103,7 @@
#endif
/* NB: name changed so netstat doesn't use it */
-struct newipsecstat newipsecstat;
+struct ipsecstat ipsec4stat;
int ip4_ah_offsetmask = 0; /* maybe IP_DF? */
int ip4_ipsec_dfbit = 0; /* DF bit on encap. 0: clear 1: set 2: copy */
int ip4_esp_trans_deflev = IPSEC_LEVEL_USE;
@@ -116,7 +120,7 @@
* -1 require software support
* 0 take anything
*/
-int crypto_support = 0;
+int crypto_support = CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE;
SYSCTL_DECL(_net_inet_ipsec);
@@ -146,9 +150,27 @@
SYSCTL_INT(_net_inet_ipsec, OID_AUTO,
crypto_support, CTLFLAG_RW, &crypto_support,0, "");
SYSCTL_STRUCT(_net_inet_ipsec, OID_AUTO,
- ipsecstats, CTLFLAG_RD, &newipsecstat, newipsecstat, "");
+ ipsecstats, CTLFLAG_RD, &ipsec4stat, ipsecstat, "");
-#ifdef INET6
+#ifdef REGRESSION
+/*
+ * When set to 1, IPsec will send packets with the same sequence number.
+ * This allows to verify if the other side has proper replay attacks detection.
+ */
+int ipsec_replay = 0;
+SYSCTL_INT(_net_inet_ipsec, OID_AUTO, test_replay, CTLFLAG_RW, &ipsec_replay, 0,
+ "Emulate replay attack");
+/*
+ * When set 1, IPsec will send packets with corrupted HMAC.
+ * This allows to verify if the other side properly detects modified packets.
+ */
+int ipsec_integrity = 0;
+SYSCTL_INT(_net_inet_ipsec, OID_AUTO, test_integrity, CTLFLAG_RW,
+ &ipsec_integrity, 0, "Emulate man-in-the-middle attack");
+#endif
+
+#ifdef INET6
+struct ipsecstat ipsec6stat;
int ip6_esp_trans_deflev = IPSEC_LEVEL_USE;
int ip6_esp_net_deflev = IPSEC_LEVEL_USE;
int ip6_ah_trans_deflev = IPSEC_LEVEL_USE;
@@ -179,6 +201,8 @@
debug, CTLFLAG_RW, &ipsec_debug, 0, "");
SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ESP_RANDPAD,
esp_randpad, CTLFLAG_RW, &ip6_esp_randpad, 0, "");
+SYSCTL_STRUCT(_net_inet6_ipsec6, IPSECCTL_STATS,
+ ipsecstats, CTLFLAG_RD, &ipsec6stat, ipsecstat, "");
#endif /* INET6 */
static int ipsec4_setspidx_inpcb __P((struct mbuf *, struct inpcb *pcb));
@@ -431,7 +455,7 @@
sp = ipsec_getpolicybysock(m, dir, inp, error);
if (sp == NULL) {
IPSEC_ASSERT(*error != 0, ("getpolicy failed w/o error"));
- newipsecstat.ips_out_inval++;
+ ipsec4stat.ips_out_inval++;
return NULL;
}
IPSEC_ASSERT(*error == 0, ("sp w/ error set to %u", *error));
@@ -441,7 +465,7 @@
printf("%s: invalid policy %u\n", __func__, sp->policy);
/* fall thru... */
case IPSEC_POLICY_DISCARD:
- newipsecstat.ips_out_polvio++;
+ ipsec4stat.ips_out_polvio++;
*error = -EINVAL; /* packet is discarded by caller */
break;
case IPSEC_POLICY_BYPASS:
@@ -732,6 +756,7 @@
int off, nxt;
struct tcphdr th;
struct udphdr uh;
+ struct icmp6_hdr ih;
/* sanity check */
if (m == NULL)
@@ -772,6 +797,15 @@
((struct sockaddr_in6 *)&spidx->dst)->sin6_port = uh.uh_dport;
break;
case IPPROTO_ICMPV6:
+ spidx->ul_proto = nxt;
+ if (off + sizeof(struct icmp6_hdr) > m->m_pkthdr.len)
+ break;
+ m_copydata(m, off, sizeof(ih), (caddr_t)&ih);
+ ((struct sockaddr_in6 *)&spidx->src)->sin6_port =
+ htons((uint16_t)ih.icmp6_type);
+ ((struct sockaddr_in6 *)&spidx->dst)->sin6_port =
+ htons((uint16_t)ih.icmp6_code);
+ break;
default:
/* XXX intermediate headers??? */
spidx->ul_proto = nxt;
@@ -1432,7 +1466,7 @@
if (sp != NULL) {
result = ipsec_in_reject(sp, m);
if (result)
- newipsecstat.ips_in_polvio++;
+ ipsec4stat.ips_in_polvio++;
KEY_FREESP(&sp);
} else {
result = 0; /* XXX should be panic ?
@@ -1472,7 +1506,7 @@
if (sp != NULL) {
result = ipsec_in_reject(sp, m);
if (result)
- newipsecstat.ips_in_polvio++;
+ ipsec6stat.ips_in_polvio++;
KEY_FREESP(&sp);
} else {
result = 0;
@@ -1814,6 +1848,7 @@
unsigned char *ucp = (unsigned char *) &ina;
static int i = 3;
+ /* XXX-BZ returns static buffer. */
i = (i + 1) % 4;
sprintf(buf[i], "%d.%d.%d.%d", ucp[0] & 0xff, ucp[1] & 0xff,
ucp[2] & 0xff, ucp[3] & 0xff);
@@ -1824,15 +1859,18 @@
char *
ipsec_address(union sockaddr_union* sa)
{
+#ifdef INET6
+ char ip6buf[INET6_ADDRSTRLEN];
+#endif
switch (sa->sa.sa_family) {
-#if INET
+#ifdef INET
case AF_INET:
return inet_ntoa4(sa->sin.sin_addr);
#endif /* INET */
-#if INET6
+#ifdef INET6
case AF_INET6:
- return ip6_sprintf(&sa->sin6.sin6_addr);
+ return ip6_sprintf(ip6buf, &sa->sin6.sin6_addr);
#endif /* INET6 */
default:
Index: ipsec6.h
===================================================================
RCS file: /home/cvs/src/sys/netipsec/ipsec6.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipsec/ipsec6.h -L sys/netipsec/ipsec6.h -u -r1.1.1.1 -r1.2
--- sys/netipsec/ipsec6.h
+++ sys/netipsec/ipsec6.h
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/netipsec/ipsec6.h,v 1.2 2005/01/07 01:45:46 imp Exp $ */
+/* $FreeBSD: src/sys/netipsec/ipsec6.h,v 1.3 2007/07/01 11:38:29 gnn Exp $ */
/* $KAME: ipsec.h,v 1.44 2001/03/23 08:08:47 itojun Exp $ */
/*-
@@ -41,6 +41,7 @@
#include <netipsec/keydb.h>
#ifdef _KERNEL
+extern struct ipsecstat ipsec6stat;
extern int ip6_esp_trans_deflev;
extern int ip6_esp_net_deflev;
extern int ip6_ah_trans_deflev;
@@ -50,15 +51,6 @@
struct inpcb;
-/* KAME compatibility shims */
-#define ipsec6_getpolicybyaddr ipsec_getpolicybyaddr
-#define ipsec6_getpolicybysock ipsec_getpolicybysock
-#define ipsec6stat newipsecstat
-#define out_inval ips_out_inval
-#define in_polvio ips_in_polvio
-#define out_polvio ips_out_polvio
-#define key_freesp(_x) KEY_FREESP(&_x)
-
extern int ipsec6_delete_pcbpolicy __P((struct inpcb *));
extern int ipsec6_set_policy __P((struct inpcb *inp, int optname,
caddr_t request, size_t len, int priv));
Index: key_debug.c
===================================================================
RCS file: /home/cvs/src/sys/netipsec/key_debug.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipsec/key_debug.c -L sys/netipsec/key_debug.c -u -r1.1.1.1 -r1.2
--- sys/netipsec/key_debug.c
+++ sys/netipsec/key_debug.c
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/netipsec/key_debug.c,v 1.3 2005/01/07 01:45:46 imp Exp $ */
+/* $FreeBSD: src/sys/netipsec/key_debug.c,v 1.5 2007/07/01 11:38:29 gnn Exp $ */
/* $KAME: key_debug.c,v 1.26 2001/06/27 10:46:50 sakane Exp $ */
/*-
@@ -73,7 +73,7 @@
#endif
#ifndef _KERNEL
-#define panic(param) { printf(param); exit(-1); }
+#define panic(fmt, ...) { printf(fmt, ## __VA_ARGS__); exit(-1); }
#endif
/* NOTE: host byte order */
@@ -588,7 +588,7 @@
if (sav->lft_s != NULL)
kdebug_sadb_lifetime((struct sadb_ext *)sav->lft_s);
-#if notyet
+#ifdef notyet
/* XXX: misc[123] ? */
#endif
Index: xform_ah.c
===================================================================
RCS file: /home/cvs/src/sys/netipsec/xform_ah.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/netipsec/xform_ah.c -L sys/netipsec/xform_ah.c -u -r1.2 -r1.3
--- sys/netipsec/xform_ah.c
+++ sys/netipsec/xform_ah.c
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/netipsec/xform_ah.c,v 1.7.2.1 2006/03/23 23:24:33 sam Exp $ */
+/* $FreeBSD: src/sys/netipsec/xform_ah.c,v 1.15 2007/08/06 14:26:02 rwatson Exp $ */
/* $OpenBSD: ip_ah.c,v 1.63 2001/06/26 06:18:58 angelos Exp $ */
/*-
* The authors of this code are John Ioannidis (ji at tla.org),
@@ -81,11 +81,11 @@
sizeof (struct ah) : sizeof (struct ah) + sizeof (u_int32_t))
/*
* Return authenticator size in bytes. The old protocol is known
- * to use a fixed 16-byte authenticator. The new algorithm gets
- * this size from the xform but is (currently) always 12.
+ * to use a fixed 16-byte authenticator. The new algorithm use 12-byte
+ * authenticator.
*/
#define AUTHSIZE(sav) \
- ((sav->flags & SADB_X_EXT_OLD) ? 16 : (sav)->tdb_authalgxform->authsize)
+ ((sav->flags & SADB_X_EXT_OLD) ? 16 : AH_HMAC_HASHLEN)
int ah_enable = 1; /* control flow of packets with AH */
int ah_cleartos = 1; /* clear ip_tos when doing AH calc */
@@ -110,17 +110,17 @@
struct auth_hash *
ah_algorithm_lookup(int alg)
{
- if (alg >= AH_ALG_MAX)
+ if (alg > SADB_AALG_MAX)
return NULL;
switch (alg) {
case SADB_X_AALG_NULL:
return &auth_hash_null;
case SADB_AALG_MD5HMAC:
- return &auth_hash_hmac_md5_96;
+ return &auth_hash_hmac_md5;
case SADB_AALG_SHA1HMAC:
- return &auth_hash_hmac_sha1_96;
+ return &auth_hash_hmac_sha1;
case SADB_X_AALG_RIPEMD160HMAC:
- return &auth_hash_hmac_ripemd_160_96;
+ return &auth_hash_hmac_ripemd_160;
case SADB_X_AALG_MD5:
return &auth_hash_key_md5;
case SADB_X_AALG_SHA:
@@ -201,7 +201,8 @@
bzero(cria, sizeof (*cria));
cria->cri_alg = sav->tdb_authalgxform->type;
cria->cri_klen = _KEYBITS(sav->key_auth);
- cria->cri_key = _KEYBUF(sav->key_auth);
+ cria->cri_key = sav->key_auth->key_data;
+ cria->cri_mlen = AUTHSIZE(sav);
return 0;
}
@@ -231,7 +232,7 @@
int err;
if (sav->key_auth)
- bzero(_KEYBUF(sav->key_auth), _KEYLEN(sav->key_auth));
+ bzero(sav->key_auth->key_data, _KEYLEN(sav->key_auth));
err = crypto_freesession(sav->tdb_cryptoid);
sav->tdb_cryptoid = 0;
@@ -622,8 +623,8 @@
/* Authentication operation. */
crda->crd_alg = ahx->type;
- crda->crd_key = _KEYBUF(sav->key_auth);
crda->crd_klen = _KEYBITS(sav->key_auth);
+ crda->crd_key = sav->key_auth->key_data;
/* Find out if we've already done crypto. */
for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, NULL);
@@ -764,8 +765,10 @@
if (sav->tdb_cryptoid != 0)
sav->tdb_cryptoid = crp->crp_sid;
- if (crp->crp_etype == EAGAIN)
- return crypto_dispatch(crp);
+ if (crp->crp_etype == EAGAIN) {
+ error = crypto_dispatch(crp);
+ return error;
+ }
ahstat.ahs_noxform++;
DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype));
@@ -857,7 +860,6 @@
IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag);
KEY_FREESAV(&sav);
-
return error;
bad:
if (sav)
@@ -992,7 +994,11 @@
error = EINVAL;
goto bad;
}
- sav->replay->count++;
+#ifdef REGRESSION
+ /* Emulate replay attack when ipsec_replay is TRUE. */
+ if (!ipsec_replay)
+#endif
+ sav->replay->count++;
ah->ah_seq = htonl(sav->replay->count);
}
@@ -1014,7 +1020,7 @@
/* Authentication operation. */
crda->crd_alg = ahx->type;
- crda->crd_key = _KEYBUF(sav->key_auth);
+ crda->crd_key = sav->key_auth->key_data;
crda->crd_klen = _KEYBITS(sav->key_auth);
/* Allocate IPsec-specific opaque crypto info. */
@@ -1140,7 +1146,8 @@
if (crp->crp_etype == EAGAIN) {
KEY_FREESAV(&sav);
IPSECREQUEST_UNLOCK(isr);
- return crypto_dispatch(crp);
+ error = crypto_dispatch(crp);
+ return error;
}
ahstat.ahs_noxform++;
@@ -1168,11 +1175,24 @@
free(tc, M_XDATA);
crypto_freereq(crp);
+#ifdef REGRESSION
+ /* Emulate man-in-the-middle attack when ipsec_integrity is TRUE. */
+ if (ipsec_integrity) {
+ int alen;
+
+ /*
+ * Corrupt HMAC if we want to test integrity verification of
+ * the other side.
+ */
+ alen = AUTHSIZE(sav);
+ m_copyback(m, m->m_pkthdr.len - alen, alen, ipseczeroes);
+ }
+#endif
+
/* NB: m is reclaimed by ipsec_process_done. */
err = ipsec_process_done(m, isr);
KEY_FREESAV(&sav);
IPSECREQUEST_UNLOCK(isr);
-
return err;
bad:
if (sav)
Index: ipsec_mbuf.c
===================================================================
RCS file: /home/cvs/src/sys/netipsec/ipsec_mbuf.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/netipsec/ipsec_mbuf.c -L sys/netipsec/ipsec_mbuf.c -u -r1.2 -r1.3
--- sys/netipsec/ipsec_mbuf.c
+++ sys/netipsec/ipsec_mbuf.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/netipsec/ipsec_mbuf.c,v 1.10.8.1 2006/03/23 23:24:32 sam Exp $
+ * $FreeBSD: src/sys/netipsec/ipsec_mbuf.c,v 1.13 2007/07/01 11:38:29 gnn Exp $
*/
/*
@@ -88,7 +88,7 @@
return (NULL);
n->m_next = m->m_next; /* splice new mbuf */
m->m_next = n;
- newipsecstat.ips_mbinserted++;
+ ipsec4stat.ips_mbinserted++;
if (hlen <= M_TRAILINGSPACE(m) + remain) {
/*
* New header fits in the old mbuf if we copy
@@ -122,7 +122,7 @@
/* splice in second mbuf */
n2->m_next = n->m_next;
n->m_next = n2;
- newipsecstat.ips_mbinserted++;
+ ipsec4stat.ips_mbinserted++;
} else {
memcpy(mtod(n, caddr_t) + hlen,
mtod(m, caddr_t) + skip, remain);
@@ -238,7 +238,7 @@
/* Remove the header and associated data from the mbuf. */
if (roff == 0) {
/* The header was at the beginning of the mbuf */
- newipsecstat.ips_input_front++;
+ ipsec4stat.ips_input_front++;
m_adj(m1, hlen);
if ((m1->m_flags & M_PKTHDR) == 0)
m->m_pkthdr.len -= hlen;
@@ -250,7 +250,7 @@
* so first let's remove the remainder of the header from
* the beginning of the remainder of the mbuf chain, if any.
*/
- newipsecstat.ips_input_end++;
+ ipsec4stat.ips_input_end++;
if (roff + hlen > m1->m_len) {
/* Adjust the next mbuf by the remainder */
m_adj(m1->m_next, roff + hlen - m1->m_len);
@@ -275,7 +275,7 @@
* The header lies in the "middle" of the mbuf; copy
* the remainder of the mbuf down over the header.
*/
- newipsecstat.ips_input_middle++;
+ ipsec4stat.ips_input_middle++;
bcopy(mtod(m1, u_char *) + roff + hlen,
mtod(m1, u_char *) + roff,
m1->m_len - (roff + hlen));
Index: keysock.c
===================================================================
RCS file: /home/cvs/src/sys/netipsec/keysock.c,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -L sys/netipsec/keysock.c -L sys/netipsec/keysock.c -u -r1.1.1.2 -r1.2
--- sys/netipsec/keysock.c
+++ sys/netipsec/keysock.c
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/netipsec/keysock.c,v 1.10.2.2 2006/01/27 21:50:11 bz Exp $ */
+/* $FreeBSD: src/sys/netipsec/keysock.c,v 1.18.2.2 2007/11/20 09:35:15 bz Exp $ */
/* $KAME: keysock.c,v 1.25 2001/08/13 20:07:41 itojun Exp $ */
/*-
@@ -43,6 +43,7 @@
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
+#include <sys/priv.h>
#include <sys/protosw.h>
#include <sys/signalvar.h>
#include <sys/socket.h>
@@ -81,7 +82,6 @@
{
struct sadb_msg *msg;
int len, error = 0;
- int s;
if (m == 0)
panic("%s: NULL pointer was passed.\n", __func__);
@@ -116,11 +116,8 @@
goto end;
}
- /*XXX giant lock*/
- s = splnet();
error = key_parse(m, so);
m = NULL;
- splx(s);
end:
if (m)
m_freem(m);
@@ -213,15 +210,19 @@
while (tlen > 0) {
if (tlen == len) {
MGETHDR(n, M_DONTWAIT, MT_DATA);
+ if (n == NULL) {
+ pfkeystat.in_nomem++;
+ return ENOBUFS;
+ }
n->m_len = MHLEN;
} else {
MGET(n, M_DONTWAIT, MT_DATA);
+ if (n == NULL) {
+ pfkeystat.in_nomem++;
+ return ENOBUFS;
+ }
n->m_len = MLEN;
}
- if (!n) {
- pfkeystat.in_nomem++;
- return ENOBUFS;
- }
if (tlen >= MCLBYTES) { /*XXX better threshold? */
MCLGET(n, M_DONTWAIT);
if ((n->m_flags & M_EXT) == 0) {
@@ -278,22 +279,18 @@
pfkeystat.in_total++;
pfkeystat.in_bytes += m->m_pkthdr.len;
if (m->m_len < sizeof(struct sadb_msg)) {
-#if 1
m = m_pullup(m, sizeof(struct sadb_msg));
if (m == NULL) {
pfkeystat.in_nomem++;
return ENOBUFS;
}
-#else
- /* don't bother pulling it up just for stats */
-#endif
}
if (m->m_len >= sizeof(struct sadb_msg)) {
struct sadb_msg *msg;
msg = mtod(m, struct sadb_msg *);
pfkeystat.in_msgtype[msg->sadb_msg_type]++;
}
-
+ mtx_lock(&rawcb_mtx);
LIST_FOREACH(rp, &rawcb_list, list)
{
if (rp->rcb_proto.sp_family != PF_KEY)
@@ -344,11 +341,13 @@
if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) {
m_freem(m);
pfkeystat.in_nomem++;
+ mtx_unlock(&rawcb_mtx);
return ENOBUFS;
}
if ((error = key_sendup0(rp, n, 0)) != 0) {
m_freem(m);
+ mtx_unlock(&rawcb_mtx);
return error;
}
@@ -362,6 +361,7 @@
error = 0;
m_freem(m);
}
+ mtx_unlock(&rawcb_mtx);
return error;
}
@@ -369,14 +369,10 @@
* key_abort()
* derived from net/rtsock.c:rts_abort()
*/
-static int
+static void
key_abort(struct socket *so)
{
- int s, error;
- s = splnet();
- error = raw_usrreqs.pru_abort(so);
- splx(s);
- return error;
+ raw_usrreqs.pru_abort(so);
}
/*
@@ -387,29 +383,27 @@
key_attach(struct socket *so, int proto, struct thread *td)
{
struct keycb *kp;
- int s, error;
+ int error;
+
+ KASSERT(so->so_pcb == NULL, ("key_attach: so_pcb != NULL"));
- if (sotorawcb(so) != 0)
- return EISCONN; /* XXX panic? */
- kp = (struct keycb *)malloc(sizeof *kp, M_PCB, M_WAITOK|M_ZERO); /* XXX */
+ if (td != NULL) {
+ error = priv_check(td, PRIV_NET_RAW);
+ if (error)
+ return error;
+ }
+
+ /* XXX */
+ MALLOC(kp, struct keycb *, sizeof *kp, M_PCB, M_WAITOK | M_ZERO);
if (kp == 0)
return ENOBUFS;
- /*
- * The splnet() is necessary to block protocols from sending
- * error notifications (like RTM_REDIRECT or RTM_LOSING) while
- * this PCB is extant but incompletely initialized.
- * Probably we should try to do more of this work beforehand and
- * eliminate the spl.
- */
- s = splnet();
so->so_pcb = (caddr_t)kp;
- error = raw_usrreqs.pru_attach(so, proto, td);
+ error = raw_attach(so, proto);
kp = (struct keycb *)sotorawcb(so);
if (error) {
free(kp, M_PCB);
so->so_pcb = (caddr_t) 0;
- splx(s);
return error;
}
@@ -423,7 +417,6 @@
soisconnected(so);
so->so_options |= SO_USELOOPBACK;
- splx(s);
return 0;
}
@@ -434,11 +427,18 @@
static int
key_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
{
- int s, error;
- s = splnet();
- error = raw_usrreqs.pru_bind(so, nam, td); /* xxx just EINVAL */
- splx(s);
- return error;
+ return EINVAL;
+}
+
+/*
+ * key_close()
+ * derived from net/rtsock.c:rts_close().
+ */
+static void
+key_close(struct socket *so)
+{
+
+ raw_usrreqs.pru_close(so);
}
/*
@@ -448,35 +448,26 @@
static int
key_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
{
- int s, error;
- s = splnet();
- error = raw_usrreqs.pru_connect(so, nam, td); /* XXX just EINVAL */
- splx(s);
- return error;
+ return EINVAL;
}
/*
* key_detach()
* derived from net/rtsock.c:rts_detach()
*/
-static int
+static void
key_detach(struct socket *so)
{
struct keycb *kp = (struct keycb *)sotorawcb(so);
- int s, error;
- s = splnet();
- if (kp != 0) {
- if (kp->kp_raw.rcb_proto.sp_protocol
- == PF_KEY) /* XXX: AF_KEY */
- key_cb.key_count--;
- key_cb.any_count--;
+ KASSERT(kp != NULL, ("key_detach: kp == NULL"));
+ if (kp->kp_raw.rcb_proto.sp_protocol
+ == PF_KEY) /* XXX: AF_KEY */
+ key_cb.key_count--;
+ key_cb.any_count--;
- key_freereg(so);
- }
- error = raw_usrreqs.pru_detach(so);
- splx(s);
- return error;
+ key_freereg(so);
+ raw_usrreqs.pru_detach(so);
}
/*
@@ -486,11 +477,7 @@
static int
key_disconnect(struct socket *so)
{
- int s, error;
- s = splnet();
- error = raw_usrreqs.pru_disconnect(so);
- splx(s);
- return error;
+ return(raw_usrreqs.pru_disconnect(so));
}
/*
@@ -500,11 +487,7 @@
static int
key_peeraddr(struct socket *so, struct sockaddr **nam)
{
- int s, error;
- s = splnet();
- error = raw_usrreqs.pru_peeraddr(so, nam);
- splx(s);
- return error;
+ return(raw_usrreqs.pru_peeraddr(so, nam));
}
/*
@@ -515,11 +498,7 @@
key_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
struct mbuf *control, struct thread *td)
{
- int s, error;
- s = splnet();
- error = raw_usrreqs.pru_send(so, flags, m, nam, control, td);
- splx(s);
- return error;
+ return(raw_usrreqs.pru_send(so, flags, m, nam, control, td));
}
/*
@@ -529,11 +508,7 @@
static int
key_shutdown(struct socket *so)
{
- int s, error;
- s = splnet();
- error = raw_usrreqs.pru_shutdown(so);
- splx(s);
- return error;
+ return(raw_usrreqs.pru_shutdown(so));
}
/*
@@ -543,11 +518,7 @@
static int
key_sockaddr(struct socket *so, struct sockaddr **nam)
{
- int s, error;
- s = splnet();
- error = raw_usrreqs.pru_sockaddr(so, nam);
- splx(s);
- return error;
+ return(raw_usrreqs.pru_sockaddr(so, nam));
}
struct pr_usrreqs key_usrreqs = {
@@ -561,6 +532,7 @@
.pru_send = key_send,
.pru_shutdown = key_shutdown,
.pru_sockaddr = key_sockaddr,
+ .pru_close = key_close,
};
/* sysctl */
Index: keysock.h
===================================================================
RCS file: /home/cvs/src/sys/netipsec/keysock.h,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -L sys/netipsec/keysock.h -L sys/netipsec/keysock.h -u -r1.1.1.2 -r1.2
--- sys/netipsec/keysock.h
+++ sys/netipsec/keysock.h
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/netipsec/keysock.h,v 1.2.2.1 2006/01/27 21:50:11 bz Exp $ */
+/* $FreeBSD: src/sys/netipsec/keysock.h,v 1.3 2006/01/21 10:44:34 bz Exp $ */
/* $KAME: keysock.h,v 1.8 2000/03/27 05:11:06 sumikawa Exp $ */
/*-
Index: xform.h
===================================================================
RCS file: /home/cvs/src/sys/netipsec/xform.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/netipsec/xform.h -L sys/netipsec/xform.h -u -r1.2 -r1.3
--- sys/netipsec/xform.h
+++ sys/netipsec/xform.h
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/netipsec/xform.h,v 1.2.2.1 2006/04/01 15:22:44 bz Exp $ */
+/* $FreeBSD: src/sys/netipsec/xform.h,v 1.3 2006/03/30 18:57:04 bz Exp $ */
/* $OpenBSD: ip_ipsp.h,v 1.119 2002/03/14 01:27:11 millert Exp $ */
/*-
* The authors of this code are John Ioannidis (ji at tla.org),
Index: xform_tcp.c
===================================================================
RCS file: /home/cvs/src/sys/netipsec/xform_tcp.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipsec/xform_tcp.c -L sys/netipsec/xform_tcp.c -u -r1.1.1.1 -r1.2
--- sys/netipsec/xform_tcp.c
+++ sys/netipsec/xform_tcp.c
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/netipsec/xform_tcp.c,v 1.4 2005/01/07 01:45:46 imp Exp $ */
+/* $FreeBSD: src/sys/netipsec/xform_tcp.c,v 1.5 2006/03/25 13:38:52 gnn Exp $ */
/*-
* Copyright (c) 2003 Bruce M. Simpson <bms at spc.org>
@@ -117,7 +117,7 @@
{
if (sav->key_auth)
- bzero(_KEYBUF(sav->key_auth), _KEYLEN(sav->key_auth));
+ bzero(sav->key_auth->key_data, _KEYLEN(sav->key_auth));
sav->tdb_cryptoid = 0;
sav->tdb_authalgxform = NULL;
Index: xform_esp.c
===================================================================
RCS file: /home/cvs/src/sys/netipsec/xform_esp.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L sys/netipsec/xform_esp.c -L sys/netipsec/xform_esp.c -u -r1.3 -r1.4
--- sys/netipsec/xform_esp.c
+++ sys/netipsec/xform_esp.c
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/netipsec/xform_esp.c,v 1.10 2005/01/07 01:45:46 imp Exp $ */
+/* $FreeBSD: src/sys/netipsec/xform_esp.c,v 1.20 2007/08/06 14:26:02 rwatson Exp $ */
/* $OpenBSD: ip_esp.c,v 1.69 2001/06/26 06:18:59 angelos Exp $ */
/*-
* The authors of this code are John Ioannidis (ji at tla.org),
@@ -113,6 +113,8 @@
return &enc_xform_skipjack;
case SADB_EALG_NULL:
return &enc_xform_null;
+ case SADB_X_EALG_CAMELLIACBC:
+ return &enc_xform_camellia;
}
return NULL;
}
@@ -215,7 +217,7 @@
bzero(&crie, sizeof (crie));
crie.cri_alg = sav->tdb_encalgxform->type;
crie.cri_klen = _KEYBITS(sav->key_enc);
- crie.cri_key = _KEYBUF(sav->key_enc);
+ crie.cri_key = sav->key_enc->key_data;
/* XXX Rounds ? */
if (sav->tdb_authalgxform && sav->tdb_encalgxform) {
@@ -248,7 +250,7 @@
int error = ah_zeroize(sav);
if (sav->key_enc)
- bzero(_KEYBUF(sav->key_enc), _KEYLEN(sav->key_enc));
+ bzero(sav->key_enc->key_data, _KEYLEN(sav->key_enc));
if (sav->iv) {
free(sav->iv, M_XDATA);
sav->iv = NULL;
@@ -329,7 +331,7 @@
}
/* Update the counters */
- espstat.esps_ibytes += m->m_pkthdr.len - skip - hlen - alen;
+ espstat.esps_ibytes += m->m_pkthdr.len - (skip + hlen + alen);
/* Find out if we've already done crypto */
for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, NULL);
@@ -381,7 +383,7 @@
crda->crd_inject = m->m_pkthdr.len - alen;
crda->crd_alg = esph->type;
- crda->crd_key = _KEYBUF(sav->key_auth);
+ crda->crd_key = sav->key_auth->key_data;
crda->crd_klen = _KEYBITS(sav->key_auth);
/* Copy the authenticator */
@@ -418,7 +420,7 @@
crde->crd_inject = skip + hlen - sav->ivlen;
crde->crd_alg = espx->type;
- crde->crd_key = _KEYBUF(sav->key_enc);
+ crde->crd_key = sav->key_enc->key_data;
crde->crd_klen = _KEYBITS(sav->key_enc);
/* XXX Rounds ? */
}
@@ -496,7 +498,8 @@
if (crp->crp_etype == EAGAIN) {
KEY_FREESAV(&sav);
- return crypto_dispatch(crp);
+ error = crypto_dispatch(crp);
+ return error;
}
espstat.esps_noxform++;
@@ -524,13 +527,13 @@
ahstat.ahs_hist[sav->alg_auth]++;
if (mtag == NULL) {
/* Copy the authenticator from the packet */
- m_copydata(m, m->m_pkthdr.len - esph->authsize,
- esph->authsize, aalg);
+ m_copydata(m, m->m_pkthdr.len - AH_HMAC_HASHLEN,
+ AH_HMAC_HASHLEN, aalg);
ptr = (caddr_t) (tc + 1);
/* Verify authenticator */
- if (bcmp(ptr, aalg, esph->authsize) != 0) {
+ if (bcmp(ptr, aalg, AH_HMAC_HASHLEN) != 0) {
DPRINTF(("%s: "
"authentication hash mismatch for packet in SA %s/%08lx\n",
__func__,
@@ -543,7 +546,7 @@
}
/* Remove trailing authenticator */
- m_adj(m, -(esph->authsize));
+ m_adj(m, -AH_HMAC_HASHLEN);
}
/* Release the crypto descriptors */
@@ -753,7 +756,14 @@
/* Initialize ESP header. */
bcopy((caddr_t) &sav->spi, mtod(mo, caddr_t) + roff, sizeof(u_int32_t));
if (sav->replay) {
- u_int32_t replay = htonl(++(sav->replay->count));
+ u_int32_t replay;
+
+#ifdef REGRESSION
+ /* Emulate replay attack when ipsec_replay is TRUE. */
+ if (!ipsec_replay)
+#endif
+ sav->replay->count++;
+ replay = htonl(sav->replay->count);
bcopy((caddr_t) &replay,
mtod(mo, caddr_t) + roff + sizeof(u_int32_t),
sizeof(u_int32_t));
@@ -819,7 +829,7 @@
/* Encryption operation. */
crde->crd_alg = espx->type;
- crde->crd_key = _KEYBUF(sav->key_enc);
+ crde->crd_key = sav->key_enc->key_data;
crde->crd_klen = _KEYBITS(sav->key_enc);
/* XXX Rounds ? */
} else
@@ -858,7 +868,7 @@
/* Authentication operation. */
crda->crd_alg = esph->type;
- crda->crd_key = _KEYBUF(sav->key_auth);
+ crda->crd_key = sav->key_auth->key_data;
crda->crd_klen = _KEYBITS(sav->key_auth);
}
@@ -908,7 +918,8 @@
if (crp->crp_etype == EAGAIN) {
KEY_FREESAV(&sav);
IPSECREQUEST_UNLOCK(isr);
- return crypto_dispatch(crp);
+ error = crypto_dispatch(crp);
+ return error;
}
espstat.esps_noxform++;
@@ -932,11 +943,28 @@
free(tc, M_XDATA);
crypto_freereq(crp);
+#ifdef REGRESSION
+ /* Emulate man-in-the-middle attack when ipsec_integrity is TRUE. */
+ if (ipsec_integrity) {
+ static unsigned char ipseczeroes[AH_HMAC_HASHLEN];
+ struct auth_hash *esph;
+
+ /*
+ * Corrupt HMAC if we want to test integrity verification of
+ * the other side.
+ */
+ esph = sav->tdb_authalgxform;
+ if (esph != NULL) {
+ m_copyback(m, m->m_pkthdr.len - AH_HMAC_HASHLEN,
+ AH_HMAC_HASHLEN, ipseczeroes);
+ }
+ }
+#endif
+
/* NB: m is reclaimed by ipsec_process_done. */
err = ipsec_process_done(m, isr);
KEY_FREESAV(&sav);
IPSECREQUEST_UNLOCK(isr);
-
return err;
bad:
if (sav)
@@ -970,6 +998,7 @@
MAXIV(enc_xform_cast5); /* SADB_X_EALG_CAST128CBC */
MAXIV(enc_xform_skipjack); /* SADB_X_EALG_SKIPJACK */
MAXIV(enc_xform_null); /* SADB_EALG_NULL */
+ MAXIV(enc_xform_camellia); /* SADB_X_EALG_CAMELLIACBC */
xform_register(&esp_xformsw);
#undef MAXIV
Index: xform_ipcomp.c
===================================================================
RCS file: /home/cvs/src/sys/netipsec/xform_ipcomp.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/netipsec/xform_ipcomp.c -L sys/netipsec/xform_ipcomp.c -u -r1.2 -r1.3
--- sys/netipsec/xform_ipcomp.c
+++ sys/netipsec/xform_ipcomp.c
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/netipsec/xform_ipcomp.c,v 1.8.2.1 2006/03/23 23:24:33 sam Exp $ */
+/* $FreeBSD: src/sys/netipsec/xform_ipcomp.c,v 1.11 2007/08/06 14:26:02 rwatson Exp $ */
/* $OpenBSD: ip_ipcomp.c,v 1.1 2001/07/05 12:08:52 jjbg Exp $ */
/*-
@@ -249,7 +249,8 @@
if (crp->crp_etype == EAGAIN) {
KEY_FREESAV(&sav);
- return crypto_dispatch(crp);
+ error = crypto_dispatch(crp);
+ return error;
}
ipcompstat.ipcomps_noxform++;
@@ -519,7 +520,8 @@
if (crp->crp_etype == EAGAIN) {
KEY_FREESAV(&sav);
IPSECREQUEST_UNLOCK(isr);
- return crypto_dispatch(crp);
+ error = crypto_dispatch(crp);
+ return error;
}
ipcompstat.ipcomps_noxform++;
DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype));
@@ -572,7 +574,6 @@
error = ipsec_process_done(m, isr);
KEY_FREESAV(&sav);
IPSECREQUEST_UNLOCK(isr);
-
return error;
bad:
if (sav)
Index: ipsec.h
===================================================================
RCS file: /home/cvs/src/sys/netipsec/ipsec.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/netipsec/ipsec.h -L sys/netipsec/ipsec.h -u -r1.2 -r1.3
--- sys/netipsec/ipsec.h
+++ sys/netipsec/ipsec.h
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/netipsec/ipsec.h,v 1.8.2.1 2006/03/23 23:24:32 sam Exp $ */
+/* $FreeBSD: src/sys/netipsec/ipsec.h,v 1.13 2007/07/01 11:38:29 gnn Exp $ */
/* $KAME: ipsec.h,v 1.53 2001/11/20 08:32:38 itojun Exp $ */
/*-
@@ -205,7 +205,7 @@
*/
#define IPSEC_REPLAYWSIZE 32
-/* old statistics for ipsec processing */
+/* statistics for ipsec processing */
struct ipsecstat {
u_quad_t in_success; /* succeeded inbound process */
u_quad_t in_polvio;
@@ -236,10 +236,7 @@
u_quad_t spdcachelookup;
u_quad_t spdcachemiss;
-};
-/* statistics for ipsec processing */
-struct newipsecstat {
u_int32_t ips_in_polvio; /* input: sec policy violation */
u_int32_t ips_out_polvio; /* output: sec policy violation */
u_int32_t ips_out_nosa; /* output: SA unavailable */
@@ -330,8 +327,12 @@
};
extern int ipsec_debug;
+#ifdef REGRESSION
+extern int ipsec_replay;
+extern int ipsec_integrity;
+#endif
-extern struct newipsecstat newipsecstat;
+extern struct ipsecstat ipsec4stat;
extern struct secpolicy ip4_def_policy;
extern int ip4_esp_trans_deflev;
extern int ip4_esp_net_deflev;
@@ -348,10 +349,6 @@
/* for openbsd compatibility */
#define DPRINTF(x) do { if (ipsec_debug) printf x; } while (0)
-/* XXX for KAME code compatibility */
-#define ipsec_pcbconn(_x)
-#define ipsec_pcbdisconn(_x)
-
extern struct ipsecrequest *ipsec_newisr(void);
extern void ipsec_delisr(struct ipsecrequest *);
@@ -413,6 +410,8 @@
extern struct mbuf *m_makespace(struct mbuf *m0, int skip, int hlen, int *off);
extern caddr_t m_pad(struct mbuf *m, int n);
extern int m_striphdr(struct mbuf *m, int skip, int hlen);
+extern int ipsec_filter(struct mbuf **, int);
+extern void ipsec_bpf(struct mbuf *, struct secasvar *, int);
#endif /* _KERNEL */
#ifndef _KERNEL
Index: ipsec_osdep.h
===================================================================
RCS file: /home/cvs/src/sys/netipsec/ipsec_osdep.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipsec/ipsec_osdep.h -L sys/netipsec/ipsec_osdep.h -u -r1.1.1.1 -r1.2
--- sys/netipsec/ipsec_osdep.h
+++ sys/netipsec/ipsec_osdep.h
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/netipsec/ipsec_osdep.h,v 1.2 2005/01/07 01:45:46 imp Exp $ */
+/* $FreeBSD: src/sys/netipsec/ipsec_osdep.h,v 1.6 2007/06/12 00:12:00 rwatson Exp $ */
/* $NetBSD: ipsec_osdep.h,v 1.1 2003/08/13 20:06:51 jonathan Exp $ */
/*-
@@ -211,14 +211,16 @@
/*
* 8. Test for "privileged" socket opened by superuser.
- * FreeBSD tests ((so)->so_cred && (so)->so_cred.cr_uid == 0),
+ * FreeBSD tests ((so)->so_cred != NULL && priv_check_cred((so)->so_cred,
+ * PRIV_NETINET_IPSEC, 0) == 0).
* NetBSD (1.6N) tests (so)->so_uid == 0).
* This difference is wrapped inside the IPSEC_PRIVILEGED_SO() macro.
- *
*/
#ifdef __FreeBSD__
#define IPSEC_IS_PRIVILEGED_SO(_so) \
- ((_so)->so_cred && (_so)->so_cred->cr_uid == 0)
+ ((_so)->so_cred != NULL && \
+ priv_check_cred((_so)->so_cred, PRIV_NETINET_IPSEC, 0) \
+ == 0)
#endif /* __FreeBSD__ */
#ifdef __NetBSD__
Index: key_var.h
===================================================================
RCS file: /home/cvs/src/sys/netipsec/key_var.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipsec/key_var.h -L sys/netipsec/key_var.h -u -r1.1.1.1 -r1.2
--- sys/netipsec/key_var.h
+++ sys/netipsec/key_var.h
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/netipsec/key_var.h,v 1.2 2005/01/07 01:45:46 imp Exp $ */
+/* $FreeBSD: src/sys/netipsec/key_var.h,v 1.3 2006/03/25 13:38:52 gnn Exp $ */
/* $KAME: key_var.h,v 1.11 2001/09/12 23:05:07 sakane Exp $ */
/*-
@@ -66,8 +66,8 @@
#ifdef _KERNEL
#define _ARRAYLEN(p) (sizeof(p)/sizeof(p[0]))
-#define _KEYLEN(key) ((u_int)((key)->sadb_key_bits >> 3))
-#define _KEYBITS(key) ((u_int)((key)->sadb_key_bits))
+#define _KEYLEN(key) ((u_int)((key)->bits >> 3))
+#define _KEYBITS(key) ((u_int)((key)->bits))
#define _KEYBUF(key) ((caddr_t)((caddr_t)(key) + sizeof(struct sadb_key)))
#endif /*_KERNEL*/
Index: ipsec_output.c
===================================================================
RCS file: /home/cvs/src/sys/netipsec/ipsec_output.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipsec/ipsec_output.c -L sys/netipsec/ipsec_output.c -u -r1.1.1.1 -r1.2
--- sys/netipsec/ipsec_output.c
+++ sys/netipsec/ipsec_output.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/netipsec/ipsec_output.c,v 1.10 2004/01/20 22:45:10 sam Exp $
+ * $FreeBSD: src/sys/netipsec/ipsec_output.c,v 1.16 2007/07/19 09:57:54 bz Exp $
*/
/*
@@ -32,6 +32,7 @@
#include "opt_inet.h"
#include "opt_inet6.h"
#include "opt_ipsec.h"
+#include "opt_enc.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -43,6 +44,7 @@
#include <sys/syslog.h>
#include <net/if.h>
+#include <net/pfil.h>
#include <net/route.h>
#include <netinet/in.h>
@@ -154,7 +156,7 @@
* doing further processing.
*/
if (isr->next) {
- newipsecstat.ips_out_bundlesa++;
+ ipsec4stat.ips_out_bundlesa++;
return ipsec4_process_packet(m, isr->next, 0, 0);
}
key_sa_recordxfer(sav, m); /* record data transfer */
@@ -280,7 +282,7 @@
* this packet because it is responsibility for
* upper layer to retransmit the packet.
*/
- newipsecstat.ips_out_nosa++;
+ ipsec4stat.ips_out_nosa++;
goto bad;
}
sav = isr->sav;
@@ -358,6 +360,13 @@
goto bad;
sav = isr->sav;
+
+#ifdef DEV_ENC
+ /* pass the mbuf to enc0 for packet filtering */
+ if ((error = ipsec_filter(&m, PFIL_OUT)) != 0)
+ goto bad;
+#endif
+
if (!tunalready) {
union sockaddr_union *dst = &sav->sah->saidx.dst;
int setdf;
@@ -455,6 +464,11 @@
}
}
+#ifdef DEV_ENC
+ /* pass the mbuf to enc0 for bpf processing */
+ ipsec_bpf(m, sav, AF_INET);
+#endif
+
/*
* Dispatch to the appropriate IPsec transform logic. The
* packet will be returned for transmission after crypto
@@ -500,7 +514,7 @@
ip6 = mtod(m, struct ip6_hdr *);
hlen = sizeof(struct ip6_hdr);
if (m->m_len > hlen) {
- MGETHDR(mh, M_DONTWAIT, MT_HEADER);
+ MGETHDR(mh, M_DONTWAIT, MT_DATA);
if (!mh) {
m_freem(m);
return NULL;
@@ -546,7 +560,7 @@
IPSEC_ASSERT(tun != NULL, ("null tun"));
KEYDEBUG(KEYDEBUG_IPSEC_DATA,
- printf("%s: applyed SP\n", __func__);
+ printf("%s: applied SP\n", __func__);
kdebug_secpolicy(sp));
isr = sp->req;
@@ -559,6 +573,7 @@
*tun = 0;
m = state->m;
+ IPSECREQUEST_LOCK(isr); /* insure SA contents don't change */
isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error);
if (isr == NULL) {
#ifdef notdef
@@ -578,10 +593,15 @@
goto bad;
}
- return (*isr->sav->tdb_xform->xf_output)(m, isr, NULL,
- sizeof (struct ip6_hdr),
- offsetof(struct ip6_hdr, ip6_nxt));
+ error = (*isr->sav->tdb_xform->xf_output)(m, isr, NULL,
+ sizeof (struct ip6_hdr),
+ offsetof(struct ip6_hdr,
+ ip6_nxt));
+ IPSECREQUEST_UNLOCK(isr);
+ return error;
bad:
+ if (isr)
+ IPSECREQUEST_UNLOCK(isr);
if (m)
m_freem(m);
state->m = NULL;
@@ -601,7 +621,7 @@
m_freem(m);
return EINVAL;
}
- IPSEC_ASSERT(m->m_len != sizeof (struct ip6_hdr),
+ IPSEC_ASSERT(m->m_len == sizeof (struct ip6_hdr),
("mbuf wrong size; len %u", m->m_len));
@@ -645,8 +665,8 @@
/* ip6->ip6_plen will be updated in ip6_output() */
}
ip6->ip6_nxt = IPPROTO_IPV6;
- sav->sah->saidx.src.sin6.sin6_addr = ip6->ip6_src;
- sav->sah->saidx.dst.sin6.sin6_addr = ip6->ip6_dst;
+ ip6->ip6_src = sav->sah->saidx.src.sin6.sin6_addr;
+ ip6->ip6_dst = sav->sah->saidx.dst.sin6.sin6_addr;
ip6->ip6_hlim = IPV6_DEFHLIM;
/* XXX Should ip6_src be updated later ? */
@@ -672,7 +692,7 @@
IPSEC_ASSERT(sp != NULL, ("null sp"));
KEYDEBUG(KEYDEBUG_IPSEC_DATA,
- printf("%s: applyed SP\n", __func__);
+ printf("%s: applied SP\n", __func__);
kdebug_secpolicy(sp));
m = state->m;
@@ -684,6 +704,8 @@
if (isr->saidx.mode == IPSEC_MODE_TUNNEL)
break;
}
+
+ IPSECREQUEST_LOCK(isr); /* insure SA contents don't change */
isr = ipsec_nextisr(m, isr, AF_INET6, &saidx, &error);
if (isr == NULL)
goto bad;
@@ -701,14 +723,14 @@
ipseclog((LOG_ERR, "%s: family mismatched between "
"inner and outer, spi=%u\n", __func__,
ntohl(isr->sav->spi)));
- newipsecstat.ips_out_inval++;
+ ipsec6stat.ips_out_inval++;
error = EAFNOSUPPORT;
goto bad;
}
m = ipsec6_splithdr(m);
if (!m) {
- newipsecstat.ips_out_nomem++;
+ ipsec6stat.ips_out_nomem++;
error = ENOMEM;
goto bad;
}
@@ -737,7 +759,7 @@
}
if (state->ro->ro_rt == 0) {
ip6stat.ip6s_noroute++;
- newipsecstat.ips_out_noroute++;
+ ipsec6stat.ips_out_noroute++;
error = EHOSTUNREACH;
goto bad;
}
@@ -751,15 +773,19 @@
m = ipsec6_splithdr(m);
if (!m) {
- newipsecstat.ips_out_nomem++;
+ ipsec6stat.ips_out_nomem++;
error = ENOMEM;
goto bad;
}
ip6 = mtod(m, struct ip6_hdr *);
- return (*isr->sav->tdb_xform->xf_output)(m, isr, NULL,
+ error = (*isr->sav->tdb_xform->xf_output)(m, isr, NULL,
sizeof (struct ip6_hdr),
offsetof(struct ip6_hdr, ip6_nxt));
+ IPSECREQUEST_UNLOCK(isr);
+ return error;
bad:
+ if (isr)
+ IPSECREQUEST_UNLOCK(isr);
if (m)
m_freem(m);
state->m = NULL;
Index: keydb.h
===================================================================
RCS file: /home/cvs/src/sys/netipsec/keydb.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipsec/keydb.h -L sys/netipsec/keydb.h -u -r1.1.1.1 -r1.2
--- sys/netipsec/keydb.h
+++ sys/netipsec/keydb.h
@@ -1,4 +1,4 @@
-/* $FreeBSD: src/sys/netipsec/keydb.h,v 1.5 2005/01/07 01:45:46 imp Exp $ */
+/* $FreeBSD: src/sys/netipsec/keydb.h,v 1.6 2006/03/25 13:38:52 gnn Exp $ */
/* $KAME: keydb.h,v 1.14 2000/08/02 17:58:26 sakane Exp $ */
/*-
@@ -60,14 +60,39 @@
/* see IPSEC_MANUAL_REQID_MAX. */
};
+/*
+ * In order to split out the keydb implementation from that of the
+ * PF_KEY sockets we need to define a few structures that while they
+ * may seem common are likely to diverge over time.
+ */
+
+/* sadb_identity */
+struct secident {
+ u_int16_t type;
+ u_int64_t id;
+};
+
+/* sadb_key */
+struct seckey {
+ u_int16_t bits;
+ char *key_data;
+};
+
+struct seclifetime {
+ u_int32_t allocations;
+ u_int64_t bytes;
+ u_int64_t addtime;
+ u_int64_t usetime;
+};
+
/* Security Association Data Base */
struct secashead {
LIST_ENTRY(secashead) chain;
struct secasindex saidx;
- struct sadb_ident *idents; /* source identity */
- struct sadb_ident *identd; /* destination identity */
+ struct secident *idents; /* source identity */
+ struct secident *identd; /* destination identity */
/* XXX I don't know how to use them. */
u_int8_t state; /* MATURE or DEAD. */
@@ -97,8 +122,8 @@
u_int32_t spi; /* SPI Value, network byte order */
u_int32_t flags; /* holder for SADB_KEY_FLAGS */
- struct sadb_key *key_auth; /* Key for Authentication */
- struct sadb_key *key_enc; /* Key for Encryption */
+ struct seckey *key_auth; /* Key for Authentication */
+ struct seckey *key_enc; /* Key for Encryption */
caddr_t iv; /* Initilization Vector */
u_int ivlen; /* length of IV */
void *sched; /* intermediate encryption key */
@@ -107,9 +132,9 @@
struct secreplay *replay; /* replay prevention */
time_t created; /* for lifetime */
- struct sadb_lifetime *lft_c; /* CURRENT lifetime, it's constant. */
- struct sadb_lifetime *lft_h; /* HARD lifetime */
- struct sadb_lifetime *lft_s; /* SOFT lifetime */
+ struct seclifetime *lft_c; /* CURRENT lifetime, it's constant. */
+ struct seclifetime *lft_h; /* HARD lifetime */
+ struct seclifetime *lft_s; /* SOFT lifetime */
u_int32_t seq; /* sequence number */
pid_t pid; /* message's pid */
More information about the Midnightbsd-cvs
mailing list