/**
 * pmksa_cache_set_current - Set the current PMKSA entry selection
 * @sm: Pointer to WPA state machine data from wpa_sm_init()
 * @pmkid: PMKID for selecting PMKSA or %NULL if not used
 * @bssid: BSSID for PMKSA or %NULL if not used
 * @network_ctx: Network configuration context
 * @try_opportunistic: Whether to allow opportunistic PMKSA caching
 * Returns: 0 if PMKSA was found or -1 if no matching entry was found
 */
int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
			    const u8 *bssid, void *network_ctx,
			    int try_opportunistic)
{
	struct rsn_pmksa_cache *pmksa = sm->pmksa;
	wpa_printf(MSG_DEBUG, "RSN: PMKSA cache search - network_ctx=%p "
		   "try_opportunistic=%d", network_ctx, try_opportunistic);
	if (pmkid)
		wpa_hexdump(MSG_DEBUG, "RSN: Search for PMKID",
			    pmkid, PMKID_LEN);
	if (bssid)
		wpa_printf(MSG_DEBUG, "RSN: Search for BSSID " MACSTR,
			   MAC2STR(bssid));

	sm->cur_pmksa = NULL;
	if (pmkid)
		sm->cur_pmksa = pmksa_cache_get(pmksa, NULL, pmkid,
						network_ctx);
	if (sm->cur_pmksa == NULL && bssid)
		sm->cur_pmksa = pmksa_cache_get(pmksa, bssid, NULL,
						network_ctx);
	if (sm->cur_pmksa == NULL && try_opportunistic && bssid)
		sm->cur_pmksa = pmksa_cache_get_opportunistic(pmksa,
							      network_ctx,
							      bssid);
	if (sm->cur_pmksa) {
		wpa_hexdump(MSG_DEBUG, "RSN: PMKSA cache entry found - PMKID",
			    sm->cur_pmksa->pmkid, PMKID_LEN);
		return 0;
	}
	wpa_printf(MSG_DEBUG, "RSN: No PMKSA cache entry found");
	return -1;
}
static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
{
	int sec;
	struct rsn_pmksa_cache_entry *entry;
	struct os_time now;

	eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL);
	eloop_cancel_timeout(pmksa_cache_reauth, pmksa, NULL);
	if (pmksa->pmksa == NULL)
		return;
	os_get_time(&now);
	sec = pmksa->pmksa->expiration - now.sec;
	if (sec < 0)
		sec = 0;
	eloop_register_timeout(sec + 1, 0, pmksa_cache_expire, pmksa, NULL);

	entry = pmksa->sm->cur_pmksa ? pmksa->sm->cur_pmksa :
		pmksa_cache_get(pmksa, pmksa->sm->bssid, NULL, NULL);
	if (entry) {
		sec = pmksa->pmksa->reauth_time - now.sec;
		if (sec < 0)
			sec = 0;
		eloop_register_timeout(sec, 0, pmksa_cache_reauth, pmksa,
				       NULL);
	}
}
Ejemplo n.º 3
0
struct rsn_pmksa_cache_entry * wlan_pmksa_cache_get(unsigned char WLANID, unsigned int BSSIndex,
					       const u8 *spa, const u8 *aa, const u8 *pmkid)
{
	struct PMK_STAINFO *pmk_sta;
	struct PMK_BSSInfo *bss;	
	struct wasd_interfaces *interfaces = (struct wasd_interfaces*) circle.user_data;
	struct asd_data *wasd;
	struct rsn_pmksa_cache_entry *entry;
	unsigned int RadioID;
	unsigned int BSS_L_ID;
	unsigned char new_pmkid[PMKID_LEN];
	if((ASD_WLAN[WLANID] == NULL)||(ASD_WLAN[WLANID]->sta_list == NULL))
		return NULL;
	pmk_sta = pmk_ap_get_sta(ASD_WLAN[WLANID],spa);
	if(pmk_sta == NULL)
		return NULL;
	bss = pmk_sta->bss;
	while(bss != NULL){
		if(bss->BSSIndex != BSSIndex){
			RadioID = bss->BSSIndex/L_BSS_NUM;
			BSS_L_ID = bss->BSSIndex%L_BSS_NUM;
			if((interfaces->iface[RadioID]!=NULL)&&(interfaces->iface[RadioID]->bss[BSS_L_ID]!=NULL))
			{
				wasd = interfaces->iface[RadioID]->bss[BSS_L_ID];
				if ((wasd == NULL) ||
					(wasd->wpa_auth == NULL) ||
					(wasd->wpa_auth->pmksa == NULL))
					continue;
				entry = pmksa_cache_get(wasd->wpa_auth->pmksa, spa, NULL);
				if(entry == NULL){
					asd_printf(ASD_DEFAULT,MSG_WARNING, "entry is NULL in func: %s\n",__func__);
					bss = bss->next;
					continue;
				}
				rsn_pmkid(entry->pmk,entry->pmk_len,aa,spa,new_pmkid);
				if(memcmp(new_pmkid, pmkid, PMKID_LEN) == 0)
				{

					if (memcmp(entry->pmkid, pmkid, PMKID_LEN)) {
						wpa_hexdump(MSG_INFO, "STA PMKID: ", entry->pmkid, PMKID_LEN);
						wpa_hexdump(MSG_INFO, "PMKID: ", pmkid, PMKID_LEN);
					}

					/* delete from hash, then update pmkid, insert again */					
					pmksa_cache_delete_from_hash(wasd->wpa_auth->pmksa, entry);
					memcpy(entry->pmkid, pmkid, PMKID_LEN);
					pmksa_cache_insert_to_hash(wasd->wpa_auth->pmksa, entry);
					if (pmk_sta->PreBssIndex != BSSIndex)
						pmk_ap_free_sta_in_prebss(pmk_sta->PreBssIndex,pmk_sta->addr);
					pmk_sta->PreBssIndex = BSSIndex;
					return entry;
				}
			}
		}
		bss = bss->next;
	}
	return NULL;
}
Ejemplo n.º 4
0
/**
 * pmksa_cache_set_current - Set the current PMKSA entry selection
 * @sm: Pointer to WPA state machine data from wpa_sm_init()
 * @pmkid: PMKID for selecting PMKSA or %NULL if not used
 * @bssid: BSSID for PMKSA or %NULL if not used
 * @ssid: The network configuration for the current network
 * @try_opportunistic: Whether to allow opportunistic PMKSA caching
 * Returns: 0 if PMKSA was found or -1 if no matching entry was found
 */
int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
			    const u8 *bssid, struct wpa_ssid *ssid,
			    int try_opportunistic)
{
	sm->cur_pmksa = NULL;
	if (pmkid)
		sm->cur_pmksa = pmksa_cache_get(sm, NULL, pmkid);
	if (sm->cur_pmksa == NULL && bssid)
		sm->cur_pmksa = pmksa_cache_get(sm, bssid, NULL);
	if (sm->cur_pmksa == NULL && try_opportunistic && bssid)
		sm->cur_pmksa = pmksa_cache_get_opportunistic(sm, ssid, bssid);
	if (sm->cur_pmksa) {
		wpa_hexdump(MSG_DEBUG, "RSN: PMKID",
			    sm->cur_pmksa->pmkid, PMKID_LEN);
		return 0;
	}
	return -1;
}
Ejemplo n.º 5
0
/**
 * pmksa_cache_set_current - Set the current PMKSA entry selection
 * @sm: Pointer to WPA state machine data from wpa_sm_init()
 * @pmkid: PMKID for selecting PMKSA or %NULL if not used
 * @bssid: BSSID for PMKSA or %NULL if not used
 * @network_ctx: Network configuration context
 * @try_opportunistic: Whether to allow opportunistic PMKSA caching
 * Returns: 0 if PMKSA was found or -1 if no matching entry was found
 */
int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
			    const u8 *bssid, void *network_ctx,
			    int try_opportunistic)
{
	struct rsn_pmksa_cache *pmksa = sm->pmksa;
	sm->cur_pmksa = NULL;
	if (pmkid)
		sm->cur_pmksa = pmksa_cache_get(pmksa, NULL, pmkid);
	if (sm->cur_pmksa == NULL && bssid)
		sm->cur_pmksa = pmksa_cache_get(pmksa, bssid, NULL);
	if (sm->cur_pmksa == NULL && try_opportunistic && bssid)
		sm->cur_pmksa = pmksa_cache_get_opportunistic(pmksa,
							      network_ctx,
							      bssid);
	if (sm->cur_pmksa) {
		wpa_hexdump(MSG_DEBUG, "RSN: PMKID",
			    sm->cur_pmksa->pmkid, PMKID_LEN);
		return 0;
	}
	return -1;
}
/**
 * rsn_preauth_candidate_process - Process PMKSA candidates
 * @sm: Pointer to WPA state machine data from wpa_sm_init()
 *
 * Go through the PMKSA candidates and start pre-authentication if a candidate
 * without an existing PMKSA cache entry is found. Processed candidates will be
 * removed from the list.
 */
void rsn_preauth_candidate_process(struct wpa_sm *sm)
{
	struct rsn_pmksa_candidate *candidate;

	if (sm->pmksa_candidates == NULL)
		return;

	/* TODO: drop priority for old candidate entries */

	wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: processing PMKSA candidate "
		"list");
	if (sm->preauth_eapol ||
	    sm->proto != WPA_PROTO_RSN ||
	    wpa_sm_get_state(sm) != WPA_COMPLETED ||
	    (sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X &&
	     sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X_SHA256)) {
		wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: not in suitable state "
			"for new pre-authentication");
		return; /* invalid state for new pre-auth */
	}

	while (sm->pmksa_candidates) {
		struct rsn_pmksa_cache_entry *p = NULL;
		candidate = sm->pmksa_candidates;
		p = pmksa_cache_get(sm->pmksa, candidate->bssid, NULL);
		if (os_memcmp(sm->bssid, candidate->bssid, ETH_ALEN) != 0 &&
		    (p == NULL || p->opportunistic)) {
			wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: PMKSA "
				"candidate " MACSTR
				" selected for pre-authentication",
				MAC2STR(candidate->bssid));
			sm->pmksa_candidates = candidate->next;
			rsn_preauth_init(sm, candidate->bssid,
					 sm->eap_conf_ctx);
			os_free(candidate);
			return;
		}
		wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: PMKSA candidate "
			MACSTR " does not need pre-authentication anymore",
			MAC2STR(candidate->bssid));
		/* Some drivers (e.g., NDIS) expect to get notified about the
		 * PMKIDs again, so report the existing data now. */
		if (p) {
			wpa_sm_add_pmkid(sm, candidate->bssid, p->pmkid);
		}

		sm->pmksa_candidates = candidate->next;
		os_free(candidate);
	}
	wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: no more pending PMKSA "
		"candidates");
}
/**
 * rsn_preauth_scan_results - Process scan results to find PMKSA candidates
 * @sm: Pointer to WPA state machine data from wpa_sm_init()
 * @results: Scan results
 *
 * This functions goes through the scan results and adds all suitable APs
 * (Authenticators) into PMKSA candidate list.
 */
void rsn_preauth_scan_results(struct wpa_sm *sm,
			      struct wpa_scan_results *results)
{
	struct wpa_scan_res *r;
	struct wpa_ie_data ie;
	int i;
	struct rsn_pmksa_cache_entry *pmksa;

	if (sm->ssid_len == 0)
		return;

	/*
	 * TODO: is it ok to free all candidates? What about the entries
	 * received from EVENT_PMKID_CANDIDATE?
	 */
	pmksa_candidate_free(sm);

	for (i = results->num - 1; i >= 0; i--) {
		const u8 *ssid, *rsn;

		r = results->res[i];

		ssid = wpa_scan_get_ie(r, WLAN_EID_SSID);
		if (ssid == NULL || ssid[1] != sm->ssid_len ||
		    os_memcmp(ssid + 2, sm->ssid, ssid[1]) != 0)
			continue;

		if (os_memcmp(r->bssid, sm->bssid, ETH_ALEN) == 0)
			continue;

		rsn = wpa_scan_get_ie(r, WLAN_EID_RSN);
		if (rsn == NULL || wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie))
			continue;

		pmksa = pmksa_cache_get(sm->pmksa, r->bssid, NULL);
		if (pmksa &&
		    (!pmksa->opportunistic ||
		     !(ie.capabilities & WPA_CAPABILITY_PREAUTH)))
			continue;

		/*
		 * Give less priority to candidates found from normal
		 * scan results.
		 */
		pmksa_candidate_add(sm, r->bssid,
				    PMKID_CANDIDATE_PRIO_SCAN,
				    ie.capabilities & WPA_CAPABILITY_PREAUTH);
	}
}
Ejemplo n.º 8
0
void rsn_preauth_candidate_process(struct wpa_supplicant *wpa_s)
{
	struct rsn_pmksa_candidate *candidate;

	if (wpa_s->pmksa_candidates == NULL)
		return;

	/* TODO: drop priority for old candidate entries */

	wpa_msg(wpa_s, MSG_DEBUG, "RSN: processing PMKSA candidate list");
	if (wpa_s->preauth_eapol ||
	    wpa_s->proto != WPA_PROTO_RSN ||
	    wpa_s->wpa_state != WPA_COMPLETED ||
	    wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X) {
		wpa_msg(wpa_s, MSG_DEBUG, "RSN: not in suitable state for new "
			"pre-authentication");
		return; /* invalid state for new pre-auth */
	}

	while (wpa_s->pmksa_candidates) {
		struct rsn_pmksa_cache *p = NULL;
		candidate = wpa_s->pmksa_candidates;
		p = pmksa_cache_get(wpa_s, candidate->bssid, NULL);
		if (memcmp(wpa_s->bssid, candidate->bssid, ETH_ALEN) != 0 &&
		    (p == NULL || p->opportunistic)) {
			wpa_msg(wpa_s, MSG_DEBUG, "RSN: PMKSA candidate "
				MACSTR " selected for pre-authentication",
				MAC2STR(candidate->bssid));
			wpa_s->pmksa_candidates = candidate->next;
			rsn_preauth_init(wpa_s, candidate->bssid);
			free(candidate);
			return;
		}
		wpa_msg(wpa_s, MSG_DEBUG, "RSN: PMKSA candidate " MACSTR
			" does not need pre-authentication anymore",
			MAC2STR(candidate->bssid));
		/* Some drivers (e.g., NDIS) expect to get notified about the
		 * PMKIDs again, so report the existing data now. */
		if (p)
			wpa_drv_add_pmkid(wpa_s, candidate->bssid, p->pmkid);

		wpa_s->pmksa_candidates = candidate->next;
		free(candidate);
	}
	wpa_msg(wpa_s, MSG_DEBUG, "RSN: no more pending PMKSA candidates");
}
Ejemplo n.º 9
0
/**
 * rsn_preauth_scan_results - Process scan results to find PMKSA candidates
 * @sm: Pointer to WPA state machine data from wpa_sm_init()
 * @results: Scan results
 * @count: Number of BSSes in scan results
 *
 * This functions goes through the scan results and adds all suitable APs
 * (Authenticators) into PMKSA candidate list.
 */
void rsn_preauth_scan_results(struct wpa_sm *sm,
			      struct wpa_scan_result *results, int count)
{
	struct wpa_scan_result *r;
	struct wpa_ie_data ie;
	int i;
	struct rsn_pmksa_cache *pmksa;

	if (sm->cur_ssid == NULL)
		return;

	/*
	 * TODO: is it ok to free all candidates? What about the entries
	 * received from EVENT_PMKID_CANDIDATE?
	 */
	pmksa_candidate_free(sm);

	for (i = count - 1; i >= 0; i--) {
		r = &results[i];
		if (r->ssid_len != sm->cur_ssid->ssid_len ||
		    memcmp(r->ssid, sm->cur_ssid->ssid,
			   r->ssid_len) != 0)
			continue;

		if (memcmp(r->bssid, sm->bssid, ETH_ALEN) == 0)
			continue;

		if (r->rsn_ie_len == 0 ||
		    wpa_parse_wpa_ie(r->rsn_ie, r->rsn_ie_len, &ie))
			continue;

		pmksa = pmksa_cache_get(sm, r->bssid, NULL);
		if (pmksa &&
		    (!pmksa->opportunistic ||
		     !(ie.capabilities & WPA_CAPABILITY_PREAUTH)))
			continue;

		/*
		 * Give less priority to candidates found from normal
		 * scan results.
		 */
		pmksa_candidate_add(sm, r->bssid,
				    PMKID_CANDIDATE_PRIO_SCAN,
				    ie.capabilities & WPA_CAPABILITY_PREAUTH);
	}
}
Ejemplo n.º 10
0
/* TODO: schedule periodic scans if current AP supports preauth */
void rsn_preauth_scan_results(struct wpa_supplicant *wpa_s,
			      struct wpa_scan_result *results, int count)
{
	struct wpa_scan_result *r;
	struct wpa_ie_data ie;
	int i;
	struct rsn_pmksa_cache *pmksa;

	if (wpa_s->current_ssid == NULL)
		return;

	pmksa_candidate_free(wpa_s);

	for (i = count - 1; i >= 0; i--) {
		r = &results[i];
		if (r->ssid_len != wpa_s->current_ssid->ssid_len ||
		    memcmp(r->ssid, wpa_s->current_ssid->ssid,
			   r->ssid_len) != 0)
			continue;

		if (memcmp(r->bssid, wpa_s->bssid, ETH_ALEN) == 0)
			continue;

		if (r->rsn_ie_len == 0 ||
		    wpa_parse_wpa_ie(wpa_s, r->rsn_ie, r->rsn_ie_len, &ie))
			continue;

		pmksa = pmksa_cache_get(wpa_s, r->bssid, NULL);
		if (pmksa &&
		    (!pmksa->opportunistic ||
		     !(ie.capabilities & WPA_CAPABILITY_PREAUTH)))
			continue;

		/*
		 * Give less priority to candidates found from normal
		 * scan results.
		 */
		pmksa_candidate_add(wpa_s, r->bssid,
				    PMKID_CANDIDATE_PRIO_SCAN,
				    ie.capabilities & WPA_CAPABILITY_PREAUTH);
	}
}
Ejemplo n.º 11
0
static void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
    dladm_wlan_ess_t *bss, struct wpa_ssid *ssid)
{
	uint8_t wpa_ie[IEEE80211_MAX_OPT_IE];
	int wpa_ie_len;

	wpa_s->reassociate = 0;
	wpa_printf(MSG_DEBUG, "Trying to associate with " MACSTR
	    " (SSID='%s' freq=%d MHz)", MAC2STR(bss->we_bssid.wb_bytes),
	    wpa_ssid_txt((char *)ssid->ssid, ssid->ssid_len), bss->we_freq);
	wpa_supplicant_cancel_scan(wpa_s);

	if (bss->we_wpa_ie_len &&
	    (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK))) {
		wpa_s->cur_pmksa = pmksa_cache_get(wpa_s,
		    bss->we_bssid.wb_bytes, NULL);
		if (wpa_s->cur_pmksa) {
			wpa_hexdump(MSG_DEBUG, "RSN: PMKID",
			    wpa_s->cur_pmksa->pmkid, PMKID_LEN);
		}
		if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
		    wpa_ie, &wpa_ie_len)) {
			wpa_printf(MSG_WARNING, "WPA: Failed to set WPA key "
			    "management and encryption suites");
			return;
		}
	} else {
		wpa_ie_len = 0;
	}

	wpa_clear_keys(wpa_s, bss->we_bssid.wb_bytes);
	wpa_s->wpa_state = WPA_ASSOCIATING;
	wpa_s->driver->associate(wpa_s->linkid,
	    (const char *)bss->we_bssid.wb_bytes, wpa_ie, wpa_ie_len);

	/* Timeout for IEEE 802.11 authentication and association */
	wpa_supplicant_req_auth_timeout(wpa_s, 15, 0);
}
Ejemplo n.º 12
0
static void pmksa_cache_set_expiration(struct wpa_sm *sm)
{
	int sec;
	struct rsn_pmksa_cache *entry;

	eloop_cancel_timeout(pmksa_cache_expire, sm, NULL);
	eloop_cancel_timeout(pmksa_cache_reauth, sm, NULL);
	if (sm->pmksa == NULL)
		return;
	sec = sm->pmksa->expiration - time(NULL);
	if (sec < 0)
		sec = 0;
	eloop_register_timeout(sec + 1, 0, pmksa_cache_expire, sm, NULL);

	entry = sm->cur_pmksa ? sm->cur_pmksa :
		pmksa_cache_get(sm, sm->bssid, NULL);
	if (entry) {
		sec = sm->pmksa->reauth_time - time(NULL);
		if (sec < 0)
			sec = 0;
		eloop_register_timeout(sec, 0, pmksa_cache_reauth, sm, NULL);
	}
}
Ejemplo n.º 13
0
/**
 * pmksa_cache_add - Add a PMKSA cache entry
 * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
 * @pmk: The new pairwise master key
 * @pmk_len: PMK length in bytes, usually PMK_LEN (32)
 * @aa: Authenticator address
 * @spa: Supplicant address
 * @session_timeout: Session timeout
 * @eapol: Pointer to EAPOL state machine data
 * Returns: Pointer to the added PMKSA cache entry or %NULL on error
 *
 * This function create a PMKSA entry for a new PMK and adds it to the PMKSA
 * cache. If an old entry is already in the cache for the same Supplicant,
 * this entry will be replaced with the new entry. PMKID will be calculated
 * based on the PMK.
 */
struct rsn_pmksa_cache_entry *
pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
		const u8 *aa, const u8 *spa, int session_timeout,
		struct eapol_state_machine *eapol)
{
	struct rsn_pmksa_cache_entry *entry, *pos, *prev;
	struct os_time now;

	if (pmk_len > PMK_LEN)
		return NULL;

	entry = wpa_zalloc(sizeof(*entry));
	if (entry == NULL)
		return NULL;
	memcpy(entry->pmk, pmk, pmk_len);
	entry->pmk_len = pmk_len;
	rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid);
	os_get_time(&now);
	entry->expiration = now.sec;
	if (session_timeout > 0)
		entry->expiration += session_timeout;
	else
		entry->expiration += dot11RSNAConfigPMKLifetime;
	entry->akmp = WPA_KEY_MGMT_IEEE8021X;
	memcpy(entry->spa, spa, ETH_ALEN);
	pmksa_cache_from_eapol_data(entry, eapol);

	/* Replace an old entry for the same STA (if found) with the new entry
	 */
	pos = pmksa_cache_get(pmksa, spa, NULL);
	if (pos)
		pmksa_cache_free_entry(pmksa, pos);

	if (pmksa->pmksa_count >= pmksa_cache_max_entries && pmksa->pmksa) {
		/* Remove the oldest entry to make room for the new entry */
		wpa_printf(MSG_DEBUG, "RSN: removed the oldest PMKSA cache "
			   "entry (for " MACSTR ") to make room for new one",
			   MAC2STR(pmksa->pmksa->spa));
		pmksa_cache_free_entry(pmksa, pmksa->pmksa);
	}

	/* Add the new entry; order by expiration time */
	pos = pmksa->pmksa;
	prev = NULL;
	while (pos) {
		if (pos->expiration > entry->expiration)
			break;
		prev = pos;
		pos = pos->next;
	}
	if (prev == NULL) {
		entry->next = pmksa->pmksa;
		pmksa->pmksa = entry;
	} else {
		entry->next = prev->next;
		prev->next = entry;
	}
	entry->hnext = pmksa->pmkid[PMKID_HASH(entry->pmkid)];
	pmksa->pmkid[PMKID_HASH(entry->pmkid)] = entry;

	pmksa->pmksa_count++;
	wpa_printf(MSG_DEBUG, "RSN: added PMKSA cache entry for " MACSTR,
		   MAC2STR(entry->spa));
	wpa_hexdump(MSG_DEBUG, "RSN: added PMKID", entry->pmkid, PMKID_LEN);

	pmksa_cache_set_expiration(pmksa) ;

	return entry;
}
Ejemplo n.º 14
0
static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
				  const unsigned char *src_addr,
				  const u8 *pmkid)
{
	int abort_cached = 0;

	if (pmkid && !sm->cur_pmksa) {
		/* When using drivers that generate RSN IE, wpa_supplicant may
		 * not have enough time to get the association information
		 * event before receiving this 1/4 message, so try to find a
		 * matching PMKSA cache entry here. */
		sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr, pmkid);
		if (sm->cur_pmksa) {
			wpa_printf(MSG_DEBUG, "RSN: found matching PMKID from "
				   "PMKSA cache");
		} else {
			wpa_printf(MSG_DEBUG, "RSN: no matching PMKID found");
			abort_cached = 1;
		}
	}

	if (pmkid && sm->cur_pmksa &&
	    os_memcmp(pmkid, sm->cur_pmksa->pmkid, PMKID_LEN) == 0) {
		wpa_hexdump(MSG_DEBUG, "RSN: matched PMKID", pmkid, PMKID_LEN);
		wpa_sm_set_pmk_from_pmksa(sm);
		wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from PMKSA cache",
				sm->pmk, sm->pmk_len);
		eapol_sm_notify_cached(sm->eapol);
#ifdef CONFIG_IEEE80211R
		sm->xxkey_len = 0;
#endif /* CONFIG_IEEE80211R */
	} else if (wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && sm->eapol) {
		int res, pmk_len;
		pmk_len = PMK_LEN;
		res = eapol_sm_get_key(sm->eapol, sm->pmk, PMK_LEN);
		if (res) {
			/*
			 * EAP-LEAP is an exception from other EAP methods: it
			 * uses only 16-byte PMK.
			 */
			res = eapol_sm_get_key(sm->eapol, sm->pmk, 16);
			pmk_len = 16;
		} else {
#ifdef CONFIG_IEEE80211R
			u8 buf[2 * PMK_LEN];
			if (eapol_sm_get_key(sm->eapol, buf, 2 * PMK_LEN) == 0)
			{
				os_memcpy(sm->xxkey, buf + PMK_LEN, PMK_LEN);
				sm->xxkey_len = PMK_LEN;
				os_memset(buf, 0, sizeof(buf));
			}
#endif /* CONFIG_IEEE80211R */
		}
		if (res == 0) {
			wpa_hexdump_key(MSG_DEBUG, "WPA: PMK from EAPOL state "
					"machines", sm->pmk, pmk_len);
			sm->pmk_len = pmk_len;
			if (sm->proto == WPA_PROTO_RSN) {
				pmksa_cache_add(sm->pmksa, sm->pmk, pmk_len,
						src_addr, sm->own_addr,
						sm->network_ctx, sm->key_mgmt);
			}
			if (!sm->cur_pmksa && pmkid &&
			    pmksa_cache_get(sm->pmksa, src_addr, pmkid)) {
				wpa_printf(MSG_DEBUG, "RSN: the new PMK "
					   "matches with the PMKID");
				abort_cached = 0;
			}
		} else {
			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
				"WPA: Failed to get master session key from "
				"EAPOL state machines");
			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
				"WPA: Key handshake aborted");
			if (sm->cur_pmksa) {
				wpa_printf(MSG_DEBUG, "RSN: Cancelled PMKSA "
					   "caching attempt");
				sm->cur_pmksa = NULL;
				abort_cached = 1;
			} else if (!abort_cached) {
				return -1;
			}
		}
	}

	if (abort_cached && wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) {
		/* Send EAPOL-Start to trigger full EAP authentication. */
		u8 *buf;
		size_t buflen;

		wpa_printf(MSG_DEBUG, "RSN: no PMKSA entry found - trigger "
			   "full EAP authentication");
		buf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START,
					 NULL, 0, &buflen, NULL);
		if (buf) {
			wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL,
					  buf, buflen);
			os_free(buf);
			return -2;
		}

		return -1;
	}

	return 0;
}