diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1999-07-15 14:15:42 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1999-07-15 14:15:42 +0000 |
commit | 893ba3a842c40c7f5d6f9f14837e0d432dd7767f (patch) | |
tree | b143d604f311079eb8a3f83241ef170196a8f67a /sys | |
parent | 7bdb8bc6dd617efd36012f956c9992b1cfa8e85c (diff) |
From angelos@, edits by me, demand keying for PF_KEY
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/pfkeyv2.c | 164 | ||||
-rw-r--r-- | sys/netinet/ip_ipsp.c | 59 | ||||
-rw-r--r-- | sys/netinet/ip_ipsp.h | 7 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 41 |
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); /* |