2 * RSN pre-authentication (supplicant)
3 * Copyright (c) 2003-2010, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
20 #include "l2_packet/l2_packet.h"
21 #include "eapol_supp/eapol_supp_sm.h"
23 #include "pmksa_cache.h"
25 #include "common/ieee802_11_defs.h"
28 #if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2)
30 #define PMKID_CANDIDATE_PRIO_SCAN 1000
33 struct rsn_pmksa_candidate
{
41 * pmksa_candidate_free - Free all entries in PMKSA candidate list
42 * @sm: Pointer to WPA state machine data from wpa_sm_init()
44 void pmksa_candidate_free(struct wpa_sm
*sm
)
46 struct rsn_pmksa_candidate
*entry
, *n
;
51 dl_list_for_each_safe(entry
, n
, &sm
->pmksa_candidates
,
52 struct rsn_pmksa_candidate
, list
) {
53 dl_list_del(&entry
->list
);
59 static void rsn_preauth_receive(void *ctx
, const u8
*src_addr
,
60 const u8
*buf
, size_t len
)
62 struct wpa_sm
*sm
= ctx
;
64 wpa_printf(MSG_DEBUG
, "RX pre-auth from " MACSTR
, MAC2STR(src_addr
));
65 wpa_hexdump(MSG_MSGDUMP
, "RX pre-auth", buf
, len
);
67 if (sm
->preauth_eapol
== NULL
||
68 is_zero_ether_addr(sm
->preauth_bssid
) ||
69 os_memcmp(sm
->preauth_bssid
, src_addr
, ETH_ALEN
) != 0) {
70 wpa_printf(MSG_WARNING
, "RSN pre-auth frame received from "
71 "unexpected source " MACSTR
" - dropped",
76 eapol_sm_rx_eapol(sm
->preauth_eapol
, src_addr
, buf
, len
);
80 static void rsn_preauth_eapol_cb(struct eapol_sm
*eapol
, int success
,
83 struct wpa_sm
*sm
= ctx
;
89 res
= eapol_sm_get_key(eapol
, pmk
, PMK_LEN
);
92 * EAP-LEAP is an exception from other EAP methods: it
93 * uses only 16-byte PMK.
95 res
= eapol_sm_get_key(eapol
, pmk
, 16);
99 wpa_hexdump_key(MSG_DEBUG
, "RSN: PMK from pre-auth",
101 sm
->pmk_len
= pmk_len
;
102 pmksa_cache_add(sm
->pmksa
, pmk
, pmk_len
,
103 sm
->preauth_bssid
, sm
->own_addr
,
105 WPA_KEY_MGMT_IEEE8021X
);
107 wpa_msg(sm
->ctx
->msg_ctx
, MSG_INFO
,
108 "RSN: failed to get master session key from "
109 "pre-auth EAPOL state machines");
114 wpa_msg(sm
->ctx
->msg_ctx
, MSG_INFO
, "RSN: pre-authentication with "
115 MACSTR
" %s", MAC2STR(sm
->preauth_bssid
),
116 success
? "completed successfully" : "failed");
118 rsn_preauth_deinit(sm
);
119 rsn_preauth_candidate_process(sm
);
123 static void rsn_preauth_timeout(void *eloop_ctx
, void *timeout_ctx
)
125 struct wpa_sm
*sm
= eloop_ctx
;
127 wpa_msg(sm
->ctx
->msg_ctx
, MSG_INFO
, "RSN: pre-authentication with "
128 MACSTR
" timed out", MAC2STR(sm
->preauth_bssid
));
129 rsn_preauth_deinit(sm
);
130 rsn_preauth_candidate_process(sm
);
134 static int rsn_preauth_eapol_send(void *ctx
, int type
, const u8
*buf
,
137 struct wpa_sm
*sm
= ctx
;
142 /* TODO: could add l2_packet_sendmsg that allows fragments to avoid
145 if (sm
->l2_preauth
== NULL
)
148 msg
= wpa_sm_alloc_eapol(sm
, type
, buf
, len
, &msglen
, NULL
);
152 wpa_hexdump(MSG_MSGDUMP
, "TX EAPOL (preauth)", msg
, msglen
);
153 res
= l2_packet_send(sm
->l2_preauth
, sm
->preauth_bssid
,
154 ETH_P_RSN_PREAUTH
, msg
, msglen
);
161 * rsn_preauth_init - Start new RSN pre-authentication
162 * @sm: Pointer to WPA state machine data from wpa_sm_init()
163 * @dst: Authenticator address (BSSID) with which to preauthenticate
164 * @eap_conf: Current EAP configuration
165 * Returns: 0 on success, -1 on another pre-authentication is in progress,
166 * -2 on layer 2 packet initialization failure, -3 on EAPOL state machine
167 * initialization failure, -4 on memory allocation failure
169 * This function request an RSN pre-authentication with a given destination
170 * address. This is usually called for PMKSA candidates found from scan results
171 * or from driver reports. In addition, ctrl_iface PREAUTH command can trigger
172 * pre-authentication.
174 int rsn_preauth_init(struct wpa_sm
*sm
, const u8
*dst
,
175 struct eap_peer_config
*eap_conf
)
177 struct eapol_config eapol_conf
;
178 struct eapol_ctx
*ctx
;
180 if (sm
->preauth_eapol
)
183 wpa_msg(sm
->ctx
->msg_ctx
, MSG_DEBUG
,
184 "RSN: starting pre-authentication with " MACSTR
, MAC2STR(dst
));
186 sm
->l2_preauth
= l2_packet_init(sm
->ifname
, sm
->own_addr
,
188 rsn_preauth_receive
, sm
, 0);
189 if (sm
->l2_preauth
== NULL
) {
190 wpa_printf(MSG_WARNING
, "RSN: Failed to initialize L2 packet "
191 "processing for pre-authentication");
195 if (sm
->bridge_ifname
) {
196 sm
->l2_preauth_br
= l2_packet_init(sm
->bridge_ifname
,
199 rsn_preauth_receive
, sm
, 0);
200 if (sm
->l2_preauth_br
== NULL
) {
201 wpa_printf(MSG_WARNING
, "RSN: Failed to initialize L2 "
202 "packet processing (bridge) for "
203 "pre-authentication");
208 ctx
= os_zalloc(sizeof(*ctx
));
210 wpa_printf(MSG_WARNING
, "Failed to allocate EAPOL context.");
213 ctx
->ctx
= sm
->ctx
->ctx
;
214 ctx
->msg_ctx
= sm
->ctx
->ctx
;
216 ctx
->cb
= rsn_preauth_eapol_cb
;
218 ctx
->scard_ctx
= sm
->scard_ctx
;
219 ctx
->eapol_send
= rsn_preauth_eapol_send
;
220 ctx
->eapol_send_ctx
= sm
;
221 ctx
->set_config_blob
= sm
->ctx
->set_config_blob
;
222 ctx
->get_config_blob
= sm
->ctx
->get_config_blob
;
224 sm
->preauth_eapol
= eapol_sm_init(ctx
);
225 if (sm
->preauth_eapol
== NULL
) {
227 wpa_printf(MSG_WARNING
, "RSN: Failed to initialize EAPOL "
228 "state machines for pre-authentication");
231 os_memset(&eapol_conf
, 0, sizeof(eapol_conf
));
232 eapol_conf
.accept_802_1x_keys
= 0;
233 eapol_conf
.required_keys
= 0;
234 eapol_conf
.fast_reauth
= sm
->fast_reauth
;
235 eapol_conf
.workaround
= sm
->eap_workaround
;
236 eapol_sm_notify_config(sm
->preauth_eapol
, eap_conf
, &eapol_conf
);
238 * Use a shorter startPeriod with preauthentication since the first
239 * preauth EAPOL-Start frame may end up being dropped due to race
240 * condition in the AP between the data receive and key configuration
241 * after the 4-Way Handshake.
243 eapol_sm_configure(sm
->preauth_eapol
, -1, -1, 5, 6);
244 os_memcpy(sm
->preauth_bssid
, dst
, ETH_ALEN
);
246 eapol_sm_notify_portValid(sm
->preauth_eapol
, TRUE
);
247 /* 802.1X::portControl = Auto */
248 eapol_sm_notify_portEnabled(sm
->preauth_eapol
, TRUE
);
250 eloop_register_timeout(sm
->dot11RSNAConfigSATimeout
, 0,
251 rsn_preauth_timeout
, sm
, NULL
);
258 * rsn_preauth_deinit - Abort RSN pre-authentication
259 * @sm: Pointer to WPA state machine data from wpa_sm_init()
261 * This function aborts the current RSN pre-authentication (if one is started)
262 * and frees resources allocated for it.
264 void rsn_preauth_deinit(struct wpa_sm
*sm
)
266 if (sm
== NULL
|| !sm
->preauth_eapol
)
269 eloop_cancel_timeout(rsn_preauth_timeout
, sm
, NULL
);
270 eapol_sm_deinit(sm
->preauth_eapol
);
271 sm
->preauth_eapol
= NULL
;
272 os_memset(sm
->preauth_bssid
, 0, ETH_ALEN
);
274 l2_packet_deinit(sm
->l2_preauth
);
275 sm
->l2_preauth
= NULL
;
276 if (sm
->l2_preauth_br
) {
277 l2_packet_deinit(sm
->l2_preauth_br
);
278 sm
->l2_preauth_br
= NULL
;
284 * rsn_preauth_candidate_process - Process PMKSA candidates
285 * @sm: Pointer to WPA state machine data from wpa_sm_init()
287 * Go through the PMKSA candidates and start pre-authentication if a candidate
288 * without an existing PMKSA cache entry is found. Processed candidates will be
289 * removed from the list.
291 void rsn_preauth_candidate_process(struct wpa_sm
*sm
)
293 struct rsn_pmksa_candidate
*candidate
, *n
;
295 if (dl_list_empty(&sm
->pmksa_candidates
))
298 /* TODO: drop priority for old candidate entries */
300 wpa_msg(sm
->ctx
->msg_ctx
, MSG_DEBUG
, "RSN: processing PMKSA candidate "
302 if (sm
->preauth_eapol
||
303 sm
->proto
!= WPA_PROTO_RSN
||
304 wpa_sm_get_state(sm
) != WPA_COMPLETED
||
305 (sm
->key_mgmt
!= WPA_KEY_MGMT_IEEE8021X
&&
306 sm
->key_mgmt
!= WPA_KEY_MGMT_IEEE8021X_SHA256
)) {
307 wpa_msg(sm
->ctx
->msg_ctx
, MSG_DEBUG
, "RSN: not in suitable "
308 "state for new pre-authentication");
309 return; /* invalid state for new pre-auth */
312 dl_list_for_each_safe(candidate
, n
, &sm
->pmksa_candidates
,
313 struct rsn_pmksa_candidate
, list
) {
314 struct rsn_pmksa_cache_entry
*p
= NULL
;
315 p
= pmksa_cache_get(sm
->pmksa
, candidate
->bssid
, NULL
);
316 if (os_memcmp(sm
->bssid
, candidate
->bssid
, ETH_ALEN
) != 0 &&
317 (p
== NULL
|| p
->opportunistic
)) {
318 wpa_msg(sm
->ctx
->msg_ctx
, MSG_DEBUG
, "RSN: PMKSA "
320 " selected for pre-authentication",
321 MAC2STR(candidate
->bssid
));
322 dl_list_del(&candidate
->list
);
323 rsn_preauth_init(sm
, candidate
->bssid
,
328 wpa_msg(sm
->ctx
->msg_ctx
, MSG_DEBUG
, "RSN: PMKSA candidate "
329 MACSTR
" does not need pre-authentication anymore",
330 MAC2STR(candidate
->bssid
));
331 /* Some drivers (e.g., NDIS) expect to get notified about the
332 * PMKIDs again, so report the existing data now. */
334 wpa_sm_add_pmkid(sm
, candidate
->bssid
, p
->pmkid
);
337 dl_list_del(&candidate
->list
);
340 wpa_msg(sm
->ctx
->msg_ctx
, MSG_DEBUG
, "RSN: no more pending PMKSA "
346 * pmksa_candidate_add - Add a new PMKSA candidate
347 * @sm: Pointer to WPA state machine data from wpa_sm_init()
348 * @bssid: BSSID (authenticator address) of the candidate
349 * @prio: Priority (the smaller number, the higher priority)
350 * @preauth: Whether the candidate AP advertises support for pre-authentication
352 * This function is used to add PMKSA candidates for RSN pre-authentication. It
353 * is called from scan result processing and from driver events for PMKSA
354 * candidates, i.e., EVENT_PMKID_CANDIDATE events to wpa_supplicant_event().
356 void pmksa_candidate_add(struct wpa_sm
*sm
, const u8
*bssid
,
357 int prio
, int preauth
)
359 struct rsn_pmksa_candidate
*cand
, *pos
;
361 if (sm
->network_ctx
&& sm
->proactive_key_caching
)
362 pmksa_cache_get_opportunistic(sm
->pmksa
, sm
->network_ctx
,
366 wpa_printf(MSG_DEBUG
, "RSN: Ignored PMKID candidate without "
371 /* If BSSID already on candidate list, update the priority of the old
372 * entry. Do not override priority based on normal scan results. */
374 dl_list_for_each(pos
, &sm
->pmksa_candidates
,
375 struct rsn_pmksa_candidate
, list
) {
376 if (os_memcmp(pos
->bssid
, bssid
, ETH_ALEN
) == 0) {
383 dl_list_del(&cand
->list
);
384 if (prio
< PMKID_CANDIDATE_PRIO_SCAN
)
385 cand
->priority
= prio
;
387 cand
= os_zalloc(sizeof(*cand
));
390 os_memcpy(cand
->bssid
, bssid
, ETH_ALEN
);
391 cand
->priority
= prio
;
394 /* Add candidate to the list; order by increasing priority value. i.e.,
395 * highest priority (smallest value) first. */
396 dl_list_for_each(pos
, &sm
->pmksa_candidates
,
397 struct rsn_pmksa_candidate
, list
) {
398 if (cand
->priority
<= pos
->priority
) {
399 dl_list_add(pos
->list
.prev
, &cand
->list
);
405 dl_list_add_tail(&sm
->pmksa_candidates
, &cand
->list
);
407 wpa_msg(sm
->ctx
->msg_ctx
, MSG_DEBUG
, "RSN: added PMKSA cache "
408 "candidate " MACSTR
" prio %d", MAC2STR(bssid
), prio
);
409 rsn_preauth_candidate_process(sm
);
413 /* TODO: schedule periodic scans if current AP supports preauth */
416 * rsn_preauth_scan_results - Start processing scan results for canditates
417 * @sm: Pointer to WPA state machine data from wpa_sm_init()
418 * Returns: 0 if ready to process results or -1 to skip processing
420 * This functions is used to notify RSN code about start of new scan results
421 * processing. The actual scan results will be provided by calling
422 * rsn_preauth_scan_result() for each BSS if this function returned 0.
424 int rsn_preauth_scan_results(struct wpa_sm
*sm
)
426 if (sm
->ssid_len
== 0)
430 * TODO: is it ok to free all candidates? What about the entries
431 * received from EVENT_PMKID_CANDIDATE?
433 pmksa_candidate_free(sm
);
440 * rsn_preauth_scan_result - Processing scan result for PMKSA canditates
441 * @sm: Pointer to WPA state machine data from wpa_sm_init()
443 * Add all suitable APs (Authenticators) from scan results into PMKSA
446 void rsn_preauth_scan_result(struct wpa_sm
*sm
, const u8
*bssid
,
447 const u8
*ssid
, const u8
*rsn
)
449 struct wpa_ie_data ie
;
450 struct rsn_pmksa_cache_entry
*pmksa
;
452 if (ssid
[1] != sm
->ssid_len
||
453 os_memcmp(ssid
+ 2, sm
->ssid
, sm
->ssid_len
) != 0)
454 return; /* Not for the current SSID */
456 if (os_memcmp(bssid
, sm
->bssid
, ETH_ALEN
) == 0)
457 return; /* Ignore current AP */
459 if (wpa_parse_wpa_ie(rsn
, 2 + rsn
[1], &ie
))
462 pmksa
= pmksa_cache_get(sm
->pmksa
, bssid
, NULL
);
463 if (pmksa
&& (!pmksa
->opportunistic
||
464 !(ie
.capabilities
& WPA_CAPABILITY_PREAUTH
)))
467 /* Give less priority to candidates found from normal scan results. */
468 pmksa_candidate_add(sm
, bssid
, PMKID_CANDIDATE_PRIO_SCAN
,
469 ie
.capabilities
& WPA_CAPABILITY_PREAUTH
);
473 #ifdef CONFIG_CTRL_IFACE
475 * rsn_preauth_get_status - Get pre-authentication status
476 * @sm: Pointer to WPA state machine data from wpa_sm_init()
477 * @buf: Buffer for status information
478 * @buflen: Maximum buffer length
479 * @verbose: Whether to include verbose status information
480 * Returns: Number of bytes written to buf.
482 * Query WPA2 pre-authentication for status information. This function fills in
483 * a text area with current status information. If the buffer (buf) is not
484 * large enough, status information will be truncated to fit the buffer.
486 int rsn_preauth_get_status(struct wpa_sm
*sm
, char *buf
, size_t buflen
,
489 char *pos
= buf
, *end
= buf
+ buflen
;
492 if (sm
->preauth_eapol
) {
493 ret
= os_snprintf(pos
, end
- pos
, "Pre-authentication "
494 "EAPOL state machines:\n");
495 if (ret
< 0 || ret
>= end
- pos
)
498 res
= eapol_sm_get_status(sm
->preauth_eapol
,
499 pos
, end
- pos
, verbose
);
506 #endif /* CONFIG_CTRL_IFACE */
510 * rsn_preauth_in_progress - Verify whether pre-authentication is in progress
511 * @sm: Pointer to WPA state machine data from wpa_sm_init()
513 int rsn_preauth_in_progress(struct wpa_sm
*sm
)
515 return sm
->preauth_eapol
!= NULL
;
518 #endif /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */