1  /*
2   * RSN pre-authentication (supplicant)
3   * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
4   *
5   * This software may be distributed under the terms of the BSD license.
6   * See README for more details.
7   */
8  
9  #include "includes.h"
10  
11  #include "common.h"
12  #include "wpa.h"
13  #include "eloop.h"
14  #include "l2_packet/l2_packet.h"
15  #include "eapol_supp/eapol_supp_sm.h"
16  #include "preauth.h"
17  #include "pmksa_cache.h"
18  #include "wpa_i.h"
19  
20  
21  #if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA)
22  
23  #define PMKID_CANDIDATE_PRIO_SCAN 1000
24  
25  
26  struct rsn_pmksa_candidate {
27  	struct dl_list list;
28  	u8 bssid[ETH_ALEN];
29  	int priority;
30  };
31  
32  
33  /**
34   * pmksa_candidate_free - Free all entries in PMKSA candidate list
35   * @sm: Pointer to WPA state machine data from wpa_sm_init()
36   */
pmksa_candidate_free(struct wpa_sm * sm)37  void pmksa_candidate_free(struct wpa_sm *sm)
38  {
39  	struct rsn_pmksa_candidate *entry, *n;
40  
41  	if (sm == NULL)
42  		return;
43  
44  	dl_list_for_each_safe(entry, n, &sm->pmksa_candidates,
45  			      struct rsn_pmksa_candidate, list) {
46  		dl_list_del(&entry->list);
47  		os_free(entry);
48  	}
49  }
50  
51  
rsn_preauth_key_mgmt(int akmp)52  static int rsn_preauth_key_mgmt(int akmp)
53  {
54  	return !!(akmp & (WPA_KEY_MGMT_IEEE8021X |
55  			  WPA_KEY_MGMT_IEEE8021X_SHA256 |
56  			  WPA_KEY_MGMT_IEEE8021X_SUITE_B |
57  			  WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 |
58  			  WPA_KEY_MGMT_IEEE8021X_SHA384));
59  }
60  
61  
rsn_preauth_receive(void * ctx,const u8 * src_addr,const u8 * buf,size_t len)62  static void rsn_preauth_receive(void *ctx, const u8 *src_addr,
63  				const u8 *buf, size_t len)
64  {
65  	struct wpa_sm *sm = ctx;
66  
67  	wpa_printf(MSG_DEBUG, "RX pre-auth from " MACSTR, MAC2STR(src_addr));
68  	wpa_hexdump(MSG_MSGDUMP, "RX pre-auth", buf, len);
69  
70  	if (sm->preauth_eapol == NULL ||
71  	    is_zero_ether_addr(sm->preauth_bssid) ||
72  	    !ether_addr_equal(sm->preauth_bssid, src_addr)) {
73  		wpa_printf(MSG_WARNING, "RSN pre-auth frame received from "
74  			   "unexpected source " MACSTR " - dropped",
75  			   MAC2STR(src_addr));
76  		return;
77  	}
78  
79  	eapol_sm_rx_eapol(sm->preauth_eapol, src_addr, buf, len,
80  			  FRAME_ENCRYPTION_UNKNOWN);
81  }
82  
83  
rsn_preauth_eapol_cb(struct eapol_sm * eapol,enum eapol_supp_result result,void * ctx)84  static void rsn_preauth_eapol_cb(struct eapol_sm *eapol,
85  				 enum eapol_supp_result result,
86  				 void *ctx)
87  {
88  	struct wpa_sm *sm = ctx;
89  	u8 pmk[PMK_LEN];
90  
91  	if (result == EAPOL_SUPP_RESULT_SUCCESS) {
92  		int res, pmk_len;
93  		pmk_len = PMK_LEN;
94  		res = eapol_sm_get_key(eapol, pmk, PMK_LEN);
95  		if (res) {
96  			/*
97  			 * EAP-LEAP is an exception from other EAP methods: it
98  			 * uses only 16-byte PMK.
99  			 */
100  			res = eapol_sm_get_key(eapol, pmk, 16);
101  			pmk_len = 16;
102  		}
103  		if (res == 0) {
104  			wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from pre-auth",
105  					pmk, pmk_len);
106  			sm->pmk_len = pmk_len;
107  			pmksa_cache_add(sm->pmksa, pmk, pmk_len, NULL,
108  					NULL, 0,
109  					sm->preauth_bssid, sm->own_addr,
110  					sm->network_ctx,
111  					WPA_KEY_MGMT_IEEE8021X, NULL);
112  		} else {
113  			wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
114  				"RSN: failed to get master session key from "
115  				"pre-auth EAPOL state machines");
116  			result = EAPOL_SUPP_RESULT_FAILURE;
117  		}
118  	}
119  
120  	wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "RSN: pre-authentication with "
121  		MACSTR " %s", MAC2STR(sm->preauth_bssid),
122  		result == EAPOL_SUPP_RESULT_SUCCESS ? "completed successfully" :
123  		"failed");
124  
125  	rsn_preauth_deinit(sm);
126  	rsn_preauth_candidate_process(sm);
127  }
128  
129  
rsn_preauth_timeout(void * eloop_ctx,void * timeout_ctx)130  static void rsn_preauth_timeout(void *eloop_ctx, void *timeout_ctx)
131  {
132  	struct wpa_sm *sm = eloop_ctx;
133  
134  	wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "RSN: pre-authentication with "
135  		MACSTR " timed out", MAC2STR(sm->preauth_bssid));
136  	rsn_preauth_deinit(sm);
137  	rsn_preauth_candidate_process(sm);
138  }
139  
140  
rsn_preauth_eapol_send(void * ctx,int type,const u8 * buf,size_t len)141  static int rsn_preauth_eapol_send(void *ctx, int type, const u8 *buf,
142  				  size_t len)
143  {
144  	struct wpa_sm *sm = ctx;
145  	u8 *msg;
146  	size_t msglen;
147  	int res;
148  
149  	/* TODO: could add l2_packet_sendmsg that allows fragments to avoid
150  	 * extra copy here */
151  
152  	if (sm->l2_preauth == NULL)
153  		return -1;
154  
155  	msg = wpa_sm_alloc_eapol(sm, type, buf, len, &msglen, NULL);
156  	if (msg == NULL)
157  		return -1;
158  
159  	wpa_hexdump(MSG_MSGDUMP, "TX EAPOL (preauth)", msg, msglen);
160  	res = l2_packet_send(sm->l2_preauth, sm->preauth_bssid,
161  			     ETH_P_RSN_PREAUTH, msg, msglen);
162  	os_free(msg);
163  	return res;
164  }
165  
166  
167  /**
168   * rsn_preauth_init - Start new RSN pre-authentication
169   * @sm: Pointer to WPA state machine data from wpa_sm_init()
170   * @dst: Authenticator address (BSSID) with which to preauthenticate
171   * @eap_conf: Current EAP configuration
172   * Returns: 0 on success, -1 on another pre-authentication is in progress,
173   * -2 on layer 2 packet initialization failure, -3 on EAPOL state machine
174   * initialization failure, -4 on memory allocation failure
175   *
176   * This function request an RSN pre-authentication with a given destination
177   * address. This is usually called for PMKSA candidates found from scan results
178   * or from driver reports. In addition, ctrl_iface PREAUTH command can trigger
179   * pre-authentication.
180   */
rsn_preauth_init(struct wpa_sm * sm,const u8 * dst,struct eap_peer_config * eap_conf)181  int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst,
182  		     struct eap_peer_config *eap_conf)
183  {
184  	struct eapol_config eapol_conf;
185  	struct eapol_ctx *ctx;
186  	int ret;
187  
188  	if (sm->preauth_eapol)
189  		return -1;
190  
191  	wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG,
192  		"RSN: starting pre-authentication with " MACSTR, MAC2STR(dst));
193  
194  	sm->l2_preauth = l2_packet_init(sm->ifname, sm->own_addr,
195  					ETH_P_RSN_PREAUTH,
196  					rsn_preauth_receive, sm, 0);
197  	if (sm->l2_preauth == NULL) {
198  		wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 packet "
199  			   "processing for pre-authentication");
200  		return -2;
201  	}
202  
203  	if (sm->bridge_ifname) {
204  		sm->l2_preauth_br = l2_packet_init(sm->bridge_ifname,
205  						   sm->own_addr,
206  						   ETH_P_RSN_PREAUTH,
207  						   rsn_preauth_receive, sm, 0);
208  		if (sm->l2_preauth_br == NULL) {
209  			wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 "
210  				   "packet processing (bridge) for "
211  				   "pre-authentication");
212  			ret = -2;
213  			goto fail;
214  		}
215  	}
216  
217  	ctx = os_zalloc(sizeof(*ctx));
218  	if (ctx == NULL) {
219  		wpa_printf(MSG_WARNING, "Failed to allocate EAPOL context.");
220  		ret = -4;
221  		goto fail;
222  	}
223  	ctx->ctx = sm->ctx->ctx;
224  	ctx->msg_ctx = sm->ctx->ctx;
225  	ctx->preauth = 1;
226  	ctx->cb = rsn_preauth_eapol_cb;
227  	ctx->cb_ctx = sm;
228  	ctx->scard_ctx = sm->scard_ctx;
229  	ctx->eapol_send = rsn_preauth_eapol_send;
230  	ctx->eapol_send_ctx = sm;
231  	ctx->set_config_blob = sm->ctx->set_config_blob;
232  	ctx->get_config_blob = sm->ctx->get_config_blob;
233  
234  	sm->preauth_eapol = eapol_sm_init(ctx);
235  	if (sm->preauth_eapol == NULL) {
236  		os_free(ctx);
237  		wpa_printf(MSG_WARNING, "RSN: Failed to initialize EAPOL "
238  			   "state machines for pre-authentication");
239  		ret = -3;
240  		goto fail;
241  	}
242  	os_memset(&eapol_conf, 0, sizeof(eapol_conf));
243  	eapol_conf.accept_802_1x_keys = 0;
244  	eapol_conf.required_keys = 0;
245  	eapol_conf.fast_reauth = sm->fast_reauth;
246  	eapol_conf.workaround = sm->eap_workaround;
247  	eapol_sm_notify_config(sm->preauth_eapol, eap_conf, &eapol_conf);
248  	/*
249  	 * Use a shorter startPeriod with preauthentication since the first
250  	 * preauth EAPOL-Start frame may end up being dropped due to race
251  	 * condition in the AP between the data receive and key configuration
252  	 * after the 4-Way Handshake.
253  	 */
254  	eapol_sm_configure(sm->preauth_eapol, -1, -1, 5, 6);
255  	os_memcpy(sm->preauth_bssid, dst, ETH_ALEN);
256  
257  	eapol_sm_notify_portValid(sm->preauth_eapol, true);
258  	/* 802.1X::portControl = Auto */
259  	eapol_sm_notify_portEnabled(sm->preauth_eapol, true);
260  
261  	eloop_register_timeout(sm->dot11RSNAConfigSATimeout, 0,
262  			       rsn_preauth_timeout, sm, NULL);
263  
264  	return 0;
265  
266  fail:
267  	if (sm->l2_preauth_br) {
268  		l2_packet_deinit(sm->l2_preauth_br);
269  		sm->l2_preauth_br = NULL;
270  	}
271  	l2_packet_deinit(sm->l2_preauth);
272  	sm->l2_preauth = NULL;
273  	return ret;
274  }
275  
276  
277  /**
278   * rsn_preauth_deinit - Abort RSN pre-authentication
279   * @sm: Pointer to WPA state machine data from wpa_sm_init()
280   *
281   * This function aborts the current RSN pre-authentication (if one is started)
282   * and frees resources allocated for it.
283   */
rsn_preauth_deinit(struct wpa_sm * sm)284  void rsn_preauth_deinit(struct wpa_sm *sm)
285  {
286  	if (sm == NULL || !sm->preauth_eapol)
287  		return;
288  
289  	eloop_cancel_timeout(rsn_preauth_timeout, sm, NULL);
290  	eapol_sm_deinit(sm->preauth_eapol);
291  	sm->preauth_eapol = NULL;
292  	os_memset(sm->preauth_bssid, 0, ETH_ALEN);
293  
294  	l2_packet_deinit(sm->l2_preauth);
295  	sm->l2_preauth = NULL;
296  	if (sm->l2_preauth_br) {
297  		l2_packet_deinit(sm->l2_preauth_br);
298  		sm->l2_preauth_br = NULL;
299  	}
300  }
301  
302  
303  /**
304   * rsn_preauth_candidate_process - Process PMKSA candidates
305   * @sm: Pointer to WPA state machine data from wpa_sm_init()
306   *
307   * Go through the PMKSA candidates and start pre-authentication if a candidate
308   * without an existing PMKSA cache entry is found. Processed candidates will be
309   * removed from the list.
310   */
rsn_preauth_candidate_process(struct wpa_sm * sm)311  void rsn_preauth_candidate_process(struct wpa_sm *sm)
312  {
313  	struct rsn_pmksa_candidate *candidate, *n;
314  
315  	if (dl_list_empty(&sm->pmksa_candidates))
316  		return;
317  
318  	/* TODO: drop priority for old candidate entries */
319  
320  	wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: processing PMKSA candidate "
321  		"list");
322  	if (sm->preauth_eapol ||
323  	    sm->proto != WPA_PROTO_RSN ||
324  	    wpa_sm_get_state(sm) != WPA_COMPLETED ||
325  	    !rsn_preauth_key_mgmt(sm->key_mgmt)) {
326  		wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: not in suitable "
327  			"state for new pre-authentication");
328  		return; /* invalid state for new pre-auth */
329  	}
330  
331  	dl_list_for_each_safe(candidate, n, &sm->pmksa_candidates,
332  			      struct rsn_pmksa_candidate, list) {
333  		struct rsn_pmksa_cache_entry *p = NULL;
334  		p = pmksa_cache_get(sm->pmksa, candidate->bssid, sm->own_addr,
335  				    NULL, NULL, 0);
336  		if (!ether_addr_equal(sm->bssid, candidate->bssid) &&
337  		    (p == NULL || p->opportunistic)) {
338  			wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA "
339  				"candidate " MACSTR
340  				" selected for pre-authentication",
341  				MAC2STR(candidate->bssid));
342  			dl_list_del(&candidate->list);
343  			rsn_preauth_init(sm, candidate->bssid,
344  					 sm->eap_conf_ctx);
345  			os_free(candidate);
346  			return;
347  		}
348  		wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA candidate "
349  			MACSTR " does not need pre-authentication anymore",
350  			MAC2STR(candidate->bssid));
351  		/* Some drivers (e.g., NDIS) expect to get notified about the
352  		 * PMKIDs again, so report the existing data now. */
353  		if (p) {
354  			wpa_sm_add_pmkid(sm, NULL, candidate->bssid, p->pmkid,
355  					 NULL, p->pmk, p->pmk_len, 0, 0,
356  					 p->akmp);
357  		}
358  
359  		dl_list_del(&candidate->list);
360  		os_free(candidate);
361  	}
362  	wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: no more pending PMKSA "
363  		"candidates");
364  }
365  
366  
367  /**
368   * pmksa_candidate_add - Add a new PMKSA candidate
369   * @sm: Pointer to WPA state machine data from wpa_sm_init()
370   * @bssid: BSSID (authenticator address) of the candidate
371   * @prio: Priority (the smaller number, the higher priority)
372   * @preauth: Whether the candidate AP advertises support for pre-authentication
373   *
374   * This function is used to add PMKSA candidates for RSN pre-authentication. It
375   * is called from scan result processing and from driver events for PMKSA
376   * candidates, i.e., EVENT_PMKID_CANDIDATE events to wpa_supplicant_event().
377   */
pmksa_candidate_add(struct wpa_sm * sm,const u8 * bssid,int prio,int preauth)378  void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid,
379  			 int prio, int preauth)
380  {
381  	struct rsn_pmksa_candidate *cand, *pos;
382  
383  	if (sm->network_ctx && sm->proactive_key_caching)
384  		pmksa_cache_get_opportunistic(sm->pmksa, sm->network_ctx,
385  					      bssid, 0);
386  
387  	if (!preauth) {
388  		wpa_printf(MSG_DEBUG, "RSN: Ignored PMKID candidate without "
389  			   "preauth flag");
390  		return;
391  	}
392  
393  	/* If BSSID already on candidate list, update the priority of the old
394  	 * entry. Do not override priority based on normal scan results. */
395  	cand = NULL;
396  	dl_list_for_each(pos, &sm->pmksa_candidates,
397  			 struct rsn_pmksa_candidate, list) {
398  		if (ether_addr_equal(pos->bssid, bssid)) {
399  			cand = pos;
400  			break;
401  		}
402  	}
403  
404  	if (cand) {
405  		dl_list_del(&cand->list);
406  		if (prio < PMKID_CANDIDATE_PRIO_SCAN)
407  			cand->priority = prio;
408  	} else {
409  		cand = os_zalloc(sizeof(*cand));
410  		if (cand == NULL)
411  			return;
412  		os_memcpy(cand->bssid, bssid, ETH_ALEN);
413  		cand->priority = prio;
414  	}
415  
416  	/* Add candidate to the list; order by increasing priority value. i.e.,
417  	 * highest priority (smallest value) first. */
418  	dl_list_for_each(pos, &sm->pmksa_candidates,
419  			 struct rsn_pmksa_candidate, list) {
420  		if (cand->priority <= pos->priority) {
421  			if (!pos->list.prev) {
422  				/*
423  				 * This cannot really happen in pracrice since
424  				 * pos was fetched from the list and the prev
425  				 * pointer must be set. It looks like clang
426  				 * static analyzer gets confused with the
427  				 * dl_list_del(&cand->list) call above and ends
428  				 * up assuming pos->list.prev could be NULL.
429  				 */
430  				os_free(cand);
431  				return;
432  			}
433  			dl_list_add(pos->list.prev, &cand->list);
434  			cand = NULL;
435  			break;
436  		}
437  	}
438  	if (cand)
439  		dl_list_add_tail(&sm->pmksa_candidates, &cand->list);
440  
441  	wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: added PMKSA cache "
442  		"candidate " MACSTR " prio %d", MAC2STR(bssid), prio);
443  	rsn_preauth_candidate_process(sm);
444  }
445  
446  
447  /* TODO: schedule periodic scans if current AP supports preauth */
448  
449  /**
450   * rsn_preauth_scan_results - Start processing scan results for canditates
451   * @sm: Pointer to WPA state machine data from wpa_sm_init()
452   * Returns: 0 if ready to process results or -1 to skip processing
453   *
454   * This functions is used to notify RSN code about start of new scan results
455   * processing. The actual scan results will be provided by calling
456   * rsn_preauth_scan_result() for each BSS if this function returned 0.
457   */
rsn_preauth_scan_results(struct wpa_sm * sm)458  int rsn_preauth_scan_results(struct wpa_sm *sm)
459  {
460  	if (sm->ssid_len == 0)
461  		return -1;
462  
463  	/*
464  	 * TODO: is it ok to free all candidates? What about the entries
465  	 * received from EVENT_PMKID_CANDIDATE?
466  	 */
467  	pmksa_candidate_free(sm);
468  
469  	return 0;
470  }
471  
472  
473  /**
474   * rsn_preauth_scan_result - Processing scan result for PMKSA canditates
475   * @sm: Pointer to WPA state machine data from wpa_sm_init()
476   *
477   * Add all suitable APs (Authenticators) from scan results into PMKSA
478   * candidate list.
479   */
rsn_preauth_scan_result(struct wpa_sm * sm,const u8 * bssid,const u8 * ssid,const u8 * rsn)480  void rsn_preauth_scan_result(struct wpa_sm *sm, const u8 *bssid,
481  			     const u8 *ssid, const u8 *rsn)
482  {
483  	struct wpa_ie_data ie;
484  	struct rsn_pmksa_cache_entry *pmksa;
485  
486  	if (ssid[1] != sm->ssid_len ||
487  	    os_memcmp(ssid + 2, sm->ssid, sm->ssid_len) != 0)
488  		return; /* Not for the current SSID */
489  
490  	if (ether_addr_equal(bssid, sm->bssid))
491  		return; /* Ignore current AP */
492  
493  	if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie))
494  		return;
495  
496  	pmksa = pmksa_cache_get(sm->pmksa, bssid, sm->own_addr, NULL, NULL, 0);
497  	if (pmksa && (!pmksa->opportunistic ||
498  		      !(ie.capabilities & WPA_CAPABILITY_PREAUTH)))
499  		return;
500  
501  	if (!rsn_preauth_key_mgmt(ie.key_mgmt))
502  		return;
503  
504  	/* Give less priority to candidates found from normal scan results. */
505  	pmksa_candidate_add(sm, bssid, PMKID_CANDIDATE_PRIO_SCAN,
506  			    ie.capabilities & WPA_CAPABILITY_PREAUTH);
507  }
508  
509  
510  #ifdef CONFIG_CTRL_IFACE
511  /**
512   * rsn_preauth_get_status - Get pre-authentication status
513   * @sm: Pointer to WPA state machine data from wpa_sm_init()
514   * @buf: Buffer for status information
515   * @buflen: Maximum buffer length
516   * @verbose: Whether to include verbose status information
517   * Returns: Number of bytes written to buf.
518   *
519   * Query WPA2 pre-authentication for status information. This function fills in
520   * a text area with current status information. If the buffer (buf) is not
521   * large enough, status information will be truncated to fit the buffer.
522   */
rsn_preauth_get_status(struct wpa_sm * sm,char * buf,size_t buflen,int verbose)523  int rsn_preauth_get_status(struct wpa_sm *sm, char *buf, size_t buflen,
524  			   int verbose)
525  {
526  	char *pos = buf, *end = buf + buflen;
527  	int res, ret;
528  
529  	if (sm->preauth_eapol) {
530  		ret = os_snprintf(pos, end - pos, "Pre-authentication "
531  				  "EAPOL state machines:\n");
532  		if (os_snprintf_error(end - pos, ret))
533  			return pos - buf;
534  		pos += ret;
535  		res = eapol_sm_get_status(sm->preauth_eapol,
536  					  pos, end - pos, verbose);
537  		if (res >= 0)
538  			pos += res;
539  	}
540  
541  	return pos - buf;
542  }
543  #endif /* CONFIG_CTRL_IFACE */
544  
545  
546  /**
547   * rsn_preauth_in_progress - Verify whether pre-authentication is in progress
548   * @sm: Pointer to WPA state machine data from wpa_sm_init()
549   */
rsn_preauth_in_progress(struct wpa_sm * sm)550  int rsn_preauth_in_progress(struct wpa_sm *sm)
551  {
552  	return sm->preauth_eapol != NULL;
553  }
554  
555  #endif /* IEEE8021X_EAPOL && !CONFIG_NO_WPA */
556