The recent rantings on misc@ made me look at getting this to work once
more. And this time I got it to work, sortof. The approach uses
wpa_supplicant, but since the OpenBSD net80211 stack takes care of
most of the key management (including the so-called 4-way handshake)
we only really need it to do the IEEE 802.1X EAP authentication for us
and have it insert the pairwise master key (PMK) into the net80211
stack. To do this I wrote a very simple OpenBSD "driver" for
wpa_supplicant that implements the bare essentials. A diff against
the current wpa_supplicant git tree is attached below. It should
apply cleanly agains wpa_supplicant-2.0.tar.gz and might just work
with older releases. As my driver doesn't support scanning for APs
and configuring the interface you need to configure the interface
yourself. Since you athenticate against a specific AP, it's best to
explicitly configure the desired BSSID. You'll need to explicitly
configure 802.1x authetication. You'll end up with something like:
# ifconfig rsu0 nwid humppa bssid 11:22:33:44:55:66 wpa wpaakms 802.1x up
Give it a couple of seconds to associate with the AP, and start
wpa_supplicant:
# wpa_supplicant -i rsu0 -c /etc/wpa_supplicant.conf
The wpa_supplicant program will print some messages about the
authenticaton process. If authentication is successful, this should end with
woething like:
rsu0: CTRL-EVENT-EAP-SUCCESS EAP authentication completed successfully
rsu0: CTRL-EVENT-CONNECTED - Connection to 11:22:33:44:55:66 completed [id=0
id_str=]
At that point ifconfig(8) should report the link status as "active".
Here is my /etc/wpa_supplicant.conf. You'll probably have to tweak
the "eap" line to match whatever the network you're connecting to is
using. And obviously you'll have to change the "ssid", "identity" and
"password" lines.
# $OpenBSD: wpa_supplicant.conf,v 1.1 2007/07/01 19:50:57 reyk Exp $
# Sample wpa_supplicant configuration file for wired IEEE 802.1x
# port authentication. See wpa_supplicant.conf(5).
ctrl_interface=/var/run/wpa_supplicant
ctrl_interface_group=wheel
ap_scan=0
network={
ssid="humppa"
key_mgmt=WPA-EAP
eap=TTLS PEAP
identity="user"
password="password"
}
Here is my .config file for building wpa_supplicant:
CONFIG_DRIVER_OPENBSD=y
CONFIG_DRIVER_WIRED=y
CONFIG_IEEE8021X_EAPOL=y
CONFIG_EAP_MD5=y
CONFIG_EAP_MSCHAPV2=y
CONFIG_EAP_TLS=y
CONFIG_EAP_PEAP=y
CONFIG_EAP_TTLS=y
CONFIG_EAP_GTC=y
CONFIG_EAP_OTP=y
CONFIG_EAP_LEAP=y
CONFIG_PKCS12=y
CONFIG_SMARTCARD=y
CONFIG_CTRL_IFACE=y
CONFIG_BACKEND=file
CONFIG_PEERKEY=y
And here is the diff:
diff --git a/src/drivers/driver_openbsd.c b/src/drivers/driver_openbsd.c
new file mode 100644
index 0000000..e94eda0
--- /dev/null
+++ b/src/drivers/driver_openbsd.c
@@ -0,0 +1,136 @@
+/*
+ * Driver interaction with OpenBSD net80211 layer
+ * Copyright (c) 2013, Mark Kettenis
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+#include <net80211/ieee80211.h>
+#include <net80211/ieee80211_crypto.h>
+#include <net80211/ieee80211_ioctl.h>
+
+#include "common.h"
+#include "driver.h"
+
+struct openbsd_driver_data {
+ char ifname[IFNAMSIZ + 1];
+ void *ctx;
+
+ int sock; /* open socket for 802.11 ioctls */
+};
+
+
+static int
+wpa_driver_openbsd_get_ssid(void *priv, u8 *ssid)
+{
+ struct openbsd_driver_data *drv = priv;
+ struct ieee80211_nwid nwid;
+ struct ifreq ifr;
+
+ os_memset(&ifr, 0, sizeof(ifr));
+ os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
+ ifr.ifr_data = (void *)&nwid;
+ if (ioctl(drv->sock, SIOCG80211NWID, &ifr) < 0 ||
+ nwid.i_len > IEEE80211_NWID_LEN)
+ return -1;
+
+ os_memcpy(ssid, nwid.i_nwid, nwid.i_len);
+ return nwid.i_len;
+}
+
+static int
+wpa_driver_openbsd_get_bssid(void *priv, u8 *bssid)
+{
+ struct openbsd_driver_data *drv = priv;
+ struct ieee80211_bssid id;
+
+ os_strlcpy(id.i_name, drv->ifname, sizeof(id.i_name));
+ if (ioctl(drv->sock, SIOCG80211BSSID, &id) < 0)
+ return -1;
+
+ os_memcpy(bssid, id.i_bssid, IEEE80211_ADDR_LEN);
+ return 0;
+}
+
+
+static int
+wpa_driver_openbsd_get_capa(void *priv, struct wpa_driver_capa *capa)
+{
+ os_memset(capa, 0, sizeof(*capa));
+ capa->flags = WPA_DRIVER_FLAGS_4WAY_HANDSHAKE;
+ return 0;
+}
+
+
+static int
+wpa_driver_openbsd_set_key(const char *ifname, void *priv, enum wpa_alg alg,
+ const unsigned char *addr, int key_idx, int set_tx, const u8 *seq,
+ size_t seq_len, const u8 *key, size_t key_len)
+{
+ struct openbsd_driver_data *drv = priv;
+ struct ieee80211_keyavail keyavail;
+
+ if (alg != WPA_ALG_PMK || key_len > IEEE80211_PMK_LEN)
+ return -1;
+
+ memset(&keyavail, 0, sizeof(keyavail));
+ os_strlcpy(keyavail.i_name, drv->ifname, sizeof(keyavail.i_name));
+ if (wpa_driver_openbsd_get_bssid(priv, keyavail.i_macaddr) < 0)
+ return -1;
+ memcpy(keyavail.i_key, key, key_len);
+
+ if (ioctl(drv->sock, SIOCS80211KEYAVAIL, &keyavail) < 0)
+ return -1;
+
+ return 0;
+}
+
+static void *
+wpa_driver_openbsd_init(void *ctx, const char *ifname)
+{
+ struct openbsd_driver_data *drv;
+
+ drv = os_zalloc(sizeof(*drv));
+ if (drv == NULL)
+ return NULL;
+
+ drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
+ if (drv->sock < 0)
+ goto fail;
+
+ drv->ctx = ctx;
+ os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
+
+ return drv;
+
+fail:
+ os_free(drv);
+ return NULL;
+}
+
+
+static void
+wpa_driver_openbsd_deinit(void *priv)
+{
+ struct openbsd_driver_data *drv = priv;
+
+ close(drv->sock);
+ os_free(drv);
+}
+
+
+const struct wpa_driver_ops wpa_driver_openbsd_ops = {
+ .name = "openbsd",
+ .desc = "OpenBSD 802.11 support",
+ .get_ssid = wpa_driver_openbsd_get_ssid,
+ .get_bssid = wpa_driver_openbsd_get_bssid,
+ .get_capa = wpa_driver_openbsd_get_capa,
+ .set_key = wpa_driver_openbsd_set_key,
+ .init = wpa_driver_openbsd_init,
+ .deinit = wpa_driver_openbsd_deinit,
+};
diff --git a/src/drivers/drivers.c b/src/drivers/drivers.c
index a92eddf..1d0ff6e 100644
--- a/src/drivers/drivers.c
+++ b/src/drivers/drivers.c
@@ -24,6 +24,9 @@ extern struct wpa_driver_ops wpa_driver_madwifi_ops; /*
driver_madwifi.c */
#ifdef CONFIG_DRIVER_BSD
extern struct wpa_driver_ops wpa_driver_bsd_ops; /* driver_bsd.c */
#endif /* CONFIG_DRIVER_BSD */
+#ifdef CONFIG_DRIVER_OPENBSD
+extern struct wpa_driver_ops wpa_driver_openbsd_ops; /* driver_openbsd.c */
+#endif /* CONFIG_DRIVER_OPENBSD */
#ifdef CONFIG_DRIVER_NDIS
extern struct wpa_driver_ops wpa_driver_ndis_ops; /* driver_ndis.c */
#endif /* CONFIG_DRIVER_NDIS */
@@ -62,6 +65,9 @@ struct wpa_driver_ops *wpa_drivers[] =
#ifdef CONFIG_DRIVER_BSD
&wpa_driver_bsd_ops,
#endif /* CONFIG_DRIVER_BSD */
+#ifdef CONFIG_DRIVER_OPENBSD
+ &wpa_driver_openbsd_ops,
+#endif /* CONFIG_DRIVER_OPENBSD */
#ifdef CONFIG_DRIVER_NDIS
&wpa_driver_ndis_ops,
#endif /* CONFIG_DRIVER_NDIS */
diff --git a/src/drivers/drivers.mak b/src/drivers/drivers.mak
index c7a98d3..68ff910 100644
--- a/src/drivers/drivers.mak
+++ b/src/drivers/drivers.mak
@@ -55,6 +55,14 @@ CONFIG_L2_FREEBSD=y
CONFIG_DNET_PCAP=y
endif
+ifdef CONFIG_DRIVER_OPENBSD
+ifndef CONFIG_L2_PACKET
+CONFIG_L2_PACKET=freebsd
+endif
+DRV_CFLAGS += -DCONFIG_DRIVER_OPENBSD
+DRV_OBJS += ../src/drivers/driver_openbsd.o
+endif
+
ifdef CONFIG_DRIVER_TEST
DRV_CFLAGS += -DCONFIG_DRIVER_TEST
DRV_OBJS += ../src/drivers/driver_test.o
diff --git a/src/drivers/drivers.mk b/src/drivers/drivers.mk
index 23fcbb7..db8561a 100644
--- a/src/drivers/drivers.mk
+++ b/src/drivers/drivers.mk
@@ -55,6 +55,14 @@ CONFIG_L2_FREEBSD=y
CONFIG_DNET_PCAP=y
endif
+ifdef CONFIG_DRIVER_OPENBSD
+ifndef CONFIG_L2_PACKET
+CONFIG_L2_PACKET=freebsd
+endif
+DRV_CFLAGS += -DCONFIG_DRIVER_OPENBSD
+DRV_OBJS += src/drivers/driver_openbsd.c
+endif
+
ifdef CONFIG_DRIVER_TEST
DRV_CFLAGS += -DCONFIG_DRIVER_TEST
DRV_OBJS += src/drivers/driver_test.c