diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 2ae5b1a0a..c3be9d127 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -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; diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index fd1256d64..5f7d681b3 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -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, diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index de4c6fb5e..e2c7a9fd8 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -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); + } } diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index c2e5e55a7..37a1927b2 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -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; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 0872efc7e..222be73a1 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -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);