aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Kondik <steve@cyngn.com>2016-08-15 02:06:33 -0700
committerSteve Kondik <steve@cyngn.com>2016-08-15 02:06:33 -0700
commitdc6ca4340a7ad6005a2e13b66bb2995e8010aa82 (patch)
treea10cfe90c813fea4f55682d918759aa5e2c54aab
parenta08fd9e9b66b23ceb7f14aaba3150e2146393b37 (diff)
parentdff13b397b9dc3a1bb9120c2c3fcc8793cdb97b9 (diff)
downloadandroid_external_wpa_supplicant_8-dc6ca4340a7ad6005a2e13b66bb2995e8010aa82.tar.gz
android_external_wpa_supplicant_8-dc6ca4340a7ad6005a2e13b66bb2995e8010aa82.tar.bz2
android_external_wpa_supplicant_8-dc6ca4340a7ad6005a2e13b66bb2995e8010aa82.zip
Merge branch 'wlan-service.lnx.1.0-rel.1.0' of git://codeaurora.org/platform/external/wpa_supplicant_8 into cm-13.0replicant-6.0-0002replicant-6.0-0001
Change-Id: I110d3aa8efe7861b7a5b0dd570bfe5b0ec88e6be
-rw-r--r--hostapd/config_file.c30
-rw-r--r--hostapd/hostapd.conf7
-rw-r--r--src/ap/ap_config.c1
-rw-r--r--src/ap/ap_config.h1
-rw-r--r--src/ap/ap_drv_ops.c5
-rw-r--r--src/ap/beacon.c2
-rw-r--r--src/ap/drv_callbacks.c11
-rw-r--r--src/ap/ieee802_11.c8
-rw-r--r--src/ap/ieee802_11.h2
-rw-r--r--src/ap/ieee802_11_vht.c113
-rw-r--r--src/eap_peer/eap_proxy_qmi.c22
-rw-r--r--src/p2p/p2p.c2
-rw-r--r--src/utils/common.c23
-rw-r--r--src/utils/common.h2
-rw-r--r--src/wps/wps_attr_process.c10
-rw-r--r--wpa_supplicant/config.c30
16 files changed, 255 insertions, 14 deletions
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 5540059d..14ddad7f 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -3295,6 +3295,36 @@ static int hostapd_config_fill(struct hostapd_config *conf,
wpabuf_free(bss->vendor_elements);
bss->vendor_elements = elems;
+ } else if (os_strcmp(buf, "assocresp_elements") == 0) {
+ struct wpabuf *elems;
+ size_t len = os_strlen(pos);
+ if (len & 0x01) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid assocresp_elements '%s'",
+ line, pos);
+ return 1;
+ }
+ len /= 2;
+ if (len == 0) {
+ wpabuf_free(bss->assocresp_elements);
+ bss->assocresp_elements = NULL;
+ return 0;
+ }
+
+ elems = wpabuf_alloc(len);
+ if (elems == NULL)
+ return 1;
+
+ if (hexstr2bin(pos, wpabuf_put(elems, len), len)) {
+ wpabuf_free(elems);
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid assocresp_elements '%s'",
+ line, pos);
+ return 1;
+ }
+
+ wpabuf_free(bss->assocresp_elements);
+ bss->assocresp_elements = elems;
} else if (os_strcmp(buf, "sae_anti_clogging_threshold") == 0) {
bss->sae_anti_clogging_threshold = atoi(pos);
} else if (os_strcmp(buf, "sae_groups") == 0) {
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index c9c4d7e3..9aa49f55 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -274,6 +274,13 @@ ignore_broadcast_ssid=0
# one or more elements)
#vendor_elements=dd0411223301
+# Additional vendor specific elements for (Re)Association Response frames
+# This parameter can be used to add additional vendor specific element(s) into
+# the end of the (Re)Association Response frames. The format for these
+# element(s) is a hexdump of the raw information elements (id+len+payload for
+# one or more elements)
+#assocresp_elements=dd0411223301
+
# TX queue parameters (EDCF / bursting)
# tx_queue_<queue name>_<param>
# queues: data0, data1, data2, data3, after_beacon, beacon
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 455013aa..3e396945 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -554,6 +554,7 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
#endif /* CONFIG_HS20 */
wpabuf_free(conf->vendor_elements);
+ wpabuf_free(conf->assocresp_elements);
os_free(conf->sae_groups);
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 71fc06e4..254f4bca 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -535,6 +535,7 @@ struct hostapd_bss_config {
#endif /* CONFIG_RADIUS_TEST */
struct wpabuf *vendor_elements;
+ struct wpabuf *assocresp_elements;
unsigned int sae_anti_clogging_threshold;
int *sae_groups;
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index 6cafcb74..b9029bb7 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -207,6 +207,11 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
if (wpabuf_resize(&proberesp, add) == 0)
wpabuf_put_buf(proberesp, hapd->conf->vendor_elements);
}
+ if (hapd->conf->assocresp_elements) {
+ size_t add = wpabuf_len(hapd->conf->assocresp_elements);
+ if (wpabuf_resize(&assocresp, add) == 0)
+ wpabuf_put_buf(assocresp, hapd->conf->assocresp_elements);
+ }
*beacon_ret = beacon;
*proberesp_ret = proberesp;
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 54d0d6f4..c319372b 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -466,6 +466,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
pos = hostapd_eid_vht_capabilities(hapd, pos);
pos = hostapd_eid_vht_operation(hapd, pos);
+ pos = hostapd_eid_txpower_envelope(hapd, pos);
}
if (hapd->conf->vendor_vht)
pos = hostapd_eid_vendor_vht(hapd, pos);
@@ -925,6 +926,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
tailpos = hostapd_eid_vht_capabilities(hapd, tailpos);
tailpos = hostapd_eid_vht_operation(hapd, tailpos);
+ tailpos = hostapd_eid_txpower_envelope(hapd, tailpos);
}
if (hapd->conf->vendor_vht)
tailpos = hostapd_eid_vendor_vht(hapd, tailpos);
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index fbbfe12c..cc664d78 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -115,8 +115,15 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
}
sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
- res = hostapd_check_acl(hapd, addr, NULL);
- if (res != HOSTAPD_ACL_ACCEPT) {
+ /*
+ * ACL configurations to the drivers (implementing AP SME and ACL
+ * offload) without hostapd's knowledge, can result in a disconnection
+ * though the driver accepts the connection. Skip the hostapd check for
+ * ACL if the driver supports ACL offload to avoid potentially
+ * conflicting ACL rules.
+ */
+ if (hapd->iface->drv_max_acl_mac_addrs == 0 &&
+ hostapd_check_acl(hapd, addr, NULL) != HOSTAPD_ACL_ACCEPT) {
wpa_printf(MSG_INFO, "STA " MACSTR " not allowed to connect",
MAC2STR(addr));
reason = WLAN_REASON_UNSPECIFIED;
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 288852db..0176c442 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -1690,6 +1690,14 @@ static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
p = hostapd_eid_p2p_manage(hapd, p);
#endif /* CONFIG_P2P_MANAGER */
+ if (hapd->conf->assocresp_elements &&
+ (size_t) (buf + sizeof(buf) - p) >=
+ wpabuf_len(hapd->conf->assocresp_elements)) {
+ os_memcpy(p, wpabuf_head(hapd->conf->assocresp_elements),
+ wpabuf_len(hapd->conf->assocresp_elements));
+ p += wpabuf_len(hapd->conf->assocresp_elements);
+ }
+
send_len += p - reply->u.assoc_resp.variable;
if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0)
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index 44c1bff3..6f505409 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -52,6 +52,8 @@ u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid);
+
int hostapd_ht_operation_update(struct hostapd_iface *iface);
void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
const u8 *addr, const u8 *trans_id);
diff --git a/src/ap/ieee802_11_vht.c b/src/ap/ieee802_11_vht.c
index 5bf1b5d7..d31ab730 100644
--- a/src/ap/ieee802_11_vht.c
+++ b/src/ap/ieee802_11_vht.c
@@ -17,6 +17,7 @@
#include "sta_info.h"
#include "beacon.h"
#include "ieee802_11.h"
+#include "dfs.h"
u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid)
@@ -131,6 +132,118 @@ static int check_valid_vht_mcs(struct hostapd_hw_modes *mode,
}
+u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid)
+{
+ struct hostapd_iface *iface = hapd->iface;
+ struct hostapd_config *iconf = iface->conf;
+ struct hostapd_hw_modes *mode = iface->current_mode;
+ struct hostapd_channel_data *chan;
+ int dfs, i;
+ u8 channel, tx_pwr_count, local_pwr_constraint;
+ int max_tx_power;
+ u8 tx_pwr;
+
+ if (!mode)
+ return eid;
+
+ if (ieee80211_freq_to_chan(iface->freq, &channel) == NUM_HOSTAPD_MODES)
+ return eid;
+
+ for (i = 0; i < mode->num_channels; i++) {
+ if (mode->channels[i].freq == iface->freq)
+ break;
+ }
+ if (i == mode->num_channels)
+ return eid;
+
+ switch (iface->conf->vht_oper_chwidth) {
+ case VHT_CHANWIDTH_USE_HT:
+ if (iconf->secondary_channel == 0) {
+ /* Max Transmit Power count = 0 (20 MHz) */
+ tx_pwr_count = 0;
+ } else {
+ /* Max Transmit Power count = 1 (20, 40 MHz) */
+ tx_pwr_count = 1;
+ }
+ break;
+ case VHT_CHANWIDTH_80MHZ:
+ /* Max Transmit Power count = 2 (20, 40, and 80 MHz) */
+ tx_pwr_count = 2;
+ break;
+ case VHT_CHANWIDTH_80P80MHZ:
+ case VHT_CHANWIDTH_160MHZ:
+ /* Max Transmit Power count = 3 (20, 40, 80, 160/80+80 MHz) */
+ tx_pwr_count = 3;
+ break;
+ default:
+ return eid;
+ }
+
+ /*
+ * Below local_pwr_constraint logic is referred from
+ * hostapd_eid_pwr_constraint.
+ *
+ * Check if DFS is required by regulatory.
+ */
+ dfs = hostapd_is_dfs_required(hapd->iface);
+ if (dfs < 0)
+ dfs = 0;
+
+ /*
+ * In order to meet regulations when TPC is not implemented using
+ * a transmit power that is below the legal maximum (including any
+ * mitigation factor) should help. In this case, indicate 3 dB below
+ * maximum allowed transmit power.
+ */
+ if (hapd->iconf->local_pwr_constraint == -1)
+ local_pwr_constraint = (dfs == 0) ? 0 : 3;
+ else
+ local_pwr_constraint = hapd->iconf->local_pwr_constraint;
+
+ /*
+ * A STA that is not an AP shall use a transmit power less than or
+ * equal to the local maximum transmit power level for the channel.
+ * The local maximum transmit power can be calculated from the formula:
+ * local max TX pwr = max TX pwr - local pwr constraint
+ * Where max TX pwr is maximum transmit power level specified for
+ * channel in Country element and local pwr constraint is specified
+ * for channel in this Power Constraint element.
+ */
+ chan = &mode->channels[i];
+ max_tx_power = chan->max_tx_power - local_pwr_constraint;
+
+ /*
+ * Local Maximum Transmit power is encoded as two's complement
+ * with a 0.5 dB step.
+ */
+ max_tx_power *= 2; /* in 0.5 dB steps */
+ if (max_tx_power > 127) {
+ /* 63.5 has special meaning of 63.5 dBm or higher */
+ max_tx_power = 127;
+ }
+ if (max_tx_power < -128)
+ max_tx_power = -128;
+ if (max_tx_power < 0)
+ tx_pwr = 0x80 + max_tx_power + 128;
+ else
+ tx_pwr = max_tx_power;
+
+ *eid++ = WLAN_EID_VHT_TRANSMIT_POWER_ENVELOPE;
+ *eid++ = 2 + tx_pwr_count;
+
+ /*
+ * Max Transmit Power count and
+ * Max Transmit Power units = 0 (EIRP)
+ */
+ *eid++ = tx_pwr_count;
+
+ for (i = 0; i <= tx_pwr_count; i++)
+ *eid++ = tx_pwr;
+
+ return eid;
+}
+
+
u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *vht_capab)
{
diff --git a/src/eap_peer/eap_proxy_qmi.c b/src/eap_peer/eap_proxy_qmi.c
index 60710306..fc469e64 100644
--- a/src/eap_peer/eap_proxy_qmi.c
+++ b/src/eap_peer/eap_proxy_qmi.c
@@ -716,6 +716,20 @@ int eap_auth_end_eap_session(qmi_client_type qmi_auth_svc_client_ptr)
return 0;
}
+static void eap_proxy_schedule_thread(void *eloop_ctx, void *timeout_ctx)
+{
+ struct eap_proxy_sm *eap_proxy = eloop_ctx;
+ pthread_attr_t attr;
+ int ret = -1;
+
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ ret = pthread_create(&eap_proxy->thread_id, &attr, eap_proxy_post_init, eap_proxy);
+ if(ret < 0)
+ wpa_printf(MSG_ERROR, "eap_proxy: starting thread is failed %d\n", ret);
+}
+
+
struct eap_proxy_sm *
eap_proxy_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb,
void *msg_ctx)
@@ -724,8 +738,6 @@ eap_proxy_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb,
int qmiRetCode;
struct eap_proxy_sm *eap_proxy;
qmi_idl_service_object_type qmi_client_service_obj;
- pthread_attr_t attr;
- int ret = -1;
eap_proxy = os_malloc(sizeof(struct eap_proxy_sm));
if (NULL == eap_proxy) {
@@ -751,11 +763,7 @@ eap_proxy_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb,
* parent process that created the qmi client context.
*/
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- ret = pthread_create(&eap_proxy->thread_id, &attr, eap_proxy_post_init, eap_proxy);
- if(ret < 0)
- wpa_printf(MSG_ERROR, "eap_proxy: starting thread is failed %d\n", ret);
+ eloop_register_timeout(0, 0, eap_proxy_schedule_thread, eap_proxy, NULL);
return eap_proxy;
}
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 5da8ab38..8c553024 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -3706,6 +3706,8 @@ void p2p_send_action_cb(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
break;
case P2P_PENDING_INVITATION_RESPONSE:
p2p_invitation_resp_cb(p2p, success);
+ if (p2p->inv_status != P2P_SC_SUCCESS)
+ p2p_check_after_scan_tx_continuation(p2p);
break;
case P2P_PENDING_DEV_DISC_REQUEST:
p2p_dev_disc_req_cb(p2p, success);
diff --git a/src/utils/common.c b/src/utils/common.c
index 5cf0d571..e77b7db5 100644
--- a/src/utils/common.c
+++ b/src/utils/common.c
@@ -697,6 +697,29 @@ int is_hex(const u8 *data, size_t len)
}
+int has_ctrl_char(const u8 *data, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ if (data[i] < 32 || data[i] == 127)
+ return 1;
+ }
+ return 0;
+}
+
+
+int has_newline(const char *str)
+{
+ while (*str) {
+ if (*str == '\n' || *str == '\r')
+ return 1;
+ str++;
+ }
+ return 0;
+}
+
+
size_t merge_byte_arrays(u8 *res, size_t res_len,
const u8 *src1, size_t src1_len,
const u8 *src2, size_t src2_len)
diff --git a/src/utils/common.h b/src/utils/common.h
index fb9b5b9a..7dbb24a6 100644
--- a/src/utils/common.h
+++ b/src/utils/common.h
@@ -503,6 +503,8 @@ const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len);
char * wpa_config_parse_string(const char *value, size_t *len);
int is_hex(const u8 *data, size_t len);
+int has_ctrl_char(const u8 *data, size_t len);
+int has_newline(const char *str);
size_t merge_byte_arrays(u8 *res, size_t res_len,
const u8 *src1, size_t src1_len,
const u8 *src2, size_t src2_len);
diff --git a/src/wps/wps_attr_process.c b/src/wps/wps_attr_process.c
index eadb22fe..e8c45793 100644
--- a/src/wps/wps_attr_process.c
+++ b/src/wps/wps_attr_process.c
@@ -229,6 +229,16 @@ static int wps_workaround_cred_key(struct wps_credential *cred)
cred->key_len--;
#endif /* CONFIG_WPS_STRICT */
}
+
+
+ if (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK) &&
+ (cred->key_len < 8 || has_ctrl_char(cred->key, cred->key_len))) {
+ wpa_printf(MSG_INFO, "WPS: Reject credential with invalid WPA/WPA2-Personal passphrase");
+ wpa_hexdump_ascii_key(MSG_INFO, "WPS: Network Key",
+ cred->key, cred->key_len);
+ return -1;
+ }
+
return 0;
}
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 63256740..3455fc0e 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -456,6 +456,12 @@ static int wpa_config_parse_psk(const struct parse_data *data,
}
wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",
(u8 *) value, len);
+ if (has_ctrl_char((u8 *) value, len)) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid passphrase character",
+ line);
+ return -1;
+ }
if (ssid->passphrase && os_strlen(ssid->passphrase) == len &&
os_memcmp(ssid->passphrase, value, len) == 0)
return 0;
@@ -2609,14 +2615,15 @@ char * wpa_config_get(struct wpa_ssid *ssid, const char *var)
const struct parse_data *field = &ssid_fields[i];
if (os_strcmp(var, field->name) == 0) {
char *ret = field->writer(field, ssid);
- if (ret != NULL && (os_strchr(ret, '\r') != NULL ||
- os_strchr(ret, '\n') != NULL)) {
+
+ if (ret && has_newline(ret)) {
wpa_printf(MSG_ERROR,
- "Found newline in value for %s; "
- "not returning it", var);
+ "Found newline in value for %s; not returning it",
+ var);
os_free(ret);
ret = NULL;
}
+
return ret;
}
}
@@ -2803,6 +2810,8 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
if (os_strcmp(var, "password") == 0 &&
os_strncmp(value, "ext:", 4) == 0) {
+ if (has_newline(value))
+ return -1;
str_clear_free(cred->password);
cred->password = os_strdup(value);
cred->ext_password = 1;
@@ -2853,9 +2862,14 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
}
val = wpa_config_parse_string(value, &len);
- if (val == NULL) {
+ if (val == NULL ||
+ (os_strcmp(var, "excluded_ssid") != 0 &&
+ os_strcmp(var, "roaming_consortium") != 0 &&
+ os_strcmp(var, "required_roaming_consortium") != 0 &&
+ has_newline(val))) {
wpa_printf(MSG_ERROR, "Line %d: invalid field '%s' string "
"value '%s'.", line, var, value);
+ os_free(val);
return -1;
}
@@ -3656,6 +3670,12 @@ static int wpa_global_config_parse_str(const struct global_parse_data *data,
return -1;
}
+ if (has_newline(pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid %s value with newline",
+ line, data->name);
+ return -1;
+ }
+
tmp = os_strdup(pos);
if (tmp == NULL)
return -1;