When announcing RSN (WPA2) capabilities in management frames such as
association requests, we currently echo back all RSN (i.e. WPA2)
capabilities which were announced by our peer.

This is bad in case the peer announces features we don't support.
One such feature is Management Frame Protection (MFP). If we announce this
capability then the peer sends us encrypted management frames which won't be
processed. One symptom of this is that we fail to negotiate 11n block ack
with APs that enable MFP if the client announces support for MFP (problem
found by sthen@).

With this patch we only echo the RSN capalibities which we actually support.
I am handling MFP and PBAR bits here as done elsewhere, but note that
neither of these features is enabled yet at run-time.
(We do have code for MFP; but it is untested, and disabled in all of our
wifi drivers. That's for another day...)

ok?

diff 18e888c6238d4d2767f9b9d181633c8a9b33b1a3 /usr/src
blob - 1610fbf508ab3f6fb12721ee5c1ba7f56c0a94b3
file + sys/net80211/ieee80211_output.c
--- sys/net80211/ieee80211_output.c
+++ sys/net80211/ieee80211_output.c
@@ -941,7 +941,7 @@ ieee80211_add_rsn_body(u_int8_t *frm, struct ieee80211
 {
        const u_int8_t *oui = wpa ? MICROSOFT_OUI : IEEE80211_OUI;
        u_int8_t *pcount;
-       u_int16_t count;
+       u_int16_t count, rsncaps;
 
        /* write Version field */
        LE_WRITE_2(frm, 1); frm += 2;
@@ -1017,7 +1017,16 @@ ieee80211_add_rsn_body(u_int8_t *frm, struct ieee80211
                return frm;
 
        /* write RSN Capabilities field */
-       LE_WRITE_2(frm, ni->ni_rsncaps); frm += 2;
+       rsncaps = (ni->ni_rsncaps & (IEEE80211_RSNCAP_PTKSA_RCNT_MASK |
+           IEEE80211_RSNCAP_GTKSA_RCNT_MASK));
+       if (ic->ic_caps & IEEE80211_C_MFP) {
+               rsncaps |= IEEE80211_RSNCAP_MFPC;
+               if (ic->ic_flags & IEEE80211_F_MFPR)
+                       rsncaps |= IEEE80211_RSNCAP_MFPR;
+       }
+       if (ic->ic_flags & IEEE80211_F_PBAR)
+               rsncaps |= IEEE80211_RSNCAP_PBAC;
+       LE_WRITE_2(frm, rsncaps); frm += 2;
 
        if (ni->ni_flags & IEEE80211_NODE_PMKID) {
                /* write PMKID Count field */


Reply via email to