driver_nl80211: Fix MLME key settings for static WEP

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.
This commit is contained in:
Johannes Berg 2009-09-15 10:48:30 +03:00 committed by Jouni Malinen
parent 60b94c9819
commit 0194fedb46
5 changed files with 77 additions and 5 deletions

View 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;

View 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,