]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
NDIS: Fix association for WPS provisioning with protected AP
authorJouni Malinen <j@w1.fi>
Sat, 4 Sep 2010 10:56:12 +0000 (13:56 +0300)
committerJouni Malinen <j@w1.fi>
Sat, 4 Sep 2010 10:56:12 +0000 (13:56 +0300)
Some NDIS drivers require a workaround to allow them to associate
with a WPS AP that is already using protection (Privacy field = 1).
Let driver_ndis.c know if the AP is already using Privacy and if so,
configure a dummy WEP key to force the driver to associate.

src/drivers/driver.h
src/drivers/driver_ndis.c
wpa_supplicant/wpa_supplicant.c

index 3c3bf9c9f61005426ca63e48bea3840c6e2c7bc6..4e40a38390ccfd50bdd8178d3c42aa94178ca1c5 100644 (file)
@@ -281,6 +281,13 @@ struct wpa_driver_auth_params {
        int local_state_change;
 };
 
+enum wps_mode {
+       WPS_MODE_NONE /* no WPS provisioning being used */,
+       WPS_MODE_OPEN /* WPS provisioning with AP that is in open mode */,
+       WPS_MODE_PRIVACY /* WPS provisioning with AP that is using protection
+                         */
+};
+
 /**
  * struct wpa_driver_associate_params - Association parameters
  * Data for struct wpa_driver_ops::associate().
@@ -460,6 +467,15 @@ struct wpa_driver_associate_params {
         * association.
         */
        const u8 *prev_bssid;
+
+       /**
+        * wps - WPS mode
+        *
+        * If the driver needs to do special configuration for WPS association,
+        * this variable provides more information on what type of association
+        * is being requested. Most drivers should not need ot use this.
+        */
+       enum wps_mode wps;
 };
 
 /**
index 462dd81f58af36c9efc635ffb62455b0f93fa447..6ce4200a499fb47efb96a1bd63bbc95dcdfe7591 100644 (file)
@@ -1066,6 +1066,7 @@ wpa_driver_ndis_associate(void *priv,
 {
        struct wpa_driver_ndis_data *drv = priv;
        u32 auth_mode, encr, priv_mode, mode;
+       u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
        drv->mode = params->mode;
 
@@ -1091,7 +1092,6 @@ wpa_driver_ndis_associate(void *priv,
        if (params->key_mgmt_suite == KEY_MGMT_NONE ||
            params->key_mgmt_suite == KEY_MGMT_802_1X_NO_WPA) {
                /* Re-set WEP keys if static WEP configuration is used. */
-               u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
                int i;
                for (i = 0; i < 4; i++) {
                        if (!params->wep_key[i])
@@ -1125,6 +1125,22 @@ wpa_driver_ndis_associate(void *priv,
        } else if (params->key_mgmt_suite == KEY_MGMT_WPS) {
                auth_mode = Ndis802_11AuthModeOpen;
                priv_mode = Ndis802_11PrivFilterAcceptAll;
+               if (params->wps == WPS_MODE_PRIVACY) {
+                       u8 dummy_key[5] = { 0x11, 0x22, 0x33, 0x44, 0x55 };
+                       /*
+                        * Some NDIS drivers refuse to associate in open mode
+                        * configuration due to Privacy field mismatch, so use
+                        * a workaround to make the configuration look like
+                        * matching one for WPS provisioning.
+                        */
+                       wpa_printf(MSG_DEBUG, "NDIS: Set dummy WEP key as a "
+                                  "workaround to allow driver to associate "
+                                  "for WPS");
+                       wpa_driver_ndis_set_key(drv->ifname, drv, WPA_ALG_WEP,
+                                               bcast, 0, 1,
+                                               NULL, 0, dummy_key,
+                                               sizeof(dummy_key));
+               }
 #endif /* CONFIG_WPS */
        } else {
                priv_mode = Ndis802_11PrivFilter8021xWEP;
@@ -1148,6 +1164,12 @@ wpa_driver_ndis_associate(void *priv,
                encr = Ndis802_11Encryption1Enabled;
                break;
        case CIPHER_NONE:
+#ifdef CONFIG_WPS
+               if (params->wps == WPS_MODE_PRIVACY) {
+                       encr = Ndis802_11Encryption1Enabled;
+                       break;
+               }
+#endif /* CONFIG_WPS */
                if (params->group_suite == CIPHER_CCMP)
                        encr = Ndis802_11Encryption3Enabled;
                else if (params->group_suite == CIPHER_TKIP)
@@ -1156,7 +1178,14 @@ wpa_driver_ndis_associate(void *priv,
                        encr = Ndis802_11EncryptionDisabled;
                break;
        default:
+#ifdef CONFIG_WPS
+               if (params->wps == WPS_MODE_PRIVACY) {
+                       encr = Ndis802_11Encryption1Enabled;
+                       break;
+               }
+#endif /* CONFIG_WPS */
                encr = Ndis802_11EncryptionDisabled;
+               break;
        };
 
        if (ndis_set_oid(drv, OID_802_11_PRIVACY_FILTER,
index bb7c913cddc8e87cc8b80dd3855459cea807a302..69c926a7774a5296ab703fd1187f12affa1f9567 100644 (file)
@@ -1024,6 +1024,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
                return;
        }
 
+       os_memset(&params, 0, sizeof(params));
        wpa_s->reassociate = 0;
        if (bss) {
 #ifdef CONFIG_IEEE80211R
@@ -1131,6 +1132,10 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
                        wpa_ie_len = 0;
                wpabuf_free(wps_ie);
                wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
+               if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
+                       params.wps = WPS_MODE_PRIVACY;
+               else
+                       params.wps = WPS_MODE_OPEN;
 #endif /* CONFIG_WPS */
        } else {
                wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
@@ -1175,7 +1180,6 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
        }
 
        wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
-       os_memset(&params, 0, sizeof(params));
        if (bss) {
                params.bssid = bss->bssid;
                params.ssid = bss->ssid;