Repository navigation
Add 802.1X (WPA2-Enterprise) support for a userspace supplicant - #1073
Closed
dantdmdarealguy wants to merge 2 commits into
Closed
dantdmdarealguy wants to merge 2 commits into
dantdmdarealguy wants to merge 2 commits into
Conversation
selector == IOCTL_ID_MAX passed the bounds check and indexed one past the end of sMethods[], calling through whatever pointer followed (a NULL in practice, panicking the kernel). selector is unsigned, so the < 0 half of the check was dead code.
itlwm can't join WPA2-Enterprise networks today. This adds the minimum
kernel support for a userspace EAP supplicant (HeliPort) to do so. No
EAP, TLS or certificate handling is in the kext: it only moves EAPOL
frames and installs the PMK that userspace derives. The existing net80211
4-way handshake code is reused unchanged.
- For 802.1X AKMs, non-Key EAPOL frames (EAP-Packet/Start/Logoff) are
handed to itlwm through a global hook and queued in a small ring buffer
for userspace, instead of being dropped by ieee80211_eapol_key_input().
EAPOL-Key frames stay in the kernel. Only the itlwm build is affected
(not IO80211FAMILY_V2 / AirportItlwm). struct ieee80211com is unchanged.
- New user-client calls, appended after the existing IDs:
- IOCTL_80211_ASSOCIATE_ENTERPRISE: join an SSID with RSN, AKM 802.1X
and no PSK.
- IOCTL_80211_TX_EAPOL: transmit a userspace-built EAPOL frame. Needed
because the link stays down until the 4-way handshake and macOS drops
ordinary writes on a down interface. Only EtherType 0x888E accepted.
- IOCTL_80211_RX_EAPOL: fetch the next queued EAPOL frame.
- ID 13 is reserved and rejected: kexts without the bounds fix panic on
it, so new clients probe with RX_EAPOL instead.
- IOCTL_80211_WPA_KEY (previously a no-op stub) delivers the PMK, or a
failure status that deauths, after EAP. The PMK goes into the PMKSA
cache for the negotiated AKM, the same mechanism as OpenBSD's
SIOCS80211KEYAVAIL, so ieee80211_recv_4way_msg1() picks it up as-is.
- externalMethod now also checks the input struct size per selector.
- ClientKit headers updated to match HeliPort's copy.
Tested on macOS 15.7.7 with an Intel Wireless-AC 9560 on a PEAP/MSCHAPv2
network (Texas A&M TAMU_WiFi): first connect, auto-join at login, and
reauthentication. PSK and open networks are unaffected.
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
EAPOL routing, callback lifecycle, PMK concurrency, and WPA protocol selection contain unresolved correctness issues.
Review effort: Balanced
Findings: 3
Open (5)
What changed in this PR
Adds kernel-side WPA2-Enterprise support for a userspace EAP supplicant while retaining the existing four-way handshake implementation.
Changes:
- Adds enterprise association and PMK installation calls.
- Relays non-Key EAPOL frames through a bounded queue.
- Validates user-client buffer sizes and reserves selector 13.
| File | Description |
|---|---|
itlwm/itlwm.hpp |
Declares enterprise association and EAPOL queue state. |
itlwm/itlwm.cpp |
Implements association, queueing, and hook lifecycle. |
itlwm/ItlNetworkUserClient.hpp |
Declares new user-client handlers. |
itlwm/ItlNetworkUserClient.cpp |
Implements EAPOL transport and PMK delivery. |
itl80211/openbsd/net80211/ieee80211_var.h |
Exposes the EAPOL callback hook. |
itl80211/openbsd/net80211/ieee80211_input.c |
Routes non-Key EAPOL frames to userspace. |
include/ClientKit/IoctlId.h |
Adds enterprise ioctl selectors. |
include/ClientKit/Common.h |
Defines enterprise ioctl payloads and statuses. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+580
to
+581
| extern void (*ieee80211_eapol_input)(void *, mbuf_t); | ||
| extern void *ieee80211_eapol_input_arg; |
Comment on lines
+383
to
+386
| enum ieee80211_akm akm = (enum ieee80211_akm)ic->ic_bss->ni_rsnakms; | ||
| if (!ieee80211_is_8021x_akm(akm)) | ||
| akm = IEEE80211_AKM_8021X; | ||
| if (ieee80211_pmksa_add(ic, akm, ic->ic_bss->ni_bssid, req->pmk, 0) == NULL) |
Comment on lines
+404
to
+405
| ieee80211_eapol_input_arg = this; | ||
| ieee80211_eapol_input = &itlwm::eapolInput; |
Comment on lines
+1153
to
+1155
| if (ieee80211_is_8021x_akm((enum ieee80211_akm)ni->ni_rsnakms) && | ||
| mbuf_len(m) >= sizeof(*eh) + 2 && | ||
| ((const uint8_t *)(eh + 1))[1] != EAPOL_KEY) { |
| wpa.i_enabled = 1; | ||
| wpa.i_ciphers = 0; | ||
| wpa.i_groupcipher = 0; | ||
| wpa.i_protos = IEEE80211_WPA_PROTO_WPA1 | IEEE80211_WPA_PROTO_WPA2; |
Author
|
Superseded by #1075. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Related: #101 (also asked in #230, #240), OpenIntelWireless/HeliPort#4, OpenIntelWireless/HeliPort#287
Includes the one-line fix from #1072 as its first commit; merge that first or together.
Summary
itlwm can't join WPA2-Enterprise networks today. This adds the minimum kernel
support needed for a userspace EAP supplicant (implemented in HeliPort, OpenIntelWireless/HeliPort#287) to do it.
In line with the concern raised in #101, the kext has no certificate handling, TLS
or EAP logic. It only moves EAPOL frames and installs the PMK that userspace
derives. The existing net80211 4-way handshake code is reused unchanged.
Changes
Start / Logoff) are handed to itlwm through a global hook
(
ieee80211_eapol_input). itlwm queues them in a small ring buffer (16 frames)for userspace. Previously
ieee80211_eapol_key_input()dropped them. EAPOL-Keyframes stay in the kernel for the 4-way handshake.
struct ieee80211comis unchanged, so the HAL softcs that embed it keep theirlayout.
IO80211FAMILY_V2) is untouched.IOCTL_80211_ASSOCIATE_ENTERPRISE: join an SSID with RSN, AKM 802.1X and no PSK.IOCTL_80211_TX_EAPOL: transmit an EAPOL frame built in userspace. It's neededbecause the interface link stays down until the 4-way handshake completes, and
macOS drops ordinary writes on a down interface. Only EtherType 0x888E is
accepted.
IOCTL_80211_RX_EAPOL: fetch the next queued frame. It returns length 0 whenthe queue is empty.
Clients detect support by calling
RX_EAPOL; older kexts reject that selectorsafely.
IOCTL_80211_WPA_KEYwas a no-op stub. It now delivers the PMK after EAP, or afailure status, which deauths.
OpenBSD's
SIOCS80211KEYAVAIL, soieee80211_recv_4way_msg1()picks it upas-is.
externalMethod()checks the input/output size against each selector'sstruct before the handler casts the buffer.
ClientKitheaders updated to match HeliPort's copy.Prebuilt binaries
Until this is merged, an unofficial prebuilt
itlwm.kext+HeliPort.appbuilt from these PRs is on my fork's releases page: https://github.com/dantdmdarealguy/itlwm/releases. The two only work together, and only with itlwm (not AirportItlwm).Testing
TAMU_WiFi(PEAP / MSCHAPv2):EAPOL-Start).
itlwmandAirportItlwm (all)(Debug), plusitlwmRelease.
Known limitations
TAMU_WiFi, the AP ran a second full EAP exchange about 3 s later. Bothsucceeded, but connectivity dropped for about 1.4 s.
ieee80211_recv_4way_msg1()rejects.