mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-07-23 05:15:32 +08:00
Update to FreeBSD head 2018-09-17
Git mirror commit 6c2192b1ef8c50788c751f878552526800b1e319. Update #3472.
This commit is contained in:
parent
3becda1fef
commit
3489e3b639
@ -11,6 +11,8 @@ FREEBSD_SRC = freebsd-org
|
||||
TOOLS = freebsd-org/sys/tools
|
||||
|
||||
GENERATED =
|
||||
GENERATED += $(LOCAL_INC)/cryptodev_if.h
|
||||
GENERATED += $(LOCAL_SRC)/cryptodev_if.c
|
||||
GENERATED += $(LOCAL_INC)/usb_if.h
|
||||
GENERATED += $(LOCAL_SRC)/usb_if.c
|
||||
GENERATED += $(LOCAL_INC)/bus_if.h
|
||||
@ -62,12 +64,12 @@ YACC_GENERATED += freebsd/contrib/libpcap/grammar.c
|
||||
LEX_GENERATED += freebsd/contrib/libpcap/scanner.h
|
||||
LEX_GENERATED += freebsd/contrib/libpcap/scanner.c
|
||||
|
||||
all: yacc lex $(GENERATED)
|
||||
|
||||
yacc: $(YACC_GENERATED)
|
||||
|
||||
lex: $(LEX_GENERATED)
|
||||
|
||||
all: yacc lex $(GENERATED)
|
||||
|
||||
program-header:
|
||||
cd freebsd/bin/stty && $(BASE)/userspace-header-gen.py $(BUILD_BSP)/freebsd/bin/stty/*.o -p stty
|
||||
cd freebsd/contrib/tcpdump && $(BASE)/userspace-header-gen.py $(BUILD_BSP)/freebsd/contrib/tcpdump/*.o -p tcpdump
|
||||
@ -89,6 +91,14 @@ $(LOCAL_INC)/usbdevs_data.h: $(FREEBSD_SRC)/sys/dev/usb/usbdevs
|
||||
awk -f $(TOOLS)/usbdevs2h.awk $< -d
|
||||
mv usbdevs_data.h $@
|
||||
|
||||
$(LOCAL_INC)/cryptodev_if.h: $(FREEBSD_SRC)/sys/opencrypto/cryptodev_if.m
|
||||
awk -f $(TOOLS)/makeobjops.awk $< -h
|
||||
mv cryptodev_if.h $@
|
||||
|
||||
$(LOCAL_SRC)/cryptodev_if.c: $(FREEBSD_SRC)/sys/opencrypto/cryptodev_if.m
|
||||
awk -f $(TOOLS)/makeobjops.awk $< -c
|
||||
mv cryptodev_if.c $@
|
||||
|
||||
$(LOCAL_INC)/usb_if.h: $(FREEBSD_SRC)/sys/dev/usb/usb_if.m
|
||||
awk -f $(TOOLS)/makeobjops.awk $< -h
|
||||
mv usb_if.h $@
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit fb63610a69b0eb7f69a201ba05c4c1a7a2739cf9
|
||||
Subproject commit 6c2192b1ef8c50788c751f878552526800b1e319
|
@ -2210,6 +2210,9 @@ main(int argc, char **argv)
|
||||
#else
|
||||
cansandbox = (cansandbox && ndo->ndo_nflag);
|
||||
#endif /* HAVE_CASPER */
|
||||
cansandbox = (cansandbox && (pcap_fileno(pd) != -1 ||
|
||||
RFileName != NULL));
|
||||
|
||||
if (cansandbox && cap_enter() < 0 && errno != ENOSYS)
|
||||
error("unable to enter the capability mode");
|
||||
#endif /* HAVE_CAPSICUM */
|
||||
|
@ -10,12 +10,14 @@
|
||||
#define HOSTAPD_CONFIG_H
|
||||
|
||||
#include "common/defs.h"
|
||||
#include "utils/list.h"
|
||||
#include "ip_addr.h"
|
||||
#include "common/wpa_common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
#include "wps/wps.h"
|
||||
#include "fst/fst.h"
|
||||
#include "vlan.h"
|
||||
|
||||
/**
|
||||
* mesh_conf - local MBSS state and settings
|
||||
@ -39,6 +41,10 @@ struct mesh_conf {
|
||||
#define MESH_CONF_SEC_AUTH BIT(1)
|
||||
#define MESH_CONF_SEC_AMPE BIT(2)
|
||||
unsigned int security;
|
||||
enum mfp_options ieee80211w;
|
||||
unsigned int pairwise_cipher;
|
||||
unsigned int group_cipher;
|
||||
unsigned int mgmt_group_cipher;
|
||||
int dot11MeshMaxRetries;
|
||||
int dot11MeshRetryTimeout; /* msec */
|
||||
int dot11MeshConfirmTimeout; /* msec */
|
||||
@ -52,7 +58,7 @@ typedef u8 macaddr[ETH_ALEN];
|
||||
|
||||
struct mac_acl_entry {
|
||||
macaddr addr;
|
||||
int vlan_id;
|
||||
struct vlan_description vlan_id;
|
||||
};
|
||||
|
||||
struct hostapd_radius_servers;
|
||||
@ -102,6 +108,7 @@ struct hostapd_ssid {
|
||||
#define DYNAMIC_VLAN_NAMING_WITH_DEVICE 1
|
||||
#define DYNAMIC_VLAN_NAMING_END 2
|
||||
int vlan_naming;
|
||||
int per_sta_vif;
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
char *vlan_tagged_interface;
|
||||
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
|
||||
@ -113,6 +120,7 @@ struct hostapd_ssid {
|
||||
struct hostapd_vlan {
|
||||
struct hostapd_vlan *next;
|
||||
int vlan_id; /* VLAN ID or -1 (VLAN_ID_WILDCARD) for wildcard entry */
|
||||
struct vlan_description vlan_desc;
|
||||
char ifname[IFNAMSIZ + 1];
|
||||
int configured;
|
||||
int dynamic_vlan;
|
||||
@ -124,9 +132,14 @@ struct hostapd_vlan {
|
||||
};
|
||||
|
||||
#define PMK_LEN 32
|
||||
#define MIN_PASSPHRASE_LEN 8
|
||||
#define MAX_PASSPHRASE_LEN 63
|
||||
struct hostapd_sta_wpa_psk_short {
|
||||
struct hostapd_sta_wpa_psk_short *next;
|
||||
unsigned int is_passphrase:1;
|
||||
u8 psk[PMK_LEN];
|
||||
char passphrase[MAX_PASSPHRASE_LEN + 1];
|
||||
int ref; /* (number of references held) - 1 */
|
||||
};
|
||||
|
||||
struct hostapd_wpa_psk {
|
||||
@ -205,6 +218,13 @@ struct hostapd_nai_realm_data {
|
||||
} eap_method[MAX_NAI_EAP_METHODS];
|
||||
};
|
||||
|
||||
struct anqp_element {
|
||||
struct dl_list list;
|
||||
u16 infoid;
|
||||
struct wpabuf *payload;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct hostapd_bss_config - Per-BSS configuration
|
||||
*/
|
||||
@ -231,6 +251,7 @@ struct hostapd_bss_config {
|
||||
struct hostapd_eap_user *eap_user;
|
||||
char *eap_user_sqlite;
|
||||
char *eap_sim_db;
|
||||
unsigned int eap_sim_db_timeout;
|
||||
int eap_server_erp; /* Whether ERP is enabled on internal EAP server */
|
||||
struct hostapd_ip_addr own_ip_addr;
|
||||
char *nas_identifier;
|
||||
@ -242,6 +263,7 @@ struct hostapd_bss_config {
|
||||
int radius_das_port;
|
||||
unsigned int radius_das_time_window;
|
||||
int radius_das_require_event_timestamp;
|
||||
int radius_das_require_message_authenticator;
|
||||
struct hostapd_ip_addr radius_das_client_addr;
|
||||
u8 *radius_das_shared_secret;
|
||||
size_t radius_das_shared_secret_len;
|
||||
@ -332,6 +354,7 @@ struct hostapd_bss_config {
|
||||
int check_crl;
|
||||
unsigned int tls_session_lifetime;
|
||||
char *ocsp_stapling_response;
|
||||
char *ocsp_stapling_response_multi;
|
||||
char *dh_file;
|
||||
char *openssl_ciphers;
|
||||
u8 *pac_opaque_encr_key;
|
||||
@ -358,6 +381,7 @@ struct hostapd_bss_config {
|
||||
|
||||
int ap_max_inactivity;
|
||||
int ignore_broadcast_ssid;
|
||||
int no_probe_resp_if_max_sta;
|
||||
|
||||
int wmm_enabled;
|
||||
int wmm_uapsd;
|
||||
@ -481,8 +505,11 @@ struct hostapd_bss_config {
|
||||
unsigned int nai_realm_count;
|
||||
struct hostapd_nai_realm_data *nai_realm_data;
|
||||
|
||||
struct dl_list anqp_elem; /* list of struct anqp_element */
|
||||
|
||||
u16 gas_comeback_delay;
|
||||
int gas_frag_limit;
|
||||
int gas_address3;
|
||||
|
||||
u8 qos_map_set[16 + 2 * 21];
|
||||
unsigned int qos_map_set_len;
|
||||
@ -536,6 +563,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;
|
||||
@ -551,12 +579,22 @@ struct hostapd_bss_config {
|
||||
#define MESH_ENABLED BIT(0)
|
||||
int mesh;
|
||||
|
||||
int radio_measurements;
|
||||
u8 radio_measurements[RRM_CAPABILITIES_IE_LEN];
|
||||
|
||||
int vendor_vht;
|
||||
int use_sta_nsts;
|
||||
|
||||
char *no_probe_resp_if_seen_on;
|
||||
char *no_auth_if_seen_on;
|
||||
|
||||
int pbss;
|
||||
|
||||
#ifdef CONFIG_MBO
|
||||
int mbo_enabled;
|
||||
#endif /* CONFIG_MBO */
|
||||
|
||||
int ftm_responder;
|
||||
int ftm_initiator;
|
||||
};
|
||||
|
||||
|
||||
@ -638,6 +676,9 @@ struct hostapd_config {
|
||||
u8 vht_oper_centr_freq_seg0_idx;
|
||||
u8 vht_oper_centr_freq_seg1_idx;
|
||||
|
||||
/* Use driver-generated interface addresses when adding multiple BSSs */
|
||||
u8 use_driver_iface_addr;
|
||||
|
||||
#ifdef CONFIG_FST
|
||||
struct fst_iface_cfg fst_cfg;
|
||||
#endif /* CONFIG_FST */
|
||||
@ -652,6 +693,7 @@ struct hostapd_config {
|
||||
double ignore_assoc_probability;
|
||||
double ignore_reassoc_probability;
|
||||
double corrupt_gtk_rekey_mic_probability;
|
||||
int ecsa_ie_only;
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
#ifdef CONFIG_ACS
|
||||
@ -662,11 +704,13 @@ struct hostapd_config {
|
||||
} *acs_chan_bias;
|
||||
unsigned int num_acs_chan_bias;
|
||||
#endif /* CONFIG_ACS */
|
||||
|
||||
struct wpabuf *lci;
|
||||
struct wpabuf *civic;
|
||||
};
|
||||
|
||||
|
||||
int hostapd_mac_comp(const void *a, const void *b);
|
||||
int hostapd_mac_comp_empty(const void *a);
|
||||
struct hostapd_config * hostapd_config_defaults(void);
|
||||
void hostapd_config_defaults_bss(struct hostapd_bss_config *bss);
|
||||
void hostapd_config_free_eap_user(struct hostapd_eap_user *user);
|
||||
@ -674,13 +718,14 @@ void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **p);
|
||||
void hostapd_config_free_bss(struct hostapd_bss_config *conf);
|
||||
void hostapd_config_free(struct hostapd_config *conf);
|
||||
int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
|
||||
const u8 *addr, int *vlan_id);
|
||||
const u8 *addr, struct vlan_description *vlan_id);
|
||||
int hostapd_rate_found(int *list, int rate);
|
||||
const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
|
||||
const u8 *addr, const u8 *p2p_dev_addr,
|
||||
const u8 *prev_psk);
|
||||
int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf);
|
||||
int hostapd_vlan_id_valid(struct hostapd_vlan *vlan, int vlan_id);
|
||||
int hostapd_vlan_valid(struct hostapd_vlan *vlan,
|
||||
struct vlan_description *vlan_desc);
|
||||
const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan,
|
||||
int vlan_id);
|
||||
struct hostapd_radius_attr *
|
||||
|
@ -35,10 +35,36 @@ u32 hostapd_sta_flags_to_drv(u32 flags)
|
||||
res |= WPA_STA_SHORT_PREAMBLE;
|
||||
if (flags & WLAN_STA_MFP)
|
||||
res |= WPA_STA_MFP;
|
||||
if (flags & WLAN_STA_AUTH)
|
||||
res |= WPA_STA_AUTHENTICATED;
|
||||
if (flags & WLAN_STA_ASSOC)
|
||||
res |= WPA_STA_ASSOCIATED;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static int add_buf(struct wpabuf **dst, const struct wpabuf *src)
|
||||
{
|
||||
if (!src)
|
||||
return 0;
|
||||
if (wpabuf_resize(dst, wpabuf_len(src)) != 0)
|
||||
return -1;
|
||||
wpabuf_put_buf(*dst, src);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int add_buf_data(struct wpabuf **dst, const u8 *data, size_t len)
|
||||
{
|
||||
if (!data || !len)
|
||||
return 0;
|
||||
if (wpabuf_resize(dst, len) != 0)
|
||||
return -1;
|
||||
wpabuf_put_data(*dst, data, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
|
||||
struct wpabuf **beacon_ret,
|
||||
struct wpabuf **proberesp_ret,
|
||||
@ -51,82 +77,38 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
|
||||
|
||||
pos = buf;
|
||||
pos = hostapd_eid_time_adv(hapd, pos);
|
||||
if (pos != buf) {
|
||||
if (wpabuf_resize(&beacon, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(beacon, buf, pos - buf);
|
||||
}
|
||||
if (add_buf_data(&beacon, buf, pos - buf) < 0)
|
||||
goto fail;
|
||||
pos = hostapd_eid_time_zone(hapd, pos);
|
||||
if (pos != buf) {
|
||||
if (wpabuf_resize(&proberesp, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(proberesp, buf, pos - buf);
|
||||
}
|
||||
if (add_buf_data(&proberesp, buf, pos - buf) < 0)
|
||||
goto fail;
|
||||
|
||||
pos = buf;
|
||||
pos = hostapd_eid_ext_capab(hapd, pos);
|
||||
if (pos != buf) {
|
||||
if (wpabuf_resize(&assocresp, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(assocresp, buf, pos - buf);
|
||||
}
|
||||
if (add_buf_data(&assocresp, buf, pos - buf) < 0)
|
||||
goto fail;
|
||||
pos = hostapd_eid_interworking(hapd, pos);
|
||||
pos = hostapd_eid_adv_proto(hapd, pos);
|
||||
pos = hostapd_eid_roaming_consortium(hapd, pos);
|
||||
if (pos != buf) {
|
||||
if (wpabuf_resize(&beacon, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(beacon, buf, pos - buf);
|
||||
|
||||
if (wpabuf_resize(&proberesp, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(proberesp, buf, pos - buf);
|
||||
}
|
||||
if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
|
||||
add_buf_data(&proberesp, buf, pos - buf) < 0)
|
||||
goto fail;
|
||||
|
||||
#ifdef CONFIG_FST
|
||||
if (hapd->iface->fst_ies) {
|
||||
size_t add = wpabuf_len(hapd->iface->fst_ies);
|
||||
|
||||
if (wpabuf_resize(&beacon, add) < 0)
|
||||
goto fail;
|
||||
wpabuf_put_buf(beacon, hapd->iface->fst_ies);
|
||||
if (wpabuf_resize(&proberesp, add) < 0)
|
||||
goto fail;
|
||||
wpabuf_put_buf(proberesp, hapd->iface->fst_ies);
|
||||
if (wpabuf_resize(&assocresp, add) < 0)
|
||||
goto fail;
|
||||
wpabuf_put_buf(assocresp, hapd->iface->fst_ies);
|
||||
}
|
||||
if (add_buf(&beacon, hapd->iface->fst_ies) < 0 ||
|
||||
add_buf(&proberesp, hapd->iface->fst_ies) < 0 ||
|
||||
add_buf(&assocresp, hapd->iface->fst_ies) < 0)
|
||||
goto fail;
|
||||
#endif /* CONFIG_FST */
|
||||
|
||||
if (hapd->wps_beacon_ie) {
|
||||
if (wpabuf_resize(&beacon, wpabuf_len(hapd->wps_beacon_ie)) <
|
||||
0)
|
||||
goto fail;
|
||||
wpabuf_put_buf(beacon, hapd->wps_beacon_ie);
|
||||
}
|
||||
|
||||
if (hapd->wps_probe_resp_ie) {
|
||||
if (wpabuf_resize(&proberesp,
|
||||
wpabuf_len(hapd->wps_probe_resp_ie)) < 0)
|
||||
goto fail;
|
||||
wpabuf_put_buf(proberesp, hapd->wps_probe_resp_ie);
|
||||
}
|
||||
if (add_buf(&beacon, hapd->wps_beacon_ie) < 0 ||
|
||||
add_buf(&proberesp, hapd->wps_probe_resp_ie) < 0)
|
||||
goto fail;
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (hapd->p2p_beacon_ie) {
|
||||
if (wpabuf_resize(&beacon, wpabuf_len(hapd->p2p_beacon_ie)) <
|
||||
0)
|
||||
goto fail;
|
||||
wpabuf_put_buf(beacon, hapd->p2p_beacon_ie);
|
||||
}
|
||||
|
||||
if (hapd->p2p_probe_resp_ie) {
|
||||
if (wpabuf_resize(&proberesp,
|
||||
wpabuf_len(hapd->p2p_probe_resp_ie)) < 0)
|
||||
goto fail;
|
||||
wpabuf_put_buf(proberesp, hapd->p2p_probe_resp_ie);
|
||||
}
|
||||
if (add_buf(&beacon, hapd->p2p_beacon_ie) < 0 ||
|
||||
add_buf(&proberesp, hapd->p2p_probe_resp_ie) < 0)
|
||||
goto fail;
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
#ifdef CONFIG_P2P_MANAGER
|
||||
@ -150,8 +132,7 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
|
||||
#ifdef CONFIG_WPS
|
||||
if (hapd->conf->wps_state) {
|
||||
struct wpabuf *a = wps_build_assoc_resp_ie();
|
||||
if (a && wpabuf_resize(&assocresp, wpabuf_len(a)) == 0)
|
||||
wpabuf_put_buf(assocresp, a);
|
||||
add_buf(&assocresp, a);
|
||||
wpabuf_free(a);
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
@ -171,44 +152,36 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
|
||||
if (hapd->p2p_group) {
|
||||
struct wpabuf *a;
|
||||
a = p2p_group_assoc_resp_ie(hapd->p2p_group, P2P_SC_SUCCESS);
|
||||
if (a && wpabuf_resize(&assocresp, wpabuf_len(a)) == 0)
|
||||
wpabuf_put_buf(assocresp, a);
|
||||
add_buf(&assocresp, a);
|
||||
wpabuf_free(a);
|
||||
}
|
||||
#endif /* CONFIG_WIFI_DISPLAY */
|
||||
|
||||
#ifdef CONFIG_HS20
|
||||
pos = buf;
|
||||
pos = hostapd_eid_hs20_indication(hapd, pos);
|
||||
if (pos != buf) {
|
||||
if (wpabuf_resize(&beacon, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(beacon, buf, pos - buf);
|
||||
|
||||
if (wpabuf_resize(&proberesp, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(proberesp, buf, pos - buf);
|
||||
}
|
||||
pos = hostapd_eid_hs20_indication(hapd, buf);
|
||||
if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
|
||||
add_buf_data(&proberesp, buf, pos - buf) < 0)
|
||||
goto fail;
|
||||
|
||||
pos = hostapd_eid_osen(hapd, buf);
|
||||
if (pos != buf) {
|
||||
if (wpabuf_resize(&beacon, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(beacon, buf, pos - buf);
|
||||
|
||||
if (wpabuf_resize(&proberesp, pos - buf) != 0)
|
||||
goto fail;
|
||||
wpabuf_put_data(proberesp, buf, pos - buf);
|
||||
}
|
||||
if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
|
||||
add_buf_data(&proberesp, buf, pos - buf) < 0)
|
||||
goto fail;
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
if (hapd->conf->vendor_elements) {
|
||||
size_t add = wpabuf_len(hapd->conf->vendor_elements);
|
||||
if (wpabuf_resize(&beacon, add) == 0)
|
||||
wpabuf_put_buf(beacon, hapd->conf->vendor_elements);
|
||||
if (wpabuf_resize(&proberesp, add) == 0)
|
||||
wpabuf_put_buf(proberesp, hapd->conf->vendor_elements);
|
||||
#ifdef CONFIG_MBO
|
||||
if (hapd->conf->mbo_enabled) {
|
||||
pos = hostapd_eid_mbo(hapd, buf, sizeof(buf));
|
||||
if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
|
||||
add_buf_data(&proberesp, buf, pos - buf) < 0 ||
|
||||
add_buf_data(&assocresp, buf, pos - buf) < 0)
|
||||
goto fail;
|
||||
}
|
||||
#endif /* CONFIG_MBO */
|
||||
|
||||
add_buf(&beacon, hapd->conf->vendor_elements);
|
||||
add_buf(&proberesp, hapd->conf->vendor_elements);
|
||||
add_buf(&assocresp, hapd->conf->assocresp_elements);
|
||||
|
||||
*beacon_ret = beacon;
|
||||
*proberesp_ret = proberesp;
|
||||
@ -392,7 +365,8 @@ int hostapd_sta_add(struct hostapd_data *hapd,
|
||||
u16 listen_interval,
|
||||
const struct ieee80211_ht_capabilities *ht_capab,
|
||||
const struct ieee80211_vht_capabilities *vht_capab,
|
||||
u32 flags, u8 qosinfo, u8 vht_opmode)
|
||||
u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps,
|
||||
int set)
|
||||
{
|
||||
struct hostapd_sta_add_params params;
|
||||
|
||||
@ -414,6 +388,8 @@ int hostapd_sta_add(struct hostapd_data *hapd,
|
||||
params.vht_opmode = vht_opmode;
|
||||
params.flags = hostapd_sta_flags_to_drv(flags);
|
||||
params.qosinfo = qosinfo;
|
||||
params.support_p2p_ps = supp_p2p_ps;
|
||||
params.set = set;
|
||||
return hapd->driver->sta_add(hapd->drv_priv, ¶ms);
|
||||
}
|
||||
|
||||
@ -470,7 +446,7 @@ int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
||||
return -1;
|
||||
return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr,
|
||||
bss_ctx, drv_priv, force_ifname, if_addr,
|
||||
bridge, use_existing);
|
||||
bridge, use_existing, 1);
|
||||
}
|
||||
|
||||
|
||||
@ -648,17 +624,29 @@ int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
|
||||
|
||||
int hostapd_drv_send_mlme(struct hostapd_data *hapd,
|
||||
const void *msg, size_t len, int noack)
|
||||
{
|
||||
if (!hapd->driver || !hapd->driver->send_mlme || !hapd->drv_priv)
|
||||
return 0;
|
||||
return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
|
||||
NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_send_mlme_csa(struct hostapd_data *hapd,
|
||||
const void *msg, size_t len, int noack,
|
||||
const u16 *csa_offs, size_t csa_offs_len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
|
||||
return 0;
|
||||
return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0);
|
||||
return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
|
||||
csa_offs, csa_offs_len);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
|
||||
const u8 *addr, int reason)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL)
|
||||
if (!hapd->driver || !hapd->driver->sta_deauth || !hapd->drv_priv)
|
||||
return 0;
|
||||
return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr,
|
||||
reason);
|
||||
@ -668,7 +656,7 @@ int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
|
||||
int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
|
||||
const u8 *addr, int reason)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL)
|
||||
if (!hapd->driver || !hapd->driver->sta_disassoc || !hapd->drv_priv)
|
||||
return 0;
|
||||
return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr,
|
||||
reason);
|
||||
@ -688,6 +676,36 @@ int hostapd_drv_wnm_oper(struct hostapd_data *hapd, enum wnm_oper oper,
|
||||
int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
|
||||
unsigned int wait, const u8 *dst, const u8 *data,
|
||||
size_t len)
|
||||
{
|
||||
const u8 *bssid;
|
||||
const u8 wildcard_bssid[ETH_ALEN] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
if (!hapd->driver || !hapd->driver->send_action || !hapd->drv_priv)
|
||||
return 0;
|
||||
bssid = hapd->own_addr;
|
||||
if (!is_multicast_ether_addr(dst) &&
|
||||
len > 0 && data[0] == WLAN_ACTION_PUBLIC) {
|
||||
struct sta_info *sta;
|
||||
|
||||
/*
|
||||
* Public Action frames to a STA that is not a member of the BSS
|
||||
* shall use wildcard BSSID value.
|
||||
*/
|
||||
sta = ap_get_sta(hapd, dst);
|
||||
if (!sta || !(sta->flags & WLAN_STA_ASSOC))
|
||||
bssid = wildcard_bssid;
|
||||
}
|
||||
return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst,
|
||||
hapd->own_addr, bssid, data, len, 0);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_send_action_addr3_ap(struct hostapd_data *hapd,
|
||||
unsigned int freq,
|
||||
unsigned int wait, const u8 *dst,
|
||||
const u8 *data, size_t len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->send_action == NULL)
|
||||
return 0;
|
||||
@ -738,7 +756,7 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
|
||||
int hostapd_drv_set_qos_map(struct hostapd_data *hapd,
|
||||
const u8 *qos_map_set, u8 qos_map_set_len)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->set_qos_map == NULL)
|
||||
if (!hapd->driver || !hapd->driver->set_qos_map || !hapd->drv_priv)
|
||||
return 0;
|
||||
return hapd->driver->set_qos_map(hapd->drv_priv, qos_map_set,
|
||||
qos_map_set_len);
|
||||
@ -764,6 +782,20 @@ static void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd,
|
||||
}
|
||||
|
||||
|
||||
void hostapd_get_ext_capa(struct hostapd_iface *iface)
|
||||
{
|
||||
struct hostapd_data *hapd = iface->bss[0];
|
||||
|
||||
if (!hapd->driver || !hapd->driver->get_ext_capab)
|
||||
return;
|
||||
|
||||
hapd->driver->get_ext_capab(hapd->drv_priv, WPA_IF_AP_BSS,
|
||||
&iface->extended_capa,
|
||||
&iface->extended_capa_mask,
|
||||
&iface->extended_capa_len);
|
||||
}
|
||||
|
||||
|
||||
int hostapd_drv_do_acs(struct hostapd_data *hapd)
|
||||
{
|
||||
struct drv_acs_params params;
|
||||
|
@ -41,7 +41,8 @@ int hostapd_sta_add(struct hostapd_data *hapd,
|
||||
u16 listen_interval,
|
||||
const struct ieee80211_ht_capabilities *ht_capab,
|
||||
const struct ieee80211_vht_capabilities *vht_capab,
|
||||
u32 flags, u8 qosinfo, u8 vht_opmode);
|
||||
u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps,
|
||||
int set);
|
||||
int hostapd_set_privacy(struct hostapd_data *hapd, int enabled);
|
||||
int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
|
||||
size_t elem_len);
|
||||
@ -88,6 +89,9 @@ int hostapd_drv_set_key(const char *ifname,
|
||||
const u8 *key, size_t key_len);
|
||||
int hostapd_drv_send_mlme(struct hostapd_data *hapd,
|
||||
const void *msg, size_t len, int noack);
|
||||
int hostapd_drv_send_mlme_csa(struct hostapd_data *hapd,
|
||||
const void *msg, size_t len, int noack,
|
||||
const u16 *csa_offs, size_t csa_offs_len);
|
||||
int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
|
||||
const u8 *addr, int reason);
|
||||
int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
|
||||
@ -95,6 +99,10 @@ int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
|
||||
int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
|
||||
unsigned int wait, const u8 *dst, const u8 *data,
|
||||
size_t len);
|
||||
int hostapd_drv_send_action_addr3_ap(struct hostapd_data *hapd,
|
||||
unsigned int freq,
|
||||
unsigned int wait, const u8 *dst,
|
||||
const u8 *data, size_t len);
|
||||
int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
|
||||
u16 auth_alg);
|
||||
int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr,
|
||||
@ -120,6 +128,8 @@ int hostapd_drv_wnm_oper(struct hostapd_data *hapd,
|
||||
int hostapd_drv_set_qos_map(struct hostapd_data *hapd, const u8 *qos_map_set,
|
||||
u8 qos_map_set_len);
|
||||
|
||||
void hostapd_get_ext_capa(struct hostapd_iface *iface);
|
||||
|
||||
static inline int hostapd_drv_set_countermeasures(struct hostapd_data *hapd,
|
||||
int enabled)
|
||||
{
|
||||
@ -150,7 +160,7 @@ static inline int hostapd_drv_get_inact_sec(struct hostapd_data *hapd,
|
||||
static inline int hostapd_drv_sta_remove(struct hostapd_data *hapd,
|
||||
const u8 *addr)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->sta_remove == NULL)
|
||||
if (!hapd->driver || !hapd->driver->sta_remove || !hapd->drv_priv)
|
||||
return 0;
|
||||
return hapd->driver->sta_remove(hapd->drv_priv, addr);
|
||||
}
|
||||
@ -273,7 +283,7 @@ static inline int hostapd_drv_switch_channel(struct hostapd_data *hapd,
|
||||
static inline int hostapd_drv_status(struct hostapd_data *hapd, char *buf,
|
||||
size_t buflen)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->status == NULL)
|
||||
if (!hapd->driver || !hapd->driver->status || !hapd->drv_priv)
|
||||
return -1;
|
||||
return hapd->driver->status(hapd->drv_priv, buf, buflen);
|
||||
}
|
||||
@ -332,7 +342,7 @@ static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd,
|
||||
|
||||
static inline int hostapd_drv_stop_ap(struct hostapd_data *hapd)
|
||||
{
|
||||
if (hapd->driver == NULL || hapd->driver->stop_ap == NULL)
|
||||
if (!hapd->driver || !hapd->driver->stop_ap || !hapd->drv_priv)
|
||||
return 0;
|
||||
return hapd->driver->stop_ap(hapd->drv_priv);
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ struct hapd_interfaces {
|
||||
|
||||
size_t count;
|
||||
int global_ctrl_sock;
|
||||
struct wpa_ctrl_dst *global_ctrl_dst;
|
||||
struct dl_list global_ctrl_dst;
|
||||
char *global_iface_path;
|
||||
char *global_iface_name;
|
||||
#ifndef CONFIG_NATIVE_WINDOWS
|
||||
@ -53,6 +53,7 @@ struct hapd_interfaces {
|
||||
#ifndef CONFIG_NO_VLAN
|
||||
struct dynamic_iface *vlan_priv;
|
||||
#endif /* CONFIG_NO_VLAN */
|
||||
int eloop_initialized;
|
||||
};
|
||||
|
||||
enum hostapd_chan_status {
|
||||
@ -99,6 +100,16 @@ struct wps_stat {
|
||||
u8 peer_addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
struct hostapd_neighbor_entry {
|
||||
struct dl_list list;
|
||||
u8 bssid[ETH_ALEN];
|
||||
struct wpa_ssid_value ssid;
|
||||
struct wpabuf *nr;
|
||||
struct wpabuf *lci;
|
||||
struct wpabuf *civic;
|
||||
/* LCI update time */
|
||||
struct os_time lci_date;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct hostapd_data - hostapd per-BSS data structure
|
||||
@ -138,7 +149,7 @@ struct hostapd_data {
|
||||
void *msg_ctx_parent; /* parent interface ctx for wpa_msg() calls */
|
||||
|
||||
struct radius_client_data *radius;
|
||||
u32 acct_session_id_hi, acct_session_id_lo;
|
||||
u64 acct_session_id;
|
||||
struct radius_das_data *radius_das;
|
||||
|
||||
struct iapp_data *iapp;
|
||||
@ -155,7 +166,7 @@ struct hostapd_data {
|
||||
int tkip_countermeasures;
|
||||
|
||||
int ctrl_sock;
|
||||
struct wpa_ctrl_dst *ctrl_dst;
|
||||
struct dl_list ctrl_dst;
|
||||
|
||||
void *ssl_ctx;
|
||||
void *eap_sim_db_priv;
|
||||
@ -228,6 +239,8 @@ struct hostapd_data {
|
||||
unsigned int cs_c_off_beacon;
|
||||
unsigned int cs_c_off_proberesp;
|
||||
int csa_in_progress;
|
||||
unsigned int cs_c_off_ecsa_beacon;
|
||||
unsigned int cs_c_off_ecsa_proberesp;
|
||||
|
||||
/* BSS Load */
|
||||
unsigned int bss_load_update_timeout;
|
||||
@ -256,9 +269,11 @@ struct hostapd_data {
|
||||
#ifdef CONFIG_MESH
|
||||
int num_plinks;
|
||||
int max_plinks;
|
||||
void (*mesh_sta_free_cb)(struct sta_info *sta);
|
||||
void (*mesh_sta_free_cb)(struct hostapd_data *hapd,
|
||||
struct sta_info *sta);
|
||||
struct wpabuf *mesh_pending_auth;
|
||||
struct os_reltime mesh_pending_auth_time;
|
||||
u8 mesh_required_peer[ETH_ALEN];
|
||||
#endif /* CONFIG_MESH */
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
@ -278,6 +293,17 @@ struct hostapd_data {
|
||||
|
||||
struct l2_packet_data *l2_test;
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
#ifdef CONFIG_MBO
|
||||
unsigned int mbo_assoc_disallow;
|
||||
#endif /* CONFIG_MBO */
|
||||
|
||||
struct dl_list nr_db;
|
||||
|
||||
u8 lci_req_token;
|
||||
u8 range_req_token;
|
||||
unsigned int lci_req_active:1;
|
||||
unsigned int range_req_active:1;
|
||||
};
|
||||
|
||||
|
||||
@ -285,6 +311,9 @@ struct hostapd_sta_info {
|
||||
struct dl_list list;
|
||||
u8 addr[ETH_ALEN];
|
||||
struct os_reltime last_seen;
|
||||
#ifdef CONFIG_TAXONOMY
|
||||
struct wpabuf *probe_ie_taxonomy;
|
||||
#endif /* CONFIG_TAXONOMY */
|
||||
};
|
||||
|
||||
/**
|
||||
@ -327,6 +356,15 @@ struct hostapd_iface {
|
||||
*/
|
||||
unsigned int driver_ap_teardown:1;
|
||||
|
||||
/*
|
||||
* When set, indicates that this interface is part of list of
|
||||
* interfaces that need to be started together (synchronously).
|
||||
*/
|
||||
unsigned int need_to_start_in_sync:1;
|
||||
|
||||
/* Ready to start but waiting for other interfaces to become ready. */
|
||||
unsigned int ready_to_start_in_sync:1;
|
||||
|
||||
int num_ap; /* number of entries in ap_list */
|
||||
struct ap_info *ap_list; /* AP info list head */
|
||||
struct ap_info *ap_hash[STA_HASH_SIZE];
|
||||
@ -402,6 +440,9 @@ struct hostapd_iface {
|
||||
u64 last_channel_time_busy;
|
||||
u8 channel_utilization;
|
||||
|
||||
/* eCSA IE will be added only if operating class is specified */
|
||||
u8 cs_oper_class;
|
||||
|
||||
unsigned int dfs_cac_ms;
|
||||
struct os_reltime dfs_cac_start;
|
||||
|
||||
@ -433,6 +474,7 @@ int hostapd_setup_interface(struct hostapd_iface *iface);
|
||||
int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err);
|
||||
void hostapd_interface_deinit(struct hostapd_iface *iface);
|
||||
void hostapd_interface_free(struct hostapd_iface *iface);
|
||||
struct hostapd_iface * hostapd_alloc_iface(void);
|
||||
struct hostapd_iface * hostapd_init(struct hapd_interfaces *interfaces,
|
||||
const char *config_file);
|
||||
struct hostapd_iface *
|
||||
@ -449,6 +491,7 @@ int hostapd_remove_iface(struct hapd_interfaces *ifaces, char *buf);
|
||||
void hostapd_channel_list_updated(struct hostapd_iface *iface, int initiator);
|
||||
void hostapd_set_state(struct hostapd_iface *iface, enum hostapd_iface_state s);
|
||||
const char * hostapd_state_text(enum hostapd_iface_state s);
|
||||
int hostapd_csa_in_progress(struct hostapd_iface *iface);
|
||||
int hostapd_switch_channel(struct hostapd_data *hapd,
|
||||
struct csa_settings *settings);
|
||||
void
|
||||
@ -478,6 +521,11 @@ int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
|
||||
int ssi_signal);
|
||||
void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
|
||||
int offset, int width, int cf1, int cf2);
|
||||
struct survey_results;
|
||||
void hostapd_event_get_survey(struct hostapd_iface *iface,
|
||||
struct survey_results *survey_results);
|
||||
void hostapd_acs_channel_selected(struct hostapd_data *hapd,
|
||||
struct acs_selected_channels *acs_res);
|
||||
|
||||
const struct hostapd_eap_user *
|
||||
hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
|
||||
|
@ -49,9 +49,13 @@ u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid);
|
||||
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_secondary_channel(struct hostapd_data *hapd, u8 *eid);
|
||||
u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts);
|
||||
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_wb_chsw_wrapper(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);
|
||||
@ -61,6 +65,7 @@ void hostapd_get_ht_capab(struct hostapd_data *hapd,
|
||||
void hostapd_get_vht_capab(struct hostapd_data *hapd,
|
||||
struct ieee80211_vht_capabilities *vht_cap,
|
||||
struct ieee80211_vht_capabilities *neg_vht_cap);
|
||||
int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *ht_capab);
|
||||
u16 copy_sta_vendor_vht(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
@ -97,6 +102,7 @@ int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
#ifdef CONFIG_SAE
|
||||
void sae_clear_retransmit_timer(struct hostapd_data *hapd,
|
||||
struct sta_info *sta);
|
||||
void sae_accept_sta(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
#else /* CONFIG_SAE */
|
||||
static inline void sae_clear_retransmit_timer(struct hostapd_data *hapd,
|
||||
struct sta_info *sta)
|
||||
@ -104,4 +110,29 @@ static inline void sae_clear_retransmit_timer(struct hostapd_data *hapd,
|
||||
}
|
||||
#endif /* CONFIG_SAE */
|
||||
|
||||
#ifdef CONFIG_MBO
|
||||
|
||||
u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len);
|
||||
|
||||
u8 hostapd_mbo_ie_len(struct hostapd_data *hapd);
|
||||
|
||||
#else /* CONFIG_MBO */
|
||||
|
||||
static inline u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid,
|
||||
size_t len)
|
||||
{
|
||||
return eid;
|
||||
}
|
||||
|
||||
static inline u8 hostapd_mbo_ie_len(struct hostapd_data *hapd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MBO */
|
||||
|
||||
void ap_copy_sta_supp_op_classes(struct sta_info *sta,
|
||||
const u8 *supp_op_classes,
|
||||
size_t supp_op_classes_len);
|
||||
|
||||
#endif /* IEEE802_11_H */
|
||||
|
@ -16,9 +16,12 @@ enum {
|
||||
HOSTAPD_ACL_ACCEPT_TIMEOUT = 3
|
||||
};
|
||||
|
||||
int hostapd_check_acl(struct hostapd_data *hapd, const u8 *addr,
|
||||
struct vlan_description *vlan_id);
|
||||
int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
|
||||
const u8 *msg, size_t len, u32 *session_timeout,
|
||||
u32 *acct_interim_interval, int *vlan_id,
|
||||
u32 *acct_interim_interval,
|
||||
struct vlan_description *vlan_id,
|
||||
struct hostapd_sta_wpa_psk_short **psk,
|
||||
char **identity, char **radius_cui);
|
||||
int hostapd_acl_init(struct hostapd_data *hapd);
|
||||
|
@ -174,6 +174,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
|
||||
case 0: /* Bits 0-7 */
|
||||
if (hapd->iconf->obss_interval)
|
||||
*pos |= 0x01; /* Bit 0 - Coexistence management */
|
||||
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA)
|
||||
*pos |= 0x04; /* Bit 2 - Extended Channel Switching */
|
||||
break;
|
||||
case 1: /* Bits 8-15 */
|
||||
if (hapd->conf->proxy_arp)
|
||||
@ -209,11 +211,21 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
|
||||
if (hapd->conf->hs20)
|
||||
*pos |= 0x40; /* Bit 46 - WNM-Notification */
|
||||
#endif /* CONFIG_HS20 */
|
||||
#ifdef CONFIG_MBO
|
||||
if (hapd->conf->mbo_enabled)
|
||||
*pos |= 0x40; /* Bit 46 - WNM-Notification */
|
||||
#endif /* CONFIG_MBO */
|
||||
break;
|
||||
case 6: /* Bits 48-55 */
|
||||
if (hapd->conf->ssid.utf8_ssid)
|
||||
*pos |= 0x01; /* Bit 48 - UTF-8 SSID */
|
||||
break;
|
||||
case 8: /* Bits 64-71 */
|
||||
if (hapd->conf->ftm_responder)
|
||||
*pos |= 0x40; /* Bit 70 - FTM responder */
|
||||
if (hapd->conf->ftm_initiator)
|
||||
*pos |= 0x80; /* Bit 71 - FTM initiator */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -233,6 +245,9 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
|
||||
len = 1;
|
||||
if (len < 7 && hapd->conf->ssid.utf8_ssid)
|
||||
len = 7;
|
||||
if (len < 9 &&
|
||||
(hapd->conf->ftm_initiator || hapd->conf->ftm_responder))
|
||||
len = 9;
|
||||
#ifdef CONFIG_WNM
|
||||
if (len < 4)
|
||||
len = 4;
|
||||
@ -241,6 +256,10 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
|
||||
if (hapd->conf->hs20 && len < 6)
|
||||
len = 6;
|
||||
#endif /* CONFIG_HS20 */
|
||||
#ifdef CONFIG_MBO
|
||||
if (hapd->conf->mbo_enabled && len < 6)
|
||||
len = 6;
|
||||
#endif /* CONFIG_MBO */
|
||||
if (len < hapd->iface->extended_capa_len)
|
||||
len = hapd->iface->extended_capa_len;
|
||||
if (len == 0)
|
||||
@ -508,3 +527,62 @@ u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid)
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_MBO
|
||||
|
||||
u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len)
|
||||
{
|
||||
u8 mbo[6], *mbo_pos = mbo;
|
||||
u8 *pos = eid;
|
||||
|
||||
if (!hapd->conf->mbo_enabled)
|
||||
return eid;
|
||||
|
||||
*mbo_pos++ = MBO_ATTR_ID_AP_CAPA_IND;
|
||||
*mbo_pos++ = 1;
|
||||
/* Not Cellular aware */
|
||||
*mbo_pos++ = 0;
|
||||
|
||||
if (hapd->mbo_assoc_disallow) {
|
||||
*mbo_pos++ = MBO_ATTR_ID_ASSOC_DISALLOW;
|
||||
*mbo_pos++ = 1;
|
||||
*mbo_pos++ = hapd->mbo_assoc_disallow;
|
||||
}
|
||||
|
||||
pos += mbo_add_ie(pos, len, mbo, mbo_pos - mbo);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
u8 hostapd_mbo_ie_len(struct hostapd_data *hapd)
|
||||
{
|
||||
if (!hapd->conf->mbo_enabled)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* MBO IE header (6) + Capability Indication attribute (3) +
|
||||
* Association Disallowed attribute (3) = 12
|
||||
*/
|
||||
return 6 + 3 + (hapd->mbo_assoc_disallow ? 3 : 0);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MBO */
|
||||
|
||||
|
||||
void ap_copy_sta_supp_op_classes(struct sta_info *sta,
|
||||
const u8 *supp_op_classes,
|
||||
size_t supp_op_classes_len)
|
||||
{
|
||||
if (!supp_op_classes)
|
||||
return;
|
||||
os_free(sta->supp_op_classes);
|
||||
sta->supp_op_classes = os_malloc(1 + supp_op_classes_len);
|
||||
if (!sta->supp_op_classes)
|
||||
return;
|
||||
|
||||
sta->supp_op_classes[0] = supp_op_classes_len;
|
||||
os_memcpy(sta->supp_op_classes + 1, supp_op_classes,
|
||||
supp_op_classes_len);
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
struct rsn_pmksa_cache_entry {
|
||||
struct rsn_pmksa_cache_entry *next, *hnext;
|
||||
u8 pmkid[PMKID_LEN];
|
||||
u8 pmk[PMK_LEN];
|
||||
u8 pmk[PMK_LEN_MAX];
|
||||
size_t pmk_len;
|
||||
os_time_t expiration;
|
||||
int akmp; /* WPA_KEY_MGMT_* */
|
||||
@ -28,11 +28,10 @@ struct rsn_pmksa_cache_entry {
|
||||
struct wpabuf *cui;
|
||||
struct radius_class_data radius_class;
|
||||
u8 eap_type_authsrv;
|
||||
int vlan_id;
|
||||
struct vlan_description *vlan_desc;
|
||||
int opportunistic;
|
||||
|
||||
u32 acct_multi_session_id_hi;
|
||||
u32 acct_multi_session_id_lo;
|
||||
u64 acct_multi_session_id;
|
||||
};
|
||||
|
||||
struct rsn_pmksa_cache;
|
||||
@ -49,7 +48,7 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get_okc(
|
||||
const u8 *pmkid);
|
||||
struct rsn_pmksa_cache_entry *
|
||||
pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa,
|
||||
const u8 *pmk, size_t pmk_len,
|
||||
const u8 *pmk, size_t pmk_len, const u8 *pmkid,
|
||||
const u8 *kck, size_t kck_len,
|
||||
const u8 *aa, const u8 *spa, int session_timeout,
|
||||
struct eapol_state_machine *eapol, int akmp);
|
||||
@ -57,11 +56,14 @@ struct rsn_pmksa_cache_entry *
|
||||
pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa,
|
||||
const struct rsn_pmksa_cache_entry *old_entry,
|
||||
const u8 *aa, const u8 *pmkid);
|
||||
void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry,
|
||||
void pmksa_cache_to_eapol_data(struct hostapd_data *hapd,
|
||||
struct rsn_pmksa_cache_entry *entry,
|
||||
struct eapol_state_machine *eapol);
|
||||
void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa,
|
||||
struct rsn_pmksa_cache_entry *entry);
|
||||
int pmksa_cache_auth_radius_das_disconnect(struct rsn_pmksa_cache *pmksa,
|
||||
struct radius_das_attrs *attr);
|
||||
int pmksa_cache_auth_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len);
|
||||
void pmksa_cache_auth_flush(struct rsn_pmksa_cache *pmksa);
|
||||
|
||||
#endif /* PMKSA_CACHE_H */
|
||||
|
@ -12,9 +12,11 @@
|
||||
#ifdef CONFIG_MESH
|
||||
/* needed for mesh_plink_state enum */
|
||||
#include "common/defs.h"
|
||||
#include "common/wpa_common.h"
|
||||
#endif /* CONFIG_MESH */
|
||||
|
||||
#include "list.h"
|
||||
#include "vlan.h"
|
||||
|
||||
/* STA flags */
|
||||
#define WLAN_STA_AUTH BIT(0)
|
||||
@ -45,6 +47,20 @@
|
||||
#define WLAN_SUPP_RATES_MAX 32
|
||||
|
||||
|
||||
struct mbo_non_pref_chan_info {
|
||||
struct mbo_non_pref_chan_info *next;
|
||||
u8 op_class;
|
||||
u8 pref;
|
||||
u8 reason_code;
|
||||
u8 num_channels;
|
||||
u8 channels[];
|
||||
};
|
||||
|
||||
struct pending_eapol_rx {
|
||||
struct wpabuf *buf;
|
||||
struct os_reltime rx_time;
|
||||
};
|
||||
|
||||
struct sta_info {
|
||||
struct sta_info *next; /* next entry in sta list */
|
||||
struct sta_info *hnext; /* next entry in hash table list */
|
||||
@ -63,13 +79,22 @@ struct sta_info {
|
||||
enum mesh_plink_state plink_state;
|
||||
u16 peer_lid;
|
||||
u16 my_lid;
|
||||
u16 peer_aid;
|
||||
u16 mpm_close_reason;
|
||||
int mpm_retries;
|
||||
u8 my_nonce[32];
|
||||
u8 peer_nonce[32];
|
||||
u8 my_nonce[WPA_NONCE_LEN];
|
||||
u8 peer_nonce[WPA_NONCE_LEN];
|
||||
u8 aek[32]; /* SHA256 digest length */
|
||||
u8 mtk[16];
|
||||
u8 mgtk[16];
|
||||
u8 mtk[WPA_TK_MAX_LEN];
|
||||
size_t mtk_len;
|
||||
u8 mgtk_rsc[6];
|
||||
u8 mgtk_key_id;
|
||||
u8 mgtk[WPA_TK_MAX_LEN];
|
||||
size_t mgtk_len;
|
||||
u8 igtk_rsc[6];
|
||||
u8 igtk[WPA_TK_MAX_LEN];
|
||||
size_t igtk_len;
|
||||
u16 igtk_key_id;
|
||||
u8 sae_auth_retry;
|
||||
#endif /* CONFIG_MESH */
|
||||
|
||||
@ -86,6 +111,8 @@ struct sta_info {
|
||||
unsigned int hs20_deauth_requested:1;
|
||||
unsigned int session_timeout_set:1;
|
||||
unsigned int radius_das_match:1;
|
||||
unsigned int ecsa_supported:1;
|
||||
unsigned int added_unassoc:1;
|
||||
|
||||
u16 auth_alg;
|
||||
|
||||
@ -100,17 +127,20 @@ struct sta_info {
|
||||
/* IEEE 802.1X related data */
|
||||
struct eapol_state_machine *eapol_sm;
|
||||
|
||||
u32 acct_session_id_hi;
|
||||
u32 acct_session_id_lo;
|
||||
struct pending_eapol_rx *pending_eapol_rx;
|
||||
|
||||
u64 acct_session_id;
|
||||
struct os_reltime acct_session_start;
|
||||
int acct_session_started;
|
||||
int acct_terminate_cause; /* Acct-Terminate-Cause */
|
||||
int acct_interim_interval; /* Acct-Interim-Interval */
|
||||
unsigned int acct_interim_errors;
|
||||
|
||||
unsigned long last_rx_bytes;
|
||||
unsigned long last_tx_bytes;
|
||||
u32 acct_input_gigawords; /* Acct-Input-Gigawords */
|
||||
u32 acct_output_gigawords; /* Acct-Output-Gigawords */
|
||||
/* For extending 32-bit driver counters to 64-bit counters */
|
||||
u32 last_rx_bytes_hi;
|
||||
u32 last_rx_bytes_lo;
|
||||
u32 last_tx_bytes_hi;
|
||||
u32 last_tx_bytes_lo;
|
||||
|
||||
u8 *challenge; /* IEEE 802.11 Shared Key Authentication Challenge */
|
||||
|
||||
@ -118,6 +148,7 @@ struct sta_info {
|
||||
struct rsn_preauth_interface *preauth_iface;
|
||||
|
||||
int vlan_id; /* 0: none, >0: VID */
|
||||
struct vlan_description *vlan_desc;
|
||||
int vlan_id_bound; /* updated by ap_sta_bind_vlan() */
|
||||
/* PSKs from RADIUS authentication server */
|
||||
struct hostapd_sta_wpa_psk_short *psk;
|
||||
@ -161,6 +192,7 @@ struct sta_info {
|
||||
|
||||
#ifdef CONFIG_SAE
|
||||
struct sae_data *sae;
|
||||
unsigned int mesh_sae_pmksa_caching:1;
|
||||
#endif /* CONFIG_SAE */
|
||||
|
||||
u32 session_timeout; /* valid only if session_timeout_set == 1 */
|
||||
@ -170,6 +202,22 @@ struct sta_info {
|
||||
u16 last_seq_ctrl;
|
||||
/* Last Authentication/(Re)Association Request/Action frame subtype */
|
||||
u8 last_subtype;
|
||||
|
||||
#ifdef CONFIG_MBO
|
||||
u8 cell_capa; /* 0 = unknown (not an MBO STA); otherwise,
|
||||
* enum mbo_cellular_capa values */
|
||||
struct mbo_non_pref_chan_info *non_pref_chan;
|
||||
#endif /* CONFIG_MBO */
|
||||
|
||||
u8 *supp_op_classes; /* Supported Operating Classes element, if
|
||||
* received, starting from the Length field */
|
||||
|
||||
u8 rrm_enabled_capa[5];
|
||||
|
||||
#ifdef CONFIG_TAXONOMY
|
||||
struct wpabuf *probe_ie_taxonomy;
|
||||
struct wpabuf *assoc_ie_taxonomy;
|
||||
#endif /* CONFIG_TAXONOMY */
|
||||
};
|
||||
|
||||
|
||||
@ -180,7 +228,7 @@ struct sta_info {
|
||||
* AP_DISASSOC_DELAY seconds. Similarly, the station will be deauthenticated
|
||||
* after AP_DEAUTH_DELAY seconds has passed after disassociation. */
|
||||
#define AP_MAX_INACTIVITY (5 * 60)
|
||||
#define AP_DISASSOC_DELAY (1)
|
||||
#define AP_DISASSOC_DELAY (3)
|
||||
#define AP_DEAUTH_DELAY (1)
|
||||
/* Number of seconds to keep STA entry with Authenticated flag after it has
|
||||
* been disassociated. */
|
||||
@ -220,6 +268,8 @@ int ap_sta_wps_cancel(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, void *ctx);
|
||||
#endif /* CONFIG_WPS */
|
||||
int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
int ap_sta_set_vlan(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
struct vlan_description *vlan_desc);
|
||||
void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
@ -235,6 +285,8 @@ static inline int ap_sta_is_authorized(struct sta_info *sta)
|
||||
|
||||
void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void ap_sta_clear_disconnect_timeouts(struct hostapd_data *hapd,
|
||||
struct sta_info *sta);
|
||||
|
||||
int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen);
|
||||
|
||||
|
30
freebsd/contrib/wpa/src/ap/vlan.h
Normal file
30
freebsd/contrib/wpa/src/ap/vlan.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* hostapd / VLAN definition
|
||||
* Copyright (c) 2015, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef VLAN_H
|
||||
#define VLAN_H
|
||||
|
||||
#define MAX_NUM_TAGGED_VLAN 32
|
||||
|
||||
struct vlan_description {
|
||||
int notempty; /* 0 : no vlan information present, 1: else */
|
||||
int untagged; /* >0 802.1q vid */
|
||||
int tagged[MAX_NUM_TAGGED_VLAN]; /* first k items, ascending order */
|
||||
};
|
||||
|
||||
#ifndef CONFIG_NO_VLAN
|
||||
int vlan_compare(struct vlan_description *a, struct vlan_description *b);
|
||||
#else /* CONFIG_NO_VLAN */
|
||||
static inline int
|
||||
vlan_compare(struct vlan_description *a, struct vlan_description *b)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_NO_VLAN */
|
||||
|
||||
#endif /* VLAN_H */
|
@ -46,7 +46,8 @@ static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
|
||||
static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_group *group);
|
||||
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
|
||||
const u8 *pmk, struct wpa_ptk *ptk);
|
||||
const u8 *pmk, unsigned int pmk_len,
|
||||
struct wpa_ptk *ptk);
|
||||
static void wpa_group_free(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_group *group);
|
||||
static void wpa_group_get(struct wpa_authenticator *wpa_auth,
|
||||
@ -829,6 +830,7 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
|
||||
struct wpa_ptk PTK;
|
||||
int ok = 0;
|
||||
const u8 *pmk = NULL;
|
||||
unsigned int pmk_len;
|
||||
|
||||
for (;;) {
|
||||
if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) {
|
||||
@ -836,10 +838,13 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
|
||||
sm->p2p_dev_addr, pmk);
|
||||
if (pmk == NULL)
|
||||
break;
|
||||
} else
|
||||
pmk_len = PMK_LEN;
|
||||
} else {
|
||||
pmk = sm->PMK;
|
||||
pmk_len = sm->pmk_len;
|
||||
}
|
||||
|
||||
wpa_derive_ptk(sm, sm->alt_SNonce, pmk, &PTK);
|
||||
wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK);
|
||||
|
||||
if (wpa_verify_key_mic(sm->wpa_key_mgmt, &PTK, data, data_len)
|
||||
== 0) {
|
||||
@ -1742,6 +1747,9 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event)
|
||||
#else /* CONFIG_IEEE80211R */
|
||||
break;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
case WPA_DRV_STA_REMOVED:
|
||||
sm->tk_already_set = FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
@ -1921,11 +1929,27 @@ SM_STATE(WPA_PTK, INITPMK)
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
if (sm->pmksa) {
|
||||
wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache");
|
||||
os_memcpy(sm->PMK, sm->pmksa->pmk, PMK_LEN);
|
||||
os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len);
|
||||
sm->pmk_len = sm->pmksa->pmk_len;
|
||||
} else if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) {
|
||||
unsigned int pmk_len;
|
||||
|
||||
if (sm->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
|
||||
pmk_len = PMK_LEN_SUITE_B_192;
|
||||
else
|
||||
pmk_len = PMK_LEN;
|
||||
wpa_printf(MSG_DEBUG, "WPA: PMK from EAPOL state machine "
|
||||
"(len=%lu)", (unsigned long) len);
|
||||
os_memcpy(sm->PMK, msk, PMK_LEN);
|
||||
"(MSK len=%lu PMK len=%u)", (unsigned long) len,
|
||||
pmk_len);
|
||||
if (len < pmk_len) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"WPA: MSK not long enough (%u) to create PMK (%u)",
|
||||
(unsigned int) len, (unsigned int) pmk_len);
|
||||
sm->Disconnect = TRUE;
|
||||
return;
|
||||
}
|
||||
os_memcpy(sm->PMK, msk, pmk_len);
|
||||
sm->pmk_len = pmk_len;
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (len >= 2 * PMK_LEN) {
|
||||
os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN);
|
||||
@ -1960,6 +1984,7 @@ SM_STATE(WPA_PTK, INITPSK)
|
||||
psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL);
|
||||
if (psk) {
|
||||
os_memcpy(sm->PMK, psk, PMK_LEN);
|
||||
sm->pmk_len = PMK_LEN;
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
os_memcpy(sm->xxkey, psk, PMK_LEN);
|
||||
sm->xxkey_len = PMK_LEN;
|
||||
@ -2011,7 +2036,7 @@ SM_STATE(WPA_PTK, PTKSTART)
|
||||
* Calculate PMKID since no PMKSA cache entry was
|
||||
* available with pre-calculated PMKID.
|
||||
*/
|
||||
rsn_pmkid(sm->PMK, PMK_LEN, sm->wpa_auth->addr,
|
||||
rsn_pmkid(sm->PMK, sm->pmk_len, sm->wpa_auth->addr,
|
||||
sm->addr, &pmkid[2 + RSN_SELECTOR_LEN],
|
||||
wpa_key_mgmt_sha256(sm->wpa_key_mgmt));
|
||||
}
|
||||
@ -2023,14 +2048,15 @@ SM_STATE(WPA_PTK, PTKSTART)
|
||||
|
||||
|
||||
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
|
||||
const u8 *pmk, struct wpa_ptk *ptk)
|
||||
const u8 *pmk, unsigned int pmk_len,
|
||||
struct wpa_ptk *ptk)
|
||||
{
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt))
|
||||
return wpa_auth_derive_ptk_ft(sm, pmk, ptk);
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
return wpa_pmk_to_ptk(pmk, PMK_LEN, "Pairwise key expansion",
|
||||
return wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion",
|
||||
sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce,
|
||||
ptk, sm->wpa_key_mgmt, sm->pairwise);
|
||||
}
|
||||
@ -2041,6 +2067,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
|
||||
struct wpa_ptk PTK;
|
||||
int ok = 0, psk_found = 0;
|
||||
const u8 *pmk = NULL;
|
||||
unsigned int pmk_len;
|
||||
|
||||
SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);
|
||||
sm->EAPOLKeyReceived = FALSE;
|
||||
@ -2056,10 +2083,13 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
|
||||
if (pmk == NULL)
|
||||
break;
|
||||
psk_found = 1;
|
||||
} else
|
||||
pmk_len = PMK_LEN;
|
||||
} else {
|
||||
pmk = sm->PMK;
|
||||
pmk_len = sm->pmk_len;
|
||||
}
|
||||
|
||||
wpa_derive_ptk(sm, sm->SNonce, pmk, &PTK);
|
||||
wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK);
|
||||
|
||||
if (wpa_verify_key_mic(sm->wpa_key_mgmt, &PTK,
|
||||
sm->last_rx_eapol_key,
|
||||
@ -2109,6 +2139,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
|
||||
* state machine data based on whatever PSK was selected here.
|
||||
*/
|
||||
os_memcpy(sm->PMK, pmk, PMK_LEN);
|
||||
sm->pmk_len = PMK_LEN;
|
||||
}
|
||||
|
||||
sm->MICVerified = TRUE;
|
||||
@ -2287,14 +2318,19 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
|
||||
pos += wpa_ie_len;
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
|
||||
int res = wpa_insert_pmkid(kde, pos - kde, sm->pmk_r1_name);
|
||||
int res;
|
||||
size_t elen;
|
||||
|
||||
elen = pos - kde;
|
||||
res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name);
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_ERROR, "FT: Failed to insert "
|
||||
"PMKR1Name into RSN IE in EAPOL-Key data");
|
||||
os_free(kde);
|
||||
return;
|
||||
}
|
||||
pos += res;
|
||||
pos -= wpa_ie_len;
|
||||
pos += elen;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
if (gtk) {
|
||||
@ -2312,10 +2348,18 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
|
||||
struct wpa_auth_config *conf;
|
||||
|
||||
conf = &sm->wpa_auth->conf;
|
||||
res = wpa_write_ftie(conf, conf->r0_key_holder,
|
||||
conf->r0_key_holder_len,
|
||||
NULL, NULL, pos, kde + kde_len - pos,
|
||||
NULL, 0);
|
||||
if (sm->assoc_resp_ftie &&
|
||||
kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) {
|
||||
os_memcpy(pos, sm->assoc_resp_ftie,
|
||||
2 + sm->assoc_resp_ftie[1]);
|
||||
res = 2 + sm->assoc_resp_ftie[1];
|
||||
} else {
|
||||
res = wpa_write_ftie(conf, conf->r0_key_holder,
|
||||
conf->r0_key_holder_len,
|
||||
NULL, NULL, pos,
|
||||
kde + kde_len - pos,
|
||||
NULL, 0);
|
||||
}
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE "
|
||||
"into EAPOL-Key Key Data");
|
||||
@ -3271,13 +3315,21 @@ const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, size_t *len)
|
||||
|
||||
|
||||
int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
|
||||
unsigned int pmk_len,
|
||||
int session_timeout, struct eapol_state_machine *eapol)
|
||||
{
|
||||
if (sm == NULL || sm->wpa != WPA_VERSION_WPA2 ||
|
||||
sm->wpa_auth->conf.disable_pmksa_caching)
|
||||
return -1;
|
||||
|
||||
if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, PMK_LEN,
|
||||
if (sm->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
|
||||
if (pmk_len > PMK_LEN_SUITE_B_192)
|
||||
pmk_len = PMK_LEN_SUITE_B_192;
|
||||
} else if (pmk_len > PMK_LEN) {
|
||||
pmk_len = PMK_LEN;
|
||||
}
|
||||
|
||||
if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, pmk_len, NULL,
|
||||
sm->PTK.kck, sm->PTK.kck_len,
|
||||
sm->wpa_auth->addr, sm->addr, session_timeout,
|
||||
eapol, sm->wpa_key_mgmt))
|
||||
@ -3295,7 +3347,7 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
|
||||
if (wpa_auth == NULL)
|
||||
return -1;
|
||||
|
||||
if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len,
|
||||
if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len, NULL,
|
||||
NULL, 0,
|
||||
wpa_auth->addr,
|
||||
sta_addr, session_timeout, eapol,
|
||||
@ -3307,12 +3359,12 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
|
||||
|
||||
|
||||
int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
|
||||
const u8 *pmk)
|
||||
const u8 *pmk, const u8 *pmkid)
|
||||
{
|
||||
if (wpa_auth->conf.disable_pmksa_caching)
|
||||
return -1;
|
||||
|
||||
if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, PMK_LEN,
|
||||
if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, PMK_LEN, pmkid,
|
||||
NULL, 0,
|
||||
wpa_auth->addr, addr, 0, NULL,
|
||||
WPA_KEY_MGMT_SAE))
|
||||
@ -3338,6 +3390,46 @@ void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
|
||||
}
|
||||
|
||||
|
||||
int wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf,
|
||||
size_t len)
|
||||
{
|
||||
if (!wpa_auth || !wpa_auth->pmksa)
|
||||
return 0;
|
||||
return pmksa_cache_auth_list(wpa_auth->pmksa, buf, len);
|
||||
}
|
||||
|
||||
|
||||
void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth)
|
||||
{
|
||||
if (wpa_auth && wpa_auth->pmksa)
|
||||
pmksa_cache_auth_flush(wpa_auth->pmksa);
|
||||
}
|
||||
|
||||
|
||||
struct rsn_pmksa_cache_entry *
|
||||
wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr)
|
||||
{
|
||||
if (!wpa_auth || !wpa_auth->pmksa)
|
||||
return NULL;
|
||||
return pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL);
|
||||
}
|
||||
|
||||
|
||||
void wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa,
|
||||
struct wpa_state_machine *sm,
|
||||
struct wpa_authenticator *wpa_auth,
|
||||
u8 *pmkid, u8 *pmk)
|
||||
{
|
||||
if (!sm)
|
||||
return;
|
||||
|
||||
sm->pmksa = pmksa;
|
||||
os_memcpy(pmk, pmksa->pmk, PMK_LEN);
|
||||
os_memcpy(pmkid, pmksa->pmkid, PMKID_LEN);
|
||||
os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmksa->pmkid, PMKID_LEN);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Remove and free the group from wpa_authenticator. This is triggered by a
|
||||
* callback to make sure nobody is currently iterating the group list while it
|
||||
@ -3416,6 +3508,98 @@ wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Enforce that the group state machine for the VLAN is running, increase
|
||||
* reference counter as interface is up. References might have been increased
|
||||
* even if a negative value is returned.
|
||||
* Returns: -1 on error (group missing, group already failed); otherwise, 0
|
||||
*/
|
||||
int wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id)
|
||||
{
|
||||
struct wpa_group *group;
|
||||
|
||||
if (wpa_auth == NULL)
|
||||
return 0;
|
||||
|
||||
group = wpa_auth->group;
|
||||
while (group) {
|
||||
if (group->vlan_id == vlan_id)
|
||||
break;
|
||||
group = group->next;
|
||||
}
|
||||
|
||||
if (group == NULL) {
|
||||
group = wpa_auth_add_group(wpa_auth, vlan_id);
|
||||
if (group == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"WPA: Ensure group state machine running for VLAN ID %d",
|
||||
vlan_id);
|
||||
|
||||
wpa_group_get(wpa_auth, group);
|
||||
group->num_setup_iface++;
|
||||
|
||||
if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decrease reference counter, expected to be zero afterwards.
|
||||
* returns: -1 on error (group not found, group in fail state)
|
||||
* -2 if wpa_group is still referenced
|
||||
* 0 else
|
||||
*/
|
||||
int wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id)
|
||||
{
|
||||
struct wpa_group *group;
|
||||
int ret = 0;
|
||||
|
||||
if (wpa_auth == NULL)
|
||||
return 0;
|
||||
|
||||
group = wpa_auth->group;
|
||||
while (group) {
|
||||
if (group->vlan_id == vlan_id)
|
||||
break;
|
||||
group = group->next;
|
||||
}
|
||||
|
||||
if (group == NULL)
|
||||
return -1;
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"WPA: Try stopping group state machine for VLAN ID %d",
|
||||
vlan_id);
|
||||
|
||||
if (group->num_setup_iface <= 0) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"WPA: wpa_auth_release_group called more often than wpa_auth_ensure_group for VLAN ID %d, skipping.",
|
||||
vlan_id);
|
||||
return -1;
|
||||
}
|
||||
group->num_setup_iface--;
|
||||
|
||||
if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE)
|
||||
ret = -1;
|
||||
|
||||
if (group->references > 1) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"WPA: Cannot stop group state machine for VLAN ID %d as references are still hold",
|
||||
vlan_id);
|
||||
ret = -2;
|
||||
}
|
||||
|
||||
wpa_group_put(wpa_auth, group);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id)
|
||||
{
|
||||
struct wpa_group *group;
|
||||
|
@ -42,10 +42,11 @@ struct ft_rrb_frame {
|
||||
#define FT_PACKET_R0KH_R1KH_RESP 201
|
||||
#define FT_PACKET_R0KH_R1KH_PUSH 202
|
||||
|
||||
#define FT_R0KH_R1KH_PULL_DATA_LEN 44
|
||||
#define FT_R0KH_R1KH_RESP_DATA_LEN 76
|
||||
#define FT_R0KH_R1KH_PUSH_DATA_LEN 88
|
||||
#define FT_R0KH_R1KH_PULL_NONCE_LEN 16
|
||||
#define FT_R0KH_R1KH_PULL_DATA_LEN (FT_R0KH_R1KH_PULL_NONCE_LEN + \
|
||||
WPA_PMK_NAME_LEN + FT_R1KH_ID_LEN + \
|
||||
ETH_ALEN)
|
||||
#define FT_R0KH_R1KH_PULL_PAD_LEN ((8 - FT_R0KH_R1KH_PULL_DATA_LEN % 8) % 8)
|
||||
|
||||
struct ft_r0kh_r1kh_pull_frame {
|
||||
u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
|
||||
@ -57,14 +58,18 @@ struct ft_r0kh_r1kh_pull_frame {
|
||||
u8 pmk_r0_name[WPA_PMK_NAME_LEN];
|
||||
u8 r1kh_id[FT_R1KH_ID_LEN];
|
||||
u8 s1kh_id[ETH_ALEN];
|
||||
u8 pad[4]; /* 8-octet boundary for AES key wrap */
|
||||
u8 pad[FT_R0KH_R1KH_PULL_PAD_LEN]; /* 8-octet boundary for AES block */
|
||||
u8 key_wrap_extra[8];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define FT_R0KH_R1KH_RESP_DATA_LEN (FT_R0KH_R1KH_PULL_NONCE_LEN + \
|
||||
FT_R1KH_ID_LEN + ETH_ALEN + PMK_LEN + \
|
||||
WPA_PMK_NAME_LEN + 2)
|
||||
#define FT_R0KH_R1KH_RESP_PAD_LEN ((8 - FT_R0KH_R1KH_RESP_DATA_LEN % 8) % 8)
|
||||
struct ft_r0kh_r1kh_resp_frame {
|
||||
u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
|
||||
u8 packet_type; /* FT_PACKET_R0KH_R1KH_RESP */
|
||||
le16 data_length; /* little endian length of data (76) */
|
||||
le16 data_length; /* little endian length of data (78) */
|
||||
u8 ap_address[ETH_ALEN];
|
||||
|
||||
u8 nonce[FT_R0KH_R1KH_PULL_NONCE_LEN]; /* copied from pull */
|
||||
@ -73,14 +78,18 @@ struct ft_r0kh_r1kh_resp_frame {
|
||||
u8 pmk_r1[PMK_LEN];
|
||||
u8 pmk_r1_name[WPA_PMK_NAME_LEN];
|
||||
le16 pairwise;
|
||||
u8 pad[2]; /* 8-octet boundary for AES key wrap */
|
||||
u8 pad[FT_R0KH_R1KH_RESP_PAD_LEN]; /* 8-octet boundary for AES block */
|
||||
u8 key_wrap_extra[8];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define FT_R0KH_R1KH_PUSH_DATA_LEN (4 + FT_R1KH_ID_LEN + ETH_ALEN + \
|
||||
WPA_PMK_NAME_LEN + PMK_LEN + \
|
||||
WPA_PMK_NAME_LEN + 2)
|
||||
#define FT_R0KH_R1KH_PUSH_PAD_LEN ((8 - FT_R0KH_R1KH_PUSH_DATA_LEN % 8) % 8)
|
||||
struct ft_r0kh_r1kh_push_frame {
|
||||
u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
|
||||
u8 packet_type; /* FT_PACKET_R0KH_R1KH_PUSH */
|
||||
le16 data_length; /* little endian length of data (88) */
|
||||
le16 data_length; /* little endian length of data (82) */
|
||||
u8 ap_address[ETH_ALEN];
|
||||
|
||||
/* Encrypted with AES key-wrap */
|
||||
@ -92,7 +101,7 @@ struct ft_r0kh_r1kh_push_frame {
|
||||
u8 pmk_r1[PMK_LEN];
|
||||
u8 pmk_r1_name[WPA_PMK_NAME_LEN];
|
||||
le16 pairwise;
|
||||
u8 pad[6]; /* 8-octet boundary for AES key wrap */
|
||||
u8 pad[FT_R0KH_R1KH_PUSH_PAD_LEN]; /* 8-octet boundary for AES block */
|
||||
u8 key_wrap_extra[8];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
@ -258,7 +267,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
|
||||
u8 *data, size_t data_len);
|
||||
enum wpa_event {
|
||||
WPA_AUTH, WPA_ASSOC, WPA_DISASSOC, WPA_DEAUTH, WPA_REAUTH,
|
||||
WPA_REAUTH_EAPOL, WPA_ASSOC_FT
|
||||
WPA_REAUTH_EAPOL, WPA_ASSOC_FT, WPA_DRV_STA_REMOVED
|
||||
};
|
||||
void wpa_remove_ptk(struct wpa_state_machine *sm);
|
||||
int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event);
|
||||
@ -280,15 +289,25 @@ void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm);
|
||||
const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||
size_t *len);
|
||||
int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
|
||||
unsigned int pmk_len,
|
||||
int session_timeout, struct eapol_state_machine *eapol);
|
||||
int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
|
||||
const u8 *pmk, size_t len, const u8 *sta_addr,
|
||||
int session_timeout,
|
||||
struct eapol_state_machine *eapol);
|
||||
int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
|
||||
const u8 *pmk);
|
||||
const u8 *pmk, const u8 *pmkid);
|
||||
void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
|
||||
const u8 *sta_addr);
|
||||
int wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf,
|
||||
size_t len);
|
||||
void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth);
|
||||
struct rsn_pmksa_cache_entry *
|
||||
wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr);
|
||||
void wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa,
|
||||
struct wpa_state_machine *sm,
|
||||
struct wpa_authenticator *wpa_auth,
|
||||
u8 *pmkid, u8 *pmk);
|
||||
int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id);
|
||||
void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm, int ack);
|
||||
@ -326,4 +345,7 @@ int wpa_auth_radius_das_disconnect_pmksa(struct wpa_authenticator *wpa_auth,
|
||||
struct radius_das_attrs *attr);
|
||||
void wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth);
|
||||
|
||||
int wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id);
|
||||
int wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id);
|
||||
|
||||
#endif /* WPA_AUTH_H */
|
||||
|
@ -722,11 +722,6 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
||||
ftie_len = res;
|
||||
pos += res;
|
||||
|
||||
os_free(sm->assoc_resp_ftie);
|
||||
sm->assoc_resp_ftie = os_malloc(ftie_len);
|
||||
if (sm->assoc_resp_ftie)
|
||||
os_memcpy(sm->assoc_resp_ftie, ftie, ftie_len);
|
||||
|
||||
_ftie = (struct rsn_ftie *) (ftie + 2);
|
||||
if (auth_alg == WLAN_AUTH_FT)
|
||||
_ftie->mic_control[1] = 3; /* Information element count */
|
||||
@ -752,6 +747,11 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
||||
_ftie->mic) < 0)
|
||||
wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
|
||||
|
||||
os_free(sm->assoc_resp_ftie);
|
||||
sm->assoc_resp_ftie = os_malloc(ftie_len);
|
||||
if (sm->assoc_resp_ftie)
|
||||
os_memcpy(sm->assoc_resp_ftie, ftie, ftie_len);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,8 @@ struct wpa_state_machine {
|
||||
u8 SNonce[WPA_NONCE_LEN];
|
||||
u8 alt_SNonce[WPA_NONCE_LEN];
|
||||
u8 alt_replay_counter[WPA_REPLAY_COUNTER_LEN];
|
||||
u8 PMK[PMK_LEN];
|
||||
u8 PMK[PMK_LEN_MAX];
|
||||
unsigned int pmk_len;
|
||||
struct wpa_ptk PTK;
|
||||
Boolean PTK_valid;
|
||||
Boolean pairwise_set;
|
||||
@ -172,6 +173,7 @@ struct wpa_group {
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
/* Number of references except those in struct wpa_group->next */
|
||||
unsigned int references;
|
||||
unsigned int num_setup_iface;
|
||||
};
|
||||
|
||||
|
||||
|
175
freebsd/contrib/wpa/src/common/ctrl_iface_common.c
Normal file
175
freebsd/contrib/wpa/src/common/ctrl_iface_common.c
Normal file
@ -0,0 +1,175 @@
|
||||
#include <machine/rtems-bsd-user-space.h>
|
||||
|
||||
/*
|
||||
* Common hostapd/wpa_supplicant ctrl iface code.
|
||||
* Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2015, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
#include <netdb.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "ctrl_iface_common.h"
|
||||
|
||||
static int sockaddr_compare(struct sockaddr_storage *a, socklen_t a_len,
|
||||
struct sockaddr_storage *b, socklen_t b_len)
|
||||
{
|
||||
if (a->ss_family != b->ss_family)
|
||||
return 1;
|
||||
|
||||
switch (a->ss_family) {
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in *in_a, *in_b;
|
||||
|
||||
in_a = (struct sockaddr_in *) a;
|
||||
in_b = (struct sockaddr_in *) b;
|
||||
|
||||
if (in_a->sin_port != in_b->sin_port)
|
||||
return 1;
|
||||
if (in_a->sin_addr.s_addr != in_b->sin_addr.s_addr)
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6 *in6_a, *in6_b;
|
||||
|
||||
in6_a = (struct sockaddr_in6 *) a;
|
||||
in6_b = (struct sockaddr_in6 *) b;
|
||||
|
||||
if (in6_a->sin6_port != in6_b->sin6_port)
|
||||
return 1;
|
||||
if (os_memcmp(&in6_a->sin6_addr, &in6_b->sin6_addr,
|
||||
sizeof(in6_a->sin6_addr)) != 0)
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP */
|
||||
#ifdef CONFIG_CTRL_IFACE_UNIX
|
||||
case AF_UNIX:
|
||||
{
|
||||
struct sockaddr_un *u_a, *u_b;
|
||||
|
||||
u_a = (struct sockaddr_un *) a;
|
||||
u_b = (struct sockaddr_un *) b;
|
||||
|
||||
if (a_len != b_len ||
|
||||
os_memcmp(u_a->sun_path, u_b->sun_path,
|
||||
a_len - offsetof(struct sockaddr_un, sun_path))
|
||||
!= 0)
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
#endif /* CONFIG_CTRL_IFACE_UNIX */
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void sockaddr_print(int level, const char *msg, struct sockaddr_storage *sock,
|
||||
socklen_t socklen)
|
||||
{
|
||||
switch (sock->ss_family) {
|
||||
#ifdef CONFIG_CTRL_IFACE_UDP
|
||||
case AF_INET:
|
||||
case AF_INET6:
|
||||
{
|
||||
char host[NI_MAXHOST] = { 0 };
|
||||
char service[NI_MAXSERV] = { 0 };
|
||||
|
||||
getnameinfo((struct sockaddr *) sock, socklen,
|
||||
host, sizeof(host),
|
||||
service, sizeof(service),
|
||||
NI_NUMERICHOST);
|
||||
|
||||
wpa_printf(level, "%s %s:%s", msg, host, service);
|
||||
break;
|
||||
}
|
||||
#endif /* CONFIG_CTRL_IFACE_UDP */
|
||||
#ifdef CONFIG_CTRL_IFACE_UNIX
|
||||
case AF_UNIX:
|
||||
{
|
||||
char addr_txt[200];
|
||||
|
||||
printf_encode(addr_txt, sizeof(addr_txt),
|
||||
(u8 *) ((struct sockaddr_un *) sock)->sun_path,
|
||||
socklen - offsetof(struct sockaddr_un, sun_path));
|
||||
wpa_printf(level, "%s %s", msg, addr_txt);
|
||||
break;
|
||||
}
|
||||
#endif /* CONFIG_CTRL_IFACE_UNIX */
|
||||
default:
|
||||
wpa_printf(level, "%s", msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int ctrl_iface_attach(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
|
||||
socklen_t fromlen)
|
||||
{
|
||||
struct wpa_ctrl_dst *dst;
|
||||
|
||||
dst = os_zalloc(sizeof(*dst));
|
||||
if (dst == NULL)
|
||||
return -1;
|
||||
os_memcpy(&dst->addr, from, fromlen);
|
||||
dst->addrlen = fromlen;
|
||||
dst->debug_level = MSG_INFO;
|
||||
dl_list_add(ctrl_dst, &dst->list);
|
||||
|
||||
sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor attached", from, fromlen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ctrl_iface_detach(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
|
||||
socklen_t fromlen)
|
||||
{
|
||||
struct wpa_ctrl_dst *dst;
|
||||
|
||||
dl_list_for_each(dst, ctrl_dst, struct wpa_ctrl_dst, list) {
|
||||
if (!sockaddr_compare(from, fromlen,
|
||||
&dst->addr, dst->addrlen)) {
|
||||
sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor detached",
|
||||
from, fromlen);
|
||||
dl_list_del(&dst->list);
|
||||
os_free(dst);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int ctrl_iface_level(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
|
||||
socklen_t fromlen, const char *level)
|
||||
{
|
||||
struct wpa_ctrl_dst *dst;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
|
||||
|
||||
dl_list_for_each(dst, ctrl_dst, struct wpa_ctrl_dst, list) {
|
||||
if (!sockaddr_compare(from, fromlen,
|
||||
&dst->addr, dst->addrlen)) {
|
||||
sockaddr_print(MSG_DEBUG,
|
||||
"CTRL_IFACE changed monitor level",
|
||||
from, fromlen);
|
||||
dst->debug_level = atoi(level);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
38
freebsd/contrib/wpa/src/common/ctrl_iface_common.h
Normal file
38
freebsd/contrib/wpa/src/common/ctrl_iface_common.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Common hostapd/wpa_supplicant ctrl iface code.
|
||||
* Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2015, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
#ifndef CONTROL_IFACE_COMMON_H
|
||||
#define CONTROL_IFACE_COMMON_H
|
||||
|
||||
#include "utils/list.h"
|
||||
|
||||
/**
|
||||
* struct wpa_ctrl_dst - Data structure of control interface monitors
|
||||
*
|
||||
* This structure is used to store information about registered control
|
||||
* interface monitors into struct wpa_supplicant.
|
||||
*/
|
||||
struct wpa_ctrl_dst {
|
||||
struct dl_list list;
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addrlen;
|
||||
int debug_level;
|
||||
int errors;
|
||||
};
|
||||
|
||||
void sockaddr_print(int level, const char *msg, struct sockaddr_storage *sock,
|
||||
socklen_t socklen);
|
||||
|
||||
int ctrl_iface_attach(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
|
||||
socklen_t fromlen);
|
||||
int ctrl_iface_detach(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
|
||||
socklen_t fromlen);
|
||||
int ctrl_iface_level(struct dl_list *ctrl_dst, struct sockaddr_storage *from,
|
||||
socklen_t fromlen, const char *level);
|
||||
|
||||
#endif /* CONTROL_IFACE_COMMON_H */
|
@ -312,6 +312,7 @@ enum wpa_ctrl_req_type {
|
||||
WPA_CTRL_REQ_EAP_PASSPHRASE,
|
||||
WPA_CTRL_REQ_SIM,
|
||||
WPA_CTRL_REQ_PSK_PASSPHRASE,
|
||||
WPA_CTRL_REQ_EXT_CERT_CHECK,
|
||||
NUM_WPA_CTRL_REQS
|
||||
};
|
||||
|
||||
@ -319,13 +320,13 @@ enum wpa_ctrl_req_type {
|
||||
#define EAP_MAX_METHODS 8
|
||||
|
||||
enum mesh_plink_state {
|
||||
PLINK_LISTEN = 1,
|
||||
PLINK_OPEN_SENT,
|
||||
PLINK_OPEN_RCVD,
|
||||
PLINK_IDLE = 1,
|
||||
PLINK_OPN_SNT,
|
||||
PLINK_OPN_RCVD,
|
||||
PLINK_CNF_RCVD,
|
||||
PLINK_ESTAB,
|
||||
PLINK_HOLDING,
|
||||
PLINK_BLOCKED,
|
||||
PLINK_BLOCKED, /* not defined in the IEEE 802.11 standard */
|
||||
};
|
||||
|
||||
enum set_band {
|
||||
@ -334,4 +335,10 @@ enum set_band {
|
||||
WPA_SETBAND_2G
|
||||
};
|
||||
|
||||
enum wpa_radio_work_band {
|
||||
BAND_2_4_GHZ = BIT(0),
|
||||
BAND_5_GHZ = BIT(1),
|
||||
BAND_60_GHZ = BIT(2),
|
||||
};
|
||||
|
||||
#endif /* DEFS_H */
|
||||
|
@ -25,7 +25,7 @@ struct ieee802_1x_hdr {
|
||||
struct ieee8023_hdr {
|
||||
u8 dest[ETH_ALEN];
|
||||
u8 src[ETH_ALEN];
|
||||
u16 ethertype;
|
||||
be16 ethertype;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
@ -117,6 +117,11 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
|
||||
elems->osen = pos;
|
||||
elems->osen_len = elen;
|
||||
break;
|
||||
case MBO_OUI_TYPE:
|
||||
/* MBO-OCE */
|
||||
elems->mbo = pos;
|
||||
elems->mbo_len = elen;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_MSGDUMP, "Unknown WFA "
|
||||
"information element ignored "
|
||||
@ -368,6 +373,14 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
|
||||
elems->mb_ies.ies[elems->mb_ies.nof_ies].ie_len = elen;
|
||||
elems->mb_ies.nof_ies++;
|
||||
break;
|
||||
case WLAN_EID_SUPPORTED_OPERATING_CLASSES:
|
||||
elems->supp_op_classes = pos;
|
||||
elems->supp_op_classes_len = elen;
|
||||
break;
|
||||
case WLAN_EID_RRM_ENABLED_CAPABILITIES:
|
||||
elems->rrm_enabled = pos;
|
||||
elems->rrm_enabled_len = elen;
|
||||
break;
|
||||
default:
|
||||
unknown++;
|
||||
if (!show_errors)
|
||||
@ -400,8 +413,8 @@ int ieee802_11_ie_count(const u8 *ies, size_t ies_len)
|
||||
pos = ies;
|
||||
end = ies + ies_len;
|
||||
|
||||
while (pos + 2 <= end) {
|
||||
if (pos + 2 + pos[1] > end)
|
||||
while (end - pos >= 2) {
|
||||
if (2 + pos[1] > end - pos)
|
||||
break;
|
||||
count++;
|
||||
pos += 2 + pos[1];
|
||||
@ -421,8 +434,8 @@ struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
|
||||
end = ies + ies_len;
|
||||
ie = NULL;
|
||||
|
||||
while (pos + 1 < end) {
|
||||
if (pos + 2 + pos[1] > end)
|
||||
while (end - pos > 1) {
|
||||
if (2 + pos[1] > end - pos)
|
||||
return NULL;
|
||||
if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
|
||||
WPA_GET_BE32(&pos[2]) == oui_type) {
|
||||
@ -443,8 +456,8 @@ struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
|
||||
* There may be multiple vendor IEs in the message, so need to
|
||||
* concatenate their data fields.
|
||||
*/
|
||||
while (pos + 1 < end) {
|
||||
if (pos + 2 + pos[1] > end)
|
||||
while (end - pos > 1) {
|
||||
if (2 + pos[1] > end - pos)
|
||||
break;
|
||||
if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
|
||||
WPA_GET_BE32(&pos[2]) == oui_type)
|
||||
@ -572,7 +585,8 @@ enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel)
|
||||
{
|
||||
u8 op_class;
|
||||
|
||||
return ieee80211_freq_to_channel_ext(freq, 0, 0, &op_class, channel);
|
||||
return ieee80211_freq_to_channel_ext(freq, 0, VHT_CHANWIDTH_USE_HT,
|
||||
&op_class, channel);
|
||||
}
|
||||
|
||||
|
||||
@ -581,7 +595,7 @@ enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel)
|
||||
* for HT40 and VHT. DFS channels are not covered.
|
||||
* @freq: Frequency (MHz) to convert
|
||||
* @sec_channel: 0 = non-HT40, 1 = sec. channel above, -1 = sec. channel below
|
||||
* @vht: 0 - non-VHT, 1 - 80 MHz
|
||||
* @vht: VHT channel width (VHT_CHANWIDTH_*)
|
||||
* @op_class: Buffer for returning operating class
|
||||
* @channel: Buffer for returning channel number
|
||||
* Returns: hw_mode on success, NUM_HOSTAPD_MODES on failure
|
||||
@ -590,6 +604,8 @@ enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
|
||||
int sec_channel, int vht,
|
||||
u8 *op_class, u8 *channel)
|
||||
{
|
||||
u8 vht_opclass;
|
||||
|
||||
/* TODO: more operating classes */
|
||||
|
||||
if (sec_channel > 1 || sec_channel < -1)
|
||||
@ -633,17 +649,32 @@ enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
|
||||
return HOSTAPD_MODE_IEEE80211A;
|
||||
}
|
||||
|
||||
switch (vht) {
|
||||
case VHT_CHANWIDTH_80MHZ:
|
||||
vht_opclass = 128;
|
||||
break;
|
||||
case VHT_CHANWIDTH_160MHZ:
|
||||
vht_opclass = 129;
|
||||
break;
|
||||
case VHT_CHANWIDTH_80P80MHZ:
|
||||
vht_opclass = 130;
|
||||
break;
|
||||
default:
|
||||
vht_opclass = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* 5 GHz, channels 36..48 */
|
||||
if (freq >= 5180 && freq <= 5240) {
|
||||
if ((freq - 5000) % 5)
|
||||
return NUM_HOSTAPD_MODES;
|
||||
|
||||
if (sec_channel == 1)
|
||||
if (vht_opclass)
|
||||
*op_class = vht_opclass;
|
||||
else if (sec_channel == 1)
|
||||
*op_class = 116;
|
||||
else if (sec_channel == -1)
|
||||
*op_class = 117;
|
||||
else if (vht)
|
||||
*op_class = 128;
|
||||
else
|
||||
*op_class = 115;
|
||||
|
||||
@ -652,31 +683,40 @@ enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
|
||||
return HOSTAPD_MODE_IEEE80211A;
|
||||
}
|
||||
|
||||
/* 5 GHz, channels 149..161 */
|
||||
if (freq >= 5745 && freq <= 5805) {
|
||||
if ((freq - 5000) % 5)
|
||||
return NUM_HOSTAPD_MODES;
|
||||
|
||||
if (sec_channel == 1)
|
||||
*op_class = 126;
|
||||
else if (sec_channel == -1)
|
||||
*op_class = 127;
|
||||
else if (vht)
|
||||
*op_class = 128;
|
||||
else
|
||||
*op_class = 124;
|
||||
|
||||
*channel = (freq - 5000) / 5;
|
||||
|
||||
return HOSTAPD_MODE_IEEE80211A;
|
||||
}
|
||||
|
||||
/* 5 GHz, channels 149..169 */
|
||||
if (freq >= 5745 && freq <= 5845) {
|
||||
if ((freq - 5000) % 5)
|
||||
return NUM_HOSTAPD_MODES;
|
||||
|
||||
*op_class = 125;
|
||||
if (vht_opclass)
|
||||
*op_class = vht_opclass;
|
||||
else if (sec_channel == 1)
|
||||
*op_class = 126;
|
||||
else if (sec_channel == -1)
|
||||
*op_class = 127;
|
||||
else if (freq <= 5805)
|
||||
*op_class = 124;
|
||||
else
|
||||
*op_class = 125;
|
||||
|
||||
*channel = (freq - 5000) / 5;
|
||||
|
||||
return HOSTAPD_MODE_IEEE80211A;
|
||||
}
|
||||
|
||||
/* 5 GHz, channels 100..140 */
|
||||
if (freq >= 5000 && freq <= 5700) {
|
||||
if ((freq - 5000) % 5)
|
||||
return NUM_HOSTAPD_MODES;
|
||||
|
||||
if (vht_opclass)
|
||||
*op_class = vht_opclass;
|
||||
else if (sec_channel == 1)
|
||||
*op_class = 122;
|
||||
else if (sec_channel == -1)
|
||||
*op_class = 123;
|
||||
else
|
||||
*op_class = 121;
|
||||
|
||||
*channel = (freq - 5000) / 5;
|
||||
|
||||
@ -1147,3 +1187,135 @@ struct wpabuf * mb_ies_by_info(struct mb_ies_info *info)
|
||||
|
||||
return mb_ies;
|
||||
}
|
||||
|
||||
|
||||
const struct oper_class_map global_op_class[] = {
|
||||
{ HOSTAPD_MODE_IEEE80211G, 81, 1, 13, 1, BW20, P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211G, 82, 14, 14, 1, BW20, NO_P2P_SUPP },
|
||||
|
||||
/* Do not enable HT40 on 2.4 GHz for P2P use for now */
|
||||
{ HOSTAPD_MODE_IEEE80211G, 83, 1, 9, 1, BW40PLUS, NO_P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211G, 84, 5, 13, 1, BW40MINUS, NO_P2P_SUPP },
|
||||
|
||||
{ HOSTAPD_MODE_IEEE80211A, 115, 36, 48, 4, BW20, P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211A, 116, 36, 44, 8, BW40PLUS, P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211A, 117, 40, 48, 8, BW40MINUS, P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211A, 118, 52, 64, 4, BW20, NO_P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211A, 119, 52, 60, 8, BW40PLUS, NO_P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211A, 120, 56, 64, 8, BW40MINUS, NO_P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211A, 121, 100, 140, 4, BW20, NO_P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211A, 122, 100, 132, 8, BW40PLUS, NO_P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211A, 123, 104, 136, 8, BW40MINUS, NO_P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211A, 124, 149, 161, 4, BW20, P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211A, 125, 149, 169, 4, BW20, P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211A, 126, 149, 157, 8, BW40PLUS, P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211A, 127, 153, 161, 8, BW40MINUS, P2P_SUPP },
|
||||
|
||||
/*
|
||||
* IEEE P802.11ac/D7.0 Table E-4 actually talks about channel center
|
||||
* frequency index 42, 58, 106, 122, 138, 155 with channel spacing of
|
||||
* 80 MHz, but currently use the following definition for simplicity
|
||||
* (these center frequencies are not actual channels, which makes
|
||||
* wpas_p2p_allow_channel() fail). wpas_p2p_verify_80mhz() should take
|
||||
* care of removing invalid channels.
|
||||
*/
|
||||
{ HOSTAPD_MODE_IEEE80211A, 128, 36, 161, 4, BW80, P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211A, 129, 50, 114, 16, BW160, P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211A, 130, 36, 161, 4, BW80P80, P2P_SUPP },
|
||||
{ HOSTAPD_MODE_IEEE80211AD, 180, 1, 4, 1, BW2160, P2P_SUPP },
|
||||
{ -1, 0, 0, 0, 0, BW20, NO_P2P_SUPP }
|
||||
};
|
||||
|
||||
|
||||
static enum phy_type ieee80211_phy_type_by_freq(int freq)
|
||||
{
|
||||
enum hostapd_hw_mode hw_mode;
|
||||
u8 channel;
|
||||
|
||||
hw_mode = ieee80211_freq_to_chan(freq, &channel);
|
||||
|
||||
switch (hw_mode) {
|
||||
case HOSTAPD_MODE_IEEE80211A:
|
||||
return PHY_TYPE_OFDM;
|
||||
case HOSTAPD_MODE_IEEE80211B:
|
||||
return PHY_TYPE_HRDSSS;
|
||||
case HOSTAPD_MODE_IEEE80211G:
|
||||
return PHY_TYPE_ERP;
|
||||
case HOSTAPD_MODE_IEEE80211AD:
|
||||
return PHY_TYPE_DMG;
|
||||
default:
|
||||
return PHY_TYPE_UNSPECIFIED;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/* ieee80211_get_phy_type - Derive the phy type by freq and bandwidth */
|
||||
enum phy_type ieee80211_get_phy_type(int freq, int ht, int vht)
|
||||
{
|
||||
if (vht)
|
||||
return PHY_TYPE_VHT;
|
||||
if (ht)
|
||||
return PHY_TYPE_HT;
|
||||
|
||||
return ieee80211_phy_type_by_freq(freq);
|
||||
}
|
||||
|
||||
|
||||
size_t global_op_class_size = ARRAY_SIZE(global_op_class);
|
||||
|
||||
|
||||
/**
|
||||
* get_ie - Fetch a specified information element from IEs buffer
|
||||
* @ies: Information elements buffer
|
||||
* @len: Information elements buffer length
|
||||
* @eid: Information element identifier (WLAN_EID_*)
|
||||
* Returns: Pointer to the information element (id field) or %NULL if not found
|
||||
*
|
||||
* This function returns the first matching information element in the IEs
|
||||
* buffer or %NULL in case the element is not found.
|
||||
*/
|
||||
const u8 * get_ie(const u8 *ies, size_t len, u8 eid)
|
||||
{
|
||||
const u8 *end;
|
||||
|
||||
if (!ies)
|
||||
return NULL;
|
||||
|
||||
end = ies + len;
|
||||
|
||||
while (end - ies > 1) {
|
||||
if (2 + ies[1] > end - ies)
|
||||
break;
|
||||
|
||||
if (ies[0] == eid)
|
||||
return ies;
|
||||
|
||||
ies += 2 + ies[1];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len)
|
||||
{
|
||||
/*
|
||||
* MBO IE requires 6 bytes without the attributes: EID (1), length (1),
|
||||
* OUI (3), OUI type (1).
|
||||
*/
|
||||
if (len < 6 + attr_len) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"MBO: Not enough room in buffer for MBO IE: buf len = %zu, attr_len = %zu",
|
||||
len, attr_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*buf++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
*buf++ = attr_len + 4;
|
||||
WPA_PUT_BE24(buf, OUI_WFA);
|
||||
buf += 3;
|
||||
*buf++ = MBO_OUI_TYPE;
|
||||
os_memcpy(buf, attr, attr_len);
|
||||
|
||||
return 6 + attr_len;
|
||||
}
|
||||
|
@ -9,6 +9,8 @@
|
||||
#ifndef IEEE802_11_COMMON_H
|
||||
#define IEEE802_11_COMMON_H
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#define MAX_NOF_MB_IES_SUPPORTED 5
|
||||
|
||||
struct mb_ies_info {
|
||||
@ -56,9 +58,12 @@ struct ieee802_11_elems {
|
||||
const u8 *bss_max_idle_period;
|
||||
const u8 *ssid_list;
|
||||
const u8 *osen;
|
||||
const u8 *mbo;
|
||||
const u8 *ampe;
|
||||
const u8 *mic;
|
||||
const u8 *pref_freq_list;
|
||||
const u8 *supp_op_classes;
|
||||
const u8 *rrm_enabled;
|
||||
|
||||
u8 ssid_len;
|
||||
u8 supp_rates_len;
|
||||
@ -85,9 +90,13 @@ struct ieee802_11_elems {
|
||||
u8 ext_capab_len;
|
||||
u8 ssid_list_len;
|
||||
u8 osen_len;
|
||||
u8 mbo_len;
|
||||
u8 ampe_len;
|
||||
u8 mic_len;
|
||||
u8 pref_freq_list_len;
|
||||
u8 supp_op_classes_len;
|
||||
u8 rrm_enabled_len;
|
||||
|
||||
struct mb_ies_info mb_ies;
|
||||
};
|
||||
|
||||
@ -118,6 +127,7 @@ enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
|
||||
int sec_channel, int vht,
|
||||
u8 *op_class, u8 *channel);
|
||||
int ieee80211_is_dfs(int freq);
|
||||
enum phy_type ieee80211_get_phy_type(int freq, int ht, int vht);
|
||||
|
||||
int supp_rates_11b_only(struct ieee802_11_elems *elems);
|
||||
int mb_ies_info_by_ies(struct mb_ies_info *info, const u8 *ies_buf,
|
||||
@ -125,4 +135,22 @@ int mb_ies_info_by_ies(struct mb_ies_info *info, const u8 *ies_buf,
|
||||
struct wpabuf * mb_ies_by_info(struct mb_ies_info *info);
|
||||
|
||||
const char * fc2str(u16 fc);
|
||||
|
||||
struct oper_class_map {
|
||||
enum hostapd_hw_mode mode;
|
||||
u8 op_class;
|
||||
u8 min_chan;
|
||||
u8 max_chan;
|
||||
u8 inc;
|
||||
enum { BW20, BW40PLUS, BW40MINUS, BW80, BW2160, BW160, BW80P80 } bw;
|
||||
enum { P2P_SUPP, NO_P2P_SUPP } p2p;
|
||||
};
|
||||
|
||||
extern const struct oper_class_map global_op_class[];
|
||||
extern size_t global_op_class_size;
|
||||
|
||||
const u8 * get_ie(const u8 *ies, size_t len, u8 eid);
|
||||
|
||||
size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len);
|
||||
|
||||
#endif /* IEEE802_11_COMMON_H */
|
||||
|
@ -94,8 +94,13 @@
|
||||
#define WLAN_CAPABILITY_PBCC BIT(6)
|
||||
#define WLAN_CAPABILITY_CHANNEL_AGILITY BIT(7)
|
||||
#define WLAN_CAPABILITY_SPECTRUM_MGMT BIT(8)
|
||||
#define WLAN_CAPABILITY_QOS BIT(9)
|
||||
#define WLAN_CAPABILITY_SHORT_SLOT_TIME BIT(10)
|
||||
#define WLAN_CAPABILITY_APSD BIT(11)
|
||||
#define WLAN_CAPABILITY_RADIO_MEASUREMENT BIT(12)
|
||||
#define WLAN_CAPABILITY_DSSS_OFDM BIT(13)
|
||||
#define WLAN_CAPABILITY_DELAYED_BLOCK_ACK BIT(14)
|
||||
#define WLAN_CAPABILITY_IMM_BLOCK_ACK BIT(15)
|
||||
|
||||
/* Status codes (IEEE 802.11-2007, 7.3.1.9, Table 7-23) */
|
||||
#define WLAN_STATUS_SUCCESS 0
|
||||
@ -247,6 +252,7 @@
|
||||
#define WLAN_EID_TIMEOUT_INTERVAL 56
|
||||
#define WLAN_EID_RIC_DATA 57
|
||||
#define WLAN_EID_SUPPORTED_OPERATING_CLASSES 59
|
||||
#define WLAN_EID_EXT_CHANSWITCH_ANN 60
|
||||
#define WLAN_EID_HT_OPERATION 61
|
||||
#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
|
||||
#define WLAN_EID_WAPI 68
|
||||
@ -360,6 +366,16 @@
|
||||
/* byte 1 (out of 5) */
|
||||
#define WLAN_RRM_CAPS_LINK_MEASUREMENT BIT(0)
|
||||
#define WLAN_RRM_CAPS_NEIGHBOR_REPORT BIT(1)
|
||||
/* byte 2 (out of 5) */
|
||||
#define WLAN_RRM_CAPS_LCI_MEASUREMENT BIT(4)
|
||||
/* byte 5 (out of 5) */
|
||||
#define WLAN_RRM_CAPS_FTM_RANGE_REPORT BIT(2)
|
||||
|
||||
/*
|
||||
* IEEE P802.11-REVmc/D5.0, 9.4.2.21.19 (Fine Timing Measurement Range
|
||||
* request) - Minimum AP count
|
||||
*/
|
||||
#define WLAN_RRM_RANGE_REQ_MAX_MIN_AP 15
|
||||
|
||||
/* Timeout Interval Type */
|
||||
#define WLAN_TIMEOUT_REASSOC_DEADLINE 1
|
||||
@ -407,7 +423,12 @@ enum anqp_info_id {
|
||||
ANQP_AP_LOCATION_PUBLIC_URI = 267,
|
||||
ANQP_DOMAIN_NAME = 268,
|
||||
ANQP_EMERGENCY_ALERT_URI = 269,
|
||||
ANQP_TDLS_CAPABILITY = 270,
|
||||
ANQP_EMERGENCY_NAI = 271,
|
||||
ANQP_NEIGHBOR_REPORT = 272,
|
||||
ANQP_VENUE_URL = 277,
|
||||
ANQP_ADVICE_OF_CHARGE = 278,
|
||||
ANQP_LOCAL_CONTENT = 279,
|
||||
ANQP_VENDOR_SPECIFIC = 56797
|
||||
};
|
||||
|
||||
@ -442,6 +463,48 @@ enum nai_realm_eap_cred_type {
|
||||
NAI_REALM_CRED_TYPE_VENDOR_SPECIFIC = 10
|
||||
};
|
||||
|
||||
/*
|
||||
* IEEE P802.11-REVmc/D5.0 Table 9-81 - Measurement type definitions for
|
||||
* measurement requests
|
||||
*/
|
||||
enum measure_type {
|
||||
MEASURE_TYPE_BASIC = 0,
|
||||
MEASURE_TYPE_CCA = 1,
|
||||
MEASURE_TYPE_RPI_HIST = 2,
|
||||
MEASURE_TYPE_CHANNEL_LOAD = 3,
|
||||
MEASURE_TYPE_NOISE_HIST = 4,
|
||||
MEASURE_TYPE_BEACON = 5,
|
||||
MEASURE_TYPE_FRAME = 6,
|
||||
MEASURE_TYPE_STA_STATISTICS = 7,
|
||||
MEASURE_TYPE_LCI = 8,
|
||||
MEASURE_TYPE_TRANSMIT_STREAM = 9,
|
||||
MEASURE_TYPE_MULTICAST_DIAG = 10,
|
||||
MEASURE_TYPE_LOCATION_CIVIC = 11,
|
||||
MEASURE_TYPE_LOCATION_ID = 12,
|
||||
MEASURE_TYPE_DIRECTIONAL_CHAN_QUALITY = 13,
|
||||
MEASURE_TYPE_DIRECTIONAL_MEASURE = 14,
|
||||
MEASURE_TYPE_DIRECTIONAL_STATS = 15,
|
||||
MEASURE_TYPE_FTM_RANGE = 16,
|
||||
MEASURE_TYPE_MEASURE_PAUSE = 255,
|
||||
};
|
||||
|
||||
/* IEEE Std 802.11-2012 Table 8-71 - Location subject definition */
|
||||
enum location_subject {
|
||||
LOCATION_SUBJECT_LOCAL = 0,
|
||||
LOCATION_SUBJECT_REMOTE = 1,
|
||||
LOCATION_SUBJECT_3RD_PARTY = 2,
|
||||
};
|
||||
|
||||
/*
|
||||
* IEEE P802.11-REVmc/D5.0 Table 9-94 - Optional subelement IDs for LCI request
|
||||
*/
|
||||
enum lci_req_subelem {
|
||||
LCI_REQ_SUBELEM_AZIMUTH_REQ = 1,
|
||||
LCI_REQ_SUBELEM_ORIGINATOR_MAC_ADDR = 2,
|
||||
LCI_REQ_SUBELEM_TARGET_MAC_ADDR = 3,
|
||||
LCI_REQ_SUBELEM_MAX_AGE = 4,
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 1)
|
||||
#endif /* _MSC_VER */
|
||||
@ -516,10 +579,7 @@ struct ieee80211_mgmt {
|
||||
* FH Params, DS Params, CF Params, IBSS Params, TIM */
|
||||
u8 variable[];
|
||||
} STRUCT_PACKED beacon;
|
||||
struct {
|
||||
/* only variable items: SSID, Supported rates */
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED probe_req;
|
||||
/* probe_req: only variable items: SSID, Supported rates */
|
||||
struct {
|
||||
u8 timestamp[8];
|
||||
le16 beacon_int;
|
||||
@ -625,12 +685,19 @@ struct ieee80211_mgmt {
|
||||
u8 action;
|
||||
u8 variable[];
|
||||
} STRUCT_PACKED fst_action;
|
||||
struct {
|
||||
u8 action;
|
||||
u8 dialog_token;
|
||||
u8 variable[];
|
||||
} STRUCT_PACKED rrm;
|
||||
} u;
|
||||
} STRUCT_PACKED action;
|
||||
} u;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
|
||||
#define IEEE80211_MAX_MMPDU_SIZE 2304
|
||||
|
||||
/* Rx MCS bitmask is in the first 77 bits of supported_mcs_set */
|
||||
#define IEEE80211_HT_MCS_MASK_LEN 10
|
||||
|
||||
@ -690,9 +757,14 @@ struct ieee80211_ampe_ie {
|
||||
u8 selected_pairwise_suite[4];
|
||||
u8 local_nonce[32];
|
||||
u8 peer_nonce[32];
|
||||
u8 mgtk[16];
|
||||
u8 key_rsc[8];
|
||||
u8 key_expiration[4];
|
||||
/* Followed by
|
||||
* Key Replay Counter[8] (optional)
|
||||
* (only in Mesh Group Key Inform/Acknowledge frames)
|
||||
* GTKdata[variable] (optional)
|
||||
* (MGTK[variable] || Key RSC[8] || GTKExpirationTime[4])
|
||||
* IGTKdata[variable] (optional)
|
||||
* (Key ID[2], IPN[6], IGTK[variable] in IGTK KDE format)
|
||||
*/
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@ -879,6 +951,8 @@ struct ieee80211_ampe_ie {
|
||||
#define WFD_OUI_TYPE 10
|
||||
#define HS20_IE_VENDOR_TYPE 0x506f9a10
|
||||
#define OSEN_IE_VENDOR_TYPE 0x506f9a12
|
||||
#define MBO_IE_VENDOR_TYPE 0x506f9a16
|
||||
#define MBO_OUI_TYPE 22
|
||||
|
||||
#define WMM_OUI_TYPE 2
|
||||
#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0
|
||||
@ -1021,6 +1095,95 @@ enum wmm_ac {
|
||||
#define HS20_DEAUTH_REASON_CODE_BSS 0
|
||||
#define HS20_DEAUTH_REASON_CODE_ESS 1
|
||||
|
||||
/* MBO v0.0_r19, 4.2: MBO Attributes */
|
||||
/* Table 4-5: MBO Attributes */
|
||||
enum mbo_attr_id {
|
||||
MBO_ATTR_ID_AP_CAPA_IND = 1,
|
||||
MBO_ATTR_ID_NON_PREF_CHAN_REPORT = 2,
|
||||
MBO_ATTR_ID_CELL_DATA_CAPA = 3,
|
||||
MBO_ATTR_ID_ASSOC_DISALLOW = 4,
|
||||
MBO_ATTR_ID_CELL_DATA_PREF = 5,
|
||||
MBO_ATTR_ID_TRANSITION_REASON = 6,
|
||||
MBO_ATTR_ID_TRANSITION_REJECT_REASON = 7,
|
||||
MBO_ATTR_ID_ASSOC_RETRY_DELAY = 8,
|
||||
};
|
||||
|
||||
/* MBO v0.0_r19, 4.2.1: MBO AP Capability Indication Attribute */
|
||||
/* Table 4-7: MBO AP Capability Indication Field Values */
|
||||
#define MBO_AP_CAPA_CELL_AWARE BIT(6)
|
||||
|
||||
/* MBO v0.0_r19, 4.2.2: Non-preferred Channel Report Attribute */
|
||||
/* Table 4-10: Reason Code Field Values */
|
||||
enum mbo_non_pref_chan_reason {
|
||||
MBO_NON_PREF_CHAN_REASON_UNSPECIFIED = 0,
|
||||
MBO_NON_PREF_CHAN_REASON_RSSI = 1,
|
||||
MBO_NON_PREF_CHAN_REASON_EXT_INTERFERENCE = 2,
|
||||
MBO_NON_PREF_CHAN_REASON_INT_INTERFERENCE = 3,
|
||||
};
|
||||
|
||||
/* MBO v0.0_r19, 4.2.3: Cellular Data Capabilities Attribute */
|
||||
/* Table 4-13: Cellular Data Connectivity Field */
|
||||
enum mbo_cellular_capa {
|
||||
MBO_CELL_CAPA_AVAILABLE = 1,
|
||||
MBO_CELL_CAPA_NOT_AVAILABLE = 2,
|
||||
MBO_CELL_CAPA_NOT_SUPPORTED = 3,
|
||||
};
|
||||
|
||||
/* MBO v0.0_r19, 4.2.4: Association Disallowed Attribute */
|
||||
/* Table 4-15: Reason Code Field Values */
|
||||
enum mbo_assoc_disallow_reason {
|
||||
MBO_ASSOC_DISALLOW_REASON_UNSPECIFIED = 1,
|
||||
MBO_ASSOC_DISALLOW_REASON_MAX_STA = 2,
|
||||
MBO_ASSOC_DISALLOW_REASON_AIR_INTERFERENCE = 3,
|
||||
MBO_ASSOC_DISALLOW_REASON_AUTH_SERVER_OVERLOAD = 4,
|
||||
MBO_ASSOC_DISALLOW_REASON_LOW_RSSI = 5,
|
||||
};
|
||||
|
||||
/* MBO v0.0_r19, 4.2.5: Cellular Data Connection Preference Attribute */
|
||||
/* Table 4-17: Cellular Preference Field Values */
|
||||
enum mbo_cell_pref {
|
||||
MBO_CELL_PREF_EXCLUDED = 0,
|
||||
MBO_CELL_PREF_NO_USE = 1,
|
||||
MBO_CELL_PREF_USE = 255
|
||||
};
|
||||
|
||||
/* MBO v0.0_r19, 4.2.6: Transition Reason Code Attribute */
|
||||
/* Table 4-19: Transition Reason Code Field Values */
|
||||
enum mbo_transition_reason {
|
||||
MBO_TRANSITION_REASON_UNSPECIFIED = 0,
|
||||
MBO_TRANSITION_REASON_FRAME_LOSS = 1,
|
||||
MBO_TRANSITION_REASON_DELAY = 2,
|
||||
MBO_TRANSITION_REASON_BANDWIDTH = 3,
|
||||
MBO_TRANSITION_REASON_LOAD_BALANCE = 4,
|
||||
MBO_TRANSITION_REASON_RSSI = 5,
|
||||
MBO_TRANSITION_REASON_RETRANSMISSIONS = 6,
|
||||
MBO_TRANSITION_REASON_INTERFERENCE = 7,
|
||||
MBO_TRANSITION_REASON_GRAY_ZONE = 8,
|
||||
MBO_TRANSITION_REASON_PREMIUM_AP = 9,
|
||||
};
|
||||
|
||||
/* MBO v0.0_r19, 4.2.7: Transition Rejection Reason Code Attribute */
|
||||
/* Table 4-21: Transition Rejection Reason Code Field Values */
|
||||
enum mbo_transition_reject_reason {
|
||||
MBO_TRANSITION_REJECT_REASON_UNSPECIFIED = 0,
|
||||
MBO_TRANSITION_REJECT_REASON_FRAME_LOSS = 1,
|
||||
MBO_TRANSITION_REJECT_REASON_DELAY = 2,
|
||||
MBO_TRANSITION_REJECT_REASON_QOS_CAPACITY = 3,
|
||||
MBO_TRANSITION_REJECT_REASON_RSSI = 4,
|
||||
MBO_TRANSITION_REJECT_REASON_INTERFERENCE = 5,
|
||||
MBO_TRANSITION_REJECT_REASON_SERVICES = 6,
|
||||
};
|
||||
|
||||
/* MBO v0.0_r19, 4.4: WNM-Notification vendor subelements */
|
||||
enum wfa_wnm_notif_subelem_id {
|
||||
WFA_WNM_NOTIF_SUBELEM_NON_PREF_CHAN_REPORT = 2,
|
||||
WFA_WNM_NOTIF_SUBELEM_CELL_DATA_CAPA = 3,
|
||||
};
|
||||
|
||||
/* MBO v0.0_r25, 4.3: MBO ANQP-elements */
|
||||
#define MBO_ANQP_OUI_TYPE 0x12
|
||||
#define MBO_ANQP_SUBTYPE_CELL_CONN_PREF 1
|
||||
|
||||
/* Wi-Fi Direct (P2P) */
|
||||
|
||||
#define P2P_OUI_TYPE 9
|
||||
@ -1178,6 +1341,14 @@ enum wifi_display_subelem {
|
||||
#define MESH_PATH_PROTOCOL_VENDOR 255
|
||||
#define MESH_PATH_METRIC_AIRTIME 1
|
||||
#define MESH_PATH_METRIC_VENDOR 255
|
||||
/* IEEE 802.11s - Mesh Capability */
|
||||
#define MESH_CAP_ACCEPT_ADDITIONAL_PEER BIT(0)
|
||||
#define MESH_CAP_MCCA_SUPPORTED BIT(1)
|
||||
#define MESH_CAP_MCCA_ENABLED BIT(2)
|
||||
#define MESH_CAP_FORWARDING BIT(3)
|
||||
#define MESH_CAP_MBCA_ENABLED BIT(4)
|
||||
#define MESH_CAP_TBTT_ADJUSTING BIT(5)
|
||||
#define MESH_CAP_MESH_PS_LEVEL BIT(6)
|
||||
|
||||
enum plink_action_field {
|
||||
PLINK_OPEN = 1,
|
||||
@ -1280,14 +1451,25 @@ enum bss_trans_mgmt_status_code {
|
||||
WNM_BSS_TM_REJECT_LEAVING_ESS = 8
|
||||
};
|
||||
|
||||
/*
|
||||
* IEEE P802.11-REVmc/D5.0 Table 9-150 - Optional subelement IDs for
|
||||
* neighbor report
|
||||
*/
|
||||
#define WNM_NEIGHBOR_TSF 1
|
||||
#define WNM_NEIGHBOR_CONDENSED_COUNTRY_STRING 2
|
||||
#define WNM_NEIGHBOR_BSS_TRANSITION_CANDIDATE 3
|
||||
#define WNM_NEIGHBOR_BSS_TERMINATION_DURATION 4
|
||||
#define WNM_NEIGHBOR_BEARING 5
|
||||
#define WNM_NEIGHBOR_WIDE_BW_CHAN 6
|
||||
#define WNM_NEIGHBOR_MEASUREMENT_REPORT 39
|
||||
#define WNM_NEIGHBOR_HT_CAPAB 45
|
||||
#define WNM_NEIGHBOR_HT_OPER 61
|
||||
#define WNM_NEIGHBOR_SEC_CHAN_OFFSET 62
|
||||
#define WNM_NEIGHBOR_MEASUREMENT_PILOT 66
|
||||
#define WNM_NEIGHBOR_RRM_ENABLED_CAPABILITIES 70
|
||||
#define WNM_NEIGHBOR_MULTIPLE_BSSID 71
|
||||
#define WNM_NEIGHBOR_VHT_CAPAB 191
|
||||
#define WNM_NEIGHBOR_VHT_OPER 192
|
||||
|
||||
/* QoS action */
|
||||
enum qos_action {
|
||||
@ -1356,6 +1538,8 @@ struct tpc_report {
|
||||
u8 link_margin;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define RRM_CAPABILITIES_IE_LEN 5
|
||||
|
||||
/* IEEE Std 802.11-2012, 8.5.7.4 - Link Measurement Request frame format */
|
||||
struct rrm_link_measurement_request {
|
||||
u8 dialog_token;
|
||||
@ -1375,8 +1559,6 @@ struct rrm_link_measurement_report {
|
||||
u8 variable[0];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define SSID_MAX_LEN 32
|
||||
|
||||
/* IEEE Std 802.11ad-2012 - Multi-band element */
|
||||
struct multi_band_ie {
|
||||
u8 eid; /* WLAN_EID_MULTI_BAND */
|
||||
@ -1433,4 +1615,49 @@ enum fst_action {
|
||||
FST_ACTION_ON_CHANNEL_TUNNEL = 5,
|
||||
};
|
||||
|
||||
/* IEEE Std 802.11ac-2013, Annex C - dot11PHYType */
|
||||
enum phy_type {
|
||||
PHY_TYPE_UNSPECIFIED = 0,
|
||||
PHY_TYPE_FHSS = 1,
|
||||
PHY_TYPE_DSSS = 2,
|
||||
PHY_TYPE_IRBASEBAND = 3,
|
||||
PHY_TYPE_OFDM = 4,
|
||||
PHY_TYPE_HRDSSS = 5,
|
||||
PHY_TYPE_ERP = 6,
|
||||
PHY_TYPE_HT = 7,
|
||||
PHY_TYPE_DMG = 8,
|
||||
PHY_TYPE_VHT = 9,
|
||||
};
|
||||
|
||||
/* IEEE P802.11-REVmc/D5.0, 9.4.2.37 - Neighbor Report element */
|
||||
/* BSSID Information Field */
|
||||
#define NEI_REP_BSSID_INFO_AP_NOT_REACH BIT(0)
|
||||
#define NEI_REP_BSSID_INFO_AP_UNKNOWN_REACH BIT(1)
|
||||
#define NEI_REP_BSSID_INFO_AP_REACHABLE (BIT(0) | BIT(1))
|
||||
#define NEI_REP_BSSID_INFO_SECURITY BIT(2)
|
||||
#define NEI_REP_BSSID_INFO_KEY_SCOPE BIT(3)
|
||||
#define NEI_REP_BSSID_INFO_SPECTRUM_MGMT BIT(4)
|
||||
#define NEI_REP_BSSID_INFO_QOS BIT(5)
|
||||
#define NEI_REP_BSSID_INFO_APSD BIT(6)
|
||||
#define NEI_REP_BSSID_INFO_RM BIT(7)
|
||||
#define NEI_REP_BSSID_INFO_DELAYED_BA BIT(8)
|
||||
#define NEI_REP_BSSID_INFO_IMM_BA BIT(9)
|
||||
#define NEI_REP_BSSID_INFO_MOBILITY_DOMAIN BIT(10)
|
||||
#define NEI_REP_BSSID_INFO_HT BIT(11)
|
||||
#define NEI_REP_BSSID_INFO_VHT BIT(12)
|
||||
#define NEI_REP_BSSID_INFO_FTM BIT(13)
|
||||
|
||||
/*
|
||||
* IEEE P802.11-REVmc/D5.0 Table 9-152 - HT/VHT Operation Information
|
||||
* subfields.
|
||||
* Note: These definitions are not the same as other VHT_CHANWIDTH_*.
|
||||
*/
|
||||
enum nr_chan_width {
|
||||
NR_CHAN_WIDTH_20 = 0,
|
||||
NR_CHAN_WIDTH_40 = 1,
|
||||
NR_CHAN_WIDTH_80 = 2,
|
||||
NR_CHAN_WIDTH_160 = 3,
|
||||
NR_CHAN_WIDTH_80P80 = 4,
|
||||
};
|
||||
|
||||
#endif /* IEEE802_11_DEFS_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -45,6 +45,7 @@ struct sae_data {
|
||||
enum { SAE_NOTHING, SAE_COMMITTED, SAE_CONFIRMED, SAE_ACCEPTED } state;
|
||||
u16 send_confirm;
|
||||
u8 pmk[SAE_PMK_LEN];
|
||||
u8 pmkid[SAE_PMKID_LEN];
|
||||
struct crypto_bignum *peer_commit_scalar;
|
||||
int group;
|
||||
int sync;
|
||||
|
@ -5,6 +5,10 @@
|
||||
#define VERSION_STR_POSTFIX ""
|
||||
#endif /* VERSION_STR_POSTFIX */
|
||||
|
||||
#define VERSION_STR "2.5" VERSION_STR_POSTFIX
|
||||
#ifndef GIT_VERSION_STR_POSTFIX
|
||||
#define GIT_VERSION_STR_POSTFIX ""
|
||||
#endif /* GIT_VERSION_STR_POSTFIX */
|
||||
|
||||
#define VERSION_STR "2.6" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX
|
||||
|
||||
#endif /* VERSION_H */
|
||||
|
@ -294,38 +294,47 @@ static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
|
||||
pos = ie + sizeof(struct rsn_ftie);
|
||||
end = ie + ie_len;
|
||||
|
||||
while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
|
||||
switch (pos[0]) {
|
||||
while (end - pos >= 2) {
|
||||
u8 id, len;
|
||||
|
||||
id = *pos++;
|
||||
len = *pos++;
|
||||
if (len > end - pos)
|
||||
break;
|
||||
|
||||
switch (id) {
|
||||
case FTIE_SUBELEM_R1KH_ID:
|
||||
if (pos[1] != FT_R1KH_ID_LEN) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Invalid R1KH-ID "
|
||||
"length in FTIE: %d", pos[1]);
|
||||
if (len != FT_R1KH_ID_LEN) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"FT: Invalid R1KH-ID length in FTIE: %d",
|
||||
len);
|
||||
return -1;
|
||||
}
|
||||
parse->r1kh_id = pos + 2;
|
||||
parse->r1kh_id = pos;
|
||||
break;
|
||||
case FTIE_SUBELEM_GTK:
|
||||
parse->gtk = pos + 2;
|
||||
parse->gtk_len = pos[1];
|
||||
parse->gtk = pos;
|
||||
parse->gtk_len = len;
|
||||
break;
|
||||
case FTIE_SUBELEM_R0KH_ID:
|
||||
if (pos[1] < 1 || pos[1] > FT_R0KH_ID_MAX_LEN) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Invalid R0KH-ID "
|
||||
"length in FTIE: %d", pos[1]);
|
||||
if (len < 1 || len > FT_R0KH_ID_MAX_LEN) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"FT: Invalid R0KH-ID length in FTIE: %d",
|
||||
len);
|
||||
return -1;
|
||||
}
|
||||
parse->r0kh_id = pos + 2;
|
||||
parse->r0kh_id_len = pos[1];
|
||||
parse->r0kh_id = pos;
|
||||
parse->r0kh_id_len = len;
|
||||
break;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
case FTIE_SUBELEM_IGTK:
|
||||
parse->igtk = pos + 2;
|
||||
parse->igtk_len = pos[1];
|
||||
parse->igtk = pos;
|
||||
parse->igtk_len = len;
|
||||
break;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
}
|
||||
|
||||
pos += 2 + pos[1];
|
||||
pos += len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -347,11 +356,18 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
|
||||
|
||||
pos = ies;
|
||||
end = ies + ies_len;
|
||||
while (pos + 2 <= end && pos + 2 + pos[1] <= end) {
|
||||
switch (pos[0]) {
|
||||
while (end - pos >= 2) {
|
||||
u8 id, len;
|
||||
|
||||
id = *pos++;
|
||||
len = *pos++;
|
||||
if (len > end - pos)
|
||||
break;
|
||||
|
||||
switch (id) {
|
||||
case WLAN_EID_RSN:
|
||||
parse->rsn = pos + 2;
|
||||
parse->rsn_len = pos[1];
|
||||
parse->rsn = pos;
|
||||
parse->rsn_len = len;
|
||||
ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2,
|
||||
parse->rsn_len + 2,
|
||||
&data);
|
||||
@ -364,32 +380,32 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
|
||||
parse->rsn_pmkid = data.pmkid;
|
||||
break;
|
||||
case WLAN_EID_MOBILITY_DOMAIN:
|
||||
if (pos[1] < sizeof(struct rsn_mdie))
|
||||
if (len < sizeof(struct rsn_mdie))
|
||||
return -1;
|
||||
parse->mdie = pos + 2;
|
||||
parse->mdie_len = pos[1];
|
||||
parse->mdie = pos;
|
||||
parse->mdie_len = len;
|
||||
break;
|
||||
case WLAN_EID_FAST_BSS_TRANSITION:
|
||||
if (pos[1] < sizeof(*ftie))
|
||||
if (len < sizeof(*ftie))
|
||||
return -1;
|
||||
ftie = (const struct rsn_ftie *) (pos + 2);
|
||||
ftie = (const struct rsn_ftie *) pos;
|
||||
prot_ie_count = ftie->mic_control[1];
|
||||
if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0)
|
||||
if (wpa_ft_parse_ftie(pos, len, parse) < 0)
|
||||
return -1;
|
||||
break;
|
||||
case WLAN_EID_TIMEOUT_INTERVAL:
|
||||
if (pos[1] != 5)
|
||||
if (len != 5)
|
||||
break;
|
||||
parse->tie = pos + 2;
|
||||
parse->tie_len = pos[1];
|
||||
parse->tie = pos;
|
||||
parse->tie_len = len;
|
||||
break;
|
||||
case WLAN_EID_RIC_DATA:
|
||||
if (parse->ric == NULL)
|
||||
parse->ric = pos;
|
||||
parse->ric = pos - 2;
|
||||
break;
|
||||
}
|
||||
|
||||
pos += 2 + pos[1];
|
||||
pos += len;
|
||||
}
|
||||
|
||||
if (prot_ie_count == 0)
|
||||
@ -418,13 +434,15 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
|
||||
}
|
||||
|
||||
/* Determine the end of the RIC IE(s) */
|
||||
pos = parse->ric;
|
||||
while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end &&
|
||||
prot_ie_count) {
|
||||
prot_ie_count--;
|
||||
pos += 2 + pos[1];
|
||||
if (parse->ric) {
|
||||
pos = parse->ric;
|
||||
while (end - pos >= 2 && 2 + pos[1] <= end - pos &&
|
||||
prot_ie_count) {
|
||||
prot_ie_count--;
|
||||
pos += 2 + pos[1];
|
||||
}
|
||||
parse->ric_len = pos - parse->ric;
|
||||
}
|
||||
parse->ric_len = pos - parse->ric;
|
||||
if (prot_ie_count) {
|
||||
wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from "
|
||||
"frame", (int) prot_ie_count);
|
||||
@ -584,8 +602,10 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
|
||||
if (left >= RSN_SELECTOR_LEN) {
|
||||
data->group_cipher = rsn_selector_to_bitfield(pos);
|
||||
if (!wpa_cipher_valid_group(data->group_cipher)) {
|
||||
wpa_printf(MSG_DEBUG, "%s: invalid group cipher 0x%x",
|
||||
__func__, data->group_cipher);
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"%s: invalid group cipher 0x%x (%08x)",
|
||||
__func__, data->group_cipher,
|
||||
WPA_GET_BE32(pos));
|
||||
return -1;
|
||||
}
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
@ -673,9 +693,10 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
|
||||
if (left >= 4) {
|
||||
data->mgmt_group_cipher = rsn_selector_to_bitfield(pos);
|
||||
if (!wpa_cipher_valid_mgmt_group(data->mgmt_group_cipher)) {
|
||||
wpa_printf(MSG_DEBUG, "%s: Unsupported management "
|
||||
"group cipher 0x%x", __func__,
|
||||
data->mgmt_group_cipher);
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"%s: Unsupported management group cipher 0x%x (%08x)",
|
||||
__func__, data->mgmt_group_cipher,
|
||||
WPA_GET_BE32(pos));
|
||||
return -10;
|
||||
}
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
@ -1165,6 +1186,8 @@ const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
|
||||
"WPA2-PSK" : "WPA-PSK";
|
||||
case WPA_KEY_MGMT_NONE:
|
||||
return "NONE";
|
||||
case WPA_KEY_MGMT_WPA_NONE:
|
||||
return "WPA-NONE";
|
||||
case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
|
||||
return "IEEE 802.1X (no WPA)";
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
@ -1263,13 +1286,13 @@ int wpa_compare_rsn_ie(int ft_initial_assoc,
|
||||
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
|
||||
int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid)
|
||||
{
|
||||
u8 *start, *end, *rpos, *rend;
|
||||
int added = 0;
|
||||
|
||||
start = ies;
|
||||
end = ies + ies_len;
|
||||
end = ies + *ies_len;
|
||||
|
||||
while (start < end) {
|
||||
if (*start == WLAN_EID_RSN)
|
||||
@ -1322,11 +1345,29 @@ int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
|
||||
added += 2 + PMKID_LEN;
|
||||
start[1] += 2 + PMKID_LEN;
|
||||
} else {
|
||||
/* PMKID-Count was included; use it */
|
||||
if (WPA_GET_LE16(rpos) != 0) {
|
||||
wpa_printf(MSG_ERROR, "FT: Unexpected PMKID "
|
||||
"in RSN IE in EAPOL-Key data");
|
||||
u16 num_pmkid;
|
||||
|
||||
if (rend - rpos < 2)
|
||||
return -1;
|
||||
num_pmkid = WPA_GET_LE16(rpos);
|
||||
/* PMKID-Count was included; use it */
|
||||
if (num_pmkid != 0) {
|
||||
u8 *after;
|
||||
|
||||
if (num_pmkid * PMKID_LEN > rend - rpos - 2)
|
||||
return -1;
|
||||
/*
|
||||
* PMKID may have been included in RSN IE in
|
||||
* (Re)Association Request frame, so remove the old
|
||||
* PMKID(s) first before adding the new one.
|
||||
*/
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"FT: Remove %u old PMKID(s) from RSN IE",
|
||||
num_pmkid);
|
||||
after = rpos + 2 + num_pmkid * PMKID_LEN;
|
||||
os_memmove(rpos + 2, after, rend - after);
|
||||
start[1] -= num_pmkid * PMKID_LEN;
|
||||
added -= num_pmkid * PMKID_LEN;
|
||||
}
|
||||
WPA_PUT_LE16(rpos, 1);
|
||||
rpos += 2;
|
||||
@ -1339,7 +1380,9 @@ int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
|
||||
wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification "
|
||||
"(PMKID inserted)", start, 2 + start[1]);
|
||||
|
||||
return added;
|
||||
*ies_len += added;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
|
@ -12,6 +12,8 @@
|
||||
/* IEEE 802.11i */
|
||||
#define PMKID_LEN 16
|
||||
#define PMK_LEN 32
|
||||
#define PMK_LEN_SUITE_B_192 48
|
||||
#define PMK_LEN_MAX 48
|
||||
#define WPA_REPLAY_COUNTER_LEN 8
|
||||
#define WPA_NONCE_LEN 32
|
||||
#define WPA_KEY_RSC_LEN 8
|
||||
@ -419,7 +421,7 @@ u32 wpa_akm_to_suite(int akm);
|
||||
int wpa_compare_rsn_ie(int ft_initial_assoc,
|
||||
const u8 *ie1, size_t ie1len,
|
||||
const u8 *ie2, size_t ie2len);
|
||||
int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid);
|
||||
int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid);
|
||||
|
||||
struct wpa_ft_ies {
|
||||
const u8 *mdie;
|
||||
|
@ -76,6 +76,21 @@ extern "C" {
|
||||
#define WPA_EVENT_SIGNAL_CHANGE "CTRL-EVENT-SIGNAL-CHANGE "
|
||||
/** Regulatory domain channel */
|
||||
#define WPA_EVENT_REGDOM_CHANGE "CTRL-EVENT-REGDOM-CHANGE "
|
||||
/** Channel switch (followed by freq=<MHz> and other channel parameters) */
|
||||
#define WPA_EVENT_CHANNEL_SWITCH "CTRL-EVENT-CHANNEL-SWITCH "
|
||||
|
||||
/** IP subnet status change notification
|
||||
*
|
||||
* When using an offloaded roaming mechanism where driver/firmware takes care
|
||||
* of roaming and IP subnet validation checks post-roaming, this event can
|
||||
* indicate whether IP subnet has changed.
|
||||
*
|
||||
* The event has a status=<0/1/2> parameter where
|
||||
* 0 = unknown
|
||||
* 1 = IP subnet unchanged (can continue to use the old IP address)
|
||||
* 2 = IP subnet changed (need to get a new IP address)
|
||||
*/
|
||||
#define WPA_EVENT_SUBNET_STATUS_UPDATE "CTRL-EVENT-SUBNET-STATUS-UPDATE "
|
||||
|
||||
/** RSN IBSS 4-way handshakes completed with specified peer */
|
||||
#define IBSS_RSN_COMPLETED "IBSS-RSN-COMPLETED "
|
||||
@ -174,6 +189,7 @@ extern "C" {
|
||||
#define P2P_EVENT_SERV_ASP_RESP "P2P-SERV-ASP-RESP "
|
||||
#define P2P_EVENT_INVITATION_RECEIVED "P2P-INVITATION-RECEIVED "
|
||||
#define P2P_EVENT_INVITATION_RESULT "P2P-INVITATION-RESULT "
|
||||
#define P2P_EVENT_INVITATION_ACCEPTED "P2P-INVITATION-ACCEPTED "
|
||||
#define P2P_EVENT_FIND_STOPPED "P2P-FIND-STOPPED "
|
||||
#define P2P_EVENT_PERSISTENT_PSK_FAIL "P2P-PERSISTENT-PSK-FAIL id="
|
||||
#define P2P_EVENT_PRESENCE_RESPONSE "P2P-PRESENCE-RESPONSE "
|
||||
@ -212,6 +228,11 @@ extern "C" {
|
||||
/* parameters: <addr> <result> */
|
||||
#define ANQP_QUERY_DONE "ANQP-QUERY-DONE "
|
||||
|
||||
#define RX_ANQP "RX-ANQP "
|
||||
#define RX_HS20_ANQP "RX-HS20-ANQP "
|
||||
#define RX_HS20_ANQP_ICON "RX-HS20-ANQP-ICON "
|
||||
#define RX_HS20_ICON "RX-HS20-ICON "
|
||||
|
||||
#define HS20_SUBSCRIPTION_REMEDIATION "HS20-SUBSCRIPTION-REMEDIATION "
|
||||
#define HS20_DEAUTH_IMMINENT_NOTICE "HS20-DEAUTH-IMMINENT-NOTICE "
|
||||
|
||||
@ -232,6 +253,7 @@ extern "C" {
|
||||
#define AP_STA_CONNECTED "AP-STA-CONNECTED "
|
||||
#define AP_STA_DISCONNECTED "AP-STA-DISCONNECTED "
|
||||
#define AP_STA_POSSIBLE_PSK_MISMATCH "AP-STA-POSSIBLE-PSK-MISMATCH "
|
||||
#define AP_STA_POLL_OK "AP-STA-POLL-OK "
|
||||
|
||||
#define AP_REJECTED_MAX_STA "AP-REJECTED-MAX-STA "
|
||||
#define AP_REJECTED_BLOCKED_STA "AP-REJECTED-BLOCKED-STA "
|
||||
@ -254,9 +276,18 @@ extern "C" {
|
||||
|
||||
#define AP_CSA_FINISHED "AP-CSA-FINISHED "
|
||||
|
||||
#define P2P_EVENT_LISTEN_OFFLOAD_STOP "P2P-LISTEN-OFFLOAD-STOPPED "
|
||||
#define P2P_LISTEN_OFFLOAD_STOP_REASON "P2P-LISTEN-OFFLOAD-STOP-REASON "
|
||||
|
||||
/* BSS Transition Management Response frame received */
|
||||
#define BSS_TM_RESP "BSS-TM-RESP "
|
||||
|
||||
/* MBO IE with cellular data connection preference received */
|
||||
#define MBO_CELL_PREFERENCE "MBO-CELL-PREFERENCE "
|
||||
|
||||
/* BSS Transition Management Request received with MBO transition reason */
|
||||
#define MBO_TRANSITION_REASON "MBO-TRANSITION-REASON "
|
||||
|
||||
/* BSS command information masks */
|
||||
|
||||
#define WPA_BSS_MASK_ALL 0xFFFDFFFF
|
||||
@ -300,6 +331,7 @@ enum wpa_vendor_elem_frame {
|
||||
VENDOR_ELEM_P2P_ASSOC_REQ = 11,
|
||||
VENDOR_ELEM_P2P_ASSOC_RESP = 12,
|
||||
VENDOR_ELEM_ASSOC_REQ = 13,
|
||||
VENDOR_ELEM_PROBE_REQ = 14,
|
||||
NUM_VENDOR_ELEM_FRAMES
|
||||
};
|
||||
|
||||
|
@ -50,6 +50,9 @@ int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
|
||||
const u8 *pos, *end;
|
||||
size_t i, e, left, total_len;
|
||||
|
||||
if (TEST_FAIL())
|
||||
return -1;
|
||||
|
||||
ctx = aes_encrypt_init(key, key_len);
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
|
@ -79,6 +79,28 @@ int __must_check fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x,
|
||||
int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
|
||||
u8 *mac);
|
||||
|
||||
/**
|
||||
* sha384_vector - SHA384 hash for data vector
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len,
|
||||
u8 *mac);
|
||||
|
||||
/**
|
||||
* sha512_vector - SHA512 hash for data vector
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len,
|
||||
u8 *mac);
|
||||
|
||||
/**
|
||||
* des_encrypt - Encrypt one block with DES
|
||||
* @clear: 8 octets (in)
|
||||
@ -135,7 +157,8 @@ void aes_decrypt_deinit(void *ctx);
|
||||
enum crypto_hash_alg {
|
||||
CRYPTO_HASH_ALG_MD5, CRYPTO_HASH_ALG_SHA1,
|
||||
CRYPTO_HASH_ALG_HMAC_MD5, CRYPTO_HASH_ALG_HMAC_SHA1,
|
||||
CRYPTO_HASH_ALG_SHA256, CRYPTO_HASH_ALG_HMAC_SHA256
|
||||
CRYPTO_HASH_ALG_SHA256, CRYPTO_HASH_ALG_HMAC_SHA256,
|
||||
CRYPTO_HASH_ALG_SHA384, CRYPTO_HASH_ALG_SHA512
|
||||
};
|
||||
|
||||
struct crypto_hash;
|
||||
|
@ -31,11 +31,61 @@
|
||||
#include "sha1.h"
|
||||
#include "sha256.h"
|
||||
#include "sha384.h"
|
||||
#include "md5.h"
|
||||
#include "aes_wrap.h"
|
||||
#include "crypto.h"
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
|
||||
/* Compatibility wrappers for older versions. */
|
||||
|
||||
static HMAC_CTX * HMAC_CTX_new(void)
|
||||
{
|
||||
HMAC_CTX *ctx;
|
||||
|
||||
ctx = os_zalloc(sizeof(*ctx));
|
||||
if (ctx)
|
||||
HMAC_CTX_init(ctx);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
static void HMAC_CTX_free(HMAC_CTX *ctx)
|
||||
{
|
||||
if (!ctx)
|
||||
return;
|
||||
HMAC_CTX_cleanup(ctx);
|
||||
bin_clear_free(ctx, sizeof(*ctx));
|
||||
}
|
||||
|
||||
|
||||
static EVP_MD_CTX * EVP_MD_CTX_new(void)
|
||||
{
|
||||
EVP_MD_CTX *ctx;
|
||||
|
||||
ctx = os_zalloc(sizeof(*ctx));
|
||||
if (ctx)
|
||||
EVP_MD_CTX_init(ctx);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
static void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
|
||||
{
|
||||
if (!ctx)
|
||||
return;
|
||||
EVP_MD_CTX_cleanup(ctx);
|
||||
bin_clear_free(ctx, sizeof(*ctx));
|
||||
}
|
||||
|
||||
#endif /* OpenSSL version < 1.1.0 */
|
||||
|
||||
static BIGNUM * get_group5_prime(void)
|
||||
{
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
|
||||
return BN_get_rfc3526_prime_1536(NULL);
|
||||
#elif !defined(OPENSSL_IS_BORINGSSL)
|
||||
return get_rfc3526_prime_1536(NULL);
|
||||
#else
|
||||
static const unsigned char RFC3526_PRIME_1536[] = {
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,
|
||||
0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,
|
||||
@ -55,9 +105,7 @@ static BIGNUM * get_group5_prime(void)
|
||||
0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
};
|
||||
return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), NULL);
|
||||
#else /* OPENSSL_IS_BORINGSSL */
|
||||
return get_rfc3526_prime_1536(NULL);
|
||||
#endif /* OPENSSL_IS_BORINGSSL */
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef OPENSSL_NO_SHA256
|
||||
@ -67,29 +115,38 @@ static BIGNUM * get_group5_prime(void)
|
||||
static int openssl_digest_vector(const EVP_MD *type, size_t num_elem,
|
||||
const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
EVP_MD_CTX ctx;
|
||||
EVP_MD_CTX *ctx;
|
||||
size_t i;
|
||||
unsigned int mac_len;
|
||||
|
||||
EVP_MD_CTX_init(&ctx);
|
||||
if (!EVP_DigestInit_ex(&ctx, type, NULL)) {
|
||||
if (TEST_FAIL())
|
||||
return -1;
|
||||
|
||||
ctx = EVP_MD_CTX_new();
|
||||
if (!ctx)
|
||||
return -1;
|
||||
if (!EVP_DigestInit_ex(ctx, type, NULL)) {
|
||||
wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestInit_ex failed: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_MD_CTX_free(ctx);
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < num_elem; i++) {
|
||||
if (!EVP_DigestUpdate(&ctx, addr[i], len[i])) {
|
||||
if (!EVP_DigestUpdate(ctx, addr[i], len[i])) {
|
||||
wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestUpdate "
|
||||
"failed: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_MD_CTX_free(ctx);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (!EVP_DigestFinal(&ctx, mac, &mac_len)) {
|
||||
if (!EVP_DigestFinal(ctx, mac, &mac_len)) {
|
||||
wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestFinal failed: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_MD_CTX_free(ctx);
|
||||
return -1;
|
||||
}
|
||||
EVP_MD_CTX_free(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -131,32 +188,34 @@ int rc4_skip(const u8 *key, size_t keylen, size_t skip,
|
||||
#ifdef OPENSSL_NO_RC4
|
||||
return -1;
|
||||
#else /* OPENSSL_NO_RC4 */
|
||||
EVP_CIPHER_CTX ctx;
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
int outl;
|
||||
int res = -1;
|
||||
unsigned char skip_buf[16];
|
||||
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
if (!EVP_CIPHER_CTX_set_padding(&ctx, 0) ||
|
||||
!EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, NULL, NULL, 1) ||
|
||||
!EVP_CIPHER_CTX_set_key_length(&ctx, keylen) ||
|
||||
!EVP_CipherInit_ex(&ctx, NULL, NULL, key, NULL, 1))
|
||||
ctx = EVP_CIPHER_CTX_new();
|
||||
if (!ctx ||
|
||||
!EVP_CIPHER_CTX_set_padding(ctx, 0) ||
|
||||
!EVP_CipherInit_ex(ctx, EVP_rc4(), NULL, NULL, NULL, 1) ||
|
||||
!EVP_CIPHER_CTX_set_key_length(ctx, keylen) ||
|
||||
!EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, 1))
|
||||
goto out;
|
||||
|
||||
while (skip >= sizeof(skip_buf)) {
|
||||
size_t len = skip;
|
||||
if (len > sizeof(skip_buf))
|
||||
len = sizeof(skip_buf);
|
||||
if (!EVP_CipherUpdate(&ctx, skip_buf, &outl, skip_buf, len))
|
||||
if (!EVP_CipherUpdate(ctx, skip_buf, &outl, skip_buf, len))
|
||||
goto out;
|
||||
skip -= len;
|
||||
}
|
||||
|
||||
if (EVP_CipherUpdate(&ctx, data, &outl, data, data_len))
|
||||
if (EVP_CipherUpdate(ctx, data, &outl, data, data_len))
|
||||
res = 0;
|
||||
|
||||
out:
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
if (ctx)
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
return res;
|
||||
#endif /* OPENSSL_NO_RC4 */
|
||||
}
|
||||
@ -208,14 +267,16 @@ void * aes_encrypt_init(const u8 *key, size_t len)
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
const EVP_CIPHER *type;
|
||||
|
||||
if (TEST_FAIL())
|
||||
return NULL;
|
||||
|
||||
type = aes_get_evp_cipher(len);
|
||||
if (type == NULL)
|
||||
return NULL;
|
||||
|
||||
ctx = os_malloc(sizeof(*ctx));
|
||||
ctx = EVP_CIPHER_CTX_new();
|
||||
if (ctx == NULL)
|
||||
return NULL;
|
||||
EVP_CIPHER_CTX_init(ctx);
|
||||
if (EVP_EncryptInit_ex(ctx, type, NULL, key, NULL) != 1) {
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
@ -249,8 +310,7 @@ void aes_encrypt_deinit(void *ctx)
|
||||
wpa_printf(MSG_ERROR, "OpenSSL: Unexpected padding length %d "
|
||||
"in AES encrypt", len);
|
||||
}
|
||||
EVP_CIPHER_CTX_cleanup(c);
|
||||
bin_clear_free(c, sizeof(*c));
|
||||
EVP_CIPHER_CTX_free(c);
|
||||
}
|
||||
|
||||
|
||||
@ -259,16 +319,18 @@ void * aes_decrypt_init(const u8 *key, size_t len)
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
const EVP_CIPHER *type;
|
||||
|
||||
if (TEST_FAIL())
|
||||
return NULL;
|
||||
|
||||
type = aes_get_evp_cipher(len);
|
||||
if (type == NULL)
|
||||
return NULL;
|
||||
|
||||
ctx = os_malloc(sizeof(*ctx));
|
||||
ctx = EVP_CIPHER_CTX_new();
|
||||
if (ctx == NULL)
|
||||
return NULL;
|
||||
EVP_CIPHER_CTX_init(ctx);
|
||||
if (EVP_DecryptInit_ex(ctx, type, NULL, key, NULL) != 1) {
|
||||
os_free(ctx);
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
EVP_CIPHER_CTX_set_padding(ctx, 0);
|
||||
@ -300,8 +362,7 @@ void aes_decrypt_deinit(void *ctx)
|
||||
wpa_printf(MSG_ERROR, "OpenSSL: Unexpected padding length %d "
|
||||
"in AES decrypt", len);
|
||||
}
|
||||
EVP_CIPHER_CTX_cleanup(c);
|
||||
bin_clear_free(c, sizeof(*c));
|
||||
EVP_CIPHER_CTX_free(c);
|
||||
}
|
||||
|
||||
|
||||
@ -340,51 +401,56 @@ int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher,
|
||||
|
||||
int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
|
||||
{
|
||||
EVP_CIPHER_CTX ctx;
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
int clen, len;
|
||||
u8 buf[16];
|
||||
int res = -1;
|
||||
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
if (EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv) != 1)
|
||||
if (TEST_FAIL())
|
||||
return -1;
|
||||
EVP_CIPHER_CTX_set_padding(&ctx, 0);
|
||||
|
||||
ctx = EVP_CIPHER_CTX_new();
|
||||
if (!ctx)
|
||||
return -1;
|
||||
clen = data_len;
|
||||
if (EVP_EncryptUpdate(&ctx, data, &clen, data, data_len) != 1 ||
|
||||
clen != (int) data_len)
|
||||
return -1;
|
||||
|
||||
len = sizeof(buf);
|
||||
if (EVP_EncryptFinal_ex(&ctx, buf, &len) != 1 || len != 0)
|
||||
return -1;
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
if (EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv) == 1 &&
|
||||
EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 &&
|
||||
EVP_EncryptUpdate(ctx, data, &clen, data, data_len) == 1 &&
|
||||
clen == (int) data_len &&
|
||||
EVP_EncryptFinal_ex(ctx, buf, &len) == 1 && len == 0)
|
||||
res = 0;
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
|
||||
return 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
|
||||
{
|
||||
EVP_CIPHER_CTX ctx;
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
int plen, len;
|
||||
u8 buf[16];
|
||||
int res = -1;
|
||||
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
if (EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv) != 1)
|
||||
if (TEST_FAIL())
|
||||
return -1;
|
||||
EVP_CIPHER_CTX_set_padding(&ctx, 0);
|
||||
|
||||
ctx = EVP_CIPHER_CTX_new();
|
||||
if (!ctx)
|
||||
return -1;
|
||||
plen = data_len;
|
||||
if (EVP_DecryptUpdate(&ctx, data, &plen, data, data_len) != 1 ||
|
||||
plen != (int) data_len)
|
||||
return -1;
|
||||
|
||||
len = sizeof(buf);
|
||||
if (EVP_DecryptFinal_ex(&ctx, buf, &len) != 1 || len != 0)
|
||||
return -1;
|
||||
EVP_CIPHER_CTX_cleanup(&ctx);
|
||||
if (EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv) == 1 &&
|
||||
EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 &&
|
||||
EVP_DecryptUpdate(ctx, data, &plen, data, data_len) == 1 &&
|
||||
plen == (int) data_len &&
|
||||
EVP_DecryptFinal_ex(ctx, buf, &len) == 1 && len == 0)
|
||||
res = 0;
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
|
||||
return res;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -427,8 +493,8 @@ error:
|
||||
|
||||
|
||||
struct crypto_cipher {
|
||||
EVP_CIPHER_CTX enc;
|
||||
EVP_CIPHER_CTX dec;
|
||||
EVP_CIPHER_CTX *enc;
|
||||
EVP_CIPHER_CTX *dec;
|
||||
};
|
||||
|
||||
|
||||
@ -489,23 +555,25 @@ struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX_init(&ctx->enc);
|
||||
EVP_CIPHER_CTX_set_padding(&ctx->enc, 0);
|
||||
if (!EVP_EncryptInit_ex(&ctx->enc, cipher, NULL, NULL, NULL) ||
|
||||
!EVP_CIPHER_CTX_set_key_length(&ctx->enc, key_len) ||
|
||||
!EVP_EncryptInit_ex(&ctx->enc, NULL, NULL, key, iv)) {
|
||||
EVP_CIPHER_CTX_cleanup(&ctx->enc);
|
||||
if (!(ctx->enc = EVP_CIPHER_CTX_new()) ||
|
||||
!EVP_CIPHER_CTX_set_padding(ctx->enc, 0) ||
|
||||
!EVP_EncryptInit_ex(ctx->enc, cipher, NULL, NULL, NULL) ||
|
||||
!EVP_CIPHER_CTX_set_key_length(ctx->enc, key_len) ||
|
||||
!EVP_EncryptInit_ex(ctx->enc, NULL, NULL, key, iv)) {
|
||||
if (ctx->enc)
|
||||
EVP_CIPHER_CTX_free(ctx->enc);
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX_init(&ctx->dec);
|
||||
EVP_CIPHER_CTX_set_padding(&ctx->dec, 0);
|
||||
if (!EVP_DecryptInit_ex(&ctx->dec, cipher, NULL, NULL, NULL) ||
|
||||
!EVP_CIPHER_CTX_set_key_length(&ctx->dec, key_len) ||
|
||||
!EVP_DecryptInit_ex(&ctx->dec, NULL, NULL, key, iv)) {
|
||||
EVP_CIPHER_CTX_cleanup(&ctx->enc);
|
||||
EVP_CIPHER_CTX_cleanup(&ctx->dec);
|
||||
if (!(ctx->dec = EVP_CIPHER_CTX_new()) ||
|
||||
!EVP_CIPHER_CTX_set_padding(ctx->dec, 0) ||
|
||||
!EVP_DecryptInit_ex(ctx->dec, cipher, NULL, NULL, NULL) ||
|
||||
!EVP_CIPHER_CTX_set_key_length(ctx->dec, key_len) ||
|
||||
!EVP_DecryptInit_ex(ctx->dec, NULL, NULL, key, iv)) {
|
||||
EVP_CIPHER_CTX_free(ctx->enc);
|
||||
if (ctx->dec)
|
||||
EVP_CIPHER_CTX_free(ctx->dec);
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
@ -518,7 +586,7 @@ int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
|
||||
u8 *crypt, size_t len)
|
||||
{
|
||||
int outl;
|
||||
if (!EVP_EncryptUpdate(&ctx->enc, crypt, &outl, plain, len))
|
||||
if (!EVP_EncryptUpdate(ctx->enc, crypt, &outl, plain, len))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
@ -529,7 +597,7 @@ int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
|
||||
{
|
||||
int outl;
|
||||
outl = len;
|
||||
if (!EVP_DecryptUpdate(&ctx->dec, plain, &outl, crypt, len))
|
||||
if (!EVP_DecryptUpdate(ctx->dec, plain, &outl, crypt, len))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
@ -537,19 +605,21 @@ int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
|
||||
|
||||
void crypto_cipher_deinit(struct crypto_cipher *ctx)
|
||||
{
|
||||
EVP_CIPHER_CTX_cleanup(&ctx->enc);
|
||||
EVP_CIPHER_CTX_cleanup(&ctx->dec);
|
||||
EVP_CIPHER_CTX_free(ctx->enc);
|
||||
EVP_CIPHER_CTX_free(ctx->dec);
|
||||
os_free(ctx);
|
||||
}
|
||||
|
||||
|
||||
void * dh5_init(struct wpabuf **priv, struct wpabuf **publ)
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
DH *dh;
|
||||
struct wpabuf *pubkey = NULL, *privkey = NULL;
|
||||
size_t publen, privlen;
|
||||
|
||||
*priv = NULL;
|
||||
wpabuf_free(*publ);
|
||||
*publ = NULL;
|
||||
|
||||
dh = DH_new();
|
||||
@ -588,11 +658,63 @@ err:
|
||||
wpabuf_clear_free(privkey);
|
||||
DH_free(dh);
|
||||
return NULL;
|
||||
#else
|
||||
DH *dh;
|
||||
struct wpabuf *pubkey = NULL, *privkey = NULL;
|
||||
size_t publen, privlen;
|
||||
BIGNUM *p = NULL, *g;
|
||||
const BIGNUM *priv_key = NULL, *pub_key = NULL;
|
||||
|
||||
*priv = NULL;
|
||||
wpabuf_free(*publ);
|
||||
*publ = NULL;
|
||||
|
||||
dh = DH_new();
|
||||
if (dh == NULL)
|
||||
return NULL;
|
||||
|
||||
g = BN_new();
|
||||
p = get_group5_prime();
|
||||
if (!g || BN_set_word(g, 2) != 1 || !p ||
|
||||
DH_set0_pqg(dh, p, NULL, g) != 1)
|
||||
goto err;
|
||||
p = NULL;
|
||||
g = NULL;
|
||||
|
||||
if (DH_generate_key(dh) != 1)
|
||||
goto err;
|
||||
|
||||
DH_get0_key(dh, &pub_key, &priv_key);
|
||||
publen = BN_num_bytes(pub_key);
|
||||
pubkey = wpabuf_alloc(publen);
|
||||
if (!pubkey)
|
||||
goto err;
|
||||
privlen = BN_num_bytes(priv_key);
|
||||
privkey = wpabuf_alloc(privlen);
|
||||
if (!privkey)
|
||||
goto err;
|
||||
|
||||
BN_bn2bin(pub_key, wpabuf_put(pubkey, publen));
|
||||
BN_bn2bin(priv_key, wpabuf_put(privkey, privlen));
|
||||
|
||||
*priv = privkey;
|
||||
*publ = pubkey;
|
||||
return dh;
|
||||
|
||||
err:
|
||||
BN_free(p);
|
||||
BN_free(g);
|
||||
wpabuf_clear_free(pubkey);
|
||||
wpabuf_clear_free(privkey);
|
||||
DH_free(dh);
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ)
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
DH *dh;
|
||||
|
||||
dh = DH_new();
|
||||
@ -623,6 +745,42 @@ void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ)
|
||||
err:
|
||||
DH_free(dh);
|
||||
return NULL;
|
||||
#else
|
||||
DH *dh;
|
||||
BIGNUM *p = NULL, *g, *priv_key = NULL, *pub_key = NULL;
|
||||
|
||||
dh = DH_new();
|
||||
if (dh == NULL)
|
||||
return NULL;
|
||||
|
||||
g = BN_new();
|
||||
p = get_group5_prime();
|
||||
if (!g || BN_set_word(g, 2) != 1 || !p ||
|
||||
DH_set0_pqg(dh, p, NULL, g) != 1)
|
||||
goto err;
|
||||
p = NULL;
|
||||
g = NULL;
|
||||
|
||||
priv_key = BN_bin2bn(wpabuf_head(priv), wpabuf_len(priv), NULL);
|
||||
pub_key = BN_bin2bn(wpabuf_head(publ), wpabuf_len(publ), NULL);
|
||||
if (!priv_key || !pub_key || DH_set0_key(dh, pub_key, priv_key) != 1)
|
||||
goto err;
|
||||
pub_key = NULL;
|
||||
priv_key = NULL;
|
||||
|
||||
if (DH_generate_key(dh) != 1)
|
||||
goto err;
|
||||
|
||||
return dh;
|
||||
|
||||
err:
|
||||
BN_free(p);
|
||||
BN_free(g);
|
||||
BN_free(pub_key);
|
||||
BN_clear_free(priv_key);
|
||||
DH_free(dh);
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -674,7 +832,7 @@ void dh5_free(void *ctx)
|
||||
|
||||
|
||||
struct crypto_hash {
|
||||
HMAC_CTX ctx;
|
||||
HMAC_CTX *ctx;
|
||||
};
|
||||
|
||||
|
||||
@ -709,16 +867,17 @@ struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
|
||||
ctx = os_zalloc(sizeof(*ctx));
|
||||
if (ctx == NULL)
|
||||
return NULL;
|
||||
HMAC_CTX_init(&ctx->ctx);
|
||||
ctx->ctx = HMAC_CTX_new();
|
||||
if (!ctx->ctx) {
|
||||
os_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x00909000
|
||||
HMAC_Init_ex(&ctx->ctx, key, key_len, md, NULL);
|
||||
#else /* openssl < 0.9.9 */
|
||||
if (HMAC_Init_ex(&ctx->ctx, key, key_len, md, NULL) != 1) {
|
||||
if (HMAC_Init_ex(ctx->ctx, key, key_len, md, NULL) != 1) {
|
||||
HMAC_CTX_free(ctx->ctx);
|
||||
bin_clear_free(ctx, sizeof(*ctx));
|
||||
return NULL;
|
||||
}
|
||||
#endif /* openssl < 0.9.9 */
|
||||
|
||||
return ctx;
|
||||
}
|
||||
@ -728,7 +887,7 @@ void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
|
||||
{
|
||||
if (ctx == NULL)
|
||||
return;
|
||||
HMAC_Update(&ctx->ctx, data, len);
|
||||
HMAC_Update(ctx->ctx, data, len);
|
||||
}
|
||||
|
||||
|
||||
@ -741,18 +900,14 @@ int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
|
||||
return -2;
|
||||
|
||||
if (mac == NULL || len == NULL) {
|
||||
HMAC_CTX_free(ctx->ctx);
|
||||
bin_clear_free(ctx, sizeof(*ctx));
|
||||
return 0;
|
||||
}
|
||||
|
||||
mdlen = *len;
|
||||
#if OPENSSL_VERSION_NUMBER < 0x00909000
|
||||
HMAC_Final(&ctx->ctx, mac, &mdlen);
|
||||
res = 1;
|
||||
#else /* openssl < 0.9.9 */
|
||||
res = HMAC_Final(&ctx->ctx, mac, &mdlen);
|
||||
#endif /* openssl < 0.9.9 */
|
||||
HMAC_CTX_cleanup(&ctx->ctx);
|
||||
res = HMAC_Final(ctx->ctx, mac, &mdlen);
|
||||
HMAC_CTX_free(ctx->ctx);
|
||||
bin_clear_free(ctx, sizeof(*ctx));
|
||||
|
||||
if (res == 1) {
|
||||
@ -769,28 +924,26 @@ static int openssl_hmac_vector(const EVP_MD *type, const u8 *key,
|
||||
const u8 *addr[], const size_t *len, u8 *mac,
|
||||
unsigned int mdlen)
|
||||
{
|
||||
HMAC_CTX ctx;
|
||||
HMAC_CTX *ctx;
|
||||
size_t i;
|
||||
int res;
|
||||
|
||||
HMAC_CTX_init(&ctx);
|
||||
#if OPENSSL_VERSION_NUMBER < 0x00909000
|
||||
HMAC_Init_ex(&ctx, key, key_len, type, NULL);
|
||||
#else /* openssl < 0.9.9 */
|
||||
if (HMAC_Init_ex(&ctx, key, key_len, type, NULL) != 1)
|
||||
if (TEST_FAIL())
|
||||
return -1;
|
||||
#endif /* openssl < 0.9.9 */
|
||||
|
||||
ctx = HMAC_CTX_new();
|
||||
if (!ctx)
|
||||
return -1;
|
||||
res = HMAC_Init_ex(ctx, key, key_len, type, NULL);
|
||||
if (res != 1)
|
||||
goto done;
|
||||
|
||||
for (i = 0; i < num_elem; i++)
|
||||
HMAC_Update(&ctx, addr[i], len[i]);
|
||||
HMAC_Update(ctx, addr[i], len[i]);
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x00909000
|
||||
HMAC_Final(&ctx, mac, &mdlen);
|
||||
res = 1;
|
||||
#else /* openssl < 0.9.9 */
|
||||
res = HMAC_Final(&ctx, mac, &mdlen);
|
||||
#endif /* openssl < 0.9.9 */
|
||||
HMAC_CTX_cleanup(&ctx);
|
||||
res = HMAC_Final(ctx, mac, &mdlen);
|
||||
done:
|
||||
HMAC_CTX_free(ctx);
|
||||
|
||||
return res == 1 ? 0 : -1;
|
||||
}
|
||||
@ -894,6 +1047,9 @@ int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
|
||||
int ret = -1;
|
||||
size_t outlen, i;
|
||||
|
||||
if (TEST_FAIL())
|
||||
return -1;
|
||||
|
||||
ctx = CMAC_CTX_new();
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
@ -943,13 +1099,20 @@ int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
|
||||
|
||||
struct crypto_bignum * crypto_bignum_init(void)
|
||||
{
|
||||
if (TEST_FAIL())
|
||||
return NULL;
|
||||
return (struct crypto_bignum *) BN_new();
|
||||
}
|
||||
|
||||
|
||||
struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len)
|
||||
{
|
||||
BIGNUM *bn = BN_bin2bn(buf, len, NULL);
|
||||
BIGNUM *bn;
|
||||
|
||||
if (TEST_FAIL())
|
||||
return NULL;
|
||||
|
||||
bn = BN_bin2bn(buf, len, NULL);
|
||||
return (struct crypto_bignum *) bn;
|
||||
}
|
||||
|
||||
@ -968,6 +1131,9 @@ int crypto_bignum_to_bin(const struct crypto_bignum *a,
|
||||
{
|
||||
int num_bytes, offset;
|
||||
|
||||
if (TEST_FAIL())
|
||||
return -1;
|
||||
|
||||
if (padlen > buflen)
|
||||
return -1;
|
||||
|
||||
@ -1021,6 +1187,9 @@ int crypto_bignum_exptmod(const struct crypto_bignum *a,
|
||||
int res;
|
||||
BN_CTX *bnctx;
|
||||
|
||||
if (TEST_FAIL())
|
||||
return -1;
|
||||
|
||||
bnctx = BN_CTX_new();
|
||||
if (bnctx == NULL)
|
||||
return -1;
|
||||
@ -1039,6 +1208,8 @@ int crypto_bignum_inverse(const struct crypto_bignum *a,
|
||||
BIGNUM *res;
|
||||
BN_CTX *bnctx;
|
||||
|
||||
if (TEST_FAIL())
|
||||
return -1;
|
||||
bnctx = BN_CTX_new();
|
||||
if (bnctx == NULL)
|
||||
return -1;
|
||||
@ -1054,6 +1225,8 @@ int crypto_bignum_sub(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *b,
|
||||
struct crypto_bignum *c)
|
||||
{
|
||||
if (TEST_FAIL())
|
||||
return -1;
|
||||
return BN_sub((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b) ?
|
||||
0 : -1;
|
||||
}
|
||||
@ -1067,6 +1240,9 @@ int crypto_bignum_div(const struct crypto_bignum *a,
|
||||
|
||||
BN_CTX *bnctx;
|
||||
|
||||
if (TEST_FAIL())
|
||||
return -1;
|
||||
|
||||
bnctx = BN_CTX_new();
|
||||
if (bnctx == NULL)
|
||||
return -1;
|
||||
@ -1087,6 +1263,9 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a,
|
||||
|
||||
BN_CTX *bnctx;
|
||||
|
||||
if (TEST_FAIL())
|
||||
return -1;
|
||||
|
||||
bnctx = BN_CTX_new();
|
||||
if (bnctx == NULL)
|
||||
return -1;
|
||||
@ -1130,6 +1309,9 @@ int crypto_bignum_legendre(const struct crypto_bignum *a,
|
||||
BIGNUM *exp = NULL, *tmp = NULL;
|
||||
int res = -2;
|
||||
|
||||
if (TEST_FAIL())
|
||||
return -2;
|
||||
|
||||
bnctx = BN_CTX_new();
|
||||
if (bnctx == NULL)
|
||||
return -2;
|
||||
@ -1254,6 +1436,8 @@ void crypto_ec_deinit(struct crypto_ec *e)
|
||||
|
||||
struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e)
|
||||
{
|
||||
if (TEST_FAIL())
|
||||
return NULL;
|
||||
if (e == NULL)
|
||||
return NULL;
|
||||
return (struct crypto_ec_point *) EC_POINT_new(e->group);
|
||||
@ -1300,6 +1484,9 @@ int crypto_ec_point_to_bin(struct crypto_ec *e,
|
||||
int ret = -1;
|
||||
int len = BN_num_bytes(e->prime);
|
||||
|
||||
if (TEST_FAIL())
|
||||
return -1;
|
||||
|
||||
x_bn = BN_new();
|
||||
y_bn = BN_new();
|
||||
|
||||
@ -1330,6 +1517,9 @@ struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e,
|
||||
EC_POINT *elem;
|
||||
int len = BN_num_bytes(e->prime);
|
||||
|
||||
if (TEST_FAIL())
|
||||
return NULL;
|
||||
|
||||
x = BN_bin2bn(val, len, NULL);
|
||||
y = BN_bin2bn(val + len, len, NULL);
|
||||
elem = EC_POINT_new(e->group);
|
||||
@ -1357,6 +1547,8 @@ int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a,
|
||||
const struct crypto_ec_point *b,
|
||||
struct crypto_ec_point *c)
|
||||
{
|
||||
if (TEST_FAIL())
|
||||
return -1;
|
||||
return EC_POINT_add(e->group, (EC_POINT *) c, (const EC_POINT *) a,
|
||||
(const EC_POINT *) b, e->bnctx) ? 0 : -1;
|
||||
}
|
||||
@ -1366,6 +1558,8 @@ int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p,
|
||||
const struct crypto_bignum *b,
|
||||
struct crypto_ec_point *res)
|
||||
{
|
||||
if (TEST_FAIL())
|
||||
return -1;
|
||||
return EC_POINT_mul(e->group, (EC_POINT *) res, NULL,
|
||||
(const EC_POINT *) p, (const BIGNUM *) b, e->bnctx)
|
||||
? 0 : -1;
|
||||
@ -1374,6 +1568,8 @@ int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p,
|
||||
|
||||
int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p)
|
||||
{
|
||||
if (TEST_FAIL())
|
||||
return -1;
|
||||
return EC_POINT_invert(e->group, (EC_POINT *) p, e->bnctx) ? 0 : -1;
|
||||
}
|
||||
|
||||
@ -1382,6 +1578,8 @@ int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
|
||||
struct crypto_ec_point *p,
|
||||
const struct crypto_bignum *x, int y_bit)
|
||||
{
|
||||
if (TEST_FAIL())
|
||||
return -1;
|
||||
if (!EC_POINT_set_compressed_coordinates_GFp(e->group, (EC_POINT *) p,
|
||||
(const BIGNUM *) x, y_bit,
|
||||
e->bnctx) ||
|
||||
@ -1397,6 +1595,9 @@ crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
|
||||
{
|
||||
BIGNUM *tmp, *tmp2, *y_sqr = NULL;
|
||||
|
||||
if (TEST_FAIL())
|
||||
return NULL;
|
||||
|
||||
tmp = BN_new();
|
||||
tmp2 = BN_new();
|
||||
|
||||
|
@ -50,7 +50,7 @@ static int utf8_to_ucs2(const u8 *utf8_string, size_t utf8_string_len,
|
||||
WPA_PUT_LE16(ucs2_buffer + j,
|
||||
((c & 0x1F) << 6) | (c2 & 0x3F));
|
||||
j += 2;
|
||||
} else if (i == utf8_string_len ||
|
||||
} else if (i == utf8_string_len - 1 ||
|
||||
j >= ucs2_buffer_size - 1) {
|
||||
/* incomplete surrogate */
|
||||
return -1;
|
||||
|
@ -30,6 +30,9 @@ int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
|
||||
struct sha256_state ctx;
|
||||
size_t i;
|
||||
|
||||
if (TEST_FAIL())
|
||||
return -1;
|
||||
|
||||
sha256_init(&ctx);
|
||||
for (i = 0; i < num_elem; i++)
|
||||
if (sha256_process(&ctx, addr[i], len[i]))
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
/*
|
||||
* SHA256-based PRF (IEEE 802.11r)
|
||||
* Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
@ -24,14 +24,16 @@
|
||||
* @data_len: Length of the data
|
||||
* @buf: Buffer for the generated pseudo-random key
|
||||
* @buf_len: Number of bytes of key to generate
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function is used to derive new, cryptographically separate keys from a
|
||||
* given key.
|
||||
*/
|
||||
void sha256_prf(const u8 *key, size_t key_len, const char *label,
|
||||
int sha256_prf(const u8 *key, size_t key_len, const char *label,
|
||||
const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
|
||||
{
|
||||
sha256_prf_bits(key, key_len, label, data, data_len, buf, buf_len * 8);
|
||||
return sha256_prf_bits(key, key_len, label, data, data_len, buf,
|
||||
buf_len * 8);
|
||||
}
|
||||
|
||||
|
||||
@ -44,15 +46,16 @@ void sha256_prf(const u8 *key, size_t key_len, const char *label,
|
||||
* @data_len: Length of the data
|
||||
* @buf: Buffer for the generated pseudo-random key
|
||||
* @buf_len: Number of bits of key to generate
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function is used to derive new, cryptographically separate keys from a
|
||||
* given key. If the requested buf_len is not divisible by eight, the least
|
||||
* significant 1-7 bits of the last octet in the output are not part of the
|
||||
* requested output.
|
||||
*/
|
||||
void sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
|
||||
const u8 *data, size_t data_len, u8 *buf,
|
||||
size_t buf_len_bits)
|
||||
int sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
|
||||
const u8 *data, size_t data_len, u8 *buf,
|
||||
size_t buf_len_bits)
|
||||
{
|
||||
u16 counter = 1;
|
||||
size_t pos, plen;
|
||||
@ -77,11 +80,14 @@ void sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
|
||||
plen = buf_len - pos;
|
||||
WPA_PUT_LE16(counter_le, counter);
|
||||
if (plen >= SHA256_MAC_LEN) {
|
||||
hmac_sha256_vector(key, key_len, 4, addr, len,
|
||||
&buf[pos]);
|
||||
if (hmac_sha256_vector(key, key_len, 4, addr, len,
|
||||
&buf[pos]) < 0)
|
||||
return -1;
|
||||
pos += SHA256_MAC_LEN;
|
||||
} else {
|
||||
hmac_sha256_vector(key, key_len, 4, addr, len, hash);
|
||||
if (hmac_sha256_vector(key, key_len, 4, addr, len,
|
||||
hash) < 0)
|
||||
return -1;
|
||||
os_memcpy(&buf[pos], hash, plen);
|
||||
pos += plen;
|
||||
break;
|
||||
@ -99,4 +105,6 @@ void sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
|
||||
}
|
||||
|
||||
os_memset(hash, 0, sizeof(hash));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* SHA256 hash implementation and interface functions
|
||||
* Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
@ -15,11 +15,11 @@ int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
|
||||
const u8 *addr[], const size_t *len, u8 *mac);
|
||||
int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
|
||||
size_t data_len, u8 *mac);
|
||||
void sha256_prf(const u8 *key, size_t key_len, const char *label,
|
||||
const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
|
||||
void sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
|
||||
const u8 *data, size_t data_len, u8 *buf,
|
||||
size_t buf_len_bits);
|
||||
int sha256_prf(const u8 *key, size_t key_len, const char *label,
|
||||
const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
|
||||
int sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
|
||||
const u8 *data, size_t data_len, u8 *buf,
|
||||
size_t buf_len_bits);
|
||||
void tls_prf_sha256(const u8 *secret, size_t secret_len,
|
||||
const char *label, const u8 *seed, size_t seed_len,
|
||||
u8 *out, size_t outlen);
|
||||
|
@ -95,6 +95,8 @@ struct tls_config {
|
||||
#define TLS_CONN_DISABLE_TLSv1_2 BIT(6)
|
||||
#define TLS_CONN_EAP_FAST BIT(7)
|
||||
#define TLS_CONN_DISABLE_TLSv1_0 BIT(8)
|
||||
#define TLS_CONN_EXT_CERT_CHECK BIT(9)
|
||||
#define TLS_CONN_REQUIRE_OCSP_ALL BIT(10)
|
||||
|
||||
/**
|
||||
* struct tls_connection_params - Parameters for TLS connection
|
||||
@ -139,6 +141,9 @@ struct tls_config {
|
||||
* @flags: Parameter options (TLS_CONN_*)
|
||||
* @ocsp_stapling_response: DER encoded file with cached OCSP stapling response
|
||||
* or %NULL if OCSP is not enabled
|
||||
* @ocsp_stapling_response_multi: DER encoded file with cached OCSP stapling
|
||||
* response list (OCSPResponseList for ocsp_multi in RFC 6961) or %NULL if
|
||||
* ocsp_multi is not enabled
|
||||
*
|
||||
* TLS connection parameters to be configured with tls_connection_set_params()
|
||||
* and tls_global_set_params().
|
||||
@ -179,6 +184,7 @@ struct tls_connection_params {
|
||||
|
||||
unsigned int flags;
|
||||
const char *ocsp_stapling_response;
|
||||
const char *ocsp_stapling_response_multi;
|
||||
};
|
||||
|
||||
|
||||
@ -330,29 +336,36 @@ int __must_check tls_connection_get_random(void *tls_ctx,
|
||||
struct tls_random *data);
|
||||
|
||||
/**
|
||||
* tls_connection_prf - Use TLS-PRF to derive keying material
|
||||
* tls_connection_export_key - Derive keying material from a TLS connection
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* @label: Label (e.g., description of the key) for PRF
|
||||
* @server_random_first: seed is 0 = client_random|server_random,
|
||||
* 1 = server_random|client_random
|
||||
* @skip_keyblock: Skip TLS key block from the beginning of PRF output
|
||||
* @out: Buffer for output data from TLS-PRF
|
||||
* @out_len: Length of the output buffer
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* tls_connection_prf() is required so that further keying material can be
|
||||
* derived from the master secret. Example implementation of this function is in
|
||||
* tls_prf_sha1_md5() when it is called with seed set to
|
||||
* client_random|server_random (or server_random|client_random). For TLSv1.2 and
|
||||
* newer, a different PRF is needed, though.
|
||||
* Exports keying material using the mechanism described in RFC 5705.
|
||||
*/
|
||||
int __must_check tls_connection_prf(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const char *label,
|
||||
int server_random_first,
|
||||
int skip_keyblock,
|
||||
u8 *out, size_t out_len);
|
||||
int __must_check tls_connection_export_key(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const char *label,
|
||||
u8 *out, size_t out_len);
|
||||
|
||||
/**
|
||||
* tls_connection_get_eap_fast_key - Derive key material for EAP-FAST
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* @out: Buffer for output data from TLS-PRF
|
||||
* @out_len: Length of the output buffer
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* Exports key material after the normal TLS key block for use with
|
||||
* EAP-FAST. Most callers will want tls_connection_export_key(), but EAP-FAST
|
||||
* uses a different legacy mechanism.
|
||||
*/
|
||||
int __must_check tls_connection_get_eap_fast_key(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
u8 *out, size_t out_len);
|
||||
|
||||
/**
|
||||
* tls_connection_handshake - Process TLS handshake (client side)
|
||||
@ -455,7 +468,9 @@ enum {
|
||||
TLS_CIPHER_RC4_SHA /* 0x0005 */,
|
||||
TLS_CIPHER_AES128_SHA /* 0x002f */,
|
||||
TLS_CIPHER_RSA_DHE_AES128_SHA /* 0x0031 */,
|
||||
TLS_CIPHER_ANON_DH_AES128_SHA /* 0x0034 */
|
||||
TLS_CIPHER_ANON_DH_AES128_SHA /* 0x0034 */,
|
||||
TLS_CIPHER_RSA_DHE_AES256_SHA /* 0x0039 */,
|
||||
TLS_CIPHER_AES256_SHA /* 0x0035 */,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -25,6 +25,11 @@ struct tls_global {
|
||||
int server;
|
||||
struct tlsv1_credentials *server_cred;
|
||||
int check_crl;
|
||||
|
||||
void (*event_cb)(void *ctx, enum tls_event ev,
|
||||
union tls_event_data *data);
|
||||
void *cb_ctx;
|
||||
int cert_in_cb;
|
||||
};
|
||||
|
||||
struct tls_connection {
|
||||
@ -53,6 +58,11 @@ void * tls_init(const struct tls_config *conf)
|
||||
global = os_zalloc(sizeof(*global));
|
||||
if (global == NULL)
|
||||
return NULL;
|
||||
if (conf) {
|
||||
global->event_cb = conf->event_cb;
|
||||
global->cb_ctx = conf->cb_ctx;
|
||||
global->cert_in_cb = conf->cert_in_cb;
|
||||
}
|
||||
|
||||
return global;
|
||||
}
|
||||
@ -66,10 +76,12 @@ void tls_deinit(void *ssl_ctx)
|
||||
tlsv1_client_global_deinit();
|
||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||
tlsv1_cred_free(global->server_cred);
|
||||
tlsv1_server_global_deinit();
|
||||
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
}
|
||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||
tlsv1_cred_free(global->server_cred);
|
||||
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
os_free(global);
|
||||
}
|
||||
|
||||
@ -97,6 +109,8 @@ struct tls_connection * tls_connection_init(void *tls_ctx)
|
||||
os_free(conn);
|
||||
return NULL;
|
||||
}
|
||||
tlsv1_client_set_cb(conn->client, global->event_cb,
|
||||
global->cb_ctx, global->cert_in_cb);
|
||||
}
|
||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||
@ -188,6 +202,12 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
|
||||
if (conn->client == NULL)
|
||||
return -1;
|
||||
|
||||
if (params->flags & TLS_CONN_EXT_CERT_CHECK) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"TLS: tls_ext_cert_check=1 not supported");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cred = tlsv1_cred_alloc();
|
||||
if (cred == NULL)
|
||||
return -1;
|
||||
@ -261,8 +281,7 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
|
||||
return -1;
|
||||
}
|
||||
|
||||
tlsv1_client_set_time_checks(
|
||||
conn->client, !(params->flags & TLS_CONN_DISABLE_TIME_CHECKS));
|
||||
tlsv1_client_set_flags(conn->client, params->flags);
|
||||
|
||||
return 0;
|
||||
#else /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
@ -314,6 +333,13 @@ int tls_global_set_params(void *tls_ctx,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (params->ocsp_stapling_response)
|
||||
cred->ocsp_stapling_response =
|
||||
os_strdup(params->ocsp_stapling_response);
|
||||
if (params->ocsp_stapling_response_multi)
|
||||
cred->ocsp_stapling_response_multi =
|
||||
os_strdup(params->ocsp_stapling_response_multi);
|
||||
|
||||
return 0;
|
||||
#else /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
return -1;
|
||||
@ -370,9 +396,9 @@ static int tls_get_keyblock_size(struct tls_connection *conn)
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
|
||||
const char *label, int server_random_first,
|
||||
int skip_keyblock, u8 *out, size_t out_len)
|
||||
static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
|
||||
const char *label, int server_random_first,
|
||||
int skip_keyblock, u8 *out, size_t out_len)
|
||||
{
|
||||
int ret = -1, skip = 0;
|
||||
u8 *tmp_out = NULL;
|
||||
@ -392,14 +418,14 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
|
||||
if (conn->client) {
|
||||
ret = tlsv1_client_prf(conn->client, label,
|
||||
server_random_first,
|
||||
_out, out_len);
|
||||
_out, skip + out_len);
|
||||
}
|
||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
||||
if (conn->server) {
|
||||
ret = tlsv1_server_prf(conn->server, label,
|
||||
server_random_first,
|
||||
_out, out_len);
|
||||
_out, skip + out_len);
|
||||
}
|
||||
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
||||
if (ret == 0 && skip_keyblock)
|
||||
@ -410,6 +436,21 @@ int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
|
||||
const char *label, u8 *out, size_t out_len)
|
||||
{
|
||||
return tls_connection_prf(tls_ctx, conn, label, 0, 0, out, out_len);
|
||||
}
|
||||
|
||||
|
||||
int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
|
||||
u8 *out, size_t out_len)
|
||||
{
|
||||
return tls_connection_prf(tls_ctx, conn, "key expansion", 1, 1, out,
|
||||
out_len);
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * tls_connection_handshake(void *tls_ctx,
|
||||
struct tls_connection *conn,
|
||||
const struct wpabuf *in_data,
|
||||
@ -623,7 +664,12 @@ int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
|
||||
int tls_get_version(void *ssl_ctx, struct tls_connection *conn,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
/* TODO */
|
||||
if (conn == NULL)
|
||||
return -1;
|
||||
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
||||
if (conn->client)
|
||||
return tlsv1_client_get_version(conn->client, buf, buflen);
|
||||
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,22 @@
|
||||
#define HOSTAPD_CHAN_INDOOR_ONLY 0x00010000
|
||||
#define HOSTAPD_CHAN_GO_CONCURRENT 0x00020000
|
||||
|
||||
#define HOSTAPD_CHAN_VHT_10_150 0x00100000
|
||||
#define HOSTAPD_CHAN_VHT_30_130 0x00200000
|
||||
#define HOSTAPD_CHAN_VHT_50_110 0x00400000
|
||||
#define HOSTAPD_CHAN_VHT_70_90 0x00800000
|
||||
#define HOSTAPD_CHAN_VHT_90_70 0x01000000
|
||||
#define HOSTAPD_CHAN_VHT_110_50 0x02000000
|
||||
#define HOSTAPD_CHAN_VHT_130_30 0x04000000
|
||||
#define HOSTAPD_CHAN_VHT_150_10 0x08000000
|
||||
|
||||
/* Filter gratuitous ARP */
|
||||
#define WPA_DATA_FRAME_FILTER_FLAG_ARP BIT(0)
|
||||
/* Filter unsolicited Neighbor Advertisement */
|
||||
#define WPA_DATA_FRAME_FILTER_FLAG_NA BIT(1)
|
||||
/* Filter unicast IP packets encrypted using the GTK */
|
||||
#define WPA_DATA_FRAME_FILTER_FLAG_GTK BIT(2)
|
||||
|
||||
/**
|
||||
* enum reg_change_initiator - Regulatory change initiator
|
||||
*/
|
||||
@ -283,6 +299,18 @@ struct wpa_interface_info {
|
||||
|
||||
#define WPAS_MAX_SCAN_SSIDS 16
|
||||
|
||||
/**
|
||||
* struct wpa_driver_scan_ssid - SSIDs to scan for
|
||||
* @ssid - specific SSID to scan for (ProbeReq)
|
||||
* %NULL or zero-length SSID is used to indicate active scan
|
||||
* with wildcard SSID.
|
||||
* @ssid_len - Length of the SSID in octets
|
||||
*/
|
||||
struct wpa_driver_scan_ssid {
|
||||
const u8 *ssid;
|
||||
size_t ssid_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wpa_driver_scan_params - Scan parameters
|
||||
* Data for struct wpa_driver_ops::scan2().
|
||||
@ -291,18 +319,7 @@ struct wpa_driver_scan_params {
|
||||
/**
|
||||
* ssids - SSIDs to scan for
|
||||
*/
|
||||
struct wpa_driver_scan_ssid {
|
||||
/**
|
||||
* ssid - specific SSID to scan for (ProbeReq)
|
||||
* %NULL or zero-length SSID is used to indicate active scan
|
||||
* with wildcard SSID.
|
||||
*/
|
||||
const u8 *ssid;
|
||||
/**
|
||||
* ssid_len: Length of the SSID in octets
|
||||
*/
|
||||
size_t ssid_len;
|
||||
} ssids[WPAS_MAX_SCAN_SSIDS];
|
||||
struct wpa_driver_scan_ssid ssids[WPAS_MAX_SCAN_SSIDS];
|
||||
|
||||
/**
|
||||
* num_ssids - Number of entries in ssids array
|
||||
@ -407,6 +424,37 @@ struct wpa_driver_scan_params {
|
||||
*/
|
||||
const u8 *mac_addr_mask;
|
||||
|
||||
/**
|
||||
* sched_scan_plans - Scan plans for scheduled scan
|
||||
*
|
||||
* Each scan plan consists of the number of iterations to scan and the
|
||||
* interval between scans. When a scan plan finishes (i.e., it was run
|
||||
* for the specified number of iterations), the next scan plan is
|
||||
* executed. The scan plans are executed in the order they appear in
|
||||
* the array (lower index first). The last scan plan will run infinitely
|
||||
* (until requested to stop), thus must not specify the number of
|
||||
* iterations. All other scan plans must specify the number of
|
||||
* iterations.
|
||||
*/
|
||||
struct sched_scan_plan {
|
||||
u32 interval; /* In seconds */
|
||||
u32 iterations; /* Zero to run infinitely */
|
||||
} *sched_scan_plans;
|
||||
|
||||
/**
|
||||
* sched_scan_plans_num - Number of scan plans in sched_scan_plans array
|
||||
*/
|
||||
unsigned int sched_scan_plans_num;
|
||||
|
||||
/**
|
||||
* bssid - Specific BSSID to scan for
|
||||
*
|
||||
* This optional parameter can be used to replace the default wildcard
|
||||
* BSSID with a specific BSSID to scan for if results are needed from
|
||||
* only a single BSS.
|
||||
*/
|
||||
const u8 *bssid;
|
||||
|
||||
/*
|
||||
* NOTE: Whenever adding new parameters here, please make sure
|
||||
* wpa_scan_clone_params() and wpa_scan_free_params() get updated with
|
||||
@ -828,6 +876,12 @@ struct wpa_driver_associate_params {
|
||||
* RRM (Radio Resource Measurements)
|
||||
*/
|
||||
int rrm_used;
|
||||
|
||||
/**
|
||||
* pbss - If set, connect to a PCP in a PBSS. Otherwise, connect to an
|
||||
* AP as usual. Valid for DMG network only.
|
||||
*/
|
||||
int pbss;
|
||||
};
|
||||
|
||||
enum hide_ssid {
|
||||
@ -1055,16 +1109,28 @@ struct wpa_driver_ap_params {
|
||||
* reenable - Whether this is to re-enable beaconing
|
||||
*/
|
||||
int reenable;
|
||||
|
||||
/**
|
||||
* pbss - Whether to start a PCP (in PBSS) instead of an AP in
|
||||
* infrastructure BSS. Valid only for DMG network.
|
||||
*/
|
||||
int pbss;
|
||||
};
|
||||
|
||||
struct wpa_driver_mesh_bss_params {
|
||||
#define WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS 0x00000001
|
||||
#define WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS 0x00000001
|
||||
#define WPA_DRIVER_MESH_CONF_FLAG_PEER_LINK_TIMEOUT 0x00000002
|
||||
#define WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS 0x00000004
|
||||
#define WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE 0x00000008
|
||||
/*
|
||||
* TODO: Other mesh configuration parameters would go here.
|
||||
* See NL80211_MESHCONF_* for all the mesh config parameters.
|
||||
*/
|
||||
unsigned int flags;
|
||||
int auto_plinks;
|
||||
int peer_link_timeout;
|
||||
int max_peer_links;
|
||||
u16 ht_opmode;
|
||||
};
|
||||
|
||||
struct wpa_driver_mesh_join_params {
|
||||
@ -1075,7 +1141,7 @@ struct wpa_driver_mesh_join_params {
|
||||
int ie_len;
|
||||
struct hostapd_freq_params freq;
|
||||
int beacon_int;
|
||||
int max_peer_links;
|
||||
int dtim_period;
|
||||
struct wpa_driver_mesh_bss_params conf;
|
||||
#define WPA_DRIVER_MESH_FLAG_USER_MPM 0x00000001
|
||||
#define WPA_DRIVER_MESH_FLAG_DRIVER_MPM 0x00000002
|
||||
@ -1214,8 +1280,17 @@ struct wpa_driver_capa {
|
||||
#define WPA_DRIVER_FLAGS_VHT_IBSS 0x0000002000000000ULL
|
||||
/** Driver supports automatic band selection */
|
||||
#define WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY 0x0000004000000000ULL
|
||||
/** Driver supports simultaneous off-channel operations */
|
||||
#define WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS 0x0000008000000000ULL
|
||||
/** Driver supports full AP client state */
|
||||
#define WPA_DRIVER_FLAGS_FULL_AP_CLIENT_STATE 0x0000010000000000ULL
|
||||
/** Driver supports P2P Listen offload */
|
||||
#define WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD 0x0000020000000000ULL
|
||||
u64 flags;
|
||||
|
||||
#define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \
|
||||
(drv_flags & WPA_DRIVER_FLAGS_FULL_AP_CLIENT_STATE)
|
||||
|
||||
#define WPA_DRIVER_SMPS_MODE_STATIC 0x00000001
|
||||
#define WPA_DRIVER_SMPS_MODE_DYNAMIC 0x00000002
|
||||
unsigned int smps_modes;
|
||||
@ -1231,6 +1306,15 @@ struct wpa_driver_capa {
|
||||
/** Maximum number of supported active probe SSIDs for sched_scan */
|
||||
int max_sched_scan_ssids;
|
||||
|
||||
/** Maximum number of supported scan plans for scheduled scan */
|
||||
unsigned int max_sched_scan_plans;
|
||||
|
||||
/** Maximum interval in a scan plan. In seconds */
|
||||
u32 max_sched_scan_plan_interval;
|
||||
|
||||
/** Maximum number of iterations in a single scan plan */
|
||||
u32 max_sched_scan_plan_iterations;
|
||||
|
||||
/** Whether sched_scan (offloaded scanning) is supported */
|
||||
int sched_scan_supported;
|
||||
|
||||
@ -1296,6 +1380,12 @@ struct wpa_driver_capa {
|
||||
* offset, namely the 6th byte in the Action frame body.
|
||||
*/
|
||||
#define WPA_DRIVER_FLAGS_TX_POWER_INSERTION 0x00000008
|
||||
/**
|
||||
* Driver supports RRM. With this support, the driver will accept to use RRM in
|
||||
* (Re)Association Request frames, without supporting quiet period.
|
||||
*/
|
||||
#define WPA_DRIVER_FLAGS_SUPPORT_RRM 0x00000010
|
||||
|
||||
u32 rrm_flags;
|
||||
|
||||
/* Driver concurrency capabilities */
|
||||
@ -1304,13 +1394,18 @@ struct wpa_driver_capa {
|
||||
unsigned int max_conc_chan_2_4;
|
||||
/* Maximum number of concurrent channels on 5 GHz */
|
||||
unsigned int max_conc_chan_5_0;
|
||||
|
||||
/* Maximum number of supported CSA counters */
|
||||
u16 max_csa_counters;
|
||||
};
|
||||
|
||||
|
||||
struct hostapd_data;
|
||||
|
||||
struct hostap_sta_driver_data {
|
||||
unsigned long rx_packets, tx_packets, rx_bytes, tx_bytes;
|
||||
unsigned long rx_packets, tx_packets;
|
||||
unsigned long long rx_bytes, tx_bytes;
|
||||
int bytes_64bit; /* whether 64-bit byte counters are supported */
|
||||
unsigned long current_tx_rate;
|
||||
unsigned long inactive_msec;
|
||||
unsigned long flags;
|
||||
@ -1336,6 +1431,7 @@ struct hostapd_sta_add_params {
|
||||
u32 flags_mask; /* unset bits in flags */
|
||||
#ifdef CONFIG_MESH
|
||||
enum mesh_plink_state plink_state;
|
||||
u16 peer_aid;
|
||||
#endif /* CONFIG_MESH */
|
||||
int set; /* Set STA parameters instead of add */
|
||||
u8 qosinfo;
|
||||
@ -1345,6 +1441,7 @@ struct hostapd_sta_add_params {
|
||||
size_t supp_channels_len;
|
||||
const u8 *supp_oper_classes;
|
||||
size_t supp_oper_classes_len;
|
||||
int support_p2p_ps;
|
||||
};
|
||||
|
||||
struct mac_address {
|
||||
@ -1450,6 +1547,7 @@ struct wpa_bss_params {
|
||||
#define WPA_STA_MFP BIT(3)
|
||||
#define WPA_STA_TDLS_PEER BIT(4)
|
||||
#define WPA_STA_AUTHENTICATED BIT(5)
|
||||
#define WPA_STA_ASSOCIATED BIT(6)
|
||||
|
||||
enum tdls_oper {
|
||||
TDLS_DISCOVERY_REQ,
|
||||
@ -1554,8 +1652,8 @@ struct csa_settings {
|
||||
struct beacon_data beacon_csa;
|
||||
struct beacon_data beacon_after;
|
||||
|
||||
u16 counter_offset_beacon;
|
||||
u16 counter_offset_presp;
|
||||
u16 counter_offset_beacon[2];
|
||||
u16 counter_offset_presp[2];
|
||||
};
|
||||
|
||||
/* TDLS peer capabilities for send_tdls_mgmt() */
|
||||
@ -1882,6 +1980,14 @@ struct wpa_driver_ops {
|
||||
*/
|
||||
void (*poll)(void *priv);
|
||||
|
||||
/**
|
||||
* get_ifindex - Get interface index
|
||||
* @priv: private driver interface data
|
||||
*
|
||||
* Returns: Interface index
|
||||
*/
|
||||
unsigned int (*get_ifindex)(void *priv);
|
||||
|
||||
/**
|
||||
* get_ifname - Get interface name
|
||||
* @priv: private driver interface data
|
||||
@ -1960,10 +2066,13 @@ struct wpa_driver_ops {
|
||||
* @noack: Do not wait for this frame to be acked (disable retries)
|
||||
* @freq: Frequency (in MHz) to send the frame on, or 0 to let the
|
||||
* driver decide
|
||||
* @csa_offs: Array of CSA offsets or %NULL
|
||||
* @csa_offs_len: Number of elements in csa_offs
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int (*send_mlme)(void *priv, const u8 *data, size_t data_len,
|
||||
int noack, unsigned int freq);
|
||||
int noack, unsigned int freq, const u16 *csa_offs,
|
||||
size_t csa_offs_len);
|
||||
|
||||
/**
|
||||
* update_ft_ies - Update FT (IEEE 802.11r) IEs
|
||||
@ -2013,6 +2122,7 @@ struct wpa_driver_ops {
|
||||
|
||||
/**
|
||||
* global_init - Global driver initialization
|
||||
* @ctx: wpa_global pointer
|
||||
* Returns: Pointer to private data (global), %NULL on failure
|
||||
*
|
||||
* This optional function is called to initialize the driver wrapper
|
||||
@ -2022,7 +2132,7 @@ struct wpa_driver_ops {
|
||||
* use init2() function instead of init() to get the pointer to global
|
||||
* data available to per-interface initializer.
|
||||
*/
|
||||
void * (*global_init)(void);
|
||||
void * (*global_init)(void *ctx);
|
||||
|
||||
/**
|
||||
* global_deinit - Global driver deinitialization
|
||||
@ -2308,12 +2418,17 @@ struct wpa_driver_ops {
|
||||
* @params: Station parameters
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function is used to add a station entry to the driver once the
|
||||
* station has completed association. This is only used if the driver
|
||||
* This function is used to add or set (params->set 1) a station
|
||||
* entry in the driver. Adding STA entries is used only if the driver
|
||||
* does not take care of association processing.
|
||||
*
|
||||
* With TDLS, this function is also used to add or set (params->set 1)
|
||||
* TDLS peer entries.
|
||||
* With drivers that don't support full AP client state, this function
|
||||
* is used to add a station entry to the driver once the station has
|
||||
* completed association.
|
||||
*
|
||||
* With TDLS, this function is used to add or set (params->set 1)
|
||||
* TDLS peer entries (even with drivers that do not support full AP
|
||||
* client state).
|
||||
*/
|
||||
int (*sta_add)(void *priv, struct hostapd_sta_add_params *params);
|
||||
|
||||
@ -2399,12 +2514,13 @@ struct wpa_driver_ops {
|
||||
* change interface address)
|
||||
* @bridge: Bridge interface to use or %NULL if no bridge configured
|
||||
* @use_existing: Whether to allow existing interface to be used
|
||||
* @setup_ap: Whether to setup AP for %WPA_IF_AP_BSS interfaces
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int (*if_add)(void *priv, enum wpa_driver_if_type type,
|
||||
const char *ifname, const u8 *addr, void *bss_ctx,
|
||||
void **drv_priv, char *force_ifname, u8 *if_addr,
|
||||
const char *bridge, int use_existing);
|
||||
const char *bridge, int use_existing, int setup_ap);
|
||||
|
||||
/**
|
||||
* if_remove - Remove a virtual interface
|
||||
@ -2986,7 +3102,6 @@ struct wpa_driver_ops {
|
||||
* sched_scan - Request the driver to initiate scheduled scan
|
||||
* @priv: Private driver interface data
|
||||
* @params: Scan parameters
|
||||
* @interval: Interval between scan cycles in milliseconds
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This operation should be used for scheduled scan offload to
|
||||
@ -2997,8 +3112,7 @@ struct wpa_driver_ops {
|
||||
* and if not provided or if it returns -1, we fall back to
|
||||
* normal host-scheduled scans.
|
||||
*/
|
||||
int (*sched_scan)(void *priv, struct wpa_driver_scan_params *params,
|
||||
u32 interval);
|
||||
int (*sched_scan)(void *priv, struct wpa_driver_scan_params *params);
|
||||
|
||||
/**
|
||||
* stop_sched_scan - Request the driver to stop a scheduled scan
|
||||
@ -3203,11 +3317,9 @@ struct wpa_driver_ops {
|
||||
* set_current_cipher_suite - Set current cipher suite
|
||||
* @priv: Private driver interface data
|
||||
* @cs: EUI64 identifier
|
||||
* @cs_len: Length of the cs buffer in octets
|
||||
* Returns: 0 on success, -1 on failure (or if not supported)
|
||||
*/
|
||||
int (*set_current_cipher_suite)(void *priv, const u8 *cs,
|
||||
size_t cs_len);
|
||||
int (*set_current_cipher_suite)(void *priv, u64 cs);
|
||||
|
||||
/**
|
||||
* enable_controlled_port - Set controlled port status
|
||||
@ -3439,6 +3551,78 @@ struct wpa_driver_ops {
|
||||
* on. Local device is assuming P2P Client role.
|
||||
*/
|
||||
int (*set_prob_oper_freq)(void *priv, unsigned int freq);
|
||||
|
||||
/**
|
||||
* abort_scan - Request the driver to abort an ongoing scan
|
||||
* @priv: Private driver interface data
|
||||
* Returns 0 on success, -1 on failure
|
||||
*/
|
||||
int (*abort_scan)(void *priv);
|
||||
|
||||
/**
|
||||
* configure_data_frame_filters - Request to configure frame filters
|
||||
* @priv: Private driver interface data
|
||||
* @filter_flags: The type of frames to filter (bitfield of
|
||||
* WPA_DATA_FRAME_FILTER_FLAG_*)
|
||||
* Returns: 0 on success or -1 on failure
|
||||
*/
|
||||
int (*configure_data_frame_filters)(void *priv, u32 filter_flags);
|
||||
|
||||
/**
|
||||
* get_ext_capab - Get extended capabilities for the specified interface
|
||||
* @priv: Private driver interface data
|
||||
* @type: Interface type for which to get extended capabilities
|
||||
* @ext_capab: Extended capabilities fetched
|
||||
* @ext_capab_mask: Extended capabilities mask
|
||||
* @ext_capab_len: Length of the extended capabilities
|
||||
* Returns: 0 on success or -1 on failure
|
||||
*/
|
||||
int (*get_ext_capab)(void *priv, enum wpa_driver_if_type type,
|
||||
const u8 **ext_capab, const u8 **ext_capab_mask,
|
||||
unsigned int *ext_capab_len);
|
||||
|
||||
/**
|
||||
* p2p_lo_start - Start offloading P2P listen to device
|
||||
* @priv: Private driver interface data
|
||||
* @freq: Listening frequency (MHz) for P2P listen
|
||||
* @period: Length of the listen operation in milliseconds
|
||||
* @interval: Interval for running the listen operation in milliseconds
|
||||
* @count: Number of times to run the listen operation
|
||||
* @device_types: Device primary and secondary types
|
||||
* @dev_types_len: Number of bytes for device_types
|
||||
* @ies: P2P IE and WSC IE for Probe Response frames
|
||||
* @ies_len: Length of ies in bytes
|
||||
* Returns: 0 on success or -1 on failure
|
||||
*/
|
||||
int (*p2p_lo_start)(void *priv, unsigned int freq,
|
||||
unsigned int period, unsigned int interval,
|
||||
unsigned int count,
|
||||
const u8 *device_types, size_t dev_types_len,
|
||||
const u8 *ies, size_t ies_len);
|
||||
|
||||
/**
|
||||
* p2p_lo_stop - Stop P2P listen offload
|
||||
* @priv: Private driver interface data
|
||||
* Returns: 0 on success or -1 on failure
|
||||
*/
|
||||
int (*p2p_lo_stop)(void *priv);
|
||||
|
||||
/**
|
||||
* set_default_scan_ies - Set default scan IEs
|
||||
* @priv: Private driver interface data
|
||||
* @ies: Scan default IEs buffer
|
||||
* @ies_len: Length of IEs in bytes
|
||||
* Returns: 0 on success or -1 on failure
|
||||
*
|
||||
* The driver can use these by default when there are no scan IEs coming
|
||||
* in the subsequent scan requests. Also in case of one or more of IEs
|
||||
* given in set_default_scan_ies() are missing in the subsequent scan
|
||||
* request, the driver should merge the missing scan IEs in the scan
|
||||
* request from the IEs set by set_default_scan_ies() in the Probe
|
||||
* Request frames sent.
|
||||
*/
|
||||
int (*set_default_scan_ies)(void *priv, const u8 *ies, size_t ies_len);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -3923,6 +4107,11 @@ enum wpa_event_type {
|
||||
* on a DFS frequency by a driver that supports DFS Offload.
|
||||
*/
|
||||
EVENT_DFS_CAC_STARTED,
|
||||
|
||||
/**
|
||||
* EVENT_P2P_LO_STOP - Notify that P2P listen offload is stopped
|
||||
*/
|
||||
EVENT_P2P_LO_STOP,
|
||||
};
|
||||
|
||||
|
||||
@ -4098,6 +4287,12 @@ union wpa_event_data {
|
||||
* ptk_kek_len - The length of ptk_kek
|
||||
*/
|
||||
size_t ptk_kek_len;
|
||||
|
||||
/**
|
||||
* subnet_status - The subnet status:
|
||||
* 0 = unknown, 1 = unchanged, 2 = changed
|
||||
*/
|
||||
u8 subnet_status;
|
||||
} assoc_info;
|
||||
|
||||
/**
|
||||
@ -4174,6 +4369,7 @@ union wpa_event_data {
|
||||
* struct interface_status - Data for EVENT_INTERFACE_STATUS
|
||||
*/
|
||||
struct interface_status {
|
||||
unsigned int ifindex;
|
||||
char ifname[100];
|
||||
enum {
|
||||
EVENT_INTERFACE_ADDED, EVENT_INTERFACE_REMOVED
|
||||
@ -4301,6 +4497,12 @@ union wpa_event_data {
|
||||
* status_code - Status Code from (Re)association Response
|
||||
*/
|
||||
u16 status_code;
|
||||
|
||||
/**
|
||||
* timed_out - Whether failure is due to timeout (etc.) rather
|
||||
* than explicit rejection response from the AP.
|
||||
*/
|
||||
int timed_out;
|
||||
} assoc_reject;
|
||||
|
||||
struct timeout_event {
|
||||
@ -4381,6 +4583,9 @@ union wpa_event_data {
|
||||
* @ssids: Scanned SSIDs (%NULL or zero-length SSID indicates wildcard
|
||||
* SSID)
|
||||
* @num_ssids: Number of entries in ssids array
|
||||
* @external_scan: Whether the scan info is for an external scan
|
||||
* @nl_scan_event: 1 if the source of this scan event is a normal scan,
|
||||
* 0 if the source of the scan event is a vendor scan
|
||||
*/
|
||||
struct scan_info {
|
||||
int aborted;
|
||||
@ -4388,6 +4593,8 @@ union wpa_event_data {
|
||||
size_t num_freqs;
|
||||
struct wpa_driver_scan_ssid ssids[WPAS_MAX_SCAN_SSIDS];
|
||||
size_t num_ssids;
|
||||
int external_scan;
|
||||
int nl_scan_event;
|
||||
} scan_info;
|
||||
|
||||
/**
|
||||
@ -4630,6 +4837,27 @@ union wpa_event_data {
|
||||
u16 ch_width;
|
||||
enum hostapd_hw_mode hw_mode;
|
||||
} acs_selected_channels;
|
||||
|
||||
/**
|
||||
* struct p2p_lo_stop - Reason code for P2P Listen offload stop event
|
||||
* @reason_code: Reason for stopping offload
|
||||
* P2P_LO_STOPPED_REASON_COMPLETE: Listen offload finished as
|
||||
* scheduled.
|
||||
* P2P_LO_STOPPED_REASON_RECV_STOP_CMD: Host requested offload to
|
||||
* be stopped.
|
||||
* P2P_LO_STOPPED_REASON_INVALID_PARAM: Invalid listen offload
|
||||
* parameters.
|
||||
* P2P_LO_STOPPED_REASON_NOT_SUPPORTED: Listen offload not
|
||||
* supported by device.
|
||||
*/
|
||||
struct p2p_lo_stop {
|
||||
enum {
|
||||
P2P_LO_STOPPED_REASON_COMPLETE = 0,
|
||||
P2P_LO_STOPPED_REASON_RECV_STOP_CMD,
|
||||
P2P_LO_STOPPED_REASON_INVALID_PARAM,
|
||||
P2P_LO_STOPPED_REASON_NOT_SUPPORTED,
|
||||
} reason_code;
|
||||
} p2p_lo_stop;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -4645,6 +4873,18 @@ union wpa_event_data {
|
||||
void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
||||
union wpa_event_data *data);
|
||||
|
||||
/**
|
||||
* wpa_supplicant_event_global - Report a driver event for wpa_supplicant
|
||||
* @ctx: Context pointer (wpa_s); this is the ctx variable registered
|
||||
* with struct wpa_driver_ops::init()
|
||||
* @event: event type (defined above)
|
||||
* @data: possible extra data for the event
|
||||
*
|
||||
* Same as wpa_supplicant_event(), but we search for the interface in
|
||||
* wpa_global.
|
||||
*/
|
||||
void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
|
||||
union wpa_event_data *data);
|
||||
|
||||
/*
|
||||
* The following inline functions are provided for convenience to simplify
|
||||
@ -4697,8 +4937,52 @@ int vht_supported(const struct hostapd_hw_modes *mode);
|
||||
struct wowlan_triggers *
|
||||
wpa_get_wowlan_triggers(const char *wowlan_triggers,
|
||||
const struct wpa_driver_capa *capa);
|
||||
/* Convert driver flag to string */
|
||||
const char * driver_flag_to_string(u64 flag);
|
||||
|
||||
/* NULL terminated array of linked in driver wrappers */
|
||||
extern const struct wpa_driver_ops *const wpa_drivers[];
|
||||
|
||||
|
||||
/* Available drivers */
|
||||
|
||||
#ifdef CONFIG_DRIVER_WEXT
|
||||
extern const struct wpa_driver_ops wpa_driver_wext_ops; /* driver_wext.c */
|
||||
#endif /* CONFIG_DRIVER_WEXT */
|
||||
#ifdef CONFIG_DRIVER_NL80211
|
||||
/* driver_nl80211.c */
|
||||
extern const struct wpa_driver_ops wpa_driver_nl80211_ops;
|
||||
#endif /* CONFIG_DRIVER_NL80211 */
|
||||
#ifdef CONFIG_DRIVER_HOSTAP
|
||||
extern const struct wpa_driver_ops wpa_driver_hostap_ops; /* driver_hostap.c */
|
||||
#endif /* CONFIG_DRIVER_HOSTAP */
|
||||
#ifdef CONFIG_DRIVER_BSD
|
||||
extern const struct wpa_driver_ops wpa_driver_bsd_ops; /* driver_bsd.c */
|
||||
#endif /* CONFIG_DRIVER_BSD */
|
||||
#ifdef CONFIG_DRIVER_OPENBSD
|
||||
/* driver_openbsd.c */
|
||||
extern const struct wpa_driver_ops wpa_driver_openbsd_ops;
|
||||
#endif /* CONFIG_DRIVER_OPENBSD */
|
||||
#ifdef CONFIG_DRIVER_NDIS
|
||||
extern struct wpa_driver_ops wpa_driver_ndis_ops; /* driver_ndis.c */
|
||||
#endif /* CONFIG_DRIVER_NDIS */
|
||||
#ifdef CONFIG_DRIVER_WIRED
|
||||
extern const struct wpa_driver_ops wpa_driver_wired_ops; /* driver_wired.c */
|
||||
#endif /* CONFIG_DRIVER_WIRED */
|
||||
#ifdef CONFIG_DRIVER_MACSEC_QCA
|
||||
/* driver_macsec_qca.c */
|
||||
extern const struct wpa_driver_ops wpa_driver_macsec_qca_ops;
|
||||
#endif /* CONFIG_DRIVER_MACSEC_QCA */
|
||||
#ifdef CONFIG_DRIVER_ROBOSWITCH
|
||||
/* driver_roboswitch.c */
|
||||
extern const struct wpa_driver_ops wpa_driver_roboswitch_ops;
|
||||
#endif /* CONFIG_DRIVER_ROBOSWITCH */
|
||||
#ifdef CONFIG_DRIVER_ATHEROS
|
||||
/* driver_atheros.c */
|
||||
extern const struct wpa_driver_ops wpa_driver_atheros_ops;
|
||||
#endif /* CONFIG_DRIVER_ATHEROS */
|
||||
#ifdef CONFIG_DRIVER_NONE
|
||||
extern const struct wpa_driver_ops wpa_driver_none_ops; /* driver_none.c */
|
||||
#endif /* CONFIG_DRIVER_NONE */
|
||||
|
||||
#endif /* DRIVER_H */
|
||||
|
@ -49,14 +49,25 @@
|
||||
|
||||
#include "l2_packet/l2_packet.h"
|
||||
|
||||
struct bsd_driver_global {
|
||||
void *ctx;
|
||||
int sock; /* socket for 802.11 ioctls */
|
||||
int route; /* routing socket for events */
|
||||
char *event_buf;
|
||||
size_t event_buf_len;
|
||||
struct dl_list ifaces; /* list of interfaces */
|
||||
};
|
||||
|
||||
struct bsd_driver_data {
|
||||
struct dl_list list;
|
||||
struct bsd_driver_global *global;
|
||||
struct hostapd_data *hapd; /* back pointer */
|
||||
|
||||
int sock; /* open socket for 802.11 ioctls */
|
||||
struct l2_packet_data *sock_xmit;/* raw packet xmit socket */
|
||||
int route; /* routing socket for events */
|
||||
char ifname[IFNAMSIZ+1]; /* interface name */
|
||||
int flags;
|
||||
unsigned int ifindex; /* interface index */
|
||||
int if_removed; /* has the interface been removed? */
|
||||
void *ctx;
|
||||
struct wpa_driver_capa capa; /* driver capability */
|
||||
int is_ap; /* Access point mode */
|
||||
@ -64,17 +75,46 @@ struct bsd_driver_data {
|
||||
int prev_privacy; /* privacy state to restore on deinit */
|
||||
int prev_wpa; /* wpa state to restore on deinit */
|
||||
enum ieee80211_opmode opmode; /* operation mode */
|
||||
char *event_buf;
|
||||
size_t event_buf_len;
|
||||
};
|
||||
|
||||
/* Generic functions for hostapd and wpa_supplicant */
|
||||
static struct bsd_driver_data *
|
||||
bsd_get_drvindex(void *priv, unsigned int ifindex)
|
||||
{
|
||||
struct bsd_driver_global *global = priv;
|
||||
struct bsd_driver_data *drv;
|
||||
|
||||
dl_list_for_each(drv, &global->ifaces, struct bsd_driver_data, list) {
|
||||
if (drv->ifindex == ifindex)
|
||||
return drv;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef HOSTAPD
|
||||
static struct bsd_driver_data *
|
||||
bsd_get_drvname(void *priv, const char *ifname)
|
||||
{
|
||||
struct bsd_driver_global *global = priv;
|
||||
struct bsd_driver_data *drv;
|
||||
|
||||
dl_list_for_each(drv, &global->ifaces, struct bsd_driver_data, list) {
|
||||
if (os_strcmp(drv->ifname, ifname) == 0)
|
||||
return drv;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif /* HOSTAPD */
|
||||
|
||||
static int
|
||||
bsd_set80211(void *priv, int op, int val, const void *arg, int arg_len)
|
||||
{
|
||||
struct bsd_driver_data *drv = priv;
|
||||
struct ieee80211req ireq;
|
||||
|
||||
if (drv->ifindex == 0 || drv->if_removed)
|
||||
return -1;
|
||||
|
||||
os_memset(&ireq, 0, sizeof(ireq));
|
||||
os_strlcpy(ireq.i_name, drv->ifname, sizeof(ireq.i_name));
|
||||
ireq.i_type = op;
|
||||
@ -82,7 +122,7 @@ bsd_set80211(void *priv, int op, int val, const void *arg, int arg_len)
|
||||
ireq.i_data = (void *) arg;
|
||||
ireq.i_len = arg_len;
|
||||
|
||||
if (ioctl(drv->sock, SIOCS80211, &ireq) < 0) {
|
||||
if (ioctl(drv->global->sock, SIOCS80211, &ireq) < 0) {
|
||||
wpa_printf(MSG_ERROR, "ioctl[SIOCS80211, op=%u, val=%u, "
|
||||
"arg_len=%u]: %s", op, val, arg_len,
|
||||
strerror(errno));
|
||||
@ -103,7 +143,7 @@ bsd_get80211(void *priv, struct ieee80211req *ireq, int op, void *arg,
|
||||
ireq->i_len = arg_len;
|
||||
ireq->i_data = arg;
|
||||
|
||||
if (ioctl(drv->sock, SIOCG80211, ireq) < 0) {
|
||||
if (ioctl(drv->global->sock, SIOCG80211, ireq) < 0) {
|
||||
wpa_printf(MSG_ERROR, "ioctl[SIOCS80211, op=%u, "
|
||||
"arg_len=%u]: %s", op, arg_len, strerror(errno));
|
||||
return -1;
|
||||
@ -144,7 +184,7 @@ bsd_get_ssid(void *priv, u8 *ssid, int len)
|
||||
os_memset(&ifr, 0, sizeof(ifr));
|
||||
os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
|
||||
ifr.ifr_data = (void *)&nwid;
|
||||
if (ioctl(drv->sock, SIOCG80211NWID, &ifr) < 0 ||
|
||||
if (ioctl(drv->global->sock, SIOCG80211NWID, &ifr) < 0 ||
|
||||
nwid.i_len > IEEE80211_NWID_LEN)
|
||||
return -1;
|
||||
os_memcpy(ssid, nwid.i_nwid, nwid.i_len);
|
||||
@ -167,7 +207,7 @@ bsd_set_ssid(void *priv, const u8 *ssid, int ssid_len)
|
||||
os_memset(&ifr, 0, sizeof(ifr));
|
||||
os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
|
||||
ifr.ifr_data = (void *)&nwid;
|
||||
return ioctl(drv->sock, SIOCS80211NWID, &ifr);
|
||||
return ioctl(drv->global->sock, SIOCS80211NWID, &ifr);
|
||||
#else
|
||||
return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len);
|
||||
#endif
|
||||
@ -182,7 +222,7 @@ bsd_get_if_media(void *priv)
|
||||
os_memset(&ifmr, 0, sizeof(ifmr));
|
||||
os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name));
|
||||
|
||||
if (ioctl(drv->sock, SIOCGIFMEDIA, &ifmr) < 0) {
|
||||
if (ioctl(drv->global->sock, SIOCGIFMEDIA, &ifmr) < 0) {
|
||||
wpa_printf(MSG_ERROR, "%s: SIOCGIFMEDIA %s", __func__,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
@ -201,7 +241,7 @@ bsd_set_if_media(void *priv, int media)
|
||||
os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
|
||||
ifr.ifr_media = media;
|
||||
|
||||
if (ioctl(drv->sock, SIOCSIFMEDIA, &ifr) < 0) {
|
||||
if (ioctl(drv->global->sock, SIOCSIFMEDIA, &ifr) < 0) {
|
||||
wpa_printf(MSG_ERROR, "%s: SIOCSIFMEDIA %s", __func__,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
@ -264,11 +304,12 @@ bsd_ctrl_iface(void *priv, int enable)
|
||||
os_memset(&ifr, 0, sizeof(ifr));
|
||||
os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name));
|
||||
|
||||
if (ioctl(drv->sock, SIOCGIFFLAGS, &ifr) < 0) {
|
||||
if (ioctl(drv->global->sock, SIOCGIFFLAGS, &ifr) < 0) {
|
||||
wpa_printf(MSG_ERROR, "ioctl[SIOCGIFFLAGS]: %s",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
drv->flags = ifr.ifr_flags;
|
||||
|
||||
if (enable) {
|
||||
if (ifr.ifr_flags & IFF_UP)
|
||||
@ -280,12 +321,13 @@ bsd_ctrl_iface(void *priv, int enable)
|
||||
ifr.ifr_flags &= ~IFF_UP;
|
||||
}
|
||||
|
||||
if (ioctl(drv->sock, SIOCSIFFLAGS, &ifr) < 0) {
|
||||
if (ioctl(drv->global->sock, SIOCSIFFLAGS, &ifr) < 0) {
|
||||
wpa_printf(MSG_ERROR, "ioctl[SIOCSIFFLAGS]: %s",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
drv->flags = ifr.ifr_flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -577,7 +619,7 @@ bsd_set_freq(void *priv, struct hostapd_freq_params *freq)
|
||||
os_memset(&creq, 0, sizeof(creq));
|
||||
os_strlcpy(creq.i_name, drv->ifname, sizeof(creq.i_name));
|
||||
creq.i_channel = (u_int16_t)channel;
|
||||
return ioctl(drv->sock, SIOCS80211CHANNEL, &creq);
|
||||
return ioctl(drv->global->sock, SIOCS80211CHANNEL, &creq);
|
||||
#else /* SIOCS80211CHANNEL */
|
||||
return set80211param(priv, IEEE80211_IOC_CHANNEL, channel);
|
||||
#endif /* SIOCS80211CHANNEL */
|
||||
@ -731,7 +773,8 @@ bsd_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
|
||||
static void
|
||||
bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
|
||||
{
|
||||
struct bsd_driver_data *drv = ctx;
|
||||
struct bsd_driver_global *global = sock_ctx;
|
||||
struct bsd_driver_data *drv;
|
||||
struct if_announcemsghdr *ifan;
|
||||
struct rt_msghdr *rtm;
|
||||
struct ieee80211_michael_event *mic;
|
||||
@ -740,7 +783,7 @@ bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
|
||||
int n;
|
||||
union wpa_event_data data;
|
||||
|
||||
n = read(sock, drv->event_buf, drv->event_buf_len);
|
||||
n = read(sock, global->event_buf, global->event_buf_len);
|
||||
if (n < 0) {
|
||||
if (errno != EINTR && errno != EAGAIN)
|
||||
wpa_printf(MSG_ERROR, "%s read() failed: %s",
|
||||
@ -748,15 +791,18 @@ bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx)
|
||||
return;
|
||||
}
|
||||
|
||||
rtm = (struct rt_msghdr *) drv->event_buf;
|
||||
rtm = (struct rt_msghdr *) global->event_buf;
|
||||
if (rtm->rtm_version != RTM_VERSION) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid routing message version=%d",
|
||||
rtm->rtm_version);
|
||||
return;
|
||||
}
|
||||
ifan = (struct if_announcemsghdr *) rtm;
|
||||
switch (rtm->rtm_type) {
|
||||
case RTM_IEEE80211:
|
||||
ifan = (struct if_announcemsghdr *) rtm;
|
||||
drv = bsd_get_drvindex(global, ifan->ifan_index);
|
||||
if (drv == NULL)
|
||||
return;
|
||||
switch (ifan->ifan_what) {
|
||||
case RTM_IEEE80211_ASSOC:
|
||||
case RTM_IEEE80211_REASSOC:
|
||||
@ -812,21 +858,15 @@ bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
drv->event_buf_len = rtbuf_len();
|
||||
|
||||
drv->event_buf = os_malloc(drv->event_buf_len);
|
||||
if (drv->event_buf == NULL) {
|
||||
wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__);
|
||||
drv->ifindex = if_nametoindex(params->ifname);
|
||||
if (drv->ifindex == 0) {
|
||||
wpa_printf(MSG_DEBUG, "%s: interface %s does not exist",
|
||||
__func__, params->ifname);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
drv->hapd = hapd;
|
||||
drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (drv->sock < 0) {
|
||||
wpa_printf(MSG_ERROR, "socket[PF_INET,SOCK_DGRAM]: %s",
|
||||
strerror(errno));
|
||||
goto bad;
|
||||
}
|
||||
drv->global = params->global_priv;
|
||||
os_strlcpy(drv->ifname, params->ifname, sizeof(drv->ifname));
|
||||
|
||||
drv->sock_xmit = l2_packet_init(drv->ifname, NULL, ETH_P_EAPOL,
|
||||
@ -840,28 +880,18 @@ bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params)
|
||||
if (bsd_ctrl_iface(drv, 0) < 0)
|
||||
goto bad;
|
||||
|
||||
drv->route = socket(PF_ROUTE, SOCK_RAW, 0);
|
||||
if (drv->route < 0) {
|
||||
wpa_printf(MSG_ERROR, "socket(PF_ROUTE,SOCK_RAW): %s",
|
||||
strerror(errno));
|
||||
goto bad;
|
||||
}
|
||||
eloop_register_read_sock(drv->route, bsd_wireless_event_receive, drv,
|
||||
NULL);
|
||||
|
||||
if (bsd_set_mediaopt(drv, IFM_OMASK, IFM_IEEE80211_HOSTAP) < 0) {
|
||||
wpa_printf(MSG_ERROR, "%s: failed to set operation mode",
|
||||
__func__);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
dl_list_add(&drv->global->ifaces, &drv->list);
|
||||
|
||||
return drv;
|
||||
bad:
|
||||
if (drv->sock_xmit != NULL)
|
||||
l2_packet_deinit(drv->sock_xmit);
|
||||
if (drv->sock >= 0)
|
||||
close(drv->sock);
|
||||
os_free(drv->event_buf);
|
||||
os_free(drv);
|
||||
return NULL;
|
||||
}
|
||||
@ -872,16 +902,10 @@ bsd_deinit(void *priv)
|
||||
{
|
||||
struct bsd_driver_data *drv = priv;
|
||||
|
||||
if (drv->route >= 0) {
|
||||
eloop_unregister_read_sock(drv->route);
|
||||
close(drv->route);
|
||||
}
|
||||
bsd_ctrl_iface(drv, 0);
|
||||
if (drv->sock >= 0)
|
||||
close(drv->sock);
|
||||
if (drv->ifindex != 0)
|
||||
bsd_ctrl_iface(drv, 0);
|
||||
if (drv->sock_xmit != NULL)
|
||||
l2_packet_deinit(drv->sock_xmit);
|
||||
os_free(drv->event_buf);
|
||||
os_free(drv);
|
||||
}
|
||||
|
||||
@ -933,7 +957,7 @@ wpa_driver_bsd_get_bssid(void *priv, u8 *bssid)
|
||||
struct ieee80211_bssid bs;
|
||||
|
||||
os_strlcpy(bs.i_name, drv->ifname, sizeof(bs.i_name));
|
||||
if (ioctl(drv->sock, SIOCG80211BSSID, &bs) < 0)
|
||||
if (ioctl(drv->global->sock, SIOCG80211BSSID, &bs) < 0)
|
||||
return -1;
|
||||
os_memcpy(bssid, bs.i_bssid, sizeof(bs.i_bssid));
|
||||
return 0;
|
||||
@ -967,7 +991,7 @@ wpa_driver_bsd_set_wpa_internal(void *priv, int wpa, int privacy)
|
||||
int ret = 0;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s: wpa=%d privacy=%d",
|
||||
__FUNCTION__, wpa, privacy);
|
||||
__func__, wpa, privacy);
|
||||
|
||||
if (!wpa && wpa_driver_bsd_set_wpa_ie(priv, NULL, 0) < 0)
|
||||
ret = -1;
|
||||
@ -982,7 +1006,7 @@ wpa_driver_bsd_set_wpa_internal(void *priv, int wpa, int privacy)
|
||||
static int
|
||||
wpa_driver_bsd_set_wpa(void *priv, int enabled)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled);
|
||||
wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
|
||||
|
||||
return wpa_driver_bsd_set_wpa_internal(priv, enabled ? 3 : 0, enabled);
|
||||
}
|
||||
@ -1201,7 +1225,8 @@ wpa_driver_bsd_scan(void *priv, struct wpa_driver_scan_params *params)
|
||||
static void
|
||||
wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
|
||||
{
|
||||
struct bsd_driver_data *drv = sock_ctx;
|
||||
struct bsd_driver_global *global = sock_ctx;
|
||||
struct bsd_driver_data *drv;
|
||||
struct if_announcemsghdr *ifan;
|
||||
struct if_msghdr *ifm;
|
||||
struct rt_msghdr *rtm;
|
||||
@ -1211,7 +1236,12 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
|
||||
struct ieee80211_join_event *join;
|
||||
int n;
|
||||
|
||||
n = read(sock, drv->event_buf, drv->event_buf_len);
|
||||
/*
|
||||
* CID 1394785: Memory - illegal access (STRING_NULL):
|
||||
* Though global->event_buf is a char *, it actually contains
|
||||
* a struct rt_msghdr *. See below.
|
||||
*/
|
||||
n = read(sock, global->event_buf, global->event_buf_len);
|
||||
if (n < 0) {
|
||||
if (errno != EINTR && errno != EAGAIN)
|
||||
wpa_printf(MSG_ERROR, "%s read() failed: %s",
|
||||
@ -1219,7 +1249,11 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
|
||||
return;
|
||||
}
|
||||
|
||||
rtm = (struct rt_msghdr *) drv->event_buf;
|
||||
/*
|
||||
* CID 1394785: global->event_buf is assigned here to a
|
||||
* struct rt_msghdr *.
|
||||
*/
|
||||
rtm = (struct rt_msghdr *) global->event_buf;
|
||||
if (rtm->rtm_version != RTM_VERSION) {
|
||||
wpa_printf(MSG_DEBUG, "Invalid routing message version=%d",
|
||||
rtm->rtm_version);
|
||||
@ -1229,53 +1263,79 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
|
||||
switch (rtm->rtm_type) {
|
||||
case RTM_IFANNOUNCE:
|
||||
ifan = (struct if_announcemsghdr *) rtm;
|
||||
if (ifan->ifan_index != drv->ifindex)
|
||||
break;
|
||||
os_strlcpy(event.interface_status.ifname, drv->ifname,
|
||||
sizeof(event.interface_status.ifname));
|
||||
switch (ifan->ifan_what) {
|
||||
case IFAN_DEPARTURE:
|
||||
drv = bsd_get_drvindex(global, ifan->ifan_index);
|
||||
if (drv)
|
||||
drv->if_removed = 1;
|
||||
event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
|
||||
break;
|
||||
case IFAN_ARRIVAL:
|
||||
drv = bsd_get_drvname(global, ifan->ifan_name);
|
||||
if (drv) {
|
||||
drv->ifindex = ifan->ifan_index;
|
||||
drv->if_removed = 0;
|
||||
}
|
||||
event.interface_status.ievent = EVENT_INTERFACE_ADDED;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: unknown action");
|
||||
return;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "RTM_IFANNOUNCE: Interface '%s' %s",
|
||||
event.interface_status.ifname,
|
||||
ifan->ifan_name,
|
||||
ifan->ifan_what == IFAN_DEPARTURE ?
|
||||
"removed" : "added");
|
||||
wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
|
||||
os_strlcpy(event.interface_status.ifname, ifan->ifan_name,
|
||||
sizeof(event.interface_status.ifname));
|
||||
if (drv) {
|
||||
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS,
|
||||
&event);
|
||||
/*
|
||||
* Set ifindex to zero after sending the event as the
|
||||
* event might query the driver to ensure a match.
|
||||
*/
|
||||
if (ifan->ifan_what == IFAN_DEPARTURE)
|
||||
drv->ifindex = 0;
|
||||
} else {
|
||||
wpa_supplicant_event_global(global->ctx,
|
||||
EVENT_INTERFACE_STATUS,
|
||||
&event);
|
||||
}
|
||||
break;
|
||||
case RTM_IEEE80211:
|
||||
ifan = (struct if_announcemsghdr *) rtm;
|
||||
if (ifan->ifan_index != drv->ifindex)
|
||||
break;
|
||||
drv = bsd_get_drvindex(global, ifan->ifan_index);
|
||||
if (drv == NULL)
|
||||
return;
|
||||
switch (ifan->ifan_what) {
|
||||
case RTM_IEEE80211_ASSOC:
|
||||
case RTM_IEEE80211_REASSOC:
|
||||
if (drv->is_ap)
|
||||
break;
|
||||
wpa_supplicant_event(ctx, EVENT_ASSOC, NULL);
|
||||
wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
|
||||
break;
|
||||
case RTM_IEEE80211_DISASSOC:
|
||||
if (drv->is_ap)
|
||||
break;
|
||||
wpa_supplicant_event(ctx, EVENT_DISASSOC, NULL);
|
||||
wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL);
|
||||
break;
|
||||
case RTM_IEEE80211_SCAN:
|
||||
if (drv->is_ap)
|
||||
break;
|
||||
wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL);
|
||||
wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS,
|
||||
NULL);
|
||||
break;
|
||||
case RTM_IEEE80211_LEAVE:
|
||||
leave = (struct ieee80211_leave_event *) &ifan[1];
|
||||
drv_event_disassoc(ctx, leave->iev_addr);
|
||||
drv_event_disassoc(drv->ctx, leave->iev_addr);
|
||||
break;
|
||||
case RTM_IEEE80211_JOIN:
|
||||
#ifdef RTM_IEEE80211_REJOIN
|
||||
case RTM_IEEE80211_REJOIN:
|
||||
#endif
|
||||
join = (struct ieee80211_join_event *) &ifan[1];
|
||||
bsd_new_sta(drv, ctx, join->iev_addr);
|
||||
bsd_new_sta(drv, drv->ctx, join->iev_addr);
|
||||
break;
|
||||
case RTM_IEEE80211_REPLAY:
|
||||
/* ignore */
|
||||
@ -1290,23 +1350,30 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
|
||||
os_memset(&event, 0, sizeof(event));
|
||||
event.michael_mic_failure.unicast =
|
||||
!IEEE80211_IS_MULTICAST(mic->iev_dst);
|
||||
wpa_supplicant_event(ctx, EVENT_MICHAEL_MIC_FAILURE,
|
||||
&event);
|
||||
wpa_supplicant_event(drv->ctx,
|
||||
EVENT_MICHAEL_MIC_FAILURE, &event);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case RTM_IFINFO:
|
||||
ifm = (struct if_msghdr *) rtm;
|
||||
if (ifm->ifm_index != drv->ifindex)
|
||||
break;
|
||||
if ((rtm->rtm_flags & RTF_UP) == 0) {
|
||||
os_strlcpy(event.interface_status.ifname, drv->ifname,
|
||||
sizeof(event.interface_status.ifname));
|
||||
event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
|
||||
drv = bsd_get_drvindex(global, ifm->ifm_index);
|
||||
if (drv == NULL)
|
||||
return;
|
||||
if ((ifm->ifm_flags & IFF_UP) == 0 &&
|
||||
(drv->flags & IFF_UP) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' DOWN",
|
||||
event.interface_status.ifname);
|
||||
wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
|
||||
drv->ifname);
|
||||
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED,
|
||||
NULL);
|
||||
} else if ((ifm->ifm_flags & IFF_UP) != 0 &&
|
||||
(drv->flags & IFF_UP) == 0) {
|
||||
wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' UP",
|
||||
drv->ifname);
|
||||
wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED,
|
||||
NULL);
|
||||
}
|
||||
drv->flags = ifm->ifm_flags;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1333,11 +1400,16 @@ wpa_driver_bsd_add_scan_entry(struct wpa_scan_results *res,
|
||||
result->caps = sr->isr_capinfo;
|
||||
result->qual = sr->isr_rssi;
|
||||
result->noise = sr->isr_noise;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
/*
|
||||
* the rssi value reported by the kernel is in 0.5dB steps relative to
|
||||
* the reported noise floor. see ieee80211_node.h for details.
|
||||
*/
|
||||
result->level = sr->isr_rssi / 2 + sr->isr_noise;
|
||||
#else
|
||||
result->level = sr->isr_rssi;
|
||||
#endif
|
||||
|
||||
pos = (u8 *)(result + 1);
|
||||
|
||||
@ -1504,7 +1576,7 @@ get80211opmode(struct bsd_driver_data *drv)
|
||||
(void) memset(&ifmr, 0, sizeof(ifmr));
|
||||
(void) os_strlcpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name));
|
||||
|
||||
if (ioctl(drv->sock, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) {
|
||||
if (ioctl(drv->global->sock, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) {
|
||||
if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) {
|
||||
if (ifmr.ifm_current & IFM_FLAG0)
|
||||
return IEEE80211_M_AHDEMO;
|
||||
@ -1526,7 +1598,7 @@ get80211opmode(struct bsd_driver_data *drv)
|
||||
}
|
||||
|
||||
static void *
|
||||
wpa_driver_bsd_init(void *ctx, const char *ifname)
|
||||
wpa_driver_bsd_init(void *ctx, const char *ifname, void *priv)
|
||||
{
|
||||
#define GETPARAM(drv, param, v) \
|
||||
(((v) = get80211param(drv, param)) != -1)
|
||||
@ -1536,14 +1608,6 @@ wpa_driver_bsd_init(void *ctx, const char *ifname)
|
||||
if (drv == NULL)
|
||||
return NULL;
|
||||
|
||||
drv->event_buf_len = rtbuf_len();
|
||||
|
||||
drv->event_buf = os_malloc(drv->event_buf_len);
|
||||
if (drv->event_buf == NULL) {
|
||||
wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__);
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
/*
|
||||
* NB: We require the interface name be mappable to an index.
|
||||
* This implies we do not support having wpa_supplicant
|
||||
@ -1554,24 +1618,12 @@ wpa_driver_bsd_init(void *ctx, const char *ifname)
|
||||
if (drv->ifindex == 0) {
|
||||
wpa_printf(MSG_DEBUG, "%s: interface %s does not exist",
|
||||
__func__, ifname);
|
||||
goto fail1;
|
||||
goto fail;
|
||||
}
|
||||
drv->sock = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (drv->sock < 0)
|
||||
goto fail1;
|
||||
|
||||
os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
|
||||
/* Down interface during setup. */
|
||||
if (bsd_ctrl_iface(drv, 0) < 0)
|
||||
goto fail;
|
||||
|
||||
drv->route = socket(PF_ROUTE, SOCK_RAW, 0);
|
||||
if (drv->route < 0)
|
||||
goto fail;
|
||||
eloop_register_read_sock(drv->route,
|
||||
wpa_driver_bsd_event_receive, ctx, drv);
|
||||
|
||||
drv->ctx = ctx;
|
||||
drv->global = priv;
|
||||
os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
|
||||
|
||||
if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) {
|
||||
wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s",
|
||||
@ -1592,13 +1644,15 @@ wpa_driver_bsd_init(void *ctx, const char *ifname)
|
||||
if (wpa_driver_bsd_capa(drv))
|
||||
goto fail;
|
||||
|
||||
/* Down interface during setup. */
|
||||
if (bsd_ctrl_iface(drv, 0) < 0)
|
||||
goto fail;
|
||||
|
||||
drv->opmode = get80211opmode(drv);
|
||||
dl_list_add(&drv->global->ifaces, &drv->list);
|
||||
|
||||
return drv;
|
||||
fail:
|
||||
close(drv->sock);
|
||||
fail1:
|
||||
os_free(drv->event_buf);
|
||||
os_free(drv);
|
||||
return NULL;
|
||||
#undef GETPARAM
|
||||
@ -1609,22 +1663,25 @@ wpa_driver_bsd_deinit(void *priv)
|
||||
{
|
||||
struct bsd_driver_data *drv = priv;
|
||||
|
||||
wpa_driver_bsd_set_wpa(drv, 0);
|
||||
eloop_unregister_read_sock(drv->route);
|
||||
if (drv->ifindex != 0 && !drv->if_removed) {
|
||||
wpa_driver_bsd_set_wpa(drv, 0);
|
||||
|
||||
/* NB: mark interface down */
|
||||
bsd_ctrl_iface(drv, 0);
|
||||
/* NB: mark interface down */
|
||||
bsd_ctrl_iface(drv, 0);
|
||||
|
||||
wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa, drv->prev_privacy);
|
||||
if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming) < 0)
|
||||
wpa_printf(MSG_DEBUG, "%s: failed to restore roaming state",
|
||||
__func__);
|
||||
wpa_driver_bsd_set_wpa_internal(drv, drv->prev_wpa,
|
||||
drv->prev_privacy);
|
||||
|
||||
if (set80211param(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)
|
||||
< 0)
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"%s: failed to restore roaming state",
|
||||
__func__);
|
||||
}
|
||||
|
||||
if (drv->sock_xmit != NULL)
|
||||
l2_packet_deinit(drv->sock_xmit);
|
||||
(void) close(drv->route); /* ioctl socket */
|
||||
(void) close(drv->sock); /* event socket */
|
||||
os_free(drv->event_buf);
|
||||
dl_list_del(&drv->list);
|
||||
os_free(drv);
|
||||
}
|
||||
|
||||
@ -1638,10 +1695,74 @@ wpa_driver_bsd_get_capa(void *priv, struct wpa_driver_capa *capa)
|
||||
}
|
||||
#endif /* HOSTAPD */
|
||||
|
||||
static void *
|
||||
bsd_global_init(void *ctx)
|
||||
{
|
||||
struct bsd_driver_global *global;
|
||||
|
||||
global = os_zalloc(sizeof(*global));
|
||||
if (global == NULL)
|
||||
return NULL;
|
||||
|
||||
global->ctx = ctx;
|
||||
dl_list_init(&global->ifaces);
|
||||
|
||||
global->sock = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (global->sock < 0) {
|
||||
wpa_printf(MSG_ERROR, "socket[PF_INET,SOCK_DGRAM]: %s",
|
||||
strerror(errno));
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
global->route = socket(PF_ROUTE, SOCK_RAW, 0);
|
||||
if (global->route < 0) {
|
||||
wpa_printf(MSG_ERROR, "socket[PF_ROUTE,SOCK_RAW]: %s",
|
||||
strerror(errno));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
global->event_buf_len = rtbuf_len();
|
||||
global->event_buf = os_malloc(global->event_buf_len);
|
||||
if (global->event_buf == NULL) {
|
||||
wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef HOSTAPD
|
||||
eloop_register_read_sock(global->route, bsd_wireless_event_receive,
|
||||
NULL, global);
|
||||
|
||||
#else /* HOSTAPD */
|
||||
eloop_register_read_sock(global->route, wpa_driver_bsd_event_receive,
|
||||
NULL, global);
|
||||
#endif /* HOSTAPD */
|
||||
|
||||
return global;
|
||||
|
||||
fail:
|
||||
close(global->sock);
|
||||
fail1:
|
||||
os_free(global);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
bsd_global_deinit(void *priv)
|
||||
{
|
||||
struct bsd_driver_global *global = priv;
|
||||
|
||||
eloop_unregister_read_sock(global->route);
|
||||
(void) close(global->route);
|
||||
(void) close(global->sock);
|
||||
os_free(global);
|
||||
}
|
||||
|
||||
|
||||
const struct wpa_driver_ops wpa_driver_bsd_ops = {
|
||||
.name = "bsd",
|
||||
.desc = "BSD 802.11 support",
|
||||
.global_init = bsd_global_init,
|
||||
.global_deinit = bsd_global_deinit,
|
||||
#ifdef HOSTAPD
|
||||
.hapd_init = bsd_init,
|
||||
.hapd_deinit = bsd_deinit,
|
||||
@ -1654,7 +1775,7 @@ const struct wpa_driver_ops wpa_driver_bsd_ops = {
|
||||
.sta_set_flags = bsd_set_sta_authorized,
|
||||
.commit = bsd_commit,
|
||||
#else /* HOSTAPD */
|
||||
.init = wpa_driver_bsd_init,
|
||||
.init2 = wpa_driver_bsd_init,
|
||||
.deinit = wpa_driver_bsd_deinit,
|
||||
.get_bssid = wpa_driver_bsd_get_bssid,
|
||||
.get_ssid = wpa_driver_bsd_get_ssid,
|
||||
|
@ -82,6 +82,7 @@ const char * event_to_string(enum wpa_event_type event)
|
||||
E2S(NEW_PEER_CANDIDATE);
|
||||
E2S(ACS_CHANNEL_SELECTED);
|
||||
E2S(DFS_CAC_STARTED);
|
||||
E2S(P2P_LO_STOP);
|
||||
}
|
||||
|
||||
return "UNKNOWN";
|
||||
@ -185,12 +186,12 @@ wpa_get_wowlan_triggers(const char *wowlan_triggers,
|
||||
|
||||
start = buf;
|
||||
while (*start != '\0') {
|
||||
while (isblank(*start))
|
||||
while (isblank((unsigned char) *start))
|
||||
start++;
|
||||
if (*start == '\0')
|
||||
break;
|
||||
end = start;
|
||||
while (!isblank(*end) && *end != '\0')
|
||||
while (!isblank((unsigned char) *end) && *end != '\0')
|
||||
end++;
|
||||
last = *end == '\0';
|
||||
*end = '\0';
|
||||
@ -220,3 +221,55 @@ out:
|
||||
os_free(buf);
|
||||
return triggers;
|
||||
}
|
||||
|
||||
|
||||
const char * driver_flag_to_string(u64 flag)
|
||||
{
|
||||
#define DF2S(x) case WPA_DRIVER_FLAGS_ ## x: return #x
|
||||
switch (flag) {
|
||||
DF2S(DRIVER_IE);
|
||||
DF2S(SET_KEYS_AFTER_ASSOC);
|
||||
DF2S(DFS_OFFLOAD);
|
||||
DF2S(4WAY_HANDSHAKE);
|
||||
DF2S(WIRED);
|
||||
DF2S(SME);
|
||||
DF2S(AP);
|
||||
DF2S(SET_KEYS_AFTER_ASSOC_DONE);
|
||||
DF2S(HT_2040_COEX);
|
||||
DF2S(P2P_CONCURRENT);
|
||||
DF2S(P2P_DEDICATED_INTERFACE);
|
||||
DF2S(P2P_CAPABLE);
|
||||
DF2S(AP_TEARDOWN_SUPPORT);
|
||||
DF2S(P2P_MGMT_AND_NON_P2P);
|
||||
DF2S(SANE_ERROR_CODES);
|
||||
DF2S(OFFCHANNEL_TX);
|
||||
DF2S(EAPOL_TX_STATUS);
|
||||
DF2S(DEAUTH_TX_STATUS);
|
||||
DF2S(BSS_SELECTION);
|
||||
DF2S(TDLS_SUPPORT);
|
||||
DF2S(TDLS_EXTERNAL_SETUP);
|
||||
DF2S(PROBE_RESP_OFFLOAD);
|
||||
DF2S(AP_UAPSD);
|
||||
DF2S(INACTIVITY_TIMER);
|
||||
DF2S(AP_MLME);
|
||||
DF2S(SAE);
|
||||
DF2S(OBSS_SCAN);
|
||||
DF2S(IBSS);
|
||||
DF2S(RADAR);
|
||||
DF2S(DEDICATED_P2P_DEVICE);
|
||||
DF2S(QOS_MAPPING);
|
||||
DF2S(AP_CSA);
|
||||
DF2S(MESH);
|
||||
DF2S(ACS_OFFLOAD);
|
||||
DF2S(KEY_MGMT_OFFLOAD);
|
||||
DF2S(TDLS_CHANNEL_SWITCH);
|
||||
DF2S(HT_IBSS);
|
||||
DF2S(VHT_IBSS);
|
||||
DF2S(SUPPORT_HW_MODE_ANY);
|
||||
DF2S(OFFCHANNEL_SIMULTANEOUS);
|
||||
DF2S(FULL_AP_CLIENT_STATE);
|
||||
DF2S(P2P_LISTEN_OFFLOAD);
|
||||
}
|
||||
return "UNKNOWN";
|
||||
#undef DF2S
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ int close(int fd);
|
||||
#include "driver.h"
|
||||
#include "eloop.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/ieee802_11_common.h"
|
||||
#include "driver_ndis.h"
|
||||
|
||||
int wpa_driver_register_event_cb(struct wpa_driver_ndis_data *drv);
|
||||
@ -783,20 +784,7 @@ static int wpa_driver_ndis_scan(void *priv,
|
||||
|
||||
static const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie)
|
||||
{
|
||||
const u8 *end, *pos;
|
||||
|
||||
pos = (const u8 *) (res + 1);
|
||||
end = pos + res->ie_len;
|
||||
|
||||
while (pos + 1 < end) {
|
||||
if (pos + 2 + pos[1] > end)
|
||||
break;
|
||||
if (pos[0] == ie)
|
||||
return pos;
|
||||
pos += 2 + pos[1];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return get_ie((const u8 *) (res + 1), res->ie_len, ie);
|
||||
}
|
||||
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#endif /* CONFIG_LIBNL20 */
|
||||
|
||||
struct nl80211_global {
|
||||
void *ctx;
|
||||
struct dl_list interfaces;
|
||||
int if_add_ifindex;
|
||||
u64 if_add_wdevid;
|
||||
@ -84,6 +85,7 @@ struct wpa_driver_nl80211_data {
|
||||
struct dl_list list;
|
||||
struct dl_list wiphy_list;
|
||||
char phyname[32];
|
||||
unsigned int wiphy_idx;
|
||||
u8 perm_addr[ETH_ALEN];
|
||||
void *ctx;
|
||||
int ifindex;
|
||||
@ -94,6 +96,13 @@ struct wpa_driver_nl80211_data {
|
||||
struct wpa_driver_capa capa;
|
||||
u8 *extended_capa, *extended_capa_mask;
|
||||
unsigned int extended_capa_len;
|
||||
struct drv_nl80211_ext_capa {
|
||||
enum nl80211_iftype iftype;
|
||||
u8 *ext_capa, *ext_capa_mask;
|
||||
unsigned int ext_capa_len;
|
||||
} iface_ext_capa[NL80211_IFTYPE_MAX];
|
||||
unsigned int num_iface_ext_capa;
|
||||
|
||||
int has_capability;
|
||||
|
||||
int operstate;
|
||||
@ -148,9 +157,16 @@ struct wpa_driver_nl80211_data {
|
||||
unsigned int setband_vendor_cmd_avail:1;
|
||||
unsigned int get_pref_freq_list:1;
|
||||
unsigned int set_prob_oper_freq:1;
|
||||
unsigned int scan_vendor_cmd_avail:1;
|
||||
unsigned int connect_reassoc:1;
|
||||
unsigned int set_wifi_conf_vendor_cmd_avail:1;
|
||||
|
||||
u64 vendor_scan_cookie;
|
||||
u64 remain_on_chan_cookie;
|
||||
u64 send_action_cookie;
|
||||
#define MAX_SEND_ACTION_COOKIES 20
|
||||
u64 send_action_cookies[MAX_SEND_ACTION_COOKIES];
|
||||
unsigned int num_send_action_cookies;
|
||||
|
||||
unsigned int last_mgmt_freq;
|
||||
|
||||
@ -166,7 +182,10 @@ struct wpa_driver_nl80211_data {
|
||||
struct nl_handle *rtnl_sk; /* nl_sock for NETLINK_ROUTE */
|
||||
|
||||
int default_if_indices[16];
|
||||
/* the AP/AP_VLAN iface that is in this bridge */
|
||||
int default_if_indices_reason[16];
|
||||
int *if_indices;
|
||||
int *if_indices_reason;
|
||||
int num_if_indices;
|
||||
|
||||
/* From failed authentication command */
|
||||
@ -182,6 +201,13 @@ struct wpa_driver_nl80211_data {
|
||||
int auth_wep_tx_keyidx;
|
||||
int auth_local_state_change;
|
||||
int auth_p2p;
|
||||
|
||||
/*
|
||||
* Tells whether the last scan issued from wpa_supplicant was a normal
|
||||
* scan (NL80211_CMD_TRIGGER_SCAN) or a vendor scan
|
||||
* (NL80211_CMD_VENDOR). 0 if no pending scan request.
|
||||
*/
|
||||
int last_scan_cmd;
|
||||
};
|
||||
|
||||
struct nl_msg;
|
||||
@ -233,6 +259,8 @@ nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags);
|
||||
int process_global_event(struct nl_msg *msg, void *arg);
|
||||
int process_bss_event(struct nl_msg *msg, void *arg);
|
||||
|
||||
const char * nl80211_iftype_str(enum nl80211_iftype mode);
|
||||
|
||||
#ifdef ANDROID
|
||||
int android_nl_socket_set_nonblocking(struct nl_handle *handle);
|
||||
int android_pno_start(struct i802_bss *bss,
|
||||
@ -267,11 +295,13 @@ void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx);
|
||||
int wpa_driver_nl80211_scan(struct i802_bss *bss,
|
||||
struct wpa_driver_scan_params *params);
|
||||
int wpa_driver_nl80211_sched_scan(void *priv,
|
||||
struct wpa_driver_scan_params *params,
|
||||
u32 interval);
|
||||
struct wpa_driver_scan_params *params);
|
||||
int wpa_driver_nl80211_stop_sched_scan(void *priv);
|
||||
struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv);
|
||||
void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv);
|
||||
const u8 * nl80211_get_ie(const u8 *ies, size_t ies_len, u8 ie);
|
||||
int wpa_driver_nl80211_abort_scan(void *priv);
|
||||
int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
|
||||
struct wpa_driver_scan_params *params);
|
||||
int nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len);
|
||||
|
||||
#endif /* DRIVER_NL80211_H */
|
||||
|
@ -10,12 +10,17 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "eloop.h"
|
||||
#include "driver.h"
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#undef IFNAMSIZ
|
||||
#include <net/if.h>
|
||||
#ifdef __linux__
|
||||
#include <netpacket/packet.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <net/if.h>
|
||||
#endif /* __linux__ */
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
|
||||
#include <net/if_dl.h>
|
||||
@ -25,10 +30,6 @@
|
||||
#include <sys/sockio.h>
|
||||
#endif /* __sun__ */
|
||||
|
||||
#include "common.h"
|
||||
#include "eloop.h"
|
||||
#include "driver.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 1)
|
||||
#endif /* _MSC_VER */
|
||||
@ -472,6 +473,7 @@ static int wpa_driver_wired_set_ifflags(const char *ifname, int flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
|
||||
static int wpa_driver_wired_get_ifstatus(const char *ifname, int *status)
|
||||
{
|
||||
@ -559,7 +561,7 @@ static int wpa_driver_wired_multi(const char *ifname, const u8 *addr, int add)
|
||||
static void * wpa_driver_wired_init(void *ctx, const char *ifname)
|
||||
{
|
||||
struct wpa_driver_wired_data *drv;
|
||||
int flags, status;
|
||||
int flags;
|
||||
|
||||
drv = os_zalloc(sizeof(*drv));
|
||||
if (drv == NULL)
|
||||
|
@ -12,42 +12,6 @@
|
||||
#include "utils/common.h"
|
||||
#include "driver.h"
|
||||
|
||||
#ifdef CONFIG_DRIVER_WEXT
|
||||
extern struct wpa_driver_ops wpa_driver_wext_ops; /* driver_wext.c */
|
||||
#endif /* CONFIG_DRIVER_WEXT */
|
||||
#ifdef CONFIG_DRIVER_NL80211
|
||||
extern struct wpa_driver_ops wpa_driver_nl80211_ops; /* driver_nl80211.c */
|
||||
#endif /* CONFIG_DRIVER_NL80211 */
|
||||
#ifdef CONFIG_DRIVER_HOSTAP
|
||||
extern struct wpa_driver_ops wpa_driver_hostap_ops; /* driver_hostap.c */
|
||||
#endif /* CONFIG_DRIVER_HOSTAP */
|
||||
#ifdef CONFIG_DRIVER_BSD
|
||||
extern struct wpa_driver_ops wpa_driver_bsd_ops; /* driver_bsd.c */
|
||||
#endif /* CONFIG_DRIVER_BSD */
|
||||
#ifdef CONFIG_DRIVER_OPENBSD
|
||||
extern struct wpa_driver_ops wpa_driver_openbsd_ops; /* driver_openbsd.c */
|
||||
#endif /* CONFIG_DRIVER_OPENBSD */
|
||||
#ifdef CONFIG_DRIVER_NDIS
|
||||
extern struct wpa_driver_ops wpa_driver_ndis_ops; /* driver_ndis.c */
|
||||
#endif /* CONFIG_DRIVER_NDIS */
|
||||
#ifdef CONFIG_DRIVER_WIRED
|
||||
extern struct wpa_driver_ops wpa_driver_wired_ops; /* driver_wired.c */
|
||||
#endif /* CONFIG_DRIVER_WIRED */
|
||||
#ifdef CONFIG_DRIVER_MACSEC_QCA
|
||||
/* driver_macsec_qca.c */
|
||||
extern struct wpa_driver_ops wpa_driver_macsec_qca_ops;
|
||||
#endif /* CONFIG_DRIVER_MACSEC_QCA */
|
||||
#ifdef CONFIG_DRIVER_ROBOSWITCH
|
||||
/* driver_roboswitch.c */
|
||||
extern struct wpa_driver_ops wpa_driver_roboswitch_ops;
|
||||
#endif /* CONFIG_DRIVER_ROBOSWITCH */
|
||||
#ifdef CONFIG_DRIVER_ATHEROS
|
||||
extern struct wpa_driver_ops wpa_driver_atheros_ops; /* driver_atheros.c */
|
||||
#endif /* CONFIG_DRIVER_ATHEROS */
|
||||
#ifdef CONFIG_DRIVER_NONE
|
||||
extern struct wpa_driver_ops wpa_driver_none_ops; /* driver_none.c */
|
||||
#endif /* CONFIG_DRIVER_NONE */
|
||||
|
||||
|
||||
const struct wpa_driver_ops *const wpa_drivers[] =
|
||||
{
|
||||
|
@ -50,6 +50,8 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req);
|
||||
static const char * eap_sm_method_state_txt(EapMethodState state);
|
||||
static const char * eap_sm_decision_txt(EapDecision decision);
|
||||
#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
|
||||
static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
|
||||
const char *msg, size_t msglen);
|
||||
|
||||
|
||||
|
||||
@ -190,6 +192,14 @@ SM_STATE(EAP, INITIALIZE)
|
||||
*/
|
||||
eapol_set_bool(sm, EAPOL_eapResp, FALSE);
|
||||
eapol_set_bool(sm, EAPOL_eapNoResp, FALSE);
|
||||
/*
|
||||
* RFC 4137 does not reset ignore here, but since it is possible for
|
||||
* some method code paths to end up not setting ignore=FALSE, clear the
|
||||
* value here to avoid issues if a previous authentication attempt
|
||||
* failed with ignore=TRUE being left behind in the last
|
||||
* m.check(eapReqData) operation.
|
||||
*/
|
||||
sm->ignore = 0;
|
||||
sm->num_rounds = 0;
|
||||
sm->prev_failure = 0;
|
||||
sm->expected_failure = 0;
|
||||
@ -314,11 +324,14 @@ SM_STATE(EAP, GET_METHOD)
|
||||
wpa_printf(MSG_DEBUG, "EAP: Initialize selected EAP method: "
|
||||
"vendor %u method %u (%s)",
|
||||
sm->reqVendor, method, sm->m->name);
|
||||
if (reinit)
|
||||
if (reinit) {
|
||||
sm->eap_method_priv = sm->m->init_for_reauth(
|
||||
sm, sm->eap_method_priv);
|
||||
else
|
||||
} else {
|
||||
sm->waiting_ext_cert_check = 0;
|
||||
sm->ext_cert_check = 0;
|
||||
sm->eap_method_priv = sm->m->init(sm);
|
||||
}
|
||||
|
||||
if (sm->eap_method_priv == NULL) {
|
||||
struct eap_peer_config *config = eap_get_config(sm);
|
||||
@ -1375,13 +1388,10 @@ static int eap_sm_imsi_identity(struct eap_sm *sm,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* PCSC_FUNCS */
|
||||
|
||||
|
||||
static int eap_sm_set_scard_pin(struct eap_sm *sm,
|
||||
struct eap_peer_config *conf)
|
||||
{
|
||||
#ifdef PCSC_FUNCS
|
||||
if (scard_set_pin(sm->scard_ctx, conf->pin)) {
|
||||
/*
|
||||
* Make sure the same PIN is not tried again in order to avoid
|
||||
@ -1395,24 +1405,20 @@ static int eap_sm_set_scard_pin(struct eap_sm *sm,
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#else /* PCSC_FUNCS */
|
||||
return -1;
|
||||
#endif /* PCSC_FUNCS */
|
||||
}
|
||||
|
||||
|
||||
static int eap_sm_get_scard_identity(struct eap_sm *sm,
|
||||
struct eap_peer_config *conf)
|
||||
{
|
||||
#ifdef PCSC_FUNCS
|
||||
if (eap_sm_set_scard_pin(sm, conf))
|
||||
return -1;
|
||||
|
||||
return eap_sm_imsi_identity(sm, conf);
|
||||
#else /* PCSC_FUNCS */
|
||||
return -1;
|
||||
#endif /* PCSC_FUNCS */
|
||||
}
|
||||
|
||||
#endif /* PCSC_FUNCS */
|
||||
|
||||
|
||||
/**
|
||||
* eap_sm_buildIdentity - Build EAP-Identity/Response for the current network
|
||||
@ -1455,23 +1461,27 @@ struct wpabuf * eap_sm_buildIdentity(struct eap_sm *sm, int id, int encrypted)
|
||||
identity, identity_len);
|
||||
}
|
||||
|
||||
if (identity == NULL) {
|
||||
wpa_printf(MSG_WARNING, "EAP: buildIdentity: identity "
|
||||
"configuration was not available");
|
||||
if (config->pcsc) {
|
||||
if (config->pcsc) {
|
||||
#ifdef PCSC_FUNCS
|
||||
if (!identity) {
|
||||
if (eap_sm_get_scard_identity(sm, config) < 0)
|
||||
return NULL;
|
||||
identity = config->identity;
|
||||
identity_len = config->identity_len;
|
||||
wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from "
|
||||
"IMSI", identity, identity_len);
|
||||
} else {
|
||||
eap_sm_request_identity(sm);
|
||||
wpa_hexdump_ascii(MSG_DEBUG,
|
||||
"permanent identity from IMSI",
|
||||
identity, identity_len);
|
||||
} else if (eap_sm_set_scard_pin(sm, config) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
} else if (config->pcsc) {
|
||||
if (eap_sm_set_scard_pin(sm, config) < 0)
|
||||
return NULL;
|
||||
#else /* PCSC_FUNCS */
|
||||
return NULL;
|
||||
#endif /* PCSC_FUNCS */
|
||||
} else if (!identity) {
|
||||
wpa_printf(MSG_WARNING,
|
||||
"EAP: buildIdentity: identity configuration was not available");
|
||||
eap_sm_request_identity(sm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, identity_len,
|
||||
@ -1512,15 +1522,9 @@ static void eap_sm_processNotify(struct eap_sm *sm, const struct wpabuf *req)
|
||||
|
||||
static struct wpabuf * eap_sm_buildNotify(int id)
|
||||
{
|
||||
struct wpabuf *resp;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "EAP: Generating EAP-Response Notification");
|
||||
resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NOTIFICATION, 0,
|
||||
EAP_CODE_RESPONSE, id);
|
||||
if (resp == NULL)
|
||||
return NULL;
|
||||
|
||||
return resp;
|
||||
return eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NOTIFICATION, 0,
|
||||
EAP_CODE_RESPONSE, id);
|
||||
}
|
||||
|
||||
|
||||
@ -1852,6 +1856,11 @@ static void eap_peer_sm_tls_event(void *ctx, enum tls_event ev,
|
||||
case TLS_CERT_CHAIN_SUCCESS:
|
||||
eap_notify_status(sm, "remote certificate verification",
|
||||
"success");
|
||||
if (sm->ext_cert_check) {
|
||||
sm->waiting_ext_cert_check = 1;
|
||||
eap_sm_request(sm, WPA_CTRL_REQ_EXT_CERT_CHECK,
|
||||
NULL, 0);
|
||||
}
|
||||
break;
|
||||
case TLS_CERT_CHAIN_FAILURE:
|
||||
wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_TLS_CERT_ERROR
|
||||
@ -2174,10 +2183,10 @@ int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, int verbose)
|
||||
#endif /* CONFIG_CTRL_IFACE */
|
||||
|
||||
|
||||
#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
|
||||
static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
|
||||
const char *msg, size_t msglen)
|
||||
{
|
||||
#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
|
||||
struct eap_peer_config *config;
|
||||
const char *txt = NULL;
|
||||
char *tmp;
|
||||
@ -2226,16 +2235,17 @@ static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
|
||||
case WPA_CTRL_REQ_SIM:
|
||||
txt = msg;
|
||||
break;
|
||||
case WPA_CTRL_REQ_EXT_CERT_CHECK:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (sm->eapol_cb->eap_param_needed)
|
||||
sm->eapol_cb->eap_param_needed(sm->eapol_ctx, field, txt);
|
||||
}
|
||||
#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
|
||||
#define eap_sm_request(sm, type, msg, msglen) do { } while (0)
|
||||
#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
|
||||
}
|
||||
|
||||
|
||||
const char * eap_sm_get_method_name(struct eap_sm *sm)
|
||||
{
|
||||
|
@ -181,13 +181,13 @@ struct eap_peer_config {
|
||||
* subject_match - Constraint for server certificate subject
|
||||
*
|
||||
* This substring is matched against the subject of the authentication
|
||||
* server certificate. If this string is set, the server sertificate is
|
||||
* server certificate. If this string is set, the server certificate is
|
||||
* only accepted if it contains this string in the subject. The subject
|
||||
* string is in following format:
|
||||
*
|
||||
* /C=US/ST=CA/L=San Francisco/CN=Test AS/emailAddress=as@n.example.com
|
||||
*
|
||||
* Note: Since this is a substring match, this cannot be used securily
|
||||
* Note: Since this is a substring match, this cannot be used securely
|
||||
* to do a suffix match against a possible domain name in the CN entry.
|
||||
* For such a use case, domain_suffix_match should be used instead.
|
||||
*/
|
||||
@ -198,7 +198,7 @@ struct eap_peer_config {
|
||||
*
|
||||
* Semicolon separated string of entries to be matched against the
|
||||
* alternative subject name of the authentication server certificate.
|
||||
* If this string is set, the server sertificate is only accepted if it
|
||||
* If this string is set, the server certificate is only accepted if it
|
||||
* contains one of the entries in an alternative subject name
|
||||
* extension.
|
||||
*
|
||||
@ -739,6 +739,20 @@ struct eap_peer_config {
|
||||
* erp - Whether EAP Re-authentication Protocol (ERP) is enabled
|
||||
*/
|
||||
int erp;
|
||||
|
||||
/**
|
||||
* pending_ext_cert_check - External server certificate check status
|
||||
*
|
||||
* This field should not be set in configuration step. It is only used
|
||||
* internally when control interface is used to request external
|
||||
* validation of server certificate chain.
|
||||
*/
|
||||
enum {
|
||||
NO_CHECK = 0,
|
||||
PENDING_CHECK,
|
||||
EXT_CERT_CHECK_GOOD,
|
||||
EXT_CERT_CHECK_BAD,
|
||||
} pending_ext_cert_check;
|
||||
};
|
||||
|
||||
|
||||
|
@ -129,7 +129,6 @@ static struct wpabuf * eap_gtc_process(struct eap_sm *sm, void *priv,
|
||||
int eap_peer_gtc_register(void)
|
||||
{
|
||||
struct eap_method *eap;
|
||||
int ret;
|
||||
|
||||
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
|
||||
EAP_VENDOR_IETF, EAP_TYPE_GTC, "GTC");
|
||||
@ -140,8 +139,5 @@ int eap_peer_gtc_register(void)
|
||||
eap->deinit = eap_gtc_deinit;
|
||||
eap->process = eap_gtc_process;
|
||||
|
||||
ret = eap_peer_method_register(eap);
|
||||
if (ret)
|
||||
eap_peer_method_free(eap);
|
||||
return ret;
|
||||
return eap_peer_method_register(eap);
|
||||
}
|
||||
|
@ -366,6 +366,8 @@ struct eap_sm {
|
||||
int external_sim;
|
||||
|
||||
unsigned int expected_failure:1;
|
||||
unsigned int ext_cert_check:1;
|
||||
unsigned int waiting_ext_cert_check:1;
|
||||
|
||||
struct dl_list erp_keys; /* struct eap_erp_key */
|
||||
};
|
||||
|
@ -395,7 +395,6 @@ static u8 * eap_leap_getKey(struct eap_sm *sm, void *priv, size_t *len)
|
||||
int eap_peer_leap_register(void)
|
||||
{
|
||||
struct eap_method *eap;
|
||||
int ret;
|
||||
|
||||
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
|
||||
EAP_VENDOR_IETF, EAP_TYPE_LEAP, "LEAP");
|
||||
@ -408,8 +407,5 @@ int eap_peer_leap_register(void)
|
||||
eap->isKeyAvailable = eap_leap_isKeyAvailable;
|
||||
eap->getKey = eap_leap_getKey;
|
||||
|
||||
ret = eap_peer_method_register(eap);
|
||||
if (ret)
|
||||
eap_peer_method_free(eap);
|
||||
return ret;
|
||||
return eap_peer_method_register(eap);
|
||||
}
|
||||
|
@ -104,7 +104,6 @@ static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv,
|
||||
int eap_peer_md5_register(void)
|
||||
{
|
||||
struct eap_method *eap;
|
||||
int ret;
|
||||
|
||||
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
|
||||
EAP_VENDOR_IETF, EAP_TYPE_MD5, "MD5");
|
||||
@ -115,8 +114,5 @@ int eap_peer_md5_register(void)
|
||||
eap->deinit = eap_md5_deinit;
|
||||
eap->process = eap_md5_process;
|
||||
|
||||
ret = eap_peer_method_register(eap);
|
||||
if (ret)
|
||||
eap_peer_method_free(eap);
|
||||
return ret;
|
||||
return eap_peer_method_register(eap);
|
||||
}
|
||||
|
@ -23,6 +23,8 @@
|
||||
|
||||
static struct eap_method *eap_methods = NULL;
|
||||
|
||||
static void eap_peer_method_free(struct eap_method *method);
|
||||
|
||||
|
||||
/**
|
||||
* eap_peer_get_eap_method - Get EAP method based on type number
|
||||
@ -300,7 +302,7 @@ struct eap_method * eap_peer_method_alloc(int version, int vendor,
|
||||
* eap_peer_method_free - Free EAP peer method structure
|
||||
* @method: Method structure allocated with eap_peer_method_alloc()
|
||||
*/
|
||||
void eap_peer_method_free(struct eap_method *method)
|
||||
static void eap_peer_method_free(struct eap_method *method)
|
||||
{
|
||||
os_free(method);
|
||||
}
|
||||
@ -308,26 +310,31 @@ void eap_peer_method_free(struct eap_method *method)
|
||||
|
||||
/**
|
||||
* eap_peer_method_register - Register an EAP peer method
|
||||
* @method: EAP method to register
|
||||
* @method: EAP method to register from eap_peer_method_alloc()
|
||||
* Returns: 0 on success, -1 on invalid method, or -2 if a matching EAP method
|
||||
* has already been registered
|
||||
*
|
||||
* Each EAP peer method needs to call this function to register itself as a
|
||||
* supported EAP method.
|
||||
* supported EAP method. The caller must not free the allocated method data
|
||||
* regardless of the return value.
|
||||
*/
|
||||
int eap_peer_method_register(struct eap_method *method)
|
||||
{
|
||||
struct eap_method *m, *last = NULL;
|
||||
|
||||
if (method == NULL || method->name == NULL ||
|
||||
method->version != EAP_PEER_METHOD_INTERFACE_VERSION)
|
||||
method->version != EAP_PEER_METHOD_INTERFACE_VERSION) {
|
||||
eap_peer_method_free(method);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (m = eap_methods; m; m = m->next) {
|
||||
if ((m->vendor == method->vendor &&
|
||||
m->method == method->method) ||
|
||||
os_strcmp(m->name, method->name) == 0)
|
||||
os_strcmp(m->name, method->name) == 0) {
|
||||
eap_peer_method_free(method);
|
||||
return -2;
|
||||
}
|
||||
last = m;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,6 @@ const struct eap_method * eap_peer_get_methods(size_t *count);
|
||||
|
||||
struct eap_method * eap_peer_method_alloc(int version, int vendor,
|
||||
EapType method, const char *name);
|
||||
void eap_peer_method_free(struct eap_method *method);
|
||||
int eap_peer_method_register(struct eap_method *method);
|
||||
|
||||
|
||||
|
@ -882,7 +882,6 @@ static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len)
|
||||
int eap_peer_mschapv2_register(void)
|
||||
{
|
||||
struct eap_method *eap;
|
||||
int ret;
|
||||
|
||||
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
|
||||
EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2,
|
||||
@ -896,8 +895,5 @@ int eap_peer_mschapv2_register(void)
|
||||
eap->isKeyAvailable = eap_mschapv2_isKeyAvailable;
|
||||
eap->getKey = eap_mschapv2_getKey;
|
||||
|
||||
ret = eap_peer_method_register(eap);
|
||||
if (ret)
|
||||
eap_peer_method_free(eap);
|
||||
return ret;
|
||||
return eap_peer_method_register(eap);
|
||||
}
|
||||
|
@ -85,7 +85,6 @@ static struct wpabuf * eap_otp_process(struct eap_sm *sm, void *priv,
|
||||
int eap_peer_otp_register(void)
|
||||
{
|
||||
struct eap_method *eap;
|
||||
int ret;
|
||||
|
||||
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
|
||||
EAP_VENDOR_IETF, EAP_TYPE_OTP, "OTP");
|
||||
@ -96,8 +95,5 @@ int eap_peer_otp_register(void)
|
||||
eap->deinit = eap_otp_deinit;
|
||||
eap->process = eap_otp_process;
|
||||
|
||||
ret = eap_peer_method_register(eap);
|
||||
if (ret)
|
||||
eap_peer_method_free(eap);
|
||||
return ret;
|
||||
return eap_peer_method_register(eap);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
/*
|
||||
* EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt)
|
||||
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
@ -61,6 +61,7 @@ struct eap_peap_data {
|
||||
size_t id_len;
|
||||
|
||||
struct wpabuf *pending_phase2_req;
|
||||
struct wpabuf *pending_resp;
|
||||
enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding;
|
||||
int crypto_binding_used;
|
||||
u8 binding_nonce[32];
|
||||
@ -71,8 +72,8 @@ struct eap_peap_data {
|
||||
};
|
||||
|
||||
|
||||
static int eap_peap_parse_phase1(struct eap_peap_data *data,
|
||||
const char *phase1)
|
||||
static void eap_peap_parse_phase1(struct eap_peap_data *data,
|
||||
const char *phase1)
|
||||
{
|
||||
const char *pos;
|
||||
|
||||
@ -127,8 +128,6 @@ static int eap_peap_parse_phase1(struct eap_peap_data *data,
|
||||
wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 2 enabled");
|
||||
}
|
||||
#endif /* EAP_TNC */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -146,11 +145,8 @@ static void * eap_peap_init(struct eap_sm *sm)
|
||||
data->peap_outer_success = 2;
|
||||
data->crypto_binding = OPTIONAL_BINDING;
|
||||
|
||||
if (config && config->phase1 &&
|
||||
eap_peap_parse_phase1(data, config->phase1) < 0) {
|
||||
eap_peap_deinit(sm, data);
|
||||
return NULL;
|
||||
}
|
||||
if (config && config->phase1)
|
||||
eap_peap_parse_phase1(data, config->phase1);
|
||||
|
||||
if (eap_peer_select_phase2_methods(config, "auth=",
|
||||
&data->phase2_types,
|
||||
@ -193,6 +189,7 @@ static void eap_peap_deinit(struct eap_sm *sm, void *priv)
|
||||
eap_peap_free_key(data);
|
||||
os_free(data->session_id);
|
||||
wpabuf_free(data->pending_phase2_req);
|
||||
wpabuf_free(data->pending_resp);
|
||||
os_free(data);
|
||||
}
|
||||
|
||||
@ -258,6 +255,7 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
|
||||
{
|
||||
u8 *tk;
|
||||
u8 isk[32], imck[60];
|
||||
int resumed;
|
||||
|
||||
/*
|
||||
* Tunnel key (TK) is the first 60 octets of the key generated by
|
||||
@ -268,8 +266,12 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
|
||||
return -1;
|
||||
wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60);
|
||||
|
||||
if (data->reauth &&
|
||||
tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) {
|
||||
resumed = tls_connection_resumed(sm->ssl_ctx, data->ssl.conn);
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-PEAP: CMK derivation - reauth=%d resumed=%d phase2_eap_started=%d phase2_success=%d",
|
||||
data->reauth, resumed, data->phase2_eap_started,
|
||||
data->phase2_success);
|
||||
if (data->reauth && !data->phase2_eap_started && resumed) {
|
||||
/* Fast-connect: IPMK|CMK = TK */
|
||||
os_memcpy(data->ipmk, tk, 40);
|
||||
wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK from TK",
|
||||
@ -339,7 +341,8 @@ static int eap_tlv_add_cryptobinding(struct eap_sm *sm,
|
||||
addr[0], len[0]);
|
||||
wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2",
|
||||
addr[1], len[1]);
|
||||
hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac);
|
||||
if (hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac) < 0)
|
||||
return -1;
|
||||
wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC", mac, SHA1_MAC_LEN);
|
||||
data->crypto_binding_used = 1;
|
||||
|
||||
@ -650,6 +653,7 @@ static int eap_peap_phase2_request(struct eap_sm *sm,
|
||||
if (*resp == NULL) {
|
||||
ret->methodState = METHOD_DONE;
|
||||
ret->decision = DECISION_FAIL;
|
||||
wpabuf_free(buf);
|
||||
return -1;
|
||||
}
|
||||
wpabuf_put_buf(*resp, buf);
|
||||
@ -1008,6 +1012,34 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
|
||||
!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,
|
||||
@ -1020,6 +1052,16 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
|
||||
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,
|
||||
@ -1125,6 +1167,8 @@ static void eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv)
|
||||
struct eap_peap_data *data = priv;
|
||||
wpabuf_free(data->pending_phase2_req);
|
||||
data->pending_phase2_req = NULL;
|
||||
wpabuf_free(data->pending_resp);
|
||||
data->pending_resp = NULL;
|
||||
data->crypto_binding_used = 0;
|
||||
}
|
||||
|
||||
@ -1239,7 +1283,6 @@ static u8 * eap_peap_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
|
||||
int eap_peer_peap_register(void)
|
||||
{
|
||||
struct eap_method *eap;
|
||||
int ret;
|
||||
|
||||
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
|
||||
EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP");
|
||||
@ -1257,8 +1300,5 @@ int eap_peer_peap_register(void)
|
||||
eap->init_for_reauth = eap_peap_init_for_reauth;
|
||||
eap->getSessionId = eap_peap_get_session_id;
|
||||
|
||||
ret = eap_peer_method_register(eap);
|
||||
if (ret)
|
||||
eap_peer_method_free(eap);
|
||||
return ret;
|
||||
return eap_peer_method_register(eap);
|
||||
}
|
||||
|
@ -482,7 +482,6 @@ static u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
|
||||
int eap_peer_psk_register(void)
|
||||
{
|
||||
struct eap_method *eap;
|
||||
int ret;
|
||||
|
||||
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
|
||||
EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK");
|
||||
@ -497,8 +496,5 @@ int eap_peer_psk_register(void)
|
||||
eap->getSessionId = eap_psk_get_session_id;
|
||||
eap->get_emsk = eap_psk_get_emsk;
|
||||
|
||||
ret = eap_peer_method_register(eap);
|
||||
if (ret)
|
||||
eap_peer_method_free(eap);
|
||||
return ret;
|
||||
return eap_peer_method_register(eap);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
/*
|
||||
* EAP peer method: EAP-TLS (RFC 2716)
|
||||
* Copyright (c) 2004-2008, 2012, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2008, 2012-2015, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
@ -27,6 +27,7 @@ struct eap_tls_data {
|
||||
size_t id_len;
|
||||
void *ssl_ctx;
|
||||
u8 eap_type;
|
||||
struct wpabuf *pending_resp;
|
||||
};
|
||||
|
||||
|
||||
@ -144,6 +145,7 @@ static void eap_tls_deinit(struct eap_sm *sm, void *priv)
|
||||
eap_peer_tls_ssl_deinit(sm, &data->ssl);
|
||||
eap_tls_free_key(data);
|
||||
os_free(data->session_id);
|
||||
wpabuf_free(data->pending_resp);
|
||||
os_free(data);
|
||||
}
|
||||
|
||||
@ -218,6 +220,32 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv,
|
||||
struct eap_tls_data *data = priv;
|
||||
struct wpabuf msg;
|
||||
|
||||
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-TLS: 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-TLS: 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-TLS: Continuing to wait external server certificate validation");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pos = eap_peer_tls_process_init(sm, &data->ssl, data->eap_type, ret,
|
||||
reqData, &left, &flags);
|
||||
if (pos == NULL)
|
||||
@ -239,6 +267,14 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv,
|
||||
return eap_tls_failure(sm, data, ret, res, resp, id);
|
||||
}
|
||||
|
||||
if (sm->waiting_ext_cert_check) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-TLS: Waiting external server certificate validation");
|
||||
wpabuf_free(data->pending_resp);
|
||||
data->pending_resp = resp;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (tls_connection_established(data->ssl_ctx, data->ssl.conn))
|
||||
eap_tls_success(sm, data, ret);
|
||||
|
||||
@ -260,6 +296,10 @@ static Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv)
|
||||
|
||||
static void eap_tls_deinit_for_reauth(struct eap_sm *sm, void *priv)
|
||||
{
|
||||
struct eap_tls_data *data = priv;
|
||||
|
||||
wpabuf_free(data->pending_resp);
|
||||
data->pending_resp = NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -352,7 +392,6 @@ static u8 * eap_tls_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
|
||||
int eap_peer_tls_register(void)
|
||||
{
|
||||
struct eap_method *eap;
|
||||
int ret;
|
||||
|
||||
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
|
||||
EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS");
|
||||
@ -371,10 +410,7 @@ int eap_peer_tls_register(void)
|
||||
eap->init_for_reauth = eap_tls_init_for_reauth;
|
||||
eap->get_emsk = eap_tls_get_emsk;
|
||||
|
||||
ret = eap_peer_method_register(eap);
|
||||
if (ret)
|
||||
eap_peer_method_free(eap);
|
||||
return ret;
|
||||
return eap_peer_method_register(eap);
|
||||
}
|
||||
|
||||
|
||||
@ -382,7 +418,6 @@ int eap_peer_tls_register(void)
|
||||
int eap_peer_unauth_tls_register(void)
|
||||
{
|
||||
struct eap_method *eap;
|
||||
int ret;
|
||||
|
||||
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
|
||||
EAP_VENDOR_UNAUTH_TLS,
|
||||
@ -401,10 +436,7 @@ int eap_peer_unauth_tls_register(void)
|
||||
eap->init_for_reauth = eap_tls_init_for_reauth;
|
||||
eap->get_emsk = eap_tls_get_emsk;
|
||||
|
||||
ret = eap_peer_method_register(eap);
|
||||
if (ret)
|
||||
eap_peer_method_free(eap);
|
||||
return ret;
|
||||
return eap_peer_method_register(eap);
|
||||
}
|
||||
#endif /* EAP_UNAUTH_TLS */
|
||||
|
||||
@ -413,7 +445,6 @@ int eap_peer_unauth_tls_register(void)
|
||||
int eap_peer_wfa_unauth_tls_register(void)
|
||||
{
|
||||
struct eap_method *eap;
|
||||
int ret;
|
||||
|
||||
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
|
||||
EAP_VENDOR_WFA_NEW,
|
||||
@ -433,9 +464,6 @@ int eap_peer_wfa_unauth_tls_register(void)
|
||||
eap->init_for_reauth = eap_tls_init_for_reauth;
|
||||
eap->get_emsk = eap_tls_get_emsk;
|
||||
|
||||
ret = eap_peer_method_register(eap);
|
||||
if (ret)
|
||||
eap_peer_method_free(eap);
|
||||
return ret;
|
||||
return eap_peer_method_register(eap);
|
||||
}
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
@ -82,6 +82,10 @@ static void eap_tls_params_flags(struct tls_connection_params *params,
|
||||
params->flags |= TLS_CONN_DISABLE_TLSv1_2;
|
||||
if (os_strstr(txt, "tls_disable_tlsv1_2=0"))
|
||||
params->flags &= ~TLS_CONN_DISABLE_TLSv1_2;
|
||||
if (os_strstr(txt, "tls_ext_cert_check=1"))
|
||||
params->flags |= TLS_CONN_EXT_CERT_CHECK;
|
||||
if (os_strstr(txt, "tls_ext_cert_check=0"))
|
||||
params->flags &= ~TLS_CONN_EXT_CERT_CHECK;
|
||||
}
|
||||
|
||||
|
||||
@ -179,6 +183,8 @@ static int eap_tls_params_from_conf(struct eap_sm *sm,
|
||||
|
||||
params->openssl_ciphers = config->openssl_ciphers;
|
||||
|
||||
sm->ext_cert_check = !!(params->flags & TLS_CONN_EXT_CERT_CHECK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -192,8 +198,10 @@ static int eap_tls_init_connection(struct eap_sm *sm,
|
||||
|
||||
if (config->ocsp)
|
||||
params->flags |= TLS_CONN_REQUEST_OCSP;
|
||||
if (config->ocsp == 2)
|
||||
if (config->ocsp >= 2)
|
||||
params->flags |= TLS_CONN_REQUIRE_OCSP;
|
||||
if (config->ocsp == 3)
|
||||
params->flags |= TLS_CONN_REQUIRE_OCSP_ALL;
|
||||
data->conn = tls_connection_init(data->ssl_ctx);
|
||||
if (data->conn == NULL) {
|
||||
wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS "
|
||||
@ -322,8 +330,8 @@ u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
|
||||
if (out == NULL)
|
||||
return NULL;
|
||||
|
||||
if (tls_connection_prf(data->ssl_ctx, data->conn, label, 0, 0,
|
||||
out, len)) {
|
||||
if (tls_connection_export_key(data->ssl_ctx, data->conn, label, out,
|
||||
len)) {
|
||||
os_free(out);
|
||||
return NULL;
|
||||
}
|
||||
@ -352,10 +360,8 @@ u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm,
|
||||
struct tls_random keys;
|
||||
u8 *out;
|
||||
|
||||
if (tls_connection_get_random(sm->ssl_ctx, data->conn, &keys))
|
||||
return NULL;
|
||||
|
||||
if (keys.client_random == NULL || keys.server_random == NULL)
|
||||
if (tls_connection_get_random(sm->ssl_ctx, data->conn, &keys) ||
|
||||
keys.client_random == NULL || keys.server_random == NULL)
|
||||
return NULL;
|
||||
|
||||
*len = 1 + keys.client_random_len + keys.server_random_len;
|
||||
@ -1037,6 +1043,9 @@ int eap_peer_select_phase2_methods(struct eap_peer_config *config,
|
||||
if (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_NONE) {
|
||||
wpa_printf(MSG_ERROR, "TLS: Unsupported Phase2 EAP "
|
||||
"method '%s'", start);
|
||||
os_free(methods);
|
||||
os_free(buf);
|
||||
return -1;
|
||||
} else {
|
||||
num_methods++;
|
||||
_methods = os_realloc_array(methods, num_methods,
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
/*
|
||||
* EAP peer method: EAP-TTLS (RFC 5281)
|
||||
* Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
@ -37,6 +37,7 @@ struct eap_ttls_data {
|
||||
void *phase2_priv;
|
||||
int phase2_success;
|
||||
int phase2_start;
|
||||
EapDecision decision_succ;
|
||||
|
||||
enum phase2_types {
|
||||
EAP_TTLS_PHASE2_EAP,
|
||||
@ -60,6 +61,7 @@ struct eap_ttls_data {
|
||||
size_t id_len;
|
||||
|
||||
struct wpabuf *pending_phase2_req;
|
||||
struct wpabuf *pending_resp;
|
||||
|
||||
#ifdef EAP_TNC
|
||||
int ready_for_tnc;
|
||||
@ -72,6 +74,7 @@ static void * eap_ttls_init(struct eap_sm *sm)
|
||||
{
|
||||
struct eap_ttls_data *data;
|
||||
struct eap_peer_config *config = eap_get_config(sm);
|
||||
int selected_non_eap;
|
||||
char *selected;
|
||||
|
||||
data = os_zalloc(sizeof(*data));
|
||||
@ -79,26 +82,67 @@ static void * eap_ttls_init(struct eap_sm *sm)
|
||||
return NULL;
|
||||
data->ttls_version = EAP_TTLS_VERSION;
|
||||
selected = "EAP";
|
||||
selected_non_eap = 0;
|
||||
data->phase2_type = EAP_TTLS_PHASE2_EAP;
|
||||
|
||||
/*
|
||||
* Either one auth= type or one or more autheap= methods can be
|
||||
* specified.
|
||||
*/
|
||||
if (config && config->phase2) {
|
||||
const char *token, *last = NULL;
|
||||
|
||||
while ((token = cstr_token(config->phase2, " \t", &last))) {
|
||||
if (os_strncmp(token, "auth=", 5) != 0)
|
||||
continue;
|
||||
token += 5;
|
||||
|
||||
if (last - token == 8 &&
|
||||
os_strncmp(token, "MSCHAPV2", 8) == 0) {
|
||||
selected = "MSCHAPV2";
|
||||
data->phase2_type = EAP_TTLS_PHASE2_MSCHAPV2;
|
||||
} else if (last - token == 6 &&
|
||||
os_strncmp(token, "MSCHAP", 6) == 0) {
|
||||
selected = "MSCHAP";
|
||||
data->phase2_type = EAP_TTLS_PHASE2_MSCHAP;
|
||||
} else if (last - token == 3 &&
|
||||
os_strncmp(token, "PAP", 3) == 0) {
|
||||
selected = "PAP";
|
||||
data->phase2_type = EAP_TTLS_PHASE2_PAP;
|
||||
} else if (last - token == 4 &&
|
||||
os_strncmp(token, "CHAP", 4) == 0) {
|
||||
selected = "CHAP";
|
||||
data->phase2_type = EAP_TTLS_PHASE2_CHAP;
|
||||
} else {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"EAP-TTLS: Unsupported Phase2 type '%s'",
|
||||
token);
|
||||
eap_ttls_deinit(sm, data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (selected_non_eap) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"EAP-TTLS: Only one Phase2 type can be specified");
|
||||
eap_ttls_deinit(sm, data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
selected_non_eap = 1;
|
||||
}
|
||||
|
||||
if (os_strstr(config->phase2, "autheap=")) {
|
||||
if (selected_non_eap) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"EAP-TTLS: Both auth= and autheap= params cannot be specified");
|
||||
eap_ttls_deinit(sm, data);
|
||||
return NULL;
|
||||
}
|
||||
selected = "EAP";
|
||||
data->phase2_type = EAP_TTLS_PHASE2_EAP;
|
||||
} else if (os_strstr(config->phase2, "auth=MSCHAPV2")) {
|
||||
selected = "MSCHAPV2";
|
||||
data->phase2_type = EAP_TTLS_PHASE2_MSCHAPV2;
|
||||
} else if (os_strstr(config->phase2, "auth=MSCHAP")) {
|
||||
selected = "MSCHAP";
|
||||
data->phase2_type = EAP_TTLS_PHASE2_MSCHAP;
|
||||
} else if (os_strstr(config->phase2, "auth=PAP")) {
|
||||
selected = "PAP";
|
||||
data->phase2_type = EAP_TTLS_PHASE2_PAP;
|
||||
} else if (os_strstr(config->phase2, "auth=CHAP")) {
|
||||
selected = "CHAP";
|
||||
data->phase2_type = EAP_TTLS_PHASE2_CHAP;
|
||||
}
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 type: %s", selected);
|
||||
|
||||
if (data->phase2_type == EAP_TTLS_PHASE2_EAP) {
|
||||
@ -155,6 +199,7 @@ static void eap_ttls_deinit(struct eap_sm *sm, void *priv)
|
||||
eap_ttls_free_key(data);
|
||||
os_free(data->session_id);
|
||||
wpabuf_free(data->pending_phase2_req);
|
||||
wpabuf_free(data->pending_resp);
|
||||
os_free(data);
|
||||
}
|
||||
|
||||
@ -1410,6 +1455,32 @@ static int eap_ttls_process_handshake(struct eap_sm *sm,
|
||||
{
|
||||
int res;
|
||||
|
||||
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-TTLS: External certificate check succeeded - continue handshake");
|
||||
*out_data = data->pending_resp;
|
||||
data->pending_resp = NULL;
|
||||
sm->waiting_ext_cert_check = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (config->pending_ext_cert_check == EXT_CERT_CHECK_BAD) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-TTLS: External certificate check failed - force authentication failure");
|
||||
ret->methodState = METHOD_DONE;
|
||||
ret->decision = DECISION_FAIL;
|
||||
sm->waiting_ext_cert_check = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-TTLS: Continuing to wait external server certificate validation");
|
||||
return 0;
|
||||
}
|
||||
|
||||
res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TTLS,
|
||||
data->ttls_version, identifier,
|
||||
in_data, out_data);
|
||||
@ -1420,6 +1491,15 @@ static int eap_ttls_process_handshake(struct eap_sm *sm,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sm->waiting_ext_cert_check) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-TTLS: Waiting external server certificate validation");
|
||||
wpabuf_free(data->pending_resp);
|
||||
data->pending_resp = *out_data;
|
||||
*out_data = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS done, proceed to "
|
||||
"Phase 2");
|
||||
@ -1470,6 +1550,7 @@ static void eap_ttls_check_auth_status(struct eap_sm *sm,
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication "
|
||||
"completed successfully");
|
||||
data->phase2_success = 1;
|
||||
data->decision_succ = ret->decision;
|
||||
#ifdef EAP_TNC
|
||||
if (!data->ready_for_tnc && !data->tnc_started) {
|
||||
/*
|
||||
@ -1487,6 +1568,18 @@ static void eap_ttls_check_auth_status(struct eap_sm *sm,
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication "
|
||||
"completed successfully (MAY_CONT)");
|
||||
data->phase2_success = 1;
|
||||
data->decision_succ = ret->decision;
|
||||
} else if (data->decision_succ != DECISION_FAIL &&
|
||||
data->phase2_success &&
|
||||
!data->ssl.tls_out) {
|
||||
/*
|
||||
* This is needed to cover the case where the final Phase 2
|
||||
* message gets fragmented since fragmentation clears
|
||||
* decision back to FAIL.
|
||||
*/
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-TTLS: Restore success decision after fragmented frame sent completely");
|
||||
ret->decision = data->decision_succ;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1559,6 +1652,9 @@ static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv)
|
||||
struct eap_ttls_data *data = priv;
|
||||
wpabuf_free(data->pending_phase2_req);
|
||||
data->pending_phase2_req = NULL;
|
||||
wpabuf_free(data->pending_resp);
|
||||
data->pending_resp = NULL;
|
||||
data->decision_succ = DECISION_FAIL;
|
||||
#ifdef EAP_TNC
|
||||
data->ready_for_tnc = 0;
|
||||
data->tnc_started = 0;
|
||||
@ -1697,7 +1793,6 @@ static u8 * eap_ttls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
|
||||
int eap_peer_ttls_register(void)
|
||||
{
|
||||
struct eap_method *eap;
|
||||
int ret;
|
||||
|
||||
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
|
||||
EAP_VENDOR_IETF, EAP_TYPE_TTLS, "TTLS");
|
||||
@ -1716,8 +1811,5 @@ int eap_peer_ttls_register(void)
|
||||
eap->init_for_reauth = eap_ttls_init_for_reauth;
|
||||
eap->get_emsk = eap_ttls_get_emsk;
|
||||
|
||||
ret = eap_peer_method_register(eap);
|
||||
if (ret)
|
||||
eap_peer_method_free(eap);
|
||||
return ret;
|
||||
return eap_peer_method_register(eap);
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ const struct eap_method * eap_server_get_eap_method(int vendor,
|
||||
EapType method);
|
||||
struct eap_method * eap_server_method_alloc(int version, int vendor,
|
||||
EapType method, const char *name);
|
||||
void eap_server_method_free(struct eap_method *method);
|
||||
int eap_server_method_register(struct eap_method *method);
|
||||
|
||||
EapType eap_server_get_type(const char *name, int *vendor);
|
||||
|
@ -316,6 +316,16 @@ SM_STATE(SUPP_PAE, RESTART)
|
||||
{
|
||||
SM_ENTRY(SUPP_PAE, RESTART);
|
||||
sm->eapRestart = TRUE;
|
||||
if (sm->altAccept) {
|
||||
/*
|
||||
* Prevent EAP peer state machine from failing due to prior
|
||||
* external EAP success notification (altSuccess=TRUE in the
|
||||
* IDLE state could result in a transition to the FAILURE state.
|
||||
*/
|
||||
wpa_printf(MSG_DEBUG, "EAPOL: Clearing prior altAccept TRUE");
|
||||
sm->eapSuccess = FALSE;
|
||||
sm->altAccept = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
||||
/**
|
||||
* P2P_MAX_REG_CLASSES - Maximum number of regulatory classes
|
||||
*/
|
||||
#define P2P_MAX_REG_CLASSES 10
|
||||
#define P2P_MAX_REG_CLASSES 15
|
||||
|
||||
/**
|
||||
* P2P_MAX_REG_CLASS_CHANNELS - Maximum number of channels per regulatory class
|
||||
@ -99,6 +99,10 @@ struct p2p_go_neg_results {
|
||||
|
||||
int vht;
|
||||
|
||||
u8 max_oper_chwidth;
|
||||
|
||||
unsigned int vht_center_freq2;
|
||||
|
||||
/**
|
||||
* ssid - SSID of the group
|
||||
*/
|
||||
@ -223,6 +227,16 @@ struct p2ps_provision {
|
||||
*/
|
||||
u8 cpt_priority[P2PS_FEATURE_CAPAB_CPT_MAX + 1];
|
||||
|
||||
/**
|
||||
* force_freq - The only allowed channel frequency in MHz or 0.
|
||||
*/
|
||||
unsigned int force_freq;
|
||||
|
||||
/**
|
||||
* pref_freq - Preferred operating frequency in MHz or 0.
|
||||
*/
|
||||
unsigned int pref_freq;
|
||||
|
||||
/**
|
||||
* info - Vendor defined extra Provisioning information
|
||||
*/
|
||||
@ -1024,6 +1038,8 @@ struct p2p_config {
|
||||
* @ssid_len: Buffer for returning length of @ssid
|
||||
* @group_iface: Buffer for returning whether a separate group interface
|
||||
* would be used
|
||||
* @freq: Variable for returning the current operating frequency of a
|
||||
* currently running P2P GO.
|
||||
* Returns: 1 if GO info found, 0 otherwise
|
||||
*
|
||||
* This is used to compose New Group settings (SSID, and intended
|
||||
@ -1031,7 +1047,8 @@ struct p2p_config {
|
||||
* result in our being an autonomous GO.
|
||||
*/
|
||||
int (*get_go_info)(void *ctx, u8 *intended_addr,
|
||||
u8 *ssid, size_t *ssid_len, int *group_iface);
|
||||
u8 *ssid, size_t *ssid_len, int *group_iface,
|
||||
unsigned int *freq);
|
||||
|
||||
/**
|
||||
* remove_stale_groups - Remove stale P2PS groups
|
||||
@ -1056,7 +1073,9 @@ struct p2p_config {
|
||||
const u8 *persist_ssid,
|
||||
size_t persist_ssid_size, int response_done,
|
||||
int prov_start, const char *session_info,
|
||||
const u8 *feat_cap, size_t feat_cap_len);
|
||||
const u8 *feat_cap, size_t feat_cap_len,
|
||||
unsigned int freq, const u8 *group_ssid,
|
||||
size_t group_ssid_len);
|
||||
|
||||
/**
|
||||
* prov_disc_resp_cb - Callback for indicating completion of PD Response
|
||||
@ -1070,14 +1089,20 @@ struct p2p_config {
|
||||
|
||||
/**
|
||||
* p2ps_group_capability - Determine group capability
|
||||
* @ctx: Callback context from cb_ctx
|
||||
* @incoming: Peer requested roles, expressed with P2PS_SETUP_* bitmap.
|
||||
* @role: Local roles, expressed with P2PS_SETUP_* bitmap.
|
||||
* @force_freq: Variable for returning forced frequency for the group.
|
||||
* @pref_freq: Variable for returning preferred frequency for the group.
|
||||
* Returns: P2PS_SETUP_* bitmap of group capability result.
|
||||
*
|
||||
* This function can be used to determine group capability based on
|
||||
* information from P2PS PD exchange and the current state of ongoing
|
||||
* groups and driver capabilities.
|
||||
*
|
||||
* P2PS_SETUP_* bitmap is used as the parameters and return value.
|
||||
* This function can be used to determine group capability and
|
||||
* frequencies based on information from P2PS PD exchange and the
|
||||
* current state of ongoing groups and driver capabilities.
|
||||
*/
|
||||
u8 (*p2ps_group_capability)(void *ctx, u8 incoming, u8 role);
|
||||
u8 (*p2ps_group_capability)(void *ctx, u8 incoming, u8 role,
|
||||
unsigned int *force_freq,
|
||||
unsigned int *pref_freq);
|
||||
|
||||
/**
|
||||
* get_pref_freq_list - Get preferred frequency list for an interface
|
||||
@ -1530,12 +1555,13 @@ enum p2p_probe_req_status {
|
||||
* @ie: Information elements from the Probe Request frame body
|
||||
* @ie_len: Length of ie buffer in octets
|
||||
* @rx_freq: Probe Request frame RX frequency
|
||||
* @p2p_lo_started: Whether P2P Listen Offload is started
|
||||
* Returns: value indicating the type and status of the probe request
|
||||
*/
|
||||
enum p2p_probe_req_status
|
||||
p2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
|
||||
const u8 *bssid, const u8 *ie, size_t ie_len,
|
||||
unsigned int rx_freq);
|
||||
unsigned int rx_freq, int p2p_lo_started);
|
||||
|
||||
/**
|
||||
* p2p_rx_action - Report received Action frame
|
||||
@ -1690,6 +1716,12 @@ struct p2p_group_config {
|
||||
*/
|
||||
int freq;
|
||||
|
||||
/**
|
||||
* ip_addr_alloc - Whether IP address allocation within 4-way handshake
|
||||
* is supported
|
||||
*/
|
||||
int ip_addr_alloc;
|
||||
|
||||
/**
|
||||
* cb_ctx - Context to use with callback functions
|
||||
*/
|
||||
@ -1877,8 +1909,10 @@ int p2p_assoc_req_ie(struct p2p_data *p2p, const u8 *bssid, u8 *buf,
|
||||
* @p2p: P2P module context from p2p_init()
|
||||
* @ies: Buffer for writing P2P IE
|
||||
* @dev_id: Device ID to search for or %NULL for any
|
||||
* @bands: Frequency bands used in the scan (enum wpa_radio_work_band bitmap)
|
||||
*/
|
||||
void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id);
|
||||
void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id,
|
||||
unsigned int bands);
|
||||
|
||||
/**
|
||||
* p2p_scan_ie_buf_len - Get maximum buffer length needed for p2p_scan_ie
|
||||
@ -2099,6 +2133,16 @@ int p2p_client_limit_reached(struct p2p_group *group);
|
||||
*/
|
||||
const u8 * p2p_iterate_group_members(struct p2p_group *group, void **next);
|
||||
|
||||
/**
|
||||
* p2p_group_get_client_interface_addr - Get P2P Interface Address of a client in a group
|
||||
* @group: P2P group context from p2p_group_init()
|
||||
* @dev_addr: P2P Device Address of the client
|
||||
* Returns: P2P Interface Address of the client if found or %NULL if no match
|
||||
* found
|
||||
*/
|
||||
const u8 * p2p_group_get_client_interface_addr(struct p2p_group *group,
|
||||
const u8 *dev_addr);
|
||||
|
||||
/**
|
||||
* p2p_group_get_dev_addr - Get a P2P Device Address of a client in a group
|
||||
* @group: P2P group context from p2p_group_init()
|
||||
@ -2241,7 +2285,7 @@ struct wpabuf * wifi_display_encaps(struct wpabuf *subelems);
|
||||
* discovery (p2p_find). A random number of 100 TU units is picked for each
|
||||
* Listen state iteration from [min_disc_int,max_disc_int] range.
|
||||
*
|
||||
* max_disc_tu can be used to futher limit the discoverable duration. However,
|
||||
* max_disc_tu can be used to further limit the discoverable duration. However,
|
||||
* it should be noted that use of this parameter is not recommended since it
|
||||
* would not be compliant with the P2P specification.
|
||||
*/
|
||||
@ -2340,4 +2384,7 @@ void p2p_set_own_pref_freq_list(struct p2p_data *p2p,
|
||||
int p2p_group_get_common_freqs(struct p2p_group *group, int *common_freqs,
|
||||
unsigned int *num);
|
||||
|
||||
struct wpabuf * p2p_build_probe_resp_template(struct p2p_data *p2p,
|
||||
unsigned int freq);
|
||||
|
||||
#endif /* P2P_H */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* RADIUS message processing
|
||||
* Copyright (c) 2002-2009, 2012, 2014, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2009, 2012, 2014-2015, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
@ -52,6 +52,8 @@ enum { RADIUS_ATTR_USER_NAME = 1,
|
||||
RADIUS_ATTR_USER_PASSWORD = 2,
|
||||
RADIUS_ATTR_NAS_IP_ADDRESS = 4,
|
||||
RADIUS_ATTR_NAS_PORT = 5,
|
||||
RADIUS_ATTR_SERVICE_TYPE = 6,
|
||||
RADIUS_ATTR_FRAMED_IP_ADDRESS = 8,
|
||||
RADIUS_ATTR_FRAMED_MTU = 12,
|
||||
RADIUS_ATTR_REPLY_MESSAGE = 18,
|
||||
RADIUS_ATTR_STATE = 24,
|
||||
@ -79,6 +81,7 @@ enum { RADIUS_ATTR_USER_NAME = 1,
|
||||
RADIUS_ATTR_ACCT_INPUT_GIGAWORDS = 52,
|
||||
RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS = 53,
|
||||
RADIUS_ATTR_EVENT_TIMESTAMP = 55,
|
||||
RADIUS_ATTR_EGRESS_VLANID = 56,
|
||||
RADIUS_ATTR_NAS_PORT_TYPE = 61,
|
||||
RADIUS_ATTR_TUNNEL_TYPE = 64,
|
||||
RADIUS_ATTR_TUNNEL_MEDIUM_TYPE = 65,
|
||||
@ -108,6 +111,9 @@ enum { RADIUS_ATTR_USER_NAME = 1,
|
||||
};
|
||||
|
||||
|
||||
/* Service-Type values (RFC 2865, 5.6) */
|
||||
#define RADIUS_SERVICE_TYPE_FRAMED 2
|
||||
|
||||
/* Termination-Action */
|
||||
#define RADIUS_TERMINATION_ACTION_DEFAULT 0
|
||||
#define RADIUS_TERMINATION_ACTION_RADIUS_REQUEST 1
|
||||
@ -236,7 +242,8 @@ void radius_msg_finish_acct_resp(struct radius_msg *msg, const u8 *secret,
|
||||
int radius_msg_verify_acct_req(struct radius_msg *msg, const u8 *secret,
|
||||
size_t secret_len);
|
||||
int radius_msg_verify_das_req(struct radius_msg *msg, const u8 *secret,
|
||||
size_t secret_len);
|
||||
size_t secret_len,
|
||||
int require_message_authenticator);
|
||||
struct radius_attr_hdr * radius_msg_add_attr(struct radius_msg *msg, u8 type,
|
||||
const u8 *data, size_t data_len);
|
||||
struct radius_msg * radius_msg_parse(const u8 *data, size_t len);
|
||||
@ -250,8 +257,7 @@ int radius_msg_verify_msg_auth(struct radius_msg *msg, const u8 *secret,
|
||||
size_t secret_len, const u8 *req_auth);
|
||||
int radius_msg_copy_attr(struct radius_msg *dst, struct radius_msg *src,
|
||||
u8 type);
|
||||
void radius_msg_make_authenticator(struct radius_msg *msg,
|
||||
const u8 *data, size_t len);
|
||||
int radius_msg_make_authenticator(struct radius_msg *msg);
|
||||
struct radius_ms_mppe_keys *
|
||||
radius_msg_get_ms_keys(struct radius_msg *msg, struct radius_msg *sent_msg,
|
||||
const u8 *secret, size_t secret_len);
|
||||
@ -274,7 +280,8 @@ radius_msg_add_attr_user_password(struct radius_msg *msg,
|
||||
const u8 *data, size_t data_len,
|
||||
const u8 *secret, size_t secret_len);
|
||||
int radius_msg_get_attr(struct radius_msg *msg, u8 type, u8 *buf, size_t len);
|
||||
int radius_msg_get_vlanid(struct radius_msg *msg);
|
||||
int radius_msg_get_vlanid(struct radius_msg *msg, int *untagged, int numtagged,
|
||||
int *tagged);
|
||||
char * radius_msg_get_tunnel_password(struct radius_msg *msg, int *keylen,
|
||||
const u8 *secret, size_t secret_len,
|
||||
struct radius_msg *sent_msg, size_t n);
|
||||
@ -319,4 +326,6 @@ int radius_copy_class(struct radius_class_data *dst,
|
||||
|
||||
u8 radius_msg_find_unlisted_attr(struct radius_msg *msg, u8 *attrs);
|
||||
|
||||
int radius_gen_session_id(u8 *id, size_t len);
|
||||
|
||||
#endif /* RADIUS_H */
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "wpa_i.h"
|
||||
#include "pmksa_cache.h"
|
||||
|
||||
#ifdef IEEE8021X_EAPOL
|
||||
#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA)
|
||||
|
||||
static const int pmksa_cache_max_entries = 32;
|
||||
|
||||
@ -111,6 +111,7 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
|
||||
* @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
|
||||
* @pmk: The new pairwise master key
|
||||
* @pmk_len: PMK length in bytes, usually PMK_LEN (32)
|
||||
* @pmkid: Calculated PMKID
|
||||
* @kck: Key confirmation key or %NULL if not yet derived
|
||||
* @kck_len: KCK length in bytes
|
||||
* @aa: Authenticator address
|
||||
@ -126,13 +127,13 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
|
||||
*/
|
||||
struct rsn_pmksa_cache_entry *
|
||||
pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
|
||||
const u8 *kck, size_t kck_len,
|
||||
const u8 *pmkid, const u8 *kck, size_t kck_len,
|
||||
const u8 *aa, const u8 *spa, void *network_ctx, int akmp)
|
||||
{
|
||||
struct rsn_pmksa_cache_entry *entry, *pos, *prev;
|
||||
struct os_reltime now;
|
||||
|
||||
if (pmk_len > PMK_LEN)
|
||||
if (pmk_len > PMK_LEN_MAX)
|
||||
return NULL;
|
||||
|
||||
if (wpa_key_mgmt_suite_b(akmp) && !kck)
|
||||
@ -143,7 +144,9 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
|
||||
return NULL;
|
||||
os_memcpy(entry->pmk, pmk, pmk_len);
|
||||
entry->pmk_len = pmk_len;
|
||||
if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
|
||||
if (pmkid)
|
||||
os_memcpy(entry->pmkid, pmkid, PMKID_LEN);
|
||||
else if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
|
||||
rsn_pmkid_suite_b_192(kck, kck_len, aa, spa, entry->pmkid);
|
||||
else if (wpa_key_mgmt_suite_b(akmp))
|
||||
rsn_pmkid_suite_b(kck, kck_len, aa, spa, entry->pmkid);
|
||||
@ -346,7 +349,7 @@ pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa,
|
||||
struct rsn_pmksa_cache_entry *new_entry;
|
||||
|
||||
new_entry = pmksa_cache_add(pmksa, old_entry->pmk, old_entry->pmk_len,
|
||||
NULL, 0,
|
||||
NULL, NULL, 0,
|
||||
aa, pmksa->sm->own_addr,
|
||||
old_entry->network_ctx, old_entry->akmp);
|
||||
if (new_entry == NULL)
|
||||
|
@ -15,7 +15,7 @@
|
||||
struct rsn_pmksa_cache_entry {
|
||||
struct rsn_pmksa_cache_entry *next;
|
||||
u8 pmkid[PMKID_LEN];
|
||||
u8 pmk[PMK_LEN];
|
||||
u8 pmk[PMK_LEN_MAX];
|
||||
size_t pmk_len;
|
||||
os_time_t expiration;
|
||||
int akmp; /* WPA_KEY_MGMT_* */
|
||||
@ -44,7 +44,7 @@ enum pmksa_free_reason {
|
||||
PMKSA_EXPIRE,
|
||||
};
|
||||
|
||||
#ifdef IEEE8021X_EAPOL
|
||||
#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA)
|
||||
|
||||
struct rsn_pmksa_cache *
|
||||
pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
|
||||
@ -57,7 +57,7 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
|
||||
int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len);
|
||||
struct rsn_pmksa_cache_entry *
|
||||
pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
|
||||
const u8 *kck, size_t kck_len,
|
||||
const u8 *pmkid, const u8 *kck, size_t kck_len,
|
||||
const u8 *aa, const u8 *spa, void *network_ctx, int akmp);
|
||||
struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm);
|
||||
void pmksa_cache_clear_current(struct wpa_sm *sm);
|
||||
@ -105,7 +105,7 @@ static inline int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf,
|
||||
|
||||
static inline struct rsn_pmksa_cache_entry *
|
||||
pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
|
||||
const u8 *kck, size_t kck_len,
|
||||
const u8 *pmkid, const u8 *kck, size_t kck_len,
|
||||
const u8 *aa, const u8 *spa, void *network_ctx, int akmp)
|
||||
{
|
||||
return NULL;
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "wpa_i.h"
|
||||
|
||||
|
||||
#ifdef IEEE8021X_EAPOL
|
||||
#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA)
|
||||
|
||||
#define PMKID_CANDIDATE_PRIO_SCAN 1000
|
||||
|
||||
@ -95,7 +95,7 @@ static void rsn_preauth_eapol_cb(struct eapol_sm *eapol,
|
||||
wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from pre-auth",
|
||||
pmk, pmk_len);
|
||||
sm->pmk_len = pmk_len;
|
||||
pmksa_cache_add(sm->pmksa, pmk, pmk_len,
|
||||
pmksa_cache_add(sm->pmksa, pmk, pmk_len, NULL,
|
||||
NULL, 0,
|
||||
sm->preauth_bssid, sm->own_addr,
|
||||
sm->network_ctx,
|
||||
@ -540,4 +540,4 @@ int rsn_preauth_in_progress(struct wpa_sm *sm)
|
||||
return sm->preauth_eapol != NULL;
|
||||
}
|
||||
|
||||
#endif /* IEEE8021X_EAPOL */
|
||||
#endif /* IEEE8021X_EAPOL && !CONFIG_NO_WPA */
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
struct wpa_scan_results;
|
||||
|
||||
#ifdef IEEE8021X_EAPOL
|
||||
#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA)
|
||||
|
||||
void pmksa_candidate_free(struct wpa_sm *sm);
|
||||
int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst,
|
||||
@ -27,7 +27,7 @@ int rsn_preauth_get_status(struct wpa_sm *sm, char *buf, size_t buflen,
|
||||
int verbose);
|
||||
int rsn_preauth_in_progress(struct wpa_sm *sm);
|
||||
|
||||
#else /* IEEE8021X_EAPOL */
|
||||
#else /* IEEE8021X_EAPOL && !CONFIG_NO_WPA */
|
||||
|
||||
static inline void pmksa_candidate_free(struct wpa_sm *sm)
|
||||
{
|
||||
@ -74,6 +74,6 @@ static inline int rsn_preauth_in_progress(struct wpa_sm *sm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* IEEE8021X_EAPOL */
|
||||
#endif /* IEEE8021X_EAPOL && !CONFIG_NO_WPA */
|
||||
|
||||
#endif /* PREAUTH_H */
|
||||
|
@ -3,6 +3,7 @@
|
||||
/*
|
||||
* WPA Supplicant - WPA state machine and EAPOL-Key processing
|
||||
* Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
|
||||
* Copyright(c) 2015 Intel Deutschland GmbH
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
@ -25,6 +26,9 @@
|
||||
#include "peerkey.h"
|
||||
|
||||
|
||||
static const u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
|
||||
/**
|
||||
* wpa_eapol_key_send - Send WPA/RSN EAPOL-Key message
|
||||
* @sm: Pointer to WPA state machine data from wpa_sm_init()
|
||||
@ -36,11 +40,13 @@
|
||||
* @msg: EAPOL-Key message
|
||||
* @msg_len: Length of message
|
||||
* @key_mic: Pointer to the buffer to which the EAPOL-Key MIC is written
|
||||
* Returns: >= 0 on success, < 0 on failure
|
||||
*/
|
||||
void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len,
|
||||
int ver, const u8 *dest, u16 proto,
|
||||
u8 *msg, size_t msg_len, u8 *key_mic)
|
||||
int wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len,
|
||||
int ver, const u8 *dest, u16 proto,
|
||||
u8 *msg, size_t msg_len, u8 *key_mic)
|
||||
{
|
||||
int ret = -1;
|
||||
size_t mic_len = wpa_mic_len(sm->key_mgmt);
|
||||
|
||||
if (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) {
|
||||
@ -71,10 +77,11 @@ void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len,
|
||||
wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", kck, kck_len);
|
||||
wpa_hexdump(MSG_DEBUG, "WPA: Derived Key MIC", key_mic, mic_len);
|
||||
wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len);
|
||||
wpa_sm_ether_send(sm, dest, proto, msg, msg_len);
|
||||
ret = wpa_sm_ether_send(sm, dest, proto, msg, msg_len);
|
||||
eapol_sm_notify_tx_eapol_key(sm->eapol);
|
||||
out:
|
||||
os_free(msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -126,7 +133,7 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise)
|
||||
EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
|
||||
key_info = WPA_KEY_INFO_REQUEST | ver;
|
||||
if (sm->ptk_set)
|
||||
key_info |= WPA_KEY_INFO_MIC;
|
||||
key_info |= WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE;
|
||||
if (error)
|
||||
key_info |= WPA_KEY_INFO_ERROR;
|
||||
if (pairwise)
|
||||
@ -208,15 +215,21 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
} else if (wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && sm->eapol) {
|
||||
int res, pmk_len;
|
||||
pmk_len = PMK_LEN;
|
||||
res = eapol_sm_get_key(sm->eapol, sm->pmk, PMK_LEN);
|
||||
|
||||
if (sm->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)
|
||||
pmk_len = PMK_LEN_SUITE_B_192;
|
||||
else
|
||||
pmk_len = PMK_LEN;
|
||||
res = eapol_sm_get_key(sm->eapol, sm->pmk, pmk_len);
|
||||
if (res) {
|
||||
/*
|
||||
* EAP-LEAP is an exception from other EAP methods: it
|
||||
* uses only 16-byte PMK.
|
||||
*/
|
||||
res = eapol_sm_get_key(sm->eapol, sm->pmk, 16);
|
||||
pmk_len = 16;
|
||||
if (pmk_len == PMK_LEN) {
|
||||
/*
|
||||
* EAP-LEAP is an exception from other EAP
|
||||
* methods: it uses only 16-byte PMK.
|
||||
*/
|
||||
res = eapol_sm_get_key(sm->eapol, sm->pmk, 16);
|
||||
pmk_len = 16;
|
||||
}
|
||||
} else {
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
u8 buf[2 * PMK_LEN];
|
||||
@ -238,7 +251,7 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
|
||||
!wpa_key_mgmt_suite_b(sm->key_mgmt) &&
|
||||
!wpa_key_mgmt_ft(sm->key_mgmt)) {
|
||||
sa = pmksa_cache_add(sm->pmksa,
|
||||
sm->pmk, pmk_len,
|
||||
sm->pmk, pmk_len, NULL,
|
||||
NULL, 0,
|
||||
src_addr, sm->own_addr,
|
||||
sm->network_ctx,
|
||||
@ -259,7 +272,7 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
|
||||
* much we can do here without knowing what
|
||||
* exactly caused the server to misbehave.
|
||||
*/
|
||||
wpa_dbg(sm->ctx->msg_ctx, MSG_INFO,
|
||||
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
||||
"RSN: PMKID mismatch - authentication server may have derived different MSK?!");
|
||||
return -1;
|
||||
}
|
||||
@ -320,7 +333,7 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
|
||||
* @wpa_ie: WPA/RSN IE
|
||||
* @wpa_ie_len: Length of the WPA/RSN IE
|
||||
* @ptk: PTK to use for keyed hash and encryption
|
||||
* Returns: 0 on success, -1 on failure
|
||||
* Returns: >= 0 on success, < 0 on failure
|
||||
*/
|
||||
int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
|
||||
const struct wpa_eapol_key *key,
|
||||
@ -353,13 +366,12 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
|
||||
if (rsn_ie_buf == NULL)
|
||||
return -1;
|
||||
os_memcpy(rsn_ie_buf, wpa_ie, wpa_ie_len);
|
||||
res = wpa_insert_pmkid(rsn_ie_buf, wpa_ie_len,
|
||||
res = wpa_insert_pmkid(rsn_ie_buf, &wpa_ie_len,
|
||||
sm->pmk_r1_name);
|
||||
if (res < 0) {
|
||||
os_free(rsn_ie_buf);
|
||||
return -1;
|
||||
}
|
||||
wpa_ie_len += res;
|
||||
|
||||
if (sm->assoc_resp_ies) {
|
||||
os_memcpy(rsn_ie_buf + wpa_ie_len, sm->assoc_resp_ies,
|
||||
@ -411,10 +423,8 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
|
||||
os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN);
|
||||
|
||||
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4");
|
||||
wpa_eapol_key_send(sm, ptk->kck, ptk->kck_len, ver, dst, ETH_P_EAPOL,
|
||||
rbuf, rlen, key_mic);
|
||||
|
||||
return 0;
|
||||
return wpa_eapol_key_send(sm, ptk->kck, ptk->kck_len, ver, dst,
|
||||
ETH_P_EAPOL, rbuf, rlen, key_mic);
|
||||
}
|
||||
|
||||
|
||||
@ -527,7 +537,7 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce,
|
||||
kde, kde_len, ptk))
|
||||
kde, kde_len, ptk) < 0)
|
||||
goto failed;
|
||||
|
||||
os_free(kde_buf);
|
||||
@ -605,7 +615,6 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
|
||||
int keylen, rsclen;
|
||||
enum wpa_alg alg;
|
||||
const u8 *key_rsc;
|
||||
u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
if (sm->ptk.installed) {
|
||||
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
|
||||
@ -783,12 +792,43 @@ static int wpa_supplicant_gtk_tx_bit_workaround(const struct wpa_sm *sm,
|
||||
}
|
||||
|
||||
|
||||
static int wpa_supplicant_rsc_relaxation(const struct wpa_sm *sm,
|
||||
const u8 *rsc)
|
||||
{
|
||||
int rsclen;
|
||||
|
||||
if (!sm->wpa_rsc_relaxation)
|
||||
return 0;
|
||||
|
||||
rsclen = wpa_cipher_rsc_len(sm->group_cipher);
|
||||
|
||||
/*
|
||||
* Try to detect RSC (endian) corruption issue where the AP sends
|
||||
* the RSC bytes in EAPOL-Key message in the wrong order, both if
|
||||
* it's actually a 6-byte field (as it should be) and if it treats
|
||||
* it as an 8-byte field.
|
||||
* An AP model known to have this bug is the Sapido RB-1632.
|
||||
*/
|
||||
if (rsclen == 6 && ((rsc[5] && !rsc[0]) || rsc[6] || rsc[7])) {
|
||||
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
|
||||
"RSC %02x%02x%02x%02x%02x%02x%02x%02x is likely bogus, using 0",
|
||||
rsc[0], rsc[1], rsc[2], rsc[3],
|
||||
rsc[4], rsc[5], rsc[6], rsc[7]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm,
|
||||
const struct wpa_eapol_key *key,
|
||||
const u8 *gtk, size_t gtk_len,
|
||||
int key_info)
|
||||
{
|
||||
struct wpa_gtk_data gd;
|
||||
const u8 *key_rsc;
|
||||
|
||||
/*
|
||||
* IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames - Figure 43x
|
||||
@ -814,11 +854,15 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm,
|
||||
os_memcpy(gd.gtk, gtk, gtk_len);
|
||||
gd.gtk_len = gtk_len;
|
||||
|
||||
key_rsc = key->key_rsc;
|
||||
if (wpa_supplicant_rsc_relaxation(sm, key->key_rsc))
|
||||
key_rsc = null_rsc;
|
||||
|
||||
if (sm->group_cipher != WPA_CIPHER_GTK_NOT_USED &&
|
||||
(wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
|
||||
gtk_len, gtk_len,
|
||||
&gd.key_rsc_len, &gd.alg) ||
|
||||
wpa_supplicant_install_gtk(sm, &gd, key->key_rsc, 0))) {
|
||||
wpa_supplicant_install_gtk(sm, &gd, key_rsc, 0))) {
|
||||
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
|
||||
"RSN: Failed to install GTK");
|
||||
os_memset(&gd, 0, sizeof(gd));
|
||||
@ -1055,8 +1099,8 @@ static int wpa_supplicant_validate_ie_ft(struct wpa_sm *sm,
|
||||
if (sm->assoc_resp_ies) {
|
||||
pos = sm->assoc_resp_ies;
|
||||
end = pos + sm->assoc_resp_ies_len;
|
||||
while (pos + 2 < end) {
|
||||
if (pos + 2 + pos[1] > end)
|
||||
while (end - pos > 2) {
|
||||
if (2 + pos[1] > end - pos)
|
||||
break;
|
||||
switch (*pos) {
|
||||
case WLAN_EID_MOBILITY_DOMAIN:
|
||||
@ -1152,7 +1196,7 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm,
|
||||
* @ver: Version bits from EAPOL-Key Key Info
|
||||
* @key_info: Key Info
|
||||
* @ptk: PTK to use for keyed hash and encryption
|
||||
* Returns: 0 on success, -1 on failure
|
||||
* Returns: >= 0 on success, < 0 on failure
|
||||
*/
|
||||
int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst,
|
||||
const struct wpa_eapol_key *key,
|
||||
@ -1192,10 +1236,8 @@ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst,
|
||||
WPA_PUT_BE16(reply->key_data_length, 0);
|
||||
|
||||
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4");
|
||||
wpa_eapol_key_send(sm, ptk->kck, ptk->kck_len, ver, dst, ETH_P_EAPOL,
|
||||
rbuf, rlen, key_mic);
|
||||
|
||||
return 0;
|
||||
return wpa_eapol_key_send(sm, ptk->kck, ptk->kck_len, ver, dst,
|
||||
ETH_P_EAPOL, rbuf, rlen, key_mic);
|
||||
}
|
||||
|
||||
|
||||
@ -1268,7 +1310,7 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info,
|
||||
&sm->ptk)) {
|
||||
&sm->ptk) < 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
@ -1313,7 +1355,7 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
|
||||
if (sm->proto == WPA_PROTO_RSN && wpa_key_mgmt_suite_b(sm->key_mgmt)) {
|
||||
struct rsn_pmksa_cache_entry *sa;
|
||||
|
||||
sa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len,
|
||||
sa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len, NULL,
|
||||
sm->ptk.kck, sm->ptk.kck_len,
|
||||
sm->bssid, sm->own_addr,
|
||||
sm->network_ctx, sm->key_mgmt);
|
||||
@ -1503,10 +1545,8 @@ static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm,
|
||||
WPA_PUT_BE16(reply->key_data_length, 0);
|
||||
|
||||
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2");
|
||||
wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, sm->bssid,
|
||||
ETH_P_EAPOL, rbuf, rlen, key_mic);
|
||||
|
||||
return 0;
|
||||
return wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver,
|
||||
sm->bssid, ETH_P_EAPOL, rbuf, rlen, key_mic);
|
||||
}
|
||||
|
||||
|
||||
@ -1519,6 +1559,7 @@ static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
|
||||
u16 key_info;
|
||||
int rekey, ret;
|
||||
struct wpa_gtk_data gd;
|
||||
const u8 *key_rsc;
|
||||
|
||||
if (!sm->msg_3_of_4_ok) {
|
||||
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
|
||||
@ -1549,13 +1590,17 @@ static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
|
||||
if (ret)
|
||||
goto failed;
|
||||
|
||||
if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc, 0) ||
|
||||
wpa_supplicant_send_2_of_2(sm, key, ver, key_info))
|
||||
key_rsc = key->key_rsc;
|
||||
if (wpa_supplicant_rsc_relaxation(sm, key->key_rsc))
|
||||
key_rsc = null_rsc;
|
||||
|
||||
if (wpa_supplicant_install_gtk(sm, &gd, key_rsc, 0) ||
|
||||
wpa_supplicant_send_2_of_2(sm, key, ver, key_info) < 0)
|
||||
goto failed;
|
||||
os_memset(&gd, 0, sizeof(gd));
|
||||
|
||||
if (rekey) {
|
||||
wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Group rekeying "
|
||||
wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Group rekeying "
|
||||
"completed with " MACSTR " [GTK=%s]",
|
||||
MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher));
|
||||
wpa_sm_cancel_auth_timeout(sm);
|
||||
@ -1683,14 +1728,14 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
|
||||
}
|
||||
if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, *key_data_len / 8,
|
||||
key_data, buf)) {
|
||||
os_free(buf);
|
||||
bin_clear_free(buf, *key_data_len);
|
||||
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
|
||||
"WPA: AES unwrap failed - "
|
||||
"could not decrypt EAPOL-Key key data");
|
||||
return -1;
|
||||
}
|
||||
os_memcpy(key_data, buf, *key_data_len);
|
||||
os_free(buf);
|
||||
bin_clear_free(buf, *key_data_len);
|
||||
WPA_PUT_BE16(key->key_data_length, *key_data_len);
|
||||
} else {
|
||||
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
|
||||
@ -2029,6 +2074,17 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
|
||||
|
||||
if ((sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) &&
|
||||
(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
|
||||
/*
|
||||
* Only decrypt the Key Data field if the frame's authenticity
|
||||
* was verified. When using AES-SIV (FILS), the MIC flag is not
|
||||
* set, so this check should only be performed if mic_len != 0
|
||||
* which is the case in this code branch.
|
||||
*/
|
||||
if (!(key_info & WPA_KEY_INFO_MIC)) {
|
||||
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
|
||||
"WPA: Ignore EAPOL-Key with encrypted but unauthenticated data");
|
||||
goto out;
|
||||
}
|
||||
if (wpa_supplicant_decrypt_key_data(sm, key, ver, key_data,
|
||||
&key_data_len))
|
||||
goto out;
|
||||
@ -2303,6 +2359,9 @@ void wpa_sm_deinit(struct wpa_sm *sm)
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
os_free(sm->assoc_resp_ies);
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
wpabuf_free(sm->test_assoc_ie);
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
os_free(sm);
|
||||
}
|
||||
|
||||
@ -2410,12 +2469,13 @@ void wpa_sm_notify_disassoc(struct wpa_sm *sm)
|
||||
* @sm: Pointer to WPA state machine data from wpa_sm_init()
|
||||
* @pmk: The new PMK
|
||||
* @pmk_len: The length of the new PMK in bytes
|
||||
* @pmkid: Calculated PMKID
|
||||
* @bssid: AA to add into PMKSA cache or %NULL to not cache the PMK
|
||||
*
|
||||
* Configure the PMK for WPA state machine.
|
||||
*/
|
||||
void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
|
||||
const u8 *bssid)
|
||||
const u8 *pmkid, const u8 *bssid)
|
||||
{
|
||||
if (sm == NULL)
|
||||
return;
|
||||
@ -2430,7 +2490,7 @@ void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
if (bssid) {
|
||||
pmksa_cache_add(sm->pmksa, pmk, pmk_len, NULL, 0,
|
||||
pmksa_cache_add(sm->pmksa, pmk, pmk_len, pmkid, NULL, 0,
|
||||
bssid, sm->own_addr,
|
||||
sm->network_ctx, sm->key_mgmt);
|
||||
}
|
||||
@ -2514,6 +2574,7 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config)
|
||||
sm->ssid_len = 0;
|
||||
sm->wpa_ptk_rekey = config->wpa_ptk_rekey;
|
||||
sm->p2p = config->p2p;
|
||||
sm->wpa_rsc_relaxation = config->wpa_rsc_relaxation;
|
||||
} else {
|
||||
sm->network_ctx = NULL;
|
||||
sm->peerkey_enabled = 0;
|
||||
@ -2524,6 +2585,7 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config)
|
||||
sm->ssid_len = 0;
|
||||
sm->wpa_ptk_rekey = 0;
|
||||
sm->p2p = 0;
|
||||
sm->wpa_rsc_relaxation = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2711,6 +2773,17 @@ int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie,
|
||||
if (sm == NULL)
|
||||
return -1;
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
if (sm->test_assoc_ie) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"TESTING: Replace association WPA/RSN IE");
|
||||
if (*wpa_ie_len < wpabuf_len(sm->test_assoc_ie))
|
||||
return -1;
|
||||
os_memcpy(wpa_ie, wpabuf_head(sm->test_assoc_ie),
|
||||
wpabuf_len(sm->test_assoc_ie));
|
||||
res = wpabuf_len(sm->test_assoc_ie);
|
||||
} else
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
res = wpa_gen_wpa_ie(sm, wpa_ie, *wpa_ie_len);
|
||||
if (res < 0)
|
||||
return -1;
|
||||
@ -3038,3 +3111,12 @@ void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm,
|
||||
}
|
||||
sm->ptk_set = 1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
void wpa_sm_set_test_assoc_ie(struct wpa_sm *sm, struct wpabuf *buf)
|
||||
{
|
||||
wpabuf_free(sm->test_assoc_ie);
|
||||
sm->test_assoc_ie = buf;
|
||||
}
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
@ -104,6 +104,7 @@ struct rsn_supp_config {
|
||||
size_t ssid_len;
|
||||
int wpa_ptk_rekey;
|
||||
int p2p;
|
||||
int wpa_rsc_relaxation;
|
||||
};
|
||||
|
||||
#ifndef CONFIG_NO_WPA
|
||||
@ -113,7 +114,7 @@ void wpa_sm_deinit(struct wpa_sm *sm);
|
||||
void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid);
|
||||
void wpa_sm_notify_disassoc(struct wpa_sm *sm);
|
||||
void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
|
||||
const u8 *bssid);
|
||||
const u8 *pmkid, const u8 *bssid);
|
||||
void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm);
|
||||
void wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth);
|
||||
void wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx);
|
||||
@ -180,7 +181,8 @@ static inline void wpa_sm_notify_disassoc(struct wpa_sm *sm)
|
||||
}
|
||||
|
||||
static inline void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk,
|
||||
size_t pmk_len)
|
||||
size_t pmk_len, const u8 *pmkid,
|
||||
const u8 *bssid)
|
||||
{
|
||||
}
|
||||
|
||||
@ -320,7 +322,8 @@ static inline void wpa_sm_set_rx_replay_ctr(struct wpa_sm *sm,
|
||||
}
|
||||
|
||||
static inline void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm, const u8 *ptk_kck,
|
||||
const u8 *ptk_kek)
|
||||
size_t ptk_kck_len,
|
||||
const u8 *ptk_kek, size_t ptk_kek_len)
|
||||
{
|
||||
}
|
||||
|
||||
@ -415,7 +418,12 @@ int wpa_tdls_enable_chan_switch(struct wpa_sm *sm, const u8 *addr,
|
||||
u8 oper_class,
|
||||
struct hostapd_freq_params *freq_params);
|
||||
int wpa_tdls_disable_chan_switch(struct wpa_sm *sm, const u8 *addr);
|
||||
#ifdef CONFIG_TDLS_TESTING
|
||||
extern unsigned int tdls_testing;
|
||||
#endif /* CONFIG_TDLS_TESTING */
|
||||
|
||||
|
||||
int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf);
|
||||
void wpa_sm_set_test_assoc_ie(struct wpa_sm *sm, struct wpabuf *buf);
|
||||
|
||||
#endif /* WPA_H */
|
||||
|
@ -19,7 +19,7 @@ struct wpa_eapol_key;
|
||||
* struct wpa_sm - Internal WPA state machine data
|
||||
*/
|
||||
struct wpa_sm {
|
||||
u8 pmk[PMK_LEN];
|
||||
u8 pmk[PMK_LEN_MAX];
|
||||
size_t pmk_len;
|
||||
struct wpa_ptk ptk, tptk;
|
||||
int ptk_set, tptk_set;
|
||||
@ -66,6 +66,7 @@ struct wpa_sm {
|
||||
size_t ssid_len;
|
||||
int wpa_ptk_rekey;
|
||||
int p2p;
|
||||
int wpa_rsc_relaxation;
|
||||
|
||||
u8 own_addr[ETH_ALEN];
|
||||
const char *ifname;
|
||||
@ -139,6 +140,10 @@ struct wpa_sm {
|
||||
#ifdef CONFIG_P2P
|
||||
u8 p2p_ip_addr[3 * 4];
|
||||
#endif /* CONFIG_P2P */
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
struct wpabuf *test_assoc_ie;
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
};
|
||||
|
||||
|
||||
@ -349,16 +354,14 @@ wpa_sm_tdls_disable_channel_switch(struct wpa_sm *sm, const u8 *addr)
|
||||
static inline int wpa_sm_key_mgmt_set_pmk(struct wpa_sm *sm,
|
||||
const u8 *pmk, size_t pmk_len)
|
||||
{
|
||||
if (!sm->proactive_key_caching)
|
||||
return 0;
|
||||
if (!sm->ctx->key_mgmt_set_pmk)
|
||||
return -1;
|
||||
return sm->ctx->key_mgmt_set_pmk(sm->ctx->ctx, pmk, pmk_len);
|
||||
}
|
||||
|
||||
void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len,
|
||||
int ver, const u8 *dest, u16 proto,
|
||||
u8 *msg, size_t msg_len, u8 *key_mic);
|
||||
int wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len,
|
||||
int ver, const u8 *dest, u16 proto,
|
||||
u8 *msg, size_t msg_len, u8 *key_mic);
|
||||
int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
|
||||
const struct wpa_eapol_key *key,
|
||||
int ver, const u8 *nonce,
|
||||
|
@ -380,7 +380,7 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pos + 1 + RSN_SELECTOR_LEN < end &&
|
||||
if (1 + RSN_SELECTOR_LEN < end - pos &&
|
||||
pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN &&
|
||||
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) {
|
||||
ie->pmkid = pos + 2 + RSN_SELECTOR_LEN;
|
||||
@ -493,13 +493,13 @@ int wpa_supplicant_parse_ies(const u8 *buf, size_t len,
|
||||
int ret = 0;
|
||||
|
||||
os_memset(ie, 0, sizeof(*ie));
|
||||
for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) {
|
||||
for (pos = buf, end = pos + len; end - pos > 1; pos += 2 + pos[1]) {
|
||||
if (pos[0] == 0xdd &&
|
||||
((pos == buf + len - 1) || pos[1] == 0)) {
|
||||
/* Ignore padding */
|
||||
break;
|
||||
}
|
||||
if (pos + 2 + pos[1] > end) {
|
||||
if (2 + pos[1] > end - pos) {
|
||||
wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data "
|
||||
"underflow (ie=%d len=%d pos=%d)",
|
||||
pos[0], pos[1], (int) (pos - buf));
|
||||
|
@ -41,7 +41,7 @@ int tlsv1_client_get_keyblock_size(struct tlsv1_client *conn);
|
||||
int tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers);
|
||||
int tlsv1_client_set_cred(struct tlsv1_client *conn,
|
||||
struct tlsv1_credentials *cred);
|
||||
void tlsv1_client_set_time_checks(struct tlsv1_client *conn, int enabled);
|
||||
void tlsv1_client_set_flags(struct tlsv1_client *conn, unsigned int flags);
|
||||
|
||||
typedef int (*tlsv1_client_session_ticket_cb)
|
||||
(void *ctx, const u8 *ticket, size_t len, const u8 *client_random,
|
||||
@ -51,4 +51,12 @@ void tlsv1_client_set_session_ticket_cb(struct tlsv1_client *conn,
|
||||
tlsv1_client_session_ticket_cb cb,
|
||||
void *ctx);
|
||||
|
||||
void tlsv1_client_set_cb(struct tlsv1_client *conn,
|
||||
void (*event_cb)(void *ctx, enum tls_event ev,
|
||||
union tls_event_data *data),
|
||||
void *cb_ctx,
|
||||
int cert_in_cb);
|
||||
int tlsv1_client_get_version(struct tlsv1_client *conn, char *buf,
|
||||
size_t buflen);
|
||||
|
||||
#endif /* TLSV1_CLIENT_H */
|
||||
|
@ -14,11 +14,19 @@ struct tlsv1_credentials {
|
||||
struct x509_certificate *cert;
|
||||
struct crypto_private_key *key;
|
||||
|
||||
unsigned int cert_probe:1;
|
||||
unsigned int ca_cert_verify:1;
|
||||
unsigned int server_cert_only:1;
|
||||
u8 srv_cert_hash[32];
|
||||
|
||||
/* Diffie-Hellman parameters */
|
||||
u8 *dh_p; /* prime */
|
||||
size_t dh_p_len;
|
||||
u8 *dh_g; /* generator */
|
||||
size_t dh_g_len;
|
||||
|
||||
char *ocsp_stapling_response;
|
||||
char *ocsp_stapling_response_multi;
|
||||
};
|
||||
|
||||
|
||||
|
@ -88,7 +88,7 @@ int hwaddr_masked_aton(const char *txt, u8 *addr, u8 *mask, u8 maskable)
|
||||
return -1;
|
||||
|
||||
/* check for optional mask */
|
||||
if (*r == '\0' || isspace(*r)) {
|
||||
if (*r == '\0' || isspace((unsigned char) *r)) {
|
||||
/* no mask specified, assume default */
|
||||
os_memset(mask, 0xff, ETH_ALEN);
|
||||
} else if (maskable && *r == '/') {
|
||||
@ -500,7 +500,7 @@ void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len)
|
||||
*txt++ = 't';
|
||||
break;
|
||||
default:
|
||||
if (data[i] >= 32 && data[i] <= 127) {
|
||||
if (data[i] >= 32 && data[i] <= 126) {
|
||||
*txt++ = data[i];
|
||||
} else {
|
||||
txt += os_snprintf(txt, end - txt, "\\x%02x",
|
||||
@ -699,6 +699,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)
|
||||
@ -980,7 +1003,7 @@ int random_mac_addr_keep_oui(u8 *addr)
|
||||
* @delim: a string of delimiters
|
||||
* @last: a pointer to a character following the returned token
|
||||
* It has to be set to NULL for the first call and passed for any
|
||||
* futher call.
|
||||
* further call.
|
||||
* Returns: a pointer to token position in str or NULL
|
||||
*
|
||||
* This function is similar to str_token, but it can be used with both
|
||||
@ -1125,3 +1148,57 @@ int is_ctrl_char(char c)
|
||||
{
|
||||
return c > 0 && c < 32;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ssid_parse - Parse a string that contains SSID in hex or text format
|
||||
* @buf: Input NULL terminated string that contains the SSID
|
||||
* @ssid: Output SSID
|
||||
* Returns: 0 on success, -1 otherwise
|
||||
*
|
||||
* The SSID has to be enclosed in double quotes for the text format or space
|
||||
* or NULL terminated string of hex digits for the hex format. buf can include
|
||||
* additional arguments after the SSID.
|
||||
*/
|
||||
int ssid_parse(const char *buf, struct wpa_ssid_value *ssid)
|
||||
{
|
||||
char *tmp, *res, *end;
|
||||
size_t len;
|
||||
|
||||
ssid->ssid_len = 0;
|
||||
|
||||
tmp = os_strdup(buf);
|
||||
if (!tmp)
|
||||
return -1;
|
||||
|
||||
if (*tmp != '"') {
|
||||
end = os_strchr(tmp, ' ');
|
||||
if (end)
|
||||
*end = '\0';
|
||||
} else {
|
||||
end = os_strchr(tmp + 1, '"');
|
||||
if (!end) {
|
||||
os_free(tmp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
end[1] = '\0';
|
||||
}
|
||||
|
||||
res = wpa_config_parse_string(tmp, &len);
|
||||
if (res && len <= SSID_MAX_LEN) {
|
||||
ssid->ssid_len = len;
|
||||
os_memcpy(ssid->ssid, res, len);
|
||||
}
|
||||
|
||||
os_free(tmp);
|
||||
os_free(res);
|
||||
|
||||
return ssid->ssid_len ? 0 : -1;
|
||||
}
|
||||
|
||||
|
||||
int str_starts(const char *str, const char *start)
|
||||
{
|
||||
return os_strncmp(str, start, os_strlen(start)) == 0;
|
||||
}
|
||||
|
@ -313,6 +313,9 @@ static inline void WPA_PUT_LE64(u8 *a, u64 val)
|
||||
#ifndef ETH_P_ALL
|
||||
#define ETH_P_ALL 0x0003
|
||||
#endif
|
||||
#ifndef ETH_P_IP
|
||||
#define ETH_P_IP 0x0800
|
||||
#endif
|
||||
#ifndef ETH_P_80211_ENCAP
|
||||
#define ETH_P_80211_ENCAP 0x890d /* TDLS comes under this category */
|
||||
#endif
|
||||
@ -416,6 +419,7 @@ void perror(const char *s);
|
||||
*/
|
||||
#ifdef __CHECKER__
|
||||
#define __force __attribute__((force))
|
||||
#undef __bitwise
|
||||
#define __bitwise __attribute__((bitwise))
|
||||
#else
|
||||
#define __force
|
||||
@ -445,6 +449,13 @@ typedef u64 __bitwise le64;
|
||||
#endif /* __GNUC__ */
|
||||
#endif /* __must_check */
|
||||
|
||||
#define SSID_MAX_LEN 32
|
||||
|
||||
struct wpa_ssid_value {
|
||||
u8 ssid[SSID_MAX_LEN];
|
||||
size_t ssid_len;
|
||||
};
|
||||
|
||||
int hwaddr_aton(const char *txt, u8 *addr);
|
||||
int hwaddr_masked_aton(const char *txt, u8 *addr, u8 *mask, u8 maskable);
|
||||
int hwaddr_compact_aton(const char *txt, u8 *addr);
|
||||
@ -461,6 +472,7 @@ int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data,
|
||||
size_t len);
|
||||
|
||||
int hwaddr_mask_txt(char *buf, size_t len, const u8 *addr, const u8 *mask);
|
||||
int ssid_parse(const char *buf, struct wpa_ssid_value *ssid);
|
||||
|
||||
#ifdef CONFIG_NATIVE_WINDOWS
|
||||
void wpa_unicode2ascii_inplace(TCHAR *str);
|
||||
@ -477,6 +489,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);
|
||||
@ -536,6 +550,8 @@ size_t utf8_unescape(const char *inp, size_t in_size,
|
||||
char *outp, size_t out_size);
|
||||
int is_ctrl_char(char c);
|
||||
|
||||
int str_starts(const char *str, const char *start);
|
||||
|
||||
|
||||
/*
|
||||
* gcc 4.4 ends up generating strict-aliasing warnings about some very common
|
||||
|
@ -20,7 +20,12 @@
|
||||
#error Do not define both of poll and epoll
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_ELOOP_POLL) && !defined(CONFIG_ELOOP_EPOLL)
|
||||
#if defined(CONFIG_ELOOP_POLL) && defined(CONFIG_ELOOP_KQUEUE)
|
||||
#error Do not define both of poll and kqueue
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_ELOOP_POLL) && !defined(CONFIG_ELOOP_EPOLL) && \
|
||||
!defined(CONFIG_ELOOP_KQUEUE)
|
||||
#define CONFIG_ELOOP_SELECT
|
||||
#endif
|
||||
|
||||
@ -32,6 +37,10 @@
|
||||
#include <sys/epoll.h>
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
|
||||
#ifdef CONFIG_ELOOP_KQUEUE
|
||||
#include <sys/event.h>
|
||||
#endif /* CONFIG_ELOOP_KQUEUE */
|
||||
|
||||
struct eloop_sock {
|
||||
int sock;
|
||||
void *eloop_data;
|
||||
@ -77,13 +86,20 @@ struct eloop_data {
|
||||
struct pollfd *pollfds;
|
||||
struct pollfd **pollfds_map;
|
||||
#endif /* CONFIG_ELOOP_POLL */
|
||||
#if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE)
|
||||
int max_fd;
|
||||
struct eloop_sock *fd_table;
|
||||
#endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
int epollfd;
|
||||
int epoll_max_event_num;
|
||||
int epoll_max_fd;
|
||||
struct eloop_sock *epoll_table;
|
||||
struct epoll_event *epoll_events;
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
#ifdef CONFIG_ELOOP_KQUEUE
|
||||
int kqueuefd;
|
||||
int kqueue_nevents;
|
||||
struct kevent *kqueue_events;
|
||||
#endif /* CONFIG_ELOOP_KQUEUE */
|
||||
struct eloop_sock_table readers;
|
||||
struct eloop_sock_table writers;
|
||||
struct eloop_sock_table exceptions;
|
||||
@ -151,14 +167,24 @@ int eloop_init(void)
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
eloop.epollfd = epoll_create1(0);
|
||||
if (eloop.epollfd < 0) {
|
||||
wpa_printf(MSG_ERROR, "%s: epoll_create1 failed. %s\n",
|
||||
wpa_printf(MSG_ERROR, "%s: epoll_create1 failed. %s",
|
||||
__func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
#ifdef CONFIG_ELOOP_KQUEUE
|
||||
eloop.kqueuefd = kqueue();
|
||||
if (eloop.kqueuefd < 0) {
|
||||
wpa_printf(MSG_ERROR, "%s: kqueue failed: %s",
|
||||
__func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
#endif /* CONFIG_ELOOP_KQUEUE */
|
||||
#if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE)
|
||||
eloop.readers.type = EVENT_TYPE_READ;
|
||||
eloop.writers.type = EVENT_TYPE_WRITE;
|
||||
eloop.exceptions.type = EVENT_TYPE_EXCEPTION;
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
#endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */
|
||||
#ifdef WPA_TRACE
|
||||
signal(SIGSEGV, eloop_sigsegv_handler);
|
||||
#endif /* WPA_TRACE */
|
||||
@ -166,15 +192,80 @@ int eloop_init(void)
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
static int eloop_sock_queue(int sock, eloop_event_type type)
|
||||
{
|
||||
struct epoll_event ev;
|
||||
|
||||
os_memset(&ev, 0, sizeof(ev));
|
||||
switch (type) {
|
||||
case EVENT_TYPE_READ:
|
||||
ev.events = EPOLLIN;
|
||||
break;
|
||||
case EVENT_TYPE_WRITE:
|
||||
ev.events = EPOLLOUT;
|
||||
break;
|
||||
/*
|
||||
* Exceptions are always checked when using epoll, but I suppose it's
|
||||
* possible that someone registered a socket *only* for exception
|
||||
* handling.
|
||||
*/
|
||||
case EVENT_TYPE_EXCEPTION:
|
||||
ev.events = EPOLLERR | EPOLLHUP;
|
||||
break;
|
||||
}
|
||||
ev.data.fd = sock;
|
||||
if (epoll_ctl(eloop.epollfd, EPOLL_CTL_ADD, sock, &ev) < 0) {
|
||||
wpa_printf(MSG_ERROR, "%s: epoll_ctl(ADD) for fd=%d failed: %s",
|
||||
__func__, sock, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
|
||||
|
||||
#ifdef CONFIG_ELOOP_KQUEUE
|
||||
static int eloop_sock_queue(int sock, eloop_event_type type)
|
||||
{
|
||||
int filter;
|
||||
struct kevent ke;
|
||||
|
||||
switch (type) {
|
||||
case EVENT_TYPE_READ:
|
||||
filter = EVFILT_READ;
|
||||
break;
|
||||
case EVENT_TYPE_WRITE:
|
||||
filter = EVFILT_WRITE;
|
||||
break;
|
||||
default:
|
||||
filter = 0;
|
||||
}
|
||||
EV_SET(&ke, sock, filter, EV_ADD, 0, 0, 0);
|
||||
if (kevent(eloop.kqueuefd, &ke, 1, NULL, 0, NULL) == -1) {
|
||||
wpa_printf(MSG_ERROR, "%s: kevent(ADD) for fd=%d failed: %s",
|
||||
__func__, sock, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_ELOOP_KQUEUE */
|
||||
|
||||
|
||||
static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
|
||||
int sock, eloop_sock_handler handler,
|
||||
void *eloop_data, void *user_data)
|
||||
{
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
struct eloop_sock *temp_table;
|
||||
struct epoll_event ev, *temp_events;
|
||||
int next;
|
||||
struct epoll_event *temp_events;
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
#ifdef CONFIG_ELOOP_KQUEUE
|
||||
struct kevent *temp_events;
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
#if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE)
|
||||
struct eloop_sock *temp_table;
|
||||
int next;
|
||||
#endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */
|
||||
struct eloop_sock *tmp;
|
||||
int new_max_sock;
|
||||
|
||||
@ -210,26 +301,28 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
|
||||
eloop.pollfds = n;
|
||||
}
|
||||
#endif /* CONFIG_ELOOP_POLL */
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
if (new_max_sock >= eloop.epoll_max_fd) {
|
||||
next = eloop.epoll_max_fd == 0 ? 16 : eloop.epoll_max_fd * 2;
|
||||
temp_table = os_realloc_array(eloop.epoll_table, next,
|
||||
#if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE)
|
||||
if (new_max_sock >= eloop.max_fd) {
|
||||
next = eloop.max_fd == 0 ? 16 : eloop.max_fd * 2;
|
||||
temp_table = os_realloc_array(eloop.fd_table, next,
|
||||
sizeof(struct eloop_sock));
|
||||
if (temp_table == NULL)
|
||||
return -1;
|
||||
|
||||
eloop.epoll_max_fd = next;
|
||||
eloop.epoll_table = temp_table;
|
||||
eloop.max_fd = next;
|
||||
eloop.fd_table = temp_table;
|
||||
}
|
||||
#endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */
|
||||
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
if (eloop.count + 1 > eloop.epoll_max_event_num) {
|
||||
next = eloop.epoll_max_event_num == 0 ? 8 :
|
||||
eloop.epoll_max_event_num * 2;
|
||||
temp_events = os_realloc_array(eloop.epoll_events, next,
|
||||
sizeof(struct epoll_event));
|
||||
if (temp_events == NULL) {
|
||||
wpa_printf(MSG_ERROR, "%s: malloc for epoll failed. "
|
||||
"%s\n", __func__, strerror(errno));
|
||||
wpa_printf(MSG_ERROR, "%s: malloc for epoll failed: %s",
|
||||
__func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -237,6 +330,22 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
|
||||
eloop.epoll_events = temp_events;
|
||||
}
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
#ifdef CONFIG_ELOOP_KQUEUE
|
||||
if (eloop.count + 1 > eloop.kqueue_nevents) {
|
||||
next = eloop.kqueue_nevents == 0 ? 8 : eloop.kqueue_nevents * 2;
|
||||
temp_events = os_malloc(next * sizeof(*temp_events));
|
||||
if (!temp_events) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"%s: malloc for kqueue failed: %s",
|
||||
__func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
os_free(eloop.kqueue_events);
|
||||
eloop.kqueue_events = temp_events;
|
||||
eloop.kqueue_nevents = next;
|
||||
}
|
||||
#endif /* CONFIG_ELOOP_KQUEUE */
|
||||
|
||||
eloop_trace_sock_remove_ref(table);
|
||||
tmp = os_realloc_array(table->table, table->count + 1,
|
||||
@ -258,33 +367,12 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
|
||||
table->changed = 1;
|
||||
eloop_trace_sock_add_ref(table);
|
||||
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
os_memset(&ev, 0, sizeof(ev));
|
||||
switch (table->type) {
|
||||
case EVENT_TYPE_READ:
|
||||
ev.events = EPOLLIN;
|
||||
break;
|
||||
case EVENT_TYPE_WRITE:
|
||||
ev.events = EPOLLOUT;
|
||||
break;
|
||||
/*
|
||||
* Exceptions are always checked when using epoll, but I suppose it's
|
||||
* possible that someone registered a socket *only* for exception
|
||||
* handling.
|
||||
*/
|
||||
case EVENT_TYPE_EXCEPTION:
|
||||
ev.events = EPOLLERR | EPOLLHUP;
|
||||
break;
|
||||
}
|
||||
ev.data.fd = sock;
|
||||
if (epoll_ctl(eloop.epollfd, EPOLL_CTL_ADD, sock, &ev) < 0) {
|
||||
wpa_printf(MSG_ERROR, "%s: epoll_ctl(ADD) for fd=%d "
|
||||
"failed. %s\n", __func__, sock, strerror(errno));
|
||||
#if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE)
|
||||
if (eloop_sock_queue(sock, table->type) < 0)
|
||||
return -1;
|
||||
}
|
||||
os_memcpy(&eloop.epoll_table[sock], &table->table[table->count - 1],
|
||||
os_memcpy(&eloop.fd_table[sock], &table->table[table->count - 1],
|
||||
sizeof(struct eloop_sock));
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
#endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -292,6 +380,9 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
|
||||
static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
|
||||
int sock)
|
||||
{
|
||||
#ifdef CONFIG_ELOOP_KQUEUE
|
||||
struct kevent ke;
|
||||
#endif /* CONFIG_ELOOP_KQUEUE */
|
||||
int i;
|
||||
|
||||
if (table == NULL || table->table == NULL || table->count == 0)
|
||||
@ -315,12 +406,21 @@ static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
|
||||
eloop_trace_sock_add_ref(table);
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
if (epoll_ctl(eloop.epollfd, EPOLL_CTL_DEL, sock, NULL) < 0) {
|
||||
wpa_printf(MSG_ERROR, "%s: epoll_ctl(DEL) for fd=%d "
|
||||
"failed. %s\n", __func__, sock, strerror(errno));
|
||||
wpa_printf(MSG_ERROR, "%s: epoll_ctl(DEL) for fd=%d failed: %s",
|
||||
__func__, sock, strerror(errno));
|
||||
return;
|
||||
}
|
||||
os_memset(&eloop.epoll_table[sock], 0, sizeof(struct eloop_sock));
|
||||
os_memset(&eloop.fd_table[sock], 0, sizeof(struct eloop_sock));
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
#ifdef CONFIG_ELOOP_KQUEUE
|
||||
EV_SET(&ke, sock, 0, EV_DELETE, 0, 0, 0);
|
||||
if (kevent(eloop.kqueuefd, &ke, 1, NULL, 0, NULL) < 0) {
|
||||
wpa_printf(MSG_ERROR, "%s: kevent(DEL) for fd=%d failed: %s",
|
||||
__func__, sock, strerror(errno));
|
||||
return;
|
||||
}
|
||||
os_memset(&eloop.fd_table[sock], 0, sizeof(struct eloop_sock));
|
||||
#endif /* CONFIG_ELOOP_KQUEUE */
|
||||
}
|
||||
|
||||
|
||||
@ -513,7 +613,7 @@ static void eloop_sock_table_dispatch(struct epoll_event *events, int nfds)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nfds; i++) {
|
||||
table = &eloop.epoll_table[events[i].data.fd];
|
||||
table = &eloop.fd_table[events[i].data.fd];
|
||||
if (table->handler == NULL)
|
||||
continue;
|
||||
table->handler(table->sock, table->eloop_data,
|
||||
@ -527,6 +627,67 @@ static void eloop_sock_table_dispatch(struct epoll_event *events, int nfds)
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
|
||||
|
||||
#ifdef CONFIG_ELOOP_KQUEUE
|
||||
|
||||
static void eloop_sock_table_dispatch(struct kevent *events, int nfds)
|
||||
{
|
||||
struct eloop_sock *table;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nfds; i++) {
|
||||
table = &eloop.fd_table[events[i].ident];
|
||||
if (table->handler == NULL)
|
||||
continue;
|
||||
table->handler(table->sock, table->eloop_data,
|
||||
table->user_data);
|
||||
if (eloop.readers.changed ||
|
||||
eloop.writers.changed ||
|
||||
eloop.exceptions.changed)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int eloop_sock_table_requeue(struct eloop_sock_table *table)
|
||||
{
|
||||
int i, r;
|
||||
|
||||
r = 0;
|
||||
for (i = 0; i < table->count && table->table; i++) {
|
||||
if (eloop_sock_queue(table->table[i].sock, table->type) == -1)
|
||||
r = -1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ELOOP_KQUEUE */
|
||||
|
||||
|
||||
int eloop_sock_requeue(void)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
#ifdef CONFIG_ELOOP_KQUEUE
|
||||
close(eloop.kqueuefd);
|
||||
eloop.kqueuefd = kqueue();
|
||||
if (eloop.kqueuefd < 0) {
|
||||
wpa_printf(MSG_ERROR, "%s: kqueue failed: %s",
|
||||
__func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (eloop_sock_table_requeue(&eloop.readers) < 0)
|
||||
r = -1;
|
||||
if (eloop_sock_table_requeue(&eloop.writers) < 0)
|
||||
r = -1;
|
||||
if (eloop_sock_table_requeue(&eloop.exceptions) < 0)
|
||||
r = -1;
|
||||
#endif /* CONFIG_ELOOP_KQUEUE */
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
static void eloop_sock_table_destroy(struct eloop_sock_table *table)
|
||||
{
|
||||
if (table) {
|
||||
@ -907,6 +1068,9 @@ void eloop_run(void)
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
int timeout_ms = -1;
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
#ifdef CONFIG_ELOOP_KQUEUE
|
||||
struct timespec ts;
|
||||
#endif /* CONFIG_ELOOP_KQUEUE */
|
||||
int res;
|
||||
struct os_reltime tv, now;
|
||||
|
||||
@ -951,6 +1115,10 @@ void eloop_run(void)
|
||||
_tv.tv_sec = tv.sec;
|
||||
_tv.tv_usec = tv.usec;
|
||||
#endif /* CONFIG_ELOOP_SELECT */
|
||||
#ifdef CONFIG_ELOOP_KQUEUE
|
||||
ts.tv_sec = tv.sec;
|
||||
ts.tv_nsec = tv.usec * 1000L;
|
||||
#endif /* CONFIG_ELOOP_KQUEUE */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ELOOP_POLL
|
||||
@ -976,6 +1144,15 @@ void eloop_run(void)
|
||||
eloop.count, timeout_ms);
|
||||
}
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
#ifdef CONFIG_ELOOP_KQUEUE
|
||||
if (eloop.count == 0) {
|
||||
res = 0;
|
||||
} else {
|
||||
res = kevent(eloop.kqueuefd, NULL, 0,
|
||||
eloop.kqueue_events, eloop.kqueue_nevents,
|
||||
timeout ? &ts : NULL);
|
||||
}
|
||||
#endif /* CONFIG_ELOOP_KQUEUE */
|
||||
if (res < 0 && errno != EINTR && errno != 0) {
|
||||
wpa_printf(MSG_ERROR, "eloop: %s: %s",
|
||||
#ifdef CONFIG_ELOOP_POLL
|
||||
@ -987,6 +1164,10 @@ void eloop_run(void)
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
"epoll"
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
#ifdef CONFIG_ELOOP_KQUEUE
|
||||
"kqueue"
|
||||
#endif /* CONFIG_ELOOP_EKQUEUE */
|
||||
|
||||
, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
@ -997,6 +1178,7 @@ void eloop_run(void)
|
||||
|
||||
eloop_process_pending_signals();
|
||||
|
||||
|
||||
/* check if some registered timeouts have occurred */
|
||||
timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
|
||||
list);
|
||||
@ -1042,6 +1224,9 @@ void eloop_run(void)
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
eloop_sock_table_dispatch(eloop.epoll_events, res);
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
#ifdef CONFIG_ELOOP_KQUEUE
|
||||
eloop_sock_table_dispatch(eloop.kqueue_events, res);
|
||||
#endif /* CONFIG_ELOOP_KQUEUE */
|
||||
}
|
||||
|
||||
eloop.terminate = 0;
|
||||
@ -1094,11 +1279,17 @@ void eloop_destroy(void)
|
||||
os_free(eloop.pollfds);
|
||||
os_free(eloop.pollfds_map);
|
||||
#endif /* CONFIG_ELOOP_POLL */
|
||||
#if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE)
|
||||
os_free(eloop.fd_table);
|
||||
#endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */
|
||||
#ifdef CONFIG_ELOOP_EPOLL
|
||||
os_free(eloop.epoll_table);
|
||||
os_free(eloop.epoll_events);
|
||||
close(eloop.epollfd);
|
||||
#endif /* CONFIG_ELOOP_EPOLL */
|
||||
#ifdef CONFIG_ELOOP_KQUEUE
|
||||
os_free(eloop.kqueue_events);
|
||||
close(eloop.kqueuefd);
|
||||
#endif /* CONFIG_ELOOP_KQUEUE */
|
||||
}
|
||||
|
||||
|
||||
@ -1137,6 +1328,17 @@ void eloop_wait_for_read_sock(int sock)
|
||||
FD_SET(sock, &rfds);
|
||||
select(sock + 1, &rfds, NULL, NULL, NULL);
|
||||
#endif /* defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL) */
|
||||
#ifdef CONFIG_ELOOP_KQUEUE
|
||||
int kfd;
|
||||
struct kevent ke1, ke2;
|
||||
|
||||
kfd = kqueue();
|
||||
if (kfd == -1)
|
||||
return;
|
||||
EV_SET(&ke1, sock, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, 0);
|
||||
kevent(kfd, &ke1, 1, &ke2, 1, NULL);
|
||||
close(kfd);
|
||||
#endif /* CONFIG_ELOOP_KQUEUE */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ELOOP_SELECT
|
||||
|
@ -312,6 +312,14 @@ int eloop_register_signal_terminate(eloop_signal_handler handler,
|
||||
int eloop_register_signal_reconfig(eloop_signal_handler handler,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* eloop_sock_requeue - Requeue sockets
|
||||
*
|
||||
* Requeue sockets after forking because some implementations require this,
|
||||
* such as epoll and kqueue.
|
||||
*/
|
||||
int eloop_sock_requeue(void);
|
||||
|
||||
/**
|
||||
* eloop_run - Start the event loop
|
||||
*
|
||||
|
20
freebsd/contrib/wpa/src/utils/module_tests.h
Normal file
20
freebsd/contrib/wpa/src/utils/module_tests.h
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Module tests
|
||||
* Copyright (c) 2014-2015, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef MODULE_TESTS_H
|
||||
#define MODULE_TESTS_H
|
||||
|
||||
int wpas_module_tests(void);
|
||||
int hapd_module_tests(void);
|
||||
|
||||
int utils_module_tests(void);
|
||||
int wps_module_tests(void);
|
||||
int common_module_tests(void);
|
||||
int crypto_module_tests(void);
|
||||
|
||||
#endif /* MODULE_TESTS_H */
|
@ -657,6 +657,10 @@ int os_exec(const char *program, const char *arg, int wait_completion);
|
||||
#if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS)
|
||||
#define TEST_FAIL() testing_test_fail()
|
||||
int testing_test_fail(void);
|
||||
extern char wpa_trace_fail_func[256];
|
||||
extern unsigned int wpa_trace_fail_after;
|
||||
extern char wpa_trace_test_fail_func[256];
|
||||
extern unsigned int wpa_trace_test_fail_after;
|
||||
#else
|
||||
#define TEST_FAIL() 0
|
||||
#endif
|
||||
|
@ -411,6 +411,7 @@ void os_program_deinit(void)
|
||||
if (total)
|
||||
wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
|
||||
(unsigned long) total);
|
||||
wpa_trace_deinit();
|
||||
#endif /* WPA_TRACE */
|
||||
}
|
||||
|
||||
@ -473,11 +474,7 @@ char * os_readfile(const char *name, size_t *len)
|
||||
|
||||
int os_file_exists(const char *fname)
|
||||
{
|
||||
FILE *f = fopen(fname, "rb");
|
||||
if (f == NULL)
|
||||
return 0;
|
||||
fclose(f);
|
||||
return 1;
|
||||
return access(fname, F_OK) == 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
\
|
||||
__ptr->__val; \
|
||||
})
|
||||
#define get_unaligned_le16(p) le16_to_cpu(get_unaligned((uint16_t *)(p)))
|
||||
#define get_unaligned_le32(p) le32_to_cpu(get_unaligned((uint32_t *)(p)))
|
||||
#define get_unaligned_le16(p) le16_to_cpu(get_unaligned((le16 *)(p)))
|
||||
#define get_unaligned_le32(p) le32_to_cpu(get_unaligned((le32 *)(p)))
|
||||
|
||||
#endif /* PLATFORM_H */
|
||||
|
@ -66,4 +66,6 @@ void wpa_trace_dump_funcname(const char *title, void *pc);
|
||||
|
||||
#endif /* WPA_TRACE_BFD */
|
||||
|
||||
void wpa_trace_deinit(void);
|
||||
|
||||
#endif /* TRACE_H */
|
||||
|
@ -150,7 +150,7 @@ int wpa_debug_open_linux_tracing(void)
|
||||
strtok_r(line, " ", &tmp2);
|
||||
tmp_path = strtok_r(NULL, " ", &tmp2);
|
||||
fstype = strtok_r(NULL, " ", &tmp2);
|
||||
if (strcmp(fstype, "debugfs") == 0) {
|
||||
if (fstype && strcmp(fstype, "debugfs") == 0) {
|
||||
path = tmp_path;
|
||||
break;
|
||||
}
|
||||
@ -519,16 +519,18 @@ int wpa_debug_reopen_file(void)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_FILE
|
||||
int rv;
|
||||
if (last_path) {
|
||||
char *tmp = os_strdup(last_path);
|
||||
wpa_debug_close_file();
|
||||
rv = wpa_debug_open_file(tmp);
|
||||
os_free(tmp);
|
||||
} else {
|
||||
wpa_printf(MSG_ERROR, "Last-path was not set, cannot "
|
||||
"re-open log file.");
|
||||
rv = -1;
|
||||
}
|
||||
char *tmp;
|
||||
|
||||
if (!last_path)
|
||||
return 0; /* logfile not used */
|
||||
|
||||
tmp = os_strdup(last_path);
|
||||
if (!tmp)
|
||||
return -1;
|
||||
|
||||
wpa_debug_close_file();
|
||||
rv = wpa_debug_open_file(tmp);
|
||||
os_free(tmp);
|
||||
return rv;
|
||||
#else /* CONFIG_DEBUG_FILE */
|
||||
return 0;
|
||||
|
@ -312,3 +312,33 @@ void wpabuf_printf(struct wpabuf *buf, char *fmt, ...)
|
||||
wpabuf_overflow(buf, res);
|
||||
buf->used += res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpabuf_parse_bin - Parse a null terminated string of binary data to a wpabuf
|
||||
* @buf: Buffer with null terminated string (hexdump) of binary data
|
||||
* Returns: wpabuf or %NULL on failure
|
||||
*
|
||||
* The string len must be a multiple of two and contain only hexadecimal digits.
|
||||
*/
|
||||
struct wpabuf * wpabuf_parse_bin(const char *buf)
|
||||
{
|
||||
size_t len;
|
||||
struct wpabuf *ret;
|
||||
|
||||
len = os_strlen(buf);
|
||||
if (len & 0x01)
|
||||
return NULL;
|
||||
len /= 2;
|
||||
|
||||
ret = wpabuf_alloc(len);
|
||||
if (ret == NULL)
|
||||
return NULL;
|
||||
|
||||
if (hexstr2bin(buf, wpabuf_put(ret, len), len)) {
|
||||
wpabuf_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ void * wpabuf_put(struct wpabuf *buf, size_t len);
|
||||
struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b);
|
||||
struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len);
|
||||
void wpabuf_printf(struct wpabuf *buf, char *fmt, ...) PRINTF_FORMAT(2, 3);
|
||||
struct wpabuf * wpabuf_parse_bin(const char *buf);
|
||||
|
||||
|
||||
/**
|
||||
@ -81,7 +82,7 @@ static inline const void * wpabuf_head(const struct wpabuf *buf)
|
||||
|
||||
static inline const u8 * wpabuf_head_u8(const struct wpabuf *buf)
|
||||
{
|
||||
return wpabuf_head(buf);
|
||||
return (const u8 *) wpabuf_head(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -96,42 +97,42 @@ static inline void * wpabuf_mhead(struct wpabuf *buf)
|
||||
|
||||
static inline u8 * wpabuf_mhead_u8(struct wpabuf *buf)
|
||||
{
|
||||
return wpabuf_mhead(buf);
|
||||
return (u8 *) wpabuf_mhead(buf);
|
||||
}
|
||||
|
||||
static inline void wpabuf_put_u8(struct wpabuf *buf, u8 data)
|
||||
{
|
||||
u8 *pos = wpabuf_put(buf, 1);
|
||||
u8 *pos = (u8 *) wpabuf_put(buf, 1);
|
||||
*pos = data;
|
||||
}
|
||||
|
||||
static inline void wpabuf_put_le16(struct wpabuf *buf, u16 data)
|
||||
{
|
||||
u8 *pos = wpabuf_put(buf, 2);
|
||||
u8 *pos = (u8 *) wpabuf_put(buf, 2);
|
||||
WPA_PUT_LE16(pos, data);
|
||||
}
|
||||
|
||||
static inline void wpabuf_put_le32(struct wpabuf *buf, u32 data)
|
||||
{
|
||||
u8 *pos = wpabuf_put(buf, 4);
|
||||
u8 *pos = (u8 *) wpabuf_put(buf, 4);
|
||||
WPA_PUT_LE32(pos, data);
|
||||
}
|
||||
|
||||
static inline void wpabuf_put_be16(struct wpabuf *buf, u16 data)
|
||||
{
|
||||
u8 *pos = wpabuf_put(buf, 2);
|
||||
u8 *pos = (u8 *) wpabuf_put(buf, 2);
|
||||
WPA_PUT_BE16(pos, data);
|
||||
}
|
||||
|
||||
static inline void wpabuf_put_be24(struct wpabuf *buf, u32 data)
|
||||
{
|
||||
u8 *pos = wpabuf_put(buf, 3);
|
||||
u8 *pos = (u8 *) wpabuf_put(buf, 3);
|
||||
WPA_PUT_BE24(pos, data);
|
||||
}
|
||||
|
||||
static inline void wpabuf_put_be32(struct wpabuf *buf, u32 data)
|
||||
{
|
||||
u8 *pos = wpabuf_put(buf, 4);
|
||||
u8 *pos = (u8 *) wpabuf_put(buf, 4);
|
||||
WPA_PUT_BE32(pos, data);
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,10 @@
|
||||
int wps_version_number = 0x20;
|
||||
int wps_testing_dummy_cred = 0;
|
||||
int wps_corrupt_pkhash = 0;
|
||||
int wps_force_auth_types_in_use = 0;
|
||||
u16 wps_force_auth_types = 0;
|
||||
int wps_force_encr_types_in_use = 0;
|
||||
u16 wps_force_encr_types = 0;
|
||||
#endif /* CONFIG_WPS_TESTING */
|
||||
|
||||
|
||||
@ -172,7 +176,7 @@ void wps_deinit(struct wps_data *data)
|
||||
} else if (data->registrar)
|
||||
wps_registrar_unlock_pin(data->wps->registrar, data->uuid_e);
|
||||
|
||||
wpabuf_free(data->dh_privkey);
|
||||
wpabuf_clear_free(data->dh_privkey);
|
||||
wpabuf_free(data->dh_pubkey_e);
|
||||
wpabuf_free(data->dh_pubkey_r);
|
||||
wpabuf_free(data->last_msg);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Wi-Fi Protected Setup
|
||||
* Copyright (c) 2007-2013, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2007-2016, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
@ -663,6 +663,16 @@ struct wps_context {
|
||||
*/
|
||||
u16 encr_types;
|
||||
|
||||
/**
|
||||
* encr_types_rsn - Enabled encryption types for RSN (WPS_ENCR_*)
|
||||
*/
|
||||
u16 encr_types_rsn;
|
||||
|
||||
/**
|
||||
* encr_types_wpa - Enabled encryption types for WPA (WPS_ENCR_*)
|
||||
*/
|
||||
u16 encr_types_wpa;
|
||||
|
||||
/**
|
||||
* auth_types - Authentication types (bit field of WPS_AUTH_*)
|
||||
*/
|
||||
@ -827,7 +837,7 @@ int wps_build_credential_wrap(struct wpabuf *msg,
|
||||
|
||||
unsigned int wps_pin_checksum(unsigned int pin);
|
||||
unsigned int wps_pin_valid(unsigned int pin);
|
||||
unsigned int wps_generate_pin(void);
|
||||
int wps_generate_pin(unsigned int *pin);
|
||||
int wps_pin_str_valid(const char *pin);
|
||||
void wps_free_pending_msgs(struct upnp_pending_message *msgs);
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
/*
|
||||
* Wi-Fi Protected Setup - attribute building
|
||||
* Copyright (c) 2008, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2008-2016, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
@ -22,10 +22,10 @@
|
||||
|
||||
int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg)
|
||||
{
|
||||
struct wpabuf *pubkey;
|
||||
struct wpabuf *pubkey = NULL;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WPS: * Public Key");
|
||||
wpabuf_free(wps->dh_privkey);
|
||||
wpabuf_clear_free(wps->dh_privkey);
|
||||
wps->dh_privkey = NULL;
|
||||
if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey &&
|
||||
wps->wps->dh_ctx) {
|
||||
@ -300,7 +300,16 @@ int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg)
|
||||
auth_types &= ~WPS_AUTH_WPA;
|
||||
auth_types &= ~WPS_AUTH_WPA2;
|
||||
auth_types &= ~WPS_AUTH_SHARED;
|
||||
wpa_printf(MSG_DEBUG, "WPS: * Authentication Type Flags");
|
||||
#ifdef CONFIG_WPS_TESTING
|
||||
if (wps_force_auth_types_in_use) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"WPS: Testing - replace auth type 0x%x with 0x%x",
|
||||
auth_types, wps_force_auth_types);
|
||||
auth_types = wps_force_auth_types;
|
||||
}
|
||||
#endif /* CONFIG_WPS_TESTING */
|
||||
wpa_printf(MSG_DEBUG, "WPS: * Authentication Type Flags (0x%x)",
|
||||
auth_types);
|
||||
wpabuf_put_be16(msg, ATTR_AUTH_TYPE_FLAGS);
|
||||
wpabuf_put_be16(msg, 2);
|
||||
wpabuf_put_be16(msg, auth_types);
|
||||
@ -312,7 +321,16 @@ int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg)
|
||||
{
|
||||
u16 encr_types = WPS_ENCR_TYPES;
|
||||
encr_types &= ~WPS_ENCR_WEP;
|
||||
wpa_printf(MSG_DEBUG, "WPS: * Encryption Type Flags");
|
||||
#ifdef CONFIG_WPS_TESTING
|
||||
if (wps_force_encr_types_in_use) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"WPS: Testing - replace encr type 0x%x with 0x%x",
|
||||
encr_types, wps_force_encr_types);
|
||||
encr_types = wps_force_encr_types;
|
||||
}
|
||||
#endif /* CONFIG_WPS_TESTING */
|
||||
wpa_printf(MSG_DEBUG, "WPS: * Encryption Type Flags (0x%x)",
|
||||
encr_types);
|
||||
wpabuf_put_be16(msg, ATTR_ENCR_TYPE_FLAGS);
|
||||
wpabuf_put_be16(msg, 2);
|
||||
wpabuf_put_be16(msg, encr_types);
|
||||
@ -397,7 +415,8 @@ int wps_build_oob_dev_pw(struct wpabuf *msg, u16 dev_pw_id,
|
||||
dev_pw_id);
|
||||
addr[0] = wpabuf_head(pubkey);
|
||||
hash_len = wpabuf_len(pubkey);
|
||||
sha256_vector(1, addr, &hash_len, pubkey_hash);
|
||||
if (sha256_vector(1, addr, &hash_len, pubkey_hash) < 0)
|
||||
return -1;
|
||||
#ifdef CONFIG_WPS_TESTING
|
||||
if (wps_corrupt_pkhash) {
|
||||
wpa_hexdump(MSG_DEBUG, "WPS: Real Public Key Hash",
|
||||
|
@ -85,10 +85,10 @@ static int wps_parse_vendor_ext_wfa(struct wps_parse_attr *attr, const u8 *pos,
|
||||
const u8 *end = pos + len;
|
||||
u8 id, elen;
|
||||
|
||||
while (pos + 2 <= end) {
|
||||
while (end - pos >= 2) {
|
||||
id = *pos++;
|
||||
elen = *pos++;
|
||||
if (pos + elen > end)
|
||||
if (elen > end - pos)
|
||||
break;
|
||||
if (wps_set_vendor_ext_wfa_subelem(attr, id, elen, pos) < 0)
|
||||
return -1;
|
||||
|
@ -231,6 +231,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;
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ int wps_derive_keys(struct wps_data *wps)
|
||||
}
|
||||
|
||||
/* Own DH private key is not needed anymore */
|
||||
wpabuf_free(wps->dh_privkey);
|
||||
wpabuf_clear_free(wps->dh_privkey);
|
||||
wps->dh_privkey = NULL;
|
||||
|
||||
wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH shared key", dh_shared);
|
||||
@ -102,7 +102,7 @@ int wps_derive_keys(struct wps_data *wps)
|
||||
len[0] = wpabuf_len(dh_shared);
|
||||
sha256_vector(1, addr, len, dhkey);
|
||||
wpa_hexdump_key(MSG_DEBUG, "WPS: DHKey", dhkey, sizeof(dhkey));
|
||||
wpabuf_free(dh_shared);
|
||||
wpabuf_clear_free(dh_shared);
|
||||
|
||||
/* KDK = HMAC-SHA-256_DHKey(N1 || EnrolleeMAC || N2) */
|
||||
addr[0] = wps->nonce_e;
|
||||
@ -131,23 +131,26 @@ int wps_derive_keys(struct wps_data *wps)
|
||||
}
|
||||
|
||||
|
||||
void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd,
|
||||
size_t dev_passwd_len)
|
||||
int wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd,
|
||||
size_t dev_passwd_len)
|
||||
{
|
||||
u8 hash[SHA256_MAC_LEN];
|
||||
|
||||
hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd,
|
||||
(dev_passwd_len + 1) / 2, hash);
|
||||
if (hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd,
|
||||
(dev_passwd_len + 1) / 2, hash) < 0)
|
||||
return -1;
|
||||
os_memcpy(wps->psk1, hash, WPS_PSK_LEN);
|
||||
hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN,
|
||||
dev_passwd + (dev_passwd_len + 1) / 2,
|
||||
dev_passwd_len / 2, hash);
|
||||
if (hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN,
|
||||
dev_passwd + (dev_passwd_len + 1) / 2,
|
||||
dev_passwd_len / 2, hash) < 0)
|
||||
return -1;
|
||||
os_memcpy(wps->psk2, hash, WPS_PSK_LEN);
|
||||
|
||||
wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Device Password",
|
||||
dev_passwd, dev_passwd_len);
|
||||
wpa_hexdump_key(MSG_DEBUG, "WPS: PSK1", wps->psk1, WPS_PSK_LEN);
|
||||
wpa_hexdump_key(MSG_DEBUG, "WPS: PSK2", wps->psk2, WPS_PSK_LEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -175,7 +178,7 @@ struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr,
|
||||
wpabuf_put_data(decrypted, encr + block_size, encr_len - block_size);
|
||||
if (aes_128_cbc_decrypt(wps->keywrapkey, encr, wpabuf_mhead(decrypted),
|
||||
wpabuf_len(decrypted))) {
|
||||
wpabuf_free(decrypted);
|
||||
wpabuf_clear_free(decrypted);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -186,14 +189,14 @@ struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr,
|
||||
pad = *pos;
|
||||
if (pad > wpabuf_len(decrypted)) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad value");
|
||||
wpabuf_free(decrypted);
|
||||
wpabuf_clear_free(decrypted);
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < pad; i++) {
|
||||
if (*pos-- != pad) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad "
|
||||
"string");
|
||||
wpabuf_free(decrypted);
|
||||
wpabuf_clear_free(decrypted);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@ -237,20 +240,18 @@ unsigned int wps_pin_valid(unsigned int pin)
|
||||
* wps_generate_pin - Generate a random PIN
|
||||
* Returns: Eight digit PIN (i.e., including the checksum digit)
|
||||
*/
|
||||
unsigned int wps_generate_pin(void)
|
||||
int wps_generate_pin(unsigned int *pin)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
/* Generate seven random digits for the PIN */
|
||||
if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0) {
|
||||
struct os_time now;
|
||||
os_get_time(&now);
|
||||
val = os_random() ^ now.sec ^ now.usec;
|
||||
}
|
||||
if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0)
|
||||
return -1;
|
||||
val %= 10000000;
|
||||
|
||||
/* Append checksum digit */
|
||||
return val * 10 + wps_pin_checksum(val);
|
||||
*pin = val * 10 + wps_pin_checksum(val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -377,7 +378,7 @@ struct wpabuf * wps_get_oob_cred(struct wps_context *wps, int rf_band,
|
||||
wps_build_mac_addr(plain, wps->dev.mac_addr) ||
|
||||
wps_build_wfa_ext(plain, 0, NULL, 0)) {
|
||||
os_free(data.new_psk);
|
||||
wpabuf_free(plain);
|
||||
wpabuf_clear_free(plain);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -425,7 +426,7 @@ struct wpabuf * wps_build_nfc_pw_token(u16 dev_pw_id,
|
||||
wps_build_wfa_ext(data, 0, NULL, 0)) {
|
||||
wpa_printf(MSG_ERROR, "WPS: Failed to build NFC password "
|
||||
"token");
|
||||
wpabuf_free(data);
|
||||
wpabuf_clear_free(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -662,7 +663,7 @@ int wps_nfc_gen_dh(struct wpabuf **pubkey, struct wpabuf **privkey)
|
||||
|
||||
wpabuf_free(*pubkey);
|
||||
*pubkey = pub;
|
||||
wpabuf_free(*privkey);
|
||||
wpabuf_clear_free(*privkey);
|
||||
*privkey = priv;
|
||||
|
||||
return 0;
|
||||
@ -693,7 +694,7 @@ struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey,
|
||||
}
|
||||
|
||||
*id = 0x10 + val % 0xfff0;
|
||||
wpabuf_free(*dev_pw);
|
||||
wpabuf_clear_free(*dev_pw);
|
||||
*dev_pw = pw;
|
||||
|
||||
return wps_nfc_token_build(ndef, *id, *pubkey, *dev_pw);
|
||||
|
@ -14,6 +14,10 @@
|
||||
extern int wps_version_number;
|
||||
extern int wps_testing_dummy_cred;
|
||||
extern int wps_corrupt_pkhash;
|
||||
extern int wps_force_auth_types_in_use;
|
||||
extern u16 wps_force_auth_types;
|
||||
extern int wps_force_encr_types_in_use;
|
||||
extern u16 wps_force_encr_types;
|
||||
#define WPS_VERSION wps_version_number
|
||||
|
||||
#else /* CONFIG_WPS_TESTING */
|
||||
|
@ -175,7 +175,8 @@ static struct wpabuf * wps_build_m3(struct wps_data *wps)
|
||||
wpa_printf(MSG_DEBUG, "WPS: No Device Password available");
|
||||
return NULL;
|
||||
}
|
||||
wps_derive_psk(wps, wps->dev_password, wps->dev_password_len);
|
||||
if (wps_derive_psk(wps, wps->dev_password, wps->dev_password_len) < 0)
|
||||
return NULL;
|
||||
|
||||
if (wps->wps->ap && random_pool_ready() != 1) {
|
||||
wpa_printf(MSG_INFO,
|
||||
@ -226,11 +227,11 @@ static struct wpabuf * wps_build_m5(struct wps_data *wps)
|
||||
wps_build_encr_settings(wps, msg, plain) ||
|
||||
wps_build_wfa_ext(msg, 0, NULL, 0) ||
|
||||
wps_build_authenticator(wps, msg)) {
|
||||
wpabuf_free(plain);
|
||||
wpabuf_clear_free(plain);
|
||||
wpabuf_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
wpabuf_free(plain);
|
||||
wpabuf_clear_free(plain);
|
||||
|
||||
wps->state = RECV_M6;
|
||||
return msg;
|
||||
@ -396,11 +397,11 @@ static struct wpabuf * wps_build_m7(struct wps_data *wps)
|
||||
wps_build_encr_settings(wps, msg, plain) ||
|
||||
wps_build_wfa_ext(msg, 0, NULL, 0) ||
|
||||
wps_build_authenticator(wps, msg)) {
|
||||
wpabuf_free(plain);
|
||||
wpabuf_clear_free(plain);
|
||||
wpabuf_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
wpabuf_free(plain);
|
||||
wpabuf_clear_free(plain);
|
||||
|
||||
if (wps->wps->ap && wps->wps->registrar) {
|
||||
/*
|
||||
@ -1009,11 +1010,11 @@ static enum wps_process_res wps_process_m2(struct wps_data *wps,
|
||||
eattr.key_wrap_auth) ||
|
||||
wps_process_creds(wps, eattr.cred, eattr.cred_len,
|
||||
eattr.num_cred, attr->version2 != NULL)) {
|
||||
wpabuf_free(decrypted);
|
||||
wpabuf_clear_free(decrypted);
|
||||
wps->state = SEND_WSC_NACK;
|
||||
return WPS_CONTINUE;
|
||||
}
|
||||
wpabuf_free(decrypted);
|
||||
wpabuf_clear_free(decrypted);
|
||||
|
||||
wps->state = WPS_MSG_DONE;
|
||||
return WPS_CONTINUE;
|
||||
@ -1114,7 +1115,7 @@ static enum wps_process_res wps_process_m4(struct wps_data *wps,
|
||||
}
|
||||
|
||||
if (wps_validate_m4_encr(decrypted, attr->version2 != NULL) < 0) {
|
||||
wpabuf_free(decrypted);
|
||||
wpabuf_clear_free(decrypted);
|
||||
wps->state = SEND_WSC_NACK;
|
||||
return WPS_CONTINUE;
|
||||
}
|
||||
@ -1124,11 +1125,11 @@ static enum wps_process_res wps_process_m4(struct wps_data *wps,
|
||||
if (wps_parse_msg(decrypted, &eattr) < 0 ||
|
||||
wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
|
||||
wps_process_r_snonce1(wps, eattr.r_snonce1)) {
|
||||
wpabuf_free(decrypted);
|
||||
wpabuf_clear_free(decrypted);
|
||||
wps->state = SEND_WSC_NACK;
|
||||
return WPS_CONTINUE;
|
||||
}
|
||||
wpabuf_free(decrypted);
|
||||
wpabuf_clear_free(decrypted);
|
||||
|
||||
wps->state = SEND_M5;
|
||||
return WPS_CONTINUE;
|
||||
@ -1167,7 +1168,7 @@ static enum wps_process_res wps_process_m6(struct wps_data *wps,
|
||||
}
|
||||
|
||||
if (wps_validate_m6_encr(decrypted, attr->version2 != NULL) < 0) {
|
||||
wpabuf_free(decrypted);
|
||||
wpabuf_clear_free(decrypted);
|
||||
wps->state = SEND_WSC_NACK;
|
||||
return WPS_CONTINUE;
|
||||
}
|
||||
@ -1177,11 +1178,11 @@ static enum wps_process_res wps_process_m6(struct wps_data *wps,
|
||||
if (wps_parse_msg(decrypted, &eattr) < 0 ||
|
||||
wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
|
||||
wps_process_r_snonce2(wps, eattr.r_snonce2)) {
|
||||
wpabuf_free(decrypted);
|
||||
wpabuf_clear_free(decrypted);
|
||||
wps->state = SEND_WSC_NACK;
|
||||
return WPS_CONTINUE;
|
||||
}
|
||||
wpabuf_free(decrypted);
|
||||
wpabuf_clear_free(decrypted);
|
||||
|
||||
if (wps->wps->ap)
|
||||
wps->wps->event_cb(wps->wps->cb_ctx, WPS_EV_AP_PIN_SUCCESS,
|
||||
@ -1238,7 +1239,7 @@ static enum wps_process_res wps_process_m8(struct wps_data *wps,
|
||||
|
||||
if (wps_validate_m8_encr(decrypted, wps->wps->ap,
|
||||
attr->version2 != NULL) < 0) {
|
||||
wpabuf_free(decrypted);
|
||||
wpabuf_clear_free(decrypted);
|
||||
wps->state = SEND_WSC_NACK;
|
||||
return WPS_CONTINUE;
|
||||
}
|
||||
@ -1251,11 +1252,11 @@ static enum wps_process_res wps_process_m8(struct wps_data *wps,
|
||||
eattr.num_cred, attr->version2 != NULL) ||
|
||||
wps_process_ap_settings_e(wps, &eattr, decrypted,
|
||||
attr->version2 != NULL)) {
|
||||
wpabuf_free(decrypted);
|
||||
wpabuf_clear_free(decrypted);
|
||||
wps->state = SEND_WSC_NACK;
|
||||
return WPS_CONTINUE;
|
||||
}
|
||||
wpabuf_free(decrypted);
|
||||
wpabuf_clear_free(decrypted);
|
||||
|
||||
wps->state = WPS_MSG_DONE;
|
||||
return WPS_CONTINUE;
|
||||
|
@ -132,8 +132,8 @@ struct wps_data {
|
||||
void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len,
|
||||
const char *label, u8 *res, size_t res_len);
|
||||
int wps_derive_keys(struct wps_data *wps);
|
||||
void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd,
|
||||
size_t dev_passwd_len);
|
||||
int wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd,
|
||||
size_t dev_passwd_len);
|
||||
struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr,
|
||||
size_t encr_len);
|
||||
void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg,
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
/*
|
||||
* Wi-Fi Protected Setup - Registrar
|
||||
* Copyright (c) 2008-2013, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2008-2016, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
@ -705,7 +705,7 @@ void wps_registrar_deinit(struct wps_registrar *reg)
|
||||
eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL);
|
||||
eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
|
||||
wps_registrar_flush(reg);
|
||||
wpabuf_free(reg->extra_cred);
|
||||
wpabuf_clear_free(reg->extra_cred);
|
||||
os_free(reg);
|
||||
}
|
||||
|
||||
@ -1579,13 +1579,13 @@ int wps_build_credential_wrap(struct wpabuf *msg,
|
||||
if (wbuf == NULL)
|
||||
return -1;
|
||||
if (wps_build_credential(wbuf, cred)) {
|
||||
wpabuf_free(wbuf);
|
||||
wpabuf_clear_free(wbuf);
|
||||
return -1;
|
||||
}
|
||||
wpabuf_put_be16(msg, ATTR_CRED);
|
||||
wpabuf_put_be16(msg, wpabuf_len(wbuf));
|
||||
wpabuf_put_buf(msg, wbuf);
|
||||
wpabuf_free(wbuf);
|
||||
wpabuf_clear_free(wbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1608,6 +1608,9 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
|
||||
wps->cred.ssid_len = wps->wps->ssid_len;
|
||||
|
||||
/* Select the best authentication and encryption type */
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"WPS: Own auth types 0x%x - masked Enrollee auth types 0x%x",
|
||||
wps->wps->auth_types, wps->auth_type);
|
||||
if (wps->auth_type & WPS_AUTH_WPA2PSK)
|
||||
wps->auth_type = WPS_AUTH_WPA2PSK;
|
||||
else if (wps->auth_type & WPS_AUTH_WPAPSK)
|
||||
@ -1621,6 +1624,14 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
|
||||
}
|
||||
wps->cred.auth_type = wps->auth_type;
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"WPS: Own encr types 0x%x (rsn: 0x%x, wpa: 0x%x) - masked Enrollee encr types 0x%x",
|
||||
wps->wps->encr_types, wps->wps->encr_types_rsn,
|
||||
wps->wps->encr_types_wpa, wps->encr_type);
|
||||
if (wps->wps->ap && wps->auth_type == WPS_AUTH_WPA2PSK)
|
||||
wps->encr_type &= wps->wps->encr_types_rsn;
|
||||
else if (wps->wps->ap && wps->auth_type == WPS_AUTH_WPAPSK)
|
||||
wps->encr_type &= wps->wps->encr_types_wpa;
|
||||
if (wps->auth_type == WPS_AUTH_WPA2PSK ||
|
||||
wps->auth_type == WPS_AUTH_WPAPSK) {
|
||||
if (wps->encr_type & WPS_ENCR_AES)
|
||||
@ -1742,14 +1753,14 @@ use_provided:
|
||||
return -1;
|
||||
|
||||
if (wps_build_credential(cred, &wps->cred)) {
|
||||
wpabuf_free(cred);
|
||||
wpabuf_clear_free(cred);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpabuf_put_be16(msg, ATTR_CRED);
|
||||
wpabuf_put_be16(msg, wpabuf_len(cred));
|
||||
wpabuf_put_buf(msg, cred);
|
||||
wpabuf_free(cred);
|
||||
wpabuf_clear_free(cred);
|
||||
|
||||
skip_cred_build:
|
||||
if (wps->wps->registrar->extra_cred) {
|
||||
@ -1787,7 +1798,7 @@ static struct wpabuf * wps_build_ap_cred(struct wps_data *wps)
|
||||
}
|
||||
|
||||
if (wps_build_ap_settings(wps, plain)) {
|
||||
wpabuf_free(plain);
|
||||
wpabuf_clear_free(plain);
|
||||
wpabuf_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
@ -1795,7 +1806,7 @@ static struct wpabuf * wps_build_ap_cred(struct wps_data *wps)
|
||||
wpabuf_put_be16(msg, ATTR_CRED);
|
||||
wpabuf_put_be16(msg, wpabuf_len(plain));
|
||||
wpabuf_put_buf(msg, plain);
|
||||
wpabuf_free(plain);
|
||||
wpabuf_clear_free(plain);
|
||||
|
||||
return msg;
|
||||
}
|
||||
@ -1855,10 +1866,10 @@ static struct wpabuf * wps_build_m2(struct wps_data *wps)
|
||||
wps_build_key_wrap_auth(wps, plain) ||
|
||||
wps_build_encr_settings(wps, msg, plain)) {
|
||||
wpabuf_free(msg);
|
||||
wpabuf_free(plain);
|
||||
wpabuf_clear_free(plain);
|
||||
return NULL;
|
||||
}
|
||||
wpabuf_free(plain);
|
||||
wpabuf_clear_free(plain);
|
||||
config_in_m2 = 1;
|
||||
}
|
||||
#endif /* CONFIG_WPS_NFC */
|
||||
@ -1919,7 +1930,8 @@ static struct wpabuf * wps_build_m4(struct wps_data *wps)
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WPS: Building Message M4");
|
||||
|
||||
wps_derive_psk(wps, wps->dev_password, wps->dev_password_len);
|
||||
if (wps_derive_psk(wps, wps->dev_password, wps->dev_password_len) < 0)
|
||||
return NULL;
|
||||
|
||||
plain = wpabuf_alloc(200);
|
||||
if (plain == NULL)
|
||||
@ -1940,11 +1952,11 @@ static struct wpabuf * wps_build_m4(struct wps_data *wps)
|
||||
wps_build_encr_settings(wps, msg, plain) ||
|
||||
wps_build_wfa_ext(msg, 0, NULL, 0) ||
|
||||
wps_build_authenticator(wps, msg)) {
|
||||
wpabuf_free(plain);
|
||||
wpabuf_clear_free(plain);
|
||||
wpabuf_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
wpabuf_free(plain);
|
||||
wpabuf_clear_free(plain);
|
||||
|
||||
wps->state = RECV_M5;
|
||||
return msg;
|
||||
@ -1975,11 +1987,11 @@ static struct wpabuf * wps_build_m6(struct wps_data *wps)
|
||||
wps_build_encr_settings(wps, msg, plain) ||
|
||||
wps_build_wfa_ext(msg, 0, NULL, 0) ||
|
||||
wps_build_authenticator(wps, msg)) {
|
||||
wpabuf_free(plain);
|
||||
wpabuf_clear_free(plain);
|
||||
wpabuf_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
wpabuf_free(plain);
|
||||
wpabuf_clear_free(plain);
|
||||
|
||||
wps->wps_pin_revealed = 1;
|
||||
wps->state = RECV_M7;
|
||||
@ -2012,11 +2024,11 @@ static struct wpabuf * wps_build_m8(struct wps_data *wps)
|
||||
wps_build_encr_settings(wps, msg, plain) ||
|
||||
wps_build_wfa_ext(msg, 0, NULL, 0) ||
|
||||
wps_build_authenticator(wps, msg)) {
|
||||
wpabuf_free(plain);
|
||||
wpabuf_free(msg);
|
||||
wpabuf_clear_free(plain);
|
||||
wpabuf_clear_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
wpabuf_free(plain);
|
||||
wpabuf_clear_free(plain);
|
||||
|
||||
wps->state = RECV_DONE;
|
||||
return msg;
|
||||
@ -2345,6 +2357,23 @@ static int wps_process_auth_type_flags(struct wps_data *wps, const u8 *auth)
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WPS: Enrollee Authentication Type flags 0x%x",
|
||||
auth_types);
|
||||
#ifdef WPS_WORKAROUNDS
|
||||
/*
|
||||
* Some deployed implementations seem to advertise incorrect information
|
||||
* in this attribute. A value of 0x1b (WPA2 + WPA + WPAPSK + OPEN, but
|
||||
* no WPA2PSK) has been reported to be used. Add WPA2PSK to the list to
|
||||
* avoid issues with building Credentials that do not use the strongest
|
||||
* actually supported authentication option (that device does support
|
||||
* WPA2PSK even when it does not claim it here).
|
||||
*/
|
||||
if ((auth_types &
|
||||
(WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK)) ==
|
||||
(WPS_AUTH_WPA2 | WPS_AUTH_WPAPSK)) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"WPS: Workaround - assume Enrollee supports WPA2PSK based on claimed WPA2 support");
|
||||
auth_types |= WPS_AUTH_WPA2PSK;
|
||||
}
|
||||
#endif /* WPS_WORKAROUNDS */
|
||||
wps->auth_type = wps->wps->auth_types & auth_types;
|
||||
if (wps->auth_type == 0) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: No match in supported "
|
||||
@ -2759,7 +2788,7 @@ static enum wps_process_res wps_process_m5(struct wps_data *wps,
|
||||
}
|
||||
|
||||
if (wps_validate_m5_encr(decrypted, attr->version2 != NULL) < 0) {
|
||||
wpabuf_free(decrypted);
|
||||
wpabuf_clear_free(decrypted);
|
||||
wps->state = SEND_WSC_NACK;
|
||||
return WPS_CONTINUE;
|
||||
}
|
||||
@ -2769,11 +2798,11 @@ static enum wps_process_res wps_process_m5(struct wps_data *wps,
|
||||
if (wps_parse_msg(decrypted, &eattr) < 0 ||
|
||||
wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
|
||||
wps_process_e_snonce1(wps, eattr.e_snonce1)) {
|
||||
wpabuf_free(decrypted);
|
||||
wpabuf_clear_free(decrypted);
|
||||
wps->state = SEND_WSC_NACK;
|
||||
return WPS_CONTINUE;
|
||||
}
|
||||
wpabuf_free(decrypted);
|
||||
wpabuf_clear_free(decrypted);
|
||||
|
||||
wps->state = SEND_M6;
|
||||
return WPS_CONTINUE;
|
||||
@ -2911,7 +2940,7 @@ static enum wps_process_res wps_process_m7(struct wps_data *wps,
|
||||
|
||||
if (wps_validate_m7_encr(decrypted, wps->wps->ap || wps->er,
|
||||
attr->version2 != NULL) < 0) {
|
||||
wpabuf_free(decrypted);
|
||||
wpabuf_clear_free(decrypted);
|
||||
wps->state = SEND_WSC_NACK;
|
||||
return WPS_CONTINUE;
|
||||
}
|
||||
@ -2922,12 +2951,12 @@ static enum wps_process_res wps_process_m7(struct wps_data *wps,
|
||||
wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
|
||||
wps_process_e_snonce2(wps, eattr.e_snonce2) ||
|
||||
wps_process_ap_settings_r(wps, &eattr)) {
|
||||
wpabuf_free(decrypted);
|
||||
wpabuf_clear_free(decrypted);
|
||||
wps->state = SEND_WSC_NACK;
|
||||
return WPS_CONTINUE;
|
||||
}
|
||||
|
||||
wpabuf_free(decrypted);
|
||||
wpabuf_clear_free(decrypted);
|
||||
|
||||
wps->state = SEND_M8;
|
||||
return WPS_CONTINUE;
|
||||
|
@ -1084,6 +1084,7 @@ upnp_wps_get_iface(struct upnp_wps_device_sm *sm, void *priv)
|
||||
void upnp_wps_device_deinit(struct upnp_wps_device_sm *sm, void *priv)
|
||||
{
|
||||
struct upnp_wps_device_interface *iface;
|
||||
struct upnp_wps_peer *peer;
|
||||
|
||||
if (!sm)
|
||||
return;
|
||||
@ -1104,8 +1105,13 @@ void upnp_wps_device_deinit(struct upnp_wps_device_sm *sm, void *priv)
|
||||
iface->wps->registrar);
|
||||
dl_list_del(&iface->list);
|
||||
|
||||
if (iface->peer.wps)
|
||||
wps_deinit(iface->peer.wps);
|
||||
while ((peer = dl_list_first(&iface->peers, struct upnp_wps_peer,
|
||||
list))) {
|
||||
if (peer->wps)
|
||||
wps_deinit(peer->wps);
|
||||
dl_list_del(&peer->list);
|
||||
os_free(peer);
|
||||
}
|
||||
os_free(iface->ctx->ap_pin);
|
||||
os_free(iface->ctx);
|
||||
os_free(iface);
|
||||
@ -1143,6 +1149,7 @@ upnp_wps_device_init(struct upnp_wps_device_ctx *ctx, struct wps_context *wps,
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "WPS UPnP: Init interface instance %p", iface);
|
||||
|
||||
dl_list_init(&iface->peers);
|
||||
iface->ctx = ctx;
|
||||
iface->wps = wps;
|
||||
iface->priv = priv;
|
||||
|
@ -11,11 +11,14 @@
|
||||
#ifndef WPS_UPNP_H
|
||||
#define WPS_UPNP_H
|
||||
|
||||
#include "utils/list.h"
|
||||
|
||||
struct upnp_wps_device_sm;
|
||||
struct wps_context;
|
||||
struct wps_data;
|
||||
|
||||
struct upnp_wps_peer {
|
||||
struct dl_list list;
|
||||
struct wps_data *wps;
|
||||
};
|
||||
|
||||
|
@ -109,8 +109,7 @@ struct upnp_wps_device_interface {
|
||||
struct wps_context *wps;
|
||||
void *priv;
|
||||
|
||||
/* FIX: maintain separate structures for each UPnP peer */
|
||||
struct upnp_wps_peer peer;
|
||||
struct dl_list peers; /* active UPnP peer sessions */
|
||||
};
|
||||
|
||||
/*
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user