Commit f8623283 authored by Dmitry Shmidt's avatar Dmitry Shmidt
Browse files

Accumulative patch from commit b618a469c42120e984ab1c85ed6058504d1fca78


  Author: Jouni Malinen <jouni@qca.qualcomm.com>
  Date:   Sat Feb 16 19:54:09 2013 +0200
    Interworking: Select highest priority cred if multiple matches

Interworking: Select highest priority cred if multiple matches
GAS server: Fix a regression in GAS server callback
hostapd: Fix Max SP Length derivation from QoS Info
nl80211: Configure STA Capabilities and Extended Capabilities
Synchronize with wireless-testing.git include/uapi/linux/nl80211.h
WPS: Fix build without CONFIG_WPS_NFC
WPS: Add support for NFC handover select generation with wpa_supplicant
WPS: Update NFC connection handover documentation
WPS: Add support for config token generation with wpa_supplicant
WPS: Allow password token to be written with nfcpy
WPS: Use pre-configured NFC password token instead of overriding it
TDLS: Pass peer's Capability and Ext Capability info during sta_add
TDLS: Pass peer's HT Capability and QOS information during sta_add
nl80211: Add debug prints for STA add/set operations
TDLS: Fix add/set STA operation
Synchronize with wireless-testing.git include/uapi/linux/nl80211.h
WPS: Allow Device Password to be changed from M1 to M2
WPS: Fix wps_reg nfc-pw option
TDLS: Tear down peers when disconnecting from the AP
P2P: Do not use old scan result data for peer discovery
Use more accurate timestamps for scan results
P2P: Postpone P2P-DEVICE-FOUND if config_methods not known
P2P: Do not allow peer update to clear config_methods
WPS: Report NFC connection handover completion differently
P2P: Avoid concurrent scans during all steps of group formation
P2P: Cancel group formation timeout on group removal (on client)
WPS: Change listen time to match nfcpy default (250 ms)
WPS: Report only the carrier record from NFC to wpa_supplicant
WPS: Fetch only the carrier record from wpa_supplicant for NFC
WPS: Update nfcpy script to support AP mode NFC connection handover
WPS: Add command for fetching carrier record for NFC handover
WPS: Clean up debug prints with nfcpy
WPS: Remove 0.5 sec extra wait from NFC handover with nfcpy
WPS: Use alternating poll/listen for NFC peer discovery with nfcpy
WPS: Configure logging to show nfcpy log message
WPS: Add an example python script for NFC operations with hostapd
hostapd: Do not change HT40 capability due to OBSS scan
dbus: Add missing signal description for WPS (7)
EAP peer: Add Session-Id derivation to more EAP methods
EAP peer: Add Session-Id derivation
EAP-IKEV2 server: Fix invalid memory freeing operation
eap_proxy: Add a dummy implementation for compilation testing
eap_proxy: Add mechanism for allowing EAP methods to be offloaded
Android: Allow setgroups to be overridden from build configuration
P2P: Send p2p_stop_find event on failure to start pending p2p_find
P2P: Fix GO Probe Response IEs when Wi-Fi Display is enabled
Capability matching for 60 GHz band
nl80211: Add ctrl_iface message for AP mode connection rejection
P2P: Allow local configuration to use 5 GHz band 40 MHz channels
Fix BSS RANGE command for no exact id match cases

Change-Id: Iac9284bba31db40911aecc3adf2843c9b1576db1
Signed-off-by: default avatarDmitry Shmidt <dimitrysh@google.com>
parent 1e1c48d2
......@@ -990,7 +990,7 @@ static int ikev2_build_kei(struct ikev2_initiator_data *data,
*/
wpabuf_put(msg, data->dh->prime_len - wpabuf_len(pv));
wpabuf_put_buf(msg, pv);
os_free(pv);
wpabuf_free(pv);
plen = (u8 *) wpabuf_put(msg, 0) - (u8 *) phdr;
WPA_PUT_BE16(phdr->payload_length, plen);
......
......@@ -16,6 +16,7 @@
#include "crypto/md5.h"
#include "common/eapol_common.h"
#include "eap_peer/eap.h"
#include "eap_peer/eap_proxy.h"
#include "eapol_supp_sm.h"
#define STATE_MACHINE_DATA struct eapol_sm
......@@ -136,6 +137,10 @@ struct eapol_sm {
Boolean cached_pmk;
Boolean unicast_key_received, broadcast_key_received;
#ifdef CONFIG_EAP_PROXY
Boolean use_eap_proxy;
struct eap_proxy_sm *eap_proxy;
#endif /* CONFIG_EAP_PROXY */
};
......@@ -463,6 +468,17 @@ SM_STATE(SUPP_BE, SUCCESS)
sm->keyRun = TRUE;
sm->suppSuccess = TRUE;
#ifdef CONFIG_EAP_PROXY
if (sm->use_eap_proxy) {
if (eap_proxy_key_available(sm->eap_proxy)) {
/* New key received - clear IEEE 802.1X EAPOL-Key replay
* counter */
sm->replay_counter_valid = FALSE;
}
return;
}
#endif /* CONFIG_EAP_PROXY */
if (eap_key_available(sm->eap)) {
/* New key received - clear IEEE 802.1X EAPOL-Key replay
* counter */
......@@ -806,6 +822,19 @@ static void eapol_sm_txSuppRsp(struct eapol_sm *sm)
struct wpabuf *resp;
wpa_printf(MSG_DEBUG, "EAPOL: txSuppRsp");
#ifdef CONFIG_EAP_PROXY
if (sm->use_eap_proxy) {
/* Get EAP Response from EAP Proxy */
resp = eap_proxy_get_eapRespData(sm->eap_proxy);
if (resp == NULL) {
wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP Proxy "
"response data not available");
return;
}
} else
#endif /* CONFIG_EAP_PROXY */
resp = eap_get_eapRespData(sm->eap);
if (resp == NULL) {
wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP response data "
......@@ -883,6 +912,13 @@ void eapol_sm_step(struct eapol_sm *sm)
SM_STEP_RUN(SUPP_PAE);
SM_STEP_RUN(KEY_RX);
SM_STEP_RUN(SUPP_BE);
#ifdef CONFIG_EAP_PROXY
if (sm->use_eap_proxy) {
/* Drive the EAP proxy state machine */
if (eap_proxy_sm_step(sm->eap_proxy, sm->eap))
sm->changed = TRUE;
} else
#endif /* CONFIG_EAP_PROXY */
if (eap_peer_sm_step(sm->eap))
sm->changed = TRUE;
if (!sm->changed)
......@@ -1070,6 +1106,13 @@ int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen,
len += ret;
}
#ifdef CONFIG_EAP_PROXY
if (sm->use_eap_proxy)
len += eap_proxy_sm_get_status(sm->eap_proxy,
buf + len, buflen - len,
verbose);
else
#endif /* CONFIG_EAP_PROXY */
len += eap_sm_get_status(sm->eap, buf + len, buflen - len, verbose);
return len;
......@@ -1227,6 +1270,16 @@ int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf,
wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet "
"frame");
sm->eapolEap = TRUE;
#ifdef CONFIG_EAP_PROXY
if (sm->use_eap_proxy) {
eap_proxy_packet_update(
sm->eap_proxy,
wpabuf_mhead_u8(sm->eapReqData),
wpabuf_len(sm->eapReqData));
wpa_printf(MSG_DEBUG, "EAPOL: eap_proxy "
"EAP Req updated");
}
#endif /* CONFIG_EAP_PROXY */
eapol_sm_step(sm);
}
break;
......@@ -1387,6 +1440,9 @@ void eapol_sm_notify_config(struct eapol_sm *sm,
return;
sm->config = config;
#ifdef CONFIG_EAP_PROXY
sm->use_eap_proxy = eap_proxy_notify_config(sm->eap_proxy, config) > 0;
#endif /* CONFIG_EAP_PROXY */
if (conf == NULL)
return;
......@@ -1395,6 +1451,12 @@ void eapol_sm_notify_config(struct eapol_sm *sm,
sm->conf.required_keys = conf->required_keys;
sm->conf.fast_reauth = conf->fast_reauth;
sm->conf.workaround = conf->workaround;
#ifdef CONFIG_EAP_PROXY
if (sm->use_eap_proxy) {
/* Using EAP Proxy, so skip EAP state machine update */
return;
}
#endif /* CONFIG_EAP_PROXY */
if (sm->eap) {
eap_set_fast_reauth(sm->eap, conf->fast_reauth);
eap_set_workaround(sm->eap, conf->workaround);
......@@ -1419,6 +1481,22 @@ int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len)
const u8 *eap_key;
size_t eap_len;
#ifdef CONFIG_EAP_PROXY
if (sm->use_eap_proxy) {
/* Get key from EAP proxy */
if (sm == NULL || !eap_proxy_key_available(sm->eap_proxy)) {
wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");
return -1;
}
eap_key = eap_proxy_get_eapKeyData(sm->eap_proxy, &eap_len);
if (eap_key == NULL) {
wpa_printf(MSG_DEBUG, "EAPOL: Failed to get "
"eapKeyData");
return -1;
}
goto key_fetched;
}
#endif /* CONFIG_EAP_PROXY */
if (sm == NULL || !eap_key_available(sm->eap)) {
wpa_printf(MSG_DEBUG, "EAPOL: EAP key not available");
return -1;
......@@ -1428,6 +1506,9 @@ int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len)
wpa_printf(MSG_DEBUG, "EAPOL: Failed to get eapKeyData");
return -1;
}
#ifdef CONFIG_EAP_PROXY
key_fetched:
#endif /* CONFIG_EAP_PROXY */
if (len > eap_len) {
wpa_printf(MSG_DEBUG, "EAPOL: Requested key length (%lu) not "
"available (len=%lu)",
......@@ -1889,6 +1970,14 @@ struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx)
return NULL;
}
#ifdef CONFIG_EAP_PROXY
sm->use_eap_proxy = FALSE;
sm->eap_proxy = eap_proxy_init(sm, &eapol_cb, sm->ctx->msg_ctx);
if (sm->eap_proxy == NULL) {
wpa_printf(MSG_ERROR, "Unable to initialize EAP Proxy");
}
#endif /* CONFIG_EAP_PROXY */
/* Initialize EAPOL state machines */
sm->initialize = TRUE;
eapol_sm_step(sm);
......@@ -1915,6 +2004,9 @@ void eapol_sm_deinit(struct eapol_sm *sm)
eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm);
eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm);
eap_peer_sm_deinit(sm->eap);
#ifdef CONFIG_EAP_PROXY
eap_proxy_deinit(sm->eap_proxy);
#endif /* CONFIG_EAP_PROXY */
os_free(sm->last_rx_key);
wpabuf_free(sm->eapReqData);
os_free(sm->ctx);
......
......@@ -617,8 +617,18 @@ static void p2p_copy_wps_info(struct p2p_device *dev, int probe_req,
}
if (!probe_req) {
dev->info.config_methods = msg->config_methods ?
u16 new_config_methods;
new_config_methods = msg->config_methods ?
msg->config_methods : msg->wps_config_methods;
if (new_config_methods &&
dev->info.config_methods != new_config_methods) {
wpa_printf(MSG_DEBUG, "P2P: Update peer " MACSTR
" config_methods 0x%x -> 0x%x",
MAC2STR(dev->info.p2p_device_addr),
dev->info.config_methods,
new_config_methods);
dev->info.config_methods = new_config_methods;
}
}
}
......@@ -630,7 +640,7 @@ static void p2p_copy_wps_info(struct p2p_device *dev, int probe_req,
* P2P Device Address or P2P Interface Address)
* @level: Signal level (signal strength of the received frame from the peer)
* @freq: Frequency on which the Beacon or Probe Response frame was received
* @age_ms: Age of the information in milliseconds
* @rx_time: Time when the result was received
* @ies: IEs from the Beacon or Probe Response frame
* @ies_len: Length of ies buffer in octets
* @scan_res: Whether this was based on scan results
......@@ -642,14 +652,14 @@ static void p2p_copy_wps_info(struct p2p_device *dev, int probe_req,
* Info attributes.
*/
int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq,
unsigned int age_ms, int level, const u8 *ies,
struct os_time *rx_time, int level, const u8 *ies,
size_t ies_len, int scan_res)
{
struct p2p_device *dev;
struct p2p_message msg;
const u8 *p2p_dev_addr;
int i;
struct os_time time_now, time_tmp_age, entry_ts;
struct os_time time_now;
os_memset(&msg, 0, sizeof(msg));
if (p2p_parse_ies(ies, ies_len, &msg)) {
......@@ -686,22 +696,29 @@ int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq,
return -1;
}
os_get_time(&time_now);
time_tmp_age.sec = age_ms / 1000;
time_tmp_age.usec = (age_ms % 1000) * 1000;
os_time_sub(&time_now, &time_tmp_age, &entry_ts);
if (rx_time == NULL) {
os_get_time(&time_now);
rx_time = &time_now;
}
/*
* Update the device entry only if the new peer
* entry is newer than the one previously stored.
*/
if (dev->last_seen.usec > 0 &&
os_time_before(&entry_ts, &dev->last_seen)) {
if (dev->last_seen.sec > 0 &&
os_time_before(rx_time, &dev->last_seen)) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Do not update peer "
"entry based on old frame (rx_time=%u.%06u "
"last_seen=%u.%06u)",
(unsigned int) rx_time->sec,
(unsigned int) rx_time->usec,
(unsigned int) dev->last_seen.sec,
(unsigned int) dev->last_seen.usec);
p2p_parse_free(&msg);
return -1;
}
os_memcpy(&dev->last_seen, &entry_ts, sizeof(struct os_time));
os_memcpy(&dev->last_seen, rx_time, sizeof(struct os_time));
dev->flags &= ~(P2P_DEV_PROBE_REQ_ONLY | P2P_DEV_GROUP_CLIENT_ONLY);
......@@ -780,13 +797,37 @@ int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq,
return 0;
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
"P2P: Peer found with Listen frequency %d MHz", freq);
"P2P: Peer found with Listen frequency %d MHz "
"(rx_time=%u.%06u)", freq, (unsigned int) rx_time->sec,
(unsigned int) rx_time->usec);
if (dev->flags & P2P_DEV_USER_REJECTED) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
"P2P: Do not report rejected device");
return 0;
}
if (dev->info.config_methods == 0 &&
(freq == 2412 || freq == 2437 || freq == 2462)) {
/*
* If we have only seen a Beacon frame from a GO, we do not yet
* know what WPS config methods it supports. Since some
* applications use config_methods value from P2P-DEVICE-FOUND
* events, postpone reporting this peer until we've fully
* discovered its capabilities.
*
* At least for now, do this only if the peer was detected on
* one of the social channels since that peer can be easily be
* found again and there are no limitations of having to use
* passive scan on this channels, so this can be done through
* Probe Response frame that includes the config_methods
* information.
*/
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
"P2P: Do not report peer " MACSTR " with unknown "
"config methods", MAC2STR(addr));
return 0;
}
p2p->cfg->dev_found(p2p->cfg->cb_ctx, addr, &dev->info,
!(dev->flags & P2P_DEV_REPORTED_ONCE));
dev->flags |= P2P_DEV_REPORTED | P2P_DEV_REPORTED_ONCE;
......@@ -1031,6 +1072,7 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout,
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting find (type=%d)",
type);
os_get_time(&p2p->find_start);
if (p2p->p2p_scan_running) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan is "
"already running");
......@@ -1133,8 +1175,10 @@ int p2p_other_scan_completed(struct p2p_data *p2p)
"now that previous scan was completed");
if (p2p_find(p2p, p2p->last_p2p_find_timeout, p2p->find_type,
p2p->num_req_dev_types, p2p->req_dev_types,
p2p->find_dev_id, p2p->search_delay) < 0)
p2p->find_dev_id, p2p->search_delay) < 0) {
wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, P2P_EVENT_FIND_STOPPED);
return 0;
}
return 1;
}
......@@ -2887,10 +2931,25 @@ static void p2p_prov_disc_cb(struct p2p_data *p2p, int success)
int p2p_scan_res_handler(struct p2p_data *p2p, const u8 *bssid, int freq,
unsigned int age, int level, const u8 *ies,
struct os_time *rx_time, int level, const u8 *ies,
size_t ies_len)
{
p2p_add_device(p2p, bssid, freq, age, level, ies, ies_len, 1);
if (os_time_before(rx_time, &p2p->find_start)) {
/*
* The driver may have cached (e.g., in cfg80211 BSS table) the
* scan results for relatively long time. To avoid reporting
* stale information, update P2P peers only based on results
* that have based on frames received after the last p2p_find
* operation was started.
*/
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Ignore old scan "
"result for " MACSTR " (rx_time=%u.%06u)",
MAC2STR(bssid), (unsigned int) rx_time->sec,
(unsigned int) rx_time->usec);
return 0;
}
p2p_add_device(p2p, bssid, freq, rx_time, level, ies, ies_len, 1);
return 0;
}
......
......@@ -1200,7 +1200,7 @@ void p2p_rx_action(struct p2p_data *p2p, const u8 *da, const u8 *sa,
* @p2p: P2P module context from p2p_init()
* @bssid: BSSID of the scan result
* @freq: Frequency of the channel on which the device was found in MHz
* @age: Age of the scan result in milliseconds
* @rx_time: Time when the result was received
* @level: Signal level (signal strength of the received Beacon/Probe Response
* frame)
* @ies: Pointer to IEs from the scan result
......@@ -1222,7 +1222,7 @@ void p2p_rx_action(struct p2p_data *p2p, const u8 *da, const u8 *sa,
* start of a pending operation, e.g., to start a pending GO negotiation.
*/
int p2p_scan_res_handler(struct p2p_data *p2p, const u8 *bssid, int freq,
unsigned int age, int level, const u8 *ies,
struct os_time *rx_time, int level, const u8 *ies,
size_t ies_len);
/**
......
......@@ -403,6 +403,8 @@ struct p2p_data {
u8 *find_dev_id;
u8 find_dev_id_buf[ETH_ALEN];
struct os_time find_start; /* time of last p2p_find start */
struct p2p_group **groups;
size_t num_groups;
......@@ -706,7 +708,7 @@ struct p2p_device * p2p_add_dev_from_go_neg_req(struct p2p_data *p2p,
void p2p_add_dev_info(struct p2p_data *p2p, const u8 *addr,
struct p2p_device *dev, struct p2p_message *msg);
int p2p_add_device(struct p2p_data *p2p, const u8 *addr, int freq,
unsigned int age_ms, int level, const u8 *ies,
struct os_time *rx_time, int level, const u8 *ies,
size_t ies_len, int scan_res);
struct p2p_device * p2p_get_device(struct p2p_data *p2p, const u8 *addr);
struct p2p_device * p2p_get_device_interface(struct p2p_data *p2p,
......
......@@ -176,7 +176,7 @@ void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
"P2P: Invitation Request from unknown peer "
MACSTR, MAC2STR(sa));
if (p2p_add_device(p2p, sa, rx_freq, 0, 0, data + 1, len - 1,
if (p2p_add_device(p2p, sa, rx_freq, NULL, 0, data + 1, len - 1,
0)) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
"P2P: Invitation Request add device failed "
......
......@@ -152,7 +152,7 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
"P2P: Provision Discovery Request from "
"unknown peer " MACSTR, MAC2STR(sa));
if (p2p_add_device(p2p, sa, rx_freq, 0, 0, data + 1, len - 1,
if (p2p_add_device(p2p, sa, rx_freq, NULL, 0, data + 1, len - 1,
0)) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
"P2P: Provision Discovery Request add device "
......
......@@ -120,6 +120,13 @@ struct wpa_tdls_peer {
u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
size_t supp_rates_len;
struct ieee80211_ht_capabilities *ht_capabilities;
u8 qos_info;
u8 *ext_capab;
size_t ext_capab_len;
};
......@@ -611,6 +618,10 @@ static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
peer->initiator = 0;
os_free(peer->sm_tmr.buf);
peer->sm_tmr.buf = NULL;
os_free(peer->ht_capabilities);
peer->ht_capabilities = NULL;
os_free(peer->ext_capab);
peer->ext_capab = NULL;
peer->rsnie_i_len = peer->rsnie_p_len = 0;
peer->cipher = 0;
peer->tpk_set = peer->tpk_success = 0;
......@@ -681,8 +692,10 @@ int wpa_tdls_send_teardown(struct wpa_sm *sm, const u8 *addr, u16 reason_code)
pos = rbuf;
if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success) {
/* Overwrite the reason code */
reason_code = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
if (reason_code != WLAN_REASON_DEAUTH_LEAVING) {
/* Overwrite the reason code */
reason_code = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
}
goto skip_ies;
}
......@@ -1329,6 +1342,58 @@ static int copy_supp_rates(const struct wpa_eapol_ie_parse *kde,
}
static int copy_peer_ht_capab(const struct wpa_eapol_ie_parse *kde,
struct wpa_tdls_peer *peer)
{
if (!kde->ht_capabilities ||
kde->ht_capabilities_len <
sizeof(struct ieee80211_ht_capabilities) ) {
wpa_printf(MSG_DEBUG, "TDLS: No supported ht capabilities "
"received");
return 0;
}
if (!peer->ht_capabilities) {
peer->ht_capabilities =
os_zalloc(sizeof(struct ieee80211_ht_capabilities));
if (peer->ht_capabilities == NULL)
return -1;
}
os_memcpy(peer->ht_capabilities, kde->ht_capabilities,
sizeof(struct ieee80211_ht_capabilities));
wpa_hexdump(MSG_DEBUG, "TDLS: Peer HT capabilities",
(u8 *) peer->ht_capabilities,
sizeof(struct ieee80211_ht_capabilities));
return 0;
}
static int copy_peer_ext_capab(const struct wpa_eapol_ie_parse *kde,
struct wpa_tdls_peer *peer)
{
if (!kde->ext_capab) {
wpa_printf(MSG_DEBUG, "TDLS: No extended capabilities "
"received");
return 0;
}
if (!peer->ext_capab || peer->ext_capab_len < kde->ext_capab_len - 2) {
/* Need to allocate buffer to fit the new information */
os_free(peer->ext_capab);
peer->ext_capab = os_zalloc(kde->ext_capab_len - 2);
if (peer->ext_capab == NULL)
return -1;
}
peer->ext_capab_len = kde->ext_capab_len - 2;
os_memcpy(peer->ext_capab, kde->ext_capab + 2, peer->ext_capab_len);
return 0;
}
static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
const u8 *buf, size_t len)
{
......@@ -1398,6 +1463,14 @@ static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
if (copy_supp_rates(&kde, peer) < 0)
goto error;
if (copy_peer_ht_capab(&kde, peer) < 0)
goto error;
if (copy_peer_ext_capab(&kde, peer) < 0)
goto error;
peer->qos_info = kde.qosinfo;
#ifdef CONFIG_TDLS_TESTING
if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) {
peer = wpa_tdls_add_peer(sm, src_addr, NULL);
......@@ -1621,7 +1694,8 @@ skip_rsn:
skip_rsn_check:
/* add the peer to the driver as a "setup in progress" peer */
wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0);
wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0, NULL, 0,
NULL, 0);
wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2");
if (wpa_tdls_send_tpk_m2(sm, src_addr, dtoken, lnkid, peer) < 0) {
......@@ -1661,9 +1735,11 @@ static void wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
#endif /* CONFIG_TDLS_TESTING */
}
/* add supported rates and capabilities to the TDLS peer */
/* add supported rates, capabilities, and qos_info to the TDLS peer */
wpa_sm_tdls_peer_addset(sm, peer->addr, 0, peer->capability,
peer->supp_rates, peer->supp_rates_len);
peer->supp_rates, peer->supp_rates_len,
peer->ht_capabilities, peer->qos_info,
peer->ext_capab, peer->ext_capab_len);
wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr);
}
......@@ -1759,6 +1835,14 @@ static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, const u8 *src_addr,
if (copy_supp_rates(&kde, peer) < 0)
goto error;
if (copy_peer_ht_capab(&kde, peer) < 0)
goto error;
if (copy_peer_ext_capab(&kde, peer) < 0)
goto error;
peer->qos_info = kde.qosinfo;
if (!wpa_tdls_get_privacy(sm)) {
peer->rsnie_p_len = 0;
peer->cipher = WPA_CIPHER_NONE;
......@@ -2062,7 +2146,8 @@ int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr)
peer->initiator = 1;
/* add the peer to the driver as a "setup in progress" peer */
wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0);
wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0, NULL, 0,
NULL, 0);
if (wpa_tdls_send_tpk_m1(sm, peer) < 0) {
wpa_tdls_disable_link(sm, peer->addr);
......@@ -2207,6 +2292,28 @@ int wpa_tdls_init(struct wpa_sm *sm)
}
void wpa_tdls_teardown_peers(struct wpa_sm *sm)
{
struct wpa_tdls_peer *peer;
peer = sm->tdls;
wpa_printf(MSG_DEBUG, "TDLS: Tear down peers");
while (peer) {
wpa_printf(MSG_DEBUG, "TDLS: Tear down peer " MACSTR,
MAC2STR(peer->addr));
if (sm->tdls_external_setup)
wpa_tdls_send_teardown(sm, peer->addr,
WLAN_REASON_DEAUTH_LEAVING);
else
wpa_sm_tdls_oper(sm, TDLS_TEARDOWN, peer->addr);
peer = peer->next;
}
}
static void wpa_tdls_remove_peers(struct wpa_sm *sm)
{
struct wpa_tdls_peer *peer, *tmp;
......
......@@ -12,6 +12,7 @@
#include "common/defs.h"
#include "common/eapol_common.h"
#include "common/wpa_common.h"
#include "common/ieee802_11_defs.h"
struct wpa_sm;
struct eapol_sm;
......@@ -57,7 +58,10 @@ struct wpa_sm_ctx {
int (*tdls_oper)(void *ctx, int oper, const u8 *peer);
int (*tdls_peer_addset)(void *ctx, const u8 *addr, int add,
u16 capability, const u8 *supp_rates,
size_t supp_rates_len);
size_t supp_rates_len,
const struct ieee80211_ht_capabilities *ht_capab,
u8 qosinfo, const u8 *ext_capab,
size_t ext_capab_len);
#endif /* CONFIG_TDLS */
void (*set_rekey_offload)(void *ctx, const u8 *kek, const u8 *kck,
const u8 *replay_ctr);
......@@ -360,6 +364,7 @@ int wpa_tdls_send_teardown(struct wpa_sm *sm, const u8 *addr, u16 reason_code);
int wpa_tdls_teardown_link(struct wpa_sm *sm, const u8 *addr, u16 reason_code);
int wpa_tdls_send_discovery_request(struct wpa_sm *sm, const u8 *addr);
int wpa_tdls_init(struct wpa_sm *sm);
void wpa_tdls_teardown_peers(struct wpa_sm *sm);
void wpa_tdls_deinit(struct wpa_sm *sm);
void wpa_tdls_enable(struct wpa_sm *sm, int enabled);
void wpa_tdls_disable_link(struct wpa_sm *sm, const u8 *addr);
......
......@@ -283,12 +283,16 @@ static inline int wpa_sm_tdls_oper(struct wpa_sm *sm, int oper,
static inline int
wpa_sm_tdls_peer_addset(struct wpa_sm *sm, const u8 *addr, int add,
u16 capability, const u8 *supp_rates,
size_t supp_rates_len)
size_t supp_rates_len,
const struct ieee80211_ht_capabilities *ht_capab,
u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len)
{
if (sm->ctx->tdls_peer_addset)
return sm->ctx->tdls_peer_addset(sm->ctx->ctx, addr, add,
capability, supp_rates,
supp_rates_len);
supp_rates_len, ht_capab,
qosinfo, ext_capab,
ext_capab_len);
return -1;
}
#endif /* CONFIG_TDLS */
......
......@@ -427,6 +427,11 @@ int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
} else if (*pos == WLAN_EID_EXT_SUPP_RATES) {
ie->ext_supp_rates = pos;
ie->ext_supp_rates_len = pos[1] + 2;
} else if (*pos == WLAN_EID_HT_CAP) {
ie->ht_capabilities = pos + 2;
ie->ht_capabilities_len = pos[1];
} else if (*pos == WLAN_EID_QOS && pos[1] >= 1) {
ie->qosinfo = pos[2];
} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
ret = wpa_parse_generic(pos, end, ie);
if (ret < 0)
......
......@@ -49,6 +49,9 @@ struct wpa_eapol_ie_parse {
size_t supp_rates_len;
const u8 *ext_supp_rates;
size_t ext_supp_rates_len;
const u8 *ht_capabilities;
size_t ht_capabilities_len;
u8 qosinfo;
};
int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
......
......@@ -257,7 +257,11 @@ int os_program_init(void)
* We ignore errors here since errors are normal if we
* are already running as non-root.
*/
#ifdef ANDROID_SETGROUPS_OVERRIDE
gid_t groups[] = { ANDROID_SETGROUPS_OVERRIDE };
#else /* ANDROID_SETGROUPS_OVERRIDE */
gid_t groups[] = { AID_INET, AID_WIFI, AID_KEYSTORE };
#endif /* ANDROID_SETGROUPS_OVERRIDE */
struct __user_cap_header_struct header;
struct __user_cap_data_struct cap;
......
......@@ -170,10 +170,30 @@ struct wpabuf * ndef_build_wifi(const struct wpabuf *buf)
}
struct wpabuf * ndef_build_wifi_hc(int begin)
{
struct wpabuf *hc, *carrier;
carrier = wpabuf_alloc(2 + os_strlen(wifi_handover_type));
if (carrier == NULL)
return NULL;
wpabuf_put_u8(carrier, 0x02); /* Carrier Type Format */
wpabuf_put_u8(carrier, os_strlen(wifi_handover_type));
wpabuf_put_str(carrier, wifi_handover_type);
hc = ndef_build_record((begin ? FLAG_MESSAGE_BEGIN : 0) |
FLAG_MESSAGE_END | FLAG_TNF_NFC_FORUM, "Hc", 2,
"0", 1, carrier);
wpabuf_free(carrier);
return hc;
}
struct wpabuf * ndef_build_wifi_hr(void)
{
struct wpabuf *rn, *cr, *ac_payload, *ac, *hr_payload, *hr;
struct wpabuf *carrier, *hc;
struct wpabuf *hc;
rn = wpabuf_alloc(2);
if (rn == NULL)
......@@ -224,18 +244,7 @@ struct wpabuf * ndef_build_wifi_hr(void)
if (hr == NULL)
return NULL;
carrier = wpabuf_alloc(2 + os_strlen(wifi_handover_type));
if (carrier == NULL) {
wpabuf_free(hr);
return NULL;
}
wpabuf_put_u8(carrier, 0x02); /* Carrier Type Format */
wpabuf_put_u8(carrier, os_strlen(wifi_handover_type));
wpabuf_put_str(carrier, wifi_handover_type);
hc = ndef_build_record(FLAG_MESSAGE_END | FLAG_TNF_NFC_FORUM, "Hc", 2,
"0", 1, carrier);
wpabuf_free(carrier);
hc = ndef_build_wifi_hc(0);
if (hc == NULL) {
wpabuf_free(hr);
return NULL;
......
......@@ -53,12 +53,18 @@ struct wps_data * wps_init(const struct wps_config *cfg)
}
os_memcpy(data->dev_password, cfg->pin, cfg->pin_len);
data->dev_password_len = cfg->pin_len;
wpa_hexdump_key(MSG_DEBUG, "WPS: AP PIN dev_password",
data->dev_password, data->dev_password_len);
}
#ifdef CONFIG_WPS_NFC
if (cfg->wps->ap && !cfg->registrar && cfg->wps->ap_nfc_dev_pw_id) {
/* Keep AP PIN as alternative Device Password */
data->alt_dev_pw_id = data->dev_pw_id;
data->alt_dev_password = data->dev_password;
data->alt_dev_password_len = data->dev_password_len;
data->dev_pw_id = cfg->wps->ap_nfc_dev_pw_id;
os_free(data->dev_password);
data->dev_password =
os_malloc(wpabuf_len(cfg->wps->ap_nfc_dev_pw));
if (data->dev_password == NULL) {
......@@ -69,6 +75,8 @@ struct wps_data * wps_init(const struct wps_config *cfg)
wpabuf_head(cfg->wps->ap_nfc_dev_pw),
wpabuf_len(cfg->wps->ap_nfc_dev_pw));
data->dev_password_len = wpabuf_len(cfg->wps->ap_nfc_dev_pw);
wpa_hexdump_key(MSG_DEBUG, "WPS: NFC dev_password",
data->dev_password, data->dev_password_len);
}
#endif /* CONFIG_WPS_NFC */
......@@ -155,6 +163,7 @@ void wps_deinit(struct wps_data *data)
wpabuf_free(data->dh_pubkey_r);
wpabuf_free(data->last_msg);
os_free(data->dev_password);
os_free(data->alt_dev_password);
os_free(data->new_psk);
wps_device_data_free(&data->peer_dev);
os_free(data->new_ap_settings);
......
......@@ -810,6 +810,8 @@ u16 wps_config_methods_str2bin(const char *str);
struct wpabuf * wps_build_nfc_pw_token(u16 dev_pw_id,
const struct wpabuf *pubkey,
const struct wpabuf *dev_pw);
struct wpabuf * wps_nfc_token_build(int ndef, int id, struct wpabuf *pubkey,
struct wpabuf *dev_pw);
struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey,
struct wpabuf **privkey,
struct wpabuf **dev_pw);
......@@ -817,6 +819,7 @@ struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey,
/* ndef.c */
struct wpabuf * ndef_parse_wifi(const struct wpabuf *buf);
struct wpabuf * ndef_build_wifi(const struct wpabuf *buf);
struct wpabuf * ndef_build_wifi_hc(int begin);
struct wpabuf * ndef_build_wifi_hr(void);
#ifdef CONFIG_WPS_STRICT
......
......@@ -562,11 +562,34 @@ struct wpabuf * wps_build_wsc_nack(struct wps_data *wps)
#ifdef CONFIG_WPS_NFC
struct wpabuf * wps_nfc_token_build(int ndef, int id, struct wpabuf *pubkey,
struct wpabuf *dev_pw)
{
struct wpabuf *ret;
if (pubkey == NULL || dev_pw == NULL)
return NULL;
ret = wps_build_nfc_pw_token(id, pubkey, dev_pw);
if (ndef && ret) {
struct wpabuf *tmp;
tmp = ndef_build_wifi(ret);
wpabuf_free(ret);
if (tmp == NULL)
return NULL;
ret = tmp;
}
return ret;
}
struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey,
struct wpabuf **privkey,
struct wpabuf **dev_pw)
{
struct wpabuf *priv = NULL, *pub = NULL, *pw, *ret;
struct wpabuf *priv = NULL, *pub = NULL, *pw;
void *dh_ctx;
u16 val;
......@@ -596,16 +619,7 @@ struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey,
wpabuf_free(*dev_pw);
*dev_pw = pw;
ret = wps_build_nfc_pw_token(*id, *pubkey, *dev_pw);
if (ndef && ret) {
struct wpabuf *tmp;
tmp = ndef_build_wifi(ret);
wpabuf_free(ret);
if (tmp == NULL)
return NULL;
ret = tmp;
}
return ret;
return wps_nfc_token_build(ndef, *id, *pubkey, *dev_pw);
}
#endif /* CONFIG_WPS_NFC */
......@@ -837,6 +837,39 @@ static int wps_process_ap_settings_e(struct wps_data *wps,
}
static int wps_process_dev_pw_id(struct wps_data *wps, const u8 *dev_pw_id)
{
u16 id;
if (dev_pw_id == NULL) {
wpa_printf(MSG_DEBUG, "WPS: Device Password ID");
return -1;
}
id = WPA_GET_BE16(dev_pw_id);
if (wps->dev_pw_id == id) {
wpa_printf(MSG_DEBUG, "WPS: Device Password ID %u", id);
return 0;
}
wpa_printf(MSG_DEBUG, "WPS: Registrar trying to change Device Password "
"ID from %u to %u", wps->dev_pw_id, id);
if (wps->alt_dev_password && wps->alt_dev_pw_id == id) {
wpa_printf(MSG_DEBUG, "WPS: Found a matching Device Password");
os_free(wps->dev_password);
wps->dev_pw_id = wps->alt_dev_pw_id;
wps->dev_password = wps->alt_dev_password;
wps->dev_password_len = wps->alt_dev_password_len;
wps->alt_dev_password = NULL;
wps->alt_dev_password_len = 0;
return 0;
}
return -1;
}
static enum wps_process_res wps_process_m2(struct wps_data *wps,
const struct wpabuf *msg,
struct wps_parse_attr *attr)
......@@ -852,7 +885,8 @@ static enum wps_process_res wps_process_m2(struct wps_data *wps,
if (wps_process_registrar_nonce(wps, attr->registrar_nonce) ||
wps_process_enrollee_nonce(wps, attr->enrollee_nonce) ||
wps_process_uuid_r(wps, attr->uuid_r)) {
wps_process_uuid_r(wps, attr->uuid_r) ||
wps_process_dev_pw_id(wps, attr->dev_password_id)) {
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}
......
......@@ -71,6 +71,9 @@ struct wps_data {
size_t dev_password_len;
u16 dev_pw_id;
int pbc;
u8 *alt_dev_password;
size_t alt_dev_password_len;
u16 alt_dev_pw_id;
/**
* request_type - Request Type attribute from (Re)AssocReq
......
......@@ -1363,6 +1363,14 @@ static int wps_get_dev_password(struct wps_data *wps)
} else {
pin = wps_registrar_get_pin(wps->wps->registrar, wps->uuid_e,
&pin_len);
if (pin && wps->dev_pw_id >= 0x10) {
wpa_printf(MSG_DEBUG, "WPS: No match for OOB Device "
"Password ID, but PIN found");
/*
* See whether Enrollee is willing to use PIN instead.
*/
wps->dev_pw_id = DEV_PW_DEFAULT;
}
}
if (pin == NULL) {
wpa_printf(MSG_DEBUG, "WPS: No Device Password available for "
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment