add a struct sadb_x_iface message for interface SAs
authordlg <dlg@openbsd.org>
Mon, 7 Aug 2023 03:35:06 +0000 (03:35 +0000)
committerdlg <dlg@openbsd.org>
Mon, 7 Aug 2023 03:35:06 +0000 (03:35 +0000)
this allows userland to install (and see) security associations for
route-based ipsec vpns. if this message is part of an SA, it causes
the TDBF_IFACE flag and associated fields in a tdb to be set.

the interface unit field in this message maps to minor number of
the sec(4) interface you want to the SA to work with. ie, set the
sadb_x_iface_unit field in struct sadb_x_iface to 1 to set up an
SA for use with sec1. the sadb_x_iface_direction in the message
uses IPSP_DIRECTION_IN and IPSP_DIRECTION_OUT to specify in which
direction that SA is supposed to process traffic.

support from many including markus@ tobhe@ claudio@ sthen@ patrick@
now is a good time deraadt@

sys/net/pfkeyv2.c
sys/net/pfkeyv2.h
sys/net/pfkeyv2_convert.c
sys/net/pfkeyv2_parsemessage.c

index cdc5ce2..e750ae8 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkeyv2.c,v 1.256 2023/04/22 20:51:56 mvs Exp $ */
+/* $OpenBSD: pfkeyv2.c,v 1.257 2023/08/07 03:35:06 dlg Exp $ */
 
 /*
  *     @(#)COPYRIGHT   1.1 (NRL) 17 January 1995
@@ -868,6 +868,9 @@ pfkeyv2_get(struct tdb *tdb, void **headers, void **buffer, int *lenp,
                i += sizeof(struct sadb_x_tap);
 #endif
 
+       if (ISSET(tdb->tdb_flags, TDBF_IFACE))
+               i += sizeof(struct sadb_x_iface);
+
        if (lenp)
                *lenp = i;
 
@@ -979,6 +982,12 @@ pfkeyv2_get(struct tdb *tdb, void **headers, void **buffer, int *lenp,
        }
 #endif
 
+       /* Export sec(4) interface information, if present */
+       if (ISSET(tdb->tdb_flags, TDBF_IFACE)) {
+               headers[SADB_X_EXT_IFACE] = p;
+               export_iface(&p, tdb);
+       }
+
        headers[SADB_X_EXT_COUNTER] = p;
        export_counter(&p, tdb);
 
@@ -1360,6 +1369,7 @@ pfkeyv2_dosend(struct socket *so, void *message, int len)
                        import_tag(newsa, headers[SADB_X_EXT_TAG]);
                        import_tap(newsa, headers[SADB_X_EXT_TAP]);
 #endif
+                       import_iface(newsa, headers[SADB_X_EXT_IFACE]);
 
                        /* Exclude sensitive data from reply message. */
                        headers[SADB_EXT_KEY_AUTH] = NULL;
@@ -1411,6 +1421,8 @@ pfkeyv2_dosend(struct socket *so, void *message, int len)
                        import_tag(sa2, headers[SADB_X_EXT_TAG]);
                        import_tap(sa2, headers[SADB_X_EXT_TAP]);
 #endif
+                       import_iface(sa2, headers[SADB_X_EXT_IFACE]);
+
                        if (headers[SADB_EXT_ADDRESS_SRC] ||
                            headers[SADB_EXT_ADDRESS_PROXY]) {
                                mtx_enter(&tdb_sadb_mtx);
@@ -1535,6 +1547,7 @@ pfkeyv2_dosend(struct socket *so, void *message, int len)
                        import_tag(newsa, headers[SADB_X_EXT_TAG]);
                        import_tap(newsa, headers[SADB_X_EXT_TAP]);
 #endif
+                       import_iface(newsa, headers[SADB_X_EXT_IFACE]);
 
                        /* Exclude sensitive data from reply message. */
                        headers[SADB_EXT_KEY_AUTH] = NULL;
index db0a7cd..64aa645 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkeyv2.h,v 1.93 2022/08/27 20:28:01 mvs Exp $ */
+/* $OpenBSD: pfkeyv2.h,v 1.94 2023/08/07 03:35:06 dlg Exp $ */
 /*
  *     @(#)COPYRIGHT   1.1 (NRL) January 1998
  *
@@ -252,6 +252,14 @@ struct sadb_x_mtu {
        uint32_t  sadb_x_mtu_mtu;
 };
 
+struct sadb_x_iface {
+       uint16_t  sadb_x_iface_len;
+       uint16_t  sadb_x_iface_exttype;
+       uint32_t  sadb_x_iface_unit;
+       uint8_t   sadb_x_iface_direction;
+       uint8_t   sadb_x_iface_reserved[7];
+};
+
 #ifdef _KERNEL
 #define SADB_X_GETSPROTO(x) \
        ( (x) == SADB_SATYPE_AH ? IPPROTO_AH :\
@@ -300,7 +308,8 @@ struct sadb_x_mtu {
 #define SADB_X_EXT_RDOMAIN            37
 #define SADB_X_EXT_MTU                38
 #define SADB_X_EXT_REPLAY             39
-#define SADB_EXT_MAX                  39
+#define SADB_X_EXT_IFACE              40
+#define SADB_EXT_MAX                  40
 
 /* Fix pfkeyv2.c struct pfkeyv2_socket if SATYPE_MAX > 31 */
 #define SADB_SATYPE_UNSPEC              0
@@ -438,6 +447,7 @@ void export_mtu(void **, struct tdb *);
 void export_tap(void **, struct tdb *);
 void export_satype(void **, struct tdb *);
 void export_counter(void **, struct tdb *);
+void export_iface(void **, struct tdb *);
 
 void import_address(struct sockaddr *, struct sadb_address *);
 void import_identities(struct ipsec_ids **, int, struct sadb_ident *,
@@ -452,6 +462,7 @@ 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 *);
+void import_iface(struct tdb *, struct sadb_x_iface *);
 
 extern const uint64_t sadb_exts_allowed_out[SADB_MAX+1];
 extern const uint64_t sadb_exts_required_out[SADB_MAX+1];
index c342b50..6868605 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pfkeyv2_convert.c,v 1.79 2022/01/20 17:13:12 bluhm Exp $      */
+/*     $OpenBSD: pfkeyv2_convert.c,v 1.80 2023/08/07 03:35:06 dlg Exp $        */
 /*
  * The author of this code is Angelos D. Keromytis (angelos@keromytis.org)
  *
@@ -951,6 +951,30 @@ export_tap(void **p, struct tdb *tdb)
 }
 #endif
 
+/* Import interface information for SA */
+void
+import_iface(struct tdb *tdb, struct sadb_x_iface *siface)
+{
+       if (siface != NULL) {
+               SET(tdb->tdb_flags, TDBF_IFACE);
+               tdb->tdb_iface = siface->sadb_x_iface_unit;
+               tdb->tdb_iface_dir = siface->sadb_x_iface_direction;
+       }
+}
+
+/* Export interface information for SA */
+void
+export_iface(void **p, struct tdb *tdb)
+{
+       struct sadb_x_iface *siface = (struct sadb_x_iface *)*p;
+
+       siface->sadb_x_iface_len = sizeof(*siface) / sizeof(uint64_t);
+       siface->sadb_x_iface_unit = tdb->tdb_iface;
+       siface->sadb_x_iface_direction = tdb->tdb_iface_dir;
+
+       *p += sizeof(*siface);
+}
+
 void
 export_satype(void **p, struct tdb *tdb)
 {
index 5345cca..edb1cc7 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pfkeyv2_parsemessage.c,v 1.60 2021/07/14 22:39:26 tobhe Exp $ */
+/*     $OpenBSD: pfkeyv2_parsemessage.c,v 1.61 2023/08/07 03:35:06 dlg Exp $   */
 
 /*
  *     @(#)COPYRIGHT   1.1 (NRL) 17 January 1995
 #define BITMAP_X_COUNTER               (1LL << SADB_X_EXT_COUNTER)
 #define BITMAP_X_MTU                   (1LL << SADB_X_EXT_MTU)
 #define BITMAP_X_REPLAY                (1LL << SADB_X_EXT_REPLAY)
+#define BITMAP_X_IFACE                 (1LL << SADB_X_EXT_IFACE)
 
 uint64_t sadb_exts_allowed_in[SADB_MAX+1] =
 {
@@ -143,9 +144,9 @@ 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_X_RDOMAIN,
+       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 | BITMAP_X_IFACE,
        /* 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_X_RDOMAIN,
+       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 | BITMAP_X_IFACE,
        /* DELETE */
        BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_X_RDOMAIN,
        /* GET */
@@ -215,13 +216,13 @@ const 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_X_RDOMAIN,
+       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 | BITMAP_X_IFACE,
        /* ADD */
-       BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN,
+       BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN | BITMAP_X_IFACE,
        /* DELETE */
        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_X_RDOMAIN | BITMAP_X_MTU | BITMAP_X_REPLAY,
+       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 | BITMAP_X_MTU | BITMAP_X_REPLAY | BITMAP_X_IFACE,
        /* ACQUIRE */
        BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL,
        /* REGISTER */
@@ -881,6 +882,12 @@ pfkeyv2_parsemessage(void *p, int len, void **headers)
                        }
                        break;
 #endif
+               case SADB_X_EXT_IFACE:
+                       if (i != sizeof(struct sadb_x_iface)) {
+                               DPRINTF("bad IFACE header length");
+                               return (EINVAL);
+                       }
+                       break;
                default:
                        DPRINTF("unknown extension header type %d",
                            sadb_ext->sadb_ext_type);