# DF-3326 — hostap association granted without completed authentication

**File:** `sys/netproto/802_11/wlan/ieee80211_hostap.c`
**Severity:** Medium · CWE-287/863 · confidence: certain · **REPRODUCED on the stock guest kernel**

## What

The ASSOC_REQ handler's only authentication gate is node-table existence:

```c
if (ni == vap->iv_bss) {              /* ieee80211_hostap.c:1953 */
        ... deny "sta not authenticated" (DEAUTH, ASSOC_NOT_AUTHED)
}
```

But a node-table entry is created by a **single shared-key auth REQUEST**
(`hostap_auth_shared()` `:1072-1083` `ieee80211_dup_bss()`) — before the
exchange ever completes. So on a shared-key (or auto) AP:

```
AUTH(shared, seq=1)            # 30 bytes; AP replies with the challenge
ASSOC_REQ                      # never sent the seq-3 response at all
=> ASSOC_RESP, AID assigned    # associated, AUTHORIZED=0
```

802.11-2016 11.3 requires authentication before association. Impact: AID
assignment + `list sta` entry + power-save queue eligibility + EAPOL (PAE)
pass-through for an unauthenticated station; repeated with distinct MACs it
exhausts the 128-entry AID space (cheap remote association-flood DoS).
(Discovered while validating the DF-3323 fix — the patched kernel refused to
*authorize* the station but still handed it an association.)

## How to reproduce

```
sh findings/poc/DF-3326/build.sh
sh findings/poc/DF-3326/run.sh
```

Success criterion (`run.log`):
```
control: fw4.attack=4 with no node   -> AP TX MGMT subtype 0xc0 (DEAUTH)   [correct]
attack:  fw4.attack=1 (request only) -> node AUTHORIZED=0
         fw4.attack=4                -> AP TX MGMT subtype 0x10 (ASSOC_RESP)
                                        associd 0xc001  AUTHORIZED=0        [bug]
```

## Fix validation

`fix.diff` widens the gate: deny association when `ni == iv_bss` **or**
(`ni_authmode ∈ {SHARED, AUTO}` and the port is not authorized) — those
authmodes complete authentication at the 802.11 layer, so authorized ==
authenticated; 802.1x/WPA legitimately defer auth until after association.
Validated on the rebuilt kernel (#1 21:29, both DF-3323+DF-3326 fixes):
`attack=1 → attack=4` now yields DEAUTH (`0xc0`) and `associd 0x0`; the
regression leg (open-authmode vap: open auth `attack=6` → AUTHORIZED=1 →
assoc) still gets `associd 0xc001`. See `fix.log`.
