summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>1999-07-15 14:15:42 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>1999-07-15 14:15:42 +0000
commit893ba3a842c40c7f5d6f9f14837e0d432dd7767f (patch)
treeb143d604f311079eb8a3f83241ef170196a8f67a /sys
parent7bdb8bc6dd617efd36012f956c9992b1cfa8e85c (diff)
From angelos@, edits by me, demand keying for PF_KEY
Diffstat (limited to 'sys')
-rw-r--r--sys/net/pfkeyv2.c164
-rw-r--r--sys/netinet/ip_ipsp.c59
-rw-r--r--sys/netinet/ip_ipsp.h7
-rw-r--r--sys/netinet/ip_output.c41
4 files changed, 186 insertions, 85 deletions
diff --git a/sys/net/pfkeyv2.c b/sys/net/pfkeyv2.c
index acf9af33e1a..760eae3e409 100644
--- a/sys/net/pfkeyv2.c
+++ b/sys/net/pfkeyv2.c
@@ -94,7 +94,7 @@ void import_key(struct ipsecinit *, struct sadb_key *, int);
void import_lifetime(struct tdb *, struct sadb_lifetime *, int);
void import_sa(struct tdb *, struct sadb_sa *, struct ipsecinit *);
int pfdatatopacket(void *, int, struct mbuf **);
-int pfkeyv2_acquire(void *);
+int pfkeyv2_acquire(struct tdb *, int);
int pfkeyv2_create(struct socket *);
int pfkeyv2_get(struct tdb *, void **, void **);
int pfkeyv2_release(struct socket *);
@@ -1632,9 +1632,8 @@ realret:
}
int
-pfkeyv2_acquire(void *os)
+pfkeyv2_acquire(struct tdb *tdb, int rekey)
{
-#if 0
int rval = 0;
int i, j;
void *p, *headers[SADB_EXT_MAX+1], *buffer = NULL;
@@ -1644,16 +1643,18 @@ pfkeyv2_acquire(void *os)
goto ret;
}
+ /* How large a buffer do we need... */
i = sizeof(struct sadb_msg) + sizeof(struct sadb_address) +
- PADUP(SA_LEN(&os->src.sa)) + sizeof(struct sadb_address) +
- PADUP(SA_LEN(&os->dst.sa)) + sizeof(struct sadb_prop) +
- os->nproposals * sizeof(struct sadb_comb) +
+ PADUP(SA_LEN(&tdb->tdb_src.sa)) + sizeof(struct sadb_address) +
+ PADUP(SA_LEN(&tdb->tdb_dst.sa)) + sizeof(struct sadb_prop) +
+ 1 * sizeof(struct sadb_comb) + /* XXX We only do one proposal for now */
2 * sizeof(struct sadb_ident);
- if (os->rekeysa)
- i += PADUP(os->rekeysa->srcident.bytes) +
- PADUP(os->rekeysa->dstident.bytes);
+ if (rekey)
+ i += PADUP(tdb->tdb_srcid_len) +
+ PADUP(tdb->tdb_dstid_len);
+ /* Allocate */
if (!(p = malloc(i, M_PFKEY, M_DONTWAIT))) {
rval = ENOMEM;
goto ret;
@@ -1668,76 +1669,133 @@ pfkeyv2_acquire(void *os)
p += sizeof(struct sadb_msg);
((struct sadb_msg *)headers[0])->sadb_msg_version = PF_KEY_V2;
((struct sadb_msg *)headers[0])->sadb_msg_type = SADB_ACQUIRE;
- ((struct sadb_msg *)headers[0])->sadb_msg_satype = os->satype;
((struct sadb_msg *)headers[0])->sadb_msg_len = i / sizeof(uint64_t);
((struct sadb_msg *)headers[0])->sadb_msg_seq = pfkeyv2_seq++;
+ j = tdb->tdb_xform->xf_type;
+ switch (j)
+ {
+ case XF_OLD_AH:
+ j = SADB_X_SATYPE_AH_OLD;
+ break;
+
+ case XF_OLD_ESP:
+ j = SADB_X_SATYPE_ESP_OLD;
+ break;
+
+ case XF_NEW_AH:
+ j = SADB_SATYPE_AH;
+ break;
+
+ case XF_NEW_ESP:
+ j = SADB_SATYPE_ESP;
+ break;
+ }
+
+ ((struct sadb_msg *)headers[0])->sadb_msg_satype = j;
+
headers[SADB_EXT_ADDRESS_SRC] = p;
- p += sizeof(struct sadb_address) + PADUP(SA_LEN(&os->src.sa));
- ((struct sadb_address *)headers[SADB_EXT_ADDRESS_SRC])->sadb_address_len = (sizeof(struct sadb_address) + SA_LEN(&os->src.sa) + sizeof(uint64_t) - 1) / sizeof(uint64_t);
- bcopy(&os->src, headers[SADB_EXT_ADDRESS_SRC] + sizeof(struct sadb_address),
- SA_LEN(&os->src.sa));
+ p += sizeof(struct sadb_address) + PADUP(SA_LEN(&tdb->tdb_src.sa));
+ ((struct sadb_address *)headers[SADB_EXT_ADDRESS_SRC])->sadb_address_len = (sizeof(struct sadb_address) + SA_LEN(&tdb->tdb_src.sa) + sizeof(uint64_t) - 1) / sizeof(uint64_t);
+ bcopy(&tdb->tdb_src, headers[SADB_EXT_ADDRESS_SRC] + sizeof(struct sadb_address), SA_LEN(&tdb->tdb_src.sa));
headers[SADB_EXT_ADDRESS_DST] = p;
- p += sizeof(struct sadb_address) + PADUP(SA_LEN(&os->dst.sa));
- ((struct sadb_address *)headers[SADB_EXT_ADDRESS_DST])->sadb_address_len = (sizeof(struct sadb_address) + SA_LEN(&os->dst.sa) + sizeof(uint64_t) - 1) / sizeof(uint64_t);
- bcopy(&os->dst, headers[SADB_EXT_ADDRESS_DST] + sizeof(struct sadb_address),
- SA_LEN(&os->dst.sa));
+ p += sizeof(struct sadb_address) + PADUP(SA_LEN(&tdb->tdb_dst.sa));
+ ((struct sadb_address *)headers[SADB_EXT_ADDRESS_DST])->sadb_address_len = (sizeof(struct sadb_address) + SA_LEN(&tdb->tdb_dst.sa) + sizeof(uint64_t) - 1) / sizeof(uint64_t);
+ bcopy(&tdb->tdb_dst, headers[SADB_EXT_ADDRESS_DST] + sizeof(struct sadb_address), SA_LEN(&tdb->tdb_dst.sa));
headers[SADB_EXT_IDENTITY_SRC] = p;
p += sizeof(struct sadb_ident);
- ((struct sadb_ident *)headers[SADB_EXT_IDENTITY_SRC])->sadb_ident_type = os->srcidenttype;
- ((struct sadb_ident *)headers[SADB_EXT_IDENTITY_SRC])->sadb_ident_id = os->srcidentid;
- if (os->rekeysa) {
- ((struct sadb_ident *)headers[SADB_EXT_IDENTITY_SRC])->sadb_ident_len = (sizeof(struct sadb_ident) + PADUP(os->rekeysa->srcident.bytes)) / sizeof(uint64_t);
- bcopy(os->rekeysa->srcident.data, p, os->rekeysa->srcident.bytes);
- p += PADUP(os->rekeysa->srcident.bytes);
+ ((struct sadb_ident *)headers[SADB_EXT_IDENTITY_SRC])->sadb_ident_type = tdb->tdb_srcid_type;
+
+ /* XXX some day we'll have to deal with real ident_ids for users */
+ ((struct sadb_ident *)headers[SADB_EXT_IDENTITY_SRC])->sadb_ident_id = 0;
+
+ if (rekey) {
+ ((struct sadb_ident *)headers[SADB_EXT_IDENTITY_SRC])->sadb_ident_len = (sizeof(struct sadb_ident) + PADUP(tdb->tdb_srcid_len)) / sizeof(uint64_t);
+ bcopy(tdb->tdb_srcid, p, tdb->tdb_srcid_len);
+ p += PADUP(tdb->tdb_srcid_len);
} else
((struct sadb_ident *)headers[SADB_EXT_IDENTITY_SRC])->sadb_ident_len = (sizeof(struct sadb_ident)) / sizeof(uint64_t);
headers[SADB_EXT_IDENTITY_DST] = p;
p += sizeof(struct sadb_ident);
- ((struct sadb_ident *)headers[SADB_EXT_IDENTITY_SRC])->sadb_ident_type = os->dstidenttype;
- ((struct sadb_ident *)headers[SADB_EXT_IDENTITY_SRC])->sadb_ident_id = os->dstidentid;
- if (os->rekeysa) {
- ((struct sadb_ident *)headers[SADB_EXT_IDENTITY_DST])->sadb_ident_len = (sizeof(struct sadb_ident) + PADUP(os->rekeysa->dstident.bytes)) / sizeof(uint64_t);
- bcopy(os->rekeysa->dstident.data, p, os->rekeysa->dstident.bytes);
- p += PADUP(os->rekeysa->srcident.bytes);
+ ((struct sadb_ident *)headers[SADB_EXT_IDENTITY_DST])->sadb_ident_type = tdb->tdb_dstid_type;
+
+ /* XXX some day we'll have to deal with real ident_ids for users */
+ ((struct sadb_ident *)headers[SADB_EXT_IDENTITY_DST])->sadb_ident_id = 0;
+
+ if (rekey) {
+ ((struct sadb_ident *)headers[SADB_EXT_IDENTITY_DST])->sadb_ident_len = (sizeof(struct sadb_ident) + PADUP(tdb->tdb_dstid_len)) / sizeof(uint64_t);
+ bcopy(tdb->tdb_dstid, p, tdb->tdb_dstid_len);
+ p += PADUP(tdb->tdb_dstid_len);
} else
((struct sadb_ident *)headers[SADB_EXT_IDENTITY_DST])->sadb_ident_len = (sizeof(struct sadb_ident)) / sizeof(uint64_t);
headers[SADB_EXT_PROPOSAL] = p;
p += sizeof(struct sadb_prop);
- ((struct sadb_prop *)headers[SADB_EXT_PROPOSAL])->sadb_prop_len = (sizeof(struct sadb_prop) + sizeof(struct sadb_comb) * os->nproposals) / sizeof(uint64_t);
- ((struct sadb_prop *)headers[SADB_EXT_PROPOSAL])->sadb_prop_num = os->nproposals;
+ ((struct sadb_prop *)headers[SADB_EXT_PROPOSAL])->sadb_prop_len = (sizeof(struct sadb_prop) + sizeof(struct sadb_comb) * 1) / sizeof(uint64_t); /* XXX 1 proposal only */
+ ((struct sadb_prop *)headers[SADB_EXT_PROPOSAL])->sadb_prop_num = 1; /* XXX 1 proposal only */
{
struct sadb_comb *sadb_comb = p;
- struct netsec_sadb_proposal *proposal = os->proposals;
-
- for (j = 0; j < os->nproposals; j++) {
- sadb_comb->sadb_comb_auth = proposal->auth;
- sadb_comb->sadb_comb_encrypt = proposal->encrypt;
- sadb_comb->sadb_comb_flags = proposal->flags;
- sadb_comb->sadb_comb_auth_minbits = proposal->auth_minbits;
- sadb_comb->sadb_comb_auth_maxbits = proposal->auth_maxbits;
- sadb_comb->sadb_comb_encrypt_minbits = proposal->encrypt_minbits;
- sadb_comb->sadb_comb_encrypt_maxbits = proposal->encrypt_maxbits;
- sadb_comb->sadb_comb_soft_allocations = proposal->soft.allocations;
- sadb_comb->sadb_comb_hard_allocations = proposal->hard.allocations;
- sadb_comb->sadb_comb_soft_bytes = proposal->soft.bytes;
- sadb_comb->sadb_comb_hard_bytes = proposal->hard.bytes;
- sadb_comb->sadb_comb_soft_addtime = proposal->soft.addtime;
- sadb_comb->sadb_comb_hard_addtime = proposal->hard.addtime;
- sadb_comb->sadb_comb_soft_usetime = proposal->soft.usetime;
- sadb_comb->sadb_comb_hard_usetime = proposal->hard.usetime;
+
+ /* XXX 1 proposal only */
+ for (j = 0; j < 1; j++) {
+ sadb_comb->sadb_comb_flags = 0;
+
+ if (tdb->tdb_flags & TDBF_PFS)
+ sadb_comb->sadb_comb_flags |= SADB_SAFLAGS_PFS;
+
+ if (tdb->tdb_flags & TDBF_HALFIV)
+ sadb_comb->sadb_comb_flags |= SADB_X_SAFLAGS_HALFIV;
+
+ if (tdb->tdb_flags & TDBF_TUNNELING)
+ sadb_comb->sadb_comb_flags |= SADB_X_SAFLAGS_TUNNEL;
+
+ if (tdb->tdb_authalgxform)
+ {
+ sadb_comb->sadb_comb_auth = tdb->tdb_authalgxform->type;
+ sadb_comb->sadb_comb_auth_minbits = tdb->tdb_authalgxform->keysize * 8;
+ sadb_comb->sadb_comb_auth_maxbits = tdb->tdb_authalgxform->keysize * 8;
+ }
+ else
+ {
+ sadb_comb->sadb_comb_auth = 0;
+ sadb_comb->sadb_comb_auth_minbits = 0;
+ sadb_comb->sadb_comb_auth_maxbits = 0;
+ }
+
+ if (tdb->tdb_encalgxform)
+ {
+ sadb_comb->sadb_comb_encrypt = tdb->tdb_encalgxform->type;
+ sadb_comb->sadb_comb_encrypt_minbits = tdb->tdb_encalgxform->minkey * 8;
+ sadb_comb->sadb_comb_encrypt_maxbits = tdb->tdb_encalgxform->maxkey * 8;
+ }
+ else
+ {
+ sadb_comb->sadb_comb_encrypt = 0;
+ sadb_comb->sadb_comb_encrypt_minbits = 0;
+ sadb_comb->sadb_comb_encrypt_maxbits = 0;
+ }
+
+ sadb_comb->sadb_comb_soft_allocations = tdb->tdb_soft_allocations;
+ sadb_comb->sadb_comb_hard_allocations = tdb->tdb_exp_allocations;
+
+ sadb_comb->sadb_comb_soft_bytes = tdb->tdb_soft_bytes;
+ sadb_comb->sadb_comb_hard_bytes = tdb->tdb_exp_bytes;
+
+ sadb_comb->sadb_comb_soft_addtime = tdb->tdb_soft_timeout;
+ sadb_comb->sadb_comb_hard_addtime = tdb->tdb_exp_timeout;
+
+ sadb_comb->sadb_comb_soft_usetime = tdb->tdb_soft_first_use;
+ sadb_comb->sadb_comb_hard_usetime = tdb->tdb_exp_first_use;
sadb_comb++;
- proposal++;
}
}
if ((rval = pfkeyv2_sendmessage(headers, PFKEYV2_SENDMESSAGE_REGISTERED,
- NULL, os->satype, count))!= 0)
+ NULL, ((struct sadb_msg *)headers[0])->sadb_msg_satype, 1))!= 0) /* XXX notice count of 1 as last arg -- is that right ? */
goto ret;
rval = 0;
@@ -1748,8 +1806,6 @@ ret:
free(buffer, M_PFKEY);
}
return rval;
-#endif
- return 0;
}
int
diff --git a/sys/netinet/ip_ipsp.c b/sys/netinet/ip_ipsp.c
index 54d22e3d5f6..111afee9b8c 100644
--- a/sys/netinet/ip_ipsp.c
+++ b/sys/netinet/ip_ipsp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.c,v 1.48 1999/07/06 20:54:03 ho Exp $ */
+/* $OpenBSD: ip_ipsp.c,v 1.49 1999/07/15 14:15:41 niklas Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -243,7 +243,8 @@ check_ipsec_policy(struct inpcb *inp, u_int32_t daddr)
gw = (struct sockaddr_encap *) (re->re_rt->rt_gateway);
- if (gw->sen_type == SENT_IPSP) {
+ if (gw->sen_type == SENT_IPSP)
+ {
bzero(&sunion, sizeof(sunion));
sunion.sin.sin_family = AF_INET;
sunion.sin.sin_len = sizeof(struct sockaddr_in);
@@ -337,9 +338,9 @@ tdb_add_inp(struct tdb *tdb, struct inpcb *inp)
}
/*
- * Reserve an SPI; the SA is not valid yet though. Zero is reserved as
- * an error return value. If tspi is not zero, we try to allocate that
- * SPI.
+ * Reserve an SPI; the SA is not valid yet though. We use SPI_LOCAL_USE as
+ * an error return value. It'll not be a problem that we also use that
+ * for demand-keying as that is manually specified.
*/
u_int32_t
@@ -350,33 +351,35 @@ reserve_spi(u_int32_t sspi, u_int32_t tspi, union sockaddr_union *src,
u_int32_t spi;
int nums;
- if (tspi <= 255) /* We don't reserve 0 < SPI <= 255 */
+ /* Don't accept ranges only encompassing reserved SPIs. */
+ if (tspi < sspi || tspi <= SPI_RESERVED_MAX)
{
- (*errval) = EEXIST;
+ (*errval) = EINVAL;
return 0;
}
-
- if ((sspi == tspi) && (sspi != 0)) /* Asking for a specific SPI */
+
+ /* Limit the range to not include reserved areas. */
+ if (sspi <= SPI_RESERVED_MAX)
+ sspi = SPI_RESERVED_MAX + 1;
+
+ if (sspi == tspi) /* Asking for a specific SPI */
nums = 1;
else
nums = 50; /* XXX figure out some good value */
while (nums--)
{
- if (tspi != 0) /* SPIRANGE was defined */
+ if (sspi == tspi) /* Specific SPI asked */
+ spi = tspi;
+ else /* Range specified */
{
- if (sspi == tspi) /* Specific SPI asked */
- spi = tspi;
- else /* Range specified */
- {
- get_random_bytes((void *) &spi, sizeof(spi));
- spi = sspi + (spi % (tspi - sspi));
- }
+ get_random_bytes((void *) &spi, sizeof(spi));
+ spi = sspi + (spi % (tspi - sspi));
}
- else /* Some SPI */
- get_random_bytes((void *) &spi, sizeof(spi));
- if (spi <= 255) /* Don't allocate SPI <= 255, they're reserved */
+ /* Don't allocate reserved SPIs. */
+ if (spi == SPI_LOCAL_USE ||
+ (spi >= SPI_RESERVED_MIN && spi <= SPI_RESERVED_MAX))
continue;
else
spi = htonl(spi);
@@ -520,6 +523,16 @@ tdb_expiration(struct tdb *tdb, int flags)
int will_be_first, sole_reason, early;
int s = spltdb();
+ /*
+ * If this is the local use SPI, this is an SPD entry, so don't setup any
+ * timers.
+ */
+ if (ntohl(tdb->tdb_spi) == SPI_LOCAL_USE)
+ {
+ splx(s);
+ return;
+ }
+
/* Find the earliest expiration. */
if ((tdb->tdb_flags & TDBF_FIRSTUSE) && tdb->tdb_first_use != 0 &&
(next_timeout == 0 ||
@@ -537,7 +550,8 @@ tdb_expiration(struct tdb *tdb, int flags)
next_timeout = tdb->tdb_soft_timeout;
/* No change? */
- if (next_timeout == tdb->tdb_timeout) {
+ if (next_timeout == tdb->tdb_timeout)
+ {
splx(s);
return;
}
@@ -633,7 +647,8 @@ tdb_expiration(struct tdb *tdb, int flags)
/*
* Check various invariants.
*/
- if (tdb->tdb_expnext.tqe_prev != NULL) {
+ if (tdb->tdb_expnext.tqe_prev != NULL)
+ {
t = TAILQ_FIRST(&expclusterlist);
if (t != tdb && t->tdb_timeout >= tdb->tdb_timeout)
panic("tdb_expiration: "
diff --git a/sys/netinet/ip_ipsp.h b/sys/netinet/ip_ipsp.h
index 7c256a5767c..54164a7fd89 100644
--- a/sys/netinet/ip_ipsp.h
+++ b/sys/netinet/ip_ipsp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_ipsp.h,v 1.38 1999/07/06 20:17:52 cmetz Exp $ */
+/* $OpenBSD: ip_ipsp.h,v 1.39 1999/07/15 14:15:41 niklas Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
@@ -99,6 +99,11 @@ union sockaddr_union
#define AH_RMD160_ALEN 20
#define AH_ALEN_MAX 20 /* Keep updated */
+/* Reserved SPI numbers */
+#define SPI_LOCAL_USE 0
+#define SPI_RESERVED_MIN 1
+#define SPI_RESERVED_MAX 255
+
struct sockaddr_encap
{
u_int8_t sen_len; /* length */
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 5b9e9e85fcb..cef8b3570e2 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_output.c,v 1.48 1999/06/15 02:24:02 deraadt Exp $ */
+/* $OpenBSD: ip_output.c,v 1.49 1999/07/15 14:15:41 niklas Exp $ */
/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
/*
@@ -90,6 +90,8 @@ int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **));
extern int ipsec_auth_default_level;
extern int ipsec_esp_trans_default_level;
extern int ipsec_esp_network_default_level;
+
+extern int pfkeyv2_acquire(struct tdb *, int);
#endif
/*
@@ -275,16 +277,39 @@ ip_output(m0, va_alist)
}
/*
- * For VPNs a route with a reserved SPI of 1 is used to
+ * For VPNs a route with a reserved SPI of 0 is used to
* indicate the need for an SA when none is established.
*/
- if (ntohl(gw->sen_ipsp_spi) == 0x1) {
- sa_require = NOTIFY_SATYPE_AUTH | NOTIFY_SATYPE_TUNNEL;
- if (gw->sen_ipsp_sproto == IPPROTO_ESP)
- sa_require |= NOTIFY_SATYPE_CONF;
+ if (ntohl(gw->sen_ipsp_spi) == SPI_LOCAL_USE) {
+ bzero(&sunion, sizeof(sunion));
+ sunion.sin.sin_family = AF_INET;
+ sunion.sin.sin_len = sizeof(struct sockaddr_in);
+ sunion.sin.sin_addr = gw->sen_ipsp_dst;
+ tdb = (struct tdb *) gettdb(gw->sen_ipsp_spi, &sunion,
+ gw->sen_ipsp_sproto);
+
+ if (tdb)
+ {
+ if (tdb->tdb_authalgxform)
+ sa_require = NOTIFY_SATYPE_AUTH;
+ if (tdb->tdb_encalgxform)
+ sa_require |= NOTIFY_SATYPE_CONF;
+ if (tdb->tdb_flags & TDBF_TUNNELING)
+ sa_require |= NOTIFY_SATYPE_TUNNEL;
+ }
+ else /* No TDB found */
+ {
+ /*
+ * XXX We should construct a TDB from system
+ * default (which should be tunable via sysctl).
+ * For now, drop packet and ignore SPD entry.
+ */
+ goto no_encap;
+ }
+
+ /* PF_KEYv2 notification message */
+ pfkeyv2_acquire(tdb, 0); /* XXX Check for errors */
- /* XXX PF_KEYv2 notification message */
-
splx(s);
/*