diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ap/ap_config.c | 1 | ||||
-rw-r--r-- | src/ap/ap_config.h | 1 | ||||
-rw-r--r-- | src/ap/ap_drv_ops.c | 5 | ||||
-rw-r--r-- | src/ap/beacon.c | 2 | ||||
-rw-r--r-- | src/ap/drv_callbacks.c | 11 | ||||
-rw-r--r-- | src/ap/ieee802_11.c | 8 | ||||
-rw-r--r-- | src/ap/ieee802_11.h | 2 | ||||
-rw-r--r-- | src/ap/ieee802_11_vht.c | 113 | ||||
-rw-r--r-- | src/eap_peer/eap_proxy_qmi.c | 22 | ||||
-rw-r--r-- | src/p2p/p2p.c | 2 | ||||
-rw-r--r-- | src/utils/common.c | 23 | ||||
-rw-r--r-- | src/utils/common.h | 2 | ||||
-rw-r--r-- | src/wps/wps_attr_process.c | 10 |
13 files changed, 193 insertions, 9 deletions
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; } |