diff options
author | tobhe <tobhe@cvs.openbsd.org> | 2020-04-23 19:38:10 +0000 |
---|---|---|
committer | tobhe <tobhe@cvs.openbsd.org> | 2020-04-23 19:38:10 +0000 |
commit | b4921f76f870f2461ae9f70dabeb2c6d3ddcd425 (patch) | |
tree | 571007de94ea7f2191d4feea227f1ae52d2cdfee /sys/net | |
parent | 5ac974a527901effb41f7289022a88d576eaa141 (diff) |
Add support for autmatically moving traffic between rdomains on ipsec(4)
encryption or decryption. This allows us to keep plaintext and encrypted
network traffic seperated and reduces the attack surface for network
sidechannel attacks.
The only way to reach the inner rdomain from outside is by successful
decryption and integrity verification through the responsible Security
Association (SA).
The only way for internal traffic to get out is getting encrypted and
moved through the outgoing SA.
Multiple plaintext rdomains can share the same encrypted rdomain while
the unencrypted packets are still kept seperate.
The encrypted and unencrypted rdomains can have different default routes.
The rdomains can be configured with the new SADB_X_EXT_RDOMAIN pfkey
extension. Each SA (tdb) gets a new attribute 'tdb_rdomain_post'.
If this differs from 'tdb_rdomain' then the packet is moved to
'tdb_rdomain_post' afer IPsec processing.
Flows and outgoing IPsec SAs are installed in the plaintext rdomain,
incoming IPsec SAs are installed in the encrypted rdomain.
IPCOMP SAs are always installed in the plaintext rdomain.
They can be viewed with 'route -T X exec ipsecctl -sa' where X is the
rdomain ID.
As the kernel does not create encX devices automatically when creating
rdomains they have to be added by hand with ifconfig for IPsec to work
in non-default rdomains.
discussed with chris@ and kn@
ok markus@, patrick@
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/pfkeyv2.c | 52 | ||||
-rw-r--r-- | sys/net/pfkeyv2.h | 14 | ||||
-rw-r--r-- | sys/net/pfkeyv2_convert.c | 23 | ||||
-rw-r--r-- | sys/net/pfkeyv2_parsemessage.c | 38 |
4 files changed, 102 insertions, 25 deletions
diff --git a/sys/net/pfkeyv2.c b/sys/net/pfkeyv2.c index 0094555edba..7ce2f0da201 100644 --- a/sys/net/pfkeyv2.c +++ b/sys/net/pfkeyv2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfkeyv2.c,v 1.199 2020/03/18 11:56:40 mpi Exp $ */ +/* $OpenBSD: pfkeyv2.c,v 1.200 2020/04/23 19:38:08 tobhe Exp $ */ /* * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 @@ -855,6 +855,9 @@ pfkeyv2_get(struct tdb *tdb, void **headers, void **buffer, int *lenp) if (tdb->tdb_udpencap_port) i += sizeof(struct sadb_x_udpencap); + if (tdb->tdb_rdomain != tdb->tdb_rdomain_post) + i += sizeof(struct sadb_x_rdomain); + #if NPF > 0 if (tdb->tdb_tag) i += sizeof(struct sadb_x_tag) + PADUP(PF_TAG_NAME_SIZE); @@ -945,6 +948,12 @@ pfkeyv2_get(struct tdb *tdb, void **headers, void **buffer, int *lenp) export_udpencap(&p, tdb); } + /* Export rdomain switch, if present */ + if (tdb->tdb_rdomain != tdb->tdb_rdomain_post) { + headers[SADB_X_EXT_RDOMAIN] = p; + export_rdomain(&p, tdb); + } + #if NPF > 0 /* Export tag information, if present */ if (tdb->tdb_tag) { @@ -1109,7 +1118,8 @@ pfkeyv2_send(struct socket *so, void *message, int len) struct sadb_supported *ssup; struct sadb_ident *sid, *did; struct srp_ref sr; - u_int rdomain; + struct sadb_x_rdomain *srdomain; + u_int rdomain = 0; int promisc, s; mtx_enter(&pfkeyv2_mtx); @@ -1155,7 +1165,7 @@ pfkeyv2_send(struct socket *so, void *message, int len) /* Send to all promiscuous listeners */ SRPL_FOREACH(bkp, &sr, &pkptable.pkp_list, kcb_list) { - if (bkp->kcb_rdomain != rdomain) + if (bkp->kcb_rdomain != kp->kcb_rdomain) continue; s = keylock(bkp); @@ -1177,6 +1187,17 @@ pfkeyv2_send(struct socket *so, void *message, int len) if ((rval = pfkeyv2_parsemessage(message, len, headers)) != 0) goto ret; + /* use specified rdomain */ + srdomain = (struct sadb_x_rdomain *) headers[SADB_X_EXT_RDOMAIN]; + if (srdomain) { + if (!rtable_exists(srdomain->sadb_x_rdomain_dom1) || + !rtable_exists(srdomain->sadb_x_rdomain_dom2)) { + rval = EINVAL; + goto ret; + } + rdomain = srdomain->sadb_x_rdomain_dom1; + } + smsg = (struct sadb_msg *) headers[0]; switch (smsg->sadb_msg_type) { case SADB_GETSPI: /* Reserve an SPI */ @@ -1316,6 +1337,7 @@ pfkeyv2_send(struct socket *so, void *message, int len) headers[SADB_X_EXT_PROTOCOL], headers[SADB_X_EXT_FLOW_TYPE]); import_udpencap(newsa, headers[SADB_X_EXT_UDPENCAP]); + import_rdomain(newsa, headers[SADB_X_EXT_RDOMAIN]); #if NPF > 0 import_tag(newsa, headers[SADB_X_EXT_TAG]); import_tap(newsa, headers[SADB_X_EXT_TAP]); @@ -1486,6 +1508,7 @@ pfkeyv2_send(struct socket *so, void *message, int len) headers[SADB_X_EXT_PROTOCOL], headers[SADB_X_EXT_FLOW_TYPE]); import_udpencap(newsa, headers[SADB_X_EXT_UDPENCAP]); + import_rdomain(newsa, headers[SADB_X_EXT_RDOMAIN]); #if NPF > 0 import_tag(newsa, headers[SADB_X_EXT_TAG]); import_tap(newsa, headers[SADB_X_EXT_TAP]); @@ -1720,7 +1743,9 @@ pfkeyv2_send(struct socket *so, void *message, int len) sizeof(struct sadb_address)); sa_proto = (struct sadb_protocol *) headers[SADB_X_EXT_SATYPE2]; - tdb2 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp, + /* optionally fetch tdb2 from rdomain2 */ + tdb2 = gettdb(srdomain ? srdomain->sadb_x_rdomain_dom2 : rdomain, + ssa->sadb_sa_spi, sunionp, SADB_X_GETSPROTO(sa_proto->sadb_protocol_proto)); if (tdb2 == NULL) { rval = ESRCH; @@ -1983,7 +2008,7 @@ pfkeyv2_send(struct socket *so, void *message, int len) goto ret; SRPL_FOREACH(bkp, &sr, &pkptable.pkp_list, kcb_list) { - if (bkp == kp || bkp->kcb_rdomain != rdomain) + if (bkp == kp || bkp->kcb_rdomain != kp->kcb_rdomain) continue; if (!smsg->sadb_msg_seq || @@ -2061,7 +2086,7 @@ ret: } } - rval = pfkeyv2_sendmessage(headers, mode, so, 0, 0, rdomain); + rval = pfkeyv2_sendmessage(headers, mode, so, 0, 0, kp->kcb_rdomain); realret: @@ -2360,6 +2385,12 @@ pfkeyv2_expire(struct tdb *tdb, u_int16_t type) if ((rval = pfkeyv2_sendmessage(headers, PFKEYV2_SENDMESSAGE_BROADCAST, NULL, 0, 0, tdb->tdb_rdomain)) != 0) goto ret; + /* XXX */ + if (tdb->tdb_rdomain != tdb->tdb_rdomain_post) + if ((rval = pfkeyv2_sendmessage(headers, + PFKEYV2_SENDMESSAGE_BROADCAST, NULL, 0, 0, + tdb->tdb_rdomain_post)) != 0) + goto ret; rval = 0; @@ -2620,6 +2651,7 @@ pfkeyv2_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, struct pfkeyv2_sysctl_walk w; int error = EINVAL; u_int rdomain; + u_int tableid; if (new) return (EPERM); @@ -2630,7 +2662,13 @@ pfkeyv2_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, w.w_where = oldp; w.w_len = oldp ? *oldlenp : 0; - rdomain = rtable_l2(curproc->p_p->ps_rtableid); + if (namelen == 3) { + tableid = name[2]; + if (!rtable_exists(tableid)) + return (ENOENT); + } else + tableid = curproc->p_p->ps_rtableid; + rdomain = rtable_l2(tableid); switch(w.w_op) { case NET_KEY_SADB_DUMP: diff --git a/sys/net/pfkeyv2.h b/sys/net/pfkeyv2.h index 9c31163e95e..eba96c43ca2 100644 --- a/sys/net/pfkeyv2.h +++ b/sys/net/pfkeyv2.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfkeyv2.h,v 1.81 2019/03/04 08:42:12 stsp Exp $ */ +/* $OpenBSD: pfkeyv2.h,v 1.82 2020/04/23 19:38:08 tobhe Exp $ */ /* * @(#)COPYRIGHT 1.1 (NRL) January 1998 * @@ -212,6 +212,13 @@ struct sadb_x_tag { u_int32_t sadb_x_tag_taglen; }; +struct sadb_x_rdomain { + uint16_t sadb_x_rdomain_len; + uint16_t sadb_x_rdomain_exttype; + uint16_t sadb_x_rdomain_dom1; + uint16_t sadb_x_rdomain_dom2; +}; + struct sadb_x_tap { uint16_t sadb_x_tap_len; uint16_t sadb_x_tap_exttype; @@ -277,7 +284,8 @@ struct sadb_x_counter { #define SADB_X_EXT_TAP 34 #define SADB_X_EXT_SATYPE2 35 #define SADB_X_EXT_COUNTER 36 -#define SADB_EXT_MAX 36 +#define SADB_X_EXT_RDOMAIN 37 +#define SADB_EXT_MAX 37 /* Fix pfkeyv2.c struct pfkeyv2_socket if SATYPE_MAX > 31 */ #define SADB_SATYPE_UNSPEC 0 @@ -409,6 +417,7 @@ void export_flow(void **, u_int8_t, struct sockaddr_encap *, void export_key(void **, struct tdb *, int); void export_udpencap(void **, struct tdb *); void export_tag(void **, struct tdb *); +void export_rdomain(void **, struct tdb *); void export_tap(void **, struct tdb *); void export_satype(void **, struct tdb *); void export_counter(void **, struct tdb *); @@ -424,6 +433,7 @@ void import_flow(struct sockaddr_encap *, struct sockaddr_encap *, struct sadb_address *, struct sadb_protocol *, struct sadb_protocol *); void import_udpencap(struct tdb *, struct sadb_x_udpencap *); void import_tag(struct tdb *, struct sadb_x_tag *); +void import_rdomain(struct tdb *, struct sadb_x_rdomain *); void import_tap(struct tdb *, struct sadb_x_tap *); #endif /* _KERNEL */ diff --git a/sys/net/pfkeyv2_convert.c b/sys/net/pfkeyv2_convert.c index c72bc152fa8..228b9554f59 100644 --- a/sys/net/pfkeyv2_convert.c +++ b/sys/net/pfkeyv2_convert.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfkeyv2_convert.c,v 1.66 2019/03/04 08:42:12 stsp Exp $ */ +/* $OpenBSD: pfkeyv2_convert.c,v 1.67 2020/04/23 19:38:08 tobhe Exp $ */ /* * The author of this code is Angelos D. Keromytis (angelos@keromytis.org) * @@ -840,6 +840,27 @@ export_udpencap(void **p, struct tdb *tdb) *p += sizeof(struct sadb_x_udpencap); } +/* Import rdomain switch for SA */ +void +import_rdomain(struct tdb *tdb, struct sadb_x_rdomain *srdomain) +{ + if (srdomain) + tdb->tdb_rdomain_post = srdomain->sadb_x_rdomain_dom2; +} + +/* Export rdomain switch for SA */ +void +export_rdomain(void **p, struct tdb *tdb) +{ + struct sadb_x_rdomain *srdomain = (struct sadb_x_rdomain *)*p; + + srdomain->sadb_x_rdomain_dom1 = tdb->tdb_rdomain; + srdomain->sadb_x_rdomain_dom2 = tdb->tdb_rdomain_post; + srdomain->sadb_x_rdomain_len = + sizeof(struct sadb_x_rdomain) / sizeof(uint64_t); + *p += sizeof(struct sadb_x_rdomain); +} + #if NPF > 0 /* Import PF tag information for SA */ void diff --git a/sys/net/pfkeyv2_parsemessage.c b/sys/net/pfkeyv2_parsemessage.c index 2d351addd6e..8b76c2387fa 100644 --- a/sys/net/pfkeyv2_parsemessage.c +++ b/sys/net/pfkeyv2_parsemessage.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfkeyv2_parsemessage.c,v 1.54 2019/02/01 13:32:00 mpi Exp $ */ +/* $OpenBSD: pfkeyv2_parsemessage.c,v 1.55 2020/04/23 19:38:08 tobhe Exp $ */ /* * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 @@ -126,6 +126,7 @@ #define BITMAP_X_TAG (1LL << SADB_X_EXT_TAG) #define BITMAP_X_TAP (1LL << SADB_X_EXT_TAP) #define BITMAP_X_SATYPE2 (1LL << SADB_X_EXT_SATYPE2) +#define BITMAP_X_RDOMAIN (1LL << SADB_X_EXT_RDOMAIN) #define BITMAP_X_COUNTER (1LL << SADB_X_EXT_COUNTER) uint64_t sadb_exts_allowed_in[SADB_MAX+1] = @@ -135,13 +136,13 @@ uint64_t sadb_exts_allowed_in[SADB_MAX+1] = /* GETSPI */ BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_SPIRANGE, /* UPDATE */ - BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_ADDRESS_PROXY | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP, + BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_ADDRESS_PROXY | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN, /* ADD */ - BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_LIFETIME_LASTUSE | BITMAP_X_TAG | BITMAP_X_TAP, + BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_LIFETIME_LASTUSE | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN, /* DELETE */ - BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST, + BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_X_RDOMAIN, /* GET */ - BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST, + BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_X_RDOMAIN, /* ACQUIRE */ BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL, /* REGISTER */ @@ -155,11 +156,11 @@ uint64_t sadb_exts_allowed_in[SADB_MAX+1] = /* X_PROMISC */ 0, /* X_ADDFLOW */ - BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY_SRC | BITMAP_IDENTITY_DST | BITMAP_X_FLOW, + BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY_SRC | BITMAP_IDENTITY_DST | BITMAP_X_FLOW | BITMAP_X_RDOMAIN, /* X_DELFLOW */ - BITMAP_X_FLOW, + BITMAP_X_FLOW | BITMAP_X_RDOMAIN, /* X_GRPSPIS */ - BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_SATYPE2, + BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_SATYPE2 | BITMAP_X_RDOMAIN, /* X_ASKPOLICY */ BITMAP_X_POLICY, }; @@ -207,13 +208,13 @@ uint64_t sadb_exts_allowed_out[SADB_MAX+1] = /* GETSPI */ BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST, /* UPDATE */ - BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_ADDRESS_PROXY | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP, + BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_ADDRESS_PROXY | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN, /* ADD */ - BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP, + BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN, /* DELETE */ - BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST, + BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_X_RDOMAIN, /* GET */ - BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_UDPENCAP | BITMAP_X_LIFETIME_LASTUSE | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_FLOW_TYPE | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_COUNTER, + BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_UDPENCAP | BITMAP_X_LIFETIME_LASTUSE | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_FLOW_TYPE | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_COUNTER | BITMAP_X_RDOMAIN, /* ACQUIRE */ BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL, /* REGISTER */ @@ -227,11 +228,11 @@ uint64_t sadb_exts_allowed_out[SADB_MAX+1] = /* X_PROMISC */ 0, /* X_ADDFLOW */ - BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE | BITMAP_IDENTITY_SRC | BITMAP_IDENTITY_DST, + BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE | BITMAP_IDENTITY_SRC | BITMAP_IDENTITY_DST | BITMAP_X_RDOMAIN, /* X_DELFLOW */ - BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE, + BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE | BITMAP_X_RDOMAIN, /* X_GRPSPIS */ - BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_SATYPE2, + BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_SATYPE2 | BITMAP_X_RDOMAIN, /* X_ASKPOLICY */ BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_FLOW_TYPE | BITMAP_X_POLICY, }; @@ -879,6 +880,13 @@ pfkeyv2_parsemessage(void *p, int len, void **headers) return (EINVAL); } break; + case SADB_X_EXT_RDOMAIN: + if (i != sizeof(struct sadb_x_rdomain)) { + DPRINTF(("pfkeyv2_parsemessage: bad RDOMAIN " + "header length\n")); + return (EINVAL); + } + break; #if NPF > 0 case SADB_X_EXT_TAG: if (i < sizeof(struct sadb_x_tag)) { |