static void gas_serv_rx_gas_comeback_req(struct hostapd_data *hapd, const u8 *sa, const u8 *data, size_t len, int prot, int std_addr3) { struct gas_dialog_info *dialog; struct wpabuf *buf, *tx_buf; u8 dialog_token; size_t frag_len; int more = 0; wpa_hexdump(MSG_DEBUG, "GAS: RX GAS Comeback Request", data, len); if (len < 1) return; dialog_token = *data; wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Dialog Token: %u", dialog_token); dialog = gas_serv_dialog_find(hapd, sa, dialog_token); if (!dialog) { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: No pending SD " "response fragment for " MACSTR " dialog token %u", MAC2STR(sa), dialog_token); if (sa[0] & 0x01) return; /* Invalid source address - drop silently */ tx_buf = gas_anqp_build_comeback_resp_buf( dialog_token, WLAN_STATUS_NO_OUTSTANDING_GAS_REQ, 0, 0, 0, NULL); if (tx_buf == NULL) return; goto send_resp; } frag_len = wpabuf_len(dialog->sd_resp) - dialog->sd_resp_pos; if (frag_len > hapd->gas_frag_limit) { frag_len = hapd->gas_frag_limit; more = 1; } wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: resp frag_len %u", (unsigned int) frag_len); buf = wpabuf_alloc_copy(wpabuf_head_u8(dialog->sd_resp) + dialog->sd_resp_pos, frag_len); if (buf == NULL) { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Failed to allocate " "buffer"); gas_serv_dialog_clear(dialog); return; } tx_buf = gas_anqp_build_comeback_resp_buf(dialog_token, WLAN_STATUS_SUCCESS, dialog->sd_frag_id, more, 0, buf); wpabuf_free(buf); if (tx_buf == NULL) { gas_serv_dialog_clear(dialog); return; } wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Tx GAS Comeback Response " "(frag_id %d more=%d frag_len=%d)", dialog->sd_frag_id, more, (int) frag_len); dialog->sd_frag_id++; dialog->sd_resp_pos += frag_len; if (more) { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: %d more bytes remain " "to be sent", (int) (wpabuf_len(dialog->sd_resp) - dialog->sd_resp_pos)); } else { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: All fragments of " "SD response sent"); gas_serv_dialog_clear(dialog); gas_serv_free_dialogs(hapd, sa); } send_resp: if (prot) convert_to_protected_dual(tx_buf); if (std_addr3) hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa, wpabuf_head(tx_buf), wpabuf_len(tx_buf)); else hostapd_drv_send_action_addr3_ap(hapd, hapd->iface->freq, 0, sa, wpabuf_head(tx_buf), wpabuf_len(tx_buf)); wpabuf_free(tx_buf); }
static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, struct sta_info *sta, const struct ieee80211_mgmt *req, int is_p2p, size_t *resp_len) { struct ieee80211_mgmt *resp; u8 *pos, *epos; size_t buflen; #define MAX_PROBERESP_LEN 768 buflen = MAX_PROBERESP_LEN; #ifdef CONFIG_WPS if (hapd->wps_probe_resp_ie) buflen += wpabuf_len(hapd->wps_probe_resp_ie); #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P if (hapd->p2p_probe_resp_ie) buflen += wpabuf_len(hapd->p2p_probe_resp_ie); #endif /* CONFIG_P2P */ resp = os_zalloc(buflen); if (resp == NULL) return NULL; epos = ((u8 *) resp) + MAX_PROBERESP_LEN; resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_PROBE_RESP); if (req) os_memcpy(resp->da, req->sa, ETH_ALEN); os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN); os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN); resp->u.probe_resp.beacon_int = host_to_le16(hapd->iconf->beacon_int); /* hardware or low-level driver will setup seq_ctrl and timestamp */ resp->u.probe_resp.capab_info = host_to_le16(hostapd_own_capab_info(hapd, sta, 1)); pos = resp->u.probe_resp.variable; *pos++ = WLAN_EID_SSID; *pos++ = hapd->conf->ssid.ssid_len; os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len); pos += hapd->conf->ssid.ssid_len; /* Supported rates */ pos = hostapd_eid_supp_rates(hapd, pos); /* DS Params */ pos = hostapd_eid_ds_params(hapd, pos); pos = hostapd_eid_country(hapd, pos, epos - pos); /* ERP Information element */ pos = hostapd_eid_erp_info(hapd, pos); /* Extended supported rates */ pos = hostapd_eid_ext_supp_rates(hapd, pos); /* RSN, MDIE, WPA */ pos = hostapd_eid_wpa(hapd, pos, epos - pos); #ifdef CONFIG_IEEE80211N pos = hostapd_eid_ht_capabilities(hapd, pos); pos = hostapd_eid_ht_operation(hapd, pos); #endif /* CONFIG_IEEE80211N */ pos = hostapd_eid_ext_capab(hapd, pos); pos = hostapd_eid_time_adv(hapd, pos); pos = hostapd_eid_time_zone(hapd, pos); pos = hostapd_eid_interworking(hapd, pos); pos = hostapd_eid_adv_proto(hapd, pos); pos = hostapd_eid_roaming_consortium(hapd, pos); /* Wi-Fi Alliance WMM */ pos = hostapd_eid_wmm(hapd, pos); #ifdef CONFIG_WPS if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) { os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie), wpabuf_len(hapd->wps_probe_resp_ie)); pos += wpabuf_len(hapd->wps_probe_resp_ie); } #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P if ((hapd->conf->p2p & P2P_ENABLED) && is_p2p && hapd->p2p_probe_resp_ie) { os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie), wpabuf_len(hapd->p2p_probe_resp_ie)); pos += wpabuf_len(hapd->p2p_probe_resp_ie); } #endif /* CONFIG_P2P */ #ifdef CONFIG_P2P_MANAGER if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) == P2P_MANAGE) pos = hostapd_eid_p2p_manage(hapd, pos); #endif /* CONFIG_P2P_MANAGER */ #ifdef CONFIG_HS20 pos = hostapd_eid_hs20_indication(hapd, pos); #endif /* CONFIG_HS20 */ *resp_len = pos - (u8 *) resp; return (u8 *) resp; }
static struct wpabuf * eap_aka_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, const struct wpabuf *reqData) { struct eap_aka_data *data = priv; const struct eap_hdr *req; u8 subtype, id; struct wpabuf *res; const u8 *pos; struct eap_sim_attrs attr; size_t len; wpa_hexdump_buf(MSG_DEBUG, "EAP-AKA: EAP data", reqData); if (eap_get_config_identity(sm, &len) == NULL) { wpa_printf(MSG_INFO, "EAP-AKA: Identity not configured"); eap_sm_request_identity(sm); ret->ignore = TRUE; return NULL; } pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_AKA, reqData, &len); if (pos == NULL || len < 1) { ret->ignore = TRUE; return NULL; } req = wpabuf_head(reqData); id = req->identifier; len = be_to_host16(req->length); ret->ignore = FALSE; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; ret->allowNotifications = TRUE; subtype = *pos++; wpa_printf(MSG_DEBUG, "EAP-AKA: Subtype=%d", subtype); pos += 2; /* Reserved */ if (eap_sim_parse_attr(pos, wpabuf_head_u8(reqData) + len, &attr, 1, 0)) { res = eap_aka_client_error(data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); goto done; } switch (subtype) { case EAP_AKA_SUBTYPE_IDENTITY: res = eap_aka_process_identity(sm, data, id, reqData, &attr); break; case EAP_AKA_SUBTYPE_CHALLENGE: res = eap_aka_process_challenge(sm, data, id, reqData, &attr); break; case EAP_AKA_SUBTYPE_NOTIFICATION: res = eap_aka_process_notification(sm, data, id, reqData, &attr); break; case EAP_AKA_SUBTYPE_REAUTHENTICATION: res = eap_aka_process_reauthentication(sm, data, id, reqData, &attr); break; case EAP_AKA_SUBTYPE_CLIENT_ERROR: wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Client-Error"); res = eap_aka_client_error(data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); break; default: wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown subtype=%d", subtype); res = eap_aka_client_error(data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); break; } done: if (data->state == FAILURE) { ret->decision = DECISION_FAIL; ret->methodState = METHOD_DONE; } else if (data->state == SUCCESS) { ret->decision = data->use_result_ind ? DECISION_UNCOND_SUCC : DECISION_COND_SUCC; /* * It is possible for the server to reply with AKA * Notification, so we must allow the method to continue and * not only accept EAP-Success at this point. */ ret->methodState = data->use_result_ind ? METHOD_DONE : METHOD_MAY_CONT; } else if (data->state == RESULT_FAILURE) ret->methodState = METHOD_CONT; else if (data->state == RESULT_SUCCESS) ret->methodState = METHOD_CONT; if (ret->methodState == METHOD_DONE) { ret->allowNotifications = FALSE; } return res; }
static void wpas_send_action_cb(void *eloop_ctx, void *timeout_ctx) { struct wpa_supplicant *wpa_s = eloop_ctx; struct wpa_supplicant *iface; int res; int without_roc; without_roc = wpa_s->pending_action_without_roc; wpa_s->pending_action_without_roc = 0; wpa_printf(MSG_DEBUG, "Off-channel: Send Action callback " "(without_roc=%d pending_action_tx=%p)", without_roc, wpa_s->pending_action_tx); if (wpa_s->pending_action_tx == NULL) return; /* * This call is likely going to be on the P2P device instance if the * driver uses a separate interface for that purpose. However, some * Action frames are actually sent within a P2P Group and when that is * the case, we need to follow power saving (e.g., GO buffering the * frame for a client in PS mode or a client following the advertised * NoA from its GO). To make that easier for the driver, select the * correct group interface here. */ iface = wpas_get_tx_interface(wpa_s, wpa_s->pending_action_src); if (wpa_s->off_channel_freq != wpa_s->pending_action_freq && wpa_s->pending_action_freq != 0 && wpa_s->pending_action_freq != iface->assoc_freq) { wpa_printf(MSG_DEBUG, "Off-channel: Pending Action frame TX " "waiting for another freq=%u (off_channel_freq=%u " "assoc_freq=%u)", wpa_s->pending_action_freq, wpa_s->off_channel_freq, iface->assoc_freq); if (without_roc && wpa_s->off_channel_freq == 0) { /* * We may get here if wpas_send_action() found us to be * on the correct channel, but remain-on-channel cancel * event was received before getting here. */ wpa_printf(MSG_DEBUG, "Off-channel: Schedule " "remain-on-channel to send Action frame"); if (wpa_drv_remain_on_channel( wpa_s, wpa_s->pending_action_freq, 200) < 0) { wpa_printf(MSG_DEBUG, "Off-channel: Failed to " "request driver to remain on " "channel (%u MHz) for Action Frame " "TX", wpa_s->pending_action_freq); } else { wpa_s->off_channel_freq = 0; wpa_s->roc_waiting_drv_freq = wpa_s->pending_action_freq; } } return; } wpa_printf(MSG_DEBUG, "Off-channel: Sending pending Action frame to " MACSTR " using interface %s", MAC2STR(wpa_s->pending_action_dst), iface->ifname); res = wpa_drv_send_action(iface, wpa_s->pending_action_freq, 0, wpa_s->pending_action_dst, wpa_s->pending_action_src, wpa_s->pending_action_bssid, wpabuf_head(wpa_s->pending_action_tx), wpabuf_len(wpa_s->pending_action_tx), wpa_s->pending_action_no_cck); if (res) { wpa_printf(MSG_DEBUG, "Off-channel: Failed to send the " "pending Action frame"); /* * Use fake TX status event to allow state machines to * continue. */ offchannel_send_action_tx_status( wpa_s, wpa_s->pending_action_dst, wpabuf_head(wpa_s->pending_action_tx), wpabuf_len(wpa_s->pending_action_tx), OFFCHANNEL_SEND_ACTION_FAILED); } }
static void sme_send_authentication(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, struct wpa_ssid *ssid, int start) { struct wpa_driver_auth_params params; struct wpa_ssid *old_ssid; #ifdef CONFIG_IEEE80211R const u8 *ie; #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211R const u8 *md = NULL; #endif /* CONFIG_IEEE80211R */ int i, bssid_changed; struct wpabuf *resp = NULL; u8 ext_capab[10]; int ext_capab_len; if (bss == NULL) { wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for " "the network"); return; } wpa_s->current_bss = bss; os_memset(¶ms, 0, sizeof(params)); wpa_s->reassociate = 0; wpa_s->roaming = 0; params.freq = bss->freq; params.bssid = bss->bssid; params.ssid = bss->ssid; params.ssid_len = bss->ssid_len; params.p2p = ssid->p2p_group; if (wpa_s->sme.ssid_len != params.ssid_len || os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0) wpa_s->sme.prev_bssid_set = 0; wpa_s->sme.freq = params.freq; os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len); wpa_s->sme.ssid_len = params.ssid_len; params.auth_alg = WPA_AUTH_ALG_OPEN; #ifdef IEEE8021X_EAPOL if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { if (ssid->leap) { if (ssid->non_leap == 0) params.auth_alg = WPA_AUTH_ALG_LEAP; else params.auth_alg |= WPA_AUTH_ALG_LEAP; } } #endif /* IEEE8021X_EAPOL */ wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", params.auth_alg); if (ssid->auth_alg) { params.auth_alg = ssid->auth_alg; wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: " "0x%x", params.auth_alg); } #ifdef CONFIG_SAE if (wpa_key_mgmt_sae(ssid->key_mgmt)) { const u8 *rsn; struct wpa_ie_data ied; rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0) { if (wpa_key_mgmt_sae(ied.key_mgmt)) { wpa_dbg(wpa_s, MSG_DEBUG, "Using SAE auth_alg"); params.auth_alg = WPA_AUTH_ALG_SAE; } } } #endif /* CONFIG_SAE */ for (i = 0; i < NUM_WEP_KEYS; i++) { if (ssid->wep_key_len[i]) params.wep_key[i] = ssid->wep_key[i]; params.wep_key_len[i] = ssid->wep_key_len[i]; } params.wep_tx_keyidx = ssid->wep_tx_keyidx; bssid_changed = !is_zero_ether_addr(wpa_s->bssid); os_memset(wpa_s->bssid, 0, ETH_ALEN); os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); if (bssid_changed) wpas_notify_bssid_changed(wpa_s); if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || wpa_bss_get_ie(bss, WLAN_EID_RSN)) && wpa_key_mgmt_wpa(ssid->key_mgmt)) { int try_opportunistic; try_opportunistic = (ssid->proactive_key_caching < 0 ? wpa_s->conf->okc : ssid->proactive_key_caching) && (ssid->proto & WPA_PROTO_RSN); if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, wpa_s->current_ssid, try_opportunistic) == 0) eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1); wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); if (wpa_supplicant_set_suites(wpa_s, bss, ssid, wpa_s->sme.assoc_req_ie, &wpa_s->sme.assoc_req_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " "key management and encryption suites"); return; } } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) { /* * Both WPA and non-WPA IEEE 802.1X enabled in configuration - * use non-WPA since the scan results did not indicate that the * AP is using WPA or WPA2. */ wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); wpa_s->sme.assoc_req_ie_len = 0; } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) { wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, wpa_s->sme.assoc_req_ie, &wpa_s->sme.assoc_req_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " "key management and encryption suites (no " "scan results)"); return; } #ifdef CONFIG_WPS } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { struct wpabuf *wps_ie; wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid)); if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_s->sme.assoc_req_ie)) { wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie); os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie), wpa_s->sme.assoc_req_ie_len); } else wpa_s->sme.assoc_req_ie_len = 0; wpabuf_free(wps_ie); wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); #endif /* CONFIG_WPS */ } else { wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); wpa_s->sme.assoc_req_ie_len = 0; } #ifdef CONFIG_IEEE80211R ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN) md = ie + 2; wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0); if (md) { /* Prepare for the next transition */ wpa_ft_prepare_auth_request(wpa_s->wpa, ie); } if (md && wpa_key_mgmt_ft(ssid->key_mgmt)) { if (wpa_s->sme.assoc_req_ie_len + 5 < sizeof(wpa_s->sme.assoc_req_ie)) { struct rsn_mdie *mdie; u8 *pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; *pos++ = WLAN_EID_MOBILITY_DOMAIN; *pos++ = sizeof(*mdie); mdie = (struct rsn_mdie *) pos; os_memcpy(mdie->mobility_domain, md, MOBILITY_DOMAIN_ID_LEN); mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN]; wpa_s->sme.assoc_req_ie_len += 5; } if (wpa_s->sme.ft_used && os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 && wpa_sm_has_ptk(wpa_s->wpa)) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT " "over-the-air"); params.auth_alg = WPA_AUTH_ALG_FT; params.ie = wpa_s->sme.ft_ies; params.ie_len = wpa_s->sme.ft_ies_len; } } #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W wpa_s->sme.mfp = ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? wpa_s->conf->pmf : ssid->ieee80211w; if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION) { const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); struct wpa_ie_data _ie; if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 && _ie.capabilities & (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports " "MFP: require MFP"); wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED; } } #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_P2P if (wpa_s->global->p2p) { u8 *pos; size_t len; int res; pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; len = sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len; res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len, ssid->p2p_group); if (res >= 0) wpa_s->sme.assoc_req_ie_len += res; } #endif /* CONFIG_P2P */ #ifdef CONFIG_HS20 if (is_hs20_network(wpa_s, ssid, bss)) { struct wpabuf *hs20; hs20 = wpabuf_alloc(20); if (hs20) { wpas_hs20_add_indication(hs20); os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len, wpabuf_head(hs20), wpabuf_len(hs20)); wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20); wpabuf_free(hs20); } } #endif /* CONFIG_HS20 */ ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab); if (ext_capab_len > 0) { u8 *pos = wpa_s->sme.assoc_req_ie; if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN) pos += 2 + pos[1]; os_memmove(pos + ext_capab_len, pos, wpa_s->sme.assoc_req_ie_len - (pos - wpa_s->sme.assoc_req_ie)); wpa_s->sme.assoc_req_ie_len += ext_capab_len; os_memcpy(pos, ext_capab, ext_capab_len); } #ifdef CONFIG_SAE if (params.auth_alg == WPA_AUTH_ALG_SAE) { if (start) resp = sme_auth_build_sae_commit(wpa_s, ssid, bss->bssid); else resp = sme_auth_build_sae_confirm(wpa_s); if (resp == NULL) return; params.sae_data = wpabuf_head(resp); params.sae_data_len = wpabuf_len(resp); wpa_s->sme.sae.state = start ? SAE_COMMITTED : SAE_CONFIRMED; } #endif /* CONFIG_SAE */ wpa_supplicant_cancel_sched_scan(wpa_s); wpa_supplicant_cancel_scan(wpa_s); wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), wpa_ssid_txt(params.ssid, params.ssid_len), params.freq); wpa_clear_keys(wpa_s, bss->bssid); wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); old_ssid = wpa_s->current_ssid; wpa_s->current_ssid = ssid; wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid); wpa_supplicant_initiate_eapol(wpa_s); if (old_ssid != wpa_s->current_ssid) wpas_notify_network_changed(wpa_s); wpa_s->sme.auth_alg = params.auth_alg; if (wpa_drv_authenticate(wpa_s, ¶ms) < 0) { wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the " "driver failed"); wpas_connection_failed(wpa_s, bss->bssid); wpa_supplicant_mark_disassoc(wpa_s); wpabuf_free(resp); return; } eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s, NULL); /* * Association will be started based on the authentication event from * the driver. */ wpabuf_free(resp); }
int ikev2_build_encrypted(int encr_id, int integ_id, struct ikev2_keys *keys, int initiator, struct wpabuf *msg, struct wpabuf *plain, u8 next_payload) { struct ikev2_payload_hdr *phdr; size_t plen; size_t iv_len, pad_len; u8 *icv, *iv; const struct ikev2_integ_alg *integ_alg; const struct ikev2_encr_alg *encr_alg; const u8 *SK_e = initiator ? keys->SK_ei : keys->SK_er; const u8 *SK_a = initiator ? keys->SK_ai : keys->SK_ar; wpa_printf(MSG_DEBUG, "IKEV2: Adding Encrypted payload"); /* Encr - RFC 4306, Sect. 3.14 */ encr_alg = ikev2_get_encr(encr_id); if (encr_alg == NULL) { wpa_printf(MSG_INFO, "IKEV2: Unsupported encryption type"); return -1; } iv_len = encr_alg->block_size; integ_alg = ikev2_get_integ(integ_id); if (integ_alg == NULL) { wpa_printf(MSG_INFO, "IKEV2: Unsupported intergrity type"); return -1; } if (SK_e == NULL) { wpa_printf(MSG_INFO, "IKEV2: No SK_e available"); return -1; } if (SK_a == NULL) { wpa_printf(MSG_INFO, "IKEV2: No SK_a available"); return -1; } phdr = wpabuf_put(msg, sizeof(*phdr)); phdr->next_payload = next_payload; phdr->flags = 0; iv = wpabuf_put(msg, iv_len); if (random_get_bytes(iv, iv_len)) { wpa_printf(MSG_INFO, "IKEV2: Could not generate IV"); return -1; } pad_len = iv_len - (wpabuf_len(plain) + 1) % iv_len; if (pad_len == iv_len) pad_len = 0; wpabuf_put(plain, pad_len); wpabuf_put_u8(plain, pad_len); if (ikev2_encr_encrypt(encr_alg->id, SK_e, keys->SK_encr_len, iv, wpabuf_head(plain), wpabuf_mhead(plain), wpabuf_len(plain)) < 0) return -1; wpabuf_put_buf(msg, plain); /* Need to update all headers (Length fields) prior to hash func */ icv = wpabuf_put(msg, integ_alg->hash_len); plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr; WPA_PUT_BE16(phdr->payload_length, plen); ikev2_update_hdr(msg); return ikev2_integ_hash(integ_id, SK_a, keys->SK_integ_len, wpabuf_head(msg), wpabuf_len(msg) - integ_alg->hash_len, icv); return 0; }
static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, const struct wpabuf *reqData) { struct eap_tnc_data *data = priv; struct wpabuf *resp; const u8 *pos, *end; u8 *rpos, *rpos1; size_t len, rlen; size_t imc_len; char *start_buf, *end_buf; size_t start_len, end_len; int tncs_done = 0; u8 flags, id; u32 message_length = 0; struct wpabuf tmpbuf; pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TNC, reqData, &len); if (pos == NULL) { wpa_printf(MSG_INFO, "EAP-TNC: Invalid frame (pos=%p len=%lu)", pos, (unsigned long) len); ret->ignore = TRUE; return NULL; } id = eap_get_id(reqData); end = pos + len; if (len == 0) flags = 0; /* fragment ack */ else flags = *pos++; if (len > 0 && (flags & EAP_TNC_VERSION_MASK) != EAP_TNC_VERSION) { wpa_printf(MSG_DEBUG, "EAP-TNC: Unsupported version %d", flags & EAP_TNC_VERSION_MASK); ret->ignore = TRUE; return NULL; } if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED) { if (end - pos < 4) { wpa_printf(MSG_DEBUG, "EAP-TNC: Message underflow"); ret->ignore = TRUE; return NULL; } message_length = WPA_GET_BE32(pos); pos += 4; if (message_length < (u32) (end - pos)) { wpa_printf(MSG_DEBUG, "EAP-TNC: Invalid Message " "Length (%d; %ld remaining in this msg)", message_length, (long) (end - pos)); ret->ignore = TRUE; return NULL; } } wpa_printf(MSG_DEBUG, "EAP-TNC: Received packet: Flags 0x%x " "Message Length %u", flags, message_length); if (data->state == WAIT_FRAG_ACK) { if (len != 0) { wpa_printf(MSG_DEBUG, "EAP-TNC: Unexpected payload in " "WAIT_FRAG_ACK state"); ret->ignore = TRUE; return NULL; } wpa_printf(MSG_DEBUG, "EAP-TNC: Fragment acknowledged"); data->state = PROC_MSG; return eap_tnc_build_msg(data, ret, id); } if (data->in_buf && eap_tnc_process_cont(data, pos, end - pos) < 0) { ret->ignore = TRUE; return NULL; } if (flags & EAP_TNC_FLAGS_MORE_FRAGMENTS) { return eap_tnc_process_fragment(data, ret, id, flags, message_length, pos, end - pos); } if (data->in_buf == NULL) { /* Wrap unfragmented messages as wpabuf without extra copy */ wpabuf_set(&tmpbuf, pos, end - pos); data->in_buf = &tmpbuf; } if (data->state == WAIT_START) { if (!(flags & EAP_TNC_FLAGS_START)) { wpa_printf(MSG_DEBUG, "EAP-TNC: Server did not use " "start flag in the first message"); ret->ignore = TRUE; return NULL; } tncc_init_connection(data->tncc); data->state = PROC_MSG; } else { enum tncc_process_res res; if (flags & EAP_TNC_FLAGS_START) { wpa_printf(MSG_DEBUG, "EAP-TNC: Server used start " "flag again"); ret->ignore = TRUE; return NULL; } res = tncc_process_if_tnccs(data->tncc, wpabuf_head(data->in_buf), wpabuf_len(data->in_buf)); switch (res) { case TNCCS_PROCESS_ERROR: ret->ignore = TRUE; return NULL; case TNCCS_PROCESS_OK_NO_RECOMMENDATION: case TNCCS_RECOMMENDATION_ERROR: wpa_printf(MSG_DEBUG, "EAP-TNC: No " "TNCCS-Recommendation received"); break; case TNCCS_RECOMMENDATION_ALLOW: wpa_msg(sm->msg_ctx, MSG_INFO, "TNC: Recommendation = allow"); tncs_done = 1; break; case TNCCS_RECOMMENDATION_NONE: wpa_msg(sm->msg_ctx, MSG_INFO, "TNC: Recommendation = none"); tncs_done = 1; break; case TNCCS_RECOMMENDATION_ISOLATE: wpa_msg(sm->msg_ctx, MSG_INFO, "TNC: Recommendation = isolate"); tncs_done = 1; break; } } if (data->in_buf != &tmpbuf) wpabuf_free(data->in_buf); data->in_buf = NULL; ret->ignore = FALSE; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_UNCOND_SUCC; ret->allowNotifications = TRUE; if (data->out_buf) { data->state = PROC_MSG; return eap_tnc_build_msg(data, ret, id); } if (tncs_done) { resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 1, EAP_CODE_RESPONSE, eap_get_id(reqData)); if (resp == NULL) return NULL; wpabuf_put_u8(resp, EAP_TNC_VERSION); wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS done - reply with an " "empty ACK message"); return resp; } imc_len = tncc_total_send_len(data->tncc); start_buf = tncc_if_tnccs_start(data->tncc); if (start_buf == NULL) return NULL; start_len = os_strlen(start_buf); end_buf = tncc_if_tnccs_end(); if (end_buf == NULL) { os_free(start_buf); return NULL; } end_len = os_strlen(end_buf); rlen = start_len + imc_len + end_len; resp = wpabuf_alloc(rlen); if (resp == NULL) { os_free(start_buf); os_free(end_buf); return NULL; } wpabuf_put_data(resp, start_buf, start_len); os_free(start_buf); rpos1 = wpabuf_put(resp, 0); rpos = tncc_copy_send_buf(data->tncc, rpos1); wpabuf_put(resp, rpos - rpos1); wpabuf_put_data(resp, end_buf, end_len); os_free(end_buf); wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TNC: Response", wpabuf_head(resp), wpabuf_len(resp)); data->out_buf = resp; data->state = PROC_MSG; return eap_tnc_build_msg(data, ret, id); }
static struct wpabuf * eap_psk_build_3(struct eap_sm *sm, struct eap_psk_data *data, u8 id) { struct wpabuf *req; struct eap_psk_hdr_3 *psk; u8 *buf, *pchannel, nonce[16]; size_t buflen; wpa_printf(MSG_DEBUG, "EAP-PSK: PSK-3 (sending)"); req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK, sizeof(*psk) + 4 + 16 + 1, EAP_CODE_REQUEST, id); if (req == NULL) { wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory " "request"); data->state = FAILURE; return NULL; } psk = wpabuf_put(req, sizeof(*psk)); psk->flags = EAP_PSK_FLAGS_SET_T(2); /* T=2 */ os_memcpy(psk->rand_s, data->rand_s, EAP_PSK_RAND_LEN); /* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */ buflen = data->id_s_len + EAP_PSK_RAND_LEN; buf = os_malloc(buflen); if (buf == NULL) goto fail; os_memcpy(buf, data->id_s, data->id_s_len); os_memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN); if (omac1_aes_128(data->ak, buf, buflen, psk->mac_s)) goto fail; os_free(buf); if (eap_psk_derive_keys(data->kdk, data->rand_p, data->tek, data->msk, data->emsk)) goto fail; wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN); wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->msk, EAP_MSK_LEN); wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: EMSK", data->emsk, EAP_EMSK_LEN); os_memset(nonce, 0, sizeof(nonce)); pchannel = wpabuf_put(req, 4 + 16 + 1); os_memcpy(pchannel, nonce + 12, 4); os_memset(pchannel + 4, 0, 16); /* Tag */ pchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_SUCCESS << 6; wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL (plaintext)", pchannel, 4 + 16 + 1); if (aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce), wpabuf_head(req), 22, pchannel + 4 + 16, 1, pchannel + 4)) goto fail; wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL (encrypted)", pchannel, 4 + 16 + 1); return req; fail: wpabuf_free(req); data->state = FAILURE; return NULL; }
void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa, const u8 *data, size_t len, int rx_freq) { struct p2p_message msg; struct p2p_device *dev; int freq; int reject = 1; struct wpabuf *resp; if (p2p_parse(data, len, &msg)) return; #ifdef CONFIG_MTK_P2P u8 status = 0; if(wfd_process_request_by_policy(p2p, &msg, &status, 0) != 0) { goto out; } #endif p2p_dbg(p2p, "Received Provision Discovery Request from " MACSTR " with config methods 0x%x (freq=%d)", MAC2STR(sa), msg.wps_config_methods, rx_freq); dev = p2p_get_device(p2p, sa); #ifdef CONFIG_MTK_P2P if(dev) { p2p_copy_wfd_info(dev, 0, &msg, 0); } #endif if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) { p2p_dbg(p2p, "Provision Discovery Request from unknown peer " MACSTR, MAC2STR(sa)); if (p2p_add_device(p2p, sa, rx_freq, NULL, 0, data + 1, len - 1, 0)) { p2p_dbg(p2p, "Provision Discovery Request add device failed " MACSTR, MAC2STR(sa)); } } else if (msg.wfd_subelems) { wpabuf_free(dev->info.wfd_subelems); dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems); } if (!(msg.wps_config_methods & (WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD | WPS_CONFIG_PUSHBUTTON))) { p2p_dbg(p2p, "Unsupported Config Methods in Provision Discovery Request"); goto out; } if (msg.group_id) { size_t i; for (i = 0; i < p2p->num_groups; i++) { if (p2p_group_is_group_id_match(p2p->groups[i], msg.group_id, msg.group_id_len)) break; } if (i == p2p->num_groups) { p2p_dbg(p2p, "PD request for unknown P2P Group ID - reject"); goto out; } } if (dev) dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY | P2P_DEV_PD_PEER_KEYPAD); if (msg.wps_config_methods & WPS_CONFIG_DISPLAY) { p2p_dbg(p2p, "Peer " MACSTR " requested us to show a PIN on display", MAC2STR(sa)); if (dev) dev->flags |= P2P_DEV_PD_PEER_KEYPAD; } else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) { p2p_dbg(p2p, "Peer " MACSTR " requested us to write its PIN using keypad", MAC2STR(sa)); if (dev) dev->flags |= P2P_DEV_PD_PEER_DISPLAY; } reject = 0; out: resp = p2p_build_prov_disc_resp(p2p, msg.dialog_token, reject ? 0 : msg.wps_config_methods, msg.group_id, msg.group_id_len); if (resp == NULL) { p2p_parse_free(&msg); return; } p2p_dbg(p2p, "Sending Provision Discovery Response"); if (rx_freq > 0) freq = rx_freq; else freq = p2p_channel_to_freq(p2p->cfg->reg_class, p2p->cfg->channel); if (freq < 0) { p2p_dbg(p2p, "Unknown regulatory class/channel"); wpabuf_free(resp); p2p_parse_free(&msg); return; } p2p->pending_action_state = P2P_NO_PENDING_ACTION; #ifdef CONFIG_MTK_P2P wfd_process_request_and_switch_role(p2p, &msg, 0); #endif if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, p2p->cfg->dev_addr, wpabuf_head(resp), wpabuf_len(resp), 200) < 0) { p2p_dbg(p2p, "Failed to send Action frame"); } else p2p->send_action_in_progress = 1; wpabuf_free(resp); if (!reject && p2p->cfg->prov_disc_req) { const u8 *dev_addr = sa; if (msg.p2p_device_addr) dev_addr = msg.p2p_device_addr; p2p->cfg->prov_disc_req(p2p->cfg->cb_ctx, sa, msg.wps_config_methods, dev_addr, msg.pri_dev_type, msg.device_name, msg.config_methods, msg.capability ? msg.capability[0] : 0, msg.capability ? msg.capability[1] : 0, msg.group_id, msg.group_id_len); } p2p_parse_free(&msg); }
static void eapol_sm_step_run(struct eapol_state_machine *sm) { struct eapol_authenticator *eapol = sm->eapol; u8 addr[ETH_ALEN]; unsigned int prev_auth_pae, prev_be_auth, prev_reauth_timer, prev_auth_key_tx, prev_key_rx, prev_ctrl_dir; int max_steps = 100; os_memcpy(addr, sm->addr, ETH_ALEN); /* * Allow EAPOL state machines to run as long as there are state * changes, but exit and return here through event loop if more than * 100 steps is needed as a precaution against infinite loops inside * eloop callback. */ restart: prev_auth_pae = sm->auth_pae_state; prev_be_auth = sm->be_auth_state; prev_reauth_timer = sm->reauth_timer_state; prev_auth_key_tx = sm->auth_key_tx_state; prev_key_rx = sm->key_rx_state; prev_ctrl_dir = sm->ctrl_dir_state; SM_STEP_RUN(AUTH_PAE); if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) SM_STEP_RUN(BE_AUTH); if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) SM_STEP_RUN(REAUTH_TIMER); if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) SM_STEP_RUN(AUTH_KEY_TX); if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) SM_STEP_RUN(KEY_RX); if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) SM_STEP_RUN(CTRL_DIR); if (prev_auth_pae != sm->auth_pae_state || prev_be_auth != sm->be_auth_state || prev_reauth_timer != sm->reauth_timer_state || prev_auth_key_tx != sm->auth_key_tx_state || prev_key_rx != sm->key_rx_state || prev_ctrl_dir != sm->ctrl_dir_state) { if (--max_steps > 0) goto restart; /* Re-run from eloop timeout */ eapol_auth_step(sm); return; } if (eapol_sm_sta_entry_alive(eapol, addr) && sm->eap) { if (eap_server_sm_step(sm->eap)) { if (--max_steps > 0) goto restart; /* Re-run from eloop timeout */ eapol_auth_step(sm); return; } /* TODO: find a better location for this */ if (sm->eap_if->aaaEapResp) { sm->eap_if->aaaEapResp = FALSE; if (sm->eap_if->aaaEapRespData == NULL) { wpa_printf(MSG_DEBUG, "EAPOL: aaaEapResp set, " "but no aaaEapRespData available"); return; } sm->eapol->cb.aaa_send( sm->eapol->conf.ctx, sm->sta, wpabuf_head(sm->eap_if->aaaEapRespData), wpabuf_len(sm->eap_if->aaaEapRespData)); } } if (eapol_sm_sta_entry_alive(eapol, addr)) sm->eapol->cb.eapol_event(sm->eapol->conf.ctx, sm->sta, EAPOL_AUTH_SM_CHANGE); }
static void eap_psk_process_4(struct eap_sm *sm, struct eap_psk_data *data, struct wpabuf *respData) { const struct eap_psk_hdr_4 *resp; u8 *decrypted, nonce[16]; size_t left; const u8 *pos, *tag; if (data->state != PSK_3) return; wpa_printf(MSG_DEBUG, "EAP-PSK: Received PSK-4"); pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, &left); if (pos == NULL || left < sizeof(*resp)) { wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame"); return; } resp = (const struct eap_psk_hdr_4 *) pos; pos = (const u8 *) (resp + 1); left -= sizeof(*resp); wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: Encrypted PCHANNEL", pos, left); if (left < 4 + 16 + 1) { wpa_printf(MSG_INFO, "EAP-PSK: Too short PCHANNEL data in " "PSK-4 (len=%lu, expected 21)", (unsigned long) left); return; } if (pos[0] == 0 && pos[1] == 0 && pos[2] == 0 && pos[3] == 0) { wpa_printf(MSG_DEBUG, "EAP-PSK: Nonce did not increase"); return; } os_memset(nonce, 0, 12); os_memcpy(nonce + 12, pos, 4); pos += 4; left -= 4; tag = pos; pos += 16; left -= 16; decrypted = os_malloc(left); if (decrypted == NULL) return; os_memcpy(decrypted, pos, left); if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce), wpabuf_head(respData), 22, decrypted, left, tag)) { wpa_printf(MSG_WARNING, "EAP-PSK: PCHANNEL decryption failed"); os_free(decrypted); data->state = FAILURE; return; } wpa_hexdump(MSG_DEBUG, "EAP-PSK: Decrypted PCHANNEL message", decrypted, left); /* Verify R flag */ switch (decrypted[0] >> 6) { case EAP_PSK_R_FLAG_CONT: wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - CONT - unsupported"); data->state = FAILURE; break; case EAP_PSK_R_FLAG_DONE_SUCCESS: wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_SUCCESS"); data->state = SUCCESS; break; case EAP_PSK_R_FLAG_DONE_FAILURE: wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_FAILURE"); data->state = FAILURE; break; } os_free(decrypted); }
#ifdef GNUTLS_IA if (conn->tls_ia) res = gnutls_ia_send(conn->session, wpabuf_head(in_data), wpabuf_len(in_data)); else #endif /* GNUTLS_IA */ res = gnutls_record_send(conn->session, wpabuf_head(in_data), wpabuf_len(in_data));
void ieee802_11_set_beacon(struct hostapd_data *hapd) { struct ieee80211_mgmt *head; u8 *pos, *tail, *tailpos; u16 capab_info; size_t head_len, tail_len; #ifdef CONFIG_P2P if ((hapd->conf->p2p & (P2P_ENABLED | P2P_GROUP_OWNER)) == P2P_ENABLED) goto no_beacon; #endif /* CONFIG_P2P */ #define BEACON_HEAD_BUF_SIZE 256 #define BEACON_TAIL_BUF_SIZE 512 head = os_zalloc(BEACON_HEAD_BUF_SIZE); tail_len = BEACON_TAIL_BUF_SIZE; #ifdef CONFIG_WPS if (hapd->conf->wps_state && hapd->wps_beacon_ie) tail_len += wpabuf_len(hapd->wps_beacon_ie); #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P if (hapd->p2p_beacon_ie) tail_len += wpabuf_len(hapd->p2p_beacon_ie); #endif /* CONFIG_P2P */ tailpos = tail = os_malloc(tail_len); if (head == NULL || tail == NULL) { wpa_printf(MSG_ERROR, "Failed to set beacon data"); os_free(head); os_free(tail); return; } head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_BEACON); head->duration = host_to_le16(0); os_memset(head->da, 0xff, ETH_ALEN); os_memcpy(head->sa, hapd->own_addr, ETH_ALEN); os_memcpy(head->bssid, hapd->own_addr, ETH_ALEN); head->u.beacon.beacon_int = host_to_le16(hapd->iconf->beacon_int); /* hardware or low-level driver will setup seq_ctrl and timestamp */ capab_info = hostapd_own_capab_info(hapd, NULL, 0); head->u.beacon.capab_info = host_to_le16(capab_info); pos = &head->u.beacon.variable[0]; /* SSID */ *pos++ = WLAN_EID_SSID; if (hapd->conf->ignore_broadcast_ssid == 2) { /* clear the data, but keep the correct length of the SSID */ *pos++ = hapd->conf->ssid.ssid_len; os_memset(pos, 0, hapd->conf->ssid.ssid_len); pos += hapd->conf->ssid.ssid_len; } else if (hapd->conf->ignore_broadcast_ssid) { *pos++ = 0; /* empty SSID */ } else { *pos++ = hapd->conf->ssid.ssid_len; os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len); pos += hapd->conf->ssid.ssid_len; } /* Supported rates */ pos = hostapd_eid_supp_rates(hapd, pos); /* DS Params */ pos = hostapd_eid_ds_params(hapd, pos); head_len = pos - (u8 *) head; tailpos = hostapd_eid_country(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE - tailpos); /* ERP Information element */ tailpos = hostapd_eid_erp_info(hapd, tailpos); /* Extended supported rates */ tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos); /* RSN, MDIE, WPA */ tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE - tailpos, NULL); #ifdef CONFIG_IEEE80211N tailpos = hostapd_eid_ht_capabilities(hapd, tailpos); tailpos = hostapd_eid_ht_operation(hapd, tailpos); #endif /* CONFIG_IEEE80211N */ tailpos = hostapd_eid_ext_capab(hapd, tailpos); /* Wi-Fi Alliance WMM */ tailpos = hostapd_eid_wmm(hapd, tailpos); #ifdef CONFIG_WPS if (hapd->conf->wps_state && hapd->wps_beacon_ie) { os_memcpy(tailpos, wpabuf_head(hapd->wps_beacon_ie), wpabuf_len(hapd->wps_beacon_ie)); tailpos += wpabuf_len(hapd->wps_beacon_ie); } #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_beacon_ie) { os_memcpy(tailpos, wpabuf_head(hapd->p2p_beacon_ie), wpabuf_len(hapd->p2p_beacon_ie)); tailpos += wpabuf_len(hapd->p2p_beacon_ie); } #endif /* CONFIG_P2P */ #ifdef CONFIG_P2P_MANAGER if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) == P2P_MANAGE) tailpos = hostapd_eid_p2p_manage(hapd, tailpos); #endif /* CONFIG_P2P_MANAGER */ tail_len = tailpos > tail ? tailpos - tail : 0; if (hostapd_drv_set_beacon(hapd, (u8 *) head, head_len, tail, tail_len, hapd->conf->dtim_period, hapd->iconf->beacon_int)) wpa_printf(MSG_ERROR, "Failed to set beacon head/tail or DTIM " "period"); os_free(tail); os_free(head); #ifdef CONFIG_P2P no_beacon: #endif /* CONFIG_P2P */ hostapd_set_bss_params(hapd, !!(ieee802_11_erp_info(hapd) & ERP_INFO_USE_PROTECTION)); }
static int eap_example_server_step(EAP_HANDLER *handler) { int res, process = 0; REQUEST *request = handler->request; res = eap_server_sm_step(handler->server_ctx.eap); if (handler->server_ctx.eap_if->eapReq) { DEBUG("==> Request"); process = 1; handler->server_ctx.eap_if->eapReq = 0; } if (handler->server_ctx.eap_if->eapSuccess) { DEBUG("==> Success"); process = 1; res = 0; if (handler->server_ctx.eap_if->eapKeyAvailable) { int length = handler->server_ctx.eap_if->eapKeyDataLen; VALUE_PAIR *vp; if (length > 64) { length = 32; } else { length /= 2; /* * FIXME: Length is zero? */ } vp = pairmake_reply("MS-MPPE-Recv-Key", NULL, T_OP_EQ); if (vp) { pairmemcpy(vp, handler->server_ctx.eap_if->eapKeyData, length); } vp = pairmake_reply("MS-MPPE-Send-Key", NULL, T_OP_EQ); if (vp) { pairmemcpy(vp, handler->server_ctx.eap_if->eapKeyData + length, length); } } } if (handler->server_ctx.eap_if->eapFail) { DEBUG("==> Fail"); process = 1; } if (process) { if (wpabuf_head(handler->server_ctx.eap_if->eapReqData)) { if (!eap_req2vp(handler)) return -1; } else { return -1; } } return res; }
static struct wpabuf *eap_pax_process_std_3(struct eap_pax_data *data, struct eap_method_ret *ret, u8 id, const struct eap_pax_hdr *req, size_t req_plen) { struct wpabuf *resp; u8 *rpos, mac[EAP_PAX_MAC_LEN]; const u8 *pos; size_t left; wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-3 (received)"); if (data->state != PAX_STD_2_SENT) { wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 received in " "unexpected state (%d) - ignored", data->state); ret->ignore = TRUE; return NULL; } if (req->flags & EAP_PAX_FLAGS_CE) { wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 with CE flag set - " "ignored"); ret->ignore = TRUE; return NULL; } left = req_plen - sizeof(*req); if (left < 2 + EAP_PAX_MAC_LEN) { wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 with too short " "payload"); ret->ignore = TRUE; return NULL; } pos = (const u8 *)(req + 1); if (WPA_GET_BE16(pos) != EAP_PAX_MAC_LEN) { wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 with incorrect " "MAC_CK length %d (expected %d)", WPA_GET_BE16(pos), EAP_PAX_MAC_LEN); ret->ignore = TRUE; return NULL; } pos += 2; left -= 2; wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(B, CID)", pos, EAP_PAX_MAC_LEN); eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN, data->rand.r.y, EAP_PAX_RAND_LEN, (u8 *)data->cid, data->cid_len, NULL, 0, mac); if (os_memcmp_const(pos, mac, EAP_PAX_MAC_LEN) != 0) { wpa_printf(MSG_INFO, "EAP-PAX: Invalid MAC_CK(B, CID) " "received"); wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: expected MAC_CK(B, CID)", mac, EAP_PAX_MAC_LEN); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; return NULL; } pos += EAP_PAX_MAC_LEN; left -= EAP_PAX_MAC_LEN; if (left > 0) { wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ignored extra payload", pos, left); } wpa_printf(MSG_DEBUG, "EAP-PAX: PAX-ACK (sending)"); resp = eap_pax_alloc_resp(req, id, EAP_PAX_OP_ACK, EAP_PAX_ICV_LEN); if (resp == NULL) { return NULL; } /* Optional ADE could be added here, if needed */ rpos = wpabuf_put(resp, EAP_PAX_ICV_LEN); eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN, wpabuf_head(resp), wpabuf_len(resp) - EAP_PAX_ICV_LEN, NULL, 0, NULL, 0, rpos); wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", rpos, EAP_PAX_ICV_LEN); data->state = PAX_DONE; ret->methodState = METHOD_DONE; ret->decision = DECISION_UNCOND_SUCC; ret->allowNotifications = FALSE; return resp; }
int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon, const struct wpabuf *proberesp, const struct wpabuf *assocresp) { char *buf; struct wpabuf *ap_wps_p2p_ie = NULL; char *_cmd = "SET_AP_WPS_P2P_IE"; char *pbuf; int ret = 0; int i; struct cmd_desc { int cmd; const struct wpabuf *src; } cmd_arr[] = { {0x1, beacon}, {0x2, proberesp}, {0x4, assocresp}, {-1, NULL} }; wpa_printf(MSG_DEBUG, "%s: Entry", __func__); for (i = 0; cmd_arr[i].cmd != -1; i++) { #if 0 if(cmd_arr[i].src){ wpa_printf(MSG_INFO, "cmd_arr[%d].src->size:%d\n" "cmd_arr[%d].src->used:%d\n" "cmd_arr[%d].src->ext_data:%s\n" , i, cmd_arr[i].src->size , i, cmd_arr[i].src->used , i, cmd_arr[i].src->ext_data ); } #endif ap_wps_p2p_ie = cmd_arr[i].src ? wpabuf_dup(cmd_arr[i].src) : NULL; if (ap_wps_p2p_ie) { buf = os_zalloc(strlen(_cmd) + 3 + wpabuf_len(ap_wps_p2p_ie)); if(buf) { pbuf = buf; pbuf += sprintf(pbuf, "%s %d", _cmd, cmd_arr[i].cmd); *pbuf++ = '\0'; os_memcpy(pbuf, wpabuf_head(ap_wps_p2p_ie), wpabuf_len(ap_wps_p2p_ie)); ret = wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(_cmd) + 3 + wpabuf_len(ap_wps_p2p_ie)); os_free(buf); } else { wpa_printf(MSG_ERROR, "%s: os_zalloc fail", __func__); ret = -1; } wpabuf_free(ap_wps_p2p_ie); if (ret < 0) break; } } return ret; }
static struct wpabuf *eap_pax_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, const struct wpabuf *reqData) { struct eap_pax_data *data = priv; const struct eap_pax_hdr *req; struct wpabuf *resp; u8 icvbuf[EAP_PAX_ICV_LEN], id; const u8 *icv, *pos; size_t len; u16 flen, mlen; pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, reqData, &len); if (pos == NULL || len < sizeof(*req) + EAP_PAX_ICV_LEN) { ret->ignore = TRUE; return NULL; } id = eap_get_id(reqData); req = (const struct eap_pax_hdr *)pos; flen = len - EAP_PAX_ICV_LEN; mlen = wpabuf_len(reqData) - EAP_PAX_ICV_LEN; wpa_printf(MSG_DEBUG, "EAP-PAX: received frame: op_code 0x%x " "flags 0x%x mac_id 0x%x dh_group_id 0x%x " "public_key_id 0x%x", req->op_code, req->flags, req->mac_id, req->dh_group_id, req->public_key_id); wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: received payload", pos, len - EAP_PAX_ICV_LEN); if (data->state != PAX_INIT && data->mac_id != req->mac_id) { wpa_printf(MSG_INFO, "EAP-PAX: MAC ID changed during " "authentication (was 0x%d, is 0x%d)", data->mac_id, req->mac_id); ret->ignore = TRUE; return NULL; } if (data->state != PAX_INIT && data->dh_group_id != req->dh_group_id) { wpa_printf(MSG_INFO, "EAP-PAX: DH Group ID changed during " "authentication (was 0x%d, is 0x%d)", data->dh_group_id, req->dh_group_id); ret->ignore = TRUE; return NULL; } if (data->state != PAX_INIT && data->public_key_id != req->public_key_id) { wpa_printf(MSG_INFO, "EAP-PAX: Public Key ID changed during " "authentication (was 0x%d, is 0x%d)", data->public_key_id, req->public_key_id); ret->ignore = TRUE; return NULL; } /* TODO: add support EAP_PAX_HMAC_SHA256_128 */ if (req->mac_id != EAP_PAX_MAC_HMAC_SHA1_128) { wpa_printf(MSG_INFO, "EAP-PAX: Unsupported MAC ID 0x%x", req->mac_id); ret->ignore = TRUE; return NULL; } if (req->dh_group_id != EAP_PAX_DH_GROUP_NONE) { wpa_printf(MSG_INFO, "EAP-PAX: Unsupported DH Group ID 0x%x", req->dh_group_id); ret->ignore = TRUE; return NULL; } if (req->public_key_id != EAP_PAX_PUBLIC_KEY_NONE) { wpa_printf(MSG_INFO, "EAP-PAX: Unsupported Public Key ID 0x%x", req->public_key_id); ret->ignore = TRUE; return NULL; } if (req->flags & EAP_PAX_FLAGS_MF) { /* TODO: add support for reassembling fragments */ wpa_printf(MSG_INFO, "EAP-PAX: fragmentation not supported - " "ignored packet"); ret->ignore = TRUE; return NULL; } icv = pos + len - EAP_PAX_ICV_LEN; wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", icv, EAP_PAX_ICV_LEN); if (req->op_code == EAP_PAX_OP_STD_1) { eap_pax_mac(req->mac_id, (u8 *)"", 0, wpabuf_head(reqData), mlen, NULL, 0, NULL, 0, icvbuf); } else { eap_pax_mac(req->mac_id, data->ick, EAP_PAX_ICK_LEN, wpabuf_head(reqData), mlen, NULL, 0, NULL, 0, icvbuf); } if (os_memcmp_const(icv, icvbuf, EAP_PAX_ICV_LEN) != 0) { wpa_printf(MSG_DEBUG, "EAP-PAX: invalid ICV - ignoring the " "message"); wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: expected ICV", icvbuf, EAP_PAX_ICV_LEN); ret->ignore = TRUE; return NULL; } ret->ignore = FALSE; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; ret->allowNotifications = TRUE; switch (req->op_code) { case EAP_PAX_OP_STD_1: resp = eap_pax_process_std_1(data, ret, id, req, flen); break; case EAP_PAX_OP_STD_3: resp = eap_pax_process_std_3(data, ret, id, req, flen); break; default: wpa_printf(MSG_DEBUG, "EAP-PAX: ignoring message with unknown " "op_code %d", req->op_code); ret->ignore = TRUE; return NULL; } if (ret->methodState == METHOD_DONE) { ret->allowNotifications = FALSE; } return resp; }
static int wps_process_ap_settings_e(struct wps_data *wps, struct wps_parse_attr *attr, struct wpabuf *attrs, int wps2) { struct wps_credential cred; if (!wps->wps->ap) return 0; if (wps_process_ap_settings(attr, &cred) < 0) return -1; wpa_printf(MSG_INFO, "WPS: Received new AP configuration from " "Registrar"); if (os_memcmp(cred.mac_addr, wps->wps->dev.mac_addr, ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: MAC Address in the AP Settings (" MACSTR ") does not match with own address (" MACSTR ")", MAC2STR(cred.mac_addr), MAC2STR(wps->wps->dev.mac_addr)); /* * In theory, this could be consider fatal error, but there are * number of deployed implementations using other address here * due to unclarity in the specification. For interoperability * reasons, allow this to be processed since we do not really * use the MAC Address information for anything. */ #ifdef CONFIG_WPS_STRICT if (wps2) { wpa_printf(MSG_INFO, "WPS: Do not accept incorrect " "MAC Address in AP Settings"); return -1; } #endif /* CONFIG_WPS_STRICT */ } #ifdef CONFIG_WPS2 if (!(cred.encr_type & (WPS_ENCR_NONE | WPS_ENCR_TKIP | WPS_ENCR_AES))) { if (cred.encr_type & WPS_ENCR_WEP) { wpa_printf(MSG_INFO, "WPS: Reject new AP settings " "due to WEP configuration"); wps->error_indication = WPS_EI_SECURITY_WEP_PROHIBITED; return -1; } wpa_printf(MSG_INFO, "WPS: Reject new AP settings due to " "invalid encr_type 0x%x", cred.encr_type); return -1; } #endif /* CONFIG_WPS2 */ #ifdef CONFIG_WPS_STRICT if (wps2) { if ((cred.encr_type & (WPS_ENCR_TKIP | WPS_ENCR_AES)) == WPS_ENCR_TKIP || (cred.auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) == WPS_AUTH_WPAPSK) { wpa_printf(MSG_INFO, "WPS-STRICT: Invalid WSC 2.0 " "AP Settings: WPA-Personal/TKIP only"); wps->error_indication = WPS_EI_SECURITY_TKIP_ONLY_PROHIBITED; return -1; } } #endif /* CONFIG_WPS_STRICT */ #ifdef CONFIG_WPS2 if ((cred.encr_type & (WPS_ENCR_TKIP | WPS_ENCR_AES)) == WPS_ENCR_TKIP) { wpa_printf(MSG_DEBUG, "WPS: Upgrade encr_type TKIP -> " "TKIP+AES"); cred.encr_type |= WPS_ENCR_AES; } if ((cred.auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) == WPS_AUTH_WPAPSK) { wpa_printf(MSG_DEBUG, "WPS: Upgrade auth_type WPAPSK -> " "WPAPSK+WPA2PSK"); cred.auth_type |= WPS_AUTH_WPA2PSK; } #endif /* CONFIG_WPS2 */ if (wps->wps->cred_cb) { cred.cred_attr = wpabuf_head(attrs); cred.cred_attr_len = wpabuf_len(attrs); wps->wps->cred_cb(wps->wps->cb_ctx, &cred); } return 0; }
static void eap_pax_process_std_2(struct eap_sm *sm, struct eap_pax_data *data, struct wpabuf *respData) { struct eap_pax_hdr *resp; u8 mac[EAP_PAX_MAC_LEN], icvbuf[EAP_PAX_ICV_LEN]; const u8 *pos; size_t len, left; int i; if (data->state != PAX_STD_1) return; wpa_printf(MSG_DEBUG, "EAP-PAX: Received PAX_STD-2"); pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, respData, &len); if (pos == NULL || len < sizeof(*resp) + EAP_PAX_ICV_LEN) return; resp = (struct eap_pax_hdr *) pos; pos = (u8 *) (resp + 1); left = len - sizeof(*resp); if (left < 2 + EAP_PAX_RAND_LEN || WPA_GET_BE16(pos) != EAP_PAX_RAND_LEN) { wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (B)"); return; } pos += 2; left -= 2; os_memcpy(data->rand.r.y, pos, EAP_PAX_RAND_LEN); wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Y (client rand)", data->rand.r.y, EAP_PAX_RAND_LEN); pos += EAP_PAX_RAND_LEN; left -= EAP_PAX_RAND_LEN; if (left < 2 || (size_t) 2 + WPA_GET_BE16(pos) > left) { wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (CID)"); return; } data->cid_len = WPA_GET_BE16(pos); os_free(data->cid); data->cid = os_malloc(data->cid_len); if (data->cid == NULL) { wpa_printf(MSG_INFO, "EAP-PAX: Failed to allocate memory for " "CID"); return; } os_memcpy(data->cid, pos + 2, data->cid_len); pos += 2 + data->cid_len; left -= 2 + data->cid_len; wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-PAX: CID", (u8 *) data->cid, data->cid_len); if (left < 2 + EAP_PAX_MAC_LEN || WPA_GET_BE16(pos) != EAP_PAX_MAC_LEN) { wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (MAC_CK)"); return; } pos += 2; left -= 2; wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(A, B, CID)", pos, EAP_PAX_MAC_LEN); if (eap_user_get(sm, (u8 *) data->cid, data->cid_len, 0) < 0) { wpa_hexdump_ascii(MSG_DEBUG, "EAP-PAX: unknown CID", (u8 *) data->cid, data->cid_len); data->state = FAILURE; return; } for (i = 0; i < EAP_MAX_METHODS && (sm->user->methods[i].vendor != EAP_VENDOR_IETF || sm->user->methods[i].method != EAP_TYPE_NONE); i++) { if (sm->user->methods[i].vendor == EAP_VENDOR_IETF && sm->user->methods[i].method == EAP_TYPE_PAX) break; } if (i >= EAP_MAX_METHODS || sm->user->methods[i].vendor != EAP_VENDOR_IETF || sm->user->methods[i].method != EAP_TYPE_PAX) { wpa_hexdump_ascii(MSG_DEBUG, "EAP-PAX: EAP-PAX not enabled for CID", (u8 *) data->cid, data->cid_len); data->state = FAILURE; return; } if (sm->user->password == NULL || sm->user->password_len != EAP_PAX_AK_LEN) { wpa_hexdump_ascii(MSG_DEBUG, "EAP-PAX: invalid password in " "user database for CID", (u8 *) data->cid, data->cid_len); data->state = FAILURE; return; } os_memcpy(data->ak, sm->user->password, EAP_PAX_AK_LEN); if (eap_pax_initial_key_derivation(data->mac_id, data->ak, data->rand.e, data->mk, data->ck, data->ick) < 0) { wpa_printf(MSG_INFO, "EAP-PAX: Failed to complete initial " "key derivation"); data->state = FAILURE; return; } data->keys_set = 1; eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN, data->rand.r.x, EAP_PAX_RAND_LEN, data->rand.r.y, EAP_PAX_RAND_LEN, (u8 *) data->cid, data->cid_len, mac); if (os_memcmp(mac, pos, EAP_PAX_MAC_LEN) != 0) { wpa_printf(MSG_INFO, "EAP-PAX: Invalid MAC_CK(A, B, CID) in " "PAX_STD-2"); wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected MAC_CK(A, B, CID)", mac, EAP_PAX_MAC_LEN); data->state = FAILURE; return; } pos += EAP_PAX_MAC_LEN; left -= EAP_PAX_MAC_LEN; if (left < EAP_PAX_ICV_LEN) { wpa_printf(MSG_INFO, "EAP-PAX: Too short ICV (%lu) in " "PAX_STD-2", (unsigned long) left); return; } wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN); eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN, wpabuf_head(respData), wpabuf_len(respData) - EAP_PAX_ICV_LEN, NULL, 0, NULL, 0, icvbuf); if (os_memcmp(icvbuf, pos, EAP_PAX_ICV_LEN) != 0) { wpa_printf(MSG_INFO, "EAP-PAX: Invalid ICV in PAX_STD-2"); wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected ICV", icvbuf, EAP_PAX_ICV_LEN); return; } pos += EAP_PAX_ICV_LEN; left -= EAP_PAX_ICV_LEN; if (left > 0) { wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ignored extra payload", pos, left); } data->state = PAX_STD_3; }
static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, struct hostapd_config *iconf, struct wpa_auth_config *wconf) { os_memset(wconf, 0, sizeof(*wconf)); wconf->wpa = conf->wpa; wconf->wpa_key_mgmt = conf->wpa_key_mgmt; wconf->wpa_pairwise = conf->wpa_pairwise; wconf->wpa_group = conf->wpa_group; wconf->wpa_group_rekey = conf->wpa_group_rekey; wconf->wpa_strict_rekey = conf->wpa_strict_rekey; wconf->wpa_gmk_rekey = conf->wpa_gmk_rekey; wconf->wpa_ptk_rekey = conf->wpa_ptk_rekey; wconf->wpa_group_update_count = conf->wpa_group_update_count; wconf->wpa_disable_eapol_key_retries = conf->wpa_disable_eapol_key_retries; wconf->wpa_pairwise_update_count = conf->wpa_pairwise_update_count; wconf->rsn_pairwise = conf->rsn_pairwise; wconf->rsn_preauth = conf->rsn_preauth; wconf->eapol_version = conf->eapol_version; wconf->wmm_enabled = conf->wmm_enabled; wconf->wmm_uapsd = conf->wmm_uapsd; wconf->disable_pmksa_caching = conf->disable_pmksa_caching; #ifdef CONFIG_OCV wconf->ocv = conf->ocv; #endif /* CONFIG_OCV */ wconf->okc = conf->okc; #ifdef CONFIG_IEEE80211W wconf->ieee80211w = conf->ieee80211w; wconf->group_mgmt_cipher = conf->group_mgmt_cipher; wconf->sae_require_mfp = conf->sae_require_mfp; #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_IEEE80211R_AP wconf->ssid_len = conf->ssid.ssid_len; if (wconf->ssid_len > SSID_MAX_LEN) wconf->ssid_len = SSID_MAX_LEN; os_memcpy(wconf->ssid, conf->ssid.ssid, wconf->ssid_len); os_memcpy(wconf->mobility_domain, conf->mobility_domain, MOBILITY_DOMAIN_ID_LEN); if (conf->nas_identifier && os_strlen(conf->nas_identifier) <= FT_R0KH_ID_MAX_LEN) { wconf->r0_key_holder_len = os_strlen(conf->nas_identifier); os_memcpy(wconf->r0_key_holder, conf->nas_identifier, wconf->r0_key_holder_len); } os_memcpy(wconf->r1_key_holder, conf->r1_key_holder, FT_R1KH_ID_LEN); wconf->r0_key_lifetime = conf->r0_key_lifetime; wconf->r1_max_key_lifetime = conf->r1_max_key_lifetime; wconf->reassociation_deadline = conf->reassociation_deadline; wconf->rkh_pos_timeout = conf->rkh_pos_timeout; wconf->rkh_neg_timeout = conf->rkh_neg_timeout; wconf->rkh_pull_timeout = conf->rkh_pull_timeout; wconf->rkh_pull_retries = conf->rkh_pull_retries; wconf->r0kh_list = &conf->r0kh_list; wconf->r1kh_list = &conf->r1kh_list; wconf->pmk_r1_push = conf->pmk_r1_push; wconf->ft_over_ds = conf->ft_over_ds; wconf->ft_psk_generate_local = conf->ft_psk_generate_local; #endif /* CONFIG_IEEE80211R_AP */ #ifdef CONFIG_HS20 wconf->disable_gtk = conf->disable_dgaf; if (conf->osen) { wconf->disable_gtk = 1; wconf->wpa = WPA_PROTO_OSEN; wconf->wpa_key_mgmt = WPA_KEY_MGMT_OSEN; wconf->wpa_pairwise = 0; wconf->wpa_group = WPA_CIPHER_CCMP; wconf->rsn_pairwise = WPA_CIPHER_CCMP; wconf->rsn_preauth = 0; wconf->disable_pmksa_caching = 1; #ifdef CONFIG_IEEE80211W wconf->ieee80211w = 1; #endif /* CONFIG_IEEE80211W */ } #endif /* CONFIG_HS20 */ #ifdef CONFIG_TESTING_OPTIONS wconf->corrupt_gtk_rekey_mic_probability = iconf->corrupt_gtk_rekey_mic_probability; if (conf->own_ie_override && wpabuf_len(conf->own_ie_override) <= MAX_OWN_IE_OVERRIDE) { wconf->own_ie_override_len = wpabuf_len(conf->own_ie_override); os_memcpy(wconf->own_ie_override, wpabuf_head(conf->own_ie_override), wconf->own_ie_override_len); } #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_P2P os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4); os_memcpy(wconf->ip_addr_mask, conf->ip_addr_mask, 4); os_memcpy(wconf->ip_addr_start, conf->ip_addr_start, 4); os_memcpy(wconf->ip_addr_end, conf->ip_addr_end, 4); #endif /* CONFIG_P2P */ #ifdef CONFIG_FILS wconf->fils_cache_id_set = conf->fils_cache_id_set; os_memcpy(wconf->fils_cache_id, conf->fils_cache_id, FILS_CACHE_ID_LEN); #endif /* CONFIG_FILS */ }
int offchannel_send_action(struct wpa_supplicant *wpa_s, unsigned int freq, const u8 *dst, const u8 *src, const u8 *bssid, const u8 *buf, size_t len, unsigned int wait_time, void (*tx_cb)(struct wpa_supplicant *wpa_s, unsigned int freq, const u8 *dst, const u8 *src, const u8 *bssid, const u8 *data, size_t data_len, enum offchannel_send_action_result result), int no_cck) { wpa_printf(MSG_DEBUG, "Off-channel: Send action frame: freq=%d dst=" MACSTR " src=" MACSTR " bssid=" MACSTR " len=%d", freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid), (int) len); wpa_s->pending_action_tx_status_cb = tx_cb; if (wpa_s->pending_action_tx) { wpa_printf(MSG_DEBUG, "Off-channel: Dropped pending Action " "frame TX to " MACSTR, MAC2STR(wpa_s->pending_action_dst)); wpabuf_free(wpa_s->pending_action_tx); } wpa_s->pending_action_tx = wpabuf_alloc(len); if (wpa_s->pending_action_tx == NULL) { wpa_printf(MSG_DEBUG, "Off-channel: Failed to allocate Action " "frame TX buffer (len=%llu)", (unsigned long long) len); return -1; } wpabuf_put_data(wpa_s->pending_action_tx, buf, len); os_memcpy(wpa_s->pending_action_src, src, ETH_ALEN); os_memcpy(wpa_s->pending_action_dst, dst, ETH_ALEN); os_memcpy(wpa_s->pending_action_bssid, bssid, ETH_ALEN); wpa_s->pending_action_freq = freq; wpa_s->pending_action_no_cck = no_cck; if (freq != 0 && wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX && 0) { struct wpa_supplicant *iface; iface = wpas_get_tx_interface(wpa_s, wpa_s->pending_action_src); wpa_s->action_tx_wait_time = wait_time; return wpa_drv_send_action( iface, wpa_s->pending_action_freq, wait_time, wpa_s->pending_action_dst, wpa_s->pending_action_src, wpa_s->pending_action_bssid, wpabuf_head(wpa_s->pending_action_tx), wpabuf_len(wpa_s->pending_action_tx), wpa_s->pending_action_no_cck); } if (wpa_s->off_channel_freq == freq || freq == 0) { wpa_printf(MSG_DEBUG, "Off-channel: Already on requested " "channel; send Action frame immediately"); /* TODO: Would there ever be need to extend the current * duration on the channel? */ wpa_s->pending_action_without_roc = 1; eloop_cancel_timeout(wpas_send_action_cb, wpa_s, NULL); eloop_register_timeout(0, 0, wpas_send_action_cb, wpa_s, NULL); return 0; } wpa_s->pending_action_without_roc = 0; if (wpa_s->roc_waiting_drv_freq == freq) { wpa_printf(MSG_DEBUG, "Off-channel: Already waiting for " "driver to get to frequency %u MHz; continue " "waiting to send the Action frame", freq); return 0; } wpa_printf(MSG_DEBUG, "Off-channel: Schedule Action frame to be " "transmitted once the driver gets to the requested " "channel"); if (wait_time > wpa_s->max_remain_on_chan) wait_time = wpa_s->max_remain_on_chan; if (wpa_drv_remain_on_channel(wpa_s, freq, wait_time) < 0) { wpa_printf(MSG_DEBUG, "Off-channel: Failed to request driver " "to remain on channel (%u MHz) for Action " "Frame TX", freq); return -1; } wpa_s->off_channel_freq = 0; wpa_s->roc_waiting_drv_freq = freq; return 0; }
/* MLME-SLEEPMODE.request */ int ieee802_11_send_wnmsleep_req(struct wpa_supplicant *wpa_s, u8 action, u16 intval, struct wpabuf *tfs_req) { struct ieee80211_mgmt *mgmt; int res; size_t len; struct wnm_sleep_element *wnmsleep_ie; u8 *wnmtfs_ie; u8 wnmsleep_ie_len; u16 wnmtfs_ie_len; /* possibly multiple IE(s) */ enum wnm_oper tfs_oper = action == 0 ? WNM_SLEEP_TFS_REQ_IE_ADD : WNM_SLEEP_TFS_REQ_IE_NONE; wpa_printf(MSG_DEBUG, "WNM: Request to send WNM-Sleep Mode Request " "action=%s to " MACSTR, action == 0 ? "enter" : "exit", MAC2STR(wpa_s->bssid)); /* WNM-Sleep Mode IE */ wnmsleep_ie_len = sizeof(struct wnm_sleep_element); wnmsleep_ie = os_zalloc(sizeof(struct wnm_sleep_element)); if (wnmsleep_ie == NULL) return -1; wnmsleep_ie->eid = WLAN_EID_WNMSLEEP; wnmsleep_ie->len = wnmsleep_ie_len - 2; wnmsleep_ie->action_type = action; wnmsleep_ie->status = WNM_STATUS_SLEEP_ACCEPT; wnmsleep_ie->intval = host_to_le16(intval); wpa_hexdump(MSG_DEBUG, "WNM: WNM-Sleep Mode element", (u8 *) wnmsleep_ie, wnmsleep_ie_len); /* TFS IE(s) */ if (tfs_req) { wnmtfs_ie_len = wpabuf_len(tfs_req); wnmtfs_ie = os_malloc(wnmtfs_ie_len); if (wnmtfs_ie == NULL) { os_free(wnmsleep_ie); return -1; } os_memcpy(wnmtfs_ie, wpabuf_head(tfs_req), wnmtfs_ie_len); } else { wnmtfs_ie = os_zalloc(MAX_TFS_IE_LEN); if (wnmtfs_ie == NULL) { os_free(wnmsleep_ie); return -1; } if (ieee80211_11_get_tfs_ie(wpa_s, wnmtfs_ie, &wnmtfs_ie_len, tfs_oper)) { wnmtfs_ie_len = 0; os_free(wnmtfs_ie); wnmtfs_ie = NULL; } } wpa_hexdump(MSG_DEBUG, "WNM: TFS Request element", (u8 *) wnmtfs_ie, wnmtfs_ie_len); mgmt = os_zalloc(sizeof(*mgmt) + wnmsleep_ie_len + wnmtfs_ie_len); if (mgmt == NULL) { wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for " "WNM-Sleep Request action frame"); os_free(wnmsleep_ie); os_free(wnmtfs_ie); return -1; } os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN); os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN); os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN); mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ACTION); mgmt->u.action.category = WLAN_ACTION_WNM; mgmt->u.action.u.wnm_sleep_req.action = WNM_SLEEP_MODE_REQ; mgmt->u.action.u.wnm_sleep_req.dialogtoken = 1; os_memcpy(mgmt->u.action.u.wnm_sleep_req.variable, wnmsleep_ie, wnmsleep_ie_len); /* copy TFS IE here */ if (wnmtfs_ie_len > 0) { os_memcpy(mgmt->u.action.u.wnm_sleep_req.variable + wnmsleep_ie_len, wnmtfs_ie, wnmtfs_ie_len); } len = 1 + sizeof(mgmt->u.action.u.wnm_sleep_req) + wnmsleep_ie_len + wnmtfs_ie_len; res = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, wpa_s->own_addr, wpa_s->bssid, &mgmt->u.action.category, len, 0); if (res < 0) wpa_printf(MSG_DEBUG, "Failed to send WNM-Sleep Request " "(action=%d, intval=%d)", action, intval); os_free(wnmsleep_ie); os_free(wnmtfs_ie); os_free(mgmt); return res; }
static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) { struct wpa_supplicant *wpa_s = eloop_ctx; struct wpa_ssid *ssid; int scan_req = 0, ret; struct wpabuf *wps_ie = NULL; const u8 *extra_ie = NULL; size_t extra_ie_len = 0; int wps = 0; #ifdef CONFIG_WPS enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO; #endif /* CONFIG_WPS */ wpa_printf(MSG_DEBUG, "%s: scan_req = %d, ap_scan = %d", __func__, wpa_s->scan_req, wpa_s->conf->ap_scan); if (wpa_s->disconnected && !wpa_s->scan_req) { wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); return; } if (!wpa_supplicant_enabled_networks(wpa_s->conf) && !wpa_s->scan_req) { wpa_printf(MSG_DEBUG, "No enabled networks - do not scan"); wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); return; } scan_req = wpa_s->scan_req; wpa_s->scan_req = 0; if (wpa_s->conf->ap_scan != 0 && wpa_s->driver && IS_WIRED(wpa_s->driver)) { wpa_printf(MSG_DEBUG, "Using wired authentication - " "overriding ap_scan configuration"); wpa_s->conf->ap_scan = 0; } if (wpa_s->conf->ap_scan == 0) { wpa_supplicant_gen_assoc_event(wpa_s); return; } if (wpa_s->wpa_state == WPA_DISCONNECTED || wpa_s->wpa_state == WPA_INACTIVE) wpa_supplicant_set_state(wpa_s, WPA_SCANNING); ssid = wpa_s->conf->ssid; if (wpa_s->prev_scan_ssid != BROADCAST_SSID_SCAN) { while (ssid) { if (ssid == wpa_s->prev_scan_ssid) { ssid = ssid->next; break; } ssid = ssid->next; } } while (ssid) { //MTK_OP01_PROTECT_START #ifdef CONFIG_CMCC_SUPPORT /* CMCC */ if ( #else //MTK_OP01_PROTECT_END if (!ssid->disabled && //MTK_OP01_PROTECT_START #endif //MTK_OP01_PROTECT_END (ssid->scan_ssid || wpa_s->conf->ap_scan == 2)) break; ssid = ssid->next; } if (scan_req != 2 && wpa_s->conf->ap_scan == 2) { /* * ap_scan=2 mode - try to associate with each SSID instead of * scanning for each scan_ssid=1 network. */ if (ssid == NULL) { wpa_printf(MSG_DEBUG, "wpa_supplicant_scan: Reached " "end of scan list - go back to beginning"); wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN; wpa_supplicant_req_scan(wpa_s, 0, 0); return; } if (ssid->next) { /* Continue from the next SSID on the next attempt. */ wpa_s->prev_scan_ssid = ssid; } else { /* Start from the beginning of the SSID list. */ wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN; } wpa_supplicant_associate(wpa_s, NULL, ssid); return; } #ifdef CONFIG_WPS wps = wpas_wps_in_use(wpa_s->conf, &req_type); #endif /* CONFIG_WPS */ if (wpa_s->scan_res_tried == 0 && wpa_s->conf->ap_scan == 1 && !wpa_s->use_client_mlme && wps != 2) { wpa_s->scan_res_tried++; wpa_s->scan_req = scan_req; wpa_printf(MSG_DEBUG, "Trying to get current scan results " "first without requesting a new scan to speed up " "initial association"); wpa_supplicant_event(wpa_s, EVENT_SCAN_RESULTS, NULL); return; } #ifdef CONFIG_WPS if (wps) { wps_ie = wps_build_probe_req_ie(wps == 2, &wpa_s->wps->dev, wpa_s->wps->uuid, req_type); if (wps_ie) { extra_ie = wpabuf_head(wps_ie); extra_ie_len = wpabuf_len(wps_ie); } } #endif /* CONFIG_WPS */ wpa_supplicant_notify_scanning(wpa_s, 1); wpa_printf(MSG_DEBUG, "Starting AP scan (%s SSID)", ssid ? "specific": "broadcast"); if (ssid) { wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID", ssid->ssid, ssid->ssid_len); wpa_s->prev_scan_ssid = ssid; } else wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN; if (wpa_s->use_client_mlme) { ieee80211_sta_set_probe_req_ie(wpa_s, extra_ie, extra_ie_len); ret = ieee80211_sta_req_scan(wpa_s, ssid ? ssid->ssid : NULL, ssid ? ssid->ssid_len : 0); } else { wpa_drv_set_probe_req_ie(wpa_s, extra_ie, extra_ie_len); ret = wpa_drv_scan(wpa_s, &ssid); } wpabuf_free(wps_ie); if (ret) { wpa_printf(MSG_WARNING, "Failed to initiate AP scan."); wpa_supplicant_notify_scanning(wpa_s, 0); wpa_supplicant_req_scan(wpa_s, 10, 0); } else { wpa_s->scan_runs++; } }
static void ieee802_1x_decapsulate_radius(struct eapol_test_data *e) { struct wpabuf *eap; const struct eap_hdr *hdr; int eap_type = -1; char buf[64]; struct radius_msg *msg; if (e->last_recv_radius == NULL) return; msg = e->last_recv_radius; eap = radius_msg_get_eap(msg); if (eap == NULL) { /* draft-aboba-radius-rfc2869bis-20.txt, Chap. 2.6.3: * RADIUS server SHOULD NOT send Access-Reject/no EAP-Message * attribute */ wpa_printf(MSG_DEBUG, "could not extract " "EAP-Message from RADIUS message"); wpabuf_free(e->last_eap_radius); e->last_eap_radius = NULL; return; } if (wpabuf_len(eap) < sizeof(*hdr)) { wpa_printf(MSG_DEBUG, "too short EAP packet " "received from authentication server"); wpabuf_free(eap); return; } if (wpabuf_len(eap) > sizeof(*hdr)) eap_type = (wpabuf_head_u8(eap))[sizeof(*hdr)]; hdr = wpabuf_head(eap); switch (hdr->code) { case EAP_CODE_REQUEST: os_snprintf(buf, sizeof(buf), "EAP-Request-%s (%d)", eap_type >= 0 ? eap_type_text(eap_type) : "??", eap_type); break; case EAP_CODE_RESPONSE: os_snprintf(buf, sizeof(buf), "EAP Response-%s (%d)", eap_type >= 0 ? eap_type_text(eap_type) : "??", eap_type); break; case EAP_CODE_SUCCESS: os_strlcpy(buf, "EAP Success", sizeof(buf)); /* LEAP uses EAP Success within an authentication, so must not * stop here with eloop_terminate(); */ break; case EAP_CODE_FAILURE: os_strlcpy(buf, "EAP Failure", sizeof(buf)); eloop_terminate(); break; default: os_strlcpy(buf, "unknown EAP code", sizeof(buf)); wpa_hexdump_buf(MSG_DEBUG, "Decapsulated EAP packet", eap); break; } wpa_printf(MSG_DEBUG, "decapsulated EAP packet (code=%d " "id=%d len=%d) from RADIUS server: %s", hdr->code, hdr->identifier, ntohs(hdr->length), buf); /* sta->eapol_sm->be_auth.idFromServer = hdr->identifier; */ wpabuf_free(e->last_eap_radius); e->last_eap_radius = eap; { struct ieee802_1x_hdr *dot1x; dot1x = os_malloc(sizeof(*dot1x) + wpabuf_len(eap)); assert(dot1x != NULL); dot1x->version = EAPOL_VERSION; dot1x->type = IEEE802_1X_TYPE_EAP_PACKET; dot1x->length = htons(wpabuf_len(eap)); os_memcpy((u8 *) (dot1x + 1), wpabuf_head(eap), wpabuf_len(eap)); eapol_sm_rx_eapol(e->wpa_s->eapol, e->wpa_s->bssid, (u8 *) dot1x, sizeof(*dot1x) + wpabuf_len(eap)); os_free(dot1x); } }
void handle_probe_req(struct hostapd_data *hapd, const struct ieee80211_mgmt *mgmt, size_t len) { struct ieee80211_mgmt *resp; struct ieee802_11_elems elems; char *ssid; u8 *pos, *epos; const u8 *ie; size_t ssid_len, ie_len; struct sta_info *sta = NULL; size_t buflen; size_t i; int noack; ie = mgmt->u.probe_req.variable; if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)) return; ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)); for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx, mgmt->sa, mgmt->da, mgmt->bssid, ie, ie_len) > 0) return; if (!hapd->iconf->send_probe_response) return; if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) { wpa_printf(MSG_DEBUG, "Could not parse ProbeReq from " MACSTR, MAC2STR(mgmt->sa)); return; } ssid = NULL; ssid_len = 0; if ((!elems.ssid || !elems.supp_rates)) { wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request " "without SSID or supported rates element", MAC2STR(mgmt->sa)); return; } #ifdef CONFIG_P2P if (hapd->p2p && elems.wps_ie) { struct wpabuf *wps; wps = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA); if (wps && !p2p_group_match_dev_type(hapd->p2p_group, wps)) { wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request " "due to mismatch with Requested Device " "Type"); wpabuf_free(wps); return; } wpabuf_free(wps); } #endif /* CONFIG_P2P */ if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0) { wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for " "broadcast SSID ignored", MAC2STR(mgmt->sa)); return; } sta = ap_get_sta(hapd, mgmt->sa); #ifdef CONFIG_P2P if ((hapd->conf->p2p & P2P_GROUP_OWNER) && elems.ssid_len == P2P_WILDCARD_SSID_LEN && os_memcmp(elems.ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) { /* Process P2P Wildcard SSID like Wildcard SSID */ elems.ssid_len = 0; } #endif /* CONFIG_P2P */ if (elems.ssid_len == 0 || (elems.ssid_len == hapd->conf->ssid.ssid_len && os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) == 0)) { ssid = hapd->conf->ssid.ssid; ssid_len = hapd->conf->ssid.ssid_len; if (sta) sta->ssid_probe = &hapd->conf->ssid; } if (!ssid) { if (!(mgmt->da[0] & 0x01)) { char ssid_txt[33]; ieee802_11_print_ssid(ssid_txt, elems.ssid, elems.ssid_len); wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for foreign SSID '%s' (DA " MACSTR ")", MAC2STR(mgmt->sa), ssid_txt, MAC2STR(mgmt->da)); } return; } #ifdef CONFIG_INTERWORKING if (elems.interworking && elems.interworking_len >= 1) { u8 ant = elems.interworking[0] & 0x0f; if (ant != INTERWORKING_ANT_WILDCARD && ant != hapd->conf->access_network_type) { wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for mismatching ANT %u ignored", MAC2STR(mgmt->sa), ant); return; } } if (elems.interworking && (elems.interworking_len == 7 || elems.interworking_len == 9)) { const u8 *hessid; if (elems.interworking_len == 7) hessid = elems.interworking + 1; else hessid = elems.interworking + 1 + 2; if (!is_broadcast_ether_addr(hessid) && os_memcmp(hessid, hapd->conf->hessid, ETH_ALEN) != 0) { wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for mismatching HESSID " MACSTR " ignored", MAC2STR(mgmt->sa), MAC2STR(hessid)); return; } } #endif /* CONFIG_INTERWORKING */ /* TODO: verify that supp_rates contains at least one matching rate * with AP configuration */ #define MAX_PROBERESP_LEN 768 buflen = MAX_PROBERESP_LEN; #ifdef CONFIG_WPS if (hapd->wps_probe_resp_ie) buflen += wpabuf_len(hapd->wps_probe_resp_ie); #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P if (hapd->p2p_probe_resp_ie) buflen += wpabuf_len(hapd->p2p_probe_resp_ie); #endif /* CONFIG_P2P */ resp = os_zalloc(buflen); if (resp == NULL) return; epos = ((u8 *) resp) + MAX_PROBERESP_LEN; resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_PROBE_RESP); os_memcpy(resp->da, mgmt->sa, ETH_ALEN); os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN); os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN); resp->u.probe_resp.beacon_int = host_to_le16(hapd->iconf->beacon_int); /* hardware or low-level driver will setup seq_ctrl and timestamp */ resp->u.probe_resp.capab_info = host_to_le16(hostapd_own_capab_info(hapd, sta, 1)); pos = resp->u.probe_resp.variable; *pos++ = WLAN_EID_SSID; *pos++ = ssid_len; os_memcpy(pos, ssid, ssid_len); pos += ssid_len; /* Supported rates */ pos = hostapd_eid_supp_rates(hapd, pos); /* DS Params */ pos = hostapd_eid_ds_params(hapd, pos); pos = hostapd_eid_country(hapd, pos, epos - pos); /* ERP Information element */ pos = hostapd_eid_erp_info(hapd, pos); /* Extended supported rates */ pos = hostapd_eid_ext_supp_rates(hapd, pos); /* RSN, MDIE, WPA */ pos = hostapd_eid_wpa(hapd, pos, epos - pos); #ifdef CONFIG_IEEE80211N pos = hostapd_eid_ht_capabilities(hapd, pos); pos = hostapd_eid_ht_operation(hapd, pos); #endif /* CONFIG_IEEE80211N */ pos = hostapd_eid_ext_capab(hapd, pos); pos = hostapd_eid_time_adv(hapd, pos); pos = hostapd_eid_time_zone(hapd, pos); pos = hostapd_eid_interworking(hapd, pos); pos = hostapd_eid_adv_proto(hapd, pos); pos = hostapd_eid_roaming_consortium(hapd, pos); /* Wi-Fi Alliance WMM */ pos = hostapd_eid_wmm(hapd, pos); #ifdef CONFIG_WPS if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) { os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie), wpabuf_len(hapd->wps_probe_resp_ie)); pos += wpabuf_len(hapd->wps_probe_resp_ie); } #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P if ((hapd->conf->p2p & P2P_ENABLED) && elems.p2p && hapd->p2p_probe_resp_ie) { os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie), wpabuf_len(hapd->p2p_probe_resp_ie)); pos += wpabuf_len(hapd->p2p_probe_resp_ie); } #endif /* CONFIG_P2P */ #ifdef CONFIG_P2P_MANAGER if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) == P2P_MANAGE) pos = hostapd_eid_p2p_manage(hapd, pos); #endif /* CONFIG_P2P_MANAGER */ #ifdef CONFIG_HS20 pos = hostapd_eid_hs20_indication(hapd, pos); #endif /* CONFIG_HS20 */ /* * If this is a broadcast probe request, apply no ack policy to avoid * excessive retries. */ noack = !!(elems.ssid_len == 0 && is_broadcast_ether_addr(mgmt->da)); if (hostapd_drv_send_mlme(hapd, resp, pos - (u8 *) resp, noack) < 0) perror("handle_probe_req: send"); os_free(resp); wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s " "SSID", MAC2STR(mgmt->sa), elems.ssid_len == 0 ? "broadcast" : "our"); }
struct wpabuf * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { struct tls_global *global = tls_ctx; struct wpabuf *out_data; int ret; if (appl_data) *appl_data = NULL; if (in_data && wpabuf_len(in_data) > 0) { if (conn->pull_buf) { wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " "pull_buf", __func__, (unsigned long) wpabuf_len(conn->pull_buf)); wpabuf_free(conn->pull_buf); } conn->pull_buf = wpabuf_dup(in_data); if (conn->pull_buf == NULL) return NULL; conn->pull_buf_offset = wpabuf_head(conn->pull_buf); } ret = gnutls_handshake(conn->session); if (ret < 0) { switch (ret) { case GNUTLS_E_AGAIN: if (global->server && conn->established && conn->push_buf == NULL) { /* Need to return something to trigger * completion of EAP-TLS. */ conn->push_buf = wpabuf_alloc(0); } break; case GNUTLS_E_FATAL_ALERT_RECEIVED: wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert", __func__, gnutls_alert_get_name( gnutls_alert_get(conn->session))); conn->read_alerts++; /* continue */ default: wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed " "-> %s", __func__, gnutls_strerror(ret)); conn->failed++; } } else { size_t size; gnutls_alert_description_t err; if (conn->verify_peer && tls_connection_verify_peer(conn, &err)) { wpa_printf(MSG_INFO, "TLS: Peer certificate chain " "failed validation"); conn->failed++; gnutls_alert_send(conn->session, GNUTLS_AL_FATAL, err); goto out; } wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully"); conn->established = 1; if (conn->push_buf == NULL) { /* Need to return something to get final TLS ACK. */ conn->push_buf = wpabuf_alloc(0); } gnutls_session_get_data(conn->session, NULL, &size); if (global->session_data == NULL || global->session_data_size < size) { os_free(global->session_data); global->session_data = os_malloc(size); } if (global->session_data) { global->session_data_size = size; gnutls_session_get_data(conn->session, global->session_data, &global->session_data_size); } if (conn->pull_buf && appl_data) *appl_data = gnutls_get_appl_data(conn); } out: out_data = conn->push_buf; conn->push_buf = NULL; return out_data; }
void ieee802_11_set_beacon(struct hostapd_data *hapd) { struct ieee80211_mgmt *head = NULL; u8 *tail = NULL; size_t head_len = 0, tail_len = 0; u8 *resp = NULL; size_t resp_len = 0; struct wpa_driver_ap_params params; struct wpabuf *beacon, *proberesp, *assocresp; #ifdef NEED_AP_MLME u16 capab_info; u8 *pos, *tailpos; #endif /* NEED_AP_MLME */ hapd->beacon_set_done = 1; #ifdef NEED_AP_MLME #define BEACON_HEAD_BUF_SIZE 256 #define BEACON_TAIL_BUF_SIZE 512 head = os_zalloc(BEACON_HEAD_BUF_SIZE); tail_len = BEACON_TAIL_BUF_SIZE; #ifdef CONFIG_WPS if (hapd->conf->wps_state && hapd->wps_beacon_ie) tail_len += wpabuf_len(hapd->wps_beacon_ie); #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P if (hapd->p2p_beacon_ie) tail_len += wpabuf_len(hapd->p2p_beacon_ie); #endif /* CONFIG_P2P */ tailpos = tail = os_malloc(tail_len); if (head == NULL || tail == NULL) { wpa_printf(MSG_ERROR, "Failed to set beacon data"); os_free(head); os_free(tail); return; } head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_BEACON); head->duration = host_to_le16(0); os_memset(head->da, 0xff, ETH_ALEN); os_memcpy(head->sa, hapd->own_addr, ETH_ALEN); os_memcpy(head->bssid, hapd->own_addr, ETH_ALEN); head->u.beacon.beacon_int = host_to_le16(hapd->iconf->beacon_int); /* hardware or low-level driver will setup seq_ctrl and timestamp */ capab_info = hostapd_own_capab_info(hapd, NULL, 0); head->u.beacon.capab_info = host_to_le16(capab_info); pos = &head->u.beacon.variable[0]; /* SSID */ *pos++ = WLAN_EID_SSID; if (hapd->conf->ignore_broadcast_ssid == 2) { /* clear the data, but keep the correct length of the SSID */ *pos++ = hapd->conf->ssid.ssid_len; os_memset(pos, 0, hapd->conf->ssid.ssid_len); pos += hapd->conf->ssid.ssid_len; } else if (hapd->conf->ignore_broadcast_ssid) { *pos++ = 0; /* empty SSID */ } else { *pos++ = hapd->conf->ssid.ssid_len; os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len); pos += hapd->conf->ssid.ssid_len; } /* Supported rates */ pos = hostapd_eid_supp_rates(hapd, pos); /* DS Params */ pos = hostapd_eid_ds_params(hapd, pos); head_len = pos - (u8 *) head; tailpos = hostapd_eid_country(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE - tailpos); /* ERP Information element */ tailpos = hostapd_eid_erp_info(hapd, tailpos); /* Extended supported rates */ tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos); /* RSN, MDIE, WPA */ tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE - tailpos); #ifdef CONFIG_IEEE80211N tailpos = hostapd_eid_ht_capabilities(hapd, tailpos); tailpos = hostapd_eid_ht_operation(hapd, tailpos); #endif /* CONFIG_IEEE80211N */ tailpos = hostapd_eid_ext_capab(hapd, tailpos); /* * TODO: Time Advertisement element should only be included in some * DTIM Beacon frames. */ tailpos = hostapd_eid_time_adv(hapd, tailpos); tailpos = hostapd_eid_interworking(hapd, tailpos); tailpos = hostapd_eid_adv_proto(hapd, tailpos); tailpos = hostapd_eid_roaming_consortium(hapd, tailpos); /* Wi-Fi Alliance WMM */ tailpos = hostapd_eid_wmm(hapd, tailpos); #ifdef CONFIG_WPS if (hapd->conf->wps_state && hapd->wps_beacon_ie) { os_memcpy(tailpos, wpabuf_head(hapd->wps_beacon_ie), wpabuf_len(hapd->wps_beacon_ie)); tailpos += wpabuf_len(hapd->wps_beacon_ie); } #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_beacon_ie) { os_memcpy(tailpos, wpabuf_head(hapd->p2p_beacon_ie), wpabuf_len(hapd->p2p_beacon_ie)); tailpos += wpabuf_len(hapd->p2p_beacon_ie); } #endif /* CONFIG_P2P */ #ifdef CONFIG_P2P_MANAGER if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) == P2P_MANAGE) tailpos = hostapd_eid_p2p_manage(hapd, tailpos); #endif /* CONFIG_P2P_MANAGER */ #ifdef CONFIG_HS20 tailpos = hostapd_eid_hs20_indication(hapd, tailpos); #endif /* CONFIG_HS20 */ tail_len = tailpos > tail ? tailpos - tail : 0; resp = hostapd_probe_resp_offloads(hapd, &resp_len); #endif /* NEED_AP_MLME */ os_memset(¶ms, 0, sizeof(params)); params.head = (u8 *) head; params.head_len = head_len; params.tail = tail; params.tail_len = tail_len; params.proberesp = resp; params.proberesp_len = resp_len; params.dtim_period = hapd->conf->dtim_period; params.beacon_int = hapd->iconf->beacon_int; params.basic_rates = hapd->iconf->basic_rates; params.ssid = (u8 *) hapd->conf->ssid.ssid; params.ssid_len = hapd->conf->ssid.ssid_len; params.pairwise_ciphers = hapd->conf->rsn_pairwise ? hapd->conf->rsn_pairwise : hapd->conf->wpa_pairwise; params.group_cipher = hapd->conf->wpa_group; params.key_mgmt_suites = hapd->conf->wpa_key_mgmt; params.auth_algs = hapd->conf->auth_algs; params.wpa_version = hapd->conf->wpa; params.privacy = hapd->conf->ssid.wep.keys_set || hapd->conf->wpa || (hapd->conf->ieee802_1x && (hapd->conf->default_wep_key_len || hapd->conf->individual_wep_key_len)); switch (hapd->conf->ignore_broadcast_ssid) { case 0: params.hide_ssid = NO_SSID_HIDING; break; case 1: params.hide_ssid = HIDDEN_SSID_ZERO_LEN; break; case 2: params.hide_ssid = HIDDEN_SSID_ZERO_CONTENTS; break; } hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp); params.beacon_ies = beacon; params.proberesp_ies = proberesp; params.assocresp_ies = assocresp; params.isolate = hapd->conf->isolate; #ifdef NEED_AP_MLME params.cts_protect = !!(ieee802_11_erp_info(hapd) & ERP_INFO_USE_PROTECTION); params.preamble = hapd->iface->num_sta_no_short_preamble == 0 && hapd->iconf->preamble == SHORT_PREAMBLE; if (hapd->iface->current_mode && hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) params.short_slot_time = hapd->iface->num_sta_no_short_slot_time > 0 ? 0 : 1; else params.short_slot_time = -1; if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n) params.ht_opmode = -1; else params.ht_opmode = hapd->iface->ht_op_mode; #endif /* NEED_AP_MLME */ params.interworking = hapd->conf->interworking; if (hapd->conf->interworking && !is_zero_ether_addr(hapd->conf->hessid)) params.hessid = hapd->conf->hessid; params.access_network_type = hapd->conf->access_network_type; params.ap_max_inactivity = hapd->conf->ap_max_inactivity; #ifdef CONFIG_HS20 params.disable_dgaf = hapd->conf->disable_dgaf; #endif /* CONFIG_HS20 */ if (hostapd_drv_set_ap(hapd, ¶ms)) wpa_printf(MSG_ERROR, "Failed to set beacon parameters"); hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp); os_free(tail); os_free(head); os_free(resp); }
static struct wpabuf *eap_pax_process_std_1(struct eap_pax_data *data, struct eap_method_ret *ret, u8 id, const struct eap_pax_hdr *req, size_t req_plen) { struct wpabuf *resp; const u8 *pos; u8 *rpos; size_t left, plen; wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-1 (received)"); if (data->state != PAX_INIT) { wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 received in " "unexpected state (%d) - ignored", data->state); ret->ignore = TRUE; return NULL; } if (req->flags & EAP_PAX_FLAGS_CE) { wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with CE flag set - " "ignored"); ret->ignore = TRUE; return NULL; } left = req_plen - sizeof(*req); if (left < 2 + EAP_PAX_RAND_LEN) { wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with too short " "payload"); ret->ignore = TRUE; return NULL; } pos = (const u8 *)(req + 1); if (WPA_GET_BE16(pos) != EAP_PAX_RAND_LEN) { wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with incorrect A " "length %d (expected %d)", WPA_GET_BE16(pos), EAP_PAX_RAND_LEN); ret->ignore = TRUE; return NULL; } pos += 2; left -= 2; os_memcpy(data->rand.r.x, pos, EAP_PAX_RAND_LEN); wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: X (server rand)", data->rand.r.x, EAP_PAX_RAND_LEN); pos += EAP_PAX_RAND_LEN; left -= EAP_PAX_RAND_LEN; if (left > 0) { wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ignored extra payload", pos, left); } if (random_get_bytes(data->rand.r.y, EAP_PAX_RAND_LEN)) { wpa_printf(MSG_ERROR, "EAP-PAX: Failed to get random data"); ret->ignore = TRUE; return NULL; } wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Y (client rand)", data->rand.r.y, EAP_PAX_RAND_LEN); if (eap_pax_initial_key_derivation(req->mac_id, data->ak, data->rand.e, data->mk, data->ck, data->ick, data->mid) < 0) { ret->ignore = TRUE; return NULL; } wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-2 (sending)"); plen = 2 + EAP_PAX_RAND_LEN + 2 + data->cid_len + 2 + EAP_PAX_MAC_LEN + EAP_PAX_ICV_LEN; resp = eap_pax_alloc_resp(req, id, EAP_PAX_OP_STD_2, plen); if (resp == NULL) { return NULL; } wpabuf_put_be16(resp, EAP_PAX_RAND_LEN); wpabuf_put_data(resp, data->rand.r.y, EAP_PAX_RAND_LEN); wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: B = Y (client rand)", data->rand.r.y, EAP_PAX_RAND_LEN); wpabuf_put_be16(resp, data->cid_len); wpabuf_put_data(resp, data->cid, data->cid_len); wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-PAX: CID", (u8 *)data->cid, data->cid_len); wpabuf_put_be16(resp, EAP_PAX_MAC_LEN); rpos = wpabuf_put(resp, EAP_PAX_MAC_LEN); eap_pax_mac(req->mac_id, data->ck, EAP_PAX_CK_LEN, data->rand.r.x, EAP_PAX_RAND_LEN, data->rand.r.y, EAP_PAX_RAND_LEN, (u8 *)data->cid, data->cid_len, rpos); wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(A, B, CID)", rpos, EAP_PAX_MAC_LEN); /* Optional ADE could be added here, if needed */ rpos = wpabuf_put(resp, EAP_PAX_ICV_LEN); eap_pax_mac(req->mac_id, data->ick, EAP_PAX_ICK_LEN, wpabuf_head(resp), wpabuf_len(resp) - EAP_PAX_ICV_LEN, NULL, 0, NULL, 0, rpos); wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", rpos, EAP_PAX_ICV_LEN); data->state = PAX_STD_2_SENT; data->mac_id = req->mac_id; data->dh_group_id = req->dh_group_id; data->public_key_id = req->public_key_id; return resp; }
static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, const struct wpabuf *reqData) { const struct eap_hdr *req; size_t left; int res; u8 flags, id; struct wpabuf *resp; const u8 *pos; struct eap_peap_data *data = priv; struct wpabuf msg; pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_PEAP, ret, reqData, &left, &flags); if (pos == NULL) return NULL; req = wpabuf_head(reqData); id = req->identifier; if (flags & EAP_TLS_FLAGS_START) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Start (server ver=%d, own " "ver=%d)", flags & EAP_TLS_VERSION_MASK, data->peap_version); if ((flags & EAP_TLS_VERSION_MASK) < data->peap_version) data->peap_version = flags & EAP_TLS_VERSION_MASK; if (data->force_peap_version >= 0 && data->force_peap_version != data->peap_version) { wpa_printf(MSG_WARNING, "EAP-PEAP: Failed to select " "forced PEAP version %d", data->force_peap_version); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; ret->allowNotifications = FALSE; return NULL; } wpa_printf(MSG_DEBUG, "EAP-PEAP: Using PEAP version %d", data->peap_version); left = 0; /* make sure that this frame is empty, even though it * should always be, anyway */ } wpabuf_set(&msg, pos, left); resp = NULL; if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) && !data->resuming) { res = eap_peap_decrypt(sm, data, ret, req, &msg, &resp); } else { if (sm->waiting_ext_cert_check && data->pending_resp) { struct eap_peer_config *config = eap_get_config(sm); if (config->pending_ext_cert_check == EXT_CERT_CHECK_GOOD) { wpa_printf(MSG_DEBUG, "EAP-PEAP: External certificate check succeeded - continue handshake"); resp = data->pending_resp; data->pending_resp = NULL; sm->waiting_ext_cert_check = 0; return resp; } if (config->pending_ext_cert_check == EXT_CERT_CHECK_BAD) { wpa_printf(MSG_DEBUG, "EAP-PEAP: External certificate check failed - force authentication failure"); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; sm->waiting_ext_cert_check = 0; return NULL; } wpa_printf(MSG_DEBUG, "EAP-PEAP: Continuing to wait external server certificate validation"); return NULL; } res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_PEAP, data->peap_version, id, &msg, &resp); if (res < 0) { wpa_printf(MSG_DEBUG, "EAP-PEAP: TLS processing failed"); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; return resp; } if (sm->waiting_ext_cert_check) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Waiting external server certificate validation"); wpabuf_free(data->pending_resp); data->pending_resp = resp; return NULL; } if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { char *label; wpa_printf(MSG_DEBUG, "EAP-PEAP: TLS done, proceed to Phase 2"); eap_peap_free_key(data); /* draft-josefsson-ppext-eap-tls-eap-05.txt * specifies that PEAPv1 would use "client PEAP * encryption" as the label. However, most existing * PEAPv1 implementations seem to be using the old * label, "client EAP encryption", instead. Use the old * label by default, but allow it to be configured with * phase1 parameter peaplabel=1. */ if (data->force_new_label) label = "client PEAP encryption"; else label = "client EAP encryption"; wpa_printf(MSG_DEBUG, "EAP-PEAP: using label '%s' in " "key derivation", label); data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, label, EAP_TLS_KEY_LEN); if (data->key_data) { wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Derived key", data->key_data, EAP_TLS_KEY_LEN); } else { wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to " "derive key"); } os_free(data->session_id); data->session_id = eap_peer_tls_derive_session_id(sm, &data->ssl, EAP_TYPE_PEAP, &data->id_len); if (data->session_id) { wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived Session-Id", data->session_id, data->id_len); } else { wpa_printf(MSG_ERROR, "EAP-PEAP: Failed to " "derive Session-Id"); } if (sm->workaround && data->resuming) { /* * At least few RADIUS servers (Aegis v1.1.6; * but not v1.1.4; and Cisco ACS) seem to be * terminating PEAPv1 (Aegis) or PEAPv0 (Cisco * ACS) session resumption with outer * EAP-Success. This does not seem to follow * draft-josefsson-pppext-eap-tls-eap-05.txt * section 4.2, so only allow this if EAP * workarounds are enabled. */ wpa_printf(MSG_DEBUG, "EAP-PEAP: Workaround - " "allow outer EAP-Success to " "terminate PEAP resumption"); ret->decision = DECISION_COND_SUCC; data->phase2_success = 1; } data->resuming = 0; } if (res == 2) { /* * Application data included in the handshake message. */ wpabuf_free(data->pending_phase2_req); data->pending_phase2_req = resp; resp = NULL; res = eap_peap_decrypt(sm, data, ret, req, &msg, &resp); } } if (ret->methodState == METHOD_DONE) { ret->allowNotifications = FALSE; } if (res == 1) { wpabuf_free(resp); return eap_peer_tls_build_ack(id, EAP_TYPE_PEAP, data->peap_version); } return resp; }
static void gas_serv_rx_gas_initial_req(struct hostapd_data *hapd, const u8 *sa, const u8 *data, size_t len, int prot, int std_addr3) { const u8 *pos = data; const u8 *end = data + len; const u8 *next; u8 dialog_token; u16 slen; struct anqp_query_info qi; const u8 *adv_proto; if (len < 1 + 2) return; os_memset(&qi, 0, sizeof(qi)); dialog_token = *pos++; wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: GAS Initial Request from " MACSTR " (dialog token %u) ", MAC2STR(sa), dialog_token); if (*pos != WLAN_EID_ADV_PROTO) { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Unexpected IE in GAS Initial Request: %u", *pos); return; } adv_proto = pos++; slen = *pos++; if (slen > end - pos || slen < 2) { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Invalid IE in GAS Initial Request"); return; } next = pos + slen; pos++; /* skip QueryRespLenLimit and PAME-BI */ if (*pos != ACCESS_NETWORK_QUERY_PROTOCOL) { struct wpabuf *buf; wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Unsupported GAS advertisement protocol id %u", *pos); if (sa[0] & 0x01) return; /* Invalid source address - drop silently */ buf = gas_build_initial_resp( dialog_token, WLAN_STATUS_GAS_ADV_PROTO_NOT_SUPPORTED, 0, 2 + slen + 2); if (buf == NULL) return; wpabuf_put_data(buf, adv_proto, 2 + slen); wpabuf_put_le16(buf, 0); /* Query Response Length */ if (prot) convert_to_protected_dual(buf); if (std_addr3) hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa, wpabuf_head(buf), wpabuf_len(buf)); else hostapd_drv_send_action_addr3_ap(hapd, hapd->iface->freq, 0, sa, wpabuf_head(buf), wpabuf_len(buf)); wpabuf_free(buf); return; } pos = next; /* Query Request */ if (end - pos < 2) return; slen = WPA_GET_LE16(pos); pos += 2; if (slen > end - pos) return; end = pos + slen; /* ANQP Query Request */ while (pos < end) { u16 info_id, elen; if (end - pos < 4) return; info_id = WPA_GET_LE16(pos); pos += 2; elen = WPA_GET_LE16(pos); pos += 2; if (elen > end - pos) { wpa_printf(MSG_DEBUG, "ANQP: Invalid Query Request"); return; } switch (info_id) { case ANQP_QUERY_LIST: rx_anqp_query_list(hapd, pos, pos + elen, &qi); break; #ifdef CONFIG_HS20 case ANQP_VENDOR_SPECIFIC: rx_anqp_vendor_specific(hapd, pos, pos + elen, &qi); break; #endif /* CONFIG_HS20 */ default: wpa_printf(MSG_DEBUG, "ANQP: Unsupported Query " "Request element %u", info_id); break; } pos += elen; } gas_serv_req_local_processing(hapd, sa, dialog_token, &qi, prot, std_addr3); }