summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorprovos <provos@openbsd.org>2000-12-14 18:32:25 +0000
committerprovos <provos@openbsd.org>2000-12-14 18:32:25 +0000
commitfbf4ab06580705a34794f7c94e423772f6b73414 (patch)
tree884d1cfe896cad929ab7ec10d1d39c7cd6d9bc14
parentsync with pfkey rfc. you need to rebuild ipsecadm and isakmpd after this. (diff)
downloadwireguard-openbsd-fbf4ab06580705a34794f7c94e423772f6b73414.tar.xz
wireguard-openbsd-fbf4ab06580705a34794f7c94e423772f6b73414.zip
setup soft lifetimes, handle hard expirations, deal with changed pfkey
supported extensions. some problems pointed out by Hans-Joerg.Hoexer@rommelwood.de
-rw-r--r--sbin/photurisd/kernel.c294
-rw-r--r--sbin/photurisd/kernel.h3
2 files changed, 211 insertions, 86 deletions
diff --git a/sbin/photurisd/kernel.c b/sbin/photurisd/kernel.c
index e414aab1855..3dfa10b93ff 100644
--- a/sbin/photurisd/kernel.c
+++ b/sbin/photurisd/kernel.c
@@ -39,7 +39,7 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: kernel.c,v 1.13 2000/12/13 08:36:27 provos Exp $";
+static char rcsid[] = "$Id: kernel.c,v 1.14 2000/12/14 18:32:25 provos Exp $";
#endif
#include <time.h>
@@ -49,18 +49,11 @@ static char rcsid[] = "$Id: kernel.c,v 1.13 2000/12/13 08:36:27 provos Exp $";
#include <sys/param.h>
#include <sys/file.h>
#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/mbuf.h>
-#include <sys/sysctl.h>
#include <sys/uio.h>
#include <net/if.h>
#include <net/route.h>
-#include <net/if_dl.h>
#include <netinet/in.h>
-#include <netns/ns.h>
-#include <netiso/iso.h>
-#include <netccitt/x25.h>
#include <arpa/inet.h>
#include <netdb.h>
@@ -71,7 +64,7 @@ static char rcsid[] = "$Id: kernel.c,v 1.13 2000/12/13 08:36:27 provos Exp $";
#include <stdlib.h>
#include <string.h>
#include <paths.h>
-#define INET /* Needed for setting ipsec routes */
+
#include <net/pfkeyv2.h>
#include <netinet/ip_ipsp.h>
#include <netinet/ip_esp.h>
@@ -121,13 +114,33 @@ kernel_get_transform(int id)
void
kernel_transform_seen(int id, int type)
{
- int i;
+ int i;
+
+ for (i=sizeof(xf)/sizeof(transform)-1; i >= 0; i--)
+ if (xf[i].kernel_id == id && (xf[i].flags & type)) {
+ LOG_DBG((LOG_KERNEL, 50, __FUNCTION__
+ ": %s algorithm %d",
+ type == XF_ENC ? "enc" : "auth", id));
+ xf[i].flags |= XF_SUP;
+ return;
+ }
+}
- for (i=sizeof(xf)/sizeof(transform)-1; i >= 0; i--)
- if (xf[i].kernel_id == id && (xf[i].flags & type)) {
- xf[i].flags |= XF_SUP;
- return;
- }
+/*
+ * Parse the supported transforms returned in the SADB_REGISTER response
+ */
+
+void
+kernel_transform_parse(struct sadb_supported *ssup)
+{
+ struct sadb_alg *salg = (struct sadb_alg *)(ssup + 1);
+ int i, type;
+
+ type = ssup->sadb_supported_exttype == SADB_EXT_SUPPORTED_AUTH ?
+ XF_AUTH : XF_ENC;
+
+ for (i = 0; i < ssup->sadb_supported_len - 1; i++, salg++)
+ kernel_transform_seen(salg->sadb_alg_id, type);
}
/*
@@ -324,12 +337,16 @@ kernel_register(int sd)
struct sadb_msg smsg, *sres;
struct sadb_supported *ssup;
struct sadb_alg *salg;
- int len;
+ struct sadb_ext *ext;
+ void *end;
+ int encfound, authfound, len;
struct iovec iov[1];
int cnt = 0;
LOG_DBG((LOG_KERNEL, 20, __FUNCTION__": fd %d", sd));
+ encfound = authfound = 0;
+
bzero(&smsg, sizeof(smsg));
smsg.sadb_msg_len = sizeof(smsg) / 8;
@@ -340,7 +357,7 @@ kernel_register(int sd)
iov[cnt].iov_base = &smsg;
iov[cnt++].iov_len = sizeof(smsg);
- /* Register for AH */
+ /* Register for ESP */
smsg.sadb_msg_satype = SADB_SATYPE_ESP;
if (!kernel_xf_set(regsd, buffer, BUFFER_SIZE, iov, cnt,
smsg.sadb_msg_len*8)) {
@@ -348,7 +365,23 @@ kernel_register(int sd)
return (-1);
}
- /* Register for ESP */
+ sres = (struct sadb_msg *)buffer;
+ ext = (struct sadb_ext *)(sres + 1);
+ end = (u_char *)sres + sres->sadb_msg_len * 8;
+ ssup = (struct sadb_supported *)
+ pfkey_find_extension(ext, end, SADB_EXT_SUPPORTED_AUTH);
+ if (ssup) {
+ kernel_transform_parse(ssup);
+ authfound = 1;
+ }
+ ssup = (struct sadb_supported *)
+ pfkey_find_extension(ext, end, SADB_EXT_SUPPORTED_ENCRYPT);
+ if (ssup) {
+ kernel_transform_parse(ssup);
+ encfound = 1;
+ }
+
+ /* Register for AH */
smsg.sadb_msg_satype = SADB_SATYPE_AH;
smsg.sadb_msg_seq = pfkey_seq++;
if (!kernel_xf_set(regsd, buffer, BUFFER_SIZE, iov, cnt,
@@ -357,34 +390,29 @@ kernel_register(int sd)
return (-1);
}
- /*
- * XXX - this might need changing in the case that the response
- * to register only includes the transforms matching the satype
- * in the message.
- */
- sres = (struct sadb_msg *)buffer;
- ssup = (struct sadb_supported *)(sres + 1);
- if (ssup->sadb_supported_exttype != SADB_EXT_SUPPORTED) {
- log_print(__FUNCTION__
- ": SADB_REGISTER did not return a SADB_EXT_SUPPORTED "
- "struct: %d in kernel_register()",
- ssup->sadb_supported_exttype);
- return (-1);
- }
+ ext = (struct sadb_ext *)(sres + 1);
+ end = (u_char *)sres + sres->sadb_msg_len * 8;
- len = ssup->sadb_supported_len * 8 - sizeof(*ssup);
- if (len != (ssup->sadb_supported_nauth + ssup->sadb_supported_nencrypt) *
- sizeof(struct sadb_alg)) {
- log_print(__FUNCTION__
- ": SADB_SUPPORTED length mismatch in kernel_register()");
- return (-1);
+ ssup = (struct sadb_supported *)
+ pfkey_find_extension(ext, end, SADB_EXT_SUPPORTED_AUTH);
+ if (ssup) {
+ kernel_transform_parse(ssup);
+ authfound = 1;
+ }
+ ssup = (struct sadb_supported *)
+ pfkey_find_extension(ext, end, SADB_EXT_SUPPORTED_ENCRYPT);
+ if (ssup) {
+ kernel_transform_parse(ssup);
+ encfound = 1;
}
- salg = (struct sadb_alg *)(ssup + 1);
- for (cnt = 0; cnt < ssup->sadb_supported_nauth; cnt++, salg++)
- kernel_transform_seen(salg->sadb_alg_type, XF_AUTH);
- for (cnt = 0; cnt < ssup->sadb_supported_nencrypt; cnt++, salg++)
- kernel_transform_seen(salg->sadb_alg_type, XF_ENC);
+ if (!authfound || !encfound) {
+ log_print(__FUNCTION__
+ ": SADB_REGISTER without supported algs %s %s",
+ encfound == 0 ? "encryption" : "",
+ authfound == 0 ? "authentication" : "");
+ return (-1);
+ }
return (0);
}
@@ -521,18 +549,51 @@ kernel_reserve_single_spi(char *srcaddress, char *dstaddress, u_int32_t spi,
}
int
+kernel_add_lifetime(struct sadb_msg *sa, struct iovec *iov, int seconds)
+{
+ static struct sadb_lifetime slh, sls;
+ int cnt = 0;
+
+ bzero(&slh, sizeof(slh));
+ bzero(&sls, sizeof(sls));
+
+ slh.sadb_lifetime_len = sizeof(slh) / 8;
+ slh.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
+ slh.sadb_lifetime_allocations = 0;
+ slh.sadb_lifetime_bytes = 1000000000; /* lots of bytes */
+ slh.sadb_lifetime_addtime = seconds + 60;
+ slh.sadb_lifetime_usetime = seconds; /* first use */
+ sa->sadb_msg_len += slh.sadb_lifetime_len;
+
+ iov[cnt].iov_base = &slh;
+ iov[cnt++].iov_len = sizeof(slh);
+
+ sls.sadb_lifetime_len = sizeof(sls) / 8;
+ sls.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
+ sls.sadb_lifetime_allocations = 0;
+ sls.sadb_lifetime_bytes = 900000000; /* lots of bytes */
+ sls.sadb_lifetime_addtime = (seconds + 60) * 9 / 10;
+ sls.sadb_lifetime_usetime = seconds * 9 / 10; /* first use */
+ sa->sadb_msg_len += slh.sadb_lifetime_len;
+
+ iov[cnt].iov_base = &sls;
+ iov[cnt++].iov_len = sizeof(sls);
+
+ return (cnt);
+}
+
+int
kernel_ah(attrib_t *ob, struct spiob *SPI, u_int8_t *secrets, int hmac)
{
struct sadb_msg sa;
struct sadb_address sad1;
struct sadb_address sad2;
struct sadb_sa sr;
- struct sadb_lifetime sl;
struct sadb_key sk;
struct sockaddr_in src;
struct sockaddr_in dst;
struct iovec iov[20];
- int len, cnt = 0;
+ int cnt = 0;
transform *xf = kernel_get_transform(ob->id);
time_t now = time(NULL);
@@ -546,7 +607,6 @@ kernel_ah(attrib_t *ob, struct spiob *SPI, u_int8_t *secrets, int hmac)
bzero(&sad2, sizeof(sad2));
bzero(&sr, sizeof(sr));
bzero(&sk, sizeof(sk));
- bzero(&sl, sizeof(sl));
bzero(&src, sizeof(src));
bzero(&dst, sizeof(dst));
@@ -558,7 +618,7 @@ kernel_ah(attrib_t *ob, struct spiob *SPI, u_int8_t *secrets, int hmac)
sa.sadb_msg_seq = pfkey_seq++;
sa.sadb_msg_pid = pfkey_pid;
iov[cnt].iov_base = &sa;
- len = iov[cnt++].iov_len = sizeof(sa);
+ iov[cnt++].iov_len = sizeof(sa);
/* Source Address */
sad1.sadb_address_len = 1 + sizeof(struct sockaddr_in) / 8;
@@ -570,9 +630,9 @@ kernel_ah(attrib_t *ob, struct spiob *SPI, u_int8_t *secrets, int hmac)
sa.sadb_msg_len += sad1.sadb_address_len;
iov[cnt].iov_base = &sad1;
- len += iov[cnt++].iov_len = sizeof(sad1);
+ iov[cnt++].iov_len = sizeof(sad1);
iov[cnt].iov_base = &src;
- len += iov[cnt++].iov_len = sizeof(struct sockaddr);
+ iov[cnt++].iov_len = sizeof(struct sockaddr);
/* Destination Address */
sad2.sadb_address_len = 1 + sizeof(struct sockaddr_in) / 8;
@@ -584,9 +644,9 @@ kernel_ah(attrib_t *ob, struct spiob *SPI, u_int8_t *secrets, int hmac)
sa.sadb_msg_len += sad2.sadb_address_len;
iov[cnt].iov_base = &sad2;
- len += iov[cnt++].iov_len = sizeof(sad2);
+ iov[cnt++].iov_len = sizeof(sad2);
iov[cnt].iov_base = &dst;
- len += iov[cnt++].iov_len = sizeof(struct sockaddr);
+ iov[cnt++].iov_len = sizeof(struct sockaddr);
sr.sadb_sa_len = sizeof(sr) / 8;
sr.sadb_sa_exttype = SADB_EXT_SA;
@@ -600,18 +660,9 @@ kernel_ah(attrib_t *ob, struct spiob *SPI, u_int8_t *secrets, int hmac)
sa.sadb_msg_len += sr.sadb_sa_len;
iov[cnt].iov_base = &sr;
- len += iov[cnt++].iov_len = sizeof(sr);
-
- sl.sadb_lifetime_len = sizeof(sl) / 8;
- sl.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
- sl.sadb_lifetime_allocations = 10; /* 10 flows */
- sl.sadb_lifetime_bytes = 1000000000; /* lots of bytes */
- sl.sadb_lifetime_addtime = SPI->lifetime + 60 - now;
- sl.sadb_lifetime_usetime = SPI->lifetime - now; /* first use */
- sa.sadb_msg_len += sl.sadb_lifetime_len;
+ iov[cnt++].iov_len = sizeof(sr);
- iov[cnt].iov_base = &sl;
- len += iov[cnt++].iov_len = sizeof(sl);
+ cnt += kernel_add_lifetime(&sa, &iov[cnt], SPI->lifetime - now);
sk.sadb_key_len = (sizeof(sk) + ob->klen + 7) / 8;
sk.sadb_key_exttype = SADB_EXT_KEY_AUTH;
@@ -619,17 +670,17 @@ kernel_ah(attrib_t *ob, struct spiob *SPI, u_int8_t *secrets, int hmac)
sa.sadb_msg_len += sk.sadb_key_len;
iov[cnt].iov_base = &sk;
- len += iov[cnt++].iov_len = sizeof(sk);
+ iov[cnt++].iov_len = sizeof(sk);
iov[cnt].iov_base = secrets;
- len += iov[cnt++].iov_len = ((ob->klen + 7) / 8) * 8;
+ iov[cnt++].iov_len = ((ob->klen + 7) / 8) * 8;
LOG_DBG((LOG_KERNEL, 35, __FUNCTION__": %08x", ntohl(sr.sadb_sa_spi)));
- if (!KERNEL_XF_SET(len)) {
+ if (!KERNEL_XF_SET(sa.sadb_msg_len * 8)) {
log_error(__FUNCTION__": kernel_xf_set()");
return (-1);
}
- return ob->klen;
+ return (ob->klen);
}
int
@@ -639,7 +690,6 @@ kernel_esp(attrib_t *ob, attrib_t *ob2, struct spiob *SPI, u_int8_t *secrets)
struct sadb_address sad1;
struct sadb_address sad2;
struct sadb_sa sr;
- struct sadb_lifetime sl;
struct sadb_key sk1;
struct sadb_key sk2;
struct sockaddr_in src;
@@ -687,7 +737,6 @@ kernel_esp(attrib_t *ob, attrib_t *ob2, struct spiob *SPI, u_int8_t *secrets)
bzero(&sr, sizeof(sr));
bzero(&sk1, sizeof(sk1));
bzero(&sk2, sizeof(sk2));
- bzero(&sl, sizeof(sl));
bzero(&src, sizeof(src));
bzero(&dst, sizeof(dst));
@@ -746,16 +795,7 @@ kernel_esp(attrib_t *ob, attrib_t *ob2, struct spiob *SPI, u_int8_t *secrets)
iov[cnt].iov_base = &dst;
iov[cnt++].iov_len = sizeof(struct sockaddr);
- sl.sadb_lifetime_len = sizeof(sl) / 8;
- sl.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
- sl.sadb_lifetime_allocations = 10; /* 10 flows */
- sl.sadb_lifetime_bytes = 1000000000; /* lots of bytes */
- sl.sadb_lifetime_addtime = SPI->lifetime + 60 - now;
- sl.sadb_lifetime_usetime = SPI->lifetime - now; /* first use */
- sa.sadb_msg_len += sl.sadb_lifetime_len;
-
- iov[cnt].iov_base = &sl;
- iov[cnt++].iov_len = sizeof(sl);
+ cnt += kernel_add_lifetime(&sa, &iov[cnt], SPI->lifetime - now);
sk1.sadb_key_len = (sizeof(sk1) + attenc->klen + 7) / 8;
sk1.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
@@ -1033,9 +1073,9 @@ kernel_handle_notify(int sd)
switch (sres->sadb_msg_type) {
case SADB_EXPIRE:
- LOG_DBG((LOG_KERNEL, 40, __FUNCTION__
- ": PFKEYV2 SA Expiration - not yet supported."));
- return;
+ LOG_DBG((LOG_KERNEL, 60, __FUNCTION__": Got SA Expiration"));
+ kernel_handle_expire(sres);
+ break;
case SADB_ACQUIRE:
LOG_DBG((LOG_KERNEL, 60, __FUNCTION__
": Got Notify SA Request (SADB_ACQUIRE): %d",
@@ -1093,6 +1133,90 @@ pfkey_askpolicy(int seq)
return ((struct sadb_msg *)buffer);
}
+int
+kernel_handle_expire(struct sadb_msg *sadb)
+{
+ struct sadb_sa *sa;
+ struct sadb_address *dst;
+ char dstbuf[NI_MAXHOST];
+ struct sockaddr *dstaddr;
+ struct sadb_lifetime *life;
+ struct sadb_ext *ext = (struct sadb_ext *)(sadb + 1);
+ struct spiob *spi;
+ void *end;
+
+ end = (struct sadb_ext *)((u_char *)sadb + sadb->sadb_msg_len * 8);
+
+ sa = (struct sadb_sa *)pfkey_find_extension(ext, end, SADB_EXT_SA);
+ if (sa == NULL) {
+ log_print(__FUNCTION__": no SA extension found");
+ return (-1);
+ }
+
+ dst = (struct sadb_address *)
+ pfkey_find_extension(ext, end, SADB_EXT_ADDRESS_DST);
+ if (dst == NULL) {
+ log_print(__FUNCTION__
+ ": no destination address extension found");
+ return (-1);
+ }
+ dstaddr = (struct sockaddr *)(dst + 1);
+
+ life = (struct sadb_lifetime *)
+ pfkey_find_extension(ext, end, SADB_EXT_LIFETIME_HARD);
+ if (life == NULL)
+ life = (struct sadb_lifetime *)
+ pfkey_find_extension(ext, end, SADB_EXT_LIFETIME_SOFT);
+ if (life == NULL) {
+ log_print(__FUNCTION__
+ ": no lifetime extension found");
+ return (-1);
+ }
+
+ switch (dstaddr->sa_family) {
+ case AF_INET:
+ if (inet_ntop (AF_INET, &((struct sockaddr_in *)dstaddr)->sin_addr,
+ dstbuf, sizeof(dstbuf)) == NULL) {
+ log_error (__FUNCTION__": inet_ntop failed");
+ return (-1);
+ }
+ break;
+ default:
+ log_error(__FUNCTION__
+ ": unsupported address family %d",
+ dstaddr->sa_family);
+ return (-1);
+ }
+
+ LOG_DBG((LOG_KERNEL, 30, __FUNCTION__": %s dst %s SPI %x sproto %d",
+ life->sadb_lifetime_exttype == SADB_EXT_LIFETIME_SOFT ? "SOFT"
+ : "HARD", dstbuf,
+ ntohl (sa->sadb_sa_spi), sadb->sadb_msg_satype));
+
+ switch(life->sadb_lifetime_exttype) {
+ case SADB_EXT_LIFETIME_HARD:
+ spi = spi_find(dstbuf, (u_char *)&sa->sadb_sa_spi);
+ if (spi == NULL) {
+ LOG_DBG((LOG_KERNEL, 35, __FUNCTION__
+ ": can't find %s SPI %x",
+ dstbuf, ntohl(sa->sadb_sa_spi)));
+ return (-1);
+ }
+ LOG_DBG((LOG_KERNEL, 35, __FUNCTION__": removing %s SPI %x",
+ dstbuf, ntohl(sa->sadb_sa_spi)));
+ spi_unlink(spi);
+ break;
+ case SADB_EXT_LIFETIME_SOFT:
+ break;
+ default:
+ log_print(__FUNCTION__": unknown extension type %d",
+ life->sadb_lifetime_exttype);
+ return (-1);
+ }
+
+ return (0);
+}
+
/*
* Tries to establish a new SA according to the information in a
* REQUEST_SA notify message received from the kernel.
@@ -1115,10 +1239,10 @@ kernel_request_sa(struct sadb_msg *sadb)
end = (struct sadb_ext *)((u_char *)sadb + sadb->sadb_msg_len * 8);
- dst = (struct sadb_address *)pfkey_find_extension(ext, end,
- SADB_EXT_ADDRESS_DST);
- src = (struct sadb_address *)pfkey_find_extension(ext, end,
- SADB_EXT_ADDRESS_SRC);
+ dst = (struct sadb_address *)
+ pfkey_find_extension(ext, end, SADB_EXT_ADDRESS_DST);
+ src = (struct sadb_address *)
+ pfkey_find_extension(ext, end, SADB_EXT_ADDRESS_SRC);
if (dst) {
dstaddr = (struct sockaddr *)(dst + 1);
diff --git a/sbin/photurisd/kernel.h b/sbin/photurisd/kernel.h
index 4f391d00efb..7a6c54ada86 100644
--- a/sbin/photurisd/kernel.h
+++ b/sbin/photurisd/kernel.h
@@ -27,7 +27,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $Id: kernel.h,v 1.7 2000/12/12 01:53:42 provos Exp $ */
+/* $Id: kernel.h,v 1.8 2000/12/14 18:32:25 provos Exp $ */
/*
* kernel.h:
* security paramter index creation.
@@ -94,6 +94,7 @@ int kernel_delete_spi(char *address, u_int32_t spi, int proto);
struct sadb_msg;
int kernel_request_sa(struct sadb_msg *);
+int kernel_handle_expire(struct sadb_msg *);
#else
#define EXTERN extern
#endif