]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
driver_nl80211: Fix MLME key settings for static WEP
authorJohannes Berg <johannes@sipsolutions.net>
Tue, 15 Sep 2009 07:48:30 +0000 (10:48 +0300)
committerJouni Malinen <j@w1.fi>
Tue, 15 Sep 2009 07:48:30 +0000 (10:48 +0300)
Current wpa_supplicant has a bug with WEP keys, it adds a zero-length
sequence counter field to netlink which the kernel doesn't accept.

Additionally, the kernel API slightly changed to accept keys only when
connected, so we need to send it the keys after that. For that to work
with shared key authentication, we also include the default WEP TX key
in the authentication command.

To upload the keys properly _after_ associating, add a new flag
WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE indicating that the driver
needs the keys at that point and not earlier.

src/drivers/driver.h
src/drivers/driver_nl80211.c
wpa_supplicant/events.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index 2ae5b1a0a5158d6d3dc4c23a48ca1326f1c3443e..c3be9d12762a354c3a34670a9a2b6930025f0d5f 100644 (file)
@@ -433,6 +433,7 @@ struct wpa_driver_capa {
 
 /* Driver generated WPA/RSN IE */
 #define WPA_DRIVER_FLAGS_DRIVER_IE     0x00000001
+/* Driver needs static WEP key setup after association command */
 #define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC 0x00000002
 #define WPA_DRIVER_FLAGS_USER_SPACE_MLME 0x00000004
 /* Driver takes care of RSN 4-way handshake internally; PMK is configured with
@@ -444,6 +445,8 @@ struct wpa_driver_capa {
 #define WPA_DRIVER_FLAGS_SME           0x00000020
 /* Driver supports AP mode */
 #define WPA_DRIVER_FLAGS_AP            0x00000040
+/* Driver needs static WEP key setup after association has been completed */
+#define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE     0x00000080
        unsigned int flags;
 
        int max_scan_ssids;
index fd1256d643e4674ce2f68929b8768b2829dd7c33..5f7d681b3754671cb6ba2ac62535a76145aa0184 100644 (file)
@@ -1170,6 +1170,8 @@ static int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
                return -1;
        }
 
+       drv->capa.flags |= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE;
+
        return 0;
 }
 #endif /* HOSTAPD */
@@ -1861,6 +1863,56 @@ nla_put_failure:
 
 
 #ifndef HOSTAPD
+static int nl_add_key(struct nl_msg *msg, wpa_alg alg,
+                     int key_idx, int defkey,
+                     const u8 *seq, size_t seq_len,
+                     const u8 *key, size_t key_len)
+{
+       struct nlattr *key_attr = nla_nest_start(msg, NL80211_ATTR_KEY);
+       if (!key_attr)
+               return -1;
+
+       if (defkey && alg == WPA_ALG_IGTK)
+               NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT_MGMT);
+       else if (defkey)
+               NLA_PUT_FLAG(msg, NL80211_KEY_DEFAULT);
+
+       NLA_PUT_U8(msg, NL80211_KEY_IDX, key_idx);
+
+       switch (alg) {
+       case WPA_ALG_WEP:
+               if (key_len == 5)
+                       NLA_PUT_U32(msg, NL80211_KEY_CIPHER, 0x000FAC01);
+               else
+                       NLA_PUT_U32(msg, NL80211_KEY_CIPHER, 0x000FAC05);
+               break;
+       case WPA_ALG_TKIP:
+               NLA_PUT_U32(msg, NL80211_KEY_CIPHER, 0x000FAC02);
+               break;
+       case WPA_ALG_CCMP:
+               NLA_PUT_U32(msg, NL80211_KEY_CIPHER, 0x000FAC04);
+               break;
+       case WPA_ALG_IGTK:
+               NLA_PUT_U32(msg, NL80211_KEY_CIPHER, 0x000FAC06);
+               break;
+       default:
+               wpa_printf(MSG_ERROR, "%s: Unsupported encryption "
+                          "algorithm %d", __func__, alg);
+               return -1;
+       }
+
+       if (seq && seq_len)
+               NLA_PUT(msg, NL80211_KEY_SEQ, seq_len, seq);
+
+       NLA_PUT(msg, NL80211_KEY_DATA, key_len, key);
+
+       nla_nest_end(msg, key_attr);
+
+       return 0;
+ nla_put_failure:
+       return -1;
+}
+
 
 static int nl80211_set_conn_keys(struct wpa_driver_associate_params *params,
                                 struct nl_msg *msg)
@@ -2012,6 +2064,9 @@ static int wpa_driver_nl80211_authenticate(
        wpa_printf(MSG_DEBUG, "nl80211: Authenticate (ifindex=%d)",
                   drv->ifindex);
 
+       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
+                   NL80211_CMD_AUTHENTICATE, 0);
+
        for (i = 0; i < 4; i++) {
                if (!params->wep_key[i])
                        continue;
@@ -2019,11 +2074,15 @@ static int wpa_driver_nl80211_authenticate(
                                           i == params->wep_tx_keyidx, NULL, 0,
                                           params->wep_key[i],
                                           params->wep_key_len[i]);
+               if (params->wep_tx_keyidx != i)
+                       continue;
+               if (nl_add_key(msg, WPA_ALG_WEP, i, 1, NULL, 0,
+                              params->wep_key[i], params->wep_key_len[i])) {
+                       nlmsg_free(msg);
+                       return -1;
+               }
        }
 
-       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
-                   NL80211_CMD_AUTHENTICATE, 0);
-
        NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
        if (params->bssid) {
                wpa_printf(MSG_DEBUG, "  * bssid=" MACSTR,
index de4c6fb5e17d25af70fab9a568a1fe6f7fa81ccd..e2c7a9fd86d02a2c690d87d907fc6bce72e8423d 100644 (file)
@@ -889,6 +889,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
        u8 bssid[ETH_ALEN];
        int ft_completed = wpa_ft_is_completed(wpa_s->wpa);
        int bssid_changed;
+       struct wpa_driver_capa capa;
 
        if (data)
                wpa_supplicant_event_associnfo(wpa_s, data);
@@ -1004,6 +1005,14 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
                        wpa_s->bgscan_ssid = NULL;
        }
 #endif /* CONFIG_BGSCAN */
+
+       if ((wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
+            wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
+           wpa_s->current_ssid && wpa_drv_get_capa(wpa_s, &capa) == 0 &&
+           capa.flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE) {
+               /* Set static WEP keys again */
+               wpa_set_wep_keys(wpa_s, wpa_s->current_ssid);
+       }
 }
 
 
index c2e5e55a78875f8d0aaf92654ec13cf7a3275e58..37a1927b2b7ca1eb40bf1337a93a692723b9acfb 100644 (file)
@@ -120,8 +120,7 @@ extern int wpa_debug_timestamp;
 extern struct wpa_driver_ops *wpa_drivers[];
 
 /* Configure default/group WEP keys for static WEP */
-static int wpa_set_wep_keys(struct wpa_supplicant *wpa_s,
-                           struct wpa_ssid *ssid)
+int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
 {
        int i, set = 0;
 
index 0872efc7ee07af71b21f91d3d56c13ab38176cd6..222be73a1a644c63e153a71820ed56d6171bb4a4 100644 (file)
@@ -396,6 +396,8 @@ struct wpa_supplicant {
 
 
 /* wpa_supplicant.c */
+int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+
 int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s);
 
 const char * wpa_supplicant_state_txt(int state);