Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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);
	}
}
Ejemplo n.º 5
0
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(&params, 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, &params) < 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);
}
Ejemplo n.º 6
0
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);
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
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);
}
Ejemplo n.º 10
0
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);
}
Ejemplo n.º 11
0
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);
}
Ejemplo n.º 12
0
#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));
Ejemplo n.º 13
0
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));
}
Ejemplo n.º 14
0
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;
}
Ejemplo n.º 15
0
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;
}
Ejemplo n.º 17
0
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;
}
Ejemplo n.º 19
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;
}
Ejemplo n.º 20
0
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 */
}
Ejemplo n.º 21
0
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;
}
Ejemplo n.º 22
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;
}
Ejemplo n.º 23
0
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++;
	}
}
Ejemplo n.º 24
0
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);
	}
}
Ejemplo n.º 25
0
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");
}
Ejemplo n.º 26
0
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;
}
Ejemplo n.º 27
0
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(&params, 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, &params))
		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);
}
Ejemplo n.º 28
0
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;
}
Ejemplo n.º 29
0
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;
}
Ejemplo n.º 30
0
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);
}