wpa_supplicant disconnect bug

Chris Zimmermann cbzimmermann
Thu Aug 17 22:01:02 PDT 2006


In wpa_supplicant version 0.5.4,
	the file events.c,
	the function wpa_supplicant_event_disassoc()

static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s)
{
	const u8 *bssid;

	if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
		/*
		 * At least Host AP driver and a Prism3 card seemed to be
		 * generating streams of disconnected events when configuring
		 * IBSS for WPA-None. Ignore them for now.
		 */
		wpa_printf(MSG_DEBUG, "Disconnect event - ignore in "
			   "IBSS/WPA-None mode");
		return;
	}

	if (wpa_s->wpa_state == WPA_4WAY_HANDSHAKE &&
	    wpa_s->key_mgmt == WPA_KEY_MGMT_PSK) {
		wpa_msg(wpa_s, MSG_INFO, "WPA: 4-Way Handshake failed - "
			"pre-shared key may be incorrect");
	}
	if (wpa_s->wpa_state >= WPA_ASSOCIATED)
		wpa_supplicant_req_scan(wpa_s, 0, 100000);
	bssid = wpa_s->bssid;
	if (memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0)
		bssid = wpa_s->pending_bssid;
	wpa_blacklist_add(wpa_s, bssid);
	wpa_sm_notify_disassoc(wpa_s->wpa);
	wpa_supplicant_mark_disassoc(wpa_s);
	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "- Disconnect event - "
		"remove keys");
	if (wpa_supplicant_dynamic_keys(wpa_s)) {
		wpa_s->keys_cleared = 0;
		wpa_clear_keys(wpa_s, wpa_s->bssid);
	}
}

However, the function, wpa_supplicant_mark_disassoc() ends up setting  
the field wpa_s->bssid to all zeros (00:00:00:00:00:00).  When you  
call wpa_clear_keys() after this, the PTK is not really cleared.   
This leads to the inability to renegotiate WPA PTK, because the  
message 2/4 will go out encrypted and the authenticator will never  
get the message.

Changing the call to use a cached version of the BSSID held by  
wpa_supplicant_event_disassoc() corrects this issue.

static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s)
{
-	const u8 *bssid;
+	u8 bssid[ETH_ALEN];

	if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
		/*
		 * At least Host AP driver and a Prism3 card seemed to be
		 * generating streams of disconnected events when configuring
		 * IBSS for WPA-None. Ignore them for now.
		 */
		wpa_printf(MSG_DEBUG, "Disconnect event - ignore in "
			   "IBSS/WPA-None mode");
		return;
	}

	if (wpa_s->wpa_state == WPA_4WAY_HANDSHAKE &&
	    wpa_s->key_mgmt == WPA_KEY_MGMT_PSK) {
		wpa_msg(wpa_s, MSG_INFO, "WPA: 4-Way Handshake failed - "
			"pre-shared key may be incorrect");
	}
	if (wpa_s->wpa_state >= WPA_ASSOCIATED)
		wpa_supplicant_req_scan(wpa_s, 0, 100000);
-	bssid = wpa_s->bssid;
+	memcpy( bssid, wpa_s->bssid, ETH_ALEN);
	if (memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0)
-		bssid = wpa_s->pending_bssid;
+		memcpy( bssid, wpa_s->pending_bssid, ETH_ALEN);

	wpa_blacklist_add(wpa_s, bssid);
	wpa_sm_notify_disassoc(wpa_s->wpa);
	wpa_supplicant_mark_disassoc(wpa_s);
	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "- Disconnect event - "
		"remove keys");
	if (wpa_supplicant_dynamic_keys(wpa_s)) {
		wpa_s->keys_cleared = 0;
-		wpa_clear_keys(wpa_s, wpa_s->bssid);
+		wpa_clear_keys(wpa_s, bssid);
	}
}

I also think it would be more optimal to do this;

	if (memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0)
		memcpy( bssid, wpa_s->pending_bssid, ETH_ALEN);
	else
		memcpy( bssid, wpa_s->bssid, ETH_ALEN);

rather than this

	memcpy( bssid, wpa_s->bssid, ETH_ALEN);
	if (memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0)
		memcpy( bssid, wpa_s->pending_bssid, ETH_ALEN);


Thanks,
Chris

-- 
Chris Zimmermann
cbzimmermann at mac.com



-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.shmoo.com/pipermail/hostap/attachments/20060817/c18646d7/attachment.htm 



More information about the Hostap mailing list