mech_eap.spec
mech_eap*tar*
*.lo
+*.a
*.o
*.d
*.gcno
wpa_supplicant/wpa_gui/wpa_gui
wpa_supplicant/wpa_gui-qt4/Makefile
wpa_supplicant/wpa_gui-qt4/wpa_gui
+wpa_supplicant/libwpa_test1
+wpa_supplicant/libwpa_test2
hostapd/hostapd
hostapd/hostapd_cli
hostapd/hlr_auc_gw
unfortunately be accepted.
+The preferred method of submitting the contribution to the project is by
+email to the hostap mailing list:
+hostap@lists.infradead.org
+Note that the list may require subscription before accepting message
+without moderation. You can subscribe to the list at this address:
+http://lists.infradead.org/mailman/listinfo/hostap
+
+The message should contain an inlined patch against the current
+development branch (i.e., the master branch of
+git://w1.fi/hostap.git). Please make sure the software you use for
+sending the patch does not corrupt whitespace. If that cannot be fixed
+for some reason, it is better to include an attached version of the
+patch file than just send a whitespace damaged version in the message
+body.
+
+The patches should be separate logical changes rather than doing
+everything in a single patch. In other words, please keep cleanup, new
+features, and bug fixes all in their own patches. Each patch needs a
+commit log that describes the changes (what the changes fix, what
+functionality is added, why the changes are useful, etc.).
+
+Please try to follow the coding style used in the project.
+
+In general, the best way of generating a suitable formatted patch file
+is by committing the changes to a cloned git repository and using git
+format-patch. The patch can then be sent, e.g., with git send-email.
+
+
History of license and contributions terms
------------------------------------------
Modified BSD license (no advertisement clause):
-Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi> and contributors
+Copyright (c) 2002-2016, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
Redistribution and use in source and binary forms, with or without
--- /dev/null
+#
+# init.rc fragment for hostapd on Android
+# Copyright (c) 2002-2016, Jouni Malinen <j@w1.fi>
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+#
+
+on post-fs-data
+ mkdir /data/misc/wifi/hostapd 0770 wifi wifi
+
+service hostapd /system/bin/hostapd \
+ -e /data/misc/wifi/entropy.bin \
+ /data/misc/wifi/hostapd.conf
+ class main
+ user wifi
+ writepid /data/misc/wifi/hostapd.pid
+ group wifi
+ disabled
+ oneshot
wpa_supplicant and hostapd
--------------------------
-Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi> and contributors
+Copyright (c) 2002-2016, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
wpa_supplicant and hostapd
--------------------------
-Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi> and contributors
+Copyright (c) 2002-2016, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
These programs are licensed under the BSD license (the one with
mkdir -p $RELDIR
git archive --format=tar --prefix=wpa-$VER/ HEAD \
- README COPYING CONTRIBUTIONS patches src wpa_supplicant hostapd hs20 |
+ README COPYING CONTRIBUTIONS src wpa_supplicant hostapd hs20 |
gzip > $RELDIR/wpa-$VER.tar.gz
git archive --format=tar --prefix=hostapd-$VER/ HEAD \
- README COPYING CONTRIBUTIONS patches src hostapd |
+ README COPYING CONTRIBUTIONS src hostapd |
gzip > $RELDIR/hostapd-$VER.tar.gz
git archive --format=tar --prefix=wpa_supplicant-$VER/ HEAD \
- README COPYING CONTRIBUTIONS patches src wpa_supplicant hs20/client |
+ README COPYING CONTRIBUTIONS src wpa_supplicant hs20/client |
tar --directory=$TMP -xf -
cd $TMP
Enable/disable extended listen timing. Without parameters, this
command disables extended listen timing. When enabling the feature,
-two parameters are used: availibility period and availability interval
+two parameters are used: availability period and availability interval
(both in milliseconds and with range of 1-65535).
<dd>Getting an interface object path failed for an unknown reason.</dd>
</dl>
</li>
+
+ <li>
+ <h3>ExpectDisconnect ( ) --> nothing</h3>
+ <p>Notify wpa_supplicant of an externally triggered disconnection, e.g., due to system suspend.</p>
+ </li>
</ul>
\subsection dbus_main_properties Properties
</dl>
</li>
<li>
+ <h3>VendorElemAdd ( i: frame_id, ay: ielems ) --> nothing</h3>
+ <p>Add Vendor Elements to corresponding frame ID.</p>
+ <h4>Arguments</h4>
+ <dl>
+ <dt>i : frame_id</dt>
+ <dd>Frame ID for which Vendor specific IE is to be added.</dd>
+ <dt>ay : ielems</dt>
+ <dd>Information Element(s).</dd>
+ </dl>
+ <h4>Possible errors</h4>
+ <dl>
+ <dt>fi.w1.wpa_supplicant1.InvalidArgs</dt>
+ <dd>The "ielems" argument is not a properly formatted or size mismatch.</dd>
+ <dt>fi.w1.wpa_supplicant1.NoMemory</dt>
+ <dd>Needed memory was not possible to get allocated.</dd>
+ </dl>
+ </li>
+ <li>
+ <h3>VendorElemGet ( i: frame_id ) --> ay: ielems</h3>
+ <p>Get Vendor Elements of corresponding frame ID.</p>
+ <h4>Arguments</h4>
+ <dl>
+ <dt>i : frame_id</dt>
+ <dd>Frame ID for which Vendor specific IE is being queried.</dd>
+ <dt>ay : ielems</dt>
+ <dd>Information Element(s).</dd>
+ </dl>
+ <h4>Possible errors</h4>
+ <dl>
+ <dt>fi.w1.wpa_supplicant1.InvalidArgs</dt>
+ <dd>The "frame_id" argument is not valid.</dd>
+ </dl>
+ </li>
+ <li>
+ <h3>VendorElemRem ( i: frame_id, ay: ielems ) --> nothing</h3>
+ <p>Remove Vendor Elements of corresponding frame ID.</p>
+ <h4>Arguments</h4>
+ <dl>
+ <dt>i : frame_id</dt>
+ <dd>Frame ID for which Vendor specific IE is to be removed.</dd>
+ <dt>ay : ielems</dt>
+ <dd>Information Element(s) OR * to remove all.</dd>
+ </dl>
+ <h4>Possible errors</h4>
+ <dl>
+ <dt>fi.w1.wpa_supplicant1.InvalidArgs</dt>
+ <dd>The "ielems" argument is not a properly formatted or size mismatch.</dd>
+ <dt>fi.w1.wpa_supplicant1.NoMemory</dt>
+ <dd>Needed memory was not possible to get allocated.</dd>
+ </dl>
+ </li>
+ <li>
+ <h3>SaveConfig ( ) --> nothing</h3>
+ <p>Save configuration to the configuration file.</p>
+ </li>
+ <li>
<h3>EAPLogoff ( ) --> nothing</h3>
<p>IEEE 802.1X EAPOL state machine logoff.</p>
</li>
</li>
<li>
+ <h3>ConfigFile - s - (read)</h3>
+ <p>Configuration file path. Returns an empty string if no configuration file is in use.</p>
+ </li>
+
+ <li>
<h3>CurrentBSS - o - (read)</h3>
<p>Path to D-Bus object representing BSS which wpa_supplicant is associated with, or "/" if is not associated at all.</p>
</li>
<h3>DisconnectReason - i - (read)</h3>
<p>The most recent IEEE 802.11 reason code for disconnect. Negative value indicates locally generated disconnection.</p>
</li>
+
+ <li>
+ <h3>AssocStatusCode - i - (read)</h3>
+ <p>The most recent IEEE 802.11 status code for association rejection.</p>
+ </li>
+
+ <li>
+ <h3>EapolVersion - s - (read/write)</h3>
+ <p>IEEE 802.1X/EAPOL version number</p>
+ </li>
+
+ <li>
+ <h3>Bgscan - s - (read/write)</h3>
+ <p>Background scan and roaming parameters or an empty string if none</p>
+ </li>
+
+ <li>
+ <h3>DisableScanOffload - s - (read/write)</h3>
+ <p>Disable automatic offloading of scan requests</p>
+ </li>
+
+ <li>
+ <h3>OpenscEnginePath - s - (read/write)</h3>
+ <p>Path to the OpenSSL engine for opensc</p>
+ </li>
+
+ <li>
+ <h3>OpensslCiphers - s - (read/write)</h3>
+ <p>OpenSSL cipher string</p>
+ </li>
+
+ <li>
+ <h3>PcscReader - s - (read/write)</h3>
+ <p>PC/SC reader name prefix</p>
+ </li>
+
+ <li>
+ <h3>PcscPin - s - (read/write)</h3>
+ <p>PIN for USIM, GSM SIM, and smartcards</p>
+ </li>
+
+ <li>
+ <h3>ExternalSim - s - (read/write)</h3>
+ <p>Use external processing for SIM/USIM operations</p>
+ </li>
+
+ <li>
+ <h3>DriverParam - s - (read/write)</h3>
+ <p>Driver interface parameters</p>
+ </li>
+
+ <li>
+ <h3>Dot11RSNAConfigPMKLifetime - s - (read/write)</h3>
+ <p>Maximum lifetime of a PMK</p>
+ </li>
+
+ <li>
+ <h3>Dot11RSNAConfigPMKReauthThreshold - s - (read/write)</h3>
+ <p>PMK re-authentication threshold</p>
+ </li>
+
+ <li>
+ <h3>Dot11RSNAConfigSATimeout - s - (read/write)</h3>
+ <p>Security association timeout</p>
+ </li>
+
+ <li>
+ <h3>BssMaxCount - s - (read/write)</h3>
+ <p>Maximum number of BSS entries to keep in memory</p>
+ </li>
+
+ <li>
+ <h3>FilterSsids - s - (read/write)</h3>
+ <p>SSID-based scan result filtering</p>
+ </li>
+
+ <li>
+ <h3>FilterRssi - s - (read/write)</h3>
+ <p>RSSI-based scan result filtering</p>
+ </li>
+
+ <li>
+ <h3>MaxNumSta - s - (read/write)</h3>
+ <p>Maximum number of STAs in an AP/P2P GO</p>
+ </li>
+
+ <li>
+ <h3>DisassocLowAck - s - (read/write)</h3>
+ <p>Disassocicate stations with massive packet loss</p>
+ </li>
+
+ <li>
+ <h3>Interworking - s - (read/write)</h3>
+ <p>Whether Interworking (IEEE 802.11u) is enabled</p>
+ </li>
+
+ <li>
+ <h3>Hessid - s - (read/write)</h3>
+ <p>Homogenous ESS identifier</p>
+ </li>
+
+ <li>
+ <h3>AccessNetworkType - s - (read/write)</h3>
+ <p>Access Network Type</p>
+ </li>
+
+ <li>
+ <h3>PbcInM1 - s - (read/write)</h3>
+ <p>AP mode WPS probing workaround for PBC with Windows 7</p>
+ </li>
+
+ <li>
+ <h3>Autoscan - s - (read/write)</h3>
+ <p>Automatic scan parameters or an empty string if none</p>
+ </li>
+
+ <li>
+ <h3>WpsNfcDevPwId - s - (read/write)</h3>
+ <p>NFC Device Password ID for password token</p>
+ </li>
+
+ <li>
+ <h3>WpsNfcDhPubkey - s - (read/write)</h3>
+ <p>NFC DH Public Key for password token</p>
+ </li>
+
+ <li>
+ <h3>WpsNfcDhPrivkey - s - (read/write)</h3>
+ <p>NFC DH Private Key for password token</p>
+ </li>
+
+ <li>
+ <h3>WpsNfcDevPw - s - (read/write)</h3>
+ <p>NFC Device Password for password token</p>
+ </li>
+
+ <li>
+ <h3>ExtPasswordBackend - s - (read/write)</h3>
+ <p>External password backend or an empty string if none</p>
+ </li>
+
+ <li>
+ <h3>P2pGoMaxInactivity - s - (read/write)</h3>
+ <p>Timeout in seconds to detect STA inactivity</p>
+ </li>
+
+ <li>
+ <h3>AutoInterworking - s - (read/write)</h3>
+ <p>Whether to use network selection automatically</p>
+ </li>
+
+ <li>
+ <h3>Okc - s - (read/write)</h3>
+ <p>Whether to enable opportunistic key caching by default</p>
+ </li>
+
+ <li>
+ <h3>Pmf - s - (read/write)</h3>
+ <p>Whether to enable/require PMF by default</p>
+ </li>
+
+ <li>
+ <h3>SaeGroups - s - (read/write)</h3>
+ <p>Preference list of enabled groups for SAE</p>
+ </li>
+
+ <li>
+ <h3>DtimPeriod - s - (read/write)</h3>
+ <p>Default DTIM period in Beacon intervals</p>
+ </li>
+
+ <li>
+ <h3>BeaconInt - s - (read/write)</h3>
+ <p>Default Beacon interval in TU</p>
+ </li>
+
+ <li>
+ <h3>IgnoreOldScanRes - s - (read/write)</h3>
+ <p>Ignore scan results older than request</p>
+ </li>
+
+ <li>
+ <h3>FreqList - s - (read/write)</h3>
+ <p>Array of allowed scan frequencies or an empty string for all</p>
+ </li>
+
+ <li>
+ <h3>ScanCurFreq - s - (read/write)</h3>
+ <p>Whether to scan only the current channel</p>
+ </li>
+
+ <li>
+ <h3>SchedScanInterval - s - (read/write)</h3>
+ <p>schedule scan interval</p>
+ </li>
+
+ <li>
+ <h3>TdlsExternalControl - s - (read/write)</h3>
+ <p>External control for TDLS setup requests</p>
+ </li>
+
+ <li>
+ <h3>OsuDir - s - (read/write)</h3>
+ <p>OSU provider information directory</p>
+ </li>
+
+ <li>
+ <h3>WowlanTriggers - s - (read/write)</h3>
+ <p>Wake-on-WLAN triggers</p>
+ </li>
+
+ <li>
+ <h3>P2pSearchDelay - s - (read/write)</h3>
+ <p>Extra delay between concurrent search iterations</p>
+ </li>
+
+ <li>
+ <h3>MacAddr - s - (read/write)</h3>
+ <p>MAC address policy default</p>
+ </li>
+
+ <li>
+ <h3>RandAddrLifetime - s - (read/write)</h3>
+ <p>Lifetime of random MAC address in seconds</p>
+ </li>
+
+ <li>
+ <h3>PreassocMacAddr - s - (read/write)</h3>
+ <p>Pre-association MAC address policy</p>
+ </li>
+
+ <li>
+ <h3>KeyMgmtOffload - s - (read/write)</h3>
+ <p>Use key management offload</p>
+ </li>
+
+ <li>
+ <h3>PassiveScan - s - (read/write)</h3>
+ <p>Whether to force passive scan for network connection</p>
+ </li>
+
+ <li>
+ <h3>ReassocSameBssOptim - s - (read/write)</h3>
+ <p>Whether to optimize reassoc-to-same-BSS</p>
+ </li>
+
+ <li>
+ <h3>WpsPriority - s - (read/write)</h3>
+ <p>Priority for the networks added through WPS</p>
+ </li>
</ul>
\subsection dbus_interface_signals Signals
</li>
<li>
+ <h3>DeviceFoundProperties ( o : path, a{sv} : properties )</h3>
+ <p>A new peer device has been found.</p>
+ <h4>Arguments</h4>
+ <dl>
+ <dt>o : path</dt>
+ <dd>A D-Bus path to an object representing the found peer device.</dd>
+ </dl>
+ <dl>
+ <dt>a{sv} : properties</dt>
+ <dd>A dictionary containing properties of the found peer device.</dd>
+ </dl>
+ </li>
+
+ <li>
<h3>DeviceLost ( o : path )</h3>
</li>
# This could be handy for archiving the generated documentation or
# if some version control system is used.
-PROJECT_NUMBER = 2.4
+PROJECT_NUMBER = 2.6
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
frames. The value received from the peers will be included in the
\ref p2p_config::sd_request() and \ref p2p_config::sd_response() callbacks. The
value to be sent to the peers is incremented with a call to
-\ref p2p_sd_service_update() whenever availibility of the local services
+\ref p2p_sd_service_update() whenever availability of the local services
changes.
INCLUDES = $(LOCAL_PATH)
INCLUDES += $(LOCAL_PATH)/src
INCLUDES += $(LOCAL_PATH)/src/utils
-INCLUDES += external/openssl/include
INCLUDES += system/security/keystore/include
ifdef CONFIG_DRIVER_NL80211
ifneq ($(wildcard external/libnl),)
OBJS += src/ap/ieee802_11_shared.c
OBJS += src/ap/beacon.c
OBJS += src/ap/bss_load.c
+OBJS += src/ap/neighbor_db.c
+OBJS += src/ap/rrm.c
OBJS_d =
OBJS_p =
LIBS =
L_CFLAGS += -DCONFIG_NO_VLAN
else
OBJS += src/ap/vlan_init.c
-ifdef CONFIG_VLAN_NETLINK
+OBJS += src/ap/vlan_ifconfig.c
+OBJS += src/ap/vlan.c
ifdef CONFIG_FULL_DYNAMIC_VLAN
+# Define CONFIG_FULL_DYNAMIC_VLAN to have hostapd manipulate bridges
+# and VLAN interfaces for the VLAN feature.
+L_CFLAGS += -DCONFIG_FULL_DYNAMIC_VLAN
+OBJS += src/ap/vlan_full.c
+ifdef CONFIG_VLAN_NETLINK
OBJS += src/ap/vlan_util.c
+else
+OBJS += src/ap/vlan_ioctl.c
endif
-L_CFLAGS += -DCONFIG_VLAN_NETLINK
endif
endif
ifdef CONFIG_NO_CTRL_IFACE
L_CFLAGS += -DCONFIG_NO_CTRL_IFACE
else
+OBJS += src/common/ctrl_iface_common.c
OBJS += ctrl_iface.c
OBJS += src/ap/ctrl_iface_ap.c
endif
L_CFLAGS += -DCONFIG_IEEE80211AC
endif
+ifdef CONFIG_MBO
+L_CFLAGS += -DCONFIG_MBO
+OBJS += src/ap/mbo_ap.c
+endif
+
ifdef CONFIG_FST
L_CFLAGS += -DCONFIG_FST
OBJS += src/fst/fst.c
ifeq ($(CONFIG_TLS), openssl)
ifdef TLS_FUNCS
OBJS += src/crypto/tls_openssl.c
+OBJS += src/crypto/tls_openssl_ocsp.c
LIBS += -lssl
endif
OBJS += src/crypto/crypto_openssl.c
CONFIG_INTERNAL_MD4=y
CONFIG_INTERNAL_MD5=y
CONFIG_INTERNAL_SHA256=y
+CONFIG_INTERNAL_SHA384=y
+CONFIG_INTERNAL_SHA512=y
CONFIG_INTERNAL_RC4=y
CONFIG_INTERNAL_DH_GROUP5=y
endif
OBJS += src/crypto/sha384-prf.c
endif
+ifdef CONFIG_INTERNAL_SHA384
+L_CFLAGS += -DCONFIG_INTERNAL_SHA384
+OBJS += src/crypto/sha384-internal.c
+endif
+
+ifdef CONFIG_INTERNAL_SHA512
+L_CFLAGS += -DCONFIG_INTERNAL_SHA512
+OBJS += src/crypto/sha512-internal.c
+endif
+
ifdef NEED_DH_GROUPS
OBJS += src/crypto/dh_groups.c
endif
L_CFLAGS += -DCONFIG_DRIVER_RADIUS_ACL
endif
-ifdef CONFIG_FULL_DYNAMIC_VLAN
-# define CONFIG_FULL_DYNAMIC_VLAN to have hostapd manipulate bridges
-# and vlan interfaces for the vlan feature.
-L_CFLAGS += -DCONFIG_FULL_DYNAMIC_VLAN
-endif
-
ifdef NEED_BASE64
OBJS += src/utils/base64.c
endif
L_CFLAGS += -DCONFIG_ANDROID_LOG
endif
-OBJS_c = hostapd_cli.c src/common/wpa_ctrl.c src/utils/os_$(CONFIG_OS).c
+OBJS_c = hostapd_cli.c
+OBJS_c += src/common/wpa_ctrl.c
+OBJS_c += src/utils/os_$(CONFIG_OS).c
+OBJS_c += src/common/cli.c
OBJS_c += src/utils/eloop.c
OBJS_c += src/utils/common.c
ifdef CONFIG_WPA_TRACE
LOCAL_CFLAGS := $(L_CFLAGS)
LOCAL_SRC_FILES := $(OBJS)
LOCAL_C_INCLUDES := $(INCLUDES)
+LOCAL_INIT_RC := hostapd.android.rc
include $(BUILD_EXECUTABLE)
endif # ifeq ($(WPA_BUILD_HOSTAPD),true)
ChangeLog for hostapd
+2016-10-02 - v2.6
+ * fixed EAP-pwd last fragment validation
+ [http://w1.fi/security/2015-7/] (CVE-2015-5314)
+ * fixed WPS configuration update vulnerability with malformed passphrase
+ [http://w1.fi/security/2016-1/] (CVE-2016-4476)
+ * extended channel switch support for VHT bandwidth changes
+ * added support for configuring new ANQP-elements with
+ anqp_elem=<InfoID>:<hexdump of payload>
+ * fixed Suite B 192-bit AKM to use proper PMK length
+ (note: this makes old releases incompatible with the fixed behavior)
+ * added no_probe_resp_if_max_sta=1 parameter to disable Probe Response
+ frame sending for not-associated STAs if max_num_sta limit has been
+ reached
+ * added option (-S as command line argument) to request all interfaces
+ to be started at the same time
+ * modified rts_threshold and fragm_threshold configuration parameters
+ to allow -1 to be used to disable RTS/fragmentation
+ * EAP-pwd: added support for Brainpool Elliptic Curves
+ (with OpenSSL 1.0.2 and newer)
+ * fixed EAPOL reauthentication after FT protocol run
+ * fixed FTIE generation for 4-way handshake after FT protocol run
+ * fixed and improved various FST operations
+ * TLS server
+ - support SHA384 and SHA512 hashes
+ - support TLS v1.2 signature algorithm with SHA384 and SHA512
+ - support PKCS #5 v2.0 PBES2
+ - support PKCS #5 with PKCS #12 style key decryption
+ - minimal support for PKCS #12
+ - support OCSP stapling (including ocsp_multi)
+ * added support for OpenSSL 1.1 API changes
+ - drop support for OpenSSL 0.9.8
+ - drop support for OpenSSL 1.0.0
+ * EAP-PEAP: support fast-connect crypto binding
+ * RADIUS
+ - fix Called-Station-Id to not escape SSID
+ - add Event-Timestamp to all Accounting-Request packets
+ - add Acct-Session-Id to Accounting-On/Off
+ - add Acct-Multi-Session-Id ton Access-Request packets
+ - add Service-Type (= Frames)
+ - allow server to provide PSK instead of passphrase for WPA-PSK
+ Tunnel_password case
+ - update full message for interim accounting updates
+ - add Acct-Delay-Time into Accounting messages
+ - add require_message_authenticator configuration option to require
+ CoA/Disconnect-Request packets to be authenticated
+ * started to postpone WNM-Notification frame sending by 100 ms so that
+ the STA has some more time to configure the key before this frame is
+ received after the 4-way handshake
+ * VHT: added interoperability workaround for 80+80 and 160 MHz channels
+ * extended VLAN support (per-STA vif, etc.)
+ * fixed PMKID derivation with SAE
+ * nl80211
+ - added support for full station state operations
+ - fix IEEE 802.1X/WEP EAP reauthentication and rekeying to use
+ unencrypted EAPOL frames
+ * added initial MBO support; number of extensions to WNM BSS Transition
+ Management
+ * added initial functionality for location related operations
+ * added assocresp_elements parameter to allow vendor specific elements
+ to be added into (Re)Association Response frames
+ * improved Public Action frame addressing
+ - use Address 3 = wildcard BSSID in GAS response if a query from an
+ unassociated STA used that address
+ - fix TX status processing for Address 3 = wildcard BSSID
+ - add gas_address3 configuration parameter to control Address 3
+ behavior
+ * added command line parameter -i to override interface parameter in
+ hostapd.conf
+ * added command completion support to hostapd_cli
+ * added passive client taxonomy determination (CONFIG_TAXONOMY=y
+ compile option and "SIGNATURE <addr>" control interface command)
+ * number of small fixes
+
2015-09-27 - v2.5
* fixed WPS UPnP vulnerability with HTTP chunked transfer encoding
[http://w1.fi/security/2015-2/] (CVE-2015-4141)
CFLAGS = -MMD -O2 -Wall -g
endif
+ifdef LIBS
+# If LIBS is set with some global build system defaults, clone those for
+# LIBS_c, LIBS_h, and LIBS_n to cover hostapd_cli, hlr_auc_gw, and
+# nt_password_hash as well.
+ifndef LIBS_c
+LIBS_c := $(LIBS)
+endif
+ifndef LIBS_h
+LIBS_h := $(LIBS)
+endif
+ifndef LIBS_n
+LIBS_n := $(LIBS)
+endif
+endif
+
CFLAGS += $(EXTRA_CFLAGS)
CFLAGS += -I$(abspath ../src)
CFLAGS += -I$(abspath ../src/utils)
export BINDIR ?= /usr/local/bin/
-# Uncomment following line and set the path to your kernel tree include
-# directory if your C library does not include all header files.
-# CFLAGS += -DUSE_KERNEL_HEADERS -I/usr/src/linux/include
-
-include .config
+ifndef CONFIG_NO_GITVER
+# Add VERSION_STR postfix for builds from a git repository
+ifeq ($(wildcard ../.git),../.git)
+GITVER := $(shell git describe --dirty=+)
+ifneq ($(GITVER),)
+CFLAGS += -DGIT_VERSION_STR_POSTFIX=\"-$(GITVER)\"
+endif
+endif
+endif
+
ifdef CONFIG_TESTING_OPTIONS
CFLAGS += -DCONFIG_TESTING_OPTIONS
CONFIG_WPS_TESTING=y
OBJS += ../src/ap/ieee802_11_shared.o
OBJS += ../src/ap/beacon.o
OBJS += ../src/ap/bss_load.o
+OBJS += ../src/ap/neighbor_db.o
+OBJS += ../src/ap/rrm.o
-OBJS_c = hostapd_cli.o ../src/common/wpa_ctrl.o ../src/utils/os_$(CONFIG_OS).o
+OBJS_c = hostapd_cli.o
+OBJS_c += ../src/common/wpa_ctrl.o
+OBJS_c += ../src/utils/os_$(CONFIG_OS).o
+OBJS_c += ../src/common/cli.o
NEED_RC4=y
NEED_AES=y
OBJS += ../src/drivers/drivers.o
CFLAGS += -DHOSTAPD
+ifdef CONFIG_TAXONOMY
+CFLAGS += -DCONFIG_TAXONOMY
+OBJS += ../src/ap/taxonomy.o
+endif
+
ifdef CONFIG_MODULE_TESTS
CFLAGS += -DCONFIG_MODULE_TESTS
OBJS += hapd_module_tests.o
CFLAGS += -DCONFIG_ELOOP_EPOLL
endif
+ifdef CONFIG_ELOOP_KQUEUE
+CFLAGS += -DCONFIG_ELOOP_KQUEUE
+endif
+
OBJS += ../src/utils/common.o
OBJS_c += ../src/utils/common.o
OBJS += ../src/utils/wpa_debug.o
CFLAGS += -DCONFIG_NO_VLAN
else
OBJS += ../src/ap/vlan_init.o
-ifdef CONFIG_VLAN_NETLINK
+OBJS += ../src/ap/vlan_ifconfig.o
+OBJS += ../src/ap/vlan.o
ifdef CONFIG_FULL_DYNAMIC_VLAN
+# Define CONFIG_FULL_DYNAMIC_VLAN to have hostapd manipulate bridges
+# and VLAN interfaces for the VLAN feature.
+CFLAGS += -DCONFIG_FULL_DYNAMIC_VLAN
+OBJS += ../src/ap/vlan_full.o
+ifdef CONFIG_VLAN_NETLINK
OBJS += ../src/ap/vlan_util.o
+else
+OBJS += ../src/ap/vlan_ioctl.o
endif
-CFLAGS += -DCONFIG_VLAN_NETLINK
endif
endif
ifdef CONFIG_NO_CTRL_IFACE
CFLAGS += -DCONFIG_NO_CTRL_IFACE
else
+ifeq ($(CONFIG_CTRL_IFACE), udp)
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP
+else
+ifeq ($(CONFIG_CTRL_IFACE), udp6)
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP_IPV6
+else
+ifeq ($(CONFIG_CTRL_IFACE), udp-remote)
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP_REMOTE
+else
+ifeq ($(CONFIG_CTRL_IFACE), udp6-remote)
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP_REMOTE
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP_IPV6
+else
+CFLAGS += -DCONFIG_CTRL_IFACE_UNIX
+endif
+endif
+endif
+endif
+OBJS += ../src/common/ctrl_iface_common.o
OBJS += ctrl_iface.o
OBJS += ../src/ap/ctrl_iface_ap.o
endif
-CFLAGS += -DCONFIG_CTRL_IFACE -DCONFIG_CTRL_IFACE_UNIX
+ifndef CONFIG_NO_CTRL_IFACE
+CFLAGS += -DCONFIG_CTRL_IFACE
+endif
ifdef CONFIG_IAPP
CFLAGS += -DCONFIG_IAPP
CFLAGS += -DCONFIG_IEEE80211AC
endif
+ifdef CONFIG_MBO
+CFLAGS += -DCONFIG_MBO
+OBJS += ../src/ap/mbo_ap.o
+endif
+
include ../src/drivers/drivers.mak
OBJS += $(DRV_AP_OBJS)
CFLAGS += $(DRV_AP_CFLAGS)
ifeq ($(CONFIG_TLS), openssl)
ifdef TLS_FUNCS
OBJS += ../src/crypto/tls_openssl.o
+OBJS += ../src/crypto/tls_openssl_ocsp.o
LIBS += -lssl
endif
OBJS += ../src/crypto/crypto_openssl.o
CONFIG_INTERNAL_MD4=y
CONFIG_INTERNAL_MD5=y
CONFIG_INTERNAL_SHA256=y
+CONFIG_INTERNAL_SHA384=y
+CONFIG_INTERNAL_SHA512=y
CONFIG_INTERNAL_RC4=y
CONFIG_INTERNAL_DH_GROUP5=y
endif
OBJS += ../src/crypto/sha384-prf.o
endif
+ifdef CONFIG_INTERNAL_SHA384
+CFLAGS += -DCONFIG_INTERNAL_SHA384
+OBJS += ../src/crypto/sha384-internal.o
+endif
+
+ifdef CONFIG_INTERNAL_SHA512
+CFLAGS += -DCONFIG_INTERNAL_SHA512
+OBJS += ../src/crypto/sha512-internal.o
+endif
+
ifdef NEED_DH_GROUPS
OBJS += ../src/crypto/dh_groups.o
endif
CFLAGS += -DCONFIG_DRIVER_RADIUS_ACL
endif
-ifdef CONFIG_FULL_DYNAMIC_VLAN
-# define CONFIG_FULL_DYNAMIC_VLAN to have hostapd manipulate bridges
-# and vlan interfaces for the vlan feature.
-CFLAGS += -DCONFIG_FULL_DYNAMIC_VLAN
-endif
-
ifdef NEED_BASE64
OBJS += ../src/utils/base64.o
endif
Authenticator and RADIUS authentication server
================================================================
-Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi> and contributors
+Copyright (c) 2002-2016, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
This program is licensed under the BSD license (the one with
#LIBS += -L$(LIBNL)/lib
CONFIG_LIBNL20=y
+# QCA vendor extensions to nl80211
+CONFIG_DRIVER_NL80211_QCA=y
+
# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
#CONFIG_DRIVER_BSD=y
#CFLAGS += -I/usr/local/include
# Enable Fast Session Transfer (FST)
#CONFIG_FST=y
+
+# Multiband Operation support
+# These extentions facilitate efficient use of multiple frequency bands
+# available to the AP and the devices that may associate with it.
+#CONFIG_MBO=y
}
vlan->vlan_id = vlan_id;
+ vlan->vlan_desc.untagged = vlan_id;
+ vlan->vlan_desc.notempty = !!vlan_id;
os_strlcpy(vlan->ifname, pos, sizeof(vlan->ifname));
vlan->next = bss->vlan;
bss->vlan = vlan;
*acl = newacl;
os_memcpy((*acl)[*num].addr, addr, ETH_ALEN);
- (*acl)[*num].vlan_id = vlan_id;
+ os_memset(&(*acl)[*num].vlan_id, 0,
+ sizeof((*acl)[*num].vlan_id));
+ (*acl)[*num].vlan_id.untagged = vlan_id;
+ (*acl)[*num].vlan_id.notempty = !!vlan_id;
(*num)++;
}
}
-static int hostapd_parse_das_client(struct hostapd_bss_config *bss,
- const char *val)
+static int hostapd_parse_das_client(struct hostapd_bss_config *bss, char *val)
{
char *secret;
if (secret == NULL)
return -1;
- secret++;
+ *secret++ = '\0';
if (hostapd_parse_ip_addr(val, &bss->radius_das_client_addr))
return -1;
}
+static int parse_anqp_elem(struct hostapd_bss_config *bss, char *buf, int line)
+{
+ char *delim;
+ u16 infoid;
+ size_t len;
+ struct wpabuf *payload;
+ struct anqp_element *elem;
+
+ delim = os_strchr(buf, ':');
+ if (!delim)
+ return -1;
+ delim++;
+ infoid = atoi(buf);
+ len = os_strlen(delim);
+ if (len & 1)
+ return -1;
+ len /= 2;
+ payload = wpabuf_alloc(len);
+ if (!payload)
+ return -1;
+ if (hexstr2bin(delim, wpabuf_put(payload, len), len) < 0) {
+ wpabuf_free(payload);
+ return -1;
+ }
+
+ dl_list_for_each(elem, &bss->anqp_elem, struct anqp_element, list) {
+ if (elem->infoid == infoid) {
+ /* Update existing entry */
+ wpabuf_free(elem->payload);
+ elem->payload = payload;
+ return 0;
+ }
+ }
+
+ /* Add a new entry */
+ elem = os_zalloc(sizeof(*elem));
+ if (!elem) {
+ wpabuf_free(payload);
+ return -1;
+ }
+ elem->infoid = infoid;
+ elem->payload = payload;
+ dl_list_add(&bss->anqp_elem, &elem->list);
+
+ return 0;
+}
+
+
static int parse_qos_map_set(struct hostapd_bss_config *bss,
char *buf, int line)
{
#endif /* CONFIG_HS20 */
-#ifdef CONFIG_WPS_NFC
-static struct wpabuf * hostapd_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;
-}
-#endif /* CONFIG_WPS_NFC */
-
-
#ifdef CONFIG_ACS
static int hostapd_config_parse_acs_chan_bias(struct hostapd_config *conf,
char *pos)
#endif /* CONFIG_ACS */
+static int parse_wpabuf_hex(int line, const char *name, struct wpabuf **buf,
+ const char *val)
+{
+ struct wpabuf *elems;
+
+ if (val[0] == '\0') {
+ wpabuf_free(*buf);
+ *buf = NULL;
+ return 0;
+ }
+
+ elems = wpabuf_parse_bin(val);
+ if (!elems) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid %s '%s'",
+ line, name, val);
+ return -1;
+ }
+
+ wpabuf_free(*buf);
+ *buf = elems;
+
+ return 0;
+}
+
+
static int hostapd_config_fill(struct hostapd_config *conf,
struct hostapd_bss_config *bss,
const char *buf, char *pos, int line)
} else if (os_strcmp(buf, "ocsp_stapling_response") == 0) {
os_free(bss->ocsp_stapling_response);
bss->ocsp_stapling_response = os_strdup(pos);
+ } else if (os_strcmp(buf, "ocsp_stapling_response_multi") == 0) {
+ os_free(bss->ocsp_stapling_response_multi);
+ bss->ocsp_stapling_response_multi = os_strdup(pos);
} else if (os_strcmp(buf, "dh_file") == 0) {
os_free(bss->dh_file);
bss->dh_file = os_strdup(pos);
} else if (os_strcmp(buf, "eap_sim_db") == 0) {
os_free(bss->eap_sim_db);
bss->eap_sim_db = os_strdup(pos);
+ } else if (os_strcmp(buf, "eap_sim_db_timeout") == 0) {
+ bss->eap_sim_db_timeout = atoi(pos);
} else if (os_strcmp(buf, "eap_sim_aka_result_ind") == 0) {
bss->eap_sim_aka_result_ind = atoi(pos);
#endif /* EAP_SERVER_SIM */
bss->radius_das_time_window = atoi(pos);
} else if (os_strcmp(buf, "radius_das_require_event_timestamp") == 0) {
bss->radius_das_require_event_timestamp = atoi(pos);
+ } else if (os_strcmp(buf, "radius_das_require_message_authenticator") ==
+ 0) {
+ bss->radius_das_require_message_authenticator = atoi(pos);
#endif /* CONFIG_NO_RADIUS */
} else if (os_strcmp(buf, "auth_algs") == 0) {
bss->auth_algs = atoi(pos);
}
} else if (os_strcmp(buf, "rts_threshold") == 0) {
conf->rts_threshold = atoi(pos);
- if (conf->rts_threshold < 0 || conf->rts_threshold > 2347) {
+ if (conf->rts_threshold < -1 || conf->rts_threshold > 65535) {
wpa_printf(MSG_ERROR,
"Line %d: invalid rts_threshold %d",
line, conf->rts_threshold);
}
} else if (os_strcmp(buf, "fragm_threshold") == 0) {
conf->fragm_threshold = atoi(pos);
- if (conf->fragm_threshold < 256 ||
- conf->fragm_threshold > 2346) {
+ if (conf->fragm_threshold == -1) {
+ /* allow a value of -1 */
+ } else if (conf->fragm_threshold < 256 ||
+ conf->fragm_threshold > 2346) {
wpa_printf(MSG_ERROR,
"Line %d: invalid fragm_threshold %d",
line, conf->fragm_threshold);
conf->preamble = LONG_PREAMBLE;
} else if (os_strcmp(buf, "ignore_broadcast_ssid") == 0) {
bss->ignore_broadcast_ssid = atoi(pos);
+ } else if (os_strcmp(buf, "no_probe_resp_if_max_sta") == 0) {
+ bss->no_probe_resp_if_max_sta = atoi(pos);
} else if (os_strcmp(buf, "wep_default_key") == 0) {
bss->ssid.wep.idx = atoi(pos);
if (bss->ssid.wep.idx > 3) {
#ifndef CONFIG_NO_VLAN
} else if (os_strcmp(buf, "dynamic_vlan") == 0) {
bss->ssid.dynamic_vlan = atoi(pos);
+ } else if (os_strcmp(buf, "per_sta_vif") == 0) {
+ bss->ssid.per_sta_vif = atoi(pos);
} else if (os_strcmp(buf, "vlan_file") == 0) {
if (hostapd_config_read_vlan_file(bss, pos)) {
wpa_printf(MSG_ERROR, "Line %d: failed to read VLAN file '%s'",
line);
return 1;
}
+ } else if (os_strcmp(buf, "use_driver_iface_addr") == 0) {
+ conf->use_driver_iface_addr = atoi(pos);
#ifdef CONFIG_IEEE80211W
} else if (os_strcmp(buf, "ieee80211w") == 0) {
bss->ieee80211w = atoi(pos);
conf->vht_oper_centr_freq_seg1_idx = atoi(pos);
} else if (os_strcmp(buf, "vendor_vht") == 0) {
bss->vendor_vht = atoi(pos);
+ } else if (os_strcmp(buf, "use_sta_nsts") == 0) {
+ bss->use_sta_nsts = atoi(pos);
#endif /* CONFIG_IEEE80211AC */
} else if (os_strcmp(buf, "max_listen_interval") == 0) {
bss->max_listen_interval = atoi(pos);
bss->wps_nfc_pw_from_config = 1;
} else if (os_strcmp(buf, "wps_nfc_dh_pubkey") == 0) {
wpabuf_free(bss->wps_nfc_dh_pubkey);
- bss->wps_nfc_dh_pubkey = hostapd_parse_bin(pos);
+ bss->wps_nfc_dh_pubkey = wpabuf_parse_bin(pos);
bss->wps_nfc_pw_from_config = 1;
} else if (os_strcmp(buf, "wps_nfc_dh_privkey") == 0) {
wpabuf_free(bss->wps_nfc_dh_privkey);
- bss->wps_nfc_dh_privkey = hostapd_parse_bin(pos);
+ bss->wps_nfc_dh_privkey = wpabuf_parse_bin(pos);
bss->wps_nfc_pw_from_config = 1;
} else if (os_strcmp(buf, "wps_nfc_dev_pw") == 0) {
wpabuf_free(bss->wps_nfc_dev_pw);
- bss->wps_nfc_dev_pw = hostapd_parse_bin(pos);
+ bss->wps_nfc_dev_pw = wpabuf_parse_bin(pos);
bss->wps_nfc_pw_from_config = 1;
#endif /* CONFIG_WPS_NFC */
#endif /* CONFIG_WPS */
} else if (os_strcmp(buf, "nai_realm") == 0) {
if (parse_nai_realm(bss, pos, line) < 0)
return 1;
+ } else if (os_strcmp(buf, "anqp_elem") == 0) {
+ if (parse_anqp_elem(bss, pos, line) < 0)
+ return 1;
} else if (os_strcmp(buf, "gas_frag_limit") == 0) {
bss->gas_frag_limit = atoi(pos);
} else if (os_strcmp(buf, "gas_comeback_delay") == 0) {
os_free(bss->dump_msk_file);
bss->dump_msk_file = os_strdup(pos);
#endif /* CONFIG_RADIUS_TEST */
+#ifdef CONFIG_PROXYARP
+ } else if (os_strcmp(buf, "proxy_arp") == 0) {
+ bss->proxy_arp = atoi(pos);
+#endif /* CONFIG_PROXYARP */
#ifdef CONFIG_HS20
} else if (os_strcmp(buf, "hs20") == 0) {
bss->hs20 = atoi(pos);
} else if (os_strcmp(buf, "disable_dgaf") == 0) {
bss->disable_dgaf = atoi(pos);
- } else if (os_strcmp(buf, "proxy_arp") == 0) {
- bss->proxy_arp = atoi(pos);
} else if (os_strcmp(buf, "na_mcast_to_ucast") == 0) {
bss->na_mcast_to_ucast = atoi(pos);
} else if (os_strcmp(buf, "osen") == 0) {
} else if (os_strcmp(buf, "subscr_remediation_method") == 0) {
bss->subscr_remediation_method = atoi(pos);
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_MBO
+ } else if (os_strcmp(buf, "mbo") == 0) {
+ bss->mbo_enabled = atoi(pos);
+#endif /* CONFIG_MBO */
#ifdef CONFIG_TESTING_OPTIONS
#define PARSE_TEST_PROBABILITY(_val) \
} else if (os_strcmp(buf, #_val) == 0) { \
PARSE_TEST_PROBABILITY(ignore_assoc_probability)
PARSE_TEST_PROBABILITY(ignore_reassoc_probability)
PARSE_TEST_PROBABILITY(corrupt_gtk_rekey_mic_probability)
+ } else if (os_strcmp(buf, "ecsa_ie_only") == 0) {
+ conf->ecsa_ie_only = atoi(pos);
} else if (os_strcmp(buf, "bss_load_test") == 0) {
WPA_PUT_LE16(bss->bss_load_test, atoi(pos));
pos = os_strchr(pos, ':');
WPA_PUT_LE16(&bss->bss_load_test[3], atoi(pos));
bss->bss_load_test_set = 1;
} else if (os_strcmp(buf, "radio_measurements") == 0) {
- bss->radio_measurements = atoi(pos);
+ /*
+ * DEPRECATED: This parameter will be removed in the future.
+ * Use rrm_neighbor_report instead.
+ */
+ int val = atoi(pos);
+
+ if (val & BIT(0))
+ bss->radio_measurements[0] |=
+ WLAN_RRM_CAPS_NEIGHBOR_REPORT;
} else if (os_strcmp(buf, "own_ie_override") == 0) {
struct wpabuf *tmp;
size_t len = os_strlen(pos) / 2;
bss->own_ie_override = tmp;
#endif /* CONFIG_TESTING_OPTIONS */
} else if (os_strcmp(buf, "vendor_elements") == 0) {
- struct wpabuf *elems;
- size_t len = os_strlen(pos);
- if (len & 0x01) {
- wpa_printf(MSG_ERROR,
- "Line %d: Invalid vendor_elements '%s'",
- line, pos);
- return 1;
- }
- len /= 2;
- if (len == 0) {
- wpabuf_free(bss->vendor_elements);
- bss->vendor_elements = NULL;
- return 0;
- }
-
- elems = wpabuf_alloc(len);
- if (elems == NULL)
+ if (parse_wpabuf_hex(line, buf, &bss->vendor_elements, pos))
return 1;
-
- if (hexstr2bin(pos, wpabuf_put(elems, len), len)) {
- wpabuf_free(elems);
- wpa_printf(MSG_ERROR,
- "Line %d: Invalid vendor_elements '%s'",
- line, pos);
+ } else if (os_strcmp(buf, "assocresp_elements") == 0) {
+ if (parse_wpabuf_hex(line, buf, &bss->assocresp_elements, pos))
return 1;
- }
-
- wpabuf_free(bss->vendor_elements);
- bss->vendor_elements = elems;
} else if (os_strcmp(buf, "sae_anti_clogging_threshold") == 0) {
bss->sae_anti_clogging_threshold = atoi(pos);
} else if (os_strcmp(buf, "sae_groups") == 0) {
return -1;
}
val = strtol(pos, &endp, 0);
- if (*endp || val < 1 || val > FST_MAX_LLT_MS) {
+ if (*endp || val < 1 ||
+ (unsigned long int) val > FST_MAX_LLT_MS) {
wpa_printf(MSG_ERROR,
"Line %d: Invalid fst_llt %ld (%s) (expected 1..%u)",
line, val, pos, FST_MAX_LLT_MS);
} else if (os_strcmp(buf, "no_auth_if_seen_on") == 0) {
os_free(bss->no_auth_if_seen_on);
bss->no_auth_if_seen_on = os_strdup(pos);
+ } else if (os_strcmp(buf, "lci") == 0) {
+ wpabuf_free(conf->lci);
+ conf->lci = wpabuf_parse_bin(pos);
+ } else if (os_strcmp(buf, "civic") == 0) {
+ wpabuf_free(conf->civic);
+ conf->civic = wpabuf_parse_bin(pos);
+ } else if (os_strcmp(buf, "rrm_neighbor_report") == 0) {
+ if (atoi(pos))
+ bss->radio_measurements[0] |=
+ WLAN_RRM_CAPS_NEIGHBOR_REPORT;
+ } else if (os_strcmp(buf, "gas_address3") == 0) {
+ bss->gas_address3 = atoi(pos);
+ } else if (os_strcmp(buf, "ftm_responder") == 0) {
+ bss->ftm_responder = atoi(pos);
+ } else if (os_strcmp(buf, "ftm_initiator") == 0) {
+ bss->ftm_initiator = atoi(pos);
} else {
wpa_printf(MSG_ERROR,
"Line %d: unknown configuration item '%s'",
{
struct hostapd_config *conf;
FILE *f;
- char buf[512], *pos;
+ char buf[4096], *pos;
int line = 0;
int errors = 0;
size_t i;
#include <sys/stat.h>
#include <stddef.h>
+#ifdef CONFIG_CTRL_IFACE_UDP
+#include <netdb.h>
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
#include "utils/common.h"
#include "utils/eloop.h"
+#include "utils/module_tests.h"
#include "common/version.h"
#include "common/ieee802_11_defs.h"
+#include "common/ctrl_iface_common.h"
#include "crypto/tls.h"
#include "drivers/driver.h"
#include "eapol_auth/eapol_auth_sm.h"
#include "ap/wnm_ap.h"
#include "ap/wpa_auth.h"
#include "ap/beacon.h"
+#include "ap/neighbor_db.h"
+#include "ap/rrm.h"
#include "wps/wps_defs.h"
#include "wps/wps.h"
#include "fst/fst_ctrl_iface.h"
#define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256
-struct wpa_ctrl_dst {
- struct wpa_ctrl_dst *next;
- struct sockaddr_un addr;
- socklen_t addrlen;
- int debug_level;
- int errors;
-};
-
+#ifdef CONFIG_CTRL_IFACE_UDP
+#define COOKIE_LEN 8
+static unsigned char cookie[COOKIE_LEN];
+static unsigned char gcookie[COOKIE_LEN];
+#define HOSTAPD_CTRL_IFACE_PORT 8877
+#define HOSTAPD_CTRL_IFACE_PORT_LIMIT 50
+#define HOSTAPD_GLOBAL_CTRL_IFACE_PORT 8878
+#define HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT 50
+#endif /* CONFIG_CTRL_IFACE_UDP */
static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
enum wpa_msg_type type,
static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
- struct sockaddr_un *from,
+ 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, sizeof(struct sockaddr_un));
- dst->addrlen = fromlen;
- dst->debug_level = MSG_INFO;
- dst->next = hapd->ctrl_dst;
- hapd->ctrl_dst = dst;
- wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
- (u8 *) from->sun_path,
- fromlen - offsetof(struct sockaddr_un, sun_path));
- return 0;
+ return ctrl_iface_attach(&hapd->ctrl_dst, from, fromlen);
}
static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
- struct sockaddr_un *from,
+ struct sockaddr_storage *from,
socklen_t fromlen)
{
- struct wpa_ctrl_dst *dst, *prev = NULL;
-
- dst = hapd->ctrl_dst;
- while (dst) {
- if (fromlen == dst->addrlen &&
- os_memcmp(from->sun_path, dst->addr.sun_path,
- fromlen - offsetof(struct sockaddr_un, sun_path))
- == 0) {
- wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
- (u8 *) from->sun_path,
- fromlen -
- offsetof(struct sockaddr_un, sun_path));
- if (prev == NULL)
- hapd->ctrl_dst = dst->next;
- else
- prev->next = dst->next;
- os_free(dst);
- return 0;
- }
- prev = dst;
- dst = dst->next;
- }
- return -1;
+ return ctrl_iface_detach(&hapd->ctrl_dst, from, fromlen);
}
static int hostapd_ctrl_iface_level(struct hostapd_data *hapd,
- struct sockaddr_un *from,
+ struct sockaddr_storage *from,
socklen_t fromlen,
char *level)
{
- struct wpa_ctrl_dst *dst;
-
- wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
-
- dst = hapd->ctrl_dst;
- while (dst) {
- if (fromlen == dst->addrlen &&
- os_memcmp(from->sun_path, dst->addr.sun_path,
- fromlen - offsetof(struct sockaddr_un, sun_path))
- == 0) {
- wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
- "level", (u8 *) from->sun_path, fromlen -
- offsetof(struct sockaddr_un, sun_path));
- dst->debug_level = atoi(level);
- return 0;
- }
- dst = dst->next;
- }
-
- return -1;
+ return ctrl_iface_level(&hapd->ctrl_dst, from, fromlen, level);
}
int ret;
u8 nei_rep[1000];
u8 *nei_pos = nei_rep;
+ u8 mbo[10];
+ size_t mbo_len = 0;
if (hwaddr_aton(cmd, addr)) {
wpa_printf(MSG_DEBUG, "Invalid STA MAC address");
if (os_strstr(cmd, " disassoc_imminent=1"))
req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
+#ifdef CONFIG_MBO
+ pos = os_strstr(cmd, "mbo=");
+ if (pos) {
+ unsigned int mbo_reason, cell_pref, reassoc_delay;
+ u8 *mbo_pos = mbo;
+
+ ret = sscanf(pos, "mbo=%u:%u:%u", &mbo_reason,
+ &reassoc_delay, &cell_pref);
+ if (ret != 3) {
+ wpa_printf(MSG_DEBUG,
+ "MBO requires three arguments: mbo=<reason>:<reassoc_delay>:<cell_pref>");
+ return -1;
+ }
+
+ if (mbo_reason > MBO_TRANSITION_REASON_PREMIUM_AP) {
+ wpa_printf(MSG_DEBUG,
+ "Invalid MBO transition reason code %u",
+ mbo_reason);
+ return -1;
+ }
+
+ /* Valid values for Cellular preference are: 0, 1, 255 */
+ if (cell_pref != 0 && cell_pref != 1 && cell_pref != 255) {
+ wpa_printf(MSG_DEBUG,
+ "Invalid MBO cellular capability %u",
+ cell_pref);
+ return -1;
+ }
+
+ if (reassoc_delay > 65535 ||
+ (reassoc_delay &&
+ !(req_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT))) {
+ wpa_printf(MSG_DEBUG,
+ "MBO: Assoc retry delay is only valid in disassoc imminent mode");
+ return -1;
+ }
+
+ *mbo_pos++ = MBO_ATTR_ID_TRANSITION_REASON;
+ *mbo_pos++ = 1;
+ *mbo_pos++ = mbo_reason;
+ *mbo_pos++ = MBO_ATTR_ID_CELL_DATA_PREF;
+ *mbo_pos++ = 1;
+ *mbo_pos++ = cell_pref;
+
+ if (reassoc_delay) {
+ *mbo_pos++ = MBO_ATTR_ID_ASSOC_RETRY_DELAY;
+ *mbo_pos++ = 2;
+ WPA_PUT_LE16(mbo_pos, reassoc_delay);
+ mbo_pos += 2;
+ }
+
+ mbo_len = mbo_pos - mbo;
+ }
+#endif /* CONFIG_MBO */
+
ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer,
valid_int, bss_term_dur, url,
nei_pos > nei_rep ? nei_rep : NULL,
- nei_pos - nei_rep);
+ nei_pos - nei_rep, mbo_len ? mbo : NULL,
+ mbo_len);
os_free(url);
return ret;
}
} else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
hapd->ext_eapol_frame_io = atoi(value);
#endif /* CONFIG_TESTING_OPTIONS */
+#ifdef CONFIG_MBO
+ } else if (os_strcasecmp(cmd, "mbo_assoc_disallow") == 0) {
+ int val;
+
+ if (!hapd->conf->mbo_enabled)
+ return -1;
+
+ val = atoi(value);
+ if (val < 0 || val > 1)
+ return -1;
+
+ hapd->mbo_assoc_disallow = val;
+ ieee802_11_update_beacons(hapd->iface);
+
+ /*
+ * TODO: Need to configure drivers that do AP MLME offload with
+ * disallowing station logic.
+ */
+#endif /* CONFIG_MBO */
} else {
struct sta_info *sta;
- int vlan_id;
+ struct vlan_description vlan_id;
ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
if (ret)
hapd->conf->deny_mac,
hapd->conf->num_deny_mac, sta->addr,
&vlan_id) &&
- (!vlan_id || vlan_id == sta->vlan_id))
+ (!vlan_id.notempty ||
+ !vlan_compare(&vlan_id, sta->vlan_desc)))
ap_sta_disconnect(
hapd, sta, sta->addr,
WLAN_REASON_UNSPECIFIED);
hapd->conf->accept_mac,
hapd->conf->num_accept_mac,
sta->addr, &vlan_id) ||
- (vlan_id && vlan_id != sta->vlan_id))
+ (vlan_id.notempty &&
+ vlan_compare(&vlan_id, sta->vlan_desc)))
ap_sta_disconnect(
hapd, sta, sta->addr,
WLAN_REASON_UNSPECIFIED);
#define HWSIM_PACKETLEN 1500
#define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
-void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
- size_t len)
+static void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
+ size_t len)
{
struct hostapd_data *hapd = ctx;
const struct ether_header *eth;
static int hostapd_ctrl_test_alloc_fail(struct hostapd_data *hapd, char *cmd)
{
#ifdef WPA_TRACE_BFD
- extern char wpa_trace_fail_func[256];
- extern unsigned int wpa_trace_fail_after;
char *pos;
wpa_trace_fail_after = atoi(cmd);
char *buf, size_t buflen)
{
#ifdef WPA_TRACE_BFD
- extern char wpa_trace_fail_func[256];
- extern unsigned int wpa_trace_fail_after;
-
return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
wpa_trace_fail_func);
#else /* WPA_TRACE_BFD */
static int hostapd_ctrl_test_fail(struct hostapd_data *hapd, char *cmd)
{
#ifdef WPA_TRACE_BFD
- extern char wpa_trace_test_fail_func[256];
- extern unsigned int wpa_trace_test_fail_after;
char *pos;
wpa_trace_test_fail_after = atoi(cmd);
char *buf, size_t buflen)
{
#ifdef WPA_TRACE_BFD
- extern char wpa_trace_test_fail_func[256];
- extern unsigned int wpa_trace_test_fail_after;
-
return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after,
wpa_trace_test_fail_func);
#else /* WPA_TRACE_BFD */
/* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
vendor_id = strtoul(cmd, &pos, 16);
- if (!isblank(*pos))
+ if (!isblank((unsigned char) *pos))
return -EINVAL;
subcmd = strtoul(pos, &pos, 10);
if (*pos != '\0') {
- if (!isblank(*pos++))
+ if (!isblank((unsigned char) *pos++))
return -EINVAL;
data_len = os_strlen(pos);
}
struct hostapd_sta_info *info;
struct os_reltime now;
+ if (!iface->num_sta_seen)
+ return 0;
+
sta_track_expire(iface, 0);
pos = buf;
#endif /* NEED_AP_MLME */
+static int hostapd_ctrl_iface_req_lci(struct hostapd_data *hapd,
+ const char *cmd)
+{
+ u8 addr[ETH_ALEN];
+
+ if (hwaddr_aton(cmd, addr)) {
+ wpa_printf(MSG_INFO, "CTRL: REQ_LCI: Invalid MAC address");
+ return -1;
+ }
+
+ return hostapd_send_lci_req(hapd, addr);
+}
+
+
+static int hostapd_ctrl_iface_req_range(struct hostapd_data *hapd, char *cmd)
+{
+ u8 addr[ETH_ALEN];
+ char *token, *context = NULL;
+ int random_interval, min_ap;
+ u8 responders[ETH_ALEN * RRM_RANGE_REQ_MAX_RESPONDERS];
+ unsigned int n_responders;
+
+ token = str_token(cmd, " ", &context);
+ if (!token || hwaddr_aton(token, addr)) {
+ wpa_printf(MSG_INFO,
+ "CTRL: REQ_RANGE - Bad destination address");
+ return -1;
+ }
+
+ token = str_token(cmd, " ", &context);
+ if (!token)
+ return -1;
+
+ random_interval = atoi(token);
+ if (random_interval < 0 || random_interval > 0xffff)
+ return -1;
+
+ token = str_token(cmd, " ", &context);
+ if (!token)
+ return -1;
+
+ min_ap = atoi(token);
+ if (min_ap <= 0 || min_ap > WLAN_RRM_RANGE_REQ_MAX_MIN_AP)
+ return -1;
+
+ n_responders = 0;
+ while ((token = str_token(cmd, " ", &context))) {
+ if (n_responders == RRM_RANGE_REQ_MAX_RESPONDERS) {
+ wpa_printf(MSG_INFO,
+ "CTRL: REQ_RANGE: Too many responders");
+ return -1;
+ }
+
+ if (hwaddr_aton(token, responders + n_responders * ETH_ALEN)) {
+ wpa_printf(MSG_INFO,
+ "CTRL: REQ_RANGE: Bad responder address");
+ return -1;
+ }
+
+ n_responders++;
+ }
+
+ if (!n_responders) {
+ wpa_printf(MSG_INFO,
+ "CTRL: REQ_RANGE - No FTM responder address");
+ return -1;
+ }
+
+ return hostapd_send_range_req(hapd, addr, random_interval, min_ap,
+ responders, n_responders);
+}
+
+
+static int hostapd_ctrl_iface_set_neighbor(struct hostapd_data *hapd, char *buf)
+{
+ struct wpa_ssid_value ssid;
+ u8 bssid[ETH_ALEN];
+ struct wpabuf *nr, *lci = NULL, *civic = NULL;
+ char *tmp;
+ int ret;
+
+ if (!(hapd->conf->radio_measurements[0] &
+ WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
+ wpa_printf(MSG_ERROR,
+ "CTRL: SET_NEIGHBOR: Neighbor report is not enabled");
+ return -1;
+ }
+
+ if (hwaddr_aton(buf, bssid)) {
+ wpa_printf(MSG_ERROR, "CTRL: SET_NEIGHBOR: Bad BSSID");
+ return -1;
+ }
+
+ tmp = os_strstr(buf, "ssid=");
+ if (!tmp || ssid_parse(tmp + 5, &ssid)) {
+ wpa_printf(MSG_ERROR,
+ "CTRL: SET_NEIGHBOR: Bad or missing SSID");
+ return -1;
+ }
+ buf = os_strchr(tmp + 6, tmp[5] == '"' ? '"' : ' ');
+ if (!buf)
+ return -1;
+
+ tmp = os_strstr(buf, "nr=");
+ if (!tmp) {
+ wpa_printf(MSG_ERROR,
+ "CTRL: SET_NEIGHBOR: Missing Neighbor Report element");
+ return -1;
+ }
+
+ buf = os_strchr(tmp, ' ');
+ if (buf)
+ *buf++ = '\0';
+
+ nr = wpabuf_parse_bin(tmp + 3);
+ if (!nr) {
+ wpa_printf(MSG_ERROR,
+ "CTRL: SET_NEIGHBOR: Bad Neighbor Report element");
+ return -1;
+ }
+
+ if (!buf)
+ goto set;
+
+ tmp = os_strstr(buf, "lci=");
+ if (tmp) {
+ buf = os_strchr(tmp, ' ');
+ if (buf)
+ *buf++ = '\0';
+ lci = wpabuf_parse_bin(tmp + 4);
+ if (!lci) {
+ wpa_printf(MSG_ERROR,
+ "CTRL: SET_NEIGHBOR: Bad LCI subelement");
+ wpabuf_free(nr);
+ return -1;
+ }
+ }
+
+ if (!buf)
+ goto set;
+
+ tmp = os_strstr(buf, "civic=");
+ if (tmp) {
+ buf = os_strchr(tmp, ' ');
+ if (buf)
+ *buf++ = '\0';
+ civic = wpabuf_parse_bin(tmp + 6);
+ if (!civic) {
+ wpa_printf(MSG_ERROR,
+ "CTRL: SET_NEIGHBOR: Bad civic subelement");
+ wpabuf_free(nr);
+ wpabuf_free(lci);
+ return -1;
+ }
+ }
+
+set:
+ ret = hostapd_neighbor_set(hapd, bssid, &ssid, nr, lci, civic);
+
+ wpabuf_free(nr);
+ wpabuf_free(lci);
+ wpabuf_free(civic);
+
+ return ret;
+}
+
+
+static int hostapd_ctrl_iface_remove_neighbor(struct hostapd_data *hapd,
+ char *buf)
+{
+ struct wpa_ssid_value ssid;
+ u8 bssid[ETH_ALEN];
+ char *tmp;
+
+ if (hwaddr_aton(buf, bssid)) {
+ wpa_printf(MSG_ERROR, "CTRL: REMOVE_NEIGHBOR: Bad BSSID");
+ return -1;
+ }
+
+ tmp = os_strstr(buf, "ssid=");
+ if (!tmp || ssid_parse(tmp + 5, &ssid)) {
+ wpa_printf(MSG_ERROR,
+ "CTRL: REMOVE_NEIGHBORr: Bad or missing SSID");
+ return -1;
+ }
+
+ return hostapd_neighbor_remove(hapd, bssid, &ssid);
+}
+
+
+static int hostapd_ctrl_driver_flags(struct hostapd_iface *iface, char *buf,
+ size_t buflen)
+{
+ int ret, i;
+ char *pos, *end;
+
+ ret = os_snprintf(buf, buflen, "%016llX:\n",
+ (long long unsigned) iface->drv_flags);
+ if (os_snprintf_error(buflen, ret))
+ return -1;
+
+ pos = buf + ret;
+ end = buf + buflen;
+
+ for (i = 0; i < 64; i++) {
+ if (iface->drv_flags & (1LLU << i)) {
+ ret = os_snprintf(pos, end - pos, "%s\n",
+ driver_flag_to_string(1LLU << i));
+ if (os_snprintf_error(end - pos, ret))
+ return -1;
+ pos += ret;
+ }
+ }
+
+ return pos - buf;
+}
+
+
static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
char *buf, char *reply,
int reply_size,
- struct sockaddr_un *from,
+ struct sockaddr_storage *from,
socklen_t fromlen)
{
int reply_len, res;
} else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
reply_len = -1;
+#ifdef CONFIG_TAXONOMY
+ } else if (os_strncmp(buf, "SIGNATURE ", 10) == 0) {
+ reply_len = hostapd_ctrl_iface_signature(hapd, buf + 10,
+ reply, reply_size);
+#endif /* CONFIG_TAXONOMY */
+ } else if (os_strncmp(buf, "POLL_STA ", 9) == 0) {
+ if (hostapd_ctrl_iface_poll_sta(hapd, buf + 9))
+ reply_len = -1;
} else if (os_strcmp(buf, "STOP_AP") == 0) {
if (hostapd_ctrl_iface_stop_ap(hapd))
reply_len = -1;
reply_len = hostapd_ctrl_iface_track_sta_list(
hapd, reply, reply_size);
#endif /* NEED_AP_MLME */
+ } else if (os_strcmp(buf, "PMKSA") == 0) {
+ reply_len = hostapd_ctrl_iface_pmksa_list(hapd, reply,
+ reply_size);
+ } else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
+ hostapd_ctrl_iface_pmksa_flush(hapd);
+ } else if (os_strncmp(buf, "SET_NEIGHBOR ", 13) == 0) {
+ if (hostapd_ctrl_iface_set_neighbor(hapd, buf + 13))
+ reply_len = -1;
+ } else if (os_strncmp(buf, "REMOVE_NEIGHBOR ", 16) == 0) {
+ if (hostapd_ctrl_iface_remove_neighbor(hapd, buf + 16))
+ reply_len = -1;
+ } else if (os_strncmp(buf, "REQ_LCI ", 8) == 0) {
+ if (hostapd_ctrl_iface_req_lci(hapd, buf + 8))
+ reply_len = -1;
+ } else if (os_strncmp(buf, "REQ_RANGE ", 10) == 0) {
+ if (hostapd_ctrl_iface_req_range(hapd, buf + 10))
+ reply_len = -1;
+ } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
+ reply_len = hostapd_ctrl_driver_flags(hapd->iface, reply,
+ reply_size);
} else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
struct hostapd_data *hapd = eloop_ctx;
char buf[4096];
int res;
- struct sockaddr_un from;
+ struct sockaddr_storage from;
socklen_t fromlen = sizeof(from);
- char *reply;
+ char *reply, *pos = buf;
const int reply_size = 4096;
int reply_len;
int level = MSG_DEBUG;
+#ifdef CONFIG_CTRL_IFACE_UDP
+ unsigned char lcookie[COOKIE_LEN];
+#endif /* CONFIG_CTRL_IFACE_UDP */
res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
(struct sockaddr *) &from, &fromlen);
return;
}
buf[res] = '\0';
- if (os_strcmp(buf, "PING") == 0)
- level = MSG_EXCESSIVE;
- wpa_hexdump_ascii(level, "RX ctrl_iface", (u8 *) buf, res);
reply = os_malloc(reply_size);
if (reply == NULL) {
return;
}
- reply_len = hostapd_ctrl_iface_receive_process(hapd, buf,
+#ifdef CONFIG_CTRL_IFACE_UDP
+ if (os_strcmp(buf, "GET_COOKIE") == 0) {
+ os_memcpy(reply, "COOKIE=", 7);
+ wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
+ cookie, COOKIE_LEN);
+ reply_len = 7 + 2 * COOKIE_LEN;
+ goto done;
+ }
+
+ if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
+ hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "CTRL: No cookie in the request - drop request");
+ os_free(reply);
+ return;
+ }
+
+ if (os_memcmp(cookie, lcookie, COOKIE_LEN) != 0) {
+ wpa_printf(MSG_DEBUG,
+ "CTRL: Invalid cookie in the request - drop request");
+ os_free(reply);
+ return;
+ }
+
+ pos = buf + 7 + 2 * COOKIE_LEN;
+ while (*pos == ' ')
+ pos++;
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
+ if (os_strcmp(pos, "PING") == 0)
+ level = MSG_EXCESSIVE;
+ wpa_hexdump_ascii(level, "RX ctrl_iface", pos, res);
+
+ reply_len = hostapd_ctrl_iface_receive_process(hapd, pos,
reply, reply_size,
&from, fromlen);
+#ifdef CONFIG_CTRL_IFACE_UDP
+done:
+#endif /* CONFIG_CTRL_IFACE_UDP */
if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
fromlen) < 0) {
wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
}
+#ifndef CONFIG_CTRL_IFACE_UDP
static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
{
char *buf;
buf[len - 1] = '\0';
return buf;
}
+#endif /* CONFIG_CTRL_IFACE_UDP */
static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
{
+#ifdef CONFIG_CTRL_IFACE_UDP
+ int port = HOSTAPD_CTRL_IFACE_PORT;
+ char p[32] = { 0 };
+ char port_str[40], *tmp;
+ char *pos;
+ struct addrinfo hints = { 0 }, *res, *saveres;
+ int n;
+
+ if (hapd->ctrl_sock > -1) {
+ wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
+ return 0;
+ }
+
+ if (hapd->conf->ctrl_interface == NULL)
+ return 0;
+
+ pos = os_strstr(hapd->conf->ctrl_interface, "udp:");
+ if (pos) {
+ pos += 4;
+ port = atoi(pos);
+ if (port <= 0) {
+ wpa_printf(MSG_ERROR, "Invalid ctrl_iface UDP port");
+ goto fail;
+ }
+ }
+
+ dl_list_init(&hapd->ctrl_dst);
+ hapd->ctrl_sock = -1;
+ os_get_random(cookie, COOKIE_LEN);
+
+#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
+ hints.ai_flags = AI_PASSIVE;
+#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
+
+#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
+ hints.ai_family = AF_INET6;
+#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
+ hints.ai_family = AF_INET;
+#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
+ hints.ai_socktype = SOCK_DGRAM;
+
+try_again:
+ os_snprintf(p, sizeof(p), "%d", port);
+ n = getaddrinfo(NULL, p, &hints, &res);
+ if (n) {
+ wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n));
+ goto fail;
+ }
+
+ saveres = res;
+ hapd->ctrl_sock = socket(res->ai_family, res->ai_socktype,
+ res->ai_protocol);
+ if (hapd->ctrl_sock < 0) {
+ wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
+ goto fail;
+ }
+
+ if (bind(hapd->ctrl_sock, res->ai_addr, res->ai_addrlen) < 0) {
+ port--;
+ if ((HOSTAPD_CTRL_IFACE_PORT - port) <
+ HOSTAPD_CTRL_IFACE_PORT_LIMIT && !pos)
+ goto try_again;
+ wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
+ goto fail;
+ }
+
+ freeaddrinfo(saveres);
+
+ os_snprintf(port_str, sizeof(port_str), "udp:%d", port);
+ tmp = os_strdup(port_str);
+ if (tmp) {
+ os_free(hapd->conf->ctrl_interface);
+ hapd->conf->ctrl_interface = tmp;
+ }
+ wpa_printf(MSG_DEBUG, "ctrl_iface_init UDP port: %d", port);
+
+ if (eloop_register_read_sock(hapd->ctrl_sock,
+ hostapd_ctrl_iface_receive, hapd, NULL) <
+ 0) {
+ hostapd_ctrl_iface_deinit(hapd);
+ return -1;
+ }
+
+ hapd->msg_ctx = hapd;
+ wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
+
+ return 0;
+
+fail:
+ if (hapd->ctrl_sock >= 0)
+ close(hapd->ctrl_sock);
+ return -1;
+#else /* CONFIG_CTRL_IFACE_UDP */
struct sockaddr_un addr;
int s = -1;
char *fname = NULL;
return 0;
}
+ dl_list_init(&hapd->ctrl_dst);
+
if (hapd->conf->ctrl_interface == NULL)
return 0;
os_free(fname);
}
return -1;
+#endif /* CONFIG_CTRL_IFACE_UDP */
}
struct wpa_ctrl_dst *dst, *prev;
if (hapd->ctrl_sock > -1) {
+#ifndef CONFIG_CTRL_IFACE_UDP
char *fname;
+#endif /* !CONFIG_CTRL_IFACE_UDP */
+
eloop_unregister_read_sock(hapd->ctrl_sock);
close(hapd->ctrl_sock);
hapd->ctrl_sock = -1;
+#ifndef CONFIG_CTRL_IFACE_UDP
fname = hostapd_ctrl_iface_path(hapd);
if (fname)
unlink(fname);
strerror(errno));
}
}
+#endif /* !CONFIG_CTRL_IFACE_UDP */
}
- dst = hapd->ctrl_dst;
- hapd->ctrl_dst = NULL;
- while (dst) {
- prev = dst;
- dst = dst->next;
- os_free(prev);
- }
+ dl_list_for_each_safe(dst, prev, &hapd->ctrl_dst, struct wpa_ctrl_dst,
+ list)
+ os_free(dst);
#ifdef CONFIG_TESTING_OPTIONS
l2_packet_deinit(hapd->l2_test);
static int hostapd_global_ctrl_iface_attach(struct hapd_interfaces *interfaces,
- struct sockaddr_un *from,
+ 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, sizeof(struct sockaddr_un));
- dst->addrlen = fromlen;
- dst->debug_level = MSG_INFO;
- dst->next = interfaces->global_ctrl_dst;
- interfaces->global_ctrl_dst = dst;
- wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached (global)",
- from->sun_path,
- fromlen - offsetof(struct sockaddr_un, sun_path));
- return 0;
+ return ctrl_iface_attach(&interfaces->global_ctrl_dst, from, fromlen);
}
static int hostapd_global_ctrl_iface_detach(struct hapd_interfaces *interfaces,
- struct sockaddr_un *from,
+ struct sockaddr_storage *from,
socklen_t fromlen)
{
- struct wpa_ctrl_dst *dst, *prev = NULL;
-
- dst = interfaces->global_ctrl_dst;
- while (dst) {
- if (fromlen == dst->addrlen &&
- os_memcmp(from->sun_path, dst->addr.sun_path,
- fromlen - offsetof(struct sockaddr_un, sun_path))
- == 0) {
- wpa_hexdump(MSG_DEBUG,
- "CTRL_IFACE monitor detached (global)",
- from->sun_path,
- fromlen -
- offsetof(struct sockaddr_un, sun_path));
- if (prev == NULL)
- interfaces->global_ctrl_dst = dst->next;
- else
- prev->next = dst->next;
- os_free(dst);
- return 0;
- }
- prev = dst;
- dst = dst->next;
- }
- return -1;
+ return ctrl_iface_detach(&interfaces->global_ctrl_dst, from, fromlen);
}
static int
+hostapd_global_ctrl_iface_interfaces(struct hapd_interfaces *interfaces,
+ const char *input,
+ char *reply, int reply_size)
+{
+ size_t i, j;
+ int res;
+ char *pos, *end;
+ struct hostapd_iface *iface;
+ int show_ctrl = 0;
+
+ if (input)
+ show_ctrl = !!os_strstr(input, "ctrl");
+
+ pos = reply;
+ end = reply + reply_size;
+
+ for (i = 0; i < interfaces->count; i++) {
+ iface = interfaces->iface[i];
+
+ for (j = 0; j < iface->num_bss; j++) {
+ struct hostapd_bss_config *conf;
+
+ conf = iface->conf->bss[j];
+ if (show_ctrl)
+ res = os_snprintf(pos, end - pos,
+ "%s ctrl_iface=%s\n",
+ conf->iface,
+ conf->ctrl_interface ?
+ conf->ctrl_interface : "N/A");
+ else
+ res = os_snprintf(pos, end - pos, "%s\n",
+ conf->iface);
+ if (os_snprintf_error(end - pos, res)) {
+ *pos = '\0';
+ return pos - reply;
+ }
+ pos += res;
+ }
+ }
+
+ return pos - reply;
+}
+
+
+static int
hostapd_global_ctrl_iface_dup_network(struct hapd_interfaces *interfaces,
char *cmd)
{
const char *ifname,
char *buf, char *reply,
int reply_size,
- struct sockaddr_un *from,
+ struct sockaddr_storage *from,
socklen_t fromlen)
{
struct hostapd_data *hapd;
void *sock_ctx)
{
void *interfaces = eloop_ctx;
- char buf[256];
+ char buffer[256], *buf = buffer;
int res;
- struct sockaddr_un from;
+ struct sockaddr_storage from;
socklen_t fromlen = sizeof(from);
char *reply;
int reply_len;
const int reply_size = 4096;
+#ifdef CONFIG_CTRL_IFACE_UDP
+ unsigned char lcookie[COOKIE_LEN];
+#endif /* CONFIG_CTRL_IFACE_UDP */
- res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
+ res = recvfrom(sock, buffer, sizeof(buffer) - 1, 0,
(struct sockaddr *) &from, &fromlen);
if (res < 0) {
wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
os_memcpy(reply, "OK\n", 3);
reply_len = 3;
+#ifdef CONFIG_CTRL_IFACE_UDP
+ if (os_strcmp(buf, "GET_COOKIE") == 0) {
+ os_memcpy(reply, "COOKIE=", 7);
+ wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
+ gcookie, COOKIE_LEN);
+ reply_len = 7 + 2 * COOKIE_LEN;
+ goto send_reply;
+ }
+
+ if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
+ hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "CTRL: No cookie in the request - drop request");
+ os_free(reply);
+ return;
+ }
+
+ if (os_memcmp(gcookie, lcookie, COOKIE_LEN) != 0) {
+ wpa_printf(MSG_DEBUG,
+ "CTRL: Invalid cookie in the request - drop request");
+ os_free(reply);
+ return;
+ }
+
+ buf += 7 + 2 * COOKIE_LEN;
+ while (*buf == ' ')
+ buf++;
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
if (os_strncmp(buf, "IFNAME=", 7) == 0) {
char *pos = os_strchr(buf + 7, ' ');
reply_len = -1;
#ifdef CONFIG_MODULE_TESTS
} else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
- int hapd_module_tests(void);
if (hapd_module_tests() < 0)
reply_len = -1;
#endif /* CONFIG_MODULE_TESTS */
reply_len = os_snprintf(reply, reply_size, "OK\n");
else
reply_len = -1;
+ } else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
+ reply_len = hostapd_global_ctrl_iface_interfaces(
+ interfaces, buf + 10, reply, sizeof(buffer));
+ } else if (os_strcmp(buf, "TERMINATE") == 0) {
+ eloop_terminate();
} else {
wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
"ignored");
}
+#ifndef CONFIG_CTRL_IFACE_UDP
static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
{
char *buf;
buf[len - 1] = '\0';
return buf;
}
+#endif /* CONFIG_CTRL_IFACE_UDP */
int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
{
+#ifdef CONFIG_CTRL_IFACE_UDP
+ int port = HOSTAPD_GLOBAL_CTRL_IFACE_PORT;
+ char p[32] = { 0 };
+ char *pos;
+ struct addrinfo hints = { 0 }, *res, *saveres;
+ int n;
+
+ if (interface->global_ctrl_sock > -1) {
+ wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
+ return 0;
+ }
+
+ if (interface->global_iface_path == NULL)
+ return 0;
+
+ pos = os_strstr(interface->global_iface_path, "udp:");
+ if (pos) {
+ pos += 4;
+ port = atoi(pos);
+ if (port <= 0) {
+ wpa_printf(MSG_ERROR, "Invalid global ctrl UDP port");
+ goto fail;
+ }
+ }
+
+ dl_list_init(&interface->global_ctrl_dst);
+ interface->global_ctrl_sock = -1;
+ os_get_random(gcookie, COOKIE_LEN);
+
+#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
+ hints.ai_flags = AI_PASSIVE;
+#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
+
+#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
+ hints.ai_family = AF_INET6;
+#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
+ hints.ai_family = AF_INET;
+#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
+ hints.ai_socktype = SOCK_DGRAM;
+
+try_again:
+ os_snprintf(p, sizeof(p), "%d", port);
+ n = getaddrinfo(NULL, p, &hints, &res);
+ if (n) {
+ wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n));
+ goto fail;
+ }
+
+ saveres = res;
+ interface->global_ctrl_sock = socket(res->ai_family, res->ai_socktype,
+ res->ai_protocol);
+ if (interface->global_ctrl_sock < 0) {
+ wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
+ goto fail;
+ }
+
+ if (bind(interface->global_ctrl_sock, res->ai_addr, res->ai_addrlen) <
+ 0) {
+ port++;
+ if ((port - HOSTAPD_GLOBAL_CTRL_IFACE_PORT) <
+ HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT && !pos)
+ goto try_again;
+ wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
+ goto fail;
+ }
+
+ freeaddrinfo(saveres);
+
+ wpa_printf(MSG_DEBUG, "global ctrl_iface_init UDP port: %d", port);
+
+ if (eloop_register_read_sock(interface->global_ctrl_sock,
+ hostapd_global_ctrl_iface_receive,
+ interface, NULL) < 0) {
+ hostapd_global_ctrl_iface_deinit(interface);
+ return -1;
+ }
+
+ return 0;
+
+fail:
+ if (interface->global_ctrl_sock >= 0)
+ close(interface->global_ctrl_sock);
+ return -1;
+#else /* CONFIG_CTRL_IFACE_UDP */
struct sockaddr_un addr;
int s = -1;
char *fname = NULL;
os_free(fname);
}
return -1;
+#endif /* CONFIG_CTRL_IFACE_UDP */
}
void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
{
+#ifndef CONFIG_CTRL_IFACE_UDP
char *fname = NULL;
+#endif /* CONFIG_CTRL_IFACE_UDP */
struct wpa_ctrl_dst *dst, *prev;
if (interfaces->global_ctrl_sock > -1) {
eloop_unregister_read_sock(interfaces->global_ctrl_sock);
close(interfaces->global_ctrl_sock);
interfaces->global_ctrl_sock = -1;
+#ifndef CONFIG_CTRL_IFACE_UDP
fname = hostapd_global_ctrl_iface_path(interfaces);
if (fname) {
unlink(fname);
strerror(errno));
}
}
+#endif /* CONFIG_CTRL_IFACE_UDP */
}
os_free(interfaces->global_iface_path);
interfaces->global_iface_path = NULL;
- dst = interfaces->global_ctrl_dst;
- interfaces->global_ctrl_dst = NULL;
- while (dst) {
- prev = dst;
- dst = dst->next;
- os_free(prev);
- }
+ dl_list_for_each_safe(dst, prev, &interfaces->global_ctrl_dst,
+ struct wpa_ctrl_dst, list)
+ os_free(dst);
}
const char *buf, size_t len)
{
struct wpa_ctrl_dst *dst, *next;
+ struct dl_list *ctrl_dst;
struct msghdr msg;
int idx;
struct iovec io[2];
if (type != WPA_MSG_ONLY_GLOBAL) {
s = hapd->ctrl_sock;
- dst = hapd->ctrl_dst;
+ ctrl_dst = &hapd->ctrl_dst;
} else {
s = hapd->iface->interfaces->global_ctrl_sock;
- dst = hapd->iface->interfaces->global_ctrl_dst;
+ ctrl_dst = &hapd->iface->interfaces->global_ctrl_dst;
}
- if (s < 0 || dst == NULL)
+ if (s < 0 || dl_list_empty(ctrl_dst))
return;
os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
msg.msg_iovlen = 2;
idx = 0;
- while (dst) {
- next = dst->next;
+ dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) {
if (level >= dst->debug_level) {
- wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
- (u8 *) dst->addr.sun_path, dst->addrlen -
- offsetof(struct sockaddr_un, sun_path));
+ sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor send",
+ &dst->addr, dst->addrlen);
msg.msg_name = &dst->addr;
msg.msg_namelen = dst->addrlen;
if (sendmsg(s, &msg, 0) < 0) {
dst->errors = 0;
}
idx++;
- dst = next;
}
}
# Driver interface for drivers using the nl80211 kernel interface
CONFIG_DRIVER_NL80211=y
+# QCA vendor extensions to nl80211
+#CONFIG_DRIVER_NL80211_QCA=y
+
# driver_nl80211.c requires libnl. If you are compiling it yourself
# you may need to point hostapd to your version of libnl.
#
# Should we use epoll instead of select? Select is used by default.
#CONFIG_ELOOP_EPOLL=y
+# Should we use kqueue instead of select? Select is used by default.
+#CONFIG_ELOOP_KQUEUE=y
+
# Select TLS implementation
# openssl = OpenSSL (default)
# gnutls = GnuTLS
# http://wireless.kernel.org/en/users/Documentation/acs
#
#CONFIG_ACS=y
+
+# Multiband Operation support
+# These extentions facilitate efficient use of multiple frequency bands
+# available to the AP and the devices that may associate with it.
+#CONFIG_MBO=y
+
+# Client Taxonomy
+# Has the AP retain the Probe Request and (Re)Association Request frames from
+# a client, from which a signature can be produced which can identify the model
+# of client device like "Nexus 6P" or "iPhone 5s".
+#CONFIG_TAXONOMY=y
#include "utils/includes.h"
#include "utils/common.h"
+#include "utils/module_tests.h"
int hapd_module_tests(void)
{
/*
* HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator
- * Copyright (c) 2005-2007, 2012-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2005-2007, 2012-2016, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
f = fopen(fname, "r");
if (f == NULL) {
- printf("Could not open GSM tripler data file '%s'\n", fname);
+ printf("Could not open GSM triplet data file '%s'\n", fname);
return -1;
}
}
/* IMSI */
- pos2 = strchr(pos, ':');
- if (pos2 == NULL) {
- printf("%s:%d - Invalid IMSI (%s)\n",
- fname, line, pos);
- ret = -1;
- break;
- }
- *pos2 = '\0';
- if (strlen(pos) >= sizeof(g->imsi)) {
- printf("%s:%d - Too long IMSI (%s)\n",
- fname, line, pos);
+ pos2 = NULL;
+ pos = str_token(buf, ":", &pos2);
+ if (!pos || os_strlen(pos) >= sizeof(g->imsi)) {
+ printf("%s:%d - Invalid IMSI\n", fname, line);
ret = -1;
break;
}
os_strlcpy(g->imsi, pos, sizeof(g->imsi));
- pos = pos2 + 1;
/* Kc */
- pos2 = strchr(pos, ':');
- if (pos2 == NULL) {
- printf("%s:%d - Invalid Kc (%s)\n", fname, line, pos);
- ret = -1;
- break;
- }
- *pos2 = '\0';
- if (strlen(pos) != 16 || hexstr2bin(pos, g->kc, 8)) {
- printf("%s:%d - Invalid Kc (%s)\n", fname, line, pos);
+ pos = str_token(buf, ":", &pos2);
+ if (!pos || os_strlen(pos) != 16 || hexstr2bin(pos, g->kc, 8)) {
+ printf("%s:%d - Invalid Kc\n", fname, line);
ret = -1;
break;
}
- pos = pos2 + 1;
/* SRES */
- pos2 = strchr(pos, ':');
- if (pos2 == NULL) {
- printf("%s:%d - Invalid SRES (%s)\n", fname, line,
- pos);
+ pos = str_token(buf, ":", &pos2);
+ if (!pos || os_strlen(pos) != 8 ||
+ hexstr2bin(pos, g->sres, 4)) {
+ printf("%s:%d - Invalid SRES\n", fname, line);
ret = -1;
break;
}
- *pos2 = '\0';
- if (strlen(pos) != 8 || hexstr2bin(pos, g->sres, 4)) {
- printf("%s:%d - Invalid SRES (%s)\n", fname, line,
- pos);
- ret = -1;
- break;
- }
- pos = pos2 + 1;
/* RAND */
- pos2 = strchr(pos, ':');
- if (pos2)
- *pos2 = '\0';
- if (strlen(pos) != 32 || hexstr2bin(pos, g->_rand, 16)) {
- printf("%s:%d - Invalid RAND (%s)\n", fname, line,
- pos);
+ pos = str_token(buf, ":", &pos2);
+ if (!pos || os_strlen(pos) != 32 ||
+ hexstr2bin(pos, g->_rand, 16)) {
+ printf("%s:%d - Invalid RAND\n", fname, line);
ret = -1;
break;
}
- pos = pos2 + 1;
g->next = gsm_db;
gsm_db = g;
}
/* IMSI */
- pos2 = strchr(pos, ' ');
- if (pos2 == NULL) {
- printf("%s:%d - Invalid IMSI (%s)\n",
- fname, line, pos);
- ret = -1;
- break;
- }
- *pos2 = '\0';
- if (strlen(pos) >= sizeof(m->imsi)) {
- printf("%s:%d - Too long IMSI (%s)\n",
- fname, line, pos);
+ pos2 = NULL;
+ pos = str_token(buf, " ", &pos2);
+ if (!pos || os_strlen(pos) >= sizeof(m->imsi)) {
+ printf("%s:%d - Invalid IMSI\n", fname, line);
ret = -1;
break;
}
os_strlcpy(m->imsi, pos, sizeof(m->imsi));
- pos = pos2 + 1;
/* Ki */
- pos2 = strchr(pos, ' ');
- if (pos2 == NULL) {
- printf("%s:%d - Invalid Ki (%s)\n", fname, line, pos);
+ pos = str_token(buf, " ", &pos2);
+ if (!pos || os_strlen(pos) != 32 ||
+ hexstr2bin(pos, m->ki, 16)) {
+ printf("%s:%d - Invalid Ki\n", fname, line);
ret = -1;
break;
}
- *pos2 = '\0';
- if (strlen(pos) != 32 || hexstr2bin(pos, m->ki, 16)) {
- printf("%s:%d - Invalid Ki (%s)\n", fname, line, pos);
- ret = -1;
- break;
- }
- pos = pos2 + 1;
/* OPc */
- pos2 = strchr(pos, ' ');
- if (pos2 == NULL) {
- printf("%s:%d - Invalid OPc (%s)\n", fname, line, pos);
- ret = -1;
- break;
- }
- *pos2 = '\0';
- if (strlen(pos) != 32 || hexstr2bin(pos, m->opc, 16)) {
- printf("%s:%d - Invalid OPc (%s)\n", fname, line, pos);
+ pos = str_token(buf, " ", &pos2);
+ if (!pos || os_strlen(pos) != 32 ||
+ hexstr2bin(pos, m->opc, 16)) {
+ printf("%s:%d - Invalid OPc\n", fname, line);
ret = -1;
break;
}
- pos = pos2 + 1;
/* AMF */
- pos2 = strchr(pos, ' ');
- if (pos2 == NULL) {
- printf("%s:%d - Invalid AMF (%s)\n", fname, line, pos);
- ret = -1;
- break;
- }
- *pos2 = '\0';
- if (strlen(pos) != 4 || hexstr2bin(pos, m->amf, 2)) {
- printf("%s:%d - Invalid AMF (%s)\n", fname, line, pos);
+ pos = str_token(buf, " ", &pos2);
+ if (!pos || os_strlen(pos) != 4 || hexstr2bin(pos, m->amf, 2)) {
+ printf("%s:%d - Invalid AMF\n", fname, line);
ret = -1;
break;
}
- pos = pos2 + 1;
/* SQN */
- pos2 = strchr(pos, ' ');
- if (pos2)
- *pos2 = '\0';
- if (strlen(pos) != 12 || hexstr2bin(pos, m->sqn, 6)) {
- printf("%s:%d - Invalid SEQ (%s)\n", fname, line, pos);
+ pos = str_token(buf, " ", &pos2);
+ if (!pos || os_strlen(pos) != 12 ||
+ hexstr2bin(pos, m->sqn, 6)) {
+ printf("%s:%d - Invalid SEQ\n", fname, line);
ret = -1;
break;
}
- if (pos2) {
- pos = pos2 + 1;
+ pos = str_token(buf, " ", &pos2);
+ if (pos) {
m->res_len = atoi(pos);
if (m->res_len &&
(m->res_len < EAP_AKA_RES_MIN_LEN ||
m->res_len > EAP_AKA_RES_MAX_LEN)) {
- printf("%s:%d - Invalid RES_len (%s)\n",
- fname, line, pos);
+ printf("%s:%d - Invalid RES_len\n",
+ fname, line);
ret = -1;
break;
}
{
printf("HLR/AuC testing gateway for hostapd EAP-SIM/AKA "
"database/authenticator\n"
- "Copyright (c) 2005-2007, 2012-2013, Jouni Malinen <j@w1.fi>\n"
+ "Copyright (c) 2005-2016, Jouni Malinen <j@w1.fi>\n"
"\n"
"usage:\n"
"hlr_auc_gw [-hu] [-s<socket path>] [-g<triplet file>] "
# AP netdevice name (without 'ap' postfix, i.e., wlan0 uses wlan0ap for
# management frames with the Host AP driver); wlan0 with many nl80211 drivers
+# Note: This attribute can be overridden by the values supplied with the '-i'
+# command line parameter.
interface=wlan0
# In case of atheros and nl80211 driver interfaces, an additional
# ieee80211d=1 and local_pwr_constraint configured.
#spectrum_mgmt_required=1
-# Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g,
-# ad = IEEE 802.11ad (60 GHz); a/g options are used with IEEE 802.11n, too, to
-# specify band). When using ACS (see channel parameter), a special value "any"
-# can be used to indicate that any support band can be used. This special case
-# is currently supported only with drivers with which offloaded ACS is used.
+# Operation mode (a = IEEE 802.11a (5 GHz), b = IEEE 802.11b (2.4 GHz),
+# g = IEEE 802.11g (2.4 GHz), ad = IEEE 802.11ad (60 GHz); a/g options are used
+# with IEEE 802.11n (HT), too, to specify band). For IEEE 802.11ac (VHT), this
+# needs to be set to hw_mode=a. When using ACS (see channel parameter), a
+# special value "any" can be used to indicate that any support band can be used.
+# This special case is currently supported only with drivers with which
+# offloaded ACS is used.
# Default: IEEE 802.11b
hw_mode=g
# Channel list restriction. This option allows hostapd to select one of the
# provided channels when a channel should be automatically selected.
# Channel list can be provided as range using hyphen ('-') or individual
-# channels can be specified by space (' ') seperated values
+# channels can be specified by space (' ') separated values
# Default: all channels allowed in selected hw_mode
#chanlist=100 104 108 112 116
#chanlist=1 6 11-13
# (default: 2007)
max_num_sta=255
-# RTS/CTS threshold; 2347 = disabled (default); range 0..2347
+# RTS/CTS threshold; -1 = disabled (default); range -1..65535
# If this field is not included in hostapd.conf, hostapd will not control
# RTS threshold and 'iwconfig wlan# rts <val>' can be used to set it.
-rts_threshold=2347
+rts_threshold=-1
-# Fragmentation threshold; 2346 = disabled (default); range 256..2346
+# Fragmentation threshold; -1 = disabled (default); range -1, 256..2346
# If this field is not included in hostapd.conf, hostapd will not control
# fragmentation threshold and 'iwconfig wlan# frag <val>' can be used to set
# it.
-fragm_threshold=2346
+fragm_threshold=-1
# Rate configuration
# Default is to enable all rates supported by the hardware. This configuration
# requests for broadcast SSID
ignore_broadcast_ssid=0
-# Additional vendor specfic elements for Beacon and Probe Response frames
+# Do not reply to broadcast Probe Request frames from unassociated STA if there
+# is no room for additional stations (max_num_sta). This can be used to
+# discourage a STA from trying to associate with this AP if the association
+# would be rejected due to maximum STA limit.
+# Default: 0 (disabled)
+#no_probe_resp_if_max_sta=0
+
+# Additional vendor specific elements for Beacon and Probe Response frames
# This parameter can be used to add additional vendor specific element(s) into
# the end of the Beacon and Probe Response frames. The format for these
# element(s) is a hexdump of the raw information elements (id+len+payload for
# one or more elements)
#vendor_elements=dd0411223301
+# Additional vendor specific elements for (Re)Association Response frames
+# This parameter can be used to add additional vendor specific element(s) into
+# the end of the (Re)Association Response frames. The format for these
+# element(s) is a hexdump of the raw information elements (id+len+payload for
+# one or more elements)
+#assocresp_elements=dd0411223301
+
# TX queue parameters (EDCF / bursting)
# tx_queue_<queue name>_<param>
# queues: data0, data1, data2, data3, after_beacon, beacon
# 0 = disabled (default)
# 1 = enabled
# Note: You will also need to enable WMM for full HT functionality.
+# Note: hw_mode=g (2.4 GHz) and hw_mode=a (5 GHz) is used to specify the band.
#ieee80211n=1
# ht_capab: HT capabilities (list of flags)
# 0 = disabled (default)
# 1 = enabled
# Note: You will also need to enable WMM for full VHT functionality.
+# Note: hw_mode=a is used to specify that 5 GHz band is used with VHT.
#ieee80211ac=1
# vht_capab: VHT capabilities (list of flags)
# VHT TXOP PS: [VHT-TXOP-PS]
# Indicates whether or not the AP supports VHT TXOP Power Save Mode
# or whether or not the STA is in VHT TXOP Power Save mode
-# 0 = VHT AP doesnt support VHT TXOP PS mode (OR) VHT Sta not in VHT TXOP PS
+# 0 = VHT AP doesn't support VHT TXOP PS mode (OR) VHT STA not in VHT TXOP PS
# mode
-# 1 = VHT AP supports VHT TXOP PS mode (OR) VHT Sta is in VHT TXOP power save
+# 1 = VHT AP supports VHT TXOP PS mode (OR) VHT STA is in VHT TXOP power save
# mode
#
# +HTC-VHT Capable: [HTC-VHT]
#
#vht_oper_centr_freq_seg1_idx=159
+# Workaround to use station's nsts capability in (Re)Association Response frame
+# This may be needed with some deployed devices as an interoperability
+# workaround for beamforming if the AP's capability is greater than the
+# station's capability. This is disabled by default and can be enabled by
+# setting use_sta_nsts=1.
+#use_sta_nsts=0
+
##### IEEE 802.1X-2004 related configuration ##################################
# Require IEEE 802.1X authorization
# -respout /tmp/ocsp-cache.der
#ocsp_stapling_response=/tmp/ocsp-cache.der
+# Cached OCSP stapling response list (DER encoded OCSPResponseList)
+# This is similar to ocsp_stapling_response, but the extended version defined in
+# RFC 6961 to allow multiple OCSP responses to be provided.
+#ocsp_stapling_response_multi=/tmp/ocsp-multi-cache.der
+
# dh_file: File path to DH/DSA parameters file (in PEM format)
# This is an optional configuration file for setting parameters for an
# ephemeral DH key exchange. In most cases, the default RSA authentication does
#eap_sim_db=unix:/tmp/hlr_auc_gw.sock
#eap_sim_db=unix:/tmp/hlr_auc_gw.sock db=/tmp/hostapd.db
+# EAP-SIM DB request timeout
+# This parameter sets the maximum time to wait for a database request response.
+# The parameter value is in seconds.
+#eap_sim_db_timeout=1
+
# Encryption key for EAP-FAST PAC-Opaque values. This key must be a secret,
# random value. It is configured as a 16-octet value in hex format. It can be
# generated, e.g., with the following command:
# The own IP address of the access point (used as NAS-IP-Address)
own_ip_addr=127.0.0.1
-# Optional NAS-Identifier string for RADIUS messages. When used, this should be
-# a unique to the NAS within the scope of the RADIUS server. For example, a
-# fully qualified domain name can be used here.
+# NAS-Identifier string for RADIUS messages. When used, this should be unique
+# to the NAS within the scope of the RADIUS server. Please note that hostapd
+# uses a separate RADIUS client for each BSS and as such, a unique
+# nas_identifier value should be configured separately for each BSS. This is
+# particularly important for cases where RADIUS accounting is used
+# (Accounting-On/Off messages are interpreted as clearing all ongoing sessions
+# and that may get interpreted as applying to all BSSes if the same
+# NAS-Identifier value is used.) For example, a fully qualified domain name
+# prefixed with a unique identifier of the BSS (e.g., BSSID) can be used here.
+#
# When using IEEE 802.11r, nas_identifier must be set and must be between 1 and
# 48 octets long.
+#
+# It is mandatory to configure either own_ip_addr or nas_identifier to be
+# compliant with the RADIUS protocol. When using RADIUS accounting, it is
+# strongly recommended that nas_identifier is set to a unique value for each
+# BSS.
#nas_identifier=ap.example.com
# RADIUS client forced local IP address for the access point
# 2 = required; reject authentication if RADIUS server does not include VLAN ID
#dynamic_vlan=0
+# Per-Station AP_VLAN interface mode
+# If enabled, each station is assigned its own AP_VLAN interface.
+# This implies per-station group keying and ebtables filtering of inter-STA
+# traffic (when passed through the AP).
+# If the sta is not assigned to any VLAN, then its AP_VLAN interface will be
+# added to the bridge given by the "bridge" configuration option (see above).
+# Otherwise, it will be added to the per-VLAN bridge.
+# 0 = disabled (default)
+# 1 = enabled
+#per_sta_vif=0
+
# VLAN interface list for dynamic VLAN mode is read from a separate text file.
# This list is used to map VLAN ID from the RADIUS server to a network
# interface. Each station is bound to one interface in the same way as with
#
# DAS require Event-Timestamp
#radius_das_require_event_timestamp=1
+#
+# DAS require Message-Authenticator
+#radius_das_require_message_authenticator=1
##### RADIUS authentication server configuration ##############################
# PMK-R1 Key Holder identifier (dot11FTR1KeyHolderID)
# 6-octet identifier as a hex string.
+# Defaults to BSSID.
#r1_key_holder=000102030405
# Reassociation deadline in time units (TUs / 1.024 ms; range 1000..65535)
# username/password
#nai_realm=0,example.org,13[5:6],21[2:4][5:7]
+# Arbitrary ANQP-element configuration
+# Additional ANQP-elements with arbitrary values can be defined by specifying
+# their contents in raw format as a hexdump of the payload. Note that these
+# values will override ANQP-element contents that may have been specified in the
+# more higher layer configuration parameters listed above.
+# format: anqp_elem=<InfoID>:<hexdump of payload>
+# For example, AP Geospatial Location ANQP-element with unknown location:
+#anqp_elem=265:0000
+# For example, AP Civic Location ANQP-element with unknown location:
+#anqp_elem=266:000000
+
+# GAS Address 3 behavior
+# 0 = P2P specification (Address3 = AP BSSID) workaround enabled by default
+# based on GAS request Address3
+# 1 = IEEE 802.11 standard compliant regardless of GAS request Address3
+# 2 = Force non-compliant behavior (Address3 = AP BSSID for all cases)
+#gas_address3=0
+
# QoS Map Set configuration
#
# Comma delimited QoS Map Set in decimal values
# Transitioning between states).
#fst_llt=100
+##### Radio measurements / location ###########################################
+
+# The content of a LCI measurement subelement
+#lci=<Hexdump of binary data of the LCI report>
+
+# The content of a location civic measurement subelement
+#civic=<Hexdump of binary data of the location civic report>
+
+# Enable neighbor report via radio measurements
+#rrm_neighbor_report=1
+
+# Publish fine timing measurement (FTM) responder functionality
+# This parameter only controls publishing via Extended Capabilities element.
+# Actual functionality is managed outside hostapd.
+#ftm_responder=0
+
+# Publish fine timing measurement (FTM) initiator functionality
+# This parameter only controls publishing via Extended Capabilities element.
+# Actual functionality is managed outside hostapd.
+#ftm_initiator=0
+
##### TESTING OPTIONS #########################################################
#
# The options in this section are only available when the build configuration
#
# Corrupt Key MIC in GTK rekey EAPOL-Key frames with the given probability
#corrupt_gtk_rekey_mic_probability=0.0
+#
+# Include only ECSA IE without CSA IE where possible
+# (channel switch operating class is needed)
+#ecsa_ie_only=0
##### Multiple BSSID support ##################################################
#
# - is not the same as the MAC address of the radio
# - is not the same as any other explicitly specified BSSID
#
+# Alternatively, the 'use_driver_iface_addr' parameter can be used to request
+# hostapd to use the driver auto-generated interface address (e.g., to use the
+# exact MAC addresses allocated to the device).
+#
# Not all drivers support multiple BSSes. The exact mechanism for determining
# the driver capabilities is driver specific. With the current (i.e., a recent
# kernel) drivers using nl80211, this information can be checked with "iw list"
/*
* hostapd - command line interface for hostapd daemon
- * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
#include "utils/eloop.h"
#include "utils/edit.h"
#include "common/version.h"
+#include "common/cli.h"
+#ifndef CONFIG_NO_CTRL_IFACE
static const char *const hostapd_cli_version =
"hostapd_cli v" VERSION_STR "\n"
-"Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> and contributors";
-
-
-static const char *const hostapd_cli_license =
-"This software may be distributed under the terms of the BSD license.\n"
-"See README for more details.\n";
-
-static const char *const hostapd_cli_full_license =
-"This software may be distributed under the terms of the BSD license.\n"
-"\n"
-"Redistribution and use in source and binary forms, with or without\n"
-"modification, are permitted provided that the following conditions are\n"
-"met:\n"
-"\n"
-"1. Redistributions of source code must retain the above copyright\n"
-" notice, this list of conditions and the following disclaimer.\n"
-"\n"
-"2. Redistributions in binary form must reproduce the above copyright\n"
-" notice, this list of conditions and the following disclaimer in the\n"
-" documentation and/or other materials provided with the distribution.\n"
-"\n"
-"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
-" names of its contributors may be used to endorse or promote products\n"
-" derived from this software without specific prior written permission.\n"
-"\n"
-"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
-"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
-"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
-"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
-"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
-"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
-"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
-"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
-"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
-"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
-"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
-"\n";
-
-static const char *const commands_help =
-"Commands:\n"
-" mib get MIB variables (dot1x, dot11, radius)\n"
-" sta <addr> get MIB variables for one station\n"
-" all_sta get MIB variables for all stations\n"
-" new_sta <addr> add a new station\n"
-" deauthenticate <addr> deauthenticate a station\n"
-" disassociate <addr> disassociate a station\n"
-#ifdef CONFIG_IEEE80211W
-" sa_query <addr> send SA Query to a station\n"
-#endif /* CONFIG_IEEE80211W */
-#ifdef CONFIG_WPS
-" wps_pin <uuid> <pin> [timeout] [addr] add WPS Enrollee PIN\n"
-" wps_check_pin <PIN> verify PIN checksum\n"
-" wps_pbc indicate button pushed to initiate PBC\n"
-" wps_cancel cancel the pending WPS operation\n"
-#ifdef CONFIG_WPS_NFC
-" wps_nfc_tag_read <hexdump> report read NFC tag with WPS data\n"
-" wps_nfc_config_token <WPS/NDEF> build NFC configuration token\n"
-" wps_nfc_token <WPS/NDEF/enable/disable> manager NFC password token\n"
-#endif /* CONFIG_WPS_NFC */
-" wps_ap_pin <cmd> [params..] enable/disable AP PIN\n"
-" wps_config <SSID> <auth> <encr> <key> configure AP\n"
-" wps_get_status show current WPS status\n"
-#endif /* CONFIG_WPS */
-" get_config show current configuration\n"
-" help show this usage help\n"
-" interface [ifname] show interfaces/select interface\n"
-" level <debug level> change debug level\n"
-" license show full hostapd_cli license\n"
-" quit exit hostapd_cli\n";
+"Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi> and contributors";
static struct wpa_ctrl *ctrl_conn;
static int hostapd_cli_quit = 0;
static const char *action_file = NULL;
static int ping_interval = 5;
static int interactive = 0;
+static int event_handler_registered = 0;
+
+static DEFINE_DL_LIST(stations); /* struct cli_txt_entry */
+
+static void print_help(FILE *stream, const char *cmd);
+static char ** list_cmd_list(void);
+static void hostapd_cli_receive(int sock, void *eloop_ctx, void *sock_ctx);
static void usage(void)
" -B run a daemon in the background\n"
" -i<ifname> Interface to listen on (default: first "
"interface found in the\n"
- " socket path)\n\n"
- "%s",
- commands_help);
+ " socket path)\n\n");
+ print_help(stderr, NULL);
+}
+
+
+static void register_event_handler(struct wpa_ctrl *ctrl)
+{
+ if (!ctrl_conn)
+ return;
+ if (interactive) {
+ event_handler_registered =
+ !eloop_register_read_sock(wpa_ctrl_get_fd(ctrl),
+ hostapd_cli_receive,
+ NULL, NULL);
+ }
+}
+
+
+static void unregister_event_handler(struct wpa_ctrl *ctrl)
+{
+ if (!ctrl_conn)
+ return;
+ if (interactive && event_handler_registered) {
+ eloop_unregister_read_sock(wpa_ctrl_get_fd(ctrl));
+ event_handler_registered = 0;
+ }
}
static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
{
+#ifndef CONFIG_CTRL_IFACE_UDP
char *cfile;
int flen;
+#endif /* !CONFIG_CTRL_IFACE_UDP */
if (ifname == NULL)
return NULL;
+#ifdef CONFIG_CTRL_IFACE_UDP
+ ctrl_conn = wpa_ctrl_open(ifname);
+ return ctrl_conn;
+#else /* CONFIG_CTRL_IFACE_UDP */
flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
cfile = malloc(flen);
if (cfile == NULL)
ctrl_conn = wpa_ctrl_open2(cfile, client_socket_dir);
free(cfile);
return ctrl_conn;
+#endif /* CONFIG_CTRL_IFACE_UDP */
}
if (ctrl_conn == NULL)
return;
+ unregister_event_handler(ctrl_conn);
if (hostapd_cli_attached) {
wpa_ctrl_detach(ctrl_conn);
hostapd_cli_attached = 0;
}
+static int hostapd_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd,
+ int min_args, int argc, char *argv[])
+{
+ char buf[4096];
+
+ if (argc < min_args) {
+ printf("Invalid %s command - at least %d argument%s required.\n",
+ cmd, min_args, min_args > 1 ? "s are" : " is");
+ return -1;
+ }
+ if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
+ return -1;
+ return wpa_ctrl_command(ctrl, buf);
+}
+
+
static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
return wpa_ctrl_command(ctrl, "PING");
}
+static char ** hostapd_complete_deauthenticate(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ char **res = NULL;
+
+ switch (arg) {
+ case 1:
+ res = cli_txt_list_array(&stations);
+ break;
+ }
+
+ return res;
+}
+
+
static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
}
+static char ** hostapd_complete_disassociate(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ char **res = NULL;
+
+ switch (arg) {
+ case 1:
+ res = cli_txt_list_array(&stations);
+ break;
+ }
+
+ return res;
+}
+
+
+#ifdef CONFIG_TAXONOMY
+static int hostapd_cli_cmd_signature(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ char buf[64];
+
+ if (argc != 1) {
+ printf("Invalid 'signature' command - exactly one argument, STA address, is required.\n");
+ return -1;
+ }
+ os_snprintf(buf, sizeof(buf), "SIGNATURE %s", argv[0]);
+ return wpa_ctrl_command(ctrl, buf);
+}
+#endif /* CONFIG_TAXONOMY */
+
+
#ifdef CONFIG_IEEE80211W
static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
char *argv[])
static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
- printf("%s", commands_help);
+ print_help(stdout, argc > 0 ? argv[0] : NULL);
return 0;
}
+static char ** hostapd_cli_complete_help(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ char **res = NULL;
+
+ switch (arg) {
+ case 1:
+ res = list_cmd_list();
+ break;
+ }
+
+ return res;
+}
+
+
static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
- printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
+ printf("%s\n\n%s\n", hostapd_cli_version, cli_full_license);
return 0;
}
}
+static void hostapd_cli_get_interfaces(struct wpa_ctrl *ctrl,
+ struct dl_list *interfaces)
+{
+ struct dirent *dent;
+ DIR *dir;
+
+ if (!ctrl || !interfaces)
+ return;
+ dir = opendir(ctrl_iface_dir);
+ if (dir == NULL)
+ return;
+
+ while ((dent = readdir(dir))) {
+ if (strcmp(dent->d_name, ".") == 0 ||
+ strcmp(dent->d_name, "..") == 0)
+ continue;
+ cli_txt_list_add(interfaces, dent->d_name);
+ }
+ closedir(dir);
+}
+
+
static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
{
struct dirent *dent;
printf("Connected to interface '%s.\n", ctrl_ifname);
if (wpa_ctrl_attach(ctrl_conn) == 0) {
hostapd_cli_attached = 1;
+ register_event_handler(ctrl_conn);
} else {
printf("Warning: Failed to attach to "
"hostapd.\n");
}
+static char ** hostapd_complete_interface(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ char **res = NULL;
+ DEFINE_DL_LIST(interfaces);
+
+ switch (arg) {
+ case 1:
+ hostapd_cli_get_interfaces(ctrl_conn, &interfaces);
+ res = cli_txt_list_array(&interfaces);
+ cli_txt_list_flush(&interfaces);
+ break;
+ }
+
+ return res;
+}
+
+
static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
char cmd[256];
}
+static int hostapd_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ if (argc == 0)
+ return -1;
+ return hostapd_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
+}
+
+
+static int hostapd_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "PMKSA");
+}
+
+
+static int hostapd_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
+}
+
+
+static int hostapd_cli_cmd_set_neighbor(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ char cmd[2048];
+ int res;
+
+ if (argc < 3 || argc > 5) {
+ printf("Invalid set_neighbor command: needs 3-5 arguments\n");
+ return -1;
+ }
+
+ res = os_snprintf(cmd, sizeof(cmd), "SET_NEIGHBOR %s %s %s %s %s",
+ argv[0], argv[1], argv[2], argc >= 4 ? argv[3] : "",
+ argc == 5 ? argv[4] : "");
+ if (os_snprintf_error(sizeof(cmd), res)) {
+ printf("Too long SET_NEIGHBOR command.\n");
+ return -1;
+ }
+ return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int hostapd_cli_cmd_remove_neighbor(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ char cmd[400];
+ int res;
+
+ if (argc != 2) {
+ printf("Invalid remove_neighbor command: needs 2 arguments\n");
+ return -1;
+ }
+
+ res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NEIGHBOR %s %s",
+ argv[0], argv[1]);
+ if (os_snprintf_error(sizeof(cmd), res)) {
+ printf("Too long REMOVE_NEIGHBOR command.\n");
+ return -1;
+ }
+ return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int hostapd_cli_cmd_req_lci(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ char cmd[256];
+ int res;
+
+ if (argc != 1) {
+ printf("Invalid req_lci command - requires destination address\n");
+ return -1;
+ }
+
+ res = os_snprintf(cmd, sizeof(cmd), "REQ_LCI %s", argv[0]);
+ if (os_snprintf_error(sizeof(cmd), res)) {
+ printf("Too long REQ_LCI command.\n");
+ return -1;
+ }
+ return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int hostapd_cli_cmd_req_range(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ if (argc < 4) {
+ printf("Invalid req_range command: needs at least 4 arguments - dest address, randomization interval, min AP count, and 1 to 16 AP addresses\n");
+ return -1;
+ }
+
+ return hostapd_cli_cmd(ctrl, "REQ_RANGE", 4, argc, argv);
+}
+
+
+static int hostapd_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "DRIVER_FLAGS");
+}
+
+
struct hostapd_cli_cmd {
const char *cmd;
int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
+ char ** (*completion)(const char *str, int pos);
+ const char *usage;
};
static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
- { "ping", hostapd_cli_cmd_ping },
- { "mib", hostapd_cli_cmd_mib },
- { "relog", hostapd_cli_cmd_relog },
- { "status", hostapd_cli_cmd_status },
- { "sta", hostapd_cli_cmd_sta },
- { "all_sta", hostapd_cli_cmd_all_sta },
- { "new_sta", hostapd_cli_cmd_new_sta },
- { "deauthenticate", hostapd_cli_cmd_deauthenticate },
- { "disassociate", hostapd_cli_cmd_disassociate },
+ { "ping", hostapd_cli_cmd_ping, NULL,
+ "= pings hostapd" },
+ { "mib", hostapd_cli_cmd_mib, NULL,
+ "= get MIB variables (dot1x, dot11, radius)" },
+ { "relog", hostapd_cli_cmd_relog, NULL, NULL },
+ { "status", hostapd_cli_cmd_status, NULL, NULL },
+ { "sta", hostapd_cli_cmd_sta, NULL,
+ "<addr> = get MIB variables for one station" },
+ { "all_sta", hostapd_cli_cmd_all_sta, NULL,
+ "= get MIB variables for all stations" },
+ { "new_sta", hostapd_cli_cmd_new_sta, NULL,
+ "<addr> = add a new station" },
+ { "deauthenticate", hostapd_cli_cmd_deauthenticate,
+ hostapd_complete_deauthenticate,
+ "<addr> = deauthenticate a station" },
+ { "disassociate", hostapd_cli_cmd_disassociate,
+ hostapd_complete_disassociate,
+ "<addr> = disassociate a station" },
+#ifdef CONFIG_TAXONOMY
+ { "signature", hostapd_cli_cmd_signature, NULL,
+ "<addr> = get taxonomy signature for a station" },
+#endif /* CONFIG_TAXONOMY */
#ifdef CONFIG_IEEE80211W
- { "sa_query", hostapd_cli_cmd_sa_query },
+ { "sa_query", hostapd_cli_cmd_sa_query, NULL,
+ "<addr> = send SA Query to a station" },
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_WPS
- { "wps_pin", hostapd_cli_cmd_wps_pin },
- { "wps_check_pin", hostapd_cli_cmd_wps_check_pin },
- { "wps_pbc", hostapd_cli_cmd_wps_pbc },
- { "wps_cancel", hostapd_cli_cmd_wps_cancel },
+ { "wps_pin", hostapd_cli_cmd_wps_pin, NULL,
+ "<uuid> <pin> [timeout] [addr] = add WPS Enrollee PIN" },
+ { "wps_check_pin", hostapd_cli_cmd_wps_check_pin, NULL,
+ "<PIN> = verify PIN checksum" },
+ { "wps_pbc", hostapd_cli_cmd_wps_pbc, NULL,
+ "= indicate button pushed to initiate PBC" },
+ { "wps_cancel", hostapd_cli_cmd_wps_cancel, NULL,
+ "= cancel the pending WPS operation" },
#ifdef CONFIG_WPS_NFC
- { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
- { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token },
- { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token },
- { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel },
+ { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read, NULL,
+ "<hexdump> = report read NFC tag with WPS data" },
+ { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token, NULL,
+ "<WPS/NDEF> = build NFC configuration token" },
+ { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token, NULL,
+ "<WPS/NDEF/enable/disable> = manager NFC password token" },
+ { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel, NULL,
+ NULL },
#endif /* CONFIG_WPS_NFC */
- { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
- { "wps_config", hostapd_cli_cmd_wps_config },
- { "wps_get_status", hostapd_cli_cmd_wps_get_status },
+ { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin, NULL,
+ "<cmd> [params..] = enable/disable AP PIN" },
+ { "wps_config", hostapd_cli_cmd_wps_config, NULL,
+ "<SSID> <auth> <encr> <key> = configure AP" },
+ { "wps_get_status", hostapd_cli_cmd_wps_get_status, NULL,
+ "= show current WPS status" },
#endif /* CONFIG_WPS */
- { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
- { "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
- { "bss_tm_req", hostapd_cli_cmd_bss_tm_req },
- { "get_config", hostapd_cli_cmd_get_config },
- { "help", hostapd_cli_cmd_help },
- { "interface", hostapd_cli_cmd_interface },
+ { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent, NULL, NULL },
+ { "ess_disassoc", hostapd_cli_cmd_ess_disassoc, NULL, NULL },
+ { "bss_tm_req", hostapd_cli_cmd_bss_tm_req, NULL, NULL },
+ { "get_config", hostapd_cli_cmd_get_config, NULL,
+ "= show current configuration" },
+ { "help", hostapd_cli_cmd_help, hostapd_cli_complete_help,
+ "= show this usage help" },
+ { "interface", hostapd_cli_cmd_interface, hostapd_complete_interface,
+ "[ifname] = show interfaces/select interface" },
#ifdef CONFIG_FST
- { "fst", hostapd_cli_cmd_fst },
+ { "fst", hostapd_cli_cmd_fst, NULL, NULL },
#endif /* CONFIG_FST */
- { "level", hostapd_cli_cmd_level },
- { "license", hostapd_cli_cmd_license },
- { "quit", hostapd_cli_cmd_quit },
- { "set", hostapd_cli_cmd_set },
- { "get", hostapd_cli_cmd_get },
- { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set },
- { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf },
- { "chan_switch", hostapd_cli_cmd_chan_switch },
- { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif },
- { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req },
- { "vendor", hostapd_cli_cmd_vendor },
- { "enable", hostapd_cli_cmd_enable },
- { "reload", hostapd_cli_cmd_reload },
- { "disable", hostapd_cli_cmd_disable },
- { "erp_flush", hostapd_cli_cmd_erp_flush },
- { "log_level", hostapd_cli_cmd_log_level },
- { NULL, NULL }
+ { "raw", hostapd_cli_cmd_raw, NULL, NULL },
+ { "level", hostapd_cli_cmd_level, NULL,
+ "<debug level> = change debug level" },
+ { "license", hostapd_cli_cmd_license, NULL,
+ "= show full hostapd_cli license" },
+ { "quit", hostapd_cli_cmd_quit, NULL,
+ "= exit hostapd_cli" },
+ { "set", hostapd_cli_cmd_set, NULL, NULL },
+ { "get", hostapd_cli_cmd_get, NULL, NULL },
+ { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set, NULL, NULL },
+ { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf, NULL, NULL },
+ { "chan_switch", hostapd_cli_cmd_chan_switch, NULL, NULL },
+ { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL, NULL },
+ { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req, NULL, NULL },
+ { "vendor", hostapd_cli_cmd_vendor, NULL, NULL },
+ { "enable", hostapd_cli_cmd_enable, NULL, NULL },
+ { "reload", hostapd_cli_cmd_reload, NULL, NULL },
+ { "disable", hostapd_cli_cmd_disable, NULL, NULL },
+ { "erp_flush", hostapd_cli_cmd_erp_flush, NULL, NULL },
+ { "log_level", hostapd_cli_cmd_log_level, NULL, NULL },
+ { "pmksa", hostapd_cli_cmd_pmksa, NULL, NULL },
+ { "pmksa_flush", hostapd_cli_cmd_pmksa_flush, NULL, NULL },
+ { "set_neighbor", hostapd_cli_cmd_set_neighbor, NULL, NULL },
+ { "remove_neighbor", hostapd_cli_cmd_remove_neighbor, NULL, NULL },
+ { "req_lci", hostapd_cli_cmd_req_lci, NULL, NULL },
+ { "req_range", hostapd_cli_cmd_req_range, NULL, NULL },
+ { "driver_flags", hostapd_cli_cmd_driver_flags, NULL, NULL },
+ { NULL, NULL, NULL, NULL }
};
+/*
+ * Prints command usage, lines are padded with the specified string.
+ */
+static void print_cmd_help(FILE *stream, const struct hostapd_cli_cmd *cmd,
+ const char *pad)
+{
+ char c;
+ size_t n;
+
+ if (cmd->usage == NULL)
+ return;
+ fprintf(stream, "%s%s ", pad, cmd->cmd);
+ for (n = 0; (c = cmd->usage[n]); n++) {
+ fprintf(stream, "%c", c);
+ if (c == '\n')
+ fprintf(stream, "%s", pad);
+ }
+ fprintf(stream, "\n");
+}
+
+
+static void print_help(FILE *stream, const char *cmd)
+{
+ int n;
+
+ fprintf(stream, "commands:\n");
+ for (n = 0; hostapd_cli_commands[n].cmd; n++) {
+ if (cmd == NULL || str_starts(hostapd_cli_commands[n].cmd, cmd))
+ print_cmd_help(stream, &hostapd_cli_commands[n], " ");
+ }
+}
+
+
static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
const struct hostapd_cli_cmd *cmd, *match = NULL;
}
+static void cli_event(const char *str)
+{
+ const char *start, *s;
+
+ start = os_strchr(str, '>');
+ if (start == NULL)
+ return;
+
+ start++;
+
+ if (str_starts(start, AP_STA_CONNECTED)) {
+ s = os_strchr(start, ' ');
+ if (s == NULL)
+ return;
+ cli_txt_list_add(&stations, s + 1);
+ return;
+ }
+
+ if (str_starts(start, AP_STA_DISCONNECTED)) {
+ s = os_strchr(start, ' ');
+ if (s == NULL)
+ return;
+ cli_txt_list_del_addr(&stations, s + 1);
+ return;
+ }
+}
+
+
static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
int action_monitor)
{
if (action_monitor)
hostapd_cli_action_process(buf, len);
else {
+ cli_event(buf);
if (in_read && first)
printf("\n");
first = 0;
}
-#define max_args 10
-
-static int tokenize_cmd(char *cmd, char *argv[])
+static void hostapd_cli_receive(int sock, void *eloop_ctx, void *sock_ctx)
{
- char *pos;
- int argc = 0;
-
- pos = cmd;
- for (;;) {
- while (*pos == ' ')
- pos++;
- if (*pos == '\0')
- break;
- argv[argc] = pos;
- argc++;
- if (argc == max_args)
- break;
- if (*pos == '"') {
- char *pos2 = os_strrchr(pos, '"');
- if (pos2)
- pos = pos2 + 1;
- }
- while (*pos != '\0' && *pos != ' ')
- pos++;
- if (*pos == ' ')
- *pos++ = '\0';
- }
-
- return argc;
+ hostapd_cli_recv_pending(ctrl_conn, 0, 0);
}
printf("Connection to hostapd re-established\n");
if (wpa_ctrl_attach(ctrl_conn) == 0) {
hostapd_cli_attached = 1;
+ register_event_handler(ctrl_conn);
} else {
printf("Warning: Failed to attach to "
"hostapd.\n");
}
+static char ** list_cmd_list(void)
+{
+ char **res;
+ int i, count;
+
+ count = ARRAY_SIZE(hostapd_cli_commands);
+ res = os_calloc(count + 1, sizeof(char *));
+ if (res == NULL)
+ return NULL;
+
+ for (i = 0; hostapd_cli_commands[i].cmd; i++) {
+ res[i] = os_strdup(hostapd_cli_commands[i].cmd);
+ if (res[i] == NULL)
+ break;
+ }
+
+ return res;
+}
+
+
+static char ** hostapd_cli_cmd_completion(const char *cmd, const char *str,
+ int pos)
+{
+ int i;
+
+ for (i = 0; hostapd_cli_commands[i].cmd; i++) {
+ if (os_strcasecmp(hostapd_cli_commands[i].cmd, cmd) != 0)
+ continue;
+ if (hostapd_cli_commands[i].completion)
+ return hostapd_cli_commands[i].completion(str, pos);
+ if (!hostapd_cli_commands[i].usage)
+ return NULL;
+ edit_clear_line();
+ printf("\r%s\n", hostapd_cli_commands[i].usage);
+ edit_redraw();
+ break;
+ }
+
+ return NULL;
+}
+
+
+static char ** hostapd_cli_edit_completion_cb(void *ctx, const char *str,
+ int pos)
+{
+ char **res;
+ const char *end;
+ char *cmd;
+
+ end = os_strchr(str, ' ');
+ if (end == NULL || str + pos < end)
+ return list_cmd_list();
+
+ cmd = os_malloc(pos + 1);
+ if (cmd == NULL)
+ return NULL;
+ os_memcpy(cmd, str, pos);
+ cmd[end - str] = '\0';
+ res = hostapd_cli_cmd_completion(cmd, str, pos);
+ os_free(cmd);
+ return res;
+}
+
+
static void hostapd_cli_interactive(void)
{
printf("\nInteractive mode\n\n");
eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
- NULL, NULL, NULL, NULL);
+ hostapd_cli_edit_completion_cb, NULL, NULL, NULL);
eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
eloop_run();
+ cli_txt_list_flush(&stations);
edit_deinit(NULL, NULL);
eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
}
interactive = (argc == optind) && (action_file == NULL);
if (interactive) {
- printf("%s\n\n%s\n\n", hostapd_cli_version,
- hostapd_cli_license);
+ printf("%s\n\n%s\n\n", hostapd_cli_version, cli_license);
}
if (eloop_init())
if (interactive || action_file) {
if (wpa_ctrl_attach(ctrl_conn) == 0) {
hostapd_cli_attached = 1;
+ register_event_handler(ctrl_conn);
} else {
printf("Warning: Failed to attach to hostapd.\n");
if (action_file)
}
}
- if (daemonize && os_daemonize(pid_file))
+ if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
return -1;
if (interactive)
else
wpa_request(ctrl_conn, argc - optind, &argv[optind]);
+ unregister_event_handler(ctrl_conn);
os_free(ctrl_ifname);
eloop_destroy();
hostapd_cli_cleanup();
return 0;
}
+
+#else /* CONFIG_NO_CTRL_IFACE */
+
+int main(int argc, char *argv[])
+{
+ return -1;
+}
+
+#endif /* CONFIG_NO_CTRL_IFACE */
/*
* hostapd / main()
- * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2016, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
if (global.drv_priv[i] == NULL &&
wpa_drivers[i]->global_init) {
- global.drv_priv[i] = wpa_drivers[i]->global_init();
+ global.drv_priv[i] =
+ wpa_drivers[i]->global_init(iface->interfaces);
if (global.drv_priv[i] == NULL) {
wpa_printf(MSG_ERROR, "Failed to initialize "
"driver '%s'",
iface->drv_flags = capa.flags;
iface->smps_modes = capa.smps_modes;
iface->probe_resp_offloads = capa.probe_resp_offloads;
+ /*
+ * Use default extended capa values from per-radio information
+ */
iface->extended_capa = capa.extended_capa;
iface->extended_capa_mask = capa.extended_capa_mask;
iface->extended_capa_len = capa.extended_capa_len;
iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
+ /*
+ * Override extended capa with per-interface type (AP), if
+ * available from the driver.
+ */
+ hostapd_get_ext_capa(iface);
+
triggs = wpa_get_wowlan_triggers(conf->wowlan_triggers, &capa);
if (triggs && hapd->driver->set_wowlan) {
if (hapd->driver->set_wowlan(hapd->drv_priv, triggs))
* interfaces. No actiual driver operations are started.
*/
static struct hostapd_iface *
-hostapd_interface_init(struct hapd_interfaces *interfaces,
+hostapd_interface_init(struct hapd_interfaces *interfaces, const char *if_name,
const char *config_fname, int debug)
{
struct hostapd_iface *iface;
iface = hostapd_init(interfaces, config_fname);
if (!iface)
return NULL;
+
+ if (if_name) {
+ os_strlcpy(iface->conf->bss[0]->iface, if_name,
+ sizeof(iface->conf->bss[0]->iface));
+ }
+
iface->interfaces = interfaces;
for (k = 0; k < debug; k++) {
if (iface->conf->bss[0]->iface[0] == '\0' &&
!hostapd_drv_none(iface->bss[0])) {
- wpa_printf(MSG_ERROR, "Interface name not specified in %s",
+ wpa_printf(MSG_ERROR,
+ "Interface name not specified in %s, nor by '-i' parameter",
config_fname);
hostapd_interface_deinit_free(iface);
return NULL;
wpa_printf(MSG_ERROR, "Failed to initialize event loop");
return -1;
}
+ interfaces->eloop_initialized = 1;
random_init(entropy_file);
}
-static void hostapd_global_deinit(const char *pid_file)
+static void hostapd_global_deinit(const char *pid_file, int eloop_initialized)
{
int i;
random_deinit();
- eloop_destroy();
+ if (eloop_initialized)
+ eloop_destroy();
#ifndef CONFIG_NATIVE_WINDOWS
closelog();
}
#endif /* EAP_SERVER_TNC */
- if (daemonize && os_daemonize(pid_file)) {
- wpa_printf(MSG_ERROR, "daemon: %s", strerror(errno));
- return -1;
+ if (daemonize) {
+ if (os_daemonize(pid_file)) {
+ wpa_printf(MSG_ERROR, "daemon: %s", strerror(errno));
+ return -1;
+ }
+ if (eloop_sock_requeue()) {
+ wpa_printf(MSG_ERROR, "eloop_sock_requeue: %s",
+ strerror(errno));
+ return -1;
+ }
}
eloop_run();
"hostapd v" VERSION_STR "\n"
"User space daemon for IEEE 802.11 AP management,\n"
"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
- "Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi> "
+ "Copyright (c) 2002-2016, Jouni Malinen <j@w1.fi> "
"and contributors\n");
}
"\n"
"usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] "
"\\\n"
- " [-g <global ctrl_iface>] [-G <group>] \\\n"
+ " [-g <global ctrl_iface>] [-G <group>]\\\n"
+ " [-i <comma-separated list of interface names>]\\\n"
" <configuration file(s)>\n"
"\n"
"options:\n"
" -T = record to Linux tracing in addition to logging\n"
" (records all messages regardless of debug verbosity)\n"
#endif /* CONFIG_DEBUG_LINUX_TRACING */
+ " -i list of interface names to use\n"
+ " -S start all the interfaces synchronously\n"
" -t include timestamps in some debug messages\n"
" -v show hostapd version\n");
static const char * hostapd_msg_ifname_cb(void *ctx)
{
struct hostapd_data *hapd = ctx;
- if (hapd && hapd->iconf && hapd->iconf->bss &&
- hapd->iconf->num_bss > 0 && hapd->iconf->bss[0])
- return hapd->iconf->bss[0]->iface;
+ if (hapd && hapd->conf)
+ return hapd->conf->iface;
return NULL;
}
static int hostapd_get_global_ctrl_iface(struct hapd_interfaces *interfaces,
const char *path)
{
+#ifndef CONFIG_CTRL_IFACE_UDP
char *pos;
+#endif /* !CONFIG_CTRL_IFACE_UDP */
+
os_free(interfaces->global_iface_path);
interfaces->global_iface_path = os_strdup(path);
if (interfaces->global_iface_path == NULL)
return -1;
+
+#ifndef CONFIG_CTRL_IFACE_UDP
pos = os_strrchr(interfaces->global_iface_path, '/');
if (pos == NULL) {
wpa_printf(MSG_ERROR, "No '/' in the global control interface "
*pos = '\0';
interfaces->global_iface_name = pos + 1;
+#endif /* !CONFIG_CTRL_IFACE_UDP */
return 0;
}
}
+static int hostapd_get_interface_names(char ***if_names,
+ size_t *if_names_size,
+ char *optarg)
+{
+ char *if_name, *tmp, **nnames;
+ size_t i;
+
+ if (!optarg)
+ return -1;
+ if_name = strtok_r(optarg, ",", &tmp);
+
+ while (if_name) {
+ nnames = os_realloc_array(*if_names, 1 + *if_names_size,
+ sizeof(char *));
+ if (!nnames)
+ goto fail;
+ *if_names = nnames;
+
+ (*if_names)[*if_names_size] = os_strdup(if_name);
+ if (!(*if_names)[*if_names_size])
+ goto fail;
+ (*if_names_size)++;
+ if_name = strtok_r(NULL, ",", &tmp);
+ }
+
+ return 0;
+
+fail:
+ for (i = 0; i < *if_names_size; i++)
+ os_free((*if_names)[i]);
+ os_free(*if_names);
+ *if_names = NULL;
+ *if_names_size = 0;
+ return -1;
+}
+
+
#ifdef CONFIG_WPS
static int gen_uuid(const char *txt_addr)
{
#ifdef CONFIG_DEBUG_LINUX_TRACING
int enable_trace_dbg = 0;
#endif /* CONFIG_DEBUG_LINUX_TRACING */
+ int start_ifaces_in_sync = 0;
+ char **if_names = NULL;
+ size_t if_names_size = 0;
if (os_program_init())
return -1;
interfaces.global_iface_path = NULL;
interfaces.global_iface_name = NULL;
interfaces.global_ctrl_sock = -1;
- interfaces.global_ctrl_dst = NULL;
+ dl_list_init(&interfaces.global_ctrl_dst);
for (;;) {
- c = getopt(argc, argv, "b:Bde:f:hKP:Ttu:vg:G:");
+ c = getopt(argc, argv, "b:Bde:f:hi:KP:STtu:vg:G:");
if (c < 0)
break;
switch (c) {
bss_config = tmp_bss;
bss_config[num_bss_configs++] = optarg;
break;
+ case 'S':
+ start_ifaces_in_sync = 1;
+ break;
#ifdef CONFIG_WPS
case 'u':
return gen_uuid(optarg);
#endif /* CONFIG_WPS */
+ case 'i':
+ if (hostapd_get_interface_names(&if_names,
+ &if_names_size, optarg))
+ goto out;
+ break;
default:
usage();
break;
/* Allocate and parse configuration for full interface files */
for (i = 0; i < interfaces.count; i++) {
+ char *if_name = NULL;
+
+ if (i < if_names_size)
+ if_name = if_names[i];
+
interfaces.iface[i] = hostapd_interface_init(&interfaces,
+ if_name,
argv[optind + i],
debug);
if (!interfaces.iface[i]) {
wpa_printf(MSG_ERROR, "Failed to initialize interface");
goto out;
}
+ if (start_ifaces_in_sync)
+ interfaces.iface[i]->need_to_start_in_sync = 1;
}
/* Allocate and parse configuration for per-BSS files */
}
os_free(interfaces.iface);
- eloop_cancel_timeout(hostapd_periodic, &interfaces, NULL);
- hostapd_global_deinit(pid_file);
+ if (interfaces.eloop_initialized)
+ eloop_cancel_timeout(hostapd_periodic, &interfaces, NULL);
+ hostapd_global_deinit(pid_file, interfaces.eloop_initialized);
os_free(pid_file);
if (log_file)
os_free(bss_config);
+ for (i = 0; i < if_names_size; i++)
+ os_free(if_names[i]);
+ os_free(if_names);
+
fst_global_deinit();
os_program_deinit();
INCLUDES += $(LOCAL_PATH)/../../src/utils
INCLUDES += $(LOCAL_PATH)/../../src/common
INCLUDES += $(LOCAL_PATH)/../../src
-INCLUDES += external/openssl/include
INCLUDES += external/libxml2/include
INCLUDES += external/curl/include
INCLUDES += external/webkit/Source/WebKit/gtk
OBJS += ../../src/crypto/md5-internal.c
OBJS += ../../src/crypto/sha1-internal.c
OBJS += ../../src/crypto/sha256-internal.c
+OBJS += ../../src/crypto/tls_openssl_ocsp.c
L_CFLAGS += -DEAP_TLS_OPENSSL
endif
CFLAGS += -DEAP_TLS_OPENSSL
+OBJS += ../../src/crypto/tls_openssl_ocsp.o
LIBS += -lssl -lcrypto
hs20-osu-client: $(OBJS)
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
+#ifdef OPENSSL_IS_BORINGSSL
+#include <openssl/buf.h>
+#endif /* OPENSSL_IS_BORINGSSL */
#include "common.h"
#include "utils/base64.h"
static int pkcs7_to_cert(struct hs20_osu_client *ctx, const u8 *pkcs7,
size_t len, char *pem_file, char *der_file)
{
+#ifdef OPENSSL_IS_BORINGSSL
+ CBS pkcs7_cbs;
+#else /* OPENSSL_IS_BORINGSSL */
PKCS7 *p7 = NULL;
const unsigned char *p = pkcs7;
+#endif /* OPENSSL_IS_BORINGSSL */
STACK_OF(X509) *certs;
int i, num, ret = -1;
BIO *out = NULL;
+#ifdef OPENSSL_IS_BORINGSSL
+ certs = sk_X509_new_null();
+ if (!certs)
+ goto fail;
+ CBS_init(&pkcs7_cbs, pkcs7, len);
+ if (!PKCS7_get_certificates(certs, &pkcs7_cbs)) {
+ wpa_printf(MSG_INFO, "Could not parse PKCS#7 object: %s",
+ ERR_error_string(ERR_get_error(), NULL));
+ write_result(ctx, "Could not parse PKCS#7 object from EST");
+ goto fail;
+ }
+#else /* OPENSSL_IS_BORINGSSL */
p7 = d2i_PKCS7(NULL, &p, len);
if (p7 == NULL) {
wpa_printf(MSG_INFO, "Could not parse PKCS#7 object: %s",
certs = NULL;
break;
}
+#endif /* OPENSSL_IS_BORINGSSL */
if (!certs || ((num = sk_X509_num(certs)) == 0)) {
wpa_printf(MSG_INFO, "No certificates found in PKCS#7 object");
ret = 0;
fail:
+#ifdef OPENSSL_IS_BORINGSSL
+ if (certs)
+ sk_X509_pop_free(certs, X509_free);
+#else /* OPENSSL_IS_BORINGSSL */
PKCS7_free(p7);
+#endif /* OPENSSL_IS_BORINGSSL */
if (out)
BIO_free_all(out);
if (!csrattrs || ! csrattrs->attrs)
return;
+#ifdef OPENSSL_IS_BORINGSSL
+ num = sk_num(CHECKED_CAST(_STACK *, STACK_OF(AttrOrOID) *,
+ csrattrs->attrs));
+ for (i = 0; i < num; i++) {
+ AttrOrOID *ao = sk_value(
+ CHECKED_CAST(_STACK *, const STACK_OF(AttrOrOID) *,
+ csrattrs->attrs), i);
+ switch (ao->type) {
+ case 0:
+ add_csrattrs_oid(ctx, ao->d.oid, exts);
+ break;
+ case 1:
+ add_csrattrs_attr(ctx, ao->d.attribute, exts);
+ break;
+ }
+ }
+#else /* OPENSSL_IS_BORINGSSL */
num = SKM_sk_num(AttrOrOID, csrattrs->attrs);
for (i = 0; i < num; i++) {
AttrOrOID *ao = SKM_sk_value(AttrOrOID, csrattrs->attrs, i);
break;
}
}
+#endif /* OPENSSL_IS_BORINGSSL */
}
STACK_OF(X509_EXTENSION) *exts = NULL;
X509_EXTENSION *ex;
BIO *out;
+ CONF *ctmp = NULL;
wpa_printf(MSG_INFO, "Generate RSA private key");
write_summary(ctx, "Generate RSA private key");
if (!exts)
goto fail;
- ex = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints,
- "CA:FALSE");
+ ex = X509V3_EXT_nconf_nid(ctmp, NULL, NID_basic_constraints,
+ "CA:FALSE");
if (ex == NULL ||
!sk_X509_EXTENSION_push(exts, ex))
goto fail;
- ex = X509V3_EXT_conf_nid(NULL, NULL, NID_key_usage,
- "nonRepudiation,digitalSignature,keyEncipherment");
+ ex = X509V3_EXT_nconf_nid(ctmp, NULL, NID_key_usage,
+ "nonRepudiation,digitalSignature,keyEncipherment");
if (ex == NULL ||
!sk_X509_EXTENSION_push(exts, ex))
goto fail;
- ex = X509V3_EXT_conf_nid(NULL, NULL, NID_ext_key_usage,
- "1.3.6.1.4.1.40808.1.1.2");
+ ex = X509V3_EXT_nconf_nid(ctmp, NULL, NID_ext_key_usage,
+ "1.3.6.1.4.1.40808.1.1.2");
if (ex == NULL ||
!sk_X509_EXTENSION_push(exts, ex))
goto fail;
char *txt;
size_t rlen;
+#if !defined(ANDROID) || !defined(OPENSSL_IS_BORINGSSL)
X509_REQ_print(out, req);
+#endif
rlen = BIO_ctrl_pending(out);
txt = os_malloc(rlen + 1);
if (txt) {
FILE *f = fopen(csr_pem, "w");
if (f == NULL)
goto fail;
+#if !defined(ANDROID) || !defined(OPENSSL_IS_BORINGSSL)
X509_REQ_print_fp(f, req);
+#endif
if (!PEM_write_X509_REQ(f, req)) {
fclose(f);
goto fail;
fprintf(f, "</table></a><br><small>BSSID: %s<br>\n"
"SSID: %s<br>\n",
last->bssid, last->osu_ssid);
- if (last->osu_nai)
+ if (last->osu_nai[0])
fprintf(f, "NAI: %s<br>\n", last->osu_nai);
fprintf(f, "URL: %s<br>\n"
"methods:%s%s<br>\n"
return -1;
snprintf(fname, sizeof(fname), "%s/osu-info", dir);
- if (mkdir(fname, S_IRWXU | S_IRWXG) < 0 && errno != EEXIST) {
+ if (mkdir(fname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0 &&
+ errno != EEXIST) {
wpa_printf(MSG_INFO, "mkdir(%s) failed: %s",
fname, strerror(errno));
return -1;
}
+#ifdef ANDROID
+ /* Allow processes running with Group ID as AID_WIFI
+ * to read/write files from osu-info directory
+ */
+ if (chown(fname, -1, AID_WIFI)) {
+ wpa_printf(MSG_INFO, "Could not chown osu-info directory: %s",
+ strerror(errno));
+ }
+#endif /* ANDROID */
+
snprintf(buf, sizeof(buf), "SET osu_dir %s", fname);
if (wpa_command(ifname, buf) < 0) {
wpa_printf(MSG_INFO, "Failed to configure osu_dir to wpa_supplicant");
if (!pps_fname) {
char buf[256];
wpa_printf(MSG_INFO, "Determining PPS file based on Home SP information");
- if (os_strncmp(address, "fqdn=", 5) == 0) {
+ if (address && os_strncmp(address, "fqdn=", 5) == 0) {
wpa_printf(MSG_INFO, "Use requested FQDN from command line");
os_snprintf(buf, sizeof(buf), "%s", address + 5);
address = NULL;
usage();
exit(0);
}
- if (argc - optind < 2)
- wpa_printf(MSG_ERROR, "Server URL missing from command line");
- else
- ret = cmd_sub_rem(&ctx, argv[optind + 1],
- argc > optind + 2 ?
- argv[optind + 2] : NULL,
- argc > optind + 3 ?
- argv[optind + 3] : NULL);
+ ret = cmd_sub_rem(&ctx, argv[optind + 1],
+ argc > optind + 2 ? argv[optind + 2] : NULL,
+ argc > optind + 3 ? argv[optind + 3] : NULL);
} else if (strcmp(argv[optind], "pol_upd") == 0) {
- if (argc - optind < 2) {
- usage();
- exit(0);
- }
- ret = cmd_pol_upd(&ctx, argc > 2 ? argv[optind + 1] : NULL,
+ ret = cmd_pol_upd(&ctx,
+ argc > optind + 1 ? argv[optind + 1] : NULL,
argc > optind + 2 ? argv[optind + 2] : NULL,
argc > optind + 3 ? argv[optind + 3] : NULL);
} else if (strcmp(argv[optind], "prov") == 0) {
putenv("HS20USER");
putenv("HS20REALM=$realm");
-putenv("HS20POST=$HTTP_RAW_POST_DATA");
+$postdata = file_get_contents("php://input");
+putenv("HS20POST=$postdata");
$addr = $_SERVER["REMOTE_ADDR"];
putenv("HS20ADDR=$addr");
+++ /dev/null
-interface=wlan0
-driver=nl80211
-
-hw_mode=g
-channel=1
-ssid=mac80211 test
-
-wpa=2
-wpa_key_mgmt=WPA-PSK
-wpa_pairwise=CCMP
-wpa_passphrase=12345678
+++ /dev/null
-# WPA2-Personal (PSK) with CCMP, AP and single client
-
-modprobe mac80211_hwsim
-
-hostapd hostapd.conf
-
-wpa_supplicant -Dwext -iwlan1 -c wpa_supplicant.conf
+++ /dev/null
-ctrl_interface=/var/run/wpa_supplicant
-
-network={
- ssid="mac80211 test"
- psk="12345678"
- key_mgmt=WPA-PSK
- proto=WPA2
- pairwise=CCMP
- group=CCMP
-}
+++ /dev/null
-02:00:00:00:01:00 1
-02:00:00:00:02:00 2
+++ /dev/null
-interface=wlan0
-driver=nl80211
-
-hw_mode=g
-channel=1
-ssid=mac80211 test
-
-dynamic_vlan=2
-vlan_file=hostapd.vlan
-
-macaddr_acl=0
-accept_mac_file=hostapd.accept
+++ /dev/null
-# Plaintext connection, two clients, different VLANs
-
-modprobe mac80211_hwsim radios=3
-
-hostapd hostapd.conf
-
-ifconfig wlan1 up
-iwconfig wlan1 essid "mac80211 test"
-
-ifconfig wlan2 up
-iwconfig wlan2 essid "mac80211 test"
-
-# Expected results:
-# STA1(wlan1) is bound to vlan1
-# STA2(wlan2) is bound to vlan2
+++ /dev/null
-This patch adds support for TLS SessionTicket extension (RFC 5077) for
-the parts used by EAP-FAST (RFC 4851).
-
-This is based on the patch from Alexey Kobozev <akobozev@cisco.com>
-(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
-
-OpenSSL 0.9.8za does not enable TLS extension support by default, so it
-will need to be enabled by adding enable-tlsext to config script
-command line.
-
-
-diff -upr openssl-0.9.8za.orig/ssl/s3_clnt.c openssl-0.9.8za/ssl/s3_clnt.c
---- openssl-0.9.8za.orig/ssl/s3_clnt.c 2014-06-05 11:09:26.000000000 +0300
-+++ openssl-0.9.8za/ssl/s3_clnt.c 2014-06-05 20:37:09.221387312 +0300
-@@ -767,6 +767,22 @@ int ssl3_get_server_hello(SSL *s)
- goto f_err;
- }
-
-+#ifndef OPENSSL_NO_TLSEXT
-+ /* check if we want to resume the session based on external pre-shared secret */
-+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb)
-+ {
-+ SSL_CIPHER *pref_cipher=NULL;
-+ s->session->master_key_length=sizeof(s->session->master_key);
-+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
-+ NULL, &pref_cipher, s->tls_session_secret_cb_arg))
-+ {
-+ s->session->cipher=pref_cipher ?
-+ pref_cipher : ssl_get_cipher_by_char(s,p+j);
-+ s->s3->flags |= SSL3_FLAGS_CCS_OK;
-+ }
-+ }
-+#endif /* OPENSSL_NO_TLSEXT */
-+
- if (j != 0 && j == s->session->session_id_length
- && memcmp(p,s->session->session_id,j) == 0)
- {
-@@ -2745,11 +2760,8 @@ int ssl3_check_finished(SSL *s)
- {
- int ok;
- long n;
-- /* If we have no ticket or session ID is non-zero length (a match of
-- * a non-zero session length would never reach here) it cannot be a
-- * resumed session.
-- */
-- if (!s->session->tlsext_tick || s->session->session_id_length)
-+ /* If we have no ticket it cannot be a resumed session. */
-+ if (!s->session->tlsext_tick)
- return 1;
- /* this function is called when we really expect a Certificate
- * message, so permit appropriate message length */
-diff -upr openssl-0.9.8za.orig/ssl/s3_srvr.c openssl-0.9.8za/ssl/s3_srvr.c
---- openssl-0.9.8za.orig/ssl/s3_srvr.c 2014-06-05 11:09:26.000000000 +0300
-+++ openssl-0.9.8za/ssl/s3_srvr.c 2014-06-05 20:37:09.225387312 +0300
-@@ -1011,6 +1011,59 @@ int ssl3_get_client_hello(SSL *s)
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
- goto err;
- }
-+
-+ /* Check if we want to use external pre-shared secret for this
-+ * handshake for not reused session only. We need to generate
-+ * server_random before calling tls_session_secret_cb in order to allow
-+ * SessionTicket processing to use it in key derivation. */
-+ {
-+ unsigned long Time;
-+ unsigned char *pos;
-+ Time=(unsigned long)time(NULL); /* Time */
-+ pos=s->s3->server_random;
-+ l2n(Time,pos);
-+ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0)
-+ {
-+ al=SSL_AD_INTERNAL_ERROR;
-+ goto f_err;
-+ }
-+ }
-+
-+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb)
-+ {
-+ SSL_CIPHER *pref_cipher=NULL;
-+
-+ s->session->master_key_length=sizeof(s->session->master_key);
-+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length,
-+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg))
-+ {
-+ s->hit=1;
-+ s->session->ciphers=ciphers;
-+ s->session->verify_result=X509_V_OK;
-+
-+ ciphers=NULL;
-+
-+ /* check if some cipher was preferred by call back */
-+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
-+ if (pref_cipher == NULL)
-+ {
-+ al=SSL_AD_HANDSHAKE_FAILURE;
-+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER);
-+ goto f_err;
-+ }
-+
-+ s->session->cipher=pref_cipher;
-+
-+ if (s->cipher_list)
-+ sk_SSL_CIPHER_free(s->cipher_list);
-+
-+ if (s->cipher_list_by_id)
-+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
-+
-+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
-+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
-+ }
-+ }
- #endif
- /* Worst case, we will use the NULL compression, but if we have other
- * options, we will now look for them. We have i-1 compression
-@@ -1161,16 +1214,22 @@ int ssl3_send_server_hello(SSL *s)
- unsigned char *buf;
- unsigned char *p,*d;
- int i,sl;
-- unsigned long l,Time;
-+ unsigned long l;
-+#ifdef OPENSSL_NO_TLSEXT
-+ unsigned long Time;
-+#endif
-
- if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
- {
- buf=(unsigned char *)s->init_buf->data;
-+#ifdef OPENSSL_NO_TLSEXT
- p=s->s3->server_random;
-+ /* Generate server_random if it was not needed previously */
- Time=(unsigned long)time(NULL); /* Time */
- l2n(Time,p);
- if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
- return -1;
-+#endif
- /* Do the message type and length last */
- d=p= &(buf[4]);
-
-diff -upr openssl-0.9.8za.orig/ssl/ssl_err.c openssl-0.9.8za/ssl/ssl_err.c
---- openssl-0.9.8za.orig/ssl/ssl_err.c 2014-06-05 11:09:08.000000000 +0300
-+++ openssl-0.9.8za/ssl/ssl_err.c 2014-06-05 20:37:09.225387312 +0300
-@@ -265,6 +265,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
- {ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"},
- {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
- {ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
-+{ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT), "SSL_set_session_ticket_ext"},
- {0,NULL}
- };
-
-diff -upr openssl-0.9.8za.orig/ssl/ssl.h openssl-0.9.8za/ssl/ssl.h
---- openssl-0.9.8za.orig/ssl/ssl.h 2014-06-05 11:09:08.000000000 +0300
-+++ openssl-0.9.8za/ssl/ssl.h 2014-06-05 20:37:09.229387312 +0300
-@@ -344,6 +344,7 @@ extern "C" {
- * 'struct ssl_st *' function parameters used to prototype callbacks
- * in SSL_CTX. */
- typedef struct ssl_st *ssl_crock_st;
-+typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
-
- /* used to hold info on the particular ciphers used */
- typedef struct ssl_cipher_st
-@@ -362,6 +363,9 @@ typedef struct ssl_cipher_st
-
- DECLARE_STACK_OF(SSL_CIPHER)
-
-+typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data, int len, void *arg);
-+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg);
-+
- /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
- typedef struct ssl_method_st
- {
-@@ -1053,6 +1057,18 @@ struct ssl_st
-
- /* RFC4507 session ticket expected to be received or sent */
- int tlsext_ticket_expected;
-+
-+ /* TLS Session Ticket extension override */
-+ TLS_SESSION_TICKET_EXT *tlsext_session_ticket;
-+
-+ /* TLS Session Ticket extension callback */
-+ tls_session_ticket_ext_cb_fn tls_session_ticket_ext_cb;
-+ void *tls_session_ticket_ext_cb_arg;
-+
-+ /* TLS pre-shared secret session resumption */
-+ tls_session_secret_cb_fn tls_session_secret_cb;
-+ void *tls_session_secret_cb_arg;
-+
- SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
- #define session_ctx initial_ctx
- #else
-@@ -1668,6 +1684,15 @@ void *SSL_COMP_get_compression_methods(v
- int SSL_COMP_add_compression_method(int id,void *cm);
- #endif
-
-+/* TLS extensions functions */
-+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len);
-+
-+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
-+ void *arg);
-+
-+/* Pre-shared secret session resumption functions */
-+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg);
-+
- /* BEGIN ERROR CODES */
- /* The following lines are auto generated by the script mkerr.pl. Any changes
- * made after this point may be overwritten when the script is next run.
-@@ -1872,6 +1897,7 @@ void ERR_load_SSL_strings(void);
- #define SSL_F_TLS1_ENC 210
- #define SSL_F_TLS1_SETUP_KEY_BLOCK 211
- #define SSL_F_WRITE_PENDING 212
-+#define SSL_F_SSL_SET_SESSION_TICKET_EXT 213
-
- /* Reason codes. */
- #define SSL_R_APP_DATA_IN_HANDSHAKE 100
-diff -upr openssl-0.9.8za.orig/ssl/ssl_sess.c openssl-0.9.8za/ssl/ssl_sess.c
---- openssl-0.9.8za.orig/ssl/ssl_sess.c 2014-06-05 11:09:08.000000000 +0300
-+++ openssl-0.9.8za/ssl/ssl_sess.c 2014-06-05 20:37:09.229387312 +0300
-@@ -712,6 +712,61 @@ long SSL_CTX_get_timeout(const SSL_CTX *
- return(s->session_timeout);
- }
-
-+#ifndef OPENSSL_NO_TLSEXT
-+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
-+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg)
-+ {
-+ if (s == NULL) return(0);
-+ s->tls_session_secret_cb = tls_session_secret_cb;
-+ s->tls_session_secret_cb_arg = arg;
-+ return(1);
-+ }
-+
-+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
-+ void *arg)
-+ {
-+ if (s == NULL) return(0);
-+ s->tls_session_ticket_ext_cb = cb;
-+ s->tls_session_ticket_ext_cb_arg = arg;
-+ return(1);
-+ }
-+
-+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
-+ {
-+ if (s->version >= TLS1_VERSION)
-+ {
-+ if (s->tlsext_session_ticket)
-+ {
-+ OPENSSL_free(s->tlsext_session_ticket);
-+ s->tlsext_session_ticket = NULL;
-+ }
-+
-+ s->tlsext_session_ticket = OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len);
-+ if (!s->tlsext_session_ticket)
-+ {
-+ SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE);
-+ return 0;
-+ }
-+
-+ if (ext_data)
-+ {
-+ s->tlsext_session_ticket->length = ext_len;
-+ s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1;
-+ memcpy(s->tlsext_session_ticket->data, ext_data, ext_len);
-+ }
-+ else
-+ {
-+ s->tlsext_session_ticket->length = 0;
-+ s->tlsext_session_ticket->data = NULL;
-+ }
-+
-+ return 1;
-+ }
-+
-+ return 0;
-+ }
-+#endif /* OPENSSL_NO_TLSEXT */
-+
- typedef struct timeout_param_st
- {
- SSL_CTX *ctx;
-diff -upr openssl-0.9.8za.orig/ssl/t1_lib.c openssl-0.9.8za/ssl/t1_lib.c
---- openssl-0.9.8za.orig/ssl/t1_lib.c 2014-06-05 11:09:08.000000000 +0300
-+++ openssl-0.9.8za/ssl/t1_lib.c 2014-06-05 20:37:09.229387312 +0300
-@@ -106,6 +106,12 @@ int tls1_new(SSL *s)
-
- void tls1_free(SSL *s)
- {
-+#ifndef OPENSSL_NO_TLSEXT
-+ if (s->tlsext_session_ticket)
-+ {
-+ OPENSSL_free(s->tlsext_session_ticket);
-+ }
-+#endif
- ssl3_free(s);
- }
-
-@@ -206,8 +212,23 @@ unsigned char *ssl_add_clienthello_tlsex
- int ticklen;
- if (!s->new_session && s->session && s->session->tlsext_tick)
- ticklen = s->session->tlsext_ticklen;
-+ else if (s->session && s->tlsext_session_ticket &&
-+ s->tlsext_session_ticket->data)
-+ {
-+ ticklen = s->tlsext_session_ticket->length;
-+ s->session->tlsext_tick = OPENSSL_malloc(ticklen);
-+ if (!s->session->tlsext_tick)
-+ return NULL;
-+ memcpy(s->session->tlsext_tick,
-+ s->tlsext_session_ticket->data,
-+ ticklen);
-+ s->session->tlsext_ticklen = ticklen;
-+ }
- else
- ticklen = 0;
-+ if (ticklen == 0 && s->tlsext_session_ticket &&
-+ s->tlsext_session_ticket->data == NULL)
-+ goto skip_ext;
- /* Check for enough room 2 for extension type, 2 for len
- * rest for ticket
- */
-@@ -221,6 +242,7 @@ unsigned char *ssl_add_clienthello_tlsex
- ret += ticklen;
- }
- }
-+ skip_ext:
-
- if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp &&
- s->version != DTLS1_VERSION)
-@@ -574,6 +596,15 @@ int ssl_parse_clienthello_tlsext(SSL *s,
- return 0;
- renegotiate_seen = 1;
- }
-+ else if (type == TLSEXT_TYPE_session_ticket)
-+ {
-+ if (s->tls_session_ticket_ext_cb &&
-+ !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
-+ {
-+ *al = TLS1_AD_INTERNAL_ERROR;
-+ return 0;
-+ }
-+ }
- else if (type == TLSEXT_TYPE_status_request &&
- s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb)
- {
-@@ -751,6 +782,12 @@ int ssl_parse_serverhello_tlsext(SSL *s,
- }
- else if (type == TLSEXT_TYPE_session_ticket)
- {
-+ if (s->tls_session_ticket_ext_cb &&
-+ !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg))
-+ {
-+ *al = TLS1_AD_INTERNAL_ERROR;
-+ return 0;
-+ }
- if ((SSL_get_options(s) & SSL_OP_NO_TICKET)
- || (size > 0))
- {
-@@ -1043,6 +1080,15 @@ int tls1_process_ticket(SSL *s, unsigned
- s->tlsext_ticket_expected = 1;
- return 0; /* Cache miss */
- }
-+ if (s->tls_session_secret_cb)
-+ {
-+ /* Indicate cache miss here and instead of
-+ * generating the session from ticket now,
-+ * trigger abbreviated handshake based on
-+ * external mechanism to calculate the master
-+ * secret later. */
-+ return 0;
-+ }
- return tls_decrypt_ticket(s, p, size, session_id, len,
- ret);
- }
-diff -upr openssl-0.9.8za.orig/ssl/tls1.h openssl-0.9.8za/ssl/tls1.h
---- openssl-0.9.8za.orig/ssl/tls1.h 2014-06-05 11:09:08.000000000 +0300
-+++ openssl-0.9.8za/ssl/tls1.h 2014-06-05 20:37:09.229387312 +0300
-@@ -415,6 +415,13 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_T
- #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/
- #endif
-
-+/* TLS extension struct */
-+struct tls_session_ticket_ext_st
-+ {
-+ unsigned short length;
-+ void *data;
-+ };
-+
- #ifdef __cplusplus
- }
- #endif
-diff -upr openssl-0.9.8za.orig/util/ssleay.num openssl-0.9.8za/util/ssleay.num
---- openssl-0.9.8za.orig/util/ssleay.num 2014-06-05 12:38:45.000000000 +0300
-+++ openssl-0.9.8za/util/ssleay.num 2014-06-05 20:37:09.229387312 +0300
-@@ -242,3 +242,5 @@ SSL_set_SSL_CTX
- SSL_get_servername 291 EXIST::FUNCTION:TLSEXT
- SSL_get_servername_type 292 EXIST::FUNCTION:TLSEXT
- SSL_CTX_set_client_cert_engine 293 EXIST::FUNCTION:ENGINE
-+SSL_set_session_ticket_ext 306 EXIST::FUNCTION:TLSEXT
-+SSL_set_session_secret_cb 307 EXIST::FUNCTION:TLSEXT
+++ /dev/null
-This patch adds support for TLS SessionTicket extension (RFC 5077) for
-the parts used by EAP-FAST (RFC 4851).
-
-This is based on the patch from Alexey Kobozev <akobozev@cisco.com>
-(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
-
-OpenSSL 0.9.8zf does not enable TLS extension support by default, so it
-will need to be enabled by adding enable-tlsext to config script
-command line.
-
-
-diff -upr openssl-0.9.8zf.orig/ssl/s3_clnt.c openssl-0.9.8zf/ssl/s3_clnt.c
---- openssl-0.9.8zf.orig/ssl/s3_clnt.c 2015-03-19 15:46:46.000000000 +0200
-+++ openssl-0.9.8zf/ssl/s3_clnt.c 2015-03-24 16:19:14.043911769 +0200
-@@ -760,6 +760,23 @@ int ssl3_get_server_hello(SSL *s)
- goto f_err;
- }
-
-+#ifndef OPENSSL_NO_TLSEXT
-+ /* check if we want to resume the session based on external pre-shared secret */
-+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) {
-+ SSL_CIPHER *pref_cipher = NULL;
-+
-+ s->session->master_key_length = sizeof(s->session->master_key);
-+ if (s->tls_session_secret_cb(s, s->session->master_key,
-+ &s->session->master_key_length,
-+ NULL, &pref_cipher,
-+ s->tls_session_secret_cb_arg)) {
-+ s->session->cipher = pref_cipher ?
-+ pref_cipher : ssl_get_cipher_by_char(s, p + j);
-+ s->s3->flags |= SSL3_FLAGS_CCS_OK;
-+ }
-+ }
-+#endif /* OPENSSL_NO_TLSEXT */
-+
- if (j != 0 && j == s->session->session_id_length
- && memcmp(p, s->session->session_id, j) == 0) {
- if (s->sid_ctx_length != s->session->sid_ctx_length
-@@ -2684,12 +2701,8 @@ int ssl3_check_finished(SSL *s)
- {
- int ok;
- long n;
-- /*
-- * If we have no ticket or session ID is non-zero length (a match of a
-- * non-zero session length would never reach here) it cannot be a resumed
-- * session.
-- */
-- if (!s->session->tlsext_tick || s->session->session_id_length)
-+ /* If we have no ticket it cannot be a resumed session. */
-+ if (!s->session->tlsext_tick)
- return 1;
- /*
- * this function is called when we really expect a Certificate message,
-diff -upr openssl-0.9.8zf.orig/ssl/s3_srvr.c openssl-0.9.8zf/ssl/s3_srvr.c
---- openssl-0.9.8zf.orig/ssl/s3_srvr.c 2015-03-19 15:46:46.000000000 +0200
-+++ openssl-0.9.8zf/ssl/s3_srvr.c 2015-03-24 16:23:34.567909681 +0200
-@@ -999,6 +999,59 @@ int ssl3_get_client_hello(SSL *s)
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
- goto err;
- }
-+
-+ /* Check if we want to use external pre-shared secret for this
-+ * handshake for not reused session only. We need to generate
-+ * server_random before calling tls_session_secret_cb in order to allow
-+ * SessionTicket processing to use it in key derivation. */
-+ {
-+ unsigned long Time;
-+ unsigned char *pos;
-+ Time = (unsigned long)time(NULL); /* Time */
-+ pos = s->s3->server_random;
-+ l2n(Time, pos);
-+ if (RAND_pseudo_bytes(pos, SSL3_RANDOM_SIZE - 4) <= 0) {
-+ al = SSL_AD_INTERNAL_ERROR;
-+ goto f_err;
-+ }
-+ }
-+
-+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) {
-+ SSL_CIPHER *pref_cipher = NULL;
-+
-+ s->session->master_key_length = sizeof(s->session->master_key);
-+ if (s->tls_session_secret_cb(s, s->session->master_key,
-+ &s->session->master_key_length,
-+ ciphers, &pref_cipher,
-+ s->tls_session_secret_cb_arg)) {
-+ s->hit = 1;
-+ s->session->ciphers = ciphers;
-+ s->session->verify_result = X509_V_OK;
-+
-+ ciphers = NULL;
-+
-+ /* check if some cipher was preferred by call back */
-+ pref_cipher = pref_cipher ? pref_cipher :
-+ ssl3_choose_cipher(s, s->session->ciphers,
-+ SSL_get_ciphers(s));
-+ if (pref_cipher == NULL) {
-+ al = SSL_AD_HANDSHAKE_FAILURE;
-+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_SHARED_CIPHER);
-+ goto f_err;
-+ }
-+
-+ s->session->cipher = pref_cipher;
-+
-+ if (s->cipher_list)
-+ sk_SSL_CIPHER_free(s->cipher_list);
-+
-+ if (s->cipher_list_by_id)
-+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
-+
-+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
-+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
-+ }
-+ }
- #endif
- /*
- * Worst case, we will use the NULL compression, but if we have other
-@@ -1143,15 +1196,21 @@ int ssl3_send_server_hello(SSL *s)
- unsigned char *buf;
- unsigned char *p, *d;
- int i, sl;
-- unsigned long l, Time;
-+ unsigned long l;
-+#ifdef OPENSSL_NO_TLSEXT
-+ unsigned long Time;
-+#endif
-
- if (s->state == SSL3_ST_SW_SRVR_HELLO_A) {
- buf = (unsigned char *)s->init_buf->data;
-+#ifdef OPENSSL_NO_TLSEXT
- p = s->s3->server_random;
-+ /* Generate server_random if it was not needed previously */
- Time = (unsigned long)time(NULL); /* Time */
- l2n(Time, p);
- if (RAND_pseudo_bytes(p, SSL3_RANDOM_SIZE - 4) <= 0)
- return -1;
-+#endif
- /* Do the message type and length last */
- d = p = &(buf[4]);
-
-diff -upr openssl-0.9.8zf.orig/ssl/ssl_err.c openssl-0.9.8zf/ssl/ssl_err.c
---- openssl-0.9.8zf.orig/ssl/ssl_err.c 2015-03-19 15:46:46.000000000 +0200
-+++ openssl-0.9.8zf/ssl/ssl_err.c 2015-03-24 16:35:58.627903717 +0200
-@@ -316,6 +316,7 @@ static ERR_STRING_DATA SSL_str_functs[]
- {ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"},
- {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
- {ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
-+ {ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT), "SSL_set_session_ticket_ext"},
- {0, NULL}
- };
-
-diff -upr openssl-0.9.8zf.orig/ssl/ssl.h openssl-0.9.8zf/ssl/ssl.h
---- openssl-0.9.8zf.orig/ssl/ssl.h 2015-03-19 15:46:46.000000000 +0200
-+++ openssl-0.9.8zf/ssl/ssl.h 2015-03-24 16:25:44.339908641 +0200
-@@ -349,6 +349,7 @@ extern "C" {
- * function parameters used to prototype callbacks in SSL_CTX.
- */
- typedef struct ssl_st *ssl_crock_st;
-+typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
-
- /* used to hold info on the particular ciphers used */
- typedef struct ssl_cipher_st {
-@@ -366,6 +367,12 @@ typedef struct ssl_cipher_st {
-
- DECLARE_STACK_OF(SSL_CIPHER)
-
-+typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data,
-+ int len, void *arg);
-+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len,
-+ STACK_OF(SSL_CIPHER) *peer_ciphers,
-+ SSL_CIPHER **cipher, void *arg);
-+
- /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
- typedef struct ssl_method_st {
- int version;
-@@ -1116,6 +1123,18 @@ struct ssl_st {
- int tlsext_ocsp_resplen;
- /* RFC4507 session ticket expected to be received or sent */
- int tlsext_ticket_expected;
-+
-+ /* TLS Session Ticket extension override */
-+ TLS_SESSION_TICKET_EXT *tlsext_session_ticket;
-+
-+ /* TLS Session Ticket extension callback */
-+ tls_session_ticket_ext_cb_fn tls_session_ticket_ext_cb;
-+ void *tls_session_ticket_ext_cb_arg;
-+
-+ /* TLS pre-shared secret session resumption */
-+ tls_session_secret_cb_fn tls_session_secret_cb;
-+ void *tls_session_secret_cb_arg;
-+
- SSL_CTX *initial_ctx; /* initial ctx, used to store sessions */
- # define session_ctx initial_ctx
- # else
-@@ -1772,6 +1791,17 @@ void *SSL_COMP_get_compression_methods(v
- int SSL_COMP_add_compression_method(int id, void *cm);
- # endif
-
-+/* TLS extensions functions */
-+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len);
-+
-+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
-+ void *arg);
-+
-+/* Pre-shared secret session resumption functions */
-+int SSL_set_session_secret_cb(SSL *s,
-+ tls_session_secret_cb_fn tls_session_secret_cb,
-+ void *arg);
-+
- /* BEGIN ERROR CODES */
- /*
- * The following lines are auto generated by the script mkerr.pl. Any changes
-@@ -1977,6 +2007,7 @@ void ERR_load_SSL_strings(void);
- # define SSL_F_TLS1_ENC 210
- # define SSL_F_TLS1_SETUP_KEY_BLOCK 211
- # define SSL_F_WRITE_PENDING 212
-+#define SSL_F_SSL_SET_SESSION_TICKET_EXT 213
-
- /* Reason codes. */
- # define SSL_R_APP_DATA_IN_HANDSHAKE 100
-diff -upr openssl-0.9.8zf.orig/ssl/ssl_sess.c openssl-0.9.8zf/ssl/ssl_sess.c
---- openssl-0.9.8zf.orig/ssl/ssl_sess.c 2015-03-19 15:46:46.000000000 +0200
-+++ openssl-0.9.8zf/ssl/ssl_sess.c 2015-03-24 16:28:04.819907515 +0200
-@@ -716,6 +716,61 @@ long SSL_CTX_get_timeout(const SSL_CTX *
- return (s->session_timeout);
- }
-
-+#ifndef OPENSSL_NO_TLSEXT
-+int SSL_set_session_secret_cb(
-+ SSL *s,
-+ int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
-+ STACK_OF(SSL_CIPHER) *peer_ciphers,
-+ SSL_CIPHER **cipher, void *arg), void *arg)
-+{
-+ if (s == NULL)
-+ return 0;
-+ s->tls_session_secret_cb = tls_session_secret_cb;
-+ s->tls_session_secret_cb_arg = arg;
-+ return 1;
-+}
-+
-+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
-+ void *arg)
-+{
-+ if (s == NULL)
-+ return 0;
-+ s->tls_session_ticket_ext_cb = cb;
-+ s->tls_session_ticket_ext_cb_arg = arg;
-+ return 1;
-+}
-+
-+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
-+{
-+ if (s->version >= TLS1_VERSION) {
-+ if (s->tlsext_session_ticket) {
-+ OPENSSL_free(s->tlsext_session_ticket);
-+ s->tlsext_session_ticket = NULL;
-+ }
-+
-+ s->tlsext_session_ticket = OPENSSL_malloc(
-+ sizeof(TLS_SESSION_TICKET_EXT) + ext_len);
-+ if (!s->tlsext_session_ticket) {
-+ SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE);
-+ return 0;
-+ }
-+
-+ if (ext_data) {
-+ s->tlsext_session_ticket->length = ext_len;
-+ s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1;
-+ memcpy(s->tlsext_session_ticket->data, ext_data, ext_len);
-+ } else {
-+ s->tlsext_session_ticket->length = 0;
-+ s->tlsext_session_ticket->data = NULL;
-+ }
-+
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+#endif /* OPENSSL_NO_TLSEXT */
-+
- typedef struct timeout_param_st {
- SSL_CTX *ctx;
- long time;
-diff -upr openssl-0.9.8zf.orig/ssl/t1_lib.c openssl-0.9.8zf/ssl/t1_lib.c
---- openssl-0.9.8zf.orig/ssl/t1_lib.c 2015-03-19 15:46:46.000000000 +0200
-+++ openssl-0.9.8zf/ssl/t1_lib.c 2015-03-24 16:32:46.923905254 +0200
-@@ -108,6 +108,11 @@ int tls1_new(SSL *s)
-
- void tls1_free(SSL *s)
- {
-+#ifndef OPENSSL_NO_TLSEXT
-+ if (s->tlsext_session_ticket) {
-+ OPENSSL_free(s->tlsext_session_ticket);
-+ }
-+#endif
- ssl3_free(s);
- }
-
-@@ -206,8 +211,20 @@ unsigned char *ssl_add_clienthello_tlsex
- int ticklen;
- if (!s->new_session && s->session && s->session->tlsext_tick)
- ticklen = s->session->tlsext_ticklen;
-- else
-+ else if (s->session && s->tlsext_session_ticket &&
-+ s->tlsext_session_ticket->data) {
-+ ticklen = s->tlsext_session_ticket->length;
-+ s->session->tlsext_tick = OPENSSL_malloc(ticklen);
-+ if (!s->session->tlsext_tick)
-+ return NULL;
-+ memcpy(s->session->tlsext_tick, s->tlsext_session_ticket->data,
-+ ticklen);
-+ s->session->tlsext_ticklen = ticklen;
-+ } else
- ticklen = 0;
-+ if (ticklen == 0 && s->tlsext_session_ticket &&
-+ s->tlsext_session_ticket->data == NULL)
-+ goto skip_ext;
- /*
- * Check for enough room 2 for extension type, 2 for len rest for
- * ticket
-@@ -221,6 +238,7 @@ unsigned char *ssl_add_clienthello_tlsex
- ret += ticklen;
- }
- }
-+skip_ext:
-
- if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp &&
- s->version != DTLS1_VERSION) {
-@@ -560,6 +578,14 @@ int ssl_parse_clienthello_tlsext(SSL *s,
- if (!ssl_parse_clienthello_renegotiate_ext(s, data, size, al))
- return 0;
- renegotiate_seen = 1;
-+ } else if (type == TLSEXT_TYPE_session_ticket) {
-+ if (s->tls_session_ticket_ext_cb &&
-+ !s->tls_session_ticket_ext_cb(s, data, size,
-+ s->tls_session_ticket_ext_cb_arg))
-+ {
-+ *al = TLS1_AD_INTERNAL_ERROR;
-+ return 0;
-+ }
- } else if (type == TLSEXT_TYPE_status_request &&
- s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb) {
-
-@@ -710,6 +736,13 @@ int ssl_parse_serverhello_tlsext(SSL *s,
- }
- tlsext_servername = 1;
- } else if (type == TLSEXT_TYPE_session_ticket) {
-+ if (s->tls_session_ticket_ext_cb &&
-+ !s->tls_session_ticket_ext_cb(
-+ s, data, size,
-+ s->tls_session_ticket_ext_cb_arg)) {
-+ *al = TLS1_AD_INTERNAL_ERROR;
-+ return 0;
-+ }
- if ((SSL_get_options(s) & SSL_OP_NO_TICKET)
- || (size > 0)) {
- *al = TLS1_AD_UNSUPPORTED_EXTENSION;
-@@ -993,6 +1026,14 @@ int tls1_process_ticket(SSL *s, unsigned
- s->tlsext_ticket_expected = 1;
- return 0; /* Cache miss */
- }
-+ if (s->tls_session_secret_cb) {
-+ /* Indicate cache miss here and instead of
-+ * generating the session from ticket now,
-+ * trigger abbreviated handshake based on
-+ * external mechanism to calculate the master
-+ * secret later. */
-+ return 0;
-+ }
- return tls_decrypt_ticket(s, p, size, session_id, len, ret);
- }
- p += size;
-diff -upr openssl-0.9.8zf.orig/ssl/tls1.h openssl-0.9.8zf/ssl/tls1.h
---- openssl-0.9.8zf.orig/ssl/tls1.h 2015-03-19 15:46:46.000000000 +0200
-+++ openssl-0.9.8zf/ssl/tls1.h 2015-03-24 16:33:31.855904894 +0200
-@@ -460,6 +460,12 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_T
- # define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"
- # endif
-
-+/* TLS extension struct */
-+struct tls_session_ticket_ext_st {
-+ unsigned short length;
-+ void *data;
-+};
-+
- #ifdef __cplusplus
- }
- #endif
-diff -upr openssl-0.9.8zf.orig/util/ssleay.num openssl-0.9.8zf/util/ssleay.num
---- openssl-0.9.8zf.orig/util/ssleay.num 2015-03-19 15:47:15.000000000 +0200
-+++ openssl-0.9.8zf/util/ssleay.num 2015-03-24 16:33:51.127904739 +0200
-@@ -242,3 +242,5 @@ SSL_set_SSL_CTX
- SSL_get_servername 291 EXIST::FUNCTION:TLSEXT
- SSL_get_servername_type 292 EXIST::FUNCTION:TLSEXT
- SSL_CTX_set_client_cert_engine 293 EXIST::FUNCTION:ENGINE
-+SSL_set_session_ticket_ext 306 EXIST::FUNCTION:TLSEXT
-+SSL_set_session_secret_cb 307 EXIST::FUNCTION:TLSEXT
return;
}
- radius_msg_make_authenticator(msg, (u8 *) ctx, sizeof(*ctx));
+ radius_msg_make_authenticator(msg);
if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME,
(u8 *) "user", 4)) {
/*
* hostapd / RADIUS Accounting
- * Copyright (c) 2002-2009, 2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2009, 2012-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
size_t len;
int i;
struct wpabuf *b;
+ struct os_time now;
msg = radius_msg_new(RADIUS_CODE_ACCOUNTING_REQUEST,
radius_client_get_id(hapd->radius));
return NULL;
}
- if (sta) {
- radius_msg_make_authenticator(msg, (u8 *) sta, sizeof(*sta));
-
- if ((hapd->conf->wpa & 2) &&
- !hapd->conf->disable_pmksa_caching &&
- sta->eapol_sm && sta->eapol_sm->acct_multi_session_id_hi) {
- os_snprintf(buf, sizeof(buf), "%08X+%08X",
- sta->eapol_sm->acct_multi_session_id_hi,
- sta->eapol_sm->acct_multi_session_id_lo);
- if (!radius_msg_add_attr(
- msg, RADIUS_ATTR_ACCT_MULTI_SESSION_ID,
- (u8 *) buf, os_strlen(buf))) {
- wpa_printf(MSG_INFO,
- "Could not add Acct-Multi-Session-Id");
- goto fail;
- }
- }
- } else {
- radius_msg_make_authenticator(msg, (u8 *) hapd, sizeof(*hapd));
- }
-
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_STATUS_TYPE,
status_type)) {
wpa_printf(MSG_INFO, "Could not add Acct-Status-Type");
goto fail;
}
- if (!hostapd_config_get_radius_attr(hapd->conf->radius_acct_req_attr,
- RADIUS_ATTR_ACCT_AUTHENTIC) &&
- !radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_AUTHENTIC,
- hapd->conf->ieee802_1x ?
- RADIUS_ACCT_AUTHENTIC_RADIUS :
- RADIUS_ACCT_AUTHENTIC_LOCAL)) {
- wpa_printf(MSG_INFO, "Could not add Acct-Authentic");
- goto fail;
- }
-
if (sta) {
+ if (!hostapd_config_get_radius_attr(
+ hapd->conf->radius_acct_req_attr,
+ RADIUS_ATTR_ACCT_AUTHENTIC) &&
+ !radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_AUTHENTIC,
+ hapd->conf->ieee802_1x ?
+ RADIUS_ACCT_AUTHENTIC_RADIUS :
+ RADIUS_ACCT_AUTHENTIC_LOCAL)) {
+ wpa_printf(MSG_INFO, "Could not add Acct-Authentic");
+ goto fail;
+ }
+
/* Use 802.1X identity if available */
val = ieee802_1x_get_identity(sta->eapol_sm, &len);
wpa_printf(MSG_ERROR, "Could not add CUI from ACL");
goto fail;
}
+
+ if (sta->ipaddr &&
+ !radius_msg_add_attr_int32(msg,
+ RADIUS_ATTR_FRAMED_IP_ADDRESS,
+ be_to_host32(sta->ipaddr))) {
+ wpa_printf(MSG_ERROR,
+ "Could not add Framed-IP-Address");
+ goto fail;
+ }
+ }
+
+ os_get_time(&now);
+ if (now.sec > 1000000000 &&
+ !radius_msg_add_attr_int32(msg, RADIUS_ATTR_EVENT_TIMESTAMP,
+ now.sec)) {
+ wpa_printf(MSG_INFO, "Could not add Event-Timestamp");
+ goto fail;
+ }
+
+ /*
+ * Add Acct-Delay-Time with zero value for the first transmission. This
+ * will be updated within radius_client.c when retransmitting the frame.
+ */
+ if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_DELAY_TIME, 0)) {
+ wpa_printf(MSG_INFO, "Could not add Acct-Delay-Time");
+ goto fail;
}
return msg;
if (hostapd_drv_read_sta_data(hapd, data, sta->addr))
return -1;
- if (sta->last_rx_bytes > data->rx_bytes)
- sta->acct_input_gigawords++;
- if (sta->last_tx_bytes > data->tx_bytes)
- sta->acct_output_gigawords++;
- sta->last_rx_bytes = data->rx_bytes;
- sta->last_tx_bytes = data->tx_bytes;
+ if (!data->bytes_64bit) {
+ /* Extend 32-bit counters from the driver to 64-bit counters */
+ if (sta->last_rx_bytes_lo > data->rx_bytes)
+ sta->last_rx_bytes_hi++;
+ sta->last_rx_bytes_lo = data->rx_bytes;
+
+ if (sta->last_tx_bytes_lo > data->tx_bytes)
+ sta->last_tx_bytes_hi++;
+ sta->last_tx_bytes_lo = data->tx_bytes;
+ }
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
- HOSTAPD_LEVEL_DEBUG, "updated TX/RX stats: "
- "Acct-Input-Octets=%lu Acct-Input-Gigawords=%u "
- "Acct-Output-Octets=%lu Acct-Output-Gigawords=%u",
- sta->last_rx_bytes, sta->acct_input_gigawords,
- sta->last_tx_bytes, sta->acct_output_gigawords);
+ HOSTAPD_LEVEL_DEBUG,
+ "updated TX/RX stats: rx_bytes=%llu [%u:%u] tx_bytes=%llu [%u:%u] bytes_64bit=%d",
+ data->rx_bytes, sta->last_rx_bytes_hi,
+ sta->last_rx_bytes_lo,
+ data->tx_bytes, sta->last_tx_bytes_hi,
+ sta->last_tx_bytes_lo,
+ data->bytes_64bit);
return 0;
}
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
HOSTAPD_LEVEL_INFO,
- "starting accounting session %08X-%08X",
- sta->acct_session_id_hi, sta->acct_session_id_lo);
+ "starting accounting session %016llX",
+ (unsigned long long) sta->acct_session_id);
os_get_reltime(&sta->acct_session_start);
- sta->last_rx_bytes = sta->last_tx_bytes = 0;
- sta->acct_input_gigawords = sta->acct_output_gigawords = 0;
+ sta->last_rx_bytes_hi = 0;
+ sta->last_rx_bytes_lo = 0;
+ sta->last_tx_bytes_hi = 0;
+ sta->last_tx_bytes_lo = 0;
hostapd_drv_sta_clear_stats(hapd, sta->addr);
if (!hapd->conf->radius->acct_server)
int cause = sta->acct_terminate_cause;
struct hostap_sta_driver_data data;
struct os_reltime now_r, diff;
- struct os_time now;
- u32 gigawords;
+ u64 bytes;
if (!hapd->conf->radius->acct_server)
return;
}
os_get_reltime(&now_r);
- os_get_time(&now);
os_reltime_sub(&now_r, &sta->acct_session_start, &diff);
if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_SESSION_TIME,
diff.sec)) {
wpa_printf(MSG_INFO, "Could not add Acct-Output-Packets");
goto fail;
}
+ if (data.bytes_64bit)
+ bytes = data.rx_bytes;
+ else
+ bytes = ((u64) sta->last_rx_bytes_hi << 32) |
+ sta->last_rx_bytes_lo;
if (!radius_msg_add_attr_int32(msg,
RADIUS_ATTR_ACCT_INPUT_OCTETS,
- data.rx_bytes)) {
+ (u32) bytes)) {
wpa_printf(MSG_INFO, "Could not add Acct-Input-Octets");
goto fail;
}
- gigawords = sta->acct_input_gigawords;
-#if __WORDSIZE == 64
- gigawords += data.rx_bytes >> 32;
-#endif
- if (gigawords &&
- !radius_msg_add_attr_int32(
- msg, RADIUS_ATTR_ACCT_INPUT_GIGAWORDS,
- gigawords)) {
+ if (!radius_msg_add_attr_int32(msg,
+ RADIUS_ATTR_ACCT_INPUT_GIGAWORDS,
+ (u32) (bytes >> 32))) {
wpa_printf(MSG_INFO, "Could not add Acct-Input-Gigawords");
goto fail;
}
+ if (data.bytes_64bit)
+ bytes = data.tx_bytes;
+ else
+ bytes = ((u64) sta->last_tx_bytes_hi << 32) |
+ sta->last_tx_bytes_lo;
if (!radius_msg_add_attr_int32(msg,
RADIUS_ATTR_ACCT_OUTPUT_OCTETS,
- data.tx_bytes)) {
+ (u32) bytes)) {
wpa_printf(MSG_INFO, "Could not add Acct-Output-Octets");
goto fail;
}
- gigawords = sta->acct_output_gigawords;
-#if __WORDSIZE == 64
- gigawords += data.tx_bytes >> 32;
-#endif
- if (gigawords &&
- !radius_msg_add_attr_int32(
- msg, RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS,
- gigawords)) {
+ if (!radius_msg_add_attr_int32(msg,
+ RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS,
+ (u32) (bytes >> 32))) {
wpa_printf(MSG_INFO, "Could not add Acct-Output-Gigawords");
goto fail;
}
}
- if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_EVENT_TIMESTAMP,
- now.sec)) {
- wpa_printf(MSG_INFO, "Could not add Event-Timestamp");
- goto fail;
- }
-
if (eloop_terminated())
cause = RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_REBOOT;
eloop_cancel_timeout(accounting_interim_update, hapd, sta);
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
HOSTAPD_LEVEL_INFO,
- "stopped accounting session %08X-%08X",
- sta->acct_session_id_hi,
- sta->acct_session_id_lo);
+ "stopped accounting session %016llX",
+ (unsigned long long) sta->acct_session_id);
sta->acct_session_started = 0;
}
}
-void accounting_sta_get_id(struct hostapd_data *hapd,
- struct sta_info *sta)
+int accounting_sta_get_id(struct hostapd_data *hapd, struct sta_info *sta)
{
- sta->acct_session_id_lo = hapd->acct_session_id_lo++;
- if (hapd->acct_session_id_lo == 0) {
- hapd->acct_session_id_hi++;
- }
- sta->acct_session_id_hi = hapd->acct_session_id_hi;
+ return radius_gen_session_id((u8 *) &sta->acct_session_id,
+ sizeof(sta->acct_session_id));
}
if (!msg)
return;
- if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_TERMINATE_CAUSE,
- RADIUS_ACCT_TERMINATE_CAUSE_NAS_REBOOT))
- {
- wpa_printf(MSG_INFO, "Could not add Acct-Terminate-Cause");
- radius_msg_free(msg);
- return;
+ if (hapd->acct_session_id) {
+ char buf[20];
+
+ os_snprintf(buf, sizeof(buf), "%016llX",
+ (unsigned long long) hapd->acct_session_id);
+ if (!radius_msg_add_attr(msg, RADIUS_ATTR_ACCT_SESSION_ID,
+ (u8 *) buf, os_strlen(buf)))
+ wpa_printf(MSG_ERROR, "Could not add Acct-Session-Id");
}
if (radius_client_send(hapd->radius, msg, RADIUS_ACCT, NULL) < 0)
}
+static void accounting_interim_error_cb(const u8 *addr, void *ctx)
+{
+ struct hostapd_data *hapd = ctx;
+ struct sta_info *sta;
+ unsigned int i, wait_time;
+ int res;
+
+ sta = ap_get_sta(hapd, addr);
+ if (!sta)
+ return;
+ sta->acct_interim_errors++;
+ if (sta->acct_interim_errors > 10 /* RADIUS_CLIENT_MAX_RETRIES */) {
+ wpa_printf(MSG_DEBUG,
+ "Interim RADIUS accounting update failed for " MACSTR
+ " - too many errors, abandon this interim accounting update",
+ MAC2STR(addr));
+ sta->acct_interim_errors = 0;
+ /* Next update will be tried after normal update interval */
+ return;
+ }
+
+ /*
+ * Use a shorter update interval as an improved retransmission mechanism
+ * for failed interim accounting updates. This allows the statistics to
+ * be updated for each retransmission.
+ *
+ * RADIUS client code has already waited RADIUS_CLIENT_FIRST_WAIT.
+ * Schedule the first retry attempt immediately and every following one
+ * with exponential backoff.
+ */
+ if (sta->acct_interim_errors == 1) {
+ wait_time = 0;
+ } else {
+ wait_time = 3; /* RADIUS_CLIENT_FIRST_WAIT */
+ for (i = 1; i < sta->acct_interim_errors; i++)
+ wait_time *= 2;
+ }
+ res = eloop_deplete_timeout(wait_time, 0, accounting_interim_update,
+ hapd, sta);
+ if (res == 1)
+ wpa_printf(MSG_DEBUG,
+ "Interim RADIUS accounting update failed for " MACSTR
+ " (error count: %u) - schedule next update in %u seconds",
+ MAC2STR(addr), sta->acct_interim_errors, wait_time);
+ else if (res == 0)
+ wpa_printf(MSG_DEBUG,
+ "Interim RADIUS accounting update failed for " MACSTR
+ " (error count: %u)", MAC2STR(addr),
+ sta->acct_interim_errors);
+ else
+ wpa_printf(MSG_DEBUG,
+ "Interim RADIUS accounting update failed for " MACSTR
+ " (error count: %u) - no timer found", MAC2STR(addr),
+ sta->acct_interim_errors);
+}
+
+
/**
* accounting_init: Initialize accounting
* @hapd: hostapd BSS data
*/
int accounting_init(struct hostapd_data *hapd)
{
- struct os_time now;
-
- /* Acct-Session-Id should be unique over reboots. Using a random number
- * is preferred. If that is not available, take the current time. Mix
- * in microseconds to make this more likely to be unique. */
- os_get_time(&now);
- if (os_get_random((u8 *) &hapd->acct_session_id_hi,
- sizeof(hapd->acct_session_id_hi)) < 0)
- hapd->acct_session_id_hi = now.sec;
- hapd->acct_session_id_hi ^= now.usec;
+ if (radius_gen_session_id((u8 *) &hapd->acct_session_id,
+ sizeof(hapd->acct_session_id)) < 0)
+ return -1;
if (radius_client_register(hapd->radius, RADIUS_ACCT,
accounting_receive, hapd))
return -1;
+ radius_client_set_interim_error_cb(hapd->radius,
+ accounting_interim_error_cb, hapd);
accounting_report_state(hapd, 1);
#define ACCOUNTING_H
#ifdef CONFIG_NO_ACCOUNTING
-static inline void accounting_sta_get_id(struct hostapd_data *hapd,
- struct sta_info *sta)
+static inline int accounting_sta_get_id(struct hostapd_data *hapd,
+ struct sta_info *sta)
{
+ return 0;
}
static inline void accounting_sta_start(struct hostapd_data *hapd,
{
}
#else /* CONFIG_NO_ACCOUNTING */
-void accounting_sta_get_id(struct hostapd_data *hapd, struct sta_info *sta);
+int accounting_sta_get_id(struct hostapd_data *hapd, struct sta_info *sta);
void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta);
void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta);
int accounting_init(struct hostapd_data *hapd);
wpa_printf(MSG_DEBUG, "ACS: Survey analysis for selected bandwidth %d MHz",
n_chans == 1 ? 20 :
n_chans == 2 ? 40 :
- n_chans == 4 ? 80 :
- -1);
+ 80);
for (i = 0; i < iface->current_mode->num_channels; i++) {
double total_weight;
return HOSTAPD_CHAN_ACS;
}
+ if (!iface->current_mode)
+ return HOSTAPD_CHAN_INVALID;
+
acs_cleanup(iface);
err = acs_request_scan(iface);
void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
{
+ dl_list_init(&bss->anqp_elem);
+
bss->logger_syslog_level = HOSTAPD_LEVEL_INFO;
bss->logger_stdout_level = HOSTAPD_LEVEL_INFO;
bss->logger_syslog = (unsigned int) -1;
bss->dtim_period = 2;
bss->radius_server_auth_port = 1812;
+ bss->eap_sim_db_timeout = 1;
bss->ap_max_inactivity = AP_MAX_INACTIVITY;
bss->eapol_version = EAPOL_VERSION;
conf->ignore_assoc_probability = 0.0;
conf->ignore_reassoc_probability = 0.0;
conf->corrupt_gtk_rekey_mic_probability = 0.0;
+ conf->ecsa_ie_only = 0;
#endif /* CONFIG_TESTING_OPTIONS */
conf->acs = 0;
}
-int hostapd_mac_comp_empty(const void *a)
-{
- macaddr empty = { 0 };
- return os_memcmp(a, empty, sizeof(macaddr));
-}
-
-
static int hostapd_config_read_wpa_psk(const char *fname,
struct hostapd_ssid *ssid)
{
}
+static void hostapd_config_free_anqp_elem(struct hostapd_bss_config *conf)
+{
+ struct anqp_element *elem;
+
+ while ((elem = dl_list_first(&conf->anqp_elem, struct anqp_element,
+ list))) {
+ dl_list_del(&elem->list);
+ wpabuf_free(elem->payload);
+ os_free(elem);
+ }
+}
+
+
void hostapd_config_free_bss(struct hostapd_bss_config *conf)
{
struct hostapd_eap_user *user, *prev_user;
os_free(conf->private_key);
os_free(conf->private_key_passwd);
os_free(conf->ocsp_stapling_response);
+ os_free(conf->ocsp_stapling_response_multi);
os_free(conf->dh_file);
os_free(conf->openssl_ciphers);
os_free(conf->pac_opaque_encr_key);
os_free(conf->network_auth_type);
os_free(conf->anqp_3gpp_cell_net);
os_free(conf->domain_name);
+ hostapd_config_free_anqp_elem(conf);
#ifdef CONFIG_RADIUS_TEST
os_free(conf->dump_msk_file);
#endif /* CONFIG_HS20 */
wpabuf_free(conf->vendor_elements);
+ wpabuf_free(conf->assocresp_elements);
os_free(conf->sae_groups);
#ifdef CONFIG_ACS
os_free(conf->acs_chan_bias);
#endif /* CONFIG_ACS */
+ wpabuf_free(conf->lci);
+ wpabuf_free(conf->civic);
os_free(conf);
}
* Perform a binary search for given MAC address from a pre-sorted list.
*/
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 start, end, middle, res;
}
-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)
{
struct hostapd_vlan *v = vlan;
+ int i;
+
+ if (!vlan_desc->notempty || vlan_desc->untagged < 0 ||
+ vlan_desc->untagged > MAX_VLAN_ID)
+ return 0;
+ for (i = 0; i < MAX_NUM_TAGGED_VLAN; i++) {
+ if (vlan_desc->tagged[i] < 0 ||
+ vlan_desc->tagged[i] > MAX_VLAN_ID)
+ return 0;
+ }
+ if (!vlan_desc->untagged && !vlan_desc->tagged[0])
+ return 0;
+
while (v) {
- if (v->vlan_id == vlan_id || v->vlan_id == VLAN_ID_WILDCARD)
+ if (!vlan_compare(&v->vlan_desc, vlan_desc) ||
+ v->vlan_id == VLAN_ID_WILDCARD)
return 1;
v = v->next;
}
return -1;
}
- if (full_config && hostapd_mac_comp_empty(bss->bssid) != 0) {
+ if (full_config && !is_zero_ether_addr(bss->bssid)) {
size_t i;
for (i = 0; i < conf->num_bss; i++) {
}
#endif /* CONFIG_IEEE80211N */
+#ifdef CONFIG_IEEE80211AC
+ if (full_config && conf->ieee80211ac &&
+ bss->ssid.security_policy == SECURITY_STATIC_WEP) {
+ bss->disable_11ac = 1;
+ wpa_printf(MSG_ERROR,
+ "VHT (IEEE 802.11ac) with WEP is not allowed, disabling VHT capabilities");
+ }
+#endif /* CONFIG_IEEE80211AC */
+
#ifdef CONFIG_WPS
if (full_config && bss->wps_state && bss->ignore_broadcast_ssid) {
wpa_printf(MSG_INFO, "WPS: ignore_broadcast_ssid "
}
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_MBO
+ if (full_config && bss->mbo_enabled && (bss->wpa & 2) &&
+ bss->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
+ wpa_printf(MSG_ERROR,
+ "MBO: PMF needs to be enabled whenever using WPA2 with MBO");
+ return -1;
+ }
+#endif /* CONFIG_MBO */
+
return 0;
}
#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
#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 */
struct mac_acl_entry {
macaddr addr;
- int vlan_id;
+ struct vlan_description vlan_id;
};
struct hostapd_radius_servers;
#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 */
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;
};
#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 {
} 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
*/
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;
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;
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;
int ap_max_inactivity;
int ignore_broadcast_ssid;
+ int no_probe_resp_if_max_sta;
int wmm_enabled;
int wmm_uapsd;
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;
#endif /* CONFIG_RADIUS_TEST */
struct wpabuf *vendor_elements;
+ struct wpabuf *assocresp_elements;
unsigned int sae_anti_clogging_threshold;
int *sae_groups;
#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;
};
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 */
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
} *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);
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 *
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,
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
#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 */
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 (add_buf_data(&beacon, buf, pos - buf) < 0 ||
+ add_buf_data(&proberesp, buf, pos - buf) < 0)
+ goto fail;
+#endif /* CONFIG_HS20 */
- if (wpabuf_resize(&proberesp, pos - buf) != 0)
+#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;
- wpabuf_put_data(proberesp, buf, pos - buf);
}
-#endif /* CONFIG_HS20 */
+#endif /* CONFIG_MBO */
- 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);
- }
+ 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;
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;
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);
}
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);
}
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);
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);
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;
return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst,
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);
}
+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;
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);
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,
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,
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)
{
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);
}
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);
}
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);
}
MAC2STR(sta->addr), mlme_auth_alg_str(sta->auth_alg));
if (sta->auth_alg != WLAN_AUTH_FT && !(sta->flags & WLAN_STA_MFP))
mlme_deletekeys_request(hapd, sta);
+ ap_sta_clear_disconnect_timeouts(hapd, sta);
}
MAC2STR(sta->addr));
if (sta->auth_alg != WLAN_AUTH_FT)
mlme_deletekeys_request(hapd, sta);
+ ap_sta_clear_disconnect_timeouts(hapd, sta);
}
MAC2STR(sta->addr));
if (sta->auth_alg != WLAN_AUTH_FT)
mlme_deletekeys_request(hapd, sta);
+ ap_sta_clear_disconnect_timeouts(hapd, sta);
}
params.openssl_ciphers = hapd->conf->openssl_ciphers;
params.ocsp_stapling_response =
hapd->conf->ocsp_stapling_response;
+ params.ocsp_stapling_response_multi =
+ hapd->conf->ocsp_stapling_response_multi;
if (tls_global_set_params(hapd->ssl_ctx, ¶ms)) {
wpa_printf(MSG_ERROR, "Failed to set TLS parameters");
if (hapd->conf->eap_sim_db) {
hapd->eap_sim_db_priv =
eap_sim_db_init(hapd->conf->eap_sim_db,
+ hapd->conf->eap_sim_db_timeout,
hostapd_sim_db_cb, hapd);
if (hapd->eap_sim_db_priv == NULL) {
wpa_printf(MSG_ERROR, "Failed to initialize EAP-SIM "
#include "beacon.h"
#include "hs20.h"
#include "dfs.h"
+#include "taxonomy.h"
#ifdef NEED_AP_MLME
static u8 * hostapd_eid_rm_enabled_capab(struct hostapd_data *hapd, u8 *eid,
size_t len)
{
- if (!hapd->conf->radio_measurements || len < 2 + 4)
+ size_t i;
+
+ for (i = 0; i < RRM_CAPABILITIES_IE_LEN; i++) {
+ if (hapd->conf->radio_measurements[i])
+ break;
+ }
+
+ if (i == RRM_CAPABILITIES_IE_LEN || len < 2 + RRM_CAPABILITIES_IE_LEN)
return eid;
*eid++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
- *eid++ = 5;
- *eid++ = (hapd->conf->radio_measurements & BIT(0)) ?
- WLAN_RRM_CAPS_NEIGHBOR_REPORT : 0x00;
- *eid++ = 0x00;
- *eid++ = 0x00;
- *eid++ = 0x00;
- *eid++ = 0x00;
- return eid;
+ *eid++ = RRM_CAPABILITIES_IE_LEN;
+ os_memcpy(eid, hapd->conf->radio_measurements, RRM_CAPABILITIES_IE_LEN);
+
+ return eid + RRM_CAPABILITIES_IE_LEN;
}
static u8 * hostapd_eid_csa(struct hostapd_data *hapd, u8 *eid)
{
- u8 chan;
-
- if (!hapd->cs_freq_params.freq)
+#ifdef CONFIG_TESTING_OPTIONS
+ if (hapd->iface->cs_oper_class && hapd->iconf->ecsa_ie_only)
return eid;
+#endif /* CONFIG_TESTING_OPTIONS */
- if (ieee80211_freq_to_chan(hapd->cs_freq_params.freq, &chan) ==
- NUM_HOSTAPD_MODES)
+ if (!hapd->cs_freq_params.channel)
return eid;
*eid++ = WLAN_EID_CHANNEL_SWITCH;
*eid++ = 3;
*eid++ = hapd->cs_block_tx;
- *eid++ = chan;
+ *eid++ = hapd->cs_freq_params.channel;
*eid++ = hapd->cs_count;
return eid;
}
-static u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid)
+static u8 * hostapd_eid_ecsa(struct hostapd_data *hapd, u8 *eid)
{
- u8 sec_ch;
-
- if (!hapd->cs_freq_params.sec_channel_offset)
+ if (!hapd->cs_freq_params.channel || !hapd->iface->cs_oper_class)
return eid;
- if (hapd->cs_freq_params.sec_channel_offset == -1)
- sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;
- else if (hapd->cs_freq_params.sec_channel_offset == 1)
- sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;
- else
- return eid;
-
- *eid++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET;
- *eid++ = 1;
- *eid++ = sec_ch;
+ *eid++ = WLAN_EID_EXT_CHANSWITCH_ANN;
+ *eid++ = 4;
+ *eid++ = hapd->cs_block_tx;
+ *eid++ = hapd->iface->cs_oper_class;
+ *eid++ = hapd->cs_freq_params.channel;
+ *eid++ = hapd->cs_count;
return eid;
}
-static u8 * hostapd_add_csa_elems(struct hostapd_data *hapd, u8 *pos,
- u8 *start, unsigned int *csa_counter_off)
+static u8 * hostapd_eid_supported_op_classes(struct hostapd_data *hapd, u8 *eid)
{
- u8 *old_pos = pos;
+ u8 op_class, channel;
- if (!csa_counter_off)
- return pos;
+ if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA) ||
+ !hapd->iface->freq)
+ return eid;
- *csa_counter_off = 0;
- pos = hostapd_eid_csa(hapd, pos);
+ if (ieee80211_freq_to_channel_ext(hapd->iface->freq,
+ hapd->iconf->secondary_channel,
+ hapd->iconf->vht_oper_chwidth,
+ &op_class, &channel) ==
+ NUM_HOSTAPD_MODES)
+ return eid;
- if (pos != old_pos) {
- /* save an offset to the counter - should be last byte */
- *csa_counter_off = pos - start - 1;
- pos = hostapd_eid_secondary_channel(hapd, pos);
- }
+ *eid++ = WLAN_EID_SUPPORTED_OPERATING_CLASSES;
+ *eid++ = 2;
- return pos;
+ /* Current Operating Class */
+ *eid++ = op_class;
+
+ /* TODO: Advertise all the supported operating classes */
+ *eid++ = 0;
+
+ return eid;
}
int is_p2p, size_t *resp_len)
{
struct ieee80211_mgmt *resp;
- u8 *pos, *epos;
+ u8 *pos, *epos, *csa_pos;
size_t buflen;
#define MAX_PROBERESP_LEN 768
buflen += 5 + 2 + sizeof(struct ieee80211_vht_capabilities) +
2 + sizeof(struct ieee80211_vht_operation);
}
+
+ buflen += hostapd_mbo_ie_len(hapd);
+
resp = os_zalloc(buflen);
if (resp == NULL)
return NULL;
/* Power Constraint element */
pos = hostapd_eid_pwr_constraint(hapd, pos);
+ /* CSA IE */
+ csa_pos = hostapd_eid_csa(hapd, pos);
+ if (csa_pos != pos)
+ hapd->cs_c_off_proberesp = csa_pos - (u8 *) resp - 1;
+ pos = csa_pos;
+
/* ERP Information element */
pos = hostapd_eid_erp_info(hapd, pos);
pos = hostapd_eid_rm_enabled_capab(hapd, pos, epos - pos);
+ /* eCSA IE */
+ csa_pos = hostapd_eid_ecsa(hapd, pos);
+ if (csa_pos != pos)
+ hapd->cs_c_off_ecsa_proberesp = csa_pos - (u8 *) resp - 1;
+ pos = csa_pos;
+
+ pos = hostapd_eid_supported_op_classes(hapd, pos);
+
#ifdef CONFIG_IEEE80211N
+ /* Secondary Channel Offset element */
+ /* TODO: The standard doesn't specify a position for this element. */
+ pos = hostapd_eid_secondary_channel(hapd, pos);
+
pos = hostapd_eid_ht_capabilities(hapd, pos);
pos = hostapd_eid_ht_operation(hapd, pos);
#endif /* CONFIG_IEEE80211N */
pos = hostapd_eid_adv_proto(hapd, pos);
pos = hostapd_eid_roaming_consortium(hapd, pos);
- pos = hostapd_add_csa_elems(hapd, pos, (u8 *)resp,
- &hapd->cs_c_off_proberesp);
-
#ifdef CONFIG_FST
if (hapd->iface->fst_ies) {
os_memcpy(pos, wpabuf_head(hapd->iface->fst_ies),
#ifdef CONFIG_IEEE80211AC
if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
- pos = hostapd_eid_vht_capabilities(hapd, pos);
+ pos = hostapd_eid_vht_capabilities(hapd, pos, 0);
pos = hostapd_eid_vht_operation(hapd, pos);
+ pos = hostapd_eid_txpower_envelope(hapd, pos);
+ pos = hostapd_eid_wb_chsw_wrapper(hapd, pos);
}
if (hapd->conf->vendor_vht)
pos = hostapd_eid_vendor_vht(hapd, pos);
pos = hostapd_eid_osen(hapd, pos);
#endif /* CONFIG_HS20 */
+ pos = hostapd_eid_mbo(hapd, pos, (u8 *) resp + buflen - pos);
+
if (hapd->conf->vendor_elements) {
os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements),
wpabuf_len(hapd->conf->vendor_elements));
pos = ssid_list;
end = ssid_list + ssid_list_len;
- while (pos + 1 <= end) {
- if (pos + 2 + pos[1] > end)
+ while (end - pos >= 1) {
+ if (2 + pos[1] > end - pos)
break;
if (pos[1] == 0)
wildcard = 1;
MAC2STR(info->addr));
dl_list_del(&info->list);
iface->num_sta_seen--;
- os_free(info);
+ sta_track_del(info);
}
}
/* Add a new entry */
info = os_zalloc(sizeof(*info));
+ if (info == NULL)
+ return;
os_memcpy(info->addr, addr, ETH_ALEN);
os_get_reltime(&info->last_seen);
}
+#ifdef CONFIG_TAXONOMY
+void sta_track_claim_taxonomy_info(struct hostapd_iface *iface, const u8 *addr,
+ struct wpabuf **probe_ie_taxonomy)
+{
+ struct hostapd_sta_info *info;
+
+ info = sta_track_get(iface, addr);
+ if (!info)
+ return;
+
+ wpabuf_free(*probe_ie_taxonomy);
+ *probe_ie_taxonomy = info->probe_ie_taxonomy;
+ info->probe_ie_taxonomy = NULL;
+}
+#endif /* CONFIG_TAXONOMY */
+
+
void handle_probe_req(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len,
int ssi_signal)
size_t i, resp_len;
int noack;
enum ssid_match_result res;
+ int ret;
+ u16 csa_offs[2];
+ size_t csa_offs_len;
- ie = mgmt->u.probe_req.variable;
- if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req))
+ if (len < IEEE80211_HDRLEN)
return;
+ ie = ((const u8 *) mgmt) + IEEE80211_HDRLEN;
if (hapd->iconf->track_sta_max_num)
sta_track_add(hapd->iface, mgmt->sa);
- ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
+ ie_len = len - IEEE80211_HDRLEN;
for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++)
if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
}
#ifdef CONFIG_P2P
- if (hapd->p2p && elems.wps_ie) {
+ if (hapd->p2p && hapd->p2p_group && elems.wps_ie) {
struct wpabuf *wps;
wps = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA);
if (wps && !p2p_group_match_dev_type(hapd->p2p_group, wps)) {
wpabuf_free(wps);
}
- if (hapd->p2p && elems.p2p) {
+ if (hapd->p2p && hapd->p2p_group && elems.p2p) {
struct wpabuf *p2p;
p2p = ieee802_11_vendor_ie_concat(ie, ie_len, P2P_IE_VENDOR_TYPE);
if (p2p && !p2p_group_match_dev_id(hapd->p2p_group, p2p)) {
}
#endif /* CONFIG_P2P */
+#ifdef CONFIG_TAXONOMY
+ {
+ struct sta_info *sta;
+ struct hostapd_sta_info *info;
+
+ if ((sta = ap_get_sta(hapd, mgmt->sa)) != NULL) {
+ taxonomy_sta_info_probe_req(hapd, sta, ie, ie_len);
+ } else if ((info = sta_track_get(hapd->iface,
+ mgmt->sa)) != NULL) {
+ taxonomy_hostapd_sta_info_probe_req(hapd, info,
+ ie, ie_len);
+ }
+ }
+#endif /* CONFIG_TAXONOMY */
+
res = ssid_match(hapd, elems.ssid, elems.ssid_len,
elems.ssid_list, elems.ssid_list_len);
if (res == NO_SSID_MATCH) {
return;
}
+ if (hapd->conf->no_probe_resp_if_max_sta &&
+ is_multicast_ether_addr(mgmt->da) &&
+ is_multicast_ether_addr(mgmt->bssid) &&
+ hapd->num_sta >= hapd->conf->max_num_sta &&
+ !ap_get_sta(hapd, mgmt->sa)) {
+ wpa_printf(MSG_MSGDUMP, "%s: Ignore Probe Request from " MACSTR
+ " since no room for additional STA",
+ hapd->conf->iface, MAC2STR(mgmt->sa));
+ return;
+ }
+
#ifdef CONFIG_TESTING_OPTIONS
if (hapd->iconf->ignore_probe_probability > 0.0 &&
drand48() < hapd->iconf->ignore_probe_probability) {
noack = !!(res == WILDCARD_SSID_MATCH &&
is_broadcast_ether_addr(mgmt->da));
- if (hostapd_drv_send_mlme(hapd, resp, resp_len, noack) < 0)
+ csa_offs_len = 0;
+ if (hapd->csa_in_progress) {
+ if (hapd->cs_c_off_proberesp)
+ csa_offs[csa_offs_len++] =
+ hapd->cs_c_off_proberesp;
+
+ if (hapd->cs_c_off_ecsa_proberesp)
+ csa_offs[csa_offs_len++] =
+ hapd->cs_c_off_ecsa_proberesp;
+ }
+
+ ret = hostapd_drv_send_mlme_csa(hapd, resp, resp_len, noack,
+ csa_offs_len ? csa_offs : NULL,
+ csa_offs_len);
+
+ if (ret < 0)
wpa_printf(MSG_INFO, "handle_probe_req: send failed");
os_free(resp);
#endif /* NEED_AP_MLME */
+void sta_track_del(struct hostapd_sta_info *info)
+{
+#ifdef CONFIG_TAXONOMY
+ wpabuf_free(info->probe_ie_taxonomy);
+ info->probe_ie_taxonomy = NULL;
+#endif /* CONFIG_TAXONOMY */
+ os_free(info);
+}
+
+
int ieee802_11_build_ap_params(struct hostapd_data *hapd,
struct wpa_driver_ap_params *params)
{
size_t resp_len = 0;
#ifdef NEED_AP_MLME
u16 capab_info;
- u8 *pos, *tailpos;
+ u8 *pos, *tailpos, *csa_pos;
#define BEACON_HEAD_BUF_SIZE 256
#define BEACON_TAIL_BUF_SIZE 512
}
#endif /* CONFIG_IEEE80211AC */
+ tail_len += hostapd_mbo_ie_len(hapd);
+
tailpos = tail = os_malloc(tail_len);
if (head == NULL || tail == NULL) {
wpa_printf(MSG_ERROR, "Failed to set beacon data");
/* Power Constraint element */
tailpos = hostapd_eid_pwr_constraint(hapd, tailpos);
+ /* CSA IE */
+ csa_pos = hostapd_eid_csa(hapd, tailpos);
+ if (csa_pos != tailpos)
+ hapd->cs_c_off_beacon = csa_pos - tail - 1;
+ tailpos = csa_pos;
+
/* ERP Information element */
tailpos = hostapd_eid_erp_info(hapd, tailpos);
tailpos = hostapd_eid_bss_load(hapd, tailpos,
tail + BEACON_TAIL_BUF_SIZE - tailpos);
+ /* eCSA IE */
+ csa_pos = hostapd_eid_ecsa(hapd, tailpos);
+ if (csa_pos != tailpos)
+ hapd->cs_c_off_ecsa_beacon = csa_pos - tail - 1;
+ tailpos = csa_pos;
+
+ tailpos = hostapd_eid_supported_op_classes(hapd, tailpos);
+
#ifdef CONFIG_IEEE80211N
+ /* Secondary Channel Offset element */
+ /* TODO: The standard doesn't specify a position for this element. */
+ tailpos = hostapd_eid_secondary_channel(hapd, tailpos);
+
tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
tailpos = hostapd_eid_ht_operation(hapd, tailpos);
#endif /* CONFIG_IEEE80211N */
tailpos = hostapd_eid_interworking(hapd, tailpos);
tailpos = hostapd_eid_adv_proto(hapd, tailpos);
tailpos = hostapd_eid_roaming_consortium(hapd, tailpos);
- tailpos = hostapd_add_csa_elems(hapd, tailpos, tail,
- &hapd->cs_c_off_beacon);
#ifdef CONFIG_FST
if (hapd->iface->fst_ies) {
#ifdef CONFIG_IEEE80211AC
if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
- tailpos = hostapd_eid_vht_capabilities(hapd, tailpos);
+ tailpos = hostapd_eid_vht_capabilities(hapd, tailpos, 0);
tailpos = hostapd_eid_vht_operation(hapd, tailpos);
+ tailpos = hostapd_eid_txpower_envelope(hapd, tailpos);
+ tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos);
}
if (hapd->conf->vendor_vht)
tailpos = hostapd_eid_vendor_vht(hapd, tailpos);
tailpos = hostapd_eid_osen(hapd, tailpos);
#endif /* CONFIG_HS20 */
+ tailpos = hostapd_eid_mbo(hapd, tailpos, tail + tail_len - tailpos);
+
if (hapd->conf->vendor_elements) {
os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements),
wpabuf_len(hapd->conf->vendor_elements));
params->osen = 1;
}
#endif /* CONFIG_HS20 */
+ params->pbss = hapd->conf->pbss;
return 0;
}
struct wpa_driver_ap_params *params);
void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params);
void sta_track_add(struct hostapd_iface *iface, const u8 *addr);
+void sta_track_del(struct hostapd_sta_info *info);
void sta_track_expire(struct hostapd_iface *iface, int force);
struct hostapd_data *
sta_track_seen_on(struct hostapd_iface *iface, const u8 *addr,
const char *ifname);
+void sta_track_claim_taxonomy_info(struct hostapd_iface *iface, const u8 *addr,
+ struct wpabuf **probe_ie_taxonomy);
#endif /* BEACON_H */
#include "p2p_hostapd.h"
#include "ctrl_iface_ap.h"
#include "ap_drv_ops.h"
+#include "mbo_ap.h"
+#include "taxonomy.h"
static int hostapd_get_sta_tx_rx(struct hostapd_data *hapd,
return 0;
ret = os_snprintf(buf, buflen, "rx_packets=%lu\ntx_packets=%lu\n"
- "rx_bytes=%lu\ntx_bytes=%lu\n",
+ "rx_bytes=%llu\ntx_bytes=%llu\ninactive_msec=%lu\n",
data.rx_packets, data.tx_packets,
- data.rx_bytes, data.tx_bytes);
+ data.rx_bytes, data.tx_bytes, data.inactive_msec);
if (os_snprintf_error(buflen, ret))
return 0;
return ret;
len += res;
}
+ res = mbo_ap_get_info(sta, buf + len, buflen - len);
+ if (res >= 0)
+ len += res;
+
+ if (sta->supp_op_classes &&
+ buflen - len > (unsigned) (17 + 2 * sta->supp_op_classes[0])) {
+ len += os_snprintf(buf + len, buflen - len, "supp_op_classes=");
+ len += wpa_snprintf_hex(buf + len, buflen - len,
+ sta->supp_op_classes + 1,
+ sta->supp_op_classes[0]);
+ len += os_snprintf(buf + len, buflen - len, "\n");
+ }
+
return len;
}
int ret;
u8 *pos;
- if (hapd->driver->send_frame == NULL)
+ if (!hapd->drv_priv || !hapd->driver->send_frame)
return -1;
mgmt = os_zalloc(sizeof(*mgmt) + 100);
wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "P2P: Disconnect STA " MACSTR
" with minor reason code %u (stype=%u (%s))",
MAC2STR(addr), minor_reason_code, stype,
- fc2str(mgmt->frame_control));
+ fc2str(le_to_host16(mgmt->frame_control)));
os_memcpy(mgmt->da, addr, ETH_ALEN);
os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
if (pos) {
struct ieee80211_mgmt mgmt;
int encrypt;
- if (hapd->driver->send_frame == NULL)
+ if (!hapd->drv_priv || !hapd->driver->send_frame)
return -1;
pos += 6;
encrypt = atoi(pos);
}
#endif /* CONFIG_P2P_MANAGER */
- hostapd_drv_sta_deauth(hapd, addr, reason);
+ if (os_strstr(txtaddr, " tx=0"))
+ hostapd_drv_sta_remove(hapd, addr);
+ else
+ hostapd_drv_sta_deauth(hapd, addr, reason);
sta = ap_get_sta(hapd, addr);
if (sta)
ap_sta_deauthenticate(hapd, sta, reason);
if (pos) {
struct ieee80211_mgmt mgmt;
int encrypt;
- if (hapd->driver->send_frame == NULL)
+ if (!hapd->drv_priv || !hapd->driver->send_frame)
return -1;
pos += 6;
encrypt = atoi(pos);
}
#endif /* CONFIG_P2P_MANAGER */
- hostapd_drv_sta_disassoc(hapd, addr, reason);
+ if (os_strstr(txtaddr, " tx=0"))
+ hostapd_drv_sta_remove(hapd, addr);
+ else
+ hostapd_drv_sta_disassoc(hapd, addr, reason);
sta = ap_get_sta(hapd, addr);
if (sta)
ap_sta_disassociate(hapd, sta, reason);
}
+#ifdef CONFIG_TAXONOMY
+int hostapd_ctrl_iface_signature(struct hostapd_data *hapd,
+ const char *txtaddr,
+ char *buf, size_t buflen)
+{
+ u8 addr[ETH_ALEN];
+ struct sta_info *sta;
+
+ wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE SIGNATURE %s", txtaddr);
+
+ if (hwaddr_aton(txtaddr, addr))
+ return -1;
+
+ sta = ap_get_sta(hapd, addr);
+ if (!sta)
+ return -1;
+
+ return retrieve_sta_taxonomy(hapd, sta, buf, buflen);
+}
+#endif /* CONFIG_TAXONOMY */
+
+
+int hostapd_ctrl_iface_poll_sta(struct hostapd_data *hapd,
+ const char *txtaddr)
+{
+ u8 addr[ETH_ALEN];
+ struct sta_info *sta;
+
+ wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE POLL_STA %s", txtaddr);
+
+ if (hwaddr_aton(txtaddr, addr))
+ return -1;
+
+ sta = ap_get_sta(hapd, addr);
+ if (!sta)
+ return -1;
+
+ hostapd_drv_poll_client(hapd, hapd->own_addr, addr,
+ sta->flags & WLAN_STA_WMM);
+ return 0;
+}
+
+
int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
size_t buflen)
{
"channel=%u\n"
"secondary_channel=%d\n"
"ieee80211n=%d\n"
- "ieee80211ac=%d\n"
- "vht_oper_chwidth=%d\n"
- "vht_oper_centr_freq_seg0_idx=%d\n"
- "vht_oper_centr_freq_seg1_idx=%d\n",
+ "ieee80211ac=%d\n",
iface->conf->channel,
- iface->conf->secondary_channel,
- iface->conf->ieee80211n,
- iface->conf->ieee80211ac,
- iface->conf->vht_oper_chwidth,
- iface->conf->vht_oper_centr_freq_seg0_idx,
- iface->conf->vht_oper_centr_freq_seg1_idx);
+ iface->conf->ieee80211n && !hapd->conf->disable_11n ?
+ iface->conf->secondary_channel : 0,
+ iface->conf->ieee80211n && !hapd->conf->disable_11n,
+ iface->conf->ieee80211ac &&
+ !hapd->conf->disable_11ac);
if (os_snprintf_error(buflen - len, ret))
return len;
len += ret;
+ if (iface->conf->ieee80211ac && !hapd->conf->disable_11ac) {
+ ret = os_snprintf(buf + len, buflen - len,
+ "vht_oper_chwidth=%d\n"
+ "vht_oper_centr_freq_seg0_idx=%d\n"
+ "vht_oper_centr_freq_seg1_idx=%d\n",
+ iface->conf->vht_oper_chwidth,
+ iface->conf->vht_oper_centr_freq_seg0_idx,
+ iface->conf->vht_oper_centr_freq_seg1_idx);
+ if (os_snprintf_error(buflen - len, ret))
+ return len;
+ len += ret;
+ }
for (i = 0; i < iface->num_bss; i++) {
struct hostapd_data *bss = iface->bss[i];
{
return hostapd_drv_stop_ap(hapd);
}
+
+
+int hostapd_ctrl_iface_pmksa_list(struct hostapd_data *hapd, char *buf,
+ size_t len)
+{
+ return wpa_auth_pmksa_list(hapd->wpa_auth, buf, len);
+}
+
+
+void hostapd_ctrl_iface_pmksa_flush(struct hostapd_data *hapd)
+{
+ wpa_auth_pmksa_flush(hapd->wpa_auth);
+}
const char *txtaddr);
int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
const char *txtaddr);
+int hostapd_ctrl_iface_signature(struct hostapd_data *hapd,
+ const char *txtaddr,
+ char *buf, size_t buflen);
+int hostapd_ctrl_iface_poll_sta(struct hostapd_data *hapd,
+ const char *txtaddr);
int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
size_t buflen);
int hostapd_parse_csa_settings(const char *pos,
struct csa_settings *settings);
int hostapd_ctrl_iface_stop_ap(struct hostapd_data *hapd);
+int hostapd_ctrl_iface_pmksa_list(struct hostapd_data *hapd, char *buf,
+ size_t len);
+void hostapd_ctrl_iface_pmksa_flush(struct hostapd_data *hapd);
#endif /* CTRL_IFACE_AP_H */
return NULL;
if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
- _rand = os_random();
+ return NULL;
chan_idx = _rand % num_available_chandefs;
dfs_find_channel(iface, &chan, chan_idx, skip_radar);
skip_radar);
if (!channel) {
wpa_printf(MSG_ERROR, "could not get valid channel");
- return -1;
+ hostapd_set_state(iface, HAPD_IFACE_DFS);
+ return 0;
}
iface->freq = channel->freq;
if (!channel) {
wpa_printf(MSG_ERROR, "No valid channel available");
- hostapd_setup_interface_complete(iface, err);
return err;
}
}
-static int hostapd_csa_in_progress(struct hostapd_iface *iface)
-{
- unsigned int i;
- for (i = 0; i < iface->num_bss; i++)
- if (iface->bss[i]->csa_in_progress)
- return 1;
- return 0;
-}
-
-
static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
{
struct hostapd_channel_data *channel;
&vht_oper_centr_freq_seg1_idx,
skip_radar);
if (!channel) {
- /* FIXME: Wait for channel(s) to become available */
- hostapd_disable_iface(iface);
+ wpa_printf(MSG_INFO,
+ "%s: no DFS channels left, waiting for NOP to finish",
+ __func__);
return err;
}
/* TODO add correct implementation here */
set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width,
cf1, cf2, HOSTAPD_CHAN_DFS_USABLE);
+
+ /* Handle cases where all channels were initially unavailable */
+ if (iface->state == HAPD_IFACE_DFS && !iface->cac_started)
+ hostapd_handle_dfs(iface);
+
return 0;
}
wpa_printf(MSG_DEBUG, "dhcp_snoop: Found DHCPACK for " MACSTR
" @ IPv4 address %s/%d",
- MAC2STR(sta->addr), ipaddr_str(ntohl(b->your_ip)),
+ MAC2STR(sta->addr),
+ ipaddr_str(be_to_host32(b->your_ip)),
prefixlen);
if (sta->ipaddr == b->your_ip)
#include "wnm_ap.h"
#include "hostapd.h"
#include "ieee802_11.h"
+#include "ieee802_11_auth.h"
#include "sta_info.h"
#include "accounting.h"
#include "tkip_countermeasures.h"
#include "hw_features.h"
#include "dfs.h"
#include "beacon.h"
+#include "mbo_ap.h"
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
}
sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
+ /*
+ * ACL configurations to the drivers (implementing AP SME and ACL
+ * offload) without hostapd's knowledge, can result in a disconnection
+ * though the driver accepts the connection. Skip the hostapd check for
+ * ACL if the driver supports ACL offload to avoid potentially
+ * conflicting ACL rules.
+ */
+ if (hapd->iface->drv_max_acl_mac_addrs == 0 &&
+ hostapd_check_acl(hapd, addr, NULL) != HOSTAPD_ACL_ACCEPT) {
+ wpa_printf(MSG_INFO, "STA " MACSTR " not allowed to connect",
+ MAC2STR(addr));
+ reason = WLAN_REASON_UNSPECIFIED;
+ goto fail;
+ }
+
#ifdef CONFIG_P2P
if (elems.p2p) {
wpabuf_free(sta->p2p_ie);
sta->mb_ies = NULL;
#endif /* CONFIG_FST */
+ mbo_ap_check_sta_assoc(hapd, sta, &elems);
+
+ ap_copy_sta_supp_op_classes(sta, elems.supp_op_classes,
+ elems.supp_op_classes_len);
+
if (hapd->conf->wpa) {
if (ie == NULL || ielen == 0) {
#ifdef CONFIG_WPS
return WLAN_STATUS_INVALID_IE;
#endif /* CONFIG_HS20 */
}
+
+#ifdef CONFIG_MBO
+ if (hapd->conf->mbo_enabled && (hapd->conf->wpa & 2) &&
+ elems.mbo && sta->cell_capa && !(sta->flags & WLAN_STA_MFP) &&
+ hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
+ wpa_printf(MSG_INFO,
+ "MBO: Reject WPA2 association without PMF");
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
+ }
+#endif /* CONFIG_MBO */
+
#ifdef CONFIG_WPS
skip_wpa_check:
#endif /* CONFIG_WPS */
int offset, int width, int cf1, int cf2)
{
#ifdef NEED_AP_MLME
- int channel, chwidth, seg0_idx = 0, seg1_idx = 0, is_dfs;
+ int channel, chwidth, is_dfs;
+ u8 seg0_idx = 0, seg1_idx = 0;
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO,
seg1_idx = (cf2 - 5000) / 5;
break;
default:
- seg0_idx = hostapd_hw_get_channel(hapd, cf1);
- seg1_idx = hostapd_hw_get_channel(hapd, cf2);
+ ieee80211_freq_to_chan(cf1, &seg0_idx);
+ ieee80211_freq_to_chan(cf2, &seg1_idx);
break;
}
#ifdef CONFIG_ACS
-static void hostapd_acs_channel_selected(struct hostapd_data *hapd,
- struct acs_selected_channels *acs_res)
+void hostapd_acs_channel_selected(struct hostapd_data *hapd,
+ struct acs_selected_channels *acs_res)
{
int ret, i;
+ int err = 0;
if (hapd->iconf->channel) {
wpa_printf(MSG_INFO, "ACS: Channel was already set to %d",
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
"driver selected to bad hw_mode");
- return;
+ err = 1;
+ goto out;
}
}
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
"driver switched to bad channel");
- return;
+ err = 1;
+ goto out;
}
hapd->iconf->channel = acs_res->pri_channel;
hapd->iconf->secondary_channel = 1;
else {
wpa_printf(MSG_ERROR, "Invalid secondary channel!");
- return;
+ err = 1;
+ goto out;
}
if (hapd->iface->conf->ieee80211ac) {
}
}
- ret = hostapd_acs_completed(hapd->iface, 0);
+out:
+ ret = hostapd_acs_completed(hapd->iface, err);
if (ret) {
wpa_printf(MSG_ERROR,
"ACS: Possibly channel configuration is invalid");
size_t len, u16 stype, int ok)
{
struct ieee80211_hdr *hdr;
+ struct hostapd_data *orig_hapd = hapd;
hdr = (struct ieee80211_hdr *) buf;
hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
- if (hapd == NULL || hapd == HAPD_BROADCAST)
+ if (!hapd)
return;
+ if (hapd == HAPD_BROADCAST) {
+ if (stype != WLAN_FC_STYPE_ACTION || len <= 25 ||
+ buf[24] != WLAN_ACTION_PUBLIC)
+ return;
+ hapd = get_hapd_bssid(orig_hapd->iface, hdr->addr2);
+ if (!hapd || hapd == HAPD_BROADCAST)
+ return;
+ /*
+ * Allow processing of TX status for a Public Action frame that
+ * used wildcard BBSID.
+ */
+ }
ieee802_11_mgmt_cb(hapd, buf, len, stype, ok);
}
ieee802_1x_receive(hapd, src, data, data_len);
}
+#endif /* HOSTAPD */
+
static struct hostapd_channel_data * hostapd_get_mode_channel(
struct hostapd_iface *iface, unsigned int freq)
for (i = 0; i < iface->current_mode->num_channels; i++) {
chan = &iface->current_mode->channels[i];
- if (!chan)
- return NULL;
if ((unsigned int) chan->freq == freq)
return chan;
}
}
-static void hostapd_event_get_survey(struct hostapd_data *hapd,
- struct survey_results *survey_results)
+void hostapd_event_get_survey(struct hostapd_iface *iface,
+ struct survey_results *survey_results)
{
- struct hostapd_iface *iface = hapd->iface;
struct freq_survey *survey, *tmp;
struct hostapd_channel_data *chan;
}
+#ifdef HOSTAPD
#ifdef NEED_AP_MLME
static void hostapd_event_iface_unavailable(struct hostapd_data *hapd)
data->connect_failed_reason.code);
break;
case EVENT_SURVEY:
- hostapd_event_get_survey(hapd, &data->survey_results);
+ hostapd_event_get_survey(hapd->iface, &data->survey_results);
break;
#ifdef NEED_AP_MLME
case EVENT_INTERFACE_UNAVAILABLE:
}
}
+
+void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
+ union wpa_event_data *data)
+{
+ struct hapd_interfaces *interfaces = ctx;
+ struct hostapd_data *hapd;
+
+ if (event != EVENT_INTERFACE_STATUS)
+ return;
+
+ hapd = hostapd_get_iface(interfaces, data->interface_status.ifname);
+ if (hapd && hapd->driver && hapd->driver->get_ifindex &&
+ hapd->drv_priv) {
+ unsigned int ifindex;
+
+ ifindex = hapd->driver->get_ifindex(hapd->drv_priv);
+ if (ifindex != data->interface_status.ifindex) {
+ wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
+ "interface status ifindex %d mismatch (%d)",
+ ifindex, data->interface_status.ifindex);
+ return;
+ }
+ }
+ if (hapd)
+ wpa_supplicant_event(hapd, event, data);
+}
+
#endif /* HOSTAPD */
if (sta->gas_dialog[i].dialog_token != dialog_token ||
!sta->gas_dialog[i].valid)
continue;
+ ap_sta_replenish_timeout(hapd, sta, 5);
return &sta->gas_dialog[i];
}
wpa_printf(MSG_DEBUG, "ANQP: Could not find dialog for "
#endif /* CONFIG_HS20 */
+static struct anqp_element * get_anqp_elem(struct hostapd_data *hapd,
+ u16 infoid)
+{
+ struct anqp_element *elem;
+
+ dl_list_for_each(elem, &hapd->conf->anqp_elem, struct anqp_element,
+ list) {
+ if (elem->infoid == infoid)
+ return elem;
+ }
+
+ return NULL;
+}
+
+
+static void anqp_add_elem(struct hostapd_data *hapd, struct wpabuf *buf,
+ u16 infoid)
+{
+ struct anqp_element *elem;
+
+ elem = get_anqp_elem(hapd, infoid);
+ if (!elem)
+ return;
+ if (wpabuf_tailroom(buf) < 2 + 2 + wpabuf_len(elem->payload)) {
+ wpa_printf(MSG_DEBUG, "ANQP: No room for InfoID %u payload",
+ infoid);
+ return;
+ }
+
+ wpabuf_put_le16(buf, infoid);
+ wpabuf_put_le16(buf, wpabuf_len(elem->payload));
+ wpabuf_put_buf(buf, elem->payload);
+}
+
+
+static int anqp_add_override(struct hostapd_data *hapd, struct wpabuf *buf,
+ u16 infoid)
+{
+ if (get_anqp_elem(hapd, infoid)) {
+ anqp_add_elem(hapd, buf, infoid);
+ return 1;
+ }
+
+ return 0;
+}
+
+
static void anqp_add_capab_list(struct hostapd_data *hapd,
struct wpabuf *buf)
{
u8 *len;
+ u16 id;
+
+ if (anqp_add_override(hapd, buf, ANQP_CAPABILITY_LIST))
+ return;
len = gas_anqp_add_element(buf, ANQP_CAPABILITY_LIST);
wpabuf_put_le16(buf, ANQP_CAPABILITY_LIST);
- if (hapd->conf->venue_name)
+ if (hapd->conf->venue_name || get_anqp_elem(hapd, ANQP_VENUE_NAME))
wpabuf_put_le16(buf, ANQP_VENUE_NAME);
- if (hapd->conf->network_auth_type)
+ if (get_anqp_elem(hapd, ANQP_EMERGENCY_CALL_NUMBER))
+ wpabuf_put_le16(buf, ANQP_EMERGENCY_CALL_NUMBER);
+ if (hapd->conf->network_auth_type ||
+ get_anqp_elem(hapd, ANQP_NETWORK_AUTH_TYPE))
wpabuf_put_le16(buf, ANQP_NETWORK_AUTH_TYPE);
- if (hapd->conf->roaming_consortium)
+ if (hapd->conf->roaming_consortium ||
+ get_anqp_elem(hapd, ANQP_ROAMING_CONSORTIUM))
wpabuf_put_le16(buf, ANQP_ROAMING_CONSORTIUM);
- if (hapd->conf->ipaddr_type_configured)
+ if (hapd->conf->ipaddr_type_configured ||
+ get_anqp_elem(hapd, ANQP_IP_ADDR_TYPE_AVAILABILITY))
wpabuf_put_le16(buf, ANQP_IP_ADDR_TYPE_AVAILABILITY);
- if (hapd->conf->nai_realm_data)
+ if (hapd->conf->nai_realm_data ||
+ get_anqp_elem(hapd, ANQP_NAI_REALM))
wpabuf_put_le16(buf, ANQP_NAI_REALM);
- if (hapd->conf->anqp_3gpp_cell_net)
+ if (hapd->conf->anqp_3gpp_cell_net ||
+ get_anqp_elem(hapd, ANQP_3GPP_CELLULAR_NETWORK))
wpabuf_put_le16(buf, ANQP_3GPP_CELLULAR_NETWORK);
- if (hapd->conf->domain_name)
+ if (get_anqp_elem(hapd, ANQP_AP_GEOSPATIAL_LOCATION))
+ wpabuf_put_le16(buf, ANQP_AP_GEOSPATIAL_LOCATION);
+ if (get_anqp_elem(hapd, ANQP_AP_CIVIC_LOCATION))
+ wpabuf_put_le16(buf, ANQP_AP_CIVIC_LOCATION);
+ if (get_anqp_elem(hapd, ANQP_AP_LOCATION_PUBLIC_URI))
+ wpabuf_put_le16(buf, ANQP_AP_LOCATION_PUBLIC_URI);
+ if (hapd->conf->domain_name || get_anqp_elem(hapd, ANQP_DOMAIN_NAME))
wpabuf_put_le16(buf, ANQP_DOMAIN_NAME);
+ if (get_anqp_elem(hapd, ANQP_EMERGENCY_ALERT_URI))
+ wpabuf_put_le16(buf, ANQP_EMERGENCY_ALERT_URI);
+ if (get_anqp_elem(hapd, ANQP_EMERGENCY_NAI))
+ wpabuf_put_le16(buf, ANQP_EMERGENCY_NAI);
+ if (get_anqp_elem(hapd, ANQP_NEIGHBOR_REPORT))
+ wpabuf_put_le16(buf, ANQP_NEIGHBOR_REPORT);
+ for (id = 273; id < 277; id++) {
+ if (get_anqp_elem(hapd, id))
+ wpabuf_put_le16(buf, id);
+ }
+ if (get_anqp_elem(hapd, ANQP_VENUE_URL))
+ wpabuf_put_le16(buf, ANQP_VENUE_URL);
+ if (get_anqp_elem(hapd, ANQP_ADVICE_OF_CHARGE))
+ wpabuf_put_le16(buf, ANQP_ADVICE_OF_CHARGE);
+ if (get_anqp_elem(hapd, ANQP_LOCAL_CONTENT))
+ wpabuf_put_le16(buf, ANQP_LOCAL_CONTENT);
#ifdef CONFIG_HS20
anqp_add_hs_capab_list(hapd, buf);
#endif /* CONFIG_HS20 */
static void anqp_add_venue_name(struct hostapd_data *hapd, struct wpabuf *buf)
{
+ if (anqp_add_override(hapd, buf, ANQP_VENUE_NAME))
+ return;
+
if (hapd->conf->venue_name) {
u8 *len;
unsigned int i;
static void anqp_add_network_auth_type(struct hostapd_data *hapd,
struct wpabuf *buf)
{
+ if (anqp_add_override(hapd, buf, ANQP_NETWORK_AUTH_TYPE))
+ return;
+
if (hapd->conf->network_auth_type) {
wpabuf_put_le16(buf, ANQP_NETWORK_AUTH_TYPE);
wpabuf_put_le16(buf, hapd->conf->network_auth_type_len);
unsigned int i;
u8 *len;
+ if (anqp_add_override(hapd, buf, ANQP_ROAMING_CONSORTIUM))
+ return;
+
len = gas_anqp_add_element(buf, ANQP_ROAMING_CONSORTIUM);
for (i = 0; i < hapd->conf->roaming_consortium_count; i++) {
struct hostapd_roaming_consortium *rc;
static void anqp_add_ip_addr_type_availability(struct hostapd_data *hapd,
struct wpabuf *buf)
{
+ if (anqp_add_override(hapd, buf, ANQP_IP_ADDR_TYPE_AVAILABILITY))
+ return;
+
if (hapd->conf->ipaddr_type_configured) {
wpabuf_put_le16(buf, ANQP_IP_ADDR_TYPE_AVAILABILITY);
wpabuf_put_le16(buf, 1);
pos = home_realm;
end = pos + home_realm_len;
- if (pos + 1 > end) {
+ if (end - pos < 1) {
wpa_hexdump(MSG_DEBUG, "Too short NAI Home Realm Query",
home_realm, home_realm_len);
return -1;
num_realms = *pos++;
for (i = 0; i < num_realms && num_matching < 10; i++) {
- if (pos + 2 > end) {
+ if (end - pos < 2) {
wpa_hexdump(MSG_DEBUG,
"Truncated NAI Home Realm Query",
home_realm, home_realm_len);
}
encoding = *pos++;
realm_len = *pos++;
- if (pos + realm_len > end) {
+ if (realm_len > end - pos) {
wpa_hexdump(MSG_DEBUG,
"Truncated NAI Home Realm Query",
home_realm, home_realm_len);
const u8 *home_realm, size_t home_realm_len,
int nai_realm, int nai_home_realm)
{
+ if (nai_realm && !nai_home_realm &&
+ anqp_add_override(hapd, buf, ANQP_NAI_REALM))
+ return;
+
if (nai_realm && hapd->conf->nai_realm_data) {
u8 *len;
unsigned int i, j;
static void anqp_add_3gpp_cellular_network(struct hostapd_data *hapd,
struct wpabuf *buf)
{
+ if (anqp_add_override(hapd, buf, ANQP_3GPP_CELLULAR_NETWORK))
+ return;
+
if (hapd->conf->anqp_3gpp_cell_net) {
wpabuf_put_le16(buf, ANQP_3GPP_CELLULAR_NETWORK);
wpabuf_put_le16(buf,
static void anqp_add_domain_name(struct hostapd_data *hapd, struct wpabuf *buf)
{
+ if (anqp_add_override(hapd, buf, ANQP_DOMAIN_NAME))
+ return;
+
if (hapd->conf->domain_name) {
wpabuf_put_le16(buf, ANQP_DOMAIN_NAME);
wpabuf_put_le16(buf, hapd->conf->domain_name_len);
#endif /* CONFIG_HS20 */
+static size_t anqp_get_required_len(struct hostapd_data *hapd,
+ const u16 *infoid,
+ unsigned int num_infoid)
+{
+ size_t len = 0;
+ unsigned int i;
+
+ for (i = 0; i < num_infoid; i++) {
+ struct anqp_element *elem = get_anqp_elem(hapd, infoid[i]);
+
+ if (elem)
+ len += 2 + 2 + wpabuf_len(elem->payload);
+ }
+
+ return len;
+}
+
+
static struct wpabuf *
gas_serv_build_gas_resp_payload(struct hostapd_data *hapd,
unsigned int request,
const u8 *home_realm, size_t home_realm_len,
- const u8 *icon_name, size_t icon_name_len)
+ const u8 *icon_name, size_t icon_name_len,
+ const u16 *extra_req,
+ unsigned int num_extra_req)
{
struct wpabuf *buf;
size_t len;
+ unsigned int i;
len = 1400;
if (request & (ANQP_REQ_NAI_REALM | ANQP_REQ_NAI_HOME_REALM))
len += 1000;
if (request & ANQP_REQ_ICON_REQUEST)
len += 65536;
+ len += anqp_get_required_len(hapd, extra_req, num_extra_req);
buf = wpabuf_alloc(len);
if (buf == NULL)
anqp_add_capab_list(hapd, buf);
if (request & ANQP_REQ_VENUE_NAME)
anqp_add_venue_name(hapd, buf);
+ if (request & ANQP_REQ_EMERGENCY_CALL_NUMBER)
+ anqp_add_elem(hapd, buf, ANQP_EMERGENCY_CALL_NUMBER);
if (request & ANQP_REQ_NETWORK_AUTH_TYPE)
anqp_add_network_auth_type(hapd, buf);
if (request & ANQP_REQ_ROAMING_CONSORTIUM)
request & ANQP_REQ_NAI_HOME_REALM);
if (request & ANQP_REQ_3GPP_CELLULAR_NETWORK)
anqp_add_3gpp_cellular_network(hapd, buf);
+ if (request & ANQP_REQ_AP_GEOSPATIAL_LOCATION)
+ anqp_add_elem(hapd, buf, ANQP_AP_GEOSPATIAL_LOCATION);
+ if (request & ANQP_REQ_AP_CIVIC_LOCATION)
+ anqp_add_elem(hapd, buf, ANQP_AP_CIVIC_LOCATION);
+ if (request & ANQP_REQ_AP_LOCATION_PUBLIC_URI)
+ anqp_add_elem(hapd, buf, ANQP_AP_LOCATION_PUBLIC_URI);
if (request & ANQP_REQ_DOMAIN_NAME)
anqp_add_domain_name(hapd, buf);
+ if (request & ANQP_REQ_EMERGENCY_ALERT_URI)
+ anqp_add_elem(hapd, buf, ANQP_EMERGENCY_ALERT_URI);
+ if (request & ANQP_REQ_TDLS_CAPABILITY)
+ anqp_add_elem(hapd, buf, ANQP_TDLS_CAPABILITY);
+ if (request & ANQP_REQ_EMERGENCY_NAI)
+ anqp_add_elem(hapd, buf, ANQP_EMERGENCY_NAI);
+
+ for (i = 0; i < num_extra_req; i++)
+ anqp_add_elem(hapd, buf, extra_req[i]);
#ifdef CONFIG_HS20
if (request & ANQP_REQ_HS_CAPABILITY_LIST)
}
+#define ANQP_MAX_EXTRA_REQ 20
+
struct anqp_query_info {
unsigned int request;
const u8 *home_realm_query;
const u8 *icon_name;
size_t icon_name_len;
int p2p_sd;
+ u16 extra_req[ANQP_MAX_EXTRA_REQ];
+ unsigned int num_extra_req;
};
set_anqp_req(ANQP_REQ_VENUE_NAME, "Venue Name",
hapd->conf->venue_name != NULL, qi);
break;
+ case ANQP_EMERGENCY_CALL_NUMBER:
+ set_anqp_req(ANQP_REQ_EMERGENCY_CALL_NUMBER,
+ "Emergency Call Number",
+ get_anqp_elem(hapd, info_id) != NULL, qi);
+ break;
case ANQP_NETWORK_AUTH_TYPE:
set_anqp_req(ANQP_REQ_NETWORK_AUTH_TYPE, "Network Auth Type",
hapd->conf->network_auth_type != NULL, qi);
"3GPP Cellular Network",
hapd->conf->anqp_3gpp_cell_net != NULL, qi);
break;
+ case ANQP_AP_GEOSPATIAL_LOCATION:
+ set_anqp_req(ANQP_REQ_AP_GEOSPATIAL_LOCATION,
+ "AP Geospatial Location",
+ get_anqp_elem(hapd, info_id) != NULL, qi);
+ break;
+ case ANQP_AP_CIVIC_LOCATION:
+ set_anqp_req(ANQP_REQ_AP_CIVIC_LOCATION,
+ "AP Civic Location",
+ get_anqp_elem(hapd, info_id) != NULL, qi);
+ break;
+ case ANQP_AP_LOCATION_PUBLIC_URI:
+ set_anqp_req(ANQP_REQ_AP_LOCATION_PUBLIC_URI,
+ "AP Location Public URI",
+ get_anqp_elem(hapd, info_id) != NULL, qi);
+ break;
case ANQP_DOMAIN_NAME:
set_anqp_req(ANQP_REQ_DOMAIN_NAME, "Domain Name",
hapd->conf->domain_name != NULL, qi);
break;
+ case ANQP_EMERGENCY_ALERT_URI:
+ set_anqp_req(ANQP_REQ_EMERGENCY_ALERT_URI,
+ "Emergency Alert URI",
+ get_anqp_elem(hapd, info_id) != NULL, qi);
+ break;
+ case ANQP_TDLS_CAPABILITY:
+ set_anqp_req(ANQP_REQ_TDLS_CAPABILITY,
+ "TDLS Capability",
+ get_anqp_elem(hapd, info_id) != NULL, qi);
+ break;
+ case ANQP_EMERGENCY_NAI:
+ set_anqp_req(ANQP_REQ_EMERGENCY_NAI,
+ "Emergency NAI",
+ get_anqp_elem(hapd, info_id) != NULL, qi);
+ break;
default:
- wpa_printf(MSG_DEBUG, "ANQP: Unsupported Info Id %u",
- info_id);
+ if (!get_anqp_elem(hapd, info_id)) {
+ wpa_printf(MSG_DEBUG, "ANQP: Unsupported Info Id %u",
+ info_id);
+ break;
+ }
+ if (qi->num_extra_req == ANQP_MAX_EXTRA_REQ) {
+ wpa_printf(MSG_DEBUG,
+ "ANQP: No more room for extra requests - ignore Info Id %u",
+ info_id);
+ break;
+ }
+ wpa_printf(MSG_DEBUG, "ANQP: Info Id %u (local)", info_id);
+ qi->extra_req[qi->num_extra_req] = info_id;
+ qi->num_extra_req++;
break;
}
}
wpa_printf(MSG_DEBUG, "ANQP: %u Info IDs requested in Query list",
(unsigned int) (end - pos) / 2);
- while (pos + 2 <= end) {
+ while (end - pos >= 2) {
rx_anqp_query_list_id(hapd, WPA_GET_LE16(pos), qi);
pos += 2;
}
u32 oui;
u8 subtype;
- if (pos + 4 > end) {
+ if (end - pos < 4) {
wpa_printf(MSG_DEBUG, "ANQP: Too short vendor specific ANQP "
"Query element");
return;
}
pos++;
- if (pos + 1 >= end)
+ if (end - pos <= 1)
return;
subtype = *pos++;
static void gas_serv_req_local_processing(struct hostapd_data *hapd,
const u8 *sa, u8 dialog_token,
- struct anqp_query_info *qi, int prot)
+ struct anqp_query_info *qi, int prot,
+ int std_addr3)
{
struct wpabuf *buf, *tx_buf;
buf = gas_serv_build_gas_resp_payload(hapd, qi->request,
qi->home_realm_query,
qi->home_realm_query_len,
- qi->icon_name, qi->icon_name_len);
+ qi->icon_name, qi->icon_name_len,
+ qi->extra_req, qi->num_extra_req);
wpa_hexdump_buf(MSG_MSGDUMP, "ANQP: Locally generated ANQP responses",
buf);
if (!buf)
return;
if (prot)
convert_to_protected_dual(tx_buf);
- hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
- wpabuf_head(tx_buf), wpabuf_len(tx_buf));
+ if (std_addr3)
+ hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
+ wpabuf_head(tx_buf),
+ wpabuf_len(tx_buf));
+ else
+ hostapd_drv_send_action_addr3_ap(hapd, hapd->iface->freq, 0, sa,
+ wpabuf_head(tx_buf),
+ wpabuf_len(tx_buf));
wpabuf_free(tx_buf);
}
static void gas_serv_rx_gas_initial_req(struct hostapd_data *hapd,
const u8 *sa,
- const u8 *data, size_t len, int prot)
+ const u8 *data, size_t len, int prot,
+ int std_addr3)
{
const u8 *pos = data;
const u8 *end = data + len;
adv_proto = pos++;
slen = *pos++;
- next = pos + slen;
- if (next > end || slen < 2) {
+ if (slen > end - pos || slen < 2) {
wpa_msg(hapd->msg_ctx, MSG_DEBUG,
"GAS: Invalid IE in GAS Initial Request");
return;
}
+ next = pos + slen;
pos++; /* skip QueryRespLenLimit and PAME-BI */
if (*pos != ACCESS_NETWORK_QUERY_PROTOCOL) {
wpabuf_put_le16(buf, 0); /* Query Response Length */
if (prot)
convert_to_protected_dual(buf);
- hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
- wpabuf_head(buf), wpabuf_len(buf));
+ if (std_addr3)
+ hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
+ wpabuf_head(buf),
+ wpabuf_len(buf));
+ else
+ hostapd_drv_send_action_addr3_ap(hapd,
+ hapd->iface->freq, 0,
+ sa, wpabuf_head(buf),
+ wpabuf_len(buf));
wpabuf_free(buf);
return;
}
pos = next;
/* Query Request */
- if (pos + 2 > end)
+ if (end - pos < 2)
return;
slen = WPA_GET_LE16(pos);
pos += 2;
- if (pos + slen > end)
+ if (slen > end - pos)
return;
end = pos + slen;
while (pos < end) {
u16 info_id, elen;
- if (pos + 4 > end)
+ if (end - pos < 4)
return;
info_id = WPA_GET_LE16(pos);
elen = WPA_GET_LE16(pos);
pos += 2;
- if (pos + elen > end) {
+ if (elen > end - pos) {
wpa_printf(MSG_DEBUG, "ANQP: Invalid Query Request");
return;
}
pos += elen;
}
- gas_serv_req_local_processing(hapd, sa, dialog_token, &qi, prot);
+ gas_serv_req_local_processing(hapd, sa, dialog_token, &qi, prot,
+ std_addr3);
}
static void gas_serv_rx_gas_comeback_req(struct hostapd_data *hapd,
const u8 *sa,
- const u8 *data, size_t len, int prot)
+ const u8 *data, size_t len, int prot,
+ int std_addr3)
{
struct gas_dialog_info *dialog;
struct wpabuf *buf, *tx_buf;
send_resp:
if (prot)
convert_to_protected_dual(tx_buf);
- hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
- wpabuf_head(tx_buf), wpabuf_len(tx_buf));
+ if (std_addr3)
+ hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
+ wpabuf_head(tx_buf),
+ wpabuf_len(tx_buf));
+ else
+ hostapd_drv_send_action_addr3_ap(hapd, hapd->iface->freq, 0, sa,
+ wpabuf_head(tx_buf),
+ wpabuf_len(tx_buf));
wpabuf_free(tx_buf);
}
struct hostapd_data *hapd = ctx;
const struct ieee80211_mgmt *mgmt;
const u8 *sa, *data;
- int prot;
+ int prot, std_addr3;
mgmt = (const struct ieee80211_mgmt *) buf;
if (len < IEEE80211_HDRLEN + 2)
*/
prot = mgmt->u.action.category == WLAN_ACTION_PROTECTED_DUAL;
sa = mgmt->sa;
+ if (hapd->conf->gas_address3 == 1)
+ std_addr3 = 1;
+ else if (hapd->conf->gas_address3 == 2)
+ std_addr3 = 0;
+ else
+ std_addr3 = is_broadcast_ether_addr(mgmt->bssid);
len -= IEEE80211_HDRLEN + 1;
data = buf + IEEE80211_HDRLEN + 1;
switch (data[0]) {
case WLAN_PA_GAS_INITIAL_REQ:
- gas_serv_rx_gas_initial_req(hapd, sa, data + 1, len - 1, prot);
+ gas_serv_rx_gas_initial_req(hapd, sa, data + 1, len - 1, prot,
+ std_addr3);
break;
case WLAN_PA_GAS_COMEBACK_REQ:
- gas_serv_rx_gas_comeback_req(hapd, sa, data + 1, len - 1, prot);
+ gas_serv_rx_gas_comeback_req(hapd, sa, data + 1, len - 1, prot,
+ std_addr3);
break;
}
}
#ifndef GAS_SERV_H
#define GAS_SERV_H
+/* First 16 ANQP InfoIDs can be included in the optimized bitmap */
#define ANQP_REQ_CAPABILITY_LIST \
(1 << (ANQP_CAPABILITY_LIST - ANQP_QUERY_LIST))
#define ANQP_REQ_VENUE_NAME \
(1 << (ANQP_VENUE_NAME - ANQP_QUERY_LIST))
+#define ANQP_REQ_EMERGENCY_CALL_NUMBER \
+ (1 << (ANQP_EMERGENCY_CALL_NUMBER - ANQP_QUERY_LIST))
#define ANQP_REQ_NETWORK_AUTH_TYPE \
(1 << (ANQP_NETWORK_AUTH_TYPE - ANQP_QUERY_LIST))
#define ANQP_REQ_ROAMING_CONSORTIUM \
(1 << (ANQP_NAI_REALM - ANQP_QUERY_LIST))
#define ANQP_REQ_3GPP_CELLULAR_NETWORK \
(1 << (ANQP_3GPP_CELLULAR_NETWORK - ANQP_QUERY_LIST))
+#define ANQP_REQ_AP_GEOSPATIAL_LOCATION \
+ (1 << (ANQP_AP_GEOSPATIAL_LOCATION - ANQP_QUERY_LIST))
+#define ANQP_REQ_AP_CIVIC_LOCATION \
+ (1 << (ANQP_AP_CIVIC_LOCATION - ANQP_QUERY_LIST))
+#define ANQP_REQ_AP_LOCATION_PUBLIC_URI \
+ (1 << (ANQP_AP_LOCATION_PUBLIC_URI - ANQP_QUERY_LIST))
#define ANQP_REQ_DOMAIN_NAME \
(1 << (ANQP_DOMAIN_NAME - ANQP_QUERY_LIST))
+#define ANQP_REQ_EMERGENCY_ALERT_URI \
+ (1 << (ANQP_EMERGENCY_ALERT_URI - ANQP_QUERY_LIST))
+#define ANQP_REQ_TDLS_CAPABILITY \
+ (1 << (ANQP_TDLS_CAPABILITY - ANQP_QUERY_LIST))
+#define ANQP_REQ_EMERGENCY_NAI \
+ (1 << (ANQP_EMERGENCY_NAI - ANQP_QUERY_LIST))
+/*
+ * First 16 Hotspot 2.0 vendor specific ANQP-elements can be included in the
+ * optimized bitmap.
+ */
#define ANQP_REQ_HS_CAPABILITY_LIST \
(0x10000 << HS20_STYPE_CAPABILITY_LIST)
#define ANQP_REQ_OPERATOR_FRIENDLY_NAME \
#include "utils/eloop.h"
#include "common/ieee802_11_defs.h"
#include "common/wpa_ctrl.h"
+#include "common/hw_features_common.h"
#include "radius/radius_client.h"
#include "radius/radius_das.h"
#include "eap_server/tncs.h"
#include "x_snoop.h"
#include "dhcp_snoop.h"
#include "ndisc_snoop.h"
+#include "neighbor_db.h"
+#include "rrm.h"
static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason);
static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
- char *ifname)
+ const char *ifname)
{
int i;
+ if (!ifname)
+ return;
for (i = 0; i < NUM_WEP_KEYS; i++) {
if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, NULL, i,
0, NULL, 0, NULL, 0)) {
wpabuf_free(hapd->mesh_pending_auth);
hapd->mesh_pending_auth = NULL;
#endif /* CONFIG_MESH */
+
+ hostapd_clean_rrm(hapd);
}
list))) {
dl_list_del(&info->list);
iface->num_sta_seen--;
- os_free(info);
+ sta_track_del(info);
}
}
if (hostapd_drv_none(hapd))
return 0;
+ if (iface->conf->use_driver_iface_addr)
+ return 0;
+
/* Generate BSSID mask that is large enough to cover the BSSIDs. */
/* Determine the bits necessary to cover the number of BSSIDs. */
/* Determine the bits necessary to any configured BSSIDs,
if they are higher than the number of BSSIDs. */
for (j = 0; j < iface->conf->num_bss; j++) {
- if (hostapd_mac_comp_empty(iface->conf->bss[j]->bssid) == 0) {
+ if (is_zero_ether_addr(iface->conf->bss[j]->bssid)) {
if (j)
auto_addr++;
continue;
if (attr->acct_session_id) {
num_attr++;
- if (attr->acct_session_id_len != 17) {
+ if (attr->acct_session_id_len != 16) {
wpa_printf(MSG_DEBUG,
"RADIUS DAS: Acct-Session-Id cannot match");
return NULL;
for (sta = hapd->sta_list; sta; sta = sta->next) {
if (!sta->radius_das_match)
continue;
- os_snprintf(buf, sizeof(buf), "%08X-%08X",
- sta->acct_session_id_hi,
- sta->acct_session_id_lo);
- if (os_memcmp(attr->acct_session_id, buf, 17) != 0)
+ os_snprintf(buf, sizeof(buf), "%016llX",
+ (unsigned long long) sta->acct_session_id);
+ if (os_memcmp(attr->acct_session_id, buf, 16) != 0)
sta->radius_das_match = 0;
else
count++;
if (attr->acct_multi_session_id) {
num_attr++;
- if (attr->acct_multi_session_id_len != 17) {
+ if (attr->acct_multi_session_id_len != 16) {
wpa_printf(MSG_DEBUG,
"RADIUS DAS: Acct-Multi-Session-Id cannot match");
return NULL;
if (!sta->radius_das_match)
continue;
if (!sta->eapol_sm ||
- !sta->eapol_sm->acct_multi_session_id_hi) {
+ !sta->eapol_sm->acct_multi_session_id) {
sta->radius_das_match = 0;
continue;
}
- os_snprintf(buf, sizeof(buf), "%08X+%08X",
- sta->eapol_sm->acct_multi_session_id_hi,
- sta->eapol_sm->acct_multi_session_id_lo);
- if (os_memcmp(attr->acct_multi_session_id, buf, 17) !=
+ os_snprintf(buf, sizeof(buf), "%016llX",
+ (unsigned long long)
+ sta->eapol_sm->acct_multi_session_id);
+ if (os_memcmp(attr->acct_multi_session_id, buf, 16) !=
0)
sta->radius_das_match = 0;
else
hapd->started = 1;
if (!first || first == -1) {
- if (hostapd_mac_comp_empty(conf->bssid) == 0) {
- /* Allocate the next available BSSID. */
- do {
- inc_byte_array(hapd->own_addr, ETH_ALEN);
- } while (mac_in_conf(hapd->iconf, hapd->own_addr));
- } else {
+ u8 *addr = hapd->own_addr;
+
+ if (!is_zero_ether_addr(conf->bssid)) {
/* Allocate the configured BSSID. */
os_memcpy(hapd->own_addr, conf->bssid, ETH_ALEN);
"the radio", conf->iface);
return -1;
}
+ } else if (hapd->iconf->use_driver_iface_addr) {
+ addr = NULL;
+ } else {
+ /* Allocate the next available BSSID. */
+ do {
+ inc_byte_array(hapd->own_addr, ETH_ALEN);
+ } while (mac_in_conf(hapd->iconf, hapd->own_addr));
}
hapd->interface_added = 1;
if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS,
- conf->iface, hapd->own_addr, hapd,
+ conf->iface, addr, hapd,
&hapd->drv_priv, force_ifname, if_addr,
conf->bridge[0] ? conf->bridge : NULL,
first == -1)) {
hapd->interface_added = 0;
return -1;
}
+
+ if (!addr)
+ os_memcpy(hapd->own_addr, if_addr, ETH_ALEN);
}
if (conf->wmm_enabled < 0)
conf->wmm_enabled = hapd->iconf->ieee80211n;
+#ifdef CONFIG_IEEE80211R
+ if (is_zero_ether_addr(conf->r1_key_holder))
+ os_memcpy(conf->r1_key_holder, hapd->own_addr, ETH_ALEN);
+#endif /* CONFIG_IEEE80211R */
+
#ifdef CONFIG_MESH
if (hapd->iface->mconf == NULL)
flush_old_stations = 0;
das_conf.time_window = conf->radius_das_time_window;
das_conf.require_event_timestamp =
conf->radius_das_require_event_timestamp;
+ das_conf.require_message_authenticator =
+ conf->radius_das_require_message_authenticator;
das_conf.ctx = hapd;
das_conf.disconnect = hostapd_das_disconnect;
hapd->radius_das = radius_das_init(&das_conf);
#endif /* CONFIG_FST */
-/**
- * hostapd_setup_interface_complete - Complete interface setup
- *
- * This function is called when previous steps in the interface setup has been
- * completed. This can also start operations, e.g., DFS, that will require
- * additional processing before interface is ready to be enabled. Such
- * operations will call this function from eloop callbacks when finished.
- */
-int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
+#ifdef NEED_AP_MLME
+static enum nr_chan_width hostapd_get_nr_chan_width(struct hostapd_data *hapd,
+ int ht, int vht)
+{
+ if (!ht && !vht)
+ return NR_CHAN_WIDTH_20;
+ if (!hapd->iconf->secondary_channel)
+ return NR_CHAN_WIDTH_20;
+ if (!vht || hapd->iconf->vht_oper_chwidth == VHT_CHANWIDTH_USE_HT)
+ return NR_CHAN_WIDTH_40;
+ if (hapd->iconf->vht_oper_chwidth == VHT_CHANWIDTH_80MHZ)
+ return NR_CHAN_WIDTH_80;
+ if (hapd->iconf->vht_oper_chwidth == VHT_CHANWIDTH_160MHZ)
+ return NR_CHAN_WIDTH_160;
+ if (hapd->iconf->vht_oper_chwidth == VHT_CHANWIDTH_80P80MHZ)
+ return NR_CHAN_WIDTH_80P80;
+ return NR_CHAN_WIDTH_20;
+}
+#endif /* NEED_AP_MLME */
+
+
+static void hostapd_set_own_neighbor_report(struct hostapd_data *hapd)
+{
+#ifdef NEED_AP_MLME
+ u16 capab = hostapd_own_capab_info(hapd);
+ int ht = hapd->iconf->ieee80211n && !hapd->conf->disable_11n;
+ int vht = hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac;
+ struct wpa_ssid_value ssid;
+ u8 channel, op_class;
+ int center_freq1 = 0, center_freq2 = 0;
+ enum nr_chan_width width;
+ u32 bssid_info;
+ struct wpabuf *nr;
+
+ if (!(hapd->conf->radio_measurements[0] &
+ WLAN_RRM_CAPS_NEIGHBOR_REPORT))
+ return;
+
+ bssid_info = 3; /* AP is reachable */
+ bssid_info |= NEI_REP_BSSID_INFO_SECURITY; /* "same as the AP" */
+ bssid_info |= NEI_REP_BSSID_INFO_KEY_SCOPE; /* "same as the AP" */
+
+ if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT)
+ bssid_info |= NEI_REP_BSSID_INFO_SPECTRUM_MGMT;
+
+ bssid_info |= NEI_REP_BSSID_INFO_RM; /* RRM is supported */
+
+ if (hapd->conf->wmm_enabled) {
+ bssid_info |= NEI_REP_BSSID_INFO_QOS;
+
+ if (hapd->conf->wmm_uapsd &&
+ (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD))
+ bssid_info |= NEI_REP_BSSID_INFO_APSD;
+ }
+
+ if (ht) {
+ bssid_info |= NEI_REP_BSSID_INFO_HT |
+ NEI_REP_BSSID_INFO_DELAYED_BA;
+
+ /* VHT bit added in IEEE P802.11-REVmc/D4.3 */
+ if (vht)
+ bssid_info |= NEI_REP_BSSID_INFO_VHT;
+ }
+
+ /* TODO: Set NEI_REP_BSSID_INFO_MOBILITY_DOMAIN if MDE is set */
+
+ ieee80211_freq_to_channel_ext(hapd->iface->freq,
+ hapd->iconf->secondary_channel,
+ hapd->iconf->vht_oper_chwidth,
+ &op_class, &channel);
+ width = hostapd_get_nr_chan_width(hapd, ht, vht);
+ if (vht) {
+ center_freq1 = ieee80211_chan_to_freq(
+ NULL, op_class,
+ hapd->iconf->vht_oper_centr_freq_seg0_idx);
+ if (width == NR_CHAN_WIDTH_80P80)
+ center_freq2 = ieee80211_chan_to_freq(
+ NULL, op_class,
+ hapd->iconf->vht_oper_centr_freq_seg1_idx);
+ } else if (ht) {
+ center_freq1 = hapd->iface->freq +
+ 10 * hapd->iconf->secondary_channel;
+ }
+
+ ssid.ssid_len = hapd->conf->ssid.ssid_len;
+ os_memcpy(ssid.ssid, hapd->conf->ssid.ssid, ssid.ssid_len);
+
+ /*
+ * Neighbor Report element size = BSSID + BSSID info + op_class + chan +
+ * phy type + wide bandwidth channel subelement.
+ */
+ nr = wpabuf_alloc(ETH_ALEN + 4 + 1 + 1 + 1 + 5);
+ if (!nr)
+ return;
+
+ wpabuf_put_data(nr, hapd->own_addr, ETH_ALEN);
+ wpabuf_put_le32(nr, bssid_info);
+ wpabuf_put_u8(nr, op_class);
+ wpabuf_put_u8(nr, channel);
+ wpabuf_put_u8(nr, ieee80211_get_phy_type(hapd->iface->freq, ht, vht));
+
+ /*
+ * Wide Bandwidth Channel subelement may be needed to allow the
+ * receiving STA to send packets to the AP. See IEEE P802.11-REVmc/D5.0
+ * Figure 9-301.
+ */
+ wpabuf_put_u8(nr, WNM_NEIGHBOR_WIDE_BW_CHAN);
+ wpabuf_put_u8(nr, 3);
+ wpabuf_put_u8(nr, width);
+ wpabuf_put_u8(nr, center_freq1);
+ wpabuf_put_u8(nr, center_freq2);
+
+ hostapd_neighbor_set(hapd, hapd->own_addr, &ssid, nr, hapd->iconf->lci,
+ hapd->iconf->civic);
+
+ wpabuf_free(nr);
+#endif /* NEED_AP_MLME */
+}
+
+
+static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
+ int err)
{
struct hostapd_data *hapd = iface->bss[0];
size_t j;
} while (j-- > 0);
goto fail;
}
- if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0)
+ if (is_zero_ether_addr(hapd->conf->bssid))
prev_addr = hapd->own_addr;
}
hapd = iface->bss[0];
hostapd_tx_queue_params(iface);
ap_list_init(iface);
- dl_list_init(&iface->sta_seen);
hostapd_set_acl(hapd);
if (iface->interfaces && iface->interfaces->terminate_on_error > 0)
iface->interfaces->terminate_on_error--;
+ for (j = 0; j < iface->num_bss; j++)
+ hostapd_set_own_neighbor_report(iface->bss[j]);
+
return 0;
fail:
/**
+ * hostapd_setup_interface_complete - Complete interface setup
+ *
+ * This function is called when previous steps in the interface setup has been
+ * completed. This can also start operations, e.g., DFS, that will require
+ * additional processing before interface is ready to be enabled. Such
+ * operations will call this function from eloop callbacks when finished.
+ */
+int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
+{
+ struct hapd_interfaces *interfaces = iface->interfaces;
+ struct hostapd_data *hapd = iface->bss[0];
+ unsigned int i;
+ int not_ready_in_sync_ifaces = 0;
+
+ if (!iface->need_to_start_in_sync)
+ return hostapd_setup_interface_complete_sync(iface, err);
+
+ if (err) {
+ wpa_printf(MSG_ERROR, "Interface initialization failed");
+ hostapd_set_state(iface, HAPD_IFACE_DISABLED);
+ iface->need_to_start_in_sync = 0;
+ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
+ if (interfaces && interfaces->terminate_on_error)
+ eloop_terminate();
+ return -1;
+ }
+
+ if (iface->ready_to_start_in_sync) {
+ /* Already in ready and waiting. should never happpen */
+ return 0;
+ }
+
+ for (i = 0; i < interfaces->count; i++) {
+ if (interfaces->iface[i]->need_to_start_in_sync &&
+ !interfaces->iface[i]->ready_to_start_in_sync)
+ not_ready_in_sync_ifaces++;
+ }
+
+ /*
+ * Check if this is the last interface, if yes then start all the other
+ * waiting interfaces. If not, add this interface to the waiting list.
+ */
+ if (not_ready_in_sync_ifaces > 1 && iface->state == HAPD_IFACE_DFS) {
+ /*
+ * If this interface went through CAC, do not synchronize, just
+ * start immediately.
+ */
+ iface->need_to_start_in_sync = 0;
+ wpa_printf(MSG_INFO,
+ "%s: Finished CAC - bypass sync and start interface",
+ iface->bss[0]->conf->iface);
+ return hostapd_setup_interface_complete_sync(iface, err);
+ }
+
+ if (not_ready_in_sync_ifaces > 1) {
+ /* need to wait as there are other interfaces still coming up */
+ iface->ready_to_start_in_sync = 1;
+ wpa_printf(MSG_INFO,
+ "%s: Interface waiting to sync with other interfaces",
+ iface->bss[0]->conf->iface);
+ return 0;
+ }
+
+ wpa_printf(MSG_INFO,
+ "%s: Last interface to sync - starting all interfaces",
+ iface->bss[0]->conf->iface);
+ iface->need_to_start_in_sync = 0;
+ hostapd_setup_interface_complete_sync(iface, err);
+ for (i = 0; i < interfaces->count; i++) {
+ if (interfaces->iface[i]->need_to_start_in_sync &&
+ interfaces->iface[i]->ready_to_start_in_sync) {
+ hostapd_setup_interface_complete_sync(
+ interfaces->iface[i], 0);
+ /* Only once the interfaces are sync started */
+ interfaces->iface[i]->need_to_start_in_sync = 0;
+ }
+ }
+
+ return 0;
+}
+
+
+/**
* hostapd_setup_interface - Setup of an interface
* @iface: Pointer to interface data.
* Returns: 0 on success, -1 on failure
hapd->iface = hapd_iface;
hapd->driver = hapd->iconf->driver;
hapd->ctrl_sock = -1;
+ dl_list_init(&hapd->ctrl_dst);
+ dl_list_init(&hapd->nr_db);
return hapd;
}
static void hostapd_bss_deinit(struct hostapd_data *hapd)
{
+ if (!hapd)
+ return;
wpa_printf(MSG_DEBUG, "%s: deinit bss %s", __func__,
hapd->conf->iface);
hostapd_bss_deinit_no_free(hapd);
}
#endif /* CONFIG_FST */
- for (j = iface->num_bss - 1; j >= 0; j--)
+ for (j = iface->num_bss - 1; j >= 0; j--) {
+ if (!iface->bss)
+ break;
hostapd_bss_deinit(iface->bss[j]);
+ }
}
size_t j;
wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
for (j = 0; j < iface->num_bss; j++) {
+ if (!iface->bss)
+ break;
wpa_printf(MSG_DEBUG, "%s: free hapd %p",
__func__, iface->bss[j]);
os_free(iface->bss[j]);
}
+struct hostapd_iface * hostapd_alloc_iface(void)
+{
+ struct hostapd_iface *hapd_iface;
+
+ hapd_iface = os_zalloc(sizeof(*hapd_iface));
+ if (!hapd_iface)
+ return NULL;
+
+ dl_list_init(&hapd_iface->sta_seen);
+
+ return hapd_iface;
+}
+
+
/**
* hostapd_init - Allocate and initialize per-interface data
* @config_file: Path to the configuration file
struct hostapd_data *hapd;
size_t i;
- hapd_iface = os_zalloc(sizeof(*hapd_iface));
+ hapd_iface = hostapd_alloc_iface();
if (hapd_iface == NULL)
goto fail;
return NULL;
interfaces->iface = iface;
hapd_iface = interfaces->iface[interfaces->count] =
- os_zalloc(sizeof(*hapd_iface));
+ hostapd_alloc_iface();
if (hapd_iface == NULL) {
wpa_printf(MSG_ERROR, "%s: Failed to allocate memory for "
"the interface", __func__);
}
hostapd_prune_associations(hapd, sta->addr);
+ ap_sta_clear_disconnect_timeouts(hapd, sta);
/* IEEE 802.11F (IAPP) */
if (hapd->conf->ieee802_11f)
wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER)) {
- wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
- "for " MACSTR " (%d seconds - ap_max_inactivity)",
- __func__, MAC2STR(sta->addr),
+ wpa_printf(MSG_DEBUG,
+ "%s: %s: reschedule ap_handle_timer timeout for "
+ MACSTR " (%d seconds - ap_max_inactivity)",
+ hapd->conf->iface, __func__, MAC2STR(sta->addr),
hapd->conf->ap_max_inactivity);
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_register_timeout(hapd->conf->ap_max_inactivity, 0,
void hostapd_set_state(struct hostapd_iface *iface, enum hostapd_iface_state s)
{
wpa_printf(MSG_INFO, "%s: interface state %s->%s",
- iface->conf->bss[0]->iface, hostapd_state_text(iface->state),
- hostapd_state_text(s));
+ iface->conf ? iface->conf->bss[0]->iface : "N/A",
+ hostapd_state_text(iface->state), hostapd_state_text(s));
iface->state = s;
}
+int hostapd_csa_in_progress(struct hostapd_iface *iface)
+{
+ unsigned int i;
+
+ for (i = 0; i < iface->num_bss; i++)
+ if (iface->bss[i]->csa_in_progress)
+ return 1;
+ return 0;
+}
+
+
#ifdef NEED_AP_MLME
static void free_beacon_data(struct beacon_data *beacon)
/*
- * TODO: This flow currently supports only changing frequency within the
- * same hw_mode. Any other changes to MAC parameters or provided settings (even
- * width) are not supported.
+ * TODO: This flow currently supports only changing channel and width within
+ * the same hw_mode. Any other changes to MAC parameters or provided settings
+ * are not supported.
*/
static int hostapd_change_config_freq(struct hostapd_data *hapd,
struct hostapd_config *conf,
return -1;
/* if a pointer to old_params is provided we save previous state */
- if (old_params) {
- old_params->channel = conf->channel;
- old_params->ht_enabled = conf->ieee80211n;
- old_params->sec_channel_offset = conf->secondary_channel;
+ if (old_params &&
+ hostapd_set_freq_params(old_params, conf->hw_mode,
+ hostapd_hw_get_freq(hapd, conf->channel),
+ conf->channel, conf->ieee80211n,
+ conf->ieee80211ac,
+ conf->secondary_channel,
+ conf->vht_oper_chwidth,
+ conf->vht_oper_centr_freq_seg0_idx,
+ conf->vht_oper_centr_freq_seg1_idx,
+ conf->vht_capab))
+ return -1;
+
+ switch (params->bandwidth) {
+ case 0:
+ case 20:
+ case 40:
+ conf->vht_oper_chwidth = VHT_CHANWIDTH_USE_HT;
+ break;
+ case 80:
+ if (params->center_freq2)
+ conf->vht_oper_chwidth = VHT_CHANWIDTH_80P80MHZ;
+ else
+ conf->vht_oper_chwidth = VHT_CHANWIDTH_80MHZ;
+ break;
+ case 160:
+ conf->vht_oper_chwidth = VHT_CHANWIDTH_160MHZ;
+ break;
+ default:
+ return -1;
}
conf->channel = channel;
conf->ieee80211n = params->ht_enabled;
conf->secondary_channel = params->sec_channel_offset;
+ ieee80211_freq_to_chan(params->center_freq1,
+ &conf->vht_oper_centr_freq_seg0_idx);
+ ieee80211_freq_to_chan(params->center_freq2,
+ &conf->vht_oper_centr_freq_seg1_idx);
/* TODO: maybe call here hostapd_config_check here? */
struct hostapd_iface *iface = hapd->iface;
struct hostapd_freq_params old_freq;
int ret;
+ u8 chan, vht_bandwidth;
os_memset(&old_freq, 0, sizeof(old_freq));
if (!iface || !iface->freq || hapd->csa_in_progress)
return -1;
+ switch (settings->freq_params.bandwidth) {
+ case 80:
+ if (settings->freq_params.center_freq2)
+ vht_bandwidth = VHT_CHANWIDTH_80P80MHZ;
+ else
+ vht_bandwidth = VHT_CHANWIDTH_80MHZ;
+ break;
+ case 160:
+ vht_bandwidth = VHT_CHANWIDTH_160MHZ;
+ break;
+ default:
+ vht_bandwidth = VHT_CHANWIDTH_USE_HT;
+ break;
+ }
+
+ if (ieee80211_freq_to_channel_ext(
+ settings->freq_params.freq,
+ settings->freq_params.sec_channel_offset,
+ vht_bandwidth,
+ &hapd->iface->cs_oper_class,
+ &chan) == NUM_HOSTAPD_MODES) {
+ wpa_printf(MSG_DEBUG,
+ "invalid frequency for channel switch (freq=%d, sec_channel_offset=%d, vht_enabled=%d)",
+ settings->freq_params.freq,
+ settings->freq_params.sec_channel_offset,
+ settings->freq_params.vht_enabled);
+ return -1;
+ }
+
+ settings->freq_params.channel = chan;
+
ret = hostapd_change_config_freq(iface->bss[0], iface->conf,
&settings->freq_params,
&old_freq);
return ret;
}
- settings->counter_offset_beacon = hapd->cs_c_off_beacon;
- settings->counter_offset_presp = hapd->cs_c_off_proberesp;
+ settings->counter_offset_beacon[0] = hapd->cs_c_off_beacon;
+ settings->counter_offset_presp[0] = hapd->cs_c_off_proberesp;
+ settings->counter_offset_beacon[1] = hapd->cs_c_off_ecsa_beacon;
+ settings->counter_offset_presp[1] = hapd->cs_c_off_ecsa_proberesp;
return 0;
}
hapd->cs_c_off_beacon = 0;
hapd->cs_c_off_proberesp = 0;
hapd->csa_in_progress = 0;
+ hapd->cs_c_off_ecsa_beacon = 0;
+ hapd->cs_c_off_ecsa_proberesp = 0;
}
hostapd_enable_iface(iface);
}
+#endif /* NEED_AP_MLME */
+
struct hostapd_data * hostapd_get_iface(struct hapd_interfaces *interfaces,
const char *ifname)
return NULL;
}
-#endif /* NEED_AP_MLME */
-
void hostapd_periodic_iface(struct hostapd_iface *iface)
{
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
#ifndef CONFIG_NO_VLAN
struct dynamic_iface *vlan_priv;
#endif /* CONFIG_NO_VLAN */
+ int eloop_initialized;
};
enum hostapd_chan_status {
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
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;
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;
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;
#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
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;
};
struct dl_list list;
u8 addr[ETH_ALEN];
struct os_reltime last_seen;
+#ifdef CONFIG_TAXONOMY
+ struct wpabuf *probe_ie_taxonomy;
+#endif /* CONFIG_TAXONOMY */
};
/**
*/
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];
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;
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 *
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
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,
res = ieee80211n_allowed_ht40_channel_pair(iface);
if (!res) {
iface->conf->secondary_channel = 0;
+ res = 1;
wpa_printf(MSG_INFO, "Fallback to 20 MHz");
}
struct wpa_driver_scan_params params;
int ret;
- if (!iface->conf->secondary_channel)
- return 0; /* HT40 not used */
+ /* Check that HT40 is used and PRI / SEC switch is allowed */
+ if (!iface->conf->secondary_channel || iface->conf->no_pri_sec_switch)
+ return 0;
hostapd_set_state(iface, HAPD_IFACE_HT_SCAN);
wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling "
#include "utils/includes.h"
#include <net/if.h>
#include <sys/ioctl.h>
-#ifdef USE_KERNEL_HEADERS
-#include <linux/if_packet.h>
-#else /* USE_KERNEL_HEADERS */
#include <netpacket/packet.h>
-#endif /* USE_KERNEL_HEADERS */
#include "utils/common.h"
#include "utils/eloop.h"
struct sockaddr_in *paddr, uaddr;
struct iapp_data *iapp;
struct ip_mreqn mreq;
+ int reuseaddr = 1;
iapp = os_zalloc(sizeof(*iapp));
if (iapp == NULL)
os_memset(&uaddr, 0, sizeof(uaddr));
uaddr.sin_family = AF_INET;
uaddr.sin_port = htons(IAPP_UDP_PORT);
+
+ if (setsockopt(iapp->udp_sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
+ sizeof(reuseaddr)) < 0) {
+ wpa_printf(MSG_INFO,
+ "iapp_init - setsockopt[UDP,SO_REUSEADDR]: %s",
+ strerror(errno));
+ /*
+ * Ignore this and try to continue. This is fine for single
+ * BSS cases, but may fail if multiple BSSes enable IAPP.
+ */
+ }
+
if (bind(iapp->udp_sock, (struct sockaddr *) &uaddr,
sizeof(uaddr)) < 0) {
wpa_printf(MSG_INFO, "iapp_init - bind[UDP]: %s",
#include "hw_features.h"
#include "ieee802_11.h"
#include "dfs.h"
+#include "mbo_ap.h"
+#include "rrm.h"
+#include "taxonomy.h"
u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
int capab = WLAN_CAPABILITY_ESS;
int privacy;
int dfs;
+ int i;
/* Check if any of configured channels require DFS */
dfs = hostapd_is_dfs_required(hapd->iface);
(hapd->iconf->spectrum_mgmt_required || dfs))
capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
- if (hapd->conf->radio_measurements)
- capab |= IEEE80211_CAP_RRM;
+ for (i = 0; i < RRM_CAPABILITIES_IE_LEN; i++) {
+ if (hapd->conf->radio_measurements[i]) {
+ capab |= IEEE80211_CAP_RRM;
+ break;
+ }
+ }
return capab;
}
if (!sta->challenge) {
/* Generate a pseudo-random challenge */
u8 key[8];
- struct os_time now;
- int r;
+
sta->challenge = os_zalloc(WLAN_AUTH_CHALLENGE_LEN);
if (sta->challenge == NULL)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
- os_get_time(&now);
- r = os_random();
- os_memcpy(key, &now.sec, 4);
- os_memcpy(key + 4, &r, 4);
+ if (os_get_random(key, sizeof(key)) < 0) {
+ os_free(sta->challenge);
+ sta->challenge = NULL;
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
+ }
+
rc4_skip(key, sizeof(key), 0,
sta->challenge, WLAN_AUTH_CHALLENGE_LEN);
}
#endif /* CONFIG_NO_RC4 */
-static void send_auth_reply(struct hostapd_data *hapd,
- const u8 *dst, const u8 *bssid,
- u16 auth_alg, u16 auth_transaction, u16 resp,
- const u8 *ies, size_t ies_len)
+static int send_auth_reply(struct hostapd_data *hapd,
+ const u8 *dst, const u8 *bssid,
+ u16 auth_alg, u16 auth_transaction, u16 resp,
+ const u8 *ies, size_t ies_len)
{
struct ieee80211_mgmt *reply;
u8 *buf;
size_t rlen;
+ int reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE;
rlen = IEEE80211_HDRLEN + sizeof(reply->u.auth) + ies_len;
buf = os_zalloc(rlen);
if (buf == NULL)
- return;
+ return -1;
reply = (struct ieee80211_mgmt *) buf;
reply->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
MAC2STR(dst), auth_alg, auth_transaction,
resp, (unsigned long) ies_len);
if (hostapd_drv_send_mlme(hapd, reply, rlen, 0) < 0)
- wpa_printf(MSG_INFO, "send_auth_reply: send");
+ wpa_printf(MSG_INFO, "send_auth_reply: send failed");
+ else
+ reply_res = WLAN_STATUS_SUCCESS;
os_free(buf);
+
+ return reply_res;
}
{
struct hostapd_data *hapd = ctx;
struct sta_info *sta;
+ int reply_res;
- send_auth_reply(hapd, dst, bssid, WLAN_AUTH_FT, auth_transaction,
- status, ies, ies_len);
-
- if (status != WLAN_STATUS_SUCCESS)
- return;
+ reply_res = send_auth_reply(hapd, dst, bssid, WLAN_AUTH_FT,
+ auth_transaction, status, ies, ies_len);
sta = ap_get_sta(hapd, dst);
if (sta == NULL)
return;
+ if (sta->added_unassoc && (reply_res != WLAN_STATUS_SUCCESS ||
+ status != WLAN_STATUS_SUCCESS)) {
+ hostapd_drv_sta_remove(hapd, sta->addr);
+ sta->added_unassoc = 0;
+ return;
+ }
+
+ if (status != WLAN_STATUS_SUCCESS)
+ return;
+
hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)");
sta->flags |= WLAN_STA_AUTH;
const u8 *bssid, int update)
{
struct wpabuf *data;
+ int reply_res;
data = auth_build_sae_commit(hapd, sta, update);
if (data == NULL)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
- send_auth_reply(hapd, sta->addr, bssid,
- WLAN_AUTH_SAE, 1, WLAN_STATUS_SUCCESS,
- wpabuf_head(data), wpabuf_len(data));
+ reply_res = send_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 1,
+ WLAN_STATUS_SUCCESS, wpabuf_head(data),
+ wpabuf_len(data));
wpabuf_free(data);
- return WLAN_STATUS_SUCCESS;
+ return reply_res;
}
const u8 *bssid)
{
struct wpabuf *data;
+ int reply_res;
data = auth_build_sae_confirm(hapd, sta);
if (data == NULL)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
- send_auth_reply(hapd, sta->addr, bssid,
- WLAN_AUTH_SAE, 2, WLAN_STATUS_SUCCESS,
- wpabuf_head(data), wpabuf_len(data));
+ reply_res = send_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 2,
+ WLAN_STATUS_SUCCESS, wpabuf_head(data),
+ wpabuf_len(data));
wpabuf_free(data);
- return WLAN_STATUS_SUCCESS;
+ return reply_res;
}
if (sae_check_big_sync(sta))
return;
sta->sae->sync++;
+ wpa_printf(MSG_DEBUG, "SAE: Auth SAE retransmit timer for " MACSTR
+ " (sync=%d state=%d)",
+ MAC2STR(sta->addr), sta->sae->sync, sta->sae->state);
switch (sta->sae->state) {
case SAE_COMMITTED:
}
+void sae_accept_sta(struct hostapd_data *hapd, struct sta_info *sta)
+{
+ sta->flags |= WLAN_STA_AUTH;
+ sta->auth_alg = WLAN_AUTH_SAE;
+ mlme_authenticate_indication(hapd, sta);
+ wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
+ sta->sae->state = SAE_ACCEPTED;
+ wpa_auth_pmksa_add_sae(hapd->wpa_auth, sta->addr,
+ sta->sae->pmk, sta->sae->pmkid);
+}
+
+
static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *bssid, u8 auth_transaction)
{
* message now to get alternating sequence of
* Authentication frames between the AP and STA.
* Confirm will be sent in
- * Commited -> Confirmed/Accepted transition
+ * Committed -> Confirmed/Accepted transition
* when receiving Confirm from STA.
*/
}
sae_set_retransmit_timer(hapd, sta);
} else {
- sta->flags |= WLAN_STA_AUTH;
- sta->auth_alg = WLAN_AUTH_SAE;
- mlme_authenticate_indication(hapd, sta);
- wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
- sta->sae->state = SAE_ACCEPTED;
- wpa_auth_pmksa_add_sae(hapd->wpa_auth, sta->addr,
- sta->sae->pmk);
+ sae_accept_sta(hapd, sta);
}
break;
case SAE_ACCEPTED:
") doing reauthentication",
MAC2STR(sta->addr));
ap_free_sta(hapd, sta);
+ wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
} else {
if (sae_check_big_sync(sta))
return WLAN_STATUS_SUCCESS;
}
+static void sae_pick_next_group(struct hostapd_data *hapd, struct sta_info *sta)
+{
+ struct sae_data *sae = sta->sae;
+ int i, *groups = hapd->conf->sae_groups;
+
+ if (sae->state != SAE_COMMITTED)
+ return;
+
+ wpa_printf(MSG_DEBUG, "SAE: Previously selected group: %d", sae->group);
+
+ for (i = 0; groups && groups[i] > 0; i++) {
+ if (sae->group == groups[i])
+ break;
+ }
+
+ if (!groups || groups[i] <= 0) {
+ wpa_printf(MSG_DEBUG,
+ "SAE: Previously selected group not found from the current configuration");
+ return;
+ }
+
+ for (;;) {
+ i++;
+ if (groups[i] <= 0) {
+ wpa_printf(MSG_DEBUG,
+ "SAE: No alternative group enabled");
+ return;
+ }
+
+ if (sae_set_group(sae, groups[i]) < 0)
+ continue;
+
+ break;
+ }
+ wpa_printf(MSG_DEBUG, "SAE: Selected new group: %d", groups[i]);
+}
+
+
static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
const struct ieee80211_mgmt *mgmt, size_t len,
u16 auth_transaction, u16 status_code)
{
- u16 resp = WLAN_STATUS_SUCCESS;
+ int resp = WLAN_STATUS_SUCCESS;
struct wpabuf *data = NULL;
if (!sta->sae) {
- if (auth_transaction != 1 || status_code != WLAN_STATUS_SUCCESS)
- return;
+ if (auth_transaction != 1 ||
+ status_code != WLAN_STATUS_SUCCESS) {
+ resp = -1;
+ goto remove_sta;
+ }
sta->sae = os_zalloc(sizeof(*sta->sae));
- if (sta->sae == NULL)
- return;
+ if (!sta->sae) {
+ resp = -1;
+ goto remove_sta;
+ }
sta->sae->state = SAE_NOTHING;
sta->sae->sync = 0;
}
+ if (sta->mesh_sae_pmksa_caching) {
+ wpa_printf(MSG_DEBUG,
+ "SAE: Cancel use of mesh PMKSA caching because peer starts SAE authentication");
+ wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
+ sta->mesh_sae_pmksa_caching = 0;
+ }
+
if (auth_transaction == 1) {
const u8 *token = NULL, *pos, *end;
size_t token_len = 0;
if (sta->sae->tmp->anti_clogging_token == NULL) {
wpa_printf(MSG_ERROR,
"SAE: Failed to alloc for anti-clogging token");
- return;
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto remove_sta;
}
/*
* Authentication frame, and the commit-scalar and
* COMMIT-ELEMENT previously sent.
*/
- if (auth_sae_send_commit(hapd, sta, mgmt->bssid, 0)) {
+ resp = auth_sae_send_commit(hapd, sta, mgmt->bssid, 0);
+ if (resp != WLAN_STATUS_SUCCESS) {
wpa_printf(MSG_ERROR,
"SAE: Failed to send commit message");
- return;
+ goto remove_sta;
}
sta->sae->state = SAE_COMMITTED;
sta->sae->sync = 0;
return;
}
+ if ((hapd->conf->mesh & MESH_ENABLED) &&
+ status_code ==
+ WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED &&
+ sta->sae->tmp) {
+ wpa_printf(MSG_DEBUG,
+ "SAE: Peer did not accept our SAE group");
+ sae_pick_next_group(hapd, sta);
+ goto remove_sta;
+ }
+
if (status_code != WLAN_STATUS_SUCCESS)
- return;
+ goto remove_sta;
resp = sae_parse_commit(sta->sae, mgmt->u.auth.variable,
((const u8 *) mgmt) + len -
wpa_printf(MSG_DEBUG,
"SAE: Drop commit message from " MACSTR " due to reflection attack",
MAC2STR(sta->addr));
- return;
+ goto remove_sta;
}
if (token && check_sae_token(hapd, sta->addr, token, token_len)
< 0) {
wpa_printf(MSG_DEBUG, "SAE: Drop commit message with "
"incorrect token from " MACSTR,
MAC2STR(sta->addr));
- return;
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto remove_sta;
}
if (resp != WLAN_STATUS_SUCCESS)
"SAE authentication (RX confirm, status=%u)",
status_code);
if (status_code != WLAN_STATUS_SUCCESS)
- return;
+ goto remove_sta;
if (sta->sae->state >= SAE_CONFIRMED ||
!(hapd->conf->mesh & MESH_ENABLED)) {
if (sae_check_confirm(sta->sae, mgmt->u.auth.variable,
"unexpected SAE authentication transaction %u (status=%u)",
auth_transaction, status_code);
if (status_code != WLAN_STATUS_SUCCESS)
- return;
+ goto remove_sta;
resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
}
data ? wpabuf_head(data) : (u8 *) "",
data ? wpabuf_len(data) : 0);
}
+
+remove_sta:
+ if (sta->added_unassoc && (resp != WLAN_STATUS_SUCCESS ||
+ status_code != WLAN_STATUS_SUCCESS)) {
+ hostapd_drv_sta_remove(hapd, sta->addr);
+ sta->added_unassoc = 0;
+ }
wpabuf_free(data);
}
u16 auth_alg, auth_transaction, status_code;
u16 resp = WLAN_STATUS_SUCCESS;
struct sta_info *sta = NULL;
- int res;
+ int res, reply_res;
u16 fc;
const u8 *challenge = NULL;
u32 session_timeout, acct_interim_interval;
- int vlan_id = 0;
+ struct vlan_description vlan_id;
struct hostapd_sta_wpa_psk_short *psk = NULL;
u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
size_t resp_ies_len = 0;
char *radius_cui = NULL;
u16 seq_ctrl;
+ os_memset(&vlan_id, 0, sizeof(vlan_id));
+
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
(unsigned long) len);
seq_ctrl);
return;
}
+#ifdef CONFIG_MESH
+ if ((hapd->conf->mesh & MESH_ENABLED) &&
+ sta->plink_state == PLINK_BLOCKED) {
+ wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR
+ " is blocked - drop Authentication frame",
+ MAC2STR(mgmt->sa));
+ return;
+ }
+#endif /* CONFIG_MESH */
} else {
#ifdef CONFIG_MESH
if (hapd->conf->mesh & MESH_ENABLED) {
/* if the mesh peer is not available, we don't do auth.
*/
wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR
- " not yet known - drop Authentiation frame",
+ " not yet known - drop Authentication frame",
MAC2STR(mgmt->sa));
/*
* Save a copy of the frame so that it can be processed
sta->last_seq_ctrl = seq_ctrl;
sta->last_subtype = WLAN_FC_STYPE_AUTH;
- if (vlan_id > 0) {
- if (!hostapd_vlan_id_valid(hapd->conf->vlan, vlan_id)) {
- hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
- HOSTAPD_LEVEL_INFO, "Invalid VLAN ID "
- "%d received from RADIUS server",
- vlan_id);
- resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
- goto fail;
- }
- sta->vlan_id = vlan_id;
+ if (vlan_id.notempty &&
+ !hostapd_vlan_valid(hapd->conf->vlan, &vlan_id)) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
- HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
+ HOSTAPD_LEVEL_INFO,
+ "Invalid VLAN %d%s received from RADIUS server",
+ vlan_id.untagged,
+ vlan_id.tagged[0] ? "+" : "");
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto fail;
}
+ if (ap_sta_set_vlan(hapd, sta, &vlan_id) < 0) {
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto fail;
+ }
+ if (sta->vlan_id)
+ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
+ HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
hostapd_free_psk_list(sta->psk);
if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) {
else
ap_sta_no_session_timeout(hapd, sta);
+ /*
+ * If the driver supports full AP client state, add a station to the
+ * driver before sending authentication reply to make sure the driver
+ * has resources, and not to go through the entire authentication and
+ * association handshake, and fail it at the end.
+ *
+ * If this is not the first transaction, in a multi-step authentication
+ * algorithm, the station already exists in the driver
+ * (sta->added_unassoc = 1) so skip it.
+ *
+ * In mesh mode, the station was already added to the driver when the
+ * NEW_PEER_CANDIDATE event is received.
+ */
+ if (FULL_AP_CLIENT_STATE_SUPP(hapd->iface->drv_flags) &&
+ !(hapd->conf->mesh & MESH_ENABLED) &&
+ !(sta->added_unassoc)) {
+ /*
+ * If a station that is already associated to the AP, is trying
+ * to authenticate again, remove the STA entry, in order to make
+ * sure the STA PS state gets cleared and configuration gets
+ * updated. To handle this, station's added_unassoc flag is
+ * cleared once the station has completed association.
+ */
+ hostapd_drv_sta_remove(hapd, sta->addr);
+ sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_AUTH |
+ WLAN_STA_AUTHORIZED);
+
+ if (hostapd_sta_add(hapd, sta->addr, 0, 0, NULL, 0, 0,
+ NULL, NULL, sta->flags, 0, 0, 0, 0)) {
+ hostapd_logger(hapd, sta->addr,
+ HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_NOTICE,
+ "Could not add STA to kernel driver");
+ resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
+ goto fail;
+ }
+
+ sta->added_unassoc = 1;
+ }
+
switch (auth_alg) {
case WLAN_AUTH_OPEN:
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
os_free(radius_cui);
hostapd_free_psk_list(psk);
- send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg,
- auth_transaction + 1, resp, resp_ies, resp_ies_len);
+ reply_res = send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg,
+ auth_transaction + 1, resp, resp_ies,
+ resp_ies_len);
+
+ if (sta && sta->added_unassoc && (resp != WLAN_STATUS_SUCCESS ||
+ reply_res != WLAN_STATUS_SUCCESS)) {
+ hostapd_drv_sta_remove(hapd, sta->addr);
+ sta->added_unassoc = 0;
+ }
}
-static int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
+int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
{
int i, j = 32, aid;
return 0;
}
+ if (TEST_FAIL())
+ return -1;
+
for (i = 0; i < AID_WORDS; i++) {
if (hapd->sta_aid[i] == (u32) -1)
continue;
}
#endif /* CONFIG_INTERWORKING */
+ if (ext_capab_ie_len > 0)
+ sta->ecsa_supported = !!(ext_capab_ie[0] & BIT(2));
+
return WLAN_STATUS_SUCCESS;
}
sta->mb_ies = NULL;
#endif /* CONFIG_FST */
+#ifdef CONFIG_MBO
+ mbo_ap_check_sta_assoc(hapd, sta, &elems);
+
+ if (hapd->conf->mbo_enabled && (hapd->conf->wpa & 2) &&
+ elems.mbo && sta->cell_capa && !(sta->flags & WLAN_STA_MFP) &&
+ hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
+ wpa_printf(MSG_INFO,
+ "MBO: Reject WPA2 association without PMF");
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
+ }
+#endif /* CONFIG_MBO */
+
+ ap_copy_sta_supp_op_classes(sta, elems.supp_op_classes,
+ elems.supp_op_classes_len);
+
+ if ((sta->capability & WLAN_CAPABILITY_RADIO_MEASUREMENT) &&
+ elems.rrm_enabled &&
+ elems.rrm_enabled_len >= sizeof(sta->rrm_enabled_capa))
+ os_memcpy(sta->rrm_enabled_capa, elems.rrm_enabled,
+ sizeof(sta->rrm_enabled_capa));
+
return WLAN_STATUS_SUCCESS;
}
}
-static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
- u16 status_code, int reassoc, const u8 *ies,
- size_t ies_len)
+static int add_associated_sta(struct hostapd_data *hapd,
+ struct sta_info *sta)
+{
+ struct ieee80211_ht_capabilities ht_cap;
+ struct ieee80211_vht_capabilities vht_cap;
+
+ /*
+ * Remove the STA entry to ensure the STA PS state gets cleared and
+ * configuration gets updated. This is relevant for cases, such as
+ * FT-over-the-DS, where a station re-associates back to the same AP but
+ * skips the authentication flow, or if working with a driver that
+ * does not support full AP client state.
+ */
+ if (!sta->added_unassoc)
+ hostapd_drv_sta_remove(hapd, sta->addr);
+
+#ifdef CONFIG_IEEE80211N
+ if (sta->flags & WLAN_STA_HT)
+ hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap);
+#endif /* CONFIG_IEEE80211N */
+#ifdef CONFIG_IEEE80211AC
+ if (sta->flags & WLAN_STA_VHT)
+ hostapd_get_vht_capab(hapd, sta->vht_capabilities, &vht_cap);
+#endif /* CONFIG_IEEE80211AC */
+
+ /*
+ * Add the station with forced WLAN_STA_ASSOC flag. The sta->flags
+ * will be set when the ACK frame for the (Re)Association Response frame
+ * is processed (TX status driver event).
+ */
+ if (hostapd_sta_add(hapd, sta->addr, sta->aid, sta->capability,
+ sta->supported_rates, sta->supported_rates_len,
+ sta->listen_interval,
+ sta->flags & WLAN_STA_HT ? &ht_cap : NULL,
+ sta->flags & WLAN_STA_VHT ? &vht_cap : NULL,
+ sta->flags | WLAN_STA_ASSOC, sta->qosinfo,
+ sta->vht_opmode, sta->p2p_ie ? 1 : 0,
+ sta->added_unassoc)) {
+ hostapd_logger(hapd, sta->addr,
+ HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_NOTICE,
+ "Could not %s STA to kernel driver",
+ sta->added_unassoc ? "set" : "add");
+
+ if (sta->added_unassoc) {
+ hostapd_drv_sta_remove(hapd, sta->addr);
+ sta->added_unassoc = 0;
+ }
+
+ return -1;
+ }
+
+ sta->added_unassoc = 0;
+
+ return 0;
+}
+
+
+static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
+ u16 status_code, int reassoc, const u8 *ies,
+ size_t ies_len)
{
int send_len;
u8 buf[sizeof(struct ieee80211_mgmt) + 1024];
#ifdef CONFIG_IEEE80211AC
if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
- p = hostapd_eid_vht_capabilities(hapd, p);
+ u32 nsts = 0, sta_nsts;
+
+ if (hapd->conf->use_sta_nsts && sta->vht_capabilities) {
+ struct ieee80211_vht_capabilities *capa;
+
+ nsts = (hapd->iface->conf->vht_capab >>
+ VHT_CAP_BEAMFORMEE_STS_OFFSET) & 7;
+ capa = sta->vht_capabilities;
+ sta_nsts = (le_to_host32(capa->vht_capabilities_info) >>
+ VHT_CAP_BEAMFORMEE_STS_OFFSET) & 7;
+
+ if (nsts < sta_nsts)
+ nsts = 0;
+ else
+ nsts = sta_nsts;
+ }
+ p = hostapd_eid_vht_capabilities(hapd, p, nsts);
p = hostapd_eid_vht_operation(hapd, p);
}
#endif /* CONFIG_IEEE80211AC */
#endif /* CONFIG_WPS */
#ifdef CONFIG_P2P
- if (sta->p2p_ie) {
+ if (sta->p2p_ie && hapd->p2p_group) {
struct wpabuf *p2p_resp_ie;
enum p2p_status_code status;
switch (status_code) {
p = hostapd_eid_p2p_manage(hapd, p);
#endif /* CONFIG_P2P_MANAGER */
+ p = hostapd_eid_mbo(hapd, p, buf + sizeof(buf) - p);
+
+ if (hapd->conf->assocresp_elements &&
+ (size_t) (buf + sizeof(buf) - p) >=
+ wpabuf_len(hapd->conf->assocresp_elements)) {
+ os_memcpy(p, wpabuf_head(hapd->conf->assocresp_elements),
+ wpabuf_len(hapd->conf->assocresp_elements));
+ p += wpabuf_len(hapd->conf->assocresp_elements);
+ }
+
send_len += p - reply->u.assoc_resp.variable;
- if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0)
+ if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0) {
wpa_printf(MSG_INFO, "Failed to send assoc resp: %s",
strerror(errno));
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
+ }
+
+ return WLAN_STATUS_SUCCESS;
}
int reassoc)
{
u16 capab_info, listen_interval, seq_ctrl, fc;
- u16 resp = WLAN_STATUS_SUCCESS;
+ u16 resp = WLAN_STATUS_SUCCESS, reply_res;
const u8 *pos;
int left, i;
struct sta_info *sta;
wpa_printf(MSG_DEBUG, "FT: Allow STA " MACSTR " to associate "
"prior to authentication since it is using "
"over-the-DS FT", MAC2STR(mgmt->sa));
+
+ /*
+ * Mark station as authenticated, to avoid adding station
+ * entry in the driver as associated and not authenticated
+ */
+ sta->flags |= WLAN_STA_AUTH;
} else
#endif /* CONFIG_IEEE80211R */
if (sta == NULL || (sta->flags & WLAN_STA_AUTH) == 0) {
goto fail;
}
+#ifdef CONFIG_MBO
+ if (hapd->conf->mbo_enabled && hapd->mbo_assoc_disallow) {
+ resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
+ goto fail;
+ }
+#endif /* CONFIG_MBO */
+
+ /*
+ * sta->capability is used in check_assoc_ies() for RRM enabled
+ * capability element.
+ */
+ sta->capability = capab_info;
+
/* followed by SSID and Supported rates; and HT capabilities if 802.11n
* is used */
resp = check_assoc_ies(hapd, sta, pos, left, reassoc);
goto fail;
}
- sta->capability = capab_info;
sta->listen_interval = listen_interval;
if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
* remove the STA immediately. */
sta->timeout_next = STA_NULLFUNC;
+#ifdef CONFIG_TAXONOMY
+ taxonomy_sta_info_assoc_req(hapd, sta, pos, left);
+#endif /* CONFIG_TAXONOMY */
+
fail:
- send_assoc_resp(hapd, sta, resp, reassoc, pos, left);
+ /*
+ * In case of a successful response, add the station to the driver.
+ * Otherwise, the kernel may ignore Data frames before we process the
+ * ACK frame (TX status). In case of a failure, this station will be
+ * removed.
+ *
+ * Note that this is not compliant with the IEEE 802.11 standard that
+ * states that a non-AP station should transition into the
+ * authenticated/associated state only after the station acknowledges
+ * the (Re)Association Response frame. However, still do this as:
+ *
+ * 1. In case the station does not acknowledge the (Re)Association
+ * Response frame, it will be removed.
+ * 2. Data frames will be dropped in the kernel until the station is
+ * set into authorized state, and there are no significant known
+ * issues with processing other non-Data Class 3 frames during this
+ * window.
+ */
+ if (resp == WLAN_STATUS_SUCCESS && add_associated_sta(hapd, sta))
+ resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
+
+ reply_res = send_assoc_resp(hapd, sta, resp, reassoc, pos, left);
+
+ /*
+ * Remove the station in case tranmission of a success response fails
+ * (the STA was added associated to the driver) or if the station was
+ * previously added unassociated.
+ */
+ if ((reply_res != WLAN_STATUS_SUCCESS &&
+ resp == WLAN_STATUS_SUCCESS) || sta->added_unassoc) {
+ hostapd_drv_sta_remove(hapd, sta->addr);
+ sta->added_unassoc = 0;
+ }
}
/* Stop Accounting and IEEE 802.1X sessions, but leave the STA
* authenticated. */
accounting_sta_stop(hapd, sta);
- ieee802_1x_free_station(sta);
+ ieee802_1x_free_station(hapd, sta);
if (sta->ipaddr)
hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr);
ap_sta_ip6addr_del(hapd, sta);
hostapd_drv_sta_remove(hapd, sta->addr);
+ sta->added_unassoc = 0;
if (sta->timeout_next == STA_NULLFUNC ||
sta->timeout_next == STA_DISASSOC) {
return 1;
}
break;
+ case WLAN_ACTION_RADIO_MEASUREMENT:
+ hostapd_handle_radio_measurement(hapd, (const u8 *) mgmt, len);
+ return 1;
}
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
"handle_action - unknown action category %d or invalid "
"frame",
mgmt->u.action.category);
- if (!(mgmt->da[0] & 0x01) && !(mgmt->u.action.category & 0x80) &&
- !(mgmt->sa[0] & 0x01)) {
+ if (!is_multicast_ether_addr(mgmt->da) &&
+ !(mgmt->u.action.category & 0x80) &&
+ !is_multicast_ether_addr(mgmt->sa)) {
struct ieee80211_mgmt *resp;
/*
struct hostapd_frame_info *fi)
{
struct ieee80211_mgmt *mgmt;
- int broadcast;
u16 fc, stype;
int ret = 0;
return 1;
}
- broadcast = mgmt->bssid[0] == 0xff && mgmt->bssid[1] == 0xff &&
- mgmt->bssid[2] == 0xff && mgmt->bssid[3] == 0xff &&
- mgmt->bssid[4] == 0xff && mgmt->bssid[5] == 0xff;
-
- if (!broadcast &&
+ if (!is_broadcast_ether_addr(mgmt->bssid) &&
#ifdef CONFIG_P2P
/* Invitation responses can be sent with the peer MAC as BSSID */
!((hapd->conf->p2p & P2P_GROUP_OWNER) &&
u16 auth_alg, auth_transaction, status_code;
struct sta_info *sta;
+ sta = ap_get_sta(hapd, mgmt->da);
+ if (!sta) {
+ wpa_printf(MSG_INFO, "handle_auth_cb: STA " MACSTR " not found",
+ MAC2STR(mgmt->da));
+ return;
+ }
+
+ auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
+ auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
+ status_code = le_to_host16(mgmt->u.auth.status_code);
+
if (!ok) {
hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_NOTICE,
"did not acknowledge authentication response");
- return;
+ goto fail;
}
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
wpa_printf(MSG_INFO, "handle_auth_cb - too short payload (len=%lu)",
(unsigned long) len);
- return;
- }
-
- auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
- auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
- status_code = le_to_host16(mgmt->u.auth.status_code);
-
- sta = ap_get_sta(hapd, mgmt->da);
- if (!sta) {
- wpa_printf(MSG_INFO, "handle_auth_cb: STA " MACSTR " not found",
- MAC2STR(mgmt->da));
- return;
+ goto fail;
}
if (status_code == WLAN_STATUS_SUCCESS &&
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "authenticated");
sta->flags |= WLAN_STA_AUTH;
+ if (sta->added_unassoc)
+ hostapd_set_sta_flags(hapd, sta);
+ return;
+ }
+
+fail:
+ if (status_code != WLAN_STATUS_SUCCESS && sta->added_unassoc) {
+ hostapd_drv_sta_remove(hapd, sta->addr);
+ sta->added_unassoc = 0;
}
}
u16 status;
struct sta_info *sta;
int new_assoc = 1;
- struct ieee80211_ht_capabilities ht_cap;
- struct ieee80211_vht_capabilities vht_cap;
-
- if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_resp) :
- sizeof(mgmt->u.assoc_resp))) {
- wpa_printf(MSG_INFO, "handle_assoc_cb(reassoc=%d) - too short payload (len=%lu)",
- reassoc, (unsigned long) len);
- return;
- }
sta = ap_get_sta(hapd, mgmt->da);
if (!sta) {
return;
}
- if (!ok) {
- hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
- HOSTAPD_LEVEL_DEBUG,
- "did not acknowledge association response");
- sta->flags &= ~WLAN_STA_ASSOC_REQ_OK;
+ if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_resp) :
+ sizeof(mgmt->u.assoc_resp))) {
+ wpa_printf(MSG_INFO,
+ "handle_assoc_cb(reassoc=%d) - too short payload (len=%lu)",
+ reassoc, (unsigned long) len);
+ hostapd_drv_sta_remove(hapd, sta->addr);
return;
}
else
status = le_to_host16(mgmt->u.assoc_resp.status_code);
+ if (!ok) {
+ hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_DEBUG,
+ "did not acknowledge association response");
+ sta->flags &= ~WLAN_STA_ASSOC_REQ_OK;
+ /* The STA is added only in case of SUCCESS */
+ if (status == WLAN_STATUS_SUCCESS)
+ hostapd_drv_sta_remove(hapd, sta->addr);
+
+ return;
+ }
+
if (status != WLAN_STATUS_SUCCESS)
return;
sta->sa_query_timed_out = 0;
#endif /* CONFIG_IEEE80211W */
- /*
- * Remove the STA entry in order to make sure the STA PS state gets
- * cleared and configuration gets updated in case of reassociation back
- * to the same AP.
- */
- hostapd_drv_sta_remove(hapd, sta->addr);
-
-#ifdef CONFIG_IEEE80211N
- if (sta->flags & WLAN_STA_HT)
- hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap);
-#endif /* CONFIG_IEEE80211N */
-#ifdef CONFIG_IEEE80211AC
- if (sta->flags & WLAN_STA_VHT)
- hostapd_get_vht_capab(hapd, sta->vht_capabilities, &vht_cap);
-#endif /* CONFIG_IEEE80211AC */
-
- if (hostapd_sta_add(hapd, sta->addr, sta->aid, sta->capability,
- sta->supported_rates, sta->supported_rates_len,
- sta->listen_interval,
- sta->flags & WLAN_STA_HT ? &ht_cap : NULL,
- sta->flags & WLAN_STA_VHT ? &vht_cap : NULL,
- sta->flags, sta->qosinfo, sta->vht_opmode)) {
- hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
- HOSTAPD_LEVEL_NOTICE,
- "Could not add STA to kernel driver");
-
- ap_sta_disconnect(hapd, sta, sta->addr,
- WLAN_REASON_DISASSOC_AP_BUSY);
-
- return;
- }
-
if (sta->flags & WLAN_STA_WDS) {
int ret;
char ifname_wds[IFNAMSIZ + 1];
else
wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
hapd->new_assoc_sta_cb(hapd, sta, !new_assoc);
-
ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
+
+ if (sta->pending_eapol_rx) {
+ struct os_reltime now, age;
+
+ os_get_reltime(&now);
+ os_reltime_sub(&now, &sta->pending_eapol_rx->rx_time, &age);
+ if (age.sec == 0 && age.usec < 200000) {
+ wpa_printf(MSG_DEBUG,
+ "Process pending EAPOL frame that was received from " MACSTR " just before association notification",
+ MAC2STR(sta->addr));
+ ieee802_1x_receive(
+ hapd, mgmt->da,
+ wpabuf_head(sta->pending_eapol_rx->buf),
+ wpabuf_len(sta->pending_eapol_rx->buf));
+ }
+ wpabuf_free(sta->pending_eapol_rx->buf);
+ os_free(sta->pending_eapol_rx);
+ sta->pending_eapol_rx = NULL;
+ }
}
size_t len, int ok)
{
struct sta_info *sta;
- if (mgmt->da[0] & 0x01)
+ if (is_multicast_ether_addr(mgmt->da))
return;
sta = ap_get_sta(hapd, mgmt->da);
if (!sta) {
size_t len, int ok)
{
struct sta_info *sta;
- if (mgmt->da[0] & 0x01)
+ if (is_multicast_ether_addr(mgmt->da))
return;
sta = ap_get_sta(hapd, mgmt->da);
if (!sta) {
handle_assoc_cb(hapd, mgmt, len, 1, ok);
break;
case WLAN_FC_STYPE_PROBE_RESP:
- wpa_printf(MSG_EXCESSIVE, "mgmt::proberesp cb");
+ wpa_printf(MSG_EXCESSIVE, "mgmt::proberesp cb ok=%d", ok);
break;
case WLAN_FC_STYPE_DEAUTH:
wpa_printf(MSG_DEBUG, "mgmt::deauth cb");
handle_disassoc_cb(hapd, mgmt, len, ok);
break;
case WLAN_FC_STYPE_ACTION:
- wpa_printf(MSG_DEBUG, "mgmt::action cb");
+ wpa_printf(MSG_DEBUG, "mgmt::action cb ok=%d", ok);
break;
default:
wpa_printf(MSG_INFO, "unknown mgmt cb frame subtype %d", stype);
}
if (sta == NULL)
return;
+ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POLL_OK MACSTR,
+ MAC2STR(sta->addr));
if (!(sta->flags & WLAN_STA_PENDING_POLL))
return;
wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated STA "
MACSTR, MAC2STR(src));
- if (src[0] & 0x01) {
+ if (is_multicast_ether_addr(src)) {
/* Broadcast bit set in SA?! Ignore the frame silently. */
return;
}
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);
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,
#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)
}
#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 */
#include "utils/common.h"
#include "utils/eloop.h"
-#include "crypto/sha1.h"
#include "radius/radius.h"
#include "radius/radius_client.h"
#include "hostapd.h"
struct hostapd_cached_radius_acl *next;
u32 session_timeout;
u32 acct_interim_interval;
- int vlan_id;
+ struct vlan_description vlan_id;
struct hostapd_sta_wpa_psk_short *psk;
char *identity;
char *radius_cui;
static void copy_psk_list(struct hostapd_sta_wpa_psk_short **psk,
struct hostapd_sta_wpa_psk_short *src)
{
- struct hostapd_sta_wpa_psk_short **copy_to;
- struct hostapd_sta_wpa_psk_short *copy_from;
-
- /* Copy PSK linked list */
- copy_to = psk;
- copy_from = src;
- while (copy_from && copy_to) {
- *copy_to = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short));
- if (*copy_to == NULL)
- break;
- os_memcpy(*copy_to, copy_from,
- sizeof(struct hostapd_sta_wpa_psk_short));
- copy_from = copy_from->next;
- copy_to = &((*copy_to)->next);
- }
- if (copy_to)
- *copy_to = NULL;
+ if (!psk)
+ return;
+
+ if (src)
+ src->ref++;
+
+ *psk = src;
}
static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr,
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)
{
if (msg == NULL)
return -1;
- radius_msg_make_authenticator(msg, addr, ETH_ALEN);
+ if (radius_msg_make_authenticator(msg) < 0) {
+ wpa_printf(MSG_INFO, "Could not make Request Authenticator");
+ goto fail;
+ }
os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, MAC2STR(addr));
if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, (u8 *) buf,
/**
+ * hostapd_check_acl - Check a specified STA against accept/deny ACLs
+ * @hapd: hostapd BSS data
+ * @addr: MAC address of the STA
+ * @vlan_id: Buffer for returning VLAN ID
+ * Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING
+ */
+int hostapd_check_acl(struct hostapd_data *hapd, const u8 *addr,
+ struct vlan_description *vlan_id)
+{
+ if (hostapd_maclist_found(hapd->conf->accept_mac,
+ hapd->conf->num_accept_mac, addr, vlan_id))
+ return HOSTAPD_ACL_ACCEPT;
+
+ if (hostapd_maclist_found(hapd->conf->deny_mac,
+ hapd->conf->num_deny_mac, addr, vlan_id))
+ return HOSTAPD_ACL_REJECT;
+
+ if (hapd->conf->macaddr_acl == ACCEPT_UNLESS_DENIED)
+ return HOSTAPD_ACL_ACCEPT;
+ if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED)
+ return HOSTAPD_ACL_REJECT;
+
+ return HOSTAPD_ACL_PENDING;
+}
+
+
+/**
* hostapd_allowed_address - Check whether a specified STA can be authenticated
* @hapd: hostapd BSS data
* @addr: MAC address of the STA
*/
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 res;
+
if (session_timeout)
*session_timeout = 0;
if (acct_interim_interval)
*acct_interim_interval = 0;
if (vlan_id)
- *vlan_id = 0;
+ os_memset(vlan_id, 0, sizeof(*vlan_id));
if (psk)
*psk = NULL;
if (identity)
if (radius_cui)
*radius_cui = NULL;
- if (hostapd_maclist_found(hapd->conf->accept_mac,
- hapd->conf->num_accept_mac, addr, vlan_id))
- return HOSTAPD_ACL_ACCEPT;
-
- if (hostapd_maclist_found(hapd->conf->deny_mac,
- hapd->conf->num_deny_mac, addr, vlan_id))
- return HOSTAPD_ACL_REJECT;
-
- if (hapd->conf->macaddr_acl == ACCEPT_UNLESS_DENIED)
- return HOSTAPD_ACL_ACCEPT;
- if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED)
- return HOSTAPD_ACL_REJECT;
+ res = hostapd_check_acl(hapd, addr, vlan_id);
+ if (res != HOSTAPD_ACL_PENDING)
+ return res;
if (hapd->conf->macaddr_acl == USE_EXTERNAL_RADIUS_AUTH) {
#ifdef CONFIG_NO_RADIUS
struct hostapd_acl_query_data *query;
/* Check whether ACL cache has an entry for this station */
- int res = hostapd_acl_cache_get(hapd, addr, session_timeout,
- acct_interim_interval,
- vlan_id, psk,
- identity, radius_cui);
+ res = hostapd_acl_cache_get(hapd, addr, session_timeout,
+ acct_interim_interval, vlan_id, psk,
+ identity, radius_cui);
if (res == HOSTAPD_ACL_ACCEPT ||
res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
return res;
struct hostapd_cached_radius_acl *cache)
{
int passphraselen;
- char *passphrase, *strpassphrase;
+ char *passphrase;
size_t i;
struct hostapd_sta_wpa_psk_short *psk;
*/
if (passphrase == NULL)
break;
+
+ /*
+ * Passphase should be 8..63 chars (to be hashed with SSID)
+ * or 64 chars hex string (no separate hashing with SSID).
+ */
+
+ if (passphraselen < MIN_PASSPHRASE_LEN ||
+ passphraselen > MAX_PASSPHRASE_LEN + 1)
+ goto free_pass;
+
/*
* passphrase does not contain the NULL termination.
* Add it here as pbkdf2_sha1() requires it.
*/
- strpassphrase = os_zalloc(passphraselen + 1);
psk = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short));
- if (strpassphrase && psk) {
- os_memcpy(strpassphrase, passphrase, passphraselen);
- pbkdf2_sha1(strpassphrase,
- hapd->conf->ssid.ssid,
- hapd->conf->ssid.ssid_len, 4096,
- psk->psk, PMK_LEN);
+ if (psk) {
+ if ((passphraselen == MAX_PASSPHRASE_LEN + 1) &&
+ (hexstr2bin(passphrase, psk->psk, PMK_LEN) < 0)) {
+ hostapd_logger(hapd, cache->addr,
+ HOSTAPD_MODULE_RADIUS,
+ HOSTAPD_LEVEL_WARNING,
+ "invalid hex string (%d chars) in Tunnel-Password",
+ passphraselen);
+ goto skip;
+ } else if (passphraselen <= MAX_PASSPHRASE_LEN) {
+ os_memcpy(psk->passphrase, passphrase,
+ passphraselen);
+ psk->is_passphrase = 1;
+ }
psk->next = cache->psk;
cache->psk = psk;
psk = NULL;
}
- os_free(strpassphrase);
+skip:
os_free(psk);
+free_pass:
os_free(passphrase);
}
}
struct hostapd_acl_query_data *query, *prev;
struct hostapd_cached_radius_acl *cache;
struct radius_hdr *hdr = radius_msg_get_hdr(msg);
+ int *untagged, *tagged, *notempty;
query = hapd->acl_queries;
prev = NULL;
cache->acct_interim_interval = 0;
}
- cache->vlan_id = radius_msg_get_vlanid(msg);
+ notempty = &cache->vlan_id.notempty;
+ untagged = &cache->vlan_id.untagged;
+ tagged = cache->vlan_id.tagged;
+ *notempty = !!radius_msg_get_vlanid(msg, untagged,
+ MAX_NUM_TAGGED_VLAN,
+ tagged);
decode_tunnel_passwords(hapd, shared_secret, shared_secret_len,
msg, req, cache);
!cache->psk)
cache->accepted = HOSTAPD_ACL_REJECT;
- if (cache->vlan_id &&
- !hostapd_vlan_id_valid(hapd->conf->vlan, cache->vlan_id)) {
+ if (cache->vlan_id.notempty &&
+ !hostapd_vlan_valid(hapd->conf->vlan, &cache->vlan_id)) {
hostapd_logger(hapd, query->addr,
HOSTAPD_MODULE_RADIUS,
HOSTAPD_LEVEL_INFO,
- "Invalid VLAN ID %d received from RADIUS server",
- cache->vlan_id);
- cache->vlan_id = 0;
+ "Invalid VLAN %d%s received from RADIUS server",
+ cache->vlan_id.untagged,
+ cache->vlan_id.tagged[0] ? "+" : "");
+ os_memset(&cache->vlan_id, 0, sizeof(cache->vlan_id));
}
if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_REQUIRED &&
- !cache->vlan_id)
+ !cache->vlan_id.notempty)
cache->accepted = HOSTAPD_ACL_REJECT;
} else
cache->accepted = HOSTAPD_ACL_REJECT;
void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk)
{
+ if (psk && psk->ref) {
+ /* This will be freed when the last reference is dropped. */
+ psk->ref--;
+ return;
+ }
+
while (psk) {
struct hostapd_sta_wpa_psk_short *prev = psk;
psk = psk->next;
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);
}
+u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid)
+{
+ u8 sec_ch;
+
+ if (!hapd->cs_freq_params.channel ||
+ !hapd->cs_freq_params.sec_channel_offset)
+ return eid;
+
+ if (hapd->cs_freq_params.sec_channel_offset == -1)
+ sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;
+ else if (hapd->cs_freq_params.sec_channel_offset == 1)
+ sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;
+ else
+ return eid;
+
+ *eid++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET;
+ *eid++ = 1;
+ *eid++ = sec_ch;
+
+ return eid;
+}
+
+
/*
op_mode
Set to 0 (HT pure) under the followign conditions
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)
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;
}
}
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;
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)
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);
+}
#include "sta_info.h"
#include "beacon.h"
#include "ieee802_11.h"
+#include "dfs.h"
-u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid)
+u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts)
{
struct ieee80211_vht_capabilities *cap;
struct hostapd_hw_modes *mode = hapd->iface->current_mode;
cap->vht_capabilities_info = host_to_le32(
hapd->iface->conf->vht_capab);
+ if (nsts != 0) {
+ u32 hapd_nsts;
+
+ hapd_nsts = le_to_host32(cap->vht_capabilities_info);
+ hapd_nsts = (hapd_nsts >> VHT_CAP_BEAMFORMEE_STS_OFFSET) & 7;
+ cap->vht_capabilities_info &=
+ ~(host_to_le32(hapd_nsts <<
+ VHT_CAP_BEAMFORMEE_STS_OFFSET));
+ cap->vht_capabilities_info |=
+ host_to_le32(nsts << VHT_CAP_BEAMFORMEE_STS_OFFSET);
+ }
+
/* Supported MCS set comes from hw */
os_memcpy(&cap->vht_supported_mcs_set, mode->vht_mcs_set, 8);
hapd->iconf->vht_oper_centr_freq_seg1_idx;
oper->vht_op_info_chwidth = hapd->iconf->vht_oper_chwidth;
+ if (hapd->iconf->vht_oper_chwidth == 2) {
+ /*
+ * Convert 160 MHz channel width to new style as interop
+ * workaround.
+ */
+ oper->vht_op_info_chwidth = 1;
+ oper->vht_op_info_chan_center_freq_seg1_idx =
+ oper->vht_op_info_chan_center_freq_seg0_idx;
+ if (hapd->iconf->channel <
+ hapd->iconf->vht_oper_centr_freq_seg0_idx)
+ oper->vht_op_info_chan_center_freq_seg0_idx -= 8;
+ else
+ oper->vht_op_info_chan_center_freq_seg0_idx += 8;
+ } else if (hapd->iconf->vht_oper_chwidth == 3) {
+ /*
+ * Convert 80+80 MHz channel width to new style as interop
+ * workaround.
+ */
+ oper->vht_op_info_chwidth = 1;
+ }
/* VHT Basic MCS set comes from hw */
/* Hard code 1 stream, MCS0-7 is a min Basic VHT MCS rates */
}
+u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid)
+{
+ u8 bw, chan1, chan2 = 0;
+ int freq1;
+
+ if (!hapd->cs_freq_params.channel ||
+ !hapd->cs_freq_params.vht_enabled)
+ return eid;
+
+ /* bandwidth: 0: 40, 1: 80, 2: 160, 3: 80+80 */
+ switch (hapd->cs_freq_params.bandwidth) {
+ case 40:
+ bw = 0;
+ break;
+ case 80:
+ /* check if it's 80+80 */
+ if (!hapd->cs_freq_params.center_freq2)
+ bw = 1;
+ else
+ bw = 3;
+ break;
+ case 160:
+ bw = 2;
+ break;
+ default:
+ /* not valid VHT bandwidth or not in CSA */
+ return eid;
+ }
+
+ freq1 = hapd->cs_freq_params.center_freq1 ?
+ hapd->cs_freq_params.center_freq1 :
+ hapd->cs_freq_params.freq;
+ if (ieee80211_freq_to_chan(freq1, &chan1) !=
+ HOSTAPD_MODE_IEEE80211A)
+ return eid;
+
+ if (hapd->cs_freq_params.center_freq2 &&
+ ieee80211_freq_to_chan(hapd->cs_freq_params.center_freq2,
+ &chan2) != HOSTAPD_MODE_IEEE80211A)
+ return eid;
+
+ *eid++ = WLAN_EID_VHT_CHANNEL_SWITCH_WRAPPER;
+ *eid++ = 5; /* Length of Channel Switch Wrapper */
+ *eid++ = WLAN_EID_VHT_WIDE_BW_CHSWITCH;
+ *eid++ = 3; /* Length of Wide Bandwidth Channel Switch element */
+ *eid++ = bw; /* New Channel Width */
+ *eid++ = chan1; /* New Channel Center Frequency Segment 0 */
+ *eid++ = chan2; /* New Channel Center Frequency Segment 1 */
+
+ return eid;
+}
+
+
+u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid)
+{
+ struct hostapd_iface *iface = hapd->iface;
+ struct hostapd_config *iconf = iface->conf;
+ struct hostapd_hw_modes *mode = iface->current_mode;
+ struct hostapd_channel_data *chan;
+ int dfs, i;
+ u8 channel, tx_pwr_count, local_pwr_constraint;
+ int max_tx_power;
+ u8 tx_pwr;
+
+ if (!mode)
+ return eid;
+
+ if (ieee80211_freq_to_chan(iface->freq, &channel) == NUM_HOSTAPD_MODES)
+ return eid;
+
+ for (i = 0; i < mode->num_channels; i++) {
+ if (mode->channels[i].freq == iface->freq)
+ break;
+ }
+ if (i == mode->num_channels)
+ return eid;
+
+ switch (iface->conf->vht_oper_chwidth) {
+ case VHT_CHANWIDTH_USE_HT:
+ if (iconf->secondary_channel == 0) {
+ /* Max Transmit Power count = 0 (20 MHz) */
+ tx_pwr_count = 0;
+ } else {
+ /* Max Transmit Power count = 1 (20, 40 MHz) */
+ tx_pwr_count = 1;
+ }
+ break;
+ case VHT_CHANWIDTH_80MHZ:
+ /* Max Transmit Power count = 2 (20, 40, and 80 MHz) */
+ tx_pwr_count = 2;
+ break;
+ case VHT_CHANWIDTH_80P80MHZ:
+ case VHT_CHANWIDTH_160MHZ:
+ /* Max Transmit Power count = 3 (20, 40, 80, 160/80+80 MHz) */
+ tx_pwr_count = 3;
+ break;
+ default:
+ return eid;
+ }
+
+ /*
+ * Below local_pwr_constraint logic is referred from
+ * hostapd_eid_pwr_constraint.
+ *
+ * Check if DFS is required by regulatory.
+ */
+ dfs = hostapd_is_dfs_required(hapd->iface);
+ if (dfs < 0)
+ dfs = 0;
+
+ /*
+ * In order to meet regulations when TPC is not implemented using
+ * a transmit power that is below the legal maximum (including any
+ * mitigation factor) should help. In this case, indicate 3 dB below
+ * maximum allowed transmit power.
+ */
+ if (hapd->iconf->local_pwr_constraint == -1)
+ local_pwr_constraint = (dfs == 0) ? 0 : 3;
+ else
+ local_pwr_constraint = hapd->iconf->local_pwr_constraint;
+
+ /*
+ * A STA that is not an AP shall use a transmit power less than or
+ * equal to the local maximum transmit power level for the channel.
+ * The local maximum transmit power can be calculated from the formula:
+ * local max TX pwr = max TX pwr - local pwr constraint
+ * Where max TX pwr is maximum transmit power level specified for
+ * channel in Country element and local pwr constraint is specified
+ * for channel in this Power Constraint element.
+ */
+ chan = &mode->channels[i];
+ max_tx_power = chan->max_tx_power - local_pwr_constraint;
+
+ /*
+ * Local Maximum Transmit power is encoded as two's complement
+ * with a 0.5 dB step.
+ */
+ max_tx_power *= 2; /* in 0.5 dB steps */
+ if (max_tx_power > 127) {
+ /* 63.5 has special meaning of 63.5 dBm or higher */
+ max_tx_power = 127;
+ }
+ if (max_tx_power < -128)
+ max_tx_power = -128;
+ if (max_tx_power < 0)
+ tx_pwr = 0x80 + max_tx_power + 128;
+ else
+ tx_pwr = max_tx_power;
+
+ *eid++ = WLAN_EID_VHT_TRANSMIT_POWER_ENVELOPE;
+ *eid++ = 2 + tx_pwr_count;
+
+ /*
+ * Max Transmit Power count and
+ * Max Transmit Power units = 0 (EIRP)
+ */
+ *eid++ = tx_pwr_count;
+
+ for (i = 0; i <= tx_pwr_count; i++)
+ *eid++ = tx_pwr;
+
+ return eid;
+}
+
+
u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *vht_capab)
{
WPA_PUT_BE32(pos, (OUI_BROADCOM << 8) | VENDOR_VHT_TYPE);
pos += 4;
*pos++ = VENDOR_VHT_SUBTYPE;
- pos = hostapd_eid_vht_capabilities(hapd, pos);
+ pos = hostapd_eid_vht_capabilities(hapd, pos, 0);
pos = hostapd_eid_vht_operation(hapd, pos);
return pos;
#include "ieee802_1x.h"
+#ifdef CONFIG_HS20
+static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx);
+#endif /* CONFIG_HS20 */
static void ieee802_1x_finished(struct hostapd_data *hapd,
struct sta_info *sta, int success,
int remediation);
MAC2STR(sta->addr));
#ifndef CONFIG_NO_VLAN
- if (sta->vlan_id > 0 && sta->vlan_id <= MAX_VLAN_ID) {
+ if (sta->vlan_id > 0) {
wpa_printf(MSG_ERROR, "Using WEP with vlans is not supported.");
return;
}
char buf[128];
if (!hostapd_config_get_radius_attr(req_attr,
+ RADIUS_ATTR_SERVICE_TYPE) &&
+ !radius_msg_add_attr_int32(msg, RADIUS_ATTR_SERVICE_TYPE,
+ RADIUS_SERVICE_TYPE_FRAMED)) {
+ wpa_printf(MSG_ERROR, "Could not add Service-Type");
+ return -1;
+ }
+
+ if (!hostapd_config_get_radius_attr(req_attr,
RADIUS_ATTR_NAS_PORT) &&
+ sta->aid > 0 &&
!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT, sta->aid)) {
wpa_printf(MSG_ERROR, "Could not add NAS-Port");
return -1;
return -1;
}
- if (sta->acct_session_id_hi || sta->acct_session_id_lo) {
- os_snprintf(buf, sizeof(buf), "%08X-%08X",
- sta->acct_session_id_hi, sta->acct_session_id_lo);
+ if (sta->acct_session_id) {
+ os_snprintf(buf, sizeof(buf), "%016llX",
+ (unsigned long long) sta->acct_session_id);
if (!radius_msg_add_attr(msg, RADIUS_ATTR_ACCT_SESSION_ID,
(u8 *) buf, os_strlen(buf))) {
wpa_printf(MSG_ERROR, "Could not add Acct-Session-Id");
}
}
+ if ((hapd->conf->wpa & 2) &&
+ !hapd->conf->disable_pmksa_caching &&
+ sta->eapol_sm && sta->eapol_sm->acct_multi_session_id) {
+ os_snprintf(buf, sizeof(buf), "%016llX",
+ (unsigned long long)
+ sta->eapol_sm->acct_multi_session_id);
+ if (!radius_msg_add_attr(
+ msg, RADIUS_ATTR_ACCT_MULTI_SESSION_ID,
+ (u8 *) buf, os_strlen(buf))) {
+ wpa_printf(MSG_INFO,
+ "Could not add Acct-Multi-Session-Id");
+ return -1;
+ }
+ }
+
#ifdef CONFIG_IEEE80211R
if (hapd->conf->wpa && wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) &&
sta->wpa_sm &&
{
char buf[128];
struct hostapd_radius_attr *attr;
+ int len;
if (!hostapd_config_get_radius_attr(req_attr,
RADIUS_ATTR_NAS_IP_ADDRESS) &&
return -1;
}
- os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":%s",
- MAC2STR(hapd->own_addr),
- wpa_ssid_txt(hapd->conf->ssid.ssid,
- hapd->conf->ssid.ssid_len));
- buf[sizeof(buf) - 1] = '\0';
+ len = os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT ":",
+ MAC2STR(hapd->own_addr));
+ os_memcpy(&buf[len], hapd->conf->ssid.ssid,
+ hapd->conf->ssid.ssid_len);
+ len += hapd->conf->ssid.ssid_len;
if (!hostapd_config_get_radius_attr(req_attr,
RADIUS_ATTR_CALLED_STATION_ID) &&
!radius_msg_add_attr(msg, RADIUS_ATTR_CALLED_STATION_ID,
- (u8 *) buf, os_strlen(buf))) {
+ (u8 *) buf, len)) {
wpa_printf(MSG_ERROR, "Could not add Called-Station-Id");
return -1;
}
return;
}
- radius_msg_make_authenticator(msg, (u8 *) sta, sizeof(*sta));
+ if (radius_msg_make_authenticator(msg) < 0) {
+ wpa_printf(MSG_INFO, "Could not make Request Authenticator");
+ goto fail;
+ }
if (sm->identity &&
!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME,
}
+static void ieee802_1x_save_eapol(struct sta_info *sta, const u8 *buf,
+ size_t len)
+{
+ if (sta->pending_eapol_rx) {
+ wpabuf_free(sta->pending_eapol_rx->buf);
+ } else {
+ sta->pending_eapol_rx =
+ os_malloc(sizeof(*sta->pending_eapol_rx));
+ if (!sta->pending_eapol_rx)
+ return;
+ }
+
+ sta->pending_eapol_rx->buf = wpabuf_alloc_copy(buf, len);
+ if (!sta->pending_eapol_rx->buf) {
+ os_free(sta->pending_eapol_rx);
+ sta->pending_eapol_rx = NULL;
+ return;
+ }
+
+ os_get_reltime(&sta->pending_eapol_rx->rx_time);
+}
+
+
/**
* ieee802_1x_receive - Process the EAPOL frames from the Supplicant
* @hapd: hostapd BSS data
!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED))) {
wpa_printf(MSG_DEBUG, "IEEE 802.1X data frame from not "
"associated/Pre-authenticating STA");
+
+ if (sta && (sta->flags & WLAN_STA_AUTH)) {
+ wpa_printf(MSG_DEBUG, "Saving EAPOL frame from " MACSTR
+ " for later use", MAC2STR(sta->addr));
+ ieee802_1x_save_eapol(sta, buf, len);
+ }
+
return;
}
* Clear any possible EAPOL authenticator state to support
* reassociation change from WPS to PSK.
*/
- ieee802_1x_free_station(sta);
+ ieee802_1x_free_station(hapd, sta);
return;
}
* Clear any possible EAPOL authenticator state to support
* reassociation change from WPA-EAP to PSK.
*/
- ieee802_1x_free_station(sta);
+ ieee802_1x_free_station(hapd, sta);
return;
}
sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS;
sta->eapol_sm->authSuccess = TRUE;
sta->eapol_sm->authFail = FALSE;
+ sta->eapol_sm->portValid = TRUE;
if (sta->eapol_sm->eap)
eap_sm_notify_cached(sta->eapol_sm->eap);
/* TODO: get vlan_id from R0KH using RRB message */
sta->eapol_sm->authFail = FALSE;
if (sta->eapol_sm->eap)
eap_sm_notify_cached(sta->eapol_sm->eap);
- pmksa_cache_to_eapol_data(pmksa, sta->eapol_sm);
+ pmksa_cache_to_eapol_data(hapd, pmksa, sta->eapol_sm);
ap_sta_bind_vlan(hapd, sta);
} else {
if (reassoc) {
}
-void ieee802_1x_free_station(struct sta_info *sta)
+void ieee802_1x_free_station(struct hostapd_data *hapd, struct sta_info *sta)
{
struct eapol_state_machine *sm = sta->eapol_sm;
+#ifdef CONFIG_HS20
+ eloop_cancel_timeout(ieee802_1x_wnm_notif_send, hapd, sta);
+#endif /* CONFIG_HS20 */
+
+ if (sta->pending_eapol_rx) {
+ wpabuf_free(sta->pending_eapol_rx->buf);
+ os_free(sta->pending_eapol_rx);
+ sta->pending_eapol_rx = NULL;
+ }
+
if (sm == NULL)
return;
#ifndef CONFIG_NO_RADIUS
radius_msg_free(sm->last_recv_radius);
radius_free_class(&sm->radius_class);
- wpabuf_free(sm->radius_cui);
#endif /* CONFIG_NO_RADIUS */
- os_free(sm->identity);
eapol_auth_free(sm);
}
struct hostapd_data *hapd = data;
struct sta_info *sta;
u32 session_timeout = 0, termination_action, acct_interim_interval;
- int session_timeout_set, vlan_id = 0;
+ int session_timeout_set;
struct eapol_state_machine *sm;
int override_eapReq = 0;
struct radius_hdr *hdr = radius_msg_get_hdr(msg);
+ struct vlan_description vlan_desc;
+#ifndef CONFIG_NO_VLAN
+ int *untagged, *tagged, *notempty;
+#endif /* CONFIG_NO_VLAN */
+
+ os_memset(&vlan_desc, 0, sizeof(vlan_desc));
sm = ieee802_1x_search_radius_identifier(hapd, hdr->identifier);
if (sm == NULL) {
switch (hdr->code) {
case RADIUS_CODE_ACCESS_ACCEPT:
- if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_DISABLED)
- vlan_id = 0;
#ifndef CONFIG_NO_VLAN
- else
- vlan_id = radius_msg_get_vlanid(msg);
- if (vlan_id > 0 &&
- hostapd_vlan_id_valid(hapd->conf->vlan, vlan_id)) {
- hostapd_logger(hapd, sta->addr,
- HOSTAPD_MODULE_RADIUS,
- HOSTAPD_LEVEL_INFO,
- "VLAN ID %d", vlan_id);
- } else if (vlan_id > 0) {
+ if (hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED) {
+ notempty = &vlan_desc.notempty;
+ untagged = &vlan_desc.untagged;
+ tagged = vlan_desc.tagged;
+ *notempty = !!radius_msg_get_vlanid(msg, untagged,
+ MAX_NUM_TAGGED_VLAN,
+ tagged);
+ }
+
+ if (vlan_desc.notempty &&
+ !hostapd_vlan_valid(hapd->conf->vlan, &vlan_desc)) {
sta->eapol_sm->authFail = TRUE;
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_RADIUS,
HOSTAPD_LEVEL_INFO,
- "Invalid VLAN ID %d received from RADIUS server",
- vlan_id);
+ "Invalid VLAN %d%s received from RADIUS server",
+ vlan_desc.untagged,
+ vlan_desc.tagged[0] ? "+" : "");
+ os_memset(&vlan_desc, 0, sizeof(vlan_desc));
+ ap_sta_set_vlan(hapd, sta, &vlan_desc);
break;
- } else if (hapd->conf->ssid.dynamic_vlan ==
- DYNAMIC_VLAN_REQUIRED) {
+ }
+
+ if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_REQUIRED &&
+ !vlan_desc.notempty) {
sta->eapol_sm->authFail = TRUE;
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_IEEE8021X,
}
#endif /* CONFIG_NO_VLAN */
- sta->vlan_id = vlan_id;
+ if (ap_sta_set_vlan(hapd, sta, &vlan_desc) < 0)
+ break;
+
+#ifndef CONFIG_NO_VLAN
+ if (sta->vlan_id > 0) {
+ hostapd_logger(hapd, sta->addr,
+ HOSTAPD_MODULE_RADIUS,
+ HOSTAPD_LEVEL_INFO,
+ "VLAN ID %d", sta->vlan_id);
+ }
+#endif /* CONFIG_NO_VLAN */
+
if ((sta->flags & WLAN_STA_ASSOC) &&
ap_sta_bind_vlan(hapd, sta) < 0)
break;
ieee802_1x_check_hs20(hapd, sta, msg,
session_timeout_set ?
(int) session_timeout : -1);
- if (sm->eap_if->eapKeyAvailable && !sta->remediation &&
- !sta->hs20_deauth_requested &&
- wpa_auth_pmksa_add(sta->wpa_sm, sm->eapol_key_crypt,
- session_timeout_set ?
- (int) session_timeout : -1, sm) == 0) {
- hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
- HOSTAPD_LEVEL_DEBUG,
- "Added PMKSA cache entry");
- }
break;
case RADIUS_CODE_ACCESS_REJECT:
sm->eap_if->aaaFail = TRUE;
{
eloop_cancel_timeout(ieee802_1x_rekey, hapd, NULL);
- if (hapd->driver != NULL &&
+ if (hapd->driver && hapd->drv_priv &&
(hapd->conf->ieee802_1x || hapd->conf->wpa))
hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 0);
/* TODO: dot1xAuthSessionOctetsTx */
/* TODO: dot1xAuthSessionFramesRx */
/* TODO: dot1xAuthSessionFramesTx */
- "dot1xAuthSessionId=%08X-%08X\n"
+ "dot1xAuthSessionId=%016llX\n"
"dot1xAuthSessionAuthenticMethod=%d\n"
"dot1xAuthSessionTime=%u\n"
"dot1xAuthSessionTerminateCause=999\n"
"dot1xAuthSessionUserName=%s\n",
- sta->acct_session_id_hi, sta->acct_session_id_lo,
+ (unsigned long long) sta->acct_session_id,
(wpa_key_mgmt_wpa_ieee8021x(
wpa_auth_sta_key_mgmt(sta->wpa_sm))) ?
1 : 2,
return len;
len += ret;
- if (sm->acct_multi_session_id_hi) {
+ if (sm->acct_multi_session_id) {
ret = os_snprintf(buf + len, buflen - len,
- "authMultiSessionId=%08X+%08X\n",
- sm->acct_multi_session_id_hi,
- sm->acct_multi_session_id_lo);
+ "authMultiSessionId=%016llX\n",
+ (unsigned long long)
+ sm->acct_multi_session_id);
if (os_snprintf_error(buflen - len, ret))
return len;
len += ret;
}
+#ifdef CONFIG_HS20
+static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx)
+{
+ struct hostapd_data *hapd = eloop_ctx;
+ struct sta_info *sta = timeout_ctx;
+
+ if (sta->remediation) {
+ wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to "
+ MACSTR " to indicate Subscription Remediation",
+ MAC2STR(sta->addr));
+ hs20_send_wnm_notification(hapd, sta->addr,
+ sta->remediation_method,
+ sta->remediation_url);
+ os_free(sta->remediation_url);
+ sta->remediation_url = NULL;
+ }
+
+ if (sta->hs20_deauth_req) {
+ wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to "
+ MACSTR " to indicate imminent deauthentication",
+ MAC2STR(sta->addr));
+ hs20_send_wnm_notification_deauth_req(hapd, sta->addr,
+ sta->hs20_deauth_req);
+ }
+}
+#endif /* CONFIG_HS20 */
+
+
static void ieee802_1x_finished(struct hostapd_data *hapd,
struct sta_info *sta, int success,
int remediation)
sta->remediation_method = 1; /* SOAP-XML SPP */
}
- if (success) {
- if (sta->remediation) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification "
- "to " MACSTR " to indicate Subscription "
- "Remediation",
- MAC2STR(sta->addr));
- hs20_send_wnm_notification(hapd, sta->addr,
- sta->remediation_method,
- sta->remediation_url);
- os_free(sta->remediation_url);
- sta->remediation_url = NULL;
- }
-
- if (sta->hs20_deauth_req) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification "
- "to " MACSTR " to indicate imminent "
- "deauthentication", MAC2STR(sta->addr));
- hs20_send_wnm_notification_deauth_req(
- hapd, sta->addr, sta->hs20_deauth_req);
- }
+ if (success && (sta->remediation || sta->hs20_deauth_req)) {
+ wpa_printf(MSG_DEBUG, "HS 2.0: Schedule WNM-Notification to "
+ MACSTR " in 100 ms", MAC2STR(sta->addr));
+ eloop_cancel_timeout(ieee802_1x_wnm_notif_send, hapd, sta);
+ eloop_register_timeout(0, 100000, ieee802_1x_wnm_notif_send,
+ hapd, sta);
}
#endif /* CONFIG_HS20 */
session_timeout = dot11RSNAConfigPMKLifetime;
if (success && key && len >= PMK_LEN && !sta->remediation &&
!sta->hs20_deauth_requested &&
- wpa_auth_pmksa_add(sta->wpa_sm, key, session_timeout,
+ wpa_auth_pmksa_add(sta->wpa_sm, key, len, session_timeout,
sta->eapol_sm) == 0) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
HOSTAPD_LEVEL_DEBUG,
void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
size_t len);
void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta);
-void ieee802_1x_free_station(struct sta_info *sta);
+void ieee802_1x_free_station(struct hostapd_data *hapd, struct sta_info *sta);
void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta);
void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd,
--- /dev/null
+/*
+ * hostapd - MBO
+ * Copyright (c) 2016, 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 "utils/common.h"
+#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
+#include "hostapd.h"
+#include "sta_info.h"
+#include "mbo_ap.h"
+
+
+void mbo_ap_sta_free(struct sta_info *sta)
+{
+ struct mbo_non_pref_chan_info *info, *prev;
+
+ info = sta->non_pref_chan;
+ sta->non_pref_chan = NULL;
+ while (info) {
+ prev = info;
+ info = info->next;
+ os_free(prev);
+ }
+}
+
+
+static void mbo_ap_parse_non_pref_chan(struct sta_info *sta,
+ const u8 *buf, size_t len)
+{
+ struct mbo_non_pref_chan_info *info, *tmp;
+ char channels[200], *pos, *end;
+ size_t num_chan, i;
+ int ret;
+
+ if (len <= 3)
+ return; /* Not enough room for any channels */
+
+ num_chan = len - 3;
+ info = os_zalloc(sizeof(*info) + num_chan);
+ if (!info)
+ return;
+ info->op_class = buf[0];
+ info->pref = buf[len - 2];
+ info->reason_code = buf[len - 1];
+ info->num_channels = num_chan;
+ buf++;
+ os_memcpy(info->channels, buf, num_chan);
+ if (!sta->non_pref_chan) {
+ sta->non_pref_chan = info;
+ } else {
+ tmp = sta->non_pref_chan;
+ while (tmp->next)
+ tmp = tmp->next;
+ tmp->next = info;
+ }
+
+ pos = channels;
+ end = pos + sizeof(channels);
+ *pos = '\0';
+ for (i = 0; i < num_chan; i++) {
+ ret = os_snprintf(pos, end - pos, "%s%u",
+ i == 0 ? "" : " ", buf[i]);
+ if (os_snprintf_error(end - pos, ret)) {
+ *pos = '\0';
+ break;
+ }
+ pos += ret;
+ }
+
+ wpa_printf(MSG_DEBUG, "MBO: STA " MACSTR
+ " non-preferred channel list (op class %u, pref %u, reason code %u, channels %s)",
+ MAC2STR(sta->addr), info->op_class, info->pref,
+ info->reason_code, channels);
+}
+
+
+void mbo_ap_check_sta_assoc(struct hostapd_data *hapd, struct sta_info *sta,
+ struct ieee802_11_elems *elems)
+{
+ const u8 *pos, *attr, *end;
+ size_t len;
+
+ if (!hapd->conf->mbo_enabled || !elems->mbo)
+ return;
+
+ pos = elems->mbo + 4;
+ len = elems->mbo_len - 4;
+ wpa_hexdump(MSG_DEBUG, "MBO: Association Request attributes", pos, len);
+
+ attr = get_ie(pos, len, MBO_ATTR_ID_CELL_DATA_CAPA);
+ if (attr && attr[1] >= 1)
+ sta->cell_capa = attr[2];
+
+ mbo_ap_sta_free(sta);
+ end = pos + len;
+ while (end - pos > 1) {
+ u8 ie_len = pos[1];
+
+ if (2 + ie_len > end - pos)
+ break;
+
+ if (pos[0] == MBO_ATTR_ID_NON_PREF_CHAN_REPORT)
+ mbo_ap_parse_non_pref_chan(sta, pos + 2, ie_len);
+ pos += 2 + pos[1];
+ }
+}
+
+
+int mbo_ap_get_info(struct sta_info *sta, char *buf, size_t buflen)
+{
+ char *pos = buf, *end = buf + buflen;
+ int ret;
+ struct mbo_non_pref_chan_info *info;
+ u8 i;
+ unsigned int count = 0;
+
+ if (!sta->cell_capa)
+ return 0;
+
+ ret = os_snprintf(pos, end - pos, "mbo_cell_capa=%u\n", sta->cell_capa);
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+
+ for (info = sta->non_pref_chan; info; info = info->next) {
+ char *pos2 = pos;
+
+ ret = os_snprintf(pos2, end - pos2,
+ "non_pref_chan[%u]=%u:%u:%u:",
+ count, info->op_class, info->pref,
+ info->reason_code);
+ count++;
+ if (os_snprintf_error(end - pos2, ret))
+ break;
+ pos2 += ret;
+
+ for (i = 0; i < info->num_channels; i++) {
+ ret = os_snprintf(pos2, end - pos2, "%u%s",
+ info->channels[i],
+ i + 1 < info->num_channels ?
+ "," : "");
+ if (os_snprintf_error(end - pos2, ret)) {
+ pos2 = NULL;
+ break;
+ }
+ pos2 += ret;
+ }
+
+ if (!pos2)
+ break;
+ ret = os_snprintf(pos2, end - pos2, "\n");
+ if (os_snprintf_error(end - pos2, ret))
+ break;
+ pos2 += ret;
+ pos = pos2;
+ }
+
+ return pos - buf;
+}
+
+
+static void mbo_ap_wnm_notif_req_cell_capa(struct sta_info *sta,
+ const u8 *buf, size_t len)
+{
+ if (len < 1)
+ return;
+ wpa_printf(MSG_DEBUG, "MBO: STA " MACSTR
+ " updated cellular data capability: %u",
+ MAC2STR(sta->addr), buf[0]);
+ sta->cell_capa = buf[0];
+}
+
+
+static void mbo_ap_wnm_notif_req_elem(struct sta_info *sta, u8 type,
+ const u8 *buf, size_t len,
+ int *first_non_pref_chan)
+{
+ switch (type) {
+ case WFA_WNM_NOTIF_SUBELEM_NON_PREF_CHAN_REPORT:
+ if (*first_non_pref_chan) {
+ /*
+ * Need to free the previously stored entries now to
+ * allow the update to replace all entries.
+ */
+ *first_non_pref_chan = 0;
+ mbo_ap_sta_free(sta);
+ }
+ mbo_ap_parse_non_pref_chan(sta, buf, len);
+ break;
+ case WFA_WNM_NOTIF_SUBELEM_CELL_DATA_CAPA:
+ mbo_ap_wnm_notif_req_cell_capa(sta, buf, len);
+ break;
+ default:
+ wpa_printf(MSG_DEBUG,
+ "MBO: Ignore unknown WNM Notification WFA subelement %u",
+ type);
+ break;
+ }
+}
+
+
+void mbo_ap_wnm_notification_req(struct hostapd_data *hapd, const u8 *addr,
+ const u8 *buf, size_t len)
+{
+ const u8 *pos, *end;
+ u8 ie_len;
+ struct sta_info *sta;
+ int first_non_pref_chan = 1;
+
+ if (!hapd->conf->mbo_enabled)
+ return;
+
+ sta = ap_get_sta(hapd, addr);
+ if (!sta)
+ return;
+
+ pos = buf;
+ end = buf + len;
+
+ while (end - pos > 1) {
+ ie_len = pos[1];
+
+ if (2 + ie_len > end - pos)
+ break;
+
+ if (pos[0] == WLAN_EID_VENDOR_SPECIFIC &&
+ ie_len >= 4 && WPA_GET_BE24(pos + 2) == OUI_WFA)
+ mbo_ap_wnm_notif_req_elem(sta, pos[5],
+ pos + 6, ie_len - 4,
+ &first_non_pref_chan);
+ else
+ wpa_printf(MSG_DEBUG,
+ "MBO: Ignore unknown WNM Notification element %u (len=%u)",
+ pos[0], pos[1]);
+
+ pos += 2 + pos[1];
+ }
+}
--- /dev/null
+/*
+ * MBO related functions and structures
+ * Copyright (c) 2016, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef MBO_AP_H
+#define MBO_AP_H
+
+struct hostapd_data;
+struct sta_info;
+struct ieee802_11_elems;
+
+#ifdef CONFIG_MBO
+
+void mbo_ap_check_sta_assoc(struct hostapd_data *hapd, struct sta_info *sta,
+ struct ieee802_11_elems *elems);
+int mbo_ap_get_info(struct sta_info *sta, char *buf, size_t buflen);
+void mbo_ap_wnm_notification_req(struct hostapd_data *hapd, const u8 *addr,
+ const u8 *buf, size_t len);
+void mbo_ap_sta_free(struct sta_info *sta);
+
+#else /* CONFIG_MBO */
+
+static inline void mbo_ap_check_sta_assoc(struct hostapd_data *hapd,
+ struct sta_info *sta,
+ struct ieee802_11_elems *elems)
+{
+}
+
+static inline int mbo_ap_get_info(struct sta_info *sta, char *buf,
+ size_t buflen)
+{
+ return 0;
+}
+
+static inline void mbo_ap_wnm_notification_req(struct hostapd_data *hapd,
+ const u8 *addr,
+ const u8 *buf, size_t len)
+{
+}
+
+static inline void mbo_ap_sta_free(struct sta_info *sta)
+{
+}
+
+#endif /* CONFIG_MBO */
+
+#endif /* MBO_AP_H */
#include "ap_drv_ops.h"
#include "list.h"
#include "x_snoop.h"
+#include "ndisc_snoop.h"
struct ip6addr {
struct in6_addr addr;
--- /dev/null
+/*
+ * hostapd / Neighboring APs DB
+ * Copyright(c) 2013 - 2016 Intel Mobile Communications GmbH.
+ * Copyright(c) 2011 - 2016 Intel Corporation. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "hostapd.h"
+#include "neighbor_db.h"
+
+
+struct hostapd_neighbor_entry *
+hostapd_neighbor_get(struct hostapd_data *hapd, const u8 *bssid,
+ const struct wpa_ssid_value *ssid)
+{
+ struct hostapd_neighbor_entry *nr;
+
+ dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
+ list) {
+ if (os_memcmp(bssid, nr->bssid, ETH_ALEN) == 0 &&
+ (!ssid ||
+ (ssid->ssid_len == nr->ssid.ssid_len &&
+ os_memcmp(ssid->ssid, nr->ssid.ssid,
+ ssid->ssid_len) == 0)))
+ return nr;
+ }
+ return NULL;
+}
+
+
+static void hostapd_neighbor_clear_entry(struct hostapd_neighbor_entry *nr)
+{
+ wpabuf_free(nr->nr);
+ nr->nr = NULL;
+ wpabuf_free(nr->lci);
+ nr->lci = NULL;
+ wpabuf_free(nr->civic);
+ nr->civic = NULL;
+ os_memset(nr->bssid, 0, sizeof(nr->bssid));
+ os_memset(&nr->ssid, 0, sizeof(nr->ssid));
+}
+
+
+static struct hostapd_neighbor_entry *
+hostapd_neighbor_add(struct hostapd_data *hapd)
+{
+ struct hostapd_neighbor_entry *nr;
+
+ nr = os_zalloc(sizeof(struct hostapd_neighbor_entry));
+ if (!nr)
+ return NULL;
+
+ dl_list_add(&hapd->nr_db, &nr->list);
+
+ return nr;
+}
+
+
+int hostapd_neighbor_set(struct hostapd_data *hapd, const u8 *bssid,
+ const struct wpa_ssid_value *ssid,
+ const struct wpabuf *nr, const struct wpabuf *lci,
+ const struct wpabuf *civic)
+{
+ struct hostapd_neighbor_entry *entry;
+
+ entry = hostapd_neighbor_get(hapd, bssid, ssid);
+ if (!entry)
+ entry = hostapd_neighbor_add(hapd);
+ if (!entry)
+ return -1;
+
+ hostapd_neighbor_clear_entry(entry);
+
+ os_memcpy(entry->bssid, bssid, ETH_ALEN);
+ os_memcpy(&entry->ssid, ssid, sizeof(entry->ssid));
+
+ entry->nr = wpabuf_dup(nr);
+ if (!entry->nr)
+ goto fail;
+
+ if (lci) {
+ entry->lci = wpabuf_dup(lci);
+ if (!entry->lci || os_get_time(&entry->lci_date))
+ goto fail;
+ }
+
+ if (civic) {
+ entry->civic = wpabuf_dup(civic);
+ if (!entry->civic)
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ hostapd_neighbor_remove(hapd, bssid, ssid);
+ return -1;
+}
+
+
+int hostapd_neighbor_remove(struct hostapd_data *hapd, const u8 *bssid,
+ const struct wpa_ssid_value *ssid)
+{
+ struct hostapd_neighbor_entry *nr;
+
+ nr = hostapd_neighbor_get(hapd, bssid, ssid);
+ if (!nr)
+ return -1;
+
+ hostapd_neighbor_clear_entry(nr);
+ dl_list_del(&nr->list);
+ os_free(nr);
+
+ return 0;
+}
+
+
+void hostpad_free_neighbor_db(struct hostapd_data *hapd)
+{
+ struct hostapd_neighbor_entry *nr, *prev;
+
+ dl_list_for_each_safe(nr, prev, &hapd->nr_db,
+ struct hostapd_neighbor_entry, list) {
+ hostapd_neighbor_clear_entry(nr);
+ dl_list_del(&nr->list);
+ os_free(nr);
+ }
+}
--- /dev/null
+/*
+ * hostapd / Neighboring APs DB
+ * Copyright(c) 2013 - 2016 Intel Mobile Communications GmbH.
+ * Copyright(c) 2011 - 2016 Intel Corporation. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef NEIGHBOR_DB_H
+#define NEIGHBOR_DB_H
+
+struct hostapd_neighbor_entry *
+hostapd_neighbor_get(struct hostapd_data *hapd, const u8 *bssid,
+ const struct wpa_ssid_value *ssid);
+int hostapd_neighbor_set(struct hostapd_data *hapd, const u8 *bssid,
+ const struct wpa_ssid_value *ssid,
+ const struct wpabuf *nr, const struct wpabuf *lci,
+ const struct wpabuf *civic);
+int hostapd_neighbor_remove(struct hostapd_data *hapd, const u8 *bssid,
+ const struct wpa_ssid_value *ssid);
+void hostpad_free_neighbor_db(struct hostapd_data *hapd);
+
+#endif /* NEIGHBOR_DB_H */
static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry)
{
+ os_free(entry->vlan_desc);
os_free(entry->identity);
wpabuf_free(entry->cui);
#ifndef CONFIG_NO_RADIUS
}
+/**
+ * pmksa_cache_auth_flush - Flush all PMKSA cache entries
+ * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init()
+ */
+void pmksa_cache_auth_flush(struct rsn_pmksa_cache *pmksa)
+{
+ while (pmksa->pmksa) {
+ wpa_printf(MSG_DEBUG, "RSN: Flush PMKSA cache entry for "
+ MACSTR, MAC2STR(pmksa->pmksa->spa));
+ pmksa_cache_free_entry(pmksa, pmksa->pmksa);
+ }
+}
+
+
static void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx)
{
struct rsn_pmksa_cache *pmksa = eloop_ctx;
static void pmksa_cache_from_eapol_data(struct rsn_pmksa_cache_entry *entry,
struct eapol_state_machine *eapol)
{
+ struct vlan_description *vlan_desc;
+
if (eapol == NULL)
return;
#endif /* CONFIG_NO_RADIUS */
entry->eap_type_authsrv = eapol->eap_type_authsrv;
- entry->vlan_id = ((struct sta_info *) eapol->sta)->vlan_id;
- entry->acct_multi_session_id_hi = eapol->acct_multi_session_id_hi;
- entry->acct_multi_session_id_lo = eapol->acct_multi_session_id_lo;
+ vlan_desc = ((struct sta_info *) eapol->sta)->vlan_desc;
+ if (vlan_desc && vlan_desc->notempty) {
+ entry->vlan_desc = os_zalloc(sizeof(struct vlan_description));
+ if (entry->vlan_desc)
+ *entry->vlan_desc = *vlan_desc;
+ } else {
+ entry->vlan_desc = NULL;
+ }
+
+ entry->acct_multi_session_id = eapol->acct_multi_session_id;
}
-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)
{
if (entry == NULL || eapol == NULL)
}
eapol->eap_type_authsrv = entry->eap_type_authsrv;
- ((struct sta_info *) eapol->sta)->vlan_id = entry->vlan_id;
+#ifndef CONFIG_NO_VLAN
+ ap_sta_set_vlan(hapd, eapol->sta, entry->vlan_desc);
+#endif /* CONFIG_NO_VLAN */
- eapol->acct_multi_session_id_hi = entry->acct_multi_session_id_hi;
- eapol->acct_multi_session_id_lo = entry->acct_multi_session_id_lo;
+ eapol->acct_multi_session_id = entry->acct_multi_session_id;
}
* @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_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
*/
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)
struct rsn_pmksa_cache_entry *entry, *pos;
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)
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);
radius_copy_class(&entry->radius_class, &old_entry->radius_class);
#endif /* CONFIG_NO_RADIUS */
entry->eap_type_authsrv = old_entry->eap_type_authsrv;
- entry->vlan_id = old_entry->vlan_id;
+ if (old_entry->vlan_desc) {
+ entry->vlan_desc = os_zalloc(sizeof(struct vlan_description));
+ if (entry->vlan_desc)
+ *entry->vlan_desc = *old_entry->vlan_desc;
+ } else {
+ entry->vlan_desc = NULL;
+ }
entry->opportunistic = 1;
pmksa_cache_link_entry(pmksa, entry);
if (attr->acct_multi_session_id) {
char buf[20];
- if (attr->acct_multi_session_id_len != 17)
+ if (attr->acct_multi_session_id_len != 16)
return 0;
- os_snprintf(buf, sizeof(buf), "%08X+%08X",
- entry->acct_multi_session_id_hi,
- entry->acct_multi_session_id_lo);
- if (os_memcmp(attr->acct_multi_session_id, buf, 17) != 0)
+ os_snprintf(buf, sizeof(buf), "%016llX",
+ (unsigned long long) entry->acct_multi_session_id);
+ if (os_memcmp(attr->acct_multi_session_id, buf, 16) != 0)
return 0;
match++;
}
return found ? 0 : -1;
}
+
+
+/**
+ * pmksa_cache_auth_list - Dump text list of entries in PMKSA cache
+ * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init()
+ * @buf: Buffer for the list
+ * @len: Length of the buffer
+ * Returns: Number of bytes written to buffer
+ *
+ * This function is used to generate a text format representation of the
+ * current PMKSA cache contents for the ctrl_iface PMKSA command.
+ */
+int pmksa_cache_auth_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len)
+{
+ int i, ret;
+ char *pos = buf;
+ struct rsn_pmksa_cache_entry *entry;
+ struct os_reltime now;
+
+ os_get_reltime(&now);
+ ret = os_snprintf(pos, buf + len - pos,
+ "Index / SPA / PMKID / expiration (in seconds) / opportunistic\n");
+ if (os_snprintf_error(buf + len - pos, ret))
+ return pos - buf;
+ pos += ret;
+ i = 0;
+ entry = pmksa->pmksa;
+ while (entry) {
+ ret = os_snprintf(pos, buf + len - pos, "%d " MACSTR " ",
+ i, MAC2STR(entry->spa));
+ if (os_snprintf_error(buf + len - pos, ret))
+ return pos - buf;
+ pos += ret;
+ pos += wpa_snprintf_hex(pos, buf + len - pos, entry->pmkid,
+ PMKID_LEN);
+ ret = os_snprintf(pos, buf + len - pos, " %d %d\n",
+ (int) (entry->expiration - now.sec),
+ entry->opportunistic);
+ if (os_snprintf_error(buf + len - pos, ret))
+ return pos - buf;
+ pos += ret;
+ entry = entry->next;
+ }
+ return pos - buf;
+}
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_* */
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;
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);
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 */
--- /dev/null
+/*
+ * hostapd / Radio Measurement (RRM)
+ * Copyright(c) 2013 - 2016 Intel Mobile Communications GmbH.
+ * Copyright(c) 2011 - 2016 Intel Corporation. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "hostapd.h"
+#include "ap_drv_ops.h"
+#include "sta_info.h"
+#include "eloop.h"
+#include "neighbor_db.h"
+#include "rrm.h"
+
+#define HOSTAPD_RRM_REQUEST_TIMEOUT 5
+
+
+static void hostapd_lci_rep_timeout_handler(void *eloop_data, void *user_ctx)
+{
+ struct hostapd_data *hapd = eloop_data;
+
+ wpa_printf(MSG_DEBUG, "RRM: LCI request (token %u) timed out",
+ hapd->lci_req_token);
+ hapd->lci_req_active = 0;
+}
+
+
+static void hostapd_handle_lci_report(struct hostapd_data *hapd, u8 token,
+ const u8 *pos, size_t len)
+{
+ if (!hapd->lci_req_active || hapd->lci_req_token != token) {
+ wpa_printf(MSG_DEBUG, "Unexpected LCI report, token %u", token);
+ return;
+ }
+
+ hapd->lci_req_active = 0;
+ eloop_cancel_timeout(hostapd_lci_rep_timeout_handler, hapd, NULL);
+ wpa_printf(MSG_DEBUG, "LCI report token %u len %zu", token, len);
+}
+
+
+static void hostapd_range_rep_timeout_handler(void *eloop_data, void *user_ctx)
+{
+ struct hostapd_data *hapd = eloop_data;
+
+ wpa_printf(MSG_DEBUG, "RRM: Range request (token %u) timed out",
+ hapd->range_req_token);
+ hapd->range_req_active = 0;
+}
+
+
+static void hostapd_handle_range_report(struct hostapd_data *hapd, u8 token,
+ const u8 *pos, size_t len)
+{
+ if (!hapd->range_req_active || hapd->range_req_token != token) {
+ wpa_printf(MSG_DEBUG, "Unexpected range report, token %u",
+ token);
+ return;
+ }
+
+ hapd->range_req_active = 0;
+ eloop_cancel_timeout(hostapd_range_rep_timeout_handler, hapd, NULL);
+ wpa_printf(MSG_DEBUG, "Range report token %u len %zu", token, len);
+}
+
+
+static void hostapd_handle_radio_msmt_report(struct hostapd_data *hapd,
+ const u8 *buf, size_t len)
+{
+ const struct ieee80211_mgmt *mgmt = (const struct ieee80211_mgmt *) buf;
+ const u8 *pos, *ie, *end;
+ u8 token;
+
+ end = buf + len;
+ token = mgmt->u.action.u.rrm.dialog_token;
+ pos = mgmt->u.action.u.rrm.variable;
+
+ while ((ie = get_ie(pos, end - pos, WLAN_EID_MEASURE_REPORT))) {
+ if (ie[1] < 5) {
+ wpa_printf(MSG_DEBUG, "Bad Measurement Report element");
+ break;
+ }
+
+ wpa_printf(MSG_DEBUG, "Measurement report type %u", ie[4]);
+
+ switch (ie[4]) {
+ case MEASURE_TYPE_LCI:
+ hostapd_handle_lci_report(hapd, token, ie + 2, ie[1]);
+ break;
+ case MEASURE_TYPE_FTM_RANGE:
+ hostapd_handle_range_report(hapd, token, ie + 2, ie[1]);
+ break;
+ default:
+ wpa_printf(MSG_DEBUG,
+ "Measurement report type %u is not supported",
+ ie[4]);
+ break;
+ }
+
+ pos = ie + ie[1] + 2;
+ }
+}
+
+
+static u16 hostapd_parse_location_lci_req_age(const u8 *buf, size_t len)
+{
+ const u8 *subelem;
+
+ /* Range Request element + Location Subject + Maximum Age subelement */
+ if (len < 3 + 1 + 4)
+ return 0;
+
+ /* Subelements are arranged as IEs */
+ subelem = get_ie(buf + 4, len - 4, LCI_REQ_SUBELEM_MAX_AGE);
+ if (subelem && subelem[1] == 2)
+ return *(u16 *) (subelem + 2);
+
+ return 0;
+}
+
+
+static int hostapd_check_lci_age(struct hostapd_neighbor_entry *nr, u16 max_age)
+{
+ struct os_time curr, diff;
+ unsigned long diff_l;
+
+ if (!max_age)
+ return 0;
+
+ if (max_age == 0xffff)
+ return 1;
+
+ if (os_get_time(&curr))
+ return 0;
+
+ os_time_sub(&curr, &nr->lci_date, &diff);
+
+ /* avoid overflow */
+ if (diff.sec > 0xffff)
+ return 0;
+
+ /* LCI age is calculated in 10th of a second units. */
+ diff_l = diff.sec * 10 + diff.usec / 100000;
+
+ return max_age > diff_l;
+}
+
+
+static size_t hostapd_neighbor_report_len(struct wpabuf *buf,
+ struct hostapd_neighbor_entry *nr,
+ int send_lci, int send_civic)
+{
+ size_t len = 2 + wpabuf_len(nr->nr);
+
+ if (send_lci && nr->lci)
+ len += 2 + wpabuf_len(nr->lci);
+
+ if (send_civic && nr->civic)
+ len += 2 + wpabuf_len(nr->civic);
+
+ return len;
+}
+
+
+static void hostapd_send_nei_report_resp(struct hostapd_data *hapd,
+ const u8 *addr, u8 dialog_token,
+ struct wpa_ssid_value *ssid, u8 lci,
+ u8 civic, u16 lci_max_age)
+{
+ struct hostapd_neighbor_entry *nr;
+ struct wpabuf *buf;
+ u8 *msmt_token;
+
+ /*
+ * The number and length of the Neighbor Report elements in a Neighbor
+ * Report frame is limited by the maximum allowed MMPDU size; + 3 bytes
+ * of RRM header.
+ */
+ buf = wpabuf_alloc(3 + IEEE80211_MAX_MMPDU_SIZE);
+ if (!buf)
+ return;
+
+ wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
+ wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_RESPONSE);
+ wpabuf_put_u8(buf, dialog_token);
+
+ dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
+ list) {
+ int send_lci;
+ size_t len;
+
+ if (ssid->ssid_len != nr->ssid.ssid_len ||
+ os_memcmp(ssid->ssid, nr->ssid.ssid, ssid->ssid_len) != 0)
+ continue;
+
+ send_lci = (lci != 0) && hostapd_check_lci_age(nr, lci_max_age);
+ len = hostapd_neighbor_report_len(buf, nr, send_lci, civic);
+
+ if (len - 2 > 0xff) {
+ wpa_printf(MSG_DEBUG,
+ "NR entry for " MACSTR " exceeds 0xFF bytes",
+ MAC2STR(nr->bssid));
+ continue;
+ }
+
+ if (len > wpabuf_tailroom(buf))
+ break;
+
+ wpabuf_put_u8(buf, WLAN_EID_NEIGHBOR_REPORT);
+ wpabuf_put_u8(buf, len - 2);
+ wpabuf_put_buf(buf, nr->nr);
+
+ if (send_lci && nr->lci) {
+ wpabuf_put_u8(buf, WLAN_EID_MEASURE_REPORT);
+ wpabuf_put_u8(buf, wpabuf_len(nr->lci));
+ /*
+ * Override measurement token - the first byte of the
+ * Measurement Report element.
+ */
+ msmt_token = wpabuf_put(buf, 0);
+ wpabuf_put_buf(buf, nr->lci);
+ *msmt_token = lci;
+ }
+
+ if (civic && nr->civic) {
+ wpabuf_put_u8(buf, WLAN_EID_MEASURE_REPORT);
+ wpabuf_put_u8(buf, wpabuf_len(nr->civic));
+ /*
+ * Override measurement token - the first byte of the
+ * Measurement Report element.
+ */
+ msmt_token = wpabuf_put(buf, 0);
+ wpabuf_put_buf(buf, nr->civic);
+ *msmt_token = civic;
+ }
+ }
+
+ hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
+ wpabuf_head(buf), wpabuf_len(buf));
+ wpabuf_free(buf);
+}
+
+
+static void hostapd_handle_nei_report_req(struct hostapd_data *hapd,
+ const u8 *buf, size_t len)
+{
+ const struct ieee80211_mgmt *mgmt = (const struct ieee80211_mgmt *) buf;
+ const u8 *pos, *ie, *end;
+ struct wpa_ssid_value ssid = {
+ .ssid_len = 0
+ };
+ u8 token;
+ u8 lci = 0, civic = 0; /* Measurement tokens */
+ u16 lci_max_age = 0;
+
+ if (!(hapd->conf->radio_measurements[0] &
+ WLAN_RRM_CAPS_NEIGHBOR_REPORT))
+ return;
+
+ end = buf + len;
+
+ token = mgmt->u.action.u.rrm.dialog_token;
+ pos = mgmt->u.action.u.rrm.variable;
+ len = end - pos;
+
+ ie = get_ie(pos, len, WLAN_EID_SSID);
+ if (ie && ie[1] && ie[1] <= SSID_MAX_LEN) {
+ ssid.ssid_len = ie[1];
+ os_memcpy(ssid.ssid, ie + 2, ssid.ssid_len);
+ } else {
+ ssid.ssid_len = hapd->conf->ssid.ssid_len;
+ os_memcpy(ssid.ssid, hapd->conf->ssid.ssid, ssid.ssid_len);
+ }
+
+ while ((ie = get_ie(pos, len, WLAN_EID_MEASURE_REQUEST))) {
+ if (ie[1] < 3)
+ break;
+
+ wpa_printf(MSG_DEBUG,
+ "Neighbor report request, measure type %u",
+ ie[4]);
+
+ switch (ie[4]) { /* Measurement Type */
+ case MEASURE_TYPE_LCI:
+ lci = ie[2]; /* Measurement Token */
+ lci_max_age = hostapd_parse_location_lci_req_age(ie + 2,
+ ie[1]);
+ break;
+ case MEASURE_TYPE_LOCATION_CIVIC:
+ civic = ie[2]; /* Measurement token */
+ break;
+ }
+
+ pos = ie + ie[1] + 2;
+ len = end - pos;
+ }
+
+ hostapd_send_nei_report_resp(hapd, mgmt->sa, token, &ssid, lci, civic,
+ lci_max_age);
+}
+
+
+void hostapd_handle_radio_measurement(struct hostapd_data *hapd,
+ const u8 *buf, size_t len)
+{
+ const struct ieee80211_mgmt *mgmt = (const struct ieee80211_mgmt *) buf;
+
+ /*
+ * Check for enough bytes: header + (1B)Category + (1B)Action +
+ * (1B)Dialog Token.
+ */
+ if (len < IEEE80211_HDRLEN + 3)
+ return;
+
+ wpa_printf(MSG_DEBUG, "Radio measurement frame, action %u from " MACSTR,
+ mgmt->u.action.u.rrm.action, MAC2STR(mgmt->sa));
+
+ switch (mgmt->u.action.u.rrm.action) {
+ case WLAN_RRM_RADIO_MEASUREMENT_REPORT:
+ hostapd_handle_radio_msmt_report(hapd, buf, len);
+ break;
+ case WLAN_RRM_NEIGHBOR_REPORT_REQUEST:
+ hostapd_handle_nei_report_req(hapd, buf, len);
+ break;
+ default:
+ wpa_printf(MSG_DEBUG, "RRM action %u is not supported",
+ mgmt->u.action.u.rrm.action);
+ break;
+ }
+}
+
+
+int hostapd_send_lci_req(struct hostapd_data *hapd, const u8 *addr)
+{
+ struct wpabuf *buf;
+ struct sta_info *sta = ap_get_sta(hapd, addr);
+ int ret;
+
+ if (!sta) {
+ wpa_printf(MSG_INFO,
+ "Request LCI: Destination address is not in station list");
+ return -1;
+ }
+
+ if (!(sta->flags & WLAN_STA_AUTHORIZED)) {
+ wpa_printf(MSG_INFO,
+ "Request LCI: Destination address is not connected");
+ return -1;
+ }
+
+ if (!(sta->rrm_enabled_capa[1] & WLAN_RRM_CAPS_LCI_MEASUREMENT)) {
+ wpa_printf(MSG_INFO,
+ "Request LCI: Station does not support LCI in RRM");
+ return -1;
+ }
+
+ if (hapd->lci_req_active) {
+ wpa_printf(MSG_DEBUG,
+ "Request LCI: LCI request is already in process, overriding");
+ hapd->lci_req_active = 0;
+ eloop_cancel_timeout(hostapd_lci_rep_timeout_handler, hapd,
+ NULL);
+ }
+
+ /* Measurement request (5) + Measurement element with LCI (10) */
+ buf = wpabuf_alloc(5 + 10);
+ if (!buf)
+ return -1;
+
+ hapd->lci_req_token++;
+ /* For wraparounds - the token must be nonzero */
+ if (!hapd->lci_req_token)
+ hapd->lci_req_token++;
+
+ wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
+ wpabuf_put_u8(buf, WLAN_RRM_RADIO_MEASUREMENT_REQUEST);
+ wpabuf_put_u8(buf, hapd->lci_req_token);
+ wpabuf_put_le16(buf, 0); /* Number of repetitions */
+
+ wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
+ wpabuf_put_u8(buf, 3 + 1 + 4);
+
+ wpabuf_put_u8(buf, 1); /* Measurement Token */
+ /*
+ * Parallel and Enable bits are 0, Duration, Request, and Report are
+ * reserved.
+ */
+ wpabuf_put_u8(buf, 0);
+ wpabuf_put_u8(buf, MEASURE_TYPE_LCI);
+
+ wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
+
+ wpabuf_put_u8(buf, LCI_REQ_SUBELEM_MAX_AGE);
+ wpabuf_put_u8(buf, 2);
+ wpabuf_put_le16(buf, 0xffff);
+
+ ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
+ wpabuf_head(buf), wpabuf_len(buf));
+ wpabuf_free(buf);
+ if (ret)
+ return ret;
+
+ hapd->lci_req_active = 1;
+
+ eloop_register_timeout(HOSTAPD_RRM_REQUEST_TIMEOUT, 0,
+ hostapd_lci_rep_timeout_handler, hapd, NULL);
+
+ return 0;
+}
+
+
+int hostapd_send_range_req(struct hostapd_data *hapd, const u8 *addr,
+ u16 random_interval, u8 min_ap,
+ const u8 *responders, unsigned int n_responders)
+{
+ struct wpabuf *buf;
+ struct sta_info *sta;
+ u8 *len;
+ unsigned int i;
+ int ret;
+
+ wpa_printf(MSG_DEBUG, "Request range: dest addr " MACSTR
+ " rand interval %u min AP %u n_responders %u", MAC2STR(addr),
+ random_interval, min_ap, n_responders);
+
+ if (min_ap == 0 || min_ap > n_responders) {
+ wpa_printf(MSG_INFO, "Request range: Wrong min AP count");
+ return -1;
+ }
+
+ sta = ap_get_sta(hapd, addr);
+ if (!sta || !(sta->flags & WLAN_STA_AUTHORIZED)) {
+ wpa_printf(MSG_INFO,
+ "Request range: Destination address is not connected");
+ return -1;
+ }
+
+ if (!(sta->rrm_enabled_capa[4] & WLAN_RRM_CAPS_FTM_RANGE_REPORT)) {
+ wpa_printf(MSG_ERROR,
+ "Request range: Destination station does not support FTM range report in RRM");
+ return -1;
+ }
+
+ if (hapd->range_req_active) {
+ wpa_printf(MSG_DEBUG,
+ "Request range: Range request is already in process; overriding");
+ hapd->range_req_active = 0;
+ eloop_register_timeout(HOSTAPD_RRM_REQUEST_TIMEOUT, 0,
+ hostapd_range_rep_timeout_handler, hapd,
+ NULL);
+ }
+
+ /* Action + measurement type + token + reps + EID + len = 7 */
+ buf = wpabuf_alloc(7 + 255);
+ if (!buf)
+ return -1;
+
+ hapd->range_req_token++;
+ if (!hapd->range_req_token) /* For wraparounds */
+ hapd->range_req_token++;
+
+ /* IEEE P802.11-REVmc/D5.0, 9.6.7.2 */
+ wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
+ wpabuf_put_u8(buf, WLAN_RRM_RADIO_MEASUREMENT_REQUEST);
+ wpabuf_put_u8(buf, hapd->range_req_token); /* Dialog Token */
+ wpabuf_put_le16(buf, 0); /* Number of Repetitions */
+
+ /* IEEE P802.11-REVmc/D5.0, 9.4.2.21 */
+ wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
+ len = wpabuf_put(buf, 1); /* Length will be set later */
+
+ wpabuf_put_u8(buf, 1); /* Measurement Token */
+ /*
+ * Parallel and Enable bits are 0; Duration, Request, and Report are
+ * reserved.
+ */
+ wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
+ wpabuf_put_u8(buf, MEASURE_TYPE_FTM_RANGE); /* Measurement Type */
+
+ /* IEEE P802.11-REVmc/D5.0, 9.4.2.21.19 */
+ wpabuf_put_le16(buf, random_interval); /* Randomization Interval */
+ wpabuf_put_u8(buf, min_ap); /* Minimum AP Count */
+
+ /* FTM Range Subelements */
+
+ /*
+ * Taking the neighbor report part of the range request from neighbor
+ * database instead of requesting the separate bits of data from the
+ * user.
+ */
+ for (i = 0; i < n_responders; i++) {
+ struct hostapd_neighbor_entry *nr;
+
+ nr = hostapd_neighbor_get(hapd, responders + ETH_ALEN * i,
+ NULL);
+ if (!nr) {
+ wpa_printf(MSG_INFO, "Missing neighbor report for "
+ MACSTR, MAC2STR(responders + ETH_ALEN * i));
+ wpabuf_free(buf);
+ return -1;
+ }
+
+ if (wpabuf_tailroom(buf) < 2 + wpabuf_len(nr->nr)) {
+ wpa_printf(MSG_ERROR, "Too long range request");
+ wpabuf_free(buf);
+ return -1;
+ }
+
+ wpabuf_put_u8(buf, WLAN_EID_NEIGHBOR_REPORT);
+ wpabuf_put_u8(buf, wpabuf_len(nr->nr));
+ wpabuf_put_buf(buf, nr->nr);
+ }
+
+ /* Action + measurement type + token + reps + EID + len = 7 */
+ *len = wpabuf_len(buf) - 7;
+
+ ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
+ wpabuf_head(buf), wpabuf_len(buf));
+ wpabuf_free(buf);
+ if (ret)
+ return ret;
+
+ hapd->range_req_active = 1;
+
+ eloop_register_timeout(HOSTAPD_RRM_REQUEST_TIMEOUT, 0,
+ hostapd_range_rep_timeout_handler, hapd, NULL);
+
+ return 0;
+}
+
+
+void hostapd_clean_rrm(struct hostapd_data *hapd)
+{
+ hostpad_free_neighbor_db(hapd);
+ eloop_cancel_timeout(hostapd_lci_rep_timeout_handler, hapd, NULL);
+ hapd->lci_req_active = 0;
+ eloop_cancel_timeout(hostapd_range_rep_timeout_handler, hapd, NULL);
+ hapd->range_req_active = 0;
+}
--- /dev/null
+/*
+ * hostapd / Radio Measurement (RRM)
+ * Copyright(c) 2013 - 2016 Intel Mobile Communications GmbH.
+ * Copyright(c) 2011 - 2016 Intel Corporation. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef RRM_H
+#define RRM_H
+
+/*
+ * Max measure request length is 255, -6 of the body we have 249 for the
+ * neighbor report elements. Each neighbor report element is at least 2 + 13
+ * bytes, so we can't have more than 16 responders in the request.
+ */
+#define RRM_RANGE_REQ_MAX_RESPONDERS 16
+
+void hostapd_handle_radio_measurement(struct hostapd_data *hapd,
+ const u8 *buf, size_t len);
+int hostapd_send_lci_req(struct hostapd_data *hapd, const u8 *addr);
+int hostapd_send_range_req(struct hostapd_data *hapd, const u8 *addr,
+ u16 random_interval, u8 min_ap,
+ const u8 *responders, unsigned int n_responders);
+void hostapd_clean_rrm(struct hostapd_data *hapd);
+
+#endif /* RRM_H */
#include "ap_drv_ops.h"
#include "gas_serv.h"
#include "wnm_ap.h"
+#include "mbo_ap.h"
#include "ndisc_snoop.h"
#include "sta_info.h"
+#include "vlan.h"
static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
struct sta_info *sta);
ap_sta_ip6addr_del(hapd, sta);
if (!hapd->iface->driver_ap_teardown &&
- !(sta->flags & WLAN_STA_PREAUTH))
+ !(sta->flags & WLAN_STA_PREAUTH)) {
hostapd_drv_sta_remove(hapd, sta->addr);
-
-#ifndef CONFIG_NO_VLAN
- if (sta->vlan_id_bound) {
- /*
- * Need to remove the STA entry before potentially removing the
- * VLAN.
- */
- if (hapd->iface->driver_ap_teardown &&
- !(sta->flags & WLAN_STA_PREAUTH))
- hostapd_drv_sta_remove(hapd, sta->addr);
- vlan_remove_dynamic(hapd, sta->vlan_id_bound);
+ sta->added_unassoc = 0;
}
-#endif /* CONFIG_NO_VLAN */
ap_sta_hash_del(hapd, sta);
ap_sta_list_del(hapd, sta);
hapd->iface->num_sta_ht_20mhz--;
}
+#ifdef CONFIG_TAXONOMY
+ wpabuf_free(sta->probe_ie_taxonomy);
+ sta->probe_ie_taxonomy = NULL;
+ wpabuf_free(sta->assoc_ie_taxonomy);
+ sta->assoc_ie_taxonomy = NULL;
+#endif /* CONFIG_TAXONOMY */
+
#ifdef CONFIG_IEEE80211N
ht40_intolerant_remove(hapd->iface, sta);
#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_MESH
if (hapd->mesh_sta_free_cb)
- hapd->mesh_sta_free_cb(sta);
+ hapd->mesh_sta_free_cb(hapd, sta);
#endif /* CONFIG_MESH */
if (set_beacon)
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
eloop_cancel_timeout(ap_handle_session_warning_timer, hapd, sta);
- eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta);
- eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
+ ap_sta_clear_disconnect_timeouts(hapd, sta);
sae_clear_retransmit_timer(hapd, sta);
- ieee802_1x_free_station(sta);
+ ieee802_1x_free_station(hapd, sta);
wpa_auth_sta_deinit(sta->wpa_sm);
rsn_preauth_free_station(hapd, sta);
#ifndef CONFIG_NO_RADIUS
radius_client_flush_auth(hapd->radius, sta->addr);
#endif /* CONFIG_NO_RADIUS */
+#ifndef CONFIG_NO_VLAN
+ /*
+ * sta->wpa_sm->group needs to be released before so that
+ * vlan_remove_dynamic() can check that no stations are left on the
+ * AP_VLAN netdev.
+ */
+ if (sta->vlan_id)
+ vlan_remove_dynamic(hapd, sta->vlan_id);
+ if (sta->vlan_id_bound) {
+ /*
+ * Need to remove the STA entry before potentially removing the
+ * VLAN.
+ */
+ if (hapd->iface->driver_ap_teardown &&
+ !(sta->flags & WLAN_STA_PREAUTH)) {
+ hostapd_drv_sta_remove(hapd, sta->addr);
+ sta->added_unassoc = 0;
+ }
+ vlan_remove_dynamic(hapd, sta->vlan_id_bound);
+ }
+#endif /* CONFIG_NO_VLAN */
+
os_free(sta->challenge);
#ifdef CONFIG_IEEE80211W
os_free(sta->sae);
#endif /* CONFIG_SAE */
+ mbo_ap_sta_free(sta);
+ os_free(sta->supp_op_classes);
+
os_free(sta);
}
unsigned long next_time = 0;
int reason;
- wpa_printf(MSG_DEBUG, "%s: " MACSTR " flags=0x%x timeout_next=%d",
- __func__, MAC2STR(sta->addr), sta->flags,
+ wpa_printf(MSG_DEBUG, "%s: %s: " MACSTR " flags=0x%x timeout_next=%d",
+ hapd->conf->iface, __func__, MAC2STR(sta->addr), sta->flags,
sta->timeout_next);
if (sta->timeout_next == STA_REMOVE) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
sta->acct_terminate_cause =
RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT;
accounting_sta_stop(hapd, sta);
- ieee802_1x_free_station(sta);
+ ieee802_1x_free_station(hapd, sta);
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "disassociated due to "
"inactivity");
struct hostapd_data *hapd = eloop_ctx;
struct sta_info *sta = timeout_ctx;
+ wpa_printf(MSG_DEBUG, "%s: Session timer for STA " MACSTR,
+ hapd->conf->iface, MAC2STR(sta->addr));
if (!(sta->flags & WLAN_STA_AUTH)) {
if (sta->flags & WLAN_STA_GAS) {
wpa_printf(MSG_DEBUG, "GAS: Remove temporary STA "
struct hostapd_data *hapd = eloop_ctx;
struct sta_info *sta = timeout_ctx;
- wpa_printf(MSG_DEBUG, "WNM: Session warning time reached for " MACSTR,
- MAC2STR(sta->addr));
+ wpa_printf(MSG_DEBUG, "%s: WNM: Session warning time reached for "
+ MACSTR, hapd->conf->iface, MAC2STR(sta->addr));
if (sta->hs20_session_info_url == NULL)
return;
return NULL;
}
sta->acct_interim_interval = hapd->conf->acct_interim_interval;
- accounting_sta_get_id(hapd, sta);
+ if (accounting_sta_get_id(hapd, sta) < 0) {
+ os_free(sta);
+ return NULL;
+ }
if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER)) {
wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout "
sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
dl_list_init(&sta->ip6addr);
+#ifdef CONFIG_TAXONOMY
+ sta_track_claim_taxonomy_info(hapd->iface, addr,
+ &sta->probe_ie_taxonomy);
+#endif /* CONFIG_TAXONOMY */
+
return sta;
}
hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr);
ap_sta_ip6addr_del(hapd, sta);
- wpa_printf(MSG_DEBUG, "Removing STA " MACSTR " from kernel driver",
- MAC2STR(sta->addr));
+ wpa_printf(MSG_DEBUG, "%s: Removing STA " MACSTR " from kernel driver",
+ hapd->conf->iface, MAC2STR(sta->addr));
if (hostapd_drv_sta_remove(hapd, sta->addr) &&
sta->flags & WLAN_STA_ASSOC) {
- wpa_printf(MSG_DEBUG, "Could not remove station " MACSTR
- " from kernel driver.", MAC2STR(sta->addr));
+ wpa_printf(MSG_DEBUG, "%s: Could not remove station " MACSTR
+ " from kernel driver",
+ hapd->conf->iface, MAC2STR(sta->addr));
return -1;
}
+ sta->added_unassoc = 0;
return 0;
}
if (!sta2)
continue;
+ wpa_printf(MSG_DEBUG, "%s: disconnect old STA " MACSTR
+ " association from another BSS %s",
+ hapd->conf->iface, MAC2STR(sta2->addr),
+ bss->conf->iface);
ap_sta_disconnect(bss, sta2, sta2->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID);
}
struct hostapd_data *hapd = eloop_ctx;
struct sta_info *sta = timeout_ctx;
+ wpa_printf(MSG_DEBUG, "%s: Disassociation callback for STA " MACSTR,
+ hapd->conf->iface, MAC2STR(sta->addr));
ap_sta_remove(hapd, sta);
mlme_disassociate_indication(hapd, sta, sta->disassoc_reason);
}
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0,
ap_handle_timer, hapd, sta);
accounting_sta_stop(hapd, sta);
- ieee802_1x_free_station(sta);
+ ieee802_1x_free_station(hapd, sta);
sta->disassoc_reason = reason;
sta->flags |= WLAN_STA_PENDING_DISASSOC_CB;
struct hostapd_data *hapd = eloop_ctx;
struct sta_info *sta = timeout_ctx;
+ wpa_printf(MSG_DEBUG, "%s: Deauthentication callback for STA " MACSTR,
+ hapd->conf->iface, MAC2STR(sta->addr));
ap_sta_remove(hapd, sta);
mlme_deauthenticate_indication(hapd, sta, sta->deauth_reason);
}
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
ap_handle_timer, hapd, sta);
accounting_sta_stop(hapd, sta);
- ieee802_1x_free_station(sta);
+ ieee802_1x_free_station(hapd, sta);
sta->deauth_reason = reason;
sta->flags |= WLAN_STA_PENDING_DEAUTH_CB;
#endif /* CONFIG_WPS */
+static int ap_sta_get_free_vlan_id(struct hostapd_data *hapd)
+{
+ struct hostapd_vlan *vlan;
+ int vlan_id = MAX_VLAN_ID + 2;
+
+retry:
+ for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) {
+ if (vlan->vlan_id == vlan_id) {
+ vlan_id++;
+ goto retry;
+ }
+ }
+ return vlan_id;
+}
+
+
+int ap_sta_set_vlan(struct hostapd_data *hapd, struct sta_info *sta,
+ struct vlan_description *vlan_desc)
+{
+ struct hostapd_vlan *vlan = NULL, *wildcard_vlan = NULL;
+ int old_vlan_id, vlan_id = 0, ret = 0;
+
+ if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_DISABLED)
+ vlan_desc = NULL;
+
+ /* Check if there is something to do */
+ if (hapd->conf->ssid.per_sta_vif && !sta->vlan_id) {
+ /* This sta is lacking its own vif */
+ } else if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_DISABLED &&
+ !hapd->conf->ssid.per_sta_vif && sta->vlan_id) {
+ /* sta->vlan_id needs to be reset */
+ } else if (!vlan_compare(vlan_desc, sta->vlan_desc)) {
+ return 0; /* nothing to change */
+ }
+
+ /* Now the real VLAN changed or the STA just needs its own vif */
+ if (hapd->conf->ssid.per_sta_vif) {
+ /* Assign a new vif, always */
+ /* find a free vlan_id sufficiently big */
+ vlan_id = ap_sta_get_free_vlan_id(hapd);
+ /* Get wildcard VLAN */
+ for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) {
+ if (vlan->vlan_id == VLAN_ID_WILDCARD)
+ break;
+ }
+ if (!vlan) {
+ hostapd_logger(hapd, sta->addr,
+ HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_DEBUG,
+ "per_sta_vif missing wildcard");
+ vlan_id = 0;
+ ret = -1;
+ goto done;
+ }
+ } else if (vlan_desc && vlan_desc->notempty) {
+ for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) {
+ if (!vlan_compare(&vlan->vlan_desc, vlan_desc))
+ break;
+ if (vlan->vlan_id == VLAN_ID_WILDCARD)
+ wildcard_vlan = vlan;
+ }
+ if (vlan) {
+ vlan_id = vlan->vlan_id;
+ } else if (wildcard_vlan) {
+ vlan = wildcard_vlan;
+ vlan_id = vlan_desc->untagged;
+ if (vlan_desc->tagged[0]) {
+ /* Tagged VLAN configuration */
+ vlan_id = ap_sta_get_free_vlan_id(hapd);
+ }
+ } else {
+ hostapd_logger(hapd, sta->addr,
+ HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_DEBUG,
+ "missing vlan and wildcard for vlan=%d%s",
+ vlan_desc->untagged,
+ vlan_desc->tagged[0] ? "+" : "");
+ vlan_id = 0;
+ ret = -1;
+ goto done;
+ }
+ }
+
+ if (vlan && vlan->vlan_id == VLAN_ID_WILDCARD) {
+ vlan = vlan_add_dynamic(hapd, vlan, vlan_id, vlan_desc);
+ if (vlan == NULL) {
+ hostapd_logger(hapd, sta->addr,
+ HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_DEBUG,
+ "could not add dynamic VLAN interface for vlan=%d%s",
+ vlan_desc ? vlan_desc->untagged : -1,
+ (vlan_desc && vlan_desc->tagged[0]) ?
+ "+" : "");
+ vlan_id = 0;
+ ret = -1;
+ goto done;
+ }
+
+ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_DEBUG,
+ "added new dynamic VLAN interface '%s'",
+ vlan->ifname);
+ } else if (vlan && vlan->dynamic_vlan > 0) {
+ vlan->dynamic_vlan++;
+ hostapd_logger(hapd, sta->addr,
+ HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_DEBUG,
+ "updated existing dynamic VLAN interface '%s'",
+ vlan->ifname);
+ }
+done:
+ old_vlan_id = sta->vlan_id;
+ sta->vlan_id = vlan_id;
+ sta->vlan_desc = vlan ? &vlan->vlan_desc : NULL;
+
+ if (vlan_id != old_vlan_id && old_vlan_id)
+ vlan_remove_dynamic(hapd, old_vlan_id);
+
+ return ret;
+}
+
+
int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta)
{
#ifndef CONFIG_NO_VLAN
if (hapd->conf->ssid.vlan[0])
iface = hapd->conf->ssid.vlan;
- if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_DISABLED)
- sta->vlan_id = 0;
- else if (sta->vlan_id > 0) {
- struct hostapd_vlan *wildcard_vlan = NULL;
- vlan = hapd->conf->vlan;
- while (vlan) {
+ if (sta->vlan_id > 0) {
+ for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) {
if (vlan->vlan_id == sta->vlan_id)
break;
- if (vlan->vlan_id == VLAN_ID_WILDCARD)
- wildcard_vlan = vlan;
- vlan = vlan->next;
}
- if (!vlan)
- vlan = wildcard_vlan;
if (vlan)
iface = vlan->ifname;
}
sta->vlan_id);
ret = -1;
goto done;
- } else if (sta->vlan_id > 0 && vlan->vlan_id == VLAN_ID_WILDCARD) {
- vlan = vlan_add_dynamic(hapd, vlan, sta->vlan_id);
- if (vlan == NULL) {
- hostapd_logger(hapd, sta->addr,
- HOSTAPD_MODULE_IEEE80211,
- HOSTAPD_LEVEL_DEBUG, "could not add "
- "dynamic VLAN interface for vlan_id=%d",
- sta->vlan_id);
- ret = -1;
- goto done;
- }
-
- iface = vlan->ifname;
- if (vlan_setup_encryption_dyn(hapd, iface) != 0) {
- hostapd_logger(hapd, sta->addr,
- HOSTAPD_MODULE_IEEE80211,
- HOSTAPD_LEVEL_DEBUG, "could not "
- "configure encryption for dynamic VLAN "
- "interface for vlan_id=%d",
- sta->vlan_id);
- }
-
- hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
- HOSTAPD_LEVEL_DEBUG, "added new dynamic VLAN "
- "interface '%s'", iface);
- } else if (vlan && vlan->vlan_id == sta->vlan_id) {
- if (vlan->dynamic_vlan > 0) {
- vlan->dynamic_vlan++;
- hostapd_logger(hapd, sta->addr,
- HOSTAPD_MODULE_IEEE80211,
- HOSTAPD_LEVEL_DEBUG, "updated existing "
- "dynamic VLAN interface '%s'", iface);
- }
-
- /*
- * Update encryption configuration for statically generated
- * VLAN interface. This is only used for static WEP
- * configuration for the case where hostapd did not yet know
- * which keys are to be used when the interface was added.
- */
- if (vlan_setup_encryption_dyn(hapd, iface) != 0) {
- hostapd_logger(hapd, sta->addr,
- HOSTAPD_MODULE_IEEE80211,
- HOSTAPD_LEVEL_DEBUG, "could not "
- "configure encryption for VLAN "
- "interface for vlan_id=%d",
- sta->vlan_id);
- }
+ } else if (vlan && vlan->dynamic_vlan > 0) {
+ vlan->dynamic_vlan++;
+ hostapd_logger(hapd, sta->addr,
+ HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_DEBUG,
+ "updated existing dynamic VLAN interface '%s'",
+ iface);
}
/* ref counters have been increased, so mark the station */
unsigned int timeout, sec, usec;
u8 *trans_id, *nbuf;
+ wpa_printf(MSG_DEBUG, "%s: SA Query timer for STA " MACSTR
+ " (count=%d)",
+ hapd->conf->iface, MAC2STR(sta->addr), sta->sa_query_count);
+
if (sta->sa_query_count > 0 &&
ap_check_sa_query_timeout(hapd, sta))
return;
void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *addr, u16 reason)
{
+ if (sta)
+ wpa_printf(MSG_DEBUG, "%s: %s STA " MACSTR " reason=%u",
+ hapd->conf->iface, __func__, MAC2STR(sta->addr),
+ reason);
+ else if (addr)
+ wpa_printf(MSG_DEBUG, "%s: %s addr " MACSTR " reason=%u",
+ hapd->conf->iface, __func__, MAC2STR(addr),
+ reason);
if (sta == NULL && addr)
sta = ap_get_sta(hapd, addr);
wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
- wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout "
+ wpa_printf(MSG_DEBUG, "%s: %s: reschedule ap_handle_timer timeout "
"for " MACSTR " (%d seconds - "
"AP_MAX_INACTIVITY_AFTER_DEAUTH)",
- __func__, MAC2STR(sta->addr),
+ hapd->conf->iface, __func__, MAC2STR(sta->addr),
AP_MAX_INACTIVITY_AFTER_DEAUTH);
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0,
}
+void ap_sta_clear_disconnect_timeouts(struct hostapd_data *hapd,
+ struct sta_info *sta)
+{
+ if (eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta) > 0)
+ wpa_printf(MSG_DEBUG,
+ "%s: Removed ap_sta_deauth_cb_timeout timeout for "
+ MACSTR,
+ hapd->conf->iface, MAC2STR(sta->addr));
+ if (eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta) > 0)
+ wpa_printf(MSG_DEBUG,
+ "%s: Removed ap_sta_disassoc_cb_timeout timeout for "
+ MACSTR,
+ hapd->conf->iface, MAC2STR(sta->addr));
+}
+
+
int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen)
{
int res;
#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)
#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 */
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 */
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;
/* 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 */
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;
#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 */
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 */
};
* 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. */
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);
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);
--- /dev/null
+/*
+ * hostapd / Client taxonomy
+ * Copyright (c) 2015 Google, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ *
+ * Parse a series of IEs, as in Probe Request or (Re)Association Request frames,
+ * and render them to a descriptive string. The tag number of standard options
+ * is written to the string, while the vendor ID and subtag are written for
+ * vendor options.
+ *
+ * Example strings:
+ * 0,1,50,45,221(00904c,51)
+ * 0,1,33,36,48,45,221(00904c,51),221(0050f2,2)
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "common/wpa_ctrl.h"
+#include "hostapd.h"
+#include "sta_info.h"
+
+
+/* Copy a string with no funny schtuff allowed; only alphanumerics. */
+static void no_mischief_strncpy(char *dst, const char *src, size_t n)
+{
+ size_t i;
+
+ for (i = 0; i < n; i++) {
+ unsigned char s = src[i];
+ int is_lower = s >= 'a' && s <= 'z';
+ int is_upper = s >= 'A' && s <= 'Z';
+ int is_digit = s >= '0' && s <= '9';
+
+ if (is_lower || is_upper || is_digit) {
+ /* TODO: if any manufacturer uses Unicode within the
+ * WPS header, it will get mangled here. */
+ dst[i] = s;
+ } else {
+ /* Note that even spaces will be transformed to
+ * underscores, so 'Nexus 7' will turn into 'Nexus_7'.
+ * This is deliberate, to make the string easier to
+ * parse. */
+ dst[i] = '_';
+ }
+ }
+}
+
+
+static int get_wps_name(char *name, size_t name_len,
+ const u8 *data, size_t data_len)
+{
+ /* Inside the WPS IE are a series of attributes, using two byte IDs
+ * and two byte lengths. We're looking for the model name, if
+ * present. */
+ while (data_len >= 4) {
+ u16 id, elen;
+
+ id = WPA_GET_BE16(data);
+ elen = WPA_GET_BE16(data + 2);
+ data += 4;
+ data_len -= 4;
+
+ if (elen > data_len)
+ return 0;
+
+ if (id == 0x1023) {
+ /* Model name, like 'Nexus 7' */
+ size_t n = (elen < name_len) ? elen : name_len;
+ no_mischief_strncpy(name, (const char *) data, n);
+ return n;
+ }
+
+ data += elen;
+ data_len -= elen;
+ }
+
+ return 0;
+}
+
+
+static void ie_to_string(char *fstr, size_t fstr_len, const struct wpabuf *ies)
+{
+ char *fpos = fstr;
+ char *fend = fstr + fstr_len;
+ char htcap[7 + 4 + 1]; /* ",htcap:" + %04hx + trailing NUL */
+ char htagg[7 + 2 + 1]; /* ",htagg:" + %02hx + trailing NUL */
+ char htmcs[7 + 8 + 1]; /* ",htmcs:" + %08x + trailing NUL */
+ char vhtcap[8 + 8 + 1]; /* ",vhtcap:" + %08x + trailing NUL */
+ char vhtrxmcs[10 + 8 + 1]; /* ",vhtrxmcs:" + %08x + trailing NUL */
+ char vhttxmcs[10 + 8 + 1]; /* ",vhttxmcs:" + %08x + trailing NUL */
+#define MAX_EXTCAP 254
+ char extcap[8 + 2 * MAX_EXTCAP + 1]; /* ",extcap:" + hex + trailing NUL
+ */
+ char txpow[7 + 4 + 1]; /* ",txpow:" + %04hx + trailing NUL */
+#define WPS_NAME_LEN 32
+ char wps[WPS_NAME_LEN + 5 + 1]; /* room to prepend ",wps:" + trailing
+ * NUL */
+ int num = 0;
+ const u8 *ie;
+ size_t ie_len;
+ int ret;
+
+ os_memset(htcap, 0, sizeof(htcap));
+ os_memset(htagg, 0, sizeof(htagg));
+ os_memset(htmcs, 0, sizeof(htmcs));
+ os_memset(vhtcap, 0, sizeof(vhtcap));
+ os_memset(vhtrxmcs, 0, sizeof(vhtrxmcs));
+ os_memset(vhttxmcs, 0, sizeof(vhttxmcs));
+ os_memset(extcap, 0, sizeof(extcap));
+ os_memset(txpow, 0, sizeof(txpow));
+ os_memset(wps, 0, sizeof(wps));
+ *fpos = '\0';
+
+ if (!ies)
+ return;
+ ie = wpabuf_head(ies);
+ ie_len = wpabuf_len(ies);
+
+ while (ie_len >= 2) {
+ u8 id, elen;
+ char *sep = (num++ == 0) ? "" : ",";
+
+ id = *ie++;
+ elen = *ie++;
+ ie_len -= 2;
+
+ if (elen > ie_len)
+ break;
+
+ if (id == WLAN_EID_VENDOR_SPECIFIC && elen >= 4) {
+ /* Vendor specific */
+ if (WPA_GET_BE32(ie) == WPS_IE_VENDOR_TYPE) {
+ /* WPS */
+ char model_name[WPS_NAME_LEN + 1];
+ const u8 *data = &ie[4];
+ size_t data_len = elen - 4;
+
+ os_memset(model_name, 0, sizeof(model_name));
+ if (get_wps_name(model_name, WPS_NAME_LEN, data,
+ data_len)) {
+ os_snprintf(wps, sizeof(wps),
+ ",wps:%s", model_name);
+ }
+ }
+
+ ret = os_snprintf(fpos, fend - fpos,
+ "%s%d(%02x%02x%02x,%d)",
+ sep, id, ie[0], ie[1], ie[2], ie[3]);
+ } else {
+ if (id == WLAN_EID_HT_CAP && elen >= 2) {
+ /* HT Capabilities (802.11n) */
+ os_snprintf(htcap, sizeof(htcap),
+ ",htcap:%04hx",
+ WPA_GET_LE16(ie));
+ }
+ if (id == WLAN_EID_HT_CAP && elen >= 3) {
+ /* HT Capabilities (802.11n), A-MPDU information
+ */
+ os_snprintf(htagg, sizeof(htagg),
+ ",htagg:%02hx", (u16) ie[2]);
+ }
+ if (id == WLAN_EID_HT_CAP && elen >= 7) {
+ /* HT Capabilities (802.11n), MCS information */
+ os_snprintf(htmcs, sizeof(htmcs),
+ ",htmcs:%08hx",
+ (u16) WPA_GET_LE32(ie + 3));
+ }
+ if (id == WLAN_EID_VHT_CAP && elen >= 4) {
+ /* VHT Capabilities (802.11ac) */
+ os_snprintf(vhtcap, sizeof(vhtcap),
+ ",vhtcap:%08x",
+ WPA_GET_LE32(ie));
+ }
+ if (id == WLAN_EID_VHT_CAP && elen >= 8) {
+ /* VHT Capabilities (802.11ac), RX MCS
+ * information */
+ os_snprintf(vhtrxmcs, sizeof(vhtrxmcs),
+ ",vhtrxmcs:%08x",
+ WPA_GET_LE32(ie + 4));
+ }
+ if (id == WLAN_EID_VHT_CAP && elen >= 12) {
+ /* VHT Capabilities (802.11ac), TX MCS
+ * information */
+ os_snprintf(vhttxmcs, sizeof(vhttxmcs),
+ ",vhttxmcs:%08x",
+ WPA_GET_LE32(ie + 8));
+ }
+ if (id == WLAN_EID_EXT_CAPAB) {
+ /* Extended Capabilities */
+ int i;
+ int len = (elen < MAX_EXTCAP) ? elen :
+ MAX_EXTCAP;
+ char *p = extcap;
+
+ p += os_snprintf(extcap, sizeof(extcap),
+ ",extcap:");
+ for (i = 0; i < len; i++) {
+ int lim;
+
+ lim = sizeof(extcap) -
+ os_strlen(extcap);
+ if (lim <= 0)
+ break;
+ p += os_snprintf(p, lim, "%02x",
+ *(ie + i));
+ }
+ }
+ if (id == WLAN_EID_PWR_CAPABILITY && elen == 2) {
+ /* TX Power */
+ os_snprintf(txpow, sizeof(txpow),
+ ",txpow:%04hx",
+ WPA_GET_LE16(ie));
+ }
+
+ ret = os_snprintf(fpos, fend - fpos, "%s%d", sep, id);
+ }
+ if (os_snprintf_error(fend - fpos, ret))
+ goto fail;
+ fpos += ret;
+
+ ie += elen;
+ ie_len -= elen;
+ }
+
+ ret = os_snprintf(fpos, fend - fpos, "%s%s%s%s%s%s%s%s%s",
+ htcap, htagg, htmcs, vhtcap, vhtrxmcs, vhttxmcs,
+ txpow, extcap, wps);
+ if (os_snprintf_error(fend - fpos, ret)) {
+ fail:
+ fstr[0] = '\0';
+ }
+}
+
+
+int retrieve_sta_taxonomy(const struct hostapd_data *hapd,
+ struct sta_info *sta, char *buf, size_t buflen)
+{
+ int ret;
+ char *pos, *end;
+
+ if (!sta->probe_ie_taxonomy || !sta->assoc_ie_taxonomy)
+ return 0;
+
+ ret = os_snprintf(buf, buflen, "wifi4|probe:");
+ if (os_snprintf_error(buflen, ret))
+ return 0;
+ pos = buf + ret;
+ end = buf + buflen;
+
+ ie_to_string(pos, end - pos, sta->probe_ie_taxonomy);
+ pos = os_strchr(pos, '\0');
+ if (pos >= end)
+ return 0;
+ ret = os_snprintf(pos, end - pos, "|assoc:");
+ if (os_snprintf_error(end - pos, ret))
+ return 0;
+ pos += ret;
+ ie_to_string(pos, end - pos, sta->assoc_ie_taxonomy);
+ pos = os_strchr(pos, '\0');
+ return pos - buf;
+}
+
+
+void taxonomy_sta_info_probe_req(const struct hostapd_data *hapd,
+ struct sta_info *sta,
+ const u8 *ie, size_t ie_len)
+{
+ wpabuf_free(sta->probe_ie_taxonomy);
+ sta->probe_ie_taxonomy = wpabuf_alloc_copy(ie, ie_len);
+}
+
+
+void taxonomy_hostapd_sta_info_probe_req(const struct hostapd_data *hapd,
+ struct hostapd_sta_info *info,
+ const u8 *ie, size_t ie_len)
+{
+ wpabuf_free(info->probe_ie_taxonomy);
+ info->probe_ie_taxonomy = wpabuf_alloc_copy(ie, ie_len);
+}
+
+
+void taxonomy_sta_info_assoc_req(const struct hostapd_data *hapd,
+ struct sta_info *sta,
+ const u8 *ie, size_t ie_len)
+{
+ wpabuf_free(sta->assoc_ie_taxonomy);
+ sta->assoc_ie_taxonomy = wpabuf_alloc_copy(ie, ie_len);
+}
--- /dev/null
+/*
+ * hostapd / Station client taxonomy
+ * Copyright (c) 2015 Google, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef TAXONOMY_H
+#define TAXONOMY_H
+
+void taxonomy_sta_info_probe_req(const struct hostapd_data *hapd,
+ struct sta_info *sta,
+ const u8 *ie, size_t ie_len);
+void taxonomy_hostapd_sta_info_probe_req(const struct hostapd_data *hapd,
+ struct hostapd_sta_info *sta,
+ const u8 *ie, size_t ie_len);
+void taxonomy_sta_info_assoc_req(const struct hostapd_data *hapd,
+ struct sta_info *sta,
+ const u8 *ie, size_t ie_len);
+int retrieve_sta_taxonomy(const struct hostapd_data *hapd,
+ struct sta_info *sta, char *buf, size_t buflen);
+
+#endif /* TAXONOMY_H */
--- /dev/null
+/*
+ * hostapd / VLAN definition
+ * Copyright (c) 2016, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "ap/vlan.h"
+
+/* compare the two arguments, NULL is treated as empty
+ * return zero iff they are equal
+ */
+int vlan_compare(struct vlan_description *a, struct vlan_description *b)
+{
+ int i;
+ const int a_empty = !a || !a->notempty;
+ const int b_empty = !b || !b->notempty;
+
+ if (a_empty && b_empty)
+ return 0;
+ if (a_empty || b_empty)
+ return 1;
+ if (a->untagged != b->untagged)
+ return 1;
+ for (i = 0; i < MAX_NUM_TAGGED_VLAN; i++) {
+ if (a->tagged[i] != b->tagged[i])
+ return 1;
+ }
+ return 0;
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * hostapd / VLAN initialization - full dynamic VLAN
+ * Copyright 2003, Instant802 Networks, Inc.
+ * Copyright 2005-2006, Devicescape Software, Inc.
+ * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+#include <net/if.h>
+/* Avoid conflicts due to NetBSD net/if.h if_type define with driver.h */
+#undef if_type
+#include <sys/ioctl.h>
+
+#include "utils/common.h"
+#include "drivers/priv_netlink.h"
+#include "common/linux_bridge.h"
+#include "common/linux_vlan.h"
+#include "utils/eloop.h"
+#include "hostapd.h"
+#include "ap_config.h"
+#include "ap_drv_ops.h"
+#include "wpa_auth.h"
+#include "vlan_init.h"
+#include "vlan_util.h"
+
+
+struct full_dynamic_vlan {
+ int s; /* socket on which to listen for new/removed interfaces. */
+};
+
+#define DVLAN_CLEAN_BR 0x1
+#define DVLAN_CLEAN_VLAN 0x2
+#define DVLAN_CLEAN_VLAN_PORT 0x4
+
+struct dynamic_iface {
+ char ifname[IFNAMSIZ + 1];
+ int usage;
+ int clean;
+ struct dynamic_iface *next;
+};
+
+
+/* Increment ref counter for ifname and add clean flag.
+ * If not in list, add it only if some flags are given.
+ */
+static void dyn_iface_get(struct hostapd_data *hapd, const char *ifname,
+ int clean)
+{
+ struct dynamic_iface *next, **dynamic_ifaces;
+ struct hapd_interfaces *interfaces;
+
+ interfaces = hapd->iface->interfaces;
+ dynamic_ifaces = &interfaces->vlan_priv;
+
+ for (next = *dynamic_ifaces; next; next = next->next) {
+ if (os_strcmp(ifname, next->ifname) == 0)
+ break;
+ }
+
+ if (next) {
+ next->usage++;
+ next->clean |= clean;
+ return;
+ }
+
+ if (!clean)
+ return;
+
+ next = os_zalloc(sizeof(*next));
+ if (!next)
+ return;
+ os_strlcpy(next->ifname, ifname, sizeof(next->ifname));
+ next->usage = 1;
+ next->clean = clean;
+ next->next = *dynamic_ifaces;
+ *dynamic_ifaces = next;
+}
+
+
+/* Decrement reference counter for given ifname.
+ * Return clean flag iff reference counter was decreased to zero, else zero
+ */
+static int dyn_iface_put(struct hostapd_data *hapd, const char *ifname)
+{
+ struct dynamic_iface *next, *prev = NULL, **dynamic_ifaces;
+ struct hapd_interfaces *interfaces;
+ int clean;
+
+ interfaces = hapd->iface->interfaces;
+ dynamic_ifaces = &interfaces->vlan_priv;
+
+ for (next = *dynamic_ifaces; next; next = next->next) {
+ if (os_strcmp(ifname, next->ifname) == 0)
+ break;
+ prev = next;
+ }
+
+ if (!next)
+ return 0;
+
+ next->usage--;
+ if (next->usage)
+ return 0;
+
+ if (prev)
+ prev->next = next->next;
+ else
+ *dynamic_ifaces = next->next;
+ clean = next->clean;
+ os_free(next);
+
+ return clean;
+}
+
+
+static int ifconfig_down(const char *if_name)
+{
+ wpa_printf(MSG_DEBUG, "VLAN: Set interface %s down", if_name);
+ return ifconfig_helper(if_name, 0);
+}
+
+
+/* This value should be 256 ONLY. If it is something else, then hostapd
+ * might crash!, as this value has been hard-coded in 2.4.x kernel
+ * bridging code.
+ */
+#define MAX_BR_PORTS 256
+
+static int br_delif(const char *br_name, const char *if_name)
+{
+ int fd;
+ struct ifreq ifr;
+ unsigned long args[2];
+ int if_index;
+
+ wpa_printf(MSG_DEBUG, "VLAN: br_delif(%s, %s)", br_name, if_name);
+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
+ "failed: %s", __func__, strerror(errno));
+ return -1;
+ }
+
+ if_index = if_nametoindex(if_name);
+
+ if (if_index == 0) {
+ wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining "
+ "interface index for '%s'",
+ __func__, if_name);
+ close(fd);
+ return -1;
+ }
+
+ args[0] = BRCTL_DEL_IF;
+ args[1] = if_index;
+
+ os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
+ ifr.ifr_data = (void *) args;
+
+ if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0 && errno != EINVAL) {
+ /* No error if interface already removed. */
+ wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE,"
+ "BRCTL_DEL_IF] failed for br_name=%s if_name=%s: "
+ "%s", __func__, br_name, if_name, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+ return 0;
+}
+
+
+/*
+ Add interface 'if_name' to the bridge 'br_name'
+
+ returns -1 on error
+ returns 1 if the interface is already part of the bridge
+ returns 0 otherwise
+*/
+static int br_addif(const char *br_name, const char *if_name)
+{
+ int fd;
+ struct ifreq ifr;
+ unsigned long args[2];
+ int if_index;
+
+ wpa_printf(MSG_DEBUG, "VLAN: br_addif(%s, %s)", br_name, if_name);
+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
+ "failed: %s", __func__, strerror(errno));
+ return -1;
+ }
+
+ if_index = if_nametoindex(if_name);
+
+ if (if_index == 0) {
+ wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining "
+ "interface index for '%s'",
+ __func__, if_name);
+ close(fd);
+ return -1;
+ }
+
+ args[0] = BRCTL_ADD_IF;
+ args[1] = if_index;
+
+ os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
+ ifr.ifr_data = (void *) args;
+
+ if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
+ if (errno == EBUSY) {
+ /* The interface is already added. */
+ close(fd);
+ return 1;
+ }
+
+ wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE,"
+ "BRCTL_ADD_IF] failed for br_name=%s if_name=%s: "
+ "%s", __func__, br_name, if_name, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+ return 0;
+}
+
+
+static int br_delbr(const char *br_name)
+{
+ int fd;
+ unsigned long arg[2];
+
+ wpa_printf(MSG_DEBUG, "VLAN: br_delbr(%s)", br_name);
+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
+ "failed: %s", __func__, strerror(errno));
+ return -1;
+ }
+
+ arg[0] = BRCTL_DEL_BRIDGE;
+ arg[1] = (unsigned long) br_name;
+
+ if (ioctl(fd, SIOCGIFBR, arg) < 0 && errno != ENXIO) {
+ /* No error if bridge already removed. */
+ wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_DEL_BRIDGE failed for "
+ "%s: %s", __func__, br_name, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+ return 0;
+}
+
+
+/*
+ Add a bridge with the name 'br_name'.
+
+ returns -1 on error
+ returns 1 if the bridge already exists
+ returns 0 otherwise
+*/
+static int br_addbr(const char *br_name)
+{
+ int fd;
+ unsigned long arg[4];
+ struct ifreq ifr;
+
+ wpa_printf(MSG_DEBUG, "VLAN: br_addbr(%s)", br_name);
+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
+ "failed: %s", __func__, strerror(errno));
+ return -1;
+ }
+
+ arg[0] = BRCTL_ADD_BRIDGE;
+ arg[1] = (unsigned long) br_name;
+
+ if (ioctl(fd, SIOCGIFBR, arg) < 0) {
+ if (errno == EEXIST) {
+ /* The bridge is already added. */
+ close(fd);
+ return 1;
+ } else {
+ wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_ADD_BRIDGE "
+ "failed for %s: %s",
+ __func__, br_name, strerror(errno));
+ close(fd);
+ return -1;
+ }
+ }
+
+ /* Decrease forwarding delay to avoid EAPOL timeouts. */
+ os_memset(&ifr, 0, sizeof(ifr));
+ os_strlcpy(ifr.ifr_name, br_name, IFNAMSIZ);
+ arg[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
+ arg[1] = 1;
+ arg[2] = 0;
+ arg[3] = 0;
+ ifr.ifr_data = (char *) &arg;
+ if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
+ wpa_printf(MSG_ERROR, "VLAN: %s: "
+ "BRCTL_SET_BRIDGE_FORWARD_DELAY (1 sec) failed for "
+ "%s: %s", __func__, br_name, strerror(errno));
+ /* Continue anyway */
+ }
+
+ close(fd);
+ return 0;
+}
+
+
+static int br_getnumports(const char *br_name)
+{
+ int fd;
+ int i;
+ int port_cnt = 0;
+ unsigned long arg[4];
+ int ifindices[MAX_BR_PORTS];
+ struct ifreq ifr;
+
+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
+ "failed: %s", __func__, strerror(errno));
+ return -1;
+ }
+
+ arg[0] = BRCTL_GET_PORT_LIST;
+ arg[1] = (unsigned long) ifindices;
+ arg[2] = MAX_BR_PORTS;
+ arg[3] = 0;
+
+ os_memset(ifindices, 0, sizeof(ifindices));
+ os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
+ ifr.ifr_data = (void *) arg;
+
+ if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
+ wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_GET_PORT_LIST "
+ "failed for %s: %s",
+ __func__, br_name, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ for (i = 1; i < MAX_BR_PORTS; i++) {
+ if (ifindices[i] > 0) {
+ port_cnt++;
+ }
+ }
+
+ close(fd);
+ return port_cnt;
+}
+
+
+static void vlan_newlink_tagged(int vlan_naming, const char *tagged_interface,
+ const char *br_name, int vid,
+ struct hostapd_data *hapd)
+{
+ char vlan_ifname[IFNAMSIZ];
+ int clean;
+
+ if (vlan_naming == DYNAMIC_VLAN_NAMING_WITH_DEVICE)
+ os_snprintf(vlan_ifname, sizeof(vlan_ifname), "%s.%d",
+ tagged_interface, vid);
+ else
+ os_snprintf(vlan_ifname, sizeof(vlan_ifname), "vlan%d", vid);
+
+ clean = 0;
+ ifconfig_up(tagged_interface);
+ if (!vlan_add(tagged_interface, vid, vlan_ifname))
+ clean |= DVLAN_CLEAN_VLAN;
+
+ if (!br_addif(br_name, vlan_ifname))
+ clean |= DVLAN_CLEAN_VLAN_PORT;
+
+ dyn_iface_get(hapd, vlan_ifname, clean);
+
+ ifconfig_up(vlan_ifname);
+}
+
+
+static void vlan_bridge_name(char *br_name, struct hostapd_data *hapd, int vid)
+{
+ char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
+
+ if (hapd->conf->vlan_bridge[0]) {
+ os_snprintf(br_name, IFNAMSIZ, "%s%d",
+ hapd->conf->vlan_bridge, vid);
+ } else if (tagged_interface) {
+ os_snprintf(br_name, IFNAMSIZ, "br%s.%d",
+ tagged_interface, vid);
+ } else {
+ os_snprintf(br_name, IFNAMSIZ, "brvlan%d", vid);
+ }
+}
+
+
+static void vlan_get_bridge(const char *br_name, struct hostapd_data *hapd,
+ int vid)
+{
+ char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
+ int vlan_naming = hapd->conf->ssid.vlan_naming;
+
+ dyn_iface_get(hapd, br_name, br_addbr(br_name) ? 0 : DVLAN_CLEAN_BR);
+
+ ifconfig_up(br_name);
+
+ if (tagged_interface)
+ vlan_newlink_tagged(vlan_naming, tagged_interface, br_name,
+ vid, hapd);
+}
+
+
+void vlan_newlink(const char *ifname, struct hostapd_data *hapd)
+{
+ char br_name[IFNAMSIZ];
+ struct hostapd_vlan *vlan;
+ int untagged, *tagged, i, notempty;
+
+ wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname);
+
+ for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) {
+ if (vlan->configured ||
+ os_strcmp(ifname, vlan->ifname) != 0)
+ continue;
+ break;
+ }
+ if (!vlan)
+ return;
+
+ vlan->configured = 1;
+
+ notempty = vlan->vlan_desc.notempty;
+ untagged = vlan->vlan_desc.untagged;
+ tagged = vlan->vlan_desc.tagged;
+
+ if (!notempty) {
+ /* Non-VLAN STA */
+ if (hapd->conf->bridge[0] &&
+ !br_addif(hapd->conf->bridge, ifname))
+ vlan->clean |= DVLAN_CLEAN_WLAN_PORT;
+ } else if (untagged > 0 && untagged <= MAX_VLAN_ID) {
+ vlan_bridge_name(br_name, hapd, untagged);
+
+ vlan_get_bridge(br_name, hapd, untagged);
+
+ if (!br_addif(br_name, ifname))
+ vlan->clean |= DVLAN_CLEAN_WLAN_PORT;
+ }
+
+ for (i = 0; i < MAX_NUM_TAGGED_VLAN && tagged[i]; i++) {
+ if (tagged[i] == untagged ||
+ tagged[i] <= 0 || tagged[i] > MAX_VLAN_ID ||
+ (i > 0 && tagged[i] == tagged[i - 1]))
+ continue;
+ vlan_bridge_name(br_name, hapd, tagged[i]);
+ vlan_get_bridge(br_name, hapd, tagged[i]);
+ vlan_newlink_tagged(DYNAMIC_VLAN_NAMING_WITH_DEVICE,
+ ifname, br_name, tagged[i], hapd);
+ }
+
+ ifconfig_up(ifname);
+}
+
+
+static void vlan_dellink_tagged(int vlan_naming, const char *tagged_interface,
+ const char *br_name, int vid,
+ struct hostapd_data *hapd)
+{
+ char vlan_ifname[IFNAMSIZ];
+ int clean;
+
+ if (vlan_naming == DYNAMIC_VLAN_NAMING_WITH_DEVICE)
+ os_snprintf(vlan_ifname, sizeof(vlan_ifname), "%s.%d",
+ tagged_interface, vid);
+ else
+ os_snprintf(vlan_ifname, sizeof(vlan_ifname), "vlan%d", vid);
+
+ clean = dyn_iface_put(hapd, vlan_ifname);
+
+ if (clean & DVLAN_CLEAN_VLAN_PORT)
+ br_delif(br_name, vlan_ifname);
+
+ if (clean & DVLAN_CLEAN_VLAN) {
+ ifconfig_down(vlan_ifname);
+ vlan_rem(vlan_ifname);
+ }
+}
+
+
+static void vlan_put_bridge(const char *br_name, struct hostapd_data *hapd,
+ int vid)
+{
+ int clean;
+ char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
+ int vlan_naming = hapd->conf->ssid.vlan_naming;
+
+ if (tagged_interface)
+ vlan_dellink_tagged(vlan_naming, tagged_interface, br_name,
+ vid, hapd);
+
+ clean = dyn_iface_put(hapd, br_name);
+ if ((clean & DVLAN_CLEAN_BR) && br_getnumports(br_name) == 0) {
+ ifconfig_down(br_name);
+ br_delbr(br_name);
+ }
+}
+
+
+void vlan_dellink(const char *ifname, struct hostapd_data *hapd)
+{
+ struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan;
+
+ wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname);
+
+ first = prev = vlan;
+
+ while (vlan) {
+ if (os_strcmp(ifname, vlan->ifname) != 0) {
+ prev = vlan;
+ vlan = vlan->next;
+ continue;
+ }
+ break;
+ }
+ if (!vlan)
+ return;
+
+ if (vlan->configured) {
+ int notempty = vlan->vlan_desc.notempty;
+ int untagged = vlan->vlan_desc.untagged;
+ int *tagged = vlan->vlan_desc.tagged;
+ char br_name[IFNAMSIZ];
+ int i;
+
+ for (i = 0; i < MAX_NUM_TAGGED_VLAN && tagged[i]; i++) {
+ if (tagged[i] == untagged ||
+ tagged[i] <= 0 || tagged[i] > MAX_VLAN_ID ||
+ (i > 0 && tagged[i] == tagged[i - 1]))
+ continue;
+ vlan_bridge_name(br_name, hapd, tagged[i]);
+ vlan_dellink_tagged(DYNAMIC_VLAN_NAMING_WITH_DEVICE,
+ ifname, br_name, tagged[i], hapd);
+ vlan_put_bridge(br_name, hapd, tagged[i]);
+ }
+
+ if (!notempty) {
+ /* Non-VLAN STA */
+ if (hapd->conf->bridge[0] &&
+ (vlan->clean & DVLAN_CLEAN_WLAN_PORT))
+ br_delif(hapd->conf->bridge, ifname);
+ } else if (untagged > 0 && untagged <= MAX_VLAN_ID) {
+ vlan_bridge_name(br_name, hapd, untagged);
+
+ if (vlan->clean & DVLAN_CLEAN_WLAN_PORT)
+ br_delif(br_name, vlan->ifname);
+
+ vlan_put_bridge(br_name, hapd, untagged);
+ }
+ }
+
+ /*
+ * Ensure this VLAN interface is actually removed even if
+ * NEWLINK message is only received later.
+ */
+ if (if_nametoindex(vlan->ifname) && vlan_if_remove(hapd, vlan))
+ wpa_printf(MSG_ERROR,
+ "VLAN: Could not remove VLAN iface: %s: %s",
+ vlan->ifname, strerror(errno));
+
+ if (vlan == first)
+ hapd->conf->vlan = vlan->next;
+ else
+ prev->next = vlan->next;
+
+ os_free(vlan);
+}
+
+
+static void
+vlan_read_ifnames(struct nlmsghdr *h, size_t len, int del,
+ struct hostapd_data *hapd)
+{
+ struct ifinfomsg *ifi;
+ int attrlen, nlmsg_len, rta_len;
+ struct rtattr *attr;
+ char ifname[IFNAMSIZ + 1];
+
+ if (len < sizeof(*ifi))
+ return;
+
+ ifi = NLMSG_DATA(h);
+
+ nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
+
+ attrlen = h->nlmsg_len - nlmsg_len;
+ if (attrlen < 0)
+ return;
+
+ attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
+
+ os_memset(ifname, 0, sizeof(ifname));
+ rta_len = RTA_ALIGN(sizeof(struct rtattr));
+ while (RTA_OK(attr, attrlen)) {
+ if (attr->rta_type == IFLA_IFNAME) {
+ int n = attr->rta_len - rta_len;
+ if (n < 0)
+ break;
+
+ if ((size_t) n >= sizeof(ifname))
+ n = sizeof(ifname) - 1;
+ os_memcpy(ifname, ((char *) attr) + rta_len, n);
+
+ }
+
+ attr = RTA_NEXT(attr, attrlen);
+ }
+
+ if (!ifname[0])
+ return;
+ if (del && if_nametoindex(ifname)) {
+ /* interface still exists, race condition ->
+ * iface has just been recreated */
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "VLAN: RTM_%sLINK: ifi_index=%d ifname=%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)",
+ del ? "DEL" : "NEW",
+ ifi->ifi_index, ifname, ifi->ifi_family, ifi->ifi_flags,
+ (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
+ (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
+ (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
+ (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
+
+ if (del)
+ vlan_dellink(ifname, hapd);
+ else
+ vlan_newlink(ifname, hapd);
+}
+
+
+static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx)
+{
+ char buf[8192];
+ int left;
+ struct sockaddr_nl from;
+ socklen_t fromlen;
+ struct nlmsghdr *h;
+ struct hostapd_data *hapd = eloop_ctx;
+
+ fromlen = sizeof(from);
+ left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
+ (struct sockaddr *) &from, &fromlen);
+ if (left < 0) {
+ if (errno != EINTR && errno != EAGAIN)
+ wpa_printf(MSG_ERROR, "VLAN: %s: recvfrom failed: %s",
+ __func__, strerror(errno));
+ return;
+ }
+
+ h = (struct nlmsghdr *) buf;
+ while (NLMSG_OK(h, left)) {
+ int len, plen;
+
+ len = h->nlmsg_len;
+ plen = len - sizeof(*h);
+ if (len > left || plen < 0) {
+ wpa_printf(MSG_DEBUG, "VLAN: Malformed netlink "
+ "message: len=%d left=%d plen=%d",
+ len, left, plen);
+ break;
+ }
+
+ switch (h->nlmsg_type) {
+ case RTM_NEWLINK:
+ vlan_read_ifnames(h, plen, 0, hapd);
+ break;
+ case RTM_DELLINK:
+ vlan_read_ifnames(h, plen, 1, hapd);
+ break;
+ }
+
+ h = NLMSG_NEXT(h, left);
+ }
+
+ if (left > 0) {
+ wpa_printf(MSG_DEBUG, "VLAN: %s: %d extra bytes in the end of "
+ "netlink message", __func__, left);
+ }
+}
+
+
+struct full_dynamic_vlan *
+full_dynamic_vlan_init(struct hostapd_data *hapd)
+{
+ struct sockaddr_nl local;
+ struct full_dynamic_vlan *priv;
+
+ priv = os_zalloc(sizeof(*priv));
+ if (priv == NULL)
+ return NULL;
+
+ vlan_set_name_type(hapd->conf->ssid.vlan_naming ==
+ DYNAMIC_VLAN_NAMING_WITH_DEVICE ?
+ VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD :
+ VLAN_NAME_TYPE_PLUS_VID_NO_PAD);
+
+ priv->s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (priv->s < 0) {
+ wpa_printf(MSG_ERROR, "VLAN: %s: socket(PF_NETLINK,SOCK_RAW,"
+ "NETLINK_ROUTE) failed: %s",
+ __func__, strerror(errno));
+ os_free(priv);
+ return NULL;
+ }
+
+ os_memset(&local, 0, sizeof(local));
+ local.nl_family = AF_NETLINK;
+ local.nl_groups = RTMGRP_LINK;
+ if (bind(priv->s, (struct sockaddr *) &local, sizeof(local)) < 0) {
+ wpa_printf(MSG_ERROR, "VLAN: %s: bind(netlink) failed: %s",
+ __func__, strerror(errno));
+ close(priv->s);
+ os_free(priv);
+ return NULL;
+ }
+
+ if (eloop_register_read_sock(priv->s, vlan_event_receive, hapd, NULL))
+ {
+ close(priv->s);
+ os_free(priv);
+ return NULL;
+ }
+
+ return priv;
+}
+
+
+void full_dynamic_vlan_deinit(struct full_dynamic_vlan *priv)
+{
+ if (priv == NULL)
+ return;
+ eloop_unregister_read_sock(priv->s);
+ close(priv->s);
+ os_free(priv);
+}
--- /dev/null
+/*
+ * hostapd / VLAN ifconfig helpers
+ * Copyright 2003, Instant802 Networks, Inc.
+ * Copyright 2005-2006, Devicescape Software, Inc.
+ * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+#include <net/if.h>
+#include <sys/ioctl.h>
+
+#include "utils/common.h"
+#include "vlan_util.h"
+
+
+int ifconfig_helper(const char *if_name, int up)
+{
+ int fd;
+ struct ifreq ifr;
+
+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
+ "failed: %s", __func__, strerror(errno));
+ return -1;
+ }
+
+ os_memset(&ifr, 0, sizeof(ifr));
+ os_strlcpy(ifr.ifr_name, if_name, IFNAMSIZ);
+
+ if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0) {
+ wpa_printf(MSG_ERROR, "VLAN: %s: ioctl(SIOCGIFFLAGS) failed "
+ "for interface %s: %s",
+ __func__, if_name, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ if (up)
+ ifr.ifr_flags |= IFF_UP;
+ else
+ ifr.ifr_flags &= ~IFF_UP;
+
+ if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0) {
+ wpa_printf(MSG_ERROR, "VLAN: %s: ioctl(SIOCSIFFLAGS) failed "
+ "for interface %s (up=%d): %s",
+ __func__, if_name, up, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+ return 0;
+}
+
+
+int ifconfig_up(const char *if_name)
+{
+ wpa_printf(MSG_DEBUG, "VLAN: Set interface %s up", if_name);
+ return ifconfig_helper(if_name, 1);
+}
+
+
+int iface_exists(const char *ifname)
+{
+ return if_nametoindex(ifname);
+}
*/
#include "utils/includes.h"
-#ifdef CONFIG_FULL_DYNAMIC_VLAN
-#include <net/if.h>
-#include <sys/ioctl.h>
-#include <linux/sockios.h>
-#include <linux/if_vlan.h>
-#include <linux/if_bridge.h>
-#endif /* CONFIG_FULL_DYNAMIC_VLAN */
#include "utils/common.h"
#include "hostapd.h"
#include "ap_config.h"
#include "ap_drv_ops.h"
+#include "wpa_auth.h"
#include "vlan_init.h"
#include "vlan_util.h"
-#ifdef CONFIG_FULL_DYNAMIC_VLAN
-
-#include "drivers/priv_netlink.h"
-#include "utils/eloop.h"
-
-
-struct full_dynamic_vlan {
- int s; /* socket on which to listen for new/removed interfaces. */
-};
-
-#define DVLAN_CLEAN_BR 0x1
-#define DVLAN_CLEAN_VLAN 0x2
-#define DVLAN_CLEAN_VLAN_PORT 0x4
-
-struct dynamic_iface {
- char ifname[IFNAMSIZ + 1];
- int usage;
- int clean;
- struct dynamic_iface *next;
-};
-
-
-/* Increment ref counter for ifname and add clean flag.
- * If not in list, add it only if some flags are given.
- */
-static void dyn_iface_get(struct hostapd_data *hapd, const char *ifname,
- int clean)
-{
- struct dynamic_iface *next, **dynamic_ifaces;
- struct hapd_interfaces *interfaces;
-
- interfaces = hapd->iface->interfaces;
- dynamic_ifaces = &interfaces->vlan_priv;
-
- for (next = *dynamic_ifaces; next; next = next->next) {
- if (os_strcmp(ifname, next->ifname) == 0)
- break;
- }
-
- if (next) {
- next->usage++;
- next->clean |= clean;
- return;
- }
-
- if (!clean)
- return;
-
- next = os_zalloc(sizeof(*next));
- if (!next)
- return;
- os_strlcpy(next->ifname, ifname, sizeof(next->ifname));
- next->usage = 1;
- next->clean = clean;
- next->next = *dynamic_ifaces;
- *dynamic_ifaces = next;
-}
-
-
-/* Decrement reference counter for given ifname.
- * Return clean flag iff reference counter was decreased to zero, else zero
- */
-static int dyn_iface_put(struct hostapd_data *hapd, const char *ifname)
-{
- struct dynamic_iface *next, *prev = NULL, **dynamic_ifaces;
- struct hapd_interfaces *interfaces;
- int clean;
-
- interfaces = hapd->iface->interfaces;
- dynamic_ifaces = &interfaces->vlan_priv;
-
- for (next = *dynamic_ifaces; next; next = next->next) {
- if (os_strcmp(ifname, next->ifname) == 0)
- break;
- prev = next;
- }
-
- if (!next)
- return 0;
-
- next->usage--;
- if (next->usage)
- return 0;
-
- if (prev)
- prev->next = next->next;
- else
- *dynamic_ifaces = next->next;
- clean = next->clean;
- os_free(next);
-
- return clean;
-}
-
-
-static int ifconfig_helper(const char *if_name, int up)
-{
- int fd;
- struct ifreq ifr;
-
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
- "failed: %s", __func__, strerror(errno));
- return -1;
- }
-
- os_memset(&ifr, 0, sizeof(ifr));
- os_strlcpy(ifr.ifr_name, if_name, IFNAMSIZ);
-
- if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: ioctl(SIOCGIFFLAGS) failed "
- "for interface %s: %s",
- __func__, if_name, strerror(errno));
- close(fd);
- return -1;
- }
-
- if (up)
- ifr.ifr_flags |= IFF_UP;
- else
- ifr.ifr_flags &= ~IFF_UP;
-
- if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: ioctl(SIOCSIFFLAGS) failed "
- "for interface %s (up=%d): %s",
- __func__, if_name, up, strerror(errno));
- close(fd);
- return -1;
- }
-
- close(fd);
- return 0;
-}
-
-
-static int ifconfig_up(const char *if_name)
-{
- wpa_printf(MSG_DEBUG, "VLAN: Set interface %s up", if_name);
- return ifconfig_helper(if_name, 1);
-}
-
-
-static int ifconfig_down(const char *if_name)
-{
- wpa_printf(MSG_DEBUG, "VLAN: Set interface %s down", if_name);
- return ifconfig_helper(if_name, 0);
-}
-
-
-/*
- * These are only available in recent linux headers (without the leading
- * underscore).
- */
-#define _GET_VLAN_REALDEV_NAME_CMD 8
-#define _GET_VLAN_VID_CMD 9
-
-/* This value should be 256 ONLY. If it is something else, then hostapd
- * might crash!, as this value has been hard-coded in 2.4.x kernel
- * bridging code.
- */
-#define MAX_BR_PORTS 256
-
-static int br_delif(const char *br_name, const char *if_name)
-{
- int fd;
- struct ifreq ifr;
- unsigned long args[2];
- int if_index;
-
- wpa_printf(MSG_DEBUG, "VLAN: br_delif(%s, %s)", br_name, if_name);
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
- "failed: %s", __func__, strerror(errno));
- return -1;
- }
-
- if_index = if_nametoindex(if_name);
-
- if (if_index == 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining "
- "interface index for '%s'",
- __func__, if_name);
- close(fd);
- return -1;
- }
-
- args[0] = BRCTL_DEL_IF;
- args[1] = if_index;
-
- os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
- ifr.ifr_data = (__caddr_t) args;
-
- if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0 && errno != EINVAL) {
- /* No error if interface already removed. */
- wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE,"
- "BRCTL_DEL_IF] failed for br_name=%s if_name=%s: "
- "%s", __func__, br_name, if_name, strerror(errno));
- close(fd);
- return -1;
- }
-
- close(fd);
- return 0;
-}
-
-
-/*
- Add interface 'if_name' to the bridge 'br_name'
-
- returns -1 on error
- returns 1 if the interface is already part of the bridge
- returns 0 otherwise
-*/
-static int br_addif(const char *br_name, const char *if_name)
-{
- int fd;
- struct ifreq ifr;
- unsigned long args[2];
- int if_index;
-
- wpa_printf(MSG_DEBUG, "VLAN: br_addif(%s, %s)", br_name, if_name);
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
- "failed: %s", __func__, strerror(errno));
- return -1;
- }
-
- if_index = if_nametoindex(if_name);
-
- if (if_index == 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining "
- "interface index for '%s'",
- __func__, if_name);
- close(fd);
- return -1;
- }
-
- args[0] = BRCTL_ADD_IF;
- args[1] = if_index;
-
- os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
- ifr.ifr_data = (__caddr_t) args;
-
- if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
- if (errno == EBUSY) {
- /* The interface is already added. */
- close(fd);
- return 1;
- }
-
- wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE,"
- "BRCTL_ADD_IF] failed for br_name=%s if_name=%s: "
- "%s", __func__, br_name, if_name, strerror(errno));
- close(fd);
- return -1;
- }
-
- close(fd);
- return 0;
-}
-
-
-static int br_delbr(const char *br_name)
-{
- int fd;
- unsigned long arg[2];
-
- wpa_printf(MSG_DEBUG, "VLAN: br_delbr(%s)", br_name);
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
- "failed: %s", __func__, strerror(errno));
- return -1;
- }
-
- arg[0] = BRCTL_DEL_BRIDGE;
- arg[1] = (unsigned long) br_name;
-
- if (ioctl(fd, SIOCGIFBR, arg) < 0 && errno != ENXIO) {
- /* No error if bridge already removed. */
- wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_DEL_BRIDGE failed for "
- "%s: %s", __func__, br_name, strerror(errno));
- close(fd);
- return -1;
- }
-
- close(fd);
- return 0;
-}
-
-
-/*
- Add a bridge with the name 'br_name'.
-
- returns -1 on error
- returns 1 if the bridge already exists
- returns 0 otherwise
-*/
-static int br_addbr(const char *br_name)
-{
- int fd;
- unsigned long arg[4];
- struct ifreq ifr;
-
- wpa_printf(MSG_DEBUG, "VLAN: br_addbr(%s)", br_name);
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
- "failed: %s", __func__, strerror(errno));
- return -1;
- }
-
- arg[0] = BRCTL_ADD_BRIDGE;
- arg[1] = (unsigned long) br_name;
-
- if (ioctl(fd, SIOCGIFBR, arg) < 0) {
- if (errno == EEXIST) {
- /* The bridge is already added. */
- close(fd);
- return 1;
- } else {
- wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_ADD_BRIDGE "
- "failed for %s: %s",
- __func__, br_name, strerror(errno));
- close(fd);
- return -1;
- }
- }
-
- /* Decrease forwarding delay to avoid EAPOL timeouts. */
- os_memset(&ifr, 0, sizeof(ifr));
- os_strlcpy(ifr.ifr_name, br_name, IFNAMSIZ);
- arg[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
- arg[1] = 1;
- arg[2] = 0;
- arg[3] = 0;
- ifr.ifr_data = (char *) &arg;
- if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: "
- "BRCTL_SET_BRIDGE_FORWARD_DELAY (1 sec) failed for "
- "%s: %s", __func__, br_name, strerror(errno));
- /* Continue anyway */
- }
-
- close(fd);
- return 0;
-}
-
-
-static int br_getnumports(const char *br_name)
-{
- int fd;
- int i;
- int port_cnt = 0;
- unsigned long arg[4];
- int ifindices[MAX_BR_PORTS];
- struct ifreq ifr;
-
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
- "failed: %s", __func__, strerror(errno));
- return -1;
- }
-
- arg[0] = BRCTL_GET_PORT_LIST;
- arg[1] = (unsigned long) ifindices;
- arg[2] = MAX_BR_PORTS;
- arg[3] = 0;
-
- os_memset(ifindices, 0, sizeof(ifindices));
- os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
- ifr.ifr_data = (__caddr_t) arg;
-
- if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_GET_PORT_LIST "
- "failed for %s: %s",
- __func__, br_name, strerror(errno));
- close(fd);
- return -1;
- }
-
- for (i = 1; i < MAX_BR_PORTS; i++) {
- if (ifindices[i] > 0) {
- port_cnt++;
- }
- }
-
- close(fd);
- return port_cnt;
-}
-
-
-#ifndef CONFIG_VLAN_NETLINK
-
-int vlan_rem(const char *if_name)
-{
- int fd;
- struct vlan_ioctl_args if_request;
-
- wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(%s)", if_name);
- if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
- wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
- if_name);
- return -1;
- }
-
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
- "failed: %s", __func__, strerror(errno));
- return -1;
- }
-
- os_memset(&if_request, 0, sizeof(if_request));
-
- os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
- if_request.cmd = DEL_VLAN_CMD;
-
- if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: DEL_VLAN_CMD failed for %s: "
- "%s", __func__, if_name, strerror(errno));
- close(fd);
- return -1;
- }
-
- close(fd);
- return 0;
-}
-
-
-/*
- Add a vlan interface with VLAN ID 'vid' and tagged interface
- 'if_name'.
-
- returns -1 on error
- returns 1 if the interface already exists
- returns 0 otherwise
-*/
-int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
-{
- int fd;
- struct vlan_ioctl_args if_request;
-
- wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d)",
- if_name, vid);
- ifconfig_up(if_name);
-
- if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
- wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
- if_name);
- return -1;
- }
-
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
- "failed: %s", __func__, strerror(errno));
- return -1;
- }
-
- os_memset(&if_request, 0, sizeof(if_request));
-
- /* Determine if a suitable vlan device already exists. */
-
- os_snprintf(if_request.device1, sizeof(if_request.device1), "vlan%d",
- vid);
-
- if_request.cmd = _GET_VLAN_VID_CMD;
-
- if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0) {
-
- if (if_request.u.VID == vid) {
- if_request.cmd = _GET_VLAN_REALDEV_NAME_CMD;
-
- if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0 &&
- os_strncmp(if_request.u.device2, if_name,
- sizeof(if_request.u.device2)) == 0) {
- close(fd);
- wpa_printf(MSG_DEBUG, "VLAN: vlan_add: "
- "if_name %s exists already",
- if_request.device1);
- return 1;
- }
- }
- }
-
- /* A suitable vlan device does not already exist, add one. */
-
- os_memset(&if_request, 0, sizeof(if_request));
- os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
- if_request.u.VID = vid;
- if_request.cmd = ADD_VLAN_CMD;
-
- if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: ADD_VLAN_CMD failed for %s: "
- "%s",
- __func__, if_request.device1, strerror(errno));
- close(fd);
- return -1;
- }
-
- close(fd);
- return 0;
-}
-
-
-static int vlan_set_name_type(unsigned int name_type)
+static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
+ int existsok)
{
- int fd;
- struct vlan_ioctl_args if_request;
+ int ret, i;
- wpa_printf(MSG_DEBUG, "VLAN: vlan_set_name_type(name_type=%u)",
- name_type);
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
- "failed: %s", __func__, strerror(errno));
+ for (i = 0; i < NUM_WEP_KEYS; i++) {
+ if (!hapd->conf->ssid.wep.key[i])
+ continue;
+ wpa_printf(MSG_ERROR,
+ "VLAN: Refusing to set up VLAN iface %s with WEP",
+ vlan->ifname);
return -1;
}
- os_memset(&if_request, 0, sizeof(if_request));
-
- if_request.u.name_type = name_type;
- if_request.cmd = SET_VLAN_NAME_TYPE_CMD;
- if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: SET_VLAN_NAME_TYPE_CMD "
- "name_type=%u failed: %s",
- __func__, name_type, strerror(errno));
- close(fd);
+ if (!iface_exists(vlan->ifname))
+ ret = hostapd_vlan_if_add(hapd, vlan->ifname);
+ else if (!existsok)
return -1;
- }
-
- close(fd);
- return 0;
-}
-
-#endif /* CONFIG_VLAN_NETLINK */
-
-
-static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
-{
- char vlan_ifname[IFNAMSIZ];
- char br_name[IFNAMSIZ];
- struct hostapd_vlan *vlan = hapd->conf->vlan;
- char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
- int vlan_naming = hapd->conf->ssid.vlan_naming;
- int clean;
-
- wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname);
-
- while (vlan) {
- if (os_strcmp(ifname, vlan->ifname) == 0 && !vlan->configured) {
- vlan->configured = 1;
-
- if (hapd->conf->vlan_bridge[0]) {
- os_snprintf(br_name, sizeof(br_name), "%s%d",
- hapd->conf->vlan_bridge,
- vlan->vlan_id);
- } else if (tagged_interface) {
- os_snprintf(br_name, sizeof(br_name),
- "br%s.%d", tagged_interface,
- vlan->vlan_id);
- } else {
- os_snprintf(br_name, sizeof(br_name),
- "brvlan%d", vlan->vlan_id);
- }
-
- dyn_iface_get(hapd, br_name,
- br_addbr(br_name) ? 0 : DVLAN_CLEAN_BR);
-
- ifconfig_up(br_name);
-
- if (tagged_interface) {
- if (vlan_naming ==
- DYNAMIC_VLAN_NAMING_WITH_DEVICE)
- os_snprintf(vlan_ifname,
- sizeof(vlan_ifname),
- "%s.%d", tagged_interface,
- vlan->vlan_id);
- else
- os_snprintf(vlan_ifname,
- sizeof(vlan_ifname),
- "vlan%d", vlan->vlan_id);
-
- clean = 0;
- ifconfig_up(tagged_interface);
- if (!vlan_add(tagged_interface, vlan->vlan_id,
- vlan_ifname))
- clean |= DVLAN_CLEAN_VLAN;
-
- if (!br_addif(br_name, vlan_ifname))
- clean |= DVLAN_CLEAN_VLAN_PORT;
-
- dyn_iface_get(hapd, vlan_ifname, clean);
-
- ifconfig_up(vlan_ifname);
- }
-
- if (!br_addif(br_name, ifname))
- vlan->clean |= DVLAN_CLEAN_WLAN_PORT;
-
- ifconfig_up(ifname);
-
- break;
- }
- vlan = vlan->next;
- }
-}
-
-
-static void vlan_dellink(char *ifname, struct hostapd_data *hapd)
-{
- char vlan_ifname[IFNAMSIZ];
- char br_name[IFNAMSIZ];
- struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan;
- char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
- int vlan_naming = hapd->conf->ssid.vlan_naming;
- int clean;
-
- wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname);
-
- first = prev = vlan;
-
- while (vlan) {
- if (os_strcmp(ifname, vlan->ifname) == 0 &&
- vlan->configured) {
- if (hapd->conf->vlan_bridge[0]) {
- os_snprintf(br_name, sizeof(br_name), "%s%d",
- hapd->conf->vlan_bridge,
- vlan->vlan_id);
- } else if (tagged_interface) {
- os_snprintf(br_name, sizeof(br_name),
- "br%s.%d", tagged_interface,
- vlan->vlan_id);
- } else {
- os_snprintf(br_name, sizeof(br_name),
- "brvlan%d", vlan->vlan_id);
- }
-
- if (vlan->clean & DVLAN_CLEAN_WLAN_PORT)
- br_delif(br_name, vlan->ifname);
-
- if (tagged_interface) {
- if (vlan_naming ==
- DYNAMIC_VLAN_NAMING_WITH_DEVICE)
- os_snprintf(vlan_ifname,
- sizeof(vlan_ifname),
- "%s.%d", tagged_interface,
- vlan->vlan_id);
- else
- os_snprintf(vlan_ifname,
- sizeof(vlan_ifname),
- "vlan%d", vlan->vlan_id);
-
- clean = dyn_iface_put(hapd, vlan_ifname);
-
- if (clean & DVLAN_CLEAN_VLAN_PORT)
- br_delif(br_name, vlan_ifname);
-
- if (clean & DVLAN_CLEAN_VLAN) {
- ifconfig_down(vlan_ifname);
- vlan_rem(vlan_ifname);
- }
- }
-
- clean = dyn_iface_put(hapd, br_name);
- if ((clean & DVLAN_CLEAN_BR) &&
- br_getnumports(br_name) == 0) {
- ifconfig_down(br_name);
- br_delbr(br_name);
- }
- }
-
- if (os_strcmp(ifname, vlan->ifname) == 0) {
- if (vlan == first) {
- hapd->conf->vlan = vlan->next;
- } else {
- prev->next = vlan->next;
- }
- os_free(vlan);
-
- break;
- }
- prev = vlan;
- vlan = vlan->next;
- }
-}
-
-
-static void
-vlan_read_ifnames(struct nlmsghdr *h, size_t len, int del,
- struct hostapd_data *hapd)
-{
- struct ifinfomsg *ifi;
- int attrlen, nlmsg_len, rta_len;
- struct rtattr *attr;
- char ifname[IFNAMSIZ + 1];
-
- if (len < sizeof(*ifi))
- return;
-
- ifi = NLMSG_DATA(h);
-
- nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
-
- attrlen = h->nlmsg_len - nlmsg_len;
- if (attrlen < 0)
- return;
-
- attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
-
- os_memset(ifname, 0, sizeof(ifname));
- rta_len = RTA_ALIGN(sizeof(struct rtattr));
- while (RTA_OK(attr, attrlen)) {
- if (attr->rta_type == IFLA_IFNAME) {
- int n = attr->rta_len - rta_len;
- if (n < 0)
- break;
-
- if ((size_t) n >= sizeof(ifname))
- n = sizeof(ifname) - 1;
- os_memcpy(ifname, ((char *) attr) + rta_len, n);
-
- }
-
- attr = RTA_NEXT(attr, attrlen);
- }
-
- if (!ifname[0])
- return;
- if (del && if_nametoindex(ifname)) {
- /* interface still exists, race condition ->
- * iface has just been recreated */
- return;
- }
-
- wpa_printf(MSG_DEBUG,
- "VLAN: RTM_%sLINK: ifi_index=%d ifname=%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)",
- del ? "DEL" : "NEW",
- ifi->ifi_index, ifname, ifi->ifi_family, ifi->ifi_flags,
- (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
- (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
- (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
- (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
-
- if (del)
- vlan_dellink(ifname, hapd);
else
- vlan_newlink(ifname, hapd);
-}
-
-
-static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx)
-{
- char buf[8192];
- int left;
- struct sockaddr_nl from;
- socklen_t fromlen;
- struct nlmsghdr *h;
- struct hostapd_data *hapd = eloop_ctx;
-
- fromlen = sizeof(from);
- left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
- (struct sockaddr *) &from, &fromlen);
- if (left < 0) {
- if (errno != EINTR && errno != EAGAIN)
- wpa_printf(MSG_ERROR, "VLAN: %s: recvfrom failed: %s",
- __func__, strerror(errno));
- return;
- }
-
- h = (struct nlmsghdr *) buf;
- while (NLMSG_OK(h, left)) {
- int len, plen;
-
- len = h->nlmsg_len;
- plen = len - sizeof(*h);
- if (len > left || plen < 0) {
- wpa_printf(MSG_DEBUG, "VLAN: Malformed netlink "
- "message: len=%d left=%d plen=%d",
- len, left, plen);
- break;
- }
-
- switch (h->nlmsg_type) {
- case RTM_NEWLINK:
- vlan_read_ifnames(h, plen, 0, hapd);
- break;
- case RTM_DELLINK:
- vlan_read_ifnames(h, plen, 1, hapd);
- break;
- }
+ ret = 0;
- h = NLMSG_NEXT(h, left);
- }
+ if (ret)
+ return ret;
- if (left > 0) {
- wpa_printf(MSG_DEBUG, "VLAN: %s: %d extra bytes in the end of "
- "netlink message", __func__, left);
- }
-}
+ ifconfig_up(vlan->ifname); /* else wpa group will fail fatal */
+ if (hapd->wpa_auth)
+ ret = wpa_auth_ensure_group(hapd->wpa_auth, vlan->vlan_id);
-static struct full_dynamic_vlan *
-full_dynamic_vlan_init(struct hostapd_data *hapd)
-{
- struct sockaddr_nl local;
- struct full_dynamic_vlan *priv;
+ if (ret == 0)
+ return ret;
- priv = os_zalloc(sizeof(*priv));
- if (priv == NULL)
- return NULL;
+ wpa_printf(MSG_ERROR, "WPA initialization for VLAN %d failed (%d)",
+ vlan->vlan_id, ret);
+ if (wpa_auth_release_group(hapd->wpa_auth, vlan->vlan_id))
+ wpa_printf(MSG_ERROR, "WPA deinit of %s failed", vlan->ifname);
-#ifndef CONFIG_VLAN_NETLINK
- vlan_set_name_type(hapd->conf->ssid.vlan_naming ==
- DYNAMIC_VLAN_NAMING_WITH_DEVICE ?
- VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD :
- VLAN_NAME_TYPE_PLUS_VID_NO_PAD);
-#endif /* CONFIG_VLAN_NETLINK */
+ /* group state machine setup failed */
+ if (hostapd_vlan_if_remove(hapd, vlan->ifname))
+ wpa_printf(MSG_ERROR, "Removal of %s failed", vlan->ifname);
- priv->s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (priv->s < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: socket(PF_NETLINK,SOCK_RAW,"
- "NETLINK_ROUTE) failed: %s",
- __func__, strerror(errno));
- os_free(priv);
- return NULL;
- }
-
- os_memset(&local, 0, sizeof(local));
- local.nl_family = AF_NETLINK;
- local.nl_groups = RTMGRP_LINK;
- if (bind(priv->s, (struct sockaddr *) &local, sizeof(local)) < 0) {
- wpa_printf(MSG_ERROR, "VLAN: %s: bind(netlink) failed: %s",
- __func__, strerror(errno));
- close(priv->s);
- os_free(priv);
- return NULL;
- }
-
- if (eloop_register_read_sock(priv->s, vlan_event_receive, hapd, NULL))
- {
- close(priv->s);
- os_free(priv);
- return NULL;
- }
-
- return priv;
-}
-
-
-static void full_dynamic_vlan_deinit(struct full_dynamic_vlan *priv)
-{
- if (priv == NULL)
- return;
- eloop_unregister_read_sock(priv->s);
- close(priv->s);
- os_free(priv);
+ return ret;
}
-#endif /* CONFIG_FULL_DYNAMIC_VLAN */
-int vlan_setup_encryption_dyn(struct hostapd_data *hapd, const char *dyn_vlan)
+int vlan_if_remove(struct hostapd_data *hapd, struct hostapd_vlan *vlan)
{
- int i;
+ int ret;
- if (dyn_vlan == NULL)
- return 0;
+ ret = wpa_auth_release_group(hapd->wpa_auth, vlan->vlan_id);
+ if (ret)
+ wpa_printf(MSG_ERROR,
+ "WPA deinitialization for VLAN %d failed (%d)",
+ vlan->vlan_id, ret);
- /* Static WEP keys are set here; IEEE 802.1X and WPA uses their own
- * functions for setting up dynamic broadcast keys. */
- for (i = 0; i < 4; i++) {
- if (hapd->conf->ssid.wep.key[i] &&
- hostapd_drv_set_key(dyn_vlan, hapd, WPA_ALG_WEP, NULL, i,
- i == hapd->conf->ssid.wep.idx, NULL, 0,
- hapd->conf->ssid.wep.key[i],
- hapd->conf->ssid.wep.len[i]))
- {
- wpa_printf(MSG_ERROR, "VLAN: Could not set WEP "
- "encryption for dynamic VLAN");
- return -1;
- }
- }
-
- return 0;
+ return hostapd_vlan_if_remove(hapd, vlan->ifname);
}
{
while (vlan) {
if (vlan->vlan_id != VLAN_ID_WILDCARD) {
- if (hostapd_vlan_if_add(hapd, vlan->ifname)) {
- if (errno != EEXIST) {
- wpa_printf(MSG_ERROR, "VLAN: Could "
- "not add VLAN %s: %s",
- vlan->ifname,
- strerror(errno));
- return -1;
- }
+ if (vlan_if_add(hapd, vlan, 1)) {
+ wpa_printf(MSG_ERROR,
+ "VLAN: Could not add VLAN %s: %s",
+ vlan->ifname, strerror(errno));
+ return -1;
}
#ifdef CONFIG_FULL_DYNAMIC_VLAN
- ifconfig_up(vlan->ifname);
+ vlan_newlink(vlan->ifname, hapd);
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
}
while (vlan) {
next = vlan->next;
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
+ /* vlan_dellink() takes care of cleanup and interface removal */
+ if (vlan->vlan_id != VLAN_ID_WILDCARD)
+ vlan_dellink(vlan->ifname, hapd);
+#else /* CONFIG_FULL_DYNAMIC_VLAN */
if (vlan->vlan_id != VLAN_ID_WILDCARD &&
- hostapd_vlan_if_remove(hapd, vlan->ifname)) {
+ vlan_if_remove(hapd, vlan)) {
wpa_printf(MSG_ERROR, "VLAN: Could not remove VLAN "
"iface: %s: %s",
vlan->ifname, strerror(errno));
}
-#ifdef CONFIG_FULL_DYNAMIC_VLAN
- if (vlan->clean)
- vlan_dellink(vlan->ifname, hapd);
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
vlan = next;
hapd->full_dynamic_vlan = full_dynamic_vlan_init(hapd);
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
- if (hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED &&
+ if ((hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED ||
+ hapd->conf->ssid.per_sta_vif) &&
!hapd->conf->vlan) {
/* dynamic vlans enabled but no (or empty) vlan_file given */
struct hostapd_vlan *vlan;
struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
struct hostapd_vlan *vlan,
- int vlan_id)
+ int vlan_id,
+ struct vlan_description *vlan_desc)
{
- struct hostapd_vlan *n = NULL;
- char *ifname, *pos;
+ struct hostapd_vlan *n;
+ char ifname[IFNAMSIZ + 1], *pos;
- if (vlan == NULL || vlan_id <= 0 || vlan_id > MAX_VLAN_ID ||
- vlan->vlan_id != VLAN_ID_WILDCARD)
+ if (vlan == NULL || vlan->vlan_id != VLAN_ID_WILDCARD)
return NULL;
wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d ifname=%s)",
__func__, vlan_id, vlan->ifname);
- ifname = os_strdup(vlan->ifname);
- if (ifname == NULL)
- return NULL;
+ os_strlcpy(ifname, vlan->ifname, sizeof(ifname));
pos = os_strchr(ifname, '#');
if (pos == NULL)
- goto free_ifname;
+ return NULL;
*pos++ = '\0';
n = os_zalloc(sizeof(*n));
if (n == NULL)
- goto free_ifname;
+ return NULL;
n->vlan_id = vlan_id;
+ if (vlan_desc)
+ n->vlan_desc = *vlan_desc;
n->dynamic_vlan = 1;
os_snprintf(n->ifname, sizeof(n->ifname), "%s%d%s", ifname, vlan_id,
pos);
- if (hostapd_vlan_if_add(hapd, n->ifname)) {
- os_free(n);
- n = NULL;
- goto free_ifname;
- }
-
n->next = hapd->conf->vlan;
hapd->conf->vlan = n;
-#ifdef CONFIG_FULL_DYNAMIC_VLAN
- ifconfig_up(n->ifname);
-#endif /* CONFIG_FULL_DYNAMIC_VLAN */
+ /* hapd->conf->vlan needs this new VLAN here for WPA setup */
+ if (vlan_if_add(hapd, n, 0)) {
+ hapd->conf->vlan = n->next;
+ os_free(n);
+ n = NULL;
+ }
-free_ifname:
- os_free(ifname);
return n;
}
{
struct hostapd_vlan *vlan;
- if (vlan_id <= 0 || vlan_id > MAX_VLAN_ID)
+ if (vlan_id <= 0)
return 1;
wpa_printf(MSG_DEBUG, "VLAN: %s(ifname=%s vlan_id=%d)",
return 1;
if (vlan->dynamic_vlan == 0) {
- hostapd_vlan_if_remove(hapd, vlan->ifname);
+ vlan_if_remove(hapd, vlan);
#ifdef CONFIG_FULL_DYNAMIC_VLAN
vlan_dellink(vlan->ifname, hapd);
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
void vlan_deinit(struct hostapd_data *hapd);
struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
struct hostapd_vlan *vlan,
- int vlan_id);
+ int vlan_id,
+ struct vlan_description *vlan_desc);
int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id);
-int vlan_setup_encryption_dyn(struct hostapd_data *hapd,
- const char *dyn_vlan);
#else /* CONFIG_NO_VLAN */
static inline int vlan_init(struct hostapd_data *hapd)
{
{
}
-static inline struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
- struct hostapd_vlan *vlan,
- int vlan_id)
+static inline struct hostapd_vlan *
+vlan_add_dynamic(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
+ int vlan_id, struct vlan_description *vlan_desc)
{
return NULL;
}
{
return -1;
}
-
-static inline int vlan_setup_encryption_dyn(struct hostapd_data *hapd,
- const char *dyn_vlan)
-{
- return -1;
-}
#endif /* CONFIG_NO_VLAN */
#endif /* VLAN_INIT_H */
--- /dev/null
+/*
+ * hostapd / VLAN ioctl API
+ * Copyright 2003, Instant802 Networks, Inc.
+ * Copyright 2005-2006, Devicescape Software, Inc.
+ * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+#include <sys/ioctl.h>
+
+#include "utils/common.h"
+#include "common/linux_vlan.h"
+#include "vlan_util.h"
+
+
+int vlan_rem(const char *if_name)
+{
+ int fd;
+ struct vlan_ioctl_args if_request;
+
+ wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(%s)", if_name);
+ if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
+ wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
+ if_name);
+ return -1;
+ }
+
+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
+ "failed: %s", __func__, strerror(errno));
+ return -1;
+ }
+
+ os_memset(&if_request, 0, sizeof(if_request));
+
+ os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
+ if_request.cmd = DEL_VLAN_CMD;
+
+ if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
+ wpa_printf(MSG_ERROR, "VLAN: %s: DEL_VLAN_CMD failed for %s: "
+ "%s", __func__, if_name, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+ return 0;
+}
+
+
+/*
+ Add a vlan interface with VLAN ID 'vid' and tagged interface
+ 'if_name'.
+
+ returns -1 on error
+ returns 1 if the interface already exists
+ returns 0 otherwise
+*/
+int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
+{
+ int fd;
+ struct vlan_ioctl_args if_request;
+
+ wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d)",
+ if_name, vid);
+ ifconfig_up(if_name);
+
+ if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
+ wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
+ if_name);
+ return -1;
+ }
+
+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
+ "failed: %s", __func__, strerror(errno));
+ return -1;
+ }
+
+ os_memset(&if_request, 0, sizeof(if_request));
+
+ /* Determine if a suitable vlan device already exists. */
+
+ os_snprintf(if_request.device1, sizeof(if_request.device1), "vlan%d",
+ vid);
+
+ if_request.cmd = GET_VLAN_VID_CMD;
+
+ if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0 &&
+ if_request.u.VID == vid) {
+ if_request.cmd = GET_VLAN_REALDEV_NAME_CMD;
+
+ if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0 &&
+ os_strncmp(if_request.u.device2, if_name,
+ sizeof(if_request.u.device2)) == 0) {
+ close(fd);
+ wpa_printf(MSG_DEBUG,
+ "VLAN: vlan_add: if_name %s exists already",
+ if_request.device1);
+ return 1;
+ }
+ }
+
+ /* A suitable vlan device does not already exist, add one. */
+
+ os_memset(&if_request, 0, sizeof(if_request));
+ os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
+ if_request.u.VID = vid;
+ if_request.cmd = ADD_VLAN_CMD;
+
+ if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
+ wpa_printf(MSG_ERROR,
+ "VLAN: %s: ADD_VLAN_CMD failed for %s: %s",
+ __func__, if_request.device1, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+ return 0;
+}
+
+
+int vlan_set_name_type(unsigned int name_type)
+{
+ int fd;
+ struct vlan_ioctl_args if_request;
+
+ wpa_printf(MSG_DEBUG, "VLAN: vlan_set_name_type(name_type=%u)",
+ name_type);
+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ wpa_printf(MSG_ERROR,
+ "VLAN: %s: socket(AF_INET,SOCK_STREAM) failed: %s",
+ __func__, strerror(errno));
+ return -1;
+ }
+
+ os_memset(&if_request, 0, sizeof(if_request));
+
+ if_request.u.name_type = name_type;
+ if_request.cmd = SET_VLAN_NAME_TYPE_CMD;
+ if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
+ wpa_printf(MSG_ERROR,
+ "VLAN: %s: SET_VLAN_NAME_TYPE_CMD name_type=%u failed: %s",
+ __func__, name_type, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+ return 0;
+}
*/
#include "utils/includes.h"
-#include <sys/ioctl.h>
-#include <linux/sockios.h>
-#include <linux/if_vlan.h>
-#include <netlink/genl/genl.h>
-#include <netlink/genl/family.h>
-#include <netlink/genl/ctrl.h>
#include <netlink/route/link.h>
#include <netlink/route/link/vlan.h>
#include "utils/common.h"
-#include "utils/eloop.h"
-#include "hostapd.h"
#include "vlan_util.h"
/*
{
int err, ret = -1;
struct nl_sock *handle = NULL;
- struct nl_cache *cache = NULL;
struct rtnl_link *rlink = NULL;
int if_idx = 0;
goto vlan_add_error;
}
- err = rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache);
+ err = rtnl_link_get_kernel(handle, 0, if_name, &rlink);
if (err < 0) {
- cache = NULL;
- wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache: %s",
- nl_geterror(err));
- goto vlan_add_error;
- }
-
- if (!(if_idx = rtnl_link_name2i(cache, if_name))) {
/* link does not exist */
wpa_printf(MSG_ERROR, "VLAN: interface %s does not exist",
if_name);
goto vlan_add_error;
}
+ if_idx = rtnl_link_get_ifindex(rlink);
+ rtnl_link_put(rlink);
+ rlink = NULL;
- if ((rlink = rtnl_link_get_by_name(cache, vlan_if_name))) {
+ err = rtnl_link_get_kernel(handle, 0, vlan_if_name, &rlink);
+ if (err >= 0) {
/* link does exist */
rtnl_link_put(rlink);
rlink = NULL;
vlan_add_error:
if (rlink)
rtnl_link_put(rlink);
- if (cache)
- nl_cache_free(cache);
if (handle)
nl_socket_free(handle);
return ret;
{
int err, ret = -1;
struct nl_sock *handle = NULL;
- struct nl_cache *cache = NULL;
struct rtnl_link *rlink = NULL;
wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(if_name=%s)", if_name);
goto vlan_rem_error;
}
- err = rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache);
+ err = rtnl_link_get_kernel(handle, 0, if_name, &rlink);
if (err < 0) {
- cache = NULL;
- wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache: %s",
- nl_geterror(err));
- goto vlan_rem_error;
- }
-
- if (!(rlink = rtnl_link_get_by_name(cache, if_name))) {
/* link does not exist */
wpa_printf(MSG_ERROR, "VLAN: interface %s does not exists",
if_name);
vlan_rem_error:
if (rlink)
rtnl_link_put(rlink);
- if (cache)
- nl_cache_free(cache);
if (handle)
nl_socket_free(handle);
return ret;
}
+
+
+int vlan_set_name_type(unsigned int name_type)
+{
+ return 0;
+}
/*
- * hostapd / VLAN netlink api
+ * hostapd / VLAN netlink/ioctl api
* Copyright (c) 2012, Michael Braun <michael-dev@fami-braun.de>
*
* This software may be distributed under the terms of the BSD license.
#ifndef VLAN_UTIL_H
#define VLAN_UTIL_H
+struct hostapd_data;
+struct hostapd_vlan;
+struct full_dynamic_vlan;
+
int vlan_add(const char *if_name, int vid, const char *vlan_if_name);
int vlan_rem(const char *if_name);
+int vlan_set_name_type(unsigned int name_type);
+
+int ifconfig_helper(const char *if_name, int up);
+int ifconfig_up(const char *if_name);
+int iface_exists(const char *ifname);
+int vlan_if_remove(struct hostapd_data *hapd, struct hostapd_vlan *vlan);
+
+struct full_dynamic_vlan *
+full_dynamic_vlan_init(struct hostapd_data *hapd);
+void full_dynamic_vlan_deinit(struct full_dynamic_vlan *priv);
+void vlan_newlink(const char *ifname, struct hostapd_data *hapd);
+void vlan_dellink(const char *ifname, struct hostapd_data *hapd);
#endif /* VLAN_UTIL_H */
#include "ap/ap_config.h"
#include "ap/ap_drv_ops.h"
#include "ap/wpa_auth.h"
+#include "mbo_ap.h"
#include "wnm_ap.h"
#define MAX_TFS_IE_LEN 1024
if (mgmt == NULL) {
wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for "
"WNM-Sleep Response action frame");
+ os_free(wnmtfs_ie);
return -1;
}
os_memcpy(mgmt->da, addr, ETH_ALEN);
}
+static void ieee802_11_rx_wnm_notification_req(struct hostapd_data *hapd,
+ const u8 *addr, const u8 *buf,
+ size_t len)
+{
+ u8 dialog_token, type;
+
+ if (len < 2)
+ return;
+ dialog_token = *buf++;
+ type = *buf++;
+ len -= 2;
+
+ wpa_printf(MSG_DEBUG,
+ "WNM: Received WNM Notification Request frame from "
+ MACSTR " (dialog_token=%u type=%u)",
+ MAC2STR(addr), dialog_token, type);
+ wpa_hexdump(MSG_MSGDUMP, "WNM: Notification Request subelements",
+ buf, len);
+ if (type == WLAN_EID_VENDOR_SPECIFIC)
+ mbo_ap_wnm_notification_req(hapd, addr, buf, len);
+}
+
+
int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len)
{
case WNM_SLEEP_MODE_REQ:
ieee802_11_rx_wnmsleep_req(hapd, mgmt->sa, payload, plen);
return 0;
+ case WNM_NOTIFICATION_REQ:
+ ieee802_11_rx_wnm_notification_req(hapd, mgmt->sa, payload,
+ plen);
+ return 0;
}
wpa_printf(MSG_DEBUG, "WNM: Unsupported WNM Action %u from " MACSTR,
int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
u8 req_mode, int disassoc_timer, u8 valid_int,
const u8 *bss_term_dur, const char *url,
- const u8 *nei_rep, size_t nei_rep_len)
+ const u8 *nei_rep, size_t nei_rep_len,
+ const u8 *mbo_attrs, size_t mbo_len)
{
u8 *buf, *pos;
struct ieee80211_mgmt *mgmt;
wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request to "
MACSTR " req_mode=0x%x disassoc_timer=%d valid_int=0x%x",
MAC2STR(sta->addr), req_mode, disassoc_timer, valid_int);
- buf = os_zalloc(1000 + nei_rep_len);
+ buf = os_zalloc(1000 + nei_rep_len + mbo_len);
if (buf == NULL)
return -1;
mgmt = (struct ieee80211_mgmt *) buf;
pos += nei_rep_len;
}
+ if (mbo_len > 0) {
+ pos += mbo_add_ie(pos, buf + sizeof(buf) - pos, mbo_attrs,
+ mbo_len);
+ }
+
if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
wpa_printf(MSG_DEBUG,
"Failed to send BSS Transition Management Request frame");
int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
u8 req_mode, int disassoc_timer, u8 valid_int,
const u8 *bss_term_dur, const char *url,
- const u8 *nei_rep, size_t nei_rep_len);
+ const u8 *nei_rep, size_t nei_rep_len,
+ const u8 *mbo_attrs, size_t mbo_len);
#endif /* WNM_AP_H */
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,
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)) {
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) {
#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);
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;
* 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));
}
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);
}
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;
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,
* 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;
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) {
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");
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))
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,
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))
}
+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
}
+/*
+ * 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;
#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 */
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 */
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 */
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;
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);
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 */
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 */
_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;
}
#include "common/ieee802_11_defs.h"
#include "common/sae.h"
#include "common/wpa_ctrl.h"
+#include "crypto/sha1.h"
#include "eapol_auth/eapol_auth_sm.h"
#include "eapol_auth/eapol_auth_sm_i.h"
#include "eap_server/eap.h"
struct hostapd_sta_wpa_psk_short *pos;
psk = sta->psk->psk;
for (pos = sta->psk; pos; pos = pos->next) {
+ if (pos->is_passphrase) {
+ pbkdf2_sha1(pos->passphrase,
+ hapd->conf->ssid.ssid,
+ hapd->conf->ssid.ssid_len, 4096,
+ pos->psk, PMK_LEN);
+ pos->is_passphrase = 0;
+ }
if (pos->psk == prev_psk) {
psk = pos->next ? pos->next->psk : NULL;
break;
hapd = iface->bss[j];
if (hapd == idata->src_hapd)
continue;
+ if (!hapd->wpa_auth)
+ continue;
if (os_memcmp(hapd->own_addr, idata->dst, ETH_ALEN) == 0) {
wpa_printf(MSG_DEBUG, "FT: Send RRB data directly to "
"locally managed BSS " MACSTR "@%s -> "
ethhdr = (struct l2_ethhdr *) buf;
wpa_printf(MSG_DEBUG, "FT: RRB received packet " MACSTR " -> "
MACSTR, MAC2STR(ethhdr->h_source), MAC2STR(ethhdr->h_dest));
+ if (!is_multicast_ether_addr(ethhdr->h_dest) &&
+ os_memcmp(hapd->own_addr, ethhdr->h_dest, ETH_ALEN) != 0)
+ return;
wpa_ft_rrb_rx(hapd->wpa_auth, ethhdr->h_source, buf + sizeof(*ethhdr),
len - sizeof(*ethhdr));
}
}
#ifdef CONFIG_IEEE80211R
- if (!hostapd_drv_none(hapd) && hapd->conf->ft_over_ds &&
+ if (!hostapd_drv_none(hapd) &&
wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt)) {
hapd->l2 = l2_packet_init(hapd->conf->bridge[0] ?
hapd->conf->bridge :
wpa_deinit(hapd->wpa_auth);
hapd->wpa_auth = NULL;
- if (hostapd_set_privacy(hapd, 0)) {
+ if (hapd->drv_priv && hostapd_set_privacy(hapd, 0)) {
wpa_printf(MSG_DEBUG, "Could not disable "
"PrivacyInvoked for interface %s",
hapd->conf->iface);
}
- if (hostapd_set_generic_elem(hapd, (u8 *) "", 0)) {
+ if (hapd->drv_priv &&
+ hostapd_set_generic_elem(hapd, (u8 *) "", 0)) {
wpa_printf(MSG_DEBUG, "Could not remove generic "
"information element from interface %s",
hapd->conf->iface);
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;
#endif /* CONFIG_IEEE80211W */
/* Number of references except those in struct wpa_group->next */
unsigned int references;
+ unsigned int num_setup_iface;
};
pos += 2;
if (pmkid) {
- if (pos + 2 + PMKID_LEN > buf + len)
+ if (2 + PMKID_LEN > buf + len - pos)
return -1;
/* PMKID Count */
WPA_PUT_LE16(pos, 1);
#ifdef CONFIG_IEEE80211W
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION &&
conf->group_mgmt_cipher != WPA_CIPHER_AES_128_CMAC) {
- if (pos + 2 + 4 > buf + len)
+ if (2 + 4 > buf + len - pos)
return -1;
if (pmkid == NULL) {
/* PMKID Count */
}
}
if (sm->pmksa && pmkid) {
+ struct vlan_description *vlan;
+
+ vlan = sm->pmksa->vlan_desc;
wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
- "PMKID found from PMKSA cache "
- "eap_type=%d vlan_id=%d",
+ "PMKID found from PMKSA cache eap_type=%d vlan=%d%s",
sm->pmksa->eap_type_authsrv,
- sm->pmksa->vlan_id);
+ vlan ? vlan->untagged : 0,
+ (vlan && vlan->tagged[0]) ? "+" : "");
os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmkid, PMKID_LEN);
}
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;
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));
/*
* hostapd / WPS integration
- * Copyright (c) 2008-2012, 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.
}
-static int str_starts(const char *str, const char *start)
-{
- return os_strncmp(str, start, os_strlen(start)) == 0;
-}
-
-
static void wps_reload_config(void *eloop_data, void *user_ctx)
{
struct hostapd_iface *iface = eloop_data;
os_memcpy(hapd->wps->ssid, cred->ssid, cred->ssid_len);
hapd->wps->ssid_len = cred->ssid_len;
hapd->wps->encr_types = cred->encr_type;
+ hapd->wps->encr_types_rsn = cred->encr_type;
+ hapd->wps->encr_types_wpa = cred->encr_type;
hapd->wps->auth_types = cred->auth_type;
hapd->wps->ap_encr_type = cred->encr_type;
hapd->wps->ap_auth_type = cred->auth_type;
hapd->wps_probe_resp_ie = NULL;
if (deinit_only) {
- hostapd_reset_ap_wps_ie(hapd);
+ if (hapd->drv_priv)
+ hostapd_reset_ap_wps_ie(hapd);
return;
}
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X)
wps->auth_types |= WPS_AUTH_WPA2;
- if (conf->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP))
+ if (conf->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) {
wps->encr_types |= WPS_ENCR_AES;
- if (conf->rsn_pairwise & WPA_CIPHER_TKIP)
+ wps->encr_types_rsn |= WPS_ENCR_AES;
+ }
+ if (conf->rsn_pairwise & WPA_CIPHER_TKIP) {
wps->encr_types |= WPS_ENCR_TKIP;
+ wps->encr_types_rsn |= WPS_ENCR_TKIP;
+ }
}
if (conf->wpa & WPA_PROTO_WPA) {
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X)
wps->auth_types |= WPS_AUTH_WPA;
- if (conf->wpa_pairwise & WPA_CIPHER_CCMP)
+ if (conf->wpa_pairwise & WPA_CIPHER_CCMP) {
wps->encr_types |= WPS_ENCR_AES;
- if (conf->wpa_pairwise & WPA_CIPHER_TKIP)
+ wps->encr_types_wpa |= WPS_ENCR_AES;
+ }
+ if (conf->wpa_pairwise & WPA_CIPHER_TKIP) {
wps->encr_types |= WPS_ENCR_TKIP;
+ wps->encr_types_wpa |= WPS_ENCR_TKIP;
+ }
}
if (conf->ssid.security_policy == SECURITY_PLAINTEXT) {
/* Override parameters to enable security by default */
wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK;
wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP;
+ wps->encr_types_rsn = WPS_ENCR_AES | WPS_ENCR_TKIP;
+ wps->encr_types_wpa = WPS_ENCR_AES | WPS_ENCR_TKIP;
}
wps->ap_settings = conf->ap_settings;
unsigned int pin;
struct wps_ap_pin_data data;
- pin = wps_generate_pin();
+ if (wps_generate_pin(&pin) < 0)
+ return NULL;
os_snprintf(data.pin_txt, sizeof(data.pin_txt), "%08u", pin);
data.timeout = timeout;
hostapd_wps_for_each(hapd, wps_ap_pin_set, &data);
--- /dev/null
+/*
+ * Common hostapd/wpa_supplicant command line interface functions
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "utils/common.h"
+#include "common/cli.h"
+
+
+const char *const cli_license =
+"This software may be distributed under the terms of the BSD license.\n"
+"See README for more details.\n";
+
+const char *const cli_full_license =
+"This software may be distributed under the terms of the BSD license.\n"
+"\n"
+"Redistribution and use in source and binary forms, with or without\n"
+"modification, are permitted provided that the following conditions are\n"
+"met:\n"
+"\n"
+"1. Redistributions of source code must retain the above copyright\n"
+" notice, this list of conditions and the following disclaimer.\n"
+"\n"
+"2. Redistributions in binary form must reproduce the above copyright\n"
+" notice, this list of conditions and the following disclaimer in the\n"
+" documentation and/or other materials provided with the distribution.\n"
+"\n"
+"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
+" names of its contributors may be used to endorse or promote products\n"
+" derived from this software without specific prior written permission.\n"
+"\n"
+"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
+"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
+"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
+"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
+"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
+"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
+"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
+"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
+"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
+"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
+"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
+"\n";
+
+
+void cli_txt_list_free(struct cli_txt_entry *e)
+{
+ dl_list_del(&e->list);
+ os_free(e->txt);
+ os_free(e);
+}
+
+
+void cli_txt_list_flush(struct dl_list *list)
+{
+ struct cli_txt_entry *e;
+
+ while ((e = dl_list_first(list, struct cli_txt_entry, list)))
+ cli_txt_list_free(e);
+}
+
+
+struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
+ const char *txt)
+{
+ struct cli_txt_entry *e;
+
+ dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
+ if (os_strcmp(e->txt, txt) == 0)
+ return e;
+ }
+ return NULL;
+}
+
+
+void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
+{
+ struct cli_txt_entry *e;
+
+ e = cli_txt_list_get(txt_list, txt);
+ if (e)
+ cli_txt_list_free(e);
+}
+
+
+void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
+{
+ u8 addr[ETH_ALEN];
+ char buf[18];
+
+ if (hwaddr_aton(txt, addr) < 0)
+ return;
+ os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
+ cli_txt_list_del(txt_list, buf);
+}
+
+
+void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt,
+ int separator)
+{
+ const char *end;
+ char *buf;
+
+ end = os_strchr(txt, separator);
+ if (end == NULL)
+ end = txt + os_strlen(txt);
+ buf = dup_binstr(txt, end - txt);
+ if (buf == NULL)
+ return;
+ cli_txt_list_del(txt_list, buf);
+ os_free(buf);
+}
+
+
+int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
+{
+ struct cli_txt_entry *e;
+
+ e = cli_txt_list_get(txt_list, txt);
+ if (e)
+ return 0;
+ e = os_zalloc(sizeof(*e));
+ if (e == NULL)
+ return -1;
+ e->txt = os_strdup(txt);
+ if (e->txt == NULL) {
+ os_free(e);
+ return -1;
+ }
+ dl_list_add(txt_list, &e->list);
+ return 0;
+}
+
+
+int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
+{
+ u8 addr[ETH_ALEN];
+ char buf[18];
+
+ if (hwaddr_aton(txt, addr) < 0)
+ return -1;
+ os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
+ return cli_txt_list_add(txt_list, buf);
+}
+
+
+int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt,
+ int separator)
+{
+ const char *end;
+ char *buf;
+ int ret;
+
+ end = os_strchr(txt, separator);
+ if (end == NULL)
+ end = txt + os_strlen(txt);
+ buf = dup_binstr(txt, end - txt);
+ if (buf == NULL)
+ return -1;
+ ret = cli_txt_list_add(txt_list, buf);
+ os_free(buf);
+ return ret;
+}
+
+
+char ** cli_txt_list_array(struct dl_list *txt_list)
+{
+ unsigned int i, count = dl_list_len(txt_list);
+ char **res;
+ struct cli_txt_entry *e;
+
+ res = os_calloc(count + 1, sizeof(char *));
+ if (res == NULL)
+ return NULL;
+
+ i = 0;
+ dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
+ res[i] = os_strdup(e->txt);
+ if (res[i] == NULL)
+ break;
+ i++;
+ }
+
+ return res;
+}
+
+
+int get_cmd_arg_num(const char *str, int pos)
+{
+ int arg = 0, i;
+
+ for (i = 0; i <= pos; i++) {
+ if (str[i] != ' ') {
+ arg++;
+ while (i <= pos && str[i] != ' ')
+ i++;
+ }
+ }
+
+ if (arg > 0)
+ arg--;
+ return arg;
+}
+
+
+int write_cmd(char *buf, size_t buflen, const char *cmd, int argc, char *argv[])
+{
+ int i, res;
+ char *pos, *end;
+
+ pos = buf;
+ end = buf + buflen;
+
+ res = os_snprintf(pos, end - pos, "%s", cmd);
+ if (os_snprintf_error(end - pos, res))
+ goto fail;
+ pos += res;
+
+ for (i = 0; i < argc; i++) {
+ res = os_snprintf(pos, end - pos, " %s", argv[i]);
+ if (os_snprintf_error(end - pos, res))
+ goto fail;
+ pos += res;
+ }
+
+ buf[buflen - 1] = '\0';
+ return 0;
+
+fail:
+ printf("Too long command\n");
+ return -1;
+}
+
+
+int tokenize_cmd(char *cmd, char *argv[])
+{
+ char *pos;
+ int argc = 0;
+
+ pos = cmd;
+ for (;;) {
+ while (*pos == ' ')
+ pos++;
+ if (*pos == '\0')
+ break;
+ argv[argc] = pos;
+ argc++;
+ if (argc == max_args)
+ break;
+ if (*pos == '"') {
+ char *pos2 = os_strrchr(pos, '"');
+ if (pos2)
+ pos = pos2 + 1;
+ }
+ while (*pos != '\0' && *pos != ' ')
+ pos++;
+ if (*pos == ' ')
+ *pos++ = '\0';
+ }
+
+ return argc;
+}
--- /dev/null
+/*
+ * Common hostapd/wpa_supplicant command line interface functionality
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef CLI_H
+#define CLI_H
+
+#include "utils/list.h"
+
+extern const char *const cli_license;
+extern const char *const cli_full_license;
+
+struct cli_txt_entry {
+ struct dl_list list;
+ char *txt;
+};
+
+void cli_txt_list_free(struct cli_txt_entry *e);
+void cli_txt_list_flush(struct dl_list *list);
+
+struct cli_txt_entry *
+cli_txt_list_get(struct dl_list *txt_list, const char *txt);
+
+void cli_txt_list_del(struct dl_list *txt_list, const char *txt);
+void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt);
+void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt,
+ int separator);
+
+int cli_txt_list_add(struct dl_list *txt_list, const char *txt);
+int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt);
+int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt,
+ int separator);
+
+char ** cli_txt_list_array(struct dl_list *txt_list);
+
+int get_cmd_arg_num(const char *str, int pos);
+int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
+ char *argv[]);
+
+#define max_args 10
+int tokenize_cmd(char *cmd, char *argv[]);
+
+#endif /* CLI_H */
#include "utils/includes.h"
#include "utils/common.h"
+#include "utils/module_tests.h"
#include "ieee802_11_common.h"
#include "ieee802_11_defs.h"
#include "gas.h"
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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 */
WPA_CTRL_REQ_EAP_PASSPHRASE,
WPA_CTRL_REQ_SIM,
WPA_CTRL_REQ_PSK_PASSPHRASE,
+ WPA_CTRL_REQ_EXT_CERT_CHECK,
NUM_WPA_CTRL_REQS
};
#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 {
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 */
struct ieee8023_hdr {
u8 dest[ETH_ALEN];
u8 src[ETH_ALEN];
- u16 ethertype;
+ be16 ethertype;
} STRUCT_PACKED;
#ifdef _MSC_VER
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 "
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)
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];
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) {
* 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)
{
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);
}
* 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
int sec_channel, int vht,
u8 *op_class, u8 *channel)
{
+ u8 vht_opclass;
+
/* TODO: more operating classes */
if (sec_channel > 1 || sec_channel < -1)
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;
return HOSTAPD_MODE_IEEE80211A;
}
- /* 5 GHz, channels 149..161 */
- if (freq >= 5745 && freq <= 5805) {
+ /* 5 GHz, channels 149..169 */
+ if (freq >= 5745 && freq <= 5845) {
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 = 126;
else if (sec_channel == -1)
*op_class = 127;
- else if (vht)
- *op_class = 128;
- else
+ else if (freq <= 5805)
*op_class = 124;
+ else
+ *op_class = 125;
*channel = (freq - 5000) / 5;
return HOSTAPD_MODE_IEEE80211A;
}
- /* 5 GHz, channels 149..169 */
- if (freq >= 5745 && freq <= 5845) {
+ /* 5 GHz, channels 100..140 */
+ if (freq >= 5000 && freq <= 5700) {
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 = 122;
+ else if (sec_channel == -1)
+ *op_class = 123;
+ else
+ *op_class = 121;
*channel = (freq - 5000) / 5;
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;
+}
#ifndef IEEE802_11_COMMON_H
#define IEEE802_11_COMMON_H
+#include "defs.h"
+
#define MAX_NOF_MB_IES_SUPPORTED 5
struct mb_ies_info {
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;
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;
};
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,
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 */
#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
#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
/* 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
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
};
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 */
* 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;
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
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
#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
#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
#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,
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 {
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;
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 */
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 */
#define IEEE802_1X_DEFS_H
#define CS_ID_LEN 8
-#define CS_ID_GCM_AES_128 {0x00, 0x80, 0x02, 0x00, 0x01, 0x00, 0x00, 0x01}
+#define CS_ID_GCM_AES_128 0x0080020001000001ULL
#define CS_NAME_GCM_AES_128 "GCM-AES-128"
enum macsec_policy {
--- /dev/null
+/*
+ * Linux bridge configuration kernel interface
+ * Copyright (c) 2016, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef LINUX_BRIDGE_H
+#define LINUX_BRIDGE_H
+
+/* This interface is defined in linux/if_bridge.h */
+
+#define BRCTL_GET_VERSION 0
+#define BRCTL_GET_BRIDGES 1
+#define BRCTL_ADD_BRIDGE 2
+#define BRCTL_DEL_BRIDGE 3
+#define BRCTL_ADD_IF 4
+#define BRCTL_DEL_IF 5
+#define BRCTL_GET_BRIDGE_INFO 6
+#define BRCTL_GET_PORT_LIST 7
+#define BRCTL_SET_BRIDGE_FORWARD_DELAY 8
+
+#endif /* LINUX_BRIDGE_H */
--- /dev/null
+/*
+ * Linux VLAN configuration kernel interface
+ * Copyright (c) 2016, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef LINUX_VLAN_H
+#define LINUX_VLAN_H
+
+/* This ioctl is defined in linux/sockios.h */
+
+#ifndef SIOCSIFVLAN
+#define SIOCSIFVLAN 0x8983
+#endif /* SIOCSIFVLAN */
+
+/* This interface is defined in linux/if_vlan.h */
+
+#define ADD_VLAN_CMD 0
+#define DEL_VLAN_CMD 1
+#define SET_VLAN_INGRESS_PRIORITY_CMD 2
+#define SET_VLAN_EGRESS_PRIORITY_CMD 3
+#define GET_VLAN_INGRESS_PRIORITY_CMD 4
+#define GET_VLAN_EGRESS_PRIORITY_CMD 5
+#define SET_VLAN_NAME_TYPE_CMD 6
+#define SET_VLAN_FLAG_CMD 7
+#define GET_VLAN_REALDEV_NAME_CMD 8
+#define GET_VLAN_VID_CMD 9
+
+#define VLAN_NAME_TYPE_PLUS_VID 0
+#define VLAN_NAME_TYPE_RAW_PLUS_VID 1
+#define VLAN_NAME_TYPE_PLUS_VID_NO_PAD 2
+#define VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD 3
+
+struct vlan_ioctl_args {
+ int cmd;
+ char device1[24];
+
+ union {
+ char device2[24];
+ int VID;
+ unsigned int skb_priority;
+ unsigned int name_type;
+ unsigned int bind_type;
+ unsigned int flag;
+ } u;
+
+ short vlan_qos;
+};
+
+#endif /* LINUX_VLAN_H */
* @QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED: Event used by driver,
* which supports DFS offloading, to indicate a radar pattern has been
* detected. The channel is now unusable.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START: Command used to
+ * start the P2P Listen offload function in device and pass the listen
+ * channel, period, interval, count, device types, and vendor specific
+ * information elements to the device driver and firmware.
+ * Uses the attributes defines in
+ * enum qca_wlan_vendor_attr_p2p_listen_offload.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP: Command/event used to
+ * indicate stop request/response of the P2P Listen offload function in
+ * device. As an event, it indicates either the feature stopped after it
+ * was already running or feature has actually failed to start. Uses the
+ * attributes defines in enum qca_wlan_vendor_attr_p2p_listen_offload.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH: After AP starts
+ * beaconing, this sub command provides the driver, the frequencies on the
+ * 5 GHz band to check for any radar activity. Driver selects one channel
+ * from this priority list provided through
+ * @QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST and starts
+ * to check for radar activity on it. If no radar activity is detected
+ * during the channel availability check period, driver internally switches
+ * to the selected frequency of operation. If the frequency is zero, driver
+ * internally selects a channel. The status of this conditional switch is
+ * indicated through an event using the same sub command through
+ * @QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_STATUS. Attributes are
+ * listed in qca_wlan_vendor_attr_sap_conditional_chan_switch.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GPIO_CONFIG_COMMAND: Set GPIO pins. This uses the
+ * attributes defined in enum qca_wlan_gpio_attr.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_HW_CAPABILITY: Fetch hardware capabilities.
+ * This uses @QCA_WLAN_VENDOR_ATTR_GET_HW_CAPABILITY to indicate which
+ * capabilities are to be fetched and other
+ * enum qca_wlan_vendor_attr_get_hw_capability attributes to return the
+ * requested capabilities.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT: Link layer statistics extension.
+ * enum qca_wlan_vendor_attr_ll_stats_ext attributes are used with this
+ * command and event.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_LOC_GET_CAPA: Get capabilities for
+ * indoor location features. Capabilities are reported in
+ * QCA_WLAN_VENDOR_ATTR_LOC_CAPA.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_FTM_START_SESSION: Start an FTM
+ * (fine timing measurement) session with one or more peers.
+ * Specify Session cookie in QCA_WLAN_VENDOR_ATTR_FTM_SESSION_COOKIE and
+ * peer information in QCA_WLAN_VENDOR_ATTR_FTM_MEAS_PEERS.
+ * On success, 0 or more QCA_NL80211_VENDOR_SUBCMD_FTM_MEAS_RESULT
+ * events will be reported, followed by
+ * QCA_NL80211_VENDOR_SUBCMD_FTM_SESSION_DONE event to indicate
+ * end of session.
+ * Refer to IEEE P802.11-REVmc/D7.0, 11.24.6
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_FTM_ABORT_SESSION: Abort a running session.
+ * A QCA_NL80211_VENDOR_SUBCMD_FTM_SESSION_DONE will be reported with
+ * status code indicating session was aborted.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_FTM_MEAS_RESULT: Event with measurement
+ * results for one peer. Results are reported in
+ * QCA_WLAN_VENDOR_ATTR_FTM_MEAS_PEER_RESULTS.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_FTM_SESSION_DONE: Event triggered when
+ * FTM session is finished, either successfully or aborted by
+ * request.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_FTM_CFG_RESPONDER: Configure FTM responder
+ * mode. QCA_WLAN_VENDOR_ATTR_FTM_RESPONDER_ENABLE specifies whether
+ * to enable or disable the responder. LCI/LCR reports can be
+ * configured with QCA_WLAN_VENDOR_ATTR_FTM_LCI and
+ * QCA_WLAN_VENDOR_ATTR_FTM_LCR. Can be called multiple
+ * times to update the LCI/LCR reports.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS: Perform a standalone AOA (angle of
+ * arrival) measurement with a single peer. Specify peer MAC address in
+ * QCA_WLAN_VENDOR_ATTR_MAC_ADDR and measurement type in
+ * QCA_WLAN_VENDOR_ATTR_AOA_TYPE. Measurement result is reported in
+ * QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS_RESULT event.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_AOA_ABORT_MEAS: Abort an AOA measurement. Specify
+ * peer MAC address in QCA_WLAN_VENDOR_ATTR_MAC_ADDR.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS_RESULT: Event that reports
+ * the AOA measurement result.
+ * Peer MAC address reported in QCA_WLAN_VENDOR_ATTR_MAC_ADDR.
+ * success/failure status is reported in
+ * QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS.
+ * Measurement data is reported in QCA_WLAN_VENDOR_ATTR_AOA_MEAS_RESULT.
+ * The antenna array(s) used in the measurement are reported in
+ * QCA_WLAN_VENDOR_ATTR_LOC_ANTENNA_ARRAY_MASK.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST: Encrypt/decrypt the given
+ * data as per the given parameters.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI: Get antenna RSSI value for a
+ * specific chain.
*/
enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED = 58,
QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED = 59,
QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED = 60,
- /* 61-90 - reserved for QCA */
+ /* 61-73 - reserved for QCA */
+ /* Wi-Fi configuration subcommands */
+ QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION = 74,
+ QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION = 75,
+ /* 76-90 - reserved for QCA */
QCA_NL80211_VENDOR_SUBCMD_DATA_OFFLOAD = 91,
QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG = 92,
QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME = 93,
QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST = 103,
QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL = 104,
QCA_NL80211_VENDOR_SUBCMD_SETBAND = 105,
+ QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN = 106,
+ QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE = 107,
+ QCA_NL80211_VENDOR_SUBCMD_OTA_TEST = 108,
+ QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE = 109,
+ /* 110..114 - reserved for QCA */
+ QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_DECR_DB = 115,
+ /* 116..117 - reserved for QCA */
+ QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG = 118,
+ QCA_NL80211_VENDOR_SUBCMD_TSF = 119,
+ QCA_NL80211_VENDOR_SUBCMD_WISA = 120,
+ /* 121 - reserved for QCA */
+ QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START = 122,
+ QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP = 123,
+ QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH = 124,
+ QCA_NL80211_VENDOR_SUBCMD_GPIO_CONFIG_COMMAND = 125,
+ QCA_NL80211_VENDOR_SUBCMD_GET_HW_CAPABILITY = 126,
+ QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT = 127,
+ /* FTM/indoor location subcommands */
+ QCA_NL80211_VENDOR_SUBCMD_LOC_GET_CAPA = 128,
+ QCA_NL80211_VENDOR_SUBCMD_FTM_START_SESSION = 129,
+ QCA_NL80211_VENDOR_SUBCMD_FTM_ABORT_SESSION = 130,
+ QCA_NL80211_VENDOR_SUBCMD_FTM_MEAS_RESULT = 131,
+ QCA_NL80211_VENDOR_SUBCMD_FTM_SESSION_DONE = 132,
+ QCA_NL80211_VENDOR_SUBCMD_FTM_CFG_RESPONDER = 133,
+ QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS = 134,
+ QCA_NL80211_VENDOR_SUBCMD_AOA_ABORT_MEAS = 135,
+ QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS_RESULT = 136,
+ QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST = 137,
+ QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI = 138,
};
QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND = 11,
/* Unsigned 32-bit value from enum qca_set_band. */
QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE = 12,
+ /* Dummy (NOP) attribute for 64 bit padding */
+ QCA_WLAN_VENDOR_ATTR_PAD = 13,
+ /* Unique FTM session cookie (Unsigned 64 bit). Specified in
+ * QCA_NL80211_VENDOR_SUBCMD_FTM_START_SESSION. Reported in
+ * the session in QCA_NL80211_VENDOR_SUBCMD_FTM_MEAS_RESULT and
+ * QCA_NL80211_VENDOR_SUBCMD_FTM_SESSION_DONE.
+ */
+ QCA_WLAN_VENDOR_ATTR_FTM_SESSION_COOKIE = 14,
+ /* Indoor location capabilities, returned by
+ * QCA_NL80211_VENDOR_SUBCMD_LOC_GET_CAPA.
+ * see enum qca_wlan_vendor_attr_loc_capa.
+ */
+ QCA_WLAN_VENDOR_ATTR_LOC_CAPA = 15,
+ /* Array of nested attributes containing information about each peer
+ * in FTM measurement session. See enum qca_wlan_vendor_attr_peer_info
+ * for supported attributes for each peer.
+ */
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_PEERS = 16,
+ /* Array of nested attributes containing measurement results for
+ * one or more peers, reported by the
+ * QCA_NL80211_VENDOR_SUBCMD_FTM_MEAS_RESULT event.
+ * See enum qca_wlan_vendor_attr_peer_result for list of supported
+ * attributes.
+ */
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_PEER_RESULTS = 17,
+ /* Flag attribute for enabling or disabling responder functionality. */
+ QCA_WLAN_VENDOR_ATTR_FTM_RESPONDER_ENABLE = 18,
+ /* Used in the QCA_NL80211_VENDOR_SUBCMD_FTM_CFG_RESPONDER
+ * command to specify the LCI report that will be sent by
+ * the responder during a measurement exchange. The format is
+ * defined in IEEE P802.11-REVmc/D7.0, 9.4.2.22.10.
+ */
+ QCA_WLAN_VENDOR_ATTR_FTM_LCI = 19,
+ /* Used in the QCA_NL80211_VENDOR_SUBCMD_FTM_CFG_RESPONDER
+ * command to specify the location civic report that will
+ * be sent by the responder during a measurement exchange.
+ * The format is defined in IEEE P802.11-REVmc/D7.0, 9.4.2.22.13.
+ */
+ QCA_WLAN_VENDOR_ATTR_FTM_LCR = 20,
+ /* Session/measurement completion status code,
+ * reported in QCA_NL80211_VENDOR_SUBCMD_FTM_SESSION_DONE and
+ * QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS_RESULT
+ * see enum qca_vendor_attr_loc_session_status.
+ */
+ QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS = 21,
+ /* Initial dialog token used by responder (0 if not specified),
+ * unsigned 8 bit value.
+ */
+ QCA_WLAN_VENDOR_ATTR_FTM_INITIAL_TOKEN = 22,
+ /* AOA measurement type. Requested in QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS
+ * and optionally in QCA_NL80211_VENDOR_SUBCMD_FTM_START_SESSION if
+ * AOA measurements are needed as part of an FTM session.
+ * Reported by QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS_RESULT. See
+ * enum qca_wlan_vendor_attr_aoa_type.
+ */
+ QCA_WLAN_VENDOR_ATTR_AOA_TYPE = 23,
+ /* A bit mask (unsigned 32 bit value) of antenna arrays used
+ * by indoor location measurements. Refers to the antenna
+ * arrays described by QCA_VENDOR_ATTR_LOC_CAPA_ANTENNA_ARRAYS.
+ */
+ QCA_WLAN_VENDOR_ATTR_LOC_ANTENNA_ARRAY_MASK = 24,
+ /* AOA measurement data. Its contents depends on the AOA measurement
+ * type and antenna array mask:
+ * QCA_WLAN_VENDOR_ATTR_AOA_TYPE_TOP_CIR_PHASE: array of U16 values,
+ * phase of the strongest CIR path for each antenna in the measured
+ * array(s).
+ * QCA_WLAN_VENDOR_ATTR_AOA_TYPE_TOP_CIR_PHASE_AMP: array of 2 U16
+ * values, phase and amplitude of the strongest CIR path for each
+ * antenna in the measured array(s).
+ */
+ QCA_WLAN_VENDOR_ATTR_AOA_MEAS_RESULT = 25,
+ /* Used in QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI command
+ * to specify the chain number (unsigned 32 bit value) to inquire
+ * the corresponding antenna RSSI value */
+ QCA_WLAN_VENDOR_ATTR_CHAIN_INDEX = 26,
+ /* Used in QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI command
+ * to report the specific antenna RSSI value (unsigned 32 bit value) */
+ QCA_WLAN_VENDOR_ATTR_CHAIN_RSSI = 27,
/* keep last */
QCA_WLAN_VENDOR_ATTR_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_MAX = QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1,
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
+ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
/* keep last */
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX =
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST - 1
};
+enum qca_wlan_vendor_attr_p2p_listen_offload {
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INVALID = 0,
+ /* A 32-bit unsigned value; the P2P listen frequency (MHz); must be one
+ * of the social channels.
+ */
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL,
+ /* A 32-bit unsigned value; the P2P listen offload period (ms).
+ */
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD,
+ /* A 32-bit unsigned value; the P2P listen interval duration (ms).
+ */
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL,
+ /* A 32-bit unsigned value; number of interval times the firmware needs
+ * to run the offloaded P2P listen operation before it stops.
+ */
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT,
+ /* An array of arbitrary binary data with one or more 8-byte values.
+ * The device types include both primary and secondary device types.
+ */
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES,
+ /* An array of unsigned 8-bit characters; vendor information elements.
+ */
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE,
+ /* A 32-bit unsigned value; a control flag to indicate whether listen
+ * results need to be flushed to wpa_supplicant.
+ */
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG,
+ /* A 8-bit unsigned value; reason code for P2P listen offload stop
+ * event.
+ */
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX =
+ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_AFTER_LAST - 1
+};
+
enum qca_wlan_vendor_attr_acs_offload {
QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0,
QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
* after roaming, rather than having the user space wpa_supplicant do it.
* @QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY: Device supports automatic
* band selection based on channel selection results.
+ * @QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS: Device supports
+ * simultaneous off-channel operations.
+ * @QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD: Device supports P2P
+ * Listen offload; a mechanism where the station's firmware takes care of
+ * responding to incoming Probe Request frames received from other P2P
+ * Devices whilst in Listen state, rather than having the user space
+ * wpa_supplicant do it. Information from received P2P requests are
+ * forwarded from firmware to host whenever the host processor wakes up.
* @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits
*/
enum qca_wlan_vendor_features {
QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD = 0,
QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY = 1,
+ QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS = 2,
+ QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD = 3,
NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */
};
QCA_SETBAND_2G,
};
+/**
+ * enum qca_access_policy - Access control policy
+ *
+ * Access control policy is applied on the configured IE
+ * (QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE).
+ * To be set with QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY.
+ *
+ * @QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED: Deny Wi-Fi connections which match
+ * the specific configuration (IE) set, i.e., allow all the
+ * connections which do not match the configuration.
+ * @QCA_ACCESS_POLICY_DENY_UNLESS_LISTED: Accept Wi-Fi connections which match
+ * the specific configuration (IE) set, i.e., deny all the
+ * connections which do not match the configuration.
+ */
+enum qca_access_policy {
+ QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED,
+ QCA_ACCESS_POLICY_DENY_UNLESS_LISTED,
+};
+
+/**
+ * enum qca_vendor_attr_get_tsf: Vendor attributes for TSF capture
+ * @QCA_WLAN_VENDOR_ATTR_TSF_CMD: enum qca_tsf_operation (u32)
+ * @QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE: Unsigned 64 bit TSF timer value
+ * @QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE: Unsigned 64 bit Synchronized
+ * SOC timer value at TSF capture
+ */
+enum qca_vendor_attr_tsf_cmd {
+ QCA_WLAN_VENDOR_ATTR_TSF_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_TSF_CMD,
+ QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE,
+ QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE,
+ QCA_WLAN_VENDOR_ATTR_TSF_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TSF_MAX =
+ QCA_WLAN_VENDOR_ATTR_TSF_AFTER_LAST - 1
+};
+
+/**
+ * enum qca_tsf_operation: TSF driver commands
+ * @QCA_TSF_CAPTURE: Initiate TSF Capture
+ * @QCA_TSF_GET: Get TSF capture value
+ * @QCA_TSF_SYNC_GET: Initiate TSF capture and return with captured value
+ */
+enum qca_tsf_cmd {
+ QCA_TSF_CAPTURE,
+ QCA_TSF_GET,
+ QCA_TSF_SYNC_GET,
+};
+
+/**
+ * enum qca_vendor_attr_wisa_cmd
+ * @QCA_WLAN_VENDOR_ATTR_WISA_MODE: WISA mode value (u32)
+ * WISA setup vendor commands
+ */
+enum qca_vendor_attr_wisa_cmd {
+ QCA_WLAN_VENDOR_ATTR_WISA_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_WISA_MODE,
+ QCA_WLAN_VENDOR_ATTR_WISA_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_WISA_MAX =
+ QCA_WLAN_VENDOR_ATTR_WISA_AFTER_LAST - 1
+};
+
/* IEEE 802.11 Vendor Specific elements */
/**
*
* This vendor element may be included in GO Negotiation Request, P2P
* Invitation Request, and Provision Discovery Request frames.
+ *
+ * @QCA_VENDOR_ELEM_HE_CAPAB: HE Capabilities element.
+ * This element can be used for pre-standard publication testing of HE
+ * before P802.11ax draft assigns the element ID. The payload of this
+ * vendor specific element is defined by the latest P802.11ax draft.
+ * Please note that the draft is still work in progress and this element
+ * payload is subject to change.
+ *
+ * @QCA_VENDOR_ELEM_HE_OPER: HE Operation element.
+ * This element can be used for pre-standard publication testing of HE
+ * before P802.11ax draft assigns the element ID. The payload of this
+ * vendor specific element is defined by the latest P802.11ax draft.
+ * Please note that the draft is still work in progress and this element
+ * payload is subject to change.
*/
enum qca_vendor_element_id {
QCA_VENDOR_ELEM_P2P_PREF_CHAN_LIST = 0,
+ QCA_VENDOR_ELEM_HE_CAPAB = 1,
+ QCA_VENDOR_ELEM_HE_OPER = 2,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_scan - Specifies vendor scan attributes
+ *
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_IE: IEs that should be included as part of scan
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES: Nested unsigned 32-bit attributes
+ * with frequencies to be scanned (in MHz)
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS: Nested attribute with SSIDs to be scanned
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES: Nested array attribute of supported
+ * rates to be included
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE: flag used to send probe requests
+ * at non CCK rate in 2GHz band
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS: Unsigned 32-bit scan flags
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE: Unsigned 64-bit cookie provided by the
+ * driver for the specific scan request
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_STATUS: Unsigned 8-bit status of the scan
+ * request decoded as in enum scan_status
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_MAC: 6-byte MAC address to use when randomisation
+ * scan flag is set
+ * @QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK: 6-byte MAC address mask to be used with
+ * randomisation
+ */
+enum qca_wlan_vendor_attr_scan {
+ QCA_WLAN_VENDOR_ATTR_SCAN_INVALID_PARAM = 0,
+ QCA_WLAN_VENDOR_ATTR_SCAN_IE,
+ QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES,
+ QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS,
+ QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES,
+ QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE,
+ QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS,
+ QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE,
+ QCA_WLAN_VENDOR_ATTR_SCAN_STATUS,
+ QCA_WLAN_VENDOR_ATTR_SCAN_MAC,
+ QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK,
+ QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SCAN_MAX =
+ QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST - 1
+};
+
+/**
+ * enum scan_status - Specifies the valid values the vendor scan attribute
+ * QCA_WLAN_VENDOR_ATTR_SCAN_STATUS can take
+ *
+ * @VENDOR_SCAN_STATUS_NEW_RESULTS: implies the vendor scan is successful with
+ * new scan results
+ * @VENDOR_SCAN_STATUS_ABORTED: implies the vendor scan was aborted in-between
+ */
+enum scan_status {
+ VENDOR_SCAN_STATUS_NEW_RESULTS,
+ VENDOR_SCAN_STATUS_ABORTED,
+ VENDOR_SCAN_STATUS_MAX,
+};
+
+/**
+ * enum qca_vendor_attr_ota_test - Specifies the values for vendor
+ * command QCA_NL80211_VENDOR_SUBCMD_OTA_TEST
+ * @QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE: enable ota test
+ */
+enum qca_vendor_attr_ota_test {
+ QCA_WLAN_VENDOR_ATTR_OTA_TEST_INVALID,
+ /* 8-bit unsigned value to indicate if OTA test is enabled */
+ QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_OTA_TEST_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX =
+ QCA_WLAN_VENDOR_ATTR_OTA_TEST_AFTER_LAST - 1
+};
+
+/**
+ * enum qca_vendor_attr_txpower_scale - vendor sub commands index
+ *
+ * @QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE: scaling value
+ */
+enum qca_vendor_attr_txpower_scale {
+ QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_INVALID,
+ /* 8-bit unsigned value to indicate the scaling of tx power */
+ QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX =
+ QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_AFTER_LAST - 1
+};
+
+/**
+ * enum qca_vendor_attr_txpower_decr_db - Attributes for TX power decrease
+ *
+ * These attributes are used with QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_DECR_DB.
+ */
+enum qca_vendor_attr_txpower_decr_db {
+ QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB_INVALID,
+ /* 8-bit unsigned value to indicate the reduction of TX power in dB for
+ * a virtual interface. */
+ QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB_MAX =
+ QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB_AFTER_LAST - 1
+};
+
+/* Attributes for data used by
+ * QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION and
+ * QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION subcommands.
+ */
+enum qca_wlan_vendor_attr_config {
+ QCA_WLAN_VENDOR_ATTR_CONFIG_INVALID = 0,
+ /* Unsigned 32-bit value to set the DTIM period.
+ * Whether the wifi chipset wakes at every dtim beacon or a multiple of
+ * the DTIM period. If DTIM is set to 3, the STA shall wake up every 3
+ * DTIM beacons.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_DTIM = 1,
+ /* Unsigned 32-bit value to set the wifi_iface stats averaging factor
+ * used to calculate statistics like average the TSF offset or average
+ * number of frame leaked.
+ * For instance, upon Beacon frame reception:
+ * current_avg = ((beacon_TSF - TBTT) * factor + previous_avg * (0x10000 - factor) ) / 0x10000
+ * For instance, when evaluating leaky APs:
+ * current_avg = ((num frame received within guard time) * factor + previous_avg * (0x10000 - factor)) / 0x10000
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR = 2,
+ /* Unsigned 32-bit value to configure guard time, i.e., when
+ * implementing IEEE power management based on frame control PM bit, how
+ * long the driver waits before shutting down the radio and after
+ * receiving an ACK frame for a Data frame with PM bit set.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME = 3,
+ /* Unsigned 32-bit value to change the FTM capability dynamically */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT = 4,
+ /* Unsigned 16-bit value to configure maximum TX rate dynamically */
+ QCA_WLAN_VENDOR_ATTR_CONF_TX_RATE = 5,
+ /* Unsigned 32-bit value to configure the number of continuous
+ * Beacon Miss which shall be used by the firmware to penalize
+ * the RSSI.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_PENALIZE_AFTER_NCONS_BEACON_MISS = 6,
+ /* Unsigned 8-bit value to configure the channel avoidance indication
+ * behavior. Firmware to send only one indication and ignore duplicate
+ * indications when set to avoid multiple Apps wakeups.
+ */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND = 7,
+ /* 8-bit unsigned value to configure the maximum TX MPDU for
+ * aggregation. */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION = 8,
+ /* 8-bit unsigned value to configure the maximum RX MPDU for
+ * aggregation. */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION = 9,
+ /* 8-bit unsigned value to configure the Non aggregrate/11g sw
+ * retry threshold (0 disable, 31 max). */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY = 10,
+ /* 8-bit unsigned value to configure the aggregrate sw
+ * retry threshold (0 disable, 31 max). */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY = 11,
+ /* 8-bit unsigned value to configure the MGMT frame
+ * retry threshold (0 disable, 31 max). */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY = 12,
+ /* 8-bit unsigned value to configure the CTRL frame
+ * retry threshold (0 disable, 31 max). */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY = 13,
+ /* 8-bit unsigned value to configure the propagation delay for
+ * 2G/5G band (0~63, units in us) */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY = 14,
+ /* Unsigned 32-bit value to configure the number of unicast TX fail
+ * packet count. The peer is disconnected once this threshold is
+ * reached. */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT = 15,
+ /* Attribute used to set scan default IEs to the driver.
+ *
+ * These IEs can be used by scan operations that will be initiated by
+ * the driver/firmware.
+ *
+ * For further scan requests coming to the driver, these IEs should be
+ * merged with the IEs received along with scan request coming to the
+ * driver. If a particular IE is present in the scan default IEs but not
+ * present in the scan request, then that IE should be added to the IEs
+ * sent in the Probe Request frames for that scan request. */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES = 16,
+ /* Unsigned 32-bit attribute for generic commands */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_COMMAND = 17,
+ /* Unsigned 32-bit value attribute for generic commands */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_VALUE = 18,
+ /* Unsigned 32-bit data attribute for generic command response */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA = 19,
+ /* Unsigned 32-bit length attribute for
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_LENGTH = 20,
+ /* Unsigned 32-bit flags attribute for
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_FLAGS = 21,
+ /* Unsigned 32-bit, defining the access policy.
+ * See enum qca_access_policy. Used with
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST. */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY = 22,
+ /* Sets the list of full set of IEs for which a specific access policy
+ * has to be applied. Used along with
+ * QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY to control the access.
+ * Zero length payload can be used to clear this access constraint. */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST = 23,
+ /* Unsigned 32-bit, specifies the interface index (netdev) for which the
+ * corresponding configurations are applied. If the interface index is
+ * not specified, the configurations are attributed to the respective
+ * wiphy. */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_IFINDEX = 24,
+ /* 8-bit unsigned value to trigger QPower: 1-Enable, 0-Disable */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER = 25,
+ /* 8-bit unsigned value to configure the driver and below layers to
+ * ignore the assoc disallowed set by APs while connecting
+ * 1-Ignore, 0-Don't ignore */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED = 26,
+ /* 32-bit unsigned value to trigger antenna diversity features:
+ * 1-Enable, 0-Disable */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA = 27,
+ /* 32-bit unsigned value to configure specific chain antenna */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN = 28,
+ /* 32-bit unsigned value to trigger cycle selftest
+ * 1-Enable, 0-Disable */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST = 29,
+ /* 32-bit unsigned to configure the cycle time of selftest
+ * the unit is micro-second */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL = 30,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_CONFIG_MAX =
+ QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_sap_config - Parameters for AP configuration
+ */
+enum qca_wlan_vendor_attr_sap_config {
+ QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_INVALID = 0,
+ /* 1 - reserved for QCA */
+ /* List of frequencies on which AP is expected to operate.
+ * This is irrespective of ACS configuration. This list is a priority
+ * based one and is looked for before the AP is created to ensure the
+ * best concurrency sessions (avoid MCC and use DBS/SCC) co-exist in
+ * the system.
+ */
+ QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST = 2,
+
+ QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX =
+ QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_sap_conditional_chan_switch - Parameters for AP
+ * conditional channel switch
+ */
+enum qca_wlan_vendor_attr_sap_conditional_chan_switch {
+ QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_INVALID = 0,
+ /* Priority based frequency list (an array of u32 values in host byte
+ * order) */
+ QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST = 1,
+ /* Status of the conditional switch (u32).
+ * 0: Success, Non-zero: Failure
+ */
+ QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_STATUS = 2,
+
+ QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX =
+ QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_gpio_attr - Parameters for GPIO configuration
+ */
+enum qca_wlan_gpio_attr {
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INVALID = 0,
+ /* Unsigned 32-bit attribute for GPIO command */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND,
+ /* Unsigned 32-bit attribute for GPIO PIN number to configure */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM,
+ /* Unsigned 32-bit attribute for GPIO value to configure */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_VALUE,
+ /* Unsigned 32-bit attribute for GPIO pull type */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE,
+ /* Unsigned 32-bit attribute for GPIO interrupt mode */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_LAST,
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MAX =
+ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_LAST - 1
+};
+
+/**
+ * enum qca_wlan_vendor_attr_get_hw_capability - Wi-Fi hardware capability
+ */
+enum qca_wlan_vendor_attr_get_hw_capability {
+ QCA_WLAN_VENDOR_ATTR_HW_CAPABILITY_INVALID,
+ /* Antenna isolation
+ * An attribute used in the response.
+ * The content of this attribute is encoded in a byte array. Each byte
+ * value is an antenna isolation value. The array length is the number
+ * of antennas.
+ */
+ QCA_WLAN_VENDOR_ATTR_ANTENNA_ISOLATION,
+ /* Request HW capability
+ * An attribute used in the request.
+ * The content of this attribute is a u32 array for one or more of
+ * hardware capabilities (attribute IDs) that are being requested. Each
+ * u32 value has a value from this
+ * enum qca_wlan_vendor_attr_get_hw_capability
+ * identifying which capabilities are requested.
+ */
+ QCA_WLAN_VENDOR_ATTR_GET_HW_CAPABILITY,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_HW_CAPABILITY_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_HW_CAPABILITY_MAX =
+ QCA_WLAN_VENDOR_ATTR_HW_CAPABILITY_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ll_stats_ext - Attributes for MAC layer monitoring
+ * offload which is an extension for LL_STATS.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CFG_PERIOD: Monitoring period. Unit in ms.
+ * If MAC counters do not exceed the threshold, FW will report monitored
+ * link layer counters periodically as this setting. The first report is
+ * always triggered by this timer.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CFG_THRESHOLD: It is a percentage (1-99).
+ * For each MAC layer counter, FW holds two copies. One is the current value.
+ * The other is the last report. Once a current counter's increment is larger
+ * than the threshold, FW will indicate that counter to host even if the
+ * monitoring timer does not expire.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_CHG: Peer STA power state change
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TID: TID of MSDU
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_NUM_MSDU: Count of MSDU with the same
+ * failure code.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_STATUS: TX failure code
+ * 1: TX packet discarded
+ * 2: No ACK
+ * 3: Postpone
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_MAC_ADDRESS: peer MAC address
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_STATE: Peer STA current state
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_GLOBAL: Global threshold.
+ * Threshold for all monitored parameters. If per counter dedicated threshold
+ * is not enabled, this threshold will take effect.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_EVENT_MODE: Indicate what triggers this
+ * event, PERORID_TIMEOUT == 1, THRESH_EXCEED == 0.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_ID: interface ID
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_ID: peer ID
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_BITMAP: bitmap for TX counters
+ * Bit0: TX counter unit in MSDU
+ * Bit1: TX counter unit in MPDU
+ * Bit2: TX counter unit in PPDU
+ * Bit3: TX counter unit in byte
+ * Bit4: Dropped MSDUs
+ * Bit5: Dropped Bytes
+ * Bit6: MPDU retry counter
+ * Bit7: MPDU failure counter
+ * Bit8: PPDU failure counter
+ * Bit9: MPDU aggregation counter
+ * Bit10: MCS counter for ACKed MPDUs
+ * Bit11: MCS counter for Failed MPDUs
+ * Bit12: TX Delay counter
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_BITMAP: bitmap for RX counters
+ * Bit0: MAC RX counter unit in MPDU
+ * Bit1: MAC RX counter unit in byte
+ * Bit2: PHY RX counter unit in PPDU
+ * Bit3: PHY RX counter unit in byte
+ * Bit4: Disorder counter
+ * Bit5: Retry counter
+ * Bit6: Duplication counter
+ * Bit7: Discard counter
+ * Bit8: MPDU aggregation size counter
+ * Bit9: MCS counter
+ * Bit10: Peer STA power state change (wake to sleep) counter
+ * Bit11: Peer STA power save counter, total time in PS mode
+ * Bit12: Probe request counter
+ * Bit13: Other management frames counter
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_CCA_BSS_BITMAP: bitmap for CCA
+ * Bit0: Idle time
+ * Bit1: TX time
+ * Bit2: time RX in current bss
+ * Bit3: Out of current bss time
+ * Bit4: Wireless medium busy time
+ * Bit5: RX in bad condition time
+ * Bit6: TX in bad condition time
+ * Bit7: time wlan card not available
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_SIGNAL_BITMAP: bitmap for signal
+ * Bit0: Per channel SNR counter
+ * Bit1: Per channel noise floor counter
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_NUM: number of peers
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_CHANNEL_NUM: number of channels
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_AC_RX_NUM: number of RX stats
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_CCA_BSS: per channel BSS CCA stats
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER: container for per PEER stats
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_MSDU: Number of total TX MSDUs
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_MPDU: Number of total TX MPDUs
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_PPDU: Number of total TX PPDUs
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_BYTES: bytes of TX data
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_DROP: Number of dropped TX packets
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_DROP_BYTES: Bytes dropped
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_RETRY: waiting time without an ACK
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_NO_ACK: number of MPDU not-ACKed
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_NO_BACK: number of PPDU not-ACKed
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_AGGR_NUM:
+ * aggregation stats buffer length
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_SUCC_MCS_NUM: length of mcs stats
+ * buffer for ACKed MPDUs.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_FAIL_MCS_NUM: length of mcs stats
+ * buffer for failed MPDUs.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_DELAY_ARRAY_SIZE:
+ * length of delay stats array.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_AGGR: TX aggregation stats
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_SUCC_MCS: MCS stats for ACKed MPDUs
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_FAIL_MCS: MCS stats for failed MPDUs
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_DELAY: tx delay stats
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU: MPDUs received
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_BYTES: bytes received
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_PPDU: PPDU received
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_PPDU_BYTES: PPDU bytes received
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_LOST: packets lost
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_RETRY: number of RX packets
+ * flagged as retransmissions
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_DUP: number of RX packets
+ * flagged as duplicated
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_DISCARD: number of RX
+ * packets discarded
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_AGGR_NUM: length of RX aggregation
+ * stats buffer.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MCS_NUM: length of RX mcs
+ * stats buffer.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MCS: RX mcs stats buffer
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_AGGR: aggregation stats buffer
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_TIMES: times STAs go to sleep
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_DURATION: STAs' total sleep time
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_PROBE_REQ: number of probe
+ * requests received
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MGMT: number of other mgmt
+ * frames received
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IDLE_TIME: Percentage of idle time
+ * there is no TX, nor RX, nor interference.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_TIME: percentage of time
+ * transmitting packets.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_TIME: percentage of time
+ * for receiving.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_BUSY: percentage of time
+ * interference detected.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_BAD: percentage of time
+ * receiving packets with errors.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_BAD: percentage of time
+ * TX no-ACK.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_NO_AVAIL: percentage of time
+ * the chip is unable to work in normal conditions.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IN_BSS_TIME: percentage of time
+ * receiving packets in current BSS.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_OUT_BSS_TIME: percentage of time
+ * receiving packets not in current BSS.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_ANT_NUM: number of antennas
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_SIGNAL:
+ * This is a container for per antenna signal stats.
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_ANT_SNR: per antenna SNR value
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_ANT_NF: per antenna NF value
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_RSSI_BEACON: RSSI of beacon
+ * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_SNR_BEACON: SNR of beacon
+ */
+enum qca_wlan_vendor_attr_ll_stats_ext {
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_INVALID = 0,
+
+ /* Attributes for configurations */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CFG_PERIOD,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_CFG_THRESHOLD,
+
+ /* Peer STA power state change */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_CHG,
+
+ /* TX failure event */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TID,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_NUM_MSDU,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_STATUS,
+
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_STATE,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_MAC_ADDRESS,
+
+ /* MAC counters */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_GLOBAL,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_EVENT_MODE,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_ID,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_ID,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_BITMAP,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_BITMAP,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_CCA_BSS_BITMAP,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_SIGNAL_BITMAP,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_NUM,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_CHANNEL_NUM,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_CCA_BSS,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER,
+
+ /* Sub-attributes for PEER_AC_TX */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_MSDU,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_MPDU,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_PPDU,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_BYTES,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_DROP,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_DROP_BYTES,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_RETRY,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_NO_ACK,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_NO_BACK,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_AGGR_NUM,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_SUCC_MCS_NUM,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_FAIL_MCS_NUM,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_AGGR,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_SUCC_MCS,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_FAIL_MCS,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_DELAY_ARRAY_SIZE,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_DELAY,
+
+ /* Sub-attributes for PEER_AC_RX */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_BYTES,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_PPDU,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_PPDU_BYTES,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_LOST,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_RETRY,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_DUP,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_DISCARD,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_AGGR_NUM,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MCS_NUM,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MCS,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_AGGR,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_TIMES,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_DURATION,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_PROBE_REQ,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MGMT,
+
+ /* Sub-attributes for CCA_BSS */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IDLE_TIME,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_TIME,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_TIME,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_BUSY,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_BAD,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_BAD,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_NO_AVAIL,
+
+ /* sub-attribute for BSS_RX_TIME */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IN_BSS_TIME,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_OUT_BSS_TIME,
+
+ /* Sub-attributes for PEER_SIGNAL */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_ANT_NUM,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_SIGNAL,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_ANT_SNR,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_ANT_NF,
+
+ /* Sub-attributes for IFACE_BSS */
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_RSSI_BEACON,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_SNR_BEACON,
+
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_LAST,
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_MAX =
+ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_LAST - 1
+};
+
+/* Attributes for FTM commands and events */
+
+/**
+ * enum qca_wlan_vendor_attr_loc_capa - Indoor location capabilities
+ *
+ * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAGS: Various flags. See
+ * enum qca_wlan_vendor_attr_loc_capa_flags.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_NUM_SESSIONS: Maximum number
+ * of measurement sessions that can run concurrently.
+ * Default is one session (no session concurrency).
+ * @QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_NUM_PEERS: The total number of unique
+ * peers that are supported in running sessions. For example,
+ * if the value is 8 and maximum number of sessions is 2, you can
+ * have one session with 8 unique peers, or 2 sessions with 4 unique
+ * peers each, and so on.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_NUM_BURSTS_EXP: Maximum number
+ * of bursts per peer, as an exponent (2^value). Default is 0,
+ * meaning no multi-burst support.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_MEAS_PER_BURST: Maximum number
+ * of measurement exchanges allowed in a single burst.
+ * @QCA_WLAN_VENDOR_ATTR_AOA_CAPA_SUPPORTED_TYPES: Supported AOA measurement
+ * types. A bit mask (unsigned 32 bit value), each bit corresponds
+ * to an AOA type as defined by enum qca_vendor_attr_aoa_type.
+ */
+enum qca_wlan_vendor_attr_loc_capa {
+ QCA_WLAN_VENDOR_ATTR_LOC_CAPA_INVALID,
+ QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAGS,
+ QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_NUM_SESSIONS,
+ QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_NUM_PEERS,
+ QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_NUM_BURSTS_EXP,
+ QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_MEAS_PER_BURST,
+ QCA_WLAN_VENDOR_ATTR_AOA_CAPA_SUPPORTED_TYPES,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_LOC_CAPA_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_LOC_CAPA_MAX =
+ QCA_WLAN_VENDOR_ATTR_LOC_CAPA_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_loc_capa_flags: Indoor location capability flags
+ *
+ * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_FTM_RESPONDER: Set if driver
+ * can be configured as an FTM responder (for example, an AP that
+ * services FTM requests). QCA_NL80211_VENDOR_SUBCMD_FTM_CFG_RESPONDER
+ * will be supported if set.
+ * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_FTM_INITIATOR: Set if driver
+ * can run FTM sessions. QCA_NL80211_VENDOR_SUBCMD_FTM_START_SESSION
+ * will be supported if set.
+* @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_ASAP: Set if FTM responder
+ * supports immediate (ASAP) response.
+ * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_AOA: Set if driver supports standalone
+ * AOA measurement using QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS.
+ * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_AOA_IN_FTM: Set if driver supports
+ * requesting AOA measurements as part of an FTM session.
+ */
+enum qca_wlan_vendor_attr_loc_capa_flags {
+ QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_FTM_RESPONDER = 1 << 0,
+ QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_FTM_INITIATOR = 1 << 1,
+ QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_ASAP = 1 << 2,
+ QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_AOA = 1 << 3,
+ QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_AOA_IN_FTM = 1 << 4,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ftm_peer_info: Information about
+ * a single peer in a measurement session.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_MAC_ADDR: The MAC address of the peer.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAGS: Various flags related
+ * to measurement. See enum qca_wlan_vendor_attr_ftm_peer_meas_flags.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_PARAMS: Nested attribute of
+ * FTM measurement parameters, as specified by IEEE P802.11-REVmc/D7.0
+ * 9.4.2.167. See enum qca_wlan_vendor_attr_ftm_meas_param for
+ * list of supported attributes.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_SECURE_TOKEN_ID: Initial token ID for
+ * secure measurement.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_AOA_BURST_PERIOD: Request AOA
+ * measurement every <value> bursts. If 0 or not specified,
+ * AOA measurements will be disabled for this peer.
+ */
+enum qca_wlan_vendor_attr_ftm_peer_info {
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_INVALID,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_MAC_ADDR,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAGS,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_PARAMS,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_SECURE_TOKEN_ID,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_AOA_BURST_PERIOD,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_MAX =
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ftm_peer_meas_flags: Measurement request flags,
+ * per-peer
+ *
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_ASAP: If set, request
+ * immediate (ASAP) response from peer.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_LCI: If set, request
+ * LCI report from peer. The LCI report includes the absolute
+ * location of the peer in "official" coordinates (similar to GPS).
+ * See IEEE P802.11-REVmc/D7.0, 11.24.6.7 for more information.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_LCR: If set, request
+ * Location civic report from peer. The LCR includes the location
+ * of the peer in free-form format. See IEEE P802.11-REVmc/D7.0,
+ * 11.24.6.7 for more information.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_SECURE: If set,
+ * request a secure measurement.
+ * QCA_WLAN_VENDOR_ATTR_FTM_PEER_SECURE_TOKEN_ID must also be provided.
+ */
+enum qca_wlan_vendor_attr_ftm_peer_meas_flags {
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_ASAP = 1 << 0,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_LCI = 1 << 1,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_LCR = 1 << 2,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_SECURE = 1 << 3,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ftm_meas_param: Measurement parameters
+ *
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PARAM_MEAS_PER_BURST: Number of measurements
+ * to perform in a single burst.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PARAM_NUM_BURSTS_EXP: Number of bursts to
+ * perform, specified as an exponent (2^value).
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PARAM_BURST_DURATION: Duration of burst
+ * instance, as specified in IEEE P802.11-REVmc/D7.0, 9.4.2.167.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PARAM_BURST_PERIOD: Time between bursts,
+ * as specified in IEEE P802.11-REVmc/D7.0, 9.4.2.167. Must
+ * be larger than QCA_WLAN_VENDOR_ATTR_FTM_PARAM_BURST_DURATION.
+ */
+enum qca_wlan_vendor_attr_ftm_meas_param {
+ QCA_WLAN_VENDOR_ATTR_FTM_PARAM_INVALID,
+ QCA_WLAN_VENDOR_ATTR_FTM_PARAM_MEAS_PER_BURST,
+ QCA_WLAN_VENDOR_ATTR_FTM_PARAM_NUM_BURSTS_EXP,
+ QCA_WLAN_VENDOR_ATTR_FTM_PARAM_BURST_DURATION,
+ QCA_WLAN_VENDOR_ATTR_FTM_PARAM_BURST_PERIOD,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_FTM_PARAM_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_FTM_PARAM_MAX =
+ QCA_WLAN_VENDOR_ATTR_FTM_PARAM_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ftm_peer_result: Per-peer results
+ *
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MAC_ADDR: MAC address of the reported
+ * peer.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS: Status of measurement
+ * request for this peer.
+ * See enum qca_wlan_vendor_attr_ftm_peer_result_status.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_FLAGS: Various flags related
+ * to measurement results for this peer.
+ * See enum qca_wlan_vendor_attr_ftm_peer_result_flags.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_VALUE_SECONDS: Specified when
+ * request failed and peer requested not to send an additional request
+ * for this number of seconds.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_LCI: LCI report when received
+ * from peer. In the format specified by IEEE P802.11-REVmc/D7.0,
+ * 9.4.2.22.10.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_LCR: Location civic report when
+ * received from peer. In the format specified by IEEE P802.11-REVmc/D7.0,
+ * 9.4.2.22.13.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MEAS_PARAMS: Reported when peer
+ * overridden some measurement request parameters. See
+ * enum qca_wlan_vendor_attr_ftm_meas_param.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_AOA_MEAS: AOA measurement
+ * for this peer. Same contents as @QCA_WLAN_VENDOR_ATTR_AOA_MEAS_RESULT.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MEAS: Array of measurement
+ * results. Each entry is a nested attribute defined
+ * by enum qca_wlan_vendor_attr_ftm_meas.
+ */
+enum qca_wlan_vendor_attr_ftm_peer_result {
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_INVALID,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MAC_ADDR,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_FLAGS,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_VALUE_SECONDS,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_LCI,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_LCR,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MEAS_PARAMS,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_AOA_MEAS,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MEAS,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MAX =
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ftm_peer_result_status
+ *
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_OK: Request sent ok and results
+ * will be provided. Peer may have overridden some measurement parameters,
+ * in which case overridden parameters will be report by
+ * QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MEAS_PARAM attribute.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_INCAPABLE: Peer is incapable
+ * of performing the measurement request. No more results will be sent
+ * for this peer in this session.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_FAILED: Peer reported request
+ * failed, and requested not to send an additional request for number
+ * of seconds specified by QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_VALUE_SECONDS
+ * attribute.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_INVALID: Request validation
+ * failed. Request was not sent over the air.
+ */
+enum qca_wlan_vendor_attr_ftm_peer_result_status {
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_OK,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_INCAPABLE,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_FAILED,
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_INVALID,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ftm_peer_result_flags: Various flags
+ * for measurement result, per-peer
+ *
+ * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_FLAG_DONE: If set,
+ * measurement completed for this peer. No more results will be reported
+ * for this peer in this session.
+ */
+enum qca_wlan_vendor_attr_ftm_peer_result_flags {
+ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_FLAG_DONE = 1 << 0,
+};
+
+/**
+ * enum qca_vendor_attr_loc_session_status: Session completion status code
+ *
+ * @QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_OK: Session completed
+ * successfully.
+ * @QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_ABORTED: Session aborted
+ * by request.
+ * @QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_INVALID: Session request
+ * was invalid and was not started.
+ * @QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_FAILED: Session had an error
+ * and did not complete normally (for example out of resources).
+ */
+enum qca_vendor_attr_loc_session_status {
+ QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_OK,
+ QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_ABORTED,
+ QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_INVALID,
+ QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_FAILED,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_ftm_meas: Single measurement data
+ *
+ * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T1: Time of departure (TOD) of FTM packet as
+ * recorded by responder, in picoseconds.
+ * See IEEE P802.11-REVmc/D7.0, 11.24.6.4 for more information.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T2: Time of arrival (TOA) of FTM packet at
+ * initiator, in picoseconds.
+ * See IEEE P802.11-REVmc/D7.0, 11.24.6.4 for more information.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T3: TOD of ACK packet as recorded by
+ * initiator, in picoseconds.
+ * See IEEE P802.11-REVmc/D7.0, 11.24.6.4 for more information.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T4: TOA of ACK packet at
+ * responder, in picoseconds.
+ * See IEEE P802.11-REVmc/D7.0, 11.24.6.4 for more information.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_RSSI: RSSI (signal level) as recorded
+ * during this measurement exchange. Optional and will be provided if
+ * the hardware can measure it.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_TOD_ERR: TOD error reported by
+ * responder. Not always provided.
+ * See IEEE P802.11-REVmc/D7.0, 9.6.8.33 for more information.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_TOA_ERR: TOA error reported by
+ * responder. Not always provided.
+ * See IEEE P802.11-REVmc/D7.0, 9.6.8.33 for more information.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_INITIATOR_TOD_ERR: TOD error measured by
+ * initiator. Not always provided.
+ * See IEEE P802.11-REVmc/D7.0, 9.6.8.33 for more information.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_INITIATOR_TOA_ERR: TOA error measured by
+ * initiator. Not always provided.
+ * See IEEE P802.11-REVmc/D7.0, 9.6.8.33 for more information.
+ * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_PAD: Dummy attribute for padding.
+ */
+enum qca_wlan_vendor_attr_ftm_meas {
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_INVALID,
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T1,
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T2,
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T3,
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T4,
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_RSSI,
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_TOD_ERR,
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_TOA_ERR,
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_INITIATOR_TOD_ERR,
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_INITIATOR_TOA_ERR,
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_PAD,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_MAX =
+ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_aoa_type - AOA measurement type
+ *
+ * @QCA_WLAN_VENDOR_ATTR_AOA_TYPE_TOP_CIR_PHASE: Phase of the strongest
+ * CIR (channel impulse response) path for each antenna.
+ * @QCA_WLAN_VENDOR_ATTR_AOA_TYPE_TOP_CIR_PHASE_AMP: Phase and amplitude
+ * of the strongest CIR path for each antenna.
+ */
+enum qca_wlan_vendor_attr_aoa_type {
+ QCA_WLAN_VENDOR_ATTR_AOA_TYPE_TOP_CIR_PHASE,
+ QCA_WLAN_VENDOR_ATTR_AOA_TYPE_TOP_CIR_PHASE_AMP,
+ QCA_WLAN_VENDOR_ATTR_AOA_TYPE_MAX
+};
+
+/**
+ * enum qca_wlan_vendor_attr_encryption_test - Attributes to
+ * validate encryption engine
+ *
+ * @QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_NEEDS_DECRYPTION: Flag attribute.
+ * This will be included if the request is for decryption; if not included,
+ * the request is treated as a request for encryption by default.
+ * @QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_CIPHER: Unsigned 32-bit value
+ * indicating the key cipher suite. Takes same values as
+ * NL80211_ATTR_KEY_CIPHER.
+ * @QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_KEYID: Unsigned 8-bit value
+ * Key Id to be used for encryption
+ * @QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_TK: Array of 8-bit values.
+ * Key (TK) to be used for encryption/decryption
+ * @QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_PN: Array of 8-bit values.
+ * Packet number to be specified for encryption/decryption
+ * 6 bytes for TKIP/CCMP/GCMP.
+ * @QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_DATA: Array of 8-bit values
+ * representing the 802.11 packet (header + payload + FCS) that
+ * needs to be encrypted/decrypted.
+ * Encrypted/decrypted response from the driver will also be sent
+ * to userspace with the same attribute.
+ */
+enum qca_wlan_vendor_attr_encryption_test {
+ QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_NEEDS_DECRYPTION,
+ QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_CIPHER,
+ QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_KEYID,
+ QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_TK,
+ QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_PN,
+ QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_DATA,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_MAX =
+ QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_AFTER_LAST - 1
};
#endif /* QCA_VENDOR_H */
/*
* Simultaneous authentication of equals
- * Copyright (c) 2012-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2012-2016, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
/* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */
bits = crypto_ec_prime_len_bits(sae->tmp->ec);
- sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
- prime, sae->tmp->prime_len, pwd_value, bits);
+ if (sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
+ prime, sae->tmp->prime_len, pwd_value, bits) < 0)
+ return -1;
if (bits % 8)
buf_shift_right(pwd_value, sizeof(pwd_value), 8 - bits % 8);
wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value",
wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
/* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */
- sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
- sae->tmp->dh->prime, sae->tmp->prime_len, pwd_value,
- bits);
- if (bits % 8)
- buf_shift_right(pwd_value, sizeof(pwd_value), 8 - bits % 8);
+ if (sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
+ sae->tmp->dh->prime, sae->tmp->prime_len, pwd_value,
+ bits) < 0)
+ return -1;
wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", pwd_value,
sae->tmp->prime_len);
crypto_bignum_mod(tmp, sae->tmp->order, tmp);
crypto_bignum_to_bin(tmp, val, sizeof(val), sae->tmp->prime_len);
wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN);
- sha256_prf(keyseed, sizeof(keyseed), "SAE KCK and PMK",
- val, sae->tmp->prime_len, keys, sizeof(keys));
+ if (sha256_prf(keyseed, sizeof(keyseed), "SAE KCK and PMK",
+ val, sae->tmp->prime_len, keys, sizeof(keys)) < 0)
+ goto fail;
os_memset(keyseed, 0, sizeof(keyseed));
os_memcpy(sae->tmp->kck, keys, SAE_KCK_LEN);
os_memcpy(sae->pmk, keys + SAE_KCK_LEN, SAE_PMK_LEN);
+ os_memcpy(sae->pmkid, val, SAE_PMKID_LEN);
os_memset(keys, 0, sizeof(keys));
wpa_hexdump_key(MSG_DEBUG, "SAE: KCK", sae->tmp->kck, SAE_KCK_LEN);
wpa_hexdump_key(MSG_DEBUG, "SAE: PMK", sae->pmk, SAE_PMK_LEN);
const u8 *end, const u8 **token,
size_t *token_len)
{
- if (*pos + (sae->tmp->ec ? 3 : 2) * sae->tmp->prime_len < end) {
+ if ((sae->tmp->ec ? 3 : 2) * sae->tmp->prime_len < end - *pos) {
size_t tlen = end - (*pos + (sae->tmp->ec ? 3 : 2) *
sae->tmp->prime_len);
wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", *pos, tlen);
{
struct crypto_bignum *peer_scalar;
- if (*pos + sae->tmp->prime_len > end) {
+ if (sae->tmp->prime_len > end - *pos) {
wpa_printf(MSG_DEBUG, "SAE: Not enough data for scalar");
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
{
u8 prime[SAE_MAX_ECC_PRIME_LEN];
- if (pos + 2 * sae->tmp->prime_len > end) {
+ if (2 * sae->tmp->prime_len > end - pos) {
wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
"commit-element");
return WLAN_STATUS_UNSPECIFIED_FAILURE;
struct crypto_bignum *res, *one;
const u8 one_bin[1] = { 0x01 };
- if (pos + sae->tmp->prime_len > end) {
+ if (sae->tmp->prime_len > end - pos) {
wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
"commit-element");
return WLAN_STATUS_UNSPECIFIED_FAILURE;
u16 res;
/* Check Finite Cyclic Group */
- if (pos + 2 > end)
+ if (end - pos < 2)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
res = sae_group_allowed(sae, allowed_groups, WPA_GET_LE16(pos));
if (res != WLAN_STATUS_SUCCESS)
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;
#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 */
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;
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);
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)
}
/* 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);
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;
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;
"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
#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)
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;
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 */
/* 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
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;
FD_ZERO(&rfds);
FD_SET(ctrl->s, &rfds);
res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
+ if (res < 0 && errno == EINTR)
+ continue;
if (res < 0)
return res;
if (FD_ISSET(ctrl->s, &rfds)) {
#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 "
#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 "
/* 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 "
#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 "
#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
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
};
if (ctrl == NULL)
return -1;
len = sizeof(buf);
- if (wpa_ctrl_request(ctrl, "STATUS", 6, buf, &len, NULL) < 0) {
+ if (wpa_ctrl_request(ctrl, "STATUS-NO_EVENTS", 16, buf, &len,
+ NULL) < 0) {
wpa_ctrl_close(ctrl);
return -1;
}
sha256.o \
sha256-prf.o \
sha256-tlsprf.o \
- sha256-internal.o
+ sha256-internal.o \
+ sha384-internal.o \
+ sha512-internal.o
LIB_OBJS += crypto_internal.o
LIB_OBJS += crypto_internal-cipher.o
u8 *pos = data;
int i, j, blocks;
+ if (TEST_FAIL())
+ return -1;
+
ctx = aes_encrypt_init(key, 16);
if (ctx == NULL)
return -1;
u8 *pos = data;
int i, j, blocks;
+ if (TEST_FAIL())
+ return -1;
+
ctx = aes_decrypt_init(key, 16);
if (ctx == NULL)
return -1;
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;
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)
* @key: 7 octets (in) (no parity bits included)
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;
#include "common.h"
#include "crypto.h"
#include "sha256_i.h"
+#include "sha384_i.h"
+#include "sha512_i.h"
#include "sha1_i.h"
#include "md5_i.h"
#ifdef CONFIG_SHA256
struct sha256_state sha256;
#endif /* CONFIG_SHA256 */
+#ifdef CONFIG_INTERNAL_SHA384
+ struct sha384_state sha384;
+#endif /* CONFIG_INTERNAL_SHA384 */
+#ifdef CONFIG_INTERNAL_SHA512
+ struct sha512_state sha512;
+#endif /* CONFIG_INTERNAL_SHA512 */
} u;
u8 key[64];
size_t key_len;
sha256_init(&ctx->u.sha256);
break;
#endif /* CONFIG_SHA256 */
+#ifdef CONFIG_INTERNAL_SHA384
+ case CRYPTO_HASH_ALG_SHA384:
+ sha384_init(&ctx->u.sha384);
+ break;
+#endif /* CONFIG_INTERNAL_SHA384 */
+#ifdef CONFIG_INTERNAL_SHA512
+ case CRYPTO_HASH_ALG_SHA512:
+ sha512_init(&ctx->u.sha512);
+ break;
+#endif /* CONFIG_INTERNAL_SHA512 */
case CRYPTO_HASH_ALG_HMAC_MD5:
if (key_len > sizeof(k_pad)) {
MD5Init(&ctx->u.md5);
sha256_process(&ctx->u.sha256, data, len);
break;
#endif /* CONFIG_SHA256 */
+#ifdef CONFIG_INTERNAL_SHA384
+ case CRYPTO_HASH_ALG_SHA384:
+ sha384_process(&ctx->u.sha384, data, len);
+ break;
+#endif /* CONFIG_INTERNAL_SHA384 */
+#ifdef CONFIG_INTERNAL_SHA512
+ case CRYPTO_HASH_ALG_SHA512:
+ sha512_process(&ctx->u.sha512, data, len);
+ break;
+#endif /* CONFIG_INTERNAL_SHA512 */
default:
break;
}
sha256_done(&ctx->u.sha256, mac);
break;
#endif /* CONFIG_SHA256 */
+#ifdef CONFIG_INTERNAL_SHA384
+ case CRYPTO_HASH_ALG_SHA384:
+ if (*len < 48) {
+ *len = 48;
+ os_free(ctx);
+ return -1;
+ }
+ *len = 48;
+ sha384_done(&ctx->u.sha384, mac);
+ break;
+#endif /* CONFIG_INTERNAL_SHA384 */
+#ifdef CONFIG_INTERNAL_SHA512
+ case CRYPTO_HASH_ALG_SHA512:
+ if (*len < 64) {
+ *len = 64;
+ os_free(ctx);
+ return -1;
+ }
+ *len = 64;
+ sha512_done(&ctx->u.sha512, mac);
+ break;
+#endif /* CONFIG_INTERNAL_SHA512 */
case CRYPTO_HASH_ALG_HMAC_MD5:
if (*len < 16) {
*len = 16;
#include "utils/includes.h"
#include "utils/common.h"
+#include "utils/module_tests.h"
#include "crypto/aes_siv.h"
#include "crypto/aes_wrap.h"
#include "crypto/aes.h"
}
-const struct {
+static const struct {
char *data;
u8 hash[32];
} tests[] = {
}
};
-const struct hmac_test {
+static const struct hmac_test {
u8 key[80];
size_t key_len;
u8 data[128];
const u8 *addr[2];
size_t len[2];
int errors = 0;
+ u8 *key;
for (i = 0; i < ARRAY_SIZE(tests); i++) {
wpa_printf(MSG_INFO, "SHA256 test case %d:", i + 1);
hash, sizeof(hash));
/* TODO: add proper test case for this */
+ key = os_malloc(8161);
+ if (key) {
+#ifdef CONFIG_HMAC_SHA256_KDF
+ int res;
+
+ res = hmac_sha256_kdf((u8 *) "secret", 6, "label",
+ (u8 *) "seed", 4, key, 8160);
+ if (res) {
+ wpa_printf(MSG_INFO,
+ "Unexpected hmac_sha256_kdf(outlen=8160) failure");
+ errors++;
+ }
+
+ res = hmac_sha256_kdf((u8 *) "secret", 6, "label",
+ (u8 *) "seed", 4, key, 8161);
+ if (res == 0) {
+ wpa_printf(MSG_INFO,
+ "Unexpected hmac_sha256_kdf(outlen=8161) success");
+ errors++;
+ }
+#endif /* CONFIG_HMAC_SHA256_KDF */
+
+ os_free(key);
+ }
+
if (!errors)
wpa_printf(MSG_INFO, "SHA256 test cases passed");
return errors;
}
+static int test_fips186_2_prf(void)
+{
+ /* http://csrc.nist.gov/encryption/dss/Examples-1024bit.pdf */
+ u8 xkey[] = {
+ 0xbd, 0x02, 0x9b, 0xbe, 0x7f, 0x51, 0x96, 0x0b,
+ 0xcf, 0x9e, 0xdb, 0x2b, 0x61, 0xf0, 0x6f, 0x0f,
+ 0xeb, 0x5a, 0x38, 0xb6
+ };
+ u8 w[] = {
+ 0x20, 0x70, 0xb3, 0x22, 0x3d, 0xba, 0x37, 0x2f,
+ 0xde, 0x1c, 0x0f, 0xfc, 0x7b, 0x2e, 0x3b, 0x49,
+ 0x8b, 0x26, 0x06, 0x14, 0x3c, 0x6c, 0x18, 0xba,
+ 0xcb, 0x0f, 0x6c, 0x55, 0xba, 0xbb, 0x13, 0x78,
+ 0x8e, 0x20, 0xd7, 0x37, 0xa3, 0x27, 0x51, 0x16
+ };
+ u8 buf[40];
+
+ wpa_printf(MSG_INFO,
+ "Testing EAP-SIM PRF (FIPS 186-2 + change notice 1)");
+ if (fips186_2_prf(xkey, sizeof(xkey), buf, sizeof(buf)) < 0 ||
+ os_memcmp(w, buf, sizeof(w)) != 0) {
+ wpa_printf(MSG_INFO, "fips186_2_prf failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+
static int test_ms_funcs(void)
{
#ifndef CONFIG_FIPS
test_md5() ||
test_sha1() ||
test_sha256() ||
+ test_fips186_2_prf() ||
test_ms_funcs())
ret = -1;
#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,
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
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;
}
#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 */
}
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;
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);
}
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);
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);
}
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);
- clen = data_len;
- if (EVP_EncryptUpdate(&ctx, data, &clen, data, data_len) != 1 ||
- clen != (int) data_len)
+ ctx = EVP_CIPHER_CTX_new();
+ if (!ctx)
return -1;
-
+ clen = data_len;
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);
- plen = data_len;
- if (EVP_DecryptUpdate(&ctx, data, &plen, data, data_len) != 1 ||
- plen != (int) data_len)
+ ctx = EVP_CIPHER_CTX_new();
+ if (!ctx)
return -1;
-
+ plen = data_len;
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;
}
struct crypto_cipher {
- EVP_CIPHER_CTX enc;
- EVP_CIPHER_CTX dec;
+ EVP_CIPHER_CTX *enc;
+ EVP_CIPHER_CTX *dec;
};
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;
}
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;
}
{
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;
}
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();
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();
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
}
struct crypto_hash {
- HMAC_CTX ctx;
+ HMAC_CTX *ctx;
};
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;
}
{
if (ctx == NULL)
return;
- HMAC_Update(&ctx->ctx, data, len);
+ HMAC_Update(ctx->ctx, data, 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) {
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;
}
int ret = -1;
size_t outlen, i;
+ if (TEST_FAIL())
+ return -1;
+
ctx = CMAC_CTX_new();
if (ctx == NULL)
return -1;
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;
}
{
int num_bytes, offset;
+ if (TEST_FAIL())
+ return -1;
+
if (padlen > buflen)
return -1;
int res;
BN_CTX *bnctx;
+ if (TEST_FAIL())
+ return -1;
+
bnctx = BN_CTX_new();
if (bnctx == NULL)
return -1;
BIGNUM *res;
BN_CTX *bnctx;
+ if (TEST_FAIL())
+ return -1;
bnctx = BN_CTX_new();
if (bnctx == NULL)
return -1;
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;
}
BN_CTX *bnctx;
+ if (TEST_FAIL())
+ return -1;
+
bnctx = BN_CTX_new();
if (bnctx == NULL)
return -1;
BN_CTX *bnctx;
+ if (TEST_FAIL())
+ return -1;
+
bnctx = BN_CTX_new();
if (bnctx == NULL)
return -1;
BIGNUM *exp = NULL, *tmp = NULL;
int res = -2;
+ if (TEST_FAIL())
+ return -2;
+
bnctx = BN_CTX_new();
if (bnctx == NULL)
return -2;
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);
int ret = -1;
int len = BN_num_bytes(e->prime);
+ if (TEST_FAIL())
+ return -1;
+
x_bn = BN_new();
y_bn = BN_new();
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);
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;
}
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;
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;
}
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) ||
{
BIGNUM *tmp, *tmp2, *y_sqr = NULL;
+ if (TEST_FAIL())
+ return NULL;
+
tmp = BN_new();
tmp2 = BN_new();
void * dh5_init(struct wpabuf **priv, struct wpabuf **publ)
{
+ wpabuf_free(*publ);
*publ = dh_init(dh_groups_get(5), priv);
if (*publ == NULL)
return NULL;
pv_len = dh->prime_len;
pv = wpabuf_alloc(pv_len);
- if (pv == NULL)
+ if (pv == NULL) {
+ wpabuf_clear_free(*priv);
+ *priv = NULL;
return NULL;
+ }
if (crypto_mod_exp(dh->generator, dh->generator_len,
wpabuf_head(*priv), wpabuf_len(*priv),
dh->prime, dh->prime_len, wpabuf_mhead(pv),
&pv_len) < 0) {
wpabuf_clear_free(pv);
wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed");
+ wpabuf_clear_free(*priv);
+ *priv = NULL;
return NULL;
}
wpabuf_put(pv, pv_len);
{
SHA_CTX context;
os_memset(&context, 0, sizeof(context));
+#if defined(OPENSSL_IS_BORINGSSL) && !defined(ANDROID)
+ context.h[0] = state[0];
+ context.h[1] = state[1];
+ context.h[2] = state[2];
+ context.h[3] = state[3];
+ context.h[4] = state[4];
+ SHA1_Transform(&context, data);
+ state[0] = context.h[0];
+ state[1] = context.h[1];
+ state[2] = context.h[2];
+ state[3] = context.h[3];
+ state[4] = context.h[4];
+#else
context.h0 = state[0];
context.h1 = state[1];
context.h2 = state[2];
state[2] = context.h2;
state[3] = context.h3;
state[4] = context.h4;
+#endif
}
/* w_i = G(t, XVAL) */
os_memcpy(_t, t, 20);
sha1_transform(_t, xkey);
- _t[0] = host_to_be32(_t[0]);
- _t[1] = host_to_be32(_t[1]);
- _t[2] = host_to_be32(_t[2]);
- _t[3] = host_to_be32(_t[3]);
- _t[4] = host_to_be32(_t[4]);
- os_memcpy(xpos, _t, 20);
+ WPA_PUT_BE32(xpos, _t[0]);
+ WPA_PUT_BE32(xpos + 4, _t[1]);
+ WPA_PUT_BE32(xpos + 8, _t[2]);
+ WPA_PUT_BE32(xpos + 12, _t[3]);
+ WPA_PUT_BE32(xpos + 16, _t[4]);
/* XKEY = (1 + XKEY + w_i) mod 2^b */
carry = 1;
MD4_CTX ctx;
size_t i;
+ if (TEST_FAIL())
+ return -1;
+
MD4Init(&ctx);
for (i = 0; i < num_elem; i++)
MD4Update(&ctx, addr[i], len[i]);
MD5_CTX ctx;
size_t i;
+ if (TEST_FAIL())
+ return -1;
+
MD5Init(&ctx);
for (i = 0; i < num_elem; i++)
MD5Update(&ctx, addr[i], len[i]);
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;
SHA1_CTX ctx;
size_t i;
+ if (TEST_FAIL())
+ return -1;
+
SHA1Init(&ctx);
for (i = 0; i < num_elem; i++)
SHA1Update(&ctx, addr[i], len[i]);
255);
}
/* Wipe variables */
- i = 0;
os_memset(context->buffer, 0, 64);
os_memset(context->state, 0, 20);
os_memset(context->count, 0, 8);
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]))
/*
* 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.
* @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);
}
* @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;
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;
}
os_memset(hash, 0, sizeof(hash));
+
+ return 0;
}
/*
* 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.
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);
--- /dev/null
+/*
+ * SHA-384 hash implementation and interface functions
+ * Copyright (c) 2015, Pali Rohár <pali.rohar@gmail.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "sha384_i.h"
+#include "crypto.h"
+
+
+/**
+ * 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 of failure
+ */
+int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len,
+ u8 *mac)
+{
+ struct sha384_state ctx;
+ size_t i;
+
+ sha384_init(&ctx);
+ for (i = 0; i < num_elem; i++)
+ if (sha384_process(&ctx, addr[i], len[i]))
+ return -1;
+ if (sha384_done(&ctx, mac))
+ return -1;
+ return 0;
+}
+
+
+/* ===== start - public domain SHA384 implementation ===== */
+
+/* This is based on SHA384 implementation in LibTomCrypt that was released into
+ * public domain by Tom St Denis. */
+
+#define CONST64(n) n ## ULL
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+void sha384_init(struct sha384_state *md)
+{
+ md->curlen = 0;
+ md->length = 0;
+ md->state[0] = CONST64(0xcbbb9d5dc1059ed8);
+ md->state[1] = CONST64(0x629a292a367cd507);
+ md->state[2] = CONST64(0x9159015a3070dd17);
+ md->state[3] = CONST64(0x152fecd8f70e5939);
+ md->state[4] = CONST64(0x67332667ffc00b31);
+ md->state[5] = CONST64(0x8eb44a8768581511);
+ md->state[6] = CONST64(0xdb0c2e0d64f98fa7);
+ md->state[7] = CONST64(0x47b5481dbefa4fa4);
+}
+
+int sha384_process(struct sha384_state *md, const unsigned char *in,
+ unsigned long inlen)
+{
+ return sha512_process(md, in, inlen);
+}
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (48 bytes)
+ @return CRYPT_OK if successful
+*/
+int sha384_done(struct sha384_state *md, unsigned char *out)
+{
+ unsigned char buf[64];
+
+ if (md->curlen >= sizeof(md->buf))
+ return -1;
+
+ if (sha512_done(md, buf) != 0)
+ return -1;
+
+ os_memcpy(out, buf, 48);
+ return 0;
+}
+
+/* ===== end - public domain SHA384 implementation ===== */
--- /dev/null
+/*
+ * SHA-384 internal definitions
+ * Copyright (c) 2015, Pali Rohár <pali.rohar@gmail.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef SHA384_I_H
+#define SHA384_I_H
+
+#include "sha512_i.h"
+
+#define SHA384_BLOCK_SIZE SHA512_BLOCK_SIZE
+
+#define sha384_state sha512_state
+
+void sha384_init(struct sha384_state *md);
+int sha384_process(struct sha384_state *md, const unsigned char *in,
+ unsigned long inlen);
+int sha384_done(struct sha384_state *md, unsigned char *out);
+
+#endif /* SHA384_I_H */
--- /dev/null
+/*
+ * SHA-512 hash implementation and interface functions
+ * Copyright (c) 2015, Pali Rohár <pali.rohar@gmail.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "sha512_i.h"
+#include "crypto.h"
+
+
+/**
+ * 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 of failure
+ */
+int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len,
+ u8 *mac)
+{
+ struct sha512_state ctx;
+ size_t i;
+
+ sha512_init(&ctx);
+ for (i = 0; i < num_elem; i++)
+ if (sha512_process(&ctx, addr[i], len[i]))
+ return -1;
+ if (sha512_done(&ctx, mac))
+ return -1;
+ return 0;
+}
+
+
+/* ===== start - public domain SHA512 implementation ===== */
+
+/* This is based on SHA512 implementation in LibTomCrypt that was released into
+ * public domain by Tom St Denis. */
+
+#define CONST64(n) n ## ULL
+
+/* the K array */
+static const u64 K[80] = {
+ CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd),
+ CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc),
+ CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019),
+ CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118),
+ CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe),
+ CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2),
+ CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1),
+ CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694),
+ CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3),
+ CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65),
+ CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483),
+ CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5),
+ CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210),
+ CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4),
+ CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725),
+ CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70),
+ CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926),
+ CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df),
+ CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8),
+ CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b),
+ CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001),
+ CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30),
+ CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910),
+ CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8),
+ CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53),
+ CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8),
+ CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb),
+ CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3),
+ CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60),
+ CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec),
+ CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9),
+ CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b),
+ CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207),
+ CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178),
+ CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6),
+ CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b),
+ CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493),
+ CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c),
+ CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a),
+ CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817)
+};
+
+/* Various logical functions */
+#define Ch(x,y,z) (z ^ (x & (y ^ z)))
+#define Maj(x,y,z) (((x | y) & z) | (x & y))
+#define S(x, n) ROR64c(x, n)
+#define R(x, n) (((x) & CONST64(0xFFFFFFFFFFFFFFFF)) >> ((u64) n))
+#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39))
+#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41))
+#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7))
+#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6))
+#ifndef MIN
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+#endif
+
+#define ROR64c(x, y) \
+ ( ((((x) & CONST64(0xFFFFFFFFFFFFFFFF)) >> ((u64) (y) & CONST64(63))) | \
+ ((x) << ((u64) (64 - ((y) & CONST64(63)))))) & \
+ CONST64(0xFFFFFFFFFFFFFFFF))
+
+/* compress 1024-bits */
+static int sha512_compress(struct sha512_state *md, unsigned char *buf)
+{
+ u64 S[8], W[80], t0, t1;
+ int i;
+
+ /* copy state into S */
+ for (i = 0; i < 8; i++) {
+ S[i] = md->state[i];
+ }
+
+ /* copy the state into 1024-bits into W[0..15] */
+ for (i = 0; i < 16; i++)
+ W[i] = WPA_GET_BE64(buf + (8 * i));
+
+ /* fill W[16..79] */
+ for (i = 16; i < 80; i++) {
+ W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) +
+ W[i - 16];
+ }
+
+ /* Compress */
+ for (i = 0; i < 80; i++) {
+ t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i];
+ t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]);
+ S[7] = S[6];
+ S[6] = S[5];
+ S[5] = S[4];
+ S[4] = S[3] + t0;
+ S[3] = S[2];
+ S[2] = S[1];
+ S[1] = S[0];
+ S[0] = t0 + t1;
+ }
+
+ /* feedback */
+ for (i = 0; i < 8; i++) {
+ md->state[i] = md->state[i] + S[i];
+ }
+
+ return 0;
+}
+
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+void sha512_init(struct sha512_state *md)
+{
+ md->curlen = 0;
+ md->length = 0;
+ md->state[0] = CONST64(0x6a09e667f3bcc908);
+ md->state[1] = CONST64(0xbb67ae8584caa73b);
+ md->state[2] = CONST64(0x3c6ef372fe94f82b);
+ md->state[3] = CONST64(0xa54ff53a5f1d36f1);
+ md->state[4] = CONST64(0x510e527fade682d1);
+ md->state[5] = CONST64(0x9b05688c2b3e6c1f);
+ md->state[6] = CONST64(0x1f83d9abfb41bd6b);
+ md->state[7] = CONST64(0x5be0cd19137e2179);
+}
+
+
+/**
+ Process a block of memory though the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+int sha512_process(struct sha512_state *md, const unsigned char *in,
+ unsigned long inlen)
+{
+ unsigned long n;
+
+ if (md->curlen >= sizeof(md->buf))
+ return -1;
+
+ while (inlen > 0) {
+ if (md->curlen == 0 && inlen >= SHA512_BLOCK_SIZE) {
+ if (sha512_compress(md, (unsigned char *) in) < 0)
+ return -1;
+ md->length += SHA512_BLOCK_SIZE * 8;
+ in += SHA512_BLOCK_SIZE;
+ inlen -= SHA512_BLOCK_SIZE;
+ } else {
+ n = MIN(inlen, (SHA512_BLOCK_SIZE - md->curlen));
+ os_memcpy(md->buf + md->curlen, in, n);
+ md->curlen += n;
+ in += n;
+ inlen -= n;
+ if (md->curlen == SHA512_BLOCK_SIZE) {
+ if (sha512_compress(md, md->buf) < 0)
+ return -1;
+ md->length += 8 * SHA512_BLOCK_SIZE;
+ md->curlen = 0;
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (64 bytes)
+ @return CRYPT_OK if successful
+*/
+int sha512_done(struct sha512_state *md, unsigned char *out)
+{
+ int i;
+
+ if (md->curlen >= sizeof(md->buf))
+ return -1;
+
+ /* increase the length of the message */
+ md->length += md->curlen * CONST64(8);
+
+ /* append the '1' bit */
+ md->buf[md->curlen++] = (unsigned char) 0x80;
+
+ /* if the length is currently above 112 bytes we append zeros
+ * then compress. Then we can fall back to padding zeros and length
+ * encoding like normal.
+ */
+ if (md->curlen > 112) {
+ while (md->curlen < 128) {
+ md->buf[md->curlen++] = (unsigned char) 0;
+ }
+ sha512_compress(md, md->buf);
+ md->curlen = 0;
+ }
+
+ /* pad up to 120 bytes of zeroes
+ * note: that from 112 to 120 is the 64 MSB of the length. We assume
+ * that you won't hash > 2^64 bits of data... :-)
+ */
+ while (md->curlen < 120) {
+ md->buf[md->curlen++] = (unsigned char) 0;
+ }
+
+ /* store length */
+ WPA_PUT_BE64(md->buf + 120, md->length);
+ sha512_compress(md, md->buf);
+
+ /* copy output */
+ for (i = 0; i < 8; i++)
+ WPA_PUT_BE64(out + (8 * i), md->state[i]);
+
+ return 0;
+}
+
+/* ===== end - public domain SHA512 implementation ===== */
--- /dev/null
+/*
+ * SHA-512 internal definitions
+ * Copyright (c) 2015, Pali Rohár <pali.rohar@gmail.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef SHA512_I_H
+#define SHA512_I_H
+
+#define SHA512_BLOCK_SIZE 128
+
+struct sha512_state {
+ u64 length, state[8];
+ u32 curlen;
+ u8 buf[SHA512_BLOCK_SIZE];
+};
+
+void sha512_init(struct sha512_state *md);
+int sha512_process(struct sha512_state *md, const unsigned char *in,
+ unsigned long inlen);
+int sha512_done(struct sha512_state *md, unsigned char *out);
+
+#endif /* SHA512_I_H */
#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 X509; /* from OpenSSL */
* @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
* @server_cert_cb: Optional callback to be used to validate server certificate
* when no CA or path was specified.
* @server_cert_ctx: Optional context arg for server_cert_cb.
unsigned int flags;
const char *ocsp_stapling_response;
-
- /**
- * If non-null, specifies a callback method that can be used to
- * confirm the validity of a peer certificate.
- */
+ const char *ocsp_stapling_response_multi;
int (*server_cert_cb)(int ok_so_far, X509* cert, void *ca_ctx);
void *server_cert_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_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_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_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)
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 */,
};
/**
union tls_event_data *data);
void *cb_ctx;
int cert_in_cb;
+
+ char *ocsp_stapling_response;
};
struct tls_connection {
if (global->params_set)
gnutls_certificate_free_credentials(global->xcred);
os_free(global->session_data);
+ os_free(global->ocsp_stapling_response);
os_free(global);
}
if (conn == NULL || params == NULL)
return -1;
+ if (params->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
+ wpa_printf(MSG_INFO,
+ "GnuTLS: ocsp=3 not supported");
+ return -1;
+ }
+
+ if (params->flags & TLS_CONN_EXT_CERT_CHECK) {
+ wpa_printf(MSG_INFO,
+ "GnuTLS: tls_ext_cert_check=1 not supported");
+ return -1;
+ }
+
if (params->subject_match) {
wpa_printf(MSG_INFO, "GnuTLS: subject_match not supported");
return -1;
}
+#if GNUTLS_VERSION_NUMBER >= 0x030103
+static int server_ocsp_status_req(gnutls_session_t session, void *ptr,
+ gnutls_datum_t *resp)
+{
+ struct tls_global *global = ptr;
+ char *cached;
+ size_t len;
+
+ if (!global->ocsp_stapling_response) {
+ wpa_printf(MSG_DEBUG, "GnuTLS: OCSP status callback - no response configured");
+ return GNUTLS_E_NO_CERTIFICATE_STATUS;
+ }
+
+ cached = os_readfile(global->ocsp_stapling_response, &len);
+ if (!cached) {
+ wpa_printf(MSG_DEBUG,
+ "GnuTLS: OCSP status callback - could not read response file (%s)",
+ global->ocsp_stapling_response);
+ return GNUTLS_E_NO_CERTIFICATE_STATUS;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "GnuTLS: OCSP status callback - send cached response");
+ resp->data = gnutls_malloc(len);
+ if (!resp->data) {
+ os_free(resp);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ os_memcpy(resp->data, cached, len);
+ resp->size = len;
+ os_free(cached);
+
+ return GNUTLS_E_SUCCESS;
+}
+#endif /* 3.1.3 */
+
+
int tls_global_set_params(void *tls_ctx,
const struct tls_connection_params *params)
{
}
}
+#if GNUTLS_VERSION_NUMBER >= 0x030103
+ os_free(global->ocsp_stapling_response);
+ if (params->ocsp_stapling_response)
+ global->ocsp_stapling_response =
+ os_strdup(params->ocsp_stapling_response);
+ else
+ global->ocsp_stapling_response = NULL;
+ gnutls_certificate_set_ocsp_status_request_function(
+ global->xcred, server_ocsp_status_req, global);
+#endif /* 3.1.3 */
+
global->params_set = 1;
return 0;
}
-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 tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
+ const char *label, u8 *out, size_t out_len)
{
- if (conn == NULL || conn->session == NULL || skip_keyblock)
+ if (conn == NULL || conn->session == NULL)
return -1;
return gnutls_prf(conn->session, os_strlen(label), label,
- server_random_first, 0, NULL, out_len, (char *) out);
+ 0 /* client_random first */, 0, NULL, out_len,
+ (char *) out);
+}
+
+
+int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
+ u8 *out, size_t out_len)
+{
+ return -1;
}
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 {
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;
}
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);
}
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
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;
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 */
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;
}
-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;
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)
}
+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,
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;
}
}
-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 tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
+ const char *label, u8 *out, size_t out_len)
+{
+ return -1;
+}
+
+
+int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
+ u8 *out, size_t out_len)
{
return -1;
}
#include <openssl/ssl.h>
#include <openssl/err.h>
+#include <openssl/opensslv.h>
#include <openssl/pkcs12.h>
#include <openssl/x509v3.h>
#ifndef OPENSSL_NO_ENGINE
#include "sha1.h"
#include "sha256.h"
#include "tls.h"
+#include "tls_openssl.h"
-#if OPENSSL_VERSION_NUMBER < 0x10000000L
-/* ERR_remove_thread_state replaces ERR_remove_state and the latter is
- * deprecated. However, OpenSSL 0.9.8 doesn't include
- * ERR_remove_thread_state. */
-#define ERR_remove_thread_state(tid) ERR_remove_state(0)
+#if !defined(CONFIG_FIPS) && \
+ (defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || \
+ defined(EAP_SERVER_FAST))
+#define OPENSSL_NEED_EAP_FAST_PRF
#endif
#if defined(OPENSSL_IS_BORINGSSL)
#endif /* OPENSSL_NO_TLSEXT */
#endif /* SSL_set_tlsext_status_type */
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L || \
+ defined(LIBRESSL_VERSION_NUMBER)) && \
+ !defined(BORINGSSL_API_VERSION)
+/*
+ * SSL_get_client_random() and SSL_get_server_random() were added in OpenSSL
+ * 1.1.0 and newer BoringSSL revisions. Provide compatibility wrappers for
+ * older versions.
+ */
+
+static size_t SSL_get_client_random(const SSL *ssl, unsigned char *out,
+ size_t outlen)
+{
+ if (!ssl->s3 || outlen < SSL3_RANDOM_SIZE)
+ return 0;
+ os_memcpy(out, ssl->s3->client_random, SSL3_RANDOM_SIZE);
+ return SSL3_RANDOM_SIZE;
+}
+
+
+static size_t SSL_get_server_random(const SSL *ssl, unsigned char *out,
+ size_t outlen)
+{
+ if (!ssl->s3 || outlen < SSL3_RANDOM_SIZE)
+ return 0;
+ os_memcpy(out, ssl->s3->server_random, SSL3_RANDOM_SIZE);
+ return SSL3_RANDOM_SIZE;
+}
+
+
+#ifdef OPENSSL_NEED_EAP_FAST_PRF
+static size_t SSL_SESSION_get_master_key(const SSL_SESSION *session,
+ unsigned char *out, size_t outlen)
+{
+ if (!session || session->master_key_length < 0 ||
+ (size_t) session->master_key_length > outlen)
+ return 0;
+ if ((size_t) session->master_key_length < outlen)
+ outlen = session->master_key_length;
+ os_memcpy(out, session->master_key, outlen);
+ return outlen;
+}
+#endif /* OPENSSL_NEED_EAP_FAST_PRF */
+
+#endif
+
#ifdef ANDROID
#include <openssl/pem.h>
#include <keystore/keystore_get.h>
free(value);
return bio;
}
+
+
+static int tls_add_ca_from_keystore(X509_STORE *ctx, const char *key_alias)
+{
+ BIO *bio = BIO_from_keystore(key_alias);
+ STACK_OF(X509_INFO) *stack = NULL;
+ stack_index_t i;
+
+ if (bio) {
+ stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
+ BIO_free(bio);
+ }
+
+ if (!stack) {
+ wpa_printf(MSG_WARNING, "TLS: Failed to parse certificate: %s",
+ key_alias);
+ return -1;
+ }
+
+ for (i = 0; i < sk_X509_INFO_num(stack); ++i) {
+ X509_INFO *info = sk_X509_INFO_value(stack, i);
+
+ if (info->x509)
+ X509_STORE_add_cert(ctx, info->x509);
+ if (info->crl)
+ X509_STORE_add_crl(ctx, info->crl);
+ }
+
+ sk_X509_INFO_pop_free(stack, X509_INFO_free);
+
+ return 0;
+}
+
+
+static int tls_add_ca_from_keystore_encoded(X509_STORE *ctx,
+ const char *encoded_key_alias)
+{
+ int rc = -1;
+ int len = os_strlen(encoded_key_alias);
+ unsigned char *decoded_alias;
+
+ if (len & 1) {
+ wpa_printf(MSG_WARNING, "Invalid hex-encoded alias: %s",
+ encoded_key_alias);
+ return rc;
+ }
+
+ decoded_alias = os_malloc(len / 2 + 1);
+ if (decoded_alias) {
+ if (!hexstr2bin(encoded_key_alias, decoded_alias, len / 2)) {
+ decoded_alias[len / 2] = '\0';
+ rc = tls_add_ca_from_keystore(
+ ctx, (const char *) decoded_alias);
+ }
+ os_free(decoded_alias);
+ }
+
+ return rc;
+}
+
#endif /* ANDROID */
static int tls_openssl_ref_count = 0;
SSL_CTX *ssl_ctx;
SSL *ssl;
BIO *ssl_in, *ssl_out;
-#ifndef OPENSSL_NO_ENGINE
+#if defined(ANDROID) || !defined(OPENSSL_NO_ENGINE)
ENGINE *engine; /* functional reference to the engine */
EVP_PKEY *private_key; /* the private key if using engine */
#endif /* OPENSSL_NO_ENGINE */
X509 *peer_issuer;
X509 *peer_issuer_issuer;
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
unsigned char client_random[SSL3_RANDOM_SIZE];
unsigned char server_random[SSL3_RANDOM_SIZE];
-#endif
int (*server_cert_cb)(int ok_so_far, X509* cert, void *ca_ctx);
void *server_cert_ctx;
wpa_printf(MSG_DEBUG, "OpenSSL: Loaded CA certificate for "
"system certificate store: subject='%s'", buf);
- if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) {
+ if (!X509_STORE_add_cert(SSL_CTX_get_cert_store(ssl_ctx),
+ cert)) {
tls_show_errors(MSG_WARNING, __func__,
"Failed to add ca_cert to OpenSSL "
"certificate store");
engine = ENGINE_by_id(id);
if (engine) {
- ENGINE_free(engine);
wpa_printf(MSG_DEBUG, "ENGINE: engine '%s' is already "
"available", id);
- return 0;
+ /*
+ * If it was auto-loaded by ENGINE_by_id() we might still
+ * need to tell it which PKCS#11 module to use in legacy
+ * (non-p11-kit) environments. Do so now; even if it was
+ * properly initialised before, setting it again will be
+ * harmless.
+ */
+ goto found;
}
ERR_clear_error();
id, ERR_error_string(ERR_get_error(), NULL));
return -1;
}
-
+ found:
while (post && post[0]) {
wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", post[0], post[1]);
if (ENGINE_ctrl_cmd_string(engine, post[0], post[1], 0) == 0) {
}
#endif /* OPENSSL_FIPS */
#endif /* CONFIG_FIPS */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
SSL_load_error_strings();
SSL_library_init();
#ifndef OPENSSL_NO_SHA256
#endif /* OPENSSL_NO_RC2 */
PKCS12_PBE_add();
#endif /* PKCS12_FUNCS */
+#endif /* < 1.1.0 */
} else {
context = tls_context_new(conf);
if (context == NULL)
os_free(tls_global);
tls_global = NULL;
}
+ os_free(data);
return NULL;
}
data->ssl = ssl;
tls_openssl_ref_count--;
if (tls_openssl_ref_count == 0) {
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
// The next four lines, and two more just below, deal with de-initializing
// global state in the OpenSSL engine. We (Moonshot) don't want that, since
// we use OpenSSL elsewhere in our apps (i.e., not only via hostap / libeap.)
ERR_remove_thread_state(NULL);
//// ERR_free_strings();
//// EVP_cleanup();
+#endif /* < 1.1.0 */
os_free(tls_global->ocsp_stapling_response);
tls_global->ocsp_stapling_response = NULL;
os_free(tls_global);
#endif /* OPENSSL_NO_ENGINE */
+#ifdef ANDROID
+/* EVP_PKEY_from_keystore comes from system/security/keystore-engine. */
+EVP_PKEY * EVP_PKEY_from_keystore(const char *key_id);
+#endif /* ANDROID */
+
static int tls_engine_init(struct tls_connection *conn, const char *engine_id,
const char *pin, const char *key_id,
const char *cert_id, const char *ca_cert_id)
{
+#if defined(ANDROID) && defined(OPENSSL_IS_BORINGSSL)
+#if !defined(OPENSSL_NO_ENGINE)
+#error "This code depends on OPENSSL_NO_ENGINE being defined by BoringSSL."
+#endif
+ if (!key_id)
+ return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
+ conn->engine = NULL;
+ conn->private_key = EVP_PKEY_from_keystore(key_id);
+ if (!conn->private_key) {
+ wpa_printf(MSG_ERROR,
+ "ENGINE: cannot load private key with id '%s' [%s]",
+ key_id,
+ ERR_error_string(ERR_get_error(), NULL));
+ return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
+ }
+#endif /* ANDROID && OPENSSL_IS_BORINGSSL */
+
#ifndef OPENSSL_NO_ENGINE
int ret = -1;
if (engine_id == NULL) {
static void tls_engine_deinit(struct tls_connection *conn)
{
-#ifndef OPENSSL_NO_ENGINE
+#if defined(ANDROID) || !defined(OPENSSL_NO_ENGINE)
wpa_printf(MSG_DEBUG, "ENGINE: engine deinit");
if (conn->private_key) {
EVP_PKEY_free(conn->private_key);
conn->private_key = NULL;
}
if (conn->engine) {
+#if !defined(OPENSSL_IS_BORINGSSL)
ENGINE_finish(conn->engine);
+#endif /* !OPENSSL_IS_BORINGSSL */
conn->engine = NULL;
}
-#endif /* OPENSSL_NO_ENGINE */
+#endif /* ANDROID || !OPENSSL_NO_ENGINE */
}
}
+static const char * openssl_content_type(int content_type)
+{
+ switch (content_type) {
+ case 20:
+ return "change cipher spec";
+ case 21:
+ return "alert";
+ case 22:
+ return "handshake";
+ case 23:
+ return "application data";
+ case 24:
+ return "heartbeat";
+ case 256:
+ return "TLS header info"; /* pseudo content type */
+ default:
+ return "?";
+ }
+}
+
+
+static const char * openssl_handshake_type(int content_type, const u8 *buf,
+ size_t len)
+{
+ if (content_type != 22 || !buf || len == 0)
+ return "";
+ switch (buf[0]) {
+ case 0:
+ return "hello request";
+ case 1:
+ return "client hello";
+ case 2:
+ return "server hello";
+ case 4:
+ return "new session ticket";
+ case 11:
+ return "certificate";
+ case 12:
+ return "server key exchange";
+ case 13:
+ return "certificate request";
+ case 14:
+ return "server hello done";
+ case 15:
+ return "certificate verify";
+ case 16:
+ return "client key exchange";
+ case 20:
+ return "finished";
+ case 21:
+ return "certificate url";
+ case 22:
+ return "certificate status";
+ default:
+ return "?";
+ }
+}
+
+
static void tls_msg_cb(int write_p, int version, int content_type,
const void *buf, size_t len, SSL *ssl, void *arg)
{
struct tls_connection *conn = arg;
const u8 *pos = buf;
- wpa_printf(MSG_DEBUG, "OpenSSL: %s ver=0x%x content_type=%d",
- write_p ? "TX" : "RX", version, content_type);
+ if (write_p == 2) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: session ver=0x%x content_type=%d",
+ version, content_type);
+ wpa_hexdump_key(MSG_MSGDUMP, "OpenSSL: Data", buf, len);
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG, "OpenSSL: %s ver=0x%x content_type=%d (%s/%s)",
+ write_p ? "TX" : "RX", version, content_type,
+ openssl_content_type(content_type),
+ openssl_handshake_type(content_type, buf, len));
wpa_hexdump_key(MSG_MSGDUMP, "OpenSSL: Message", buf, len);
if (content_type == 24 && len >= 3 && pos[0] == 1) {
size_t payload_len = WPA_GET_BE16(pos + 1);
found++;
}
+ sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free);
+
return found;
}
1) {
wpa_printf(MSG_DEBUG, "TLS: %s in dNSName found",
full ? "Match" : "Suffix match");
+ sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free);
return 1;
}
}
+ sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free);
if (dns_name) {
wpa_printf(MSG_DEBUG, "TLS: None of the dNSName(s) matched");
return;
os_memset(&ev, 0, sizeof(ev));
- if (conn->cert_probe || context->cert_in_cb) {
+ if (conn->cert_probe || (conn->flags & TLS_CONN_EXT_CERT_CHECK) ||
+ context->cert_in_cb) {
cert = get_x509_cert(err_cert);
ev.peer_cert.cert = cert;
}
pos += gen->d.ia5->length;
*pos = '\0';
}
+ sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free);
for (alt = 0; alt < num_altsubject; alt++)
ev.peer_cert.altsubject[alt] = altsubject[alt];
TLS_FAIL_SERVER_CHAIN_PROBE);
}
- if (preverify_ok && context->event_cb != NULL)
+#ifdef OPENSSL_IS_BORINGSSL
+ if (depth == 0 && (conn->flags & TLS_CONN_REQUEST_OCSP) &&
+ preverify_ok) {
+ enum ocsp_result res;
+
+ res = check_ocsp_resp(conn->ssl_ctx, conn->ssl, err_cert,
+ conn->peer_issuer,
+ conn->peer_issuer_issuer);
+ if (res == OCSP_REVOKED) {
+ preverify_ok = 0;
+ openssl_tls_fail_event(conn, err_cert, err, depth, buf,
+ "certificate revoked",
+ TLS_FAIL_REVOKED);
+ if (err == X509_V_OK)
+ X509_STORE_CTX_set_error(
+ x509_ctx, X509_V_ERR_CERT_REVOKED);
+ } else if (res != OCSP_GOOD &&
+ (conn->flags & TLS_CONN_REQUIRE_OCSP)) {
+ preverify_ok = 0;
+ openssl_tls_fail_event(conn, err_cert, err, depth, buf,
+ "bad certificate status response",
+ TLS_FAIL_UNSPECIFIED);
+ }
+ }
+#endif /* OPENSSL_IS_BORINGSSL */
+
+ if (depth == 0 && preverify_ok && context->event_cb != NULL)
context->event_cb(context->cb_ctx,
TLS_CERT_CHAIN_SUCCESS, NULL);
}
#ifdef ANDROID
+ /* Single alias */
if (ca_cert && os_strncmp("keystore://", ca_cert, 11) == 0) {
- BIO *bio = BIO_from_keystore(&ca_cert[11]);
- STACK_OF(X509_INFO) *stack = NULL;
- stack_index_t i;
-
- if (bio) {
- stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
- BIO_free(bio);
- }
- if (!stack)
+ if (tls_add_ca_from_keystore(SSL_CTX_get_cert_store(ssl_ctx),
+ &ca_cert[11]) < 0)
return -1;
+ SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
+ return 0;
+ }
- for (i = 0; i < sk_X509_INFO_num(stack); ++i) {
- X509_INFO *info = sk_X509_INFO_value(stack, i);
- if (info->x509) {
- X509_STORE_add_cert(ssl_ctx->cert_store,
- info->x509);
- }
- if (info->crl) {
- X509_STORE_add_crl(ssl_ctx->cert_store,
- info->crl);
+ /* Multiple aliases separated by space */
+ if (ca_cert && os_strncmp("keystores://", ca_cert, 12) == 0) {
+ char *aliases = os_strdup(&ca_cert[12]);
+ const char *delim = " ";
+ int rc = 0;
+ char *savedptr;
+ char *alias;
+
+ if (!aliases)
+ return -1;
+ alias = strtok_r(aliases, delim, &savedptr);
+ for (; alias; alias = strtok_r(NULL, delim, &savedptr)) {
+ if (tls_add_ca_from_keystore_encoded(
+ SSL_CTX_get_cert_store(ssl_ctx), alias)) {
+ wpa_printf(MSG_WARNING,
+ "OpenSSL: %s - Failed to add ca_cert %s from keystore",
+ __func__, alias);
+ rc = -1;
+ break;
}
}
- sk_X509_INFO_pop_free(stack, X509_INFO_free);
+ os_free(aliases);
+ if (rc)
+ return rc;
+
SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
return 0;
}
if (client_cert == NULL && client_cert_blob == NULL)
return 0;
+#ifdef PKCS12_FUNCS
+#if OPENSSL_VERSION_NUMBER < 0x10002000L
+ /*
+ * Clear previously set extra chain certificates, if any, from PKCS#12
+ * processing in tls_parse_pkcs12() to allow OpenSSL to build a new
+ * chain properly.
+ */
+ SSL_CTX_clear_extra_chain_certs(conn->ssl_ctx);
+#endif /* OPENSSL_VERSION_NUMBER < 0x10002000L */
+#endif /* PKCS12_FUNCS */
+
if (client_cert_blob &&
SSL_use_certificate_ASN1(conn->ssl, (u8 *) client_cert_blob,
client_cert_blob_len) == 1) {
}
if (certs) {
-#if OPENSSL_VERSION_NUMBER >= 0x10002000L
- SSL_clear_chain_certs(ssl);
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
+ if (ssl)
+ SSL_clear_chain_certs(ssl);
+ else
+ SSL_CTX_clear_chain_certs(data->ssl);
while ((cert = sk_X509_pop(certs)) != NULL) {
X509_NAME_oneline(X509_get_subject_name(cert), buf,
sizeof(buf));
wpa_printf(MSG_DEBUG, "TLS: additional certificate"
" from PKCS12: subject='%s'", buf);
- if (SSL_add1_chain_cert(ssl, cert) != 1) {
+ if ((ssl && SSL_add1_chain_cert(ssl, cert) != 1) ||
+ (!ssl && SSL_CTX_add1_chain_cert(data->ssl,
+ cert) != 1)) {
tls_show_errors(MSG_DEBUG, __func__,
"Failed to add additional certificate");
res = -1;
+ X509_free(cert);
break;
}
+ X509_free(cert);
}
if (!res) {
/* Try to continue anyway */
}
- sk_X509_free(certs);
+ sk_X509_pop_free(certs, X509_free);
#ifndef OPENSSL_IS_BORINGSSL
- res = SSL_build_cert_chain(ssl,
- SSL_BUILD_CHAIN_FLAG_CHECK |
- SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR);
+ if (ssl)
+ res = SSL_build_cert_chain(
+ ssl,
+ SSL_BUILD_CHAIN_FLAG_CHECK |
+ SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR);
+ else
+ res = SSL_CTX_build_cert_chain(
+ data->ssl,
+ SSL_BUILD_CHAIN_FLAG_CHECK |
+ SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR);
if (!res) {
tls_show_errors(MSG_DEBUG, __func__,
"Failed to build certificate chain");
*/
res = 0;
#else /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
SSL_CTX_clear_extra_chain_certs(data->ssl);
-#endif /* OPENSSL_VERSION_NUMBER >= 0x10001000L */
while ((cert = sk_X509_pop(certs)) != NULL) {
X509_NAME_oneline(X509_get_subject_name(cert), buf,
sizeof(buf));
*/
if (SSL_CTX_add_extra_chain_cert(data->ssl, cert) != 1)
{
+ X509_free(cert);
res = -1;
break;
}
}
- sk_X509_free(certs);
+ sk_X509_pop_free(certs, X509_free);
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
}
static int tls_connection_engine_private_key(struct tls_connection *conn)
{
-#ifndef OPENSSL_NO_ENGINE
+#if defined(ANDROID) || !defined(OPENSSL_NO_ENGINE)
if (SSL_use_PrivateKey(conn->ssl, conn->private_key) != 1) {
tls_show_errors(MSG_ERROR, __func__,
"ENGINE: cannot use private key for TLS");
if (conn == NULL || keys == NULL)
return -1;
ssl = conn->ssl;
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
- if (ssl == NULL || ssl->s3 == NULL || ssl->session == NULL)
- return -1;
-
- os_memset(keys, 0, sizeof(*keys));
- keys->client_random = ssl->s3->client_random;
- keys->client_random_len = SSL3_RANDOM_SIZE;
- keys->server_random = ssl->s3->server_random;
- keys->server_random_len = SSL3_RANDOM_SIZE;
-#else
if (ssl == NULL)
return -1;
keys->server_random = conn->server_random;
keys->server_random_len = SSL_get_server_random(
ssl, conn->server_random, sizeof(conn->server_random));
-#endif
return 0;
}
-#ifndef CONFIG_FIPS
+#ifdef OPENSSL_NEED_EAP_FAST_PRF
static int openssl_get_keyblock_size(SSL *ssl)
{
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
const EVP_CIPHER *c;
const EVP_MD *h;
int md_size;
return -1;
c = ssl->enc_read_ctx->cipher;
-#if OPENSSL_VERSION_NUMBER >= 0x00909000L
h = EVP_MD_CTX_md(ssl->read_hash);
-#else
- h = ssl->read_hash;
-#endif
if (h)
md_size = EVP_MD_size(h);
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
else if (ssl->s3)
md_size = ssl->s3->tmp.new_mac_secret_size;
-#endif
else
return -1;
EVP_CIPHER_iv_length(c));
#endif
}
-#endif /* CONFIG_FIPS */
+#endif /* OPENSSL_NEED_EAP_FAST_PRF */
-static int openssl_tls_prf(struct tls_connection *conn,
- const char *label, int server_random_first,
- int skip_keyblock, u8 *out, size_t out_len)
+int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
+ const char *label, u8 *out, size_t out_len)
{
-#ifdef CONFIG_FIPS
- wpa_printf(MSG_ERROR, "OpenSSL: TLS keys cannot be exported in FIPS "
- "mode");
- return -1;
-#else /* CONFIG_FIPS */
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
- SSL *ssl;
- u8 *rnd;
- int ret = -1;
- int skip = 0;
- u8 *tmp_out = NULL;
- u8 *_out = out;
- const char *ver;
-
- /*
- * TLS library did not support key generation, so get the needed TLS
- * session parameters and use an internal implementation of TLS PRF to
- * derive the key.
- */
-
- if (conn == NULL)
- return -1;
- ssl = conn->ssl;
- if (ssl == NULL || ssl->s3 == NULL || ssl->session == NULL ||
- ssl->session->master_key_length <= 0)
- return -1;
- ver = SSL_get_version(ssl);
-
- if (skip_keyblock) {
- skip = openssl_get_keyblock_size(ssl);
- if (skip < 0)
- return -1;
- tmp_out = os_malloc(skip + out_len);
- if (!tmp_out)
- return -1;
- _out = tmp_out;
- }
-
- rnd = os_malloc(2 * SSL3_RANDOM_SIZE);
- if (!rnd) {
- os_free(tmp_out);
+ if (!conn ||
+ SSL_export_keying_material(conn->ssl, out, out_len, label,
+ os_strlen(label), NULL, 0, 0) != 1)
return -1;
- }
+ return 0;
+}
- if (server_random_first) {
- os_memcpy(rnd, ssl->s3->server_random, SSL3_RANDOM_SIZE);
- os_memcpy(rnd + SSL3_RANDOM_SIZE, ssl->s3->client_random,
- SSL3_RANDOM_SIZE);
- } else {
- os_memcpy(rnd, ssl->s3->client_random, SSL3_RANDOM_SIZE);
- os_memcpy(rnd + SSL3_RANDOM_SIZE, ssl->s3->server_random,
- SSL3_RANDOM_SIZE);
- }
- if (os_strcmp(ver, "TLSv1.2") == 0) {
- tls_prf_sha256(ssl->session->master_key,
- ssl->session->master_key_length,
- label, rnd, 2 * SSL3_RANDOM_SIZE,
- _out, skip + out_len);
- ret = 0;
- } else if (tls_prf_sha1_md5(ssl->session->master_key,
- ssl->session->master_key_length,
- label, rnd, 2 * SSL3_RANDOM_SIZE,
- _out, skip + out_len) == 0) {
- ret = 0;
- }
- os_free(rnd);
- if (ret == 0 && skip_keyblock)
- os_memcpy(out, _out + skip, out_len);
- bin_clear_free(tmp_out, skip);
-
- return ret;
-#else
+int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
+ u8 *out, size_t out_len)
+{
+#ifdef OPENSSL_NEED_EAP_FAST_PRF
SSL *ssl;
SSL_SESSION *sess;
u8 *rnd;
const char *ver;
/*
- * TLS library did not support key generation, so get the needed TLS
- * session parameters and use an internal implementation of TLS PRF to
- * derive the key.
+ * TLS library did not support EAP-FAST key generation, so get the
+ * needed TLS session parameters and use an internal implementation of
+ * TLS PRF to derive the key.
*/
if (conn == NULL)
if (!ver || !sess)
return -1;
- if (skip_keyblock) {
- skip = openssl_get_keyblock_size(ssl);
- if (skip < 0)
- return -1;
- tmp_out = os_malloc(skip + out_len);
- if (!tmp_out)
- return -1;
- _out = tmp_out;
- }
+ skip = openssl_get_keyblock_size(ssl);
+ if (skip < 0)
+ return -1;
+ tmp_out = os_malloc(skip + out_len);
+ if (!tmp_out)
+ return -1;
+ _out = tmp_out;
rnd = os_malloc(2 * SSL3_RANDOM_SIZE);
if (!rnd) {
master_key_len = SSL_SESSION_get_master_key(sess, master_key,
sizeof(master_key));
- if (server_random_first) {
- os_memcpy(rnd, server_random, SSL3_RANDOM_SIZE);
- os_memcpy(rnd + SSL3_RANDOM_SIZE, client_random,
- SSL3_RANDOM_SIZE);
- } else {
- os_memcpy(rnd, client_random, SSL3_RANDOM_SIZE);
- os_memcpy(rnd + SSL3_RANDOM_SIZE, server_random,
- SSL3_RANDOM_SIZE);
- }
+ os_memcpy(rnd, server_random, SSL3_RANDOM_SIZE);
+ os_memcpy(rnd + SSL3_RANDOM_SIZE, client_random, SSL3_RANDOM_SIZE);
if (os_strcmp(ver, "TLSv1.2") == 0) {
tls_prf_sha256(master_key, master_key_len,
- label, rnd, 2 * SSL3_RANDOM_SIZE,
+ "key expansion", rnd, 2 * SSL3_RANDOM_SIZE,
_out, skip + out_len);
ret = 0;
} else if (tls_prf_sha1_md5(master_key, master_key_len,
- label, rnd, 2 * SSL3_RANDOM_SIZE,
+ "key expansion", rnd, 2 * SSL3_RANDOM_SIZE,
_out, skip + out_len) == 0) {
ret = 0;
}
os_memset(master_key, 0, sizeof(master_key));
os_free(rnd);
- if (ret == 0 && skip_keyblock)
+ if (ret == 0)
os_memcpy(out, _out + skip, out_len);
bin_clear_free(tmp_out, skip);
return ret;
-#endif
-#endif /* CONFIG_FIPS */
-}
-
-
-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)
-{
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
- SSL *ssl;
- if (conn == NULL)
- return -1;
- if (server_random_first || skip_keyblock)
- return openssl_tls_prf(conn, label,
- server_random_first, skip_keyblock,
- out, out_len);
- ssl = conn->ssl;
- if (SSL_export_keying_material(ssl, out, out_len, label,
- os_strlen(label), NULL, 0, 0) == 1) {
- wpa_printf(MSG_DEBUG, "OpenSSL: Using internal PRF");
- return 0;
- }
-#endif
- return openssl_tls_prf(conn, label, server_random_first,
- skip_keyblock, out, out_len);
+#else /* OPENSSL_NEED_EAP_FAST_PRF */
+ wpa_printf(MSG_ERROR,
+ "OpenSSL: EAP-FAST keys cannot be exported in FIPS mode");
+ return -1;
+#endif /* OPENSSL_NEED_EAP_FAST_PRF */
}
int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
{
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
return conn ? SSL_cache_hit(conn->ssl) : 0;
-#else
- return conn ? conn->ssl->hit : 0;
-#endif
}
int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
u8 *ciphers)
{
- char buf[100], *pos, *end;
+ char buf[500], *pos, *end;
u8 *c;
int ret;
case TLS_CIPHER_ANON_DH_AES128_SHA:
suite = "ADH-AES128-SHA";
break;
+ case TLS_CIPHER_RSA_DHE_AES256_SHA:
+ suite = "DHE-RSA-AES256-SHA";
+ break;
+ case TLS_CIPHER_AES256_SHA:
+ suite = "AES256-SHA";
+ break;
default:
wpa_printf(MSG_DEBUG, "TLS: Unsupported "
"cipher selection: %d", *c);
wpa_printf(MSG_DEBUG, "OpenSSL: cipher suites: %s", buf + 1);
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
if (os_strstr(buf, ":ADH-")) {
/*
wpa_printf(MSG_INFO, "OpenSSL: Could not find current server certificate from OCSP response%s",
(conn->flags & TLS_CONN_REQUIRE_OCSP) ? "" :
" (OCSP not required)");
+ OCSP_CERTID_free(id);
OCSP_BASICRESP_free(basic);
OCSP_RESPONSE_free(rsp);
return (conn->flags & TLS_CONN_REQUIRE_OCSP) ? 0 : 1;
}
+ OCSP_CERTID_free(id);
if (!OCSP_check_validity(this_update, next_update, 5 * 60, -1)) {
tls_show_errors(MSG_INFO, __func__,
if (conn == NULL)
return -1;
+ if (params->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
+ wpa_printf(MSG_INFO,
+ "OpenSSL: ocsp=3 not supported");
+ return -1;
+ }
+
/*
* If the engine isn't explicitly configured, and any of the
* cert/key fields are actually PKCS#11 URIs, then automatically
tls_set_conn_flags(conn->ssl, params->flags);
+#ifdef OPENSSL_IS_BORINGSSL
+ if (params->flags & TLS_CONN_REQUEST_OCSP) {
+ SSL_enable_ocsp_stapling(conn->ssl);
+ }
+#else /* OPENSSL_IS_BORINGSSL */
#ifdef HAVE_OCSP
if (params->flags & TLS_CONN_REQUEST_OCSP) {
SSL_CTX *ssl_ctx = data->ssl;
"OpenSSL: No OCSP support included - allow optional OCSP case to continue");
}
#endif /* HAVE_OCSP */
+#endif /* OPENSSL_IS_BORINGSSL */
conn->flags = params->flags;
* commented out unless explicitly needed for EAP-FAST in order to be able to
* build this file with unmodified openssl. */
-#ifdef OPENSSL_IS_BORINGSSL
+#if (defined(OPENSSL_IS_BORINGSSL) || OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len,
STACK_OF(SSL_CIPHER) *peer_ciphers,
const SSL_CIPHER **cipher, void *arg)
struct tls_connection *conn = arg;
int ret;
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
if (conn == NULL || conn->session_ticket_cb == NULL)
return 0;
int tls_get_library_version(char *buf, size_t buf_len)
{
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+ return os_snprintf(buf, buf_len, "OpenSSL build=%s run=%s",
+ OPENSSL_VERSION_TEXT,
+ OpenSSL_version(OPENSSL_VERSION));
+#else
return os_snprintf(buf, buf_len, "OpenSSL build=%s run=%s",
OPENSSL_VERSION_TEXT,
SSLeay_version(SSLEAY_VERSION));
+#endif
}
--- /dev/null
+/*
+ * SSL/TLS interface functions for OpenSSL
+ * 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.
+ */
+
+#ifndef TLS_OPENSSL_H
+#define TLS_OPENSSL_H
+
+enum ocsp_result {
+ OCSP_GOOD, OCSP_REVOKED, OCSP_NO_RESPONSE, OCSP_INVALID
+};
+
+enum ocsp_result check_ocsp_resp(SSL_CTX *ssl_ctx, SSL *ssl, X509 *cert,
+ X509 *issuer, X509 *issuer_issuer);
+
+#endif /* TLS_OPENSSL_H */
--- /dev/null
+/*
+ * SSL/TLS interface functions for OpenSSL - BoringSSL OCSP
+ * 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.
+ */
+
+#include "includes.h"
+
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/x509v3.h>
+#ifdef OPENSSL_IS_BORINGSSL
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#endif /* OPENSSL_IS_BORINGSSL */
+
+#include "common.h"
+#include "tls_openssl.h"
+
+
+#ifdef OPENSSL_IS_BORINGSSL
+
+static void tls_show_errors(int level, const char *func, const char *txt)
+{
+ unsigned long err;
+
+ wpa_printf(level, "OpenSSL: %s - %s %s",
+ func, txt, ERR_error_string(ERR_get_error(), NULL));
+
+ while ((err = ERR_get_error())) {
+ wpa_printf(MSG_INFO, "OpenSSL: pending error: %s",
+ ERR_error_string(err, NULL));
+ }
+}
+
+
+/*
+ * CertID ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * issuerNameHash OCTET STRING, -- Hash of Issuer's DN
+ * issuerKeyHash OCTET STRING, -- Hash of Issuer's public key
+ * serialNumber CertificateSerialNumber }
+ */
+typedef struct {
+ X509_ALGOR *hashAlgorithm;
+ ASN1_OCTET_STRING *issuerNameHash;
+ ASN1_OCTET_STRING *issuerKeyHash;
+ ASN1_INTEGER *serialNumber;
+} CertID;
+
+/*
+ * ResponseBytes ::= SEQUENCE {
+ * responseType OBJECT IDENTIFIER,
+ * response OCTET STRING }
+ */
+typedef struct {
+ ASN1_OBJECT *responseType;
+ ASN1_OCTET_STRING *response;
+} ResponseBytes;
+
+/*
+ * OCSPResponse ::= SEQUENCE {
+ * responseStatus OCSPResponseStatus,
+ * responseBytes [0] EXPLICIT ResponseBytes OPTIONAL }
+ */
+typedef struct {
+ ASN1_ENUMERATED *responseStatus;
+ ResponseBytes *responseBytes;
+} OCSPResponse;
+
+ASN1_SEQUENCE(ResponseBytes) = {
+ ASN1_SIMPLE(ResponseBytes, responseType, ASN1_OBJECT),
+ ASN1_SIMPLE(ResponseBytes, response, ASN1_OCTET_STRING)
+} ASN1_SEQUENCE_END(ResponseBytes);
+
+ASN1_SEQUENCE(OCSPResponse) = {
+ ASN1_SIMPLE(OCSPResponse, responseStatus, ASN1_ENUMERATED),
+ ASN1_EXP_OPT(OCSPResponse, responseBytes, ResponseBytes, 0)
+} ASN1_SEQUENCE_END(OCSPResponse);
+
+IMPLEMENT_ASN1_FUNCTIONS(OCSPResponse);
+
+/*
+ * ResponderID ::= CHOICE {
+ * byName [1] Name,
+ * byKey [2] KeyHash }
+ */
+typedef struct {
+ int type;
+ union {
+ X509_NAME *byName;
+ ASN1_OCTET_STRING *byKey;
+ } value;
+} ResponderID;
+
+/*
+ * RevokedInfo ::= SEQUENCE {
+ * revocationTime GeneralizedTime,
+ * revocationReason [0] EXPLICIT CRLReason OPTIONAL }
+ */
+typedef struct {
+ ASN1_GENERALIZEDTIME *revocationTime;
+ ASN1_ENUMERATED *revocationReason;
+} RevokedInfo;
+
+/*
+ * CertStatus ::= CHOICE {
+ * good [0] IMPLICIT NULL,
+ * revoked [1] IMPLICIT RevokedInfo,
+ * unknown [2] IMPLICIT UnknownInfo }
+ */
+typedef struct {
+ int type;
+ union {
+ ASN1_NULL *good;
+ RevokedInfo *revoked;
+ ASN1_NULL *unknown;
+ } value;
+} CertStatus;
+
+/*
+ * SingleResponse ::= SEQUENCE {
+ * certID CertID,
+ * certStatus CertStatus,
+ * thisUpdate GeneralizedTime,
+ * nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
+ * singleExtensions [1] EXPLICIT Extensions OPTIONAL }
+ */
+typedef struct {
+ CertID *certID;
+ CertStatus *certStatus;
+ ASN1_GENERALIZEDTIME *thisUpdate;
+ ASN1_GENERALIZEDTIME *nextUpdate;
+ STACK_OF(X509_EXTENSION) *singleExtensions;
+} SingleResponse;
+
+/*
+ * ResponseData ::= SEQUENCE {
+ * version [0] EXPLICIT Version DEFAULT v1,
+ * responderID ResponderID,
+ * producedAt GeneralizedTime,
+ * responses SEQUENCE OF SingleResponse,
+ * responseExtensions [1] EXPLICIT Extensions OPTIONAL }
+ */
+typedef struct {
+ ASN1_INTEGER *version;
+ ResponderID *responderID;
+ ASN1_GENERALIZEDTIME *producedAt;
+ STACK_OF(SingleResponse) *responses;
+ STACK_OF(X509_EXTENSION) *responseExtensions;
+} ResponseData;
+
+/*
+ * BasicOCSPResponse ::= SEQUENCE {
+ * tbsResponseData ResponseData,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING,
+ * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
+ */
+typedef struct {
+ ResponseData *tbsResponseData;
+ X509_ALGOR *signatureAlgorithm;
+ ASN1_BIT_STRING *signature;
+ STACK_OF(X509) *certs;
+} BasicOCSPResponse;
+
+ASN1_SEQUENCE(CertID) = {
+ ASN1_SIMPLE(CertID, hashAlgorithm, X509_ALGOR),
+ ASN1_SIMPLE(CertID, issuerNameHash, ASN1_OCTET_STRING),
+ ASN1_SIMPLE(CertID, issuerKeyHash, ASN1_OCTET_STRING),
+ ASN1_SIMPLE(CertID, serialNumber, ASN1_INTEGER)
+} ASN1_SEQUENCE_END(CertID);
+
+ASN1_CHOICE(ResponderID) = {
+ ASN1_EXP(ResponderID, value.byName, X509_NAME, 1),
+ ASN1_EXP(ResponderID, value.byKey, ASN1_OCTET_STRING, 2)
+} ASN1_CHOICE_END(ResponderID);
+
+ASN1_SEQUENCE(RevokedInfo) = {
+ ASN1_SIMPLE(RevokedInfo, revocationTime, ASN1_GENERALIZEDTIME),
+ ASN1_EXP_OPT(RevokedInfo, revocationReason, ASN1_ENUMERATED, 0)
+} ASN1_SEQUENCE_END(RevokedInfo);
+
+ASN1_CHOICE(CertStatus) = {
+ ASN1_IMP(CertStatus, value.good, ASN1_NULL, 0),
+ ASN1_IMP(CertStatus, value.revoked, RevokedInfo, 1),
+ ASN1_IMP(CertStatus, value.unknown, ASN1_NULL, 2)
+} ASN1_CHOICE_END(CertStatus);
+
+ASN1_SEQUENCE(SingleResponse) = {
+ ASN1_SIMPLE(SingleResponse, certID, CertID),
+ ASN1_SIMPLE(SingleResponse, certStatus, CertStatus),
+ ASN1_SIMPLE(SingleResponse, thisUpdate, ASN1_GENERALIZEDTIME),
+ ASN1_EXP_OPT(SingleResponse, nextUpdate, ASN1_GENERALIZEDTIME, 0),
+ ASN1_EXP_SEQUENCE_OF_OPT(SingleResponse, singleExtensions,
+ X509_EXTENSION, 1)
+} ASN1_SEQUENCE_END(SingleResponse);
+
+ASN1_SEQUENCE(ResponseData) = {
+ ASN1_EXP_OPT(ResponseData, version, ASN1_INTEGER, 0),
+ ASN1_SIMPLE(ResponseData, responderID, ResponderID),
+ ASN1_SIMPLE(ResponseData, producedAt, ASN1_GENERALIZEDTIME),
+ ASN1_SEQUENCE_OF(ResponseData, responses, SingleResponse),
+ ASN1_EXP_SEQUENCE_OF_OPT(ResponseData, responseExtensions,
+ X509_EXTENSION, 1)
+} ASN1_SEQUENCE_END(ResponseData);
+
+ASN1_SEQUENCE(BasicOCSPResponse) = {
+ ASN1_SIMPLE(BasicOCSPResponse, tbsResponseData, ResponseData),
+ ASN1_SIMPLE(BasicOCSPResponse, signatureAlgorithm, X509_ALGOR),
+ ASN1_SIMPLE(BasicOCSPResponse, signature, ASN1_BIT_STRING),
+ ASN1_EXP_SEQUENCE_OF_OPT(BasicOCSPResponse, certs, X509, 0)
+} ASN1_SEQUENCE_END(BasicOCSPResponse);
+
+IMPLEMENT_ASN1_FUNCTIONS(BasicOCSPResponse);
+
+#define sk_SingleResponse_num(sk) \
+sk_num(CHECKED_CAST(_STACK *, STACK_OF(SingleResponse) *, sk))
+
+#define sk_SingleResponse_value(sk, i) \
+ ((SingleResponse *) \
+ sk_value(CHECKED_CAST(_STACK *, STACK_OF(SingleResponse) *, sk), (i)))
+
+
+static char * mem_bio_to_str(BIO *out)
+{
+ char *txt;
+ size_t rlen;
+ int res;
+
+ rlen = BIO_ctrl_pending(out);
+ txt = os_malloc(rlen + 1);
+ if (!txt) {
+ BIO_free(out);
+ return NULL;
+ }
+
+ res = BIO_read(out, txt, rlen);
+ BIO_free(out);
+ if (res < 0) {
+ os_free(txt);
+ return NULL;
+ }
+
+ txt[res] = '\0';
+ return txt;
+}
+
+
+static char * generalizedtime_str(ASN1_GENERALIZEDTIME *t)
+{
+ BIO *out;
+
+ out = BIO_new(BIO_s_mem());
+ if (!out)
+ return NULL;
+
+ if (!ASN1_GENERALIZEDTIME_print(out, t)) {
+ BIO_free(out);
+ return NULL;
+ }
+
+ return mem_bio_to_str(out);
+}
+
+
+static char * responderid_str(ResponderID *rid)
+{
+ BIO *out;
+
+ out = BIO_new(BIO_s_mem());
+ if (!out)
+ return NULL;
+
+ switch (rid->type) {
+ case 0:
+ X509_NAME_print_ex(out, rid->value.byName, 0, XN_FLAG_ONELINE);
+ break;
+ case 1:
+ i2a_ASN1_STRING(out, rid->value.byKey, V_ASN1_OCTET_STRING);
+ break;
+ default:
+ BIO_free(out);
+ return NULL;
+ }
+
+ return mem_bio_to_str(out);
+}
+
+
+static char * octet_string_str(ASN1_OCTET_STRING *o)
+{
+ BIO *out;
+
+ out = BIO_new(BIO_s_mem());
+ if (!out)
+ return NULL;
+
+ i2a_ASN1_STRING(out, o, V_ASN1_OCTET_STRING);
+ return mem_bio_to_str(out);
+}
+
+
+static char * integer_str(ASN1_INTEGER *i)
+{
+ BIO *out;
+
+ out = BIO_new(BIO_s_mem());
+ if (!out)
+ return NULL;
+
+ i2a_ASN1_INTEGER(out, i);
+ return mem_bio_to_str(out);
+}
+
+
+static char * algor_str(X509_ALGOR *alg)
+{
+ BIO *out;
+
+ out = BIO_new(BIO_s_mem());
+ if (!out)
+ return NULL;
+
+ i2a_ASN1_OBJECT(out, alg->algorithm);
+ return mem_bio_to_str(out);
+}
+
+
+static char * extensions_str(const char *title, STACK_OF(X509_EXTENSION) *ext)
+{
+ BIO *out;
+
+ if (!ext)
+ return NULL;
+
+ out = BIO_new(BIO_s_mem());
+ if (!out)
+ return NULL;
+
+ if (!X509V3_extensions_print(out, title, ext, 0, 0)) {
+ BIO_free(out);
+ return NULL;
+ }
+ return mem_bio_to_str(out);
+}
+
+
+static int ocsp_resp_valid(ASN1_GENERALIZEDTIME *thisupd,
+ ASN1_GENERALIZEDTIME *nextupd)
+{
+ time_t now, tmp;
+
+ if (!ASN1_GENERALIZEDTIME_check(thisupd)) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: Invalid OCSP response thisUpdate");
+ return 0;
+ }
+
+ time(&now);
+ tmp = now + 5 * 60; /* allow five minute clock difference */
+ if (X509_cmp_time(thisupd, &tmp) > 0) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: OCSP response not yet valid");
+ return 0;
+ }
+
+ if (!nextupd)
+ return 1; /* OK - no limit on response age */
+
+ if (!ASN1_GENERALIZEDTIME_check(nextupd)) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: Invalid OCSP response nextUpdate");
+ return 0;
+ }
+
+ tmp = now - 5 * 60; /* allow five minute clock difference */
+ if (X509_cmp_time(nextupd, &tmp) < 0) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: OCSP response expired");
+ return 0;
+ }
+
+ if (ASN1_STRING_cmp(nextupd, thisupd) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: OCSP response nextUpdate before thisUpdate");
+ return 0;
+ }
+
+ /* Both thisUpdate and nextUpdate are valid */
+ return -1;
+}
+
+
+static int issuer_match(X509 *cert, X509 *issuer, CertID *certid)
+{
+ X509_NAME *iname;
+ ASN1_BIT_STRING *ikey;
+ const EVP_MD *dgst;
+ unsigned int len;
+ unsigned char md[EVP_MAX_MD_SIZE];
+ ASN1_OCTET_STRING *hash;
+ char *txt;
+
+ dgst = EVP_get_digestbyobj(certid->hashAlgorithm->algorithm);
+ if (!dgst) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: Could not find matching hash algorithm for OCSP");
+ return -1;
+ }
+
+ iname = X509_get_issuer_name(cert);
+ if (!X509_NAME_digest(iname, dgst, md, &len))
+ return -1;
+ hash = ASN1_OCTET_STRING_new();
+ if (!hash)
+ return -1;
+ if (!ASN1_OCTET_STRING_set(hash, md, len)) {
+ ASN1_OCTET_STRING_free(hash);
+ return -1;
+ }
+
+ txt = octet_string_str(hash);
+ if (txt) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: calculated issuerNameHash: %s",
+ txt);
+ os_free(txt);
+ }
+
+ if (ASN1_OCTET_STRING_cmp(certid->issuerNameHash, hash)) {
+ ASN1_OCTET_STRING_free(hash);
+ return -1;
+ }
+
+ ikey = X509_get0_pubkey_bitstr(issuer);
+ if (!ikey ||
+ !EVP_Digest(ikey->data, ikey->length, md, &len, dgst, NULL) ||
+ !ASN1_OCTET_STRING_set(hash, md, len)) {
+ ASN1_OCTET_STRING_free(hash);
+ return -1;
+ }
+
+ txt = octet_string_str(hash);
+ if (txt) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: calculated issuerKeyHash: %s",
+ txt);
+ os_free(txt);
+ }
+
+ if (ASN1_OCTET_STRING_cmp(certid->issuerKeyHash, hash)) {
+ ASN1_OCTET_STRING_free(hash);
+ return -1;
+ }
+
+ ASN1_OCTET_STRING_free(hash);
+ return 0;
+}
+
+
+static X509 * ocsp_find_signer(STACK_OF(X509) *certs, ResponderID *rid)
+{
+ unsigned int i;
+ unsigned char hash[SHA_DIGEST_LENGTH];
+
+ if (rid->type == 0) {
+ /* byName */
+ return X509_find_by_subject(certs, rid->value.byName);
+ }
+
+ /* byKey */
+ if (rid->value.byKey->length != SHA_DIGEST_LENGTH)
+ return NULL;
+ for (i = 0; i < sk_X509_num(certs); i++) {
+ X509 *x = sk_X509_value(certs, i);
+
+ X509_pubkey_digest(x, EVP_sha1(), hash, NULL);
+ if (os_memcmp(rid->value.byKey->data, hash,
+ SHA_DIGEST_LENGTH) == 0)
+ return x;
+ }
+
+ return NULL;
+}
+
+
+enum ocsp_result check_ocsp_resp(SSL_CTX *ssl_ctx, SSL *ssl, X509 *cert,
+ X509 *issuer, X509 *issuer_issuer)
+{
+ const uint8_t *resp_data;
+ size_t resp_len;
+ OCSPResponse *resp;
+ int status;
+ ResponseBytes *bytes;
+ const u8 *basic_data;
+ size_t basic_len;
+ BasicOCSPResponse *basic;
+ ResponseData *rd;
+ char *txt;
+ int i, num;
+ unsigned int j, num_resp;
+ SingleResponse *matching_resp = NULL, *cmp_sresp;
+ enum ocsp_result result = OCSP_INVALID;
+ X509_STORE *store;
+ STACK_OF(X509) *untrusted = NULL, *certs = NULL, *chain = NULL;
+ X509_STORE_CTX ctx;
+ X509 *signer, *tmp_cert;
+ int signer_trusted = 0;
+ EVP_PKEY *skey;
+ int ret;
+ char buf[256];
+
+ txt = integer_str(X509_get_serialNumber(cert));
+ if (txt) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: Searching OCSP response for peer certificate serialNumber: %s", txt);
+ os_free(txt);
+ }
+
+ SSL_get0_ocsp_response(ssl, &resp_data, &resp_len);
+ if (resp_data == NULL || resp_len == 0) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: No OCSP response received");
+ return OCSP_NO_RESPONSE;
+ }
+
+ wpa_hexdump(MSG_DEBUG, "OpenSSL: OCSP response", resp_data, resp_len);
+
+ resp = d2i_OCSPResponse(NULL, &resp_data, resp_len);
+ if (!resp) {
+ wpa_printf(MSG_INFO, "OpenSSL: Failed to parse OCSPResponse");
+ return OCSP_INVALID;
+ }
+
+ status = ASN1_ENUMERATED_get(resp->responseStatus);
+ if (status != 0) {
+ wpa_printf(MSG_INFO, "OpenSSL: OCSP responder error %d",
+ status);
+ return OCSP_INVALID;
+ }
+
+ bytes = resp->responseBytes;
+
+ if (!bytes ||
+ OBJ_obj2nid(bytes->responseType) != NID_id_pkix_OCSP_basic) {
+ wpa_printf(MSG_INFO,
+ "OpenSSL: Could not find BasicOCSPResponse");
+ return OCSP_INVALID;
+ }
+
+ basic_data = ASN1_STRING_data(bytes->response);
+ basic_len = ASN1_STRING_length(bytes->response);
+ wpa_hexdump(MSG_DEBUG, "OpenSSL: BasicOCSPResponse",
+ basic_data, basic_len);
+
+ basic = d2i_BasicOCSPResponse(NULL, &basic_data, basic_len);
+ if (!basic) {
+ wpa_printf(MSG_INFO,
+ "OpenSSL: Could not parse BasicOCSPResponse");
+ OCSPResponse_free(resp);
+ return OCSP_INVALID;
+ }
+
+ rd = basic->tbsResponseData;
+
+ if (basic->certs) {
+ untrusted = sk_X509_dup(basic->certs);
+ if (!untrusted)
+ goto fail;
+
+ num = sk_X509_num(basic->certs);
+ for (i = 0; i < num; i++) {
+ X509 *extra_cert;
+
+ extra_cert = sk_X509_value(basic->certs, i);
+ X509_NAME_oneline(X509_get_subject_name(extra_cert),
+ buf, sizeof(buf));
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: BasicOCSPResponse cert %s", buf);
+
+ if (!sk_X509_push(untrusted, extra_cert)) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: Could not add certificate to the untrusted stack");
+ }
+ }
+ }
+
+ store = SSL_CTX_get_cert_store(ssl_ctx);
+ if (issuer) {
+ if (X509_STORE_add_cert(store, issuer) != 1) {
+ tls_show_errors(MSG_INFO, __func__,
+ "OpenSSL: Could not add issuer to certificate store");
+ }
+ certs = sk_X509_new_null();
+ if (certs) {
+ tmp_cert = X509_dup(issuer);
+ if (tmp_cert && !sk_X509_push(certs, tmp_cert)) {
+ tls_show_errors(
+ MSG_INFO, __func__,
+ "OpenSSL: Could not add issuer to OCSP responder trust store");
+ X509_free(tmp_cert);
+ sk_X509_free(certs);
+ certs = NULL;
+ }
+ if (certs && issuer_issuer) {
+ tmp_cert = X509_dup(issuer_issuer);
+ if (tmp_cert &&
+ !sk_X509_push(certs, tmp_cert)) {
+ tls_show_errors(
+ MSG_INFO, __func__,
+ "OpenSSL: Could not add issuer's issuer to OCSP responder trust store");
+ X509_free(tmp_cert);
+ }
+ }
+ }
+ }
+
+ signer = ocsp_find_signer(certs, rd->responderID);
+ if (!signer)
+ signer = ocsp_find_signer(untrusted, rd->responderID);
+ else
+ signer_trusted = 1;
+ if (!signer) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: Could not find OCSP signer certificate");
+ goto fail;
+ }
+
+ skey = X509_get_pubkey(signer);
+ if (!skey) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: Could not get OCSP signer public key");
+ goto fail;
+ }
+ if (ASN1_item_verify(ASN1_ITEM_rptr(ResponseData),
+ basic->signatureAlgorithm, basic->signature,
+ basic->tbsResponseData, skey) <= 0) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: BasicOCSPResponse signature is invalid");
+ goto fail;
+ }
+
+ X509_NAME_oneline(X509_get_subject_name(signer), buf, sizeof(buf));
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: Found OCSP signer certificate %s and verified BasicOCSPResponse signature",
+ buf);
+
+ if (!X509_STORE_CTX_init(&ctx, store, signer, untrusted))
+ goto fail;
+ X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_OCSP_HELPER);
+ ret = X509_verify_cert(&ctx);
+ chain = X509_STORE_CTX_get1_chain(&ctx);
+ X509_STORE_CTX_cleanup(&ctx);
+ if (ret <= 0) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: Could not validate OCSP signer certificate");
+ goto fail;
+ }
+
+ if (!chain || sk_X509_num(chain) <= 0) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: No OCSP signer chain found");
+ goto fail;
+ }
+
+ if (!signer_trusted) {
+ X509_check_purpose(signer, -1, 0);
+ if ((signer->ex_flags & EXFLAG_XKUSAGE) &&
+ (signer->ex_xkusage & XKU_OCSP_SIGN)) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: OCSP signer certificate delegation OK");
+ } else {
+ tmp_cert = sk_X509_value(chain, sk_X509_num(chain) - 1);
+ if (X509_check_trust(tmp_cert, NID_OCSP_sign, 0) !=
+ X509_TRUST_TRUSTED) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: OCSP signer certificate not trusted");
+ result = OCSP_NO_RESPONSE;
+ goto fail;
+ }
+ }
+ }
+
+ wpa_printf(MSG_DEBUG, "OpenSSL: OCSP version: %lu",
+ ASN1_INTEGER_get(rd->version));
+
+ txt = responderid_str(rd->responderID);
+ if (txt) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: OCSP responderID: %s",
+ txt);
+ os_free(txt);
+ }
+
+ txt = generalizedtime_str(rd->producedAt);
+ if (txt) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: OCSP producedAt: %s",
+ txt);
+ os_free(txt);
+ }
+
+ num_resp = sk_SingleResponse_num(rd->responses);
+ if (num_resp == 0) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: No OCSP SingleResponse within BasicOCSPResponse");
+ result = OCSP_NO_RESPONSE;
+ goto fail;
+ }
+ cmp_sresp = sk_SingleResponse_value(rd->responses, 0);
+ for (j = 0; j < num_resp; j++) {
+ SingleResponse *sresp;
+ CertID *cid1, *cid2;
+
+ sresp = sk_SingleResponse_value(rd->responses, j);
+ wpa_printf(MSG_DEBUG, "OpenSSL: OCSP SingleResponse %u/%u",
+ j + 1, num_resp);
+
+ txt = algor_str(sresp->certID->hashAlgorithm);
+ if (txt) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: certID hashAlgorithm: %s", txt);
+ os_free(txt);
+ }
+
+ txt = octet_string_str(sresp->certID->issuerNameHash);
+ if (txt) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: certID issuerNameHash: %s", txt);
+ os_free(txt);
+ }
+
+ txt = octet_string_str(sresp->certID->issuerKeyHash);
+ if (txt) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: certID issuerKeyHash: %s", txt);
+ os_free(txt);
+ }
+
+ txt = integer_str(sresp->certID->serialNumber);
+ if (txt) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: certID serialNumber: %s", txt);
+ os_free(txt);
+ }
+
+ switch (sresp->certStatus->type) {
+ case 0:
+ wpa_printf(MSG_DEBUG, "OpenSSL: certStatus: good");
+ break;
+ case 1:
+ wpa_printf(MSG_DEBUG, "OpenSSL: certStatus: revoked");
+ break;
+ default:
+ wpa_printf(MSG_DEBUG, "OpenSSL: certStatus: unknown");
+ break;
+ }
+
+ txt = generalizedtime_str(sresp->thisUpdate);
+ if (txt) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: thisUpdate: %s", txt);
+ os_free(txt);
+ }
+
+ if (sresp->nextUpdate) {
+ txt = generalizedtime_str(sresp->nextUpdate);
+ if (txt) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: nextUpdate: %s",
+ txt);
+ os_free(txt);
+ }
+ }
+
+ txt = extensions_str("singleExtensions",
+ sresp->singleExtensions);
+ if (txt) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: %s", txt);
+ os_free(txt);
+ }
+
+ cid1 = cmp_sresp->certID;
+ cid2 = sresp->certID;
+ if (j > 0 &&
+ (OBJ_cmp(cid1->hashAlgorithm->algorithm,
+ cid2->hashAlgorithm->algorithm) != 0 ||
+ ASN1_OCTET_STRING_cmp(cid1->issuerNameHash,
+ cid2->issuerNameHash) != 0 ||
+ ASN1_OCTET_STRING_cmp(cid1->issuerKeyHash,
+ cid2->issuerKeyHash) != 0)) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: Different OCSP response issuer information between SingleResponse values within BasicOCSPResponse");
+ goto fail;
+ }
+
+ if (!matching_resp && issuer &&
+ ASN1_INTEGER_cmp(sresp->certID->serialNumber,
+ X509_get_serialNumber(cert)) == 0 &&
+ issuer_match(cert, issuer, sresp->certID) == 0) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: This response matches peer certificate");
+ matching_resp = sresp;
+ }
+ }
+
+ txt = extensions_str("responseExtensions", rd->responseExtensions);
+ if (txt) {
+ wpa_printf(MSG_DEBUG, "OpenSSL: %s", txt);
+ os_free(txt);
+ }
+
+ if (!matching_resp) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: Could not find OCSP response that matches the peer certificate");
+ result = OCSP_NO_RESPONSE;
+ goto fail;
+ }
+
+ if (!ocsp_resp_valid(matching_resp->thisUpdate,
+ matching_resp->nextUpdate)) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: OCSP response not valid at this time");
+ goto fail;
+ }
+
+ if (matching_resp->certStatus->type == 1) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: OCSP response indicated that the peer certificate has been revoked");
+ result = OCSP_REVOKED;
+ goto fail;
+ }
+
+ if (matching_resp->certStatus->type != 0) {
+ wpa_printf(MSG_DEBUG,
+ "OpenSSL: OCSP response did not indicate good status");
+ result = OCSP_NO_RESPONSE;
+ goto fail;
+ }
+
+ /* OCSP response indicated the certificate is good. */
+ result = OCSP_GOOD;
+fail:
+ sk_X509_pop_free(chain, X509_free);
+ sk_X509_free(untrusted);
+ sk_X509_pop_free(certs, X509_free);
+ BasicOCSPResponse_free(basic);
+ OCSPResponse_free(resp);
+
+ return result;
+}
+
+#endif /* OPENSSL_IS_BORINGSSL */
#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
*/
#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().
*/
/**
* 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
*/
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
* 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 {
* 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 {
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
#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;
/** 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;
* 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 */
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;
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;
size_t supp_channels_len;
const u8 *supp_oper_classes;
size_t supp_oper_classes_len;
+ int support_p2p_ps;
};
struct mac_address {
#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,
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() */
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
*
* @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
/**
* 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
* 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
* @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);
* 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
* 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
* 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
* 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
* 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);
+
};
* 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,
};
* 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;
/**
* struct interface_status - Data for EVENT_INTERFACE_STATUS
*/
struct interface_status {
+ unsigned int ifindex;
char ifname[100];
enum {
EVENT_INTERFACE_ADDED, EVENT_INTERFACE_REMOVED
* 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 {
* @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;
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;
/**
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;
};
/**
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
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 */
op == IEEE80211_IOCTL_FILTERFRAME)
do_inline = 0;
- memset(&iwr, 0, sizeof(iwr));
+ os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
if (do_inline) {
/*
* Argument data fits inline; put it there.
*/
- memcpy(iwr.u.name, data, len);
+ os_memcpy(iwr.u.name, data, len);
} else {
/*
* Argument data too big for inline transfer; setup a
{
struct iwreq iwr;
- memset(&iwr, 0, sizeof(iwr));
+ os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
iwr.u.mode = op;
- memcpy(iwr.u.name+sizeof(__u32), &arg, sizeof(arg));
+ os_memcpy(iwr.u.name + sizeof(__u32), &arg, sizeof(arg));
if (ioctl(drv->ioctl_sock, IEEE80211_IOCTL_SETPARAM, &iwr) < 0) {
wpa_printf(MSG_INFO,
static char buf[sizeof(MACSTR)];
if (addr != NULL)
- snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
+ os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
else
- snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0);
+ os_snprintf(buf, sizeof(buf), MACSTR, 0, 0, 0, 0, 0, 0);
return buf;
}
#endif /* CONFIG_NO_STDOUT_DEBUG */
else
mlme.im_op = IEEE80211_MLME_UNAUTHORIZE;
mlme.im_reason = 0;
- memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
+ os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme));
if (ret < 0) {
wpa_printf(MSG_DEBUG, "%s: Failed to %sauthorize STA " MACSTR,
wpa_printf(MSG_DEBUG, "%s: addr=%s key_idx=%d",
__func__, ether_sprintf(addr), key_idx);
- memset(&wk, 0, sizeof(wk));
+ os_memset(&wk, 0, sizeof(wk));
if (addr != NULL) {
- memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
+ os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN);
wk.idk_keyix = (u8) IEEE80211_KEYIX_NONE;
} else {
wk.idk_keyix = key_idx;
return -3;
}
- memset(&wk, 0, sizeof(wk));
+ os_memset(&wk, 0, sizeof(wk));
wk.ik_type = cipher;
wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT;
if (addr == NULL || is_broadcast_ether_addr(addr)) {
- memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
+ os_memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
wk.ik_keyix = key_idx;
if (set_tx)
wk.ik_flags |= IEEE80211_KEY_DEFAULT;
} else {
- memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
+ os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
wk.ik_keyix = IEEE80211_KEYIX_NONE;
}
wk.ik_keylen = key_len;
- memcpy(wk.ik_keydata, key, key_len);
+ os_memcpy(wk.ik_keydata, key, key_len);
ret = set80211priv(drv, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk));
if (ret < 0) {
wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d",
__func__, ether_sprintf(addr), idx);
- memset(&wk, 0, sizeof(wk));
+ os_memset(&wk, 0, sizeof(wk));
if (addr == NULL)
- memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
+ os_memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
else
- memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
+ os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
wk.ik_keyix = idx;
if (set80211priv(drv, IEEE80211_IOCTL_GETKEY, &wk, sizeof(wk))) {
#define WPA_KEY_RSC_LEN 8
#endif
u8 tmp[WPA_KEY_RSC_LEN];
- memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
+ os_memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
for (i = 0; i < WPA_KEY_RSC_LEN; i++) {
seq[i] = tmp[WPA_KEY_RSC_LEN - i - 1];
}
}
#else /* WORDS_BIGENDIAN */
- memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
+ os_memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc));
#endif /* WORDS_BIGENDIAN */
return 0;
}
atheros_flush(void *priv)
{
u8 allsta[IEEE80211_ADDR_LEN];
- memset(allsta, 0xff, IEEE80211_ADDR_LEN);
+ os_memset(allsta, 0xff, IEEE80211_ADDR_LEN);
return atheros_sta_deauth(priv, NULL, allsta,
IEEE80211_REASON_AUTH_LEAVE);
}
struct atheros_driver_data *drv = priv;
struct ieee80211req_sta_stats stats;
- memset(data, 0, sizeof(*data));
+ os_memset(data, 0, sizeof(*data));
/*
* Fetch statistics for station from the system.
*/
- memset(&stats, 0, sizeof(stats));
- memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN);
+ os_memset(&stats, 0, sizeof(stats));
+ os_memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN);
if (set80211priv(drv, IEEE80211_IOCTL_STA_STATS,
&stats, sizeof(stats))) {
wpa_printf(MSG_DEBUG, "%s: Failed to fetch STA stats (addr "
MACSTR ")", __func__, MAC2STR(addr));
- if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) {
- memcpy(data, &drv->acct_data, sizeof(*data));
+ if (os_memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) {
+ os_memcpy(data, &drv->acct_data, sizeof(*data));
return 0;
}
wpa_printf(MSG_DEBUG, "%s: addr=%s", __func__, ether_sprintf(addr));
mlme.im_op = IEEE80211_MLME_CLEAR_STATS;
- memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
+ os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme,
sizeof(mlme));
if (ret < 0) {
mlme.im_op = IEEE80211_MLME_DEAUTH;
mlme.im_reason = reason_code;
- memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
+ os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme));
if (ret < 0) {
wpa_printf(MSG_DEBUG, "%s: Failed to deauth STA (addr " MACSTR
mlme.im_op = IEEE80211_MLME_DISASSOC;
mlme.im_reason = reason_code;
- memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
+ os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN);
ret = set80211priv(drv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme));
if (ret < 0) {
wpa_printf(MSG_DEBUG, "%s: Failed to disassoc STA (addr "
wpa_printf(MSG_ERROR, "Invalid QoS Map");
return -1;
} else {
- memset(&req, 0, sizeof(struct ieee80211req_athdbg));
+ os_memset(&req, 0, sizeof(struct ieee80211req_athdbg));
req.cmd = IEEE80211_DBGREQ_SETQOSMAPCONF;
os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->iface, sizeof(iwr.ifr_name));
(int) len);
if (stype == WLAN_FC_STYPE_PROBE_REQ) {
- if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req))
+ if (len < IEEE80211_HDRLEN)
return;
os_memset(&event, 0, sizeof(event));
event.rx_probe_req.sa = mgmt->sa;
event.rx_probe_req.da = mgmt->da;
event.rx_probe_req.bssid = mgmt->bssid;
- event.rx_probe_req.ie = mgmt->u.probe_req.variable;
- event.rx_probe_req.ie_len =
- len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
+ event.rx_probe_req.ie = buf + IEEE80211_HDRLEN;
+ event.rx_probe_req.ie_len = len - IEEE80211_HDRLEN;
wpa_supplicant_event(drv->hapd, EVENT_RX_PROBE_REQ, &event);
return;
}
+ if (stype == WLAN_FC_STYPE_ACTION &&
+ (os_memcmp(drv->own_addr, mgmt->bssid, ETH_ALEN) == 0 ||
+ is_broadcast_ether_addr(mgmt->bssid))) {
+ os_memset(&event, 0, sizeof(event));
+ event.rx_mgmt.frame = buf;
+ event.rx_mgmt.frame_len = len;
+ wpa_supplicant_event(drv->hapd, EVENT_RX_MGMT, &event);
+ return;
+ }
+
if (os_memcmp(drv->own_addr, mgmt->bssid, ETH_ALEN) != 0) {
wpa_printf(MSG_DEBUG, "%s: BSSID does not match - ignore",
__func__);
iebuf = mgmt->u.reassoc_req.variable;
drv_event_assoc(drv->hapd, mgmt->sa, iebuf, ielen, 1);
break;
- case WLAN_FC_STYPE_ACTION:
- os_memset(&event, 0, sizeof(event));
- event.rx_mgmt.frame = buf;
- event.rx_mgmt.frame_len = len;
- wpa_supplicant_event(drv->hapd, EVENT_RX_MGMT, &event);
- break;
case WLAN_FC_STYPE_AUTH:
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth))
break;
/*
* Fetch negotiated WPA/RSN parameters from the system.
*/
- memset(&ie, 0, sizeof(ie));
- memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN);
+ os_memset(&ie, 0, sizeof(ie));
+ os_memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN);
if (set80211priv(drv, IEEE80211_IOCTL_GETWPAIE, &ie, sizeof(ie))) {
/*
* See ATH_WPS_IE comment in the beginning of the file for a
no_ie:
drv_event_assoc(hapd, addr, iebuf, ielen, 0);
- if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) {
+ if (os_memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) {
/* Cached accounting data is not valid anymore. */
- memset(drv->acct_mac, 0, ETH_ALEN);
- memset(&drv->acct_data, 0, sizeof(drv->acct_data));
+ os_memset(drv->acct_mac, 0, ETH_ALEN);
+ os_memset(&drv->acct_data, 0, sizeof(drv->acct_data));
}
}
#define MGMT_FRAM_TAG_SIZE 30 /* hardcoded in driver */
wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom);
- if (strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
+ if (os_strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
char *pos;
u8 addr[ETH_ALEN];
- pos = strstr(custom, "addr=");
+ pos = os_strstr(custom, "addr=");
if (pos == NULL) {
wpa_printf(MSG_DEBUG,
"MLME-MICHAELMICFAILURE.indication "
char *key, *value;
u32 val;
key = custom;
- while ((key = strchr(key, '\n')) != NULL) {
+ while ((key = os_strchr(key, '\n')) != NULL) {
key++;
- value = strchr(key, '=');
+ value = os_strchr(key, '=');
if (value == NULL)
continue;
*value++ = '\0';
val = strtoul(value, NULL, 10);
- if (strcmp(key, "mac") == 0)
+ if (os_strcmp(key, "mac") == 0)
hwaddr_aton(value, drv->acct_mac);
- else if (strcmp(key, "rx_packets") == 0)
+ else if (os_strcmp(key, "rx_packets") == 0)
drv->acct_data.rx_packets = val;
- else if (strcmp(key, "tx_packets") == 0)
+ else if (os_strcmp(key, "tx_packets") == 0)
drv->acct_data.tx_packets = val;
- else if (strcmp(key, "rx_bytes") == 0)
+ else if (os_strcmp(key, "rx_bytes") == 0)
drv->acct_data.rx_bytes = val;
- else if (strcmp(key, "tx_bytes") == 0)
+ else if (os_strcmp(key, "tx_bytes") == 0)
drv->acct_data.tx_bytes = val;
key = value;
}
#ifdef CONFIG_WPS
- } else if (strncmp(custom, "PUSH-BUTTON.indication", 22) == 0) {
+ } else if (os_strncmp(custom, "PUSH-BUTTON.indication", 22) == 0) {
/* Some atheros kernels send push button as a wireless event */
/* PROBLEM! this event is received for ALL BSSs ...
* so all are enabled for WPS... ugh.
*/
wpa_supplicant_event(drv->hapd, EVENT_WPS_BUTTON_PUSHED, NULL);
- } else if (strncmp(custom, "Manage.prob_req ", 16) == 0) {
+ } else if (os_strncmp(custom, "Manage.prob_req ", 16) == 0) {
/*
* Atheros driver uses a hack to pass Probe Request frames as a
* binary data in the custom wireless event. The old way (using
* Format: "Manage.prob_req <frame len>" | zero padding | frame
*/
int len = atoi(custom + 16);
- if (len < 0 || custom + MGMT_FRAM_TAG_SIZE + len > end) {
+ if (len < 0 || MGMT_FRAM_TAG_SIZE + len > end - custom) {
wpa_printf(MSG_DEBUG, "Invalid Manage.prob_req event "
"length %d", len);
return;
(u8 *) custom + MGMT_FRAM_TAG_SIZE, len);
#endif /* CONFIG_WPS */
#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
- } else if (strncmp(custom, "Manage.assoc_req ", 17) == 0) {
+ } else if (os_strncmp(custom, "Manage.assoc_req ", 17) == 0) {
/* Format: "Manage.assoc_req <frame len>" | zero padding |
* frame */
int len = atoi(custom + 17);
- if (len < 0 || custom + MGMT_FRAM_TAG_SIZE + len > end) {
+ if (len < 0 || MGMT_FRAM_TAG_SIZE + len > end - custom) {
wpa_printf(MSG_DEBUG,
"Invalid Manage.assoc_req event length %d",
len);
}
atheros_raw_receive(drv, NULL,
(u8 *) custom + MGMT_FRAM_TAG_SIZE, len);
- } else if (strncmp(custom, "Manage.auth ", 12) == 0) {
+ } else if (os_strncmp(custom, "Manage.auth ", 12) == 0) {
/* Format: "Manage.auth <frame len>" | zero padding | frame */
int len = atoi(custom + 12);
if (len < 0 ||
- custom + MGMT_FRAM_TAG_SIZE + len > end) {
+ MGMT_FRAM_TAG_SIZE + len > end - custom) {
wpa_printf(MSG_DEBUG,
"Invalid Manage.auth event length %d", len);
return;
(u8 *) custom + MGMT_FRAM_TAG_SIZE, len);
#endif /* CONFIG_IEEE80211W || CONFIG_IEEE80211R */
#ifdef ATHEROS_USE_RAW_RECEIVE
- } else if (strncmp(custom, "Manage.action ", 14) == 0) {
+ } else if (os_strncmp(custom, "Manage.action ", 14) == 0) {
/* Format: "Manage.assoc_req <frame len>" | zero padding | frame
*/
int len = atoi(custom + 14);
- if (len < 0 || custom + MGMT_FRAM_TAG_SIZE + len > end) {
+ if (len < 0 || MGMT_FRAM_TAG_SIZE + len > end - custom) {
wpa_printf(MSG_DEBUG,
"Invalid Manage.action event length %d",
len);
static void
atheros_wireless_event_wireless(struct atheros_driver_data *drv,
- char *data, int len)
+ char *data, unsigned int len)
{
struct iw_event iwe_buf, *iwe = &iwe_buf;
char *pos, *end, *custom, *buf;
pos = data;
end = data + len;
- while (pos + IW_EV_LCP_LEN <= end) {
+ while ((size_t) (end - pos) >= IW_EV_LCP_LEN) {
/* Event data may be unaligned, so make a local, aligned copy
* before processing. */
- memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
+ os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
wpa_printf(MSG_MSGDUMP, "Wireless event: cmd=0x%x len=%d",
iwe->cmd, iwe->len);
- if (iwe->len <= IW_EV_LCP_LEN)
+ if (iwe->len <= IW_EV_LCP_LEN || iwe->len > end - pos)
return;
custom = pos + IW_EV_POINT_LEN;
/* WE-19 removed the pointer from struct iw_point */
char *dpos = (char *) &iwe_buf.u.data.length;
int dlen = dpos - (char *) &iwe_buf;
- memcpy(dpos, pos + IW_EV_LCP_LEN,
- sizeof(struct iw_event) - dlen);
+ os_memcpy(dpos, pos + IW_EV_LCP_LEN,
+ sizeof(struct iw_event) - dlen);
} else {
- memcpy(&iwe_buf, pos, sizeof(struct iw_event));
+ os_memcpy(&iwe_buf, pos, sizeof(struct iw_event));
custom += IW_EV_POINT_OFF;
}
* just like IWEVCUSTOM.
*/
case IWEVCUSTOM:
- if (custom + iwe->u.data.length > end)
+ if (iwe->u.data.length > end - custom)
return;
- buf = malloc(iwe->u.data.length + 1);
+ buf = os_malloc(iwe->u.data.length + 1);
if (buf == NULL)
return; /* XXX */
- memcpy(buf, custom, iwe->u.data.length);
+ os_memcpy(buf, custom, iwe->u.data.length);
buf[iwe->u.data.length] = '\0';
if (iwe->u.data.flags != 0) {
atheros_wireless_event_wireless_custom(
drv, buf, buf + iwe->u.data.length);
}
- free(buf);
+ os_free(buf);
break;
}
if (range == NULL)
return -1;
- memset(&iwr, 0, sizeof(iwr));
+ os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
iwr.u.data.pointer = (caddr_t) range;
iwr.u.data.length = buflen;
*/
len = data_len + sizeof(struct l2_ethhdr);
if (len > sizeof(buf)) {
- bp = malloc(len);
+ bp = os_malloc(len);
if (bp == NULL) {
wpa_printf(MSG_INFO,
"EAPOL frame discarded, cannot malloc temp buffer of size %lu!",
}
}
eth = (struct l2_ethhdr *) bp;
- memcpy(eth->h_dest, addr, ETH_ALEN);
- memcpy(eth->h_source, own_addr, ETH_ALEN);
+ os_memcpy(eth->h_dest, addr, ETH_ALEN);
+ os_memcpy(eth->h_source, own_addr, ETH_ALEN);
eth->h_proto = host_to_be16(ETH_P_EAPOL);
- memcpy(eth+1, data, data_len);
+ os_memcpy(eth + 1, data, data_len);
wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", bp, len);
status = l2_packet_send(drv->sock_xmit, addr, ETH_P_EAPOL, bp, len);
if (bp != buf)
- free(bp);
+ os_free(bp);
return status;
}
strerror(errno));
goto bad;
}
- memcpy(drv->iface, params->ifname, sizeof(drv->iface));
+ os_memcpy(drv->iface, params->ifname, sizeof(drv->iface));
- memset(&ifr, 0, sizeof(ifr));
+ os_memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
if (ioctl(drv->ioctl_sock, SIOCGIFINDEX, &ifr) != 0) {
wpa_printf(MSG_ERROR, "ioctl(SIOCGIFINDEX): %s",
} else
drv->sock_recv = drv->sock_xmit;
- memset(&iwr, 0, sizeof(iwr));
+ os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
iwr.u.mode = IW_MODE_MASTER;
atheros_reset_appfilter(drv);
if (drv->wpa_ie || drv->wps_beacon_ie || drv->wps_probe_resp_ie) {
+ atheros_set_opt_ie(priv, NULL, 0);
wpabuf_free(drv->wpa_ie);
wpabuf_free(drv->wps_beacon_ie);
wpabuf_free(drv->wps_probe_resp_ie);
- atheros_set_opt_ie(priv, NULL, 0);
}
netlink_deinit(drv->netlink);
(void) linux_set_iface_flags(drv->ioctl_sock, drv->iface, 0);
struct atheros_driver_data *drv = priv;
struct iwreq iwr;
- memset(&iwr, 0, sizeof(iwr));
+ os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
iwr.u.essid.flags = 1; /* SSID active */
iwr.u.essid.pointer = (caddr_t) buf;
struct iwreq iwr;
int ret = 0;
- memset(&iwr, 0, sizeof(iwr));
+ os_memset(&iwr, 0, sizeof(iwr));
os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
iwr.u.essid.pointer = (caddr_t) buf;
iwr.u.essid.length = (len > IW_ESSID_MAX_SIZE) ?
#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
static int atheros_send_mgmt(void *priv, const u8 *frm, size_t data_len,
- int noack, unsigned int freq)
+ int noack, unsigned int freq,
+ const u16 *csa_offs, size_t csa_offs_len)
{
struct atheros_driver_data *drv = priv;
u8 buf[1510];
wpa_printf(MSG_DEBUG, "%s frmlen = %lu " MACSTR, __func__,
(unsigned long) data_len, MAC2STR(mgmt->da));
mgmt_frm = (struct ieee80211req_mgmtbuf *) buf;
- memcpy(mgmt_frm->macaddr, (u8 *)mgmt->da, IEEE80211_ADDR_LEN);
+ os_memcpy(mgmt_frm->macaddr, (u8 *)mgmt->da, IEEE80211_ADDR_LEN);
mgmt_frm->buflen = data_len;
if (&mgmt_frm->buf[0] + data_len > buf + sizeof(buf)) {
wpa_printf(MSG_INFO, "atheros: Too long frame for "
#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 */
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;
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));
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;
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);
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
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;
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;
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)
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;
}
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 */
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;
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",
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:
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,
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;
}
{
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);
}
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;
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;
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);
}
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;
struct ieee80211_join_event *join;
int n;
- 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",
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);
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 */
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;
}
}
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);
(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;
}
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)
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
if (drv->ifindex == 0) {
wpa_printf(MSG_DEBUG, "%s: interface %s does not exist",
__func__, ifname);
- goto fail1;
- }
- 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",
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
{
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);
}
}
#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,
.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,
E2S(NEW_PEER_CANDIDATE);
E2S(ACS_CHANNEL_SELECTED);
E2S(DFS_CAC_STARTED);
+ E2S(P2P_LO_STOP);
}
return "UNKNOWN";
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';
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
+}
static int hostap_send_mlme(void *priv, const u8 *msg, size_t len, int noack,
- unsigned int freq)
+ unsigned int freq,
+ const u16 *csa_offs, size_t csa_offs_len)
{
struct hostap_driver_data *drv = priv;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) msg;
pos += 2;
memcpy(pos, data, data_len);
- res = hostap_send_mlme(drv, (u8 *) hdr, len, 0, 0);
+ res = hostap_send_mlme(drv, (u8 *) hdr, len, 0, 0, NULL, 0);
if (res < 0) {
wpa_printf(MSG_ERROR, "hostap_send_eapol - packet len: %lu - "
"failed: %d (%s)",
static void hostapd_wireless_event_wireless(struct hostap_driver_data *drv,
- char *data, int len)
+ char *data, unsigned int len)
{
struct iw_event iwe_buf, *iwe = &iwe_buf;
char *pos, *end, *custom, *buf;
pos = data;
end = data + len;
- while (pos + IW_EV_LCP_LEN <= end) {
+ while ((size_t) (end - pos) >= IW_EV_LCP_LEN) {
/* Event data may be unaligned, so make a local, aligned copy
* before processing. */
memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d",
iwe->cmd, iwe->len);
- if (iwe->len <= IW_EV_LCP_LEN)
+ if (iwe->len <= IW_EV_LCP_LEN || iwe->len > end - pos)
return;
custom = pos + IW_EV_POINT_LEN;
switch (iwe->cmd) {
case IWEVCUSTOM:
- if (custom + iwe->u.data.length > end)
+ if (iwe->u.data.length > end - custom)
return;
buf = malloc(iwe->u.data.length + 1);
if (buf == NULL)
memcpy(mgmt.bssid, own_addr, ETH_ALEN);
mgmt.u.deauth.reason_code = host_to_le16(reason);
return hostap_send_mlme(drv, (u8 *) &mgmt, IEEE80211_HDRLEN +
- sizeof(mgmt.u.deauth), 0, 0);
+ sizeof(mgmt.u.deauth), 0, 0, NULL, 0);
}
memcpy(mgmt.bssid, own_addr, ETH_ALEN);
mgmt.u.disassoc.reason_code = host_to_le16(reason);
return hostap_send_mlme(drv, (u8 *) &mgmt, IEEE80211_HDRLEN +
- sizeof(mgmt.u.disassoc), 0, 0);
+ sizeof(mgmt.u.disassoc), 0, 0, NULL, 0);
}
os_memcpy(hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
os_memcpy(hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
- hostap_send_mlme(priv, (u8 *)&hdr, sizeof(hdr), 0, 0);
+ hostap_send_mlme(priv, (u8 *)&hdr, sizeof(hdr), 0, 0, NULL, 0);
}
#include "includes.h"
#include <sys/ioctl.h>
#include <net/if.h>
+#include <inttypes.h>
#ifdef __linux__
#include <netpacket/packet.h>
#include <net/if_arp.h>
}
-static int macsec_qca_set_current_cipher_suite(void *priv, const u8 *cs,
- size_t cs_len)
+static int macsec_qca_set_current_cipher_suite(void *priv, u64 cs)
{
- u8 default_cs_id[] = CS_ID_GCM_AES_128;
-
- if (cs_len != CS_ID_LEN ||
- os_memcmp(cs, default_cs_id, cs_len) != 0) {
- wpa_hexdump(MSG_ERROR, "macsec: NOT supported CipherSuite",
- cs, cs_len);
+ if (cs != CS_ID_GCM_AES_128) {
+ wpa_printf(MSG_ERROR,
+ "%s: NOT supported CipherSuite: %016" PRIx64,
+ __func__, cs);
return -1;
}
#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);
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);
}
static int nl80211_send_frame_cmd(struct i802_bss *bss,
unsigned int freq, unsigned int wait,
const u8 *buf, size_t buf_len, u64 *cookie,
- int no_cck, int no_ack, int offchanok);
+ int no_cck, int no_ack, int offchanok,
+ const u16 *csa_offs, size_t csa_offs_len);
static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss,
int report);
-static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
-static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
-static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
+#define IFIDX_ANY -1
+
+static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
+ int ifidx_reason);
+static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
+ int ifidx_reason);
+static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
+ int ifidx_reason);
static int nl80211_set_channel(struct i802_bss *bss,
struct hostapd_freq_params *freq, int set_chan);
static int i802_set_iface_flags(struct i802_bss *bss, int up);
static int nl80211_set_param(void *priv, const char *param);
+#ifdef CONFIG_MESH
+static int nl80211_put_mesh_config(struct nl_msg *msg,
+ struct wpa_driver_mesh_bss_params *params);
+#endif /* CONFIG_MESH */
/* Converts nl80211_chan_width to a common format */
void * nl80211_cmd(struct wpa_driver_nl80211_data *drv,
struct nl_msg *msg, int flags, uint8_t cmd)
{
+ if (TEST_FAIL())
+ return NULL;
return genlmsg_put(msg, 0, 0, drv->global->nl80211_id,
0, flags, cmd, 0);
}
}
+static unsigned int nl80211_get_ifindex(void *priv)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+
+ return drv->ifindex;
+}
+
+
static int wpa_driver_nl80211_get_bssid(void *priv, u8 *bssid)
{
struct i802_bss *bss = priv;
static void wpa_driver_nl80211_event_newlink(
- struct wpa_driver_nl80211_data *drv, const char *ifname)
+ struct nl80211_global *global, struct wpa_driver_nl80211_data *drv,
+ int ifindex, const char *ifname)
{
union wpa_event_data event;
- if (os_strcmp(drv->first_bss->ifname, ifname) == 0) {
+ if (drv && os_strcmp(drv->first_bss->ifname, ifname) == 0) {
if (if_nametoindex(drv->first_bss->ifname) == 0) {
wpa_printf(MSG_DEBUG, "nl80211: Interface %s does not exist - ignore RTM_NEWLINK",
drv->first_bss->ifname);
}
os_memset(&event, 0, sizeof(event));
+ event.interface_status.ifindex = ifindex;
os_strlcpy(event.interface_status.ifname, ifname,
sizeof(event.interface_status.ifname));
event.interface_status.ievent = EVENT_INTERFACE_ADDED;
- wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
+ if (drv)
+ wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
+ else
+ wpa_supplicant_event_global(global->ctx, EVENT_INTERFACE_STATUS,
+ &event);
}
static void wpa_driver_nl80211_event_dellink(
- struct wpa_driver_nl80211_data *drv, const char *ifname)
+ struct nl80211_global *global, struct wpa_driver_nl80211_data *drv,
+ int ifindex, const char *ifname)
{
union wpa_event_data event;
- if (os_strcmp(drv->first_bss->ifname, ifname) == 0) {
+ if (drv && os_strcmp(drv->first_bss->ifname, ifname) == 0) {
if (drv->if_removed) {
wpa_printf(MSG_DEBUG, "nl80211: if_removed already set - ignore RTM_DELLINK event for %s",
ifname);
}
os_memset(&event, 0, sizeof(event));
+ event.interface_status.ifindex = ifindex;
os_strlcpy(event.interface_status.ifname, ifname,
sizeof(event.interface_status.ifname));
event.interface_status.ievent = EVENT_INTERFACE_REMOVED;
- wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
+ if (drv)
+ wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);
+ else
+ wpa_supplicant_event_global(global->ctx, EVENT_INTERFACE_STATUS,
+ &event);
}
dl_list_for_each(drv, &global->interfaces,
struct wpa_driver_nl80211_data, list) {
if (wpa_driver_nl80211_own_ifindex(drv, idx, buf, len) ||
- have_ifidx(drv, idx))
+ have_ifidx(drv, idx, IFIDX_ANY))
return drv;
}
return NULL;
char ifname[IFNAMSIZ + 1];
char extra[100], *pos, *end;
- drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
- if (!drv) {
- wpa_printf(MSG_DEBUG, "nl80211: Ignore RTM_NEWLINK event for foreign ifindex %d",
- ifi->ifi_index);
- return;
- }
-
extra[0] = '\0';
pos = extra;
end = pos + sizeof(extra);
(ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
(ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
+ drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
+ if (!drv)
+ goto event_newlink;
+
if (!drv->if_disabled && !(ifi->ifi_flags & IFF_UP)) {
namebuf[0] = '\0';
if (if_indextoname(ifi->ifi_index, namebuf) &&
-1, IF_OPER_UP);
}
+event_newlink:
if (ifname[0])
- wpa_driver_nl80211_event_newlink(drv, ifname);
+ wpa_driver_nl80211_event_newlink(global, drv, ifi->ifi_index,
+ ifname);
- if (ifi->ifi_family == AF_BRIDGE && brid) {
+ if (ifi->ifi_family == AF_BRIDGE && brid && drv) {
struct i802_bss *bss;
/* device has been added to bridge */
}
wpa_printf(MSG_DEBUG, "nl80211: Add ifindex %u for bridge %s",
brid, namebuf);
- add_ifidx(drv, brid);
+ add_ifidx(drv, brid, ifi->ifi_index);
for (bss = drv->first_bss; bss; bss = bss->next) {
if (os_strcmp(ifname, bss->ifname) == 0) {
char ifname[IFNAMSIZ + 1];
char extra[100], *pos, *end;
- drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
- if (!drv) {
- wpa_printf(MSG_DEBUG, "nl80211: Ignore RTM_DELLINK event for foreign ifindex %d",
- ifi->ifi_index);
- return;
- }
-
extra[0] = '\0';
pos = extra;
end = pos + sizeof(extra);
(ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
(ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
- if (ifname[0] && (ifi->ifi_family != AF_BRIDGE || !brid))
- wpa_driver_nl80211_event_dellink(drv, ifname);
+ drv = nl80211_find_drv(global, ifi->ifi_index, buf, len);
- if (ifi->ifi_family == AF_BRIDGE && brid) {
+ if (ifi->ifi_family == AF_BRIDGE && brid && drv) {
/* device has been removed from bridge */
char namebuf[IFNAMSIZ];
"nl80211: Remove ifindex %u for bridge %s",
brid, namebuf);
}
- del_ifidx(drv, brid);
+ del_ifidx(drv, brid, ifi->ifi_index);
}
+
+ if (ifi->ifi_family != AF_BRIDGE || !brid)
+ wpa_driver_nl80211_event_dellink(global, drv, ifi->ifi_index,
+ ifname);
}
static void wpa_driver_nl80211_rfkill_blocked(void *ctx)
{
+ struct wpa_driver_nl80211_data *drv = ctx;
+
wpa_printf(MSG_DEBUG, "nl80211: RFKILL blocked");
+
/*
- * This may be for any interface; use ifdown event to disable
- * interface.
+ * rtnetlink ifdown handler will report interfaces other than the P2P
+ * Device interface as disabled.
*/
+ if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
+ wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_DISABLED, NULL);
}
"after rfkill unblock");
return;
}
- /* rtnetlink ifup handler will report interface as enabled */
+
+ if (is_p2p_net_interface(drv->nlmode))
+ nl80211_disable_11b_rates(drv, drv->ifindex, 1);
+
+ /*
+ * rtnetlink ifup handler will report interfaces other than the P2P
+ * Device interface as enabled.
+ */
+ if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
+ wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, NULL);
}
}
+static void
+wpa_driver_nl80211_drv_init_rfkill(struct wpa_driver_nl80211_data *drv)
+{
+ struct rfkill_config *rcfg;
+
+ if (drv->rfkill)
+ return;
+
+ rcfg = os_zalloc(sizeof(*rcfg));
+ if (!rcfg)
+ return;
+
+ rcfg->ctx = drv;
+
+ /* rfkill uses netdev sysfs for initialization. However, P2P Device is
+ * not associated with a netdev, so use the name of some other interface
+ * sharing the same wiphy as the P2P Device interface.
+ *
+ * Note: This is valid, as a P2P Device interface is always dynamically
+ * created and is created only once another wpa_s interface was added.
+ */
+ if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE) {
+ struct nl80211_global *global = drv->global;
+ struct wpa_driver_nl80211_data *tmp1;
+
+ dl_list_for_each(tmp1, &global->interfaces,
+ struct wpa_driver_nl80211_data, list) {
+ if (drv == tmp1 || drv->wiphy_idx != tmp1->wiphy_idx ||
+ !tmp1->rfkill)
+ continue;
+
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Use (%s) to initialize P2P Device rfkill",
+ tmp1->first_bss->ifname);
+ os_strlcpy(rcfg->ifname, tmp1->first_bss->ifname,
+ sizeof(rcfg->ifname));
+ break;
+ }
+ } else {
+ os_strlcpy(rcfg->ifname, drv->first_bss->ifname,
+ sizeof(rcfg->ifname));
+ }
+
+ rcfg->blocked_cb = wpa_driver_nl80211_rfkill_blocked;
+ rcfg->unblocked_cb = wpa_driver_nl80211_rfkill_unblocked;
+ drv->rfkill = rfkill_init(rcfg);
+ if (!drv->rfkill) {
+ wpa_printf(MSG_DEBUG, "nl80211: RFKILL status not available");
+ os_free(rcfg);
+ }
+}
+
+
static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname,
void *global_priv, int hostapd,
const u8 *set_addr,
const char *driver_params)
{
struct wpa_driver_nl80211_data *drv;
- struct rfkill_config *rcfg;
struct i802_bss *bss;
if (global_priv == NULL)
drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);
drv->if_indices = drv->default_if_indices;
+ drv->if_indices_reason = drv->default_if_indices_reason;
drv->first_bss = os_zalloc(sizeof(*drv->first_bss));
if (!drv->first_bss) {
if (nl80211_init_bss(bss))
goto failed;
- rcfg = os_zalloc(sizeof(*rcfg));
- if (rcfg == NULL)
- goto failed;
- rcfg->ctx = drv;
- os_strlcpy(rcfg->ifname, ifname, sizeof(rcfg->ifname));
- rcfg->blocked_cb = wpa_driver_nl80211_rfkill_blocked;
- rcfg->unblocked_cb = wpa_driver_nl80211_rfkill_unblocked;
- drv->rfkill = rfkill_init(rcfg);
- if (drv->rfkill == NULL) {
- wpa_printf(MSG_DEBUG, "nl80211: RFKILL status not available");
- os_free(rcfg);
- }
-
- if (linux_iface_up(drv->global->ioctl_sock, ifname) > 0)
- drv->start_iface_up = 1;
-
if (wpa_driver_nl80211_finish_drv_init(drv, set_addr, 1, driver_params))
goto failed;
if (nl80211_register_action_frame(bss, (u8 *) "\x05\x05", 2) < 0)
ret = -1;
+ /* Radio Measurement - Radio Measurement Request */
+ if (nl80211_register_action_frame(bss, (u8 *) "\x05\x00", 2) < 0)
+ ret = -1;
+
/* Radio Measurement - Link Measurement Request */
if ((drv->capa.rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION) &&
(nl80211_register_action_frame(bss, (u8 *) "\x05\x02", 2) < 0))
}
+static int nl80211_action_subscribe_ap(struct i802_bss *bss)
+{
+ int ret = 0;
+
+ /* Public Action frames */
+ if (nl80211_register_action_frame(bss, (u8 *) "\x04", 1) < 0)
+ ret = -1;
+ /* RRM Measurement Report */
+ if (nl80211_register_action_frame(bss, (u8 *) "\x05\x01", 2) < 0)
+ ret = -1;
+ /* RRM Neighbor Report Request */
+ if (nl80211_register_action_frame(bss, (u8 *) "\x05\x04", 2) < 0)
+ ret = -1;
+ /* FT Action frames */
+ if (nl80211_register_action_frame(bss, (u8 *) "\x06", 1) < 0)
+ ret = -1;
+#ifdef CONFIG_IEEE80211W
+ /* SA Query */
+ if (nl80211_register_action_frame(bss, (u8 *) "\x08", 1) < 0)
+ ret = -1;
+#endif /* CONFIG_IEEE80211W */
+ /* Protected Dual of Public Action */
+ if (nl80211_register_action_frame(bss, (u8 *) "\x09", 1) < 0)
+ ret = -1;
+ /* WNM */
+ if (nl80211_register_action_frame(bss, (u8 *) "\x0a", 1) < 0)
+ ret = -1;
+ /* WMM */
+ if (nl80211_register_action_frame(bss, (u8 *) "\x11", 1) < 0)
+ ret = -1;
+#ifdef CONFIG_FST
+ /* FST Action frames */
+ if (nl80211_register_action_frame(bss, (u8 *) "\x12", 1) < 0)
+ ret = -1;
+#endif /* CONFIG_FST */
+ /* Vendor-specific */
+ if (nl80211_register_action_frame(bss, (u8 *) "\x7f", 1) < 0)
+ ret = -1;
+
+ return ret;
+}
+
+
static int nl80211_mgmt_subscribe_ap(struct i802_bss *bss)
{
static const int stypes[] = {
WLAN_FC_STYPE_REASSOC_REQ,
WLAN_FC_STYPE_DISASSOC,
WLAN_FC_STYPE_DEAUTH,
- WLAN_FC_STYPE_ACTION,
WLAN_FC_STYPE_PROBE_REQ,
/* Beacon doesn't work as mac80211 doesn't currently allow
* it, but it wouldn't really be the right thing anyway as
}
}
+ if (nl80211_action_subscribe_ap(bss))
+ goto out_err;
+
if (nl80211_register_spurious_class3(bss))
goto out_err;
wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with AP "
"handle %p (device SME)", bss->nl_mgmt);
- if (nl80211_register_frame(bss, bss->nl_mgmt,
- (WLAN_FC_TYPE_MGMT << 2) |
- (WLAN_FC_STYPE_ACTION << 4),
- NULL, 0) < 0)
+ if (nl80211_action_subscribe_ap(bss))
goto out_err;
nl80211_mgmt_handle_register_eloop(bss);
if (!bss->if_dynamic && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP)
bss->static_ap = 1;
+ if (first &&
+ nl80211_get_ifmode(bss) != NL80211_IFTYPE_P2P_DEVICE &&
+ linux_iface_up(drv->global->ioctl_sock, bss->ifname) > 0)
+ drv->start_iface_up = 1;
+
if (wpa_driver_nl80211_capa(drv))
return -1;
if (drv->hostapd || bss->static_ap)
nlmode = NL80211_IFTYPE_AP;
- else if (bss->if_dynamic)
+ else if (bss->if_dynamic ||
+ nl80211_get_ifmode(bss) == NL80211_IFTYPE_MESH_POINT)
nlmode = nl80211_get_ifmode(bss);
else
nlmode = NL80211_IFTYPE_STATION;
if (nlmode == NL80211_IFTYPE_P2P_DEVICE)
nl80211_get_macaddr(bss);
+ wpa_driver_nl80211_drv_init_rfkill(drv);
+
if (!rfkill_is_blocked(drv->rfkill)) {
int ret = i802_set_iface_flags(bss, 1);
if (ret) {
"interface '%s' UP", bss->ifname);
return ret;
}
+
+ if (is_p2p_net_interface(nlmode))
+ nl80211_disable_11b_rates(bss->drv,
+ bss->drv->ifindex, 1);
+
if (nlmode == NL80211_IFTYPE_P2P_DEVICE)
return ret;
} else {
wpa_printf(MSG_DEBUG, "nl80211: Could not yet enable "
"interface '%s' due to rfkill", bss->ifname);
- if (nlmode == NL80211_IFTYPE_P2P_DEVICE)
- return 0;
- drv->if_disabled = 1;
+ if (nlmode != NL80211_IFTYPE_P2P_DEVICE)
+ drv->if_disabled = 1;
+
send_rfkill_event = 1;
}
- if (!drv->hostapd)
+ if (!drv->hostapd && nlmode != NL80211_IFTYPE_P2P_DEVICE)
netlink_send_oper_ifla(drv->global->netlink, drv->ifindex,
1, IF_OPER_DORMANT);
- if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
- bss->addr))
- return -1;
- os_memcpy(drv->perm_addr, bss->addr, ETH_ALEN);
+ if (nlmode != NL80211_IFTYPE_P2P_DEVICE) {
+ if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname,
+ bss->addr))
+ return -1;
+ os_memcpy(drv->perm_addr, bss->addr, ETH_ALEN);
+ }
if (send_rfkill_event) {
eloop_register_timeout(0, 0, wpa_driver_nl80211_send_rfkill,
static void wpa_driver_nl80211_deinit(struct i802_bss *bss)
{
struct wpa_driver_nl80211_data *drv = bss->drv;
+ unsigned int i;
wpa_printf(MSG_INFO, "nl80211: deinit ifname=%s disabled_11b_rates=%d",
bss->ifname, drv->disabled_11b_rates);
if (drv->if_indices != drv->default_if_indices)
os_free(drv->if_indices);
+ if (drv->if_indices_reason != drv->default_if_indices_reason)
+ os_free(drv->if_indices_reason);
+
if (drv->disabled_11b_rates)
nl80211_disable_11b_rates(drv, drv->ifindex, 0);
os_free(drv->extended_capa);
os_free(drv->extended_capa_mask);
+ for (i = 0; i < drv->num_iface_ext_capa; i++) {
+ os_free(drv->iface_ext_capa[i].ext_capa);
+ os_free(drv->iface_ext_capa[i].ext_capa_mask);
+ }
os_free(drv->first_bss);
os_free(drv);
}
}
+#ifdef CONFIG_DRIVER_NL80211_QCA
static int issue_key_mgmt_set_key(struct wpa_driver_nl80211_data *drv,
const u8 *key, size_t key_len)
{
return ret;
}
+#endif /* CONFIG_DRIVER_NL80211_QCA */
static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
}
#endif /* CONFIG_TDLS */
+#ifdef CONFIG_DRIVER_NL80211_QCA
if (alg == WPA_ALG_PMK &&
(drv->capa.flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD)) {
wpa_printf(MSG_DEBUG, "%s: calling issue_key_mgmt_set_key",
ret = issue_key_mgmt_set_key(drv, key, key_len);
return ret;
}
+#endif /* CONFIG_DRIVER_NL80211_QCA */
if (alg == WPA_ALG_NONE) {
msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_DEL_KEY);
const void *data, size_t len,
int encrypt, int noack,
unsigned int freq, int no_cck,
- int offchanok, unsigned int wait_time)
+ int offchanok, unsigned int wait_time,
+ const u16 *csa_offs,
+ size_t csa_offs_len)
{
struct wpa_driver_nl80211_data *drv = bss->drv;
u64 cookie;
wpa_printf(MSG_DEBUG, "nl80211: send_frame -> send_frame_cmd");
res = nl80211_send_frame_cmd(bss, freq, wait_time, data, len,
- &cookie, no_cck, noack, offchanok);
+ &cookie, no_cck, noack, offchanok,
+ csa_offs, csa_offs_len);
if (res == 0 && !noack) {
const struct ieee80211_mgmt *mgmt;
u16 fc;
size_t data_len, int noack,
unsigned int freq, int no_cck,
int offchanok,
- unsigned int wait_time)
+ unsigned int wait_time,
+ const u16 *csa_offs,
+ size_t csa_offs_len)
{
struct wpa_driver_nl80211_data *drv = bss->drv;
struct ieee80211_mgmt *mgmt;
}
return nl80211_send_frame_cmd(bss, freq, 0,
data, data_len, NULL, 1, noack,
- 1);
+ 1, csa_offs, csa_offs_len);
}
if (drv->device_ap_sme && is_ap_interface(drv->nlmode)) {
wait_time,
data, data_len,
&drv->send_action_cookie,
- no_cck, noack, offchanok);
+ no_cck, noack, offchanok,
+ csa_offs, csa_offs_len);
}
if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
wpa_printf(MSG_DEBUG, "nl80211: send_mlme -> send_frame");
return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt,
noack, freq, no_cck, offchanok,
- wait_time);
+ wait_time, csa_offs,
+ csa_offs_len);
}
}
+static int nl80211_put_dtim_period(struct nl_msg *msg, int dtim_period)
+{
+ if (dtim_period > 0) {
+ wpa_printf(MSG_DEBUG, " * dtim_period=%d", dtim_period);
+ return nla_put_u32(msg, NL80211_ATTR_DTIM_PERIOD, dtim_period);
+ }
+
+ return 0;
+}
+
+
+#ifdef CONFIG_MESH
+static int nl80211_set_mesh_config(void *priv,
+ struct wpa_driver_mesh_bss_params *params)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ int ret;
+
+ msg = nl80211_drv_msg(drv, 0, NL80211_CMD_SET_MESH_CONFIG);
+ if (!msg)
+ return -1;
+
+ ret = nl80211_put_mesh_config(msg, params);
+ if (ret < 0) {
+ nlmsg_free(msg);
+ return ret;
+ }
+
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ if (ret) {
+ wpa_printf(MSG_ERROR,
+ "nl80211: Mesh config set failed: %d (%s)",
+ ret, strerror(-ret));
+ return ret;
+ }
+ return 0;
+}
+#endif /* CONFIG_MESH */
+
+
static int wpa_driver_nl80211_set_ap(void *priv,
struct wpa_driver_ap_params *params)
{
int smps_mode;
u32 suites[10], suite;
u32 ver;
+#ifdef CONFIG_MESH
+ struct wpa_driver_mesh_bss_params mesh_params;
+#endif /* CONFIG_MESH */
beacon_set = params->reenable ? 0 : bss->beacon_set;
nla_put(msg, NL80211_ATTR_BEACON_TAIL, params->tail_len,
params->tail) ||
nl80211_put_beacon_int(msg, params->beacon_int) ||
- nla_put_u32(msg, NL80211_ATTR_DTIM_PERIOD, params->dtim_period) ||
+ nl80211_put_dtim_period(msg, params->dtim_period) ||
nla_put(msg, NL80211_ATTR_SSID, params->ssid_len, params->ssid))
goto fail;
if (params->proberesp && params->proberesp_len) {
goto fail;
if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
- params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40) &&
- nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT))
+ (!params->pairwise_ciphers ||
+ params->pairwise_ciphers & (WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40)) &&
+ (nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, ETH_P_PAE) ||
+ nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
goto fail;
wpa_printf(MSG_DEBUG, "nl80211: pairwise_ciphers=0x%x",
nla_put_u32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, suite))
goto fail;
- switch (params->smps_mode) {
- case HT_CAP_INFO_SMPS_DYNAMIC:
- wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - dynamic");
- smps_mode = NL80211_SMPS_DYNAMIC;
- break;
- case HT_CAP_INFO_SMPS_STATIC:
- wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - static");
- smps_mode = NL80211_SMPS_STATIC;
- break;
- default:
- /* invalid - fallback to smps off */
- case HT_CAP_INFO_SMPS_DISABLED:
- wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - off");
- smps_mode = NL80211_SMPS_OFF;
- break;
+ if (params->ht_opmode != -1) {
+ switch (params->smps_mode) {
+ case HT_CAP_INFO_SMPS_DYNAMIC:
+ wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - dynamic");
+ smps_mode = NL80211_SMPS_DYNAMIC;
+ break;
+ case HT_CAP_INFO_SMPS_STATIC:
+ wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - static");
+ smps_mode = NL80211_SMPS_STATIC;
+ break;
+ default:
+ /* invalid - fallback to smps off */
+ case HT_CAP_INFO_SMPS_DISABLED:
+ wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - off");
+ smps_mode = NL80211_SMPS_OFF;
+ break;
+ }
+ if (nla_put_u32(msg, NL80211_ATTR_SMPS_MODE, smps_mode))
+ goto fail;
}
- if (nla_put_u32(msg, NL80211_ATTR_SMPS_MODE, smps_mode))
- goto fail;
if (params->beacon_ies) {
wpa_hexdump_buf(MSG_DEBUG, "nl80211: beacon_ies",
}
#endif /* CONFIG_P2P */
+ if (params->pbss) {
+ wpa_printf(MSG_DEBUG, "nl80211: PBSS");
+ if (nla_put_flag(msg, NL80211_ATTR_PBSS))
+ goto fail;
+ }
+
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
if (ret) {
wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)",
"nl80211: Frequency set succeeded for ht2040 coex");
bss->bandwidth = params->freq->bandwidth;
}
- } else if (!beacon_set) {
+ } else if (!beacon_set && params->freq) {
/*
* cfg80211 updates the driver on frequence change in AP
* mode only at the point when beaconing is started, so
bss->bandwidth = params->freq->bandwidth;
}
}
+
+#ifdef CONFIG_MESH
+ if (is_mesh_interface(drv->nlmode) && params->ht_opmode != -1) {
+ os_memset(&mesh_params, 0, sizeof(mesh_params));
+ mesh_params.flags |= WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE;
+ mesh_params.ht_opmode = params->ht_opmode;
+ ret = nl80211_set_mesh_config(priv, &mesh_params);
+ if (ret < 0)
+ return ret;
+ }
+#endif /* CONFIG_MESH */
+
return ret;
fail:
nlmsg_free(msg);
wpa_printf(MSG_DEBUG, " * channel_type=%d", ct);
if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, ct))
return -ENOBUFS;
+ } else {
+ wpa_printf(MSG_DEBUG, " * channel_type=%d",
+ NL80211_CHAN_NO_HT);
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
+ NL80211_CHAN_NO_HT))
+ return -ENOBUFS;
}
return 0;
}
f |= BIT(NL80211_STA_FLAG_TDLS_PEER);
if (flags & WPA_STA_AUTHENTICATED)
f |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
+ if (flags & WPA_STA_ASSOCIATED)
+ f |= BIT(NL80211_STA_FLAG_ASSOCIATED);
return f;
}
static u32 sta_plink_state_nl80211(enum mesh_plink_state state)
{
switch (state) {
- case PLINK_LISTEN:
+ case PLINK_IDLE:
return NL80211_PLINK_LISTEN;
- case PLINK_OPEN_SENT:
+ case PLINK_OPN_SNT:
return NL80211_PLINK_OPN_SNT;
- case PLINK_OPEN_RCVD:
+ case PLINK_OPN_RCVD:
return NL80211_PLINK_OPN_RCVD;
case PLINK_CNF_RCVD:
return NL80211_PLINK_CNF_RCVD;
if (!msg || nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr))
goto fail;
- if (!params->set || (params->flags & WPA_STA_TDLS_PEER)) {
+ /*
+ * Set the below properties only in one of the following cases:
+ * 1. New station is added, already associated.
+ * 2. Set WPA_STA_TDLS_PEER station.
+ * 3. Set an already added unassociated station, if driver supports
+ * full AP client state. (Set these properties after station became
+ * associated will be rejected by the driver).
+ */
+ if (!params->set || (params->flags & WPA_STA_TDLS_PEER) ||
+ (params->set && FULL_AP_CLIENT_STATE_SUPP(drv->capa.flags) &&
+ (params->flags & WPA_STA_ASSOCIATED))) {
wpa_hexdump(MSG_DEBUG, " * supported rates",
params->supp_rates, params->supp_rates_len);
wpa_printf(MSG_DEBUG, " * capability=0x%x",
params->ext_capab_len, params->ext_capab))
goto fail;
}
+
+ if (is_ap_interface(drv->nlmode) &&
+ nla_put_u8(msg, NL80211_ATTR_STA_SUPPORT_P2P_PS,
+ params->support_p2p_ps ?
+ NL80211_P2P_PS_SUPPORTED :
+ NL80211_P2P_PS_UNSUPPORTED))
+ goto fail;
}
if (!params->set) {
if (params->aid) {
/*
* cfg80211 validates that AID is non-zero, so we have
* to make this a non-zero value for the TDLS case where
- * a dummy STA entry is used for now.
+ * a dummy STA entry is used for now and for a station
+ * that is still not associated.
*/
- wpa_printf(MSG_DEBUG, " * aid=1 (TDLS workaround)");
+ wpa_printf(MSG_DEBUG, " * aid=1 (%s workaround)",
+ (params->flags & WPA_STA_TDLS_PEER) ?
+ "TDLS" : "UNASSOC_STA");
if (nla_put_u16(msg, NL80211_ATTR_STA_AID, 1))
goto fail;
}
wpa_printf(MSG_DEBUG, " * peer_aid=%u", params->aid);
if (nla_put_u16(msg, NL80211_ATTR_PEER_AID, params->aid))
goto fail;
+ } else if (FULL_AP_CLIENT_STATE_SUPP(drv->capa.flags) &&
+ (params->flags & WPA_STA_ASSOCIATED)) {
+ wpa_printf(MSG_DEBUG, " * aid=%u", params->aid);
+ wpa_printf(MSG_DEBUG, " * listen_interval=%u",
+ params->listen_interval);
+ if (nla_put_u16(msg, NL80211_ATTR_STA_AID, params->aid) ||
+ nla_put_u16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL,
+ params->listen_interval))
+ goto fail;
}
if (params->vht_opmode_enabled) {
os_memset(&upd, 0, sizeof(upd));
upd.set = sta_flags_nl80211(params->flags);
upd.mask = upd.set | sta_flags_nl80211(params->flags_mask);
+
+ /*
+ * If the driver doesn't support full AP client state, ignore ASSOC/AUTH
+ * flags, as nl80211 driver moves a new station, by default, into
+ * associated state.
+ *
+ * On the other hand, if the driver supports that feature and the
+ * station is added in unauthenticated state, set the
+ * authenticated/associated bits in the mask to prevent moving this
+ * station to associated state before it is actually associated.
+ *
+ * This is irrelevant for mesh mode where the station is added to the
+ * driver as authenticated already, and ASSOCIATED isn't part of the
+ * nl80211 API.
+ */
+ if (!is_mesh_interface(drv->nlmode)) {
+ if (!FULL_AP_CLIENT_STATE_SUPP(drv->capa.flags)) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Ignore ASSOC/AUTH flags since driver doesn't support full AP client state");
+ upd.mask &= ~(BIT(NL80211_STA_FLAG_ASSOCIATED) |
+ BIT(NL80211_STA_FLAG_AUTHENTICATED));
+ } else if (!params->set &&
+ !(params->flags & WPA_STA_TDLS_PEER)) {
+ if (!(params->flags & WPA_STA_AUTHENTICATED))
+ upd.mask |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
+ if (!(params->flags & WPA_STA_ASSOCIATED))
+ upd.mask |= BIT(NL80211_STA_FLAG_ASSOCIATED);
+ }
+#ifdef CONFIG_MESH
+ } else {
+ if (params->plink_state == PLINK_ESTAB && params->peer_aid) {
+ ret = nla_put_u16(msg, NL80211_ATTR_MESH_PEER_AID,
+ params->peer_aid);
+ if (ret)
+ goto fail;
+ }
+#endif /* CONFIG_MESH */
+ }
+
wpa_printf(MSG_DEBUG, " * flags set=0x%x mask=0x%x",
upd.set, upd.mask);
if (nla_put(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd))
/* stop listening for EAPOL on this interface */
dl_list_for_each(drv2, &drv->global->interfaces,
struct wpa_driver_nl80211_data, list)
- del_ifidx(drv2, ifidx);
+ {
+ del_ifidx(drv2, ifidx, IFIDX_ANY);
+ /* Remove all bridges learned for this iface */
+ del_ifidx(drv2, IFIDX_ANY, ifidx);
+ }
msg = nl80211_ifindex_msg(drv, ifidx, 0, NL80211_CMD_DEL_INTERFACE);
if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
}
-static const char * nl80211_iftype_str(enum nl80211_iftype mode)
+const char * nl80211_iftype_str(enum nl80211_iftype mode)
{
switch (mode) {
case NL80211_IFTYPE_ADHOC:
iftype == NL80211_IFTYPE_WDS ||
iftype == NL80211_IFTYPE_MONITOR) {
/* start listening for EAPOL on this interface */
- add_ifidx(drv, ifidx);
+ add_ifidx(drv, ifidx, IFIDX_ANY);
}
if (addr && iftype != NL80211_IFTYPE_MONITOR &&
if (drv->device_ap_sme && !drv->use_monitor)
if (nl80211_mgmt_subscribe_ap_dev_sme(bss))
- return -1;
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Failed to subscribe for mgmt frames from SME driver - trying to run without it");
if (!drv->device_ap_sme && drv->use_monitor &&
nl80211_create_monitor_interface(drv) &&
memcpy(pos, data, data_len);
res = wpa_driver_nl80211_send_frame(bss, (u8 *) hdr, len, encrypt, 0,
- 0, 0, 0, 0);
+ 0, 0, 0, 0, NULL, 0);
if (res < 0) {
wpa_printf(MSG_ERROR, "i802_send_eapol - packet len: %lu - "
"failed: %d (%s)",
goto fail;
}
- if (nl80211_ht_vht_overrides(msg, params) < 0)
- return -1;
+ ret = nl80211_ht_vht_overrides(msg, params);
+ if (ret < 0)
+ goto fail;
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
msg = NULL;
if (nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT))
return -1;
+ if (params->key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
+ (params->pairwise_suite == WPA_CIPHER_NONE ||
+ params->pairwise_suite == WPA_CIPHER_WEP104 ||
+ params->pairwise_suite == WPA_CIPHER_WEP40) &&
+ (nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, ETH_P_PAE) ||
+ nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))
+ return -1;
+
if (params->mgmt_frame_protection == MGMT_FRAME_PROTECTION_REQUIRED &&
nla_put_u32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_REQUIRED))
return -1;
if (params->rrm_used) {
u32 drv_rrm_flags = drv->capa.rrm_flags;
- if (!(drv_rrm_flags &
- WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES) ||
- !(drv_rrm_flags & WPA_DRIVER_FLAGS_QUIET) ||
+ if ((!((drv_rrm_flags &
+ WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES) &&
+ (drv_rrm_flags & WPA_DRIVER_FLAGS_QUIET)) &&
+ !(drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_RRM)) ||
nla_put_flag(msg, NL80211_ATTR_USE_RRM))
return -1;
}
if (params->p2p)
wpa_printf(MSG_DEBUG, " * P2P group");
+ if (params->pbss) {
+ wpa_printf(MSG_DEBUG, " * PBSS");
+ if (nla_put_flag(msg, NL80211_ATTR_PBSS))
+ return -1;
+ }
+
+ drv->connect_reassoc = 0;
+ if (params->prev_bssid) {
+ wpa_printf(MSG_DEBUG, " * prev_bssid=" MACSTR,
+ MAC2STR(params->prev_bssid));
+ if (nla_put(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,
+ params->prev_bssid))
+ return -1;
+ drv->connect_reassoc = 1;
+ }
+
return 0;
}
int ret;
int algs;
+#ifdef CONFIG_DRIVER_NL80211_QCA
if (params->req_key_mgmt_offload && params->psk &&
(params->key_mgmt_suite == WPA_KEY_MGMT_PSK ||
params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
if (ret)
return ret;
}
+#endif /* CONFIG_DRIVER_NL80211_QCA */
wpa_printf(MSG_DEBUG, "nl80211: Connect (ifindex=%d)", drv->ifindex);
msg = nl80211_drv_msg(drv, 0, NL80211_CMD_CONNECT);
if (ret)
goto fail;
- if (params->prev_bssid) {
- wpa_printf(MSG_DEBUG, " * prev_bssid=" MACSTR,
- MAC2STR(params->prev_bssid));
- if (nla_put(msg, NL80211_ATTR_PREV_BSSID, ETH_ALEN,
- params->prev_bssid))
- goto fail;
- }
-
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
msg = NULL;
if (ret) {
int res;
int mode_switch_res;
+ if (TEST_FAIL())
+ return -1;
+
mode_switch_res = nl80211_set_mode(drv, drv->ifindex, nlmode);
if (mode_switch_res && nlmode == nl80211_get_ifmode(bss))
mode_switch_res = 0;
[NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
[NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
[NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_RX_BYTES64] = { .type = NLA_U64 },
+ [NL80211_STA_INFO_TX_BYTES64] = { .type = NLA_U64 },
};
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
if (stats[NL80211_STA_INFO_INACTIVE_TIME])
data->inactive_msec =
nla_get_u32(stats[NL80211_STA_INFO_INACTIVE_TIME]);
+ /* For backwards compatibility, fetch the 32-bit counters first. */
if (stats[NL80211_STA_INFO_RX_BYTES])
data->rx_bytes = nla_get_u32(stats[NL80211_STA_INFO_RX_BYTES]);
if (stats[NL80211_STA_INFO_TX_BYTES])
data->tx_bytes = nla_get_u32(stats[NL80211_STA_INFO_TX_BYTES]);
+ if (stats[NL80211_STA_INFO_RX_BYTES64] &&
+ stats[NL80211_STA_INFO_TX_BYTES64]) {
+ /*
+ * The driver supports 64-bit counters, so use them to override
+ * the 32-bit values.
+ */
+ data->rx_bytes =
+ nla_get_u64(stats[NL80211_STA_INFO_RX_BYTES64]);
+ data->tx_bytes =
+ nla_get_u64(stats[NL80211_STA_INFO_TX_BYTES64]);
+ data->bytes_64bit = 1;
+ }
if (stats[NL80211_STA_INFO_RX_PACKETS])
data->rx_packets =
nla_get_u32(stats[NL80211_STA_INFO_RX_PACKETS]);
return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
IEEE80211_HDRLEN +
sizeof(mgmt.u.deauth), 0, 0, 0, 0,
- 0);
+ 0, NULL, 0);
}
return wpa_driver_nl80211_send_mlme(bss, (u8 *) &mgmt,
IEEE80211_HDRLEN +
sizeof(mgmt.u.disassoc), 0, 0, 0, 0,
- 0);
+ 0, NULL, 0);
}
for (i = 0; i < drv->num_if_indices; i++) {
if (!drv->if_indices[i])
continue;
- res = os_snprintf(pos, end - pos, " %d", drv->if_indices[i]);
+ res = os_snprintf(pos, end - pos, " %d(%d)",
+ drv->if_indices[i],
+ drv->if_indices_reason[i]);
if (os_snprintf_error(end - pos, res))
break;
pos += res;
}
-static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
+static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
+ int ifidx_reason)
{
int i;
- int *old;
+ int *old, *old_reason;
- wpa_printf(MSG_DEBUG, "nl80211: Add own interface ifindex %d",
- ifidx);
- if (have_ifidx(drv, ifidx)) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Add own interface ifindex %d (ifidx_reason %d)",
+ ifidx, ifidx_reason);
+ if (have_ifidx(drv, ifidx, ifidx_reason)) {
wpa_printf(MSG_DEBUG, "nl80211: ifindex %d already in the list",
ifidx);
return;
for (i = 0; i < drv->num_if_indices; i++) {
if (drv->if_indices[i] == 0) {
drv->if_indices[i] = ifidx;
+ drv->if_indices_reason[i] = ifidx_reason;
dump_ifidx(drv);
return;
}
else
old = NULL;
+ if (drv->if_indices_reason != drv->default_if_indices_reason)
+ old_reason = drv->if_indices_reason;
+ else
+ old_reason = NULL;
+
drv->if_indices = os_realloc_array(old, drv->num_if_indices + 1,
sizeof(int));
+ drv->if_indices_reason = os_realloc_array(old_reason,
+ drv->num_if_indices + 1,
+ sizeof(int));
if (!drv->if_indices) {
if (!old)
drv->if_indices = drv->default_if_indices;
else
drv->if_indices = old;
+ }
+ if (!drv->if_indices_reason) {
+ if (!old_reason)
+ drv->if_indices_reason = drv->default_if_indices_reason;
+ else
+ drv->if_indices_reason = old_reason;
+ }
+ if (!drv->if_indices || !drv->if_indices_reason) {
wpa_printf(MSG_ERROR, "Failed to reallocate memory for "
"interfaces");
wpa_printf(MSG_ERROR, "Ignoring EAPOL on interface %d", ifidx);
return;
- } else if (!old)
+ }
+ if (!old)
os_memcpy(drv->if_indices, drv->default_if_indices,
sizeof(drv->default_if_indices));
+ if (!old_reason)
+ os_memcpy(drv->if_indices_reason,
+ drv->default_if_indices_reason,
+ sizeof(drv->default_if_indices_reason));
drv->if_indices[drv->num_if_indices] = ifidx;
+ drv->if_indices_reason[drv->num_if_indices] = ifidx_reason;
drv->num_if_indices++;
dump_ifidx(drv);
}
-static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
+static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
+ int ifidx_reason)
{
int i;
for (i = 0; i < drv->num_if_indices; i++) {
- if (drv->if_indices[i] == ifidx) {
+ if ((drv->if_indices[i] == ifidx || ifidx == IFIDX_ANY) &&
+ (drv->if_indices_reason[i] == ifidx_reason ||
+ ifidx_reason == IFIDX_ANY)) {
drv->if_indices[i] = 0;
break;
}
}
-static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx)
+static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx,
+ int ifidx_reason)
{
int i;
for (i = 0; i < drv->num_if_indices; i++)
- if (drv->if_indices[i] == ifidx)
+ if (drv->if_indices[i] == ifidx &&
+ (drv->if_indices_reason[i] == ifidx_reason ||
+ ifidx_reason == IFIDX_ANY))
return 1;
return 0;
return;
}
- if (have_ifidx(drv, lladdr.sll_ifindex))
+ if (have_ifidx(drv, lladdr.sll_ifindex, IFIDX_ANY))
drv_event_eapol_rx(drv->ctx, lladdr.sll_addr, buf, len);
}
}
bss->added_bridge = 1;
br_ifindex = if_nametoindex(brname);
- add_ifidx(drv, br_ifindex);
+ add_ifidx(drv, br_ifindex, drv->ifindex);
}
bss->br_ifindex = br_ifindex;
wpa_printf(MSG_DEBUG, "nl80211: Interface %s is in master %s",
params->ifname, master_ifname);
/* start listening for EAPOL on the master interface */
- add_ifidx(drv, if_nametoindex(master_ifname));
+ add_ifidx(drv, if_nametoindex(master_ifname), drv->ifindex);
+
+ /* check if master itself is under bridge */
+ if (linux_br_get(master_ifname, master_ifname) == 0) {
+ wpa_printf(MSG_DEBUG, "nl80211: which is in bridge %s",
+ master_ifname);
+ br_ifindex = if_nametoindex(master_ifname);
+ os_strlcpy(bss->brname, master_ifname, IFNAMSIZ);
+ }
} else {
master_ifname[0] = '\0';
}
if (params->bridge[i]) {
ifindex = if_nametoindex(params->bridge[i]);
if (ifindex)
- add_ifidx(drv, ifindex);
+ add_ifidx(drv, ifindex, drv->ifindex);
if (ifindex == br_ifindex)
br_added = 1;
}
}
/* start listening for EAPOL on the default AP interface */
- add_ifidx(drv, drv->ifindex);
+ add_ifidx(drv, drv->ifindex, IFIDX_ANY);
if (params->num_bridge && params->bridge[0]) {
if (i802_check_bridge(drv, bss, params->bridge[0],
if (!br_added && br_ifindex &&
(params->num_bridge == 0 || !params->bridge[0]))
- add_ifidx(drv, br_ifindex);
+ add_ifidx(drv, br_ifindex, drv->ifindex);
#ifdef CONFIG_LIBNL3_ROUTE
if (bss->added_if_into_bridge) {
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)
{
enum nl80211_iftype nlmode;
struct i802_bss *bss = priv;
os_memcpy(if_addr, new_addr, ETH_ALEN);
}
- if (type == WPA_IF_AP_BSS) {
+ if (type == WPA_IF_AP_BSS && setup_ap) {
struct i802_bss *new_bss = os_zalloc(sizeof(*new_bss));
if (new_bss == NULL) {
if (added)
nlmode == NL80211_IFTYPE_AP_VLAN ||
nlmode == NL80211_IFTYPE_WDS ||
nlmode == NL80211_IFTYPE_MONITOR))
- add_ifidx(drv, ifidx);
+ add_ifidx(drv, ifidx, IFIDX_ANY);
return 0;
}
else if (ifindex > 0 && !bss->added_if) {
struct wpa_driver_nl80211_data *drv2;
dl_list_for_each(drv2, &drv->global->interfaces,
- struct wpa_driver_nl80211_data, list)
- del_ifidx(drv2, ifindex);
+ struct wpa_driver_nl80211_data, list) {
+ del_ifidx(drv2, ifindex, IFIDX_ANY);
+ del_ifidx(drv2, IFIDX_ANY, ifindex);
+ }
}
if (type != WPA_IF_AP_BSS)
unsigned int freq, unsigned int wait,
const u8 *buf, size_t buf_len,
u64 *cookie_out, int no_cck, int no_ack,
- int offchanok)
+ int offchanok, const u16 *csa_offs,
+ size_t csa_offs_len)
{
struct wpa_driver_nl80211_data *drv = bss->drv;
struct nl_msg *msg;
nla_put_flag(msg, NL80211_ATTR_OFFCHANNEL_TX_OK)) ||
(no_cck && nla_put_flag(msg, NL80211_ATTR_TX_NO_CCK_RATE)) ||
(no_ack && nla_put_flag(msg, NL80211_ATTR_DONT_WAIT_FOR_ACK)) ||
+ (csa_offs && nla_put(msg, NL80211_ATTR_CSA_C_OFFSETS_TX,
+ csa_offs_len * sizeof(u16), csa_offs)) ||
nla_put(msg, NL80211_ATTR_FRAME, buf_len, buf))
goto fail;
if (cookie_out)
*cookie_out = no_ack ? (u64) -1 : cookie;
+
+ if (drv->num_send_action_cookies == MAX_SEND_ACTION_COOKIES) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Drop oldest pending send action cookie 0x%llx",
+ (long long unsigned int)
+ drv->send_action_cookies[0]);
+ os_memmove(&drv->send_action_cookies[0],
+ &drv->send_action_cookies[1],
+ (MAX_SEND_ACTION_COOKIES - 1) *
+ sizeof(u64));
+ drv->num_send_action_cookies--;
+ }
+ drv->send_action_cookies[drv->num_send_action_cookies] = cookie;
+ drv->num_send_action_cookies++;
}
fail:
!drv->use_monitor))
ret = wpa_driver_nl80211_send_mlme(bss, buf, 24 + data_len,
0, freq, no_cck, 1,
- wait_time);
+ wait_time, NULL, 0);
else
ret = nl80211_send_frame_cmd(bss, freq, wait_time, buf,
24 + data_len,
&drv->send_action_cookie,
- no_cck, 0, 1);
+ no_cck, 0, 1, NULL, 0);
os_free(buf);
return ret;
}
-static void wpa_driver_nl80211_send_action_cancel_wait(void *priv)
+static void nl80211_frame_wait_cancel(struct i802_bss *bss, u64 cookie)
{
- struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
struct nl_msg *msg;
int ret;
wpa_printf(MSG_DEBUG, "nl80211: Cancel TX frame wait: cookie=0x%llx",
- (long long unsigned int) drv->send_action_cookie);
+ (long long unsigned int) cookie);
if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_FRAME_WAIT_CANCEL)) ||
- nla_put_u64(msg, NL80211_ATTR_COOKIE, drv->send_action_cookie)) {
+ nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie)) {
nlmsg_free(msg);
return;
}
}
+static void wpa_driver_nl80211_send_action_cancel_wait(void *priv)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ unsigned int i;
+ u64 cookie;
+
+ /* Cancel the last pending TX cookie */
+ nl80211_frame_wait_cancel(bss, drv->send_action_cookie);
+
+ /*
+ * Cancel the other pending TX cookies, if any. This is needed since
+ * the driver may keep a list of all pending offchannel TX operations
+ * and free up the radio only once they have expired or cancelled.
+ */
+ for (i = drv->num_send_action_cookies; i > 0; i--) {
+ cookie = drv->send_action_cookies[i - 1];
+ if (cookie != drv->send_action_cookie)
+ nl80211_frame_wait_cancel(bss, cookie);
+ }
+ drv->num_send_action_cookies = 0;
+}
+
+
static int wpa_driver_nl80211_remain_on_channel(void *priv, unsigned int freq,
unsigned int duration)
{
static void wpa_driver_nl80211_resume(void *priv)
{
struct i802_bss *bss = priv;
+ enum nl80211_iftype nlmode = nl80211_get_ifmode(bss);
if (i802_set_iface_flags(bss, 1))
wpa_printf(MSG_DEBUG, "nl80211: Failed to set interface up on resume event");
+
+ if (is_p2p_net_interface(nlmode))
+ nl80211_disable_11b_rates(bss->drv, bss->drv->ifindex, 1);
}
os_memset(si, 0, sizeof(*si));
res = nl80211_get_link_signal(drv, si);
- if (res != 0)
- return res;
+ if (res) {
+ if (drv->nlmode != NL80211_IFTYPE_ADHOC &&
+ drv->nlmode != NL80211_IFTYPE_MESH_POINT)
+ return res;
+ si->current_signal = 0;
+ }
res = nl80211_get_channel_width(drv, si);
if (res != 0)
{
struct i802_bss *bss = priv;
return wpa_driver_nl80211_send_frame(bss, data, data_len, encrypt, 0,
- 0, 0, 0, 0);
+ 0, 0, 0, 0, NULL, 0);
}
static int nl80211_set_param(void *priv, const char *param)
{
- wpa_printf(MSG_DEBUG, "nl80211: driver param='%s'", param);
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+
if (param == NULL)
return 0;
+ wpa_printf(MSG_DEBUG, "nl80211: driver param='%s'", param);
#ifdef CONFIG_P2P
if (os_strstr(param, "use_p2p_group_interface=1")) {
- struct i802_bss *bss = priv;
- struct wpa_driver_nl80211_data *drv = bss->drv;
-
wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group "
"interface");
drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
}
#endif /* CONFIG_P2P */
- if (os_strstr(param, "use_monitor=1")) {
- struct i802_bss *bss = priv;
- struct wpa_driver_nl80211_data *drv = bss->drv;
+ if (os_strstr(param, "use_monitor=1"))
drv->use_monitor = 1;
- }
if (os_strstr(param, "force_connect_cmd=1")) {
- struct i802_bss *bss = priv;
- struct wpa_driver_nl80211_data *drv = bss->drv;
drv->capa.flags &= ~WPA_DRIVER_FLAGS_SME;
drv->force_connect_cmd = 1;
}
+ if (os_strstr(param, "force_bss_selection=1"))
+ drv->capa.flags |= WPA_DRIVER_FLAGS_BSS_SELECTION;
+
if (os_strstr(param, "no_offchannel_tx=1")) {
- struct i802_bss *bss = priv;
- struct wpa_driver_nl80211_data *drv = bss->drv;
drv->capa.flags &= ~WPA_DRIVER_FLAGS_OFFCHANNEL_TX;
drv->test_use_roc_tx = 1;
}
}
-static void * nl80211_global_init(void)
+static void * nl80211_global_init(void *ctx)
{
struct nl80211_global *global;
struct netlink_config *cfg;
global = os_zalloc(sizeof(*global));
if (global == NULL)
return NULL;
+ global->ctx = ctx;
global->ioctl_sock = -1;
dl_list_init(&global->interfaces);
global->if_add_ifindex = -1;
os_memcpy(nulldata.hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
if (wpa_driver_nl80211_send_mlme(bss, (u8 *) &nulldata, size, 0, 0, 0,
- 0, 0) < 0)
+ 0, 0, NULL, 0) < 0)
wpa_printf(MSG_DEBUG, "nl80211_send_null_frame: Failed to "
"send poll frame");
}
struct wpa_driver_scan_params *params)
{
struct i802_bss *bss = priv;
+#ifdef CONFIG_DRIVER_NL80211_QCA
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+
+ /*
+ * Do a vendor specific scan if possible. If only_new_results is
+ * set, do a normal scan since a kernel (cfg80211) BSS cache flush
+ * cannot be achieved through a vendor scan. The below condition may
+ * need to be modified if new scan flags are added in the future whose
+ * functionality can only be achieved through a normal scan.
+ */
+ if (drv->scan_vendor_cmd_avail && !params->only_new_results)
+ return wpa_driver_nl80211_vendor_scan(bss, params);
+#endif /* CONFIG_DRIVER_NL80211_QCA */
return wpa_driver_nl80211_scan(bss, params);
}
static int driver_nl80211_send_mlme(void *priv, const u8 *data,
size_t data_len, int noack,
- unsigned int freq)
+ unsigned int freq,
+ const u16 *csa_offs, size_t csa_offs_len)
{
struct i802_bss *bss = priv;
return wpa_driver_nl80211_send_mlme(bss, data, data_len, noack,
- freq, 0, 0, 0);
+ freq, 0, 0, 0, csa_offs,
+ csa_offs_len);
}
}
-const u8 * wpa_driver_nl80211_get_macaddr(void *priv)
+static const u8 * wpa_driver_nl80211_get_macaddr(void *priv)
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
"capa.mac_addr_rand_scan_supported=%d\n"
"capa.conc_capab=%u\n"
"capa.max_conc_chan_2_4=%u\n"
- "capa.max_conc_chan_5_0=%u\n",
+ "capa.max_conc_chan_5_0=%u\n"
+ "capa.max_sched_scan_plans=%u\n"
+ "capa.max_sched_scan_plan_interval=%u\n"
+ "capa.max_sched_scan_plan_iterations=%u\n",
drv->capa.key_mgmt,
drv->capa.enc,
drv->capa.auth,
drv->capa.mac_addr_rand_scan_supported,
drv->capa.conc_capab,
drv->capa.max_conc_chan_2_4,
- drv->capa.max_conc_chan_5_0);
+ drv->capa.max_conc_chan_5_0,
+ drv->capa.max_sched_scan_plans,
+ drv->capa.max_sched_scan_plan_interval,
+ drv->capa.max_sched_scan_plan_iterations);
if (os_snprintf_error(end - pos, res))
return pos - buf;
pos += res;
struct wpa_driver_nl80211_data *drv = bss->drv;
struct nlattr *beacon_csa;
int ret = -ENOBUFS;
+ int csa_off_len = 0;
+ int i;
wpa_printf(MSG_DEBUG, "nl80211: Channel switch request (cs_count=%u block_tx=%u freq=%d width=%d cf1=%d cf2=%d)",
settings->cs_count, settings->block_tx,
(drv->nlmode != NL80211_IFTYPE_P2P_GO))
return -EOPNOTSUPP;
- /* check settings validity */
- if (!settings->beacon_csa.tail ||
- ((settings->beacon_csa.tail_len <=
- settings->counter_offset_beacon) ||
- (settings->beacon_csa.tail[settings->counter_offset_beacon] !=
- settings->cs_count)))
+ /*
+ * Remove empty counters, assuming Probe Response and Beacon frame
+ * counters match. This implementation assumes that there are only two
+ * counters.
+ */
+ if (settings->counter_offset_beacon[0] &&
+ !settings->counter_offset_beacon[1]) {
+ csa_off_len = 1;
+ } else if (settings->counter_offset_beacon[1] &&
+ !settings->counter_offset_beacon[0]) {
+ csa_off_len = 1;
+ settings->counter_offset_beacon[0] =
+ settings->counter_offset_beacon[1];
+ settings->counter_offset_presp[0] =
+ settings->counter_offset_presp[1];
+ } else if (settings->counter_offset_beacon[1] &&
+ settings->counter_offset_beacon[0]) {
+ csa_off_len = 2;
+ } else {
+ wpa_printf(MSG_ERROR, "nl80211: No CSA counters provided");
+ return -EINVAL;
+ }
+
+ /* Check CSA counters validity */
+ if (drv->capa.max_csa_counters &&
+ csa_off_len > drv->capa.max_csa_counters) {
+ wpa_printf(MSG_ERROR,
+ "nl80211: Too many CSA counters provided");
return -EINVAL;
+ }
- if (settings->beacon_csa.probe_resp &&
- ((settings->beacon_csa.probe_resp_len <=
- settings->counter_offset_presp) ||
- (settings->beacon_csa.probe_resp[settings->counter_offset_presp] !=
- settings->cs_count)))
+ if (!settings->beacon_csa.tail)
return -EINVAL;
+ for (i = 0; i < csa_off_len; i++) {
+ u16 csa_c_off_bcn = settings->counter_offset_beacon[i];
+ u16 csa_c_off_presp = settings->counter_offset_presp[i];
+
+ if ((settings->beacon_csa.tail_len <= csa_c_off_bcn) ||
+ (settings->beacon_csa.tail[csa_c_off_bcn] !=
+ settings->cs_count))
+ return -EINVAL;
+
+ if (settings->beacon_csa.probe_resp &&
+ ((settings->beacon_csa.probe_resp_len <=
+ csa_c_off_presp) ||
+ (settings->beacon_csa.probe_resp[csa_c_off_presp] !=
+ settings->cs_count)))
+ return -EINVAL;
+ }
+
if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_CHANNEL_SWITCH)) ||
nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT,
settings->cs_count) ||
if (ret)
goto error;
- if (nla_put_u16(msg, NL80211_ATTR_CSA_C_OFF_BEACON,
- settings->counter_offset_beacon) ||
+ if (nla_put(msg, NL80211_ATTR_CSA_C_OFF_BEACON,
+ csa_off_len * sizeof(u16),
+ settings->counter_offset_beacon) ||
(settings->beacon_csa.probe_resp &&
- nla_put_u16(msg, NL80211_ATTR_CSA_C_OFF_PRESP,
- settings->counter_offset_presp)))
+ nla_put(msg, NL80211_ATTR_CSA_C_OFF_PRESP,
+ csa_off_len * sizeof(u16),
+ settings->counter_offset_presp)))
goto fail;
nla_nest_end(msg, beacon_csa);
}
+#ifdef CONFIG_DRIVER_NL80211_QCA
static int nl80211_roaming(void *priv, int allowed, const u8 *bssid)
{
struct i802_bss *bss = priv;
return send_and_recv_msgs(drv, msg, NULL, NULL);
}
+#endif /* CONFIG_DRIVER_NL80211_QCA */
static int nl80211_set_mac_addr(void *priv, const u8 *addr)
struct wpa_driver_nl80211_data *drv = bss->drv;
int new_addr = addr != NULL;
+ if (TEST_FAIL())
+ return -1;
+
if (!addr)
addr = drv->perm_addr;
}
+static int nl80211_put_mesh_config(struct nl_msg *msg,
+ struct wpa_driver_mesh_bss_params *params)
+{
+ struct nlattr *container;
+
+ container = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG);
+ if (!container)
+ return -1;
+
+ if (((params->flags & WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS) &&
+ nla_put_u32(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS,
+ params->auto_plinks)) ||
+ ((params->flags & WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS) &&
+ nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
+ params->max_peer_links)))
+ return -1;
+
+ /*
+ * Set NL80211_MESHCONF_PLINK_TIMEOUT even if user mpm is used because
+ * the timer could disconnect stations even in that case.
+ */
+ if ((params->flags & WPA_DRIVER_MESH_CONF_FLAG_PEER_LINK_TIMEOUT) &&
+ nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT,
+ params->peer_link_timeout)) {
+ wpa_printf(MSG_ERROR, "nl80211: Failed to set PLINK_TIMEOUT");
+ return -1;
+ }
+
+ if ((params->flags & WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE) &&
+ nla_put_u16(msg, NL80211_MESHCONF_HT_OPMODE, params->ht_opmode)) {
+ wpa_printf(MSG_ERROR, "nl80211: Failed to set HT_OP_MODE");
+ return -1;
+ }
+
+ nla_nest_end(msg, container);
+
+ return 0;
+}
+
+
static int nl80211_join_mesh(struct i802_bss *bss,
struct wpa_driver_mesh_join_params *params)
{
nl80211_put_freq_params(msg, ¶ms->freq) ||
nl80211_put_basic_rates(msg, params->basic_rates) ||
nl80211_put_mesh_id(msg, params->meshid, params->meshid_len) ||
- nl80211_put_beacon_int(msg, params->beacon_int))
+ nl80211_put_beacon_int(msg, params->beacon_int) ||
+ nl80211_put_dtim_period(msg, params->dtim_period))
goto fail;
wpa_printf(MSG_DEBUG, " * flags=%08X", params->flags);
goto fail;
nla_nest_end(msg, container);
- container = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG);
- if (!container)
+ params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS;
+ params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_PEER_LINK_TIMEOUT;
+ params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS;
+ if (nl80211_put_mesh_config(msg, ¶ms->conf) < 0)
goto fail;
- if (!(params->conf.flags & WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS) &&
- nla_put_u32(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS, 0))
- goto fail;
- if ((params->conf.flags & WPA_DRIVER_MESH_FLAG_DRIVER_MPM) &&
- nla_put_u16(msg, NL80211_MESHCONF_MAX_PEER_LINKS,
- params->max_peer_links))
- goto fail;
-
- /*
- * Set NL80211_MESHCONF_PLINK_TIMEOUT even if user mpm is used because
- * the timer could disconnect stations even in that case.
- */
- if (nla_put_u32(msg, NL80211_MESHCONF_PLINK_TIMEOUT,
- params->conf.peer_link_timeout)) {
- wpa_printf(MSG_ERROR, "nl80211: Failed to set PLINK_TIMEOUT");
- goto fail;
- }
-
- nla_nest_end(msg, container);
-
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
msg = NULL;
if (ret) {
goto fail;
}
ret = 0;
- bss->freq = params->freq.freq;
+ drv->assoc_freq = bss->freq = params->freq.freq;
wpa_printf(MSG_DEBUG, "nl80211: mesh join request send successfully");
fail:
}
+#ifdef CONFIG_DRIVER_NL80211_QCA
+
static int hw_mode_to_qca_acs(enum hostapd_hw_mode hw_mode)
{
switch (hw_mode) {
}
+static int nl80211_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)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ struct nlattr *container;
+ int ret;
+
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Start P2P Listen offload: freq=%u, period=%u, interval=%u, count=%u",
+ freq, period, interval, count);
+
+ if (!(drv->capa.flags & WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD))
+ return -1;
+
+ if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
+ QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START))
+ goto fail;
+
+ container = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
+ if (!container)
+ goto fail;
+
+ if (nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL,
+ freq) ||
+ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD,
+ period) ||
+ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL,
+ interval) ||
+ nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT,
+ count) ||
+ nla_put(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES,
+ dev_types_len, device_types) ||
+ nla_put(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE,
+ ies_len, ies))
+ goto fail;
+
+ nla_nest_end(msg, container);
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ msg = NULL;
+ if (ret) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Failed to send P2P Listen offload vendor command");
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ nlmsg_free(msg);
+ return -1;
+}
+
+
+static int nl80211_p2p_lo_stop(void *priv)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Stop P2P Listen offload");
+
+ if (!(drv->capa.flags & WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD))
+ return -1;
+
+ if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
+ QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP)) {
+ nlmsg_free(msg);
+ return -1;
+ }
+
+ return send_and_recv_msgs(drv, msg, NULL, NULL);
+}
+
+#endif /* CONFIG_DRIVER_NL80211_QCA */
+
+
+static int nl80211_write_to_file(const char *name, unsigned int val)
+{
+ int fd, len;
+ char tmp[128];
+
+ fd = open(name, O_RDWR);
+ if (fd < 0) {
+ wpa_printf(MSG_ERROR, "nl80211: Failed to open %s: %s",
+ name, strerror(errno));
+ return fd;
+ }
+
+ len = os_snprintf(tmp, sizeof(tmp), "%u\n", val);
+ len = write(fd, tmp, len);
+ if (len < 0)
+ wpa_printf(MSG_ERROR, "nl80211: Failed to write to %s: %s",
+ name, strerror(errno));
+ close(fd);
+
+ return 0;
+}
+
+
+static int nl80211_configure_data_frame_filters(void *priv, u32 filter_flags)
+{
+ struct i802_bss *bss = priv;
+ char path[128];
+ int ret;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Data frame filter flags=0x%x",
+ filter_flags);
+
+ /* Configure filtering of unicast frame encrypted using GTK */
+ ret = os_snprintf(path, sizeof(path),
+ "/proc/sys/net/ipv4/conf/%s/drop_unicast_in_l2_multicast",
+ bss->ifname);
+ if (os_snprintf_error(sizeof(path), ret))
+ return -1;
+
+ ret = nl80211_write_to_file(path,
+ !!(filter_flags &
+ WPA_DATA_FRAME_FILTER_FLAG_GTK));
+ if (ret) {
+ wpa_printf(MSG_ERROR,
+ "nl80211: Failed to set IPv4 unicast in multicast filter");
+ return ret;
+ }
+
+ os_snprintf(path, sizeof(path),
+ "/proc/sys/net/ipv6/conf/%s/drop_unicast_in_l2_multicast",
+ bss->ifname);
+ ret = nl80211_write_to_file(path,
+ !!(filter_flags &
+ WPA_DATA_FRAME_FILTER_FLAG_GTK));
+
+ if (ret) {
+ wpa_printf(MSG_ERROR,
+ "nl80211: Failed to set IPv6 unicast in multicast filter");
+ return ret;
+ }
+
+ /* Configure filtering of unicast frame encrypted using GTK */
+ os_snprintf(path, sizeof(path),
+ "/proc/sys/net/ipv4/conf/%s/drop_gratuitous_arp",
+ bss->ifname);
+ ret = nl80211_write_to_file(path,
+ !!(filter_flags &
+ WPA_DATA_FRAME_FILTER_FLAG_ARP));
+ if (ret) {
+ wpa_printf(MSG_ERROR,
+ "nl80211: Failed set gratuitous ARP filter");
+ return ret;
+ }
+
+ /* Configure filtering of IPv6 NA frames */
+ os_snprintf(path, sizeof(path),
+ "/proc/sys/net/ipv6/conf/%s/drop_unsolicited_na",
+ bss->ifname);
+ ret = nl80211_write_to_file(path,
+ !!(filter_flags &
+ WPA_DATA_FRAME_FILTER_FLAG_NA));
+ if (ret) {
+ wpa_printf(MSG_ERROR,
+ "nl80211: Failed to set unsolicited NA filter");
+ return ret;
+ }
+
+ return 0;
+}
+
+
+static int nl80211_get_ext_capab(void *priv, enum wpa_driver_if_type type,
+ const u8 **ext_capa, const u8 **ext_capa_mask,
+ unsigned int *ext_capa_len)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ enum nl80211_iftype nlmode;
+ unsigned int i;
+
+ if (!ext_capa || !ext_capa_mask || !ext_capa_len)
+ return -1;
+
+ nlmode = wpa_driver_nl80211_if_type(type);
+
+ /* By default, use the per-radio values */
+ *ext_capa = drv->extended_capa;
+ *ext_capa_mask = drv->extended_capa_mask;
+ *ext_capa_len = drv->extended_capa_len;
+
+ /* Replace the default value if a per-interface type value exists */
+ for (i = 0; i < drv->num_iface_ext_capa; i++) {
+ if (nlmode == drv->iface_ext_capa[i].iftype) {
+ *ext_capa = drv->iface_ext_capa[i].ext_capa;
+ *ext_capa_mask = drv->iface_ext_capa[i].ext_capa_mask;
+ *ext_capa_len = drv->iface_ext_capa[i].ext_capa_len;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.name = "nl80211",
.desc = "Linux nl80211/cfg80211",
.sched_scan = wpa_driver_nl80211_sched_scan,
.stop_sched_scan = wpa_driver_nl80211_stop_sched_scan,
.get_scan_results2 = wpa_driver_nl80211_get_scan_results,
+ .abort_scan = wpa_driver_nl80211_abort_scan,
.deauthenticate = driver_nl80211_deauthenticate,
.authenticate = driver_nl80211_authenticate,
.associate = wpa_driver_nl80211_associate,
.vendor_cmd = nl80211_vendor_cmd,
.set_qos_map = nl80211_set_qos_map,
.set_wowlan = nl80211_set_wowlan,
- .roaming = nl80211_roaming,
.set_mac_addr = nl80211_set_mac_addr,
#ifdef CONFIG_MESH
.init_mesh = wpa_driver_nl80211_init_mesh,
.br_set_net_param = wpa_driver_br_set_net_param,
.add_tx_ts = nl80211_add_ts,
.del_tx_ts = nl80211_del_ts,
+ .get_ifindex = nl80211_get_ifindex,
+#ifdef CONFIG_DRIVER_NL80211_QCA
+ .roaming = nl80211_roaming,
.do_acs = wpa_driver_do_acs,
.set_band = nl80211_set_band,
.get_pref_freq_list = nl80211_get_pref_freq_list,
.set_prob_oper_freq = nl80211_set_prob_oper_freq,
+ .p2p_lo_start = nl80211_p2p_lo_start,
+ .p2p_lo_stop = nl80211_p2p_lo_stop,
+ .set_default_scan_ies = nl80211_set_default_scan_ies,
+#endif /* CONFIG_DRIVER_NL80211_QCA */
+ .configure_data_frame_filters = nl80211_configure_data_frame_filters,
+ .get_ext_capab = nl80211_get_ext_capab,
};
#endif /* CONFIG_LIBNL20 */
struct nl80211_global {
+ void *ctx;
struct dl_list interfaces;
int if_add_ifindex;
u64 if_add_wdevid;
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;
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;
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;
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 */
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;
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,
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 */
unsigned int device_ap_sme:1;
unsigned int poll_command_supported:1;
unsigned int data_tx_status:1;
- unsigned int monitor_supported:1;
unsigned int auth_supported:1;
unsigned int connect_supported:1;
unsigned int p2p_go_supported:1;
case NL80211_IFTYPE_P2P_CLIENT:
info->p2p_client_supported = 1;
break;
- case NL80211_IFTYPE_MONITOR:
- info->monitor_supported = 1;
- break;
}
}
}
struct nlattr *tb)
{
struct wpa_driver_capa *capa = info->capa;
+ u8 *ext_features;
+ int len;
if (tb == NULL)
return;
- if (ext_feature_isset(nla_data(tb), nla_len(tb),
- NL80211_EXT_FEATURE_VHT_IBSS))
+ ext_features = nla_data(tb);
+ len = nla_len(tb);
+
+ if (ext_feature_isset(ext_features, len, NL80211_EXT_FEATURE_VHT_IBSS))
capa->flags |= WPA_DRIVER_FLAGS_VHT_IBSS;
+
+ if (ext_feature_isset(ext_features, len, NL80211_EXT_FEATURE_RRM))
+ capa->rrm_flags |= WPA_DRIVER_FLAGS_SUPPORT_RRM;
}
if (flags & NL80211_FEATURE_HT_IBSS)
capa->flags |= WPA_DRIVER_FLAGS_HT_IBSS;
+
+ if (flags & NL80211_FEATURE_FULL_AP_CLIENT_STATE)
+ capa->flags |= WPA_DRIVER_FLAGS_FULL_AP_CLIENT_STATE;
}
}
+static void wiphy_info_extended_capab(struct wpa_driver_nl80211_data *drv,
+ struct nlattr *tb)
+{
+ int rem = 0, i;
+ struct nlattr *tb1[NL80211_ATTR_MAX + 1], *attr;
+
+ if (!tb || drv->num_iface_ext_capa == NL80211_IFTYPE_MAX)
+ return;
+
+ nla_for_each_nested(attr, tb, rem) {
+ unsigned int len;
+ struct drv_nl80211_ext_capa *capa;
+
+ nla_parse(tb1, NL80211_ATTR_MAX, nla_data(attr),
+ nla_len(attr), NULL);
+
+ if (!tb1[NL80211_ATTR_IFTYPE] ||
+ !tb1[NL80211_ATTR_EXT_CAPA] ||
+ !tb1[NL80211_ATTR_EXT_CAPA_MASK])
+ continue;
+
+ capa = &drv->iface_ext_capa[drv->num_iface_ext_capa];
+ capa->iftype = nla_get_u32(tb1[NL80211_ATTR_IFTYPE]);
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Driver-advertised extended capabilities for interface type %s",
+ nl80211_iftype_str(capa->iftype));
+
+ len = nla_len(tb1[NL80211_ATTR_EXT_CAPA]);
+ capa->ext_capa = os_malloc(len);
+ if (!capa->ext_capa)
+ goto err;
+
+ os_memcpy(capa->ext_capa, nla_data(tb1[NL80211_ATTR_EXT_CAPA]),
+ len);
+ capa->ext_capa_len = len;
+ wpa_hexdump(MSG_DEBUG, "nl80211: Extended capabilities",
+ capa->ext_capa, capa->ext_capa_len);
+
+ len = nla_len(tb1[NL80211_ATTR_EXT_CAPA_MASK]);
+ capa->ext_capa_mask = os_malloc(len);
+ if (!capa->ext_capa_mask)
+ goto err;
+
+ os_memcpy(capa->ext_capa_mask,
+ nla_data(tb1[NL80211_ATTR_EXT_CAPA_MASK]), len);
+ wpa_hexdump(MSG_DEBUG, "nl80211: Extended capabilities mask",
+ capa->ext_capa_mask, capa->ext_capa_len);
+
+ drv->num_iface_ext_capa++;
+ if (drv->num_iface_ext_capa == NL80211_IFTYPE_MAX)
+ break;
+ }
+
+ return;
+
+err:
+ /* Cleanup allocated memory on error */
+ for (i = 0; i < NL80211_IFTYPE_MAX; i++) {
+ os_free(drv->iface_ext_capa[i].ext_capa);
+ drv->iface_ext_capa[i].ext_capa = NULL;
+ os_free(drv->iface_ext_capa[i].ext_capa_mask);
+ drv->iface_ext_capa[i].ext_capa_mask = NULL;
+ drv->iface_ext_capa[i].ext_capa_len = 0;
+ }
+ drv->num_iface_ext_capa = 0;
+}
+
+
static int wiphy_info_handler(struct nl_msg *msg, void *arg)
{
struct nlattr *tb[NL80211_ATTR_MAX + 1];
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
genlmsg_attrlen(gnlh, 0), NULL);
+ if (tb[NL80211_ATTR_WIPHY])
+ drv->wiphy_idx = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
+
if (tb[NL80211_ATTR_WIPHY_NAME])
os_strlcpy(drv->phyname,
nla_get_string(tb[NL80211_ATTR_WIPHY_NAME]),
capa->max_sched_scan_ssids =
nla_get_u8(tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS]);
+ if (tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS] &&
+ tb[NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL] &&
+ tb[NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS]) {
+ capa->max_sched_scan_plans =
+ nla_get_u32(tb[NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS]);
+
+ capa->max_sched_scan_plan_interval =
+ nla_get_u32(tb[NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL]);
+
+ capa->max_sched_scan_plan_iterations =
+ nla_get_u32(tb[NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS]);
+ }
+
if (tb[NL80211_ATTR_MAX_MATCH_SETS])
capa->max_match_sets =
nla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]);
nla_len(tb[NL80211_ATTR_EXT_CAPA]));
drv->extended_capa_len =
nla_len(tb[NL80211_ATTR_EXT_CAPA]);
+ wpa_hexdump(MSG_DEBUG,
+ "nl80211: Driver-advertised extended capabilities (default)",
+ drv->extended_capa, drv->extended_capa_len);
}
drv->extended_capa_mask =
os_malloc(nla_len(tb[NL80211_ATTR_EXT_CAPA_MASK]));
os_memcpy(drv->extended_capa_mask,
nla_data(tb[NL80211_ATTR_EXT_CAPA_MASK]),
nla_len(tb[NL80211_ATTR_EXT_CAPA_MASK]));
+ wpa_hexdump(MSG_DEBUG,
+ "nl80211: Driver-advertised extended capabilities mask (default)",
+ drv->extended_capa_mask,
+ drv->extended_capa_len);
} else {
os_free(drv->extended_capa);
drv->extended_capa = NULL;
}
}
+ wiphy_info_extended_capab(drv, tb[NL80211_ATTR_IFTYPE_EXT_CAPA]);
+
if (tb[NL80211_ATTR_VENDOR_DATA]) {
struct nlattr *nl;
int rem;
case QCA_NL80211_VENDOR_SUBCMD_TEST:
drv->vendor_cmd_test_avail = 1;
break;
+#ifdef CONFIG_DRIVER_NL80211_QCA
case QCA_NL80211_VENDOR_SUBCMD_ROAMING:
drv->roaming_vendor_cmd_avail = 1;
break;
case QCA_NL80211_VENDOR_SUBCMD_SETBAND:
drv->setband_vendor_cmd_avail = 1;
break;
+ case QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN:
+ drv->scan_vendor_cmd_avail = 1;
+ break;
+ case QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION:
+ drv->set_wifi_conf_vendor_cmd_avail = 1;
+ break;
+#endif /* CONFIG_DRIVER_NL80211_QCA */
}
}
capa->max_stations =
nla_get_u32(tb[NL80211_ATTR_MAX_AP_ASSOC_STA]);
+ if (tb[NL80211_ATTR_MAX_CSA_COUNTERS])
+ capa->max_csa_counters =
+ nla_get_u8(tb[NL80211_ATTR_MAX_CSA_COUNTERS]);
+
return NL_SKIP;
}
if (!drv->capa.max_remain_on_chan)
drv->capa.max_remain_on_chan = 5000;
- if (info->channel_switch_supported)
- drv->capa.flags |= WPA_DRIVER_FLAGS_AP_CSA;
drv->capa.wmm_ac_supported = info->wmm_ac_supported;
drv->capa.mac_addr_rand_sched_scan_supported =
drv->capa.mac_addr_rand_scan_supported =
info->mac_addr_rand_scan_supported;
+ if (info->channel_switch_supported) {
+ drv->capa.flags |= WPA_DRIVER_FLAGS_AP_CSA;
+ if (!drv->capa.max_csa_counters)
+ drv->capa.max_csa_counters = 1;
+ }
+
+ if (!drv->capa.max_sched_scan_plans) {
+ drv->capa.max_sched_scan_plans = 1;
+ drv->capa.max_sched_scan_plan_interval = UINT32_MAX;
+ drv->capa.max_sched_scan_plan_iterations = 0;
+ }
+
return 0;
}
+#ifdef CONFIG_DRIVER_NL80211_QCA
+
static int dfs_info_handler(struct nl_msg *msg, void *arg)
{
struct nlattr *tb[NL80211_ATTR_MAX + 1];
attr = tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS];
if (attr) {
- info->flags = nla_data(attr);
- info->flags_len = nla_len(attr);
+ int len = nla_len(attr);
+ info->flags = os_malloc(len);
+ if (info->flags != NULL) {
+ os_memcpy(info->flags, nla_data(attr), len);
+ info->flags_len = len;
+ }
}
attr = tb_vendor[QCA_WLAN_VENDOR_ATTR_CONCURRENCY_CAPA];
if (attr)
if (check_feature(QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY, &info))
drv->capa.flags |= WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY;
+
+ if (check_feature(QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS,
+ &info))
+ drv->capa.flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS;
+ if (check_feature(QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD, &info))
+ drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD;
+ os_free(info.flags);
}
+#endif /* CONFIG_DRIVER_NL80211_QCA */
+
int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
{
* If poll command and tx status are supported, mac80211 is new enough
* to have everything we need to not need monitor interfaces.
*/
- drv->use_monitor = !info.poll_command_supported || !info.data_tx_status;
-
- if (drv->device_ap_sme && drv->use_monitor) {
- /*
- * Non-mac80211 drivers may not support monitor interface.
- * Make sure we do not get stuck with incorrect capability here
- * by explicitly testing this.
- */
- if (!info.monitor_supported) {
- wpa_printf(MSG_DEBUG, "nl80211: Disable use_monitor "
- "with device_ap_sme since no monitor mode "
- "support detected");
- drv->use_monitor = 0;
- }
- }
+ drv->use_monitor = !info.device_ap_sme &&
+ (!info.poll_command_supported || !info.data_tx_status);
/*
* If we aren't going to use monitor interfaces, but the
if (!drv->use_monitor && !info.data_tx_status)
drv->capa.flags &= ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
+#ifdef CONFIG_DRIVER_NL80211_QCA
qca_nl80211_check_dfs_capa(drv);
qca_nl80211_get_features(drv);
+ /*
+ * To enable offchannel simultaneous support in wpa_supplicant, the
+ * underlying driver needs to support the same along with offchannel TX.
+ * Offchannel TX support is needed since remain_on_channel and
+ * action_tx use some common data structures and hence cannot be
+ * scheduled simultaneously.
+ */
+ if (!(drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX))
+ drv->capa.flags &= ~WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS;
+#endif /* CONFIG_DRIVER_NL80211_QCA */
+
return 0;
}
u16 *num_modes;
struct hostapd_hw_modes *modes;
int last_mode, last_chan_idx;
+ int failed;
};
static void phy_info_ht_capa(struct hostapd_hw_modes *mode, struct nlattr *capa,
mode->num_channels + new_channels,
sizeof(struct hostapd_channel_data));
if (!channel)
- return NL_SKIP;
+ return NL_STOP;
mode->channels = channel;
mode->num_channels += new_channels;
mode->rates = os_calloc(mode->num_rates, sizeof(int));
if (!mode->rates)
- return NL_SKIP;
+ return NL_STOP;
idx = 0;
mode = os_realloc_array(phy_info->modes,
*phy_info->num_modes + 1,
sizeof(*mode));
- if (!mode)
- return NL_SKIP;
+ if (!mode) {
+ phy_info->failed = 1;
+ return NL_STOP;
+ }
phy_info->modes = mode;
mode = &phy_info->modes[*(phy_info->num_modes)];
phy_info_vht_capa(mode, tb_band[NL80211_BAND_ATTR_VHT_CAPA],
tb_band[NL80211_BAND_ATTR_VHT_MCS_SET]);
ret = phy_info_freqs(phy_info, mode, tb_band[NL80211_BAND_ATTR_FREQS]);
- if (ret != NL_OK)
- return ret;
- ret = phy_info_rates(mode, tb_band[NL80211_BAND_ATTR_RATES]);
- if (ret != NL_OK)
+ if (ret == NL_OK)
+ ret = phy_info_rates(mode, tb_band[NL80211_BAND_ATTR_RATES]);
+ if (ret != NL_OK) {
+ phy_info->failed = 1;
return ret;
+ }
return NL_OK;
}
static void nl80211_set_vht_mode(struct hostapd_hw_modes *mode, int start,
- int end)
+ int end, int max_bw)
{
int c;
if (chan->freq - 70 >= start && chan->freq + 10 <= end)
chan->flag |= HOSTAPD_CHAN_VHT_70_10;
+
+ if (max_bw >= 160) {
+ if (chan->freq - 10 >= start && chan->freq + 150 <= end)
+ chan->flag |= HOSTAPD_CHAN_VHT_10_150;
+
+ if (chan->freq - 30 >= start && chan->freq + 130 <= end)
+ chan->flag |= HOSTAPD_CHAN_VHT_30_130;
+
+ if (chan->freq - 50 >= start && chan->freq + 110 <= end)
+ chan->flag |= HOSTAPD_CHAN_VHT_50_110;
+
+ if (chan->freq - 70 >= start && chan->freq + 90 <= end)
+ chan->flag |= HOSTAPD_CHAN_VHT_70_90;
+
+ if (chan->freq - 90 >= start && chan->freq + 70 <= end)
+ chan->flag |= HOSTAPD_CHAN_VHT_90_70;
+
+ if (chan->freq - 110 >= start && chan->freq + 50 <= end)
+ chan->flag |= HOSTAPD_CHAN_VHT_110_50;
+
+ if (chan->freq - 130 >= start && chan->freq + 30 <= end)
+ chan->flag |= HOSTAPD_CHAN_VHT_130_30;
+
+ if (chan->freq - 150 >= start && chan->freq + 10 <= end)
+ chan->flag |= HOSTAPD_CHAN_VHT_150_10;
+ }
}
}
if (!results->modes[m].vht_capab)
continue;
- nl80211_set_vht_mode(&results->modes[m], start, end);
+ nl80211_set_vht_mode(&results->modes[m], start, end, max_bw);
}
}
.num_modes = num_modes,
.modes = NULL,
.last_mode = -1,
+ .failed = 0,
};
*num_modes = 0;
if (send_and_recv_msgs(drv, msg, phy_info_handler, &result) == 0) {
nl80211_set_regulatory_flags(drv, &result);
+ if (result.failed) {
+ int i;
+
+ for (i = 0; result.modes && i < *num_modes; i++) {
+ os_free(result.modes[i].channels);
+ os_free(result.modes[i].rates);
+ }
+ os_free(result.modes);
+ return NULL;
+ }
return wpa_driver_nl80211_postprocess_modes(result.modes,
num_modes);
}
enum nl80211_commands cmd, struct nlattr *status,
struct nlattr *addr, struct nlattr *req_ie,
struct nlattr *resp_ie,
+ struct nlattr *timed_out,
struct nlattr *authorized,
struct nlattr *key_replay_ctr,
struct nlattr *ptk_kck,
- struct nlattr *ptk_kek)
+ struct nlattr *ptk_kek,
+ struct nlattr *subnet_status)
{
union wpa_event_data event;
const u8 *ssid;
return;
}
+ drv->connect_reassoc = 0;
+
status_code = status ? nla_get_u16(status) : WLAN_STATUS_SUCCESS;
if (cmd == NL80211_CMD_CONNECT) {
event.assoc_reject.resp_ies_len = nla_len(resp_ie);
}
event.assoc_reject.status_code = status_code;
+ event.assoc_reject.timed_out = timed_out != NULL;
wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);
return;
}
event.assoc_info.req_ies_len = nla_len(req_ie);
if (cmd == NL80211_CMD_ROAM) {
- ssid = nl80211_get_ie(event.assoc_info.req_ies,
- event.assoc_info.req_ies_len,
- WLAN_EID_SSID);
+ ssid = get_ie(event.assoc_info.req_ies,
+ event.assoc_info.req_ies_len,
+ WLAN_EID_SSID);
if (ssid && ssid[1] > 0 && ssid[1] <= 32) {
drv->ssid_len = ssid[1];
os_memcpy(drv->ssid, ssid + 2, ssid[1]);
event.assoc_info.ptk_kek_len = nla_len(ptk_kek);
}
+ if (subnet_status) {
+ /*
+ * At least for now, this is only available from
+ * QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS and that
+ * attribute has the same values 0, 1, 2 as are used in the
+ * variable here, so no mapping between different values are
+ * needed.
+ */
+ event.assoc_info.subnet_status = nla_get_u8(subnet_status);
+ }
+
wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
}
rx_freq = drv->last_mgmt_freq = event.rx_mgmt.freq;
}
wpa_printf(MSG_DEBUG,
- "nl80211: RX frame sa=" MACSTR
+ "nl80211: RX frame da=" MACSTR " sa=" MACSTR " bssid=" MACSTR
" freq=%d ssi_signal=%d fc=0x%x seq_ctrl=0x%x stype=%u (%s) len=%u",
- MAC2STR(mgmt->sa), rx_freq, ssi_signal, fc,
+ MAC2STR(mgmt->da), MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid),
+ rx_freq, ssi_signal, fc,
le_to_host16(mgmt->seq_ctrl), stype, fc2str(fc),
(unsigned int) len);
event.rx_mgmt.frame = frame;
* Avoid issues with some roaming cases where
* disconnection event for the old AP may show up after
* we have started connection with the new AP.
+ * In case of locally generated event clear
+ * ignore_next_local_deauth as well, to avoid next local
+ * deauth event be wrongly ignored.
*/
- wpa_printf(MSG_DEBUG, "nl80211: Ignore deauth/disassoc event from old AP " MACSTR " when already authenticating with " MACSTR,
- MAC2STR(bssid),
- MAC2STR(drv->auth_attempt_bssid));
+ if (!os_memcmp(mgmt->sa, drv->first_bss->addr,
+ ETH_ALEN)) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Received a locally generated deauth event. Clear ignore_next_local_deauth flag");
+ drv->ignore_next_local_deauth = 0;
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Ignore deauth/disassoc event from old AP " MACSTR " when already authenticating with " MACSTR,
+ MAC2STR(bssid),
+ MAC2STR(drv->auth_attempt_bssid));
+ }
+ return;
+ }
+
+ if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME) &&
+ drv->connect_reassoc && drv->associated &&
+ os_memcmp(bssid, drv->prev_bssid, ETH_ALEN) == 0 &&
+ os_memcmp(bssid, drv->auth_attempt_bssid, ETH_ALEN) != 0) {
+ /*
+ * Avoid issues with some roaming cases where
+ * disconnection event for the old AP may show up after
+ * we have started connection with the new AP.
+ */
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Ignore deauth/disassoc event from old AP "
+ MACSTR
+ " when already connecting with " MACSTR,
+ MAC2STR(bssid),
+ MAC2STR(drv->auth_attempt_bssid));
return;
}
mgmt->u.disassoc.variable;
}
} else {
+ event.deauth_info.locally_generated =
+ !os_memcmp(mgmt->sa, drv->first_bss->addr, ETH_ALEN);
if (drv->ignore_deauth_event) {
wpa_printf(MSG_DEBUG, "nl80211: Ignore deauth event due to previous forced deauth-during-auth");
drv->ignore_deauth_event = 0;
+ if (event.deauth_info.locally_generated)
+ drv->ignore_next_local_deauth = 0;
return;
}
- event.deauth_info.locally_generated =
- !os_memcmp(mgmt->sa, drv->first_bss->addr, ETH_ALEN);
if (drv->ignore_next_local_deauth) {
drv->ignore_next_local_deauth = 0;
if (event.deauth_info.locally_generated) {
struct nlattr *tb[])
{
unsigned int freq;
+ union wpa_event_data event;
if (tb[NL80211_ATTR_MAC] == NULL) {
wpa_printf(MSG_DEBUG, "nl80211: No address in IBSS joined "
drv->first_bss->freq = freq;
}
- wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
+ os_memset(&event, 0, sizeof(event));
+ event.assoc_info.freq = freq;
+
+ wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
}
static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
- struct nlattr *tb[])
+ struct nlattr *tb[], int external_scan)
{
union wpa_event_data event;
struct nlattr *nl;
int freqs[MAX_REPORT_FREQS];
int num_freqs = 0;
- if (drv->scan_for_auth) {
+ if (!external_scan && drv->scan_for_auth) {
drv->scan_for_auth = 0;
wpa_printf(MSG_DEBUG, "nl80211: Scan results for missing "
"cfg80211 BSS entry");
os_memset(&event, 0, sizeof(event));
info = &event.scan_info;
info->aborted = aborted;
+ info->external_scan = external_scan;
+ info->nl_scan_event = 1;
if (tb[NL80211_ATTR_SCAN_SSIDS]) {
nla_for_each_nested(nl, tb[NL80211_ATTR_SCAN_SSIDS], rem) {
}
}
if (tb[NL80211_ATTR_SCAN_FREQUENCIES]) {
- char msg[200], *pos, *end;
+ char msg[300], *pos, *end;
int res;
pos = msg;
return;
addr = nla_data(tb[NL80211_ATTR_MAC]);
- wpa_printf(MSG_DEBUG, "nl80211: New peer candidate" MACSTR,
+ wpa_printf(MSG_DEBUG, "nl80211: New peer candidate " MACSTR,
MAC2STR(addr));
os_memset(&data, 0, sizeof(data));
static void nl80211_del_station_event(struct wpa_driver_nl80211_data *drv,
+ struct i802_bss *bss,
struct nlattr **tb)
{
u8 *addr;
MAC2STR(addr));
if (is_ap_interface(drv->nlmode) && drv->device_ap_sme) {
- drv_event_disassoc(drv->ctx, addr);
+ drv_event_disassoc(bss->ctx, addr);
return;
}
os_memset(&data, 0, sizeof(data));
os_memcpy(data.ibss_peer_lost.peer, addr, ETH_ALEN);
- wpa_supplicant_event(drv->ctx, EVENT_IBSS_PEER_LOST, &data);
+ wpa_supplicant_event(bss->ctx, EVENT_IBSS_PEER_LOST, &data);
}
}
+#ifdef CONFIG_DRIVER_NL80211_QCA
+
static void qca_nl80211_avoid_freq(struct wpa_driver_nl80211_data *drv,
const u8 *data, size_t len)
{
tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID],
tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE],
tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE],
+ NULL,
tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED],
tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR],
tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK],
- tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK]);
+ tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK],
+ tb[QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS]);
}
}
+static void qca_nl80211_scan_trigger_event(struct wpa_driver_nl80211_data *drv,
+ u8 *data, size_t len)
+{
+ struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SCAN_MAX + 1];
+ u64 cookie = 0;
+ union wpa_event_data event;
+ struct scan_info *info;
+
+ if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SCAN_MAX,
+ (struct nlattr *) data, len, NULL) ||
+ !tb[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE])
+ return;
+
+ cookie = nla_get_u64(tb[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE]);
+ if (cookie != drv->vendor_scan_cookie) {
+ /* External scan trigger event, ignore */
+ return;
+ }
+
+ /* Cookie match, own scan */
+ os_memset(&event, 0, sizeof(event));
+ info = &event.scan_info;
+ info->external_scan = 0;
+ info->nl_scan_event = 0;
+
+ drv->scan_state = SCAN_STARTED;
+ wpa_supplicant_event(drv->ctx, EVENT_SCAN_STARTED, &event);
+}
+
+
+static void send_vendor_scan_event(struct wpa_driver_nl80211_data *drv,
+ int aborted, struct nlattr *tb[],
+ int external_scan)
+{
+ union wpa_event_data event;
+ struct nlattr *nl;
+ int rem;
+ struct scan_info *info;
+ int freqs[MAX_REPORT_FREQS];
+ int num_freqs = 0;
+
+ os_memset(&event, 0, sizeof(event));
+ info = &event.scan_info;
+ info->aborted = aborted;
+ info->external_scan = external_scan;
+
+ if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS]) {
+ nla_for_each_nested(nl,
+ tb[QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS], rem) {
+ struct wpa_driver_scan_ssid *s =
+ &info->ssids[info->num_ssids];
+ s->ssid = nla_data(nl);
+ s->ssid_len = nla_len(nl);
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Scan probed for SSID '%s'",
+ wpa_ssid_txt(s->ssid, s->ssid_len));
+ info->num_ssids++;
+ if (info->num_ssids == WPAS_MAX_SCAN_SSIDS)
+ break;
+ }
+ }
+
+ if (tb[QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES]) {
+ char msg[300], *pos, *end;
+ int res;
+
+ pos = msg;
+ end = pos + sizeof(msg);
+ *pos = '\0';
+
+ nla_for_each_nested(nl,
+ tb[QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES],
+ rem) {
+ freqs[num_freqs] = nla_get_u32(nl);
+ res = os_snprintf(pos, end - pos, " %d",
+ freqs[num_freqs]);
+ if (!os_snprintf_error(end - pos, res))
+ pos += res;
+ num_freqs++;
+ if (num_freqs == MAX_REPORT_FREQS - 1)
+ break;
+ }
+
+ info->freqs = freqs;
+ info->num_freqs = num_freqs;
+ wpa_printf(MSG_DEBUG, "nl80211: Scan included frequencies:%s",
+ msg);
+ }
+ wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, &event);
+}
+
+
+static void qca_nl80211_scan_done_event(struct wpa_driver_nl80211_data *drv,
+ u8 *data, size_t len)
+{
+ struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SCAN_MAX + 1];
+ u64 cookie = 0;
+ enum scan_status status;
+ int external_scan;
+
+ if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SCAN_MAX,
+ (struct nlattr *) data, len, NULL) ||
+ !tb[QCA_WLAN_VENDOR_ATTR_SCAN_STATUS] ||
+ !tb[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE])
+ return;
+
+ status = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SCAN_STATUS]);
+ if (status >= VENDOR_SCAN_STATUS_MAX)
+ return; /* invalid status */
+
+ cookie = nla_get_u64(tb[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE]);
+ if (cookie != drv->vendor_scan_cookie) {
+ /* Event from an external scan, get scan results */
+ external_scan = 1;
+ } else {
+ external_scan = 0;
+ if (status == VENDOR_SCAN_STATUS_NEW_RESULTS)
+ drv->scan_state = SCAN_COMPLETED;
+ else
+ drv->scan_state = SCAN_ABORTED;
+
+ eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
+ drv->ctx);
+ drv->vendor_scan_cookie = 0;
+ drv->last_scan_cmd = 0;
+ }
+
+ send_vendor_scan_event(drv, (status == VENDOR_SCAN_STATUS_ABORTED), tb,
+ external_scan);
+}
+
+
+static void qca_nl80211_p2p_lo_stop_event(struct wpa_driver_nl80211_data *drv,
+ u8 *data, size_t len)
+{
+ struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
+ union wpa_event_data event;
+
+ wpa_printf(MSG_DEBUG,
+ "nl80211: P2P listen offload stop vendor event received");
+
+ if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
+ (struct nlattr *) data, len, NULL) ||
+ !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON])
+ return;
+
+ os_memset(&event, 0, sizeof(event));
+ event.p2p_lo_stop.reason_code =
+ nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON]);
+
+ wpa_printf(MSG_DEBUG,
+ "nl80211: P2P Listen offload stop reason: %d",
+ event.p2p_lo_stop.reason_code);
+ wpa_supplicant_event(drv->ctx, EVENT_P2P_LO_STOP, &event);
+}
+
+#endif /* CONFIG_DRIVER_NL80211_QCA */
+
+
static void nl80211_vendor_event_qca(struct wpa_driver_nl80211_data *drv,
u32 subcmd, u8 *data, size_t len)
{
case QCA_NL80211_VENDOR_SUBCMD_TEST:
wpa_hexdump(MSG_DEBUG, "nl80211: QCA test event", data, len);
break;
+#ifdef CONFIG_DRIVER_NL80211_QCA
case QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY:
qca_nl80211_avoid_freq(drv, data, len);
break;
case QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED:
qca_nl80211_dfs_offload_radar_event(drv, subcmd, data, len);
break;
+ case QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN:
+ qca_nl80211_scan_trigger_event(drv, data, len);
+ break;
+ case QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE:
+ qca_nl80211_scan_done_event(drv, data, len);
+ break;
+ case QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP:
+ qca_nl80211_p2p_lo_stop_event(drv, data, len);
+ break;
+#endif /* CONFIG_DRIVER_NL80211_QCA */
default:
wpa_printf(MSG_DEBUG,
"nl80211: Ignore unsupported QCA vendor event %u",
{
struct wpa_driver_nl80211_data *drv = bss->drv;
union wpa_event_data data;
+ int external_scan_event = 0;
wpa_printf(MSG_DEBUG, "nl80211: Drv Event %d (%s) received for %s",
cmd, nl80211_command_to_string(cmd), bss->ifname);
case NL80211_CMD_NEW_SCAN_RESULTS:
wpa_dbg(drv->ctx, MSG_DEBUG,
"nl80211: New scan results available");
- drv->scan_state = SCAN_COMPLETED;
drv->scan_complete_events = 1;
- eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
- drv->ctx);
- send_scan_event(drv, 0, tb);
+ if (drv->last_scan_cmd == NL80211_CMD_TRIGGER_SCAN) {
+ drv->scan_state = SCAN_COMPLETED;
+ eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout,
+ drv, drv->ctx);
+ drv->last_scan_cmd = 0;
+ } else {
+ external_scan_event = 1;
+ }
+ send_scan_event(drv, 0, tb, external_scan_event);
break;
case NL80211_CMD_SCHED_SCAN_RESULTS:
wpa_dbg(drv->ctx, MSG_DEBUG,
"nl80211: New sched scan results available");
drv->scan_state = SCHED_SCAN_RESULTS;
- send_scan_event(drv, 0, tb);
+ send_scan_event(drv, 0, tb, 0);
break;
case NL80211_CMD_SCAN_ABORTED:
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan aborted");
- drv->scan_state = SCAN_ABORTED;
- /*
- * Need to indicate that scan results are available in order
- * not to make wpa_supplicant stop its scanning.
- */
- eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
- drv->ctx);
- send_scan_event(drv, 1, tb);
+ if (drv->last_scan_cmd == NL80211_CMD_TRIGGER_SCAN) {
+ drv->scan_state = SCAN_ABORTED;
+ /*
+ * Need to indicate that scan results are available in
+ * order not to make wpa_supplicant stop its scanning.
+ */
+ eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout,
+ drv, drv->ctx);
+ drv->last_scan_cmd = 0;
+ } else {
+ external_scan_event = 1;
+ }
+ send_scan_event(drv, 1, tb, external_scan_event);
break;
case NL80211_CMD_AUTHENTICATE:
case NL80211_CMD_ASSOCIATE:
tb[NL80211_ATTR_MAC],
tb[NL80211_ATTR_REQ_IE],
tb[NL80211_ATTR_RESP_IE],
- NULL, NULL, NULL, NULL);
+ tb[NL80211_ATTR_TIMED_OUT],
+ NULL, NULL, NULL, NULL, NULL);
break;
case NL80211_CMD_CH_SWITCH_NOTIFY:
mlme_event_ch_switch(drv,
nl80211_new_station_event(drv, bss, tb);
break;
case NL80211_CMD_DEL_STATION:
- nl80211_del_station_event(drv, tb);
+ nl80211_del_station_event(drv, bss, tb);
break;
case NL80211_CMD_SET_REKEY_OFFLOAD:
nl80211_rekey_offload_event(drv, tb);
break;
case IEEE80211_RADIOTAP_TX_FLAGS:
injected = 1;
- failed = le_to_host16((*(uint16_t *) iter.this_arg)) &
+ failed = le_to_host16((*(le16 *) iter.this_arg)) &
IEEE80211_RADIOTAP_F_TX_FAIL;
break;
case IEEE80211_RADIOTAP_DATA_RETRIES:
/*
* Driver interaction with Linux nl80211/cfg80211 - Scanning
+ * Copyright(c) 2015 Intel Deutschland GmbH
* Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi>
* Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
* Copyright (c) 2009-2010, Atheros Communications
#include "utils/common.h"
#include "utils/eloop.h"
#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
+#include "common/qca-vendor.h"
#include "driver_nl80211.h"
void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_driver_nl80211_data *drv = eloop_ctx;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Scan timeout - try to abort it");
+ if (!wpa_driver_nl80211_abort_scan(drv->first_bss))
+ return;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Failed to abort scan");
+
if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) {
wpa_driver_nl80211_set_mode(drv->first_bss,
drv->ap_scan_as_station);
drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
}
- wpa_printf(MSG_DEBUG, "Scan timeout - try to get results");
+
+ wpa_printf(MSG_DEBUG, "nl80211: Try to get scan results");
wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
}
goto fail;
}
nla_nest_end(msg, ssids);
+ } else {
+ wpa_printf(MSG_DEBUG, "nl80211: Passive scan requested");
}
if (params->extra_ies) {
goto fail;
}
+ if (params->bssid) {
+ wpa_printf(MSG_DEBUG, "nl80211: Scan for a specific BSSID: "
+ MACSTR, MAC2STR(params->bssid));
+ if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->bssid))
+ goto fail;
+ }
+
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
msg = NULL;
if (ret) {
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout,
drv, drv->ctx);
+ drv->last_scan_cmd = NL80211_CMD_TRIGGER_SCAN;
fail:
nlmsg_free(msg);
}
+static int
+nl80211_sched_scan_add_scan_plans(struct wpa_driver_nl80211_data *drv,
+ struct nl_msg *msg,
+ struct wpa_driver_scan_params *params)
+{
+ struct nlattr *plans;
+ struct sched_scan_plan *scan_plans = params->sched_scan_plans;
+ unsigned int i;
+
+ plans = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_PLANS);
+ if (!plans)
+ return -1;
+
+ for (i = 0; i < params->sched_scan_plans_num; i++) {
+ struct nlattr *plan = nla_nest_start(msg, i + 1);
+
+ if (!plan)
+ return -1;
+
+ if (!scan_plans[i].interval ||
+ scan_plans[i].interval >
+ drv->capa.max_sched_scan_plan_interval) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: sched scan plan no. %u: Invalid interval: %u",
+ i, scan_plans[i].interval);
+ return -1;
+ }
+
+ if (nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL,
+ scan_plans[i].interval))
+ return -1;
+
+ if (scan_plans[i].iterations >
+ drv->capa.max_sched_scan_plan_iterations) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: sched scan plan no. %u: Invalid number of iterations: %u",
+ i, scan_plans[i].iterations);
+ return -1;
+ }
+
+ if (scan_plans[i].iterations &&
+ nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_ITERATIONS,
+ scan_plans[i].iterations))
+ return -1;
+
+ nla_nest_end(msg, plan);
+
+ /*
+ * All the scan plans must specify the number of iterations
+ * except the last plan, which will run infinitely. So if the
+ * number of iterations is not specified, this ought to be the
+ * last scan plan.
+ */
+ if (!scan_plans[i].iterations)
+ break;
+ }
+
+ if (i != params->sched_scan_plans_num - 1) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: All sched scan plans but the last must specify number of iterations");
+ return -1;
+ }
+
+ nla_nest_end(msg, plans);
+ return 0;
+}
+
+
/**
* wpa_driver_nl80211_sched_scan - Initiate a scheduled scan
* @priv: Pointer to private driver data from wpa_driver_nl80211_init()
* @params: Scan parameters
- * @interval: Interval between scan cycles in milliseconds
* Returns: 0 on success, -1 on failure or if not supported
*/
int wpa_driver_nl80211_sched_scan(void *priv,
- struct wpa_driver_scan_params *params,
- u32 interval)
+ struct wpa_driver_scan_params *params)
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
return android_pno_start(bss, params);
#endif /* ANDROID */
+ if (!params->sched_scan_plans_num ||
+ params->sched_scan_plans_num > drv->capa.max_sched_scan_plans) {
+ wpa_printf(MSG_ERROR,
+ "nl80211: Invalid number of sched scan plans: %u",
+ params->sched_scan_plans_num);
+ return -1;
+ }
+
msg = nl80211_scan_common(bss, NL80211_CMD_START_SCHED_SCAN, params);
- if (!msg ||
- nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, interval))
+ if (!msg)
goto fail;
+ if (drv->capa.max_sched_scan_plan_iterations) {
+ if (nl80211_sched_scan_add_scan_plans(drv, msg, params))
+ goto fail;
+ } else {
+ if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL,
+ params->sched_scan_plans[0].interval * 1000))
+ goto fail;
+ }
+
if ((drv->num_filter_ssids &&
(int) drv->num_filter_ssids <= drv->capa.max_match_sets) ||
params->filter_rssi) {
goto fail;
}
- wpa_printf(MSG_DEBUG, "nl80211: Sched scan requested (ret=%d) - "
- "scan interval %d msec", ret, interval);
+ wpa_printf(MSG_DEBUG, "nl80211: Sched scan requested (ret=%d)", ret);
fail:
nlmsg_free(msg);
}
-const u8 * nl80211_get_ie(const u8 *ies, size_t ies_len, u8 ie)
-{
- const u8 *end, *pos;
-
- if (ies == NULL)
- return NULL;
-
- pos = ies;
- end = ies + ies_len;
-
- while (pos + 1 < end) {
- if (pos + 2 + pos[1] > end)
- break;
- if (pos[0] == ie)
- return pos;
- pos += 2 + pos[1];
- }
-
- return NULL;
-}
-
-
static int nl80211_scan_filtered(struct wpa_driver_nl80211_data *drv,
const u8 *ie, size_t ie_len)
{
if (drv->filter_ssids == NULL)
return 0;
- ssid = nl80211_get_ie(ie, ie_len, WLAN_EID_SSID);
+ ssid = get_ie(ie, ie_len, WLAN_EID_SSID);
if (ssid == NULL)
return 1;
if (os_memcmp(res->res[i]->bssid, r->bssid, ETH_ALEN) != 0)
continue;
- s1 = nl80211_get_ie((u8 *) (res->res[i] + 1),
- res->res[i]->ie_len, WLAN_EID_SSID);
- s2 = nl80211_get_ie((u8 *) (r + 1), r->ie_len, WLAN_EID_SSID);
+ s1 = get_ie((u8 *) (res->res[i] + 1),
+ res->res[i]->ie_len, WLAN_EID_SSID);
+ s2 = get_ie((u8 *) (r + 1), r->ie_len, WLAN_EID_SSID);
if (s1 == NULL || s2 == NULL || s1[1] != s2[1] ||
os_memcmp(s1, s2, 2 + s1[1]) != 0)
continue;
wpa_scan_results_free(res);
}
+
+
+int wpa_driver_nl80211_abort_scan(void *priv)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ int ret;
+ struct nl_msg *msg;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Abort scan");
+ msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_ABORT_SCAN);
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "nl80211: Abort scan failed: ret=%d (%s)",
+ ret, strerror(-ret));
+ }
+
+ return ret;
+}
+
+
+#ifdef CONFIG_DRIVER_NL80211_QCA
+
+static int scan_cookie_handler(struct nl_msg *msg, void *arg)
+{
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ u64 *cookie = arg;
+
+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+
+ if (tb[NL80211_ATTR_VENDOR_DATA]) {
+ struct nlattr *nl_vendor = tb[NL80211_ATTR_VENDOR_DATA];
+ struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_SCAN_MAX + 1];
+
+ nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_SCAN_MAX,
+ nla_data(nl_vendor), nla_len(nl_vendor), NULL);
+
+ if (tb_vendor[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE])
+ *cookie = nla_get_u64(
+ tb_vendor[QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE]);
+ }
+
+ return NL_SKIP;
+}
+
+
+/**
+ * wpa_driver_nl80211_vendor_scan - Request the driver to initiate a vendor scan
+ * @bss: Pointer to private driver data from wpa_driver_nl80211_init()
+ * @params: Scan parameters
+ * Returns: 0 on success, -1 on failure
+ */
+int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
+ struct wpa_driver_scan_params *params)
+{
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg = NULL;
+ struct nlattr *attr;
+ size_t i;
+ u32 scan_flags = 0;
+ int ret = -1;
+ u64 cookie = 0;
+
+ wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: vendor scan request");
+ drv->scan_for_auth = 0;
+
+ if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
+ QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN) )
+ goto fail;
+
+ attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
+ if (attr == NULL)
+ goto fail;
+
+ if (params->num_ssids) {
+ struct nlattr *ssids;
+
+ ssids = nla_nest_start(msg, QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS);
+ if (ssids == NULL)
+ goto fail;
+ for (i = 0; i < params->num_ssids; i++) {
+ wpa_hexdump_ascii(MSG_MSGDUMP, "nl80211: Scan SSID",
+ params->ssids[i].ssid,
+ params->ssids[i].ssid_len);
+ if (nla_put(msg, i + 1, params->ssids[i].ssid_len,
+ params->ssids[i].ssid))
+ goto fail;
+ }
+ nla_nest_end(msg, ssids);
+ }
+
+ if (params->extra_ies) {
+ wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan extra IEs",
+ params->extra_ies, params->extra_ies_len);
+ if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_SCAN_IE,
+ params->extra_ies_len, params->extra_ies))
+ goto fail;
+ }
+
+ if (params->freqs) {
+ struct nlattr *freqs;
+
+ freqs = nla_nest_start(msg,
+ QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES);
+ if (freqs == NULL)
+ goto fail;
+ for (i = 0; params->freqs[i]; i++) {
+ wpa_printf(MSG_MSGDUMP,
+ "nl80211: Scan frequency %u MHz",
+ params->freqs[i]);
+ if (nla_put_u32(msg, i + 1, params->freqs[i]))
+ goto fail;
+ }
+ nla_nest_end(msg, freqs);
+ }
+
+ os_free(drv->filter_ssids);
+ drv->filter_ssids = params->filter_ssids;
+ params->filter_ssids = NULL;
+ drv->num_filter_ssids = params->num_filter_ssids;
+
+ if (params->low_priority && drv->have_low_prio_scan) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Add NL80211_SCAN_FLAG_LOW_PRIORITY");
+ scan_flags |= NL80211_SCAN_FLAG_LOW_PRIORITY;
+ }
+
+ if (params->mac_addr_rand) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Add NL80211_SCAN_FLAG_RANDOM_ADDR");
+ scan_flags |= NL80211_SCAN_FLAG_RANDOM_ADDR;
+
+ if (params->mac_addr) {
+ wpa_printf(MSG_DEBUG, "nl80211: MAC address: " MACSTR,
+ MAC2STR(params->mac_addr));
+ if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_SCAN_MAC,
+ ETH_ALEN, params->mac_addr))
+ goto fail;
+ }
+
+ if (params->mac_addr_mask) {
+ wpa_printf(MSG_DEBUG, "nl80211: MAC address mask: "
+ MACSTR, MAC2STR(params->mac_addr_mask));
+ if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK,
+ ETH_ALEN, params->mac_addr_mask))
+ goto fail;
+ }
+ }
+
+ if (scan_flags &&
+ nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, scan_flags))
+ goto fail;
+
+ if (params->p2p_probe) {
+ struct nlattr *rates;
+
+ wpa_printf(MSG_DEBUG, "nl80211: P2P probe - mask SuppRates");
+
+ rates = nla_nest_start(msg,
+ QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES);
+ if (rates == NULL)
+ goto fail;
+
+ /*
+ * Remove 2.4 GHz rates 1, 2, 5.5, 11 Mbps from supported rates
+ * by masking out everything else apart from the OFDM rates 6,
+ * 9, 12, 18, 24, 36, 48, 54 Mbps from non-MCS rates. All 5 GHz
+ * rates are left enabled.
+ */
+ if (nla_put(msg, NL80211_BAND_2GHZ, 8,
+ "\x0c\x12\x18\x24\x30\x48\x60\x6c"))
+ goto fail;
+ nla_nest_end(msg, rates);
+
+ if (nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE))
+ goto fail;
+ }
+
+ nla_nest_end(msg, attr);
+
+ ret = send_and_recv_msgs(drv, msg, scan_cookie_handler, &cookie);
+ msg = NULL;
+ if (ret) {
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Vendor scan trigger failed: ret=%d (%s)",
+ ret, strerror(-ret));
+ goto fail;
+ }
+
+ drv->vendor_scan_cookie = cookie;
+ drv->scan_state = SCAN_REQUESTED;
+
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Vendor scan requested (ret=%d) - scan timeout 30 seconds, scan cookie:0x%llx",
+ ret, (long long unsigned int) cookie);
+ eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
+ eloop_register_timeout(30, 0, wpa_driver_nl80211_scan_timeout,
+ drv, drv->ctx);
+ drv->last_scan_cmd = NL80211_CMD_VENDOR;
+
+fail:
+ nlmsg_free(msg);
+ return ret;
+}
+
+
+/**
+ * nl80211_set_default_scan_ies - Set the scan default IEs to the driver
+ * @priv: Pointer to private driver data from wpa_driver_nl80211_init()
+ * @ies: Pointer to IEs buffer
+ * @ies_len: Length of IEs in bytes
+ * Returns: 0 on success, -1 on failure
+ */
+int nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg = NULL;
+ struct nlattr *attr;
+ int ret = -1;
+
+ if (!drv->set_wifi_conf_vendor_cmd_avail)
+ return -1;
+
+ if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
+ QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION))
+ goto fail;
+
+ attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
+ if (attr == NULL)
+ goto fail;
+
+ wpa_hexdump(MSG_MSGDUMP, "nl80211: Scan default IEs", ies, ies_len);
+ if (nla_put(msg, QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES,
+ ies_len, ies))
+ goto fail;
+
+ nla_nest_end(msg, attr);
+
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ msg = NULL;
+ if (ret) {
+ wpa_printf(MSG_ERROR,
+ "nl80211: Set scan default IEs failed: ret=%d (%s)",
+ ret, strerror(-ret));
+ goto fail;
+ }
+
+fail:
+ nlmsg_free(msg);
+ return ret;
+}
+
+#endif /* CONFIG_DRIVER_NL80211_QCA */
return NULL;
}
- while (results->num < (size_t) num && pos + sizeof(int) < end) {
+ while (results->num < (size_t) num && end - pos > (int) sizeof(int)) {
int len;
os_memcpy(&len, pos, sizeof(int));
pos += sizeof(int);
- if (len < 0 || len > 10000 || pos + len > end)
+ if (len < 0 || len > 10000 || len > end - pos)
break;
r = os_malloc(len);
/*
* WPA Supplicant - roboswitch driver interface
- * Copyright (c) 2008-2009 Jouke Witteveen
+ * Copyright (c) 2008-2012 Jouke Witteveen
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
os_free(drv);
return NULL;
}
- if (if_mii(&drv->ifr)->phy_id != ROBO_PHY_ADDR) {
+ /* BCM63xx devices provide 0 here */
+ if (if_mii(&drv->ifr)->phy_id != ROBO_PHY_ADDR &&
+ if_mii(&drv->ifr)->phy_id != 0) {
wpa_printf(MSG_INFO, "%s: Invalid phy address (not a "
"RoboSwitch?)", __func__);
os_free(drv);
static void wpa_driver_wext_event_wireless(struct wpa_driver_wext_data *drv,
- char *data, int len)
+ char *data, unsigned int len)
{
struct iw_event iwe_buf, *iwe = &iwe_buf;
char *pos, *end, *custom, *buf;
pos = data;
end = data + len;
- while (pos + IW_EV_LCP_LEN <= end) {
+ while ((size_t) (end - pos) >= IW_EV_LCP_LEN) {
/* Event data may be unaligned, so make a local, aligned copy
* before processing. */
os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d",
iwe->cmd, iwe->len);
- if (iwe->len <= IW_EV_LCP_LEN)
+ if (iwe->len <= IW_EV_LCP_LEN || iwe->len > end - pos)
return;
custom = pos + IW_EV_POINT_LEN;
}
break;
case IWEVMICHAELMICFAILURE:
- if (custom + iwe->u.data.length > end) {
+ if (iwe->u.data.length > end - custom) {
wpa_printf(MSG_DEBUG, "WEXT: Invalid "
"IWEVMICHAELMICFAILURE length");
return;
drv->ctx, custom, iwe->u.data.length);
break;
case IWEVCUSTOM:
- if (custom + iwe->u.data.length > end) {
+ if (iwe->u.data.length > end - custom) {
wpa_printf(MSG_DEBUG, "WEXT: Invalid "
"IWEVCUSTOM length");
return;
NULL);
break;
case IWEVASSOCREQIE:
- if (custom + iwe->u.data.length > end) {
+ if (iwe->u.data.length > end - custom) {
wpa_printf(MSG_DEBUG, "WEXT: Invalid "
"IWEVASSOCREQIE length");
return;
drv, custom, iwe->u.data.length);
break;
case IWEVASSOCRESPIE:
- if (custom + iwe->u.data.length > end) {
+ if (iwe->u.data.length > end - custom) {
wpa_printf(MSG_DEBUG, "WEXT: Invalid "
"IWEVASSOCRESPIE length");
return;
drv, custom, iwe->u.data.length);
break;
case IWEVPMKIDCAND:
- if (custom + iwe->u.data.length > end) {
+ if (iwe->u.data.length > end - custom) {
wpa_printf(MSG_DEBUG, "WEXT: Invalid "
"IWEVPMKIDCAND length");
return;
char *end)
{
int ssid_len = iwe->u.essid.length;
- if (custom + ssid_len > end)
+ if (ssid_len > end - custom)
return;
if (iwe->u.essid.flags &&
ssid_len > 0 &&
size_t clen;
clen = iwe->len;
- if (custom + clen > end)
+ if (clen > (size_t) (end - custom))
return;
maxrate = 0;
while (((ssize_t) clen) >= (ssize_t) sizeof(struct iw_param)) {
u8 *tmp;
clen = iwe->u.data.length;
- if (custom + clen > end)
+ if (clen > (size_t) (end - custom))
return;
if (clen > 7 && os_strncmp(custom, "wpa_ie=", 7) == 0) {
/* Figure out whether we need to fake any IEs */
pos = data->ie;
end = pos + data->ie_len;
- while (pos && pos + 1 < end) {
- if (pos + 2 + pos[1] > end)
+ while (pos && end - pos > 1) {
+ if (2 + pos[1] > end - pos)
break;
if (pos[0] == WLAN_EID_SSID)
ssid_ie = pos;
end = (char *) res_buf + len;
os_memset(&data, 0, sizeof(data));
- while (pos + IW_EV_LCP_LEN <= end) {
+ while ((size_t) (end - pos) >= IW_EV_LCP_LEN) {
/* Event data may be unaligned, so make a local, aligned copy
* before processing. */
os_memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
- if (iwe->len <= IW_EV_LCP_LEN)
+ if (iwe->len <= IW_EV_LCP_LEN || iwe->len > end - pos)
break;
custom = pos + IW_EV_POINT_LEN;
*/
#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>
#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 */
#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[] =
{
DRV_OBJS += ../src/drivers/driver_nl80211_event.o
DRV_OBJS += ../src/drivers/driver_nl80211_monitor.o
DRV_OBJS += ../src/drivers/driver_nl80211_scan.o
-DRV_OBJS += ../src/utils/radiotap.o
+ifdef CONFIG_DRIVER_NL80211_QCA
+DRV_CFLAGS += -DCONFIG_DRIVER_NL80211_QCA
+endif
NEED_SME=y
NEED_AP_MLME=y
NEED_NETLINK=y
NEED_LINUX_IOCTL=y
NEED_RFKILL=y
+NEED_RADIOTAP=y
ifdef CONFIG_LIBNL32
DRV_LIBS += -lnl-3
endif
ifdef CONFIG_LIBNL20
- DRV_LIBS += -lnl-genl
+ ifndef CONFIG_LIBNL_TINY
+ DRV_LIBS += -lnl-genl
+ endif
DRV_CFLAGS += -DCONFIG_LIBNL20
endif
endif
DRV_OBJS += ../src/drivers/rfkill.o
endif
+ifdef NEED_RADIOTAP
+DRV_OBJS += ../src/utils/radiotap.o
+endif
+
ifdef CONFIG_VLAN_NETLINK
ifdef CONFIG_FULL_DYNAMIC_VLAN
ifdef CONFIG_LIBNL32
DRV_OBJS += src/drivers/driver_nl80211_event.c
DRV_OBJS += src/drivers/driver_nl80211_monitor.c
DRV_OBJS += src/drivers/driver_nl80211_scan.c
-DRV_OBJS += src/utils/radiotap.c
+ifdef CONFIG_DRIVER_NL80211_QCA
+DRV_CFLAGS += -DCONFIG_DRIVER_NL80211_QCA
+endif
NEED_SME=y
NEED_AP_MLME=y
NEED_NETLINK=y
NEED_LINUX_IOCTL=y
NEED_RFKILL=y
+NEED_RADIOTAP=y
ifdef CONFIG_LIBNL32
DRV_LIBS += -lnl-3
endif
ifdef CONFIG_LIBNL20
- DRV_LIBS += -lnl-genl
+ ifndef CONFIG_LIBNL_TINY
+ DRV_LIBS += -lnl-genl
+ endif
DRV_CFLAGS += -DCONFIG_LIBNL20
endif
endif
DRV_OBJS += src/drivers/rfkill.c
endif
+ifdef NEED_RADIOTAP
+DRV_OBJS += src/utils/radiotap.c
+endif
+
ifdef CONFIG_DRIVER_CUSTOM
DRV_CFLAGS += -DCONFIG_DRIVER_CUSTOM
endif
* Copyright 2008, 2009 Luis R. Rodriguez <lrodriguez@atheros.com>
* Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com>
* Copyright 2008 Colin McCabe <colin@cozybit.com>
+ * Copyright 2015 Intel Deutschland GmbH
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* @NL80211_CMD_GET_SCAN: get scan results
* @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters
* %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the
- * probe requests at CCK rate or not.
+ * probe requests at CCK rate or not. %NL80211_ATTR_MAC can be used to
+ * specify a BSSID to scan for; if not included, the wildcard BSSID will
+ * be used.
* @NL80211_CMD_NEW_SCAN_RESULTS: scan notification (as a reply to
* NL80211_CMD_GET_SCAN and on the "scan" multicast group)
* @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons,
* partial scan results may be available
*
* @NL80211_CMD_START_SCHED_SCAN: start a scheduled scan at certain
- * intervals, as specified by %NL80211_ATTR_SCHED_SCAN_INTERVAL.
+ * intervals and certain number of cycles, as specified by
+ * %NL80211_ATTR_SCHED_SCAN_PLANS. If %NL80211_ATTR_SCHED_SCAN_PLANS is
+ * not specified and only %NL80211_ATTR_SCHED_SCAN_INTERVAL is specified,
+ * scheduled scan will run in an infinite loop with the specified interval.
+ * These attributes are mutually exculsive,
+ * i.e. NL80211_ATTR_SCHED_SCAN_INTERVAL must not be passed if
+ * NL80211_ATTR_SCHED_SCAN_PLANS is defined.
+ * If for some reason scheduled scan is aborted by the driver, all scan
+ * plans are canceled (including scan plans that did not start yet).
* Like with normal scans, if SSIDs (%NL80211_ATTR_SCAN_SSIDS)
* are passed, they are used in the probe requests. For
* broadcast, a broadcast SSID must be passed (ie. an empty
* @NL80211_CMD_ASSOCIATE: association request and notification; like
* NL80211_CMD_AUTHENTICATE but for Association and Reassociation
* (similar to MLME-ASSOCIATE.request, MLME-REASSOCIATE.request,
- * MLME-ASSOCIATE.confirm or MLME-REASSOCIATE.confirm primitives).
+ * MLME-ASSOCIATE.confirm or MLME-REASSOCIATE.confirm primitives). The
+ * %NL80211_ATTR_PREV_BSSID attribute is used to specify whether the
+ * request is for the initial association to an ESS (that attribute not
+ * included) or for reassociation within the ESS (that attribute is
+ * included).
* @NL80211_CMD_DEAUTHENTICATE: deauthentication request and notification; like
* NL80211_CMD_AUTHENTICATE but for Deauthentication frames (similar to
* MLME-DEAUTHENTICATION.request and MLME-DEAUTHENTICATE.indication
* set of BSSID,frequency parameters is used (i.e., either the enforcing
* %NL80211_ATTR_MAC,%NL80211_ATTR_WIPHY_FREQ or the less strict
* %NL80211_ATTR_MAC_HINT and %NL80211_ATTR_WIPHY_FREQ_HINT).
+ * %NL80211_ATTR_PREV_BSSID can be used to request a reassociation within
+ * the ESS in case the device is already associated and an association with
+ * a different BSS is desired.
* Background scan period can optionally be
* specified in %NL80211_ATTR_BG_SCAN_PERIOD,
* if not specified default background scan configuration
* This attribute is ignored if driver does not support roam scan.
* It is also sent as an event, with the BSSID and response IEs when the
* connection is established or failed to be established. This can be
- * determined by the STATUS_CODE attribute.
+ * determined by the %NL80211_ATTR_STATUS_CODE attribute (0 = success,
+ * non-zero = failure). If %NL80211_ATTR_TIMED_OUT is included in the
+ * event, the connection attempt failed due to not being able to initiate
+ * authentication/association or not receiving a response from the AP.
+ * Non-zero %NL80211_ATTR_STATUS_CODE value is indicated in that case as
+ * well to remain backwards compatible.
* @NL80211_CMD_ROAM: request that the card roam (currently not implemented),
* sent as an event when the card/driver roamed by itself.
* @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify
* as an event to indicate changes for devices with wiphy-specific regdom
* management.
*
+ * @NL80211_CMD_ABORT_SCAN: Stop an ongoing scan. Returns -ENOENT if a scan is
+ * not running. The driver indicates the status of the scan through
+ * cfg80211_scan_done().
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
NL80211_CMD_WIPHY_REG_CHANGE,
+ NL80211_CMD_ABORT_SCAN,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
* @NL80211_ATTR_RESP_IE: (Re)association response information elements as
* sent by peer, for ROAM and successful CONNECT events.
*
- * @NL80211_ATTR_PREV_BSSID: previous BSSID, to be used by in ASSOCIATE
- * commands to specify using a reassociate frame
+ * @NL80211_ATTR_PREV_BSSID: previous BSSID, to be used in ASSOCIATE and CONNECT
+ * commands to specify a request to reassociate within an ESS, i.e., to use
+ * Reassociate Request frame (with the value of this attribute in the
+ * Current AP address field) instead of Association Request frame which is
+ * used for the initial association to an ESS.
*
* @NL80211_ATTR_KEY: key information in a nested attribute with
* %NL80211_KEY_* sub-attributes
* underlying device supports these minimal RRM features:
* %NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES,
* %NL80211_FEATURE_QUIET,
+ * Or, if global RRM is supported, see:
+ * %NL80211_EXT_FEATURE_RRM
* If this flag is used, driver must add the Power Capabilities IE to the
* association request. In addition, it must also set the RRM capability
* flag in the association request's Capability Info field.
* should be contained in the result as the sum of the respective counters
* over all channels.
*
- * @NL80211_ATTR_SCHED_SCAN_DELAY: delay before a scheduled scan (or a
- * WoWLAN net-detect scan) is started, u32 in seconds.
+ * @NL80211_ATTR_SCHED_SCAN_DELAY: delay before the first cycle of a
+ * scheduled scan is started. Or the delay before a WoWLAN
+ * net-detect scan is started, counting from the moment the
+ * system is suspended. This value is a u32, in seconds.
* @NL80211_ATTR_REG_INDOOR: flag attribute, if set indicates that the device
* is operating in an indoor environment.
*
+ * @NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS: maximum number of scan plans for
+ * scheduled scan supported by the device (u32), a wiphy attribute.
+ * @NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL: maximum interval (in seconds) for
+ * a scan plan (u32), a wiphy attribute.
+ * @NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS: maximum number of iterations in
+ * a scan plan (u32), a wiphy attribute.
+ * @NL80211_ATTR_SCHED_SCAN_PLANS: a list of scan plans for scheduled scan.
+ * Each scan plan defines the number of scan iterations and the interval
+ * between scans. The last scan plan will always run infinitely,
+ * thus it must not specify the number of iterations, only the interval
+ * between scans. The scan plans are executed sequentially.
+ * Each scan plan is a nested attribute of &enum nl80211_sched_scan_plan.
+ * @NL80211_ATTR_PBSS: flag attribute. If set it means operate
+ * in a PBSS. Specified in %NL80211_CMD_CONNECT to request
+ * connecting to a PCP, and in %NL80211_CMD_START_AP to start
+ * a PCP instead of AP. Relevant for DMG networks only.
+ * @NL80211_ATTR_BSS_SELECT: nested attribute for driver supporting the
+ * BSS selection feature. When used with %NL80211_CMD_GET_WIPHY it contains
+ * attributes according &enum nl80211_bss_select_attr to indicate what
+ * BSS selection behaviours are supported. When used with %NL80211_CMD_CONNECT
+ * it contains the behaviour-specific attribute containing the parameters for
+ * BSS selection to be done by driver and/or firmware.
+ *
+ * @NL80211_ATTR_STA_SUPPORT_P2P_PS: whether P2P PS mechanism supported
+ * or not. u8, one of the values of &enum nl80211_sta_p2p_ps_status
+ *
+ * @NL80211_ATTR_PAD: attribute used for padding for 64-bit alignment
+ *
+ * @NL80211_ATTR_IFTYPE_EXT_CAPA: Nested attribute of the following attributes:
+ * %NL80211_ATTR_IFTYPE, %NL80211_ATTR_EXT_CAPA,
+ * %NL80211_ATTR_EXT_CAPA_MASK, to specify the extended capabilities per
+ * interface type.
+ *
+ * @NL80211_ATTR_MU_MIMO_GROUP_DATA: array of 24 bytes that defines a MU-MIMO
+ * groupID for monitor mode.
+ * The first 8 bytes are a mask that defines the membership in each
+ * group (there are 64 groups, group 0 and 63 are reserved),
+ * each bit represents a group and set to 1 for being a member in
+ * that group and 0 for not being a member.
+ * The remaining 16 bytes define the position in each group: 2 bits for
+ * each group.
+ * (smaller group numbers represented on most significant bits and bigger
+ * group numbers on least significant bits.)
+ * This attribute is used only if all interfaces are in monitor mode.
+ * Set this attribute in order to monitor packets using the given MU-MIMO
+ * groupID data.
+ * to turn off that feature set all the bits of the groupID to zero.
+ * @NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR: mac address for the sniffer to follow
+ * when using MU-MIMO air sniffer.
+ * to turn that feature off set an invalid mac address
+ * (e.g. FF:FF:FF:FF:FF:FF)
+ *
+ * @NL80211_ATTR_SCAN_START_TIME_TSF: The time at which the scan was actually
+ * started (u64). The time is the TSF of the BSS the interface that
+ * requested the scan is connected to (if available, otherwise this
+ * attribute must not be included).
+ * @NL80211_ATTR_SCAN_START_TIME_TSF_BSSID: The BSS according to which
+ * %NL80211_ATTR_SCAN_START_TIME_TSF is set.
+ * @NL80211_ATTR_MEASUREMENT_DURATION: measurement duration in TUs (u16). If
+ * %NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY is not set, this is the
+ * maximum measurement duration allowed. This attribute is used with
+ * measurement requests. It can also be used with %NL80211_CMD_TRIGGER_SCAN
+ * if the scan is used for beacon report radio measurement.
+ * @NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY: flag attribute that indicates
+ * that the duration specified with %NL80211_ATTR_MEASUREMENT_DURATION is
+ * mandatory. If this flag is not set, the duration is the maximum duration
+ * and the actual measurement duration may be shorter.
+ *
+ * @NL80211_ATTR_MESH_PEER_AID: Association ID for the mesh peer (u16). This is
+ * used to pull the stored data for mesh peer in power save state.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
NL80211_ATTR_REG_INDOOR,
+ NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS,
+ NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL,
+ NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS,
+ NL80211_ATTR_SCHED_SCAN_PLANS,
+
+ NL80211_ATTR_PBSS,
+
+ NL80211_ATTR_BSS_SELECT,
+
+ NL80211_ATTR_STA_SUPPORT_P2P_PS,
+
+ NL80211_ATTR_PAD,
+
+ NL80211_ATTR_IFTYPE_EXT_CAPA,
+
+ NL80211_ATTR_MU_MIMO_GROUP_DATA,
+ NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR,
+
+ NL80211_ATTR_SCAN_START_TIME_TSF,
+ NL80211_ATTR_SCAN_START_TIME_TSF_BSSID,
+ NL80211_ATTR_MEASUREMENT_DURATION,
+ NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY,
+
+ NL80211_ATTR_MESH_PEER_AID,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1
};
+/**
+ * enum nl80211_sta_p2p_ps_status - station support of P2P PS
+ *
+ * @NL80211_P2P_PS_UNSUPPORTED: station doesn't support P2P PS mechanism
+ * @@NL80211_P2P_PS_SUPPORTED: station supports P2P PS mechanism
+ * @NUM_NL80211_P2P_PS_STATUS: number of values
+ */
+enum nl80211_sta_p2p_ps_status {
+ NL80211_P2P_PS_UNSUPPORTED = 0,
+ NL80211_P2P_PS_SUPPORTED,
+
+ NUM_NL80211_P2P_PS_STATUS,
+};
+
#define NL80211_STA_FLAG_MAX_OLD_API NL80211_STA_FLAG_TDLS_PEER
/**
* TID+1 and the special TID 16 (i.e. value 17) is used for non-QoS frames;
* each one of those is again nested with &enum nl80211_tid_stats
* attributes carrying the actual values.
+ * @NL80211_STA_INFO_RX_DURATION: aggregate PPDU duration for all frames
+ * received from the station (u64, usec)
+ * @NL80211_STA_INFO_PAD: attribute used for padding for 64-bit alignment
* @__NL80211_STA_INFO_AFTER_LAST: internal
* @NL80211_STA_INFO_MAX: highest possible station info attribute
*/
NL80211_STA_INFO_BEACON_RX,
NL80211_STA_INFO_BEACON_SIGNAL_AVG,
NL80211_STA_INFO_TID_STATS,
+ NL80211_STA_INFO_RX_DURATION,
+ NL80211_STA_INFO_PAD,
/* keep last */
__NL80211_STA_INFO_AFTER_LAST,
* transmitted MSDUs (not counting the first attempt; u64)
* @NL80211_TID_STATS_TX_MSDU_FAILED: number of failed transmitted
* MSDUs (u64)
+ * @NL80211_TID_STATS_PAD: attribute used for padding for 64-bit alignment
* @NUM_NL80211_TID_STATS: number of attributes here
* @NL80211_TID_STATS_MAX: highest numbered attribute here
*/
NL80211_TID_STATS_TX_MSDU,
NL80211_TID_STATS_TX_MSDU_RETRIES,
NL80211_TID_STATS_TX_MSDU_FAILED,
+ NL80211_TID_STATS_PAD,
/* keep last */
NUM_NL80211_TID_STATS,
* an indoor surroundings, i.e., it is connected to AC power (and not
* through portable DC inverters) or is under the control of a master
* that is acting as an AP and is connected to AC power.
- * @NL80211_FREQUENCY_ATTR_GO_CONCURRENT: GO operation is allowed on this
+ * @NL80211_FREQUENCY_ATTR_IR_CONCURRENT: IR operation is allowed on this
* channel if it's connected concurrently to a BSS on the same channel on
* the 2 GHz band or to a channel in the same UNII band (on the 5 GHz
- * band), and IEEE80211_CHAN_RADAR is not set. Instantiating a GO on a
- * channel that has the GO_CONCURRENT attribute set can be done when there
- * is a clear assessment that the device is operating under the guidance of
- * an authorized master, i.e., setting up a GO while the device is also
- * connected to an AP with DFS and radar detection on the UNII band (it is
- * up to user-space, i.e., wpa_supplicant to perform the required
- * verifications)
+ * band), and IEEE80211_CHAN_RADAR is not set. Instantiating a GO or TDLS
+ * off-channel on a channel that has the IR_CONCURRENT attribute set can be
+ * done when there is a clear assessment that the device is operating under
+ * the guidance of an authorized master, i.e., setting up a GO or TDLS
+ * off-channel while the device is also connected to an AP with DFS and
+ * radar detection on the UNII band (it is up to user-space, i.e.,
+ * wpa_supplicant to perform the required verifications). Using this
+ * attribute for IR is disallowed for master interfaces (IBSS, AP).
* @NL80211_FREQUENCY_ATTR_NO_20MHZ: 20 MHz operation is not allowed
* on this channel in current regulatory domain.
* @NL80211_FREQUENCY_ATTR_NO_10MHZ: 10 MHz operation is not allowed
* See https://apps.fcc.gov/eas/comments/GetPublishedDocument.html?id=327&tn=528122
* for more information on the FCC description of the relaxations allowed
* by NL80211_FREQUENCY_ATTR_INDOOR_ONLY and
- * NL80211_FREQUENCY_ATTR_GO_CONCURRENT.
+ * NL80211_FREQUENCY_ATTR_IR_CONCURRENT.
*/
enum nl80211_frequency_attr {
__NL80211_FREQUENCY_ATTR_INVALID,
NL80211_FREQUENCY_ATTR_NO_160MHZ,
NL80211_FREQUENCY_ATTR_DFS_CAC_TIME,
NL80211_FREQUENCY_ATTR_INDOOR_ONLY,
- NL80211_FREQUENCY_ATTR_GO_CONCURRENT,
+ NL80211_FREQUENCY_ATTR_IR_CONCURRENT,
NL80211_FREQUENCY_ATTR_NO_20MHZ,
NL80211_FREQUENCY_ATTR_NO_10MHZ,
#define NL80211_FREQUENCY_ATTR_PASSIVE_SCAN NL80211_FREQUENCY_ATTR_NO_IR
#define NL80211_FREQUENCY_ATTR_NO_IBSS NL80211_FREQUENCY_ATTR_NO_IR
#define NL80211_FREQUENCY_ATTR_NO_IR NL80211_FREQUENCY_ATTR_NO_IR
+#define NL80211_FREQUENCY_ATTR_GO_CONCURRENT \
+ NL80211_FREQUENCY_ATTR_IR_CONCURRENT
/**
* enum nl80211_bitrate_attr - bitrate attributes
* @NL80211_RRF_AUTO_BW: maximum available bandwidth should be calculated
* base on contiguous rules and wider channels will be allowed to cross
* multiple contiguous/overlapping frequency ranges.
- * @NL80211_RRF_GO_CONCURRENT: See &NL80211_FREQUENCY_ATTR_GO_CONCURRENT
+ * @NL80211_RRF_IR_CONCURRENT: See &NL80211_FREQUENCY_ATTR_IR_CONCURRENT
* @NL80211_RRF_NO_HT40MINUS: channels can't be used in HT40- operation
* @NL80211_RRF_NO_HT40PLUS: channels can't be used in HT40+ operation
* @NL80211_RRF_NO_80MHZ: 80MHz operation not allowed
NL80211_RRF_NO_IR = 1<<7,
__NL80211_RRF_NO_IBSS = 1<<8,
NL80211_RRF_AUTO_BW = 1<<11,
- NL80211_RRF_GO_CONCURRENT = 1<<12,
+ NL80211_RRF_IR_CONCURRENT = 1<<12,
NL80211_RRF_NO_HT40MINUS = 1<<13,
NL80211_RRF_NO_HT40PLUS = 1<<14,
NL80211_RRF_NO_80MHZ = 1<<15,
#define NL80211_RRF_NO_IR NL80211_RRF_NO_IR
#define NL80211_RRF_NO_HT40 (NL80211_RRF_NO_HT40MINUS |\
NL80211_RRF_NO_HT40PLUS)
+#define NL80211_RRF_GO_CONCURRENT NL80211_RRF_IR_CONCURRENT
/* For backport compatibility with older userspace */
#define NL80211_RRF_NO_IR_ALL (NL80211_RRF_NO_IR | __NL80211_RRF_NO_IBSS)
* transmitting data (on channel or globally)
* @NL80211_SURVEY_INFO_TIME_SCAN: time the radio spent for scan
* (on this channel or globally)
+ * @NL80211_SURVEY_INFO_PAD: attribute used for padding for 64-bit alignment
* @NL80211_SURVEY_INFO_MAX: highest survey info attribute number
* currently defined
* @__NL80211_SURVEY_INFO_AFTER_LAST: internal use
NL80211_SURVEY_INFO_TIME_RX,
NL80211_SURVEY_INFO_TIME_TX,
NL80211_SURVEY_INFO_TIME_SCAN,
+ NL80211_SURVEY_INFO_PAD,
/* keep last */
__NL80211_SURVEY_INFO_AFTER_LAST,
* (not present if no beacon frame has been received yet)
* @NL80211_BSS_PRESP_DATA: the data in @NL80211_BSS_INFORMATION_ELEMENTS and
* @NL80211_BSS_TSF is known to be from a probe response (flag attribute)
+ * @NL80211_BSS_LAST_SEEN_BOOTTIME: CLOCK_BOOTTIME timestamp when this entry
+ * was last updated by a received frame. The value is expected to be
+ * accurate to about 10ms. (u64, nanoseconds)
+ * @NL80211_BSS_PAD: attribute used for padding for 64-bit alignment
+ * @NL80211_BSS_PARENT_TSF: the time at the start of reception of the first
+ * octet of the timestamp field of the last beacon/probe received for
+ * this BSS. The time is the TSF of the BSS specified by
+ * @NL80211_BSS_PARENT_BSSID. (u64).
+ * @NL80211_BSS_PARENT_BSSID: the BSS according to which @NL80211_BSS_PARENT_TSF
+ * is set.
* @__NL80211_BSS_AFTER_LAST: internal
* @NL80211_BSS_MAX: highest BSS attribute
*/
NL80211_BSS_CHAN_WIDTH,
NL80211_BSS_BEACON_TSF,
NL80211_BSS_PRESP_DATA,
+ NL80211_BSS_LAST_SEEN_BOOTTIME,
+ NL80211_BSS_PAD,
+ NL80211_BSS_PARENT_TSF,
+ NL80211_BSS_PARENT_BSSID,
/* keep last */
__NL80211_BSS_AFTER_LAST,
* @NL80211_BAND_2GHZ: 2.4 GHz ISM band
* @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz)
* @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 64.80 GHz)
+ * @NUM_NL80211_BANDS: number of bands, avoid using this in userspace
+ * since newer kernel versions may support more bands
*/
enum nl80211_band {
NL80211_BAND_2GHZ,
NL80211_BAND_5GHZ,
NL80211_BAND_60GHZ,
+
+ NUM_NL80211_BANDS,
};
/**
/**
* enum nl80211_ext_feature_index - bit index of extended features.
* @NL80211_EXT_FEATURE_VHT_IBSS: This driver supports IBSS with VHT datarates.
+ * @NL80211_EXT_FEATURE_RRM: This driver supports RRM. When featured, user can
+ * can request to use RRM (see %NL80211_ATTR_USE_RRM) with
+ * %NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests, which will set
+ * the ASSOC_REQ_USE_RRM flag in the association request even if
+ * NL80211_FEATURE_QUIET is not advertized.
+ * @NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER: This device supports MU-MIMO air
+ * sniffer which means that it can be configured to hear packets from
+ * certain groups which can be configured by the
+ * %NL80211_ATTR_MU_MIMO_GROUP_DATA attribute,
+ * or can be configured to follow a station by configuring the
+ * %NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR attribute.
+ * @NL80211_EXT_FEATURE_SCAN_START_TIME: This driver includes the actual
+ * time the scan started in scan results event. The time is the TSF of
+ * the BSS that the interface that requested the scan is connected to
+ * (if available).
+ * @NL80211_EXT_FEATURE_BSS_PARENT_TSF: Per BSS, this driver reports the
+ * time the last beacon/probe was received. The time is the TSF of the
+ * BSS that the interface that requested the scan is connected to
+ * (if available).
+ * @NL80211_EXT_FEATURE_SET_SCAN_DWELL: This driver supports configuration of
+ * channel dwell time.
*
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
*/
enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_VHT_IBSS,
+ NL80211_EXT_FEATURE_RRM,
+ NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER,
+ NL80211_EXT_FEATURE_SCAN_START_TIME,
+ NL80211_EXT_FEATURE_BSS_PARENT_TSF,
+ NL80211_EXT_FEATURE_SET_SCAN_DWELL,
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
NL80211_TDLS_PEER_WMM = 1<<2,
};
+/**
+ * enum nl80211_sched_scan_plan - scanning plan for scheduled scan
+ * @__NL80211_SCHED_SCAN_PLAN_INVALID: attribute number 0 is reserved
+ * @NL80211_SCHED_SCAN_PLAN_INTERVAL: interval between scan iterations. In
+ * seconds (u32).
+ * @NL80211_SCHED_SCAN_PLAN_ITERATIONS: number of scan iterations in this
+ * scan plan (u32). The last scan plan must not specify this attribute
+ * because it will run infinitely. A value of zero is invalid as it will
+ * make the scan plan meaningless.
+ * @NL80211_SCHED_SCAN_PLAN_MAX: highest scheduled scan plan attribute number
+ * currently defined
+ * @__NL80211_SCHED_SCAN_PLAN_AFTER_LAST: internal use
+ */
+enum nl80211_sched_scan_plan {
+ __NL80211_SCHED_SCAN_PLAN_INVALID,
+ NL80211_SCHED_SCAN_PLAN_INTERVAL,
+ NL80211_SCHED_SCAN_PLAN_ITERATIONS,
+
+ /* keep last */
+ __NL80211_SCHED_SCAN_PLAN_AFTER_LAST,
+ NL80211_SCHED_SCAN_PLAN_MAX =
+ __NL80211_SCHED_SCAN_PLAN_AFTER_LAST - 1
+};
+
+/**
+ * struct nl80211_bss_select_rssi_adjust - RSSI adjustment parameters.
+ *
+ * @band: band of BSS that must match for RSSI value adjustment.
+ * @delta: value used to adjust the RSSI value of matching BSS.
+ */
+struct nl80211_bss_select_rssi_adjust {
+ __u8 band;
+ __s8 delta;
+} __attribute__((packed));
+
+/**
+ * enum nl80211_bss_select_attr - attributes for bss selection.
+ *
+ * @__NL80211_BSS_SELECT_ATTR_INVALID: reserved.
+ * @NL80211_BSS_SELECT_ATTR_RSSI: Flag indicating only RSSI-based BSS selection
+ * is requested.
+ * @NL80211_BSS_SELECT_ATTR_BAND_PREF: attribute indicating BSS
+ * selection should be done such that the specified band is preferred.
+ * When there are multiple BSS-es in the preferred band, the driver
+ * shall use RSSI-based BSS selection as a second step. The value of
+ * this attribute is according to &enum nl80211_band (u32).
+ * @NL80211_BSS_SELECT_ATTR_RSSI_ADJUST: When present the RSSI level for
+ * BSS-es in the specified band is to be adjusted before doing
+ * RSSI-based BSS selection. The attribute value is a packed structure
+ * value as specified by &struct nl80211_bss_select_rssi_adjust.
+ * @NL80211_BSS_SELECT_ATTR_MAX: highest bss select attribute number.
+ * @__NL80211_BSS_SELECT_ATTR_AFTER_LAST: internal use.
+ *
+ * One and only one of these attributes are found within %NL80211_ATTR_BSS_SELECT
+ * for %NL80211_CMD_CONNECT. It specifies the required BSS selection behaviour
+ * which the driver shall use.
+ */
+enum nl80211_bss_select_attr {
+ __NL80211_BSS_SELECT_ATTR_INVALID,
+ NL80211_BSS_SELECT_ATTR_RSSI,
+ NL80211_BSS_SELECT_ATTR_BAND_PREF,
+ NL80211_BSS_SELECT_ATTR_RSSI_ADJUST,
+
+ /* keep last */
+ __NL80211_BSS_SELECT_ATTR_AFTER_LAST,
+ NL80211_BSS_SELECT_ATTR_MAX = __NL80211_BSS_SELECT_ATTR_AFTER_LAST - 1
+};
+
#endif /* __LINUX_NL80211_H */
#include "includes.h"
#include <fcntl.h>
+#include <limits.h>
#include "utils/common.h"
#include "utils/eloop.h"
struct rfkill_config *cfg;
int fd;
int blocked;
+ uint32_t idx;
};
(int) len, RFKILL_EVENT_SIZE_V1);
return;
}
+ if (event.op != RFKILL_OP_CHANGE || event.idx != rfkill->idx)
+ return;
+
wpa_printf(MSG_DEBUG, "rfkill: event: idx=%u type=%d "
"op=%u soft=%u hard=%u",
event.idx, event.type, event.op, event.soft,
event.hard);
- if (event.op != RFKILL_OP_CHANGE || event.type != RFKILL_TYPE_WLAN)
- return;
if (event.hard) {
wpa_printf(MSG_INFO, "rfkill: WLAN hard blocked");
struct rfkill_data *rfkill;
struct rfkill_event event;
ssize_t len;
+ char *phy = NULL, *rfk_phy;
+ char buf[24 + IFNAMSIZ + 1];
+ char buf2[31 + 11 + 1];
+ int found = 0;
rfkill = os_zalloc(sizeof(*rfkill));
if (rfkill == NULL)
return NULL;
+ os_snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211",
+ cfg->ifname);
+ phy = realpath(buf, NULL);
+ if (!phy) {
+ wpa_printf(MSG_INFO, "rfkill: Cannot get wiphy information");
+ goto fail;
+ }
+
rfkill->cfg = cfg;
rfkill->fd = open("/dev/rfkill", O_RDONLY);
if (rfkill->fd < 0) {
(int) len, RFKILL_EVENT_SIZE_V1);
continue;
}
+ if (event.op != RFKILL_OP_ADD ||
+ event.type != RFKILL_TYPE_WLAN)
+ continue;
+
+ os_snprintf(buf2, sizeof(buf2),
+ "/sys/class/rfkill/rfkill%d/device", event.idx);
+ rfk_phy = realpath(buf2, NULL);
+ if (!rfk_phy)
+ goto fail2;
+ found = os_strcmp(phy, rfk_phy) == 0;
+ free(rfk_phy);
+
+ if (!found)
+ continue;
+
wpa_printf(MSG_DEBUG, "rfkill: initial event: idx=%u type=%d "
"op=%u soft=%u hard=%u",
event.idx, event.type, event.op, event.soft,
event.hard);
- if (event.op != RFKILL_OP_ADD ||
- event.type != RFKILL_TYPE_WLAN)
- continue;
+
+ rfkill->idx = event.idx;
if (event.hard) {
wpa_printf(MSG_INFO, "rfkill: WLAN hard blocked");
rfkill->blocked = 1;
wpa_printf(MSG_INFO, "rfkill: WLAN soft blocked");
rfkill->blocked = 1;
}
+ break;
}
+ if (!found)
+ goto fail2;
+
+ free(phy);
eloop_register_read_sock(rfkill->fd, rfkill_receive, rfkill, NULL);
return rfkill;
close(rfkill->fd);
fail:
os_free(rfkill);
+ /* use standard free function to match realpath() */
+ free(phy);
return NULL;
}
int dhlen;
dhlen = eap_eke_dh_len(dhgroup);
- if (dhlen < 0)
- return -1;
- if (encr != EAP_EKE_ENCR_AES128_CBC)
+ if (dhlen < 0 || encr != EAP_EKE_ENCR_AES128_CBC)
return -1;
return AES_BLOCK_SIZE + dhlen;
}
size_t pub_len, i;
generator = eap_eke_dh_generator(group);
- if (generator < 0 || generator > 255)
- return -1;
- gen = generator;
-
dh = eap_eke_dh_group(group);
- if (dh == NULL)
+ if (generator < 0 || generator > 255 || !dh)
return -1;
+ gen = generator;
/* x = random number 2 .. p-1 */
if (random_get_bytes(ret_priv, dh->prime_len))
size_t len;
const struct dh_group *dh;
- if (sess->encr != EAP_EKE_ENCR_AES128_CBC)
- return -1;
-
dh = eap_eke_dh_group(sess->dhgroup);
- if (dh == NULL)
+ if (sess->encr != EAP_EKE_ENCR_AES128_CBC || !dh)
return -1;
/* Decrypt peer DHComponent */
if (*prot_len < block_size + data_len + pad + icv_len) {
wpa_printf(MSG_INFO, "EAP-EKE: Not enough room for Prot() data");
+ return -1;
}
pos = prot;
pos += pad;
}
- if (aes_128_cbc_encrypt(sess->ke, iv, e, data_len + pad) < 0)
- return -1;
-
- if (eap_eke_mac(sess->mac, sess->ki, e, data_len + pad, pos) < 0)
+ if (aes_128_cbc_encrypt(sess->ke, iv, e, data_len + pad) < 0 ||
+ eap_eke_mac(sess->mac, sess->ki, e, data_len + pad, pos) < 0)
return -1;
pos += icv_len;
else
return -1;
- if (prot_len < 2 * block_size + icv_len)
- return -1;
- if ((prot_len - icv_len) % block_size)
+ if (prot_len < 2 * block_size + icv_len ||
+ (prot_len - icv_len) % block_size)
return -1;
if (eap_eke_mac(sess->mac, sess->ki, prot + block_size,
sess->mac = mac;
sess->prf_len = eap_eke_prf_len(prf);
- if (sess->prf_len < 0)
- return -1;
sess->nonce_len = eap_eke_nonce_len(prf);
- if (sess->nonce_len < 0)
- return -1;
sess->auth_len = eap_eke_auth_len(prf);
- if (sess->auth_len < 0)
- return -1;
sess->dhcomp_len = eap_eke_dhcomp_len(sess->dhgroup, sess->encr);
- if (sess->dhcomp_len < 0)
- return -1;
sess->pnonce_len = eap_eke_pnonce_len(sess->mac);
- if (sess->pnonce_len < 0)
- return -1;
sess->pnonce_ps_len = eap_eke_pnonce_ps_len(sess->mac);
- if (sess->pnonce_ps_len < 0)
+ if (sess->prf_len < 0 || sess->nonce_len < 0 || sess->auth_len < 0 ||
+ sess->dhcomp_len < 0 || sess->pnonce_len < 0 ||
+ sess->pnonce_ps_len < 0)
return -1;
return 0;
}
-u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn,
- const char *label, size_t len)
+u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn, size_t len)
{
u8 *out;
if (out == NULL)
return NULL;
- if (tls_connection_prf(ssl_ctx, conn, label, 1, 1, out, len)) {
+ if (tls_connection_get_eap_fast_key(ssl_ctx, conn, out, len)) {
os_free(out);
return NULL;
}
}
-void eap_fast_derive_eap_msk(const u8 *simck, u8 *msk)
+int eap_fast_derive_eap_msk(const u8 *simck, u8 *msk)
{
/*
* RFC 4851, Section 5.4: EAP Master Session Key Generation
* MSK = T-PRF(S-IMCK[j], "Session Key Generating Function", 64)
*/
- sha1_t_prf(simck, EAP_FAST_SIMCK_LEN,
- "Session Key Generating Function", (u8 *) "", 0,
- msk, EAP_FAST_KEY_LEN);
+ if (sha1_t_prf(simck, EAP_FAST_SIMCK_LEN,
+ "Session Key Generating Function", (u8 *) "", 0,
+ msk, EAP_FAST_KEY_LEN) < 0)
+ return -1;
wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (MSK)",
msk, EAP_FAST_KEY_LEN);
+ return 0;
}
-void eap_fast_derive_eap_emsk(const u8 *simck, u8 *emsk)
+int eap_fast_derive_eap_emsk(const u8 *simck, u8 *emsk)
{
/*
* RFC 4851, Section 5.4: EAP Master Session Key Genreration
* "Extended Session Key Generating Function", 64)
*/
- sha1_t_prf(simck, EAP_FAST_SIMCK_LEN,
- "Extended Session Key Generating Function", (u8 *) "", 0,
- emsk, EAP_EMSK_LEN);
+ if (sha1_t_prf(simck, EAP_FAST_SIMCK_LEN,
+ "Extended Session Key Generating Function", (u8 *) "", 0,
+ emsk, EAP_EMSK_LEN) < 0)
+ return -1;
wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (EMSK)",
emsk, EAP_EMSK_LEN);
+ return 0;
}
void eap_fast_derive_master_secret(const u8 *pac_key, const u8 *server_random,
const u8 *client_random, u8 *master_secret);
u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn,
- const char *label, size_t len);
-void eap_fast_derive_eap_msk(const u8 *simck, u8 *msk);
-void eap_fast_derive_eap_emsk(const u8 *simck, u8 *emsk);
+ size_t len);
+int eap_fast_derive_eap_msk(const u8 *simck, u8 *msk);
+int eap_fast_derive_eap_emsk(const u8 *simck, u8 *emsk);
int eap_fast_parse_tlv(struct eap_fast_tlv_parse *tlv,
int tlv_type, u8 *pos, size_t len);
n = (len + hashlen - 1) / hashlen;
for (i = 1; i <= n; i++) {
WPA_PUT_BE16(ibuf, i);
- hmac_sha256_vector(psk, 32, 2, addr, vlen, hash);
+ if (hmac_sha256_vector(psk, 32, 2, addr, vlen, hash))
+ return -1;
clen = left > hashlen ? hashlen : left;
os_memcpy(opos, hash, clen);
opos += clen;
break;
#ifdef EAP_GPSK_SHA256
case EAP_GPSK_CIPHER_SHA256:
- hmac_sha256(sk, sk_len, data, len, mic);
- ret = 0;
+ ret = hmac_sha256(sk, sk_len, data, len, mic);
break;
#endif /* EAP_GPSK_SHA256 */
default:
break;
}
+ if (ret)
+ wpa_printf(MSG_DEBUG, "EAP-GPSK: Could not compute MIC");
+
return ret;
}
left = output_len;
for (counter = 1; counter <= (u8) num_blocks; counter++) {
size_t clen = left > EAP_PAX_MAC_LEN ? EAP_PAX_MAC_LEN : left;
- hmac_sha1_vector(key, key_len, 3, addr, len, mac);
+ if (hmac_sha1_vector(key, key_len, 3, addr, len, mac) < 0)
+ return -1;
os_memcpy(pos, mac, clen);
pos += clen;
left -= clen;
len[2] = data3_len;
count = (data1 ? 1 : 0) + (data2 ? 1 : 0) + (data3 ? 1 : 0);
- hmac_sha1_vector(key, key_len, count, addr, len, hash);
+ if (hmac_sha1_vector(key, key_len, count, addr, len, hash) < 0)
+ return -1;
os_memcpy(mac, hash, EAP_PAX_MAC_LEN);
return 0;
case 26:
nid = NID_secp224r1;
break;
+#ifdef NID_brainpoolP224r1
+ case 27:
+ nid = NID_brainpoolP224r1;
+ break;
+#endif /* NID_brainpoolP224r1 */
+#ifdef NID_brainpoolP256r1
+ case 28:
+ nid = NID_brainpoolP256r1;
+ break;
+#endif /* NID_brainpoolP256r1 */
+#ifdef NID_brainpoolP384r1
+ case 29:
+ nid = NID_brainpoolP384r1;
+ break;
+#endif /* NID_brainpoolP384r1 */
+#ifdef NID_brainpoolP512r1
+ case 30:
+ nid = NID_brainpoolP512r1;
+ break;
+#endif /* NID_brainpoolP512r1 */
default:
wpa_printf(MSG_INFO, "EAP-pwd: unsupported group %d", num);
return -1;
attr->next_tmpid_len = len;
break;
case EAP_SAKE_AT_MSK_LIFE:
- wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_IV");
+ wpa_printf(MSG_DEBUG, "EAP-SAKE: Parse: AT_MSK_LIFE");
if (len != 4) {
wpa_printf(MSG_DEBUG, "EAP-SAKE: Invalid "
"AT_MSK_LIFE payload length %d", len);
case AUTH_HMAC_SHA1_96:
if (key_len != 20)
return -1;
- hmac_sha1(key, key_len, data, data_len, tmphash);
+ if (hmac_sha1(key, key_len, data, data_len, tmphash) < 0)
+ return -1;
os_memcpy(hash, tmphash, 12);
break;
case AUTH_HMAC_MD5_96:
if (key_len != 16)
return -1;
- hmac_md5(key, key_len, data, data_len, tmphash);
+ if (hmac_md5(key, key_len, data, data_len, tmphash) < 0)
+ return -1;
os_memcpy(hash, tmphash, 12);
break;
default:
{
switch (alg) {
case PRF_HMAC_SHA1:
- hmac_sha1_vector(key, key_len, num_elem, addr, len, hash);
- break;
+ return hmac_sha1_vector(key, key_len, num_elem, addr, len,
+ hash);
case PRF_HMAC_MD5:
- hmac_md5_vector(key, key_len, num_elem, addr, len, hash);
- break;
+ return hmac_md5_vector(key, key_len, num_elem, addr, len, hash);
default:
return -1;
}
-
- return 0;
}
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);
*/
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;
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);
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
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
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,
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);
}
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
#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;
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)
{
int eap_peer_aka_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA");
eap->get_identity = eap_aka_get_identity;
eap->get_emsk = eap_aka_get_emsk;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
int eap_peer_aka_prime_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME,
eap->get_identity = eap_aka_get_identity;
eap->get_emsk = eap_aka_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_AKA_PRIME */
* 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.
*/
*
* 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.
*
*/
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;
+
/**
- * If non-null, specifies a callback method that can be used to
- * override the validity of a peer certificate.
+ * server_cert_cb -- if non-null, specifies a callback method that can
+ * be used to override the validity of a peer (server/acceptor) certificate.
*/
int (*server_cert_cb)(int ok_so_far, X509* cert, void *ca_ctx);
void *server_cert_ctx;
/* DHComponent_P = Encr(key, y_p) */
rpos = wpabuf_put(resp, data->sess.dhcomp_len);
if (eap_eke_dhcomp(&data->sess, key, pub, rpos) < 0) {
+ wpabuf_free(resp);
wpa_printf(MSG_INFO, "EAP-EKE: Failed to build DHComponent_P");
os_memset(key, 0, sizeof(key));
return eap_eke_build_fail(data, ret, id,
int eap_peer_eke_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_EKE, "EKE");
eap->get_emsk = eap_eke_get_emsk;
eap->getSessionId = eap_eke_get_session_id;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
/*
* EAP peer method: EAP-FAST (RFC 4851)
- * 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.
int simck_idx;
struct wpabuf *pending_phase2_req;
+ struct wpabuf *pending_resp;
};
}
-static int eap_fast_parse_phase1(struct eap_fast_data *data,
- const char *phase1)
+static void eap_fast_parse_phase1(struct eap_fast_data *data,
+ const char *phase1)
{
const char *pos;
wpa_printf(MSG_DEBUG, "EAP-FAST: Using binary format for PAC "
"list");
}
-
- return 0;
}
data->fast_version = EAP_FAST_VERSION;
data->max_pac_list_len = 10;
- if (config->phase1 && eap_fast_parse_phase1(data, config->phase1) < 0) {
- eap_fast_deinit(sm, data);
- return NULL;
- }
+ if (config->phase1)
+ eap_fast_parse_phase1(data, config->phase1);
if (eap_peer_select_phase2_methods(config, "auth=",
&data->phase2_types,
os_memset(data->emsk, 0, EAP_EMSK_LEN);
os_free(data->session_id);
wpabuf_free(data->pending_phase2_req);
+ wpabuf_free(data->pending_resp);
os_free(data);
}
static int eap_fast_derive_msk(struct eap_fast_data *data)
{
- eap_fast_derive_eap_msk(data->simck, data->key_data);
- eap_fast_derive_eap_emsk(data->simck, data->emsk);
+ if (eap_fast_derive_eap_msk(data->simck, data->key_data) < 0 ||
+ eap_fast_derive_eap_emsk(data->simck, data->emsk) < 0)
+ return -1;
data->success = 1;
return 0;
}
* Extra key material after TLS key_block: session_key_seed[40]
*/
- sks = eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn, "key expansion",
+ sks = eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn,
EAP_FAST_SKS_LEN);
if (sks == NULL) {
wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive "
os_free(data->key_block_p);
data->key_block_p = (struct eap_fast_key_block_provisioning *)
eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn,
- "key expansion",
sizeof(*data->key_block_p));
if (data->key_block_p == NULL) {
wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive key block");
if (eap_fast_get_phase2_key(sm, data, isk, sizeof(isk)) < 0)
return -1;
wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: ISK[j]", isk, sizeof(isk));
- sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN,
- "Inner Methods Compound Keys",
- isk, sizeof(isk), imck, sizeof(imck));
+ if (sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN,
+ "Inner Methods Compound Keys",
+ isk, sizeof(isk), imck, sizeof(imck)) < 0)
+ return -1;
data->simck_idx++;
os_memcpy(data->simck, imck, EAP_FAST_SIMCK_LEN);
wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: S-IMCK[j]",
/* Parse TLVs from the decrypted Phase 2 data */
pos = wpabuf_mhead(decrypted);
end = pos + wpabuf_len(decrypted);
- while (pos + 4 < end) {
+ while (end - pos > 4) {
mandatory = pos[0] & 0x80;
tlv_type = WPA_GET_BE16(pos) & 0x3fff;
pos += 2;
static int eap_fast_set_provisioning_ciphers(struct eap_sm *sm,
struct eap_fast_data *data)
{
- u8 ciphers[5];
+ u8 ciphers[7];
int count = 0;
if (data->provisioning_allowed & EAP_FAST_PROV_UNAUTH) {
if (data->provisioning_allowed & EAP_FAST_PROV_AUTH) {
wpa_printf(MSG_DEBUG, "EAP-FAST: Enabling authenticated "
"provisioning TLS cipher suites");
+ ciphers[count++] = TLS_CIPHER_RSA_DHE_AES256_SHA;
ciphers[count++] = TLS_CIPHER_RSA_DHE_AES128_SHA;
+ ciphers[count++] = TLS_CIPHER_AES256_SHA;
ciphers[count++] = TLS_CIPHER_AES128_SHA;
ciphers[count++] = TLS_CIPHER_RC4_SHA;
}
res = 1;
}
} 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-FAST: 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-FAST: 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-FAST: Continuing to wait external server certificate validation");
+ return NULL;
+ }
+
/* Continue processing TLS handshake (phase 1). */
res = eap_peer_tls_process_helper(sm, &data->ssl,
EAP_TYPE_FAST,
return resp;
}
+ if (sm->waiting_ext_cert_check) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-FAST: 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 cipher[80];
wpa_printf(MSG_DEBUG,
data->key_block_p = NULL;
wpabuf_free(data->pending_phase2_req);
data->pending_phase2_req = NULL;
+ wpabuf_free(data->pending_resp);
+ data->pending_resp = NULL;
}
struct eap_fast_data *data = priv;
u8 *id;
- if (!data->success)
+ if (!data->success || !data->session_id)
return NULL;
id = os_malloc(data->id_len);
int eap_peer_fast_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_FAST, "FAST");
#endif
eap->get_emsk = eap_fast_get_emsk;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
}
if (pac) {
- err = "PAC block not terminated with END";
+ if (!err)
+ err = "PAC block not terminated with END";
eap_fast_free_pac(pac);
}
pos = pac->pac_info;
end = pos + pac->pac_info_len;
- while (pos + 4 < end) {
+ while (end - pos > 4) {
type = WPA_GET_BE16(pos);
pos += 2;
len = WPA_GET_BE16(pos);
while (pos < end) {
u16 val;
- if (end - pos < 2 + EAP_FAST_PAC_KEY_LEN + 2 + 2)
+ if (end - pos < 2 + EAP_FAST_PAC_KEY_LEN + 2 + 2) {
+ pac = NULL;
goto parse_fail;
+ }
pac = os_zalloc(sizeof(*pac));
if (pac == NULL)
int eap_peer_gpsk_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK");
eap->get_emsk = eap_gpsk_get_emsk;
eap->getSessionId = eap_gpsk_get_session_id;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
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");
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);
}
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 */
};
int eap_peer_ikev2_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_IKEV2,
eap->get_emsk = eap_ikev2_get_emsk;
eap->getSessionId = eap_ikev2_get_session_id;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
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");
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);
}
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");
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);
}
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
* 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);
}
/**
* 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;
}
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);
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,
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);
}
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");
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);
}
left -= 2;
wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(B, CID)",
pos, EAP_PAX_MAC_LEN);
- eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN,
- data->rand.r.y, EAP_PAX_RAND_LEN,
- (u8 *) data->cid, data->cid_len, NULL, 0, mac);
+ if (eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN,
+ data->rand.r.y, EAP_PAX_RAND_LEN,
+ (u8 *) data->cid, data->cid_len, NULL, 0, mac) < 0) {
+ wpa_printf(MSG_INFO,
+ "EAP-PAX: Could not derive MAC_CK(B, CID)");
+ ret->methodState = METHOD_DONE;
+ ret->decision = DECISION_FAIL;
+ return NULL;
+ }
+
if (os_memcmp_const(pos, mac, EAP_PAX_MAC_LEN) != 0) {
wpa_printf(MSG_INFO, "EAP-PAX: Invalid MAC_CK(B, CID) "
"received");
/* Optional ADE could be added here, if needed */
rpos = wpabuf_put(resp, EAP_PAX_ICV_LEN);
- eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN,
- wpabuf_head(resp), wpabuf_len(resp) - EAP_PAX_ICV_LEN,
- NULL, 0, NULL, 0, rpos);
+ if (eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN,
+ wpabuf_head(resp), wpabuf_len(resp) - EAP_PAX_ICV_LEN,
+ NULL, 0, NULL, 0, rpos) < 0) {
+ wpabuf_free(resp);
+ return NULL;
+ }
wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", rpos, EAP_PAX_ICV_LEN);
data->state = PAX_DONE;
return NULL;
*len = EAP_MSK_LEN;
- eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN,
- "Master Session Key", data->rand.e, 2 * EAP_PAX_RAND_LEN,
- EAP_MSK_LEN, key);
+ if (eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN,
+ "Master Session Key",
+ data->rand.e, 2 * EAP_PAX_RAND_LEN,
+ EAP_MSK_LEN, key) < 0) {
+ os_free(key);
+ return NULL;
+ }
return key;
}
return NULL;
*len = EAP_EMSK_LEN;
- eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN,
- "Extended Master Session Key",
- data->rand.e, 2 * EAP_PAX_RAND_LEN,
- EAP_EMSK_LEN, key);
+ if (eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN,
+ "Extended Master Session Key",
+ data->rand.e, 2 * EAP_PAX_RAND_LEN,
+ EAP_EMSK_LEN, key) < 0) {
+ os_free(key);
+ return NULL;
+ }
return key;
}
int eap_peer_pax_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_PAX, "PAX");
eap->get_emsk = eap_pax_get_emsk;
eap->getSessionId = eap_pax_get_session_id;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
/*
* 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.
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];
};
-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;
wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 2 enabled");
}
#endif /* EAP_TNC */
-
- return 0;
}
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,
eap_peap_free_key(data);
os_free(data->session_id);
wpabuf_free(data->pending_phase2_req);
+ wpabuf_free(data->pending_resp);
os_free(data);
}
{
u8 *tk;
u8 isk[32], imck[60];
+ int resumed;
/*
* Tunnel key (TK) is the first 60 octets of the key generated by
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",
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;
if (*resp == NULL) {
ret->methodState = METHOD_DONE;
ret->decision = DECISION_FAIL;
+ wpabuf_free(buf);
return -1;
}
wpabuf_put_buf(*resp, buf);
!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,
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,
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;
}
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");
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);
}
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");
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);
}
wpa_printf(MSG_INFO, "EAP-PWD (peer): element inversion fail");
goto fin;
}
- BN_clear_free(mask);
if (((x = BN_new()) == NULL) ||
((y = BN_new()) == NULL)) {
os_free(element);
BN_clear_free(x);
BN_clear_free(y);
+ BN_clear_free(mask);
BN_clear_free(cofactor);
EC_POINT_clear_free(K);
EC_POINT_clear_free(point);
wpabuf_put_data(data->outbuf, conf, SHA256_MAC_LEN);
fin:
- bin_clear_free(cruft, BN_num_bytes(data->grp->prime));
+ if (data->grp)
+ bin_clear_free(cruft, BN_num_bytes(data->grp->prime));
BN_clear_free(x);
BN_clear_free(y);
if (data->outbuf == NULL) {
/*
* buffer and ACK the fragment
*/
- if (EAP_PWD_GET_MORE_BIT(lm_exch)) {
+ if (EAP_PWD_GET_MORE_BIT(lm_exch) || data->in_frag_pos) {
data->in_frag_pos += len;
if (data->in_frag_pos > wpabuf_size(data->inbuf)) {
wpa_printf(MSG_INFO, "EAP-pwd: Buffer overflow attack "
return NULL;
}
wpabuf_put_data(data->inbuf, pos, len);
-
+ }
+ if (EAP_PWD_GET_MORE_BIT(lm_exch)) {
resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PWD,
EAP_PWD_HDR_SIZE,
EAP_CODE_RESPONSE, eap_get_id(reqData));
* we're buffering and this is the last fragment
*/
if (data->in_frag_pos) {
- wpabuf_put_data(data->inbuf, pos, len);
wpa_printf(MSG_DEBUG, "EAP-pwd: Last fragment, %d bytes",
(int) len);
- data->in_frag_pos += len;
pos = wpabuf_head_u8(data->inbuf);
len = data->in_frag_pos;
}
int eap_peer_pwd_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_PWD, "PWD");
eap->getSessionId = eap_pwd_get_session_id;
eap->get_emsk = eap_pwd_get_emsk;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
return NULL;
}
- eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p,
- data->serverid, data->serverid_len,
- data->peerid, data->peerid_len, 0,
- wpabuf_head(reqData), wpabuf_len(reqData),
- attr.mic_s, mic_s);
+ if (eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p,
+ data->serverid, data->serverid_len,
+ data->peerid, data->peerid_len, 0,
+ wpabuf_head(reqData), wpabuf_len(reqData),
+ attr.mic_s, mic_s)) {
+ wpa_printf(MSG_INFO, "EAP-SAKE: Failed to compute MIC");
+ eap_sake_state(data, FAILURE);
+ ret->methodState = METHOD_DONE;
+ ret->decision = DECISION_FAIL;
+ ret->allowNotifications = FALSE;
+ wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending Response/Auth-Reject");
+ return eap_sake_build_msg(data, id, 0,
+ EAP_SAKE_SUBTYPE_AUTH_REJECT);
+ }
if (os_memcmp_const(attr.mic_s, mic_s, EAP_SAKE_MIC_LEN) != 0) {
wpa_printf(MSG_INFO, "EAP-SAKE: Incorrect AT_MIC_S");
eap_sake_state(data, FAILURE);
int eap_peer_sake_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_SAKE, "SAKE");
eap->getSessionId = eap_sake_get_session_id;
eap->get_emsk = eap_sake_get_emsk;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
return eap_sim_ext_sim_req(sm, data);
}
+#ifdef PCSC_FUNCS
if (conf->pcsc) {
if (scard_gsm_auth(sm->scard_ctx, data->rand[0],
data->sres[0], data->kc[0]) ||
}
return 0;
}
+#endif /* PCSC_FUNCS */
#ifdef CONFIG_SIM_SIMULATOR
if (conf->password) {
if (random_get_bytes(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) {
wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data "
"for NONCE_MT");
- os_free(data);
+ eap_sim_deinit(sm, data);
return NULL;
}
data->num_id_req = 0;
int eap_peer_sim_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM");
eap->get_identity = eap_sim_get_identity;
eap->get_emsk = eap_sim_get_emsk;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
/*
* 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.
size_t id_len;
void *ssl_ctx;
u8 eap_type;
+ struct wpabuf *pending_resp;
};
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);
}
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)
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);
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;
}
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");
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);
}
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,
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 */
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,
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 */
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;
}
params->openssl_ciphers = config->openssl_ciphers;
+ sm->ext_cert_check = !!(params->flags & TLS_CONN_EXT_CERT_CHECK);
+
return 0;
}
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 "
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;
}
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;
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,
#include "common.h"
#include "eap_i.h"
+#include "eap_config.h"
#include "tncc.h"
static void * eap_tnc_init(struct eap_sm *sm)
{
struct eap_tnc_data *data;
+ struct eap_peer_config *config = eap_get_config(sm);
data = os_zalloc(sizeof(*data));
if (data == NULL)
return NULL;
data->state = WAIT_START;
- data->fragment_size = 1300;
+ if (config && config->fragment_size)
+ data->fragment_size = config->fragment_size;
+ else
+ data->fragment_size = 1300;
data->tncc = tncc_init();
if (data->tncc == NULL) {
os_free(data);
ret->decision = DECISION_UNCOND_SUCC;
ret->allowNotifications = TRUE;
- if (data->out_buf) {
- data->state = PROC_MSG;
- return eap_tnc_build_msg(data, ret, id);
- }
-
if (tncs_done) {
resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 1,
EAP_CODE_RESPONSE, eap_get_id(reqData));
int eap_peer_tnc_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_TNC, "TNC");
eap->deinit = eap_tnc_deinit;
eap->process = eap_tnc_process;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
/*
* 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.
void *phase2_priv;
int phase2_success;
int phase2_start;
+ EapDecision decision_succ;
enum phase2_types {
EAP_TTLS_PHASE2_EAP,
size_t id_len;
struct wpabuf *pending_phase2_req;
+ struct wpabuf *pending_resp;
int chbind_req_sent; /* channel binding request was sent */
int done_butfor_cb; /*we turned METHOD_DONE into METHOD_MAY_CONT to receive cb*/
- EapDecision cbDecision;
+ EapDecision cbDecision;
#ifdef EAP_TNC
int ready_for_tnc;
int tnc_started;
{
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));
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) {
eap_ttls_free_key(data);
os_free(data->session_id);
wpabuf_free(data->pending_phase2_req);
+ wpabuf_free(data->pending_resp);
os_free(data);
}
{
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);
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");
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) {
/*
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;
}
}
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;
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");
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);
}
int eap_peer_vendor_test_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_ID, EAP_VENDOR_TYPE,
eap->isKeyAvailable = eap_vendor_test_isKeyAvailable;
eap->getKey = eap_vendor_test_getKey;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
struct eap_wsc_data {
- enum { WAIT_START, MESG, FRAG_ACK, WAIT_FRAG_ACK, DONE, FAIL } state;
+ enum { WAIT_START, MESG, WAIT_FRAG_ACK, FAIL } state;
int registrar;
struct wpabuf *in_buf;
struct wpabuf *out_buf;
return "WAIT_START";
case MESG:
return "MESG";
- case FRAG_ACK:
- return "FRAG_ACK";
case WAIT_FRAG_ACK:
return "WAIT_FRAG_ACK";
- case DONE:
- return "DONE";
case FAIL:
return "FAIL";
default:
int eap_peer_wsc_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC,
eap->deinit = eap_wsc_deinit;
eap->process = eap_wsc_process;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}
t = (const struct ikev2_transform *) pos;
transform_len = WPA_GET_BE16(t->transform_length);
- if (transform_len < (int) sizeof(*t) || pos + transform_len > end) {
+ if (transform_len < (int) sizeof(*t) || transform_len > end - pos) {
wpa_printf(MSG_INFO, "IKEV2: Invalid transform length %d",
transform_len);
return -1;
ppos = (const u8 *) (p + 1);
pend = pos + proposal_len;
- if (ppos + p->spi_size > pend) {
+ if (p->spi_size > pend - ppos) {
wpa_printf(MSG_INFO, "IKEV2: Not enough room for SPI "
"in proposal");
return -1;
/* TNCC functions that IMCs can call */
-TNC_Result TNC_TNCC_ReportMessageTypes(
+static TNC_Result TNC_TNCC_ReportMessageTypes(
TNC_IMCID imcID,
TNC_MessageTypeList supportedTypes,
TNC_UInt32 typeCount)
}
-TNC_Result TNC_TNCC_SendMessage(
+static TNC_Result TNC_TNCC_SendMessage(
TNC_IMCID imcID,
TNC_ConnectionID connectionID,
TNC_BufferReference message,
}
-TNC_Result TNC_TNCC_RequestHandshakeRetry(
+static TNC_Result TNC_TNCC_RequestHandshakeRetry(
TNC_IMCID imcID,
TNC_ConnectionID connectionID,
TNC_RetryReason reason)
}
-TNC_Result TNC_9048_LogMessage(TNC_IMCID imcID, TNC_UInt32 severity,
- const char *message)
+static TNC_Result TNC_9048_LogMessage(TNC_IMCID imcID, TNC_UInt32 severity,
+ const char *message)
{
wpa_printf(MSG_DEBUG, "TNC: TNC_9048_LogMessage(imcID=%lu "
"severity==%lu message='%s')",
}
-TNC_Result TNC_9048_UserMessage(TNC_IMCID imcID, TNC_ConnectionID connectionID,
- const char *message)
+static TNC_Result TNC_9048_UserMessage(TNC_IMCID imcID,
+ TNC_ConnectionID connectionID,
+ const char *message)
{
wpa_printf(MSG_DEBUG, "TNC: TNC_9048_UserMessage(imcID=%lu "
"connectionID==%lu message='%s')",
}
-TNC_Result TNC_TNCC_BindFunction(
+static TNC_Result TNC_TNCC_BindFunction(
TNC_IMCID imcID,
char *functionName,
void **pOutfunctionPointer)
enum tncc_process_res res = TNCCS_PROCESS_OK_NO_RECOMMENDATION;
int recommendation_msg = 0;
+ wpa_hexdump_ascii(MSG_MSGDUMP, "TNC: Received IF-TNCCS message",
+ msg, len);
buf = dup_binstr(msg, len);
if (buf == NULL)
return TNCCS_PROCESS_ERROR;
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);
int eap_server_aka_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_AKA, "AKA");
eap->get_emsk = eap_aka_get_emsk;
eap->getSessionId = eap_aka_get_session_id;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}
int eap_server_aka_prime_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME,
eap->get_emsk = eap_aka_get_emsk;
eap->getSessionId = eap_aka_get_session_id;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
-
- return ret;
+ return eap_server_method_register(eap);
}
#endif /* EAP_SERVER_AKA_PRIME */
int eap_server_eke_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_EKE, "EKE");
eap->get_emsk = eap_eke_get_emsk;
eap->getSessionId = eap_eke_get_session_id;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}
buf, end - buf);
pos = buf;
- while (pos + 1 < end) {
- if (pos + 2 + pos[1] > end)
+ while (end - pos > 1) {
+ u8 id, elen;
+
+ id = *pos++;
+ elen = *pos++;
+ if (elen > end - pos)
break;
- switch (*pos) {
+ switch (id) {
case PAC_OPAQUE_TYPE_PAD:
goto done;
case PAC_OPAQUE_TYPE_KEY:
- if (pos[1] != EAP_FAST_PAC_KEY_LEN) {
- wpa_printf(MSG_DEBUG, "EAP-FAST: Invalid "
- "PAC-Key length %d", pos[1]);
+ if (elen != EAP_FAST_PAC_KEY_LEN) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-FAST: Invalid PAC-Key length %d",
+ elen);
os_free(buf);
return -1;
}
- pac_key = pos + 2;
+ pac_key = pos;
wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: PAC-Key from "
"decrypted PAC-Opaque",
pac_key, EAP_FAST_PAC_KEY_LEN);
break;
case PAC_OPAQUE_TYPE_LIFETIME:
- if (pos[1] != 4) {
+ if (elen != 4) {
wpa_printf(MSG_DEBUG, "EAP-FAST: Invalid "
"PAC-Key lifetime length %d",
- pos[1]);
+ elen);
os_free(buf);
return -1;
}
- lifetime = WPA_GET_BE32(pos + 2);
+ lifetime = WPA_GET_BE32(pos);
break;
case PAC_OPAQUE_TYPE_IDENTITY:
- identity = pos + 2;
- identity_len = pos[1];
+ identity = pos;
+ identity_len = elen;
break;
}
- pos += 2 + pos[1];
+ pos += elen;
}
done:
* Extra key material after TLS key_block: session_key_seed[40]
*/
- sks = eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn, "key expansion",
+ sks = eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn,
EAP_FAST_SKS_LEN);
if (sks == NULL) {
wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive "
os_free(data->key_block_p);
data->key_block_p = (struct eap_fast_key_block_provisioning *)
eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn,
- "key expansion",
sizeof(*data->key_block_p));
if (data->key_block_p == NULL) {
wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive key block");
static void * eap_fast_init(struct eap_sm *sm)
{
struct eap_fast_data *data;
- u8 ciphers[5] = {
+ u8 ciphers[7] = {
TLS_CIPHER_ANON_DH_AES128_SHA,
TLS_CIPHER_AES128_SHA,
TLS_CIPHER_RSA_DHE_AES128_SHA,
TLS_CIPHER_RC4_SHA,
+ TLS_CIPHER_RSA_DHE_AES256_SHA,
+ TLS_CIPHER_AES256_SHA,
TLS_CIPHER_NONE
};
pos = wpabuf_mhead(data);
end = pos + wpabuf_len(data);
- while (pos + 4 < end) {
+ while (end - pos > 4) {
mandatory = pos[0] & 0x80;
tlv_type = WPA_GET_BE16(pos) & 0x3fff;
pos += 2;
if (eapKeyData == NULL)
return NULL;
- eap_fast_derive_eap_msk(data->simck, eapKeyData);
+ if (eap_fast_derive_eap_msk(data->simck, eapKeyData) < 0) {
+ os_free(eapKeyData);
+ return NULL;
+ }
*len = EAP_FAST_KEY_LEN;
return eapKeyData;
if (eapKeyData == NULL)
return NULL;
- eap_fast_derive_eap_emsk(data->simck, eapKeyData);
+ if (eap_fast_derive_eap_emsk(data->simck, eapKeyData) < 0) {
+ os_free(eapKeyData);
+ return NULL;
+ }
*len = EAP_EMSK_LEN;
return eapKeyData;
int eap_server_fast_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_FAST, "FAST");
eap->isSuccess = eap_fast_isSuccess;
eap->getSessionId = eap_fast_get_session_id;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}
int eap_server_gpsk_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK");
eap->get_emsk = eap_gpsk_get_emsk;
eap->getSessionId = eap_gpsk_get_session_id;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}
int eap_server_gtc_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_GTC, "GTC");
eap->isDone = eap_gtc_isDone;
eap->isSuccess = eap_gtc_isSuccess;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}
int eap_server_identity_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_IDENTITY,
eap->isDone = eap_identity_isDone;
eap->isSuccess = eap_identity_isSuccess;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}
int eap_server_ikev2_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_IKEV2,
eap->get_emsk = eap_ikev2_get_emsk;
eap->getSessionId = eap_ikev2_get_session_id;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}
int eap_server_md5_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_MD5, "MD5");
eap->isDone = eap_md5_isDone;
eap->isSuccess = eap_md5_isSuccess;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}
* eap_server_method_free - Free EAP server method structure
* @method: Method structure allocated with eap_server_method_alloc()
*/
-void eap_server_method_free(struct eap_method *method)
+static void eap_server_method_free(struct eap_method *method)
{
os_free(method);
}
/**
* eap_server_method_register - Register an EAP server method
- * @method: EAP method to register
+ * @method: EAP method to register from eap_server_method_alloc()
* Returns: 0 on success, -1 on invalid method, or -2 if a matching EAP method
* has already been registered
*
* Each EAP server 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_server_method_register(struct eap_method *method)
{
struct eap_method *m, *last = NULL;
if (method == NULL || method->name == NULL ||
- method->version != EAP_SERVER_METHOD_INTERFACE_VERSION)
+ method->version != EAP_SERVER_METHOD_INTERFACE_VERSION) {
+ eap_server_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_server_method_free(method);
return -2;
+ }
last = m;
}
int eap_server_mschapv2_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2,
eap->getKey = eap_mschapv2_getKey;
eap->isSuccess = eap_mschapv2_isSuccess;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}
int eap_server_pax_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_PAX, "PAX");
eap->get_emsk = eap_pax_get_emsk;
eap->getSessionId = eap_pax_get_session_id;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}
return -1;
wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60);
+ if (tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) {
+ /* Fast-connect: IPMK|CMK = TK */
+ os_memcpy(data->ipmk, tk, 40);
+ wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK from TK",
+ data->ipmk, 40);
+ os_memcpy(data->cmk, tk + 40, 20);
+ wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK from TK",
+ data->cmk, 20);
+ os_free(tk);
+ return 0;
+ }
+
eap_peap_get_isk(data, isk, sizeof(isk));
wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk));
os_free(tk);
- /* TODO: fast-connect: IPMK|CMK = TK */
os_memcpy(data->ipmk, imck, 40);
wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40);
os_memcpy(data->cmk, imck + 40, 20);
wpa_printf(MSG_DEBUG,
"EAP-PEAP: Resuming previous session - skip Phase2");
- eap_peap_state(data, SUCCESS_REQ);
- tls_connection_set_success_data_resumed(data->ssl.conn);
+ eap_peap_req_success(sm, data);
+ if (data->state == SUCCESS_REQ)
+ tls_connection_set_success_data_resumed(data->ssl.conn);
}
int eap_server_peap_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP");
eap->isSuccess = eap_peap_isSuccess;
eap->getSessionId = eap_peap_get_session_id;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}
int eap_server_psk_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK");
eap->get_emsk = eap_psk_get_emsk;
eap->getSessionId = eap_psk_get_session_id;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}
return;
}
- /* an lfsr is good enough to generate unpredictable tokens */
- data->token = os_random();
+ if (os_get_random((u8 *) &data->token, sizeof(data->token)) < 0) {
+ wpabuf_free(data->outbuf);
+ data->outbuf = NULL;
+ eap_pwd_state(data, FAILURE);
+ return;
+ }
+
wpabuf_put_be16(data->outbuf, data->group_num);
wpabuf_put_u8(data->outbuf, EAP_PWD_DEFAULT_RAND_FUNC);
wpabuf_put_u8(data->outbuf, EAP_PWD_DEFAULT_PRF);
/*
* the first and all intermediate fragments have the M bit set
*/
- if (EAP_PWD_GET_MORE_BIT(lm_exch)) {
+ if (EAP_PWD_GET_MORE_BIT(lm_exch) || data->in_frag_pos) {
if ((data->in_frag_pos + len) > wpabuf_size(data->inbuf)) {
wpa_printf(MSG_DEBUG, "EAP-pwd: Buffer overflow "
"attack detected! (%d+%d > %d)",
}
wpabuf_put_data(data->inbuf, pos, len);
data->in_frag_pos += len;
+ }
+ if (EAP_PWD_GET_MORE_BIT(lm_exch)) {
wpa_printf(MSG_DEBUG, "EAP-pwd: Got a %d byte fragment",
(int) len);
return;
* buffering fragments so that's how we know it's the last)
*/
if (data->in_frag_pos) {
- wpabuf_put_data(data->inbuf, pos, len);
- data->in_frag_pos += len;
pos = wpabuf_head_u8(data->inbuf);
len = data->in_frag_pos;
wpa_printf(MSG_DEBUG, "EAP-pwd: Last fragment, %d bytes",
int eap_server_pwd_register(void)
{
struct eap_method *eap;
- int ret;
struct timeval tp;
struct timezone tz;
u32 sr;
eap->isSuccess = eap_pwd_is_success;
eap->getSessionId = eap_pwd_get_session_id;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}
int eap_server_sake_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_SAKE, "SAKE");
eap->get_emsk = eap_sake_get_emsk;
eap->getSessionId = eap_sake_get_session_id;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}
int eap_server_sim_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM");
eap->get_emsk = eap_sim_get_emsk;
eap->getSessionId = eap_sim_get_session_id;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}
int eap_server_tls_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS");
eap->get_emsk = eap_tls_get_emsk;
eap->getSessionId = eap_tls_get_session_id;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}
int eap_server_unauth_tls_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_UNAUTH_TLS,
eap->isSuccess = eap_tls_isSuccess;
eap->get_emsk = eap_tls_get_emsk;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}
#endif /* EAP_SERVER_UNAUTH_TLS */
int eap_server_wfa_unauth_tls_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_WFA_NEW,
eap->isSuccess = eap_tls_isSuccess;
eap->get_emsk = eap_tls_get_emsk;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}
#endif /* CONFIG_HS20 */
if (out == NULL)
return NULL;
- if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, 0,
- out, len)) {
+ if (tls_connection_export_key(sm->ssl_ctx, data->conn, label, out,
+ len)) {
os_free(out);
return NULL;
}
int eap_server_tnc_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_TNC, "TNC");
eap->isDone = eap_tnc_isDone;
eap->isSuccess = eap_tnc_isSuccess;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}
int eap_server_ttls_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_TTLS, "TTLS");
eap->getSessionId = eap_ttls_get_session_id;
eap->get_emsk = eap_ttls_get_emsk;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}
int eap_server_vendor_test_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_ID, EAP_VENDOR_TYPE,
eap->getKey = eap_vendor_test_getKey;
eap->isSuccess = eap_vendor_test_isSuccess;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}
int eap_server_wsc_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC,
eap->isSuccess = eap_wsc_isSuccess;
eap->getTimeout = eap_wsc_getTimeout;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}
struct eap_sim_pseudonym *pseudonyms;
struct eap_sim_reauth *reauths;
struct eap_sim_db_pending *pending;
+ unsigned int eap_sim_db_timeout;
#ifdef CONFIG_SQLITE
sqlite3 *sqlite_db;
char db_tmp_identity[100];
};
+static void eap_sim_db_del_timeout(void *eloop_ctx, void *user_ctx);
+static void eap_sim_db_query_timeout(void *eloop_ctx, void *user_ctx);
+
+
#ifdef CONFIG_SQLITE
static int db_table_exists(sqlite3 *db, const char *name)
}
+static void eap_sim_db_free_pending(struct eap_sim_db_data *data,
+ struct eap_sim_db_pending *entry)
+{
+ eloop_cancel_timeout(eap_sim_db_query_timeout, data, entry);
+ eloop_cancel_timeout(eap_sim_db_del_timeout, data, entry);
+ os_free(entry);
+}
+
+
+static void eap_sim_db_del_pending(struct eap_sim_db_data *data,
+ struct eap_sim_db_pending *entry)
+{
+ struct eap_sim_db_pending **pp = &data->pending;
+
+ while (*pp != NULL) {
+ if (*pp == entry) {
+ *pp = entry->next;
+ eap_sim_db_free_pending(data, entry);
+ return;
+ }
+ pp = &(*pp)->next;
+ }
+}
+
+
+static void eap_sim_db_del_timeout(void *eloop_ctx, void *user_ctx)
+{
+ struct eap_sim_db_data *data = eloop_ctx;
+ struct eap_sim_db_pending *entry = user_ctx;
+
+ wpa_printf(MSG_DEBUG, "EAP-SIM DB: Delete query timeout for %p", entry);
+ eap_sim_db_del_pending(data, entry);
+}
+
+
+static void eap_sim_db_query_timeout(void *eloop_ctx, void *user_ctx)
+{
+ struct eap_sim_db_data *data = eloop_ctx;
+ struct eap_sim_db_pending *entry = user_ctx;
+
+ /*
+ * Report failure and allow some time for EAP server to process it
+ * before deleting the query.
+ */
+ wpa_printf(MSG_DEBUG, "EAP-SIM DB: Query timeout for %p", entry);
+ entry->state = FAILURE;
+ data->get_complete_cb(data->ctx, entry->cb_session_ctx);
+ eloop_register_timeout(1, 0, eap_sim_db_del_timeout, data, entry);
+}
+
+
static void eap_sim_db_sim_resp_auth(struct eap_sim_db_data *data,
const char *imsi, char *buf)
{
parse_fail:
wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string");
- os_free(entry);
+ eap_sim_db_free_pending(data, entry);
}
parse_fail:
wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failed to parse response string");
- os_free(entry);
+ eap_sim_db_free_pending(data, entry);
}
/**
* eap_sim_db_init - Initialize EAP-SIM DB / authentication gateway interface
* @config: Configuration data (e.g., file name)
+ * @db_timeout: Database lookup timeout
* @get_complete_cb: Callback function for reporting availability of triplets
* @ctx: Context pointer for get_complete_cb
* Returns: Pointer to a private data structure or %NULL on failure
*/
struct eap_sim_db_data *
-eap_sim_db_init(const char *config,
+eap_sim_db_init(const char *config, unsigned int db_timeout,
void (*get_complete_cb)(void *ctx, void *session_ctx),
void *ctx)
{
data->sock = -1;
data->get_complete_cb = get_complete_cb;
data->ctx = ctx;
+ data->eap_sim_db_timeout = db_timeout;
data->fname = os_strdup(config);
if (data->fname == NULL)
goto fail;
while (pending) {
prev_pending = pending;
pending = pending->next;
- os_free(prev_pending);
+ eap_sim_db_free_pending(data, prev_pending);
}
os_free(data);
}
-static void eap_sim_db_expire_pending(struct eap_sim_db_data *data)
+static void eap_sim_db_expire_pending(struct eap_sim_db_data *data,
+ struct eap_sim_db_pending *entry)
{
- /* TODO: add limit for maximum length for pending list; remove latest
- * (i.e., last) entry from the list if the limit is reached; could also
- * use timeout to expire pending entries */
+ eloop_register_timeout(data->eap_sim_db_timeout, 0,
+ eap_sim_db_query_timeout, data, entry);
}
if (entry->state == FAILURE) {
wpa_printf(MSG_DEBUG, "EAP-SIM DB: Pending entry -> "
"failure");
- os_free(entry);
+ eap_sim_db_free_pending(data, entry);
return EAP_SIM_DB_FAILURE;
}
os_memcpy(sres, entry->u.sim.sres,
num_chal * EAP_SIM_SRES_LEN);
os_memcpy(kc, entry->u.sim.kc, num_chal * EAP_SIM_KC_LEN);
- os_free(entry);
+ eap_sim_db_free_pending(data, entry);
return num_chal;
}
entry->cb_session_ctx = cb_session_ctx;
entry->state = PENDING;
eap_sim_db_add_pending(data, entry);
- eap_sim_db_expire_pending(data);
+ eap_sim_db_expire_pending(data, entry);
+ wpa_printf(MSG_DEBUG, "EAP-SIM DB: Added query %p", entry);
return EAP_SIM_DB_PENDING;
}
entry = eap_sim_db_get_pending(data, imsi, 1);
if (entry) {
if (entry->state == FAILURE) {
- os_free(entry);
+ eap_sim_db_free_pending(data, entry);
wpa_printf(MSG_DEBUG, "EAP-SIM DB: Failure");
return EAP_SIM_DB_FAILURE;
}
os_memcpy(ck, entry->u.aka.ck, EAP_AKA_CK_LEN);
os_memcpy(res, entry->u.aka.res, EAP_AKA_RES_MAX_LEN);
*res_len = entry->u.aka.res_len;
- os_free(entry);
+ eap_sim_db_free_pending(data, entry);
return 0;
}
entry->cb_session_ctx = cb_session_ctx;
entry->state = PENDING;
eap_sim_db_add_pending(data, entry);
- eap_sim_db_expire_pending(data);
+ eap_sim_db_expire_pending(data, entry);
+ wpa_printf(MSG_DEBUG, "EAP-SIM DB: Added query %p", entry);
return EAP_SIM_DB_PENDING;
}
struct eap_sim_db_data;
struct eap_sim_db_data *
-eap_sim_db_init(const char *config,
+eap_sim_db_init(const char *config, unsigned int db_timeout,
void (*get_complete_cb)(void *ctx, void *session_ctx),
void *ctx);
t = (const struct ikev2_transform *) pos;
transform_len = WPA_GET_BE16(t->transform_length);
- if (transform_len < (int) sizeof(*t) || pos + transform_len > end) {
+ if (transform_len < (int) sizeof(*t) || transform_len > end - pos) {
wpa_printf(MSG_INFO, "IKEV2: Invalid transform length %d",
transform_len);
return -1;
p = (const struct ikev2_proposal *) pos;
proposal_len = WPA_GET_BE16(p->proposal_length);
- if (proposal_len < (int) sizeof(*p) || pos + proposal_len > end) {
+ if (proposal_len < (int) sizeof(*p) || proposal_len > end - pos) {
wpa_printf(MSG_INFO, "IKEV2: Invalid proposal length %d",
proposal_len);
return -1;
ppos = (const u8 *) (p + 1);
pend = pos + proposal_len;
- if (ppos + p->spi_size > pend) {
+ if (p->spi_size > pend - ppos) {
wpa_printf(MSG_INFO, "IKEV2: Not enough room for SPI "
"in proposal");
return -1;
/* TNCS functions that IMVs can call */
-TNC_Result TNC_TNCS_ReportMessageTypes(
+static TNC_Result TNC_TNCS_ReportMessageTypes(
TNC_IMVID imvID,
TNC_MessageTypeList supportedTypes,
TNC_UInt32 typeCount)
}
-TNC_Result TNC_TNCS_SendMessage(
+static TNC_Result TNC_TNCS_SendMessage(
TNC_IMVID imvID,
TNC_ConnectionID connectionID,
TNC_BufferReference message,
}
-TNC_Result TNC_TNCS_RequestHandshakeRetry(
+static TNC_Result TNC_TNCS_RequestHandshakeRetry(
TNC_IMVID imvID,
TNC_ConnectionID connectionID,
TNC_RetryReason reason)
}
-TNC_Result TNC_TNCS_ProvideRecommendation(
+static TNC_Result TNC_TNCS_ProvideRecommendation(
TNC_IMVID imvID,
TNC_ConnectionID connectionID,
TNC_IMV_Action_Recommendation recommendation,
}
-TNC_Result TNC_TNCS_GetAttribute(
+static TNC_Result TNC_TNCS_GetAttribute(
TNC_IMVID imvID,
TNC_ConnectionID connectionID,
TNC_AttributeID attribureID,
}
-TNC_Result TNC_TNCS_SetAttribute(
+static TNC_Result TNC_TNCS_SetAttribute(
TNC_IMVID imvID,
TNC_ConnectionID connectionID,
TNC_AttributeID attribureID,
}
-TNC_Result TNC_TNCS_BindFunction(
+static TNC_Result TNC_TNCS_BindFunction(
TNC_IMVID imvID,
char *functionName,
void **pOutFunctionPointer)
sm->radius_cui = wpabuf_alloc_copy(radius_cui,
os_strlen(radius_cui));
- sm->acct_multi_session_id_lo = eapol->acct_multi_session_id_lo++;
- if (eapol->acct_multi_session_id_lo == 0)
- eapol->acct_multi_session_id_hi++;
- sm->acct_multi_session_id_hi = eapol->acct_multi_session_id_hi;
+#ifndef CONFIG_NO_RADIUS
+ if (radius_gen_session_id((u8 *) &sm->acct_multi_session_id,
+ sizeof(sm->acct_multi_session_id)) < 0) {
+ eapol_auth_free(sm);
+ return NULL;
+ }
+#endif /* CONFIG_NO_RADIUS */
return sm;
}
eloop_cancel_timeout(eapol_sm_step_cb, sm, NULL);
if (sm->eap)
eap_server_sm_deinit(sm->eap);
+
+ wpabuf_free(sm->radius_cui);
+ os_free(sm->identity);
os_free(sm);
}
struct eapol_auth_cb *cb)
{
struct eapol_authenticator *eapol;
- struct os_time now;
eapol = os_zalloc(sizeof(*eapol));
if (eapol == NULL)
eapol->cb.erp_get_key = cb->erp_get_key;
eapol->cb.erp_add_key = cb->erp_add_key;
- /* Acct-Multi-Session-Id should be unique over reboots. If reliable
- * clock is not available, this could be replaced with reboot counter,
- * etc. */
- os_get_time(&now);
- eapol->acct_multi_session_id_hi = now.sec;
-
return eapol;
}
u8 *default_wep_key;
u8 default_wep_key_idx;
-
- u32 acct_multi_session_id_hi;
- u32 acct_multi_session_id_lo;
};
struct radius_class_data radius_class;
struct wpabuf *radius_cui; /* Chargeable-User-Identity */
- /* Keys for encrypting and signing EAPOL-Key frames */
- u8 *eapol_key_sign;
- size_t eapol_key_sign_len;
- u8 *eapol_key_crypt;
- size_t eapol_key_crypt_len;
-
struct eap_sm *eap;
Boolean initializing; /* in process of initializing state machines */
int remediation;
- u32 acct_multi_session_id_hi;
- u32 acct_multi_session_id_lo;
+ u64 acct_multi_session_id;
};
#endif /* EAPOL_AUTH_SM_I_H */
{
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;
+ }
}
#include "fst/fst_defs.h"
#include "fst/fst_ctrl_iface.h"
+static int fst_global_initialized = 0;
struct dl_list fst_global_ctrls_list;
dl_list_init(&fst_global_groups_list);
dl_list_init(&fst_global_ctrls_list);
fst_session_global_init();
+ fst_global_initialized = 1;
return 0;
}
struct fst_group *group;
struct fst_ctrl_handle *h;
+ if (!fst_global_initialized)
+ return;
+
fst_session_global_deinit();
while ((group = fst_first_group()) != NULL)
fst_group_delete(group);
struct fst_ctrl_handle,
global_ctrls_lentry)))
fst_global_del_ctrl(h);
+ fst_global_initialized = 0;
}
void fst_rx_action(struct fst_iface *iface, const struct ieee80211_mgmt *mgmt,
size_t len)
{
- if (fst_iface_is_connected(iface, mgmt->sa))
+ if (fst_iface_is_connected(iface, mgmt->sa, FALSE))
fst_session_on_action_rx(iface, mgmt, len);
else
wpa_printf(MSG_DEBUG,
static const char *session_event_names[] = {
- [EVENT_FST_ESTABLISHED] FST_PVAL_EVT_TYPE_ESTABLISHED,
- [EVENT_FST_SETUP] FST_PVAL_EVT_TYPE_SETUP,
- [EVENT_FST_SESSION_STATE_CHANGED] FST_PVAL_EVT_TYPE_SESSION_STATE,
+ [EVENT_FST_ESTABLISHED] = FST_PVAL_EVT_TYPE_ESTABLISHED,
+ [EVENT_FST_SETUP] = FST_PVAL_EVT_TYPE_SETUP,
+ [EVENT_FST_SESSION_STATE_CHANGED] = FST_PVAL_EVT_TYPE_SESSION_STATE,
};
static const char *reason_names[] = {
- [REASON_TEARDOWN] FST_CS_PVAL_REASON_TEARDOWN,
- [REASON_SETUP] FST_CS_PVAL_REASON_SETUP,
- [REASON_SWITCH] FST_CS_PVAL_REASON_SWITCH,
- [REASON_STT] FST_CS_PVAL_REASON_STT,
- [REASON_REJECT] FST_CS_PVAL_REASON_REJECT,
- [REASON_ERROR_PARAMS] FST_CS_PVAL_REASON_ERROR_PARAMS,
- [REASON_RESET] FST_CS_PVAL_REASON_RESET,
- [REASON_DETACH_IFACE] FST_CS_PVAL_REASON_DETACH_IFACE,
+ [REASON_TEARDOWN] = FST_CS_PVAL_REASON_TEARDOWN,
+ [REASON_SETUP] = FST_CS_PVAL_REASON_SETUP,
+ [REASON_SWITCH] = FST_CS_PVAL_REASON_SWITCH,
+ [REASON_STT] = FST_CS_PVAL_REASON_STT,
+ [REASON_REJECT] = FST_CS_PVAL_REASON_REJECT,
+ [REASON_ERROR_PARAMS] = FST_CS_PVAL_REASON_ERROR_PARAMS,
+ [REASON_RESET] = FST_CS_PVAL_REASON_RESET,
+ [REASON_DETACH_IFACE] = FST_CS_PVAL_REASON_DETACH_IFACE,
};
static const char *session_state_names[] = {
- [FST_SESSION_STATE_INITIAL] FST_CS_PVAL_STATE_INITIAL,
- [FST_SESSION_STATE_SETUP_COMPLETION] FST_CS_PVAL_STATE_SETUP_COMPLETION,
- [FST_SESSION_STATE_TRANSITION_DONE] FST_CS_PVAL_STATE_TRANSITION_DONE,
- [FST_SESSION_STATE_TRANSITION_CONFIRMED]
+ [FST_SESSION_STATE_INITIAL] = FST_CS_PVAL_STATE_INITIAL,
+ [FST_SESSION_STATE_SETUP_COMPLETION] =
+ FST_CS_PVAL_STATE_SETUP_COMPLETION,
+ [FST_SESSION_STATE_TRANSITION_DONE] = FST_CS_PVAL_STATE_TRANSITION_DONE,
+ [FST_SESSION_STATE_TRANSITION_CONFIRMED] =
FST_CS_PVAL_STATE_TRANSITION_CONFIRMED,
};
static const char * band_freq(enum mb_band_id band)
{
static const char *band_names[] = {
- [MB_BAND_ID_WIFI_2_4GHZ] "2.4GHZ",
- [MB_BAND_ID_WIFI_5GHZ] "5GHZ",
- [MB_BAND_ID_WIFI_60GHZ] "60GHZ",
+ [MB_BAND_ID_WIFI_2_4GHZ] = "2.4GHZ",
+ [MB_BAND_ID_WIFI_5GHZ] = "5GHZ",
+ [MB_BAND_ID_WIFI_60GHZ] = "60GHZ",
};
return fst_get_str_name(band, band_names, ARRAY_SIZE(band_names));
foreach_fst_group(g) {
foreach_fst_group_iface(g, f) {
- if (fst_iface_is_connected(f, addr)) {
+ if (fst_iface_is_connected(f, addr, TRUE)) {
ret += print_band(num++, f, addr,
buf + ret, buflen - ret);
}
struct session_transition_ie {
u8 element_id;
u8 length;
- u32 fsts_id;
+ le32 fsts_id;
u8 session_control;
u8 new_band_id;
u8 new_band_setup;
struct fst_setup_req {
u8 action;
u8 dialog_token;
- u32 llt;
+ le32 llt;
struct session_transition_ie stie;
/* Multi-band (optional) */
/* Wakeup Schedule (optional) */
struct fst_ack_req {
u8 action;
u8 dialog_token;
- u32 fsts_id;
+ le32 fsts_id;
} STRUCT_PACKED;
struct fst_ack_res {
u8 action;
u8 dialog_token;
- u32 fsts_id;
+ le32 fsts_id;
} STRUCT_PACKED;
struct fst_tear_down {
u8 action;
- u32 fsts_id;
+ le32 fsts_id;
} STRUCT_PACKED;
#endif /* IEEE_80211_FST_DEFS_H */
struct dl_list fst_global_groups_list;
-#ifndef HOSTAPD
-static Boolean fst_has_fst_peer(struct fst_iface *iface, Boolean *has_peer)
-{
- const u8 *bssid;
-
- bssid = fst_iface_get_bssid(iface);
- if (!bssid) {
- *has_peer = FALSE;
- return FALSE;
- }
-
- *has_peer = TRUE;
- return fst_iface_get_peer_mb_ie(iface, bssid) != NULL;
-}
-#endif /* HOSTAPD */
-
static void fst_dump_mb_ies(const char *group_id, const char *ifname,
struct wpabuf *mbies)
struct fst_iface *f;
unsigned int nof_mbies = 0;
unsigned int nof_ifaces_added = 0;
-#ifndef HOSTAPD
- Boolean has_peer;
- Boolean has_fst_peer;
-
- foreach_fst_group_iface(g, f) {
- has_fst_peer = fst_has_fst_peer(f, &has_peer);
- if (has_peer && !has_fst_peer)
- return NULL;
- }
-#endif /* HOSTAPD */
foreach_fst_group_iface(g, f) {
if (f == i)
}
-static struct fst_iface *
-fst_group_get_new_iface_by_mbie_and_band_id(struct fst_group *g,
- const u8 *mb_ies_buff,
- size_t mb_ies_size,
- u8 band_id,
- u8 *iface_peer_addr)
+static const u8 * fst_mbie_get_peer_addr_for_band(const struct wpabuf *mbies,
+ u8 band_id)
{
- while (mb_ies_size >= 2) {
- const struct multi_band_ie *mbie =
- (const struct multi_band_ie *) mb_ies_buff;
-
- if (mbie->eid != WLAN_EID_MULTI_BAND ||
- (size_t) 2 + mbie->len < sizeof(*mbie))
- break;
+ const u8 *p = wpabuf_head(mbies);
+ size_t s = wpabuf_len(mbies);
- if (mbie->band_id == band_id) {
- struct fst_iface *iface;
+ while (s >= 2) {
+ const struct multi_band_ie *mbie =
+ (const struct multi_band_ie *) p;
- foreach_fst_group_iface(g, iface) {
- const u8 *peer_addr =
- fst_mbie_get_peer_addr(mbie);
+ if (mbie->eid != WLAN_EID_MULTI_BAND) {
+ fst_printf(MSG_INFO, "unexpected eid %d", mbie->eid);
+ return NULL;
+ }
- if (peer_addr &&
- fst_iface_is_connected(iface, peer_addr) &&
- band_id == fst_iface_get_band_id(iface)) {
- os_memcpy(iface_peer_addr, peer_addr,
- ETH_ALEN);
- return iface;
- }
- }
- break;
+ if (mbie->len < sizeof(*mbie) - 2 || mbie->len > s - 2) {
+ fst_printf(MSG_INFO, "invalid mbie len %d",
+ mbie->len);
+ return NULL;
}
- mb_ies_buff += 2 + mbie->len;
- mb_ies_size -= 2 + mbie->len;
+ if (mbie->band_id == band_id)
+ return fst_mbie_get_peer_addr(mbie);
+
+ p += 2 + mbie->len;
+ s -= 2 + mbie->len;
}
+ fst_printf(MSG_INFO, "mbie doesn't contain band %d", band_id);
return NULL;
}
}
-static Boolean
-fst_group_does_iface_appear_in_other_mbies(struct fst_group *g,
- struct fst_iface *iface,
- struct fst_iface *other,
- u8 *peer_addr)
+/**
+ * fst_group_get_peer_other_connection_1 - Find peer's "other" connection
+ * (iface, MAC tuple) by using peer's MB IE on iface.
+ *
+ * @iface: iface on which FST Setup Request was received
+ * @peer_addr: Peer address on iface
+ * @band_id: "other" connection band id
+ * @other_peer_addr (out): Peer's MAC address on the "other" connection (on the
+ * "other" iface)
+ *
+ * This function parses peer's MB IE on iface. It looks for peer's MAC address
+ * on band_id (tmp_peer_addr). Next all interfaces are iterated to find an
+ * interface which correlates with band_id. If such interface is found, peer
+ * database is iterated to see if tmp_peer_addr is connected over it.
+ */
+static struct fst_iface *
+fst_group_get_peer_other_connection_1(struct fst_iface *iface,
+ const u8 *peer_addr, u8 band_id,
+ u8 *other_peer_addr)
{
- struct fst_get_peer_ctx *ctx;
- const u8 *addr;
- const u8 *iface_addr;
- enum mb_band_id iface_band_id;
+ const struct wpabuf *mbies;
+ struct fst_iface *other_iface;
+ const u8 *tmp_peer_addr;
- WPA_ASSERT(g == fst_iface_get_group(iface));
- WPA_ASSERT(g == fst_iface_get_group(other));
+ /* Get peer's MB IEs on iface */
+ mbies = fst_iface_get_peer_mb_ie(iface, peer_addr);
+ if (!mbies)
+ return NULL;
- iface_addr = fst_iface_get_addr(iface);
- iface_band_id = fst_iface_get_band_id(iface);
+ /* Get peer's MAC address on the "other" interface */
+ tmp_peer_addr = fst_mbie_get_peer_addr_for_band(mbies, band_id);
+ if (!tmp_peer_addr) {
+ fst_printf(MSG_INFO,
+ "couldn't extract other peer addr from mbies");
+ return NULL;
+ }
- addr = fst_iface_get_peer_first(other, &ctx, TRUE);
- for (; addr; addr = fst_iface_get_peer_next(other, &ctx, TRUE)) {
- const struct wpabuf *mbies;
- u8 other_iface_peer_addr[ETH_ALEN];
- struct fst_iface *other_new_iface;
+ fst_printf(MSG_DEBUG, "found other peer addr from mbies: " MACSTR,
+ MAC2STR(tmp_peer_addr));
- mbies = fst_iface_get_peer_mb_ie(other, addr);
- if (!mbies)
+ foreach_fst_group_iface(fst_iface_get_group(iface), other_iface) {
+ if (other_iface == iface ||
+ band_id != fst_iface_get_band_id(other_iface))
continue;
-
- other_new_iface = fst_group_get_new_iface_by_mbie_and_band_id(
- g, wpabuf_head(mbies), wpabuf_len(mbies),
- iface_band_id, other_iface_peer_addr);
- if (other_new_iface == iface &&
- os_memcmp(iface_addr, other_iface_peer_addr,
- ETH_ALEN) != 0) {
- os_memcpy(peer_addr, addr, ETH_ALEN);
- return TRUE;
+ if (fst_iface_is_connected(other_iface, tmp_peer_addr, FALSE)) {
+ os_memcpy(other_peer_addr, tmp_peer_addr, ETH_ALEN);
+ return other_iface;
}
}
- return FALSE;
+ return NULL;
}
-struct fst_iface *
-fst_group_find_new_iface_by_stie(struct fst_group *g,
- struct fst_iface *iface,
- const u8 *peer_addr,
- const struct session_transition_ie *stie,
- u8 *iface_peer_addr)
+/**
+ * fst_group_get_peer_other_connection_2 - Find peer's "other" connection
+ * (iface, MAC tuple) by using MB IEs of other peers.
+ *
+ * @iface: iface on which FST Setup Request was received
+ * @peer_addr: Peer address on iface
+ * @band_id: "other" connection band id
+ * @other_peer_addr (out): Peer's MAC address on the "other" connection (on the
+ * "other" iface)
+ *
+ * This function iterates all connection (other_iface, cur_peer_addr tuples).
+ * For each connection, MB IE (of cur_peer_addr on other_iface) is parsed and
+ * MAC address on iface's band_id is extracted (this_peer_addr).
+ * this_peer_addr is then compared to peer_addr. A match indicates we have
+ * found the "other" connection.
+ */
+static struct fst_iface *
+fst_group_get_peer_other_connection_2(struct fst_iface *iface,
+ const u8 *peer_addr, u8 band_id,
+ u8 *other_peer_addr)
{
- struct fst_iface *i;
+ u8 this_band_id = fst_iface_get_band_id(iface);
+ const u8 *cur_peer_addr, *this_peer_addr;
+ struct fst_get_peer_ctx *ctx;
+ struct fst_iface *other_iface;
+ const struct wpabuf *cur_mbie;
- foreach_fst_group_iface(g, i) {
- if (i == iface ||
- stie->new_band_id != fst_iface_get_band_id(i))
+ foreach_fst_group_iface(fst_iface_get_group(iface), other_iface) {
+ if (other_iface == iface ||
+ band_id != fst_iface_get_band_id(other_iface))
continue;
- if (fst_group_does_iface_appear_in_other_mbies(g, iface, i,
- iface_peer_addr))
- return i;
- break;
+ cur_peer_addr = fst_iface_get_peer_first(other_iface, &ctx,
+ TRUE);
+ for (; cur_peer_addr;
+ cur_peer_addr = fst_iface_get_peer_next(other_iface, &ctx,
+ TRUE)) {
+ cur_mbie = fst_iface_get_peer_mb_ie(other_iface,
+ cur_peer_addr);
+ if (!cur_mbie)
+ continue;
+ this_peer_addr = fst_mbie_get_peer_addr_for_band(
+ cur_mbie, this_band_id);
+ if (!this_peer_addr)
+ continue;
+ if (os_memcmp(this_peer_addr, peer_addr, ETH_ALEN) ==
+ 0) {
+ os_memcpy(other_peer_addr, cur_peer_addr,
+ ETH_ALEN);
+ return other_iface;
+ }
+ }
}
+
return NULL;
}
+/**
+ * fst_group_get_peer_other_connection - Find peer's "other" connection (iface,
+ * MAC tuple).
+ *
+ * @iface: iface on which FST Setup Request was received
+ * @peer_addr: Peer address on iface
+ * @band_id: "other" connection band id
+ * @other_peer_addr (out): Peer's MAC address on the "other" connection (on the
+ * "other" iface)
+ *
+ * This function is called upon receiving FST Setup Request from some peer who
+ * has peer_addr on iface. It searches for another connection of the same peer
+ * on different interface which correlates with band_id. MB IEs received from
+ * peer (on the two different interfaces) are used to identify same peer.
+ */
struct fst_iface *
-fst_group_get_new_iface_by_stie_and_mbie(
- struct fst_group *g, const u8 *mb_ies_buff, size_t mb_ies_size,
- const struct session_transition_ie *stie, u8 *iface_peer_addr)
+fst_group_get_peer_other_connection(struct fst_iface *iface,
+ const u8 *peer_addr, u8 band_id,
+ u8 *other_peer_addr)
{
- return fst_group_get_new_iface_by_mbie_and_band_id(
- g, mb_ies_buff, mb_ies_size, stie->new_band_id,
- iface_peer_addr);
+ struct fst_iface *other_iface;
+
+ fst_printf(MSG_DEBUG, "%s: %s:" MACSTR ", %d", __func__,
+ fst_iface_get_name(iface), MAC2STR(peer_addr), band_id);
+
+ /*
+ * Two search methods are used:
+ * 1. Use peer's MB IE on iface to extract peer's MAC address on
+ * "other" connection. Then check if such "other" connection exists.
+ * 2. Iterate peer database, examine each MB IE to see if it points to
+ * (iface, peer_addr) tuple
+ */
+
+ other_iface = fst_group_get_peer_other_connection_1(iface, peer_addr,
+ band_id,
+ other_peer_addr);
+ if (other_iface) {
+ fst_printf(MSG_DEBUG, "found by method #1. %s:" MACSTR,
+ fst_iface_get_name(other_iface),
+ MAC2STR(other_peer_addr));
+ return other_iface;
+ }
+
+ other_iface = fst_group_get_peer_other_connection_2(iface, peer_addr,
+ band_id,
+ other_peer_addr);
+ if (other_iface) {
+ fst_printf(MSG_DEBUG, "found by method #2. %s:" MACSTR,
+ fst_iface_get_name(other_iface),
+ MAC2STR(other_peer_addr));
+ return other_iface;
+ }
+
+ fst_printf(MSG_INFO, "%s: other connection not found", __func__);
+ return NULL;
}
struct fst_iface * fst_group_get_iface_by_name(struct fst_group *g,
const char *ifname);
struct fst_iface *
-fst_group_find_new_iface_by_stie(struct fst_group *g,
- struct fst_iface *iface,
- const u8 *peer_addr,
- const struct session_transition_ie *stie,
- u8 *iface_peer_addr);
-struct fst_iface *
-fst_group_get_new_iface_by_stie_and_mbie(
- struct fst_group *g, const u8 *mb_ies_buff, size_t mb_ies_size,
- const struct session_transition_ie *stie, u8 *iface_peer_addr);
+fst_group_get_peer_other_connection(struct fst_iface *iface,
+ const u8 *peer_addr, u8 band_id,
+ u8 *other_peer_addr);
u8 fst_group_assign_dialog_token(struct fst_group *g);
u32 fst_group_assign_fsts_id(struct fst_group *g);
}
-Boolean fst_iface_is_connected(struct fst_iface *iface, const u8 *addr)
+Boolean fst_iface_is_connected(struct fst_iface *iface, const u8 *addr,
+ Boolean mb_only)
{
struct fst_get_peer_ctx *ctx;
- const u8 *a = fst_iface_get_peer_first(iface, &ctx, TRUE);
+ const u8 *a = fst_iface_get_peer_first(iface, &ctx, mb_only);
- for (; a != NULL; a = fst_iface_get_peer_next(iface, &ctx, TRUE))
+ for (; a != NULL; a = fst_iface_get_peer_next(iface, &ctx, mb_only))
if (os_memcmp(addr, a, ETH_ALEN) == 0)
return TRUE;
return i->iface_obj.get_peer_next(i->iface_obj.ctx, ctx, mb_only);
}
-Boolean fst_iface_is_connected(struct fst_iface *iface, const u8 *addr);
+Boolean fst_iface_is_connected(struct fst_iface *iface, const u8 *addr,
+ Boolean mb_only);
void fst_iface_attach_mbie(struct fst_iface *i, struct wpabuf *mbie);
enum mb_band_id fst_iface_get_band_id(struct fst_iface *i);
#define FST_LLT_MS_DEFAULT 50
#define FST_ACTION_MAX_SUPPORTED FST_ACTION_ON_CHANNEL_TUNNEL
-const char * const fst_action_names[] = {
+static const char * const fst_action_names[] = {
[FST_ACTION_SETUP_REQUEST] = "Setup Request",
[FST_ACTION_SETUP_RESPONSE] = "Setup Response",
[FST_ACTION_TEAR_DOWN] = "Tear Down",
static void fst_session_stt_arm(struct fst_session *s)
{
- eloop_register_timeout(0, TU_TO_US(FST_DEFAULT_SESSION_TIMEOUT_TU),
+ /* Action frames sometimes get delayed. Use relaxed timeout (2*) */
+ eloop_register_timeout(0, 2 * TU_TO_US(FST_DEFAULT_SESSION_TIMEOUT_TU),
fst_session_timeout_handler, NULL, s);
s->stt_armed = TRUE;
}
struct fst_iface *new_iface = NULL;
struct fst_group *g;
u8 new_iface_peer_addr[ETH_ALEN];
- const struct wpabuf *peer_mbies;
size_t plen;
if (frame_len < IEEE80211_HDRLEN + 1 + sizeof(*req)) {
MAC2STR(mgmt->sa));
}
- peer_mbies = fst_iface_get_peer_mb_ie(iface, mgmt->sa);
- if (peer_mbies) {
- new_iface = fst_group_get_new_iface_by_stie_and_mbie(
- g, wpabuf_head(peer_mbies), wpabuf_len(peer_mbies),
- &req->stie, new_iface_peer_addr);
- if (new_iface)
- fst_printf_iface(iface, MSG_INFO,
- "FST Request: new iface (%s:" MACSTR
- ") found by MB IEs",
- fst_iface_get_name(new_iface),
- MAC2STR(new_iface_peer_addr));
- }
-
- if (!new_iface) {
- new_iface = fst_group_find_new_iface_by_stie(
- g, iface, mgmt->sa, &req->stie,
- new_iface_peer_addr);
- if (new_iface)
- fst_printf_iface(iface, MSG_INFO,
- "FST Request: new iface (%s:" MACSTR
- ") found by others",
- fst_iface_get_name(new_iface),
- MAC2STR(new_iface_peer_addr));
- }
-
+ new_iface = fst_group_get_peer_other_connection(iface, mgmt->sa,
+ req->stie.new_band_id,
+ new_iface_peer_addr);
if (!new_iface) {
fst_printf_iface(iface, MSG_WARNING,
"FST Request dropped: new iface not found");
return;
}
+ fst_printf_iface(iface, MSG_INFO,
+ "FST Request: new iface (%s:" MACSTR ") found",
+ fst_iface_get_name(new_iface),
+ MAC2STR(new_iface_peer_addr));
s = fst_find_session_in_progress(mgmt->sa, g);
if (s) {
* the initiator’s MAC address, in which case, the responder
* shall delete the received FST Setup Request.
*/
- if (os_memcmp(mgmt->da, mgmt->sa, ETH_ALEN) > 0) {
+ if (fst_session_is_ready_pending(s) &&
+ /* waiting for Setup Response */
+ os_memcmp(mgmt->da, mgmt->sa, ETH_ALEN) > 0) {
fst_printf_session(s, MSG_WARNING,
"FST Request dropped due to MAC comparison (our MAC is "
MACSTR ")",
return;
}
- if (!fst_session_is_ready_pending(s)) {
- fst_printf_session(s, MSG_WARNING,
- "FST Request from " MACSTR
- " dropped due to inappropriate state %s",
- MAC2STR(mgmt->da),
- fst_session_state_name(s->state));
- return;
- }
+ /*
+ * State is SETUP_COMPLETION (either in transition or not) or
+ * TRANSITION_DONE (in transition).
+ * Setup Request arriving in this state could mean:
+ * 1. peer sent it before receiving our Setup Request (race
+ * condition)
+ * 2. peer didn't receive our Setup Response. Peer is retrying
+ * after STT timeout
+ * 3. peer's FST state machines are out of sync due to some
+ * other reason
+ *
+ * We will reset our session and create a new one instead.
+ */
+ fst_printf_session(s, MSG_WARNING,
+ "resetting due to FST request");
/*
* If FST Setup Request arrived with the same FSTS ID as one we
- * initialized before, it means the other side either didn't
- * receive our FST Request or skipped it for some reason (for
- * example, due to numerical MAC comparison).
- *
- * In this case, there's no need to tear down the session.
+ * initialized before, there's no need to tear down the session.
* Moreover, as FSTS ID is the same, the other side will
* associate this tear down with the session it initiated that
* will break the sync.
"Skipping TearDown as the FST request has the same FSTS ID as initiated");
fst_session_set_state(s, FST_SESSION_STATE_INITIAL, &evext);
fst_session_stt_disarm(s);
- fst_printf_session(s, MSG_WARNING, "reset due to FST request");
}
s = fst_session_create(g);
enum hostapd_hw_mode hw_mode;
u8 channel;
union fst_session_state_switch_extra evext = {
- .to_initial = {0},
+ .to_initial = {
+ .reject_code = 0,
+ },
};
if (iface != s->data.old_iface) {
return -EINVAL;
}
- if (!fst_iface_is_connected(s->data.old_iface, s->data.old_peer_addr)) {
+ if (!fst_iface_is_connected(s->data.old_iface, s->data.old_peer_addr,
+ FALSE)) {
fst_printf_session(s, MSG_ERROR,
"The preset old peer address is not connected");
return -EINVAL;
}
- if (!fst_iface_is_connected(s->data.new_iface, s->data.new_peer_addr)) {
+ if (!fst_iface_is_connected(s->data.new_iface, s->data.new_peer_addr,
+ FALSE)) {
fst_printf_session(s, MSG_ERROR,
"The preset new peer address is not connected");
return -EINVAL;
return -EINVAL;
}
- if (!fst_iface_is_connected(s->data.old_iface, s->data.old_peer_addr)) {
+ if (!fst_iface_is_connected(s->data.old_iface,
+ s->data.old_peer_addr, FALSE)) {
fst_printf_session(s, MSG_ERROR,
"The preset peer address is not in the peer list");
return -EINVAL;
res.stie.length = sizeof(res.stie) - 2;
if (status_code == WLAN_STATUS_SUCCESS) {
- res.stie.fsts_id = s->data.fsts_id;
+ res.stie.fsts_id = host_to_le32(s->data.fsts_id);
res.stie.session_control = SESSION_CONTROL(SESSION_TYPE_BSS, 0);
fst_iface_get_channel_info(s->data.new_iface, &hw_mode,
res.stie.length = sizeof(res.stie) - 2;
if (res.status_code == WLAN_STATUS_SUCCESS) {
- res.stie.fsts_id = fsts_id;
+ res.stie.fsts_id = host_to_le32(fsts_id);
res.stie.session_control = SESSION_CONTROL(SESSION_TYPE_BSS, 0);
fst_iface_get_channel_info(s.data.new_iface, &hw_mode,
os_memset(&req, 0, sizeof(req));
req.action = FST_ACTION_ACK_REQUEST;
req.dialog_token = g->dialog_token;
- req.fsts_id = fsts_id;
+ req.fsts_id = host_to_le32(fsts_id);
return fst_session_send_action(&s, FALSE, &req, sizeof(req), NULL);
}
os_memset(&res, 0, sizeof(res));
res.action = FST_ACTION_ACK_RESPONSE;
res.dialog_token = g->dialog_token;
- res.fsts_id = fsts_id;
+ res.fsts_id = host_to_le32(fsts_id);
return fst_session_send_action(&s, FALSE, &res, sizeof(res), NULL);
}
os_memset(&td, 0, sizeof(td));
td.action = FST_ACTION_TEAR_DOWN;
- td.fsts_id = fsts_id;
+ td.fsts_id = host_to_le32(fsts_id);
return fst_session_send_action(&s, TRUE, &td, sizeof(td), NULL);
}
int l2_hdr; /* whether to include layer 2 (Ethernet) header data
* buffers */
+#ifndef CONFIG_NO_LINUX_PACKET_SOCKET_WAR
/* For working around Linux packet socket behavior and regression. */
int fd_br_rx;
- int last_from_br;
+ int last_from_br, last_from_br_prev;
u8 last_hash[SHA1_MAC_LEN];
- unsigned int num_rx, num_rx_br;
+ u8 last_hash_prev[SHA1_MAC_LEN];
+ unsigned int num_rx_br;
+#endif /* CONFIG_NO_LINUX_PACKET_SOCKET_WAR */
};
/* Generated by 'sudo tcpdump -s 3000 -dd greater 278 and ip and udp and
struct sockaddr_ll ll;
socklen_t fromlen;
- l2->num_rx++;
os_memset(&ll, 0, sizeof(ll));
fromlen = sizeof(ll);
res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &ll,
wpa_printf(MSG_DEBUG, "%s: src=" MACSTR " len=%d",
__func__, MAC2STR(ll.sll_addr), (int) res);
+#ifndef CONFIG_NO_LINUX_PACKET_SOCKET_WAR
if (l2->fd_br_rx >= 0) {
u8 hash[SHA1_MAC_LEN];
const u8 *addr[1];
__func__);
return;
}
+ if (l2->last_from_br_prev &&
+ os_memcmp(hash, l2->last_hash_prev, SHA1_MAC_LEN) == 0) {
+ wpa_printf(MSG_DEBUG, "%s: Drop duplicate RX(prev)",
+ __func__);
+ return;
+ }
+ os_memcpy(l2->last_hash_prev, l2->last_hash, SHA1_MAC_LEN);
+ l2->last_from_br_prev = l2->last_from_br;
os_memcpy(l2->last_hash, hash, SHA1_MAC_LEN);
}
l2->last_from_br = 0;
+#endif /* CONFIG_NO_LINUX_PACKET_SOCKET_WAR */
l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res);
}
+#ifndef CONFIG_NO_LINUX_PACKET_SOCKET_WAR
static void l2_packet_receive_br(int sock, void *eloop_ctx, void *sock_ctx)
{
struct l2_packet_data *l2 = eloop_ctx;
wpa_printf(MSG_DEBUG, "%s: src=" MACSTR " len=%d",
__func__, MAC2STR(ll.sll_addr), (int) res);
+ if (os_memcmp(ll.sll_addr, l2->own_addr, ETH_ALEN) == 0) {
+ wpa_printf(MSG_DEBUG, "%s: Drop RX of own frame", __func__);
+ return;
+ }
+
addr[0] = buf;
len[0] = res;
sha1_vector(1, addr, len, hash);
wpa_printf(MSG_DEBUG, "%s: Drop duplicate RX", __func__);
return;
}
+ if (!l2->last_from_br_prev &&
+ os_memcmp(hash, l2->last_hash_prev, SHA1_MAC_LEN) == 0) {
+ wpa_printf(MSG_DEBUG, "%s: Drop duplicate RX(prev)", __func__);
+ return;
+ }
+ os_memcpy(l2->last_hash_prev, l2->last_hash, SHA1_MAC_LEN);
+ l2->last_from_br_prev = l2->last_from_br;
l2->last_from_br = 1;
os_memcpy(l2->last_hash, hash, SHA1_MAC_LEN);
l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res);
}
+#endif /* CONFIG_NO_LINUX_PACKET_SOCKET_WAR */
struct l2_packet_data * l2_packet_init(
l2->rx_callback = rx_callback;
l2->rx_callback_ctx = rx_callback_ctx;
l2->l2_hdr = l2_hdr;
+#ifndef CONFIG_NO_LINUX_PACKET_SOCKET_WAR
l2->fd_br_rx = -1;
+#endif /* CONFIG_NO_LINUX_PACKET_SOCKET_WAR */
l2->fd = socket(PF_PACKET, l2_hdr ? SOCK_RAW : SOCK_DGRAM,
htons(protocol));
void *rx_callback_ctx, int l2_hdr)
{
struct l2_packet_data *l2;
+#ifndef CONFIG_NO_LINUX_PACKET_SOCKET_WAR
struct sock_filter ethertype_sock_filter_insns[] = {
/* Load ethertype */
BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 2 * ETH_ALEN),
.filter = ethertype_sock_filter_insns,
};
struct sockaddr_ll ll;
+#endif /* CONFIG_NO_LINUX_PACKET_SOCKET_WAR */
l2 = l2_packet_init(br_ifname, own_addr, protocol, rx_callback,
rx_callback_ctx, l2_hdr);
if (!l2)
return NULL;
+#ifndef CONFIG_NO_LINUX_PACKET_SOCKET_WAR
/*
* The Linux packet socket behavior has changed over the years and there
* is an inconvenient regression in it that breaks RX for a specific
}
eloop_register_read_sock(l2->fd_br_rx, l2_packet_receive_br, l2, NULL);
+#endif /* CONFIG_NO_LINUX_PACKET_SOCKET_WAR */
return l2;
}
close(l2->fd);
}
+#ifndef CONFIG_NO_LINUX_PACKET_SOCKET_WAR
if (l2->fd_br_rx >= 0) {
eloop_unregister_read_sock(l2->fd_br_rx);
close(l2->fd_br_rx);
}
+#endif /* CONFIG_NO_LINUX_PACKET_SOCKET_WAR */
os_free(l2);
}
}
+struct l2_packet_data * l2_packet_init_bridge(
+ const char *br_ifname, const char *ifname, const u8 *own_addr,
+ unsigned short protocol,
+ void (*rx_callback)(void *ctx, const u8 *src_addr,
+ const u8 *buf, size_t len),
+ void *rx_callback_ctx, int l2_hdr)
+{
+ return l2_packet_init(br_ifname, own_addr, protocol, rx_callback,
+ rx_callback_ctx, l2_hdr);
+}
+
+
void l2_packet_deinit(struct l2_packet_data *l2)
{
if (l2 == NULL)
#include "common.h"
#include "eloop.h"
+#include "common/defs.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "common/wpa_ctrl.h"
static void p2p_copy_client_info(struct p2p_device *dev,
struct p2p_client_info *cli)
{
- os_memcpy(dev->info.device_name, cli->dev_name, cli->dev_name_len);
- dev->info.device_name[cli->dev_name_len] = '\0';
+ p2p_copy_filter_devname(dev->info.device_name,
+ sizeof(dev->info.device_name),
+ cli->dev_name, cli->dev_name_len);
dev->info.dev_capab = cli->dev_capab;
dev->info.config_methods = cli->config_methods;
os_memcpy(dev->info.pri_dev_type, cli->pri_dev_type, 8);
end = ies + ies_len;
- for (pos = ies; pos + 1 < end; pos += len) {
+ for (pos = ies; end - pos > 1; pos += len) {
id = *pos++;
len = *pos++;
- if (pos + len > end)
+ if (len > end - pos)
break;
if (id != WLAN_EID_VENDOR_SPECIFIC || len < 3)
dev->oper_ssid_len = msg.ssid[1];
}
- if (msg.adv_service_instance && msg.adv_service_instance_len) {
- wpabuf_free(dev->info.p2ps_instance);
+ wpabuf_free(dev->info.p2ps_instance);
+ dev->info.p2ps_instance = NULL;
+ if (msg.adv_service_instance && msg.adv_service_instance_len)
dev->info.p2ps_instance = wpabuf_alloc_copy(
msg.adv_service_instance, msg.adv_service_instance_len);
- }
if (freq >= 2412 && freq <= 2484 && msg.ds_params &&
*msg.ds_params >= 1 && *msg.ds_params <= 14) {
p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
p2p_clear_timeout(p2p);
+ if (p2p->pending_listen_freq) {
+ p2p_dbg(p2p, "Clear pending_listen_freq for p2p_find");
+ p2p->pending_listen_freq = 0;
+ }
p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
p2p->find_type = type;
p2p_device_clear_reported(p2p);
+ os_memset(p2p->sd_query_no_ack, 0, ETH_ALEN);
p2p_set_state(p2p, P2P_SEARCH);
p2p->search_delay = search_delay;
p2p->in_search_delay = 0;
/**
- * p2p_prepare_channel - Select operating channel for GO Negotiation
+ * p2p_prepare_channel - Select operating channel for GO Negotiation or P2PS PD
* @p2p: P2P module context from p2p_init()
* @dev: Selected peer device
* @force_freq: Forced frequency in MHz or 0 if not forced
* Returns: 0 on success, -1 on failure (channel not supported for P2P)
*
* This function is used to do initial operating channel selection for GO
- * Negotiation prior to having received peer information. The selected channel
- * may be further optimized in p2p_reselect_channel() once the peer information
- * is available.
+ * Negotiation prior to having received peer information or for P2PS PD
+ * signalling. The selected channel may be further optimized in
+ * p2p_reselect_channel() once the peer information is available.
*/
int p2p_prepare_channel(struct p2p_data *p2p, struct p2p_device *dev,
unsigned int force_freq, unsigned int pref_freq, int go)
dev = p2p_get_device(p2p, addr);
if (dev) {
- if (dev->country[0] == 0 && msg.listen_channel)
- os_memcpy(dev->country, msg.listen_channel, 3);
+ if (msg.listen_channel) {
+ int freq;
+
+ if (dev->country[0] == 0)
+ os_memcpy(dev->country, msg.listen_channel, 3);
+
+ freq = p2p_channel_to_freq(msg.listen_channel[3],
+ msg.listen_channel[4]);
+
+ if (freq > 0 && dev->listen_freq != freq) {
+ p2p_dbg(p2p,
+ "Updated peer " MACSTR " Listen channel (Probe Request): %d -> %d MHz",
+ MAC2STR(addr), dev->listen_freq, freq);
+ dev->listen_freq = freq;
+ }
+ }
+
os_get_reltime(&dev->last_seen);
p2p_parse_free(&msg);
return; /* already known */
return buf;
}
+static int p2p_build_probe_resp_buf(struct p2p_data *p2p, struct wpabuf *buf,
+ struct wpabuf *ies,
+ const u8 *addr, int rx_freq)
+{
+ struct ieee80211_mgmt *resp;
+ u8 channel, op_class;
+
+ resp = wpabuf_put(buf, offsetof(struct ieee80211_mgmt,
+ u.probe_resp.variable));
+
+ resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
+ (WLAN_FC_STYPE_PROBE_RESP << 4));
+ os_memcpy(resp->da, addr, ETH_ALEN);
+ os_memcpy(resp->sa, p2p->cfg->dev_addr, ETH_ALEN);
+ os_memcpy(resp->bssid, p2p->cfg->dev_addr, ETH_ALEN);
+ resp->u.probe_resp.beacon_int = host_to_le16(100);
+ /* hardware or low-level driver will setup seq_ctrl and timestamp */
+ resp->u.probe_resp.capab_info =
+ host_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE |
+ WLAN_CAPABILITY_PRIVACY |
+ WLAN_CAPABILITY_SHORT_SLOT_TIME);
+
+ wpabuf_put_u8(buf, WLAN_EID_SSID);
+ wpabuf_put_u8(buf, P2P_WILDCARD_SSID_LEN);
+ wpabuf_put_data(buf, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
+
+ wpabuf_put_u8(buf, WLAN_EID_SUPP_RATES);
+ wpabuf_put_u8(buf, 8);
+ wpabuf_put_u8(buf, (60 / 5) | 0x80);
+ wpabuf_put_u8(buf, 90 / 5);
+ wpabuf_put_u8(buf, (120 / 5) | 0x80);
+ wpabuf_put_u8(buf, 180 / 5);
+ wpabuf_put_u8(buf, (240 / 5) | 0x80);
+ wpabuf_put_u8(buf, 360 / 5);
+ wpabuf_put_u8(buf, 480 / 5);
+ wpabuf_put_u8(buf, 540 / 5);
+
+ if (!rx_freq) {
+ channel = p2p->cfg->channel;
+ } else if (p2p_freq_to_channel(rx_freq, &op_class, &channel)) {
+ p2p_err(p2p, "Failed to convert freq to channel");
+ return -1;
+ }
+
+ wpabuf_put_u8(buf, WLAN_EID_DS_PARAMS);
+ wpabuf_put_u8(buf, 1);
+ wpabuf_put_u8(buf, channel);
+
+ wpabuf_put_buf(buf, ies);
+
+ return 0;
+}
static int p2p_service_find_asp(struct p2p_data *p2p, const u8 *hash)
{
{
struct ieee802_11_elems elems;
struct wpabuf *buf;
- struct ieee80211_mgmt *resp;
struct p2p_message msg;
struct wpabuf *ies;
- u8 channel, op_class;
if (ieee802_11_parse_elems((u8 *) ie, ie_len, &elems, 0) ==
ParseFailed) {
return P2P_PREQ_NOT_PROCESSED;
}
- resp = wpabuf_put(buf, offsetof(struct ieee80211_mgmt,
- u.probe_resp.variable));
-
- resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
- (WLAN_FC_STYPE_PROBE_RESP << 4));
- os_memcpy(resp->da, addr, ETH_ALEN);
- os_memcpy(resp->sa, p2p->cfg->dev_addr, ETH_ALEN);
- os_memcpy(resp->bssid, p2p->cfg->dev_addr, ETH_ALEN);
- resp->u.probe_resp.beacon_int = host_to_le16(100);
- /* hardware or low-level driver will setup seq_ctrl and timestamp */
- resp->u.probe_resp.capab_info =
- host_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE |
- WLAN_CAPABILITY_PRIVACY |
- WLAN_CAPABILITY_SHORT_SLOT_TIME);
-
- wpabuf_put_u8(buf, WLAN_EID_SSID);
- wpabuf_put_u8(buf, P2P_WILDCARD_SSID_LEN);
- wpabuf_put_data(buf, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
-
- wpabuf_put_u8(buf, WLAN_EID_SUPP_RATES);
- wpabuf_put_u8(buf, 8);
- wpabuf_put_u8(buf, (60 / 5) | 0x80);
- wpabuf_put_u8(buf, 90 / 5);
- wpabuf_put_u8(buf, (120 / 5) | 0x80);
- wpabuf_put_u8(buf, 180 / 5);
- wpabuf_put_u8(buf, (240 / 5) | 0x80);
- wpabuf_put_u8(buf, 360 / 5);
- wpabuf_put_u8(buf, 480 / 5);
- wpabuf_put_u8(buf, 540 / 5);
-
- if (!rx_freq) {
- channel = p2p->cfg->channel;
- } else if (p2p_freq_to_channel(rx_freq, &op_class, &channel)) {
+ if (p2p_build_probe_resp_buf(p2p, buf, ies, addr, rx_freq)) {
wpabuf_free(ies);
wpabuf_free(buf);
return P2P_PREQ_NOT_PROCESSED;
}
- wpabuf_put_u8(buf, WLAN_EID_DS_PARAMS);
- wpabuf_put_u8(buf, 1);
- wpabuf_put_u8(buf, channel);
-
- wpabuf_put_buf(buf, ies);
wpabuf_free(ies);
p2p->cfg->send_probe_resp(p2p->cfg->cb_ctx, buf, rx_freq);
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)
{
enum p2p_probe_req_status res;
p2p_add_dev_from_probe_req(p2p, addr, ie, ie_len);
+ if (p2p_lo_started) {
+ p2p_dbg(p2p,
+ "Probe Response is offloaded, do not reply Probe Request");
+ return P2P_PREQ_PROCESSED;
+ }
+
res = p2p_reply_probe(p2p, addr, dst, bssid, ie, ie_len, rx_freq);
if (res != P2P_PREQ_PROCESSED && res != P2P_PREQ_NOT_PROCESSED)
return res;
wpabuf_free(p2p->wfd_coupled_sink_info);
#endif /* CONFIG_WIFI_DISPLAY */
- eloop_cancel_timeout(p2p_ext_listen_timeout, p2p, NULL);
eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
eloop_cancel_timeout(p2p_go_neg_start, p2p, NULL);
eloop_cancel_timeout(p2p_go_neg_wait_timeout, p2p, NULL);
os_free(p2p->groups);
p2ps_prov_free(p2p);
wpabuf_free(p2p->sd_resp);
- os_free(p2p->after_scan_tx);
p2p_remove_wps_vendor_extensions(p2p);
os_free(p2p->no_go_freq.range);
p2p_service_flush_asp(p2p);
void p2p_flush(struct p2p_data *p2p)
{
struct p2p_device *dev, *prev;
+
+ p2p_ext_listen(p2p, 0, 0);
p2p_stop_find(p2p);
dl_list_for_each_safe(dev, prev, &p2p->devices, struct p2p_device,
list) {
static int p2p_pre_find_operation(struct p2p_data *p2p, struct p2p_device *dev)
{
+ int res;
+
if (dev->sd_pending_bcast_queries == 0) {
/* Initialize with total number of registered broadcast
* SD queries. */
dev->sd_pending_bcast_queries = p2p->num_p2p_sd_queries;
}
- if (p2p_start_sd(p2p, dev) == 0)
+ res = p2p_start_sd(p2p, dev);
+ if (res == -2)
+ return -2;
+ if (res == 0)
return 1;
if (dev->req_config_methods &&
void p2p_continue_find(struct p2p_data *p2p)
{
struct p2p_device *dev;
- int found;
+ int found, res;
p2p_set_state(p2p, P2P_SEARCH);
}
if (!found)
continue;
- if (p2p_pre_find_operation(p2p, dev) > 0) {
+ res = p2p_pre_find_operation(p2p, dev);
+ if (res > 0) {
p2p->last_p2p_find_oper = dev;
return;
}
+ if (res == -2)
+ goto skip_sd;
}
/*
* iteration device.
*/
dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
- if (p2p_pre_find_operation(p2p, dev) > 0) {
+ res = p2p_pre_find_operation(p2p, dev);
+ if (res > 0) {
p2p->last_p2p_find_oper = dev;
return;
}
+ if (res == -2)
+ goto skip_sd;
if (dev == p2p->last_p2p_find_oper)
break;
}
+skip_sd:
+ os_memset(p2p->sd_query_no_ack, 0, ETH_ALEN);
p2p_listen_in_find(p2p, 1);
}
p2p->pending_action_state = P2P_NO_PENDING_ACTION;
if (!success) {
- if (p2p->sd_peer)
+ if (p2p->sd_peer) {
+ if (is_zero_ether_addr(p2p->sd_query_no_ack)) {
+ os_memcpy(p2p->sd_query_no_ack,
+ p2p->sd_peer->info.p2p_device_addr,
+ ETH_ALEN);
+ p2p_dbg(p2p,
+ "First SD Query no-ACK in this search iteration: "
+ MACSTR, MAC2STR(p2p->sd_query_no_ack));
+ }
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
+ }
p2p->sd_peer = NULL;
if (p2p->state != P2P_IDLE)
p2p_continue_find(p2p);
}
/*
+ * If after PD Request the peer doesn't expect to receive PD Response
+ * the PD Request ACK indicates a completion of the current PD. This
+ * happens only on the advertiser side sending the follow-on PD Request
+ * with the status different than 12 (Success: accepted by user).
+ */
+ if (p2p->p2ps_prov && !p2p->p2ps_prov->pd_seeker &&
+ p2p->p2ps_prov->status != P2P_SC_SUCCESS_DEFERRED) {
+ p2p_dbg(p2p, "P2PS PD completion on Follow-on PD Request ACK");
+
+ if (p2p->send_action_in_progress) {
+ p2p->send_action_in_progress = 0;
+ p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
+ }
+
+ p2p->pending_action_state = P2P_NO_PENDING_ACTION;
+
+ if (p2p->cfg->p2ps_prov_complete) {
+ p2p->cfg->p2ps_prov_complete(
+ p2p->cfg->cb_ctx,
+ p2p->p2ps_prov->status,
+ p2p->p2ps_prov->adv_mac,
+ p2p->p2ps_prov->adv_mac,
+ p2p->p2ps_prov->session_mac,
+ NULL, p2p->p2ps_prov->adv_id,
+ p2p->p2ps_prov->session_id,
+ 0, 0, NULL, 0, 0, 0,
+ NULL, NULL, 0, 0, NULL, 0);
+ }
+
+ if (p2p->user_initiated_pd)
+ p2p_reset_pending_pd(p2p);
+
+ p2ps_prov_free(p2p);
+ return;
+ }
+
+ /*
* This postponing, of resetting pending_action_state, needs to be
* done only for user initiated PD requests and not internal ones.
*/
* operation was started.
*/
p2p_dbg(p2p, "Ignore old scan result for " MACSTR
- " (rx_time=%u.%06u)",
+ " (rx_time=%u.%06u find_start=%u.%06u)",
MAC2STR(bssid), (unsigned int) rx_time->sec,
- (unsigned int) rx_time->usec);
+ (unsigned int) rx_time->usec,
+ (unsigned int) p2p->find_start.sec,
+ (unsigned int) p2p->find_start.usec);
return 0;
}
}
-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)
{
u8 dev_capab;
u8 *len;
p2p_buf_add_ext_listen_timing(ies, p2p->ext_listen_period,
p2p->ext_listen_interval);
+ if (bands & BAND_60_GHZ)
+ p2p_buf_add_device_info(ies, p2p, NULL);
+
if (p2p->p2ps_seek && p2p->p2ps_seek_count)
p2p_buf_add_service_hash(ies, p2p);
break;
case P2P_PENDING_INVITATION_RESPONSE:
p2p_invitation_resp_cb(p2p, success);
+ if (p2p->inv_status != P2P_SC_SUCCESS)
+ p2p_check_after_scan_tx_continuation(p2p);
break;
case P2P_PENDING_DEV_DISC_REQUEST:
p2p_dev_disc_req_cb(p2p, success);
i, p2p->pref_freq_list[i]);
}
}
+
+
+struct wpabuf * p2p_build_probe_resp_template(struct p2p_data *p2p,
+ unsigned int freq)
+{
+ struct wpabuf *ies, *buf;
+ u8 addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+ int ret;
+
+ ies = p2p_build_probe_resp_ies(p2p, NULL, 0);
+ if (!ies) {
+ wpa_printf(MSG_ERROR,
+ "CTRL: Failed to build Probe Response IEs");
+ return NULL;
+ }
+
+ buf = wpabuf_alloc(200 + wpabuf_len(ies));
+ if (!buf) {
+ wpabuf_free(ies);
+ return NULL;
+ }
+
+ ret = p2p_build_probe_resp_buf(p2p, buf, ies, addr, freq);
+ wpabuf_free(ies);
+ if (ret) {
+ wpabuf_free(buf);
+ return NULL;
+ }
+
+ return buf;
+}
/**
* 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
int vht;
+ u8 max_oper_chwidth;
+
+ unsigned int vht_center_freq2;
+
/**
* ssid - SSID of the group
*/
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
*/
char info[0];
* @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
* 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
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
/**
* 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
* @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
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
*/
void *cb_ctx;
* @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
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()
* @addr: P2P Interface Address of the client
* 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.
*/
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 */
if (peer && peer->wps_method != WPS_NOT_READY) {
if (peer->wps_method == WPS_PBC)
methods |= WPS_CONFIG_PUSHBUTTON;
+ else if (peer->wps_method == WPS_P2PS)
+ methods |= WPS_CONFIG_P2PS;
else if (peer->wps_method == WPS_PIN_DISPLAY ||
- peer->wps_method == WPS_PIN_KEYPAD) {
+ peer->wps_method == WPS_PIN_KEYPAD)
methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
- methods |= WPS_CONFIG_P2PS;
- }
} else if (p2p->cfg->config_methods) {
methods |= p2p->cfg->config_methods &
(WPS_CONFIG_PUSHBUTTON | WPS_CONFIG_DISPLAY |
{
const u8 *pos, *end;
struct p2p_channels *ch;
- size_t channels;
+ u8 channels;
struct p2p_channels intersection;
ch = &dev->channels;
}
pos += 3;
- while (pos + 2 < end) {
+ while (end - pos > 2) {
struct p2p_reg_class *cl = &ch->reg_class[ch->reg_classes];
cl->reg_class = *pos++;
- if (pos + 1 + pos[0] > end) {
+ channels = *pos++;
+ if (channels > end - pos) {
p2p_info(p2p, "Invalid peer Channel List");
return -1;
}
- channels = *pos++;
cl->channels = channels > P2P_MAX_REG_CLASS_CHANNELS ?
P2P_MAX_REG_CLASS_CHANNELS : channels;
os_memcpy(cl->channel, pos, cl->channels);
unsigned int i;
const int op_classes_5ghz[] = { 124, 125, 115, 0 };
const int op_classes_ht40[] = { 126, 127, 116, 117, 0 };
- const int op_classes_vht[] = { 128, 0 };
+ const int op_classes_vht[] = { 128, 129, 130, 0 };
if (p2p->own_freq_preference > 0 &&
p2p_freq_to_channel(p2p->own_freq_preference,
return;
}
+ if (dev->go_neg_req_sent &&
+ (dev->flags & P2P_DEV_PEER_WAITING_RESPONSE)) {
+ p2p_dbg(p2p,
+ "Do not reply since peer is waiting for us to start a new GO Negotiation and GO Neg Request already sent");
+ p2p_parse_free(&msg);
+ return;
+ }
+
go = p2p_go_det(p2p->go_intent, *msg.go_intent);
if (go < 0) {
p2p_dbg(p2p, "Incompatible GO Intent");
P2P_PENDING_GO_NEG_RESPONSE_FAILURE;
if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
p2p->cfg->dev_addr,
- wpabuf_head(resp), wpabuf_len(resp), 500) < 0) {
+ wpabuf_head(resp), wpabuf_len(resp), 100) < 0) {
p2p_dbg(p2p, "Failed to send Action frame");
}
dev->client_timeout = msg.config_timeout[1];
}
+ if (msg.wfd_subelems) {
+ wpabuf_free(dev->info.wfd_subelems);
+ dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
+ }
+
if (!msg.operating_channel && !go) {
/*
* Note: P2P Client may omit Operating Channel attribute to
if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, sa,
wpabuf_head(dev->go_neg_conf),
- wpabuf_len(dev->go_neg_conf), 200) < 0) {
+ wpabuf_len(dev->go_neg_conf), 50) < 0) {
p2p_dbg(p2p, "Failed to send Action frame");
p2p_go_neg_failed(p2p, -1);
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
group_capab |= P2P_GROUP_CAPAB_CROSS_CONN;
if (group->num_members >= group->cfg->max_clients)
group_capab |= P2P_GROUP_CAPAB_GROUP_LIMIT;
- group_capab |= P2P_GROUP_CAPAB_IP_ADDR_ALLOCATION;
+ if (group->cfg->ip_addr_alloc)
+ group_capab |= P2P_GROUP_CAPAB_IP_ADDR_ALLOCATION;
p2p_buf_add_capability(ie, dev_capab, group_capab);
}
os_memset(zero_addr, 0, ETH_ALEN);
pos = wpabuf_head_u8(m->wfd_ie);
end = pos + wpabuf_len(m->wfd_ie);
- while (pos + 1 < end) {
+ while (end - pos >= 3) {
u8 id;
u16 len;
id = *pos++;
len = WPA_GET_BE16(pos);
pos += 2;
- if (pos + len > end)
+ if (len > end - pos)
break;
switch (id) {
}
+const u8 * p2p_group_get_client_interface_addr(struct p2p_group *group,
+ const u8 *dev_addr)
+{
+ struct p2p_group_member *m;
+
+ if (!group)
+ return NULL;
+ m = p2p_group_get_client(group, dev_addr);
+ if (m)
+ return m->addr;
+ return NULL;
+}
+
+
static struct p2p_group_member * p2p_group_get_client_iface(
struct p2p_group *group, const u8 *interface_addr)
{
struct p2p_device *dev;
dev = p2p_get_device(group->p2p, m->dev_addr);
- if (!dev)
+ if (!dev || dev->channels.reg_classes == 0)
continue;
p2p_channels_intersect(&intersect, &dev->channels, &res);
*/
int num_p2p_sd_queries;
+ /**
+ * sd_query_no_ack - The first peer (Dev Addr) that did not ACK SD Query
+ *
+ * This is used to track the first peer that did not ACK an SD Query
+ * within a single P2P Search iteration. All zeros address means no such
+ * peer was yet seen. This information is used to allow a new Listen and
+ * Search phases to be once every pending SD Query has been sent once to
+ * each peer instead of looping all pending attempts continuously until
+ * running out of retry maximums.
+ */
+ u8 sd_query_no_ack[ETH_ALEN];
+
/* GO Negotiation data */
/**
u8 *op_channel);
/* p2p_parse.c */
+void p2p_copy_filter_devname(char *dst, size_t dst_len,
+ const void *src, size_t src_len);
int p2p_parse_p2p_ie(const struct wpabuf *buf, struct p2p_message *msg);
int p2p_parse_ies(const u8 *data, size_t len, struct p2p_message *msg);
int p2p_parse(const u8 *data, size_t len, struct p2p_message *msg);
if (!p2p_channels_includes(&intersection, reg_class, channel))
{
- p2p_dbg(p2p, "forced freq %d MHz not in the supported channels interaction",
+ p2p_dbg(p2p, "forced freq %d MHz not in the supported channels intersection",
op_freq);
status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
goto fail;
p2p->pending_action_state = P2P_PENDING_INVITATION_RESPONSE;
if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
p2p->cfg->dev_addr,
- wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
+ wpabuf_head(resp), wpabuf_len(resp), 50) < 0) {
p2p_dbg(p2p, "Failed to send Action frame");
}
#include "p2p_i.h"
+void p2p_copy_filter_devname(char *dst, size_t dst_len,
+ const void *src, size_t src_len)
+{
+ size_t i;
+
+ if (src_len >= dst_len)
+ src_len = dst_len - 1;
+ os_memcpy(dst, src, src_len);
+ dst[src_len] = '\0';
+ for (i = 0; i < src_len; i++) {
+ if (dst[i] == '\0')
+ break;
+ if (is_ctrl_char(dst[i]))
+ dst[i] = '_';
+ }
+}
+
+
static int p2p_parse_attribute(u8 id, const u8 *data, u16 len,
struct p2p_message *msg)
{
const u8 *pos;
- size_t i, nlen;
+ u16 nlen;
char devtype[WPS_DEV_TYPE_BUFSIZE];
switch (id) {
pos += 2;
nlen = WPA_GET_BE16(pos);
pos += 2;
- if (data + len - pos < (int) nlen ||
- nlen > WPS_DEV_NAME_MAX_LEN) {
+ if (nlen > data + len - pos || nlen > WPS_DEV_NAME_MAX_LEN) {
wpa_printf(MSG_DEBUG, "P2P: Invalid Device Name "
- "length %d (buf len %d)", (int) nlen,
+ "length %u (buf len %d)", nlen,
(int) (data + len - pos));
return -1;
}
- os_memcpy(msg->device_name, pos, nlen);
- msg->device_name[nlen] = '\0';
- for (i = 0; i < nlen; i++) {
- if (msg->device_name[i] == '\0')
- break;
- if (is_ctrl_char(msg->device_name[i]))
- msg->device_name[i] = '_';
- }
+ p2p_copy_filter_devname(msg->device_name,
+ sizeof(msg->device_name), pos, nlen);
wpa_printf(MSG_DEBUG, "P2P: * Device Info: addr " MACSTR
" primary device type %s device name '%s' "
"config methods 0x%x",
gend = gi + gi_len;
while (g < gend) {
struct p2p_client_info *cli;
- const u8 *t, *cend;
- int count;
+ const u8 *cend;
+ u16 count;
+ u8 len;
cli = &info->client[info->num_clients];
- cend = g + 1 + g[0];
- if (cend > gend)
+ len = *g++;
+ if (len > gend - g || len < 2 * ETH_ALEN + 1 + 2 + 8 + 1)
return -1; /* invalid data */
+ cend = g + len;
/* g at start of P2P Client Info Descriptor */
- /* t at Device Capability Bitmap */
- t = g + 1 + 2 * ETH_ALEN;
- if (t > cend)
- return -1; /* invalid data */
- cli->p2p_device_addr = g + 1;
- cli->p2p_interface_addr = g + 1 + ETH_ALEN;
- cli->dev_capab = t[0];
-
- if (t + 1 + 2 + 8 + 1 > cend)
- return -1; /* invalid data */
-
- cli->config_methods = WPA_GET_BE16(&t[1]);
- cli->pri_dev_type = &t[3];
-
- t += 1 + 2 + 8;
- /* t at Number of Secondary Device Types */
- cli->num_sec_dev_types = *t++;
- if (t + 8 * cli->num_sec_dev_types > cend)
+ cli->p2p_device_addr = g;
+ g += ETH_ALEN;
+ cli->p2p_interface_addr = g;
+ g += ETH_ALEN;
+ cli->dev_capab = *g++;
+
+ cli->config_methods = WPA_GET_BE16(g);
+ g += 2;
+ cli->pri_dev_type = g;
+ g += 8;
+
+ /* g at Number of Secondary Device Types */
+ len = *g++;
+ if (8 * len > cend - g)
return -1; /* invalid data */
- cli->sec_dev_types = t;
- t += 8 * cli->num_sec_dev_types;
+ cli->num_sec_dev_types = len;
+ cli->sec_dev_types = g;
+ g += 8 * len;
- /* t at Device Name in WPS TLV format */
- if (t + 2 + 2 > cend)
+ /* g at Device Name in WPS TLV format */
+ if (cend - g < 2 + 2)
return -1; /* invalid data */
- if (WPA_GET_BE16(t) != ATTR_DEV_NAME)
+ if (WPA_GET_BE16(g) != ATTR_DEV_NAME)
return -1; /* invalid Device Name TLV */
- t += 2;
- count = WPA_GET_BE16(t);
- t += 2;
- if (count > cend - t)
+ g += 2;
+ count = WPA_GET_BE16(g);
+ g += 2;
+ if (count > cend - g)
return -1; /* invalid Device Name TLV */
if (count >= WPS_DEV_NAME_MAX_LEN)
count = WPS_DEV_NAME_MAX_LEN;
- cli->dev_name = (const char *) t;
+ cli->dev_name = (const char *) g;
cli->dev_name_len = count;
g = cend;
}
-static void p2ps_add_new_group_info(struct p2p_data *p2p, struct wpabuf *buf)
+static void p2ps_add_new_group_info(struct p2p_data *p2p,
+ struct p2p_device *dev,
+ struct wpabuf *buf)
{
int found;
u8 intended_addr[ETH_ALEN];
u8 ssid[SSID_MAX_LEN];
size_t ssid_len;
int group_iface;
+ unsigned int force_freq;
if (!p2p->cfg->get_go_info)
return;
found = p2p->cfg->get_go_info(
p2p->cfg->cb_ctx, intended_addr, ssid,
- &ssid_len, &group_iface);
+ &ssid_len, &group_iface, &force_freq);
if (found) {
+ if (force_freq > 0) {
+ p2p->p2ps_prov->force_freq = force_freq;
+ p2p->p2ps_prov->pref_freq = 0;
+
+ if (dev)
+ p2p_prepare_channel(p2p, dev, force_freq, 0, 0);
+ }
p2p_buf_add_group_id(buf, p2p->cfg->dev_addr,
ssid, ssid_len);
size_t ssid_len;
u8 go_dev_addr[ETH_ALEN];
u8 intended_addr[ETH_ALEN];
+ int follow_on_req_fail = prov->status >= 0 &&
+ prov->status != P2P_SC_SUCCESS_DEFERRED;
/* If we might be explicite group owner, add GO details */
- if (prov->conncap & (P2PS_SETUP_GROUP_OWNER |
- P2PS_SETUP_NEW))
- p2ps_add_new_group_info(p2p, buf);
+ if (!follow_on_req_fail &&
+ (prov->conncap & (P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_NEW)))
+ p2ps_add_new_group_info(p2p, dev, buf);
if (prov->status >= 0)
p2p_buf_add_status(buf, (u8) prov->status);
else
prov->method = config_methods;
- if (p2p->cfg->get_persistent_group) {
- shared_group = p2p->cfg->get_persistent_group(
- p2p->cfg->cb_ctx, dev->info.p2p_device_addr, NULL, 0,
- go_dev_addr, ssid, &ssid_len, intended_addr);
- }
-
- /* Add Operating Channel if conncap includes GO */
- if (shared_group ||
- (prov->conncap & (P2PS_SETUP_GROUP_OWNER |
- P2PS_SETUP_NEW))) {
- u8 tmp;
+ if (!follow_on_req_fail) {
+ if (p2p->cfg->get_persistent_group) {
+ shared_group = p2p->cfg->get_persistent_group(
+ p2p->cfg->cb_ctx, dev->info.p2p_device_addr,
+ NULL, 0, go_dev_addr, ssid, &ssid_len,
+ intended_addr);
+ }
- p2p_go_select_channel(p2p, dev, &tmp);
+ if (shared_group ||
+ (prov->conncap & (P2PS_SETUP_CLIENT | P2PS_SETUP_NEW)))
+ p2p_buf_add_channel_list(buf, p2p->cfg->country,
+ &p2p->channels);
- if (p2p->op_reg_class && p2p->op_channel)
+ if ((shared_group && !is_zero_ether_addr(intended_addr)) ||
+ (prov->conncap & (P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_NEW)))
p2p_buf_add_operating_channel(buf, p2p->cfg->country,
p2p->op_reg_class,
p2p->op_channel);
- else
- p2p_buf_add_operating_channel(buf, p2p->cfg->country,
- p2p->cfg->op_reg_class,
- p2p->cfg->op_channel);
}
- p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->cfg->channels);
-
- if (prov->info[0])
+ if (prov->status < 0 && prov->info[0])
p2p_buf_add_session_info(buf, prov->info);
- p2p_buf_add_connection_capability(buf, prov->conncap);
+ if (!follow_on_req_fail)
+ p2p_buf_add_connection_capability(buf, prov->conncap);
p2p_buf_add_advertisement_id(buf, prov->adv_id, prov->adv_mac);
- if (shared_group || prov->conncap == P2PS_SETUP_NEW ||
- prov->conncap ==
- (P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_NEW) ||
- prov->conncap ==
- (P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_CLIENT)) {
- /* Add Config Timeout */
- p2p_buf_add_config_timeout(buf, p2p->go_timeout,
- p2p->client_timeout);
- }
+ if (!follow_on_req_fail) {
+ if (shared_group || prov->conncap == P2PS_SETUP_NEW ||
+ prov->conncap ==
+ (P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_NEW) ||
+ prov->conncap ==
+ (P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_CLIENT)) {
+ /* Add Config Timeout */
+ p2p_buf_add_config_timeout(buf, p2p->go_timeout,
+ p2p->client_timeout);
+ }
- p2p_buf_add_listen_channel(buf, p2p->cfg->country, p2p->cfg->reg_class,
- p2p->cfg->channel);
+ p2p_buf_add_listen_channel(buf, p2p->cfg->country,
+ p2p->cfg->reg_class,
+ p2p->cfg->channel);
+ }
p2p_buf_add_session_id(buf, prov->session_id, prov->session_mac);
u8 *len = p2p_buf_add_ie_hdr(buf);
struct p2ps_provision *prov = p2p->p2ps_prov;
u8 group_capab;
+ u8 conncap = 0;
+
+ if (status == P2P_SC_SUCCESS ||
+ status == P2P_SC_SUCCESS_DEFERRED)
+ conncap = prov->conncap;
if (!status && prov->status != -1)
status = prov->status;
group_capab);
p2p_buf_add_device_info(buf, p2p, NULL);
- if (persist_ssid && p2p->cfg->get_persistent_group &&
+ if (persist_ssid && p2p->cfg->get_persistent_group && dev &&
(status == P2P_SC_SUCCESS ||
status == P2P_SC_SUCCESS_DEFERRED)) {
u8 ssid[SSID_MAX_LEN];
}
}
- if (!persist && (prov->conncap & P2PS_SETUP_GROUP_OWNER))
- p2ps_add_new_group_info(p2p, buf);
+ if (!persist && (conncap & P2PS_SETUP_GROUP_OWNER))
+ p2ps_add_new_group_info(p2p, dev, buf);
/* Add Operating Channel if conncap indicates GO */
- if (persist || (prov->conncap & P2PS_SETUP_GROUP_OWNER)) {
- u8 tmp;
-
- if (dev)
- p2p_go_select_channel(p2p, dev, &tmp);
-
+ if (persist || (conncap & P2PS_SETUP_GROUP_OWNER)) {
if (p2p->op_reg_class && p2p->op_channel)
p2p_buf_add_operating_channel(
buf, p2p->cfg->country,
p2p->cfg->op_channel);
}
- p2p_buf_add_channel_list(buf, p2p->cfg->country,
- &p2p->cfg->channels);
+ if (persist ||
+ (conncap & (P2PS_SETUP_CLIENT | P2PS_SETUP_GROUP_OWNER)))
+ p2p_buf_add_channel_list(buf, p2p->cfg->country,
+ &p2p->channels);
- if (!persist && (status == P2P_SC_SUCCESS ||
- status == P2P_SC_SUCCESS_DEFERRED))
- p2p_buf_add_connection_capability(buf, prov->conncap);
+ if (!persist && conncap)
+ p2p_buf_add_connection_capability(buf, conncap);
p2p_buf_add_advertisement_id(buf, adv_id, prov->adv_mac);
- p2p_buf_add_config_timeout(buf, p2p->go_timeout,
- p2p->client_timeout);
+ if (persist ||
+ (conncap & (P2PS_SETUP_CLIENT | P2PS_SETUP_GROUP_OWNER)))
+ p2p_buf_add_config_timeout(buf, p2p->go_timeout,
+ p2p->client_timeout);
p2p_buf_add_session_id(buf, prov->session_id,
prov->session_mac);
}
+/* Check if the message contains a valid P2PS PD Request */
+static int p2ps_validate_pd_req(struct p2p_data *p2p, struct p2p_message *msg,
+ const u8 *addr)
+{
+ u8 group_id = 0;
+ u8 intended_addr = 0;
+ u8 operating_channel = 0;
+ u8 channel_list = 0;
+ u8 config_timeout = 0;
+ u8 listen_channel = 0;
+
+#define P2PS_PD_REQ_CHECK(_val, _attr) \
+do { \
+ if ((_val) && !msg->_attr) { \
+ p2p_dbg(p2p, "Not P2PS PD Request. Missing %s", #_attr); \
+ return -1; \
+ } \
+} while (0)
+
+ P2PS_PD_REQ_CHECK(1, adv_id);
+ P2PS_PD_REQ_CHECK(1, session_id);
+ P2PS_PD_REQ_CHECK(1, session_mac);
+ P2PS_PD_REQ_CHECK(1, adv_mac);
+ P2PS_PD_REQ_CHECK(1, capability);
+ P2PS_PD_REQ_CHECK(1, p2p_device_info);
+ P2PS_PD_REQ_CHECK(1, feature_cap);
+
+ /*
+ * We don't need to check Connection Capability, Persistent Group,
+ * and related attributes for follow-on PD Request with a status
+ * other than SUCCESS_DEFERRED.
+ */
+ if (msg->status && *msg->status != P2P_SC_SUCCESS_DEFERRED)
+ return 0;
+
+ P2PS_PD_REQ_CHECK(1, conn_cap);
+
+ /*
+ * Note 1: A feature capability attribute structure can be changed
+ * in the future. The assumption is that such modifications are
+ * backward compatible, therefore we allow processing of msg.feature_cap
+ * exceeding the size of the p2ps_feature_capab structure.
+ * Note 2: Verification of msg.feature_cap_len below has to be changed
+ * to allow 2 byte feature capability processing if
+ * struct p2ps_feature_capab is extended to include additional fields
+ * and it affects the structure size.
+ */
+ if (msg->feature_cap_len < sizeof(struct p2ps_feature_capab)) {
+ p2p_dbg(p2p, "P2PS: Invalid feature capability len");
+ return -1;
+ }
+
+ switch (*msg->conn_cap) {
+ case P2PS_SETUP_NEW:
+ group_id = 1;
+ intended_addr = 1;
+ operating_channel = 1;
+ channel_list = 1;
+ config_timeout = 1;
+ listen_channel = 1;
+ break;
+ case P2PS_SETUP_CLIENT:
+ channel_list = 1;
+ listen_channel = 1;
+ break;
+ case P2PS_SETUP_GROUP_OWNER:
+ group_id = 1;
+ intended_addr = 1;
+ operating_channel = 1;
+ break;
+ case P2PS_SETUP_NEW | P2PS_SETUP_GROUP_OWNER:
+ group_id = 1;
+ operating_channel = 1;
+ intended_addr = 1;
+ channel_list = 1;
+ config_timeout = 1;
+ break;
+ case P2PS_SETUP_CLIENT | P2PS_SETUP_GROUP_OWNER:
+ group_id = 1;
+ intended_addr = 1;
+ operating_channel = 1;
+ channel_list = 1;
+ config_timeout = 1;
+ break;
+ default:
+ p2p_dbg(p2p, "Invalid P2PS PD connection capability");
+ return -1;
+ }
+
+ if (msg->persistent_dev) {
+ channel_list = 1;
+ config_timeout = 1;
+ if (os_memcmp(msg->persistent_dev, addr, ETH_ALEN) == 0) {
+ intended_addr = 1;
+ operating_channel = 1;
+ }
+ }
+
+ P2PS_PD_REQ_CHECK(group_id, group_id);
+ P2PS_PD_REQ_CHECK(intended_addr, intended_addr);
+ P2PS_PD_REQ_CHECK(operating_channel, operating_channel);
+ P2PS_PD_REQ_CHECK(channel_list, channel_list);
+ P2PS_PD_REQ_CHECK(config_timeout, config_timeout);
+ P2PS_PD_REQ_CHECK(listen_channel, listen_channel);
+
+#undef P2PS_PD_REQ_CHECK
+
+ return 0;
+}
+
+
void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
const u8 *data, size_t len, int rx_freq)
{
u8 conncap = P2PS_SETUP_NEW;
u8 auto_accept = 0;
u32 session_id = 0;
- u8 session_mac[ETH_ALEN];
- u8 adv_mac[ETH_ALEN];
+ u8 session_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
+ u8 adv_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
const u8 *group_mac;
int passwd_id = DEV_PW_DEFAULT;
u16 config_methods;
u16 allowed_config_methods = WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
struct p2ps_feature_capab resp_fcap = { 0, 0 };
- struct p2ps_feature_capab *req_fcap;
+ struct p2ps_feature_capab *req_fcap = NULL;
+ u8 remote_conncap;
+ u16 method;
if (p2p_parse(data, len, &msg))
return;
0)) {
p2p_dbg(p2p, "Provision Discovery Request add device failed "
MACSTR, MAC2STR(sa));
+ goto out;
+ }
+
+ if (!dev) {
+ dev = p2p_get_device(p2p, sa);
+ if (!dev) {
+ p2p_dbg(p2p,
+ "Provision Discovery device not found "
+ MACSTR, MAC2STR(sa));
+ goto out;
+ }
}
} else if (msg.wfd_subelems) {
wpabuf_free(dev->info.wfd_subelems);
dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
}
- if (msg.adv_id)
- allowed_config_methods |= WPS_CONFIG_P2PS;
- else
+ if (!msg.adv_id) {
allowed_config_methods |= WPS_CONFIG_PUSHBUTTON;
+ if (!(msg.wps_config_methods & allowed_config_methods)) {
+ p2p_dbg(p2p,
+ "Unsupported Config Methods in Provision Discovery Request");
+ goto out;
+ }
- if (!(msg.wps_config_methods & allowed_config_methods)) {
- p2p_dbg(p2p, "Unsupported Config Methods in Provision Discovery Request");
- goto out;
- }
+ /* Legacy (non-P2PS) - Unknown groups allowed for P2PS */
+ if (msg.group_id) {
+ size_t i;
- /* Legacy (non-P2PS) - Unknown groups allowed for P2PS */
- if (!msg.adv_id && msg.group_id) {
- size_t i;
- for (i = 0; i < p2p->num_groups; i++) {
- if (p2p_group_is_group_id_match(p2p->groups[i],
- msg.group_id,
- msg.group_id_len))
- break;
+ for (i = 0; i < p2p->num_groups; i++) {
+ if (p2p_group_is_group_id_match(
+ p2p->groups[i],
+ msg.group_id, msg.group_id_len))
+ break;
+ }
+ if (i == p2p->num_groups) {
+ p2p_dbg(p2p,
+ "PD request for unknown P2P Group ID - reject");
+ goto out;
+ }
}
- if (i == p2p->num_groups) {
- p2p_dbg(p2p, "PD request for unknown P2P Group ID - reject");
+ } else {
+ allowed_config_methods |= WPS_CONFIG_P2PS;
+
+ /*
+ * Set adv_id here, so in case of an error, a P2PS PD Response
+ * will be sent.
+ */
+ adv_id = WPA_GET_LE32(msg.adv_id);
+ if (p2ps_validate_pd_req(p2p, &msg, sa) < 0) {
+ reject = P2P_SC_FAIL_INVALID_PARAMS;
goto out;
}
- }
- if (dev) {
- dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY |
- P2P_DEV_PD_PEER_KEYPAD |
- P2P_DEV_PD_PEER_P2PS);
+ req_fcap = (struct p2ps_feature_capab *) msg.feature_cap;
- /* Remove stale persistent groups */
- if (p2p->cfg->remove_stale_groups) {
- p2p->cfg->remove_stale_groups(
- p2p->cfg->cb_ctx, dev->info.p2p_device_addr,
- msg.persistent_dev,
- msg.persistent_ssid, msg.persistent_ssid_len);
+ os_memcpy(session_mac, msg.session_mac, ETH_ALEN);
+ os_memcpy(adv_mac, msg.adv_mac, ETH_ALEN);
+
+ session_id = WPA_GET_LE32(msg.session_id);
+
+ if (msg.conn_cap)
+ conncap = *msg.conn_cap;
+
+ /*
+ * We need to verify a P2PS config methog in an initial PD
+ * request or in a follow-on PD request with the status
+ * SUCCESS_DEFERRED.
+ */
+ if ((!msg.status || *msg.status == P2P_SC_SUCCESS_DEFERRED) &&
+ !(msg.wps_config_methods & allowed_config_methods)) {
+ p2p_dbg(p2p,
+ "Unsupported Config Methods in Provision Discovery Request");
+ goto out;
}
+
+ /*
+ * TODO: since we don't support multiple PD, reject PD request
+ * if we are in the middle of P2PS PD with some other peer
+ */
}
+
+ dev->flags &= ~(P2P_DEV_PD_PEER_DISPLAY |
+ P2P_DEV_PD_PEER_KEYPAD |
+ P2P_DEV_PD_PEER_P2PS);
+
if (msg.wps_config_methods & WPS_CONFIG_DISPLAY) {
p2p_dbg(p2p, "Peer " MACSTR
" requested us to show a PIN on display", MAC2STR(sa));
- if (dev)
- dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
+ dev->flags |= P2P_DEV_PD_PEER_KEYPAD;
passwd_id = DEV_PW_USER_SPECIFIED;
} else if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
p2p_dbg(p2p, "Peer " MACSTR
" requested us to write its PIN using keypad",
MAC2STR(sa));
- if (dev)
- dev->flags |= P2P_DEV_PD_PEER_DISPLAY;
+ dev->flags |= P2P_DEV_PD_PEER_DISPLAY;
passwd_id = DEV_PW_REGISTRAR_SPECIFIED;
} else if (msg.wps_config_methods & WPS_CONFIG_P2PS) {
p2p_dbg(p2p, "Peer " MACSTR " requesting P2PS PIN",
MAC2STR(sa));
- if (dev)
- dev->flags |= P2P_DEV_PD_PEER_P2PS;
+ dev->flags |= P2P_DEV_PD_PEER_P2PS;
passwd_id = DEV_PW_P2PS_DEFAULT;
}
- reject = P2P_SC_SUCCESS;
+ /* Remove stale persistent groups */
+ if (p2p->cfg->remove_stale_groups) {
+ p2p->cfg->remove_stale_groups(
+ p2p->cfg->cb_ctx, dev->info.p2p_device_addr,
+ msg.persistent_dev,
+ msg.persistent_ssid, msg.persistent_ssid_len);
+ }
- os_memset(session_mac, 0, ETH_ALEN);
- os_memset(adv_mac, 0, ETH_ALEN);
+ reject = P2P_SC_SUCCESS;
- /* Note 1: A feature capability attribute structure can be changed
- * in the future. The assumption is that such modifications are
- * backwards compatible, therefore we allow processing of
- * msg.feature_cap exceeding the size of the p2ps_feature_capab
- * structure.
- * Note 2: Vverification of msg.feature_cap_len below has to be changed
- * to allow 2 byte feature capability processing if struct
- * p2ps_feature_capab is extended to include additional fields and it
- * affects the structure size.
+ /*
+ * End of a legacy P2P PD Request processing, from this point continue
+ * with P2PS one.
*/
- if (msg.adv_id && msg.session_id && msg.session_mac && msg.adv_mac &&
- msg.feature_cap && msg.feature_cap_len >= sizeof(*req_fcap) &&
- (msg.status || msg.conn_cap)) {
- u8 remote_conncap;
+ if (!msg.adv_id)
+ goto out;
- req_fcap = (struct p2ps_feature_capab *) msg.feature_cap;
+ remote_conncap = conncap;
- os_memcpy(session_mac, msg.session_mac, ETH_ALEN);
- os_memcpy(adv_mac, msg.adv_mac, ETH_ALEN);
+ if (!msg.status) {
+ unsigned int forced_freq, pref_freq;
- session_id = WPA_GET_LE32(msg.session_id);
- adv_id = WPA_GET_LE32(msg.adv_id);
-
- if (!msg.status)
- p2ps_adv = p2p_service_p2ps_id(p2p, adv_id);
+ if (os_memcmp(p2p->cfg->dev_addr, msg.adv_mac, ETH_ALEN)) {
+ p2p_dbg(p2p,
+ "P2PS PD adv mac does not match the local one");
+ reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
+ goto out;
+ }
- p2p_dbg(p2p, "adv_id: %x - p2ps_adv - %p", adv_id, p2ps_adv);
+ p2ps_adv = p2p_service_p2ps_id(p2p, adv_id);
+ if (!p2ps_adv) {
+ p2p_dbg(p2p, "P2PS PD invalid adv_id=0x%X", adv_id);
+ reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
+ goto out;
+ }
+ p2p_dbg(p2p, "adv_id: 0x%X, p2ps_adv: %p", adv_id, p2ps_adv);
- if (msg.conn_cap)
- conncap = *msg.conn_cap;
- remote_conncap = conncap;
+ auto_accept = p2ps_adv->auto_accept;
+ conncap = p2p->cfg->p2ps_group_capability(p2p->cfg->cb_ctx,
+ conncap, auto_accept,
+ &forced_freq,
+ &pref_freq);
- if (p2ps_adv) {
- auto_accept = p2ps_adv->auto_accept;
- conncap = p2p->cfg->p2ps_group_capability(
- p2p->cfg->cb_ctx, conncap, auto_accept);
+ p2p_dbg(p2p, "Conncap: local:%d remote:%d result:%d",
+ auto_accept, remote_conncap, conncap);
- p2p_dbg(p2p, "Conncap: local:%d remote:%d result:%d",
- auto_accept, remote_conncap, conncap);
+ p2p_prepare_channel(p2p, dev, forced_freq, pref_freq, 0);
- resp_fcap.cpt =
- p2ps_own_preferred_cpt(p2ps_adv->cpt_priority,
+ resp_fcap.cpt = p2ps_own_preferred_cpt(p2ps_adv->cpt_priority,
req_fcap->cpt);
+ p2p_dbg(p2p, "cpt: service:0x%x remote:0x%x result:0x%x",
+ p2ps_adv->cpt_mask, req_fcap->cpt, resp_fcap.cpt);
+
+ if (!resp_fcap.cpt) {
+ p2p_dbg(p2p,
+ "Incompatible P2PS feature capability CPT bitmask");
+ reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
+ } else if (p2ps_adv->config_methods &&
+ !(msg.wps_config_methods &
+ p2ps_adv->config_methods)) {
p2p_dbg(p2p,
- "cpt: service:0x%x remote:0x%x result:0x%x",
- p2ps_adv->cpt_mask, req_fcap->cpt,
- resp_fcap.cpt);
+ "Unsupported config methods in Provision Discovery Request (own=0x%x peer=0x%x)",
+ p2ps_adv->config_methods,
+ msg.wps_config_methods);
+ reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
+ } else if (!p2ps_adv->state) {
+ p2p_dbg(p2p, "P2PS state unavailable");
+ reject = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
+ } else if (!conncap) {
+ p2p_dbg(p2p, "Conncap resolution failed");
+ reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
+ }
- if (!resp_fcap.cpt) {
- p2p_dbg(p2p,
- "Incompatible P2PS feature capability CPT bitmask");
- reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
- } else if (p2ps_adv->config_methods &&
- !(msg.wps_config_methods &
- p2ps_adv->config_methods)) {
- p2p_dbg(p2p,
- "Unsupported config methods in Provision Discovery Request (own=0x%x peer=0x%x)",
- p2ps_adv->config_methods,
- msg.wps_config_methods);
- reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
- } else if (!p2ps_adv->state) {
- p2p_dbg(p2p, "P2PS state unavailable");
- reject = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
- } else if (!conncap) {
- p2p_dbg(p2p, "Conncap resolution failed");
- reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
- }
+ if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
+ p2p_dbg(p2p, "Keypad - always defer");
+ auto_accept = 0;
+ }
- if (msg.wps_config_methods & WPS_CONFIG_KEYPAD) {
- p2p_dbg(p2p, "Keypad - always defer");
- auto_accept = 0;
+ if ((remote_conncap & (P2PS_SETUP_NEW | P2PS_SETUP_CLIENT) ||
+ msg.persistent_dev) && conncap != P2PS_SETUP_NEW &&
+ msg.channel_list && msg.channel_list_len &&
+ p2p_peer_channels_check(p2p, &p2p->channels, dev,
+ msg.channel_list,
+ msg.channel_list_len) < 0) {
+ p2p_dbg(p2p,
+ "No common channels - force deferred flow");
+ auto_accept = 0;
+ }
+
+ if (((remote_conncap & P2PS_SETUP_GROUP_OWNER) ||
+ msg.persistent_dev) && msg.operating_channel) {
+ struct p2p_channels intersect;
+
+ /*
+ * There are cases where only the operating channel is
+ * provided. This requires saving the channel as the
+ * supported channel list, and verifying that it is
+ * supported.
+ */
+ if (dev->channels.reg_classes == 0 ||
+ !p2p_channels_includes(&dev->channels,
+ msg.operating_channel[3],
+ msg.operating_channel[4])) {
+ struct p2p_channels *ch = &dev->channels;
+
+ os_memset(ch, 0, sizeof(*ch));
+ ch->reg_class[0].reg_class =
+ msg.operating_channel[3];
+ ch->reg_class[0].channel[0] =
+ msg.operating_channel[4];
+ ch->reg_class[0].channels = 1;
+ ch->reg_classes = 1;
}
- if (auto_accept || reject != P2P_SC_SUCCESS) {
- struct p2ps_provision *tmp;
-
- if (reject == P2P_SC_SUCCESS && !conncap) {
- reject =
- P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
- }
-
- if (p2ps_setup_p2ps_prov(
- p2p, adv_id, session_id,
- msg.wps_config_methods,
- session_mac, adv_mac) < 0) {
- reject = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
- goto out;
- }
-
- tmp = p2p->p2ps_prov;
- if (conncap) {
- tmp->conncap = conncap;
- tmp->status = P2P_SC_SUCCESS;
- } else {
- tmp->conncap = auto_accept;
- tmp->status = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
- }
-
- if (reject != P2P_SC_SUCCESS)
- goto out;
+ p2p_channels_intersect(&p2p->channels, &dev->channels,
+ &intersect);
+
+ if (intersect.reg_classes == 0) {
+ p2p_dbg(p2p,
+ "No common channels - force deferred flow");
+ auto_accept = 0;
}
- } else if (!msg.status) {
- reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
- goto out;
}
- if (!msg.status && !auto_accept &&
- (!p2p->p2ps_prov || p2p->p2ps_prov->adv_id != adv_id)) {
+ if (auto_accept || reject != P2P_SC_SUCCESS) {
struct p2ps_provision *tmp;
- if (!conncap) {
- reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
- goto out;
- }
-
if (p2ps_setup_p2ps_prov(p2p, adv_id, session_id,
msg.wps_config_methods,
session_mac, adv_mac) < 0) {
reject = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
goto out;
}
+
tmp = p2p->p2ps_prov;
- reject = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
- tmp->status = reject;
+ tmp->force_freq = forced_freq;
+ tmp->pref_freq = pref_freq;
+ if (conncap) {
+ tmp->conncap = conncap;
+ tmp->status = P2P_SC_SUCCESS;
+ } else {
+ tmp->conncap = auto_accept;
+ tmp->status = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
+ }
+
+ if (reject != P2P_SC_SUCCESS)
+ goto out;
}
+ }
- if (msg.status) {
- if (*msg.status &&
- *msg.status != P2P_SC_SUCCESS_DEFERRED) {
- reject = *msg.status;
- } else if (*msg.status == P2P_SC_SUCCESS_DEFERRED &&
- p2p->p2ps_prov) {
- u16 method = p2p->p2ps_prov->method;
+ if (!msg.status && !auto_accept &&
+ (!p2p->p2ps_prov || p2p->p2ps_prov->adv_id != adv_id)) {
+ struct p2ps_provision *tmp;
- conncap = p2p->cfg->p2ps_group_capability(
- p2p->cfg->cb_ctx, remote_conncap,
- p2p->p2ps_prov->conncap);
+ if (!conncap) {
+ reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
+ goto out;
+ }
- p2p_dbg(p2p,
- "Conncap: local:%d remote:%d result:%d",
- p2p->p2ps_prov->conncap,
- remote_conncap, conncap);
+ if (p2ps_setup_p2ps_prov(p2p, adv_id, session_id,
+ msg.wps_config_methods,
+ session_mac, adv_mac) < 0) {
+ reject = P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
+ goto out;
+ }
+ tmp = p2p->p2ps_prov;
+ reject = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE;
+ tmp->status = reject;
+ }
- resp_fcap.cpt = p2ps_own_preferred_cpt(
- p2p->p2ps_prov->cpt_priority,
- req_fcap->cpt);
+ /* Not a P2PS Follow-on PD */
+ if (!msg.status)
+ goto out;
- p2p_dbg(p2p,
- "cpt: local:0x%x remote:0x%x result:0x%x",
- p2p->p2ps_prov->cpt_mask,
- req_fcap->cpt, resp_fcap.cpt);
+ if (*msg.status && *msg.status != P2P_SC_SUCCESS_DEFERRED) {
+ reject = *msg.status;
+ goto out;
+ }
- /*
- * Ensure that if we asked for PIN originally,
- * our method is consistent with original
- * request.
- */
- if (method & WPS_CONFIG_DISPLAY)
- method = WPS_CONFIG_KEYPAD;
- else if (method & WPS_CONFIG_KEYPAD)
- method = WPS_CONFIG_DISPLAY;
-
- if (!conncap ||
- !(msg.wps_config_methods & method)) {
- /*
- * Reject this "Deferred Accept*
- * if incompatible conncap or method
- */
- reject =
- P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
- } else if (!resp_fcap.cpt) {
- p2p_dbg(p2p,
- "Incompatible P2PS feature capability CPT bitmask");
- reject =
- P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
- } else {
- reject = P2P_SC_SUCCESS;
- }
-
- p2p->p2ps_prov->status = reject;
- p2p->p2ps_prov->conncap = conncap;
- }
- }
+ if (*msg.status != P2P_SC_SUCCESS_DEFERRED || !p2p->p2ps_prov)
+ goto out;
+
+ if (p2p->p2ps_prov->adv_id != adv_id ||
+ os_memcmp(p2p->p2ps_prov->adv_mac, msg.adv_mac, ETH_ALEN)) {
+ p2p_dbg(p2p,
+ "P2PS Follow-on PD with mismatch Advertisement ID/MAC");
+ goto out;
}
+ if (p2p->p2ps_prov->session_id != session_id ||
+ os_memcmp(p2p->p2ps_prov->session_mac, msg.session_mac, ETH_ALEN)) {
+ p2p_dbg(p2p, "P2PS Follow-on PD with mismatch Session ID/MAC");
+ goto out;
+ }
+
+ method = p2p->p2ps_prov->method;
+
+ conncap = p2p->cfg->p2ps_group_capability(p2p->cfg->cb_ctx,
+ remote_conncap,
+ p2p->p2ps_prov->conncap,
+ &p2p->p2ps_prov->force_freq,
+ &p2p->p2ps_prov->pref_freq);
+
+ resp_fcap.cpt = p2ps_own_preferred_cpt(p2p->p2ps_prov->cpt_priority,
+ req_fcap->cpt);
+
+ p2p_dbg(p2p, "cpt: local:0x%x remote:0x%x result:0x%x",
+ p2p->p2ps_prov->cpt_mask, req_fcap->cpt, resp_fcap.cpt);
+
+ p2p_prepare_channel(p2p, dev, p2p->p2ps_prov->force_freq,
+ p2p->p2ps_prov->pref_freq, 0);
+
+ /*
+ * Ensure that if we asked for PIN originally, our method is consistent
+ * with original request.
+ */
+ if (method & WPS_CONFIG_DISPLAY)
+ method = WPS_CONFIG_KEYPAD;
+ else if (method & WPS_CONFIG_KEYPAD)
+ method = WPS_CONFIG_DISPLAY;
+
+ if (!conncap || !(msg.wps_config_methods & method)) {
+ /*
+ * Reject this "Deferred Accept*
+ * if incompatible conncap or method
+ */
+ reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
+ } else if (!resp_fcap.cpt) {
+ p2p_dbg(p2p,
+ "Incompatible P2PS feature capability CPT bitmask");
+ reject = P2P_SC_FAIL_INCOMPATIBLE_PARAMS;
+ } else if ((remote_conncap & (P2PS_SETUP_NEW | P2PS_SETUP_CLIENT) ||
+ msg.persistent_dev) && conncap != P2PS_SETUP_NEW &&
+ msg.channel_list && msg.channel_list_len &&
+ p2p_peer_channels_check(p2p, &p2p->channels, dev,
+ msg.channel_list,
+ msg.channel_list_len) < 0) {
+ p2p_dbg(p2p,
+ "No common channels in Follow-On Provision Discovery Request");
+ reject = P2P_SC_FAIL_NO_COMMON_CHANNELS;
+ } else {
+ reject = P2P_SC_SUCCESS;
+ }
+
+ dev->oper_freq = 0;
+ if (reject == P2P_SC_SUCCESS || reject == P2P_SC_SUCCESS_DEFERRED) {
+ u8 tmp;
+
+ if (msg.operating_channel)
+ dev->oper_freq =
+ p2p_channel_to_freq(msg.operating_channel[3],
+ msg.operating_channel[4]);
+
+ if ((conncap & P2PS_SETUP_GROUP_OWNER) &&
+ p2p_go_select_channel(p2p, dev, &tmp) < 0)
+ reject = P2P_SC_FAIL_NO_COMMON_CHANNELS;
+ }
+
+ p2p->p2ps_prov->status = reject;
+ p2p->p2ps_prov->conncap = conncap;
+
out:
if (reject == P2P_SC_SUCCESS ||
reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE)
config_methods = msg.wps_config_methods;
else
config_methods = 0;
- resp = p2p_build_prov_disc_resp(p2p, dev, msg.dialog_token, reject,
- config_methods, adv_id,
- msg.group_id, msg.group_id_len,
- msg.persistent_ssid,
- msg.persistent_ssid_len,
- (const u8 *) &resp_fcap,
- sizeof(resp_fcap));
- if (resp == NULL) {
- p2p_parse_free(&msg);
- return;
- }
- p2p_dbg(p2p, "Sending Provision Discovery Response");
- if (rx_freq > 0)
- freq = rx_freq;
- else
- freq = p2p_channel_to_freq(p2p->cfg->reg_class,
- p2p->cfg->channel);
- if (freq < 0) {
- p2p_dbg(p2p, "Unknown regulatory class/channel");
+
+ /*
+ * Send PD Response for an initial PD Request or for follow-on
+ * PD Request with P2P_SC_SUCCESS_DEFERRED status.
+ */
+ if (!msg.status || *msg.status == P2P_SC_SUCCESS_DEFERRED) {
+ resp = p2p_build_prov_disc_resp(p2p, dev, msg.dialog_token,
+ reject, config_methods, adv_id,
+ msg.group_id, msg.group_id_len,
+ msg.persistent_ssid,
+ msg.persistent_ssid_len,
+ (const u8 *) &resp_fcap,
+ sizeof(resp_fcap));
+ if (!resp) {
+ p2p_parse_free(&msg);
+ return;
+ }
+ p2p_dbg(p2p, "Sending Provision Discovery Response");
+ if (rx_freq > 0)
+ freq = rx_freq;
+ else
+ freq = p2p_channel_to_freq(p2p->cfg->reg_class,
+ p2p->cfg->channel);
+ if (freq < 0) {
+ p2p_dbg(p2p, "Unknown regulatory class/channel");
+ wpabuf_free(resp);
+ p2p_parse_free(&msg);
+ return;
+ }
+ p2p->pending_action_state = P2P_PENDING_PD_RESPONSE;
+ if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
+ p2p->cfg->dev_addr,
+ wpabuf_head(resp), wpabuf_len(resp),
+ 50) < 0)
+ p2p_dbg(p2p, "Failed to send Action frame");
+ else
+ p2p->send_action_in_progress = 1;
+
wpabuf_free(resp);
+ }
+
+ if (!dev) {
p2p_parse_free(&msg);
return;
}
- p2p->pending_action_state = P2P_PENDING_PD_RESPONSE;
- if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
- p2p->cfg->dev_addr,
- wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
- p2p_dbg(p2p, "Failed to send Action frame");
- } else
- p2p->send_action_in_progress = 1;
- wpabuf_free(resp);
+ freq = 0;
+ if (reject == P2P_SC_SUCCESS && conncap == P2PS_SETUP_GROUP_OWNER) {
+ freq = p2p_channel_to_freq(p2p->op_reg_class,
+ p2p->op_channel);
+ if (freq < 0)
+ freq = 0;
+ }
if (!p2p->cfg->p2ps_prov_complete) {
/* Don't emit anything */
NULL, adv_id, session_id,
0, 0, msg.persistent_ssid,
msg.persistent_ssid_len,
- 0, 0, NULL, NULL, 0);
+ 0, 0, NULL, NULL, 0, freq,
+ NULL, 0);
} else if (msg.status && *msg.status == P2P_SC_SUCCESS_DEFERRED &&
p2p->p2ps_prov) {
p2p->p2ps_prov->status = reject;
session_id, conncap, 0,
msg.persistent_ssid,
msg.persistent_ssid_len, 0,
- 0, NULL, NULL, 0);
+ 0, NULL, NULL, 0, freq,
+ NULL, 0);
else
p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx,
*msg.status,
msg.persistent_ssid_len, 0,
0, NULL,
(const u8 *) &resp_fcap,
- sizeof(resp_fcap));
+ sizeof(resp_fcap), freq,
+ NULL, 0);
} else if (msg.status && p2p->p2ps_prov) {
p2p->p2ps_prov->status = P2P_SC_SUCCESS;
p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, *msg.status, sa,
msg.persistent_ssid_len,
0, 0, NULL,
(const u8 *) &resp_fcap,
- sizeof(resp_fcap));
+ sizeof(resp_fcap), freq, NULL, 0);
} else if (msg.status) {
} else if (auto_accept && reject == P2P_SC_SUCCESS) {
p2p->cfg->p2ps_prov_complete(p2p->cfg->cb_ctx, P2P_SC_SUCCESS,
msg.persistent_ssid_len,
0, 0, NULL,
(const u8 *) &resp_fcap,
- sizeof(resp_fcap));
+ sizeof(resp_fcap), freq,
+ msg.group_id ?
+ msg.group_id + ETH_ALEN : NULL,
+ msg.group_id ?
+ msg.group_id_len - ETH_ALEN : 0);
} else if (reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE &&
(!msg.session_info || !msg.session_info_len)) {
p2p->p2ps_prov->method = msg.wps_config_methods;
msg.persistent_ssid_len,
0, 1, NULL,
(const u8 *) &resp_fcap,
- sizeof(resp_fcap));
+ sizeof(resp_fcap), freq, NULL, 0);
} else if (reject == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
size_t buf_len = msg.session_info_len;
char *buf = os_malloc(2 * buf_len + 1);
session_id, conncap, passwd_id,
msg.persistent_ssid, msg.persistent_ssid_len,
0, 1, buf,
- (const u8 *) &resp_fcap, sizeof(resp_fcap));
+ (const u8 *) &resp_fcap, sizeof(resp_fcap),
+ freq, NULL, 0);
os_free(buf);
}
msg.group_id, msg.group_id_len);
}
- if (dev && reject == P2P_SC_SUCCESS) {
+ if (reject == P2P_SC_SUCCESS) {
switch (config_methods) {
case WPS_CONFIG_DISPLAY:
dev->wps_prov_info = WPS_CONFIG_KEYPAD;
" with no pending request", MAC2STR(sa));
p2p_parse_free(&msg);
return;
+ } else if (msg.wfd_subelems) {
+ wpabuf_free(dev->info.wfd_subelems);
+ dev->info.wfd_subelems = wpabuf_dup(msg.wfd_subelems);
}
if (dev->dialog_token != msg.dialog_token) {
passwd_id = DEV_PW_P2PS_DEFAULT;
}
- if ((msg.conn_cap || msg.persistent_dev) &&
- (status == P2P_SC_SUCCESS || status == P2P_SC_SUCCESS_DEFERRED) &&
+ if ((status == P2P_SC_SUCCESS || status == P2P_SC_SUCCESS_DEFERRED) &&
p2p->p2ps_prov) {
+ dev->oper_freq = 0;
+
+ /*
+ * Save the reported channel list and operating frequency.
+ * Note that the specification mandates that the responder
+ * should include in the channel list only channels reported by
+ * the initiator, so this is only a sanity check, and if this
+ * fails the flow would continue, although it would probably
+ * fail. Same is true for the operating channel.
+ */
+ if (msg.channel_list && msg.channel_list_len &&
+ p2p_peer_channels_check(p2p, &p2p->channels, dev,
+ msg.channel_list,
+ msg.channel_list_len) < 0)
+ p2p_dbg(p2p, "P2PS PD Response - no common channels");
+
+ if (msg.operating_channel) {
+ if (p2p_channels_includes(&p2p->channels,
+ msg.operating_channel[3],
+ msg.operating_channel[4]) &&
+ p2p_channels_includes(&dev->channels,
+ msg.operating_channel[3],
+ msg.operating_channel[4])) {
+ dev->oper_freq =
+ p2p_channel_to_freq(
+ msg.operating_channel[3],
+ msg.operating_channel[4]);
+ } else {
+ p2p_dbg(p2p,
+ "P2PS PD Response - invalid operating channel");
+ }
+ }
+
if (p2p->cfg->p2ps_prov_complete) {
+ int freq = 0;
+
+ if (conncap == P2PS_SETUP_GROUP_OWNER) {
+ u8 tmp;
+
+ /*
+ * Re-select the operating channel as it is
+ * possible that original channel is no longer
+ * valid. This should not really fail.
+ */
+ if (p2p_go_select_channel(p2p, dev, &tmp) < 0)
+ p2p_dbg(p2p,
+ "P2PS PD channel selection failed");
+
+ freq = p2p_channel_to_freq(p2p->op_reg_class,
+ p2p->op_channel);
+ if (freq < 0)
+ freq = 0;
+ }
+
p2p->cfg->p2ps_prov_complete(
p2p->cfg->cb_ctx, status, sa, adv_mac,
p2p->p2ps_prov->session_mac,
group_mac, adv_id, p2p->p2ps_prov->session_id,
conncap, passwd_id, msg.persistent_ssid,
msg.persistent_ssid_len, 1, 0, NULL,
- msg.feature_cap, msg.feature_cap_len);
+ msg.feature_cap, msg.feature_cap_len, freq,
+ msg.group_id ? msg.group_id + ETH_ALEN : NULL,
+ msg.group_id ? msg.group_id_len - ETH_ALEN : 0);
}
p2ps_prov_free(p2p);
} else if (status != P2P_SC_SUCCESS &&
p2p->cfg->cb_ctx, status, sa, adv_mac,
p2p->p2ps_prov->session_mac,
group_mac, adv_id, p2p->p2ps_prov->session_id,
- 0, 0, NULL, 0, 1, 0, NULL, NULL, 0);
+ 0, 0, NULL, 0, 1, 0, NULL, NULL, 0, 0, NULL, 0);
p2ps_prov_free(p2p);
}
"Building PD Request based on P2PS config method 0x%x status %d --> req_config_methods 0x%x",
p2p->p2ps_prov->method, p2p->p2ps_prov->status,
dev->req_config_methods);
+
+ if (p2p_prepare_channel(p2p, dev, p2p->p2ps_prov->force_freq,
+ p2p->p2ps_prov->pref_freq, 1) < 0)
+ return -1;
}
req = p2p_build_prov_disc_req(p2p, dev, join);
pos = wpabuf_head(wfd);
end = pos + wpabuf_len(wfd);
- while (pos + 3 <= end) {
+ while (end - pos >= 3) {
subelem = *pos++;
len = WPA_GET_BE16(pos);
pos += 2;
- if (pos + len > end)
+ if (len > end - pos)
break;
if (subelem == WFD_SUBELEM_DEVICE_INFO && len >= 6) {
query = p2p_pending_sd_req(p2p, dev);
if (query == NULL)
return -1;
+ if (p2p->state == P2P_SEARCH &&
+ os_memcmp(p2p->sd_query_no_ack, dev->info.p2p_device_addr,
+ ETH_ALEN) == 0) {
+ p2p_dbg(p2p, "Do not start Service Discovery with " MACSTR
+ " due to it being the first no-ACK peer in this search iteration",
+ MAC2STR(dev->info.p2p_device_addr));
+ return -2;
+ }
p2p_dbg(p2p, "Start Service Discovery with " MACSTR,
MAC2STR(dev->info.p2p_device_addr));
pos++;
slen = *pos++;
- next = pos + slen;
- if (next > end || slen < 2) {
+ if (slen > end - pos || slen < 2) {
p2p_dbg(p2p, "Invalid IE in GAS Initial Request");
return;
}
+ next = pos + slen;
pos++; /* skip QueryRespLenLimit and PAME-BI */
if (*pos != ACCESS_NETWORK_QUERY_PROTOCOL) {
pos = next;
/* Query Request */
- if (pos + 2 > end)
+ if (end - pos < 2)
return;
slen = WPA_GET_LE16(pos);
pos += 2;
- if (pos + slen > end)
+ if (slen > end - pos)
return;
end = pos + slen;
/* ANQP Query Request */
- if (pos + 4 > end)
+ if (end - pos < 4)
return;
if (WPA_GET_LE16(pos) != ANQP_VENDOR_SPECIFIC) {
p2p_dbg(p2p, "Unsupported ANQP Info ID %u", WPA_GET_LE16(pos));
slen = WPA_GET_LE16(pos);
pos += 2;
- if (pos + slen > end || slen < 3 + 1) {
+ if (slen > end - pos || slen < 3 + 1) {
p2p_dbg(p2p, "Invalid ANQP Query Request length");
return;
}
}
pos += 4;
- if (pos + 2 > end)
+ if (end - pos < 2)
return;
update_indic = WPA_GET_LE16(pos);
p2p_dbg(p2p, "Service Update Indicator: %u", update_indic);
u8 dialog_token, const struct wpabuf *resp_tlvs)
{
struct wpabuf *resp;
+ size_t max_len;
+
+ /*
+ * In the 60 GHz, we have a smaller maximum frame length for management
+ * frames.
+ */
+ max_len = (freq > 56160) ? 928 : 1400;
/* TODO: fix the length limit to match with the maximum frame length */
- if (wpabuf_len(resp_tlvs) > 1400) {
+ if (wpabuf_len(resp_tlvs) > max_len) {
p2p_dbg(p2p, "SD response long enough to require fragmentation");
if (p2p->sd_resp) {
/*
pos++;
slen = *pos++;
- next = pos + slen;
- if (next > end || slen < 2) {
+ if (slen > end - pos || slen < 2) {
p2p_dbg(p2p, "Invalid IE in GAS Initial Response");
return;
}
+ next = pos + slen;
pos++; /* skip QueryRespLenLimit and PAME-BI */
if (*pos != ACCESS_NETWORK_QUERY_PROTOCOL) {
pos = next;
/* Query Response */
- if (pos + 2 > end) {
+ if (end - pos < 2) {
p2p_dbg(p2p, "Too short Query Response");
return;
}
slen = WPA_GET_LE16(pos);
pos += 2;
p2p_dbg(p2p, "Query Response Length: %d", slen);
- if (pos + slen > end) {
+ if (slen > end - pos) {
p2p_dbg(p2p, "Not enough Query Response data");
return;
}
}
/* ANQP Query Response */
- if (pos + 4 > end)
+ if (end - pos < 4)
return;
if (WPA_GET_LE16(pos) != ANQP_VENDOR_SPECIFIC) {
p2p_dbg(p2p, "Unsupported ANQP Info ID %u", WPA_GET_LE16(pos));
slen = WPA_GET_LE16(pos);
pos += 2;
- if (pos + slen > end || slen < 3 + 1) {
+ if (slen > end - pos || slen < 3 + 1) {
p2p_dbg(p2p, "Invalid ANQP Query Response length");
return;
}
}
pos += 4;
- if (pos + 2 > end)
+ if (end - pos < 2)
return;
update_indic = WPA_GET_LE16(pos);
p2p_dbg(p2p, "Service Update Indicator: %u", update_indic);
{
struct wpabuf *resp;
u8 dialog_token;
- size_t frag_len;
+ size_t frag_len, max_len;
int more = 0;
wpa_hexdump(MSG_DEBUG, "P2P: RX GAS Comeback Request", data, len);
return;
}
+ /*
+ * In the 60 GHz, we have a smaller maximum frame length for management
+ * frames.
+ */
+ max_len = (rx_freq > 56160) ? 928 : 1400;
frag_len = wpabuf_len(p2p->sd_resp) - p2p->sd_resp_pos;
- if (frag_len > 1400) {
- frag_len = 1400;
+ if (frag_len > max_len) {
+ frag_len = max_len;
more = 1;
}
resp = p2p_build_gas_comeback_resp(dialog_token, WLAN_STATUS_SUCCESS,
pos++;
slen = *pos++;
- next = pos + slen;
- if (next > end || slen < 2) {
+ if (slen > end - pos || slen < 2) {
p2p_dbg(p2p, "Invalid IE in GAS Comeback Response");
return;
}
+ next = pos + slen;
pos++; /* skip QueryRespLenLimit and PAME-BI */
if (*pos != ACCESS_NETWORK_QUERY_PROTOCOL) {
pos = next;
/* Query Response */
- if (pos + 2 > end) {
+ if (end - pos < 2) {
p2p_dbg(p2p, "Too short Query Response");
return;
}
slen = WPA_GET_LE16(pos);
pos += 2;
p2p_dbg(p2p, "Query Response Length: %d", slen);
- if (pos + slen > end) {
+ if (slen > end - pos) {
p2p_dbg(p2p, "Not enough Query Response data");
return;
}
}
/* ANQP Query Response */
- if (pos + 4 > end)
+ if (end - pos < 4)
return;
if (WPA_GET_LE16(pos) != ANQP_VENDOR_SPECIFIC) {
p2p_dbg(p2p, "Unsupported ANQP Info ID %u", WPA_GET_LE16(pos));
p2p_dbg(p2p, "Invalid ANQP Query Response length");
return;
}
- if (pos + 4 > end)
+ if (end - pos < 4)
return;
if (WPA_GET_BE32(pos) != P2P_IE_VENDOR_TYPE) {
}
pos += 4;
- if (pos + 2 > end)
+ if (end - pos < 2)
return;
p2p->sd_rx_update_indic = WPA_GET_LE16(pos);
p2p_dbg(p2p, "Service Update Indicator: %u", p2p->sd_rx_update_indic);
#define STATE_MACHINE_DATA struct ieee802_1x_cp_sm
#define STATE_MACHINE_DEBUG_PREFIX "CP"
-static u8 default_cs_id[] = CS_ID_GCM_AES_128;
+static u64 default_cs_id = CS_ID_GCM_AES_128;
/* The variable defined in clause 12 in IEEE Std 802.1X-2010 */
enum connect_type { PENDING, UNAUTHENTICATED, AUTHENTICATED, SECURE };
Boolean elected_self;
u8 *authorization_data1;
enum confidentiality_offset cipher_offset;
- u8 *cipher_suite;
+ u64 cipher_suite;
Boolean new_sak; /* clear by CP */
struct ieee802_1x_mka_ki distributed_ki;
u8 distributed_an;
Boolean replay_protect;
u32 replay_window;
- u8 *current_cipher_suite;
+ u64 current_cipher_suite;
enum confidentiality_offset confidentiality_offset;
Boolean controlled_port_enabled;
static int changed_cipher(struct ieee802_1x_cp_sm *sm)
{
return sm->confidentiality_offset != sm->cipher_offset ||
- os_memcmp(sm->current_cipher_suite, sm->cipher_suite,
- CS_ID_LEN) != 0;
+ sm->current_cipher_suite != sm->cipher_suite;
}
SM_STATE(CP, SECURED)
{
- struct ieee802_1x_cp_conf conf;
-
SM_ENTRY(CP, SECURED);
sm->chgd_server = FALSE;
- ieee802_1x_kay_cp_conf(sm->kay, &conf);
- sm->protect_frames = conf.protect;
- sm->replay_protect = conf.replay_protect;
- sm->validate_frames = conf.validate;
+ sm->protect_frames = sm->kay->macsec_protect;
+ sm->replay_protect = sm->kay->macsec_replay_protect;
+ sm->validate_frames = sm->kay->macsec_validate;
- /* NOTE: now no other than default cipher suiter(AES-GCM-128) */
- os_memcpy(sm->current_cipher_suite, sm->cipher_suite, CS_ID_LEN);
- secy_cp_control_current_cipher_suite(sm->kay, sm->current_cipher_suite,
- CS_ID_LEN);
+ /* NOTE: now no other than default cipher suite (AES-GCM-128) */
+ sm->current_cipher_suite = sm->cipher_suite;
+ secy_cp_control_current_cipher_suite(sm->kay, sm->current_cipher_suite);
sm->confidentiality_offset = sm->cipher_offset;
/**
* ieee802_1x_cp_sm_init -
*/
-struct ieee802_1x_cp_sm * ieee802_1x_cp_sm_init(
- struct ieee802_1x_kay *kay,
- struct ieee802_1x_cp_conf *pcp_conf)
+struct ieee802_1x_cp_sm * ieee802_1x_cp_sm_init(struct ieee802_1x_kay *kay)
{
struct ieee802_1x_cp_sm *sm;
sm->chgd_server = FALSE;
- sm->protect_frames = pcp_conf->protect;
- sm->validate_frames = pcp_conf->validate;
- sm->replay_protect = pcp_conf->replay_protect;
- sm->replay_window = pcp_conf->replay_window;
+ sm->protect_frames = kay->macsec_protect;
+ sm->validate_frames = kay->macsec_validate;
+ sm->replay_protect = kay->macsec_replay_protect;
+ sm->replay_window = kay->macsec_replay_window;
sm->controlled_port_enabled = FALSE;
sm->orx = FALSE;
sm->otx = FALSE;
- sm->cipher_suite = os_zalloc(CS_ID_LEN);
- sm->current_cipher_suite = os_zalloc(CS_ID_LEN);
- if (!sm->cipher_suite || !sm->current_cipher_suite) {
- wpa_printf(MSG_ERROR, "CP-%s: out of memory", __func__);
- os_free(sm->cipher_suite);
- os_free(sm->current_cipher_suite);
- os_free(sm);
- return NULL;
- }
- os_memcpy(sm->current_cipher_suite, default_cs_id, CS_ID_LEN);
- os_memcpy(sm->cipher_suite, default_cs_id, CS_ID_LEN);
+ sm->current_cipher_suite = default_cs_id;
+ sm->cipher_suite = default_cs_id;
sm->cipher_offset = CONFIDENTIALITY_OFFSET_0;
sm->confidentiality_offset = sm->cipher_offset;
sm->transmit_delay = MKA_LIFE_TIME;
eloop_cancel_timeout(ieee802_1x_cp_step_cb, sm, NULL);
os_free(sm->lki);
os_free(sm->oki);
- os_free(sm->cipher_suite);
- os_free(sm->current_cipher_suite);
os_free(sm->authorization_data);
os_free(sm);
}
/**
* ieee802_1x_cp_set_ciphersuite -
*/
-void ieee802_1x_cp_set_ciphersuite(void *cp_ctx, void *pid)
+void ieee802_1x_cp_set_ciphersuite(void *cp_ctx, u64 cs)
{
struct ieee802_1x_cp_sm *sm = cp_ctx;
- os_memcpy(sm->cipher_suite, pid, CS_ID_LEN);
+ sm->cipher_suite = cs;
}
struct ieee802_1x_kay;
struct ieee802_1x_mka_ki;
-struct ieee802_1x_cp_conf {
- Boolean protect;
- Boolean replay_protect;
- enum validate_frames validate;
- u32 replay_window;
-};
-
-
-struct ieee802_1x_cp_sm *
-ieee802_1x_cp_sm_init(struct ieee802_1x_kay *kay,
- struct ieee802_1x_cp_conf *pcp_conf);
+struct ieee802_1x_cp_sm * ieee802_1x_cp_sm_init(struct ieee802_1x_kay *kay);
void ieee802_1x_cp_sm_deinit(struct ieee802_1x_cp_sm *sm);
void ieee802_1x_cp_sm_step(void *cp_ctx);
void ieee802_1x_cp_connect_pending(void *cp_ctx);
void ieee802_1x_cp_signal_chgdserver(void *cp_ctx);
void ieee802_1x_cp_set_electedself(void *cp_ctx, Boolean status);
void ieee802_1x_cp_set_authorizationdata(void *cp_ctx, u8 *pdata, int len);
-void ieee802_1x_cp_set_ciphersuite(void *cp_ctx, void *pid);
+void ieee802_1x_cp_set_ciphersuite(void *cp_ctx, u64 cs);
void ieee802_1x_cp_set_offset(void *cp_ctx, enum confidentiality_offset offset);
void ieee802_1x_cp_signal_newsak(void *cp_ctx);
void ieee802_1x_cp_set_distributedki(void *cp_ctx,
#define PENDING_PN_EXHAUSTION 0xC0000000
+#define MKA_ALIGN_LENGTH(len) (((len) + 0x3) & ~0x3)
+
/* IEEE Std 802.1X-2010, Table 9-1 - MKA Algorithm Agility */
#define MKA_ALGO_AGILITY_2009 { 0x00, 0x80, 0xC2, 0x01 }
static u8 mka_algo_agility[4] = MKA_ALGO_AGILITY_2009;
static struct macsec_ciphersuite cipher_suite_tbl[] = {
/* GCM-AES-128 */
{
- CS_ID_GCM_AES_128,
- CS_NAME_GCM_AES_128,
- MACSEC_CAP_INTEG_AND_CONF_0_30_50,
- 16,
-
- 0 /* index */
+ .id = CS_ID_GCM_AES_128,
+ .name = CS_NAME_GCM_AES_128,
+ .capable = MACSEC_CAP_INTEG_AND_CONF_0_30_50,
+ .sak_len = DEFAULT_SA_KEY_LEN,
+ .index = 0,
},
};
#define CS_TABLE_SIZE (ARRAY_SIZE(cipher_suite_tbl))
static struct mka_alg mka_alg_tbl[] = {
{
- MKA_ALGO_AGILITY_2009,
+ .parameter = MKA_ALGO_AGILITY_2009,
+
/* 128-bit CAK, KEK, ICK, ICV */
- 16, 16, 16, 16,
- ieee802_1x_cak_128bits_aes_cmac,
- ieee802_1x_ckn_128bits_aes_cmac,
- ieee802_1x_kek_128bits_aes_cmac,
- ieee802_1x_ick_128bits_aes_cmac,
- ieee802_1x_icv_128bits_aes_cmac,
-
- 1, /* index */
+ .cak_len = DEFAULT_ICV_LEN,
+ .kek_len = DEFAULT_ICV_LEN,
+ .ick_len = DEFAULT_ICV_LEN,
+ .icv_len = DEFAULT_ICV_LEN,
+
+ .cak_trfm = ieee802_1x_cak_128bits_aes_cmac,
+ .ckn_trfm = ieee802_1x_ckn_128bits_aes_cmac,
+ .kek_trfm = ieee802_1x_kek_128bits_aes_cmac,
+ .ick_trfm = ieee802_1x_ick_128bits_aes_cmac,
+ .icv_hash = ieee802_1x_icv_128bits_aes_cmac,
+
+ .index = 1,
},
};
#define MKA_ALG_TABLE_SIZE (ARRAY_SIZE(mka_alg_tbl))
}
-struct mka_param_body_handler {
- int (*body_tx)(struct ieee802_1x_mka_participant *participant,
- struct wpabuf *buf);
- int (*body_rx)(struct ieee802_1x_mka_participant *participant,
- const u8 *mka_msg, size_t msg_len);
- int (*body_length)(struct ieee802_1x_mka_participant *participant);
- Boolean (*body_present)(struct ieee802_1x_mka_participant *participant);
-};
-
-
static void set_mka_param_body_len(void *body, unsigned int len)
{
struct ieee802_1x_mka_hdr *hdr = body;
}
-static int get_mka_param_body_type(const void *body)
+static u8 get_mka_param_body_type(const void *body)
{
const struct ieee802_1x_mka_hdr *hdr = body;
return hdr->type;
wpa_printf(MSG_DEBUG, "\tPriority......: %d", body->priority);
wpa_printf(MSG_DEBUG, "\tKeySvr........: %d", body->key_server);
wpa_printf(MSG_DEBUG, "\tMACSecDesired.: %d", body->macsec_desired);
- wpa_printf(MSG_DEBUG, "\tMACSecCapable.: %d", body->macsec_capbility);
- wpa_printf(MSG_DEBUG, "\tBody Length...: %d", (int) body_len);
+ wpa_printf(MSG_DEBUG, "\tMACSecCapable.: %d", body->macsec_capability);
+ wpa_printf(MSG_DEBUG, "\tBody Length...: %zu", body_len);
wpa_printf(MSG_DEBUG, "\tSCI MAC.......: " MACSTR,
MAC2STR(body->actor_sci.addr));
wpa_printf(MSG_DEBUG, "\tSCI Port .....: %d",
size_t body_len;
size_t i;
u8 *mi;
- u32 mn;
+ be32 mn;
if (body == NULL)
return;
body_len = get_mka_param_body_len(body);
if (body->type == MKA_LIVE_PEER_LIST) {
wpa_printf(MSG_DEBUG, "*** Live Peer List ***");
- wpa_printf(MSG_DEBUG, "\tBody Length...: %d", (int) body_len);
+ wpa_printf(MSG_DEBUG, "\tBody Length...: %zu", body_len);
} else if (body->type == MKA_POTENTIAL_PEER_LIST) {
wpa_printf(MSG_DEBUG, "*** Potential Live Peer List ***");
- wpa_printf(MSG_DEBUG, "\tBody Length...: %d", (int) body_len);
+ wpa_printf(MSG_DEBUG, "\tBody Length...: %zu", body_len);
}
for (i = 0; i < body_len; i += MI_LEN + sizeof(mn)) {
wpa_printf(MSG_INFO, "\tDistributed AN........: %d", body->dan);
wpa_printf(MSG_INFO, "\tConfidentiality Offset: %d",
body->confid_offset);
- wpa_printf(MSG_INFO, "\tBody Length...........: %d", (int) body_len);
+ wpa_printf(MSG_INFO, "\tBody Length...........: %zu", body_len);
if (!body_len)
return;
return participant;
}
- wpa_printf(MSG_DEBUG, "KaY: principal participant is not founded");
+ wpa_printf(MSG_DEBUG, "KaY: principal participant is not found");
return NULL;
}
/**
- * ieee802_1x_kay_is_in_potential_peer
+ * ieee802_1x_kay_get_potential_peer
*/
-static Boolean
-ieee802_1x_kay_is_in_potential_peer(
+static struct ieee802_1x_kay_peer *
+ieee802_1x_kay_get_potential_peer(
struct ieee802_1x_mka_participant *participant, const u8 *mi)
{
- return get_peer_mi(&participant->potential_peers, mi) != NULL;
+ return get_peer_mi(&participant->potential_peers, mi);
}
/**
- * ieee802_1x_kay_is_in_live_peer
+ * ieee802_1x_kay_get_live_peer
+ */
+static struct ieee802_1x_kay_peer *
+ieee802_1x_kay_get_live_peer(struct ieee802_1x_mka_participant *participant,
+ const u8 *mi)
+{
+ return get_peer_mi(&participant->live_peers, mi);
+}
+
+
+/**
+ * ieee802_1x_kay_is_in_potential_peer
*/
static Boolean
-ieee802_1x_kay_is_in_live_peer(
+ieee802_1x_kay_is_in_potential_peer(
struct ieee802_1x_mka_participant *participant, const u8 *mi)
{
- return get_peer_mi(&participant->live_peers, mi) != NULL;
+ return ieee802_1x_kay_get_potential_peer(participant, mi) != NULL;
}
/**
- * ieee802_1x_kay_is_in_peer
+ * ieee802_1x_kay_is_in_live_peer
*/
static Boolean
-ieee802_1x_kay_is_in_peer(struct ieee802_1x_mka_participant *participant,
- const u8 *mi)
+ieee802_1x_kay_is_in_live_peer(
+ struct ieee802_1x_mka_participant *participant, const u8 *mi)
{
- return ieee802_1x_kay_is_in_live_peer(participant, mi) ||
- ieee802_1x_kay_is_in_potential_peer(participant, mi);
+ return ieee802_1x_kay_get_live_peer(participant, mi) != NULL;
}
{
struct ieee802_1x_kay_peer *peer;
- peer = get_peer_mi(&participant->live_peers, mi);
+ peer = ieee802_1x_kay_get_live_peer(participant, mi);
if (peer)
return peer;
- return get_peer_mi(&participant->potential_peers, mi);
-}
-
-
-/**
- * ieee802_1x_kay_get_live_peer
- */
-static struct ieee802_1x_kay_peer *
-ieee802_1x_kay_get_live_peer(struct ieee802_1x_mka_participant *participant,
- const u8 *mi)
-{
- return get_peer_mi(&participant->live_peers, mi);
+ return ieee802_1x_kay_get_potential_peer(participant, mi);
}
*/
static struct macsec_ciphersuite *
ieee802_1x_kay_get_cipher_suite(struct ieee802_1x_mka_participant *participant,
- u8 *cs_id)
+ const u8 *cs_id)
{
unsigned int i;
+ u64 cs;
+ be64 _cs;
+
+ os_memcpy(&_cs, cs_id, CS_ID_LEN);
+ cs = be_to_host64(_cs);
for (i = 0; i < CS_TABLE_SIZE; i++) {
- if (os_memcmp(cipher_suite_tbl[i].id, cs_id, CS_ID_LEN) == 0)
- break;
+ if (cipher_suite_tbl[i].id == cs)
+ return &cipher_suite_tbl[i];
}
- if (i >= CS_TABLE_SIZE)
- return NULL;
- return &cipher_suite_tbl[i];
+ return NULL;
+}
+
+
+static Boolean sci_equal(const struct ieee802_1x_mka_sci *a,
+ const struct ieee802_1x_mka_sci *b)
+{
+ return os_memcmp(a, b, sizeof(struct ieee802_1x_mka_sci)) == 0;
}
dl_list_for_each(peer, &participant->live_peers,
struct ieee802_1x_kay_peer, list) {
- if (os_memcmp(&peer->sci, sci, sizeof(peer->sci)) == 0)
+ if (sci_equal(&peer->sci, sci))
return peer;
}
dl_list_for_each(peer, &participant->potential_peers,
struct ieee802_1x_kay_peer, list) {
- if (os_memcmp(&peer->sci, sci, sizeof(peer->sci)) == 0)
+ if (sci_equal(&peer->sci, sci))
return peer;
}
dl_list_add(&psc->sa_list, &psa->list);
wpa_printf(MSG_DEBUG,
- "KaY: Create receive SA(AN: %d lowest_pn: %u of SC(channel: %d)",
- (int) an, lowest_pn, psc->channel);
+ "KaY: Create receive SA(AN: %hhu lowest_pn: %u of SC(channel: %d)",
+ an, lowest_pn, psc->channel);
return psa;
}
{
psa->pkey = NULL;
wpa_printf(MSG_DEBUG,
- "KaY: Delete receive SA(an: %d) of SC(channel: %d)",
- psa->an, psa->sc->channel);
+ "KaY: Delete receive SA(an: %hhu) of SC",
+ psa->an);
dl_list_del(&psa->list);
os_free(psa);
}
}
-/**
- * ieee802_1x_kay_create_live_peer
- */
+static void ieee802_1x_kay_dump_peer(struct ieee802_1x_kay_peer *peer)
+{
+ wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi, sizeof(peer->mi));
+ wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn);
+ wpa_hexdump(MSG_DEBUG, "\tSCI Addr: ", peer->sci.addr, ETH_ALEN);
+ wpa_printf(MSG_DEBUG, "\tPort: %d", peer->sci.port);
+}
+
+
static struct ieee802_1x_kay_peer *
-ieee802_1x_kay_create_live_peer(struct ieee802_1x_mka_participant *participant,
- u8 *mi, u32 mn)
+ieee802_1x_kay_create_peer(const u8 *mi, u32 mn)
{
struct ieee802_1x_kay_peer *peer;
- struct receive_sc *rxsc;
- u32 sc_ch = 0;
peer = os_zalloc(sizeof(*peer));
- if (peer == NULL) {
+ if (!peer) {
wpa_printf(MSG_ERROR, "KaY-%s: out of memory", __func__);
return NULL;
}
peer->mn = mn;
peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
peer->sak_used = FALSE;
+
+ return peer;
+}
+
+
+/**
+ * ieee802_1x_kay_create_live_peer
+ */
+static struct ieee802_1x_kay_peer *
+ieee802_1x_kay_create_live_peer(struct ieee802_1x_mka_participant *participant,
+ const u8 *mi, u32 mn)
+{
+ struct ieee802_1x_kay_peer *peer;
+ struct receive_sc *rxsc;
+ u32 sc_ch = 0;
+
+ peer = ieee802_1x_kay_create_peer(mi, mn);
+ if (!peer)
+ return NULL;
+
os_memcpy(&peer->sci, &participant->current_peer_sci,
sizeof(peer->sci));
- dl_list_add(&participant->live_peers, &peer->list);
secy_get_available_receive_sc(participant->kay, &sc_ch);
rxsc = ieee802_1x_kay_init_receive_sc(&peer->sci, sc_ch);
- if (!rxsc)
+ if (!rxsc) {
+ os_free(peer);
return NULL;
+ }
+ dl_list_add(&participant->live_peers, &peer->list);
dl_list_add(&participant->rxsc_list, &rxsc->list);
secy_create_receive_sc(participant->kay, rxsc);
wpa_printf(MSG_DEBUG, "KaY: Live peer created");
- wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi, sizeof(peer->mi));
- wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn);
- wpa_hexdump(MSG_DEBUG, "\tSCI Addr: ", peer->sci.addr, ETH_ALEN);
- wpa_printf(MSG_DEBUG, "\tPort: %d", peer->sci.port);
+ ieee802_1x_kay_dump_peer(peer);
return peer;
}
{
struct ieee802_1x_kay_peer *peer;
- peer = os_zalloc(sizeof(*peer));
- if (peer == NULL) {
- wpa_printf(MSG_ERROR, "KaY-%s: out of memory", __func__);
+ peer = ieee802_1x_kay_create_peer(mi, mn);
+ if (!peer)
return NULL;
- }
-
- os_memcpy(peer->mi, mi, MI_LEN);
- peer->mn = mn;
- peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
- peer->sak_used = FALSE;
dl_list_add(&participant->potential_peers, &peer->list);
wpa_printf(MSG_DEBUG, "KaY: potential peer created");
- wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi, sizeof(peer->mi));
- wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn);
- wpa_hexdump(MSG_DEBUG, "\tSCI Addr: ", peer->sci.addr, ETH_ALEN);
- wpa_printf(MSG_DEBUG, "\tPort: %d", peer->sci.port);
+ ieee802_1x_kay_dump_peer(peer);
return peer;
}
struct receive_sc *rxsc;
u32 sc_ch = 0;
- dl_list_for_each(peer, &participant->potential_peers,
- struct ieee802_1x_kay_peer, list) {
- if (os_memcmp(peer->mi, mi, MI_LEN) == 0)
- break;
- }
+ peer = ieee802_1x_kay_get_potential_peer(participant, mi);
+
+ rxsc = ieee802_1x_kay_init_receive_sc(&participant->current_peer_sci,
+ sc_ch);
+ if (!rxsc)
+ return NULL;
os_memcpy(&peer->sci, &participant->current_peer_sci,
sizeof(peer->sci));
peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
wpa_printf(MSG_DEBUG, "KaY: move potential peer to live peer");
- wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi, sizeof(peer->mi));
- wpa_printf(MSG_DEBUG, "\tMN: %d", peer->mn);
- wpa_hexdump(MSG_DEBUG, "\tSCI Addr: ", peer->sci.addr, ETH_ALEN);
- wpa_printf(MSG_DEBUG, "\tPort: %d", peer->sci.port);
+ ieee802_1x_kay_dump_peer(peer);
dl_list_del(&peer->list);
dl_list_add_tail(&participant->live_peers, &peer->list);
secy_get_available_receive_sc(participant->kay, &sc_ch);
- rxsc = ieee802_1x_kay_init_receive_sc(&peer->sci, sc_ch);
- if (!rxsc)
- return NULL;
-
dl_list_add(&participant->rxsc_list, &rxsc->list);
secy_create_receive_sc(participant->kay, rxsc);
length = sizeof(struct ieee802_1x_mka_basic_body);
length += participant->ckn.len;
- return (length + 0x3) & ~0x3;
+ return MKA_ALIGN_LENGTH(length);
}
body->key_server = participant->can_be_key_server;
body->macsec_desired = kay->macsec_desired;
- body->macsec_capbility = kay->macsec_capable;
+ body->macsec_capability = kay->macsec_capable;
set_mka_param_body_len(body, length - MKA_HDR_LEN);
os_memcpy(body->actor_sci.addr, kay->actor_sci.addr,
sizeof(kay->actor_sci.addr));
- body->actor_sci.port = host_to_be16(kay->actor_sci.port);
+ body->actor_sci.port = kay->actor_sci.port;
os_memcpy(body->actor_mi, participant->mi, sizeof(body->actor_mi));
participant->mn = participant->mn + 1;
body->actor_mn = host_to_be32(participant->mn);
- os_memcpy(body->algo_agility, participant->kay->algo_agility,
+ os_memcpy(body->algo_agility, kay->algo_agility,
sizeof(body->algo_agility));
os_memcpy(body->ckn, participant->ckn.name, participant->ckn.len);
}
+static Boolean
+reset_participant_mi(struct ieee802_1x_mka_participant *participant)
+{
+ if (os_get_random(participant->mi, sizeof(participant->mi)) < 0)
+ return FALSE;
+ participant->mn = 0;
+
+ return TRUE;
+}
+
+
/**
* ieee802_1x_mka_decode_basic_body -
*/
/* If the peer's MI is my MI, I will choose new MI */
if (os_memcmp(body->actor_mi, participant->mi, MI_LEN) == 0) {
- if (os_get_random(participant->mi, sizeof(participant->mi)) < 0)
+ if (!reset_participant_mi(participant))
return NULL;
- participant->mn = 0;
}
os_memcpy(participant->current_peer_id.mi, body->actor_mi, MI_LEN);
- participant->current_peer_id.mn = be_to_host32(body->actor_mn);
+ participant->current_peer_id.mn = body->actor_mn;
os_memcpy(participant->current_peer_sci.addr, body->actor_sci.addr,
sizeof(participant->current_peer_sci.addr));
- participant->current_peer_sci.port = be_to_host16(body->actor_sci.port);
+ participant->current_peer_sci.port = body->actor_sci.port;
/* handler peer */
peer = ieee802_1x_kay_get_peer(participant, body->actor_mi);
return NULL;
peer->macsec_desired = body->macsec_desired;
- peer->macsec_capbility = body->macsec_capbility;
+ peer->macsec_capability = body->macsec_capability;
peer->is_key_server = (Boolean) body->key_server;
peer->key_server_priority = body->priority;
} else if (peer->mn < be_to_host32(body->actor_mn)) {
peer->mn = be_to_host32(body->actor_mn);
peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
peer->macsec_desired = body->macsec_desired;
- peer->macsec_capbility = body->macsec_capbility;
+ peer->macsec_capability = body->macsec_capability;
peer->is_key_server = (Boolean) body->key_server;
peer->key_server_priority = body->priority;
} else {
struct ieee802_1x_kay_peer, list)
len += sizeof(struct ieee802_1x_mka_peer_id);
- return (len + 0x3) & ~0x3;
+ return MKA_ALIGN_LENGTH(len);
}
sizeof(struct ieee802_1x_mka_peer_id));
os_memcpy(body_peer->mi, peer->mi, MI_LEN);
body_peer->mn = host_to_be32(peer->mn);
- body_peer++;
}
ieee802_1x_mka_dump_peer_body(body);
struct ieee802_1x_kay_peer, list)
len += sizeof(struct ieee802_1x_mka_peer_id);
- return (len + 0x3) & ~0x3;
+ return MKA_ALIGN_LENGTH(len);
}
sizeof(struct ieee802_1x_mka_peer_id));
os_memcpy(body_peer->mi, peer->mi, MI_LEN);
body_peer->mn = host_to_be32(peer->mn);
- body_peer++;
}
ieee802_1x_mka_dump_peer_body(body);
ieee802_1x_mka_i_in_peerlist(struct ieee802_1x_mka_participant *participant,
const u8 *mka_msg, size_t msg_len)
{
- Boolean included = FALSE;
struct ieee802_1x_mka_hdr *hdr;
size_t body_len;
size_t left_len;
- int body_type;
- u32 peer_mn;
- const u8 *peer_mi;
+ u8 body_type;
const u8 *pos;
size_t i;
- pos = mka_msg;
- left_len = msg_len;
- while (left_len > (MKA_HDR_LEN + DEFAULT_ICV_LEN)) {
+ for (pos = mka_msg, left_len = msg_len;
+ left_len > MKA_HDR_LEN + DEFAULT_ICV_LEN;
+ left_len -= body_len + MKA_HDR_LEN,
+ pos += body_len + MKA_HDR_LEN) {
hdr = (struct ieee802_1x_mka_hdr *) pos;
body_len = get_mka_param_body_len(hdr);
body_type = get_mka_param_body_type(hdr);
if (body_type != MKA_LIVE_PEER_LIST &&
body_type != MKA_POTENTIAL_PEER_LIST)
- goto SKIP_PEER;
+ continue;
ieee802_1x_mka_dump_peer_body(
(struct ieee802_1x_mka_peer_body *)pos);
if (left_len < (MKA_HDR_LEN + body_len + DEFAULT_ICV_LEN)) {
wpa_printf(MSG_ERROR,
- "KaY: MKA Peer Packet Body Length (%d bytes) is less than the Parameter Set Header Length (%d bytes) + the Parameter Set Body Length (%d bytes) + %d bytes of ICV",
- (int) left_len, (int) MKA_HDR_LEN,
- (int) body_len, DEFAULT_ICV_LEN);
- goto SKIP_PEER;
+ "KaY: MKA Peer Packet Body Length (%zu bytes) is less than the Parameter Set Header Length (%zu bytes) + the Parameter Set Body Length (%zu bytes) + %d bytes of ICV",
+ left_len, MKA_HDR_LEN,
+ body_len, DEFAULT_ICV_LEN);
+ continue;
}
if ((body_len % 16) != 0) {
wpa_printf(MSG_ERROR,
- "KaY: MKA Peer Packet Body Length (%d bytes) should multiple of 16 octets",
- (int) body_len);
- goto SKIP_PEER;
- }
-
- for (i = 0; i < body_len; i += MI_LEN + sizeof(peer_mn)) {
- peer_mi = MKA_HDR_LEN + pos + i;
- os_memcpy(&peer_mn, peer_mi + MI_LEN, sizeof(peer_mn));
- peer_mn = be_to_host32(peer_mn);
- if (os_memcmp(peer_mi, participant->mi, MI_LEN) == 0 &&
- peer_mn == participant->mn) {
- included = TRUE;
- break;
- }
+ "KaY: MKA Peer Packet Body Length (%zu bytes) should be a multiple of 16 octets",
+ body_len);
+ continue;
}
- if (included)
- return TRUE;
+ for (i = 0; i < body_len;
+ i += sizeof(struct ieee802_1x_mka_peer_id)) {
+ const struct ieee802_1x_mka_peer_id *peer_mi;
-SKIP_PEER:
- left_len -= body_len + MKA_HDR_LEN;
- pos += body_len + MKA_HDR_LEN;
+ peer_mi = (const struct ieee802_1x_mka_peer_id *)
+ (pos + MKA_HDR_LEN + i);
+ if (os_memcmp(peer_mi->mi, participant->mi,
+ MI_LEN) == 0 &&
+ be_to_host32(peer_mi->mn) == participant->mn)
+ return TRUE;
+ }
}
return FALSE;
const struct ieee802_1x_mka_hdr *hdr;
struct ieee802_1x_kay_peer *peer;
size_t body_len;
- u32 peer_mn;
- const u8 *peer_mi;
size_t i;
Boolean is_included;
hdr = (const struct ieee802_1x_mka_hdr *) peer_msg;
body_len = get_mka_param_body_len(hdr);
+ if (body_len % 16 != 0) {
+ wpa_printf(MSG_ERROR,
+ "KaY: MKA Peer Packet Body Length (%zu bytes) should be a multiple of 16 octets",
+ body_len);
+ return -1;
+ }
+
+ for (i = 0; i < body_len; i += sizeof(struct ieee802_1x_mka_peer_id)) {
+ const struct ieee802_1x_mka_peer_id *peer_mi;
+ u32 peer_mn;
- for (i = 0; i < body_len; i += MI_LEN + sizeof(peer_mn)) {
- peer_mi = MKA_HDR_LEN + peer_msg + i;
- os_memcpy(&peer_mn, peer_mi + MI_LEN, sizeof(peer_mn));
- peer_mn = be_to_host32(peer_mn);
+ peer_mi = (const struct ieee802_1x_mka_peer_id *)
+ (peer_msg + MKA_HDR_LEN + i);
+ peer_mn = be_to_host32(peer_mi->mn);
/* it is myself */
if (os_memcmp(peer_mi, participant->mi, MI_LEN) == 0) {
/* My message id is used by other participant */
- if (peer_mn > participant->mn) {
- if (os_get_random(participant->mi,
- sizeof(participant->mi)) < 0)
- wpa_printf(MSG_DEBUG,
- "KaY: Could not update mi");
- participant->mn = 0;
- }
+ if (peer_mn > participant->mn &&
+ !reset_participant_mi(participant))
+ wpa_printf(MSG_DEBUG, "KaY: Could not update mi");
continue;
}
+
if (!is_included)
continue;
- peer = ieee802_1x_kay_get_peer(participant, peer_mi);
- if (NULL != peer) {
+ peer = ieee802_1x_kay_get_peer(participant, peer_mi->mi);
+ if (peer) {
peer->mn = peer_mn;
peer->expire = time(NULL) + MKA_LIFE_TIME / 1000;
- } else {
- if (!ieee802_1x_kay_create_potential_peer(
- participant, peer_mi, peer_mn)) {
- return -1;
- }
+ } else if (!ieee802_1x_kay_create_potential_peer(
+ participant, peer_mi->mi, peer_mn)) {
+ return -1;
}
}
struct ieee802_1x_mka_participant *participant,
const u8 *peer_msg, size_t msg_len)
{
- struct ieee802_1x_mka_hdr *hdr;
+ const struct ieee802_1x_mka_hdr *hdr;
size_t body_len;
- u32 peer_mn;
- const u8 *peer_mi;
size_t i;
- hdr = (struct ieee802_1x_mka_hdr *) peer_msg;
+ hdr = (const struct ieee802_1x_mka_hdr *) peer_msg;
body_len = get_mka_param_body_len(hdr);
+ if (body_len % 16 != 0) {
+ wpa_printf(MSG_ERROR,
+ "KaY: MKA Peer Packet Body Length (%zu bytes) should be a multiple of 16 octets",
+ body_len);
+ return -1;
+ }
- for (i = 0; i < body_len; i += MI_LEN + sizeof(peer_mn)) {
- peer_mi = MKA_HDR_LEN + peer_msg + i;
- os_memcpy(&peer_mn, peer_mi + MI_LEN, sizeof(peer_mn));
- peer_mn = be_to_host32(peer_mn);
+ for (i = 0; i < body_len; i += sizeof(struct ieee802_1x_mka_peer_id)) {
+ const struct ieee802_1x_mka_peer_id *peer_mi;
+ u32 peer_mn;
+
+ peer_mi = (struct ieee802_1x_mka_peer_id *)
+ (peer_msg + MKA_HDR_LEN + i);
+ peer_mn = be_to_host32(peer_mi->mn);
/* it is myself */
if (os_memcmp(peer_mi, participant->mi, MI_LEN) == 0) {
/* My message id is used by other participant */
- if (peer_mn > participant->mn) {
- if (os_get_random(participant->mi,
- sizeof(participant->mi)) < 0)
- wpa_printf(MSG_DEBUG,
- "KaY: Could not update mi");
- participant->mn = 0;
- }
+ if (peer_mn > participant->mn &&
+ !reset_participant_mi(participant))
+ wpa_printf(MSG_DEBUG, "KaY: Could not update mi");
continue;
}
}
ieee802_1x_mka_sak_use_body_present(
struct ieee802_1x_mka_participant *participant)
{
- if (participant->to_use_sak)
- return TRUE;
- else
- return FALSE;
+ return participant->to_use_sak;
}
if (participant->kay->macsec_desired && participant->advised_desired)
length = sizeof(struct ieee802_1x_mka_sak_use_body);
- else
- length = MKA_HDR_LEN;
- length = (length + 0x3) & ~0x3;
-
- return length;
+ return MKA_ALIGN_LENGTH(length);
}
struct wpabuf *buf)
{
struct ieee802_1x_mka_sak_use_body *body;
+ struct ieee802_1x_kay *kay = participant->kay;
unsigned int length;
u32 pn = 1;
length = ieee802_1x_mka_get_sak_use_length(participant);
- body = wpabuf_put(buf, sizeof(struct ieee802_1x_mka_sak_use_body));
+ body = wpabuf_put(buf, length);
body->type = MKA_SAK_USE;
set_mka_param_body_len(body, length - MKA_HDR_LEN);
}
/* data protect, lowest accept packet number */
- body->delay_protect = participant->kay->macsec_replay_protect;
+ body->delay_protect = kay->macsec_replay_protect;
pn = ieee802_1x_mka_get_lpn(participant, &participant->lki);
- if (pn > participant->kay->pn_exhaustion) {
+ if (pn > kay->pn_exhaustion) {
wpa_printf(MSG_WARNING, "KaY: My LPN exhaustion");
if (participant->is_key_server)
participant->new_sak = TRUE;
body->olpn = host_to_be32(pn);
/* plain tx, plain rx */
- if (participant->kay->macsec_protect)
- body->ptx = FALSE;
- else
- body->ptx = TRUE;
-
- if (participant->kay->macsec_validate == Strict)
- body->prx = FALSE;
- else
- body->prx = TRUE;
+ body->ptx = !kay->macsec_protect;
+ body->prx = kay->macsec_validate != Strict;
/* latest key: rx, tx, key server member identifier key number */
body->lan = participant->lan;
- os_memcpy(body->lsrv_mi, participant->lki.mi,
- sizeof(body->lsrv_mi));
+ os_memcpy(body->lsrv_mi, participant->lki.mi, sizeof(body->lsrv_mi));
body->lkn = host_to_be32(participant->lki.kn);
body->lrx = participant->lrx;
body->ltx = participant->ltx;
/* set CP's variable */
if (body->ltx) {
- if (!participant->kay->tx_enable)
- participant->kay->tx_enable = TRUE;
-
- if (!participant->kay->port_enable)
- participant->kay->port_enable = TRUE;
- }
- if (body->lrx) {
- if (!participant->kay->rx_enable)
- participant->kay->rx_enable = TRUE;
+ kay->tx_enable = TRUE;
+ kay->port_enable = TRUE;
}
+ if (body->lrx)
+ kay->rx_enable = TRUE;
ieee802_1x_mka_dump_sak_use_body(body);
return 0;
struct ieee802_1x_mka_ki ki;
u32 lpn;
Boolean all_receiving;
- Boolean founded;
+ Boolean found;
+ struct ieee802_1x_kay *kay = participant->kay;
if (!participant->principal) {
wpa_printf(MSG_WARNING, "KaY: Participant is not principal");
if ((body_len != 0) && (body_len < 40)) {
wpa_printf(MSG_ERROR,
- "KaY: MKA Use SAK Packet Body Length (%d bytes) should be 0, 40, or more octets",
- (int) body_len);
+ "KaY: MKA Use SAK Packet Body Length (%zu bytes) should be 0, 40, or more octets",
+ body_len);
return -1;
}
/* check latest key is valid */
if (body->ltx || body->lrx) {
- founded = FALSE;
+ found = FALSE;
os_memcpy(ki.mi, body->lsrv_mi, sizeof(ki.mi));
- ki.kn = ntohl(body->lkn);
+ ki.kn = be_to_host32(body->lkn);
dl_list_for_each(sa_key, &participant->sak_list,
struct data_key, list) {
if (is_ki_equal(&sa_key->key_identifier, &ki)) {
- founded = TRUE;
+ found = TRUE;
break;
}
}
- if (!founded) {
+ if (!found) {
wpa_printf(MSG_WARNING, "KaY: Latest key is invalid");
return -1;
}
if (os_memcmp(participant->lki.mi, body->lsrv_mi,
sizeof(participant->lki.mi)) == 0 &&
- ntohl(body->lkn) == participant->lki.kn &&
+ be_to_host32(body->lkn) == participant->lki.kn &&
body->lan == participant->lan) {
peer->sak_used = TRUE;
}
if (body->ltx && peer->is_key_server) {
- ieee802_1x_cp_set_servertransmitting(
- participant->kay->cp, TRUE);
- ieee802_1x_cp_sm_step(participant->kay->cp);
+ ieee802_1x_cp_set_servertransmitting(kay->cp, TRUE);
+ ieee802_1x_cp_sm_step(kay->cp);
}
}
if (body->otx || body->orx) {
if (os_memcmp(participant->oki.mi, body->osrv_mi,
sizeof(participant->oki.mi)) != 0 ||
- ntohl(body->okn) != participant->oki.kn ||
+ be_to_host32(body->okn) != participant->oki.kn ||
body->oan != participant->oan) {
wpa_printf(MSG_WARNING, "KaY: Old key is invalid");
return -1;
}
/* TODO: how to set the MACsec hardware when delay_protect is true */
- if (body->delay_protect && (!ntohl(body->llpn) || !ntohl(body->olpn))) {
+ if (body->delay_protect &&
+ (!be_to_host32(body->llpn) || !be_to_host32(body->olpn))) {
wpa_printf(MSG_WARNING,
"KaY: Lowest packet number should greater than 0 when delay_protect is TRUE");
return -1;
}
if (all_receiving) {
participant->to_dist_sak = FALSE;
- ieee802_1x_cp_set_allreceiving(participant->kay->cp, TRUE);
- ieee802_1x_cp_sm_step(participant->kay->cp);
+ ieee802_1x_cp_set_allreceiving(kay->cp, TRUE);
+ ieee802_1x_cp_sm_step(kay->cp);
}
/* if i'm key server, and detects peer member pn exhaustion, rekey.*/
- lpn = ntohl(body->llpn);
- if (lpn > participant->kay->pn_exhaustion) {
+ lpn = be_to_host32(body->llpn);
+ if (lpn > kay->pn_exhaustion) {
if (participant->is_key_server) {
participant->new_sak = TRUE;
wpa_printf(MSG_WARNING, "KaY: Peer LPN exhaustion");
}
}
- founded = FALSE;
+ found = FALSE;
dl_list_for_each(txsa, &participant->txsc->sa_list,
struct transmit_sa, list) {
if (sa_key != NULL && txsa->pkey == sa_key) {
- founded = TRUE;
+ found = TRUE;
break;
}
}
- if (!founded) {
+ if (!found) {
wpa_printf(MSG_WARNING, "KaY: Can't find txsa");
return -1;
}
/* FIXME: Secy creates txsa with default npn. If MKA detected Latest Key
* npn is larger than txsa's npn, set it to txsa.
*/
- secy_get_transmit_next_pn(participant->kay, txsa);
+ secy_get_transmit_next_pn(kay, txsa);
if (lpn > txsa->next_pn) {
- secy_set_transmit_next_pn(participant->kay, txsa);
+ secy_set_transmit_next_pn(kay, txsa);
wpa_printf(MSG_INFO, "KaY: update lpn =0x%x", lpn);
}
ieee802_1x_mka_dist_sak_body_present(
struct ieee802_1x_mka_participant *participant)
{
- if (!participant->to_dist_sak || !participant->new_key)
- return FALSE;
-
- return TRUE;
+ return participant->to_dist_sak && participant->new_key;
}
ieee802_1x_mka_get_dist_sak_length(
struct ieee802_1x_mka_participant *participant)
{
- int length;
- int cs_index = participant->kay->macsec_csindex;
+ int length = MKA_HDR_LEN;
+ unsigned int cs_index = participant->kay->macsec_csindex;
- if (participant->advised_desired) {
+ if (participant->advised_desired && cs_index < CS_TABLE_SIZE) {
length = sizeof(struct ieee802_1x_mka_dist_sak_body);
if (cs_index != DEFAULT_CS_INDEX)
length += CS_ID_LEN;
length += cipher_suite_tbl[cs_index].sak_len + 8;
- } else {
- length = MKA_HDR_LEN;
}
- length = (length + 0x3) & ~0x3;
- return length;
+ return MKA_ALIGN_LENGTH(length);
}
struct ieee802_1x_mka_dist_sak_body *body;
struct data_key *sak;
unsigned int length;
- int cs_index;
+ unsigned int cs_index;
int sak_pos;
length = ieee802_1x_mka_get_dist_sak_length(participant);
body->kn = host_to_be32(sak->key_identifier.kn);
cs_index = participant->kay->macsec_csindex;
sak_pos = 0;
+ if (cs_index >= CS_TABLE_SIZE)
+ return -1;
if (cs_index != DEFAULT_CS_INDEX) {
- os_memcpy(body->sak, cipher_suite_tbl[cs_index].id, CS_ID_LEN);
+ be64 cs;
+
+ cs = host_to_be64(cipher_suite_tbl[cs_index].id);
+ os_memcpy(body->sak, &cs, CS_ID_LEN);
sak_pos = CS_ID_LEN;
}
if (aes_wrap(participant->kek.key, 16,
/**
* ieee802_1x_kay_init_data_key -
*/
-static struct data_key *
-ieee802_1x_kay_init_data_key(const struct key_conf *conf)
+static void ieee802_1x_kay_init_data_key(struct data_key *pkey)
{
- struct data_key *pkey;
-
- if (!conf)
- return NULL;
-
- pkey = os_zalloc(sizeof(*pkey));
- if (pkey == NULL) {
- wpa_printf(MSG_ERROR, "%s: out of memory", __func__);
- return NULL;
- }
-
- pkey->key = os_zalloc(conf->key_len);
- if (pkey->key == NULL) {
- wpa_printf(MSG_ERROR, "%s: out of memory", __func__);
- os_free(pkey);
- return NULL;
- }
-
- os_memcpy(pkey->key, conf->key, conf->key_len);
- os_memcpy(&pkey->key_identifier, &conf->ki,
- sizeof(pkey->key_identifier));
- pkey->confidentiality_offset = conf->offset;
- pkey->an = conf->an;
- pkey->transmits = conf->tx;
- pkey->receives = conf->rx;
+ pkey->transmits = TRUE;
+ pkey->receives = TRUE;
os_get_time(&pkey->created_time);
pkey->user = 1;
-
- return pkey;
}
struct ieee802_1x_kay_peer *peer;
struct macsec_ciphersuite *cs;
size_t body_len;
- struct key_conf *conf;
struct data_key *sa_key = NULL;
- struct ieee802_1x_mka_ki sak_ki;
int sak_len;
u8 *wrap_sak;
u8 *unwrap_sak;
+ struct ieee802_1x_kay *kay = participant->kay;
hdr = (struct ieee802_1x_mka_hdr *) mka_msg;
body_len = get_mka_param_body_len(hdr);
if ((body_len != 0) && (body_len != 28) && (body_len < 36)) {
wpa_printf(MSG_ERROR,
- "KaY: MKA Use SAK Packet Body Length (%d bytes) should be 0, 28, 36, or more octets",
- (int) body_len);
+ "KaY: MKA Use SAK Packet Body Length (%zu bytes) should be 0, 28, 36, or more octets",
+ body_len);
return -1;
}
"KaY: I can't accept the distributed SAK as myself is key server ");
return -1;
}
- if (!participant->kay->macsec_desired ||
- participant->kay->macsec_capable == MACSEC_CAP_NOT_IMPLEMENTED) {
+ if (!kay->macsec_desired ||
+ kay->macsec_capable == MACSEC_CAP_NOT_IMPLEMENTED) {
wpa_printf(MSG_ERROR,
"KaY: I am not MACsec-desired or without MACsec capable");
return -1;
"KaY: The key server is not in my live peers list");
return -1;
}
- if (os_memcmp(&participant->kay->key_server_sci,
- &peer->sci, sizeof(struct ieee802_1x_mka_sci)) != 0) {
+ if (!sci_equal(&kay->key_server_sci, &peer->sci)) {
wpa_printf(MSG_ERROR, "KaY: The key server is not elected");
return -1;
}
+
if (body_len == 0) {
- participant->kay->authenticated = TRUE;
- participant->kay->secured = FALSE;
- participant->kay->failed = FALSE;
+ kay->authenticated = TRUE;
+ kay->secured = FALSE;
+ kay->failed = FALSE;
participant->advised_desired = FALSE;
- ieee802_1x_cp_connect_authenticated(participant->kay->cp);
- ieee802_1x_cp_sm_step(participant->kay->cp);
+ ieee802_1x_cp_connect_authenticated(kay->cp);
+ ieee802_1x_cp_sm_step(kay->cp);
wpa_printf(MSG_WARNING, "KaY:The Key server advise no MACsec");
participant->to_use_sak = TRUE;
return 0;
}
+
participant->advised_desired = TRUE;
- participant->kay->authenticated = FALSE;
- participant->kay->secured = TRUE;
- participant->kay->failed = FALSE;
- ieee802_1x_cp_connect_secure(participant->kay->cp);
- ieee802_1x_cp_sm_step(participant->kay->cp);
+ kay->authenticated = FALSE;
+ kay->secured = TRUE;
+ kay->failed = FALSE;
+ ieee802_1x_cp_connect_secure(kay->cp);
+ ieee802_1x_cp_sm_step(kay->cp);
body = (struct ieee802_1x_mka_dist_sak_body *)mka_msg;
ieee802_1x_mka_dump_dist_sak_body(body);
return 0;
}
}
+
if (body_len == 28) {
sak_len = DEFAULT_SA_KEY_LEN;
wrap_sak = body->sak;
- participant->kay->macsec_csindex = DEFAULT_CS_INDEX;
+ kay->macsec_csindex = DEFAULT_CS_INDEX;
+ cs = &cipher_suite_tbl[kay->macsec_csindex];
} else {
cs = ieee802_1x_kay_get_cipher_suite(participant, body->sak);
if (!cs) {
}
sak_len = cs->sak_len;
wrap_sak = body->sak + CS_ID_LEN;
- participant->kay->macsec_csindex = cs->index;
+ kay->macsec_csindex = cs->index;
}
unwrap_sak = os_zalloc(sak_len);
}
wpa_hexdump(MSG_DEBUG, "\tAES Key Unwrap of SAK:", unwrap_sak, sak_len);
- conf = os_zalloc(sizeof(*conf));
- if (!conf) {
- wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
- os_free(unwrap_sak);
- return -1;
- }
- conf->key_len = sak_len;
-
- conf->key = os_zalloc(conf->key_len);
- if (!conf->key) {
- wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
+ sa_key = os_zalloc(sizeof(*sa_key));
+ if (!sa_key) {
os_free(unwrap_sak);
- os_free(conf);
return -1;
}
- os_memcpy(conf->key, unwrap_sak, conf->key_len);
+ os_memcpy(&sa_key->key_identifier.mi, &participant->current_peer_id.mi,
+ MI_LEN);
+ sa_key->key_identifier.kn = be_to_host32(body->kn);
- os_memcpy(&sak_ki.mi, &participant->current_peer_id.mi,
- sizeof(sak_ki.mi));
- sak_ki.kn = be_to_host32(body->kn);
+ sa_key->key = unwrap_sak;
+ sa_key->key_len = sak_len;
- os_memcpy(conf->ki.mi, sak_ki.mi, MI_LEN);
- conf->ki.kn = sak_ki.kn;
- conf->an = body->dan;
- conf->offset = body->confid_offset;
- conf->rx = TRUE;
- conf->tx = TRUE;
-
- sa_key = ieee802_1x_kay_init_data_key(conf);
- if (!sa_key) {
- os_free(unwrap_sak);
- os_free(conf->key);
- os_free(conf);
- return -1;
- }
+ sa_key->confidentiality_offset = body->confid_offset;
+ sa_key->an = body->dan;
+ ieee802_1x_kay_init_data_key(sa_key);
dl_list_add(&participant->sak_list, &sa_key->list);
- ieee802_1x_cp_set_ciphersuite(
- participant->kay->cp,
- cipher_suite_tbl[participant->kay->macsec_csindex].id);
- ieee802_1x_cp_sm_step(participant->kay->cp);
- ieee802_1x_cp_set_offset(participant->kay->cp, body->confid_offset);
- ieee802_1x_cp_sm_step(participant->kay->cp);
- ieee802_1x_cp_set_distributedki(participant->kay->cp, &sak_ki);
- ieee802_1x_cp_set_distributedan(participant->kay->cp, body->dan);
- ieee802_1x_cp_signal_newsak(participant->kay->cp);
- ieee802_1x_cp_sm_step(participant->kay->cp);
+ ieee802_1x_cp_set_ciphersuite(kay->cp, cs->id);
+ ieee802_1x_cp_sm_step(kay->cp);
+ ieee802_1x_cp_set_offset(kay->cp, body->confid_offset);
+ ieee802_1x_cp_sm_step(kay->cp);
+ ieee802_1x_cp_set_distributedki(kay->cp, &sa_key->key_identifier);
+ ieee802_1x_cp_set_distributedan(kay->cp, body->dan);
+ ieee802_1x_cp_signal_newsak(kay->cp);
+ ieee802_1x_cp_sm_step(kay->cp);
participant->to_use_sak = TRUE;
- os_free(unwrap_sak);
- os_free(conf->key);
- os_free(conf);
-
return 0;
}
length = sizeof(struct ieee802_1x_mka_icv_body);
length += mka_alg_tbl[participant->kay->mka_algindex].icv_len;
- return (length + 0x3) & ~0x3;
+ return MKA_ALIGN_LENGTH(length);
}
return -1;
}
- if (length != DEFAULT_ICV_LEN) {
- os_memcpy(wpabuf_put(buf, length - MKA_HDR_LEN), cmac,
- length - MKA_HDR_LEN);
- } else {
- os_memcpy(wpabuf_put(buf, length), cmac, length);
- }
+ if (length != DEFAULT_ICV_LEN)
+ length -= MKA_HDR_LEN;
+ os_memcpy(wpabuf_put(buf, length), cmac, length);
return 0;
}
struct ieee802_1x_mka_icv_body *body;
size_t body_len;
size_t left_len;
- int body_type;
+ u8 body_type;
const u8 *pos;
pos = mka_msg;
body_len = get_mka_param_body_len(hdr);
if (body_len < 28) {
wpa_printf(MSG_ERROR,
- "KaY: MKA Use SAK Packet Body Length (%d bytes) should be 28 or more octets",
- (int) body_len);
+ "KaY: MKA Use SAK Packet Body Length (%zu bytes) should be 28 or more octets",
+ body_len);
return -1;
}
body_len = get_mka_param_body_len(hdr);
if (body_len < 5) {
wpa_printf(MSG_ERROR,
- "KaY: MKA Use SAK Packet Body Length (%d bytes) should be 5 or more octets",
- (int) body_len);
+ "KaY: MKA Use SAK Packet Body Length (%zu bytes) should be 5 or more octets",
+ body_len);
return -1;
}
}
-static struct mka_param_body_handler mak_body_handler[] = {
+struct mka_param_body_handler {
+ int (*body_tx)(struct ieee802_1x_mka_participant *participant,
+ struct wpabuf *buf);
+ int (*body_rx)(struct ieee802_1x_mka_participant *participant,
+ const u8 *mka_msg, size_t msg_len);
+ int (*body_length)(struct ieee802_1x_mka_participant *participant);
+ Boolean (*body_present)(struct ieee802_1x_mka_participant *participant);
+};
+
+
+static struct mka_param_body_handler mka_body_handler[] = {
/* basic parameter set */
{
- ieee802_1x_mka_encode_basic_body,
- NULL,
- ieee802_1x_mka_basic_body_length,
- ieee802_1x_mka_basic_body_present
+ .body_tx = ieee802_1x_mka_encode_basic_body,
+ .body_rx = NULL,
+ .body_length = ieee802_1x_mka_basic_body_length,
+ .body_present = ieee802_1x_mka_basic_body_present
},
/* live peer list parameter set */
{
- ieee802_1x_mka_encode_live_peer_body,
- ieee802_1x_mka_decode_live_peer_body,
- ieee802_1x_mka_get_live_peer_length,
- ieee802_1x_mka_live_peer_body_present
+ .body_tx = ieee802_1x_mka_encode_live_peer_body,
+ .body_rx = ieee802_1x_mka_decode_live_peer_body,
+ .body_length = ieee802_1x_mka_get_live_peer_length,
+ .body_present = ieee802_1x_mka_live_peer_body_present
},
/* potential peer list parameter set */
{
- ieee802_1x_mka_encode_potential_peer_body,
- ieee802_1x_mka_decode_potential_peer_body,
- ieee802_1x_mka_get_potential_peer_length,
- ieee802_1x_mka_potential_peer_body_present
+ .body_tx = ieee802_1x_mka_encode_potential_peer_body,
+ .body_rx = ieee802_1x_mka_decode_potential_peer_body,
+ .body_length = ieee802_1x_mka_get_potential_peer_length,
+ .body_present = ieee802_1x_mka_potential_peer_body_present
},
/* sak use parameter set */
{
- ieee802_1x_mka_encode_sak_use_body,
- ieee802_1x_mka_decode_sak_use_body,
- ieee802_1x_mka_get_sak_use_length,
- ieee802_1x_mka_sak_use_body_present
+ .body_tx = ieee802_1x_mka_encode_sak_use_body,
+ .body_rx = ieee802_1x_mka_decode_sak_use_body,
+ .body_length = ieee802_1x_mka_get_sak_use_length,
+ .body_present = ieee802_1x_mka_sak_use_body_present
},
/* distribute sak parameter set */
{
- ieee802_1x_mka_encode_dist_sak_body,
- ieee802_1x_mka_decode_dist_sak_body,
- ieee802_1x_mka_get_dist_sak_length,
- ieee802_1x_mka_dist_sak_body_present
+ .body_tx = ieee802_1x_mka_encode_dist_sak_body,
+ .body_rx = ieee802_1x_mka_decode_dist_sak_body,
+ .body_length = ieee802_1x_mka_get_dist_sak_length,
+ .body_present = ieee802_1x_mka_dist_sak_body_present
},
/* distribute cak parameter set */
{
- NULL,
- ieee802_1x_mka_decode_dist_cak_body,
- NULL,
- NULL
+ .body_tx = NULL,
+ .body_rx = ieee802_1x_mka_decode_dist_cak_body,
+ .body_length = NULL,
+ .body_present = NULL
},
/* kmd parameter set */
{
- NULL,
- ieee802_1x_mka_decode_kmd_body,
- NULL,
- NULL
+ .body_tx = NULL,
+ .body_rx = ieee802_1x_mka_decode_kmd_body,
+ .body_length = NULL,
+ .body_present = NULL
},
/* announce parameter set */
{
- NULL,
- ieee802_1x_mka_decode_announce_body,
- NULL,
- NULL
+ .body_tx = NULL,
+ .body_rx = ieee802_1x_mka_decode_announce_body,
+ .body_length = NULL,
+ .body_present = NULL
},
/* icv parameter set */
{
- ieee802_1x_mka_encode_icv_body,
- NULL,
- ieee802_1x_mka_get_icv_length,
- ieee802_1x_mka_icv_body_present
+ .body_tx = ieee802_1x_mka_encode_icv_body,
+ .body_rx = NULL,
+ .body_length = ieee802_1x_mka_get_icv_length,
+ .body_present = ieee802_1x_mka_icv_body_present
},
};
/**
* ieee802_1x_kay_deinit_data_key -
*/
-void ieee802_1x_kay_deinit_data_key(struct data_key *pkey)
+static void ieee802_1x_kay_deinit_data_key(struct data_key *pkey)
{
if (!pkey)
return;
ieee802_1x_kay_generate_new_sak(struct ieee802_1x_mka_participant *participant)
{
struct data_key *sa_key = NULL;
- struct key_conf *conf;
struct ieee802_1x_kay_peer *peer;
struct ieee802_1x_kay *kay = participant->kay;
int ctx_len, ctx_offset;
u8 *context;
+ unsigned int key_len;
+ u8 *key;
+ struct macsec_ciphersuite *cs;
/* check condition for generating a fresh SAK:
* must have one live peer
return -1;
}
- conf = os_zalloc(sizeof(*conf));
- if (!conf) {
+ cs = &cipher_suite_tbl[kay->macsec_csindex];
+ key_len = cs->sak_len;
+ key = os_zalloc(key_len);
+ if (!key) {
wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
return -1;
}
- conf->key_len = cipher_suite_tbl[kay->macsec_csindex].sak_len;
- conf->key = os_zalloc(conf->key_len);
- if (!conf->key) {
- os_free(conf);
- wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
- return -1;
- }
-
- ctx_len = conf->key_len + sizeof(kay->dist_kn);
+ ctx_len = key_len + sizeof(kay->dist_kn);
dl_list_for_each(peer, &participant->live_peers,
struct ieee802_1x_kay_peer, list)
ctx_len += sizeof(peer->mi);
ctx_len += sizeof(participant->mi);
context = os_zalloc(ctx_len);
- if (!context) {
- os_free(conf->key);
- os_free(conf);
- return -1;
- }
+ if (!context)
+ goto fail;
+
ctx_offset = 0;
- if (os_get_random(context + ctx_offset, conf->key_len) < 0) {
- os_free(context);
- os_free(conf->key);
- os_free(conf);
- return -1;
- }
- ctx_offset += conf->key_len;
+ if (os_get_random(context + ctx_offset, key_len) < 0)
+ goto fail;
+
+ ctx_offset += key_len;
dl_list_for_each(peer, &participant->live_peers,
struct ieee802_1x_kay_peer, list) {
os_memcpy(context + ctx_offset, peer->mi, sizeof(peer->mi));
ctx_offset += sizeof(participant->mi);
os_memcpy(context + ctx_offset, &kay->dist_kn, sizeof(kay->dist_kn));
- if (conf->key_len == 16) {
+ if (key_len == 16) {
ieee802_1x_sak_128bits_aes_cmac(participant->cak.key,
- context, ctx_len, conf->key);
- } else if (conf->key_len == 32) {
+ context, ctx_len, key);
+ } else if (key_len == 32) {
ieee802_1x_sak_128bits_aes_cmac(participant->cak.key,
- context, ctx_len, conf->key);
+ context, ctx_len, key);
} else {
wpa_printf(MSG_ERROR, "KaY: SAK Length not support");
- os_free(conf->key);
- os_free(conf);
- os_free(context);
- return -1;
+ goto fail;
}
- wpa_hexdump(MSG_DEBUG, "KaY: generated new SAK",
- conf->key, conf->key_len);
-
- os_memcpy(conf->ki.mi, participant->mi, MI_LEN);
- conf->ki.kn = participant->kay->dist_kn;
- conf->an = participant->kay->dist_an;
- conf->offset = kay->macsec_confidentiality;
- conf->rx = TRUE;
- conf->tx = TRUE;
+ wpa_hexdump(MSG_DEBUG, "KaY: generated new SAK", key, key_len);
+ os_free(context);
+ context = NULL;
- sa_key = ieee802_1x_kay_init_data_key(conf);
+ sa_key = os_zalloc(sizeof(*sa_key));
if (!sa_key) {
- os_free(conf->key);
- os_free(conf);
- os_free(context);
- return -1;
+ wpa_printf(MSG_ERROR, "KaY-%s: Out of memory", __func__);
+ goto fail;
}
+
+ sa_key->key = key;
+ sa_key->key_len = key_len;
+ os_memcpy(sa_key->key_identifier.mi, participant->mi, MI_LEN);
+ sa_key->key_identifier.kn = kay->dist_kn;
+
+ sa_key->confidentiality_offset = kay->macsec_confidentiality;
+ sa_key->an = kay->dist_an;
+ ieee802_1x_kay_init_data_key(sa_key);
+
participant->new_key = sa_key;
dl_list_add(&participant->sak_list, &sa_key->list);
- ieee802_1x_cp_set_ciphersuite(participant->kay->cp,
- cipher_suite_tbl[kay->macsec_csindex].id);
+ ieee802_1x_cp_set_ciphersuite(kay->cp, cs->id);
ieee802_1x_cp_sm_step(kay->cp);
- ieee802_1x_cp_set_offset(kay->cp, conf->offset);
+ ieee802_1x_cp_set_offset(kay->cp, kay->macsec_confidentiality);
ieee802_1x_cp_sm_step(kay->cp);
- ieee802_1x_cp_set_distributedki(kay->cp, &conf->ki);
- ieee802_1x_cp_set_distributedan(kay->cp, conf->an);
+ ieee802_1x_cp_set_distributedki(kay->cp, &sa_key->key_identifier);
+ ieee802_1x_cp_set_distributedan(kay->cp, sa_key->an);
ieee802_1x_cp_signal_newsak(kay->cp);
ieee802_1x_cp_sm_step(kay->cp);
struct ieee802_1x_kay_peer, list)
peer->sak_used = FALSE;
- participant->kay->dist_kn++;
- participant->kay->dist_an++;
- if (participant->kay->dist_an > 3)
- participant->kay->dist_an = 0;
+ kay->dist_kn++;
+ kay->dist_an++;
+ if (kay->dist_an > 3)
+ kay->dist_an = 0;
- participant->kay->dist_time = time(NULL);
+ kay->dist_time = time(NULL);
- os_free(conf->key);
- os_free(conf);
- os_free(context);
return 0;
+
+fail:
+ os_free(key);
+ os_free(context);
+ return -1;
+}
+
+
+static int compare_priorities(const struct ieee802_1x_kay_peer *peer,
+ const struct ieee802_1x_kay_peer *other)
+{
+ if (peer->key_server_priority < other->key_server_priority)
+ return -1;
+ if (other->key_server_priority < peer->key_server_priority)
+ return 1;
+
+ return os_memcmp(peer->sci.addr, other->sci.addr, ETH_ALEN);
}
struct ieee802_1x_kay_peer *key_server = NULL;
struct ieee802_1x_kay *kay = participant->kay;
Boolean i_is_key_server;
- int i;
if (participant->is_obliged_key_server) {
participant->new_sak = TRUE;
continue;
}
- if (peer->key_server_priority <
- key_server->key_server_priority) {
+ if (compare_priorities(peer, key_server) < 0)
key_server = peer;
- } else if (peer->key_server_priority ==
- key_server->key_server_priority) {
- for (i = 0; i < 6; i++) {
- if (peer->sci.addr[i] <
- key_server->sci.addr[i])
- key_server = peer;
- }
- }
}
/* elect the key server between me and the above elected peer */
i_is_key_server = FALSE;
if (key_server && participant->can_be_key_server) {
- if (kay->actor_priority
- < key_server->key_server_priority) {
- i_is_key_server = TRUE;
- } else if (kay->actor_priority
- == key_server->key_server_priority) {
- for (i = 0; i < 6; i++) {
- if (kay->actor_sci.addr[i]
- < key_server->sci.addr[i]) {
- i_is_key_server = TRUE;
- }
- }
- }
- }
+ struct ieee802_1x_kay_peer tmp;
- if (!key_server && !i_is_key_server) {
- participant->principal = FALSE;
- participant->is_key_server = FALSE;
- participant->is_elected = FALSE;
- return 0;
+ tmp.key_server_priority = kay->actor_priority;
+ os_memcpy(&tmp.sci, &kay->actor_sci, sizeof(tmp.sci));
+ if (compare_priorities(&tmp, key_server) < 0)
+ i_is_key_server = TRUE;
+ } else if (participant->can_be_key_server) {
+ i_is_key_server = TRUE;
}
if (i_is_key_server) {
ieee802_1x_cp_set_electedself(kay->cp, TRUE);
- if (os_memcmp(&kay->key_server_sci, &kay->actor_sci,
- sizeof(kay->key_server_sci))) {
+ if (!sci_equal(&kay->key_server_sci, &kay->actor_sci)) {
ieee802_1x_cp_signal_chgdserver(kay->cp);
ieee802_1x_cp_sm_step(kay->cp);
}
os_memcpy(&kay->key_server_sci, &kay->actor_sci,
sizeof(kay->key_server_sci));
kay->key_server_priority = kay->actor_priority;
- }
-
- if (key_server) {
+ } else if (key_server) {
ieee802_1x_cp_set_electedself(kay->cp, FALSE);
- if (os_memcmp(&kay->key_server_sci, &key_server->sci,
- sizeof(kay->key_server_sci))) {
+ if (!sci_equal(&kay->key_server_sci, &key_server->sci)) {
ieee802_1x_cp_signal_chgdserver(kay->cp);
ieee802_1x_cp_sm_step(kay->cp);
}
os_memcpy(&kay->key_server_sci, &key_server->sci,
sizeof(kay->key_server_sci));
kay->key_server_priority = key_server->key_server_priority;
+ } else {
+ participant->principal = FALSE;
+ participant->is_key_server = FALSE;
+ participant->is_elected = FALSE;
}
return 0;
if (!peer->macsec_desired)
continue;
- if (peer->macsec_capbility == MACSEC_CAP_NOT_IMPLEMENTED)
+ if (peer->macsec_capability == MACSEC_CAP_NOT_IMPLEMENTED)
continue;
- less_capability = (less_capability < peer->macsec_capbility) ?
- less_capability : peer->macsec_capbility;
+ less_capability = (less_capability < peer->macsec_capability) ?
+ less_capability : peer->macsec_capability;
has_peer = TRUE;
}
eapol_hdr->type = IEEE802_1X_TYPE_EAPOL_MKA;
eapol_hdr->length = host_to_be16(pbuf->size - pbuf->used);
- for (i = 0; i < ARRAY_SIZE(mak_body_handler); i++) {
- if (mak_body_handler[i].body_present &&
- mak_body_handler[i].body_present(participant)) {
- if (mak_body_handler[i].body_tx(participant, pbuf))
+ for (i = 0; i < ARRAY_SIZE(mka_body_handler); i++) {
+ if (mka_body_handler[i].body_present &&
+ mka_body_handler[i].body_present(participant)) {
+ if (mka_body_handler[i].body_tx(participant, pbuf))
return -1;
}
}
wpa_printf(MSG_DEBUG, "KaY: to enpacket and send the MKPDU");
length += sizeof(struct ieee802_1x_hdr) + sizeof(struct ieee8023_hdr);
- for (i = 0; i < ARRAY_SIZE(mak_body_handler); i++) {
- if (mak_body_handler[i].body_present &&
- mak_body_handler[i].body_present(participant))
- length += mak_body_handler[i].body_length(participant);
+ for (i = 0; i < ARRAY_SIZE(mka_body_handler); i++) {
+ if (mka_body_handler[i].body_present &&
+ mka_body_handler[i].body_present(participant))
+ length += mka_body_handler[i].body_length(participant);
}
buf = wpabuf_alloc(length);
participant = (struct ieee802_1x_mka_participant *)eloop_ctx;
kay = participant->kay;
if (participant->cak_life) {
- if (now > participant->cak_life) {
- kay->authenticated = FALSE;
- kay->secured = FALSE;
- kay->failed = TRUE;
- ieee802_1x_kay_delete_mka(kay, &participant->ckn);
- return;
- }
+ if (now > participant->cak_life)
+ goto delete_mka;
}
/* should delete MKA instance if there are not live peers
* when the MKA life elapsed since its creating */
if (participant->mka_life) {
if (dl_list_empty(&participant->live_peers)) {
- if (now > participant->mka_life) {
- kay->authenticated = FALSE;
- kay->secured = FALSE;
- kay->failed = TRUE;
- ieee802_1x_kay_delete_mka(kay,
- &participant->ckn);
- return;
- }
+ if (now > participant->mka_life)
+ goto delete_mka;
} else {
participant->mka_life = 0;
}
dl_list_for_each_safe(rxsc, pre_rxsc,
&participant->rxsc_list,
struct receive_sc, list) {
- if (os_memcmp(&rxsc->sci, &peer->sci,
- sizeof(rxsc->sci)) == 0) {
+ if (sci_equal(&rxsc->sci, &peer->sci)) {
secy_delete_receive_sc(kay, rxsc);
ieee802_1x_kay_deinit_receive_sc(
participant, rxsc);
eloop_register_timeout(MKA_HELLO_TIME / 1000, 0,
ieee802_1x_participant_timer,
participant, NULL);
+
+ return;
+
+delete_mka:
+ kay->authenticated = FALSE;
+ kay->secured = FALSE;
+ kay->failed = TRUE;
+ ieee802_1x_kay_delete_mka(kay, &participant->ckn);
}
dl_list_add(&psc->sa_list, &psa->list);
wpa_printf(MSG_DEBUG,
- "KaY: Create transmit SA(an: %d, next_PN: %u) of SC(channel: %d)",
- (int) an, next_PN, psc->channel);
+ "KaY: Create transmit SA(an: %hhu, next_PN: %u) of SC(channel: %d)",
+ an, next_PN, psc->channel);
return psa;
}
{
psa->pkey = NULL;
wpa_printf(MSG_DEBUG,
- "KaY: Delete transmit SA(an: %d) of SC(channel: %d)",
- psa->an, psa->sc->channel);
+ "KaY: Delete transmit SA(an: %hhu) of SC",
+ psa->an);
dl_list_del(&psa->list);
os_free(psa);
}
/**
- * ieee802_1x_kay_cp_conf -
- */
-int ieee802_1x_kay_cp_conf(struct ieee802_1x_kay *kay,
- struct ieee802_1x_cp_conf *pconf)
-{
- pconf->protect = kay->macsec_protect;
- pconf->replay_protect = kay->macsec_replay_protect;
- pconf->validate = kay->macsec_validate;
-
- return 0;
-}
-
-
-/**
- * ieee802_1x_kay_alloc_cp_sm -
- */
-static struct ieee802_1x_cp_sm *
-ieee802_1x_kay_alloc_cp_sm(struct ieee802_1x_kay *kay)
-{
- struct ieee802_1x_cp_conf conf;
-
- os_memset(&conf, 0, sizeof(conf));
- conf.protect = kay->macsec_protect;
- conf.replay_protect = kay->macsec_replay_protect;
- conf.validate = kay->macsec_validate;
- conf.replay_window = kay->macsec_replay_window;
-
- return ieee802_1x_cp_sm_init(kay, &conf);
-}
-
-
-/**
* ieee802_1x_kay_mkpdu_sanity_check -
* sanity check specified in clause 11.11.2 of IEEE802.1X-2010
*/
return -1;
}
- /* MKPDU should not less than 32 octets */
+ /* MKPDU should not be less than 32 octets */
mka_msg_len = be_to_host16(eapol_hdr->length);
if (mka_msg_len < 32) {
wpa_printf(MSG_MSGDUMP, "KaY: MKPDU is less than 32 octets");
return -1;
}
- /* MKPDU should multiple 4 octets */
+ /* MKPDU should be a multiple of 4 octets */
if ((mka_msg_len % 4) != 0) {
wpa_printf(MSG_MSGDUMP,
"KaY: MKPDU is not multiple of 4 octets");
/* EAPOL-MKA body should comprise basic parameter set and ICV */
if (mka_msg_len < MKA_HDR_LEN + body_len + DEFAULT_ICV_LEN) {
wpa_printf(MSG_ERROR,
- "KaY: Received EAPOL-MKA Packet Body Length (%d bytes) is less than the Basic Parameter Set Header Length (%d bytes) + the Basic Parameter Set Body Length (%d bytes) + %d bytes of ICV",
- (int) mka_msg_len, (int) MKA_HDR_LEN,
- (int) body_len, DEFAULT_ICV_LEN);
+ "KaY: Received EAPOL-MKA Packet Body Length (%zu bytes) is less than the Basic Parameter Set Header Length (%zu bytes) + the Basic Parameter Set Body Length (%zu bytes) + %d bytes of ICV",
+ mka_msg_len, MKA_HDR_LEN,
+ body_len, DEFAULT_ICV_LEN);
return -1;
}
wpa_printf(MSG_ERROR, "KaY: omac1_aes_128 failed");
return -1;
}
+
msg_icv = ieee802_1x_mka_decode_icv_body(participant, (u8 *) mka_hdr,
mka_msg_len);
-
- if (msg_icv) {
- if (os_memcmp_const(msg_icv, icv,
- mka_alg_tbl[kay->mka_algindex].icv_len) !=
- 0) {
- wpa_printf(MSG_ERROR,
- "KaY: Computed ICV is not equal to Received ICV");
- return -1;
- }
- } else {
+ if (!msg_icv) {
wpa_printf(MSG_ERROR, "KaY: No ICV");
return -1;
}
+ if (os_memcmp_const(msg_icv, icv,
+ mka_alg_tbl[kay->mka_algindex].icv_len) != 0) {
+ wpa_printf(MSG_ERROR,
+ "KaY: Computed ICV is not equal to Received ICV");
+ return -1;
+ }
return 0;
}
struct ieee802_1x_mka_hdr *hdr;
size_t body_len;
size_t left_len;
- int body_type;
+ u8 body_type;
int i;
const u8 *pos;
- Boolean my_included;
Boolean handled[256];
if (ieee802_1x_kay_mkpdu_sanity_check(kay, buf, len))
left_len -= body_len + MKA_HDR_LEN;
/* check i am in the peer's peer list */
- my_included = ieee802_1x_mka_i_in_peerlist(participant, pos, left_len);
- if (my_included) {
+ if (ieee802_1x_mka_i_in_peerlist(participant, pos, left_len) &&
+ !ieee802_1x_kay_is_in_live_peer(participant,
+ participant->current_peer_id.mi)) {
/* accept the peer as live peer */
- if (!ieee802_1x_kay_is_in_peer(
- participant,
- participant->current_peer_id.mi)) {
- if (!ieee802_1x_kay_create_live_peer(
+ if (ieee802_1x_kay_is_in_potential_peer(
+ participant, participant->current_peer_id.mi)) {
+ if (!ieee802_1x_kay_move_live_peer(
participant,
participant->current_peer_id.mi,
- participant->current_peer_id.mn))
+ be_to_host32(participant->
+ current_peer_id.mn)))
+ return -1;
+ } else if (!ieee802_1x_kay_create_live_peer(
+ participant, participant->current_peer_id.mi,
+ be_to_host32(participant->
+ current_peer_id.mn))) {
return -1;
- ieee802_1x_kay_elect_key_server(participant);
- ieee802_1x_kay_decide_macsec_use(participant);
- }
- if (ieee802_1x_kay_is_in_potential_peer(
- participant, participant->current_peer_id.mi)) {
- ieee802_1x_kay_move_live_peer(
- participant, participant->current_peer_id.mi,
- participant->current_peer_id.mn);
- ieee802_1x_kay_elect_key_server(participant);
- ieee802_1x_kay_decide_macsec_use(participant);
}
+
+ ieee802_1x_kay_elect_key_server(participant);
+ ieee802_1x_kay_decide_macsec_use(participant);
}
/*
handled[i] = FALSE;
handled[0] = TRUE;
- while (left_len > MKA_HDR_LEN + DEFAULT_ICV_LEN) {
+ for (; left_len > MKA_HDR_LEN + DEFAULT_ICV_LEN;
+ pos += body_len + MKA_HDR_LEN,
+ left_len -= body_len + MKA_HDR_LEN) {
hdr = (struct ieee802_1x_mka_hdr *) pos;
body_len = get_mka_param_body_len(hdr);
body_type = get_mka_param_body_type(hdr);
if (left_len < (MKA_HDR_LEN + body_len + DEFAULT_ICV_LEN)) {
wpa_printf(MSG_ERROR,
- "KaY: MKA Peer Packet Body Length (%d bytes) is less than the Parameter Set Header Length (%d bytes) + the Parameter Set Body Length (%d bytes) + %d bytes of ICV",
- (int) left_len, (int) MKA_HDR_LEN,
- (int) body_len, DEFAULT_ICV_LEN);
- goto next_para_set;
+ "KaY: MKA Peer Packet Body Length (%zu bytes) is less than the Parameter Set Header Length (%zu bytes) + the Parameter Set Body Length (%zu bytes) + %d bytes of ICV",
+ left_len, MKA_HDR_LEN,
+ body_len, DEFAULT_ICV_LEN);
+ continue;
}
if (handled[body_type])
- goto next_para_set;
+ continue;
handled[body_type] = TRUE;
- if (mak_body_handler[body_type].body_rx) {
- mak_body_handler[body_type].body_rx
+ if (body_type < ARRAY_SIZE(mka_body_handler) &&
+ mka_body_handler[body_type].body_rx) {
+ mka_body_handler[body_type].body_rx
(participant, pos, left_len);
} else {
wpa_printf(MSG_ERROR,
- "The type %d not supported in this MKA version %d",
+ "The type %d is not supported in this MKA version %d",
body_type, MKA_VERSION_ID);
}
-
-next_para_set:
- pos += body_len + MKA_HDR_LEN;
- left_len -= body_len + MKA_HDR_LEN;
}
kay->active = TRUE;
eth_hdr = (struct ieee8023_hdr *) buf;
eapol_hdr = (struct ieee802_1x_hdr *) (eth_hdr + 1);
if (len != sizeof(*eth_hdr) + sizeof(*eapol_hdr) +
- ntohs(eapol_hdr->length)) {
+ be_to_host16(eapol_hdr->length)) {
wpa_printf(MSG_MSGDUMP, "KAY: EAPOL MPDU is invalid: (%lu-%lu)",
(unsigned long) len,
- (unsigned long) ntohs(eapol_hdr->length));
+ (unsigned long) be_to_host16(eapol_hdr->length));
return;
}
eapol_hdr->version);
return;
}
- if (ntohs(eth_hdr->ethertype) != ETH_P_PAE ||
+ if (be_to_host16(eth_hdr->ethertype) != ETH_P_PAE ||
eapol_hdr->type != IEEE802_1X_TYPE_EAPOL_MKA)
return;
os_strlcpy(kay->if_name, ifname, IFNAMSIZ);
os_memcpy(kay->actor_sci.addr, addr, ETH_ALEN);
- kay->actor_sci.port = 0x0001;
+ kay->actor_sci.port = host_to_be16(0x0001);
kay->actor_priority = DEFAULT_PRIO_NOT_KEY_SERVER;
/* While actor acts as a key server, shall distribute sakey */
wpa_printf(MSG_DEBUG, "KaY: secy init macsec done");
/* init CP */
- kay->cp = ieee802_1x_kay_alloc_cp_sm(kay);
+ kay->cp = ieee802_1x_cp_sm_init(kay);
if (kay->cp == NULL) {
ieee802_1x_kay_deinit(kay);
return NULL;
default:
participant->is_obliged_key_server = FALSE;
participant->can_be_key_server = TRUE;
- participant->is_key_server = FALSE;
+ participant->is_key_server = TRUE;
participant->is_elected = FALSE;
break;
}
participant->retry_count = 0;
participant->kay = kay;
- if (os_get_random(participant->mi, sizeof(participant->mi)) < 0)
+ if (!reset_participant_mi(participant))
goto fail;
- participant->mn = 0;
participant->lrx = FALSE;
participant->ltx = FALSE;
return;
}
+ eloop_cancel_timeout(ieee802_1x_participant_timer, participant, NULL);
dl_list_del(&participant->list);
/* remove live peer */
* ieee802_1x_kay_change_cipher_suite -
*/
int
-ieee802_1x_kay_change_cipher_suite(struct ieee802_1x_kay *kay, int cs_index)
+ieee802_1x_kay_change_cipher_suite(struct ieee802_1x_kay *kay,
+ unsigned int cs_index)
{
struct ieee802_1x_mka_participant *participant;
if (!kay)
return -1;
- if ((unsigned int) cs_index >= CS_TABLE_SIZE) {
+ if (cs_index >= CS_TABLE_SIZE) {
wpa_printf(MSG_ERROR,
"KaY: Configured cipher suite index is out of range");
return -1;
#include "common/ieee802_1x_defs.h"
struct macsec_init_params;
-struct ieee802_1x_cp_conf;
#define MI_LEN 12
#define MAX_KEY_LEN 32 /* 32 bytes, 256 bits */
struct ieee802_1x_mka_sci {
u8 addr[ETH_ALEN];
- u16 port;
+ be16 port;
};
struct mka_key {
enum mka_created_mode {
PSK,
EAP_EXCHANGE,
- DISTRIBUTED,
- CACHED,
};
struct ieee802_1x_kay_ctx {
int (*macsec_deinit)(void *ctx);
int (*enable_protect_frames)(void *ctx, Boolean enabled);
int (*set_replay_protect)(void *ctx, Boolean enabled, u32 window);
- int (*set_current_cipher_suite)(void *ctx, const u8 *cs, size_t cs_len);
+ int (*set_current_cipher_suite)(void *ctx, u64 cs);
int (*enable_controlled_port)(void *ctx, Boolean enabled);
int (*get_receive_lowest_pn)(void *ctx, u32 channel, u8 an,
u32 *lowest_pn);
Boolean is_obliged_key_server;
char if_name[IFNAMSIZ];
- int macsec_csindex; /* MACsec cipher suite table index */
+ unsigned int macsec_csindex; /* MACsec cipher suite table index */
int mka_algindex; /* MKA alg table index */
u32 dist_kn;
Boolean status);
int ieee802_1x_kay_new_sak(struct ieee802_1x_kay *kay);
int ieee802_1x_kay_change_cipher_suite(struct ieee802_1x_kay *kay,
- int cs_index);
+ unsigned int cs_index);
int ieee802_1x_kay_set_latest_sa_attr(struct ieee802_1x_kay *kay,
struct ieee802_1x_mka_ki *lki, u8 lan,
int ieee802_1x_kay_enable_rx_sas(struct ieee802_1x_kay *kay,
struct ieee802_1x_mka_ki *lki);
int ieee802_1x_kay_enable_new_info(struct ieee802_1x_kay *kay);
-int ieee802_1x_kay_cp_conf(struct ieee802_1x_kay *kay,
- struct ieee802_1x_cp_conf *pconf);
#endif /* IEEE802_1X_KAY_H */
struct ieee802_1x_mka_peer_id {
u8 mi[MI_LEN];
- u32 mn;
+ be32 mn;
};
struct ieee802_1x_kay_peer {
Boolean is_key_server;
u8 key_server_priority;
Boolean macsec_desired;
- enum macsec_cap macsec_capbility;
+ enum macsec_cap macsec_capability;
Boolean sak_used;
struct dl_list list;
};
-struct key_conf {
- u8 *key;
- struct ieee802_1x_mka_ki ki;
- enum confidentiality_offset offset;
- u8 an;
- Boolean tx;
- Boolean rx;
- int key_len; /* unit: byte */
-};
-
struct data_key {
u8 *key;
int key_len;
};
struct macsec_ciphersuite {
- u8 id[CS_ID_LEN];
+ u64 id;
char name[32];
enum macsec_cap capable;
int sak_len; /* unit: byte */
struct ieee802_1x_mka_hdr {
/* octet 1 */
- u32 type:8;
+ u8 type;
/* octet 2 */
- u32 reserve:8;
+ u8 reserve;
/* octet 3 */
#if __BYTE_ORDER == __LITTLE_ENDIAN
- u32 length:4;
- u32 reserve1:4;
+ u8 length:4;
+ u8 reserve1:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
- u32 reserve1:4;
- u32 length:4;
+ u8 reserve1:4;
+ u8 length:4;
#else
#error "Please fix <bits/endian.h>"
#endif
/* octet 4 */
- u32 length1:8;
+ u8 length1;
};
#define MKA_HDR_LEN sizeof(struct ieee802_1x_mka_hdr)
struct ieee802_1x_mka_basic_body {
/* octet 1 */
- u32 version:8;
+ u8 version;
/* octet 2 */
- u32 priority:8;
+ u8 priority;
/* octet 3 */
#if __BYTE_ORDER == __LITTLE_ENDIAN
- u32 length:4;
- u32 macsec_capbility:2;
- u32 macsec_desired:1;
- u32 key_server:1;
+ u8 length:4;
+ u8 macsec_capability:2;
+ u8 macsec_desired:1;
+ u8 key_server:1;
#elif __BYTE_ORDER == __BIG_ENDIAN
- u32 key_server:1;
- u32 macsec_desired:1;
- u32 macsec_capbility:2;
- u32 length:4;
+ u8 key_server:1;
+ u8 macsec_desired:1;
+ u8 macsec_capability:2;
+ u8 length:4;
#endif
/* octet 4 */
- u32 length1:8;
+ u8 length1;
struct ieee802_1x_mka_sci actor_sci;
u8 actor_mi[MI_LEN];
- u32 actor_mn;
+ be32 actor_mn;
u8 algo_agility[4];
/* followed by CAK Name*/
struct ieee802_1x_mka_peer_body {
/* octet 1 */
- u32 type:8;
+ u8 type;
/* octet 2 */
- u32 reserve:8;
+ u8 reserve;
/* octet 3 */
#if __BYTE_ORDER == __LITTLE_ENDIAN
- u32 length:4;
- u32 reserve1:4;
+ u8 length:4;
+ u8 reserve1:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
- u32 reserve1:4;
- u32 length:4;
+ u8 reserve1:4;
+ u8 length:4;
#endif
/* octet 4 */
- u32 length1:8;
+ u8 length1;
u8 peer[0];
/* followed by Peers */
struct ieee802_1x_mka_sak_use_body {
/* octet 1 */
- u32 type:8;
+ u8 type;
/* octet 2 */
#if __BYTE_ORDER == __LITTLE_ENDIAN
- u32 orx:1;
- u32 otx:1;
- u32 oan:2;
- u32 lrx:1;
- u32 ltx:1;
- u32 lan:2;
+ u8 orx:1;
+ u8 otx:1;
+ u8 oan:2;
+ u8 lrx:1;
+ u8 ltx:1;
+ u8 lan:2;
#elif __BYTE_ORDER == __BIG_ENDIAN
- u32 lan:2;
- u32 ltx:1;
- u32 lrx:1;
- u32 oan:2;
- u32 otx:1;
- u32 orx:1;
+ u8 lan:2;
+ u8 ltx:1;
+ u8 lrx:1;
+ u8 oan:2;
+ u8 otx:1;
+ u8 orx:1;
#endif
/* octet 3 */
#if __BYTE_ORDER == __LITTLE_ENDIAN
- u32 length:4;
- u32 delay_protect:1;
- u32 reserve:1;
- u32 prx:1;
- u32 ptx:1;
+ u8 length:4;
+ u8 delay_protect:1;
+ u8 reserve:1;
+ u8 prx:1;
+ u8 ptx:1;
#elif __BYTE_ORDER == __BIG_ENDIAN
- u32 ptx:1;
- u32 prx:1;
- u32 reserve:1;
- u32 delay_protect:1;
- u32 length:4;
+ u8 ptx:1;
+ u8 prx:1;
+ u8 reserve:1;
+ u8 delay_protect:1;
+ u8 length:4;
#endif
/* octet 4 */
- u32 length1:8;
+ u8 length1;
/* octet 5 - 16 */
u8 lsrv_mi[MI_LEN];
/* octet 17 - 20 */
- u32 lkn;
+ be32 lkn;
/* octet 21 - 24 */
- u32 llpn;
+ be32 llpn;
/* octet 25 - 36 */
u8 osrv_mi[MI_LEN];
/* octet 37 - 40 */
- u32 okn;
+ be32 okn;
/* octet 41 - 44 */
- u32 olpn;
+ be32 olpn;
};
struct ieee802_1x_mka_dist_sak_body {
/* octet 1 */
- u32 type:8;
+ u8 type;
/* octet 2 */
#if __BYTE_ORDER == __LITTLE_ENDIAN
- u32 reserve:4;
- u32 confid_offset:2;
- u32 dan:2;
+ u8 reserve:4;
+ u8 confid_offset:2;
+ u8 dan:2;
#elif __BYTE_ORDER == __BIG_ENDIAN
- u32 dan:2;
- u32 confid_offset:2;
- u32 reserve:4;
+ u8 dan:2;
+ u8 confid_offset:2;
+ u8 reserve:4;
#endif
/* octet 3 */
#if __BYTE_ORDER == __LITTLE_ENDIAN
- u32 length:4;
- u32 reserve1:4;
+ u8 length:4;
+ u8 reserve1:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
- u32 reserve1:4;
- u32 length:4;
+ u8 reserve1:4;
+ u8 length:4;
#endif
/* octet 4 */
- u32 length1:8;
+ u8 length1;
/* octet 5 - 8 */
- u32 kn;
+ be32 kn;
/* for GCM-AES-128: octet 9-32: SAK
* for other cipher suite: octet 9-16: cipher suite id, octet 17-: SAK
struct ieee802_1x_mka_icv_body {
/* octet 1 */
- u32 type:8;
+ u8 type;
/* octet 2 */
- u32 reserve:8;
+ u8 reserve;
/* octet 3 */
#if __BYTE_ORDER == __LITTLE_ENDIAN
- u32 length:4;
- u32 reserve1:4;
+ u8 length:4;
+ u8 reserve1:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
- u32 reserve1:4;
- u32 length:4;
+ u8 reserve1:4;
+ u8 length:4;
#endif
/* octet 4 */
- u32 length1:8;
+ u8 length1;
/* octet 5 - */
u8 icv[0];
}
-int secy_cp_control_current_cipher_suite(struct ieee802_1x_kay *kay,
- const u8 *cs, size_t cs_len)
+int secy_cp_control_current_cipher_suite(struct ieee802_1x_kay *kay, u64 cs)
{
struct ieee802_1x_kay_ctx *ops;
return -1;
}
- return ops->set_current_cipher_suite(ops->ctx, cs, cs_len);
+ return ops->set_current_cipher_suite(ops->ctx, cs);
}
enum validate_frames vf);
int secy_cp_control_protect_frames(struct ieee802_1x_kay *kay, Boolean flag);
int secy_cp_control_replay(struct ieee802_1x_kay *kay, Boolean flag, u32 win);
-int secy_cp_control_current_cipher_suite(struct ieee802_1x_kay *kay,
- const u8 *cs, size_t cs_len);
+int secy_cp_control_current_cipher_suite(struct ieee802_1x_kay *kay, u64 cs);
int secy_cp_control_confidentiality_offset(struct ieee802_1x_kay *kay,
enum confidentiality_offset co);
int secy_cp_control_enable_port(struct ieee802_1x_kay *kay, Boolean flag);
/*
* RADIUS message processing
- * Copyright (c) 2002-2009, 2011-2014, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2009, 2011-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
{ RADIUS_ATTR_USER_PASSWORD, "User-Password", RADIUS_ATTR_UNDIST },
{ RADIUS_ATTR_NAS_IP_ADDRESS, "NAS-IP-Address", RADIUS_ATTR_IP },
{ RADIUS_ATTR_NAS_PORT, "NAS-Port", RADIUS_ATTR_INT32 },
+ { RADIUS_ATTR_SERVICE_TYPE, "Service-Type", RADIUS_ATTR_INT32 },
+ { RADIUS_ATTR_FRAMED_IP_ADDRESS, "Framed-IP-Address", RADIUS_ATTR_IP },
{ RADIUS_ATTR_FRAMED_MTU, "Framed-MTU", RADIUS_ATTR_INT32 },
{ RADIUS_ATTR_REPLY_MESSAGE, "Reply-Message", RADIUS_ATTR_TEXT },
{ RADIUS_ATTR_STATE, "State", RADIUS_ATTR_UNDIST },
RADIUS_ATTR_INT32 },
{ RADIUS_ATTR_EVENT_TIMESTAMP, "Event-Timestamp",
RADIUS_ATTR_INT32 },
+ { RADIUS_ATTR_EGRESS_VLANID, "EGRESS-VLANID", RADIUS_ATTR_HEXDUMP },
{ RADIUS_ATTR_NAS_PORT_TYPE, "NAS-Port-Type", RADIUS_ATTR_INT32 },
{ RADIUS_ATTR_TUNNEL_TYPE, "Tunnel-Type", RADIUS_ATTR_HEXDUMP },
{ RADIUS_ATTR_TUNNEL_MEDIUM_TYPE, "Tunnel-Medium-Type",
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)
{
const u8 *addr[4];
size_t len[4];
}
if (attr == NULL) {
- /* Message-Authenticator is MAY; not required */
+ if (require_message_authenticator) {
+ wpa_printf(MSG_WARNING,
+ "Missing Message-Authenticator attribute in RADIUS message");
+ return 1;
+ }
return 0;
}
attr = (struct radius_attr_hdr *) pos;
- if (pos + attr->length > end || attr->length < sizeof(*attr))
+ if (attr->length > end - pos || attr->length < sizeof(*attr))
goto fail;
/* TODO: check that attr->length is suitable for attr->type */
os_memcpy(msg->hdr->authenticator, req_auth,
sizeof(msg->hdr->authenticator));
}
- hmac_md5(secret, secret_len, wpabuf_head(msg->buf),
- wpabuf_len(msg->buf), auth);
+ if (hmac_md5(secret, secret_len, wpabuf_head(msg->buf),
+ wpabuf_len(msg->buf), auth) < 0)
+ return 1;
os_memcpy(attr + 1, orig, MD5_MAC_LEN);
if (req_auth) {
os_memcpy(msg->hdr->authenticator, orig_authenticator,
len[2] = wpabuf_len(msg->buf) - sizeof(struct radius_hdr);
addr[3] = secret;
len[3] = secret_len;
- md5_vector(4, addr, len, hash);
- if (os_memcmp_const(hash, msg->hdr->authenticator, MD5_MAC_LEN) != 0) {
+ if (md5_vector(4, addr, len, hash) < 0 ||
+ os_memcmp_const(hash, msg->hdr->authenticator, MD5_MAC_LEN) != 0) {
wpa_printf(MSG_INFO, "Response Authenticator invalid!");
return 1;
}
/* Create Request Authenticator. The value should be unique over the lifetime
* of the shared secret between authenticator and authentication server.
- * Use one-way MD5 hash calculated from current timestamp and some data given
- * by the caller. */
-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 os_time tv;
- long int l;
- const u8 *addr[3];
- size_t elen[3];
-
- os_get_time(&tv);
- l = os_random();
- addr[0] = (u8 *) &tv;
- elen[0] = sizeof(tv);
- addr[1] = data;
- elen[1] = len;
- addr[2] = (u8 *) &l;
- elen[2] = sizeof(l);
- md5_vector(3, addr, elen, msg->hdr->authenticator);
+ return os_get_random((u8 *) &msg->hdr->authenticator,
+ sizeof(msg->hdr->authenticator));
}
addr[1] = pos - MD5_MAC_LEN;
elen[1] = MD5_MAC_LEN;
}
- md5_vector(first ? 3 : 2, addr, elen, hash);
+ if (md5_vector(first ? 3 : 2, addr, elen, hash) < 0) {
+ os_free(plain);
+ return NULL;
+ }
first = 0;
for (i = 0; i < MD5_MAC_LEN; i++)
vhdr = (struct radius_attr_vendor *) pos;
vhdr->vendor_type = RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY;
pos = (u8 *) (vhdr + 1);
- salt = os_random() | 0x8000;
+ if (os_get_random((u8 *) &salt, sizeof(salt)) < 0) {
+ os_free(buf);
+ return 0;
+ }
+ salt |= 0x8000;
WPA_PUT_BE16(pos, salt);
pos += 2;
encrypt_ms_key(send_key, send_key_len, salt, req_authenticator, secret,
};
+static int cmp_int(const void *a, const void *b)
+{
+ int x, y;
+
+ x = *((int *) a);
+ y = *((int *) b);
+ return (x - y);
+}
+
+
/**
* radius_msg_get_vlanid - Parse RADIUS attributes for VLAN tunnel information
+ * The k tagged vlans found are sorted by vlan_id and stored in the first k
+ * items of tagged.
+ *
* @msg: RADIUS message
- * Returns: VLAN ID for the first tunnel configuration or 0 if none is found
+ * @untagged: Pointer to store untagged vid
+ * @numtagged: Size of tagged
+ * @tagged: Pointer to store tagged list
+ *
+ * Returns: 0 if neither tagged nor untagged configuration is found, 1 otherwise
*/
-int radius_msg_get_vlanid(struct radius_msg *msg)
+int radius_msg_get_vlanid(struct radius_msg *msg, int *untagged, int numtagged,
+ int *tagged)
{
struct radius_tunnel_attrs tunnel[RADIUS_TUNNEL_TAGS], *tun;
size_t i;
const u8 *data;
char buf[10];
size_t dlen;
+ int j, taggedidx = 0, vlan_id;
os_memset(&tunnel, 0, sizeof(tunnel));
+ for (j = 0; j < numtagged; j++)
+ tagged[j] = 0;
+ *untagged = 0;
for (i = 0; i < msg->attr_used; i++) {
attr = radius_get_attr_hdr(msg, i);
break;
os_memcpy(buf, data, dlen);
buf[dlen] = '\0';
+ vlan_id = atoi(buf);
+ if (vlan_id <= 0)
+ break;
tun->tag_used++;
- tun->vlanid = atoi(buf);
+ tun->vlanid = vlan_id;
+ break;
+ case RADIUS_ATTR_EGRESS_VLANID: /* RFC 4675 */
+ if (attr->length != 6)
+ break;
+ vlan_id = WPA_GET_BE24(data + 1);
+ if (vlan_id <= 0)
+ break;
+ if (data[0] == 0x32)
+ *untagged = vlan_id;
+ else if (data[0] == 0x31 && tagged &&
+ taggedidx < numtagged)
+ tagged[taggedidx++] = vlan_id;
break;
}
}
+ /* Use tunnel with the lowest tag for untagged VLAN id */
for (i = 0; i < RADIUS_TUNNEL_TAGS; i++) {
tun = &tunnel[i];
if (tun->tag_used &&
tun->type == RADIUS_TUNNEL_TYPE_VLAN &&
tun->medium_type == RADIUS_TUNNEL_MEDIUM_TYPE_802 &&
- tun->vlanid > 0)
- return tun->vlanid;
+ tun->vlanid > 0) {
+ *untagged = tun->vlanid;
+ break;
+ }
}
+ if (taggedidx)
+ qsort(tagged, taggedidx, sizeof(int), cmp_int);
+
+ if (*untagged > 0 || taggedidx)
+ return 1;
return 0;
}
return 0;
}
+
+
+int radius_gen_session_id(u8 *id, size_t len)
+{
+ /*
+ * Acct-Session-Id and Acct-Multi-Session-Id should be globally and
+ * temporarily unique. A high quality random number is required
+ * therefore. This could be be improved by switching to a GUID.
+ */
+ return os_get_random(id, len);
+}
/*
* 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.
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,
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,
};
+/* 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
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);
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);
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);
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 */
* next_radius_identifier - Next RADIUS message identifier to use
*/
u8 next_radius_identifier;
+
+ /**
+ * interim_error_cb - Interim accounting error callback
+ */
+ void (*interim_error_cb)(const u8 *addr, void *ctx);
+
+ /**
+ * interim_error_cb_ctx - interim_error_cb() context data
+ */
+ void *interim_error_cb_ctx;
};
}
+/**
+ * radius_client_set_interim_erro_cb - Register an interim acct error callback
+ * @radius: RADIUS client context from radius_client_init()
+ * @addr: Station address from the failed message
+ * @cb: Handler for interim accounting errors
+ * @ctx: Context pointer for handler callbacks
+ *
+ * This function is used to register a handler for processing failed
+ * transmission attempts of interim accounting update messages.
+ */
+void radius_client_set_interim_error_cb(struct radius_client_data *radius,
+ void (*cb)(const u8 *addr, void *ctx),
+ void *ctx)
+{
+ radius->interim_error_cb = cb;
+ radius->interim_error_cb_ctx = ctx;
+}
+
+
/*
* Returns >0 if message queue was flushed (i.e., the message that triggered
* the error is not available anymore)
int _errno = errno;
wpa_printf(MSG_INFO, "send[RADIUS,s=%d]: %s", s, strerror(errno));
if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL ||
- _errno == EBADF || _errno == ENETUNREACH) {
+ _errno == EBADF || _errno == ENETUNREACH || _errno == EACCES) {
hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
HOSTAPD_LEVEL_INFO,
"Send failed - maybe interface status changed -"
int s;
struct wpabuf *buf;
size_t prev_num_msgs;
+ u8 *acct_delay_time;
+ size_t acct_delay_time_len;
if (entry->msg_type == RADIUS_ACCT ||
entry->msg_type == RADIUS_ACCT_INTERIM) {
conf->auth_server->retransmissions++;
}
}
+
+ if (entry->msg_type == RADIUS_ACCT_INTERIM) {
+ wpa_printf(MSG_DEBUG,
+ "RADIUS: Failed to transmit interim accounting update to "
+ MACSTR " - drop message and request a new update",
+ MAC2STR(entry->addr));
+ if (radius->interim_error_cb)
+ radius->interim_error_cb(entry->addr,
+ radius->interim_error_cb_ctx);
+ return 1;
+ }
+
if (s < 0) {
wpa_printf(MSG_INFO,
"RADIUS: No valid socket for retransmission");
return 1;
}
+ if (entry->msg_type == RADIUS_ACCT &&
+ radius_msg_get_attr_ptr(entry->msg, RADIUS_ATTR_ACCT_DELAY_TIME,
+ &acct_delay_time, &acct_delay_time_len,
+ NULL) == 0 &&
+ acct_delay_time_len == 4) {
+ struct radius_hdr *hdr;
+ u32 delay_time;
+
+ /*
+ * Need to assign a new identifier since attribute contents
+ * changes.
+ */
+ hdr = radius_msg_get_hdr(entry->msg);
+ hdr->identifier = radius_client_get_id(radius);
+
+ /* Update Acct-Delay-Time to show wait time in queue */
+ delay_time = now - entry->first_try;
+ WPA_PUT_BE32(acct_delay_time, delay_time);
+
+ wpa_printf(MSG_DEBUG,
+ "RADIUS: Updated Acct-Delay-Time to %u for retransmission",
+ delay_time);
+ radius_msg_finish_acct(entry->msg, entry->shared_secret,
+ entry->shared_secret_len);
+ if (radius->conf->msg_dumps)
+ radius_msg_dump(entry->msg);
+ }
+
/* retransmit; remove entry if too many attempts */
entry->attempts++;
hostapd_logger(radius->ctx, entry->addr, HOSTAPD_MODULE_RADIUS,
static void radius_client_timer(void *eloop_ctx, void *timeout_ctx)
{
struct radius_client_data *radius = eloop_ctx;
- struct hostapd_radius_servers *conf = radius->conf;
struct os_reltime now;
os_time_t first;
struct radius_msg_list *entry, *prev, *tmp;
(long int) (first - now.sec));
}
- if (auth_failover && conf->num_auth_servers > 1)
+ if (auth_failover)
radius_client_auth_failover(radius);
- if (acct_failover && conf->num_acct_servers > 1)
+ if (acct_failover)
radius_client_acct_failover(radius);
}
}
-static void radius_client_list_del(struct radius_client_data *radius,
- RadiusType msg_type, const u8 *addr)
-{
- struct radius_msg_list *entry, *prev, *tmp;
-
- if (addr == NULL)
- return;
-
- entry = radius->msgs;
- prev = NULL;
- while (entry) {
- if (entry->msg_type == msg_type &&
- os_memcmp(entry->addr, addr, ETH_ALEN) == 0) {
- if (prev)
- prev->next = entry->next;
- else
- radius->msgs = entry->next;
- tmp = entry;
- entry = entry->next;
- hostapd_logger(radius->ctx, addr,
- HOSTAPD_MODULE_RADIUS,
- HOSTAPD_LEVEL_DEBUG,
- "Removing matching RADIUS message");
- radius_client_msg_free(tmp);
- radius->num_msgs--;
- continue;
- }
- prev = entry;
- entry = entry->next;
- }
-}
-
-
/**
* radius_client_send - Send a RADIUS request
* @radius: RADIUS client context from radius_client_init()
* This function is used to transmit a RADIUS authentication (RADIUS_AUTH) or
* accounting request (RADIUS_ACCT or RADIUS_ACCT_INTERIM). The only difference
* between accounting and interim accounting messages is that the interim
- * message will override any pending interim accounting updates while a new
- * accounting message does not remove any pending messages.
+ * message will not be retransmitted. Instead, a callback is used to indicate
+ * that the transmission failed for the specific station @addr so that a new
+ * interim accounting update message can be generated with up-to-date session
+ * data instead of trying to resend old information.
*
* The message is added on the retransmission queue and will be retransmitted
* automatically until a response is received or maximum number of retries
- * (RADIUS_CLIENT_MAX_RETRIES) is reached.
+ * (RADIUS_CLIENT_MAX_RETRIES) is reached. No such retries are used with
+ * RADIUS_ACCT_INTERIM, i.e., such a pending message is removed from the queue
+ * automatically on transmission failure.
*
* The related device MAC address can be used to identify pending messages that
- * can be removed with radius_client_flush_auth() or with interim accounting
- * updates.
+ * can be removed with radius_client_flush_auth().
*/
int radius_client_send(struct radius_client_data *radius,
struct radius_msg *msg, RadiusType msg_type,
int s, res;
struct wpabuf *buf;
- if (msg_type == RADIUS_ACCT_INTERIM) {
- /* Remove any pending interim acct update for the same STA. */
- radius_client_list_del(radius, msg_type, addr);
- }
-
if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) {
if (conf->acct_server && radius->acct_sock < 0)
radius_client_init_acct(radius);
int sel_sock;
struct radius_msg_list *entry;
struct hostapd_radius_servers *conf = radius->conf;
+ struct sockaddr_in disconnect_addr = {
+ .sin_family = AF_UNSPEC,
+ };
hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS,
HOSTAPD_LEVEL_INFO,
hostapd_ip_txt(&nserv->addr, abuf, sizeof(abuf)),
nserv->port);
+ if (oserv && oserv == nserv) {
+ /* Reconnect to same server, flush */
+ if (auth)
+ radius_client_flush(radius, 1);
+ }
+
if (oserv && oserv != nserv &&
(nserv->shared_secret_len != oserv->shared_secret_len ||
os_memcmp(nserv->shared_secret, oserv->shared_secret,
}
}
+ /* Force a reconnect by disconnecting the socket first */
+ if (connect(sel_sock, (struct sockaddr *) &disconnect_addr,
+ sizeof(disconnect_addr)) < 0)
+ wpa_printf(MSG_INFO, "disconnect[radius]: %s", strerror(errno));
+
if (connect(sel_sock, addr, addrlen) < 0) {
wpa_printf(MSG_INFO, "connect[radius]: %s", strerror(errno));
return -1;
int radius_client_get_mib(struct radius_client_data *radius, char *buf,
size_t buflen)
{
- struct hostapd_radius_servers *conf = radius->conf;
+ struct hostapd_radius_servers *conf;
int i;
struct hostapd_radius_server *serv;
int count = 0;
+ if (!radius)
+ return 0;
+
+ conf = radius->conf;
+
if (conf->auth_servers) {
for (i = 0; i < conf->num_auth_servers; i++) {
serv = &conf->auth_servers[i];
const u8 *shared_secret, size_t shared_secret_len,
void *data),
void *data);
+void radius_client_set_interim_error_cb(struct radius_client_data *radius,
+ void (*cb)(const u8 *addr, void *ctx),
+ void *ctx);
int radius_client_send(struct radius_client_data *radius,
struct radius_msg *msg,
RadiusType msg_type, const u8 *addr);
struct hostapd_ip_addr client_addr;
unsigned int time_window;
int require_event_timestamp;
+ int require_message_authenticator;
void *ctx;
enum radius_das_res (*disconnect)(void *ctx,
struct radius_das_attrs *attr);
radius_msg_dump(msg);
if (radius_msg_verify_das_req(msg, das->shared_secret,
- das->shared_secret_len)) {
- wpa_printf(MSG_DEBUG, "DAS: Invalid authenticator in packet "
- "from %s:%d - drop", abuf, from_port);
+ das->shared_secret_len,
+ das->require_message_authenticator)) {
+ wpa_printf(MSG_DEBUG,
+ "DAS: Invalid authenticator or Message-Authenticator in packet from %s:%d - drop",
+ abuf, from_port);
goto fail;
}
das->time_window = conf->time_window;
das->require_event_timestamp = conf->require_event_timestamp;
+ das->require_message_authenticator =
+ conf->require_message_authenticator;
das->ctx = conf->ctx;
das->disconnect = conf->disconnect;
const struct hostapd_ip_addr *client_addr;
unsigned int time_window;
int require_event_timestamp;
+ int require_message_authenticator;
void *ctx;
enum radius_das_res (*disconnect)(void *ctx,
struct radius_das_attrs *attr);
#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;
* @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
*/
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)
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);
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)
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_* */
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,
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);
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;
#include "wpa_i.h"
-#ifdef IEEE8021X_EAPOL
+#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA)
#define PMKID_CANDIDATE_PRIO_SCAN 1000
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,
return sm->preauth_eapol != NULL;
}
-#endif /* IEEE8021X_EAPOL */
+#endif /* IEEE8021X_EAPOL && !CONFIG_NO_WPA */
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,
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)
{
return 0;
}
-#endif /* IEEE8021X_EAPOL */
+#endif /* IEEE8021X_EAPOL && !CONFIG_NO_WPA */
#endif /* PREAUTH_H */
*/
if (peer->initiator) {
+ u8 addr[ETH_ALEN];
+
wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR
" - try to renew", MAC2STR(peer->addr));
- wpa_tdls_start(sm, peer->addr);
+ /* cache the peer address before do_teardown */
+ os_memcpy(addr, peer->addr, ETH_ALEN);
+ wpa_tdls_do_teardown(sm, peer,
+ WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
+ wpa_tdls_start(sm, addr);
} else {
wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR
" - tear down", MAC2STR(peer->addr));
"ignore TPK M2 from " MACSTR, MAC2STR(src_addr));
return -1;
}
+
+ if (peer->tpk_success) {
+ wpa_printf(MSG_INFO, "TDLS: Ignore incoming TPK M2 retry, from "
+ MACSTR " as TPK M3 was already sent",
+ MAC2STR(src_addr));
+ return 0;
+ }
+
wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_REQUEST);
if (len < 3 + 2 + 1) {
kde.ftie, sizeof(*ftie));
ftie = (struct wpa_tdls_ftie *) kde.ftie;
- if (!os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) == 0) {
+ if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0) {
wpa_printf(MSG_INFO, "TDLS: FTIE SNonce in TPK M2 does "
"not match with FTIE SNonce used in TPK M1");
/* Silently discard the frame */
wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Confirm / "
"TPK Handshake Message 3");
if (wpa_tdls_send_tpk_m3(sm, src_addr, dtoken, lnkid, peer) < 0)
- goto error;
+ goto error_no_msg;
if (!peer->tpk_success) {
/*
error:
wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken, 1,
status);
+error_no_msg:
wpa_tdls_disable_peer_link(sm, peer);
return -1;
}
goto error;
}
- if (!os_memcmp(peer->rnonce, ftie->Anonce, WPA_NONCE_LEN) == 0) {
+ if (os_memcmp(peer->rnonce, ftie->Anonce, WPA_NONCE_LEN) != 0) {
wpa_printf(MSG_INFO, "TDLS: FTIE ANonce in TPK M3 does "
"not match with FTIE ANonce used in TPK M2");
goto error;
}
- if (!os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) == 0) {
+ if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0) {
wpa_printf(MSG_INFO, "TDLS: FTIE SNonce in TPK M3 does not "
"match with FTIE SNonce used in TPK M1");
goto error;
/*
* 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.
#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()
* @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)) {
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;
}
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)
#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];
!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,
* 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;
}
* @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,
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,
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);
}
os_memset(buf, 0, sizeof(buf));
}
sm->tptk_set = 1;
+ sm->tk_to_set = 1;
kde = sm->assoc_wpa_ie;
kde_len = sm->assoc_wpa_ie_len;
#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);
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->tk_to_set) {
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "WPA: Do not re-install same PTK to the driver");
+ return 0;
+ }
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
"WPA: Installing PTK to the driver");
/* TK is not needed anymore in supplicant */
os_memset(sm->ptk.tk, 0, WPA_TK_MAX_LEN);
+ sm->tk_to_set = 0;
if (sm->wpa_ptk_rekey) {
eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
}
+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
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))) {
+ wpa_supplicant_install_gtk(sm, &gd, key_rsc))) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
"RSN: Failed to install GTK");
os_memset(&gd, 0, sizeof(gd));
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:
* @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,
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);
}
#endif /* CONFIG_P2P */
if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info,
- &sm->ptk)) {
+ &sm->ptk) < 0) {
goto failed;
}
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);
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);
}
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,
if (ret)
goto failed;
- if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc) ||
- 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) ||
+ wpa_supplicant_send_2_of_2(sm, key, ver, key_info) < 0)
goto failed;
os_memset(&gd, 0, sizeof(gd));
}
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,
#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);
}
* @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;
#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);
}
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;
sm->ssid_len = 0;
sm->wpa_ptk_rekey = 0;
sm->p2p = 0;
+ sm->wpa_rsc_relaxation = 0;
}
}
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;
}
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 */
size_t ssid_len;
int wpa_ptk_rekey;
int p2p;
+ int wpa_rsc_relaxation;
};
#ifndef CONFIG_NO_WPA
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);
}
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)
{
}
}
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)
{
}
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 */
* 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;
unsigned int msg_3_of_4_ok:1;
+ unsigned int tk_to_set:1;
u8 snonce[WPA_NONCE_LEN];
u8 anonce[WPA_NONCE_LEN]; /* ANonce from the last 1/4 msg */
int renew_snonce;
size_t ssid_len;
int wpa_ptk_rekey;
int p2p;
+ int wpa_rsc_relaxation;
u8 own_addr[ETH_ALEN];
const char *ifname;
#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 */
};
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,
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;
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));
tlsv1_client.o \
tlsv1_client_read.o \
tlsv1_client_write.o \
+ tlsv1_client_ocsp.o \
tlsv1_common.o \
tlsv1_cred.o \
tlsv1_record.o \
#define ASN1_TAG_EXTERNAL 0x08 /* not yet parsed */
#define ASN1_TAG_REAL 0x09 /* not yet parsed */
#define ASN1_TAG_ENUMERATED 0x0A /* not yet parsed */
+#define ASN1_TAG_EMBEDDED_PDV 0x0B /* not yet parsed */
#define ASN1_TAG_UTF8STRING 0x0C /* not yet parsed */
#define ANS1_TAG_RELATIVE_OID 0x0D
#define ASN1_TAG_SEQUENCE 0x10 /* shall be constructed */
#define ASN1_TAG_VISIBLESTRING 0x1A
#define ASN1_TAG_GENERALSTRING 0x1B /* not yet parsed */
#define ASN1_TAG_UNIVERSALSTRING 0x1C /* not yet parsed */
-#define ASN1_TAG_BMPSTRING 0x1D /* not yet parsed */
+#define ASN1_TAG_CHARACTERSTRING 0x1D /* not yet parsed */
+#define ASN1_TAG_BMPSTRING 0x1E /* not yet parsed */
#define ASN1_CLASS_UNIVERSAL 0
#define ASN1_CLASS_APPLICATION 1
/*
* PKCS #5 (Password-based Encryption)
- * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
#include "common.h"
#include "crypto/crypto.h"
#include "crypto/md5.h"
+#include "crypto/sha1.h"
#include "asn1.h"
#include "pkcs5.h"
struct pkcs5_params {
enum pkcs5_alg {
PKCS5_ALG_UNKNOWN,
- PKCS5_ALG_MD5_DES_CBC
+ PKCS5_ALG_MD5_DES_CBC,
+ PKCS5_ALG_PBES2,
+ PKCS5_ALG_SHA1_3DES_CBC,
} alg;
- u8 salt[8];
+ u8 salt[64];
size_t salt_len;
unsigned int iter_count;
+ enum pbes2_enc_alg {
+ PBES2_ENC_ALG_UNKNOWN,
+ PBES2_ENC_ALG_DES_EDE3_CBC,
+ } enc_alg;
+ u8 iv[8];
+ size_t iv_len;
};
+static int oid_is_rsadsi(struct asn1_oid *oid)
+{
+ return oid->len >= 4 &&
+ oid->oid[0] == 1 /* iso */ &&
+ oid->oid[1] == 2 /* member-body */ &&
+ oid->oid[2] == 840 /* us */ &&
+ oid->oid[3] == 113549 /* rsadsi */;
+}
+
+
+static int pkcs5_is_oid(struct asn1_oid *oid, unsigned long alg)
+{
+ return oid->len == 7 &&
+ oid_is_rsadsi(oid) &&
+ oid->oid[4] == 1 /* pkcs */ &&
+ oid->oid[5] == 5 /* pkcs-5 */ &&
+ oid->oid[6] == alg;
+}
+
+
+static int enc_alg_is_oid(struct asn1_oid *oid, unsigned long alg)
+{
+ return oid->len == 6 &&
+ oid_is_rsadsi(oid) &&
+ oid->oid[4] == 3 /* encryptionAlgorithm */ &&
+ oid->oid[5] == alg;
+}
+
+
+static int pkcs12_is_pbe_oid(struct asn1_oid *oid, unsigned long alg)
+{
+ return oid->len == 8 &&
+ oid_is_rsadsi(oid) &&
+ oid->oid[4] == 1 /* pkcs */ &&
+ oid->oid[5] == 12 /* pkcs-12 */ &&
+ oid->oid[6] == 1 /* pkcs-12PbeIds */ &&
+ oid->oid[7] == alg;
+}
+
+
static enum pkcs5_alg pkcs5_get_alg(struct asn1_oid *oid)
{
- if (oid->len == 7 &&
- oid->oid[0] == 1 /* iso */ &&
- oid->oid[1] == 2 /* member-body */ &&
- oid->oid[2] == 840 /* us */ &&
- oid->oid[3] == 113549 /* rsadsi */ &&
- oid->oid[4] == 1 /* pkcs */ &&
- oid->oid[5] == 5 /* pkcs-5 */ &&
- oid->oid[6] == 3 /* pbeWithMD5AndDES-CBC */)
+ if (pkcs5_is_oid(oid, 3)) /* pbeWithMD5AndDES-CBC (PBES1) */
return PKCS5_ALG_MD5_DES_CBC;
-
+ if (pkcs12_is_pbe_oid(oid, 3)) /* pbeWithSHAAnd3-KeyTripleDES-CBC */
+ return PKCS5_ALG_SHA1_3DES_CBC;
+ if (pkcs5_is_oid(oid, 13)) /* id-PBES2 (PBES2) */
+ return PKCS5_ALG_PBES2;
return PKCS5_ALG_UNKNOWN;
}
+static int pkcs5_get_params_pbes2(struct pkcs5_params *params, const u8 *pos,
+ const u8 *enc_alg_end)
+{
+ struct asn1_hdr hdr;
+ const u8 *end, *kdf_end;
+ struct asn1_oid oid;
+ char obuf[80];
+
+ /*
+ * RFC 2898, Ch. A.4
+ *
+ * PBES2-params ::= SEQUENCE {
+ * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
+ * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} }
+ *
+ * PBES2-KDFs ALGORITHM-IDENTIFIER ::=
+ * { {PBKDF2-params IDENTIFIED BY id-PBKDF2}, ... }
+ */
+
+ if (asn1_get_next(pos, enc_alg_end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #5: Expected SEQUENCE (PBES2-params) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+ pos = hdr.payload;
+ end = hdr.payload + hdr.length;
+
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #5: Expected SEQUENCE (keyDerivationFunc) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+
+ pos = hdr.payload;
+ kdf_end = end = hdr.payload + hdr.length;
+
+ if (asn1_get_oid(pos, end - pos, &oid, &pos)) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #5: Failed to parse OID (keyDerivationFunc algorithm)");
+ return -1;
+ }
+
+ asn1_oid_to_str(&oid, obuf, sizeof(obuf));
+ wpa_printf(MSG_DEBUG, "PKCS #5: PBES2 keyDerivationFunc algorithm %s",
+ obuf);
+ if (!pkcs5_is_oid(&oid, 12)) /* id-PBKDF2 */ {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #5: Unsupported PBES2 keyDerivationFunc algorithm %s",
+ obuf);
+ return -1;
+ }
+
+ /*
+ * RFC 2898, C.
+ *
+ * PBKDF2-params ::= SEQUENCE {
+ * salt CHOICE {
+ * specified OCTET STRING,
+ * otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}}
+ * },
+ * iterationCount INTEGER (1..MAX),
+ * keyLength INTEGER (1..MAX) OPTIONAL,
+ * prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT
+ * algid-hmacWithSHA1
+ * }
+ */
+
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #5: Expected SEQUENCE (PBKDF2-params) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+
+ pos = hdr.payload;
+ end = hdr.payload + hdr.length;
+
+ /* For now, only support the salt CHOICE specified (OCTET STRING) */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_OCTETSTRING ||
+ hdr.length > sizeof(params->salt)) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #5: Expected OCTET STRING (salt.specified) - found class %d tag 0x%x size %d",
+ hdr.class, hdr.tag, hdr.length);
+ return -1;
+ }
+ pos = hdr.payload + hdr.length;
+ os_memcpy(params->salt, hdr.payload, hdr.length);
+ params->salt_len = hdr.length;
+ wpa_hexdump(MSG_DEBUG, "PKCS #5: salt", params->salt, params->salt_len);
+
+ /* iterationCount INTEGER */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #5: Expected INTEGER - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+ if (hdr.length == 1) {
+ params->iter_count = *hdr.payload;
+ } else if (hdr.length == 2) {
+ params->iter_count = WPA_GET_BE16(hdr.payload);
+ } else if (hdr.length == 4) {
+ params->iter_count = WPA_GET_BE32(hdr.payload);
+ } else {
+ wpa_hexdump(MSG_DEBUG,
+ "PKCS #5: Unsupported INTEGER value (iterationCount)",
+ hdr.payload, hdr.length);
+ return -1;
+ }
+ wpa_printf(MSG_DEBUG, "PKCS #5: iterationCount=0x%x",
+ params->iter_count);
+ if (params->iter_count == 0 || params->iter_count > 0xffff) {
+ wpa_printf(MSG_INFO, "PKCS #5: Unsupported iterationCount=0x%x",
+ params->iter_count);
+ return -1;
+ }
+
+ /* For now, ignore optional keyLength and prf */
+
+ pos = kdf_end;
+
+ /* encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} */
+
+ if (asn1_get_next(pos, enc_alg_end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #5: Expected SEQUENCE (encryptionScheme) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+
+ pos = hdr.payload;
+ end = hdr.payload + hdr.length;
+
+ if (asn1_get_oid(pos, end - pos, &oid, &pos)) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #5: Failed to parse OID (encryptionScheme algorithm)");
+ return -1;
+ }
+
+ asn1_oid_to_str(&oid, obuf, sizeof(obuf));
+ wpa_printf(MSG_DEBUG, "PKCS #5: PBES2 encryptionScheme algorithm %s",
+ obuf);
+ if (enc_alg_is_oid(&oid, 7)) {
+ params->enc_alg = PBES2_ENC_ALG_DES_EDE3_CBC;
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #5: Unsupported PBES2 encryptionScheme algorithm %s",
+ obuf);
+ return -1;
+ }
+
+ /*
+ * RFC 2898, B.2.2:
+ * The parameters field associated with this OID in an
+ * AlgorithmIdentifier shall have type OCTET STRING (SIZE(8)),
+ * specifying the initialization vector for CBC mode.
+ */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_OCTETSTRING ||
+ hdr.length != 8) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #5: Expected OCTET STRING (SIZE(8)) (IV) - found class %d tag 0x%x size %d",
+ hdr.class, hdr.tag, hdr.length);
+ return -1;
+ }
+ os_memcpy(params->iv, hdr.payload, hdr.length);
+ params->iv_len = hdr.length;
+ wpa_hexdump(MSG_DEBUG, "PKCS #5: IV", params->iv, params->iv_len);
+
+ return 0;
+}
+
+
static int pkcs5_get_params(const u8 *enc_alg, size_t enc_alg_len,
struct pkcs5_params *params)
{
return -1;
}
+ if (params->alg == PKCS5_ALG_PBES2)
+ return pkcs5_get_params_pbes2(params, pos, enc_alg_end);
+
+ /* PBES1 */
+
/*
* PKCS#5, Section 8
* PBEParameter ::= SEQUENCE {
* salt OCTET STRING SIZE(8),
* iterationCount INTEGER }
+ *
+ * Note: The same implementation can be used to parse the PKCS #12
+ * version described in RFC 7292, C:
+ * pkcs-12PbeParams ::= SEQUENCE {
+ * salt OCTET STRING,
+ * iterations INTEGER
+ * }
*/
if (asn1_get_next(pos, enc_alg_end - pos, &hdr) < 0 ||
pos = hdr.payload;
end = hdr.payload + hdr.length;
- /* salt OCTET STRING SIZE(8) */
+ /* salt OCTET STRING SIZE(8) (PKCS #5) or OCTET STRING (PKCS #12) */
if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
hdr.class != ASN1_CLASS_UNIVERSAL ||
hdr.tag != ASN1_TAG_OCTETSTRING ||
- hdr.length != 8) {
+ hdr.length > sizeof(params->salt)) {
wpa_printf(MSG_DEBUG, "PKCS #5: Expected OCTETSTRING SIZE(8) "
"(salt) - found class %d tag 0x%x size %d",
hdr.class, hdr.tag, hdr.length);
}
+static struct crypto_cipher *
+pkcs5_crypto_init_pbes2(struct pkcs5_params *params, const char *passwd)
+{
+ u8 key[24];
+
+ if (params->enc_alg != PBES2_ENC_ALG_DES_EDE3_CBC ||
+ params->iv_len != 8)
+ return NULL;
+
+ wpa_hexdump_ascii_key(MSG_DEBUG, "PKCS #5: PBES2 password for PBKDF2",
+ passwd, os_strlen(passwd));
+ wpa_hexdump(MSG_DEBUG, "PKCS #5: PBES2 salt for PBKDF2",
+ params->salt, params->salt_len);
+ wpa_printf(MSG_DEBUG, "PKCS #5: PBES2 PBKDF2 iterations: %u",
+ params->iter_count);
+ if (pbkdf2_sha1(passwd, params->salt, params->salt_len,
+ params->iter_count, key, sizeof(key)) < 0)
+ return NULL;
+ wpa_hexdump_key(MSG_DEBUG, "PKCS #5: DES EDE3 key", key, sizeof(key));
+ wpa_hexdump(MSG_DEBUG, "PKCS #5: DES IV", params->iv, params->iv_len);
+
+ return crypto_cipher_init(CRYPTO_CIPHER_ALG_3DES, params->iv,
+ key, sizeof(key));
+}
+
+
+static void add_byte_array_mod(u8 *a, const u8 *b, size_t len)
+{
+ size_t i;
+ unsigned int carry = 0;
+
+ for (i = len - 1; i < len; i--) {
+ carry = carry + a[i] + b[i];
+ a[i] = carry & 0xff;
+ carry >>= 8;
+ }
+}
+
+
+static int pkcs12_key_gen(const u8 *pw, size_t pw_len, const u8 *salt,
+ size_t salt_len, u8 id, unsigned int iter,
+ size_t out_len, u8 *out)
+{
+ unsigned int u, v, S_len, P_len, i;
+ u8 *D = NULL, *I = NULL, *B = NULL, *pos;
+ int res = -1;
+
+ /* RFC 7292, B.2 */
+ u = SHA1_MAC_LEN;
+ v = 64;
+
+ /* D = copies of ID */
+ D = os_malloc(v);
+ if (!D)
+ goto done;
+ os_memset(D, id, v);
+
+ /* S = copies of salt; P = copies of password, I = S || P */
+ S_len = v * ((salt_len + v - 1) / v);
+ P_len = v * ((pw_len + v - 1) / v);
+ I = os_malloc(S_len + P_len);
+ if (!I)
+ goto done;
+ pos = I;
+ if (salt_len) {
+ for (i = 0; i < S_len; i++)
+ *pos++ = salt[i % salt_len];
+ }
+ if (pw_len) {
+ for (i = 0; i < P_len; i++)
+ *pos++ = pw[i % pw_len];
+ }
+
+ B = os_malloc(v);
+ if (!B)
+ goto done;
+
+ for (;;) {
+ u8 hash[SHA1_MAC_LEN];
+ const u8 *addr[2];
+ size_t len[2];
+
+ addr[0] = D;
+ len[0] = v;
+ addr[1] = I;
+ len[1] = S_len + P_len;
+ if (sha1_vector(2, addr, len, hash) < 0)
+ goto done;
+
+ addr[0] = hash;
+ len[0] = SHA1_MAC_LEN;
+ for (i = 1; i < iter; i++) {
+ if (sha1_vector(1, addr, len, hash) < 0)
+ goto done;
+ }
+
+ if (out_len <= u) {
+ os_memcpy(out, hash, out_len);
+ res = 0;
+ goto done;
+ }
+
+ os_memcpy(out, hash, u);
+ out += u;
+ out_len -= u;
+
+ /* I_j = (I_j + B + 1) mod 2^(v*8) */
+ /* B = copies of Ai (final hash value) */
+ for (i = 0; i < v; i++)
+ B[i] = hash[i % u];
+ inc_byte_array(B, v);
+ for (i = 0; i < S_len + P_len; i += v)
+ add_byte_array_mod(&I[i], B, v);
+ }
+
+done:
+ os_free(B);
+ os_free(I);
+ os_free(D);
+ return res;
+}
+
+
+#define PKCS12_ID_ENC 1
+#define PKCS12_ID_IV 2
+#define PKCS12_ID_MAC 3
+
+static struct crypto_cipher *
+pkcs12_crypto_init_sha1(struct pkcs5_params *params, const char *passwd)
+{
+ unsigned int i;
+ u8 *pw;
+ size_t pw_len;
+ u8 key[24];
+ u8 iv[8];
+
+ if (params->alg != PKCS5_ALG_SHA1_3DES_CBC)
+ return NULL;
+
+ pw_len = passwd ? os_strlen(passwd) : 0;
+ pw = os_malloc(2 * (pw_len + 1));
+ if (!pw)
+ return NULL;
+ if (pw_len) {
+ for (i = 0; i <= pw_len; i++)
+ WPA_PUT_BE16(&pw[2 * i], passwd[i]);
+ pw_len = 2 * (pw_len + 1);
+ }
+
+ if (pkcs12_key_gen(pw, pw_len, params->salt, params->salt_len,
+ PKCS12_ID_ENC, params->iter_count,
+ sizeof(key), key) < 0 ||
+ pkcs12_key_gen(pw, pw_len, params->salt, params->salt_len,
+ PKCS12_ID_IV, params->iter_count,
+ sizeof(iv), iv) < 0) {
+ os_free(pw);
+ return NULL;
+ }
+
+ os_free(pw);
+
+ wpa_hexdump_key(MSG_DEBUG, "PKCS #12: DES key", key, sizeof(key));
+ wpa_hexdump_key(MSG_DEBUG, "PKCS #12: DES IV", iv, sizeof(iv));
+
+ return crypto_cipher_init(CRYPTO_CIPHER_ALG_3DES, iv, key, sizeof(key));
+}
+
+
static struct crypto_cipher * pkcs5_crypto_init(struct pkcs5_params *params,
const char *passwd)
{
const u8 *addr[2];
size_t len[2];
+ if (params->alg == PKCS5_ALG_PBES2)
+ return pkcs5_crypto_init_pbes2(params, passwd);
+
+ if (params->alg == PKCS5_ALG_SHA1_3DES_CBC)
+ return pkcs12_crypto_init_sha1(params, passwd);
+
if (params->alg != PKCS5_ALG_MD5_DES_CBC)
return NULL;
/*
* TLS v1.0/v1.1/v1.2 client (RFC 2246, RFC 4346, RFC 5246)
- * Copyright (c) 2006-2014, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
#include "common.h"
#include "crypto/sha1.h"
#include "crypto/tls.h"
+#include "x509v3.h"
#include "tlsv1_common.h"
#include "tlsv1_record.h"
#include "tlsv1_client.h"
pos += conn->rl.iv_size;
/* server_write_IV */
os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size);
- pos += conn->rl.iv_size;
} else {
/*
* Use IV field to set the mask value for TLS v1.1. A fixed
tlsv1_client_free_dh(conn);
tlsv1_cred_free(conn->cred);
wpabuf_free(conn->partial_input);
+ x509_certificate_chain_free(conn->server_cert);
os_free(conn);
}
if (data == NULL || data_len == 0)
return 0;
- pos = conn->client_hello_ext = os_malloc(6 + data_len);
+ pos = conn->client_hello_ext = os_malloc(4 + data_len);
if (pos == NULL)
return -1;
- WPA_PUT_BE16(pos, 4 + data_len);
- pos += 2;
WPA_PUT_BE16(pos, ext_type);
pos += 2;
WPA_PUT_BE16(pos, data_len);
pos += 2;
os_memcpy(pos, data, data_len);
- conn->client_hello_ext_len = 6 + data_len;
+ conn->client_hello_ext_len = 4 + data_len;
if (ext_type == TLS_EXT_PAC_OPAQUE) {
conn->session_ticket_included = 1;
}
-void tlsv1_client_set_time_checks(struct tlsv1_client *conn, int enabled)
+/**
+ * tlsv1_client_set_flags - Set connection flags
+ * @conn: TLSv1 client connection data from tlsv1_client_init()
+ * @flags: TLS_CONN_* bitfield
+ */
+void tlsv1_client_set_flags(struct tlsv1_client *conn, unsigned int flags)
{
- conn->disable_time_checks = !enabled;
+ conn->flags = flags;
}
conn->session_ticket_cb = cb;
conn->session_ticket_cb_ctx = 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)
+{
+ conn->event_cb = event_cb;
+ conn->cb_ctx = cb_ctx;
+ conn->cert_in_cb = !!cert_in_cb;
+}
+
+
+int tlsv1_client_get_version(struct tlsv1_client *conn, char *buf,
+ size_t buflen)
+{
+ if (!conn)
+ return -1;
+ switch (conn->rl.tls_version) {
+ case TLS_VERSION_1:
+ os_strlcpy(buf, "TLSv1", buflen);
+ break;
+ case TLS_VERSION_1_1:
+ os_strlcpy(buf, "TLSv1.1", buflen);
+ break;
+ case TLS_VERSION_1_2:
+ os_strlcpy(buf, "TLSv1.2", buflen);
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
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,
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 */
u8 alert_level;
u8 alert_description;
+ unsigned int flags; /* TLS_CONN_* bitfield */
+
unsigned int certificate_requested:1;
unsigned int session_resumed:1;
unsigned int session_ticket_included:1;
unsigned int use_session_ticket:1;
- unsigned int disable_time_checks:1;
+ unsigned int cert_in_cb:1;
+ unsigned int ocsp_resp_received:1;
struct crypto_public_key *server_rsa_key;
void *session_ticket_cb_ctx;
struct wpabuf *partial_input;
+
+ void (*event_cb)(void *ctx, enum tls_event ev,
+ union tls_event_data *data);
+ void *cb_ctx;
+
+ struct x509_certificate *server_cert;
};
const u8 *buf, size_t *len,
u8 **out_data, size_t *out_len);
+enum tls_ocsp_result {
+ TLS_OCSP_NO_RESPONSE, TLS_OCSP_INVALID, TLS_OCSP_GOOD, TLS_OCSP_REVOKED
+};
+
+enum tls_ocsp_result tls_process_ocsp_response(struct tlsv1_client *conn,
+ const u8 *resp, size_t len);
+
#endif /* TLSV1_CLIENT_I_H */
--- /dev/null
+/*
+ * TLSv1 client - OCSP
+ * 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.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "crypto/tls.h"
+#include "crypto/sha1.h"
+#include "asn1.h"
+#include "x509v3.h"
+#include "tlsv1_common.h"
+#include "tlsv1_record.h"
+#include "tlsv1_client.h"
+#include "tlsv1_client_i.h"
+
+
+/* RFC 6960, 4.2.1: OCSPResponseStatus ::= ENUMERATED */
+enum ocsp_response_status {
+ OCSP_RESP_STATUS_SUCCESSFUL = 0,
+ OCSP_RESP_STATUS_MALFORMED_REQ = 1,
+ OCSP_RESP_STATUS_INT_ERROR = 2,
+ OCSP_RESP_STATUS_TRY_LATER = 3,
+ /* 4 not used */
+ OCSP_RESP_STATUS_SIG_REQUIRED = 5,
+ OCSP_RESP_STATUS_UNAUTHORIZED = 6,
+};
+
+
+static int is_oid_basic_ocsp_resp(struct asn1_oid *oid)
+{
+ return oid->len == 10 &&
+ oid->oid[0] == 1 /* iso */ &&
+ oid->oid[1] == 3 /* identified-organization */ &&
+ oid->oid[2] == 6 /* dod */ &&
+ oid->oid[3] == 1 /* internet */ &&
+ oid->oid[4] == 5 /* security */ &&
+ oid->oid[5] == 5 /* mechanisms */ &&
+ oid->oid[6] == 7 /* id-pkix */ &&
+ oid->oid[7] == 48 /* id-ad */ &&
+ oid->oid[8] == 1 /* id-pkix-ocsp */ &&
+ oid->oid[9] == 1 /* id-pkix-ocsp-basic */;
+}
+
+
+static int ocsp_responder_id_match(struct x509_certificate *signer,
+ struct x509_name *name, const u8 *key_hash)
+{
+ if (key_hash) {
+ u8 hash[SHA1_MAC_LEN];
+ const u8 *addr[1] = { signer->public_key };
+ size_t len[1] = { signer->public_key_len };
+
+ if (sha1_vector(1, addr, len, hash) < 0)
+ return 0;
+ return os_memcmp(hash, key_hash, SHA1_MAC_LEN) == 0;
+ }
+
+ return x509_name_compare(&signer->subject, name) == 0;
+}
+
+
+static unsigned int ocsp_hash_data(struct asn1_oid *alg, const u8 *data,
+ size_t data_len, u8 *hash)
+{
+ const u8 *addr[1] = { data };
+ size_t len[1] = { data_len };
+ char buf[100];
+
+ if (x509_sha1_oid(alg)) {
+ if (sha1_vector(1, addr, len, hash) < 0)
+ return 0;
+ wpa_hexdump(MSG_MSGDUMP, "OCSP: Hash (SHA1)", hash, 20);
+ return 20;
+ }
+
+ if (x509_sha256_oid(alg)) {
+ if (sha256_vector(1, addr, len, hash) < 0)
+ return 0;
+ wpa_hexdump(MSG_MSGDUMP, "OCSP: Hash (SHA256)", hash, 32);
+ return 32;
+ }
+
+ if (x509_sha384_oid(alg)) {
+ if (sha384_vector(1, addr, len, hash) < 0)
+ return 0;
+ wpa_hexdump(MSG_MSGDUMP, "OCSP: Hash (SHA384)", hash, 48);
+ return 48;
+ }
+
+ if (x509_sha512_oid(alg)) {
+ if (sha512_vector(1, addr, len, hash) < 0)
+ return 0;
+ wpa_hexdump(MSG_MSGDUMP, "OCSP: Hash (SHA512)", hash, 64);
+ return 64;
+ }
+
+
+ asn1_oid_to_str(alg, buf, sizeof(buf));
+ wpa_printf(MSG_DEBUG, "OCSP: Could not calculate hash with alg %s",
+ buf);
+ return 0;
+}
+
+
+static int tls_process_ocsp_single_response(struct tlsv1_client *conn,
+ struct x509_certificate *cert,
+ struct x509_certificate *issuer,
+ const u8 *resp, size_t len,
+ enum tls_ocsp_result *res)
+{
+ struct asn1_hdr hdr;
+ const u8 *pos, *end;
+ struct x509_algorithm_identifier alg;
+ const u8 *name_hash, *key_hash;
+ size_t name_hash_len, key_hash_len;
+ const u8 *serial_number;
+ size_t serial_number_len;
+ u8 hash[64];
+ unsigned int hash_len;
+ unsigned int cert_status;
+ os_time_t update;
+ struct os_time now;
+
+ wpa_hexdump(MSG_MSGDUMP, "OCSP: SingleResponse", resp, len);
+
+ /*
+ * SingleResponse ::= SEQUENCE {
+ * certID CertID,
+ * certStatus CertStatus,
+ * thisUpdate GeneralizedTime,
+ * nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
+ * singleExtensions [1] EXPLICIT Extensions OPTIONAL }
+ */
+
+ /* CertID ::= SEQUENCE */
+ if (asn1_get_next(resp, len, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Expected SEQUENCE (CertID) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+ pos = hdr.payload;
+ end = hdr.payload + hdr.length;
+
+ /*
+ * CertID ::= SEQUENCE {
+ * hashAlgorithm AlgorithmIdentifier,
+ * issuerNameHash OCTET STRING,
+ * issuerKeyHash OCTET STRING,
+ * serialNumber CertificateSerialNumber }
+ */
+
+ /* hashAlgorithm AlgorithmIdentifier */
+ if (x509_parse_algorithm_identifier(pos, end - pos, &alg, &pos))
+ return -1;
+
+ /* issuerNameHash OCTET STRING */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_OCTETSTRING) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Expected OCTET STRING (issuerNameHash) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+ name_hash = hdr.payload;
+ name_hash_len = hdr.length;
+ wpa_hexdump(MSG_DEBUG, "OCSP: issuerNameHash",
+ name_hash, name_hash_len);
+ pos = hdr.payload + hdr.length;
+
+ wpa_hexdump(MSG_DEBUG, "OCSP: Issuer subject DN",
+ issuer->subject_dn, issuer->subject_dn_len);
+ hash_len = ocsp_hash_data(&alg.oid, issuer->subject_dn,
+ issuer->subject_dn_len, hash);
+ if (hash_len == 0 || name_hash_len != hash_len ||
+ os_memcmp(name_hash, hash, hash_len) != 0) {
+ wpa_printf(MSG_DEBUG, "OCSP: issuerNameHash mismatch");
+ wpa_hexdump(MSG_DEBUG, "OCSP: Calculated issuerNameHash",
+ hash, hash_len);
+ return -1;
+ }
+
+ /* issuerKeyHash OCTET STRING */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_OCTETSTRING) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Expected OCTET STRING (issuerKeyHash) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+ key_hash = hdr.payload;
+ key_hash_len = hdr.length;
+ wpa_hexdump(MSG_DEBUG, "OCSP: issuerKeyHash", key_hash, key_hash_len);
+ pos = hdr.payload + hdr.length;
+
+ hash_len = ocsp_hash_data(&alg.oid, issuer->public_key,
+ issuer->public_key_len, hash);
+ if (hash_len == 0 || key_hash_len != hash_len ||
+ os_memcmp(key_hash, hash, hash_len) != 0) {
+ wpa_printf(MSG_DEBUG, "OCSP: issuerKeyHash mismatch");
+ wpa_hexdump(MSG_DEBUG, "OCSP: Calculated issuerKeyHash",
+ hash, hash_len);
+ return -1;
+ }
+
+ /* serialNumber CertificateSerialNumber ::= INTEGER */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_INTEGER ||
+ hdr.length < 1 || hdr.length > X509_MAX_SERIAL_NUM_LEN) {
+ wpa_printf(MSG_DEBUG, "OCSP: No INTEGER tag found for serialNumber; class=%d tag=0x%x length=%u",
+ hdr.class, hdr.tag, hdr.length);
+ return -1;
+ }
+ serial_number = hdr.payload;
+ serial_number_len = hdr.length;
+ while (serial_number_len > 0 && serial_number[0] == 0) {
+ serial_number++;
+ serial_number_len--;
+ }
+ wpa_hexdump(MSG_MSGDUMP, "OCSP: serialNumber", serial_number,
+ serial_number_len);
+
+ if (serial_number_len != cert->serial_number_len ||
+ os_memcmp(serial_number, cert->serial_number,
+ serial_number_len) != 0) {
+ wpa_printf(MSG_DEBUG, "OCSP: serialNumber mismatch");
+ return -1;
+ }
+
+ pos = end;
+ end = resp + len;
+
+ /* certStatus CertStatus ::= CHOICE */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Expected CHOICE (CertStatus) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+ cert_status = hdr.tag;
+ wpa_printf(MSG_DEBUG, "OCSP: certStatus=%u", cert_status);
+ wpa_hexdump(MSG_DEBUG, "OCSP: CertStatus additional data",
+ hdr.payload, hdr.length);
+ pos = hdr.payload + hdr.length;
+
+ os_get_time(&now);
+ /* thisUpdate GeneralizedTime */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_GENERALIZEDTIME ||
+ x509_parse_time(hdr.payload, hdr.length, hdr.tag, &update) < 0) {
+ wpa_printf(MSG_DEBUG, "OCSP: Failed to parse thisUpdate");
+ return -1;
+ }
+ wpa_printf(MSG_DEBUG, "OCSP: thisUpdate %lu", (unsigned long) update);
+ pos = hdr.payload + hdr.length;
+ if ((unsigned long) now.sec < (unsigned long) update) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: thisUpdate time in the future (response not yet valid)");
+ return -1;
+ }
+
+ /* nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL */
+ if (pos < end) {
+ if (asn1_get_next(pos, end - pos, &hdr) < 0)
+ return -1;
+ if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC && hdr.tag == 0) {
+ const u8 *next = hdr.payload + hdr.length;
+
+ if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_GENERALIZEDTIME ||
+ x509_parse_time(hdr.payload, hdr.length, hdr.tag,
+ &update) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Failed to parse nextUpdate");
+ return -1;
+ }
+ wpa_printf(MSG_DEBUG, "OCSP: nextUpdate %lu",
+ (unsigned long) update);
+ pos = next;
+ if ((unsigned long) now.sec > (unsigned long) update) {
+ wpa_printf(MSG_DEBUG, "OCSP: nextUpdate time in the past (response has expired)");
+ return -1;
+ }
+ }
+ }
+
+ /* singleExtensions [1] EXPLICIT Extensions OPTIONAL */
+ if (pos < end) {
+ wpa_hexdump(MSG_MSGDUMP, "OCSP: singleExtensions",
+ pos, end - pos);
+ /* Ignore for now */
+ }
+
+ if (cert_status == 0 /* good */)
+ *res = TLS_OCSP_GOOD;
+ else if (cert_status == 1 /* revoked */)
+ *res = TLS_OCSP_REVOKED;
+ else
+ return -1;
+ return 0;
+}
+
+
+static enum tls_ocsp_result
+tls_process_ocsp_responses(struct tlsv1_client *conn,
+ struct x509_certificate *cert,
+ struct x509_certificate *issuer, const u8 *resp,
+ size_t len)
+{
+ struct asn1_hdr hdr;
+ const u8 *pos, *end;
+ enum tls_ocsp_result res;
+
+ pos = resp;
+ end = resp + len;
+ while (pos < end) {
+ /* SingleResponse ::= SEQUENCE */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Expected SEQUENCE (SingleResponse) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return TLS_OCSP_INVALID;
+ }
+ if (tls_process_ocsp_single_response(conn, cert, issuer,
+ hdr.payload, hdr.length,
+ &res) == 0)
+ return res;
+ pos = hdr.payload + hdr.length;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Did not find a response matching the server certificate");
+ return TLS_OCSP_NO_RESPONSE;
+}
+
+
+static enum tls_ocsp_result
+tls_process_basic_ocsp_response(struct tlsv1_client *conn,
+ struct x509_certificate *srv_cert,
+ const u8 *resp, size_t len)
+{
+ struct asn1_hdr hdr;
+ const u8 *pos, *end;
+ const u8 *resp_data, *sign_value, *key_hash = NULL, *responses;
+ const u8 *resp_data_signed;
+ size_t resp_data_len, sign_value_len, responses_len;
+ size_t resp_data_signed_len;
+ struct x509_algorithm_identifier alg;
+ struct x509_certificate *certs = NULL, *last_cert = NULL;
+ struct x509_certificate *issuer, *signer;
+ struct x509_name name; /* used if key_hash == NULL */
+ char buf[100];
+ os_time_t produced_at;
+ enum tls_ocsp_result res;
+
+ wpa_hexdump(MSG_MSGDUMP, "OCSP: BasicOCSPResponse", resp, len);
+
+ os_memset(&name, 0, sizeof(name));
+
+ /*
+ * RFC 6960, 4.2.1:
+ * BasicOCSPResponse ::= SEQUENCE {
+ * tbsResponseData ResponseData,
+ * signatureAlgorithm AlgorithmIdentifier,
+ * signature BIT STRING,
+ * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
+ */
+
+ if (asn1_get_next(resp, len, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Expected SEQUENCE (BasicOCSPResponse) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return TLS_OCSP_INVALID;
+ }
+ pos = hdr.payload;
+ end = hdr.payload + hdr.length;
+
+ /* ResponseData ::= SEQUENCE */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Expected SEQUENCE (ResponseData) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return TLS_OCSP_INVALID;
+ }
+ resp_data = hdr.payload;
+ resp_data_len = hdr.length;
+ resp_data_signed = pos;
+ pos = hdr.payload + hdr.length;
+ resp_data_signed_len = pos - resp_data_signed;
+
+ /* signatureAlgorithm AlgorithmIdentifier */
+ if (x509_parse_algorithm_identifier(pos, end - pos, &alg, &pos))
+ return TLS_OCSP_INVALID;
+
+ /* signature BIT STRING */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_BITSTRING) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Expected BITSTRING (signature) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return TLS_OCSP_INVALID;
+ }
+ if (hdr.length < 1)
+ return TLS_OCSP_INVALID;
+ pos = hdr.payload;
+ if (*pos) {
+ wpa_printf(MSG_DEBUG, "OCSP: BITSTRING - %d unused bits", *pos);
+ /* PKCS #1 v1.5 10.2.1:
+ * It is an error if the length in bits of the signature S is
+ * not a multiple of eight.
+ */
+ return TLS_OCSP_INVALID;
+ }
+ sign_value = pos + 1;
+ sign_value_len = hdr.length - 1;
+ pos += hdr.length;
+ wpa_hexdump(MSG_MSGDUMP, "OCSP: signature", sign_value, sign_value_len);
+
+ /* certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL */
+ if (pos < end) {
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
+ hdr.tag != 0) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Expected [0] EXPLICIT (certs) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return TLS_OCSP_INVALID;
+ }
+ wpa_hexdump(MSG_MSGDUMP, "OCSP: certs",
+ hdr.payload, hdr.length);
+ pos = hdr.payload;
+ end = hdr.payload + hdr.length;
+ while (pos < end) {
+ struct x509_certificate *cert;
+
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Expected SEQUENCE (Certificate) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ goto fail;
+ }
+
+ cert = x509_certificate_parse(hdr.payload, hdr.length);
+ if (!cert)
+ goto fail;
+ if (last_cert) {
+ last_cert->next = cert;
+ last_cert = cert;
+ } else {
+ last_cert = certs = cert;
+ }
+ pos = hdr.payload + hdr.length;
+ }
+ }
+
+ /*
+ * ResponseData ::= SEQUENCE {
+ * version [0] EXPLICIT Version DEFAULT v1,
+ * responderID ResponderID,
+ * producedAt GeneralizedTime,
+ * responses SEQUENCE OF SingleResponse,
+ * responseExtensions [1] EXPLICIT Extensions OPTIONAL }
+ */
+ pos = resp_data;
+ end = resp_data + resp_data_len;
+ wpa_hexdump(MSG_MSGDUMP, "OCSP: ResponseData", pos, end - pos);
+
+ /*
+ * version [0] EXPLICIT Version DEFAULT v1
+ * Version ::= INTEGER { v1(0) }
+ */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 &&
+ hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC &&
+ hdr.tag == 0) {
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_INTEGER ||
+ hdr.length != 1) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: No INTEGER (len=1) tag found for version field - found class %d tag 0x%x length %d",
+ hdr.class, hdr.tag, hdr.length);
+ goto fail;
+ }
+ wpa_printf(MSG_DEBUG, "OCSP: ResponseData version %u",
+ hdr.payload[0]);
+ if (hdr.payload[0] != 0) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Unsupported ResponseData version %u",
+ hdr.payload[0]);
+ goto no_resp;
+ }
+ pos = hdr.payload + hdr.length;
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Default ResponseData version (v1)");
+ }
+
+ /*
+ * ResponderID ::= CHOICE {
+ * byName [1] Name,
+ * byKey [2] KeyHash }
+ */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Expected CHOICE (ResponderID) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ goto fail;
+ }
+
+ if (hdr.tag == 1) {
+ /* Name */
+ if (x509_parse_name(hdr.payload, hdr.length, &name, &pos) < 0)
+ goto fail;
+ x509_name_string(&name, buf, sizeof(buf));
+ wpa_printf(MSG_DEBUG, "OCSP: ResponderID byName Name: %s", buf);
+ } else if (hdr.tag == 2) {
+ /* KeyHash ::= OCTET STRING */
+ if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_OCTETSTRING) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Expected OCTET STRING (KeyHash) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ goto fail;
+ }
+ key_hash = hdr.payload;
+ wpa_hexdump(MSG_DEBUG, "OCSP: ResponderID byKey KeyHash",
+ key_hash, hdr.length);
+ if (hdr.length != SHA1_MAC_LEN) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Unexpected byKey KeyHash length %u - expected %u for SHA-1",
+ hdr.length, SHA1_MAC_LEN);
+ goto fail;
+ }
+ pos = hdr.payload + hdr.length;
+ } else {
+ wpa_printf(MSG_DEBUG, "OCSP: Unexpected ResponderID CHOICE %u",
+ hdr.tag);
+ goto fail;
+ }
+
+ /* producedAt GeneralizedTime */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_GENERALIZEDTIME ||
+ x509_parse_time(hdr.payload, hdr.length, hdr.tag,
+ &produced_at) < 0) {
+ wpa_printf(MSG_DEBUG, "OCSP: Failed to parse producedAt");
+ goto fail;
+ }
+ wpa_printf(MSG_DEBUG, "OCSP: producedAt %lu",
+ (unsigned long) produced_at);
+ pos = hdr.payload + hdr.length;
+
+ /* responses SEQUENCE OF SingleResponse */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Expected SEQUENCE (responses) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ goto fail;
+ }
+ responses = hdr.payload;
+ responses_len = hdr.length;
+ wpa_hexdump(MSG_MSGDUMP, "OCSP: responses", responses, responses_len);
+ pos = hdr.payload + hdr.length;
+
+ if (pos < end) {
+ /* responseExtensions [1] EXPLICIT Extensions OPTIONAL */
+ wpa_hexdump(MSG_MSGDUMP, "OCSP: responseExtensions",
+ pos, end - pos);
+ /* Ignore for now. */
+ }
+
+ if (!srv_cert) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Server certificate not known - cannot check OCSP response");
+ goto no_resp;
+ }
+
+ if (srv_cert->next) {
+ /* Issuer has already been verified in the chain */
+ issuer = srv_cert->next;
+ } else {
+ /* Find issuer from the set of trusted certificates */
+ for (issuer = conn->cred ? conn->cred->trusted_certs : NULL;
+ issuer; issuer = issuer->next) {
+ if (x509_name_compare(&srv_cert->issuer,
+ &issuer->subject) == 0)
+ break;
+ }
+ }
+ if (!issuer) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Server certificate issuer not known - cannot check OCSP response");
+ goto no_resp;
+ }
+
+ if (ocsp_responder_id_match(issuer, &name, key_hash)) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Server certificate issuer certificate matches ResponderID");
+ signer = issuer;
+ } else {
+ for (signer = certs; signer; signer = signer->next) {
+ if (!ocsp_responder_id_match(signer, &name, key_hash) ||
+ x509_name_compare(&srv_cert->issuer,
+ &issuer->subject) != 0 ||
+ !(signer->ext_key_usage &
+ X509_EXT_KEY_USAGE_OCSP) ||
+ x509_certificate_check_signature(issuer, signer) <
+ 0)
+ continue;
+ wpa_printf(MSG_DEBUG,
+ "OCSP: An extra certificate from the response matches ResponderID and is trusted as an OCSP signer");
+ break;
+ }
+ if (!signer) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Could not find OCSP signer certificate");
+ goto no_resp;
+ }
+ }
+
+ x509_free_name(&name);
+ os_memset(&name, 0, sizeof(name));
+ x509_certificate_chain_free(certs);
+ certs = NULL;
+
+ if (x509_check_signature(signer, &alg, sign_value, sign_value_len,
+ resp_data_signed, resp_data_signed_len) < 0) {
+ wpa_printf(MSG_DEBUG, "OCSP: Invalid signature");
+ return TLS_OCSP_INVALID;
+ }
+
+ res = tls_process_ocsp_responses(conn, srv_cert, issuer,
+ responses, responses_len);
+ if (res == TLS_OCSP_REVOKED)
+ srv_cert->ocsp_revoked = 1;
+ else if (res == TLS_OCSP_GOOD)
+ srv_cert->ocsp_good = 1;
+ return res;
+
+no_resp:
+ x509_free_name(&name);
+ x509_certificate_chain_free(certs);
+ return TLS_OCSP_NO_RESPONSE;
+
+fail:
+ x509_free_name(&name);
+ x509_certificate_chain_free(certs);
+ return TLS_OCSP_INVALID;
+}
+
+
+enum tls_ocsp_result tls_process_ocsp_response(struct tlsv1_client *conn,
+ const u8 *resp, size_t len)
+{
+ struct asn1_hdr hdr;
+ const u8 *pos, *end;
+ u8 resp_status;
+ struct asn1_oid oid;
+ char obuf[80];
+ struct x509_certificate *cert;
+ enum tls_ocsp_result res = TLS_OCSP_NO_RESPONSE;
+ enum tls_ocsp_result res_first = res;
+
+ wpa_hexdump(MSG_MSGDUMP, "TLSv1: OCSPResponse", resp, len);
+
+ /*
+ * RFC 6960, 4.2.1:
+ * OCSPResponse ::= SEQUENCE {
+ * responseStatus OCSPResponseStatus,
+ * responseBytes [0] EXPLICIT ResponseBytes OPTIONAL }
+ */
+
+ if (asn1_get_next(resp, len, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Expected SEQUENCE (OCSPResponse) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return TLS_OCSP_INVALID;
+ }
+ pos = hdr.payload;
+ end = hdr.payload + hdr.length;
+
+ /* OCSPResponseStatus ::= ENUMERATED */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_ENUMERATED ||
+ hdr.length != 1) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Expected ENUMERATED (responseStatus) - found class %d tag 0x%x length %u",
+ hdr.class, hdr.tag, hdr.length);
+ return TLS_OCSP_INVALID;
+ }
+ resp_status = hdr.payload[0];
+ wpa_printf(MSG_DEBUG, "OCSP: responseStatus %u", resp_status);
+ pos = hdr.payload + hdr.length;
+ if (resp_status != OCSP_RESP_STATUS_SUCCESSFUL) {
+ wpa_printf(MSG_DEBUG, "OCSP: No stapling result");
+ return TLS_OCSP_NO_RESPONSE;
+ }
+
+ /* responseBytes [0] EXPLICIT ResponseBytes OPTIONAL */
+ if (pos == end)
+ return TLS_OCSP_NO_RESPONSE;
+
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
+ hdr.tag != 0) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Expected [0] EXPLICIT (responseBytes) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return TLS_OCSP_INVALID;
+ }
+
+ /*
+ * ResponseBytes ::= SEQUENCE {
+ * responseType OBJECT IDENTIFIER,
+ * response OCTET STRING }
+ */
+
+ if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Expected SEQUENCE (ResponseBytes) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return TLS_OCSP_INVALID;
+ }
+ pos = hdr.payload;
+ end = hdr.payload + hdr.length;
+
+ /* responseType OBJECT IDENTIFIER */
+ if (asn1_get_oid(pos, end - pos, &oid, &pos)) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Failed to parse OID (responseType)");
+ return TLS_OCSP_INVALID;
+ }
+ asn1_oid_to_str(&oid, obuf, sizeof(obuf));
+ wpa_printf(MSG_DEBUG, "OCSP: responseType %s", obuf);
+ if (!is_oid_basic_ocsp_resp(&oid)) {
+ wpa_printf(MSG_DEBUG, "OCSP: Ignore unsupported response type");
+ return TLS_OCSP_NO_RESPONSE;
+ }
+
+ /* response OCTET STRING */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_OCTETSTRING) {
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Expected OCTET STRING (response) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return TLS_OCSP_INVALID;
+ }
+
+ cert = conn->server_cert;
+ while (cert) {
+ if (!cert->ocsp_good && !cert->ocsp_revoked) {
+ char sbuf[128];
+
+ x509_name_string(&cert->subject, sbuf, sizeof(sbuf));
+ wpa_printf(MSG_DEBUG,
+ "OCSP: Trying to find certificate status for %s",
+ sbuf);
+
+ res = tls_process_basic_ocsp_response(conn, cert,
+ hdr.payload,
+ hdr.length);
+ if (cert == conn->server_cert)
+ res_first = res;
+ }
+ if (res == TLS_OCSP_REVOKED || cert->issuer_trusted)
+ break;
+ cert = cert->next;
+ }
+ return res == TLS_OCSP_REVOKED ? res : res_first;
+}
/*
* TLSv1 client - read handshake message
- * Copyright (c) 2006-2014, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
const u8 *in_data, size_t *in_len);
+static int tls_version_disabled(struct tlsv1_client *conn, u16 ver)
+{
+ return (((conn->flags & TLS_CONN_DISABLE_TLSv1_0) &&
+ ver == TLS_VERSION_1) ||
+ ((conn->flags & TLS_CONN_DISABLE_TLSv1_1) &&
+ ver == TLS_VERSION_1_1) ||
+ ((conn->flags & TLS_CONN_DISABLE_TLSv1_2) &&
+ ver == TLS_VERSION_1_2));
+}
+
+
+static int tls_process_server_hello_extensions(struct tlsv1_client *conn,
+ const u8 *pos, size_t len)
+{
+ const u8 *end = pos + len;
+
+ wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerHello extensions",
+ pos, len);
+ while (pos < end) {
+ u16 ext, elen;
+
+ if (end - pos < 4) {
+ wpa_printf(MSG_INFO, "TLSv1: Truncated ServerHello extension header");
+ return -1;
+ }
+
+ ext = WPA_GET_BE16(pos);
+ pos += 2;
+ elen = WPA_GET_BE16(pos);
+ pos += 2;
+
+ if (elen > end - pos) {
+ wpa_printf(MSG_INFO, "TLSv1: Truncated ServerHello extension");
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "TLSv1: ServerHello ExtensionType %u",
+ ext);
+ wpa_hexdump(MSG_DEBUG, "TLSv1: ServerHello extension data",
+ pos, elen);
+
+ pos += elen;
+ }
+
+ return 0;
+}
+
+
static int tls_process_server_hello(struct tlsv1_client *conn, u8 ct,
const u8 *in_data, size_t *in_len)
{
if (end - pos < 2)
goto decode_error;
tls_version = WPA_GET_BE16(pos);
- if (!tls_version_ok(tls_version)) {
+ if (!tls_version_ok(tls_version) ||
+ tls_version_disabled(conn, tls_version)) {
wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in "
"ServerHello %u.%u", pos[0], pos[1]);
tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
}
pos++;
+ if (end - pos >= 2) {
+ u16 ext_len;
+
+ ext_len = WPA_GET_BE16(pos);
+ pos += 2;
+ if (end - pos < ext_len) {
+ wpa_printf(MSG_INFO,
+ "TLSv1: Invalid ServerHello extension length: %u (left: %u)",
+ ext_len, (unsigned int) (end - pos));
+ goto decode_error;
+ }
+
+ if (tls_process_server_hello_extensions(conn, pos, ext_len))
+ goto decode_error;
+ pos += ext_len;
+ }
+
if (end != pos) {
- /* TODO: ServerHello extensions */
wpa_hexdump(MSG_DEBUG, "TLSv1: Unexpected extra data in the "
"end of ServerHello", pos, end - pos);
goto decode_error;
}
+static void tls_peer_cert_event(struct tlsv1_client *conn, int depth,
+ struct x509_certificate *cert)
+{
+ union tls_event_data ev;
+ struct wpabuf *cert_buf = NULL;
+#ifdef CONFIG_SHA256
+ u8 hash[32];
+#endif /* CONFIG_SHA256 */
+ char subject[128];
+
+ if (!conn->event_cb)
+ return;
+
+ os_memset(&ev, 0, sizeof(ev));
+ if (conn->cred->cert_probe || conn->cert_in_cb) {
+ cert_buf = wpabuf_alloc_copy(cert->cert_start,
+ cert->cert_len);
+ ev.peer_cert.cert = cert_buf;
+ }
+#ifdef CONFIG_SHA256
+ if (cert_buf) {
+ const u8 *addr[1];
+ size_t len[1];
+ addr[0] = wpabuf_head(cert_buf);
+ len[0] = wpabuf_len(cert_buf);
+ if (sha256_vector(1, addr, len, hash) == 0) {
+ ev.peer_cert.hash = hash;
+ ev.peer_cert.hash_len = sizeof(hash);
+ }
+ }
+#endif /* CONFIG_SHA256 */
+
+ ev.peer_cert.depth = depth;
+ x509_name_string(&cert->subject, subject, sizeof(subject));
+ ev.peer_cert.subject = subject;
+
+ conn->event_cb(conn->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
+ wpabuf_free(cert_buf);
+}
+
+
+static void tls_cert_chain_failure_event(struct tlsv1_client *conn, int depth,
+ struct x509_certificate *cert,
+ enum tls_fail_reason reason,
+ const char *reason_txt)
+{
+ struct wpabuf *cert_buf = NULL;
+ union tls_event_data ev;
+ char subject[128];
+
+ if (!conn->event_cb || !cert)
+ return;
+
+ os_memset(&ev, 0, sizeof(ev));
+ ev.cert_fail.depth = depth;
+ x509_name_string(&cert->subject, subject, sizeof(subject));
+ ev.peer_cert.subject = subject;
+ ev.cert_fail.reason = reason;
+ ev.cert_fail.reason_txt = reason_txt;
+ cert_buf = wpabuf_alloc_copy(cert->cert_start,
+ cert->cert_len);
+ ev.cert_fail.cert = cert_buf;
+ conn->event_cb(conn->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
+ wpabuf_free(cert_buf);
+}
+
+
static int tls_process_certificate(struct tlsv1_client *conn, u8 ct,
const u8 *in_data, size_t *in_len)
{
return -1;
}
+ tls_peer_cert_event(conn, idx, cert);
+
if (last == NULL)
chain = cert;
else
pos += cert_len;
}
- if (conn->cred &&
- x509_certificate_chain_validate(conn->cred->trusted_certs, chain,
- &reason, conn->disable_time_checks)
- < 0) {
+ if (conn->cred && conn->cred->server_cert_only && chain) {
+ u8 hash[SHA256_MAC_LEN];
+ char buf[128];
+
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Validate server certificate hash");
+ x509_name_string(&chain->subject, buf, sizeof(buf));
+ wpa_printf(MSG_DEBUG, "TLSv1: 0: %s", buf);
+ if (sha256_vector(1, &chain->cert_start, &chain->cert_len,
+ hash) < 0 ||
+ os_memcmp(conn->cred->srv_cert_hash, hash,
+ SHA256_MAC_LEN) != 0) {
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Server certificate hash mismatch");
+ wpa_hexdump(MSG_MSGDUMP, "TLSv1: SHA256 hash",
+ hash, SHA256_MAC_LEN);
+ if (conn->event_cb) {
+ union tls_event_data ev;
+
+ os_memset(&ev, 0, sizeof(ev));
+ ev.cert_fail.reason = TLS_FAIL_UNSPECIFIED;
+ ev.cert_fail.reason_txt =
+ "Server certificate mismatch";
+ ev.cert_fail.subject = buf;
+ conn->event_cb(conn->cb_ctx,
+ TLS_CERT_CHAIN_FAILURE, &ev);
+ }
+ tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_BAD_CERTIFICATE);
+ x509_certificate_chain_free(chain);
+ return -1;
+ }
+ } else if (conn->cred && conn->cred->cert_probe) {
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Reject server certificate on probe-only rune");
+ if (conn->event_cb) {
+ union tls_event_data ev;
+ char buf[128];
+
+ os_memset(&ev, 0, sizeof(ev));
+ ev.cert_fail.reason = TLS_FAIL_SERVER_CHAIN_PROBE;
+ ev.cert_fail.reason_txt =
+ "Server certificate chain probe";
+ if (chain) {
+ x509_name_string(&chain->subject, buf,
+ sizeof(buf));
+ ev.cert_fail.subject = buf;
+ }
+ conn->event_cb(conn->cb_ctx, TLS_CERT_CHAIN_FAILURE,
+ &ev);
+ }
+ tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_BAD_CERTIFICATE);
+ x509_certificate_chain_free(chain);
+ return -1;
+ } else if (conn->cred && conn->cred->ca_cert_verify &&
+ x509_certificate_chain_validate(
+ conn->cred->trusted_certs, chain, &reason,
+ !!(conn->flags & TLS_CONN_DISABLE_TIME_CHECKS))
+ < 0) {
int tls_reason;
wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain "
"validation failed (reason=%d)", reason);
switch (reason) {
case X509_VALIDATE_BAD_CERTIFICATE:
tls_reason = TLS_ALERT_BAD_CERTIFICATE;
+ tls_cert_chain_failure_event(
+ conn, 0, chain, TLS_FAIL_BAD_CERTIFICATE,
+ "bad certificate");
break;
case X509_VALIDATE_UNSUPPORTED_CERTIFICATE:
tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE;
break;
case X509_VALIDATE_CERTIFICATE_REVOKED:
tls_reason = TLS_ALERT_CERTIFICATE_REVOKED;
+ tls_cert_chain_failure_event(
+ conn, 0, chain, TLS_FAIL_REVOKED,
+ "certificate revoked");
break;
case X509_VALIDATE_CERTIFICATE_EXPIRED:
tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED;
+ tls_cert_chain_failure_event(
+ conn, 0, chain, TLS_FAIL_EXPIRED,
+ "certificate has expired or is not yet valid");
break;
case X509_VALIDATE_CERTIFICATE_UNKNOWN:
tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN;
break;
case X509_VALIDATE_UNKNOWN_CA:
tls_reason = TLS_ALERT_UNKNOWN_CA;
+ tls_cert_chain_failure_event(
+ conn, 0, chain, TLS_FAIL_UNTRUSTED,
+ "unknown CA");
break;
default:
tls_reason = TLS_ALERT_BAD_CERTIFICATE;
return -1;
}
- x509_certificate_chain_free(chain);
+ if (conn->cred && !conn->cred->server_cert_only && chain &&
+ (chain->extensions_present & X509_EXT_EXT_KEY_USAGE) &&
+ !(chain->ext_key_usage &
+ (X509_EXT_KEY_USAGE_ANY | X509_EXT_KEY_USAGE_SERVER_AUTH))) {
+ tls_cert_chain_failure_event(
+ conn, 0, chain, TLS_FAIL_BAD_CERTIFICATE,
+ "certificate not allowed for server authentication");
+ tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_BAD_CERTIFICATE);
+ x509_certificate_chain_free(chain);
+ return -1;
+ }
+
+ if (conn->flags & TLS_CONN_REQUEST_OCSP) {
+ x509_certificate_chain_free(conn->server_cert);
+ conn->server_cert = chain;
+ } else {
+ x509_certificate_chain_free(chain);
+ }
*in_len = end - in_data;
server_params_end = pos;
if (key_exchange == TLS_KEY_X_DHE_RSA) {
- u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
+ u8 hash[64];
int hlen;
if (conn->rl.tls_version == TLS_VERSION_1_2) {
*/
if (end - pos < 2)
goto fail;
- if (pos[0] != TLS_HASH_ALG_SHA256 ||
+ if ((pos[0] != TLS_HASH_ALG_SHA256 &&
+ pos[0] != TLS_HASH_ALG_SHA384 &&
+ pos[0] != TLS_HASH_ALG_SHA512) ||
pos[1] != TLS_SIGN_ALG_RSA) {
wpa_printf(MSG_DEBUG, "TLSv1.2: Unsupported hash(%u)/signature(%u) algorithm",
pos[0], pos[1]);
goto fail;
}
- pos += 2;
hlen = tlsv12_key_x_server_params_hash(
- conn->rl.tls_version, conn->client_random,
+ conn->rl.tls_version, pos[0],
+ conn->client_random,
conn->server_random, server_params,
server_params_end - server_params, hash);
+ pos += 2;
#else /* CONFIG_TLSV12 */
goto fail;
#endif /* CONFIG_TLSV12 */
}
+static enum tls_ocsp_result
+tls_process_certificate_status_ocsp_response(struct tlsv1_client *conn,
+ const u8 *pos, size_t len)
+{
+ const u8 *end = pos + len;
+ u32 ocsp_resp_len;
+
+ /* opaque OCSPResponse<1..2^24-1>; */
+ if (end - pos < 3) {
+ wpa_printf(MSG_INFO, "TLSv1: Too short OCSPResponse");
+ tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
+ return TLS_OCSP_INVALID;
+ }
+ ocsp_resp_len = WPA_GET_BE24(pos);
+ pos += 3;
+ if (end - pos < ocsp_resp_len) {
+ wpa_printf(MSG_INFO, "TLSv1: Truncated OCSPResponse");
+ tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
+ return TLS_OCSP_INVALID;
+ }
+
+ return tls_process_ocsp_response(conn, pos, ocsp_resp_len);
+}
+
+
+static int tls_process_certificate_status(struct tlsv1_client *conn, u8 ct,
+ const u8 *in_data, size_t *in_len)
+{
+ const u8 *pos, *end;
+ size_t left, len;
+ u8 type, status_type;
+ enum tls_ocsp_result res;
+ struct x509_certificate *cert;
+ int depth;
+
+ if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Expected Handshake; received content type 0x%x",
+ ct);
+ tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_UNEXPECTED_MESSAGE);
+ return -1;
+ }
+
+ pos = in_data;
+ left = *in_len;
+
+ if (left < 4) {
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Too short CertificateStatus (left=%lu)",
+ (unsigned long) left);
+ tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
+ return -1;
+ }
+
+ type = *pos++;
+ len = WPA_GET_BE24(pos);
+ pos += 3;
+ left -= 4;
+
+ if (len > left) {
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Mismatch in CertificateStatus length (len=%lu != left=%lu)",
+ (unsigned long) len, (unsigned long) left);
+ tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
+ return -1;
+ }
+
+ end = pos + len;
+
+ if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS) {
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Received unexpected handshake message %d (expected CertificateStatus)",
+ type);
+ tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_UNEXPECTED_MESSAGE);
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateStatus");
+
+ /*
+ * struct {
+ * CertificateStatusType status_type;
+ * select (status_type) {
+ * case ocsp: OCSPResponse;
+ * case ocsp_multi: OCSPResponseList;
+ * } response;
+ * } CertificateStatus;
+ */
+ if (end - pos < 1) {
+ wpa_printf(MSG_INFO, "TLSv1: Too short CertificateStatus");
+ tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR);
+ return -1;
+ }
+ status_type = *pos++;
+ wpa_printf(MSG_DEBUG, "TLSv1: CertificateStatus status_type %u",
+ status_type);
+
+ if (status_type == 1 /* ocsp */) {
+ res = tls_process_certificate_status_ocsp_response(
+ conn, pos, end - pos);
+ } else if (status_type == 2 /* ocsp_multi */) {
+ int good = 0, revoked = 0;
+ u32 resp_len;
+
+ res = TLS_OCSP_NO_RESPONSE;
+
+ /*
+ * opaque OCSPResponse<0..2^24-1>;
+ *
+ * struct {
+ * OCSPResponse ocsp_response_list<1..2^24-1>;
+ * } OCSPResponseList;
+ */
+ if (end - pos < 3) {
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Truncated OCSPResponseList");
+ res = TLS_OCSP_INVALID;
+ goto done;
+ }
+ resp_len = WPA_GET_BE24(pos);
+ pos += 3;
+ if (end - pos < resp_len) {
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Truncated OCSPResponseList(len=%u)",
+ resp_len);
+ res = TLS_OCSP_INVALID;
+ goto done;
+ }
+ end = pos + resp_len;
+
+ while (end - pos >= 3) {
+ resp_len = WPA_GET_BE24(pos);
+ pos += 3;
+ if (resp_len > end - pos) {
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Truncated OCSPResponse(len=%u; left=%d) in ocsp_multi",
+ resp_len, (int) (end - pos));
+ res = TLS_OCSP_INVALID;
+ break;
+ }
+ if (!resp_len)
+ continue; /* Skip an empty response */
+ res = tls_process_certificate_status_ocsp_response(
+ conn, pos - 3, resp_len + 3);
+ if (res == TLS_OCSP_REVOKED)
+ revoked++;
+ else if (res == TLS_OCSP_GOOD)
+ good++;
+ pos += resp_len;
+ }
+
+ if (revoked)
+ res = TLS_OCSP_REVOKED;
+ else if (good)
+ res = TLS_OCSP_GOOD;
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Ignore unsupported CertificateStatus");
+ goto skip;
+ }
+
+done:
+ if (res == TLS_OCSP_REVOKED) {
+ tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_CERTIFICATE_REVOKED);
+ for (cert = conn->server_cert, depth = 0; cert;
+ cert = cert->next, depth++) {
+ if (cert->ocsp_revoked) {
+ tls_cert_chain_failure_event(
+ conn, depth, cert, TLS_FAIL_REVOKED,
+ "certificate revoked");
+ }
+ }
+ return -1;
+ }
+
+ if (conn->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
+ /*
+ * Verify that each certificate on the chain that is not part
+ * of the trusted certificates has a good status. If not,
+ * terminate handshake.
+ */
+ for (cert = conn->server_cert, depth = 0; cert;
+ cert = cert->next, depth++) {
+ if (!cert->ocsp_good) {
+ tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE);
+ tls_cert_chain_failure_event(
+ conn, depth, cert,
+ TLS_FAIL_UNSPECIFIED,
+ "bad certificate status response");
+ return -1;
+ }
+ if (cert->issuer_trusted)
+ break;
+ }
+ }
+
+ if ((conn->flags & TLS_CONN_REQUIRE_OCSP) && res != TLS_OCSP_GOOD) {
+ tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ res == TLS_OCSP_INVALID ? TLS_ALERT_DECODE_ERROR :
+ TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE);
+ if (conn->server_cert)
+ tls_cert_chain_failure_event(
+ conn, 0, conn->server_cert,
+ TLS_FAIL_UNSPECIFIED,
+ "bad certificate status response");
+ return -1;
+ }
+
+ conn->ocsp_resp_received = 1;
+
+skip:
+ *in_len = end - in_data;
+
+ conn->state = SERVER_KEY_EXCHANGE;
+
+ return 0;
+}
+
+
static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct,
const u8 *in_data, size_t *in_len)
{
end = pos + len;
+ if ((conn->flags & TLS_CONN_REQUEST_OCSP) &&
+ type == TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS)
+ return tls_process_certificate_status(conn, ct, in_data,
+ in_len);
if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST)
return tls_process_certificate_request(conn, ct, in_data,
in_len);
if (type != TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) {
wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake "
"message %d (expected ServerKeyExchange/"
- "CertificateRequest/ServerHelloDone)", type);
+ "CertificateRequest/ServerHelloDone%s)", type,
+ (conn->flags & TLS_CONN_REQUEST_OCSP) ?
+ "/CertificateStatus" : "");
tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
TLS_ALERT_UNEXPECTED_MESSAGE);
return -1;
wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHelloDone");
+ if ((conn->flags & TLS_CONN_REQUIRE_OCSP) &&
+ !conn->ocsp_resp_received) {
+ wpa_printf(MSG_INFO,
+ "TLSv1: No OCSP response received - reject handshake");
+ tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE);
+ return -1;
+ }
+
*in_len = end - in_data;
conn->state = CLIENT_KEY_EXCHANGE;
/*
* TLSv1 client - write handshake message
- * Copyright (c) 2006-2014, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
u8 *hello, *end, *pos, *hs_length, *hs_start, *rhdr;
struct os_time now;
size_t len, i;
+ u8 *ext_start;
+ u16 tls_version = TLS_VERSION;
- wpa_printf(MSG_DEBUG, "TLSv1: Send ClientHello");
+ /* Pick the highest locally enabled TLS version */
+#ifdef CONFIG_TLSV12
+ if ((conn->flags & TLS_CONN_DISABLE_TLSv1_2) &&
+ tls_version == TLS_VERSION_1_2)
+ tls_version = TLS_VERSION_1_1;
+#endif /* CONFIG_TLSV12 */
+#ifdef CONFIG_TLSV11
+ if ((conn->flags & TLS_CONN_DISABLE_TLSv1_1) &&
+ tls_version == TLS_VERSION_1_1)
+ tls_version = TLS_VERSION_1;
+#endif /* CONFIG_TLSV11 */
+ if ((conn->flags & TLS_CONN_DISABLE_TLSv1_0) &&
+ tls_version == TLS_VERSION_1) {
+ wpa_printf(MSG_INFO, "TLSv1: No TLS version allowed");
+ return NULL;
+ }
+
+ wpa_printf(MSG_DEBUG, "TLSv1: Send ClientHello (ver %s)",
+ tls_version_str(tls_version));
*out_len = 0;
os_get_time(&now);
wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random",
conn->client_random, TLS_RANDOM_LEN);
- len = 100 + conn->num_cipher_suites * 2 + conn->client_hello_ext_len;
+ len = 150 + conn->num_cipher_suites * 2 + conn->client_hello_ext_len;
hello = os_malloc(len);
if (hello == NULL)
return NULL;
pos += 3;
/* body - ClientHello */
/* ProtocolVersion client_version */
- WPA_PUT_BE16(pos, TLS_VERSION);
+ WPA_PUT_BE16(pos, tls_version);
pos += 2;
/* Random random: uint32 gmt_unix_time, opaque random_bytes */
os_memcpy(pos, conn->client_random, TLS_RANDOM_LEN);
*pos++ = 1;
*pos++ = TLS_COMPRESSION_NULL;
+ /* Extension */
+ ext_start = pos;
+ pos += 2;
+
+#ifdef CONFIG_TLSV12
+ if (conn->rl.tls_version >= TLS_VERSION_1_2) {
+ /*
+ * Add signature_algorithms extension since we support only
+ * SHA256 (and not the default SHA1) with TLSv1.2.
+ */
+ /* ExtensionsType extension_type = signature_algorithms(13) */
+ WPA_PUT_BE16(pos, TLS_EXT_SIGNATURE_ALGORITHMS);
+ pos += 2;
+ /* opaque extension_data<0..2^16-1> length */
+ WPA_PUT_BE16(pos, 8);
+ pos += 2;
+ /* supported_signature_algorithms<2..2^16-2> length */
+ WPA_PUT_BE16(pos, 6);
+ pos += 2;
+ /* supported_signature_algorithms */
+ *pos++ = TLS_HASH_ALG_SHA512;
+ *pos++ = TLS_SIGN_ALG_RSA;
+ *pos++ = TLS_HASH_ALG_SHA384;
+ *pos++ = TLS_SIGN_ALG_RSA;
+ *pos++ = TLS_HASH_ALG_SHA256;
+ *pos++ = TLS_SIGN_ALG_RSA;
+ }
+#endif /* CONFIG_TLSV12 */
+
if (conn->client_hello_ext) {
os_memcpy(pos, conn->client_hello_ext,
conn->client_hello_ext_len);
pos += conn->client_hello_ext_len;
}
+ if (conn->flags & TLS_CONN_REQUEST_OCSP) {
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Add status_request extension for OCSP stapling");
+ /* ExtensionsType extension_type = status_request(5) */
+ WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST);
+ pos += 2;
+ /* opaque extension_data<0..2^16-1> length */
+ WPA_PUT_BE16(pos, 5);
+ pos += 2;
+
+ /*
+ * RFC 6066, 8:
+ * struct {
+ * CertificateStatusType status_type;
+ * select (status_type) {
+ * case ocsp: OCSPStatusRequest;
+ * } request;
+ * } CertificateStatusRequest;
+ *
+ * enum { ocsp(1), (255) } CertificateStatusType;
+ */
+ *pos++ = 1; /* status_type = ocsp(1) */
+
+ /*
+ * struct {
+ * ResponderID responder_id_list<0..2^16-1>;
+ * Extensions request_extensions;
+ * } OCSPStatusRequest;
+ *
+ * opaque ResponderID<1..2^16-1>;
+ * opaque Extensions<0..2^16-1>;
+ */
+ WPA_PUT_BE16(pos, 0); /* responder_id_list(empty) */
+ pos += 2;
+ WPA_PUT_BE16(pos, 0); /* request_extensions(empty) */
+ pos += 2;
+
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Add status_request_v2 extension for OCSP stapling");
+ /* ExtensionsType extension_type = status_request_v2(17) */
+ WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST_V2);
+ pos += 2;
+ /* opaque extension_data<0..2^16-1> length */
+ WPA_PUT_BE16(pos, 7);
+ pos += 2;
+
+ /*
+ * RFC 6961, 2.2:
+ * struct {
+ * CertificateStatusType status_type;
+ * uint16 request_length;
+ * select (status_type) {
+ * case ocsp: OCSPStatusRequest;
+ * case ocsp_multi: OCSPStatusRequest;
+ * } request;
+ * } CertificateStatusRequestItemV2;
+ *
+ * enum { ocsp(1), ocsp_multi(2), (255) } CertificateStatusType;
+ *
+ * struct {
+ * CertificateStatusRequestItemV2
+ * certificate_status_req_list<1..2^16-1>;
+ * } CertificateStatusRequestListV2;
+ */
+
+ /* certificate_status_req_list<1..2^16-1> */
+ WPA_PUT_BE16(pos, 5);
+ pos += 2;
+
+ /* CertificateStatusRequestItemV2 */
+ *pos++ = 2; /* status_type = ocsp_multi(2) */
+ /* OCSPStatusRequest as shown above for v1 */
+ WPA_PUT_BE16(pos, 0); /* responder_id_list(empty) */
+ pos += 2;
+ WPA_PUT_BE16(pos, 0); /* request_extensions(empty) */
+ pos += 2;
+ }
+
+ if (pos == ext_start + 2)
+ pos -= 2; /* no extensions */
+ else
+ WPA_PUT_BE16(ext_start, pos - ext_start - 2);
+
WPA_PUT_BE24(hs_length, pos - hs_length - 3);
tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
struct x509_certificate *cert;
pos = *msgpos;
+ if (TLS_RECORD_HEADER_LEN + 1 + 3 + 3 > end - pos) {
+ tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_INTERNAL_ERROR);
+ return -1;
+ }
wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate");
rhdr = pos;
pos += 3;
cert = conn->cred ? conn->cred->cert : NULL;
while (cert) {
- if (pos + 3 + cert->cert_len > end) {
+ if (3 + cert->cert_len > (size_t) (end - pos)) {
wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space "
"for Certificate (cert_len=%lu left=%lu)",
(unsigned long) cert->cert_len,
wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)",
dh_yc, dh_yc_len);
+ if (end - *pos < 2) {
+ tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_INTERNAL_ERROR);
+ os_free(csecret);
+ os_free(dh_yc);
+ return -1;
+ }
WPA_PUT_BE16(*pos, dh_yc_len);
*pos += 2;
- if (*pos + dh_yc_len > end) {
+ if (dh_yc_len > (size_t) (end - *pos)) {
wpa_printf(MSG_DEBUG, "TLSv1: Not enough room in the "
"message buffer for Yc");
tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
wpa_printf(MSG_DEBUG, "TLSv1: Session resumption completed "
"successfully");
+ if (!conn->session_resumed && conn->use_session_ticket)
+ conn->session_resumed = 1;
conn->state = ESTABLISHED;
return msg;
#ifdef CONFIG_TLSV12
-int tlsv12_key_x_server_params_hash(u16 tls_version,
+int tlsv12_key_x_server_params_hash(u16 tls_version, u8 hash_alg,
const u8 *client_random,
const u8 *server_random,
const u8 *server_params,
{
size_t hlen;
struct crypto_hash *ctx;
-
- ctx = crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL, 0);
+ enum crypto_hash_alg alg;
+
+ switch (hash_alg) {
+ case TLS_HASH_ALG_SHA256:
+ alg = CRYPTO_HASH_ALG_SHA256;
+ hlen = SHA256_MAC_LEN;
+ break;
+ case TLS_HASH_ALG_SHA384:
+ alg = CRYPTO_HASH_ALG_SHA384;
+ hlen = 48;
+ break;
+ case TLS_HASH_ALG_SHA512:
+ alg = CRYPTO_HASH_ALG_SHA512;
+ hlen = 64;
+ break;
+ default:
+ return -1;
+ }
+ ctx = crypto_hash_init(alg, NULL, 0);
if (ctx == NULL)
return -1;
crypto_hash_update(ctx, client_random, TLS_RANDOM_LEN);
crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN);
crypto_hash_update(ctx, server_params, server_params_len);
- hlen = SHA256_MAC_LEN;
if (crypto_hash_finish(ctx, hash, &hlen) < 0)
return -1;
wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithn = SHA-256");
decrypted = buf + 19;
buflen -= 19;
+ } else if (buflen >= 19 + 48 &&
+ os_memcmp(buf, "\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01"
+ "\x65\x03\x04\x02\x02\x05\x00\x04\x30", 19) == 0)
+ {
+ wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithn = SHA-384");
+ decrypted = buf + 19;
+ buflen -= 19;
+ } else if (buflen >= 19 + 64 &&
+ os_memcmp(buf, "\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01"
+ "\x65\x03\x04\x02\x03\x05\x00\x04\x40", 19) == 0)
+ {
+ wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithn = SHA-512");
+ decrypted = buf + 19;
+ buflen -= 19;
+
} else {
wpa_printf(MSG_DEBUG, "TLSv1.2: Unrecognized DigestInfo");
os_free(buf);
#define TLS_EXT_TRUSTED_CA_KEYS 3 /* RFC 4366 */
#define TLS_EXT_TRUNCATED_HMAC 4 /* RFC 4366 */
#define TLS_EXT_STATUS_REQUEST 5 /* RFC 4366 */
+#define TLS_EXT_SIGNATURE_ALGORITHMS 13 /* RFC 5246 */
+#define TLS_EXT_STATUS_REQUEST_V2 17 /* RFC 6961 */
#define TLS_EXT_SESSION_TICKET 35 /* RFC 4507 */
#define TLS_EXT_PAC_OPAQUE TLS_EXT_SESSION_TICKET /* EAP-FAST terminology */
const char * tls_version_str(u16 ver);
int tls_prf(u16 ver, const u8 *secret, size_t secret_len, const char *label,
const u8 *seed, size_t seed_len, u8 *out, size_t outlen);
-int tlsv12_key_x_server_params_hash(u16 tls_version, const u8 *client_random,
+int tlsv12_key_x_server_params_hash(u16 tls_version, u8 hash_Alg,
+ const u8 *client_random,
const u8 *server_random,
const u8 *server_params,
size_t server_params_len, u8 *hash);
/*
* TLSv1 credentials
- * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
#include "common.h"
#include "base64.h"
#include "crypto/crypto.h"
+#include "crypto/sha1.h"
+#include "pkcs5.h"
+#include "pkcs8.h"
#include "x509v3.h"
#include "tlsv1_cred.h"
crypto_private_key_free(cred->key);
os_free(cred->dh_p);
os_free(cred->dh_g);
+ os_free(cred->ocsp_stapling_response);
+ os_free(cred->ocsp_stapling_response_multi);
os_free(cred);
}
const u8 *cert_blob, size_t cert_blob_len,
const char *path)
{
+ if (cert && os_strncmp(cert, "hash://", 7) == 0) {
+ const char *pos = cert + 7;
+ if (os_strncmp(pos, "server/sha256/", 14) != 0) {
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Unsupported ca_cert hash value '%s'",
+ cert);
+ return -1;
+ }
+ pos += 14;
+ if (os_strlen(pos) != 32 * 2) {
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Unexpected SHA256 hash length in ca_cert '%s'",
+ cert);
+ return -1;
+ }
+ if (hexstr2bin(pos, cred->srv_cert_hash, 32) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Invalid SHA256 hash value in ca_cert '%s'",
+ cert);
+ return -1;
+ }
+ cred->server_cert_only = 1;
+ cred->ca_cert_verify = 0;
+ wpa_printf(MSG_DEBUG,
+ "TLSv1: Checking only server certificate match");
+ return 0;
+ }
+
+ if (cert && os_strncmp(cert, "probe://", 8) == 0) {
+ cred->cert_probe = 1;
+ cred->ca_cert_verify = 0;
+ wpa_printf(MSG_DEBUG, "TLSv1: Only probe server certificate");
+ return 0;
+ }
+
+ cred->ca_cert_verify = cert || cert_blob || path;
+
if (tlsv1_set_cert_chain(&cred->trusted_certs, cert,
cert_blob, cert_blob_len) < 0)
return -1;
}
+#ifdef PKCS12_FUNCS
+
+static int oid_is_rsadsi(struct asn1_oid *oid)
+{
+ return oid->len >= 4 &&
+ oid->oid[0] == 1 /* iso */ &&
+ oid->oid[1] == 2 /* member-body */ &&
+ oid->oid[2] == 840 /* us */ &&
+ oid->oid[3] == 113549 /* rsadsi */;
+}
+
+
+static int pkcs12_is_bagtype_oid(struct asn1_oid *oid, unsigned long type)
+{
+ return oid->len == 9 &&
+ oid_is_rsadsi(oid) &&
+ oid->oid[4] == 1 /* pkcs */ &&
+ oid->oid[5] == 12 /* pkcs-12 */ &&
+ oid->oid[6] == 10 &&
+ oid->oid[7] == 1 /* bagtypes */ &&
+ oid->oid[8] == type;
+}
+
+
+static int is_oid_pkcs7(struct asn1_oid *oid)
+{
+ return oid->len == 7 &&
+ oid->oid[0] == 1 /* iso */ &&
+ oid->oid[1] == 2 /* member-body */ &&
+ oid->oid[2] == 840 /* us */ &&
+ oid->oid[3] == 113549 /* rsadsi */ &&
+ oid->oid[4] == 1 /* pkcs */ &&
+ oid->oid[5] == 7 /* pkcs-7 */;
+}
+
+
+static int is_oid_pkcs7_data(struct asn1_oid *oid)
+{
+ return is_oid_pkcs7(oid) && oid->oid[6] == 1 /* data */;
+}
+
+
+static int is_oid_pkcs7_enc_data(struct asn1_oid *oid)
+{
+ return is_oid_pkcs7(oid) && oid->oid[6] == 6 /* encryptedData */;
+}
+
+
+static int is_oid_pkcs9(struct asn1_oid *oid)
+{
+ return oid->len >= 6 &&
+ oid->oid[0] == 1 /* iso */ &&
+ oid->oid[1] == 2 /* member-body */ &&
+ oid->oid[2] == 840 /* us */ &&
+ oid->oid[3] == 113549 /* rsadsi */ &&
+ oid->oid[4] == 1 /* pkcs */ &&
+ oid->oid[5] == 9 /* pkcs-9 */;
+}
+
+
+static int is_oid_pkcs9_friendly_name(struct asn1_oid *oid)
+{
+ return oid->len == 7 && is_oid_pkcs9(oid) &&
+ oid->oid[6] == 20;
+}
+
+
+static int is_oid_pkcs9_local_key_id(struct asn1_oid *oid)
+{
+ return oid->len == 7 && is_oid_pkcs9(oid) &&
+ oid->oid[6] == 21;
+}
+
+
+static int is_oid_pkcs9_x509_cert(struct asn1_oid *oid)
+{
+ return oid->len == 8 && is_oid_pkcs9(oid) &&
+ oid->oid[6] == 22 /* certTypes */ &&
+ oid->oid[7] == 1 /* x509Certificate */;
+}
+
+
+static int pkcs12_keybag(struct tlsv1_credentials *cred,
+ const u8 *buf, size_t len)
+{
+ /* TODO */
+ return 0;
+}
+
+
+static int pkcs12_pkcs8_keybag(struct tlsv1_credentials *cred,
+ const u8 *buf, size_t len,
+ const char *passwd)
+{
+ struct crypto_private_key *key;
+
+ /* PKCS8ShroudedKeyBag ::= EncryptedPrivateKeyInfo */
+ key = pkcs8_enc_key_import(buf, len, passwd);
+ if (!key)
+ return -1;
+
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Successfully decrypted PKCS8ShroudedKeyBag");
+ crypto_private_key_free(cred->key);
+ cred->key = key;
+
+ return 0;
+}
+
+
+static int pkcs12_certbag(struct tlsv1_credentials *cred,
+ const u8 *buf, size_t len)
+{
+ struct asn1_hdr hdr;
+ struct asn1_oid oid;
+ char obuf[80];
+ const u8 *pos, *end;
+
+ /*
+ * CertBag ::= SEQUENCE {
+ * certId BAG-TYPE.&id ({CertTypes}),
+ * certValue [0] EXPLICIT BAG-TYPE.&Type ({CertTypes}{@certId})
+ * }
+ */
+
+ if (asn1_get_next(buf, len, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Expected SEQUENCE (CertBag) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+
+ pos = hdr.payload;
+ end = hdr.payload + hdr.length;
+
+ if (asn1_get_oid(pos, end - pos, &oid, &pos)) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Failed to parse OID (certId)");
+ return -1;
+ }
+
+ asn1_oid_to_str(&oid, obuf, sizeof(obuf));
+ wpa_printf(MSG_DEBUG, "PKCS #12: certId %s", obuf);
+
+ if (!is_oid_pkcs9_x509_cert(&oid)) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Ignored unsupported certificate type (certId %s)",
+ obuf);
+ }
+
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
+ hdr.tag != 0) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Expected [0] EXPLICIT (certValue) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+
+ if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_OCTETSTRING) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Expected OCTET STRING (x509Certificate) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+
+ wpa_hexdump(MSG_DEBUG, "PKCS #12: x509Certificate",
+ hdr.payload, hdr.length);
+ if (cred->cert) {
+ struct x509_certificate *cert;
+
+ wpa_printf(MSG_DEBUG, "PKCS #12: Ignore extra certificate");
+ cert = x509_certificate_parse(hdr.payload, hdr.length);
+ if (!cert) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Failed to parse x509Certificate");
+ return 0;
+ }
+ x509_certificate_chain_free(cert);
+
+ return 0;
+ }
+ return tlsv1_set_cert(cred, NULL, hdr.payload, hdr.length);
+}
+
+
+static int pkcs12_parse_attr_friendly_name(const u8 *pos, const u8 *end)
+{
+ struct asn1_hdr hdr;
+
+ /*
+ * RFC 2985, 5.5.1:
+ * friendlyName ATTRIBUTE ::= {
+ * WITH SYNTAX BMPString (SIZE(1..pkcs-9-ub-friendlyName))
+ * EQUALITY MATCHING RULE caseIgnoreMatch
+ * SINGLE VALUE TRUE
+ * ID pkcs-9-at-friendlyName
+ * }
+ */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_BMPSTRING) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Expected BMPSTRING (friendlyName) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return 0;
+ }
+ wpa_hexdump_ascii(MSG_DEBUG, "PKCS #12: friendlyName",
+ hdr.payload, hdr.length);
+ return 0;
+}
+
+
+static int pkcs12_parse_attr_local_key_id(const u8 *pos, const u8 *end)
+{
+ struct asn1_hdr hdr;
+
+ /*
+ * RFC 2985, 5.5.2:
+ * localKeyId ATTRIBUTE ::= {
+ * WITH SYNTAX OCTET STRING
+ * EQUALITY MATCHING RULE octetStringMatch
+ * SINGLE VALUE TRUE
+ * ID pkcs-9-at-localKeyId
+ * }
+ */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_OCTETSTRING) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Expected OCTET STRING (localKeyID) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+ wpa_hexdump_key(MSG_DEBUG, "PKCS #12: localKeyID",
+ hdr.payload, hdr.length);
+ return 0;
+}
+
+
+static int pkcs12_parse_attr(const u8 *pos, size_t len)
+{
+ const u8 *end = pos + len;
+ struct asn1_hdr hdr;
+ struct asn1_oid a_oid;
+ char obuf[80];
+
+ /*
+ * PKCS12Attribute ::= SEQUENCE {
+ * attrId ATTRIBUTE.&id ({PKCS12AttrSet}),
+ * attrValues SET OF ATTRIBUTE.&Type ({PKCS12AttrSet}{@attrId})
+ * }
+ */
+
+ if (asn1_get_oid(pos, end - pos, &a_oid, &pos)) {
+ wpa_printf(MSG_DEBUG, "PKCS #12: Failed to parse OID (attrId)");
+ return -1;
+ }
+
+ asn1_oid_to_str(&a_oid, obuf, sizeof(obuf));
+ wpa_printf(MSG_DEBUG, "PKCS #12: attrId %s", obuf);
+
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SET) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Expected SET (attrValues) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+ wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: attrValues",
+ hdr.payload, hdr.length);
+ pos = hdr.payload;
+ end = hdr.payload + hdr.length;
+
+ if (is_oid_pkcs9_friendly_name(&a_oid))
+ return pkcs12_parse_attr_friendly_name(pos, end);
+ if (is_oid_pkcs9_local_key_id(&a_oid))
+ return pkcs12_parse_attr_local_key_id(pos, end);
+
+ wpa_printf(MSG_DEBUG, "PKCS #12: Ignore unknown attribute");
+ return 0;
+}
+
+
+static int pkcs12_safebag(struct tlsv1_credentials *cred,
+ const u8 *buf, size_t len, const char *passwd)
+{
+ struct asn1_hdr hdr;
+ struct asn1_oid oid;
+ char obuf[80];
+ const u8 *pos = buf, *end = buf + len;
+ const u8 *value;
+ size_t value_len;
+
+ wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: SafeBag", buf, len);
+
+ /* BAG-TYPE ::= TYPE-IDENTIFIER */
+ if (asn1_get_oid(pos, end - pos, &oid, &pos)) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Failed to parse OID (BAG-TYPE)");
+ return -1;
+ }
+
+ asn1_oid_to_str(&oid, obuf, sizeof(obuf));
+ wpa_printf(MSG_DEBUG, "PKCS #12: BAG-TYPE %s", obuf);
+
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
+ hdr.tag != 0) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Expected [0] EXPLICIT (bagValue) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return 0;
+ }
+ value = hdr.payload;
+ value_len = hdr.length;
+ wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: bagValue", value, value_len);
+ pos = hdr.payload + hdr.length;
+
+ if (pos < end) {
+ /* bagAttributes SET OF PKCS12Attribute OPTIONAL */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SET) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Expected SET (bagAttributes) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+ wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: bagAttributes",
+ hdr.payload, hdr.length);
+
+ pos = hdr.payload;
+ end = hdr.payload + hdr.length;
+ while (pos < end) {
+ /* PKCS12Attribute ::= SEQUENCE */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Expected SEQUENCE (PKCS12Attribute) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+ if (pkcs12_parse_attr(hdr.payload, hdr.length) < 0)
+ return -1;
+ pos = hdr.payload + hdr.length;
+ }
+ }
+
+ if (pkcs12_is_bagtype_oid(&oid, 1))
+ return pkcs12_keybag(cred, value, value_len);
+ if (pkcs12_is_bagtype_oid(&oid, 2))
+ return pkcs12_pkcs8_keybag(cred, value, value_len, passwd);
+ if (pkcs12_is_bagtype_oid(&oid, 3))
+ return pkcs12_certbag(cred, value, value_len);
+
+ wpa_printf(MSG_DEBUG, "PKCS #12: Ignore unsupported BAG-TYPE");
+ return 0;
+}
+
+
+static int pkcs12_safecontents(struct tlsv1_credentials *cred,
+ const u8 *buf, size_t len,
+ const char *passwd)
+{
+ struct asn1_hdr hdr;
+ const u8 *pos, *end;
+
+ /* SafeContents ::= SEQUENCE OF SafeBag */
+ if (asn1_get_next(buf, len, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Expected SEQUENCE (SafeContents) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+ pos = hdr.payload;
+ end = hdr.payload + hdr.length;
+
+ /*
+ * SafeBag ::= SEQUENCE {
+ * bagId BAG-TYPE.&id ({PKCS12BagSet})
+ * bagValue [0] EXPLICIT BAG-TYPE.&Type({PKCS12BagSet}{@bagId}),
+ * bagAttributes SET OF PKCS12Attribute OPTIONAL
+ * }
+ */
+
+ while (pos < end) {
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Expected SEQUENCE (SafeBag) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+ if (pkcs12_safebag(cred, hdr.payload, hdr.length, passwd) < 0)
+ return -1;
+ pos = hdr.payload + hdr.length;
+ }
+
+ return 0;
+}
+
+
+static int pkcs12_parse_content_data(struct tlsv1_credentials *cred,
+ const u8 *pos, const u8 *end,
+ const char *passwd)
+{
+ struct asn1_hdr hdr;
+
+ /* Data ::= OCTET STRING */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_OCTETSTRING) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Expected OCTET STRING (Data) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+
+ wpa_hexdump(MSG_MSGDUMP, "PKCS #12: Data", hdr.payload, hdr.length);
+
+ return pkcs12_safecontents(cred, hdr.payload, hdr.length, passwd);
+}
+
+
+static int pkcs12_parse_content_enc_data(struct tlsv1_credentials *cred,
+ const u8 *pos, const u8 *end,
+ const char *passwd)
+{
+ struct asn1_hdr hdr;
+ struct asn1_oid oid;
+ char buf[80];
+ const u8 *enc_alg;
+ u8 *data;
+ size_t enc_alg_len, data_len;
+ int res = -1;
+
+ /*
+ * EncryptedData ::= SEQUENCE {
+ * version Version,
+ * encryptedContentInfo EncryptedContentInfo }
+ */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Expected SEQUENCE (EncryptedData) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return 0;
+ }
+ pos = hdr.payload;
+
+ /* Version ::= INTEGER */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: No INTEGER tag found for version; class=%d tag=0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+ if (hdr.length != 1 || hdr.payload[0] != 0) {
+ wpa_printf(MSG_DEBUG, "PKCS #12: Unrecognized PKCS #7 version");
+ return -1;
+ }
+ pos = hdr.payload + hdr.length;
+
+ wpa_hexdump(MSG_MSGDUMP, "PKCS #12: EncryptedContentInfo",
+ pos, end - pos);
+
+ /*
+ * EncryptedContentInfo ::= SEQUENCE {
+ * contentType ContentType,
+ * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
+ * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL }
+ */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Expected SEQUENCE (EncryptedContentInfo) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+
+ pos = hdr.payload;
+ end = pos + hdr.length;
+
+ /* ContentType ::= OBJECT IDENTIFIER */
+ if (asn1_get_oid(pos, end - pos, &oid, &pos)) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Could not find OBJECT IDENTIFIER (contentType)");
+ return -1;
+ }
+ asn1_oid_to_str(&oid, buf, sizeof(buf));
+ wpa_printf(MSG_DEBUG, "PKCS #12: EncryptedContentInfo::contentType %s",
+ buf);
+
+ if (!is_oid_pkcs7_data(&oid)) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Unsupported EncryptedContentInfo::contentType %s",
+ buf);
+ return 0;
+ }
+
+ /* ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG, "PKCS #12: Expected SEQUENCE (ContentEncryptionAlgorithmIdentifier) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+ enc_alg = hdr.payload;
+ enc_alg_len = hdr.length;
+ pos = hdr.payload + hdr.length;
+
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
+ hdr.tag != 0) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Expected [0] IMPLICIT (encryptedContent) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+
+ /* EncryptedContent ::= OCTET STRING */
+ data = pkcs5_decrypt(enc_alg, enc_alg_len, hdr.payload, hdr.length,
+ passwd, &data_len);
+ if (data) {
+ wpa_hexdump_key(MSG_MSGDUMP,
+ "PKCS #12: Decrypted encryptedContent",
+ data, data_len);
+ res = pkcs12_safecontents(cred, data, data_len, passwd);
+ os_free(data);
+ }
+
+ return res;
+}
+
+
+static int pkcs12_parse_content(struct tlsv1_credentials *cred,
+ const u8 *buf, size_t len,
+ const char *passwd)
+{
+ const u8 *pos = buf;
+ const u8 *end = buf + len;
+ struct asn1_oid oid;
+ char txt[80];
+ struct asn1_hdr hdr;
+
+ wpa_hexdump(MSG_MSGDUMP, "PKCS #12: ContentInfo", buf, len);
+
+ if (asn1_get_oid(pos, end - pos, &oid, &pos)) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Could not find OBJECT IDENTIFIER (contentType)");
+ return 0;
+ }
+
+ asn1_oid_to_str(&oid, txt, sizeof(txt));
+ wpa_printf(MSG_DEBUG, "PKCS #12: contentType %s", txt);
+
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
+ hdr.tag != 0) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Expected [0] EXPLICIT (content) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return 0;
+ }
+ pos = hdr.payload;
+
+ if (is_oid_pkcs7_data(&oid))
+ return pkcs12_parse_content_data(cred, pos, end, passwd);
+ if (is_oid_pkcs7_enc_data(&oid))
+ return pkcs12_parse_content_enc_data(cred, pos, end, passwd);
+
+ wpa_printf(MSG_DEBUG, "PKCS #12: Ignored unsupported contentType %s",
+ txt);
+
+ return 0;
+}
+
+
+static int pkcs12_parse(struct tlsv1_credentials *cred,
+ const u8 *key, size_t len, const char *passwd)
+{
+ struct asn1_hdr hdr;
+ const u8 *pos, *end;
+ struct asn1_oid oid;
+ char buf[80];
+
+ /*
+ * PFX ::= SEQUENCE {
+ * version INTEGER {v3(3)}(v3,...),
+ * authSafe ContentInfo,
+ * macData MacData OPTIONAL
+ * }
+ */
+
+ if (asn1_get_next(key, len, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Expected SEQUENCE (PFX) - found class %d tag 0x%x; assume PKCS #12 not used",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+
+ pos = hdr.payload;
+ end = pos + hdr.length;
+
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: No INTEGER tag found for version; class=%d tag=0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+ if (hdr.length != 1 || hdr.payload[0] != 3) {
+ wpa_printf(MSG_DEBUG, "PKCS #12: Unrecognized version");
+ return -1;
+ }
+ pos = hdr.payload + hdr.length;
+
+ /*
+ * ContentInfo ::= SEQUENCE {
+ * contentType ContentType,
+ * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+ */
+
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Expected SEQUENCE (authSafe) - found class %d tag 0x%x; assume PKCS #12 not used",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+
+ pos = hdr.payload;
+ end = pos + hdr.length;
+
+ /* ContentType ::= OBJECT IDENTIFIER */
+ if (asn1_get_oid(pos, end - pos, &oid, &pos)) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Could not find OBJECT IDENTIFIER (contentType); assume PKCS #12 not used");
+ return -1;
+ }
+ asn1_oid_to_str(&oid, buf, sizeof(buf));
+ wpa_printf(MSG_DEBUG, "PKCS #12: contentType %s", buf);
+ if (!is_oid_pkcs7_data(&oid)) {
+ wpa_printf(MSG_DEBUG, "PKCS #12: Unsupported contentType %s",
+ buf);
+ return -1;
+ }
+
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
+ hdr.tag != 0) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Expected [0] EXPLICIT (content) - found class %d tag 0x%x; assume PKCS #12 not used",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+
+ pos = hdr.payload;
+
+ /* Data ::= OCTET STRING */
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_OCTETSTRING) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Expected OCTET STRING (Data) - found class %d tag 0x%x; assume PKCS #12 not used",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+
+ /*
+ * AuthenticatedSafe ::= SEQUENCE OF ContentInfo
+ * -- Data if unencrypted
+ * -- EncryptedData if password-encrypted
+ * -- EnvelopedData if public key-encrypted
+ */
+ wpa_hexdump(MSG_MSGDUMP, "PKCS #12: Data content",
+ hdr.payload, hdr.length);
+
+ if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Expected SEQUENCE within Data content - found class %d tag 0x%x; assume PKCS #12 not used",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+
+ pos = hdr.payload;
+ end = pos + hdr.length;
+
+ while (end > pos) {
+ if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG,
+ "PKCS #12: Expected SEQUENCE (ContentInfo) - found class %d tag 0x%x; assume PKCS #12 not used",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+ if (pkcs12_parse_content(cred, hdr.payload, hdr.length,
+ passwd) < 0)
+ return -1;
+
+ pos = hdr.payload + hdr.length;
+ }
+
+ return 0;
+}
+
+#endif /* PKCS12_FUNCS */
+
+
static int tlsv1_set_key(struct tlsv1_credentials *cred,
const u8 *key, size_t len, const char *passwd)
{
cred->key = tlsv1_set_key_pem(key, len);
if (cred->key == NULL)
cred->key = tlsv1_set_key_enc_pem(key, len, passwd);
+#ifdef PKCS12_FUNCS
+ if (!cred->key)
+ pkcs12_parse(cred, key, len, passwd);
+#endif /* PKCS12_FUNCS */
if (cred->key == NULL) {
wpa_printf(MSG_INFO, "TLSv1: Failed to parse private key");
return -1;
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;
};
void *log_cb_ctx;
int use_session_ticket;
+ unsigned int status_request:1;
+ unsigned int status_request_v2:1;
+ unsigned int status_request_multi:1;
u8 *dh_secret;
size_t dh_secret_len;
}
+static void tls_process_status_request_item(struct tlsv1_server *conn,
+ const u8 *req, size_t req_len)
+{
+ const u8 *pos, *end;
+ u8 status_type;
+
+ pos = req;
+ end = req + req_len;
+
+ /*
+ * RFC 6961, 2.2:
+ * struct {
+ * CertificateStatusType status_type;
+ * uint16 request_length;
+ * select (status_type) {
+ * case ocsp: OCSPStatusRequest;
+ * case ocsp_multi: OCSPStatusRequest;
+ * } request;
+ * } CertificateStatusRequestItemV2;
+ *
+ * enum { ocsp(1), ocsp_multi(2), (255) } CertificateStatusType;
+ */
+
+ if (end - pos < 1)
+ return; /* Truncated data */
+
+ status_type = *pos++;
+ wpa_printf(MSG_DEBUG, "TLSv1: CertificateStatusType %u", status_type);
+ if (status_type != 1 && status_type != 2)
+ return; /* Unsupported status type */
+ /*
+ * For now, only OCSP stapling is supported, so ignore the specific
+ * request, if any.
+ */
+ wpa_hexdump(MSG_DEBUG, "TLSv1: OCSPStatusRequest", pos, end - pos);
+
+ if (status_type == 2)
+ conn->status_request_multi = 1;
+}
+
+
+static void tls_process_status_request_v2(struct tlsv1_server *conn,
+ const u8 *ext, size_t ext_len)
+{
+ const u8 *pos, *end;
+
+ conn->status_request_v2 = 1;
+
+ pos = ext;
+ end = ext + ext_len;
+
+ /*
+ * RFC 6961, 2.2:
+ * struct {
+ * CertificateStatusRequestItemV2
+ * certificate_status_req_list<1..2^16-1>;
+ * } CertificateStatusRequestListV2;
+ */
+
+ while (end - pos >= 2) {
+ u16 len;
+
+ len = WPA_GET_BE16(pos);
+ pos += 2;
+ if (len > end - pos)
+ break; /* Truncated data */
+ tls_process_status_request_item(conn, pos, len);
+ pos += len;
+ }
+}
+
+
static int tls_process_client_hello(struct tlsv1_server *conn, u8 ct,
const u8 *in_data, size_t *in_len)
{
ext_len);
conn->session_ticket_len = ext_len;
}
+ } else if (ext_type == TLS_EXT_STATUS_REQUEST) {
+ conn->status_request = 1;
+ } else if (ext_type == TLS_EXT_STATUS_REQUEST_V2) {
+ tls_process_status_request_v2(conn, pos,
+ ext_len);
}
pos += ext_len;
return -1;
}
+ if (chain && (chain->extensions_present & X509_EXT_EXT_KEY_USAGE) &&
+ !(chain->ext_key_usage &
+ (X509_EXT_KEY_USAGE_ANY | X509_EXT_KEY_USAGE_CLIENT_AUTH))) {
+ tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_BAD_CERTIFICATE);
+ x509_certificate_chain_free(chain);
+ return -1;
+ }
+
x509_certificate_chain_free(chain);
*in_len = end - in_data;
static int tls_write_server_hello(struct tlsv1_server *conn,
u8 **msgpos, u8 *end)
{
- u8 *pos, *rhdr, *hs_start, *hs_length;
+ u8 *pos, *rhdr, *hs_start, *hs_length, *ext_start;
struct os_time now;
size_t rlen;
/* CompressionMethod compression_method */
*pos++ = TLS_COMPRESSION_NULL;
+ /* Extension */
+ ext_start = pos;
+ pos += 2;
+
+ if (conn->status_request) {
+ /* Add a status_request extension with empty extension_data */
+ /* ExtensionsType extension_type = status_request(5) */
+ WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST);
+ pos += 2;
+ /* opaque extension_data<0..2^16-1> length */
+ WPA_PUT_BE16(pos, 0);
+ pos += 2;
+ }
+
+ if (conn->status_request_v2) {
+ /*
+ Add a status_request_v2 extension with empty extension_data
+ */
+ /* ExtensionsType extension_type = status_request_v2(17) */
+ WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST_V2);
+ pos += 2;
+ /* opaque extension_data<0..2^16-1> length */
+ WPA_PUT_BE16(pos, 0);
+ pos += 2;
+ }
+
if (conn->session_ticket && conn->session_ticket_cb) {
int res = conn->session_ticket_cb(
conn->session_ticket_cb_ctx,
*/
}
+ if (pos == ext_start + 2)
+ pos -= 2; /* no extensions */
+ else
+ WPA_PUT_BE16(ext_start, pos - ext_start - 2);
+
WPA_PUT_BE24(hs_length, pos - hs_length - 3);
tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
}
pos = *msgpos;
+ if (TLS_RECORD_HEADER_LEN + 1 + 3 + 3 > end - pos) {
+ tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_INTERNAL_ERROR);
+ return -1;
+ }
tlsv1_server_log(conn, "Send Certificate");
rhdr = pos;
pos += 3;
cert = conn->cred->cert;
while (cert) {
- if (pos + 3 + cert->cert_len > end) {
+ if (3 + cert->cert_len > (size_t) (end - pos)) {
wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space "
"for Certificate (cert_len=%lu left=%lu)",
(unsigned long) cert->cert_len,
}
+static int tls_write_server_certificate_status(struct tlsv1_server *conn,
+ u8 **msgpos, u8 *end,
+ int ocsp_multi,
+ char *ocsp_resp,
+ size_t ocsp_resp_len)
+{
+ u8 *pos, *rhdr, *hs_start, *hs_length;
+ size_t rlen;
+
+ if (!ocsp_resp) {
+ /*
+ * Client did not request certificate status or there is no
+ * matching response cached.
+ */
+ return 0;
+ }
+
+ pos = *msgpos;
+ if (TLS_RECORD_HEADER_LEN + 1 + 3 + 1 + 3 + ocsp_resp_len >
+ (unsigned int) (end - pos)) {
+ tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_INTERNAL_ERROR);
+ return -1;
+ }
+
+ tlsv1_server_log(conn, "Send CertificateStatus (multi=%d)", ocsp_multi);
+ rhdr = pos;
+ pos += TLS_RECORD_HEADER_LEN;
+
+ /* opaque fragment[TLSPlaintext.length] */
+
+ /* Handshake */
+ hs_start = pos;
+ /* HandshakeType msg_type */
+ *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS;
+ /* uint24 length (to be filled) */
+ hs_length = pos;
+ pos += 3;
+
+ /* body - CertificateStatus
+ *
+ * struct {
+ * CertificateStatusType status_type;
+ * select (status_type) {
+ * case ocsp: OCSPResponse;
+ * case ocsp_multi: OCSPResponseList;
+ * } response;
+ * } CertificateStatus;
+ *
+ * opaque OCSPResponse<1..2^24-1>;
+ *
+ * struct {
+ * OCSPResponse ocsp_response_list<1..2^24-1>;
+ * } OCSPResponseList;
+ */
+
+ /* CertificateStatusType status_type */
+ if (ocsp_multi)
+ *pos++ = 2; /* ocsp_multi(2) */
+ else
+ *pos++ = 1; /* ocsp(1) */
+ /* uint24 length of OCSPResponse */
+ WPA_PUT_BE24(pos, ocsp_resp_len);
+ pos += 3;
+ os_memcpy(pos, ocsp_resp, ocsp_resp_len);
+ pos += ocsp_resp_len;
+
+ WPA_PUT_BE24(hs_length, pos - hs_length - 3);
+
+ if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
+ rhdr, end - rhdr, hs_start, pos - hs_start,
+ &rlen) < 0) {
+ wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
+ tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_INTERNAL_ERROR);
+ return -1;
+ }
+ pos = rhdr + rlen;
+
+ tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
+
+ *msgpos = pos;
+
+ return 0;
+}
+
+
static int tls_write_server_key_exchange(struct tlsv1_server *conn,
u8 **msgpos, u8 *end)
{
/* body - ServerDHParams */
server_params = pos;
/* dh_p */
- if (pos + 2 + dh_p_len > end) {
+ if (2 + dh_p_len > (size_t) (end - pos)) {
wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for "
"dh_p");
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
pos += dh_p_len;
/* dh_g */
- if (pos + 2 + conn->cred->dh_g_len > end) {
+ if (2 + conn->cred->dh_g_len > (size_t) (end - pos)) {
wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for "
"dh_g");
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
pos += conn->cred->dh_g_len;
/* dh_Ys */
- if (pos + 2 + dh_ys_len > end) {
+ if (2 + dh_ys_len > (size_t) (end - pos)) {
wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for "
"dh_Ys");
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
if (conn->rl.tls_version >= TLS_VERSION_1_2) {
#ifdef CONFIG_TLSV12
hlen = tlsv12_key_x_server_params_hash(
- conn->rl.tls_version, conn->client_random,
+ conn->rl.tls_version, TLS_HASH_ALG_SHA256,
+ conn->client_random,
conn->server_random, server_params,
pos - server_params, hash + 19);
* SignatureAlgorithm signature;
* } SignatureAndHashAlgorithm;
*/
- if (hlen < 0 || pos + 2 > end) {
+ if (hlen < 0 || end - pos < 2) {
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
TLS_ALERT_INTERNAL_ERROR);
return -1;
{
u8 *msg, *end, *pos;
size_t msglen;
+ int ocsp_multi = 0;
+ char *ocsp_resp = NULL;
+ size_t ocsp_resp_len = 0;
*out_len = 0;
- msglen = 1000 + tls_server_cert_chain_der_len(conn);
+ if (conn->status_request_multi &&
+ conn->cred->ocsp_stapling_response_multi) {
+ ocsp_resp = os_readfile(
+ conn->cred->ocsp_stapling_response_multi,
+ &ocsp_resp_len);
+ ocsp_multi = 1;
+ } else if ((conn->status_request || conn->status_request_v2) &&
+ conn->cred->ocsp_stapling_response) {
+ ocsp_resp = os_readfile(conn->cred->ocsp_stapling_response,
+ &ocsp_resp_len);
+ }
+ if (!ocsp_resp)
+ ocsp_resp_len = 0;
+
+ msglen = 1000 + tls_server_cert_chain_der_len(conn) + ocsp_resp_len;
msg = os_malloc(msglen);
- if (msg == NULL)
+ if (msg == NULL) {
+ os_free(ocsp_resp);
return NULL;
+ }
pos = msg;
end = msg + msglen;
if (tls_write_server_hello(conn, &pos, end) < 0) {
os_free(msg);
+ os_free(ocsp_resp);
return NULL;
}
if (conn->use_session_ticket) {
+ os_free(ocsp_resp);
+
/* Abbreviated handshake using session ticket; RFC 4507 */
if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 ||
tls_write_server_finished(conn, &pos, end) < 0) {
/* Full handshake */
if (tls_write_server_certificate(conn, &pos, end) < 0 ||
+ tls_write_server_certificate_status(conn, &pos, end, ocsp_multi,
+ ocsp_resp, ocsp_resp_len) < 0 ||
tls_write_server_key_exchange(conn, &pos, end) < 0 ||
tls_write_server_certificate_request(conn, &pos, end) < 0 ||
tls_write_server_hello_done(conn, &pos, end) < 0) {
os_free(msg);
+ os_free(ocsp_resp);
return NULL;
}
+ os_free(ocsp_resp);
*out_len = pos - msg;
/*
* X.509v3 certificate parsing and processing (RFC 3280 profile)
- * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
#include "x509v3.h"
-static void x509_free_name(struct x509_name *name)
+void x509_free_name(struct x509_name *name)
{
size_t i;
x509_free_name(&cert->subject);
os_free(cert->public_key);
os_free(cert->sign_value);
+ os_free(cert->subject_dn);
os_free(cert);
}
}
-static int x509_parse_algorithm_identifier(
- const u8 *buf, size_t len,
- struct x509_algorithm_identifier *id, const u8 **next)
+int x509_parse_algorithm_identifier(const u8 *buf, size_t len,
+ struct x509_algorithm_identifier *id,
+ const u8 **next)
{
struct asn1_hdr hdr;
const u8 *pos, *end;
hdr.class, hdr.tag);
return -1;
}
+ if (hdr.length > buf + len - hdr.payload)
+ return -1;
pos = hdr.payload;
end = pos + hdr.length;
- if (end > buf + len)
- return -1;
-
*next = end;
if (asn1_get_oid(pos, end - pos, &id->oid, &pos))
}
pos = hdr.payload;
- if (pos + hdr.length > end)
+ if (hdr.length > end - pos)
return -1;
end = pos + hdr.length;
*next = end;
}
-static int x509_parse_name(const u8 *buf, size_t len, struct x509_name *name,
- const u8 **next)
+int x509_parse_name(const u8 *buf, size_t len, struct x509_name *name,
+ const u8 **next)
{
struct asn1_hdr hdr;
const u8 *pos, *end, *set_pos, *set_end, *seq_pos, *seq_end;
}
pos = hdr.payload;
- if (pos + hdr.length > buf + len)
+ if (hdr.length > buf + len - pos)
return -1;
end = *next = pos + hdr.length;
}
-static int x509_parse_time(const u8 *buf, size_t len, u8 asn1_tag,
- os_time_t *val)
+int x509_parse_time(const u8 *buf, size_t len, u8 asn1_tag, os_time_t *val)
{
const char *pos;
int year, month, day, hour, min, sec;
pos = hdr.payload;
plen = hdr.length;
- if (pos + plen > buf + len)
+ if (plen > (size_t) (buf + len - pos))
return -1;
*next = pos + plen;
}
+static int x509_any_ext_key_usage_oid(struct asn1_oid *oid)
+{
+ return oid->len == 6 &&
+ x509_id_ce_oid(oid) &&
+ oid->oid[3] == 37 /* extKeyUsage */ &&
+ oid->oid[4] == 0 /* anyExtendedKeyUsage */;
+}
+
+
static int x509_parse_ext_key_usage(struct x509_certificate *cert,
const u8 *pos, size_t len)
{
}
cert->ca = hdr.payload[0];
- if (hdr.payload + hdr.length == pos + len) {
+ if (hdr.length == pos + len - hdr.payload) {
wpa_printf(MSG_DEBUG, "X509: BasicConstraints - cA=%d",
cert->ca);
return 0;
}
+static int x509_id_pkix_oid(struct asn1_oid *oid)
+{
+ return oid->len >= 7 &&
+ oid->oid[0] == 1 /* iso */ &&
+ oid->oid[1] == 3 /* identified-organization */ &&
+ oid->oid[2] == 6 /* dod */ &&
+ oid->oid[3] == 1 /* internet */ &&
+ oid->oid[4] == 5 /* security */ &&
+ oid->oid[5] == 5 /* mechanisms */ &&
+ oid->oid[6] == 7 /* id-pkix */;
+}
+
+
+static int x509_id_kp_oid(struct asn1_oid *oid)
+{
+ /* id-kp */
+ return oid->len >= 8 &&
+ x509_id_pkix_oid(oid) &&
+ oid->oid[7] == 3 /* id-kp */;
+}
+
+
+static int x509_id_kp_server_auth_oid(struct asn1_oid *oid)
+{
+ /* id-kp */
+ return oid->len == 9 &&
+ x509_id_kp_oid(oid) &&
+ oid->oid[8] == 1 /* id-kp-serverAuth */;
+}
+
+
+static int x509_id_kp_client_auth_oid(struct asn1_oid *oid)
+{
+ /* id-kp */
+ return oid->len == 9 &&
+ x509_id_kp_oid(oid) &&
+ oid->oid[8] == 2 /* id-kp-clientAuth */;
+}
+
+
+static int x509_id_kp_ocsp_oid(struct asn1_oid *oid)
+{
+ /* id-kp */
+ return oid->len == 9 &&
+ x509_id_kp_oid(oid) &&
+ oid->oid[8] == 9 /* id-kp-OCSPSigning */;
+}
+
+
+static int x509_parse_ext_ext_key_usage(struct x509_certificate *cert,
+ const u8 *pos, size_t len)
+{
+ struct asn1_hdr hdr;
+ const u8 *end;
+ struct asn1_oid oid;
+
+ /*
+ * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
+ *
+ * KeyPurposeId ::= OBJECT IDENTIFIER
+ */
+
+ if (asn1_get_next(pos, len, &hdr) < 0 ||
+ hdr.class != ASN1_CLASS_UNIVERSAL ||
+ hdr.tag != ASN1_TAG_SEQUENCE) {
+ wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE "
+ "(ExtKeyUsageSyntax) - found class %d tag 0x%x",
+ hdr.class, hdr.tag);
+ return -1;
+ }
+ if (hdr.length > pos + len - hdr.payload)
+ return -1;
+ pos = hdr.payload;
+ end = pos + hdr.length;
+
+ wpa_hexdump(MSG_MSGDUMP, "X509: ExtKeyUsageSyntax", pos, end - pos);
+
+ while (pos < end) {
+ char buf[80];
+
+ if (asn1_get_oid(pos, end - pos, &oid, &pos))
+ return -1;
+ if (x509_any_ext_key_usage_oid(&oid)) {
+ os_strlcpy(buf, "anyExtendedKeyUsage", sizeof(buf));
+ cert->ext_key_usage |= X509_EXT_KEY_USAGE_ANY;
+ } else if (x509_id_kp_server_auth_oid(&oid)) {
+ os_strlcpy(buf, "id-kp-serverAuth", sizeof(buf));
+ cert->ext_key_usage |= X509_EXT_KEY_USAGE_SERVER_AUTH;
+ } else if (x509_id_kp_client_auth_oid(&oid)) {
+ os_strlcpy(buf, "id-kp-clientAuth", sizeof(buf));
+ cert->ext_key_usage |= X509_EXT_KEY_USAGE_CLIENT_AUTH;
+ } else if (x509_id_kp_ocsp_oid(&oid)) {
+ os_strlcpy(buf, "id-kp-OCSPSigning", sizeof(buf));
+ cert->ext_key_usage |= X509_EXT_KEY_USAGE_OCSP;
+ } else {
+ asn1_oid_to_str(&oid, buf, sizeof(buf));
+ }
+ wpa_printf(MSG_DEBUG, "ExtKeyUsage KeyPurposeId: %s", buf);
+ }
+
+ cert->extensions_present |= X509_EXT_EXT_KEY_USAGE;
+
+ return 0;
+}
+
+
static int x509_parse_extension_data(struct x509_certificate *cert,
struct asn1_oid *oid,
const u8 *pos, size_t len)
* certificate policies (section 4.2.1.5)
* name constraints (section 4.2.1.11)
* policy constraints (section 4.2.1.12)
- * extended key usage (section 4.2.1.13)
* inhibit any-policy (section 4.2.1.15)
*/
switch (oid->oid[3]) {
return x509_parse_ext_issuer_alt_name(cert, pos, len);
case 19: /* id-ce-basicConstraints */
return x509_parse_ext_basic_constraints(cert, pos, len);
+ case 37: /* id-ce-extKeyUsage */
+ return x509_parse_ext_ext_key_usage(cert, pos, len);
default:
return 1;
}
size_t left;
char sbuf[128];
unsigned long value;
+ const u8 *subject_dn;
/* tbsCertificate TBSCertificate ::= SEQUENCE */
if (asn1_get_next(buf, len, &hdr) < 0 ||
/* serialNumber CertificateSerialNumber ::= INTEGER */
if (hdr.class != ASN1_CLASS_UNIVERSAL ||
- hdr.tag != ASN1_TAG_INTEGER) {
+ hdr.tag != ASN1_TAG_INTEGER ||
+ hdr.length < 1 || hdr.length > X509_MAX_SERIAL_NUM_LEN) {
wpa_printf(MSG_DEBUG, "X509: No INTEGER tag found for "
- "serialNumber; class=%d tag=0x%x",
- hdr.class, hdr.tag);
+ "serialNumber; class=%d tag=0x%x length=%u",
+ hdr.class, hdr.tag, hdr.length);
return -1;
}
- pos = hdr.payload;
- left = hdr.length;
- while (left) {
- cert->serial_number <<= 8;
- cert->serial_number |= *pos++;
- left--;
+ pos = hdr.payload + hdr.length;
+ while (hdr.length > 0 && hdr.payload[0] == 0) {
+ hdr.payload++;
+ hdr.length--;
}
- wpa_printf(MSG_MSGDUMP, "X509: serialNumber %lu", cert->serial_number);
+ os_memcpy(cert->serial_number, hdr.payload, hdr.length);
+ cert->serial_number_len = hdr.length;
+ wpa_hexdump(MSG_MSGDUMP, "X509: serialNumber", cert->serial_number,
+ cert->serial_number_len);
/* signature AlgorithmIdentifier */
if (x509_parse_algorithm_identifier(pos, end - pos, &cert->signature,
return -1;
/* subject Name */
+ subject_dn = pos;
if (x509_parse_name(pos, end - pos, &cert->subject, &pos))
return -1;
+ cert->subject_dn = os_malloc(pos - subject_dn);
+ if (!cert->subject_dn)
+ return -1;
+ cert->subject_dn_len = pos - subject_dn;
+ os_memcpy(cert->subject_dn, subject_dn, cert->subject_dn_len);
x509_name_string(&cert->subject, sbuf, sizeof(sbuf));
wpa_printf(MSG_MSGDUMP, "X509: subject %s", sbuf);
}
-static int x509_sha1_oid(struct asn1_oid *oid)
+int x509_sha1_oid(struct asn1_oid *oid)
{
return oid->len == 6 &&
oid->oid[0] == 1 /* iso */ &&
}
-static int x509_sha256_oid(struct asn1_oid *oid)
+static int x509_sha2_oid(struct asn1_oid *oid)
{
return oid->len == 9 &&
oid->oid[0] == 2 /* joint-iso-itu-t */ &&
oid->oid[4] == 101 /* gov */ &&
oid->oid[5] == 3 /* csor */ &&
oid->oid[6] == 4 /* nistAlgorithm */ &&
- oid->oid[7] == 2 /* hashAlgs */ &&
+ oid->oid[7] == 2 /* hashAlgs */;
+}
+
+
+int x509_sha256_oid(struct asn1_oid *oid)
+{
+ return x509_sha2_oid(oid) &&
oid->oid[8] == 1 /* sha256 */;
}
+int x509_sha384_oid(struct asn1_oid *oid)
+{
+ return x509_sha2_oid(oid) &&
+ oid->oid[8] == 2 /* sha384 */;
+}
+
+
+int x509_sha512_oid(struct asn1_oid *oid)
+{
+ return x509_sha2_oid(oid) &&
+ oid->oid[8] == 3 /* sha512 */;
+}
+
+
/**
* x509_certificate_parse - Parse a X.509 certificate in DER format
* @buf: Pointer to the X.509 certificate in DER format
}
pos = hdr.payload;
- if (pos + hdr.length > end) {
+ if (hdr.length > end - pos) {
x509_certificate_free(cert);
return NULL;
}
- if (pos + hdr.length < end) {
+ if (hdr.length < end - pos) {
wpa_hexdump(MSG_MSGDUMP, "X509: Ignoring extra data after DER "
"encoded certificate",
pos + hdr.length, end - (pos + hdr.length));
int x509_certificate_check_signature(struct x509_certificate *issuer,
struct x509_certificate *cert)
{
+ return x509_check_signature(issuer, &cert->signature,
+ cert->sign_value, cert->sign_value_len,
+ cert->tbs_cert_start, cert->tbs_cert_len);
+}
+
+
+int x509_check_signature(struct x509_certificate *issuer,
+ struct x509_algorithm_identifier *signature,
+ const u8 *sign_value, size_t sign_value_len,
+ const u8 *signed_data, size_t signed_data_len)
+{
struct crypto_public_key *pk;
u8 *data;
const u8 *pos, *end, *next, *da_end;
size_t data_len;
struct asn1_hdr hdr;
struct asn1_oid oid;
- u8 hash[32];
+ u8 hash[64];
size_t hash_len;
+ const u8 *addr[1] = { signed_data };
+ size_t len[1] = { signed_data_len };
- if (!x509_pkcs_oid(&cert->signature.oid) ||
- cert->signature.oid.len != 7 ||
- cert->signature.oid.oid[5] != 1 /* pkcs-1 */) {
+ if (!x509_pkcs_oid(&signature->oid) ||
+ signature->oid.len != 7 ||
+ signature->oid.oid[5] != 1 /* pkcs-1 */) {
wpa_printf(MSG_DEBUG, "X509: Unrecognized signature "
"algorithm");
return -1;
if (pk == NULL)
return -1;
- data_len = cert->sign_value_len;
+ data_len = sign_value_len;
data = os_malloc(data_len);
if (data == NULL) {
crypto_public_key_free(pk);
return -1;
}
- if (crypto_public_key_decrypt_pkcs1(pk, cert->sign_value,
- cert->sign_value_len, data,
+ if (crypto_public_key_decrypt_pkcs1(pk, sign_value,
+ sign_value_len, data,
&data_len) < 0) {
wpa_printf(MSG_DEBUG, "X509: Failed to decrypt signature");
crypto_public_key_free(pk);
}
if (x509_sha1_oid(&oid)) {
- if (cert->signature.oid.oid[6] !=
- 5 /* sha-1WithRSAEncryption */) {
+ if (signature->oid.oid[6] != 5 /* sha-1WithRSAEncryption */) {
wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA1 "
"does not match with certificate "
"signatureAlgorithm (%lu)",
- cert->signature.oid.oid[6]);
+ signature->oid.oid[6]);
os_free(data);
return -1;
}
}
if (x509_sha256_oid(&oid)) {
- if (cert->signature.oid.oid[6] !=
+ if (signature->oid.oid[6] !=
11 /* sha2561WithRSAEncryption */) {
wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA256 "
"does not match with certificate "
"signatureAlgorithm (%lu)",
- cert->signature.oid.oid[6]);
+ signature->oid.oid[6]);
+ os_free(data);
+ return -1;
+ }
+ goto skip_digest_oid;
+ }
+
+ if (x509_sha384_oid(&oid)) {
+ if (signature->oid.oid[6] != 12 /* sha384WithRSAEncryption */) {
+ wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA384 "
+ "does not match with certificate "
+ "signatureAlgorithm (%lu)",
+ signature->oid.oid[6]);
+ os_free(data);
+ return -1;
+ }
+ goto skip_digest_oid;
+ }
+
+ if (x509_sha512_oid(&oid)) {
+ if (signature->oid.oid[6] != 13 /* sha512WithRSAEncryption */) {
+ wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA512 "
+ "does not match with certificate "
+ "signatureAlgorithm (%lu)",
+ signature->oid.oid[6]);
os_free(data);
return -1;
}
}
switch (oid.oid[5]) {
case 5: /* md5 */
- if (cert->signature.oid.oid[6] != 4 /* md5WithRSAEncryption */)
- {
+ if (signature->oid.oid[6] != 4 /* md5WithRSAEncryption */) {
wpa_printf(MSG_DEBUG, "X509: digestAlgorithm MD5 does "
"not match with certificate "
"signatureAlgorithm (%lu)",
- cert->signature.oid.oid[6]);
+ signature->oid.oid[6]);
os_free(data);
return -1;
}
wpa_hexdump(MSG_MSGDUMP, "X509: Decrypted Digest",
hdr.payload, hdr.length);
- switch (cert->signature.oid.oid[6]) {
+ switch (signature->oid.oid[6]) {
case 4: /* md5WithRSAEncryption */
- md5_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len,
- hash);
+ md5_vector(1, addr, len, hash);
hash_len = 16;
wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (MD5)",
hash, hash_len);
break;
case 5: /* sha-1WithRSAEncryption */
- sha1_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len,
- hash);
+ sha1_vector(1, addr, len, hash);
hash_len = 20;
wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA1)",
hash, hash_len);
break;
case 11: /* sha256WithRSAEncryption */
- sha256_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len,
- hash);
+ sha256_vector(1, addr, len, hash);
hash_len = 32;
wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA256)",
hash, hash_len);
break;
- case 2: /* md2WithRSAEncryption */
case 12: /* sha384WithRSAEncryption */
+ sha384_vector(1, addr, len, hash);
+ hash_len = 48;
+ wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA384)",
+ hash, hash_len);
+ break;
case 13: /* sha512WithRSAEncryption */
+ sha512_vector(1, addr, len, hash);
+ hash_len = 64;
+ wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA512)",
+ hash, hash_len);
+ break;
+ case 2: /* md2WithRSAEncryption */
default:
wpa_printf(MSG_INFO, "X509: Unsupported certificate signature "
- "algorithm (%lu)", cert->signature.oid.oid[6]);
+ "algorithm (%lu)", signature->oid.oid[6]);
os_free(data);
return -1;
}
os_get_time(&now);
for (cert = chain, idx = 0; cert; cert = cert->next, idx++) {
+ cert->issuer_trusted = 0;
x509_name_string(&cert->subject, buf, sizeof(buf));
wpa_printf(MSG_DEBUG, "X509: %lu: %s", idx, buf);
wpa_printf(MSG_DEBUG, "X509: Trusted certificate "
"found to complete the chain");
+ cert->issuer_trusted = 1;
chain_trusted = 1;
}
}
struct asn1_oid rid; /* registeredID */
};
+#define X509_MAX_SERIAL_NUM_LEN 20
+
struct x509_certificate {
struct x509_certificate *next;
enum { X509_CERT_V1 = 0, X509_CERT_V2 = 1, X509_CERT_V3 = 2 } version;
- unsigned long serial_number;
+ u8 serial_number[X509_MAX_SERIAL_NUM_LEN];
+ size_t serial_number_len;
struct x509_algorithm_identifier signature;
struct x509_name issuer;
struct x509_name subject;
+ u8 *subject_dn;
+ size_t subject_dn_len;
os_time_t not_before;
os_time_t not_after;
struct x509_algorithm_identifier public_key_alg;
#define X509_EXT_KEY_USAGE (1 << 2)
#define X509_EXT_SUBJECT_ALT_NAME (1 << 3)
#define X509_EXT_ISSUER_ALT_NAME (1 << 4)
+#define X509_EXT_EXT_KEY_USAGE (1 << 5)
/* BasicConstraints */
int ca; /* cA */
#define X509_KEY_USAGE_ENCIPHER_ONLY (1 << 7)
#define X509_KEY_USAGE_DECIPHER_ONLY (1 << 8)
+ /* ExtKeyUsage */
+ unsigned long ext_key_usage;
+#define X509_EXT_KEY_USAGE_ANY (1 << 0)
+#define X509_EXT_KEY_USAGE_SERVER_AUTH (1 << 1)
+#define X509_EXT_KEY_USAGE_CLIENT_AUTH (1 << 2)
+#define X509_EXT_KEY_USAGE_OCSP (1 << 3)
+
/*
* The DER format certificate follows struct x509_certificate. These
* pointers point to that buffer.
size_t cert_len;
const u8 *tbs_cert_start;
size_t tbs_cert_len;
+
+ /* Meta data used for certificate validation */
+ unsigned int ocsp_good:1;
+ unsigned int ocsp_revoked:1;
+ unsigned int issuer_trusted:1;
};
enum {
};
void x509_certificate_free(struct x509_certificate *cert);
+int x509_parse_algorithm_identifier(const u8 *buf, size_t len,
+ struct x509_algorithm_identifier *id,
+ const u8 **next);
+int x509_parse_name(const u8 *buf, size_t len, struct x509_name *name,
+ const u8 **next);
+int x509_parse_time(const u8 *buf, size_t len, u8 asn1_tag, os_time_t *val);
struct x509_certificate * x509_certificate_parse(const u8 *buf, size_t len);
+void x509_free_name(struct x509_name *name);
void x509_name_string(struct x509_name *name, char *buf, size_t len);
int x509_name_compare(struct x509_name *a, struct x509_name *b);
void x509_certificate_chain_free(struct x509_certificate *cert);
+int x509_check_signature(struct x509_certificate *issuer,
+ struct x509_algorithm_identifier *signature,
+ const u8 *sign_value, size_t sign_value_len,
+ const u8 *signed_data, size_t signed_data_len);
int x509_certificate_check_signature(struct x509_certificate *issuer,
struct x509_certificate *cert);
int x509_certificate_chain_validate(struct x509_certificate *trusted,
struct x509_name *name);
int x509_certificate_self_signed(struct x509_certificate *cert);
+int x509_sha1_oid(struct asn1_oid *oid);
+int x509_sha256_oid(struct asn1_oid *oid);
+int x509_sha384_oid(struct asn1_oid *oid);
+int x509_sha512_oid(struct asn1_oid *oid);
+
#endif /* X509V3_H */
if (pid == 0) {
/* run the external command in the child process */
- char *argv[9];
+ char *argv[7];
argv[0] = "browser-android";
argv[1] = "start";
argv[3] = "android.intent.action.VIEW";
argv[4] = "-d";
argv[5] = (void *) url;
- argv[6] = "-n";
- argv[7] = "com.android.browser/.BrowserActivity";
- argv[8] = NULL;
+ argv[6] = NULL;
execv("/system/bin/am", argv);
wpa_printf(MSG_ERROR, "execv: %s", strerror(errno));
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 == '/') {
*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",
}
+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)
* @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
{
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;
+}
#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
*/
#ifdef __CHECKER__
#define __force __attribute__((force))
+#undef __bitwise
#define __bitwise __attribute__((bitwise))
#else
#define __force
#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);
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);
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);
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
return;
}
+ if (c == '\b') {
+ if (cmdbuf_pos > 0)
+ cmdbuf_pos--;
+ return;
+ }
+
if (c >= 32 && c <= 255) {
if (cmdbuf_pos < (int) sizeof(cmdbuf) - 1) {
cmdbuf[cmdbuf_pos++] = c;
#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
#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;
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;
#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 */
}
+#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 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;
- struct epoll_event ev, *temp_events;
int next;
-#endif /* CONFIG_ELOOP_EPOLL */
+#endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */
struct eloop_sock *tmp;
int new_max_sock;
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;
}
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,
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;
}
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)
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 */
}
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,
#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) {
#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;
_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
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
#ifdef CONFIG_ELOOP_EPOLL
"epoll"
#endif /* CONFIG_ELOOP_EPOLL */
+#ifdef CONFIG_ELOOP_KQUEUE
+ "kqueue"
+#endif /* CONFIG_ELOOP_EKQUEUE */
+
, strerror(errno));
goto out;
}
eloop_process_pending_signals();
+
/* check if some registered timeouts have occurred */
timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
list);
#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;
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 */
}
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
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
*
* Start the event loop and continue running as long as there are any
WSAEventSelect(sock, event, 0);
WSACloseEvent(event);
}
+
+
+int eloop_sock_requeue(void)
+{
+ return 0;
+}
#include "ext_password_i.h"
-#ifdef CONFIG_EXT_PASSWORD_TEST
-extern struct ext_password_backend ext_password_test;
-#endif /* CONFIG_EXT_PASSWORD_TEST */
-
static const struct ext_password_backend *backends[] = {
#ifdef CONFIG_EXT_PASSWORD_TEST
&ext_password_test,
struct wpabuf * ext_password_alloc(size_t len);
+/* Available ext_password backends */
+
+#ifdef CONFIG_EXT_PASSWORD_TEST
+extern const struct ext_password_backend ext_password_test;
+#endif /* CONFIG_EXT_PASSWORD_TEST */
+
#endif /* EXT_PASSWORD_I_H */
#include "common.h"
#include "xml-utils.h"
#include "http-utils.h"
+#ifdef EAP_TLS_OPENSSL
+#include "crypto/tls_openssl.h"
+#endif /* EAP_TLS_OPENSSL */
struct http_ctx {
IMPLEMENT_ASN1_FUNCTIONS(LogotypeExtn);
+#ifdef OPENSSL_IS_BORINGSSL
+#define sk_LogotypeInfo_num(st) \
+sk_num(CHECKED_CAST(_STACK *, STACK_OF(LogotypeInfo) *, (st)))
+#define sk_LogotypeInfo_value(st, i) (LogotypeInfo *) \
+sk_value(CHECKED_CAST(_STACK *, const STACK_OF(LogotypeInfo) *, (st)), (i))
+#define sk_LogotypeImage_num(st) \
+sk_num(CHECKED_CAST(_STACK *, STACK_OF(LogotypeImage) *, (st)))
+#define sk_LogotypeImage_value(st, i) (LogotypeImage *) \
+sk_value(CHECKED_CAST(_STACK *, const STACK_OF(LogotypeImage) *, (st)), (i))
+#define sk_LogotypeAudio_num(st) \
+sk_num(CHECKED_CAST(_STACK *, STACK_OF(LogotypeAudio) *, (st)))
+#define sk_LogotypeAudio_value(st, i) (LogotypeAudio *) \
+sk_value(CHECK_CAST(_STACK *, const STACK_OF(LogotypeAudio) *, (st)), (i))
+#define sk_HashAlgAndValue_num(st) \
+sk_num(CHECKED_CAST(_STACK *, STACK_OF(HashAlgAndValue) *, (st)))
+#define sk_HashAlgAndValue_value(st, i) (HashAlgAndValue *) \
+sk_value(CHECKED_CAST(_STACK *, const STACK_OF(HashAlgAndValue) *, (st)), (i))
+#define sk_ASN1_IA5STRING_num(st) \
+sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_IA5STRING) *, (st)))
+#define sk_ASN1_IA5STRING_value(st, i) (ASN1_IA5STRING *) \
+sk_value(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_IA5STRING) *, (st)), (i))
+#else /* OPENSSL_IS_BORINGSSL */
#define sk_LogotypeInfo_num(st) SKM_sk_num(LogotypeInfo, (st))
#define sk_LogotypeInfo_value(st, i) SKM_sk_value(LogotypeInfo, (st), (i))
#define sk_LogotypeImage_num(st) SKM_sk_num(LogotypeImage, (st))
#define sk_HashAlgAndValue_value(st, i) SKM_sk_value(HashAlgAndValue, (st), (i))
#define sk_ASN1_IA5STRING_num(st) SKM_sk_num(ASN1_IA5STRING, (st))
#define sk_ASN1_IA5STRING_value(st, i) SKM_sk_value(ASN1_IA5STRING, (st), (i))
+#endif /* OPENSSL_IS_BORINGSSL */
static void add_logo(struct http_ctx *ctx, struct http_cert *hcert,
} else {
BIO_printf(out, "%*stype: default (1)\n", indent, "");
}
+ val = ASN1_INTEGER_get(info->fileSize);
+ BIO_printf(out, "%*sfileSize: %ld\n", indent, "", val);
val = ASN1_INTEGER_get(info->xSize);
BIO_printf(out, "%*sxSize: %ld\n", indent, "", val);
val = ASN1_INTEGER_get(info->ySize);
BIO_printf(out, "%*sySize: %ld\n", indent, "", val);
if (info->resolution) {
- BIO_printf(out, "%*sresolution\n", indent, "");
- /* TODO */
+ BIO_printf(out, "%*sresolution [%d]\n", indent, "",
+ info->resolution->type);
+ switch (info->resolution->type) {
+ case 0:
+ val = ASN1_INTEGER_get(info->resolution->d.numBits);
+ BIO_printf(out, "%*snumBits: %ld\n", indent, "", val);
+ break;
+ case 1:
+ val = ASN1_INTEGER_get(info->resolution->d.tableSize);
+ BIO_printf(out, "%*stableSize: %ld\n", indent, "", val);
+ break;
+ }
}
if (info->language) {
BIO_printf(out, "%*slanguage: ", indent, "");
if (depth == 0 && preverify_ok && validate_server_cert(ctx, cert) < 0)
return 0;
+#ifdef OPENSSL_IS_BORINGSSL
+ if (depth == 0 && ctx->ocsp != NO_OCSP && preverify_ok) {
+ enum ocsp_result res;
+
+ res = check_ocsp_resp(ssl_ctx, ssl, cert, ctx->peer_issuer,
+ ctx->peer_issuer_issuer);
+ if (res == OCSP_REVOKED) {
+ preverify_ok = 0;
+ wpa_printf(MSG_INFO, "OCSP: certificate revoked");
+ if (err == X509_V_OK)
+ X509_STORE_CTX_set_error(
+ x509_ctx, X509_V_ERR_CERT_REVOKED);
+ } else if (res != OCSP_GOOD && (ctx->ocsp == MANDATORY_OCSP)) {
+ preverify_ok = 0;
+ wpa_printf(MSG_INFO,
+ "OCSP: bad certificate status response");
+ }
+ }
+#endif /* OPENSSL_IS_BORINGSSL */
+
if (!preverify_ok)
ctx->last_err = "TLS validation failed";
wpa_printf(MSG_INFO, "OpenSSL: Could not find current server certificate from OCSP response%s",
(ctx->ocsp == MANDATORY_OCSP) ? "" :
" (OCSP not required)");
+ OCSP_CERTID_free(id);
OCSP_BASICRESP_free(basic);
OCSP_RESPONSE_free(rsp);
if (ctx->ocsp == MANDATORY_OCSP)
ctx->last_err = "Could not find current server certificate from OCSP response";
return (ctx->ocsp == MANDATORY_OCSP) ? 0 : 1;
}
+ OCSP_CERTID_free(id);
if (!OCSP_check_validity(this_update, next_update, 5 * 60, -1)) {
tls_show_errors(__func__, "OpenSSL: OCSP status times invalid");
#ifdef EAP_TLS_OPENSSL
curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, curl_cb_ssl);
curl_easy_setopt(curl, CURLOPT_SSL_CTX_DATA, ctx);
+#ifdef OPENSSL_IS_BORINGSSL
+ /* For now, using the CURLOPT_SSL_VERIFYSTATUS option only
+ * with BoringSSL since the OpenSSL specific callback hack to
+ * enable OCSP is not available with BoringSSL. The OCSP
+ * implementation within libcurl is not sufficient for the
+ * Hotspot 2.0 OSU needs, so cannot use this with OpenSSL.
+ */
+ if (ctx->ocsp != NO_OCSP)
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYSTATUS, 1L);
+#endif /* OPENSSL_IS_BORINGSSL */
#endif /* EAP_TLS_OPENSSL */
} else {
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
--- /dev/null
+/*
+ * 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 */
#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
if (total)
wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
(unsigned long) total);
+ wpa_trace_deinit();
#endif /* WPA_TRACE */
}
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;
}
int os_fdatasync(FILE *stream)
{
if (!fflush(stream)) {
-#ifndef __MACH__
+#ifdef __linux__
return fdatasync(fileno(stream));
-#else /* __MACH__ */
+#else /* !__linux__ */
#ifdef F_FULLFSYNC
/* OS X does not implement fdatasync(). */
return fcntl(fileno(stream), F_FULLFSYNC);
#else /* F_FULLFSYNC */
-#error Neither fdatasync nor F_FULLSYNC are defined
+ return fsync(fileno(stream));
#endif /* F_FULLFSYNC */
-#endif /* __MACH__ */
+#endif /* __linux__ */
}
return -1;
*/
#include "includes.h"
+#ifdef __APPLE__
+#include <PCSC/winscard.h>
+#else
#include <winscard.h>
+#endif
#include "common.h"
#include "pcsc_funcs.h"
struct scard_data {
SCARDCONTEXT ctx;
SCARDHANDLE card;
+#ifdef __APPLE__
+ uint32_t protocol;
+#else
DWORD protocol;
+#endif
sim_types sim_type;
int pin1_required;
};
pos++;
if (pos >= end)
return -1;
- if ((pos + pos[0]) < end)
+ if (pos[0] < end - pos)
end = pos + 1 + pos[0];
pos++;
wpa_hexdump(MSG_DEBUG, "SCARD: file header FSP template",
struct scard_data * scard_init(const char *reader)
{
long ret;
- unsigned long len, pos;
+#ifdef __APPLE__
+ uint32_t len;
+#else
+ unsigned long len;
+#endif
+ unsigned long pos;
struct scard_data *scard;
#ifdef CONFIG_NATIVE_WINDOWS
TCHAR *readers = NULL;
readers = NULL;
wpa_printf(MSG_DEBUG, "SCARD: card=0x%x active_protocol=%lu (%s)",
- (unsigned int) scard->card, scard->protocol,
+ (unsigned int) scard->card, (unsigned long) scard->protocol,
scard->protocol == SCARD_PROTOCOL_T0 ? "T0" : "T1");
ret = SCardBeginTransaction(scard->card);
unsigned char *_recv, size_t *recv_len)
{
long ret;
+#ifdef __APPLE__
+ uint32_t rlen;
+#else
unsigned long rlen;
+#endif
wpa_hexdump_key(MSG_DEBUG, "SCARD: scard_transmit: send",
_send, send_len);
end = buf + len;
/* RES */
- if (pos[0] > RES_MAX_LEN || pos + pos[0] > end) {
+ if (pos[0] > RES_MAX_LEN || pos[0] > end - pos) {
wpa_printf(MSG_DEBUG, "SCARD: Invalid RES");
return -1;
}
wpa_hexdump(MSG_DEBUG, "SCARD: RES", res, *res_len);
/* CK */
- if (pos[0] != CK_LEN || pos + CK_LEN > end) {
+ if (pos[0] != CK_LEN || CK_LEN > end - pos) {
wpa_printf(MSG_DEBUG, "SCARD: Invalid CK");
return -1;
}
wpa_hexdump(MSG_DEBUG, "SCARD: CK", ck, CK_LEN);
/* IK */
- if (pos[0] != IK_LEN || pos + IK_LEN > end) {
+ if (pos[0] != IK_LEN || IK_LEN > end - pos) {
wpa_printf(MSG_DEBUG, "SCARD: Invalid IK");
return -1;
}
\
__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 */
*
* See COPYING for more details.
*/
-#include "radiotap_iter.h"
#include "platform.h"
+#include "radiotap_iter.h"
/* function prototypes and related defs are in radiotap_iter.h */
* new fields does not count.
*/
uint8_t it_pad;
- uint16_t it_len; /* length of the whole
+ le16 it_len; /* length of the whole
* header in bytes, including
* it_version, it_pad,
* it_len, and data fields.
*/
- uint32_t it_present; /* A bitmap telling which
+ le32 it_present; /* A bitmap telling which
* fields are present. Set bit 31
* (0x80000000) to extend the
* bitmap by another 32 bits.
const struct ieee80211_radiotap_namespace *current_namespace;
unsigned char *_arg, *_next_ns_data;
- uint32_t *_next_bitmap;
+ le32 *_next_bitmap;
unsigned char *this_arg;
#ifdef RADIOTAP_SUPPORT_OVERRIDES
}
}
+
+void wpa_trace_deinit(void)
+{
+#ifdef WPA_TRACE_BFD
+ free(syms);
+ syms = NULL;
+#endif /* WPA_TRACE_BFD */
+}
+
#endif /* WPA_TRACE */
#endif /* WPA_TRACE_BFD */
+void wpa_trace_deinit(void);
+
#endif /* TRACE_H */
#include "utils/base64.h"
#include "utils/ip_addr.h"
#include "utils/eloop.h"
+#include "utils/module_tests.h"
struct printf_test_data {
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;
}
{
#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;
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;
+}
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);
/**
static inline const u8 * wpabuf_head_u8(const struct wpabuf *buf)
{
- return (const u8 *)wpabuf_head(buf);
+ return (const u8 *) wpabuf_head(buf);
}
/**
static inline u8 * wpabuf_mhead_u8(struct wpabuf *buf)
{
- return (u8 *)wpabuf_mhead(buf);
+ return (u8 *) wpabuf_mhead(buf);
}
static inline void wpabuf_put_u8(struct wpabuf *buf, u8 data)
{
- u8 *pos = (u8 *)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 = (u8 *)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 = (u8 *)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 = (u8 *)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 = (u8 *)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 = (u8 *)wpabuf_put(buf, 4);
+ u8 *pos = (u8 *) wpabuf_put(buf, 4);
WPA_PUT_BE32(pos, data);
}
xmlDocSetRootElement(doc, n);
xmlDocDumpFormatMemory(doc, &buf, &bufsiz, 0);
xmlFreeDoc(doc);
+ if (!buf)
+ return NULL;
pos = (char *) buf;
if (strncmp(pos, "<?xml", 5) == 0) {
pos = strchr(pos, '>');
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 */
} 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);
/*
* 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.
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_*)
*/
u16 auth_types;
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);
/*
* 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.
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) {
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);
{
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);
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",
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;
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;
}
}
/* 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);
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;
}
-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;
}
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;
}
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;
}
}
* 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;
}
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;
}
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;
}
wpabuf_free(*pubkey);
*pubkey = pub;
- wpabuf_free(*privkey);
+ wpabuf_clear_free(*privkey);
*privkey = priv;
return 0;
}
*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);
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 */
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,
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;
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) {
/*
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;
}
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;
}
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;
}
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;
}
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,
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;
}
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;
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,
#include "utils/includes.h"
#include "utils/common.h"
+#include "utils/module_tests.h"
#include "wps_attr_parse.h"
struct wps_attr_parse_test {
int extra;
};
-const struct wps_attr_parse_test wps_attr_parse_test_cases[] = {
+static const struct wps_attr_parse_test wps_attr_parse_test_cases[] = {
/* Empty message */
{ "", 0, 0 },
/* Truncated attribute header */
/*
* 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.
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);
}
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;
}
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)
}
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)
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) {
}
if (wps_build_ap_settings(wps, plain)) {
- wpabuf_free(plain);
+ wpabuf_clear_free(plain);
wpabuf_free(msg);
return NULL;
}
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;
}
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 */
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)
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;
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;
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;
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 "
}
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;
}
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;
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;
}
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;
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;
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);
}
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;
#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;
};
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 */
};
/*
}
-static int str_starts(const char *str, const char *start)
-{
- return os_strncmp(str, start, os_strlen(start)) == 0;
-}
-
-
/***************************************************************************
* Advertisements.
* These are multicast to the world to tell them we are here.
* would appear to be required (given that we will be closing it!).
*/
static void web_connection_parse_get(struct upnp_wps_device_sm *sm,
- struct http_request *hreq, char *filename)
+ struct http_request *hreq,
+ const char *filename)
{
struct wpabuf *buf; /* output buffer, allocated */
char *put_length_here;
}
+static void wps_upnp_peer_del(struct upnp_wps_peer *peer)
+{
+ dl_list_del(&peer->list);
+ if (peer->wps)
+ wps_deinit(peer->wps);
+ os_free(peer);
+}
+
+
static enum http_reply_code
web_process_get_device_info(struct upnp_wps_device_sm *sm,
struct wpabuf **reply, const char **replyname)
if (!iface || iface->ctx->ap_pin == NULL)
return HTTP_INTERNAL_SERVER_ERROR;
- peer = &iface->peer;
+ peer = os_zalloc(sizeof(*peer));
+ if (!peer)
+ return HTTP_INTERNAL_SERVER_ERROR;
/*
* Request for DeviceInfo, i.e., M1 TLVs. This is a start of WPS
* registration.
*/
- if (peer->wps)
- wps_deinit(peer->wps);
-
os_memset(&cfg, 0, sizeof(cfg));
cfg.wps = iface->wps;
cfg.pin = (u8 *) iface->ctx->ap_pin;
*reply = NULL;
if (*reply == NULL) {
wpa_printf(MSG_INFO, "WPS UPnP: Failed to get DeviceInfo");
+ os_free(peer);
return HTTP_INTERNAL_SERVER_ERROR;
}
+
+ if (dl_list_len(&iface->peers) > 3) {
+ struct upnp_wps_peer *old;
+
+ old = dl_list_first(&iface->peers, struct upnp_wps_peer, list);
+ if (old) {
+ wpa_printf(MSG_DEBUG, "WPS UPnP: Drop oldest active session");
+ wps_upnp_peer_del(old);
+ }
+ }
+ dl_list_add_tail(&iface->peers, &peer->list);
+ /* TODO: Could schedule a timeout to free the entry */
+
*replyname = name;
return HTTP_OK;
}
enum wps_process_res res;
enum wsc_op_code op_code;
struct upnp_wps_device_interface *iface;
+ struct wps_parse_attr attr;
+ struct upnp_wps_peer *tmp, *peer;
iface = dl_list_first(&sm->interfaces,
struct upnp_wps_device_interface, list);
msg = xml_get_base64_item(data, "NewInMessage", &ret);
if (msg == NULL)
return ret;
- res = wps_process_msg(iface->peer.wps, WSC_UPnP, msg);
- if (res == WPS_FAILURE)
+
+ if (wps_parse_msg(msg, &attr)) {
+ wpa_printf(MSG_DEBUG,
+ "WPS UPnP: Could not parse PutMessage - NewInMessage");
+ wpabuf_free(msg);
+ return HTTP_BAD_REQUEST;
+ }
+
+ /* Find a matching active peer session */
+ peer = NULL;
+ dl_list_for_each(tmp, &iface->peers, struct upnp_wps_peer, list) {
+ if (!tmp->wps)
+ continue;
+ if (attr.enrollee_nonce &&
+ os_memcmp(tmp->wps->nonce_e, attr.enrollee_nonce,
+ WPS_NONCE_LEN) != 0)
+ continue; /* Enrollee nonce mismatch */
+ if (attr.msg_type &&
+ *attr.msg_type != WPS_M2 &&
+ *attr.msg_type != WPS_M2D &&
+ attr.registrar_nonce &&
+ os_memcmp(tmp->wps->nonce_r, attr.registrar_nonce,
+ WPS_NONCE_LEN) != 0)
+ continue; /* Registrar nonce mismatch */
+ peer = tmp;
+ break;
+ }
+ if (!peer) {
+ /*
+ Try to use the first entry in case message could work with
+ * it. The actual handler function will reject this, if needed.
+ * This maintains older behavior where only a single peer entry
+ * was supported.
+ */
+ peer = dl_list_first(&iface->peers, struct upnp_wps_peer, list);
+ }
+ if (!peer || !peer->wps) {
+ wpa_printf(MSG_DEBUG, "WPS UPnP: No active peer entry found");
+ wpabuf_free(msg);
+ return HTTP_BAD_REQUEST;
+ }
+
+ res = wps_process_msg(peer->wps, WSC_UPnP, msg);
+ if (res == WPS_FAILURE) {
*reply = NULL;
- else
- *reply = wps_get_msg(iface->peer.wps, &op_code);
+ wpa_printf(MSG_DEBUG, "WPS UPnP: Drop active peer session");
+ wps_upnp_peer_del(peer);
+ } else {
+ *reply = wps_get_msg(peer->wps, &op_code);
+ }
wpabuf_free(msg);
if (*reply == NULL)
return HTTP_INTERNAL_SERVER_ERROR;
server_cert=auth_serv/server.pem
private_key=auth_serv/server.key
ocsp_stapling_response=LOGDIR/ocsp-server-cache.der
+ocsp_stapling_response_multi=LOGDIR/ocsp-multi-server-cache.der
server_id=server.w1.fi
eap_sim_db=unix:/tmp/hlr_auc_gw.sock
dh_file=auth_serv/dh.conf
server_cert=auth_serv/server.pem
private_key=auth_serv/server.key
ocsp_stapling_response=LOGDIR/ocsp-server-cache.der
+ocsp_stapling_response_multi=LOGDIR/ocsp-multi-server-cache.der
server_id=server2.w1.fi
eap_sim_db=unix:/tmp/hlr_auc_gw.sock db=LOGDIR/hostapd.db
dh_file=auth_serv/dh.conf
"osen@example.com" WFA-UNAUTH-TLS
"unauth-tls" UNAUTH-TLS
+"WFA-SimpleConfig-Enrollee-1-0" WSC
+"WFA-SimpleConfig-Enrollee-unexpected" WSC
+
"erp-fast@example.com" FAST
"erp-fast@example.com" GTC "password" [2]
"erp-gpsk@example.com" GPSK "abcdefghijklmnop0123456789abcdef"
"erp-tls@example.com" TLS
"erp-ttls@example.com" TTLS
"erp-ttls@example.com" TTLS-PAP "password" [2]
+"erp-ttls" TTLS
+"erp-ttls" TTLS-PAP "password" [2]
"erp-ikev2@example.com" IKEV2 "password"
"vlan1" PAX 0123456789abcdef0123456789abcdef
radius_accept_attr=65:d:6
radius_accept_attr=81:s:2
+"vlan1b" PAX 0123456789abcdef0123456789abcdef
+radius_accept_attr=56:x:32000001
+
+"vlan1tagged" PAX 0123456789abcdef0123456789abcdef
+radius_accept_attr=56:x:31000001
+
+"vlan12mixed" PAX 0123456789abcdef0123456789abcdef
+radius_accept_attr=56:x:31000001
+radius_accept_attr=64:d:13
+radius_accept_attr=65:d:6
+radius_accept_attr=81:s:2
+
"test-class" PAX 0123456789abcdef0123456789abcdef
radius_accept_attr=25:x:00112233445566778899
"gpsk-user-session-timeout" GPSK "abcdefghijklmnop0123456789abcdef"
radius_accept_attr=27:d:3
+"phase1-user" MSCHAPV2,MD5,GTC "password"
+
"020000000000" MACACL "020000000000"
"020000000100" MACACL "020000000100"
"0232010000000000@peap" PEAP,AKA
"0232010000000000@fast" FAST,AKA
"6555444333222111@both" AKA',AKA
+"peap-ver0" PEAP [ver=0]
+"peap-ver1" PEAP [ver=1]
"0"* AKA
"1"* SIM
"mschap user" TTLS-MSCHAP "password" [2]
"DOMAIN\mschapv2 user" TTLS-MSCHAPV2 hash:8846f7eaee8fb117ad06bdd830b7586c [2]
"hs20-test" TTLS-MSCHAPV2 "password" [2]
+"hs20-test-with-domain@example.com" TTLS-MSCHAPV2 "password" [2]
"utf8-user" TTLS-MSCHAPV2 "secret-åäö-€-password" [2]
"utf8-user-hash" TTLS-MSCHAPV2 hash:bd5844fad2489992da7fe8c5a01559cf [2]
"user" MSCHAPV2,MD5,GTC "password" [2]
+"user@example.com" MSCHAPV2,MD5,GTC "password" [2]
"user2" MSCHAPV2,MD5,GTC "password" [2]
"DOMAIN\user3" MSCHAPV2 "password" [2]
"user-no-passwd" MSCHAPV2,MD5,GTC [2]
radius_accept_attr=64:d:13
radius_accept_attr=65:d:6
radius_accept_attr=81:s:2
+
+"vlan1tagged" PAX 0123456789abcdef0123456789abcdef
+radius_accept_attr=56:x:31000002
copy_extensions = copy
-default_days = 365
+default_days = 3650
default_crl_days= 30
default_md = default
preserve = no
-----BEGIN CERTIFICATE-----
-MIICAjCCAaegAwIBAgIJANry4MnEh6ybMAoGCCqGSM49BAMCMFIxCzAJBgNVBAYT
+MIICAjCCAaegAwIBAgIJAPdTJDJVY8FeMAoGCCqGSM49BAMCMFIxCzAJBgNVBAYT
AkZJMREwDwYDVQQHDAhIZWxzaW5raTEOMAwGA1UECgwFdzEuZmkxIDAeBgNVBAMM
-F1N1aXRlIEIgMTI4LWJpdCBSb290IENBMB4XDTE1MDEyNTExMjk1M1oXDTI1MDEy
-MjExMjk1M1owUjELMAkGA1UEBhMCRkkxETAPBgNVBAcMCEhlbHNpbmtpMQ4wDAYD
+F1N1aXRlIEIgMTI4LWJpdCBSb290IENBMB4XDTE2MDIwMTA5MjUyM1oXDTI2MDEy
+OTA5MjUyM1owUjELMAkGA1UEBhMCRkkxETAPBgNVBAcMCEhlbHNpbmtpMQ4wDAYD
VQQKDAV3MS5maTEgMB4GA1UEAwwXU3VpdGUgQiAxMjgtYml0IFJvb3QgQ0EwWTAT
-BgcqhkjOPQIBBggqhkjOPQMBBwNCAASqUNEASvF83W/PA2xqq/2fhIgZeLdSnnLc
-0yLcjku5WvpLHGy/pLhRsvghtjWjTsgqBqfeW8tq0ywsUdY0ylsNo2YwZDAdBgNV
-HQ4EFgQU/IP6SzTrGV4cfeWF7Mf8IfXodWgwHwYDVR0jBBgwFoAU/IP6SzTrGV4c
-feWF7Mf8IfXodWgwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYw
-CgYIKoZIzj0EAwIDSQAwRgIhAIfEWvUO4+28moKfVL8RXbKKexTZk82UCRL2yi01
-c81AAiEAxBGPZU0vnwxjAaCOhRIH+5X9PDkdLSs25S4ua6BicT8=
+BgcqhkjOPQIBBggqhkjOPQMBBwNCAARwuOrBY7USD4V+MOidWwSkY3S8+4lXWUZ3
++YqRAcVjEPMtokc0zyJAofV0BPgz/yt41gXmvOTALpXfdHpPkeqOo2YwZDAdBgNV
+HQ4EFgQUcyrcCIxm5gVTsimSHN2Km8Amy/gwHwYDVR0jBBgwFoAUcyrcCIxm5gVT
+simSHN2Km8Amy/gwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYw
+CgYIKoZIzj0EAwIDSQAwRgIhAOHO2+N8tgUQKakQcLGR+kB3mKPmjyhu478xmrKg
+wQq9AiEAmnN7YQBgVBk/+zOri1rCCP8DJ3gE+BSUA3cyQGUvtAc=
-----END CERTIFICATE-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
-MHcCAQEEIN/qNiKLsQDpQWumSiRRF6LM7TP7GTwdS8vG7xP8vKz/oAoGCCqGSM49
-AwEHoUQDQgAEvl8WCLIK1vIZbxQZ7yDyKzzgvoxlhl+VwbuQNuzcWTq6QJqdEXbH
-gFohTPzAXxlSyHi45Uz6yWrR/uq2OldcmQ==
+MHcCAQEEIEoiI2GTM68G6vG2zpbM/a5j7e2yBCCWxaNe+nKPT47+oAoGCCqGSM49
+AwEHoUQDQgAEJu1Mahit1ZcoiSaYwew1ugckxpSGVvbrZUVf/IF13kiW+JBMcgrX
+oukSJOw2LVtLLJEf24YHRST8Dw7Kpzr+bQ==
-----END EC PRIVATE KEY-----
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 9573410140069116734 (0x84db95ccdff13b3e)
+ Serial Number: 11095559361558864825 (0x99fb5873d9f9e3b9)
Signature Algorithm: ecdsa-with-SHA256
Issuer: C=FI, L=Helsinki, O=w1.fi, CN=Suite B 128-bit Root CA
Validity
- Not Before: Jan 25 11:29:53 2015 GMT
- Not After : Jan 25 11:29:53 2016 GMT
+ Not Before: Feb 1 09:25:23 2016 GMT
+ Not After : Jan 29 09:25:23 2026 GMT
Subject: C=FI, O=w1.fi, CN=server.w1.fi
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
- 04:be:5f:16:08:b2:0a:d6:f2:19:6f:14:19:ef:20:
- f2:2b:3c:e0:be:8c:65:86:5f:95:c1:bb:90:36:ec:
- dc:59:3a:ba:40:9a:9d:11:76:c7:80:5a:21:4c:fc:
- c0:5f:19:52:c8:78:b8:e5:4c:fa:c9:6a:d1:fe:ea:
- b6:3a:57:5c:99
+ 04:26:ed:4c:6a:18:ad:d5:97:28:89:26:98:c1:ec:
+ 35:ba:07:24:c6:94:86:56:f6:eb:65:45:5f:fc:81:
+ 75:de:48:96:f8:90:4c:72:0a:d7:a2:e9:12:24:ec:
+ 36:2d:5b:4b:2c:91:1f:db:86:07:45:24:fc:0f:0e:
+ ca:a7:3a:fe:6d
ASN1 OID: prime256v1
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Key Identifier:
- 6E:21:26:96:72:29:39:BF:8B:EF:EB:65:CD:E0:4E:97:6F:1A:2C:E5
+ A4:A4:2C:68:89:C6:74:44:B4:BF:9A:BF:5F:D6:02:2C:DC:FE:4F:5A
X509v3 Authority Key Identifier:
- keyid:FC:83:FA:4B:34:EB:19:5E:1C:7D:E5:85:EC:C7:FC:21:F5:E8:75:68
+ keyid:73:2A:DC:08:8C:66:E6:05:53:B2:29:92:1C:DD:8A:9B:C0:26:CB:F8
X509v3 Subject Alternative Name: critical
DNS:server.w1.fi
X509v3 Key Usage:
Digital Signature, Key Encipherment
Signature Algorithm: ecdsa-with-SHA256
- 30:44:02:20:47:b1:5e:57:ae:6c:0b:df:78:11:79:5c:b2:60:
- fd:0c:9c:37:18:19:fe:c1:b6:ca:f6:4f:62:63:13:ff:ff:64:
- 02:20:07:1f:3b:1d:c7:d8:fe:ff:26:0b:68:d0:85:bc:01:15:
- 62:e4:7f:f4:c7:e4:ad:d5:da:40:44:5a:0b:f5:72:9e
+ 30:45:02:20:25:ec:c6:e5:a2:66:e9:3a:f5:fa:b0:4a:dd:24:
+ 89:fa:d0:e3:78:a6:2e:a5:da:39:8b:96:7a:ac:ae:17:1f:ef:
+ 02:21:00:a8:2a:d1:f1:54:73:b9:8e:b9:8b:48:63:54:01:b3:
+ a3:cd:02:05:ba:d0:53:63:0b:d0:9c:f2:13:74:60:7a:a2
-----BEGIN CERTIFICATE-----
-MIICDzCCAbagAwIBAgIJAITblczf8Ts+MAoGCCqGSM49BAMCMFIxCzAJBgNVBAYT
+MIICEDCCAbagAwIBAgIJAJn7WHPZ+eO5MAoGCCqGSM49BAMCMFIxCzAJBgNVBAYT
AkZJMREwDwYDVQQHDAhIZWxzaW5raTEOMAwGA1UECgwFdzEuZmkxIDAeBgNVBAMM
-F1N1aXRlIEIgMTI4LWJpdCBSb290IENBMB4XDTE1MDEyNTExMjk1M1oXDTE2MDEy
-NTExMjk1M1owNDELMAkGA1UEBhMCRkkxDjAMBgNVBAoMBXcxLmZpMRUwEwYDVQQD
-DAxzZXJ2ZXIudzEuZmkwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS+XxYIsgrW
-8hlvFBnvIPIrPOC+jGWGX5XBu5A27NxZOrpAmp0RdseAWiFM/MBfGVLIeLjlTPrJ
-atH+6rY6V1yZo4GSMIGPMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFG4hJpZyKTm/
-i+/rZc3gTpdvGizlMB8GA1UdIwQYMBaAFPyD+ks06xleHH3lhezH/CH16HVoMBoG
+F1N1aXRlIEIgMTI4LWJpdCBSb290IENBMB4XDTE2MDIwMTA5MjUyM1oXDTI2MDEy
+OTA5MjUyM1owNDELMAkGA1UEBhMCRkkxDjAMBgNVBAoMBXcxLmZpMRUwEwYDVQQD
+DAxzZXJ2ZXIudzEuZmkwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQm7UxqGK3V
+lyiJJpjB7DW6ByTGlIZW9utlRV/8gXXeSJb4kExyCtei6RIk7DYtW0sskR/bhgdF
+JPwPDsqnOv5to4GSMIGPMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFKSkLGiJxnRE
+tL+av1/WAizc/k9aMB8GA1UdIwQYMBaAFHMq3AiMZuYFU7IpkhzdipvAJsv4MBoG
A1UdEQEB/wQQMA6CDHNlcnZlci53MS5maTAWBgNVHSUBAf8EDDAKBggrBgEFBQcD
-ATALBgNVHQ8EBAMCBaAwCgYIKoZIzj0EAwIDRwAwRAIgR7FeV65sC994EXlcsmD9
-DJw3GBn+wbbK9k9iYxP//2QCIAcfOx3H2P7/Jgto0IW8ARVi5H/0x+St1dpARFoL
-9XKe
+ATALBgNVHQ8EBAMCBaAwCgYIKoZIzj0EAwIDSAAwRQIgJezG5aJm6Tr1+rBK3SSJ
++tDjeKYupdo5i5Z6rK4XH+8CIQCoKtHxVHO5jrmLSGNUAbOjzQIFutBTYwvQnPIT
+dGB6og==
-----END CERTIFICATE-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
-MHcCAQEEIL52ZfaYm8GAzhot94BCQriTmQEq2+JPkS+HCwUpLuwaoAoGCCqGSM49
-AwEHoUQDQgAEnE2sSN8ZOateUoi3Ao0VewSH+1ceTf+NkiJpoymO6U6q0CSlG2bp
-dZyBk+6UIOD9WiCi2tN+QGbvPnPrlLfBOg==
+MHcCAQEEINKa/lt6n2rVp/6cLl65e8GR0vY0WKDfpBGltnggadz3oAoGCCqGSM49
+AwEHoUQDQgAEDbAoh2fby/hkxmF9Hm8fyzBHCpaDzFuAyG+SYmTBqpccxTXXfSNJ
+eYQXMoPTm14BXWgiTf7U9/C3FHolI5oBNQ==
-----END EC PRIVATE KEY-----
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 9573410140069116735 (0x84db95ccdff13b3f)
+ Serial Number: 11095559361558864826 (0x99fb5873d9f9e3ba)
Signature Algorithm: ecdsa-with-SHA256
Issuer: C=FI, L=Helsinki, O=w1.fi, CN=Suite B 128-bit Root CA
Validity
- Not Before: Jan 25 11:29:53 2015 GMT
- Not After : Jan 25 11:29:53 2016 GMT
+ Not Before: Feb 1 09:25:23 2016 GMT
+ Not After : Jan 29 09:25:23 2026 GMT
Subject: C=FI, O=w1.fi, CN=user
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
- 04:9c:4d:ac:48:df:19:39:ab:5e:52:88:b7:02:8d:
- 15:7b:04:87:fb:57:1e:4d:ff:8d:92:22:69:a3:29:
- 8e:e9:4e:aa:d0:24:a5:1b:66:e9:75:9c:81:93:ee:
- 94:20:e0:fd:5a:20:a2:da:d3:7e:40:66:ef:3e:73:
- eb:94:b7:c1:3a
+ 04:0d:b0:28:87:67:db:cb:f8:64:c6:61:7d:1e:6f:
+ 1f:cb:30:47:0a:96:83:cc:5b:80:c8:6f:92:62:64:
+ c1:aa:97:1c:c5:35:d7:7d:23:49:79:84:17:32:83:
+ d3:9b:5e:01:5d:68:22:4d:fe:d4:f7:f0:b7:14:7a:
+ 25:23:9a:01:35
ASN1 OID: prime256v1
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
X509v3 Subject Key Identifier:
- 89:28:76:9A:42:DB:B6:F8:36:97:63:8F:7D:0A:EA:0B:FE:66:2B:CD
+ 0E:0F:F9:64:AC:F9:DB:7C:45:22:9A:DF:E0:DB:1E:25:9D:8F:4D:C3
X509v3 Authority Key Identifier:
- keyid:FC:83:FA:4B:34:EB:19:5E:1C:7D:E5:85:EC:C7:FC:21:F5:E8:75:68
+ keyid:73:2A:DC:08:8C:66:E6:05:53:B2:29:92:1C:DD:8A:9B:C0:26:CB:F8
X509v3 Subject Alternative Name:
email:user@w1.fi
X509v3 Key Usage:
Digital Signature, Key Encipherment
Signature Algorithm: ecdsa-with-SHA256
- 30:45:02:20:26:84:14:f6:50:ac:ed:da:88:27:6d:18:d5:b3:
- 2c:c8:59:ea:2a:c3:ae:69:03:79:0d:66:5e:5f:a5:52:27:92:
- 02:21:00:db:8d:fd:58:e5:22:9b:17:32:57:34:e9:2e:30:da:
- 1d:77:4c:15:18:9b:7d:e4:5d:bc:64:cd:21:ff:57:df:16
+ 30:44:02:20:12:a1:d9:30:43:fb:12:3d:67:72:a2:12:24:7c:
+ cb:1e:ce:f7:e6:fe:b6:79:b4:af:d8:85:72:49:2d:e9:de:01:
+ 02:20:18:f3:6a:65:5d:c0:04:df:28:5a:44:b1:5f:75:25:eb:
+ a8:56:e9:5d:35:3c:9e:8d:63:cc:47:7f:22:a1:c0:27
-----BEGIN CERTIFICATE-----
-MIIB/TCCAaOgAwIBAgIJAITblczf8Ts/MAoGCCqGSM49BAMCMFIxCzAJBgNVBAYT
+MIIB/DCCAaOgAwIBAgIJAJn7WHPZ+eO6MAoGCCqGSM49BAMCMFIxCzAJBgNVBAYT
AkZJMREwDwYDVQQHDAhIZWxzaW5raTEOMAwGA1UECgwFdzEuZmkxIDAeBgNVBAMM
-F1N1aXRlIEIgMTI4LWJpdCBSb290IENBMB4XDTE1MDEyNTExMjk1M1oXDTE2MDEy
-NTExMjk1M1owLDELMAkGA1UEBhMCRkkxDjAMBgNVBAoMBXcxLmZpMQ0wCwYDVQQD
-DAR1c2VyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnE2sSN8ZOateUoi3Ao0V
-ewSH+1ceTf+NkiJpoymO6U6q0CSlG2bpdZyBk+6UIOD9WiCi2tN+QGbvPnPrlLfB
-OqOBhzCBhDAJBgNVHRMEAjAAMB0GA1UdDgQWBBSJKHaaQtu2+DaXY499CuoL/mYr
-zTAfBgNVHSMEGDAWgBT8g/pLNOsZXhx95YXsx/wh9eh1aDAVBgNVHREEDjAMgQp1
+F1N1aXRlIEIgMTI4LWJpdCBSb290IENBMB4XDTE2MDIwMTA5MjUyM1oXDTI2MDEy
+OTA5MjUyM1owLDELMAkGA1UEBhMCRkkxDjAMBgNVBAoMBXcxLmZpMQ0wCwYDVQQD
+DAR1c2VyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEDbAoh2fby/hkxmF9Hm8f
+yzBHCpaDzFuAyG+SYmTBqpccxTXXfSNJeYQXMoPTm14BXWgiTf7U9/C3FHolI5oB
+NaOBhzCBhDAJBgNVHRMEAjAAMB0GA1UdDgQWBBQOD/lkrPnbfEUimt/g2x4lnY9N
+wzAfBgNVHSMEGDAWgBRzKtwIjGbmBVOyKZIc3YqbwCbL+DAVBgNVHREEDjAMgQp1
c2VyQHcxLmZpMBMGA1UdJQQMMAoGCCsGAQUFBwMCMAsGA1UdDwQEAwIFoDAKBggq
-hkjOPQQDAgNIADBFAiAmhBT2UKzt2ognbRjVsyzIWeoqw65pA3kNZl5fpVInkgIh
-ANuN/VjlIpsXMlc06S4w2h13TBUYm33kXbxkzSH/V98W
+hkjOPQQDAgNHADBEAiASodkwQ/sSPWdyohIkfMsezvfm/rZ5tK/YhXJJLeneAQIg
+GPNqZV3ABN8oWkSxX3Ul66hW6V01PJ6NY8xHfyKhwCc=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
-MIICPTCCAcSgAwIBAgIJAL63h7lu0KZpMAoGCCqGSM49BAMDMFIxCzAJBgNVBAYT
+MIICPjCCAcSgAwIBAgIJAIEUIb9N+rpkMAoGCCqGSM49BAMDMFIxCzAJBgNVBAYT
AkZJMREwDwYDVQQHDAhIZWxzaW5raTEOMAwGA1UECgwFdzEuZmkxIDAeBgNVBAMM
-F1N1aXRlIEIgMTkyLWJpdCBSb290IENBMB4XDTE1MDEyNTExMzIwM1oXDTI1MDEy
-MjExMzIwM1owUjELMAkGA1UEBhMCRkkxETAPBgNVBAcMCEhlbHNpbmtpMQ4wDAYD
+F1N1aXRlIEIgMTkyLWJpdCBSb290IENBMB4XDTE2MDIwMTA5MjYyNFoXDTI2MDEy
+OTA5MjYyNFowUjELMAkGA1UEBhMCRkkxETAPBgNVBAcMCEhlbHNpbmtpMQ4wDAYD
VQQKDAV3MS5maTEgMB4GA1UEAwwXU3VpdGUgQiAxOTItYml0IFJvb3QgQ0EwdjAQ
-BgcqhkjOPQIBBgUrgQQAIgNiAAQjdOMC9bqcDR9/SaOhxNbmQLQTGZfhtmoxHkJL
-5GG3bwW5hYA2jYHWU84H+mR6om6fg78G+IxjLly2OWiByYUeWDcsYqLGj3UHHaVv
-rIitaRPyg3dExemnmK3zjgXnoaajZjBkMB0GA1UdDgQWBBSuBbynInvH0vn8IKZc
-MbtBTo9svTAfBgNVHSMEGDAWgBSuBbynInvH0vn8IKZcMbtBTo9svTASBgNVHRMB
-Af8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjBZ
-vEbGRDQNvzAY3nfYrsrE2Dd11smT6zv0mIvDeQCktbISGpStRBQjAaFjcCyjDEkC
-MH7ywcqJe+mpWDt5xFJvB52iZ7rX7rO0OX0qmjI38PC0IOo7euJdfcC1gHdSoAW3
-bA==
+BgcqhkjOPQIBBgUrgQQAIgNiAARWEuSpvRL6glbrbPMhDEcvHpQCirI4GtFDFYUE
+YIDqRObNZkeM4A9ygH3HUUmdm3SLHVxb+2nIVfPY3jyxwfOZGiL6ASomy1WwGY0A
+AaXU61MCiJBny1VTsjR7Dw+VcRejZjBkMB0GA1UdDgQWBBS4l8m+YxKr9qCMtl77
+l24QjtxI9TAfBgNVHSMEGDAWgBS4l8m+YxKr9qCMtl77l24QjtxI9TASBgNVHRMB
+Af8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjEA
+v+QeMLDKAY3+9dbdzPit9WCg7erYxa0LsV6ZTr4wIYwUIkybksD1Bwlq7Sw/lVpO
+AjBy4q3wJbj6unHQq9VsCKpHWiTi/WeKRo8X0djScKsN7R92A3vGgdhVEAXP0vTl
+Rn0=
-----END CERTIFICATE-----
BgUrgQQAIg==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
-MIGkAgEBBDCjaz/zVDXqNO/XprtliomKOC6QjbBFgsF2YwUAtKB5ukL4miVGNyCu
-jIlq9eUD1x6gBwYFK4EEACKhZANiAARWq1ut1b6ctOFBkEOjULL3VjJFP15g0gk+
-sBTMBogU5WRN7Qod/jfem5k4O7FKYZNAarDFMh2yDMXZvRooiNyL0AH2wk0qzN5u
-n02JOt9Q76TVYflE91C5DTxjgLOgxBw=
+MIGkAgEBBDAgwG8tK5eYT4AX09cjhztI1oSnO7iEVf8n6UdbY41gmuU+ce+HPfpt
+mRFxdKSU29CgBwYFK4EEACKhZANiAAS4CCNfatEOzJswkLMlEn+bPMUEYQEYQwad
+uiJ3hJHkHxKnjjamvn+OCHxZwX0I2ci19y+cxgCIAKHRI2C/iijvr12ZcOkVEysf
+PODhGzHDloYyEfLcPSJ9hTk1ZIvyRSU=
-----END EC PRIVATE KEY-----
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 9347590364512421238 (0x81b94fe92ea08576)
+ Serial Number: 11652367451091730033 (0xa1b58675baa57e71)
Signature Algorithm: ecdsa-with-SHA384
Issuer: C=FI, L=Helsinki, O=w1.fi, CN=Suite B 192-bit Root CA
Validity
- Not Before: Jan 25 11:32:03 2015 GMT
- Not After : Jan 25 11:32:03 2016 GMT
+ Not Before: Feb 1 09:26:24 2016 GMT
+ Not After : Jan 29 09:26:24 2026 GMT
Subject: C=FI, O=w1.fi, CN=server.w1.fi
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (384 bit)
pub:
- 04:56:ab:5b:ad:d5:be:9c:b4:e1:41:90:43:a3:50:
- b2:f7:56:32:45:3f:5e:60:d2:09:3e:b0:14:cc:06:
- 88:14:e5:64:4d:ed:0a:1d:fe:37:de:9b:99:38:3b:
- b1:4a:61:93:40:6a:b0:c5:32:1d:b2:0c:c5:d9:bd:
- 1a:28:88:dc:8b:d0:01:f6:c2:4d:2a:cc:de:6e:9f:
- 4d:89:3a:df:50:ef:a4:d5:61:f9:44:f7:50:b9:0d:
- 3c:63:80:b3:a0:c4:1c
+ 04:b8:08:23:5f:6a:d1:0e:cc:9b:30:90:b3:25:12:
+ 7f:9b:3c:c5:04:61:01:18:43:06:9d:ba:22:77:84:
+ 91:e4:1f:12:a7:8e:36:a6:be:7f:8e:08:7c:59:c1:
+ 7d:08:d9:c8:b5:f7:2f:9c:c6:00:88:00:a1:d1:23:
+ 60:bf:8a:28:ef:af:5d:99:70:e9:15:13:2b:1f:3c:
+ e0:e1:1b:31:c3:96:86:32:11:f2:dc:3d:22:7d:85:
+ 39:35:64:8b:f2:45:25
ASN1 OID: secp384r1
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Key Identifier:
- 19:D7:57:D0:3B:91:84:A4:AF:93:03:32:3C:AB:C4:F9:A7:B0:27:19
+ EA:4A:EB:D2:AD:05:FC:FD:5F:A0:CA:8A:53:3B:4D:ED:F5:6B:EF:75
X509v3 Authority Key Identifier:
- keyid:AE:05:BC:A7:22:7B:C7:D2:F9:FC:20:A6:5C:31:BB:41:4E:8F:6C:BD
+ keyid:B8:97:C9:BE:63:12:AB:F6:A0:8C:B6:5E:FB:97:6E:10:8E:DC:48:F5
X509v3 Subject Alternative Name: critical
DNS:server.w1.fi
X509v3 Key Usage:
Digital Signature, Key Encipherment
Signature Algorithm: ecdsa-with-SHA384
- 30:65:02:30:79:68:37:af:eb:46:e8:77:35:13:77:d5:db:eb:
- f9:75:40:cd:d4:3d:0a:03:ec:67:a0:22:fe:65:f5:d7:ca:53:
- 4a:85:f5:14:4b:41:f9:b9:98:a6:85:8b:ac:e0:c8:6c:02:31:
- 00:83:12:02:be:93:2b:c2:00:74:ec:cb:fc:5a:8c:a6:5e:52:
- ee:20:76:3d:73:2b:fb:fe:60:4c:52:f3:bc:1e:4c:e8:f9:ea:
- f6:e2:f6:ca:c6:a8:3b:2d:9a:17:eb:4d:0a
+ 30:65:02:30:1f:26:d2:79:e7:54:59:1a:b8:3b:92:26:05:1d:
+ f7:57:43:9d:8e:01:3d:57:ca:54:e1:9b:2e:ec:3a:32:a0:0d:
+ 8b:7c:70:c2:27:d2:31:8b:39:5c:64:6d:81:dd:14:56:02:31:
+ 00:f1:ac:58:25:9a:9e:cd:1c:fa:76:9d:da:1a:6b:28:b5:43:
+ 15:4e:c7:aa:4d:26:4d:44:26:23:86:a8:5f:6e:f5:42:6d:26:
+ 37:99:1d:70:b9:8e:96:4d:69:99:a9:6f:c6
-----BEGIN CERTIFICATE-----
-MIICTTCCAdOgAwIBAgIJAIG5T+kuoIV2MAoGCCqGSM49BAMDMFIxCzAJBgNVBAYT
+MIICTTCCAdOgAwIBAgIJAKG1hnW6pX5xMAoGCCqGSM49BAMDMFIxCzAJBgNVBAYT
AkZJMREwDwYDVQQHDAhIZWxzaW5raTEOMAwGA1UECgwFdzEuZmkxIDAeBgNVBAMM
-F1N1aXRlIEIgMTkyLWJpdCBSb290IENBMB4XDTE1MDEyNTExMzIwM1oXDTE2MDEy
-NTExMzIwM1owNDELMAkGA1UEBhMCRkkxDjAMBgNVBAoMBXcxLmZpMRUwEwYDVQQD
-DAxzZXJ2ZXIudzEuZmkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARWq1ut1b6ctOFB
-kEOjULL3VjJFP15g0gk+sBTMBogU5WRN7Qod/jfem5k4O7FKYZNAarDFMh2yDMXZ
-vRooiNyL0AH2wk0qzN5un02JOt9Q76TVYflE91C5DTxjgLOgxByjgZIwgY8wDAYD
-VR0TAQH/BAIwADAdBgNVHQ4EFgQUGddX0DuRhKSvkwMyPKvE+aewJxkwHwYDVR0j
-BBgwFoAUrgW8pyJ7x9L5/CCmXDG7QU6PbL0wGgYDVR0RAQH/BBAwDoIMc2VydmVy
+F1N1aXRlIEIgMTkyLWJpdCBSb290IENBMB4XDTE2MDIwMTA5MjYyNFoXDTI2MDEy
+OTA5MjYyNFowNDELMAkGA1UEBhMCRkkxDjAMBgNVBAoMBXcxLmZpMRUwEwYDVQQD
+DAxzZXJ2ZXIudzEuZmkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAS4CCNfatEOzJsw
+kLMlEn+bPMUEYQEYQwaduiJ3hJHkHxKnjjamvn+OCHxZwX0I2ci19y+cxgCIAKHR
+I2C/iijvr12ZcOkVEysfPODhGzHDloYyEfLcPSJ9hTk1ZIvyRSWjgZIwgY8wDAYD
+VR0TAQH/BAIwADAdBgNVHQ4EFgQU6krr0q0F/P1foMqKUztN7fVr73UwHwYDVR0j
+BBgwFoAUuJfJvmMSq/agjLZe+5duEI7cSPUwGgYDVR0RAQH/BBAwDoIMc2VydmVy
LncxLmZpMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMBMAsGA1UdDwQEAwIFoDAKBggq
-hkjOPQQDAwNoADBlAjB5aDev60bodzUTd9Xb6/l1QM3UPQoD7GegIv5l9dfKU0qF
-9RRLQfm5mKaFi6zgyGwCMQCDEgK+kyvCAHTsy/xajKZeUu4gdj1zK/v+YExS87we
-TOj56vbi9srGqDstmhfrTQo=
+hkjOPQQDAwNoADBlAjAfJtJ551RZGrg7kiYFHfdXQ52OAT1XylThmy7sOjKgDYt8
+cMIn0jGLOVxkbYHdFFYCMQDxrFglmp7NHPp2ndoaayi1QxVOx6pNJk1EJiOGqF9u
+9UJtJjeZHXC5jpZNaZmpb8Y=
-----END CERTIFICATE-----
BgUrgQQAIg==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
-MIGkAgEBBDB7tpaHBuZZG+MVYjRVpZvZvZxxFOu/reH2Ms3DiBH5DHW7dLP7T4Gs
-X+yw8bQZwCqgBwYFK4EEACKhZANiAATJYVk5woo/LAFd+znRAoMOClGXtfO2yZlp
-3n6jYUsG48W03XOlYd2/aCJVtGp6SwRVxumfYT4TejEj/Ky44vOlmQ9pasNfMYYN
-kpHcAWJ8sV7mP7LM9YVksksfhon91+E=
+MIGkAgEBBDCkY69v8ff6oUI3wxJYeJdT500cYU9SE7LOLByjFyW5kKh0wfNI+PTj
+QCboPDTNgy6gBwYFK4EEACKhZANiAATuB6iYrTnzUXstmwJhnMBpU3SB6Hwa92ne
+S3VaDG2HGjdfBCV5JUHXt4o4JTtknjum/cKR/99xQ6pvBemWQjEcyeAyK18zIQrP
+Kce5MCGEcJ8c5GwKVwVYlBPzr85IcBg=
-----END EC PRIVATE KEY-----
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 9347590364512421239 (0x81b94fe92ea08577)
+ Serial Number: 11652367451091730034 (0xa1b58675baa57e72)
Signature Algorithm: ecdsa-with-SHA384
Issuer: C=FI, L=Helsinki, O=w1.fi, CN=Suite B 192-bit Root CA
Validity
- Not Before: Jan 25 11:32:03 2015 GMT
- Not After : Jan 25 11:32:03 2016 GMT
+ Not Before: Feb 1 09:26:24 2016 GMT
+ Not After : Jan 29 09:26:24 2026 GMT
Subject: C=FI, O=w1.fi, CN=user
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (384 bit)
pub:
- 04:c9:61:59:39:c2:8a:3f:2c:01:5d:fb:39:d1:02:
- 83:0e:0a:51:97:b5:f3:b6:c9:99:69:de:7e:a3:61:
- 4b:06:e3:c5:b4:dd:73:a5:61:dd:bf:68:22:55:b4:
- 6a:7a:4b:04:55:c6:e9:9f:61:3e:13:7a:31:23:fc:
- ac:b8:e2:f3:a5:99:0f:69:6a:c3:5f:31:86:0d:92:
- 91:dc:01:62:7c:b1:5e:e6:3f:b2:cc:f5:85:64:b2:
- 4b:1f:86:89:fd:d7:e1
+ 04:ee:07:a8:98:ad:39:f3:51:7b:2d:9b:02:61:9c:
+ c0:69:53:74:81:e8:7c:1a:f7:69:de:4b:75:5a:0c:
+ 6d:87:1a:37:5f:04:25:79:25:41:d7:b7:8a:38:25:
+ 3b:64:9e:3b:a6:fd:c2:91:ff:df:71:43:aa:6f:05:
+ e9:96:42:31:1c:c9:e0:32:2b:5f:33:21:0a:cf:29:
+ c7:b9:30:21:84:70:9f:1c:e4:6c:0a:57:05:58:94:
+ 13:f3:af:ce:48:70:18
ASN1 OID: secp384r1
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
X509v3 Subject Key Identifier:
- 75:EA:7B:CE:8A:99:D2:E7:77:B4:3B:80:68:59:E9:B6:88:B2:FA:F6
+ 63:19:63:3E:D9:CB:7F:DC:C9:E0:DD:4D:75:A4:34:63:18:16:C3:EF
X509v3 Authority Key Identifier:
- keyid:AE:05:BC:A7:22:7B:C7:D2:F9:FC:20:A6:5C:31:BB:41:4E:8F:6C:BD
+ keyid:B8:97:C9:BE:63:12:AB:F6:A0:8C:B6:5E:FB:97:6E:10:8E:DC:48:F5
X509v3 Subject Alternative Name:
email:user@w1.fi
X509v3 Key Usage:
Digital Signature, Key Encipherment
Signature Algorithm: ecdsa-with-SHA384
- 30:65:02:31:00:c2:b7:35:4e:5e:d1:da:7f:35:a0:ac:54:92:
- 18:08:0d:9c:86:e9:4e:cf:3a:09:48:23:eb:4d:56:77:e5:d0:
- e7:b0:55:b3:0e:91:2d:f8:3e:1c:4e:0d:b7:32:dc:11:1b:02:
- 30:49:c2:6b:63:39:3c:4b:d9:e9:8d:b9:ce:6e:8e:9f:88:43:
- 03:e0:5f:7e:75:44:12:66:f8:c6:ae:8e:f1:da:10:02:36:8c:
- 7b:a2:89:a0:05:3b:c6:39:d6:e1:7a:b7:85
+ 30:66:02:31:00:91:55:b8:e4:26:b6:19:10:b3:f5:47:fb:a0:
+ dc:6a:a1:1b:c6:53:28:be:bd:9e:94:48:34:45:cc:87:41:64:
+ 14:2d:d0:bb:dd:75:0a:c3:47:3a:05:7f:35:5c:1c:be:51:02:
+ 31:00:ce:4e:8d:cb:05:73:0d:f5:03:74:c5:b1:11:14:a8:0b:
+ e7:d8:26:36:bc:3b:90:60:5a:0e:bf:06:df:27:a3:59:79:52:
+ 7b:8e:7c:06:57:70:46:4c:dd:6f:dc:13:95:94
-----BEGIN CERTIFICATE-----
-MIICOjCCAcCgAwIBAgIJAIG5T+kuoIV3MAoGCCqGSM49BAMDMFIxCzAJBgNVBAYT
+MIICOzCCAcCgAwIBAgIJAKG1hnW6pX5yMAoGCCqGSM49BAMDMFIxCzAJBgNVBAYT
AkZJMREwDwYDVQQHDAhIZWxzaW5raTEOMAwGA1UECgwFdzEuZmkxIDAeBgNVBAMM
-F1N1aXRlIEIgMTkyLWJpdCBSb290IENBMB4XDTE1MDEyNTExMzIwM1oXDTE2MDEy
-NTExMzIwM1owLDELMAkGA1UEBhMCRkkxDjAMBgNVBAoMBXcxLmZpMQ0wCwYDVQQD
-DAR1c2VyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEyWFZOcKKPywBXfs50QKDDgpR
-l7XztsmZad5+o2FLBuPFtN1zpWHdv2giVbRqeksEVcbpn2E+E3oxI/ysuOLzpZkP
-aWrDXzGGDZKR3AFifLFe5j+yzPWFZLJLH4aJ/dfho4GHMIGEMAkGA1UdEwQCMAAw
-HQYDVR0OBBYEFHXqe86KmdLnd7Q7gGhZ6baIsvr2MB8GA1UdIwQYMBaAFK4FvKci
-e8fS+fwgplwxu0FOj2y9MBUGA1UdEQQOMAyBCnVzZXJAdzEuZmkwEwYDVR0lBAww
-CgYIKwYBBQUHAwIwCwYDVR0PBAQDAgWgMAoGCCqGSM49BAMDA2gAMGUCMQDCtzVO
-XtHafzWgrFSSGAgNnIbpTs86CUgj601Wd+XQ57BVsw6RLfg+HE4NtzLcERsCMEnC
-a2M5PEvZ6Y25zm6On4hDA+BffnVEEmb4xq6O8doQAjaMe6KJoAU7xjnW4Xq3hQ==
+F1N1aXRlIEIgMTkyLWJpdCBSb290IENBMB4XDTE2MDIwMTA5MjYyNFoXDTI2MDEy
+OTA5MjYyNFowLDELMAkGA1UEBhMCRkkxDjAMBgNVBAoMBXcxLmZpMQ0wCwYDVQQD
+DAR1c2VyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE7geomK0581F7LZsCYZzAaVN0
+geh8Gvdp3kt1Wgxthxo3XwQleSVB17eKOCU7ZJ47pv3Ckf/fcUOqbwXplkIxHMng
+MitfMyEKzynHuTAhhHCfHORsClcFWJQT86/OSHAYo4GHMIGEMAkGA1UdEwQCMAAw
+HQYDVR0OBBYEFGMZYz7Zy3/cyeDdTXWkNGMYFsPvMB8GA1UdIwQYMBaAFLiXyb5j
+Eqv2oIy2XvuXbhCO3Ej1MBUGA1UdEQQOMAyBCnVzZXJAdzEuZmkwEwYDVR0lBAww
+CgYIKwYBBQUHAwIwCwYDVR0PBAQDAgWgMAoGCCqGSM49BAMDA2kAMGYCMQCRVbjk
+JrYZELP1R/ug3GqhG8ZTKL69npRINEXMh0FkFC3Qu911CsNHOgV/NVwcvlECMQDO
+To3LBXMN9QN0xbERFKgL59gmNrw7kGBaDr8G3yejWXlSe458BldwRkzdb9wTlZQ=
-----END CERTIFICATE-----
# IMSI Ki OPc AMF SQN
232010000000000 90dca4eda45b53cf0f12d7c9c3bc6a89 cb9cccc4b9258e6dca4760379fb82581 61df 000000000000
+# Modified version of the previous to allow testing with replaced SIM.
+232010000000009 a0dca4eda45b53cf0f12d7c9c3bc6a89 cb9cccc4b9258e6dca4760379fb82581 61df 000000000000
+
# These values are from Test Set 19 which has the AMF separation bit set to 1
# and as such, is suitable for EAP-AKA' test.
555444333222111 5122250214c33e723a5dd523fc145fc0 981d464c7c52eb6e5036234984ad0bcf c3ab 16f3b3f70fc1
V 150215083008Z D8D3E3A6CBE3CCCB unknown /C=FI/O=w1.fi/CN=server5.w1.fi
V 150228224144Z D8D3E3A6CBE3CCCC unknown /C=FI/O=w1.fi/CN=server6.w1.fi
V 160111185024Z D8D3E3A6CBE3CCCD unknown /C=FI/O=w1.fi/CN=ocsp.w1.fi
-R 150929211122Z 160111185024Z D8D3E3A6CBE3CCD0 unknown /C=FI/O=w1.fi/CN=server.w1.fi
+R 150929211122Z 160111185024Z D8D3E3A6CBE3CCE2 unknown /C=FI/O=w1.fi/CN=server.w1.fi
R 150929211300Z 160111185024Z D8D3E3A6CBE3CCD1 unknown /C=FI/O=w1.fi/CN=Test User
V 150215083008Z D8D3E3A6CBE3CCCB unknown /C=FI/O=w1.fi/CN=server5.w1.fi
V 150228224144Z D8D3E3A6CBE3CCCC unknown /C=FI/O=w1.fi/CN=server6.w1.fi
V 160111185024Z D8D3E3A6CBE3CCCD unknown /C=FI/O=w1.fi/CN=ocsp.w1.fi
-V 150929211122Z D8D3E3A6CBE3CCD0 unknown /C=FI/O=w1.fi/CN=server.w1.fi
+V 170930181357Z D8D3E3A6CBE3CCE9 unknown /C=FI/O=w1.fi/CN=server.w1.fi
V 150929211300Z D8D3E3A6CBE3CCD1 unknown /C=FI/O=w1.fi/CN=Test User
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 15624081837803162829 (0xd8d3e3a6cbe3cccd)
+ Serial Number: 15624081837803162831 (0xd8d3e3a6cbe3cccf)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=FI, O=w1.fi, CN=Root CA
Validity
- Not Before: Jan 11 18:50:24 2015 GMT
- Not After : Jan 11 18:50:24 2016 GMT
+ Not Before: Jan 12 22:37:50 2016 GMT
+ Not After : Jan 11 22:37:50 2021 GMT
Subject: C=FI, O=w1.fi, CN=ocsp.w1.fi
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
X509v3 Extended Key Usage:
OCSP Signing
Signature Algorithm: sha256WithRSAEncryption
- 41:42:b6:70:4a:70:1f:ad:d9:25:f7:02:94:bd:91:b7:69:ad:
- 31:59:c6:2a:4e:5e:4a:ed:5d:c1:24:09:98:94:15:42:86:2c:
- b2:9d:62:7a:e0:ec:60:39:47:93:c9:c7:61:01:b5:2c:00:53:
- 86:6e:66:99:ee:b3:57:5d:fb:83:6b:d3:77:26:0c:c7:2d:16:
- ea:84:69:59:b7:a8:de:35:61:0b:7a:f3:62:1e:1a:94:91:c4:
- bd:85:4a:63:10:09:11:88:75:c9:f5:57:84:9a:ef:d1:78:29:
- 5e:76:fc:33:76:84:b2:b5:f6:88:cc:fb:f9:cf:9f:b4:88:29:
- 3c:9d
+ ae:47:b6:23:18:58:9a:d4:26:63:ad:41:c1:5d:3e:34:78:c3:
+ 80:29:f6:10:2b:95:3b:dc:ef:f2:b3:b8:4b:23:07:a0:11:e5:
+ 5c:b6:4e:7c:6d:d4:62:a2:ae:0f:fd:25:ef:bf:9a:1a:4a:d5:
+ 21:c1:9a:0f:57:e6:da:96:b5:e6:d9:02:1e:5b:98:e3:35:8b:
+ b6:0d:24:22:d3:35:a4:20:e7:42:ea:ba:11:72:a0:64:84:73:
+ 3c:ce:28:5b:b0:24:53:e9:47:a4:ee:07:85:b2:7a:ec:95:8f:
+ 5b:4b:02:b7:c9:3b:2f:e3:30:57:f9:0c:df:f8:a9:7c:4d:b5:
+ 0f:01
-----BEGIN CERTIFICATE-----
-MIICDjCCAXegAwIBAgIJANjT46bL48zNMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV
-BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNTAx
-MTExODUwMjRaFw0xNjAxMTExODUwMjRaMDIxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
+MIICDjCCAXegAwIBAgIJANjT46bL48zPMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNjAx
+MTIyMjM3NTBaFw0yMTAxMTEyMjM3NTBaMDIxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
DAV3MS5maTETMBEGA1UEAwwKb2NzcC53MS5maTCBnzANBgkqhkiG9w0BAQEFAAOB
jQAwgYkCgYEAsl4vHecs9myrsBae+hIvskzII3toCHY4g5f1PwWsXdmBqc51kqG8
lsbIAO4e1/DaitjnwNdCwyVi58dg+qiCTBvOc5qrjbP+PbZ/Af5ZZEJ1qAQYBy0i
ZCe58a8BtO2/puqReNGcMPVhN//5G/gWX2t3MvnX450M1cO5QxbwOsMCAwEAAaMv
MC0wCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwEwYDVR0lBAwwCgYIKwYBBQUHAwkw
-DQYJKoZIhvcNAQELBQADgYEAQUK2cEpwH63ZJfcClL2Rt2mtMVnGKk5eSu1dwSQJ
-mJQVQoYssp1ieuDsYDlHk8nHYQG1LABThm5mme6zV137g2vTdyYMxy0W6oRpWbeo
-3jVhC3rzYh4alJHEvYVKYxAJEYh1yfVXhJrv0XgpXnb8M3aEsrX2iMz7+c+ftIgp
-PJ0=
+DQYJKoZIhvcNAQELBQADgYEArke2IxhYmtQmY61BwV0+NHjDgCn2ECuVO9zv8rO4
+SyMHoBHlXLZOfG3UYqKuD/0l77+aGkrVIcGaD1fm2pa15tkCHluY4zWLtg0kItM1
+pCDnQuq6EXKgZIRzPM4oW7AkU+lHpO4HhbJ67JWPW0sCt8k7L+MwV/kM3/ipfE21
+DwE=
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 15624081837803162841 (0xd8d3e3a6cbe3ccd9)
- Signature Algorithm: sha1WithRSAEncryption
+ Serial Number: 15624081837803162852 (0xd8d3e3a6cbe3cce4)
+ Signature Algorithm: sha256WithRSAEncryption
Issuer: C=FI, O=w1.fi, CN=Root CA
Validity
- Not Before: Feb 19 12:18:22 2015 GMT
- Not After : Feb 19 12:18:22 2016 GMT
+ Not Before: Feb 19 16:39:44 2016 GMT
+ Not After : Feb 18 16:39:44 2017 GMT
Subject: C=FI, O=w1.fi, CN=server6.w1.fi
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
X509v3 Extended Key Usage:
TLS Web Client Authentication, TLS Web Server Authentication
- Signature Algorithm: sha1WithRSAEncryption
- b8:35:8c:b6:18:ac:e9:f6:cb:2c:df:d8:50:88:48:50:33:50:
- fa:92:21:94:b7:82:04:0c:c2:c4:16:bc:dd:2f:75:f8:9d:1a:
- d5:1a:50:dc:7c:97:78:10:25:33:ba:01:6d:47:b8:28:4f:7c:
- d8:c4:a6:85:0d:f5:84:5f:31:68:1e:44:13:16:fd:ce:8b:98:
- 39:46:03:de:aa:62:16:ee:ae:aa:15:27:4a:f2:9d:9c:1f:5a:
- 61:04:ef:3a:7b:c4:5a:3d:a1:d0:2e:f6:31:ea:92:7e:5f:6b:
- 4d:d3:06:d2:ee:a9:4a:56:68:38:76:25:58:e0:07:fb:d5:d8:
- fa:b0
+ Signature Algorithm: sha256WithRSAEncryption
+ 23:91:f7:da:2a:7d:a4:2c:81:e1:0e:3f:43:fb:cc:67:3d:11:
+ f2:4b:b8:2c:2c:41:d0:90:13:38:6a:5a:12:ea:a7:f1:52:b4:
+ 4b:5e:ba:98:b9:b4:36:fc:fe:88:53:2d:4a:f7:08:8f:40:49:
+ aa:90:60:a7:ee:5f:38:af:66:11:f8:31:2b:48:b9:7e:98:1c:
+ ed:38:68:80:b2:18:7e:e9:4f:07:48:7e:a5:ab:fb:e4:46:a6:
+ 2c:e7:66:67:93:bd:41:7f:49:d8:c1:e5:1c:08:c5:ed:17:0c:
+ f4:d9:3a:d8:bb:15:4a:44:c6:c7:42:3a:bf:c5:0f:df:8e:a1:
+ 05:7f
-----BEGIN CERTIFICATE-----
-MIIChzCCAfCgAwIBAgIJANjT46bL48zZMA0GCSqGSIb3DQEBBQUAMC8xCzAJBgNV
-BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNTAy
-MTkxMjE4MjJaFw0xNjAyMTkxMjE4MjJaMDUxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
+MIIChzCCAfCgAwIBAgIJANjT46bL48zkMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNjAy
+MTkxNjM5NDRaFw0xNzAyMTgxNjM5NDRaMDUxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
DAV3MS5maTEWMBQGA1UEAwwNc2VydmVyNi53MS5maTCBnzANBgkqhkiG9w0BAQEF
AAOBjQAwgYkCgYEAyjAe/RNqAihRmg6pHnJ+51rIywx+ipmBjQWzCbCphueuRPrg
x+7zGLQxZeMFb2ZO4+SFgZtHf1+1FiuwWZGcxVXT08osgc7wJ6hU3g5P2PARvQsQ
AaOBpDCBoTAJBgNVHRMEAjAAMB0GA1UdDgQWBBTHxu/1YdKgCIFqa0Qs9XL32t5b
uTAfBgNVHSMEGDAWgBS4kt79ihizMMOfVfMzXbTIKYpBFDA1BggrBgEFBQcBAQQp
MCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9zZXJ2ZXIudzEuZmk6ODg4OC8wHQYDVR0l
-BBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMA0GCSqGSIb3DQEBBQUAA4GBALg1jLYY
-rOn2yyzf2FCISFAzUPqSIZS3ggQMwsQWvN0vdfidGtUaUNx8l3gQJTO6AW1HuChP
-fNjEpoUN9YRfMWgeRBMW/c6LmDlGA96qYhburqoVJ0rynZwfWmEE7zp7xFo9odAu
-9jHqkn5fa03TBtLuqUpWaDh2JVjgB/vV2Pqw
+BBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4GBACOR99oq
+faQsgeEOP0P7zGc9EfJLuCwsQdCQEzhqWhLqp/FStEteupi5tDb8/ohTLUr3CI9A
+SaqQYKfuXzivZhH4MStIuX6YHO04aICyGH7pTwdIfqWr++RGpiznZmeTvUF/SdjB
+5RwIxe0XDPTZOti7FUpExsdCOr/FD9+OoQV/
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 15624081837803162840 (0xd8d3e3a6cbe3ccd8)
- Signature Algorithm: sha1WithRSAEncryption
+ Serial Number: 15624081837803162851 (0xd8d3e3a6cbe3cce3)
+ Signature Algorithm: sha256WithRSAEncryption
Issuer: C=FI, O=w1.fi, CN=Root CA
Validity
- Not Before: Feb 19 12:18:03 2015 GMT
- Not After : Feb 19 12:18:03 2016 GMT
+ Not Before: Feb 19 16:37:01 2016 GMT
+ Not After : Feb 18 16:37:01 2017 GMT
Subject: C=FI, O=w1.fi, CN=server5.w1.fi
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
X509v3 Extended Key Usage:
TLS Web Client Authentication
- Signature Algorithm: sha1WithRSAEncryption
- 49:88:dd:04:23:86:22:49:cb:73:57:9a:f7:d8:71:cf:33:62:
- cc:24:a8:e9:ae:cd:22:91:16:2f:17:86:fc:09:8f:79:c0:93:
- 22:e6:77:25:21:8c:45:38:a3:4d:07:6e:d0:c3:ca:49:8a:3e:
- 86:1f:4e:dd:72:93:f3:47:7d:c3:5b:95:f1:98:50:a5:4e:36:
- ed:71:94:3a:55:ee:ae:21:e3:27:3d:90:df:4a:be:f5:93:a5:
- e2:0b:1a:3d:7d:c7:02:98:c1:17:67:9e:9b:a2:1d:65:fc:81:
- 59:72:2b:89:a9:47:31:ad:30:c0:82:39:47:a2:d2:eb:0e:71:
- d6:3c
+ Signature Algorithm: sha256WithRSAEncryption
+ a0:1e:a7:a7:ce:f9:df:0d:6b:d8:eb:cd:f8:61:69:56:37:0c:
+ 15:91:07:a3:e8:ba:c4:9d:bf:10:1f:b2:21:48:59:b7:9e:80:
+ 30:80:56:eb:fa:e7:f6:07:89:ab:04:be:9c:b0:96:80:9d:12:
+ 90:23:20:b6:f3:3c:3f:08:1c:00:67:2d:9f:b1:bd:72:ce:ed:
+ 64:74:d5:cc:86:e5:26:a5:f1:3f:9f:8d:96:b5:a6:6e:94:10:
+ 84:cb:8c:45:c3:86:c7:79:48:89:6a:fc:1b:00:23:ac:84:ba:
+ be:13:73:82:73:00:c1:fb:e1:8a:bc:7a:d6:d0:19:3f:43:11:
+ 82:26
-----BEGIN CERTIFICATE-----
-MIICfTCCAeagAwIBAgIJANjT46bL48zYMA0GCSqGSIb3DQEBBQUAMC8xCzAJBgNV
-BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNTAy
-MTkxMjE4MDNaFw0xNjAyMTkxMjE4MDNaMDUxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
+MIICfTCCAeagAwIBAgIJANjT46bL48zjMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNjAy
+MTkxNjM3MDFaFw0xNzAyMTgxNjM3MDFaMDUxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
DAV3MS5maTEWMBQGA1UEAwwNc2VydmVyNS53MS5maTCBnzANBgkqhkiG9w0BAQEF
AAOBjQAwgYkCgYEAo5np4uEXYDtwNBp0XEbjuL27qsnz7vsSMKBpw3Q4gDq6I1LH
wWrPut1B49JpNaSmYGwxH4W9Vmx7CWPNp1FrhECQd36XaHs4tcQVO3Q3NCi6euLX
AaOBmjCBlzAJBgNVHRMEAjAAMB0GA1UdDgQWBBQzFp07FxWCKzRuOOjMIr9Jp14q
KzAfBgNVHSMEGDAWgBS4kt79ihizMMOfVfMzXbTIKYpBFDA1BggrBgEFBQcBAQQp
MCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9zZXJ2ZXIudzEuZmk6ODg4OC8wEwYDVR0l
-BAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEASYjdBCOGIknLc1ea99hx
-zzNizCSo6a7NIpEWLxeG/AmPecCTIuZ3JSGMRTijTQdu0MPKSYo+hh9O3XKT80d9
-w1uV8ZhQpU427XGUOlXuriHjJz2Q30q+9ZOl4gsaPX3HApjBF2eem6IdZfyBWXIr
-ialHMa0wwII5R6LS6w5x1jw=
+BAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADgYEAoB6np8753w1r2OvN+GFp
+VjcMFZEHo+i6xJ2/EB+yIUhZt56AMIBW6/rn9geJqwS+nLCWgJ0SkCMgtvM8Pwgc
+AGctn7G9cs7tZHTVzIblJqXxP5+NlrWmbpQQhMuMRcOGx3lIiWr8GwAjrIS6vhNz
+gnMAwfvhirx61tAZP0MRgiY=
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 15624081837803162838 (0xd8d3e3a6cbe3ccd6)
- Signature Algorithm: sha1WithRSAEncryption
+ Serial Number: 15624081837803162853 (0xd8d3e3a6cbe3cce5)
+ Signature Algorithm: sha256WithRSAEncryption
Issuer: C=FI, O=w1.fi, CN=Root CA
Validity
- Not Before: Feb 19 12:16:15 2015 GMT
- Not After : Feb 19 12:16:15 2016 GMT
+ Not Before: Feb 19 16:40:33 2016 GMT
+ Not After : Feb 18 16:40:33 2017 GMT
Subject: C=FI, O=w1.fi, CN=server3.w1.fi
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
X509v3 Extended Key Usage:
TLS Web Server Authentication
- Signature Algorithm: sha1WithRSAEncryption
- 91:6b:2b:90:41:55:93:9a:70:d9:56:57:21:56:08:6e:fb:04:
- e3:40:0d:eb:25:b5:56:21:7d:7b:81:12:97:22:e8:38:95:bc:
- ba:cb:db:97:a8:6f:dd:da:61:40:dd:fc:0d:82:e6:a0:b5:b0:
- 13:d9:dc:ee:84:d7:27:f2:b3:be:01:31:11:5b:23:29:6d:37:
- 8b:24:3c:d9:6c:21:7c:cc:d6:a2:68:32:39:40:00:5f:04:af:
- db:32:f7:10:af:e8:53:c4:d3:2f:03:61:cb:fa:67:c5:18:20:
- 63:f9:d9:42:01:34:c9:eb:9d:33:c8:a3:7e:b5:fb:fe:6b:5f:
- f8:86
+ Signature Algorithm: sha256WithRSAEncryption
+ 8d:b6:aa:0a:f5:7f:1c:6b:0b:6b:34:87:35:c4:76:0e:fd:38:
+ a9:80:5c:79:36:fd:f5:71:10:90:ba:db:07:a1:65:f8:8a:04:
+ 6d:17:94:53:51:cb:e9:76:c2:d3:c3:60:d9:64:fd:f1:b7:b2:
+ 69:4f:aa:18:ef:98:41:58:3d:8d:b5:b5:1b:b0:a1:af:e9:f5:
+ e7:20:8f:44:22:85:00:72:a7:24:78:fd:9a:84:fe:93:87:df:
+ f9:3d:26:76:7b:27:4b:c9:a6:5f:20:10:46:4b:3e:02:b2:39:
+ b0:2f:ef:a9:4b:0c:a5:a0:2f:63:fc:b9:18:44:8f:ff:a2:2b:
+ 27:7d
-----BEGIN CERTIFICATE-----
-MIICfTCCAeagAwIBAgIJANjT46bL48zWMA0GCSqGSIb3DQEBBQUAMC8xCzAJBgNV
-BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNTAy
-MTkxMjE2MTVaFw0xNjAyMTkxMjE2MTVaMDUxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
+MIICfTCCAeagAwIBAgIJANjT46bL48zlMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNjAy
+MTkxNjQwMzNaFw0xNzAyMTgxNjQwMzNaMDUxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
DAV3MS5maTEWMBQGA1UEAwwNc2VydmVyMy53MS5maTCBnzANBgkqhkiG9w0BAQEF
AAOBjQAwgYkCgYEA2/wPoUiHaIbEnnr4GCh3baNYD9u+a9RDQ8S6FzebqP+WonMU
ExyuGQ+BVDUQZJTjZGW+mwsW0p6SmHeH4pqZ/B1XDIoNTCEvrmfXY2HrkVtYL61n
AaOBmjCBlzAJBgNVHRMEAjAAMB0GA1UdDgQWBBSOmk9NRq1ZrH9MnL5tW9eZY43H
cDAfBgNVHSMEGDAWgBS4kt79ihizMMOfVfMzXbTIKYpBFDA1BggrBgEFBQcBAQQp
MCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9zZXJ2ZXIudzEuZmk6ODg4OC8wEwYDVR0l
-BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQEFBQADgYEAkWsrkEFVk5pw2VZXIVYI
-bvsE40AN6yW1ViF9e4ESlyLoOJW8usvbl6hv3dphQN38DYLmoLWwE9nc7oTXJ/Kz
-vgExEVsjKW03iyQ82WwhfMzWomgyOUAAXwSv2zL3EK/oU8TTLwNhy/pnxRggY/nZ
-QgE0yeudM8ijfrX7/mtf+IY=
+BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADgYEAjbaqCvV/HGsLazSHNcR2
+Dv04qYBceTb99XEQkLrbB6Fl+IoEbReUU1HL6XbC08Ng2WT98beyaU+qGO+YQVg9
+jbW1G7Chr+n15yCPRCKFAHKnJHj9moT+k4ff+T0mdnsnS8mmXyAQRks+ArI5sC/v
+qUsMpaAvY/y5GESP/6IrJ30=
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 15624081837803162832 (0xd8d3e3a6cbe3ccd0)
+ Serial Number: 15624081837803162857 (0xd8d3e3a6cbe3cce9)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=FI, O=w1.fi, CN=Root CA
Validity
- Not Before: Sep 29 21:11:22 2014 GMT
- Not After : Sep 29 21:11:22 2015 GMT
+ Not Before: Sep 30 18:13:57 2016 GMT
+ Not After : Sep 30 18:13:57 2017 GMT
Subject: C=FI, O=w1.fi, CN=server.w1.fi
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
X509v3 Extended Key Usage:
TLS Web Server Authentication
Signature Algorithm: sha256WithRSAEncryption
- 92:b7:19:2f:15:84:00:c6:68:01:ba:96:67:11:df:7d:0c:1e:
- 45:eb:59:e5:64:ad:db:f0:23:ce:22:af:a0:35:a2:6f:99:96:
- 9d:2d:bc:b5:8d:58:36:c7:71:f4:fb:c8:a5:e8:44:45:52:7e:
- 1e:44:dd:99:3b:1c:40:f1:f7:73:ec:f9:b7:fc:06:cc:a9:a5:
- 37:41:d1:20:2b:b5:93:75:26:1b:46:2e:3d:25:a3:5e:e9:7e:
- 73:37:9d:e7:71:6f:bb:21:22:cc:31:3e:a2:3f:18:05:ca:35:
- d2:98:b8:53:6b:92:ac:73:10:8d:8a:09:a4:e3:46:ad:28:72:
- ab:51
+ 24:da:48:be:a8:ae:6e:25:ed:12:bd:f5:a3:32:1f:40:4c:ab:
+ 50:87:23:b1:46:45:b0:e5:9b:02:ad:c9:d3:fb:c0:52:78:b5:
+ 91:2a:d4:8f:f8:c8:a4:48:b4:66:f7:2e:f1:cf:8c:3a:7a:54:
+ fc:e2:41:a7:af:e3:d1:66:d6:02:d8:93:de:52:b2:c2:6e:d9:
+ 7a:bd:8c:ce:e5:dc:3b:0b:7a:f6:fc:a0:4e:9c:64:84:14:3f:
+ 9b:24:fc:d0:8f:9c:78:c8:57:0f:32:dd:ed:97:f1:c1:a2:b3:
+ 0a:14:9e:c8:35:68:30:1a:10:22:14:66:4a:6b:a4:47:b4:c6:
+ 4f:3b
-----BEGIN CERTIFICATE-----
-MIIClTCCAf6gAwIBAgIJANjT46bL48zQMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV
-BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNDA5
-MjkyMTExMjJaFw0xNTA5MjkyMTExMjJaMDQxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
+MIIClTCCAf6gAwIBAgIJANjT46bL48zpMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNjA5
+MzAxODEzNTdaFw0xNzA5MzAxODEzNTdaMDQxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
DAV3MS5maTEVMBMGA1UEAwwMc2VydmVyLncxLmZpMIGfMA0GCSqGSIb3DQEBAQUA
A4GNADCBiQKBgQC6oHdVIhSFVWWbZCyt7ZvdZTHJ2mBQzjjWNNzovBueMOcS41Ns
ye1IA3mBaZjOirh3RzZFz8bg8XsecYlU9wHMIq2gQrGoNZ5gqjqYUdD/H+6+jQpj
MB8GA1UdIwQYMBaAFLiS3v2KGLMww59V8zNdtMgpikEUMDUGCCsGAQUFBwEBBCkw
JzAlBggrBgEFBQcwAYYZaHR0cDovL3NlcnZlci53MS5maTo4ODg4LzAXBgNVHREE
EDAOggxzZXJ2ZXIudzEuZmkwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcN
-AQELBQADgYEAkrcZLxWEAMZoAbqWZxHffQweRetZ5WSt2/AjziKvoDWib5mWnS28
-tY1YNsdx9PvIpehERVJ+HkTdmTscQPH3c+z5t/wGzKmlN0HRICu1k3UmG0YuPSWj
-Xul+czed53FvuyEizDE+oj8YBco10pi4U2uSrHMQjYoJpONGrShyq1E=
+AQELBQADgYEAJNpIvqiubiXtEr31ozIfQEyrUIcjsUZFsOWbAq3J0/vAUni1kSrU
+j/jIpEi0Zvcu8c+MOnpU/OJBp6/j0WbWAtiT3lKywm7Zer2MzuXcOwt69vygTpxk
+hBQ/myT80I+ceMhXDzLd7ZfxwaKzChSeyDVoMBoQIhRmSmukR7TGTzs=
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 15624081837803162833 (0xd8d3e3a6cbe3ccd1)
+ Serial Number: 15624081837803162859 (0xd8d3e3a6cbe3cceb)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=FI, O=w1.fi, CN=Root CA
Validity
- Not Before: Sep 29 21:13:00 2014 GMT
- Not After : Sep 29 21:13:00 2015 GMT
+ Not Before: Sep 30 18:20:27 2016 GMT
+ Not After : Sep 30 18:20:27 2017 GMT
Subject: C=FI, O=w1.fi, CN=Test User
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
X509v3 Extended Key Usage:
TLS Web Client Authentication
Signature Algorithm: sha256WithRSAEncryption
- 76:24:5a:f8:de:ef:8b:65:02:67:ab:8f:3a:42:88:22:35:40:
- 48:df:97:91:9b:5a:d4:60:af:61:ef:53:7a:2c:76:04:5f:80:
- 27:79:7e:1f:0a:ed:ab:71:0c:6e:90:7a:69:04:4e:21:cb:31:
- 47:ee:e9:36:87:a9:f4:a1:dd:e9:8a:fd:41:cc:d2:ae:dd:47:
- 66:d1:71:08:b2:e8:5e:e3:36:9e:98:c8:66:51:5b:41:95:02:
- 29:fd:b6:46:d2:40:ec:0e:46:40:92:b1:b7:e2:28:6e:85:17:
- 1e:8d:52:40:c8:20:ca:9b:ab:f0:10:30:8c:0b:5d:91:91:8c:
- ff:ca
+ 47:2e:3d:23:86:d0:3e:fb:b5:7f:d6:32:6b:12:fb:7c:76:78:
+ ec:82:db:ab:fa:5e:0f:1d:97:36:f9:de:b3:cb:fd:08:9e:d5:
+ cd:3d:97:78:c5:00:ce:78:f1:39:3b:84:c9:d0:e6:17:58:ed:
+ ac:e2:d2:a8:7a:fd:b9:19:a4:1c:57:08:17:8c:7f:70:88:82:
+ d5:89:0f:1e:18:22:6d:62:69:4c:12:92:32:bc:cc:1b:a0:05:
+ bc:af:7f:53:a9:dc:a9:55:48:e0:28:34:3e:60:3f:82:16:ac:
+ 70:a1:01:e7:75:cf:a0:72:ad:39:ad:52:65:a8:64:fa:7f:11:
+ f2:f5
-----BEGIN CERTIFICATE-----
-MIICeTCCAeKgAwIBAgIJANjT46bL48zRMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV
-BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNDA5
-MjkyMTEzMDBaFw0xNTA5MjkyMTEzMDBaMDExCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
+MIICeTCCAeKgAwIBAgIJANjT46bL48zrMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNjA5
+MzAxODIwMjdaFw0xNzA5MzAxODIwMjdaMDExCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
DAV3MS5maTESMBAGA1UEAwwJVGVzdCBVc2VyMIGfMA0GCSqGSIb3DQEBAQUAA4GN
ADCBiQKBgQCmli6bIozflL6LiUn2eHaiYH4UlfOW/qsZJQM0ZHQBPqiffPFHYWBM
gpIofCugDsuHv1nr1/NhIjsU86sx9lqVH7h6uCw8qWFTeJvoPlDswtZE50PNvD5O
MIGXMAkGA1UdEwQCMAAwHQYDVR0OBBYEFIHe3+laABrKZ9YG3WWyTsWaBEN9MB8G
A1UdIwQYMBaAFLiS3v2KGLMww59V8zNdtMgpikEUMDUGCCsGAQUFBwEBBCkwJzAl
BggrBgEFBQcwAYYZaHR0cDovL3NlcnZlci53MS5maTo4ODg4LzATBgNVHSUEDDAK
-BggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOBgQB2JFr43u+LZQJnq486QogiNUBI
-35eRm1rUYK9h71N6LHYEX4AneX4fCu2rcQxukHppBE4hyzFH7uk2h6n0od3piv1B
-zNKu3Udm0XEIsuhe4zaemMhmUVtBlQIp/bZG0kDsDkZAkrG34ihuhRcejVJAyCDK
-m6vwEDCMC12RkYz/yg==
+BggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOBgQBHLj0jhtA++7V/1jJrEvt8dnjs
+gtur+l4PHZc2+d6zy/0IntXNPZd4xQDOePE5O4TJ0OYXWO2s4tKoev25GaQcVwgX
+jH9wiILViQ8eGCJtYmlMEpIyvMwboAW8r39TqdypVUjgKDQ+YD+CFqxwoQHndc+g
+cq05rVJlqGT6fxHy9Q==
-----END CERTIFICATE-----
CONFIG_TLSV12=y
CONFIG_FULL_DYNAMIC_VLAN=y
+CONFIG_VLAN_NETLINK=y
CONFIG_LIBNL32=y
CONFIG_LIBNL3_ROUTE=y
CONFIG_PEERKEY=y
#LIBS_h += -fsanitize=undefined
#LIBS_n += -fsanitize=undefined
#LIBS_c += -fsanitize=undefined
+CONFIG_MBO=y
+
+CONFIG_IAPP=y
+CONFIG_TAXONOMY=y
Install the prerequisite packages that may not have been installed by default
-sudo apt-get install build-essential git libpcap-dev libsqlite3-dev binutils-dev libnl-3-dev libnl-genl-3-dev libnl-route-3-dev libssl-dev libiberty-dev libdbus-1-dev iw bridge-utils python-pyrad python-crypto
+sudo apt-get install build-essential git libpcap-dev libsqlite3-dev binutils-dev libnl-3-dev libnl-genl-3-dev libnl-route-3-dev libssl-dev libiberty-dev libdbus-1-dev iw bridge-utils python-pyrad python-crypto tshark
+
+optional:
+sudo apt-get install python-netifaces
Install a recent kernel wireless components (mac80211_hwsim, mac80211,
CONFIG_IEEE80211W=y
CONFIG_IEEE80211R=y
CONFIG_IEEE80211N=y
+CONFIG_IEEE80211AC=y
CONFIG_DEBUG_FILE=y
CONFIG_P2P=y
CONFIG_WIFI_DISPLAY=y
+CONFIG_ACS=y
+
CONFIG_BGSCAN_SIMPLE=y
CONFIG_BGSCAN_LEARN=y
##LIBS += -fno-sanitize-recover
#LIBS_c += -fsanitize=undefined
#LIBS_p += -fsanitize=undefined
+CONFIG_MBO=y
# See README for more details.
import logging
-import subprocess
import os
import signal
import time
function"""
if self.peer_obj is None:
raise Exception("Peer wasn't added before starting session")
+ self.dump_monitor()
grp = ' ' + self.fst_group if self.fst_group != '' else ''
sid = self.grequest("FST-MANAGER SESSION_ADD" + grp)
sid = sid.strip()
if sid.startswith("FAIL"):
raise Exception("Cannot add FST session with groupid ==" + grp)
+ self.dump_monitor()
return sid
def set_session_param(self, params):
in "self" while others are passed to this function explicitly. If
old_iface is None, current iface is used; if old_iface is an empty
string."""
+ self.dump_monitor()
oldiface = old_iface if old_iface is not None else self.iface
s = self.set_session_param(sid + ' old_ifname=' + oldiface)
if not s.startswith("OK"):
s = self.set_session_param(sid + " llt=" + self.fst_llt)
if not s.startswith("OK"):
raise Exception("Cannot set FST session llt:" + s)
+ self.dump_monitor()
def send_iface_attach_request(self, ifname, group, llt, priority):
request = "FST-ATTACH " + ifname + ' ' + group
Returns: REASON_SWITCH - the session has been transferred successfully
or a REASON_... reported by the reset event."""
request = "FST-MANAGER SESSION_TRANSFER"
+ self.dump_monitor()
if sid != '':
request += ' ' + sid
s = self.grequest(request)
raise Exception("Unrecognized FST event: " % ev)
if event['new_state'] == 'INITIAL':
result = event['reason']
+ self.dump_monitor()
return result
def wait_for_tear_down(self):
hostapd."""
if len(self.fst_group) != 0:
self.remove_all_sessions()
- self.send_iface_detach_request(self.iface)
+ try:
+ self.send_iface_detach_request(self.iface)
+ except Exception, e:
+ logger.info(str(e))
self.reg_ctrl.stop()
del self.global_instance
self.global_instance = None
def get_ssid(self):
return self.ssid
+ def dump_monitor(self):
+ """Dump control interface monitor events"""
+ if self.instance:
+ self.instance.dump_monitor()
+
#
# FstSTA class
#
the STA will be removed when the fst wpa_supplicant process is killed by
fstap.cleanup()."""
h = self.get_instance()
+ h.dump_monitor()
if len(self.fst_group) != 0:
self.remove_all_sessions()
self.send_iface_detach_request(self.iface)
+ h.dump_monitor()
h.interface_remove(self.iface)
h.close_ctrl()
del h
no_wait=True. Note, request("SCAN_RESULTS") can be used to get all the
results at once."""
h = self.get_instance()
+ h.dump_monitor()
h.scan(None, freq, no_wait, only_new)
r = h.get_bss('0')
+ h.dump_monitor()
return r
def connect(self, ap, **kwargs):
raise Exception("Bad AP object to connect to")
h = self.get_instance()
hap = ap.get_instance()
+ h.dump_monitor()
h.connect(ap.get_ssid(), **kwargs)
+ h.dump_monitor()
self.connected = ap
def connect_to_external_ap(self, ap, ssid, check_connection=True, **kwargs):
if not isinstance(ap, hostapd.Hostapd):
raise Exception("Bad AP object to connect to")
h = self.get_instance()
+ h.dump_monitor()
h.connect(ssid, **kwargs)
self.connected = ap
if check_connection:
if ev is None:
self.connected = None
raise Exception("No connection event received from %s" % ssid)
+ h.dump_monitor()
def disconnect(self, check_disconnect=True):
"""Disconnects from the AP the station is currently connected to"""
if self.connected is not None:
h = self.get_instance()
+ h.dump_monitor()
h.request("DISCONNECT")
if check_disconnect:
hap = self.connected.get_instance()
ev = hap.wait_event([ "AP-STA-DISCONNECTED" ], timeout=10)
if ev is None:
raise Exception("No disconnection event received from %s" % self.connected.get_ssid())
+ h.dump_monitor()
self.connected = None
to"""
if self.connected is not None:
h = self.get_instance()
+ h.dump_monitor()
h.request("DISCONNECT")
if check_disconnect:
hap = self.connected
ev = hap.wait_event([ "AP-STA-DISCONNECTED" ], timeout=10)
if ev is None:
raise Exception("No disconnection event received from AP")
+ h.dump_monitor()
self.connected = None
+
+ def dump_monitor(self):
+ """Dump control interface monitor events"""
+ if self.instance:
+ self.instance.dump_monitor()
import binascii
import struct
import wpaspy
+import remotehost
+import utils
+import subprocess
logger = logging.getLogger()
hapd_ctrl = '/var/run/hostapd'
return struct.unpack('6B', binascii.unhexlify(mac.replace(':','')))
class HostapdGlobal:
- def __init__(self):
- self.ctrl = wpaspy.Ctrl(hapd_global)
- self.mon = wpaspy.Ctrl(hapd_global)
+ def __init__(self, apdev=None):
+ try:
+ hostname = apdev['hostname']
+ port = apdev['port']
+ except:
+ hostname = None
+ port = 8878
+ self.host = remotehost.Host(hostname)
+ self.hostname = hostname
+ self.port = port
+ if hostname is None:
+ self.ctrl = wpaspy.Ctrl(hapd_global)
+ self.mon = wpaspy.Ctrl(hapd_global)
+ self.dbg = ""
+ else:
+ self.ctrl = wpaspy.Ctrl(hostname, port)
+ self.mon = wpaspy.Ctrl(hostname, port)
+ self.dbg = hostname + "/" + str(port)
self.mon.attach()
- def request(self, cmd):
- return self.ctrl.request(cmd)
+ def cmd_execute(self, cmd_array, shell=False):
+ if self.hostname is None:
+ if shell:
+ cmd = ' '.join(cmd_array)
+ else:
+ cmd = cmd_array
+ proc = subprocess.Popen(cmd, stderr=subprocess.STDOUT,
+ stdout=subprocess.PIPE, shell=shell)
+ out = proc.communicate()[0]
+ ret = proc.returncode
+ return ret, out
+ else:
+ return self.host.execute(cmd_array)
+
+ def request(self, cmd, timeout=10):
+ logger.debug(self.dbg + ": CTRL(global): " + cmd)
+ return self.ctrl.request(cmd, timeout)
def wait_event(self, events, timeout):
start = os.times()[4]
while True:
while self.mon.pending():
ev = self.mon.recv()
- logger.debug("(global): " + ev)
+ logger.debug(self.dbg + "(global): " + ev)
for event in events:
if event in ev:
return ev
break
return None
- def request(self, cmd):
- return self.ctrl.request(cmd)
-
def add(self, ifname, driver=None):
cmd = "ADD " + ifname + " " + hapd_ctrl
if driver:
cmd += " " + driver
- res = self.ctrl.request(cmd)
+ res = self.request(cmd)
if not "OK" in res:
raise Exception("Could not add hostapd interface " + ifname)
def add_iface(self, ifname, confname):
- res = self.ctrl.request("ADD " + ifname + " config=" + confname)
+ res = self.request("ADD " + ifname + " config=" + confname)
if not "OK" in res:
raise Exception("Could not add hostapd interface")
def add_bss(self, phy, confname, ignore_error=False):
- res = self.ctrl.request("ADD bss_config=" + phy + ":" + confname)
+ res = self.request("ADD bss_config=" + phy + ":" + confname)
if not "OK" in res:
if not ignore_error:
raise Exception("Could not add hostapd BSS")
def remove(self, ifname):
- self.ctrl.request("REMOVE " + ifname, timeout=30)
+ self.request("REMOVE " + ifname, timeout=30)
def relog(self):
- self.ctrl.request("RELOG")
+ self.request("RELOG")
def flush(self):
- self.ctrl.request("FLUSH")
+ self.request("FLUSH")
+ def get_ctrl_iface_port(self, ifname):
+ if self.hostname is None:
+ return None
+
+ res = self.request("INTERFACES ctrl")
+ lines = res.splitlines()
+ found = False
+ for line in lines:
+ words = line.split()
+ if words[0] == ifname:
+ found = True
+ break
+ if not found:
+ raise Exception("Could not find UDP port for " + ifname)
+ res = line.find("ctrl_iface=udp:")
+ if res == -1:
+ raise Exception("Wrong ctrl_interface format")
+ words = line.split(":")
+ return int(words[1])
+
+ def terminate(self):
+ self.mon.detach()
+ self.mon.close()
+ self.mon = None
+ self.ctrl.terminate()
+ self.ctrl = None
class Hostapd:
- def __init__(self, ifname, bssidx=0):
+ def __init__(self, ifname, bssidx=0, hostname=None, port=8877):
+ self.hostname = hostname
+ self.host = remotehost.Host(hostname, ifname)
self.ifname = ifname
- self.ctrl = wpaspy.Ctrl(os.path.join(hapd_ctrl, ifname))
- self.mon = wpaspy.Ctrl(os.path.join(hapd_ctrl, ifname))
+ if hostname is None:
+ self.ctrl = wpaspy.Ctrl(os.path.join(hapd_ctrl, ifname))
+ self.mon = wpaspy.Ctrl(os.path.join(hapd_ctrl, ifname))
+ self.dbg = ifname
+ else:
+ self.ctrl = wpaspy.Ctrl(hostname, port)
+ self.mon = wpaspy.Ctrl(hostname, port)
+ self.dbg = hostname + "/" + ifname
self.mon.attach()
self.bssid = None
self.bssidx = bssidx
+ def cmd_execute(self, cmd_array, shell=False):
+ if self.hostname is None:
+ if shell:
+ cmd = ' '.join(cmd_array)
+ else:
+ cmd = cmd_array
+ proc = subprocess.Popen(cmd, stderr=subprocess.STDOUT,
+ stdout=subprocess.PIPE, shell=shell)
+ out = proc.communicate()[0]
+ ret = proc.returncode
+ return ret, out
+ else:
+ return self.host.execute(cmd_array)
+
+ def close_ctrl(self):
+ if self.mon is not None:
+ self.mon.detach()
+ self.mon.close()
+ self.mon = None
+ self.ctrl.close()
+ self.ctrl = None
+
def own_addr(self):
if self.bssid is None:
self.bssid = self.get_status_field('bssid[%d]' % self.bssidx)
return self.bssid
def request(self, cmd):
- logger.debug(self.ifname + ": CTRL: " + cmd)
+ logger.debug(self.dbg + ": CTRL: " + cmd)
return self.ctrl.request(cmd)
def ping(self):
def dump_monitor(self):
while self.mon.pending():
ev = self.mon.recv()
- logger.debug(self.ifname + ": " + ev)
+ logger.debug(self.dbg + ": " + ev)
def wait_event(self, events, timeout):
start = os.times()[4]
while True:
while self.mon.pending():
ev = self.mon.recv()
- logger.debug(self.ifname + ": " + ev)
+ logger.debug(self.dbg + ": " + ev)
for event in events:
if event in ev:
return ev
vals[name_val[0]] = name_val[1]
return vals
-def add_ap(ifname, params, wait_enabled=True, no_enable=False):
- logger.info("Starting AP " + ifname)
- hapd_global = HostapdGlobal()
+ def get_pmksa(self, addr):
+ res = self.request("PMKSA")
+ lines = res.splitlines()
+ for l in lines:
+ if addr not in l:
+ continue
+ vals = dict()
+ [index,aa,pmkid,expiration,opportunistic] = l.split(' ')
+ vals['index'] = index
+ vals['pmkid'] = pmkid
+ vals['expiration'] = expiration
+ vals['opportunistic'] = opportunistic
+ return vals
+ return None
+
+def add_ap(apdev, params, wait_enabled=True, no_enable=False, timeout=30):
+ if isinstance(apdev, dict):
+ ifname = apdev['ifname']
+ try:
+ hostname = apdev['hostname']
+ port = apdev['port']
+ logger.info("Starting AP " + hostname + "/" + port + " " + ifname)
+ except:
+ logger.info("Starting AP " + ifname)
+ hostname = None
+ port = 8878
+ else:
+ ifname = apdev
+ logger.info("Starting AP " + ifname + " (old add_ap argument type)")
+ hostname = None
+ port = 8878
+ hapd_global = HostapdGlobal(apdev)
hapd_global.remove(ifname)
hapd_global.add(ifname)
- hapd = Hostapd(ifname)
+ port = hapd_global.get_ctrl_iface_port(ifname)
+ hapd = Hostapd(ifname, hostname=hostname, port=port)
if not hapd.ping():
raise Exception("Could not ping hostapd")
hapd.set_defaults()
return hapd
hapd.enable()
if wait_enabled:
- ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=30)
+ ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=timeout)
if ev is None:
raise Exception("AP startup timed out")
if "AP-ENABLED" not in ev:
raise Exception("AP startup failed")
return hapd
-def add_bss(phy, ifname, confname, ignore_error=False):
- logger.info("Starting BSS phy=" + phy + " ifname=" + ifname)
- hapd_global = HostapdGlobal()
+def add_bss(apdev, ifname, confname, ignore_error=False):
+ phy = utils.get_phy(apdev)
+ try:
+ hostname = apdev['hostname']
+ port = apdev['port']
+ logger.info("Starting BSS " + hostname + "/" + port + " phy=" + phy + " ifname=" + ifname)
+ except:
+ logger.info("Starting BSS phy=" + phy + " ifname=" + ifname)
+ hostname = None
+ port = 8878
+ hapd_global = HostapdGlobal(apdev)
hapd_global.add_bss(phy, confname, ignore_error)
- hapd = Hostapd(ifname)
+ port = hapd_global.get_ctrl_iface_port(ifname)
+ hapd = Hostapd(ifname, hostname=hostname, port=port)
if not hapd.ping():
raise Exception("Could not ping hostapd")
-
-def add_iface(ifname, confname):
- logger.info("Starting interface " + ifname)
- hapd_global = HostapdGlobal()
+ return hapd
+
+def add_iface(apdev, confname):
+ ifname = apdev['ifname']
+ try:
+ hostname = apdev['hostname']
+ port = apdev['port']
+ logger.info("Starting interface " + hostname + "/" + port + " " + ifname)
+ except:
+ logger.info("Starting interface " + ifname)
+ hostname = None
+ port = 8878
+ hapd_global = HostapdGlobal(apdev)
hapd_global.add_iface(ifname, confname)
- hapd = Hostapd(ifname)
+ port = hapd_global.get_ctrl_iface_port(ifname)
+ hapd = Hostapd(ifname, hostname=hostname, port=port)
if not hapd.ping():
raise Exception("Could not ping hostapd")
-
-def remove_bss(ifname):
- logger.info("Removing BSS " + ifname)
- hapd_global = HostapdGlobal()
+ return hapd
+
+def remove_bss(apdev, ifname=None):
+ if ifname == None:
+ ifname = apdev['ifname']
+ try:
+ hostname = apdev['hostname']
+ port = apdev['port']
+ logger.info("Removing BSS " + hostname + "/" + port + " " + ifname)
+ except:
+ logger.info("Removing BSS " + ifname)
+ hapd_global = HostapdGlobal(apdev)
hapd_global.remove(ifname)
+def terminate(apdev):
+ try:
+ hostname = apdev['hostname']
+ port = apdev['port']
+ logger.info("Terminating hostapd " + hostname + "/" + port)
+ except:
+ logger.info("Terminating hostapd")
+ hapd_global = HostapdGlobal(apdev)
+ hapd_global.terminate()
+
def wpa2_params(ssid=None, passphrase=None):
params = { "wpa": "2",
"wpa_key_mgmt": "WPA-PSK",
if ssid:
params["ssid"] = ssid
return params
+
+def b_only_params(channel="1", ssid=None, country=None):
+ params = { "hw_mode" : "b",
+ "channel" : channel }
+ if ssid:
+ params["ssid"] = ssid
+ if country:
+ params["country_code"] = country
+ return params
+
+def g_only_params(channel="1", ssid=None, country=None):
+ params = { "hw_mode" : "g",
+ "channel" : channel }
+ if ssid:
+ params["ssid"] = ssid
+ if country:
+ params["country_code"] = country
+ return params
+
+def a_only_params(channel="36", ssid=None, country=None):
+ params = { "hw_mode" : "a",
+ "channel" : channel }
+ if ssid:
+ params["ssid"] = ssid
+ if country:
+ params["country_code"] = country
+ return params
+
+def ht20_params(channel="1", ssid=None, country=None):
+ params = { "ieee80211n" : "1",
+ "channel" : channel,
+ "hw_mode" : "g" }
+ if int(channel) > 14:
+ params["hw_mode"] = "a"
+ if ssid:
+ params["ssid"] = ssid
+ if country:
+ params["country_code"] = country
+ return params
+
+def ht40_plus_params(channel="1", ssid=None, country=None):
+ params = ht20_params(channel, ssid, country)
+ params['ht_capab'] = "[HT40+]"
+ return params
+
+def ht40_minus_params(channel="1", ssid=None, country=None):
+ params = ht20_params(channel, ssid, country)
+ params['ht_capab'] = "[HT40-]"
+ return params
+
+def cmd_execute(apdev, cmd, shell=False):
+ hapd_global = HostapdGlobal(apdev)
+ return hapd_global.cmd_execute(cmd, shell=shell)
# See README for more details.
import os
-import subprocess
import time
import logging
logger = logging.getLogger()
dev1.dump_monitor()
dev2.dump_monitor()
+ if dev1.hostname is None and dev2.hostname is None:
+ broadcast_retry_c = 1
+ else:
+ broadcast_retry_c = 10
+
try:
if config:
cmd = "DATA_TEST_CONFIG 1"
raise Exception("Unexpected dev1->dev2 unicast data result")
cmd = "DATA_TEST_TX ff:ff:ff:ff:ff:ff {} {}".format(addr1, tos)
- if dev1group:
- dev1.group_request(cmd)
- else:
- dev1.request(cmd)
- if dev2group:
- ev = dev2.wait_group_event(["DATA-TEST-RX"], timeout=timeout)
- else:
- ev = dev2.wait_event(["DATA-TEST-RX"], timeout=timeout)
- if ev is None:
- raise Exception("dev1->dev2 broadcast data delivery failed")
- if "DATA-TEST-RX ff:ff:ff:ff:ff:ff {}".format(addr1) not in ev:
- raise Exception("Unexpected dev1->dev2 broadcast data result")
+ for i in xrange(broadcast_retry_c):
+ try:
+ if dev1group:
+ dev1.group_request(cmd)
+ else:
+ dev1.request(cmd)
+ if dev2group:
+ ev = dev2.wait_group_event(["DATA-TEST-RX"],
+ timeout=timeout)
+ else:
+ ev = dev2.wait_event(["DATA-TEST-RX"], timeout=timeout)
+ if ev is None:
+ raise Exception("dev1->dev2 broadcast data delivery failed")
+ if "DATA-TEST-RX ff:ff:ff:ff:ff:ff {}".format(addr1) not in ev:
+ raise Exception("Unexpected dev1->dev2 broadcast data result")
+ break
+ except Exception as e:
+ if i == broadcast_retry_c - 1:
+ raise
cmd = "DATA_TEST_TX {} {} {}".format(addr1, addr2, tos)
if dev2group:
raise Exception("Unexpected dev2->dev1 unicast data result")
cmd = "DATA_TEST_TX ff:ff:ff:ff:ff:ff {} {}".format(addr2, tos)
- if dev2group:
- dev2.group_request(cmd)
- else:
- dev2.request(cmd)
- if dev1group:
- ev = dev1.wait_group_event(["DATA-TEST-RX"], timeout=timeout)
- else:
- ev = dev1.wait_event(["DATA-TEST-RX"], timeout=timeout)
- if ev is None:
- raise Exception("dev2->dev1 broadcast data delivery failed")
- if "DATA-TEST-RX ff:ff:ff:ff:ff:ff {}".format(addr2) not in ev:
- raise Exception("Unexpected dev2->dev1 broadcast data result")
+ for i in xrange(broadcast_retry_c):
+ try:
+ if dev2group:
+ dev2.group_request(cmd)
+ else:
+ dev2.request(cmd)
+ if dev1group:
+ ev = dev1.wait_group_event(["DATA-TEST-RX"],
+ timeout=timeout)
+ else:
+ ev = dev1.wait_event(["DATA-TEST-RX"], timeout=timeout)
+ if ev is None:
+ raise Exception("dev2->dev1 broadcast data delivery failed")
+ if "DATA-TEST-RX ff:ff:ff:ff:ff:ff {}".format(addr2) not in ev:
+ raise Exception("Unexpected dev2->dev1 broadcast data result")
+ break
+ except Exception as e:
+ if i == broadcast_retry_c - 1:
+ raise
finally:
if config:
if dev1group:
def set_powersave(dev, val):
phy = dev.get_driver_status_field("phyname")
- psf = open('/sys/kernel/debug/ieee80211/%s/hwsim/ps' % phy, 'w')
- psf.write('%d\n' % val)
- psf.close()
+ fname = '/sys/kernel/debug/ieee80211/%s/hwsim/ps' % phy
+ data = '%d' % val
+ (res, data) = dev.cmd_execute(["echo", data, ">", fname], shell=True)
+ if res != 0:
+ raise Exception("Failed to set power save for device")
alen,attr = struct.unpack("@HH", msg[0:4])
if alen < 4:
raise Exception("Too short nl80211 attribute")
- alen -= 4;
+ alen -= 4
msg = msg[4:]
if alen > len(msg):
raise Exception("nl80211 attribute underflow")
# read the modules from the modules file
if args.mfile:
- args.testmodules = []
- with open(args.mfile) as f:
- for line in f.readlines():
- line = line.strip()
- if not line or line.startswith('#'):
- continue
- args.testmodules.append(line)
+ args.testmodules = []
+ with open(args.mfile) as f:
+ for line in f.readlines():
+ line = line.strip()
+ if not line or line.startswith('#'):
+ continue
+ args.testmodules.append(line)
tests_to_run = []
if args.tests:
t = tests_to_run.pop(0)
name = t.__name__.replace('test_', '', 1)
+ open('/dev/kmsg', 'w').write('running hwsim test case %s\n' % name)
if log_handler:
log_handler.stream.close()
logger.removeHandler(log_handler)
except HwsimSkip, e:
logger.info("Skip test case: %s" % e)
result = "SKIP"
+ except NameError, e:
+ import traceback
+ logger.info(e)
+ traceback.print_exc()
+ result = "FAIL"
except Exception, e:
+ import traceback
logger.info(e)
+ traceback.print_exc()
if args.loglevel == logging.WARNING:
print "Exception: " + str(e)
result = "FAIL"
logger.info("Failed to issue TEST-STOP after {} for {}".format(name, d.ifname))
logger.info(e)
result = "FAIL"
+ if args.no_reset:
+ print "Leaving devices in current state"
+ else:
+ reset_ok = reset_devs(dev, apdev)
wpas = None
try:
wpas = WpaSupplicant(global_iface="/tmp/wpas-wlan5")
pass
if wpas:
wpas.close_ctrl()
- if args.no_reset:
- print "Leaving devices in current state"
- else:
- reset_ok = reset_devs(dev, apdev)
for i in range(0, 3):
rename_log(args.logdir, 'log' + str(i), name, dev[i])
del hapd
hapd = None
+ # Use None here since this instance of Wlantest() will never be
+ # used for remote host hwsim tests on real hardware.
+ Wlantest.setup(None)
wt = Wlantest()
rename_log(args.logdir, 'hwsim0.pcapng', name, wt)
rename_log(args.logdir, 'hwsim0', name, wt)
test -f /proc/modules && sudo modprobe mac80211_hwsim radios=7 channels=$NUM_CH support_p2p_device=0
sudo ifconfig hwsim0 up
-sudo $WLANTEST -i hwsim0 -n $LOGDIR/hwsim0.pcapng -c -dt -L $LOGDIR/hwsim0 &
+sudo $WLANTEST -i hwsim0 -n $LOGDIR/hwsim0.pcapng -c -dtN -L $LOGDIR/hwsim0 &
for i in 0 1 2; do
DBUSARG=""
if [ $i = "0" -a -r /var/run/dbus/pid -a -r /var/run/dbus/hwsim-test ]; then
cp $DIR/auth_serv/ocsp-server-cache.der $LOGDIR/ocsp-server-cache.der
fi
+cp $DIR/auth_serv/ocsp-multi-server-cache.der $LOGDIR/ocsp-multi-server-cache.der
+
+openssl ocsp -index $DIR/auth_serv/index.txt \
+ -rsigner $DIR/auth_serv/ocsp-responder.pem \
+ -rkey $DIR/auth_serv/ocsp-responder.key \
+ -resp_key_id \
+ -CA $DIR/auth_serv/ca.pem \
+ -issuer $DIR/auth_serv/ca.pem \
+ -verify_other $DIR/auth_serv/ca.pem -trust_other \
+ -ndays 7 \
+ -reqin $DIR/auth_serv/ocsp-req.der \
+ -respout $LOGDIR/ocsp-server-cache-key-id.der > $LOGDIR/ocsp.log 2>&1
+
for i in unknown revoked; do
openssl ocsp -index $DIR/auth_serv/index-$i.txt \
-rsigner $DIR/auth_serv/ocsp-responder.pem \
-reqin $DIR/auth_serv/ocsp-req.der \
-respout $LOGDIR/ocsp-server-cache-$i.der >> $LOGDIR/ocsp.log 2>&1
done
+
+openssl ocsp -reqout $LOGDIR/ocsp-req.der -issuer $DIR/auth_serv/ca.pem \
+ -serial 0xD8D3E3A6CBE3CCE9 -no_nonce -sha256 >> $LOGDIR/ocsp.log 2>&1
+for i in "" "-unknown" "-revoked"; do
+ openssl ocsp -index $DIR/auth_serv/index$i.txt \
+ -rsigner $DIR/auth_serv/ca.pem \
+ -rkey $DIR/auth_serv/ca-key.pem \
+ -CA $DIR/auth_serv/ca.pem \
+ -ndays 7 \
+ -reqin $LOGDIR/ocsp-req.der \
+ -resp_no_certs \
+ -respout $LOGDIR/ocsp-resp-ca-signed$i.der >> $LOGDIR/ocsp.log 2>&1
+done
+openssl ocsp -index $DIR/auth_serv/index.txt \
+ -rsigner $DIR/auth_serv/server.pem \
+ -rkey $DIR/auth_serv/server.key \
+ -CA $DIR/auth_serv/ca.pem \
+ -ndays 7 \
+ -reqin $LOGDIR/ocsp-req.der \
+ -respout $LOGDIR/ocsp-resp-server-signed.der >> $LOGDIR/ocsp.log 2>&1
+
touch $LOGDIR/hostapd.db
sudo $HAPD_AS -ddKt $LOGDIR/as.conf $LOGDIR/as2.conf > $LOGDIR/auth_serv &
import logging
logger = logging.getLogger()
-import subprocess
import time
import hostapd
def force_prev_ap_on_24g(ap):
# For now, make sure the last operating channel was on 2.4 GHz band to get
# sufficient survey data from mac80211_hwsim.
- hostapd.add_ap(ap['ifname'], { "ssid": "open" })
+ hostapd.add_ap(ap, { "ssid": "open" })
time.sleep(0.1)
- hapd_global = hostapd.HostapdGlobal()
- hapd_global.remove(ap['ifname'])
+ hostapd.remove_bss(ap)
def force_prev_ap_on_5g(ap):
# For now, make sure the last operating channel was on 5 GHz band to get
# sufficient survey data from mac80211_hwsim.
- hostapd.add_ap(ap['ifname'], { "ssid": "open", "hw_mode": "a",
- "channel": "36", "country_code": "US" })
+ hostapd.add_ap(ap, { "ssid": "open", "hw_mode": "a",
+ "channel": "36", "country_code": "US" })
time.sleep(0.1)
- hapd_global = hostapd.HostapdGlobal()
- hapd_global.remove(ap['ifname'])
+ hostapd.remove_bss(ap)
def wait_acs(hapd):
ev = hapd.wait_event(["ACS-STARTED", "ACS-COMPLETED", "ACS-FAILED",
force_prev_ap_on_24g(apdev[0])
params = hostapd.wpa2_params(ssid="test-acs", passphrase="12345678")
params['channel'] = '0'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
wait_acs(hapd)
freq = hapd.get_status_field("freq")
params = hostapd.wpa2_params(ssid="test-acs", passphrase="12345678")
params['channel'] = '0'
params['chanlist'] = '1 6 11'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
wait_acs(hapd)
freq = hapd.get_status_field("freq")
def test_ap_multi_bss_acs(dev, apdev):
"""hostapd start with a multi-BSS configuration file using ACS"""
skip_with_fips(dev[0])
- ifname = apdev[0]['ifname']
force_prev_ap_on_24g(apdev[0])
# start the actual test
- hostapd.add_iface(ifname, 'multi-bss-acs.conf')
- hapd = hostapd.Hostapd(ifname)
+ hapd = hostapd.add_iface(apdev[0], 'multi-bss-acs.conf')
hapd.enable()
wait_acs(hapd)
def test_ap_acs_40mhz(dev, apdev):
"""Automatic channel selection for 40 MHz channel"""
- clear_scan_cache(apdev[0]['ifname'])
+ clear_scan_cache(apdev[0])
force_prev_ap_on_24g(apdev[0])
params = hostapd.wpa2_params(ssid="test-acs", passphrase="12345678")
params['channel'] = '0'
params['ht_capab'] = '[HT40+]'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
wait_acs(hapd)
freq = hapd.get_status_field("freq")
params['hw_mode'] = 'a'
params['channel'] = '0'
params['country_code'] = 'US'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
wait_acs(hapd)
freq = hapd.get_status_field("freq")
if int(freq) < 5000:
dev[0].request("DISCONNECT")
if hapd:
hapd.request("DISABLE")
- subprocess.call(['iw', 'reg', 'set', '00'])
+ hostapd.cmd_execute(apdev[0], ['iw', 'reg', 'set', '00'])
dev[0].flush_scan_cache()
def test_ap_acs_5ghz_40mhz(dev, apdev):
params['channel'] = '0'
params['ht_capab'] = '[HT40+]'
params['country_code'] = 'US'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
wait_acs(hapd)
freq = hapd.get_status_field("freq")
if int(freq) < 5000:
dev[0].request("DISCONNECT")
if hapd:
hapd.request("DISABLE")
- subprocess.call(['iw', 'reg', 'set', '00'])
+ hostapd.cmd_execute(apdev[0], ['iw', 'reg', 'set', '00'])
dev[0].flush_scan_cache()
def test_ap_acs_vht(dev, apdev):
params['country_code'] = 'US'
params['ieee80211ac'] = '1'
params['vht_oper_chwidth'] = '1'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
wait_acs(hapd)
freq = hapd.get_status_field("freq")
if int(freq) < 5000:
dev[0].request("DISCONNECT")
if hapd:
hapd.request("DISABLE")
- subprocess.call(['iw', 'reg', 'set', '00'])
+ hostapd.cmd_execute(apdev[0], ['iw', 'reg', 'set', '00'])
dev[0].flush_scan_cache()
def test_ap_acs_bias(dev, apdev):
params = hostapd.wpa2_params(ssid="test-acs", passphrase="12345678")
params['channel'] = '0'
params['acs_chan_bias'] = '1:0.8 3:1.2 6:0.7 11:0.8'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
wait_acs(hapd)
freq = hapd.get_status_field("freq")
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import time
import logging
logger = logging.getLogger()
"wpa": "2",
"wpa_key_mgmt": "WPA-PSK",
"rsn_pairwise": cipher }
- hapd = hostapd.add_ap(ap['ifname'], params)
+ hapd = hostapd.add_ap(ap, params)
dev.connect("test-wpa2-psk", psk="12345678",
pairwise=cipher, group=cipher, scan_freq="2412")
hwsim_utils.test_connectivity(dev, hapd)
def check_group_mgmt_cipher(dev, ap, cipher):
- wt = Wlantest()
- wt.flush()
- wt.add_passphrase("12345678")
-
if cipher not in dev.get_capability("group_mgmt"):
raise HwsimSkip("Cipher %s not supported" % cipher)
params = { "ssid": "test-wpa2-psk-pmf",
"wpa_key_mgmt": "WPA-PSK-SHA256",
"rsn_pairwise": "CCMP",
"group_mgmt_cipher": cipher }
- hapd = hostapd.add_ap(ap['ifname'], params)
+ hapd = hostapd.add_ap(ap, params)
+
+ Wlantest.setup(hapd)
+ wt = Wlantest()
+ wt.flush()
+ wt.add_passphrase("12345678")
+
dev.connect("test-wpa2-psk-pmf", psk="12345678", ieee80211w="2",
key_mgmt="WPA-PSK-SHA256",
pairwise="CCMP", group="CCMP", scan_freq="2412")
if res != group_mgmt:
raise Exception("Unexpected group mgmt cipher: " + res)
+@remote_compatible
def test_ap_cipher_tkip(dev, apdev):
"""WPA2-PSK/TKIP connection"""
skip_with_fips(dev[0])
check_cipher(dev[0], apdev[0], "TKIP")
+@remote_compatible
def test_ap_cipher_tkip_countermeasures_ap(dev, apdev):
"""WPA-PSK/TKIP countermeasures (detected by AP)"""
skip_with_fips(dev[0])
testfile = "/sys/kernel/debug/ieee80211/%s/netdev:%s/tkip_mic_test" % (dev[0].get_driver_status_field("phyname"), dev[0].ifname)
- if not os.path.exists(testfile):
+ if dev[0].cmd_execute([ "ls", testfile ])[0] != 0:
raise HwsimSkip("tkip_mic_test not supported in mac80211")
params = { "ssid": "tkip-countermeasures",
"wpa": "1",
"wpa_key_mgmt": "WPA-PSK",
"wpa_pairwise": "TKIP" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("tkip-countermeasures", psk="12345678",
pairwise="TKIP", group="TKIP", scan_freq="2412")
dev[0].dump_monitor()
- with open(testfile, "w") as f:
- f.write(apdev[0]['bssid'])
+ dev[0].cmd_execute([ "echo", "-n", apdev[0]['bssid'], ">", testfile ],
+ shell=True)
ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1)
if ev is not None:
raise Exception("Unexpected disconnection on first Michael MIC failure")
- with open(testfile, "w") as f:
- f.write("ff:ff:ff:ff:ff:ff")
+ dev[0].cmd_execute([ "echo", "-n", "ff:ff:ff:ff:ff:ff", ">", testfile ],
+ shell=True)
ev = dev[0].wait_disconnected(timeout=10,
error="No disconnection after two Michael MIC failures")
if "reason=14" not in ev:
if ev is not None:
raise Exception("Unexpected connection during TKIP countermeasures")
+@remote_compatible
def test_ap_cipher_tkip_countermeasures_sta(dev, apdev):
"""WPA-PSK/TKIP countermeasures (detected by STA)"""
skip_with_fips(dev[0])
"wpa": "1",
"wpa_key_mgmt": "WPA-PSK",
"wpa_pairwise": "TKIP" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
testfile = "/sys/kernel/debug/ieee80211/%s/netdev:%s/tkip_mic_test" % (hapd.get_driver_status_field("phyname"), apdev[0]['ifname'])
- if not os.path.exists(testfile):
+ if hapd.cmd_execute([ "ls", testfile ])[0] != 0:
raise HwsimSkip("tkip_mic_test not supported in mac80211")
dev[0].connect("tkip-countermeasures", psk="12345678",
pairwise="TKIP", group="TKIP", scan_freq="2412")
dev[0].dump_monitor()
- with open(testfile, "w") as f:
- f.write(dev[0].p2p_dev_addr())
+ hapd.cmd_execute([ "echo", "-n", dev[0].own_addr(), ">", testfile ],
+ shell=True)
ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1)
if ev is not None:
raise Exception("Unexpected disconnection on first Michael MIC failure")
- with open(testfile, "w") as f:
- f.write("ff:ff:ff:ff:ff:ff")
+ hapd.cmd_execute([ "echo", "-n", "ff:ff:ff:ff:ff:ff", ">", testfile ],
+ shell=True)
ev = dev[0].wait_disconnected(timeout=10,
error="No disconnection after two Michael MIC failures")
if "reason=14 locally_generated=1" not in ev:
if ev is not None:
raise Exception("Unexpected connection during TKIP countermeasures")
+@remote_compatible
def test_ap_cipher_ccmp(dev, apdev):
"""WPA2-PSK/CCMP connection"""
check_cipher(dev[0], apdev[0], "CCMP")
"""WPA2-PSK/GCMP-256 connection"""
check_cipher(dev[0], apdev[0], "GCMP-256")
+@remote_compatible
def test_ap_cipher_mixed_wpa_wpa2(dev, apdev):
"""WPA2-PSK/CCMP/ and WPA-PSK/TKIP mixed configuration"""
skip_with_fips(dev[0])
"wpa_key_mgmt": "WPA-PSK",
"rsn_pairwise": "CCMP",
"wpa_pairwise": "TKIP" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, proto="WPA2",
pairwise="CCMP", group="TKIP", scan_freq="2412")
status = dev[0].get_status()
hwsim_utils.test_connectivity(dev[1], hapd)
hwsim_utils.test_connectivity(dev[0], dev[1])
+@remote_compatible
def test_ap_cipher_bip(dev, apdev):
"""WPA2-PSK with BIP"""
check_group_mgmt_cipher(dev[0], apdev[0], "AES-128-CMAC")
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import hostapd
+@remote_compatible
def test_ap_config_errors(dev, apdev):
"""Various hostapd configuration errors"""
- hapd_global = hostapd.HostapdGlobal()
- ifname = apdev[0]['ifname']
# IEEE 802.11d without country code
params = { "ssid": "foo", "ieee80211d": "1" }
- hapd = hostapd.add_ap(ifname, params, no_enable=True)
+ hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
if "FAIL" not in hapd.request("ENABLE"):
raise Exception("Unexpected ENABLE success (ieee80211d without country_code)")
- hapd_global.remove(ifname)
+ hostapd.remove_bss(apdev[0])
# IEEE 802.11h without IEEE 802.11d
params = { "ssid": "foo", "ieee80211h": "1" }
- hapd = hostapd.add_ap(ifname, params, no_enable=True)
+ hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
if "FAIL" not in hapd.request("ENABLE"):
raise Exception("Unexpected ENABLE success (ieee80211h without ieee80211d")
- hapd_global.remove(ifname)
+ hostapd.remove_bss(apdev[0])
# Power Constraint without IEEE 802.11d
params = { "ssid": "foo", "local_pwr_constraint": "1" }
- hapd = hostapd.add_ap(ifname, params, no_enable=True)
+ hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
if "FAIL" not in hapd.request("ENABLE"):
raise Exception("Unexpected ENABLE success (local_pwr_constraint without ieee80211d)")
- hapd_global.remove(ifname)
+ hostapd.remove_bss(apdev[0])
# Spectrum management without Power Constraint
params = { "ssid": "foo", "spectrum_mgmt_required": "1" }
- hapd = hostapd.add_ap(ifname, params, no_enable=True)
+ hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
if "FAIL" not in hapd.request("ENABLE"):
raise Exception("Unexpected ENABLE success (spectrum_mgmt_required without local_pwr_constraint)")
- hapd_global.remove(ifname)
+ hostapd.remove_bss(apdev[0])
# IEEE 802.1X without authentication server
params = { "ssid": "foo", "ieee8021x": "1" }
- hapd = hostapd.add_ap(ifname, params, no_enable=True)
+ hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
if "FAIL" not in hapd.request("ENABLE"):
raise Exception("Unexpected ENABLE success (ieee8021x)")
- hapd_global.remove(ifname)
+ hostapd.remove_bss(apdev[0])
# RADIUS-PSK without macaddr_acl=2
params = hostapd.wpa2_params(ssid="foo", passphrase="12345678")
params["wpa_psk_radius"] = "1"
- hapd = hostapd.add_ap(ifname, params, no_enable=True)
+ hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
if "FAIL" not in hapd.request("ENABLE"):
raise Exception("Unexpected ENABLE success (wpa_psk_radius)")
- hapd_global.remove(ifname)
+ hostapd.remove_bss(apdev[0])
# FT without NAS-Identifier
params = { "wpa": "2",
"wpa_key_mgmt": "FT-PSK",
"rsn_pairwise": "CCMP",
"wpa_passphrase": "12345678" }
- hapd = hostapd.add_ap(ifname, params, no_enable=True)
+ hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
if "FAIL" not in hapd.request("ENABLE"):
raise Exception("Unexpected ENABLE success (FT without nas_identifier)")
- hapd_global.remove(ifname)
+ hostapd.remove_bss(apdev[0])
# Hotspot 2.0 without WPA2/CCMP
params = hostapd.wpa2_params(ssid="foo")
params['interworking'] = "1"
params['hs20'] = "1"
params['wpa'] = "1"
- hapd = hostapd.add_ap(ifname, params, no_enable=True)
+ hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
if "FAIL" not in hapd.request("ENABLE"):
raise Exception("Unexpected ENABLE success (HS 2.0 without WPA2/CCMP)")
- hapd_global.remove(ifname)
+ hostapd.remove_bss(apdev[0])
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import time
import logging
logger = logging.getLogger()
import hostapd
from utils import HwsimSkip
-def connect(dev, apdev):
+def connect(dev, apdev, **kwargs):
params = { "ssid": "ap-csa",
"channel": "1" }
- ap = hostapd.add_ap(apdev[0]['ifname'], params)
- dev.connect("ap-csa", key_mgmt="NONE")
+ params.update(kwargs)
+ ap = hostapd.add_ap(apdev[0], params)
+ dev.connect("ap-csa", key_mgmt="NONE", scan_freq="2412")
return ap
def switch_channel(ap, count, freq):
raise Exception("CSA finished event timed out")
if "freq=" + str(freq) not in ev:
raise Exception("Unexpected channel in CSA finished event")
- time.sleep(0.1)
+
+def wait_channel_switch(dev, freq):
+ ev = dev.wait_event(["CTRL-EVENT-CHANNEL-SWITCH"], timeout=5)
+ if ev is None:
+ raise Exception("Channel switch not reported")
+ if "freq=%d" % freq not in ev:
+ raise Exception("Unexpected frequency: " + ev)
# This function checks whether the provided dev, which may be either
# WpaSupplicant or Hostapd supports CSA.
if (int(res['capa.flags'], 0) & 0x80000000) == 0:
raise HwsimSkip("CSA not supported")
+@remote_compatible
def test_ap_csa_1_switch(dev, apdev):
"""AP Channel Switch, one switch"""
csa_supported(dev[0])
hwsim_utils.test_connectivity(dev[0], ap)
switch_channel(ap, 10, 2462)
+ wait_channel_switch(dev[0], 2462)
hwsim_utils.test_connectivity(dev[0], ap)
+@remote_compatible
def test_ap_csa_2_switches(dev, apdev):
"""AP Channel Switch, two switches"""
csa_supported(dev[0])
hwsim_utils.test_connectivity(dev[0], ap)
switch_channel(ap, 10, 2462)
+ wait_channel_switch(dev[0], 2462)
hwsim_utils.test_connectivity(dev[0], ap)
switch_channel(ap, 10, 2412)
+ wait_channel_switch(dev[0], 2412)
hwsim_utils.test_connectivity(dev[0], ap)
+@remote_compatible
def test_ap_csa_1_switch_count_0(dev, apdev):
"""AP Channel Switch, one switch with count 0"""
csa_supported(dev[0])
# this does not result in CSA currently, so do not bother checking
# connectivity
+@remote_compatible
def test_ap_csa_2_switches_count_0(dev, apdev):
"""AP Channel Switch, two switches with count 0"""
csa_supported(dev[0])
# this does not result in CSA currently, so do not bother checking
# connectivity
+@remote_compatible
def test_ap_csa_1_switch_count_1(dev, apdev):
"""AP Channel Switch, one switch with count 1"""
csa_supported(dev[0])
# this does not result in CSA currently, so do not bother checking
# connectivity
+@remote_compatible
def test_ap_csa_2_switches_count_1(dev, apdev):
"""AP Channel Switch, two switches with count 1"""
csa_supported(dev[0])
# this does not result in CSA currently, so do not bother checking
# connectivity
+@remote_compatible
def test_ap_csa_1_switch_count_2(dev, apdev):
"""AP Channel Switch, one switch with count 2"""
csa_supported(dev[0])
hwsim_utils.test_connectivity(dev[0], ap)
switch_channel(ap, 2, 2462)
+ wait_channel_switch(dev[0], 2462)
+ hwsim_utils.test_connectivity(dev[0], ap)
+
+@remote_compatible
+def test_ap_csa_ecsa_only(dev, apdev):
+ """AP Channel Switch, one switch with only ECSA IE"""
+ csa_supported(dev[0])
+ ap = connect(dev[0], apdev, ecsa_ie_only="1")
+
hwsim_utils.test_connectivity(dev[0], ap)
+ switch_channel(ap, 10, 2462)
+ wait_channel_switch(dev[0], 2462)
+ hwsim_utils.test_connectivity(dev[0], ap)
+
+@remote_compatible
+def test_ap_csa_invalid(dev, apdev):
+ """AP Channel Switch - invalid channel"""
+ csa_supported(dev[0])
+ ap = connect(dev[0], apdev)
+
+ vals = [ 2461, 4900, 4901, 5181, 5746, 5699, 5895, 5899 ]
+ for val in vals:
+ if "FAIL" not in ap.request("CHAN_SWITCH 1 %d" % val):
+ raise Exception("Invalid channel accepted: %d" % val)
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import time
import subprocess
import logging
import hwsim_utils
import hostapd
-from utils import alloc_fail
+from utils import alloc_fail, require_under_vm
from test_ap_acs import force_prev_ap_on_24g
+@remote_compatible
def test_ap_change_ssid(dev, apdev):
"""Dynamic SSID change with hostapd and WPA2-PSK"""
params = hostapd.wpa2_params(ssid="test-wpa2-psk-start",
passphrase="12345678")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
id = dev[0].connect("test-wpa2-psk-start", psk="12345678",
scan_freq="2412")
dev[0].request("DISCONNECT")
logger.info("Change SSID dynamically")
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
res = hapd.request("SET ssid test-wpa2-psk-new")
if "OK" not in res:
raise Exception("SET command failed")
def _test_ap_bss_add_remove(dev, apdev):
for i in range(3):
+ dev[i].flush_scan_cache()
dev[i].request("SCAN_INTERVAL 1")
ifname1 = apdev[0]['ifname']
ifname2 = apdev[0]['ifname'] + '-2'
ifname3 = apdev[0]['ifname'] + '-3'
logger.info("Set up three BSSes one by one")
- hostapd.add_bss('phy3', ifname1, 'bss-1.conf')
+ hostapd.add_bss(apdev[0], ifname1, 'bss-1.conf')
multi_check(dev, [ True, False, False ])
- hostapd.add_bss('phy3', ifname2, 'bss-2.conf')
+ hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf')
multi_check(dev, [ True, True, False ])
- hostapd.add_bss('phy3', ifname3, 'bss-3.conf')
+ hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf')
multi_check(dev, [ True, True, True ])
logger.info("Remove the last BSS and re-add it")
- hostapd.remove_bss(ifname3)
+ hostapd.remove_bss(apdev[0], ifname3)
multi_check(dev, [ True, True, False ])
- hostapd.add_bss('phy3', ifname3, 'bss-3.conf')
+ hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf')
multi_check(dev, [ True, True, True ])
logger.info("Remove the middle BSS and re-add it")
- hostapd.remove_bss(ifname2)
+ hostapd.remove_bss(apdev[0], ifname2)
multi_check(dev, [ True, False, True ])
- hostapd.add_bss('phy3', ifname2, 'bss-2.conf')
+ hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf')
multi_check(dev, [ True, True, True ])
logger.info("Remove the first BSS and re-add it and other BSSs")
- hostapd.remove_bss(ifname1)
+ hostapd.remove_bss(apdev[0], ifname1)
multi_check(dev, [ False, False, False ])
- hostapd.add_bss('phy3', ifname1, 'bss-1.conf')
- hostapd.add_bss('phy3', ifname2, 'bss-2.conf')
- hostapd.add_bss('phy3', ifname3, 'bss-3.conf')
+ hostapd.add_bss(apdev[0], ifname1, 'bss-1.conf')
+ hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf')
+ hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf')
multi_check(dev, [ True, True, True ])
logger.info("Remove two BSSes and re-add them")
- hostapd.remove_bss(ifname2)
+ hostapd.remove_bss(apdev[0], ifname2)
multi_check(dev, [ True, False, True ])
- hostapd.remove_bss(ifname3)
+ hostapd.remove_bss(apdev[0], ifname3)
multi_check(dev, [ True, False, False ])
- hostapd.add_bss('phy3', ifname2, 'bss-2.conf')
+ hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf')
multi_check(dev, [ True, True, False ])
- hostapd.add_bss('phy3', ifname3, 'bss-3.conf')
+ hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf')
multi_check(dev, [ True, True, True ])
logger.info("Remove three BSSes in and re-add them")
- hostapd.remove_bss(ifname3)
+ hostapd.remove_bss(apdev[0], ifname3)
multi_check(dev, [ True, True, False ])
- hostapd.remove_bss(ifname2)
+ hostapd.remove_bss(apdev[0], ifname2)
multi_check(dev, [ True, False, False ])
- hostapd.remove_bss(ifname1)
+ hostapd.remove_bss(apdev[0], ifname1)
multi_check(dev, [ False, False, False ])
- hostapd.add_bss('phy3', ifname1, 'bss-1.conf')
+ hostapd.add_bss(apdev[0], ifname1, 'bss-1.conf')
multi_check(dev, [ True, False, False ])
- hostapd.add_bss('phy3', ifname2, 'bss-2.conf')
+ hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf')
multi_check(dev, [ True, True, False ])
- hostapd.add_bss('phy3', ifname3, 'bss-3.conf')
+ hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf')
multi_check(dev, [ True, True, True ])
logger.info("Test error handling if a duplicate ifname is tried")
- hostapd.add_bss('phy3', ifname3, 'bss-3.conf', ignore_error=True)
+ hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf', ignore_error=True)
multi_check(dev, [ True, True, True ])
def test_ap_bss_add_remove_during_ht_scan(dev, apdev):
"""Dynamic BSS add during HT40 co-ex scan"""
+ for i in range(3):
+ dev[i].flush_scan_cache()
ifname1 = apdev[0]['ifname']
ifname2 = apdev[0]['ifname'] + '-2'
- hostapd.add_bss('phy3', ifname1, 'bss-ht40-1.conf')
- hostapd.add_bss('phy3', ifname2, 'bss-ht40-2.conf')
+ hostapd.add_bss(apdev[0], ifname1, 'bss-ht40-1.conf')
+ hostapd.add_bss(apdev[0], ifname2, 'bss-ht40-2.conf')
multi_check(dev, [ True, True ], scan_opt=False)
- hostapd.remove_bss(ifname2)
- hostapd.remove_bss(ifname1)
+ hostapd.remove_bss(apdev[0], ifname2)
+ hostapd.remove_bss(apdev[0], ifname1)
- hostapd.add_bss('phy3', ifname1, 'bss-ht40-1.conf')
- hostapd.add_bss('phy3', ifname2, 'bss-ht40-2.conf')
- hostapd.remove_bss(ifname2)
+ hostapd.add_bss(apdev[0], ifname1, 'bss-ht40-1.conf')
+ hostapd.add_bss(apdev[0], ifname2, 'bss-ht40-2.conf')
+ hostapd.remove_bss(apdev[0], ifname2)
multi_check(dev, [ True, False ], scan_opt=False)
- hostapd.remove_bss(ifname1)
+ hostapd.remove_bss(apdev[0], ifname1)
- hostapd.add_bss('phy3', ifname1, 'bss-ht40-1.conf')
- hostapd.add_bss('phy3', ifname2, 'bss-ht40-2.conf')
- hostapd.remove_bss(ifname1)
+ hostapd.add_bss(apdev[0], ifname1, 'bss-ht40-1.conf')
+ hostapd.add_bss(apdev[0], ifname2, 'bss-ht40-2.conf')
+ hostapd.remove_bss(apdev[0], ifname1)
multi_check(dev, [ False, False ])
def test_ap_multi_bss_config(dev, apdev):
"""hostapd start with a multi-BSS configuration file"""
+ for i in range(3):
+ dev[i].flush_scan_cache()
ifname1 = apdev[0]['ifname']
ifname2 = apdev[0]['ifname'] + '-2'
ifname3 = apdev[0]['ifname'] + '-3'
logger.info("Set up three BSSes with one configuration file")
- hostapd.add_iface(ifname1, 'multi-bss.conf')
- hapd = hostapd.Hostapd(ifname1)
+ hapd = hostapd.add_iface(apdev[0], 'multi-bss.conf')
hapd.enable()
multi_check(dev, [ True, True, True ])
- hostapd.remove_bss(ifname2)
+ hostapd.remove_bss(apdev[0], ifname2)
multi_check(dev, [ True, False, True ])
- hostapd.remove_bss(ifname3)
+ hostapd.remove_bss(apdev[0], ifname3)
multi_check(dev, [ True, False, False ])
- hostapd.remove_bss(ifname1)
+ hostapd.remove_bss(apdev[0], ifname1)
multi_check(dev, [ False, False, False ])
- hostapd.add_iface(ifname1, 'multi-bss.conf')
- hapd = hostapd.Hostapd(ifname1)
+ hapd = hostapd.add_iface(apdev[0], 'multi-bss.conf')
hapd.enable()
- hostapd.remove_bss(ifname1)
+ hostapd.remove_bss(apdev[0], ifname1)
multi_check(dev, [ False, False, False ])
-def invalid_ap(hapd_global, ifname):
- logger.info("Trying to start AP " + ifname + " with invalid configuration")
- hapd_global.remove(ifname)
- hapd_global.add(ifname)
- hapd = hostapd.Hostapd(ifname)
- if not hapd.ping():
- raise Exception("Could not ping hostapd")
- hapd.set_defaults()
+def invalid_ap(ap):
+ logger.info("Trying to start AP " + ap['ifname'] + " with invalid configuration")
+ hapd = hostapd.add_ap(ap, {}, no_enable=True)
hapd.set("ssid", "invalid-config")
hapd.set("channel", "12345")
try:
raise Exception("ENABLE command succeeded unexpectedly")
return hapd
+@remote_compatible
def test_ap_invalid_config(dev, apdev):
"""Try to start AP with invalid configuration and fix configuration"""
- hapd_global = hostapd.HostapdGlobal()
- ifname = apdev[0]['ifname']
- hapd = invalid_ap(hapd_global, ifname)
+ hapd = invalid_ap(apdev[0])
logger.info("Fix configuration and start AP again")
hapd.set("channel", "1")
hapd.enable()
dev[0].connect("invalid-config", key_mgmt="NONE", scan_freq="2412")
+@remote_compatible
def test_ap_invalid_config2(dev, apdev):
"""Try to start AP with invalid configuration and remove interface"""
- hapd_global = hostapd.HostapdGlobal()
- ifname = apdev[0]['ifname']
- hapd = invalid_ap(hapd_global, ifname)
+ hapd = invalid_ap(apdev[0])
logger.info("Remove interface with failed configuration")
- hapd_global.remove(ifname)
+ hostapd.remove_bss(apdev[0])
def test_ap_remove_during_acs(dev, apdev):
"""Remove interface during ACS"""
force_prev_ap_on_24g(apdev[0])
params = hostapd.wpa2_params(ssid="test-acs-remove", passphrase="12345678")
params['channel'] = '0'
- ifname = apdev[0]['ifname']
- hapd = hostapd.HostapdGlobal()
- hostapd.add_ap(ifname, params)
- hapd.remove(ifname)
+ hostapd.add_ap(apdev[0], params)
+ hostapd.remove_bss(apdev[0])
def test_ap_remove_during_acs2(dev, apdev):
"""Remove BSS during ACS in multi-BSS configuration"""
force_prev_ap_on_24g(apdev[0])
ifname = apdev[0]['ifname']
ifname2 = ifname + "-2"
- hapd_global = hostapd.HostapdGlobal()
- hapd_global.add(ifname)
- hapd = hostapd.Hostapd(ifname)
- hapd.set_defaults()
+ hapd = hostapd.add_ap(apdev[0], {}, no_enable=True)
hapd.set("ssid", "test-acs-remove")
hapd.set("channel", "0")
hapd.set("bss", ifname2)
hapd.set("ssid", "test-acs-remove2")
hapd.enable()
- hapd_global.remove(ifname)
+ hostapd.remove_bss(apdev[0])
def test_ap_remove_during_acs3(dev, apdev):
"""Remove second BSS during ACS in multi-BSS configuration"""
force_prev_ap_on_24g(apdev[0])
ifname = apdev[0]['ifname']
ifname2 = ifname + "-2"
- hapd_global = hostapd.HostapdGlobal()
- hapd_global.add(ifname)
- hapd = hostapd.Hostapd(ifname)
- hapd.set_defaults()
+ hapd = hostapd.add_ap(apdev[0], {}, no_enable=True)
hapd.set("ssid", "test-acs-remove")
hapd.set("channel", "0")
hapd.set("bss", ifname2)
hapd.set("ssid", "test-acs-remove2")
hapd.enable()
- hapd_global.remove(ifname2)
+ hostapd.remove_bss(apdev[0], ifname2)
+@remote_compatible
def test_ap_remove_during_ht_coex_scan(dev, apdev):
"""Remove interface during HT co-ex scan"""
params = hostapd.wpa2_params(ssid="test-ht-remove", passphrase="12345678")
params['channel'] = '1'
params['ht_capab'] = "[HT40+]"
ifname = apdev[0]['ifname']
- hapd = hostapd.HostapdGlobal()
- hostapd.add_ap(ifname, params)
- hapd.remove(ifname)
+ hostapd.add_ap(apdev[0], params)
+ hostapd.remove_bss(apdev[0])
def test_ap_remove_during_ht_coex_scan2(dev, apdev):
"""Remove BSS during HT co-ex scan in multi-BSS configuration"""
ifname = apdev[0]['ifname']
ifname2 = ifname + "-2"
- hapd_global = hostapd.HostapdGlobal()
- hapd_global.add(ifname)
- hapd = hostapd.Hostapd(ifname)
- hapd.set_defaults()
+ hapd = hostapd.add_ap(apdev[0], {}, no_enable=True)
hapd.set("ssid", "test-ht-remove")
hapd.set("channel", "1")
hapd.set("ht_capab", "[HT40+]")
hapd.set("bss", ifname2)
hapd.set("ssid", "test-ht-remove2")
hapd.enable()
- hapd_global.remove(ifname)
+ hostapd.remove_bss(apdev[0])
def test_ap_remove_during_ht_coex_scan3(dev, apdev):
"""Remove second BSS during HT co-ex scan in multi-BSS configuration"""
ifname = apdev[0]['ifname']
ifname2 = ifname + "-2"
- hapd_global = hostapd.HostapdGlobal()
- hapd_global.add(ifname)
- hapd = hostapd.Hostapd(ifname)
- hapd.set_defaults()
+ hapd = hostapd.add_ap(apdev[0], {}, no_enable=True)
hapd.set("ssid", "test-ht-remove")
hapd.set("channel", "1")
hapd.set("ht_capab", "[HT40+]")
hapd.set("bss", ifname2)
hapd.set("ssid", "test-ht-remove2")
hapd.enable()
- hapd_global.remove(ifname2)
+ hostapd.remove_bss(apdev[0], ifname2)
+@remote_compatible
def test_ap_enable_disable_reenable(dev, apdev):
"""Enable, disable, re-enable AP"""
- ifname = apdev[0]['ifname']
- hapd_global = hostapd.HostapdGlobal()
- hapd_global.add(ifname)
- hapd = hostapd.Hostapd(ifname)
- hapd.set_defaults()
+ hapd = hostapd.add_ap(apdev[0], {}, no_enable=True)
hapd.set("ssid", "dynamic")
hapd.enable()
ev = hapd.wait_event(["AP-ENABLED"], timeout=30)
def test_ap_double_disable(dev, apdev):
"""Double DISABLE regression test"""
- hostapd.add_bss('phy3', apdev[0]['ifname'], 'bss-1.conf')
- hostapd.add_bss('phy3', apdev[0]['ifname'] + '-2', 'bss-2.conf')
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_bss(apdev[0], apdev[0]['ifname'], 'bss-1.conf')
+ hostapd.add_bss(apdev[0], apdev[0]['ifname'] + '-2', 'bss-2.conf')
hapd.disable()
if "FAIL" not in hapd.request("DISABLE"):
raise Exception("Second DISABLE accepted unexpectedly")
finally:
dev[0].request("SCAN_INTERVAL 5")
ifname = apdev[0]['ifname']
- hapd = hostapd.HostapdGlobal()
+ hapd = hostapd.HostapdGlobal(apdev[0])
hapd.flush()
for i in range(16):
ifname2 = ifname + '-' + str(i)
def _test_ap_bss_add_many(dev, apdev):
ifname = apdev[0]['ifname']
- phy = 'phy3'
- hostapd.add_bss(phy, ifname, 'bss-1.conf')
- hapd = hostapd.HostapdGlobal()
+ hostapd.add_bss(apdev[0], ifname, 'bss-1.conf')
fname = '/tmp/hwsim-bss.conf'
for i in range(16):
ifname2 = ifname + '-' + str(i)
f.write("bssid=02:00:00:00:03:%02x\n" % (i + 1))
f.write("ctrl_interface=/var/run/hostapd\n")
f.write("ssid=test-%d\n" % i)
- hostapd.add_bss(phy, ifname2, fname)
+ hostapd.add_bss(apdev[0], ifname2, fname)
os.remove(fname)
dev[0].request("SCAN_INTERVAL 1")
dev[0].request("DISCONNECT")
dev[0].wait_disconnected(timeout=5)
ifname2 = ifname + '-' + str(i)
- hapd.remove(ifname2)
+ hostapd.remove_bss(apdev[0], ifname2)
def test_ap_bss_add_reuse_existing(dev, apdev):
"""Dynamic BSS add operation reusing existing interface"""
ifname1 = apdev[0]['ifname']
ifname2 = apdev[0]['ifname'] + '-2'
- hostapd.add_bss('phy3', ifname1, 'bss-1.conf')
+ hostapd.add_bss(apdev[0], ifname1, 'bss-1.conf')
subprocess.check_call(["iw", "dev", ifname1, "interface", "add", ifname2,
"type", "__ap"])
- hostapd.add_bss('phy3', ifname2, 'bss-2.conf')
- hostapd.remove_bss(ifname2)
+ hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf')
+ hostapd.remove_bss(apdev[0], ifname2)
subprocess.check_call(["iw", "dev", ifname2, "del"])
def hapd_bss_out_of_mem(hapd, phy, confname, count, func):
def test_ap_bss_add_out_of_memory(dev, apdev):
"""Running out of memory while adding a BSS"""
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], { "ssid": "open" })
+ hapd2 = hostapd.add_ap(apdev[1], { "ssid": "open" })
ifname1 = apdev[0]['ifname']
ifname2 = apdev[0]['ifname'] + '-2'
hapd_bss_out_of_mem(hapd2, 'phy3', 'bss-1.conf',
1, 'ieee802_11_build_ap_params')
- hostapd.add_bss('phy3', ifname1, 'bss-1.conf')
+ hostapd.add_bss(apdev[0], ifname1, 'bss-1.conf')
hapd_bss_out_of_mem(hapd2, 'phy3', 'bss-2.conf',
1, 'hostapd_interface_init_bss')
hapd_bss_out_of_mem(hapd2, 'phy3', 'bss-2.conf',
1, 'ieee802_11_build_ap_params')
- hostapd.add_bss('phy3', ifname2, 'bss-2.conf')
- hostapd.remove_bss(ifname2)
- hostapd.remove_bss(ifname1)
+ hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf')
+ hostapd.remove_bss(apdev[0], ifname2)
+ hostapd.remove_bss(apdev[0], ifname1)
def test_ap_multi_bss(dev, apdev):
"""Multiple BSSes with hostapd"""
ifname1 = apdev[0]['ifname']
ifname2 = apdev[0]['ifname'] + '-2'
- hostapd.add_bss('phy3', ifname1, 'bss-1.conf')
- hostapd.add_bss('phy3', ifname2, 'bss-2.conf')
+ hapd1 = hostapd.add_bss(apdev[0], ifname1, 'bss-1.conf')
+ hapd2 = hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf')
dev[0].connect("bss-1", key_mgmt="NONE", scan_freq="2412")
dev[1].connect("bss-2", key_mgmt="NONE", scan_freq="2412")
- hapd1 = hostapd.Hostapd(ifname1)
- hapd2 = hostapd.Hostapd(ifname2)
-
hwsim_utils.test_connectivity(dev[0], hapd1)
hwsim_utils.test_connectivity(dev[1], hapd2)
if 'rx_packets' not in sta1 or int(sta1['rx_packets']) < 1:
raise Exception("sta1 did not report receiving packets")
+@remote_compatible
def test_ap_add_with_driver(dev, apdev):
"""Add hostapd interface with driver specified"""
ifname = apdev[0]['ifname']
- hapd_global = hostapd.HostapdGlobal()
+ try:
+ hostname = apdev[0]['hostname']
+ except:
+ hostname = None
+ hapd_global = hostapd.HostapdGlobal(apdev[0])
hapd_global.add(ifname, driver="nl80211")
- hapd = hostapd.Hostapd(ifname)
+ port = hapd_global.get_ctrl_iface_port(ifname)
+ hapd = hostapd.Hostapd(ifname, hostname, port)
hapd.set_defaults()
hapd.set("ssid", "dynamic")
hapd.enable()
dev[0].request("DISCONNECT")
dev[0].wait_disconnected()
hapd.disable()
+
+def test_ap_iapp(dev, apdev):
+ """IAPP and multiple BSSes"""
+ require_under_vm()
+ try:
+ _test_ap_iapp(dev, apdev)
+ finally:
+ subprocess.call(['ifconfig', 'br-multicast', 'down'],
+ stderr=open('/dev/null', 'w'))
+ subprocess.call(['brctl', 'delbr', 'br-multicast'],
+ stderr=open('/dev/null', 'w'))
+
+def _test_ap_iapp(dev, apdev):
+ br_ifname = 'br-multicast'
+ subprocess.call(['brctl', 'addbr', br_ifname])
+ subprocess.call(['brctl', 'setfd', br_ifname, '0'])
+ subprocess.call(['ip', 'addr', 'add', '10.174.65.206/31', 'dev', br_ifname])
+ subprocess.call(['ip', 'link', 'set', 'dev', br_ifname, 'up'])
+ subprocess.call(['ip', 'route', 'add', '224.0.0.0/4', 'dev', br_ifname])
+
+ params = { "ssid": "test-1",
+ "bridge": br_ifname,
+ "iapp_interface": br_ifname }
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
+ dev[0].connect("test-1", key_mgmt="NONE", scan_freq="2412")
+ dev[1].connect("test-1", key_mgmt="NONE", scan_freq="2412")
+
+ hapd2 = hostapd.add_ap(apdev[1], params)
+ dev[0].scan_for_bss(apdev[1]['bssid'], freq=2412)
+ dev[0].roam(apdev[1]['bssid'])
+ dev[0].roam(apdev[0]['bssid'])
+
+ dev[0].request("DISCONNECT")
+ dev[1].request("DISCONNECT")
+ dev[0].wait_disconnected()
+ dev[1].wait_disconnected()
+
+ hapd.disable()
+ hapd2.disable()
import logging
logger = logging.getLogger()
import os
+import socket
+import SocketServer
+import struct
+import tempfile
import hwsim_utils
import hostapd
-from utils import HwsimSkip, alloc_fail, fail_test, skip_with_fips
+from utils import HwsimSkip, alloc_fail, fail_test, skip_with_fips, wait_fail_trigger
from wpasupplicant import WpaSupplicant
-from test_ap_psk import check_mib, find_wpas_process, read_process_memory, verify_not_present, get_key_locations
+from test_ap_psk import check_mib, find_wpas_process, read_process_memory, verify_not_present, get_key_locations, set_test_assoc_ie
+
+try:
+ import OpenSSL
+ openssl_imported = True
+except ImportError:
+ openssl_imported = False
def check_hlr_auc_gw_support():
if not os.path.exists("/tmp/hlr_auc_gw.sock"):
if not tls.startswith("OpenSSL"):
raise HwsimSkip("altsubject_match not supported with this TLS library: " + tls)
+def check_domain_match(dev):
+ tls = dev.request("GET tls_library")
+ if tls.startswith("internal"):
+ raise HwsimSkip("domain_match not supported with this TLS library: " + tls)
+
+def check_domain_suffix_match(dev):
+ tls = dev.request("GET tls_library")
+ if tls.startswith("internal"):
+ raise HwsimSkip("domain_suffix_match not supported with this TLS library: " + tls)
+
def check_domain_match_full(dev):
tls = dev.request("GET tls_library")
if not tls.startswith("OpenSSL"):
def check_cert_probe_support(dev):
tls = dev.request("GET tls_library")
- if not tls.startswith("OpenSSL"):
+ if not tls.startswith("OpenSSL") and not tls.startswith("internal"):
raise HwsimSkip("Certificate probing not supported with this TLS library: " + tls)
+def check_ext_cert_check_support(dev):
+ tls = dev.request("GET tls_library")
+ if not tls.startswith("OpenSSL"):
+ raise HwsimSkip("ext_cert_check not supported with this TLS library: " + tls)
+
def check_ocsp_support(dev):
tls = dev.request("GET tls_library")
- if "BoringSSL" in tls:
- raise HwsimSkip("OCSP not supported with this TLS library: " + tls)
+ #if tls.startswith("internal"):
+ # raise HwsimSkip("OCSP not supported with this TLS library: " + tls)
+ #if "BoringSSL" in tls:
+ # raise HwsimSkip("OCSP not supported with this TLS library: " + tls)
+
+def check_ocsp_multi_support(dev):
+ tls = dev.request("GET tls_library")
+ if not tls.startswith("internal"):
+ raise HwsimSkip("OCSP-multi not supported with this TLS library: " + tls)
+ as_hapd = hostapd.Hostapd("as")
+ res = as_hapd.request("GET tls_library")
+ del as_hapd
+ if not res.startswith("internal"):
+ raise HwsimSkip("Authentication server does not support ocsp_multi")
+
+def check_pkcs12_support(dev):
+ tls = dev.request("GET tls_library")
+ #if tls.startswith("internal"):
+ # raise HwsimSkip("PKCS#12 not supported with this TLS library: " + tls)
+
+def check_dh_dsa_support(dev):
+ tls = dev.request("GET tls_library")
+ if tls.startswith("internal"):
+ raise HwsimSkip("DH DSA not supported with this TLS library: " + tls)
def read_pem(fname):
with open(fname, "r") as f:
copy = True
return base64.b64decode(cert)
-def eap_connect(dev, ap, method, identity,
+def eap_connect(dev, hapd, method, identity,
sha256=False, expect_failure=False, local_error_report=False,
maybe_local_error=False, **kwargs):
- hapd = hostapd.Hostapd(ap['ifname'])
id = dev.connect("test-wpa2-eap", key_mgmt="WPA-EAP WPA-EAP-SHA256",
eap=method, identity=identity,
wait_connect=False, scan_freq="2412", ieee80211w="1",
def eap_check_auth(dev, method, initial, rsn=True, sha256=False,
expect_failure=False, local_error_report=False,
maybe_local_error=False):
- ev = dev.wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=10)
+ ev = dev.wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=16)
if ev is None:
raise Exception("Association and EAP start timed out")
ev = dev.wait_event(["CTRL-EVENT-EAP-METHOD",
if status["suppPortStatus"] != "Authorized":
raise Exception("Port not authorized")
+ if "selectedMethod" not in status:
+ logger.info("Status: " + str(status))
+ raise Exception("No selectedMethod in status")
if method not in status["selectedMethod"]:
raise Exception("Incorrect EAP method status")
if sha256:
"""WPA2-Enterprise connection using EAP-SIM"""
check_hlr_auc_gw_support()
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "SIM", "1232010000000000",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "SIM", "1232010000000000",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
hwsim_utils.test_connectivity(dev[0], hapd)
eap_reauth(dev[0], "SIM")
- eap_connect(dev[1], apdev[0], "SIM", "1232010000000001",
+ eap_connect(dev[1], hapd, "SIM", "1232010000000001",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
- eap_connect(dev[2], apdev[0], "SIM", "1232010000000002",
+ eap_connect(dev[2], hapd, "SIM", "1232010000000002",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
expect_failure=True)
logger.info("Negative test with incorrect key")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "SIM", "1232010000000000",
+ eap_connect(dev[0], hapd, "SIM", "1232010000000000",
password="ffdca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
expect_failure=True)
logger.info("Invalid GSM-Milenage key")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "SIM", "1232010000000000",
+ eap_connect(dev[0], hapd, "SIM", "1232010000000000",
password="ffdca4eda45b53cf0f12d7c9c3bc6a",
expect_failure=True)
logger.info("Invalid GSM-Milenage key(2)")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "SIM", "1232010000000000",
+ eap_connect(dev[0], hapd, "SIM", "1232010000000000",
password="ffdca4eda45b53cf0f12d7c9c3bc6a8q:cb9cccc4b9258e6dca4760379fb82581",
expect_failure=True)
logger.info("Invalid GSM-Milenage key(3)")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "SIM", "1232010000000000",
+ eap_connect(dev[0], hapd, "SIM", "1232010000000000",
password="ffdca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb8258q",
expect_failure=True)
logger.info("Invalid GSM-Milenage key(4)")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "SIM", "1232010000000000",
+ eap_connect(dev[0], hapd, "SIM", "1232010000000000",
password="ffdca4eda45b53cf0f12d7c9c3bc6a89qcb9cccc4b9258e6dca4760379fb82581",
expect_failure=True)
logger.info("Missing key configuration")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "SIM", "1232010000000000",
+ eap_connect(dev[0], hapd, "SIM", "1232010000000000",
expect_failure=True)
def test_ap_wpa2_eap_sim_sql(dev, apdev, params):
con = sqlite3.connect(os.path.join(params['logdir'], "hostapd.db"))
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
params['auth_server_port'] = "1814"
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "SIM", "1232010000000000",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "SIM", "1232010000000000",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
logger.info("SIM fast re-authentication")
eap_reauth(dev[0], "SIM", expect_failure=True)
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "SIM", "1232010000000000",
+ eap_connect(dev[0], hapd, "SIM", "1232010000000000",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
with con:
cur = con.cursor()
eap_reauth(dev[0], "SIM")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "SIM", "1232010000000000",
+ eap_connect(dev[0], hapd, "SIM", "1232010000000000",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
with con:
cur = con.cursor()
def test_ap_wpa2_eap_sim_config(dev, apdev):
"""EAP-SIM configuration options"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="SIM",
identity="1232010000000000",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
raise Exception("No EAP error message seen (2)")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "SIM", "1232010000000000",
+ eap_connect(dev[0], hapd, "SIM", "1232010000000000",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
phase1="sim_min_num_chal=2")
- eap_connect(dev[1], apdev[0], "SIM", "1232010000000000",
+ eap_connect(dev[1], hapd, "SIM", "1232010000000000",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
anonymous_identity="345678")
def _test_ap_wpa2_eap_sim_ext(dev, apdev):
check_hlr_auc_gw_support()
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].request("SET external_sim 1")
id = dev[0].connect("test-wpa2-eap", eap="SIM", key_mgmt="WPA-EAP",
identity="1232010000000000",
if ev is None:
raise Exception("EAP failure not reported")
+def test_ap_wpa2_eap_sim_ext_replace_sim(dev, apdev):
+ """EAP-SIM with external GSM auth and replacing SIM without clearing pseudonym id"""
+ try:
+ _test_ap_wpa2_eap_sim_ext_replace_sim(dev, apdev)
+ finally:
+ dev[0].request("SET external_sim 0")
+
+def _test_ap_wpa2_eap_sim_ext_replace_sim(dev, apdev):
+ check_hlr_auc_gw_support()
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hostapd.add_ap(apdev[0], params)
+ dev[0].request("SET external_sim 1")
+ id = dev[0].connect("test-wpa2-eap", eap="SIM", key_mgmt="WPA-EAP",
+ identity="1232010000000000",
+ wait_connect=False, scan_freq="2412")
+
+ ev = dev[0].wait_event(["CTRL-REQ-SIM"], timeout=15)
+ if ev is None:
+ raise Exception("Wait for external SIM processing request timed out")
+ p = ev.split(':', 2)
+ if p[1] != "GSM-AUTH":
+ raise Exception("Unexpected CTRL-REQ-SIM type")
+ rid = p[0].split('-')[3]
+ rand = p[2].split(' ')[0]
+
+ res = subprocess.check_output(["../../hostapd/hlr_auc_gw",
+ "-m",
+ "auth_serv/hlr_auc_gw.milenage_db",
+ "GSM-AUTH-REQ 232010000000000 " + rand])
+ if "GSM-AUTH-RESP" not in res:
+ raise Exception("Unexpected hlr_auc_gw response")
+ resp = res.split(' ')[2].rstrip()
+
+ dev[0].request("CTRL-RSP-SIM-" + rid + ":GSM-AUTH:" + resp)
+ dev[0].wait_connected(timeout=15)
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected()
+
+ # Replace SIM, but forget to drop the previous pseudonym identity
+ dev[0].set_network_quoted(id, "identity", "1232010000000009")
+ dev[0].select_network(id, freq="2412")
+
+ ev = dev[0].wait_event(["CTRL-REQ-SIM"], timeout=15)
+ if ev is None:
+ raise Exception("Wait for external SIM processing request timed out")
+ p = ev.split(':', 2)
+ if p[1] != "GSM-AUTH":
+ raise Exception("Unexpected CTRL-REQ-SIM type")
+ rid = p[0].split('-')[3]
+ rand = p[2].split(' ')[0]
+
+ res = subprocess.check_output(["../../hostapd/hlr_auc_gw",
+ "-m",
+ "auth_serv/hlr_auc_gw.milenage_db",
+ "GSM-AUTH-REQ 232010000000009 " + rand])
+ if "GSM-AUTH-RESP" not in res:
+ raise Exception("Unexpected hlr_auc_gw response")
+ resp = res.split(' ')[2].rstrip()
+
+ dev[0].request("CTRL-RSP-SIM-" + rid + ":GSM-AUTH:" + resp)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=15)
+ if ev is None:
+ raise Exception("EAP-Failure not reported")
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected()
+
+def test_ap_wpa2_eap_sim_ext_replace_sim2(dev, apdev):
+ """EAP-SIM with external GSM auth and replacing SIM and clearing pseudonym identity"""
+ try:
+ _test_ap_wpa2_eap_sim_ext_replace_sim2(dev, apdev)
+ finally:
+ dev[0].request("SET external_sim 0")
+
+def _test_ap_wpa2_eap_sim_ext_replace_sim2(dev, apdev):
+ check_hlr_auc_gw_support()
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hostapd.add_ap(apdev[0], params)
+ dev[0].request("SET external_sim 1")
+ id = dev[0].connect("test-wpa2-eap", eap="SIM", key_mgmt="WPA-EAP",
+ identity="1232010000000000",
+ wait_connect=False, scan_freq="2412")
+
+ ev = dev[0].wait_event(["CTRL-REQ-SIM"], timeout=15)
+ if ev is None:
+ raise Exception("Wait for external SIM processing request timed out")
+ p = ev.split(':', 2)
+ if p[1] != "GSM-AUTH":
+ raise Exception("Unexpected CTRL-REQ-SIM type")
+ rid = p[0].split('-')[3]
+ rand = p[2].split(' ')[0]
+
+ res = subprocess.check_output(["../../hostapd/hlr_auc_gw",
+ "-m",
+ "auth_serv/hlr_auc_gw.milenage_db",
+ "GSM-AUTH-REQ 232010000000000 " + rand])
+ if "GSM-AUTH-RESP" not in res:
+ raise Exception("Unexpected hlr_auc_gw response")
+ resp = res.split(' ')[2].rstrip()
+
+ dev[0].request("CTRL-RSP-SIM-" + rid + ":GSM-AUTH:" + resp)
+ dev[0].wait_connected(timeout=15)
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected()
+
+ # Replace SIM and drop the previous pseudonym identity
+ dev[0].set_network_quoted(id, "identity", "1232010000000009")
+ dev[0].set_network(id, "anonymous_identity", "NULL")
+ dev[0].select_network(id, freq="2412")
+
+ ev = dev[0].wait_event(["CTRL-REQ-SIM"], timeout=15)
+ if ev is None:
+ raise Exception("Wait for external SIM processing request timed out")
+ p = ev.split(':', 2)
+ if p[1] != "GSM-AUTH":
+ raise Exception("Unexpected CTRL-REQ-SIM type")
+ rid = p[0].split('-')[3]
+ rand = p[2].split(' ')[0]
+
+ res = subprocess.check_output(["../../hostapd/hlr_auc_gw",
+ "-m",
+ "auth_serv/hlr_auc_gw.milenage_db",
+ "GSM-AUTH-REQ 232010000000009 " + rand])
+ if "GSM-AUTH-RESP" not in res:
+ raise Exception("Unexpected hlr_auc_gw response")
+ resp = res.split(' ')[2].rstrip()
+
+ dev[0].request("CTRL-RSP-SIM-" + rid + ":GSM-AUTH:" + resp)
+ dev[0].wait_connected()
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected()
+
+def test_ap_wpa2_eap_sim_ext_replace_sim3(dev, apdev):
+ """EAP-SIM with external GSM auth, replacing SIM, and no identity in config"""
+ try:
+ _test_ap_wpa2_eap_sim_ext_replace_sim3(dev, apdev)
+ finally:
+ dev[0].request("SET external_sim 0")
+
+def _test_ap_wpa2_eap_sim_ext_replace_sim3(dev, apdev):
+ check_hlr_auc_gw_support()
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hostapd.add_ap(apdev[0], params)
+ dev[0].request("SET external_sim 1")
+ id = dev[0].connect("test-wpa2-eap", eap="SIM", key_mgmt="WPA-EAP",
+ wait_connect=False, scan_freq="2412")
+
+ ev = dev[0].wait_event(["CTRL-REQ-IDENTITY"])
+ if ev is None:
+ raise Exception("Request for identity timed out")
+ rid = ev.split(':')[0].split('-')[-1]
+ dev[0].request("CTRL-RSP-IDENTITY-" + rid + ":1232010000000000")
+
+ ev = dev[0].wait_event(["CTRL-REQ-SIM"], timeout=15)
+ if ev is None:
+ raise Exception("Wait for external SIM processing request timed out")
+ p = ev.split(':', 2)
+ if p[1] != "GSM-AUTH":
+ raise Exception("Unexpected CTRL-REQ-SIM type")
+ rid = p[0].split('-')[3]
+ rand = p[2].split(' ')[0]
+
+ res = subprocess.check_output(["../../hostapd/hlr_auc_gw",
+ "-m",
+ "auth_serv/hlr_auc_gw.milenage_db",
+ "GSM-AUTH-REQ 232010000000000 " + rand])
+ if "GSM-AUTH-RESP" not in res:
+ raise Exception("Unexpected hlr_auc_gw response")
+ resp = res.split(' ')[2].rstrip()
+
+ dev[0].request("CTRL-RSP-SIM-" + rid + ":GSM-AUTH:" + resp)
+ dev[0].wait_connected(timeout=15)
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected()
+
+ # Replace SIM and drop the previous permanent and pseudonym identities
+ dev[0].set_network(id, "identity", "NULL")
+ dev[0].set_network(id, "anonymous_identity", "NULL")
+ dev[0].select_network(id, freq="2412")
+
+ ev = dev[0].wait_event(["CTRL-REQ-IDENTITY"])
+ if ev is None:
+ raise Exception("Request for identity timed out")
+ rid = ev.split(':')[0].split('-')[-1]
+ dev[0].request("CTRL-RSP-IDENTITY-" + rid + ":1232010000000009")
+
+ ev = dev[0].wait_event(["CTRL-REQ-SIM"], timeout=15)
+ if ev is None:
+ raise Exception("Wait for external SIM processing request timed out")
+ p = ev.split(':', 2)
+ if p[1] != "GSM-AUTH":
+ raise Exception("Unexpected CTRL-REQ-SIM type")
+ rid = p[0].split('-')[3]
+ rand = p[2].split(' ')[0]
+
+ res = subprocess.check_output(["../../hostapd/hlr_auc_gw",
+ "-m",
+ "auth_serv/hlr_auc_gw.milenage_db",
+ "GSM-AUTH-REQ 232010000000009 " + rand])
+ if "GSM-AUTH-RESP" not in res:
+ raise Exception("Unexpected hlr_auc_gw response")
+ resp = res.split(' ')[2].rstrip()
+
+ dev[0].request("CTRL-RSP-SIM-" + rid + ":GSM-AUTH:" + resp)
+ dev[0].wait_connected()
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected()
+
+def test_ap_wpa2_eap_sim_ext_auth_fail(dev, apdev):
+ """EAP-SIM with external GSM auth and auth failing"""
+ try:
+ _test_ap_wpa2_eap_sim_ext_auth_fail(dev, apdev)
+ finally:
+ dev[0].request("SET external_sim 0")
+
+def _test_ap_wpa2_eap_sim_ext_auth_fail(dev, apdev):
+ check_hlr_auc_gw_support()
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hostapd.add_ap(apdev[0], params)
+ dev[0].request("SET external_sim 1")
+ id = dev[0].connect("test-wpa2-eap", eap="SIM", key_mgmt="WPA-EAP",
+ identity="1232010000000000",
+ wait_connect=False, scan_freq="2412")
+
+ ev = dev[0].wait_event(["CTRL-REQ-SIM"], timeout=15)
+ if ev is None:
+ raise Exception("Wait for external SIM processing request timed out")
+ p = ev.split(':', 2)
+ rid = p[0].split('-')[3]
+ dev[0].request("CTRL-RSP-SIM-" + rid + ":GSM-FAIL")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
+ if ev is None:
+ raise Exception("EAP failure not reported")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+def test_ap_wpa2_eap_sim_change_bssid(dev, apdev):
+ """EAP-SIM and external GSM auth to check fast reauth with bssid change"""
+ try:
+ _test_ap_wpa2_eap_sim_change_bssid(dev, apdev)
+ finally:
+ dev[0].request("SET external_sim 0")
+
+def _test_ap_wpa2_eap_sim_change_bssid(dev, apdev):
+ check_hlr_auc_gw_support()
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hostapd.add_ap(apdev[0], params)
+ dev[0].request("SET external_sim 1")
+ id = dev[0].connect("test-wpa2-eap", eap="SIM", key_mgmt="WPA-EAP",
+ identity="1232010000000000",
+ wait_connect=False, scan_freq="2412")
+
+ ev = dev[0].wait_event(["CTRL-REQ-SIM"], timeout=15)
+ if ev is None:
+ raise Exception("Wait for external SIM processing request timed out")
+ p = ev.split(':', 2)
+ if p[1] != "GSM-AUTH":
+ raise Exception("Unexpected CTRL-REQ-SIM type")
+ rid = p[0].split('-')[3]
+ rand = p[2].split(' ')[0]
+
+ res = subprocess.check_output(["../../hostapd/hlr_auc_gw",
+ "-m",
+ "auth_serv/hlr_auc_gw.milenage_db",
+ "GSM-AUTH-REQ 232010000000000 " + rand])
+ if "GSM-AUTH-RESP" not in res:
+ raise Exception("Unexpected hlr_auc_gw response")
+ resp = res.split(' ')[2].rstrip()
+
+ dev[0].request("CTRL-RSP-SIM-" + rid + ":GSM-AUTH:" + resp)
+ dev[0].wait_connected(timeout=15)
+
+ # Verify that EAP-SIM Reauthentication can be used after a profile change
+ # that does not affect EAP parameters.
+ dev[0].set_network(id, "bssid", "any")
+ eap_reauth(dev[0], "SIM")
+
+def test_ap_wpa2_eap_sim_no_change_set(dev, apdev):
+ """EAP-SIM and external GSM auth to check fast reauth with no-change SET_NETWORK"""
+ try:
+ _test_ap_wpa2_eap_sim_no_change_set(dev, apdev)
+ finally:
+ dev[0].request("SET external_sim 0")
+
+def _test_ap_wpa2_eap_sim_no_change_set(dev, apdev):
+ check_hlr_auc_gw_support()
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hostapd.add_ap(apdev[0], params)
+ dev[0].request("SET external_sim 1")
+ id = dev[0].connect("test-wpa2-eap", eap="SIM", key_mgmt="WPA-EAP",
+ identity="1232010000000000",
+ wait_connect=False, scan_freq="2412")
+
+ ev = dev[0].wait_event(["CTRL-REQ-SIM"], timeout=15)
+ if ev is None:
+ raise Exception("Wait for external SIM processing request timed out")
+ p = ev.split(':', 2)
+ if p[1] != "GSM-AUTH":
+ raise Exception("Unexpected CTRL-REQ-SIM type")
+ rid = p[0].split('-')[3]
+ rand = p[2].split(' ')[0]
+
+ res = subprocess.check_output(["../../hostapd/hlr_auc_gw",
+ "-m",
+ "auth_serv/hlr_auc_gw.milenage_db",
+ "GSM-AUTH-REQ 232010000000000 " + rand])
+ if "GSM-AUTH-RESP" not in res:
+ raise Exception("Unexpected hlr_auc_gw response")
+ resp = res.split(' ')[2].rstrip()
+
+ dev[0].request("CTRL-RSP-SIM-" + rid + ":GSM-AUTH:" + resp)
+ dev[0].wait_connected(timeout=15)
+
+ # Verify that EAP-SIM Reauthentication can be used after network profile
+ # SET_NETWORK commands that do not actually change previously set
+ # parameter values.
+ dev[0].set_network(id, "key_mgmt", "WPA-EAP")
+ dev[0].set_network(id, "eap", "SIM")
+ dev[0].set_network_quoted(id, "identity", "1232010000000000")
+ dev[0].set_network_quoted(id, "ssid", "test-wpa2-eap")
+ eap_reauth(dev[0], "SIM")
+
def test_ap_wpa2_eap_sim_oom(dev, apdev):
"""EAP-SIM and OOM"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
tests = [ (1, "milenage_f2345"),
(2, "milenage_f2345"),
(3, "milenage_f2345"),
(11, "milenage_f2345"),
(12, "milenage_f2345") ]
for count, func in tests:
- with alloc_fail(dev[0], count, func):
+ with fail_test(dev[0], count, func):
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="SIM",
identity="1232010000000000",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
"""WPA2-Enterprise connection using EAP-AKA"""
check_hlr_auc_gw_support()
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "AKA", "0232010000000000",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "AKA", "0232010000000000",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123")
hwsim_utils.test_connectivity(dev[0], hapd)
eap_reauth(dev[0], "AKA")
logger.info("Negative test with incorrect key")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "AKA", "0232010000000000",
+ eap_connect(dev[0], hapd, "AKA", "0232010000000000",
password="ffdca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123",
expect_failure=True)
logger.info("Invalid Milenage key")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "AKA", "0232010000000000",
+ eap_connect(dev[0], hapd, "AKA", "0232010000000000",
password="ffdca4eda45b53cf0f12d7c9c3bc6a",
expect_failure=True)
logger.info("Invalid Milenage key(2)")
- eap_connect(dev[0], apdev[0], "AKA", "0232010000000000",
+ eap_connect(dev[0], hapd, "AKA", "0232010000000000",
password="ffdca4eda45b53cf0f12d7c9c3bc6a8q:cb9cccc4b9258e6dca4760379fb82581:000000000123",
expect_failure=True)
logger.info("Invalid Milenage key(3)")
- eap_connect(dev[0], apdev[0], "AKA", "0232010000000000",
+ eap_connect(dev[0], hapd, "AKA", "0232010000000000",
password="ffdca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb8258q:000000000123",
expect_failure=True)
logger.info("Invalid Milenage key(4)")
- eap_connect(dev[0], apdev[0], "AKA", "0232010000000000",
+ eap_connect(dev[0], hapd, "AKA", "0232010000000000",
password="ffdca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:00000000012q",
expect_failure=True)
logger.info("Invalid Milenage key(5)")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "AKA", "0232010000000000",
+ eap_connect(dev[0], hapd, "AKA", "0232010000000000",
password="ffdca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581q000000000123",
expect_failure=True)
logger.info("Invalid Milenage key(6)")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "AKA", "0232010000000000",
+ eap_connect(dev[0], hapd, "AKA", "0232010000000000",
password="ffdca4eda45b53cf0f12d7c9c3bc6a89qcb9cccc4b9258e6dca4760379fb82581q000000000123",
expect_failure=True)
logger.info("Missing key configuration")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "AKA", "0232010000000000",
+ eap_connect(dev[0], hapd, "AKA", "0232010000000000",
expect_failure=True)
def test_ap_wpa2_eap_aka_sql(dev, apdev, params):
con = sqlite3.connect(os.path.join(params['logdir'], "hostapd.db"))
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
params['auth_server_port'] = "1814"
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "AKA", "0232010000000000",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "AKA", "0232010000000000",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123")
logger.info("AKA fast re-authentication")
eap_reauth(dev[0], "AKA", expect_failure=True)
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "AKA", "0232010000000000",
+ eap_connect(dev[0], hapd, "AKA", "0232010000000000",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123")
with con:
cur = con.cursor()
eap_reauth(dev[0], "AKA")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "AKA", "0232010000000000",
+ eap_connect(dev[0], hapd, "AKA", "0232010000000000",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123")
with con:
cur = con.cursor()
def test_ap_wpa2_eap_aka_config(dev, apdev):
"""EAP-AKA configuration options"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "AKA", "0232010000000000",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "AKA", "0232010000000000",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123",
anonymous_identity="2345678")
def _test_ap_wpa2_eap_aka_ext(dev, apdev):
check_hlr_auc_gw_support()
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].request("SET external_sim 1")
id = dev[0].connect("test-wpa2-eap", eap="AKA", key_mgmt="WPA-EAP",
identity="0232010000000000",
dev[0].request("DISCONNECT")
dev[0].wait_disconnected()
time.sleep(0.1)
+ dev[0].dump_monitor()
dev[0].select_network(id, freq="2412")
ev = dev[0].wait_event(["CTRL-REQ-SIM"], timeout=15)
dev[0].request("DISCONNECT")
dev[0].wait_disconnected()
time.sleep(0.1)
+ dev[0].dump_monitor()
tests = [ ":UMTS-AUTH:00112233445566778899aabbccddeeff:00112233445566778899aabbccddeeff:0011223344",
":UMTS-AUTH:34",
dev[0].request("DISCONNECT")
dev[0].wait_disconnected()
time.sleep(0.1)
+ dev[0].dump_monitor()
+
+def test_ap_wpa2_eap_aka_ext_auth_fail(dev, apdev):
+ """EAP-AKA with external UMTS auth and auth failing"""
+ try:
+ _test_ap_wpa2_eap_aka_ext_auth_fail(dev, apdev)
+ finally:
+ dev[0].request("SET external_sim 0")
+
+def _test_ap_wpa2_eap_aka_ext_auth_fail(dev, apdev):
+ check_hlr_auc_gw_support()
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hostapd.add_ap(apdev[0], params)
+ dev[0].request("SET external_sim 1")
+ id = dev[0].connect("test-wpa2-eap", eap="AKA", key_mgmt="WPA-EAP",
+ identity="0232010000000000",
+ wait_connect=False, scan_freq="2412")
+
+ ev = dev[0].wait_event(["CTRL-REQ-SIM"], timeout=15)
+ if ev is None:
+ raise Exception("Wait for external SIM processing request timed out")
+ p = ev.split(':', 2)
+ rid = p[0].split('-')[3]
+ dev[0].request("CTRL-RSP-SIM-" + rid + ":UMTS-FAIL")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
+ if ev is None:
+ raise Exception("EAP failure not reported")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
def test_ap_wpa2_eap_aka_prime(dev, apdev):
"""WPA2-Enterprise connection using EAP-AKA'"""
check_hlr_auc_gw_support()
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "AKA'", "6555444333222111",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "AKA'", "6555444333222111",
password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123")
hwsim_utils.test_connectivity(dev[0], hapd)
eap_reauth(dev[0], "AKA'")
logger.info("Negative test with incorrect key")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "AKA'", "6555444333222111",
+ eap_connect(dev[0], hapd, "AKA'", "6555444333222111",
password="ff22250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123",
expect_failure=True)
con = sqlite3.connect(os.path.join(params['logdir'], "hostapd.db"))
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
params['auth_server_port'] = "1814"
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "AKA'", "6555444333222111",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "AKA'", "6555444333222111",
password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123")
logger.info("AKA' fast re-authentication")
eap_reauth(dev[0], "AKA'", expect_failure=True)
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "AKA'", "6555444333222111",
+ eap_connect(dev[0], hapd, "AKA'", "6555444333222111",
password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123")
with con:
cur = con.cursor()
eap_reauth(dev[0], "AKA'")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "AKA'", "6555444333222111",
+ eap_connect(dev[0], hapd, "AKA'", "6555444333222111",
password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123")
with con:
cur = con.cursor()
logger.info("AKA' reauth with max reauth count reached")
eap_reauth(dev[0], "AKA'")
+def test_ap_wpa2_eap_aka_prime_ext_auth_fail(dev, apdev):
+ """EAP-AKA' with external UMTS auth and auth failing"""
+ try:
+ _test_ap_wpa2_eap_aka_prime_ext_auth_fail(dev, apdev)
+ finally:
+ dev[0].request("SET external_sim 0")
+
+def _test_ap_wpa2_eap_aka_prime_ext_auth_fail(dev, apdev):
+ check_hlr_auc_gw_support()
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hostapd.add_ap(apdev[0], params)
+ dev[0].request("SET external_sim 1")
+ id = dev[0].connect("test-wpa2-eap", eap="AKA'", key_mgmt="WPA-EAP",
+ identity="6555444333222111",
+ wait_connect=False, scan_freq="2412")
+
+ ev = dev[0].wait_event(["CTRL-REQ-SIM"], timeout=15)
+ if ev is None:
+ raise Exception("Wait for external SIM processing request timed out")
+ p = ev.split(':', 2)
+ rid = p[0].split('-')[3]
+ dev[0].request("CTRL-RSP-SIM-" + rid + ":UMTS-FAIL")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
+ if ev is None:
+ raise Exception("EAP failure not reported")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
def test_ap_wpa2_eap_ttls_pap(dev, apdev):
"""WPA2-Enterprise connection using EAP-TTLS/PAP"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
key_mgmt = hapd.get_config()['key_mgmt']
if key_mgmt.split(' ')[0] != "WPA-EAP":
raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
- eap_connect(dev[0], apdev[0], "TTLS", "pap user",
+ eap_connect(dev[0], hapd, "TTLS", "pap user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=PAP")
hwsim_utils.test_connectivity(dev[0], hapd)
check_subject_match_support(dev[0])
check_altsubject_match_support(dev[0])
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "pap user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "pap user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
subject_match="/C=FI/O=w1.fi/CN=server.w1.fi",
def test_ap_wpa2_eap_ttls_pap_incorrect_password(dev, apdev):
"""WPA2-Enterprise connection using EAP-TTLS/PAP - incorrect password"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "pap user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "pap user",
anonymous_identity="ttls", password="wrong",
ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
expect_failure=True)
- eap_connect(dev[1], apdev[0], "TTLS", "user",
+ eap_connect(dev[1], hapd, "TTLS", "user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
expect_failure=True)
"""WPA2-Enterprise connection using EAP-TTLS/CHAP"""
skip_with_fips(dev[0])
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "chap user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "chap user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.der", phase2="auth=CHAP")
hwsim_utils.test_connectivity(dev[0], hapd)
skip_with_fips(dev[0])
check_altsubject_match_support(dev[0])
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "chap user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "chap user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.der", phase2="auth=CHAP",
altsubject_match="EMAIL:noone@example.com;URI:http://example.com/;DNS:server.w1.fi")
"""WPA2-Enterprise connection using EAP-TTLS/CHAP - incorrect password"""
skip_with_fips(dev[0])
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "chap user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "chap user",
anonymous_identity="ttls", password="wrong",
ca_cert="auth_serv/ca.pem", phase2="auth=CHAP",
expect_failure=True)
- eap_connect(dev[1], apdev[0], "TTLS", "user",
+ eap_connect(dev[1], hapd, "TTLS", "user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=CHAP",
expect_failure=True)
def test_ap_wpa2_eap_ttls_mschap(dev, apdev):
"""WPA2-Enterprise connection using EAP-TTLS/MSCHAP"""
skip_with_fips(dev[0])
+ check_domain_suffix_match(dev[0])
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "mschap user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "mschap user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAP",
domain_suffix_match="server.w1.fi")
hwsim_utils.test_connectivity(dev[0], hapd)
eap_reauth(dev[0], "TTLS")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "TTLS", "mschap user",
+ eap_connect(dev[0], hapd, "TTLS", "mschap user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAP",
fragment_size="200")
-
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ eap_connect(dev[0], hapd, "TTLS", "mschap user",
+ anonymous_identity="ttls",
+ password_hex="hash:8846f7eaee8fb117ad06bdd830b7586c",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAP")
+
def test_ap_wpa2_eap_ttls_mschap_incorrect_password(dev, apdev):
"""WPA2-Enterprise connection using EAP-TTLS/MSCHAP - incorrect password"""
skip_with_fips(dev[0])
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "mschap user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "mschap user",
anonymous_identity="ttls", password="wrong",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAP",
expect_failure=True)
- eap_connect(dev[1], apdev[0], "TTLS", "user",
+ eap_connect(dev[1], hapd, "TTLS", "user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAP",
expect_failure=True)
- eap_connect(dev[2], apdev[0], "TTLS", "no such user",
+ eap_connect(dev[2], hapd, "TTLS", "no such user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAP",
expect_failure=True)
def test_ap_wpa2_eap_ttls_mschapv2(dev, apdev):
"""WPA2-Enterprise connection using EAP-TTLS/MSCHAPv2"""
+ check_domain_suffix_match(dev[0])
check_eap_capa(dev[0], "MSCHAPV2")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
- eap_connect(dev[0], apdev[0], "TTLS", "DOMAIN\mschapv2 user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "DOMAIN\mschapv2 user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
domain_suffix_match="server.w1.fi")
logger.info("Password as hash value")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "TTLS", "DOMAIN\mschapv2 user",
+ eap_connect(dev[0], hapd, "TTLS", "DOMAIN\mschapv2 user",
anonymous_identity="ttls",
password_hex="hash:8846f7eaee8fb117ad06bdd830b7586c",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2")
+def test_ap_wpa2_eap_ttls_invalid_phase2(dev, apdev):
+ """EAP-TTLS with invalid phase2 parameter values"""
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hostapd.add_ap(apdev[0], params)
+ tests = [ "auth=MSCHAPv2", "auth=MSCHAPV2 autheap=MD5",
+ "autheap=MD5 auth=MSCHAPV2", "auth=PAP auth=CHAP",
+ "autheap=MD5 autheap=FOO autheap=MSCHAPV2" ]
+ for t in tests:
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
+ identity="DOMAIN\mschapv2 user",
+ anonymous_identity="ttls", password="password",
+ ca_cert="auth_serv/ca.pem", phase2=t,
+ wait_connect=False, scan_freq="2412")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=10)
+ if ev is None or "method=21" not in ev:
+ raise Exception("EAP-TTLS not started")
+ ev = dev[0].wait_event(["EAP: Failed to initialize EAP method",
+ "CTRL-EVENT-CONNECTED"], timeout=5)
+ if ev is None or "CTRL-EVENT-CONNECTED" in ev:
+ raise Exception("No EAP-TTLS failure reported for phase2=" + t)
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ dev[0].dump_monitor()
+
def test_ap_wpa2_eap_ttls_mschapv2_suffix_match(dev, apdev):
"""WPA2-Enterprise connection using EAP-TTLS/MSCHAPv2"""
check_domain_match_full(dev[0])
skip_with_fips(dev[0])
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
- eap_connect(dev[0], apdev[0], "TTLS", "DOMAIN\mschapv2 user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "DOMAIN\mschapv2 user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
domain_suffix_match="w1.fi")
def test_ap_wpa2_eap_ttls_mschapv2_domain_match(dev, apdev):
"""WPA2-Enterprise connection using EAP-TTLS/MSCHAPv2 (domain_match)"""
+ check_domain_match(dev[0])
skip_with_fips(dev[0])
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
- eap_connect(dev[0], apdev[0], "TTLS", "DOMAIN\mschapv2 user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "DOMAIN\mschapv2 user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
domain_match="Server.w1.fi")
"""WPA2-Enterprise connection using EAP-TTLS/MSCHAPv2 - incorrect password"""
skip_with_fips(dev[0])
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "DOMAIN\mschapv2 user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "DOMAIN\mschapv2 user",
anonymous_identity="ttls", password="password1",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
expect_failure=True)
- eap_connect(dev[1], apdev[0], "TTLS", "user",
+ eap_connect(dev[1], hapd, "TTLS", "user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
expect_failure=True)
"""WPA2-Enterprise connection using EAP-TTLS/MSCHAPv2 and UTF-8 password"""
skip_with_fips(dev[0])
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
- eap_connect(dev[0], apdev[0], "TTLS", "utf8-user-hash",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "utf8-user-hash",
anonymous_identity="ttls", password="secret-åäö-€-password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2")
- eap_connect(dev[1], apdev[0], "TTLS", "utf8-user",
+ eap_connect(dev[1], hapd, "TTLS", "utf8-user",
anonymous_identity="ttls",
password_hex="hash:bd5844fad2489992da7fe8c5a01559cf",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2")
+ for p in [ "80", "41c041e04141e041", 257*"41" ]:
+ dev[2].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
+ eap="TTLS", identity="utf8-user-hash",
+ anonymous_identity="ttls", password_hex=p,
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ wait_connect=False, scan_freq="2412")
+ ev = dev[2].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=1)
+ if ev is None:
+ raise Exception("No failure reported")
+ dev[2].request("REMOVE_NETWORK all")
+ dev[2].wait_disconnected()
def test_ap_wpa2_eap_ttls_eap_gtc(dev, apdev):
"""WPA2-Enterprise connection using EAP-TTLS/EAP-GTC"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="autheap=GTC")
hwsim_utils.test_connectivity(dev[0], hapd)
def test_ap_wpa2_eap_ttls_eap_gtc_incorrect_password(dev, apdev):
"""WPA2-Enterprise connection using EAP-TTLS/EAP-GTC - incorrect password"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "user",
anonymous_identity="ttls", password="wrong",
ca_cert="auth_serv/ca.pem", phase2="autheap=GTC",
expect_failure=True)
def test_ap_wpa2_eap_ttls_eap_gtc_no_password(dev, apdev):
"""WPA2-Enterprise connection using EAP-TTLS/EAP-GTC - no password"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "user-no-passwd",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "user-no-passwd",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="autheap=GTC",
expect_failure=True)
def test_ap_wpa2_eap_ttls_eap_gtc_server_oom(dev, apdev):
"""WPA2-Enterprise connection using EAP-TTLS/EAP-GTC - server OOM"""
params = int_eap_server_params()
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
with alloc_fail(hapd, 1, "eap_gtc_init"):
- eap_connect(dev[0], apdev[0], "TTLS", "user",
+ eap_connect(dev[0], hapd, "TTLS", "user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="autheap=GTC",
expect_failure=True)
if hapd.request("GET_ALLOC_FAIL").startswith('0'):
break
+def test_ap_wpa2_eap_ttls_eap_gtc_oom(dev, apdev):
+ """WPA2-Enterprise connection using EAP-TTLS/EAP-GTC (OOM)"""
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ tests = [ "eap_gtc_init",
+ "eap_msg_alloc;eap_gtc_process" ]
+ for func in tests:
+ with alloc_fail(dev[0], 1, func):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
+ scan_freq="2412",
+ eap="TTLS", identity="user",
+ anonymous_identity="ttls", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="autheap=GTC",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
def test_ap_wpa2_eap_ttls_eap_md5(dev, apdev):
"""WPA2-Enterprise connection using EAP-TTLS/EAP-MD5"""
check_eap_capa(dev[0], "MD5")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="autheap=MD5")
hwsim_utils.test_connectivity(dev[0], hapd)
"""WPA2-Enterprise connection using EAP-TTLS/EAP-MD5 - incorrect password"""
check_eap_capa(dev[0], "MD5")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "user",
anonymous_identity="ttls", password="wrong",
ca_cert="auth_serv/ca.pem", phase2="autheap=MD5",
expect_failure=True)
"""WPA2-Enterprise connection using EAP-TTLS/EAP-MD5 - no password"""
check_eap_capa(dev[0], "MD5")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "user-no-passwd",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "user-no-passwd",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="autheap=MD5",
expect_failure=True)
"""WPA2-Enterprise connection using EAP-TTLS/EAP-MD5 - server OOM"""
check_eap_capa(dev[0], "MD5")
params = int_eap_server_params()
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
with alloc_fail(hapd, 1, "eap_md5_init"):
- eap_connect(dev[0], apdev[0], "TTLS", "user",
+ eap_connect(dev[0], hapd, "TTLS", "user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="autheap=MD5",
expect_failure=True)
"""WPA2-Enterprise connection using EAP-TTLS/EAP-MSCHAPv2"""
check_eap_capa(dev[0], "MSCHAPV2")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="autheap=MSCHAPV2")
hwsim_utils.test_connectivity(dev[0], hapd)
logger.info("Negative test with incorrect password")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "TTLS", "user",
+ eap_connect(dev[0], hapd, "TTLS", "user",
anonymous_identity="ttls", password="password1",
ca_cert="auth_serv/ca.pem", phase2="autheap=MSCHAPV2",
expect_failure=True)
"""WPA2-Enterprise connection using EAP-TTLS/EAP-MSCHAPv2 - no password"""
check_eap_capa(dev[0], "MSCHAPV2")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "user-no-passwd",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "user-no-passwd",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="autheap=MSCHAPV2",
expect_failure=True)
"""WPA2-Enterprise connection using EAP-TTLS/EAP-MSCHAPv2 - server OOM"""
check_eap_capa(dev[0], "MSCHAPV2")
params = int_eap_server_params()
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
with alloc_fail(hapd, 1, "eap_mschapv2_init"):
- eap_connect(dev[0], apdev[0], "TTLS", "user",
+ eap_connect(dev[0], hapd, "TTLS", "user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="autheap=MSCHAPV2",
expect_failure=True)
def test_ap_wpa2_eap_ttls_eap_aka(dev, apdev):
"""WPA2-Enterprise connection using EAP-TTLS/EAP-AKA"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "0232010000000000",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "0232010000000000",
anonymous_identity="0232010000000000@ttls",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123",
ca_cert="auth_serv/ca.pem", phase2="autheap=AKA")
def test_ap_wpa2_eap_peap_eap_aka(dev, apdev):
"""WPA2-Enterprise connection using EAP-PEAP/EAP-AKA"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "PEAP", "0232010000000000",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "PEAP", "0232010000000000",
anonymous_identity="0232010000000000@peap",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123",
ca_cert="auth_serv/ca.pem", phase2="auth=AKA")
"""WPA2-Enterprise connection using EAP-FAST/EAP-AKA"""
check_eap_capa(dev[0], "FAST")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "FAST", "0232010000000000",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "FAST", "0232010000000000",
anonymous_identity="0232010000000000@fast",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123",
phase1="fast_provisioning=2",
"""WPA2-Enterprise connection using EAP-PEAP/EAP-MSCHAPv2"""
check_eap_capa(dev[0], "MSCHAPV2")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "PEAP", "user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "PEAP", "user",
anonymous_identity="peap", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2")
hwsim_utils.test_connectivity(dev[0], hapd)
eap_reauth(dev[0], "PEAP")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "PEAP", "user",
+ eap_connect(dev[0], hapd, "PEAP", "user",
anonymous_identity="peap", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
fragment_size="200")
logger.info("Password as hash value")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "PEAP", "user",
+ eap_connect(dev[0], hapd, "PEAP", "user",
anonymous_identity="peap",
password_hex="hash:8846f7eaee8fb117ad06bdd830b7586c",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2")
logger.info("Negative test with incorrect password")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "PEAP", "user",
+ eap_connect(dev[0], hapd, "PEAP", "user",
anonymous_identity="peap", password="password1",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
expect_failure=True)
"""WPA2-Enterprise connection using EAP-PEAP/EAP-MSCHAPv2 with domain"""
check_eap_capa(dev[0], "MSCHAPV2")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "PEAP", "DOMAIN\user3",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "PEAP", "DOMAIN\user3",
anonymous_identity="peap", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2")
hwsim_utils.test_connectivity(dev[0], hapd)
"""WPA2-Enterprise connection using EAP-PEAP/EAP-MSCHAPv2 - incorrect password"""
check_eap_capa(dev[0], "MSCHAPV2")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "PEAP", "user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "PEAP", "user",
anonymous_identity="peap", password="wrong",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
expect_failure=True)
"""WPA2-Enterprise connection using EAP-PEAPv0/EAP-MSCHAPv2 and crypto binding"""
check_eap_capa(dev[0], "MSCHAPV2")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "PEAP", "user", password="password",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "PEAP", "user", password="password",
ca_cert="auth_serv/ca.pem",
phase1="peapver=0 crypto_binding=2",
phase2="auth=MSCHAPV2")
hwsim_utils.test_connectivity(dev[0], hapd)
eap_reauth(dev[0], "PEAP")
- eap_connect(dev[1], apdev[0], "PEAP", "user", password="password",
+ eap_connect(dev[1], hapd, "PEAP", "user", password="password",
ca_cert="auth_serv/ca.pem",
phase1="peapver=0 crypto_binding=1",
phase2="auth=MSCHAPV2")
- eap_connect(dev[2], apdev[0], "PEAP", "user", password="password",
+ eap_connect(dev[2], hapd, "PEAP", "user", password="password",
ca_cert="auth_serv/ca.pem",
phase1="peapver=0 crypto_binding=0",
phase2="auth=MSCHAPV2")
"""WPA2-Enterprise connection using EAP-PEAPv0/EAP-MSCHAPv2 and crypto binding with server OOM"""
check_eap_capa(dev[0], "MSCHAPV2")
params = int_eap_server_params()
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
with alloc_fail(hapd, 1, "eap_mschapv2_getKey"):
- eap_connect(dev[0], apdev[0], "PEAP", "user", password="password",
+ eap_connect(dev[0], hapd, "PEAP", "user", password="password",
ca_cert="auth_serv/ca.pem",
phase1="peapver=0 crypto_binding=2",
phase2="auth=MSCHAPV2",
"""WPA2-Enterprise connection using EAP-PEAPv0/EAP-MSCHAPv2 and various parameters"""
check_eap_capa(dev[0], "MSCHAPV2")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "PEAP", "user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "PEAP", "user",
anonymous_identity="peap", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
phase1="peapver=0 peaplabel=1",
expect_failure=True)
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[1], apdev[0], "PEAP", "user", password="password",
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="PEAP",
+ identity="user",
+ anonymous_identity="peap", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ phase1="peap_outer_success=0",
+ wait_connect=False, scan_freq="2412")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
+ if ev is None:
+ raise Exception("No EAP success seen")
+ # This won't succeed to connect with peap_outer_success=0, so stop here.
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ eap_connect(dev[1], hapd, "PEAP", "user", password="password",
ca_cert="auth_serv/ca.pem",
phase1="peap_outer_success=1",
phase2="auth=MSCHAPV2")
- eap_connect(dev[2], apdev[0], "PEAP", "user", password="password",
+ eap_connect(dev[2], hapd, "PEAP", "user", password="password",
ca_cert="auth_serv/ca.pem",
phase1="peap_outer_success=2",
phase2="auth=MSCHAPV2")
if ev is not None:
raise Exception("Unexpected connection")
+ tests = [ ("peap-ver0", ""),
+ ("peap-ver1", ""),
+ ("peap-ver0", "peapver=0"),
+ ("peap-ver1", "peapver=1") ]
+ for anon,phase1 in tests:
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="PEAP",
+ identity="user", anonymous_identity=anon,
+ password="password", phase1=phase1,
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ scan_freq="2412")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ ("peap-ver0", "peapver=1"),
+ ("peap-ver1", "peapver=0") ]
+ for anon,phase1 in tests:
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="PEAP",
+ identity="user", anonymous_identity=anon,
+ password="password", phase1=phase1,
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ wait_connect=False, scan_freq="2412")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=15)
+ if ev is None:
+ raise Exception("No EAP-Failure seen")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ eap_connect(dev[0], hapd, "PEAP", "user", password="password",
+ ca_cert="auth_serv/ca.pem",
+ phase1="tls_allow_md5=1 tls_disable_session_ticket=1 tls_disable_tlsv1_0=0 tls_disable_tlsv1_1=0 tls_disable_tlsv1_2=0 tls_ext_cert_check=0",
+ phase2="auth=MSCHAPV2")
+
def test_ap_wpa2_eap_peap_eap_tls(dev, apdev):
"""WPA2-Enterprise connection using EAP-PEAP/EAP-TLS"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "PEAP", "cert user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "PEAP", "cert user",
ca_cert="auth_serv/ca.pem", phase2="auth=TLS",
ca_cert2="auth_serv/ca.pem",
client_cert2="auth_serv/user.pem",
def test_ap_wpa2_eap_tls(dev, apdev):
"""WPA2-Enterprise connection using EAP-TLS"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TLS", "tls user", ca_cert="auth_serv/ca.pem",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TLS", "tls user", ca_cert="auth_serv/ca.pem",
client_cert="auth_serv/user.pem",
private_key="auth_serv/user.key")
eap_reauth(dev[0], "TLS")
+def test_eap_tls_pkcs8_pkcs5_v2_des3(dev, apdev):
+ """WPA2-Enterprise connection using EAP-TLS and PKCS #8, PKCS #5 v2 DES3 key"""
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TLS", "tls user", ca_cert="auth_serv/ca.pem",
+ client_cert="auth_serv/user.pem",
+ private_key="auth_serv/user.key.pkcs8",
+ private_key_passwd="whatever")
+
+def test_eap_tls_pkcs8_pkcs5_v15(dev, apdev):
+ """WPA2-Enterprise connection using EAP-TLS and PKCS #8, PKCS #5 v1.5 key"""
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TLS", "tls user", ca_cert="auth_serv/ca.pem",
+ client_cert="auth_serv/user.pem",
+ private_key="auth_serv/user.key.pkcs8.pkcs5v15",
+ private_key_passwd="whatever")
+
def test_ap_wpa2_eap_tls_blob(dev, apdev):
"""WPA2-Enterprise connection using EAP-TLS and config blobs"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
cert = read_pem("auth_serv/ca.pem")
if "OK" not in dev[0].request("SET blob cacert " + cert.encode("hex")):
raise Exception("Could not set cacert blob")
key = read_pem("auth_serv/user.rsa-key")
if "OK" not in dev[0].request("SET blob userkey " + key.encode("hex")):
raise Exception("Could not set cacert blob")
- eap_connect(dev[0], apdev[0], "TLS", "tls user", ca_cert="blob://cacert",
+ eap_connect(dev[0], hapd, "TLS", "tls user", ca_cert="blob://cacert",
client_cert="blob://usercert",
private_key="blob://userkey")
+def test_ap_wpa2_eap_tls_blob_missing(dev, apdev):
+ """EAP-TLS and config blob missing"""
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hostapd.add_ap(apdev[0], params)
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
+ identity="tls user",
+ ca_cert="blob://testing-blob-does-not-exist",
+ client_cert="blob://testing-blob-does-not-exist",
+ private_key="blob://testing-blob-does-not-exist",
+ wait_connect=False, scan_freq="2412")
+ ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"], timeout=10)
+ if ev is None:
+ raise Exception("EAP failure not reported")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+def test_ap_wpa2_eap_tls_with_tls_len(dev, apdev):
+ """EAP-TLS and TLS Message Length in unfragmented packets"""
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TLS", "tls user", ca_cert="auth_serv/ca.pem",
+ phase1="include_tls_length=1",
+ client_cert="auth_serv/user.pem",
+ private_key="auth_serv/user.key")
+
def test_ap_wpa2_eap_tls_pkcs12(dev, apdev):
"""WPA2-Enterprise connection using EAP-TLS and PKCS#12"""
+ check_pkcs12_support(dev[0])
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TLS", "tls user", ca_cert="auth_serv/ca.pem",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TLS", "tls user", ca_cert="auth_serv/ca.pem",
private_key="auth_serv/user.pkcs12",
private_key_passwd="whatever")
dev[0].request("REMOVE_NETWORK all")
# client certificate.
for pkcs12 in "auth_serv/user2.pkcs12", "auth_serv/user3.pkcs12":
for i in range(2):
- eap_connect(dev[0], apdev[0], "TLS", "tls user",
+ eap_connect(dev[0], hapd, "TLS", "tls user",
ca_cert="auth_serv/ca.pem",
private_key=pkcs12,
private_key_passwd="whatever")
def test_ap_wpa2_eap_tls_pkcs12_blob(dev, apdev):
"""WPA2-Enterprise connection using EAP-TLS and PKCS#12 from configuration blob"""
+ check_pkcs12_support(dev[0])
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
cert = read_pem("auth_serv/ca.pem")
if "OK" not in dev[0].request("SET blob cacert " + cert.encode("hex")):
raise Exception("Could not set cacert blob")
with open("auth_serv/user.pkcs12", "rb") as f:
if "OK" not in dev[0].request("SET blob pkcs12 " + f.read().encode("hex")):
raise Exception("Could not set pkcs12 blob")
- eap_connect(dev[0], apdev[0], "TLS", "tls user", ca_cert="blob://cacert",
+ eap_connect(dev[0], hapd, "TLS", "tls user", ca_cert="blob://cacert",
private_key="blob://pkcs12",
private_key_passwd="whatever")
"""WPA2-Enterprise negative test - incorrect trust root"""
check_eap_capa(dev[0], "MSCHAPV2")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
cert = read_pem("auth_serv/ca-incorrect.pem")
if "OK" not in dev[0].request("SET blob cacert " + cert.encode("hex")):
raise Exception("Could not set cacert blob")
wait_connect=False, scan_freq="2412")
for dev in (dev[0], dev[1]):
- ev = dev.wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=10)
+ ev = dev.wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=16)
if ev is None:
raise Exception("Association and EAP start timed out")
def test_ap_wpa2_eap_tls_diff_ca_trust(dev, apdev):
"""WPA2-Enterprise connection using EAP-TTLS/PAP and different CA trust"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="pap user", anonymous_identity="ttls",
password="password", phase2="auth=PAP",
def test_ap_wpa2_eap_tls_diff_ca_trust2(dev, apdev):
"""WPA2-Enterprise connection using EAP-TTLS/PAP and different CA trust"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="pap user", anonymous_identity="ttls",
password="password", phase2="auth=PAP",
def test_ap_wpa2_eap_tls_diff_ca_trust3(dev, apdev):
"""WPA2-Enterprise connection using EAP-TTLS/PAP and different CA trust"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="pap user", anonymous_identity="ttls",
password="password", phase2="auth=PAP",
def test_ap_wpa2_eap_tls_neg_suffix_match(dev, apdev):
"""WPA2-Enterprise negative test - domain suffix mismatch"""
+ check_domain_suffix_match(dev[0])
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="DOMAIN\mschapv2 user", anonymous_identity="ttls",
password="password", phase2="auth=MSCHAPV2",
domain_suffix_match="incorrect.example.com",
wait_connect=False, scan_freq="2412")
- ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=10)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=16)
if ev is None:
raise Exception("Association and EAP start timed out")
def test_ap_wpa2_eap_tls_neg_domain_match(dev, apdev):
"""WPA2-Enterprise negative test - domain mismatch"""
+ check_domain_match(dev[0])
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="DOMAIN\mschapv2 user", anonymous_identity="ttls",
password="password", phase2="auth=MSCHAPV2",
domain_match="w1.fi",
wait_connect=False, scan_freq="2412")
- ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=10)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=16)
if ev is None:
raise Exception("Association and EAP start timed out")
def test_ap_wpa2_eap_tls_neg_subject_match(dev, apdev):
"""WPA2-Enterprise negative test - subject mismatch"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="DOMAIN\mschapv2 user", anonymous_identity="ttls",
password="password", phase2="auth=MSCHAPV2",
subject_match="/C=FI/O=w1.fi/CN=example.com",
wait_connect=False, scan_freq="2412")
- ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=10)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=16)
if ev is None:
raise Exception("Association and EAP start timed out")
def test_ap_wpa2_eap_tls_neg_altsubject_match(dev, apdev):
"""WPA2-Enterprise negative test - altsubject mismatch"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
tests = [ "incorrect.example.com",
"DNS:incorrect.example.com",
altsubject_match=match,
wait_connect=False, scan_freq="2412")
- ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=10)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=16)
if ev is None:
raise Exception("Association and EAP start timed out")
def test_ap_wpa2_eap_unauth_tls(dev, apdev):
"""WPA2-Enterprise connection using UNAUTH-TLS"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "UNAUTH-TLS", "unauth-tls",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "UNAUTH-TLS", "unauth-tls",
ca_cert="auth_serv/ca.pem")
eap_reauth(dev[0], "UNAUTH-TLS")
"""WPA2-Enterprise connection using EAP-TTLS and server certificate hash"""
check_cert_probe_support(dev[0])
skip_with_fips(dev[0])
- srv_cert_hash = "1477c9cd88391609444b83eca45c4f9f324e3051c5c31fc233ac6aede30ce7cd"
+ srv_cert_hash = "bdb9cb55d3df278e52a071abf58e7f0238fbec3ad8fb2c254742f63562628272"
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="probe", ca_cert="probe://",
wait_connect=False, scan_freq="2412")
- ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=10)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=16)
if ev is None:
raise Exception("Association and EAP start timed out")
ev = dev[0].wait_event(["CTRL-EVENT-EAP-PEER-CERT depth=0"], timeout=10)
password="password", phase2="auth=MSCHAPV2",
ca_cert="hash://server/sha256/5a1bc1296205e6fdbe3979728efe3920798885c1c4590b5f90f43222d239ca6a",
wait_connect=False, scan_freq="2412")
- ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=10)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=16)
if ev is None:
raise Exception("Association and EAP start timed out")
ev = dev[0].wait_event(["CTRL-EVENT-EAP-TLS-CERT-ERROR"], timeout=10)
dev[0].wait_disconnected(timeout=10)
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "TTLS", "DOMAIN\mschapv2 user",
+ eap_connect(dev[0], hapd, "TTLS", "DOMAIN\mschapv2 user",
anonymous_identity="ttls", password="password",
ca_cert="hash://server/sha256/" + srv_cert_hash,
phase2="auth=MSCHAPV2")
def test_ap_wpa2_eap_ttls_server_cert_hash_invalid(dev, apdev):
"""WPA2-Enterprise connection using EAP-TTLS and server certificate hash (invalid config)"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="DOMAIN\mschapv2 user", anonymous_identity="ttls",
password="password", phase2="auth=MSCHAPV2",
ca_cert="hash://server/sha256/5a1bc1296205e6fdbe3979728efe3920798885c1c4590b5f90f43222d239ca6Q",
wait_connect=False, scan_freq="2412")
for i in range(0, 3):
- ev = dev[i].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=10)
+ ev = dev[i].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=16)
if ev is None:
raise Exception("Association and EAP start timed out")
ev = dev[i].wait_event(["EAP: Failed to initialize EAP method: vendor 0 method 21 (TTLS)"], timeout=5)
"""WPA2-Enterprise connection using EAP-pwd"""
check_eap_capa(dev[0], "PWD")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "PWD", "pwd user", password="secret password")
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "PWD", "pwd user", password="secret password")
eap_reauth(dev[0], "PWD")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[1], apdev[0], "PWD",
+ eap_connect(dev[1], hapd, "PWD",
"pwd.user@test123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890.example.com",
password="secret password",
fragment_size="90")
logger.info("Negative test with incorrect password")
- eap_connect(dev[2], apdev[0], "PWD", "pwd user", password="secret-password",
+ eap_connect(dev[2], hapd, "PWD", "pwd user", password="secret-password",
expect_failure=True, local_error_report=True)
- eap_connect(dev[0], apdev[0], "PWD",
+ eap_connect(dev[0], hapd, "PWD",
"pwd.user@test123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890.example.com",
password="secret password",
fragment_size="31")
check_eap_capa(dev[0], "PWD")
skip_with_fips(dev[0])
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "PWD", "pwd-hash", password="secret password")
- eap_connect(dev[1], apdev[0], "PWD", "pwd-hash",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "PWD", "pwd-hash", password="secret password")
+ eap_connect(dev[1], hapd, "PWD", "pwd-hash",
password_hex="hash:e3718ece8ab74792cbbfffd316d2d19a")
- eap_connect(dev[2], apdev[0], "PWD", "pwd user",
+ eap_connect(dev[2], hapd, "PWD", "pwd user",
password_hex="hash:e3718ece8ab74792cbbfffd316d2d19a",
expect_failure=True, local_error_report=True)
params = { "ssid": "test-wpa2-eap", "wpa": "2", "wpa_key_mgmt": "WPA-EAP",
"rsn_pairwise": "CCMP", "ieee8021x": "1",
"eap_server": "1", "eap_user_file": "auth_serv/eap_user.conf" }
- for i in [ 19, 20, 21, 25, 26 ]:
+ groups = [ 19, 20, 21, 25, 26 ]
+ if tls.startswith("OpenSSL") and "build=OpenSSL 1.0.2" in tls and "run=OpenSSL 1.0.2" in tls:
+ logger.info("Add Brainpool EC groups since OpenSSL is new enough")
+ groups += [ 27, 28, 29, 30 ]
+ for i in groups:
+ logger.info("Group %d" % i)
params['pwd_group'] = str(i)
- hostapd.add_ap(apdev[0]['ifname'], params)
- dev[0].request("REMOVE_NETWORK all")
+ hapd = hostapd.add_ap(apdev[0], params)
try:
- eap_connect(dev[0], apdev[0], "PWD", "pwd user",
+ eap_connect(dev[0], hapd, "PWD", "pwd user",
password="secret password")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ dev[0].dump_monitor()
except:
if "BoringSSL" in tls and i in [ 25 ]:
logger.info("Ignore connection failure with group %d with BoringSSL" % i)
dev[0].request("DISCONNECT")
time.sleep(0.1)
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
continue
raise
"rsn_pairwise": "CCMP", "ieee8021x": "1",
"eap_server": "1", "eap_user_file": "auth_serv/eap_user.conf" }
params['pwd_group'] = "0"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="PWD",
identity="pwd user", password="secret password",
scan_freq="2412", wait_connect=False)
"rsn_pairwise": "CCMP", "ieee8021x": "1",
"eap_server": "1", "eap_user_file": "auth_serv/eap_user.conf",
"pwd_group": "19", "fragment_size": "40" }
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "PWD", "pwd user", password="secret password")
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "PWD", "pwd user", password="secret password")
def test_ap_wpa2_eap_gpsk(dev, apdev):
"""WPA2-Enterprise connection using EAP-GPSK"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- id = eap_connect(dev[0], apdev[0], "GPSK", "gpsk user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ id = eap_connect(dev[0], hapd, "GPSK", "gpsk user",
password="abcdefghijklmnop0123456789abcdef")
eap_reauth(dev[0], "GPSK")
logger.info("Negative test with incorrect password")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "GPSK", "gpsk user",
+ eap_connect(dev[0], hapd, "GPSK", "gpsk user",
password="ffcdefghijklmnop0123456789abcdef",
expect_failure=True)
def test_ap_wpa2_eap_sake(dev, apdev):
"""WPA2-Enterprise connection using EAP-SAKE"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "SAKE", "sake user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "SAKE", "sake user",
password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef")
eap_reauth(dev[0], "SAKE")
logger.info("Negative test with incorrect password")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "SAKE", "sake user",
+ eap_connect(dev[0], hapd, "SAKE", "sake user",
password_hex="ff23456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
expect_failure=True)
def test_ap_wpa2_eap_eke(dev, apdev):
"""WPA2-Enterprise connection using EAP-EKE"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- id = eap_connect(dev[0], apdev[0], "EKE", "eke user", password="hello")
+ hapd = hostapd.add_ap(apdev[0], params)
+ id = eap_connect(dev[0], hapd, "EKE", "eke user", password="hello")
eap_reauth(dev[0], "EKE")
logger.info("Test forced algorithm selection")
logger.info("Negative test with incorrect password")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "EKE", "eke user", password="hello1",
+ eap_connect(dev[0], hapd, "EKE", "eke user", password="hello1",
expect_failure=True)
+def test_ap_wpa2_eap_eke_many(dev, apdev, params):
+ """WPA2-Enterprise connection using EAP-EKE (many connections) [long]"""
+ if not params['long']:
+ raise HwsimSkip("Skip test case with long duration due to --long not specified")
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hostapd.add_ap(apdev[0], params)
+ success = 0
+ fail = 0
+ for i in range(100):
+ for j in range(3):
+ dev[j].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="EKE",
+ identity="eke user", password="hello",
+ phase1="dhgroup=3 encr=1 prf=1 mac=1",
+ scan_freq="2412", wait_connect=False)
+ for j in range(3):
+ ev = dev[j].wait_event(["CTRL-EVENT-CONNECTED",
+ "CTRL-EVENT-DISCONNECTED"], timeout=15)
+ if ev is None:
+ raise Exception("No connected/disconnected event")
+ if "CTRL-EVENT-DISCONNECTED" in ev:
+ fail += 1
+ # The RADIUS server limits on active sessions can be hit when
+ # going through this test case, so try to give some more time
+ # for the server to remove sessions.
+ logger.info("Failed to connect i=%d j=%d" % (i, j))
+ dev[j].request("REMOVE_NETWORK all")
+ time.sleep(1)
+ else:
+ success += 1
+ dev[j].request("REMOVE_NETWORK all")
+ dev[j].wait_disconnected()
+ dev[j].dump_monitor()
+ logger.info("Total success=%d failure=%d" % (success, fail))
+
def test_ap_wpa2_eap_eke_serverid_nai(dev, apdev):
"""WPA2-Enterprise connection using EAP-EKE with serverid NAI"""
params = int_eap_server_params()
params['server_id'] = 'example.server@w1.fi'
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "EKE", "eke user", password="hello")
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "EKE", "eke user", password="hello")
def test_ap_wpa2_eap_eke_server_oom(dev, apdev):
"""WPA2-Enterprise connection using EAP-EKE with server OOM"""
params = int_eap_server_params()
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
for count,func in [ (1, "eap_eke_build_commit"),
(3, "eap_eke_process_identity"),
(4, "eap_eke_process_identity") ]:
with alloc_fail(hapd, count, func):
- eap_connect(dev[0], apdev[0], "EKE", "eke user", password="hello",
+ eap_connect(dev[0], hapd, "EKE", "eke user", password="hello",
expect_failure=True)
dev[0].request("REMOVE_NETWORK all")
"""WPA2-Enterprise connection using EAP-IKEv2"""
check_eap_capa(dev[0], "IKEV2")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "IKEV2", "ikev2 user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "IKEV2", "ikev2 user",
password="ike password")
eap_reauth(dev[0], "IKEV2")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "IKEV2", "ikev2 user",
+ eap_connect(dev[0], hapd, "IKEV2", "ikev2 user",
password="ike password", fragment_size="50")
logger.info("Negative test with incorrect password")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "IKEV2", "ikev2 user",
+ eap_connect(dev[0], hapd, "IKEV2", "ikev2 user",
password="ike-password", expect_failure=True)
+ dev[0].request("REMOVE_NETWORK all")
+
+ eap_connect(dev[0], hapd, "IKEV2", "ikev2 user",
+ password="ike password", fragment_size="0")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
def test_ap_wpa2_eap_ikev2_as_frag(dev, apdev):
"""WPA2-Enterprise connection using EAP-IKEv2 with server fragmentation"""
"rsn_pairwise": "CCMP", "ieee8021x": "1",
"eap_server": "1", "eap_user_file": "auth_serv/eap_user.conf",
"fragment_size": "50" }
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "IKEV2", "ikev2 user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "IKEV2", "ikev2 user",
password="ike password")
eap_reauth(dev[0], "IKEV2")
"""WPA2-Enterprise connection using EAP-IKEv2 and OOM"""
check_eap_capa(dev[0], "IKEV2")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
tests = [ (1, "dh_init"),
(2, "dh_init"),
def test_ap_wpa2_eap_pax(dev, apdev):
"""WPA2-Enterprise connection using EAP-PAX"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "PAX", "pax.user@example.com",
password_hex="0123456789abcdef0123456789abcdef")
eap_reauth(dev[0], "PAX")
logger.info("Negative test with incorrect password")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
+ eap_connect(dev[0], hapd, "PAX", "pax.user@example.com",
password_hex="ff23456789abcdef0123456789abcdef",
expect_failure=True)
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
params["wpa_key_mgmt"] = "WPA-EAP-SHA256"
params["ieee80211w"] = "2"
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "PSK", "psk.user@example.com",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "PSK", "psk.user@example.com",
password_hex="0123456789abcdef0123456789abcdef", sha256=True)
eap_reauth(dev[0], "PSK", sha256=True)
check_mib(dev[0], [ ("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-5"),
logger.info("Negative test with incorrect password")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "PSK", "psk.user@example.com",
+ eap_connect(dev[0], hapd, "PSK", "psk.user@example.com",
password_hex="ff23456789abcdef0123456789abcdef", sha256=True,
expect_failure=True)
"""WPA2-Enterprise connection using EAP-PSK and OOM"""
skip_with_fips(dev[0])
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
+ tests = [ (1, "=aes_128_eax_encrypt"),
+ (1, "=aes_128_eax_decrypt") ]
+ for count, func in tests:
+ with alloc_fail(dev[0], count, func):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="PSK",
+ identity="psk.user@example.com",
+ password_hex="0123456789abcdef0123456789abcdef",
+ wait_connect=False, scan_freq="2412")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
+ if ev is None:
+ raise Exception("EAP method not selected")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL",
+ note="Failure not triggered: %d:%s" % (count, func))
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
tests = [ (1, "aes_128_ctr_encrypt;aes_128_eax_encrypt"),
(1, "omac1_aes_128;aes_128_eax_encrypt"),
(2, "omac1_aes_128;aes_128_eax_encrypt"),
(3, "omac1_aes_128;aes_128_eax_encrypt"),
- (1, "=aes_128_eax_encrypt"),
(1, "omac1_aes_vector"),
- (1, "aes_128_ctr_encrypt;aes_128_eax_decrypt"),
(1, "omac1_aes_128;aes_128_eax_decrypt"),
(2, "omac1_aes_128;aes_128_eax_decrypt"),
(3, "omac1_aes_128;aes_128_eax_decrypt"),
- (1, "=aes_128_eax_decrypt") ]
+ (1, "aes_128_ctr_encrypt;aes_128_eax_decrypt") ]
for count, func in tests:
- with alloc_fail(dev[0], count, func):
+ with fail_test(dev[0], count, func):
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="PSK",
identity="psk.user@example.com",
password_hex="0123456789abcdef0123456789abcdef",
ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
if ev is None:
raise Exception("EAP method not selected")
- for i in range(10):
- if "0:" in dev[0].request("GET_ALLOC_FAIL"):
- break
- time.sleep(0.02)
+ wait_fail_trigger(dev[0], "GET_FAIL",
+ note="Failure not triggered: %d:%s" % (count, func))
dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
- with alloc_fail(dev[0], 1, "aes_128_encrypt_block"):
+ with fail_test(dev[0], 1, "aes_128_encrypt_block"):
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="PSK",
identity="psk.user@example.com",
password_hex="0123456789abcdef0123456789abcdef",
if ev is None:
raise Exception("EAP method failure not reported")
dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
def test_ap_wpa_eap_peap_eap_mschapv2(dev, apdev):
"""WPA-Enterprise connection using EAP-PEAP/EAP-MSCHAPv2"""
check_eap_capa(dev[0], "MSCHAPV2")
params = hostapd.wpa_eap_params(ssid="test-wpa-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa-eap", key_mgmt="WPA-EAP", eap="PEAP",
identity="user", password="password", phase2="auth=MSCHAPV2",
ca_cert="auth_serv/ca.pem", wait_connect=False,
"""WPA2-Enterprise connection using interactive identity/password entry"""
check_eap_capa(dev[0], "MSCHAPV2")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
tests = [ ("Connection with dynamic TTLS/MSCHAPv2 password entry",
"TTLS", "ttls", "DOMAIN\mschapv2 user", "auth=MSCHAPV2",
"""WPA2-Enterprise interactive identity entry and ENABLE_NETWORK"""
check_eap_capa(dev[0], "MSCHAPV2")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
id_other = dev[0].connect("other", key_mgmt="NONE", scan_freq="2412",
only_add_network=True)
def test_ap_wpa2_eap_vendor_test(dev, apdev):
"""WPA2-Enterprise connection using EAP vendor test"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "VENDOR-TEST", "vendor-test")
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "VENDOR-TEST", "vendor-test")
eap_reauth(dev[0], "VENDOR-TEST")
- eap_connect(dev[1], apdev[0], "VENDOR-TEST", "vendor-test",
+ eap_connect(dev[1], hapd, "VENDOR-TEST", "vendor-test",
password="pending")
+def test_ap_wpa2_eap_vendor_test_oom(dev, apdev):
+ """WPA2-Enterprise connection using EAP vendor test (OOM)"""
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hostapd.add_ap(apdev[0], params)
+
+ tests = [ "eap_vendor_test_init",
+ "eap_msg_alloc;eap_vendor_test_process",
+ "eap_vendor_test_getKey" ]
+ for func in tests:
+ with alloc_fail(dev[0], 1, func):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
+ scan_freq="2412",
+ eap="VENDOR-TEST", identity="vendor-test",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
def test_ap_wpa2_eap_fast_mschapv2_unauth_prov(dev, apdev):
"""WPA2-Enterprise connection using EAP-FAST/MSCHAPv2 and unauthenticated provisioning"""
check_eap_capa(dev[0], "FAST")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "FAST", "user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "FAST", "user",
anonymous_identity="FAST", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
phase1="fast_provisioning=1", pac_file="blob://fast_pac")
pac_file = os.path.join(params['logdir'], "fast.pac")
pac_file2 = os.path.join(params['logdir'], "fast-bin.pac")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
try:
- eap_connect(dev[0], apdev[0], "FAST", "user",
+ eap_connect(dev[0], hapd, "FAST", "user",
anonymous_identity="FAST", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
phase1="fast_provisioning=1", pac_file=pac_file)
if "PAC-Key=" not in data:
raise Exception("PAC-Key missing from PAC file")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "FAST", "user",
+ eap_connect(dev[0], hapd, "FAST", "user",
anonymous_identity="FAST", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
pac_file=pac_file)
- eap_connect(dev[1], apdev[0], "FAST", "user",
+ eap_connect(dev[1], hapd, "FAST", "user",
anonymous_identity="FAST", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
phase1="fast_provisioning=1 fast_pac_format=binary",
pac_file=pac_file2)
dev[1].request("REMOVE_NETWORK all")
- eap_connect(dev[1], apdev[0], "FAST", "user",
+ eap_connect(dev[1], hapd, "FAST", "user",
anonymous_identity="FAST", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
phase1="fast_pac_format=binary",
"""WPA2-Enterprise connection using EAP-FAST and binary PAC format"""
check_eap_capa(dev[0], "FAST")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "FAST", "user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "FAST", "user",
anonymous_identity="FAST", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
phase1="fast_provisioning=1 fast_max_pac_list_len=1 fast_pac_format=binary",
if res['tls_session_reused'] != '1':
raise Exception("EAP-FAST could not use PAC session ticket")
+ # Verify fast_max_pac_list_len=0 special case
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ eap_connect(dev[0], hapd, "FAST", "user",
+ anonymous_identity="FAST", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ phase1="fast_provisioning=1 fast_max_pac_list_len=0 fast_pac_format=binary",
+ pac_file="blob://fast_pac_bin")
+
def test_ap_wpa2_eap_fast_missing_pac_config(dev, apdev):
"""WPA2-Enterprise connection using EAP-FAST and missing PAC config"""
check_eap_capa(dev[0], "FAST")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="FAST",
identity="user", anonymous_identity="FAST",
if ev is None:
raise Exception("Timeout on EAP failure report")
+def test_ap_wpa2_eap_fast_binary_pac_errors(dev, apdev):
+ """EAP-FAST and binary PAC errors"""
+ check_eap_capa(dev[0], "FAST")
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ tests = [ (1, "=eap_fast_save_pac_bin"),
+ (1, "eap_fast_write_pac"),
+ (2, "eap_fast_write_pac"), ]
+ for count, func in tests:
+ if "OK" not in dev[0].request("SET blob fast_pac_bin_errors "):
+ raise Exception("Could not set blob")
+
+ with alloc_fail(dev[0], count, func):
+ eap_connect(dev[0], hapd, "FAST", "user",
+ anonymous_identity="FAST", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ phase1="fast_provisioning=1 fast_pac_format=binary",
+ pac_file="blob://fast_pac_bin_errors")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ "00", "000000000000", "6ae4920c0001",
+ "6ae4920c000000",
+ "6ae4920c0000" + "0000" + 32*"00" + "ffff" + "0000",
+ "6ae4920c0000" + "0000" + 32*"00" + "0001" + "0000",
+ "6ae4920c0000" + "0000" + 32*"00" + "0000" + "0001",
+ "6ae4920c0000" + "0000" + 32*"00" + "0000" + "0008" + "00040000" + "0007000100"]
+ for t in tests:
+ if "OK" not in dev[0].request("SET blob fast_pac_bin_errors " + t):
+ raise Exception("Could not set blob")
+
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="FAST",
+ identity="user", anonymous_identity="FAST",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ phase1="fast_provisioning=1 fast_pac_format=binary",
+ pac_file="blob://fast_pac_bin_errors",
+ scan_freq="2412", wait_connect=False)
+ ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
+ timeout=5)
+ if ev is None:
+ raise Exception("Failure not reported")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ pac = "6ae4920c0000" + "0000" + 32*"00" + "0000" + "0000"
+ tests = [ (1, "eap_fast_load_pac_bin"),
+ (2, "eap_fast_load_pac_bin"),
+ (3, "eap_fast_load_pac_bin") ]
+ for count, func in tests:
+ if "OK" not in dev[0].request("SET blob fast_pac_bin_errors " + pac):
+ raise Exception("Could not set blob")
+
+ with alloc_fail(dev[0], count, func):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="FAST",
+ identity="user", anonymous_identity="FAST",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ phase1="fast_provisioning=1 fast_pac_format=binary",
+ pac_file="blob://fast_pac_bin_errors",
+ scan_freq="2412", wait_connect=False)
+ ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
+ timeout=5)
+ if ev is None:
+ raise Exception("Failure not reported")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ pac = "6ae4920c0000" + "0000" + 32*"00" + "0000" + "0005" + "0011223344"
+ if "OK" not in dev[0].request("SET blob fast_pac_bin_errors " + pac):
+ raise Exception("Could not set blob")
+
+ eap_connect(dev[0], hapd, "FAST", "user",
+ anonymous_identity="FAST", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ phase1="fast_provisioning=1 fast_pac_format=binary",
+ pac_file="blob://fast_pac_bin_errors")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ pac = "6ae4920c0000" + "0000" + 32*"00" + "0000" + "0009" + "00040000" + "0007000100"
+ tests = [ (1, "eap_fast_pac_get_a_id"),
+ (2, "eap_fast_pac_get_a_id") ]
+ for count, func in tests:
+ if "OK" not in dev[0].request("SET blob fast_pac_bin_errors " + pac):
+ raise Exception("Could not set blob")
+ with alloc_fail(dev[0], count, func):
+ eap_connect(dev[0], hapd, "FAST", "user",
+ anonymous_identity="FAST", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ phase1="fast_provisioning=1 fast_pac_format=binary",
+ pac_file="blob://fast_pac_bin_errors")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+def test_ap_wpa2_eap_fast_text_pac_errors(dev, apdev):
+ """EAP-FAST and text PAC errors"""
+ check_eap_capa(dev[0], "FAST")
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hostapd.add_ap(apdev[0], params)
+
+ tests = [ (1, "eap_fast_parse_hex;eap_fast_parse_pac_key"),
+ (1, "eap_fast_parse_hex;eap_fast_parse_pac_opaque"),
+ (1, "eap_fast_parse_hex;eap_fast_parse_a_id"),
+ (1, "eap_fast_parse_start"),
+ (1, "eap_fast_save_pac") ]
+ for count, func in tests:
+ dev[0].request("FLUSH")
+ if "OK" not in dev[0].request("SET blob fast_pac_text_errors "):
+ raise Exception("Could not set blob")
+
+ with alloc_fail(dev[0], count, func):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="FAST",
+ identity="user", anonymous_identity="FAST",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ phase1="fast_provisioning=1",
+ pac_file="blob://fast_pac_text_errors",
+ scan_freq="2412", wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ pac = "wpa_supplicant EAP-FAST PAC file - version 1\n"
+ pac += "START\n"
+ pac += "PAC-Type\n"
+ pac += "END\n"
+ if "OK" not in dev[0].request("SET blob fast_pac_text_errors " + pac.encode("hex")):
+ raise Exception("Could not set blob")
+
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="FAST",
+ identity="user", anonymous_identity="FAST",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ phase1="fast_provisioning=1",
+ pac_file="blob://fast_pac_text_errors",
+ scan_freq="2412", wait_connect=False)
+ ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"], timeout=5)
+ if ev is None:
+ raise Exception("Failure not reported")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ dev[0].request("FLUSH")
+ if "OK" not in dev[0].request("SET blob fast_pac_text_errors "):
+ raise Exception("Could not set blob")
+
+ with alloc_fail(dev[0], 1, "eap_fast_add_pac_data"):
+ for i in range(3):
+ params = int_eap_server_params()
+ params['ssid'] = "test-wpa2-eap-2"
+ params['pac_opaque_encr_key'] = "000102030405060708090a0b0c0dff%02x" % i
+ params['eap_fast_a_id'] = "101112131415161718191a1b1c1dff%02x" % i
+ params['eap_fast_a_id_info'] = "test server %d" % i
+
+ hapd2 = hostapd.add_ap(apdev[1], params)
+
+ dev[0].connect("test-wpa2-eap-2", key_mgmt="WPA-EAP", eap="FAST",
+ identity="user", anonymous_identity="FAST",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ phase1="fast_provisioning=1",
+ pac_file="blob://fast_pac_text_errors",
+ scan_freq="2412", wait_connect=False)
+ dev[0].wait_connected()
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ hapd2.disable()
+
+def test_ap_wpa2_eap_fast_pac_truncate(dev, apdev):
+ """EAP-FAST and PAC list truncation"""
+ check_eap_capa(dev[0], "FAST")
+ if "OK" not in dev[0].request("SET blob fast_pac_truncate "):
+ raise Exception("Could not set blob")
+ for i in range(5):
+ params = int_eap_server_params()
+ params['pac_opaque_encr_key'] = "000102030405060708090a0b0c0dff%02x" % i
+ params['eap_fast_a_id'] = "101112131415161718191a1b1c1dff%02x" % i
+ params['eap_fast_a_id_info'] = "test server %d" % i
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="FAST",
+ identity="user", anonymous_identity="FAST",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ phase1="fast_provisioning=1 fast_max_pac_list_len=2",
+ pac_file="blob://fast_pac_truncate",
+ scan_freq="2412", wait_connect=False)
+ dev[0].wait_connected()
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ hapd.disable()
+
+def test_ap_wpa2_eap_fast_pac_refresh(dev, apdev):
+ """EAP-FAST and PAC refresh"""
+ check_eap_capa(dev[0], "FAST")
+ if "OK" not in dev[0].request("SET blob fast_pac_refresh "):
+ raise Exception("Could not set blob")
+ for i in range(2):
+ params = int_eap_server_params()
+ params['pac_opaque_encr_key'] = "000102030405060708090a0b0c0dff%02x" % i
+ params['eap_fast_a_id'] = "101112131415161718191a1b1c1dff%02x" % i
+ params['eap_fast_a_id_info'] = "test server %d" % i
+ params['pac_key_refresh_time'] = "1"
+ params['pac_key_lifetime'] = "10"
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="FAST",
+ identity="user", anonymous_identity="FAST",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ phase1="fast_provisioning=1",
+ pac_file="blob://fast_pac_refresh",
+ scan_freq="2412", wait_connect=False)
+ dev[0].wait_connected()
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ hapd.disable()
+
+ for i in range(2):
+ params = int_eap_server_params()
+ params['pac_opaque_encr_key'] = "000102030405060708090a0b0c0dff%02x" % i
+ params['eap_fast_a_id'] = "101112131415161718191a1b1c1dff%02x" % i
+ params['eap_fast_a_id_info'] = "test server %d" % i
+ params['pac_key_refresh_time'] = "10"
+ params['pac_key_lifetime'] = "10"
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="FAST",
+ identity="user", anonymous_identity="FAST",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ phase1="fast_provisioning=1",
+ pac_file="blob://fast_pac_refresh",
+ scan_freq="2412", wait_connect=False)
+ dev[0].wait_connected()
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ hapd.disable()
+
+def test_ap_wpa2_eap_fast_pac_lifetime(dev, apdev):
+ """EAP-FAST and PAC lifetime"""
+ check_eap_capa(dev[0], "FAST")
+ if "OK" not in dev[0].request("SET blob fast_pac_refresh "):
+ raise Exception("Could not set blob")
+
+ i = 0
+ params = int_eap_server_params()
+ params['pac_opaque_encr_key'] = "000102030405060708090a0b0c0dff%02x" % i
+ params['eap_fast_a_id'] = "101112131415161718191a1b1c1dff%02x" % i
+ params['eap_fast_a_id_info'] = "test server %d" % i
+ params['pac_key_refresh_time'] = "0"
+ params['pac_key_lifetime'] = "2"
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="FAST",
+ identity="user", anonymous_identity="FAST",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ phase1="fast_provisioning=2",
+ pac_file="blob://fast_pac_refresh",
+ scan_freq="2412", wait_connect=False)
+ dev[0].wait_connected()
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected()
+
+ time.sleep(3)
+ dev[0].request("PMKSA_FLUSH")
+ dev[0].request("RECONNECT")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=10)
+ if ev is None:
+ raise Exception("No EAP-Failure seen after expired PAC")
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected()
+
+ dev[0].select_network(id)
+ dev[0].wait_connected()
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
def test_ap_wpa2_eap_fast_gtc_auth_prov(dev, apdev):
"""WPA2-Enterprise connection using EAP-FAST/GTC and authenticated provisioning"""
check_eap_capa(dev[0], "FAST")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "FAST", "user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "FAST", "user",
anonymous_identity="FAST", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=GTC",
phase1="fast_provisioning=2", pac_file="blob://fast_pac_auth")
"""WPA2-Enterprise connection using EAP-FAST/GTC and identity changing"""
check_eap_capa(dev[0], "FAST")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- id = eap_connect(dev[0], apdev[0], "FAST", "user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ id = eap_connect(dev[0], hapd, "FAST", "user",
anonymous_identity="FAST", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=GTC",
phase1="fast_provisioning=2",
def test_ap_wpa2_eap_fast_prf_oom(dev, apdev):
"""WPA2-Enterprise connection using EAP-FAST and OOM in PRF"""
check_eap_capa(dev[0], "FAST")
+ tls = dev[0].request("GET tls_library")
+ if tls.startswith("OpenSSL"):
+ func = "tls_connection_get_eap_fast_key"
+ count = 2
+ elif tls.startswith("internal"):
+ func = "tls_connection_prf"
+ count = 1
+ else:
+ raise HwsimSkip("Unsupported TLS library")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- with alloc_fail(dev[0], 2, "openssl_tls_prf"):
+ hapd = hostapd.add_ap(apdev[0], params)
+ with alloc_fail(dev[0], count, func):
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="FAST",
identity="user", anonymous_identity="FAST",
password="password", ca_cert="auth_serv/ca.pem",
params['pac_opaque_encr_key'] = '000102030405060708090a0b0c0d0e0f'
params['eap_fast_a_id'] = '1011'
params['eap_fast_a_id_info'] = 'another test server'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
with alloc_fail(hapd, 1, "tls_session_ticket_ext_cb"):
- id = eap_connect(dev[0], apdev[0], "FAST", "user",
+ id = eap_connect(dev[0], hapd, "FAST", "user",
anonymous_identity="FAST", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
phase1="fast_provisioning=1",
dev[0].select_network(id, freq="2412")
+def test_ap_wpa2_eap_fast_cipher_suites(dev, apdev):
+ """EAP-FAST and different TLS cipher suites"""
+ check_eap_capa(dev[0], "FAST")
+ tls = dev[0].request("GET tls_library")
+ if not tls.startswith("OpenSSL"):
+ raise HwsimSkip("TLS library is not OpenSSL: " + tls)
+
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].request("SET blob fast_pac_ciphers ")
+ eap_connect(dev[0], hapd, "FAST", "user",
+ anonymous_identity="FAST", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=GTC",
+ phase1="fast_provisioning=2",
+ pac_file="blob://fast_pac_ciphers")
+ res = dev[0].get_status_field('EAP TLS cipher')
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ if res != "DHE-RSA-AES256-SHA":
+ raise Exception("Unexpected cipher suite for provisioning: " + res)
+
+ tests = [ "DHE-RSA-AES128-SHA",
+ "RC4-SHA",
+ "AES128-SHA",
+ "AES256-SHA",
+ "DHE-RSA-AES256-SHA" ]
+ for cipher in tests:
+ dev[0].dump_monitor()
+ logger.info("Testing " + cipher)
+ try:
+ eap_connect(dev[0], hapd, "FAST", "user",
+ openssl_ciphers=cipher,
+ anonymous_identity="FAST", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=GTC",
+ pac_file="blob://fast_pac_ciphers")
+ except Exception, e:
+ if "Could not select EAP method" in str(e) and cipher == "RC4-SHA":
+ tls = dev[0].request("GET tls_library")
+ if "run=OpenSSL 1.1" in tls:
+ logger.info("Allow failure due to missing TLS library support")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ continue
+ raise
+ res = dev[0].get_status_field('EAP TLS cipher')
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ if res != cipher:
+ raise Exception("Unexpected TLS cipher info (configured %s): %s" % (cipher, res))
+
def test_ap_wpa2_eap_tls_ocsp(dev, apdev):
"""WPA2-Enterprise connection using EAP-TLS and verifying OCSP"""
check_ocsp_support(dev[0])
+ check_pkcs12_support(dev[0])
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TLS", "tls user", ca_cert="auth_serv/ca.pem",
+ private_key="auth_serv/user.pkcs12",
+ private_key_passwd="whatever", ocsp=2)
+
+def test_ap_wpa2_eap_tls_ocsp_multi(dev, apdev):
+ """WPA2-Enterprise connection using EAP-TLS and verifying OCSP-multi"""
+ check_ocsp_multi_support(dev[0])
+ check_pkcs12_support(dev[0])
+
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TLS", "tls user", ca_cert="auth_serv/ca.pem",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TLS", "tls user", ca_cert="auth_serv/ca.pem",
private_key="auth_serv/user.pkcs12",
private_key_passwd="whatever", ocsp=2)
"eap_server": "1", "eap_user_file": "auth_serv/eap_user.conf",
"ca_cert": "auth_serv/ca.pem",
"server_cert": "auth_serv/server.pem",
- "private_key": "auth_serv/server.key" }
+ "private_key": "auth_serv/server.key",
+ "dh_file": "auth_serv/dh.conf" }
return params
+def test_ap_wpa2_eap_tls_ocsp_key_id(dev, apdev, params):
+ """EAP-TLS and OCSP certificate signed OCSP response using key ID"""
+ check_ocsp_support(dev[0])
+ ocsp = os.path.join(params['logdir'], "ocsp-server-cache-key-id.der")
+ if not os.path.exists(ocsp):
+ raise HwsimSkip("No OCSP response available")
+ params = int_eap_server_params()
+ params["ocsp_stapling_response"] = ocsp
+ hostapd.add_ap(apdev[0], params)
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
+ identity="tls user", ca_cert="auth_serv/ca.pem",
+ private_key="auth_serv/user.pkcs12",
+ private_key_passwd="whatever", ocsp=2,
+ scan_freq="2412")
+
+def test_ap_wpa2_eap_tls_ocsp_ca_signed_good(dev, apdev, params):
+ """EAP-TLS and CA signed OCSP response (good)"""
+ check_ocsp_support(dev[0])
+ ocsp = os.path.join(params['logdir'], "ocsp-resp-ca-signed.der")
+ if not os.path.exists(ocsp):
+ raise HwsimSkip("No OCSP response available")
+ params = int_eap_server_params()
+ params["ocsp_stapling_response"] = ocsp
+ hostapd.add_ap(apdev[0], params)
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
+ identity="tls user", ca_cert="auth_serv/ca.pem",
+ private_key="auth_serv/user.pkcs12",
+ private_key_passwd="whatever", ocsp=2,
+ scan_freq="2412")
+
+def test_ap_wpa2_eap_tls_ocsp_ca_signed_revoked(dev, apdev, params):
+ """EAP-TLS and CA signed OCSP response (revoked)"""
+ check_ocsp_support(dev[0])
+ ocsp = os.path.join(params['logdir'], "ocsp-resp-ca-signed-revoked.der")
+ if not os.path.exists(ocsp):
+ raise HwsimSkip("No OCSP response available")
+ params = int_eap_server_params()
+ params["ocsp_stapling_response"] = ocsp
+ hostapd.add_ap(apdev[0], params)
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
+ identity="tls user", ca_cert="auth_serv/ca.pem",
+ private_key="auth_serv/user.pkcs12",
+ private_key_passwd="whatever", ocsp=2,
+ wait_connect=False, scan_freq="2412")
+ count = 0
+ while True:
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STATUS"])
+ if ev is None:
+ raise Exception("Timeout on EAP status")
+ if 'bad certificate status response' in ev:
+ break
+ if 'certificate revoked' in ev:
+ break
+ count = count + 1
+ if count > 10:
+ raise Exception("Unexpected number of EAP status messages")
+
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"])
+ if ev is None:
+ raise Exception("Timeout on EAP failure report")
+
+def test_ap_wpa2_eap_tls_ocsp_ca_signed_unknown(dev, apdev, params):
+ """EAP-TLS and CA signed OCSP response (unknown)"""
+ check_ocsp_support(dev[0])
+ ocsp = os.path.join(params['logdir'], "ocsp-resp-ca-signed-unknown.der")
+ if not os.path.exists(ocsp):
+ raise HwsimSkip("No OCSP response available")
+ params = int_eap_server_params()
+ params["ocsp_stapling_response"] = ocsp
+ hostapd.add_ap(apdev[0], params)
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
+ identity="tls user", ca_cert="auth_serv/ca.pem",
+ private_key="auth_serv/user.pkcs12",
+ private_key_passwd="whatever", ocsp=2,
+ wait_connect=False, scan_freq="2412")
+ count = 0
+ while True:
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STATUS"])
+ if ev is None:
+ raise Exception("Timeout on EAP status")
+ if 'bad certificate status response' in ev:
+ break
+ count = count + 1
+ if count > 10:
+ raise Exception("Unexpected number of EAP status messages")
+
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"])
+ if ev is None:
+ raise Exception("Timeout on EAP failure report")
+
+def test_ap_wpa2_eap_tls_ocsp_server_signed(dev, apdev, params):
+ """EAP-TLS and server signed OCSP response"""
+ check_ocsp_support(dev[0])
+ ocsp = os.path.join(params['logdir'], "ocsp-resp-server-signed.der")
+ if not os.path.exists(ocsp):
+ raise HwsimSkip("No OCSP response available")
+ params = int_eap_server_params()
+ params["ocsp_stapling_response"] = ocsp
+ hostapd.add_ap(apdev[0], params)
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
+ identity="tls user", ca_cert="auth_serv/ca.pem",
+ private_key="auth_serv/user.pkcs12",
+ private_key_passwd="whatever", ocsp=2,
+ wait_connect=False, scan_freq="2412")
+ count = 0
+ while True:
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STATUS"])
+ if ev is None:
+ raise Exception("Timeout on EAP status")
+ if 'bad certificate status response' in ev:
+ break
+ count = count + 1
+ if count > 10:
+ raise Exception("Unexpected number of EAP status messages")
+
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"])
+ if ev is None:
+ raise Exception("Timeout on EAP failure report")
+
def test_ap_wpa2_eap_tls_ocsp_invalid_data(dev, apdev):
"""WPA2-Enterprise connection using EAP-TLS and invalid OCSP data"""
check_ocsp_support(dev[0])
params = int_eap_server_params()
params["ocsp_stapling_response"] = "auth_serv/ocsp-req.der"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
identity="tls user", ca_cert="auth_serv/ca.pem",
private_key="auth_serv/user.pkcs12",
check_ocsp_support(dev[0])
params = int_eap_server_params()
params["ocsp_stapling_response"] = "auth_serv/ocsp-server-cache.der-invalid"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
identity="tls user", ca_cert="auth_serv/ca.pem",
private_key="auth_serv/user.pkcs12",
check_ocsp_support(dev[0])
params = int_eap_server_params()
params["ocsp_stapling_response"] = "auth_serv/ocsp-server-cache.der-unknown-sign"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
identity="tls user", ca_cert="auth_serv/ca.pem",
private_key="auth_serv/user.pkcs12",
raise HwsimSkip("No OCSP response available")
params = int_eap_server_params()
params["ocsp_stapling_response"] = ocsp
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="pap user", ca_cert="auth_serv/ca.pem",
anonymous_identity="ttls", password="password",
raise HwsimSkip("No OCSP response available")
params = int_eap_server_params()
params["ocsp_stapling_response"] = ocsp
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="pap user", ca_cert="auth_serv/ca.pem",
anonymous_identity="ttls", password="password",
if ev is None:
raise Exception("Timeout on EAP failure report")
-def test_ap_wpa2_eap_ttls_optional_ocsp_unknown(dev, apdev, params):
- """WPA2-Enterprise connection using EAP-TTLS and OCSP status revoked"""
- ocsp = os.path.join(params['logdir'], "ocsp-server-cache-unknown.der")
- if not os.path.exists(ocsp):
- raise HwsimSkip("No OCSP response available")
+def test_ap_wpa2_eap_ttls_optional_ocsp_unknown(dev, apdev, params):
+ """WPA2-Enterprise connection using EAP-TTLS and OCSP status revoked"""
+ ocsp = os.path.join(params['logdir'], "ocsp-server-cache-unknown.der")
+ if not os.path.exists(ocsp):
+ raise HwsimSkip("No OCSP response available")
+ params = int_eap_server_params()
+ params["ocsp_stapling_response"] = ocsp
+ hostapd.add_ap(apdev[0], params)
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
+ identity="pap user", ca_cert="auth_serv/ca.pem",
+ anonymous_identity="ttls", password="password",
+ phase2="auth=PAP", ocsp=1, scan_freq="2412")
+
+def test_ap_wpa2_eap_tls_intermediate_ca(dev, apdev, params):
+ """EAP-TLS with intermediate server/user CA"""
+ params = int_eap_server_params()
+ params["ca_cert"] = "auth_serv/iCA-server/ca-and-root.pem"
+ params["server_cert"] = "auth_serv/iCA-server/server.pem"
+ params["private_key"] = "auth_serv/iCA-server/server.key"
+ hostapd.add_ap(apdev[0], params)
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
+ identity="tls user",
+ ca_cert="auth_serv/iCA-user/ca-and-root.pem",
+ client_cert="auth_serv/iCA-user/user.pem",
+ private_key="auth_serv/iCA-user/user.key",
+ scan_freq="2412")
+
+def root_ocsp(cert):
+ ca = "auth_serv/ca.pem"
+
+ fd2, fn2 = tempfile.mkstemp()
+ os.close(fd2)
+
+ arg = [ "openssl", "ocsp", "-reqout", fn2, "-issuer", ca, "-cert", cert,
+ "-no_nonce", "-sha256", "-text" ]
+ cmd = subprocess.Popen(arg, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ res = cmd.stdout.read() + "\n" + cmd.stderr.read()
+ cmd.stdout.close()
+ cmd.stderr.close()
+ logger.info("OCSP request:\n" + res)
+
+ fd, fn = tempfile.mkstemp()
+ os.close(fd)
+ arg = [ "openssl", "ocsp", "-index", "auth_serv/rootCA/index.txt",
+ "-rsigner", ca, "-rkey", "auth_serv/ca-key.pem",
+ "-CA", ca, "-issuer", ca, "-verify_other", ca, "-trust_other",
+ "-ndays", "7", "-reqin", fn2, "-resp_no_certs", "-respout", fn,
+ "-text" ]
+ cmd = subprocess.Popen(arg, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ res = cmd.stdout.read() + "\n" + cmd.stderr.read()
+ cmd.stdout.close()
+ cmd.stderr.close()
+ logger.info("OCSP response:\n" + res)
+ os.unlink(fn2)
+ return fn
+
+def ica_ocsp(cert):
+ prefix = "auth_serv/iCA-server/"
+ ca = prefix + "cacert.pem"
+ cert = prefix + cert
+
+ fd2, fn2 = tempfile.mkstemp()
+ os.close(fd2)
+
+ arg = [ "openssl", "ocsp", "-reqout", fn2, "-issuer", ca, "-cert", cert,
+ "-no_nonce", "-sha256", "-text" ]
+ cmd = subprocess.Popen(arg, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ res = cmd.stdout.read() + "\n" + cmd.stderr.read()
+ cmd.stdout.close()
+ cmd.stderr.close()
+ logger.info("OCSP request:\n" + res)
+
+ fd, fn = tempfile.mkstemp()
+ os.close(fd)
+ arg = [ "openssl", "ocsp", "-index", prefix + "index.txt",
+ "-rsigner", ca, "-rkey", prefix + "private/cakey.pem",
+ "-CA", ca, "-issuer", ca, "-verify_other", ca, "-trust_other",
+ "-ndays", "7", "-reqin", fn2, "-resp_no_certs", "-respout", fn,
+ "-text" ]
+ cmd = subprocess.Popen(arg, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ res = cmd.stdout.read() + "\n" + cmd.stderr.read()
+ cmd.stdout.close()
+ cmd.stderr.close()
+ logger.info("OCSP response:\n" + res)
+ os.unlink(fn2)
+ return fn
+
+def test_ap_wpa2_eap_tls_intermediate_ca_ocsp(dev, apdev, params):
+ """EAP-TLS with intermediate server/user CA and OCSP on server certificate"""
+ params = int_eap_server_params()
+ params["ca_cert"] = "auth_serv/iCA-server/ca-and-root.pem"
+ params["server_cert"] = "auth_serv/iCA-server/server.pem"
+ params["private_key"] = "auth_serv/iCA-server/server.key"
+ fn = ica_ocsp("server.pem")
+ params["ocsp_stapling_response"] = fn
+ try:
+ hostapd.add_ap(apdev[0], params)
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
+ identity="tls user",
+ ca_cert="auth_serv/iCA-user/ca-and-root.pem",
+ client_cert="auth_serv/iCA-user/user.pem",
+ private_key="auth_serv/iCA-user/user.key",
+ scan_freq="2412", ocsp=2)
+ finally:
+ os.unlink(fn)
+
+def test_ap_wpa2_eap_tls_intermediate_ca_ocsp_revoked(dev, apdev, params):
+ """EAP-TLS with intermediate server/user CA and OCSP on revoked server certificate"""
+ params = int_eap_server_params()
+ params["ca_cert"] = "auth_serv/iCA-server/ca-and-root.pem"
+ params["server_cert"] = "auth_serv/iCA-server/server-revoked.pem"
+ params["private_key"] = "auth_serv/iCA-server/server-revoked.key"
+ fn = ica_ocsp("server-revoked.pem")
+ params["ocsp_stapling_response"] = fn
+ try:
+ hostapd.add_ap(apdev[0], params)
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
+ identity="tls user",
+ ca_cert="auth_serv/iCA-user/ca-and-root.pem",
+ client_cert="auth_serv/iCA-user/user.pem",
+ private_key="auth_serv/iCA-user/user.key",
+ scan_freq="2412", ocsp=1, wait_connect=False)
+ count = 0
+ while True:
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STATUS",
+ "CTRL-EVENT-EAP-SUCCESS"])
+ if ev is None:
+ raise Exception("Timeout on EAP status")
+ if "CTRL-EVENT-EAP-SUCCESS" in ev:
+ raise Exception("Unexpected EAP-Success")
+ if 'bad certificate status response' in ev:
+ break
+ if 'certificate revoked' in ev:
+ break
+ count = count + 1
+ if count > 10:
+ raise Exception("Unexpected number of EAP status messages")
+
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"])
+ if ev is None:
+ raise Exception("Timeout on EAP failure report")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ finally:
+ os.unlink(fn)
+
+def test_ap_wpa2_eap_tls_intermediate_ca_ocsp_multi_missing_resp(dev, apdev, params):
+ """EAP-TLS with intermediate server/user CA and OCSP multi missing response"""
+ check_ocsp_support(dev[0])
+ check_ocsp_multi_support(dev[0])
+
+ params = int_eap_server_params()
+ params["ca_cert"] = "auth_serv/iCA-server/ca-and-root.pem"
+ params["server_cert"] = "auth_serv/iCA-server/server.pem"
+ params["private_key"] = "auth_serv/iCA-server/server.key"
+ fn = ica_ocsp("server.pem")
+ params["ocsp_stapling_response"] = fn
+ try:
+ hostapd.add_ap(apdev[0], params)
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
+ identity="tls user",
+ ca_cert="auth_serv/iCA-user/ca-and-root.pem",
+ client_cert="auth_serv/iCA-user/user.pem",
+ private_key="auth_serv/iCA-user/user.key",
+ scan_freq="2412", ocsp=3, wait_connect=False)
+ count = 0
+ while True:
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STATUS",
+ "CTRL-EVENT-EAP-SUCCESS"])
+ if ev is None:
+ raise Exception("Timeout on EAP status")
+ if "CTRL-EVENT-EAP-SUCCESS" in ev:
+ raise Exception("Unexpected EAP-Success")
+ if 'bad certificate status response' in ev:
+ break
+ if 'certificate revoked' in ev:
+ break
+ count = count + 1
+ if count > 10:
+ raise Exception("Unexpected number of EAP status messages")
+
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"])
+ if ev is None:
+ raise Exception("Timeout on EAP failure report")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ finally:
+ os.unlink(fn)
+
+def test_ap_wpa2_eap_tls_intermediate_ca_ocsp_multi(dev, apdev, params):
+ """EAP-TLS with intermediate server/user CA and OCSP multi OK"""
+ check_ocsp_support(dev[0])
+ check_ocsp_multi_support(dev[0])
+
params = int_eap_server_params()
- params["ocsp_stapling_response"] = ocsp
- hostapd.add_ap(apdev[0]['ifname'], params)
- dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
- identity="pap user", ca_cert="auth_serv/ca.pem",
- anonymous_identity="ttls", password="password",
- phase2="auth=PAP", ocsp=1, scan_freq="2412")
+ params["ca_cert"] = "auth_serv/iCA-server/ca-and-root.pem"
+ params["server_cert"] = "auth_serv/iCA-server/server.pem"
+ params["private_key"] = "auth_serv/iCA-server/server.key"
+ fn = ica_ocsp("server.pem")
+ fn2 = root_ocsp("auth_serv/iCA-server/cacert.pem")
+ params["ocsp_stapling_response"] = fn
+
+ with open(fn, "r") as f:
+ resp_server = f.read()
+ with open(fn2, "r") as f:
+ resp_ica = f.read()
+
+ fd3, fn3 = tempfile.mkstemp()
+ try:
+ f = os.fdopen(fd3, 'w')
+ f.write(struct.pack(">L", len(resp_server))[1:4])
+ f.write(resp_server)
+ f.write(struct.pack(">L", len(resp_ica))[1:4])
+ f.write(resp_ica)
+ f.close()
+
+ params["ocsp_stapling_response_multi"] = fn3
+
+ hostapd.add_ap(apdev[0], params)
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
+ identity="tls user",
+ ca_cert="auth_serv/iCA-user/ca-and-root.pem",
+ client_cert="auth_serv/iCA-user/user.pem",
+ private_key="auth_serv/iCA-user/user.key",
+ scan_freq="2412", ocsp=3)
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ finally:
+ os.unlink(fn)
+ os.unlink(fn2)
+ os.unlink(fn3)
+
+def test_ap_wpa2_eap_tls_ocsp_multi_revoked(dev, apdev, params):
+ """EAP-TLS and CA signed OCSP multi response (revoked)"""
+ check_ocsp_support(dev[0])
+ check_ocsp_multi_support(dev[0])
+
+ ocsp_revoked = os.path.join(params['logdir'],
+ "ocsp-resp-ca-signed-revoked.der")
+ if not os.path.exists(ocsp_revoked):
+ raise HwsimSkip("No OCSP response (revoked) available")
+ ocsp_unknown = os.path.join(params['logdir'],
+ "ocsp-resp-ca-signed-unknown.der")
+ if not os.path.exists(ocsp_unknown):
+ raise HwsimSkip("No OCSP response(unknown) available")
+
+ with open(ocsp_revoked, "r") as f:
+ resp_revoked = f.read()
+ with open(ocsp_unknown, "r") as f:
+ resp_unknown = f.read()
+
+ fd, fn = tempfile.mkstemp()
+ try:
+ # This is not really a valid order of the OCSPResponse items in the
+ # list, but this works for now to verify parsing and processing of
+ # multiple responses.
+ f = os.fdopen(fd, 'w')
+ f.write(struct.pack(">L", len(resp_unknown))[1:4])
+ f.write(resp_unknown)
+ f.write(struct.pack(">L", len(resp_revoked))[1:4])
+ f.write(resp_revoked)
+ f.write(struct.pack(">L", 0)[1:4])
+ f.write(struct.pack(">L", len(resp_unknown))[1:4])
+ f.write(resp_unknown)
+ f.close()
+
+ params = int_eap_server_params()
+ params["ocsp_stapling_response_multi"] = fn
+ hostapd.add_ap(apdev[0], params)
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
+ identity="tls user", ca_cert="auth_serv/ca.pem",
+ private_key="auth_serv/user.pkcs12",
+ private_key_passwd="whatever", ocsp=1,
+ wait_connect=False, scan_freq="2412")
+ count = 0
+ while True:
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STATUS",
+ "CTRL-EVENT-EAP-SUCCESS"])
+ if ev is None:
+ raise Exception("Timeout on EAP status")
+ if "CTRL-EVENT-EAP-SUCCESS" in ev:
+ raise Exception("Unexpected EAP-Success")
+ if 'bad certificate status response' in ev:
+ break
+ if 'certificate revoked' in ev:
+ break
+ count = count + 1
+ if count > 10:
+ raise Exception("Unexpected number of EAP status messages")
+ finally:
+ os.unlink(fn)
def test_ap_wpa2_eap_tls_domain_suffix_match_cn_full(dev, apdev):
"""WPA2-Enterprise using EAP-TLS and domain suffix match (CN)"""
+ check_domain_match_full(dev[0])
params = int_eap_server_params()
params["server_cert"] = "auth_serv/server-no-dnsname.pem"
params["private_key"] = "auth_serv/server-no-dnsname.key"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
identity="tls user", ca_cert="auth_serv/ca.pem",
private_key="auth_serv/user.pkcs12",
def test_ap_wpa2_eap_tls_domain_match_cn(dev, apdev):
"""WPA2-Enterprise using EAP-TLS and domainmatch (CN)"""
+ check_domain_match(dev[0])
params = int_eap_server_params()
params["server_cert"] = "auth_serv/server-no-dnsname.pem"
params["private_key"] = "auth_serv/server-no-dnsname.key"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
identity="tls user", ca_cert="auth_serv/ca.pem",
private_key="auth_serv/user.pkcs12",
params = int_eap_server_params()
params["server_cert"] = "auth_serv/server-no-dnsname.pem"
params["private_key"] = "auth_serv/server-no-dnsname.key"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[1].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
identity="tls user", ca_cert="auth_serv/ca.pem",
private_key="auth_serv/user.pkcs12",
def test_ap_wpa2_eap_tls_domain_suffix_mismatch_cn(dev, apdev):
"""WPA2-Enterprise using EAP-TLS and domain suffix mismatch (CN)"""
+ check_domain_suffix_match(dev[0])
params = int_eap_server_params()
params["server_cert"] = "auth_serv/server-no-dnsname.pem"
params["private_key"] = "auth_serv/server-no-dnsname.key"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
identity="tls user", ca_cert="auth_serv/ca.pem",
private_key="auth_serv/user.pkcs12",
def test_ap_wpa2_eap_tls_domain_mismatch_cn(dev, apdev):
"""WPA2-Enterprise using EAP-TLS and domain mismatch (CN)"""
+ check_domain_match(dev[0])
params = int_eap_server_params()
params["server_cert"] = "auth_serv/server-no-dnsname.pem"
params["private_key"] = "auth_serv/server-no-dnsname.key"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
identity="tls user", ca_cert="auth_serv/ca.pem",
private_key="auth_serv/user.pkcs12",
params = int_eap_server_params()
params["server_cert"] = "auth_serv/server-expired.pem"
params["private_key"] = "auth_serv/server-expired.key"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="mschap user", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAP",
params = int_eap_server_params()
params["server_cert"] = "auth_serv/server-expired.pem"
params["private_key"] = "auth_serv/server-expired.key"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="mschap user", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAP",
params = int_eap_server_params()
params["server_cert"] = "auth_serv/server-long-duration.pem"
params["private_key"] = "auth_serv/server-long-duration.key"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="mschap user", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAP",
params = int_eap_server_params()
params["server_cert"] = "auth_serv/server-eku-client.pem"
params["private_key"] = "auth_serv/server-eku-client.key"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="mschap user", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAP",
params = int_eap_server_params()
params["server_cert"] = "auth_serv/server-eku-client-server.pem"
params["private_key"] = "auth_serv/server-eku-client-server.key"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="mschap user", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAP",
params = int_eap_server_params()
del params["server_cert"]
params["private_key"] = "auth_serv/server.pkcs12"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
+ identity="mschap user", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAP",
+ scan_freq="2412")
+
+def test_ap_wpa2_eap_ttls_server_pkcs12_extra(dev, apdev):
+ """EAP-TTLS and server PKCS#12 file with extra certs"""
+ skip_with_fips(dev[0])
+ params = int_eap_server_params()
+ del params["server_cert"]
+ params["private_key"] = "auth_serv/server-extra.pkcs12"
+ params["private_key_passwd"] = "whatever"
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="mschap user", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAP",
def test_ap_wpa2_eap_ttls_dh_params(dev, apdev):
"""WPA2-Enterprise connection using EAP-TTLS/CHAP and setting DH params"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "pap user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "pap user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.der", phase2="auth=PAP",
dh_file="auth_serv/dh.conf")
def test_ap_wpa2_eap_ttls_dh_params_dsa(dev, apdev):
"""WPA2-Enterprise connection using EAP-TTLS and setting DH params (DSA)"""
+ check_dh_dsa_support(dev[0])
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "pap user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "pap user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.der", phase2="auth=PAP",
dh_file="auth_serv/dsaparam.pem")
"""EAP-TTLS and DH params file not found"""
skip_with_fips(dev[0])
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="mschap user", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAP",
"""EAP-TTLS and invalid DH params file"""
skip_with_fips(dev[0])
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="mschap user", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAP",
def test_ap_wpa2_eap_ttls_dh_params_blob(dev, apdev):
"""WPA2-Enterprise connection using EAP-TTLS/CHAP and setting DH params from blob"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dh = read_pem("auth_serv/dh2.conf")
if "OK" not in dev[0].request("SET blob dhparams " + dh.encode("hex")):
raise Exception("Could not set dhparams blob")
- eap_connect(dev[0], apdev[0], "TTLS", "pap user",
+ eap_connect(dev[0], hapd, "TTLS", "pap user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.der", phase2="auth=PAP",
dh_file="blob://dhparams")
"""WPA2-Enterprise using EAP-TTLS and alternative server dhparams"""
params = int_eap_server_params()
params["dh_file"] = "auth_serv/dh2.conf"
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "pap user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "pap user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.der", phase2="auth=PAP")
"""WPA2-Enterprise using EAP-TTLS and alternative server dhparams (DSA)"""
params = int_eap_server_params()
params["dh_file"] = "auth_serv/dsaparam.pem"
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "pap user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "pap user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.der", phase2="auth=PAP")
"""EAP-TLS server and dhparams file not found"""
params = int_eap_server_params()
params["dh_file"] = "auth_serv/dh-no-such-file.conf"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
+ hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
if "FAIL" not in hapd.request("ENABLE"):
raise Exception("Invalid configuration accepted")
"""EAP-TLS server and invalid dhparams file"""
params = int_eap_server_params()
params["dh_file"] = "auth_serv/ca.pem"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
+ hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
if "FAIL" not in hapd.request("ENABLE"):
raise Exception("Invalid configuration accepted")
"""WPA2-Enterprise and Authenticator forcing reauthentication"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
params['eap_reauth_period'] = '2'
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "PAX", "pax.user@example.com",
password_hex="0123456789abcdef0123456789abcdef")
logger.info("Wait for reauthentication")
ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=10)
"""Optional displayable message in EAP Request-Identity"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
params['eap_message'] = 'hello\\0networkid=netw,nasid=foo,portid=0,NAIRealms=example.com'
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "PAX", "pax.user@example.com",
password_hex="0123456789abcdef0123456789abcdef")
def test_ap_wpa2_eap_sim_aka_result_ind(dev, apdev):
params = int_eap_server_params()
params['eap_sim_db'] = "unix:/tmp/hlr_auc_gw.sock"
params['eap_sim_aka_result_ind'] = "1"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
- eap_connect(dev[0], apdev[0], "SIM", "1232010000000000",
+ eap_connect(dev[0], hapd, "SIM", "1232010000000000",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
phase1="result_ind=1")
eap_reauth(dev[0], "SIM")
- eap_connect(dev[1], apdev[0], "SIM", "1232010000000000",
+ eap_connect(dev[1], hapd, "SIM", "1232010000000000",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
dev[0].request("REMOVE_NETWORK all")
dev[1].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "AKA", "0232010000000000",
+ eap_connect(dev[0], hapd, "AKA", "0232010000000000",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123",
phase1="result_ind=1")
eap_reauth(dev[0], "AKA")
- eap_connect(dev[1], apdev[0], "AKA", "0232010000000000",
+ eap_connect(dev[1], hapd, "AKA", "0232010000000000",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123")
dev[0].request("REMOVE_NETWORK all")
dev[1].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "AKA'", "6555444333222111",
+ eap_connect(dev[0], hapd, "AKA'", "6555444333222111",
password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123",
phase1="result_ind=1")
eap_reauth(dev[0], "AKA'")
- eap_connect(dev[1], apdev[0], "AKA'", "6555444333222111",
+ eap_connect(dev[1], hapd, "AKA'", "6555444333222111",
password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123")
def test_ap_wpa2_eap_too_many_roundtrips(dev, apdev):
"""WPA2-Enterprise connection resulting in too many EAP roundtrips"""
skip_with_fips(dev[0])
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP WPA-EAP-SHA256",
eap="TTLS", identity="mschap user",
wait_connect=False, scan_freq="2412", ieee80211w="1",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAP",
- fragment_size="10")
- ev = dev[0].wait_event(["EAP: more than"], timeout=20)
- if ev is None:
+ fragment_size="8")
+ ev = dev[0].wait_event(["EAP: more than",
+ "CTRL-EVENT-EAP-SUCCESS"], timeout=20)
+ if ev is None or "EAP: more than" not in ev:
raise Exception("EAP roundtrip limit not reached")
def test_ap_wpa2_eap_expanded_nak(dev, apdev):
"""WPA2-Enterprise connection with EAP resulting in expanded NAK"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP WPA-EAP-SHA256",
eap="PSK", identity="vendor-test",
password_hex="ff23456789abcdef0123456789abcdef",
found = False
for i in range(0, 5):
- ev = dev[0].wait_event(["CTRL-EVENT-EAP-STATUS"], timeout=10)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STATUS"], timeout=16)
if ev is None:
raise Exception("Association and EAP start timed out")
if "refuse proposed method" in ev:
try:
params = int_eap_server_params()
params["eap_user_file"] = "sqlite:" + dbfile
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "user-mschapv2",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "user-mschapv2",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2")
dev[0].request("REMOVE_NETWORK all")
- eap_connect(dev[1], apdev[0], "TTLS", "user-mschap",
+ eap_connect(dev[1], hapd, "TTLS", "user-mschap",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAP")
dev[1].request("REMOVE_NETWORK all")
- eap_connect(dev[0], apdev[0], "TTLS", "user-chap",
+ eap_connect(dev[0], hapd, "TTLS", "user-chap",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=CHAP")
- eap_connect(dev[1], apdev[0], "TTLS", "user-pap",
+ eap_connect(dev[1], hapd, "TTLS", "user-pap",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=PAP")
finally:
def test_ap_wpa2_eap_non_ascii_identity(dev, apdev):
"""WPA2-Enterprise connection attempt using non-ASCII identity"""
params = int_eap_server_params()
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="\x80", password="password", wait_connect=False)
dev[1].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="a\x80", password="password", wait_connect=False)
for i in range(0, 2):
- ev = dev[i].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=10)
+ ev = dev[i].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=16)
if ev is None:
raise Exception("Association and EAP start timed out")
ev = dev[i].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=10)
def test_ap_wpa2_eap_non_ascii_identity2(dev, apdev):
"""WPA2-Enterprise connection attempt using non-ASCII identity"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="\x80", password="password", wait_connect=False)
dev[1].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="a\x80", password="password", wait_connect=False)
for i in range(0, 2):
- ev = dev[i].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=10)
+ ev = dev[i].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=16)
if ev is None:
raise Exception("Association and EAP start timed out")
ev = dev[i].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=10)
if not tls.startswith("OpenSSL"):
raise HwsimSkip("TLS library is not OpenSSL: " + tls)
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "pap user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "pap user",
anonymous_identity="ttls", password="password",
openssl_ciphers="AES128",
ca_cert="auth_serv/ca.pem", phase2="auth=PAP")
- eap_connect(dev[1], apdev[0], "TTLS", "pap user",
+ eap_connect(dev[1], hapd, "TTLS", "pap user",
anonymous_identity="ttls", password="password",
openssl_ciphers="EXPORT",
ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
raise HwsimSkip("wpa_supplicant TLS library is not OpenSSL: " + tls)
params = int_eap_server_params()
params['openssl_ciphers'] = "AES256"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
tls = hapd.request("GET tls_library")
if not tls.startswith("OpenSSL"):
raise HwsimSkip("hostapd TLS library is not OpenSSL: " + tls)
- eap_connect(dev[0], apdev[0], "TTLS", "pap user",
+ eap_connect(dev[0], hapd, "TTLS", "pap user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=PAP")
- eap_connect(dev[1], apdev[0], "TTLS", "pap user",
+ eap_connect(dev[1], hapd, "TTLS", "pap user",
anonymous_identity="ttls", password="password",
openssl_ciphers="AES128",
ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
expect_failure=True)
- eap_connect(dev[2], apdev[0], "TTLS", "pap user",
+ eap_connect(dev[2], hapd, "TTLS", "pap user",
anonymous_identity="ttls", password="password",
openssl_ciphers="HIGH:!ADH",
ca_cert="auth_serv/ca.pem", phase2="auth=PAP")
params['openssl_ciphers'] = "FOO"
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params, no_enable=True)
+ hapd2 = hostapd.add_ap(apdev[1], params, no_enable=True)
if "FAIL" not in hapd2.request("ENABLE"):
raise Exception("Invalid openssl_ciphers value accepted")
def test_wpa2_eap_ttls_pap_key_lifetime_in_memory(dev, apdev, params):
"""Key lifetime in memory with WPA2-Enterprise using EAP-TTLS/PAP"""
p = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], p)
+ hapd = hostapd.add_ap(apdev[0], p)
password = "63d2d21ac3c09ed567ee004a34490f1d16e7fa5835edf17ddba70a63f1a90a25"
pid = find_wpas_process(dev[0])
- id = eap_connect(dev[0], apdev[0], "TTLS", "pap-secret",
+ id = eap_connect(dev[0], hapd, "TTLS", "pap-secret",
anonymous_identity="ttls", password=password,
ca_cert="auth_serv/ca.pem", phase2="auth=PAP")
+ # The decrypted copy of GTK is freed only after the CTRL-EVENT-CONNECTED
+ # event has been delivered, so verify that wpa_supplicant has returned to
+ # eloop before reading process memory.
time.sleep(1)
+ dev[0].ping()
buf = read_process_memory(pid, password)
dev[0].request("DISCONNECT")
if tk in buf:
raise Exception("TK found from memory")
if gtk in buf:
+ get_key_locations(buf, gtk, "GTK")
raise Exception("GTK found from memory")
logger.info("Checking keys in memory after disassociation")
def test_ap_wpa2_eap_unexpected_wep_eapol_key(dev, apdev):
"""WPA2-Enterprise connection and unexpected WEP EAPOL-Key"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
- eap_connect(dev[0], apdev[0], "TTLS", "pap user",
+ eap_connect(dev[0], hapd, "TTLS", "pap user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=PAP")
def _test_ap_wpa2_eap_in_bridge(dev, apdev):
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
br_ifname='sta-br0'
ifname='wlan5'
subprocess.call(['iw', ifname, 'set', '4addr', 'on'])
subprocess.check_call(['brctl', 'addif', br_ifname, ifname])
wpas.interface_add(ifname, br_ifname=br_ifname)
+ wpas.dump_monitor()
- id = eap_connect(wpas, apdev[0], "PAX", "pax.user@example.com",
+ id = eap_connect(wpas, hapd, "PAX", "pax.user@example.com",
password_hex="0123456789abcdef0123456789abcdef")
+ wpas.dump_monitor()
eap_reauth(wpas, "PAX")
+ wpas.dump_monitor()
# Try again as a regression test for packet socket workaround
eap_reauth(wpas, "PAX")
+ wpas.dump_monitor()
wpas.request("DISCONNECT")
wpas.wait_disconnected()
+ wpas.dump_monitor()
wpas.request("RECONNECT")
wpas.wait_connected()
+ wpas.dump_monitor()
def test_ap_wpa2_eap_session_ticket(dev, apdev):
"""WPA2-Enterprise connection using EAP-TTLS and TLS session ticket enabled"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
key_mgmt = hapd.get_config()['key_mgmt']
if key_mgmt.split(' ')[0] != "WPA-EAP":
raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
- eap_connect(dev[0], apdev[0], "TTLS", "pap user",
+ eap_connect(dev[0], hapd, "TTLS", "pap user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem",
phase1="tls_disable_session_ticket=0", phase2="auth=PAP")
def test_ap_wpa2_eap_no_workaround(dev, apdev):
"""WPA2-Enterprise connection using EAP-TTLS and eap_workaround=0"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
key_mgmt = hapd.get_config()['key_mgmt']
if key_mgmt.split(' ')[0] != "WPA-EAP":
raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
- eap_connect(dev[0], apdev[0], "TTLS", "pap user",
+ eap_connect(dev[0], hapd, "TTLS", "pap user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", eap_workaround='0',
phase2="auth=PAP")
"""EAP-TLS and server checking CRL"""
params = int_eap_server_params()
params['check_crl'] = '1'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
# check_crl=1 and no CRL available --> reject connection
- eap_connect(dev[0], apdev[0], "TLS", "tls user", ca_cert="auth_serv/ca.pem",
+ eap_connect(dev[0], hapd, "TLS", "tls user", ca_cert="auth_serv/ca.pem",
client_cert="auth_serv/user.pem",
private_key="auth_serv/user.key", expect_failure=True)
dev[0].request("REMOVE_NETWORK all")
hapd.enable()
# check_crl=1 and valid CRL --> accept
- eap_connect(dev[0], apdev[0], "TLS", "tls user", ca_cert="auth_serv/ca.pem",
+ eap_connect(dev[0], hapd, "TLS", "tls user", ca_cert="auth_serv/ca.pem",
client_cert="auth_serv/user.pem",
private_key="auth_serv/user.key")
dev[0].request("REMOVE_NETWORK all")
hapd.enable()
# check_crl=2 and valid CRL --> accept
- eap_connect(dev[0], apdev[0], "TLS", "tls user", ca_cert="auth_serv/ca.pem",
+ eap_connect(dev[0], hapd, "TLS", "tls user", ca_cert="auth_serv/ca.pem",
client_cert="auth_serv/user.pem",
private_key="auth_serv/user.key")
dev[0].request("REMOVE_NETWORK all")
"""EAP-TLS and OOM"""
check_subject_match_support(dev[0])
check_altsubject_match_support(dev[0])
+ check_domain_match(dev[0])
check_domain_match_full(dev[0])
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
tests = [ (1, "tls_connection_set_subject_match"),
(2, "tls_connection_set_subject_match"),
"""WPA2-Enterprise connection using MAC ACL"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
params["macaddr_acl"] = "2"
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[1], apdev[0], "TLS", "tls user", ca_cert="auth_serv/ca.pem",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[1], hapd, "TLS", "tls user", ca_cert="auth_serv/ca.pem",
client_cert="auth_serv/user.pem",
private_key="auth_serv/user.key")
def test_ap_wpa2_eap_oom(dev, apdev):
"""EAP server and OOM"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
with alloc_fail(hapd, 1, "eapol_auth_alloc"):
private_key="auth_serv/user.key",
scan_freq="2412")
-def check_tls_ver(dev, ap, phase1, expected):
- eap_connect(dev, ap, "TLS", "tls user", ca_cert="auth_serv/ca.pem",
+def check_tls_ver(dev, hapd, phase1, expected):
+ eap_connect(dev, hapd, "TLS", "tls user", ca_cert="auth_serv/ca.pem",
client_cert="auth_serv/user.pem",
private_key="auth_serv/user.key",
phase1=phase1)
def test_ap_wpa2_eap_tls_versions(dev, apdev):
"""EAP-TLS and TLS version configuration"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
tls = dev[0].request("GET tls_library")
if tls.startswith("OpenSSL"):
if "build=OpenSSL 1.0.2" in tls and "run=OpenSSL 1.0.2" in tls:
- check_tls_ver(dev[0], apdev[0],
+ check_tls_ver(dev[0], hapd,
"tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=1",
"TLSv1.2")
- check_tls_ver(dev[1], apdev[0],
+ elif tls.startswith("internal"):
+ check_tls_ver(dev[0], hapd,
+ "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=1", "TLSv1.2")
+ check_tls_ver(dev[1], hapd,
"tls_disable_tlsv1_0=1 tls_disable_tlsv1_2=1", "TLSv1.1")
- check_tls_ver(dev[2], apdev[0],
+ check_tls_ver(dev[2], hapd,
"tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1", "TLSv1")
def test_rsn_ie_proto_eap_sta(dev, apdev):
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
# This is the RSN element used normally by hostapd
params['own_ie_override'] = '30140100000fac040100000fac040100000fac010c00'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="GPSK",
identity="gpsk user",
password="abcdefghijklmnop0123456789abcdef",
dev[0].select_network(id, freq=2412)
dev[0].wait_connected()
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected()
+ dev[0].flush_scan_cache()
+
def check_tls_session_resumption_capa(dev, hapd):
tls = hapd.request("GET tls_library")
if not tls.startswith("OpenSSL"):
"""EAP-TTLS/PAP session resumption"""
params = int_eap_server_params()
params['tls_session_lifetime'] = '60'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
check_tls_session_resumption_capa(dev[0], hapd)
- eap_connect(dev[0], apdev[0], "TTLS", "pap user",
+ eap_connect(dev[0], hapd, "TTLS", "pap user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", eap_workaround='0',
phase2="auth=PAP")
"""EAP-TTLS/CHAP session resumption"""
params = int_eap_server_params()
params['tls_session_lifetime'] = '60'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
check_tls_session_resumption_capa(dev[0], hapd)
- eap_connect(dev[0], apdev[0], "TTLS", "chap user",
+ eap_connect(dev[0], hapd, "TTLS", "chap user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.der", phase2="auth=CHAP")
if dev[0].get_status_field("tls_session_reused") != '0':
def test_eap_ttls_mschap_session_resumption(dev, apdev):
"""EAP-TTLS/MSCHAP session resumption"""
+ check_domain_suffix_match(dev[0])
params = int_eap_server_params()
params['tls_session_lifetime'] = '60'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
check_tls_session_resumption_capa(dev[0], hapd)
- eap_connect(dev[0], apdev[0], "TTLS", "mschap user",
+ eap_connect(dev[0], hapd, "TTLS", "mschap user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAP",
domain_suffix_match="server.w1.fi")
def test_eap_ttls_mschapv2_session_resumption(dev, apdev):
"""EAP-TTLS/MSCHAPv2 session resumption"""
+ check_domain_suffix_match(dev[0])
check_eap_capa(dev[0], "MSCHAPV2")
params = int_eap_server_params()
params['tls_session_lifetime'] = '60'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
check_tls_session_resumption_capa(dev[0], hapd)
- eap_connect(dev[0], apdev[0], "TTLS", "DOMAIN\mschapv2 user",
+ eap_connect(dev[0], hapd, "TTLS", "DOMAIN\mschapv2 user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
domain_suffix_match="server.w1.fi")
"""EAP-TTLS/EAP-GTC session resumption"""
params = int_eap_server_params()
params['tls_session_lifetime'] = '60'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
check_tls_session_resumption_capa(dev[0], hapd)
- eap_connect(dev[0], apdev[0], "TTLS", "user",
+ eap_connect(dev[0], hapd, "TTLS", "user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", phase2="autheap=GTC")
if dev[0].get_status_field("tls_session_reused") != '0':
"""EAP-TTLS session resumption disabled on server"""
params = int_eap_server_params()
params['tls_session_lifetime'] = '0'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TTLS", "pap user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TTLS", "pap user",
anonymous_identity="ttls", password="password",
ca_cert="auth_serv/ca.pem", eap_workaround='0',
phase2="auth=PAP")
"""EAP-PEAP session resumption"""
params = int_eap_server_params()
params['tls_session_lifetime'] = '60'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
+ check_tls_session_resumption_capa(dev[0], hapd)
+ eap_connect(dev[0], hapd, "PEAP", "user",
+ anonymous_identity="peap", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2")
+ if dev[0].get_status_field("tls_session_reused") != '0':
+ raise Exception("Unexpected session resumption on the first connection")
+
+ dev[0].request("REAUTHENTICATE")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
+ if ev is None:
+ raise Exception("EAP success timed out")
+ ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=10)
+ if ev is None:
+ raise Exception("Key handshake with the AP timed out")
+ if dev[0].get_status_field("tls_session_reused") != '1':
+ raise Exception("Session resumption not used on the second connection")
+
+def test_eap_peap_session_resumption_crypto_binding(dev, apdev):
+ """EAP-PEAP session resumption with crypto binding"""
+ params = int_eap_server_params()
+ params['tls_session_lifetime'] = '60'
+ hapd = hostapd.add_ap(apdev[0], params)
check_tls_session_resumption_capa(dev[0], hapd)
- eap_connect(dev[0], apdev[0], "PEAP", "user",
+ eap_connect(dev[0], hapd, "PEAP", "user",
anonymous_identity="peap", password="password",
+ phase1="peapver=0 crypto_binding=2",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2")
if dev[0].get_status_field("tls_session_reused") != '0':
raise Exception("Unexpected session resumption on the first connection")
def test_eap_peap_no_session_resumption(dev, apdev):
"""EAP-PEAP session resumption disabled on server"""
params = int_eap_server_params()
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "PEAP", "user",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "PEAP", "user",
anonymous_identity="peap", password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2")
if dev[0].get_status_field("tls_session_reused") != '0':
"""EAP-TLS session resumption"""
params = int_eap_server_params()
params['tls_session_lifetime'] = '60'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
check_tls_session_resumption_capa(dev[0], hapd)
- eap_connect(dev[0], apdev[0], "TLS", "tls user", ca_cert="auth_serv/ca.pem",
+ eap_connect(dev[0], hapd, "TLS", "tls user", ca_cert="auth_serv/ca.pem",
client_cert="auth_serv/user.pem",
private_key="auth_serv/user.key")
if dev[0].get_status_field("tls_session_reused") != '0':
"""EAP-TLS session resumption"""
params = int_eap_server_params()
params['tls_session_lifetime'] = '1'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
check_tls_session_resumption_capa(dev[0], hapd)
- eap_connect(dev[0], apdev[0], "TLS", "tls user", ca_cert="auth_serv/ca.pem",
+ eap_connect(dev[0], hapd, "TLS", "tls user", ca_cert="auth_serv/ca.pem",
client_cert="auth_serv/user.pem",
private_key="auth_serv/user.key")
if dev[0].get_status_field("tls_session_reused") != '0':
def test_eap_tls_no_session_resumption(dev, apdev):
"""EAP-TLS session resumption disabled on server"""
params = int_eap_server_params()
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TLS", "tls user", ca_cert="auth_serv/ca.pem",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TLS", "tls user", ca_cert="auth_serv/ca.pem",
client_cert="auth_serv/user.pem",
private_key="auth_serv/user.key")
if dev[0].get_status_field("tls_session_reused") != '0':
"server_cert": "auth_serv/server.pem",
"private_key": "auth_serv/server.key",
"tls_session_lifetime": "60" }
- authsrv = hostapd.add_ap(apdev[1]['ifname'], params)
+ authsrv = hostapd.add_ap(apdev[1], params)
check_tls_session_resumption_capa(dev[0], authsrv)
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
params['auth_server_port'] = "18128"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TLS", "tls user", ca_cert="auth_serv/ca.pem",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TLS", "tls user", ca_cert="auth_serv/ca.pem",
client_cert="auth_serv/user.pem",
private_key="auth_serv/user.key")
if dev[0].get_status_field("tls_session_reused") != '0':
"server_cert": "auth_serv/server.pem",
"private_key": "auth_serv/server.key",
"tls_session_lifetime": "0" }
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
params['auth_server_port'] = "18128"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "TLS", "tls user", ca_cert="auth_serv/ca.pem",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "TLS", "tls user", ca_cert="auth_serv/ca.pem",
client_cert="auth_serv/user.pem",
private_key="auth_serv/user.key")
if dev[0].get_status_field("tls_session_reused") != '0':
raise Exception("Key handshake with the AP timed out")
if dev[0].get_status_field("tls_session_reused") != '0':
raise Exception("Unexpected session resumption on the second connection")
+
+def test_eap_mschapv2_errors(dev, apdev):
+ """EAP-MSCHAPv2 error cases"""
+ check_eap_capa(dev[0], "MSCHAPV2")
+ check_eap_capa(dev[0], "FAST")
+
+ params = hostapd.wpa2_eap_params(ssid="test-wpa-eap")
+ hapd = hostapd.add_ap(apdev[0], params)
+ dev[0].connect("test-wpa-eap", key_mgmt="WPA-EAP", eap="MSCHAPV2",
+ identity="phase1-user", password="password",
+ scan_freq="2412")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ (1, "hash_nt_password_hash;mschapv2_derive_response"),
+ (1, "nt_password_hash;mschapv2_derive_response"),
+ (1, "nt_password_hash;=mschapv2_derive_response"),
+ (1, "generate_nt_response;mschapv2_derive_response"),
+ (1, "generate_authenticator_response;mschapv2_derive_response"),
+ (1, "nt_password_hash;=mschapv2_derive_response"),
+ (1, "get_master_key;mschapv2_derive_response"),
+ (1, "os_get_random;eap_mschapv2_challenge_reply") ]
+ for count, func in tests:
+ with fail_test(dev[0], count, func):
+ dev[0].connect("test-wpa-eap", key_mgmt="WPA-EAP", eap="MSCHAPV2",
+ identity="phase1-user", password="password",
+ wait_connect=False, scan_freq="2412")
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ (1, "hash_nt_password_hash;mschapv2_derive_response"),
+ (1, "hash_nt_password_hash;=mschapv2_derive_response"),
+ (1, "generate_nt_response_pwhash;mschapv2_derive_response"),
+ (1, "generate_authenticator_response_pwhash;mschapv2_derive_response") ]
+ for count, func in tests:
+ with fail_test(dev[0], count, func):
+ dev[0].connect("test-wpa-eap", key_mgmt="WPA-EAP", eap="MSCHAPV2",
+ identity="phase1-user",
+ password_hex="hash:8846f7eaee8fb117ad06bdd830b7586c",
+ wait_connect=False, scan_freq="2412")
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ (1, "eap_mschapv2_init"),
+ (1, "eap_msg_alloc;eap_mschapv2_challenge_reply"),
+ (1, "eap_msg_alloc;eap_mschapv2_success"),
+ (1, "eap_mschapv2_getKey") ]
+ for count, func in tests:
+ with alloc_fail(dev[0], count, func):
+ dev[0].connect("test-wpa-eap", key_mgmt="WPA-EAP", eap="MSCHAPV2",
+ identity="phase1-user", password="password",
+ wait_connect=False, scan_freq="2412")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ (1, "eap_msg_alloc;eap_mschapv2_failure") ]
+ for count, func in tests:
+ with alloc_fail(dev[0], count, func):
+ dev[0].connect("test-wpa-eap", key_mgmt="WPA-EAP", eap="MSCHAPV2",
+ identity="phase1-user", password="wrong password",
+ wait_connect=False, scan_freq="2412")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ (2, "eap_mschapv2_init"),
+ (3, "eap_mschapv2_init") ]
+ for count, func in tests:
+ with alloc_fail(dev[0], count, func):
+ dev[0].connect("test-wpa-eap", key_mgmt="WPA-EAP", eap="FAST",
+ anonymous_identity="FAST", identity="user",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ phase1="fast_provisioning=1",
+ pac_file="blob://fast_pac",
+ wait_connect=False, scan_freq="2412")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+def test_eap_gpsk_errors(dev, apdev):
+ """EAP-GPSK error cases"""
+ params = hostapd.wpa2_eap_params(ssid="test-wpa-eap")
+ hapd = hostapd.add_ap(apdev[0], params)
+ dev[0].connect("test-wpa-eap", key_mgmt="WPA-EAP", eap="GPSK",
+ identity="gpsk user",
+ password="abcdefghijklmnop0123456789abcdef",
+ scan_freq="2412")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ (1, "os_get_random;eap_gpsk_send_gpsk_2", None),
+ (1, "eap_gpsk_derive_session_id;eap_gpsk_send_gpsk_2",
+ "cipher=1"),
+ (1, "eap_gpsk_derive_session_id;eap_gpsk_send_gpsk_2",
+ "cipher=2"),
+ (1, "eap_gpsk_derive_keys_helper", None),
+ (2, "eap_gpsk_derive_keys_helper", None),
+ (1, "eap_gpsk_compute_mic_aes;eap_gpsk_compute_mic;eap_gpsk_send_gpsk_2",
+ "cipher=1"),
+ (1, "hmac_sha256;eap_gpsk_compute_mic;eap_gpsk_send_gpsk_2",
+ "cipher=2"),
+ (1, "eap_gpsk_compute_mic;eap_gpsk_validate_gpsk_3_mic", None),
+ (1, "eap_gpsk_compute_mic;eap_gpsk_send_gpsk_4", None),
+ (1, "eap_gpsk_derive_mid_helper", None) ]
+ for count, func, phase1 in tests:
+ with fail_test(dev[0], count, func):
+ dev[0].connect("test-wpa-eap", key_mgmt="WPA-EAP", eap="GPSK",
+ identity="gpsk user",
+ password="abcdefghijklmnop0123456789abcdef",
+ phase1=phase1,
+ wait_connect=False, scan_freq="2412")
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ (1, "eap_gpsk_init"),
+ (2, "eap_gpsk_init"),
+ (3, "eap_gpsk_init"),
+ (1, "eap_gpsk_process_id_server"),
+ (1, "eap_msg_alloc;eap_gpsk_send_gpsk_2"),
+ (1, "eap_gpsk_derive_session_id;eap_gpsk_send_gpsk_2"),
+ (1, "eap_gpsk_derive_mid_helper;eap_gpsk_derive_session_id;eap_gpsk_send_gpsk_2"),
+ (1, "eap_gpsk_derive_keys"),
+ (1, "eap_gpsk_derive_keys_helper"),
+ (1, "eap_msg_alloc;eap_gpsk_send_gpsk_4"),
+ (1, "eap_gpsk_getKey"),
+ (1, "eap_gpsk_get_emsk"),
+ (1, "eap_gpsk_get_session_id") ]
+ for count, func in tests:
+ with alloc_fail(dev[0], count, func):
+ dev[0].request("ERP_FLUSH")
+ dev[0].connect("test-wpa-eap", key_mgmt="WPA-EAP", eap="GPSK",
+ identity="gpsk user", erp="1",
+ password="abcdefghijklmnop0123456789abcdef",
+ wait_connect=False, scan_freq="2412")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+def test_ap_wpa2_eap_sim_db(dev, apdev, params):
+ """EAP-SIM DB error cases"""
+ sockpath = '/tmp/hlr_auc_gw.sock-test'
+ try:
+ os.remove(sockpath)
+ except:
+ pass
+ hparams = int_eap_server_params()
+ hparams['eap_sim_db'] = 'unix:' + sockpath
+ hapd = hostapd.add_ap(apdev[0], hparams)
+
+ # Initial test with hlr_auc_gw socket not available
+ id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP WPA-EAP-SHA256",
+ eap="SIM", identity="1232010000000000",
+ password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
+ scan_freq="2412", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=10)
+ if ev is None:
+ raise Exception("EAP-Failure not reported")
+ dev[0].wait_disconnected()
+ dev[0].request("DISCONNECT")
+
+ # Test with invalid responses and response timeout
+
+ class test_handler(SocketServer.DatagramRequestHandler):
+ def handle(self):
+ data = self.request[0].strip()
+ socket = self.request[1]
+ logger.debug("Received hlr_auc_gw request: " + data)
+ # EAP-SIM DB: Failed to parse response string
+ socket.sendto("FOO", self.client_address)
+ # EAP-SIM DB: Failed to parse response string
+ socket.sendto("FOO 1", self.client_address)
+ # EAP-SIM DB: Unknown external response
+ socket.sendto("FOO 1 2", self.client_address)
+ logger.info("No proper response - wait for pending eap_sim_db request timeout")
+
+ server = SocketServer.UnixDatagramServer(sockpath, test_handler)
+ server.timeout = 1
+
+ dev[0].select_network(id)
+ server.handle_request()
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=10)
+ if ev is None:
+ raise Exception("EAP-Failure not reported")
+ dev[0].wait_disconnected()
+ dev[0].request("DISCONNECT")
+
+ # Test with a valid response
+
+ class test_handler2(SocketServer.DatagramRequestHandler):
+ def handle(self):
+ data = self.request[0].strip()
+ socket = self.request[1]
+ logger.debug("Received hlr_auc_gw request: " + data)
+ fname = os.path.join(params['logdir'],
+ 'hlr_auc_gw.milenage_db')
+ cmd = subprocess.Popen(['../../hostapd/hlr_auc_gw',
+ '-m', fname, data],
+ stdout=subprocess.PIPE)
+ res = cmd.stdout.read().strip()
+ cmd.stdout.close()
+ logger.debug("hlr_auc_gw response: " + res)
+ socket.sendto(res, self.client_address)
+
+ server.RequestHandlerClass = test_handler2
+
+ dev[0].select_network(id)
+ server.handle_request()
+ dev[0].wait_connected()
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected()
+
+def test_eap_tls_sha512(dev, apdev, params):
+ """EAP-TLS with SHA512 signature"""
+ params = int_eap_server_params()
+ params["ca_cert"] = "auth_serv/sha512-ca.pem"
+ params["server_cert"] = "auth_serv/sha512-server.pem"
+ params["private_key"] = "auth_serv/sha512-server.key"
+ hostapd.add_ap(apdev[0], params)
+
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
+ identity="tls user sha512",
+ ca_cert="auth_serv/sha512-ca.pem",
+ client_cert="auth_serv/sha512-user.pem",
+ private_key="auth_serv/sha512-user.key",
+ scan_freq="2412")
+ dev[1].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
+ identity="tls user sha512",
+ ca_cert="auth_serv/sha512-ca.pem",
+ client_cert="auth_serv/sha384-user.pem",
+ private_key="auth_serv/sha384-user.key",
+ scan_freq="2412")
+
+def test_eap_tls_sha384(dev, apdev, params):
+ """EAP-TLS with SHA384 signature"""
+ params = int_eap_server_params()
+ params["ca_cert"] = "auth_serv/sha512-ca.pem"
+ params["server_cert"] = "auth_serv/sha384-server.pem"
+ params["private_key"] = "auth_serv/sha384-server.key"
+ hostapd.add_ap(apdev[0], params)
+
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
+ identity="tls user sha512",
+ ca_cert="auth_serv/sha512-ca.pem",
+ client_cert="auth_serv/sha512-user.pem",
+ private_key="auth_serv/sha512-user.key",
+ scan_freq="2412")
+ dev[1].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
+ identity="tls user sha512",
+ ca_cert="auth_serv/sha512-ca.pem",
+ client_cert="auth_serv/sha384-user.pem",
+ private_key="auth_serv/sha384-user.key",
+ scan_freq="2412")
+
+def test_ap_wpa2_eap_assoc_rsn(dev, apdev):
+ """WPA2-Enterprise AP and association request RSN IE differences"""
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hostapd.add_ap(apdev[0], params)
+
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap-11w")
+ params["ieee80211w"] = "2"
+ hostapd.add_ap(apdev[1], params)
+
+ # Success cases with optional RSN IE fields removed one by one
+ tests = [ ("Normal wpa_supplicant assoc req RSN IE",
+ "30140100000fac040100000fac040100000fac010000"),
+ ("Extra PMKIDCount field in RSN IE",
+ "30160100000fac040100000fac040100000fac0100000000"),
+ ("Extra Group Management Cipher Suite in RSN IE",
+ "301a0100000fac040100000fac040100000fac0100000000000fac06"),
+ ("Extra undefined extension field in RSN IE",
+ "301c0100000fac040100000fac040100000fac0100000000000fac061122"),
+ ("RSN IE without RSN Capabilities",
+ "30120100000fac040100000fac040100000fac01"),
+ ("RSN IE without AKM", "300c0100000fac040100000fac04"),
+ ("RSN IE without pairwise", "30060100000fac04"),
+ ("RSN IE without group", "30020100") ]
+ for title, ie in tests:
+ logger.info(title)
+ set_test_assoc_ie(dev[0], ie)
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="GPSK",
+ identity="gpsk user",
+ password="abcdefghijklmnop0123456789abcdef",
+ scan_freq="2412")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ ("Normal wpa_supplicant assoc req RSN IE",
+ "30140100000fac040100000fac040100000fac01cc00"),
+ ("Group management cipher included in assoc req RSN IE",
+ "301a0100000fac040100000fac040100000fac01cc000000000fac06") ]
+ for title, ie in tests:
+ logger.info(title)
+ set_test_assoc_ie(dev[0], ie)
+ dev[0].connect("test-wpa2-eap-11w", key_mgmt="WPA-EAP", ieee80211w="1",
+ eap="GPSK", identity="gpsk user",
+ password="abcdefghijklmnop0123456789abcdef",
+ scan_freq="2412")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ ("Invalid group cipher", "30060100000fac02", 41),
+ ("Invalid pairwise cipher", "300c0100000fac040100000fac02", 42) ]
+ for title, ie, status in tests:
+ logger.info(title)
+ set_test_assoc_ie(dev[0], ie)
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="GPSK",
+ identity="gpsk user",
+ password="abcdefghijklmnop0123456789abcdef",
+ scan_freq="2412", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
+ if ev is None:
+ raise Exception("Association rejection not reported")
+ if "status_code=" + str(status) not in ev:
+ raise Exception("Unexpected status code: " + ev)
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
+
+ tests = [ ("Management frame protection not enabled",
+ "30140100000fac040100000fac040100000fac010000", 31),
+ ("Unsupported management group cipher",
+ "301a0100000fac040100000fac040100000fac01cc000000000fac0b", 31) ]
+ for title, ie, status in tests:
+ logger.info(title)
+ set_test_assoc_ie(dev[0], ie)
+ dev[0].connect("test-wpa2-eap-11w", key_mgmt="WPA-EAP", ieee80211w="1",
+ eap="GPSK", identity="gpsk user",
+ password="abcdefghijklmnop0123456789abcdef",
+ scan_freq="2412", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
+ if ev is None:
+ raise Exception("Association rejection not reported")
+ if "status_code=" + str(status) not in ev:
+ raise Exception("Unexpected status code: " + ev)
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
+
+def test_eap_tls_ext_cert_check(dev, apdev):
+ """EAP-TLS and external server certification validation"""
+ # With internal server certificate chain validation
+ id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
+ identity="tls user",
+ ca_cert="auth_serv/ca.pem",
+ client_cert="auth_serv/user.pem",
+ private_key="auth_serv/user.key",
+ phase1="tls_ext_cert_check=1", scan_freq="2412",
+ only_add_network=True)
+ run_ext_cert_check(dev, apdev, id)
+
+def test_eap_ttls_ext_cert_check(dev, apdev):
+ """EAP-TTLS and external server certification validation"""
+ # Without internal server certificate chain validation
+ id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
+ identity="pap user", anonymous_identity="ttls",
+ password="password", phase2="auth=PAP",
+ phase1="tls_ext_cert_check=1", scan_freq="2412",
+ only_add_network=True)
+ run_ext_cert_check(dev, apdev, id)
+
+def test_eap_peap_ext_cert_check(dev, apdev):
+ """EAP-PEAP and external server certification validation"""
+ # With internal server certificate chain validation
+ id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="PEAP",
+ identity="user", anonymous_identity="peap",
+ ca_cert="auth_serv/ca.pem",
+ password="password", phase2="auth=MSCHAPV2",
+ phase1="tls_ext_cert_check=1", scan_freq="2412",
+ only_add_network=True)
+ run_ext_cert_check(dev, apdev, id)
+
+def test_eap_fast_ext_cert_check(dev, apdev):
+ """EAP-FAST and external server certification validation"""
+ check_eap_capa(dev[0], "FAST")
+ # With internal server certificate chain validation
+ dev[0].request("SET blob fast_pac_auth_ext ")
+ id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="FAST",
+ identity="user", anonymous_identity="FAST",
+ ca_cert="auth_serv/ca.pem",
+ password="password", phase2="auth=GTC",
+ phase1="tls_ext_cert_check=1 fast_provisioning=2",
+ pac_file="blob://fast_pac_auth_ext",
+ scan_freq="2412",
+ only_add_network=True)
+ run_ext_cert_check(dev, apdev, id)
+
+def run_ext_cert_check(dev, apdev, net_id):
+ check_ext_cert_check_support(dev[0])
+ if not openssl_imported:
+ raise HwsimSkip("OpenSSL python method not available")
+
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].select_network(net_id)
+ certs = {}
+ while True:
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PEER-CERT",
+ "CTRL-REQ-EXT_CERT_CHECK",
+ "CTRL-EVENT-EAP-SUCCESS"], timeout=10)
+ if ev is None:
+ raise Exception("No peer server certificate event seen")
+ if "CTRL-EVENT-EAP-PEER-CERT" in ev:
+ depth = None
+ cert = None
+ vals = ev.split(' ')
+ for v in vals:
+ if v.startswith("depth="):
+ depth = int(v.split('=')[1])
+ elif v.startswith("cert="):
+ cert = v.split('=')[1]
+ if depth is not None and cert:
+ certs[depth] = binascii.unhexlify(cert)
+ elif "CTRL-EVENT-EAP-SUCCESS" in ev:
+ raise Exception("Unexpected EAP-Success")
+ elif "CTRL-REQ-EXT_CERT_CHECK" in ev:
+ id = ev.split(':')[0].split('-')[-1]
+ break
+ if 0 not in certs:
+ raise Exception("Server certificate not received")
+ if 1 not in certs:
+ raise Exception("Server certificate issuer not received")
+
+ cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_ASN1,
+ certs[0])
+ cn = cert.get_subject().commonName
+ logger.info("Server certificate CN=" + cn)
+
+ issuer = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_ASN1,
+ certs[1])
+ icn = issuer.get_subject().commonName
+ logger.info("Issuer certificate CN=" + icn)
+
+ if cn != "server.w1.fi":
+ raise Exception("Unexpected server certificate CN: " + cn)
+ if icn != "Root CA":
+ raise Exception("Unexpected server certificate issuer CN: " + icn)
+
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=0.1)
+ if ev:
+ raise Exception("Unexpected EAP-Success before external check result indication")
+
+ dev[0].request("CTRL-RSP-EXT_CERT_CHECK-" + id + ":good")
+ dev[0].wait_connected()
+
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected()
+ if "FAIL" in dev[0].request("PMKSA_FLUSH"):
+ raise Exception("PMKSA_FLUSH failed")
+ dev[0].request("SET blob fast_pac_auth_ext ")
+ dev[0].request("RECONNECT")
+
+ ev = dev[0].wait_event(["CTRL-REQ-EXT_CERT_CHECK"], timeout=10)
+ if ev is None:
+ raise Exception("No peer server certificate event seen (2)")
+ id = ev.split(':')[0].split('-')[-1]
+ dev[0].request("CTRL-RSP-EXT_CERT_CHECK-" + id + ":bad")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
+ if ev is None:
+ raise Exception("EAP-Failure not reported")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+def test_eap_tls_errors(dev, apdev):
+ """EAP-TLS error cases"""
+ params = int_eap_server_params()
+ params['fragment_size'] = '100'
+ hostapd.add_ap(apdev[0], params)
+ with alloc_fail(dev[0], 1,
+ "eap_peer_tls_reassemble_fragment"):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
+ identity="tls user", ca_cert="auth_serv/ca.pem",
+ client_cert="auth_serv/user.pem",
+ private_key="auth_serv/user.key",
+ wait_connect=False, scan_freq="2412")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with alloc_fail(dev[0], 1, "eap_tls_init"):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
+ identity="tls user", ca_cert="auth_serv/ca.pem",
+ client_cert="auth_serv/user.pem",
+ private_key="auth_serv/user.key",
+ wait_connect=False, scan_freq="2412")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with alloc_fail(dev[0], 1, "eap_peer_tls_ssl_init"):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
+ identity="tls user", ca_cert="auth_serv/ca.pem",
+ client_cert="auth_serv/user.pem",
+ private_key="auth_serv/user.key",
+ engine="1",
+ wait_connect=False, scan_freq="2412")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ ev = dev[0].wait_event(["CTRL-REQ-PIN"], timeout=5)
+ if ev is None:
+ raise Exception("No CTRL-REQ-PIN seen")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ "eap_peer_tls_derive_key;eap_tls_success",
+ "eap_peer_tls_derive_session_id;eap_tls_success",
+ "eap_tls_getKey",
+ "eap_tls_get_emsk",
+ "eap_tls_get_session_id" ]
+ for func in tests:
+ with alloc_fail(dev[0], 1, func):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
+ identity="tls user", ca_cert="auth_serv/ca.pem",
+ client_cert="auth_serv/user.pem",
+ private_key="auth_serv/user.key",
+ erp="1",
+ wait_connect=False, scan_freq="2412")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with alloc_fail(dev[0], 1, "eap_unauth_tls_init"):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="UNAUTH-TLS",
+ identity="unauth-tls", ca_cert="auth_serv/ca.pem",
+ wait_connect=False, scan_freq="2412")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with alloc_fail(dev[0], 1, "eap_peer_tls_ssl_init;eap_unauth_tls_init"):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="UNAUTH-TLS",
+ identity="unauth-tls", ca_cert="auth_serv/ca.pem",
+ wait_connect=False, scan_freq="2412")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with alloc_fail(dev[0], 1, "eap_wfa_unauth_tls_init"):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
+ eap="WFA-UNAUTH-TLS",
+ identity="osen@example.com", ca_cert="auth_serv/ca.pem",
+ wait_connect=False, scan_freq="2412")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with alloc_fail(dev[0], 1, "eap_peer_tls_ssl_init;eap_wfa_unauth_tls_init"):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
+ eap="WFA-UNAUTH-TLS",
+ identity="osen@example.com", ca_cert="auth_serv/ca.pem",
+ wait_connect=False, scan_freq="2412")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+def test_ap_wpa2_eap_status(dev, apdev):
+ """EAP state machine status information"""
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hostapd.add_ap(apdev[0], params)
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="PEAP",
+ identity="cert user",
+ ca_cert="auth_serv/ca.pem", phase2="auth=TLS",
+ ca_cert2="auth_serv/ca.pem",
+ client_cert2="auth_serv/user.pem",
+ private_key2="auth_serv/user.key",
+ scan_freq="2412", wait_connect=False)
+ success = False
+ states = []
+ method_states = []
+ decisions = []
+ req_methods = []
+ selected_methods = []
+ for i in range(100000):
+ s = dev[0].get_status(extra="VERBOSE")
+ if 'EAP state' in s:
+ state = s['EAP state']
+ if state:
+ if state not in states:
+ states.append(state)
+ if state == "SUCCESS":
+ success = True
+ break
+ if 'methodState' in s:
+ val = s['methodState']
+ if val not in method_states:
+ method_states.append(val)
+ if 'decision' in s:
+ val = s['decision']
+ if val not in decisions:
+ decisions.append(val)
+ if 'reqMethod' in s:
+ val = s['reqMethod']
+ if val not in req_methods:
+ req_methods.append(val)
+ if 'selectedMethod' in s:
+ val = s['selectedMethod']
+ if val not in selected_methods:
+ selected_methods.append(val)
+ logger.info("Iterations: %d" % i)
+ logger.info("EAP states: " + str(states))
+ logger.info("methodStates: " + str(method_states))
+ logger.info("decisions: " + str(decisions))
+ logger.info("reqMethods: " + str(req_methods))
+ logger.info("selectedMethods: " + str(selected_methods))
+ if not success:
+ raise Exception("EAP did not succeed")
+ dev[0].wait_connected()
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+def test_ap_wpa2_eap_gpsk_ptk_rekey_ap(dev, apdev):
+ """WPA2-Enterprise with EAP-GPSK and PTK rekey enforced by AP"""
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ params['wpa_ptk_rekey'] = '2'
+ hapd = hostapd.add_ap(apdev[0], params)
+ id = eap_connect(dev[0], hapd, "GPSK", "gpsk user",
+ password="abcdefghijklmnop0123456789abcdef")
+ ev = dev[0].wait_event(["WPA: Key negotiation completed"])
+ if ev is None:
+ raise Exception("PTK rekey timed out")
+ hwsim_utils.test_connectivity(dev[0], hapd)
+
+def test_ap_wpa2_eap_wildcard_ssid(dev, apdev):
+ """WPA2-Enterprise connection using EAP-GPSK and wildcard SSID"""
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ hapd = hostapd.add_ap(apdev[0], params)
+ dev[0].connect(bssid=apdev[0]['bssid'], key_mgmt="WPA-EAP", eap="GPSK",
+ identity="gpsk user",
+ password="abcdefghijklmnop0123456789abcdef",
+ scan_freq="2412")
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import binascii
import os
import time
-import subprocess
import logging
logger = logging.getLogger()
def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False,
sae=False, eap=False, fail_test=False, roams=1,
- pairwise_cipher="CCMP", group_cipher="TKIP CCMP"):
+ pairwise_cipher="CCMP", group_cipher="TKIP CCMP", ptk_rekey="0"):
logger.info("Connect to first AP")
if eap:
dev.connect(ssid, key_mgmt="FT-EAP", proto="WPA2", ieee80211w="1",
eap="GPSK", identity="gpsk user",
password="abcdefghijklmnop0123456789abcdef",
scan_freq="2412",
- pairwise=pairwise_cipher, group=group_cipher)
+ pairwise=pairwise_cipher, group=group_cipher,
+ wpa_ptk_rekey=ptk_rekey)
else:
if sae:
key_mgmt="FT-SAE"
key_mgmt="FT-PSK"
dev.connect(ssid, psk=passphrase, key_mgmt=key_mgmt, proto="WPA2",
ieee80211w="1", scan_freq="2412",
- pairwise=pairwise_cipher, group=group_cipher)
+ pairwise=pairwise_cipher, group=group_cipher,
+ wpa_ptk_rekey=ptk_rekey)
if dev.get_status_field('bssid') == apdev[0]['bssid']:
ap1 = apdev[0]
ap2 = apdev[1]
passphrase="12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase)
if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"):
passphrase="12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, roams=50)
passphrase="12345678"
params = ft_params1(rsn=False, ssid=ssid, passphrase=passphrase)
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
key_mgmt = hapd.get_config()['key_mgmt']
vals = key_mgmt.split(' ')
if vals[0] != "WPA-PSK" or vals[1] != "FT-PSK":
raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
params = ft_params2(rsn=False, ssid=ssid, passphrase=passphrase)
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase)
passphrase="12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
- params["ieee80211w"] = "2";
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
+ params["ieee80211w"] = "2"
+ hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
- params["ieee80211w"] = "2";
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ params["ieee80211w"] = "2"
+ hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase)
passphrase="12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True)
check_mib(dev[0], [ ("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-4"),
passphrase="12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
roams=50)
+@remote_compatible
def test_ap_ft_over_ds_unknown_target(dev, apdev):
"""WPA2-PSK-FT AP"""
ssid = "test-ft"
passphrase="12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd0 = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
dev[0].roam_over_ds("02:11:22:33:44:55", fail_test=True)
+@remote_compatible
def test_ap_ft_over_ds_unexpected(dev, apdev):
"""WPA2-PSK-FT AP over DS and unexpected response"""
ssid = "test-ft"
passphrase="12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd1 = hostapd.add_ap(apdev[1], params)
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
passphrase="12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
- params["ieee80211w"] = "2";
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
+ params["ieee80211w"] = "2"
+ hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
- params["ieee80211w"] = "2";
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ params["ieee80211w"] = "2"
+ hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True)
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True)
params = ft_params1(ssid=ssid, passphrase=passphrase)
params['wpa_key_mgmt'] = "FT-SAE"
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params['wpa_key_mgmt'] = "FT-SAE"
- hapd = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[1], params)
key_mgmt = hapd.get_config()['key_mgmt']
if key_mgmt.split(' ')[0] != "FT-SAE":
raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
params = ft_params1(ssid=ssid, passphrase=passphrase)
params['wpa_key_mgmt'] = "FT-SAE"
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params['wpa_key_mgmt'] = "FT-SAE"
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd1 = hostapd.add_ap(apdev[1], params)
dev[0].request("SET sae_groups ")
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, sae=True,
params['wpa_key_mgmt'] = "FT-EAP"
params["ieee8021x"] = "1"
params = dict(radius.items() + params.items())
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
key_mgmt = hapd.get_config()['key_mgmt']
if key_mgmt.split(' ')[0] != "FT-EAP":
raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
params['wpa_key_mgmt'] = "FT-EAP"
params["ieee8021x"] = "1"
params = dict(radius.items() + params.items())
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase, eap=True)
if "[WPA2-FT/EAP-CCMP]" not in dev[0].request("SCAN_RESULTS"):
check_mib(dev[0], [ ("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-3"),
("dot11RSNAAuthenticationSuiteSelected", "00-0f-ac-3") ])
+ # Verify EAPOL reauthentication after FT protocol
+ if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
+ ap = hapd
+ else:
+ ap = hapd1
+ ap.request("EAPOL_REAUTH " + dev[0].own_addr())
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
+ if ev is None:
+ raise Exception("EAP authentication did not start")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=5)
+ if ev is None:
+ raise Exception("EAP authentication did not succeed")
+ time.sleep(0.1)
+ hwsim_utils.test_connectivity(dev[0], ap)
+
def test_ap_ft_eap_pull(dev, apdev):
"""WPA2-EAP-FT AP (pull PMK)"""
ssid = "test-ft"
params["ieee8021x"] = "1"
params["pmk_r1_push"] = "0"
params = dict(radius.items() + params.items())
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
key_mgmt = hapd.get_config()['key_mgmt']
if key_mgmt.split(' ')[0] != "FT-EAP":
raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
params["ieee8021x"] = "1"
params["pmk_r1_push"] = "0"
params = dict(radius.items() + params.items())
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase, eap=True)
+@remote_compatible
def test_ap_ft_mismatching_rrb_key_push(dev, apdev):
"""WPA2-PSK-FT AP over DS with mismatching RRB key (push)"""
ssid = "test-ft"
passphrase="12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
- params["ieee80211w"] = "2";
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
+ params["ieee80211w"] = "2"
+ hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2_incorrect_rrb_key(ssid=ssid, passphrase=passphrase)
- params["ieee80211w"] = "2";
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ params["ieee80211w"] = "2"
+ hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
fail_test=True)
+@remote_compatible
def test_ap_ft_mismatching_rrb_key_pull(dev, apdev):
"""WPA2-PSK-FT AP over DS with mismatching RRB key (pull)"""
ssid = "test-ft"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2_incorrect_rrb_key(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
fail_test=True)
+@remote_compatible
def test_ap_ft_mismatching_r0kh_id_pull(dev, apdev):
"""WPA2-PSK-FT AP over DS with mismatching R0KH-ID (pull)"""
ssid = "test-ft"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
params["nas_identifier"] = "nas0.w1.fi"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
dev[0].roam_over_ds(apdev[1]['bssid'], fail_test=True)
+@remote_compatible
def test_ap_ft_mismatching_rrb_r0kh_push(dev, apdev):
"""WPA2-PSK-FT AP over DS with mismatching R0KH key (push)"""
ssid = "test-ft"
passphrase="12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
- params["ieee80211w"] = "2";
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
+ params["ieee80211w"] = "2"
+ hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2_r0kh_mismatch(ssid=ssid, passphrase=passphrase)
- params["ieee80211w"] = "2";
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ params["ieee80211w"] = "2"
+ hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
fail_test=True)
+@remote_compatible
def test_ap_ft_mismatching_rrb_r0kh_pull(dev, apdev):
"""WPA2-PSK-FT AP over DS with mismatching R0KH key (pull)"""
ssid = "test-ft"
params = ft_params1_r0kh_mismatch(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
fail_test=True)
params = ft_params1(ssid=ssid, passphrase=passphrase)
params['wpa_group_rekey'] = '1'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
ieee80211w="1", scan_freq="2412")
params = ft_params2(ssid=ssid, passphrase=passphrase)
params['wpa_group_rekey'] = '1'
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd1 = hostapd.add_ap(apdev[1], params)
dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
dev[0].roam(apdev[1]['bssid'])
psk = '93c90846ff67af9037ed83fb72b63dbeddaa81d47f926c20909b5886f1d9358d'
pmk = binascii.unhexlify(psk)
p = ft_params1(ssid=ssid, passphrase=passphrase)
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], p)
+ hapd0 = hostapd.add_ap(apdev[0], p)
p = ft_params2(ssid=ssid, passphrase=passphrase)
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], p)
+ hapd1 = hostapd.add_ap(apdev[1], p)
pid = find_wpas_process(dev[0])
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
+ # The decrypted copy of GTK is freed only after the CTRL-EVENT-CONNECTED
+ # event has been delivered, so verify that wpa_supplicant has returned to
+ # eloop before reading process memory.
time.sleep(1)
+ dev[0].ping()
buf = read_process_memory(pid, pmk)
if tk in buf:
raise Exception("TK found from memory")
if gtk in buf:
+ get_key_locations(buf, gtk, "GTK")
raise Exception("GTK found from memory")
logger.info("Checking keys in memory after disassociation")
verify_not_present(buf, tk, fname, "TK")
verify_not_present(buf, gtk, fname, "GTK")
+@remote_compatible
def test_ap_ft_invalid_resp(dev, apdev):
"""WPA2-PSK-FT AP and invalid response IEs"""
ssid = "test-ft"
passphrase="12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd0 = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
params = ft_params2(ssid=ssid, passphrase=passphrase)
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd1 = hostapd.add_ap(apdev[1], params)
tests = [
# Various IEs for test coverage. The last one is FTIE with invalid
params = ft_params1(ssid=ssid, passphrase=passphrase)
params['rsn_pairwise'] = "GCMP-256"
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params['rsn_pairwise'] = "GCMP-256"
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
pairwise_cipher="GCMP-256", group_cipher="GCMP-256")
passphrase="12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd1 = hostapd.add_ap(apdev[1], params)
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
dev[0].scan_for_bss(dst, freq="2412")
with alloc_fail(dev[0], 1, "wpa_ft_gen_req_ies"):
dev[0].roam(dst)
- with alloc_fail(dev[0], 1, "wpa_ft_mic"):
+ with fail_test(dev[0], 1, "wpa_ft_mic"):
dev[0].roam(dst, fail_test=True)
with fail_test(dev[0], 1, "os_get_random;wpa_ft_prepare_auth_request"):
dev[0].roam(dst, fail_test=True)
+ dev[0].request("REMOVE_NETWORK all")
+ with alloc_fail(dev[0], 1, "=sme_update_ft_ies"):
+ dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
+ scan_freq="2412")
+
def test_ap_ft_over_ds_proto(dev, apdev):
"""WPA2-PSK-FT AP over DS protocol testing"""
ssid = "test-ft"
passphrase="12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd0 = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
hapd0.mgmt_tx(msg)
params = ft_params2(ssid=ssid, passphrase=passphrase)
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd1 = hostapd.add_ap(apdev[1], params)
dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
hapd0.set("ext_mgmt_frame_handling", "1")
hapd0.dump_monitor()
msg['payload'] = binascii.unhexlify("0602020000000000" + "020000000400" + "0000" + "3603a1b201" + "3766000000000000000000000000000000000000c4e67ac1999bebd00ff4ae4d5dcaf87896bb060b469f7c78d49623fb395c3455ffffff6b693fe6f8d8c5dfac0a22344750775bd09437f98b238c9f87b97f790c0106000102030406030a6e6173312e77312e6669")
hapd0.mgmt_tx(msg)
+@remote_compatible
def test_ap_ft_rrb(dev, apdev):
"""WPA2-PSK-FT RRB protocol testing"""
ssid = "test-ft"
passphrase="12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd0 = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
raise Exception("DATA_TEST_FRAME failed")
+@remote_compatible
def test_rsn_ie_proto_ft_psk_sta(dev, apdev):
"""RSN element protocol testing for FT-PSK + PMF cases on STA side"""
bssid = apdev[0]['bssid']
passphrase="12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
- params["ieee80211w"] = "1";
+ params["ieee80211w"] = "1"
# This is the RSN element used normally by hostapd
params['own_ie_override'] = '30140100000fac040100000fac040100000fac048c00' + '3603a1b201'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
id = dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
ieee80211w="1", scan_freq="2412",
pairwise="CCMP", group="CCMP")
if ev is not None:
raise Exception("Unexpected connection")
dev[0].request("DISCONNECT")
+
+def test_ap_ft_ptk_rekey(dev, apdev):
+ """WPA2-PSK-FT PTK rekeying triggered by station after roam"""
+ ssid = "test-ft"
+ passphrase="12345678"
+
+ params = ft_params1(ssid=ssid, passphrase=passphrase)
+ hapd0 = hostapd.add_ap(apdev[0], params)
+ params = ft_params2(ssid=ssid, passphrase=passphrase)
+ hapd1 = hostapd.add_ap(apdev[1], params)
+
+ run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, ptk_rekey="1")
+
+ ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED",
+ "WPA: Key negotiation completed"], timeout=5)
+ if ev is None:
+ raise Exception("No event received after roam")
+ if "CTRL-EVENT-DISCONNECTED" in ev:
+ raise Exception("Unexpected disconnection after roam")
+
+ if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
+ hapd = hapd0
+ else:
+ hapd = hapd1
+ hwsim_utils.test_connectivity(dev[0], hapd)
+
+def test_ap_ft_ptk_rekey_ap(dev, apdev):
+ """WPA2-PSK-FT PTK rekeying triggered by AP after roam"""
+ ssid = "test-ft"
+ passphrase="12345678"
+
+ params = ft_params1(ssid=ssid, passphrase=passphrase)
+ params['wpa_ptk_rekey'] = '2'
+ hapd0 = hostapd.add_ap(apdev[0], params)
+ params = ft_params2(ssid=ssid, passphrase=passphrase)
+ params['wpa_ptk_rekey'] = '2'
+ hapd1 = hostapd.add_ap(apdev[1], params)
+
+ run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase)
+
+ ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED",
+ "WPA: Key negotiation completed"], timeout=5)
+ if ev is None:
+ raise Exception("No event received after roam")
+ if "CTRL-EVENT-DISCONNECTED" in ev:
+ raise Exception("Unexpected disconnection after roam")
+
+ if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
+ hapd = hapd0
+ else:
+ hapd = hapd1
+ hwsim_utils.test_connectivity(dev[0], hapd)
+
+def test_ap_ft_internal_rrb_check(dev, apdev):
+ """RRB internal delivery only to WPA enabled BSS"""
+ ssid = "test-ft"
+ passphrase="12345678"
+
+ radius = hostapd.radius_params()
+ params = ft_params1(ssid=ssid, passphrase=passphrase)
+ params['wpa_key_mgmt'] = "FT-EAP"
+ params["ieee8021x"] = "1"
+ params = dict(radius.items() + params.items())
+ hapd = hostapd.add_ap(apdev[0], params)
+ key_mgmt = hapd.get_config()['key_mgmt']
+ if key_mgmt.split(' ')[0] != "FT-EAP":
+ raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
+
+ hapd1 = hostapd.add_ap(apdev[1], { "ssid" : ssid })
+
+ # Connect to WPA enabled AP
+ dev[0].connect(ssid, key_mgmt="FT-EAP", proto="WPA2", ieee80211w="1",
+ eap="GPSK", identity="gpsk user",
+ password="abcdefghijklmnop0123456789abcdef",
+ scan_freq="2412")
+
+ # Try over_ds roaming to non-WPA-enabled AP.
+ # If hostapd does not check hapd->wpa_auth internally, it will crash now.
+ dev[0].roam_over_ds(apdev[1]['bssid'], fail_test=True)
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
+import base64
import binascii
import struct
import time
-import subprocess
import logging
logger = logging.getLogger()
import os
import subprocess
import hostapd
-from utils import HwsimSkip, skip_with_fips
+from utils import HwsimSkip, skip_with_fips, alloc_fail, wait_fail_trigger
import hwsim_utils
from tshark import run_tshark
from wlantest import Wlantest
from wpasupplicant import WpaSupplicant
from test_ap_eap import check_eap_capa, check_domain_match_full
+from test_gas import gas_rx, parse_gas, action_response, anqp_initial_resp, send_gas_resp, ACTION_CATEG_PUBLIC, GAS_INITIAL_RESPONSE
def hs20_ap_params(ssid="test-hs20"):
params = hostapd.wpa2_params(ssid=ssid)
raise Exception("Connected to incorrect network")
dev.request("REMOVE_NETWORK all")
dev.wait_disconnected()
+ dev.dump_monitor()
def interworking_select(dev, bssid, type=None, no_match=False, freq=None):
dev.dump_monitor()
ev = dev.wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH"],
timeout=15)
if ev is None:
- raise Exception("Network selection timed out");
+ raise Exception("Network selection timed out")
if no_match:
if "INTERWORKING-NO-MATCH" not in ev:
raise Exception("Unexpected network match")
ev = dev.wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH"],
timeout=15)
if ev is None:
- raise Exception("Network selection timed out");
+ raise Exception("Network selection timed out")
if "INTERWORKING-NO-MATCH" in ev:
raise Exception("Matching network not found")
if bssid and bssid not in ev:
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
bssid2 = apdev[1]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid
params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]" ]
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
dev[0].hs20_enable()
id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
if res1['anqp_nai_realm'] == res2['anqp_nai_realm']:
raise Exception("ANQP results were not unshared")
+def test_ap_anqp_no_sharing_diff_ess(dev, apdev):
+ """ANQP no sharing between ESSs"""
+ check_eap_capa(dev[0], "MSCHAPV2")
+ dev[0].flush_scan_cache()
+
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ hostapd.add_ap(apdev[0], params)
+
+ bssid2 = apdev[1]['bssid']
+ params = hs20_ap_params(ssid="test-hs20-another")
+ params['hessid'] = bssid
+ params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]" ]
+ hostapd.add_ap(apdev[1], params)
+
+ dev[0].hs20_enable()
+ id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
+ 'password': "secret",
+ 'domain': "example.com" })
+ logger.info("Normal network selection with shared ANQP results")
+ dev[0].scan_for_bss(bssid, freq="2412")
+ dev[0].scan_for_bss(bssid2, freq="2412")
+ interworking_select(dev[0], None, "home", freq="2412")
+
+def test_ap_anqp_no_sharing_missing_info(dev, apdev):
+ """ANQP no sharing due to missing information"""
+ check_eap_capa(dev[0], "MSCHAPV2")
+ dev[0].flush_scan_cache()
+
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ del params['roaming_consortium']
+ del params['domain_name']
+ del params['anqp_3gpp_cell_net']
+ del params['nai_realm']
+ hostapd.add_ap(apdev[0], params)
+
+ bssid2 = apdev[1]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]" ]
+ hostapd.add_ap(apdev[1], params)
+
+ dev[0].hs20_enable()
+ id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
+ 'password': "secret",
+ 'domain': "example.com" })
+ logger.info("Normal network selection with shared ANQP results")
+ dev[0].scan_for_bss(bssid, freq="2412")
+ dev[0].scan_for_bss(bssid2, freq="2412")
+ interworking_select(dev[0], None, "home", freq="2412")
+
+def test_ap_anqp_sharing_oom(dev, apdev):
+ """ANQP sharing within ESS and explicit unshare OOM"""
+ check_eap_capa(dev[0], "MSCHAPV2")
+ dev[0].flush_scan_cache()
+
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ hostapd.add_ap(apdev[0], params)
+
+ bssid2 = apdev[1]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]" ]
+ hostapd.add_ap(apdev[1], params)
+
+ dev[0].hs20_enable()
+ id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
+ 'password': "secret",
+ 'domain': "example.com" })
+ dev[0].scan_for_bss(bssid, freq="2412")
+ dev[0].scan_for_bss(bssid2, freq="2412")
+ interworking_select(dev[0], None, "home", freq="2412")
+ dev[0].dump_monitor()
+
+ with alloc_fail(dev[0], 1, "wpa_bss_anqp_clone"):
+ dev[0].request("ANQP_GET " + bssid + " 263")
+ ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
+ if ev is None:
+ raise Exception("ANQP operation timed out")
+
def test_ap_nai_home_realm_query(dev, apdev):
"""NAI Home Realm Query"""
check_eap_capa(dev[0], "MSCHAPV2")
params = hs20_ap_params()
params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]",
"0,another.example.org" ]
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].scan(freq="2412")
dev[0].request("HS20_GET_NAI_HOME_REALM_LIST " + bssid + " realm=example.com")
if "NAI Realm list" not in ev:
raise Exception("Missing NAI Realm list: " + ev)
+@remote_compatible
def test_ap_interworking_scan_filtering(dev, apdev):
"""Interworking scan filtering with HESSID and access network type"""
try:
ssid = "test-hs20-ap1"
params['ssid'] = ssid
params['hessid'] = bssid
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd0 = hostapd.add_ap(apdev[0], params)
bssid2 = apdev[1]['bssid']
params = hs20_ap_params()
params['access_network_type'] = "1"
del params['venue_group']
del params['venue_type']
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
dev[0].hs20_enable()
+ Wlantest.setup(hapd0)
wt = Wlantest()
wt.flush()
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
id = dev[0].add_cred_values({ 'realm': "example.com", 'username': "test",
'domain': "no.match.example.com" })
interworking_select(dev[0], bssid, "roaming", freq="2412")
- dev[0].set_cred_quoted(id, "realm", "no.match.example.com");
+ dev[0].set_cred_quoted(id, "realm", "no.match.example.com")
interworking_select(dev[0], bssid, no_match=True, freq="2412")
res = dev[0].request("SCAN_RESULTS")
params['nai_realm'] = [ "0,example.org,21" ]
params['hessid'] = bssid2
params['domain_name'] = "example.org"
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
dev[0].remove_cred(id)
id = dev[0].add_cred_values({ 'realm': "example.org", 'username': "test",
'password': "secret",
params['hessid'] = bssid
params['anqp_3gpp_cell_net'] = "555,444"
params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org"
- hostapd.add_ap(ap['ifname'], params)
+ hostapd.add_ap(ap, params)
dev.hs20_enable()
dev.add_cred_values({ 'imsi': "555444-333222111", 'eap': method,
'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"})
- interworking_select(dev, "home", freq="2412")
+ interworking_select(dev, bssid, "home", freq="2412")
interworking_connect(dev, bssid, method)
check_sp_type(dev, "home")
if ev is None:
raise Exception("Timeout on already-connected event")
+def test_ap_hs20_sim_invalid(dev, apdev):
+ """Hotspot 2.0 with simulated SIM and EAP-SIM - invalid IMSI"""
+ hlr_auc_gw_available()
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ params['anqp_3gpp_cell_net'] = "555,444"
+ params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org"
+ hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+ dev[0].add_cred_values({ 'imsi': "555444-3332221110", 'eap': "SIM",
+ 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"})
+ # This hits "No valid IMSI available" in build_root_nai()
+ interworking_select(dev[0], bssid, freq="2412")
+
+def test_ap_hs20_sim_oom(dev, apdev):
+ """Hotspot 2.0 with simulated SIM and EAP-SIM - OOM"""
+ hlr_auc_gw_available()
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ params['anqp_3gpp_cell_net'] = "555,444"
+ params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org"
+ hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+ dev[0].add_cred_values({ 'imsi': "555444-333222111", 'eap': "SIM",
+ 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"})
+ dev[0].scan_for_bss(bssid, freq=2412)
+ interworking_select(dev[0], bssid, freq="2412")
+
+ with alloc_fail(dev[0], 1, "wpa_config_add_network;interworking_connect_3gpp"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+
+ with alloc_fail(dev[0], 1, "=interworking_connect_3gpp"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+
def test_ap_hs20_aka(dev, apdev):
"""Hotspot 2.0 with simulated USIM and EAP-AKA"""
hlr_auc_gw_available()
params['hessid'] = bssid
params['anqp_3gpp_cell_net'] = "232,01"
params['domain_name'] = "wlan.mnc001.mcc232.3gppnetwork.org"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
try:
dev[0].request("SET external_sim 1")
dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM" })
- interworking_select(dev[0], "home", freq="2412")
+ interworking_select(dev[0], bssid, "home", freq="2412")
interworking_ext_sim_connect(dev[0], bssid, "SIM")
check_sp_type(dev[0], "home")
finally:
params['hessid'] = bssid
params['anqp_3gpp_cell_net'] = "244,91;310,026;232,01;234,56"
params['domain_name'] = "wlan.mnc091.mcc244.3gppnetwork.org"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
try:
dev[0].request("SET external_sim 1")
dev[0].add_cred_values({ 'imsi': "23201-0000000000", 'eap': "SIM" })
- interworking_select(dev[0], "roaming", freq="2412")
+ interworking_select(dev[0], bssid, "roaming", freq="2412")
interworking_ext_sim_connect(dev[0], bssid, "SIM")
check_sp_type(dev[0], "roaming")
finally:
params = hs20_ap_params()
params['hessid'] = bssid
params['disable_dgaf'] = '1'
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
id = dev[0].add_cred_values({ 'realm': "example.com",
params = hs20_ap_params()
params['hessid'] = bssid
params['disable_dgaf'] = '1'
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
params = hs20_ap_params()
params['hessid'] = bssid
params['disable_dgaf'] = '1'
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable(auto_interworking=True)
id = dev[0].add_cred_values({ 'realm': "example.com",
if status['hs20'] != "2":
raise Exception("Unexpected HS 2.0 support indication")
+@remote_compatible
def test_ap_hs20_auto_interworking_no_match(dev, apdev):
"""Hotspot 2.0 connection with auto_interworking=1 and no matching network"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "mismatch" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "mismatch" })
dev[0].hs20_enable(auto_interworking=True)
id = dev[0].connect("mismatch", psk="12345678", scan_freq="2412",
dev[0].dump_monitor()
dev[0].request("DISCONNECT")
+@remote_compatible
def test_ap_hs20_auto_interworking_no_cred_match(dev, apdev):
"""Hotspot 2.0 connection with auto_interworking=1 but no cred match"""
bssid = apdev[0]['bssid']
params = { "ssid": "test" }
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable(auto_interworking=True)
dev[0].add_cred_values({ 'realm': "example.com",
bssid = ap['bssid']
params = hs20_ap_params()
params['nai_realm'] = [ "0,example.com," + eap_params ]
- hostapd.add_ap(ap['ifname'], params)
+ hostapd.add_ap(ap, params)
dev.hs20_enable()
dev.add_cred_values({ 'realm': "example.com",
interworking_select(dev, bssid, freq="2412")
interworking_connect(dev, bssid, method)
+@remote_compatible
def test_ap_hs20_eap_unknown(dev, apdev):
"""Hotspot 2.0 connection with unknown EAP method"""
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['nai_realm'] = "0,example.com,99"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
dev[0].add_cred_values(default_cred())
"""Hotspot 2.0 connection with PEAP/GTC"""
eap_test(dev[0], apdev[0], "25[3:6]", "PEAP", "user")
+@remote_compatible
def test_ap_hs20_eap_peap_unknown(dev, apdev):
"""Hotspot 2.0 connection with PEAP/unknown"""
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['nai_realm'] = "0,example.com,25[3:99]"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
dev[0].add_cred_values(default_cred())
skip_with_fips(dev[0])
eap_test(dev[0], apdev[0], "21[2:3]", "TTLS", "mschap user")
+def test_ap_hs20_eap_ttls_default(dev, apdev):
+ """Hotspot 2.0 connection with TTLS/default"""
+ skip_with_fips(dev[0])
+ eap_test(dev[0], apdev[0], "21", "TTLS", "hs20-test")
+
def test_ap_hs20_eap_ttls_eap_mschapv2(dev, apdev):
"""Hotspot 2.0 connection with TTLS/EAP-MSCHAPv2"""
check_eap_capa(dev[0], "MSCHAPV2")
eap_test(dev[0], apdev[0], "21[3:26][6:7][99:99]", "TTLS", "user")
+@remote_compatible
def test_ap_hs20_eap_ttls_eap_unknown(dev, apdev):
"""Hotspot 2.0 connection with TTLS/EAP-unknown"""
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['nai_realm'] = "0,example.com,21[3:99]"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
dev[0].add_cred_values(default_cred())
interworking_select(dev[0], None, no_match=True, freq="2412")
+@remote_compatible
def test_ap_hs20_eap_ttls_eap_unsupported(dev, apdev):
"""Hotspot 2.0 connection with TTLS/EAP-OTP(unsupported)"""
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['nai_realm'] = "0,example.com,21[3:5]"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
dev[0].add_cred_values(default_cred())
interworking_select(dev[0], None, no_match=True, freq="2412")
+@remote_compatible
def test_ap_hs20_eap_ttls_unknown(dev, apdev):
"""Hotspot 2.0 connection with TTLS/unknown"""
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['nai_realm'] = "0,example.com,21[2:5]"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
dev[0].add_cred_values(default_cred())
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['nai_realm'] = [ "0,example.com,13[5:6]" ]
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
dev[0].add_cred_values({ 'realm': "example.com",
interworking_select(dev[0], bssid, freq="2412")
interworking_connect(dev[0], bssid, "TLS")
+@remote_compatible
def test_ap_hs20_eap_cert_unknown(dev, apdev):
"""Hotspot 2.0 connection with certificate, but unknown EAP method"""
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['nai_realm'] = [ "0,example.com,99[5:6]" ]
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
dev[0].add_cred_values({ 'realm': "example.com",
'private_key': "auth_serv/user.key"})
interworking_select(dev[0], None, no_match=True, freq="2412")
+@remote_compatible
def test_ap_hs20_eap_cert_unsupported(dev, apdev):
"""Hotspot 2.0 connection with certificate, but unsupported TTLS"""
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['nai_realm'] = [ "0,example.com,21[5:6]" ]
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
dev[0].add_cred_values({ 'realm': "example.com",
'private_key': "auth_serv/user.key"})
interworking_select(dev[0], None, no_match=True, freq="2412")
+@remote_compatible
def test_ap_hs20_eap_invalid_cred(dev, apdev):
"""Hotspot 2.0 connection with invalid cred configuration"""
bssid = apdev[0]['bssid']
params = hs20_ap_params()
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
dev[0].add_cred_values({ 'realm': "example.com",
params = hs20_ap_params()
params['hessid'] = bssid
params['nai_realm'] = [ "0,no.match.here;example.com;no.match.here.either,21[2:1][5:7]" ]
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
id = dev[0].add_cred_values({ 'realm': "example.com",
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
for consortium in [ "112233", "1020304050", "010203040506", "fedcba" ]:
raise Exception("Timeout on already-connected event")
dev[0].remove_cred(id)
+def test_ap_hs20_roaming_consortium_invalid(dev, apdev):
+ """Hotspot 2.0 connection and invalid roaming consortium ANQP-element"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ # Override Roaming Consortium ANQP-element with an incorrectly encoded
+ # value.
+ params['anqp_elem'] = "261:04fedcba"
+ hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+ id = dev[0].add_cred_values({ 'username': "user",
+ 'password': "password",
+ 'domain': "example.com",
+ 'ca_cert': "auth_serv/ca.pem",
+ 'roaming_consortium': "fedcba",
+ 'eap': "PEAP" })
+ interworking_select(dev[0], bssid, "home", freq="2412", no_match=True)
+
+def test_ap_hs20_roaming_consortium_element(dev, apdev):
+ """Hotspot 2.0 connection and invalid roaming consortium element"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ del params['roaming_consortium']
+ params['vendor_elements'] = '6f00'
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+ dev[0].scan_for_bss(bssid, freq="2412")
+ id = dev[0].add_cred_values({ 'username': "user",
+ 'password': "password",
+ 'domain': "example.com",
+ 'ca_cert': "auth_serv/ca.pem",
+ 'roaming_consortium': "112233",
+ 'eap': "PEAP" })
+ interworking_select(dev[0], bssid, freq="2412", no_match=True)
+
+ hapd.set('vendor_elements', '6f020001')
+ if "OK" not in hapd.request("UPDATE_BEACON"):
+ raise Exception("UPDATE_BEACON failed")
+ dev[0].request("BSS_FLUSH 0")
+ dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
+ interworking_select(dev[0], bssid, freq="2412", no_match=True)
+
+def test_ap_hs20_roaming_consortium_constraints(dev, apdev):
+ """Hotspot 2.0 connection and roaming consortium constraints"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ params['bss_load_test'] = "12:200:20000"
+ hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+
+ vals = { 'username': "user",
+ 'password': "password",
+ 'domain': "example.com",
+ 'ca_cert': "auth_serv/ca.pem",
+ 'roaming_consortium': "fedcba",
+ 'eap': "TTLS" }
+ vals2 = vals.copy()
+ vals2['required_roaming_consortium'] = "223344"
+ id = dev[0].add_cred_values(vals2)
+ interworking_select(dev[0], bssid, "home", freq="2412", no_match=True)
+ dev[0].remove_cred(id)
+
+ vals2 = vals.copy()
+ vals2['min_dl_bandwidth_home'] = "65500"
+ id = dev[0].add_cred_values(vals2)
+ dev[0].request("INTERWORKING_SELECT freq=2412")
+ ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
+ if ev is None:
+ raise Exception("No AP found")
+ if "below_min_backhaul=1" not in ev:
+ raise Exception("below_min_backhaul not reported")
+ dev[0].remove_cred(id)
+
+ vals2 = vals.copy()
+ vals2['max_bss_load'] = "100"
+ id = dev[0].add_cred_values(vals2)
+ dev[0].request("INTERWORKING_SELECT freq=2412")
+ ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
+ if ev is None:
+ raise Exception("No AP found")
+ if "over_max_bss_load=1" not in ev:
+ raise Exception("over_max_bss_load not reported")
+ dev[0].remove_cred(id)
+
+ vals2 = vals.copy()
+ vals2['req_conn_capab'] = "6:1234"
+ vals2['domain'] = 'example.org'
+ id = dev[0].add_cred_values(vals2)
+
+ dev[0].request("INTERWORKING_SELECT freq=2412")
+ ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
+ if ev is None:
+ raise Exception("No AP found")
+ if "conn_capab_missing=1" not in ev:
+ raise Exception("conn_capab_missing not reported")
+ dev[0].remove_cred(id)
+
+ values = default_cred()
+ values['roaming_consortium'] = "fedcba"
+ id3 = dev[0].add_cred_values(values)
+
+ vals2 = vals.copy()
+ vals2['roaming_consortium'] = "fedcba"
+ vals2['priority'] = "2"
+ id = dev[0].add_cred_values(vals2)
+
+ values = default_cred()
+ values['roaming_consortium'] = "fedcba"
+ id2 = dev[0].add_cred_values(values)
+
+ dev[0].request("INTERWORKING_SELECT freq=2412")
+ ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
+ if ev is None:
+ raise Exception("No AP found")
+ dev[0].remove_cred(id)
+ dev[0].remove_cred(id2)
+ dev[0].remove_cred(id3)
+
+def test_ap_hs20_3gpp_constraints(dev, apdev):
+ """Hotspot 2.0 connection and 3GPP credential constraints"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ params['anqp_3gpp_cell_net'] = "555,444"
+ params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org"
+ params['bss_load_test'] = "12:200:20000"
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+
+ vals = { 'imsi': "555444-333222111",
+ 'eap': "SIM",
+ 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123" }
+ vals2 = vals.copy()
+ vals2['required_roaming_consortium'] = "223344"
+ id = dev[0].add_cred_values(vals2)
+ interworking_select(dev[0], bssid, "home", freq="2412", no_match=True)
+ dev[0].remove_cred(id)
+
+ vals2 = vals.copy()
+ vals2['min_dl_bandwidth_home'] = "65500"
+ id = dev[0].add_cred_values(vals2)
+ dev[0].request("INTERWORKING_SELECT freq=2412")
+ ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
+ if ev is None:
+ raise Exception("No AP found")
+ if "below_min_backhaul=1" not in ev:
+ raise Exception("below_min_backhaul not reported")
+ dev[0].remove_cred(id)
+
+ vals2 = vals.copy()
+ vals2['max_bss_load'] = "100"
+ id = dev[0].add_cred_values(vals2)
+ dev[0].request("INTERWORKING_SELECT freq=2412")
+ ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
+ if ev is None:
+ raise Exception("No AP found")
+ if "over_max_bss_load=1" not in ev:
+ raise Exception("over_max_bss_load not reported")
+ dev[0].remove_cred(id)
+
+ values = default_cred()
+ values['roaming_consortium'] = "fedcba"
+ id3 = dev[0].add_cred_values(values)
+
+ vals2 = vals.copy()
+ vals2['roaming_consortium'] = "fedcba"
+ vals2['priority'] = "2"
+ id = dev[0].add_cred_values(vals2)
+
+ values = default_cred()
+ values['roaming_consortium'] = "fedcba"
+ id2 = dev[0].add_cred_values(values)
+
+ dev[0].request("INTERWORKING_SELECT freq=2412")
+ ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
+ if ev is None:
+ raise Exception("No AP found")
+ dev[0].remove_cred(id)
+ dev[0].remove_cred(id2)
+ dev[0].remove_cred(id3)
+
+ hapd.disable()
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ params['anqp_3gpp_cell_net'] = "555,444"
+ params['bss_load_test'] = "12:200:20000"
+ hapd = hostapd.add_ap(apdev[0], params)
+ vals2 = vals.copy()
+ vals2['req_conn_capab'] = "6:1234"
+ id = dev[0].add_cred_values(vals2)
+ dev[0].request("INTERWORKING_SELECT freq=2412")
+ ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
+ if ev is None:
+ raise Exception("No AP found")
+ if "conn_capab_missing=1" not in ev:
+ raise Exception("conn_capab_missing not reported")
+ dev[0].remove_cred(id)
+
+def test_ap_hs20_connect_no_full_match(dev, apdev):
+ """Hotspot 2.0 connection and no full match"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ params['anqp_3gpp_cell_net'] = "555,444"
+ hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+
+ vals = { 'username': "user",
+ 'password': "password",
+ 'domain': "example.com",
+ 'ca_cert': "auth_serv/ca.pem",
+ 'roaming_consortium': "fedcba",
+ 'eap': "TTLS",
+ 'min_dl_bandwidth_home': "65500" }
+ id = dev[0].add_cred_values(vals)
+ dev[0].request("INTERWORKING_SELECT freq=2412")
+ ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
+ if ev is None:
+ raise Exception("No AP found")
+ if "below_min_backhaul=1" not in ev:
+ raise Exception("below_min_backhaul not reported")
+ interworking_connect(dev[0], bssid, "TTLS")
+ dev[0].remove_cred(id)
+ dev[0].wait_disconnected()
+
+ vals = { 'imsi': "555444-333222111", 'eap': "SIM",
+ 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123",
+ 'min_dl_bandwidth_roaming': "65500" }
+ id = dev[0].add_cred_values(vals)
+ dev[0].request("INTERWORKING_SELECT freq=2412")
+ ev = dev[0].wait_event(["INTERWORKING-AP"], timeout=15)
+ if ev is None:
+ raise Exception("No AP found")
+ if "below_min_backhaul=1" not in ev:
+ raise Exception("below_min_backhaul not reported")
+ interworking_connect(dev[0], bssid, "SIM")
+ dev[0].remove_cred(id)
+ dev[0].wait_disconnected()
+
def test_ap_hs20_username_roaming(dev, apdev):
"""Hotspot 2.0 connection in username/password credential (roaming)"""
check_eap_capa(dev[0], "MSCHAPV2")
"0,another.example.com" ]
params['domain_name'] = "another.example.com"
params['hessid'] = bssid
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
id = dev[0].add_cred_values({ 'realm': "roaming.example.com",
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
id = dev[0].add_cred_values({ 'realm': "example.com",
params = hs20_ap_params()
params['hessid'] = bssid
del params['domain_name']
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
id = dev[0].add_cred_values({ 'realm': "example.com",
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
id = dev[0].add_cred_values({ 'realm': "example.com",
if ev is None:
raise Exception("Operation timed out")
+def test_ap_hs20_gas_with_another_ap_while_associated(dev, apdev):
+ """GAS query with another AP while associated"""
+ check_eap_capa(dev[0], "MSCHAPV2")
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ hostapd.add_ap(apdev[0], params)
+
+ bssid2 = apdev[1]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid2
+ params['nai_realm'] = [ "0,no-match.example.org,13[5:6],21[2:4][5:7]" ]
+ hostapd.add_ap(apdev[1], params)
+
+ dev[0].hs20_enable()
+ id = dev[0].add_cred_values({ 'realm': "example.com",
+ 'ca_cert': "auth_serv/ca.pem",
+ 'username': "hs20-test",
+ 'password': "password",
+ 'domain': "example.com" })
+ interworking_select(dev[0], bssid, "home", freq="2412")
+ interworking_connect(dev[0], bssid, "TTLS")
+ dev[0].dump_monitor()
+
+ logger.info("Verifying GAS query with same AP while associated")
+ dev[0].request("ANQP_GET " + bssid + " 263")
+ ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
+ if ev is None:
+ raise Exception("ANQP operation timed out")
+ dev[0].dump_monitor()
+
+ logger.info("Verifying GAS query with another AP while associated")
+ dev[0].scan_for_bss(bssid2, 2412)
+ dev[0].request("ANQP_GET " + bssid2 + " 263")
+ ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
+ if ev is None:
+ raise Exception("ANQP operation timed out")
+
def test_ap_hs20_gas_while_associated_with_pmf(dev, apdev):
"""Hotspot 2.0 connection with GAS query while associated and using PMF"""
check_eap_capa(dev[0], "MSCHAPV2")
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
bssid2 = apdev[1]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid2
params['nai_realm'] = [ "0,no-match.example.org,13[5:6],21[2:4][5:7]" ]
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
dev[0].hs20_enable()
dev[0].request("SET pmf 2")
if ev is None:
raise Exception("Operation timed out")
-def test_ap_hs20_gas_frag_while_associated(dev, apdev):
- """Hotspot 2.0 connection with fragmented GAS query while associated"""
+def test_ap_hs20_gas_with_another_ap_while_using_pmf(dev, apdev):
+ """GAS query with another AP while associated and using PMF"""
check_eap_capa(dev[0], "MSCHAPV2")
+ try:
+ _test_ap_hs20_gas_with_another_ap_while_using_pmf(dev, apdev)
+ finally:
+ dev[0].request("SET pmf 0")
+
+def _test_ap_hs20_gas_with_another_ap_while_using_pmf(dev, apdev):
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
- hapd.set("gas_frag_limit", "50")
+ hostapd.add_ap(apdev[0], params)
+
+ bssid2 = apdev[1]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid2
+ params['nai_realm'] = [ "0,no-match.example.org,13[5:6],21[2:4][5:7]" ]
+ hostapd.add_ap(apdev[1], params)
+
+ dev[0].hs20_enable()
+ dev[0].request("SET pmf 2")
+ id = dev[0].add_cred_values({ 'realm': "example.com",
+ 'ca_cert': "auth_serv/ca.pem",
+ 'username': "hs20-test",
+ 'password': "password",
+ 'domain': "example.com" })
+ interworking_select(dev[0], bssid, "home", freq="2412")
+ interworking_connect(dev[0], bssid, "TTLS")
+ dev[0].dump_monitor()
+
+ logger.info("Verifying GAS query with same AP while associated")
+ dev[0].request("ANQP_GET " + bssid + " 263")
+ ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
+ if ev is None:
+ raise Exception("ANQP operation timed out")
+ dev[0].dump_monitor()
+
+ logger.info("Verifying GAS query with another AP while associated")
+ dev[0].scan_for_bss(bssid2, 2412)
+ dev[0].request("ANQP_GET " + bssid2 + " 263")
+ ev = dev[0].wait_event(["RX-ANQP"], timeout=5)
+ if ev is None:
+ raise Exception("ANQP operation timed out")
+
+def test_ap_hs20_gas_frag_while_associated(dev, apdev):
+ """Hotspot 2.0 connection with fragmented GAS query while associated"""
+ check_eap_capa(dev[0], "MSCHAPV2")
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ hapd = hostapd.add_ap(apdev[0], params)
+ hapd.set("gas_frag_limit", "50")
dev[0].hs20_enable()
id = dev[0].add_cred_values({ 'realm': "example.com",
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
values = { 'realm': "example.com",
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
values = { 'realm': "example.com",
check_eap_capa(dev[0], "MSCHAPV2")
params = hs20_ap_params()
params['domain_name'] = "example.org"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
params = hs20_ap_params()
params['ssid'] = "test-hs20-other"
params['domain_name'] = "example.com"
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
values = default_cred()
values['domain'] = "example.com"
"""Hotspot 2.0 required roaming consortium"""
check_eap_capa(dev[0], "MSCHAPV2")
params = hs20_ap_params()
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
params = hs20_ap_params()
params['ssid'] = "test-hs20-other"
params['roaming_consortium'] = [ "223344" ]
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
values = default_cred()
values['required_roaming_consortium'] = "223344"
if "FAIL" not in dev[0].request('SET_CRED {} required_roaming_consortium {}'.format(id, val)):
raise Exception("Invalid roaming consortium value accepted: " + val)
+def test_ap_hs20_req_roaming_consortium_no_match(dev, apdev):
+ """Hotspot 2.0 required roaming consortium and no match"""
+ check_eap_capa(dev[0], "MSCHAPV2")
+ params = hs20_ap_params()
+ del params['roaming_consortium']
+ hostapd.add_ap(apdev[0], params)
+
+ params = hs20_ap_params()
+ params['ssid'] = "test-hs20-other"
+ params['roaming_consortium'] = [ "223345" ]
+ hostapd.add_ap(apdev[1], params)
+
+ values = default_cred()
+ values['required_roaming_consortium'] = "223344"
+ dev[0].hs20_enable()
+ id = dev[0].add_cred_values(values)
+ dev[0].request("INTERWORKING_SELECT auto freq=2412")
+ ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=10)
+ if ev is None:
+ raise Exception("INTERWORKING-NO-MATCH not reported")
+
def test_ap_hs20_excluded_ssid(dev, apdev):
"""Hotspot 2.0 exclusion based on SSID"""
check_eap_capa(dev[0], "MSCHAPV2")
params = hs20_ap_params()
params['roaming_consortium'] = [ "223344" ]
params['anqp_3gpp_cell_net'] = "555,444"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
params = hs20_ap_params()
params['ssid'] = "test-hs20-other"
params['roaming_consortium'] = [ "223344" ]
params['anqp_3gpp_cell_net'] = "555,444"
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
values = default_cred()
values['excluded_ssid'] = "test-hs20"
bssid = apdev[0]['bssid']
params = hs20_ap_params(ssid="test-hs20-visited")
params['domain_name'] = "visited.example.org"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
id = dev[0].add_cred_values({ 'realm': "example.com",
bssid2 = apdev[1]['bssid']
params = hs20_ap_params(ssid="test-hs20-home")
params['domain_name'] = "example.com"
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
dev[0].scan_for_bss(bssid2, freq="2412", force_scan=True)
dev[0].request("INTERWORKING_SELECT auto freq=2412")
def test_ap_hs20_domain_suffix_match_full(dev, apdev):
"""Hotspot 2.0 and domain_suffix_match"""
+ check_domain_match_full(dev[0])
check_eap_capa(dev[0], "MSCHAPV2")
bssid = apdev[0]['bssid']
params = hs20_ap_params()
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
id = dev[0].add_cred_values({ 'realm': "example.com",
check_domain_match_full(dev[0])
bssid = apdev[0]['bssid']
params = hs20_ap_params()
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
id = dev[0].add_cred_values({ 'realm': "example.com",
check_eap_capa(dev[0], "MSCHAPV2")
params = hs20_ap_params()
params['domain_name'] = "roaming.example.org"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
params = hs20_ap_params()
params['ssid'] = "test-hs20-other"
params['domain_name'] = "roaming.example.net"
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
logger.info("Verify default vs. specified preference")
values = default_cred()
check_eap_capa(dev[0], "MSCHAPV2")
params = hs20_ap_params()
params['bss_load_test'] = "12:200:20000"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
params = hs20_ap_params()
params['ssid'] = "test-hs20-other"
params['bss_load_test'] = "5:20:10000"
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
logger.info("Verify maximum BSS load constraint")
values = default_cred()
check_eap_capa(dev[0], "MSCHAPV2")
params = hs20_ap_params()
params['bss_load_test'] = "12:200:20000"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
params = hs20_ap_params()
params['ssid'] = "test-hs20-other"
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
logger.info("Verify maximum BSS load constraint with AP advertisement")
values = default_cred()
if len(ev) != 1 or "over_max_bss_load=1" in ev[0]:
raise Exception("Maximum BSS Load case reported incorrectly")
+def test_ap_hs20_max_bss_load_roaming(dev, apdev):
+ """Hotspot 2.0 and maximum BSS load (roaming)"""
+ check_eap_capa(dev[0], "MSCHAPV2")
+ params = hs20_ap_params()
+ params['bss_load_test'] = "12:200:20000"
+ hostapd.add_ap(apdev[0], params)
+
+ values = default_cred()
+ values['domain'] = "roaming.example.com"
+ values['max_bss_load'] = "100"
+ events = policy_test(dev[0], apdev[0], values, only_one=True)
+ ev = [e for e in events if "INTERWORKING-AP " + apdev[0]['bssid'] in e]
+ if len(ev) != 1:
+ raise Exception("No INTERWORKING-AP event")
+ if "over_max_bss_load=1" in ev[0]:
+ raise Exception("Maximum BSS Load reported for roaming")
+
def test_ap_hs20_multi_cred_sp_prio(dev, apdev):
"""Hotspot 2.0 multi-cred sp_priority"""
check_eap_capa(dev[0], "MSCHAPV2")
params['hessid'] = bssid
del params['domain_name']
params['anqp_3gpp_cell_net'] = "232,01"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
dev[0].scan_for_bss(bssid, freq="2412")
del params['nai_realm']
del params['domain_name']
params['anqp_3gpp_cell_net'] = "232,01"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
bssid2 = apdev[1]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid2
del params['domain_name']
del params['anqp_3gpp_cell_net']
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
dev[0].hs20_enable()
dev[0].request("SET external_sim 1")
if conn_bssid != bssid2:
raise Exception("Connected to incorrect BSS")
+def test_ap_hs20_multi_cred_sp_prio_same(dev, apdev):
+ """Hotspot 2.0 multi-cred and same sp_priority"""
+ check_eap_capa(dev[0], "MSCHAPV2")
+ hlr_auc_gw_available()
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ del params['domain_name']
+ params['anqp_3gpp_cell_net'] = "232,01"
+ hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+ dev[0].scan_for_bss(bssid, freq="2412")
+ id1 = dev[0].add_cred_values({ 'realm': "example.com",
+ 'ca_cert': "auth_serv/ca.pem",
+ 'username': "hs20-test",
+ 'password': "password",
+ 'domain': "domain1.example.com",
+ 'provisioning_sp': "example.com",
+ 'sp_priority': "1" })
+ id2 = dev[0].add_cred_values({ 'realm': "example.com",
+ 'ca_cert': "auth_serv/ca.pem",
+ 'username': "hs20-test",
+ 'password': "password",
+ 'domain': "domain2.example.com",
+ 'provisioning_sp': "example.com",
+ 'sp_priority': "1" })
+ dev[0].dump_monitor()
+ dev[0].scan_for_bss(bssid, freq="2412")
+ check_auto_select(dev[0], bssid)
+
def check_conn_capab_selection(dev, type, missing):
dev.request("INTERWORKING_SELECT freq=2412")
ev = dev.wait_event(["INTERWORKING-AP"])
if ev is None:
- raise Exception("Network selection timed out");
+ raise Exception("Network selection timed out")
if "type=" + type not in ev:
raise Exception("Unexpected network type")
if missing and "conn_capab_missing=1" not in ev:
check_eap_capa(dev[0], "MSCHAPV2")
bssid = apdev[0]['bssid']
params = hs20_ap_params()
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
dev[0].scan_for_bss(bssid, freq="2412")
bssid2 = apdev[1]['bssid']
params = hs20_ap_params(ssid="test-hs20b")
params['hs20_conn_capab'] = [ "1:0:2", "6:22:1", "17:5060:0", "50:0:1" ]
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
dev[0].remove_cred(id)
values = conn_capab_cred(domain="example.org", req_conn_capab="50")
for i in range(0, 2):
ev = dev[0].wait_event(["INTERWORKING-AP"])
if ev is None:
- raise Exception("Network selection timed out");
+ raise Exception("Network selection timed out")
if bssid in ev and "conn_capab_missing=1" not in ev:
raise Exception("Missing protocol connection capability not reported")
if bssid2 in ev and "conn_capab_missing=1" in ev:
raise Exception("Protocol connection capability not reported correctly")
+def test_ap_hs20_req_conn_capab2(dev, apdev):
+ """Hotspot 2.0 network selection with req_conn_capab (not present)"""
+ check_eap_capa(dev[0], "MSCHAPV2")
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ del params['hs20_conn_capab']
+ hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+ dev[0].scan_for_bss(bssid, freq="2412")
+ values = conn_capab_cred(domain="example.org", req_conn_capab="6:1234")
+ id = dev[0].add_cred_values(values)
+ check_conn_capab_selection(dev[0], "roaming", False)
+
def test_ap_hs20_req_conn_capab_and_roaming_partner_preference(dev, apdev):
"""Hotspot 2.0 and req_conn_capab with roaming partner preference"""
check_eap_capa(dev[0], "MSCHAPV2")
params = hs20_ap_params()
params['domain_name'] = "roaming.example.org"
params['hs20_conn_capab'] = [ "1:0:2", "6:22:1", "17:5060:0", "50:0:1" ]
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
bssid2 = apdev[1]['bssid']
params = hs20_ap_params(ssid="test-hs20-b")
params['domain_name'] = "roaming.example.net"
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
values = default_cred()
values['roaming_partner'] = "roaming.example.net,1,127,*"
dev.request("INTERWORKING_SELECT freq=2412")
ev = dev.wait_event(["INTERWORKING-AP"])
if ev is None:
- raise Exception("Network selection timed out");
+ raise Exception("Network selection timed out")
logger.debug("BSS entries:\n" + dev.request("BSS RANGE=ALL"))
if "type=" + type not in ev:
raise Exception("Unexpected network type")
check_eap_capa(dev[0], "MSCHAPV2")
bssid = apdev[0]['bssid']
params = hs20_ap_params()
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
dev[0].scan_for_bss(bssid, freq="2412")
bssid2 = apdev[1]['bssid']
params = hs20_ap_params(ssid="test-hs20-b")
params['hs20_wan_metrics'] = "01:8000:1000:1:1:3000"
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
check_auto_select(dev[0], bssid2)
+def test_ap_hs20_min_bandwidth_home2(dev, apdev):
+ """Hotspot 2.0 network selection with min bandwidth - special cases"""
+ check_eap_capa(dev[0], "MSCHAPV2")
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+ dev[0].scan_for_bss(bssid, freq="2412")
+ values = bw_cred(domain="example.com", dl_home=5490, ul_home=58)
+ id = dev[0].add_cred_values(values)
+ check_bandwidth_selection(dev[0], "home", False)
+
+ logger.info("WAN link at capacity")
+ hapd.set('hs20_wan_metrics', "09:8000:1000:80:240:3000")
+ check_bandwidth_selection(dev[0], "home", True)
+
+ logger.info("Downlink/Uplink Load was not measured")
+ hapd.set('hs20_wan_metrics', "01:8000:1000:80:240:0")
+ check_bandwidth_selection(dev[0], "home", False)
+
+ logger.info("Uplink and Downlink max values")
+ hapd.set('hs20_wan_metrics', "01:4294967295:4294967295:80:240:3000")
+ check_bandwidth_selection(dev[0], "home", False)
+
+ dev[0].remove_cred(id)
+
def test_ap_hs20_min_bandwidth_home_hidden_ssid_in_scan_res(dev, apdev):
"""Hotspot 2.0 network selection with min bandwidth (home) while hidden SSID is included in scan results"""
check_eap_capa(dev[0], "MSCHAPV2")
bssid = apdev[0]['bssid']
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": 'secret',
- "ignore_broadcast_ssid": "1" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": 'secret',
+ "ignore_broadcast_ssid": "1" })
dev[0].scan_for_bss(bssid, freq=2412)
hapd.disable()
- hapd_global = hostapd.HostapdGlobal()
+ hapd_global = hostapd.HostapdGlobal(apdev[0])
hapd_global.flush()
hapd_global.remove(apdev[0]['ifname'])
params = hs20_ap_params()
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
dev[0].scan_for_bss(bssid, freq="2412")
bssid2 = apdev[1]['bssid']
params = hs20_ap_params(ssid="test-hs20-b")
params['hs20_wan_metrics'] = "01:8000:1000:1:1:3000"
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
check_auto_select(dev[0], bssid2)
check_eap_capa(dev[0], "MSCHAPV2")
bssid = apdev[0]['bssid']
params = hs20_ap_params()
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
dev[0].scan_for_bss(bssid, freq="2412")
bssid2 = apdev[1]['bssid']
params = hs20_ap_params(ssid="test-hs20-b")
params['hs20_wan_metrics'] = "01:8000:1000:1:1:3000"
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
check_auto_select(dev[0], bssid2)
params = hs20_ap_params()
params['domain_name'] = "roaming.example.org"
params['hs20_wan_metrics'] = "01:8000:1000:1:1:3000"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
bssid2 = apdev[1]['bssid']
params = hs20_ap_params(ssid="test-hs20-b")
params['domain_name'] = "roaming.example.net"
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
values = default_cred()
values['roaming_partner'] = "roaming.example.net,1,127,*"
bssid = apdev[0]['bssid']
params = hs20_ap_params()
del params['hs20_wan_metrics']
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
dev[0].scan_for_bss(bssid, freq="2412")
params = hs20_ap_params()
params['nai_realm'] = [ "0,example.com,21[2:4]" ]
params['hs20_deauth_req_timeout'] = "2"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].request("SET pmf 2")
dev[0].hs20_enable()
raise Exception("Unexpected deauth imminent contents")
dev[0].wait_disconnected(timeout=3)
+def test_ap_hs20_deauth_req_without_pmf(dev, apdev):
+ """Hotspot 2.0 connection and deauthentication request without PMF"""
+ check_eap_capa(dev[0], "MSCHAPV2")
+ dev[0].request("SET pmf 0")
+ eap_test(dev[0], apdev[0], "21[3:26]", "TTLS", "user")
+ dev[0].dump_monitor()
+ addr = dev[0].own_addr()
+ hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd.request("HS20_DEAUTH_REQ " + addr + " 1 120 http://example.com/")
+ ev = dev[0].wait_event(["HS20-DEAUTH-IMMINENT-NOTICE"], timeout=0.2)
+ if ev is not None:
+ raise Exception("Deauth imminent notice without PMF accepted")
+
def test_ap_hs20_remediation_required(dev, apdev):
"""Hotspot 2.0 connection and remediation required from RADIUS"""
check_eap_capa(dev[0], "MSCHAPV2")
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['nai_realm'] = [ "0,example.com,21[2:4]" ]
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].request("SET pmf 1")
dev[0].hs20_enable()
addr = dev[0].own_addr()
params = hs20_ap_params()
params['nai_realm'] = [ "0,example.com,21[2:4]" ]
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].request("SET pmf 1")
dev[0].hs20_enable()
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['nai_realm'] = [ "0,example.com,21[2:4]" ]
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].request("SET pmf 1")
dev[0].hs20_enable()
'auth_server_addr': "127.0.0.1",
'auth_server_port': "1812",
'auth_server_shared_secret': "radius" }
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[1].connect("osen", key_mgmt="NONE", scan_freq="2412",
wait_connect=False)
check_eap_capa(dev[0], "MSCHAPV2")
bssid = apdev[0]['bssid']
params = hs20_ap_params()
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
values = { 'realm': "example.com",
bssid2 = apdev[1]['bssid']
params = hostapd.wpa2_params(ssid="home", passphrase="12345678")
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
dev[0].scan_for_bss(bssid2, freq="2412")
dev[0].request("INTERWORKING_SELECT auto freq=2412")
check_eap_capa(dev[0], "MSCHAPV2")
bssid2 = apdev[1]['bssid']
params = hostapd.wpa2_params(ssid="home", passphrase="12345678")
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
dev[0].hs20_enable()
values = { 'realm': "example.com",
bssid = apdev[0]['bssid']
params = hs20_ap_params()
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].scan_for_bss(bssid, freq="2412")
dev[0].request("INTERWORKING_SELECT auto freq=2412")
check_eap_capa(dev[0], "MSCHAPV2")
bssid = apdev[0]['bssid']
params = hs20_ap_params()
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
bssid2 = apdev[1]['bssid']
params = hs20_ap_params(ssid="test-hs20b")
params['nai_realm'] = "0,example.org,13[5:6],21[2:4][5:7]"
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
dev[0].hs20_enable()
values = { 'realm': "example.com",
check_eap_capa(dev[0], "MSCHAPV2")
bssid = apdev[0]['bssid']
params = hs20_ap_params()
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
bssid2 = apdev[1]['bssid']
params = hs20_ap_params(ssid="test-hs20b")
params['hessid'] = bssid2
params['anqp_3gpp_cell_net'] = "555,444"
params['domain_name'] = "wlan.mnc444.mcc555.3gppnetwork.org"
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
dev[0].hs20_enable()
values = { 'realm': "example.com",
check_eap_capa(dev[0], "MSCHAPV2")
bssid = apdev[0]['bssid']
params = hs20_ap_params()
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
values = { 'realm': "example.com",
params['osu_icon'] = "w1fi_logo"
params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
params['osu_server_uri'] = "https://example.com/osu/"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
bssid2 = apdev[1]['bssid']
params = hs20_ap_params(ssid="test-hs20b")
params['osu_icon'] = "w1fi_logo"
params['osu_service_desc'] = [ "eng:Example services2", "fin:Esimerkkipalveluja2" ]
params['osu_server_uri'] = "https://example.org/osu/"
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
with open("w1fi_logo.png", "r") as f:
orig_logo = f.read()
pass
try:
dev[1].scan_for_bss(bssid, freq="2412")
+ dev[2].scan_for_bss(bssid, freq="2412")
dev[0].request("SET osu_dir " + dir)
dev[0].request("FETCH_OSU")
if "FAIL" not in dev[1].request("HS20_ICON_REQUEST foo w1fi_logo"):
raise Exception("Invalid HS20_ICON_REQUEST accepted")
if "OK" not in dev[1].request("HS20_ICON_REQUEST " + bssid + " w1fi_logo"):
raise Exception("HS20_ICON_REQUEST failed")
+ if "OK" not in dev[2].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
+ raise Exception("REQ_HS20_ICON failed")
icons = 0
while True:
ev = dev[0].wait_event(["OSU provider fetch completed",
if "Icon Binary File" not in ev:
raise Exception("Unexpected ANQP element")
+ ev = dev[2].wait_event(["RX-HS20-ICON"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on RX-HS20-ICON")
+ event_icon_len = ev.split(' ')[3]
+ if " w1fi_logo " not in ev:
+ raise Exception("RX-HS20-ICON did not have the expected file name")
+ if bssid not in ev:
+ raise Exception("RX-HS20-ICON did not have the expected BSSID")
+ if "FAIL" in dev[2].request("GET_HS20_ICON " + bssid + " w1fi_logo 0 10"):
+ raise Exception("GET_HS20_ICON 0..10 failed")
+ if "FAIL" in dev[2].request("GET_HS20_ICON " + bssid + " w1fi_logo 5 10"):
+ raise Exception("GET_HS20_ICON 5..15 failed")
+ if "FAIL" not in dev[2].request("GET_HS20_ICON " + bssid + " w1fi_logo 100000 10"):
+ raise Exception("Unexpected success of GET_HS20_ICON with too large offset")
+ if "FAIL" not in dev[2].request("GET_HS20_ICON " + bssid + " no_such_logo 0 10"):
+ raise Exception("GET_HS20_ICON for not existing icon succeeded")
+ if "FAIL" not in dev[2].request("GET_HS20_ICON " + bssid + " w1fi_logo 0 3070"):
+ raise Exception("GET_HS20_ICON with too many output bytes to fit the buffer succeeded")
+ if "FAIL" not in dev[2].request("GET_HS20_ICON " + bssid + " w1fi_logo 0 0"):
+ raise Exception("GET_HS20_ICON 0..0 succeeded")
+ icon = ""
+ pos = 0
+ while True:
+ if pos > 100000:
+ raise Exception("Unexpectedly long icon")
+ res = dev[2].request("GET_HS20_ICON " + bssid + " w1fi_logo %d 1000" % pos)
+ if res.startswith("FAIL"):
+ break
+ icon += base64.b64decode(res)
+ pos += 1000
+ hex = binascii.hexlify(icon)
+ if not hex.startswith("0009696d6167652f706e677d1d"):
+ raise Exception("Unexpected beacon binary header: " + hex)
+ with open('w1fi_logo.png', 'r') as f:
+ data = f.read()
+ if icon[13:] != data:
+ raise Exception("Unexpected icon data")
+ if len(icon) != int(event_icon_len):
+ raise Exception("Unexpected RX-HS20-ICON event length: " + event_icon_len)
+
+ for i in range(3):
+ if "OK" not in dev[i].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
+ raise Exception("REQ_HS20_ICON failed [2]")
+ for i in range(3):
+ ev = dev[i].wait_event(["RX-HS20-ICON"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on RX-HS20-ICON [2]")
+
+ if "FAIL" not in dev[2].request("DEL_HS20_ICON foo w1fi_logo"):
+ raise Exception("Invalid DEL_HS20_ICON accepted")
+ if "OK" not in dev[2].request("DEL_HS20_ICON " + bssid + " w1fi_logo"):
+ raise Exception("DEL_HS20_ICON failed")
+ if "OK" not in dev[1].request("DEL_HS20_ICON " + bssid):
+ raise Exception("DEL_HS20_ICON failed")
+ if "OK" not in dev[0].request("DEL_HS20_ICON "):
+ raise Exception("DEL_HS20_ICON failed")
+ for i in range(3):
+ if "FAIL" not in dev[i].request("DEL_HS20_ICON "):
+ raise Exception("DEL_HS20_ICON accepted when no icons left")
+
+def test_ap_hs20_fetch_osu_no_info(dev, apdev):
+ """Hotspot 2.0 OSU provider and no AP with info"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+ dir = "/tmp/osu-fetch"
+ if os.path.isdir(dir):
+ files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
+ for f in files:
+ os.remove(dir + "/" + f)
+ else:
+ try:
+ os.makedirs(dir)
+ except:
+ pass
+ dev[0].scan_for_bss(bssid, freq="2412")
+ try:
+ dev[0].request("SET osu_dir " + dir)
+ dev[0].request("FETCH_OSU")
+ ev = dev[0].wait_event(["OSU provider fetch completed"], timeout=30)
+ if ev is None:
+ raise Exception("Timeout on OSU fetch")
+ finally:
+ files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
+ for f in files:
+ os.remove(dir + "/" + f)
+ os.rmdir(dir)
+
+def test_ap_hs20_fetch_osu_no_icon(dev, apdev):
+ """Hotspot 2.0 OSU provider and no icon found"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo-no-file.png"
+ params['osu_ssid'] = '"HS 2.0 OSU open"'
+ params['osu_method_list'] = "1"
+ params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
+ params['osu_icon'] = "w1fi_logo"
+ params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
+ params['osu_server_uri'] = "https://example.com/osu/"
+ hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+ dir = "/tmp/osu-fetch"
+ if os.path.isdir(dir):
+ files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
+ for f in files:
+ os.remove(dir + "/" + f)
+ else:
+ try:
+ os.makedirs(dir)
+ except:
+ pass
+ dev[0].scan_for_bss(bssid, freq="2412")
+ try:
+ dev[0].request("SET osu_dir " + dir)
+ dev[0].request("FETCH_OSU")
+ ev = dev[0].wait_event(["OSU provider fetch completed"], timeout=30)
+ if ev is None:
+ raise Exception("Timeout on OSU fetch")
+ finally:
+ files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
+ for f in files:
+ os.remove(dir + "/" + f)
+ os.rmdir(dir)
+
+def get_icon(dev, bssid, iconname):
+ icon = ""
+ pos = 0
+ while True:
+ if pos > 100000:
+ raise Exception("Unexpectedly long icon")
+ res = dev.request("GET_HS20_ICON " + bssid + " " + iconname + " %d 3000" % pos)
+ if res.startswith("FAIL"):
+ break
+ icon += base64.b64decode(res)
+ pos += 3000
+ if len(icon) < 13:
+ raise Exception("Too short GET_HS20_ICON response")
+ return icon[0:13], icon[13:]
+
+def test_ap_hs20_req_hs20_icon(dev, apdev):
+ """Hotspot 2.0 OSU provider and multi-icon fetch with REQ_HS20_ICON"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hs20_icon'] = [ "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png",
+ "128:80:zxx:image/png:test_logo:auth_serv/sha512-server.pem" ]
+ params['osu_ssid'] = '"HS 2.0 OSU open"'
+ params['osu_method_list'] = "1"
+ params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
+ params['osu_icon'] = [ "w1fi_logo", "w1fi_logo2" ]
+ params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
+ params['osu_server_uri'] = "https://example.com/osu/"
+ hostapd.add_ap(apdev[0], params)
+
+ dev[0].scan_for_bss(bssid, freq="2412")
+
+ # First, fetch two icons from the AP to wpa_supplicant
+
+ if "OK" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
+ raise Exception("REQ_HS20_ICON failed")
+ ev = dev[0].wait_event(["RX-HS20-ICON"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on RX-HS20-ICON (1)")
+
+ if "OK" not in dev[0].request("REQ_HS20_ICON " + bssid + " test_logo"):
+ raise Exception("REQ_HS20_ICON failed")
+ ev = dev[0].wait_event(["RX-HS20-ICON"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on RX-HS20-ICON (2)")
+
+ # Then, fetch the icons from wpa_supplicant for validation
+
+ hdr, data1 = get_icon(dev[0], bssid, "w1fi_logo")
+ hdr, data2 = get_icon(dev[0], bssid, "test_logo")
+
+ with open('w1fi_logo.png', 'r') as f:
+ data = f.read()
+ if data1 != data:
+ raise Exception("Unexpected icon data (1)")
+
+ with open('auth_serv/sha512-server.pem', 'r') as f:
+ data = f.read()
+ if data2 != data:
+ raise Exception("Unexpected icon data (2)")
+
+ # Finally, delete the icons from wpa_supplicant
+
+ if "OK" not in dev[0].request("DEL_HS20_ICON " + bssid + " w1fi_logo"):
+ raise Exception("DEL_HS20_ICON failed")
+ if "OK" not in dev[0].request("DEL_HS20_ICON " + bssid + " test_logo"):
+ raise Exception("DEL_HS20_ICON failed")
+
+def test_ap_hs20_req_hs20_icon_oom(dev, apdev):
+ """Hotspot 2.0 icon fetch OOM with REQ_HS20_ICON"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hs20_icon'] = [ "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png",
+ "128:80:zxx:image/png:test_logo:auth_serv/sha512-server.pem" ]
+ params['osu_ssid'] = '"HS 2.0 OSU open"'
+ params['osu_method_list'] = "1"
+ params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
+ params['osu_icon'] = [ "w1fi_logo", "w1fi_logo2" ]
+ params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
+ params['osu_server_uri'] = "https://example.com/osu/"
+ hostapd.add_ap(apdev[0], params)
+
+ dev[0].scan_for_bss(bssid, freq="2412")
+
+ if "FAIL" not in dev[0].request("REQ_HS20_ICON 11:22:33:44:55:66 w1fi_logo"):
+ raise Exception("REQ_HS20_ICON succeeded with unknown BSSID")
+
+ with alloc_fail(dev[0], 1, "hs20_build_anqp_req;hs20_anqp_send_req"):
+ if "FAIL" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
+ raise Exception("REQ_HS20_ICON succeeded during OOM")
+
+ with alloc_fail(dev[0], 1, "gas_query_req;hs20_anqp_send_req"):
+ if "FAIL" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
+ raise Exception("REQ_HS20_ICON succeeded during OOM")
+
+ with alloc_fail(dev[0], 1, "=hs20_anqp_send_req"):
+ if "FAIL" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
+ raise Exception("REQ_HS20_ICON succeeded during OOM")
+ with alloc_fail(dev[0], 2, "=hs20_anqp_send_req"):
+ if "FAIL" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
+ raise Exception("REQ_HS20_ICON succeeded during OOM")
+
+ if "OK" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
+ raise Exception("REQ_HS20_ICON failed")
+ ev = dev[0].wait_event(["RX-HS20-ICON"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on RX-HS20-ICON (1)")
+
+ with alloc_fail(dev[0], 1, "hs20_get_icon"):
+ if "FAIL" not in dev[0].request("GET_HS20_ICON " + bssid + "w1fi_logo 0 100"):
+ raise Exception("GET_HS20_ICON succeeded during OOM")
+
+ if "OK" not in dev[0].request("DEL_HS20_ICON " + bssid + " w1fi_logo"):
+ raise Exception("DEL_HS20_ICON failed")
+
+ with alloc_fail(dev[0], 1, "=hs20_process_icon_binary_file"):
+ if "OK" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
+ raise Exception("REQ_HS20_ICON failed")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+
+def test_ap_hs20_req_hs20_icon_parallel(dev, apdev):
+ """Hotspot 2.0 OSU provider and multi-icon parallel fetch with REQ_HS20_ICON"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hs20_icon'] = [ "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png",
+ "128:80:zxx:image/png:test_logo:auth_serv/sha512-server.pem" ]
+ params['osu_ssid'] = '"HS 2.0 OSU open"'
+ params['osu_method_list'] = "1"
+ params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
+ params['osu_icon'] = [ "w1fi_logo", "w1fi_logo2" ]
+ params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
+ params['osu_server_uri'] = "https://example.com/osu/"
+ hostapd.add_ap(apdev[0], params)
+
+ dev[0].scan_for_bss(bssid, freq="2412")
+
+ # First, fetch two icons from the AP to wpa_supplicant
+
+ if "OK" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
+ raise Exception("REQ_HS20_ICON failed")
+
+ if "OK" not in dev[0].request("REQ_HS20_ICON " + bssid + " test_logo"):
+ raise Exception("REQ_HS20_ICON failed")
+ ev = dev[0].wait_event(["RX-HS20-ICON"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on RX-HS20-ICON (1)")
+ ev = dev[0].wait_event(["RX-HS20-ICON"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on RX-HS20-ICON (2)")
+
+ # Then, fetch the icons from wpa_supplicant for validation
+
+ hdr, data1 = get_icon(dev[0], bssid, "w1fi_logo")
+ hdr, data2 = get_icon(dev[0], bssid, "test_logo")
+
+ with open('w1fi_logo.png', 'r') as f:
+ data = f.read()
+ if data1 != data:
+ raise Exception("Unexpected icon data (1)")
+
+ with open('auth_serv/sha512-server.pem', 'r') as f:
+ data = f.read()
+ if data2 != data:
+ raise Exception("Unexpected icon data (2)")
+
+ # Finally, delete the icons from wpa_supplicant
+
+ if "OK" not in dev[0].request("DEL_HS20_ICON " + bssid + " w1fi_logo"):
+ raise Exception("DEL_HS20_ICON failed")
+ if "OK" not in dev[0].request("DEL_HS20_ICON " + bssid + " test_logo"):
+ raise Exception("DEL_HS20_ICON failed")
+
def test_ap_hs20_fetch_osu_stop(dev, apdev):
"""Hotspot 2.0 OSU provider fetch stopped"""
bssid = apdev[0]['bssid']
params['osu_icon'] = "w1fi_logo"
params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
params['osu_server_uri'] = "https://example.com/osu/"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
dir = "/tmp/osu-fetch"
ev = dev[0].wait_event(["INTERWORKING-AP", "INTERWORKING-NO-MATCH"],
timeout=15)
if ev is None:
- raise Exception("Network selection timed out");
+ raise Exception("Network selection timed out")
dev[0].dump_monitor()
if "OK" not in dev[0].request("FETCH_OSU"):
os.remove(dir + "/" + f)
os.rmdir(dir)
-def test_ap_hs20_ft(dev, apdev):
- """Hotspot 2.0 connection with FT"""
- check_eap_capa(dev[0], "MSCHAPV2")
+def test_ap_hs20_fetch_osu_proto(dev, apdev):
+ """Hotspot 2.0 OSU provider and protocol testing"""
bssid = apdev[0]['bssid']
params = hs20_ap_params()
- params['wpa_key_mgmt'] = "FT-EAP"
- params['nas_identifier'] = "nas1.w1.fi"
- params['r1_key_holder'] = "000102030405"
- params["mobility_domain"] = "a1b2"
- params["reassociation_deadline"] = "1000"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
- id = dev[0].add_cred_values({ 'realm': "example.com",
- 'username': "hs20-test",
- 'password': "password",
- 'ca_cert': "auth_serv/ca.pem",
- 'domain': "example.com",
- 'update_identifier': "1234" })
- interworking_select(dev[0], bssid, "home", freq="2412")
+ dir = "/tmp/osu-fetch"
+ if os.path.isdir(dir):
+ files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
+ for f in files:
+ os.remove(dir + "/" + f)
+ else:
+ try:
+ os.makedirs(dir)
+ except:
+ pass
+
+ tests = [ ( "Empty provider list (no OSU SSID field)", '' ),
+ ( "HS 2.0: Not enough room for OSU SSID",
+ binascii.unhexlify('01') ),
+ ( "HS 2.0: Invalid OSU SSID Length 33",
+ binascii.unhexlify('21') + 33*'A' ),
+ ( "HS 2.0: Not enough room for Number of OSU Providers",
+ binascii.unhexlify('0130') ),
+ ( "Truncated OSU Provider",
+ binascii.unhexlify('013001020000') ),
+ ( "HS 2.0: Ignored 5 bytes of extra data after OSU Providers",
+ binascii.unhexlify('0130001122334455') ),
+ ( "HS 2.0: Not enough room for OSU Friendly Name Length",
+ binascii.unhexlify('013001000000') ),
+ ( "HS 2.0: Not enough room for OSU Friendly Name Duples",
+ build_prov('0100') ),
+ ( "Invalid OSU Friendly Name", build_prov('040000000000') ),
+ ( "Invalid OSU Friendly Name(2)", build_prov('040004000000') ),
+ ( "HS 2.0: Not enough room for OSU Server URI length",
+ build_prov('0000') ),
+ ( "HS 2.0: Not enough room for OSU Server URI",
+ build_prov('000001') ),
+ ( "HS 2.0: Not enough room for OSU Method list length",
+ build_prov('000000') ),
+ ( "HS 2.0: Not enough room for OSU Method list",
+ build_prov('00000001') ),
+ ( "HS 2.0: Not enough room for Icons Available Length",
+ build_prov('00000000') ),
+ ( "HS 2.0: Not enough room for Icons Available Length(2)",
+ build_prov('00000001ff00') ),
+ ( "HS 2.0: Not enough room for Icons Available",
+ build_prov('000000000100') ),
+ ( "HS 2.0: Invalid Icon Metadata",
+ build_prov('00000000010000') ),
+ ( "HS 2.0: Not room for Icon Type",
+ build_prov('000000000900111122223333330200') ),
+ ( "HS 2.0: Not room for Icon Filename length",
+ build_prov('000000000900111122223333330100') ),
+ ( "HS 2.0: Not room for Icon Filename",
+ build_prov('000000000900111122223333330001') ),
+ ( "HS 2.0: Not enough room for OSU_NAI",
+ build_prov('000000000000') ),
+ ( "HS 2.0: Not enough room for OSU_NAI(2)",
+ build_prov('00000000000001') ),
+ ( "HS 2.0: Not enough room for OSU Service Description Length",
+ build_prov('00000000000000') ),
+ ( "HS 2.0: Not enough room for OSU Service Description Length(2)",
+ build_prov('0000000000000000') ),
+ ( "HS 2.0: Not enough room for OSU Service Description Duples",
+ build_prov('000000000000000100') ),
+ ( "Invalid OSU Service Description",
+ build_prov('00000000000000040000000000') ),
+ ( "Invalid OSU Service Description(2)",
+ build_prov('00000000000000040004000000') ) ]
+
+ try:
+ dev[0].request("SET osu_dir " + dir)
+ run_fetch_osu_icon_failure(hapd, dev, bssid)
+ for note, prov in tests:
+ run_fetch_osu(hapd, dev, bssid, note, prov)
+ finally:
+ files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
+ for f in files:
+ os.remove(dir + "/" + f)
+ os.rmdir(dir)
+
+def test_ap_hs20_fetch_osu_invalid_dir(dev, apdev):
+ """Hotspot 2.0 OSU provider and invalid directory"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
+ params['osu_ssid'] = '"HS 2.0 OSU open"'
+ params['osu_method_list'] = "1"
+ params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
+ params['osu_icon'] = "w1fi_logo"
+ params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
+ params['osu_server_uri'] = "https://example.com/osu/"
+ hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+ dir = "/tmp/osu-fetch-no-such-dir"
+ dev[0].scan_for_bss(bssid, freq="2412")
+ dev[0].request("SET osu_dir " + dir)
+ dev[0].request("FETCH_OSU no-scan")
+ ev = dev[0].wait_event(["Could not write OSU provider information"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on OSU fetch")
+
+def test_ap_hs20_fetch_osu_oom(dev, apdev):
+ """Hotspot 2.0 OSU provider and OOM"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hs20_icon'] = "128:80:zxx:image/png:w1fi_logo:w1fi_logo.png"
+ params['osu_ssid'] = '"HS 2.0 OSU open"'
+ params['osu_method_list'] = "1"
+ params['osu_friendly_name'] = [ "eng:Test OSU", "fin:Testi-OSU" ]
+ params['osu_icon'] = "w1fi_logo"
+ params['osu_service_desc'] = [ "eng:Example services", "fin:Esimerkkipalveluja" ]
+ params['osu_server_uri'] = "https://example.com/osu/"
+ hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+ dir = "/tmp/osu-fetch"
+ if os.path.isdir(dir):
+ files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
+ for f in files:
+ os.remove(dir + "/" + f)
+ else:
+ try:
+ os.makedirs(dir)
+ except:
+ pass
+ dev[0].scan_for_bss(bssid, freq="2412")
+ try:
+ dev[0].request("SET osu_dir " + dir)
+ with alloc_fail(dev[0], 1, "=hs20_osu_add_prov"):
+ dev[0].request("FETCH_OSU no-scan")
+ ev = dev[0].wait_event(["OSU provider fetch completed"], timeout=30)
+ if ev is None:
+ raise Exception("Timeout on OSU fetch")
+ with alloc_fail(dev[0], 1, "hs20_anqp_send_req;hs20_next_osu_icon"):
+ dev[0].request("FETCH_OSU no-scan")
+ ev = dev[0].wait_event(["OSU provider fetch completed"], timeout=30)
+ if ev is None:
+ raise Exception("Timeout on OSU fetch")
+ finally:
+ files = [ f for f in os.listdir(dir) if f.startswith("osu-") ]
+ for f in files:
+ os.remove(dir + "/" + f)
+ os.rmdir(dir)
+
+def build_prov(prov):
+ data = binascii.unhexlify(prov)
+ return binascii.unhexlify('013001') + struct.pack('<H', len(data)) + data
+
+def handle_osu_prov_fetch(hapd, dev, prov):
+ # GAS/ANQP query for OSU Providers List
+ query = gas_rx(hapd)
+ gas = parse_gas(query['payload'])
+ dialog_token = gas['dialog_token']
+
+ resp = action_response(query)
+ osu_prov = struct.pack('<HH', 0xdddd, len(prov) + 6) + binascii.unhexlify('506f9a110800') + prov
+ data = struct.pack('<H', len(osu_prov)) + osu_prov
+ resp['payload'] = anqp_initial_resp(dialog_token, 0) + data
+ send_gas_resp(hapd, resp)
+
+ ev = dev[0].wait_event(["RX-HS20-ANQP"], timeout=5)
+ if ev is None:
+ raise Exception("ANQP query response for OSU Providers not received")
+ if "OSU Providers list" not in ev:
+ raise Exception("ANQP query response for OSU Providers not received(2)")
+ ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
+ if ev is None:
+ raise Exception("ANQP query for OSU Providers list not completed")
+
+def start_osu_fetch(hapd, dev, bssid, note):
+ hapd.set("ext_mgmt_frame_handling", "0")
+ dev[0].request("BSS_FLUSH 0")
+ dev[0].scan_for_bss(bssid, freq="2412")
+ hapd.set("ext_mgmt_frame_handling", "1")
+ dev[0].dump_monitor()
+ dev[0].request("NOTE " + note)
+ dev[0].request("FETCH_OSU no-scan")
+
+def wait_osu_fetch_completed(dev):
+ ev = dev[0].wait_event(["OSU provider fetch completed"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on OSU fetch")
+
+def run_fetch_osu_icon_failure(hapd, dev, bssid):
+ start_osu_fetch(hapd, dev, bssid, "Icon fetch failure")
+
+ prov = binascii.unhexlify('01ff' + '01' + '800019000b656e6754657374204f53550c66696e54657374692d4f53551868747470733a2f2f6578616d706c652e636f6d2f6f73752f01011b00800050007a787809696d6167652f706e6709773166695f6c6f676f002a0013656e674578616d706c652073657276696365731566696e4573696d65726b6b6970616c76656c756a61')
+ handle_osu_prov_fetch(hapd, dev, prov)
+
+ # GAS/ANQP query for icon
+ query = gas_rx(hapd)
+ gas = parse_gas(query['payload'])
+ dialog_token = gas['dialog_token']
+
+ resp = action_response(query)
+ # Unexpected Advertisement Protocol in response
+ adv_proto = struct.pack('8B', 108, 6, 127, 0xdd, 0x00, 0x11, 0x22, 0x33)
+ data = struct.pack('<H', 0)
+ resp['payload'] = struct.pack('<BBBHH', ACTION_CATEG_PUBLIC,
+ GAS_INITIAL_RESPONSE,
+ gas['dialog_token'], 0, 0) + adv_proto + data
+ send_gas_resp(hapd, resp)
+
+ ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
+ if ev is None:
+ raise Exception("ANQP query for icon not completed")
+
+ wait_osu_fetch_completed(dev)
+
+def run_fetch_osu(hapd, dev, bssid, note, prov):
+ start_osu_fetch(hapd, dev, bssid, note)
+ handle_osu_prov_fetch(hapd, dev, prov)
+ wait_osu_fetch_completed(dev)
+
+def test_ap_hs20_ft(dev, apdev):
+ """Hotspot 2.0 connection with FT"""
+ check_eap_capa(dev[0], "MSCHAPV2")
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['wpa_key_mgmt'] = "FT-EAP"
+ params['nas_identifier'] = "nas1.w1.fi"
+ params['r1_key_holder'] = "000102030405"
+ params["mobility_domain"] = "a1b2"
+ params["reassociation_deadline"] = "1000"
+ hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+ id = dev[0].add_cred_values({ 'realm': "example.com",
+ 'username': "hs20-test",
+ 'password': "password",
+ 'ca_cert': "auth_serv/ca.pem",
+ 'domain': "example.com",
+ 'update_identifier': "1234" })
+ interworking_select(dev[0], bssid, "home", freq="2412")
interworking_connect(dev[0], bssid, "TTLS")
def test_ap_hs20_remediation_sql(dev, apdev, params):
"private_key": "auth_serv/server.key",
"subscr_remediation_url": "https://example.org/",
"subscr_remediation_method": "1" }
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['auth_server_port'] = "18128"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].request("SET pmf 1")
dev[0].hs20_enable()
params = hs20_ap_params()
params['hessid'] = bssid
params['disable_dgaf'] = '1'
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
dev[0].connect("test-hs20", proto="RSN", key_mgmt="WPA-EAP", eap="TTLS",
params = hs20_ap_params()
params['hessid'] = bssid
params['disable_dgaf'] = '1'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5")
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['nai_realm'] = [ "0,example.com,25[3:26]"]
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].add_network()
dev[0].hs20_enable()
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['nai_realm'] = [ "0,example.com,21[3:26][6:7][99:99]" ]
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
dev[0].add_cred_values(default_cred(user="user"))
params['hessid'] = bssid
params['disable_dgaf'] = '0'
params['proxy_arp'] = '1'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
+ hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
if "OK" in hapd.request("ENABLE"):
raise Exception("Incomplete hostapd configuration was accepted")
hapd.set("ap_isolate", "1")
check_eap_capa(dev[0], "MSCHAPV2")
bssid = apdev[0]['bssid']
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": 'secret',
- "ignore_broadcast_ssid": "1" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": 'secret',
+ "ignore_broadcast_ssid": "1" })
dev[0].scan_for_bss(bssid, freq=2412)
hapd.disable()
- hapd_global = hostapd.HostapdGlobal()
+ hapd_global = hostapd.HostapdGlobal(apdev[0])
hapd_global.flush()
hapd_global.remove(apdev[0]['ifname'])
params = hs20_ap_params()
params['hessid'] = bssid
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
id = dev[0].add_cred_values({ 'realm': "example.com",
params['na_mcast_to_ucast'] = '1'
params['ap_isolate'] = '1'
params['bridge'] = 'ap-br0'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
+ hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
try:
hapd.enable()
except:
if "OK" not in dev.request(cmd + binascii.hexlify(pkt)):
raise Exception("DATA_TEST_FRAME failed")
-def build_na(src_ll, ip_src, ip_dst, target, opt=None):
+def build_na(src_ll, ip_src, ip_dst, target, opt=None, flags=0):
link_mc = binascii.unhexlify("3333ff000002")
_src_ll = binascii.unhexlify(src_ll.replace(':',''))
proto = '\x86\xdd'
_ip_src = socket.inet_pton(socket.AF_INET6, ip_src)
_ip_dst = socket.inet_pton(socket.AF_INET6, ip_dst)
- reserved = '\x00\x00\x00\x00'
_target = socket.inet_pton(socket.AF_INET6, target)
if opt:
- payload = reserved + _target + opt
+ payload = struct.pack('>Bxxx', flags) + _target + opt
else:
- payload = reserved + _target
+ payload = struct.pack('>Bxxx', flags) + _target
icmp = build_icmpv6(_ip_src + _ip_dst, 136, 0, payload)
ipv6 = struct.pack('>BBBBHBB', 0x60, 0, 0, 0, len(icmp), 58, 255)
bssid = apdev[0]['bssid']
params = { 'ssid': 'open' }
params['proxy_arp'] = '1'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
+ hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
hapd.set("ap_isolate", "1")
hapd.set('bridge', 'ap-br0')
hapd.dump_monitor()
raise Exception("AP startup failed")
params2 = { 'ssid': 'another' }
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params2, no_enable=True)
+ hapd2 = hostapd.add_ap(apdev[1], params2, no_enable=True)
hapd2.set('bridge', 'ap-br0')
hapd2.enable()
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5", drv_params="")
# Remove the interface while the gas-query radio work is still pending and
# GAS query has not yet been started.
wpas.interface_remove("wlan5")
+
+def test_ap_hs20_anqp_format_errors(dev, apdev):
+ """Interworking network selection and ANQP format errors"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+ values = { 'realm': "example.com",
+ 'ca_cert': "auth_serv/ca.pem",
+ 'username': "hs20-test",
+ 'password': "password",
+ 'domain': "example.com" }
+ id = dev[0].add_cred_values(values)
+
+ dev[0].scan_for_bss(bssid, freq="2412")
+
+ tests = [ "00", "ffff", "010011223344", "020008000005112233445500",
+ "01000400000000", "01000000000000",
+ "01000300000200", "0100040000ff0000", "01000300000100",
+ "01000300000001",
+ "01000600000056112233",
+ "01000900000002050001000111",
+ "01000600000001000000", "01000600000001ff0000",
+ "01000600000001020001",
+ "010008000000010400010001", "0100080000000104000100ff",
+ "010011000000010d00050200020100030005000600",
+ "0000" ]
+ for t in tests:
+ hapd.set("anqp_elem", "263:" + t)
+ dev[0].request("INTERWORKING_SELECT freq=2412")
+ ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=5)
+ if ev is None:
+ raise Exception("Network selection timed out")
+ dev[0].dump_monitor()
+
+ dev[0].remove_cred(id)
+ id = dev[0].add_cred_values({ 'imsi': "555444-333222111", 'eap': "AKA",
+ 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"})
+
+ tests = [ "00", "0100", "0001", "00ff", "000200ff", "0003000101",
+ "00020100" ]
+ for t in tests:
+ hapd.set("anqp_elem", "264:" + t)
+ dev[0].request("INTERWORKING_SELECT freq=2412")
+ ev = dev[0].wait_event(["INTERWORKING-NO-MATCH"], timeout=5)
+ if ev is None:
+ raise Exception("Network selection timed out")
+ dev[0].dump_monitor()
+
+def test_ap_hs20_cred_with_nai_realm(dev, apdev):
+ """Hotspot 2.0 network selection and cred_with_nai_realm cred->realm"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+
+ id = dev[0].add_cred_values({ 'realm': "example.com",
+ 'username': "test",
+ 'password': "secret",
+ 'domain': "example.com",
+ 'eap': 'TTLS' })
+ interworking_select(dev[0], bssid, "home", freq=2412)
+ dev[0].remove_cred(id)
+
+ id = dev[0].add_cred_values({ 'realm': "foo.com",
+ 'username': "test",
+ 'password': "secret",
+ 'domain': "example.com",
+ 'roaming_consortium': "112234",
+ 'eap': 'TTLS' })
+ interworking_select(dev[0], bssid, "home", freq=2412, no_match=True)
+ dev[0].remove_cred(id)
+
+def test_ap_hs20_cred_and_no_roaming_consortium(dev, apdev):
+ """Hotspot 2.0 network selection and no roaming consortium"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ del params['roaming_consortium']
+ hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+
+ id = dev[0].add_cred_values({ 'realm': "example.com",
+ 'username': "test",
+ 'password': "secret",
+ 'domain': "example.com",
+ 'roaming_consortium': "112234",
+ 'eap': 'TTLS' })
+ interworking_select(dev[0], bssid, "home", freq=2412, no_match=True)
+
+def test_ap_hs20_interworking_oom(dev, apdev):
+ """Hotspot 2.0 network selection and OOM"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ params['nai_realm'] = [ "0,no.match.here;example.com;no.match.here.either,21[2:1][5:7]",
+ "0,example.com,13[5:6],21[2:4][5:7]",
+ "0,another.example.com" ]
+ hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+
+ id = dev[0].add_cred_values({ 'realm': "example.com",
+ 'username': "test",
+ 'password': "secret",
+ 'domain': "example.com",
+ 'eap': 'TTLS' })
+
+ dev[0].scan_for_bss(bssid, freq="2412")
+
+ funcs = [ "wpabuf_alloc;interworking_anqp_send_req",
+ "anqp_build_req;interworking_anqp_send_req",
+ "gas_query_req;interworking_anqp_send_req",
+ "dup_binstr;nai_realm_parse_realm",
+ "=nai_realm_parse_realm",
+ "=nai_realm_parse",
+ "=nai_realm_match" ]
+ for func in funcs:
+ with alloc_fail(dev[0], 1, func):
+ dev[0].request("INTERWORKING_SELECT auto freq=2412")
+ ev = dev[0].wait_event(["Starting ANQP"], timeout=5)
+ if ev is None:
+ raise Exception("ANQP did not start")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+
+def test_ap_hs20_no_cred_connect(dev, apdev):
+ """Hotspot 2.0 and connect attempt without credential"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+ dev[0].scan_for_bss(bssid, freq="2412")
+ if "FAIL" not in dev[0].request("INTERWORKING_CONNECT " + bssid):
+ raise Exception("Unexpected INTERWORKING_CONNECT success")
+
+def test_ap_hs20_no_rsn_connect(dev, apdev):
+ """Hotspot 2.0 and connect attempt without RSN"""
+ bssid = apdev[0]['bssid']
+ params = hostapd.wpa_params(ssid="test-hs20")
+ params['wpa_key_mgmt'] = "WPA-EAP"
+ params['ieee80211w'] = "1"
+ params['ieee8021x'] = "1"
+ params['auth_server_addr'] = "127.0.0.1"
+ params['auth_server_port'] = "1812"
+ params['auth_server_shared_secret'] = "radius"
+ params['interworking'] = "1"
+ params['roaming_consortium'] = [ "112233", "1020304050", "010203040506",
+ "fedcba" ]
+ params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]",
+ "0,another.example.com" ]
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+ dev[0].scan_for_bss(bssid, freq="2412")
+
+ id = dev[0].add_cred_values({ 'realm': "example.com",
+ 'username': "test",
+ 'password': "secret",
+ 'domain': "example.com",
+ 'roaming_consortium': "112233",
+ 'eap': 'TTLS' })
+
+ interworking_select(dev[0], bssid, freq=2412, no_match=True)
+ if "FAIL" not in dev[0].request("INTERWORKING_CONNECT " + bssid):
+ raise Exception("Unexpected INTERWORKING_CONNECT success")
+
+def test_ap_hs20_no_match_connect(dev, apdev):
+ """Hotspot 2.0 and connect attempt without matching cred"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+ dev[0].scan_for_bss(bssid, freq="2412")
+
+ id = dev[0].add_cred_values({ 'realm': "example.org",
+ 'username': "test",
+ 'password': "secret",
+ 'domain': "example.org",
+ 'roaming_consortium': "112234",
+ 'eap': 'TTLS' })
+
+ interworking_select(dev[0], bssid, freq=2412, no_match=True)
+ if "FAIL" not in dev[0].request("INTERWORKING_CONNECT " + bssid):
+ raise Exception("Unexpected INTERWORKING_CONNECT success")
+
+def test_ap_hs20_multiple_home_cred(dev, apdev):
+ """Hotspot 2.0 and select with multiple matching home credentials"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ params['nai_realm'] = [ "0,example.com,13[5:6],21[2:4][5:7]" ]
+ params['domain_name'] = "example.com"
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ bssid2 = apdev[1]['bssid']
+ params = hs20_ap_params(ssid="test-hs20-other")
+ params['hessid'] = bssid2
+ params['nai_realm'] = [ "0,example.org,13[5:6],21[2:4][5:7]" ]
+ params['domain_name'] = "example.org"
+ hapd2 = hostapd.add_ap(apdev[1], params)
+
+ dev[0].hs20_enable()
+ dev[0].scan_for_bss(bssid2, freq="2412")
+ dev[0].scan_for_bss(bssid, freq="2412")
+ id = dev[0].add_cred_values({ 'realm': "example.com",
+ 'priority': '2',
+ 'username': "hs20-test",
+ 'password': "password",
+ 'domain': "example.com" })
+ id2 = dev[0].add_cred_values({ 'realm': "example.org",
+ 'priority': '3',
+ 'username': "hs20-test",
+ 'password': "password",
+ 'domain': "example.org" })
+ dev[0].request("INTERWORKING_SELECT auto freq=2412")
+ ev = dev[0].wait_connected(timeout=15)
+ if bssid2 not in ev:
+ raise Exception("Connected to incorrect network")
+
+def test_ap_hs20_anqp_invalid_gas_response(dev, apdev):
+ """Hotspot 2.0 network selection and invalid GAS response"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].scan_for_bss(bssid, freq="2412")
+ hapd.set("ext_mgmt_frame_handling", "1")
+
+ dev[0].hs20_enable()
+
+ id = dev[0].add_cred_values({ 'realm': "example.com",
+ 'username': "test",
+ 'password': "secret",
+ 'domain': "example.com",
+ 'roaming_consortium': "112234",
+ 'eap': 'TTLS' })
+ dev[0].request("INTERWORKING_SELECT freq=2412")
+
+ query = gas_rx(hapd)
+ gas = parse_gas(query['payload'])
+
+ logger.info("ANQP: Unexpected Advertisement Protocol in response")
+ resp = action_response(query)
+ adv_proto = struct.pack('8B', 108, 6, 127, 0xdd, 0x00, 0x11, 0x22, 0x33)
+ data = struct.pack('<H', 0)
+ resp['payload'] = struct.pack('<BBBHH', ACTION_CATEG_PUBLIC,
+ GAS_INITIAL_RESPONSE,
+ gas['dialog_token'], 0, 0) + adv_proto + data
+ send_gas_resp(hapd, resp)
+
+ ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
+ if ev is None:
+ raise Exception("No ANQP-QUERY-DONE seen")
+ if "result=INVALID_FRAME" not in ev:
+ raise Exception("Unexpected result: " + ev)
+
+ dev[0].request("INTERWORKING_SELECT freq=2412")
+
+ query = gas_rx(hapd)
+ gas = parse_gas(query['payload'])
+
+ logger.info("ANQP: Invalid element length for Info ID 1234")
+ resp = action_response(query)
+ adv_proto = struct.pack('BBBB', 108, 2, 127, 0)
+ elements = struct.pack('<HH', 1234, 1)
+ data = struct.pack('<H', len(elements)) + elements
+ resp['payload'] = struct.pack('<BBBHH', ACTION_CATEG_PUBLIC,
+ GAS_INITIAL_RESPONSE,
+ gas['dialog_token'], 0, 0) + adv_proto + data
+ send_gas_resp(hapd, resp)
+
+ ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
+ if ev is None:
+ raise Exception("No ANQP-QUERY-DONE seen")
+ if "result=INVALID_FRAME" not in ev:
+ raise Exception("Unexpected result: " + ev)
+
+ with alloc_fail(dev[0], 1, "=anqp_add_extra"):
+ dev[0].request("INTERWORKING_SELECT freq=2412")
+
+ query = gas_rx(hapd)
+ gas = parse_gas(query['payload'])
+
+ resp = action_response(query)
+ elements = struct.pack('<HHHH', 1, 0, 1, 0)
+ data = struct.pack('<H', len(elements)) + elements
+ resp['payload'] = struct.pack('<BBBHH', ACTION_CATEG_PUBLIC,
+ GAS_INITIAL_RESPONSE,
+ gas['dialog_token'], 0, 0) + adv_proto + data
+ send_gas_resp(hapd, resp)
+
+ ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
+ if ev is None:
+ raise Exception("No ANQP-QUERY-DONE seen")
+ if "result=SUCCESS" not in ev:
+ raise Exception("Unexpected result: " + ev)
+
+ with alloc_fail(dev[0], 1, "wpabuf_alloc_copy;anqp_add_extra"):
+ dev[0].request("INTERWORKING_SELECT freq=2412")
+
+ query = gas_rx(hapd)
+ gas = parse_gas(query['payload'])
+
+ resp = action_response(query)
+ elements = struct.pack('<HHHH', 1, 0, 1, 0)
+ data = struct.pack('<H', len(elements)) + elements
+ resp['payload'] = struct.pack('<BBBHH', ACTION_CATEG_PUBLIC,
+ GAS_INITIAL_RESPONSE,
+ gas['dialog_token'], 0, 0) + adv_proto + data
+ send_gas_resp(hapd, resp)
+
+ ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
+ if ev is None:
+ raise Exception("No ANQP-QUERY-DONE seen")
+ if "result=SUCCESS" not in ev:
+ raise Exception("Unexpected result: " + ev)
+
+ tests = [ struct.pack('<HH', 0xdddd, 0),
+ struct.pack('<HH3B', 0xdddd, 3, 0x50, 0x6f, 0x9a),
+ struct.pack('<HH4B', 0xdddd, 4, 0x50, 0x6f, 0x9a, 0),
+ struct.pack('<HH4B', 0xdddd, 4, 0x11, 0x22, 0x33, 0),
+ struct.pack('<HHHH', 1, 0, 1, 0) ]
+ for elements in tests:
+ dev[0].request("INTERWORKING_SELECT freq=2412")
+
+ query = gas_rx(hapd)
+ gas = parse_gas(query['payload'])
+
+ resp = action_response(query)
+ data = struct.pack('<H', len(elements)) + elements
+ resp['payload'] = struct.pack('<BBBHH', ACTION_CATEG_PUBLIC,
+ GAS_INITIAL_RESPONSE,
+ gas['dialog_token'], 0, 0) + adv_proto + data
+ send_gas_resp(hapd, resp)
+
+ ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
+ if ev is None:
+ raise Exception("No ANQP-QUERY-DONE seen")
+ if "result=SUCCESS" not in ev:
+ raise Exception("Unexpected result: " + ev)
+
+def test_ap_hs20_set_profile_failures(dev, apdev):
+ """Hotspot 2.0 and failures during profile configuration"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ params['anqp_3gpp_cell_net'] = "555,444"
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+ dev[0].scan_for_bss(bssid, freq="2412")
+
+ id = dev[0].add_cred_values({ 'realm': "example.com",
+ 'domain': "example.com",
+ 'username': "test",
+ 'password': "secret",
+ 'eap': 'TTLS' })
+ interworking_select(dev[0], bssid, "home", freq=2412)
+ dev[0].dump_monitor()
+ dev[0].request("NOTE ssid->eap.eap_methods = os_malloc()")
+ with alloc_fail(dev[0], 1, "interworking_set_eap_params"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].remove_cred(id)
+
+ id = dev[0].add_cred_values({ 'realm': "example.com",
+ 'domain': "example.com",
+ 'username': "hs20-test-with-domain@example.com",
+ 'password': "password" })
+ interworking_select(dev[0], bssid, "home", freq=2412)
+ dev[0].dump_monitor()
+ dev[0].request("NOTE anon = os_malloc()")
+ with alloc_fail(dev[0], 1, "interworking_set_eap_params"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("NOTE Successful connection with cred->username including realm")
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ dev[0].wait_connected()
+ dev[0].remove_cred(id)
+ dev[0].wait_disconnected()
+
+ id = dev[0].add_cred_values({ 'realm': "example.com",
+ 'domain': "example.com",
+ 'username': "hs20-test",
+ 'password': "password" })
+ interworking_select(dev[0], bssid, "home", freq=2412)
+ dev[0].dump_monitor()
+ dev[0].request("NOTE anon = os_malloc() (second)")
+ with alloc_fail(dev[0], 1, "interworking_set_eap_params"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ with alloc_fail(dev[0], 1, "wpa_config_add_network;interworking_connect"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ with alloc_fail(dev[0], 1, "=interworking_connect"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("NOTE wpa_config_set(eap)")
+ with alloc_fail(dev[0], 1, "wpa_config_parse_eap;wpa_config_set;interworking_connect"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("NOTE wpa_config_set(TTLS-NON_EAP_MSCHAPV2-phase2)")
+ with alloc_fail(dev[0], 1, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].remove_cred(id)
+
+ id = dev[0].add_cred_values({ 'roaming_consortium': "112233",
+ 'domain': "example.com",
+ 'username': "hs20-test",
+ 'password': "password",
+ 'eap': 'TTLS',
+ 'phase2': "auth=MSCHAPV2" })
+ interworking_select(dev[0], bssid, "home", freq=2412)
+ dev[0].dump_monitor()
+ dev[0].request("NOTE anon = os_strdup()")
+ with alloc_fail(dev[0], 2, "interworking_set_eap_params"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("NOTE wpa_config_set_quoted(anonymous_identity)")
+ with alloc_fail(dev[0], 1, "=wpa_config_set_quoted;interworking_set_eap_params"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("NOTE Successful connection with cred->realm not included")
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ dev[0].wait_connected()
+ dev[0].remove_cred(id)
+ dev[0].wait_disconnected()
+
+ id = dev[0].add_cred_values({ 'roaming_consortium': "112233",
+ 'domain': "example.com",
+ 'realm': "example.com",
+ 'username': "user",
+ 'password': "password",
+ 'eap': 'PEAP' })
+ interworking_select(dev[0], bssid, "home", freq=2412)
+ dev[0].dump_monitor()
+ dev[0].request("NOTE id = os_strdup()")
+ with alloc_fail(dev[0], 2, "interworking_set_eap_params"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("NOTE wpa_config_set_quoted(identity)")
+ with alloc_fail(dev[0], 1, "=wpa_config_set_quoted;interworking_set_eap_params"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].remove_cred(id)
+
+ id = dev[0].add_cred_values({ 'roaming_consortium': "112233",
+ 'domain': "example.com",
+ 'realm': "example.com",
+ 'username': "user",
+ 'password': "password",
+ 'eap': "TTLS" })
+ interworking_select(dev[0], bssid, "home", freq=2412)
+ dev[0].dump_monitor()
+ dev[0].request("NOTE wpa_config_set_quoted(identity) (second)")
+ with alloc_fail(dev[0], 2, "=wpa_config_set_quoted;interworking_set_eap_params"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("NOTE wpa_config_set_quoted(password)")
+ with alloc_fail(dev[0], 3, "=wpa_config_set_quoted;interworking_set_eap_params"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ with alloc_fail(dev[0], 1, "wpa_config_add_network;interworking_connect_roaming_consortium"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ with alloc_fail(dev[0], 1, "=interworking_connect_roaming_consortium"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].remove_cred(id)
+
+ id = dev[0].add_cred_values({ 'roaming_consortium': "112233",
+ 'domain': "example.com",
+ 'realm': "example.com",
+ 'username': "user",
+ 'eap': "PEAP" })
+ dev[0].set_cred(id, "password", "ext:password");
+ interworking_select(dev[0], bssid, "home", freq=2412)
+ dev[0].dump_monitor()
+ dev[0].request("NOTE wpa_config_set(password)")
+ with alloc_fail(dev[0], 3, "wpa_config_set;interworking_set_eap_params"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ with alloc_fail(dev[0], 1, "interworking_set_hs20_params"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].remove_cred(id)
+
+ id = dev[0].add_cred_values({ 'realm': "example.com",
+ 'domain': "example.com",
+ 'username': "certificate-user",
+ 'phase1': "include_tls_length=0",
+ 'domain_suffix_match': "example.com",
+ 'ca_cert': "auth_serv/ca.pem",
+ 'client_cert': "auth_serv/user.pem",
+ 'private_key': "auth_serv/user.key",
+ 'private_key_passwd': "secret" })
+ interworking_select(dev[0], bssid, "home", freq=2412)
+ dev[0].dump_monitor()
+ dev[0].request("NOTE wpa_config_set_quoted(client_cert)")
+ with alloc_fail(dev[0], 2, "=wpa_config_set_quoted;interworking_set_eap_params"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("NOTE wpa_config_set_quoted(private_key)")
+ with alloc_fail(dev[0], 3, "=wpa_config_set_quoted;interworking_set_eap_params"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("NOTE wpa_config_set_quoted(private_key_passwd)")
+ with alloc_fail(dev[0], 4, "=wpa_config_set_quoted;interworking_set_eap_params"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("NOTE wpa_config_set_quoted(ca_cert)")
+ with alloc_fail(dev[0], 5, "=wpa_config_set_quoted;interworking_set_eap_params"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("NOTE wpa_config_set_quoted(domain_suffix_match)")
+ with alloc_fail(dev[0], 6, "=wpa_config_set_quoted;interworking_set_eap_params"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ with alloc_fail(dev[0], 1, "interworking_set_hs20_params"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].remove_cred(id)
+
+ id = dev[0].add_cred_values({ 'imsi': "555444-333222111", 'eap': "SIM",
+ 'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"})
+ interworking_select(dev[0], bssid, freq=2412)
+ dev[0].dump_monitor()
+ with alloc_fail(dev[0], 1, "interworking_set_hs20_params"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("NOTE wpa_config_set_quoted(password;milenage)")
+ with alloc_fail(dev[0], 2, "=wpa_config_set_quoted;interworking_connect_3gpp"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("NOTE wpa_config_set(eap)")
+ with alloc_fail(dev[0], 1, "wpa_config_parse_eap;wpa_config_set;interworking_connect_3gpp"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("NOTE set_root_nai:wpa_config_set(identity)")
+ with alloc_fail(dev[0], 1, "wpa_config_parse_str;interworking_connect_3gpp"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].remove_cred(id)
+
+ id = dev[0].add_cred_values({ 'roaming_consortium': "112233",
+ 'username': "user@example.com",
+ 'password': "password" })
+ interworking_select(dev[0], bssid, freq=2412)
+ dev[0].dump_monitor()
+ dev[0].request("NOTE Interworking: No EAP method set for credential using roaming consortium")
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ dev[0].remove_cred(id)
+
+ hapd.disable()
+ params = hs20_ap_params()
+ params['nai_realm'] = "0,example.com,25[3:26]"
+ hapd = hostapd.add_ap(apdev[0], params)
+ id = dev[0].add_cred_values({ 'realm': "example.com",
+ 'domain': "example.com",
+ 'username': "hs20-test",
+ 'password': "password" })
+ interworking_select(dev[0], bssid, freq=2412)
+ dev[0].dump_monitor()
+ dev[0].request("NOTE wpa_config_set(PEAP/FAST-phase1)")
+ with alloc_fail(dev[0], 1, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("NOTE wpa_config_set(PEAP/FAST-pac_interworking)")
+ with alloc_fail(dev[0], 2, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("NOTE wpa_config_set(PEAP/FAST-phase2)")
+ with alloc_fail(dev[0], 3, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+
+ hapd.disable()
+ params = hs20_ap_params()
+ params['nai_realm'] = "0,example.com,21"
+ hapd = hostapd.add_ap(apdev[0], params)
+ interworking_select(dev[0], bssid, freq=2412)
+ dev[0].request("NOTE wpa_config_set(TTLS-defaults-phase2)")
+ with alloc_fail(dev[0], 1, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+
+ hapd.disable()
+ params = hs20_ap_params()
+ params['nai_realm'] = "0,example.com,21[2:3]"
+ hapd = hostapd.add_ap(apdev[0], params)
+ interworking_select(dev[0], bssid, freq=2412)
+ dev[0].request("NOTE wpa_config_set(TTLS-NON_EAP_MSCHAP-phase2)")
+ with alloc_fail(dev[0], 1, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+
+ hapd.disable()
+ params = hs20_ap_params()
+ params['nai_realm'] = "0,example.com,21[2:2]"
+ hapd = hostapd.add_ap(apdev[0], params)
+ interworking_select(dev[0], bssid, freq=2412)
+ dev[0].request("NOTE wpa_config_set(TTLS-NON_EAP_CHAP-phase2)")
+ with alloc_fail(dev[0], 1, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+
+ hapd.disable()
+ params = hs20_ap_params()
+ params['nai_realm'] = "0,example.com,21[2:1]"
+ hapd = hostapd.add_ap(apdev[0], params)
+ interworking_select(dev[0], bssid, freq=2412)
+ dev[0].request("NOTE wpa_config_set(TTLS-NON_EAP_PAP-phase2)")
+ with alloc_fail(dev[0], 1, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+
+ hapd.disable()
+ params = hs20_ap_params()
+ params['nai_realm'] = "0,example.com,21[3:26]"
+ hapd = hostapd.add_ap(apdev[0], params)
+ interworking_select(dev[0], bssid, freq=2412)
+ dev[0].request("NOTE wpa_config_set(TTLS-EAP-MSCHAPV2-phase2)")
+ with alloc_fail(dev[0], 1, "wpa_config_parse_str;wpa_config_set;interworking_connect"):
+ dev[0].request("INTERWORKING_CONNECT " + bssid)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+
+ dev[0].remove_cred(id)
+
+def test_ap_hs20_unexpected(dev, apdev):
+ """Unexpected Hotspot 2.0 AP configuration"""
+ check_eap_capa(dev[0], "MSCHAPV2")
+ bssid = apdev[0]['bssid']
+ params = hostapd.wpa_eap_params(ssid="test-hs20-fake")
+ params['wpa'] = "3"
+ params['wpa_pairwise'] = "TKIP CCMP"
+ params['rsn_pairwise'] = "CCMP"
+ #params['vendor_elements'] = 'dd07506f9a10140000'
+ params['vendor_elements'] = 'dd04506f9a10'
+ hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+ dev[0].scan_for_bss(bssid, freq="2412")
+ dev[0].connect("test-hs20-fake", key_mgmt="WPA-EAP", eap="TTLS",
+ pairwise="TKIP",
+ identity="hs20-test", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ scan_freq="2412")
+
+ dev[1].hs20_enable()
+ dev[1].scan_for_bss(bssid, freq="2412")
+ dev[1].connect("test-hs20-fake", key_mgmt="WPA-EAP", eap="TTLS",
+ proto="WPA",
+ identity="hs20-test", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ scan_freq="2412")
+
+ dev[2].hs20_enable()
+ dev[2].scan_for_bss(bssid, freq="2412")
+ dev[2].connect("test-hs20-fake", key_mgmt="WPA-EAP", eap="TTLS",
+ proto="RSN", pairwise="CCMP",
+ identity="hs20-test", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ scan_freq="2412")
+
+def test_ap_interworking_element_update(dev, apdev):
+ """Dynamic Interworking element update"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].hs20_enable()
+ dev[0].scan_for_bss(bssid, freq="2412")
+ bss = dev[0].get_bss(bssid)
+ logger.info("Before update: " + str(bss))
+ if '6b091e0701020000000300' not in bss['ie']:
+ raise Exception("Expected Interworking element not seen before update")
+
+ # Update configuration parameters related to Interworking element
+ hapd.set('access_network_type', '2')
+ hapd.set('asra', '1')
+ hapd.set('esr', '1')
+ hapd.set('uesa', '1')
+ hapd.set('venue_group', '2')
+ hapd.set('venue_type', '8')
+ if "OK" not in hapd.request("UPDATE_BEACON"):
+ raise Exception("UPDATE_BEACON failed")
+ dev[0].request("BSS_FLUSH 0")
+ dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
+ bss = dev[0].get_bss(bssid)
+ logger.info("After update: " + str(bss))
+ if '6b09f20208020000000300' not in bss['ie']:
+ raise Exception("Expected Interworking element not seen after update")
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import time
import logging
logger = logging.getLogger()
import struct
-import subprocess
import hostapd
from utils import HwsimSkip, alloc_fail
import hwsim_utils
from test_ap_csa import csa_supported
-def clear_scan_cache(ifname):
- subprocess.call(['ifconfig', ifname, 'up'])
- subprocess.call(['iw', ifname, 'scan', 'trigger', 'freq', '2412', 'flush'])
+def clear_scan_cache(apdev):
+ ifname = apdev['ifname']
+ hostapd.cmd_execute(apdev, ['ifconfig', ifname, 'up'])
+ hostapd.cmd_execute(apdev, ['iw', ifname, 'scan', 'trigger', 'freq', '2412',
+ 'flush'])
time.sleep(0.1)
- subprocess.call(['ifconfig', ifname, 'down'])
+ hostapd.cmd_execute(apdev, ['ifconfig', ifname, 'down'])
+
+def set_world_reg(apdev0=None, apdev1=None, dev0=None):
+ if apdev0:
+ hostapd.cmd_execute(apdev0, ['iw', 'reg', 'set', '00'])
+ if apdev1:
+ hostapd.cmd_execute(apdev1, ['iw', 'reg', 'set', '00'])
+ if dev0:
+ dev0.cmd_execute(['iw', 'reg', 'set', '00'])
def test_ap_ht40_scan(dev, apdev):
"""HT40 co-ex scan"""
- clear_scan_cache(apdev[0]['ifname'])
+ clear_scan_cache(apdev[0])
params = { "ssid": "test-ht40",
"channel": "5",
"ht_capab": "[HT40-]"}
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
state = hapd.get_status_field("state")
if state != "HT_SCAN":
dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
+@remote_compatible
def test_ap_ht40_scan_conflict(dev, apdev):
"""HT40 co-ex scan conflict"""
- clear_scan_cache(apdev[0]['ifname'])
+ clear_scan_cache(apdev[0])
params = { "ssid": "test-ht40",
"channel": "6",
"ht_capab": "[HT40+]"}
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
params = { "ssid": "test-ht40",
"channel": "5",
"ht_capab": "[HT40-]"}
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
state = hapd.get_status_field("state")
if state != "HT_SCAN":
dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
+@remote_compatible
def test_ap_ht40_scan_conflict2(dev, apdev):
"""HT40 co-ex scan conflict (HT40-)"""
- clear_scan_cache(apdev[0]['ifname'])
+ clear_scan_cache(apdev[0])
params = { "ssid": "test-ht40",
"channel": "11",
"ht_capab": "[HT40-]"}
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
params = { "ssid": "test-ht40",
"channel": "1",
"ht_capab": "[HT40+]"}
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
state = hapd.get_status_field("state")
if state != "HT_SCAN":
def test_ap_ht40_scan_not_affected(dev, apdev):
"""HT40 co-ex scan and other BSS not affected"""
- clear_scan_cache(apdev[0]['ifname'])
+ clear_scan_cache(apdev[0])
params = { "ssid": "test-ht20",
"channel": "11" }
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
- subprocess.call(['ifconfig', apdev[0]['ifname'], 'up'])
- subprocess.call(['iw', apdev[0]['ifname'], 'scan', 'trigger', 'freq', '2462'])
+ hostapd.cmd_execute(apdev[0], ['ifconfig', apdev[0]['ifname'], 'up'])
+ hostapd.cmd_execute(apdev[0], ['iw', apdev[0]['ifname'], 'scan', 'trigger',
+ 'freq', '2462'])
time.sleep(0.5)
- subprocess.call(['iw', apdev[0]['ifname'], 'scan', 'dump'],
- stdout=open('/dev/null', 'w'))
+ hostapd.cmd_execute(apdev[0], ['iw', apdev[0]['ifname'], 'scan', 'dump'])
time.sleep(0.1)
- subprocess.call(['ifconfig', apdev[0]['ifname'], 'down'])
+ hostapd.cmd_execute(apdev[0], ['ifconfig', apdev[0]['ifname'], 'down'])
params = { "ssid": "test-ht40",
"channel": "1",
"ht_capab": "[HT40+]"}
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
state = hapd.get_status_field("state")
if state != "HT_SCAN":
dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
+@remote_compatible
def test_ap_ht40_scan_legacy_conflict(dev, apdev):
"""HT40 co-ex scan conflict with legacy 20 MHz AP"""
- clear_scan_cache(apdev[0]['ifname'])
+ clear_scan_cache(apdev[0])
params = { "ssid": "legacy-20",
"channel": "7", "ieee80211n": "0" }
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
params = { "ssid": "test-ht40",
"channel": "5",
"ht_capab": "[HT40-]"}
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
state = hapd.get_status_field("state")
if state != "HT_SCAN":
dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
+@remote_compatible
def test_ap_ht40_scan_ht20_conflict(dev, apdev):
"""HT40 co-ex scan conflict with HT 20 MHz AP"""
- clear_scan_cache(apdev[0]['ifname'])
+ clear_scan_cache(apdev[0])
params = { "ssid": "ht-20",
"channel": "7", "ieee80211n": "1" }
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
params = { "ssid": "test-ht40",
"channel": "5",
"ht_capab": "[HT40-]"}
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
state = hapd.get_status_field("state")
if state != "HT_SCAN":
def test_ap_ht40_scan_intolerant(dev, apdev):
"""HT40 co-ex scan finding an AP advertising 40 MHz intolerant"""
- clear_scan_cache(apdev[0]['ifname'])
+ clear_scan_cache(apdev[0])
params = { "ssid": "another-bss",
"channel": "1",
"ht_capab": "[40-INTOLERANT]" }
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
params = { "ssid": "test-ht40",
"channel": "1",
"ht_capab": "[HT40+]"}
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
state = hapd.get_status_field("state")
if state != "HT_SCAN":
def test_ap_ht40_scan_match(dev, apdev):
"""HT40 co-ex scan matching configuration"""
- clear_scan_cache(apdev[0]['ifname'])
+ clear_scan_cache(apdev[0])
params = { "ssid": "test-ht40",
"channel": "5",
"ht_capab": "[HT40-]"}
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
params = { "ssid": "test-ht40",
"channel": "5",
"ht_capab": "[HT40-]"}
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
state = hapd.get_status_field("state")
if state != "HT_SCAN":
def test_ap_ht40_5ghz_match(dev, apdev):
"""HT40 co-ex scan on 5 GHz with matching pri/sec channel"""
- clear_scan_cache(apdev[0]['ifname'])
+ clear_scan_cache(apdev[0])
try:
hapd = None
hapd2 = None
"channel": "36",
"country_code": "US",
"ht_capab": "[HT40+]"}
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
params = { "ssid": "test-ht40",
"hw_mode": "a",
"channel": "36",
"ht_capab": "[HT40+]"}
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
state = hapd.get_status_field("state")
if state != "HT_SCAN":
hapd.request("DISABLE")
if hapd2:
hapd2.request("DISABLE")
- subprocess.call(['iw', 'reg', 'set', '00'])
+ set_world_reg(apdev[0], apdev[1], dev[0])
dev[0].flush_scan_cache()
def test_ap_ht40_5ghz_switch(dev, apdev):
"""HT40 co-ex scan on 5 GHz switching pri/sec channel"""
- clear_scan_cache(apdev[0]['ifname'])
+ clear_scan_cache(apdev[0])
try:
hapd = None
hapd2 = None
"channel": "36",
"country_code": "US",
"ht_capab": "[HT40+]"}
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
params = { "ssid": "test-ht40",
"hw_mode": "a",
"channel": "40",
"ht_capab": "[HT40-]"}
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
state = hapd.get_status_field("state")
if state != "HT_SCAN":
hapd.request("DISABLE")
if hapd2:
hapd2.request("DISABLE")
- subprocess.call(['iw', 'reg', 'set', '00'])
+ set_world_reg(apdev[0], apdev[1], dev[0])
def test_ap_ht40_5ghz_switch2(dev, apdev):
"""HT40 co-ex scan on 5 GHz switching pri/sec channel (2)"""
- clear_scan_cache(apdev[0]['ifname'])
+ clear_scan_cache(apdev[0])
try:
hapd = None
hapd2 = None
"channel": "36",
"country_code": "US",
"ht_capab": "[HT40+]"}
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
id = dev[0].add_network()
dev[0].set_network(id, "mode", "2")
"hw_mode": "a",
"channel": "40",
"ht_capab": "[HT40-]"}
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
state = hapd.get_status_field("state")
if state != "HT_SCAN":
hapd.request("DISABLE")
if hapd2:
hapd2.request("DISABLE")
- subprocess.call(['iw', 'reg', 'set', '00'])
+ set_world_reg(apdev[0], apdev[1], dev[0])
dev[0].flush_scan_cache()
def test_obss_scan(dev, apdev):
"channel": "6",
"ht_capab": "[HT40-]",
"obss_interval": "10" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ params = { "ssid": "another-bss",
+ "channel": "9",
+ "ieee80211n": "0" }
+ hostapd.add_ap(apdev[1], params)
+ run_obss_scan(hapd, dev)
+
+def test_obss_scan_ht40_plus(dev, apdev):
+ """Overlapping BSS scan request (HT40+)"""
+ params = { "ssid": "obss-scan",
+ "channel": "6",
+ "ht_capab": "[HT40+]",
+ "obss_interval": "10" }
+ hapd = hostapd.add_ap(apdev[0], params)
params = { "ssid": "another-bss",
"channel": "9",
"ieee80211n": "0" }
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
+ run_obss_scan(hapd, dev)
+def run_obss_scan(hapd, dev):
dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
hapd.set("ext_mgmt_frame_handling", "1")
logger.info("Waiting for OBSS scan to occur")
"channel": "6",
"ht_capab": "[HT40-]",
"obss_interval": "10" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
params = { "ssid": "another-bss",
"channel": "7",
"ht_capab": "[40-INTOLERANT]" }
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
hapd.set("ext_mgmt_frame_handling", "1")
def test_obss_coex_report_handling(dev, apdev):
"""Overlapping BSS scan report handling with obss_interval=0"""
- clear_scan_cache(apdev[0]['ifname'])
+ clear_scan_cache(apdev[0])
params = { "ssid": "obss-scan",
"channel": "6",
"ht_capab": "[HT40-]" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
def test_obss_coex_report_handling1(dev, apdev):
"""Overlapping BSS scan report handling with obss_interval=1"""
- clear_scan_cache(apdev[0]['ifname'])
+ clear_scan_cache(apdev[0])
params = { "ssid": "obss-scan",
"channel": "6",
"ht_capab": "[HT40+]",
"obss_interval": "1" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
"channel": "6",
"ht_capab": "[HT40-]",
"ap_table_expiration_time": "2" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
status = hapd.get_status()
if status['olbc'] != '0' or status['olbc_ht'] != '0':
raise Exception("Unexpected OLBC information")
"hw_mode": "b",
"channel": "6",
"wmm_enabled": "0" }
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
time.sleep(0.5)
status = hapd.get_status()
if status['olbc'] != '1' or status['olbc_ht'] != '1':
raise Exception("Missing OLBC information")
- hapd_global = hostapd.HostapdGlobal()
- hapd_global.remove(apdev[1]['ifname'])
+ hostapd.remove_bss(apdev[1])
logger.info("Waiting for OLBC state to time out")
cleared = False
ifname1 = apdev[0]['ifname']
ifname2 = apdev[0]['ifname'] + '-2'
ifname3 = apdev[0]['ifname'] + '-3'
- hostapd.add_bss('phy3', ifname1, 'bss-1.conf')
- hostapd.add_bss('phy3', ifname2, 'bss-2.conf')
- hostapd.add_bss('phy3', ifname3, 'bss-3.conf')
+ hostapd.add_bss(apdev[0], ifname1, 'bss-1.conf')
+ hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf')
+ hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf')
params = { "ssid": "test-olbc",
"channel": "1",
"ap_table_max_size": "2" }
- hapd = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[1], params)
time.sleep(0.3)
with alloc_fail(hapd, 1, "ap_list_process_beacon"):
"hw_mode": "a",
"channel": "36",
"ht_capab": "[HT40+]" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
status = hapd.get_status()
if status['olbc'] != '0' or status['olbc_ht'] != '0':
raise Exception("Unexpected OLBC information")
"channel": "36",
"ieee80211n": "0",
"wmm_enabled": "0" }
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
found = False
for i in range(20):
time.sleep(0.1)
hapd.request("DISABLE")
if hapd2:
hapd2.request("DISABLE")
- subprocess.call(['iw', 'reg', 'set', '00'])
+ set_world_reg(apdev[0], apdev[1], None)
def test_ap_require_ht(dev, apdev):
"""Require HT"""
params = { "ssid": "require-ht",
"require_ht": "1" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
dev[1].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
disable_ht="1", wait_connect=False)
dev[0].connect("require-ht", key_mgmt="NONE", scan_freq="2412")
ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
+ dev[1].request("DISCONNECT")
if ev is None:
raise Exception("Association rejection timed out")
if "status_code=27" not in ev:
ampdu_density="1", disable_ht40="1", disable_sgi="1",
disable_ldpc="1")
+@remote_compatible
def test_ap_require_ht_limited_rates(dev, apdev):
"""Require HT with limited supported rates"""
params = { "ssid": "require-ht",
"supported_rates": "60 120 240 360 480 540",
"require_ht": "1" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
dev[1].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
disable_ht="1", wait_connect=False)
dev[0].connect("require-ht", key_mgmt="NONE", scan_freq="2412")
ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
+ dev[1].request("DISCONNECT")
if ev is None:
raise Exception("Association rejection timed out")
if "status_code=27" not in ev:
raise Exception("Unexpected rejection status code")
+@remote_compatible
def test_ap_ht_capab_not_supported(dev, apdev):
"""HT configuration with driver not supporting all ht_capab entries"""
params = { "ssid": "test-ht40",
"channel": "5",
"ht_capab": "[HT40-][LDPC][SMPS-STATIC][SMPS-DYNAMIC][GF][SHORT-GI-20][SHORT-GI-40][TX-STBC][RX-STBC1][RX-STBC12][RX-STBC123][DELAYED-BA][MAX-AMSDU-7935][DSSS_CCK-40][LSIG-TXOP-PROT]"}
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
+ hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
if "FAIL" not in hapd.request("ENABLE"):
raise Exception("Unexpected ENABLE success")
def test_ap_ht_40mhz_intolerant_sta(dev, apdev):
"""Associated STA indicating 40 MHz intolerant"""
- clear_scan_cache(apdev[0]['ifname'])
+ clear_scan_cache(apdev[0])
params = { "ssid": "intolerant",
"channel": "6",
"ht_capab": "[HT40-]" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
raise Exception("Unexpected num_sta_ht40_intolerant value")
if hapd.get_status_field("secondary_channel") != "-1":
def test_ap_ht_40mhz_intolerant_ap(dev, apdev):
"""Associated STA reports 40 MHz intolerant AP after association"""
- clear_scan_cache(apdev[0]['ifname'])
+ clear_scan_cache(apdev[0])
params = { "ssid": "ht",
"channel": "6",
"ht_capab": "[HT40-]",
"obss_interval": "3" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("ht", key_mgmt="NONE", scan_freq="2437")
params = { "ssid": "intolerant",
"channel": "5",
"ht_capab": "[40-INTOLERANT]" }
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
logger.info("Waiting for co-ex report from STA")
ok = False
"channel": "36",
"ht_capab": "[HT40+]",
"ieee80211n": "1" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
hwsim_utils.test_connectivity(dev[0], hapd)
dev[0].request("DISCONNECT")
if hapd:
hapd.request("DISABLE")
- subprocess.call(['iw', 'reg', 'set', '00'])
+ set_world_reg(apdev[0], None, dev[0])
dev[0].flush_scan_cache()
def test_ap_ht40_csa2(dev, apdev):
"channel": "36",
"ht_capab": "[HT40+]",
"ieee80211n": "1" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
hwsim_utils.test_connectivity(dev[0], hapd)
dev[0].request("DISCONNECT")
if hapd:
hapd.request("DISABLE")
- subprocess.call(['iw', 'reg', 'set', '00'])
+ set_world_reg(apdev[0], None, dev[0])
dev[0].flush_scan_cache()
def test_ap_ht40_csa3(dev, apdev):
"channel": "36",
"ht_capab": "[HT40+]",
"ieee80211n": "1" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
hwsim_utils.test_connectivity(dev[0], hapd)
dev[0].request("DISCONNECT")
if hapd:
hapd.request("DISABLE")
- subprocess.call(['iw', 'reg', 'set', '00'])
+ set_world_reg(apdev[0], None, dev[0])
dev[0].flush_scan_cache()
+@remote_compatible
def test_ap_ht_smps(dev, apdev):
"""SMPS AP configuration options"""
params = { "ssid": "ht1", "ht_capab": "[SMPS-STATIC]" }
try:
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
except:
raise HwsimSkip("Assume mac80211_hwsim was not recent enough to support SMPS")
params = { "ssid": "ht2", "ht_capab": "[SMPS-DYNAMIC]" }
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
dev[0].connect("ht1", key_mgmt="NONE", scan_freq="2412")
dev[1].connect("ht2", key_mgmt="NONE", scan_freq="2412")
hwsim_utils.test_connectivity(dev[0], hapd)
hwsim_utils.test_connectivity(dev[1], hapd2)
+@remote_compatible
def test_prefer_ht20(dev, apdev):
"""Preference on HT20 over no-HT"""
params = { "ssid": "test",
"channel": "1",
"ieee80211n": "0" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
params = { "ssid": "test",
"channel": "1",
"ieee80211n": "1" }
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
bssid2 = apdev[1]['bssid']
dev[0].scan_for_bss(bssid, freq=2412)
params = { "ssid": "test",
"channel": "1",
"ieee80211n": "1" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
params = { "ssid": "test",
"channel": "1",
"ieee80211n": "1",
"ht_capab": "[HT40+]" }
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
bssid2 = apdev[1]['bssid']
dev[0].scan_for_bss(bssid, freq=2412)
if est != "135000":
raise Exception("Unexpected BSS1 est_throughput: " + est)
+@remote_compatible
def test_prefer_ht20_during_roam(dev, apdev):
"""Preference on HT20 over no-HT in roaming consideration"""
params = { "ssid": "test",
"channel": "1",
"ieee80211n": "0" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
dev[0].scan_for_bss(bssid, freq=2412)
params = { "ssid": "test",
"channel": "1",
"ieee80211n": "1" }
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
bssid2 = apdev[1]['bssid']
dev[0].scan_for_bss(bssid2, freq=2412)
dev[0].scan(freq=2412)
dev[0].wait_connected()
-
+
if dev[0].get_status_field('bssid') != bssid2:
raise Exception("Unexpected BSS selected")
+@remote_compatible
def test_ap_ht40_5ghz_invalid_pair(dev, apdev):
"""HT40 on 5 GHz with invalid channel pair"""
- clear_scan_cache(apdev[0]['ifname'])
+ clear_scan_cache(apdev[0])
try:
params = { "ssid": "test-ht40",
"hw_mode": "a",
"channel": "40",
"country_code": "US",
"ht_capab": "[HT40+]"}
- hapd = hostapd.add_ap(apdev[1]['ifname'], params, wait_enabled=False)
- ev = hapd.wait_event(["AP-DISABLED"], timeout=10)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
+ ev = hapd.wait_event(["AP-DISABLED", "AP-ENABLED"], timeout=10)
+ if not ev:
+ raise Exception("AP setup failure timed out")
+ if "AP-ENABLED" in ev:
+ sec = hapd.get_status_field("secondary_channel")
+ if sec != "0":
+ raise Exception("Invalid 40 MHz channel accepted")
+ finally:
+ set_world_reg(apdev[0], None, None)
+
+@remote_compatible
+def test_ap_ht40_5ghz_disabled_sec(dev, apdev):
+ """HT40 on 5 GHz with disabled secondary channel"""
+ clear_scan_cache(apdev[0])
+ try:
+ params = { "ssid": "test-ht40",
+ "hw_mode": "a",
+ "channel": "48",
+ "country_code": "US",
+ "ht_capab": "[HT40+]"}
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
+ ev = hapd.wait_event(["AP-DISABLED", "AP-ENABLED"], timeout=10)
if not ev:
raise Exception("AP setup failure timed out")
+ if "AP-ENABLED" in ev:
+ sec = hapd.get_status_field("secondary_channel")
+ if sec != "0":
+ raise Exception("Invalid 40 MHz channel accepted")
finally:
- subprocess.call(['iw', 'reg', 'set', '00'])
+ set_world_reg(apdev[0], None, None)
+
+def test_ap_ht40_scan_broken_ap(dev, apdev):
+ """HT40 co-ex scan and broken legacy/HT AP"""
+ clear_scan_cache(apdev[0])
+
+ # Broken AP: Include HT Capabilities element but not HT Operation element
+ params = { "ssid": "legacy-20",
+ "channel": "7", "ieee80211n": "0",
+ "wmm_enabled": "1",
+ "vendor_elements": "2d1a0e001bffff000000000000000000000100000000000000000000" }
+ hapd2 = hostapd.add_ap(apdev[1], params)
+
+ params = { "ssid": "test-ht40",
+ "channel": "5",
+ "ht_capab": "[HT40-]"}
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
+
+ state = hapd.get_status_field("state")
+ if state != "HT_SCAN":
+ time.sleep(0.1)
+ state = hapd.get_status_field("state")
+ if state != "HT_SCAN":
+ raise Exception("Unexpected interface state - expected HT_SCAN")
+
+ ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
+ if not ev:
+ raise Exception("AP setup timed out")
+
+ state = hapd.get_status_field("state")
+ if state != "ENABLED":
+ raise Exception("Unexpected interface state - expected ENABLED")
+
+ freq = hapd.get_status_field("freq")
+ if freq != "2432":
+ raise Exception("Unexpected frequency: " + freq)
+ pri = hapd.get_status_field("channel")
+ if pri != "5":
+ raise Exception("Unexpected primary channel: " + pri)
+ sec = hapd.get_status_field("secondary_channel")
+ if sec != "-1":
+ raise Exception("Unexpected secondary channel: " + sec)
+
+ dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
+ dev[1].connect("legacy-20", key_mgmt="NONE", scan_freq="2442")
+ hwsim_utils.test_connectivity(dev[0], hapd)
+ hwsim_utils.test_connectivity(dev[1], hapd2)
params["eap_server"] = "1"
params["eap_user_file"] = "auth_serv/eap_user.conf"
params['nas_identifier'] = "nas1.w1.fi"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, key_mgmt="WPA-PSK", proto="WPA", pairwise="TKIP",
psk=passphrase, scan_freq="2412")
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import logging
logger = logging.getLogger()
import struct
import hostapd
import hwsim_utils
from tshark import run_tshark
-from utils import alloc_fail
+from utils import alloc_fail, fail_test, wait_fail_trigger
from wpasupplicant import WpaSupplicant
+@remote_compatible
def test_ap_open(dev, apdev):
"""AP with open mode (no security) configuration"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ _test_ap_open(dev, apdev)
+
+def _test_ap_open(dev, apdev):
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
bg_scan_period="0")
ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
"ignore_auth_probability": "0.5",
"ignore_assoc_probability": "0.5",
"ignore_reassoc_probability": "0.5" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
for i in range(0, 3):
dev[i].connect("open", key_mgmt="NONE", scan_freq="2412",
wait_connect=False)
for i in range(0, 3):
dev[i].wait_connected(timeout=20)
+@remote_compatible
def test_ap_open_unknown_action(dev, apdev):
"""AP with open mode configuration and unknown Action frame"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
bssid = apdev[0]['bssid']
cmd = "MGMT_TX {} {} freq=2412 action=765432".format(bssid, bssid)
def test_ap_open_invalid_wmm_action(dev, apdev):
"""AP with open mode configuration and invalid WMM Action frame"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
bssid = apdev[0]['bssid']
cmd = "MGMT_TX {} {} freq=2412 action=1100".format(bssid, bssid)
if ev is None or "result=SUCCESS" not in ev:
raise Exception("AP did not ack Action frame")
+@remote_compatible
def test_ap_open_reconnect_on_inactivity_disconnect(dev, apdev):
"""Reconnect to open mode AP after inactivity related disconnection"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
hapd.request("DEAUTHENTICATE " + dev[0].p2p_interface_addr() + " reason=4")
dev[0].wait_disconnected(timeout=5)
dev[0].wait_connected(timeout=2, error="Timeout on reconnection")
+@remote_compatible
def test_ap_open_assoc_timeout(dev, apdev):
"""AP timing out association"""
ssid = "test"
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
dev[0].scan(freq="2412")
hapd.set("ext_mgmt_frame_handling", "1")
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
hapd.set("ext_mgmt_frame_handling", "0")
dev[0].wait_connected(timeout=15)
+@remote_compatible
def test_ap_open_id_str(dev, apdev):
"""AP with open mode and id_str"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412", id_str="foo",
wait_connect=False)
ev = dev[0].wait_connected(timeout=10)
if dev[0].get_status_field("id_str") != "foo":
raise Exception("id_str mismatch")
+@remote_compatible
def test_ap_open_select_any(dev, apdev):
"""AP with open mode and select any network"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
id = dev[0].connect("unknown", key_mgmt="NONE", scan_freq="2412",
only_add_network=True)
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
dev[0].select_network("any")
dev[0].wait_connected(timeout=10)
+@remote_compatible
def test_ap_open_unexpected_assoc_event(dev, apdev):
"""AP with open mode and unexpected association event"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
dev[0].request("DISCONNECT")
dev[0].wait_disconnected(timeout=15)
dev[0].dump_monitor()
# This will be accepted due to matching network
- subprocess.call(['iw', 'dev', dev[0].ifname, 'connect', 'open', "2412",
- apdev[0]['bssid']])
+ dev[0].cmd_execute(['iw', 'dev', dev[0].ifname, 'connect', 'open', "2412",
+ apdev[0]['bssid']])
dev[0].wait_connected(timeout=15)
dev[0].dump_monitor()
dev[0].wait_disconnected(timeout=5)
dev[0].dump_monitor()
# This will result in disconnection due to no matching network
- subprocess.call(['iw', 'dev', dev[0].ifname, 'connect', 'open', "2412",
- apdev[0]['bssid']])
+ dev[0].cmd_execute(['iw', 'dev', dev[0].ifname, 'connect', 'open', "2412",
+ apdev[0]['bssid']])
dev[0].wait_disconnected(timeout=15)
+@remote_compatible
def test_ap_bss_load(dev, apdev):
"""AP with open mode (no security) configuration"""
- hapd = hostapd.add_ap(apdev[0]['ifname'],
+ hapd = hostapd.add_ap(apdev[0],
{ "ssid": "open",
"bss_load_update_period": "10" })
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
with alloc_fail(hapd, count, func):
started = False
try:
- hostapd.add_ap(apdev['ifname'], { "ssid": "open" })
+ hostapd.add_ap(apdev, { "ssid": "open" })
started = True
except:
pass
if started:
- raise Exception("hostapd interface started even with memory allocation failure: " + arg)
+ raise Exception("hostapd interface started even with memory allocation failure: %d:%s" % (count, func))
def test_ap_open_out_of_memory(dev, apdev):
"""hostapd failing to setup interface due to allocation failure"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
hapd_out_of_mem(hapd, apdev[1], 1, "hostapd_alloc_bss_data")
for i in range(1, 3):
hapd_out_of_mem(hapd, apdev[1], 1, "hostapd_driver_init")
- for i in range(1, 4):
+ for i in range(1, 3):
hapd_out_of_mem(hapd, apdev[1], i, "=wpa_driver_nl80211_drv_init")
# eloop_register_read_sock() call from i802_init()
- hapd_out_of_mem(hapd, apdev[1], 1, "eloop_sock_table_add_sock;eloop_register_sock;?eloop_register_read_sock;=i802_init")
+ hapd_out_of_mem(hapd, apdev[1], 1, "eloop_sock_table_add_sock;?eloop_register_sock;?eloop_register_read_sock;=i802_init")
# verify that a new interface can still be added when memory allocation does
# not fail
- hostapd.add_ap(apdev[1]['ifname'], { "ssid": "open" })
+ hostapd.add_ap(apdev[1], { "ssid": "open" })
def test_bssid_black_white_list(dev, apdev):
"""BSSID black/white list"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
+ hapd2 = hostapd.add_ap(apdev[1], { "ssid": "open" })
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
bssid_whitelist=apdev[1]['bssid'])
subprocess.call(['iw', ifname, 'set', '4addr', 'off'])
def _test_ap_open_wpas_in_bridge(dev, apdev):
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
br_ifname='sta-br0'
ifname='wlan5'
wpas.connect("open", key_mgmt="NONE", scan_freq="2412")
+@remote_compatible
def test_ap_open_start_disabled(dev, apdev):
"""AP with open mode and beaconing disabled"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open",
- "start_disabled": "1" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open",
+ "start_disabled": "1" })
bssid = apdev[0]['bssid']
dev[0].flush_scan_cache()
dev[0].scan_for_bss(bssid, freq=2412)
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
+@remote_compatible
def test_ap_open_start_disabled2(dev, apdev):
"""AP with open mode and beaconing disabled (2)"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open",
- "start_disabled": "1" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open",
+ "start_disabled": "1" })
bssid = apdev[0]['bssid']
dev[0].flush_scan_cache()
dev[0].request("RECONNECT")
dev[0].wait_connected()
+@remote_compatible
def test_ap_open_ifdown(dev, apdev):
"""AP with open mode and external ifconfig down"""
params = { "ssid": "open",
"ap_max_inactivity": "1" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
dev[1].connect("open", key_mgmt="NONE", scan_freq="2412")
- subprocess.call(['ip', 'link', 'set', 'dev', apdev[0]['ifname'], 'down'])
+ hapd.cmd_execute(['ip', 'link', 'set', 'dev', apdev[0]['ifname'], 'down'])
ev = hapd.wait_event(["AP-STA-DISCONNECTED"], timeout=10)
if ev is None:
raise Exception("Timeout on AP-STA-DISCONNECTED (1)")
# The following wait tests beacon loss detection in mac80211 on dev0.
# dev1 is used to test stopping of AP side functionality on client polling.
dev[1].request("REMOVE_NETWORK all")
- subprocess.call(['ip', 'link', 'set', 'dev', apdev[0]['ifname'], 'up'])
+ hapd.cmd_execute(['ip', 'link', 'set', 'dev', apdev[0]['ifname'], 'up'])
dev[0].wait_disconnected()
dev[1].wait_disconnected()
ev = hapd.wait_event(["INTERFACE-ENABLED"], timeout=10)
def test_ap_open_disconnect_in_ps(dev, apdev, params):
"""Disconnect with the client in PS to regression-test a kernel bug"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
bg_scan_period="0")
ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
if state != 2:
raise Exception("Didn't observe TIM bit getting set and unset (state=%d)" % state)
+@remote_compatible
def test_ap_open_select_network(dev, apdev):
"""Open mode connection and SELECT_NETWORK to change network"""
- hapd1 = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd1 = hostapd.add_ap(apdev[0], { "ssid": "open" })
bssid1 = apdev[0]['bssid']
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], { "ssid": "open2" })
+ hapd2 = hostapd.add_ap(apdev[1], { "ssid": "open2" })
bssid2 = apdev[1]['bssid']
id1 = dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
if bssid1 in res or bssid2 in res:
raise Exception("Unexpected blacklist entry(2)")
+@remote_compatible
def test_ap_open_disable_enable(dev, apdev):
"""AP with open mode getting disabled and re-enabled"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
bg_scan_period="0")
def test_ap_open_sta_enable_disable(dev, apdev):
"""AP with open mode and wpa_supplicant ENABLE/DISABLE_NETWORK"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
bssid = apdev[0]['bssid']
sta_enable_disable(dev[0], bssid)
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
sta_enable_disable(wpas, bssid)
+
+@remote_compatible
+def test_ap_open_select_twice(dev, apdev):
+ """AP with open mode and select network twice"""
+ id = dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
+ only_add_network=True)
+ dev[0].select_network(id)
+ ev = dev[0].wait_event(["CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=10)
+ if ev is None:
+ raise Exception("No result reported")
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
+ # Verify that the second SELECT_NETWORK starts a new scan immediately by
+ # waiting less than the default scan period.
+ dev[0].select_network(id)
+ dev[0].wait_connected(timeout=3)
+
+@remote_compatible
+def test_ap_open_reassoc_not_found(dev, apdev):
+ """AP with open mode and REASSOCIATE not finding a match"""
+ id = dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
+ only_add_network=True)
+ dev[0].select_network(id)
+ ev = dev[0].wait_event(["CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=10)
+ if ev is None:
+ raise Exception("No result reported")
+ dev[0].request("DISCONNECT")
+
+ time.sleep(0.1)
+ dev[0].dump_monitor()
+
+ dev[0].request("REASSOCIATE")
+ ev = dev[0].wait_event(["CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=10)
+ if ev is None:
+ raise Exception("No result reported")
+ dev[0].request("DISCONNECT")
+
+@remote_compatible
+def test_ap_open_sta_statistics(dev, apdev):
+ """AP with open mode and STA statistics"""
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
+ dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
+ addr = dev[0].own_addr()
+
+ stats1 = hapd.get_sta(addr)
+ logger.info("stats1: " + str(stats1))
+ time.sleep(0.4)
+ stats2 = hapd.get_sta(addr)
+ logger.info("stats2: " + str(stats2))
+ hwsim_utils.test_connectivity(dev[0], hapd)
+ stats3 = hapd.get_sta(addr)
+ logger.info("stats3: " + str(stats3))
+
+ # Cannot require specific inactive_msec changes without getting rid of all
+ # unrelated traffic, so for now, just print out the results in the log for
+ # manual checks.
+
+@remote_compatible
+def test_ap_open_poll_sta(dev, apdev):
+ """AP with open mode and STA poll"""
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
+ dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
+ addr = dev[0].own_addr()
+
+ if "OK" not in hapd.request("POLL_STA " + addr):
+ raise Exception("POLL_STA failed")
+ ev = hapd.wait_event(["AP-STA-POLL-OK"], timeout=5)
+ if ev is None:
+ raise Exception("Poll response not seen")
+ if addr not in ev:
+ raise Exception("Unexpected poll response: " + ev)
+
+def test_ap_open_pmf_default(dev, apdev):
+ """AP with open mode (no security) configuration and pmf=2"""
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
+ dev[1].connect("open", key_mgmt="NONE", scan_freq="2412",
+ ieee80211w="2", wait_connect=False)
+ dev[2].connect("open", key_mgmt="NONE", scan_freq="2412",
+ ieee80211w="1")
+ try:
+ dev[0].request("SET pmf 2")
+ dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
+
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected()
+ finally:
+ dev[0].request("SET pmf 0")
+ dev[2].request("DISCONNECT")
+ dev[2].wait_disconnected()
+
+ ev = dev[1].wait_event(["CTRL-EVENT-CONNECTED"], timeout=0.1)
+ if ev is not None:
+ raise Exception("Unexpected dev[1] connection")
+ dev[1].request("DISCONNECT")
+
+def test_ap_open_drv_fail(dev, apdev):
+ """AP with open mode and driver operations failing"""
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
+
+ with fail_test(dev[0], 1, "wpa_driver_nl80211_authenticate"):
+ dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+
+ with fail_test(dev[0], 1, "wpa_driver_nl80211_associate"):
+ dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import logging
logger = logging.getLogger()
-import subprocess
+import os
import hwsim_utils
import hostapd
+from tshark import run_tshark
+from utils import alloc_fail
+@remote_compatible
def test_ap_fragmentation_rts_set_high(dev, apdev):
"""WPA2-PSK AP with fragmentation and RTS thresholds larger than frame length"""
ssid = "test-wpa2-psk"
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['rts_threshold'] = "1000"
params['fragm_threshold'] = "2000"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
hwsim_utils.test_connectivity(dev[0], hapd)
+@remote_compatible
def test_ap_fragmentation_open(dev, apdev):
"""Open AP with fragmentation threshold"""
ssid = "fragmentation"
params = {}
params['ssid'] = ssid
params['fragm_threshold'] = "1000"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412")
hwsim_utils.test_connectivity(dev[0], hapd)
+@remote_compatible
def test_ap_fragmentation_wpa2(dev, apdev):
"""WPA2-PSK AP with fragmentation threshold"""
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['fragm_threshold'] = "1000"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
hwsim_utils.test_connectivity(dev[0], hapd)
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['vendor_elements'] = "dd0411223301"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ params['assocresp_elements'] = "dd0411223302"
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
bss = dev[0].get_bss(bssid)
if "dd0411223301" not in bss['ie']:
raise Exception("Vendor element not shown in scan results")
- hapd.set('vendor_elements', 'dd051122330203')
+ hapd.set('vendor_elements', 'dd051122330203dd0400137400dd04001374ff')
if "OK" not in hapd.request("UPDATE_BEACON"):
raise Exception("UPDATE_BEACON failed")
dev[1].scan_for_bss(apdev[0]['bssid'], freq="2412")
if "dd051122330203" not in bss['ie']:
raise Exception("New vendor element not shown in scan results")
+def test_ap_element_parse(dev, apdev):
+ """Information element parsing - extra coverage"""
+ bssid = apdev[0]['bssid']
+ ssid = "test-wpa2-psk"
+ params = { 'ssid': ssid,
+ 'vendor_elements': "380501020304059e009e009e009e009e009e00" }
+ hapd = hostapd.add_ap(apdev[0], params)
+ dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
+ bss = dev[0].get_bss(bssid)
+ if "38050102030405" not in bss['ie']:
+ raise Exception("Timeout element not shown in scan results")
+
+@remote_compatible
+def test_ap_element_parse_oom(dev, apdev):
+ """Information element parsing OOM"""
+ bssid = apdev[0]['bssid']
+ ssid = "test-wpa2-psk"
+ params = { 'ssid': ssid,
+ 'vendor_elements': "dd0d506f9a0a00000600411c440028" }
+ hapd = hostapd.add_ap(apdev[0], params)
+ dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
+ with alloc_fail(dev[0], 1, "wpabuf_alloc;ieee802_11_vendor_ie_concat"):
+ bss = dev[0].get_bss(bssid)
+ logger.info(str(bss))
+
def test_ap_country(dev, apdev):
"""WPA2-PSK AP setting country code and using 5 GHz band"""
try:
params['ieee80211d'] = '1'
params['hw_mode'] = 'a'
params['channel'] = '36'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="5180")
hwsim_utils.test_connectivity(dev[0], hapd)
finally:
dev[0].request("DISCONNECT")
if hapd:
hapd.request("DISABLE")
- subprocess.call(['iw', 'reg', 'set', '00'])
+ hostapd.cmd_execute(apdev[0], ['iw', 'reg', 'set', '00'])
dev[0].flush_scan_cache()
def test_ap_acl_accept(dev, apdev):
params = {}
params['ssid'] = ssid
params['accept_mac_file'] = "hostapd.macaddr"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412")
dev[1].scan_for_bss(apdev[0]['bssid'], freq="2412")
params = {}
params['ssid'] = ssid
params['deny_mac_file'] = "hostapd.macaddr"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412", wait_connect=False)
dev[1].scan_for_bss(apdev[0]['bssid'], freq="2412")
if ev is not None:
raise Exception("Unexpected association")
+@remote_compatible
def test_ap_wds_sta(dev, apdev):
"""WPA2-PSK AP with STA using 4addr mode"""
ssid = "test-wpa2-psk"
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['wds_sta'] = "1"
params['wds_bridge'] = "wds-br0"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
try:
- subprocess.call(['brctl', 'addbr', 'wds-br0'])
- subprocess.call(['brctl', 'setfd', 'wds-br0', '0'])
- subprocess.call(['ip', 'link', 'set', 'dev', 'wds-br0', 'up'])
- subprocess.call(['iw', dev[0].ifname, 'set', '4addr', 'on'])
+ dev[0].cmd_execute(['brctl', 'addbr', 'wds-br0'])
+ dev[0].cmd_execute(['brctl', 'setfd', 'wds-br0', '0'])
+ dev[0].cmd_execute(['ip', 'link', 'set', 'dev', 'wds-br0', 'up'])
+ dev[0].cmd_execute(['iw', dev[0].ifname, 'set', '4addr', 'on'])
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
hwsim_utils.test_connectivity_iface(dev[0], hapd, "wds-br0",
max_tries=15)
finally:
- subprocess.call(['iw', dev[0].ifname, 'set', '4addr', 'off'])
- subprocess.call(['ip', 'link', 'set', 'dev', 'wds-br0', 'down'])
- subprocess.call(['brctl', 'delbr', 'wds-br0'])
+ dev[0].cmd_execute(['iw', dev[0].ifname, 'set', '4addr', 'off'])
+ dev[0].cmd_execute(['ip', 'link', 'set', 'dev', 'wds-br0', 'down'])
+ dev[0].cmd_execute(['brctl', 'delbr', 'wds-br0'])
+@remote_compatible
def test_ap_inactivity_poll(dev, apdev):
"""AP using inactivity poll"""
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['ap_max_inactivity'] = "1"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
hapd.set("ext_mgmt_frame_handling", "1")
dev[0].request("DISCONNECT")
if ev is None:
raise Exception("STA disconnection on inactivity was not reported")
+@remote_compatible
def test_ap_inactivity_disconnect(dev, apdev):
"""AP using inactivity disconnect"""
ssid = "test-wpa2-psk"
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['ap_max_inactivity'] = "1"
params['skip_inactivity_poll'] = "1"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
hapd.set("ext_mgmt_frame_handling", "1")
dev[0].request("DISCONNECT")
if ev is None:
raise Exception("STA disconnection on inactivity was not reported")
+@remote_compatible
def test_ap_basic_rates(dev, apdev):
"""Open AP with lots of basic rates"""
ssid = "basic rates"
params = {}
params['ssid'] = ssid
params['basic_rates'] = "10 20 55 110 60 90 120 180 240 360 480 540"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412")
+@remote_compatible
def test_ap_short_preamble(dev, apdev):
"""Open AP with short preamble"""
ssid = "short preamble"
params = {}
params['ssid'] = ssid
params['preamble'] = "1"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412")
def test_ap_spectrum_management_required(dev, apdev):
params['spectrum_mgmt_required'] = "1"
try:
hapd = None
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, key_mgmt="NONE", scan_freq="5180")
finally:
dev[0].request("DISCONNECT")
if hapd:
hapd.request("DISABLE")
- subprocess.call(['iw', 'reg', 'set', '00'])
+ hostapd.cmd_execute(apdev[0], ['iw', 'reg', 'set', '00'])
dev[0].flush_scan_cache()
+@remote_compatible
def test_ap_max_listen_interval(dev, apdev):
"""Open AP with maximum listen interval limit"""
ssid = "listen"
params = {}
params['ssid'] = ssid
params['max_listen_interval'] = "1"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412", wait_connect=False)
ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
if ev is None:
if "status_code=51" not in ev:
raise Exception("Unexpected ASSOC-REJECT reason")
+@remote_compatible
def test_ap_max_num_sta(dev, apdev):
"""Open AP with maximum STA count"""
ssid = "max"
params = {}
params['ssid'] = ssid
params['max_num_sta'] = "1"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[1].connect(ssid, key_mgmt="NONE", scan_freq="2412")
dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412", wait_connect=False)
ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
if ev is not None:
raise Exception("Unexpected association")
+def test_ap_max_num_sta_no_probe_resp(dev, apdev, params):
+ """Maximum STA count and limit on Probe Response frames"""
+ logdir = params['logdir']
+ dev[0].flush_scan_cache()
+ ssid = "max"
+ params = {}
+ params['ssid'] = ssid
+ params['beacon_int'] = "2000"
+ params['max_num_sta'] = "1"
+ params['no_probe_resp_if_max_sta'] = "1"
+ hostapd.add_ap(apdev[0], params)
+ dev[1].connect(ssid, key_mgmt="NONE", scan_freq="2412")
+ dev[0].scan(freq=2412, type="ONLY")
+ dev[0].scan(freq=2412, type="ONLY")
+ seen = dev[0].get_bss(apdev[0]['bssid']) != None
+ dev[1].scan(freq=2412, type="ONLY")
+ if seen:
+ out = run_tshark(os.path.join(logdir, "hwsim0.pcapng"),
+ "wlan.fc.type_subtype == 5", ["wlan.da" ])
+ if out:
+ if dev[0].own_addr() not in out:
+ # Discovery happened through Beacon frame reception. That's not
+ # an error case.
+ seen = False
+ if dev[1].own_addr() not in out:
+ raise Exception("No Probe Response frames to dev[1] seen")
+ if seen:
+ raise Exception("AP found unexpectedly")
+
+@remote_compatible
def test_ap_tx_queue_params(dev, apdev):
"""Open AP with TX queue params set"""
ssid = "tx"
params['tx_queue_data1_cwmin'] = "7"
params['tx_queue_data1_cwmax'] = "1023"
params['tx_queue_data1_burst'] = "2"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412")
hwsim_utils.test_connectivity(dev[0], hapd)
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import time
-import subprocess
import logging
logger = logging.getLogger()
import hwsim_utils
import hostapd
+from utils import alloc_fail, fail_test, wait_fail_trigger
from wlantest import Wlantest
from wpasupplicant import WpaSupplicant
-from test_ap_eap import eap_connect
+@remote_compatible
def test_ap_pmf_required(dev, apdev):
"""WPA2-PSK AP with PMF required"""
ssid = "test-pmf-required"
+ params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
+ params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
+ params["ieee80211w"] = "2"
+ hapd = hostapd.add_ap(apdev[0], params)
+ Wlantest.setup(hapd)
wt = Wlantest()
wt.flush()
wt.add_passphrase("12345678")
- params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
- params["wpa_key_mgmt"] = "WPA-PSK-SHA256";
- params["ieee80211w"] = "2";
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
key_mgmt = hapd.get_config()['key_mgmt']
if key_mgmt.split(' ')[0] != "WPA-PSK-SHA256":
raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
scan_freq="2412")
hwsim_utils.test_connectivity(dev[1], hapd)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
hapd.request("SA_QUERY " + dev[0].p2p_interface_addr())
hapd.request("SA_QUERY " + dev[1].p2p_interface_addr())
wt.require_ap_pmf_mandatory(apdev[0]['bssid'])
dev[1].p2p_interface_addr()) < 1:
raise Exception("STA did not reply to SA Query")
+@remote_compatible
def test_ap_pmf_optional(dev, apdev):
"""WPA2-PSK AP with PMF optional"""
ssid = "test-pmf-optional"
+ params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
+ params["wpa_key_mgmt"] = "WPA-PSK"
+ params["ieee80211w"] = "1"
+ hapd = hostapd.add_ap(apdev[0], params)
+ Wlantest.setup(hapd)
wt = Wlantest()
wt.flush()
wt.add_passphrase("12345678")
- params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
- params["wpa_key_mgmt"] = "WPA-PSK";
- params["ieee80211w"] = "1";
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
dev[0].connect(ssid, psk="12345678", ieee80211w="1",
key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
scan_freq="2412")
wt.require_sta_pmf(apdev[0]['bssid'], dev[0].p2p_interface_addr())
wt.require_sta_pmf_mandatory(apdev[0]['bssid'], dev[1].p2p_interface_addr())
+@remote_compatible
def test_ap_pmf_optional_2akm(dev, apdev):
"""WPA2-PSK AP with PMF optional (2 AKMs)"""
ssid = "test-pmf-optional-2akm"
+ params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
+ params["wpa_key_mgmt"] = "WPA-PSK WPA-PSK-SHA256"
+ params["ieee80211w"] = "1"
+ hapd = hostapd.add_ap(apdev[0], params)
+ Wlantest.setup(hapd)
wt = Wlantest()
wt.flush()
wt.add_passphrase("12345678")
- params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
- params["wpa_key_mgmt"] = "WPA-PSK WPA-PSK-SHA256";
- params["ieee80211w"] = "1";
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
dev[0].connect(ssid, psk="12345678", ieee80211w="1",
key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
scan_freq="2412")
wt.require_sta_key_mgmt(apdev[0]['bssid'], dev[1].p2p_interface_addr(),
"PSK-SHA256")
+@remote_compatible
def test_ap_pmf_negative(dev, apdev):
"""WPA2-PSK AP without PMF (negative test)"""
ssid = "test-pmf-negative"
+ params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
+ hapd = hostapd.add_ap(apdev[0], params)
+ Wlantest.setup(hapd)
wt = Wlantest()
wt.flush()
wt.add_passphrase("12345678")
- params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
dev[0].connect(ssid, psk="12345678", ieee80211w="1",
key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
scan_freq="2412")
logger.debug("Ignore expected exception: " + str(e))
wt.require_ap_no_pmf(apdev[0]['bssid'])
+@remote_compatible
def test_ap_pmf_assoc_comeback(dev, apdev):
"""WPA2-PSK AP with PMF association comeback"""
ssid = "assoc-comeback"
+ params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
+ params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
+ params["ieee80211w"] = "2"
+ hapd = hostapd.add_ap(apdev[0], params)
+ Wlantest.setup(hapd)
wt = Wlantest()
wt.flush()
wt.add_passphrase("12345678")
- params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
- params["wpa_key_mgmt"] = "WPA-PSK-SHA256";
- params["ieee80211w"] = "2";
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
dev[0].connect(ssid, psk="12345678", ieee80211w="1",
key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
scan_freq="2412")
dev[0].p2p_interface_addr()) < 1:
raise Exception("AP did not use association comeback request")
+@remote_compatible
def test_ap_pmf_assoc_comeback2(dev, apdev):
"""WPA2-PSK AP with PMF association comeback (using DROP_SA)"""
ssid = "assoc-comeback"
+ params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
+ params["wpa_key_mgmt"] = "WPA-PSK"
+ params["ieee80211w"] = "1"
+ hapd = hostapd.add_ap(apdev[0], params)
+ Wlantest.setup(hapd)
wt = Wlantest()
wt.flush()
wt.add_passphrase("12345678")
- params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
- params["wpa_key_mgmt"] = "WPA-PSK";
- params["ieee80211w"] = "1";
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
dev[0].connect(ssid, psk="12345678", ieee80211w="2",
key_mgmt="WPA-PSK", proto="WPA2", scan_freq="2412")
if "OK" not in dev[0].request("DROP_SA"):
dev[0].p2p_interface_addr()) < 1:
raise Exception("AP did not use reassociation comeback request")
-def test_ap_pmf_sta_sa_query(dev, apdev):
- """WPA2-PSK AP with station using SA Query"""
- ssid = "assoc-comeback"
- addr = dev[0].own_addr()
- wt = Wlantest()
- wt.flush()
- wt.add_passphrase("12345678")
-
+def start_wpas_ap(ssid):
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5", drv_params="use_monitor=1")
id = wpas.add_network()
wpas.set_network(id, "pairwise", "CCMP")
wpas.set_network(id, "group", "CCMP")
wpas.set_network(id, "frequency", "2412")
+ wpas.set_network(id, "scan_freq", "2412")
wpas.connect_network(id)
+ wpas.dump_monitor()
+ return wpas
+
+def test_ap_pmf_sta_sa_query(dev, apdev):
+ """WPA2-PSK AP with station using SA Query"""
+ ssid = "assoc-comeback"
+ addr = dev[0].own_addr()
+
+ wpas = start_wpas_ap(ssid)
bssid = wpas.own_addr()
+ Wlantest.setup(wpas)
+ wt = Wlantest()
+ wt.flush()
+ wt.add_passphrase("12345678")
+
dev[0].connect(ssid, psk="12345678", ieee80211w="1",
key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
scan_freq="2412")
+ wpas.dump_monitor()
wpas.request("DEAUTHENTICATE " + addr + " test=0")
+ wpas.dump_monitor()
wpas.request("DISASSOCIATE " + addr + " test=0")
+ wpas.dump_monitor()
ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1)
if ev is not None:
raise Exception("Unexpected disconnection")
wpas.request("DEAUTHENTICATE " + addr + " reason=6 test=0")
+ wpas.dump_monitor()
wpas.request("DISASSOCIATE " + addr + " reason=7 test=0")
+ wpas.dump_monitor()
ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1)
if ev is not None:
raise Exception("Unexpected disconnection")
raise Exception("STA did not send SA Query")
if wt.get_sta_counter("valid_saqueryresp_rx", bssid, addr) < 1:
raise Exception("AP did not reply to SA Query")
+ wpas.dump_monitor()
def test_ap_pmf_sta_sa_query_no_response(dev, apdev):
"""WPA2-PSK AP with station using SA Query and getting no response"""
ssid = "assoc-comeback"
addr = dev[0].own_addr()
- wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
- wpas.interface_add("wlan5", drv_params="use_monitor=1")
- id = wpas.add_network()
- wpas.set_network(id, "mode", "2")
- wpas.set_network_quoted(id, "ssid", ssid)
- wpas.set_network(id, "proto", "WPA2")
- wpas.set_network(id, "key_mgmt", "WPA-PSK-SHA256")
- wpas.set_network(id, "ieee80211w", "2")
- wpas.set_network_quoted(id, "psk", "12345678")
- wpas.set_network(id, "pairwise", "CCMP")
- wpas.set_network(id, "group", "CCMP")
- wpas.set_network(id, "frequency", "2412")
- wpas.connect_network(id)
+ wpas = start_wpas_ap(ssid)
bssid = wpas.own_addr()
dev[0].connect(ssid, psk="12345678", ieee80211w="1",
key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
scan_freq="2412")
+ wpas.dump_monitor()
wpas.request("DEAUTHENTICATE " + addr + " test=0")
+ wpas.dump_monitor()
wpas.request("DISASSOCIATE " + addr + " test=0")
+ wpas.dump_monitor()
ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1)
if ev is not None:
raise Exception("Unexpected disconnection")
wpas.request("SET ext_mgmt_frame_handling 1")
wpas.request("DEAUTHENTICATE " + addr + " reason=6 test=0")
+ wpas.dump_monitor()
wpas.request("DISASSOCIATE " + addr + " reason=7 test=0")
+ wpas.dump_monitor()
dev[0].wait_disconnected()
+ wpas.dump_monitor()
wpas.request("SET ext_mgmt_frame_handling 0")
dev[0].wait_connected()
+ wpas.dump_monitor()
def test_ap_pmf_sta_unprot_deauth_burst(dev, apdev):
"""WPA2-PSK AP with station receiving burst of unprotected Deauthentication frames"""
ssid = "deauth-attack"
addr = dev[0].own_addr()
+
+ wpas = start_wpas_ap(ssid)
+ bssid = wpas.own_addr()
+
+ Wlantest.setup(wpas)
wt = Wlantest()
wt.flush()
wt.add_passphrase("12345678")
- wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
- wpas.interface_add("wlan5", drv_params="use_monitor=1")
- id = wpas.add_network()
- wpas.set_network(id, "mode", "2")
- wpas.set_network_quoted(id, "ssid", ssid)
- wpas.set_network(id, "proto", "WPA2")
- wpas.set_network(id, "key_mgmt", "WPA-PSK-SHA256")
- wpas.set_network(id, "ieee80211w", "2")
- wpas.set_network_quoted(id, "psk", "12345678")
- wpas.set_network(id, "pairwise", "CCMP")
- wpas.set_network(id, "group", "CCMP")
- wpas.set_network(id, "frequency", "2412")
- wpas.connect_network(id)
- bssid = wpas.own_addr()
-
dev[0].connect(ssid, psk="12345678", ieee80211w="1",
key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
scan_freq="2412")
if num_req != 2 or num_resp != 2:
raise Exception("Unexpected number of SA Query procedures (req=%d resp=%d)" % (num_req, num_resp))
+def test_ap_pmf_sta_sa_query_oom(dev, apdev):
+ """WPA2-PSK AP with station using SA Query (OOM)"""
+ ssid = "assoc-comeback"
+ addr = dev[0].own_addr()
+ wpas = start_wpas_ap(ssid)
+ dev[0].connect(ssid, psk="12345678", ieee80211w="1",
+ key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
+ scan_freq="2412")
+ with alloc_fail(dev[0], 1, "=sme_sa_query_timer"):
+ wpas.request("DEAUTHENTICATE " + addr + " reason=6 test=0")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("DISCONNECT")
+ wpas.request("DISCONNECT")
+ dev[0].wait_disconnected()
+
+def test_ap_pmf_sta_sa_query_local_failure(dev, apdev):
+ """WPA2-PSK AP with station using SA Query (local failure)"""
+ ssid = "assoc-comeback"
+ addr = dev[0].own_addr()
+ wpas = start_wpas_ap(ssid)
+ dev[0].connect(ssid, psk="12345678", ieee80211w="1",
+ key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
+ scan_freq="2412")
+ with fail_test(dev[0], 1, "os_get_random;sme_sa_query_timer"):
+ wpas.request("DEAUTHENTICATE " + addr + " reason=6 test=0")
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("DISCONNECT")
+ wpas.request("DISCONNECT")
+ dev[0].wait_disconnected()
+
def test_ap_pmf_required_eap(dev, apdev):
"""WPA2-EAP AP with PMF required"""
ssid = "test-pmf-required-eap"
params = hostapd.wpa2_eap_params(ssid=ssid)
- params["wpa_key_mgmt"] = "WPA-EAP-SHA256";
- params["ieee80211w"] = "2";
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ params["wpa_key_mgmt"] = "WPA-EAP-SHA256"
+ params["ieee80211w"] = "2"
+ hapd = hostapd.add_ap(apdev[0], params)
key_mgmt = hapd.get_config()['key_mgmt']
if key_mgmt.split(' ')[0] != "WPA-EAP-SHA256":
raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
def test_ap_pmf_optional_eap(dev, apdev):
"""WPA2EAP AP with PMF optional"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- params["ieee80211w"] = "1";
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ params["ieee80211w"] = "1"
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="pap user", anonymous_identity="ttls",
password="password",
ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
ieee80211w="2", scan_freq="2412")
+@remote_compatible
def test_ap_pmf_required_sha1(dev, apdev):
"""WPA2-PSK AP with PMF required with SHA1 AKM"""
ssid = "test-pmf-required-sha1"
+ params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
+ params["wpa_key_mgmt"] = "WPA-PSK"
+ params["ieee80211w"] = "2"
+ hapd = hostapd.add_ap(apdev[0], params)
+ Wlantest.setup(hapd)
wt = Wlantest()
wt.flush()
wt.add_passphrase("12345678")
- params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
- params["wpa_key_mgmt"] = "WPA-PSK";
- params["ieee80211w"] = "2";
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
key_mgmt = hapd.get_config()['key_mgmt']
if key_mgmt.split(' ')[0] != "WPA-PSK":
raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
raise Exception("Scan results missing RSN element info")
hwsim_utils.test_connectivity(dev[0], hapd)
+@remote_compatible
def test_ap_pmf_toggle(dev, apdev):
"""WPA2-PSK AP with PMF optional and changing PMF on reassociation"""
try:
def _test_ap_pmf_toggle(dev, apdev):
ssid = "test-pmf-optional"
- wt = Wlantest()
- wt.flush()
- wt.add_passphrase("12345678")
params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
- params["wpa_key_mgmt"] = "WPA-PSK";
- params["ieee80211w"] = "1";
+ params["wpa_key_mgmt"] = "WPA-PSK"
+ params["ieee80211w"] = "1"
params["assoc_sa_query_max_timeout"] = "1"
params["assoc_sa_query_retry_timeout"] = "1"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
+ Wlantest.setup(hapd)
+ wt = Wlantest()
+ wt.flush()
+ wt.add_passphrase("12345678")
bssid = apdev[0]['bssid']
addr = dev[0].own_addr()
dev[0].request("SET reassoc_same_bss_optim 1")
sta = hapd.get_sta(addr)
if '[MFP]' in sta['flags']:
raise Exception("MFP flag unexpectedly present for STA")
- cmd = subprocess.Popen(['iw', 'dev', apdev[0]['ifname'], 'station', 'get',
- addr], stdout=subprocess.PIPE)
- (data,err) = cmd.communicate()
+ err, data = hapd.cmd_execute(['iw', 'dev', apdev[0]['ifname'], 'station',
+ 'get', addr])
if "yes" in [l for l in data.splitlines() if "MFP" in l][0]:
raise Exception("Kernel STA entry had MFP enabled")
sta = hapd.get_sta(addr)
if '[MFP]' not in sta['flags']:
raise Exception("MFP flag not present for STA")
- cmd = subprocess.Popen(['iw', 'dev', apdev[0]['ifname'], 'station', 'get',
- addr], stdout=subprocess.PIPE)
- (data,err) = cmd.communicate()
+ err, data = hapd.cmd_execute(['iw', 'dev', apdev[0]['ifname'], 'station',
+ 'get', addr])
if "yes" not in [l for l in data.splitlines() if "MFP" in l][0]:
raise Exception("Kernel STA entry did not have MFP enabled")
+
+@remote_compatible
+def test_ap_pmf_required_sta_no_pmf(dev, apdev):
+ """WPA2-PSK AP with PMF required and PMF disabled on STA"""
+ ssid = "test-pmf-required"
+ params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
+ params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
+ params["ieee80211w"] = "2"
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ # Disable PMF on the station and try to connect
+ dev[0].connect(ssid, psk="12345678", ieee80211w="0",
+ key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
+ scan_freq="2412", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-NETWORK-NOT-FOUND",
+ "CTRL-EVENT-ASSOC-REJECT"], timeout=2)
+ if ev is None:
+ raise Exception("No connection result")
+ if "CTRL-EVENT-ASSOC-REJECT" in ev:
+ raise Exception("Tried to connect to PMF required AP without PMF enabled")
+ dev[0].request("REMOVE_NETWORK all")
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import binascii
from Crypto.Cipher import AES
import hashlib
if mib[v[0]] != v[1]:
raise Exception("Unexpected {} = {} (expected {})".format(v[0], mib[v[0]], v[1]))
+@remote_compatible
def test_ap_wpa2_psk(dev, apdev):
"""WPA2-PSK AP with PSK instead of passphrase"""
ssid = "test-wpa2-psk"
psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6'
params = hostapd.wpa2_params(ssid=ssid)
params['wpa_psk'] = psk
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
key_mgmt = hapd.get_config()['key_mgmt']
if key_mgmt.split(' ')[0] != "WPA-PSK":
raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['wpa_psk_file'] = 'hostapd.wpa_psk'
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[1].connect(ssid, psk="very secret", scan_freq="2412", wait_connect=False)
dev[2].connect(ssid, raw_psk=psk, scan_freq="2412")
dev[2].request("REMOVE_NETWORK all")
raise Exception("Timed out while waiting for failure report")
dev[1].request("REMOVE_NETWORK all")
+@remote_compatible
def test_ap_wpa2_psk_mem(dev, apdev):
"""WPA2-PSK AP with passphrase only in memory"""
try:
psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6'
params = hostapd.wpa2_params(ssid=ssid)
params['wpa_psk'] = psk
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, mem_only_psk="1", scan_freq="2412", wait_connect=False)
dev[0].request("SCAN_INTERVAL 1")
dev[1].request("CTRL-RSP-PSK_PASSPHRASE-" + id + ':' + psk)
dev[1].wait_connected(timeout=10)
+@remote_compatible
def test_ap_wpa2_ptk_rekey(dev, apdev):
"""WPA2-PSK AP and PTK rekey enforced by station"""
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", scan_freq="2412")
ev = dev[0].wait_event(["WPA: Key negotiation completed"])
if ev is None:
raise Exception("PTK rekey timed out")
hwsim_utils.test_connectivity(dev[0], hapd)
+@remote_compatible
def test_ap_wpa2_ptk_rekey_ap(dev, apdev):
"""WPA2-PSK AP and PTK rekey enforced by AP"""
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['wpa_ptk_rekey'] = '2'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
ev = dev[0].wait_event(["WPA: Key negotiation completed"])
if ev is None:
raise Exception("PTK rekey timed out")
hwsim_utils.test_connectivity(dev[0], hapd)
+@remote_compatible
def test_ap_wpa2_sha256_ptk_rekey(dev, apdev):
"""WPA2-PSK/SHA256 AKM AP and PTK rekey enforced by station"""
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, key_mgmt="WPA-PSK-SHA256",
wpa_ptk_rekey="1", scan_freq="2412")
ev = dev[0].wait_event(["WPA: Key negotiation completed"])
check_mib(dev[0], [ ("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-6"),
("dot11RSNAAuthenticationSuiteSelected", "00-0f-ac-6") ])
+@remote_compatible
def test_ap_wpa2_sha256_ptk_rekey_ap(dev, apdev):
"""WPA2-PSK/SHA256 AKM AP and PTK rekey enforced by AP"""
ssid = "test-wpa2-psk"
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
params['wpa_ptk_rekey'] = '2'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, key_mgmt="WPA-PSK-SHA256",
scan_freq="2412")
ev = dev[0].wait_event(["WPA: Key negotiation completed"])
check_mib(dev[0], [ ("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-6"),
("dot11RSNAAuthenticationSuiteSelected", "00-0f-ac-6") ])
+@remote_compatible
def test_ap_wpa_ptk_rekey(dev, apdev):
"""WPA-PSK/TKIP AP and PTK rekey enforced by station"""
skip_with_fips(dev[0])
ssid = "test-wpa-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa_params(ssid=ssid, passphrase=passphrase)
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", scan_freq="2412")
if "[WPA-PSK-TKIP]" not in dev[0].request("SCAN_RESULTS"):
raise Exception("Scan results missing WPA element info")
raise Exception("PTK rekey timed out")
hwsim_utils.test_connectivity(dev[0], hapd)
+@remote_compatible
def test_ap_wpa_ptk_rekey_ap(dev, apdev):
"""WPA-PSK/TKIP AP and PTK rekey enforced by AP"""
skip_with_fips(dev[0])
passphrase = 'qwertyuiop'
params = hostapd.wpa_params(ssid=ssid, passphrase=passphrase)
params['wpa_ptk_rekey'] = '2'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=10)
if ev is None:
raise Exception("PTK rekey timed out")
hwsim_utils.test_connectivity(dev[0], hapd)
+@remote_compatible
def test_ap_wpa_ccmp(dev, apdev):
"""WPA-PSK/CCMP"""
ssid = "test-wpa-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa_params(ssid=ssid, passphrase=passphrase)
params['wpa_pairwise'] = "CCMP"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
hwsim_utils.test_connectivity(dev[0], hapd)
check_mib(dev[0], [ ("dot11RSNAConfigGroupCipherSize", "128"),
try:
# missing PSK file
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
+ hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
if "FAIL" not in hapd.request("ENABLE"):
raise Exception("Unexpected ENABLE success")
hapd.request("DISABLE")
except:
pass
+@remote_compatible
def test_ap_wpa2_psk_wildcard_ssid(dev, apdev):
"""WPA2-PSK AP and wildcard SSID configuration"""
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("", bssid=apdev[0]['bssid'], psk=passphrase,
scan_freq="2412")
dev[1].connect("", bssid=apdev[0]['bssid'], raw_psk=psk, scan_freq="2412")
+@remote_compatible
def test_ap_wpa2_gtk_rekey(dev, apdev):
"""WPA2-PSK AP and GTK rekey enforced by AP"""
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['wpa_group_rekey'] = '1'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
if ev is None:
raise Exception("GTK rekey timed out")
hwsim_utils.test_connectivity(dev[0], hapd)
+@remote_compatible
def test_ap_wpa_gtk_rekey(dev, apdev):
"""WPA-PSK/TKIP AP and GTK rekey enforced by AP"""
skip_with_fips(dev[0])
passphrase = 'qwertyuiop'
params = hostapd.wpa_params(ssid=ssid, passphrase=passphrase)
params['wpa_group_rekey'] = '1'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
if ev is None:
raise Exception("GTK rekey timed out")
hwsim_utils.test_connectivity(dev[0], hapd)
+@remote_compatible
def test_ap_wpa2_gmk_rekey(dev, apdev):
"""WPA2-PSK AP and GMK and GTK rekey enforced by AP"""
ssid = "test-wpa2-psk"
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['wpa_group_rekey'] = '1'
params['wpa_gmk_rekey'] = '2'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
for i in range(0, 3):
ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
raise Exception("GTK rekey timed out")
hwsim_utils.test_connectivity(dev[0], hapd)
+@remote_compatible
def test_ap_wpa2_strict_rekey(dev, apdev):
"""WPA2-PSK AP and strict GTK rekey enforced by AP"""
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['wpa_strict_rekey'] = '1'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
dev[1].connect(ssid, psk=passphrase, scan_freq="2412")
dev[1].request("DISCONNECT")
raise Exception("GTK rekey timed out")
hwsim_utils.test_connectivity(dev[0], hapd)
+@remote_compatible
def test_ap_wpa2_bridge_fdb(dev, apdev):
"""Bridge FDB entry removal"""
+ hapd = None
try:
ssid = "test-wpa2-psk"
passphrase = "12345678"
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['bridge'] = 'ap-br0'
- hostapd.add_ap(apdev[0]['ifname'], params)
- subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
- subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
+ hapd = hostapd.add_ap(apdev[0], params)
+ hapd.cmd_execute(['brctl', 'setfd', 'ap-br0', '0'])
+ hapd.cmd_execute(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
dev[0].connect(ssid, psk=passphrase, scan_freq="2412",
bssid=apdev[0]['bssid'])
dev[1].connect(ssid, psk=passphrase, scan_freq="2412",
bssid=apdev[0]['bssid'])
addr0 = dev[0].p2p_interface_addr()
hwsim_utils.test_connectivity_sta(dev[0], dev[1])
- cmd = subprocess.Popen(['brctl', 'showmacs', 'ap-br0'],
- stdout=subprocess.PIPE)
- macs1 = cmd.stdout.read()
+ err, macs1 = hapd.cmd_execute(['brctl', 'showmacs', 'ap-br0'])
+ hapd.cmd_execute(['brctl', 'setageing', 'ap-br0', '1'])
dev[0].request("DISCONNECT")
dev[1].request("DISCONNECT")
time.sleep(1)
- cmd = subprocess.Popen(['brctl', 'showmacs', 'ap-br0'],
- stdout=subprocess.PIPE)
- macs2 = cmd.stdout.read()
+ err, macs2 = hapd.cmd_execute(['brctl', 'showmacs', 'ap-br0'])
addr1 = dev[1].p2p_interface_addr()
if addr0 not in macs1 or addr1 not in macs1:
if addr0 in macs2 or addr1 in macs2:
raise Exception("Bridge FDB entry was not removed")
finally:
- subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'])
- subprocess.call(['brctl', 'delbr', 'ap-br0'])
+ hostapd.cmd_execute(apdev[0], ['ip', 'link', 'set', 'dev', 'ap-br0',
+ 'down'])
+ hostapd.cmd_execute(apdev[0], ['brctl', 'delbr', 'ap-br0'])
+@remote_compatible
def test_ap_wpa2_already_in_bridge(dev, apdev):
"""hostapd behavior with interface already in bridge"""
ifname = apdev[0]['ifname']
try:
ssid = "test-wpa2-psk"
passphrase = "12345678"
- subprocess.call(['brctl', 'addbr', br_ifname])
- subprocess.call(['brctl', 'setfd', br_ifname, '0'])
- subprocess.call(['ip', 'link', 'set', 'dev', br_ifname, 'up'])
- subprocess.call(['iw', ifname, 'set', 'type', '__ap'])
- subprocess.call(['brctl', 'addif', br_ifname, ifname])
+ hostapd.cmd_execute(apdev[0], ['brctl', 'addbr', br_ifname])
+ hostapd.cmd_execute(apdev[0], ['brctl', 'setfd', br_ifname, '0'])
+ hostapd.cmd_execute(apdev[0], ['ip', 'link', 'set', 'dev', br_ifname,
+ 'up'])
+ hostapd.cmd_execute(apdev[0], ['iw', ifname, 'set', 'type', '__ap'])
+ hostapd.cmd_execute(apdev[0], ['brctl', 'addif', br_ifname, ifname])
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
- hapd = hostapd.add_ap(ifname, params)
+ hapd = hostapd.add_ap(apdev[0], params)
if hapd.get_driver_status_field('brname') != br_ifname:
raise Exception("Bridge name not identified correctly")
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
finally:
- subprocess.call(['ip', 'link', 'set', 'dev', br_ifname, 'down'])
- subprocess.call(['brctl', 'delif', br_ifname, ifname])
- subprocess.call(['iw', ifname, 'set', 'type', 'station'])
- subprocess.call(['brctl', 'delbr', br_ifname])
+ hostapd.cmd_execute(apdev[0], ['ip', 'link', 'set', 'dev', br_ifname,
+ 'down'])
+ hostapd.cmd_execute(apdev[0], ['brctl', 'delif', br_ifname, ifname])
+ hostapd.cmd_execute(apdev[0], ['iw', ifname, 'set', 'type', 'station'])
+ hostapd.cmd_execute(apdev[0], ['brctl', 'delbr', br_ifname])
+@remote_compatible
def test_ap_wpa2_in_different_bridge(dev, apdev):
"""hostapd behavior with interface in different bridge"""
ifname = apdev[0]['ifname']
try:
ssid = "test-wpa2-psk"
passphrase = "12345678"
- subprocess.call(['brctl', 'addbr', br_ifname])
- subprocess.call(['brctl', 'setfd', br_ifname, '0'])
- subprocess.call(['ip', 'link', 'set', 'dev', br_ifname, 'up'])
- subprocess.call(['iw', ifname, 'set', 'type', '__ap'])
- subprocess.call(['brctl', 'addif', br_ifname, ifname])
+ hostapd.cmd_execute(apdev[0], ['brctl', 'addbr', br_ifname])
+ hostapd.cmd_execute(apdev[0], ['brctl', 'setfd', br_ifname, '0'])
+ hostapd.cmd_execute(apdev[0], ['ip', 'link', 'set', 'dev', br_ifname,
+ 'up'])
+ hostapd.cmd_execute(apdev[0], ['iw', ifname, 'set', 'type', '__ap'])
+ hostapd.cmd_execute(apdev[0], ['brctl', 'addif', br_ifname, ifname])
time.sleep(0.5)
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['bridge'] = 'ap-br0'
- hapd = hostapd.add_ap(ifname, params)
- subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
- subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
+ hapd = hostapd.add_ap(apdev[0], params)
+ hostapd.cmd_execute(apdev[0], ['brctl', 'setfd', 'ap-br0', '0'])
+ hostapd.cmd_execute(apdev[0], ['ip', 'link', 'set', 'dev', 'ap-br0',
+ 'up'])
brname = hapd.get_driver_status_field('brname')
if brname != 'ap-br0':
raise Exception("Incorrect bridge: " + brname)
dev[0].request("DISCONNECT")
hapd.disable()
finally:
- subprocess.call(['ip', 'link', 'set', 'dev', br_ifname, 'down'])
- subprocess.call(['brctl', 'delif', br_ifname, ifname],
- stderr=open('/dev/null', 'w'))
- subprocess.call(['brctl', 'delbr', br_ifname])
+ hostapd.cmd_execute(apdev[0], ['ip', 'link', 'set', 'dev', br_ifname,
+ 'down'])
+ hostapd.cmd_execute(apdev[0], ['brctl', 'delif', br_ifname, ifname,
+ "2>", "/dev/null"], shell=True)
+ hostapd.cmd_execute(apdev[0], ['brctl', 'delbr', br_ifname])
+@remote_compatible
def test_ap_wpa2_ext_add_to_bridge(dev, apdev):
"""hostapd behavior with interface added to bridge externally"""
ifname = apdev[0]['ifname']
ssid = "test-wpa2-psk"
passphrase = "12345678"
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
- hapd = hostapd.add_ap(ifname, params)
+ hapd = hostapd.add_ap(apdev[0], params)
- subprocess.call(['brctl', 'addbr', br_ifname])
- subprocess.call(['brctl', 'setfd', br_ifname, '0'])
- subprocess.call(['ip', 'link', 'set', 'dev', br_ifname, 'up'])
- subprocess.call(['brctl', 'addif', br_ifname, ifname])
+ hostapd.cmd_execute(apdev[0], ['brctl', 'addbr', br_ifname])
+ hostapd.cmd_execute(apdev[0], ['brctl', 'setfd', br_ifname, '0'])
+ hostapd.cmd_execute(apdev[0], ['ip', 'link', 'set', 'dev', br_ifname,
+ 'up'])
+ hostapd.cmd_execute(apdev[0], ['brctl', 'addif', br_ifname, ifname])
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
if hapd.get_driver_status_field('brname') != br_ifname:
raise Exception("Bridge name not identified correctly")
finally:
- subprocess.call(['ip', 'link', 'set', 'dev', br_ifname, 'down'])
- subprocess.call(['brctl', 'delif', br_ifname, ifname])
- subprocess.call(['brctl', 'delbr', br_ifname])
+ hostapd.cmd_execute(apdev[0], ['ip', 'link', 'set', 'dev', br_ifname,
+ 'down'])
+ hostapd.cmd_execute(apdev[0], ['brctl', 'delif', br_ifname, ifname])
+ hostapd.cmd_execute(apdev[0], ['brctl', 'delbr', br_ifname])
def test_ap_wpa2_psk_ext(dev, apdev):
"""WPA2-PSK AP using external EAPOL I/O"""
psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6'
params = hostapd.wpa2_params(ssid=ssid)
params['wpa_psk'] = psk
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
hapd.request("SET ext_eapol_frame_io 1")
dev[0].request("SET ext_eapol_frame_io 1")
dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False)
if "OK" not in res:
raise Exception("EAPOL_RX to hostapd failed")
+def test_ap_wpa2_psk_ext_retry_msg_3(dev, apdev):
+ """WPA2-PSK AP using external EAPOL I/O and retry for EAPOL-Key msg 3/4"""
+ bssid = apdev[0]['bssid']
+ ssid = "test-wpa2-psk"
+ passphrase = 'qwertyuiop'
+ psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6'
+ params = hostapd.wpa2_params(ssid=ssid)
+ params['wpa_psk'] = psk
+ hapd = hostapd.add_ap(apdev[0], params)
+ hapd.request("SET ext_eapol_frame_io 1")
+ dev[0].request("SET ext_eapol_frame_io 1")
+ dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False)
+ addr = dev[0].p2p_interface_addr()
+
+ # EAPOL-Key msg 1/4
+ ev = hapd.wait_event(["EAPOL-TX"], timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAPOL-TX from hostapd")
+ res = dev[0].request("EAPOL_RX " + bssid + " " + ev.split(' ')[2])
+ if "OK" not in res:
+ raise Exception("EAPOL_RX to wpa_supplicant failed")
+
+ # EAPOL-Key msg 2/4
+ ev = dev[0].wait_event(["EAPOL-TX"], timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAPOL-TX from wpa_supplicant")
+ res = hapd.request("EAPOL_RX " + addr + " " + ev.split(' ')[2])
+ if "OK" not in res:
+ raise Exception("EAPOL_RX to hostapd failed")
+
+ # EAPOL-Key msg 3/4
+ ev = hapd.wait_event(["EAPOL-TX"], timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAPOL-TX from hostapd")
+ res = dev[0].request("EAPOL_RX " + bssid + " " + ev.split(' ')[2])
+ if "OK" not in res:
+ raise Exception("EAPOL_RX to wpa_supplicant failed")
+
+ # EAPOL-Key msg 4/4
+ ev = dev[0].wait_event(["EAPOL-TX"], timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAPOL-TX from wpa_supplicant")
+ # Do not send to the AP
+ dev[0].wait_connected(timeout=15)
+
+ # EAPOL-Key msg 3/4 (retry)
+ ev = hapd.wait_event(["EAPOL-TX"], timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAPOL-TX from hostapd")
+ res = dev[0].request("EAPOL_RX " + bssid + " " + ev.split(' ')[2])
+ if "OK" not in res:
+ raise Exception("EAPOL_RX to wpa_supplicant failed")
+
+ # EAPOL-Key msg 4/4
+ ev = dev[0].wait_event(["EAPOL-TX"], timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAPOL-TX from wpa_supplicant")
+ res = hapd.request("EAPOL_RX " + addr + " " + ev.split(' ')[2])
+ if "OK" not in res:
+ raise Exception("EAPOL_RX to hostapd failed")
+
+ ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=15)
+ if ev is None:
+ raise Exception("Timeout on AP-STA-CONNECTED from hostapd")
+
+ hwsim_utils.test_connectivity(dev[0], hapd)
+
def parse_eapol(data):
(version, type, length) = struct.unpack('>BBH', data[0:4])
payload = data[4:]
else:
params = hostapd.wpa_params(ssid=ssid)
params['wpa_psk'] = psk
- hapd = hostapd.add_ap(apdev['ifname'], params)
+ hapd = hostapd.add_ap(apdev, params)
hapd.request("SET ext_eapol_frame_io 1")
dev.request("SET ext_eapol_frame_io 1")
dev.connect(ssid, raw_psk=psk, scan_freq="2412", wait_connect=False)
snonce = binascii.unhexlify('1111111111111111111111111111111111111111111111111111111111111111')
return (bssid,ssid,hapd,snonce,pmk,addr,rsne)
+@remote_compatible
def test_ap_wpa2_psk_ext_eapol(dev, apdev):
"""WPA2-PSK AP using external EAPOL supplicant"""
(bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
hapd_connected(hapd)
+@remote_compatible
def test_ap_wpa2_psk_ext_eapol_retry1(dev, apdev):
"""WPA2 4-way handshake with EAPOL-Key 1/4 retransmitted"""
(bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
hapd_connected(hapd)
+@remote_compatible
def test_ap_wpa2_psk_ext_eapol_retry1b(dev, apdev):
"""WPA2 4-way handshake with EAPOL-Key 1/4 and 2/4 retransmitted"""
(bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
hapd_connected(hapd)
+@remote_compatible
def test_ap_wpa2_psk_ext_eapol_retry1c(dev, apdev):
"""WPA2 4-way handshake with EAPOL-Key 1/4 and 2/4 retransmitted and SNonce changing"""
(bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
hapd_connected(hapd)
+@remote_compatible
def test_ap_wpa2_psk_ext_eapol_retry1d(dev, apdev):
"""WPA2 4-way handshake with EAPOL-Key 1/4 and 2/4 retransmitted and SNonce changing and older used"""
(bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
hapd_connected(hapd)
+@remote_compatible
def test_ap_wpa2_psk_ext_eapol_type_diff(dev, apdev):
"""WPA2 4-way handshake using external EAPOL supplicant"""
(bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
hapd_connected(hapd)
+@remote_compatible
def test_ap_wpa_psk_ext_eapol(dev, apdev):
"""WPA2-PSK AP using external EAPOL supplicant"""
(bssid,ssid,hapd,snonce,pmk,addr,wpae) = eapol_test(apdev[0], dev[0],
reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
hapd_connected(hapd)
+@remote_compatible
def test_ap_wpa2_psk_ext_eapol_key_info(dev, apdev):
"""WPA2-PSK 4-way handshake with strange key info values"""
(bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
raise Exception("Unexpected group key message not reported")
dev[0].wait_disconnected(timeout=1)
+@remote_compatible
def test_ap_wpa2_psk_supp_proto_msg_1_invalid_kde(dev, apdev):
"""WPA2-PSK supplicant protocol testing: invalid KDE in msg 1/4"""
(bssid,ssid,hapd,snonce,pmk,addr,rsne) = eapol_test(apdev[0], dev[0])
def find_wpas_process(dev):
ifname = dev.ifname
- cmd = subprocess.Popen(['ps', 'ax'], stdout=subprocess.PIPE)
- (data,err) = cmd.communicate()
+ err, data = dev.cmd_execute(['ps', 'ax'])
for l in data.splitlines():
if "wpa_supplicant" not in l:
continue
def read_process_memory(pid, key=None):
buf = bytes()
+ logger.info("Reading process memory (pid=%d)" % pid)
with open('/proc/%d/maps' % pid, 'r') as maps, \
open('/proc/%d/mem' % pid, 'r') as mem:
for l in maps.readlines():
continue
if not perm.startswith('rw'):
continue
+ for name in [ "[heap]", "[stack]" ]:
+ if name in l:
+ logger.info("%s 0x%x-0x%x is at %d-%d" % (name, start, end, len(buf), len(buf) + (end - start)))
mem.seek(start)
data = mem.read(end - start)
buf += data
if key and key in data:
logger.info("Key found in " + l)
+ logger.info("Total process memory read: %d bytes" % len(buf))
return buf
def verify_not_present(buf, key, fname, keyname):
if pos < 0:
break
logger.info("Found %s at %d" % (keyname, pos))
+ context = 128
+ start = pos - context if pos > context else 0
+ before = binascii.hexlify(buf[start:pos])
+ context += len(key)
+ end = pos + context if pos < len(buf) - context else len(buf) - context
+ after = binascii.hexlify(buf[pos + len(key):end])
+ logger.debug("Memory context %d-%d: %s|%s|%s" % (start, end, before, binascii.hexlify(key), after))
count += 1
pos += len(key)
return count
pmk = binascii.unhexlify(psk)
p = hostapd.wpa2_params(ssid=ssid)
p['wpa_psk'] = psk
- hapd = hostapd.add_ap(apdev[0]['ifname'], p)
+ hapd = hostapd.add_ap(apdev[0], p)
pid = find_wpas_process(dev[0])
get_key_locations(buf, pmk, "PMK")
dev[0].connect_network(id, timeout=20)
+ # The decrypted copy of GTK is freed only after the CTRL-EVENT-CONNECTED
+ # event has been delivered, so verify that wpa_supplicant has returned to
+ # eloop before reading process memory.
time.sleep(1)
+ dev[0].ping()
buf = read_process_memory(pid, pmk)
if tk in buf:
raise Exception("TK found from memory")
if gtk in buf:
+ get_key_locations(buf, gtk, "GTK")
raise Exception("GTK found from memory")
logger.info("Checking keys in memory after disassociation")
verify_not_present(buf, tk, fname, "TK")
verify_not_present(buf, gtk, fname, "GTK")
+@remote_compatible
def test_ap_wpa2_psk_wep(dev, apdev):
"""WPA2-PSK AP and WEP enabled"""
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
try:
hapd.set('wep_key0', '"hello"')
raise Exception("WEP key accepted to WPA2 network")
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
br_ifname='sta-br0'
ifname='wlan5'
subprocess.call(['iw', ifname, 'set', '4addr', 'on'])
subprocess.check_call(['brctl', 'addif', br_ifname, ifname])
wpas.interface_add(ifname, br_ifname=br_ifname)
+ wpas.dump_monitor()
wpas.connect(ssid, psk=passphrase, scan_freq="2412")
+ wpas.dump_monitor()
+@remote_compatible
def test_ap_wpa2_psk_ifdown(dev, apdev):
"""AP with open mode and external ifconfig down"""
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
- subprocess.call(['ip', 'link', 'set', 'dev', apdev[0]['ifname'], 'down'])
+ hapd.cmd_execute(['ip', 'link', 'set', 'dev', apdev[0]['ifname'], 'down'])
ev = hapd.wait_event(["INTERFACE-DISABLED"], timeout=10)
if ev is None:
raise Exception("No INTERFACE-DISABLED event")
# this wait tests beacon loss detection in mac80211
dev[0].wait_disconnected()
- subprocess.call(['ip', 'link', 'set', 'dev', apdev[0]['ifname'], 'up'])
+ hapd.cmd_execute(['ip', 'link', 'set', 'dev', apdev[0]['ifname'], 'up'])
ev = hapd.wait_event(["INTERFACE-ENABLED"], timeout=10)
if ev is None:
raise Exception("No INTERFACE-ENABLED event")
psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6'
params = hostapd.wpa2_params(ssid=ssid)
params['wpa_psk'] = psk
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
hapd.request("SET ext_eapol_frame_io 1")
dev[0].request("SET ext_eapol_frame_io 1")
dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False)
# case, this exception can be uncommented here.
#raise Exception("Unexpected disconnection")
+@remote_compatible
def test_ap_wpa2_psk_disable_enable(dev, apdev):
"""WPA2-PSK AP getting disabled and re-enabled"""
ssid = "test-wpa2-psk"
psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6'
params = hostapd.wpa2_params(ssid=ssid)
params['wpa_psk'] = psk
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, raw_psk=psk, scan_freq="2412")
for i in range(2):
dev[0].wait_connected()
hwsim_utils.test_connectivity(dev[0], hapd)
+@remote_compatible
def test_ap_wpa2_psk_incorrect_passphrase(dev, apdev):
"""WPA2-PSK AP and station using incorrect passphrase"""
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk="incorrect passphrase", scan_freq="2412",
wait_connect=False)
ev = hapd.wait_event(["AP-STA-POSSIBLE-PSK-MISMATCH"], timeout=10)
dev[0].wait_connected(timeout=20)
+@remote_compatible
def test_ap_wpa_ie_parsing(dev, apdev):
"""WPA IE parsing"""
skip_with_fips(dev[0])
ssid = "test-wpa-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa_params(ssid=ssid, passphrase=passphrase)
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
id = dev[0].connect(ssid, psk=passphrase, scan_freq="2412",
only_add_network=True)
if ev is None:
raise Exception("Association rejection not reported")
dev[0].request("DISCONNECT")
+ dev[0].dump_monitor()
finally:
dev[0].request("VENDOR_ELEM_REMOVE 13 *")
dev[0].select_network(id)
dev[0].wait_connected()
dev[0].request("DISCONNECT")
+ dev[0].dump_monitor()
finally:
dev[0].request("VENDOR_ELEM_REMOVE 13 *")
+@remote_compatible
def test_ap_wpa2_psk_no_random(dev, apdev):
"""WPA2-PSK AP and no random numbers available"""
ssid = "test-wpa2-psk"
psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6'
params = hostapd.wpa2_params(ssid=ssid)
params['wpa_psk'] = psk
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
with fail_test(hapd, 1, "wpa_gmk_to_gtk"):
id = dev[0].connect(ssid, raw_psk=psk, scan_freq="2412",
wait_connect=False)
dev[0].select_network(id, freq=2412)
dev[0].wait_connected()
+@remote_compatible
def test_rsn_ie_proto_psk_sta(dev, apdev):
"""RSN element protocol testing for PSK cases on STA side"""
bssid = apdev[0]['bssid']
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
# This is the RSN element used normally by hostapd
params['own_ie_override'] = '30140100000fac040100000fac040100000fac020c00'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
if "FAIL" not in hapd.request("SET own_ie_override qwerty"):
raise Exception("Invalid own_ie_override value accepted")
id = dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
dev[0].select_network(id, freq=2412)
dev[0].wait_connected()
+@remote_compatible
def test_ap_cli_order(dev, apdev):
ssid = "test-rsn-setup"
passphrase = 'zzzzzzzz'
- ifname = apdev[0]['ifname']
- hapd_global = hostapd.HostapdGlobal()
- hapd_global.remove(ifname)
- hapd_global.add(ifname)
-
- hapd = hostapd.Hostapd(ifname)
- hapd.set_defaults()
+ hapd = hostapd.add_ap(apdev[0], {}, no_enable=True)
hapd.set('ssid', ssid)
hapd.set('wpa_passphrase', passphrase)
hapd.set('rsn_pairwise', 'CCMP')
raise Exception("AP startup failed")
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
+
+def set_test_assoc_ie(dev, ie):
+ if "OK" not in dev.request("TEST_ASSOC_IE " + ie):
+ raise Exception("Could not set TEST_ASSOC_IE")
+
+@remote_compatible
+def test_ap_wpa2_psk_assoc_rsn(dev, apdev):
+ """WPA2-PSK AP and association request RSN IE differences"""
+ ssid = "test-wpa2-psk"
+ passphrase = 'qwertyuiop'
+ params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ tests = [ ("Normal wpa_supplicant assoc req RSN IE",
+ "30140100000fac040100000fac040100000fac020000"),
+ ("RSN IE without RSN Capabilities",
+ "30120100000fac040100000fac040100000fac02") ]
+ for title, ie in tests:
+ logger.info(title)
+ set_test_assoc_ie(dev[0], ie)
+ dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ ("WPA IE instead of RSN IE and only RSN enabled on AP",
+ "dd160050f20101000050f20201000050f20201000050f202", 40),
+ ("Empty RSN IE", "3000", 40),
+ ("RSN IE with truncated Version", "300101", 40),
+ ("RSN IE with only Version", "30020100", 43) ]
+ for title, ie, status in tests:
+ logger.info(title)
+ set_test_assoc_ie(dev[0], ie)
+ dev[0].connect(ssid, psk=passphrase, scan_freq="2412",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
+ if ev is None:
+ raise Exception("Association rejection not reported")
+ if "status_code=" + str(status) not in ev:
+ raise Exception("Unexpected status code: " + ev)
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
+
+def test_ap_wpa_psk_rsn_pairwise(dev, apdev):
+ """WPA-PSK AP and only rsn_pairwise set"""
+ params = { "ssid": "wpapsk", "wpa": "1", "wpa_key_mgmt": "WPA-PSK",
+ "rsn_pairwise": "TKIP", "wpa_passphrase": "1234567890" }
+ hapd = hostapd.add_ap(apdev[0], params)
+ dev[0].connect("wpapsk", psk="1234567890", proto="WPA", pairwise="TKIP",
+ scan_freq="2412")
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import time
-import subprocess
import logging
logger = logging.getLogger()
wt = Wlantest()
wt.clear_sta_counters(bssid, sta)
hwsim_utils.test_connectivity(dev, hapd, dscp=dscp, config=False)
- time.sleep(0.02)
+ sleep_time = 0.02 if dev.hostname is None else 0.2
+ time.sleep(sleep_time)
tx = wt.get_tx_tid(bssid, sta, tid)
if tx == 0:
[ tx, rx ] = wt.get_tid_counters(bssid, sta)
logger.info("Expected RX DSCP " + str(dscp) + " with TID " + str(ap_tid) + " but counters: " + str(rx))
raise Exception("No AP->STA data frame using the expected TID")
+@remote_compatible
def test_ap_qosmap(dev, apdev):
"""QoS mapping"""
drv_flags = dev[0].get_driver_status_field("capa.flags")
ssid = "test-qosmap"
params = { "ssid": ssid }
params['qos_map_set'] = '53,2,22,6,8,15,0,7,255,255,16,31,32,39,255,255,40,47,48,55'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412")
time.sleep(0.1)
addr = dev[0].p2p_interface_addr()
dev[0].request("DATA_TEST_CONFIG 1")
hapd.request("DATA_TEST_CONFIG 1")
+ Wlantest.setup(hapd)
check_qos_map(apdev[0], hapd, dev[0], addr, 53, 2)
check_qos_map(apdev[0], hapd, dev[0], addr, 22, 6)
check_qos_map(apdev[0], hapd, dev[0], addr, 8, 0)
dev[0].request("DATA_TEST_CONFIG 0")
hapd.request("DATA_TEST_CONFIG 0")
+@remote_compatible
def test_ap_qosmap_default(dev, apdev):
"""QoS mapping with default values"""
ssid = "test-qosmap-default"
params = { "ssid": ssid }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412")
addr = dev[0].p2p_interface_addr()
dev[0].request("DATA_TEST_CONFIG 1")
hapd.request("DATA_TEST_CONFIG 1")
+ Wlantest.setup(hapd)
for dscp in [ 0, 7, 8, 15, 16, 23, 24, 31, 32, 39, 40, 47, 48, 55, 56, 63]:
check_qos_map(apdev[0], hapd, dev[0], addr, dscp, dscp >> 3)
dev[0].request("DATA_TEST_CONFIG 0")
hapd.request("DATA_TEST_CONFIG 0")
+@remote_compatible
def test_ap_qosmap_default_acm(dev, apdev):
"""QoS mapping with default values and ACM=1 for VO/VI"""
ssid = "test-qosmap-default"
"wmm_ac_vo_cwmax": "2",
"wmm_ac_vo_txop_limit": "47",
"wmm_ac_vo_acm": "1" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412")
addr = dev[0].p2p_interface_addr()
dev[0].request("DATA_TEST_CONFIG 1")
hapd.request("DATA_TEST_CONFIG 1")
+ Wlantest.setup(hapd)
for dscp in [ 0, 7, 8, 15, 16, 23, 24, 31, 32, 39, 40, 47, 48, 55, 56, 63]:
ap_tid = dscp >> 3
tid = ap_tid
dev[0].request("DATA_TEST_CONFIG 0")
hapd.request("DATA_TEST_CONFIG 0")
+@remote_compatible
def test_ap_qosmap_invalid(dev, apdev):
"""QoS mapping ctrl_iface error handling"""
ssid = "test-qosmap"
params = { "ssid": ssid }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
if "FAIL" not in hapd.request("SEND_QOS_MAP_CONF 00:11:22:33:44:55"):
raise Exception("Unexpected SEND_QOS_MAP_CONF success")
if "FAIL" not in hapd.request("SET_QOS_MAP_SET "):
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import time
-import subprocess
import logging
logger = logging.getLogger()
import hwsim_utils
import hostapd
+from wpasupplicant import WpaSupplicant
+@remote_compatible
def test_ap_roam_open(dev, apdev):
"""Roam between two open APs"""
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-open" })
+ hapd0 = hostapd.add_ap(apdev[0], { "ssid": "test-open" })
dev[0].connect("test-open", key_mgmt="NONE")
hwsim_utils.test_connectivity(dev[0], hapd0)
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], { "ssid": "test-open" })
+ hapd1 = hostapd.add_ap(apdev[1], { "ssid": "test-open" })
dev[0].scan(type="ONLY")
dev[0].roam(apdev[1]['bssid'])
hwsim_utils.test_connectivity(dev[0], hapd1)
dev[0].roam(apdev[0]['bssid'])
hwsim_utils.test_connectivity(dev[0], hapd0)
+@remote_compatible
+def test_ap_roam_open_failed(dev, apdev):
+ """Roam failure due to rejected authentication"""
+ hapd0 = hostapd.add_ap(apdev[0], { "ssid": "test-open" })
+ dev[0].connect("test-open", key_mgmt="NONE", scan_freq="2412")
+ hwsim_utils.test_connectivity(dev[0], hapd0)
+ params = { "ssid": "test-open", "max_num_sta" : "0" }
+ hapd1 = hostapd.add_ap(apdev[1], params)
+ bssid = hapd1.own_addr()
+
+ dev[0].scan_for_bss(bssid, freq=2412)
+ dev[0].dump_monitor()
+ if "OK" not in dev[0].request("ROAM " + bssid):
+ raise Exception("ROAM failed")
+
+ ev = dev[0].wait_event(["CTRL-EVENT-AUTH-REJECT"], 1)
+ if not ev:
+ raise Exception("CTRL-EVENT-AUTH-REJECT was not seen")
+
+ dev[0].wait_connected(timeout=5)
+ hwsim_utils.test_connectivity(dev[0], hapd0)
+
+@remote_compatible
def test_ap_roam_wpa2_psk(dev, apdev):
"""Roam between two WPA2-PSK APs"""
params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678")
- hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd0 = hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-psk", psk="12345678")
hwsim_utils.test_connectivity(dev[0], hapd0)
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd1 = hostapd.add_ap(apdev[1], params)
dev[0].scan(type="ONLY")
dev[0].roam(apdev[1]['bssid'])
hwsim_utils.test_connectivity(dev[0], hapd1)
dev[0].roam(apdev[0]['bssid'])
hwsim_utils.test_connectivity(dev[0], hapd0)
+def get_blacklist(dev):
+ return dev.request("BLACKLIST").splitlines()
+
+def test_ap_reconnect_auth_timeout(dev, apdev, params):
+ """Reconnect to 2nd AP and authentication times out"""
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add("wlan5",
+ drv_params="force_connect_cmd=1,force_bss_selection=1")
+
+ params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678")
+ hapd0 = hostapd.add_ap(apdev[0], params)
+ bssid0 = hapd0.own_addr()
+ hapd1 = hostapd.add_ap(apdev[1], params)
+ bssid1 = hapd1.own_addr()
+
+ wpas.scan_for_bss(bssid0, freq=2412)
+ id = wpas.connect("test-wpa2-psk", psk="12345678", scan_freq="2412")
+ hwsim_utils.test_connectivity(wpas, hapd0)
+
+ wpas.request("BLACKLIST " + bssid0)
+
+ wpas.scan_for_bss(bssid1, freq=2412)
+ wpas.request("DISCONNECT")
+ if "OK" not in wpas.request("SET ignore_auth_resp 1"):
+ raise Exception("SET ignore_auth_resp failed")
+ if "OK" not in wpas.request("ENABLE_NETWORK " + str(id)):
+ raise Exception("ENABLE_NETWORK failed")
+ if "OK" not in wpas.request("SELECT_NETWORK " + str(id)):
+ raise Exception("SELECT_NETWORK failed")
+
+ logger.info("Wait ~10s for auth timeout...")
+ time.sleep(10)
+ ev = wpas.wait_event(["CTRL-EVENT-SCAN-STARTED"], 12)
+ if not ev:
+ raise Exception("CTRL-EVENT-SCAN-STARTED not seen");
+
+ b = get_blacklist(wpas)
+ if '00:00:00:00:00:00' in b:
+ raise Exception("Unexpected blacklist contents: " + str(b))
+ if bssid1 not in b:
+ raise Exception("Unexpected blacklist contents: " + str(b))
+
+def test_ap_roam_with_reassoc_auth_timeout(dev, apdev, params):
+ """Roam using reassoc between two APs and authentication times out"""
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add("wlan5",
+ drv_params="force_connect_cmd=1,force_bss_selection=1")
+
+ params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678")
+ hapd0 = hostapd.add_ap(apdev[0], params)
+ bssid0 = hapd0.own_addr()
+
+ id = wpas.connect("test-wpa2-psk", psk="12345678", scan_freq="2412")
+ hwsim_utils.test_connectivity(wpas, hapd0)
+
+ hapd1 = hostapd.add_ap(apdev[1], params)
+ bssid1 = hapd1.own_addr()
+ wpas.scan_for_bss(bssid1, freq=2412)
+
+ if "OK" not in wpas.request("SET_NETWORK " + str(id) + " bssid " + bssid1):
+ raise Exception("SET_NETWORK failed")
+ if "OK" not in wpas.request("SET ignore_auth_resp 1"):
+ raise Exception("SET ignore_auth_resp failed")
+ if "OK" not in wpas.request("REASSOCIATE"):
+ raise Exception("REASSOCIATE failed")
+
+ logger.info("Wait ~10s for auth timeout...")
+ time.sleep(10)
+ ev = wpas.wait_event(["CTRL-EVENT-SCAN-STARTED"], 12)
+ if not ev:
+ raise Exception("CTRL-EVENT-SCAN-STARTED not seen");
+
+ b = get_blacklist(wpas)
+ if bssid0 in b:
+ raise Exception("Unexpected blacklist contents: " + str(b))
+
+def test_ap_roam_wpa2_psk_failed(dev, apdev, params):
+ """Roam failure with WPA2-PSK AP due to wrong passphrase"""
+ params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678")
+ hapd0 = hostapd.add_ap(apdev[0], params)
+ id = dev[0].connect("test-wpa2-psk", psk="12345678", scan_freq="2412")
+ hwsim_utils.test_connectivity(dev[0], hapd0)
+ params['wpa_passphrase'] = "22345678"
+ hapd1 = hostapd.add_ap(apdev[1], params)
+ bssid = hapd1.own_addr()
+ dev[0].scan_for_bss(bssid, freq=2412)
+
+ dev[0].dump_monitor()
+ if "OK" not in dev[0].request("ROAM " + bssid):
+ raise Exception("ROAM failed")
+
+ ev = dev[0].wait_event(["CTRL-EVENT-SSID-TEMP-DISABLED",
+ "CTRL-EVENT-CONNECTED"], 5)
+ if "CTRL-EVENT-CONNECTED" in ev:
+ raise Exception("Got unexpected CTRL-EVENT-CONNECTED")
+ if "CTRL-EVENT-SSID-TEMP-DISABLED" not in ev:
+ raise Exception("CTRL-EVENT-SSID-TEMP-DISABLED not seen")
+
+ if "OK" not in dev[0].request("SELECT_NETWORK id=" + str(id)):
+ raise Exception("SELECT_NETWORK failed")
+
+ ev = dev[0].wait_event(["CTRL-EVENT-SSID-REENABLED"], 3)
+ if not ev:
+ raise Exception("CTRL-EVENT-SSID-REENABLED not seen")
+
+ dev[0].wait_connected(timeout=5)
+ hwsim_utils.test_connectivity(dev[0], hapd0)
+
+@remote_compatible
def test_ap_reassociation_to_same_bss(dev, apdev):
"""Reassociate to the same BSS"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-open" })
dev[0].connect("test-open", key_mgmt="NONE")
dev[0].request("REASSOCIATE")
dev[0].wait_connected(timeout=10, error="Reattach timed out")
hwsim_utils.test_connectivity(dev[0], hapd)
+ # Wait for previous scan results to expire to trigger new scan
+ time.sleep(5)
+ dev[0].request("REATTACH")
+ dev[0].wait_connected(timeout=10, error="Reattach timed out")
+ hwsim_utils.test_connectivity(dev[0], hapd)
+
+@remote_compatible
def test_ap_roam_set_bssid(dev, apdev):
"""Roam control"""
- hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-open" })
- hostapd.add_ap(apdev[1]['ifname'], { "ssid": "test-open" })
+ hostapd.add_ap(apdev[0], { "ssid": "test-open" })
+ hostapd.add_ap(apdev[1], { "ssid": "test-open" })
id = dev[0].connect("test-open", key_mgmt="NONE", bssid=apdev[1]['bssid'],
scan_freq="2412")
if dev[0].get_status_field('bssid') != apdev[1]['bssid']:
dev[0].set_network(id, "bssid", "")
dev[0].set_network(id, "bssid", apdev[0]['bssid'])
dev[0].set_network(id, "bssid", apdev[1]['bssid'])
+
+@remote_compatible
+def test_ap_roam_wpa2_psk_race(dev, apdev):
+ """Roam between two WPA2-PSK APs and try to hit a disconnection race"""
+ params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678")
+ hapd0 = hostapd.add_ap(apdev[0], params)
+ dev[0].connect("test-wpa2-psk", psk="12345678", scan_freq="2412")
+ hwsim_utils.test_connectivity(dev[0], hapd0)
+
+ params['channel'] = '2'
+ hapd1 = hostapd.add_ap(apdev[1], params)
+ dev[0].scan_for_bss(apdev[1]['bssid'], freq=2417)
+ dev[0].roam(apdev[1]['bssid'])
+ hwsim_utils.test_connectivity(dev[0], hapd1)
+ dev[0].roam(apdev[0]['bssid'])
+ hwsim_utils.test_connectivity(dev[0], hapd0)
+ # Wait at least two seconds to trigger the previous issue with the
+ # disconnection callback.
+ for i in range(3):
+ time.sleep(0.8)
+ hwsim_utils.test_connectivity(dev[0], hapd0)
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import time
import logging
logger = logging.getLogger()
import hostapd
from utils import HwsimSkip, skip_with_fips
from wlantest import Wlantest
+from test_ap_vht import vht_supported
-def start_ap_wpa2_psk(ifname):
+def start_ap_wpa2_psk(ap):
params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678")
- return hostapd.add_ap(ifname, params)
+ return hostapd.add_ap(ap, params)
def connectivity(dev, hapd):
hwsim_utils.test_connectivity_sta(dev[0], dev[1])
dev[1].connect("test-open", key_mgmt="NONE", scan_freq=scan_freq)
connectivity(dev, hapd)
-def wlantest_setup():
+def wlantest_setup(hapd):
+ Wlantest.setup(hapd)
wt = Wlantest()
wt.flush()
wt.add_passphrase("12345678")
def tdls_check_ap(sta0, sta1, bssid, addr0, addr1):
wt = Wlantest()
- wt.tdls_clear(bssid, addr0, addr1);
+ wt.tdls_clear(bssid, addr0, addr1)
hwsim_utils.test_connectivity_sta(sta0, sta1)
[dl,inv_dl,ap,inv_ap] = wlantest_tdls_packet_counters(bssid, addr0, addr1)
if dl > 0:
hwsim_utils.test_connectivity(sta0, hapd)
hwsim_utils.test_connectivity(sta1, hapd)
-def setup_tdls(sta0, sta1, ap, reverse=False, expect_fail=False):
+def setup_tdls(sta0, sta1, hapd, reverse=False, expect_fail=False):
logger.info("Setup TDLS")
- hapd = hostapd.Hostapd(ap['ifname'])
check_connectivity(sta0, sta1, hapd)
- bssid = ap['bssid']
+ bssid = hapd.own_addr()
addr0 = sta0.p2p_interface_addr()
addr1 = sta1.p2p_interface_addr()
wt = Wlantest()
- wt.tdls_clear(bssid, addr0, addr1);
- wt.tdls_clear(bssid, addr1, addr0);
+ wt.tdls_clear(bssid, addr0, addr1)
+ wt.tdls_clear(bssid, addr1, addr0)
sta0.tdls_setup(addr1)
time.sleep(1)
if expect_fail:
if reverse:
addr1 = sta0.p2p_interface_addr()
addr0 = sta1.p2p_interface_addr()
- conf = wt.get_tdls_counter("setup_conf_ok", bssid, addr0, addr1);
+ conf = wt.get_tdls_counter("setup_conf_ok", bssid, addr0, addr1)
if conf == 0:
raise Exception("No TDLS Setup Confirm (success) seen")
tdls_check_dl(sta0, sta1, bssid, addr0, addr1)
check_connectivity(sta0, sta1, hapd)
-def teardown_tdls(sta0, sta1, ap, responder=False, wildcard=False):
+def teardown_tdls(sta0, sta1, hapd, responder=False, wildcard=False):
logger.info("Teardown TDLS")
- hapd = hostapd.Hostapd(ap['ifname'])
check_connectivity(sta0, sta1, hapd)
- bssid = ap['bssid']
+ bssid = hapd.own_addr()
addr0 = sta0.p2p_interface_addr()
addr1 = sta1.p2p_interface_addr()
if responder:
sta0.tdls_teardown(addr1)
time.sleep(1)
wt = Wlantest()
- teardown = wt.get_tdls_counter("teardown", bssid, addr0, addr1);
+ teardown = wt.get_tdls_counter("teardown", bssid, addr0, addr1)
if teardown == 0:
raise Exception("No TDLS Setup Teardown seen")
tdls_check_ap(sta0, sta1, bssid, addr0, addr1)
if connected:
raise Exception("Expected TDLS link status to be connected")
+@remote_compatible
def test_ap_tdls_discovery(dev, apdev):
"""WPA2-PSK AP and two stations using TDLS discovery"""
- hapd = start_ap_wpa2_psk(apdev[0]['ifname'])
- wlantest_setup()
+ hapd = start_ap_wpa2_psk(apdev[0])
+ wlantest_setup(hapd)
connect_2sta_wpa2_psk(dev, hapd)
dev[0].request("TDLS_DISCOVER " + dev[1].p2p_interface_addr())
time.sleep(0.2)
def test_ap_wpa2_tdls(dev, apdev):
"""WPA2-PSK AP and two stations using TDLS"""
- hapd = start_ap_wpa2_psk(apdev[0]['ifname'])
- wlantest_setup()
+ hapd = start_ap_wpa2_psk(apdev[0])
+ wlantest_setup(hapd)
connect_2sta_wpa2_psk(dev, hapd)
- setup_tdls(dev[0], dev[1], apdev[0])
- teardown_tdls(dev[0], dev[1], apdev[0])
- setup_tdls(dev[1], dev[0], apdev[0])
- #teardown_tdls(dev[0], dev[1], apdev[0])
+ setup_tdls(dev[0], dev[1], hapd)
+ teardown_tdls(dev[0], dev[1], hapd)
+ setup_tdls(dev[1], dev[0], hapd)
+ #teardown_tdls(dev[0], dev[1], hapd)
def test_ap_wpa2_tdls_concurrent_init(dev, apdev):
"""Concurrent TDLS setup initiation"""
- hapd = start_ap_wpa2_psk(apdev[0]['ifname'])
- wlantest_setup()
+ hapd = start_ap_wpa2_psk(apdev[0])
+ wlantest_setup(hapd)
connect_2sta_wpa2_psk(dev, hapd)
dev[0].request("SET tdls_testing 0x80")
- setup_tdls(dev[1], dev[0], apdev[0], reverse=True)
+ setup_tdls(dev[1], dev[0], hapd, reverse=True)
def test_ap_wpa2_tdls_concurrent_init2(dev, apdev):
"""Concurrent TDLS setup initiation (reverse)"""
- hapd = start_ap_wpa2_psk(apdev[0]['ifname'])
- wlantest_setup()
+ hapd = start_ap_wpa2_psk(apdev[0])
+ wlantest_setup(hapd)
connect_2sta_wpa2_psk(dev, hapd)
dev[1].request("SET tdls_testing 0x80")
- setup_tdls(dev[0], dev[1], apdev[0])
+ setup_tdls(dev[0], dev[1], hapd)
def test_ap_wpa2_tdls_decline_resp(dev, apdev):
"""Decline TDLS Setup Response"""
- hapd = start_ap_wpa2_psk(apdev[0]['ifname'])
- wlantest_setup()
+ hapd = start_ap_wpa2_psk(apdev[0])
+ wlantest_setup(hapd)
connect_2sta_wpa2_psk(dev, hapd)
dev[1].request("SET tdls_testing 0x200")
- setup_tdls(dev[1], dev[0], apdev[0], expect_fail=True)
+ setup_tdls(dev[1], dev[0], hapd, expect_fail=True)
def test_ap_wpa2_tdls_long_lifetime(dev, apdev):
"""TDLS with long TPK lifetime"""
- hapd = start_ap_wpa2_psk(apdev[0]['ifname'])
- wlantest_setup()
+ hapd = start_ap_wpa2_psk(apdev[0])
+ wlantest_setup(hapd)
connect_2sta_wpa2_psk(dev, hapd)
dev[1].request("SET tdls_testing 0x40")
- setup_tdls(dev[1], dev[0], apdev[0])
+ setup_tdls(dev[1], dev[0], hapd)
def test_ap_wpa2_tdls_long_frame(dev, apdev):
"""TDLS with long setup/teardown frames"""
- hapd = start_ap_wpa2_psk(apdev[0]['ifname'])
- wlantest_setup()
+ hapd = start_ap_wpa2_psk(apdev[0])
+ wlantest_setup(hapd)
connect_2sta_wpa2_psk(dev, hapd)
dev[0].request("SET tdls_testing 0x1")
dev[1].request("SET tdls_testing 0x1")
- setup_tdls(dev[1], dev[0], apdev[0])
- teardown_tdls(dev[1], dev[0], apdev[0])
- setup_tdls(dev[0], dev[1], apdev[0])
+ setup_tdls(dev[1], dev[0], hapd)
+ teardown_tdls(dev[1], dev[0], hapd)
+ setup_tdls(dev[0], dev[1], hapd)
def test_ap_wpa2_tdls_reneg(dev, apdev):
"""Renegotiate TDLS link"""
- hapd = start_ap_wpa2_psk(apdev[0]['ifname'])
- wlantest_setup()
+ hapd = start_ap_wpa2_psk(apdev[0])
+ wlantest_setup(hapd)
connect_2sta_wpa2_psk(dev, hapd)
- setup_tdls(dev[1], dev[0], apdev[0])
- setup_tdls(dev[0], dev[1], apdev[0])
+ setup_tdls(dev[1], dev[0], hapd)
+ setup_tdls(dev[0], dev[1], hapd)
def test_ap_wpa2_tdls_wrong_lifetime_resp(dev, apdev):
"""Incorrect TPK lifetime in TDLS Setup Response"""
- hapd = start_ap_wpa2_psk(apdev[0]['ifname'])
- wlantest_setup()
+ hapd = start_ap_wpa2_psk(apdev[0])
+ wlantest_setup(hapd)
connect_2sta_wpa2_psk(dev, hapd)
dev[1].request("SET tdls_testing 0x10")
- setup_tdls(dev[0], dev[1], apdev[0], expect_fail=True)
+ setup_tdls(dev[0], dev[1], hapd, expect_fail=True)
def test_ap_wpa2_tdls_diff_rsnie(dev, apdev):
"""TDLS with different RSN IEs"""
- hapd = start_ap_wpa2_psk(apdev[0]['ifname'])
- wlantest_setup()
+ hapd = start_ap_wpa2_psk(apdev[0])
+ wlantest_setup(hapd)
connect_2sta_wpa2_psk(dev, hapd)
dev[1].request("SET tdls_testing 0x2")
- setup_tdls(dev[1], dev[0], apdev[0])
- teardown_tdls(dev[1], dev[0], apdev[0])
+ setup_tdls(dev[1], dev[0], hapd)
+ teardown_tdls(dev[1], dev[0], hapd)
def test_ap_wpa2_tdls_wrong_tpk_m2_mic(dev, apdev):
"""Incorrect MIC in TDLS Setup Response"""
- hapd = start_ap_wpa2_psk(apdev[0]['ifname'])
- wlantest_setup()
+ hapd = start_ap_wpa2_psk(apdev[0])
+ wlantest_setup(hapd)
connect_2sta_wpa2_psk(dev, hapd)
dev[0].request("SET tdls_testing 0x800")
addr0 = dev[0].p2p_interface_addr()
def test_ap_wpa2_tdls_wrong_tpk_m3_mic(dev, apdev):
"""Incorrect MIC in TDLS Setup Confirm"""
- hapd = start_ap_wpa2_psk(apdev[0]['ifname'])
- wlantest_setup()
+ hapd = start_ap_wpa2_psk(apdev[0])
+ wlantest_setup(hapd)
connect_2sta_wpa2_psk(dev, hapd)
dev[1].request("SET tdls_testing 0x800")
addr0 = dev[0].p2p_interface_addr()
def test_ap_wpa_tdls(dev, apdev):
"""WPA-PSK AP and two stations using TDLS"""
skip_with_fips(dev[0])
- hapd = hostapd.add_ap(apdev[0]['ifname'],
+ hapd = hostapd.add_ap(apdev[0],
hostapd.wpa_params(ssid="test-wpa-psk",
passphrase="12345678"))
- wlantest_setup()
+ wlantest_setup(hapd)
connect_2sta_wpa_psk(dev, hapd)
- setup_tdls(dev[0], dev[1], apdev[0])
- teardown_tdls(dev[0], dev[1], apdev[0])
- setup_tdls(dev[1], dev[0], apdev[0])
+ setup_tdls(dev[0], dev[1], hapd)
+ teardown_tdls(dev[0], dev[1], hapd)
+ setup_tdls(dev[1], dev[0], hapd)
def test_ap_wpa_mixed_tdls(dev, apdev):
"""WPA+WPA2-PSK AP and two stations using TDLS"""
skip_with_fips(dev[0])
- hapd = hostapd.add_ap(apdev[0]['ifname'],
+ hapd = hostapd.add_ap(apdev[0],
hostapd.wpa_mixed_params(ssid="test-wpa-mixed-psk",
passphrase="12345678"))
- wlantest_setup()
+ wlantest_setup(hapd)
connect_2sta_wpa_psk_mixed(dev, hapd)
- setup_tdls(dev[0], dev[1], apdev[0])
- teardown_tdls(dev[0], dev[1], apdev[0])
- setup_tdls(dev[1], dev[0], apdev[0])
+ setup_tdls(dev[0], dev[1], hapd)
+ teardown_tdls(dev[0], dev[1], hapd)
+ setup_tdls(dev[1], dev[0], hapd)
def test_ap_wep_tdls(dev, apdev):
"""WEP AP and two stations using TDLS"""
- hapd = hostapd.add_ap(apdev[0]['ifname'],
+ hapd = hostapd.add_ap(apdev[0],
{ "ssid": "test-wep", "wep_key0": '"hello"' })
- wlantest_setup()
+ wlantest_setup(hapd)
connect_2sta_wep(dev, hapd)
- setup_tdls(dev[0], dev[1], apdev[0])
- teardown_tdls(dev[0], dev[1], apdev[0])
- setup_tdls(dev[1], dev[0], apdev[0])
+ setup_tdls(dev[0], dev[1], hapd)
+ teardown_tdls(dev[0], dev[1], hapd)
+ setup_tdls(dev[1], dev[0], hapd)
def test_ap_open_tdls(dev, apdev):
"""Open AP and two stations using TDLS"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-open" })
- wlantest_setup()
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-open" })
+ wlantest_setup(hapd)
connect_2sta_open(dev, hapd)
- setup_tdls(dev[0], dev[1], apdev[0])
- teardown_tdls(dev[0], dev[1], apdev[0])
- setup_tdls(dev[1], dev[0], apdev[0])
- teardown_tdls(dev[1], dev[0], apdev[0], wildcard=True)
+ setup_tdls(dev[0], dev[1], hapd)
+ teardown_tdls(dev[0], dev[1], hapd)
+ setup_tdls(dev[1], dev[0], hapd)
+ teardown_tdls(dev[1], dev[0], hapd, wildcard=True)
def test_ap_wpa2_tdls_bssid_mismatch(dev, apdev):
"""TDLS failure due to BSSID mismatch"""
passphrase = "12345678"
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['bridge'] = 'ap-br0'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- hostapd.add_ap(apdev[1]['ifname'], params)
- wlantest_setup()
+ hapd = hostapd.add_ap(apdev[0], params)
+ hostapd.add_ap(apdev[1], params)
+ wlantest_setup(hapd)
subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
dev[0].connect(ssid, psk=passphrase, scan_freq="2412",
def test_ap_wpa2_tdls_responder_teardown(dev, apdev):
"""TDLS teardown from responder with WPA2-PSK AP"""
- hapd = start_ap_wpa2_psk(apdev[0]['ifname'])
- wlantest_setup()
+ hapd = start_ap_wpa2_psk(apdev[0])
+ wlantest_setup(hapd)
connect_2sta_wpa2_psk(dev, hapd)
- setup_tdls(dev[0], dev[1], apdev[0])
- teardown_tdls(dev[0], dev[1], apdev[0], responder=True)
+ setup_tdls(dev[0], dev[1], hapd)
+ teardown_tdls(dev[0], dev[1], hapd, responder=True)
def test_ap_open_tdls_vht(dev, apdev):
"""Open AP and two stations using TDLS"""
"vht_capab": "",
"vht_oper_chwidth": "0",
"vht_oper_centr_freq_seg0_idx": "0" }
+ hapd = None
+ try:
+ hapd = hostapd.add_ap(apdev[0], params)
+ wlantest_setup(hapd)
+ connect_2sta_open(dev, hapd, scan_freq="5180")
+ setup_tdls(dev[0], dev[1], hapd)
+ teardown_tdls(dev[0], dev[1], hapd)
+ setup_tdls(dev[1], dev[0], hapd)
+ teardown_tdls(dev[1], dev[0], hapd, wildcard=True)
+ finally:
+ dev[0].request("DISCONNECT")
+ dev[1].request("DISCONNECT")
+ if hapd:
+ hapd.request("DISABLE")
+ subprocess.call(['iw', 'reg', 'set', '00'])
+ dev[0].flush_scan_cache()
+ dev[1].flush_scan_cache()
+
+def test_ap_open_tdls_vht80(dev, apdev):
+ """Open AP and two stations using TDLS with VHT 80"""
+ params = { "ssid": "test-open",
+ "country_code": "US",
+ "hw_mode": "a",
+ "channel": "36",
+ "ht_capab": "[HT40+]",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "vht_capab": "",
+ "vht_oper_chwidth": "1",
+ "vht_oper_centr_freq_seg0_idx": "42" }
+ try:
+ hapd = None
+ hapd = hostapd.add_ap(apdev[0], params)
+ wlantest_setup(hapd)
+ connect_2sta_open(dev, hapd, scan_freq="5180")
+ sig = dev[0].request("SIGNAL_POLL").splitlines()
+ if "WIDTH=80 MHz" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
+ setup_tdls(dev[0], dev[1], hapd)
+ for i in range(10):
+ check_connectivity(dev[0], dev[1], hapd)
+ for i in range(2):
+ cmd = subprocess.Popen(['iw', dev[0].ifname, 'station', 'dump'],
+ stdout=subprocess.PIPE)
+ res = cmd.stdout.read()
+ cmd.stdout.close()
+ logger.info("Station dump on dev[%d]:\n%s" % (i, res))
+ except Exception, e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not vht_supported():
+ raise HwsimSkip("80/160 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ dev[0].request("DISCONNECT")
+ dev[1].request("DISCONNECT")
+ if hapd:
+ hapd.request("DISABLE")
+ subprocess.call(['iw', 'reg', 'set', '00'])
+ dev[0].flush_scan_cache()
+ dev[1].flush_scan_cache()
+
+def test_ap_open_tdls_vht80plus80(dev, apdev):
+ """Open AP and two stations using TDLS with VHT 80+80"""
+ params = { "ssid": "test-open",
+ "country_code": "US",
+ "hw_mode": "a",
+ "channel": "36",
+ "ht_capab": "[HT40+]",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "vht_capab": "",
+ "vht_oper_chwidth": "3",
+ "vht_oper_centr_freq_seg0_idx": "42",
+ "vht_oper_centr_freq_seg1_idx": "155" }
try:
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- wlantest_setup()
+ hapd = None
+ hapd = hostapd.add_ap(apdev[0], params)
+ wlantest_setup(hapd)
connect_2sta_open(dev, hapd, scan_freq="5180")
- setup_tdls(dev[0], dev[1], apdev[0])
- teardown_tdls(dev[0], dev[1], apdev[0])
- setup_tdls(dev[1], dev[0], apdev[0])
- teardown_tdls(dev[1], dev[0], apdev[0], wildcard=True)
+ sig = dev[0].request("SIGNAL_POLL").splitlines()
+ if "FREQUENCY=5180" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig))
+ if "WIDTH=80+80 MHz" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
+ if "CENTER_FRQ1=5210" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(3): " + str(sig))
+ if "CENTER_FRQ2=5775" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(4): " + str(sig))
+ setup_tdls(dev[0], dev[1], hapd)
+ for i in range(10):
+ check_connectivity(dev[0], dev[1], hapd)
+ for i in range(2):
+ cmd = subprocess.Popen(['iw', dev[0].ifname, 'station', 'dump'],
+ stdout=subprocess.PIPE)
+ res = cmd.stdout.read()
+ cmd.stdout.close()
+ logger.info("Station dump on dev[%d]:\n%s" % (i, res))
+ except Exception, e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not vht_supported():
+ raise HwsimSkip("80/160 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ dev[0].request("DISCONNECT")
+ dev[1].request("DISCONNECT")
+ if hapd:
+ hapd.request("DISABLE")
+ subprocess.call(['iw', 'reg', 'set', '00'])
+ dev[0].flush_scan_cache()
+ dev[1].flush_scan_cache()
+
+def test_ap_open_tdls_vht160(dev, apdev):
+ """Open AP and two stations using TDLS with VHT 160"""
+ params = { "ssid": "test-open",
+ "country_code": "ZA",
+ "hw_mode": "a",
+ "channel": "104",
+ "ht_capab": "[HT40-]",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "vht_oper_chwidth": "2",
+ "vht_oper_centr_freq_seg0_idx": "114" }
+ try:
+ hapd = None
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
+ ev = hapd.wait_event(["AP-ENABLED"], timeout=2)
+ if not ev:
+ cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE)
+ reg = cmd.stdout.readlines()
+ for r in reg:
+ if "5490" in r and "DFS" in r:
+ raise HwsimSkip("ZA regulatory rule did not have DFS requirement removed")
+ raise Exception("AP setup timed out")
+ wlantest_setup(hapd)
+ connect_2sta_open(dev, hapd, scan_freq="5520")
+ sig = dev[0].request("SIGNAL_POLL").splitlines()
+ if "WIDTH=160 MHz" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
+ setup_tdls(dev[0], dev[1], hapd)
+ for i in range(10):
+ check_connectivity(dev[0], dev[1], hapd)
+ for i in range(2):
+ cmd = subprocess.Popen(['iw', dev[0].ifname, 'station', 'dump'],
+ stdout=subprocess.PIPE)
+ res = cmd.stdout.read()
+ cmd.stdout.close()
+ logger.info("Station dump on dev[%d]:\n%s" % (i, res))
+ except Exception, e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not vht_supported():
+ raise HwsimSkip("80/160 MHz channel not supported in regulatory information")
+ raise
finally:
dev[0].request("DISCONNECT")
dev[1].request("DISCONNECT")
if flags & 0x800000000 == 0:
raise HwsimSkip("Driver does not support TDLS channel switching")
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-open" })
+ wlantest_setup(hapd)
connect_2sta_open(dev, hapd)
- setup_tdls(dev[0], dev[1], apdev[0])
+ setup_tdls(dev[0], dev[1], hapd)
if "OK" not in dev[0].request("TDLS_CHAN_SWITCH " + dev[1].own_addr() + " 81 2462"):
raise Exception("Failed to enable TDLS channel switching")
if "OK" not in dev[0].request("TDLS_CANCEL_CHAN_SWITCH " + dev[1].own_addr()):
def test_ap_tdls_link_status(dev, apdev):
"""Check TDLS link status between two stations"""
- hapd = start_ap_wpa2_psk(apdev[0]['ifname'])
- wlantest_setup()
+ hapd = start_ap_wpa2_psk(apdev[0])
+ wlantest_setup(hapd)
connect_2sta_wpa2_psk(dev, hapd)
check_tdls_link(dev[0], dev[1], connected=False)
- setup_tdls(dev[0], dev[1], apdev[0])
+ setup_tdls(dev[0], dev[1], hapd)
check_tdls_link(dev[0], dev[1], connected=True)
- teardown_tdls(dev[0], dev[1], apdev[0])
+ teardown_tdls(dev[0], dev[1], hapd)
check_tdls_link(dev[0], dev[1], connected=False)
if "FAIL" not in dev[0].request("TDLS_LINK_STATUS foo"):
raise Exception("Unexpected TDLS_LINK_STATUS response for invalid argument")
"hw_mode": "g",
"channel": "6",
"track_sta_max_num": "2" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
params = { "ssid": "track",
"channel": "40",
"track_sta_max_num": "100",
"track_sta_max_age": "1" }
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
bssid2 = apdev[1]['bssid']
for i in range(2):
"channel": "6",
"beacon_int": "10000",
"no_probe_resp_if_seen_on": apdev[1]['ifname'] }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
params = { "ssid": "track",
"hw_mode": "a",
"channel": "40",
"track_sta_max_num": "100" }
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
bssid2 = apdev[1]['bssid']
dev[0].scan_for_bss(bssid2, freq=5200, force_scan=True)
"channel": "6",
"track_sta_max_num": "100",
"no_auth_if_seen_on": apdev[1]['ifname'] }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
params = { "ssid": "track",
"hw_mode": "a",
"channel": "40",
"track_sta_max_num": "100" }
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
bssid2 = apdev[1]['bssid']
dev[0].scan_for_bss(bssid, freq=2437, force_scan=True)
"hw_mode": "g",
"channel": "6",
"no_auth_if_seen_on": apdev[1]['ifname'] }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
params = { "ssid": "track",
"interworking": "1",
"venue_name": "eng:Venue",
"track_sta_max_num": "100" }
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
bssid2 = apdev[1]['bssid']
dev[0].scan_for_bss(bssid, freq=2437, force_scan=True)
"channel": "6",
"no_probe_resp_if_seen_on": apdev[1]['ifname'],
"no_auth_if_seen_on": apdev[1]['ifname'] }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
params = { "ssid": "track",
"hw_mode": "a",
"channel": "40",
"track_sta_max_num": "100" }
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
bssid2 = apdev[1]['bssid']
dev[0].scan_for_bss(bssid, freq=2437, force_scan=True)
"hw_mode": "g",
"channel": "6",
"track_sta_max_num": "100" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
params = { "ssid": "track",
"channel": "40",
"no_probe_resp_if_seen_on": apdev[0]['ifname'],
"no_auth_if_seen_on": apdev[0]['ifname'] }
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
bssid2 = apdev[1]['bssid']
dev[0].scan_for_bss(bssid2, freq=5200, force_scan=True)
if freq != '2437':
raise Exception("Unexpected operating channel")
dev[0].request("DISCONNECT")
+
+def test_ap_track_taxonomy(dev, apdev):
+ """AP tracking STA taxonomy"""
+ try:
+ _test_ap_track_taxonomy(dev, apdev)
+ finally:
+ dev[1].request("SET p2p_disabled 0")
+ subprocess.call(['iw', 'reg', 'set', '00'])
+ dev[0].flush_scan_cache()
+ dev[1].flush_scan_cache()
+ dev[2].flush_scan_cache()
+
+def _test_ap_track_taxonomy(dev, apdev):
+ params = { "ssid": "track",
+ "country_code": "US",
+ "hw_mode": "g",
+ "channel": "6",
+ "track_sta_max_num": "2" }
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+
+ dev[0].scan_for_bss(bssid, freq=2437, force_scan=True)
+ addr0 = dev[0].own_addr()
+ dev[0].connect("track", key_mgmt="NONE", scan_freq="2437")
+
+ dev[1].request("SET p2p_disabled 1")
+ dev[1].scan_for_bss(bssid, freq=2437, force_scan=True)
+ addr1 = dev[1].own_addr()
+ dev[1].connect("track", key_mgmt="NONE", scan_freq="2437")
+
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add("wlan5")
+ wpas.request("SET model_name track test")
+ wpas.scan_for_bss(bssid, freq=2437, force_scan=True)
+ addr = wpas.own_addr()
+ wpas.connect("track", key_mgmt="NONE", scan_freq="2437")
+
+ if "FAIL" not in hapd.request("SIGNATURE abc"):
+ raise Exception("SIGNATURE failure not reported (1)")
+ if "FAIL" not in hapd.request("SIGNATURE 22:33:44:55:66:77"):
+ raise Exception("SIGNATURE failure not reported (2)")
+
+ res = hapd.request("SIGNATURE " + addr0)
+ logger.info("sta0: " + res)
+ if not res.startswith("wifi4|probe:"):
+ raise Exception("Unexpected SIGNATURE prefix")
+ if "|assoc:" not in res:
+ raise Exception("Missing assoc info in SIGNATURE")
+ if "wps:track_test" in res:
+ raise Exception("Unexpected WPS model name")
+
+ res = hapd.request("SIGNATURE " + addr1)
+ logger.info("sta1: " + res)
+ if not res.startswith("wifi4|probe:"):
+ raise Exception("Unexpected SIGNATURE prefix")
+ if "|assoc:" not in res:
+ raise Exception("Missing assoc info in SIGNATURE")
+ if "wps:" in res:
+ raise Exception("Unexpected WPS info");
+ if ",221(0050f2,4)," in res:
+ raise Exception("Unexpected WPS IE info");
+ if ",221(506f9a,9)," in res:
+ raise Exception("Unexpected P2P IE info");
+
+ res = hapd.request("SIGNATURE " + addr)
+ logger.info("sta: " + res)
+ if not res.startswith("wifi4|probe:"):
+ raise Exception("Unexpected SIGNATURE prefix")
+ if "|assoc:" not in res:
+ raise Exception("Missing assoc info in SIGNATURE")
+ if "wps:track_test" not in res:
+ raise Exception("Missing WPS model name")
+ if ",221(0050f2,4)," not in res:
+ raise Exception("Missing WPS IE info");
+ if ",221(506f9a,9)," not in res:
+ raise Exception("Missing P2P IE info");
+
+ addr2 = dev[2].own_addr()
+ res = hapd.request("SIGNATURE " + addr2)
+ if "FAIL" not in res:
+ raise Exception("Unexpected SIGNATURE success for sta2 (1)")
+
+ for i in range(10):
+ dev[2].request("SCAN freq=2437 passive=1")
+ ev = dev[2].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
+ if ev is None:
+ raise Exception("Scan did not complete")
+ if dev[2].get_bss(bssid):
+ break
+
+ res = hapd.request("SIGNATURE " + addr2)
+ if "FAIL" not in res:
+ raise Exception("Unexpected SIGNATURE success for sta2 (2)")
+
+ dev[2].connect("track", key_mgmt="NONE", scan_freq="2437")
+
+ res = hapd.request("SIGNATURE " + addr2)
+ if "FAIL" not in res and len(res) > 0:
+ raise Exception("Unexpected SIGNATURE success for sta2 (3)")
+
+ dev[2].scan_for_bss(bssid, freq=2437, force_scan=True)
+
+ res = hapd.request("SIGNATURE " + addr2)
+ logger.info("sta2: " + res)
+ if not res.startswith("wifi4|probe:"):
+ raise Exception("Unexpected SIGNATURE prefix")
+ if "|assoc:" not in res:
+ raise Exception("Missing assoc info in SIGNATURE")
from utils import HwsimSkip
from test_dfs import wait_dfs_event
from test_ap_csa import csa_supported
+from test_ap_ht import clear_scan_cache
def vht_supported():
cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE)
"ieee80211ac": "1",
"vht_oper_chwidth": "1",
"vht_oper_centr_freq_seg0_idx": "42" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
dev[0].connect("vht", key_mgmt="NONE", scan_freq="5180")
hwsim_utils.test_connectivity(dev[0], hapd)
+ sig = dev[0].request("SIGNAL_POLL").splitlines()
+ if "FREQUENCY=5180" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig))
+ if "WIDTH=80 MHz" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
est = dev[0].get_bss(bssid)['est_throughput']
if est != "390001":
raise Exception("Unexpected BSS est_throughput: " + est)
+ status = hapd.get_status()
+ logger.info("hostapd STATUS: " + str(status))
+ if status["ieee80211n"] != "1":
+ raise Exception("Unexpected STATUS ieee80211n value")
+ if status["ieee80211ac"] != "1":
+ raise Exception("Unexpected STATUS ieee80211ac value")
+ if status["secondary_channel"] != "1":
+ raise Exception("Unexpected STATUS secondary_channel value")
+ if status["vht_oper_chwidth"] != "1":
+ raise Exception("Unexpected STATUS vht_oper_chwidth value")
+ if status["vht_oper_centr_freq_seg0_idx"] != "42":
+ raise Exception("Unexpected STATUS vht_oper_centr_freq_seg0_idx value")
except Exception, e:
if isinstance(e, Exception) and str(e) == "AP startup failed":
if not vht_supported():
dev[0].flush_scan_cache()
def vht80_test(apdev, dev, channel, ht_capab):
+ clear_scan_cache(apdev)
try:
hapd = None
params = { "ssid": "vht",
"ieee80211ac": "1",
"vht_oper_chwidth": "1",
"vht_oper_centr_freq_seg0_idx": "42" }
- hapd = hostapd.add_ap(apdev['ifname'], params)
+ hapd = hostapd.add_ap(apdev, params)
bssid = apdev['bssid']
dev.connect("vht", key_mgmt="NONE", scan_freq=str(5000 + 5 * channel))
"vht_capab": "[MAX-MPDU-11454][RXLDPC][SHORT-GI-80][TX-STBC-2BY1][RX-STBC-1][MAX-A-MPDU-LEN-EXP0]",
"vht_oper_centr_freq_seg0_idx": "42",
"require_vht": "1" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[1].connect("vht", key_mgmt="NONE", scan_freq="5180",
disable_vht="1", wait_connect=False)
dev[0].flush_scan_cache()
dev[1].flush_scan_cache()
+def test_ap_vht80_invalid(dev, apdev):
+ """VHT with invalid 80 MHz channel configuration (seg1)"""
+ try:
+ hapd = None
+ params = { "ssid": "vht",
+ "country_code": "US",
+ "hw_mode": "a",
+ "channel": "36",
+ "ht_capab": "[HT40+]",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "vht_oper_chwidth": "1",
+ "vht_oper_centr_freq_seg0_idx": "42",
+ "vht_oper_centr_freq_seg1_idx": "155",
+ 'ieee80211d': '1',
+ 'ieee80211h': '1' }
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
+ # This fails due to unexpected seg1 configuration
+ ev = hapd.wait_event(["AP-DISABLED"], timeout=5)
+ if ev is None:
+ raise Exception("AP-DISABLED not reported")
+ except Exception, e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not vht_supported():
+ raise HwsimSkip("80/160 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ if hapd:
+ hapd.request("DISABLE")
+ subprocess.call(['iw', 'reg', 'set', '00'])
+
+def test_ap_vht80_invalid2(dev, apdev):
+ """VHT with invalid 80 MHz channel configuration (seg0)"""
+ try:
+ hapd = None
+ params = { "ssid": "vht",
+ "country_code": "US",
+ "hw_mode": "a",
+ "channel": "36",
+ "ht_capab": "[HT40+]",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "vht_oper_chwidth": "1",
+ "vht_oper_centr_freq_seg0_idx": "46",
+ 'ieee80211d': '1',
+ 'ieee80211h': '1' }
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
+ # This fails due to invalid seg0 configuration
+ ev = hapd.wait_event(["AP-DISABLED"], timeout=5)
+ if ev is None:
+ raise Exception("AP-DISABLED not reported")
+ except Exception, e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not vht_supported():
+ raise HwsimSkip("80/160 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ if hapd:
+ hapd.request("DISABLE")
+ subprocess.call(['iw', 'reg', 'set', '00'])
+
def test_ap_vht_20(devs, apdevs):
"""VHT and 20 MHz channel"""
dev = devs[0]
"supported_rates": "60 120 240 360 480 540",
"require_vht": "1",
}
- hapd = hostapd.add_ap(ap['ifname'], params)
+ hapd = hostapd.add_ap(ap, params)
dev.connect("test-vht20", scan_freq="5180", key_mgmt="NONE")
hwsim_utils.test_connectivity(dev, hapd)
finally:
"vht_oper_chwidth": "0",
"vht_oper_centr_freq_seg0_idx": "0",
}
- hapd = hostapd.add_ap(ap['ifname'], params)
+ hapd = hostapd.add_ap(ap, params)
dev.connect("test-vht40", scan_freq="5180", key_mgmt="NONE")
hwsim_utils.test_connectivity(dev, hapd)
finally:
"vht_capab": "[MAX-MPDU-7991][MAX-MPDU-11454][VHT160][VHT160-80PLUS80][RXLDPC][SHORT-GI-80][SHORT-GI-160][TX-STBC-2BY1][RX-STBC-1][RX-STBC-12][RX-STBC-123][RX-STBC-1234][SU-BEAMFORMER][SU-BEAMFORMEE][BF-ANTENNA-2][BF-ANTENNA-3][BF-ANTENNA-4][SOUNDING-DIMENSION-2][SOUNDING-DIMENSION-3][SOUNDING-DIMENSION-4][MU-BEAMFORMER][VHT-TXOP-PS][HTC-VHT][MAX-A-MPDU-LEN-EXP0][MAX-A-MPDU-LEN-EXP7][VHT-LINK-ADAPT2][VHT-LINK-ADAPT3][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN]",
"vht_oper_centr_freq_seg0_idx": "42",
"require_vht": "1" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
ev = hapd.wait_event(["AP-DISABLED"], timeout=5)
if ev is None:
raise Exception("Startup failure not reported")
"vht_oper_centr_freq_seg0_idx": "50",
'ieee80211d': '1',
'ieee80211h': '1' }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
ev = wait_dfs_event(hapd, "DFS-CAC-START", 5)
if "DFS-CAC-START" not in ev:
"vht_oper_centr_freq_seg0_idx": "114",
'ieee80211d': '1',
'ieee80211h': '1' }
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params, wait_enabled=False)
+ hapd2 = hostapd.add_ap(apdev[1], params, wait_enabled=False)
ev = wait_dfs_event(hapd2, "DFS-CAC-START", 5)
if "DFS-CAC-START" not in ev:
dev[0].flush_scan_cache()
dev[1].flush_scan_cache()
+def test_ap_vht160_no_dfs(dev, apdev):
+ """VHT with 160 MHz channel width and no DFS"""
+ try:
+ hapd = None
+ params = { "ssid": "vht",
+ "country_code": "ZA",
+ "hw_mode": "a",
+ "channel": "104",
+ "ht_capab": "[HT40-]",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "vht_oper_chwidth": "2",
+ "vht_oper_centr_freq_seg0_idx": "114",
+ 'ieee80211d': '1',
+ 'ieee80211h': '1' }
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
+ ev = hapd.wait_event(["AP-ENABLED"], timeout=2)
+ if not ev:
+ cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE)
+ reg = cmd.stdout.readlines()
+ for r in reg:
+ if "5490" in r and "DFS" in r:
+ raise HwsimSkip("ZA regulatory rule did not have DFS requirement removed")
+ raise Exception("AP setup timed out")
+
+ dev[0].connect("vht", key_mgmt="NONE", scan_freq="5520")
+ hwsim_utils.test_connectivity(dev[0], hapd)
+ sig = dev[0].request("SIGNAL_POLL").splitlines()
+ if "FREQUENCY=5520" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig))
+ if "WIDTH=160 MHz" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
+ except Exception, e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not vht_supported():
+ raise HwsimSkip("80/160 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ dev[0].request("DISCONNECT")
+ if hapd:
+ hapd.request("DISABLE")
+ subprocess.call(['iw', 'reg', 'set', '00'])
+ dev[0].flush_scan_cache()
+
def test_ap_vht80plus80(dev, apdev):
"""VHT with 80+80 MHz channel width"""
try:
"vht_oper_centr_freq_seg1_idx": "155",
'ieee80211d': '1',
'ieee80211h': '1' }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
# This will actually fail since DFS on 80+80 is not yet supported
ev = hapd.wait_event(["AP-DISABLED"], timeout=5)
# ignore result to avoid breaking the test once 80+80 DFS gets enabled
"vht_oper_chwidth": "3",
"vht_oper_centr_freq_seg0_idx": "42",
"vht_oper_centr_freq_seg1_idx": "155" }
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params, wait_enabled=False)
+ hapd2 = hostapd.add_ap(apdev[1], params, wait_enabled=False)
ev = hapd2.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=5)
if not ev:
dev[0].flush_scan_cache()
dev[1].flush_scan_cache()
+def test_ap_vht80plus80_invalid(dev, apdev):
+ """VHT with invalid 80+80 MHz channel"""
+ try:
+ hapd = None
+ params = { "ssid": "vht",
+ "country_code": "US",
+ "hw_mode": "a",
+ "channel": "36",
+ "ht_capab": "[HT40+]",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "vht_oper_chwidth": "3",
+ "vht_oper_centr_freq_seg0_idx": "42",
+ "vht_oper_centr_freq_seg1_idx": "0",
+ 'ieee80211d': '1',
+ 'ieee80211h': '1' }
+ hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
+ # This fails due to missing(invalid) seg1 configuration
+ ev = hapd.wait_event(["AP-DISABLED"], timeout=5)
+ if ev is None:
+ raise Exception("AP-DISABLED not reported")
+ except Exception, e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not vht_supported():
+ raise HwsimSkip("80/160 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ if hapd:
+ hapd.request("DISABLE")
+ subprocess.call(['iw', 'reg', 'set', '00'])
+
def test_ap_vht80_csa(dev, apdev):
"""VHT with 80 MHz channel width and CSA"""
csa_supported(dev[0])
"ieee80211ac": "1",
"vht_oper_chwidth": "1",
"vht_oper_centr_freq_seg0_idx": "155" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("vht", key_mgmt="NONE", scan_freq="5745")
hwsim_utils.test_connectivity(dev[0], hapd)
"vht_oper_chwidth": "0",
"vht_oper_centr_freq_seg0_idx": "1"
}
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
try:
if "OK" not in dev[0].request("VENDOR_ELEM_ADD 13 dd1300904c0400bf0c3240820feaff0000eaff0000"):
raise Exception("Failed to add vendor element")
"channel": "36",
"ieee80211n": "1",
"ht_capab": "[HT40+]" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
params = { "ssid": "test",
"vht_oper_chwidth": "0",
"vht_oper_centr_freq_seg0_idx": "0",
}
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
bssid2 = apdev[1]['bssid']
dev[0].scan_for_bss(bssid, freq=5180)
hapd2.request("DISABLE")
subprocess.call(['iw', 'reg', 'set', '00'])
dev[0].flush_scan_cache()
+
+def test_ap_vht80_pwr_constraint(dev, apdev):
+ """VHT with 80 MHz channel width and local power constraint"""
+ hapd = None
+ try:
+ params = { "ssid": "vht",
+ "country_code": "FI",
+ "hw_mode": "a",
+ "channel": "36",
+ "ht_capab": "[HT40+]",
+ "ieee80211d": "1",
+ "local_pwr_constraint": "3",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "vht_oper_chwidth": "1",
+ "vht_oper_centr_freq_seg0_idx": "42" }
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].connect("vht", key_mgmt="NONE", scan_freq="5180")
+ except Exception, e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not vht_supported():
+ raise HwsimSkip("80 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ dev[0].request("DISCONNECT")
+ if hapd:
+ hapd.request("DISABLE")
+ subprocess.call(['iw', 'reg', 'set', '00'])
+ dev[0].flush_scan_cache()
+
+def test_ap_vht_use_sta_nsts(dev, apdev):
+ """VHT with 80 MHz channel width and use_sta_nsts=1"""
+ try:
+ hapd = None
+ params = { "ssid": "vht",
+ "country_code": "FI",
+ "hw_mode": "a",
+ "channel": "36",
+ "ht_capab": "[HT40+]",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "vht_oper_chwidth": "1",
+ "vht_oper_centr_freq_seg0_idx": "42",
+ "use_sta_nsts": "1" }
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+
+ dev[0].connect("vht", key_mgmt="NONE", scan_freq="5180")
+ hwsim_utils.test_connectivity(dev[0], hapd)
+ except Exception, e:
+ if isinstance(e, Exception) and str(e) == "AP startup failed":
+ if not vht_supported():
+ raise HwsimSkip("80 MHz channel not supported in regulatory information")
+ raise
+ finally:
+ dev[0].request("DISCONNECT")
+ if hapd:
+ hapd.request("DISABLE")
+ subprocess.call(['iw', 'reg', 'set', '00'])
+ dev[0].flush_scan_cache()
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import time
import subprocess
import logging
import hwsim_utils
import hostapd
from utils import iface_is_in_bridge, HwsimSkip
+import os
+from tshark import run_tshark
def test_ap_vlan_open(dev, apdev):
"""AP VLAN with open network"""
params = { "ssid": "test-vlan-open",
"dynamic_vlan": "1",
"accept_mac_file": "hostapd.accept" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412")
dev[1].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412")
"dynamic_vlan": "1",
"vlan_file": "hostapd.vlan",
"accept_mac_file": "hostapd.accept" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412")
dev[1].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412")
"""AP VLAN with WPA2-PSK"""
params = hostapd.wpa2_params(ssid="test-vlan",
passphrase="12345678")
- params['dynamic_vlan'] = "1";
- params['accept_mac_file'] = "hostapd.accept";
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ params['dynamic_vlan'] = "1"
+ params['accept_mac_file'] = "hostapd.accept"
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("test-vlan", psk="12345678", scan_freq="2412")
dev[1].connect("test-vlan", psk="12345678", scan_freq="2412")
def test_ap_vlan_wpa2_radius(dev, apdev):
"""AP VLAN with WPA2-Enterprise and RADIUS attributes"""
params = hostapd.wpa2_eap_params(ssid="test-vlan")
- params['dynamic_vlan'] = "1";
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ params['dynamic_vlan'] = "1"
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("test-vlan", key_mgmt="WPA-EAP", eap="PAX",
identity="vlan1",
hwsim_utils.test_connectivity_iface(dev[1], hapd, "brvlan2")
hwsim_utils.test_connectivity(dev[2], hapd)
+def test_ap_vlan_wpa2_radius_2(dev, apdev):
+ """AP VLAN with WPA2-Enterprise and RADIUS EGRESS_VLANID attributes"""
+ params = hostapd.wpa2_eap_params(ssid="test-vlan")
+ params['dynamic_vlan'] = "1"
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].connect("test-vlan", key_mgmt="WPA-EAP", eap="PAX",
+ identity="vlan1b",
+ password_hex="0123456789abcdef0123456789abcdef",
+ scan_freq="2412")
+
+ hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1")
+
def test_ap_vlan_wpa2_radius_id_change(dev, apdev):
"""AP VLAN with WPA2-Enterprise and RADIUS attributes changing VLANID"""
+ generic_ap_vlan_wpa2_radius_id_change(dev, apdev, False)
+
+def test_ap_vlan_tagged_wpa2_radius_id_change(dev, apdev):
+ """AP tagged VLAN with WPA2-Enterprise and RADIUS attributes changing VLANID"""
+ ifname1 = 'wlan0.1'
+ ifname2 = 'wlan0.2'
+ try:
+ # Create tagged interface for wpa_supplicant
+ subprocess.call(['ip', 'link', 'add', 'link', dev[0].ifname,
+ 'name', ifname1, 'type', 'vlan', 'id', '1'])
+ subprocess.call(['ifconfig', ifname1, 'up'])
+
+ subprocess.call(['ip', 'link', 'add', 'link', dev[0].ifname,
+ 'name', ifname2, 'type', 'vlan', 'id', '2'])
+ subprocess.call(['ifconfig', ifname2, 'up'])
+
+ generic_ap_vlan_wpa2_radius_id_change(dev, apdev, True)
+ finally:
+ subprocess.call(['ifconfig', ifname1, 'down'])
+ subprocess.call(['ifconfig', ifname2, 'down'])
+ subprocess.call(['ip', 'link', 'del', ifname1])
+ subprocess.call(['ip', 'link', 'del', ifname2])
+
+def generic_ap_vlan_wpa2_radius_id_change(dev, apdev, tagged):
as_params = { "ssid": "as",
"beacon_int": "2000",
"radius_server_clients": "auth_serv/radius_clients.conf",
"ca_cert": "auth_serv/ca.pem",
"server_cert": "auth_serv/server.pem",
"private_key": "auth_serv/server.key" }
- authserv = hostapd.add_ap(apdev[1]['ifname'], as_params)
+ authserv = hostapd.add_ap(apdev[1], as_params)
params = hostapd.wpa2_eap_params(ssid="test-vlan")
- params['dynamic_vlan'] = "1";
+ params['dynamic_vlan'] = "1"
params['auth_server_port'] = "18128"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ identity = "vlan1tagged" if tagged else "vlan1"
dev[0].connect("test-vlan", key_mgmt="WPA-EAP", eap="PAX",
- identity="vlan1",
+ identity=identity,
password_hex="0123456789abcdef0123456789abcdef",
scan_freq="2412")
- hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1")
+ if tagged:
+ hwsim_utils.run_connectivity_test(dev[0], hapd, 0, ifname1="wlan0.1",
+ ifname2="brvlan1")
+ else:
+ hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1")
logger.info("VLAN-ID -> 2")
sta = hapd.get_sta(dev[0].own_addr())
if 'vlan_id' not in sta:
raise Exception("No VLAN ID in STA info")
- if sta['vlan_id'] != '2':
+ if (not tagged) and (sta['vlan_id'] != '2'):
raise Exception("Unexpected VLAN ID: " + sta['vlan_id'])
- hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan2")
+ if tagged:
+ hwsim_utils.run_connectivity_test(dev[0], hapd, 0, ifname1="wlan0.2",
+ ifname2="brvlan2")
+ else:
+ hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan2")
logger.info("VLAN-ID -> 1")
time.sleep(1)
sta = hapd.get_sta(dev[0].own_addr())
if 'vlan_id' not in sta:
raise Exception("No VLAN ID in STA info")
- if sta['vlan_id'] != '1':
+ if (not tagged) and (sta['vlan_id'] != '1'):
raise Exception("Unexpected VLAN ID: " + sta['vlan_id'])
time.sleep(0.2)
try:
- hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1")
+ if tagged:
+ hwsim_utils.run_connectivity_test(dev[0], hapd, 0,
+ ifname1="wlan0.1",
+ ifname2="brvlan1")
+ else:
+ hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1")
except Exception, e:
# It is possible for new bridge setup to not be ready immediately, so
# try again to avoid reporting issues related to that.
logger.info("First VLAN-ID 1 data test failed - try again")
- hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1")
+ if tagged:
+ hwsim_utils.run_connectivity_test(dev[0], hapd, 0,
+ ifname1="wlan0.1",
+ ifname2="brvlan1")
+ else:
+ hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1")
def test_ap_vlan_wpa2_radius_required(dev, apdev):
"""AP VLAN with WPA2-Enterprise and RADIUS attributes required"""
params = hostapd.wpa2_eap_params(ssid="test-vlan")
- params['dynamic_vlan'] = "2";
- hostapd.add_ap(apdev[0]['ifname'], params)
+ params['dynamic_vlan'] = "2"
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-vlan", key_mgmt="WPA-EAP", eap="PAX",
identity="vlan1",
"dynamic_vlan": "1",
"vlan_tagged_interface": "lo",
"accept_mac_file": "hostapd.accept" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412")
dev[1].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412")
def test_ap_vlan_iface_cleanup_multibss(dev, apdev):
"""AP VLAN operation in multi-BSS multi-VLAN case"""
+ ap_vlan_iface_cleanup_multibss(dev, apdev, 'multi-bss-iface.conf')
+def ap_vlan_iface_cleanup_multibss(dev, apdev, cfgfile):
# AP VLAN with WPA2-Enterprise and RADIUS attributes changing VLANID
# check that multiple bss do not interfere with each other with respect
# to deletion of bridge and tagged interface.
"server_cert": "auth_serv/server.pem",
"private_key": "auth_serv/server.key",
"vlan_naming": "1" }
- authserv = hostapd.add_ap(apdev[1]['ifname'], as_params)
-
- ifname = apdev[0]['ifname']
+ authserv = hostapd.add_ap(apdev[1], as_params)
# start the actual test
- hostapd.add_iface(ifname, 'multi-bss-iface.conf')
- hapd = hostapd.Hostapd(ifname)
+ hapd = hostapd.add_iface(apdev[0], cfgfile)
hapd1 = hostapd.Hostapd("wlan3-2", 1)
hapd1.enable()
hapd.request("DISABLE")
finally:
ap_vlan_iface_cleanup_multibss_cleanup()
+
+def test_ap_vlan_iface_cleanup_multibss_per_sta_vif(dev, apdev):
+ """AP VLAN operation in multi-BSS multi-VLAN case with per-sta-vif set"""
+
+ # AP VLAN with WPA2-Enterprise and RADIUS attributes changing VLANID
+ # check that multiple bss do not interfere with each other with respect
+ # to deletion of bridge and tagged interface. per_sta_vif is enabled.
+ ap_vlan_iface_cleanup_multibss(dev, apdev,
+ 'multi-bss-iface-per_sta_vif.conf')
+
+def test_ap_vlan_without_station(dev, apdev, p):
+ """AP VLAN with WPA2-PSK and no station"""
+ try:
+ subprocess.call(['brctl', 'addbr', 'brvlan1'])
+ subprocess.call(['brctl', 'setfd', 'brvlan1', '0'])
+ subprocess.call(['ifconfig', 'brvlan1', 'up'])
+ # use a passphrase wlantest does not know, so it cannot
+ # inject decrypted frames into pcap
+ params = hostapd.wpa2_params(ssid="test-vlan",
+ passphrase="12345678x")
+ params['dynamic_vlan'] = "1"
+ params['vlan_file'] = 'hostapd.wlan3.vlan'
+ params['accept_mac_file'] = "hostapd.accept"
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ # inject some traffic
+ sa = hapd.own_addr()
+ da = "ff:ff:ff:ff:ff:00"
+ hapd.request('DATA_TEST_CONFIG 1 ifname=brvlan1')
+ hapd.request('DATA_TEST_TX {} {} 0'.format(da, sa))
+ hapd.request('DATA_TEST_CONFIG 0')
+ time.sleep(.1)
+
+ dev[0].connect("test-vlan", psk="12345678x", scan_freq="2412")
+
+ # inject some traffic
+ sa = hapd.own_addr()
+ da = "ff:ff:ff:ff:ff:01"
+ hapd.request('DATA_TEST_CONFIG 1 ifname=brvlan1')
+ hapd.request('DATA_TEST_TX {} {} 0'.format(da, sa))
+ hapd.request('DATA_TEST_CONFIG 0')
+
+ # let the AP send couple of Beacon frames
+ time.sleep(1)
+ out = run_tshark(os.path.join(p['logdir'], "hwsim0.pcapng"),
+ "wlan.da == ff:ff:ff:ff:ff:00",
+ ["wlan.fc.protected"])
+
+ if out is not None:
+ lines = out.splitlines()
+ if len(lines) < 1:
+ raise Exception("first frame not observed")
+ state = 1
+ for l in lines:
+ is_protected = int(l, 16)
+ if is_protected != 1:
+ state = 0
+ if state != 1:
+ raise Exception("Broadcast packets were not encrypted when no station was connected")
+ else:
+ raise Exception("first frame not observed")
+
+ out = run_tshark(os.path.join(p['logdir'], "hwsim0.pcapng"),
+ "wlan.da == ff:ff:ff:ff:ff:01",
+ ["wlan.fc.protected"])
+
+ if out is not None:
+ lines = out.splitlines()
+ if len(lines) < 1:
+ raise Exception("second frame not observed")
+ state = 1
+ for l in lines:
+ is_protected = int(l, 16)
+ if is_protected != 1:
+ state = 0
+ if state != 1:
+ raise Exception("Broadcast packets were not encrypted when station was connected")
+ else:
+ raise Exception("second frame not observed")
+
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected()
+
+ finally:
+ subprocess.call(['ip', 'link', 'set', 'dev', 'brvlan1', 'down'])
+ subprocess.call(['ip', 'link', 'set', 'dev', 'wlan3.1', 'down'],
+ stderr=open('/dev/null', 'w'))
+ subprocess.call(['brctl', 'delif', 'brvlan1', 'wlan3.1'],
+ stderr=open('/dev/null', 'w'))
+ subprocess.call(['brctl', 'delbr', 'brvlan1'])
+
+@remote_compatible
+def test_ap_open_per_sta_vif(dev, apdev):
+ """AP VLAN with open network"""
+ params = { "ssid": "test-vlan-open",
+ "per_sta_vif": "1" }
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412")
+ hwsim_utils.test_connectivity_iface(dev[0], hapd,
+ apdev[0]['ifname'] + ".4096")
+
+@remote_compatible
+def test_ap_vlan_open_per_sta_vif(dev, apdev):
+ """AP VLAN (dynamic) with open network"""
+ params = { "ssid": "test-vlan-open",
+ "per_sta_vif": "1",
+ "dynamic_vlan": "1" }
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412")
+ hwsim_utils.test_connectivity_iface(dev[0], hapd,
+ apdev[0]['ifname'] + ".4096")
+
+def test_ap_vlan_wpa2_radius_tagged(dev, apdev):
+ """AP VLAN with WPA2-Enterprise and RADIUS EGRESS_VLANID attributes"""
+ ifname = 'wlan0.1'
+ try:
+ params = hostapd.wpa2_eap_params(ssid="test-vlan")
+ params['dynamic_vlan'] = "1"
+ params["vlan_naming"] = "1"
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].connect("test-vlan", key_mgmt="WPA-EAP", eap="PAX",
+ identity="vlan1tagged",
+ password_hex="0123456789abcdef0123456789abcdef",
+ scan_freq="2412")
+
+ # Create tagged interface for wpa_supplicant
+ subprocess.call(['ip', 'link', 'add', 'link', dev[0].ifname,
+ 'name', ifname, 'type', 'vlan', 'id', '1'])
+ subprocess.call(['ifconfig', ifname, 'up'])
+
+ hwsim_utils.run_connectivity_test(dev[0], hapd, 0, ifname1=ifname,
+ ifname2="brvlan1")
+ finally:
+ subprocess.call(['ifconfig', ifname, 'down'])
+ subprocess.call(['ip', 'link', 'del', ifname])
+
+def test_ap_vlan_wpa2_radius_mixed(dev, apdev):
+ """AP VLAN with WPA2-Enterprise and tagged+untagged VLANs"""
+ ifname = 'wlan0.1'
+ try:
+ params = hostapd.wpa2_eap_params(ssid="test-vlan")
+ params['dynamic_vlan'] = "1"
+ params["vlan_naming"] = "1"
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].connect("test-vlan", key_mgmt="WPA-EAP", eap="PAX",
+ identity="vlan12mixed",
+ password_hex="0123456789abcdef0123456789abcdef",
+ scan_freq="2412")
+
+ # Add tagged VLAN interface to wpa_supplicant interface for testing
+ subprocess.call(['ip', 'link', 'add', 'link', dev[0].ifname,
+ 'name', ifname, 'type', 'vlan', 'id', '1'])
+ subprocess.call(['ifconfig', ifname, 'up'])
+
+ logger.info("Test connectivity in untagged VLAN 2")
+ hwsim_utils.run_connectivity_test(dev[0], hapd, 0,
+ ifname1=dev[0].ifname,
+ ifname2="brvlan2")
+ logger.info("Test connectivity in tagged VLAN 1")
+ hwsim_utils.run_connectivity_test(dev[0], hapd, 0, ifname1=ifname,
+ ifname2="brvlan1")
+ finally:
+ subprocess.call(['ifconfig', ifname, 'down'])
+ subprocess.call(['ip', 'link', 'del', ifname])
+
+def test_ap_vlan_reconnect(dev, apdev):
+ """AP VLAN with WPA2-PSK connect, disconnect, connect"""
+ params = hostapd.wpa2_params(ssid="test-vlan",
+ passphrase="12345678")
+ params['dynamic_vlan'] = "1"
+ params['accept_mac_file'] = "hostapd.accept"
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ logger.info("connect sta")
+ dev[0].connect("test-vlan", psk="12345678", scan_freq="2412")
+ hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1")
+ logger.info("disconnect sta")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected(timeout=10)
+ time.sleep(1)
+ logger.info("reconnect sta")
+ dev[0].connect("test-vlan", psk="12345678", scan_freq="2412")
+ hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1")
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import base64
import binascii
from Crypto.Cipher import AES
import hostapd
from wpasupplicant import WpaSupplicant
from utils import HwsimSkip, alloc_fail, fail_test, skip_with_fips
+from utils import wait_fail_trigger
+from test_ap_eap import int_eap_server_params
def wps_start_ap(apdev, ssid="test-wps-conf"):
params = { "ssid": ssid, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP" }
- return hostapd.add_ap(apdev['ifname'], params)
+ return hostapd.add_ap(apdev, params)
+@remote_compatible
def test_ap_wps_init(dev, apdev):
"""Initial AP configuration with first WPS Enrollee"""
ssid = "test-wps"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "1" })
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "1" })
logger.info("WPS provisioning step")
hapd.request("WPS_PBC")
if "PBC Status: Active" not in hapd.request("WPS_GET_STATUS"):
"""Initial two-radio AP configuration with first WPS PBC Enrollee"""
ssid = "test-wps"
params = { "ssid": ssid, "eap_server": "1", "wps_state": "1" }
- hostapd.add_ap(apdev[0]['ifname'], params)
- hostapd.add_ap(apdev[1]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
+ hostapd.add_ap(apdev[1], params)
logger.info("WPS provisioning step")
hapd.request("WPS_PBC")
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
"""Initial two-radio AP configuration with first WPS PIN Enrollee"""
ssid = "test-wps"
params = { "ssid": ssid, "eap_server": "1", "wps_state": "1" }
- hostapd.add_ap(apdev[0]['ifname'], params)
- hostapd.add_ap(apdev[1]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
+ hostapd.add_ap(apdev[1], params)
logger.info("WPS provisioning step")
pin = dev[0].wps_read_pin()
hapd.request("WPS_PIN any " + pin)
if "[WPS-AUTH]" in bss['flags']:
raise Exception("WPS-AUTH flag not cleared from AP2")
+@remote_compatible
def test_ap_wps_init_through_wps_config(dev, apdev):
"""Initial AP configuration using wps_config command"""
ssid = "test-wps-init-config"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "1" })
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "1" })
if "FAIL" in hapd.request("WPS_CONFIG " + ssid.encode("hex") + " WPA2PSK CCMP " + "12345678".encode("hex")):
raise Exception("WPS_CONFIG command failed")
ev = hapd.wait_event(["WPS-NEW-AP-SETTINGS"], timeout=5)
dev[0].connect(ssid, psk="12345678", scan_freq="2412", proto="WPA2",
pairwise="CCMP", group="CCMP")
+@remote_compatible
def test_ap_wps_init_through_wps_config_2(dev, apdev):
"""AP configuration using wps_config and wps_cred_processing=2"""
ssid = "test-wps-init-config"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "1",
- "wps_cred_processing": "2" })
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "1",
+ "wps_cred_processing": "2" })
if "FAIL" in hapd.request("WPS_CONFIG " + ssid.encode("hex") + " WPA2PSK CCMP " + "12345678".encode("hex")):
raise Exception("WPS_CONFIG command failed")
ev = hapd.wait_event(["WPS-NEW-AP-SETTINGS"], timeout=5)
if "100e" not in ev:
raise Exception("WPS-NEW-AP-SETTINGS did not include Credential")
+@remote_compatible
def test_ap_wps_invalid_wps_config_passphrase(dev, apdev):
"""AP configuration using wps_config command with invalid passphrase"""
ssid = "test-wps-init-config"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "1" })
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "1" })
if "FAIL" not in hapd.request("WPS_CONFIG " + ssid.encode("hex") + " WPA2PSK CCMP " + "1234567".encode("hex")):
raise Exception("Invalid WPS_CONFIG command accepted")
def test_ap_wps_conf(dev, apdev):
"""WPS PBC provisioning with configured AP"""
ssid = "test-wps-conf"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "wpa_passphrase": "12345678", "wpa": "2",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
logger.info("WPS provisioning step")
hapd.request("WPS_PBC")
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
"country_code": "FI", "hw_mode": "a", "channel": "36" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
logger.info("WPS provisioning step")
hapd.request("WPS_PBC")
dev[0].scan_for_bss(apdev[0]['bssid'], freq="5180")
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
"country_code": "JP", "hw_mode": "b", "channel": "14" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
logger.info("WPS provisioning step")
hapd.request("WPS_PBC")
dev[0].request("WPS_PBC")
subprocess.call(['iw', 'reg', 'set', '00'])
dev[0].flush_scan_cache()
+@remote_compatible
def test_ap_wps_twice(dev, apdev):
"""WPS provisioning with twice to change passphrase"""
ssid = "test-wps-twice"
params = { "ssid": ssid, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP" }
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
logger.info("WPS provisioning step")
hapd.request("WPS_PBC")
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
dev[0].request("DISCONNECT")
logger.info("Restart AP with different passphrase and re-run WPS")
- hapd_global = hostapd.HostapdGlobal()
- hapd_global.remove(apdev[0]['ifname'])
+ hostapd.remove_bss(apdev[0])
params['wpa_passphrase'] = 'another passphrase'
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
logger.info("WPS provisioning step")
hapd.request("WPS_PBC")
dev[0].dump_monitor()
if len(networks) > 1:
raise Exception("Unexpected duplicated network block present")
+@remote_compatible
def test_ap_wps_incorrect_pin(dev, apdev):
"""WPS PIN provisioning with incorrect PIN"""
ssid = "test-wps-incorrect-pin"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "wpa_passphrase": "12345678", "wpa": "2",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
logger.info("WPS provisioning attempt 1")
hapd.request("WPS_PIN any 12345670")
raise Exception("PIN error detected on incorrect message")
dev[0].wait_disconnected(timeout=10)
+@remote_compatible
def test_ap_wps_conf_pin(dev, apdev):
"""WPS PIN provisioning with configured AP"""
ssid = "test-wps-conf-pin"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "wpa_passphrase": "12345678", "wpa": "2",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
logger.info("WPS provisioning step")
pin = dev[0].wps_read_pin()
hapd.request("WPS_PIN any " + pin)
hapd.request("WPS_PIN any " + pin)
dev[1].wait_connected(timeout=30)
+def test_ap_wps_conf_pin_mixed_mode(dev, apdev):
+ """WPS PIN provisioning with configured AP (WPA+WPA2)"""
+ ssid = "test-wps-conf-pin-mixed"
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "3",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
+ "wpa_pairwise": "TKIP" })
+
+ logger.info("WPS provisioning step")
+ pin = dev[0].wps_read_pin()
+ hapd.request("WPS_PIN any " + pin)
+ dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
+ dev[0].dump_monitor()
+ dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
+ dev[0].wait_connected(timeout=30)
+ status = dev[0].get_status()
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ if status['pairwise_cipher'] != 'CCMP' or status['group_cipher'] != 'TKIP' or status['key_mgmt'] != 'WPA2-PSK':
+ raise Exception("Unexpected encryption/key_mgmt configuration: pairwise=%s group=%s key_mgmt=%s" % (status['pairwise_cipher'], status['group_cipher'], status['key_mgmt']))
+
+ logger.info("WPS provisioning step (auth_types=0x1b)")
+ if "OK" not in dev[0].request("SET wps_force_auth_types 0x1b"):
+ raise Exception("Failed to set wps_force_auth_types 0x1b")
+ pin = dev[0].wps_read_pin()
+ hapd.request("WPS_PIN any " + pin)
+ dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
+ dev[0].dump_monitor()
+ dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
+ dev[0].wait_connected(timeout=30)
+ status = dev[0].get_status()
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ if status['pairwise_cipher'] != 'CCMP' or status['group_cipher'] != 'TKIP' or status['key_mgmt'] != 'WPA2-PSK':
+ raise Exception("Unexpected encryption/key_mgmt configuration: pairwise=%s group=%s key_mgmt=%s" % (status['pairwise_cipher'], status['group_cipher'], status['key_mgmt']))
+
+ logger.info("WPS provisioning step (auth_types=0 encr_types=0)")
+ if "OK" not in dev[0].request("SET wps_force_auth_types 0"):
+ raise Exception("Failed to set wps_force_auth_types 0")
+ if "OK" not in dev[0].request("SET wps_force_encr_types 0"):
+ raise Exception("Failed to set wps_force_encr_types 0")
+ pin = dev[0].wps_read_pin()
+ hapd.request("WPS_PIN any " + pin)
+ dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
+ dev[0].dump_monitor()
+ dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
+ dev[0].wait_connected(timeout=30)
+ status = dev[0].get_status()
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ if status['pairwise_cipher'] != 'CCMP' or status['group_cipher'] != 'TKIP' or status['key_mgmt'] != 'WPA2-PSK':
+ raise Exception("Unexpected encryption/key_mgmt configuration: pairwise=%s group=%s key_mgmt=%s" % (status['pairwise_cipher'], status['group_cipher'], status['key_mgmt']))
+
+ dev[0].request("SET wps_force_auth_types ")
+ dev[0].request("SET wps_force_encr_types ")
+
+@remote_compatible
def test_ap_wps_conf_pin_v1(dev, apdev):
"""WPS PIN provisioning with configured WPS v1.0 AP"""
ssid = "test-wps-conf-pin-v1"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "wpa_passphrase": "12345678", "wpa": "2",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
logger.info("WPS provisioning step")
pin = dev[0].wps_read_pin()
hapd.request("SET wps_version_number 0x10")
dev[0].wait_connected(timeout=30)
hapd.request("SET wps_version_number 0x20")
+@remote_compatible
def test_ap_wps_conf_pin_2sta(dev, apdev):
"""Two stations trying to use WPS PIN at the same time"""
ssid = "test-wps-conf-pin2"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "wpa_passphrase": "12345678", "wpa": "2",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
logger.info("WPS provisioning step")
pin = "12345670"
pin2 = "55554444"
dev[0].wait_connected(timeout=30)
dev[1].wait_connected(timeout=30)
+@remote_compatible
def test_ap_wps_conf_pin_timeout(dev, apdev):
"""WPS PIN provisioning with configured AP timing out PIN"""
ssid = "test-wps-conf-pin"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "wpa_passphrase": "12345678", "wpa": "2",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
addr = dev[0].p2p_interface_addr()
pin = dev[0].wps_read_pin()
if "FAIL" not in hapd.request("WPS_PIN "):
"""WPS registrar using AP PIN to connect"""
ssid = "test-wps-reg-ap-pin"
appin = "12345670"
- hostapd.add_ap(apdev[0]['ifname'],
+ hostapd.add_ap(apdev[0],
{ "ssid": ssid, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
"""WPS registrar using AP PIN to connect (WPA+WPA2)"""
ssid = "test-wps-reg-ap-pin"
appin = "12345670"
- hostapd.add_ap(apdev[0]['ifname'],
+ hostapd.add_ap(apdev[0],
{ "ssid": ssid, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "3",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
f.write(data)
ssid = "test-wps-reg-ap-pin"
appin = "12345670"
- hostapd.add_ap(apdev[0]['ifname'],
+ hostapd.add_ap(apdev[0],
{ "ssid": ssid, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
"ap_pin": appin, "ap_settings": ap_settings })
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], { "ssid": "test" })
+ hapd2 = hostapd.add_ap(apdev[1], { "ssid": "test" })
dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
dev[0].scan_for_bss(apdev[1]['bssid'], freq=2412)
dev[0].wps_reg(apdev[0]['bssid'], appin)
"""WPS registrar using random AP PIN"""
ssid = "test-wps-reg-random-ap-pin"
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "wpa_passphrase": "12345678", "wpa": "2",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
- "device_name": "Wireless AP", "manufacturer": "Company",
- "model_name": "WAP", "model_number": "123",
- "serial_number": "12345", "device_type": "6-0050F204-1",
- "os_version": "01020300",
- "config_methods": "label push_button",
- "uuid": ap_uuid, "upnp_iface": "lo" })
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ params = { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
+ "device_name": "Wireless AP", "manufacturer": "Company",
+ "model_name": "WAP", "model_number": "123",
+ "serial_number": "12345", "device_type": "6-0050F204-1",
+ "os_version": "01020300",
+ "config_methods": "label push_button",
+ "uuid": ap_uuid, "upnp_iface": "lo" }
+ hapd = hostapd.add_ap(apdev[0], params)
appin = hapd.request("WPS_AP_PIN random")
if "FAIL" in appin:
raise Exception("Could not generate random AP PIN")
check_wps_reg_failure(dev[1], apdev[0], appin)
with fail_test(hapd, 1, "os_get_random;wps_generate_pin"):
- if "FAIL" in hapd.request("WPS_AP_PIN random 1"):
- raise Exception("Failed to generate PIN during OOM")
+ hapd.request("WPS_AP_PIN random 1")
hapd.request("WPS_AP_PIN disable")
with alloc_fail(hapd, 1, "upnp_wps_set_ap_pin"):
"""WPS registrar configuring an AP using AP PIN"""
ssid = "test-wps-init-ap-pin"
appin = "12345670"
- hostapd.add_ap(apdev[0]['ifname'],
+ hostapd.add_ap(apdev[0],
{ "ssid": ssid, "eap_server": "1", "wps_state": "2",
"ap_pin": appin})
logger.info("WPS configuration step")
appin = "12345670"
params = { "ssid": ssid, "eap_server": "1", "wps_state": "2",
"wps_cred_processing": "1", "ap_pin": appin}
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
new_ssid = "wps-new-ssid"
new_passphrase = "1234567890"
skip_with_fips(dev[0])
ssid = "test-wps-init-ap"
appin = "12345670"
- hostapd.add_ap(apdev[0]['ifname'],
+ hostapd.add_ap(apdev[0],
{ "ssid": ssid, "eap_server": "1", "wps_state": "1",
"ap_pin": appin})
logger.info("WPS configuration step")
"""WPS registrar locking up AP setup on AP PIN failures"""
ssid = "test-wps-incorrect-ap-pin"
appin = "12345670"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "wpa_passphrase": "12345678", "wpa": "2",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
- "ap_pin": appin})
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
+ "ap_pin": appin})
new_ssid = "wps-new-ssid-test"
new_passphrase = "1234567890"
logger.info("BSS: " + str(bss))
raise Exception("AP Setup Locked not indicated in scan results")
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
status = hapd.request("WPS_GET_STATUS")
if "Last WPS result: Failed" not in status:
raise Exception("WPS failure result not shown correctly")
dev[0].dump_monitor()
logger.info("WPS provisioning step")
pin = dev[0].wps_read_pin()
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
hapd.request("WPS_PIN any " + pin)
dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
ev = dev[0].wait_event(["WPS-SUCCESS"], timeout=30)
"""WPS re-enabling AP PIN after timeout"""
ssid = "test-wps-incorrect-ap-pin"
appin = "12345670"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "wpa_passphrase": "12345678", "wpa": "2",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
- "ap_pin": appin})
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
+ "ap_pin": appin})
new_ssid = "wps-new-ssid-test"
new_passphrase = "1234567890"
time.sleep(0.1)
if not ap_setup_locked:
raise Exception("AP setup was not locked")
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
ev = hapd.wait_event(["WPS-AP-SETUP-UNLOCKED"], timeout=80)
if ev is None:
raise Exception("AP PIN did not get unlocked on 60 second timeout")
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
"ap_pin": appin, "ap_setup_locked": "2" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
new_ssid = "wps-new-ssid-test"
new_passphrase = "1234567890"
dev[0].request("WPS_CANCEL")
dev[0].wait_disconnected()
+@remote_compatible
def test_ap_wps_pbc_overlap_2ap(dev, apdev):
"""WPS PBC session overlap with two active APs"""
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": "wps1", "eap_server": "1", "wps_state": "2",
- "wpa_passphrase": "12345678", "wpa": "2",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
- "wps_independent": "1"})
- hostapd.add_ap(apdev[1]['ifname'],
- { "ssid": "wps2", "eap_server": "1", "wps_state": "2",
- "wpa_passphrase": "123456789", "wpa": "2",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
- "wps_independent": "1"})
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ params = { "ssid": "wps1", "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
+ "wps_independent": "1"}
+ hapd = hostapd.add_ap(apdev[0], params)
+ params = { "ssid": "wps2", "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "123456789", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
+ "wps_independent": "1"}
+ hapd2 = hostapd.add_ap(apdev[1], params)
hapd.request("WPS_PBC")
- hapd2 = hostapd.Hostapd(apdev[1]['ifname'])
hapd2.request("WPS_PBC")
logger.info("WPS provisioning step")
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
hapd2.request("DISABLE")
dev[0].flush_scan_cache()
+@remote_compatible
def test_ap_wps_pbc_overlap_2sta(dev, apdev):
"""WPS PBC session overlap with two active STAs"""
ssid = "test-wps-pbc-overlap"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "wpa_passphrase": "12345678", "wpa": "2",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
logger.info("WPS provisioning step")
hapd.request("WPS_PBC")
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
dev[0].flush_scan_cache()
dev[1].flush_scan_cache()
+@remote_compatible
def test_ap_wps_cancel(dev, apdev):
"""WPS AP cancelling enabled config method"""
ssid = "test-wps-ap-cancel"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "wpa_passphrase": "12345678", "wpa": "2",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP" })
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP" })
bssid = apdev[0]['bssid']
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
logger.info("Verify PBC enable/cancel")
hapd.request("WPS_PBC")
ssid = "wps-er-add-enrollee"
ap_pin = "12345670"
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
- hostapd.add_ap(apdev[0]['ifname'],
+ hostapd.add_ap(apdev[0],
{ "ssid": ssid, "eap_server": "1", "wps_state": "1",
"device_name": "Wireless AP", "manufacturer": "Company",
"model_name": "WAP", "model_number": "123",
ssid = "wps-er-add-enrollee"
ap_pin = "12345670"
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
- hostapd.add_ap(apdev[0]['ifname'],
+ hostapd.add_ap(apdev[0],
{ "ssid": ssid, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
try:
_test_ap_wps_er_multi_add_enrollee(dev, apdev)
finally:
- dev[0].request("WPS_ER_STOP")
+ for i in range(2):
+ dev[i].request("WPS_ER_STOP")
def _test_ap_wps_er_multi_add_enrollee(dev, apdev):
ssid = "wps-er-add-enrollee"
ap_pin = "12345670"
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
- hostapd.add_ap(apdev[0]['ifname'],
+ hostapd.add_ap(apdev[0],
{ "ssid": ssid, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
for i in range(2):
dev[i].scan_for_bss(apdev[0]['bssid'], freq=2412)
dev[i].wps_reg(apdev[0]['bssid'], ap_pin)
+ for i in range(2):
dev[i].request("WPS_ER_START ifname=lo")
for i in range(2):
ev = dev[i].wait_event(["WPS-ER-AP-ADD"], timeout=15)
if ev is None:
raise Exception("AP discovery timed out")
dev[i].dump_monitor()
+ for i in range(2):
dev[i].request("WPS_ER_LEARN " + ap_uuid + " " + ap_pin)
+ for i in range(2):
ev = dev[i].wait_event(["WPS-ER-AP-SETTINGS"], timeout=15)
if ev is None:
raise Exception("AP learn timed out")
ssid = "wps-er-add-enrollee-pbc"
ap_pin = "12345670"
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
- hostapd.add_ap(apdev[0]['ifname'],
+ hostapd.add_ap(apdev[0],
{ "ssid": ssid, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
ssid = "wps-er-add-enrollee-pbc"
ap_pin = "12345670"
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
- hostapd.add_ap(apdev[0]['ifname'],
+ hostapd.add_ap(apdev[0],
{ "ssid": ssid, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
ssid = "wps-er-add-enrollee-pbc"
ap_pin = "12345670"
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
- hostapd.add_ap(apdev[0]['ifname'],
+ hostapd.add_ap(apdev[0],
{ "ssid": ssid, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
if ev is None:
raise Exception("WPS ER did not report success")
+@remote_compatible
def test_ap_wps_er_config_ap(dev, apdev):
"""WPS ER configuring AP over UPnP"""
try:
ssid = "wps-er-ap-config"
ap_pin = "12345670"
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
- hostapd.add_ap(apdev[0]['ifname'],
+ hostapd.add_ap(apdev[0],
{ "ssid": ssid, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
if "OK" not in dev[0].request("WPS_ER_STOP"):
raise Exception("WPS_ER_STOP failed")
+@remote_compatible
def test_ap_wps_er_cache_ap_settings(dev, apdev):
"""WPS ER caching AP settings"""
try:
"os_version": "01020300",
"config_methods": "label push_button",
"ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
dev[0].wps_reg(apdev[0]['bssid'], ap_pin)
id = int(dev[0].list_networks()[0]['id'])
if ev is None:
raise Exception("AP removal or disconnection timed out")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
for i in range(2):
ev = dev[0].wait_event([ "WPS-ER-AP-ADD", "CTRL-EVENT-CONNECTED" ],
timeout=15)
"os_version": "01020300",
"config_methods": "label push_button",
"ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
dev[0].wps_reg(apdev[0]['bssid'], ap_pin)
id = int(dev[0].list_networks()[0]['id'])
if ev is None:
raise Exception("AP removal or disconnection timed out")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
for i in range(2):
ev = dev[0].wait_event([ "WPS-ER-AP-ADD", "CTRL-EVENT-CONNECTED" ],
timeout=15)
"os_version": "01020300",
"config_methods": "label push_button",
"ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
dev[0].wps_reg(apdev[0]['bssid'], ap_pin)
id = int(dev[0].list_networks()[0]['id'])
if ev is None:
raise Exception("AP removal or disconnection timed out")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
for i in range(2):
ev = dev[0].wait_event([ "WPS-ER-AP-ADD", "CTRL-EVENT-CONNECTED" ],
timeout=15)
"os_version": "01020300",
"config_methods": "label push_button",
"ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
dev[0].wps_reg(apdev[0]['bssid'], ap_pin)
id = int(dev[0].list_networks()[0]['id'])
"os_version": "01020300",
"config_methods": "label push_button",
"ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
dev[0].wps_reg(apdev[0]['bssid'], ap_pin)
dev[0].request("WPS_ER_STOP")
+@remote_compatible
def test_ap_wps_er_learn_oom(dev, apdev):
"""WPS ER learn OOM"""
try:
"os_version": "01020300",
"config_methods": "label push_button",
"ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
dev[0].wps_reg(apdev[0]['bssid'], ap_pin)
"""WPS with fragmentation in EAP-WSC and mixed mode WPA+WPA2"""
ssid = "test-wps-fragmentation"
appin = "12345670"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "wpa_passphrase": "12345678", "wpa": "3",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
- "wpa_pairwise": "TKIP", "ap_pin": appin,
- "fragment_size": "50" })
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "3",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
+ "wpa_pairwise": "TKIP", "ap_pin": appin,
+ "fragment_size": "50" })
logger.info("WPS provisioning step (PBC)")
hapd.request("WPS_PBC")
dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
if status['key_mgmt'] != 'WPA2-PSK':
raise Exception("Unexpected key_mgmt")
+@remote_compatible
def test_ap_wps_new_version_sta(dev, apdev):
"""WPS compatibility with new version number on the station"""
ssid = "test-wps-ver"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "wpa_passphrase": "12345678", "wpa": "2",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP" })
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP" })
logger.info("WPS provisioning step")
hapd.request("WPS_PBC")
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
dev[0].request("WPS_PBC " + apdev[0]['bssid'])
dev[0].wait_connected(timeout=30)
+@remote_compatible
def test_ap_wps_new_version_ap(dev, apdev):
"""WPS compatibility with new version number on the AP"""
ssid = "test-wps-ver"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "wpa_passphrase": "12345678", "wpa": "2",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP" })
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP" })
logger.info("WPS provisioning step")
if "FAIL" in hapd.request("SET wps_version_number 0x43"):
raise Exception("Failed to enable test functionality")
dev[0].wait_connected(timeout=30)
hapd.request("SET wps_version_number 0x20")
+@remote_compatible
def test_ap_wps_check_pin(dev, apdev):
"""Verify PIN checking through control interface"""
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": "wps", "eap_server": "1", "wps_state": "2",
- "wpa_passphrase": "12345678", "wpa": "2",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP" })
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": "wps", "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP" })
for t in [ ("12345670", "12345670"),
("12345678", "FAIL-CHECKSUM"),
("12345", "FAIL"),
"""WPS 2.0 AP rejecting WEP configuration"""
ssid = "test-wps-config"
appin = "12345670"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "ap_pin": appin})
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "ap_pin": appin})
dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
dev[0].wps_reg(apdev[0]['bssid'], appin, "wps-new-ssid-wep", "OPEN", "WEP",
"hello", no_wait=True)
def test_ap_wps_wep_enroll(dev, apdev):
"""WPS 2.0 STA rejecting WEP configuration"""
ssid = "test-wps-wep"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "skip_cred_build": "1", "extra_cred": "wps-wep-cred" })
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ params = { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "skip_cred_build": "1", "extra_cred": "wps-wep-cred" }
+ hapd = hostapd.add_ap(apdev[0], params)
hapd.request("WPS_PBC")
dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
dev[0].request("WPS_PBC " + apdev[0]['bssid'])
if "msg=12" not in ev or "reason=2 (WEP Prohibited)" not in ev:
raise Exception("Unexpected WPS-FAIL event: " + ev)
+@remote_compatible
def test_ap_wps_ie_fragmentation(dev, apdev):
"""WPS AP using fragmented WPS IE"""
ssid = "test-wps-ie-fragmentation"
"model_name": "1234567890abcdef1234567890abcdef",
"model_number": "1234567890abcdef1234567890abcdef",
"serial_number": "1234567890abcdef1234567890abcdef" }
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
hapd.request("WPS_PBC")
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
dev[0].request("WPS_PBC " + apdev[0]['bssid'])
except:
pass
+ hapd = None
try:
with open(pskfile, "w") as f:
f.write("# WPA PSKs\n")
"wpa": "2", "wpa_key_mgmt": "WPA-PSK",
"rsn_pairwise": "CCMP", "ap_pin": appin,
"wpa_psk_file": pskfile }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
logger.info("First enrollee")
hapd.request("WPS_PBC")
raise Exception("Same PSK recorded for sta0(enrollee) and sta0(reg)")
finally:
os.remove(pskfile)
+ if hapd:
+ dev[0].request("DISCONNECT")
+ dev[1].request("DISCONNECT")
+ dev[2].request("DISCONNECT")
+ hapd.disable()
+ dev[0].flush_scan_cache()
+ dev[1].flush_scan_cache()
+ dev[2].flush_scan_cache()
def test_ap_wps_per_station_psk_failure(dev, apdev):
"""WPS PBC provisioning with per-station PSK (file not writable)"""
"wpa": "2", "wpa_key_mgmt": "WPA-PSK",
"rsn_pairwise": "CCMP", "ap_pin": appin,
"wpa_psk_file": pskfile }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
if "FAIL" in hapd.request("SET wpa_psk_file /tmp/does/not/exists/ap_wps_per_enrollee_psk_failure.psk_file"):
raise Exception("Failed to set wpa_psk_file")
pinfile = "/tmp/ap_wps_pin_request_file.log"
if os.path.exists(pinfile):
os.remove(pinfile)
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "wps_pin_requests": pinfile,
- "wpa_passphrase": "12345678", "wpa": "2",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "wps_pin_requests": pinfile,
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
uuid = dev[0].get_status_field("uuid")
pin = dev[0].wps_read_pin()
try:
f.write("ssid=wps\n")
f.write("eap_server=1\n")
f.write("wps_state=1\n")
- hostapd.add_bss('phy3', ifname, conffile)
- hapd = hostapd.Hostapd(ifname)
+ hapd = hostapd.add_bss(apdev[0], ifname, conffile)
hapd.request("WPS_PBC")
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
dev[0].request("WPS_PBC " + apdev[0]['bssid'])
if not params['long']:
raise HwsimSkip("Skip test case with long duration due to --long not specified")
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
- hapd = add_ssdp_ap(apdev[0]['ifname'], ap_uuid)
+ hapd = add_ssdp_ap(apdev[0], ap_uuid)
location = ssdp_get_location(ap_uuid)
urls = upnp_get_urls(location)
if ev is None:
raise Exception("WPS-TIMEOUT not reported")
-def add_ssdp_ap(ifname, ap_uuid):
+def add_ssdp_ap(ap, ap_uuid):
ssid = "wps-ssdp"
ap_pin = "12345670"
params = { "ssid": ssid, "eap_server": "1", "wps_state": "2",
"model_description": "Wireless Access Point",
"model_url": "http://www.example.com/model/",
"upc": "123456789012" }
- return hostapd.add_ap(ifname, params)
+ return hostapd.add_ap(ap, params)
def ssdp_send(msg, no_recv=False):
socket.setdefaulttimeout(1)
def test_ap_wps_ssdp_msearch(dev, apdev):
"""WPS AP and SSDP M-SEARCH messages"""
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
- add_ssdp_ap(apdev[0]['ifname'], ap_uuid)
+ add_ssdp_ap(apdev[0], ap_uuid)
msg = '\r\n'.join([
'M-SEARCH * HTTP/1.1',
ssdp_send_msearch("upnp:rootdevice")
ssdp_send_msearch("uuid:" + ap_uuid)
ssdp_send_msearch("urn:schemas-wifialliance-org:service:WFAWLANConfig:1")
- ssdp_send_msearch("urn:schemas-wifialliance-org:device:WFADevice:1");
+ ssdp_send_msearch("urn:schemas-wifialliance-org:device:WFADevice:1")
msg = '\r\n'.join([
'M-SEARCH * HTTP/1.1',
def test_ap_wps_ssdp_invalid_msearch(dev, apdev):
"""WPS AP and invalid SSDP M-SEARCH messages"""
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
- add_ssdp_ap(apdev[0]['ifname'], ap_uuid)
+ add_ssdp_ap(apdev[0], ap_uuid)
socket.setdefaulttimeout(1)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
def test_ap_wps_ssdp_burst(dev, apdev):
"""WPS AP and SSDP burst"""
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
- add_ssdp_ap(apdev[0]['ifname'], ap_uuid)
+ add_ssdp_ap(apdev[0], ap_uuid)
msg = '\r\n'.join([
'M-SEARCH * HTTP/1.1',
return location
def upnp_get_urls(location):
- conn = urllib.urlopen(location)
+ conn = urllib.urlopen(location, proxies={})
tree = ET.parse(conn)
root = tree.getroot()
urn = '{urn:schemas-upnp-org:device-1-0}'
res['event_sub_url'] = urlparse.urljoin(location, service.find(urn + 'eventSubURL').text)
return res
-def upnp_soap_action(conn, path, action, include_soap_action=True, soap_action_override=None):
+def upnp_soap_action(conn, path, action, include_soap_action=True,
+ soap_action_override=None, newmsg=None, neweventtype=None,
+ neweventmac=None):
soapns = 'http://schemas.xmlsoap.org/soap/envelope/'
wpsns = 'urn:schemas-wifialliance-org:service:WFAWLANConfig:1'
ET.register_namespace('soapenv', soapns)
root = ET.Element("{%s}Envelope" % soapns, attrib=attrib)
body = ET.SubElement(root, "{%s}Body" % soapns)
act = ET.SubElement(body, "{%s}%s" % (wpsns, action))
+ if newmsg:
+ msg = ET.SubElement(act, "NewMessage")
+ msg.text = base64.b64encode(newmsg)
+ if neweventtype:
+ msg = ET.SubElement(act, "NewWLANEventType")
+ msg.text = neweventtype
+ if neweventmac:
+ msg = ET.SubElement(act, "NewWLANEventMAC")
+ msg.text = neweventmac
tree = ET.ElementTree(root)
soap = StringIO.StringIO()
tree.write(soap, xml_declaration=True, encoding='utf-8')
def test_ap_wps_upnp(dev, apdev):
"""WPS AP and UPnP operations"""
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
- add_ssdp_ap(apdev[0]['ifname'], ap_uuid)
+ add_ssdp_ap(apdev[0], ap_uuid)
location = ssdp_get_location(ap_uuid)
urls = upnp_get_urls(location)
- conn = urllib.urlopen(urls['scpd_url'])
+ conn = urllib.urlopen(urls['scpd_url'], proxies={})
scpd = conn.read()
- conn = urllib.urlopen(urlparse.urljoin(location, "unknown.html"))
+ conn = urllib.urlopen(urlparse.urljoin(location, "unknown.html"),
+ proxies={})
if conn.getcode() != 404:
raise Exception("Unexpected HTTP response to GET unknown URL")
def test_ap_wps_upnp_subscribe(dev, apdev):
"""WPS AP and UPnP event subscription"""
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
- hapd = add_ssdp_ap(apdev[0]['ifname'], ap_uuid)
+ hapd = add_ssdp_ap(apdev[0], ap_uuid)
location = ssdp_get_location(ap_uuid)
urls = upnp_get_urls(location)
def test_ap_wps_upnp_subscribe_events(dev, apdev):
"""WPS AP and UPnP event subscription and many events"""
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
- hapd = add_ssdp_ap(apdev[0]['ifname'], ap_uuid)
+ hapd = add_ssdp_ap(apdev[0], ap_uuid)
location = ssdp_get_location(ap_uuid)
urls = upnp_get_urls(location)
def test_ap_wps_upnp_http_proto(dev, apdev):
"""WPS AP and UPnP/HTTP protocol testing"""
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
- add_ssdp_ap(apdev[0]['ifname'], ap_uuid)
+ add_ssdp_ap(apdev[0], ap_uuid)
location = ssdp_get_location(ap_uuid)
def test_ap_wps_upnp_http_proto_chunked(dev, apdev):
"""WPS AP and UPnP/HTTP protocol testing for chunked encoding"""
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
- add_ssdp_ap(apdev[0]['ifname'], ap_uuid)
+ add_ssdp_ap(apdev[0], ap_uuid)
location = ssdp_get_location(ap_uuid)
pass
conn.close()
+@remote_compatible
def test_ap_wps_disabled(dev, apdev):
"""WPS operations while WPS is disabled"""
ssid = "test-wps-disabled"
- hostapd.add_ap(apdev[0]['ifname'], { "ssid": ssid })
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], { "ssid": ssid })
if "FAIL" not in hapd.request("WPS_PBC"):
raise Exception("WPS_PBC succeeded unexpectedly")
if "FAIL" not in hapd.request("WPS_CANCEL"):
def test_ap_wps_mixed_cred(dev, apdev):
"""WPS 2.0 STA merging mixed mode WPA/WPA2 credentials"""
ssid = "test-wps-wep"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "skip_cred_build": "1", "extra_cred": "wps-mixed-cred" })
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ params = { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "skip_cred_build": "1", "extra_cred": "wps-mixed-cred" }
+ hapd = hostapd.add_ap(apdev[0], params)
hapd.request("WPS_PBC")
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
dev[0].request("WPS_PBC " + apdev[0]['bssid'])
if pairwise != "CCMP TKIP" and pairwise != "CCMP GCMP TKIP":
raise Exception("Unexpected merged pairwise field value: " + pairwise)
+@remote_compatible
def test_ap_wps_while_connected(dev, apdev):
"""WPS PBC provisioning while connected to another AP"""
ssid = "test-wps-conf"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "wpa_passphrase": "12345678", "wpa": "2",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
- hostapd.add_ap(apdev[1]['ifname'], { "ssid": "open" })
+ hostapd.add_ap(apdev[1], { "ssid": "open" })
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
logger.info("WPS provisioning step")
if status['bssid'] != apdev[0]['bssid']:
raise Exception("Unexpected BSSID")
+@remote_compatible
def test_ap_wps_while_connected_no_autoconnect(dev, apdev):
"""WPS PBC provisioning while connected to another AP and STA_AUTOCONNECT disabled"""
ssid = "test-wps-conf"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "wpa_passphrase": "12345678", "wpa": "2",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
- hostapd.add_ap(apdev[1]['ifname'], { "ssid": "open" })
+ hostapd.add_ap(apdev[1], { "ssid": "open" })
try:
dev[0].request("STA_AUTOCONNECT 0")
finally:
dev[0].request("STA_AUTOCONNECT 1")
+@remote_compatible
def test_ap_wps_from_event(dev, apdev):
"""WPS PBC event on AP to enable PBC"""
ssid = "test-wps-conf"
- hapd = hostapd.add_ap(apdev[0]['ifname'],
+ hapd = hostapd.add_ap(apdev[0],
{ "ssid": ssid, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
def test_ap_wps_ap_scan_2(dev, apdev):
"""AP_SCAN 2 for WPS"""
ssid = "test-wps-conf"
- hapd = hostapd.add_ap(apdev[0]['ifname'],
+ hapd = hostapd.add_ap(apdev[0],
{ "ssid": ssid, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
+ wpas.dump_monitor()
if "OK" not in wpas.request("AP_SCAN 2"):
raise Exception("Failed to set AP_SCAN 2")
wpas.flush_scan_cache()
wpas.scan_for_bss(apdev[0]['bssid'], freq="2412")
+ wpas.dump_monitor()
wpas.request("WPS_PBC " + apdev[0]['bssid'])
ev = wpas.wait_event(["WPS-SUCCESS"], timeout=15)
if ev is None:
raise Exception("WPS-SUCCESS event timed out")
wpas.wait_connected(timeout=30)
+ wpas.dump_monitor()
wpas.request("DISCONNECT")
wpas.request("BSS_FLUSH 0")
wpas.dump_monitor()
wpas.request("REASSOCIATE")
wpas.wait_connected(timeout=30)
+ wpas.dump_monitor()
+@remote_compatible
def test_ap_wps_eapol_workaround(dev, apdev):
"""EAPOL workaround code path for 802.1X header length mismatch"""
ssid = "test-wps"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "1" })
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "1" })
bssid = apdev[0]['bssid']
hapd.request("SET ext_eapol_frame_io 1")
dev[0].request("SET ext_eapol_frame_io 1")
def test_ap_wps_iteration(dev, apdev):
"""WPS PIN and iterate through APs without selected registrar"""
ssid = "test-wps-conf"
- hapd = hostapd.add_ap(apdev[0]['ifname'],
+ hapd = hostapd.add_ap(apdev[0],
{ "ssid": ssid, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
ssid2 = "test-wps-conf2"
- hapd2 = hostapd.add_ap(apdev[1]['ifname'],
+ hapd2 = hostapd.add_ap(apdev[1],
{ "ssid": ssid2, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
def test_ap_wps_iteration_error(dev, apdev):
"""WPS AP iteration on no Selected Registrar and error case with an AP"""
ssid = "test-wps-conf-pin"
- hapd = hostapd.add_ap(apdev[0]['ifname'],
+ hapd = hostapd.add_ap(apdev[0],
{ "ssid": ssid, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
# a case with an incorrectly behaving WPS AP.
# Start the real target AP and activate registrar on it.
- hapd2 = hostapd.add_ap(apdev[1]['ifname'],
+ hapd2 = hostapd.add_ap(apdev[1],
{ "ssid": ssid, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
raise Exception("No WPS-CRED-RECEIVED for the second AP")
dev[0].wait_connected(timeout=15)
+@remote_compatible
def test_ap_wps_priority(dev, apdev):
"""WPS PIN provisioning with configured AP and wps_priority"""
ssid = "test-wps-conf-pin"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "wpa_passphrase": "12345678", "wpa": "2",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
logger.info("WPS provisioning step")
pin = dev[0].wps_read_pin()
hapd.request("WPS_PIN any " + pin)
finally:
dev[0].request("SET wps_priority 0")
+@remote_compatible
def test_ap_wps_and_non_wps(dev, apdev):
"""WPS and non-WPS AP in single hostapd process"""
params = { "ssid": "wps", "eap_server": "1", "wps_state": "1" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
params = { "ssid": "no wps" }
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
appin = hapd.request("WPS_AP_PIN random")
if "FAIL" in appin:
"""Initial AP configuration and OOM during PSK generation"""
ssid = "test-wps"
params = { "ssid": ssid, "eap_server": "1", "wps_state": "1" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
with alloc_fail(hapd, 1, "base64_encode;wps_build_cred"):
pin = dev[0].wps_read_pin()
hapd.request("WPS_PIN any " + pin)
dev[0].wait_connected(timeout=30)
+@remote_compatible
def test_ap_wps_er_oom(dev, apdev):
"""WPS ER OOM in XML processing"""
try:
ssid = "wps-er-ap-config"
ap_pin = "12345670"
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
- hostapd.add_ap(apdev[0]['ifname'],
+ hostapd.add_ap(apdev[0],
{ "ssid": ssid, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
if ev is None:
raise Exception("Enrollee discovery timed out")
+@remote_compatible
def test_ap_wps_er_init_oom(dev, apdev):
"""WPS ER and OOM during init"""
try:
with alloc_fail(dev[0], 2, "http_server_init"):
if "FAIL" not in dev[0].request("WPS_ER_START ifname=lo"):
raise Exception("WPS_ER_START succeeded during OOM")
- with alloc_fail(dev[0], 1, "eloop_register_sock;wps_er_ssdp_init"):
+ with alloc_fail(dev[0], 1, "eloop_sock_table_add_sock;?eloop_register_sock;wps_er_ssdp_init"):
if "FAIL" not in dev[0].request("WPS_ER_START ifname=lo"):
raise Exception("WPS_ER_START succeeded during OOM")
with fail_test(dev[0], 1, "os_get_random;wps_er_init"):
if "FAIL" not in dev[0].request("WPS_ER_START ifname=lo"):
raise Exception("WPS_ER_START succeeded during os_get_random failure")
+@remote_compatible
def test_ap_wps_er_init_fail(dev, apdev):
"""WPS ER init failure"""
if "FAIL" not in dev[0].request("WPS_ER_START ifname=does-not-exist"):
stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
ssid = "test-wps-conf"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "wpa_passphrase": "12345678", "wpa": "2",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
prg = os.path.join(test_params['logdir'],
'alt-wpa_supplicant/wpa_supplicant/wpa_cli')
for i in range(20):
socks[i] = socket.socket(socket.AF_INET, socket.SOCK_STREAM,
socket.IPPROTO_TCP)
+ socks[i].settimeout(10)
socks[i].connect(addr)
for i in range(20):
socks[i].send("GET / HTTP/1.1\r\n\r\n")
logger.info("OOM in HTTP server")
for func in [ "http_request_init", "httpread_create",
"eloop_register_timeout;httpread_create",
- "eloop_register_sock;httpread_create",
+ "eloop_sock_table_add_sock;?eloop_register_sock;httpread_create",
"httpread_hdr_analyze" ]:
with alloc_fail(dev[0], 1, func):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM,
tests = [ (1, "http_client_url_parse"),
(1, "wpabuf_alloc;wps_er_subscribe"),
(1, "http_client_addr"),
- (1, "eloop_register_sock;http_client_addr"),
+ (1, "eloop_sock_table_add_sock;?eloop_register_sock;http_client_addr"),
(1, "eloop_register_timeout;http_client_addr") ]
for count,func in tests:
with alloc_fail(dev[0], count, func):
def _test_ap_wps_http_timeout(dev, apdev):
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
- add_ssdp_ap(apdev[0]['ifname'], ap_uuid)
+ add_ssdp_ap(apdev[0], ap_uuid)
location = ssdp_get_location(ap_uuid)
url = urlparse.urlparse(location)
appin = "12345670"
params = { "ssid": ssid, "eap_server": "1", "wps_state": "2",
"ap_pin": appin }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
pin = dev[0].wps_read_pin()
with alloc_fail(hapd, 1, "wps_init"):
dev[0].flush_scan_cache()
+@remote_compatible
def test_ap_wps_invalid_assoc_req_elem(dev, apdev):
"""WPS and invalid IE in Association Request frame"""
ssid = "test-wps"
params = { "ssid": ssid, "eap_server": "1", "wps_state": "2" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
pin = "12345670"
hapd.request("WPS_PIN any " + pin)
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
"""WPS PBC/PIN mismatch"""
ssid = "test-wps"
params = { "ssid": ssid, "eap_server": "1", "wps_state": "2" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
hapd.request("SET wps_version_number 0x10")
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
hapd.request("WPS_PBC")
hapd.request("WPS_CANCEL")
dev[0].flush_scan_cache()
+@remote_compatible
def test_ap_wps_ie_invalid(dev, apdev):
"""WPS PIN attempt with AP that has invalid WSC IE"""
ssid = "test-wps"
params = { "ssid": ssid, "eap_server": "1", "wps_state": "2",
"vendor_elements": "dd050050f20410" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
params = { 'ssid': "another", "vendor_elements": "dd050050f20410" }
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
pin = dev[0].wps_read_pin()
dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
raise Exception("Scan did not complete")
dev[0].request("WPS_CANCEL")
+@remote_compatible
def test_ap_wps_scan_prio_order(dev, apdev):
"""WPS scan priority ordering"""
ssid = "test-wps"
params = { "ssid": ssid, "eap_server": "1", "wps_state": "2" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
params = { 'ssid': "another", "vendor_elements": "dd050050f20410" }
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
pin = dev[0].wps_read_pin()
"""WPS ProbeReq IE OOM"""
ssid = "test-wps"
params = { "ssid": ssid, "eap_server": "1", "wps_state": "2" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
pin = dev[0].wps_read_pin()
hapd.request("WPS_PIN any " + pin)
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
if ev is None:
raise Exception("Association not seen")
dev[0].request("WPS_CANCEL")
+ dev[0].wait_disconnected()
with alloc_fail(dev[0], 1, "wps_ie_encapsulate"):
dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
if ev is None:
raise Exception("Association not seen")
dev[0].request("WPS_CANCEL")
+ hapd.disable()
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ time.sleep(0.2)
+ dev[0].flush_scan_cache()
def test_ap_wps_assoc_req_ie_oom(dev, apdev):
"""WPS AssocReq IE OOM"""
ssid = "test-wps"
params = { "ssid": ssid, "eap_server": "1", "wps_state": "2" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
pin = dev[0].wps_read_pin()
hapd.request("WPS_PIN any " + pin)
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
"""WPS AssocResp IE OOM"""
ssid = "test-wps"
params = { "ssid": ssid, "eap_server": "1", "wps_state": "2" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
pin = dev[0].wps_read_pin()
hapd.request("WPS_PIN any " + pin)
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
raise Exception("Association not seen")
dev[0].request("WPS_CANCEL")
+@remote_compatible
def test_ap_wps_bss_info_errors(dev, apdev):
"""WPS BSS info errors"""
params = { "ssid": "1",
"vendor_elements": "dd0e0050f20410440001ff101100010a" }
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
params = { 'ssid': "2", "vendor_elements": "dd050050f20410" }
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
bss = dev[0].get_bss(apdev[0]['bssid'])
hapd = wps_start_ap(apdev)
wps_run_pbc_fail_ap(apdev, dev, hapd)
+@remote_compatible
def test_ap_wps_pk_oom(dev, apdev):
"""WPS and public key OOM"""
with alloc_fail(dev[0], 1, "wps_build_public_key"):
wps_run_pbc_fail(apdev[0], dev[0])
+@remote_compatible
def test_ap_wps_pk_oom_ap(dev, apdev):
"""WPS and public key OOM on AP"""
hapd = wps_start_ap(apdev[0])
with alloc_fail(hapd, 1, "wps_build_public_key"):
wps_run_pbc_fail_ap(apdev[0], dev[0], hapd)
+@remote_compatible
def test_ap_wps_encr_oom_ap(dev, apdev):
"""WPS and encrypted settings decryption OOM on AP"""
hapd = wps_start_ap(apdev[0])
dev[0].request("WPS_CANCEL")
dev[0].wait_disconnected()
+@remote_compatible
def test_ap_wps_encr_no_random_ap(dev, apdev):
"""WPS and no random data available for encryption on AP"""
hapd = wps_start_ap(apdev[0])
with fail_test(hapd, 1, "os_get_random;wps_build_encr_settings"):
wps_run_pbc_fail_ap(apdev[0], dev[0], hapd)
+@remote_compatible
def test_ap_wps_e_hash_no_random_sta(dev, apdev):
"""WPS and no random data available for e-hash on STA"""
with fail_test(dev[0], 1, "os_get_random;wps_build_e_hash"):
wps_run_pbc_fail(apdev[0], dev[0])
+@remote_compatible
def test_ap_wps_m1_no_random(dev, apdev):
"""WPS and no random for M1 on STA"""
with fail_test(dev[0], 1, "os_get_random;wps_build_m1"):
wps_run_pbc_fail(apdev[0], dev[0])
+@remote_compatible
def test_ap_wps_m1_oom(dev, apdev):
"""WPS and OOM for M1 on STA"""
with alloc_fail(dev[0], 1, "wps_build_m1"):
wps_run_pbc_fail(apdev[0], dev[0])
+@remote_compatible
def test_ap_wps_m3_oom(dev, apdev):
"""WPS and OOM for M3 on STA"""
with alloc_fail(dev[0], 1, "wps_build_m3"):
wps_run_pbc_fail(apdev[0], dev[0])
+@remote_compatible
def test_ap_wps_m5_oom(dev, apdev):
"""WPS and OOM for M5 on STA"""
hapd = wps_start_ap(apdev[0])
dev[0].wait_disconnected()
dev[0].flush_scan_cache()
+@remote_compatible
def test_ap_wps_m5_no_random(dev, apdev):
"""WPS and no random for M5 on STA"""
with fail_test(dev[0], 1,
"os_get_random;wps_build_encr_settings;wps_build_m5"):
wps_run_pbc_fail(apdev[0], dev[0])
+@remote_compatible
def test_ap_wps_m7_oom(dev, apdev):
"""WPS and OOM for M7 on STA"""
hapd = wps_start_ap(apdev[0])
dev[0].wait_disconnected()
dev[0].flush_scan_cache()
+@remote_compatible
def test_ap_wps_m7_no_random(dev, apdev):
"""WPS and no random for M7 on STA"""
with fail_test(dev[0], 1,
"os_get_random;wps_build_encr_settings;wps_build_m7"):
wps_run_pbc_fail(apdev[0], dev[0])
+@remote_compatible
def test_ap_wps_wsc_done_oom(dev, apdev):
"""WPS and OOM for WSC_Done on STA"""
with alloc_fail(dev[0], 1, "wps_build_wsc_done"):
"wpa": "2", "wpa_key_mgmt": "WPA-PSK",
"rsn_pairwise": "CCMP", "ap_pin": appin,
"wpa_psk_file": pskfile }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
with fail_test(hapd, 1, "os_get_random;wps_build_cred_network_key"):
params = { "ssid": ssid, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"}
- hapd = hostapd.add_ap(apdev['ifname'], params)
+ hapd = hostapd.add_ap(apdev, params)
if pbc:
hapd.request("WPS_PBC")
"""WPS and M4 but Message Type M2D"""
wps_m4_but_other(dev[0], apdev[0], "M4/M2D", "06")
+@remote_compatible
def test_ap_wps_config_methods(dev, apdev):
"""WPS configuration method parsing"""
ssid = "test-wps-conf"
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
"config_methods": "ethernet display ext_nfc_token int_nfc_token physical_display physical_push_button" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
params = { "ssid": ssid, "eap_server": "1", "wps_state": "2",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
"config_methods": "display push_button" }
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
def test_ap_wps_set_selected_registrar_proto(dev, apdev):
"""WPS UPnP SetSelectedRegistrar protocol testing"""
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
- hapd = add_ssdp_ap(apdev[0]['ifname'], ap_uuid)
+ hapd = add_ssdp_ap(apdev[0], ap_uuid)
location = ssdp_get_location(ap_uuid)
urls = upnp_get_urls(location)
def test_ap_wps_adv_oom(dev, apdev):
"""WPS AP and advertisement OOM"""
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
- hapd = add_ssdp_ap(apdev[0]['ifname'], ap_uuid)
+ hapd = add_ssdp_ap(apdev[0], ap_uuid)
with alloc_fail(hapd, 1, "=msearchreply_state_machine_start"):
ssdp_send_msearch("urn:schemas-wifialliance-org:service:WFAWLANConfig:1",
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
"ap_pin": appin }
- hapd = hostapd.add_ap(apdev['ifname'], params)
+ hapd = hostapd.add_ap(apdev, params)
dev.scan_for_bss(bssid, freq="2412")
hapd.request("SET ext_eapol_frame_io 1")
ap_settings += build_wsc_attr(ATTR_MAC_ADDR, binascii.unhexlify(apdev[0]['bssid'].replace(':', '')))
wps_run_ap_settings_proto(dev, apdev, ap_settings, True)
+@remote_compatible
def test_wps_ext_ap_settings_missing(dev, apdev):
"""WPS and AP Settings: missing"""
wps_run_ap_settings_proto(dev, apdev, None, False)
+@remote_compatible
def test_wps_ext_ap_settings_mac_addr_mismatch(dev, apdev):
"""WPS and AP Settings: MAC Address mismatch"""
ap_settings = build_wsc_attr(ATTR_NETWORK_INDEX, '\x01')
ap_settings += build_wsc_attr(ATTR_MAC_ADDR, '\x00\x00\x00\x00\x00\x00')
wps_run_ap_settings_proto(dev, apdev, ap_settings, True)
+@remote_compatible
def test_wps_ext_ap_settings_mac_addr_missing(dev, apdev):
"""WPS and AP Settings: missing MAC Address"""
ap_settings = build_wsc_attr(ATTR_NETWORK_INDEX, '\x01')
ap_settings += build_wsc_attr(ATTR_NETWORK_KEY, '')
wps_run_ap_settings_proto(dev, apdev, ap_settings, False)
+@remote_compatible
def test_wps_ext_ap_settings_reject_encr_type(dev, apdev):
"""WPS and AP Settings: reject Encr Type"""
ap_settings = build_wsc_attr(ATTR_NETWORK_INDEX, '\x01')
ap_settings += build_wsc_attr(ATTR_MAC_ADDR, binascii.unhexlify(apdev[0]['bssid'].replace(':', '')))
wps_run_ap_settings_proto(dev, apdev, ap_settings, False)
+@remote_compatible
def test_wps_ext_ap_settings_m2d(dev, apdev):
"""WPS and AP Settings: M2D"""
addr,bssid,hapd = wps_start_ext_reg(apdev[0], dev[0])
send_wsc_msg(hapd, dev.own_addr(), nack)
dev.wait_disconnected()
+@remote_compatible
def test_wps_ext_m3_missing_e_hash1(dev, apdev):
"""WPS proto: M3 missing E-Hash1"""
pin = "12345670"
wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
+@remote_compatible
def test_wps_ext_m3_missing_e_hash2(dev, apdev):
"""WPS proto: M3 missing E-Hash2"""
pin = "12345670"
wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
+@remote_compatible
def test_wps_ext_m5_missing_e_snonce1(dev, apdev):
"""WPS proto: M5 missing E-SNonce1"""
pin = "12345670"
wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
+@remote_compatible
def test_wps_ext_m5_e_snonce1_mismatch(dev, apdev):
"""WPS proto: M5 E-SNonce1 mismatch"""
pin = "12345670"
wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
+@remote_compatible
def test_wps_ext_m7_e_snonce2_mismatch(dev, apdev):
"""WPS proto: M7 E-SNonce2 mismatch"""
pin = "12345670"
wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
+@remote_compatible
def test_wps_ext_m1_pubkey_oom(dev, apdev):
"""WPS proto: M1 PubKey OOM"""
pin = "12345670"
raise Exception("EAP-Failure not reported")
dev.wait_disconnected()
+@remote_compatible
def test_wps_ext_m3_m1(dev, apdev):
"""WPS proto: M3 replaced with M1"""
pin = "12345670"
wps_wait_eap_failure(hapd, dev[0])
+@remote_compatible
def test_wps_ext_m5_m3(dev, apdev):
"""WPS proto: M5 replaced with M3"""
pin = "12345670"
wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
+@remote_compatible
def test_wps_ext_m3_m2(dev, apdev):
"""WPS proto: M3 replaced with M2"""
pin = "12345670"
wps_wait_eap_failure(hapd, dev[0])
+@remote_compatible
def test_wps_ext_m3_m5(dev, apdev):
"""WPS proto: M3 replaced with M5"""
pin = "12345670"
wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
+@remote_compatible
def test_wps_ext_m3_m7(dev, apdev):
"""WPS proto: M3 replaced with M7"""
pin = "12345670"
wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
+@remote_compatible
def test_wps_ext_m3_done(dev, apdev):
"""WPS proto: M3 replaced with WSC_Done"""
pin = "12345670"
wps_wait_eap_failure(hapd, dev[0])
+@remote_compatible
def test_wps_ext_m2_nack_invalid(dev, apdev):
"""WPS proto: M2 followed by invalid NACK"""
pin = "12345670"
wps_wait_eap_failure(hapd, dev[0])
+@remote_compatible
def test_wps_ext_m2_nack_no_msg_type(dev, apdev):
"""WPS proto: M2 followed by NACK without Msg Type"""
pin = "12345670"
wps_wait_eap_failure(hapd, dev[0])
+@remote_compatible
def test_wps_ext_m2_nack_invalid_msg_type(dev, apdev):
"""WPS proto: M2 followed by NACK with invalid Msg Type"""
pin = "12345670"
wps_wait_eap_failure(hapd, dev[0])
+@remote_compatible
def test_wps_ext_m2_nack_e_nonce_mismatch(dev, apdev):
"""WPS proto: M2 followed by NACK with e-nonce mismatch"""
pin = "12345670"
wps_wait_eap_failure(hapd, dev[0])
+@remote_compatible
def test_wps_ext_m2_nack_no_config_error(dev, apdev):
"""WPS proto: M2 followed by NACK without Config Error"""
pin = "12345670"
wps_wait_eap_failure(hapd, dev[0])
+@remote_compatible
def test_wps_ext_m2_ack_invalid(dev, apdev):
"""WPS proto: M2 followed by invalid ACK"""
pin = "12345670"
wps_wait_eap_failure(hapd, dev[0])
+@remote_compatible
def test_wps_ext_m2_ack(dev, apdev):
"""WPS proto: M2 followed by ACK"""
pin = "12345670"
wps_wait_eap_failure(hapd, dev[0])
+@remote_compatible
def test_wps_ext_m2_ack_no_msg_type(dev, apdev):
"""WPS proto: M2 followed by ACK missing Msg Type"""
pin = "12345670"
wps_wait_eap_failure(hapd, dev[0])
+@remote_compatible
def test_wps_ext_m2_ack_invalid_msg_type(dev, apdev):
"""WPS proto: M2 followed by ACK with invalid Msg Type"""
pin = "12345670"
wps_wait_eap_failure(hapd, dev[0])
+@remote_compatible
def test_wps_ext_m2_ack_e_nonce_mismatch(dev, apdev):
"""WPS proto: M2 followed by ACK with e-nonce mismatch"""
pin = "12345670"
wps_wait_eap_failure(hapd, dev[0])
+@remote_compatible
def test_wps_ext_m1_invalid(dev, apdev):
"""WPS proto: M1 failing parsing"""
pin = "12345670"
msg, m8_attrs, raw_m8_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M8)
return hapd, msg, e_nonce, r_nonce
+@remote_compatible
def test_wps_ext_wsc_done_invalid(dev, apdev):
"""WPS proto: invalid WSC_Done"""
hapd, msg, e_nonce, r_nonce = wps_ext_wsc_done(dev, apdev)
wps_wait_eap_failure(hapd, dev[0])
+@remote_compatible
def test_wps_ext_wsc_done_no_msg_type(dev, apdev):
"""WPS proto: invalid WSC_Done"""
hapd, msg, e_nonce, r_nonce = wps_ext_wsc_done(dev, apdev)
wps_wait_eap_failure(hapd, dev[0])
+@remote_compatible
def test_wps_ext_wsc_done_wrong_msg_type(dev, apdev):
"""WPS proto: WSC_Done with wrong Msg Type"""
hapd, msg, e_nonce, r_nonce = wps_ext_wsc_done(dev, apdev)
wps_wait_eap_failure(hapd, dev[0])
+@remote_compatible
def test_wps_ext_wsc_done_no_e_nonce(dev, apdev):
"""WPS proto: WSC_Done without e_nonce"""
hapd, msg, e_nonce, r_nonce = wps_ext_wsc_done(dev, apdev)
wps_wait_eap_failure(hapd, dev[0])
+@remote_compatible
def test_wps_ext_m7_no_encr_settings(dev, apdev):
"""WPS proto: M7 without Encr Settings"""
pin = "12345670"
wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
+@remote_compatible
def test_wps_ext_m1_workaround(dev, apdev):
"""WPS proto: M1 Manufacturer/Model workaround"""
pin = "12345670"
logger.debug("Receive M2 from AP")
msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
+@remote_compatible
def test_ap_wps_disable_enable(dev, apdev):
"""WPS and DISABLE/ENABLE AP"""
hapd = wps_start_ap(apdev[0])
hapd.disable()
hapd.enable()
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
+
+def test_ap_wps_upnp_web_oom(dev, apdev, params):
+ """hostapd WPS UPnP web OOM"""
+ ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
+ hapd = add_ssdp_ap(apdev[0], ap_uuid)
+
+ location = ssdp_get_location(ap_uuid)
+ url = urlparse.urlparse(location)
+ urls = upnp_get_urls(location)
+ eventurl = urlparse.urlparse(urls['event_sub_url'])
+ ctrlurl = urlparse.urlparse(urls['control_url'])
+
+ conn = httplib.HTTPConnection(url.netloc)
+ with alloc_fail(hapd, 1, "web_connection_parse_get"):
+ conn.request("GET", "/wps_device.xml")
+ try:
+ resp = conn.getresponse()
+ except:
+ pass
+
+ conn = httplib.HTTPConnection(url.netloc)
+ conn.request("GET", "/unknown")
+ resp = conn.getresponse()
+ if resp.status != 404:
+ raise Exception("Unexpected HTTP result for unknown URL: %d" + resp.status)
+
+ with alloc_fail(hapd, 1, "web_connection_parse_get"):
+ conn.request("GET", "/unknown")
+ try:
+ resp = conn.getresponse()
+ print resp.status
+ except:
+ pass
+
+ conn = httplib.HTTPConnection(url.netloc)
+ conn.request("GET", "/wps_device.xml")
+ resp = conn.getresponse()
+ if resp.status != 200:
+ raise Exception("GET /wps_device.xml failed")
+
+ conn = httplib.HTTPConnection(url.netloc)
+ resp = upnp_soap_action(conn, ctrlurl.path, "GetDeviceInfo")
+ if resp.status != 200:
+ raise Exception("GetDeviceInfo failed")
+
+ with alloc_fail(hapd, 1, "web_process_get_device_info"):
+ conn = httplib.HTTPConnection(url.netloc)
+ resp = upnp_soap_action(conn, ctrlurl.path, "GetDeviceInfo")
+ if resp.status != 500:
+ raise Exception("Internal error not reported from GetDeviceInfo OOM")
+
+ with alloc_fail(hapd, 1, "wps_build_m1;web_process_get_device_info"):
+ conn = httplib.HTTPConnection(url.netloc)
+ resp = upnp_soap_action(conn, ctrlurl.path, "GetDeviceInfo")
+ if resp.status != 500:
+ raise Exception("Internal error not reported from GetDeviceInfo OOM")
+
+ with alloc_fail(hapd, 1, "wpabuf_alloc;web_connection_send_reply"):
+ conn = httplib.HTTPConnection(url.netloc)
+ try:
+ resp = upnp_soap_action(conn, ctrlurl.path, "GetDeviceInfo")
+ except:
+ pass
+
+ conn = httplib.HTTPConnection(url.netloc)
+ resp = upnp_soap_action(conn, ctrlurl.path, "GetDeviceInfo")
+ if resp.status != 200:
+ raise Exception("GetDeviceInfo failed")
+
+ # No NewWLANEventType in PutWLANResponse NewMessage
+ conn = httplib.HTTPConnection(url.netloc)
+ resp = upnp_soap_action(conn, ctrlurl.path, "PutWLANResponse", newmsg="foo")
+ if resp.status != 600:
+ raise Exception("Unexpected HTTP response: %d" % resp.status)
+
+ # No NewWLANEventMAC in PutWLANResponse NewMessage
+ conn = httplib.HTTPConnection(url.netloc)
+ resp = upnp_soap_action(conn, ctrlurl.path, "PutWLANResponse",
+ newmsg="foo", neweventtype="1")
+ if resp.status != 600:
+ raise Exception("Unexpected HTTP response: %d" % resp.status)
+
+ # Invalid NewWLANEventMAC in PutWLANResponse NewMessage
+ conn = httplib.HTTPConnection(url.netloc)
+ resp = upnp_soap_action(conn, ctrlurl.path, "PutWLANResponse",
+ newmsg="foo", neweventtype="1",
+ neweventmac="foo")
+ if resp.status != 600:
+ raise Exception("Unexpected HTTP response: %d" % resp.status)
+
+ # Workaround for NewWLANEventMAC in PutWLANResponse NewMessage
+ # Ignored unexpected PutWLANResponse WLANEventType 1
+ conn = httplib.HTTPConnection(url.netloc)
+ resp = upnp_soap_action(conn, ctrlurl.path, "PutWLANResponse",
+ newmsg="foo", neweventtype="1",
+ neweventmac="00.11.22.33.44.55")
+ if resp.status != 500:
+ raise Exception("Unexpected HTTP response: %d" % resp.status)
+
+ # PutWLANResponse NewMessage with invalid EAP message
+ conn = httplib.HTTPConnection(url.netloc)
+ resp = upnp_soap_action(conn, ctrlurl.path, "PutWLANResponse",
+ newmsg="foo", neweventtype="2",
+ neweventmac="00:11:22:33:44:55")
+ if resp.status != 200:
+ raise Exception("Unexpected HTTP response: %d" % resp.status)
+
+ with alloc_fail(hapd, 1, "web_connection_parse_subscribe"):
+ conn = httplib.HTTPConnection(url.netloc)
+ headers = { "callback": '<http://127.0.0.1:12345/event>',
+ "NT": "upnp:event",
+ "timeout": "Second-1234" }
+ conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
+ try:
+ resp = conn.getresponse()
+ except:
+ pass
+
+ with alloc_fail(hapd, 1, "dup_binstr;web_connection_parse_subscribe"):
+ conn = httplib.HTTPConnection(url.netloc)
+ headers = { "callback": '<http://127.0.0.1:12345/event>',
+ "NT": "upnp:event",
+ "timeout": "Second-1234" }
+ conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
+ resp = conn.getresponse()
+ if resp.status != 500:
+ raise Exception("Unexpected HTTP response: %d" % resp.status)
+
+ with alloc_fail(hapd, 1, "wpabuf_alloc;web_connection_parse_unsubscribe"):
+ conn = httplib.HTTPConnection(url.netloc)
+ headers = { "callback": '<http://127.0.0.1:12345/event>',
+ "NT": "upnp:event",
+ "timeout": "Second-1234" }
+ conn.request("UNSUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
+ try:
+ resp = conn.getresponse()
+ except:
+ pass
+
+ with alloc_fail(hapd, 1, "web_connection_unimplemented"):
+ conn = httplib.HTTPConnection(url.netloc)
+ conn.request("HEAD", "/wps_device.xml")
+ try:
+ resp = conn.getresponse()
+ except:
+ pass
+
+def test_ap_wps_frag_ack_oom(dev, apdev):
+ """WPS and fragment ack OOM"""
+ dev[0].request("SET wps_fragment_size 50")
+ hapd = wps_start_ap(apdev[0])
+ with alloc_fail(hapd, 1, "eap_wsc_build_frag_ack"):
+ wps_run_pbc_fail_ap(apdev[0], dev[0], hapd)
+
+def wait_scan_stopped(dev):
+ dev.request("ABORT_SCAN")
+ for i in range(50):
+ res = dev.get_driver_status_field("scan_state")
+ if "SCAN_STARTED" not in res and "SCAN_REQUESTED" not in res:
+ break
+ logger.debug("Waiting for scan to complete")
+ time.sleep(0.1)
+
+@remote_compatible
+def test_ap_wps_eap_wsc_errors(dev, apdev):
+ """WPS and EAP-WSC error cases"""
+ ssid = "test-wps-conf-pin"
+ appin = "12345670"
+ params = { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
+ "fragment_size": "300", "ap_pin": appin }
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+
+ pin = dev[0].wps_read_pin()
+ hapd.request("WPS_PIN any " + pin)
+ dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
+ dev[0].dump_monitor()
+
+ dev[0].wps_reg(bssid, appin + " new_ssid=a", "new ssid", "WPA2PSK", "CCMP",
+ "new passphrase", no_wait=True)
+ ev = dev[0].wait_event(["WPS-FAIL"], timeout=10)
+ if ev is None:
+ raise Exception("WPS-FAIL not reported")
+ dev[0].request("WPS_CANCEL")
+ dev[0].wait_disconnected()
+ wait_scan_stopped(dev[0])
+ dev[0].dump_monitor()
+
+ dev[0].wps_reg(bssid, appin, "new ssid", "FOO", "CCMP",
+ "new passphrase", no_wait=True)
+ ev = dev[0].wait_event(["WPS-FAIL"], timeout=10)
+ if ev is None:
+ raise Exception("WPS-FAIL not reported")
+ dev[0].request("WPS_CANCEL")
+ dev[0].wait_disconnected()
+ wait_scan_stopped(dev[0])
+ dev[0].dump_monitor()
+
+ dev[0].wps_reg(bssid, appin, "new ssid", "WPA2PSK", "FOO",
+ "new passphrase", no_wait=True)
+ ev = dev[0].wait_event(["WPS-FAIL"], timeout=10)
+ if ev is None:
+ raise Exception("WPS-FAIL not reported")
+ dev[0].request("WPS_CANCEL")
+ dev[0].wait_disconnected()
+ wait_scan_stopped(dev[0])
+ dev[0].dump_monitor()
+
+ dev[0].wps_reg(bssid, appin + "new_key=a", "new ssid", "WPA2PSK", "CCMP",
+ "new passphrase", no_wait=True)
+ ev = dev[0].wait_event(["WPS-FAIL"], timeout=10)
+ if ev is None:
+ raise Exception("WPS-FAIL not reported")
+ dev[0].request("WPS_CANCEL")
+ dev[0].wait_disconnected()
+ wait_scan_stopped(dev[0])
+ dev[0].dump_monitor()
+
+ tests = [ "eap_wsc_init",
+ "eap_msg_alloc;eap_wsc_build_msg",
+ "wpabuf_alloc;eap_wsc_process_fragment" ]
+ for func in tests:
+ with alloc_fail(dev[0], 1, func):
+ dev[0].request("WPS_PIN %s %s" % (bssid, pin))
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("WPS_CANCEL")
+ dev[0].wait_disconnected()
+ wait_scan_stopped(dev[0])
+ dev[0].dump_monitor()
+
+ with alloc_fail(dev[0], 1, "eap_msg_alloc;eap_sm_build_expanded_nak"):
+ dev[0].wps_reg(bssid, appin + " new_ssid=a", "new ssid", "WPA2PSK",
+ "CCMP", "new passphrase", no_wait=True)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("WPS_CANCEL")
+ dev[0].wait_disconnected()
+ wait_scan_stopped(dev[0])
+ dev[0].dump_monitor()
+
+def test_ap_wps_eap_wsc(dev, apdev):
+ """WPS and EAP-WSC in network profile"""
+ params = int_eap_server_params()
+ params["wps_state"] = "2"
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+
+ logger.info("Unexpected identity")
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="WSC", identity="WFA-SimpleConfig-Enrollee-unexpected",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
+ if ev is None:
+ raise Exception("No EAP-Failure seen")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ logger.info("No phase1 parameter")
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="WSC", identity="WFA-SimpleConfig-Enrollee-1-0",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP method start")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
+ if ev is None:
+ raise Exception("No EAP-Failure seen")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ logger.info("No PIN/PBC in phase1")
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="WSC", identity="WFA-SimpleConfig-Enrollee-1-0",
+ phase1="foo", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP method start")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
+ if ev is None:
+ raise Exception("No EAP-Failure seen")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ logger.info("Invalid pkhash in phase1")
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="WSC", identity="WFA-SimpleConfig-Enrollee-1-0",
+ phase1="foo pkhash=q pbc=1", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP method start")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
+ if ev is None:
+ raise Exception("No EAP-Failure seen")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ logger.info("Zero fragment_size")
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="WSC", identity="WFA-SimpleConfig-Enrollee-1-0",
+ fragment_size="0", phase1="pin=12345670", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP method start")
+ ev = dev[0].wait_event(["WPS-M2D"], timeout=5)
+ if ev is None:
+ raise Exception("No M2D seen")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
+ if ev is None:
+ raise Exception("No EAP-Failure seen")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ logger.info("Missing new_auth")
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="WSC", identity="WFA-SimpleConfig-Enrollee-1-0",
+ phase1="pin=12345670 new_ssid=aa", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP method start")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
+ if ev is None:
+ raise Exception("No EAP-Failure seen")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ logger.info("Missing new_encr")
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="WSC", identity="WFA-SimpleConfig-Enrollee-1-0",
+ phase1="pin=12345670 new_auth=WPA2PSK new_ssid=aa", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP method start")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
+ if ev is None:
+ raise Exception("No EAP-Failure seen")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ logger.info("Missing new_key")
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="WSC", identity="WFA-SimpleConfig-Enrollee-1-0",
+ phase1="pin=12345670 new_auth=WPA2PSK new_ssid=aa new_encr=CCMP",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP method start")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
+ if ev is None:
+ raise Exception("No EAP-Failure seen")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+def test_ap_wps_and_bss_limit(dev, apdev):
+ """WPS and wpa_supplicant BSS entry limit"""
+ try:
+ _test_ap_wps_and_bss_limit(dev, apdev)
+ finally:
+ dev[0].request("SET bss_max_count 200")
+ pass
+
+def _test_ap_wps_and_bss_limit(dev, apdev):
+ params = { "ssid": "test-wps", "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP" }
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ params = { "ssid": "test-wps-2", "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "1234567890", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP" }
+ hapd2 = hostapd.add_ap(apdev[1], params)
+
+ id = dev[1].add_network()
+ dev[1].set_network(id, "mode", "2")
+ dev[1].set_network_quoted(id, "ssid", "wpas-ap-no-wps")
+ dev[1].set_network_quoted(id, "psk", "12345678")
+ dev[1].set_network(id, "frequency", "2462")
+ dev[1].set_network(id, "scan_freq", "2462")
+ dev[1].set_network(id, "wps_disabled", "1")
+ dev[1].select_network(id)
+
+ id = dev[2].add_network()
+ dev[2].set_network(id, "mode", "2")
+ dev[2].set_network_quoted(id, "ssid", "wpas-ap")
+ dev[2].set_network_quoted(id, "psk", "12345678")
+ dev[2].set_network(id, "frequency", "2437")
+ dev[2].set_network(id, "scan_freq", "2437")
+ dev[2].select_network(id)
+
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add("wlan5")
+ id = wpas.add_network()
+ wpas.set_network(id, "mode", "2")
+ wpas.set_network_quoted(id, "ssid", "wpas-ap")
+ wpas.set_network_quoted(id, "psk", "12345678")
+ wpas.set_network(id, "frequency", "2437")
+ wpas.set_network(id, "scan_freq", "2437")
+ wpas.select_network(id)
+
+ dev[1].wait_connected()
+ dev[2].wait_connected()
+ wpas.wait_connected()
+ wpas.request("WPS_PIN any 12345670")
+
+ hapd.request("WPS_PBC")
+ hapd2.request("WPS_PBC")
+
+ dev[0].request("SET bss_max_count 1")
+
+ id = dev[0].add_network()
+ dev[0].set_network_quoted(id, "ssid", "testing")
+
+ id = dev[0].add_network()
+ dev[0].set_network_quoted(id, "ssid", "testing")
+ dev[0].set_network(id, "key_mgmt", "WPS")
+
+ dev[0].request("WPS_PBC")
+ ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
+ dev[0].request("WPS_CANCEL")
+
+ id = dev[0].add_network()
+ dev[0].set_network_quoted(id, "ssid", "testing")
+ dev[0].set_network(id, "key_mgmt", "WPS")
+
+ dev[0].scan(freq="2412")
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import time
import logging
logger = logging.getLogger()
def test_autoscan_periodic(dev, apdev):
"""autoscan_periodic"""
- hostapd.add_ap(apdev[0]['ifname'], { "ssid": "autoscan" })
+ hostapd.add_ap(apdev[0], { "ssid": "autoscan" })
try:
if "OK" not in dev[0].request("AUTOSCAN periodic:1"):
finally:
dev[0].request("AUTOSCAN ")
+@remote_compatible
def test_autoscan_exponential(dev, apdev):
"""autoscan_exponential"""
- hostapd.add_ap(apdev[0]['ifname'], { "ssid": "autoscan" })
+ hostapd.add_ap(apdev[0], { "ssid": "autoscan" })
try:
if "OK" not in dev[0].request("AUTOSCAN exponential:2:10"):
def test_bgscan_simple(dev, apdev):
"""bgscan_simple"""
- hostapd.add_ap(apdev[0]['ifname'], { "ssid": "bgscan" })
- hostapd.add_ap(apdev[1]['ifname'], { "ssid": "bgscan" })
+ hostapd.add_ap(apdev[0], { "ssid": "bgscan" })
+ hostapd.add_ap(apdev[1], { "ssid": "bgscan" })
dev[0].connect("bgscan", key_mgmt="NONE", scan_freq="2412",
bgscan="simple:1:-20:2")
def test_bgscan_learn(dev, apdev):
"""bgscan_learn"""
- hostapd.add_ap(apdev[0]['ifname'], { "ssid": "bgscan" })
- hostapd.add_ap(apdev[1]['ifname'], { "ssid": "bgscan" })
+ hostapd.add_ap(apdev[0], { "ssid": "bgscan" })
+ hostapd.add_ap(apdev[1], { "ssid": "bgscan" })
try:
os.remove("/tmp/test_bgscan_learn.bgscan")
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import logging
logger = logging.getLogger()
import binascii
import os
-import subprocess
import time
import hostapd
import hwsim_utils
from tshark import run_tshark
from nl80211 import *
+from wpasupplicant import WpaSupplicant
def nl80211_command(dev, cmd, attr):
res = dev.request("VENDOR ffffffff {} {}".format(nl80211_cmd[cmd],
raise Exception("nl80211 command failed")
return binascii.unhexlify(res)
+@remote_compatible
def test_cfg80211_disassociate(dev, apdev):
"""cfg80211 disassociation command"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
if ev is None:
def test_cfg80211_tx_frame(dev, apdev, params):
"""cfg80211 offchannel TX frame command"""
- ifindex = int(dev[0].get_driver_status_field("ifindex"))
-
- frame = binascii.unhexlify("d000000002000000010002000000000002000000010000000409506f9a090001dd5e506f9a0902020025080401001f0502006414060500585804510b0906000200000000000b1000585804510b0102030405060708090a0b0d1d000200000000000108000000000000000000101100084465766963652041110500585804510bdd190050f204104a0001101012000200011049000600372a000120")
- dev[0].request("P2P_GROUP_ADD freq=2412")
- res = nl80211_frame(dev[0], ifindex, frame, freq=2422, duration=500,
+ dev[0].p2p_start_go(freq='2412')
+ go = WpaSupplicant(dev[0].group_ifname)
+ frame = binascii.unhexlify("d0000000020000000100" + go.own_addr().translate(None, ':') + "02000000010000000409506f9a090001dd5e506f9a0902020025080401001f0502006414060500585804510b0906000200000000000b1000585804510b0102030405060708090a0b0d1d000200000000000108000000000000000000101100084465766963652041110500585804510bdd190050f204104a0001101012000200011049000600372a000120")
+ ifindex = int(go.get_driver_status_field("ifindex"))
+ res = nl80211_frame(go, ifindex, frame, freq=2422, duration=500,
offchannel_tx_ok=True)
time.sleep(0.1)
#nl80211_frame_wait_cancel(dev[0], ifindex, res[nl80211_attr['COOKIE']])
# note: this Action frame ends up getting sent incorrectly on 2422 MHz
- nl80211_frame(dev[0], ifindex, frame, freq=2412)
+ nl80211_frame(go, ifindex, frame, freq=2412)
time.sleep(1.5)
# note: also the Deauthenticate frame sent by the GO going down ends up
# being transmitted incorrectly on 2422 MHz.
+ del go
+
out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"),
"wlan.fc.type_subtype == 13", ["radiotap.channel.freq"])
if out is not None:
if freq[1] != "2412":
raise Exception("Second Action frame on unexpected channel: %s MHz" % freq[1])
+@remote_compatible
def test_cfg80211_wep_key_idx_change(dev, apdev):
"""WEP Shared Key authentication and key index change without deauth"""
- hapd = hostapd.add_ap(apdev[0]['ifname'],
+ hapd = hostapd.add_ap(apdev[0],
{ "ssid": "wep-shared-key",
"wep_key0": '"hello12345678"',
"wep_key1": '"other12345678"',
dev[0].wait_connected(timeout=10, error="Reassociation timed out")
hwsim_utils.test_connectivity(dev[0], hapd)
+@remote_compatible
def test_cfg80211_hostapd_ext_sta_remove(dev, apdev):
"""cfg80211 DEL_STATION issued externally to hostapd"""
- hapd = hostapd.add_ap(apdev[0]['ifname'],
+ hapd = hostapd.add_ap(apdev[0],
{ "ssid": "open" })
id = dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
import hwsim_utils
import hostapd
from wpasupplicant import WpaSupplicant
-from test_p2p_grpform import go_neg_pin_authorized
-from test_p2p_grpform import check_grpform_results
-from test_p2p_grpform import remove_group
+from p2p_utils import *
def test_connect_cmd_open(dev, apdev):
"""Open connection using cfg80211 connect command"""
params = { "ssid": "sta-connect",
"manage_p2p": "1",
"allow_cross_connection": "1" }
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
wpas.connect("sta-connect", key_mgmt="NONE", scan_freq="2412",
bg_scan_period="1")
+ wpas.dump_monitor()
wpas.request("DISCONNECT")
+ wpas.wait_disconnected()
+ wpas.dump_monitor()
def test_connect_cmd_wep(dev, apdev):
"""WEP Open System using cfg80211 connect command"""
params = { "ssid": "sta-connect-wep", "wep_key0": '"hello"' }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
wpas.connect("sta-connect-wep", key_mgmt="NONE", scan_freq="2412",
wep_key0='"hello"')
+ wpas.dump_monitor()
hwsim_utils.test_connectivity(wpas, hapd)
wpas.request("DISCONNECT")
+ wpas.wait_disconnected()
+ wpas.dump_monitor()
def test_connect_cmd_wep_shared(dev, apdev):
"""WEP Shared key using cfg80211 connect command"""
params = { "ssid": "sta-connect-wep", "wep_key0": '"hello"',
"auth_algs": "2" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
id = wpas.connect("sta-connect-wep", key_mgmt="NONE", scan_freq="2412",
auth_alg="SHARED", wep_key0='"hello"')
+ wpas.dump_monitor()
hwsim_utils.test_connectivity(wpas, hapd)
wpas.request("DISCONNECT")
wpas.remove_network(id)
wpas.connect("sta-connect-wep", key_mgmt="NONE", scan_freq="2412",
auth_alg="OPEN SHARED", wep_key0='"hello"')
+ wpas.dump_monitor()
hwsim_utils.test_connectivity(wpas, hapd)
wpas.request("DISCONNECT")
+ wpas.wait_disconnected()
+ wpas.dump_monitor()
def test_connect_cmd_p2p_management(dev, apdev):
"""Open connection using cfg80211 connect command and AP using P2P management"""
params = { "ssid": "sta-connect",
"manage_p2p": "1",
"allow_cross_connection": "0" }
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
wpas.connect("sta-connect", key_mgmt="NONE", scan_freq="2412")
+ wpas.dump_monitor()
wpas.request("DISCONNECT")
+ wpas.wait_disconnected()
+ wpas.dump_monitor()
def test_connect_cmd_wpa2_psk(dev, apdev):
"""WPA2-PSK connection using cfg80211 connect command"""
params = hostapd.wpa2_params(ssid="sta-connect", passphrase="12345678")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
wpas.connect("sta-connect", psk="12345678", scan_freq="2412")
+ wpas.dump_monitor()
wpas.request("DISCONNECT")
+ wpas.wait_disconnected()
+ wpas.dump_monitor()
def test_connect_cmd_concurrent_grpform_while_connecting(dev, apdev):
"""Concurrent P2P group formation while connecting to an AP using cfg80211 connect command"""
logger.info("Start connection to an infrastructure AP")
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-open" })
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
wpas.connect("test-open", key_mgmt="NONE", wait_connect=False)
+ wpas.dump_monitor()
logger.info("Form a P2P group while connecting to an AP")
wpas.request("SET p2p_no_group_iface 0")
r_dev=wpas, r_freq=2412)
check_grpform_results(i_res, r_res)
remove_group(dev[0], wpas)
+ wpas.dump_monitor()
logger.info("Confirm AP connection after P2P group removal")
hwsim_utils.test_connectivity(wpas, hapd)
+ wpas.request("DISCONNECT")
+ wpas.wait_disconnected()
+ wpas.dump_monitor()
+
def test_connect_cmd_reject_assoc(dev, apdev):
"""Connection using cfg80211 connect command getting rejected"""
params = { "ssid": "sta-connect",
"require_ht": "1" }
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
if "status_code=27" not in ev:
raise Exception("Unexpected rejection status code")
+ wpas.request("DISCONNECT")
+ wpas.dump_monitor()
+
def test_connect_cmd_disconnect_event(dev, apdev):
"""Connection using cfg80211 connect command getting disconnected by the AP"""
params = { "ssid": "sta-connect" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
# testing purposes. Anyway, wait some time to allow the debug log to capture
# the following NL80211_CMD_DISCONNECT event.
time.sleep(0.1)
+ wpas.dump_monitor()
+
+ # Clean up to avoid causing issue for following test cases
+ wpas.request("REMOVE_NETWORK all")
+ wpas.wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=2)
+ wpas.flush_scan_cache()
+ wpas.dump_monitor()
+ wpas.interface_remove("wlan5")
+ del wpas
def test_connect_cmd_roam(dev, apdev):
"""cfg80211 connect command to trigger roam"""
params = { "ssid": "sta-connect" }
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
wpas.connect("sta-connect", key_mgmt="NONE", scan_freq="2412")
+ wpas.dump_monitor()
- hostapd.add_ap(apdev[1]['ifname'], params)
- wpas.scan_for_bss(apdev[1]['bssid'], freq=2412)
+ hostapd.add_ap(apdev[1], params)
+ wpas.scan_for_bss(apdev[1]['bssid'], freq=2412, force_scan=True)
wpas.roam(apdev[1]['bssid'])
+ time.sleep(0.1)
+ wpas.request("DISCONNECT")
+ wpas.wait_disconnected()
+ wpas.dump_monitor()
import hostapd
from wpasupplicant import WpaSupplicant
from utils import HwsimSkip, alloc_fail, fail_test
+from p2p_utils import *
from test_ap_tdls import connect_2sta_open
+from test_ap_eap import check_altsubject_match_support
WPAS_DBUS_SERVICE = "fi.w1.wpa_supplicant1"
WPAS_DBUS_PATH = "/fi/w1/wpa_supplicant1"
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
"ap_pin": "12345670", "uuid": ap_uuid}
- return hostapd.add_ap(ap['ifname'], params)
+ return hostapd.add_ap(ap, params)
def test_dbus_getall(dev, apdev):
"""D-Bus GetAll"""
if len(res) != 0:
raise Exception("Unexpected Networks entry: " + str(res))
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
bssid = apdev[0]['bssid']
dev[0].scan_for_bss(bssid, freq=2412)
id = dev[0].add_network()
if ssid != '"test"':
raise Exception("Unexpected SSID in network entry")
+def test_dbus_getall_oom(dev, apdev):
+ """D-Bus GetAll wpa_config_get_all() OOM"""
+ (bus,wpas_obj,path,if_obj) = prepare_dbus(dev[0])
+
+ id = dev[0].add_network()
+ dev[0].set_network(id, "disabled", "0")
+ dev[0].set_network_quoted(id, "ssid", "test")
+
+ res = if_obj.Get(WPAS_DBUS_IFACE, 'Networks',
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ if len(res) != 1:
+ raise Exception("Missing Networks entry: " + str(res))
+ net_obj = bus.get_object(WPAS_DBUS_SERVICE, res[0])
+ for i in range(1, 50):
+ with alloc_fail(dev[0], i, "wpa_config_get_all"):
+ try:
+ props = net_obj.GetAll(WPAS_DBUS_NETWORK,
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ except dbus.exceptions.DBusException, e:
+ pass
+
def dbus_get(dbus, wpas_obj, prop, expect=None, byte_arrays=False):
val = wpas_obj.Get(WPAS_DBUS_SERVICE, prop,
dbus_interface=dbus.PROPERTIES_IFACE,
if "InvalidArgs: invalid message format" not in str(e):
raise Exception("Unexpected error message: " + str(e))
+def test_dbus_set_global_properties(dev, apdev):
+ """D-Bus Get/Set fi.w1.wpa_supplicant1 interface global properties"""
+ (bus,wpas_obj,path,if_obj) = prepare_dbus(dev[0])
+
+ props = [ ('Okc', '0', '1'), ('ModelName', '', 'blahblahblah') ]
+
+ for p in props:
+ res = if_obj.Get(WPAS_DBUS_IFACE, p[0],
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ if res != p[1]:
+ raise Exception("Unexpected " + p[0] + " value: " + str(res))
+
+ if_obj.Set(WPAS_DBUS_IFACE, p[0], p[2],
+ dbus_interface=dbus.PROPERTIES_IFACE)
+
+ res = if_obj.Get(WPAS_DBUS_IFACE, p[0],
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ if res != p[2]:
+ raise Exception("Unexpected " + p[0] + " value after set: " + str(res))
+
def test_dbus_invalid_method(dev, apdev):
"""D-Bus invalid method"""
(bus,wpas_obj,path,if_obj) = prepare_dbus(dev[0])
dbus_interface=dbus.PROPERTIES_IFACE)
if if_obj.Get(WPAS_DBUS_IFACE_WPS, "ProcessCredentials",
dbus_interface=dbus.PROPERTIES_IFACE) != True:
- raise Exception("Unexpected Get(ProcessCredentials) result after Set");
+ raise Exception("Unexpected Get(ProcessCredentials) result after Set")
if_obj.Set(WPAS_DBUS_IFACE_WPS, "ProcessCredentials",
dbus.Boolean(0),
dbus_interface=dbus.PROPERTIES_IFACE)
if if_obj.Get(WPAS_DBUS_IFACE_WPS, "ProcessCredentials",
dbus_interface=dbus.PROPERTIES_IFACE) != False:
- raise Exception("Unexpected Get(ProcessCredentials) result after Set");
+ raise Exception("Unexpected Get(ProcessCredentials) result after Set")
self.dbus_sets_done = True
return False
if_obj.Get(WPAS_DBUS_IFACE, "State",
dbus_interface=dbus.PROPERTIES_IFACE)
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
bssid = apdev[0]['bssid']
dev[0].scan_for_bss(bssid, freq=2412)
+ time.sleep(0.05)
for i in range(1, 3):
with alloc_fail_dbus(dev[0], i, "=wpas_dbus_getter_bsss", "Get"):
if_obj.Get(WPAS_DBUS_IFACE, "BSSs",
with alloc_fail_dbus(dev[0], 1, "=wpas_dbus_getter_bss_rates", "Get"):
bss_obj.Get(WPAS_DBUS_BSS, "Rates",
dbus_interface=dbus.PROPERTIES_IFACE)
+ with alloc_fail(dev[0], 1,
+ "wpa_bss_get_bit_rates;wpas_dbus_getter_bss_rates"):
+ try:
+ bss_obj.Get(WPAS_DBUS_BSS, "Rates",
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ except dbus.exceptions.DBusException, e:
+ pass
id = dev[0].add_network()
dev[0].set_network(id, "disabled", "0")
(bus,wpas_obj,path,if_obj) = prepare_dbus(dev[0])
iface = dbus.Interface(if_obj, WPAS_DBUS_IFACE)
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
class TestDbusScan(TestDbus):
def __init__(self, bus):
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
class TestDbusConnect(TestDbus):
def __init__(self, bus):
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
class TestDbusConnect(TestDbus):
def __init__(self, bus):
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
class TestDbusConnect(TestDbus):
def __init__(self, bus):
except:
pass
+ # Force regulatory update to re-fetch hw capabilities for the following
+ # test cases.
+ try:
+ dev[0].dump_monitor()
+ subprocess.call(['iw', 'reg', 'set', 'US'])
+ ev = dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=1)
+ finally:
+ dev[0].dump_monitor()
+ subprocess.call(['iw', 'reg', 'set', '00'])
+ ev = dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=1)
+
def test_dbus_while_not_connected(dev, apdev):
"""D-Bus invalid operations while not connected"""
(bus,wpas_obj,path,if_obj) = prepare_dbus(dev[0])
def test_dbus_connect_eap(dev, apdev):
"""D-Bus AddNetwork and connect to EAP network"""
+ check_altsubject_match_support(dev[0])
(bus,wpas_obj,path,if_obj) = prepare_dbus(dev[0])
iface = dbus.Interface(if_obj, WPAS_DBUS_IFACE)
params = hostapd.radius_params()
params["ssid"] = ssid
params["ieee8021x"] = "1"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
class TestDbusConnect(TestDbus):
def __init__(self, bus):
def test_dbus_interface(dev, apdev):
"""D-Bus CreateInterface/GetInterface/RemoveInterface parameters and error cases"""
+ try:
+ _test_dbus_interface(dev, apdev)
+ finally:
+ # Need to force P2P channel list update since the 'lo' interface
+ # with driver=none ends up configuring default dualband channels.
+ dev[0].request("SET country US")
+ ev = dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=1)
+ if ev is None:
+ ev = dev[0].wait_global_event(["CTRL-EVENT-REGDOM-CHANGE"],
+ timeout=1)
+ dev[0].request("SET country 00")
+ ev = dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=1)
+ if ev is None:
+ ev = dev[0].wait_global_event(["CTRL-EVENT-REGDOM-CHANGE"],
+ timeout=1)
+ subprocess.call(['iw', 'reg', 'set', '00'])
+
+def _test_dbus_interface(dev, apdev):
(bus,wpas_obj,path,if_obj) = prepare_dbus(dev[0])
wpas = dbus.Interface(wpas_obj, WPAS_DBUS_SERVICE)
(bus,wpas_obj,path,if_obj) = prepare_dbus(dev[0])
iface = dbus.Interface(if_obj, WPAS_DBUS_IFACE)
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-open" })
connect_2sta_open(dev, hapd)
addr1 = dev[1].p2p_interface_addr()
(bus,wpas_obj,path,if_obj) = prepare_dbus(dev[0])
iface = dbus.Interface(if_obj, WPAS_DBUS_IFACE)
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-open" })
connect_2sta_open(dev, hapd)
addr1 = dev[1].p2p_interface_addr()
ev = dev[0].wait_global_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=1)
if ev is None:
raise Exception("regdom change event not seen")
- if "init=CORE type=WORLD" not in ev:
+ # init=CORE was previously used due to invalid db.txt data for 00. For
+ # now, allow both it and the new init=USER after fixed db.txt.
+ if "init=CORE type=WORLD" not in ev and "init=USER type=WORLD" not in ev:
raise Exception("Unexpected event contents: " + ev)
def test_dbus_scan_interval(dev, apdev):
TestDbus.__init__(self, bus)
self.found = False
self.found2 = False
+ self.found_prop = False
self.lost = False
self.find_stopped = False
gobject.timeout_add(15000, self.timeout)
self.add_signal(self.deviceFound, WPAS_DBUS_IFACE_P2PDEVICE,
"DeviceFound")
+ self.add_signal(self.deviceFoundProperties,
+ WPAS_DBUS_IFACE_P2PDEVICE, "DeviceFoundProperties")
self.add_signal(self.deviceLost, WPAS_DBUS_IFACE_P2PDEVICE,
"DeviceLost")
self.add_signal(self.provisionDiscoveryResponseEnterPin,
raise Exception("Unexpected error message for invalid RejectPeer(): " + str(e))
self.loop.quit()
+ def deviceFoundProperties(self, path, properties):
+ logger.debug("deviceFoundProperties: path=%s" % path)
+ logger.debug("peer properties: " + str(properties))
+ if properties['DeviceAddress'] == a1:
+ self.found_prop = True
+
def provisionDiscoveryResponseEnterPin(self, peer_object):
logger.debug("provisionDiscoveryResponseEnterPin - peer=%s" % peer_object)
p2p.Flush()
dev[2].p2p_stop_find()
+def test_dbus_p2p_invitation_received(dev, apdev):
+ """D-Bus P2P and InvitationReceived"""
+ (bus,wpas_obj,path,if_obj) = prepare_dbus(dev[0])
+ p2p = dbus.Interface(if_obj, WPAS_DBUS_IFACE_P2PDEVICE)
+
+ form(dev[0], dev[1])
+ addr0 = dev[0].p2p_dev_addr()
+ dev[0].p2p_listen()
+ dev[0].global_request("SET persistent_reconnect 0")
+
+ if not dev[1].discover_peer(addr0, social=True):
+ raise Exception("Peer " + addr0 + " not found")
+ peer = dev[1].get_peer(addr0)
+
+ class TestDbusP2p(TestDbus):
+ def __init__(self, bus):
+ TestDbus.__init__(self, bus)
+ self.done = False
+
+ def __enter__(self):
+ gobject.timeout_add(1, self.run_test)
+ gobject.timeout_add(15000, self.timeout)
+ self.add_signal(self.invitationReceived, WPAS_DBUS_IFACE_P2PDEVICE,
+ "InvitationReceived")
+ self.loop.run()
+ return self
+
+ def invitationReceived(self, result):
+ logger.debug("invitationReceived: " + str(result))
+ self.done = True
+ self.loop.quit()
+
+ def run_test(self, *args):
+ logger.debug("run_test")
+ dev1 = WpaSupplicant('wlan1', '/tmp/wpas-wlan1')
+ cmd = "P2P_INVITE persistent=" + peer['persistent'] + " peer=" + addr0
+ dev1.global_request(cmd)
+ return False
+
+ def success(self):
+ return self.done
+
+ with TestDbusP2p(bus) as t:
+ if not t.success():
+ raise Exception("Expected signals not seen")
+
+ dev[0].p2p_stop_find()
+ dev[1].p2p_stop_find()
+
def test_dbus_p2p_config(dev, apdev):
"""D-Bus Get/Set P2PDeviceConfig"""
try:
if not dev1.discover_peer(addr0):
raise Exception("Peer not found")
dev1.global_request("P2P_CONNECT " + addr0 + " 12345670 display go_intent=0")
- ev = dev1.wait_global_event(["P2P-GROUP-STARTED"], timeout=15);
+ ev = dev1.wait_global_event(["P2P-GROUP-STARTED"], timeout=15)
if ev is None:
raise Exception("Group formation timed out")
self.sta_group_ev = ev
if ev is None:
raise Exception("Timeout while waiting for GO Neg Request")
dev1.global_request("P2P_CONNECT " + addr0 + " 12345670 display go_intent=15")
- ev = dev1.wait_global_event(["P2P-GROUP-STARTED"], timeout=15);
+ ev = dev1.wait_global_event(["P2P-GROUP-STARTED"], timeout=15)
if ev is None:
raise Exception("Group formation timed out")
self.sta_group_ev = ev
if ev is None:
raise Exception("Timeout while waiting for GO Neg Request")
dev1.global_request("P2P_CONNECT " + addr0 + " 12345670 display go_intent=15")
- ev = dev1.wait_global_event(["P2P-GROUP-STARTED"], timeout=15);
+ ev = dev1.wait_global_event(["P2P-GROUP-STARTED"], timeout=15)
if ev is None:
raise Exception("Group formation timed out")
self.sta_group_ev = ev
def __init__(self, bus):
TestDbus.__init__(self, bus)
self.done = False
+ self.group_started = False
self.peer_group_added = False
self.peer_group_removed = False
if ev is None:
raise Exception("Timeout while waiting for GO Neg Request")
dev1.global_request("P2P_CONNECT " + addr0 + " 12345670 display go_intent=15")
- ev = dev1.wait_global_event(["P2P-GROUP-STARTED"], timeout=15);
+ ev = dev1.wait_global_event(["P2P-GROUP-STARTED"], timeout=15)
if ev is None:
raise Exception("Group formation timed out")
self.sta_group_ev = ev
def groupStarted(self, properties):
logger.debug("groupStarted: " + str(properties))
+ self.group_started = True
g_if_obj = bus.get_object(WPAS_DBUS_SERVICE,
properties['interface_object'])
dev1 = WpaSupplicant('wlan1', '/tmp/wpas-wlan1')
logger.debug("propertiesChanged: interface_name=%s changed_properties=%s invalidated_properties=%s" % (interface_name, str(changed_properties), str(invalidated_properties)))
if interface_name != WPAS_DBUS_P2P_PEER:
return
+ if not self.group_started:
+ return
if "Groups" not in changed_properties:
return
if len(changed_properties["Groups"]) > 0:
dev2 = WpaSupplicant('wlan2', '/tmp/wpas-wlan2')
dev2.scan_for_bss(bssid, freq=2412)
dev2.global_request("P2P_CONNECT " + bssid + " 12345670 join freq=2412")
- ev = dev2.wait_global_event(["P2P-GROUP-STARTED"], timeout=15);
+ ev = dev2.wait_global_event(["P2P-GROUP-STARTED"], timeout=15)
if ev is None:
raise Exception("Group join timed out")
self.dev2_group_ev = ev
logger.info("Initial Introspect: " + str(res))
if res is None or "Introspectable" not in res or "GroupStarted" not in res:
raise Exception("Unexpected initial Introspect response: " + str(res))
+ if "FastReauth" not in res or "PassiveScan" not in res:
+ raise Exception("Unexpected initial Introspect response: " + str(res))
with alloc_fail(dev[0], 1, "wpa_dbus_introspect"):
res2 = if_obj.Introspect(WPAS_DBUS_IFACE,
params = hostapd.wpa_eap_params(ssid=ssid)
params["wpa"] = "3"
params["rsn_pairwise"] = "CCMP"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
class TestDbusConnect(TestDbus):
def __init__(self, bus):
dev[1].wait_disconnected()
dev[0].request("DISCONNECT")
dev[0].wait_disconnected()
+
+def test_dbus_expectdisconnect(dev, apdev):
+ """D-Bus ExpectDisconnect"""
+ (bus,wpas_obj,path,if_obj) = prepare_dbus(dev[0])
+ wpas = dbus.Interface(wpas_obj, WPAS_DBUS_SERVICE)
+
+ params = { "ssid": "test-open" }
+ hapd = hostapd.add_ap(apdev[0], params)
+ dev[0].connect("test-open", key_mgmt="NONE", scan_freq="2412")
+
+ # This does not really verify the behavior other than by going through the
+ # code path for additional coverage.
+ wpas.ExpectDisconnect()
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected()
+
+def test_dbus_save_config(dev, apdev):
+ """D-Bus SaveConfig"""
+ (bus,wpas_obj,path,if_obj) = prepare_dbus(dev[0])
+ iface = dbus.Interface(if_obj, WPAS_DBUS_IFACE)
+ try:
+ iface.SaveConfig()
+ raise Exception("SaveConfig() accepted unexpectedly")
+ except dbus.exceptions.DBusException, e:
+ if not str(e).startswith("fi.w1.wpa_supplicant1.UnknownError: Not allowed to update configuration"):
+ raise Exception("Unexpected error message for SaveConfig(): " + str(e))
+
+def test_dbus_vendor_elem(dev, apdev):
+ """D-Bus vendor element operations"""
+ try:
+ _test_dbus_vendor_elem(dev, apdev)
+ finally:
+ dev[0].request("VENDOR_ELEM_REMOVE 1 *")
+
+def _test_dbus_vendor_elem(dev, apdev):
+ (bus,wpas_obj,path,if_obj) = prepare_dbus(dev[0])
+ iface = dbus.Interface(if_obj, WPAS_DBUS_IFACE)
+
+ dev[0].request("VENDOR_ELEM_REMOVE 1 *")
+
+ try:
+ ie = dbus.ByteArray("\x00\x00")
+ iface.VendorElemAdd(-1, ie)
+ raise Exception("Invalid VendorElemAdd() accepted")
+ except dbus.exceptions.DBusException, e:
+ if "InvalidArgs" not in str(e) or "Invalid ID" not in str(e):
+ raise Exception("Unexpected error message for invalid VendorElemAdd[1]: " + str(e))
+
+ try:
+ ie = dbus.ByteArray("")
+ iface.VendorElemAdd(1, ie)
+ raise Exception("Invalid VendorElemAdd() accepted")
+ except dbus.exceptions.DBusException, e:
+ if "InvalidArgs" not in str(e) or "Invalid value" not in str(e):
+ raise Exception("Unexpected error message for invalid VendorElemAdd[2]: " + str(e))
+
+ try:
+ ie = dbus.ByteArray("\x00\x01")
+ iface.VendorElemAdd(1, ie)
+ raise Exception("Invalid VendorElemAdd() accepted")
+ except dbus.exceptions.DBusException, e:
+ if "InvalidArgs" not in str(e) or "Parse error" not in str(e):
+ raise Exception("Unexpected error message for invalid VendorElemAdd[3]: " + str(e))
+
+ try:
+ iface.VendorElemGet(-1)
+ raise Exception("Invalid VendorElemGet() accepted")
+ except dbus.exceptions.DBusException, e:
+ if "InvalidArgs" not in str(e) or "Invalid ID" not in str(e):
+ raise Exception("Unexpected error message for invalid VendorElemGet[1]: " + str(e))
+
+ try:
+ iface.VendorElemGet(1)
+ raise Exception("Invalid VendorElemGet() accepted")
+ except dbus.exceptions.DBusException, e:
+ if "InvalidArgs" not in str(e) or "ID value does not exist" not in str(e):
+ raise Exception("Unexpected error message for invalid VendorElemGet[2]: " + str(e))
+
+ try:
+ ie = dbus.ByteArray("\x00\x00")
+ iface.VendorElemRem(-1, ie)
+ raise Exception("Invalid VendorElemRemove() accepted")
+ except dbus.exceptions.DBusException, e:
+ if "InvalidArgs" not in str(e) or "Invalid ID" not in str(e):
+ raise Exception("Unexpected error message for invalid VendorElemRemove[1]: " + str(e))
+
+ try:
+ ie = dbus.ByteArray("")
+ iface.VendorElemRem(1, ie)
+ raise Exception("Invalid VendorElemRemove() accepted")
+ except dbus.exceptions.DBusException, e:
+ if "InvalidArgs" not in str(e) or "Invalid value" not in str(e):
+ raise Exception("Unexpected error message for invalid VendorElemRemove[1]: " + str(e))
+
+ iface.VendorElemRem(1, "*")
+
+ ie = dbus.ByteArray("\x00\x01\x00")
+ iface.VendorElemAdd(1, ie)
+
+ val = iface.VendorElemGet(1)
+ if len(val) != len(ie):
+ raise Exception("Unexpected VendorElemGet length")
+ for i in range(len(val)):
+ if val[i] != dbus.Byte(ie[i]):
+ raise Exception("Unexpected VendorElemGet data")
+
+ ie2 = dbus.ByteArray("\xe0\x00")
+ iface.VendorElemAdd(1, ie2)
+
+ ies = ie + ie2
+ val = iface.VendorElemGet(1)
+ if len(val) != len(ies):
+ raise Exception("Unexpected VendorElemGet length[2]")
+ for i in range(len(val)):
+ if val[i] != dbus.Byte(ies[i]):
+ raise Exception("Unexpected VendorElemGet data[2]")
+
+ try:
+ test_ie = dbus.ByteArray("\x01\x01")
+ iface.VendorElemRem(1, test_ie)
+ raise Exception("Invalid VendorElemRemove() accepted")
+ except dbus.exceptions.DBusException, e:
+ if "InvalidArgs" not in str(e) or "Parse error" not in str(e):
+ raise Exception("Unexpected error message for invalid VendorElemRemove[1]: " + str(e))
+
+ iface.VendorElemRem(1, ie)
+ val = iface.VendorElemGet(1)
+ if len(val) != len(ie2):
+ raise Exception("Unexpected VendorElemGet length[3]")
+
+ iface.VendorElemRem(1, "*")
+ try:
+ iface.VendorElemGet(1)
+ raise Exception("Invalid VendorElemGet() accepted after removal")
+ except dbus.exceptions.DBusException, e:
+ if "InvalidArgs" not in str(e) or "ID value does not exist" not in str(e):
+ raise Exception("Unexpected error message for invalid VendorElemGet after removal: " + str(e))
+
+def test_dbus_assoc_reject(dev, apdev):
+ """D-Bus AssocStatusCode"""
+ (bus,wpas_obj,path,if_obj) = prepare_dbus(dev[0])
+ iface = dbus.Interface(if_obj, WPAS_DBUS_IFACE)
+
+ ssid = "test-open"
+ params = { "ssid": ssid,
+ "max_listen_interval": "1" }
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ class TestDbusConnect(TestDbus):
+ def __init__(self, bus):
+ TestDbus.__init__(self, bus)
+ self.assoc_status_seen = False
+ self.state = 0
+
+ def __enter__(self):
+ gobject.timeout_add(1, self.run_connect)
+ gobject.timeout_add(15000, self.timeout)
+ self.add_signal(self.propertiesChanged, WPAS_DBUS_IFACE,
+ "PropertiesChanged")
+ self.loop.run()
+ return self
+
+ def propertiesChanged(self, properties):
+ logger.debug("propertiesChanged: %s" % str(properties))
+ if 'AssocStatusCode' in properties:
+ status = properties['AssocStatusCode']
+ if status != 51:
+ logger.info("Unexpected status code: " + str(status))
+ else:
+ self.assoc_status_seen = True
+ iface.Disconnect()
+ self.loop.quit()
+
+ def run_connect(self, *args):
+ args = dbus.Dictionary({ 'ssid': ssid,
+ 'key_mgmt': 'NONE',
+ 'scan_freq': 2412 },
+ signature='sv')
+ self.netw = iface.AddNetwork(args)
+ iface.SelectNetwork(self.netw)
+ return False
+
+ def success(self):
+ return self.assoc_status_seen
+
+ with TestDbusConnect(bus) as t:
+ if not t.success():
+ raise Exception("Expected signals not seen")
"""The old D-Bus interface - scanning"""
(bus,wpas_obj,path,if_obj) = prepare_dbus(dev[0])
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
params['wpa'] = '3'
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
class TestDbusScan(TestDbus):
def __init__(self, bus):
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
for p in [ "/no/where/to/be/found",
path + "/Networks/12345",
ssid = "test-wpa2-eap"
params = hostapd.wpa2_eap_params(ssid=ssid)
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
class TestDbusConnect(TestDbus):
def __init__(self, bus):
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import os
import subprocess
import time
return ev
def start_dfs_ap(ap, allow_failure=False, ssid="dfs", ht=True, ht40=False,
- ht40minus=False, vht80=False, vht20=False, chanlist=None):
+ ht40minus=False, vht80=False, vht20=False, chanlist=None,
+ channel=None):
ifname = ap['ifname']
logger.info("Starting AP " + ifname + " on DFS channel")
- hapd_global = hostapd.HostapdGlobal()
- hapd_global.remove(ifname)
- hapd_global.add(ifname)
- hapd = hostapd.Hostapd(ifname)
- if not hapd.ping():
- raise Exception("Could not ping hostapd")
- hapd.set_defaults()
+ hapd = hostapd.add_ap(ap, {}, no_enable=True)
hapd.set("ssid", ssid)
hapd.set("country_code", "FI")
hapd.set("ieee80211d", "1")
hapd.set("vht_oper_centr_freq_seg0_idx", "0")
if chanlist:
hapd.set("chanlist", chanlist)
+ if channel:
+ hapd.set("channel", str(channel))
hapd.enable()
ev = wait_dfs_event(hapd, "DFS-CAC-START", 5)
if ev is None:
raise Exception("DFS-RADAR-DETECTED event not reported")
if "freq=5260" not in ev:
- raise Exception("Incorrect frequency in radar detected event: " + ev);
+ raise Exception("Incorrect frequency in radar detected event: " + ev)
ev = hapd.wait_event(["DFS-NEW-CHANNEL"], timeout=70)
if ev is None:
raise Exception("DFS-NEW-CHANNEL event not reported")
if "freq=5260" in ev:
- raise Exception("Channel did not change after radar was detected");
+ raise Exception("Channel did not change after radar was detected")
ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=70)
if ev is None:
raise Exception("AP-CSA-FINISHED event not reported")
if "freq=5260" in ev:
- raise Exception("Channel did not change after radar was detected(2)");
+ raise Exception("Channel did not change after radar was detected(2)")
time.sleep(1)
hwsim_utils.test_connectivity(dev[0], hapd)
finally:
subprocess.call(['iw', 'reg', 'set', '00'])
dev[0].flush_scan_cache()
+@remote_compatible
def test_dfs_radar_on_non_dfs_channel(dev, apdev):
"""DFS radar detection test code on non-DFS channel"""
params = { "ssid": "radar" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
hapd.request("RADAR DETECTED freq=5260 ht_enabled=1 chan_width=1")
hapd.request("RADAR DETECTED freq=2412 ht_enabled=1 chan_width=1")
hapd.request("DISABLE")
subprocess.call(['iw', 'reg', 'set', '00'])
dev[0].flush_scan_cache()
+
+def test_dfs_ht40_minus(dev, apdev, params):
+ """DFS CAC functionality on channel 104 HT40- [long]"""
+ if not params['long']:
+ raise HwsimSkip("Skip test case with long duration due to --long not specified")
+ try:
+ hapd = None
+ hapd = start_dfs_ap(apdev[0], allow_failure=True, ht40minus=True,
+ channel=104)
+
+ ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70)
+ if "success=1" not in ev:
+ raise Exception("CAC failed")
+ if "freq=5520" not in ev:
+ raise Exception("Unexpected DFS freq result")
+
+ ev = hapd.wait_event(["AP-ENABLED"], timeout=5)
+ if not ev:
+ raise Exception("AP setup timed out")
+
+ state = hapd.get_status_field("state")
+ if state != "ENABLED":
+ raise Exception("Unexpected interface state")
+
+ freq = hapd.get_status_field("freq")
+ if freq != "5520":
+ raise Exception("Unexpected frequency")
+
+ dev[0].connect("dfs", key_mgmt="NONE", scan_freq="5520")
+ hwsim_utils.test_connectivity(dev[0], hapd)
+ finally:
+ dev[0].request("DISCONNECT")
+ if hapd:
+ hapd.request("DISABLE")
+ subprocess.call(['iw', 'reg', 'set', '00'])
+ dev[0].flush_scan_cache()
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+import binascii
+import hashlib
import hmac
import logging
logger = logging.getLogger()
+import os
import select
import struct
import threading
import time
import hostapd
-from utils import HwsimSkip
-from test_ap_eap import check_eap_capa
+from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger
+from test_ap_eap import check_eap_capa, check_hlr_auc_gw_support, int_eap_server_params
+from test_erp import check_erp_capa
+
+try:
+ import OpenSSL
+ openssl_imported = True
+except ImportError:
+ openssl_imported = False
EAP_CODE_REQUEST = 1
EAP_CODE_RESPONSE = 2
EAP_CODE_SUCCESS = 3
EAP_CODE_FAILURE = 4
+EAP_CODE_INITIATE = 5
+EAP_CODE_FINISH = 6
EAP_TYPE_IDENTITY = 1
EAP_TYPE_NOTIFICATION = 2
EAP_TYPE_GPSK = 51
EAP_TYPE_PWD = 52
EAP_TYPE_EKE = 53
+EAP_TYPE_EXPANDED = 254
+
+# Type field in EAP-Initiate and EAP-Finish messages
+EAP_ERP_TYPE_REAUTH_START = 1
+EAP_ERP_TYPE_REAUTH = 2
+
+EAP_ERP_TLV_KEYNAME_NAI = 1
+EAP_ERP_TV_RRK_LIFETIME = 2
+EAP_ERP_TV_RMSK_LIFETIME = 3
+EAP_ERP_TLV_DOMAIN_NAME = 4
+EAP_ERP_TLV_CRYPTOSUITES = 5
+EAP_ERP_TLV_AUTHORIZATION_INDICATION = 6
+EAP_ERP_TLV_CALLED_STATION_ID = 128
+EAP_ERP_TLV_CALLING_STATION_ID = 129
+EAP_ERP_TLV_NAS_IDENTIFIER = 130
+EAP_ERP_TLV_NAS_IP_ADDRESS = 131
+EAP_ERP_TLV_NAS_IPV6_ADDRESS = 132
def run_pyrad_server(srv, t_stop, eap_handler):
srv.RunWithStop(t_stop, eap_handler)
class TestServer(pyrad.server.Server):
def _HandleAuthPacket(self, pkt):
pyrad.server.Server._HandleAuthPacket(self, pkt)
- if len(pkt[79]) > 1:
- logger.info("Multiple EAP-Message attributes")
- # TODO: reassemble
- eap = pkt[79][0]
+ eap = ""
+ for p in pkt[79]:
+ eap += p
eap_req = self.eap_handler(self.ctx, eap)
reply = self.CreateReplyPacket(pkt)
if eap_req:
self.ctx = {}
while not t_stop.is_set():
- for (fd, event) in self._poll.poll(1000):
+ for (fd, event) in self._poll.poll(200):
if event == select.POLLIN:
try:
fdo = self._fdmap[fd]
srv['stop'].set()
srv['thread'].join()
-def start_ap(ifname):
+def start_ap(ap):
params = hostapd.wpa2_eap_params(ssid="eap-test")
params['auth_server_port'] = "18138"
- hapd = hostapd.add_ap(ifname, params)
+ hapd = hostapd.add_ap(ap, params)
return hapd
def test_eap_proto(dev, apdev):
srv = start_radius_server(eap_handler)
try:
- hapd = start_ap(apdev[0]['ifname'])
+ hapd = start_ap(apdev[0])
dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
eap="MD5", identity="user", password="password",
finally:
stop_radius_server(srv)
+def test_eap_proto_notification_errors(dev, apdev):
+ """EAP Notification errors"""
+ def eap_handler(ctx, req):
+ logger.info("eap_handler - RX " + req.encode("hex"))
+ if 'num' not in ctx:
+ ctx['num'] = 0
+ ctx['num'] = ctx['num'] + 1
+ if 'id' not in ctx:
+ ctx['id'] = 1
+ ctx['id'] = (ctx['id'] + 1) % 256
+ idx = 0
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: MD5 challenge")
+ return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3,
+ EAP_TYPE_MD5,
+ 1, 0xaa, ord('n'))
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Notification/Request")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_NOTIFICATION,
+ ord('A'))
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: MD5 challenge")
+ return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3,
+ EAP_TYPE_MD5,
+ 1, 0xaa, ord('n'))
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Notification/Request")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_NOTIFICATION,
+ ord('A'))
+
+ return None
+
+ srv = start_radius_server(eap_handler)
+
+ try:
+ hapd = start_ap(apdev[0])
+
+ with alloc_fail(dev[0], 1, "eap_sm_processNotify"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="MD5", identity="user", password="password",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with alloc_fail(dev[0], 1, "eap_msg_alloc;sm_EAP_NOTIFICATION_Enter"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="MD5", identity="user", password="password",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ finally:
+ stop_radius_server(srv)
+
EAP_SAKE_VERSION = 2
EAP_SAKE_SUBTYPE_CHALLENGE = 1
def test_eap_proto_sake(dev, apdev):
"""EAP-SAKE protocol tests"""
+ global eap_proto_sake_test_done
+ eap_proto_sake_test_done = False
+
def sake_challenge(ctx):
logger.info("Test: Challenge subtype")
return struct.pack(">BBHBBBBBBLLLL", EAP_CODE_REQUEST, ctx['id'],
logger.info("sake_handler - RX " + req.encode("hex"))
if 'num' not in ctx:
ctx['num'] = 0
- ctx['num'] = ctx['num'] + 1
+ ctx['num'] += 1
if 'id' not in ctx:
ctx['id'] = 1
ctx['id'] = (ctx['id'] + 1) % 256
+ idx = 0
- if ctx['num'] == 1:
+ idx += 1
+ if ctx['num'] == idx:
logger.info("Test: Missing payload")
return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'], 4 + 1,
EAP_TYPE_SAKE)
- if ctx['num'] == 2:
+ idx += 1
+ if ctx['num'] == idx:
logger.info("Test: Identity subtype without any attributes")
return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
4 + 1 + 3,
EAP_TYPE_SAKE,
EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY)
- if ctx['num'] == 3:
+ idx += 1
+ if ctx['num'] == idx:
logger.info("Test: Identity subtype")
return struct.pack(">BBHBBBBBBH", EAP_CODE_REQUEST, ctx['id'],
4 + 1 + 3 + 4,
EAP_TYPE_SAKE,
EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY,
EAP_SAKE_AT_ANY_ID_REQ, 4, 0)
- if ctx['num'] == 4:
+ idx += 1
+ if ctx['num'] == idx:
logger.info("Test: Identity subtype (different session id)")
return struct.pack(">BBHBBBBBBH", EAP_CODE_REQUEST, ctx['id'],
4 + 1 + 3 + 4,
EAP_SAKE_VERSION, 1, EAP_SAKE_SUBTYPE_IDENTITY,
EAP_SAKE_AT_PERM_ID_REQ, 4, 0)
- if ctx['num'] == 5:
+ idx += 1
+ if ctx['num'] == idx:
logger.info("Test: Identity subtype with too short attribute")
return struct.pack(">BBHBBBBBB", EAP_CODE_REQUEST, ctx['id'],
4 + 1 + 3 + 2,
EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY,
EAP_SAKE_AT_ANY_ID_REQ, 2)
- if ctx['num'] == 6:
+ idx += 1
+ if ctx['num'] == idx:
logger.info("Test: Identity subtype with truncated attribute")
return struct.pack(">BBHBBBBBB", EAP_CODE_REQUEST, ctx['id'],
4 + 1 + 3 + 2,
EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY,
EAP_SAKE_AT_ANY_ID_REQ, 4)
- if ctx['num'] == 7:
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity subtype with too short attribute header")
+ payload = struct.pack("B", EAP_SAKE_AT_ANY_ID_REQ)
+ return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + len(payload),
+ EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
+ EAP_SAKE_SUBTYPE_IDENTITY) + payload
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity subtype with AT_IV but not AT_ENCR_DATA")
+ payload = struct.pack("BB", EAP_SAKE_AT_IV, 2)
+ return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + len(payload),
+ EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
+ EAP_SAKE_SUBTYPE_IDENTITY) + payload
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity subtype with skippable and non-skippable unknown attribute")
+ payload = struct.pack("BBBB", 255, 2, 127, 2)
+ return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + len(payload),
+ EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
+ EAP_SAKE_SUBTYPE_IDENTITY) + payload
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity subtype: AT_RAND_P with invalid payload length")
+ payload = struct.pack("BB", EAP_SAKE_AT_RAND_P, 2)
+ return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + len(payload),
+ EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
+ EAP_SAKE_SUBTYPE_IDENTITY) + payload
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity subtype: AT_MIC_P with invalid payload length")
+ payload = struct.pack("BB", EAP_SAKE_AT_MIC_P, 2)
+ return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + len(payload),
+ EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
+ EAP_SAKE_SUBTYPE_IDENTITY) + payload
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity subtype: AT_PERM_ID_REQ with invalid payload length")
+ payload = struct.pack("BBBBBBBBBBBBBB",
+ EAP_SAKE_AT_SPI_S, 2,
+ EAP_SAKE_AT_SPI_P, 2,
+ EAP_SAKE_AT_ENCR_DATA, 2,
+ EAP_SAKE_AT_NEXT_TMPID, 2,
+ EAP_SAKE_AT_PERM_ID_REQ, 4, 0, 0,
+ EAP_SAKE_AT_PERM_ID_REQ, 2)
+ return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + len(payload),
+ EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
+ EAP_SAKE_SUBTYPE_IDENTITY) + payload
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity subtype: AT_PADDING")
+ payload = struct.pack("BBBBBB",
+ EAP_SAKE_AT_PADDING, 3, 0,
+ EAP_SAKE_AT_PADDING, 3, 1)
+ return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + len(payload),
+ EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
+ EAP_SAKE_SUBTYPE_IDENTITY) + payload
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity subtype: AT_MSK_LIFE")
+ payload = struct.pack(">BBLBBH",
+ EAP_SAKE_AT_MSK_LIFE, 6, 0,
+ EAP_SAKE_AT_MSK_LIFE, 4, 0)
+ return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + len(payload),
+ EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
+ EAP_SAKE_SUBTYPE_IDENTITY) + payload
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity subtype with invalid attribute length")
+ payload = struct.pack("BB", EAP_SAKE_AT_ANY_ID_REQ, 0)
+ return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + len(payload),
+ EAP_TYPE_SAKE, EAP_SAKE_VERSION, 0,
+ EAP_SAKE_SUBTYPE_IDENTITY) + payload
+
+ idx += 1
+ if ctx['num'] == idx:
logger.info("Test: Unknown subtype")
return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
4 + 1 + 3,
EAP_TYPE_SAKE,
EAP_SAKE_VERSION, 0, 123)
- if ctx['num'] == 8:
+ idx += 1
+ if ctx['num'] == idx:
logger.info("Test: Challenge subtype without any attributes")
return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
4 + 1 + 3,
EAP_TYPE_SAKE,
EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CHALLENGE)
- if ctx['num'] == 9:
+ idx += 1
+ if ctx['num'] == idx:
logger.info("Test: Challenge subtype with too short AT_RAND_S")
return struct.pack(">BBHBBBBBB", EAP_CODE_REQUEST, ctx['id'],
4 + 1 + 3 + 2,
EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CHALLENGE,
EAP_SAKE_AT_RAND_S, 2)
- if ctx['num'] == 10:
+ idx += 1
+ if ctx['num'] == idx:
return sake_challenge(ctx)
- if ctx['num'] == 11:
+ idx += 1
+ if ctx['num'] == idx:
logger.info("Test: Unexpected Identity subtype")
return struct.pack(">BBHBBBBBBH", EAP_CODE_REQUEST, ctx['id'],
4 + 1 + 3 + 4,
EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY,
EAP_SAKE_AT_ANY_ID_REQ, 4, 0)
- if ctx['num'] == 12:
+ idx += 1
+ if ctx['num'] == idx:
return sake_challenge(ctx)
- if ctx['num'] == 13:
+ idx += 1
+ if ctx['num'] == idx:
logger.info("Test: Unexpected Challenge subtype")
return struct.pack(">BBHBBBBBBLLLL", EAP_CODE_REQUEST, ctx['id'],
4 + 1 + 3 + 18,
EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CHALLENGE,
EAP_SAKE_AT_RAND_S, 18, 0, 0, 0, 0)
- if ctx['num'] == 14:
+ idx += 1
+ if ctx['num'] == idx:
return sake_challenge(ctx)
- if ctx['num'] == 15:
+ idx += 1
+ if ctx['num'] == idx:
logger.info("Test: Confirm subtype without any attributes")
return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
4 + 1 + 3,
EAP_TYPE_SAKE,
EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CONFIRM)
- if ctx['num'] == 16:
+ idx += 1
+ if ctx['num'] == idx:
return sake_challenge(ctx)
- if ctx['num'] == 17:
+ idx += 1
+ if ctx['num'] == idx:
logger.info("Test: Confirm subtype with too short AT_MIC_S")
return struct.pack(">BBHBBBBBB", EAP_CODE_REQUEST, ctx['id'],
4 + 1 + 3 + 2,
EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CONFIRM,
EAP_SAKE_AT_MIC_S, 2)
- if ctx['num'] == 18:
+ idx += 1
+ if ctx['num'] == idx:
logger.info("Test: Unexpected Confirm subtype")
return struct.pack(">BBHBBBBBBLLLL", EAP_CODE_REQUEST, ctx['id'],
4 + 1 + 3 + 18,
EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CONFIRM,
EAP_SAKE_AT_MIC_S, 18, 0, 0, 0, 0)
- if ctx['num'] == 19:
+ idx += 1
+ if ctx['num'] == idx:
return sake_challenge(ctx)
- if ctx['num'] == 20:
+ idx += 1
+ if ctx['num'] == idx:
logger.info("Test: Confirm subtype with incorrect AT_MIC_S")
return struct.pack(">BBHBBBBBBLLLL", EAP_CODE_REQUEST, ctx['id'],
4 + 1 + 3 + 18,
EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_CONFIRM,
EAP_SAKE_AT_MIC_S, 18, 0, 0, 0, 0)
- return sake_challenge(ctx)
+ global eap_proto_sake_test_done
+ if eap_proto_sake_test_done:
+ return sake_challenge(ctx)
+
+ logger.info("No more test responses available - test case completed")
+ eap_proto_sake_test_done = True
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
srv = start_radius_server(sake_handler)
try:
- hapd = start_ap(apdev[0]['ifname'])
+ hapd = start_ap(apdev[0])
- for i in range(0, 14):
+ while not eap_proto_sake_test_done:
dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
eap="SAKE", identity="sake user",
password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
finally:
stop_radius_server(srv)
+def test_eap_proto_sake_errors(dev, apdev):
+ """EAP-SAKE local error cases"""
+ check_eap_capa(dev[0], "SAKE")
+ params = hostapd.wpa2_eap_params(ssid="eap-test")
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ for i in range(1, 3):
+ with alloc_fail(dev[0], i, "eap_sake_init"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="SAKE", identity="sake user",
+ password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
+ wait_connect=False)
+ ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ ( 1, "eap_msg_alloc;eap_sake_build_msg;eap_sake_process_challenge" ),
+ ( 1, "=eap_sake_process_challenge" ),
+ ( 1, "eap_sake_compute_mic;eap_sake_process_challenge" ),
+ ( 1, "eap_sake_build_msg;eap_sake_process_confirm" ),
+ ( 1, "eap_sake_compute_mic;eap_sake_process_confirm" ),
+ ( 2, "eap_sake_compute_mic;eap_sake_process_confirm" ),
+ ( 1, "eap_sake_getKey" ),
+ ( 1, "eap_sake_get_emsk" ),
+ ( 1, "eap_sake_get_session_id" ) ]
+ for count, func in tests:
+ with alloc_fail(dev[0], count, func):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="SAKE", identity="sake user",
+ password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
+ erp="1",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with fail_test(dev[0], 1, "os_get_random;eap_sake_process_challenge"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="SAKE", identity="sake user",
+ password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+def test_eap_proto_sake_errors2(dev, apdev):
+ """EAP-SAKE protocol tests (2)"""
+ def sake_handler(ctx, req):
+ logger.info("sake_handler - RX " + req.encode("hex"))
+ if 'num' not in ctx:
+ ctx['num'] = 0
+ ctx['num'] += 1
+ if 'id' not in ctx:
+ ctx['id'] = 1
+ ctx['id'] = (ctx['id'] + 1) % 256
+ idx = 0
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity subtype")
+ return struct.pack(">BBHBBBBBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_SAKE,
+ EAP_SAKE_VERSION, 0, EAP_SAKE_SUBTYPE_IDENTITY,
+ EAP_SAKE_AT_ANY_ID_REQ, 4, 0)
+
+ srv = start_radius_server(sake_handler)
+
+ try:
+ hapd = start_ap(apdev[0])
+
+ with alloc_fail(dev[0], 1, "eap_msg_alloc;eap_sake_build_msg;eap_sake_process_identity"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="SAKE", identity="sake user",
+ password_hex="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ finally:
+ stop_radius_server(srv)
+
def test_eap_proto_leap(dev, apdev):
"""EAP-LEAP protocol tests"""
check_eap_capa(dev[0], "LEAP")
srv = start_radius_server(leap_handler)
try:
- hapd = start_ap(apdev[0]['ifname'])
+ hapd = start_ap(apdev[0])
for i in range(0, 12):
dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
finally:
stop_radius_server(srv)
-def test_eap_proto_md5(dev, apdev):
- """EAP-MD5 protocol tests"""
- check_eap_capa(dev[0], "MD5")
+def test_eap_proto_leap_errors(dev, apdev):
+ """EAP-LEAP protocol tests (error paths)"""
+ check_eap_capa(dev[0], "LEAP")
- def md5_handler(ctx, req):
- logger.info("md5_handler - RX " + req.encode("hex"))
+ def leap_handler2(ctx, req):
+ logger.info("leap_handler2 - RX " + req.encode("hex"))
if 'num' not in ctx:
ctx['num'] = 0
ctx['num'] = ctx['num'] + 1
if 'id' not in ctx:
ctx['id'] = 1
ctx['id'] = (ctx['id'] + 1) % 256
+ idx = 0
- if ctx['num'] == 1:
- logger.info("Test: Missing payload")
- return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1,
- EAP_TYPE_MD5)
-
- if ctx['num'] == 2:
- logger.info("Test: Zero-length challenge")
- return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1,
- EAP_TYPE_MD5,
- 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid challenge")
+ return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_LEAP,
+ 1, 0, 8, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
- if ctx['num'] == 3:
- logger.info("Test: Truncated challenge")
- return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1,
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid challenge")
+ return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_LEAP,
+ 1, 0, 8, 0, 0)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid challenge")
+ return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_LEAP,
+ 1, 0, 8, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Success")
+ return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid challenge")
+ return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_LEAP,
+ 1, 0, 8, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Success")
+ return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid challenge")
+ return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_LEAP,
+ 1, 0, 8, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid challange value in Response")
+ return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
+ 4 + 1 + 3 + 24,
+ EAP_TYPE_LEAP,
+ 1, 0, 24,
+ 0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
+ 0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
+ 0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid challenge")
+ return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_LEAP,
+ 1, 0, 8, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid challange value in Response")
+ return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
+ 4 + 1 + 3 + 24,
+ EAP_TYPE_LEAP,
+ 1, 0, 24,
+ 0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
+ 0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
+ 0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid challenge")
+ return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_LEAP,
+ 1, 0, 8, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid challange value in Response")
+ return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
+ 4 + 1 + 3 + 24,
+ EAP_TYPE_LEAP,
+ 1, 0, 24,
+ 0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
+ 0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
+ 0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid challenge")
+ return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_LEAP,
+ 1, 0, 8, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid challange value in Response")
+ return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
+ 4 + 1 + 3 + 24,
+ EAP_TYPE_LEAP,
+ 1, 0, 24,
+ 0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
+ 0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
+ 0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid challenge")
+ return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_LEAP,
+ 1, 0, 8, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid challange value in Response")
+ return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
+ 4 + 1 + 3 + 24,
+ EAP_TYPE_LEAP,
+ 1, 0, 24,
+ 0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
+ 0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
+ 0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid challenge")
+ return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_LEAP,
+ 1, 0, 8, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid challange value in Response")
+ return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
+ 4 + 1 + 3 + 24,
+ EAP_TYPE_LEAP,
+ 1, 0, 24,
+ 0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
+ 0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
+ 0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid challenge")
+ return struct.pack(">BBHBBBBLL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_LEAP,
+ 1, 0, 8, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid challange value in Response")
+ return struct.pack(">BBHBBBB24B", EAP_CODE_RESPONSE, ctx['id'],
+ 4 + 1 + 3 + 24,
+ EAP_TYPE_LEAP,
+ 1, 0, 24,
+ 0x48, 0x4e, 0x46, 0xe3, 0x88, 0x49, 0x46, 0xbd,
+ 0x28, 0x48, 0xf8, 0x53, 0x82, 0x50, 0x00, 0x04,
+ 0x93, 0x50, 0x30, 0xd7, 0x25, 0xea, 0x5f, 0x66)
+
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ srv = start_radius_server(leap_handler2)
+
+ try:
+ hapd = start_ap(apdev[0])
+
+ with alloc_fail(dev[0], 1, "eap_leap_init"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="LEAP", identity="user", password="password",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with alloc_fail(dev[0], 1, "eap_msg_alloc;eap_leap_process_request"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="LEAP", identity="user",
+ password_hex="hash:8846f7eaee8fb117ad06bdd830b7586c",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with alloc_fail(dev[0], 1, "eap_leap_process_success"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="LEAP", identity="user", password="password",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with fail_test(dev[0], 1, "os_get_random;eap_leap_process_success"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="LEAP", identity="user", password="password",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with fail_test(dev[0], 1, "eap_leap_process_response"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="LEAP", identity="user",
+ password_hex="hash:8846f7eaee8fb117ad06bdd830b7586c",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with fail_test(dev[0], 1, "nt_password_hash;eap_leap_process_response"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="LEAP", identity="user", password="password",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with fail_test(dev[0], 1, "hash_nt_password_hash;eap_leap_process_response"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="LEAP", identity="user", password="password",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with alloc_fail(dev[0], 1, "eap_leap_getKey"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="LEAP", identity="user",
+ password_hex="hash:8846f7eaee8fb117ad06bdd830b7586c",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with fail_test(dev[0], 1, "eap_leap_getKey"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="LEAP", identity="user",
+ password_hex="hash:8846f7eaee8fb117ad06bdd830b7586c",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with fail_test(dev[0], 1, "nt_password_hash;eap_leap_getKey"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="LEAP", identity="user", password="password",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with fail_test(dev[0], 1, "hash_nt_password_hash;eap_leap_getKey"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="LEAP", identity="user", password="password",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ finally:
+ stop_radius_server(srv)
+
+def test_eap_proto_md5(dev, apdev):
+ """EAP-MD5 protocol tests"""
+ check_eap_capa(dev[0], "MD5")
+
+ def md5_handler(ctx, req):
+ logger.info("md5_handler - RX " + req.encode("hex"))
+ if 'num' not in ctx:
+ ctx['num'] = 0
+ ctx['num'] = ctx['num'] + 1
+ if 'id' not in ctx:
+ ctx['id'] = 1
+ ctx['id'] = (ctx['id'] + 1) % 256
+
+ if ctx['num'] == 1:
+ logger.info("Test: Missing payload")
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1,
+ EAP_TYPE_MD5)
+
+ if ctx['num'] == 2:
+ logger.info("Test: Zero-length challenge")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_MD5,
+ 0)
+
+ if ctx['num'] == 3:
+ logger.info("Test: Truncated challenge")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
EAP_TYPE_MD5,
1)
srv = start_radius_server(md5_handler)
try:
- hapd = start_ap(apdev[0]['ifname'])
+ hapd = start_ap(apdev[0])
for i in range(0, 4):
dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
finally:
stop_radius_server(srv)
-def test_eap_proto_otp(dev, apdev):
- """EAP-OTP protocol tests"""
- def otp_handler(ctx, req):
- logger.info("otp_handler - RX " + req.encode("hex"))
- if 'num' not in ctx:
- ctx['num'] = 0
- ctx['num'] = ctx['num'] + 1
- if 'id' not in ctx:
- ctx['id'] = 1
- ctx['id'] = (ctx['id'] + 1) % 256
+def test_eap_proto_md5_errors(dev, apdev):
+ """EAP-MD5 local error cases"""
+ check_eap_capa(dev[0], "MD5")
+ params = hostapd.wpa2_eap_params(ssid="eap-test")
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ with fail_test(dev[0], 1, "chap_md5"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="MD5", identity="phase1-user", password="password",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with alloc_fail(dev[0], 1, "eap_msg_alloc;eap_md5_process"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="MD5", identity="phase1-user", password="password",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ time.sleep(0.1)
+ dev[0].request("REMOVE_NETWORK all")
+
+def test_eap_proto_otp(dev, apdev):
+ """EAP-OTP protocol tests"""
+ def otp_handler(ctx, req):
+ logger.info("otp_handler - RX " + req.encode("hex"))
+ if 'num' not in ctx:
+ ctx['num'] = 0
+ ctx['num'] = ctx['num'] + 1
+ if 'id' not in ctx:
+ ctx['id'] = 1
+ ctx['id'] = (ctx['id'] + 1) % 256
+
+ if ctx['num'] == 1:
+ logger.info("Test: Empty payload")
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1,
+ EAP_TYPE_OTP)
+ if ctx['num'] == 2:
+ logger.info("Test: Success")
+ return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'],
+ 4)
+
+ if ctx['num'] == 3:
+ logger.info("Test: Challenge included")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_OTP,
+ ord('A'))
+ if ctx['num'] == 4:
+ logger.info("Test: Success")
+ return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'],
+ 4)
+
+ return None
+
+ srv = start_radius_server(otp_handler)
+
+ try:
+ hapd = start_ap(apdev[0])
+
+ for i in range(0, 1):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="OTP", identity="user", password="password",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ time.sleep(0.1)
+ dev[0].request("REMOVE_NETWORK all")
+
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="OTP", identity="user", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-REQ-OTP"])
+ if ev is None:
+ raise Exception("Request for password timed out")
+ id = ev.split(':')[0].split('-')[-1]
+ dev[0].request("CTRL-RSP-OTP-" + id + ":password")
+ ev = dev[0].wait_event("CTRL-EVENT-EAP-SUCCESS")
+ if ev is None:
+ raise Exception("Success not reported")
+ finally:
+ stop_radius_server(srv)
+
+def test_eap_proto_otp_errors(dev, apdev):
+ """EAP-OTP local error cases"""
+ def otp_handler2(ctx, req):
+ logger.info("otp_handler2 - RX " + req.encode("hex"))
+ if 'num' not in ctx:
+ ctx['num'] = 0
+ ctx['num'] = ctx['num'] + 1
+ if 'id' not in ctx:
+ ctx['id'] = 1
+ ctx['id'] = (ctx['id'] + 1) % 256
+ idx = 0
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Challenge included")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_OTP,
+ ord('A'))
+
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ srv = start_radius_server(otp_handler2)
+
+ try:
+ hapd = start_ap(apdev[0])
+
+ with alloc_fail(dev[0], 1, "eap_msg_alloc;eap_otp_process"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="OTP", identity="user", password="password",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ finally:
+ stop_radius_server(srv)
+
+EAP_GPSK_OPCODE_GPSK_1 = 1
+EAP_GPSK_OPCODE_GPSK_2 = 2
+EAP_GPSK_OPCODE_GPSK_3 = 3
+EAP_GPSK_OPCODE_GPSK_4 = 4
+EAP_GPSK_OPCODE_FAIL = 5
+EAP_GPSK_OPCODE_PROTECTED_FAIL = 6
+
+def test_eap_proto_gpsk(dev, apdev):
+ """EAP-GPSK protocol tests"""
+ def gpsk_handler(ctx, req):
+ logger.info("gpsk_handler - RX " + req.encode("hex"))
+ if 'num' not in ctx:
+ ctx['num'] = 0
+ ctx['num'] = ctx['num'] + 1
+ if 'id' not in ctx:
+ ctx['id'] = 1
+ ctx['id'] = (ctx['id'] + 1) % 256
+
+ idx = 0
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Missing payload")
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1,
+ EAP_TYPE_GPSK)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unknown opcode")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_GPSK,
+ 255)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unexpected GPSK-3")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_3)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Too short GPSK-1")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Truncated ID_Server")
+ return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 1)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Missing RAND_Server")
+ return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 0)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Missing CSuite_List")
+ return struct.pack(">BBHBBH8L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 32,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Truncated CSuite_List")
+ return struct.pack(">BBHBBH8LH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 32 + 2,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Empty CSuite_List")
+ return struct.pack(">BBHBBH8LH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 32 + 2,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Invalid CSuite_List")
+ return struct.pack(">BBHBBH8LHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 32 + 2 + 1,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 No supported CSuite")
+ return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 32 + 2 + 6,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 0)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Supported CSuite")
+ return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 32 + 2 + 6,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 1)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unexpected GPSK-1")
+ return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 32 + 2 + 6,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 1)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Supported CSuite but too short key")
+ return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 32 + 2 + 6,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 1)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Supported CSuite")
+ return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 32 + 2 + 6,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 1)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Too short GPSK-3")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_3)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Supported CSuite")
+ return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 32 + 2 + 6,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 1)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-3 Mismatch in RAND_Peer")
+ return struct.pack(">BBHBB8L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 32,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_3,
+ 0, 0, 0, 0, 0, 0, 0, 0)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Supported CSuite")
+ return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 32 + 2 + 6,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 1)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-3 Missing RAND_Server")
+ msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 32,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_3)
+ msg += req[14:46]
+ return msg
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Supported CSuite")
+ return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 32 + 2 + 6,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 1)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-3 Mismatch in RAND_Server")
+ msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 32 + 32,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_3)
+ msg += req[14:46]
+ msg += struct.pack(">8L", 1, 1, 1, 1, 1, 1, 1, 1)
+ return msg
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Supported CSuite")
+ return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 32 + 2 + 6,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 1)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-3 Missing ID_Server")
+ msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 32 + 32,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_3)
+ msg += req[14:46]
+ msg += struct.pack(">8L", 0, 0, 0, 0, 0, 0, 0, 0)
+ return msg
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Supported CSuite")
+ return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 32 + 2 + 6,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 1)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-3 Truncated ID_Server")
+ msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 32 + 32 + 2,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_3)
+ msg += req[14:46]
+ msg += struct.pack(">8LH", 0, 0, 0, 0, 0, 0, 0, 0, 1)
+ return msg
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Supported CSuite")
+ return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 32 + 2 + 6,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 1)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-3 Mismatch in ID_Server")
+ msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 32 + 32 + 3,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_3)
+ msg += req[14:46]
+ msg += struct.pack(">8LHB", 0, 0, 0, 0, 0, 0, 0, 0, 1, ord('B'))
+ return msg
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Supported CSuite")
+ return struct.pack(">BBHBBHB8LHLH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 3 + 32 + 2 + 6,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 1, ord('A'),
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 1)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-3 Mismatch in ID_Server (same length)")
+ msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 32 + 32 + 3,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_3)
+ msg += req[15:47]
+ msg += struct.pack(">8LHB", 0, 0, 0, 0, 0, 0, 0, 0, 1, ord('B'))
+ return msg
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Supported CSuite")
+ return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 32 + 2 + 6,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 1)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-3 Missing CSuite_Sel")
+ msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 32 + 32 + 2,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_3)
+ msg += req[14:46]
+ msg += struct.pack(">8LH", 0, 0, 0, 0, 0, 0, 0, 0, 0)
+ return msg
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Supported CSuite")
+ return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 32 + 2 + 6,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 1)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-3 Mismatch in CSuite_Sel")
+ msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 32 + 32 + 2 + 6,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_3)
+ msg += req[14:46]
+ msg += struct.pack(">8LHLH", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2)
+ return msg
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Supported CSuite")
+ return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 32 + 2 + 6,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 1)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-3 Missing len(PD_Payload_Block)")
+ msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 32 + 32 + 2 + 6,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_3)
+ msg += req[14:46]
+ msg += struct.pack(">8LHLH", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)
+ return msg
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Supported CSuite")
+ return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 32 + 2 + 6,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 1)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-3 Truncated PD_Payload_Block")
+ msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 32 + 32 + 2 + 6 + 2,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_3)
+ msg += req[14:46]
+ msg += struct.pack(">8LHLHH", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1)
+ return msg
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Supported CSuite")
+ return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 32 + 2 + 6,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 1)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-3 Missing MAC")
+ msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 32 + 32 + 2 + 6 + 3,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_3)
+ msg += req[14:46]
+ msg += struct.pack(">8LHLHHB",
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 123)
+ return msg
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-1 Supported CSuite")
+ return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 32 + 2 + 6,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 1)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: GPSK-3 Incorrect MAC")
+ msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 32 + 32 + 2 + 6 + 3 + 16,
+ EAP_TYPE_GPSK,
+ EAP_GPSK_OPCODE_GPSK_3)
+ msg += req[14:46]
+ msg += struct.pack(">8LHLHHB4L",
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 123,
+ 0, 0, 0, 0)
+ return msg
+
+ return None
+
+ srv = start_radius_server(gpsk_handler)
+
+ try:
+ hapd = start_ap(apdev[0])
+
+ for i in range(0, 27):
+ if i == 12:
+ pw = "short"
+ else:
+ pw = "abcdefghijklmnop0123456789abcdef"
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="GPSK", identity="user", password=pw,
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ time.sleep(0.05)
+ dev[0].request("REMOVE_NETWORK all")
+ finally:
+ stop_radius_server(srv)
+
+EAP_EKE_ID = 1
+EAP_EKE_COMMIT = 2
+EAP_EKE_CONFIRM = 3
+EAP_EKE_FAILURE = 4
+
+def test_eap_proto_eke(dev, apdev):
+ """EAP-EKE protocol tests"""
+ def eke_handler(ctx, req):
+ logger.info("eke_handler - RX " + req.encode("hex"))
+ if 'num' not in ctx:
+ ctx['num'] = 0
+ ctx['num'] = ctx['num'] + 1
+ if 'id' not in ctx:
+ ctx['id'] = 1
+ ctx['id'] = (ctx['id'] + 1) % 256
+
+ idx = 0
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Missing payload")
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1,
+ EAP_TYPE_EKE)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unknown exchange")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_EKE,
+ 255)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: No NumProposals in EAP-EKE-ID/Request")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_EKE,
+ EAP_EKE_ID)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: NumProposals=0 in EAP-EKE-ID/Request")
+ return struct.pack(">BBHBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 1,
+ EAP_TYPE_EKE,
+ EAP_EKE_ID,
+ 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Truncated Proposals list in EAP-EKE-ID/Request")
+ return struct.pack(">BBHBBBB4B", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 4,
+ EAP_TYPE_EKE,
+ EAP_EKE_ID,
+ 2, 0, 0, 0, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unsupported proposals in EAP-EKE-ID/Request")
+ return struct.pack(">BBHBBBB4B4B4B4B", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 4 * 4,
+ EAP_TYPE_EKE,
+ EAP_EKE_ID,
+ 4, 0,
+ 0, 0, 0, 0,
+ 3, 0, 0, 0,
+ 3, 1, 0, 0,
+ 3, 1, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Missing IDType/Identity in EAP-EKE-ID/Request")
+ return struct.pack(">BBHBBBB4B4B4B4B4B",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 5 * 4,
+ EAP_TYPE_EKE,
+ EAP_EKE_ID,
+ 5, 0,
+ 0, 0, 0, 0,
+ 3, 0, 0, 0,
+ 3, 1, 0, 0,
+ 3, 1, 1, 0,
+ 3, 1, 1, 1)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid EAP-EKE-ID/Request")
+ return struct.pack(">BBHBBBB4BB",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 4 + 1,
+ EAP_TYPE_EKE,
+ EAP_EKE_ID,
+ 1, 0,
+ 3, 1, 1, 1,
+ 255)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unexpected EAP-EKE-ID/Request")
+ return struct.pack(">BBHBBBB4BB",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 4 + 1,
+ EAP_TYPE_EKE,
+ EAP_EKE_ID,
+ 1, 0,
+ 3, 1, 1, 1,
+ 255)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid EAP-EKE-ID/Request")
+ return struct.pack(">BBHBBBB4BB",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 4 + 1,
+ EAP_TYPE_EKE,
+ EAP_EKE_ID,
+ 1, 0,
+ 3, 1, 1, 1,
+ 255)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unexpected EAP-EKE-Confirm/Request")
+ return struct.pack(">BBHBB",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_EKE,
+ EAP_EKE_CONFIRM)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Too short EAP-EKE-Failure/Request")
+ return struct.pack(">BBHBB",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_EKE,
+ EAP_EKE_FAILURE)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unexpected EAP-EKE-Commit/Request")
+ return struct.pack(">BBHBB",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_EKE,
+ EAP_EKE_COMMIT)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid EAP-EKE-ID/Request")
+ return struct.pack(">BBHBBBB4BB",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 4 + 1,
+ EAP_TYPE_EKE,
+ EAP_EKE_ID,
+ 1, 0,
+ 3, 1, 1, 1,
+ 255)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Too short EAP-EKE-Commit/Request")
+ return struct.pack(">BBHBB",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_EKE,
+ EAP_EKE_COMMIT)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid EAP-EKE-ID/Request")
+ return struct.pack(">BBHBBBB4BB",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 4 + 1,
+ EAP_TYPE_EKE,
+ EAP_EKE_ID,
+ 1, 0,
+ 1, 1, 1, 1,
+ 255)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: All zeroes DHComponent_S and empty CBvalue in EAP-EKE-Commit/Request")
+ return struct.pack(">BBHBB4L32L",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 16 + 128,
+ EAP_TYPE_EKE,
+ EAP_EKE_COMMIT,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Too short EAP-EKE-Confirm/Request")
+ return struct.pack(">BBHBB",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_EKE,
+ EAP_EKE_CONFIRM)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid EAP-EKE-ID/Request")
+ return struct.pack(">BBHBBBB4BB",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2 + 4 + 1,
+ EAP_TYPE_EKE,
+ EAP_EKE_ID,
+ 1, 0,
+ 1, 1, 1, 1,
+ 255)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: All zeroes DHComponent_S and empty CBvalue in EAP-EKE-Commit/Request")
+ return struct.pack(">BBHBB4L32L",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 16 + 128,
+ EAP_TYPE_EKE,
+ EAP_EKE_COMMIT,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Invalid PNonce_PS and Auth_S values in EAP-EKE-Confirm/Request")
+ return struct.pack(">BBHBB4L8L5L5L",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 16 + 2 * 16 + 20 + 20,
+ EAP_TYPE_EKE,
+ EAP_EKE_CONFIRM,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ return None
+
+ srv = start_radius_server(eke_handler)
+
+ try:
+ hapd = start_ap(apdev[0])
+
+ for i in range(0, 14):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="EKE", identity="user", password="password",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ if i in [ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]:
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
+ timeout=10)
+ if ev is None:
+ raise Exception("Timeout on EAP failure")
+ else:
+ time.sleep(0.05)
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
+ finally:
+ stop_radius_server(srv)
+
+def eap_eke_test_fail(dev, phase1=None, success=False):
+ dev.connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="EKE", identity="eke user", password="hello",
+ phase1=phase1, erp="1", wait_connect=False)
+ ev = dev.wait_event([ "CTRL-EVENT-EAP-FAILURE",
+ "CTRL-EVENT-EAP-SUCCESS" ], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP failure")
+ if not success and "CTRL-EVENT-EAP-FAILURE" not in ev:
+ raise Exception("EAP did not fail during failure test")
+ dev.request("REMOVE_NETWORK all")
+ dev.wait_disconnected()
+
+def test_eap_proto_eke_errors(dev, apdev):
+ """EAP-EKE local error cases"""
+ check_eap_capa(dev[0], "EKE")
+ params = hostapd.wpa2_eap_params(ssid="eap-test")
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ for i in range(1, 3):
+ with alloc_fail(dev[0], i, "eap_eke_init"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="EKE", identity="eke user", password="hello",
+ wait_connect=False)
+ ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ (1, "eap_eke_dh_init", None),
+ (1, "eap_eke_prf_hmac_sha1", "dhgroup=3 encr=1 prf=1 mac=1"),
+ (1, "eap_eke_prf_hmac_sha256", "dhgroup=5 encr=1 prf=2 mac=2"),
+ (1, "eap_eke_prf", None),
+ (1, "os_get_random;eap_eke_dhcomp", None),
+ (1, "aes_128_cbc_encrypt;eap_eke_dhcomp", None),
+ (1, "aes_128_cbc_decrypt;eap_eke_shared_secret", None),
+ (1, "eap_eke_prf;eap_eke_shared_secret", None),
+ (1, "eap_eke_prfplus;eap_eke_derive_ke_ki", None),
+ (1, "eap_eke_prfplus;eap_eke_derive_ka", None),
+ (1, "eap_eke_prfplus;eap_eke_derive_msk", None),
+ (1, "os_get_random;eap_eke_prot", None),
+ (1, "aes_128_cbc_decrypt;eap_eke_decrypt_prot", None),
+ (1, "eap_eke_derive_key;eap_eke_process_commit", None),
+ (1, "eap_eke_dh_init;eap_eke_process_commit", None),
+ (1, "eap_eke_shared_secret;eap_eke_process_commit", None),
+ (1, "eap_eke_derive_ke_ki;eap_eke_process_commit", None),
+ (1, "eap_eke_dhcomp;eap_eke_process_commit", None),
+ (1, "os_get_random;eap_eke_process_commit", None),
+ (1, "os_get_random;=eap_eke_process_commit", None),
+ (1, "eap_eke_prot;eap_eke_process_commit", None),
+ (1, "eap_eke_decrypt_prot;eap_eke_process_confirm", None),
+ (1, "eap_eke_derive_ka;eap_eke_process_confirm", None),
+ (1, "eap_eke_auth;eap_eke_process_confirm", None),
+ (2, "eap_eke_auth;eap_eke_process_confirm", None),
+ (1, "eap_eke_prot;eap_eke_process_confirm", None),
+ (1, "eap_eke_derive_msk;eap_eke_process_confirm", None) ]
+ for count, func, phase1 in tests:
+ with fail_test(dev[0], count, func):
+ eap_eke_test_fail(dev[0], phase1)
+
+ tests = [ (1, "=eap_eke_derive_ke_ki", None),
+ (1, "=eap_eke_derive_ka", None),
+ (1, "=eap_eke_derive_msk", None),
+ (1, "eap_eke_build_msg;eap_eke_process_id", None),
+ (1, "wpabuf_alloc;eap_eke_process_id", None),
+ (1, "=eap_eke_process_id", None),
+ (1, "wpabuf_alloc;=eap_eke_process_id", None),
+ (1, "wpabuf_alloc;eap_eke_process_id", None),
+ (1, "eap_eke_build_msg;eap_eke_process_commit", None),
+ (1, "wpabuf_resize;eap_eke_process_commit", None),
+ (1, "eap_eke_build_msg;eap_eke_process_confirm", None) ]
+ for count, func, phase1 in tests:
+ with alloc_fail(dev[0], count, func):
+ eap_eke_test_fail(dev[0], phase1)
+
+ tests = [ (1, "eap_eke_getKey", None),
+ (1, "eap_eke_get_emsk", None),
+ (1, "eap_eke_get_session_id", None) ]
+ for count, func, phase1 in tests:
+ with alloc_fail(dev[0], count, func):
+ eap_eke_test_fail(dev[0], phase1, success=True)
+
+EAP_PAX_OP_STD_1 = 0x01
+EAP_PAX_OP_STD_2 = 0x02
+EAP_PAX_OP_STD_3 = 0x03
+EAP_PAX_OP_SEC_1 = 0x11
+EAP_PAX_OP_SEC_2 = 0x12
+EAP_PAX_OP_SEC_3 = 0x13
+EAP_PAX_OP_SEC_4 = 0x14
+EAP_PAX_OP_SEC_5 = 0x15
+EAP_PAX_OP_ACK = 0x21
+
+EAP_PAX_FLAGS_MF = 0x01
+EAP_PAX_FLAGS_CE = 0x02
+EAP_PAX_FLAGS_AI = 0x04
+
+EAP_PAX_MAC_HMAC_SHA1_128 = 0x01
+EAP_PAX_HMAC_SHA256_128 = 0x02
+
+EAP_PAX_DH_GROUP_NONE = 0x00
+EAP_PAX_DH_GROUP_2048_MODP = 0x01
+EAP_PAX_DH_GROUP_3072_MODP = 0x02
+EAP_PAX_DH_GROUP_NIST_ECC_P_256 = 0x03
+
+EAP_PAX_PUBLIC_KEY_NONE = 0x00
+EAP_PAX_PUBLIC_KEY_RSAES_OAEP = 0x01
+EAP_PAX_PUBLIC_KEY_RSA_PKCS1_V1_5 = 0x02
+EAP_PAX_PUBLIC_KEY_EL_GAMAL_NIST_ECC = 0x03
+
+EAP_PAX_ADE_VENDOR_SPECIFIC = 0x01
+EAP_PAX_ADE_CLIENT_CHANNEL_BINDING = 0x02
+EAP_PAX_ADE_SERVER_CHANNEL_BINDING = 0x03
+
+def test_eap_proto_pax(dev, apdev):
+ """EAP-PAX protocol tests"""
+ def pax_std_1(ctx):
+ logger.info("Test: STD-1")
+ ctx['id'] = 10
+ return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 5 + 2 + 32 + 16,
+ EAP_TYPE_PAX,
+ EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
+ EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
+ 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x16, 0xc9, 0x08, 0x9d, 0x98, 0xa5, 0x6e, 0x1f,
+ 0xf0, 0xac, 0xcf, 0xc4, 0x66, 0xcd, 0x2d, 0xbf)
+
+ def pax_handler(ctx, req):
+ logger.info("pax_handler - RX " + req.encode("hex"))
+ if 'num' not in ctx:
+ ctx['num'] = 0
+ ctx['num'] = ctx['num'] + 1
+ if 'id' not in ctx:
+ ctx['id'] = 1
+ ctx['id'] = (ctx['id'] + 1) % 256
+
+ idx = 0
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Missing payload")
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1,
+ EAP_TYPE_PAX)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Minimum length payload")
+ return struct.pack(">BBHB4L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 16,
+ EAP_TYPE_PAX,
+ 0, 0, 0, 0)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unsupported MAC ID")
+ return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 5 + 16,
+ EAP_TYPE_PAX,
+ EAP_PAX_OP_STD_1, 0, 255, EAP_PAX_DH_GROUP_NONE,
+ EAP_PAX_PUBLIC_KEY_NONE,
+ 0, 0, 0, 0)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unsupported DH Group ID")
+ return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 5 + 16,
+ EAP_TYPE_PAX,
+ EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
+ 255, EAP_PAX_PUBLIC_KEY_NONE,
+ 0, 0, 0, 0)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unsupported Public Key ID")
+ return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 5 + 16,
+ EAP_TYPE_PAX,
+ EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
+ EAP_PAX_DH_GROUP_NONE, 255,
+ 0, 0, 0, 0)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: More fragments")
+ return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 5 + 16,
+ EAP_TYPE_PAX,
+ EAP_PAX_OP_STD_1, EAP_PAX_FLAGS_MF,
+ EAP_PAX_MAC_HMAC_SHA1_128,
+ EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
+ 0, 0, 0, 0)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Invalid ICV")
+ return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 5 + 16,
+ EAP_TYPE_PAX,
+ EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
+ EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
+ 0, 0, 0, 0)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Invalid ICV in short frame")
+ return struct.pack(">BBHBBBBBB3L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 5 + 12,
+ EAP_TYPE_PAX,
+ EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
+ EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
+ 0, 0, 0)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Correct ICV - unsupported op_code")
+ ctx['id'] = 10
+ return struct.pack(">BBHBBBBBB16B", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 5 + 16,
+ EAP_TYPE_PAX,
+ 255, 0, EAP_PAX_MAC_HMAC_SHA1_128,
+ EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
+ 0x90, 0x78, 0x97, 0x38, 0x29, 0x94, 0x32, 0xd4,
+ 0x81, 0x27, 0xe0, 0xf6, 0x3b, 0x0d, 0xb2, 0xb2)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Correct ICV - CE flag in STD-1")
+ ctx['id'] = 10
+ return struct.pack(">BBHBBBBBB16B", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 5 + 16,
+ EAP_TYPE_PAX,
+ EAP_PAX_OP_STD_1, EAP_PAX_FLAGS_CE,
+ EAP_PAX_MAC_HMAC_SHA1_128,
+ EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
+ 0x9c, 0x98, 0xb4, 0x0b, 0x94, 0x90, 0xde, 0x88,
+ 0xb7, 0x72, 0x63, 0x44, 0x1d, 0xe3, 0x7c, 0x5c)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Correct ICV - too short STD-1 payload")
+ ctx['id'] = 10
+ return struct.pack(">BBHBBBBBB16B", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 5 + 16,
+ EAP_TYPE_PAX,
+ EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
+ EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
+ 0xda, 0xab, 0x2c, 0xe7, 0x84, 0x41, 0xb5, 0x5c,
+ 0xee, 0xcf, 0x62, 0x03, 0xc5, 0x69, 0xcb, 0xf4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Correct ICV - incorrect A length in STD-1")
+ ctx['id'] = 10
+ return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 5 + 2 + 32 + 16,
+ EAP_TYPE_PAX,
+ EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
+ EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xc4, 0xb0, 0x81, 0xe4, 0x6c, 0x8c, 0x20, 0x23,
+ 0x60, 0x46, 0x89, 0xea, 0x94, 0x60, 0xf3, 0x2a)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Correct ICV - extra data in STD-1")
+ ctx['id'] = 10
+ return struct.pack(">BBHBBBBBBH8LB16B", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 5 + 2 + 32 + 1 + 16,
+ EAP_TYPE_PAX,
+ EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
+ EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
+ 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1,
+ 0x61, 0x49, 0x65, 0x37, 0x21, 0xe8, 0xd8, 0xbf,
+ 0xf3, 0x02, 0x01, 0xe5, 0x42, 0x51, 0xd3, 0x34)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unexpected STD-1")
+ return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 5 + 2 + 32 + 16,
+ EAP_TYPE_PAX,
+ EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
+ EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
+ 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xe5, 0x1d, 0xbf, 0xb8, 0x70, 0x20, 0x5c, 0xba,
+ 0x41, 0xbb, 0x34, 0xda, 0x1a, 0x08, 0xe6, 0x8d)
+
+ idx += 1
+ if ctx['num'] == idx:
+ return pax_std_1(ctx)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: MAC ID changed during session")
+ return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 5 + 2 + 32 + 16,
+ EAP_TYPE_PAX,
+ EAP_PAX_OP_STD_1, 0, EAP_PAX_HMAC_SHA256_128,
+ EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
+ 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xee, 0x00, 0xbf, 0xb8, 0x70, 0x20, 0x5c, 0xba,
+ 0x41, 0xbb, 0x34, 0xda, 0x1a, 0x08, 0xe6, 0x8d)
+
+ idx += 1
+ if ctx['num'] == idx:
+ return pax_std_1(ctx)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: DH Group ID changed during session")
+ return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 5 + 2 + 32 + 16,
+ EAP_TYPE_PAX,
+ EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
+ EAP_PAX_DH_GROUP_2048_MODP,
+ EAP_PAX_PUBLIC_KEY_NONE,
+ 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xee, 0x01, 0xbf, 0xb8, 0x70, 0x20, 0x5c, 0xba,
+ 0x41, 0xbb, 0x34, 0xda, 0x1a, 0x08, 0xe6, 0x8d)
+
+ idx += 1
+ if ctx['num'] == idx:
+ return pax_std_1(ctx)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Public Key ID changed during session")
+ return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 5 + 2 + 32 + 16,
+ EAP_TYPE_PAX,
+ EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
+ EAP_PAX_DH_GROUP_NONE,
+ EAP_PAX_PUBLIC_KEY_RSAES_OAEP,
+ 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xee, 0x02, 0xbf, 0xb8, 0x70, 0x20, 0x5c, 0xba,
+ 0x41, 0xbb, 0x34, 0xda, 0x1a, 0x08, 0xe6, 0x8d)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unexpected STD-3")
+ ctx['id'] = 10
+ return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 5 + 2 + 32 + 16,
+ EAP_TYPE_PAX,
+ EAP_PAX_OP_STD_3, 0, EAP_PAX_MAC_HMAC_SHA1_128,
+ EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
+ 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x47, 0xbb, 0xc0, 0xf9, 0xb9, 0x69, 0xf5, 0xcb,
+ 0x3a, 0xe8, 0xe7, 0xd6, 0x80, 0x28, 0xf2, 0x59)
+
+ idx += 1
+ if ctx['num'] == idx:
+ return pax_std_1(ctx)
+ idx += 1
+ if ctx['num'] == idx:
+ # TODO: MAC calculation; for now, this gets dropped due to incorrect
+ # ICV
+ logger.info("Test: STD-3 with CE flag")
+ return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 5 + 2 + 32 + 16,
+ EAP_TYPE_PAX,
+ EAP_PAX_OP_STD_3, EAP_PAX_FLAGS_CE,
+ EAP_PAX_MAC_HMAC_SHA1_128,
+ EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
+ 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x8a, 0xc2, 0xf9, 0xf4, 0x8b, 0x75, 0x72, 0xa2,
+ 0x4d, 0xd3, 0x1e, 0x54, 0x77, 0x04, 0x05, 0xe2)
+
+ idx += 1
+ if ctx['num'] & 0x1 == idx & 0x1:
+ logger.info("Test: Default request")
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1,
+ EAP_TYPE_PAX)
+ else:
+ logger.info("Test: Default EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ srv = start_radius_server(pax_handler)
+
+ try:
+ hapd = start_ap(apdev[0])
+
+ for i in range(0, 18):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PAX", identity="user",
+ password_hex="0123456789abcdef0123456789abcdef",
+ wait_connect=False)
+ logger.info("Waiting for EAP method to start")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ time.sleep(0.05)
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
+
+ logger.info("Too short password")
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PAX", identity="user",
+ password_hex="0123456789abcdef0123456789abcd",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ time.sleep(0.1)
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
+
+ logger.info("No password")
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PAX", identity="user",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ time.sleep(0.1)
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
+ finally:
+ stop_radius_server(srv)
+
+def test_eap_proto_pax_errors(dev, apdev):
+ """EAP-PAX local error cases"""
+ check_eap_capa(dev[0], "PAX")
+ params = hostapd.wpa2_eap_params(ssid="eap-test")
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ for i in range(1, 3):
+ with alloc_fail(dev[0], i, "eap_pax_init"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PAX", identity="pax.user@example.com",
+ password_hex="0123456789abcdef0123456789abcdef",
+ wait_connect=False)
+ ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ "eap_msg_alloc;eap_pax_alloc_resp;eap_pax_process_std_1",
+ "eap_msg_alloc;eap_pax_alloc_resp;eap_pax_process_std_3",
+ "eap_pax_getKey",
+ "eap_pax_get_emsk",
+ "eap_pax_get_session_id" ]
+ for func in tests:
+ with alloc_fail(dev[0], 1, func):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PAX", identity="pax.user@example.com",
+ password_hex="0123456789abcdef0123456789abcdef",
+ erp="1", wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ (1, "os_get_random;eap_pax_process_std_1"),
+ (1, "eap_pax_initial_key_derivation"),
+ (1, "eap_pax_mac;eap_pax_process_std_3"),
+ (2, "eap_pax_mac;eap_pax_process_std_3"),
+ (1, "eap_pax_kdf;eap_pax_getKey"),
+ (1, "eap_pax_kdf;eap_pax_get_emsk") ]
+ for count, func in tests:
+ with fail_test(dev[0], count, func):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PAX", identity="pax.user@example.com",
+ password_hex="0123456789abcdef0123456789abcdef",
+ erp="1", wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+def test_eap_proto_psk(dev, apdev):
+ """EAP-PSK protocol tests"""
+ def psk_handler(ctx, req):
+ logger.info("psk_handler - RX " + req.encode("hex"))
+ if 'num' not in ctx:
+ ctx['num'] = 0
+ ctx['num'] = ctx['num'] + 1
+ if 'id' not in ctx:
+ ctx['id'] = 1
+ ctx['id'] = (ctx['id'] + 1) % 256
+
+ idx = 0
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Missing payload")
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1,
+ EAP_TYPE_PSK)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Non-zero T in first message")
+ return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 16,
+ EAP_TYPE_PSK, 0xc0, 0, 0, 0, 0)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid first message")
+ return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 16,
+ EAP_TYPE_PSK, 0, 0, 0, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Too short third message")
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1,
+ EAP_TYPE_PSK)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid first message")
+ return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 16,
+ EAP_TYPE_PSK, 0, 0, 0, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Incorrect T in third message")
+ return struct.pack(">BBHBB4L4L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 16 + 16,
+ EAP_TYPE_PSK, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid first message")
+ return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 16,
+ EAP_TYPE_PSK, 0, 0, 0, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Missing PCHANNEL in third message")
+ return struct.pack(">BBHBB4L4L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 16 + 16,
+ EAP_TYPE_PSK, 0x80, 0, 0, 0, 0, 0, 0, 0, 0)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid first message")
+ return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 16,
+ EAP_TYPE_PSK, 0, 0, 0, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Invalic MAC_S in third message")
+ return struct.pack(">BBHBB4L4L5LB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 16 + 16 + 21,
+ EAP_TYPE_PSK, 0x80, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Valid first message")
+ return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 16,
+ EAP_TYPE_PSK, 0, 0, 0, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ return None
+
+ srv = start_radius_server(psk_handler)
+
+ try:
+ hapd = start_ap(apdev[0])
+
+ for i in range(0, 6):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PSK", identity="user",
+ password_hex="0123456789abcdef0123456789abcdef",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ time.sleep(0.1)
+ dev[0].request("REMOVE_NETWORK all")
+
+ logger.info("Test: Invalid PSK length")
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PSK", identity="user",
+ password_hex="0123456789abcdef0123456789abcd",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ time.sleep(0.1)
+ dev[0].request("REMOVE_NETWORK all")
+ finally:
+ stop_radius_server(srv)
+
+def test_eap_proto_psk_errors(dev, apdev):
+ """EAP-PSK local error cases"""
+ check_eap_capa(dev[0], "PSK")
+ params = hostapd.wpa2_eap_params(ssid="eap-test")
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ for i in range(1, 3):
+ with alloc_fail(dev[0], i, "eap_psk_init"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PSK", identity="psk.user@example.com",
+ password_hex="0123456789abcdef0123456789abcdef",
+ wait_connect=False)
+ ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ for i in range(1, 4):
+ with fail_test(dev[0], i, "eap_psk_key_setup;eap_psk_init"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PSK", identity="psk.user@example.com",
+ password_hex="0123456789abcdef0123456789abcdef",
+ wait_connect=False)
+ ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ (1, "=eap_psk_process_1"),
+ (2, "=eap_psk_process_1"),
+ (1, "eap_msg_alloc;eap_psk_process_1"),
+ (1, "=eap_psk_process_3"),
+ (2, "=eap_psk_process_3"),
+ (1, "eap_msg_alloc;eap_psk_process_3"),
+ (1, "eap_psk_getKey"),
+ (1, "eap_psk_get_session_id"),
+ (1, "eap_psk_get_emsk") ]
+ for count, func in tests:
+ with alloc_fail(dev[0], count, func):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PSK", identity="psk.user@example.com",
+ password_hex="0123456789abcdef0123456789abcdef",
+ erp="1", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL",
+ note="No allocation failure seen for %d:%s" % (count, func))
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ (1, "os_get_random;eap_psk_process_1"),
+ (1, "omac1_aes_128;eap_psk_process_3"),
+ (1, "aes_128_eax_decrypt;eap_psk_process_3"),
+ (2, "aes_128_eax_decrypt;eap_psk_process_3"),
+ (3, "aes_128_eax_decrypt;eap_psk_process_3"),
+ (1, "aes_128_eax_encrypt;eap_psk_process_3"),
+ (2, "aes_128_eax_encrypt;eap_psk_process_3"),
+ (3, "aes_128_eax_encrypt;eap_psk_process_3"),
+ (1, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
+ (2, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
+ (3, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
+ (4, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
+ (5, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
+ (6, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
+ (7, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
+ (8, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
+ (9, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
+ (10, "aes_128_encrypt_block;eap_psk_derive_keys;eap_psk_process_3"),
+ (1, "aes_128_ctr_encrypt;aes_128_eax_decrypt;eap_psk_process_3"),
+ (1, "aes_128_ctr_encrypt;aes_128_eax_encrypt;eap_psk_process_3") ]
+ for count, func in tests:
+ with fail_test(dev[0], count, func):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PSK", identity="psk.user@example.com",
+ password_hex="0123456789abcdef0123456789abcdef",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ wait_fail_trigger(dev[0], "GET_FAIL",
+ note="No failure seen for %d:%s" % (count, func))
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+EAP_SIM_SUBTYPE_START = 10
+EAP_SIM_SUBTYPE_CHALLENGE = 11
+EAP_SIM_SUBTYPE_NOTIFICATION = 12
+EAP_SIM_SUBTYPE_REAUTHENTICATION = 13
+EAP_SIM_SUBTYPE_CLIENT_ERROR = 14
+
+EAP_AKA_SUBTYPE_CHALLENGE = 1
+EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT = 2
+EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE = 4
+EAP_AKA_SUBTYPE_IDENTITY = 5
+EAP_AKA_SUBTYPE_NOTIFICATION = 12
+EAP_AKA_SUBTYPE_REAUTHENTICATION = 13
+EAP_AKA_SUBTYPE_CLIENT_ERROR = 14
+
+EAP_SIM_AT_RAND = 1
+EAP_SIM_AT_AUTN = 2
+EAP_SIM_AT_RES = 3
+EAP_SIM_AT_AUTS = 4
+EAP_SIM_AT_PADDING = 6
+EAP_SIM_AT_NONCE_MT = 7
+EAP_SIM_AT_PERMANENT_ID_REQ = 10
+EAP_SIM_AT_MAC = 11
+EAP_SIM_AT_NOTIFICATION = 12
+EAP_SIM_AT_ANY_ID_REQ = 13
+EAP_SIM_AT_IDENTITY = 14
+EAP_SIM_AT_VERSION_LIST = 15
+EAP_SIM_AT_SELECTED_VERSION = 16
+EAP_SIM_AT_FULLAUTH_ID_REQ = 17
+EAP_SIM_AT_COUNTER = 19
+EAP_SIM_AT_COUNTER_TOO_SMALL = 20
+EAP_SIM_AT_NONCE_S = 21
+EAP_SIM_AT_CLIENT_ERROR_CODE = 22
+EAP_SIM_AT_KDF_INPUT = 23
+EAP_SIM_AT_KDF = 24
+EAP_SIM_AT_IV = 129
+EAP_SIM_AT_ENCR_DATA = 130
+EAP_SIM_AT_NEXT_PSEUDONYM = 132
+EAP_SIM_AT_NEXT_REAUTH_ID = 133
+EAP_SIM_AT_CHECKCODE = 134
+EAP_SIM_AT_RESULT_IND = 135
+EAP_SIM_AT_BIDDING = 136
+
+def test_eap_proto_aka(dev, apdev):
+ """EAP-AKA protocol tests"""
+ def aka_handler(ctx, req):
+ logger.info("aka_handler - RX " + req.encode("hex"))
+ if 'num' not in ctx:
+ ctx['num'] = 0
+ ctx['num'] = ctx['num'] + 1
+ if 'id' not in ctx:
+ ctx['id'] = 1
+ ctx['id'] = (ctx['id'] + 1) % 256
+
+ idx = 0
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Missing payload")
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1,
+ EAP_TYPE_AKA)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unknown subtype")
+ return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3,
+ EAP_TYPE_AKA, 255, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Client Error")
+ return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CLIENT_ERROR, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Too short attribute header")
+ return struct.pack(">BBHBBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 3,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0, 255)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Truncated attribute")
+ return struct.pack(">BBHBBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0, 255,
+ 255)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Too short attribute data")
+ return struct.pack(">BBHBBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0, 255,
+ 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Skippable/non-skippable unrecognzized attribute")
+ return struct.pack(">BBHBBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 10,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ 255, 1, 0, 127, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity request without ID type")
+ return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity request ANY_ID")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_ANY_ID_REQ, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity request ANY_ID (duplicate)")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_ANY_ID_REQ, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity request ANY_ID")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_ANY_ID_REQ, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity request FULLAUTH_ID")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity request FULLAUTH_ID (duplicate)")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity request ANY_ID")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_ANY_ID_REQ, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity request FULLAUTH_ID")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity request PERMANENT_ID")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_PERMANENT_ID_REQ, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity request PERMANENT_ID (duplicate)")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_PERMANENT_ID_REQ, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Challenge with no attributes")
+ return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: AKA Challenge with BIDDING")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_BIDDING, 1, 0x8000)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Notification with no attributes")
+ return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Notification indicating success, but no MAC")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
+ EAP_SIM_AT_NOTIFICATION, 1, 32768)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Notification indicating success, but invalid MAC value")
+ return struct.pack(">BBHBBHBBHBBH4L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4 + 20,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
+ EAP_SIM_AT_NOTIFICATION, 1, 32768,
+ EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Notification indicating success with zero-key MAC")
+ return struct.pack(">BBHBBHBBHBBH16B", EAP_CODE_REQUEST,
+ ctx['id'] - 2,
+ 4 + 1 + 3 + 4 + 20,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
+ EAP_SIM_AT_NOTIFICATION, 1, 32768,
+ EAP_SIM_AT_MAC, 5, 0,
+ 0xbe, 0x2e, 0xbb, 0xa9, 0xfa, 0x2e, 0x82, 0x36,
+ 0x37, 0x8c, 0x32, 0x41, 0xb7, 0xc7, 0x58, 0xa3)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Success")
+ return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Notification before auth")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
+ EAP_SIM_AT_NOTIFICATION, 1, 16384)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Notification before auth")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
+ EAP_SIM_AT_NOTIFICATION, 1, 16385)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Notification with unrecognized non-failure")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
+ EAP_SIM_AT_NOTIFICATION, 1, 0xc000)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Notification before auth (duplicate)")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
+ EAP_SIM_AT_NOTIFICATION, 1, 0xc000)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Re-authentication (unexpected) with no attributes")
+ return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_REAUTHENTICATION,
+ 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: AKA Challenge with Checkcode claiming identity round was used")
+ return struct.pack(">BBHBBHBBH5L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 24,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_CHECKCODE, 6, 0, 0, 0, 0, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity request ANY_ID")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_ANY_ID_REQ, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: AKA Challenge with Checkcode claiming no identity round was used")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_CHECKCODE, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity request ANY_ID")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_ANY_ID_REQ, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: AKA Challenge with mismatching Checkcode value")
+ return struct.pack(">BBHBBHBBH5L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 24,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_CHECKCODE, 6, 0, 0, 0, 0, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Re-authentication (unexpected) with Checkcode claimin identity round was used")
+ return struct.pack(">BBHBBHBBH5L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 24,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_REAUTHENTICATION,
+ 0,
+ EAP_SIM_AT_CHECKCODE, 6, 0, 0, 0, 0, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Invalid AT_RAND length")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_RAND, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Invalid AT_AUTN length")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_AUTN, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unencrypted AT_PADDING")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_PADDING, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Invalid AT_NONCE_MT length")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_NONCE_MT, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Invalid AT_MAC length")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_MAC, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Invalid AT_NOTIFICATION length")
+ return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_NOTIFICATION, 2, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: AT_IDENTITY overflow")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_IDENTITY, 1, 0xffff)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unexpected AT_VERSION_LIST")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_VERSION_LIST, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Invalid AT_SELECTED_VERSION length")
+ return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_SELECTED_VERSION, 2, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unencrypted AT_COUNTER")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_COUNTER, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unencrypted AT_COUNTER_TOO_SMALL")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_COUNTER_TOO_SMALL, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unencrypted AT_NONCE_S")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_NONCE_S, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Invalid AT_CLIENT_ERROR_CODE length")
+ return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_CLIENT_ERROR_CODE, 2, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Invalid AT_IV length")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_IV, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Invalid AT_ENCR_DATA length")
+ return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_ENCR_DATA, 2, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unencrypted AT_NEXT_PSEUDONYM")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_NEXT_PSEUDONYM, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unencrypted AT_NEXT_REAUTH_ID")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_NEXT_REAUTH_ID, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Invalid AT_RES length")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_RES, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Invalid AT_RES length")
+ return struct.pack(">BBHBBHBBH5L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 24,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_RES, 6, 0xffff, 0, 0, 0, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Invalid AT_AUTS length")
+ return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_AUTS, 2, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Invalid AT_CHECKCODE length")
+ return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_CHECKCODE, 2, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Invalid AT_RESULT_IND length")
+ return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_RESULT_IND, 2, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unexpected AT_KDF_INPUT")
+ return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_KDF_INPUT, 2, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
- if ctx['num'] == 1:
- logger.info("Test: Empty payload")
- return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1,
- EAP_TYPE_OTP)
- if ctx['num'] == 2:
- logger.info("Test: Success")
- return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'],
- 4)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unexpected AT_KDF")
+ return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_KDF, 2, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
- if ctx['num'] == 3:
- logger.info("Test: Challenge included")
- return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1,
- EAP_TYPE_OTP,
- ord('A'))
- if ctx['num'] == 4:
- logger.info("Test: Success")
- return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'],
- 4)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Invalid AT_BIDDING length")
+ return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_BIDDING, 2, 0, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
return None
- srv = start_radius_server(otp_handler)
+ srv = start_radius_server(aka_handler)
try:
- hapd = start_ap(apdev[0]['ifname'])
+ hapd = start_ap(apdev[0])
- for i in range(0, 1):
+ for i in range(0, 49):
+ eap = "AKA AKA'" if i == 11 else "AKA"
dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
- eap="OTP", identity="user", password="password",
+ eap=eap, identity="0232010000000000",
+ password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123",
wait_connect=False)
ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
timeout=15)
if ev is None:
raise Exception("Timeout on EAP start")
- time.sleep(0.1)
+ if i in [ 0, 15 ]:
+ time.sleep(0.1)
+ else:
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
+ timeout=10)
+ if ev is None:
+ raise Exception("Timeout on EAP failure")
dev[0].request("REMOVE_NETWORK all")
-
- dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
- eap="OTP", identity="user", wait_connect=False)
- ev = dev[0].wait_event(["CTRL-REQ-OTP"])
- if ev is None:
- raise Exception("Request for password timed out")
- id = ev.split(':')[0].split('-')[-1]
- dev[0].request("CTRL-RSP-OTP-" + id + ":password")
- ev = dev[0].wait_event("CTRL-EVENT-EAP-SUCCESS")
- if ev is None:
- raise Exception("Success not reported")
+ dev[0].dump_monitor()
finally:
stop_radius_server(srv)
-EAP_GPSK_OPCODE_GPSK_1 = 1
-EAP_GPSK_OPCODE_GPSK_2 = 2
-EAP_GPSK_OPCODE_GPSK_3 = 3
-EAP_GPSK_OPCODE_GPSK_4 = 4
-EAP_GPSK_OPCODE_FAIL = 5
-EAP_GPSK_OPCODE_PROTECTED_FAIL = 6
-
-def test_eap_proto_gpsk(dev, apdev):
- """EAP-GPSK protocol tests"""
- def gpsk_handler(ctx, req):
- logger.info("gpsk_handler - RX " + req.encode("hex"))
+def test_eap_proto_aka_prime(dev, apdev):
+ """EAP-AKA' protocol tests"""
+ def aka_prime_handler(ctx, req):
+ logger.info("aka_prime_handler - RX " + req.encode("hex"))
if 'num' not in ctx:
ctx['num'] = 0
ctx['num'] = ctx['num'] + 1
logger.info("Test: Missing payload")
return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
4 + 1,
- EAP_TYPE_GPSK)
-
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Unknown opcode")
- return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1,
- EAP_TYPE_GPSK,
- 255)
-
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Unexpected GPSK-3")
- return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_3)
-
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Too short GPSK-1")
- return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1)
-
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Truncated ID_Server")
- return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 1)
+ EAP_TYPE_AKA_PRIME)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Missing RAND_Server")
+ logger.info("Test: Challenge with no attributes")
return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 0)
-
+ 4 + 1 + 3,
+ EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Missing CSuite_List")
- return struct.pack(">BBHBBH8L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 32,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0)
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Truncated CSuite_List")
- return struct.pack(">BBHBBH8LH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 32 + 2,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 1)
-
+ logger.info("Test: Challenge with empty AT_KDF_INPUT")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_KDF_INPUT, 1, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Empty CSuite_List")
- return struct.pack(">BBHBBH8LH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 32 + 2,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0)
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Invalid CSuite_List")
- return struct.pack(">BBHBBH8LHB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 32 + 2 + 1,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 0)
-
+ logger.info("Test: Challenge with AT_KDF_INPUT")
+ return struct.pack(">BBHBBHBBHBBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
+ ord('c'), ord('d'))
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-1 No supported CSuite")
- return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 32 + 2 + 6,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 0, 0)
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Supported CSuite")
- return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 32 + 2 + 6,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 0, 1)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Unexpected GPSK-1")
- return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 32 + 2 + 6,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 0, 1)
-
+ logger.info("Test: Challenge with duplicated KDF")
+ return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8 + 3 * 4,
+ EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
+ ord('c'), ord('d'),
+ EAP_SIM_AT_KDF, 1, 1,
+ EAP_SIM_AT_KDF, 1, 2,
+ EAP_SIM_AT_KDF, 1, 1)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Supported CSuite but too short key")
- return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 32 + 2 + 6,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 0, 1)
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Supported CSuite")
- return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 32 + 2 + 6,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 0, 1)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Too short GPSK-3")
- return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_3)
-
+ logger.info("Test: Challenge with multiple KDF proposals")
+ return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8 + 3 * 4,
+ EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
+ ord('c'), ord('d'),
+ EAP_SIM_AT_KDF, 1, 255,
+ EAP_SIM_AT_KDF, 1, 254,
+ EAP_SIM_AT_KDF, 1, 1)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Supported CSuite")
- return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 32 + 2 + 6,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 0, 1)
+ logger.info("Test: Challenge with incorrect KDF selected")
+ return struct.pack(">BBHBBHBBHBBBBBBHBBHBBHBBH",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8 + 4 * 4,
+ EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
+ ord('c'), ord('d'),
+ EAP_SIM_AT_KDF, 1, 255,
+ EAP_SIM_AT_KDF, 1, 255,
+ EAP_SIM_AT_KDF, 1, 254,
+ EAP_SIM_AT_KDF, 1, 1)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-3 Mismatch in RAND_Peer")
- return struct.pack(">BBHBB8L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 32,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_3,
- 0, 0, 0, 0, 0, 0, 0, 0)
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Supported CSuite")
- return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 32 + 2 + 6,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 0, 1)
+ logger.info("Test: Challenge with multiple KDF proposals")
+ return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8 + 3 * 4,
+ EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
+ ord('c'), ord('d'),
+ EAP_SIM_AT_KDF, 1, 255,
+ EAP_SIM_AT_KDF, 1, 254,
+ EAP_SIM_AT_KDF, 1, 1)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-3 Missing RAND_Server")
- msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 32,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_3)
- msg += req[14:46]
- return msg
-
+ logger.info("Test: Challenge with selected KDF not duplicated")
+ return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8 + 3 * 4,
+ EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
+ ord('c'), ord('d'),
+ EAP_SIM_AT_KDF, 1, 1,
+ EAP_SIM_AT_KDF, 1, 255,
+ EAP_SIM_AT_KDF, 1, 254)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Supported CSuite")
- return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 32 + 2 + 6,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 0, 1)
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-3 Mismatch in RAND_Server")
- msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 32 + 32,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_3)
- msg += req[14:46]
- msg += struct.pack(">8L", 1, 1, 1, 1, 1, 1, 1, 1)
- return msg
-
+ logger.info("Test: Challenge with multiple KDF proposals")
+ return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8 + 3 * 4,
+ EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
+ ord('c'), ord('d'),
+ EAP_SIM_AT_KDF, 1, 255,
+ EAP_SIM_AT_KDF, 1, 254,
+ EAP_SIM_AT_KDF, 1, 1)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Supported CSuite")
- return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 32 + 2 + 6,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 0, 1)
+ logger.info("Test: Challenge with selected KDF duplicated (missing MAC, RAND, AUTN)")
+ return struct.pack(">BBHBBHBBHBBBBBBHBBHBBHBBH",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8 + 4 * 4,
+ EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
+ ord('c'), ord('d'),
+ EAP_SIM_AT_KDF, 1, 1,
+ EAP_SIM_AT_KDF, 1, 255,
+ EAP_SIM_AT_KDF, 1, 254,
+ EAP_SIM_AT_KDF, 1, 1)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-3 Missing ID_Server")
- msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 32 + 32,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_3)
- msg += req[14:46]
- msg += struct.pack(">8L", 0, 0, 0, 0, 0, 0, 0, 0)
- return msg
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Supported CSuite")
- return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 32 + 2 + 6,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 0, 1)
+ logger.info("Test: Challenge with multiple unsupported KDF proposals")
+ return struct.pack(">BBHBBHBBHBBBBBBHBBH",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8 + 2 * 4,
+ EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
+ ord('c'), ord('d'),
+ EAP_SIM_AT_KDF, 1, 255,
+ EAP_SIM_AT_KDF, 1, 254)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-3 Truncated ID_Server")
- msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 32 + 32 + 2,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_3)
- msg += req[14:46]
- msg += struct.pack(">8LH", 0, 0, 0, 0, 0, 0, 0, 0, 1)
- return msg
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Supported CSuite")
- return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 32 + 2 + 6,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 0, 1)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: GPSK-3 Mismatch in ID_Server")
- msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 32 + 32 + 3,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_3)
- msg += req[14:46]
- msg += struct.pack(">8LHB", 0, 0, 0, 0, 0, 0, 0, 0, 1, ord('B'))
- return msg
-
+ logger.info("Test: Challenge with multiple KDF proposals")
+ return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8 + 3 * 4,
+ EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
+ ord('c'), ord('d'),
+ EAP_SIM_AT_KDF, 1, 255,
+ EAP_SIM_AT_KDF, 1, 254,
+ EAP_SIM_AT_KDF, 1, 1)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Supported CSuite")
- return struct.pack(">BBHBBHB8LHLH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 3 + 32 + 2 + 6,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 1, ord('A'),
- 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 0, 1)
+ logger.info("Test: Challenge with invalid MAC, RAND, AUTN values)")
+ return struct.pack(">BBHBBHBBHBBBBBBHBBHBBHBBHBBH4LBBH4LBBH4L",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8 + 4 * 4 + 20 + 20 + 20,
+ EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
+ ord('c'), ord('d'),
+ EAP_SIM_AT_KDF, 1, 1,
+ EAP_SIM_AT_KDF, 1, 255,
+ EAP_SIM_AT_KDF, 1, 254,
+ EAP_SIM_AT_KDF, 1, 1,
+ EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0,
+ EAP_SIM_AT_RAND, 5, 0, 0, 0, 0, 0,
+ EAP_SIM_AT_AUTN, 5, 0, 0, 0, 0, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-3 Mismatch in ID_Server (same length)")
- msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 32 + 32 + 3,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_3)
- msg += req[15:47]
- msg += struct.pack(">8LHB", 0, 0, 0, 0, 0, 0, 0, 0, 1, ord('B'))
- return msg
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Supported CSuite")
- return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 32 + 2 + 6,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 0, 1)
+ logger.info("Test: Challenge - AMF separation bit not set)")
+ return struct.pack(">BBHBBHBBHBBBBBBHBBH4LBBH4LBBH4L",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8 + 4 + 20 + 20 + 20,
+ EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
+ ord('c'), ord('d'),
+ EAP_SIM_AT_KDF, 1, 1,
+ EAP_SIM_AT_MAC, 5, 0, 1, 2, 3, 4,
+ EAP_SIM_AT_RAND, 5, 0, 5, 6, 7, 8,
+ EAP_SIM_AT_AUTN, 5, 0, 9, 10,
+ 0x2fda8ef7, 0xbba518cc)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-3 Missing CSuite_Sel")
- msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 32 + 32 + 2,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_3)
- msg += req[14:46]
- msg += struct.pack(">8LH", 0, 0, 0, 0, 0, 0, 0, 0, 0)
- return msg
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Supported CSuite")
- return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 32 + 2 + 6,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 0, 1)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: GPSK-3 Mismatch in CSuite_Sel")
- msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 32 + 32 + 2 + 6,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_3)
- msg += req[14:46]
- msg += struct.pack(">8LHLH", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2)
- return msg
-
+ logger.info("Test: Challenge - Invalid MAC")
+ return struct.pack(">BBHBBHBBHBBBBBBHBBH4LBBH4LBBH4L",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8 + 4 + 20 + 20 + 20,
+ EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
+ ord('c'), ord('d'),
+ EAP_SIM_AT_KDF, 1, 1,
+ EAP_SIM_AT_MAC, 5, 0, 1, 2, 3, 4,
+ EAP_SIM_AT_RAND, 5, 0, 5, 6, 7, 8,
+ EAP_SIM_AT_AUTN, 5, 0, 0xffffffff, 0xffffffff,
+ 0xd1f90322, 0x40514cb4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Supported CSuite")
- return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 32 + 2 + 6,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 0, 1)
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-3 Missing len(PD_Payload_Block)")
- msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 32 + 32 + 2 + 6,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_3)
- msg += req[14:46]
- msg += struct.pack(">8LHLH", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)
- return msg
+ logger.info("Test: Challenge - Valid MAC")
+ return struct.pack(">BBHBBHBBHBBBBBBHBBH4LBBH4LBBH4L",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8 + 4 + 20 + 20 + 20,
+ EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
+ ord('c'), ord('d'),
+ EAP_SIM_AT_KDF, 1, 1,
+ EAP_SIM_AT_MAC, 5, 0,
+ 0xf4a3c1d3, 0x7c901401, 0x34bd8b01, 0x6f7fa32f,
+ EAP_SIM_AT_RAND, 5, 0, 5, 6, 7, 8,
+ EAP_SIM_AT_AUTN, 5, 0, 0xffffffff, 0xffffffff,
+ 0xd1f90322, 0x40514cb4)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Supported CSuite")
- return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 32 + 2 + 6,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 0, 1)
+ logger.info("Test: Invalid AT_KDF_INPUT length")
+ return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_KDF_INPUT, 2, 0xffff, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-3 Truncated PD_Payload_Block")
- msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 32 + 32 + 2 + 6 + 2,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_3)
- msg += req[14:46]
- msg += struct.pack(">8LHLHH", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1)
- return msg
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Supported CSuite")
- return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 32 + 2 + 6,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 0, 1)
+ logger.info("Test: Invalid AT_KDF length")
+ return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_IDENTITY, 0,
+ EAP_SIM_AT_KDF, 2, 0, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-3 Missing MAC")
- msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 32 + 32 + 2 + 6 + 3,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_3)
- msg += req[14:46]
- msg += struct.pack(">8LHLHHB",
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 123)
- return msg
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-1 Supported CSuite")
- return struct.pack(">BBHBBH8LHLH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 32 + 2 + 6,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 6, 0, 1)
+ logger.info("Test: Challenge with large number of KDF proposals")
+ return struct.pack(">BBHBBHBBHBBHBBHBBHBBHBBHBBHBBHBBHBBHBBHBBH",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 12 * 4,
+ EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_KDF, 1, 255,
+ EAP_SIM_AT_KDF, 1, 254,
+ EAP_SIM_AT_KDF, 1, 253,
+ EAP_SIM_AT_KDF, 1, 252,
+ EAP_SIM_AT_KDF, 1, 251,
+ EAP_SIM_AT_KDF, 1, 250,
+ EAP_SIM_AT_KDF, 1, 249,
+ EAP_SIM_AT_KDF, 1, 248,
+ EAP_SIM_AT_KDF, 1, 247,
+ EAP_SIM_AT_KDF, 1, 246,
+ EAP_SIM_AT_KDF, 1, 245,
+ EAP_SIM_AT_KDF, 1, 244)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: GPSK-3 Incorrect MAC")
- msg = struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 32 + 32 + 2 + 6 + 3 + 16,
- EAP_TYPE_GPSK,
- EAP_GPSK_OPCODE_GPSK_3)
- msg += req[14:46]
- msg += struct.pack(">8LHLHHB4L",
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 123,
- 0, 0, 0, 0)
- return msg
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
return None
- srv = start_radius_server(gpsk_handler)
+ srv = start_radius_server(aka_prime_handler)
try:
- hapd = start_ap(apdev[0]['ifname'])
+ hapd = start_ap(apdev[0])
- for i in range(0, 27):
- if i == 12:
- pw = "short"
- else:
- pw = "abcdefghijklmnop0123456789abcdef"
+ for i in range(0, 16):
dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
- eap="GPSK", identity="user", password=pw,
+ eap="AKA'", identity="6555444333222111",
+ password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123",
wait_connect=False)
ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
timeout=15)
if ev is None:
raise Exception("Timeout on EAP start")
- time.sleep(0.05)
+ if i in [ 0 ]:
+ time.sleep(0.1)
+ else:
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
+ timeout=10)
+ if ev is None:
+ raise Exception("Timeout on EAP failure")
dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
finally:
stop_radius_server(srv)
-EAP_EKE_ID = 1
-EAP_EKE_COMMIT = 2
-EAP_EKE_CONFIRM = 3
-EAP_EKE_FAILURE = 4
-
-def test_eap_proto_eke(dev, apdev):
- """EAP-EKE protocol tests"""
- def eke_handler(ctx, req):
- logger.info("eke_handler - RX " + req.encode("hex"))
+def test_eap_proto_sim(dev, apdev):
+ """EAP-SIM protocol tests"""
+ def sim_handler(ctx, req):
+ logger.info("sim_handler - RX " + req.encode("hex"))
if 'num' not in ctx:
ctx['num'] = 0
ctx['num'] = ctx['num'] + 1
logger.info("Test: Missing payload")
return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
4 + 1,
- EAP_TYPE_EKE)
-
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Unknown exchange")
- return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1,
- EAP_TYPE_EKE,
- 255)
-
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: No NumProposals in EAP-EKE-ID/Request")
- return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1,
- EAP_TYPE_EKE,
- EAP_EKE_ID)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
-
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: NumProposals=0 in EAP-EKE-ID/Request")
- return struct.pack(">BBHBBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 1,
- EAP_TYPE_EKE,
- EAP_EKE_ID,
- 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
-
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Truncated Proposals list in EAP-EKE-ID/Request")
- return struct.pack(">BBHBBBB4B", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 4,
- EAP_TYPE_EKE,
- EAP_EKE_ID,
- 2, 0, 0, 0, 0, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ EAP_TYPE_SIM)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unsupported proposals in EAP-EKE-ID/Request")
- return struct.pack(">BBHBBBB4B4B4B4B", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 4 * 4,
- EAP_TYPE_EKE,
- EAP_EKE_ID,
- 4, 0,
- 0, 0, 0, 0,
- 3, 0, 0, 0,
- 3, 1, 0, 0,
- 3, 1, 1, 0)
+ logger.info("Test: Unexpected AT_AUTN")
+ return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
+ EAP_SIM_AT_AUTN, 2, 0, 0)
idx += 1
if ctx['num'] == idx:
logger.info("Test: EAP-Failure")
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Missing IDType/Identity in EAP-EKE-ID/Request")
- return struct.pack(">BBHBBBB4B4B4B4B4B",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 5 * 4,
- EAP_TYPE_EKE,
- EAP_EKE_ID,
- 5, 0,
- 0, 0, 0, 0,
- 3, 0, 0, 0,
- 3, 1, 0, 0,
- 3, 1, 1, 0,
- 3, 1, 1, 1)
+ logger.info("Test: Too short AT_VERSION_LIST")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
+ EAP_SIM_AT_VERSION_LIST, 1, 0)
idx += 1
if ctx['num'] == idx:
logger.info("Test: EAP-Failure")
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Valid EAP-EKE-ID/Request")
- return struct.pack(">BBHBBBB4BB",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 4 + 1,
- EAP_TYPE_EKE,
- EAP_EKE_ID,
- 1, 0,
- 3, 1, 1, 1,
- 255)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Unexpected EAP-EKE-ID/Request")
- return struct.pack(">BBHBBBB4BB",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 4 + 1,
- EAP_TYPE_EKE,
- EAP_EKE_ID,
- 1, 0,
- 3, 1, 1, 1,
- 255)
+ logger.info("Test: AT_VERSION_LIST overflow")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
+ EAP_SIM_AT_VERSION_LIST, 1, 0xffff)
idx += 1
if ctx['num'] == idx:
logger.info("Test: EAP-Failure")
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Valid EAP-EKE-ID/Request")
- return struct.pack(">BBHBBBB4BB",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 4 + 1,
- EAP_TYPE_EKE,
- EAP_EKE_ID,
- 1, 0,
- 3, 1, 1, 1,
- 255)
+ logger.info("Test: Unexpected AT_AUTS")
+ return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
+ EAP_SIM_AT_AUTS, 2, 0, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unexpected EAP-EKE-Confirm/Request")
- return struct.pack(">BBHBB",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1,
- EAP_TYPE_EKE,
- EAP_EKE_CONFIRM)
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unexpected AT_CHECKCODE")
+ return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
+ EAP_SIM_AT_CHECKCODE, 2, 0, 0)
idx += 1
if ctx['num'] == idx:
logger.info("Test: EAP-Failure")
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Too short EAP-EKE-Failure/Request")
- return struct.pack(">BBHBB",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1,
- EAP_TYPE_EKE,
- EAP_EKE_FAILURE)
+ logger.info("Test: No AT_VERSION_LIST in Start")
+ return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0)
idx += 1
if ctx['num'] == idx:
logger.info("Test: EAP-Failure")
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unexpected EAP-EKE-Commit/Request")
- return struct.pack(">BBHBB",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1,
- EAP_TYPE_EKE,
- EAP_EKE_COMMIT)
+ logger.info("Test: No support version in AT_VERSION_LIST")
+ return struct.pack(">BBHBBHBBH4B", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
+ EAP_SIM_AT_VERSION_LIST, 2, 3, 2, 3, 4, 5)
idx += 1
if ctx['num'] == idx:
logger.info("Test: EAP-Failure")
return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Valid EAP-EKE-ID/Request")
- return struct.pack(">BBHBBBB4BB",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 4 + 1,
- EAP_TYPE_EKE,
- EAP_EKE_ID,
- 1, 0,
- 3, 1, 1, 1,
- 255)
+ logger.info("Test: Identity request without ID type")
+ return struct.pack(">BBHBBHBBH2H", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
+ EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Too short EAP-EKE-Commit/Request")
- return struct.pack(">BBHBB",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1,
- EAP_TYPE_EKE,
- EAP_EKE_COMMIT)
+ logger.info("Test: Identity request ANY_ID")
+ return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8 + 4,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
+ EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
+ EAP_SIM_AT_ANY_ID_REQ, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity request ANY_ID (duplicate)")
+ return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8 + 4,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
+ EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
+ EAP_SIM_AT_ANY_ID_REQ, 1, 0)
idx += 1
if ctx['num'] == idx:
logger.info("Test: EAP-Failure")
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Valid EAP-EKE-ID/Request")
- return struct.pack(">BBHBBBB4BB",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 4 + 1,
- EAP_TYPE_EKE,
- EAP_EKE_ID,
- 1, 0,
- 1, 1, 1, 1,
- 255)
+ logger.info("Test: Identity request ANY_ID")
+ return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8 + 4,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
+ EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
+ EAP_SIM_AT_ANY_ID_REQ, 1, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: All zeroes DHComponent_S and empty CBvalue in EAP-EKE-Commit/Request")
- return struct.pack(">BBHBB4L32L",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 16 + 128,
- EAP_TYPE_EKE,
- EAP_EKE_COMMIT,
- 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+ logger.info("Test: Identity request FULLAUTH_ID")
+ return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8 + 4,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
+ EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
+ EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Too short EAP-EKE-Confirm/Request")
- return struct.pack(">BBHBB",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1,
- EAP_TYPE_EKE,
- EAP_EKE_CONFIRM)
+ logger.info("Test: Identity request FULLAUTH_ID (duplicate)")
+ return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8 + 4,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
+ EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
+ EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
idx += 1
if ctx['num'] == idx:
logger.info("Test: EAP-Failure")
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Valid EAP-EKE-ID/Request")
- return struct.pack(">BBHBBBB4BB",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2 + 4 + 1,
- EAP_TYPE_EKE,
- EAP_EKE_ID,
- 1, 0,
- 1, 1, 1, 1,
- 255)
+ logger.info("Test: Identity request ANY_ID")
+ return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8 + 4,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
+ EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
+ EAP_SIM_AT_ANY_ID_REQ, 1, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: All zeroes DHComponent_S and empty CBvalue in EAP-EKE-Commit/Request")
- return struct.pack(">BBHBB4L32L",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 16 + 128,
- EAP_TYPE_EKE,
- EAP_EKE_COMMIT,
- 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+ logger.info("Test: Identity request FULLAUTH_ID")
+ return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8 + 4,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
+ EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
+ EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Invalid PNonce_PS and Auth_S values in EAP-EKE-Confirm/Request")
- return struct.pack(">BBHBB4L8L5L5L",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 16 + 2 * 16 + 20 + 20,
- EAP_TYPE_EKE,
- EAP_EKE_CONFIRM,
- 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0)
+ logger.info("Test: Identity request PERMANENT_ID")
+ return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8 + 4,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
+ EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
+ EAP_SIM_AT_PERMANENT_ID_REQ, 1, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Identity request PERMANENT_ID (duplicate)")
+ return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 8 + 4,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
+ EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
+ EAP_SIM_AT_PERMANENT_ID_REQ, 1, 0)
idx += 1
if ctx['num'] == idx:
logger.info("Test: EAP-Failure")
return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
- return None
-
- srv = start_radius_server(eke_handler)
-
- try:
- hapd = start_ap(apdev[0]['ifname'])
-
- for i in range(0, 14):
- dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
- eap="EKE", identity="user", password="password",
- wait_connect=False)
- ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
- timeout=15)
- if ev is None:
- raise Exception("Timeout on EAP start")
- if i in [ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]:
- ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
- timeout=10)
- if ev is None:
- raise Exception("Timeout on EAP failure")
- else:
- time.sleep(0.05)
- dev[0].request("REMOVE_NETWORK all")
- dev[0].dump_monitor()
- finally:
- stop_radius_server(srv)
-
-EAP_PAX_OP_STD_1 = 0x01
-EAP_PAX_OP_STD_2 = 0x02
-EAP_PAX_OP_STD_3 = 0x03
-EAP_PAX_OP_SEC_1 = 0x11
-EAP_PAX_OP_SEC_2 = 0x12
-EAP_PAX_OP_SEC_3 = 0x13
-EAP_PAX_OP_SEC_4 = 0x14
-EAP_PAX_OP_SEC_5 = 0x15
-EAP_PAX_OP_ACK = 0x21
-
-EAP_PAX_FLAGS_MF = 0x01
-EAP_PAX_FLAGS_CE = 0x02
-EAP_PAX_FLAGS_AI = 0x04
-
-EAP_PAX_MAC_HMAC_SHA1_128 = 0x01
-EAP_PAX_HMAC_SHA256_128 = 0x02
-
-EAP_PAX_DH_GROUP_NONE = 0x00
-EAP_PAX_DH_GROUP_2048_MODP = 0x01
-EAP_PAX_DH_GROUP_3072_MODP = 0x02
-EAP_PAX_DH_GROUP_NIST_ECC_P_256 = 0x03
-
-EAP_PAX_PUBLIC_KEY_NONE = 0x00
-EAP_PAX_PUBLIC_KEY_RSAES_OAEP = 0x01
-EAP_PAX_PUBLIC_KEY_RSA_PKCS1_V1_5 = 0x02
-EAP_PAX_PUBLIC_KEY_EL_GAMAL_NIST_ECC = 0x03
-
-EAP_PAX_ADE_VENDOR_SPECIFIC = 0x01
-EAP_PAX_ADE_CLIENT_CHANNEL_BINDING = 0x02
-EAP_PAX_ADE_SERVER_CHANNEL_BINDING = 0x03
-
-def test_eap_proto_pax(dev, apdev):
- """EAP-PAX protocol tests"""
- def pax_std_1(ctx):
- logger.info("Test: STD-1")
- ctx['id'] = 10
- return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 5 + 2 + 32 + 16,
- EAP_TYPE_PAX,
- EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
- EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
- 32, 0, 0, 0, 0, 0, 0, 0, 0,
- 0x16, 0xc9, 0x08, 0x9d, 0x98, 0xa5, 0x6e, 0x1f,
- 0xf0, 0xac, 0xcf, 0xc4, 0x66, 0xcd, 0x2d, 0xbf)
-
- def pax_handler(ctx, req):
- logger.info("pax_handler - RX " + req.encode("hex"))
- if 'num' not in ctx:
- ctx['num'] = 0
- ctx['num'] = ctx['num'] + 1
- if 'id' not in ctx:
- ctx['id'] = 1
- ctx['id'] = (ctx['id'] + 1) % 256
-
- idx = 0
-
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Missing payload")
- return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1,
- EAP_TYPE_PAX)
+ logger.info("Test: No AT_MAC and AT_RAND in Challenge")
+ return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Minimum length payload")
- return struct.pack(">BBHB4L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 16,
- EAP_TYPE_PAX,
- 0, 0, 0, 0)
-
+ logger.info("Test: No AT_RAND in Challenge")
+ return struct.pack(">BBHBBHBBH4L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 20,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unsupported MAC ID")
- return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 5 + 16,
- EAP_TYPE_PAX,
- EAP_PAX_OP_STD_1, 0, 255, EAP_PAX_DH_GROUP_NONE,
- EAP_PAX_PUBLIC_KEY_NONE,
- 0, 0, 0, 0)
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unsupported DH Group ID")
- return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 5 + 16,
- EAP_TYPE_PAX,
- EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
- 255, EAP_PAX_PUBLIC_KEY_NONE,
- 0, 0, 0, 0)
-
+ logger.info("Test: Insufficient number of challenges in Challenge")
+ return struct.pack(">BBHBBHBBH4LBBH4L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 20 + 20,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_RAND, 5, 0, 0, 0, 0, 0,
+ EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unsupported Public Key ID")
- return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 5 + 16,
- EAP_TYPE_PAX,
- EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
- EAP_PAX_DH_GROUP_NONE, 255,
- 0, 0, 0, 0)
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: More fragments")
- return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 5 + 16,
- EAP_TYPE_PAX,
- EAP_PAX_OP_STD_1, EAP_PAX_FLAGS_MF,
- EAP_PAX_MAC_HMAC_SHA1_128,
- EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
- 0, 0, 0, 0)
-
+ logger.info("Test: Too many challenges in Challenge")
+ return struct.pack(">BBHBBHBBH4L4L4L4LBBH4L", EAP_CODE_REQUEST,
+ ctx['id'],
+ 4 + 1 + 3 + 4 + 4 * 16 + 20,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_RAND, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Invalid ICV")
- return struct.pack(">BBHBBBBBB4L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 5 + 16,
- EAP_TYPE_PAX,
- EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
- EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
- 0, 0, 0, 0)
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Invalid ICV in short frame")
- return struct.pack(">BBHBBBBBB3L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 5 + 12,
- EAP_TYPE_PAX,
- EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
- EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
- 0, 0, 0)
-
+ logger.info("Test: Same RAND multiple times in Challenge")
+ return struct.pack(">BBHBBHBBH4L4L4LBBH4L", EAP_CODE_REQUEST,
+ ctx['id'],
+ 4 + 1 + 3 + 4 + 3 * 16 + 20,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0,
+ EAP_SIM_AT_RAND, 13, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0,
+ EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Correct ICV - unsupported op_code")
- ctx['id'] = 10
- return struct.pack(">BBHBBBBBB16B", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 5 + 16,
- EAP_TYPE_PAX,
- 255, 0, EAP_PAX_MAC_HMAC_SHA1_128,
- EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
- 0x90, 0x78, 0x97, 0x38, 0x29, 0x94, 0x32, 0xd4,
- 0x81, 0x27, 0xe0, 0xf6, 0x3b, 0x0d, 0xb2, 0xb2)
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Correct ICV - CE flag in STD-1")
- ctx['id'] = 10
- return struct.pack(">BBHBBBBBB16B", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 5 + 16,
- EAP_TYPE_PAX,
- EAP_PAX_OP_STD_1, EAP_PAX_FLAGS_CE,
- EAP_PAX_MAC_HMAC_SHA1_128,
- EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
- 0x9c, 0x98, 0xb4, 0x0b, 0x94, 0x90, 0xde, 0x88,
- 0xb7, 0x72, 0x63, 0x44, 0x1d, 0xe3, 0x7c, 0x5c)
-
+ logger.info("Test: Notification with no attributes")
+ return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Correct ICV - too short STD-1 payload")
- ctx['id'] = 10
- return struct.pack(">BBHBBBBBB16B", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 5 + 16,
- EAP_TYPE_PAX,
- EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
- EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
- 0xda, 0xab, 0x2c, 0xe7, 0x84, 0x41, 0xb5, 0x5c,
- 0xee, 0xcf, 0x62, 0x03, 0xc5, 0x69, 0xcb, 0xf4)
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Correct ICV - incorrect A length in STD-1")
- ctx['id'] = 10
- return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 5 + 2 + 32 + 16,
- EAP_TYPE_PAX,
- EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
- EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0xc4, 0xb0, 0x81, 0xe4, 0x6c, 0x8c, 0x20, 0x23,
- 0x60, 0x46, 0x89, 0xea, 0x94, 0x60, 0xf3, 0x2a)
+ logger.info("Test: Notification indicating success, but no MAC")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
+ EAP_SIM_AT_NOTIFICATION, 1, 32768)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Correct ICV - extra data in STD-1")
- ctx['id'] = 10
- return struct.pack(">BBHBBBBBBH8LB16B", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 5 + 2 + 32 + 1 + 16,
- EAP_TYPE_PAX,
- EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
- EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
- 32, 0, 0, 0, 0, 0, 0, 0, 0,
- 1,
- 0x61, 0x49, 0x65, 0x37, 0x21, 0xe8, 0xd8, 0xbf,
- 0xf3, 0x02, 0x01, 0xe5, 0x42, 0x51, 0xd3, 0x34)
+ logger.info("Test: Notification indicating success, but invalid MAC value")
+ return struct.pack(">BBHBBHBBHBBH4L", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4 + 20,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
+ EAP_SIM_AT_NOTIFICATION, 1, 32768,
+ EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unexpected STD-1")
- return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 5 + 2 + 32 + 16,
- EAP_TYPE_PAX,
- EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
- EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
- 32, 0, 0, 0, 0, 0, 0, 0, 0,
- 0xe5, 0x1d, 0xbf, 0xb8, 0x70, 0x20, 0x5c, 0xba,
- 0x41, 0xbb, 0x34, 0xda, 0x1a, 0x08, 0xe6, 0x8d)
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- return pax_std_1(ctx)
+ logger.info("Test: Notification before auth")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
+ EAP_SIM_AT_NOTIFICATION, 1, 16384)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: MAC ID changed during session")
- return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 5 + 2 + 32 + 16,
- EAP_TYPE_PAX,
- EAP_PAX_OP_STD_1, 0, EAP_PAX_HMAC_SHA256_128,
- EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
- 32, 0, 0, 0, 0, 0, 0, 0, 0,
- 0xee, 0x00, 0xbf, 0xb8, 0x70, 0x20, 0x5c, 0xba,
- 0x41, 0xbb, 0x34, 0xda, 0x1a, 0x08, 0xe6, 0x8d)
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- return pax_std_1(ctx)
+ logger.info("Test: Notification before auth")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
+ EAP_SIM_AT_NOTIFICATION, 1, 16385)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: DH Group ID changed during session")
- return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 5 + 2 + 32 + 16,
- EAP_TYPE_PAX,
- EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
- EAP_PAX_DH_GROUP_2048_MODP,
- EAP_PAX_PUBLIC_KEY_NONE,
- 32, 0, 0, 0, 0, 0, 0, 0, 0,
- 0xee, 0x01, 0xbf, 0xb8, 0x70, 0x20, 0x5c, 0xba,
- 0x41, 0xbb, 0x34, 0xda, 0x1a, 0x08, 0xe6, 0x8d)
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- return pax_std_1(ctx)
+ logger.info("Test: Notification with unrecognized non-failure")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
+ EAP_SIM_AT_NOTIFICATION, 1, 0xc000)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Public Key ID changed during session")
- return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 5 + 2 + 32 + 16,
- EAP_TYPE_PAX,
- EAP_PAX_OP_STD_1, 0, EAP_PAX_MAC_HMAC_SHA1_128,
- EAP_PAX_DH_GROUP_NONE,
- EAP_PAX_PUBLIC_KEY_RSAES_OAEP,
- 32, 0, 0, 0, 0, 0, 0, 0, 0,
- 0xee, 0x02, 0xbf, 0xb8, 0x70, 0x20, 0x5c, 0xba,
- 0x41, 0xbb, 0x34, 0xda, 0x1a, 0x08, 0xe6, 0x8d)
+ logger.info("Test: Notification before auth (duplicate)")
+ return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
+ EAP_SIM_AT_NOTIFICATION, 1, 0xc000)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unexpected STD-3")
- ctx['id'] = 10
- return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 5 + 2 + 32 + 16,
- EAP_TYPE_PAX,
- EAP_PAX_OP_STD_3, 0, EAP_PAX_MAC_HMAC_SHA1_128,
- EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
- 32, 0, 0, 0, 0, 0, 0, 0, 0,
- 0x47, 0xbb, 0xc0, 0xf9, 0xb9, 0x69, 0xf5, 0xcb,
- 0x3a, 0xe8, 0xe7, 0xd6, 0x80, 0x28, 0xf2, 0x59)
+ logger.info("Test: Re-authentication (unexpected) with no attributes")
+ return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_REAUTHENTICATION,
+ 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- return pax_std_1(ctx)
+ logger.info("Test: Client Error")
+ return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3,
+ EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CLIENT_ERROR, 0)
idx += 1
if ctx['num'] == idx:
- # TODO: MAC calculation; for now, this gets dropped due to incorrect
- # ICV
- logger.info("Test: STD-3 with CE flag")
- return struct.pack(">BBHBBBBBBH8L16B", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 5 + 2 + 32 + 16,
- EAP_TYPE_PAX,
- EAP_PAX_OP_STD_3, EAP_PAX_FLAGS_CE,
- EAP_PAX_MAC_HMAC_SHA1_128,
- EAP_PAX_DH_GROUP_NONE, EAP_PAX_PUBLIC_KEY_NONE,
- 32, 0, 0, 0, 0, 0, 0, 0, 0,
- 0x8a, 0xc2, 0xf9, 0xf4, 0x8b, 0x75, 0x72, 0xa2,
- 0x4d, 0xd3, 0x1e, 0x54, 0x77, 0x04, 0x05, 0xe2)
+ logger.info("Test: EAP-Failure")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
- if ctx['num'] & 0x1 == idx & 0x1:
- logger.info("Test: Default request")
- return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1,
- EAP_TYPE_PAX)
- else:
- logger.info("Test: Default EAP-Failure")
+ if ctx['num'] == idx:
+ logger.info("Test: Unknown subtype")
+ return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3,
+ EAP_TYPE_SIM, 255, 0)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: EAP-Failure")
return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
- srv = start_radius_server(pax_handler)
+ return None
+
+ srv = start_radius_server(sim_handler)
try:
- hapd = start_ap(apdev[0]['ifname'])
+ hapd = start_ap(apdev[0])
- for i in range(0, 18):
+ for i in range(0, 25):
dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
- eap="PAX", identity="user",
- password_hex="0123456789abcdef0123456789abcdef",
+ eap="SIM", identity="1232010000000000",
+ password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
wait_connect=False)
- logger.info("Waiting for EAP method to start")
ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
timeout=15)
if ev is None:
raise Exception("Timeout on EAP start")
- time.sleep(0.05)
+ if i in [ 0 ]:
+ time.sleep(0.1)
+ else:
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
+ timeout=10)
+ if ev is None:
+ raise Exception("Timeout on EAP failure")
dev[0].request("REMOVE_NETWORK all")
dev[0].dump_monitor()
+ finally:
+ stop_radius_server(srv)
- logger.info("Too short password")
+def test_eap_proto_sim_errors(dev, apdev):
+ """EAP-SIM protocol tests (error paths)"""
+ check_hlr_auc_gw_support()
+ params = hostapd.wpa2_eap_params(ssid="eap-test")
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ with alloc_fail(dev[0], 1, "eap_sim_init"):
dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
- eap="PAX", identity="user",
- password_hex="0123456789abcdef0123456789abcd",
+ eap="SIM", identity="1232010000000000",
+ password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
wait_connect=False)
- ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
+ ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
+ timeout=15)
if ev is None:
raise Exception("Timeout on EAP start")
- time.sleep(0.1)
dev[0].request("REMOVE_NETWORK all")
- dev[0].dump_monitor()
+ dev[0].wait_disconnected()
- logger.info("No password")
+ with fail_test(dev[0], 1, "os_get_random;eap_sim_init"):
dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
- eap="PAX", identity="user",
+ eap="SIM", identity="1232010000000000",
+ password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
wait_connect=False)
- ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
+ ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
+ timeout=15)
if ev is None:
raise Exception("Timeout on EAP start")
- time.sleep(0.1)
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="SIM", identity="1232010000000000",
+ password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
+
+ with fail_test(dev[0], 1, "aes_128_cbc_encrypt;eap_sim_response_reauth"):
+ hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
+ if ev is None:
+ raise Exception("EAP re-authentication did not start")
+ wait_fail_trigger(dev[0], "GET_FAIL")
dev[0].request("REMOVE_NETWORK all")
dev[0].dump_monitor()
- finally:
- stop_radius_server(srv)
-def test_eap_proto_psk(dev, apdev):
- """EAP-PSK protocol tests"""
- def psk_handler(ctx, req):
- logger.info("psk_handler - RX " + req.encode("hex"))
- if 'num' not in ctx:
- ctx['num'] = 0
- ctx['num'] = ctx['num'] + 1
- if 'id' not in ctx:
- ctx['id'] = 1
- ctx['id'] = (ctx['id'] + 1) % 256
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="SIM", identity="1232010000000000",
+ password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
- idx = 0
+ with fail_test(dev[0], 1, "os_get_random;eap_sim_msg_add_encr_start"):
+ hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
+ if ev is None:
+ raise Exception("EAP re-authentication did not start")
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Missing payload")
- return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1,
- EAP_TYPE_PSK)
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="SIM", identity="1232010000000000",
+ password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Non-zero T in first message")
- return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 16,
- EAP_TYPE_PSK, 0xc0, 0, 0, 0, 0)
+ with fail_test(dev[0], 1, "os_get_random;eap_sim_init_for_reauth"):
+ hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
+ if ev is None:
+ raise Exception("EAP re-authentication did not start")
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Valid first message")
- return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 16,
- EAP_TYPE_PSK, 0, 0, 0, 0, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Too short third message")
- return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1,
- EAP_TYPE_PSK)
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="SIM", identity="1232010000000000",
+ password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Valid first message")
- return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 16,
- EAP_TYPE_PSK, 0, 0, 0, 0, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Incorrect T in third message")
- return struct.pack(">BBHBB4L4L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 16 + 16,
- EAP_TYPE_PSK, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+ with alloc_fail(dev[0], 1, "eap_sim_parse_encr;eap_sim_process_reauthentication"):
+ hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
+ if ev is None:
+ raise Exception("EAP re-authentication did not start")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Valid first message")
- return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 16,
- EAP_TYPE_PSK, 0, 0, 0, 0, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Missing PCHANNEL in third message")
- return struct.pack(">BBHBB4L4L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 16 + 16,
- EAP_TYPE_PSK, 0x80, 0, 0, 0, 0, 0, 0, 0, 0)
+ tests = [ (1, "eap_sim_verify_mac;eap_sim_process_challenge"),
+ (1, "eap_sim_parse_encr;eap_sim_process_challenge"),
+ (1, "eap_sim_msg_init;eap_sim_response_start"),
+ (1, "wpabuf_alloc;eap_sim_msg_init;eap_sim_response_start"),
+ (1, "=eap_sim_learn_ids"),
+ (2, "=eap_sim_learn_ids"),
+ (2, "eap_sim_learn_ids"),
+ (3, "eap_sim_learn_ids"),
+ (1, "eap_sim_process_start"),
+ (1, "eap_sim_getKey"),
+ (1, "eap_sim_get_emsk"),
+ (1, "eap_sim_get_session_id") ]
+ for count, func in tests:
+ with alloc_fail(dev[0], count, func):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="SIM", identity="1232010000000000",
+ password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
+ erp="1", wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Valid first message")
- return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 16,
- EAP_TYPE_PSK, 0, 0, 0, 0, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Invalic MAC_S in third message")
- return struct.pack(">BBHBB4L4L5LB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 16 + 16 + 21,
- EAP_TYPE_PSK, 0x80, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0)
+ tests = [ (1, "aes_128_cbc_decrypt;eap_sim_parse_encr") ]
+ for count, func in tests:
+ with fail_test(dev[0], count, func):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="SIM", identity="1232010000000000",
+ password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Valid first message")
- return struct.pack(">BBHBB4L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 16,
- EAP_TYPE_PSK, 0, 0, 0, 0, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ params = int_eap_server_params()
+ params['eap_sim_db'] = "unix:/tmp/hlr_auc_gw.sock"
+ params['eap_sim_aka_result_ind'] = "1"
+ hostapd.add_ap(apdev[1], params)
+
+ with alloc_fail(dev[0], 1,
+ "eap_sim_msg_init;eap_sim_response_notification"):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
+ scan_freq="2412",
+ eap="SIM", identity="1232010000000000",
+ phase1="result_ind=1",
+ password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
- return None
+ tests = [ "eap_sim_msg_add_encr_start;eap_sim_response_notification",
+ "aes_128_cbc_encrypt;eap_sim_response_notification" ]
+ for func in tests:
+ with fail_test(dev[0], 1, func):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
+ scan_freq="2412",
+ eap="SIM", identity="1232010000000000",
+ phase1="result_ind=1",
+ password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
+ dev[0].request("REAUTHENTICATE")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
+ if ev is None:
+ raise Exception("EAP method not started on reauthentication")
+ time.sleep(0.1)
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
- srv = start_radius_server(psk_handler)
+ tests = [ "eap_sim_parse_encr;eap_sim_process_notification_reauth" ]
+ for func in tests:
+ with alloc_fail(dev[0], 1, func):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
+ scan_freq="2412",
+ eap="SIM", identity="1232010000000000",
+ phase1="result_ind=1",
+ password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581")
+ dev[0].request("REAUTHENTICATE")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
+ if ev is None:
+ raise Exception("EAP method not started on reauthentication")
+ time.sleep(0.1)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
- try:
- hapd = start_ap(apdev[0]['ifname'])
+def test_eap_proto_aka_errors(dev, apdev):
+ """EAP-AKA protocol tests (error paths)"""
+ check_hlr_auc_gw_support()
+ params = hostapd.wpa2_eap_params(ssid="eap-test")
+ hapd = hostapd.add_ap(apdev[0], params)
- for i in range(0, 6):
+ with alloc_fail(dev[0], 1, "eap_aka_init"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="AKA", identity="0232010000000000",
+ password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123",
+ wait_connect=False)
+ ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ (1, "=eap_aka_learn_ids"),
+ (2, "=eap_aka_learn_ids"),
+ (1, "eap_sim_parse_encr;eap_aka_process_challenge"),
+ (1, "wpabuf_dup;eap_aka_add_id_msg"),
+ (1, "wpabuf_resize;eap_aka_add_id_msg"),
+ (1, "eap_aka_getKey"),
+ (1, "eap_aka_get_emsk"),
+ (1, "eap_aka_get_session_id") ]
+ for count, func in tests:
+ with alloc_fail(dev[0], count, func):
dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
- eap="PSK", identity="user",
- password_hex="0123456789abcdef0123456789abcdef",
- wait_connect=False)
- ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
- timeout=15)
+ eap="AKA", identity="0232010000000000",
+ password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123",
+ erp="1", wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
+
+ params = int_eap_server_params()
+ params['eap_sim_db'] = "unix:/tmp/hlr_auc_gw.sock"
+ params['eap_sim_aka_result_ind'] = "1"
+ hostapd.add_ap(apdev[1], params)
+
+ with alloc_fail(dev[0], 1,
+ "eap_sim_msg_init;eap_aka_response_notification"):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="AKA", identity="0232010000000000",
+ phase1="result_ind=1",
+ password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
+
+ tests = [ "eap_sim_msg_add_encr_start;eap_aka_response_notification",
+ "aes_128_cbc_encrypt;eap_aka_response_notification" ]
+ for func in tests:
+ with fail_test(dev[0], 1, func):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
+ scan_freq="2412",
+ eap="AKA", identity="0232010000000000",
+ phase1="result_ind=1",
+ password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123")
+ dev[0].request("REAUTHENTICATE")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
if ev is None:
- raise Exception("Timeout on EAP start")
+ raise Exception("EAP method not started on reauthentication")
time.sleep(0.1)
+ wait_fail_trigger(dev[0], "GET_FAIL")
dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
- logger.info("Test: Invalid PSK length")
+ tests = [ "eap_sim_parse_encr;eap_aka_process_notification_reauth" ]
+ for func in tests:
+ with alloc_fail(dev[0], 1, func):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
+ scan_freq="2412",
+ eap="AKA", identity="0232010000000000",
+ phase1="result_ind=1",
+ password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123")
+ dev[0].request("REAUTHENTICATE")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
+ if ev is None:
+ raise Exception("EAP method not started on reauthentication")
+ time.sleep(0.1)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
+
+def test_eap_proto_aka_prime_errors(dev, apdev):
+ """EAP-AKA' protocol tests (error paths)"""
+ check_hlr_auc_gw_support()
+ params = hostapd.wpa2_eap_params(ssid="eap-test")
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ with alloc_fail(dev[0], 1, "eap_aka_init"):
dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
- eap="PSK", identity="user",
- password_hex="0123456789abcdef0123456789abcd",
+ eap="AKA'", identity="6555444333222111",
+ password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123",
wait_connect=False)
- ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
timeout=15)
if ev is None:
raise Exception("Timeout on EAP start")
- time.sleep(0.1)
dev[0].request("REMOVE_NETWORK all")
- finally:
- stop_radius_server(srv)
+ dev[0].wait_disconnected()
-EAP_SIM_SUBTYPE_START = 10
-EAP_SIM_SUBTYPE_CHALLENGE = 11
-EAP_SIM_SUBTYPE_NOTIFICATION = 12
-EAP_SIM_SUBTYPE_REAUTHENTICATION = 13
-EAP_SIM_SUBTYPE_CLIENT_ERROR = 14
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="AKA'", identity="6555444333222111",
+ password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123")
-EAP_AKA_SUBTYPE_CHALLENGE = 1
-EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT = 2
-EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE = 4
-EAP_AKA_SUBTYPE_IDENTITY = 5
-EAP_AKA_SUBTYPE_NOTIFICATION = 12
-EAP_AKA_SUBTYPE_REAUTHENTICATION = 13
-EAP_AKA_SUBTYPE_CLIENT_ERROR = 14
+ with fail_test(dev[0], 1, "aes_128_cbc_encrypt;eap_aka_response_reauth"):
+ hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
+ if ev is None:
+ raise Exception("EAP re-authentication did not start")
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
+
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="AKA'", identity="6555444333222111",
+ password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123")
+
+ with alloc_fail(dev[0], 1, "eap_sim_parse_encr;eap_aka_process_reauthentication"):
+ hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
+ if ev is None:
+ raise Exception("EAP re-authentication did not start")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
+
+ tests = [ (1, "eap_sim_verify_mac_sha256"),
+ (1, "=eap_aka_process_challenge") ]
+ for count, func in tests:
+ with alloc_fail(dev[0], count, func):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="AKA'", identity="6555444333222111",
+ password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123",
+ erp="1", wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
-EAP_SIM_AT_RAND = 1
-EAP_SIM_AT_AUTN = 2
-EAP_SIM_AT_RES = 3
-EAP_SIM_AT_AUTS = 4
-EAP_SIM_AT_PADDING = 6
-EAP_SIM_AT_NONCE_MT = 7
-EAP_SIM_AT_PERMANENT_ID_REQ = 10
-EAP_SIM_AT_MAC = 11
-EAP_SIM_AT_NOTIFICATION = 12
-EAP_SIM_AT_ANY_ID_REQ = 13
-EAP_SIM_AT_IDENTITY = 14
-EAP_SIM_AT_VERSION_LIST = 15
-EAP_SIM_AT_SELECTED_VERSION = 16
-EAP_SIM_AT_FULLAUTH_ID_REQ = 17
-EAP_SIM_AT_COUNTER = 19
-EAP_SIM_AT_COUNTER_TOO_SMALL = 20
-EAP_SIM_AT_NONCE_S = 21
-EAP_SIM_AT_CLIENT_ERROR_CODE = 22
-EAP_SIM_AT_KDF_INPUT = 23
-EAP_SIM_AT_KDF = 24
-EAP_SIM_AT_IV = 129
-EAP_SIM_AT_ENCR_DATA = 130
-EAP_SIM_AT_NEXT_PSEUDONYM = 132
-EAP_SIM_AT_NEXT_REAUTH_ID = 133
-EAP_SIM_AT_CHECKCODE = 134
-EAP_SIM_AT_RESULT_IND = 135
-EAP_SIM_AT_BIDDING = 136
+def test_eap_proto_ikev2(dev, apdev):
+ """EAP-IKEv2 protocol tests"""
+ check_eap_capa(dev[0], "IKEV2")
-def test_eap_proto_aka(dev, apdev):
- """EAP-AKA protocol tests"""
- def aka_handler(ctx, req):
- logger.info("aka_handler - RX " + req.encode("hex"))
+ global eap_proto_ikev2_test_done
+ eap_proto_ikev2_test_done = False
+
+ def ikev2_handler(ctx, req):
+ logger.info("ikev2_handler - RX " + req.encode("hex"))
if 'num' not in ctx:
ctx['num'] = 0
ctx['num'] = ctx['num'] + 1
logger.info("Test: Missing payload")
return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
4 + 1,
- EAP_TYPE_AKA)
-
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Unknown subtype")
- return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3,
- EAP_TYPE_AKA, 255, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
-
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Client Error")
- return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CLIENT_ERROR, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ EAP_TYPE_IKEV2)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Too short attribute header")
- return struct.pack(">BBHBBHB", EAP_CODE_REQUEST, ctx['id'],
+ logger.info("Test: Truncated Message Length field")
+ return struct.pack(">BBHBB3B", EAP_CODE_REQUEST, ctx['id'],
4 + 1 + 1 + 3,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0, 255)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ EAP_TYPE_IKEV2, 0x80, 0, 0, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Truncated attribute")
- return struct.pack(">BBHBBHBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0, 255,
- 255)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Too short Message Length value")
+ return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 4 + 1,
+ EAP_TYPE_IKEV2, 0x80, 0, 1)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Too short attribute data")
- return struct.pack(">BBHBBHBB", EAP_CODE_REQUEST, ctx['id'],
+ logger.info("Test: Truncated message")
+ return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
4 + 1 + 1 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0, 255,
- 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
-
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Skippable/non-skippable unrecognzized attribute")
- return struct.pack(">BBHBBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 10,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- 255, 1, 0, 127, 1, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
-
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Identity request without ID type")
- return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Identity request ANY_ID")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_ANY_ID_REQ, 1, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Identity request ANY_ID (duplicate)")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_ANY_ID_REQ, 1, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
-
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Identity request ANY_ID")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_ANY_ID_REQ, 1, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Identity request FULLAUTH_ID")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Identity request FULLAUTH_ID (duplicate)")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ EAP_TYPE_IKEV2, 0x80, 1)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Identity request ANY_ID")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_ANY_ID_REQ, 1, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Identity request FULLAUTH_ID")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Identity request PERMANENT_ID")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_PERMANENT_ID_REQ, 1, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Identity request PERMANENT_ID (duplicate)")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_PERMANENT_ID_REQ, 1, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Truncated message(2)")
+ return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 4,
+ EAP_TYPE_IKEV2, 0x80, 0xffffffff)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Challenge with no attributes")
- return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Truncated message(3)")
+ return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 4,
+ EAP_TYPE_IKEV2, 0xc0, 0xffffffff)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: AKA Challenge with BIDDING")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_BIDDING, 1, 0x8000)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Truncated message(4)")
+ return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 4,
+ EAP_TYPE_IKEV2, 0xc0, 10000000)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Notification with no attributes")
- return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Too long fragments (first fragment)")
+ return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 4 + 1,
+ EAP_TYPE_IKEV2, 0xc0, 2, 1)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Notification indicating success, but no MAC")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
- EAP_SIM_AT_NOTIFICATION, 1, 32768)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Too long fragments (second fragment)")
+ return struct.pack(">BBHBB2B", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2,
+ EAP_TYPE_IKEV2, 0x00, 2, 3)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Notification indicating success, but invalid MAC value")
- return struct.pack(">BBHBBHBBHBBH4L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4 + 20,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
- EAP_SIM_AT_NOTIFICATION, 1, 32768,
- EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: No Message Length field in first fragment")
+ return struct.pack(">BBHBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 1,
+ EAP_TYPE_IKEV2, 0x40, 1)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Notification indicating success with zero-key MAC")
- return struct.pack(">BBHBBHBBHBBH16B", EAP_CODE_REQUEST,
- ctx['id'] - 2,
- 4 + 1 + 3 + 4 + 20,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
- EAP_SIM_AT_NOTIFICATION, 1, 32768,
- EAP_SIM_AT_MAC, 5, 0,
- 0xbe, 0x2e, 0xbb, 0xa9, 0xfa, 0x2e, 0x82, 0x36,
- 0x37, 0x8c, 0x32, 0x41, 0xb7, 0xc7, 0x58, 0xa3)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Success")
- return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
+ logger.info("Test: ICV before keys")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_IKEV2, 0x20)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Notification before auth")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
- EAP_SIM_AT_NOTIFICATION, 1, 16384)
+ logger.info("Test: Unsupported IKEv2 header version")
+ return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 28,
+ EAP_TYPE_IKEV2, 0x00,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Incorrect IKEv2 header Length")
+ return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 28,
+ EAP_TYPE_IKEV2, 0x00,
+ 0, 0, 0, 0,
+ 0, 0x20, 0, 0, 0, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Notification before auth")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
- EAP_SIM_AT_NOTIFICATION, 1, 16385)
+ logger.info("Test: Unexpected IKEv2 Exchange Type in SA_INIT state")
+ return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 28,
+ EAP_TYPE_IKEV2, 0x00,
+ 0, 0, 0, 0,
+ 0, 0x20, 0, 0, 0, 28)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Unexpected IKEv2 Message ID in SA_INIT state")
+ return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 28,
+ EAP_TYPE_IKEV2, 0x00,
+ 0, 0, 0, 0,
+ 0, 0x20, 34, 0, 1, 28)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Notification with unrecognized non-failure")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
- EAP_SIM_AT_NOTIFICATION, 1, 0xc000)
+ logger.info("Test: Unexpected IKEv2 Flags value")
+ return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 28,
+ EAP_TYPE_IKEV2, 0x00,
+ 0, 0, 0, 0,
+ 0, 0x20, 34, 0, 0, 28)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Notification before auth (duplicate)")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION, 0,
- EAP_SIM_AT_NOTIFICATION, 1, 0xc000)
+ logger.info("Test: Unexpected IKEv2 Flags value(2)")
+ return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 28,
+ EAP_TYPE_IKEV2, 0x00,
+ 0, 0, 0, 0,
+ 0, 0x20, 34, 0x20, 0, 28)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: No SAi1 in SA_INIT")
+ return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 28,
+ EAP_TYPE_IKEV2, 0x00,
+ 0, 0, 0, 0,
+ 0, 0x20, 34, 0x08, 0, 28)
+
+ def build_ike(id, next=0, exch_type=34, flags=0x00, ike=''):
+ return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, id,
+ 4 + 1 + 1 + 28 + len(ike),
+ EAP_TYPE_IKEV2, flags,
+ 0, 0, 0, 0,
+ next, 0x20, exch_type, 0x08, 0,
+ 28 + len(ike)) + ike
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Re-authentication (unexpected) with no attributes")
- return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_REAUTHENTICATION,
- 0)
+ logger.info("Test: Unexpected extra data after payloads")
+ return build_ike(ctx['id'], ike=struct.pack(">B", 1))
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Truncated payload header")
+ return build_ike(ctx['id'], next=128, ike=struct.pack(">B", 1))
idx += 1
if ctx['num'] == idx:
- logger.info("Test: AKA Challenge with Checkcode claiming identity round was used")
- return struct.pack(">BBHBBHBBH5L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 24,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_CHECKCODE, 6, 0, 0, 0, 0, 0, 0)
+ logger.info("Test: Too small payload header length")
+ ike = struct.pack(">BBH", 0, 0, 3)
+ return build_ike(ctx['id'], next=128, ike=ike)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Too large payload header length")
+ ike = struct.pack(">BBH", 0, 0, 5)
+ return build_ike(ctx['id'], next=128, ike=ike)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Identity request ANY_ID")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_ANY_ID_REQ, 1, 0)
+ logger.info("Test: Unsupported payload (non-critical and critical)")
+ ike = struct.pack(">BBHBBH", 129, 0, 4, 0, 0x01, 4)
+ return build_ike(ctx['id'], next=128, ike=ike)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: AKA Challenge with Checkcode claiming no identity round was used")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_CHECKCODE, 1, 0)
+ logger.info("Test: Certificate and empty SAi1")
+ ike = struct.pack(">BBHBBH", 33, 0, 4, 0, 0, 4)
+ return build_ike(ctx['id'], next=37, ike=ike)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Too short proposal")
+ ike = struct.pack(">BBHBBHBBB", 0, 0, 4 + 7,
+ 0, 0, 7, 0, 0, 0)
+ return build_ike(ctx['id'], next=33, ike=ike)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Identity request ANY_ID")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_ANY_ID_REQ, 1, 0)
+ logger.info("Test: Too small proposal length in SAi1")
+ ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
+ 0, 0, 7, 0, 0, 0, 0)
+ return build_ike(ctx['id'], next=33, ike=ike)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: AKA Challenge with mismatching Checkcode value")
- return struct.pack(">BBHBBHBBH5L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 24,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_CHECKCODE, 6, 0, 0, 0, 0, 0, 0)
+ logger.info("Test: Too large proposal length in SAi1")
+ ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
+ 0, 0, 9, 0, 0, 0, 0)
+ return build_ike(ctx['id'], next=33, ike=ike)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Unexpected proposal type in SAi1")
+ ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
+ 1, 0, 8, 0, 0, 0, 0)
+ return build_ike(ctx['id'], next=33, ike=ike)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Re-authentication (unexpected) with Checkcode claimin identity round was used")
- return struct.pack(">BBHBBHBBH5L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 24,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_REAUTHENTICATION,
- 0,
- EAP_SIM_AT_CHECKCODE, 6, 0, 0, 0, 0, 0, 0)
+ logger.info("Test: Unexpected Protocol ID in SAi1")
+ ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
+ 0, 0, 8, 0, 0, 0, 0)
+ return build_ike(ctx['id'], next=33, ike=ike)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Unexpected proposal number in SAi1")
+ ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
+ 0, 0, 8, 0, 1, 0, 0)
+ return build_ike(ctx['id'], next=33, ike=ike)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Invalid AT_RAND length")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_RAND, 1, 0)
+ logger.info("Test: Not enough room for SPI in SAi1")
+ ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
+ 0, 0, 8, 1, 1, 1, 0)
+ return build_ike(ctx['id'], next=33, ike=ike)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Unexpected SPI in SAi1")
+ ike = struct.pack(">BBHBBHBBBBB", 0, 0, 4 + 9,
+ 0, 0, 9, 1, 1, 1, 0, 1)
+ return build_ike(ctx['id'], next=33, ike=ike)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Invalid AT_AUTN length")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_AUTN, 1, 0)
+ logger.info("Test: No transforms in SAi1")
+ ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
+ 0, 0, 8, 1, 1, 0, 0)
+ return build_ike(ctx['id'], next=33, ike=ike)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Too short transform in SAi1")
+ ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
+ 0, 0, 8, 1, 1, 0, 1)
+ return build_ike(ctx['id'], next=33, ike=ike)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unencrypted AT_PADDING")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_PADDING, 1, 0)
+ logger.info("Test: Too small transform length in SAi1")
+ ike = struct.pack(">BBHBBHBBBBBBHBBH", 0, 0, 4 + 8 + 8,
+ 0, 0, 8 + 8, 1, 1, 0, 1,
+ 0, 0, 7, 0, 0, 0)
+ return build_ike(ctx['id'], next=33, ike=ike)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Too large transform length in SAi1")
+ ike = struct.pack(">BBHBBHBBBBBBHBBH", 0, 0, 4 + 8 + 8,
+ 0, 0, 8 + 8, 1, 1, 0, 1,
+ 0, 0, 9, 0, 0, 0)
+ return build_ike(ctx['id'], next=33, ike=ike)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Invalid AT_NONCE_MT length")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_NONCE_MT, 1, 0)
+ logger.info("Test: Unexpected Transform type in SAi1")
+ ike = struct.pack(">BBHBBHBBBBBBHBBH", 0, 0, 4 + 8 + 8,
+ 0, 0, 8 + 8, 1, 1, 0, 1,
+ 1, 0, 8, 0, 0, 0)
+ return build_ike(ctx['id'], next=33, ike=ike)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: No transform attributes in SAi1")
+ ike = struct.pack(">BBHBBHBBBBBBHBBH", 0, 0, 4 + 8 + 8,
+ 0, 0, 8 + 8, 1, 1, 0, 1,
+ 0, 0, 8, 0, 0, 0)
+ return build_ike(ctx['id'], next=33, ike=ike)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Invalid AT_MAC length")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_MAC, 1, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: No transform attr for AES and unexpected data after transforms in SAi1")
+ tlen1 = 8 + 3
+ tlen2 = 8 + 4
+ tlen3 = 8 + 4
+ tlen = tlen1 + tlen2 + tlen3
+ ike = struct.pack(">BBHBBHBBBBBBHBBH3BBBHBBHHHBBHBBHHHB",
+ 0, 0, 4 + 8 + tlen + 1,
+ 0, 0, 8 + tlen + 1, 1, 1, 0, 3,
+ 3, 0, tlen1, 1, 0, 12, 1, 2, 3,
+ 3, 0, tlen2, 1, 0, 12, 0, 128,
+ 0, 0, tlen3, 1, 0, 12, 0x8000 | 14, 127,
+ 1)
+ return build_ike(ctx['id'], next=33, ike=ike)
+
+ def build_sa(next=0):
+ tlen = 5 * 8
+ return struct.pack(">BBHBBHBBBBBBHBBHBBHBBHBBHBBHBBHBBHBBHBBH",
+ next, 0, 4 + 8 + tlen,
+ 0, 0, 8 + tlen, 1, 1, 0, 5,
+ 3, 0, 8, 1, 0, 3,
+ 3, 0, 8, 2, 0, 1,
+ 3, 0, 8, 3, 0, 1,
+ 3, 0, 8, 4, 0, 5,
+ 0, 0, 8, 241, 0, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Invalid AT_NOTIFICATION length")
- return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_NOTIFICATION, 2, 0, 0)
+ logger.info("Test: Valid proposal, but no KEi in SAi1")
+ ike = build_sa()
+ return build_ike(ctx['id'], next=33, ike=ike)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Empty KEi in SAi1")
+ ike = build_sa(next=34) + struct.pack(">BBH", 0, 0, 4)
+ return build_ike(ctx['id'], next=33, ike=ike)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: AT_IDENTITY overflow")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_IDENTITY, 1, 0xffff)
+ logger.info("Test: Mismatch in DH Group in SAi1")
+ ike = build_sa(next=34)
+ ike += struct.pack(">BBHHH", 0, 0, 4 + 4 + 96, 12345, 0)
+ ike += 96*'\x00'
+ return build_ike(ctx['id'], next=33, ike=ike)
idx += 1
if ctx['num'] == idx:
logger.info("Test: EAP-Failure")
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unexpected AT_VERSION_LIST")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_VERSION_LIST, 1, 0)
+ logger.info("Test: Invalid DH public value length in SAi1")
+ ike = build_sa(next=34)
+ ike += struct.pack(">BBHHH", 0, 0, 4 + 4 + 96, 5, 0)
+ ike += 96*'\x00'
+ return build_ike(ctx['id'], next=33, ike=ike)
+
+ def build_ke(next=0):
+ ke = struct.pack(">BBHHH", next, 0, 4 + 4 + 192, 5, 0)
+ ke += 192*'\x00'
+ return ke
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Valid proposal and KEi, but no Ni in SAi1")
+ ike = build_sa(next=34)
+ ike += build_ke()
+ return build_ike(ctx['id'], next=33, ike=ike)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Invalid AT_SELECTED_VERSION length")
- return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_SELECTED_VERSION, 2, 0, 0)
+ logger.info("Test: Too short Ni in SAi1")
+ ike = build_sa(next=34)
+ ike += build_ke(next=40)
+ ike += struct.pack(">BBH", 0, 0, 4)
+ return build_ike(ctx['id'], next=33, ike=ike)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Too long Ni in SAi1")
+ ike = build_sa(next=34)
+ ike += build_ke(next=40)
+ ike += struct.pack(">BBH", 0, 0, 4 + 257) + 257*'\x00'
+ return build_ike(ctx['id'], next=33, ike=ike)
+
+ def build_ni(next=0):
+ return struct.pack(">BBH", next, 0, 4 + 256) + 256*'\x00'
+
+ def build_sai1(id):
+ ike = build_sa(next=34)
+ ike += build_ke(next=40)
+ ike += build_ni()
+ return build_ike(ctx['id'], next=33, ike=ike)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unencrypted AT_COUNTER")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_COUNTER, 1, 0)
+ logger.info("Test: Valid proposal, KEi, and Ni in SAi1")
+ return build_sai1(ctx['id'])
idx += 1
if ctx['num'] == idx:
logger.info("Test: EAP-Failure")
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unencrypted AT_COUNTER_TOO_SMALL")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_COUNTER_TOO_SMALL, 1, 0)
+ logger.info("Test: Valid proposal, KEi, and Ni in SAi1")
+ return build_sai1(ctx['id'])
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: No integrity checksum")
+ ike = ''
+ return build_ike(ctx['id'], next=37, ike=ike)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unencrypted AT_NONCE_S")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_NONCE_S, 1, 0)
+ logger.info("Test: Valid proposal, KEi, and Ni in SAi1")
+ return build_sai1(ctx['id'])
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Truncated integrity checksum")
+ return struct.pack(">BBHBB",
+ EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_IKEV2, 0x20)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Invalid AT_CLIENT_ERROR_CODE length")
- return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_CLIENT_ERROR_CODE, 2, 0, 0)
+ logger.info("Test: Valid proposal, KEi, and Ni in SAi1")
+ return build_sai1(ctx['id'])
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Invalid integrity checksum")
+ ike = ''
+ return build_ike(ctx['id'], next=37, flags=0x20, ike=ike)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Invalid AT_IV length")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_IV, 1, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("No more test responses available - test case completed")
+ global eap_proto_ikev2_test_done
+ eap_proto_ikev2_test_done = True
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1,
+ EAP_TYPE_IKEV2)
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ srv = start_radius_server(ikev2_handler)
+
+ try:
+ hapd = start_ap(apdev[0])
+
+ i = 0
+ while not eap_proto_ikev2_test_done:
+ i += 1
+ logger.info("Running connection iteration %d" % i)
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="IKEV2", identity="user",
+ password="password",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP method start")
+ if i in [ 41, 46 ]:
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
+ timeout=10)
+ if ev is None:
+ raise Exception("Timeout on EAP failure")
+ else:
+ time.sleep(0.05)
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ dev[0].dump_monitor()
+ dev[1].dump_monitor()
+ dev[2].dump_monitor()
+ finally:
+ stop_radius_server(srv)
+
+def NtPasswordHash(password):
+ pw = password.encode('utf_16_le')
+ return hashlib.new('md4', pw).digest()
+
+def HashNtPasswordHash(password_hash):
+ return hashlib.new('md4', password_hash).digest()
+
+def ChallengeHash(peer_challenge, auth_challenge, username):
+ data = peer_challenge + auth_challenge + username
+ return hashlib.sha1(data).digest()[0:8]
+
+def GenerateAuthenticatorResponse(password, nt_response, peer_challenge,
+ auth_challenge, username):
+ magic1 = binascii.unhexlify("4D616769632073657276657220746F20636C69656E74207369676E696E6720636F6E7374616E74")
+ magic2 = binascii.unhexlify("50616420746F206D616B6520697420646F206D6F7265207468616E206F6E6520697465726174696F6E")
+
+ password_hash = NtPasswordHash(password)
+ password_hash_hash = HashNtPasswordHash(password_hash)
+ data = password_hash_hash + nt_response + magic1
+ digest = hashlib.sha1(data).digest()
+
+ challenge = ChallengeHash(peer_challenge, auth_challenge, username)
+
+ data = digest + challenge + magic2
+ resp = hashlib.sha1(data).digest()
+ return resp
+
+def test_eap_proto_ikev2_errors(dev, apdev):
+ """EAP-IKEv2 local error cases"""
+ check_eap_capa(dev[0], "IKEV2")
+ params = hostapd.wpa2_eap_params(ssid="eap-test")
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ for i in range(1, 5):
+ with alloc_fail(dev[0], i, "eap_ikev2_init"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="IKEV2", identity="ikev2 user",
+ password="ike password",
+ wait_connect=False)
+ ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ (1, "ikev2_encr_encrypt"),
+ (1, "ikev2_encr_decrypt"),
+ (1, "ikev2_derive_auth_data"),
+ (2, "ikev2_derive_auth_data"),
+ (1, "=ikev2_decrypt_payload"),
+ (1, "ikev2_encr_decrypt;ikev2_decrypt_payload"),
+ (1, "ikev2_encr_encrypt;ikev2_build_encrypted"),
+ (1, "ikev2_derive_sk_keys"),
+ (2, "ikev2_derive_sk_keys"),
+ (3, "ikev2_derive_sk_keys"),
+ (4, "ikev2_derive_sk_keys"),
+ (5, "ikev2_derive_sk_keys"),
+ (6, "ikev2_derive_sk_keys"),
+ (7, "ikev2_derive_sk_keys"),
+ (8, "ikev2_derive_sk_keys"),
+ (1, "eap_ikev2_derive_keymat;eap_ikev2_peer_keymat"),
+ (1, "eap_msg_alloc;eap_ikev2_build_msg"),
+ (1, "eap_ikev2_getKey"),
+ (1, "eap_ikev2_get_emsk"),
+ (1, "eap_ikev2_get_session_id"),
+ (1, "=ikev2_derive_keys"),
+ (2, "=ikev2_derive_keys"),
+ (1, "wpabuf_alloc;ikev2_process_kei"),
+ (1, "=ikev2_process_idi"),
+ (1, "ikev2_derive_auth_data;ikev2_build_auth"),
+ (1, "wpabuf_alloc;ikev2_build_sa_init"),
+ (2, "wpabuf_alloc;ikev2_build_sa_init"),
+ (3, "wpabuf_alloc;ikev2_build_sa_init"),
+ (4, "wpabuf_alloc;ikev2_build_sa_init"),
+ (5, "wpabuf_alloc;ikev2_build_sa_init"),
+ (6, "wpabuf_alloc;ikev2_build_sa_init"),
+ (1, "wpabuf_alloc;ikev2_build_sa_auth"),
+ (2, "wpabuf_alloc;ikev2_build_sa_auth"),
+ (1, "ikev2_build_auth;ikev2_build_sa_auth") ]
+ for count, func in tests:
+ with alloc_fail(dev[0], count, func):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="IKEV2", identity="ikev2 user",
+ password="ike password", erp="1", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ ok = False
+ for j in range(10):
+ state = dev[0].request('GET_ALLOC_FAIL')
+ if state.startswith('0:'):
+ ok = True
+ break
+ time.sleep(0.1)
+ if not ok:
+ raise Exception("No allocation failure seen for %d:%s" % (count, func))
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ (1, "wpabuf_alloc;ikev2_build_notify"),
+ (2, "wpabuf_alloc;ikev2_build_notify"),
+ (1, "ikev2_build_encrypted;ikev2_build_notify") ]
+ for count, func in tests:
+ with alloc_fail(dev[0], count, func):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="IKEV2", identity="ikev2 user",
+ password="wrong password", erp="1",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ ok = False
+ for j in range(10):
+ state = dev[0].request('GET_ALLOC_FAIL')
+ if state.startswith('0:'):
+ ok = True
+ break
+ time.sleep(0.1)
+ if not ok:
+ raise Exception("No allocation failure seen for %d:%s" % (count, func))
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ (1, "ikev2_integ_hash"),
+ (1, "ikev2_integ_hash;ikev2_decrypt_payload"),
+ (1, "os_get_random;ikev2_build_encrypted"),
+ (1, "ikev2_prf_plus;ikev2_derive_sk_keys"),
+ (1, "eap_ikev2_derive_keymat;eap_ikev2_peer_keymat"),
+ (1, "os_get_random;ikev2_build_sa_init"),
+ (2, "os_get_random;ikev2_build_sa_init"),
+ (1, "ikev2_integ_hash;eap_ikev2_validate_icv"),
+ (1, "hmac_sha1_vector;?ikev2_prf_hash;ikev2_derive_keys"),
+ (1, "hmac_sha1_vector;?ikev2_prf_hash;ikev2_derive_auth_data"),
+ (2, "hmac_sha1_vector;?ikev2_prf_hash;ikev2_derive_auth_data"),
+ (3, "hmac_sha1_vector;?ikev2_prf_hash;ikev2_derive_auth_data") ]
+ for count, func in tests:
+ with fail_test(dev[0], count, func):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="IKEV2", identity="ikev2 user",
+ password="ike password", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ ok = False
+ for j in range(10):
+ state = dev[0].request('GET_FAIL')
+ if state.startswith('0:'):
+ ok = True
+ break
+ time.sleep(0.1)
+ if not ok:
+ raise Exception("No failure seen for %d:%s" % (count, func))
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ params = { "ssid": "eap-test2", "wpa": "2", "wpa_key_mgmt": "WPA-EAP",
+ "rsn_pairwise": "CCMP", "ieee8021x": "1",
+ "eap_server": "1", "eap_user_file": "auth_serv/eap_user.conf",
+ "fragment_size": "50" }
+ hostapd.add_ap(apdev[1], params)
+
+ tests = [ (1, "eap_ikev2_build_frag_ack"),
+ (1, "wpabuf_alloc;eap_ikev2_process_fragment") ]
+ for count, func in tests:
+ with alloc_fail(dev[0], count, func):
+ dev[0].connect("eap-test2", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="IKEV2", identity="ikev2 user",
+ password="ike password", erp="1", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ ok = False
+ for j in range(10):
+ state = dev[0].request('GET_ALLOC_FAIL')
+ if state.startswith('0:'):
+ ok = True
+ break
+ time.sleep(0.1)
+ if not ok:
+ raise Exception("No allocation failure seen for %d:%s" % (count, func))
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+def test_eap_proto_mschapv2(dev, apdev):
+ """EAP-MSCHAPv2 protocol tests"""
+ check_eap_capa(dev[0], "MSCHAPV2")
+
+ def mschapv2_handler(ctx, req):
+ logger.info("mschapv2_handler - RX " + req.encode("hex"))
+ if 'num' not in ctx:
+ ctx['num'] = 0
+ ctx['num'] = ctx['num'] + 1
+ if 'id' not in ctx:
+ ctx['id'] = 1
+ ctx['id'] = (ctx['id'] + 1) % 256
+ idx = 0
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Invalid AT_ENCR_DATA length")
- return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_ENCR_DATA, 2, 0, 0)
+ logger.info("Test: Missing payload")
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1,
+ EAP_TYPE_MSCHAPV2)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Unknown MSCHAPv2 op_code")
+ return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + 1,
+ EAP_TYPE_MSCHAPV2,
+ 0, 0, 5, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unencrypted AT_NEXT_PSEUDONYM")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_NEXT_PSEUDONYM, 1, 0)
+ logger.info("Test: Invalid ms_len and unknown MSCHAPv2 op_code")
+ return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + 1,
+ EAP_TYPE_MSCHAPV2,
+ 255, 0, 0, 0)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Success before challenge")
+ return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + 1,
+ EAP_TYPE_MSCHAPV2,
+ 3, 0, 5, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unencrypted AT_NEXT_REAUTH_ID")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_NEXT_REAUTH_ID, 1, 0)
+ logger.info("Test: Failure before challenge - required challenge field not present")
+ return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + 1,
+ EAP_TYPE_MSCHAPV2,
+ 4, 0, 5, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
+ logger.info("Test: Failure")
return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Invalid AT_RES length")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_RES, 1, 0)
+ logger.info("Test: Failure before challenge - invalid failure challenge len")
+ payload = 'C=12'
+ return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + len(payload),
+ EAP_TYPE_MSCHAPV2,
+ 4, 0, 4 + len(payload)) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
+ logger.info("Test: Failure")
return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Invalid AT_RES length")
- return struct.pack(">BBHBBHBBH5L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 24,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_RES, 6, 0xffff, 0, 0, 0, 0, 0)
+ logger.info("Test: Failure before challenge - invalid failure challenge len")
+ payload = 'C=12 V=3'
+ return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + len(payload),
+ EAP_TYPE_MSCHAPV2,
+ 4, 0, 4 + len(payload)) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
+ logger.info("Test: Failure")
return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Invalid AT_AUTS length")
- return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_AUTS, 2, 0, 0)
+ logger.info("Test: Failure before challenge - invalid failure challenge")
+ payload = 'C=00112233445566778899aabbccddeefQ '
+ return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + len(payload),
+ EAP_TYPE_MSCHAPV2,
+ 4, 0, 4 + len(payload)) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
+ logger.info("Test: Failure")
return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Invalid AT_CHECKCODE length")
- return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_CHECKCODE, 2, 0, 0)
+ logger.info("Test: Failure before challenge - password expired")
+ payload = 'E=648 R=1 C=00112233445566778899aabbccddeeff V=3 M=Password expired'
+ return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + len(payload),
+ EAP_TYPE_MSCHAPV2,
+ 4, 0, 4 + len(payload)) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Success after password change")
+ payload = "S=1122334455667788990011223344556677889900"
+ return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + len(payload),
+ EAP_TYPE_MSCHAPV2,
+ 3, 0, 4 + len(payload)) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Invalid AT_RESULT_IND length")
- return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_RESULT_IND, 2, 0, 0)
+ logger.info("Test: Invalid challenge length")
+ return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + 1,
+ EAP_TYPE_MSCHAPV2,
+ 1, 0, 4 + 1, 0)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Too short challenge packet")
+ return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + 1,
+ EAP_TYPE_MSCHAPV2,
+ 1, 0, 4 + 1, 16)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Challenge")
+ return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + 1 + 16 + 6,
+ EAP_TYPE_MSCHAPV2,
+ 1, 0, 4 + 1 + 16 + 6, 16) + 16*'A' + 'foobar'
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Failure - password expired")
+ payload = 'E=648 R=1 C=00112233445566778899aabbccddeeff V=3 M=Password expired'
+ return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + len(payload),
+ EAP_TYPE_MSCHAPV2,
+ 4, 0, 4 + len(payload)) + payload
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Success after password change")
+ if len(req) != 591:
+ logger.info("Unexpected Change-Password packet length: %s" % len(req))
+ return None
+ data = req[9:]
+ enc_pw = data[0:516]
+ data = data[516:]
+ enc_hash = data[0:16]
+ data = data[16:]
+ peer_challenge = data[0:16]
+ data = data[16:]
+ # Reserved
+ data = data[8:]
+ nt_response = data[0:24]
+ data = data[24:]
+ flags = data
+ logger.info("enc_hash: " + enc_hash.encode("hex"))
+ logger.info("peer_challenge: " + peer_challenge.encode("hex"))
+ logger.info("nt_response: " + nt_response.encode("hex"))
+ logger.info("flags: " + flags.encode("hex"))
+
+ auth_challenge = binascii.unhexlify("00112233445566778899aabbccddeeff")
+ logger.info("auth_challenge: " + auth_challenge.encode("hex"))
+
+ auth_resp = GenerateAuthenticatorResponse("new-pw", nt_response,
+ peer_challenge,
+ auth_challenge, "user")
+ payload = "S=" + auth_resp.encode('hex').upper()
+ logger.info("Success message payload: " + payload)
+ return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + len(payload),
+ EAP_TYPE_MSCHAPV2,
+ 3, 0, 4 + len(payload)) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: EAP-Success")
+ return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unexpected AT_KDF_INPUT")
- return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_KDF_INPUT, 2, 0, 0)
+ logger.info("Test: Failure - password expired")
+ payload = 'E=648 R=1 C=00112233445566778899aabbccddeeff V=3 M=Password expired'
+ return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + len(payload),
+ EAP_TYPE_MSCHAPV2,
+ 4, 0, 4 + len(payload)) + payload
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Success after password change")
+ if len(req) != 591:
+ logger.info("Unexpected Change-Password packet length: %s" % len(req))
+ return None
+ data = req[9:]
+ enc_pw = data[0:516]
+ data = data[516:]
+ enc_hash = data[0:16]
+ data = data[16:]
+ peer_challenge = data[0:16]
+ data = data[16:]
+ # Reserved
+ data = data[8:]
+ nt_response = data[0:24]
+ data = data[24:]
+ flags = data
+ logger.info("enc_hash: " + enc_hash.encode("hex"))
+ logger.info("peer_challenge: " + peer_challenge.encode("hex"))
+ logger.info("nt_response: " + nt_response.encode("hex"))
+ logger.info("flags: " + flags.encode("hex"))
+
+ auth_challenge = binascii.unhexlify("00112233445566778899aabbccddeeff")
+ logger.info("auth_challenge: " + auth_challenge.encode("hex"))
+
+ auth_resp = GenerateAuthenticatorResponse("new-pw", nt_response,
+ peer_challenge,
+ auth_challenge, "user")
+ payload = "S=" + auth_resp.encode('hex').upper()
+ logger.info("Success message payload: " + payload)
+ return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + len(payload),
+ EAP_TYPE_MSCHAPV2,
+ 3, 0, 4 + len(payload)) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: EAP-Success")
+ return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unexpected AT_KDF")
- return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_KDF, 2, 0, 0)
+ logger.info("Test: Challenge")
+ return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + 1 + 16 + 6,
+ EAP_TYPE_MSCHAPV2,
+ 1, 0, 4 + 1 + 16 + 6, 16) + 16*'A' + 'foobar'
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Failure - authentication failure")
+ payload = 'E=691 R=1 C=00112233445566778899aabbccddeeff V=3 M=Authentication failed'
+ return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + len(payload),
+ EAP_TYPE_MSCHAPV2,
+ 4, 0, 4 + len(payload)) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Invalid AT_BIDDING length")
- return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8,
- EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_BIDDING, 2, 0, 0)
+ logger.info("Test: Challenge")
+ return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + 1 + 16 + 6,
+ EAP_TYPE_MSCHAPV2,
+ 1, 0, 4 + 1 + 16 + 6, 16) + 16*'A' + 'foobar'
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
+ logger.info("Test: Failure - authentication failure")
+ payload = 'E=691 R=1 C=00112233445566778899aabbccddeeff V=3 M=Authentication failed (2)'
+ return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + len(payload),
+ EAP_TYPE_MSCHAPV2,
+ 4, 0, 4 + len(payload)) + payload
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Failure")
return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Challenge - invalid ms_len and workaround disabled")
+ return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + 1 + 16 + 6,
+ EAP_TYPE_MSCHAPV2,
+ 1, 0, 4 + 1 + 16 + 6 + 1, 16) + 16*'A' + 'foobar'
+
return None
- srv = start_radius_server(aka_handler)
+ srv = start_radius_server(mschapv2_handler)
try:
- hapd = start_ap(apdev[0]['ifname'])
+ hapd = start_ap(apdev[0])
- for i in range(0, 49):
- eap = "AKA AKA'" if i == 11 else "AKA"
- dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
- eap=eap, identity="0232010000000000",
- password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123",
- wait_connect=False)
- ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
- timeout=15)
+ for i in range(0, 16):
+ logger.info("RUN: %d" % i)
+ if i == 12:
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="MSCHAPV2", identity="user",
+ password_hex="hash:8846f7eaee8fb117ad06bdd830b7586c",
+ wait_connect=False)
+ elif i == 14:
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="MSCHAPV2", identity="user",
+ phase2="mschapv2_retry=0",
+ password="password", wait_connect=False)
+ elif i == 15:
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="MSCHAPV2", identity="user",
+ eap_workaround="0",
+ password="password", wait_connect=False)
+ else:
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="MSCHAPV2", identity="user",
+ password="password", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=15)
if ev is None:
raise Exception("Timeout on EAP start")
- if i in [ 0, 15 ]:
- time.sleep(0.1)
- else:
+
+ if i in [ 8, 11, 12 ]:
+ ev = dev[0].wait_event(["CTRL-REQ-NEW_PASSWORD"],
+ timeout=10)
+ if ev is None:
+ raise Exception("Timeout on new password request")
+ id = ev.split(':')[0].split('-')[-1]
+ dev[0].request("CTRL-RSP-NEW_PASSWORD-" + id + ":new-pw")
+ if i in [ 11, 12 ]:
+ ev = dev[0].wait_event(["CTRL-EVENT-PASSWORD-CHANGED"],
+ timeout=10)
+ if ev is None:
+ raise Exception("Timeout on password change")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"],
+ timeout=10)
+ if ev is None:
+ raise Exception("Timeout on EAP success")
+ else:
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
+ timeout=10)
+ if ev is None:
+ raise Exception("Timeout on EAP failure")
+
+ if i in [ 13 ]:
+ ev = dev[0].wait_event(["CTRL-REQ-IDENTITY"],
+ timeout=10)
+ if ev is None:
+ raise Exception("Timeout on identity request")
+ id = ev.split(':')[0].split('-')[-1]
+ dev[0].request("CTRL-RSP-IDENTITY-" + id + ":user")
+
+ ev = dev[0].wait_event(["CTRL-REQ-PASSWORD"],
+ timeout=10)
+ if ev is None:
+ raise Exception("Timeout on password request")
+ id = ev.split(':')[0].split('-')[-1]
+ dev[0].request("CTRL-RSP-PASSWORD-" + id + ":password")
+
+ # TODO: Does this work correctly?
+
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
+ timeout=10)
+ if ev is None:
+ raise Exception("Timeout on EAP failure")
+
+ if i in [ 4, 5, 6, 7, 14 ]:
ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
timeout=10)
if ev is None:
raise Exception("Timeout on EAP failure")
+ else:
+ time.sleep(0.05)
dev[0].request("REMOVE_NETWORK all")
- dev[0].dump_monitor()
+ dev[0].wait_disconnected(timeout=1)
finally:
stop_radius_server(srv)
-def test_eap_proto_aka_prime(dev, apdev):
- """EAP-AKA' protocol tests"""
- def aka_prime_handler(ctx, req):
- logger.info("aka_prime_handler - RX " + req.encode("hex"))
+def test_eap_proto_mschapv2_errors(dev, apdev):
+ """EAP-MSCHAPv2 protocol tests (error paths)"""
+ check_eap_capa(dev[0], "MSCHAPV2")
+
+ def mschapv2_fail_password_expired(ctx):
+ logger.info("Test: Failure before challenge - password expired")
+ payload = 'E=648 R=1 C=00112233445566778899aabbccddeeff V=3 M=Password expired'
+ return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + len(payload),
+ EAP_TYPE_MSCHAPV2,
+ 4, 0, 4 + len(payload)) + payload
+
+ def mschapv2_success_after_password_change(ctx, req=None):
+ logger.info("Test: Success after password change")
+ if req is None or len(req) != 591:
+ payload = "S=1122334455667788990011223344556677889900"
+ else:
+ data = req[9:]
+ enc_pw = data[0:516]
+ data = data[516:]
+ enc_hash = data[0:16]
+ data = data[16:]
+ peer_challenge = data[0:16]
+ data = data[16:]
+ # Reserved
+ data = data[8:]
+ nt_response = data[0:24]
+ data = data[24:]
+ flags = data
+ logger.info("enc_hash: " + enc_hash.encode("hex"))
+ logger.info("peer_challenge: " + peer_challenge.encode("hex"))
+ logger.info("nt_response: " + nt_response.encode("hex"))
+ logger.info("flags: " + flags.encode("hex"))
+
+ auth_challenge = binascii.unhexlify("00112233445566778899aabbccddeeff")
+ logger.info("auth_challenge: " + auth_challenge.encode("hex"))
+
+ auth_resp = GenerateAuthenticatorResponse("new-pw", nt_response,
+ peer_challenge,
+ auth_challenge, "user")
+ payload = "S=" + auth_resp.encode('hex').upper()
+ return struct.pack(">BBHBBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + len(payload),
+ EAP_TYPE_MSCHAPV2,
+ 3, 0, 4 + len(payload)) + payload
+
+ def mschapv2_handler(ctx, req):
+ logger.info("mschapv2_handler - RX " + req.encode("hex"))
if 'num' not in ctx:
ctx['num'] = 0
ctx['num'] = ctx['num'] + 1
if 'id' not in ctx:
ctx['id'] = 1
ctx['id'] = (ctx['id'] + 1) % 256
-
idx = 0
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Missing payload")
- return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1,
- EAP_TYPE_AKA_PRIME)
+ return mschapv2_fail_password_expired(ctx)
+ idx += 1
+ if ctx['num'] == idx:
+ return mschapv2_success_after_password_change(ctx, req)
+ idx += 1
+ if ctx['num'] == idx:
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Challenge with no attributes")
- return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3,
- EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0)
+ return mschapv2_fail_password_expired(ctx)
+ idx += 1
+ if ctx['num'] == idx:
+ return mschapv2_success_after_password_change(ctx, req)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Challenge with empty AT_KDF_INPUT")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_KDF_INPUT, 1, 0)
+ return mschapv2_fail_password_expired(ctx)
+ idx += 1
+ if ctx['num'] == idx:
+ return mschapv2_success_after_password_change(ctx, req)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Challenge with AT_KDF_INPUT")
- return struct.pack(">BBHBBHBBHBBBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8,
- EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
- ord('c'), ord('d'))
+ return mschapv2_fail_password_expired(ctx)
+ idx += 1
+ if ctx['num'] == idx:
+ return mschapv2_success_after_password_change(ctx, req)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Challenge with duplicated KDF")
- return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8 + 3 * 4,
- EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
- ord('c'), ord('d'),
- EAP_SIM_AT_KDF, 1, 1,
- EAP_SIM_AT_KDF, 1, 2,
- EAP_SIM_AT_KDF, 1, 1)
+ return mschapv2_fail_password_expired(ctx)
+ idx += 1
+ if ctx['num'] == idx:
+ return mschapv2_success_after_password_change(ctx, req)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Challenge with multiple KDF proposals")
- return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8 + 3 * 4,
- EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
- ord('c'), ord('d'),
- EAP_SIM_AT_KDF, 1, 255,
- EAP_SIM_AT_KDF, 1, 254,
- EAP_SIM_AT_KDF, 1, 1)
+ return mschapv2_fail_password_expired(ctx)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Challenge with incorrect KDF selected")
- return struct.pack(">BBHBBHBBHBBBBBBHBBHBBHBBH",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8 + 4 * 4,
- EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
- ord('c'), ord('d'),
- EAP_SIM_AT_KDF, 1, 255,
- EAP_SIM_AT_KDF, 1, 255,
- EAP_SIM_AT_KDF, 1, 254,
- EAP_SIM_AT_KDF, 1, 1)
+ return mschapv2_success_after_password_change(ctx, req)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Challenge with multiple KDF proposals")
- return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8 + 3 * 4,
- EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
- ord('c'), ord('d'),
- EAP_SIM_AT_KDF, 1, 255,
- EAP_SIM_AT_KDF, 1, 254,
- EAP_SIM_AT_KDF, 1, 1)
+ return mschapv2_fail_password_expired(ctx)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Challenge with selected KDF not duplicated")
- return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8 + 3 * 4,
- EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
- ord('c'), ord('d'),
- EAP_SIM_AT_KDF, 1, 1,
- EAP_SIM_AT_KDF, 1, 255,
- EAP_SIM_AT_KDF, 1, 254)
+ return mschapv2_success_after_password_change(ctx, req)
+ idx += 1
+ if ctx['num'] == idx:
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ return mschapv2_fail_password_expired(ctx)
+ idx += 1
+ if ctx['num'] == idx:
+ return mschapv2_success_after_password_change(ctx, req)
+ idx += 1
+ if ctx['num'] == idx:
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ return mschapv2_fail_password_expired(ctx)
+ idx += 1
+ if ctx['num'] == idx:
+ return mschapv2_success_after_password_change(ctx, req)
+ idx += 1
+ if ctx['num'] == idx:
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ return None
+
+ srv = start_radius_server(mschapv2_handler)
+
+ try:
+ hapd = start_ap(apdev[0])
+
+ tests = [ "os_get_random;eap_mschapv2_change_password",
+ "generate_nt_response;eap_mschapv2_change_password",
+ "get_master_key;eap_mschapv2_change_password",
+ "nt_password_hash;eap_mschapv2_change_password",
+ "old_nt_password_hash_encrypted_with_new_nt_password_hash" ]
+ for func in tests:
+ with fail_test(dev[0], 1, func):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="MSCHAPV2", identity="user",
+ password="password", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-REQ-NEW_PASSWORD"], timeout=10)
+ if ev is None:
+ raise Exception("Timeout on new password request")
+ id = ev.split(':')[0].split('-')[-1]
+ dev[0].request("CTRL-RSP-NEW_PASSWORD-" + id + ":new-pw")
+ time.sleep(0.1)
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected(timeout=1)
+
+ tests = [ "encrypt_pw_block_with_password_hash;eap_mschapv2_change_password",
+ "nt_password_hash;eap_mschapv2_change_password",
+ "nt_password_hash;eap_mschapv2_success" ]
+ for func in tests:
+ with fail_test(dev[0], 1, func):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="MSCHAPV2", identity="user",
+ password_hex="hash:8846f7eaee8fb117ad06bdd830b7586c",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-REQ-NEW_PASSWORD"], timeout=10)
+ if ev is None:
+ raise Exception("Timeout on new password request")
+ id = ev.split(':')[0].split('-')[-1]
+ dev[0].request("CTRL-RSP-NEW_PASSWORD-" + id + ":new-pw")
+ time.sleep(0.1)
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected(timeout=1)
+
+ tests = [ "eap_msg_alloc;eap_mschapv2_change_password" ]
+ for func in tests:
+ with alloc_fail(dev[0], 1, func):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="MSCHAPV2", identity="user",
+ password="password", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-REQ-NEW_PASSWORD"], timeout=10)
+ if ev is None:
+ raise Exception("Timeout on new password request")
+ id = ev.split(':')[0].split('-')[-1]
+ dev[0].request("CTRL-RSP-NEW_PASSWORD-" + id + ":new-pw")
+ time.sleep(0.1)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected(timeout=1)
+ finally:
+ stop_radius_server(srv)
+
+def test_eap_proto_pwd(dev, apdev):
+ """EAP-pwd protocol tests"""
+ check_eap_capa(dev[0], "PWD")
+
+ global eap_proto_pwd_test_done, eap_proto_pwd_test_wait
+ eap_proto_pwd_test_done = False
+ eap_proto_pwd_test_wait = False
+
+ def pwd_handler(ctx, req):
+ logger.info("pwd_handler - RX " + req.encode("hex"))
+ if 'num' not in ctx:
+ ctx['num'] = 0
+ ctx['num'] = ctx['num'] + 1
+ if 'id' not in ctx:
+ ctx['id'] = 1
+ ctx['id'] = (ctx['id'] + 1) % 256
+ idx = 0
+
+ global eap_proto_pwd_test_wait
+ eap_proto_pwd_test_wait = False
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Missing payload")
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'], 4 + 1,
+ EAP_TYPE_PWD)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Missing Total-Length field")
+ payload = struct.pack("B", 0x80)
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Challenge with multiple KDF proposals")
- return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8 + 3 * 4,
- EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
- ord('c'), ord('d'),
- EAP_SIM_AT_KDF, 1, 255,
- EAP_SIM_AT_KDF, 1, 254,
- EAP_SIM_AT_KDF, 1, 1)
+ logger.info("Test: Too large Total-Length")
+ payload = struct.pack(">BH", 0x80, 65535)
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Challenge with selected KDF duplicated (missing MAC, RAND, AUTN)")
- return struct.pack(">BBHBBHBBHBBBBBBHBBHBBHBBH",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8 + 4 * 4,
- EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
- ord('c'), ord('d'),
- EAP_SIM_AT_KDF, 1, 1,
- EAP_SIM_AT_KDF, 1, 255,
- EAP_SIM_AT_KDF, 1, 254,
- EAP_SIM_AT_KDF, 1, 1)
+ eap_proto_pwd_test_wait = True
+ logger.info("Test: First fragment")
+ payload = struct.pack(">BH", 0xc0, 10)
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Unexpected Total-Length value in the second fragment")
+ payload = struct.pack(">BH", 0x80, 0)
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Challenge with multiple unsupported KDF proposals")
- return struct.pack(">BBHBBHBBHBBBBBBHBBH",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8 + 2 * 4,
- EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
- ord('c'), ord('d'),
- EAP_SIM_AT_KDF, 1, 255,
- EAP_SIM_AT_KDF, 1, 254)
+ logger.info("Test: First and only fragment")
+ payload = struct.pack(">BH", 0x80, 0)
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: First and only fragment with extra data")
+ payload = struct.pack(">BHB", 0x80, 0, 0)
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Challenge with multiple KDF proposals")
- return struct.pack(">BBHBBHBBHBBBBBBHBBHBBH",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8 + 3 * 4,
- EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
- ord('c'), ord('d'),
- EAP_SIM_AT_KDF, 1, 255,
- EAP_SIM_AT_KDF, 1, 254,
- EAP_SIM_AT_KDF, 1, 1)
+ eap_proto_pwd_test_wait = True
+ logger.info("Test: First fragment")
+ payload = struct.pack(">BHB", 0xc0, 2, 1)
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Challenge with invalid MAC, RAND, AUTN values)")
- return struct.pack(">BBHBBHBBHBBBBBBHBBHBBHBBHBBH4LBBH4LBBH4L",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8 + 4 * 4 + 20 + 20 + 20,
- EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
- ord('c'), ord('d'),
- EAP_SIM_AT_KDF, 1, 1,
- EAP_SIM_AT_KDF, 1, 255,
- EAP_SIM_AT_KDF, 1, 254,
- EAP_SIM_AT_KDF, 1, 1,
- EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0,
- EAP_SIM_AT_RAND, 5, 0, 0, 0, 0, 0,
- EAP_SIM_AT_AUTN, 5, 0, 0, 0, 0, 0)
+ logger.info("Test: Extra data in the second fragment")
+ payload = struct.pack(">BBB", 0x0, 2, 3)
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Too short id exchange")
+ payload = struct.pack(">B", 0x01)
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Challenge - AMF separation bit not set)")
- return struct.pack(">BBHBBHBBHBBBBBBHBBH4LBBH4LBBH4L",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8 + 4 + 20 + 20 + 20,
- EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
- ord('c'), ord('d'),
- EAP_SIM_AT_KDF, 1, 1,
- EAP_SIM_AT_MAC, 5, 0, 1, 2, 3, 4,
- EAP_SIM_AT_RAND, 5, 0, 5, 6, 7, 8,
- EAP_SIM_AT_AUTN, 5, 0, 9, 10,
- 0x2fda8ef7, 0xbba518cc)
+ logger.info("Test: Unsupported rand func in id exchange")
+ payload = struct.pack(">BHBBLB", 0x01, 0, 0, 0, 0, 0)
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Unsupported prf in id exchange")
+ payload = struct.pack(">BHBBLB", 0x01, 19, 1, 0, 0, 0)
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Challenge - Invalid MAC")
- return struct.pack(">BBHBBHBBHBBBBBBHBBH4LBBH4LBBH4L",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8 + 4 + 20 + 20 + 20,
- EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
- ord('c'), ord('d'),
- EAP_SIM_AT_KDF, 1, 1,
- EAP_SIM_AT_MAC, 5, 0, 1, 2, 3, 4,
- EAP_SIM_AT_RAND, 5, 0, 5, 6, 7, 8,
- EAP_SIM_AT_AUTN, 5, 0, 0xffffffff, 0xffffffff,
- 0xd1f90322, 0x40514cb4)
+ logger.info("Test: Unsupported password pre-processing technique in id exchange")
+ payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 255)
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ eap_proto_pwd_test_wait = True
+ logger.info("Test: Valid id exchange")
+ payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 0)
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unexpected id exchange")
+ payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 0)
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Challenge - Valid MAC")
- return struct.pack(">BBHBBHBBHBBBBBBHBBH4LBBH4LBBH4L",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8 + 4 + 20 + 20 + 20,
- EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_KDF_INPUT, 2, 1, ord('a'), ord('b'),
- ord('c'), ord('d'),
- EAP_SIM_AT_KDF, 1, 1,
- EAP_SIM_AT_MAC, 5, 0,
- 0xf4a3c1d3, 0x7c901401, 0x34bd8b01, 0x6f7fa32f,
- EAP_SIM_AT_RAND, 5, 0, 5, 6, 7, 8,
- EAP_SIM_AT_AUTN, 5, 0, 0xffffffff, 0xffffffff,
- 0xd1f90322, 0x40514cb4)
+ logger.info("Test: Unexpected commit exchange")
+ payload = struct.pack(">B", 0x02)
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ eap_proto_pwd_test_wait = True
+ logger.info("Test: Valid id exchange")
+ payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 0)
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unexpected Commit payload length")
+ payload = struct.pack(">B", 0x02)
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Invalid AT_KDF_INPUT length")
- return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8,
- EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_KDF_INPUT, 2, 0xffff, 0)
+ eap_proto_pwd_test_wait = True
+ logger.info("Test: Valid id exchange")
+ payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 0)
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Commit payload with all zeros values --> Shared key at infinity")
+ payload = struct.pack(">B", 0x02) + 96*'\0'
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Invalid AT_KDF length")
- return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8,
- EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_IDENTITY, 0,
- EAP_SIM_AT_KDF, 2, 0, 0)
+ eap_proto_pwd_test_wait = True
+ logger.info("Test: Valid id exchange")
+ payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 0)
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ eap_proto_pwd_test_wait = True
+ logger.info("Test: Commit payload with valid values")
+ element = binascii.unhexlify("8dcab2862c5396839a6bac0c689ff03d962863108e7c275bbf1d6eedf634ee832a214db99f0d0a1a6317733eecdd97f0fc4cda19f57e1bb9bb9c8dcf8c60ba6f")
+ scalar = binascii.unhexlify("450f31e058cf2ac2636a5d6e2b3c70b1fcc301957f0716e77f13aa69f9a2e5bd")
+ payload = struct.pack(">B", 0x02) + element + scalar
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unexpected Confirm payload length 0")
+ payload = struct.pack(">B", 0x03)
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Challenge with large number of KDF proposals")
- return struct.pack(">BBHBBHBBHBBHBBHBBHBBHBBHBBHBBHBBHBBHBBHBBH",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 12 * 4,
- EAP_TYPE_AKA_PRIME, EAP_AKA_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_KDF, 1, 255,
- EAP_SIM_AT_KDF, 1, 254,
- EAP_SIM_AT_KDF, 1, 253,
- EAP_SIM_AT_KDF, 1, 252,
- EAP_SIM_AT_KDF, 1, 251,
- EAP_SIM_AT_KDF, 1, 250,
- EAP_SIM_AT_KDF, 1, 249,
- EAP_SIM_AT_KDF, 1, 248,
- EAP_SIM_AT_KDF, 1, 247,
- EAP_SIM_AT_KDF, 1, 246,
- EAP_SIM_AT_KDF, 1, 245,
- EAP_SIM_AT_KDF, 1, 244)
+ eap_proto_pwd_test_wait = True
+ logger.info("Test: Valid id exchange")
+ payload = struct.pack(">BHBBLB", 0x01, 19, 1, 1, 0, 0)
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ eap_proto_pwd_test_wait = True
+ logger.info("Test: Commit payload with valid values")
+ element = binascii.unhexlify("8dcab2862c5396839a6bac0c689ff03d962863108e7c275bbf1d6eedf634ee832a214db99f0d0a1a6317733eecdd97f0fc4cda19f57e1bb9bb9c8dcf8c60ba6f")
+ scalar = binascii.unhexlify("450f31e058cf2ac2636a5d6e2b3c70b1fcc301957f0716e77f13aa69f9a2e5bd")
+ payload = struct.pack(">B", 0x02) + element + scalar
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Confirm payload with incorrect value")
+ payload = struct.pack(">B", 0x03) + 32*'\0'
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
- return None
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Unexpected confirm exchange")
+ payload = struct.pack(">B", 0x03)
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + len(payload), EAP_TYPE_PWD) + payload
- srv = start_radius_server(aka_prime_handler)
+ logger.info("No more test responses available - test case completed")
+ global eap_proto_pwd_test_done
+ eap_proto_pwd_test_done = True
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ srv = start_radius_server(pwd_handler)
try:
- hapd = start_ap(apdev[0]['ifname'])
+ hapd = start_ap(apdev[0])
- for i in range(0, 16):
+ i = 0
+ while not eap_proto_pwd_test_done:
+ i += 1
+ logger.info("Running connection iteration %d" % i)
dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
- eap="AKA'", identity="6555444333222111",
- password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123",
+ eap="PWD", identity="pwd user",
+ password="secret password",
+ wait_connect=False)
+ ok = False
+ for j in range(5):
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STATUS",
+ "CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ if "CTRL-EVENT-EAP-PROPOSED-METHOD" in ev:
+ ok = True
+ break
+ if "CTRL-EVENT-EAP-STATUS" in ev and "status='completion' parameter='failure'" in ev:
+ ok = True
+ break
+ if not ok:
+ raise Exception("Expected EAP event not seen")
+ if eap_proto_pwd_test_wait:
+ for k in range(10):
+ time.sleep(0.1)
+ if not eap_proto_pwd_test_wait:
+ break
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected(timeout=1)
+ dev[0].dump_monitor()
+ finally:
+ stop_radius_server(srv)
+
+def test_eap_proto_pwd_errors(dev, apdev):
+ """EAP-pwd local error cases"""
+ check_eap_capa(dev[0], "PWD")
+ params = hostapd.wpa2_eap_params(ssid="eap-test")
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ for i in range(1, 4):
+ with alloc_fail(dev[0], i, "eap_pwd_init"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PWD", identity="pwd user",
+ password="secret password",
+ wait_connect=False)
+ ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with alloc_fail(dev[0], 1, "eap_pwd_get_session_id"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PWD", identity="pwd user",
+ fragment_size="0",
+ password="secret password")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ funcs = [ "eap_pwd_getkey", "eap_pwd_get_emsk" ]
+ for func in funcs:
+ with alloc_fail(dev[0], 1, func):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PWD", identity="pwd user",
+ password="secret password", erp="1",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ for i in range(1, 7):
+ with alloc_fail(dev[0], i, "eap_pwd_perform_id_exchange"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PWD", identity="pwd user",
+ password="secret password",
wait_connect=False)
ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
timeout=15)
if ev is None:
raise Exception("Timeout on EAP start")
- if i in [ 0 ]:
+ ok = False
+ for j in range(10):
+ state = dev[0].request('GET_ALLOC_FAIL')
+ if state.startswith('0:'):
+ ok = True
+ break
time.sleep(0.1)
- else:
- ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
- timeout=10)
- if ev is None:
- raise Exception("Timeout on EAP failure")
+ if not ok:
+ raise Exception("No allocation failure seen")
dev[0].request("REMOVE_NETWORK all")
- dev[0].dump_monitor()
- finally:
- stop_radius_server(srv)
+ dev[0].wait_disconnected()
+
+ with alloc_fail(dev[0], 1, "wpabuf_alloc;eap_pwd_perform_id_exchange"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PWD", identity="pwd user",
+ password="secret password",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ for i in range(1, 4):
+ with alloc_fail(dev[0], i, "eap_pwd_perform_commit_exchange"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PWD", identity="pwd user",
+ password="secret password",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ ok = False
+ for j in range(10):
+ state = dev[0].request('GET_ALLOC_FAIL')
+ if state.startswith('0:'):
+ ok = True
+ break
+ time.sleep(0.1)
+ if not ok:
+ raise Exception("No allocation failure seen")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ for i in range(1, 12):
+ with alloc_fail(dev[0], i, "eap_pwd_perform_confirm_exchange"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PWD", identity="pwd user",
+ password="secret password",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ ok = False
+ for j in range(10):
+ state = dev[0].request('GET_ALLOC_FAIL')
+ if state.startswith('0:'):
+ ok = True
+ break
+ time.sleep(0.1)
+ if not ok:
+ raise Exception("No allocation failure seen")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ for i in range(1, 5):
+ with alloc_fail(dev[0], i, "eap_msg_alloc;=eap_pwd_process"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PWD", identity="pwd user",
+ password="secret password", fragment_size="50",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ # No password configured
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PWD", identity="pwd user",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD vendor=0 method=52"],
+ timeout=15)
+ if ev is None:
+ raise Exception("EAP-pwd not started")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with fail_test(dev[0], 1,
+ "hash_nt_password_hash;eap_pwd_perform_id_exchange"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PWD", identity="pwd-hash",
+ password_hex="hash:e3718ece8ab74792cbbfffd316d2d19a",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=10)
+ if ev is None:
+ raise Exception("No EAP-Failure reported")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ params = { "ssid": "eap-test2", "wpa": "2", "wpa_key_mgmt": "WPA-EAP",
+ "rsn_pairwise": "CCMP", "ieee8021x": "1",
+ "eap_server": "1", "eap_user_file": "auth_serv/eap_user.conf",
+ "pwd_group": "19", "fragment_size": "40" }
+ hostapd.add_ap(apdev[1], params)
+
+ with alloc_fail(dev[0], 1, "wpabuf_alloc;=eap_pwd_process"):
+ dev[0].connect("eap-test2", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PWD", identity="pwd user",
+ password="secret password",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
-def test_eap_proto_sim(dev, apdev):
- """EAP-SIM protocol tests"""
- def sim_handler(ctx, req):
- logger.info("sim_handler - RX " + req.encode("hex"))
+def test_eap_proto_erp(dev, apdev):
+ """ERP protocol tests"""
+ check_erp_capa(dev[0])
+
+ global eap_proto_erp_test_done
+ eap_proto_erp_test_done = False
+
+ def erp_handler(ctx, req):
+ logger.info("erp_handler - RX " + req.encode("hex"))
if 'num' not in ctx:
ctx['num'] = 0
- ctx['num'] = ctx['num'] + 1
+ ctx['num'] += 1
if 'id' not in ctx:
ctx['id'] = 1
ctx['id'] = (ctx['id'] + 1) % 256
-
idx = 0
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Missing payload")
- return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1,
- EAP_TYPE_SIM)
+ logger.info("Test: Missing type")
+ return struct.pack(">BBH", EAP_CODE_INITIATE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unexpected AT_AUTN")
- return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
- EAP_SIM_AT_AUTN, 2, 0, 0)
+ logger.info("Test: Unexpected type")
+ return struct.pack(">BBHB", EAP_CODE_INITIATE, ctx['id'], 4 + 1,
+ 255)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Missing Reserved field")
+ return struct.pack(">BBHB", EAP_CODE_INITIATE, ctx['id'], 4 + 1,
+ EAP_ERP_TYPE_REAUTH_START)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Too short AT_VERSION_LIST")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
- EAP_SIM_AT_VERSION_LIST, 1, 0)
+ logger.info("Test: Zero-length TVs/TLVs")
+ payload = ""
+ return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
+ 4 + 1 + 1 + len(payload),
+ EAP_ERP_TYPE_REAUTH_START, 0) + payload
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Too short TLV")
+ payload = struct.pack("B", 191)
+ return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
+ 4 + 1 + 1 + len(payload),
+ EAP_ERP_TYPE_REAUTH_START, 0) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: AT_VERSION_LIST overflow")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
- EAP_SIM_AT_VERSION_LIST, 1, 0xffff)
+ logger.info("Test: Truncated TLV")
+ payload = struct.pack("BB", 191, 1)
+ return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
+ 4 + 1 + 1 + len(payload),
+ EAP_ERP_TYPE_REAUTH_START, 0) + payload
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Ignored unknown TLV and unknown TV/TLV terminating parsing")
+ payload = struct.pack("BBB", 191, 0, 192)
+ return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
+ 4 + 1 + 1 + len(payload),
+ EAP_ERP_TYPE_REAUTH_START, 0) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unexpected AT_AUTS")
- return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
- EAP_SIM_AT_AUTS, 2, 0, 0)
+ logger.info("Test: More than one keyName-NAI")
+ payload = struct.pack("BBBB", EAP_ERP_TLV_KEYNAME_NAI, 0,
+ EAP_ERP_TLV_KEYNAME_NAI, 0)
+ return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
+ 4 + 1 + 1 + len(payload),
+ EAP_ERP_TYPE_REAUTH_START, 0) + payload
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Too short TLV keyName-NAI")
+ payload = struct.pack("B", EAP_ERP_TLV_KEYNAME_NAI)
+ return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
+ 4 + 1 + 1 + len(payload),
+ EAP_ERP_TYPE_REAUTH_START, 0) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unexpected AT_CHECKCODE")
- return struct.pack(">BBHBBHBBHL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
- EAP_SIM_AT_CHECKCODE, 2, 0, 0)
+ logger.info("Test: Truncated TLV keyName-NAI")
+ payload = struct.pack("BB", EAP_ERP_TLV_KEYNAME_NAI, 1)
+ return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
+ 4 + 1 + 1 + len(payload),
+ EAP_ERP_TYPE_REAUTH_START, 0) + payload
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Valid rRK lifetime TV followed by too short rMSK lifetime TV")
+ payload = struct.pack(">BLBH", EAP_ERP_TV_RRK_LIFETIME, 0,
+ EAP_ERP_TV_RMSK_LIFETIME, 0)
+ return struct.pack(">BBHBB", EAP_CODE_INITIATE, ctx['id'],
+ 4 + 1 + 1 + len(payload),
+ EAP_ERP_TYPE_REAUTH_START, 0) + payload
idx += 1
if ctx['num'] == idx:
- logger.info("Test: No AT_VERSION_LIST in Start")
- return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0)
+ logger.info("Test: Missing type (Finish)")
+ return struct.pack(">BBH", EAP_CODE_FINISH, ctx['id'], 4)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Unexpected type (Finish)")
+ return struct.pack(">BBHB", EAP_CODE_FINISH, ctx['id'], 4 + 1,
+ 255)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: No support version in AT_VERSION_LIST")
- return struct.pack(">BBHBBHBBH4B", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
- EAP_SIM_AT_VERSION_LIST, 2, 3, 2, 3, 4, 5)
+ logger.info("Test: Missing fields (Finish)")
+ return struct.pack(">BBHB", EAP_CODE_FINISH, ctx['id'], 4 + 1,
+ EAP_ERP_TYPE_REAUTH)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Unexpected SEQ (Finish)")
+ return struct.pack(">BBHBBHB", EAP_CODE_FINISH, ctx['id'],
+ 4 + 1 + 4,
+ EAP_ERP_TYPE_REAUTH, 0, 0xffff, 0)
+ logger.info("No more test responses available - test case completed")
+ global eap_proto_erp_test_done
+ eap_proto_erp_test_done = True
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Identity request without ID type")
- return struct.pack(">BBHBBHBBH2H", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
- EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Identity request ANY_ID")
- return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8 + 4,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
- EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
- EAP_SIM_AT_ANY_ID_REQ, 1, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Identity request ANY_ID (duplicate)")
- return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8 + 4,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
- EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
- EAP_SIM_AT_ANY_ID_REQ, 1, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ srv = start_radius_server(erp_handler)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Identity request ANY_ID")
- return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8 + 4,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
- EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
- EAP_SIM_AT_ANY_ID_REQ, 1, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Identity request FULLAUTH_ID")
- return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8 + 4,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
- EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
- EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Identity request FULLAUTH_ID (duplicate)")
- return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8 + 4,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
- EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
- EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ try:
+ hapd = start_ap(apdev[0])
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Identity request ANY_ID")
- return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8 + 4,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
- EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
- EAP_SIM_AT_ANY_ID_REQ, 1, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Identity request FULLAUTH_ID")
- return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8 + 4,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
- EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
- EAP_SIM_AT_FULLAUTH_ID_REQ, 1, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Identity request PERMANENT_ID")
- return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8 + 4,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
- EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
- EAP_SIM_AT_PERMANENT_ID_REQ, 1, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Identity request PERMANENT_ID (duplicate)")
- return struct.pack(">BBHBBHBBH2HBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 8 + 4,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START, 0,
- EAP_SIM_AT_VERSION_LIST, 2, 2, 1, 0,
- EAP_SIM_AT_PERMANENT_ID_REQ, 1, 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ i = 0
+ while not eap_proto_erp_test_done:
+ i += 1
+ logger.info("Running connection iteration %d" % i)
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PAX", identity="pax.user@example.com",
+ password_hex="0123456789abcdef0123456789abcdef",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ time.sleep(0.1)
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected(timeout=1)
+ dev[0].dump_monitor()
+ finally:
+ stop_radius_server(srv)
+
+def test_eap_proto_fast_errors(dev, apdev):
+ """EAP-FAST local error cases"""
+ check_eap_capa(dev[0], "FAST")
+ params = hostapd.wpa2_eap_params(ssid="eap-test")
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ for i in range(1, 5):
+ with alloc_fail(dev[0], i, "eap_fast_init"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="FAST", anonymous_identity="FAST",
+ identity="user", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=GTC",
+ phase1="fast_provisioning=2",
+ pac_file="blob://fast_pac_auth",
+ wait_connect=False)
+ ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
+ timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ (1, "wpabuf_alloc;eap_fast_tlv_eap_payload"),
+ (1, "eap_fast_derive_key;eap_fast_derive_key_auth"),
+ (1, "eap_msg_alloc;eap_peer_tls_phase2_nak"),
+ (1, "wpabuf_alloc;eap_fast_tlv_result"),
+ (1, "wpabuf_alloc;eap_fast_tlv_pac_ack"),
+ (1, "=eap_peer_tls_derive_session_id;eap_fast_process_crypto_binding"),
+ (1, "eap_peer_tls_decrypt;eap_fast_decrypt"),
+ (1, "eap_fast_getKey"),
+ (1, "eap_fast_get_session_id"),
+ (1, "eap_fast_get_emsk") ]
+ for count, func in tests:
+ dev[0].request("SET blob fast_pac_auth_errors ")
+ with alloc_fail(dev[0], count, func):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="FAST", anonymous_identity="FAST",
+ identity="user", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=GTC",
+ phase1="fast_provisioning=2",
+ pac_file="blob://fast_pac_auth_errors",
+ erp="1",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ (1, "eap_fast_derive_key;eap_fast_derive_key_provisioning"),
+ (1, "eap_mschapv2_getKey;eap_fast_get_phase2_key"),
+ (1, "=eap_fast_use_pac_opaque"),
+ (1, "eap_fast_copy_buf"),
+ (1, "=eap_fast_add_pac"),
+ (1, "=eap_fast_init_pac_data"),
+ (1, "=eap_fast_write_pac"),
+ (2, "=eap_fast_write_pac") ]
+ for count, func in tests:
+ dev[0].request("SET blob fast_pac_errors ")
+ with alloc_fail(dev[0], count, func):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="FAST", anonymous_identity="FAST",
+ identity="user", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ phase1="fast_provisioning=1",
+ pac_file="blob://fast_pac_errors",
+ erp="1",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ (1, "eap_fast_get_cmk;eap_fast_process_crypto_binding"),
+ (1, "eap_fast_derive_eap_msk;eap_fast_process_crypto_binding"),
+ (1, "eap_fast_derive_eap_emsk;eap_fast_process_crypto_binding") ]
+ for count, func in tests:
+ dev[0].request("SET blob fast_pac_auth_errors ")
+ with fail_test(dev[0], count, func):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="FAST", anonymous_identity="FAST",
+ identity="user", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=GTC",
+ phase1="fast_provisioning=2",
+ pac_file="blob://fast_pac_auth_errors",
+ erp="1",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ dev[0].request("SET blob fast_pac_errors ")
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="FAST", anonymous_identity="FAST",
+ identity="user", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=GTC",
+ phase1="fast_provisioning=1",
+ pac_file="blob://fast_pac_errors",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ # EAP-FAST: Only EAP-MSCHAPv2 is allowed during unauthenticated
+ # provisioning; reject phase2 type 6
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP failure")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ logger.info("Wrong password in Phase 2")
+ dev[0].request("SET blob fast_pac_errors ")
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="FAST", anonymous_identity="FAST",
+ identity="user", password="wrong password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ phase1="fast_provisioning=1",
+ pac_file="blob://fast_pac_errors",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP failure")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ "FOOBAR\n",
+ "wpa_supplicant EAP-FAST PAC file - version 1\nFOOBAR\n",
+ "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\n",
+ "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nSTART\n",
+ "wpa_supplicant EAP-FAST PAC file - version 1\nEND\n",
+ "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nPAC-Type=12345\nEND\n"
+ "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nPAC-Key=12\nEND\n",
+ "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nPAC-Key=1\nEND\n",
+ "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nPAC-Key=1q\nEND\n",
+ "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nPAC-Opaque=1\nEND\n",
+ "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nA-ID=1\nEND\n",
+ "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nI-ID=1\nEND\n",
+ "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nA-ID-Info=1\nEND\n" ]
+ for pac in tests:
+ blob = binascii.hexlify(pac)
+ dev[0].request("SET blob fast_pac_errors " + blob)
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="FAST", anonymous_identity="FAST",
+ identity="user", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=GTC",
+ phase1="fast_provisioning=2",
+ pac_file="blob://fast_pac_errors",
+ wait_connect=False)
+ ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
+ timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nEND\n",
+ "wpa_supplicant EAP-FAST PAC file - version 1\nSTART\nEND\nSTART\nEND\nSTART\nEND\n" ]
+ for pac in tests:
+ blob = binascii.hexlify(pac)
+ dev[0].request("SET blob fast_pac_errors " + blob)
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="FAST", anonymous_identity="FAST",
+ identity="user", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=GTC",
+ phase1="fast_provisioning=2",
+ pac_file="blob://fast_pac_errors")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ dev[0].request("SET blob fast_pac_errors ")
+
+def test_eap_proto_peap_errors(dev, apdev):
+ """EAP-PEAP local error cases"""
+ check_eap_capa(dev[0], "PEAP")
+ check_eap_capa(dev[0], "MSCHAPV2")
+ params = hostapd.wpa2_eap_params(ssid="eap-test")
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ for i in range(1, 5):
+ with alloc_fail(dev[0], i, "eap_peap_init"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PEAP", anonymous_identity="peap",
+ identity="user", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ wait_connect=False)
+ ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
+ timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ (1, "eap_mschapv2_getKey;eap_peap_get_isk;eap_peap_derive_cmk"),
+ (1, "eap_msg_alloc;eap_tlv_build_result"),
+ (1, "eap_mschapv2_init;eap_peap_phase2_request"),
+ (1, "eap_peer_tls_decrypt;eap_peap_decrypt"),
+ (1, "wpabuf_alloc;=eap_peap_decrypt"),
+ (1, "eap_peer_tls_encrypt;eap_peap_decrypt"),
+ (1, "eap_peer_tls_process_helper;eap_peap_process"),
+ (1, "eap_peer_tls_derive_key;eap_peap_process"),
+ (1, "eap_peer_tls_derive_session_id;eap_peap_process"),
+ (1, "eap_peap_getKey"),
+ (1, "eap_peap_get_session_id") ]
+ for count, func in tests:
+ with alloc_fail(dev[0], count, func):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PEAP", anonymous_identity="peap",
+ identity="user", password="password",
+ phase1="peapver=0 crypto_binding=2",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ erp="1", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ (1, "peap_prfplus;eap_peap_derive_cmk"),
+ (1, "eap_tlv_add_cryptobinding;eap_tlv_build_result"),
+ (1, "peap_prfplus;eap_peap_getKey") ]
+ for count, func in tests:
+ with fail_test(dev[0], count, func):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PEAP", anonymous_identity="peap",
+ identity="user", password="password",
+ phase1="peapver=0 crypto_binding=2",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ erp="1", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with alloc_fail(dev[0], 1,
+ "eap_peer_tls_phase2_nak;eap_peap_phase2_request"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PEAP", anonymous_identity="peap",
+ identity="cert user", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+def test_eap_proto_ttls_errors(dev, apdev):
+ """EAP-TTLS local error cases"""
+ check_eap_capa(dev[0], "TTLS")
+ check_eap_capa(dev[0], "MSCHAPV2")
+ params = hostapd.wpa2_eap_params(ssid="eap-test")
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ for i in range(1, 5):
+ with alloc_fail(dev[0], i, "eap_ttls_init"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="TTLS", anonymous_identity="ttls",
+ identity="user", password="password",
+ ca_cert="auth_serv/ca.pem",
+ phase2="autheap=MSCHAPV2",
+ wait_connect=False)
+ ev = dev[0].wait_event(["EAP: Failed to initialize EAP method"],
+ timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ (1, "eap_peer_tls_derive_key;eap_ttls_v0_derive_key",
+ "DOMAIN\mschapv2 user", "auth=MSCHAPV2"),
+ (1, "eap_peer_tls_derive_session_id;eap_ttls_v0_derive_key",
+ "DOMAIN\mschapv2 user", "auth=MSCHAPV2"),
+ (1, "wpabuf_alloc;eap_ttls_phase2_request_mschapv2",
+ "DOMAIN\mschapv2 user", "auth=MSCHAPV2"),
+ (1, "eap_peer_tls_derive_key;eap_ttls_phase2_request_mschapv2",
+ "DOMAIN\mschapv2 user", "auth=MSCHAPV2"),
+ (1, "eap_peer_tls_encrypt;eap_ttls_encrypt_response;eap_ttls_implicit_identity_request",
+ "DOMAIN\mschapv2 user", "auth=MSCHAPV2"),
+ (1, "eap_peer_tls_decrypt;eap_ttls_decrypt",
+ "DOMAIN\mschapv2 user", "auth=MSCHAPV2"),
+ (1, "eap_ttls_getKey",
+ "DOMAIN\mschapv2 user", "auth=MSCHAPV2"),
+ (1, "eap_ttls_get_session_id",
+ "DOMAIN\mschapv2 user", "auth=MSCHAPV2"),
+ (1, "eap_ttls_get_emsk",
+ "DOMAIN\mschapv2 user", "auth=MSCHAPV2"),
+ (1, "wpabuf_alloc;eap_ttls_phase2_request_mschap",
+ "mschap user", "auth=MSCHAP"),
+ (1, "eap_peer_tls_derive_key;eap_ttls_phase2_request_mschap",
+ "mschap user", "auth=MSCHAP"),
+ (1, "wpabuf_alloc;eap_ttls_phase2_request_chap",
+ "chap user", "auth=CHAP"),
+ (1, "eap_peer_tls_derive_key;eap_ttls_phase2_request_chap",
+ "chap user", "auth=CHAP"),
+ (1, "wpabuf_alloc;eap_ttls_phase2_request_pap",
+ "pap user", "auth=PAP"),
+ (1, "wpabuf_alloc;eap_ttls_avp_encapsulate",
+ "user", "autheap=MSCHAPV2"),
+ (1, "eap_mschapv2_init;eap_ttls_phase2_request_eap_method",
+ "user", "autheap=MSCHAPV2"),
+ (1, "eap_sm_buildIdentity;eap_ttls_phase2_request_eap",
+ "user", "autheap=MSCHAPV2"),
+ (1, "eap_ttls_avp_encapsulate;eap_ttls_phase2_request_eap",
+ "user", "autheap=MSCHAPV2"),
+ (1, "eap_ttls_parse_attr_eap",
+ "user", "autheap=MSCHAPV2"),
+ (1, "eap_peer_tls_encrypt;eap_ttls_encrypt_response;eap_ttls_process_decrypted",
+ "user", "autheap=MSCHAPV2"),
+ (1, "eap_ttls_fake_identity_request",
+ "user", "autheap=MSCHAPV2"),
+ (1, "eap_msg_alloc;eap_tls_process_output",
+ "user", "autheap=MSCHAPV2"),
+ (1, "eap_msg_alloc;eap_peer_tls_build_ack",
+ "user", "autheap=MSCHAPV2"),
+ (1, "tls_connection_decrypt;eap_peer_tls_decrypt",
+ "user", "autheap=MSCHAPV2"),
+ (1, "eap_peer_tls_phase2_nak;eap_ttls_phase2_request_eap_method",
+ "cert user", "autheap=MSCHAPV2") ]
+ for count, func, identity, phase2 in tests:
+ with alloc_fail(dev[0], count, func):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="TTLS", anonymous_identity="ttls",
+ identity=identity, password="password",
+ ca_cert="auth_serv/ca.pem", phase2=phase2,
+ erp="1", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL",
+ note="Allocation failure not triggered for: %d:%s" % (count, func))
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ tests = [ (1, "os_get_random;eap_ttls_phase2_request_mschapv2"),
+ (1, "mschapv2_derive_response;eap_ttls_phase2_request_mschapv2") ]
+ for count, func in tests:
+ with fail_test(dev[0], count, func):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="TTLS", anonymous_identity="ttls",
+ identity="DOMAIN\mschapv2 user", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ erp="1", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ wait_fail_trigger(dev[0], "GET_FAIL",
+ note="Test failure not triggered for: %d:%s" % (count, func))
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+def test_eap_proto_expanded(dev, apdev):
+ """EAP protocol tests with expanded header"""
+ global eap_proto_expanded_test_done
+ eap_proto_expanded_test_done = False
+
+ def expanded_handler(ctx, req):
+ logger.info("expanded_handler - RX " + req.encode("hex"))
+ if 'num' not in ctx:
+ ctx['num'] = 0
+ ctx['num'] += 1
+ if 'id' not in ctx:
+ ctx['id'] = 1
+ ctx['id'] = (ctx['id'] + 1) % 256
+ idx = 0
idx += 1
if ctx['num'] == idx:
- logger.info("Test: No AT_MAC and AT_RAND in Challenge")
- return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0)
+ logger.info("Test: MD5 challenge in expanded header")
+ return struct.pack(">BBHB3BLBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4 + 3,
+ EAP_TYPE_EXPANDED, 0, 0, 0, EAP_TYPE_MD5,
+ 1, 0xaa, ord('n'))
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: No AT_RAND in Challenge")
- return struct.pack(">BBHBBHBBH4L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 20,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
+ logger.info("Test: Invalid expanded EAP length")
+ return struct.pack(">BBHB3BH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 2,
+ EAP_TYPE_EXPANDED, 0, 0, 0, EAP_TYPE_MD5)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Insufficient number of challenges in Challenge")
- return struct.pack(">BBHBBHBBH4LBBH4L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 20 + 20,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_RAND, 5, 0, 0, 0, 0, 0,
- EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
+ logger.info("Test: Invalid expanded frame type")
+ return struct.pack(">BBHB3BL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_EXPANDED, 0, 0, 1, EAP_TYPE_MD5)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Too many challenges in Challenge")
- return struct.pack(">BBHBBHBBH4L4L4L4LBBH4L", EAP_CODE_REQUEST,
- ctx['id'],
- 4 + 1 + 3 + 4 + 4 * 16 + 20,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_RAND, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
+ logger.info("Test: MSCHAPv2 Challenge")
+ return struct.pack(">BBHBBBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 4 + 1 + 16 + 6,
+ EAP_TYPE_MSCHAPV2,
+ 1, 0, 4 + 1 + 16 + 6, 16) + 16*'A' + 'foobar'
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Invalid expanded frame type")
+ return struct.pack(">BBHB3BL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4,
+ EAP_TYPE_EXPANDED, 0, 0, 1, EAP_TYPE_MSCHAPV2)
+
+ logger.info("No more test responses available - test case completed")
+ global eap_proto_expanded_test_done
+ eap_proto_expanded_test_done = True
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ srv = start_radius_server(expanded_handler)
+
+ try:
+ hapd = start_ap(apdev[0])
+
+ i = 0
+ while not eap_proto_expanded_test_done:
+ i += 1
+ logger.info("Running connection iteration %d" % i)
+ if i == 4:
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="MSCHAPV2", identity="user",
+ password="password",
+ wait_connect=False)
+ else:
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="MD5", identity="user", password="password",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ if i in [ 1 ]:
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP method start")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP failure")
+ elif i in [ 2, 3 ]:
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP proposed method")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP failure")
+ else:
+ time.sleep(0.1)
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected(timeout=1)
+ dev[0].dump_monitor()
+ finally:
+ stop_radius_server(srv)
+
+def test_eap_proto_tls(dev, apdev):
+ """EAP-TLS protocol tests"""
+ check_eap_capa(dev[0], "TLS")
+ global eap_proto_tls_test_done, eap_proto_tls_test_wait
+ eap_proto_tls_test_done = False
+ eap_proto_tls_test_wait = False
+
+ def tls_handler(ctx, req):
+ logger.info("tls_handler - RX " + req.encode("hex"))
+ if 'num' not in ctx:
+ ctx['num'] = 0
+ ctx['num'] += 1
+ if 'id' not in ctx:
+ ctx['id'] = 1
+ ctx['id'] = (ctx['id'] + 1) % 256
+ idx = 0
+
+ global eap_proto_tls_test_wait
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Same RAND multiple times in Challenge")
- return struct.pack(">BBHBBHBBH4L4L4LBBH4L", EAP_CODE_REQUEST,
- ctx['id'],
- 4 + 1 + 3 + 4 + 3 * 16 + 20,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE, 0,
- EAP_SIM_AT_RAND, 13, 0, 0, 0, 0, 0, 0, 0, 0, 1,
- 0, 0, 0, 0,
- EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
+ logger.info("Test: Too much payload in TLS/Start: TLS Message Length (0 bytes) smaller than this fragment (1 bytes)")
+ return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 4 + 1,
+ EAP_TYPE_TLS, 0xa0, 0, 1)
+
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
-
+ logger.info("Test: Fragmented TLS/Start")
+ return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 4 + 1,
+ EAP_TYPE_TLS, 0xe0, 2, 1)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Notification with no attributes")
- return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0)
+ logger.info("Test: Too long fragment of TLS/Start: Invalid reassembly state: tls_in_left=2 tls_in_len=0 in_len=0")
+ return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2,
+ EAP_TYPE_TLS, 0x00, 2, 3)
idx += 1
if ctx['num'] == idx:
logger.info("Test: EAP-Failure")
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Notification indicating success, but no MAC")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
- EAP_SIM_AT_NOTIFICATION, 1, 32768)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
-
+ logger.info("Test: TLS/Start")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TLS, 0x20)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Notification indicating success, but invalid MAC value")
- return struct.pack(">BBHBBHBBHBBH4L", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4 + 20,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
- EAP_SIM_AT_NOTIFICATION, 1, 32768,
- EAP_SIM_AT_MAC, 5, 0, 0, 0, 0, 0)
+ logger.info("Test: Fragmented TLS message")
+ return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 4 + 1,
+ EAP_TYPE_TLS, 0xc0, 2, 1)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
-
+ logger.info("Test: Invalid TLS message: no Flags octet included + workaround")
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1,
+ EAP_TYPE_TLS)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Notification before auth")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
- EAP_SIM_AT_NOTIFICATION, 1, 16384)
+ logger.info("Test: Too long fragment of TLS message: more data than TLS message length indicated")
+ return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2,
+ EAP_TYPE_TLS, 0x00, 2, 3)
idx += 1
if ctx['num'] == idx:
logger.info("Test: EAP-Failure")
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Notification before auth")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
- EAP_SIM_AT_NOTIFICATION, 1, 16385)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Fragmented TLS/Start and truncated Message Length field")
+ return struct.pack(">BBHBB3B", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 3,
+ EAP_TYPE_TLS, 0xe0, 1, 2, 3)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Notification with unrecognized non-failure")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
- EAP_SIM_AT_NOTIFICATION, 1, 0xc000)
+ logger.info("Test: TLS/Start")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TLS, 0x20)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Notification before auth (duplicate)")
- return struct.pack(">BBHBBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3 + 4,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION, 0,
- EAP_SIM_AT_NOTIFICATION, 1, 0xc000)
+ logger.info("Test: Fragmented TLS message")
+ return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 4 + 1,
+ EAP_TYPE_TLS, 0xc0, 2, 1)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ logger.info("Test: Invalid TLS message: no Flags octet included + workaround disabled")
+ return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1,
+ EAP_TYPE_TLS)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Re-authentication (unexpected) with no attributes")
- return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_REAUTHENTICATION,
- 0)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
-
+ logger.info("Test: TLS/Start")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TLS, 0x20)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Client Error")
- return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3,
- EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CLIENT_ERROR, 0)
+ logger.info("Test: Fragmented TLS message (long; first)")
+ payload = 1450*'A'
+ return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 4 + len(payload),
+ EAP_TYPE_TLS, 0xc0, 65536) + payload
+ # "Too long TLS fragment (size over 64 kB)" on the last one
+ for i in range(44):
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Fragmented TLS message (long; cont %d)" % i)
+ eap_proto_tls_test_wait = True
+ payload = 1470*'A'
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + len(payload),
+ EAP_TYPE_TLS, 0x40) + payload
+ eap_proto_tls_test_wait = False
idx += 1
if ctx['num'] == idx:
logger.info("Test: EAP-Failure")
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unknown subtype")
- return struct.pack(">BBHBBH", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 3,
- EAP_TYPE_SIM, 255, 0)
+ logger.info("Test: TLS/Start")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TLS, 0x20)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Non-ACK to more-fragment message")
+ return struct.pack(">BBHBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 1,
+ EAP_TYPE_TLS, 0x00, 255)
idx += 1
if ctx['num'] == idx:
logger.info("Test: EAP-Failure")
return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
- return None
+ logger.info("No more test responses available - test case completed")
+ global eap_proto_tls_test_done
+ eap_proto_tls_test_done = True
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
- srv = start_radius_server(sim_handler)
+ srv = start_radius_server(tls_handler)
try:
- hapd = start_ap(apdev[0]['ifname'])
-
- for i in range(0, 25):
+ hapd = start_ap(apdev[0])
+
+ i = 0
+ while not eap_proto_tls_test_done:
+ i += 1
+ logger.info("Running connection iteration %d" % i)
+ workaround = "0" if i == 6 else "1"
+ fragment_size = "100" if i == 8 else "1400"
dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
- eap="SIM", identity="1232010000000000",
- password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
+ eap="TLS", identity="tls user",
+ ca_cert="auth_serv/ca.pem",
+ client_cert="auth_serv/user.pem",
+ private_key="auth_serv/user.key",
+ eap_workaround=workaround,
+ fragment_size=fragment_size,
wait_connect=False)
- ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
- timeout=15)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
if ev is None:
raise Exception("Timeout on EAP start")
- if i in [ 0 ]:
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD",
+ "CTRL-EVENT-EAP-STATUS"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP method start")
+ time.sleep(0.1)
+ start = os.times()[4]
+ while eap_proto_tls_test_wait:
+ now = os.times()[4]
+ if now - start > 10:
+ break
time.sleep(0.1)
- else:
- ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
- timeout=10)
- if ev is None:
- raise Exception("Timeout on EAP failure")
dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected(timeout=1)
dev[0].dump_monitor()
finally:
stop_radius_server(srv)
-def test_eap_proto_ikev2(dev, apdev):
- """EAP-IKEv2 protocol tests"""
- check_eap_capa(dev[0], "IKEV2")
- def ikev2_handler(ctx, req):
- logger.info("ikev2_handler - RX " + req.encode("hex"))
+def test_eap_proto_tnc(dev, apdev):
+ """EAP-TNC protocol tests"""
+ check_eap_capa(dev[0], "TNC")
+ global eap_proto_tnc_test_done
+ eap_proto_tnc_test_done = False
+
+ def tnc_handler(ctx, req):
+ logger.info("tnc_handler - RX " + req.encode("hex"))
if 'num' not in ctx:
ctx['num'] = 0
- ctx['num'] = ctx['num'] + 1
+ ctx['num'] += 1
if 'id' not in ctx:
ctx['id'] = 1
ctx['id'] = (ctx['id'] + 1) % 256
-
idx = 0
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Missing payload")
+ logger.info("Test: TNC start with unsupported version")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TNC, 0x20)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: TNC without Flags field")
return struct.pack(">BBHB", EAP_CODE_REQUEST, ctx['id'],
4 + 1,
- EAP_TYPE_IKEV2)
+ EAP_TYPE_TNC)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Message underflow due to missing Message Length")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TNC, 0xa1)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Invalid Message Length")
+ return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 4 + 1,
+ EAP_TYPE_TNC, 0xa1, 0, 0)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Invalid Message Length")
+ return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 4,
+ EAP_TYPE_TNC, 0xe1, 75001)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Start with Message Length")
+ return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 4,
+ EAP_TYPE_TNC, 0xa1, 1)
+ idx += 1
+ if ctx['num'] == idx:
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: Server used start flag again")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TNC, 0x21)
+ idx += 1
+ if ctx['num'] == idx:
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TNC, 0x21)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Truncated Message Length field")
- return struct.pack(">BBHBB3B", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 3,
- EAP_TYPE_IKEV2, 0x80, 0, 0, 0)
+ logger.info("Test: Fragmentation and unexpected payload in ack")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TNC, 0x21)
+ idx += 1
+ if ctx['num'] == idx:
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TNC, 0x01)
+ idx += 1
+ if ctx['num'] == idx:
+ return struct.pack(">BBHBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 1,
+ EAP_TYPE_TNC, 0x01, 0)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Too short Message Length value")
+ logger.info("Test: Server fragmenting and fragment overflow")
return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
4 + 1 + 1 + 4 + 1,
- EAP_TYPE_IKEV2, 0x80, 0, 1)
-
+ EAP_TYPE_TNC, 0xe1, 2, 1)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Truncated message")
- return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 4,
- EAP_TYPE_IKEV2, 0x80, 1)
+ return struct.pack(">BBHBBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 2,
+ EAP_TYPE_TNC, 0x01, 2, 3)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Truncated message(2)")
- return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 4,
- EAP_TYPE_IKEV2, 0x80, 0xffffffff)
+ logger.info("Test: Server fragmenting and no message length in a fragment")
+ return struct.pack(">BBHBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 1,
+ EAP_TYPE_TNC, 0x61, 2)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Truncated message(3)")
- return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 4,
- EAP_TYPE_IKEV2, 0xc0, 0xffffffff)
-
+ logger.info("Test: TNC start followed by invalid TNCCS-Batch")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TNC, 0x21)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Truncated message(4)")
- return struct.pack(">BBHBBL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 4,
- EAP_TYPE_IKEV2, 0xc0, 10000000)
+ logger.info("Received TNCCS-Batch: " + req[6:])
+ resp = "FOO"
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + len(resp),
+ EAP_TYPE_TNC, 0x01) + resp
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Too long fragments (first fragment)")
- return struct.pack(">BBHBBLB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 4 + 1,
- EAP_TYPE_IKEV2, 0xc0, 2, 1)
-
+ logger.info("Test: TNC start followed by invalid TNCCS-Batch (2)")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TNC, 0x21)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Too long fragments (second fragment)")
- return struct.pack(">BBHBB2B", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 2,
- EAP_TYPE_IKEV2, 0x00, 2, 3)
+ logger.info("Received TNCCS-Batch: " + req[6:])
+ resp = "</TNCCS-Batch><TNCCS-Batch>"
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + len(resp),
+ EAP_TYPE_TNC, 0x01) + resp
idx += 1
if ctx['num'] == idx:
- logger.info("Test: No Message Length field in first fragment")
- return struct.pack(">BBHBBB", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 1,
- EAP_TYPE_IKEV2, 0x40, 1)
+ logger.info("Test: TNCCS-Batch missing BatchId attribute")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TNC, 0x21)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Received TNCCS-Batch: " + req[6:])
+ resp = "<TNCCS-Batch foo=3></TNCCS-Batch>"
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + len(resp),
+ EAP_TYPE_TNC, 0x01) + resp
idx += 1
if ctx['num'] == idx:
- logger.info("Test: ICV before keys")
+ logger.info("Test: Unexpected IF-TNCCS BatchId")
return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
4 + 1 + 1,
- EAP_TYPE_IKEV2, 0x20)
-
+ EAP_TYPE_TNC, 0x21)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unsupported IKEv2 header version")
- return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 28,
- EAP_TYPE_IKEV2, 0x00,
- 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0)
+ logger.info("Received TNCCS-Batch: " + req[6:])
+ resp = "<TNCCS-Batch BatchId=123456789></TNCCS-Batch>"
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + len(resp),
+ EAP_TYPE_TNC, 0x01) + resp
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Incorrect IKEv2 header Length")
- return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 28,
- EAP_TYPE_IKEV2, 0x00,
- 0, 0, 0, 0,
- 0, 0x20, 0, 0, 0, 0)
-
+ logger.info("Test: Missing IMC-IMV-Message and TNCC-TNCS-Message end tags")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TNC, 0x21)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unexpected IKEv2 Exchange Type in SA_INIT state")
- return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 28,
- EAP_TYPE_IKEV2, 0x00,
- 0, 0, 0, 0,
- 0, 0x20, 0, 0, 0, 28)
+ logger.info("Received TNCCS-Batch: " + req[6:])
+ resp = "<TNCCS-Batch BatchId=2><IMC-IMV-Message><TNCC-TNCS-Message></TNCCS-Batch>"
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + len(resp),
+ EAP_TYPE_TNC, 0x01) + resp
+ idx += 1
+ if ctx['num'] == idx:
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unexpected IKEv2 Message ID in SA_INIT state")
- return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 28,
- EAP_TYPE_IKEV2, 0x00,
- 0, 0, 0, 0,
- 0, 0x20, 34, 0, 1, 28)
+ logger.info("Test: Missing IMC-IMV-Message and TNCC-TNCS-Message Type")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TNC, 0x21)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Received TNCCS-Batch: " + req[6:])
+ resp = "<TNCCS-Batch BatchId=2><IMC-IMV-Message></IMC-IMV-Message><TNCC-TNCS-Message></TNCC-TNCS-Message></TNCCS-Batch>"
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + len(resp),
+ EAP_TYPE_TNC, 0x01) + resp
+ idx += 1
+ if ctx['num'] == idx:
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unexpected IKEv2 Flags value")
- return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 28,
- EAP_TYPE_IKEV2, 0x00,
- 0, 0, 0, 0,
- 0, 0x20, 34, 0, 0, 28)
+ logger.info("Test: Missing TNCC-TNCS-Message XML end tag")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TNC, 0x21)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Received TNCCS-Batch: " + req[6:])
+ resp = "<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type><XML></TNCC-TNCS-Message></TNCCS-Batch>"
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + len(resp),
+ EAP_TYPE_TNC, 0x01) + resp
+ idx += 1
+ if ctx['num'] == idx:
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unexpected IKEv2 Flags value(2)")
- return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 28,
- EAP_TYPE_IKEV2, 0x00,
- 0, 0, 0, 0,
- 0, 0x20, 34, 0x20, 0, 28)
+ logger.info("Test: Missing TNCC-TNCS-Message Base64 start tag")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TNC, 0x21)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Received TNCCS-Batch: " + req[6:])
+ resp = "<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type></TNCC-TNCS-Message></TNCCS-Batch>"
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + len(resp),
+ EAP_TYPE_TNC, 0x01) + resp
+ idx += 1
+ if ctx['num'] == idx:
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: No SAi1 in SA_INIT")
- return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1 + 28,
- EAP_TYPE_IKEV2, 0x00,
- 0, 0, 0, 0,
- 0, 0x20, 34, 0x08, 0, 28)
+ logger.info("Test: Missing TNCC-TNCS-Message Base64 end tag")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TNC, 0x21)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Received TNCCS-Batch: " + req[6:])
+ resp = "<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type><Base64>abc</TNCC-TNCS-Message></TNCCS-Batch>"
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + len(resp),
+ EAP_TYPE_TNC, 0x01) + resp
+ idx += 1
+ if ctx['num'] == idx:
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
- def build_ike(id, next=0, exch_type=34, flags=0x00, ike=''):
- return struct.pack(">BBHBB2L2LBBBBLL", EAP_CODE_REQUEST, id,
- 4 + 1 + 1 + 28 + len(ike),
- EAP_TYPE_IKEV2, flags,
- 0, 0, 0, 0,
- next, 0x20, exch_type, 0x08, 0,
- 28 + len(ike)) + ike
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Test: TNCC-TNCS-Message Base64 message")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TNC, 0x21)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Received TNCCS-Batch: " + req[6:])
+ resp = "<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type><Base64>aGVsbG8=</Base64></TNCC-TNCS-Message></TNCCS-Batch>"
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + len(resp),
+ EAP_TYPE_TNC, 0x01) + resp
+ idx += 1
+ if ctx['num'] == idx:
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unexpected extra data after payloads")
- return build_ike(ctx['id'], ike=struct.pack(">B", 1))
+ logger.info("Test: Invalid TNCC-TNCS-Message XML message")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TNC, 0x21)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Received TNCCS-Batch: " + req[6:])
+ resp = "<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type><XML>hello</XML></TNCC-TNCS-Message></TNCCS-Batch>"
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + len(resp),
+ EAP_TYPE_TNC, 0x01) + resp
+ idx += 1
+ if ctx['num'] == idx:
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Truncated payload header")
- return build_ike(ctx['id'], next=128, ike=struct.pack(">B", 1))
+ logger.info("Test: Missing TNCCS-Recommendation type")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TNC, 0x21)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Received TNCCS-Batch: " + req[6:])
+ resp = '<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type><XML><TNCCS-Recommendation foo=1></TNCCS-Recommendation></XML></TNCC-TNCS-Message></TNCCS-Batch>'
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + len(resp),
+ EAP_TYPE_TNC, 0x01) + resp
+ idx += 1
+ if ctx['num'] == idx:
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Too small payload header length")
- ike = struct.pack(">BBH", 0, 0, 3)
- return build_ike(ctx['id'], next=128, ike=ike)
+ logger.info("Test: TNCCS-Recommendation type=none")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TNC, 0x21)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Received TNCCS-Batch: " + req[6:])
+ resp = '<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type><XML><TNCCS-Recommendation type="none"></TNCCS-Recommendation></XML></TNCC-TNCS-Message></TNCCS-Batch>'
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + len(resp),
+ EAP_TYPE_TNC, 0x01) + resp
+ idx += 1
+ if ctx['num'] == idx:
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Too large payload header length")
- ike = struct.pack(">BBH", 0, 0, 5)
- return build_ike(ctx['id'], next=128, ike=ike)
+ logger.info("Test: TNCCS-Recommendation type=isolate")
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1,
+ EAP_TYPE_TNC, 0x21)
+ idx += 1
+ if ctx['num'] == idx:
+ logger.info("Received TNCCS-Batch: " + req[6:])
+ resp = '<TNCCS-Batch BatchId=2><TNCC-TNCS-Message><Type>00000001</Type><XML><TNCCS-Recommendation type="isolate"></TNCCS-Recommendation></XML></TNCC-TNCS-Message></TNCCS-Batch>'
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + len(resp),
+ EAP_TYPE_TNC, 0x01) + resp
+ idx += 1
+ if ctx['num'] == idx:
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ logger.info("No more test responses available - test case completed")
+ global eap_proto_tnc_test_done
+ eap_proto_tnc_test_done = True
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ srv = start_radius_server(tnc_handler)
+
+ try:
+ hapd = start_ap(apdev[0])
+
+ i = 0
+ while not eap_proto_tnc_test_done:
+ i += 1
+ logger.info("Running connection iteration %d" % i)
+ frag = 1400
+ if i == 8:
+ frag = 150
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="TNC", identity="tnc", fragment_size=str(frag),
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD",
+ "CTRL-EVENT-EAP-STATUS"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP method start")
+ time.sleep(0.1)
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected(timeout=1)
+ dev[0].dump_monitor()
+ finally:
+ stop_radius_server(srv)
+
+def test_eap_canned_success_after_identity(dev, apdev):
+ """EAP protocol tests for canned EAP-Success after identity"""
+ check_eap_capa(dev[0], "MD5")
+ def eap_canned_success_handler(ctx, req):
+ logger.info("eap_canned_success_handler - RX " + req.encode("hex"))
+ if 'num' not in ctx:
+ ctx['num'] = 0
+ ctx['num'] = ctx['num'] + 1
+ if 'id' not in ctx:
+ ctx['id'] = 1
+ ctx['id'] = (ctx['id'] + 1) % 256
+ idx = 0
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unsupported payload (non-critical and critical)")
- ike = struct.pack(">BBHBBH", 129, 0, 4, 0, 0x01, 4)
- return build_ike(ctx['id'], next=128, ike=ike)
+ logger.info("Test: EAP-Success")
+ return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Certificate and empty SAi1")
- ike = struct.pack(">BBHBBH", 33, 0, 4, 0, 0, 4)
- return build_ike(ctx['id'], next=37, ike=ike)
+ logger.info("Test: EAP-Success")
+ return struct.pack(">BBH", EAP_CODE_SUCCESS, ctx['id'], 4)
+
+ return None
+
+ srv = start_radius_server(eap_canned_success_handler)
+
+ try:
+ hapd = start_ap(apdev[0])
+
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ phase1="allow_canned_success=1",
+ eap="MD5", identity="user", password="password",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP success")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="MD5", identity="user", password="password",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=0.1)
+ if ev is not None:
+ raise Exception("Unexpected EAP success")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ finally:
+ stop_radius_server(srv)
+
+def test_eap_proto_wsc(dev, apdev):
+ """EAP-WSC protocol tests"""
+ global eap_proto_wsc_test_done, eap_proto_wsc_wait_failure
+ eap_proto_wsc_test_done = False
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Too short proposal")
- ike = struct.pack(">BBHBBHBBB", 0, 0, 4 + 7,
- 0, 0, 7, 0, 0, 0)
- return build_ike(ctx['id'], next=33, ike=ike)
+ def wsc_handler(ctx, req):
+ logger.info("wsc_handler - RX " + req.encode("hex"))
+ if 'num' not in ctx:
+ ctx['num'] = 0
+ ctx['num'] += 1
+ if 'id' not in ctx:
+ ctx['id'] = 1
+ ctx['id'] = (ctx['id'] + 1) % 256
+ idx = 0
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Too small proposal length in SAi1")
- ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
- 0, 0, 7, 0, 0, 0, 0)
- return build_ike(ctx['id'], next=33, ike=ike)
+ global eap_proto_wsc_wait_failure
+ eap_proto_wsc_wait_failure = False
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Too large proposal length in SAi1")
- ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
- 0, 0, 9, 0, 0, 0, 0)
- return build_ike(ctx['id'], next=33, ike=ike)
+ logger.info("Test: Missing Flags field")
+ return struct.pack(">BBHB3BLB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4 + 1,
+ EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
+ 1)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unexpected proposal type in SAi1")
- ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
- 1, 0, 8, 0, 0, 0, 0)
- return build_ike(ctx['id'], next=33, ike=ike)
+ logger.info("Test: Message underflow (missing Message Length field)")
+ return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4 + 2,
+ EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
+ 1, 0x02)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unexpected Protocol ID in SAi1")
- ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
- 0, 0, 8, 0, 0, 0, 0)
- return build_ike(ctx['id'], next=33, ike=ike)
+ logger.info("Test: Invalid Message Length (> 50000)")
+ return struct.pack(">BBHB3BLBBH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4 + 4,
+ EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
+ 1, 0x02, 65535)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unexpected proposal number in SAi1")
- ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
- 0, 0, 8, 0, 1, 0, 0)
- return build_ike(ctx['id'], next=33, ike=ike)
+ logger.info("Test: Invalid Message Length (< current payload)")
+ return struct.pack(">BBHB3BLBBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4 + 5,
+ EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
+ 1, 0x02, 0, 0xff)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Not enough room for SPI in SAi1")
- ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
- 0, 0, 8, 1, 1, 1, 0)
- return build_ike(ctx['id'], next=33, ike=ike)
+ logger.info("Test: Unexpected Op-Code 5 in WAIT_START state")
+ return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4 + 2,
+ EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
+ 5, 0x00)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unexpected SPI in SAi1")
- ike = struct.pack(">BBHBBHBBBBB", 0, 0, 4 + 9,
- 0, 0, 9, 1, 1, 1, 0, 1)
- return build_ike(ctx['id'], next=33, ike=ike)
-
+ logger.info("Test: Valid WSC Start to start the sequence")
+ return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4 + 2,
+ EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
+ 1, 0x00)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: No transforms in SAi1")
- ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
- 0, 0, 8, 1, 1, 0, 0)
- return build_ike(ctx['id'], next=33, ike=ike)
+ logger.info("Test: No Message Length field in a fragmented packet")
+ return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4 + 2,
+ EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
+ 4, 0x01)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Too short transform in SAi1")
- ike = struct.pack(">BBHBBHBBBB", 0, 0, 4 + 8,
- 0, 0, 8, 1, 1, 0, 1)
- return build_ike(ctx['id'], next=33, ike=ike)
-
+ logger.info("Test: Valid WSC Start to start the sequence")
+ return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4 + 2,
+ EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
+ 1, 0x00)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Too small transform length in SAi1")
- ike = struct.pack(">BBHBBHBBBBBBHBBH", 0, 0, 4 + 8 + 8,
- 0, 0, 8 + 8, 1, 1, 0, 1,
- 0, 0, 7, 0, 0, 0)
- return build_ike(ctx['id'], next=33, ike=ike)
-
+ logger.info("Test: Valid first fragmented packet")
+ return struct.pack(">BBHB3BLBBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4 + 5,
+ EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
+ 4, 0x03, 10, 1)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Too large transform length in SAi1")
- ike = struct.pack(">BBHBBHBBBBBBHBBH", 0, 0, 4 + 8 + 8,
- 0, 0, 8 + 8, 1, 1, 0, 1,
- 0, 0, 9, 0, 0, 0)
- return build_ike(ctx['id'], next=33, ike=ike)
+ logger.info("Test: Unexpected Op-Code 5 in fragment (expected 4)")
+ return struct.pack(">BBHB3BLBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4 + 3,
+ EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
+ 5, 0x01, 2)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Unexpected Transform type in SAi1")
- ike = struct.pack(">BBHBBHBBBBBBHBBH", 0, 0, 4 + 8 + 8,
- 0, 0, 8 + 8, 1, 1, 0, 1,
- 1, 0, 8, 0, 0, 0)
- return build_ike(ctx['id'], next=33, ike=ike)
-
+ logger.info("Test: Valid WSC Start to start the sequence")
+ return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4 + 2,
+ EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
+ 1, 0x00)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: No transform attributes in SAi1")
- ike = struct.pack(">BBHBBHBBBBBBHBBH", 0, 0, 4 + 8 + 8,
- 0, 0, 8 + 8, 1, 1, 0, 1,
- 0, 0, 8, 0, 0, 0)
- return build_ike(ctx['id'], next=33, ike=ike)
-
+ logger.info("Test: Valid first fragmented packet")
+ return struct.pack(">BBHB3BLBBHB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4 + 5,
+ EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
+ 4, 0x03, 2, 1)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: No transform attr for AES and unexpected data after transforms in SAi1")
- tlen1 = 8 + 3
- tlen2 = 8 + 4
- tlen3 = 8 + 4
- tlen = tlen1 + tlen2 + tlen3
- ike = struct.pack(">BBHBBHBBBBBBHBBH3BBBHBBHHHBBHBBHHHB",
- 0, 0, 4 + 8 + tlen + 1,
- 0, 0, 8 + tlen + 1, 1, 1, 0, 3,
- 3, 0, tlen1, 1, 0, 12, 1, 2, 3,
- 3, 0, tlen2, 1, 0, 12, 0, 128,
- 0, 0, tlen3, 1, 0, 12, 0x8000 | 14, 127,
- 1)
- return build_ike(ctx['id'], next=33, ike=ike)
-
- def build_sa(next=0):
- tlen = 5 * 8
- return struct.pack(">BBHBBHBBBBBBHBBHBBHBBHBBHBBHBBHBBHBBHBBH",
- next, 0, 4 + 8 + tlen,
- 0, 0, 8 + tlen, 1, 1, 0, 5,
- 3, 0, 8, 1, 0, 3,
- 3, 0, 8, 2, 0, 1,
- 3, 0, 8, 3, 0, 1,
- 3, 0, 8, 4, 0, 5,
- 0, 0, 8, 241, 0, 0)
+ logger.info("Test: Fragment overflow")
+ return struct.pack(">BBHB3BLBBBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4 + 4,
+ EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
+ 4, 0x01, 2, 3)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Valid proposal, but no KEi in SAi1")
- ike = build_sa()
- return build_ike(ctx['id'], next=33, ike=ike)
-
+ logger.info("Test: Valid WSC Start to start the sequence")
+ return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4 + 2,
+ EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
+ 1, 0x00)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Empty KEi in SAi1")
- ike = build_sa(next=34) + struct.pack(">BBH", 0, 0, 4)
- return build_ike(ctx['id'], next=33, ike=ike)
+ logger.info("Test: Unexpected Op-Code 5 in WAIT_FRAG_ACK state")
+ return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4 + 2,
+ EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
+ 5, 0x00)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Mismatch in DH Group in SAi1")
- ike = build_sa(next=34)
- ike += struct.pack(">BBHHH", 0, 0, 4 + 4 + 96, 12345, 0)
- ike += 96*'\x00'
- return build_ike(ctx['id'], next=33, ike=ike)
+ logger.info("Test: Valid WSC Start")
+ return struct.pack(">BBHB3BLBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 3 + 4 + 2,
+ EAP_TYPE_EXPANDED, 0x00, 0x37, 0x2a, 1,
+ 1, 0x00)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
+ logger.info("No more test responses available - test case completed")
+ global eap_proto_wsc_test_done
+ eap_proto_wsc_test_done = True
+ eap_proto_wsc_wait_failure = True
return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Invalid DH public value length in SAi1")
- ike = build_sa(next=34)
- ike += struct.pack(">BBHHH", 0, 0, 4 + 4 + 96, 5, 0)
- ike += 96*'\x00'
- return build_ike(ctx['id'], next=33, ike=ike)
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
- def build_ke(next=0):
- ke = struct.pack(">BBHHH", next, 0, 4 + 4 + 192, 5, 0)
- ke += 192*'\x00'
- return ke
+ srv = start_radius_server(wsc_handler)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Valid proposal and KEi, but no Ni in SAi1")
- ike = build_sa(next=34)
- ike += build_ke()
- return build_ike(ctx['id'], next=33, ike=ike)
+ try:
+ hapd = start_ap(apdev[0])
+
+ i = 0
+ while not eap_proto_wsc_test_done:
+ i += 1
+ logger.info("Running connection iteration %d" % i)
+ fragment_size = 1398 if i != 9 else 50
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", eap="WSC",
+ fragment_size=str(fragment_size),
+ identity="WFA-SimpleConfig-Enrollee-1-0",
+ phase1="pin=12345670",
+ scan_freq="2412", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP method start")
+ if eap_proto_wsc_wait_failure:
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP failure")
+ else:
+ time.sleep(0.1)
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected(timeout=1)
+ dev[0].dump_monitor()
+ finally:
+ stop_radius_server(srv)
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Too short Ni in SAi1")
- ike = build_sa(next=34)
- ike += build_ke(next=40)
- ike += struct.pack(">BBH", 0, 0, 4)
- return build_ike(ctx['id'], next=33, ike=ike)
+def test_eap_canned_success_before_method(dev, apdev):
+ """EAP protocol tests for canned EAP-Success before any method"""
+ params = int_eap_server_params()
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+ hapd.request("SET ext_eapol_frame_io 1")
+
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
+ phase1="allow_canned_success=1",
+ eap="MD5", identity="user", password="password",
+ wait_connect=False)
+
+ ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
+ if ev is None:
+ raise Exception("Timeout on EAPOL-TX from hostapd")
+
+ res = dev[0].request("EAPOL_RX " + bssid + " 0200000403020004")
+ if "OK" not in res:
+ raise Exception("EAPOL_RX to wpa_supplicant failed")
+
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP success")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+def test_eap_canned_failure_before_method(dev, apdev):
+ """EAP protocol tests for canned EAP-Failure before any method"""
+ params = int_eap_server_params()
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+ hapd.request("SET ext_eapol_frame_io 1")
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
+ phase1="allow_canned_success=1",
+ eap="MD5", identity="user", password="password",
+ wait_connect=False)
+
+ ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
+ if ev is None:
+ raise Exception("Timeout on EAPOL-TX from hostapd")
+
+ res = dev[0].request("EAPOL_RX " + bssid + " 0200000404020004")
+ if "OK" not in res:
+ raise Exception("EAPOL_RX to wpa_supplicant failed")
+
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
+ if ev is None:
+ raise Exception("Timeout on EAP failure")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+def test_eap_nak_oom(dev, apdev):
+ """EAP-Nak OOM"""
+ check_eap_capa(dev[0], "MD5")
+ params = hostapd.wpa2_eap_params(ssid="eap-test")
+ hapd = hostapd.add_ap(apdev[0], params)
+ with alloc_fail(dev[0], 1, "eap_msg_alloc;eap_sm_buildNak"):
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="MD5", identity="sake user", password="password",
+ wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: Too long Ni in SAi1")
- ike = build_sa(next=34)
- ike += build_ke(next=40)
- ike += struct.pack(">BBH", 0, 0, 4 + 257) + 257*'\x00'
- return build_ike(ctx['id'], next=33, ike=ike)
+def test_eap_nak_expanded(dev, apdev):
+ """EAP-Nak with expanded method"""
+ check_eap_capa(dev[0], "MD5")
+ check_eap_capa(dev[0], "VENDOR-TEST")
+ params = hostapd.wpa2_eap_params(ssid="eap-test")
+ hapd = hostapd.add_ap(apdev[0], params)
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="VENDOR-TEST WSC",
+ identity="sake user", password="password",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=10)
+ if ev is None or "NAK" not in ev:
+ raise Exception("No NAK event seen")
+
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=10)
+ if ev is None:
+ raise Exception("No EAP-Failure seen")
+
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+EAP_TLV_RESULT_TLV = 3
+EAP_TLV_NAK_TLV = 4
+EAP_TLV_ERROR_CODE_TLV = 5
+EAP_TLV_CONNECTION_BINDING_TLV = 6
+EAP_TLV_VENDOR_SPECIFIC_TLV = 7
+EAP_TLV_URI_TLV = 8
+EAP_TLV_EAP_PAYLOAD_TLV = 9
+EAP_TLV_INTERMEDIATE_RESULT_TLV = 10
+EAP_TLV_PAC_TLV = 11
+EAP_TLV_CRYPTO_BINDING_TLV = 12
+EAP_TLV_CALLING_STATION_ID_TLV = 13
+EAP_TLV_CALLED_STATION_ID_TLV = 14
+EAP_TLV_NAS_PORT_TYPE_TLV = 15
+EAP_TLV_SERVER_IDENTIFIER_TLV = 16
+EAP_TLV_IDENTITY_TYPE_TLV = 17
+EAP_TLV_SERVER_TRUSTED_ROOT_TLV = 18
+EAP_TLV_REQUEST_ACTION_TLV = 19
+EAP_TLV_PKCS7_TLV = 20
+
+EAP_TLV_RESULT_SUCCESS = 1
+EAP_TLV_RESULT_FAILURE = 2
+
+EAP_TLV_TYPE_MANDATORY = 0x8000
+EAP_TLV_TYPE_MASK = 0x3fff
+
+PAC_TYPE_PAC_KEY = 1
+PAC_TYPE_PAC_OPAQUE = 2
+PAC_TYPE_CRED_LIFETIME = 3
+PAC_TYPE_A_ID = 4
+PAC_TYPE_I_ID = 5
+PAC_TYPE_A_ID_INFO = 7
+PAC_TYPE_PAC_ACKNOWLEDGEMENT = 8
+PAC_TYPE_PAC_INFO = 9
+PAC_TYPE_PAC_TYPE = 10
+
+def eap_fast_start(ctx):
+ logger.info("Send EAP-FAST/Start")
+ return struct.pack(">BBHBBHH", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + 4 + 16,
+ EAP_TYPE_FAST, 0x21, 4, 16) + 16*'A'
+
+def test_eap_fast_proto(dev, apdev):
+ """EAP-FAST Phase protocol testing"""
+ check_eap_capa(dev[0], "FAST")
+ global eap_fast_proto_ctx
+ eap_fast_proto_ctx = None
- def build_ni(next=0):
- return struct.pack(">BBH", next, 0, 4 + 256) + 256*'\x00'
+ def eap_handler(ctx, req):
+ logger.info("eap_handler - RX " + req.encode("hex"))
+ if 'num' not in ctx:
+ ctx['num'] = 0
+ ctx['num'] = ctx['num'] + 1
+ if 'id' not in ctx:
+ ctx['id'] = 1
+ ctx['id'] = (ctx['id'] + 1) % 256
+ idx = 0
- def build_sai1(id):
- ike = build_sa(next=34)
- ike += build_ke(next=40)
- ike += build_ni()
- return build_ike(ctx['id'], next=33, ike=ike)
+ global eap_fast_proto_ctx
+ eap_fast_proto_ctx = ctx
+ ctx['test_done'] = False
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Valid proposal, KEi, and Ni in SAi1")
- return build_sai1(ctx['id'])
- idx += 1
- if ctx['num'] == idx:
- logger.info("Test: EAP-Failure")
- return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
-
+ return eap_fast_start(ctx)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Valid proposal, KEi, and Ni in SAi1")
- return build_sai1(ctx['id'])
+ logger.info("EAP-FAST: TLS processing failed")
+ data = 'ABCDEFGHIK'
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + len(data),
+ EAP_TYPE_FAST, 0x01) + data
idx += 1
if ctx['num'] == idx:
- logger.info("Test: No integrity checksum")
- ike = ''
- return build_ike(ctx['id'], next=37, ike=ike)
+ ctx['test_done'] = True
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ logger.info("Past last test case")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+
+ srv = start_radius_server(eap_handler)
+ try:
+ hapd = start_ap(apdev[0])
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="FAST", anonymous_identity="FAST",
+ identity="user", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ phase1="fast_provisioning=1",
+ pac_file="blob://fast_pac_proto",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
+ if ev is None:
+ raise Exception("Could not start EAP-FAST")
+ ok = False
+ for i in range(100):
+ if eap_fast_proto_ctx:
+ if eap_fast_proto_ctx['test_done']:
+ ok = True
+ break
+ time.sleep(0.05)
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ finally:
+ stop_radius_server(srv)
+
+def run_eap_fast_phase2(dev, test_payload, test_failure=True):
+ global eap_fast_proto_ctx
+ eap_fast_proto_ctx = None
+
+ def ssl_info_callback(conn, where, ret):
+ logger.debug("SSL: info where=%d ret=%d" % (where, ret))
+
+ def process_clienthello(ctx, payload):
+ logger.info("Process ClientHello")
+ ctx['sslctx'] = OpenSSL.SSL.Context(OpenSSL.SSL.TLSv1_METHOD)
+ ctx['sslctx'].set_info_callback(ssl_info_callback)
+ ctx['sslctx'].load_tmp_dh("auth_serv/dh.conf")
+ ctx['sslctx'].set_cipher_list("ADH-AES128-SHA")
+ ctx['conn'] = OpenSSL.SSL.Connection(ctx['sslctx'], None)
+ ctx['conn'].set_accept_state()
+ logger.info("State: " + ctx['conn'].state_string())
+ ctx['conn'].bio_write(payload)
+ try:
+ ctx['conn'].do_handshake()
+ except OpenSSL.SSL.WantReadError:
+ pass
+ logger.info("State: " + ctx['conn'].state_string())
+ data = ctx['conn'].bio_read(4096)
+ logger.info("State: " + ctx['conn'].state_string())
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + len(data),
+ EAP_TYPE_FAST, 0x01) + data
+
+ def process_clientkeyexchange(ctx, payload, appl_data):
+ logger.info("Process ClientKeyExchange")
+ logger.info("State: " + ctx['conn'].state_string())
+ ctx['conn'].bio_write(payload)
+ try:
+ ctx['conn'].do_handshake()
+ except OpenSSL.SSL.WantReadError:
+ pass
+ ctx['conn'].send(appl_data)
+ logger.info("State: " + ctx['conn'].state_string())
+ data = ctx['conn'].bio_read(4096)
+ logger.info("State: " + ctx['conn'].state_string())
+ return struct.pack(">BBHBB", EAP_CODE_REQUEST, ctx['id'],
+ 4 + 1 + 1 + len(data),
+ EAP_TYPE_FAST, 0x01) + data
+
+ def eap_handler(ctx, req):
+ logger.info("eap_handler - RX " + req.encode("hex"))
+ if 'num' not in ctx:
+ ctx['num'] = 0
+ ctx['num'] = ctx['num'] + 1
+ if 'id' not in ctx:
+ ctx['id'] = 1
+ ctx['id'] = (ctx['id'] + 1) % 256
+ idx = 0
+
+ global eap_fast_proto_ctx
+ eap_fast_proto_ctx = ctx
+ ctx['test_done'] = False
+ logger.debug("ctx['num']=%d" % ctx['num'])
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Valid proposal, KEi, and Ni in SAi1")
- return build_sai1(ctx['id'])
+ return eap_fast_start(ctx)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Truncated integrity checksum")
- return struct.pack(">BBHBB",
- EAP_CODE_REQUEST, ctx['id'],
- 4 + 1 + 1,
- EAP_TYPE_IKEV2, 0x20)
-
+ return process_clienthello(ctx, req[6:])
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Valid proposal, KEi, and Ni in SAi1")
- return build_sai1(ctx['id'])
+ if not test_failure:
+ ctx['test_done'] = True
+ return process_clientkeyexchange(ctx, req[6:], test_payload)
idx += 1
if ctx['num'] == idx:
- logger.info("Test: Invalid integrity checksum")
- ike = ''
- return build_ike(ctx['id'], next=37, flags=0x20, ike=ike)
-
- return None
+ ctx['test_done'] = True
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
- srv = start_radius_server(ikev2_handler)
+ logger.info("Past last test case")
+ return struct.pack(">BBH", EAP_CODE_FAILURE, ctx['id'], 4)
+ srv = start_radius_server(eap_handler)
try:
- hapd = start_ap(apdev[0]['ifname'])
-
- for i in range(49):
- dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
- eap="IKEV2", identity="user",
- password="password",
- wait_connect=False)
- ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
- timeout=15)
- if ev is None:
- raise Exception("Timeout on EAP start")
- if i in [ 40, 45 ]:
- ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"],
- timeout=10)
- if ev is None:
- raise Exception("Timeout on EAP failure")
- else:
- time.sleep(0.05)
- dev[0].request("REMOVE_NETWORK all")
+ dev[0].connect("eap-test", key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="FAST", anonymous_identity="FAST",
+ identity="user", password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+ phase1="fast_provisioning=1",
+ pac_file="blob://fast_pac_proto",
+ wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-METHOD"], timeout=5)
+ if ev is None:
+ raise Exception("Could not start EAP-FAST")
+ dev[0].dump_monitor()
+ ok = False
+ for i in range(100):
+ if eap_fast_proto_ctx:
+ if eap_fast_proto_ctx['test_done']:
+ ok = True
+ break
+ time.sleep(0.05)
+ time.sleep(0.1)
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ if not ok:
+ raise Exception("EAP-FAST TLS exchange did not complete")
+ for i in range(3):
+ dev[i].dump_monitor()
finally:
stop_radius_server(srv)
+
+def test_eap_fast_proto_phase2(dev, apdev):
+ """EAP-FAST Phase 2 protocol testing"""
+ if not openssl_imported:
+ raise HwsimSkip("OpenSSL python method not available")
+ check_eap_capa(dev[0], "FAST")
+ hapd = start_ap(apdev[0])
+
+ tests = [ ("Too short Phase 2 TLV frame (len=3)",
+ "ABC",
+ False),
+ ("EAP-FAST: TLV overflow",
+ struct.pack(">HHB", 0, 2, 0xff),
+ False),
+ ("EAP-FAST: Unknown TLV (optional and mandatory)",
+ struct.pack(">HHB", 0, 1, 0xff) +
+ struct.pack(">HHB", EAP_TLV_TYPE_MANDATORY, 1, 0xff),
+ True),
+ ("EAP-FAST: More than one EAP-Payload TLV in the message",
+ struct.pack(">HHBHHB",
+ EAP_TLV_EAP_PAYLOAD_TLV, 1, 0xff,
+ EAP_TLV_EAP_PAYLOAD_TLV, 1, 0xff),
+ True),
+ ("EAP-FAST: Unknown Result 255 and More than one Result TLV in the message",
+ struct.pack(">HHHHHH",
+ EAP_TLV_RESULT_TLV, 2, 0xff,
+ EAP_TLV_RESULT_TLV, 2, 0xff),
+ True),
+ ("EAP-FAST: Too short Result TLV",
+ struct.pack(">HHB", EAP_TLV_RESULT_TLV, 1, 0xff),
+ True),
+ ("EAP-FAST: Unknown Intermediate Result 255 and More than one Intermediate-Result TLV in the message",
+ struct.pack(">HHHHHH",
+ EAP_TLV_INTERMEDIATE_RESULT_TLV, 2, 0xff,
+ EAP_TLV_INTERMEDIATE_RESULT_TLV, 2, 0xff),
+ True),
+ ("EAP-FAST: Too short Intermediate-Result TLV",
+ struct.pack(">HHB", EAP_TLV_INTERMEDIATE_RESULT_TLV, 1, 0xff),
+ True),
+ ("EAP-FAST: More than one Crypto-Binding TLV in the message",
+ struct.pack(">HH", EAP_TLV_CRYPTO_BINDING_TLV, 60) + 60*'A' +
+ struct.pack(">HH", EAP_TLV_CRYPTO_BINDING_TLV, 60) + 60*'A',
+ True),
+ ("EAP-FAST: Too short Crypto-Binding TLV",
+ struct.pack(">HHB", EAP_TLV_CRYPTO_BINDING_TLV, 1, 0xff),
+ True),
+ ("EAP-FAST: More than one Request-Action TLV in the message",
+ struct.pack(">HHBBHHBB",
+ EAP_TLV_REQUEST_ACTION_TLV, 2, 0xff, 0xff,
+ EAP_TLV_REQUEST_ACTION_TLV, 2, 0xff, 0xff),
+ True),
+ ("EAP-FAST: Too short Request-Action TLV",
+ struct.pack(">HHB", EAP_TLV_REQUEST_ACTION_TLV, 1, 0xff),
+ True),
+ ("EAP-FAST: More than one PAC TLV in the message",
+ struct.pack(">HHBHHB",
+ EAP_TLV_PAC_TLV, 1, 0xff,
+ EAP_TLV_PAC_TLV, 1, 0xff),
+ True),
+ ("EAP-FAST: Too short EAP Payload TLV (Len=3)",
+ struct.pack(">HH3B",
+ EAP_TLV_EAP_PAYLOAD_TLV, 3, 0, 0, 0),
+ False),
+ ("EAP-FAST: Too short Phase 2 request (Len=0)",
+ struct.pack(">HHBBH",
+ EAP_TLV_EAP_PAYLOAD_TLV, 4,
+ EAP_CODE_REQUEST, 0, 0),
+ False),
+ ("EAP-FAST: EAP packet overflow in EAP Payload TLV",
+ struct.pack(">HHBBH",
+ EAP_TLV_EAP_PAYLOAD_TLV, 4,
+ EAP_CODE_REQUEST, 0, 4 + 1),
+ False),
+ ("EAP-FAST: Unexpected code=0 in Phase 2 EAP header",
+ struct.pack(">HHBBH",
+ EAP_TLV_EAP_PAYLOAD_TLV, 4,
+ 0, 0, 0),
+ False),
+ ("EAP-FAST: PAC TLV without Result TLV acknowledging success",
+ struct.pack(">HHB", EAP_TLV_PAC_TLV, 1, 0xff),
+ True),
+ ("EAP-FAST: PAC TLV does not include all the required fields",
+ struct.pack(">HHH", EAP_TLV_RESULT_TLV, 2,
+ EAP_TLV_RESULT_SUCCESS) +
+ struct.pack(">HHB", EAP_TLV_PAC_TLV, 1, 0xff),
+ True),
+ ("EAP-FAST: Invalid PAC-Key length 0, Ignored unknown PAC type 0, and PAC TLV overrun (type=0 len=2 left=1)",
+ struct.pack(">HHH", EAP_TLV_RESULT_TLV, 2,
+ EAP_TLV_RESULT_SUCCESS) +
+ struct.pack(">HHHHHHHHB", EAP_TLV_PAC_TLV, 4 + 4 + 5,
+ PAC_TYPE_PAC_KEY, 0, 0, 0, 0, 2, 0),
+ True),
+ ("EAP-FAST: PAC-Info does not include all the required fields",
+ struct.pack(">HHH", EAP_TLV_RESULT_TLV, 2,
+ EAP_TLV_RESULT_SUCCESS) +
+ struct.pack(">HHHHHHHH", EAP_TLV_PAC_TLV, 4 + 4 + 4 + 32,
+ PAC_TYPE_PAC_OPAQUE, 0,
+ PAC_TYPE_PAC_INFO, 0,
+ PAC_TYPE_PAC_KEY, 32) + 32*'A',
+ True),
+ ("EAP-FAST: Invalid CRED_LIFETIME length, Ignored unknown PAC-Info type 0, and Invalid PAC-Type length 1",
+ struct.pack(">HHH", EAP_TLV_RESULT_TLV, 2,
+ EAP_TLV_RESULT_SUCCESS) +
+ struct.pack(">HHHHHHHHHHHHBHH", EAP_TLV_PAC_TLV, 4 + 4 + 13 + 4 + 32,
+ PAC_TYPE_PAC_OPAQUE, 0,
+ PAC_TYPE_PAC_INFO, 13, PAC_TYPE_CRED_LIFETIME, 0,
+ 0, 0, PAC_TYPE_PAC_TYPE, 1, 0,
+ PAC_TYPE_PAC_KEY, 32) + 32*'A',
+ True),
+ ("EAP-FAST: Unsupported PAC-Type 0",
+ struct.pack(">HHH", EAP_TLV_RESULT_TLV, 2,
+ EAP_TLV_RESULT_SUCCESS) +
+ struct.pack(">HHHHHHHHHHH", EAP_TLV_PAC_TLV, 4 + 4 + 6 + 4 + 32,
+ PAC_TYPE_PAC_OPAQUE, 0,
+ PAC_TYPE_PAC_INFO, 6, PAC_TYPE_PAC_TYPE, 2, 0,
+ PAC_TYPE_PAC_KEY, 32) + 32*'A',
+ True),
+ ("EAP-FAST: PAC-Info overrun (type=0 len=2 left=1)",
+ struct.pack(">HHH", EAP_TLV_RESULT_TLV, 2,
+ EAP_TLV_RESULT_SUCCESS) +
+ struct.pack(">HHHHHHHHBHH", EAP_TLV_PAC_TLV, 4 + 4 + 5 + 4 + 32,
+ PAC_TYPE_PAC_OPAQUE, 0,
+ PAC_TYPE_PAC_INFO, 5, 0, 2, 1,
+ PAC_TYPE_PAC_KEY, 32) + 32*'A',
+ True),
+ ("EAP-FAST: Valid PAC",
+ struct.pack(">HHH", EAP_TLV_RESULT_TLV, 2,
+ EAP_TLV_RESULT_SUCCESS) +
+ struct.pack(">HHHHHHHHBHHBHH", EAP_TLV_PAC_TLV,
+ 4 + 4 + 10 + 4 + 32,
+ PAC_TYPE_PAC_OPAQUE, 0,
+ PAC_TYPE_PAC_INFO, 10, PAC_TYPE_A_ID, 1, 0x41,
+ PAC_TYPE_A_ID_INFO, 1, 0x42,
+ PAC_TYPE_PAC_KEY, 32) + 32*'A',
+ True),
+ ("EAP-FAST: Invalid version/subtype in Crypto-Binding TLV",
+ struct.pack(">HH", EAP_TLV_CRYPTO_BINDING_TLV, 60) + 60*'A',
+ True) ]
+ for title, payload, failure in tests:
+ logger.info("Phase 2 test: " + title)
+ run_eap_fast_phase2(dev, payload, failure)
+
+def test_eap_fast_tlv_nak_oom(dev, apdev):
+ """EAP-FAST Phase 2 TLV NAK OOM"""
+ if not openssl_imported:
+ raise HwsimSkip("OpenSSL python method not available")
+ check_eap_capa(dev[0], "FAST")
+ hapd = start_ap(apdev[0])
+
+ with alloc_fail(dev[0], 1, "eap_fast_tlv_nak"):
+ run_eap_fast_phase2(dev, struct.pack(">HHB", EAP_TLV_TYPE_MANDATORY,
+ 1, 0xff), False)
import time
import hostapd
-from utils import HwsimSkip
+from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger
from test_ap_eap import int_eap_server_params
from test_ap_psk import find_wpas_process, read_process_memory, verify_not_present, get_key_locations
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
params['erp_send_reauth_start'] = '1'
params['erp_domain'] = 'example.com'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].request("ERP_FLUSH")
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
params['erp_send_reauth_start'] = '1'
params['erp_domain'] = 'example.com'
params['eap_server_erp'] = '1'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].request("ERP_FLUSH")
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
params['erp_domain'] = 'example.com'
params['eap_server_erp'] = '1'
params['disable_pmksa_caching'] = '1'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].request("ERP_FLUSH")
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
params['erp_domain'] = 'example.com'
params['eap_server_erp'] = '1'
params['disable_pmksa_caching'] = '1'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].request("ERP_FLUSH")
id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
"eap_fast_a_id_info": "test server",
"eap_server_erp": "1",
"erp_domain": "example.com" }
- hostapd.add_ap(apdev['ifname'], params)
+ hostapd.add_ap(apdev, params)
def test_erp_radius(dev, apdev):
"""ERP enabled on RADIUS server and peer"""
params['erp_send_reauth_start'] = '1'
params['erp_domain'] = 'example.com'
params['disable_pmksa_caching'] = '1'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].request("ERP_FLUSH")
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
params['erp_send_reauth_start'] = '1'
params['erp_domain'] = 'example.com'
params['disable_pmksa_caching'] = '1'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
erp_test(dev[0], hapd, eap="AKA", identity="0232010000000000@example.com",
password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123")
p['erp_domain'] = 'example.com'
p['eap_server_erp'] = '1'
p['disable_pmksa_caching'] = '1'
- hapd = hostapd.add_ap(apdev[0]['ifname'], p)
+ hapd = hostapd.add_ap(apdev[0], p)
password = "63d2d21ac3c09ed567ee004a34490f1d16e7fa5835edf17ddba70a63f1a90a25"
pid = find_wpas_process(dev[0])
ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
erp="1", scan_freq="2412")
+ # The decrypted copy of GTK is freed only after the CTRL-EVENT-CONNECTED
+ # event has been delivered, so verify that wpa_supplicant has returned to
+ # eloop before reading process memory.
time.sleep(1)
+ dev[0].ping()
buf = read_process_memory(pid, password)
dev[0].request("DISCONNECT")
if tk in buf:
raise Exception("TK found from memory")
if gtk in buf:
+ get_key_locations(buf, gtk, "GTK")
raise Exception("GTK found from memory")
logger.info("Checking keys in memory after disassociation")
get_key_locations(buf, rIK, "rIK")
verify_not_present(buf, rRK, fname, "rRK")
verify_not_present(buf, rIK, fname, "rIK")
+
+def test_erp_anonymous_identity(dev, apdev):
+ """ERP and anonymous identity"""
+ check_erp_capa(dev[0])
+ params = int_eap_server_params()
+ params['erp_send_reauth_start'] = '1'
+ params['erp_domain'] = 'example.com'
+ params['eap_server_erp'] = '1'
+ params['disable_pmksa_caching'] = '1'
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].request("ERP_FLUSH")
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
+ identity="erp-ttls",
+ anonymous_identity="anonymous@example.com",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
+ erp="1", scan_freq="2412")
+ for i in range(3):
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected(timeout=15)
+ dev[0].request("RECONNECT")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
+ if ev is None:
+ raise Exception("EAP success timed out")
+ if "EAP re-authentication completed successfully" not in ev:
+ raise Exception("Did not use ERP")
+ dev[0].wait_connected(timeout=15, error="Reconnection timed out")
+
+def test_erp_home_realm_oom(dev, apdev):
+ """ERP and home realm OOM"""
+ check_erp_capa(dev[0])
+ params = int_eap_server_params()
+ params['erp_send_reauth_start'] = '1'
+ params['erp_domain'] = 'example.com'
+ params['eap_server_erp'] = '1'
+ params['disable_pmksa_caching'] = '1'
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ for count in range(1, 3):
+ with alloc_fail(dev[0], count, "eap_home_realm"):
+ dev[0].request("ERP_FLUSH")
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
+ identity="erp-ttls@example.com",
+ anonymous_identity="anonymous@example.com",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
+ erp="1", scan_freq="2412", wait_connect=False)
+ dev[0].wait_connected(timeout=10)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ for count in range(1, 3):
+ with alloc_fail(dev[0], count, "eap_home_realm"):
+ dev[0].request("ERP_FLUSH")
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
+ identity="erp-ttls",
+ anonymous_identity="anonymous@example.com",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
+ erp="1", scan_freq="2412", wait_connect=False)
+ dev[0].wait_connected(timeout=10)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ for count in range(1, 3):
+ dev[0].request("ERP_FLUSH")
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
+ identity="erp-ttls@example.com",
+ anonymous_identity="anonymous@example.com",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
+ erp="1", scan_freq="2412", wait_connect=False)
+ dev[0].wait_connected(timeout=10)
+ if range > 1:
+ continue
+ with alloc_fail(dev[0], count, "eap_home_realm"):
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected(timeout=15)
+ dev[0].request("RECONNECT")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+def test_erp_local_errors(dev, apdev):
+ """ERP and local error cases"""
+ check_erp_capa(dev[0])
+ params = int_eap_server_params()
+ params['erp_send_reauth_start'] = '1'
+ params['erp_domain'] = 'example.com'
+ params['eap_server_erp'] = '1'
+ params['disable_pmksa_caching'] = '1'
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].request("ERP_FLUSH")
+ with alloc_fail(dev[0], 1, "eap_peer_erp_init"):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
+ identity="erp-ttls@example.com",
+ anonymous_identity="anonymous@example.com",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
+ erp="1", scan_freq="2412")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ for count in range(1, 6):
+ dev[0].request("ERP_FLUSH")
+ with fail_test(dev[0], count, "hmac_sha256_kdf;eap_peer_erp_init"):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
+ identity="erp-ttls@example.com",
+ anonymous_identity="anonymous@example.com",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
+ erp="1", scan_freq="2412")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ dev[0].request("ERP_FLUSH")
+ with alloc_fail(dev[0], 1, "eap_msg_alloc;eap_peer_erp_reauth_start"):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
+ identity="erp-ttls@example.com",
+ anonymous_identity="anonymous@example.com",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
+ erp="1", scan_freq="2412")
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected(timeout=15)
+ dev[0].request("RECONNECT")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ dev[0].request("ERP_FLUSH")
+ with fail_test(dev[0], 1, "hmac_sha256;eap_peer_erp_reauth_start"):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
+ identity="erp-ttls@example.com",
+ anonymous_identity="anonymous@example.com",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
+ erp="1", scan_freq="2412")
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected(timeout=15)
+ dev[0].request("RECONNECT")
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ dev[0].request("ERP_FLUSH")
+ with fail_test(dev[0], 1, "hmac_sha256;eap_peer_finish"):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
+ identity="erp-ttls@example.com",
+ anonymous_identity="anonymous@example.com",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
+ erp="1", scan_freq="2412")
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected(timeout=15)
+ dev[0].request("RECONNECT")
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ dev[0].request("ERP_FLUSH")
+ with alloc_fail(dev[0], 1, "eap_peer_erp_init"):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
+ identity="erp-ttls@example.com",
+ anonymous_identity="anonymous@example.com",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
+ erp="1", scan_freq="2412")
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected(timeout=15)
+
+ dev[0].request("ERP_FLUSH")
+ with alloc_fail(dev[0], 1, "eap_peer_finish"):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
+ identity="erp-ttls@example.com",
+ anonymous_identity="anonymous@example.com",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
+ erp="1", scan_freq="2412")
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected(timeout=15)
+ dev[0].request("RECONNECT")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ dev[0].request("ERP_FLUSH")
+ with fail_test(dev[0], 1, "hmac_sha256_kdf;eap_peer_finish"):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
+ identity="erp-ttls@example.com",
+ anonymous_identity="anonymous@example.com",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
+ erp="1", scan_freq="2412")
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected(timeout=15)
+ dev[0].request("RECONNECT")
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import logging
logger = logging.getLogger()
from test_ap_hs20 import interworking_select
from test_ap_hs20 import interworking_connect
+@remote_compatible
def test_ext_password_psk(dev, apdev):
"""External password storage for PSK"""
params = hostapd.wpa2_params(ssid="ext-pw-psk", passphrase="12345678")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].request("SET ext_password_backend test:psk1=12345678")
dev[0].connect("ext-pw-psk", raw_psk="ext:psk1", scan_freq="2412")
def test_ext_password_psk_not_found(dev, apdev):
"""External password storage for PSK and PSK not found"""
params = hostapd.wpa2_params(ssid="ext-pw-psk", passphrase="12345678")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].request("SET ext_password_backend test:psk1=12345678")
dev[0].connect("ext-pw-psk", raw_psk="ext:psk2", scan_freq="2412",
wait_connect=False)
def test_ext_password_eap(dev, apdev):
"""External password storage for EAP password"""
params = hostapd.wpa2_eap_params(ssid="ext-pw-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].request("SET ext_password_backend test:pw0=hello|pw1=password|pw2=secret")
dev[0].connect("ext-pw-eap", key_mgmt="WPA-EAP", eap="PEAP",
identity="user", password_hex="ext:pw1",
skip_with_fips(dev[0])
bssid = apdev[0]['bssid']
params = hs20_ap_params()
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].hs20_enable()
dev[0].request("SET ext_password_backend test:pw1=password")
self.nof_aps -= 1
else:
self.nof_stas -= 1
- config_file = self.get_cfg_pathname(cfg);
+ config_file = self.get_cfg_pathname(cfg)
if os.path.exists(config_file):
os.remove(config_file)
'alt-hostapd/hostapd/hostapd')
if not os.path.exists(prg):
prg = '../../hostapd/hostapd'
- cmd = [ prg, '-B', '-ddd',
+ cmd = [ prg, '-B', '-dddt',
'-P', pidfile, '-f', mylogfile, '-g', self.hapd_fst_global]
for i in range(0, len(self.cfgs_to_run)):
cfg = self.cfgs_to_run[i]
'alt-wpa_supplicant/wpa_supplicant/wpa_supplicant')
if not os.path.exists(prg):
prg = '../../wpa_supplicant/wpa_supplicant'
- cmd = [ prg, '-B', '-ddd',
+ cmd = [ prg, '-B', '-dddt',
'-P' + pidfile, '-f', mylogfile, '-g', self.wsup_fst_global ]
sta_no = 0
for i in range(0, len(self.cfgs_to_run)):
"""Terminates hostapd/wpa_supplicant processes previously launched with
run_hostapd/run_wpa_supplicant"""
pidfile = self.fst_logpath + '/' + 'myhostapd.pid'
- self.kill_pid(pidfile)
+ self.kill_pid(pidfile, self.nof_aps > 0)
pidfile = self.fst_logpath + '/' + 'mywpa_supplicant.pid'
- self.kill_pid(pidfile)
+ self.kill_pid(pidfile, self.nof_stas > 0)
self.reg_ctrl.stop()
while len(self.cfgs_to_run) != 0:
cfg = self.cfgs_to_run[0]
self.remove_cfg(cfg)
- def kill_pid(self, pidfile):
+ def kill_pid(self, pidfile, try_again=False):
"""Kills process by PID file"""
if not os.path.exists(pidfile):
- return
+ if not try_again:
+ return
+ # It might take some time for the process to write the PID file,
+ # so wait a bit longer before giving up.
+ self.logger.info("kill_pid: pidfile %s does not exist - try again after a second" % pidfile)
+ time.sleep(1)
+ if not os.path.exists(pidfile):
+ self.logger.info("kill_pid: pidfile %s does not exist - could not kill the process" % pidfile)
+ return
pid = -1
try:
- pf = file(pidfile, 'r')
- pid = int(pf.read().strip())
- pf.close()
+ for i in range(3):
+ pf = file(pidfile, 'r')
+ pidtxt = pf.read().strip()
+ self.logger.debug("kill_pid: %s: '%s'" % (pidfile, pidtxt))
+ pf.close()
+ try:
+ pid = int(pidtxt)
+ break
+ except Exception, e:
+ self.logger.debug("kill_pid: No valid PID found: %s" % str(e))
+ time.sleep(1)
self.logger.debug("kill_pid %s --> pid %d" % (pidfile, pid))
os.kill(pid, signal.SIGTERM)
for i in range(10):
exception_text = "Failure. Bad parameter was not detected (%s)" % bad_param_names[bad_param_type]
raise Exception(exception_text)
else:
- print "Failure. Unexpected exception"
+ logger.info("Failure. Unexpected exception")
def fst_initiate_session(apdev, test_params, bad_param_type, init_on_ap):
"""This function makes the necessary preparations and then adds, sets and
else:
raise Exception("Failure. Bad parameter was not detected (%s)" % bad_param_names[bad_param_type])
else:
- print "Failure. Unexpected exception"
+ logger.info("Failure. Unexpected exception")
def fst_transfer_session(apdev, test_params, bad_param_type, init_on_ap,
rsn=False):
else:
raise Exception("Failure. Bad parameter was not detected (%s)" % bad_param_names[bad_param_type])
else:
- print "Failure. Unexpected exception"
+ logger.info("Failure. Unexpected exception")
def fst_tear_down_session(apdev, test_params, bad_param_type, init_on_ap):
else:
raise Exception("Failure. Bad parameter was not detected (%s)" % bad_param_names[bad_param_type])
else:
- print "Failure. Unexpected exception"
+ logger.info("Failure. Unexpected exception")
#enum - remove session scenarios
else:
raise Exception("Failure. Remove scenario ended in an unexpected way (%s)" % remove_scenario_names[remove_session_scenario])
else:
- print "Failure. Unexpected exception"
+ logger.info("Failure. Unexpected exception")
#enum - frame types
else:
raise Exception("Failure. Frame was not ignored (%s)" % frame_type_names[frame_type])
else:
- print "Failure. Unexpected exception"
+ logger.info("Failure. Unexpected exception")
#enum - bad session transfer scenarios
else:
raise Exception("Failure. Bad scenario was handled incorrectly (%s)" % bad_scenario_names[bad_scenario_type])
else:
- print "Failure. Unexpected exception"
+ logger.info("Failure. Unexpected exception")
def test_fst_sta_connect_to_non_fst_ap(dev, apdev, test_params):
"""FST STA connecting to non-FST AP"""
res_sta2_mbies = sta2.get_local_mbies()
if (orig_sta1_mbies.startswith("FAIL") or
orig_sta2_mbies.startswith("FAIL") or
- not res_sta1_mbies.startswith("FAIL") or
- not res_sta2_mbies.startswith("FAIL")):
- raise Exception("Failure. MB IEs have not been removed on the stations")
+ res_sta1_mbies.startswith("FAIL") or
+ res_sta2_mbies.startswith("FAIL")):
+ raise Exception("Failure. MB IEs must be present on the stations")
except Exception, e:
logger.info(e)
raise
res_sta2_mbies = sta2.get_local_mbies()
if (orig_sta1_mbies.startswith("FAIL") or
orig_sta2_mbies.startswith("FAIL") or
- not res_sta1_mbies.startswith("FAIL") or
- not res_sta2_mbies.startswith("FAIL")):
- raise Exception("Failure. MB IEs have not been removed on the stations")
+ res_sta1_mbies.startswith("FAIL") or
+ res_sta2_mbies.startswith("FAIL")):
+ raise Exception("Failure. MB IEs must be present on the stations")
except Exception, e:
logger.info(e)
raise
time.sleep(2)
res_sta1_mbies = sta1.get_local_mbies()
res_sta2_mbies = sta2.get_local_mbies()
- if (not orig_sta1_mbies.startswith("FAIL") or
- not orig_sta2_mbies.startswith("FAIL") or
- not res_sta1_mbies.startswith("FAIL") or
- not res_sta2_mbies.startswith("FAIL")):
- raise Exception("Failure. MB IEs should have stayed non-present on the stations")
+ if (orig_sta1_mbies.startswith("FAIL") or
+ orig_sta2_mbies.startswith("FAIL") or
+ res_sta1_mbies.startswith("FAIL") or
+ res_sta2_mbies.startswith("FAIL")):
+ raise Exception("Failure. MB IEs must be present on the stations")
except Exception, e:
logger.info(e)
raise
time.sleep(2)
res_sta1_mbies = sta1.get_local_mbies()
res_sta2_mbies = sta2.get_local_mbies()
- if (not orig_sta1_mbies.startswith("FAIL") or
- not orig_sta2_mbies.startswith("FAIL") or
+ if (orig_sta1_mbies.startswith("FAIL") or
+ orig_sta2_mbies.startswith("FAIL") or
res_sta1_mbies.startswith("FAIL") or
res_sta2_mbies.startswith("FAIL")):
- raise Exception("Failure. MB IEs haven't reappeared on the stations")
+ raise Exception("Failure. MB IEs must be present on the stations")
except Exception, e:
logger.info(e)
raise
time.sleep(2)
res_sta1_mbies = sta1.get_local_mbies()
res_sta2_mbies = sta2.get_local_mbies()
- if (not orig_sta1_mbies.startswith("FAIL") or
- not orig_sta2_mbies.startswith("FAIL") or
- not res_sta1_mbies.startswith("FAIL") or
- not res_sta2_mbies.startswith("FAIL")):
- raise Exception("Failure. MB IEs should have stayed non-present on the stations")
+ if (orig_sta1_mbies.startswith("FAIL") or
+ orig_sta2_mbies.startswith("FAIL") or
+ res_sta1_mbies.startswith("FAIL") or
+ res_sta2_mbies.startswith("FAIL")):
+ raise Exception("Failure. MB IEs must be present on the stations")
except Exception, e:
logger.info(e)
raise
time.sleep(2)
res_sta1_mbies = sta1.get_local_mbies()
res_sta2_mbies = sta2.get_local_mbies()
- if (not orig_sta1_mbies.startswith("FAIL") or
- not orig_sta2_mbies.startswith("FAIL") or
+ if (orig_sta1_mbies.startswith("FAIL") or
+ orig_sta2_mbies.startswith("FAIL") or
res_sta1_mbies.startswith("FAIL") or
res_sta2_mbies.startswith("FAIL")):
- raise Exception("Failure. MB IEs haven't reappeared on the stations")
+ raise Exception("Failure. MB IEs must be present on the stations")
except Exception, e:
logger.info(e)
raise
def test_fst_disconnect_fst_sta(dev, apdev, test_params):
"""FST disconnect FST STA"""
ap1, ap2, fst_sta1, fst_sta2 = fst_module_aux.start_two_ap_sta_pairs(apdev)
- external_sta_connected = False;
+ external_sta_connected = False
try:
vals = fst_sta1.scan(freq=fst_test_common.fst_test_def_freq_a)
fst_sta1.connect(ap1, key_mgmt="NONE",
fst_test_common.fst_test_def_prio_low,
fst_test_common.fst_test_def_llt)
ap1.start()
+ try:
+ run_fst_ap_start_session_oom(apdev, ap1)
+ finally:
+ ap1.stop()
+
+def run_fst_ap_start_session_oom(apdev, ap1):
with alloc_fail(ap1, 1, "fst_iface_create"):
ap2_started = False
try:
except:
pass
finally:
- ap1.stop()
try:
ap2.stop()
except:
params = { "ssid": "fst_11a", "hw_mode": "a", "channel": "36",
"country_code": "US" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
fst_attach_ap(hglobal, apdev[0]['ifname'], group)
params = { "ssid": "fst_11g", "hw_mode": "g", "channel": "1",
"country_code": "US" }
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
fst_attach_ap(hglobal, apdev[1]['ifname'], group)
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
req = "1200011a060000"
stie = "a40b0100000000020001040001"
mbie = "9e16040200010200000004000000000000000000000000ff"
- with alloc_fail(hapd, 1, "mb_ies_by_info"):
- fst_setup_req(wpas, hglobal, 5180, apdev[0]['bssid'], req, stie, mbie,
- no_wait=True)
+ try:
+ with alloc_fail(hapd, 1, "mb_ies_by_info"):
+ fst_setup_req(wpas, hglobal, 5180, apdev[0]['bssid'], req, stie,
+ mbie, no_wait=True)
+ except HwsimSkip, e:
+ # Skip exception to allow proper cleanup
+ pass
+
+ # Remove sessions to avoid causing issues to following test ases
+ s = hglobal.request("FST-MANAGER LIST_SESSIONS " + group)
+ if not s.startswith("FAIL"):
+ for sid in s.split(' '):
+ if len(sid):
+ hglobal.request("FST-MANAGER SESSION_REMOVE " + sid)
def test_fst_many_setup(dev, apdev, test_params):
"""FST setup multiple times"""
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import time
import binascii
import logging
logger = logging.getLogger()
+import os
import re
import struct
import hostapd
from wpasupplicant import WpaSupplicant
-from utils import alloc_fail, skip_with_fips
+from tshark import run_tshark
+from utils import alloc_fail, wait_fail_trigger, skip_with_fips
+from hwsim import HWSimRadio
def hs20_ap_params():
params = hostapd.wpa2_params(ssid="test-gas")
def start_ap(ap):
params = hs20_ap_params()
params['hessid'] = ap['bssid']
- hostapd.add_ap(ap['ifname'], params)
- return hostapd.Hostapd(ap['ifname'])
+ return hostapd.add_ap(ap, params)
def get_gas_response(dev, bssid, info, allow_fetch_failure=False,
extra_test=False):
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
cmds = [ "foo",
"00:11:22:33:44:55",
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
# get BSS entry available to allow GAS query
dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
if "CTRL-EVENT-CONNECTED" not in ev:
raise Exception("Unexpected operation order")
-def test_gas_fragment(dev, apdev):
- """GAS fragmentation"""
- hapd = start_ap(apdev[0])
- hapd.set("gas_frag_limit", "50")
+def gas_fragment_and_comeback(dev, apdev, frag_limit=0, comeback_delay=0):
+ hapd = start_ap(apdev)
+ if frag_limit:
+ hapd.set("gas_frag_limit", str(frag_limit))
+ if comeback_delay:
+ hapd.set("gas_comeback_delay", str(comeback_delay))
- dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
- dev[0].request("FETCH_ANQP")
- ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=1)
+ dev.scan_for_bss(apdev['bssid'], freq="2412", force_scan=True)
+ dev.request("FETCH_ANQP")
+ ev = dev.wait_event(["GAS-QUERY-DONE"], timeout=5)
if ev is None:
raise Exception("No GAS-QUERY-DONE event")
if "result=SUCCESS" not in ev:
raise Exception("Unexpected GAS result: " + ev)
for i in range(0, 13):
- ev = dev[0].wait_event(["RX-ANQP", "RX-HS20-ANQP"], timeout=5)
+ ev = dev.wait_event(["RX-ANQP", "RX-HS20-ANQP"], timeout=5)
if ev is None:
raise Exception("Operation timed out")
- ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=1)
+ ev = dev.wait_event(["ANQP-QUERY-DONE"], timeout=1)
if ev is None:
raise Exception("No ANQP-QUERY-DONE event")
if "result=SUCCESS" not in ev:
raise Exception("Unexpected ANQP result: " + ev)
+def test_gas_fragment(dev, apdev):
+ """GAS fragmentation"""
+ gas_fragment_and_comeback(dev[0], apdev[0], frag_limit=50)
+
+def test_gas_fragment_mcc(dev, apdev):
+ """GAS fragmentation with mac80211_hwsim MCC enabled"""
+ with HWSimRadio(n_channels=2) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+ gas_fragment_and_comeback(wpas, apdev[0], frag_limit=50)
+
+def test_gas_fragment_with_comeback_delay(dev, apdev):
+ """GAS fragmentation and comeback delay"""
+ gas_fragment_and_comeback(dev[0], apdev[0], frag_limit=50,
+ comeback_delay=500)
+
+def test_gas_fragment_with_comeback_delay_mcc(dev, apdev):
+ """GAS fragmentation and comeback delay with mac80211_hwsim MCC enabled"""
+ with HWSimRadio(n_channels=2) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+ gas_fragment_and_comeback(wpas, apdev[0], frag_limit=50,
+ comeback_delay=500)
+
def test_gas_comeback_delay(dev, apdev):
"""GAS comeback delay"""
hapd = start_ap(apdev[0])
if ev is None:
raise Exception("Operation timed out")
+@remote_compatible
def test_gas_stop_fetch_anqp(dev, apdev):
"""Stop FETCH_ANQP operation"""
hapd = start_ap(apdev[0])
if ev is None or "WAN Metrics" not in ev:
raise Exception("Did not receive WAN Metrics")
+ logger.info("Attempt an MBO request with an AP that does not support MBO")
+ if "OK" not in dev[0].request("ANQP_GET " + bssid + " 272,mbo:1"):
+ raise Exception("ANQP_GET command failed (2)")
+
+ ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5)
+ if ev is None:
+ raise Exception("GAS query start timed out (2)")
+
+ ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
+ if ev is None:
+ raise Exception("GAS query timed out (2)")
+
cmds = [ "",
"foo",
"00:11:22:33:44:55 258,hs20:-1",
"00:11:22:33:44:55 hs20:-1",
"00:11:22:33:44:55 hs20:0",
"00:11:22:33:44:55 hs20:32",
+ "00:11:22:33:44:55 mbo:-1",
+ "00:11:22:33:44:55 mbo:0",
+ "00:11:22:33:44:55 mbo:999",
"00:11:22:33:44:55",
"00:11:22:33:44:55 ",
- "00:11:22:33:44:55 0" ]
+ "00:11:22:33:44:55 0",
+ "00:11:22:33:44:55 1" ]
for cmd in cmds:
if "FAIL" not in dev[0].request("ANQP_GET " + cmd):
raise Exception("Invalid ANQP_GET accepted")
"00:11:22:33:44:55 32",
"00:11:22:33:44:55",
"00:11:22:33:44:55 ",
- "00:11:22:33:44:55 0" ]
+ "00:11:22:33:44:55 0",
+ "00:11:22:33:44:55 1" ]
for cmd in cmds:
if "FAIL" not in dev[0].request("HS20_ANQP_GET " + cmd):
raise Exception("Invalid HS20_ANQP_GET accepted")
+def test_gas_anqp_get_oom(dev, apdev):
+ """GAS/ANQP query OOM"""
+ hapd = start_ap(apdev[0])
+ bssid = apdev[0]['bssid']
+
+ dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
+ with alloc_fail(dev[0], 1, "wpabuf_alloc;anqp_send_req"):
+ if "FAIL" not in dev[0].request("ANQP_GET " + bssid + " 258,268,hs20:3,hs20:4"):
+ raise Exception("ANQP_GET command accepted during OOM")
+ with alloc_fail(dev[0], 1, "hs20_build_anqp_req;hs20_anqp_send_req"):
+ if "FAIL" not in dev[0].request("HS20_ANQP_GET " + bssid + " 1"):
+ raise Exception("HS20_ANQP_GET command accepted during OOM")
+ with alloc_fail(dev[0], 1, "gas_query_req;hs20_anqp_send_req"):
+ if "FAIL" not in dev[0].request("HS20_ANQP_GET " + bssid + " 1"):
+ raise Exception("HS20_ANQP_GET command accepted during OOM")
+ with alloc_fail(dev[0], 1, "=hs20_anqp_send_req"):
+ if "FAIL" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
+ raise Exception("REQ_HS20_ICON command accepted during OOM")
+ with alloc_fail(dev[0], 2, "=hs20_anqp_send_req"):
+ if "FAIL" not in dev[0].request("REQ_HS20_ICON " + bssid + " w1fi_logo"):
+ raise Exception("REQ_HS20_ICON command accepted during OOM")
+
+def test_gas_anqp_icon_binary_proto(dev, apdev):
+ """GAS/ANQP and icon binary protocol testing"""
+ hapd = start_ap(apdev[0])
+ bssid = apdev[0]['bssid']
+
+ dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
+ hapd.set("ext_mgmt_frame_handling", "1")
+
+ tests = [ '010000', '01000000', '00000000', '00030000', '00020000',
+ '00000100', '0001ff0100ee', '0001ff0200ee' ]
+ for test in tests:
+ dev[0].request("HS20_ICON_REQUEST " + bssid + " w1fi_logo")
+ query = gas_rx(hapd)
+ gas = parse_gas(query['payload'])
+ resp = action_response(query)
+ data = binascii.unhexlify(test)
+ data = binascii.unhexlify('506f9a110b00') + data
+ data = struct.pack('<HHH', len(data) + 4, 0xdddd, len(data)) + data
+ resp['payload'] = anqp_initial_resp(gas['dialog_token'], 0) + data
+ send_gas_resp(hapd, resp)
+ expect_gas_result(dev[0], "SUCCESS")
+
+def test_gas_anqp_hs20_proto(dev, apdev):
+ """GAS/ANQP and Hotspot 2.0 element protocol testing"""
+ hapd = start_ap(apdev[0])
+ bssid = apdev[0]['bssid']
+
+ dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
+ hapd.set("ext_mgmt_frame_handling", "1")
+
+ tests = [ '00', '0100', '0201', '0300', '0400', '0500', '0600', '0700',
+ '0800', '0900', '0a00', '0b0000000000' ]
+ for test in tests:
+ dev[0].request("HS20_ANQP_GET " + bssid + " 3,4")
+ query = gas_rx(hapd)
+ gas = parse_gas(query['payload'])
+ resp = action_response(query)
+ data = binascii.unhexlify(test)
+ data = binascii.unhexlify('506f9a11') + data
+ data = struct.pack('<HHH', len(data) + 4, 0xdddd, len(data)) + data
+ resp['payload'] = anqp_initial_resp(gas['dialog_token'], 0) + data
+ send_gas_resp(hapd, resp)
+ expect_gas_result(dev[0], "SUCCESS")
+
def expect_gas_result(dev, result, status=None):
ev = dev.wait_event(["GAS-QUERY-DONE"], timeout=10)
if ev is None:
raise Exception("Unexpected dialog token change")
return query, dialog_token
+def allow_gas_initial_req(hapd, dialog_token):
+ msg = hapd.mgmt_rx(timeout=1)
+ if msg is not None:
+ gas = parse_gas(msg['payload'])
+ if gas['action'] != GAS_INITIAL_REQUEST or dialog_token == gas['dialog_token']:
+ raise Exception("Unexpected management frame")
+
def test_gas_malformed_comeback_resp(dev, apdev):
"""GAS malformed comeback response frames"""
hapd = start_ap(apdev[0])
resp = action_response(query)
resp['payload'] = anqp_initial_resp(dialog_token, 0) + struct.pack('<H', 0)
send_gas_resp(hapd, resp)
- ev = hapd.wait_event(["MGMT-RX"], timeout=1)
- if ev is not None:
- raise Exception("Unexpected management frame")
+ allow_gas_initial_req(hapd, dialog_token)
expect_gas_result(dev[0], "TIMEOUT")
logger.debug("Too short comeback response")
resp['payload'] = struct.pack('<BBBH', ACTION_CATEG_PUBLIC,
GAS_COMEBACK_RESPONSE, dialog_token, 0)
send_gas_resp(hapd, resp)
- ev = hapd.wait_event(["MGMT-RX"], timeout=1)
- if ev is not None:
- raise Exception("Unexpected management frame")
+ allow_gas_initial_req(hapd, dialog_token)
expect_gas_result(dev[0], "TIMEOUT")
logger.debug("Too short comeback response(2)")
GAS_COMEBACK_RESPONSE, dialog_token, 0, 0x80,
0)
send_gas_resp(hapd, resp)
- ev = hapd.wait_event(["MGMT-RX"], timeout=1)
- if ev is not None:
- raise Exception("Unexpected management frame")
+ allow_gas_initial_req(hapd, dialog_token)
expect_gas_result(dev[0], "TIMEOUT")
logger.debug("Maximum comeback response fragment claiming more fragments")
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
req = dev[0].request("GAS_REQUEST " + bssid + " 42 000102000101")
if status != "59":
raise Exception("Unexpected GAS-RESPONSE-INFO status")
+def test_gas_request_oom(dev, apdev):
+ """GAS_REQUEST OOM"""
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+ hostapd.add_ap(apdev[0], params)
+
+ dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
+
+ with alloc_fail(dev[0], 1, "gas_build_req;gas_send_request"):
+ if "FAIL" not in dev[0].request("GAS_REQUEST " + bssid + " 42"):
+ raise Exception("GAS query request rejected")
+
+ with alloc_fail(dev[0], 1, "gas_query_req;gas_send_request"):
+ if "FAIL" not in dev[0].request("GAS_REQUEST " + bssid + " 42"):
+ raise Exception("GAS query request rejected")
+
+ with alloc_fail(dev[0], 1, "wpabuf_dup;gas_resp_cb"):
+ if "OK" not in dev[0].request("GAS_REQUEST " + bssid + " 00 000102000101"):
+ raise Exception("GAS query request rejected")
+ ev = dev[0].wait_event(["GAS-RESPONSE-INFO"], timeout=10)
+ if ev is None:
+ raise Exception("No GAS response")
+ if "status_code=0" not in ev:
+ raise Exception("GAS response indicated a failure")
+
def test_gas_max_pending(dev, apdev):
"""GAS and maximum pending query limit"""
hapd = start_ap(apdev[0])
if status_code != 60:
raise Exception("Unexpected status code {} (expected 60)".format(status_code))
+def test_gas_delete_at_deinit(dev, apdev):
+ """GAS query deleted at deinit"""
+ hapd = start_ap(apdev[0])
+ hapd.set("gas_comeback_delay", "1000")
+ bssid = apdev[0]['bssid']
+
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add("wlan5")
+ wpas.scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
+ wpas.request("ANQP_GET " + bssid + " 258")
+
+ wpas.global_request("INTERFACE_REMOVE " + wpas.ifname)
+ ev = wpas.wait_event(["GAS-QUERY-DONE"], timeout=2)
+ del wpas
+ if ev is None:
+ raise Exception("GAS-QUERY-DONE not seen")
+ if "result=DELETED_AT_DEINIT" not in ev:
+ raise Exception("Unexpected result code: " + ev)
+
def test_gas_missing_payload(dev, apdev):
"""No action code in the query frame"""
bssid = apdev[0]['bssid']
params = hs20_ap_params()
params['hessid'] = bssid
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
# GAS query has not yet been started.
wpas.interface_remove("wlan5")
+@remote_compatible
def test_gas_anqp_oom_wpas(dev, apdev):
"""GAS/ANQP query and OOM in wpa_supplicant"""
hapd = start_ap(apdev[0])
dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
+ with alloc_fail(dev[0], 1, "wpa_bss_anqp_alloc"):
+ if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"):
+ raise Exception("ANQP_GET command failed")
+ ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=5)
+ if ev is None:
+ raise Exception("ANQP query did not complete")
+
with alloc_fail(dev[0], 1, "gas_build_req"):
if "FAIL" not in dev[0].request("ANQP_GET " + bssid + " 258"):
raise Exception("Unexpected ANQP_GET command success (OOM)")
with alloc_fail(hapd, 1, "gas_anqp_build_comeback_resp"):
hapd.set("gas_frag_limit", "50")
- # This query will time out due to the AP not sending a response (OOM).
- print dev[0].request("FETCH_ANQP")
+ # The first attempt of this query will time out due to the AP not
+ # sending a response (OOM), but the retry succeeds.
+ dev[0].request("FETCH_ANQP")
ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5)
if ev is None:
raise Exception("GAS query start timed out")
ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
if ev is None:
raise Exception("GAS query timed out")
- if "result=TIMEOUT" not in ev:
+ if "result=SUCCESS" not in ev:
raise Exception("Unexpected result: " + ev)
ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10)
if ev is None:
raise Exception("ANQP-QUERY-DONE event not seen")
- if "result=FAILURE" not in ev:
+ if "result=SUCCESS" not in ev:
raise Exception("Unexpected result: " + ev)
+
+def test_gas_anqp_extra_elements(dev, apdev):
+ """GAS/ANQP and extra ANQP elements"""
+ geo_loc = "001052834d12efd2b08b9b4bf1cc2c00004104050000000000060100"
+ civic_loc = "0000f9555302f50102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5"
+ held_uri = "https://held.example.com/location"
+ held = struct.pack('BBB', 0, 1 + len(held_uri), 1) + held_uri
+ supl_fqdn = "supl.example.com"
+ supl = struct.pack('BBB', 0, 1 + len(supl_fqdn), 1) + supl_fqdn
+ public_id = binascii.hexlify(held + supl)
+ params = { "ssid": "gas/anqp",
+ "interworking": "1",
+ "anqp_elem": [ "265:" + geo_loc,
+ "266:" + civic_loc,
+ "262:1122334455",
+ "267:" + public_id,
+ "275:01020304",
+ "60000:01",
+ "299:0102" ] }
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+
+ dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
+ if "OK" not in dev[0].request("ANQP_GET " + bssid + " 265,266"):
+ raise Exception("ANQP_GET command failed")
+
+ ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
+ if ev is None:
+ raise Exception("GAS query timed out")
+
+ bss = dev[0].get_bss(bssid)
+
+ if 'anqp[265]' not in bss:
+ raise Exception("AP Geospatial Location ANQP-element not seen")
+ if bss['anqp[265]'] != geo_loc:
+ raise Exception("Unexpected AP Geospatial Location ANQP-element value: " + bss['anqp[265]'])
+
+ if 'anqp[266]' not in bss:
+ raise Exception("AP Civic Location ANQP-element not seen")
+ if bss['anqp[266]'] != civic_loc:
+ raise Exception("Unexpected AP Civic Location ANQP-element value: " + bss['anqp[266]'])
+
+ dev[1].scan_for_bss(bssid, freq="2412", force_scan=True)
+ if "OK" not in dev[1].request("ANQP_GET " + bssid + " 257,258,259,260,261,262,263,264,265,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299"):
+ raise Exception("ANQP_GET command failed")
+
+ ev = dev[1].wait_event(["GAS-QUERY-DONE"], timeout=10)
+ if ev is None:
+ raise Exception("GAS query timed out")
+
+ bss = dev[1].get_bss(bssid)
+
+ if 'anqp[265]' not in bss:
+ raise Exception("AP Geospatial Location ANQP-element not seen")
+ if bss['anqp[265]'] != geo_loc:
+ raise Exception("Unexpected AP Geospatial Location ANQP-element value: " + bss['anqp[265]'])
+
+ if 'anqp[266]' in bss:
+ raise Exception("AP Civic Location ANQP-element unexpectedly seen")
+
+ if 'anqp[267]' not in bss:
+ raise Exception("AP Location Public Identifier ANQP-element not seen")
+ if bss['anqp[267]'] != public_id:
+ raise Exception("Unexpected AP Location Public Identifier ANQP-element value: " + bss['anqp[267]'])
+
+ if 'anqp[275]' not in bss:
+ raise Exception("ANQP-element Info ID 275 not seen")
+ if bss['anqp[275]'] != "01020304":
+ raise Exception("Unexpected AP ANQP-element Info ID 299 value: " + bss['anqp[299]'])
+
+ if 'anqp[299]' not in bss:
+ raise Exception("ANQP-element Info ID 299 not seen")
+ if bss['anqp[299]'] != "0102":
+ raise Exception("Unexpected AP ANQP-element Info ID 299 value: " + bss['anqp[299]'])
+
+ if 'anqp_ip_addr_type_availability' not in bss:
+ raise Exception("ANQP-element Info ID 292 not seen")
+ if bss['anqp_ip_addr_type_availability'] != "1122334455":
+ raise Exception("Unexpected AP ANQP-element Info ID 262 value: " + bss['anqp_ip_addr_type_availability'])
+
+def test_gas_anqp_address3_not_assoc(dev, apdev, params):
+ """GAS/ANQP query using IEEE 802.11 compliant Address 3 value when not associated"""
+ try:
+ _test_gas_anqp_address3_not_assoc(dev, apdev, params)
+ finally:
+ dev[0].request("SET gas_address3 0")
+
+def _test_gas_anqp_address3_not_assoc(dev, apdev, params):
+ hapd = start_ap(apdev[0])
+ bssid = apdev[0]['bssid']
+
+ if "OK" not in dev[0].request("SET gas_address3 1"):
+ raise Exception("Failed to set gas_address3")
+
+ dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
+ if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"):
+ raise Exception("ANQP_GET command failed")
+
+ ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5)
+ if ev is None:
+ raise Exception("GAS query start timed out")
+
+ ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
+ if ev is None:
+ raise Exception("GAS query timed out")
+
+ ev = dev[0].wait_event(["RX-ANQP"], timeout=1)
+ if ev is None or "Venue Name" not in ev:
+ raise Exception("Did not receive Venue Name")
+
+ ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10)
+ if ev is None:
+ raise Exception("ANQP-QUERY-DONE event not seen")
+ if "result=SUCCESS" not in ev:
+ raise Exception("Unexpected result: " + ev)
+
+ out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"),
+ "wlan_mgt.fixed.category_code == 4 && (wlan_mgt.fixed.publicact == 0x0a || wlan_mgt.fixed.publicact == 0x0b)",
+ display=["wlan.bssid"])
+ res = out.splitlines()
+ if len(res) != 2:
+ raise Exception("Unexpected number of GAS frames")
+ if res[0] != 'ff:ff:ff:ff:ff:ff':
+ raise Exception("GAS request used unexpected Address3 field value: " + res[0])
+ if res[1] != 'ff:ff:ff:ff:ff:ff':
+ raise Exception("GAS response used unexpected Address3 field value: " + res[1])
+
+def test_gas_anqp_address3_assoc(dev, apdev, params):
+ """GAS/ANQP query using IEEE 802.11 compliant Address 3 value when associated"""
+ try:
+ _test_gas_anqp_address3_assoc(dev, apdev, params)
+ finally:
+ dev[0].request("SET gas_address3 0")
+
+def _test_gas_anqp_address3_assoc(dev, apdev, params):
+ hapd = start_ap(apdev[0])
+ bssid = apdev[0]['bssid']
+
+ if "OK" not in dev[0].request("SET gas_address3 1"):
+ raise Exception("Failed to set gas_address3")
+
+ dev[0].scan_for_bss(bssid, freq="2412")
+ dev[0].connect("test-gas", key_mgmt="WPA-EAP", eap="TTLS",
+ identity="DOMAIN\mschapv2 user", anonymous_identity="ttls",
+ password="password", phase2="auth=MSCHAPV2",
+ ca_cert="auth_serv/ca.pem", scan_freq="2412")
+
+ if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"):
+ raise Exception("ANQP_GET command failed")
+
+ ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5)
+ if ev is None:
+ raise Exception("GAS query start timed out")
+
+ ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
+ if ev is None:
+ raise Exception("GAS query timed out")
+
+ ev = dev[0].wait_event(["RX-ANQP"], timeout=1)
+ if ev is None or "Venue Name" not in ev:
+ raise Exception("Did not receive Venue Name")
+
+ ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10)
+ if ev is None:
+ raise Exception("ANQP-QUERY-DONE event not seen")
+ if "result=SUCCESS" not in ev:
+ raise Exception("Unexpected result: " + ev)
+
+ out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"),
+ "wlan_mgt.fixed.category_code == 4 && (wlan_mgt.fixed.publicact == 0x0a || wlan_mgt.fixed.publicact == 0x0b)",
+ display=["wlan.bssid"])
+ res = out.splitlines()
+ if len(res) != 2:
+ raise Exception("Unexpected number of GAS frames")
+ if res[0] != bssid:
+ raise Exception("GAS request used unexpected Address3 field value: " + res[0])
+ if res[1] != bssid:
+ raise Exception("GAS response used unexpected Address3 field value: " + res[1])
+
+def test_gas_anqp_address3_ap_forced(dev, apdev, params):
+ """GAS/ANQP query using IEEE 802.11 compliant Address 3 value on AP"""
+ hapd = start_ap(apdev[0])
+ bssid = apdev[0]['bssid']
+ hapd.set("gas_address3", "1")
+
+ dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
+ if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"):
+ raise Exception("ANQP_GET command failed")
+
+ ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5)
+ if ev is None:
+ raise Exception("GAS query start timed out")
+
+ ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
+ if ev is None:
+ raise Exception("GAS query timed out")
+
+ ev = dev[0].wait_event(["RX-ANQP"], timeout=1)
+ if ev is None or "Venue Name" not in ev:
+ raise Exception("Did not receive Venue Name")
+
+ ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10)
+ if ev is None:
+ raise Exception("ANQP-QUERY-DONE event not seen")
+ if "result=SUCCESS" not in ev:
+ raise Exception("Unexpected result: " + ev)
+
+ out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"),
+ "wlan_mgt.fixed.category_code == 4 && (wlan_mgt.fixed.publicact == 0x0a || wlan_mgt.fixed.publicact == 0x0b)",
+ display=["wlan.bssid"])
+ res = out.splitlines()
+ if len(res) != 2:
+ raise Exception("Unexpected number of GAS frames")
+ if res[0] != bssid:
+ raise Exception("GAS request used unexpected Address3 field value: " + res[0])
+ if res[1] != 'ff:ff:ff:ff:ff:ff':
+ raise Exception("GAS response used unexpected Address3 field value: " + res[1])
+
+def test_gas_anqp_address3_ap_non_compliant(dev, apdev, params):
+ """GAS/ANQP query using IEEE 802.11 non-compliant Address 3 (AP)"""
+ try:
+ _test_gas_anqp_address3_ap_non_compliant(dev, apdev, params)
+ finally:
+ dev[0].request("SET gas_address3 0")
+
+def _test_gas_anqp_address3_ap_non_compliant(dev, apdev, params):
+ hapd = start_ap(apdev[0])
+ bssid = apdev[0]['bssid']
+ hapd.set("gas_address3", "2")
+
+ if "OK" not in dev[0].request("SET gas_address3 1"):
+ raise Exception("Failed to set gas_address3")
+
+ dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
+ if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"):
+ raise Exception("ANQP_GET command failed")
+
+ ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5)
+ if ev is None:
+ raise Exception("GAS query start timed out")
+
+ ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
+ if ev is None:
+ raise Exception("GAS query timed out")
+
+ ev = dev[0].wait_event(["RX-ANQP"], timeout=1)
+ if ev is None or "Venue Name" not in ev:
+ raise Exception("Did not receive Venue Name")
+
+ ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10)
+ if ev is None:
+ raise Exception("ANQP-QUERY-DONE event not seen")
+ if "result=SUCCESS" not in ev:
+ raise Exception("Unexpected result: " + ev)
+
+ out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"),
+ "wlan_mgt.fixed.category_code == 4 && (wlan_mgt.fixed.publicact == 0x0a || wlan_mgt.fixed.publicact == 0x0b)",
+ display=["wlan.bssid"])
+ res = out.splitlines()
+ if len(res) != 2:
+ raise Exception("Unexpected number of GAS frames")
+ if res[0] != 'ff:ff:ff:ff:ff:ff':
+ raise Exception("GAS request used unexpected Address3 field value: " + res[0])
+ if res[1] != bssid:
+ raise Exception("GAS response used unexpected Address3 field value: " + res[1])
+
+def test_gas_prot_vs_not_prot(dev, apdev, params):
+ """GAS/ANQP query protected vs. not protected"""
+ hapd = start_ap(apdev[0])
+ bssid = apdev[0]['bssid']
+
+ dev[0].scan_for_bss(bssid, freq="2412")
+ dev[0].connect("test-gas", key_mgmt="WPA-EAP", eap="TTLS",
+ identity="DOMAIN\mschapv2 user", anonymous_identity="ttls",
+ password="password", phase2="auth=MSCHAPV2",
+ ca_cert="auth_serv/ca.pem", scan_freq="2412",
+ ieee80211w="2")
+
+ if "OK" not in dev[0].request("ANQP_GET " + bssid + " 258"):
+ raise Exception("ANQP_GET command failed")
+
+ ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5)
+ if ev is None:
+ raise Exception("No GAS-QUERY-DONE event")
+ if "result=SUCCESS" not in ev:
+ raise Exception("Unexpected GAS result: " + ev)
+
+ # GAS: Drop unexpected unprotected GAS frame when PMF is enabled
+ dev[0].request("SET ext_mgmt_frame_handling 1")
+ res = dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=d0003a010200000000000200000003000200000003001000040b00000005006c027f000000")
+ dev[0].request("SET ext_mgmt_frame_handling 0")
+ if "OK" not in res:
+ raise Exception("MGMT_RX_PROCESS failed")
+
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected()
+
+ # GAS: No pending query found for 02:00:00:00:03:00 dialog token 0
+ dev[0].request("SET ext_mgmt_frame_handling 1")
+ res = dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=d0003a010200000000000200000003000200000003001000040b00000005006c027f000000")
+ dev[0].request("SET ext_mgmt_frame_handling 0")
+ if "OK" not in res:
+ raise Exception("MGMT_RX_PROCESS failed")
+
+ # GAS: Drop unexpected protected GAS frame when PMF is disabled
+ dev[0].request("SET ext_mgmt_frame_handling 1")
+ res = dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=d0003a010200000000000200000003000200000003001000090b00000005006c027f000000")
+ dev[0].request("SET ext_mgmt_frame_handling 0")
+ if "OK" not in res:
+ raise Exception("MGMT_RX_PROCESS failed")
+
+def test_gas_failures(dev, apdev):
+ """GAS failure cases"""
+ hapd = start_ap(apdev[0])
+ hapd.set("gas_comeback_delay", "5")
+ bssid = apdev[0]['bssid']
+
+ hapd2 = start_ap(apdev[1])
+ bssid2 = apdev[1]['bssid']
+
+ dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
+ dev[0].scan_for_bss(bssid2, freq="2412")
+
+ tests = [ (bssid, "gas_build_req;gas_query_tx_comeback_req"),
+ (bssid, "gas_query_tx;gas_query_tx_comeback_req"),
+ (bssid, "gas_query_append;gas_query_rx_comeback"),
+ (bssid2, "gas_query_append;gas_query_rx_initial"),
+ (bssid2, "wpabuf_alloc_copy;gas_query_rx_initial"),
+ (bssid, "gas_query_tx;gas_query_tx_initial_req") ]
+ for addr,func in tests:
+ with alloc_fail(dev[0], 1, func):
+ dev[0].request("ANQP_GET " + addr + " 258")
+ ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5)
+ if ev is None:
+ raise Exception("No GAS-QUERY-DONE seen")
+ if "result=INTERNAL_ERROR" not in ev:
+ raise Exception("Unexpected result code: " + ev)
+ dev[0].dump_monitor()
+
+ tests = [ "=gas_query_req", "radio_add_work;gas_query_req" ]
+ for func in tests:
+ with alloc_fail(dev[0], 1, func):
+ if "FAIL" not in dev[0].request("ANQP_GET " + bssid + " 258"):
+ raise Exception("ANQP_GET succeeded unexpectedly during OOM")
+ dev[0].dump_monitor()
+
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add("wlan5")
+ wpas.scan_for_bss(bssid2, freq="2412")
+ wpas.request("SET preassoc_mac_addr 1111")
+ wpas.request("ANQP_GET " + bssid2 + " 258")
+ ev = wpas.wait_event(["Failed to assign random MAC address for GAS"],
+ timeout=5)
+ wpas.request("SET preassoc_mac_addr 0")
+ if ev is None:
+ raise Exception("No random MAC address error seen")
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import hostapd
+import hwsim_utils
from utils import skip_with_fips
+@remote_compatible
def test_hapd_ctrl_status(dev, apdev):
"""hostapd ctrl_iface STATUS commands"""
ssid = "hapd-ctrl"
bssid = apdev[0]['bssid']
params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
status = hapd.get_status()
driver = hapd.get_driver_status()
if driver['addr'] != bssid:
raise Exception("Unexpected addr")
+@remote_compatible
def test_hapd_ctrl_p2p_manager(dev, apdev):
"""hostapd as P2P Device manager"""
ssid = "hapd-p2p-mgr"
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['manage_p2p'] = '1'
params['allow_cross_connection'] = '0'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
addr = dev[0].own_addr()
if "OK" not in hapd.request("DEAUTHENTICATE " + addr + " p2p=2"):
dev[0].wait_disconnected(timeout=5)
dev[0].wait_connected(timeout=10, error="Re-connection timed out")
+@remote_compatible
def test_hapd_ctrl_sta(dev, apdev):
"""hostapd and STA ctrl_iface commands"""
ssid = "hapd-ctrl-sta"
passphrase = "12345678"
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
addr = dev[0].own_addr()
if "FAIL" in hapd.request("STA " + addr):
if "FAIL" not in hapd.request("STA-NEXT 00:11:22:33:44"):
raise Exception("Unexpected STA-NEXT success")
+@remote_compatible
def test_hapd_ctrl_disconnect(dev, apdev):
"""hostapd and disconnection ctrl_iface commands"""
ssid = "hapd-ctrl"
passphrase = "12345678"
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
addr = dev[0].p2p_dev_addr()
dev[0].wait_disconnected(timeout=5)
dev[0].wait_connected(timeout=10, error="Re-connection timed out")
+@remote_compatible
def test_hapd_ctrl_chan_switch(dev, apdev):
"""hostapd and CHAN_SWITCH ctrl_iface command"""
ssid = "hapd-ctrl"
params = { "ssid": ssid }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
if "FAIL" not in hapd.request("CHAN_SWITCH "):
raise Exception("Unexpected CHAN_SWITCH success")
if "FAIL" not in hapd.request("CHAN_SWITCH qwerty 2422"):
if "FAIL" not in hapd.request("CHAN_SWITCH 0 2432 center_freq1=123 center_freq2=234 bandwidth=1000 sec_channel_offset=20 ht vht"):
raise Exception("Unexpected CHAN_SWITCH success")
+@remote_compatible
def test_hapd_ctrl_level(dev, apdev):
"""hostapd and LEVEL ctrl_iface command"""
ssid = "hapd-ctrl"
params = { "ssid": ssid }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
if "FAIL" not in hapd.request("LEVEL 0"):
raise Exception("Unexpected LEVEL success on non-monitor interface")
+@remote_compatible
def test_hapd_ctrl_new_sta(dev, apdev):
"""hostapd and NEW_STA ctrl_iface command"""
ssid = "hapd-ctrl"
params = { "ssid": ssid }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
if "FAIL" not in hapd.request("NEW_STA 00:11:22:33:44"):
raise Exception("Unexpected NEW_STA success")
if "OK" not in hapd.request("NEW_STA 00:11:22:33:44:55"):
if "AUTHORIZED" not in hapd.request("STA 00:11:22:33:44:55"):
raise Exception("Unexpected NEW_STA STA status")
+@remote_compatible
def test_hapd_ctrl_get(dev, apdev):
"""hostapd and GET ctrl_iface command"""
ssid = "hapd-ctrl"
params = { "ssid": ssid }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
if "FAIL" not in hapd.request("GET foo"):
raise Exception("Unexpected GET success")
if "FAIL" in hapd.request("GET version"):
raise Exception("Unexpected GET version failure")
+@remote_compatible
def test_hapd_ctrl_unknown(dev, apdev):
"""hostapd and unknown ctrl_iface command"""
ssid = "hapd-ctrl"
params = { "ssid": ssid }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
if "UNKNOWN COMMAND" not in hapd.request("FOO"):
raise Exception("Unexpected response")
+@remote_compatible
def test_hapd_ctrl_hs20_wnm_notif(dev, apdev):
"""hostapd and HS20_WNM_NOTIF ctrl_iface command"""
ssid = "hapd-ctrl"
params = { "ssid": ssid }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
if "FAIL" not in hapd.request("HS20_WNM_NOTIF 00:11:22:33:44 http://example.com/"):
raise Exception("Unexpected HS20_WNM_NOTIF success")
if "FAIL" not in hapd.request("HS20_WNM_NOTIF 00:11:22:33:44:55http://example.com/"):
raise Exception("Unexpected HS20_WNM_NOTIF success")
+@remote_compatible
def test_hapd_ctrl_hs20_deauth_req(dev, apdev):
"""hostapd and HS20_DEAUTH_REQ ctrl_iface command"""
ssid = "hapd-ctrl"
params = { "ssid": ssid }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
if "FAIL" not in hapd.request("HS20_DEAUTH_REQ 00:11:22:33:44 1 120 http://example.com/"):
raise Exception("Unexpected HS20_DEAUTH_REQ success")
if "FAIL" not in hapd.request("HS20_DEAUTH_REQ 00:11:22:33:44:55"):
if "FAIL" not in hapd.request("HS20_DEAUTH_REQ 00:11:22:33:44:55 1"):
raise Exception("Unexpected HS20_DEAUTH_REQ success")
+@remote_compatible
def test_hapd_ctrl_disassoc_imminent(dev, apdev):
"""hostapd and DISASSOC_IMMINENT ctrl_iface command"""
ssid = "hapd-ctrl"
params = { "ssid": ssid }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
if "FAIL" not in hapd.request("DISASSOC_IMMINENT 00:11:22:33:44"):
raise Exception("Unexpected DISASSOC_IMMINENT success")
if "FAIL" not in hapd.request("DISASSOC_IMMINENT 00:11:22:33:44:55"):
if ev is None:
raise Exception("Scan timed out")
+@remote_compatible
def test_hapd_ctrl_ess_disassoc(dev, apdev):
"""hostapd and ESS_DISASSOC ctrl_iface command"""
ssid = "hapd-ctrl"
params = { "ssid": ssid }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
if "FAIL" not in hapd.request("ESS_DISASSOC 00:11:22:33:44"):
raise Exception("Unexpected ESS_DISASSOCT success")
if "FAIL" not in hapd.request("ESS_DISASSOC 00:11:22:33:44:55"):
"""hostapd and SET deny_mac_file ctrl_iface command"""
ssid = "hapd-ctrl"
params = { "ssid": ssid }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412")
dev[1].connect(ssid, key_mgmt="NONE", scan_freq="2412")
if "OK" not in hapd.request("SET deny_mac_file hostapd.macaddr"):
"""hostapd and SET accept_mac_file ctrl_iface command"""
ssid = "hapd-ctrl"
params = { "ssid": ssid }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412")
dev[1].connect(ssid, key_mgmt="NONE", scan_freq="2412")
hapd.request("SET macaddr_acl 1")
if ev is not None:
raise Exception("Unexpected disconnection")
+@remote_compatible
def test_hapd_ctrl_set_error_cases(dev, apdev):
"""hostapd and SET error cases"""
ssid = "hapd-ctrl"
params = { "ssid": ssid }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
errors = [ "wpa_key_mgmt FOO",
"wpa_key_mgmt WPA-PSK \t FOO",
"wpa_key_mgmt \t ",
"beacon_int 65536",
"acs_num_scans 0",
"acs_num_scans 101",
- "rts_threshold -1",
- "rts_threshold 2348",
- "fragm_threshold -1",
+ "rts_threshold -2",
+ "rts_threshold 65536",
+ "fragm_threshold -2",
"fragm_threshold 2347",
"send_probe_response -1",
"send_probe_response 2",
"bss_load_test 12:80",
"vendor_elements 0",
"vendor_elements 0q",
+ "assocresp_elements 0",
+ "assocresp_elements 0q",
"local_pwr_constraint -1",
"local_pwr_constraint 256",
"wmm_ac_bk_cwmin -1",
if "OK" not in hapd.request("SET " + e):
raise Exception("Unexpected SET failure: '%s'" % e)
+@remote_compatible
def test_hapd_ctrl_global(dev, apdev):
"""hostapd and GET ctrl_iface command"""
ssid = "hapd-ctrl"
params = { "ssid": ssid }
ifname = apdev[0]['ifname']
- hapd = hostapd.add_ap(ifname, params)
- hapd_global = hostapd.HostapdGlobal()
+ hapd = hostapd.add_ap(apdev[0], params)
+ hapd_global = hostapd.HostapdGlobal(apdev[0])
res = hapd_global.request("IFNAME=" + ifname + " PING")
if "PONG" not in res:
raise Exception("Could not ping hostapd interface " + ifname + " via global control interface")
src_params = hostapd.wpa2_params(ssid=src_ssid, passphrase=passphrase)
src_ifname = apdev[0]['ifname']
- src_hapd = hostapd.add_ap(src_ifname, src_params)
+ src_hapd = hostapd.add_ap(apdev[0], src_params)
dst_params = { "ssid": dst_ssid }
dst_ifname = apdev[1]['ifname']
- dst_hapd = hostapd.add_ap(dst_ifname, dst_params, no_enable=True)
+ dst_hapd = hostapd.add_ap(apdev[1], dst_params, no_enable=True)
hapd_global = hostapd.HostapdGlobal()
src_params = hostapd.wpa_params(ssid=src_ssid)
src_params['wpa_psk'] = psk
src_ifname = apdev[0]['ifname']
- src_hapd = hostapd.add_ap(src_ifname, src_params)
+ src_hapd = hostapd.add_ap(apdev[0], src_params)
dst_params = { "ssid": dst_ssid }
dst_ifname = apdev[1]['ifname']
- dst_hapd = hostapd.add_ap(dst_ifname, dst_params, no_enable=True)
+ dst_hapd = hostapd.add_ap(apdev[1], dst_params, no_enable=True)
hapd_global = hostapd.HostapdGlobal()
if "FAIL" in dst_hapd.request("STA " + addr):
raise Exception("Could not connect using duplicated wpa params")
+@remote_compatible
def test_hapd_ctrl_log_level(dev, apdev):
"""hostapd ctrl_iface LOG_LEVEL"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
level = hapd.request("LOG_LEVEL")
if "Current level: MSGDUMP" not in level:
raise Exception("Unexpected debug level(1): " + level)
raise Exception("Unexpected debug level(3): " + level)
if "Timestamp: 1" not in level:
raise Exception("Unexpected timestamp(3): " + level)
+
+@remote_compatible
+def test_hapd_ctrl_disconnect_no_tx(dev, apdev):
+ """hostapd disconnecting STA without transmitting Deauth/Disassoc"""
+ ssid = "hapd-test"
+ passphrase = "12345678"
+ params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+ dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
+ addr0 = dev[0].own_addr()
+ dev[1].connect(ssid, psk=passphrase, scan_freq="2412")
+ addr1 = dev[1].own_addr()
+
+ # Disconnect the STA without sending out Deauthentication frame
+ if "OK" not in hapd.request("DEAUTHENTICATE " + addr0 + " tx=0"):
+ raise Exception("DEAUTHENTICATE command failed")
+ # Force disconnection due to AP receiving a frame from not-asssociated STA
+ dev[0].request("DATA_TEST_CONFIG 1")
+ dev[0].request("DATA_TEST_TX " + bssid + " " + addr0)
+ ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=5)
+ dev[0].request("DATA_TEST_CONFIG 0")
+ if ev is None:
+ raise Exception("Disconnection event not seen after TX attempt")
+ if "reason=7" not in ev:
+ raise Exception("Unexpected disconnection reason: " + ev)
+
+ # Disconnect the STA without sending out Disassociation frame
+ if "OK" not in hapd.request("DISASSOCIATE " + addr1 + " tx=0"):
+ raise Exception("DISASSOCIATE command failed")
+ # Force disconnection due to AP receiving a frame from not-asssociated STA
+ dev[1].request("DATA_TEST_CONFIG 1")
+ dev[1].request("DATA_TEST_TX " + bssid + " " + addr1)
+ ev = dev[1].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=5)
+ dev[1].request("DATA_TEST_CONFIG 0")
+ if ev is None:
+ raise Exception("Disconnection event not seen after TX attempt")
+ if "reason=7" not in ev:
+ raise Exception("Unexpected disconnection reason: " + ev)
+
+def test_hapd_ctrl_mib(dev, apdev):
+ """hostapd and MIB ctrl_iface command with open network"""
+ ssid = "hapd-ctrl"
+ params = { "ssid": ssid }
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ mib = hapd.request("MIB")
+ if len(mib) != 0:
+ raise Exception("Unexpected MIB response: " + mib)
+
+ mib = hapd.request("MIB radius_server")
+ if len(mib) != 0:
+ raise Exception("Unexpected 'MIB radius_server' response: " + mib)
+
+ if "FAIL" not in hapd.request("MIB foo"):
+ raise Exception("'MIB foo' succeeded")
+
+ dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412")
+
+ mib = hapd.request("MIB")
+ if "FAIL" in mib:
+ raise Exception("Unexpected MIB response: " + mib)
+
+ mib = hapd.request("MIB radius_server")
+ if len(mib) != 0:
+ raise Exception("Unexpected 'MIB radius_server' response: " + mib)
+
+ if "FAIL" not in hapd.request("MIB foo"):
+ raise Exception("'MIB foo' succeeded")
+
+def test_hapd_ctrl_not_yet_fully_enabled(dev, apdev):
+ """hostapd and ctrl_iface commands when BSS not yet fully enabled"""
+ ssid = "hapd-ctrl"
+ params = { "ssid": ssid }
+ hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
+
+ if not hapd.ping():
+ raise Exception("PING failed")
+ if "FAIL" in hapd.request("MIB"):
+ raise Exception("MIB failed")
+ if len(hapd.request("MIB radius_server")) != 0:
+ raise Exception("Unexpected 'MIB radius_server' response")
+ if "state=UNINITIALIZED" not in hapd.request("STATUS"):
+ raise Exception("Unexpected STATUS response")
+ if "FAIL" not in hapd.request("STATUS-DRIVER"):
+ raise Exception("Unexpected response to STATUS-DRIVER")
+ if len(hapd.request("STA-FIRST")) != 0:
+ raise Exception("Unexpected response to STA-FIRST")
+ if "FAIL" not in hapd.request("STA ff:ff:ff:ff:ff:ff"):
+ raise Exception("Unexpected response to STA")
+ cmds = [ "NEW_STA 02:ff:ff:ff:ff:ff",
+ "DEAUTHENTICATE 02:ff:ff:ff:ff:ff",
+ "DEAUTHENTICATE 02:ff:ff:ff:ff:ff test=0",
+ "DEAUTHENTICATE 02:ff:ff:ff:ff:ff p2p=0",
+ "DEAUTHENTICATE 02:ff:ff:ff:ff:ff tx=0",
+ "DISASSOCIATE 02:ff:ff:ff:ff:ff",
+ "DISASSOCIATE 02:ff:ff:ff:ff:ff test=0",
+ "DISASSOCIATE 02:ff:ff:ff:ff:ff p2p=0",
+ "DISASSOCIATE 02:ff:ff:ff:ff:ff tx=0",
+ "SA_QUERY 02:ff:ff:ff:ff:ff",
+ "WPS_PIN any 12345670",
+ "WPS_PBC",
+ "WPS_CANCEL",
+ "WPS_AP_PIN random",
+ "WPS_AP_PIN disable",
+ "WPS_CHECK_PIN 123456789",
+ "WPS_GET_STATUS",
+ "WPS_NFC_TAG_READ 00",
+ "WPS_NFC_CONFIG_TOKEN NDEF",
+ "WPS_NFC_TOKEN WPS",
+ "NFC_GET_HANDOVER_SEL NDEF WPS-CR",
+ "NFC_REPORT_HANDOVER RESP WPS 00 00",
+ "SET_QOS_MAP_SET 22,6,8,15,0,7,255,255,16,31,32,39,255,255,40,47,48,55",
+ "SEND_QOS_MAP_CONF 02:ff:ff:ff:ff:ff",
+ "HS20_WNM_NOTIF 02:ff:ff:ff:ff:ff https://example.com/",
+ "HS20_DEAUTH_REQ 02:ff:ff:ff:ff:ff 1 120 https://example.com/",
+ "DISASSOC_IMMINENT 02:ff:ff:ff:ff:ff 10",
+ "ESS_DISASSOC 02:ff:ff:ff:ff:ff 10 https://example.com/",
+ "BSS_TM_REQ 02:ff:ff:ff:ff:ff",
+ "GET_CONFIG",
+ "RADAR DETECTED freq=5260 ht_enabled=1 chan_width=1",
+ "CHAN_SWITCH 5 5200 ht sec_channel_offset=-1 bandwidth=40",
+ "TRACK_STA_LIST",
+ "PMKSA",
+ "PMKSA_FLUSH",
+ "SET_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\"",
+ "REMOVE_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\"",
+ "REQ_LCI 00:11:22:33:44:55",
+ "REQ_RANGE 00:11:22:33:44:55",
+ "DRIVER_FLAGS",
+ "STOP_AP" ]
+ for cmd in cmds:
+ hapd.request(cmd)
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import logging
logger = logging.getLogger()
import time
from utils import HwsimSkip
def hostapd_oom_loop(apdev, params, start_func="main"):
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "ctrl" })
- hapd_global = hostapd.HostapdGlobal()
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "ctrl" })
count = 0
for i in range(1, 1000):
if "OK" not in hapd.request("TEST_ALLOC_FAIL %d:%s" % (i, start_func)):
raise HwsimSkip("TEST_ALLOC_FAIL not supported")
try:
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params, timeout=2.5)
logger.info("Iteration %d - success" % i)
- hapd_global.remove(apdev[1]['ifname'])
+ hostapd.remove_bss(apdev[1])
state = hapd.request('GET_ALLOC_FAIL')
logger.info("GET_ALLOC_FAIL: " + state)
except Exception, e:
logger.info("Iteration %d - %s" % (i, str(e)))
+@remote_compatible
def test_hostapd_oom_open(dev, apdev):
"""hostapd failing to setup open mode due to OOM"""
params = { "ssid": "open" }
params['wpa_psk_file'] = 'hostapd.wpa_psk'
hostapd_oom_loop(apdev, params)
+@remote_compatible
def test_hostapd_oom_wpa2_eap(dev, apdev):
"""hostapd failing to setup WPA2-EAP mode due to OOM"""
params = hostapd.wpa2_eap_params(ssid="test")
params['acct_server_shared_secret'] = "radius"
hostapd_oom_loop(apdev, params)
+@remote_compatible
def test_hostapd_oom_wpa2_eap_radius(dev, apdev):
"""hostapd failing to setup WPA2-EAP mode due to OOM in RADIUS"""
params = hostapd.wpa2_eap_params(ssid="test")
def test_hostapd_oom_wpa2_psk_connect(dev, apdev):
"""hostapd failing during WPA2-PSK mode connection due to OOM"""
params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].request("SCAN_INTERVAL 1")
count = 0
params['acct_server_addr'] = "127.0.0.1"
params['acct_server_port'] = "1813"
params['acct_server_shared_secret'] = "radius"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].request("SCAN_INTERVAL 1")
count = 0
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import logging
logger = logging.getLogger()
import time
import subprocess
import hwsim_utils
-from utils import alloc_fail
+from utils import alloc_fail, wait_fail_trigger
def connect_ibss_cmd(dev, id, freq=2412):
dev.dump_monitor()
def add_ibss(dev, ssid, psk=None, proto=None, key_mgmt=None, pairwise=None,
group=None, beacon_int=None, bssid=None, scan_freq=None,
- wep_key0=None, freq=2412):
+ wep_key0=None, freq=2412, chwidth=0, group_rekey=0):
id = dev.add_network()
dev.set_network(id, "mode", "1")
dev.set_network(id, "frequency", str(freq))
+ if chwidth > 0:
+ dev.set_network(id, "max_oper_chwidth", str(chwidth))
if scan_freq:
dev.set_network(id, "scan_freq", str(scan_freq))
dev.set_network_quoted(id, "ssid", ssid)
dev.set_network(id, "bssid", bssid)
if wep_key0:
dev.set_network(id, "wep_key0", wep_key0)
+ if group_rekey:
+ dev.set_network(id, "group_rekey", str(group_rekey))
dev.request("ENABLE_NETWORK " + str(id) + " no-connect")
return id
-def add_ibss_rsn(dev, ssid):
- return add_ibss(dev, ssid, "12345678", "RSN", "WPA-PSK", "CCMP", "CCMP")
+def add_ibss_rsn(dev, ssid, group_rekey=0, scan_freq=None):
+ return add_ibss(dev, ssid, "12345678", "RSN", "WPA-PSK", "CCMP", "CCMP",
+ group_rekey=group_rekey, scan_freq=scan_freq)
def add_ibss_rsn_tkip(dev, ssid):
return add_ibss(dev, ssid, "12345678", "RSN", "WPA-PSK", "TKIP", "TKIP")
if "OK" not in dev[0].request("IBSS_RSN " + dev[1].p2p_interface_addr()):
raise Exception("IBSS_RSN command failed")
+ key_mgmt = dev[0].get_status_field("key_mgmt")
+ if key_mgmt != "WPA2-PSK":
+ raise Exception("Unexpected STATUS key_mgmt: " + key_mgmt)
+
+def test_ibss_rsn_group_rekey(dev):
+ """IBSS RSN group rekeying"""
+ ssid="ibss-rsn"
+
+ logger.info("Start IBSS on the first STA")
+ id = add_ibss_rsn(dev[0], ssid, group_rekey=4, scan_freq=2412)
+ connect_ibss_cmd(dev[0], id)
+ bssid0 = wait_ibss_connection(dev[0])
+ dev[0].dump_monitor()
+
+ logger.info("Join two STAs to the IBSS")
+
+ dev[1].scan_for_bss(bssid0, freq=2412)
+ id = add_ibss_rsn(dev[1], ssid, scan_freq=2412)
+ connect_ibss_cmd(dev[1], id)
+ bssid1 = wait_ibss_connection(dev[1])
+ if bssid0 != bssid1:
+ raise Exception("STA0 BSSID " + bssid0 + " differs from STA1 BSSID " + bssid1)
+ wait_4way_handshake(dev[0], dev[1])
+ wait_4way_handshake(dev[1], dev[0])
+ dev[0].dump_monitor()
+ dev[1].dump_monitor()
+
+ hwsim_utils.test_connectivity(dev[0], dev[1])
+ ev = dev[1].wait_event(["WPA: Group rekeying completed"], timeout=10)
+ if ev is None:
+ raise Exception("No group rekeying reported")
+ hwsim_utils.test_connectivity(dev[0], dev[1])
+
def test_ibss_wpa_none(dev):
"""IBSS WPA-None"""
ssid="ibss-wpa-none"
except Exception, e:
logger.info("Ignoring known connectivity failure: " + str(e))
+ key_mgmt = dev[0].get_status_field("key_mgmt")
+ if key_mgmt != "WPA-NONE":
+ raise Exception("Unexpected STATUS key_mgmt: " + key_mgmt)
+
def test_ibss_wpa_none_ccmp(dev):
"""IBSS WPA-None/CCMP"""
ssid="ibss-wpa-none"
if "[IBSS]" not in bss['flags']:
raise Exception("Unexpected BSS flags: " + bss['flags'])
+ freq0 = dev[0].get_status_field("freq")
+ freq1 = dev[1].get_status_field("freq")
+ if freq0 != "2412" or freq1 != "2412":
+ raise Exception("IBSS operating frequency not reported correctly (%s %s)" % (freq0, freq1))
+
+ key_mgmt = dev[0].get_status_field("key_mgmt")
+ if key_mgmt != "NONE":
+ raise Exception("Unexpected STATUS key_mgmt: " + key_mgmt)
+
def test_ibss_open_fixed_bssid(dev):
"""IBSS open (no security) and fixed BSSID"""
ssid="ibss"
connect_ibss_cmd(dev[1], id)
bssid1 = wait_ibss_connection(dev[1])
+@remote_compatible
def test_ibss_rsn_error_case(dev):
"""IBSS RSN regression test for IBSS_RSN prior IBSS setup"""
if "FAIL" not in dev[0].request("IBSS_RSN 02:03:04:05:06:07"):
dev[0].dump_monitor()
dev[1].dump_monitor()
+def test_ibss_vht_80p80(dev):
+ """IBSS on VHT 80+80 MHz channel"""
+ try:
+ _test_ibss_vht_80p80(dev)
+ finally:
+ subprocess.call(['iw', 'reg', 'set', '00'])
+ dev[0].flush_scan_cache()
+ dev[1].flush_scan_cache()
+
+def _test_ibss_vht_80p80(dev):
+ subprocess.call(['iw', 'reg', 'set', 'US'])
+ for i in range(2):
+ for j in range(5):
+ ev = dev[i].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=5)
+ if ev is None:
+ raise Exception("No regdom change event")
+ if "alpha2=US" in ev:
+ break
+ dev[i].dump_monitor()
+
+ ssid="ibss"
+ id = add_ibss(dev[0], ssid, key_mgmt="NONE", freq=5180, chwidth=3)
+ connect_ibss_cmd(dev[0], id, freq=5180)
+ bssid0 = wait_ibss_connection(dev[0])
+ sig = dev[0].request("SIGNAL_POLL").splitlines()
+ if "FREQUENCY=5180" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig))
+ if "WIDTH=80+80 MHz" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
+ if "CENTER_FRQ1=5210" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(3): " + str(sig))
+ if "CENTER_FRQ2=5775" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(4): " + str(sig))
+
+ dev[1].scan_for_bss(bssid0, freq=5180)
+ id = add_ibss(dev[1], ssid, key_mgmt="NONE", freq=5180, chwidth=3)
+ connect_ibss_cmd(dev[1], id, freq=5180)
+ bssid1 = wait_ibss_connection(dev[1])
+ if bssid0 != bssid1:
+ logger.info("STA0 BSSID " + bssid0 + " differs from STA1 BSSID " + bssid1)
+
+ sig = dev[1].request("SIGNAL_POLL").splitlines()
+ if "FREQUENCY=5180" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(1b): " + str(sig))
+ logger.info("STA1 SIGNAL_POLL: " + str(sig))
+ # For now, don't report errors on joining STA failing to get 80+80 MHZ
+ # since mac80211 missed functionality for that to work.
+
+ dev[0].request("DISCONNECT")
+ dev[1].request("DISCONNECT")
+ dev[0].dump_monitor()
+ dev[1].dump_monitor()
+
def test_ibss_rsn_oom(dev):
"""IBSS RSN OOM during wpa_init"""
with alloc_fail(dev[0], 1, "wpa_init"):
ssid="ibss-rsn"
- id = add_ibss_rsn(dev[0], ssid)
+ id = add_ibss_rsn(dev[0], ssid, scan_freq=2412)
connect_ibss_cmd(dev[0], id)
bssid0 = wait_ibss_connection(dev[0])
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
+
+ with alloc_fail(dev[0], 1, "=ibss_rsn_init"):
+ ssid="ibss-rsn"
+ id = add_ibss_rsn(dev[0], ssid, scan_freq=2412)
+ connect_ibss_cmd(dev[0], id)
+ bssid0 = wait_ibss_connection(dev[0])
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].dump_monitor()
+
+def send_eapol_rx(dev, dst):
+ if "OK" not in dev.request("EAPOL_RX %s 0203005f02008a001000000000000000013a54fb19d8a785f5986bdc2ba800553550bc9513e6603eb50809154588c22b110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" % dst):
+ raise Exception("EAPOL_RX for %s failed" % dst)
+
+def test_ibss_rsn_eapol_trigger(dev):
+ """IBSS RSN and EAPOL trigger for a new peer"""
+ ssid="ibss-rsn"
+
+ id = add_ibss_rsn(dev[0], ssid, scan_freq=2412)
+ connect_ibss_cmd(dev[0], id)
+ bssid0 = wait_ibss_connection(dev[0])
+
+ send_eapol_rx(dev[0], "02:ff:00:00:00:01")
+ send_eapol_rx(dev[0], "02:ff:00:00:00:01")
+
+ dst = "02:ff:00:00:00:01"
+ logger.info("Too short EAPOL frame")
+ if "OK" not in dev[0].request("EAPOL_RX %s 0203005e02008a001000000000000000013a54fb19d8a785f5986bdc2ba800553550bc9513e6603eb50809154588c22b1100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" % dst):
+ raise Exception("EAPOL_RX for %s failed" % dst)
+ logger.info("RSN: EAPOL frame (type 255) discarded, not a Key frame")
+ if "OK" not in dev[0].request("EAPOL_RX %s 02ff005f02008a001000000000000000013a54fb19d8a785f5986bdc2ba800553550bc9513e6603eb50809154588c22b110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" % dst):
+ raise Exception("EAPOL_RX for %s failed" % dst)
+ logger.info("RSN: EAPOL frame payload size 96 invalid (frame size 99)")
+ if "OK" not in dev[0].request("EAPOL_RX %s 0203006002008a001000000000000000013a54fb19d8a785f5986bdc2ba800553550bc9513e6603eb50809154588c22b110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" % dst):
+ raise Exception("EAPOL_RX for %s failed" % dst)
+ logger.info("RSN: EAPOL-Key type (255) unknown, discarded")
+ if "OK" not in dev[0].request("EAPOL_RX %s 0203005fff008a001000000000000000013a54fb19d8a785f5986bdc2ba800553550bc9513e6603eb50809154588c22b110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" % dst):
+ raise Exception("EAPOL_RX for %s failed" % dst)
+
+ with alloc_fail(dev[0], 1, "ibss_rsn_rx_eapol"):
+ send_eapol_rx(dev[0], "02:ff:00:00:00:02")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+
+ with alloc_fail(dev[0], 1, "wpa_auth_sta_init;ibss_rsn_auth_init"):
+ send_eapol_rx(dev[0], "02:ff:00:00:00:03")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+
+ with alloc_fail(dev[0], 1, "=ibss_rsn_peer_init"):
+ send_eapol_rx(dev[0], "02:ff:00:00:00:04")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+
+ with alloc_fail(dev[0], 1, "ibss_rsn_process_rx_eapol"):
+ send_eapol_rx(dev[0], "02:ff:00:00:00:05")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+
+ with alloc_fail(dev[0], 1,
+ "wpa_sm_set_assoc_wpa_ie_default;ibss_rsn_supp_init"):
+ send_eapol_rx(dev[0], "02:ff:00:00:00:06")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+
+ with alloc_fail(dev[0], 1, "wpa_sm_init;ibss_rsn_supp_init"):
+ send_eapol_rx(dev[0], "02:ff:00:00:00:07")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+
+ with alloc_fail(dev[0], 1, "=ibss_rsn_supp_init"):
+ send_eapol_rx(dev[0], "02:ff:00:00:00:08")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+
+ with alloc_fail(dev[0], 1, "supp_alloc_eapol"):
+ send_eapol_rx(dev[0], "02:ff:00:00:00:09")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+
+ with alloc_fail(dev[0], 1, "wpa_validate_wpa_ie;ibss_rsn_auth_init"):
+ send_eapol_rx(dev[0], "02:ff:00:00:00:0a")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+
+ logger.info("RSN: Timeout on waiting Authentication frame response")
+ if "OK" not in dev[0].request("IBSS_RSN 02:ff:00:00:00:0b"):
+ raise Exception("Unexpected IBSS_RSN result")
+ time.sleep(1.1)
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import binascii
import hmac
import logging
+import os
import time
import hostapd
import hwsim_utils
from utils import skip_with_fips
+from tshark import run_tshark
logger = logging.getLogger()
params["ieee8021x"] = "1"
params["wep_key_len_broadcast"] = "13"
params["wep_key_len_unicast"] = "13"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("ieee8021x-wep", key_mgmt="IEEE8021X", eap="PSK",
identity="psk.user@example.com",
params["ieee8021x"] = "1"
params["wep_key_len_broadcast"] = "5"
params["wep_key_len_unicast"] = "5"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("ieee8021x-wep", key_mgmt="IEEE8021X", eap="PSK",
identity="psk.user@example.com",
params = hostapd.radius_params()
params["ssid"] = "ieee8021x-open"
params["ieee8021x"] = "1"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
id = dev[0].connect("ieee8021x-open", key_mgmt="IEEE8021X", eapol_flags="0",
eap="PSK", identity="psk.user@example.com",
params["ssid"] = "ieee8021x-wep"
params["ieee8021x"] = "1"
params["wep_key0"] = '"hello"'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("ieee8021x-wep", key_mgmt="IEEE8021X", eap="PSK",
identity="psk.user@example.com",
params = hostapd.radius_params()
params["ssid"] = "ieee8021x-open"
params["ieee8021x"] = "1"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
dev[1].request("SET ext_eapol_frame_io 1")
if int(stop[val]) <= int(start[val]):
raise Exception(val + " did not increase")
+@remote_compatible
def test_ieee8021x_eapol_start(dev, apdev):
"""IEEE 802.1X and EAPOL-Start retransmissions"""
params = hostapd.radius_params()
params["ssid"] = "ieee8021x-open"
params["ieee8021x"] = "1"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
addr0 = dev[0].own_addr()
params = hostapd.radius_params()
params["ssid"] = "ieee8021x-open"
params["ieee8021x"] = "1"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
hapd.set("ext_eapol_frame_io", "1")
params["ieee8021x"] = "1"
params["wep_key_len_broadcast"] = "5"
params["wep_key_len_unicast"] = "5"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
dev[0].connect("ieee8021x-wep", key_mgmt="IEEE8021X", eap="VENDOR-TEST",
params = hostapd.radius_params()
params["ssid"] = "ieee8021x-open"
params["ieee8021x"] = "1"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("ieee8021x-open", key_mgmt="IEEE8021X", eapol_flags="0",
eap="PSK", identity="psk.user@example.com",
time.sleep(0.1)
hwsim_utils.test_connectivity(dev[0], hapd)
+def test_ieee8021x_reauth_wep(dev, apdev, params):
+ """IEEE 802.1X and EAPOL_REAUTH request with WEP"""
+ logdir = params['logdir']
+
+ params = hostapd.radius_params()
+ params["ssid"] = "ieee8021x-open"
+ params["ieee8021x"] = "1"
+ params["wep_key_len_broadcast"] = "13"
+ params["wep_key_len_unicast"] = "13"
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].connect("ieee8021x-open", key_mgmt="IEEE8021X",
+ eap="PSK", identity="psk.user@example.com",
+ password_hex="0123456789abcdef0123456789abcdef",
+ scan_freq="2412")
+ hwsim_utils.test_connectivity(dev[0], hapd)
+
+ hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
+ if ev is None:
+ raise Exception("EAP authentication did not start")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=5)
+ if ev is None:
+ raise Exception("EAP authentication did not succeed")
+ time.sleep(0.1)
+ hwsim_utils.test_connectivity(dev[0], hapd)
+
+ out = run_tshark(os.path.join(logdir, "hwsim0.pcapng"),
+ "llc.type == 0x888e", ["eapol.type", "eap.code"])
+ if out is None:
+ raise Exception("Could not find EAPOL frames in capture")
+ num_eapol_key = 0
+ num_eap_req = 0
+ num_eap_resp = 0
+ for line in out.splitlines():
+ vals = line.split()
+ if vals[0] == '3':
+ num_eapol_key += 1
+ if vals[0] == '0' and len(vals) == 2:
+ if vals[1] == '1':
+ num_eap_req += 1
+ elif vals[1] == '2':
+ num_eap_resp += 1
+ logger.info("num_eapol_key: %d" % num_eapol_key)
+ logger.info("num_eap_req: %d" % num_eap_req)
+ logger.info("num_eap_resp: %d" % num_eap_resp)
+ if num_eapol_key < 4:
+ raise Exception("Did not see four unencrypted EAPOL-Key frames")
+ if num_eap_req < 6:
+ raise Exception("Did not see six unencrypted EAP-Request frames")
+ if num_eap_resp < 6:
+ raise Exception("Did not see six unencrypted EAP-Response frames")
+
def test_ieee8021x_set_conf(dev, apdev):
"""IEEE 802.1X and EAPOL_SET command"""
params = hostapd.radius_params()
params["ssid"] = "ieee8021x-open"
params["ieee8021x"] = "1"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("ieee8021x-open", key_mgmt="IEEE8021X", eapol_flags="0",
eap="PSK", identity="psk.user@example.com",
params["ssid"] = "ieee8021x-open"
params["ieee8021x"] = "1"
params['auth_server_port'] = "18129"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
addr0 = dev[0].own_addr()
params['ca_cert'] = 'auth_serv/ca.pem'
params['server_cert'] = 'auth_serv/server.pem'
params['private_key'] = 'auth_serv/server.key'
- hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd1 = hostapd.add_ap(apdev[1], params)
dev[0].connect("ieee8021x-open", key_mgmt="IEEE8021X", eapol_flags="0",
eap="PSK", identity="psk.user@example.com",
ev = hapd.wait_event(["CTRL-EVENT-EAP-PROPOSED"], timeout=10)
if ev is None:
raise Exception("Authentication restart not seen")
+
+def test_ieee8021x_open_leap(dev, apdev):
+ """IEEE 802.1X connection with LEAP included in configuration"""
+ params = hostapd.radius_params()
+ params["ssid"] = "ieee8021x-open"
+ params["ieee8021x"] = "1"
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[1].connect("ieee8021x-open", key_mgmt="IEEE8021X", eapol_flags="0",
+ eap="LEAP", identity="psk.user@example.com",
+ password_hex="0123456789abcdef0123456789abcdef",
+ scan_freq="2412", wait_connect=False)
+ dev[0].connect("ieee8021x-open", key_mgmt="IEEE8021X", eapol_flags="0",
+ eap="PSK LEAP", identity="psk.user@example.com",
+ password_hex="0123456789abcdef0123456789abcdef",
+ scan_freq="2412")
+ ev = dev[1].wait_event(["CTRL-EVENT-AUTH-REJECT"], timeout=5)
+ dev[1].request("DISCONNECT")
+
+def test_ieee8021x_and_wpa_enabled(dev, apdev):
+ """IEEE 802.1X connection using dynamic WEP104 when WPA enabled"""
+ skip_with_fips(dev[0])
+ params = hostapd.radius_params()
+ params["ssid"] = "ieee8021x-wep"
+ params["ieee8021x"] = "1"
+ params["wep_key_len_broadcast"] = "13"
+ params["wep_key_len_unicast"] = "13"
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].connect("ieee8021x-wep", key_mgmt="IEEE8021X WPA-EAP", eap="PSK",
+ identity="psk.user@example.com",
+ password_hex="0123456789abcdef0123456789abcdef",
+ scan_freq="2412")
+ hwsim_utils.test_connectivity(dev[0], hapd)
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import logging
logger = logging.getLogger()
import time
def test_monitor_iface_multi_bss(dev, apdev):
"""AP mode mmonitor interface with hostapd multi-BSS setup"""
params = { "ssid": "monitor-iface", "driver_params": "use_monitor=1" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- hostapd.add_bss('phy3', apdev[0]['ifname'] + '-2', 'bss-2.conf')
+ hapd = hostapd.add_ap(apdev[0], params)
+ hostapd.add_bss(apdev[0], apdev[0]['ifname'] + '-2', 'bss-2.conf')
dev[0].connect("monitor-iface", key_mgmt="NONE", scan_freq="2412")
dev[1].connect("bss-2", key_mgmt="NONE", scan_freq="2412")
+@remote_compatible
def test_monitor_iface_unknown_sta(dev, apdev):
"""AP mode monitor interface and Data frame from unknown STA"""
ssid = "monitor-iface-pmf"
params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
params["ieee80211w"] = "2"
params['driver_params'] = "use_monitor=1"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
addr = dev[0].p2p_interface_addr()
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import time
-import subprocess
import logging
logger = logging.getLogger(__name__)
def test_nfc_p2p_go_neg(dev):
"""NFC connection handover to form a new P2P group (initiator becomes GO)"""
+ try:
+ _test_nfc_p2p_go_neg(dev)
+ finally:
+ dev[0].global_request("SET p2p_go_intent 7")
+
+def _test_nfc_p2p_go_neg(dev):
set_ip_addr_info(dev[0])
- ip = dev[0].request("GET ip_addr_go")
+ ip = dev[0].p2pdev_request("GET ip_addr_go")
if ip != "192.168.42.1":
raise Exception("Unexpected ip_addr_go returned: " + ip)
dev[0].global_request("SET p2p_go_intent 10")
def test_nfc_p2p_go_neg_ip_pool_oom(dev):
"""NFC connection handover to form a new P2P group and IP pool OOM"""
+ try:
+ _test_nfc_p2p_go_neg_ip_pool_oom(dev)
+ finally:
+ dev[0].global_request("SET p2p_go_intent 7")
+
+def _test_nfc_p2p_go_neg_ip_pool_oom(dev):
set_ip_addr_info(dev[0])
- ip = dev[0].request("GET ip_addr_go")
+ ip = dev[0].p2pdev_request("GET ip_addr_go")
if ip != "192.168.42.1":
raise Exception("Unexpected ip_addr_go returned: " + ip)
dev[0].global_request("SET p2p_go_intent 10")
def test_nfc_p2p_go_neg_reverse(dev):
"""NFC connection handover to form a new P2P group (responder becomes GO)"""
+ try:
+ _test_nfc_p2p_go_neg_reverse(dev)
+ finally:
+ dev[0].global_request("SET p2p_go_intent 7")
+
+def _test_nfc_p2p_go_neg_reverse(dev):
set_ip_addr_info(dev[1])
dev[0].global_request("SET p2p_go_intent 3")
logger.info("Perform NFC connection handover")
def test_nfc_p2p_client(dev):
"""NFC connection handover when one device is P2P client"""
logger.info("Start autonomous GOs")
- dev[0].p2p_start_go()
+ go_res = dev[0].p2p_start_go()
logger.info("Connect one device as a P2P client")
pin = dev[1].wps_read_pin()
dev[0].p2p_go_authorize_client(pin)
- dev[1].p2p_connect_group(dev[0].p2p_dev_addr(), pin, timeout=60)
+ dev[1].p2p_connect_group(dev[0].p2p_dev_addr(), pin,
+ freq=int(go_res['freq']), timeout=60)
logger.info("Client connected")
hwsim_utils.test_connectivity_p2p(dev[0], dev[1])
logger.info("Connect to group based on upper layer trigger")
pin = dev[2].wps_read_pin()
dev[0].p2p_go_authorize_client(pin)
- dev[2].p2p_connect_group(dev[0].p2p_dev_addr(), pin, timeout=60)
+ dev[2].p2p_connect_group(dev[0].p2p_dev_addr(), pin,
+ freq=int(go_res['freq']), timeout=60)
logger.info("Client connected")
hwsim_utils.test_connectivity_p2p(dev[0], dev[1])
hwsim_utils.test_connectivity_p2p(dev[1], dev[2])
def test_nfc_p2p_static_handover_tagdev_client(dev):
"""NFC static handover to form a new P2P group (NFC Tag device becomes P2P Client)"""
+ try:
+ _test_nfc_p2p_static_handover_tagdev_client(dev)
+ finally:
+ dev[0].global_request("SET p2p_go_intent 7")
+def _test_nfc_p2p_static_handover_tagdev_client(dev):
set_ip_addr_info(dev[0])
logger.info("Perform NFC connection handover")
def test_nfc_p2p_static_handover_tagdev_client_group_iface(dev):
"""NFC static handover to form a new P2P group (NFC Tag device becomes P2P Client with group iface)"""
+ try:
+ _test_nfc_p2p_static_handover_tagdev_client_group_iface(dev)
+ finally:
+ dev[0].global_request("SET p2p_go_intent 7")
+def _test_nfc_p2p_static_handover_tagdev_client_group_iface(dev):
set_ip_addr_info(dev[0])
logger.info("Perform NFC connection handover")
def test_nfc_p2p_static_handover_tagdev_go(dev):
"""NFC static handover to form a new P2P group (NFC Tag device becomes GO)"""
+ try:
+ _test_nfc_p2p_static_handover_tagdev_go(dev)
+ finally:
+ dev[0].global_request("SET p2p_go_intent 7")
+def _test_nfc_p2p_static_handover_tagdev_go(dev):
set_ip_addr_info(dev[1])
logger.info("Perform NFC connection handover")
def test_nfc_p2p_static_handover_tagdev_go_forced_freq(dev):
"""NFC static handover to form a new P2P group on forced channel (NFC Tag device becomes GO)"""
+ try:
+ _test_nfc_p2p_static_handover_tagdev_go_forced_freq(dev)
+ finally:
+ dev[0].global_request("SET p2p_go_intent 7")
+def _test_nfc_p2p_static_handover_tagdev_go_forced_freq(dev):
set_ip_addr_info(dev[1])
logger.info("Perform NFC connection handover")
def test_nfc_p2p_static_handover_join_tagdev_client(dev):
"""NFC static handover to join a P2P group (NFC Tag device is the P2P Client)"""
+ try:
+ _test_nfc_p2p_static_handover_join_tagdev_client(dev)
+ finally:
+ dev[1].global_request("SET ignore_old_scan_res 0")
+ dev[2].global_request("SET ignore_old_scan_res 0")
+
+def _test_nfc_p2p_static_handover_join_tagdev_client(dev):
set_ip_addr_info(dev[0])
logger.info("Start autonomous GO")
dev[0].p2p_start_go()
def test_nfc_p2p_ip_addr_assignment(dev):
"""NFC connection handover and legacy station IP address assignment"""
+ try:
+ _test_nfc_p2p_ip_addr_assignment(dev)
+ finally:
+ dev[0].global_request("SET p2p_go_intent 7")
+
+def _test_nfc_p2p_ip_addr_assignment(dev):
set_ip_addr_info(dev[1])
dev[0].global_request("SET p2p_go_intent 3")
logger.info("Perform NFC connection handover")
def test_nfc_p2p_ip_addr_assignment2(dev):
"""NFC connection handover and IP address assignment for two clients"""
+ try:
+ _test_nfc_p2p_ip_addr_assignment2(dev)
+ finally:
+ dev[0].global_request("SET p2p_go_intent 7")
+
+def _test_nfc_p2p_ip_addr_assignment2(dev):
set_ip_addr_info(dev[1])
dev[0].global_request("SET p2p_go_intent 3")
logger.info("Perform NFC connection handover")
if res['ip_addr'] == res0['ip_addr']:
raise Exception("Same IP address assigned to both clients")
+@remote_compatible
def test_nfc_p2p_tag_enable_disable(dev):
"""NFC tag enable/disable for P2P"""
if "FAIL" in dev[0].request("WPS_NFC_TOKEN NDEF").rstrip():
if "OK" not in dev[0].request("P2P_SET nfc_tag 0"):
raise Exception("Failed to disable NFC Tag for P2P static handover")
+@remote_compatible
def test_nfc_p2p_static_handover_invalid(dev):
"""NFC static handover with invalid contents"""
logger.info("Unknown OOB GO Neg channel")
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import time
import subprocess
import logging
"wpa_passphrase": "12345678", "wpa": "2",
"wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"}
+@remote_compatible
def test_nfc_wps_password_token_sta(dev, apdev):
"""NFC tag with password token on the station/Enrollee"""
ssid = "test-wps-nfc-pw-token-conf"
params = ap_wps_params(ssid)
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
logger.info("WPS provisioning step using password token from station")
wps = dev[0].request("WPS_NFC_TOKEN WPS").rstrip()
if "FAIL" in wps:
"""NFC tag with configuration token from AP"""
ssid = "test-wps-nfc-conf-token"
params = ap_wps_params(ssid)
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
logger.info("NFC configuration token from AP to station")
conf = hapd.request("WPS_NFC_CONFIG_TOKEN NDEF").rstrip()
if "FAIL" in conf:
def test_nfc_wps_config_token_init(dev, apdev):
"""NFC tag with configuration token from AP with auto configuration"""
ssid = "test-wps-nfc-conf-token-init"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "1" })
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "1" })
logger.info("NFC configuration token from AP to station")
conf = hapd.request("WPS_NFC_CONFIG_TOKEN NDEF").rstrip()
if "FAIL" in conf:
dev[0].wait_connected(timeout=15)
check_wpa2_connection(dev[0], apdev[0], hapd, ssid, mixed=True)
+@remote_compatible
def test_nfc_wps_password_token_sta_init(dev, apdev):
"""Initial AP configuration with first WPS NFC Enrollee"""
ssid = "test-wps-nfc-pw-token-init"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "1" })
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "1" })
logger.info("WPS provisioning step using password token from station")
pw = dev[0].request("WPS_NFC_TOKEN NDEF").rstrip()
if "FAIL" in pw:
dev[0].wait_connected(timeout=30)
check_wpa2_connection(dev[0], apdev[0], hapd, ssid, mixed=True)
+@remote_compatible
def test_nfc_wps_password_token_ap(dev, apdev):
"""WPS registrar configuring an AP using AP password token"""
ssid = "test-wps-nfc-pw-token-init"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "1" })
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "1" })
logger.info("WPS configuration step")
pw = hapd.request("WPS_NFC_TOKEN NDEF").rstrip()
if "FAIL" in pw:
def test_nfc_wps_handover_init(dev, apdev):
"""Connect to WPS AP with NFC connection handover and move to configured state"""
+ try:
+ _test_nfc_wps_handover_init(dev, apdev)
+ finally:
+ dev[0].request("SET ignore_old_scan_res 0")
+
+def _test_nfc_wps_handover_init(dev, apdev):
dev[0].request("SET ignore_old_scan_res 1")
ssid = "test-wps-nfc-handover-init"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "1" })
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "1" })
logger.info("NFC connection handover")
req = dev[0].request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip()
if "FAIL" in req:
if "FAIL" not in hapd.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR"):
raise Exception("Unexpected NFC_GET_HANDOVER_SEL success during OOM")
+@remote_compatible
def test_nfc_wps_handover_errors(dev, apdev):
"""WPS AP NFC handover report error cases"""
ssid = "test-wps-nfc-handover"
- hostapd.add_ap(apdev[0]['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "1" })
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": ssid, "eap_server": "1", "wps_state": "1" })
sel = hapd.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR").rstrip()
if "FAIL" in sel:
raise Exception("Failed to generate NFC connection handover select")
"""Connect to WPS AP with NFC connection handover"""
ssid = "test-wps-nfc-handover"
params = ap_wps_params(ssid)
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
logger.info("NFC connection handover")
req = dev[0].request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip()
if "FAIL" in req:
def test_nfc_wps_handover_5ghz(dev, apdev):
"""Connect to WPS AP with NFC connection handover on 5 GHz band"""
+ hapd = None
try:
ssid = "test-wps-nfc-handover"
params = ap_wps_params(ssid)
params["country_code"] = "FI"
params["hw_mode"] = "a"
params["channel"] = "36"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
logger.info("NFC connection handover")
req = dev[0].request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip()
if "FAIL" in req:
def test_nfc_wps_handover_chan14(dev, apdev):
"""Connect to WPS AP with NFC connection handover on channel 14"""
+ hapd = None
try:
ssid = "test-wps-nfc-handover"
params = ap_wps_params(ssid)
params["country_code"] = "JP"
params["hw_mode"] = "b"
params["channel"] = "14"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
logger.info("NFC connection handover")
req = dev[0].request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip()
if "FAIL" in req:
"""Connect to WPS AP with NFC connection handover (wps_nfc_* set)"""
ssid = "test-wps-nfc-handover2"
params = ap_wps_params(ssid)
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
# enable a password token (which won't be used in this test case)
pw = hapd.request("WPS_NFC_TOKEN NDEF").rstrip()
if "FAIL" in pw:
if "FAIL" in dev[0].request("SET wps_corrupt_pkhash 1"):
raise Exception("Could not enable wps_corrupt_pkhash")
params = ap_wps_params(ssid)
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
logger.info("NFC connection handover")
req = dev[0].request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip()
if "FAIL" in req:
"""WPS NFC connection handover with invalid pkhash from AP (negative)"""
ssid = "wps-nfc-handover-pkhash-ap"
params = ap_wps_params(ssid)
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
if "FAIL" in hapd.request("SET wps_corrupt_pkhash 1"):
raise Exception("Could not enable wps_corrupt_pkhash")
logger.info("NFC connection handover")
def start_ap_er(er, ap, ssid):
ap_pin = "12345670"
ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
- hostapd.add_ap(ap['ifname'],
- { "ssid": ssid, "eap_server": "1", "wps_state": "2",
- "wpa_passphrase": "12345678", "wpa": "2",
- "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
- "device_name": "Wireless AP", "manufacturer": "Company",
- "model_name": "WAP", "model_number": "123",
- "serial_number": "12345", "device_type": "6-0050F204-1",
- "os_version": "01020300",
- "config_methods": "label push_button",
- "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"})
+ params = { "ssid": ssid, "eap_server": "1", "wps_state": "2",
+ "wpa_passphrase": "12345678", "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
+ "device_name": "Wireless AP", "manufacturer": "Company",
+ "model_name": "WAP", "model_number": "123",
+ "serial_number": "12345", "device_type": "6-0050F204-1",
+ "os_version": "01020300",
+ "config_methods": "label push_button",
+ "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"}
+ hapd = hostapd.add_ap(ap, params)
logger.info("Learn AP configuration")
er.dump_monitor()
- er.request("SET ignore_old_scan_res 1")
- er.wps_reg(ap['bssid'], ap_pin)
+ try:
+ er.request("SET ignore_old_scan_res 1")
+ er.wps_reg(ap['bssid'], ap_pin)
+ finally:
+ er.request("SET ignore_old_scan_res 0")
logger.info("Start ER")
er.request("WPS_ER_STOP")
logger.info("Use learned network configuration on ER")
er.request("WPS_ER_SET_CONFIG " + ap_uuid + " 0")
+ return hapd
+@remote_compatible
def test_nfc_wps_er_pw_token(dev, apdev):
"""WPS NFC password token from Enrollee to ER"""
try:
_test_nfc_wps_er_pw_token(dev, apdev)
finally:
dev[0].request("WPS_ER_STOP")
+ dev[1].request("SET ignore_old_scan_res 0")
def _test_nfc_wps_er_pw_token(dev, apdev):
ssid = "wps-nfc-er-pw-token"
- start_ap_er(dev[0], apdev[0], ssid)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = start_ap_er(dev[0], apdev[0], ssid)
logger.info("WPS provisioning step using password token from station")
dev[1].request("SET ignore_old_scan_res 1")
pw = dev[1].request("WPS_NFC_TOKEN NDEF").rstrip()
dev[1].wait_connected(timeout=15)
check_wpa2_connection(dev[1], apdev[0], hapd, ssid)
+@remote_compatible
def test_nfc_wps_er_config_token(dev, apdev):
"""WPS NFC configuration token from ER to Enrollee"""
try:
_test_nfc_wps_er_config_token(dev, apdev)
finally:
dev[0].request("WPS_ER_STOP")
+ dev[1].request("SET ignore_old_scan_res 0")
def _test_nfc_wps_er_config_token(dev, apdev):
ssid = "wps-nfc-er-config-token"
- start_ap_er(dev[0], apdev[0], ssid)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = start_ap_er(dev[0], apdev[0], ssid)
logger.info("WPS provisioning step using configuration token from ER")
wps = dev[0].request("WPS_ER_NFC_CONFIG_TOKEN WPS " + apdev[0]['bssid']).rstrip()
if "FAIL" in wps:
def _test_nfc_wps_er_handover(dev, apdev):
ssid = "wps-nfc-er-handover"
- start_ap_er(dev[0], apdev[0], ssid)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = start_ap_er(dev[0], apdev[0], ssid)
logger.info("WPS provisioning step using connection handover")
req = dev[1].request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip()
if "FAIL" in req:
_test_nfc_wps_er_handover_pk_hash_mismatch_sta(dev, apdev)
finally:
dev[0].request("WPS_ER_STOP")
+ dev[1].request("SET ignore_old_scan_res 0")
def _test_nfc_wps_er_handover_pk_hash_mismatch_sta(dev, apdev):
ssid = "wps-nfc-er-handover-pkhash-sta"
- start_ap_er(dev[0], apdev[0], ssid)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = start_ap_er(dev[0], apdev[0], ssid)
logger.info("WPS provisioning step using connection handover")
if "FAIL" in dev[1].request("SET wps_corrupt_pkhash 1"):
raise Exception("Could not enable wps_corrupt_pkhash")
_test_nfc_wps_er_handover_pk_hash_mismatch_er(dev, apdev)
finally:
dev[0].request("WPS_ER_STOP")
+ dev[1].request("SET ignore_old_scan_res 0")
def _test_nfc_wps_er_handover_pk_hash_mismatch_er(dev, apdev):
ssid = "wps-nfc-er-handover-pkhash-er"
- start_ap_er(dev[0], apdev[0], ssid)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = start_ap_er(dev[0], apdev[0], ssid)
logger.info("WPS provisioning step using connection handover")
if "FAIL" in dev[0].request("SET wps_corrupt_pkhash 1"):
raise Exception("Could not enable wps_corrupt_pkhash")
if "WPS-FAIL" not in ev:
raise Exception("Public key hash mismatch not detected")
+@remote_compatible
def test_nfc_invalid_ndef_record(dev, apdev):
"""Invalid NFC NDEF record handling"""
tests = [ "11223344",
from wpasupplicant import WpaSupplicant
from test_gas import start_ap
from test_gas import anqp_get
-from test_p2p_grpform import go_neg_pin_authorized
-from test_p2p_grpform import check_grpform_results
-from test_p2p_grpform import remove_group
+from p2p_utils import *
def test_offchannel_tx_roc_gas(dev, apdev):
"""GAS using cfg80211 remain-on-channel for offchannel TX"""
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import time
import subprocess
import logging
from utils import HwsimSkip
from wlantest import Wlantest
from wpasupplicant import WpaSupplicant
-
-def autogo(go, freq=None, persistent=None):
- logger.info("Start autonomous GO " + go.ifname)
- res = go.p2p_start_go(freq=freq, persistent=persistent)
- logger.debug("res: " + str(res))
- return res
-
-def connect_cli(go, client, social=False, freq=None):
- logger.info("Try to connect the client to the GO")
- pin = client.wps_read_pin()
- go.p2p_go_authorize_client(pin)
- res = client.p2p_connect_group(go.p2p_dev_addr(), pin, timeout=60,
- social=social, freq=freq)
- logger.info("Client connected")
- hwsim_utils.test_connectivity_p2p(go, client)
- return res
+from p2p_utils import *
+from test_p2p_messages import mgmt_tx, parse_p2p_public_action
def test_autogo(dev):
"""P2P autonomous GO and client joining group"""
def test_autogo2(dev):
"""P2P autonomous GO with a separate group interface and client joining group"""
- dev[0].request("SET p2p_no_group_iface 0")
+ dev[0].global_request("SET p2p_no_group_iface 0")
res = autogo(dev[0], freq=2437)
if "p2p-wlan" not in res['ifname']:
raise Exception("Unexpected group interface name on GO")
def test_autogo3(dev):
"""P2P autonomous GO and client with a separate group interface joining group"""
- dev[1].request("SET p2p_no_group_iface 0")
+ dev[1].global_request("SET p2p_no_group_iface 0")
autogo(dev[0], freq=2462)
res = connect_cli(dev[0], dev[1], social=True, freq=2462)
if "p2p-wlan" not in res['ifname']:
def test_autogo4(dev):
"""P2P autonomous GO and client joining group (both with a separate group interface)"""
- dev[0].request("SET p2p_no_group_iface 0")
- dev[1].request("SET p2p_no_group_iface 0")
+ dev[0].global_request("SET p2p_no_group_iface 0")
+ dev[1].global_request("SET p2p_no_group_iface 0")
res1 = autogo(dev[0], freq=2412)
res2 = connect_cli(dev[0], dev[1], social=True, freq=2412)
if "p2p-wlan" not in res1['ifname']:
if ev is None:
raise Exception("No M2D event on group interface (2)")
+@remote_compatible
def test_autogo_fail(dev):
"""P2P autonomous GO and incorrect PIN"""
autogo(dev[0], freq=2412)
go_addr = dev[0].p2p_dev_addr()
dev[0].p2p_go_authorize_client("00000000")
- dev[1].request("SET p2p_no_group_iface 0")
+ dev[1].global_request("SET p2p_no_group_iface 0")
if not dev[1].discover_peer(go_addr, social=True):
raise Exception("GO " + go_addr + " not found")
dev[1].dump_monitor()
def test_autogo_tdls(dev):
"""P2P autonomous GO and two clients using TDLS"""
- wt = Wlantest()
go = dev[0]
logger.info("Start autonomous GO with fixed parameters " + go.ifname)
id = go.add_network()
go.set_network(id, "disabled", "2")
res = go.p2p_start_go(persistent=id, freq="2462")
logger.debug("res: " + str(res))
+ Wlantest.setup(go, True)
+ wt = Wlantest()
wt.flush()
wt.add_passphrase("12345678")
connect_cli(go, dev[1], social=True, freq=2462)
dev[1].tdls_setup(addr2)
time.sleep(1)
hwsim_utils.test_connectivity_p2p(dev[1], dev[2])
- conf = wt.get_tdls_counter("setup_conf_ok", bssid, addr1, addr2);
+ conf = wt.get_tdls_counter("setup_conf_ok", bssid, addr1, addr2)
if conf == 0:
raise Exception("No TDLS Setup Confirm (success) seen")
- dl = wt.get_tdls_counter("valid_direct_link", bssid, addr1, addr2);
+ dl = wt.get_tdls_counter("valid_direct_link", bssid, addr1, addr2)
if dl == 0:
raise Exception("No valid frames through direct link")
- wt.tdls_clear(bssid, addr1, addr2);
+ wt.tdls_clear(bssid, addr1, addr2)
dev[1].tdls_teardown(addr2)
time.sleep(1)
- teardown = wt.get_tdls_counter("teardown", bssid, addr1, addr2);
+ teardown = wt.get_tdls_counter("teardown", bssid, addr1, addr2)
if teardown == 0:
raise Exception("No TDLS Setup Teardown seen")
- wt.tdls_clear(bssid, addr1, addr2);
+ wt.tdls_clear(bssid, addr1, addr2)
hwsim_utils.test_connectivity_p2p(dev[1], dev[2])
- ap_path = wt.get_tdls_counter("valid_ap_path", bssid, addr1, addr2);
+ ap_path = wt.get_tdls_counter("valid_ap_path", bssid, addr1, addr2)
if ap_path == 0:
raise Exception("No valid frames via AP path")
- direct_link = wt.get_tdls_counter("valid_direct_link", bssid, addr1, addr2);
+ direct_link = wt.get_tdls_counter("valid_direct_link", bssid, addr1, addr2)
if direct_link > 0:
raise Exception("Unexpected frames through direct link")
idirect_link = wt.get_tdls_counter("invalid_direct_link", bssid, addr1,
- addr2);
+ addr2)
if idirect_link > 0:
raise Exception("Unexpected frames through direct link (invalid)")
dev[2].remove_group()
time.sleep(0.1)
hwsim_utils.test_connectivity_p2p(dev[0], dev[1])
+@remote_compatible
def test_autogo_extra_cred(dev):
"""P2P autonomous GO sending two WPS credentials"""
if "FAIL" in dev[0].request("SET wps_testing_dummy_cred 1"):
if res['ifname'] not in ev:
raise Exception("Unexpected group removal event: " + ev)
+@remote_compatible
def test_autogo_start_during_scan(dev):
"""P2P autonomous GO started during ongoing manual scan"""
try:
finally:
dev[0].request("SET p2p_passphrase_len 8")
+@remote_compatible
def test_autogo_bridge(dev):
"""P2P autonomous GO in a bridge"""
try:
raise Exception("Failed to set autoscan")
autogo(dev[0])
ifname = dev[0].get_group_ifname()
- subprocess.call(['brctl', 'addbr', 'p2p-br0'])
- subprocess.call(['brctl', 'setfd', 'p2p-br0', '0'])
- subprocess.call(['brctl', 'addif', 'p2p-br0', ifname])
- subprocess.call(['ip', 'link', 'set', 'dev', 'p2p-br0', 'up'])
+ dev[0].cmd_execute(['brctl', 'addbr', 'p2p-br0'])
+ dev[0].cmd_execute(['brctl', 'setfd', 'p2p-br0', '0'])
+ dev[0].cmd_execute(['brctl', 'addif', 'p2p-br0', ifname])
+ dev[0].cmd_execute(['ip', 'link', 'set', 'dev', 'p2p-br0', 'up'])
time.sleep(0.1)
- subprocess.call(['brctl', 'delif', 'p2p-br0', ifname])
+ dev[0].cmd_execute(['brctl', 'delif', 'p2p-br0', ifname])
time.sleep(0.1)
- subprocess.call(['ip', 'link', 'set', 'dev', 'p2p-br0', 'down'])
+ dev[0].cmd_execute(['ip', 'link', 'set', 'dev', 'p2p-br0', 'down'])
time.sleep(0.1)
- subprocess.call(['brctl', 'delbr', 'p2p-br0'])
+ dev[0].cmd_execute(['brctl', 'delbr', 'p2p-br0'])
ev = dev[0].wait_global_event(["P2P-GROUP-REMOVED"], timeout=1)
if ev is not None:
raise Exception("P2P group removed unexpectedly")
dev[0].remove_group()
finally:
dev[0].request("AUTOSCAN ")
- subprocess.Popen(['brctl', 'delif', 'p2p-br0', ifname],
- stderr=open('/dev/null', 'w'))
- subprocess.Popen(['ip', 'link', 'set', 'dev', 'p2p-br0', 'down'],
- stderr=open('/dev/null', 'w'))
- subprocess.Popen(['brctl', 'delbr', 'p2p-br0'],
- stderr=open('/dev/null', 'w'))
-
+ dev[0].cmd_execute(['brctl', 'delif', 'p2p-br0', ifname,
+ '2>', '/dev/null'], shell=True)
+ dev[0].cmd_execute(['ip', 'link', 'set', 'dev', 'p2p-br0', 'down',
+ '2>', '/dev/null'], shell=True)
+ dev[0].cmd_execute(['brctl', 'delbr', 'p2p-br0', '2>', '/dev/null'],
+ shell=True)
+
+@remote_compatible
def test_presence_req_on_group_interface(dev):
"""P2P_PRESENCE_REQ on group interface"""
- dev[1].request("SET p2p_no_group_iface 0")
+ dev[1].global_request("SET p2p_no_group_iface 0")
res = autogo(dev[0], freq=2437)
res = connect_cli(dev[0], dev[1], social=True, freq=2437)
if "FAIL" in dev[1].group_request("P2P_PRESENCE_REQ 30000 102400"):
autogo(wpas, freq=2412)
addr = wpas.p2p_dev_addr()
bssid = wpas.p2p_interface_addr()
+ wpas.dump_monitor()
dev[1].global_request("SET p2p_no_group_iface 0")
dev[1].scan_for_bss(bssid, freq=2412)
# exchange.
if "OK" not in wpas.group_request("STOP_AP"):
raise Exception("STOP_AP failed")
+ wpas.dump_monitor()
wpas.group_request("SET ext_mgmt_frame_handling 1")
wpas.p2p_listen()
+ wpas.dump_monitor()
time.sleep(0.02)
dev[1].global_request("P2P_CONNECT " + addr + " pbc auto")
ev = dev[1].wait_global_event(["P2P-FALLBACK-TO-GO-NEG-ENABLED"], 15)
+ wpas.dump_monitor()
if ev is None:
raise Exception("Could not trigger old-scan-only case")
return
raise Exception("Fallback to GO Negotiation not seen")
if "reason=GO-not-found" not in ev:
raise Exception("Unexpected reason for fallback: " + ev)
+ wpas.dump_monitor()
def test_autogo_join_auto(dev):
"""P2P_CONNECT-auto joining a group"""
dev[1].wait_go_ending_session()
dev[1].flush_scan_cache()
+@remote_compatible
def test_autogo_join_auto_go_neg(dev):
"""P2P_CONNECT-auto fallback to GO Neg"""
dev[1].flush_scan_cache()
dev[0].p2p_listen()
addr = dev[0].p2p_dev_addr()
+ if not dev[1].discover_peer(addr, social=True):
+ raise Exception("Peer not found")
+ dev[1].p2p_stop_find()
if "OK" not in dev[1].global_request("P2P_CONNECT " + addr + " pbc auto"):
raise Exception("P2P_CONNECT failed")
dev[1].wait_go_ending_session()
dev[1].flush_scan_cache()
+@remote_compatible
def test_autogo_join_auto_go_neg_after_seeing_go(dev):
"""P2P_CONNECT-auto fallback to GO Neg after seeing GO"""
autogo(dev[0], freq=2412)
def test_autogo_many(dev):
"""P2P autonomous GO with large number of GO instances"""
- dev[0].request("SET p2p_no_group_iface 0")
+ dev[0].global_request("SET p2p_no_group_iface 0")
for i in range(100):
if "OK" not in dev[0].global_request("P2P_GROUP_ADD freq=2412"):
logger.info("Was able to add %d groups" % i)
for i in [ name0, name2, name3 ]:
if i not in ev1 and i not in ev2 and i not in ev3:
raise Exception('name "%s" not found' % i)
+
+def rx_pd_req(dev):
+ msg = dev.mgmt_rx()
+ if msg is None:
+ raise Exception("MGMT-RX timeout")
+ p2p = parse_p2p_public_action(msg['payload'])
+ if p2p is None:
+ raise Exception("Not a P2P Public Action frame " + str(dialog_token))
+ if p2p['subtype'] != P2P_PROV_DISC_REQ:
+ raise Exception("Unexpected subtype %d" % p2p['subtype'])
+ p2p['freq'] = msg['freq']
+ return p2p
+
+@remote_compatible
+def test_autogo_scan(dev):
+ """P2P autonomous GO and no P2P IE in Probe Response scan results"""
+ addr0 = dev[0].p2p_dev_addr()
+ addr1 = dev[1].p2p_dev_addr()
+ dev[0].p2p_start_go(freq=2412, persistent=True)
+ bssid = dev[0].p2p_interface_addr()
+
+ dev[1].discover_peer(addr0)
+ dev[1].p2p_stop_find()
+ ev = dev[1].wait_global_event(["P2P-FIND-STOPPED"], timeout=2)
+ time.sleep(0.1)
+ dev[1].flush_scan_cache()
+
+ pin = dev[1].wps_read_pin()
+ dev[0].group_request("WPS_PIN any " + pin)
+
+ try:
+ dev[1].request("SET p2p_disabled 1")
+ dev[1].request("SCAN freq=2412")
+ ev = dev[1].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
+ if ev is None:
+ raise Exception("Active scan did not complete")
+ finally:
+ dev[1].request("SET p2p_disabled 0")
+
+ for i in range(2):
+ dev[1].request("SCAN freq=2412 passive=1")
+ ev = dev[1].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
+ if ev is None:
+ raise Exception("Scan did not complete")
+
+ # Disable management frame processing for a moment to skip Probe Response
+ # frame with P2P IE.
+ dev[0].group_request("SET ext_mgmt_frame_handling 1")
+
+ dev[1].global_request("P2P_CONNECT " + bssid + " " + pin + " freq=2412 join")
+
+ # Skip the first Probe Request frame
+ ev = dev[0].wait_group_event(["MGMT-RX"], timeout=10)
+ if ev is None:
+ raise Exception("No Probe Request frame seen")
+ if not ev.split(' ')[4].startswith("40"):
+ raise Exception("Not a Probe Request frame")
+
+ # If a P2P Device is not used, the PD Request will be received on the group
+ # interface (which is actually wlan0, since a separate interface is not
+ # used), which was set to external management frame handling, so need to
+ # reply to it manually.
+ res = dev[0].get_driver_status()
+ if not (int(res['capa.flags'], 0) & 0x20000000):
+ # Reply to PD Request while still filtering Probe Request frames
+ msg = rx_pd_req(dev[0])
+ mgmt_tx(dev[0], "MGMT_TX {} {} freq={} wait_time=10 no_cck=1 action={}".format(addr1, addr0, 2412, "0409506f9a0908%02xdd0a0050f204100800020008" % msg['dialog_token']))
+
+ # Skip Probe Request frames until something else is received
+ for i in range(10):
+ ev = dev[0].wait_group_event(["MGMT-RX"], timeout=10)
+ if ev is None:
+ raise Exception("No frame seen")
+ if not ev.split(' ')[4].startswith("40"):
+ break
+
+ # Allow wpa_supplicant to process authentication and association
+ dev[0].group_request("SET ext_mgmt_frame_handling 0")
+
+ # Joining the group should succeed and indicate persistent group based on
+ # Beacon frame P2P IE.
+ ev = dev[1].wait_global_event(["P2P-GROUP-STARTED"], timeout=10)
+ if ev is None:
+ raise Exception("Failed to join group")
+ if "[PERSISTENT]" not in ev:
+ raise Exception("Did not recognize group as persistent")
+ dev[0].remove_group()
+ dev[1].wait_go_ending_session()
+
+@remote_compatible
+def test_autogo_join_before_found(dev):
+ """P2P client joining a group before having found GO Device Address"""
+ dev[0].global_request("SET p2p_no_group_iface 0")
+ res = autogo(dev[0], freq=2412)
+ if "p2p-wlan" not in res['ifname']:
+ raise Exception("Unexpected group interface name on GO")
+ status = dev[0].get_group_status()
+ bssid = status['bssid']
+
+ pin = dev[1].wps_read_pin()
+ dev[0].p2p_go_authorize_client(pin)
+ cmd = "P2P_CONNECT " + bssid + " " + pin + " join freq=2412"
+ if "OK" not in dev[1].global_request(cmd):
+ raise Exception("P2P_CONNECT join failed")
+ ev = dev[1].wait_global_event(["P2P-GROUP-STARTED"], timeout=15)
+ if ev is None:
+ raise Exception("Joining the group timed out")
+ dev[0].remove_group()
+ dev[1].wait_go_ending_session()
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import logging
logger = logging.getLogger()
import os
import hostapd
import hwsim_utils
-from utils import HwsimSkip
from tshark import run_tshark
from wpasupplicant import WpaSupplicant
from hwsim import HWSimRadio
-from test_p2p_grpform import go_neg_pin_authorized
-from test_p2p_grpform import check_grpform_results
-from test_p2p_grpform import remove_group
-from test_p2p_grpform import go_neg_pbc
-from test_p2p_autogo import autogo
+from p2p_utils import *
def set_country(country, dev=None):
subprocess.call(['iw', 'reg', 'set', country])
"""P2P group formation with 5 GHz preference when VHT channels are disallowed"""
try:
set_country("US", dev[0])
- dev[0].request("P2P_SET disallow_freq 5180-5240")
+ dev[0].global_request("P2P_SET disallow_freq 5180-5240")
[i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=15,
r_dev=dev[1], r_intent=0,
test_data=False)
remove_group(dev[0], dev[1])
finally:
set_country("00")
- dev[0].request("P2P_SET disallow_freq ")
+ dev[0].global_request("P2P_SET disallow_freq ")
dev[1].flush_scan_cache()
def test_p2p_channel_random_social(dev):
"""P2P group formation with 5 GHz preference but all 5 GHz channels disabled"""
try:
set_country("US", dev[0])
- dev[0].request("SET p2p_oper_channel 11")
- dev[0].request("P2P_SET disallow_freq 5000-6000,2462")
+ dev[0].global_request("SET p2p_oper_channel 11")
+ dev[0].global_request("P2P_SET disallow_freq 5000-6000,2462")
[i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=15,
r_dev=dev[1], r_intent=0,
test_data=False)
remove_group(dev[0], dev[1])
finally:
set_country("00")
- dev[0].request("P2P_SET disallow_freq ")
+ dev[0].global_request("P2P_SET disallow_freq ")
dev[1].flush_scan_cache()
def test_p2p_channel_random(dev):
"""P2P group formation with 5 GHz preference but all 5 GHz channels and all social channels disabled"""
try:
set_country("US", dev[0])
- dev[0].request("SET p2p_oper_channel 11")
- dev[0].request("P2P_SET disallow_freq 5000-6000,2412,2437,2462")
+ dev[0].global_request("SET p2p_oper_channel 11")
+ dev[0].global_request("P2P_SET disallow_freq 5000-6000,2412,2437,2462")
[i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=15,
r_dev=dev[1], r_intent=0,
test_data=False)
remove_group(dev[0], dev[1])
finally:
set_country("00")
- dev[0].request("P2P_SET disallow_freq ")
+ dev[0].global_request("P2P_SET disallow_freq ")
dev[1].flush_scan_cache()
def test_p2p_channel_random_social_with_op_class_change(dev, apdev, params):
remove_group(dev[0], dev[1])
logger.info("Disable 5 GHz and try to re-start group based on 5 GHz preference")
- dev[0].request("SET p2p_oper_reg_class 115")
- dev[0].request("SET p2p_oper_channel 36")
- dev[0].request("P2P_SET disallow_freq 5000-6000")
+ dev[0].global_request("SET p2p_oper_reg_class 115")
+ dev[0].global_request("SET p2p_oper_channel 36")
+ dev[0].global_request("P2P_SET disallow_freq 5000-6000")
[i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=15,
r_dev=dev[1], r_intent=0,
test_data=False)
raise Exception("Unexpected operating class: " + last.strip())
finally:
set_country("00")
- dev[0].request("P2P_SET disallow_freq ")
- dev[0].request("SET p2p_oper_reg_class 0")
- dev[0].request("SET p2p_oper_channel 0")
+ dev[0].global_request("P2P_SET disallow_freq ")
+ dev[0].global_request("SET p2p_oper_reg_class 0")
+ dev[0].global_request("SET p2p_oper_channel 0")
dev[1].flush_scan_cache()
def test_p2p_channel_avoid(dev):
ev = dev[0].wait_event(["CTRL-EVENT-AVOID-FREQ"], timeout=10)
if ev is None:
raise Exception("No CTRL-EVENT-AVOID-FREQ event")
- ev = dev[0].wait_group_event(["P2P-REMOVE-AND-REFORM-GROUP"], timeout=1)
+ ev = dev[0].wait_group_event(["P2P-REMOVE-AND-REFORM-GROUP",
+ "AP-CSA-FINISHED"], timeout=1)
if ev is not None:
- raise Exception("Unexpected P2P-REMOVE-AND-REFORM-GROUP event")
+ raise Exception("Unexpected + " + ev + " event")
if "OK" not in dev[0].request("DRIVER_EVENT AVOID_FREQUENCIES " + str(freq)):
raise Exception("Could not simulate driver event(3)")
ev = dev[0].wait_event(["CTRL-EVENT-AVOID-FREQ"], timeout=10)
if ev is None:
raise Exception("No CTRL-EVENT-AVOID-FREQ event")
- ev = dev[0].wait_group_event(["P2P-REMOVE-AND-REFORM-GROUP"],
+ ev = dev[0].wait_group_event(["P2P-REMOVE-AND-REFORM-GROUP",
+ "AP-CSA-FINISHED"],
timeout=10)
if ev is None:
- raise Exception("No P2P-REMOVE-AND-REFORM-GROUP event")
+ raise Exception("No P2P-REMOVE-AND-REFORM-GROUP or AP-CSA-FINISHED event")
finally:
set_country("00")
dev[0].request("DRIVER_EVENT AVOID_FREQUENCIES")
dev[1].flush_scan_cache()
+@remote_compatible
def test_autogo_following_bss(dev, apdev):
"""P2P autonomous GO operate on the same channel as station interface"""
if dev[0].get_mcc() > 1:
logger.info("test mode: MCC")
- dev[0].request("SET p2p_no_group_iface 0")
+ dev[0].global_request("SET p2p_no_group_iface 0")
channels = { 3 : "2422", 5 : "2432", 9 : "2452" }
for key in channels:
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid" : 'ap-test',
- "channel" : str(key) })
+ hapd = hostapd.add_ap(apdev[0], { "ssid" : 'ap-test',
+ "channel" : str(key) })
dev[0].connect("ap-test", key_mgmt="NONE",
scan_freq=str(channels[key]))
res_go = autogo(dev[0])
hwsim_utils.test_connectivity(dev[0], hapd)
dev[0].remove_group(res_go['ifname'])
+@remote_compatible
def test_go_neg_with_bss_connected(dev, apdev):
"""P2P channel selection: GO negotiation when station interface is connected"""
dev[0].flush_scan_cache()
dev[1].flush_scan_cache()
- dev[0].request("SET p2p_no_group_iface 0")
+ dev[0].global_request("SET p2p_no_group_iface 0")
- hapd = hostapd.add_ap(apdev[0]['ifname'],
+ hapd = hostapd.add_ap(apdev[0],
{ "ssid": 'bss-2.4ghz', "channel": '5' })
dev[0].connect("bss-2.4ghz", key_mgmt="NONE", scan_freq="2432")
#dev[0] as GO
if dev[0].get_mcc() > 1:
logger.info("Skip as-client case due to MCC being enabled")
- return;
+ return
#dev[0] as client
[i_res2, r_res2] = go_neg_pbc(i_dev=dev[0], i_intent=1, r_dev=dev[1],
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add(iface)
- wpas.request("SET p2p_no_group_iface 0")
+ wpas.global_request("SET p2p_no_group_iface 0")
if wpas.get_mcc() < 2:
raise Exception("New radio does not support MCC")
try:
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": 'bss-2.4ghz',
- "channel": '1' })
- wpas.request("P2P_SET disallow_freq 2412")
+ hapd = hostapd.add_ap(apdev[0], { "ssid": 'bss-2.4ghz',
+ "channel": '1' })
+ wpas.global_request("P2P_SET disallow_freq 2412")
wpas.connect("bss-2.4ghz", key_mgmt="NONE", scan_freq="2412")
res = autogo(wpas)
if res['freq'] == "2412":
raise Exception("GO set on a disallowed channel")
hwsim_utils.test_connectivity(wpas, hapd)
finally:
- wpas.request("P2P_SET disallow_freq ")
+ wpas.global_request("P2P_SET disallow_freq ")
def test_go_neg_with_bss_on_disallowed_chan(dev, apdev):
"""P2P channel selection: GO negotiation with station interface on a disallowed channel"""
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add(iface)
- wpas.request("SET p2p_no_group_iface 0")
+ wpas.global_request("SET p2p_no_group_iface 0")
if wpas.get_mcc() < 2:
raise Exception("New radio does not support MCC")
try:
- hapd = hostapd.add_ap(apdev[0]['ifname'],
+ hapd = hostapd.add_ap(apdev[0],
{ "ssid": 'bss-2.4ghz', "channel": '1' })
# make sure PBC overlap from old test cases is not maintained
dev[1].flush_scan_cache()
wpas.connect("bss-2.4ghz", key_mgmt="NONE", scan_freq="2412")
- wpas.request("P2P_SET disallow_freq 2412")
+ wpas.global_request("P2P_SET disallow_freq 2412")
#wpas as GO
[i_res, r_res] = go_neg_pbc(i_dev=wpas, i_intent=10, r_dev=dev[1],
wpas.request("DISCONNECT")
hapd.disable()
finally:
- wpas.request("P2P_SET disallow_freq ")
+ wpas.global_request("P2P_SET disallow_freq ")
def test_autogo_force_diff_channel(dev, apdev):
"""P2P autonomous GO and station interface operate on different channels"""
if wpas.get_mcc() < 2:
raise Exception("New radio does not support MCC")
- wpas.request("SET p2p_no_group_iface 0")
+ wpas.global_request("SET p2p_no_group_iface 0")
- hapd = hostapd.add_ap(apdev[0]['ifname'],
+ hapd = hostapd.add_ap(apdev[0],
{"ssid" : 'ap-test', "channel" : '1'})
wpas.connect("ap-test", key_mgmt = "NONE", scan_freq = "2412")
+ wpas.dump_monitor()
channels = { 2 : 2417, 5 : 2432, 9 : 2452 }
for key in channels:
res_go = autogo(wpas, channels[key])
+ wpas.dump_monitor()
hwsim_utils.test_connectivity(wpas, hapd)
if int(res_go['freq']) == 2412:
raise Exception("Group operation channel is: 2412 excepted: " + res_go['freq'])
wpas.remove_group(res_go['ifname'])
+ wpas.dump_monitor()
def test_go_neg_forced_freq_diff_than_bss_freq(dev, apdev):
"""P2P channel selection: GO negotiation with forced freq different than station interface"""
# Clear possible PBC session overlap from previous test case
dev[1].flush_scan_cache()
- wpas.request("SET p2p_no_group_iface 0")
+ wpas.global_request("SET p2p_no_group_iface 0")
- hapd = hostapd.add_ap(apdev[0]['ifname'],
+ hapd = hostapd.add_ap(apdev[0],
{ "country_code": 'US',
"ssid": 'bss-5ghz', "hw_mode": 'a',
"channel": '40' })
subprocess.call(['iw', 'reg', 'set', '00'])
wpas.flush_scan_cache()
+@remote_compatible
def test_go_pref_chan_bss_on_diff_chan(dev, apdev):
"""P2P channel selection: Station on different channel than GO configured pref channel"""
- dev[0].request("SET p2p_no_group_iface 0")
+ dev[0].global_request("SET p2p_no_group_iface 0")
try:
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": 'bss-2.4ghz',
- "channel": '1' })
- dev[0].request("SET p2p_pref_chan 81:2")
+ hapd = hostapd.add_ap(apdev[0], { "ssid": 'bss-2.4ghz',
+ "channel": '1' })
+ dev[0].global_request("SET p2p_pref_chan 81:2")
dev[0].connect("bss-2.4ghz", key_mgmt="NONE", scan_freq="2412")
res = autogo(dev[0])
if res['freq'] != "2412":
raise Exception("GO channel did not follow BSS")
hwsim_utils.test_connectivity(dev[0], hapd)
finally:
- dev[0].request("SET p2p_pref_chan ")
+ dev[0].global_request("SET p2p_pref_chan ")
def test_go_pref_chan_bss_on_disallowed_chan(dev, apdev):
"""P2P channel selection: Station interface on different channel than GO configured pref channel, and station channel is disallowed"""
if wpas.get_mcc() < 2:
raise Exception("New radio does not support MCC")
- wpas.request("SET p2p_no_group_iface 0")
+ wpas.global_request("SET p2p_no_group_iface 0")
try:
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": 'bss-2.4ghz',
- "channel": '1' })
- wpas.request("P2P_SET disallow_freq 2412")
- wpas.request("SET p2p_pref_chan 81:2")
+ hapd = hostapd.add_ap(apdev[0], { "ssid": 'bss-2.4ghz',
+ "channel": '1' })
+ wpas.global_request("P2P_SET disallow_freq 2412")
+ wpas.global_request("SET p2p_pref_chan 81:2")
wpas.connect("bss-2.4ghz", key_mgmt="NONE", scan_freq="2412")
res2 = autogo(wpas)
if res2['freq'] != "2417":
raise Exception("GO channel did not follow pref_chan configuration")
hwsim_utils.test_connectivity(wpas, hapd)
finally:
- wpas.request("P2P_SET disallow_freq ")
- wpas.request("SET p2p_pref_chan ")
+ wpas.global_request("P2P_SET disallow_freq ")
+ wpas.global_request("SET p2p_pref_chan ")
+@remote_compatible
def test_no_go_freq(dev, apdev):
"""P2P channel selection: no GO freq"""
try:
- dev[0].request("SET p2p_no_go_freq 2412")
+ dev[0].global_request("SET p2p_no_go_freq 2412")
# dev[0] as client, channel 1 is ok
[i_res, r_res] = go_neg_pbc(i_dev=dev[0], i_intent=1,
r_dev=dev[1], r_intent=14, r_freq=2412)
fail = False
# dev[0] as GO, channel 1 is not allowed
try:
- dev[0].request("SET p2p_no_go_freq 2412")
+ dev[0].global_request("SET p2p_no_go_freq 2412")
[i_res2, r_res2] = go_neg_pbc(i_dev=dev[0], i_intent=14,
r_dev=dev[1], r_intent=1, r_freq=2412)
check_grpform_results(i_res2, r_res2)
if fail:
raise Exception("GO set on a disallowed freq")
finally:
- dev[0].request("SET p2p_no_go_freq ")
+ dev[0].global_request("SET p2p_no_go_freq ")
+@remote_compatible
def test_go_neg_peers_force_diff_freq(dev, apdev):
"""P2P channel selection when peers for different frequency"""
try:
return
raise Exception("Unexpected group formation success")
+@remote_compatible
def test_autogo_random_channel(dev, apdev):
"""P2P channel selection: GO instantiated on random channel 1, 6, 11"""
freqs = []
if i == 20:
raise Exception("GO created 20 times and not all social channels were selected. freqs not selected: " + str(list(set(go_freqs) - set(freqs))))
+@remote_compatible
def test_p2p_autogo_pref_chan_disallowed(dev, apdev):
"""P2P channel selection: GO preferred channels are disallowed"""
try:
- dev[0].request("SET p2p_pref_chan 81:1,81:3,81:6,81:9,81:11")
- dev[0].request("P2P_SET disallow_freq 2412,2422,2437,2452,2462")
+ dev[0].global_request("SET p2p_pref_chan 81:1,81:3,81:6,81:9,81:11")
+ dev[0].global_request("P2P_SET disallow_freq 2412,2422,2437,2452,2462")
for i in range(0, 5):
res = autogo(dev[0])
if res['freq'] in [ "2412", "2422", "2437", "2452", "2462" ]:
raise Exception("GO channel is disallowed")
dev[0].remove_group(res['ifname'])
finally:
- dev[0].request("P2P_SET disallow_freq ")
- dev[0].request("SET p2p_pref_chan ")
+ dev[0].global_request("P2P_SET disallow_freq ")
+ dev[0].global_request("SET p2p_pref_chan ")
def test_p2p_autogo_pref_chan_not_in_regulatory(dev, apdev):
"""P2P channel selection: GO preferred channel not allowed in the regulatory rules"""
try:
set_country("US", dev[0])
- dev[0].request("SET p2p_pref_chan 124:149")
+ dev[0].global_request("SET p2p_pref_chan 124:149")
res = autogo(dev[0], persistent=True)
if res['freq'] != "5745":
raise Exception("Unexpected channel selected: " + res['freq'])
raise Exception("Unexpected channel selected(2): " + res['freq'])
dev[0].remove_group(res['ifname'])
finally:
- dev[0].request("SET p2p_pref_chan ")
+ dev[0].global_request("SET p2p_pref_chan ")
set_country("00")
def run_autogo(dev, param):
wpas.interface_add("wlan5")
addr5 = wpas.p2p_dev_addr()
try:
- if "OK" not in wpas.request("SET p2p_optimize_listen_chan 1"):
+ if "OK" not in wpas.global_request("SET p2p_optimize_listen_chan 1"):
raise Exception("Failed to set p2p_optimize_listen_chan")
wpas.p2p_listen()
if not dev[0].discover_peer(addr5):
channel = "1" if lfreq != '2412' else "6"
freq = "2412" if lfreq != '2412' else "2437"
params = { "ssid": "test-open", "channel": channel }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
id = wpas.connect("test-open", key_mgmt="NONE", scan_freq=freq)
wpas.p2p_listen()
- if "OK" not in dev[0].request("P2P_FLUSH"):
+ if "OK" not in dev[0].global_request("P2P_FLUSH"):
raise Exception("P2P_FLUSH failed")
if not dev[0].discover_peer(addr5):
raise Exception("Could not discover peer")
lchannel = "1" if channel != "1" else "6"
lfreq3 = "2412" if channel != "1" else "2437"
- if "OK" not in wpas.request("P2P_SET listen_channel " + lchannel):
+ if "OK" not in wpas.global_request("P2P_SET listen_channel " + lchannel):
raise Exception("Failed to set listen channel")
wpas.select_network(id)
wpas.wait_connected()
wpas.p2p_listen()
- if "OK" not in dev[0].request("P2P_FLUSH"):
+ if "OK" not in dev[0].global_request("P2P_FLUSH"):
raise Exception("P2P_FLUSH failed")
if not dev[0].discover_peer(addr5):
raise Exception("Could not discover peer")
wpas.p2p_stop_find()
dev[0].p2p_stop_find()
finally:
- wpas.request("SET p2p_optimize_listen_chan 0")
+ wpas.global_request("SET p2p_optimize_listen_chan 0")
def test_p2p_channel_5ghz_only(dev):
"""P2P GO start with only 5 GHz band allowed"""
try:
set_country("US", dev[0])
- dev[0].request("P2P_SET disallow_freq 2400-2500")
+ dev[0].global_request("P2P_SET disallow_freq 2400-2500")
res = autogo(dev[0])
freq = int(res['freq'])
if freq < 5000:
dev[0].remove_group()
finally:
set_country("00")
- dev[0].request("P2P_SET disallow_freq ")
+ dev[0].global_request("P2P_SET disallow_freq ")
def test_p2p_channel_5ghz_165_169_us(dev):
"""P2P GO and 5 GHz channels 165 (allowed) and 169 (disallowed) in US"""
finally:
set_country("00")
-def test_p2p_go_move_reg_change(dev, apdev, params):
- """P2P GO move due to regulatory change [long]"""
- if not params['long']:
- raise HwsimSkip("Skip test case with long duration due to --long not specified")
+def wait_go_down_up(dev):
+ ev = dev.wait_group_event(["AP-DISABLED"], timeout=5)
+ if ev is None:
+ raise Exception("AP-DISABLED not seen after P2P-REMOVE-AND-REFORM-GROUP")
+ ev = dev.wait_group_event(["AP-ENABLED"], timeout=5)
+ if ev is None:
+ raise Exception("AP-ENABLED not seen after P2P-REMOVE-AND-REFORM-GROUP")
+def test_p2p_go_move_reg_change(dev, apdev):
+ """P2P GO move due to regulatory change"""
try:
set_country("US")
dev[0].global_request("P2P_SET disallow_freq 2400-5000")
dev[0].global_request("P2P_SET disallow_freq ")
# GO move is not allowed while waiting for initial client connection
- time.sleep(20)
+ connect_cli(dev[0], dev[1], freq=freq1)
+ dev[1].remove_group()
+
+ freq = dev[0].get_group_status_field('freq')
+ if int(freq) < 5000:
+ raise Exception("Unexpected freq after initial client: " + freq)
+ dev[0].dump_monitor()
+
set_country("00")
- ev = dev[0].wait_group_event(["P2P-REMOVE-AND-REFORM-GROUP"],
+ ev = dev[0].wait_group_event(["P2P-REMOVE-AND-REFORM-GROUP",
+ "AP-CSA-FINISHED"],
timeout=10)
if ev is None:
- raise Exception("P2P-REMOVE-AND-REFORM-GROUP not seen")
+ raise Exception("P2P-REMOVE-AND-REFORM-GROUP or AP-CSA-FINISHED not seen")
+ if "P2P-REMOVE-AND-REFORM-GROUP" in ev:
+ wait_go_down_up(dev[0])
freq2 = dev[0].get_group_status_field('freq')
if freq1 == freq2:
dev[0].global_request("P2P_SET disallow_freq ")
set_country("00")
-def test_p2p_go_move_active(dev, apdev, params):
- """P2P GO stays in freq although SCM is possible [long]"""
- if dev[0].get_mcc() <= 1:
- raise HwsimSkip("Skip due to MCC not being enabled")
+def test_p2p_go_move_active(dev, apdev):
+ """P2P GO stays in freq although SCM is possible"""
+ with HWSimRadio(n_channels=2) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+
+ if wpas.get_mcc() < 2:
+ raise Exception("New radio does not support MCC")
- if not params['long']:
- raise HwsimSkip("Skip test case with long duration due to --long not specified")
+ ndev = [ wpas, dev[1] ]
+ _test_p2p_go_move_active(ndev, apdev)
- dev[0].request("SET p2p_no_group_iface 0")
+def _test_p2p_go_move_active(dev, apdev):
+ dev[0].global_request("SET p2p_no_group_iface 0")
try:
dev[0].global_request("P2P_SET disallow_freq 2430-6000")
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid" : 'ap-test',
- "channel" : '11' })
+ hapd = hostapd.add_ap(apdev[0], { "ssid" : 'ap-test',
+ "channel" : '11' })
dev[0].connect("ap-test", key_mgmt="NONE",
scan_freq="2462")
raise Exception("Unexpected channel %d MHz" % freq)
# GO move is not allowed while waiting for initial client connection
- time.sleep(20)
+ connect_cli(dev[0], dev[1], freq=freq)
+ dev[1].remove_group()
+
+ freq = dev[0].get_group_status_field('freq')
+ if int(freq) > 2430:
+ raise Exception("Unexpected freq after initial client: " + freq)
+
+ dev[0].dump_monitor()
dev[0].global_request("P2P_SET disallow_freq ")
- ev = dev[0].wait_group_event(["P2P-REMOVE-AND-REFORM-GROUP"],
+ ev = dev[0].wait_group_event(["P2P-REMOVE-AND-REFORM-GROUP",
+ "AP-CSA-FINISHED"],
timeout=10)
if ev is not None:
- raise Exception("Unexpected P2P-REMOVE-AND-REFORM-GROUP seen")
+ raise Exception("Unexpected P2P-REMOVE-AND-REFORM-GROUP or AP-CSA-FINISHED seen")
dev[0].remove_group()
finally:
dev[0].global_request("P2P_SET disallow_freq ")
-def test_p2p_go_move_scm(dev, apdev, params):
- """P2P GO move due to SCM operation preference [long]"""
- if dev[0].get_mcc() <= 1:
- raise HwsimSkip("Skip due to MCC not being enabled")
+def test_p2p_go_move_scm(dev, apdev):
+ """P2P GO move due to SCM operation preference"""
+ with HWSimRadio(n_channels=2) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
- if not params['long']:
- raise HwsimSkip("Skip test case with long duration due to --long not specified")
+ if wpas.get_mcc() < 2:
+ raise Exception("New radio does not support MCC")
- dev[0].request("SET p2p_no_group_iface 0")
+ ndev = [ wpas, dev[1] ]
+ _test_p2p_go_move_scm(ndev, apdev)
+
+def _test_p2p_go_move_scm(dev, apdev):
+ dev[0].global_request("SET p2p_no_group_iface 0")
try:
dev[0].global_request("P2P_SET disallow_freq 2430-6000")
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid" : 'ap-test',
- "channel" : '11' })
+ hapd = hostapd.add_ap(apdev[0], { "ssid" : 'ap-test',
+ "channel" : '11' })
dev[0].connect("ap-test", key_mgmt="NONE",
scan_freq="2462")
raise Exception("Unexpected channel %d MHz" % freq)
# GO move is not allowed while waiting for initial client connection
- time.sleep(20)
+ connect_cli(dev[0], dev[1], freq=freq)
+ dev[1].remove_group()
+
+ freq = dev[0].get_group_status_field('freq')
+ if int(freq) > 2430:
+ raise Exception("Unexpected freq after initial client: " + freq)
+
+ dev[0].dump_monitor()
dev[0].global_request("P2P_SET disallow_freq ")
- ev = dev[0].wait_group_event(["P2P-REMOVE-AND-REFORM-GROUP"], timeout=3)
+ ev = dev[0].wait_group_event(["P2P-REMOVE-AND-REFORM-GROUP",
+ "AP-CSA-FINISHED"], timeout=3)
if ev is None:
- raise Exception("P2P-REMOVE-AND-REFORM-GROUP not seen")
+ raise Exception("P2P-REMOVE-AND-REFORM-GROUP or AP-CSA-FINISHED not seen")
+ if "P2P-REMOVE-AND-REFORM-GROUP" in ev:
+ wait_go_down_up(dev[0])
freq = dev[0].get_group_status_field('freq')
if freq != '2462':
dev[0].global_request("P2P_SET disallow_freq ")
dev[0].global_request("SET p2p_go_freq_change_policy 2")
-def test_p2p_go_move_scm_peer_supports(dev, apdev, params):
- """P2P GO move due to SCM operation preference (peer supports) [long]"""
- if dev[0].get_mcc() <= 1:
- raise HwsimSkip("Skip due to MCC not being enabled")
+def test_p2p_go_move_scm_peer_supports(dev, apdev):
+ """P2P GO move due to SCM operation preference (peer supports)"""
+ with HWSimRadio(n_channels=2) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+
+ if wpas.get_mcc() < 2:
+ raise Exception("New radio does not support MCC")
- if not params['long']:
- raise HwsimSkip("Skip test case with long duration due to --long not specified")
+ ndev = [ wpas, dev[1] ]
+ _test_p2p_go_move_scm_peer_supports(ndev, apdev)
+def _test_p2p_go_move_scm_peer_supports(dev, apdev):
try:
dev[0].global_request("SET p2p_go_freq_change_policy 1")
set_country("US", dev[0])
- dev[0].request("SET p2p_no_group_iface 0")
+ dev[0].global_request("SET p2p_no_group_iface 0")
[i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=15,
r_dev=dev[1], r_intent=0,
test_data=False)
if freq < 5000:
raise Exception("Unexpected channel %d MHz - did not follow 5 GHz preference" % freq)
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid" : 'ap-test',
- "channel" : '11' })
- logger.info('Connecting client to to an AP on channel 11');
+ hapd = hostapd.add_ap(apdev[0], { "ssid" : 'ap-test',
+ "channel" : '11' })
+ logger.info('Connecting client to to an AP on channel 11')
dev[0].connect("ap-test", key_mgmt="NONE",
scan_freq="2462")
- ev = dev[0].wait_group_event(["P2P-REMOVE-AND-REFORM-GROUP"], timeout=3)
+ ev = dev[0].wait_group_event(["P2P-REMOVE-AND-REFORM-GROUP",
+ "AP-CSA-FINISHED"], timeout=3)
if ev is None:
- raise Exception("P2P-REMOVE-AND-REFORM-GROUP not seen")
+ raise Exception("P2P-REMOVE-AND-REFORM-GROUP or AP-CSA-FINISHED not seen")
+ if "P2P-REMOVE-AND-REFORM-GROUP" in ev:
+ wait_go_down_up(dev[0])
freq = dev[0].get_group_status_field('freq')
if freq != '2462':
dev[0].global_request("SET p2p_go_freq_change_policy 2")
set_country("00")
-def test_p2p_go_move_scm_peer_does_not_support(dev, apdev, params):
- """No P2P GO move due to SCM operation (peer does not supports) [long]"""
- if dev[0].get_mcc() <= 1:
- raise HwsimSkip("Skip due to MCC not being enabled")
+def test_p2p_go_move_scm_peer_does_not_support(dev, apdev):
+ """No P2P GO move due to SCM operation (peer does not supports)"""
+ with HWSimRadio(n_channels=2) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+
+ if wpas.get_mcc() < 2:
+ raise Exception("New radio does not support MCC")
- if not params['long']:
- raise HwsimSkip("Skip test case with long duration due to --long not specified")
+ ndev = [ wpas, dev[1] ]
+ _test_p2p_go_move_scm_peer_does_not_support(ndev, apdev)
+def _test_p2p_go_move_scm_peer_does_not_support(dev, apdev):
try:
dev[0].global_request("SET p2p_go_freq_change_policy 1")
set_country("US", dev[0])
- dev[0].request("SET p2p_no_group_iface 0")
+ dev[0].global_request("SET p2p_no_group_iface 0")
if "OK" not in dev[1].request("DRIVER_EVENT AVOID_FREQUENCIES 2400-2500"):
raise Exception("Could not simulate driver event")
[i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=15,
if freq < 5000:
raise Exception("Unexpected channel %d MHz - did not follow 5 GHz preference" % freq)
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid" : 'ap-test',
- "channel" : '11' })
- logger.info('Connecting client to to an AP on channel 11');
+ hapd = hostapd.add_ap(apdev[0], { "ssid" : 'ap-test',
+ "channel" : '11' })
+ logger.info('Connecting client to to an AP on channel 11')
dev[0].connect("ap-test", key_mgmt="NONE",
scan_freq="2462")
- ev = dev[0].wait_group_event(["P2P-REMOVE-AND-REFORM-GROUP"],
+ ev = dev[0].wait_group_event(["P2P-REMOVE-AND-REFORM-GROUP",
+ "AP-CSA-FINISHED"],
timeout=10)
if ev is not None:
- raise Exception("Unexpected P2P-REMOVE-AND-REFORM-GROUP seen")
+ raise Exception("Unexpected P2P-REMOVE-AND-REFORM-GROUP or AP-CSA-FINISHED seen")
dev[0].remove_group()
finally:
dev[0].global_request("SET p2p_go_freq_change_policy 2")
+ dev[1].request("DRIVER_EVENT AVOID_FREQUENCIES")
set_country("00")
-def test_p2p_go_move_scm_multi(dev, apdev, params):
- """P2P GO move due to SCM operation preference multiple times [long]"""
- if dev[0].get_mcc() <= 1:
- raise HwsimSkip("Skip due to MCC not being enabled")
+def test_p2p_go_move_scm_multi(dev, apdev):
+ """P2P GO move due to SCM operation preference multiple times"""
+ with HWSimRadio(n_channels=2) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
- if not params['long']:
- raise HwsimSkip("Skip test case with long duration due to --long not specified")
+ if wpas.get_mcc() < 2:
+ raise Exception("New radio does not support MCC")
+
+ ndev = [ wpas, dev[1] ]
+ _test_p2p_go_move_scm_multi(ndev, apdev)
+def _test_p2p_go_move_scm_multi(dev, apdev):
dev[0].request("SET p2p_no_group_iface 0")
try:
dev[0].global_request("P2P_SET disallow_freq 2430-6000")
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid" : 'ap-test-1',
- "channel" : '11' })
+ hapd = hostapd.add_ap(apdev[0], { "ssid" : 'ap-test-1',
+ "channel" : '11' })
dev[0].connect("ap-test-1", key_mgmt="NONE",
scan_freq="2462")
raise Exception("Unexpected channel %d MHz" % freq)
# GO move is not allowed while waiting for initial client connection
- time.sleep(20)
+ connect_cli(dev[0], dev[1], freq=freq)
+ dev[1].remove_group()
+
+ freq = dev[0].get_group_status_field('freq')
+ if int(freq) > 2430:
+ raise Exception("Unexpected freq after initial client: " + freq)
+
+ dev[0].dump_monitor()
dev[0].global_request("P2P_SET disallow_freq ")
- ev = dev[0].wait_group_event(["P2P-REMOVE-AND-REFORM-GROUP"], timeout=3)
+ ev = dev[0].wait_group_event(["P2P-REMOVE-AND-REFORM-GROUP",
+ "AP-CSA-FINISHED"], timeout=3)
if ev is None:
- raise Exception("P2P-REMOVE-AND-REFORM-GROUP not seen")
+ raise Exception("P2P-REMOVE-AND-REFORM-GROUP or AP-CSA-FINISHED not seen")
+ if "P2P-REMOVE-AND-REFORM-GROUP" in ev:
+ wait_go_down_up(dev[0])
freq = dev[0].get_group_status_field('freq')
if freq != '2462':
raise Exception("Unexpected freq after group reform=" + freq)
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid" : 'ap-test-2',
- "channel" : '6' })
+ hapd = hostapd.add_ap(apdev[0], { "ssid" : 'ap-test-2',
+ "channel" : '6' })
dev[0].connect("ap-test-2", key_mgmt="NONE",
scan_freq="2437")
- ev = dev[0].wait_group_event(["P2P-REMOVE-AND-REFORM-GROUP"], timeout=5)
+ ev = dev[0].wait_group_event(["P2P-REMOVE-AND-REFORM-GROUP",
+ "AP-CSA-FINISHED"], timeout=5)
if ev is None:
- raise Exception("(2) P2P-REMOVE-AND-REFORM-GROUP not seen")
+ raise Exception("(2) P2P-REMOVE-AND-REFORM-GROUP or AP-CSA-FINISHED not seen")
+ if "P2P-REMOVE-AND-REFORM-GROUP" in ev:
+ wait_go_down_up(dev[0])
freq = dev[0].get_group_status_field('freq')
if freq != '2437':
finally:
dev[0].global_request("P2P_SET disallow_freq ")
dev[0].global_request("SET p2p_go_freq_change_policy 2")
+
+def test_p2p_delay_go_csa(dev, apdev, params):
+ """P2P GO CSA delayed when inviting a P2P Device to an active P2P Group"""
+ with HWSimRadio(n_channels=2) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+
+ wpas.global_request("SET p2p_no_group_iface 0")
+
+ if wpas.get_mcc() < 2:
+ raise Exception("New radio does not support MCC")
+
+ addr0 = wpas.p2p_dev_addr()
+ addr1 = dev[1].p2p_dev_addr()
+
+ try:
+ dev[1].p2p_listen()
+ if not wpas.discover_peer(addr1, social=True):
+ raise Exception("Peer " + addr1 + " not found")
+ wpas.p2p_stop_find()
+
+ hapd = hostapd.add_ap(apdev[0], { "ssid": 'bss-2.4ghz',
+ "channel": '1' })
+
+ wpas.connect("bss-2.4ghz", key_mgmt="NONE", scan_freq="2412")
+
+ wpas.global_request("SET p2p_go_freq_change_policy 0")
+ wpas.dump_monitor()
+
+ logger.info("Start GO on channel 6")
+ res = autogo(wpas, freq=2437)
+ if res['freq'] != "2437":
+ raise Exception("GO set on a freq=%s instead of 2437" % res['freq'])
+
+ # Start find on dev[1] to run scans with dev[2] in parallel
+ dev[1].p2p_find(social=True)
+
+ # Use another client device to stop the initial client connection
+ # timeout on the GO
+ if not dev[2].discover_peer(addr0, social=True):
+ raise Exception("Peer2 did not find the GO")
+ dev[2].p2p_stop_find()
+ pin = dev[2].wps_read_pin()
+ wpas.p2p_go_authorize_client(pin)
+ dev[2].global_request("P2P_CONNECT " + addr0 + " " + pin + " join freq=2437")
+ ev = dev[2].wait_global_event(["P2P-GROUP-STARTED"], timeout=10)
+ if ev is None:
+ raise Exception("Peer2 did not get connected")
+
+ if not dev[1].discover_peer(addr0, social=True):
+ raise Exception("Peer did not find the GO")
+
+ pin = dev[1].wps_read_pin()
+ dev[1].global_request("P2P_CONNECT " + addr0 + " " + pin + " join auth")
+ dev[1].p2p_listen()
+
+ # Force P2P GO channel switch on successful invitation signaling
+ wpas.group_request("SET p2p_go_csa_on_inv 1")
+
+ logger.info("Starting invitation")
+ wpas.p2p_go_authorize_client(pin)
+ wpas.global_request("P2P_INVITE group=" + wpas.group_ifname + " peer=" + addr1)
+ ev = dev[1].wait_global_event(["P2P-INVITATION-RECEIVED",
+ "P2P-GROUP-STARTED"], timeout=10)
+
+ if ev is None:
+ raise Exception("Timeout on invitation on peer")
+ if "P2P-INVITATION-RECEIVED" in ev:
+ raise Exception("Unexpected request to accept pre-authorized invitation")
+
+ # A P2P GO move is not expected at this stage, as during the
+ # invitation signaling, the P2P GO includes only its current
+ # operating channel in the channel list, and as the invitation
+ # response can only include channels that were also in the
+ # invitation request channel list, the group common channels
+ # includes only the current P2P GO operating channel.
+ ev = wpas.wait_group_event(["P2P-REMOVE-AND-REFORM-GROUP",
+ "AP-CSA-FINISHED"], timeout=1)
+ if ev is not None:
+ raise Exception("Unexpected + " + ev + " event")
+
+ finally:
+ wpas.global_request("SET p2p_go_freq_change_policy 2")
+
+def test_p2p_channel_vht80p80(dev):
+ """P2P group formation and VHT 80+80 MHz channel"""
+ try:
+ set_country("US", dev[0])
+ [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=15,
+ i_freq=5180,
+ i_freq2=5775,
+ i_max_oper_chwidth=160,
+ i_ht40=True, i_vht=True,
+ r_dev=dev[1], r_intent=0,
+ test_data=False)
+ check_grpform_results(i_res, r_res)
+ freq = int(i_res['freq'])
+ if freq < 5000:
+ raise Exception("Unexpected channel %d MHz - did not follow 5 GHz preference" % freq)
+ sig = dev[1].group_request("SIGNAL_POLL").splitlines()
+ if "FREQUENCY=5180" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig))
+ if "WIDTH=80+80 MHz" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
+ if "CENTER_FRQ1=5210" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(3): " + str(sig))
+ if "CENTER_FRQ2=5775" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(4): " + str(sig))
+ remove_group(dev[0], dev[1])
+ finally:
+ set_country("00")
+ dev[1].flush_scan_cache()
+
+def test_p2p_channel_vht80p80_autogo(dev):
+ """P2P autonomous GO and VHT 80+80 MHz channel"""
+ addr0 = dev[0].p2p_dev_addr()
+
+ try:
+ set_country("US", dev[0])
+ if "OK" not in dev[0].global_request("P2P_GROUP_ADD vht freq=5180 freq2=5775"):
+ raise Exception("Could not start GO")
+ ev = dev[0].wait_global_event(["P2P-GROUP-STARTED"], timeout=5)
+ if ev is None:
+ raise Exception("GO start up timed out")
+ dev[0].group_form_result(ev)
+
+ pin = dev[1].wps_read_pin()
+ dev[0].p2p_go_authorize_client(pin)
+
+ dev[1].global_request("P2P_CONNECT " + addr0 + " " + pin + " join freq=5180")
+ ev = dev[1].wait_global_event(["P2P-GROUP-STARTED"], timeout=10)
+ if ev is None:
+ raise Exception("Peer did not get connected")
+
+ dev[1].group_form_result(ev)
+ sig = dev[1].group_request("SIGNAL_POLL").splitlines()
+ if "FREQUENCY=5180" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig))
+ if "WIDTH=80+80 MHz" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
+ if "CENTER_FRQ1=5210" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(3): " + str(sig))
+ if "CENTER_FRQ2=5775" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(4): " + str(sig))
+ remove_group(dev[0], dev[1])
+ finally:
+ set_country("00")
+ dev[1].flush_scan_cache()
+
+def test_p2p_channel_vht80_autogo(dev):
+ """P2P autonomous GO and VHT 80 MHz channel"""
+ addr0 = dev[0].p2p_dev_addr()
+
+ try:
+ set_country("US", dev[0])
+ if "OK" not in dev[0].global_request("P2P_GROUP_ADD vht freq=5180 max_oper_chwidth=80"):
+ raise Exception("Could not start GO")
+ ev = dev[0].wait_global_event(["P2P-GROUP-STARTED"], timeout=5)
+ if ev is None:
+ raise Exception("GO start up timed out")
+ dev[0].group_form_result(ev)
+
+ pin = dev[1].wps_read_pin()
+ dev[0].p2p_go_authorize_client(pin)
+
+ dev[1].global_request("P2P_CONNECT " + addr0 + " " + pin + " join freq=5180")
+ ev = dev[1].wait_global_event(["P2P-GROUP-STARTED"], timeout=10)
+ if ev is None:
+ raise Exception("Peer did not get connected")
+
+ dev[1].group_form_result(ev)
+ sig = dev[1].group_request("SIGNAL_POLL").splitlines()
+ if "FREQUENCY=5180" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig))
+ if "WIDTH=80 MHz" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
+ remove_group(dev[0], dev[1])
+ finally:
+ set_country("00")
+ dev[1].flush_scan_cache()
+
+def test_p2p_channel_vht80p80_persistent(dev):
+ """P2P persistent group re-invocation and VHT 80+80 MHz channel"""
+ addr0 = dev[0].p2p_dev_addr()
+ form(dev[0], dev[1])
+
+ try:
+ set_country("US", dev[0])
+ invite(dev[0], dev[1], extra="vht freq=5745 freq2=5210")
+ [go_res, cli_res] = check_result(dev[0], dev[1])
+
+ sig = dev[1].group_request("SIGNAL_POLL").splitlines()
+ if "FREQUENCY=5745" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig))
+ if "WIDTH=80+80 MHz" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
+ if "CENTER_FRQ1=5775" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(3): " + str(sig))
+ if "CENTER_FRQ2=5210" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(4): " + str(sig))
+ remove_group(dev[0], dev[1])
+ finally:
+ set_country("00")
+ dev[1].flush_scan_cache()
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import logging
logger = logging.getLogger()
import subprocess
import hwsim_utils
import hostapd
-from test_p2p_grpform import go_neg_pin_authorized
-from test_p2p_grpform import go_neg_pbc
-from test_p2p_grpform import check_grpform_results
-from test_p2p_grpform import remove_group
-from test_p2p_persistent import form
-from test_p2p_persistent import invite_from_cli
-from test_p2p_persistent import invite_from_go
-from test_p2p_persistent import invite
+from p2p_utils import *
from test_ap_ht import clear_scan_cache
from utils import HwsimSkip
+@remote_compatible
def test_concurrent_autogo(dev, apdev):
"""Concurrent P2P autonomous GO"""
logger.info("Connect to an infrastructure AP")
dev[0].request("P2P_SET cross_connect 0")
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-open" })
dev[0].connect("test-open", key_mgmt="NONE", scan_freq="2412")
hwsim_utils.test_connectivity(dev[0], hapd)
logger.info("Start a P2P group while associated to an AP")
- dev[0].request("SET p2p_no_group_iface 0")
+ dev[0].global_request("SET p2p_no_group_iface 0")
dev[0].p2p_start_go()
pin = dev[1].wps_read_pin()
dev[0].p2p_go_authorize_client(pin)
def test_concurrent_autogo_5ghz_ht40(dev, apdev):
"""Concurrent P2P autonomous GO on 5 GHz and HT40 co-ex"""
- clear_scan_cache(apdev[1]['ifname'])
+ clear_scan_cache(apdev[1])
try:
hapd = None
hapd2 = None
"channel": "153",
"country_code": "US",
"ht_capab": "[HT40-]" }
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
params = { "ssid": "test-open-5",
"hw_mode": "a",
"channel": "149",
"country_code": "US" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].request("P2P_SET cross_connect 0")
dev[0].scan_for_bss(apdev[0]['bssid'], freq=5745)
dev[0].scan_for_bss(apdev[1]['bssid'], freq=5765)
dev[0].connect("test-open-5", key_mgmt="NONE", scan_freq="5745")
- dev[0].request("SET p2p_no_group_iface 0")
+ dev[0].global_request("SET p2p_no_group_iface 0")
if "OK" not in dev[0].global_request("P2P_GROUP_ADD ht40"):
raise Exception("P2P_GROUP_ADD failed")
ev = dev[0].wait_global_event(["P2P-GROUP-STARTED"], timeout=5)
def test_concurrent_autogo_crossconnect(dev, apdev):
"""Concurrent P2P autonomous GO"""
dev[0].global_request("P2P_SET cross_connect 1")
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-open" })
dev[0].connect("test-open", key_mgmt="NONE", scan_freq="2412")
dev[0].global_request("SET p2p_no_group_iface 0")
raise Exception("Timeout on cross connection disabled event")
dev[0].global_request("P2P_SET cross_connect 0")
+@remote_compatible
def test_concurrent_p2pcli(dev, apdev):
"""Concurrent P2P client join"""
logger.info("Connect to an infrastructure AP")
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-open" })
dev[0].connect("test-open", key_mgmt="NONE", scan_freq="2412")
hwsim_utils.test_connectivity(dev[0], hapd)
logger.info("Join a P2P group while associated to an AP")
- dev[0].request("SET p2p_no_group_iface 0")
+ dev[0].global_request("SET p2p_no_group_iface 0")
dev[1].p2p_start_go(freq=2412)
pin = dev[0].wps_read_pin()
dev[1].p2p_go_authorize_client(pin)
logger.info("Confirm AP connection after P2P group removal")
hwsim_utils.test_connectivity(dev[0], hapd)
+@remote_compatible
def test_concurrent_grpform_go(dev, apdev):
"""Concurrent P2P group formation to become GO"""
logger.info("Connect to an infrastructure AP")
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-open" })
dev[0].connect("test-open", key_mgmt="NONE", scan_freq="2412")
hwsim_utils.test_connectivity(dev[0], hapd)
logger.info("Form a P2P group while associated to an AP")
- dev[0].request("SET p2p_no_group_iface 0")
+ dev[0].global_request("SET p2p_no_group_iface 0")
[i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=15,
r_dev=dev[1], r_intent=0)
logger.info("Confirm AP connection after P2P group removal")
hwsim_utils.test_connectivity(dev[0], hapd)
+@remote_compatible
def test_concurrent_grpform_cli(dev, apdev):
"""Concurrent P2P group formation to become P2P Client"""
logger.info("Connect to an infrastructure AP")
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-open" })
dev[0].connect("test-open", key_mgmt="NONE", scan_freq="2412")
hwsim_utils.test_connectivity(dev[0], hapd)
logger.info("Form a P2P group while associated to an AP")
- dev[0].request("SET p2p_no_group_iface 0")
+ dev[0].global_request("SET p2p_no_group_iface 0")
[i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=0,
r_dev=dev[1], r_intent=15)
logger.info("Confirm AP connection after P2P group removal")
hwsim_utils.test_connectivity(dev[0], hapd)
+@remote_compatible
def test_concurrent_grpform_while_connecting(dev, apdev):
"""Concurrent P2P group formation while connecting to an AP"""
logger.info("Start connection to an infrastructure AP")
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-open" })
dev[0].connect("test-open", key_mgmt="NONE", wait_connect=False)
logger.info("Form a P2P group while connecting to an AP")
- dev[0].request("SET p2p_no_group_iface 0")
+ dev[0].global_request("SET p2p_no_group_iface 0")
[i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_freq=2412,
r_dev=dev[1], r_freq=2412)
logger.info("Confirm AP connection after P2P group removal")
hwsim_utils.test_connectivity(dev[0], hapd)
+@remote_compatible
def test_concurrent_grpform_while_connecting2(dev, apdev):
"""Concurrent P2P group formation while connecting to an AP (2)"""
logger.info("Start connection to an infrastructure AP")
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-open" })
dev[0].connect("test-open", key_mgmt="NONE", wait_connect=False)
dev[1].flush_scan_cache()
logger.info("Form a P2P group while connecting to an AP")
- dev[0].request("SET p2p_no_group_iface 0")
+ dev[0].global_request("SET p2p_no_group_iface 0")
[i_res, r_res] = go_neg_pbc(i_dev=dev[0], i_intent=15, i_freq=2412,
r_dev=dev[1], r_intent=0, r_freq=2412)
dev[0].wait_completed()
hwsim_utils.test_connectivity(dev[0], hapd)
+@remote_compatible
def test_concurrent_grpform_while_connecting3(dev, apdev):
"""Concurrent P2P group formation while connecting to an AP (3)"""
logger.info("Start connection to an infrastructure AP")
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-open" })
dev[0].connect("test-open", key_mgmt="NONE", wait_connect=False)
logger.info("Form a P2P group while connecting to an AP")
- dev[0].request("SET p2p_no_group_iface 0")
+ dev[0].global_request("SET p2p_no_group_iface 0")
[i_res, r_res] = go_neg_pbc(i_dev=dev[1], i_intent=15, i_freq=2412,
r_dev=dev[0], r_intent=0, r_freq=2412)
dev[0].wait_completed()
hwsim_utils.test_connectivity(dev[0], hapd)
+@remote_compatible
def test_concurrent_persistent_group(dev, apdev):
"""Concurrent P2P persistent group"""
logger.info("Connect to an infrastructure AP")
- hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-open", "channel": "2" })
+ hostapd.add_ap(apdev[0], { "ssid": "test-open", "channel": "2" })
dev[0].global_request("SET p2p_no_group_iface 0")
dev[0].connect("test-open", key_mgmt="NONE", scan_freq="2417")
dev[1].dump_monitor()
logger.info("Connect to an infrastructure AP")
- hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-open", "channel": "2" })
+ hostapd.add_ap(apdev[0], { "ssid": "test-open", "channel": "2" })
dev[0].global_request("SET p2p_no_group_iface 0")
dev[0].connect("test-open", key_mgmt="NONE", scan_freq="2417")
invite(dev[1], dev[0], extra="freq=2412")
import time
from wpasupplicant import WpaSupplicant
-from test_p2p_grpform import go_neg_pin_authorized
-from test_p2p_grpform import check_grpform_results
-from test_p2p_grpform import remove_group
+from p2p_utils import *
from test_nfc_p2p import set_ip_addr_info, check_ip_addr, grpform_events
from hwsim import HWSimRadio
+from utils import HwsimSkip
import hostapd
import hwsim_utils
[i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=15,
r_dev=wpas, r_intent=0)
check_grpform_results(i_res, r_res)
+ wpas.dump_monitor()
remove_group(dev[0], wpas)
+ wpas.dump_monitor()
+ if not r_res['ifname'].startswith('p2p-' + iface):
+ raise Exception("Unexpected group ifname: " + r_res['ifname'])
res = wpas.global_request("IFNAME=p2p-dev-" + iface + " STATUS-DRIVER")
lines = res.splitlines()
[i_res, r_res] = go_neg_pin_authorized(i_dev=wpas, i_intent=15,
r_dev=dev[0], r_intent=0)
check_grpform_results(i_res, r_res)
+ wpas.dump_monitor()
remove_group(wpas, dev[0])
+ wpas.dump_monitor()
+ if not i_res['ifname'].startswith('p2p-' + iface):
+ raise Exception("Unexpected group ifname: " + i_res['ifname'])
+
+def test_p2p_device_grpform_no_group_iface(dev, apdev):
+ """P2P group formation with driver using cfg80211 P2P Device but no separate group interface"""
+ with HWSimRadio(use_p2p_device=True) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+ wpas.global_request("SET p2p_no_group_iface 1")
+ [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=15,
+ r_dev=wpas, r_intent=0)
+ check_grpform_results(i_res, r_res)
+ wpas.dump_monitor()
+ remove_group(dev[0], wpas)
+ wpas.dump_monitor()
+ if r_res['ifname'] != iface:
+ raise Exception("Unexpected group ifname: " + r_res['ifname'])
+
+def test_p2p_device_grpform_no_group_iface2(dev, apdev):
+ """P2P group formation with driver using cfg80211 P2P Device but no separate group interface (reverse)"""
+ with HWSimRadio(use_p2p_device=True) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+ wpas.global_request("SET p2p_no_group_iface 1")
+ [i_res, r_res] = go_neg_pin_authorized(i_dev=wpas, i_intent=15,
+ r_dev=dev[0], r_intent=0)
+ check_grpform_results(i_res, r_res)
+ wpas.dump_monitor()
+ remove_group(dev[0], wpas)
+ wpas.dump_monitor()
+ if i_res['ifname'] != iface:
+ raise Exception("Unexpected group ifname: " + i_res['ifname'])
def test_p2p_device_group_remove(dev, apdev):
"""P2P group removal via the P2P ctrl interface with driver using cfg80211 P2P Device"""
raise Exception("Station mode scan did not start")
def test_p2p_device_nfc_invite(dev, apdev):
- """P2P NFC invitiation with driver using cfg80211 P2P Device"""
+ """P2P NFC invitation with driver using cfg80211 P2P Device"""
+ run_p2p_device_nfc_invite(dev, apdev, 0)
+
+def test_p2p_device_nfc_invite_no_group_iface(dev, apdev):
+ """P2P NFC invitation with driver using cfg80211 P2P Device (no separate group interface)"""
+ run_p2p_device_nfc_invite(dev, apdev, 1)
+
+def run_p2p_device_nfc_invite(dev, apdev, no_group_iface):
with HWSimRadio(use_p2p_device=True) as (radio, iface):
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add(iface)
+ wpas.global_request("SET p2p_no_group_iface %d" % no_group_iface)
set_ip_addr_info(dev[0])
logger.info("Start autonomous GO")
res = wpas.global_request("P2P_LISTEN")
if "FAIL" in res:
raise Exception("Failed to start Listen mode")
+ wpas.dump_monitor()
pw = wpas.global_request("WPS_NFC_TOKEN NDEF").rstrip()
if "FAIL" in pw:
raise Exception("Failed to generate password token")
sel = wpas.global_request("NFC_GET_HANDOVER_SEL NDEF P2P-CR-TAG").rstrip()
if "FAIL" in sel:
raise Exception("Failed to generate NFC connection handover select")
+ wpas.dump_monitor()
logger.info("Read NFC Tag on the GO to trigger invitation")
res = dev[0].global_request("WPS_NFC_TAG_READ " + sel)
if ev is None:
raise Exception("Joining the group timed out")
res = wpas.group_form_result(ev)
+ wpas.dump_monitor()
hwsim_utils.test_connectivity_p2p(dev[0], wpas)
check_ip_addr(res)
+ wpas.dump_monitor()
def test_p2p_device_misuses(dev, apdev):
"""cfg80211 P2P Device misuses"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
with HWSimRadio(use_p2p_device=True) as (radio, iface):
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add(iface)
ev = wpas.wait_event(["P2P-DEVICE-FOUND"], timeout=0.1)
if ev is not None:
raise Exception("Unexpected P2P-DEVICE-FOUND event on station interface")
+ wpas.dump_monitor()
pin = wpas.wps_read_pin()
dev[0].p2p_go_neg_auth(wpas.p2p_dev_addr(), pin, "enter", go_intent=14,
freq=2412)
wpas.request('P2P_STOP_FIND')
+ wpas.dump_monitor()
if "OK" not in wpas.request('P2P_CONNECT ' + dev[0].p2p_dev_addr() + ' ' + pin + ' display go_intent=1'):
raise Exception("P2P_CONNECT failed")
if ev is None:
raise Exception("Group formation timed out")
wpas.group_form_result(ev)
+ wpas.dump_monitor()
ev = dev[0].wait_global_event(["P2P-GROUP-STARTED"], timeout=15)
if ev is None:
dev[0].remove_group()
wpas.wait_go_ending_session()
+ wpas.dump_monitor()
def test_p2p_device_incorrect_command_interface2(dev, apdev):
"""cfg80211 P2P Device and P2P_GROUP_ADD command on incorrect interface"""
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add(iface)
- print wpas.request('P2P_GROUP_ADD')
+ if "OK" not in wpas.request('P2P_GROUP_ADD'):
+ raise Exception("P2P_GROUP_ADD failed")
ev = wpas.wait_global_event(["P2P-GROUP-STARTED"], timeout=15)
if ev is None:
raise Exception("Group formation timed out")
res = wpas.group_form_result(ev)
+ wpas.dump_monitor()
logger.info("Group results: " + str(res))
wpas.remove_group()
if not res['ifname'].startswith('p2p-' + iface + '-'):
raise Exception("Unexpected group ifname: " + res['ifname'])
+ wpas.dump_monitor()
+
+def test_p2p_device_grpform_timeout_client(dev, apdev):
+ """P2P group formation timeout on client with cfg80211 P2P Device"""
+ with HWSimRadio(use_p2p_device=True) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+ addr0 = dev[0].p2p_dev_addr()
+ addr5 = wpas.p2p_dev_addr()
+ wpas.p2p_listen()
+ dev[0].discover_peer(addr5)
+ dev[0].p2p_listen()
+ wpas.discover_peer(addr0)
+ wpas.p2p_ext_listen(100, 150)
+ dev[0].global_request("P2P_CONNECT " + addr5 + " 12345670 enter go_intent=15 auth")
+ wpas.global_request("P2P_CONNECT " + addr0 + " 12345670 display go_intent=0")
+ ev = dev[0].wait_global_event(["P2P-GO-NEG-SUCCESS"], timeout=5)
+ if ev is None:
+ raise Exception("GO Negotiation did not succeed")
+ ev = dev[0].wait_global_event(["WPS-SUCCESS"], timeout=10)
+ if ev is None:
+ raise Exception("WPS did not succeed (GO)")
+ if "OK" not in dev[0].global_request("P2P_CANCEL"):
+ wpas.global_request("P2P_CANCEL")
+ del wpas
+ raise HwsimSkip("Did not manage to cancel group formation")
+ dev[0].dump_monitor()
+ ev = wpas.wait_global_event(["WPS-SUCCESS"], timeout=10)
+ if ev is None:
+ raise Exception("WPS did not succeed (Client)")
+ dev[0].dump_monitor()
+ ev = wpas.wait_global_event(["P2P-GROUP-FORMATION-FAILURE"], timeout=20)
+ if ev is None:
+ raise Exception("Group formation timeout not seen on client")
+ ev = wpas.wait_global_event(["P2P-GROUP-REMOVED"], timeout=5)
+ if ev is None:
+ raise Exception("Group removal not seen on client")
+ wpas.p2p_cancel_ext_listen()
+ time.sleep(0.1)
+ ifaces = wpas.global_request("INTERFACES")
+ logger.info("Remaining interfaces: " + ifaces)
+ del wpas
+ if "p2p-" + iface + "-" in ifaces:
+ raise Exception("Group interface still present after failure")
+
+def test_p2p_device_grpform_timeout_go(dev, apdev):
+ """P2P group formation timeout on GO with cfg80211 P2P Device"""
+ with HWSimRadio(use_p2p_device=True) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+ addr0 = dev[0].p2p_dev_addr()
+ addr5 = wpas.p2p_dev_addr()
+ wpas.p2p_listen()
+ dev[0].discover_peer(addr5)
+ dev[0].p2p_listen()
+ wpas.discover_peer(addr0)
+ wpas.p2p_ext_listen(100, 150)
+ dev[0].global_request("P2P_CONNECT " + addr5 + " 12345670 enter go_intent=0 auth")
+ wpas.global_request("P2P_CONNECT " + addr0 + " 12345670 display go_intent=15")
+ ev = dev[0].wait_global_event(["P2P-GO-NEG-SUCCESS"], timeout=5)
+ if ev is None:
+ raise Exception("GO Negotiation did not succeed")
+ ev = dev[0].wait_global_event(["WPS-SUCCESS"], timeout=10)
+ if ev is None:
+ raise Exception("WPS did not succeed (Client)")
+ if "OK" not in dev[0].global_request("P2P_CANCEL"):
+ if "OK" not in dev[0].global_request("P2P_GROUP_REMOVE *"):
+ wpas.global_request("P2P_CANCEL")
+ del wpas
+ raise HwsimSkip("Did not manage to cancel group formation")
+ dev[0].dump_monitor()
+ ev = wpas.wait_global_event(["WPS-SUCCESS"], timeout=10)
+ if ev is None:
+ raise Exception("WPS did not succeed (GO)")
+ dev[0].dump_monitor()
+ ev = wpas.wait_global_event(["P2P-GROUP-FORMATION-FAILURE"], timeout=20)
+ if ev is None:
+ raise Exception("Group formation timeout not seen on GO")
+ ev = wpas.wait_global_event(["P2P-GROUP-REMOVED"], timeout=5)
+ if ev is None:
+ raise Exception("Group removal not seen on GO")
+ wpas.p2p_cancel_ext_listen()
+ time.sleep(0.1)
+ ifaces = wpas.global_request("INTERFACES")
+ logger.info("Remaining interfaces: " + ifaces)
+ del wpas
+ if "p2p-" + iface + "-" in ifaces:
+ raise Exception("Group interface still present after failure")
+
+def test_p2p_device_autogo(dev, apdev):
+ """P2P autogo using cfg80211 P2P Device"""
+ with HWSimRadio(use_p2p_device=True) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+
+ res = wpas.p2p_start_go()
+ if not res['ifname'].startswith('p2p-' + iface):
+ raise Exception("Unexpected group ifname: " + res['ifname'])
+ bssid = wpas.get_group_status_field('bssid')
+
+ dev[0].scan_for_bss(bssid, res['freq'])
+ connect_cli(wpas, dev[0], freq=res['freq'])
+ terminate_group(wpas, dev[0])
+
+def test_p2p_device_autogo_no_group_iface(dev, apdev):
+ """P2P autogo using cfg80211 P2P Device (no separate group interface)"""
+ with HWSimRadio(use_p2p_device=True) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+ wpas.global_request("SET p2p_no_group_iface 1")
+
+ res = wpas.p2p_start_go()
+ if res['ifname'] != iface:
+ raise Exception("Unexpected group ifname: " + res['ifname'])
+ bssid = wpas.get_group_status_field('bssid')
+
+ dev[0].scan_for_bss(bssid, res['freq'])
+ connect_cli(wpas, dev[0], freq=res['freq'])
+ terminate_group(wpas, dev[0])
+
+def test_p2p_device_join(dev, apdev):
+ """P2P join-group using cfg80211 P2P Device"""
+ with HWSimRadio(use_p2p_device=True) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+
+ res = dev[0].p2p_start_go()
+ bssid = dev[0].get_group_status_field('bssid')
+
+ wpas.scan_for_bss(bssid, res['freq'])
+ res2 = connect_cli(dev[0], wpas, freq=res['freq'])
+ if not res2['ifname'].startswith('p2p-' + iface):
+ raise Exception("Unexpected group ifname: " + res2['ifname'])
+
+ terminate_group(dev[0], wpas)
+
+def test_p2p_device_join_no_group_iface(dev, apdev):
+ """P2P join-group using cfg80211 P2P Device (no separate group interface)"""
+ with HWSimRadio(use_p2p_device=True) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+ wpas.global_request("SET p2p_no_group_iface 1")
+
+ res = dev[0].p2p_start_go()
+ bssid = dev[0].get_group_status_field('bssid')
+
+ wpas.scan_for_bss(bssid, res['freq'])
+ res2 = connect_cli(dev[0], wpas, freq=res['freq'])
+ if res2['ifname'] != iface:
+ raise Exception("Unexpected group ifname: " + res2['ifname'])
+
+ terminate_group(dev[0], wpas)
+
+def test_p2p_device_persistent_group(dev):
+ """P2P persistent group formation and re-invocation with cfg80211 P2P Device"""
+ with HWSimRadio(use_p2p_device=True) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+ wpas.global_request("SET p2p_no_group_iface 0")
+
+ form(dev[0], wpas)
+ invite_from_cli(dev[0], wpas)
+ invite_from_go(dev[0], wpas)
+
+def test_p2p_device_persistent_group_no_group_iface(dev):
+ """P2P persistent group formation and re-invocation with cfg80211 P2P Device (no separate group interface)"""
+ with HWSimRadio(use_p2p_device=True) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+ wpas.global_request("SET p2p_no_group_iface 1")
+
+ form(dev[0], wpas)
+ invite_from_cli(dev[0], wpas)
+ invite_from_go(dev[0], wpas)
+
+def test_p2p_device_persistent_group2(dev):
+ """P2P persistent group formation and re-invocation (reverse) with cfg80211 P2P Device"""
+ with HWSimRadio(use_p2p_device=True) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+ wpas.global_request("SET p2p_no_group_iface 0")
+
+ form(wpas, dev[0])
+ invite_from_cli(wpas, dev[0])
+ invite_from_go(wpas, dev[0])
+
+def test_p2p_device_persistent_group2_no_group_iface(dev):
+ """P2P persistent group formation and re-invocation (reverse) with cfg80211 P2P Device (no separate group interface)"""
+ with HWSimRadio(use_p2p_device=True) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+ wpas.global_request("SET p2p_no_group_iface 1")
+
+ form(wpas, dev[0])
+ invite_from_cli(wpas, dev[0])
+ invite_from_go(wpas, dev[0])
+
+def p2p_device_group_conf(dev1, dev2):
+ dev1.global_request("SET p2p_group_idle 12")
+ dev1.global_request("SET p2p_go_freq_change_policy 2")
+ dev1.global_request("SET p2p_go_ctwindow 7")
+
+ [i_res, r_res] = go_neg_pin_authorized(i_dev=dev1, i_intent=15,
+ r_dev=dev2, r_intent=0)
+ check_grpform_results(i_res, r_res)
+
+ if (dev1.group_request("GET p2p_group_idle") != "12" or
+ dev1.group_request("GET p2p_go_freq_change_policy") != "2" or
+ dev1.group_request("GET p2p_go_ctwindow") != "7"):
+ raise Exception("Unexpected configuration value")
+
+ remove_group(dev1, dev2)
+ dev1.global_request("P2P_FLUSH")
+ dev2.global_request("P2P_FLUSH")
+
+def test_p2p_device_conf(dev, apdev):
+ """P2P configuration with cfg80211 P2P Device"""
+ with HWSimRadio(use_p2p_device=True) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+ wpas.global_request("SET p2p_no_group_iface 1")
+ p2p_device_group_conf(wpas, dev[0])
+ wpas.global_request("SET p2p_no_group_iface 0")
+ p2p_device_group_conf(wpas, dev[0])
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import logging
logger = logging.getLogger()
+import os
import time
import hwsim_utils
from wpasupplicant import WpaSupplicant
+from p2p_utils import *
+from test_gas import start_ap
+from test_cfg80211 import nl80211_remain_on_channel
+@remote_compatible
def test_discovery(dev):
"""P2P device discovery and provision discovery"""
addr0 = dev[0].p2p_dev_addr()
if "FAIL" not in dev[0].global_request("P2P_PROV_DISC 00:11:22:33:44:55 foo"):
raise Exception("Invalid P2P_PROV_DISC accepted")
+@remote_compatible
def test_discovery_pd_retries(dev):
"""P2P device discovery and provision discovery retries"""
addr0 = dev[0].p2p_dev_addr()
logger.info("Connect a client to the GO")
pin = dev[1].wps_read_pin()
dev[0].p2p_go_authorize_client(pin)
- dev[1].p2p_connect_group(dev[0].p2p_dev_addr(), pin, timeout=60)
+ dev[1].p2p_connect_group(dev[0].p2p_dev_addr(), pin, freq=int(res['freq']),
+ timeout=60)
logger.info("Client connected")
hwsim_utils.test_connectivity_p2p(dev[0], dev[1])
logger.info("Try to discover a P2P client in a group")
if not dev[2].discover_peer(dev[1].p2p_dev_addr(), social=False, timeout=10):
+ stop_p2p_find_and_wait(dev[2])
if not dev[2].discover_peer(dev[1].p2p_dev_addr(), social=False, timeout=10):
+ stop_p2p_find_and_wait(dev[2])
if not dev[2].discover_peer(dev[1].p2p_dev_addr(), social=False, timeout=10):
raise Exception("Could not discover group client")
if ev is None:
raise Exception("Timeout on waiting for GO Negotiation Request")
+def stop_p2p_find_and_wait(dev):
+ dev.request("P2P_STOP_FIND")
+ for i in range(10):
+ res = dev.get_driver_status_field("scan_state")
+ if "SCAN_STARTED" not in res and "SCAN_REQUESTED" not in res:
+ break
+ logger.debug("Waiting for final P2P_FIND scan to complete")
+ time.sleep(0.02)
+
+def test_discovery_ctrl_char_in_devname(dev):
+ """P2P device discovery and control character in Device Name"""
+ try:
+ _test_discovery_ctrl_char_in_devname(dev)
+ finally:
+ dev[1].global_request("SET device_name Device B")
+
+def _test_discovery_ctrl_char_in_devname(dev):
+ dev[1].global_request("SET device_name Device\tB")
+ addr0 = dev[0].p2p_dev_addr()
+ addr1 = dev[1].p2p_dev_addr()
+ res = dev[0].p2p_start_go(freq=2422)
+ bssid = dev[0].p2p_interface_addr()
+ pin = dev[1].wps_read_pin()
+ dev[0].p2p_go_authorize_client(pin)
+ dev[1].scan_for_bss(bssid, freq=2422)
+ dev[1].p2p_connect_group(addr0, pin, timeout=60, freq=2422)
+ if not dev[2].discover_peer(addr1, social=False, freq=2422, timeout=5):
+ stop_p2p_find_and_wait(dev[2])
+ if not dev[2].discover_peer(addr1, social=False, freq=2422, timeout=5):
+ stop_p2p_find_and_wait(dev[2])
+ if not dev[2].discover_peer(addr1, social=False, freq=2422,
+ timeout=5):
+ raise Exception("Could not discover group client")
+ devname = dev[2].get_peer(addr1)['device_name']
+ dev[2].p2p_stop_find()
+ if devname != "Device_B":
+ raise Exception("Unexpected device_name from group client: " + devname)
+
+ terminate_group(dev[0], dev[1])
+ dev[2].request("P2P_FLUSH")
+
+ dev[1].p2p_listen()
+ if not dev[2].discover_peer(addr1, social=True, timeout=10):
+ raise Exception("Could not discover peer")
+ devname = dev[2].get_peer(addr1)['device_name']
+ dev[2].p2p_stop_find()
+ if devname != "Device_B":
+ raise Exception("Unexpected device_name from peer: " + devname)
+
+@remote_compatible
def test_discovery_dev_type(dev):
"""P2P device discovery with Device Type filter"""
dev[1].request("SET sec_device_type 1-0050F204-2")
if dev[1].peer_known(go):
raise Exception("GO found in social-only scan")
-def test_discovery_and_interface_disabled(dev):
- """P2P device discovery with interface getting didabled"""
+def _test_discovery_and_interface_disabled(dev, delay=1):
try:
if "OK" not in dev[0].p2p_find():
raise Exception("Failed to start P2P find")
if ev is None:
raise Exception("Scan did not start")
dev[0].request("DRIVER_EVENT INTERFACE_DISABLED")
- time.sleep(1)
+ time.sleep(delay)
# verify that P2P_FIND is rejected
if "FAIL" not in dev[0].p2p_find():
finally:
dev[0].request("DRIVER_EVENT INTERFACE_ENABLED")
+def test_discovery_and_interface_disabled(dev):
+ """P2P device discovery with interface getting disabled"""
+ _test_discovery_and_interface_disabled(dev, delay=1)
+ _test_discovery_and_interface_disabled(dev, delay=5)
+
def test_discovery_auto(dev):
"""P2P device discovery and provision discovery with auto GO/dev selection"""
dev[0].flush_scan_cache()
dev[2].p2p_stop_find()
dev[0].p2p_stop_find()
+@remote_compatible
def test_p2p_listen_and_scan(dev):
"""P2P_LISTEN and scan"""
dev[0].p2p_listen()
raise Exception("Unexpected peer config methods(2): " + peer['config_methods'])
wpas.p2p_stop_find()
+
+@remote_compatible
+def test_discovery_after_gas(dev, apdev):
+ """P2P device discovery after GAS/ANQP exchange"""
+ hapd = start_ap(apdev[0])
+ hapd.set("gas_frag_limit", "50")
+ dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
+ dev[0].request("FETCH_ANQP")
+ ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10)
+ if ev is None:
+ raise Exception("No ANQP-QUERY-DONE event")
+ dev[0].dump_monitor()
+
+ start = os.times()[4]
+ dev[0].p2p_listen()
+ dev[1].p2p_find(social=True)
+ ev = dev[1].wait_global_event(["P2P-DEVICE-FOUND"], timeout=5)
+ if ev is None:
+ raise Exception("Peer not discovered")
+ end = os.times()[4]
+ dev[0].dump_monitor()
+ dev[0].p2p_stop_find()
+ dev[1].p2p_stop_find()
+ logger.info("Device discovery after fragmented GAS took %f seconds" % (end - start))
+ if end - start > 1.3:
+ raise Exception("Device discovery took unexpectedly long time")
+
+@remote_compatible
+def test_discovery_listen_find(dev):
+ """P2P_LISTEN immediately followed by P2P_FIND"""
+ # Request an external remain-on-channel operation to delay start of the ROC
+ # for the following p2p_listen() enough to get p2p_find() processed before
+ # the ROC started event shows up. This is done to test a code path where the
+ # p2p_find() needs to clear the wait for the pending listen operation
+ # (p2p->pending_listen_freq).
+ ifindex = int(dev[0].get_driver_status_field("ifindex"))
+ nl80211_remain_on_channel(dev[0], ifindex, 2417, 200)
+
+ addr0 = dev[0].p2p_dev_addr()
+ dev[0].p2p_listen()
+ dev[0].p2p_find(social=True)
+ time.sleep(0.4)
+ dev[1].p2p_listen()
+ ev = dev[0].wait_global_event(["P2P-DEVICE-FOUND"], timeout=1.2)
+ if not dev[1].discover_peer(addr0):
+ raise Exception("Device discovery timed out")
+ if ev is None:
+ raise Exception("Did not find peer quickly enough after stopped P2P_LISTEN")
+
+def test_discovery_long_listen(dev):
+ """Long P2P_LISTEN and offchannel TX"""
+ addr0 = dev[0].p2p_dev_addr()
+ dev[0].p2p_listen()
+
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add("wlan5")
+ addr = wpas.p2p_dev_addr()
+ if not wpas.discover_peer(addr0):
+ raise Exception("Device discovery timed out")
+ peer = wpas.get_peer(addr0)
+ chan = '1' if peer['listen_freq'] == '2462' else '11'
+
+ wpas.request("P2P_SET listen_channel " + chan)
+ wpas.request("P2P_LISTEN 10")
+ if not dev[0].discover_peer(addr):
+ raise Exception("Device discovery timed out (2)")
+
+ time.sleep(0.1)
+ wpas.global_request("P2P_PROV_DISC " + addr0 + " display")
+ ev = dev[0].wait_global_event(["P2P-PROV-DISC-SHOW-PIN"], timeout=15)
+ if ev is None:
+ raise Exception("Provision discovery timed out")
+ dev[0].p2p_stop_find()
+
+ # Verify that the long listen period is still continuing after off-channel
+ # TX of Provision Discovery frames.
+ if not dev[1].discover_peer(addr):
+ raise Exception("Device discovery timed out (3)")
+
+ dev[1].p2p_stop_find()
+ wpas.p2p_stop_find()
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import logging
logger = logging.getLogger()
import os
from tshark import run_tshark
-from test_p2p_persistent import form
+from p2p_utils import *
+@remote_compatible
def test_p2p_ext_discovery(dev):
"""P2P device discovery with vendor specific extensions"""
addr0 = dev[0].p2p_dev_addr()
finally:
dev[0].request("VENDOR_ELEM_REMOVE 1 *")
+@remote_compatible
def test_p2p_ext_discovery_go(dev):
"""P2P device discovery with vendor specific extensions for GO"""
addr0 = dev[0].p2p_dev_addr()
def _test_p2p_ext_vendor_elem_assoc(dev, apdev, params):
addr0 = dev[0].p2p_dev_addr()
addr1 = dev[1].p2p_dev_addr()
+
+ res = dev[0].get_driver_status()
+ p2p_device = True if (int(res['capa.flags'], 0) & 0x20000000) else False
+
if "OK" not in dev[0].request("VENDOR_ELEM_ADD 11 dd050011223308"):
raise Exception("VENDOR_ELEM_ADD failed")
if "OK" not in dev[1].request("VENDOR_ELEM_ADD 12 dd050011223309"):
raise Exception("VENDOR_ELEM_ADD failed")
- if "OK" not in dev[0].request("VENDOR_ELEM_ADD 13 dd05001122330a"):
+ if not p2p_device and "OK" not in dev[0].request("VENDOR_ELEM_ADD 13 dd05001122330a"):
raise Exception("VENDOR_ELEM_ADD failed")
dev[0].p2p_listen()
dev[1].p2p_listen()
"wlan.fc.type_subtype == 0x00", wait=False)
if "Vendor Specific Data: 3308" not in out:
raise Exception("Vendor element (P2P) not found from Association Request frame")
- if "Vendor Specific Data: 330a" not in out:
+ if not p2p_device and "Vendor Specific Data: 330a" not in out:
raise Exception("Vendor element (non-P2P) not found from Association Request frame")
out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"),
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
+import binascii
import logging
logger = logging.getLogger()
+import struct
import time
-import threading
-import Queue
import os
import hostapd
import utils
from utils import HwsimSkip
from wpasupplicant import WpaSupplicant
+from p2p_utils import *
+from test_p2p_messages import parse_p2p_public_action, p2p_hdr, p2p_attr_capability, p2p_attr_go_intent, p2p_attr_config_timeout, p2p_attr_listen_channel, p2p_attr_intended_interface_addr, p2p_attr_channel_list, p2p_attr_device_info, p2p_attr_operating_channel, ie_p2p, ie_wsc, mgmt_tx, P2P_GO_NEG_REQ
-def check_grpform_results(i_res, r_res):
- if i_res['result'] != 'success' or r_res['result'] != 'success':
- raise Exception("Failed group formation")
- if i_res['ssid'] != r_res['ssid']:
- raise Exception("SSID mismatch")
- if i_res['freq'] != r_res['freq']:
- raise Exception("freq mismatch")
- if 'go_neg_freq' in r_res and i_res['go_neg_freq'] != r_res['go_neg_freq']:
- raise Exception("go_neg_freq mismatch")
- if i_res['freq'] != i_res['go_neg_freq']:
- raise Exception("freq/go_neg_freq mismatch")
- if i_res['role'] != i_res['go_neg_role']:
- raise Exception("role/go_neg_role mismatch")
- if 'go_neg_role' in r_res and r_res['role'] != r_res['go_neg_role']:
- raise Exception("role/go_neg_role mismatch")
- if i_res['go_dev_addr'] != r_res['go_dev_addr']:
- raise Exception("GO Device Address mismatch")
-
-def go_neg_init(i_dev, r_dev, pin, i_method, i_intent, res):
- logger.debug("Initiate GO Negotiation from i_dev")
- try:
- i_res = i_dev.p2p_go_neg_init(r_dev.p2p_dev_addr(), pin, i_method, timeout=20, go_intent=i_intent)
- logger.debug("i_res: " + str(i_res))
- except Exception, e:
- i_res = None
- logger.info("go_neg_init thread caught an exception from p2p_go_neg_init: " + str(e))
- res.put(i_res)
-
-def go_neg_pin(i_dev, r_dev, i_intent=None, r_intent=None, i_method='enter', r_method='display'):
- r_dev.p2p_listen()
- i_dev.p2p_listen()
- pin = r_dev.wps_read_pin()
- logger.info("Start GO negotiation " + i_dev.ifname + " -> " + r_dev.ifname)
- r_dev.dump_monitor()
- res = Queue.Queue()
- t = threading.Thread(target=go_neg_init, args=(i_dev, r_dev, pin, i_method, i_intent, res))
- t.start()
- logger.debug("Wait for GO Negotiation Request on r_dev")
- ev = r_dev.wait_global_event(["P2P-GO-NEG-REQUEST"], timeout=15)
- if ev is None:
- raise Exception("GO Negotiation timed out")
- r_dev.dump_monitor()
- logger.debug("Re-initiate GO Negotiation from r_dev")
- r_res = r_dev.p2p_go_neg_init(i_dev.p2p_dev_addr(), pin, r_method, go_intent=r_intent, timeout=20)
- logger.debug("r_res: " + str(r_res))
- r_dev.dump_monitor()
- t.join()
- i_res = res.get()
- if i_res is None:
- raise Exception("go_neg_init thread failed")
- logger.debug("i_res: " + str(i_res))
- logger.info("Group formed")
- hwsim_utils.test_connectivity_p2p(r_dev, i_dev)
- i_dev.dump_monitor()
- return [i_res, r_res]
-
-def go_neg_pin_authorized(i_dev, r_dev, i_intent=None, r_intent=None, expect_failure=False, i_go_neg_status=None, i_method='enter', r_method='display', test_data=True, i_freq=None, r_freq=None):
- i_dev.p2p_listen()
- pin = r_dev.wps_read_pin()
- logger.info("Start GO negotiation " + i_dev.ifname + " -> " + r_dev.ifname)
- r_dev.p2p_go_neg_auth(i_dev.p2p_dev_addr(), pin, r_method, go_intent=r_intent, freq=r_freq)
- r_dev.p2p_listen()
- i_res = i_dev.p2p_go_neg_init(r_dev.p2p_dev_addr(), pin, i_method, timeout=20, go_intent=i_intent, expect_failure=expect_failure, freq=i_freq)
- r_res = r_dev.p2p_go_neg_auth_result(expect_failure=expect_failure)
- logger.debug("i_res: " + str(i_res))
- logger.debug("r_res: " + str(r_res))
- r_dev.dump_monitor()
- i_dev.dump_monitor()
- if i_go_neg_status:
- if i_res['result'] != 'go-neg-failed':
- raise Exception("Expected GO Negotiation failure not reported")
- if i_res['status'] != i_go_neg_status:
- raise Exception("Expected GO Negotiation status not seen")
- if expect_failure:
- return
- logger.info("Group formed")
- if test_data:
- hwsim_utils.test_connectivity_p2p(r_dev, i_dev)
- return [i_res, r_res]
-
-def go_neg_init_pbc(i_dev, r_dev, i_intent, res, freq, provdisc):
- logger.debug("Initiate GO Negotiation from i_dev")
- try:
- i_res = i_dev.p2p_go_neg_init(r_dev.p2p_dev_addr(), None, "pbc",
- timeout=20, go_intent=i_intent, freq=freq,
- provdisc=provdisc)
- logger.debug("i_res: " + str(i_res))
- except Exception, e:
- i_res = None
- logger.info("go_neg_init_pbc thread caught an exception from p2p_go_neg_init: " + str(e))
- res.put(i_res)
-
-def go_neg_pbc(i_dev, r_dev, i_intent=None, r_intent=None, i_freq=None, r_freq=None, provdisc=False, r_listen=False):
- if r_listen:
- r_dev.p2p_listen()
- else:
- r_dev.p2p_find(social=True)
- i_dev.p2p_find(social=True)
- logger.info("Start GO negotiation " + i_dev.ifname + " -> " + r_dev.ifname)
- r_dev.dump_monitor()
- res = Queue.Queue()
- t = threading.Thread(target=go_neg_init_pbc, args=(i_dev, r_dev, i_intent, res, i_freq, provdisc))
- t.start()
- logger.debug("Wait for GO Negotiation Request on r_dev")
- ev = r_dev.wait_global_event(["P2P-GO-NEG-REQUEST"], timeout=15)
- if ev is None:
- raise Exception("GO Negotiation timed out")
- r_dev.dump_monitor()
- # Allow some time for the GO Neg Resp to go out before initializing new
- # GO Negotiation.
- time.sleep(0.2)
- logger.debug("Re-initiate GO Negotiation from r_dev")
- r_res = r_dev.p2p_go_neg_init(i_dev.p2p_dev_addr(), None, "pbc",
- go_intent=r_intent, timeout=20, freq=r_freq)
- logger.debug("r_res: " + str(r_res))
- r_dev.dump_monitor()
- t.join()
- i_res = res.get()
- if i_res is None:
- raise Exception("go_neg_init_pbc thread failed")
- logger.debug("i_res: " + str(i_res))
- logger.info("Group formed")
- hwsim_utils.test_connectivity_p2p(r_dev, i_dev)
- i_dev.dump_monitor()
- return [i_res, r_res]
-
-def go_neg_pbc_authorized(i_dev, r_dev, i_intent=None, r_intent=None,
- expect_failure=False, i_freq=None, r_freq=None):
- i_dev.p2p_listen()
- logger.info("Start GO negotiation " + i_dev.ifname + " -> " + r_dev.ifname)
- r_dev.p2p_go_neg_auth(i_dev.p2p_dev_addr(), None, "pbc",
- go_intent=r_intent, freq=r_freq)
- r_dev.p2p_listen()
- i_res = i_dev.p2p_go_neg_init(r_dev.p2p_dev_addr(), None, "pbc", timeout=20,
- go_intent=i_intent,
- expect_failure=expect_failure, freq=i_freq)
- r_res = r_dev.p2p_go_neg_auth_result(expect_failure=expect_failure)
- logger.debug("i_res: " + str(i_res))
- logger.debug("r_res: " + str(r_res))
- r_dev.dump_monitor()
- i_dev.dump_monitor()
- if expect_failure:
- return
- logger.info("Group formed")
- return [i_res, r_res]
-
-def remove_group(dev1, dev2):
- dev1.remove_group()
- try:
- dev2.remove_group()
- except:
- pass
-
+@remote_compatible
def test_grpform(dev):
"""P2P group formation using PIN and authorized connection (init -> GO)"""
try:
if "p2p-wlan" not in r_res['ifname']:
raise Exception("Unexpected group interface name")
check_grpform_results(i_res, r_res)
+ addr = dev[0].group_request("P2P_GROUP_MEMBER " + dev[1].p2p_dev_addr())
+ if "FAIL" in addr:
+ raise Exception("P2P_GROUP_MEMBER failed")
+ if addr != dev[1].p2p_interface_addr():
+ raise Exception("Unexpected P2P_GROUP_MEMBER result: " + addr)
+ if "FAIL" not in dev[0].group_request("P2P_GROUP_MEMBER a"):
+ raise Exception("Invalid P2P_GROUP_MEMBER command accepted")
+ if "FAIL" not in dev[0].group_request("P2P_GROUP_MEMBER 00:11:22:33:44:55"):
+ raise Exception("P2P_GROUP_MEMBER for non-member accepted")
remove_group(dev[0], dev[1])
if r_res['ifname'] in utils.get_ifnames():
raise Exception("Group interface netdev was not removed")
if r_res['ifname'] in utils.get_ifnames():
raise Exception("Group interface netdev was not removed")
+@remote_compatible
def test_grpform2(dev):
"""P2P group formation using PIN and authorized connection (resp -> GO)"""
go_neg_pin_authorized(i_dev=dev[0], i_intent=0, r_dev=dev[1], r_intent=15)
if r_res['ifname'] in utils.get_ifnames():
raise Exception("Group interface netdev was not removed")
+@remote_compatible
def test_grpform3(dev):
"""P2P group formation using PIN and re-init GO Negotiation"""
go_neg_pin(i_dev=dev[0], i_intent=15, r_dev=dev[1], r_intent=0)
if r_res['ifname'] in utils.get_ifnames():
raise Exception("Group interface netdev was not removed")
+@remote_compatible
def test_grpform4(dev):
"""P2P group formation response during p2p_find"""
addr1 = dev[1].p2p_dev_addr()
dev[1].p2p_stop_find()
dev[0].p2p_stop_find()
+@remote_compatible
def test_grpform_pbc(dev):
"""P2P group formation using PBC and re-init GO Negotiation"""
[i_res, r_res] = go_neg_pbc(i_dev=dev[0], i_intent=15, r_dev=dev[1], r_intent=0)
raise Exception("Unexpected device roles")
remove_group(dev[0], dev[1])
+@remote_compatible
def test_grpform_pd(dev):
"""P2P group formation with PD-before-GO-Neg workaround"""
[i_res, r_res] = go_neg_pbc(i_dev=dev[0], provdisc=True, r_dev=dev[1], r_listen=True)
if not found:
raise Exception("Could not discover peer that was supposed to use extended listen")
+@remote_compatible
def test_both_go_intent_15(dev):
"""P2P GO Negotiation with both devices using GO intent 15"""
go_neg_pin_authorized(i_dev=dev[0], i_intent=15, r_dev=dev[1], r_intent=15, expect_failure=True, i_go_neg_status=9)
+@remote_compatible
def test_both_go_neg_display(dev):
"""P2P GO Negotiation with both devices trying to display PIN"""
go_neg_pin_authorized(i_dev=dev[0], r_dev=dev[1], expect_failure=True, i_go_neg_status=10, i_method='display', r_method='display')
+@remote_compatible
def test_both_go_neg_enter(dev):
"""P2P GO Negotiation with both devices trying to enter PIN"""
go_neg_pin_authorized(i_dev=dev[0], r_dev=dev[1], expect_failure=True, i_go_neg_status=10, i_method='enter', r_method='enter')
+@remote_compatible
def test_go_neg_pbc_vs_pin(dev):
"""P2P GO Negotiation with one device using PBC and the other PIN"""
addr0 = dev[0].p2p_dev_addr()
if "status=10" not in ev:
raise Exception("Unexpected failure reason: " + ev)
+@remote_compatible
def test_go_neg_pin_vs_pbc(dev):
"""P2P GO Negotiation with one device using PIN and the other PBC"""
addr0 = dev[0].p2p_dev_addr()
dev[2].request("DISCONNECT")
dev[1].wait_go_ending_session()
+@remote_compatible
def test_grpform_force_chan_go(dev):
"""P2P group formation forced channel selection by GO"""
[i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=15,
raise Exception("Unexpected channel - did not follow GO's forced channel")
remove_group(dev[0], dev[1])
+@remote_compatible
def test_grpform_force_chan_cli(dev):
"""P2P group formation forced channel selection by client"""
[i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=0,
raise Exception("Unexpected channel - did not follow GO's forced channel")
remove_group(dev[0], dev[1])
+@remote_compatible
def test_grpform_force_chan_conflict(dev):
"""P2P group formation fails due to forced channel mismatch"""
go_neg_pin_authorized(i_dev=dev[0], i_intent=0, i_freq=2422,
r_dev=dev[1], r_intent=15, r_freq=2427,
expect_failure=True, i_go_neg_status=7)
+@remote_compatible
def test_grpform_pref_chan_go(dev):
"""P2P group formation preferred channel selection by GO"""
- dev[0].request("SET p2p_pref_chan 81:7")
- [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=15,
- r_dev=dev[1], r_intent=0,
- test_data=False)
- check_grpform_results(i_res, r_res)
- if i_res['freq'] != "2442":
- raise Exception("Unexpected channel - did not follow GO's p2p_pref_chan")
- remove_group(dev[0], dev[1])
+ try:
+ dev[0].request("SET p2p_pref_chan 81:7")
+ [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=15,
+ r_dev=dev[1], r_intent=0,
+ test_data=False)
+ check_grpform_results(i_res, r_res)
+ if i_res['freq'] != "2442":
+ raise Exception("Unexpected channel - did not follow GO's p2p_pref_chan")
+ remove_group(dev[0], dev[1])
+ finally:
+ dev[0].request("SET p2p_pref_chan ")
+@remote_compatible
def test_grpform_pref_chan_go_overridden(dev):
"""P2P group formation preferred channel selection by GO overridden by client"""
- dev[1].request("SET p2p_pref_chan 81:7")
- [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=0,
- i_freq=2422,
- r_dev=dev[1], r_intent=15,
- test_data=False)
- check_grpform_results(i_res, r_res)
- if i_res['freq'] != "2422":
- raise Exception("Unexpected channel - did not follow client's forced channel")
- remove_group(dev[0], dev[1])
+ try:
+ dev[1].request("SET p2p_pref_chan 81:7")
+ [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=0,
+ i_freq=2422,
+ r_dev=dev[1], r_intent=15,
+ test_data=False)
+ check_grpform_results(i_res, r_res)
+ if i_res['freq'] != "2422":
+ raise Exception("Unexpected channel - did not follow client's forced channel")
+ remove_group(dev[0], dev[1])
+ finally:
+ dev[1].request("SET p2p_pref_chan ")
+@remote_compatible
def test_grpform_no_go_freq_forcing_chan(dev):
"""P2P group formation with no-GO freq forcing channel"""
- dev[1].request("SET p2p_no_go_freq 100-200,300,4000-6000")
- [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=0,
- r_dev=dev[1], r_intent=15,
- test_data=False)
- check_grpform_results(i_res, r_res)
- if int(i_res['freq']) > 4000:
- raise Exception("Unexpected channel - did not follow no-GO freq")
- remove_group(dev[0], dev[1])
+ try:
+ dev[1].request("SET p2p_no_go_freq 100-200,300,4000-6000")
+ [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=0,
+ r_dev=dev[1], r_intent=15,
+ test_data=False)
+ check_grpform_results(i_res, r_res)
+ if int(i_res['freq']) > 4000:
+ raise Exception("Unexpected channel - did not follow no-GO freq")
+ remove_group(dev[0], dev[1])
+ finally:
+ dev[1].request("SET p2p_no_go_freq ")
+@remote_compatible
def test_grpform_no_go_freq_conflict(dev):
"""P2P group formation fails due to no-GO range forced by client"""
- dev[1].request("SET p2p_no_go_freq 2000-3000")
- go_neg_pin_authorized(i_dev=dev[0], i_intent=0, i_freq=2422,
- r_dev=dev[1], r_intent=15,
- expect_failure=True, i_go_neg_status=7)
+ try:
+ dev[1].request("SET p2p_no_go_freq 2000-3000")
+ go_neg_pin_authorized(i_dev=dev[0], i_intent=0, i_freq=2422,
+ r_dev=dev[1], r_intent=15,
+ expect_failure=True, i_go_neg_status=7)
+ finally:
+ dev[1].request("SET p2p_no_go_freq ")
+@remote_compatible
def test_grpform_no_5ghz_world_roaming(dev):
"""P2P group formation with world roaming regulatory"""
[i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=0,
raise Exception("Unexpected channel - did not follow world roaming rules")
remove_group(dev[0], dev[1])
+@remote_compatible
def test_grpform_no_5ghz_add_cli(dev):
"""P2P group formation with passive scan 5 GHz and p2p_add_cli_chan=1"""
- dev[0].request("SET p2p_add_cli_chan 1")
- dev[1].request("SET p2p_add_cli_chan 1")
- [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=0,
- r_dev=dev[1], r_intent=14,
- test_data=False)
- check_grpform_results(i_res, r_res)
- if int(i_res['freq']) > 4000:
- raise Exception("Unexpected channel - did not follow world roaming rules")
- remove_group(dev[0], dev[1])
+ try:
+ dev[0].request("SET p2p_add_cli_chan 1")
+ dev[1].request("SET p2p_add_cli_chan 1")
+ [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=0,
+ r_dev=dev[1], r_intent=14,
+ test_data=False)
+ check_grpform_results(i_res, r_res)
+ if int(i_res['freq']) > 4000:
+ raise Exception("Unexpected channel - did not follow world roaming rules")
+ remove_group(dev[0], dev[1])
+ finally:
+ dev[0].request("SET p2p_add_cli_chan 0")
+ dev[1].request("SET p2p_add_cli_chan 0")
+@remote_compatible
def test_grpform_no_5ghz_add_cli2(dev):
"""P2P group formation with passive scan 5 GHz and p2p_add_cli_chan=1 (reverse)"""
- dev[0].request("SET p2p_add_cli_chan 1")
- dev[1].request("SET p2p_add_cli_chan 1")
- [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=14,
- r_dev=dev[1], r_intent=0,
- test_data=False)
- check_grpform_results(i_res, r_res)
- if int(i_res['freq']) > 4000:
- raise Exception("Unexpected channel - did not follow world roaming rules")
- remove_group(dev[0], dev[1])
+ try:
+ dev[0].request("SET p2p_add_cli_chan 1")
+ dev[1].request("SET p2p_add_cli_chan 1")
+ [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=14,
+ r_dev=dev[1], r_intent=0,
+ test_data=False)
+ check_grpform_results(i_res, r_res)
+ if int(i_res['freq']) > 4000:
+ raise Exception("Unexpected channel - did not follow world roaming rules")
+ remove_group(dev[0], dev[1])
+ finally:
+ dev[0].request("SET p2p_add_cli_chan 0")
+ dev[1].request("SET p2p_add_cli_chan 0")
+@remote_compatible
def test_grpform_no_5ghz_add_cli3(dev):
"""P2P group formation with passive scan 5 GHz and p2p_add_cli_chan=1 (intent 15)"""
- dev[0].request("SET p2p_add_cli_chan 1")
- dev[1].request("SET p2p_add_cli_chan 1")
- [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=0,
- r_dev=dev[1], r_intent=15,
- test_data=False)
- check_grpform_results(i_res, r_res)
- if int(i_res['freq']) > 4000:
- raise Exception("Unexpected channel - did not follow world roaming rules")
- remove_group(dev[0], dev[1])
+ try:
+ dev[0].request("SET p2p_add_cli_chan 1")
+ dev[1].request("SET p2p_add_cli_chan 1")
+ [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=0,
+ r_dev=dev[1], r_intent=15,
+ test_data=False)
+ check_grpform_results(i_res, r_res)
+ if int(i_res['freq']) > 4000:
+ raise Exception("Unexpected channel - did not follow world roaming rules")
+ remove_group(dev[0], dev[1])
+ finally:
+ dev[0].request("SET p2p_add_cli_chan 0")
+ dev[1].request("SET p2p_add_cli_chan 0")
+@remote_compatible
def test_grpform_no_5ghz_add_cli4(dev):
"""P2P group formation with passive scan 5 GHz and p2p_add_cli_chan=1 (reverse; intent 15)"""
- dev[0].request("SET p2p_add_cli_chan 1")
- dev[1].request("SET p2p_add_cli_chan 1")
- [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=15,
- r_dev=dev[1], r_intent=0,
- test_data=False)
- check_grpform_results(i_res, r_res)
- if int(i_res['freq']) > 4000:
- raise Exception("Unexpected channel - did not follow world roaming rules")
- remove_group(dev[0], dev[1])
+ try:
+ dev[0].request("SET p2p_add_cli_chan 1")
+ dev[1].request("SET p2p_add_cli_chan 1")
+ [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=15,
+ r_dev=dev[1], r_intent=0,
+ test_data=False)
+ check_grpform_results(i_res, r_res)
+ if int(i_res['freq']) > 4000:
+ raise Exception("Unexpected channel - did not follow world roaming rules")
+ remove_group(dev[0], dev[1])
+ finally:
+ dev[0].request("SET p2p_add_cli_chan 0")
+ dev[1].request("SET p2p_add_cli_chan 0")
+@remote_compatible
def test_grpform_incorrect_pin(dev):
"""P2P GO Negotiation with incorrect PIN"""
dev[1].p2p_listen()
if ev is None:
raise Exception("Group formation failure timed out")
+@remote_compatible
def test_grpform_reject(dev):
"""User rejecting group formation attempt by a P2P peer"""
addr0 = dev[0].p2p_dev_addr()
raise Exception("P2P_REJECT failed")
dev[1].request("P2P_STOP_FIND")
dev[1].p2p_go_neg_init(addr0, None, "pbc")
- ev = dev[1].wait_global_event(["GO-NEG-FAILURE"], timeout=10)
+ ev = dev[1].wait_global_event(["P2P-GO-NEG-FAILURE"], timeout=10)
if ev is None:
raise Exception("Rejection not reported")
if "status=11" not in ev:
raise Exception("Unexpected status code in rejection")
+@remote_compatible
def test_grpform_pd_no_probe_resp(dev):
"""GO Negotiation after PD, but no Probe Response"""
addr0 = dev[0].p2p_dev_addr()
if ev is None:
raise Exception("timeout on GO Neg RX event")
dev[2].request("P2P_CONNECT " + addr0 + " pbc")
- ev = dev[2].wait_global_event(["GO-NEG-FAILURE"], timeout=10)
+ ev = dev[2].wait_global_event(["P2P-GO-NEG-FAILURE"], timeout=10)
if ev is None:
raise Exception("Rejection not reported")
if "status=5" not in ev:
raise Exception("Unexpected status code in rejection: " + ev)
-def clear_pbc_overlap(dev, ifname):
- hapd_global = hostapd.HostapdGlobal()
- hapd_global.remove(ifname)
+def clear_pbc_overlap(dev, ap):
+ hostapd.remove_bss(ap)
dev[0].request("P2P_CANCEL")
dev[1].request("P2P_CANCEL")
dev[0].p2p_stop_find()
dev[1].flush_scan_cache()
time.sleep(0.1)
+@remote_compatible
def test_grpform_pbc_overlap(dev, apdev):
"""P2P group formation during PBC overlap"""
params = { "ssid": "wps", "eap_server": "1", "wps_state": "1" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
hapd.request("WPS_PBC")
time.sleep(0.1)
if ev is None:
raise Exception("PBC overlap not reported")
- clear_pbc_overlap(dev, apdev[0]['ifname'])
+ clear_pbc_overlap(dev, apdev[0])
+@remote_compatible
def test_grpform_pbc_overlap_group_iface(dev, apdev):
"""P2P group formation during PBC overlap using group interfaces"""
# Note: Need to include P2P IE from the AP to get the P2P interface BSS
# update use this information.
params = { "ssid": "wps", "eap_server": "1", "wps_state": "1",
"beacon_int": "15", 'manage_p2p': '1' }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
hapd.request("WPS_PBC")
dev[0].request("SET p2p_no_group_iface 0")
# the group interface.
logger.info("PBC overlap not reported")
- clear_pbc_overlap(dev, apdev[0]['ifname'])
+ clear_pbc_overlap(dev, apdev[0])
+@remote_compatible
def test_grpform_goneg_fail_with_group_iface(dev):
"""P2P group formation fails while using group interface"""
dev[0].request("SET p2p_no_group_iface 0")
if mode != "P2P GO - group formation":
raise Exception("Unexpected mode on GO during group formation: " + mode)
+@remote_compatible
def test_grpform_wait_peer(dev):
"""P2P group formation wait for peer to become ready"""
addr0 = dev[0].p2p_dev_addr()
raise Exception("Group formation timed out")
dev[0].remove_group()
+@remote_compatible
def test_invalid_p2p_connect_command(dev):
"""P2P_CONNECT error cases"""
id = dev[0].add_network()
if "FAIL-CHANNEL-UNSUPPORTED" not in dev[0].request("P2P_CONNECT 00:11:22:33:44:55 pin freq=3000"):
raise Exception("Unsupported channel not reported")
+@remote_compatible
def test_p2p_unauthorize(dev):
"""P2P_UNAUTHORIZE to unauthorize a peer"""
if "FAIL" not in dev[0].request("P2P_UNAUTHORIZE foo"):
if ev is None:
raise Exception("No GO Negotiation Request RX reported")
+@remote_compatible
def test_grpform_pbc_multiple(dev):
"""P2P group formation using PBC multiple times in a row"""
try:
raise Exception("Unexpected peer discovered: " + ev)
for i in range(3):
dev[i].p2p_stop_find()
+
+@remote_compatible
+def test_grpform_and_scan(dev):
+ """GO Negotiation and scan operations"""
+ addr0 = dev[0].p2p_dev_addr()
+ addr1 = dev[1].p2p_dev_addr()
+ dev[1].p2p_listen()
+ if not dev[0].discover_peer(addr1):
+ raise Exception("Could not discover peer")
+ dev[0].p2p_stop_find()
+ dev[1].p2p_stop_find()
+
+ if "OK" not in dev[0].request("SCAN TYPE=ONLY freq=2412-2472"):
+ raise Exception("Could not start scan")
+ ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
+ if ev is None:
+ raise Exception("Scan did not start")
+ time.sleep(0.1)
+ # Request PD while the previously started scan is still in progress
+ if "OK" not in dev[0].request("P2P_PROV_DISC %s pbc" % addr1):
+ raise Exception("Could not request PD")
+ ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
+ if ev is None:
+ raise Exception("Scan did not complete")
+ time.sleep(0.3)
+
+ dev[1].p2p_listen()
+ ev = dev[0].wait_global_event(["P2P-PROV-DISC-PBC-RESP"], timeout=5)
+ if ev is None:
+ raise Exception("PD Response not received")
+
+ if "OK" not in dev[0].request("SCAN TYPE=ONLY freq=2412-2472"):
+ raise Exception("Could not start scan")
+ ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
+ if ev is None:
+ raise Exception("Scan did not start")
+ time.sleep(0.1)
+ # Request GO Neg while the previously started scan is still in progress
+ if "OK" not in dev[0].request("P2P_CONNECT %s pbc" % addr1):
+ raise Exception("Could not request GO Negotiation")
+ ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
+ if ev is None:
+ raise Exception("Scan did not complete")
+
+ ev = dev[1].wait_global_event(["P2P-GO-NEG-REQUEST"], timeout=10)
+ if ev is None:
+ raise Exception("GO Neg Req RX not reported")
+
+ dev[1].p2p_stop_find()
+
+ if "OK" not in dev[1].request("SCAN TYPE=ONLY freq=2412-2472"):
+ raise Exception("Could not start scan")
+ ev = dev[1].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
+ if ev is None:
+ raise Exception("Scan did not start")
+ time.sleep(0.1)
+ dev[1].global_request("P2P_CONNECT " + addr0 + " pbc")
+ ev = dev[1].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
+ if ev is None:
+ raise Exception("Scan did not complete")
+
+ ev0 = dev[0].wait_global_event(["P2P-GROUP-STARTED"], timeout=15)
+ if ev0 is None:
+ raise Exception("Group formation timed out on dev0")
+ dev[0].group_form_result(ev0)
+
+ ev1 = dev[1].wait_global_event(["P2P-GROUP-STARTED"], timeout=15)
+ if ev1 is None:
+ raise Exception("Group formation timed out on dev1")
+ dev[1].group_form_result(ev1)
+
+ dev[0].dump_monitor()
+ dev[1].dump_monitor()
+
+ remove_group(dev[0], dev[1])
+
+ dev[0].dump_monitor()
+ dev[1].dump_monitor()
+
+def test_grpform_go_neg_dup_on_restart(dev):
+ """Duplicated GO Negotiation Request after GO Neg restart"""
+ if dev[0].p2p_dev_addr() > dev[1].p2p_dev_addr():
+ higher = dev[0]
+ lower = dev[1]
+ else:
+ higher = dev[1]
+ lower = dev[0]
+ addr_low = lower.p2p_dev_addr()
+ addr_high = higher.p2p_dev_addr()
+ higher.p2p_listen()
+ if not lower.discover_peer(addr_high):
+ raise Exception("Could not discover peer")
+ lower.p2p_stop_find()
+
+ if "OK" not in lower.request("P2P_CONNECT %s pbc" % addr_high):
+ raise Exception("Could not request GO Negotiation")
+ ev = higher.wait_global_event(["P2P-GO-NEG-REQUEST"], timeout=10)
+ if ev is None:
+ raise Exception("GO Neg Req RX not reported")
+
+ # Wait for GO Negotiation Response (Status=1) to go through
+ time.sleep(0.2)
+
+ if "FAIL" in lower.request("SET ext_mgmt_frame_handling 1"):
+ raise Exception("Failed to enable external management frame handling")
+
+ higher.p2p_stop_find()
+ higher.global_request("P2P_CONNECT " + addr_low + " pbc")
+
+ # Wait for the GO Negotiation Request frame of the restarted GO Negotiation
+ rx_msg = lower.mgmt_rx()
+ if rx_msg is None:
+ raise Exception("MGMT-RX timeout")
+ p2p = parse_p2p_public_action(rx_msg['payload'])
+ if p2p is None:
+ raise Exception("Not a P2P Public Action frame")
+ if p2p['subtype'] != 0:
+ raise Exception("Unexpected P2P Public Action subtype %d" % p2p['subtype'])
+
+ # Send duplicate GO Negotiation Request from the prior instance of GO
+ # Negotiation
+ lower.p2p_stop_find()
+ peer = higher.get_peer(addr_low)
+
+ msg = p2p_hdr(addr_high, addr_low, type=P2P_GO_NEG_REQ, dialog_token=123)
+ attrs = p2p_attr_capability(dev_capab=0x25, group_capab=0x08)
+ attrs += p2p_attr_go_intent(go_intent=7, tie_breaker=1)
+ attrs += p2p_attr_config_timeout()
+ attrs += p2p_attr_listen_channel(chan=(int(peer['listen_freq']) - 2407) / 5)
+ attrs += p2p_attr_intended_interface_addr(lower.p2p_dev_addr())
+ attrs += p2p_attr_channel_list()
+ attrs += p2p_attr_device_info(addr_low, config_methods=0x80, name="Device A")
+ attrs += p2p_attr_operating_channel()
+ wsc_attrs = struct.pack(">HHH", 0x1012, 2, 4)
+ msg['payload'] += ie_p2p(attrs) + ie_wsc(wsc_attrs)
+ mgmt_tx(lower, "MGMT_TX {} {} freq={} wait_time=200 no_cck=1 action={}".format(addr_high, addr_high, peer['listen_freq'], binascii.hexlify(msg['payload'])))
+
+ # Wait for the GO Negotiation Response frame which would have been sent in
+ # this case previously, but not anymore after the check for
+ # dev->go_neg_req_sent and dev->flags & P2P_DEV_PEER_WAITING_RESPONSE.
+ rx_msg = lower.mgmt_rx(timeout=0.2)
+ if rx_msg is not None:
+ raise Exception("Unexpected management frame")
+
+ if "FAIL" in lower.request("SET ext_mgmt_frame_handling 0"):
+ raise Exception("Failed to disable external management frame handling")
+ lower.p2p_listen()
+
+ ev = lower.wait_global_event(["P2P-GO-NEG-SUCCESS"], timeout=10)
+ if ev is None:
+ raise Exception("GO Negotiation did not succeed on dev0")
+
+ ev = higher.wait_global_event(["P2P-GO-NEG-SUCCESS"], timeout=10)
+ if ev is None:
+ raise Exception("GO Negotiation did not succeed on dev1")
+
+ ev0 = lower.wait_global_event(["P2P-GROUP-STARTED"], timeout=15)
+ if ev0 is None:
+ raise Exception("Group formation timed out on dev0")
+ lower.group_form_result(ev0)
+
+ ev1 = higher.wait_global_event(["P2P-GROUP-STARTED"], timeout=15)
+ if ev1 is None:
+ raise Exception("Group formation timed out on dev1")
+ higher.group_form_result(ev1)
+
+ lower.dump_monitor()
+ higher.dump_monitor()
+
+ remove_group(lower, higher)
+
+ lower.dump_monitor()
+ higher.dump_monitor()
+
+@remote_compatible
+def test_grpform_go_neg_stopped(dev):
+ """GO Negotiation stopped after TX start"""
+ addr0 = dev[0].p2p_dev_addr()
+ dev[0].p2p_listen()
+ if not dev[1].discover_peer(addr0):
+ raise Exception("Could not discover peer")
+ dev[0].p2p_stop_find()
+ if "OK" not in dev[1].request("P2P_CONNECT %s pbc" % addr0):
+ raise Exception("Could not request GO Negotiation")
+ dev[1].p2p_stop_find()
+ dev[1].p2p_listen()
+ dev[0].p2p_find(social=True)
+ ev = dev[0].wait_global_event(["P2P-DEVICE-FOUND"], timeout=1.2)
+ dev[0].p2p_stop_find()
+ dev[1].p2p_stop_find()
+ if ev is None:
+ raise Exception("Did not find peer quickly enough after stopped P2P_CONNECT")
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import logging
logger = logging.getLogger()
import hwsim_utils
+@remote_compatible
def test_p2p_go_invite(dev):
"""P2P GO inviting a client to join"""
addr0 = dev[0].p2p_dev_addr()
dev[0].remove_group()
dev[1].wait_go_ending_session()
+@remote_compatible
def test_p2p_go_invite_auth(dev):
"""P2P GO inviting a client to join (authorized invitation)"""
addr0 = dev[0].p2p_dev_addr()
dev[0].remove_group()
dev[1].wait_go_ending_session()
+@remote_compatible
def test_p2p_go_invite_unknown(dev):
"""P2P GO inviting a client that has not discovered the GO"""
try:
dev[1].wait_go_ending_session()
dev[2].wait_go_ending_session()
+@remote_compatible
def test_p2p_invite_invalid(dev):
"""Invalid parameters to P2P_INVITE"""
id = dev[0].add_network()
# P2P protocol tests for various messages
-# Copyright (c) 2014, Jouni Malinen <j@w1.fi>
+# 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.
+from remotehost import remote_compatible
import binascii
import struct
import time
logger = logging.getLogger()
import hostapd
-from test_p2p_persistent import form
-from test_p2p_persistent import invite
-
-MGMT_SUBTYPE_PROBE_REQ = 4
-MGMT_SUBTYPE_ACTION = 13
-ACTION_CATEG_PUBLIC = 4
-
-P2P_GO_NEG_REQ = 0
-P2P_GO_NEG_RESP = 1
-P2P_GO_NEG_CONF = 2
-P2P_INVITATION_REQ = 3
-P2P_INVITATION_RESP = 4
-P2P_DEV_DISC_REQ = 5
-P2P_DEV_DISC_RESP = 6
-P2P_PROV_DISC_REQ = 7
-P2P_PROV_DISC_RESP = 8
-
-P2P_ATTR_STATUS = 0
-P2P_ATTR_MINOR_REASON_CODE = 1
-P2P_ATTR_CAPABILITY = 2
-P2P_ATTR_DEVICE_ID = 3
-P2P_ATTR_GROUP_OWNER_INTENT = 4
-P2P_ATTR_CONFIGURATION_TIMEOUT = 5
-P2P_ATTR_LISTEN_CHANNEL = 6
-P2P_ATTR_GROUP_BSSID = 7
-P2P_ATTR_EXT_LISTEN_TIMING = 8
-P2P_ATTR_INTENDED_INTERFACE_ADDR = 9
-P2P_ATTR_MANAGEABILITY = 10
-P2P_ATTR_CHANNEL_LIST = 11
-P2P_ATTR_NOTICE_OF_ABSENCE = 12
-P2P_ATTR_DEVICE_INFO = 13
-P2P_ATTR_GROUP_INFO = 14
-P2P_ATTR_GROUP_ID = 15
-P2P_ATTR_INTERFACE = 16
-P2P_ATTR_OPERATING_CHANNEL = 17
-P2P_ATTR_INVITATION_FLAGS = 18
-P2P_ATTR_OOB_GO_NEG_CHANNEL = 19
-P2P_ATTR_SERVICE_HASH = 21
-P2P_ATTR_SESSION_INFORMATION_DATA = 22
-P2P_ATTR_CONNECTION_CAPABILITY = 23
-P2P_ATTR_ADVERTISEMENT_ID = 24
-P2P_ATTR_ADVERTISED_SERVICE = 25
-P2P_ATTR_SESSION_ID = 26
-P2P_ATTR_FEATURE_CAPABILITY = 27
-P2P_ATTR_PERSISTENT_GROUP = 28
-P2P_ATTR_VENDOR_SPECIFIC = 221
-
-P2P_SC_SUCCESS = 0
-P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE = 1
-P2P_SC_FAIL_INCOMPATIBLE_PARAMS = 2
-P2P_SC_FAIL_LIMIT_REACHED = 3
-P2P_SC_FAIL_INVALID_PARAMS = 4
-P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE = 5
-P2P_SC_FAIL_PREV_PROTOCOL_ERROR = 6
-P2P_SC_FAIL_NO_COMMON_CHANNELS = 7
-P2P_SC_FAIL_UNKNOWN_GROUP = 8
-P2P_SC_FAIL_BOTH_GO_INTENT_15 = 9
-P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD = 10
-P2P_SC_FAIL_REJECTED_BY_USER = 11
-
-WSC_ATTR_CONFIG_METHODS = 0x1008
-
-WLAN_EID_SSID = 0
-WLAN_EID_SUPP_RATES = 1
-WLAN_EID_VENDOR_SPECIFIC = 221
+from p2p_utils import *
+from test_gas import anqp_adv_proto
def ie_ssid(ssid):
return struct.pack("<BB", WLAN_EID_SSID, len(ssid)) + ssid
def p2p_attr_device_info(addr, name="Test", config_methods=0, dev_type="00010050F2040001"):
val = struct.unpack('6B', binascii.unhexlify(addr.replace(':','')))
val2 = struct.unpack('8B', binascii.unhexlify(dev_type))
- t = (P2P_ATTR_DEVICE_INFO, 6 + 2 + 8 + 1 + 4 + len(name)) + val + (config_methods,) + val2 + (0,)
- return struct.pack("<BH6BH8BB", *t) + struct.pack('>HH', 0x1011, len(name)) +name
+ t = (P2P_ATTR_DEVICE_INFO, 6 + 2 + 8 + 1 + 4 + len(name)) + val
+ t2 = val2 + (0,)
+ return struct.pack("<BH6B", *t) + struct.pack(">H", config_methods) + struct.pack("8BB", *t2) + struct.pack('>HH', 0x1011, len(name)) +name
def p2p_attr_group_id(addr, ssid):
val = struct.unpack('6B', binascii.unhexlify(addr.replace(':','')))
params['channel'] = '6'
elif peer['listen_freq'] == "2462":
params['channel'] = '11'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
hapd.set("ext_mgmt_frame_handling", "1")
return addr0, bssid, hapd, int(params['channel'])
return p2p
+@remote_compatible
def test_p2p_msg_empty(dev, apdev):
"""P2P protocol test: empty P2P Public Action frame"""
dst, src, hapd, channel = start_p2p(dev, apdev)
msg = p2p_hdr(dst, src)
hapd.mgmt_tx(msg)
+@remote_compatible
def test_p2p_msg_long_ssid(dev, apdev):
"""P2P protocol test: Too long SSID in P2P Public Action frame"""
dst, src, hapd, channel = start_p2p(dev, apdev)
msg['payload'] += ie_p2p(attrs)
msg['payload'] += ie_ssid(255 * 'A')
hapd.mgmt_tx(msg)
- ev = dev[0].wait_event(["P2P-DEVICE-FOUND"], timeout=5)
+ ev = dev[0].wait_global_event(["P2P-DEVICE-FOUND"], timeout=5)
if ev is None:
raise Exception("Timeout on device found event")
+@remote_compatible
def test_p2p_msg_long_dev_name(dev, apdev):
"""P2P protocol test: Too long Device Name in P2P Public Action frame"""
dst, src, hapd, channel = start_p2p(dev, apdev)
if p2p['p2p_status'] != 7 and dev[1].get_mcc() <= 1:
raise Exception("Unexpected status %d" % p2p['p2p_status'])
+@remote_compatible
def test_p2p_msg_invitation_req_unknown(dev, apdev):
"""P2P protocol tests for invitation request from unknown peer"""
dst, src, hapd, channel = start_p2p(dev, apdev)
if hapd.mgmt_rx(timeout=1) is None:
raise Exception("No invitation response " + str(dialog_token))
+@remote_compatible
def test_p2p_msg_invitation_no_common_channels(dev, apdev):
"""P2P protocol tests for invitation request without common channels"""
dst, src, hapd, channel = start_p2p(dev, apdev)
msg['payload'] += ie_p2p(attrs)
mgmt_tx(dev[1], "MGMT_TX {} {} freq={} wait_time=200 no_cck=1 action={}".format(addr0, addr0, rx_msg['freq'], binascii.hexlify(msg['payload'])))
- ev = dev[0].wait_global_event(["P2P-GROUP-STARTED"], timeout=15);
+ ev = dev[0].wait_global_event(["P2P-GROUP-STARTED"], timeout=15)
if ev is None:
raise Exception("Group was not started")
mgmt_tx(dev[1], "MGMT_TX {} {} freq={} wait_time=200 no_cck=1 action={}".format(addr0, addr0, rx_msg['freq'], binascii.hexlify(msg['payload'])))
ev = dev[0].wait_global_event(["P2P-INVITATION-RESULT"], timeout=15)
if ev is None:
- raise Exception("Timeout on invitation result");
+ raise Exception("Timeout on invitation result")
if "status=7" not in ev:
raise Exception("Unexpected invitation result: " + ev)
- logger.info("Any channel allowed, only preference provided in invitation");
+ logger.info("Any channel allowed, only preference provided in invitation")
invite(dev[0], dev[1], extra="pref=2422")
rx_msg = dev[1].mgmt_rx()
if rx_msg is None:
mgmt_tx(dev[1], "MGMT_TX {} {} freq={} wait_time=200 no_cck=1 action={}".format(addr0, addr0, rx_msg['freq'], binascii.hexlify(msg['payload'])))
ev = dev[0].wait_global_event(["P2P-INVITATION-RESULT"], timeout=15)
if ev is None:
- raise Exception("Timeout on invitation result");
+ raise Exception("Timeout on invitation result")
if "status=0" not in ev:
raise Exception("Unexpected invitation result: " + ev)
- ev = dev[0].wait_global_event(["P2P-GROUP-STARTED"], timeout=15);
+ ev = dev[0].wait_global_event(["P2P-GROUP-STARTED"], timeout=15)
if ev is None:
raise Exception("Group was not started on dev0")
- ev = dev[1].wait_global_event(["P2P-GROUP-STARTED"], timeout=15);
+ ev = dev[1].wait_global_event(["P2P-GROUP-STARTED"], timeout=15)
if ev is None:
raise Exception("Group was not started on dev1")
if "FAIL" in dev[1].request("SET ext_mgmt_frame_handling 1"):
raise Exception("Failed to enable external management frame handling")
- logger.info("Any channel allowed, only preference provided in invitation");
+ logger.info("Any channel allowed, only preference provided in invitation")
invite(dev[0], dev[1], extra="pref=2422")
rx_msg = dev[1].mgmt_rx()
if rx_msg is None:
ev = dev[0].wait_global_event(["P2P-INVITATION-RESULT"], timeout=10)
if ev is None:
- raise Exception("Timeout on invitation result");
+ raise Exception("Timeout on invitation result")
if "status=0" not in ev:
raise Exception("Unexpected invitation result: " + ev)
ev = dev[0].wait_global_event(["P2P-GROUP-STARTED"], timeout=10)
dev[0].group_form_result(ev)
dev[0].remove_group()
+@remote_compatible
def test_p2p_msg_pd_req(dev, apdev):
"""P2P protocol tests for provision discovery request processing"""
dst, src, hapd, channel = start_p2p(dev, apdev)
ev = dev[0].wait_global_event(["P2P-GO-NEG-SUCCESS"], timeout=10)
if ev is None:
raise Exception("GO Neg did not succeed")
- ev = dev[0].wait_global_event(["P2P-GROUP-STARTED"], timeout=5);
+ ev = dev[0].wait_global_event(["P2P-GROUP-STARTED"], timeout=5)
if ev is None:
raise Exception("Group formation not succeed")
- ev = dev[1].wait_global_event(["P2P-GROUP-STARTED"], timeout=5);
+ ev = dev[1].wait_global_event(["P2P-GROUP-STARTED"], timeout=5)
if ev is None:
raise Exception("Group formation not succeed")
mgmt_tx(dev[0], "MGMT_TX {} {} freq={} wait_time=200 no_cck=1 action={}".format(addr1, addr1, p2p['freq'], binascii.hexlify(msg['payload'])))
check_p2p_go_neg_fail_event(dev[1], P2P_SC_FAIL_NO_COMMON_CHANNELS)
rx_go_neg_conf(dev[0], P2P_SC_FAIL_NO_COMMON_CHANNELS, dialog_token)
+
+def test_p2p_msg_group_info(dev):
+ """P2P protocol tests for Group Info parsing"""
+ try:
+ _test_p2p_msg_group_info(dev)
+ finally:
+ dev[0].request("VENDOR_ELEM_REMOVE 2 *")
+
+def _test_p2p_msg_group_info(dev):
+ tests = [ "dd08506f9a090e010001",
+ "dd08506f9a090e010000",
+ "dd20506f9a090e190018" + "112233445566" + "aabbccddeeff" + "00" + "0000" + "0000000000000000" + "ff",
+ "dd20506f9a090e190018" + "112233445566" + "aabbccddeeff" + "00" + "0000" + "0000000000000000" + "00",
+ "dd24506f9a090e1d001c" + "112233445566" + "aabbccddeeff" + "00" + "0000" + "0000000000000000" + "00" + "00000000",
+ "dd24506f9a090e1d001c" + "112233445566" + "aabbccddeeff" + "00" + "0000" + "0000000000000000" + "00" + "10110001",
+ "dd24506f9a090e1d001c" + "112233445566" + "aabbccddeeff" + "00" + "0000" + "0000000000000000" + "00" + "1011ffff" ]
+ for t in tests:
+ dev[0].request("VENDOR_ELEM_REMOVE 2 *")
+ if "OK" not in dev[0].request("VENDOR_ELEM_ADD 2 " + t):
+ raise Exception("VENDOR_ELEM_ADD failed")
+ dev[0].p2p_start_go(freq=2412)
+ bssid = dev[0].get_group_status_field('bssid')
+ dev[2].request("BSS_FLUSH 0")
+ dev[2].scan_for_bss(bssid, freq=2412, force_scan=True)
+ bss = dev[2].request("BSS " + bssid)
+ if 'p2p_group_client' in bss:
+ raise Exception("Unexpected p2p_group_client")
+ dev[0].remove_group()
+
+MGMT_SUBTYPE_ACTION = 13
+ACTION_CATEG_PUBLIC = 4
+
+GAS_INITIAL_REQUEST = 10
+GAS_INITIAL_RESPONSE = 11
+GAS_COMEBACK_REQUEST = 12
+GAS_COMEBACK_RESPONSE = 13
+
+def gas_hdr(dst, src, type, req=True, dialog_token=0):
+ msg = {}
+ msg['fc'] = MGMT_SUBTYPE_ACTION << 4
+ msg['da'] = dst
+ msg['sa'] = src
+ if req:
+ msg['bssid'] = dst
+ else:
+ msg['bssid'] = src
+ if dialog_token is None:
+ msg['payload'] = struct.pack("<BB", ACTION_CATEG_PUBLIC, type)
+ else:
+ msg['payload'] = struct.pack("<BBB", ACTION_CATEG_PUBLIC, type,
+ dialog_token)
+ return msg
+
+@remote_compatible
+def test_p2p_msg_sd(dev, apdev):
+ """P2P protocol tests for service discovery messages"""
+ dst, src, hapd, channel = start_p2p(dev, apdev)
+
+ logger.debug("Truncated GAS Initial Request - no Dialog Token field")
+ msg = gas_hdr(dst, src, GAS_INITIAL_REQUEST, dialog_token=None)
+ hapd.mgmt_tx(msg)
+
+ logger.debug("Truncated GAS Initial Request - no Advertisement Protocol element")
+ msg = gas_hdr(dst, src, GAS_INITIAL_REQUEST)
+ hapd.mgmt_tx(msg)
+
+ logger.debug("Truncated GAS Initial Request - no Advertisement Protocol element length")
+ msg = gas_hdr(dst, src, GAS_INITIAL_REQUEST)
+ msg['payload'] += struct.pack('B', 108)
+ hapd.mgmt_tx(msg)
+
+ logger.debug("Invalid GAS Initial Request - unexpected IE")
+ msg = gas_hdr(dst, src, GAS_INITIAL_REQUEST)
+ msg['payload'] += struct.pack('BB', 0, 0)
+ hapd.mgmt_tx(msg)
+
+ logger.debug("Truncated GAS Initial Request - too short Advertisement Protocol element")
+ msg = gas_hdr(dst, src, GAS_INITIAL_REQUEST)
+ msg['payload'] += struct.pack('BB', 108, 0)
+ hapd.mgmt_tx(msg)
+
+ logger.debug("Truncated GAS Initial Request - too short Advertisement Protocol element 2")
+ msg = gas_hdr(dst, src, GAS_INITIAL_REQUEST)
+ msg['payload'] += struct.pack('BBB', 108, 1, 127)
+ hapd.mgmt_tx(msg)
+
+ logger.debug("Invalid GAS Initial Request - unsupported GAS advertisement protocol id 255")
+ msg = gas_hdr(dst, src, GAS_INITIAL_REQUEST)
+ msg['payload'] += struct.pack('BBBB', 108, 2, 127, 255)
+ hapd.mgmt_tx(msg)
+
+ logger.debug("Truncated GAS Initial Request - no Query Request length field")
+ msg = gas_hdr(dst, src, GAS_INITIAL_REQUEST)
+ msg['payload'] += anqp_adv_proto()
+ hapd.mgmt_tx(msg)
+
+ logger.debug("Truncated GAS Initial Request - too short Query Request length field")
+ msg = gas_hdr(dst, src, GAS_INITIAL_REQUEST)
+ msg['payload'] += anqp_adv_proto()
+ msg['payload'] += struct.pack('<B', 0)
+ hapd.mgmt_tx(msg)
+
+ logger.debug("Truncated GAS Initial Request - too short Query Request field (minimum underflow)")
+ msg = gas_hdr(dst, src, GAS_INITIAL_REQUEST)
+ msg['payload'] += anqp_adv_proto()
+ msg['payload'] += struct.pack('<H', 1)
+ hapd.mgmt_tx(msg)
+
+ logger.debug("Truncated GAS Initial Request - too short Query Request field (maximum underflow)")
+ msg = gas_hdr(dst, src, GAS_INITIAL_REQUEST)
+ msg['payload'] += anqp_adv_proto()
+ msg['payload'] += struct.pack('<H', 65535)
+ hapd.mgmt_tx(msg)
+
+ logger.debug("Truncated GAS Initial Request - too short Query Request field")
+ msg = gas_hdr(dst, src, GAS_INITIAL_REQUEST)
+ msg['payload'] += anqp_adv_proto()
+ msg['payload'] += struct.pack('<H', 0)
+ hapd.mgmt_tx(msg)
+
+ logger.debug("Invalid GAS Initial Request - unsupported ANQP Info ID 65535")
+ msg = gas_hdr(dst, src, GAS_INITIAL_REQUEST)
+ msg['payload'] += anqp_adv_proto()
+ msg['payload'] += struct.pack('<HHH', 4, 65535, 0)
+ hapd.mgmt_tx(msg)
+
+ logger.debug("Invalid GAS Initial Request - invalid ANQP Query Request length (truncated frame)")
+ msg = gas_hdr(dst, src, GAS_INITIAL_REQUEST)
+ msg['payload'] += anqp_adv_proto()
+ msg['payload'] += struct.pack('<HHH', 4, 56797, 65535)
+ hapd.mgmt_tx(msg)
+
+ logger.debug("Invalid GAS Initial Request - invalid ANQP Query Request length (too short Query Request to contain OUI + OUI-type)")
+ msg = gas_hdr(dst, src, GAS_INITIAL_REQUEST)
+ msg['payload'] += anqp_adv_proto()
+ msg['payload'] += struct.pack('<HHH', 4, 56797, 0)
+ hapd.mgmt_tx(msg)
+
+ logger.debug("Invalid GAS Initial Request - unsupported ANQP vendor OUI-type")
+ msg = gas_hdr(dst, src, GAS_INITIAL_REQUEST)
+ msg['payload'] += anqp_adv_proto()
+ req = struct.pack('<HH', 56797, 4) + struct.pack('>L', 0x506f9a00)
+ msg['payload'] += struct.pack('<H', len(req)) + req
+ hapd.mgmt_tx(msg)
+
+ logger.debug("Truncated GAS Initial Request - no Service Update Indicator")
+ msg = gas_hdr(dst, src, GAS_INITIAL_REQUEST)
+ msg['payload'] += anqp_adv_proto()
+ req = struct.pack('<HH', 56797, 4) + struct.pack('>L', 0x506f9a09)
+ msg['payload'] += struct.pack('<H', len(req)) + req
+ hapd.mgmt_tx(msg)
+
+ logger.debug("Truncated GAS Initial Request - truncated Service Update Indicator")
+ msg = gas_hdr(dst, src, GAS_INITIAL_REQUEST)
+ msg['payload'] += anqp_adv_proto()
+ req = struct.pack('<HH', 56797, 4) + struct.pack('>L', 0x506f9a09)
+ req += struct.pack('<B', 0)
+ msg['payload'] += struct.pack('<H', len(req)) + req
+ hapd.mgmt_tx(msg)
+
+ logger.debug("Unexpected GAS Initial Response")
+ hapd.dump_monitor()
+ msg = gas_hdr(dst, src, GAS_INITIAL_RESPONSE)
+ msg['payload'] += struct.pack('<HH', 0, 0)
+ msg['payload'] += anqp_adv_proto()
+ msg['payload'] += struct.pack('<H', 0)
+ hapd.mgmt_tx(msg)
+
+ logger.debug("Truncated GAS Comeback Request - no Dialog Token field")
+ msg = gas_hdr(dst, src, GAS_COMEBACK_REQUEST, dialog_token=None)
+ hapd.mgmt_tx(msg)
+
+ logger.debug("GAS Comeback Request - no pending SD response fragment available")
+ msg = gas_hdr(dst, src, GAS_COMEBACK_REQUEST)
+ hapd.mgmt_tx(msg)
+
+ logger.debug("Unexpected GAS Comeback Response")
+ hapd.dump_monitor()
+ msg = gas_hdr(dst, src, GAS_COMEBACK_RESPONSE)
+ msg['payload'] += struct.pack('<HBH', 0, 0, 0)
+ msg['payload'] += anqp_adv_proto()
+ msg['payload'] += struct.pack('<H', 0)
+ hapd.mgmt_tx(msg)
+
+ logger.debug("Minimal GAS Initial Request")
+ hapd.dump_monitor()
+ msg = gas_hdr(dst, src, GAS_INITIAL_REQUEST)
+ msg['payload'] += anqp_adv_proto()
+ req = struct.pack('<HH', 56797, 4) + struct.pack('>L', 0x506f9a09)
+ req += struct.pack('<H', 0)
+ msg['payload'] += struct.pack('<H', len(req)) + req
+ hapd.mgmt_tx(msg)
+ resp = hapd.mgmt_rx()
+ if resp is None:
+ raise Exception("No response to minimal GAS Initial Request")
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import logging
logger = logging.getLogger()
import re
import time
import hwsim_utils
-from test_p2p_autogo import connect_cli
-
-def go_neg_pin_authorized_persistent(i_dev, r_dev, i_intent=None, r_intent=None, i_method='enter', r_method='display', test_data=True):
- r_dev.p2p_listen()
- i_dev.p2p_listen()
- pin = r_dev.wps_read_pin()
- logger.info("Start GO negotiation " + i_dev.ifname + " -> " + r_dev.ifname)
- r_dev.p2p_go_neg_auth(i_dev.p2p_dev_addr(), pin, r_method,
- go_intent=r_intent, persistent=True)
- r_dev.p2p_listen()
- i_res = i_dev.p2p_go_neg_init(r_dev.p2p_dev_addr(), pin, i_method,
- timeout=20, go_intent=i_intent,
- persistent=True)
- r_res = r_dev.p2p_go_neg_auth_result()
- logger.debug("i_res: " + str(i_res))
- logger.debug("r_res: " + str(r_res))
- r_dev.dump_monitor()
- i_dev.dump_monitor()
- logger.info("Group formed")
- if test_data:
- hwsim_utils.test_connectivity_p2p(r_dev, i_dev)
- return [i_res, r_res]
-
-def terminate_group(go, cli):
- logger.info("Terminate persistent group")
- go.remove_group()
- cli.wait_go_ending_session()
-
-def invite(inv, resp, extra=None, persistent_reconnect=True):
- addr = resp.p2p_dev_addr()
- if persistent_reconnect:
- resp.global_request("SET persistent_reconnect 1")
- else:
- resp.global_request("SET persistent_reconnect 0")
- resp.p2p_listen()
- if not inv.discover_peer(addr, social=True):
- raise Exception("Peer " + addr + " not found")
- inv.dump_monitor()
- peer = inv.get_peer(addr)
- cmd = "P2P_INVITE persistent=" + peer['persistent'] + " peer=" + addr
- if extra:
- cmd = cmd + " " + extra;
- inv.global_request(cmd)
-
-def check_result(go, cli):
- ev = go.wait_global_event(["P2P-GROUP-STARTED"], timeout=30)
- if ev is None:
- raise Exception("Timeout on group re-invocation (on GO)")
- if "[PERSISTENT]" not in ev:
- raise Exception("Re-invoked group not marked persistent")
- go_res = go.group_form_result(ev)
- if go_res['role'] != 'GO':
- raise Exception("Persistent group GO did not become GO")
- if not go_res['persistent']:
- raise Exception("Persistent group not re-invoked as persistent (GO)")
- ev = cli.wait_global_event(["P2P-GROUP-STARTED"], timeout=30)
- if ev is None:
- raise Exception("Timeout on group re-invocation (on client)")
- if "[PERSISTENT]" not in ev:
- raise Exception("Re-invoked group not marked persistent")
- cli_res = cli.group_form_result(ev)
- if cli_res['role'] != 'client':
- raise Exception("Persistent group client did not become client")
- if not cli_res['persistent']:
- raise Exception("Persistent group not re-invoked as persistent (cli)")
- return [go_res, cli_res]
-
-def form(go, cli, test_data=True, reverse_init=False):
- logger.info("Form a persistent group")
- if reverse_init:
- [i_res, r_res] = go_neg_pin_authorized_persistent(i_dev=cli, i_intent=0,
- r_dev=go, r_intent=15,
- test_data=test_data)
- else:
- [i_res, r_res] = go_neg_pin_authorized_persistent(i_dev=go, i_intent=15,
- r_dev=cli, r_intent=0,
- test_data=test_data)
- if not i_res['persistent'] or not r_res['persistent']:
- raise Exception("Formed group was not persistent")
- terminate_group(go, cli)
- if reverse_init:
- return r_res
- else:
- return i_res
-
-def invite_from_cli(go, cli):
- logger.info("Re-invoke persistent group from client")
- invite(cli, go)
- [go_res, cli_res] = check_result(go, cli)
- hwsim_utils.test_connectivity_p2p(go, cli)
- terminate_group(go, cli)
- return [go_res, cli_res]
-
-def invite_from_go(go, cli):
- logger.info("Re-invoke persistent group from GO")
- invite(go, cli)
- [go_res, cli_res] = check_result(go, cli)
- hwsim_utils.test_connectivity_p2p(go, cli)
- terminate_group(go, cli)
- return [go_res, cli_res]
+from p2p_utils import *
+@remote_compatible
def test_persistent_group(dev):
"""P2P persistent group formation and re-invocation"""
form(dev[0], dev[1])
if dev[1].p2p_dev_addr() in clients:
raise Exception("Peer was still in client list")
+@remote_compatible
def test_persistent_group2(dev):
"""P2P persistent group formation with reverse roles"""
form(dev[0], dev[1], reverse_init=True)
invite_from_cli(dev[0], dev[1])
invite_from_go(dev[0], dev[1])
+@remote_compatible
def test_persistent_group3(dev):
"""P2P persistent group formation and re-invocation with empty BSS table"""
form(dev[0], dev[1])
terminate_group(dev[0], dev[1])
+@remote_compatible
def test_persistent_group_channel(dev):
"""P2P persistent group re-invocation with channel selection"""
form(dev[0], dev[1], test_data=False)
raise Exception("Persistent group client channel preference not followed")
terminate_group(dev[0], dev[1])
+@remote_compatible
def test_persistent_group_and_role_change(dev):
"""P2P persistent group, auto GO in another role, and re-invocation"""
form(dev[0], dev[1])
if 'persistent' not in peer or peer['persistent'] != id:
raise Exception("Persistent group client not recognized(2)")
+@remote_compatible
def test_persistent_group_in_grpform(dev):
"""P2P persistent group parameters re-used in group formation"""
addr0 = dev[0].p2p_dev_addr()
logger.debug("i_res: " + str(i_res))
logger.debug("r_res: " + str(r_res))
+@remote_compatible
def test_persistent_group_without_persistent_reconnect(dev):
"""P2P persistent group re-invocation without persistent reconnect"""
form(dev[0], dev[1])
ev = dev[0].wait_global_event(["P2P-INVITATION-RECEIVED"], timeout=15)
if ev is None:
- raise Exception("No invitation request reported");
+ raise Exception("No invitation request reported")
if "persistent=" not in ev:
raise Exception("Invalid invitation type reported: " + ev)
ev2 = dev[1].wait_global_event(["P2P-INVITATION-RESULT"], timeout=15)
if ev2 is None:
- raise Exception("No invitation response reported");
+ raise Exception("No invitation response reported")
if "status=1" not in ev2:
raise Exception("Unexpected status: " + ev2)
dev[1].p2p_listen()
ev = dev[1].wait_global_event(["P2P-INVITATION-RECEIVED"], timeout=15)
if ev is None:
- raise Exception("No invitation request reported");
+ raise Exception("No invitation request reported")
if "persistent=" not in ev:
raise Exception("Invalid invitation type reported: " + ev)
ev2 = dev[0].wait_global_event(["P2P-INVITATION-RESULT"], timeout=15)
if ev2 is None:
- raise Exception("No invitation response reported");
+ raise Exception("No invitation response reported")
if "status=1" not in ev2:
raise Exception("Unexpected status: " + ev2)
dev[0].p2p_listen()
[go_res, cli_res] = check_result(dev[0], dev[1])
terminate_group(dev[0], dev[1])
+@remote_compatible
def test_persistent_group_already_running(dev):
"""P2P persistent group formation and invitation while GO already running"""
form(dev[0], dev[1])
raise Exception("Could not state GO")
invite_from_cli(dev[0], dev[1])
+@remote_compatible
def test_persistent_group_add_cli_chan(dev):
"""P2P persistent group formation and re-invocation with p2p_add_cli_chan=1"""
- dev[0].request("SET p2p_add_cli_chan 1")
- dev[1].request("SET p2p_add_cli_chan 1")
- form(dev[0], dev[1])
- dev[1].request("BSS_FLUSH 0")
- dev[1].scan(freq="2412", only_new=True)
- dev[1].scan(freq="2437", only_new=True)
- dev[1].scan(freq="2462", only_new=True)
- dev[1].request("BSS_FLUSH 0")
- invite_from_cli(dev[0], dev[1])
- invite_from_go(dev[0], dev[1])
-
+ try:
+ dev[0].request("SET p2p_add_cli_chan 1")
+ dev[1].request("SET p2p_add_cli_chan 1")
+ form(dev[0], dev[1])
+ dev[1].request("BSS_FLUSH 0")
+ dev[1].scan(freq="2412", only_new=True)
+ dev[1].scan(freq="2437", only_new=True)
+ dev[1].scan(freq="2462", only_new=True)
+ dev[1].request("BSS_FLUSH 0")
+ invite_from_cli(dev[0], dev[1])
+ invite_from_go(dev[0], dev[1])
+ finally:
+ dev[0].request("SET p2p_add_cli_chan 0")
+ dev[1].request("SET p2p_add_cli_chan 0")
+
+@remote_compatible
def test_persistent_invalid_group_add(dev):
"""Invalid P2P_GROUP_ADD command"""
id = dev[0].add_network()
terminate_group(dev[0], dev[1])
+@remote_compatible
def test_persistent_group_profile_add(dev):
"""Create a P2P persistent group with ADD_NETWORK"""
passphrase="passphrase here"
- id = dev[0].add_network()
- dev[0].set_network_quoted(id, "ssid", "DIRECT-ab")
- dev[0].set_network_quoted(id, "psk", passphrase)
- dev[0].set_network(id, "mode", "3")
- dev[0].set_network(id, "disabled", "2")
+ id = dev[0].p2pdev_add_network()
+ dev[0].p2pdev_set_network_quoted(id, "ssid", "DIRECT-ab")
+ dev[0].p2pdev_set_network_quoted(id, "psk", passphrase)
+ dev[0].p2pdev_set_network(id, "mode", "3")
+ dev[0].p2pdev_set_network(id, "disabled", "2")
dev[0].p2p_start_go(persistent=id, freq=2412)
pin = dev[1].wps_read_pin()
dev[0].remove_group()
dev[1].wait_go_ending_session()
+
+@remote_compatible
+def test_persistent_group_cancel_on_cli(dev):
+ """P2P persistent group formation, re-invocation, and cancel"""
+ dev[0].global_request("SET p2p_no_group_iface 0")
+ dev[1].global_request("SET p2p_no_group_iface 0")
+ form(dev[0], dev[1])
+
+ invite_from_go(dev[0], dev[1], terminate=False)
+ if "FAIL" not in dev[1].global_request("P2P_CANCEL"):
+ raise Exception("P2P_CANCEL succeeded unexpectedly on CLI")
+ if "FAIL" not in dev[0].global_request("P2P_CANCEL"):
+ raise Exception("P2P_CANCEL succeeded unexpectedly on GO")
+ terminate_group(dev[0], dev[1])
+
+ invite_from_cli(dev[0], dev[1], terminate=False)
+ if "FAIL" not in dev[1].global_request("P2P_CANCEL"):
+ raise Exception("P2P_CANCEL succeeded unexpectedly on CLI")
+ if "FAIL" not in dev[0].global_request("P2P_CANCEL"):
+ raise Exception("P2P_CANCEL succeeded unexpectedly on GO")
+ terminate_group(dev[0], dev[1])
+
+@remote_compatible
+def test_persistent_group_cancel_on_cli2(dev):
+ """P2P persistent group formation, re-invocation, and cancel (2)"""
+ form(dev[0], dev[1])
+ invite_from_go(dev[0], dev[1], terminate=False)
+ if "FAIL" not in dev[1].global_request("P2P_CANCEL"):
+ raise Exception("P2P_CANCEL succeeded unexpectedly on CLI")
+ if "FAIL" not in dev[0].global_request("P2P_CANCEL"):
+ raise Exception("P2P_CANCEL succeeded unexpectedly on GO")
+ terminate_group(dev[0], dev[1])
+
+ invite_from_cli(dev[0], dev[1], terminate=False)
+ if "FAIL" not in dev[1].global_request("P2P_CANCEL"):
+ raise Exception("P2P_CANCEL succeeded unexpectedly on CLI")
+ if "FAIL" not in dev[0].global_request("P2P_CANCEL"):
+ raise Exception("P2P_CANCEL succeeded unexpectedly on GO")
+ terminate_group(dev[0], dev[1])
+
+@remote_compatible
+def test_persistent_group_peer_dropped(dev):
+ """P2P persistent group formation and re-invocation with peer having dropped group"""
+ form(dev[0], dev[1], reverse_init=True)
+ invite_from_cli(dev[0], dev[1])
+
+ logger.info("Remove group on the GO and try to invite from the client")
+ dev[0].global_request("REMOVE_NETWORK all")
+ invite(dev[1], dev[0])
+ ev = dev[1].wait_global_event(["P2P-INVITATION-RESULT"], timeout=10)
+ if ev is None:
+ raise Exception("No invitation result seen")
+ if "status=8" not in ev:
+ raise Exception("Unexpected invitation result: " + ev)
+ networks = dev[1].list_networks(p2p=True)
+ if len(networks) > 0:
+ raise Exception("Unexpected network block on client")
+
+ logger.info("Verify that a new group can be formed")
+ form(dev[0], dev[1], reverse_init=True)
+
+@remote_compatible
+def test_persistent_group_peer_dropped2(dev):
+ """P2P persistent group formation and re-invocation with peer having dropped group (2)"""
+ form(dev[0], dev[1])
+ invite_from_go(dev[0], dev[1])
+
+ logger.info("Remove group on the client and try to invite from the GO")
+ dev[1].global_request("REMOVE_NETWORK all")
+ invite(dev[0], dev[1])
+ ev = dev[0].wait_global_event(["P2P-INVITATION-RESULT"], timeout=10)
+ if ev is None:
+ raise Exception("No invitation result seen")
+ if "status=8" not in ev:
+ raise Exception("Unexpected invitation result: " + ev)
+ networks = dev[1].list_networks(p2p=True)
+ if len(networks) > 0:
+ raise Exception("Unexpected network block on client")
+
+ logger.info("Verify that a new group can be formed")
+ form(dev[0], dev[1])
+
+def test_persistent_group_peer_dropped3(dev):
+ """P2P persistent group formation and re-invocation with peer having dropped group (3)"""
+ form(dev[0], dev[1], reverse_init=True)
+ invite_from_cli(dev[0], dev[1])
+
+ logger.info("Remove group on the GO and try to invite from the client")
+ dev[0].global_request("REMOVE_NETWORK all")
+ invite(dev[1], dev[0], use_listen=False)
+ ev = dev[1].wait_global_event(["P2P-INVITATION-RESULT"], timeout=10)
+ if ev is None:
+ raise Exception("No invitation result seen")
+ if "status=8" not in ev:
+ raise Exception("Unexpected invitation result: " + ev)
+ networks = dev[1].list_networks(p2p=True)
+ if len(networks) > 0:
+ raise Exception("Unexpected network block on client")
+
+ time.sleep(0.2)
+ logger.info("Verify that a new group can be formed")
+ form(dev[0], dev[1], reverse_init=True, r_listen=False)
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import logging
logger = logging.getLogger()
import time
return ev
+@remote_compatible
def test_p2p_service_discovery(dev):
"""P2P service discovery"""
addr0 = dev[0].p2p_dev_addr()
if "496e7465726e6574" not in ev:
raise Exception("Unexpected service discovery response contents (UPnP)")
+@remote_compatible
def test_p2p_service_discovery_multiple_queries(dev):
"""P2P service discovery with multiple queries"""
for dst in [ "00:00:00:00:00:00", dev[0].p2p_dev_addr() ]:
if "496e7465726e6574" not in ev:
raise Exception("Unexpected service discovery response contents (UPnP)")
+@remote_compatible
def test_p2p_service_discovery_bonjour(dev):
"""P2P service discovery (Bonjour)"""
ev = run_sd(dev, "00:00:00:00:00:00", "02000101")
if "496e7465726e6574" in ev:
raise Exception("Unexpected service discovery response contents (UPnP not expected)")
+@remote_compatible
def test_p2p_service_discovery_bonjour2(dev):
"""P2P service discovery (Bonjour AFS)"""
ev = run_sd(dev, "00:00:00:00:00:00", "130001010b5f6166706f766572746370c00c000c01")
if "496e7465726e6574" in ev:
raise Exception("Unexpected service discovery response contents (UPnP not expected)")
+@remote_compatible
def test_p2p_service_discovery_bonjour3(dev):
"""P2P service discovery (Bonjour AFS - no match)"""
ev = run_sd(dev, "00:00:00:00:00:00", "130001010b5f6166706f766572746370c00c000c02")
if "496e7465726e6574" in ev:
raise Exception("Unexpected service discovery response contents (UPnP not expected)")
+@remote_compatible
def test_p2p_service_discovery_upnp(dev):
"""P2P service discovery (UPnP)"""
ev = run_sd(dev, "00:00:00:00:00:00", "02000201")
if "496e7465726e6574" not in ev:
raise Exception("Unexpected service discovery response contents (UPnP)")
+@remote_compatible
def test_p2p_service_discovery_upnp2(dev):
"""P2P service discovery (UPnP using request helper)"""
ev = run_sd(dev, "00:00:00:00:00:00", "upnp 10 ssdp:all", "0b00020110737364703a616c6c")
if "496e7465726e6574" not in ev:
raise Exception("Unexpected service discovery response contents (UPnP)")
+@remote_compatible
def test_p2p_service_discovery_upnp3(dev):
"""P2P service discovery (UPnP using request helper - no match)"""
ev = run_sd(dev, "00:00:00:00:00:00", "upnp 10 ssdp:foo", "0b00020110737364703a666f6f")
if "496e7465726e6574" in ev:
raise Exception("Unexpected service discovery response contents (UPnP)")
+@remote_compatible
def test_p2p_service_discovery_ws(dev):
"""P2P service discovery (WS-Discovery)"""
ev = run_sd(dev, "00:00:00:00:00:00", "02000301")
if "0300030101" not in ev:
raise Exception("Unexpected service discovery response contents (WS)")
+@remote_compatible
def test_p2p_service_discovery_wfd(dev):
"""P2P service discovery (Wi-Fi Display)"""
dev[0].global_request("SET wifi_display 1")
if "0300040101" not in ev:
raise Exception("Unexpected response to WFD SD query (protocol was disabled)")
+@remote_compatible
def test_p2p_service_discovery_req_cancel(dev):
"""Cancel a P2P service discovery request"""
if "FAIL" not in dev[0].global_request("P2P_SERV_DISC_CANCEL_REQ ab"):
if "OK" not in dev[0].global_request("P2P_SERV_DISC_CANCEL_REQ " + query):
raise Exception("Unexpected SD(broadcast) cancel failure")
+@remote_compatible
def test_p2p_service_discovery_go(dev):
"""P2P service discovery from GO"""
addr0 = dev[0].p2p_dev_addr()
if "FAIL" not in dev[0].global_request("P2P_SERV_DISC_RESP " + cmd):
raise Exception("Invalid P2P_SERV_DISC_RESP accepted: " + cmd)
+@remote_compatible
def test_p2p_service_discovery_external(dev):
"""P2P service discovery using external response"""
try:
finally:
dev[0].global_request("P2P_SERV_DISC_EXTERNAL 0")
+@remote_compatible
def test_p2p_service_discovery_invalid_commands(dev):
"""P2P service discovery invalid commands"""
for cmd in [ "bonjour",
raise Exception("Could not get p2p_state")
return p2p_state
+@remote_compatible
def test_p2p_service_discovery_peer_not_listening(dev):
"""P2P service discovery and peer not listening"""
addr0 = dev[0].p2p_dev_addr()
if p2p_state != "IDLE":
raise Exception("Unexpected p2p_state after P2P_FIND timeout: " + p2p_state)
+@remote_compatible
def test_p2p_service_discovery_peer_not_listening2(dev):
"""P2P service discovery and peer not listening"""
addr0 = dev[0].p2p_dev_addr()
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
+
def test_p2p_set(dev):
"""P2P_SET commands"""
for cmd in [ "",
dev[2].p2p_stop_find()
dev[0].p2p_stop_find()
+@remote_compatible
def test_p2p_set_ssid_postfix(dev):
"""P2P_SET ssid_postfix"""
addr0 = dev[0].p2p_dev_addr()
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import logging
logger = logging.getLogger()
import time
import hwsim_utils
import utils
-from test_p2p_autogo import connect_cli
-from test_p2p_persistent import form, invite, invite_from_cli, invite_from_go
+from p2p_utils import *
def test_wifi_display(dev):
"""Wi-Fi Display extensions to P2P"""
dev[1].request("SET wifi_display 0")
dev[2].request("SET wifi_display 0")
+@remote_compatible
def test_wifi_display_invalid_subelem(dev):
"""Wi-Fi Display and invalid subelement parsing"""
addr1 = dev[1].p2p_dev_addr()
finally:
dev[0].request("SET wifi_display 0")
dev[1].request("SET wifi_display 0")
+
+def test_wifi_display_parsing(dev):
+ """Wi-Fi Display extensions to P2P and special parsing cases"""
+ try:
+ _test_wifi_display_parsing(dev)
+ finally:
+ dev[1].request("VENDOR_ELEM_REMOVE 11 *")
+ dev[0].request("SET wifi_display 0")
+
+def _test_wifi_display_parsing(dev):
+ wfd_devinfo = "00411c440028"
+ dev[0].request("SET wifi_display 1")
+ dev[0].request("WFD_SUBELEM_SET 0 0006" + wfd_devinfo)
+ dev[0].p2p_start_go(freq=2412)
+
+ # P2P Client with invalid WFD IE
+ if "OK" not in dev[1].request("VENDOR_ELEM_ADD 11 dd10506f9a0a000000010000060000ffffff"):
+ raise Exception("VENDOR_ELEM_ADD failed")
+
+ pin = dev[1].wps_read_pin()
+ dev[0].p2p_go_authorize_client(pin)
+ dev[1].p2p_connect_group(dev[0].p2p_dev_addr(), pin, timeout=60,
+ social=True, freq=2412)
+ bssid = dev[0].get_group_status_field('bssid')
+ dev[2].scan_for_bss(bssid, freq=2412, force_scan=True)
+ bss = dev[2].get_bss(bssid)
+ if bss['wfd_subelems'] != "000006" + wfd_devinfo:
+ raise Exception("Unexpected WFD elements in scan results: " + bss['wfd_subelems'])
+
+ # P2P Client without WFD IE
+ pin = dev[2].wps_read_pin()
+ dev[0].p2p_go_authorize_client(pin)
+ dev[2].p2p_connect_group(dev[0].p2p_dev_addr(), pin, timeout=60,
+ social=True, freq=2412)
+ dev[2].remove_group()
+
+ dev[0].remove_group()
+ dev[1].wait_go_ending_session()
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import logging
logger = logging.getLogger()
import time
import hwsim_utils
from wpasupplicant import WpaSupplicant
-from test_p2p_grpform import check_grpform_results
-from test_p2p_grpform import remove_group
-from test_p2p_persistent import go_neg_pin_authorized_persistent
+import hostapd
+from p2p_utils import *
from utils import HwsimSkip
+from hwsim import HWSimRadio
# Dev[0] -> Advertiser
# Dev[1] -> Seeker
if rcvd_svc_name != svc_name:
raise Exception("service name not matching")
+ i_dev.p2p_stop_find()
return [adv_id, rcvd_svc_name]
def p2ps_nonexact_seek(i_dev, r_dev, svc_name, srv_info=None, adv_num=None):
adv_id = ev1.split(" ")[3]
rcvd_svc_name = ev1.split(" ")[6]
ev_list.append(''.join([adv_id, ' ', rcvd_svc_name]))
+
+ i_dev.p2p_stop_find()
return ev_list
def p2ps_parse_event(ev, *args):
ret += (m.group(1) if m is not None else None,)
return ret
-def p2ps_provision(seeker, advertiser, adv_id, auto_accept=True, method="1000", adv_cpt=None, seeker_cpt=None):
+def p2ps_provision(seeker, advertiser, adv_id, auto_accept=True, method="1000",
+ adv_cpt=None, seeker_cpt=None, handler=None, adv_role=None,
+ seeker_role=None):
addr0 = seeker.p2p_dev_addr()
addr1 = advertiser.p2p_dev_addr()
seeker.asp_provision(addr1, adv_id=str(adv_id), adv_mac=addr1, session_id=1,
- session_mac=addr0, method=method, cpt=seeker_cpt)
+ session_mac=addr0, method=method, cpt=seeker_cpt,
+ role=seeker_role)
if not auto_accept or method == "100":
pin = None
if ev is None:
raise Exception("P2P-PROV-DISC-FAILURE timeout on seeker side")
+ if handler:
+ handler(seeker, advertiser)
+
+ # Put seeker into a listen state, since we expect the deferred flow to
+ # continue.
+ seeker.p2p_ext_listen(500, 500)
+
if method == "100":
ev = advertiser.wait_global_event(["P2P-PROV-DISC-ENTER-PIN"],
timeout=10)
raise Exception("Unknown peer " + addr0)
pin = ev.split()[2]
+ # Stop P2P_LISTEN before issuing P2P_ASP_PROVISION_RESP to avoid
+ # excessive delay and test case timeouts if it takes large number of
+ # retries to find the peer awake on its Listen channel.
+ advertiser.p2p_stop_find()
+
advertiser.asp_provision(peer, adv_id=advert_id, adv_mac=advert_mac,
session_id=int(session, 0),
session_mac=session_mac, status=12,
- cpt=adv_cpt)
+ cpt=adv_cpt, role=adv_role)
ev1 = seeker.wait_global_event(["P2PS-PROV-DONE"], timeout=10)
if ev1 is None:
if addr1 not in ev:
raise Exception("Unknown peer " + addr1)
+ seeker.p2p_cancel_ext_listen()
if pin is not None:
return ev1, ev2, pin
return ev1, ev2
return ev1, ev2
-def p2ps_connect_pd(dev0, dev1, ev0, ev1, pin=None):
+def p2ps_connect_pd(dev0, dev1, ev0, ev1, pin=None, join_extra="", go_ev=None):
conf_methods_map = {"8": "p2ps", "1": "display", "5": "keypad"}
peer0 = ev0.split()[1]
peer1 = ev1.split()[1]
- status0, conncap0, adv_id0, adv_mac0, mac0, session0, dev_passwd_id0, go0, join0, feature_cap0, persist0 =\
- p2ps_parse_event(ev0, "status", "conncap", "adv_id", "adv_mac", "mac", "session", "dev_passwd_id", "go", "join", "feature_cap", "persist")
- status1, conncap1, adv_id1, adv_mac1, mac1, session1, dev_passwd_id1, go1, join1, feature_cap1, persist1 =\
- p2ps_parse_event(ev1, "status", "conncap", "adv_id", "adv_mac", "mac", "session", "dev_passwd_id", "go", "join", "feature_cap", "persist")
+ status0, conncap0, adv_id0, adv_mac0, mac0, session0, dev_passwd_id0, go0, join0, feature_cap0, persist0, group_ssid0 =\
+ p2ps_parse_event(ev0, "status", "conncap", "adv_id", "adv_mac", "mac", "session", "dev_passwd_id", "go", "join", "feature_cap", "persist", "group_ssid")
+ status1, conncap1, adv_id1, adv_mac1, mac1, session1, dev_passwd_id1, go1, join1, feature_cap1, persist1, group_ssid1 =\
+ p2ps_parse_event(ev1, "status", "conncap", "adv_id", "adv_mac", "mac", "session", "dev_passwd_id", "go", "join", "feature_cap", "persist", "group_ssid")
if status0 != "0" and status0 != "12":
raise Exception("PD failed on " + dev0.p2p_dev_addr())
# Persistent Connection (todo: handle frequency)
if persist0 is not None:
+ dev0.p2p_stop_find()
if "OK" not in dev0.global_request("P2P_GROUP_ADD persistent=" + persist0 + " freq=2412"):
raise Exception("Could not re-start persistent group")
ev0 = dev0.wait_global_event(["P2P-GROUP-STARTED"], timeout=10)
dev1.group_form_result(ev)
else:
if conncap0 == "2" and conncap1 == "4": # dev0 CLI, dev1 GO
- dev_cli, dev_go, go_if, join_address, go_method, cli_method = dev0, dev1, go1, join0, method1, method0
+ dev_cli, dev_go, go_if, join_address, go_method, cli_method, join_ssid = dev0, dev1, go1, join0, method1, method0, group_ssid0
elif conncap0 == "4" and conncap1 == "2": # dev0 GO, dev1 CLI
- dev_cli, dev_go, go_if, join_address, go_method, cli_method = dev1, dev0, go0, join1, method0, method1
+ dev_cli, dev_go, go_if, join_address, go_method, cli_method, join_ssid = dev1, dev0, go0, join1, method0, method1, group_ssid1
else:
raise Exception("Bad connection capabilities")
raise Exception("Device " + dev_go.p2p_dev_addr() + " failed to become GO")
if join_address is None:
raise Exception("Device " + dev_cli.p2p_dev_addr() + " failed to become CLI")
- ev = dev_go.wait_global_event(["P2P-GROUP-STARTED"], timeout=10)
- if ev is None:
- raise Exception("P2P-GROUP-STARTED timeout on " + dev_go.p2p_dev_addr())
- dev_go.group_form_result(ev)
+
+ if not dev_go.get_group_ifname().startswith('p2p-'):
+ if go_ev:
+ ev = go_ev
+ else:
+ ev = dev_go.wait_global_event(["P2P-GROUP-STARTED"],
+ timeout=10)
+ if ev is None:
+ raise Exception("P2P-GROUP-STARTED timeout on " + dev_go.p2p_dev_addr())
+ dev_go.group_form_result(ev)
+
if go_method != "p2ps":
ev = dev_go.group_request("WPS_PIN any " + pin)
if ev is None:
raise Exception("Failed to initiate pin authorization on registrar side")
- if "OK" not in dev_cli.global_request("P2P_CONNECT " + join_address + " " + pin + " " + cli_method + " persistent join"):
+ if join_ssid:
+ group_ssid_txt = " ssid=" + join_ssid
+ else:
+ group_ssid_txt = ""
+ if "OK" not in dev_cli.global_request("P2P_CONNECT " + join_address + " " + pin + " " + cli_method + join_extra + " persistent join" + group_ssid_txt):
raise Exception("P2P_CONNECT failed on " + dev_cli.p2p_dev_addr())
ev = dev_cli.wait_global_event(["P2P-GROUP-STARTED"], timeout=10)
if ev is None:
def set_no_group_iface(dev, enable):
if enable:
res = dev.get_driver_status()
- if (int(res['capa.flags'], 0) & 0x20000000):
- raise HwsimSkip("P2P Device used. Cannot set enable no_group_iface")
+ if (int(res['capa.flags'], 0) & 0x20000000):
+ raise HwsimSkip("P2P Device used. Cannot set enable no_group_iface")
dev.global_request("SET p2p_no_group_iface 1")
else:
dev.global_request("SET p2p_no_group_iface 0")
+@remote_compatible
def test_p2ps_exact_search(dev):
"""P2PS exact service request"""
p2ps_advertise(r_dev=dev[0], r_role='1', svc_name='org.wi-fi.wfds.send.rx',
if ev0 is None:
raise Exception("Unable to remove the advertisement instance")
+@remote_compatible
def test_p2ps_exact_search_srvinfo(dev):
"""P2PS exact service request with service info"""
p2ps_advertise(r_dev=dev[0], r_role='0', svc_name='org.wi-fi.wfds.send.rx',
if ev0 is None:
raise Exception("Unable to remove the advertisement instance")
+@remote_compatible
def test_p2ps_nonexact_search(dev):
"""P2PS nonexact seek request"""
p2ps_advertise(r_dev=dev[0], r_role='0', svc_name='org.wi-fi.wfds.play.rx',
if ev0 is None:
raise Exception("Unable to remove the advertisement instance")
+@remote_compatible
def test_p2ps_nonexact_search_srvinfo(dev):
"""P2PS nonexact seek request with service info"""
p2ps_advertise(r_dev=dev[0], r_role='0', svc_name='org.wi-fi.wfds.send.rx',
if ev0 is None:
raise Exception("Unable to remove the advertisement instance")
+@remote_compatible
def test_p2ps_connect_p2ps_method_nonautoaccept(dev):
"""P2PS connect for non-auto-accept and P2PS config method"""
p2ps_advertise(r_dev=dev[0], r_role='0', svc_name='org.wi-fi.wfds.send.rx',
raise Exception("Unable to remove the advertisement instance")
remove_group(dev[0], dev[1])
+@remote_compatible
def test_p2ps_connect_p2ps_method_autoaccept(dev):
"""P2PS connection with P2PS default config method and auto-accept"""
p2ps_advertise(r_dev=dev[0], r_role='1', svc_name='org.wi-fi.wfds.send.rx',
raise Exception("Unable to remove the advertisement instance")
remove_group(dev[0], dev[1])
+@remote_compatible
def test_p2ps_connect_keypad_method_nonautoaccept(dev):
"""P2PS Connection with non-auto-accept and seeker having keypad method"""
p2ps_advertise(r_dev=dev[0], r_role='0', svc_name='org.wi-fi.wfds.send.rx',
raise Exception("Unable to remove the advertisement instance")
remove_group(dev[0], dev[1])
+@remote_compatible
def test_p2ps_connect_display_method_nonautoaccept(dev):
"""P2PS connection with non-auto-accept and seeker having display method"""
p2ps_advertise(r_dev=dev[0], r_role='0', svc_name='org.wi-fi.wfds.send.rx',
raise Exception("Unable to remove the advertisement instance")
remove_group(dev[0], dev[1])
+@remote_compatible
def test_p2ps_connect_keypad_method_autoaccept(dev):
"""P2PS connection with auto-accept and keypad method on seeker side"""
p2ps_advertise(r_dev=dev[0], r_role='1', svc_name='org.wi-fi.wfds.send.rx',
raise Exception("Unable to remove the advertisement instance")
remove_group(dev[0], dev[1])
+@remote_compatible
def test_p2ps_connect_display_method_autoaccept(dev):
"""P2PS connection with auto-accept and display method on seeker side"""
p2ps_advertise(r_dev=dev[0], r_role='1', svc_name='org.wi-fi.wfds.send.rx',
raise Exception("Unable to remove the advertisement instance")
remove_group(dev[0], dev[1])
+@remote_compatible
def test_p2ps_connect_adv_go_p2ps_method(dev):
"""P2PS auto-accept connection with advertisement as GO and P2PS method"""
p2ps_advertise(r_dev=dev[0], r_role='4', svc_name='org.wi-fi.wfds.send.rx',
raise Exception("Unable to remove the advertisement instance")
remove_group(dev[0], dev[1])
+@remote_compatible
def test_p2ps_connect_adv_go_p2ps_method_group_iface(dev):
"""P2PS auto-accept connection with advertisement as GO and P2PS method using separate group interface"""
set_no_group_iface(dev[0], 0)
raise Exception("Unable to remove the advertisement instance")
remove_group(dev[0], dev[1])
+@remote_compatible
def test_p2ps_connect_adv_client_p2ps_method(dev):
"""P2PS auto-accept connection with advertisement as Client and P2PS method"""
p2ps_advertise(r_dev=dev[0], r_role='2', svc_name='org.wi-fi.wfds.send.rx',
raise Exception("Unable to remove the advertisement instance")
remove_group(dev[0], dev[1])
+@remote_compatible
def test_p2ps_connect_adv_go_pin_method(dev):
"""P2PS advertiser as GO with keypad config method on seeker side and auto-accept"""
p2ps_connect_adv_go_pin_method(dev)
+@remote_compatible
def test_p2ps_connect_adv_client_pin_method(dev):
"""P2PS advertiser as client with keypad config method on seeker side and auto-accept"""
dev[0].flush_scan_cache()
ifnames.append(ifname)
return ifnames
-def p2ps_connect_p2ps_method(dev, keep_group=False):
- dev[0].flush_scan_cache()
- dev[1].flush_scan_cache()
+def p2ps_connect_p2ps_method(dev, keep_group=False, join_extra="", flush=True):
+ if flush:
+ dev[0].flush_scan_cache()
+ dev[1].flush_scan_cache()
p2ps_advertise(r_dev=dev[0], r_role='2', svc_name='org.wi-fi.wfds.send.rx',
srv_info='I can receive files upto size 2 GB')
[adv_id, rcvd_svc_name] = p2ps_exact_seek(i_dev=dev[1], r_dev=dev[0],
svc_name='org.wi-fi.wfds.send.rx',
srv_info='2 GB')
ev1, ev0 = p2ps_provision(dev[1], dev[0], adv_id)
+ go_ev = None
+ if "join=" in ev0 and "go=" in ev1:
+ # dev[1] started GO and dev[0] is about to join it.
+ # Parse P2P-GROUP-STARTED from the GO to learn the operating frequency.
+ go_ev = dev[1].wait_global_event(["P2P-GROUP-STARTED"], timeout=10)
+ if go_ev is None:
+ raise Exception("P2P-GROUP-STARTED timeout on dev1")
+ res = dev[1].group_form_result(go_ev)
+ if join_extra == "":
+ join_extra = " freq=" + res['freq']
+
ifnames = get_ifnames()
- p2ps_connect_pd(dev[0], dev[1], ev0, ev1)
+ p2ps_connect_pd(dev[0], dev[1], ev0, ev1, join_extra=join_extra,
+ go_ev=go_ev)
grp_ifname0 = dev[0].get_group_ifname()
grp_ifname1 = dev[1].get_group_ifname()
(grp_ifname0, grp_ifname1, ifnames) = p2ps_connect_p2ps_method(dev)
if not grp_ifname0.startswith('p2p-' + dev[0].ifname + '-'):
- raise Exception("unexpected dev0 group ifname: " + res0['ifname'])
+ raise Exception("unexpected dev0 group ifname: " + grp_ifname0)
if not grp_ifname1.startswith('p2p-' + dev[1].ifname + '-'):
- raise Exception("unexpected dev1 group ifname: " + res1['ifname'])
+ raise Exception("unexpected dev1 group ifname: " + grp_ifname1)
def test_p2ps_connect_adv_go_persistent(dev):
"""P2PS auto-accept connection with advertisement as GO and having persistent group"""
p2ps_connect_pd(dev[0], dev[1], ev0, ev1)
remove_group(dev[0], dev[1])
+@remote_compatible
+def test_p2ps_adv_go_persistent_no_peer_entry(dev):
+ """P2PS advertisement as GO having persistent group (no peer entry)"""
+ go_neg_pin_authorized_persistent(i_dev=dev[0], i_intent=15,
+ r_dev=dev[1], r_intent=0)
+ dev[0].remove_group()
+ dev[1].wait_go_ending_session()
+
+ p2ps_advertise(r_dev=dev[0], r_role='4', svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='I can receive files upto size 2 GB')
+ [adv_id, rcvd_svc_name] = p2ps_exact_seek(i_dev=dev[1], r_dev=dev[0],
+ svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='2 GB')
+ dev[0].global_request("P2P_FLUSH")
+ dev[0].p2p_listen()
+ ev1, ev0 = p2ps_provision(dev[1], dev[0], adv_id)
+ if "persist=" not in ev0 or "persist=" not in ev1:
+ raise Exception("Persistent group isn't used by peers")
+
+@remote_compatible
+def test_p2ps_pd_follow_on_status_failure(dev):
+ """P2PS PD follow on request with status 11"""
+ addr0 = dev[0].p2p_dev_addr()
+ addr1 = dev[1].p2p_dev_addr()
+
+ p2ps_advertise(r_dev=dev[0], r_role='0', svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='I can receive files upto size 2 GB')
+ [adv_id, rcvd_svc_name] = p2ps_exact_seek(i_dev=dev[1], r_dev=dev[0],
+ svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='2 GB')
+ dev[1].asp_provision(addr0, adv_id=str(adv_id), adv_mac=addr0,
+ session_id=1, session_mac=addr1)
+ ev_pd_start = dev[0].wait_global_event(["P2PS-PROV-START"], timeout=10)
+ if ev_pd_start is None:
+ raise Exception("P2PS-PROV-START timeout on Advertiser side")
+ ev = dev[1].wait_global_event(["P2P-PROV-DISC-FAILURE"], timeout=10)
+ if ev is None:
+ raise Exception("P2P-PROV-DISC-FAILURE timeout on seeker side")
+ dev[1].p2p_ext_listen(500, 500)
+ dev[0].p2p_stop_find()
+ dev[0].asp_provision(addr1, adv_id=str(adv_id), adv_mac=addr0, session_id=1,
+ session_mac=addr1, status=11, method=0)
+
+ ev = dev[1].wait_global_event(["P2PS-PROV-DONE"], timeout=10)
+ if ev is None:
+ raise Exception("P2P-PROV-DONE timeout on seeker side")
+ if adv_id not in ev:
+ raise Exception("P2P-PROV-DONE without adv_id on seeker side")
+ if "status=11" not in ev:
+ raise Exception("P2P-PROV-DONE without status on seeker side")
+
+ ev = dev[0].wait_global_event(["P2PS-PROV-DONE"], timeout=10)
+ if ev is None:
+ raise Exception("P2P-PROV-DONE timeout on advertiser side")
+ if adv_id not in ev:
+ raise Exception("P2P-PROV-DONE without adv_id on advertiser side")
+ if "status=11" not in ev:
+ raise Exception("P2P-PROV-DONE without status on advertiser side")
+
def test_p2ps_client_probe(dev):
"""P2PS CLI discoverability on operating channel"""
cli_probe = dev[0].global_request("SET p2p_cli_probe 1")
dev[0].global_request("P2P_SERVICE_DEL asp " + str(adv_id))
remove_group(dev[0], dev[1])
+@remote_compatible
def test_p2ps_wildcard_p2ps(dev):
"""P2PS wildcard SD Probe Request/Response"""
p2ps_wildcard = "org.wi-fi.wfds"
if ev is None:
raise Exception("Unable to remove the advertisement instance")
+@remote_compatible
def test_p2ps_feature_capability_mac_autoaccept(dev):
"""P2PS PD Feature Capability CPT: advertiser MAC, seeker UDP:MAC, autoaccept"""
p2ps_test_feature_capability_cpt(dev, adv_cpt="MAC", seeker_cpt="UDP:MAC",
adv_role="4", result="MAC")
+@remote_compatible
def test_p2ps_feature_capability_mac_nonautoaccept(dev):
"""P2PS PD Feature Capability CPT: advertiser:MAC, seeker UDP:MAC, nonautoaccept"""
p2ps_test_feature_capability_cpt(dev, adv_cpt="MAC", seeker_cpt="UDP:MAC",
adv_role="0", result="MAC")
+@remote_compatible
def test_p2ps_feature_capability_mac_udp_autoaccept(dev):
"""P2PS PD Feature Capability CPT: advertiser MAC:UDP, seeker UDP:MAC, autoaccept"""
p2ps_test_feature_capability_cpt(dev, adv_cpt="MAC:UDP",
seeker_cpt="UDP:MAC", adv_role="2",
result="MAC")
+@remote_compatible
def test_p2ps_feature_capability_mac_udp_nonautoaccept(dev):
"""P2PS PD Feature Capability CPT: advertiser MAC:UDP, seeker UDP:MAC, nonautoaccept"""
p2ps_test_feature_capability_cpt(dev, adv_cpt="MAC:UDP",
seeker_cpt="UDP:MAC", adv_role="0",
result="UDP")
+@remote_compatible
def test_p2ps_feature_capability_udp_mac_autoaccept(dev):
"""P2PS PD Feature Capability CPT: advertiser UDP:MAC, seeker MAC:UDP, autoaccept"""
p2ps_test_feature_capability_cpt(dev, adv_cpt="UDP:MAC",
seeker_cpt="MAC:UDP", adv_role="2",
result="UDP")
+@remote_compatible
def test_p2ps_feature_capability_udp_mac_nonautoaccept(dev):
"""P2PS PD Feature Capability CPT: advertiser UDP:MAC, seeker MAC:UDP, nonautoaccept"""
p2ps_test_feature_capability_cpt(dev, adv_cpt="UDP:MAC",
seeker_cpt="MAC:UDP", adv_role="0",
result="MAC")
+
+def test_p2ps_channel_one_connected(dev, apdev):
+ """P2PS connection with P2PS method - one of the stations connected"""
+ set_no_group_iface(dev[0], 0)
+ set_no_group_iface(dev[1], 0)
+
+ try:
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": 'bss-2.4ghz', "channel": '7' })
+ dev[1].connect("bss-2.4ghz", key_mgmt="NONE", scan_freq="2442")
+
+ (grp_ifname0, grp_ifname1, ifnames) = p2ps_connect_p2ps_method(dev, keep_group=True, join_extra=" freq=2442")
+ freq = dev[0].get_group_status_field('freq')
+
+ if freq != '2442':
+ raise Exception('Unexpected frequency for group 2442 != ' + freq)
+ finally:
+ remove_group(dev[0], dev[1])
+ dev[0].global_request("P2P_SERVICE_DEL asp all")
+
+def set_random_listen_chan(dev):
+ chan = random.randrange(0, 3) * 5 + 1
+ dev.global_request("P2P_SET listen_channel %d" % chan)
+
+def test_p2ps_channel_both_connected_same(dev, apdev):
+ """P2PS connection with P2PS method - stations connected on same channel"""
+ set_no_group_iface(dev[2], 0)
+ set_no_group_iface(dev[1], 0)
+
+ dev[2].global_request("P2P_SET listen_channel 6")
+ dev[1].global_request("P2P_SET listen_channel 6")
+
+ dev[1].flush_scan_cache()
+ dev[2].flush_scan_cache()
+
+ try:
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": 'bss-2.4ghz', "channel": '6' })
+
+ dev[2].connect("bss-2.4ghz", key_mgmt="NONE", scan_freq="2437")
+ dev[1].connect("bss-2.4ghz", key_mgmt="NONE", scan_freq="2437")
+
+ tmpdev = [ dev[2], dev[1] ]
+ (grp_ifname0, grp_ifname1, ifnames) = p2ps_connect_p2ps_method(tmpdev, keep_group=True, join_extra=" freq=2437", flush=False)
+ freq = dev[2].get_group_status_field('freq')
+
+ if freq != '2437':
+ raise Exception('Unexpected frequency for group 2437 != ' + freq)
+ finally:
+ remove_group(dev[2], dev[1])
+ dev[2].global_request("P2P_SERVICE_DEL asp all")
+ for i in range(1, 3):
+ set_random_listen_chan(dev[i])
+
+def disconnect_handler(seeker, advertiser):
+ advertiser.request("DISCONNECT")
+ advertiser.wait_disconnected(timeout=1)
+
+def test_p2ps_channel_both_connected_different(dev, apdev):
+ """P2PS connection with P2PS method - stations connected on different channel"""
+ if dev[0].get_mcc() > 1:
+ raise HwsimSkip('Skip due to MCC being enabled')
+
+ set_no_group_iface(dev[0], 0)
+ set_no_group_iface(dev[1], 0)
+
+ try:
+ hapd1 = hostapd.add_ap(apdev[0],
+ { "ssid": 'bss-channel-3', "channel": '3' })
+
+ hapd2 = hostapd.add_ap(apdev[1],
+ { "ssid": 'bss-channel-10', "channel": '10' })
+
+ dev[0].connect("bss-channel-3", key_mgmt="NONE", scan_freq="2422")
+ dev[1].connect("bss-channel-10", key_mgmt="NONE", scan_freq="2457")
+
+ p2ps_advertise(r_dev=dev[0], r_role='2',
+ svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='I can receive files upto size 2 GB')
+ [adv_id, rcvd_svc_name] = p2ps_exact_seek(i_dev=dev[1], r_dev=dev[0],
+ svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='2 GB')
+
+ ev1, ev0 = p2ps_provision(dev[1], dev[0], adv_id, auto_accept=False,
+ handler=disconnect_handler)
+ p2ps_connect_pd(dev[0], dev[1], ev0, ev1)
+ freq = dev[0].get_group_status_field('freq')
+ if freq != '2457':
+ raise Exception('Unexpected frequency for group 2457 != ' + freq)
+ finally:
+ remove_group(dev[0], dev[1])
+ dev[0].global_request("P2P_SERVICE_DEL asp all")
+
+def test_p2ps_channel_both_connected_different_mcc(dev, apdev):
+ """P2PS connection with P2PS method - stations connected on different channels with mcc"""
+ if dev[0].get_mcc() == 1:
+ raise HwsimSkip('Skip case due to MCC not enabled')
+
+ set_no_group_iface(dev[0], 0)
+ set_no_group_iface(dev[1], 0)
+
+ try:
+ hapd1 = hostapd.add_ap(apdev[0],
+ { "ssid": 'bss-channel-3', "channel": '3' })
+
+ hapd2 = hostapd.add_ap(apdev[1],
+ { "ssid": 'bss-channel-10', "channel": '10' })
+
+ dev[0].connect("bss-channel-3", key_mgmt="NONE", scan_freq="2422")
+ dev[1].connect("bss-channel-10", key_mgmt="NONE", scan_freq="2457")
+
+ (grp_ifname0, grp_ifname1, ifnames) = p2ps_connect_p2ps_method(dev, keep_group=True)
+ freq = dev[0].get_group_status_field('freq')
+
+ if freq != '2422' and freq != '2457':
+ raise Exception('Unexpected frequency for group =' + freq)
+ finally:
+ remove_group(dev[0], dev[1])
+ dev[0].global_request("P2P_SERVICE_DEL asp all")
+
+def clear_disallow_handler(seeker, advertiser):
+ advertiser.global_request("P2P_SET disallow_freq ")
+
+@remote_compatible
+def test_p2ps_channel_disallow_freq(dev, apdev):
+ """P2PS connection with P2PS method - disallow freqs"""
+ set_no_group_iface(dev[0], 0)
+ set_no_group_iface(dev[1], 0)
+
+ try:
+ dev[0].global_request("P2P_SET disallow_freq 2412-2457")
+ dev[1].global_request("P2P_SET disallow_freq 2417-2462")
+
+ p2ps_advertise(r_dev=dev[0], r_role='2',
+ svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='I can receive files upto size 2 GB')
+
+ [adv_id, rcvd_svc_name] = p2ps_exact_seek(i_dev=dev[1], r_dev=dev[0],
+ svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='2 GB')
+
+ ev1, ev0 = p2ps_provision(dev[1], dev[0], adv_id, auto_accept=False,
+ handler=clear_disallow_handler)
+ p2ps_connect_pd(dev[0], dev[1], ev0, ev1)
+
+ freq = dev[0].get_group_status_field('freq')
+ if freq != '2412':
+ raise Exception('Unexpected frequency for group 2412 != ' + freq)
+ finally:
+ remove_group(dev[0], dev[1])
+ dev[0].global_request("P2P_SERVICE_DEL asp all")
+ dev[0].global_request("P2P_SET disallow_freq ")
+ dev[1].global_request("P2P_SET disallow_freq ")
+
+def test_p2ps_channel_sta_connected_disallow_freq(dev, apdev):
+ """P2PS connection with P2PS method - one station and disallow freqs"""
+ if dev[0].get_mcc() > 1:
+ raise HwsimSkip('Skip due to MCC being enabled')
+
+ set_no_group_iface(dev[0], 0)
+ set_no_group_iface(dev[1], 0)
+
+ try:
+ dev[0].global_request("P2P_SET disallow_freq 2437")
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": 'bss-channel-6', "channel": '6' })
+
+ dev[1].connect("bss-channel-6", key_mgmt="NONE", scan_freq="2437")
+
+ p2ps_advertise(r_dev=dev[0], r_role='2',
+ svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='I can receive files upto size 2 GB')
+ [adv_id, rcvd_svc_name] = p2ps_exact_seek(i_dev=dev[1], r_dev=dev[0],
+ svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='2 GB')
+
+ ev1, ev0 = p2ps_provision(dev[1], dev[0], adv_id, auto_accept=False,
+ handler=clear_disallow_handler)
+ p2ps_connect_pd(dev[0], dev[1], ev0, ev1)
+
+ freq = dev[0].get_group_status_field('freq')
+ if freq != '2437':
+ raise Exception('Unexpected frequency for group 2437 != ' + freq)
+ finally:
+ remove_group(dev[0], dev[1])
+ dev[0].global_request("P2P_SET disallow_freq ")
+ dev[0].global_request("P2P_SERVICE_DEL asp all")
+
+def test_p2ps_channel_sta_connected_disallow_freq_mcc(dev, apdev):
+ """P2PS connection with P2PS method - one station and disallow freqs with mcc"""
+ with HWSimRadio(n_channels=2) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+
+ if wpas.get_mcc() < 2:
+ raise Exception("New radio does not support MCC")
+
+ set_no_group_iface(dev[0], 0)
+ set_no_group_iface(wpas, 0)
+
+ try:
+ dev[0].global_request("P2P_SET disallow_freq 2437")
+ hapd1 = hostapd.add_ap(apdev[0],
+ { "ssid": 'bss-channel-6', "channel": '6' })
+
+ wpas.connect("bss-channel-6", key_mgmt="NONE", scan_freq="2437")
+
+ tmpdev = [ dev[0], wpas ]
+ (grp_ifname0, grp_ifname1, ifnames) = p2ps_connect_p2ps_method(tmpdev, keep_group=True)
+
+ freq = dev[0].get_group_status_field('freq')
+ if freq == '2437':
+ raise Exception('Unexpected frequency=2437')
+ finally:
+ remove_group(dev[0], wpas)
+ dev[0].global_request("P2P_SET disallow_freq ")
+ dev[0].global_request("P2P_SERVICE_DEL asp all")
+
+@remote_compatible
+def test_p2ps_active_go_adv(dev, apdev):
+ """P2PS connection with P2PS method - active GO on advertiser"""
+ set_no_group_iface(dev[0], 0)
+ set_no_group_iface(dev[1], 0)
+
+ try:
+ # Add a P2P GO
+ dev[0].global_request("P2P_GROUP_ADD persistent")
+ ev = dev[0].wait_global_event(["P2P-GROUP-STARTED"], timeout=10)
+ if ev is None:
+ raise Exception("P2P-GROUP-STARTED timeout on " + dev[0].p2p_dev_addr())
+
+ dev[0].group_form_result(ev)
+
+ p2ps_advertise(r_dev=dev[0], r_role='4',
+ svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='I can receive files upto size 2 GB')
+ [adv_id, rcvd_svc_name] = p2ps_exact_seek(i_dev=dev[1], r_dev=dev[0],
+ svc_name='org.wi-fi.wfds.send.rx',
+ single_peer_expected=False)
+
+ ev1, ev0 = p2ps_provision(dev[1], dev[0], adv_id)
+
+ # explicitly stop find/listen as otherwise the long listen started by
+ # the advertiser would prevent the seeker to connect with the P2P GO
+ dev[0].p2p_stop_find()
+ p2ps_connect_pd(dev[0], dev[1], ev0, ev1)
+ finally:
+ remove_group(dev[0], dev[1])
+ dev[0].global_request("P2P_SERVICE_DEL asp all")
+
+@remote_compatible
+def test_p2ps_active_go_seeker(dev, apdev):
+ """P2PS connection with P2PS method - active GO on seeker"""
+ set_no_group_iface(dev[0], 0)
+ set_no_group_iface(dev[1], 0)
+
+ try:
+ # Add a P2P GO on the seeker
+ dev[1].global_request("P2P_GROUP_ADD persistent")
+ ev = dev[1].wait_global_event(["P2P-GROUP-STARTED"], timeout=10)
+ if ev is None:
+ raise Exception("P2P-GROUP-STARTED timeout on " + dev[1].p2p_dev_addr())
+
+ res = dev[1].group_form_result(ev)
+
+ p2ps_advertise(r_dev=dev[0], r_role='2',
+ svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='I can receive files upto size 2 GB')
+ [adv_id, rcvd_svc_name] = p2ps_exact_seek(i_dev=dev[1], r_dev=dev[0],
+ svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='2 GB')
+
+ ev1, ev0 = p2ps_provision(dev[1], dev[0], adv_id)
+ p2ps_connect_pd(dev[0], dev[1], ev0, ev1,
+ join_extra=" freq=" + res['freq'])
+ finally:
+ remove_group(dev[0], dev[1])
+ dev[0].global_request("P2P_SERVICE_DEL asp all")
+
+def test_p2ps_channel_active_go_and_station_same(dev, apdev):
+ """P2PS connection, active P2P GO and station on channel"""
+ set_no_group_iface(dev[2], 0)
+ set_no_group_iface(dev[1], 0)
+
+ dev[2].global_request("P2P_SET listen_channel 11")
+ dev[1].global_request("P2P_SET listen_channel 11")
+ try:
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": 'bss-channel-11', "channel": '11' })
+
+ dev[2].connect("bss-channel-11", key_mgmt="NONE", scan_freq="2462")
+
+ # Add a P2P GO on the seeker
+ dev[1].global_request("P2P_GROUP_ADD freq=2462 persistent")
+ ev = dev[1].wait_global_event(["P2P-GROUP-STARTED"], timeout=10)
+ if ev is None:
+ raise Exception("P2P-GROUP-STARTED timeout on " + dev[1].p2p_dev_addr())
+
+ dev[1].group_form_result(ev)
+
+ p2ps_advertise(r_dev=dev[2], r_role='2',
+ svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='I can receive files upto size 2 GB')
+ [adv_id, rcvd_svc_name] = p2ps_exact_seek(i_dev=dev[1], r_dev=dev[2],
+ svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='2 GB')
+
+ ev1, ev0 = p2ps_provision(dev[1], dev[2], adv_id)
+ p2ps_connect_pd(dev[2], dev[1], ev0, ev1, join_extra=" freq=2462")
+ finally:
+ remove_group(dev[2], dev[1])
+ dev[2].global_request("P2P_SERVICE_DEL asp all")
+ for i in range(1, 3):
+ set_random_listen_chan(dev[i])
+
+def test_p2ps_channel_active_go_and_station_different(dev, apdev):
+ """P2PS connection, active P2P GO and station on channel"""
+ if dev[0].get_mcc() > 1:
+ raise HwsimSkip('Skip due to MCC being enabled')
+
+ set_no_group_iface(dev[0], 0)
+ set_no_group_iface(dev[1], 0)
+
+ try:
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": 'bss-channel-2', "channel": '2' })
+
+ dev[0].connect("bss-channel-2", key_mgmt="NONE", scan_freq="2417")
+
+ # Add a P2P GO on the seeker. Force the listen channel to be the same,
+ # as extended listen will not kick as long as P2P GO is waiting for
+ # initial connection.
+ dev[1].global_request("P2P_SET listen_channel 11")
+ dev[1].global_request("P2P_GROUP_ADD freq=2462 persistent")
+ ev = dev[1].wait_global_event(["P2P-GROUP-STARTED"], timeout=10)
+ if ev is None:
+ raise Exception("P2P-GROUP-STARTED timeout on " + dev[1].p2p_dev_addr())
+
+ dev[1].group_form_result(ev)
+
+ p2ps_advertise(r_dev=dev[0], r_role='2',
+ svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='I can receive files upto size 2 GB')
+ [adv_id, rcvd_svc_name] = p2ps_exact_seek(i_dev=dev[1], r_dev=dev[0],
+ svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='2 GB')
+
+ ev1, ev0 = p2ps_provision(dev[1], dev[0], adv_id, auto_accept=False,
+ handler=disconnect_handler, adv_role='2',
+ seeker_role='4')
+ p2ps_connect_pd(dev[0], dev[1], ev0, ev1)
+ freq = dev[0].get_group_status_field('freq')
+ if freq != '2462':
+ raise Exception('Unexpected frequency for group 2462!=' + freq)
+ finally:
+ dev[0].global_request("P2P_SERVICE_DEL asp all")
+ set_random_listen_chan(dev[1])
+
+@remote_compatible
+def test_p2ps_channel_active_go_and_station_different_mcc(dev, apdev):
+ """P2PS connection, active P2P GO and station on channel"""
+ if dev[0].get_mcc() == 1:
+ raise HwsimSkip('Skip due to MCC not being enabled')
+
+ set_no_group_iface(dev[0], 0)
+ set_no_group_iface(dev[1], 0)
+
+ try:
+ hapd = hostapd.add_ap(apdev[0],
+ { "ssid": 'bss-channel-6', "channel": '6' })
+
+ dev[0].connect("bss-channel-6", key_mgmt="NONE", scan_freq="2437")
+
+ # Add a P2P GO on the seeker
+ dev[1].global_request("P2P_GROUP_ADD freq=2462 persistent")
+ ev = dev[1].wait_global_event(["P2P-GROUP-STARTED"], timeout=10)
+ if ev is None:
+ raise Exception("P2P-GROUP-STARTED timeout on " + dev[1].p2p_dev_addr())
+
+ dev[1].group_form_result(ev)
+
+ p2ps_advertise(r_dev=dev[0], r_role='2',
+ svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='I can receive files upto size 2 GB')
+ [adv_id, rcvd_svc_name] = p2ps_exact_seek(i_dev=dev[1], r_dev=dev[0],
+ svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='2 GB')
+
+ ev1, ev0 = p2ps_provision(dev[1], dev[0], adv_id)
+ p2ps_connect_pd(dev[0], dev[1], ev0, ev1)
+ finally:
+ remove_group(dev[0], dev[1])
+ dev[0].request("DISCONNECT")
+ hapd.disable()
+ dev[0].global_request("P2P_SERVICE_DEL asp all")
+
+def test_p2ps_connect_p2p_device(dev):
+ """P2PS connection using cfg80211 P2P Device"""
+ run_p2ps_connect_p2p_device(dev, 0)
+
+def test_p2ps_connect_p2p_device_no_group_iface(dev):
+ """P2PS connection using cfg80211 P2P Device (no separate group interface)"""
+ run_p2ps_connect_p2p_device(dev, 1)
+
+def run_p2ps_connect_p2p_device(dev, no_group_iface):
+ with HWSimRadio(use_p2p_device=True) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+ wpas.global_request("SET p2p_no_group_iface %d" % no_group_iface)
+
+ p2ps_advertise(r_dev=dev[0], r_role='1',
+ svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='I can receive files upto size 2 GB')
+ [adv_id, rcvd_svc_name] = p2ps_exact_seek(i_dev=wpas, r_dev=dev[0],
+ svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='2 GB')
+
+ ev1, ev0 = p2ps_provision(wpas, dev[0], adv_id)
+ p2ps_connect_pd(dev[0], wpas, ev0, ev1)
+
+ ev0 = dev[0].global_request("P2P_SERVICE_DEL asp " + str(adv_id))
+ if ev0 is None:
+ raise Exception("Unable to remove the advertisement instance")
+ remove_group(dev[0], wpas)
+
+def test_p2ps_connect_p2p_device2(dev):
+ """P2PS connection using cfg80211 P2P Device (reverse)"""
+ run_p2ps_connect_p2p_device2(dev, 0)
+
+def test_p2ps_connect_p2p_device2_no_group_iface(dev):
+ """P2PS connection using cfg80211 P2P Device (reverse) (no separate group interface)"""
+ run_p2ps_connect_p2p_device2(dev, 1)
+
+def run_p2ps_connect_p2p_device2(dev, no_group_iface):
+ with HWSimRadio(use_p2p_device=True) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+ wpas.global_request("SET p2p_no_group_iface %d" % no_group_iface)
+
+ p2ps_advertise(r_dev=wpas, r_role='1',
+ svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='I can receive files upto size 2 GB')
+ [adv_id, rcvd_svc_name] = p2ps_exact_seek(i_dev=dev[0], r_dev=wpas,
+ svc_name='org.wi-fi.wfds.send.rx',
+ srv_info='2 GB')
+
+ ev1, ev0 = p2ps_provision(dev[0], wpas, adv_id)
+ p2ps_connect_pd(wpas, dev[0], ev0, ev1)
+
+ ev0 = wpas.global_request("P2P_SERVICE_DEL asp " + str(adv_id))
+ if ev0 is None:
+ raise Exception("Unable to remove the advertisement instance")
+ remove_group(wpas, dev[0])
+
+@remote_compatible
+def test_p2ps_connect_p2ps_method_no_pin(dev):
+ """P2P group formation using P2PS method without specifying PIN"""
+ dev[0].p2p_listen()
+ dev[1].p2p_go_neg_auth(dev[0].p2p_dev_addr(), None, "p2ps", go_intent=15)
+ dev[1].p2p_listen()
+ i_res = dev[0].p2p_go_neg_init(dev[1].p2p_dev_addr(), None, "p2ps",
+ timeout=20, go_intent=0)
+ r_res = dev[1].p2p_go_neg_auth_result()
+ logger.debug("i_res: " + str(i_res))
+ logger.debug("r_res: " + str(r_res))
+ check_grpform_results(i_res, r_res)
+ remove_group(dev[0], dev[1])
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import logging
logger = logging.getLogger()
import time
from utils import skip_with_fips
from wlantest import Wlantest
+@remote_compatible
def test_peerkey(dev, apdev):
"""RSN AP and PeerKey between two STAs"""
ssid = "test-peerkey"
passphrase = "12345678"
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['peerkey'] = "1"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="2412", peerkey=True)
dev[1].connect(ssid, psk=passphrase, scan_freq="2412", peerkey=True)
passphrase = "12345678"
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['peerkey'] = "1"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="2412", peerkey=True)
dev[1].connect(ssid, psk=passphrase, scan_freq="2412", peerkey=True)
dev[0].request("STKSTART " + dev[2].p2p_interface_addr())
time.sleep(0.5)
+@remote_compatible
def test_peerkey_pairwise_mismatch(dev, apdev):
"""RSN TKIP+CCMP AP and PeerKey between two STAs using different ciphers"""
skip_with_fips(dev[0])
- wt = Wlantest()
- wt.flush()
- wt.add_passphrase("12345678")
ssid = "test-peerkey"
passphrase = "12345678"
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
params['peerkey'] = "1"
params['rsn_pairwise'] = "TKIP CCMP"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ Wlantest.setup(hapd)
+ wt = Wlantest()
+ wt.flush()
+ wt.add_passphrase("12345678")
dev[0].connect(ssid, psk=passphrase, scan_freq="2412", peerkey=True,
pairwise="CCMP")
import time
import hostapd
+import hwsim_utils
from wpasupplicant import WpaSupplicant
from utils import alloc_fail
from test_ap_eap import eap_connect
def test_pmksa_cache_on_roam_back(dev, apdev):
"""PMKSA cache to skip EAP on reassociation back to same AP"""
params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
eap="GPSK", identity="gpsk user",
if pmksa['opportunistic'] != '0':
raise Exception("Unexpected opportunistic PMKSA cache entry")
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
bssid2 = apdev[1]['bssid']
dev[0].dump_monitor()
dev[0].wait_disconnected(timeout=5)
dev[0].wait_connected(timeout=15, error="Reconnection timed out")
+def test_pmksa_cache_and_reauth(dev, apdev):
+ """PMKSA caching and EAPOL reauthentication"""
+ params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+ dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
+ eap="GPSK", identity="gpsk user",
+ password="abcdefghijklmnop0123456789abcdef",
+ scan_freq="2412")
+
+ hostapd.add_ap(apdev[1], params)
+ bssid2 = apdev[1]['bssid']
+
+ dev[0].dump_monitor()
+ logger.info("Roam to AP2")
+ # It can take some time for the second AP to become ready to reply to Probe
+ # Request frames especially under heavy CPU load, so allow couple of rounds
+ # of scanning to avoid reporting errors incorrectly just because of scans
+ # not having seen the target AP.
+ for i in range(0, 10):
+ dev[0].scan(freq="2412")
+ if dev[0].get_bss(bssid2) is not None:
+ break
+ logger.info("Scan again to find target AP")
+ dev[0].request("ROAM " + bssid2)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
+ if ev is None:
+ raise Exception("EAP success timed out")
+ dev[0].wait_connected(timeout=10, error="Roaming timed out")
+
+ dev[0].dump_monitor()
+ logger.info("Roam back to AP1")
+ dev[0].scan(freq="2412")
+ dev[0].request("ROAM " + bssid)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
+ "CTRL-EVENT-CONNECTED"], timeout=10)
+ if ev is None:
+ raise Exception("Roaming with the AP timed out")
+ if "CTRL-EVENT-EAP-STARTED" in ev:
+ raise Exception("Unexpected EAP exchange")
+
+ # Verify EAPOL reauthentication after PMKSA caching
+ hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
+ if ev is None:
+ raise Exception("EAP authentication did not start")
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=5)
+ if ev is None:
+ raise Exception("EAP authentication did not succeed")
+
def test_pmksa_cache_opportunistic_only_on_sta(dev, apdev):
"""Opportunistic PMKSA caching enabled only on station"""
params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
eap="GPSK", identity="gpsk user",
if pmksa['opportunistic'] != '0':
raise Exception("Unexpected opportunistic PMKSA cache entry")
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
bssid2 = apdev[1]['bssid']
dev[0].dump_monitor()
"""Opportunistic PMKSA caching"""
params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
params['okc'] = "1"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
eap="GPSK", identity="gpsk user",
if pmksa['opportunistic'] != '0':
raise Exception("Unexpected opportunistic PMKSA cache entry")
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
bssid2 = apdev[1]['bssid']
dev[0].dump_monitor()
"""Opportunistic PMKSA caching with connect API"""
params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
params['okc'] = "1"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
if pmksa['opportunistic'] != '0':
raise Exception("Unexpected opportunistic PMKSA cache entry")
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
bssid2 = apdev[1]['bssid']
wpas.dump_monitor()
logger.info("Roam to AP2")
- wpas.scan_for_bss(bssid2, freq="2412")
+ wpas.scan_for_bss(bssid2, freq="2412", force_scan=True)
wpas.request("ROAM " + bssid2)
ev = wpas.wait_event(["CTRL-EVENT-EAP-STARTED",
"CTRL-EVENT-CONNECTED"], timeout=10)
def test_pmksa_cache_expiration(dev, apdev):
"""PMKSA cache entry expiration"""
params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
dev[0].request("SET dot11RSNAConfigPMKLifetime 10")
dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
def test_pmksa_cache_expiration_disconnect(dev, apdev):
"""PMKSA cache entry expiration (disconnect)"""
params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
dev[0].request("SET dot11RSNAConfigPMKLifetime 2")
dev[0].request("SET dot11RSNAConfigPMKReauthThreshold 100")
params['acct_server_addr'] = "127.0.0.1"
params['acct_server_port'] = "1813"
params['acct_server_shared_secret'] = "radius"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
dev[0].connect("cui", proto="RSN", key_mgmt="WPA-EAP",
eap="GPSK", identity="gpsk-cui",
if state != "COMPLETED":
raise Exception("Reauthentication did not complete")
-def test_pmksa_cache_preauth(dev, apdev):
- """RSN pre-authentication to generate PMKSA cache entry"""
+def generic_pmksa_cache_preauth(dev, apdev, extraparams, identity, databridge,
+ force_disconnect=False):
+ if not extraparams:
+ extraparams = [{}, {}]
try:
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
params['bridge'] = 'ap-br0'
- hostapd.add_ap(apdev[0]['ifname'], params)
- subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
- subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
- eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
+ for key, value in extraparams[0].iteritems():
+ params[key] = value
+
+ hapd = hostapd.add_ap(apdev[0], params)
+ hapd.cmd_execute(['brctl', 'setfd', 'ap-br0', '0'])
+ hapd.cmd_execute(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
+ eap_connect(dev[0], hapd, "PAX", identity,
password_hex="0123456789abcdef0123456789abcdef")
+ # Verify connectivity in the correct VLAN
+ hwsim_utils.test_connectivity_iface(dev[0], hapd, databridge)
+
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
params['bridge'] = 'ap-br0'
params['rsn_preauth'] = '1'
- params['rsn_preauth_interfaces'] = 'ap-br0'
- hostapd.add_ap(apdev[1]['ifname'], params)
+ params['rsn_preauth_interfaces'] = databridge
+ for key, value in extraparams[1].iteritems():
+ params[key] = value
+ hostapd.add_ap(apdev[1], params)
bssid1 = apdev[1]['bssid']
dev[0].scan(freq="2412")
success = False
if pmksa['pmkid'] != pmksa2['pmkid']:
raise Exception("Unexpected PMKID change")
- finally:
- subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'])
- subprocess.call(['brctl', 'delbr', 'ap-br0'])
+ # Verify connectivity in the correct VLAN
+ hwsim_utils.test_connectivity_iface(dev[0], hapd, databridge)
-def test_pmksa_cache_preauth_vlan_enabled(dev, apdev):
- """RSN pre-authentication to generate PMKSA cache entry (dynamic_vlan optional but station without VLAN set)"""
- try:
- params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- params['bridge'] = 'ap-br0'
- params['dynamic_vlan'] = '1'
- hostapd.add_ap(apdev[0]['ifname'], params)
- subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
- subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
- eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
- password_hex="0123456789abcdef0123456789abcdef")
+ if not force_disconnect:
+ return
- params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- params['bridge'] = 'ap-br0'
- params['rsn_preauth'] = '1'
- params['rsn_preauth_interfaces'] = 'ap-br0'
- params['dynamic_vlan'] = '1'
- hostapd.add_ap(apdev[1]['ifname'], params)
- bssid1 = apdev[1]['bssid']
- dev[0].scan(freq="2412")
- success = False
- status_seen = False
- for i in range(0, 50):
- if not status_seen:
- status = dev[0].request("STATUS")
- if "Pre-authentication EAPOL state machines:" in status:
- status_seen = True
- time.sleep(0.1)
- pmksa = dev[0].get_pmksa(bssid1)
- if pmksa:
- success = True
- break
- if not success:
- raise Exception("No PMKSA cache entry created from pre-authentication")
- if not status_seen:
- raise Exception("Pre-authentication EAPOL status was not available")
-
- dev[0].scan(freq="2412")
- if "[WPA2-EAP-CCMP-preauth]" not in dev[0].request("SCAN_RESULTS"):
- raise Exception("Scan results missing RSN element info")
- dev[0].request("ROAM " + bssid1)
- ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
- "CTRL-EVENT-CONNECTED"], timeout=10)
- if ev is None:
- raise Exception("Roaming with the AP timed out")
- if "CTRL-EVENT-EAP-STARTED" in ev:
- raise Exception("Unexpected EAP exchange")
- pmksa2 = dev[0].get_pmksa(bssid1)
- if pmksa2 is None:
- raise Exception("No PMKSA cache entry")
- if pmksa['pmkid'] != pmksa2['pmkid']:
- raise Exception("Unexpected PMKID change")
+ # Disconnect the STA from both APs to avoid forceful ifdown by the
+ # test script on a VLAN that this has an associated STA. That used to
+ # trigger a mac80211 warning.
+ dev[0].request("DISCONNECT")
+ hapd.request("DISABLE")
finally:
- subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'])
- subprocess.call(['brctl', 'delbr', 'ap-br0'])
+ hostapd.cmd_execute(apdev[0], ['ip', 'link', 'set', 'dev',
+ 'ap-br0', 'down', '2>', '/dev/null'],
+ shell=True)
+ hostapd.cmd_execute(apdev[0], ['brctl', 'delbr', 'ap-br0',
+ '2>', '/dev/null'], shell=True)
+
+def test_pmksa_cache_preauth(dev, apdev):
+ """RSN pre-authentication to generate PMKSA cache entry"""
+ generic_pmksa_cache_preauth(dev, apdev, None,
+ "pax.user@example.com", "ap-br0")
+
+def test_pmksa_cache_preauth_per_sta_vif(dev, apdev):
+ """RSN pre-authentication to generate PMKSA cache entry with per_sta_vif"""
+ extraparams = [{}, {}]
+ extraparams[0]['per_sta_vif'] = "1"
+ extraparams[1]['per_sta_vif'] = "1"
+ generic_pmksa_cache_preauth(dev, apdev, extraparams,
+ "pax.user@example.com", "ap-br0")
+
+def test_pmksa_cache_preauth_vlan_enabled(dev, apdev):
+ """RSN pre-authentication to generate PMKSA cache entry (dynamic_vlan optional but station without VLAN set)"""
+ extraparams = [{}, {}]
+ extraparams[0]['dynamic_vlan'] = '1'
+ extraparams[1]['dynamic_vlan'] = '1'
+ generic_pmksa_cache_preauth(dev, apdev, extraparams,
+ "pax.user@example.com", "ap-br0")
+
+def test_pmksa_cache_preauth_vlan_enabled_per_sta_vif(dev, apdev):
+ """RSN pre-authentication to generate PMKSA cache entry (dynamic_vlan optional but station without VLAN set, with per_sta_vif enabled)"""
+ extraparams = [{}, {}]
+ extraparams[0]['per_sta_vif'] = "1"
+ extraparams[1]['per_sta_vif'] = "1"
+ extraparams[0]['dynamic_vlan'] = '1'
+ extraparams[1]['dynamic_vlan'] = '1'
+ generic_pmksa_cache_preauth(dev, apdev, extraparams,
+ "pax.user@example.com", "ap-br0")
def test_pmksa_cache_preauth_vlan_used(dev, apdev):
"""RSN pre-authentication to generate PMKSA cache entry (station with VLAN set)"""
+ run_pmksa_cache_preauth_vlan_used(dev, apdev, None, force_disconnect=True)
+
+def run_pmksa_cache_preauth_vlan_used(dev, apdev, extraparams=None,
+ force_disconnect=False):
try:
subprocess.call(['brctl', 'addbr', 'brvlan1'])
subprocess.call(['brctl', 'setfd', 'brvlan1', '0'])
- params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- params['bridge'] = 'ap-br0'
- params['dynamic_vlan'] = '1'
- params['vlan_file'] = 'hostapd.wlan3.vlan'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
- subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
- subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
- eap_connect(dev[0], apdev[0], "PAX", "vlan1",
- password_hex="0123456789abcdef0123456789abcdef")
-
- params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- params['bridge'] = 'ap-br0'
- params['rsn_preauth'] = '1'
- params['rsn_preauth_interfaces'] = 'brvlan1'
- params['dynamic_vlan'] = '1'
- params['vlan_file'] = 'hostapd.wlan4.vlan'
- hostapd.add_ap(apdev[1]['ifname'], params)
- bssid1 = apdev[1]['bssid']
- dev[0].scan(freq="2412")
- success = False
- status_seen = False
- for i in range(0, 50):
- if not status_seen:
- status = dev[0].request("STATUS")
- if "Pre-authentication EAPOL state machines:" in status:
- status_seen = True
- time.sleep(0.1)
- pmksa = dev[0].get_pmksa(bssid1)
- if pmksa:
- success = True
- break
- if not success:
- raise Exception("No PMKSA cache entry created from pre-authentication")
- if not status_seen:
- raise Exception("Pre-authentication EAPOL status was not available")
-
- dev[0].scan(freq="2412")
- if "[WPA2-EAP-CCMP-preauth]" not in dev[0].request("SCAN_RESULTS"):
- raise Exception("Scan results missing RSN element info")
- dev[0].request("ROAM " + bssid1)
- ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
- "CTRL-EVENT-CONNECTED"], timeout=10)
- if ev is None:
- raise Exception("Roaming with the AP timed out")
- if "CTRL-EVENT-EAP-STARTED" in ev:
- raise Exception("Unexpected EAP exchange")
- pmksa2 = dev[0].get_pmksa(bssid1)
- if pmksa2 is None:
- raise Exception("No PMKSA cache entry")
- if pmksa['pmkid'] != pmksa2['pmkid']:
- raise Exception("Unexpected PMKID change")
-
- # Disconnect the STA from both APs to avoid forceful ifdown by the
- # test script on a VLAN that this has an associated STA. That used to
- # trigger a mac80211 warning.
- dev[0].request("DISCONNECT")
- hapd.request("DISABLE")
-
+ if not extraparams:
+ extraparams = [{}, {}]
+ extraparams[0]['dynamic_vlan'] = '1'
+ extraparams[0]['vlan_file'] = 'hostapd.wlan3.vlan'
+ extraparams[1]['dynamic_vlan'] = '1'
+ extraparams[1]['vlan_file'] = 'hostapd.wlan4.vlan'
+ generic_pmksa_cache_preauth(dev, apdev, extraparams,
+ "vlan1", "brvlan1",
+ force_disconnect=force_disconnect)
finally:
- subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
- stderr=open('/dev/null', 'w'))
subprocess.call(['ip', 'link', 'set', 'dev', 'brvlan1', 'down'])
subprocess.call(['ip', 'link', 'set', 'dev', 'wlan3.1', 'down'],
stderr=open('/dev/null', 'w'))
stderr=open('/dev/null', 'w'))
subprocess.call(['brctl', 'delif', 'brvlan1', 'wlan4.1'],
stderr=open('/dev/null', 'w'))
- subprocess.call(['brctl', 'delbr', 'ap-br0'],
- stderr=open('/dev/null', 'w'))
subprocess.call(['brctl', 'delbr', 'brvlan1'])
+def test_pmksa_cache_preauth_vlan_used_per_sta_vif(dev, apdev):
+ """RSN pre-authentication to generate PMKSA cache entry (station with VLAN set, per_sta_vif=1)"""
+ extraparams = [{}, {}]
+ extraparams[0]['per_sta_vif'] = "1"
+ extraparams[1]['per_sta_vif'] = "1"
+ run_pmksa_cache_preauth_vlan_used(dev, apdev, extraparams)
+
def test_pmksa_cache_disabled(dev, apdev):
"""PMKSA cache disabling on AP"""
params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
params['disable_pmksa_caching'] = '1'
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
eap="GPSK", identity="gpsk user",
password="abcdefghijklmnop0123456789abcdef",
scan_freq="2412")
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
bssid2 = apdev[1]['bssid']
dev[0].dump_monitor()
def test_pmksa_cache_ap_expiration(dev, apdev):
"""PMKSA cache entry expiring on AP"""
params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
eap="GPSK", identity="gpsk-user-session-timeout",
def test_pmksa_cache_multiple_sta(dev, apdev):
"""PMKSA cache with multiple stations"""
params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
+ for d in dev:
+ d.flush_scan_cache()
dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
eap="GPSK", identity="gpsk-user-session-timeout",
password="abcdefghijklmnop0123456789abcdef",
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5")
+ wpas.flush_scan_cache()
wpas.connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
eap="GPSK", identity="gpsk user",
password="abcdefghijklmnop0123456789abcdef",
scan_freq="2412")
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
bssid2 = apdev[1]['bssid']
logger.info("Roam to AP2")
for sta in [ dev[1], dev[0], dev[2], wpas ]:
sta.dump_monitor()
sta.scan_for_bss(bssid2, freq="2412")
- sta.request("ROAM " + bssid2)
+ if "OK" not in sta.request("ROAM " + bssid2):
+ raise Exception("ROAM command failed (" + sta.ifname + ")")
ev = sta.wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10)
if ev is None:
raise Exception("EAP success timed out")
sta.wait_connected(timeout=10, error="Roaming timed out")
+ sta.dump_monitor()
logger.info("Roam back to AP1")
for sta in [ dev[1], wpas, dev[0], dev[2] ]:
"""Opportunistic PMKSA caching with multiple stations"""
params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
params['okc'] = "1"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
+ for d in dev:
+ d.flush_scan_cache()
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5")
+ wpas.flush_scan_cache()
for sta in [ dev[0], dev[1], dev[2], wpas ]:
sta.connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
eap="GPSK", identity="gpsk user",
password="abcdefghijklmnop0123456789abcdef", okc=True,
scan_freq="2412")
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
bssid2 = apdev[1]['bssid']
logger.info("Roam to AP2")
pmksa2 = sta.get_pmksa(bssid2)
if pmksa2 is None:
raise Exception("No PMKSA cache entry created")
+ sta.dump_monitor()
logger.info("Roam back to AP1")
for sta in [ dev[0], dev[1], dev[2], wpas ]:
try:
_test_pmksa_cache_preauth_oom(dev, apdev)
finally:
- subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'])
- subprocess.call(['brctl', 'delbr', 'ap-br0'])
+ hostapd.cmd_execute(apdev[0], ['ip', 'link', 'set', 'dev', 'ap-br0',
+ 'down'])
+ hostapd.cmd_execute(apdev[0], ['brctl', 'delbr', 'ap-br0'])
def _test_pmksa_cache_preauth_oom(dev, apdev):
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
params['bridge'] = 'ap-br0'
- hostapd.add_ap(apdev[0]['ifname'], params)
- subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
- subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
- eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
+ hapd = hostapd.add_ap(apdev[0], params)
+ hostapd.cmd_execute(apdev[0], ['brctl', 'setfd', 'ap-br0', '0'])
+ hostapd.cmd_execute(apdev[0], ['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
+ eap_connect(dev[0], hapd, "PAX", "pax.user@example.com",
password_hex="0123456789abcdef0123456789abcdef",
bssid=apdev[0]['bssid'])
params['bridge'] = 'ap-br0'
params['rsn_preauth'] = '1'
params['rsn_preauth_interfaces'] = 'ap-br0'
- hapd = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[1], params)
bssid1 = apdev[1]['bssid']
tests = [ (1, "rsn_preauth_receive"),
_test_pmksa_cache_size_limit(dev, apdev)
finally:
try:
- hapd = hostapd.HostapdGlobal()
+ hapd = hostapd.HostapdGlobal(apdev[0])
hapd.flush()
hapd.remove(apdev[0]['ifname'])
except:
params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
bssid = apdev[0]['bssid']
params['bssid'] = bssid
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
def _test_pmksa_cache_size_limit(dev, apdev):
params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
bssid = apdev[0]['bssid'][0:15] + "%02x" % i
logger.info("Iteration with BSSID " + bssid)
params['bssid'] = bssid
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].request("BSS_FLUSH 0")
dev[0].scan_for_bss(bssid, freq=2412, only_new=True)
dev[0].select_network(id)
elif i + 1 != entries:
raise Exception("Unexpected number of PMKSA entries")
- hapd = hostapd.HostapdGlobal()
+ hapd = hostapd.HostapdGlobal(apdev[0])
hapd.flush()
hapd.remove(apdev[0]['ifname'])
def _test_pmksa_cache_preauth_timeout(dev, apdev):
dev[0].request("SET dot11RSNAConfigSATimeout 1")
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "PAX", "pax.user@example.com",
password_hex="0123456789abcdef0123456789abcdef",
bssid=apdev[0]['bssid'])
if "OK" not in dev[0].request("PREAUTH f2:11:22:33:44:55"):
def test_pmksa_cache_preauth_wpas_oom(dev, apdev):
"""RSN pre-authentication OOM in wpa_supplicant"""
params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
- hostapd.add_ap(apdev[0]['ifname'], params)
- eap_connect(dev[0], apdev[0], "PAX", "pax.user@example.com",
+ hapd = hostapd.add_ap(apdev[0], params)
+ eap_connect(dev[0], hapd, "PAX", "pax.user@example.com",
password_hex="0123456789abcdef0123456789abcdef",
bssid=apdev[0]['bssid'])
for i in range(1, 11):
if state.startswith('0:'):
break
time.sleep(0.05)
+
+def test_pmksa_cache_ctrl(dev, apdev):
+ """PMKSA cache control interface operations"""
+ params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+ addr = dev[0].own_addr()
+
+ dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
+ eap="GPSK", identity="gpsk user",
+ password="abcdefghijklmnop0123456789abcdef",
+ scan_freq="2412")
+
+ pmksa_sta = dev[0].get_pmksa(bssid)
+ if pmksa_sta is None:
+ raise Exception("No PMKSA cache entry created on STA")
+ pmksa_ap = hapd.get_pmksa(addr)
+ if pmksa_ap is None:
+ raise Exception("No PMKSA cache entry created on AP")
+ if pmksa_sta['pmkid'] != pmksa_ap['pmkid']:
+ raise Exception("PMKID mismatch in PMKSA cache entries")
+
+ if "OK" not in hapd.request("PMKSA_FLUSH"):
+ raise Exception("PMKSA_FLUSH failed")
+ pmksa_ap = hapd.get_pmksa(addr)
+ if pmksa_ap is not None:
+ raise Exception("PMKSA cache entry was not removed on AP")
+
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected()
+ dev[0].request("RECONNECT")
+ dev[0].wait_connected()
+
+ pmksa_sta2 = dev[0].get_pmksa(bssid)
+ if pmksa_sta2 is None:
+ raise Exception("No PMKSA cache entry created on STA after reconnect")
+ pmksa_ap2 = hapd.get_pmksa(addr)
+ if pmksa_ap2 is None:
+ raise Exception("No PMKSA cache entry created on AP after reconnect")
+ if pmksa_sta2['pmkid'] != pmksa_ap2['pmkid']:
+ raise Exception("PMKID mismatch in PMKSA cache entries after reconnect")
+ if pmksa_sta2['pmkid'] == pmksa_sta['pmkid']:
+ raise Exception("PMKID did not change after reconnect")
import time
import logging
logger = logging.getLogger()
-import subprocess
import hostapd
from wpasupplicant import WpaSupplicant
if ev is None:
raise Exception("Timeout while waiting radio work to start")
if "FAIL" not in dev[0].request("RADIO_WORK done 12345678"):
- raise Exception("Invalid RADIO_WORK done accepted");
+ raise Exception("Invalid RADIO_WORK done accepted")
if "FAIL" not in dev[0].request("RADIO_WORK foo"):
- raise Exception("Invalid RADIO_WORK accepted");
+ raise Exception("Invalid RADIO_WORK accepted")
dev[0].request("FLUSH")
items = dev[0].request("RADIO_WORK show")
if items != "":
def test_radio_work_cancel(dev, apdev):
"""Radio work items cancelled on interface removal"""
params = hostapd.wpa2_params(ssid="radio", passphrase="12345678")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5")
wpas.scan(freq="2412")
# RADIUS tests
-# Copyright (c) 2013-2015, Jouni Malinen <j@w1.fi>
+# Copyright (c) 2013-2016, Jouni Malinen <j@w1.fi>
#
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
+import binascii
import hashlib
import hmac
import logging
import time
import hostapd
-from utils import HwsimSkip, require_under_vm
+from utils import HwsimSkip, require_under_vm, skip_with_fips, fail_test
+from test_ap_hs20 import build_dhcp_ack
+from test_ap_ft import ft_params1
def connect(dev, ssid, wait_connect=True):
dev.connect(ssid, key_mgmt="WPA-EAP", scan_freq="2412",
password_hex="0123456789abcdef0123456789abcdef",
wait_connect=wait_connect)
+@remote_compatible
def test_radius_auth_unreachable(dev, apdev):
"""RADIUS Authentication server unreachable"""
params = hostapd.wpa2_eap_params(ssid="radius-auth")
params['auth_server_port'] = "18139"
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
connect(dev[0], "radius-auth", wait_connect=False)
ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"])
if ev is None:
params = hostapd.wpa2_eap_params(ssid="radius-auth")
params['auth_server_addr'] = "192.168.213.17"
params['auth_server_port'] = "18139"
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
subprocess.call(['ip', 'ro', 'del', '192.168.213.17', 'dev', 'lo'])
connect(dev[0], "radius-auth", wait_connect=False)
ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"])
subprocess.call(['ip', 'ro', 'replace', 'blackhole', '192.168.213.18'])
params = hostapd.wpa2_eap_params(ssid="radius-auth")
params['auth_server_addr'] = "192.168.213.18"
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
connect(dev[0], "radius-auth", wait_connect=False)
ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"])
if ev is None:
params['acct_server_addr'] = "127.0.0.1"
params['acct_server_port'] = "18139"
params['acct_server_shared_secret'] = "radius"
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
connect(dev[0], "radius-acct")
logger.info("Checking for RADIUS retries")
time.sleep(4)
params['acct_server_addr'] = "192.168.213.17"
params['acct_server_port'] = "18139"
params['acct_server_shared_secret'] = "radius"
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
subprocess.call(['ip', 'ro', 'del', '192.168.213.17', 'dev', 'lo'])
connect(dev[0], "radius-acct")
logger.info("Checking for RADIUS retries")
params['acct_server_addr'] = "192.168.213.18"
params['acct_server_port'] = "1813"
params['acct_server_shared_secret'] = "radius"
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
connect(dev[0], "radius-acct")
subprocess.call(['ip', 'ro', 'del', 'blackhole', '192.168.213.18'])
time.sleep(0.1)
params['acct_server_addr'] = "127.0.0.1"
params['acct_server_port'] = "18139"
params['acct_server_shared_secret'] = "radius"
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
for i in range(20):
connect(dev[0], "radius-acct")
dev[0].request("REMOVE_NETWORK all")
params['acct_server_shared_secret'] = "radius"
params['radius_auth_req_attr'] = [ "126:s:Operator", "77:s:testing" ]
params['radius_acct_req_attr'] = [ "126:s:Operator", "77:s:testing" ]
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
connect(dev[0], "radius-acct")
dev[1].connect("radius-acct", key_mgmt="WPA-EAP", scan_freq="2412",
eap="PAX", identity="test-class",
if acc_e < acc_s + 1:
raise Exception("Unexpected RADIUS server auth MIB value")
+def test_radius_acct_non_ascii_ssid(dev, apdev):
+ """RADIUS Accounting and non-ASCII SSID"""
+ params = hostapd.wpa2_eap_params()
+ params['acct_server_addr'] = "127.0.0.1"
+ params['acct_server_port'] = "1813"
+ params['acct_server_shared_secret'] = "radius"
+ ssid2 = "740665007374"
+ params['ssid2'] = ssid2
+ hostapd.add_ap(apdev[0], params)
+ dev[0].connect(ssid2=ssid2, key_mgmt="WPA-EAP", scan_freq="2412",
+ eap="PSK", identity="psk.user@example.com",
+ password_hex="0123456789abcdef0123456789abcdef")
+
def test_radius_acct_pmksa_caching(dev, apdev):
"""RADIUS Accounting with PMKSA caching"""
as_hapd = hostapd.Hostapd("as")
params['acct_server_addr'] = "127.0.0.1"
params['acct_server_port'] = "1813"
params['acct_server_shared_secret'] = "radius"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
connect(dev[0], "radius-acct")
dev[1].connect("radius-acct", key_mgmt="WPA-EAP", scan_freq="2412",
eap="PAX", identity="test-class",
params['acct_server_port'] = "1813"
params['acct_server_shared_secret'] = "radius"
params['radius_acct_interim_interval'] = "1"
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
connect(dev[0], "radius-acct")
logger.info("Checking for RADIUS counters")
as_mib_start = as_hapd.get_mib(param="radius_server")
params['acct_server_port'] = "18139"
params['acct_server_shared_secret'] = "radius"
params['radius_acct_interim_interval'] = "1"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
start = hapd.get_mib()
connect(dev[0], "radius-acct")
logger.info("Waiting for interium accounting updates")
if req_e < req_s + 2:
raise Exception("Unexpected RADIUS server acct MIB value")
+def test_radius_acct_interim_unreachable2(dev, apdev):
+ """RADIUS Accounting interim update with unreachable server (retry)"""
+ params = hostapd.wpa2_eap_params(ssid="radius-acct")
+ params['acct_server_addr'] = "127.0.0.1"
+ params['acct_server_port'] = "18139"
+ params['acct_server_shared_secret'] = "radius"
+ # Use long enough interim update interval to allow RADIUS retransmission
+ # case (3 seconds) to trigger first.
+ params['radius_acct_interim_interval'] = "4"
+ hapd = hostapd.add_ap(apdev[0], params)
+ start = hapd.get_mib()
+ connect(dev[0], "radius-acct")
+ logger.info("Waiting for interium accounting updates")
+ time.sleep(7.5)
+ end = hapd.get_mib()
+ req_s = int(start['radiusAccClientTimeouts'])
+ req_e = int(end['radiusAccClientTimeouts'])
+ if req_e < req_s + 2:
+ raise Exception("Unexpected RADIUS server acct MIB value")
+
+def test_radius_acct_ipaddr(dev, apdev):
+ """RADIUS Accounting and Framed-IP-Address"""
+ try:
+ _test_radius_acct_ipaddr(dev, apdev)
+ finally:
+ subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'down'],
+ stderr=open('/dev/null', 'w'))
+ subprocess.call(['brctl', 'delbr', 'ap-br0'],
+ stderr=open('/dev/null', 'w'))
+
+def _test_radius_acct_ipaddr(dev, apdev):
+ params = { "ssid": "radius-acct-open",
+ 'acct_server_addr': "127.0.0.1",
+ 'acct_server_port': "1813",
+ 'acct_server_shared_secret': "radius",
+ 'proxy_arp': '1',
+ 'ap_isolate': '1',
+ 'bridge': 'ap-br0' }
+ hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
+ try:
+ hapd.enable()
+ except:
+ # For now, do not report failures due to missing kernel support
+ raise HwsimSkip("Could not start hostapd - assume proxyarp not supported in kernel version")
+ bssid = apdev[0]['bssid']
+
+ subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
+ subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
+
+ dev[0].connect("radius-acct-open", key_mgmt="NONE", scan_freq="2412")
+ addr0 = dev[0].own_addr()
+
+ pkt = build_dhcp_ack(dst_ll="ff:ff:ff:ff:ff:ff", src_ll=bssid,
+ ip_src="192.168.1.1", ip_dst="255.255.255.255",
+ yiaddr="192.168.1.123", chaddr=addr0)
+ if "OK" not in hapd.request("DATA_TEST_FRAME ifname=ap-br0 " + binascii.hexlify(pkt)):
+ raise Exception("DATA_TEST_FRAME failed")
+
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected()
+ hapd.disable()
+
def send_and_check_reply(srv, req, code, error_cause=0):
reply = srv.SendPacket(req)
logger.debug("RADIUS response from hostapd")
if reply['Error-Cause'][0] != error_cause:
raise Exception("Unexpected Error-Cause: {}".format(reply['Error-Cause']))
+def test_radius_acct_psk(dev, apdev):
+ """RADIUS Accounting - PSK"""
+ as_hapd = hostapd.Hostapd("as")
+ params = hostapd.wpa2_params(ssid="radius-acct", passphrase="12345678")
+ params['acct_server_addr'] = "127.0.0.1"
+ params['acct_server_port'] = "1813"
+ params['acct_server_shared_secret'] = "radius"
+ hapd = hostapd.add_ap(apdev[0], params)
+ dev[0].connect("radius-acct", psk="12345678", scan_freq="2412")
+
+def test_radius_acct_psk_sha256(dev, apdev):
+ """RADIUS Accounting - PSK SHA256"""
+ as_hapd = hostapd.Hostapd("as")
+ params = hostapd.wpa2_params(ssid="radius-acct", passphrase="12345678")
+ params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
+ params['acct_server_addr'] = "127.0.0.1"
+ params['acct_server_port'] = "1813"
+ params['acct_server_shared_secret'] = "radius"
+ hapd = hostapd.add_ap(apdev[0], params)
+ dev[0].connect("radius-acct", key_mgmt="WPA-PSK-SHA256",
+ psk="12345678", scan_freq="2412")
+
+def test_radius_acct_ft_psk(dev, apdev):
+ """RADIUS Accounting - FT-PSK"""
+ as_hapd = hostapd.Hostapd("as")
+ params = ft_params1(ssid="radius-acct", passphrase="12345678")
+ params['acct_server_addr'] = "127.0.0.1"
+ params['acct_server_port'] = "1813"
+ params['acct_server_shared_secret'] = "radius"
+ hapd = hostapd.add_ap(apdev[0], params)
+ dev[0].connect("radius-acct", key_mgmt="FT-PSK",
+ psk="12345678", scan_freq="2412")
+
+def test_radius_acct_ieee8021x(dev, apdev):
+ """RADIUS Accounting - IEEE 802.1X"""
+ skip_with_fips(dev[0])
+ as_hapd = hostapd.Hostapd("as")
+ params = hostapd.radius_params()
+ params["ssid"] = "radius-acct-1x"
+ params["ieee8021x"] = "1"
+ params["wep_key_len_broadcast"] = "13"
+ params["wep_key_len_unicast"] = "13"
+ params['acct_server_addr'] = "127.0.0.1"
+ params['acct_server_port'] = "1813"
+ params['acct_server_shared_secret'] = "radius"
+ hapd = hostapd.add_ap(apdev[0], params)
+ dev[0].connect("radius-acct-1x", key_mgmt="IEEE8021X", eap="PSK",
+ identity="psk.user@example.com",
+ password_hex="0123456789abcdef0123456789abcdef",
+ scan_freq="2412")
+
def test_radius_das_disconnect(dev, apdev):
"""RADIUS Dynamic Authorization Extensions - Disconnect"""
try:
params['radius_das_require_event_timestamp'] = "1"
params['own_ip_addr'] = "127.0.0.1"
params['nas_identifier'] = "nas.example.com"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
connect(dev[0], "radius-das")
addr = dev[0].p2p_interface_addr()
sta = hapd.get_sta(addr)
params['radius_das_port'] = "3799"
params['radius_das_client'] = "127.0.0.1 secret"
params['radius_das_require_event_timestamp'] = "1"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
connect(dev[0], "radius-das")
addr = dev[0].p2p_interface_addr()
sta = hapd.get_sta(addr)
params['ca_cert'] = 'auth_serv/ca.pem'
params['server_cert'] = 'auth_serv/server.pem'
params['private_key'] = 'auth_serv/server.key'
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
params = hostapd.wpa2_eap_params(ssid="radius-ipv6")
params['auth_server_addr'] = "::0"
params['acct_server_port'] = "18139"
params['acct_server_shared_secret'] = "radius"
params['own_ip_addr'] = "::0"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
connect(dev[0], "radius-ipv6")
def test_radius_macacl(dev, apdev):
params = hostapd.radius_params()
params["ssid"] = "radius"
params["macaddr_acl"] = "2"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("radius", key_mgmt="NONE", scan_freq="2412")
def test_radius_macacl_acct(dev, apdev):
params['acct_server_addr'] = "127.0.0.1"
params['acct_server_port'] = "1813"
params['acct_server_shared_secret'] = "radius"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("radius", key_mgmt="NONE", scan_freq="2412")
dev[1].connect("radius", key_mgmt="NONE", scan_freq="2412")
dev[1].request("DISCONNECT")
params['acct_server_port'] = "1813"
params['acct_server_shared_secret'] = "testing"
params['radius_retry_primary_interval'] = "20"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
+ hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
hapd.set("auth_server_addr", "127.0.0.1")
hapd.set("auth_server_port", "1812")
hapd.set("auth_server_shared_secret", "radius")
try:
fdo = self._fdmap[fd]
self._ProcessInput(fdo)
- except ServerPacketError as err:
+ except pyrad.server.ServerPacketError as err:
logger.info("pyrad server dropping packet: " + str(err))
except pyrad.packet.PacketError as err:
logger.info("pyrad server received invalid packet: " + str(err))
try:
params = hostapd.wpa2_eap_params(ssid="radius-test")
params['auth_server_port'] = "18138"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
connect(dev[0], "radius-test", wait_connect=False)
ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=15)
if ev is None:
try:
fdo = self._fdmap[fd]
self._ProcessInput(fdo)
- except ServerPacketError as err:
+ except pyrad.server.ServerPacketError as err:
logger.info("pyrad server dropping packet: " + str(err))
except pyrad.packet.PacketError as err:
logger.info("pyrad server received invalid packet: " + str(err))
params['macaddr_acl'] = '2'
params['wpa_psk_radius'] = '2'
params['auth_server_port'] = "18138"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk="12345678", scan_freq="2412")
t_events['long'].set()
dev[1].connect(ssid, psk="0123456789abcdef", scan_freq="2412")
t_events['stop'].set()
t.join()
+def test_radius_psk_invalid(dev, apdev):
+ """WPA2 with invalid PSK from RADIUS"""
+ try:
+ import pyrad.server
+ import pyrad.packet
+ import pyrad.dictionary
+ except ImportError:
+ raise HwsimSkip("No pyrad modules available")
+
+ class TestServer(pyrad.server.Server):
+ def _HandleAuthPacket(self, pkt):
+ pyrad.server.Server._HandleAuthPacket(self, pkt)
+ logger.info("Received authentication request")
+ reply = self.CreateReplyPacket(pkt)
+ reply.code = pyrad.packet.AccessAccept
+ a = "\xab\xcd"
+ secret = reply.secret
+ p = b'\x07' + "1234567" + 8 * b'\x00'
+ b = hashlib.md5(secret + pkt.authenticator + a).digest()
+ pp = bytearray(p)
+ bb = bytearray(b)
+ cc = bytearray(pp[i] ^ bb[i] for i in range(len(bb)))
+ data = '\x00' + a + bytes(cc)
+ reply.AddAttribute("Tunnel-Password", data)
+ self.SendReplyPacket(pkt.fd, reply)
+
+ def RunWithStop(self, t_events):
+ self._poll = select.poll()
+ self._fdmap = {}
+ self._PrepareSockets()
+ self.t_events = t_events
+
+ while not t_events['stop'].is_set():
+ for (fd, event) in self._poll.poll(1000):
+ if event == select.POLLIN:
+ try:
+ fdo = self._fdmap[fd]
+ self._ProcessInput(fdo)
+ except pyrad.server.ServerPacketError as err:
+ logger.info("pyrad server dropping packet: " + str(err))
+ except pyrad.packet.PacketError as err:
+ logger.info("pyrad server received invalid packet: " + str(err))
+ else:
+ logger.error("Unexpected event in pyrad server main loop")
+
+ srv = TestServer(dict=pyrad.dictionary.Dictionary("dictionary.radius"),
+ authport=18138, acctport=18139)
+ srv.hosts["127.0.0.1"] = pyrad.server.RemoteHost("127.0.0.1",
+ "radius",
+ "localhost")
+ srv.BindToAddress("")
+ t_events = {}
+ t_events['stop'] = threading.Event()
+ t = threading.Thread(target=run_pyrad_server, args=(srv, t_events))
+ t.start()
+
+ try:
+ ssid = "test-wpa2-psk"
+ params = hostapd.radius_params()
+ params['ssid'] = ssid
+ params["wpa"] = "2"
+ params["wpa_key_mgmt"] = "WPA-PSK"
+ params["rsn_pairwise"] = "CCMP"
+ params['macaddr_acl'] = '2'
+ params['wpa_psk_radius'] = '2'
+ params['auth_server_port'] = "18138"
+ hapd = hostapd.add_ap(apdev[0], params)
+ dev[0].connect(ssid, psk="12345678", scan_freq="2412",
+ wait_connect=False)
+ time.sleep(1)
+ finally:
+ t_events['stop'].set()
+ t.join()
+
def test_radius_auth_force_client_addr(dev, apdev):
"""RADIUS client address specified"""
params = hostapd.wpa2_eap_params(ssid="radius-auth")
params['radius_client_addr'] = "127.0.0.1"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
connect(dev[0], "radius-auth")
+@remote_compatible
def test_radius_auth_force_invalid_client_addr(dev, apdev):
"""RADIUS client address specified and invalid address"""
params = hostapd.wpa2_eap_params(ssid="radius-auth")
#params['radius_client_addr'] = "10.11.12.14"
params['radius_client_addr'] = "1::2"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
connect(dev[0], "radius-auth", wait_connect=False)
ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"])
if ev is None:
try:
fdo = self._fdmap[fd]
self._ProcessInput(fdo)
- except ServerPacketError as err:
+ except pyrad.server.ServerPacketError as err:
logger.info("pyrad server dropping packet: " + str(err))
except pyrad.packet.PacketError as err:
logger.info("pyrad server received invalid packet: " + str(err))
params['dynamic_vlan'] = "2"
params['wpa_passphrase'] = '0123456789abcdefghi'
params['auth_server_port'] = "18138"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
logger.info("connecting without VLAN")
dev[0].connect(ssid, psk="0123456789abcdefghi", scan_freq="2412",
finally:
t_events['stop'].set()
t.join()
+
+def test_radius_mppe_failure(dev, apdev):
+ """RADIUS failure when adding MPPE keys"""
+ params = { "ssid": "as", "beacon_int": "2000",
+ "radius_server_clients": "auth_serv/radius_clients.conf",
+ "radius_server_auth_port": '18127',
+ "eap_server": "1",
+ "eap_user_file": "auth_serv/eap_user.conf",
+ "ca_cert": "auth_serv/ca.pem",
+ "server_cert": "auth_serv/server.pem",
+ "private_key": "auth_serv/server.key" }
+ authsrv = hostapd.add_ap(apdev[1], params)
+
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
+ params['auth_server_port'] = "18127"
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ with fail_test(authsrv, 1, "os_get_random;radius_msg_add_mppe_keys"):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
+ identity="user", anonymous_identity="ttls",
+ password="password",
+ ca_cert="auth_serv/ca.pem", phase2="autheap=GTC",
+ wait_connect=False, scan_freq="2412")
+ dev[0].wait_disconnected()
+ dev[0].request("REMOVE_NETWORK all")
from wpasupplicant import WpaSupplicant
from rfkill import RFKill
from utils import HwsimSkip
+from hwsim import HWSimRadio
def get_rfkill(dev):
phy = dev.get_driver_status_field("phyname")
"""rfkill block/unblock during open mode connection"""
rfk = get_rfkill(dev[0])
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
try:
logger.info("rfkill block")
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, scan_freq="2412")
try:
logger.info("rfkill block")
rfk0.unblock()
rfk1.unblock()
+def _test_rfkill_p2p_discovery(dev0, dev1):
+ """rfkill block/unblock P2P Discovery"""
+ rfk0 = get_rfkill(dev0)
+ rfk1 = get_rfkill(dev1)
+
+ try:
+ addr0 = dev0.p2p_dev_addr()
+
+ logger.info("rfkill block 0")
+ rfk0.block()
+ logger.info("rfkill block 1")
+ rfk1.block()
+
+ for i in range(10):
+ time.sleep(0.1)
+ if dev0.get_status_field("wpa_state") == "INTERFACE_DISABLED" and dev1.get_status_field("wpa_state") == "INTERFACE_DISABLED":
+ break
+
+ if "OK" in dev0.p2p_listen():
+ raise Exception("P2P Listen success although in rfkill")
+
+ if "OK" in dev1.p2p_find():
+ raise Exception("P2P Find success although in rfkill")
+
+ dev0.dump_monitor()
+ dev1.dump_monitor()
+
+ logger.info("rfkill unblock 0")
+ rfk0.unblock()
+ logger.info("rfkill unblock 1")
+ rfk1.unblock()
+
+ for i in range(10):
+ time.sleep(0.1)
+ if dev0.get_status_field("wpa_state") != "INTERFACE_DISABLED" and dev1.get_status_field("wpa_state") != "INTERFACE_DISABLED":
+ break
+
+ if not "OK" in dev0.p2p_listen():
+ raise Exception("P2P Listen failed after unblocking rfkill")
+
+ if not dev1.discover_peer(addr0, social=True):
+ raise Exception("Failed to discover peer after unblocking rfkill")
+
+ finally:
+ rfk0.unblock()
+ rfk1.unblock()
+ dev0.p2p_stop_find()
+ dev1.p2p_stop_find()
+ dev0.dump_monitor()
+ dev1.dump_monitor()
+
+def test_rfkill_p2p_discovery(dev, apdev):
+ """rfkill block/unblock P2P Discovery"""
+ _test_rfkill_p2p_discovery(dev[0], dev[1])
+
+def test_rfkill_p2p_discovery_p2p_dev(dev, apdev):
+ """rfkill block/unblock P2P Discovery with P2P Device"""
+ with HWSimRadio(use_p2p_device=True) as (radio, iface):
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add(iface)
+ _test_rfkill_p2p_discovery(dev[0], wpas)
+ _test_rfkill_p2p_discovery(wpas, dev[1])
+
def test_rfkill_hostapd(dev, apdev):
"""rfkill block/unblock during and prior to hostapd operations"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
rfk = get_rfkill(hapd)
dev[0].request("DISCONNECT")
hapd.disable()
- hglobal = HostapdGlobal()
+ hglobal = HostapdGlobal(apdev[0])
hglobal.flush()
hglobal.remove(apdev[0]['ifname'])
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open2" },
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open2" },
no_enable=True)
if "FAIL" not in hapd.request("ENABLE"):
raise Exception("ENABLE succeeded unexpectedly (rfkill)")
# Test cases for SAE
-# Copyright (c) 2013-2015, Jouni Malinen <j@w1.fi>
+# Copyright (c) 2013-2016, Jouni Malinen <j@w1.fi>
#
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import binascii
import os
import time
-import subprocess
import logging
logger = logging.getLogger()
import hwsim_utils
import hostapd
-from utils import HwsimSkip, alloc_fail, fail_test
+from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger
from test_ap_psk import find_wpas_process, read_process_memory, verify_not_present, get_key_locations
+@remote_compatible
def test_sae(dev, apdev):
"""SAE with default group"""
if "SAE" not in dev[0].get_capability("auth_alg"):
params = hostapd.wpa2_params(ssid="test-sae",
passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
key_mgmt = hapd.get_config()['key_mgmt']
if key_mgmt.split(' ')[0] != "SAE":
raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
if "[WPA2-SAE-CCMP]" not in bss['flags']:
raise Exception("Unexpected BSS flags: " + bss['flags'])
+@remote_compatible
def test_sae_password_ecc(dev, apdev):
"""SAE with number of different passwords (ECC)"""
if "SAE" not in dev[0].get_capability("auth_alg"):
params = hostapd.wpa2_params(ssid="test-sae",
passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].request("SET sae_groups 19")
dev[0].request("REMOVE_NETWORK all")
dev[0].wait_disconnected()
+@remote_compatible
def test_sae_password_ffc(dev, apdev):
"""SAE with number of different passwords (FFC)"""
if "SAE" not in dev[0].get_capability("auth_alg"):
passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE'
params['sae_groups'] = '22'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].request("SET sae_groups 22")
dev[0].request("REMOVE_NETWORK all")
dev[0].wait_disconnected()
+@remote_compatible
def test_sae_pmksa_caching(dev, apdev):
"""SAE and PMKSA caching"""
if "SAE" not in dev[0].get_capability("auth_alg"):
params = hostapd.wpa2_params(ssid="test-sae",
passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].request("SET sae_groups ")
dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
if dev[0].get_status_field('sae_group') is not None:
raise Exception("SAE group claimed to have been used")
+@remote_compatible
def test_sae_pmksa_caching_disabled(dev, apdev):
"""SAE and PMKSA caching disabled"""
if "SAE" not in dev[0].get_capability("auth_alg"):
passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE'
params['disable_pmksa_caching'] = '1'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].request("SET sae_groups ")
dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE'
params['sae_groups'] = ' '.join(groups)
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
for g in groups:
logger.info("Testing SAE group " + g)
dev[0].wait_disconnected()
dev[0].dump_monitor()
+@remote_compatible
def test_sae_group_nego(dev, apdev):
"""SAE group negotiation"""
if "SAE" not in dev[0].get_capability("auth_alg"):
passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE'
params['sae_groups'] = '19'
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].request("SET sae_groups 25 26 20 19")
dev[0].connect("test-sae-group-nego", psk="12345678", key_mgmt="SAE",
if dev[0].get_status_field('sae_group') != '19':
raise Exception("Expected SAE group not used")
+@remote_compatible
def test_sae_anti_clogging(dev, apdev):
"""SAE anti clogging"""
if "SAE" not in dev[0].get_capability("auth_alg"):
params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE'
params['sae_anti_clogging_threshold'] = '1'
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].request("SET sae_groups ")
dev[1].request("SET sae_groups ")
params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE WPA-PSK'
params['sae_anti_clogging_threshold'] = '0'
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[2].connect("test-sae", psk="12345678", scan_freq="2412")
for i in range(0, 2):
dev[i].request("SET sae_groups ")
params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE WPA-PSK'
params['sae_anti_clogging_threshold'] = '0'
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[2].connect("test-sae", psk="12345678", scan_freq="2412")
for i in range(0, 2):
dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE",
scan_freq="2412")
+@remote_compatible
def test_sae_missing_password(dev, apdev):
"""SAE and missing password"""
if "SAE" not in dev[0].get_capability("auth_alg"):
params = hostapd.wpa2_params(ssid="test-sae",
passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].request("SET sae_groups ")
id = dev[0].connect("test-sae",
password = "5ad144a7c1f5a5503baa6fa01dabc15b1843e8c01662d78d16b70b5cd23cf8b"
p = hostapd.wpa2_params(ssid="test-sae", passphrase=password)
p['wpa_key_mgmt'] = 'SAE'
- hapd = hostapd.add_ap(apdev[0]['ifname'], p)
+ hapd = hostapd.add_ap(apdev[0], p)
pid = find_wpas_process(dev[0])
id = dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
scan_freq="2412")
+ # The decrypted copy of GTK is freed only after the CTRL-EVENT-CONNECTED
+ # event has been delivered, so verify that wpa_supplicant has returned to
+ # eloop before reading process memory.
time.sleep(1)
+ dev[0].ping()
buf = read_process_memory(pid, password)
dev[0].request("DISCONNECT")
if tk in buf:
raise Exception("TK found from memory")
if gtk in buf:
+ get_key_locations(buf, gtk, "GTK")
raise Exception("GTK found from memory")
verify_not_present(buf, sae_k, fname, "SAE(k)")
verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
verify_not_present(buf, sae_kck, fname, "SAE(KCK)")
+@remote_compatible
def test_sae_oom_wpas(dev, apdev):
"""SAE and OOM in wpa_supplicant"""
if "SAE" not in dev[0].get_capability("auth_alg"):
params = hostapd.wpa2_params(ssid="test-sae",
passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].request("SET sae_groups 25")
tls = dev[0].request("GET tls_library")
scan_freq="2412")
dev[0].request("REMOVE_NETWORK all")
+ with alloc_fail(dev[0], 1, "wpabuf_alloc;sme_auth_build_sae_commit"):
+ dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
+ scan_freq="2412")
+ dev[0].request("REMOVE_NETWORK all")
+
+ with alloc_fail(dev[0], 1, "wpabuf_alloc;sme_auth_build_sae_confirm"):
+ dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
+ scan_freq="2412", wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+
+ with alloc_fail(dev[0], 1, "=sme_authenticate"):
+ dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
+ scan_freq="2412", wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+
+ with alloc_fail(dev[0], 1, "radio_add_work;sme_authenticate"):
+ dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
+ scan_freq="2412", wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+
+@remote_compatible
def test_sae_proto_ecc(dev, apdev):
"""SAE protocol testing (ECC)"""
if "SAE" not in dev[0].get_capability("auth_alg"):
params = hostapd.wpa2_params(ssid="test-sae",
passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
dev[0].request("SET sae_groups 19")
hapd.set("ext_mgmt_frame_handling", "0")
hapd.dump_monitor()
+@remote_compatible
def test_sae_proto_ffc(dev, apdev):
"""SAE protocol testing (FFC)"""
if "SAE" not in dev[0].get_capability("auth_alg"):
params = hostapd.wpa2_params(ssid="test-sae",
passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
dev[0].request("SET sae_groups 2")
hapd.set("ext_mgmt_frame_handling", "0")
hapd.dump_monitor()
+@remote_compatible
def test_sae_no_ffc_by_default(dev, apdev):
"""SAE and default groups rejecting FFC"""
if "SAE" not in dev[0].get_capability("auth_alg"):
raise HwsimSkip("SAE not supported")
params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].request("SET sae_groups 5")
dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412",
params = hostapd.wpa2_params(ssid="test-sae",
passphrase="no-knowledge-of-passphrase")
params['wpa_key_mgmt'] = 'SAE'
- hapd = hostapd.add_ap(apdev['ifname'], params)
+ hapd = hostapd.add_ap(apdev, params)
bssid = apdev['bssid']
dev.scan_for_bss(bssid, freq=2412)
if req['subtype'] == 11:
raise Exception("Unexpected Authentication frame seen")
+@remote_compatible
def test_sae_reflection_attack_ecc(dev, apdev):
"""SAE reflection attack (ECC)"""
sae_reflection_attack(apdev[0], dev[0], 19)
+@remote_compatible
def test_sae_reflection_attack_ffc(dev, apdev):
"""SAE reflection attack (FFC)"""
sae_reflection_attack(apdev[0], dev[0], 5)
+@remote_compatible
def test_sae_anti_clogging_proto(dev, apdev):
"""SAE anti clogging protocol testing"""
if "SAE" not in dev[0].get_capability("auth_alg"):
params = hostapd.wpa2_params(ssid="test-sae",
passphrase="no-knowledge-of-passphrase")
params['wpa_key_mgmt'] = 'SAE'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
dev[0].scan_for_bss(bssid, freq=2412)
if req['subtype'] == 11:
raise Exception("Unexpected Authentication frame seen")
+@remote_compatible
def test_sae_no_random(dev, apdev):
"""SAE and no random numbers available"""
if "SAE" not in dev[0].get_capability("auth_alg"):
raise HwsimSkip("SAE not supported")
params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
params['wpa_key_mgmt'] = 'SAE'
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].request("SET sae_groups ")
tests = [ (1, "os_get_random;sae_get_rand"),
scan_freq="2412")
dev[0].request("REMOVE_NETWORK all")
dev[0].wait_disconnected()
+
+@remote_compatible
+def test_sae_pwe_failure(dev, apdev):
+ """SAE and pwe failure"""
+ if "SAE" not in dev[0].get_capability("auth_alg"):
+ raise HwsimSkip("SAE not supported")
+ params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
+ params['wpa_key_mgmt'] = 'SAE'
+ params['sae_groups'] = '19 5'
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].request("SET sae_groups 19")
+ with fail_test(dev[0], 1, "hmac_sha256_vector;sae_derive_pwe_ecc"):
+ dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
+ scan_freq="2412")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ with fail_test(dev[0], 1, "sae_test_pwd_seed_ecc"):
+ dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
+ scan_freq="2412")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ dev[0].request("SET sae_groups 5")
+ with fail_test(dev[0], 1, "hmac_sha256_vector;sae_derive_pwe_ffc"):
+ dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
+ scan_freq="2412")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ dev[0].request("SET sae_groups 5")
+ with fail_test(dev[0], 1, "sae_test_pwd_seed_ffc"):
+ dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
+ scan_freq="2412")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ with fail_test(dev[0], 2, "sae_test_pwd_seed_ffc"):
+ dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
+ scan_freq="2412")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+@remote_compatible
+def test_sae_bignum_failure(dev, apdev):
+ """SAE and bignum failure"""
+ if "SAE" not in dev[0].get_capability("auth_alg"):
+ raise HwsimSkip("SAE not supported")
+ params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
+ params['wpa_key_mgmt'] = 'SAE'
+ params['sae_groups'] = '19 5 22'
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].request("SET sae_groups 19")
+ tests = [ (1, "crypto_bignum_init_set;get_rand_1_to_p_1"),
+ (1, "crypto_bignum_init;is_quadratic_residue_blind"),
+ (1, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
+ (2, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
+ (3, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
+ (1, "crypto_bignum_legendre;is_quadratic_residue_blind"),
+ (1, "crypto_bignum_init_set;sae_test_pwd_seed_ecc"),
+ (1, "crypto_ec_point_compute_y_sqr;sae_test_pwd_seed_ecc"),
+ (1, "crypto_bignum_init_set;get_random_qr_qnr"),
+ (1, "crypto_bignum_to_bin;sae_derive_pwe_ecc"),
+ (1, "crypto_ec_point_init;sae_derive_pwe_ecc"),
+ (1, "crypto_ec_point_solve_y_coord;sae_derive_pwe_ecc"),
+ (1, "crypto_ec_point_init;sae_derive_commit_element_ecc"),
+ (1, "crypto_ec_point_mul;sae_derive_commit_element_ecc"),
+ (1, "crypto_ec_point_invert;sae_derive_commit_element_ecc"),
+ (1, "crypto_bignum_init;=sae_derive_commit"),
+ (1, "crypto_ec_point_init;sae_derive_k_ecc"),
+ (1, "crypto_ec_point_mul;sae_derive_k_ecc"),
+ (1, "crypto_ec_point_add;sae_derive_k_ecc"),
+ (2, "crypto_ec_point_mul;sae_derive_k_ecc"),
+ (1, "crypto_ec_point_to_bin;sae_derive_k_ecc"),
+ (1, "crypto_bignum_legendre;get_random_qr_qnr"),
+ (1, "sha256_prf;sae_derive_keys"),
+ (1, "crypto_bignum_init;sae_derive_keys"),
+ (1, "crypto_bignum_init_set;sae_parse_commit_scalar"),
+ (1, "crypto_bignum_to_bin;sae_parse_commit_element_ecc"),
+ (1, "crypto_ec_point_from_bin;sae_parse_commit_element_ecc") ]
+ for count, func in tests:
+ with fail_test(dev[0], count, func):
+ dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
+ scan_freq="2412", wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+
+ dev[0].request("SET sae_groups 5")
+ tests = [ (1, "crypto_bignum_init_set;sae_set_group"),
+ (2, "crypto_bignum_init_set;sae_set_group"),
+ (1, "crypto_bignum_init_set;sae_get_rand"),
+ (1, "crypto_bignum_init_set;sae_test_pwd_seed_ffc"),
+ (1, "crypto_bignum_exptmod;sae_test_pwd_seed_ffc"),
+ (1, "crypto_bignum_init;sae_derive_pwe_ffc"),
+ (1, "crypto_bignum_init;sae_derive_commit_element_ffc"),
+ (1, "crypto_bignum_exptmod;sae_derive_commit_element_ffc"),
+ (1, "crypto_bignum_inverse;sae_derive_commit_element_ffc"),
+ (1, "crypto_bignum_init;sae_derive_k_ffc"),
+ (1, "crypto_bignum_exptmod;sae_derive_k_ffc"),
+ (1, "crypto_bignum_mulmod;sae_derive_k_ffc"),
+ (2, "crypto_bignum_exptmod;sae_derive_k_ffc"),
+ (1, "crypto_bignum_to_bin;sae_derive_k_ffc"),
+ (1, "crypto_bignum_init_set;sae_parse_commit_element_ffc"),
+ (1, "crypto_bignum_init;sae_parse_commit_element_ffc"),
+ (2, "crypto_bignum_init_set;sae_parse_commit_element_ffc"),
+ (1, "crypto_bignum_exptmod;sae_parse_commit_element_ffc") ]
+ for count, func in tests:
+ with fail_test(dev[0], count, func):
+ dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
+ scan_freq="2412", wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+
+ dev[0].request("SET sae_groups 22")
+ tests = [ (1, "crypto_bignum_init_set;sae_test_pwd_seed_ffc"),
+ (1, "crypto_bignum_sub;sae_test_pwd_seed_ffc"),
+ (1, "crypto_bignum_div;sae_test_pwd_seed_ffc") ]
+ for count, func in tests:
+ with fail_test(dev[0], count, func):
+ dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
+ scan_freq="2412", wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+
+def test_sae_invalid_anti_clogging_token_req(dev, apdev):
+ """SAE and invalid anti-clogging token request"""
+ if "SAE" not in dev[0].get_capability("auth_alg"):
+ raise HwsimSkip("SAE not supported")
+ params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
+ params['wpa_key_mgmt'] = 'SAE'
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+
+ dev[0].request("SET sae_groups 19")
+ dev[0].scan_for_bss(bssid, freq=2412)
+ hapd.set("ext_mgmt_frame_handling", "1")
+ dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
+ scan_freq="2412", wait_connect=False)
+ ev = dev[0].wait_event(["SME: Trying to authenticate"])
+ if ev is None:
+ raise Exception("No authentication attempt seen")
+ dev[0].dump_monitor()
+
+ for i in range(0, 10):
+ req = hapd.mgmt_rx()
+ if req is None:
+ raise Exception("MGMT RX wait timed out (commit)")
+ if req['subtype'] == 11:
+ break
+ req = None
+ if not req:
+ raise Exception("Authentication frame (commit) not received")
+
+ hapd.dump_monitor()
+ resp = {}
+ resp['fc'] = req['fc']
+ resp['da'] = req['sa']
+ resp['sa'] = req['da']
+ resp['bssid'] = req['bssid']
+ resp['payload'] = binascii.unhexlify("030001004c0013")
+ hapd.mgmt_tx(resp)
+
+ ev = dev[0].wait_event(["SME: Trying to authenticate"])
+ if ev is None:
+ raise Exception("No authentication attempt seen")
+ dev[0].dump_monitor()
+
+ for i in range(0, 10):
+ req = hapd.mgmt_rx()
+ if req is None:
+ raise Exception("MGMT RX wait timed out (commit) (2)")
+ if req['subtype'] == 11:
+ break
+ req = None
+ if not req:
+ raise Exception("Authentication frame (commit) not received (2)")
+
+ hapd.dump_monitor()
+ resp = {}
+ resp['fc'] = req['fc']
+ resp['da'] = req['sa']
+ resp['sa'] = req['da']
+ resp['bssid'] = req['bssid']
+ resp['payload'] = binascii.unhexlify("030001000100")
+ hapd.mgmt_tx(resp)
+
+ ev = dev[0].wait_event(["SME: Trying to authenticate"])
+ if ev is None:
+ raise Exception("No authentication attempt seen")
+ dev[0].dump_monitor()
+
+ dev[0].request("DISCONNECT")
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import time
import logging
logger = logging.getLogger()
import hostapd
from wpasupplicant import WpaSupplicant
-from utils import HwsimSkip, fail_test
+from utils import HwsimSkip, fail_test, alloc_fail, wait_fail_trigger
from tshark import run_tshark
def check_scan(dev, params, other_started=False, test_busy=False):
return
raise Exception("Unexpectedly old BSS entry")
+@remote_compatible
def test_scan(dev, apdev):
"""Control interface behavior on scan parameters"""
- hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" })
+ hostapd.add_ap(apdev[0], { "ssid": "test-scan" })
bssid = apdev[0]['bssid']
logger.info("Full scan")
logger.info("Active single-channel scan on AP's operating channel")
check_scan_retry(dev[0], "freq=2412 passive=0 use_id=1", bssid)
+@remote_compatible
def test_scan_tsf(dev, apdev):
"""Scan and TSF updates from Beacon/Probe Response frames"""
- hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan",
- 'beacon_int': "100" })
+ hostapd.add_ap(apdev[0], { "ssid": "test-scan",
+ 'beacon_int': "100" })
bssid = apdev[0]['bssid']
tsf = []
if 0 in tsf:
raise Exception("0 TSF reported")
+@remote_compatible
def test_scan_only(dev, apdev):
"""Control interface behavior on scan parameters with type=only"""
- hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" })
+ hostapd.add_ap(apdev[0], { "ssid": "test-scan" })
bssid = apdev[0]['bssid']
logger.info("Full scan")
logger.info("Active single-channel scan on AP's operating channel")
check_scan_retry(dev[0], "type=only freq=2412 passive=0 use_id=1", bssid)
+@remote_compatible
def test_scan_external_trigger(dev, apdev):
"""Avoid operations during externally triggered scan"""
- hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" })
+ hostapd.add_ap(apdev[0], { "ssid": "test-scan" })
bssid = apdev[0]['bssid']
- subprocess.call(['iw', dev[0].ifname, 'scan', 'trigger'])
+ dev[0].cmd_execute(['iw', dev[0].ifname, 'scan', 'trigger'])
check_scan(dev[0], "use_id=1", other_started=True)
def test_scan_bss_expiration_count(dev, apdev):
raise Exception("Invalid BSS_EXPIRE_COUNT accepted")
if "OK" not in dev[0].request("BSS_EXPIRE_COUNT 2"):
raise Exception("BSS_EXPIRE_COUNT failed")
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-scan" })
bssid = apdev[0]['bssid']
dev[0].scan(freq="2412", only_new=True)
if bssid not in dev[0].request("SCAN_RESULTS"):
if bssid in dev[0].request("SCAN_RESULTS"):
raise Exception("BSS found after two scans without match")
+@remote_compatible
def test_scan_bss_expiration_age(dev, apdev):
"""BSS entry expiration based on age"""
try:
raise Exception("Invalid BSS_EXPIRE_AGE accepted")
if "OK" not in dev[0].request("BSS_EXPIRE_AGE 10"):
raise Exception("BSS_EXPIRE_AGE failed")
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-scan" })
bssid = apdev[0]['bssid']
- dev[0].scan(freq="2412")
+ # Allow couple more retries to avoid reporting errors during heavy load
+ for i in range(5):
+ dev[0].scan(freq="2412")
+ if bssid in dev[0].request("SCAN_RESULTS"):
+ break
if bssid not in dev[0].request("SCAN_RESULTS"):
raise Exception("BSS not found in initial scan")
hapd.request("DISABLE")
finally:
dev[0].request("BSS_EXPIRE_AGE 180")
+@remote_compatible
def test_scan_filter(dev, apdev):
"""Filter scan results based on SSID"""
try:
if "OK" not in dev[0].request("SET filter_ssids 1"):
raise Exception("SET failed")
id = dev[0].connect("test-scan", key_mgmt="NONE", only_add_network=True)
- hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" })
+ hostapd.add_ap(apdev[0], { "ssid": "test-scan" })
bssid = apdev[0]['bssid']
- hostapd.add_ap(apdev[1]['ifname'], { "ssid": "test-scan2" })
+ hostapd.add_ap(apdev[1], { "ssid": "test-scan2" })
bssid2 = apdev[1]['bssid']
dev[0].scan(freq="2412", only_new=True)
if bssid not in dev[0].request("SCAN_RESULTS"):
finally:
dev[0].request("SET filter_ssids 0")
+@remote_compatible
def test_scan_int(dev, apdev):
"""scan interval configuration"""
try:
def test_scan_bss_operations(dev, apdev):
"""Control interface behavior on BSS parameters"""
- hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" })
+ hostapd.add_ap(apdev[0], { "ssid": "test-scan" })
bssid = apdev[0]['bssid']
- hostapd.add_ap(apdev[1]['ifname'], { "ssid": "test2-scan" })
+ hostapd.add_ap(apdev[1], { "ssid": "test2-scan" })
bssid2 = apdev[1]['bssid']
dev[0].scan(freq="2412")
if len(res) != 0:
raise Exception("Unexpected result after BSS_FLUSH 0")
+@remote_compatible
def test_scan_and_interface_disabled(dev, apdev):
"""Scan operation when interface gets disabled"""
try:
finally:
dev[0].request("DRIVER_EVENT INTERFACE_ENABLED")
+@remote_compatible
def test_scan_for_auth(dev, apdev):
"""cfg80211 workaround with scan-for-auth"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
# Block sme-connect radio work with an external radio work item, so that
# SELECT_NETWORK can decide to use fast associate without a new scan while
wait_connect=False)
dev[0].dump_monitor()
# Clear cfg80211 BSS table.
- try:
- subprocess.check_call(['iw', dev[0].ifname, 'scan', 'trigger',
- 'freq', '2457', 'flush'])
- except subprocess.CalledProcessError, e:
+ res, data = dev[0].cmd_execute(['iw', dev[0].ifname, 'scan', 'trigger',
+ 'freq', '2457', 'flush'])
+ if res != 0:
raise HwsimSkip("iw scan trigger flush not supported")
ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5)
if ev is None:
dev[0].wait_connected(timeout=15)
+@remote_compatible
def test_scan_for_auth_fail(dev, apdev):
"""cfg80211 workaround with scan-for-auth failing"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
# Block sme-connect radio work with an external radio work item, so that
# SELECT_NETWORK can decide to use fast associate without a new scan while
dev[0].dump_monitor()
hapd.disable()
# Clear cfg80211 BSS table.
- try:
- subprocess.check_call(['iw', dev[0].ifname, 'scan', 'trigger',
- 'freq', '2457', 'flush'])
- except subprocess.CalledProcessError, e:
+ res, data = dev[0].cmd_execute(['iw', dev[0].ifname, 'scan', 'trigger',
+ 'freq', '2457', 'flush'])
+ if res != 0:
raise HwsimSkip("iw scan trigger flush not supported")
ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5)
if ev is None:
raise Exception("Unexpected connection")
dev[0].request("DISCONNECT")
+@remote_compatible
def test_scan_for_auth_wep(dev, apdev):
"""cfg80211 scan-for-auth workaround with WEP keys"""
dev[0].flush_scan_cache()
- hapd = hostapd.add_ap(apdev[0]['ifname'],
+ hapd = hostapd.add_ap(apdev[0],
{ "ssid": "wep", "wep_key0": '"abcde"',
"auth_algs": "2" })
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
auth_alg="SHARED", scan_freq="2412", wait_connect=False)
dev[0].dump_monitor()
# Clear cfg80211 BSS table.
- try:
- subprocess.check_call(['iw', dev[0].ifname, 'scan', 'trigger',
- 'freq', '2457', 'flush'])
- except subprocess.CalledProcessError, e:
+ res, data = dev[0].cmd_execute(['iw', dev[0].ifname, 'scan', 'trigger',
+ 'freq', '2457', 'flush'])
+ if res != 0:
raise HwsimSkip("iw scan trigger flush not supported")
ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5)
if ev is None:
dev[0].wait_connected(timeout=15)
+@remote_compatible
def test_scan_hidden(dev, apdev):
"""Control interface behavior on scan parameters"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan",
- "ignore_broadcast_ssid": "1" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-scan",
+ "ignore_broadcast_ssid": "1" })
bssid = apdev[0]['bssid']
check_scan(dev[0], "freq=2412 use_id=1")
if "FAIL" not in dev[0].request("SCAN scan_id=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17"):
raise Exception("Too many scan_id values accepted")
+ # Duplicate SSID removal
+ check_scan(dev[0], "scan_id=%d,%d,%d freq=2412 use_id=1" % (id1, id1, id2))
+
dev[0].request("REMOVE_NETWORK all")
hapd.disable()
dev[0].flush_scan_cache(freq=2432)
def test_scan_and_bss_entry_removed(dev, apdev):
"""Last scan result and connect work processing on BSS entry update"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open",
- "eap_server": "1",
- "wps_state": "2" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open",
+ "eap_server": "1",
+ "wps_state": "2" })
bssid = apdev[0]['bssid']
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
dev[0].flush_scan_cache()
wpas.flush_scan_cache()
+@remote_compatible
def test_scan_reqs_with_non_scan_radio_work(dev, apdev):
"""SCAN commands while non-scan radio_work is in progress"""
id = dev[0].request("RADIO_WORK add test-work-a")
"hw_mode": "a",
"channel": "36",
"country_code": "US" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
params = { "ssid": "test-setband",
"hw_mode": "g",
"channel": "1" }
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
bssid2 = apdev[1]['bssid']
if "FAIL" not in dev[0].request("SET setband FOO"):
if "OK" not in dev[2].request("SET setband 2G"):
raise Exception("Failed to set setband")
- for i in range(3):
- dev[i].request("SCAN only_new=1")
+ # Allow a retry to avoid reporting errors during heavy load
+ for j in range(5):
+ for i in range(3):
+ dev[i].request("SCAN only_new=1")
- for i in range(3):
- ev = dev[i].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 15)
- if ev is None:
- raise Exception("Scan timed out")
+ for i in range(3):
+ ev = dev[i].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 15)
+ if ev is None:
+ raise Exception("Scan timed out")
+
+ res0 = dev[0].request("SCAN_RESULTS")
+ res1 = dev[1].request("SCAN_RESULTS")
+ res2 = dev[2].request("SCAN_RESULTS")
+ if bssid in res0 and bssid2 in res0 and bssid in res1 and bssid2 in res2:
+ break
res = dev[0].request("SCAN_RESULTS")
if bssid not in res or bssid2 not in res:
dev[i].request("SET setband AUTO")
dev[i].flush_scan_cache()
+@remote_compatible
def test_scan_hidden_many(dev, apdev):
"""scan_ssid=1 with large number of profile with hidden SSID"""
try:
dev[0].request("SCAN_INTERVAL 5")
def _test_scan_hidden_many(dev, apdev):
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan-ssid",
- "ignore_broadcast_ssid": "1" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-scan-ssid",
+ "ignore_broadcast_ssid": "1" })
bssid = apdev[0]['bssid']
dev[0].request("SCAN_INTERVAL 1")
dev[0].request("MAC_RAND_SCAN all enable=0")
def _test_scan_random_mac(dev, apdev, params):
- hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" })
+ hostapd.add_ap(apdev[0], { "ssid": "test-scan" })
bssid = apdev[0]['bssid']
tests = [ "",
if not found:
raise Exception("Fixed OUI random address not seen")
+@remote_compatible
def test_scan_trigger_failure(dev, apdev):
"""Scan trigger to the driver failing"""
- hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" })
+ hostapd.add_ap(apdev[0], { "ssid": "test-scan" })
bssid = apdev[0]['bssid']
if "OK" not in dev[0].request("SET test_failure 1"):
raise Exception("wpa_state COMPLETED not restored")
dev[0].request("SET test_failure 0")
+@remote_compatible
def test_scan_specify_ssid(dev, apdev):
"""Control interface behavior on scan SSID parameter"""
dev[0].flush_scan_cache()
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-hidden",
- "ignore_broadcast_ssid": "1" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-hidden",
+ "ignore_broadcast_ssid": "1" })
bssid = apdev[0]['bssid']
check_scan(dev[0], "freq=2412 use_id=1 ssid 414243")
bss = dev[0].get_bss(bssid)
if bss is not None and bss['ssid'] == 'test-hidden':
raise Exception("BSS entry for hidden AP present unexpectedly")
- check_scan(dev[0], "freq=2412 ssid 414243 ssid 746573742d68696464656e ssid 616263313233 use_id=1")
- bss = dev[0].get_bss(bssid)
+ # Allow couple more retries to avoid reporting errors during heavy load
+ for i in range(5):
+ check_scan(dev[0], "freq=2412 ssid 414243 ssid 746573742d68696464656e ssid 616263313233 use_id=1")
+ bss = dev[0].get_bss(bssid)
+ if bss and 'test-hidden' in dev[0].request("SCAN_RESULTS"):
+ break
if bss is None:
raise Exception("BSS entry for hidden AP not found")
if 'test-hidden' not in dev[0].request("SCAN_RESULTS"):
- raise Exception("Expected SSID not included in the scan results");
+ raise Exception("Expected SSID not included in the scan results")
hapd.disable()
dev[0].flush_scan_cache(freq=2432)
if "FAIL" not in dev[0].request("SCAN ssid foo"):
raise Exception("Invalid SCAN command accepted")
+@remote_compatible
def test_scan_ap_scan_2_ap_mode(dev, apdev):
"""AP_SCAN 2 AP mode and scan()"""
try:
def test_scan_bss_expiration_on_ssid_change(dev, apdev):
"""BSS entry expiration when AP changes SSID"""
dev[0].flush_scan_cache()
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-scan" })
bssid = apdev[0]['bssid']
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
hapd.request("DISABLE")
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
if "OK" not in dev[0].request("BSS_EXPIRE_COUNT 3"):
raise Exception("BSS_EXPIRE_COUNT failed")
dev[0].scan(freq="2412")
raise Exception("The BSS entry with the old SSID was not removed")
dev[0].request("DISCONNECT")
dev[0].wait_disconnected()
+
+def test_scan_dfs(dev, apdev, params):
+ """Scan on DFS channels"""
+ try:
+ _test_scan_dfs(dev, apdev, params)
+ finally:
+ subprocess.call(['iw', 'reg', 'set', '00'])
+
+def _test_scan_dfs(dev, apdev, params):
+ subprocess.call(['iw', 'reg', 'set', 'US'])
+ for i in range(2):
+ for j in range(5):
+ ev = dev[i].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=5)
+ if ev is None:
+ raise Exception("No regdom change event")
+ if "alpha2=US" in ev:
+ break
+ dev[i].dump_monitor()
+
+ if "OK" not in dev[0].request("SCAN"):
+ raise Exception("SCAN command failed")
+ ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
+ if ev is None:
+ raise Exception("Scan did not complete")
+
+ if "OK" not in dev[0].request("SCAN freq=2412,5180,5260,5500,5600,5745"):
+ raise Exception("SCAN command failed")
+ ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
+ if ev is None:
+ raise Exception("Scan did not complete")
+
+ out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"),
+ "wlan.fc.type_subtype == 4", [ "radiotap.channel.freq" ])
+ if out is not None:
+ freq = out.splitlines()
+ freq = [int(f) for f in freq]
+ freq = list(set(freq))
+ freq.sort()
+ logger.info("Active scan seen on channels: " + str(freq))
+ for f in freq:
+ if (f >= 5260 and f <= 5320) or (f >= 5500 and f <= 5700):
+ raise Exception("Active scan on DFS channel: %d" % f)
+ if f in [ 2467, 2472 ]:
+ raise Exception("Active scan on US-disallowed channel: %d" % f)
+
+@remote_compatible
+def test_scan_abort(dev, apdev):
+ """Aborting a full scan"""
+ dev[0].request("SCAN")
+ ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"])
+ if ev is None:
+ raise Exception("Scan did not start")
+ if "OK" not in dev[0].request("ABORT_SCAN"):
+ raise Exception("ABORT_SCAN command failed")
+ ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=2)
+ if ev is None:
+ raise Exception("Scan did not terminate")
+
+@remote_compatible
+def test_scan_abort_on_connect(dev, apdev):
+ """Aborting a full scan on connection request"""
+ hostapd.add_ap(apdev[0], { "ssid": "test-scan" })
+ bssid = apdev[0]['bssid']
+
+ dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
+ dev[0].dump_monitor()
+ dev[0].request("SCAN")
+ ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"])
+ if ev is None:
+ raise Exception("Scan did not start")
+ dev[0].connect("test-scan", key_mgmt="NONE")
+
+@remote_compatible
+def test_scan_ext(dev, apdev):
+ """Custom IE in Probe Request frame"""
+ hostapd.add_ap(apdev[0], { "ssid": "test-scan" })
+ bssid = apdev[0]['bssid']
+
+ try:
+ if "OK" not in dev[0].request("VENDOR_ELEM_ADD 14 dd050011223300"):
+ raise Exception("VENDOR_ELEM_ADD failed")
+ check_scan(dev[0], "freq=2412 use_id=1")
+ finally:
+ dev[0].request("VENDOR_ELEM_REMOVE 14 *")
+
+def test_scan_fail(dev, apdev):
+ """Scan failures"""
+ with fail_test(dev[0], 1, "wpa_driver_nl80211_scan"):
+ dev[0].request("DISCONNECT")
+ if "OK" not in dev[0].request("SCAN freq=2412"):
+ raise Exception("SCAN failed")
+ ev = dev[0].wait_event(["CTRL-EVENT-SCAN-FAILED"], timeout=5)
+ if ev is None:
+ raise Exception("Did not see scan failure event")
+ dev[0].dump_monitor()
+
+ for i in range(1, 5):
+ with alloc_fail(dev[0], i,
+ "wpa_scan_clone_params;wpa_supplicant_trigger_scan"):
+ if "OK" not in dev[0].request("SCAN ssid 112233 freq=2412"):
+ raise Exception("SCAN failed")
+ ev = dev[0].wait_event(["CTRL-EVENT-SCAN-FAILED"], timeout=5)
+ if ev is None:
+ raise Exception("Did not see scan failure event")
+ dev[0].dump_monitor()
+
+ with alloc_fail(dev[0], 1, "radio_add_work;wpa_supplicant_trigger_scan"):
+ if "OK" not in dev[0].request("SCAN freq=2412"):
+ raise Exception("SCAN failed")
+ ev = dev[0].wait_event(["CTRL-EVENT-SCAN-FAILED"], timeout=5)
+ if ev is None:
+ raise Exception("Did not see scan failure event")
+ dev[0].dump_monitor()
+
+ try:
+ if "OK" not in dev[0].request("SET filter_ssids 1"):
+ raise Exception("SET failed")
+ id = dev[0].connect("test-scan", key_mgmt="NONE", only_add_network=True)
+ with alloc_fail(dev[0], 1, "wpa_supplicant_build_filter_ssids"):
+ # While the filter list cannot be created due to memory allocation
+ # failure, this scan is expected to be completed without SSID
+ # filtering.
+ if "OK" not in dev[0].request("SCAN freq=2412"):
+ raise Exception("SCAN failed")
+ ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
+ if ev is None:
+ raise Exception("Scan did not complete")
+ dev[0].remove_network(id)
+ finally:
+ dev[0].request("SET filter_ssids 0")
+ dev[0].dump_monitor()
+
+ with alloc_fail(dev[0], 1, "nl80211_get_scan_results"):
+ if "OK" not in dev[0].request("SCAN freq=2412"):
+ raise Exception("SCAN failed")
+ ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=5)
+ if ev is None:
+ raise Exception("Did not see scan started event")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].dump_monitor()
+
+ try:
+ if "OK" not in dev[0].request("SET setband 2G"):
+ raise Exception("SET setband failed")
+ with alloc_fail(dev[0], 1, "=wpa_setband_scan_freqs_list"):
+ # While the frequency list cannot be created due to memory
+ # allocation failure, this scan is expected to be completed without
+ # frequency filtering.
+ if "OK" not in dev[0].request("SCAN"):
+ raise Exception("SCAN failed")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("ABORT_SCAN")
+ ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
+ if ev is None:
+ raise Exception("Scan did not complete")
+ finally:
+ dev[0].request("SET setband AUTO")
+ dev[0].dump_monitor()
+
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add("wlan5")
+ wpas.request("SET preassoc_mac_addr 1")
+ with fail_test(wpas, 1, "nl80211_set_mac_addr;wpas_trigger_scan_cb"):
+ if "OK" not in wpas.request("SCAN freq=2412"):
+ raise Exception("SCAN failed")
+ ev = wpas.wait_event(["CTRL-EVENT-SCAN-FAILED"], timeout=5)
+ if ev is None:
+ raise Exception("Did not see scan failure event")
+ wpas.request("SET preassoc_mac_addr 0")
+ wpas.dump_monitor()
+
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
+ with alloc_fail(dev[0], 1, "wpa_bss_add"):
+ dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
+
+@remote_compatible
+def test_scan_freq_list(dev, apdev):
+ """Scan with SET freq_list and scan_cur_freq"""
+ try:
+ if "OK" not in dev[0].request("SET freq_list 2412 2417"):
+ raise Exception("SET freq_list failed")
+ check_scan(dev[0], "use_id=1")
+ finally:
+ dev[0].request("SET freq_list ")
+
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-scan" })
+ dev[0].connect("test-scan", key_mgmt="NONE", scan_freq="2412")
+ try:
+ if "OK" not in dev[0].request("SET scan_cur_freq 1"):
+ raise Exception("SET scan_cur_freq failed")
+ check_scan(dev[0], "use_id=1")
+ finally:
+ dev[0].request("SET scan_cur_freq 0")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+def test_scan_bss_limit(dev, apdev):
+ """Scan and wpa_supplicant BSS entry limit"""
+ try:
+ _test_scan_bss_limit(dev, apdev)
+ finally:
+ dev[0].request("SET bss_max_count 200")
+ pass
+
+def _test_scan_bss_limit(dev, apdev):
+ # Trigger 'Increasing the MAX BSS count to 2 because all BSSes are in use.
+ # We should normally not get here!' message by limiting the maximum BSS
+ # count to one so that the second AP would not fit in the BSS list and the
+ # first AP cannot be removed from the list since it is still in use.
+ dev[0].request("SET bss_max_count 1")
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-scan" })
+ dev[0].connect("test-scan", key_mgmt="NONE", scan_freq="2412")
+ hapd2 = hostapd.add_ap(apdev[1], { "ssid": "test-scan-2",
+ "channel": "6" })
+ dev[0].scan_for_bss(apdev[1]['bssid'], freq=2437, force_scan=True)
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import logging
logger = logging.getLogger()
import hostapd
+@remote_compatible
def test_ssid_hex_encoded(dev, apdev):
"""SSID configuration using hex encoded version"""
- hostapd.add_ap(apdev[0]['ifname'], { "ssid2": '68656c6c6f' })
+ hostapd.add_ap(apdev[0], { "ssid2": '68656c6c6f' })
dev[0].connect("hello", key_mgmt="NONE", scan_freq="2412")
dev[1].connect(ssid2="68656c6c6f", key_mgmt="NONE", scan_freq="2412")
def test_ssid_printf_encoded(dev, apdev):
"""SSID configuration using printf encoded version"""
- hostapd.add_ap(apdev[0]['ifname'], { "ssid2": 'P"\\0hello\\nthere"' })
+ hostapd.add_ap(apdev[0], { "ssid2": 'P"\\0hello\\nthere"' })
dev[0].connect(ssid2="0068656c6c6f0a7468657265", key_mgmt="NONE",
scan_freq="2412")
dev[1].connect(ssid2='P"\\x00hello\\nthere"', key_mgmt="NONE",
raise Exception("Unexpected difference in SSID")
dev[2].connect(ssid2='P"' + ssid + '"', key_mgmt="NONE", scan_freq="2412")
+@remote_compatible
def test_ssid_1_octet(dev, apdev):
"""SSID with one octet"""
- hostapd.add_ap(apdev[0]['ifname'], { "ssid": '1' })
+ hostapd.add_ap(apdev[0], { "ssid": '1' })
dev[0].connect("1", key_mgmt="NONE", scan_freq="2412")
+@remote_compatible
def test_ssid_32_octets(dev, apdev):
"""SSID with 32 octets"""
- hostapd.add_ap(apdev[0]['ifname'],
+ hostapd.add_ap(apdev[0],
{ "ssid": '1234567890abcdef1234567890ABCDEF' })
dev[0].connect("1234567890abcdef1234567890ABCDEF", key_mgmt="NONE",
scan_freq="2412")
+@remote_compatible
def test_ssid_utf8(dev, apdev):
"""SSID with UTF8 encoding"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": 'testi-åäöÅÄÖ-testi',
- "utf8_ssid": "1" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": 'testi-åäöÅÄÖ-testi',
+ "utf8_ssid": "1" })
dev[0].connect("testi-åäöÅÄÖ-testi", key_mgmt="NONE", scan_freq="2412")
dev[1].connect(ssid2="74657374692dc3a5c3a4c3b6c385c384c3962d7465737469",
key_mgmt="NONE", scan_freq="2412")
if len(sta3) != 0:
raise Exception("Unexpected STA iteration result (did not stop)")
+def clear_scan_cache(hapd, dev):
+ # clear BSS table to avoid issues in following test cases
+ dev[0].request("REMOVE_NETWORK all")
+ dev[1].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ hapd.disable()
+ dev[0].flush_scan_cache()
+ dev[1].flush_scan_cache()
+
+@remote_compatible
def test_ssid_hidden(dev, apdev):
"""Hidden SSID"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": 'secret',
- "ignore_broadcast_ssid": "1" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": 'secret',
+ "ignore_broadcast_ssid": "1" })
dev[1].connect("secret", key_mgmt="NONE", scan_freq="2412",
wait_connect=False)
dev[0].connect("secret", key_mgmt="NONE", scan_freq="2412", scan_ssid="1")
ev = dev[1].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
if ev is not None:
raise Exception("Unexpected connection")
- dev[0].request("DISCONNECT")
- dev[1].request("DISCONNECT")
- # clear BSS table to avoid issues in following test cases
- hapd.disable()
- dev[0].request("BSS_FLUSH 0")
- dev[0].request("SCAN freq=2412 only_new=1")
- dev[1].request("BSS_FLUSH 0")
- dev[1].request("SCAN freq=2412 only_new=1")
+ clear_scan_cache(hapd, dev)
+@remote_compatible
def test_ssid_hidden2(dev, apdev):
"""Hidden SSID using zero octets as payload"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": 'secret2',
- "ignore_broadcast_ssid": "2" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": 'secret2',
+ "ignore_broadcast_ssid": "2" })
dev[1].connect("secret2", key_mgmt="NONE", scan_freq="2412",
wait_connect=False)
dev[0].connect("secret2", key_mgmt="NONE", scan_freq="2412", scan_ssid="1")
ev = dev[1].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
if ev is not None:
raise Exception("Unexpected connection")
- dev[0].request("DISCONNECT")
- dev[1].request("DISCONNECT")
- # clear BSS table to avoid issues in following test cases
- hapd.disable()
- dev[0].request("BSS_FLUSH 0")
- dev[0].request("SCAN freq=2412 only_new=1")
- dev[1].request("BSS_FLUSH 0")
- dev[1].request("SCAN freq=2412 only_new=1")
+ clear_scan_cache(hapd, dev)
+@remote_compatible
def test_ssid_hidden_wpa2(dev, apdev):
"""Hidden SSID with WPA2-PSK"""
params = hostapd.wpa2_params(ssid="secret", passphrase="12345678")
params["ignore_broadcast_ssid"] = "1"
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[1].connect("secret", psk="12345678", scan_freq="2412",
wait_connect=False)
dev[0].connect("secret", psk="12345678", scan_freq="2412", scan_ssid="1")
ev = dev[1].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
if ev is not None:
raise Exception("Unexpected connection")
- dev[0].request("DISCONNECT")
- dev[1].request("DISCONNECT")
- # clear BSS table to avoid issues in following test cases
- hapd.disable()
- dev[0].request("BSS_FLUSH 0")
- dev[0].request("SCAN freq=2412 only_new=1")
- dev[1].request("BSS_FLUSH 0")
- dev[1].request("SCAN freq=2412 only_new=1")
+ clear_scan_cache(hapd, dev)
def test_sta_dynamic(dev, apdev):
"""Dynamically added wpa_supplicant interface"""
params = hostapd.wpa2_params(ssid="sta-dynamic", passphrase="12345678")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
logger.info("Create a dynamic wpa_supplicant interface and connect")
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
def test_sta_ap_scan_0(dev, apdev):
"""Dynamically added wpa_supplicant interface with AP_SCAN 0 connection"""
- hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test" })
+ hostapd.add_ap(apdev[0], { "ssid": "test" })
bssid = apdev[0]['bssid']
logger.info("Create a dynamic wpa_supplicant interface and connect")
def test_sta_ap_scan_2(dev, apdev):
"""Dynamically added wpa_supplicant interface with AP_SCAN 2 connection"""
- hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test" })
+ hostapd.add_ap(apdev[0], { "ssid": "test" })
bssid = apdev[0]['bssid']
logger.info("Create a dynamic wpa_supplicant interface and connect")
def test_sta_ap_scan_2b(dev, apdev):
"""Dynamically added wpa_supplicant interface with AP_SCAN 2 operation"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test" })
bssid = apdev[0]['bssid']
logger.info("Create a dynamic wpa_supplicant interface and connect")
def test_sta_dynamic_down_up(dev, apdev):
"""Dynamically added wpa_supplicant interface down/up"""
params = hostapd.wpa2_params(ssid="sta-dynamic", passphrase="12345678")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
logger.info("Create a dynamic wpa_supplicant interface and connect")
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
def test_sta_dynamic_ext_mac_addr_change(dev, apdev):
"""Dynamically added wpa_supplicant interface with external MAC address change"""
params = hostapd.wpa2_params(ssid="sta-dynamic", passphrase="12345678")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
logger.info("Create a dynamic wpa_supplicant interface and connect")
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
def test_sta_dynamic_random_mac_addr(dev, apdev):
"""Dynamically added wpa_supplicant interface and random MAC address"""
params = hostapd.wpa2_params(ssid="sta-dynamic", passphrase="12345678")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5")
def test_sta_dynamic_random_mac_addr_keep_oui(dev, apdev):
"""Dynamically added wpa_supplicant interface and random MAC address (keep OUI)"""
params = hostapd.wpa2_params(ssid="sta-dynamic", passphrase="12345678")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5")
def test_sta_dynamic_random_mac_addr_scan(dev, apdev):
"""Dynamically added wpa_supplicant interface and random MAC address for scan"""
params = hostapd.wpa2_params(ssid="sta-dynamic", passphrase="12345678")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5")
def test_sta_dynamic_random_mac_addr_scan_keep_oui(dev, apdev):
"""Dynamically added wpa_supplicant interface and random MAC address for scan (keep OUI)"""
params = hostapd.wpa2_params(ssid="sta-dynamic", passphrase="12345678")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
wpas.interface_add("wlan5")
logger = logging.getLogger()
import hostapd
-from utils import HwsimSkip
+from utils import HwsimSkip, fail_test
def check_suite_b_capa(dev):
if "GCMP" not in dev[0].get_capability("pairwise"):
def check_suite_b_tls_lib(dev):
tls = dev[0].request("GET tls_library")
if not tls.startswith("OpenSSL"):
- raise HwsimSkip("TLS library not supported for Suite B: " + tls);
+ raise HwsimSkip("TLS library not supported for Suite B: " + tls)
supported = False
for ver in [ '1.0.2', '1.1.0' ]:
if "build=OpenSSL " + ver in tls and "run=OpenSSL " + ver in tls:
if not supported:
raise HwsimSkip("OpenSSL version not supported for Suite B: " + tls)
-def test_suite_b(dev, apdev):
- """WPA2/GCMP connection at Suite B 128-bit level"""
- check_suite_b_capa(dev)
- dev[0].flush_scan_cache()
+def suite_b_ap_params():
params = { "ssid": "test-suite-b",
"wpa": "2",
"wpa_key_mgmt": "WPA-EAP-SUITE-B",
"ca_cert": "auth_serv/ec-ca.pem",
"server_cert": "auth_serv/ec-server.pem",
"private_key": "auth_serv/ec-server.key" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ return params
+
+def test_suite_b(dev, apdev):
+ """WPA2/GCMP connection at Suite B 128-bit level"""
+ check_suite_b_capa(dev)
+ dev[0].flush_scan_cache()
+ params = suite_b_ap_params()
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("test-suite-b", key_mgmt="WPA-EAP-SUITE-B", ieee80211w="2",
openssl_ciphers="SUITEB128",
check_suite_b_capa(dev)
dev[0].flush_scan_cache()
params = suite_b_as_params()
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
params = { "ssid": "test-suite-b",
"wpa": "2",
'auth_server_port': "18129",
'auth_server_shared_secret': "radius",
'nas_identifier': "nas.w1.fi" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("test-suite-b", key_mgmt="WPA-EAP-SUITE-B", ieee80211w="2",
openssl_ciphers="SUITEB128",
raise HwsimSkip("WPA-EAP-SUITE-B-192 not supported")
check_suite_b_tls_lib(dev)
-def test_suite_b_192(dev, apdev):
- """WPA2/GCMP-256 connection at Suite B 192-bit level"""
- check_suite_b_192_capa(dev)
- dev[0].flush_scan_cache()
+def suite_b_192_ap_params():
params = { "ssid": "test-suite-b",
"wpa": "2",
"wpa_key_mgmt": "WPA-EAP-SUITE-B-192",
"ca_cert": "auth_serv/ec2-ca.pem",
"server_cert": "auth_serv/ec2-server.pem",
"private_key": "auth_serv/ec2-server.key" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ return params
+
+def test_suite_b_192(dev, apdev):
+ """WPA2/GCMP-256 connection at Suite B 192-bit level"""
+ check_suite_b_192_capa(dev)
+ dev[0].flush_scan_cache()
+ params = suite_b_192_ap_params()
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("test-suite-b", key_mgmt="WPA-EAP-SUITE-B-192",
ieee80211w="2",
params['server_cert'] = 'auth_serv/ec2-server.pem'
params['private_key'] = 'auth_serv/ec2-server.key'
params['openssl_ciphers'] = 'SUITEB192'
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
params = { "ssid": "test-suite-b",
"wpa": "2",
'auth_server_port': "18129",
'auth_server_shared_secret': "radius",
'nas_identifier': "nas.w1.fi" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("test-suite-b", key_mgmt="WPA-EAP-SUITE-B-192",
ieee80211w="2",
client_cert="auth_serv/ec2-user.pem",
private_key="auth_serv/ec2-user.key",
pairwise="GCMP-256", group="GCMP-256", scan_freq="2412")
+
+def test_suite_b_pmkid_failure(dev, apdev):
+ """WPA2/GCMP connection at Suite B 128-bit level and PMKID derivation failure"""
+ check_suite_b_capa(dev)
+ dev[0].flush_scan_cache()
+ params = suite_b_ap_params()
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ with fail_test(dev[0], 1, "rsn_pmkid_suite_b"):
+ dev[0].connect("test-suite-b", key_mgmt="WPA-EAP-SUITE-B",
+ ieee80211w="2",
+ openssl_ciphers="SUITEB128",
+ eap="TLS", identity="tls user",
+ ca_cert="auth_serv/ec-ca.pem",
+ client_cert="auth_serv/ec-user.pem",
+ private_key="auth_serv/ec-user.key",
+ pairwise="GCMP", group="GCMP", scan_freq="2412")
+
+def test_suite_b_192_pmkid_failure(dev, apdev):
+ """WPA2/GCMP-256 connection at Suite B 192-bit level and PMKID derivation failure"""
+ check_suite_b_192_capa(dev)
+ dev[0].flush_scan_cache()
+ params = suite_b_192_ap_params()
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ with fail_test(dev[0], 1, "rsn_pmkid_suite_b"):
+ dev[0].connect("test-suite-b", key_mgmt="WPA-EAP-SUITE-B-192",
+ ieee80211w="2",
+ openssl_ciphers="SUITEB192",
+ eap="TLS", identity="tls user",
+ ca_cert="auth_serv/ec2-ca.pem",
+ client_cert="auth_serv/ec2-user.pem",
+ private_key="auth_serv/ec2-user.key",
+ pairwise="GCMP-256", group="GCMP-256", scan_freq="2412")
+
+def test_suite_b_mic_failure(dev, apdev):
+ """WPA2/GCMP connection at Suite B 128-bit level and MIC derivation failure"""
+ check_suite_b_capa(dev)
+ dev[0].flush_scan_cache()
+ params = suite_b_ap_params()
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ with fail_test(dev[0], 1, "wpa_eapol_key_mic"):
+ dev[0].connect("test-suite-b", key_mgmt="WPA-EAP-SUITE-B",
+ ieee80211w="2",
+ openssl_ciphers="SUITEB128",
+ eap="TLS", identity="tls user",
+ ca_cert="auth_serv/ec-ca.pem",
+ client_cert="auth_serv/ec-user.pem",
+ private_key="auth_serv/ec-user.key",
+ pairwise="GCMP", group="GCMP", scan_freq="2412",
+ wait_connect=False)
+ dev[0].wait_disconnected()
+
+def test_suite_b_192_mic_failure(dev, apdev):
+ """WPA2/GCMP connection at Suite B 192-bit level and MIC derivation failure"""
+ check_suite_b_capa(dev)
+ dev[0].flush_scan_cache()
+ params = suite_b_192_ap_params()
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ with fail_test(dev[0], 1, "wpa_eapol_key_mic"):
+ dev[0].connect("test-suite-b", key_mgmt="WPA-EAP-SUITE-B-192",
+ ieee80211w="2",
+ openssl_ciphers="SUITEB192",
+ eap="TLS", identity="tls user",
+ ca_cert="auth_serv/ec2-ca.pem",
+ client_cert="auth_serv/ec2-user.pem",
+ private_key="auth_serv/ec2-user.key",
+ pairwise="GCMP-256", group="GCMP-256", scan_freq="2412",
+ wait_connect=False)
+ dev[0].wait_disconnected()
import os.path
import hostapd
-from utils import HwsimSkip
+from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger
from test_ap_eap import int_eap_server_params, check_eap_capa
def test_tnc_peap_soh(dev, apdev):
"""TNC PEAP-SoH"""
params = int_eap_server_params()
params["tnc"] = "1"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
eap="PEAP", identity="user", password="password",
ca_cert="auth_serv/ca.pem",
phase1="peapver=0 tnc=soh cryptobinding=0",
phase2="auth=MSCHAPV2",
- wait_connect=False)
+ scan_freq="2412", wait_connect=False)
dev[0].wait_connected(timeout=10)
dev[1].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
ca_cert="auth_serv/ca.pem",
phase1="peapver=0 tnc=soh1 cryptobinding=1",
phase2="auth=MSCHAPV2",
- wait_connect=False)
+ scan_freq="2412", wait_connect=False)
dev[1].wait_connected(timeout=10)
dev[2].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
ca_cert="auth_serv/ca.pem",
phase1="peapver=0 tnc=soh2 cryptobinding=2",
phase2="auth=MSCHAPV2",
- wait_connect=False)
+ scan_freq="2412", wait_connect=False)
dev[2].wait_connected(timeout=10)
+def test_tnc_peap_soh_errors(dev, apdev):
+ """TNC PEAP-SoH local error cases"""
+ params = int_eap_server_params()
+ params["tnc"] = "1"
+ hostapd.add_ap(apdev[0], params)
+
+ tests = [ (1, "tncc_build_soh"),
+ (1, "eap_msg_alloc;=eap_peap_phase2_request") ]
+ for count, func in tests:
+ with alloc_fail(dev[0], count, func):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
+ eap="PEAP", identity="user", password="password",
+ ca_cert="auth_serv/ca.pem",
+ phase1="peapver=0 tnc=soh cryptobinding=0",
+ phase2="auth=MSCHAPV2",
+ scan_freq="2412", wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
+ with fail_test(dev[0], 1, "os_get_random;tncc_build_soh"):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
+ eap="PEAP", identity="user", password="password",
+ ca_cert="auth_serv/ca.pem",
+ phase1="peapver=0 tnc=soh cryptobinding=0",
+ phase2="auth=MSCHAPV2",
+ scan_freq="2412", wait_connect=False)
+ wait_fail_trigger(dev[0], "GET_FAIL")
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+
def test_tnc_ttls(dev, apdev):
"""TNC TTLS"""
check_eap_capa(dev[0], "MSCHAPV2")
params = int_eap_server_params()
params["tnc"] = "1"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
if not os.path.exists("tnc/libhostap_imc.so"):
raise HwsimSkip("No IMC installed")
anonymous_identity="ttls", password="password",
phase2="auth=MSCHAPV2",
ca_cert="auth_serv/ca.pem",
- wait_connect=False)
+ scan_freq="2412", wait_connect=False)
dev[0].wait_connected(timeout=10)
def test_tnc_ttls_fragmentation(dev, apdev):
params = int_eap_server_params()
params["tnc"] = "1"
params["fragment_size"] = "150"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
if not os.path.exists("tnc/libhostap_imc.so"):
raise HwsimSkip("No IMC installed")
phase2="auth=MSCHAPV2",
ca_cert="auth_serv/ca.pem",
fragment_size="150",
- wait_connect=False)
+ scan_freq="2412", wait_connect=False)
dev[0].wait_connected(timeout=10)
+def test_tnc_ttls_errors(dev, apdev):
+ """TNC TTLS local error cases"""
+ if not os.path.exists("tnc/libhostap_imc.so"):
+ raise HwsimSkip("No IMC installed")
+ check_eap_capa(dev[0], "MSCHAPV2")
+
+ params = int_eap_server_params()
+ params["tnc"] = "1"
+ params["fragment_size"] = "150"
+ hostapd.add_ap(apdev[0], params)
+
+ tests = [ (1, "eap_ttls_process_phase2_eap;eap_ttls_process_tnc_start",
+ "DOMAIN\mschapv2 user", "auth=MSCHAPV2"),
+ (1, "eap_ttls_process_phase2_eap;eap_ttls_process_tnc_start",
+ "mschap user", "auth=MSCHAP"),
+ (1, "=eap_tnc_init", "chap user", "auth=CHAP"),
+ (1, "tncc_init;eap_tnc_init", "pap user", "auth=PAP"),
+ (1, "eap_msg_alloc;eap_tnc_build_frag_ack",
+ "pap user", "auth=PAP"),
+ (1, "eap_msg_alloc;eap_tnc_build_msg",
+ "pap user", "auth=PAP"),
+ (1, "wpabuf_alloc;=eap_tnc_process_fragment",
+ "pap user", "auth=PAP"),
+ (1, "eap_msg_alloc;=eap_tnc_process", "pap user", "auth=PAP"),
+ (1, "wpabuf_alloc;=eap_tnc_process", "pap user", "auth=PAP"),
+ (1, "dup_binstr;tncc_process_if_tnccs", "pap user", "auth=PAP"),
+ (1, "tncc_get_base64;tncc_process_if_tnccs",
+ "pap user", "auth=PAP"),
+ (1, "tncc_if_tnccs_start", "pap user", "auth=PAP"),
+ (1, "tncc_if_tnccs_end", "pap user", "auth=PAP"),
+ (1, "tncc_parse_imc", "pap user", "auth=PAP"),
+ (2, "tncc_parse_imc", "pap user", "auth=PAP"),
+ (3, "tncc_parse_imc", "pap user", "auth=PAP"),
+ (1, "os_readfile;tncc_read_config", "pap user", "auth=PAP"),
+ (1, "tncc_init", "pap user", "auth=PAP"),
+ (1, "TNC_TNCC_ReportMessageTypes", "pap user", "auth=PAP"),
+ (1, "base64_encode;TNC_TNCC_SendMessage", "pap user", "auth=PAP"),
+ (1, "=TNC_TNCC_SendMessage", "pap user", "auth=PAP"),
+ (1, "tncc_get_base64;tncc_process_if_tnccs",
+ "pap user", "auth=PAP") ]
+ for count, func, identity, phase2 in tests:
+ with alloc_fail(dev[0], count, func):
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP",
+ scan_freq="2412",
+ eap="TTLS", anonymous_identity="ttls",
+ identity=identity, password="password",
+ ca_cert="auth_serv/ca.pem", phase2=phase2,
+ fragment_size="150", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"],
+ timeout=15)
+ if ev is None:
+ raise Exception("Timeout on EAP start")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL",
+ note="Allocation failure not triggered for: %d:%s" % (count, func))
+ dev[0].request("REMOVE_NETWORK all")
+ dev[0].wait_disconnected()
+ dev[0].dump_monitor()
+
def test_tnc_fast(dev, apdev):
"""TNC FAST"""
check_eap_capa(dev[0], "FAST")
params["eap_fast_a_id"] = "101112131415161718191a1b1c1d1e00"
params["eap_fast_a_id_info"] = "test server2"
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
if not os.path.exists("tnc/libhostap_imc.so"):
raise HwsimSkip("No IMC installed")
phase1="fast_provisioning=2",
pac_file="blob://fast_pac_auth_tnc",
ca_cert="auth_serv/ca.pem",
- wait_connect=False)
+ scan_freq="2412", wait_connect=False)
dev[0].wait_connected(timeout=10)
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+import logging
+logger = logging.getLogger()
+import subprocess
+
+from remotehost import remote_compatible
import hostapd
import hwsim_utils
+@remote_compatible
def test_wep_open_auth(dev, apdev):
"""WEP Open System authentication"""
- hapd = hostapd.add_ap(apdev[0]['ifname'],
+ hapd = hostapd.add_ap(apdev[0],
{ "ssid": "wep-open",
"wep_key0": '"hello"' })
dev[0].flush_scan_cache()
if "[WEP]" not in bss['flags']:
raise Exception("Unexpected BSS flags: " + bss['flags'])
+@remote_compatible
def test_wep_shared_key_auth(dev, apdev):
"""WEP Shared Key authentication"""
- hapd = hostapd.add_ap(apdev[0]['ifname'],
+ hapd = hostapd.add_ap(apdev[0],
{ "ssid": "wep-shared-key",
"wep_key0": '"hello12345678"',
"auth_algs": "2" })
wep_key0='"hello12345678"',
scan_freq="2412")
+@remote_compatible
def test_wep_shared_key_auth_not_allowed(dev, apdev):
"""WEP Shared Key authentication not allowed"""
- hostapd.add_ap(apdev[0]['ifname'],
+ hostapd.add_ap(apdev[0],
{ "ssid": "wep-shared-key",
"wep_key0": '"hello12345678"',
"auth_algs": "1" })
def test_wep_shared_key_auth_multi_key(dev, apdev):
"""WEP Shared Key authentication with multiple keys"""
- hapd = hostapd.add_ap(apdev[0]['ifname'],
+ hapd = hostapd.add_ap(apdev[0],
{ "ssid": "wep-shared-key",
"wep_key0": '"hello12345678"',
"wep_key1": '"other12345678"',
dev[2].request("REASSOCIATE")
dev[2].wait_connected(timeout=10, error="Reassociation timed out")
hwsim_utils.test_connectivity(dev[2], hapd)
+
+def test_wep_ht_vht(dev, apdev):
+ """WEP and HT/VHT"""
+ dev[0].flush_scan_cache()
+ try:
+ hapd = None
+ params = { "ssid": "test-vht40-wep",
+ "country_code": "SE",
+ "hw_mode": "a",
+ "channel": "36",
+ "ieee80211n": "1",
+ "ieee80211ac": "1",
+ "ht_capab": "[HT40+]",
+ "vht_capab": "",
+ "vht_oper_chwidth": "0",
+ "vht_oper_centr_freq_seg0_idx": "0",
+ "wep_key0": '"hello"' }
+ hapd = hostapd.add_ap(apdev[0], params)
+ dev[0].connect("test-vht40-wep", scan_freq="5180", key_mgmt="NONE",
+ wep_key0='"hello"')
+ hwsim_utils.test_connectivity(dev[0], hapd)
+ status = hapd.get_status()
+ logger.info("hostapd STATUS: " + str(status))
+ if status["ieee80211n"] != "0":
+ raise Exception("Unexpected STATUS ieee80211n value")
+ if status["ieee80211ac"] != "0":
+ raise Exception("Unexpected STATUS ieee80211ac value")
+ if status["secondary_channel"] != "0":
+ raise Exception("Unexpected STATUS secondary_channel value")
+ finally:
+ dev[0].request("DISCONNECT")
+ if hapd:
+ hapd.request("DISABLE")
+ subprocess.call(['iw', 'reg', 'set', '00'])
+ dev[0].flush_scan_cache()
wpas = get_wext_interface()
params = { "ssid": "wext-open" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
wpas.connect("wext-open", key_mgmt="NONE")
hwsim_utils.test_connectivity(wpas, hapd)
wpas = get_wext_interface()
params = hostapd.wpa2_params(ssid="wext-wpa2-psk", passphrase="12345678")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
wpas.connect("wext-wpa2-psk", psk="12345678")
hwsim_utils.test_connectivity(wpas, hapd)
wpas = get_wext_interface()
params = hostapd.wpa_params(ssid="wext-wpa-psk", passphrase="12345678")
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
testfile = "/sys/kernel/debug/ieee80211/%s/netdev:%s/tkip_mic_test" % (hapd.get_driver_status_field("phyname"), apdev[0]['ifname'])
if not os.path.exists(testfile):
wpas.close_ctrl()
wpas = get_wext_interface()
params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache")
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
bssid = apdev[0]['bssid']
wpas.connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP",
eap="GPSK", identity="gpsk user",
if pmksa['opportunistic'] != '0':
raise Exception("Unexpected opportunistic PMKSA cache entry")
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
bssid2 = apdev[1]['bssid']
wpas.dump_monitor()
"""WEP Open System authentication"""
wpas = get_wext_interface()
- hapd = hostapd.add_ap(apdev[0]['ifname'],
+ hapd = hostapd.add_ap(apdev[0],
{ "ssid": "wep-open",
"wep_key0": '"hello"' })
wpas.connect("wep-open", key_mgmt="NONE", wep_key0='"hello"',
"""WEP Shared Key authentication"""
wpas = get_wext_interface()
- hapd = hostapd.add_ap(apdev[0]['ifname'],
+ hapd = hostapd.add_ap(apdev[0],
{ "ssid": "wep-shared-key",
"wep_key0": '"hello12345678"',
"auth_algs": "2" })
wpas = get_wext_interface()
params = hostapd.wpa2_params(ssid="wext-wpa2-psk", passphrase="12345678")
- params["wpa_key_mgmt"] = "WPA-PSK-SHA256";
- params["ieee80211w"] = "2";
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
+ params["ieee80211w"] = "2"
+ hapd = hostapd.add_ap(apdev[0], params)
wpas.connect("wext-wpa2-psk", psk="12345678", ieee80211w="1",
key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
"""WEXT with hidden SSID"""
wpas = get_wext_interface()
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "test-scan",
- "ignore_broadcast_ssid": "1" })
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], { "ssid": "test-scan2",
- "ignore_broadcast_ssid": "1" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "test-scan",
+ "ignore_broadcast_ssid": "1" })
+ hapd2 = hostapd.add_ap(apdev[1], { "ssid": "test-scan2",
+ "ignore_broadcast_ssid": "1" })
id1 = wpas.connect("test-scan", key_mgmt="NONE", scan_ssid="1",
only_add_network=True)
wpas = get_wext_interface()
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
wpas.connect("open", key_mgmt="NONE", scan_freq="2412")
try:
logger.info("rfkill block")
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import binascii
import struct
import time
import subprocess
import hostapd
+from wpasupplicant import WpaSupplicant
+from utils import alloc_fail, wait_fail_trigger
from wlantest import Wlantest
+@remote_compatible
def test_wnm_bss_transition_mgmt(dev, apdev):
"""WNM BSS Transition Management"""
params = { "ssid": "test-wnm",
"time_zone": "EST5",
"wnm_sleep_mode": "1",
"bss_transition": "1" }
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
dev[0].request("WNM_BSS_QUERY 0")
+@remote_compatible
def test_wnm_disassoc_imminent(dev, apdev):
"""WNM Disassociation Imminent"""
params = { "ssid": "test-wnm",
"time_zone": "EST5",
"wnm_sleep_mode": "1",
"bss_transition": "1" }
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
addr = dev[0].p2p_interface_addr()
if ev is None:
raise Exception("Timeout while waiting for re-connection scan")
+@remote_compatible
def test_wnm_ess_disassoc_imminent(dev, apdev):
"""WNM ESS Disassociation Imminent"""
params = { "ssid": "test-wnm",
"time_zone": "EST5",
"wnm_sleep_mode": "1",
"bss_transition": "1" }
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
addr = dev[0].p2p_interface_addr()
if ev is None:
raise Exception("Timeout while waiting for re-connection scan")
+def test_wnm_ess_disassoc_imminent_reject(dev, apdev):
+ """WNM ESS Disassociation Imminent getting rejected"""
+ params = { "ssid": "test-wnm",
+ "bss_transition": "1" }
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
+ addr = dev[0].own_addr()
+ if "OK" not in dev[0].request("SET reject_btm_req_reason 123"):
+ raise Exception("Failed to set reject_btm_req_reason")
+
+ hapd.request("ESS_DISASSOC " + addr + " 1 http://example.com/session-info")
+ ev = hapd.wait_event(["BSS-TM-RESP"], timeout=10)
+ if ev is None:
+ raise Exception("BSS-TM-RESP not seen")
+ if "status_code=123" not in ev:
+ raise Exception("Unexpected response status: " + ev)
+ dev[0].wait_disconnected()
+ dev[0].request("DISCONNECT")
+
+@remote_compatible
def test_wnm_ess_disassoc_imminent_pmf(dev, apdev):
"""WNM ESS Disassociation Imminent"""
params = hostapd.wpa2_params("test-wnm-rsn", "12345678")
- params["wpa_key_mgmt"] = "WPA-PSK-SHA256";
- params["ieee80211w"] = "2";
+ params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
+ params["ieee80211w"] = "2"
params["bss_transition"] = "1"
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
if not ok:
raise Exception("Station failed to exit WNM-Sleep Mode")
+@remote_compatible
def test_wnm_sleep_mode_open(dev, apdev):
"""WNM Sleep Mode - open"""
params = { "ssid": "test-wnm",
"time_zone": "EST5",
"wnm_sleep_mode": "1",
"bss_transition": "1" }
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
if "FAIL" not in dev[0].request("WNM_SLEEP " + cmd):
raise Exception("Invalid WNM_SLEEP accepted")
+@remote_compatible
def test_wnm_sleep_mode_rsn(dev, apdev):
"""WNM Sleep Mode - RSN"""
params = hostapd.wpa2_params("test-wnm-rsn", "12345678")
params["time_zone"] = "EST5"
params["wnm_sleep_mode"] = "1"
params["bss_transition"] = "1"
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wnm-rsn", psk="12345678", scan_freq="2412")
ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
raise Exception("No connection event received from hostapd")
check_wnm_sleep_mode_enter_exit(hapd, dev[0])
+@remote_compatible
+def test_wnm_sleep_mode_ap_oom(dev, apdev):
+ """WNM Sleep Mode - AP side OOM"""
+ params = { "ssid": "test-wnm",
+ "wnm_sleep_mode": "1" }
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
+ ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
+ if ev is None:
+ raise Exception("No connection event received from hostapd")
+ with alloc_fail(hapd, 1, "ieee802_11_send_wnmsleep_resp"):
+ dev[0].request("WNM_SLEEP enter")
+ wait_fail_trigger(hapd, "GET_ALLOC_FAIL")
+ with alloc_fail(hapd, 2, "ieee802_11_send_wnmsleep_resp"):
+ dev[0].request("WNM_SLEEP exit")
+ wait_fail_trigger(hapd, "GET_ALLOC_FAIL")
+
+@remote_compatible
def test_wnm_sleep_mode_rsn_pmf(dev, apdev):
"""WNM Sleep Mode - RSN with PMF"""
- wt = Wlantest()
- wt.flush()
- wt.add_passphrase("12345678")
params = hostapd.wpa2_params("test-wnm-rsn", "12345678")
- params["wpa_key_mgmt"] = "WPA-PSK-SHA256";
- params["ieee80211w"] = "2";
+ params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
+ params["ieee80211w"] = "2"
params["time_advertisement"] = "2"
params["time_zone"] = "EST5"
params["wnm_sleep_mode"] = "1"
params["bss_transition"] = "1"
- hostapd.add_ap(apdev[0]['ifname'], params)
- hapd = hostapd.Hostapd(apdev[0]['ifname'])
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ Wlantest.setup(hapd)
+ wt = Wlantest()
+ wt.flush()
+ wt.add_passphrase("12345678")
dev[0].connect("test-wnm-rsn", psk="12345678", ieee80211w="2",
key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
ACTION_CATEG_WNM = 10
WNM_ACT_BSS_TM_REQ = 7
WNM_ACT_BSS_TM_RESP = 8
+WNM_ACT_SLEEP_MODE_REQ = 16
+WNM_ACT_SLEEP_MODE_RESP = 17
+WNM_ACT_NOTIFICATION_REQ = 26
+WNM_ACT_NOTIFICATION_RESP = 27
+WNM_NOTIF_TYPE_FW_UPGRADE = 0
+WNM_NOTIF_TYPE_WFA = 1
+WLAN_EID_TFS_RESP = 92
+WLAN_EID_WNMSLEEP = 93
+WNM_SLEEP_MODE_ENTER = 0
+WNM_SLEEP_MODE_EXIT = 1
+WNM_STATUS_SLEEP_ACCEPT = 0
+WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE = 1
+WNM_STATUS_DENIED_ACTION = 2
+WNM_STATUS_DENIED_TMP = 3
+WNM_STATUS_DENIED_KEY = 4
+WNM_STATUS_DENIED_OTHER_WNM_SERVICE = 5
+WNM_SLEEP_SUBELEM_GTK = 0
+WNM_SLEEP_SUBELEM_IGTK = 1
def bss_tm_req(dst, src, dialog_token=1, req_mode=0, disassoc_timer=0,
validity_interval=1):
if "ok=1" not in ev:
raise Exception("Action frame not acknowledged")
+@remote_compatible
def test_wnm_bss_tm_req(dev, apdev):
"""BSS Transition Management Request"""
params = { "ssid": "test-wnm", "bss_transition": "1" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
hapd.set("ext_mgmt_frame_handling", "1")
hapd.mgmt_tx(req)
resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
+ # Preferred Candidate List followed by vendor element
+ req = bss_tm_req(dev[0].p2p_interface_addr(), apdev[0]['bssid'],
+ req_mode=0x01, dialog_token=8)
+ subelems = ""
+ req['payload'] += struct.pack("<BB6BLBBB", 52, 13 + len(subelems),
+ 1, 2, 3, 4, 5, 6,
+ 0, 81, 1, 7) + subelems
+ req['payload'] += binascii.unhexlify("DD0411223344")
+ hapd.mgmt_tx(req)
+ resp = rx_bss_tm_resp(hapd, expect_dialog=8, expect_status=7)
+
+@remote_compatible
def test_wnm_bss_keep_alive(dev, apdev):
"""WNM keep-alive"""
params = { "ssid": "test-wnm",
"ap_max_inactivity": "1" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
addr = dev[0].p2p_interface_addr()
dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
"hw_mode": "g",
"channel": "1",
"bss_transition": "1" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
id = dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
dev[0].set_network(id, "scan_freq", "")
"hw_mode": "a",
"channel": "36",
"bss_transition": "1" }
- hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
+ hapd2 = hostapd.add_ap(apdev[1], params)
addr = dev[0].p2p_interface_addr()
dev[0].dump_monitor()
raise Exception("Unexpected scan started")
ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=0.5)
if ev is not None:
- raise Exception("Unexpected reassociation");
+ raise Exception("Unexpected reassociation")
+ finally:
+ dev[0].request("DISCONNECT")
+ if hapd:
+ hapd.request("DISABLE")
+ if hapd2:
+ hapd2.request("DISABLE")
+ subprocess.call(['iw', 'reg', 'set', '00'])
+ dev[0].flush_scan_cache()
+
+def test_wnm_bss_tm_scan_not_needed(dev, apdev):
+ """WNM BSS Transition Management and scan not needed"""
+ run_wnm_bss_tm_scan_not_needed(dev, apdev)
+
+def test_wnm_bss_tm_nei_vht(dev, apdev):
+ """WNM BSS Transition Management and VHT neighbor"""
+ run_wnm_bss_tm_scan_not_needed(dev, apdev, vht=True, nei_info="115,36,9")
+
+def test_wnm_bss_tm_nei_11a(dev, apdev):
+ """WNM BSS Transition Management and 11a neighbor"""
+ run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=False, nei_info="115,36,4")
+
+def test_wnm_bss_tm_nei_11g(dev, apdev):
+ """WNM BSS Transition Management and 11g neighbor"""
+ run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=False, hwmode='g',
+ channel='2', freq=2417, nei_info="81,2,6")
+
+def test_wnm_bss_tm_nei_11b(dev, apdev):
+ """WNM BSS Transition Management and 11g neighbor"""
+ run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=False, hwmode='b',
+ channel='3', freq=2422, nei_info="81,2,5")
+
+def run_wnm_bss_tm_scan_not_needed(dev, apdev, ht=True, vht=False, hwmode='a',
+ channel='36', freq=5180,
+ nei_info="115,36,7,0301ff"):
+ try:
+ hapd = None
+ hapd2 = None
+ params = { "ssid": "test-wnm",
+ "country_code": "FI",
+ "ieee80211d": "1",
+ "hw_mode": "g",
+ "channel": "1",
+ "bss_transition": "1" }
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ params = { "ssid": "test-wnm",
+ "country_code": "FI",
+ "ieee80211d": "1",
+ "hw_mode": hwmode,
+ "channel": channel,
+ "bss_transition": "1" }
+ if not ht:
+ params['ieee80211n'] = '0'
+ if vht:
+ params['ieee80211ac'] = "1"
+ params["vht_oper_chwidth"] = "0"
+ params["vht_oper_centr_freq_seg0_idx"] = "0"
+
+ hapd2 = hostapd.add_ap(apdev[1], params)
+
+ dev[0].scan_for_bss(apdev[1]['bssid'], freq)
+
+ id = dev[0].connect("test-wnm", key_mgmt="NONE",
+ bssid=apdev[0]['bssid'], scan_freq="2412")
+ dev[0].set_network(id, "scan_freq", "")
+ dev[0].set_network(id, "bssid", "")
+
+ addr = dev[0].own_addr()
+ dev[0].dump_monitor()
+
+ logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
+ if "OK" not in hapd.request("BSS_TM_REQ " + addr + " pref=1 abridged=1 valid_int=255 neighbor=" + apdev[1]['bssid'] + ",0x0000," + nei_info):
+ raise Exception("BSS_TM_REQ command failed")
+ ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
+ if ev is None:
+ raise Exception("No BSS Transition Management Response")
+ if "status_code=0" not in ev:
+ raise Exception("BSS transition request was not accepted: " + ev)
+ if "target_bssid=" + apdev[1]['bssid'] not in ev:
+ raise Exception("Unexpected target BSS: " + ev)
+ dev[0].wait_connected(timeout=15, error="No reassociation seen")
+ if apdev[1]['bssid'] not in ev:
+ raise Exception("Unexpected reassociation target: " + ev)
+ ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
+ if ev is not None:
+ raise Exception("Unexpected scan started")
+ dev[0].dump_monitor()
+ finally:
+ dev[0].request("DISCONNECT")
+ if hapd:
+ hapd.request("DISABLE")
+ if hapd2:
+ hapd2.request("DISABLE")
+ subprocess.call(['iw', 'reg', 'set', '00'])
+ dev[0].flush_scan_cache()
+
+def test_wnm_bss_tm_scan_needed(dev, apdev):
+ """WNM BSS Transition Management and scan needed"""
+ try:
+ hapd = None
+ hapd2 = None
+ params = { "ssid": "test-wnm",
+ "country_code": "FI",
+ "ieee80211d": "1",
+ "hw_mode": "g",
+ "channel": "1",
+ "bss_transition": "1" }
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ params = { "ssid": "test-wnm",
+ "country_code": "FI",
+ "ieee80211d": "1",
+ "hw_mode": "a",
+ "channel": "36",
+ "bss_transition": "1" }
+ hapd2 = hostapd.add_ap(apdev[1], params)
+
+ dev[0].scan_for_bss(apdev[1]['bssid'], 5180)
+
+ id = dev[0].connect("test-wnm", key_mgmt="NONE",
+ bssid=apdev[0]['bssid'], scan_freq="2412")
+ dev[0].set_network(id, "scan_freq", "")
+ dev[0].set_network(id, "bssid", "")
+
+ addr = dev[0].own_addr()
+ dev[0].dump_monitor()
+
+ logger.info("Wait 11 seconds for the last scan result to be too old, but still present in BSS table")
+ time.sleep(11)
+ logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
+ if "OK" not in hapd.request("BSS_TM_REQ " + addr + " pref=1 abridged=1 valid_int=255 neighbor=" + apdev[1]['bssid'] + ",0x0000,115,36,7,0301ff"):
+ raise Exception("BSS_TM_REQ command failed")
+ ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
+ if ev is None:
+ raise Exception("No BSS Transition Management Response")
+ if "status_code=0" not in ev:
+ raise Exception("BSS transition request was not accepted: " + ev)
+ if "target_bssid=" + apdev[1]['bssid'] not in ev:
+ raise Exception("Unexpected target BSS: " + ev)
+ dev[0].wait_connected(timeout=15, error="No reassociation seen")
+ if apdev[1]['bssid'] not in ev:
+ raise Exception("Unexpected reassociation target: " + ev)
+ ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=0.1)
+ if ev is not None:
+ raise Exception("Unexpected scan started")
+ dev[0].dump_monitor()
finally:
dev[0].request("DISCONNECT")
if hapd:
"hw_mode": "g",
"channel": "1",
"bss_transition": "1" }
- hapd = hostapd.add_ap(ap['ifname'], params)
+ hapd = hostapd.add_ap(ap, params)
id = dev.connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
dev.dump_monitor()
dev.set_network(id, "scan_freq", "")
wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=00:11:22:33:44:00,0x0000,124,162,7 neighbor=00:11:22:33:44:01,0x0000,125,148,7 neighbor=00:11:22:33:44:02,0x0000,125,170,7 neighbor=00:11:22:33:44:03,0x0000,128,35,7 neighbor=00:11:22:33:44:04,0x0000,128,162,7 neighbor=00:11:22:33:44:05,0x0000,129,49,7 neighbor=00:11:22:33:44:06,0x0000,129,115,7 neighbor=00:11:22:33:44:07,0x0000,180,0,7 neighbor=00:11:22:33:44:08,0x0000,180,5,7 neighbor=00:11:22:33:44:09,0x0000,0,0,7")
finally:
stop_wnm_tm(hapd, dev[0])
+
+def test_wnm_bss_tm_op_class_0(dev, apdev):
+ """WNM BSS Transition Management with invalid operating class"""
+ try:
+ hapd = None
+ hapd, id = start_wnm_tm(apdev[0], "US", dev[0])
+
+ logger.info("Preferred Candidate List (no matching neighbor, invalid op class specified for channels)")
+ wnm_bss_tm_check(hapd, dev[0], "pref=1 neighbor=00:11:22:33:44:59,0x0000,0,149,7 neighbor=00:11:22:33:44:5b,0x0000,0,1,7")
+ finally:
+ stop_wnm_tm(hapd, dev[0])
+
+def test_wnm_action_proto(dev, apdev):
+ """WNM Action protocol testing"""
+ params = { "ssid": "test-wnm" }
+ params['wnm_sleep_mode'] = '1'
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+ dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
+ dev[0].request("WNM_SLEEP enter")
+ time.sleep(0.1)
+ hapd.set("ext_mgmt_frame_handling", "1")
+
+ msg = {}
+ msg['fc'] = MGMT_SUBTYPE_ACTION << 4
+ msg['da'] = dev[0].own_addr()
+ msg['sa'] = bssid
+ msg['bssid'] = bssid
+
+ dialog_token = 1
+
+ logger.debug("Unexpected WNM-Notification Response")
+ # Note: This is actually not registered for user space processing in
+ # driver_nl80211.c nl80211_mgmt_subscribe_non_ap() and as such, won't make
+ # it to wpa_supplicant.
+ msg['payload'] = struct.pack("<BBBB",
+ ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_RESP,
+ dialog_token, 0)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("Truncated WNM-Notification Request (no Type field)")
+ msg['payload'] = struct.pack("<BBB",
+ ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
+ dialog_token)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WFA WNM-Notification Request with truncated IE (min)")
+ msg['payload'] = struct.pack("<BBBBBB",
+ ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
+ dialog_token, WNM_NOTIF_TYPE_WFA, 0, 1)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WFA WNM-Notification Request with truncated IE (max)")
+ msg['payload'] = struct.pack("<BBBBBB",
+ ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
+ dialog_token, WNM_NOTIF_TYPE_WFA, 0, 255)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WFA WNM-Notification Request with too short IE")
+ msg['payload'] = struct.pack("<BBBBBB",
+ ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
+ dialog_token, WNM_NOTIF_TYPE_WFA, 0, 0)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL")
+ msg['payload'] = struct.pack(">BBBBBBLB",
+ ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
+ dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
+ 0x506f9a00, 1)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(2)")
+ msg['payload'] = struct.pack(">BBBBBBLBB",
+ ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
+ dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 6,
+ 0x506f9a00, 1, 0)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WFA WNM-Notification Request with truncated Sub Rem URL(3)")
+ msg['payload'] = struct.pack(">BBBBBBLB",
+ ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
+ dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 5,
+ 0x506f9a00, 0xff)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(min)")
+ msg['payload'] = struct.pack(">BBBBBBLBHB",
+ ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
+ dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
+ 0x506f9a01, 0, 0, 1)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WFA WNM-Notification Request with truncated Deauth Imminent URL(max)")
+ msg['payload'] = struct.pack(">BBBBBBLBHB",
+ ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
+ dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 8,
+ 0x506f9a01, 0, 0, 0xff)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WFA WNM-Notification Request with unsupported IE")
+ msg['payload'] = struct.pack("<BBBBBBL",
+ ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
+ dialog_token, WNM_NOTIF_TYPE_WFA, 0xdd, 4, 0)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WNM-Notification Request with unknown WNM-Notification type 0")
+ msg['payload'] = struct.pack("<BBBB",
+ ACTION_CATEG_WNM, WNM_ACT_NOTIFICATION_REQ,
+ dialog_token, WNM_NOTIF_TYPE_FW_UPGRADE)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("Truncated WNM Sleep Mode Response - no Dialog Token")
+ msg['payload'] = struct.pack("<BB",
+ ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("Truncated WNM Sleep Mode Response - no Key Data Length")
+ msg['payload'] = struct.pack("<BBB",
+ ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (min)")
+ msg['payload'] = struct.pack("<BBBH",
+ ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
+ 1)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("Truncated WNM Sleep Mode Response - truncated Key Data (max)")
+ msg['payload'] = struct.pack("<BBBH",
+ ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
+ 0xffff)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WNM Sleep Mode Response - truncated IE header")
+ msg['payload'] = struct.pack("<BBBHB",
+ ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
+ 0, 0)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WNM Sleep Mode Response - truncated IE")
+ msg['payload'] = struct.pack("<BBBHBB",
+ ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
+ 0, 0, 1)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WNM Sleep Mode Response - Empty TFS Response")
+ msg['payload'] = struct.pack("<BBBHBB",
+ ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
+ 0, WLAN_EID_TFS_RESP, 0)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WNM Sleep Mode Response - EID 0 not recognized")
+ msg['payload'] = struct.pack("<BBBHBB",
+ ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
+ 0, 0, 0)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WNM Sleep Mode Response - Empty WNM Sleep Mode element and TFS Response element")
+ msg['payload'] = struct.pack("<BBBHBBBB",
+ ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
+ 0, WLAN_EID_WNMSLEEP, 0, WLAN_EID_TFS_RESP, 0)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element and empty TFS Response element")
+ msg['payload'] = struct.pack("<BBBHBBBBHBB",
+ ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
+ 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
+ WNM_STATUS_SLEEP_ACCEPT, 0,
+ WLAN_EID_TFS_RESP, 0)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(exit, deny key) and empty TFS Response element")
+ msg['payload'] = struct.pack("<BBBHBBBBHBB",
+ ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
+ 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
+ WNM_STATUS_DENIED_KEY, 0,
+ WLAN_EID_TFS_RESP, 0)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WNM Sleep Mode Response - WNM Sleep Mode element(enter, deny key) and empty TFS Response element")
+ msg['payload'] = struct.pack("<BBBHBBBBHBB",
+ ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
+ 0, WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_ENTER,
+ WNM_STATUS_DENIED_KEY, 0,
+ WLAN_EID_TFS_RESP, 0)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+@remote_compatible
+def test_wnm_action_proto_pmf(dev, apdev):
+ """WNM Action protocol testing (PMF enabled)"""
+ ssid = "test-wnm-pmf"
+ params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
+ params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
+ params["ieee80211w"] = "2"
+ params['wnm_sleep_mode'] = '1'
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+ dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK-SHA256",
+ proto="WPA2", ieee80211w="2", scan_freq="2412")
+ dev[0].request("WNM_SLEEP enter")
+ time.sleep(0.1)
+ hapd.set("ext_mgmt_frame_handling", "1")
+
+ msg = {}
+ msg['fc'] = MGMT_SUBTYPE_ACTION << 4
+ msg['da'] = dev[0].own_addr()
+ msg['sa'] = bssid
+ msg['bssid'] = bssid
+
+ logger.debug("WNM Sleep Mode Response - Invalid Key Data element length")
+ keydata = struct.pack("<BB", 0, 1)
+ msg['payload'] = struct.pack("<BBBH",
+ ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
+ len(keydata))
+ msg['payload'] += keydata
+ msg['payload'] += struct.pack("<BBBBHBB",
+ WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
+ WNM_STATUS_SLEEP_ACCEPT, 0,
+ WLAN_EID_TFS_RESP, 0)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WNM Sleep Mode Response - Too short GTK subelem")
+ keydata = struct.pack("<BB", WNM_SLEEP_SUBELEM_GTK, 0)
+ msg['payload'] = struct.pack("<BBBH",
+ ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
+ len(keydata))
+ msg['payload'] += keydata
+ msg['payload'] += struct.pack("<BBBBHBB",
+ WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
+ WNM_STATUS_SLEEP_ACCEPT, 0,
+ WLAN_EID_TFS_RESP, 0)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WNM Sleep Mode Response - Invalid GTK subelem")
+ keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
+ 0, 17, 0, 0, 0, 0, 0, 0)
+ msg['payload'] = struct.pack("<BBBH",
+ ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
+ len(keydata))
+ msg['payload'] += keydata
+ msg['payload'] += struct.pack("<BBBBHBB",
+ WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
+ WNM_STATUS_SLEEP_ACCEPT, 0,
+ WLAN_EID_TFS_RESP, 0)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WNM Sleep Mode Response - Invalid GTK subelem (2)")
+ keydata = struct.pack("<BBHB2L4L", WNM_SLEEP_SUBELEM_GTK, 11 + 16,
+ 0, 0, 0, 0, 0, 0, 0, 0)
+ msg['payload'] = struct.pack("<BBBH",
+ ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
+ len(keydata))
+ msg['payload'] += keydata
+ msg['payload'] += struct.pack("<BBBBHBB",
+ WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
+ WNM_STATUS_SLEEP_ACCEPT, 0,
+ WLAN_EID_TFS_RESP, 0)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WNM Sleep Mode Response - GTK subelem and too short IGTK subelem")
+ keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
+ keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
+ 0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
+ keydata += struct.pack("<BB", WNM_SLEEP_SUBELEM_IGTK, 0)
+ msg['payload'] = struct.pack("<BBBH",
+ ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
+ len(keydata))
+ msg['payload'] += keydata
+ msg['payload'] += struct.pack("<BBBBHBB",
+ WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
+ WNM_STATUS_SLEEP_ACCEPT, 0,
+ WLAN_EID_TFS_RESP, 0)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ logger.debug("WNM Sleep Mode Response - Unknown subelem")
+ keydata = struct.pack("<BB", 255, 0)
+ msg['payload'] = struct.pack("<BBBH",
+ ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
+ len(keydata))
+ msg['payload'] += keydata
+ msg['payload'] += struct.pack("<BBBBHBB",
+ WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
+ WNM_STATUS_SLEEP_ACCEPT, 0,
+ WLAN_EID_TFS_RESP, 0)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+@remote_compatible
+def test_wnm_action_proto_no_pmf(dev, apdev):
+ """WNM Action protocol testing (PMF disabled)"""
+ ssid = "test-wnm-no-pmf"
+ params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
+ params['wnm_sleep_mode'] = '1'
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+ dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
+ proto="WPA2", ieee80211w="0", scan_freq="2412")
+ dev[0].request("WNM_SLEEP enter")
+ time.sleep(0.1)
+ hapd.set("ext_mgmt_frame_handling", "1")
+
+ msg = {}
+ msg['fc'] = MGMT_SUBTYPE_ACTION << 4
+ msg['da'] = dev[0].own_addr()
+ msg['sa'] = bssid
+ msg['bssid'] = bssid
+
+ logger.debug("WNM Sleep Mode Response - GTK subelem and IGTK subelem")
+ keydata = struct.pack("<BBHB", WNM_SLEEP_SUBELEM_GTK, 11 + 16, 0, 16)
+ keydata += struct.pack(">2L4L", 0x01020304, 0x05060708,
+ 0x11223344, 0x55667788, 0x9900aabb, 0xccddeeff)
+ keydata += struct.pack("<BBHLH4L", WNM_SLEEP_SUBELEM_IGTK, 2 + 6 + 16, 0,
+ 0x10203040, 0x5060,
+ 0xf1f2f3f4, 0xf5f6f7f8, 0xf9f0fafb, 0xfcfdfeff)
+ msg['payload'] = struct.pack("<BBBH",
+ ACTION_CATEG_WNM, WNM_ACT_SLEEP_MODE_RESP, 0,
+ len(keydata))
+ msg['payload'] += keydata
+ msg['payload'] += struct.pack("<BBBBHBB",
+ WLAN_EID_WNMSLEEP, 4, WNM_SLEEP_MODE_EXIT,
+ WNM_STATUS_SLEEP_ACCEPT, 0,
+ WLAN_EID_TFS_RESP, 0)
+ hapd.mgmt_tx(msg)
+ expect_ack(hapd)
+
+ ev = dev[0].wait_event(["WNM: Ignore Key Data"], timeout=5)
+ if ev is None:
+ raise Exception("Key Data not ignored")
+
+def test_wnm_bss_tm_req_with_mbo_ie(dev, apdev):
+ """WNM BSS transition request with MBO IE and reassociation delay attribute"""
+ ssid = "test-wnm-mbo"
+ params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+ if "OK" not in dev[0].request("SET mbo_cell_capa 1"):
+ raise Exception("Failed to set STA as cellular data capable")
+
+ dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
+ proto="WPA2", ieee80211w="0", scan_freq="2412")
+
+ logger.debug("BTM request with MBO reassociation delay when disassoc imminent is not set")
+ if 'FAIL' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " mbo=3:2:1"):
+ raise Exception("BSS transition management succeeded unexpectedly")
+
+ logger.debug("BTM request with invalid MBO transition reason code")
+ if 'FAIL' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " mbo=10:2:1"):
+ raise Exception("BSS transition management succeeded unexpectedly")
+
+ logger.debug("BTM request with MBO reassociation retry delay of 5 seconds")
+ if 'OK' not in hapd.request("BSS_TM_REQ " + dev[0].own_addr() + " disassoc_imminent=1 disassoc_timer=3 mbo=3:5:1"):
+ raise Exception("BSS transition management command failed")
+
+ ev = dev[0].wait_event(['MBO-CELL-PREFERENCE'], 1)
+ if ev is None or "preference=1" not in ev:
+ raise Exception("Timeout waiting for MBO-CELL-PREFERENCE event")
+
+ ev = dev[0].wait_event(['MBO-TRANSITION-REASON'], 1)
+ if ev is None or "reason=3" not in ev:
+ raise Exception("Timeout waiting for MBO-TRANSITION-REASON event")
+
+ ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
+ if ev is None:
+ raise Exception("No BSS Transition Management Response")
+ if dev[0].own_addr() not in ev:
+ raise Exception("Unexpected BSS Transition Management Response address")
+
+ ev = dev[0].wait_event(['CTRL-EVENT-DISCONNECTED'], 5)
+ if ev is None:
+ raise Exception("Station did not disconnect although disassoc imminent was set")
+
+ # Set the scan interval to make dev[0] look for connections
+ if 'OK' not in dev[0].request("SCAN_INTERVAL 1"):
+ raise Exception("Failed to set scan interval")
+
+ # Make sure no connection is made during the retry delay
+ ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 5)
+ if ev is not None:
+ raise Exception("Station connected before assoc retry delay was over")
+
+ # After the assoc retry delay is over, we can reconnect
+ ev = dev[0].wait_event(['CTRL-EVENT-CONNECTED'], 5)
+ if ev is None:
+ raise Exception("Station did not connect after assoc retry delay is over")
+
+ if "OK" not in dev[0].request("SET mbo_cell_capa 3"):
+ raise Exception("Failed to set STA as cellular data not-capable")
+
+@remote_compatible
+def test_wnm_bss_transition_mgmt_query(dev, apdev):
+ """WNM BSS Transition Management query"""
+ params = { "ssid": "test-wnm",
+ "bss_transition": "1" }
+ hapd = hostapd.add_ap(apdev[0], params)
+ params = { "ssid": "another" }
+ hapd2 = hostapd.add_ap(apdev[1], params)
+
+ dev[0].scan_for_bss(apdev[1]['bssid'], 2412)
+ dev[0].scan_for_bss(apdev[0]['bssid'], 2412)
+
+ dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
+ dev[0].request("WNM_BSS_QUERY 0 list")
+
+ ev = dev[0].wait_event(["WNM: BSS Transition Management Request"],
+ timeout=5)
+ if ev is None:
+ raise Exception("No BSS Transition Management Request frame seen")
+
+ ev = hapd.wait_event(["BSS-TM-RESP"], timeout=5)
+ if ev is None:
+ raise Exception("No BSS Transition Management Response frame seen")
+
+@remote_compatible
+def test_wnm_bss_tm_security_mismatch(dev, apdev):
+ """WNM BSS Transition Management and security mismatch"""
+ params = { "ssid": "test-wnm",
+ "wpa": "2",
+ "wpa_key_mgmt": "WPA-PSK",
+ "rsn_pairwise": "CCMP",
+ "wpa_passphrase": "12345678",
+ "hw_mode": "g",
+ "channel": "1",
+ "bss_transition": "1" }
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ params = { "ssid": "test-wnm",
+ "hw_mode": "g",
+ "channel": "11",
+ "bss_transition": "1" }
+ hapd2 = hostapd.add_ap(apdev[1], params)
+
+ dev[0].scan_for_bss(apdev[1]['bssid'], 2462)
+
+ id = dev[0].connect("test-wnm", psk="12345678",
+ bssid=apdev[0]['bssid'], scan_freq="2412")
+ dev[0].set_network(id, "scan_freq", "")
+ dev[0].set_network(id, "bssid", "")
+
+ addr = dev[0].own_addr()
+ dev[0].dump_monitor()
+
+ logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
+ if "OK" not in hapd.request("BSS_TM_REQ " + addr + " pref=1 abridged=1 valid_int=255 neighbor=" + apdev[1]['bssid'] + ",0x0000,115,36,7,0301ff"):
+ raise Exception("BSS_TM_REQ command failed")
+ ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
+ if ev is None:
+ raise Exception("No BSS Transition Management Response")
+ if "status_code=7" not in ev:
+ raise Exception("Unexpected BSS transition request response: " + ev)
+
+def test_wnm_bss_tm_connect_cmd(dev, apdev):
+ """WNM BSS Transition Management and cfg80211 connect command"""
+ params = { "ssid": "test-wnm",
+ "hw_mode": "g",
+ "channel": "1",
+ "bss_transition": "1" }
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ params = { "ssid": "test-wnm",
+ "hw_mode": "g",
+ "channel": "11",
+ "bss_transition": "1" }
+ hapd2 = hostapd.add_ap(apdev[1], params)
+
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
+
+ wpas.scan_for_bss(apdev[1]['bssid'], 2462)
+
+ id = wpas.connect("test-wnm", key_mgmt="NONE",
+ bssid=apdev[0]['bssid'], scan_freq="2412")
+ wpas.set_network(id, "scan_freq", "")
+ wpas.set_network(id, "bssid", "")
+
+ addr = wpas.own_addr()
+ wpas.dump_monitor()
+
+ logger.info("Preferred Candidate List (matching neighbor for another BSS) without Disassociation Imminent")
+ if "OK" not in hapd.request("BSS_TM_REQ " + addr + " pref=1 abridged=1 valid_int=255 neighbor=" + apdev[1]['bssid'] + ",0x0000,115,36,7,0301ff"):
+ raise Exception("BSS_TM_REQ command failed")
+ ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
+ if ev is None:
+ raise Exception("No BSS Transition Management Response")
+ if "status_code=0" not in ev:
+ raise Exception("BSS transition request was not accepted: " + ev)
+ if "target_bssid=" + apdev[1]['bssid'] not in ev:
+ raise Exception("Unexpected target BSS: " + ev)
+ ev = wpas.wait_event(["CTRL-EVENT-CONNECTED",
+ "CTRL-EVENT-DISCONNECTED"], timeout=10)
+ if ev is None:
+ raise Exception("No reassociation seen")
+ if "CTRL-EVENT-DISCONNECTED" in ev:
+ #TODO: Uncomment this once kernel side changes for Connect command
+ #reassociation are in upstream.
+ #raise Exception("Unexpected disconnection reported")
+ logger.info("Unexpected disconnection reported")
+ ev = wpas.wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
+ if ev is None:
+ raise Exception("No reassociation seen")
+ if apdev[1]['bssid'] not in ev:
+ raise Exception("Unexpected reassociation target: " + ev)
+
+def test_wnm_bss_tm_reject(dev, apdev):
+ """WNM BSS Transition Management request getting rejected"""
+ try:
+ hapd = None
+ params = { "ssid": "test-wnm",
+ "country_code": "FI",
+ "ieee80211d": "1",
+ "hw_mode": "g",
+ "channel": "1",
+ "bss_transition": "1" }
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ id = dev[0].connect("test-wnm", key_mgmt="NONE", scan_freq="2412")
+ addr = dev[0].own_addr()
+ dev[0].dump_monitor()
+
+ if "OK" not in dev[0].request("SET reject_btm_req_reason 123"):
+ raise Exception("Failed to set reject_btm_req_reason")
+
+ if "OK" not in hapd.request("BSS_TM_REQ " + addr + " disassoc_timer=1"):
+ raise Exception("BSS_TM_REQ command failed")
+ ev = hapd.wait_event(['BSS-TM-RESP'], timeout=10)
+ if ev is None:
+ raise Exception("No BSS Transition Management Response")
+ if addr not in ev:
+ raise Exception("Unexpected BSS Transition Management Response address")
+ if "status_code=123" not in ev:
+ raise Exception("Unexpected BSS Transition Management Response status: " + ev)
+ dev[0].wait_disconnected()
+ finally:
+ dev[0].request("DISCONNECT")
+ if hapd:
+ hapd.request("DISABLE")
+ subprocess.call(['iw', 'reg', 'set', '00'])
+ dev[0].flush_scan_cache()
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import time
import logging
logger = logging.getLogger()
import hwsim_utils
-from utils import HwsimSkip
+from utils import HwsimSkip, alloc_fail
+from wpasupplicant import WpaSupplicant
from test_p2p_channel import set_country
def wait_ap_ready(dev):
dev[1].request("DISCONNECT")
dev[2].request("DISCONNECT")
+@remote_compatible
def test_wpas_ap_wep(dev):
"""wpa_supplicant AP mode - WEP"""
id = dev[0].add_network()
hwsim_utils.test_connectivity(dev[0], dev[1])
dev[1].request("DISCONNECT")
+@remote_compatible
def test_wpas_ap_no_ssid(dev):
"""wpa_supplicant AP mode - invalid network configuration"""
id = dev[0].add_network()
if ev is not None:
raise Exception("Unexpected AP start")
+@remote_compatible
def test_wpas_ap_default_frequency(dev):
"""wpa_supplicant AP mode - default frequency"""
id = dev[0].add_network()
dev[1].connect("wpas-ap-open", key_mgmt="NONE", scan_freq="2462")
dev[1].request("DISCONNECT")
+@remote_compatible
def test_wpas_ap_invalid_frequency(dev):
"""wpa_supplicant AP mode - invalid frequency configuration"""
id = dev[0].add_network()
if "FAIL" not in dev[0].request("WPS_AP_PIN set"):
raise Exception("Invalid WPS_AP_PIN command not rejected")
+def test_wpas_ap_wps_frag(dev):
+ """wpa_supplicant AP mode - WPS operations with fragmentation"""
+ id = dev[0].add_network()
+ dev[0].set_network(id, "mode", "2")
+ dev[0].set_network_quoted(id, "ssid", "wpas-ap-wps")
+ dev[0].set_network_quoted(id, "psk", "1234567890")
+ dev[0].set_network(id, "frequency", "2412")
+ dev[0].set_network(id, "scan_freq", "2412")
+ dev[0].set_network(id, "fragment_size", "300")
+ dev[0].select_network(id)
+ wait_ap_ready(dev[0])
+ bssid = dev[0].own_addr()
+
+ pin = dev[1].wps_read_pin()
+ dev[0].request("WPS_PIN any " + pin)
+ dev[1].scan_for_bss(bssid, freq="2412")
+ dev[1].request("WPS_PIN " + bssid + " " + pin)
+ dev[1].wait_connected(timeout=30)
+
def test_wpas_ap_wps_pbc_overlap(dev):
"""wpa_supplicant AP mode - WPS operations with PBC overlap"""
id = dev[0].add_network()
dev[1].request("WPS_CANCEL")
dev[2].request("WPS_CANCEL")
+@remote_compatible
+def test_wpas_ap_wps_disabled(dev):
+ """wpa_supplicant AP mode - WPS disabled"""
+ id = dev[0].add_network()
+ dev[0].set_network(id, "mode", "2")
+ dev[0].set_network_quoted(id, "ssid", "wpas-ap-no-wps")
+ dev[0].set_network_quoted(id, "psk", "12345678")
+ dev[0].set_network(id, "frequency", "2412")
+ dev[0].set_network(id, "scan_freq", "2412")
+ dev[0].set_network(id, "wps_disabled", "1")
+ dev[0].select_network(id)
+ wait_ap_ready(dev[0])
+
+ dev[1].connect("wpas-ap-no-wps", psk="12345678", scan_freq="2412")
+ dev[1].request("DISCONNECT")
+ dev[1].wait_disconnected()
+
def test_wpas_ap_dfs(dev):
"""wpa_supplicant AP mode - DFS"""
+ if dev[0].get_mcc() > 1:
+ raise HwsimSkip("DFS is not supported with multi channel contexts")
+
try:
_test_wpas_ap_dfs(dev)
finally:
dev[1].connect("wpas-ap-dfs", key_mgmt="NONE")
+@remote_compatible
def test_wpas_ap_disable(dev):
"""wpa_supplicant AP mode - DISABLE_NETWORK"""
id = dev[0].add_network()
if ev is None:
raise Exception("AP-DISABLED event not seen")
dev[0].wait_disconnected()
+
+def test_wpas_ap_acs(dev):
+ """wpa_supplicant AP mode - ACS"""
+ res = dev[0].get_capability("acs")
+ if res is None or "ACS" not in res:
+ raise HwsimSkip("ACS not supported")
+
+ id = dev[0].add_network()
+ dev[0].set_network(id, "mode", "2")
+ dev[0].set_network_quoted(id, "ssid", "wpas-ap-open")
+ dev[0].set_network(id, "key_mgmt", "NONE")
+ dev[0].set_network(id, "frequency", "2417")
+ dev[0].set_network(id, "scan_freq", "2417")
+ dev[0].set_network(id, "acs", "1")
+ dev[0].select_network(id)
+ wait_ap_ready(dev[0])
+
+ # ACS prefers channels 1, 6, 11
+ freq = dev[0].get_status_field('freq')
+ if freq == "2417":
+ raise Exception("Unexpected operating channel selected")
+
+ dev[1].connect("wpas-ap-open", key_mgmt="NONE", scan_freq=freq)
+
+@remote_compatible
+def test_wpas_ap_and_assoc_req_p2p_ie(dev):
+ """wpa_supplicant AP mode - unexpected P2P IE in Association Request"""
+ try:
+ _test_wpas_ap_and_assoc_req_p2p_ie(dev)
+ finally:
+ dev[1].request("VENDOR_ELEM_REMOVE 13 *")
+ dev[0].request("P2P_SET disabled 0")
+
+def _test_wpas_ap_and_assoc_req_p2p_ie(dev):
+ dev[0].request("P2P_SET disabled 1")
+ id = dev[0].add_network()
+ dev[0].set_network(id, "mode", "2")
+ dev[0].set_network_quoted(id, "ssid", "wpas-ap-open")
+ dev[0].set_network(id, "key_mgmt", "NONE")
+ dev[0].set_network(id, "frequency", "2412")
+ dev[0].set_network(id, "scan_freq", "2412")
+ dev[0].select_network(id)
+ wait_ap_ready(dev[0])
+
+ dev[1].request("VENDOR_ELEM_ADD 13 dd04506f9a09")
+ dev[1].connect("wpas-ap-open", key_mgmt="NONE", scan_freq="2412")
+ dev[1].request("DISCONNECT")
+ dev[1].wait_disconnected()
+
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected()
+
+@remote_compatible
+def test_wpas_ap_open_ht_disabled(dev):
+ """wpa_supplicant AP mode - open network and HT disabled"""
+ id = dev[0].add_network()
+ dev[0].set_network(id, "mode", "2")
+ dev[0].set_network_quoted(id, "ssid", "wpas-ap-open")
+ dev[0].set_network(id, "key_mgmt", "NONE")
+ dev[0].set_network(id, "frequency", "2412")
+ dev[0].set_network(id, "scan_freq", "2412")
+ dev[0].set_network(id, "disable_ht", "1")
+ dev[0].select_network(id)
+ wait_ap_ready(dev[0])
+
+ dev[1].connect("wpas-ap-open", key_mgmt="NONE", scan_freq="2412")
+ hwsim_utils.test_connectivity(dev[0], dev[1])
+
+def test_wpas_ap_failures(dev):
+ """wpa_supplicant AP mode - failures"""
+ # No SSID configured for AP mode
+ id = dev[0].add_network()
+ dev[0].set_network(id, "mode", "2")
+ dev[0].set_network(id, "key_mgmt", "NONE")
+ dev[0].set_network(id, "frequency", "2412")
+ dev[0].set_network(id, "scan_freq", "2412")
+ dev[0].select_network(id)
+ ev = dev[0].wait_event([ "CTRL-EVENT-CONNECTED" ], timeout=0.1)
+ if ev is not None:
+ raise Exception("Unexpected connection event")
+ dev[0].request("REMOVE_NETWORK all")
+
+ # Invalid pbss value(2) for AP mode
+ dev[0].dump_monitor()
+ id = dev[0].add_network()
+ dev[0].set_network(id, "mode", "2")
+ dev[0].set_network_quoted(id, "ssid", "wpas-ap-open")
+ dev[0].set_network(id, "key_mgmt", "NONE")
+ dev[0].set_network(id, "frequency", "2412")
+ dev[0].set_network(id, "scan_freq", "2412")
+ dev[0].set_network(id, "pbss", "2")
+ dev[0].select_network(id)
+ ev = dev[0].wait_event([ "CTRL-EVENT-CONNECTED",
+ "CTRL-EVENT-DISCONNECTED" ], timeout=0.1)
+ if ev is not None and "CTRL-EVENT-CONNECTED" in ev:
+ raise Exception("Unexpected connection event(2)")
+ dev[0].request("REMOVE_NETWORK all")
+
+def test_wpas_ap_oom(dev):
+ """wpa_supplicant AP mode - OOM"""
+ id = dev[0].add_network()
+ dev[0].set_network(id, "mode", "2")
+ dev[0].set_network_quoted(id, "ssid", "wpas-ap")
+ dev[0].set_network_quoted(id, "psk", "1234567890")
+ dev[0].set_network(id, "frequency", "2412")
+ dev[0].set_network(id, "scan_freq", "2412")
+ with alloc_fail(dev[0], 1, "=wpa_supplicant_conf_ap"):
+ dev[0].select_network(id)
+ dev[0].wait_disconnected()
+ dev[0].request("REMOVE_NETWORK all")
+
+ id = dev[0].add_network()
+ dev[0].set_network(id, "mode", "2")
+ dev[0].set_network_quoted(id, "ssid", "wpas-ap")
+ dev[0].set_network(id, "psk", "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef")
+ dev[0].set_network(id, "frequency", "2412")
+ dev[0].set_network(id, "scan_freq", "2412")
+ with alloc_fail(dev[0], 1, "=wpa_supplicant_conf_ap"):
+ dev[0].select_network(id)
+ dev[0].wait_disconnected()
+ dev[0].request("REMOVE_NETWORK all")
+
+ id = dev[0].add_network()
+ dev[0].set_network(id, "mode", "2")
+ dev[0].set_network_quoted(id, "ssid", "wpas-ap")
+ dev[0].set_network(id, "key_mgmt", "NONE")
+ dev[0].set_network_quoted(id, "wep_key0", "hello")
+ dev[0].set_network(id, "frequency", "2412")
+ dev[0].set_network(id, "scan_freq", "2412")
+ with alloc_fail(dev[0], 1, "=wpa_supplicant_conf_ap"):
+ dev[0].select_network(id)
+ dev[0].wait_disconnected()
+ dev[0].request("REMOVE_NETWORK all")
+
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add("wlan5")
+ wpas.request("SET manufacturer test")
+ wpas.request("SET model_name test")
+ wpas.request("SET model_number test")
+ wpas.request("SET serial_number test")
+ wpas.request("SET serial_number test")
+ wpas.request("SET serial_number test")
+ wpas.request("SET ap_vendor_elements dd0411223301")
+ id = wpas.add_network()
+ wpas.set_network(id, "mode", "2")
+ wpas.set_network_quoted(id, "ssid", "wpas-ap")
+ wpas.set_network(id, "key_mgmt", "NONE")
+ wpas.set_network(id, "frequency", "2412")
+ wpas.set_network(id, "scan_freq", "2412")
+
+ for i in range(5):
+ with alloc_fail(wpas, i, "=wpa_supplicant_conf_ap"):
+ wpas.select_network(id)
+ ev = dev[0].wait_event([ "CTRL-EVENT-CONNECTED",
+ "CTRL-EVENT-DISCONNECTED" ], timeout=1)
+ wpas.request("DISCONNECT")
+ wpas.wait_disconnected()
+
+def test_wpas_ap_params(dev):
+ """wpa_supplicant AP mode - parameters"""
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas.interface_add("wlan5")
+ wpas.request("SET manufacturer test")
+ wpas.request("SET model_name test")
+ wpas.request("SET model_number test")
+ wpas.request("SET serial_number test")
+ wpas.request("SET serial_number test")
+ wpas.request("SET serial_number test")
+ wpas.request("SET ap_vendor_elements dd0411223301")
+ id = wpas.add_network()
+ wpas.set_network(id, "mode", "2")
+ wpas.set_network_quoted(id, "ssid", "wpas-ap")
+ wpas.set_network(id, "key_mgmt", "NONE")
+ wpas.set_network(id, "frequency", "2412")
+ wpas.set_network(id, "scan_freq", "2412")
+ wpas.select_network(id)
+ wpas.wait_connected()
+ wpas.request("DISCONNECT")
+ wpas.wait_disconnected()
+
+ wpas.request("SET beacon_int 200 3")
+ wpas.request("SET dtim_period 3")
+ wpas.select_network(id)
+ wpas.wait_connected()
+ wpas.request("DISCONNECT")
+ wpas.wait_disconnected()
+
+ wpas.set_network(id, "beacon_int", "300")
+ wpas.set_network(id, "dtim_period", "2")
+ wpas.select_network(id)
+ wpas.wait_connected()
+ if "---- AP ----" not in wpas.request("PMKSA"):
+ raise Exception("AP section missing from PMKSA output")
+ if "OK" not in wpas.request("PMKSA_FLUSH"):
+ raise Exception("PMKSA_FLUSH failed")
+ wpas.request("DISCONNECT")
+ wpas.wait_disconnected()
import os
from wpasupplicant import WpaSupplicant
+import hostapd
def check_config(config):
with open(config, "r") as f:
raise Exception("Missing network")
if "wps_priority=5\n" not in data:
raise Exception("Missing wps_priority")
+ if "ip_addr_go=192.168.1.1\n" not in data:
+ raise Exception("Missing ip_addr_go")
+ if "ip_addr_mask=255.255.255.0\n" not in data:
+ raise Exception("Missing ip_addr_mask")
+ if "ip_addr_start=192.168.1.10\n" not in data:
+ raise Exception("Missing ip_addr_start")
+ if "ip_addr_end=192.168.1.20\n" not in data:
+ raise Exception("Missing ip_addr_end")
return data
def test_wpas_config_file(dev):
ev = wpas.wait_event(["CRED-MODIFIED 0 password"])
wpas.request("SET blob foo 12345678")
+ wpas.request("SET ip_addr_go 192.168.1.1")
+ wpas.request("SET ip_addr_mask 255.255.255.0")
+ wpas.request("SET ip_addr_start 192.168.1.10")
+ wpas.request("SET ip_addr_end 192.168.1.20")
if "OK" not in wpas.request("SAVE_CONFIG"):
raise Exception("Failed to save configuration file")
raise Exception("Unexpected configuration change")
wpas.request("SET update_config 0")
+ wpas.global_request("SET update_config 0")
if "OK" in wpas.request("SAVE_CONFIG"):
raise Exception("SAVE_CONFIG succeeded unexpectedly")
if "OK" in wpas.global_request("SAVE_CONFIG"):
os.remove(config)
os.mkdir(config)
wpas.request("SET update_config 1")
+ wpas.global_request("SET update_config 1")
if "OK" in wpas.request("SAVE_CONFIG"):
raise Exception("SAVE_CONFIG succeeded unexpectedly")
if "OK" in wpas.global_request("SAVE_CONFIG"):
os.rmdir(config)
except:
pass
+
+def test_wpas_config_file_wps(dev, apdev):
+ """wpa_supplicant config file parsing/writing with WPS"""
+ config = "/tmp/test_wpas_config_file.conf"
+ if os.path.exists(config):
+ os.remove(config)
+
+ params = { "ssid": "test-wps", "eap_server": "1", "wps_state": "2",
+ "skip_cred_build": "1", "extra_cred": "wps-ctrl-cred" }
+ hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+
+ try:
+ with open(config, "w") as f:
+ f.write("update_config=1\n")
+
+ wpas.interface_add("wlan5", config=config)
+
+ hapd.request("WPS_PIN any 12345670")
+ wpas.scan_for_bss(apdev[0]['bssid'], freq="2412")
+ wpas.request("WPS_PIN " + apdev[0]['bssid'] + " 12345670")
+ ev = wpas.wait_event(["WPS-FAIL"], timeout=10)
+ if ev is None:
+ raise Exception("WPS-FAIL event timed out")
+
+ with open(config, "r") as f:
+ data = f.read()
+ logger.info("Configuration file contents: " + data)
+ if "network=" in data:
+ raise Exception("Unexpected network block in configuration data")
+
+ finally:
+ try:
+ os.remove(config)
+ except:
+ pass
+ try:
+ os.remove(config + ".tmp")
+ except:
+ pass
+ try:
+ os.rmdir(config)
+ except:
+ pass
+
+def test_wpas_config_file_wps2(dev, apdev):
+ """wpa_supplicant config file parsing/writing with WPS (2)"""
+ config = "/tmp/test_wpas_config_file.conf"
+ if os.path.exists(config):
+ os.remove(config)
+
+ params = { "ssid": "test-wps", "eap_server": "1", "wps_state": "2",
+ "skip_cred_build": "1", "extra_cred": "wps-ctrl-cred2" }
+ hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+
+ try:
+ with open(config, "w") as f:
+ f.write("update_config=1\n")
+
+ wpas.interface_add("wlan5", config=config)
+
+ hapd.request("WPS_PIN any 12345670")
+ wpas.scan_for_bss(apdev[0]['bssid'], freq="2412")
+ wpas.request("WPS_PIN " + apdev[0]['bssid'] + " 12345670")
+ ev = wpas.wait_event(["WPS-SUCCESS"], timeout=10)
+ if ev is None:
+ raise Exception("WPS-SUCCESS event timed out")
+
+ with open(config, "r") as f:
+ data = f.read()
+ logger.info("Configuration file contents: " + data)
+
+ with open(config, "r") as f:
+ data = f.read()
+ if "network=" not in data:
+ raise Exception("Missing network block in configuration data")
+ if "ssid=410a420d430044" not in data:
+ raise Exception("Unexpected ssid parameter value")
+
+ finally:
+ try:
+ os.remove(config)
+ except:
+ pass
+ try:
+ os.remove(config + ".tmp")
+ except:
+ pass
+ try:
+ os.rmdir(config)
+ except:
+ pass
+
+def test_wpas_config_file_set_psk(dev):
+ """wpa_supplicant config file parsing/writing with arbitrary PSK value"""
+ config = "/tmp/test_wpas_config_file.conf"
+ if os.path.exists(config):
+ os.remove(config)
+
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+
+ try:
+ with open(config, "w") as f:
+ f.write("update_config=1\n")
+
+ wpas.interface_add("wlan5", config=config)
+
+ id = wpas.add_network()
+ wpas.set_network_quoted(id, "ssid", "foo")
+ if "OK" in wpas.request('SET_NETWORK %d psk "12345678"\n}\nmodel_name=foobar\nnetwork={\n#\"' % id):
+ raise Exception("Invalid psk value accepted")
+
+ if "OK" not in wpas.request("SAVE_CONFIG"):
+ raise Exception("Failed to save configuration file")
+
+ with open(config, "r") as f:
+ data = f.read()
+ logger.info("Configuration file contents: " + data)
+ if "model_name" in data:
+ raise Exception("Unexpected parameter added to configuration")
+
+ wpas.interface_remove("wlan5")
+ wpas.interface_add("wlan5", config=config)
+
+ finally:
+ try:
+ os.remove(config)
+ except:
+ pass
+ try:
+ os.remove(config + ".tmp")
+ except:
+ pass
+ try:
+ os.rmdir(config)
+ except:
+ pass
+
+def test_wpas_config_file_set_cred(dev):
+ """wpa_supplicant config file parsing/writing with arbitrary cred values"""
+ config = "/tmp/test_wpas_config_file.conf"
+ if os.path.exists(config):
+ os.remove(config)
+
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+
+ try:
+ with open(config, "w") as f:
+ f.write("update_config=1\n")
+
+ wpas.interface_add("wlan5", config=config)
+
+ id = wpas.add_cred()
+ wpas.set_cred_quoted(id, "username", "hello")
+ fields = [ "username", "milenage", "imsi", "password", "realm",
+ "phase1", "phase2", "provisioning_sp" ]
+ for field in fields:
+ if "FAIL" not in wpas.request('SET_CRED %d %s "hello"\n}\nmodel_name=foobar\ncred={\n#\"' % (id, field)):
+ raise Exception("Invalid %s value accepted" % field)
+
+ if "OK" not in wpas.request("SAVE_CONFIG"):
+ raise Exception("Failed to save configuration file")
+
+ with open(config, "r") as f:
+ data = f.read()
+ logger.info("Configuration file contents: " + data)
+ if "model_name" in data:
+ raise Exception("Unexpected parameter added to configuration")
+
+ wpas.interface_remove("wlan5")
+ wpas.interface_add("wlan5", config=config)
+
+ finally:
+ try:
+ os.remove(config)
+ except:
+ pass
+ try:
+ os.remove(config + ".tmp")
+ except:
+ pass
+ try:
+ os.rmdir(config)
+ except:
+ pass
+
+def test_wpas_config_file_set_global(dev):
+ """wpa_supplicant config file parsing/writing with arbitrary global values"""
+ config = "/tmp/test_wpas_config_file.conf"
+ if os.path.exists(config):
+ os.remove(config)
+
+ wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+
+ try:
+ with open(config, "w") as f:
+ f.write("update_config=1\n")
+
+ wpas.interface_add("wlan5", config=config)
+
+ fields = [ "model_name", "device_name", "ctrl_interface_group",
+ "opensc_engine_path", "pkcs11_engine_path",
+ "pkcs11_module_path", "openssl_ciphers", "pcsc_reader",
+ "pcsc_pin", "driver_param", "manufacturer", "model_name",
+ "model_number", "serial_number", "config_methods",
+ "p2p_ssid_postfix", "autoscan", "ext_password_backend",
+ "osu_dir", "wowlan_triggers", "fst_group_id",
+ "sched_scan_plans", "non_pref_chan" ]
+ for field in fields:
+ if "FAIL" not in wpas.request('SET %s hello\nmodel_name=foobar' % field):
+ raise Exception("Invalid %s value accepted" % field)
+
+ if "OK" not in wpas.request("SAVE_CONFIG"):
+ raise Exception("Failed to save configuration file")
+
+ with open(config, "r") as f:
+ data = f.read()
+ logger.info("Configuration file contents: " + data)
+ if "model_name" in data:
+ raise Exception("Unexpected parameter added to configuration")
+
+ wpas.interface_remove("wlan5")
+ wpas.interface_add("wlan5", config=config)
+
+ finally:
+ try:
+ os.remove(config)
+ except:
+ pass
+ try:
+ os.remove(config + ".tmp")
+ except:
+ pass
+ try:
+ os.rmdir(config)
+ except:
+ pass
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import logging
logger = logging.getLogger()
import os
import hwsim_utils
from hwsim import HWSimRadio
from wpasupplicant import WpaSupplicant
-from utils import alloc_fail
+from utils import alloc_fail, fail_test
+from test_wpas_ap import wait_ap_ready
+@remote_compatible
def test_wpas_ctrl_network(dev):
"""wpa_supplicant ctrl_iface network set/get"""
id = dev[0].add_network()
if "FAIL" not in dev[0].request("GET_NETWORK " + str(id + 1) + " proto"):
raise Exception("Unexpected success for invalid network id")
- tests = (("key_mgmt", "WPA-PSK WPA-EAP IEEE8021X NONE WPA-NONE FT-PSK FT-EAP WPA-PSK-SHA256 WPA-EAP-SHA256"),
+ if "OK" not in dev[0].request("SET_NETWORK " + str(id) + " proto \t WPA2 "):
+ raise Exception("Unexpected failure for SET_NETWORK proto")
+ res = dev[0].request("GET_NETWORK " + str(id) + " proto")
+ if res != "RSN":
+ raise Exception("Unexpected SET_NETWORK/GET_NETWORK conversion for proto: " + res)
+
+ if "OK" not in dev[0].request("SET_NETWORK " + str(id) + " key_mgmt \t WPA-PSK "):
+ raise Exception("Unexpected success for SET_NETWORK key_mgmt")
+ res = dev[0].request("GET_NETWORK " + str(id) + " key_mgmt")
+ if res != "WPA-PSK":
+ raise Exception("Unexpected SET_NETWORK/GET_NETWORK conversion for key_mgmt: " + res)
+
+ if "OK" not in dev[0].request("SET_NETWORK " + str(id) + " auth_alg \t OPEN "):
+ raise Exception("Unexpected failure for SET_NETWORK auth_alg")
+ res = dev[0].request("GET_NETWORK " + str(id) + " auth_alg")
+ if res != "OPEN":
+ raise Exception("Unexpected SET_NETWORK/GET_NETWORK conversion for auth_alg: " + res)
+
+ if "OK" not in dev[0].request("SET_NETWORK " + str(id) + " eap \t TLS "):
+ raise Exception("Unexpected failure for SET_NETWORK eap")
+ res = dev[0].request("GET_NETWORK " + str(id) + " eap")
+ if res != "TLS":
+ raise Exception("Unexpected SET_NETWORK/GET_NETWORK conversion for eap: " + res)
+
+ tests = ("bssid foo", "key_mgmt foo", "key_mgmt ", "group NONE")
+ for t in tests:
+ if "FAIL" not in dev[0].request("SET_NETWORK " + str(id) + " " + t):
+ raise Exception("Unexpected success for invalid SET_NETWORK: " + t)
+
+ tests = [("key_mgmt", "WPA-PSK WPA-EAP IEEE8021X NONE WPA-NONE FT-PSK FT-EAP WPA-PSK-SHA256 WPA-EAP-SHA256"),
("pairwise", "CCMP-256 GCMP-256 CCMP GCMP TKIP"),
("group", "CCMP-256 GCMP-256 CCMP GCMP TKIP"),
("auth_alg", "OPEN SHARED LEAP"),
("proto", "WPA RSN OSEN"),
("eap", "TLS"),
("go_p2p_dev_addr", "22:33:44:55:66:aa"),
- ("p2p_client_list", "22:33:44:55:66:bb 02:11:22:33:44:55"))
+ ("p2p_client_list", "22:33:44:55:66:bb 02:11:22:33:44:55")]
+ if "SAE" not in dev[0].get_capability("auth_alg"):
+ tests.append(("key_mgmt", "WPS OSEN"))
+ else:
+ tests.append(("key_mgmt", "WPS SAE FT-SAE OSEN"))
dev[0].set_network_quoted(id, "ssid", "test")
for field, value in tests:
if res != value:
raise Exception("Unexpected response for '" + field + "': '" + res + "'")
+ try:
+ value = "WPA-EAP-SUITE-B WPA-EAP-SUITE-B-192"
+ dev[0].set_network(id, "key_mgmt", value)
+ res = dev[0].get_network(id, "key_mgmt")
+ if res != value:
+ raise Exception("Unexpected response for key_mgmt")
+ except Exception, e:
+ if str(e).startswith("Unexpected"):
+ raise
+ else:
+ pass
+
q_tests = (("identity", "hello"),
("anonymous_identity", "foo@nowhere.com"))
for field, value in q_tests:
raise Exception("Too short PSK accepted")
if "FAIL" not in dev[0].request('SET_NETWORK ' + str(id) + ' psk "1234567890123456789012345678901234567890123456789012345678901234"'):
raise Exception("Too long PSK accepted")
- dev[0].set_network_quoted(id, "psk", "123456768");
- dev[0].set_network_quoted(id, "psk", "123456789012345678901234567890123456789012345678901234567890123");
+ dev[0].set_network_quoted(id, "psk", "123456768")
+ dev[0].set_network_quoted(id, "psk", "123456789012345678901234567890123456789012345678901234567890123")
if dev[0].get_network(id, "psk") != '*':
- raise Exception("Unexpected psk read result");
+ raise Exception("Unexpected psk read result")
if "FAIL" not in dev[0].request('SET_NETWORK ' + str(id) + ' eap UNKNOWN'):
raise Exception("Unknown EAP method accepted")
if "FAIL" not in dev[0].request("SET_NETWORK %d bssid_blacklist %s" % (id, val)):
raise Exception("Invalid bssid_blacklist value accepted")
+@remote_compatible
def test_wpas_ctrl_network_oom(dev):
"""wpa_supplicant ctrl_iface network OOM in string parsing"""
id = dev[0].add_network()
if "FAIL" not in dev[0].request("SET_NETWORK " + str(id) + ' ssid ' + val):
raise Exception("Unexpected success for SET_NETWORK during OOM")
+@remote_compatible
def test_wpas_ctrl_many_networks(dev, apdev):
"""wpa_supplicant ctrl_iface LIST_NETWORKS with huge number of networks"""
for i in range(1000):
# with the test case failing and following reset operation timing out.
dev[0].request("REMOVE_NETWORK all", timeout=60)
+@remote_compatible
def test_wpas_ctrl_dup_network(dev, apdev):
"""wpa_supplicant ctrl_iface DUP_NETWORK"""
ssid = "target"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
src = dev[0].connect("another", psk=passphrase, scan_freq="2412",
only_add_network=True)
if "OK" not in dev[0].request("DUP_NETWORK %d %d ssid" % (id, id)):
raise Exception("Unexpected DUP_NETWORK failure")
+@remote_compatible
def test_wpas_ctrl_dup_network_global(dev, apdev):
"""wpa_supplicant ctrl_iface DUP_NETWORK (global)"""
ssid = "target"
passphrase = 'qwertyuiop'
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
src = dev[0].connect("another", psk=passphrase, scan_freq="2412",
only_add_network=True)
if " " + str(id) not in ev:
raise Exception("CRED-REMOVED event without matching id")
+@remote_compatible
def test_wpas_ctrl_cred(dev):
"""wpa_supplicant ctrl_iface cred set"""
id1 = add_cred(dev[0])
set_cred(dev[0], id, "temporary", "1")
set_cred(dev[0], id, "priority", "1")
set_cred(dev[0], id, "pcsc", "1")
+ set_cred(dev[0], id, "sim_num", "0")
set_cred_quoted(dev[0], id, "private_key_passwd", "test")
set_cred_quoted(dev[0], id, "domain_suffix_match", "test")
set_cred_quoted(dev[0], id, "phase1", "test")
if "FAIL" not in dev[0].request("SET_CRED " + str(id) + " foo 4142"):
raise Exception("Unexpected success on unknown field")
+ tests = ["sp_priority 256",
+ 'roaming_partner "example.org"',
+ 'roaming_partner "' + 200*'a' + '.example.org,"',
+ 'roaming_partner "example.org,1"',
+ 'roaming_partner "example.org,1,2"',
+ 'roaming_partner "example.org,1,2,ABC"' ]
+ for t in tests:
+ if "FAIL" not in dev[0].request("SET_CRED " + str(id) + " " + t):
+ raise Exception("Unexpected success on invalid SET_CRED value: " + t)
+
id3 = add_cred(dev[0])
id4 = add_cred(dev[0])
if len(dev[0].request("LIST_CREDS").splitlines()) != 6:
if "FAIL" in dev[0].request("SET pno 0"):
raise Exception("Unexpected failure in disabling PNO")
+@remote_compatible
def test_wpas_ctrl_get(dev):
"""wpa_supplicant ctrl_iface get"""
if "FAIL" in dev[0].request("GET version"):
if "FAIL" not in dev[0].request("GET foo"):
raise Exception("Unexpected success on get command")
+@remote_compatible
def test_wpas_ctrl_preauth(dev):
"""wpa_supplicant ctrl_iface preauth"""
if "FAIL" not in dev[0].request("PREAUTH "):
if "FAIL" in dev[0].request("PREAUTH 00:11:22:33:44:55"):
raise Exception("Unexpected failure on PREAUTH")
+@remote_compatible
def test_wpas_ctrl_stkstart(dev):
"""wpa_supplicant ctrl_iface strkstart"""
if "FAIL" not in dev[0].request("STKSTART "):
if "FAIL" not in dev[0].request("STKSTART 00:11:22:33:44:55"):
raise Exception("Unexpected success on STKSTART")
+@remote_compatible
def test_wpas_ctrl_tdls_discover(dev):
"""wpa_supplicant ctrl_iface tdls_discover"""
if "FAIL" not in dev[0].request("TDLS_DISCOVER "):
if "FAIL" not in dev[0].request("TDLS_DISCOVER 00:11:22:33:44:55"):
raise Exception("Unexpected success on TDLS_DISCOVER")
+@remote_compatible
def test_wpas_ctrl_tdls_chan_switch(dev):
"""wpa_supplicant ctrl_iface tdls_chan_switch error cases"""
for args in [ '', '00:11:22:33:44:55' ]:
if "FAIL" not in dev[0].request("TDLS_CHAN_SWITCH " + args):
raise Exception("Unexpected success on invalid TDLS_CHAN_SWITCH: " + args)
+@remote_compatible
def test_wpas_ctrl_addr(dev):
"""wpa_supplicant ctrl_iface invalid address"""
if "FAIL" not in dev[0].request("TDLS_SETUP "):
if "FAIL" not in dev[0].request("BLACKLIST 00:11:22:33:44"):
raise Exception("Unexpected success on invalid BLACKLIST")
+@remote_compatible
def test_wpas_ctrl_wps_errors(dev):
"""wpa_supplicant ctrl_iface WPS error cases"""
if "FAIL" not in dev[0].request("WPS_REG 00:11:22:33:44:55"):
if "FAIL" not in dev[0].request("WPS_NFC_TOKEN FOO"):
raise Exception("Unexpected success on invalid WPS_NFC_TOKEN")
+@remote_compatible
def test_wpas_ctrl_config_parser(dev):
"""wpa_supplicant ctrl_iface SET config parser"""
if "FAIL" not in dev[0].request("SET pbc_in_m1 qwerty"):
if "FAIL" not in dev[0].request("SET serial_number 0123456789abcdef0123456789abcdef0"):
raise Exception("Too long string accepted")
+@remote_compatible
def test_wpas_ctrl_mib(dev):
"""wpa_supplicant ctrl_iface MIB"""
mib = dev[0].get_mib()
def test_wpas_ctrl_set_wps_params(dev):
"""wpa_supplicant ctrl_iface SET config_methods"""
+ try:
+ _test_wpas_ctrl_set_wps_params(dev)
+ finally:
+ dev[2].request("SET config_methods ")
+
+def _test_wpas_ctrl_set_wps_params(dev):
ts = [ "config_methods label virtual_display virtual_push_button keypad",
"device_type 1-0050F204-1",
"os_version 01020300",
if "OK" not in dev[2].request("SET bssid_filter " + apdev[0]['bssid']):
raise Exception("Failed to set bssid_filter")
params = { "ssid": "test" }
- hostapd.add_ap(apdev[0]['ifname'], params)
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
+ hostapd.add_ap(apdev[1], params)
dev[2].scan_for_bss(apdev[0]['bssid'], freq="2412")
dev[2].scan(freq="2412")
bss = dev[2].get_bss(apdev[0]['bssid'])
finally:
dev[2].request("SET bssid_filter ")
+@remote_compatible
def test_wpas_ctrl_disallow_aps(dev, apdev):
"""wpa_supplicant ctrl_iface disallow_aps"""
params = { "ssid": "test" }
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
if "FAIL" not in dev[0].request("SET disallow_aps bssid "):
raise Exception("Unexpected success on invalid disallow_aps")
raise Exception("Unexpected success on invalid disallow_aps")
dev[0].connect("test", key_mgmt="NONE", scan_freq="2412")
- hostapd.add_ap(apdev[1]['ifname'], params)
+ hostapd.add_ap(apdev[1], params)
dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
dev[0].dump_monitor()
if "OK" not in dev[0].request("SET disallow_aps bssid 00:11:22:33:44:55 bssid 00:22:33:44:55:66"):
if "OK" not in dev[0].request("SET disallow_aps "):
raise Exception("Failed to set disallow_aps")
+@remote_compatible
def test_wpas_ctrl_blob(dev):
"""wpa_supplicant ctrl_iface SET blob"""
if "FAIL" not in dev[0].request("SET blob foo"):
if "OK" not in dev[0].request("SET blob foo 0011"):
raise Exception("Unexpected SET failure")
+@remote_compatible
def test_wpas_ctrl_set_uapsd(dev):
"""wpa_supplicant ctrl_iface SET uapsd"""
if "FAIL" not in dev[0].request("SET uapsd foo"):
"dot11RSNAConfigPMKReauthThreshold 101",
"dot11RSNAConfigSATimeout 0",
"wps_version_number -1",
- "wps_version_number 256" ]
+ "wps_version_number 256",
+ "fst_group_id ",
+ "fst_llt 0"]
for val in vals:
if "FAIL" not in dev[0].request("SET " + val):
raise Exception("Unexpected SET success for " + val)
if "OK" not in dev[0].request("SET " + val):
raise Exception("Unexpected SET failure for " + val)
+ # This fails if wpa_supplicant is built with loadable EAP peer method
+ # support due to missing file and succeeds if no support for loadable
+ # methods is included, so don't check the return value for now.
+ dev[0].request("SET load_dynamic_eap /tmp/hwsim-eap-not-found.so")
+
+@remote_compatible
def test_wpas_ctrl_get_capability(dev):
"""wpa_supplicant ctrl_iface GET_CAPABILITY"""
if "FAIL" not in dev[0].request("GET_CAPABILITY 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"):
if dev[0].get_capability("foo") is not None:
raise Exception("Unexpected GET_CAPABILITY foo response: " + str(res))
+@remote_compatible
def test_wpas_ctrl_nfc_report_handover(dev):
"""wpa_supplicant ctrl_iface NFC_REPORT_HANDOVER"""
vals = [ "FOO",
if "FAIL" not in dev[0].request("NFC_REPORT_HANDOVER " + v):
raise Exception("Unexpected NFC_REPORT_HANDOVER success for " + v)
+@remote_compatible
def test_wpas_ctrl_nfc_tag_read(dev):
"""wpa_supplicant ctrl_iface WPS_NFC_TAG_READ"""
vals = [ "FOO", "0Q", "00", "000000", "10000001", "10000000", "00000000",
if "FAIL" not in dev[0].request("WPS_NFC_TAG_READ " + v):
raise Exception("Unexpected WPS_NFC_TAG_READ success for " + v)
+@remote_compatible
def test_wpas_ctrl_nfc_get_handover(dev):
"""wpa_supplicant ctrl_iface NFC_GET_HANDOVER"""
vals = [ "FOO", "FOO BAR", "WPS WPS", "WPS WPS-CR", "WPS FOO", "NDEF P2P" ]
def get_blacklist(dev):
return dev.request("BLACKLIST").splitlines()
+@remote_compatible
def test_wpas_ctrl_blacklist(dev):
"""wpa_supplicant ctrl_iface BLACKLIST"""
if "OK" not in dev[0].request("BLACKLIST clear"):
if dev[0].request("BLACKLIST") != "":
raise Exception("Unexpected blacklist contents")
+@remote_compatible
def test_wpas_ctrl_blacklist_oom(dev):
"""wpa_supplicant ctrl_iface BLACKLIST and out-of-memory"""
with alloc_fail(dev[0], 1, "wpa_blacklist_add"):
if "Timestamp: 1" not in level:
raise Exception("Unexpected timestamp(3): " + level)
+@remote_compatible
def test_wpas_ctrl_enable_disable_network(dev, apdev):
"""wpa_supplicant ctrl_iface ENABLE/DISABLE_NETWORK"""
params = { "ssid": "test" }
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
id = dev[0].connect("test", key_mgmt="NONE", scan_freq="2412",
only_add_network=True)
ev = dev[0].wait_global_event(["CTRL-EVENT-REGDOM-CHANGE"], 10)
if ev is None:
raise Exception("regdom change event not seen")
- if "init=CORE type=WORLD" not in ev:
+ # init=CORE was previously used due to invalid db.txt data for 00. For
+ # now, allow both it and the new init=USER after fixed db.txt.
+ if "init=CORE type=WORLD" not in ev and "init=USER type=WORLD" not in ev:
raise Exception("Unexpected event contents: " + ev)
finally:
subprocess.call(['iw', 'reg', 'set', '00'])
raise Exception("INTERFACE_ADD succeeded unexpectedly")
if "FAIL" not in wpas.global_request("INTERFACE_ADD FOO "):
raise Exception("INTERFACE_ADD succeeded unexpectedly")
+ if "FAIL" not in wpas.global_request("INTERFACE_ADD FOO conf driver ctrliface driverparam bridge create abcd"):
+ raise Exception("INTERFACE_ADD succeeded unexpectedly")
+@remote_compatible
def test_wpas_ctrl_roam(dev, apdev):
"""wpa_supplicant ctrl_iface ROAM error cases"""
if "FAIL" not in dev[0].request("ROAM 00:11:22:33:44"):
if "FAIL" not in dev[0].request("ROAM 00:11:22:33:44:55"):
raise Exception("Unexpected success")
params = { "ssid": "test" }
- hostapd.add_ap(apdev[0]['ifname'], params)
+ hostapd.add_ap(apdev[0], params)
id = dev[0].connect("test", key_mgmt="NONE", scan_freq="2412")
if "FAIL" not in dev[0].request("ROAM 00:11:22:33:44:55"):
raise Exception("Unexpected success")
+@remote_compatible
def test_wpas_ctrl_ipaddr(dev, apdev):
"""wpa_supplicant IP address in STATUS"""
try:
- subprocess.call(['ip', 'addr', 'add', '10.174.65.207/32', 'dev',
- dev[0].ifname])
+ dev[0].cmd_execute(['ip', 'addr', 'add', '10.174.65.207/32', 'dev',
+ dev[0].ifname])
ipaddr = dev[0].get_status_field('ip_address')
if ipaddr != '10.174.65.207':
raise Exception("IP address not in STATUS output")
finally:
- subprocess.call(['ip', 'addr', 'del', '10.174.65.207/32', 'dev',
- dev[0].ifname])
-
-def test_wpas_ctrl_neighbor_rep_req(dev, apdev):
- """wpa_supplicant ctrl_iface NEIGHBOR_REP_REQUEST"""
- params = { "ssid": "test" }
- hostapd.add_ap(apdev[0]['ifname'], params)
- params = { "ssid": "test2", "radio_measurements": "1" }
- hostapd.add_ap(apdev[1]['ifname'], params)
-
- dev[0].connect("test", key_mgmt="NONE", scan_freq="2412")
- if "FAIL" not in dev[0].request("NEIGHBOR_REP_REQUEST"):
- raise Exception("Request succeeded unexpectedly")
- if "FAIL" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=abcdef"):
- raise Exception("Request succeeded unexpectedly")
- dev[0].request("DISCONNECT")
-
- rrm = int(dev[0].get_driver_status_field("capa.rrm_flags"), 16)
- if rrm & 0x5 != 0x5:
- logger.info("Driver does not support required RRM capabilities - skip rest of the test case")
- return
-
- dev[0].connect("test2", key_mgmt="NONE", scan_freq="2412")
-
- # These requests are expected to get sent properly, but since hostapd does
- # not yet support processing of the request, these are expected to fail.
-
- if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST"):
- raise Exception("Request failed")
- ev = dev[0].wait_event([ "RRM-NEIGHBOR-REP-RECEIVED",
- "RRM-NEIGHBOR-REP-REQUEST-FAILED" ], timeout=10)
- if ev is None:
- raise Exception("RRM report result not indicated")
- logger.info("RRM result: " + ev)
-
- if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=abcdef"):
- raise Exception("Request failed")
- ev = dev[0].wait_event([ "RRM-NEIGHBOR-REP-RECEIVED",
- "RRM-NEIGHBOR-REP-REQUEST-FAILED" ], timeout=10)
- if ev is None:
- raise Exception("RRM report result not indicated")
- logger.info("RRM result: " + ev)
+ dev[0].cmd_execute(['ip', 'addr', 'del', '10.174.65.207/32', 'dev',
+ dev[0].ifname])
+@remote_compatible
def test_wpas_ctrl_rsp(dev, apdev):
"""wpa_supplicant ctrl_iface CTRL-RSP-"""
if "FAIL" not in dev[0].request("CTRL-RSP-"):
if "OK" not in dev[0].request("CTRL-RSP-%s-%d:" % (req, id)):
raise Exception("Request failed unexpectedly")
+@remote_compatible
def test_wpas_ctrl_vendor(dev, apdev):
"""wpa_supplicant ctrl_iface VENDOR"""
cmds = [ "foo",
if "FAIL" not in dev[0].request("VENDOR " + cmd):
raise Exception("Invalid VENDOR command accepted: " + cmd)
+@remote_compatible
def test_wpas_ctrl_mgmt_tx(dev, apdev):
"""wpa_supplicant ctrl_iface MGMT_TX"""
cmds = [ "foo",
if "OK" not in dev[0].request("MGMT_TX_DONE"):
raise Exception("MGMT_TX_DONE failed")
+@remote_compatible
def test_wpas_ctrl_driver_event(dev, apdev):
"""wpa_supplicant ctrl_iface DRIVER_EVENT"""
if "FAIL" not in dev[0].request("DRIVER_EVENT foo"):
raise Exception("Invalid DRIVER_EVENT accepted")
+@remote_compatible
def test_wpas_ctrl_eapol_rx(dev, apdev):
"""wpa_supplicant ctrl_iface EAPOL_RX"""
cmds = [ "foo",
if "FAIL" not in dev[0].request("EAPOL_RX " + cmd):
raise Exception("Invalid EAPOL_RX command accepted: " + cmd)
+@remote_compatible
def test_wpas_ctrl_data_test(dev, apdev):
"""wpa_supplicant ctrl_iface DATA_TEST"""
dev[0].request("DATA_TEST_CONFIG 0")
if "OK" not in dev[0].request("DATA_TEST_FRAME 00112233445566778899aabbccddee"):
raise Exception("DATA_TEST_FRAME failed")
+@remote_compatible
def test_wpas_ctrl_vendor_elem(dev, apdev):
"""wpa_supplicant ctrl_iface VENDOR_ELEM"""
if "OK" not in dev[0].request("VENDOR_ELEM_ADD 1 "):
if "FAIL" not in dev[0].global_request("SET foo"):
raise Exception("Invalid global SET accepted")
+@remote_compatible
def test_wpas_ctrl_dump(dev, apdev):
"""wpa_supplicant ctrl_iface and DUMP/GET global parameters"""
vals = dev[0].get_config()
def test_wpas_ctrl_interface_add(dev, apdev):
"""wpa_supplicant INTERFACE_ADD/REMOVE with vif creation/removal"""
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
hwsim_utils.test_connectivity(dev[0], hapd)
dev[0].global_request("INTERFACE_REMOVE " + ifname)
hwsim_utils.test_connectivity(dev[0], hapd)
+def test_wpas_ctrl_interface_add_sta(dev, apdev):
+ """wpa_supplicant INTERFACE_ADD/REMOVE with STA vif creation/removal"""
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
+ ifname = "test-" + dev[0].ifname
+ dev[0].interface_add(ifname, create=True, if_type='sta')
+ wpas = WpaSupplicant(ifname=ifname)
+ wpas.connect("open", key_mgmt="NONE", scan_freq="2412")
+ wpas.request("DISCONNECT")
+ wpas.wait_disconnected()
+ dev[0].global_request("INTERFACE_REMOVE " + ifname)
+
+def test_wpas_ctrl_interface_add_ap(dev, apdev):
+ """wpa_supplicant INTERFACE_ADD/REMOVE AP interface"""
+ with HWSimRadio() as (radio, iface):
+ wpas0 = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
+ wpas0.interface_add(iface)
+
+ ifname = "test-wpas-ap"
+ wpas0.interface_add(ifname, create=True, if_type='ap')
+ wpas = WpaSupplicant(ifname=ifname)
+
+ id = wpas.add_network()
+ wpas.set_network(id, "mode", "2")
+ wpas.set_network_quoted(id, "ssid", "wpas-ap-open")
+ wpas.set_network(id, "key_mgmt", "NONE")
+ wpas.set_network(id, "frequency", "2412")
+ wpas.set_network(id, "scan_freq", "2412")
+ wpas.select_network(id)
+ wait_ap_ready(wpas)
+
+ dev[1].connect("wpas-ap-open", key_mgmt="NONE", scan_freq="2412")
+ dev[2].connect("wpas-ap-open", key_mgmt="NONE", scan_freq="2412")
+
+ hwsim_utils.test_connectivity(wpas, dev[1])
+ hwsim_utils.test_connectivity(dev[1], dev[2])
+
+ dev[1].request("DISCONNECT")
+ dev[2].request("DISCONNECT")
+ dev[1].wait_disconnected()
+ dev[2].wait_disconnected()
+ wpas0.global_request("INTERFACE_REMOVE " + ifname)
+
def test_wpas_ctrl_interface_add_many(dev, apdev):
"""wpa_supplicant INTERFACE_ADD/REMOVE with vif creation/removal (many)"""
try:
dev[0].global_request("INTERFACE_REMOVE " + ifname)
def _test_wpas_ctrl_interface_add_many(dev, apdev):
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
hwsim_utils.test_connectivity(dev[0], hapd)
+ dev[0].dump_monitor()
l = []
for i in range(10):
dev[0].interface_add(ifname, create=True)
wpas = WpaSupplicant(ifname=ifname)
wpas.connect("open", key_mgmt="NONE", scan_freq="2412")
+ wpas.dump_monitor()
l.append(wpas)
+ dev[0].dump_monitor()
for wpas in l:
+ wpas.dump_monitor()
hwsim_utils.test_connectivity(wpas, hapd)
+ wpas.dump_monitor()
+ dev[0].dump_monitor()
def test_wpas_ctrl_interface_add2(dev, apdev):
"""wpa_supplicant INTERFACE_ADD/REMOVE with vif without creation/removal"""
subprocess.call(['iw', 'dev', ifname, 'del'])
def _test_wpas_ctrl_interface_add2(dev, apdev, ifname):
- hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
hwsim_utils.test_connectivity(dev[0], hapd)
subprocess.call(['iw', 'dev', dev[0].ifname, 'interface', 'add', ifname,
'type', 'station'])
+ subprocess.call(['ip', 'link', 'set', 'dev', ifname, 'address',
+ '02:01:00:00:02:01'])
dev[0].interface_add(ifname, set_ifname=False, all_params=True)
wpas = WpaSupplicant(ifname=ifname)
wpas.connect("open", key_mgmt="NONE", scan_freq="2412")
if os.path.exists(pidfile):
raise Exception("PID file not removed")
+@remote_compatible
def test_wpas_ctrl_oom(dev):
"""Various wpa_supplicant ctrl_iface OOM cases"""
try:
3, 'wpa_supplicant_ctrl_iface_wps_nfc_token'),
('WPS_NFC_TOKEN NDEF', 'FAIL',
4, 'wpa_supplicant_ctrl_iface_wps_nfc_token'),
- ('WPS_NFC_TOKEN NDEF', 'FAIL',
- 5, 'wpa_supplicant_ctrl_iface_wps_nfc_token'),
('NFC_REPORT_HANDOVER ROLE TYPE 00 00', 'FAIL',
1, 'wpas_ctrl_nfc_report_handover'),
('NFC_REPORT_HANDOVER ROLE TYPE 00 00', 'FAIL',
1, 'ndef_build_record'),
('NFC_GET_HANDOVER_REQ NDEF P2P-CR', None,
1, 'wpas_p2p_nfc_handover'),
- ('NFC_GET_HANDOVER_REQ NDEF P2P-CR', 'FAIL',
- 2, 'wpas_p2p_nfc_handover'),
('NFC_GET_HANDOVER_REQ NDEF P2P-CR', None,
1, 'wps_build_nfc_handover_req_p2p'),
('NFC_GET_HANDOVER_REQ NDEF P2P-CR', 'FAIL',
1, 'wpas_ctrl_nfc_get_handover_sel_p2p'),
('NFC_GET_HANDOVER_SEL NDEF P2P-CR', None,
1, 'wpas_ctrl_nfc_get_handover_sel_p2p'),
- ('NFC_GET_HANDOVER_SEL NDEF P2P-CR-TAG', 'FAIL',
- 2, 'wpas_ctrl_nfc_get_handover_sel_p2p'),
- ('NFC_GET_HANDOVER_SEL NDEF P2P-CR', 'FAIL',
- 2, 'wpas_ctrl_nfc_get_handover_sel_p2p'),
- ('NFC_GET_HANDOVER_SEL NDEF P2P-CR-TAG', 'FAIL',
- 3, 'wpas_ctrl_nfc_get_handover_sel_p2p'),
- ('NFC_GET_HANDOVER_SEL NDEF P2P-CR', 'FAIL',
- 3, 'wpas_ctrl_nfc_get_handover_sel_p2p'),
- ('NFC_GET_HANDOVER_SEL NDEF P2P-CR-TAG', 'FAIL',
- 4, 'wpas_ctrl_nfc_get_handover_sel_p2p'),
- ('NFC_GET_HANDOVER_SEL NDEF P2P-CR', 'FAIL',
- 4, 'wpas_ctrl_nfc_get_handover_sel_p2p'),
('P2P_ASP_PROVISION_RESP 00:11:22:33:44:55 id=1', 'FAIL',
1, 'p2p_parse_asp_provision_cmd'),
('P2P_SERV_DISC_REQ 00:11:22:33:44:55 02000001', 'FAIL',
1, 'wpa_supplicant_ctrl_iface_autoscan'),
('PING', None,
1, 'wpa_supplicant_ctrl_iface_process') ]
+ tls = dev[0].request("GET tls_library")
+ if not tls.startswith("internal"):
+ tests.append(('NFC_GET_HANDOVER_SEL NDEF P2P-CR-TAG', 'FAIL',
+ 4, 'wpas_ctrl_nfc_get_handover_sel_p2p'))
for cmd,exp,count,func in tests:
with alloc_fail(dev[0], count, func):
res = dev[0].request(cmd)
if exp and exp not in res:
- raise Exception("Unexpected success for '%s' during OOM" % cmd)
+ raise Exception("Unexpected success for '%s' during OOM (%d:%s)" % (cmd, count, func))
tests = [ ('FOO', None,
1, 'wpa_supplicant_global_ctrl_iface_process'),
if exp and exp not in res:
raise Exception("Unexpected success for '%s' during OOM" % cmd)
+@remote_compatible
+def test_wpas_ctrl_error(dev):
+ """Various wpa_supplicant ctrl_iface error cases"""
+ tests = [ ('WPS_NFC_TOKEN NDEF', 'FAIL',
+ 1, 'wpa_supplicant_ctrl_iface_wps_nfc_token'),
+ ('WPS_NFC_TOKEN NDEF', 'FAIL',
+ 2, 'wpa_supplicant_ctrl_iface_wps_nfc_token'),
+ ('NFC_GET_HANDOVER_REQ NDEF P2P-CR', None,
+ 1, 'wpas_p2p_nfc_handover'),
+ ('NFC_GET_HANDOVER_REQ NDEF P2P-CR', None,
+ 1, 'wps_build_nfc_handover_req_p2p') ]
+ for cmd,exp,count,func in tests:
+ with fail_test(dev[0], count, func):
+ res = dev[0].request(cmd)
+ if exp and exp not in res:
+ raise Exception("Unexpected success for '%s' during failure testing (%d:%s)" % (cmd, count, func))
+
def test_wpas_ctrl_socket_full(dev, apdev, test_params):
"""wpa_supplicant control socket and full send buffer"""
if not dev[0].ping():
if not dev[0].ping():
raise Exception("Could not ping wpa_supplicant at the end of the test")
dev[0].get_status()
+
+def test_wpas_ctrl_event_burst(dev, apdev):
+ """wpa_supplicant control socket and event burst"""
+ if "OK" not in dev[0].request("EVENT_TEST 1000"):
+ raise Exception("Could not request event messages")
+
+ total_i = 0
+ total_g = 0
+ for i in range(100):
+ (i,g) = dev[0].dump_monitor()
+ total_i += i
+ total_g += g
+ logger.info("Received i=%d g=%d" % (i, g))
+ if total_i >= 1000 and total_g >= 1000:
+ break
+ time.sleep(0.05)
+
+ if total_i < 1000:
+ raise Exception("Some per-interface events not seen: %d" % total_i)
+ if total_g < 1000:
+ raise Exception("Some global events not seen: %d" % total_g)
+
+ if not dev[0].ping():
+ raise Exception("Could not ping wpa_supplicant at the end of the test")
+
+@remote_compatible
+def test_wpas_ctrl_sched_scan_plans(dev, apdev):
+ """wpa_supplicant sched_scan_plans parsing"""
+ dev[0].request("SET sched_scan_plans foo")
+ dev[0].request("SET sched_scan_plans 10:100 20:200 30")
+ with alloc_fail(dev[0], 1, "wpas_sched_scan_plans_set"):
+ dev[0].request("SET sched_scan_plans 10:100")
+ dev[0].request("SET sched_scan_plans 4294967295:0")
+ dev[0].request("SET sched_scan_plans 1 1")
+ dev[0].request("SET sched_scan_plans ")
+ dev[0].request("SET sched_scan_plans ")
+
+def test_wpas_ctrl_signal_monitor(dev, apdev):
+ """wpa_supplicant SIGNAL_MONITOR command"""
+ hapd = hostapd.add_ap(apdev[0], { "ssid": "open" })
+ dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
+ dev[1].connect("open", key_mgmt="NONE", scan_freq="2412",
+ bgscan="simple:1:-45:2")
+ dev[2].connect("open", key_mgmt="NONE", scan_freq="2412")
+
+ tests = [ " THRESHOLD=-45", " THRESHOLD=-44 HYSTERESIS=5", "" ]
+ try:
+ if "FAIL" in dev[2].request("SIGNAL_MONITOR THRESHOLD=-1 HYSTERESIS=5"):
+ raise Exception("SIGNAL_MONITOR command failed")
+ for t in tests:
+ if "OK" not in dev[0].request("SIGNAL_MONITOR" + t):
+ raise Exception("SIGNAL_MONITOR command failed: " + t)
+ if "FAIL" not in dev[1].request("SIGNAL_MONITOR THRESHOLD=-44 HYSTERESIS=5"):
+ raise Exception("SIGNAL_MONITOR command accepted while using bgscan")
+ ev = dev[2].wait_event(["CTRL-EVENT-SIGNAL-CHANGE"], timeout=10)
+ if ev is None:
+ raise Exception("No signal change event seen")
+ if "above=0" not in ev:
+ raise Exception("Unexpected signal change event contents: " + ev)
+ finally:
+ dev[0].request("SIGNAL_MONITOR")
+ dev[1].request("SIGNAL_MONITOR")
+ dev[2].request("SIGNAL_MONITOR")
+
+ dev[0].request("REMOVE_NETWORK all")
+ dev[1].request("REMOVE_NETWORK all")
+ dev[1].wait_disconnected()
+
+def test_wpas_ctrl_p2p_listen_offload(dev, apdev):
+ """wpa_supplicant P2P_LO_START and P2P_LO_STOP commands"""
+ dev[0].request("P2P_LO_STOP")
+ dev[0].request("P2P_LO_START ")
+ dev[0].request("P2P_LO_START 2412")
+ dev[0].request("P2P_LO_START 2412 100 200 3")
+ dev[0].request("P2P_LO_STOP")
+
+def test_wpas_ctrl_driver_flags(dev, apdev):
+ """DRIVER_FLAGS command"""
+ params = hostapd.wpa2_params(ssid="test", passphrase="12345678")
+ hapd = hostapd.add_ap(apdev[0], params)
+ hapd_flags = hapd.request("DRIVER_FLAGS")
+ wpas_flags = dev[0].request("DRIVER_FLAGS")
+ if "FAIL" in hapd_flags:
+ raise Exception("DRIVER_FLAGS failed")
+ if hapd_flags != wpas_flags:
+ raise Exception("Unexpected difference in hostapd vs. wpa_supplicant DRIVER_FLAGS output")
+ logger.info("DRIVER_FLAGS: " + hapd_flags)
+ flags = hapd_flags.split('\n')
+ if 'AP' not in flags:
+ raise Exception("AP flag missing from DRIVER_FLAGS")
-#!/usr/bin/python
-#
# wpa_supplicant mesh mode tests
# Copyright (c) 2014, cozybit Inc.
#
import logging
logger = logging.getLogger()
+import os
+import struct
import subprocess
+import time
import hwsim_utils
+import hostapd
from wpasupplicant import WpaSupplicant
-from utils import HwsimSkip, alloc_fail
+from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger
+from tshark import run_tshark
def check_mesh_support(dev, secure=False):
if "MESH" not in dev.get_capability("modes"):
dev[0].set_network(id, "mode", "5")
dev[0].remove_network(id)
-def add_open_mesh_network(dev, freq="2412", start=True, beacon_int=0):
+def add_open_mesh_network(dev, freq="2412", start=True, beacon_int=0,
+ basic_rates=None, chwidth=0):
id = dev.add_network()
dev.set_network(id, "mode", "5")
dev.set_network_quoted(id, "ssid", "wpas-mesh-open")
dev.set_network(id, "key_mgmt", "NONE")
- dev.set_network(id, "frequency", freq)
+ if freq:
+ dev.set_network(id, "frequency", freq)
+ if chwidth > 0:
+ dev.set_network(id, "max_oper_chwidth", str(chwidth))
if beacon_int:
dev.set_network(id, "beacon_int", str(beacon_int))
+ if basic_rates:
+ dev.set_network(id, "mesh_basic_rates", basic_rates)
if start:
dev.mesh_group_add(id)
return id
def test_wpas_mesh_open(dev, apdev):
"""wpa_supplicant open MESH network connectivity"""
check_mesh_support(dev[0])
- add_open_mesh_network(dev[0], freq="2462")
- add_open_mesh_network(dev[1], freq="2462")
+ add_open_mesh_network(dev[0], freq="2462", basic_rates="60 120 240")
+ add_open_mesh_network(dev[1], freq="2462", basic_rates="60 120 240")
# Check for mesh joined
check_mesh_group_added(dev[0])
# Test connectivity 0->1 and 1->0
hwsim_utils.test_connectivity(dev[0], dev[1])
+ state = dev[0].get_status_field("wpa_state")
+ if state != "COMPLETED":
+ raise Exception("Unexpected wpa_state on dev0: " + state)
+ state = dev[1].get_status_field("wpa_state")
+ if state != "COMPLETED":
+ raise Exception("Unexpected wpa_state on dev1: " + state)
+
+ mode = dev[0].get_status_field("mode")
+ if mode != "mesh":
+ raise Exception("Unexpected mode: " + mode)
+
def test_wpas_mesh_open_no_auto(dev, apdev):
"""wpa_supplicant open MESH network connectivity"""
check_mesh_support(dev[0])
# Test connectivity 0->1 and 1->0
hwsim_utils.test_connectivity(dev[0], dev[1])
-def add_mesh_secure_net(dev, psk=True):
+def test_mesh_open_no_auto2(dev, apdev):
+ """Open mesh network connectivity, no_auto on both peers"""
+ check_mesh_support(dev[0])
+ id = add_open_mesh_network(dev[0], start=False)
+ dev[0].set_network(id, "no_auto_peer", "1")
+ dev[0].mesh_group_add(id)
+
+ id = add_open_mesh_network(dev[1], start=False)
+ dev[1].set_network(id, "no_auto_peer", "1")
+ dev[1].mesh_group_add(id)
+
+ check_mesh_group_added(dev[0])
+ check_mesh_group_added(dev[1])
+
+ ev = dev[0].wait_event(["will not initiate new peer link"], timeout=10)
+ if ev is None:
+ raise Exception("Missing no-initiate message")
+ addr1 = dev[1].own_addr()
+ if "OK" not in dev[0].request("MESH_PEER_ADD " + addr1):
+ raise Exception("MESH_PEER_ADD failed")
+ if "FAIL" not in dev[0].request("MESH_PEER_ADD ff:ff:ff:ff:ff:ff"):
+ raise Exception("MESH_PEER_ADD with unknown STA succeeded")
+ check_mesh_peer_connected(dev[0], timeout=30)
+ check_mesh_peer_connected(dev[1])
+ if "FAIL" not in dev[0].request("MESH_PEER_ADD " + addr1):
+ raise Exception("MESH_PEER_ADD succeeded for connected STA")
+ hwsim_utils.test_connectivity(dev[0], dev[1])
+
+def add_mesh_secure_net(dev, psk=True, pmf=False, pairwise=None, group=None):
id = dev.add_network()
dev.set_network(id, "mode", "5")
dev.set_network_quoted(id, "ssid", "wpas-mesh-sec")
dev.set_network(id, "frequency", "2412")
if psk:
dev.set_network_quoted(id, "psk", "thisismypassphrase!")
+ if pmf:
+ dev.set_network(id, "ieee80211w", "2")
+ if pairwise:
+ dev.set_network(id, "pairwise", pairwise)
+ if group:
+ dev.set_network(id, "group", group)
return id
def test_wpas_mesh_secure(dev, apdev):
# Test connectivity 0->1 and 1->0
hwsim_utils.test_connectivity(dev[0], dev[1])
+ state = dev[0].get_status_field("wpa_state")
+ if state != "COMPLETED":
+ raise Exception("Unexpected wpa_state on dev0: " + state)
+ state = dev[1].get_status_field("wpa_state")
+ if state != "COMPLETED":
+ raise Exception("Unexpected wpa_state on dev1: " + state)
+
+def test_mesh_secure_pmf(dev, apdev):
+ """Secure mesh network connectivity with PMF enabled"""
+ check_mesh_support(dev[0], secure=True)
+ dev[0].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[0], pmf=True)
+ dev[0].mesh_group_add(id)
+
+ dev[1].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[1], pmf=True)
+ dev[1].mesh_group_add(id)
+
+ # Check for mesh joined
+ check_mesh_group_added(dev[0])
+ check_mesh_group_added(dev[1])
+
+ # Check for peer connected
+ check_mesh_peer_connected(dev[0])
+ check_mesh_peer_connected(dev[1])
+
+ # Test connectivity 0->1 and 1->0
+ hwsim_utils.test_connectivity(dev[0], dev[1])
+
+def run_mesh_secure(dev, cipher):
+ if cipher not in dev[0].get_capability("pairwise"):
+ raise HwsimSkip("Cipher %s not supported" % cipher)
+ check_mesh_support(dev[0], secure=True)
+ dev[0].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[0], pairwise=cipher, group=cipher)
+ dev[0].mesh_group_add(id)
+
+ dev[1].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[1], pairwise=cipher, group=cipher)
+ dev[1].mesh_group_add(id)
+
+ # Check for mesh joined
+ check_mesh_group_added(dev[0])
+ check_mesh_group_added(dev[1])
+
+ # Check for peer connected
+ check_mesh_peer_connected(dev[0])
+ check_mesh_peer_connected(dev[1])
+
+ # Test connectivity 0->1 and 1->0
+ hwsim_utils.test_connectivity(dev[0], dev[1])
+
+def test_mesh_secure_ccmp(dev, apdev):
+ """Secure mesh with CCMP"""
+ run_mesh_secure(dev, "CCMP")
+
+def test_mesh_secure_gcmp(dev, apdev):
+ """Secure mesh with GCMP"""
+ run_mesh_secure(dev, "GCMP")
+
+def test_mesh_secure_gcmp_256(dev, apdev):
+ """Secure mesh with GCMP-256"""
+ run_mesh_secure(dev, "GCMP-256")
+
+def test_mesh_secure_ccmp_256(dev, apdev):
+ """Secure mesh with CCMP-256"""
+ run_mesh_secure(dev, "CCMP-256")
+
+def test_mesh_secure_invalid_pairwise_cipher(dev, apdev):
+ """Secure mesh and invalid group cipher"""
+ check_mesh_support(dev[0], secure=True)
+ dev[0].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[0], pairwise="TKIP", group="CCMP")
+ if dev[0].mesh_group_add(id) != None:
+ raise Exception("Unexpected group add success")
+ ev = dev[0].wait_event(["mesh: Invalid pairwise cipher"], timeout=1)
+ if ev is None:
+ raise Exception("Invalid pairwise cipher not reported")
+
+def test_mesh_secure_invalid_group_cipher(dev, apdev):
+ """Secure mesh and invalid group cipher"""
+ check_mesh_support(dev[0], secure=True)
+ dev[0].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[0], pairwise="CCMP", group="TKIP")
+ if dev[0].mesh_group_add(id) != None:
+ raise Exception("Unexpected group add success")
+ ev = dev[0].wait_event(["mesh: Invalid group cipher"], timeout=1)
+ if ev is None:
+ raise Exception("Invalid group cipher not reported")
+
def test_wpas_mesh_secure_sae_group_mismatch(dev, apdev):
"""wpa_supplicant secure MESH and SAE group mismatch"""
check_mesh_support(dev[0], secure=True)
dev[1].request("SET sae_groups ")
dev[2].request("SET sae_groups ")
+def test_wpas_mesh_secure_sae_group_negotiation(dev, apdev):
+ """wpa_supplicant secure MESH and SAE group negotiation"""
+ check_mesh_support(dev[0], secure=True)
+ addr0 = dev[0].own_addr()
+ addr1 = dev[1].own_addr()
+
+ #dev[0].request("SET sae_groups 21 20 25 26")
+ dev[0].request("SET sae_groups 25")
+ id = add_mesh_secure_net(dev[0])
+ dev[0].mesh_group_add(id)
+
+ dev[1].request("SET sae_groups 19 25")
+ id = add_mesh_secure_net(dev[1])
+ dev[1].mesh_group_add(id)
+
+ check_mesh_group_added(dev[0])
+ check_mesh_group_added(dev[1])
+
+ check_mesh_peer_connected(dev[0])
+ check_mesh_peer_connected(dev[1])
+
+ dev[0].request("SET sae_groups ")
+ dev[1].request("SET sae_groups ")
+
def test_wpas_mesh_secure_sae_missing_password(dev, apdev):
"""wpa_supplicant secure MESH and missing SAE password"""
check_mesh_support(dev[0], secure=True)
dev[0].request("SET sae_groups ")
dev[1].request("SET sae_groups ")
+def test_wpas_mesh_secure_dropped_frame(dev, apdev):
+ """Secure mesh network connectivity when the first plink Open is dropped"""
+ check_mesh_support(dev[0], secure=True)
+
+ dev[0].request("SET ext_mgmt_frame_handling 1")
+ dev[0].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[0])
+ dev[0].mesh_group_add(id)
+
+ dev[1].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[1])
+ dev[1].mesh_group_add(id)
+
+ # Check for mesh joined
+ check_mesh_group_added(dev[0])
+ check_mesh_group_added(dev[1])
+
+ # Drop the first Action frame (plink Open) to test unexpected order of
+ # Confirm/Open messages.
+ count = 0
+ while True:
+ count += 1
+ if count > 10:
+ raise Exception("Did not see Action frames")
+ rx_msg = dev[0].mgmt_rx()
+ if rx_msg is None:
+ raise Exception("MGMT-RX timeout")
+ if rx_msg['subtype'] == 13:
+ logger.info("Drop the first Action frame")
+ break
+ if "OK" not in dev[0].request("MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(rx_msg['freq'], rx_msg['datarate'], rx_msg['ssi_signal'], rx_msg['frame'].encode('hex'))):
+ raise Exception("MGMT_RX_PROCESS failed")
+
+ dev[0].request("SET ext_mgmt_frame_handling 0")
+
+ # Check for peer connected
+ check_mesh_peer_connected(dev[0])
+ check_mesh_peer_connected(dev[1])
+
+ # Test connectivity 0->1 and 1->0
+ hwsim_utils.test_connectivity(dev[0], dev[1])
+
+def test_mesh_secure_fail(dev, apdev):
+ """Secure mesh network connectivity failure"""
+ check_mesh_support(dev[0], secure=True)
+ dev[0].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[0], pmf=True)
+ dev[0].mesh_group_add(id)
+
+ dev[1].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[1], pmf=True)
+
+ with fail_test(dev[0], 1, "wpa_driver_nl80211_sta_add;mesh_mpm_auth_peer"):
+ dev[1].mesh_group_add(id)
+
+ check_mesh_group_added(dev[0])
+ check_mesh_group_added(dev[1])
+
+ check_mesh_peer_connected(dev[0])
+ check_mesh_peer_connected(dev[1])
+
def test_wpas_mesh_ctrl(dev):
"""wpa_supplicant ctrl_iface mesh command error cases"""
check_mesh_support(dev[0])
if mesh1:
dev[1].request("MESH_GROUP_REMOVE " + mesh1)
-def test_wpas_mesh_max_peering(dev, apdev):
+def test_wpas_mesh_max_peering(dev, apdev, params):
"""Mesh max peering limit"""
check_mesh_support(dev[0])
try:
finally:
dev[0].request("SET max_peer_links 99")
+ addr0 = dev[0].own_addr()
+ addr1 = dev[1].own_addr()
+ addr2 = dev[2].own_addr()
+
+ capfile = os.path.join(params['logdir'], "hwsim0.pcapng")
+ filt = "wlan.fc.type_subtype == 8"
+ out = run_tshark(capfile, filt, [ "wlan.sa", "wlan.mesh.config.cap" ])
+ pkts = out.splitlines()
+ one = [ 0, 0, 0 ]
+ zero = [ 0, 0, 0 ]
+ for pkt in pkts:
+ addr, cap = pkt.split('\t')
+ cap = int(cap, 16)
+ if addr == addr0:
+ idx = 0
+ elif addr == addr1:
+ idx = 1
+ elif addr == addr2:
+ idx = 2
+ else:
+ continue
+ if cap & 0x01:
+ one[idx] += 1
+ else:
+ zero[idx] += 1
+ logger.info("one: " + str(one))
+ logger.info("zero: " + str(zero))
+ if zero[0] == 0:
+ raise Exception("Accepting Additional Mesh Peerings not cleared")
+ if one[0] == 0:
+ raise Exception("Accepting Additional Mesh Peerings was not set in the first Beacon frame")
+ if zero[1] > 0 or zero[2] > 0 or one[1] == 0 or one[2] == 0:
+ raise Exception("Unexpected value in Accepting Additional Mesh Peerings from other STAs")
+
def test_wpas_mesh_open_5ghz(dev, apdev):
"""wpa_supplicant open MESH network on 5 GHz band"""
try:
# Test connectivity 0->1 and 1->0
hwsim_utils.test_connectivity(dev[0], dev[1])
+def test_wpas_mesh_open_vht_80p80(dev, apdev):
+ """wpa_supplicant open MESH network on VHT 80+80 MHz channel"""
+ try:
+ _test_wpas_mesh_open_vht_80p80(dev, apdev)
+ finally:
+ subprocess.call(['iw', 'reg', 'set', '00'])
+ dev[0].flush_scan_cache()
+ dev[1].flush_scan_cache()
+
+def _test_wpas_mesh_open_vht_80p80(dev, apdev):
+ check_mesh_support(dev[0])
+ subprocess.call(['iw', 'reg', 'set', 'US'])
+ for i in range(2):
+ for j in range(5):
+ ev = dev[i].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=5)
+ if ev is None:
+ raise Exception("No regdom change event")
+ if "alpha2=US" in ev:
+ break
+ add_open_mesh_network(dev[i], freq="5180", chwidth=3)
+
+ # Check for mesh joined
+ check_mesh_group_added(dev[0])
+ check_mesh_group_added(dev[1])
+
+ # Check for peer connected
+ check_mesh_peer_connected(dev[0])
+ check_mesh_peer_connected(dev[1])
+
+ # Test connectivity 0->1 and 1->0
+ hwsim_utils.test_connectivity(dev[0], dev[1])
+
+ sig = dev[0].request("SIGNAL_POLL").splitlines()
+ if "WIDTH=80+80 MHz" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
+ if "CENTER_FRQ1=5210" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(3): " + str(sig))
+ if "CENTER_FRQ2=5775" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(4): " + str(sig))
+
+ sig = dev[1].request("SIGNAL_POLL").splitlines()
+ if "WIDTH=80+80 MHz" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(2b): " + str(sig))
+ if "CENTER_FRQ1=5210" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(3b): " + str(sig))
+ if "CENTER_FRQ2=5775" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(4b): " + str(sig))
+
+def test_mesh_open_vht_160(dev, apdev):
+ """Open mesh network on VHT 160 MHz channel"""
+ try:
+ _test_mesh_open_vht_160(dev, apdev)
+ finally:
+ subprocess.call(['iw', 'reg', 'set', '00'])
+ dev[0].flush_scan_cache()
+ dev[1].flush_scan_cache()
+
+def _test_mesh_open_vht_160(dev, apdev):
+ check_mesh_support(dev[0])
+ subprocess.call(['iw', 'reg', 'set', 'ZA'])
+ for i in range(2):
+ for j in range(5):
+ ev = dev[i].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=5)
+ if ev is None:
+ raise Exception("No regdom change event")
+ if "alpha2=ZA" in ev:
+ break
+
+ cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE)
+ reg = cmd.stdout.read()
+ if "@ 160)" not in reg:
+ raise HwsimSkip("160 MHz channel not supported in regulatory information")
+
+ add_open_mesh_network(dev[i], freq="5520", chwidth=2)
+
+ # Check for mesh joined
+ check_mesh_group_added(dev[0])
+ check_mesh_group_added(dev[1])
+
+ # Check for peer connected
+ check_mesh_peer_connected(dev[0])
+ check_mesh_peer_connected(dev[1])
+
+ # Test connectivity 0->1 and 1->0
+ hwsim_utils.test_connectivity(dev[0], dev[1])
+
+ sig = dev[0].request("SIGNAL_POLL").splitlines()
+ if "WIDTH=160 MHz" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig))
+ if "FREQUENCY=5520" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(3): " + str(sig))
+
+ sig = dev[1].request("SIGNAL_POLL").splitlines()
+ if "WIDTH=160 MHz" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(2b): " + str(sig))
+ if "FREQUENCY=5520" not in sig:
+ raise Exception("Unexpected SIGNAL_POLL value(3b): " + str(sig))
+
def test_wpas_mesh_password_mismatch(dev, apdev):
"""Mesh network and one device with mismatching password"""
check_mesh_support(dev[0], secure=True)
ev = dev[0].wait_event(["MESH-GROUP-STARTED"], timeout=0.2)
if ev is not None:
raise Exception("Unexpected mesh group start during OOM")
+
+def test_mesh_wpa_init_fail(dev, apdev):
+ """Secure mesh network setup local failure"""
+ check_mesh_support(dev[0], secure=True)
+ dev[0].request("SET sae_groups ")
+
+ with fail_test(dev[0], 1, "os_get_random;=__mesh_rsn_auth_init"):
+ id = add_mesh_secure_net(dev[0])
+ dev[0].mesh_group_add(id)
+ wait_fail_trigger(dev[0], "GET_FAIL")
+
+ dev[0].dump_monitor()
+ with alloc_fail(dev[0], 1, "mesh_rsn_auth_init"):
+ id = add_mesh_secure_net(dev[0])
+ dev[0].mesh_group_add(id)
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+
+ dev[0].dump_monitor()
+ with fail_test(dev[0], 1, "os_get_random;mesh_rsn_init_ampe_sta"):
+ id = add_mesh_secure_net(dev[0])
+ dev[0].mesh_group_add(id)
+ dev[1].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[1])
+ dev[1].mesh_group_add(id)
+ wait_fail_trigger(dev[0], "GET_FAIL")
+
+def test_wpas_mesh_reconnect(dev, apdev):
+ """Secure mesh network plink counting during reconnection"""
+ check_mesh_support(dev[0])
+ try:
+ _test_wpas_mesh_reconnect(dev)
+ finally:
+ dev[0].request("SET max_peer_links 99")
+
+def _test_wpas_mesh_reconnect(dev):
+ dev[0].request("SET max_peer_links 2")
+ dev[0].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[0])
+ dev[0].set_network(id, "beacon_int", "100")
+ dev[0].mesh_group_add(id)
+ dev[1].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[1])
+ dev[1].mesh_group_add(id)
+ check_mesh_group_added(dev[0])
+ check_mesh_group_added(dev[1])
+ check_mesh_peer_connected(dev[0])
+ check_mesh_peer_connected(dev[1])
+
+ for i in range(3):
+ # Drop incoming management frames to avoid handling link close
+ dev[0].request("SET ext_mgmt_frame_handling 1")
+ dev[1].mesh_group_remove()
+ check_mesh_group_removed(dev[1])
+ dev[1].request("FLUSH")
+ dev[0].request("SET ext_mgmt_frame_handling 0")
+ id = add_mesh_secure_net(dev[1])
+ dev[1].mesh_group_add(id)
+ check_mesh_group_added(dev[1])
+ check_mesh_peer_connected(dev[1])
+ dev[0].dump_monitor()
+ dev[1].dump_monitor()
+
+def test_wpas_mesh_gate_forwarding(dev, apdev, p):
+ """Mesh forwards traffic to unknown sta to mesh gates"""
+ addr0 = dev[0].own_addr()
+ addr1 = dev[1].own_addr()
+ addr2 = dev[2].own_addr()
+ external_sta = '02:11:22:33:44:55'
+
+ # start 3 node connected mesh
+ check_mesh_support(dev[0])
+ for i in range(3):
+ add_open_mesh_network(dev[i])
+ check_mesh_group_added(dev[i])
+ for i in range(3):
+ check_mesh_peer_connected(dev[i])
+
+ hwsim_utils.test_connectivity(dev[0], dev[1])
+ hwsim_utils.test_connectivity(dev[1], dev[2])
+ hwsim_utils.test_connectivity(dev[0], dev[2])
+
+ # dev0 and dev1 are mesh gates
+ subprocess.call(['iw', 'dev', dev[0].ifname, 'set', 'mesh_param',
+ 'mesh_gate_announcements=1'])
+ subprocess.call(['iw', 'dev', dev[1].ifname, 'set', 'mesh_param',
+ 'mesh_gate_announcements=1'])
+
+ # wait for gate announcement frames
+ time.sleep(1)
+
+ # data frame from dev2 -> external sta should be sent to both gates
+ dev[2].request("DATA_TEST_CONFIG 1")
+ dev[2].request("DATA_TEST_TX {} {} 0".format(external_sta, addr2))
+ dev[2].request("DATA_TEST_CONFIG 0")
+
+ capfile = os.path.join(p['logdir'], "hwsim0.pcapng")
+ filt = "wlan.sa==%s && wlan_mgt.fixed.mesh_addr5==%s" % (addr2,
+ external_sta)
+ for i in range(15):
+ da = run_tshark(capfile, filt, [ "wlan.da" ])
+ if addr0 in da and addr1 in da:
+ logger.debug("Frames seen in tshark iteration %d" % i)
+ break
+ time.sleep(0.3)
+
+ if addr0 not in da:
+ raise Exception("Frame to gate %s not observed" % addr0)
+ if addr1 not in da:
+ raise Exception("Frame to gate %s not observed" % addr1)
+
+def test_wpas_mesh_pmksa_caching(dev, apdev):
+ """Secure mesh network and PMKSA caching"""
+ check_mesh_support(dev[0], secure=True)
+ dev[0].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[0])
+ dev[0].mesh_group_add(id)
+
+ dev[1].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[1])
+ dev[1].mesh_group_add(id)
+
+ # Check for mesh joined
+ check_mesh_group_added(dev[0])
+ check_mesh_group_added(dev[1])
+
+ # Check for peer connected
+ check_mesh_peer_connected(dev[0])
+ check_mesh_peer_connected(dev[1])
+
+ addr0 = dev[0].own_addr()
+ addr1 = dev[1].own_addr()
+ pmksa0 = dev[0].get_pmksa(addr1)
+ pmksa1 = dev[1].get_pmksa(addr0)
+ if pmksa0 is None or pmksa1 is None:
+ raise Exception("No PMKSA cache entry created")
+ if pmksa0['pmkid'] != pmksa1['pmkid']:
+ raise Exception("PMKID mismatch in PMKSA cache entries")
+
+ if "OK" not in dev[0].request("MESH_PEER_REMOVE " + addr1):
+ raise Exception("Failed to remove peer")
+ pmksa0b = dev[0].get_pmksa(addr1)
+ if pmksa0b is None:
+ raise Exception("PMKSA cache entry not maintained")
+ time.sleep(0.1)
+
+ if "FAIL" not in dev[0].request("MESH_PEER_ADD " + addr1):
+ raise Exception("MESH_PEER_ADD unexpectedly succeeded in no_auto_peer=0 case")
+
+def test_wpas_mesh_pmksa_caching2(dev, apdev):
+ """Secure mesh network and PMKSA caching with no_auto_peer=1"""
+ check_mesh_support(dev[0], secure=True)
+ addr0 = dev[0].own_addr()
+ addr1 = dev[1].own_addr()
+ dev[0].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[0])
+ dev[0].set_network(id, "no_auto_peer", "1")
+ dev[0].mesh_group_add(id)
+
+ dev[1].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[1])
+ dev[1].set_network(id, "no_auto_peer", "1")
+ dev[1].mesh_group_add(id)
+
+ # Check for mesh joined
+ check_mesh_group_added(dev[0])
+ check_mesh_group_added(dev[1])
+
+ # Check for peer connected
+ ev = dev[0].wait_event(["will not initiate new peer link"], timeout=10)
+ if ev is None:
+ raise Exception("Missing no-initiate message")
+ if "OK" not in dev[0].request("MESH_PEER_ADD " + addr1):
+ raise Exception("MESH_PEER_ADD failed")
+ check_mesh_peer_connected(dev[0])
+ check_mesh_peer_connected(dev[1])
+
+ pmksa0 = dev[0].get_pmksa(addr1)
+ pmksa1 = dev[1].get_pmksa(addr0)
+ if pmksa0 is None or pmksa1 is None:
+ raise Exception("No PMKSA cache entry created")
+ if pmksa0['pmkid'] != pmksa1['pmkid']:
+ raise Exception("PMKID mismatch in PMKSA cache entries")
+
+ if "OK" not in dev[0].request("MESH_PEER_REMOVE " + addr1):
+ raise Exception("Failed to remove peer")
+ pmksa0b = dev[0].get_pmksa(addr1)
+ if pmksa0b is None:
+ raise Exception("PMKSA cache entry not maintained")
+
+ ev = dev[0].wait_event(["will not initiate new peer link"], timeout=10)
+ if ev is None:
+ raise Exception("Missing no-initiate message (2)")
+ if "OK" not in dev[0].request("MESH_PEER_ADD " + addr1):
+ raise Exception("MESH_PEER_ADD failed (2)")
+ check_mesh_peer_connected(dev[0])
+ check_mesh_peer_connected(dev[1])
+
+ pmksa0c = dev[0].get_pmksa(addr1)
+ pmksa1c = dev[1].get_pmksa(addr0)
+ if pmksa0c is None or pmksa1c is None:
+ raise Exception("No PMKSA cache entry created (2)")
+ if pmksa0c['pmkid'] != pmksa1c['pmkid']:
+ raise Exception("PMKID mismatch in PMKSA cache entries")
+ if pmksa0['pmkid'] != pmksa0c['pmkid']:
+ raise Exception("PMKID changed")
+
+ hwsim_utils.test_connectivity(dev[0], dev[1])
+
+def test_wpas_mesh_pmksa_caching_no_match(dev, apdev):
+ """Secure mesh network and PMKSA caching with no PMKID match"""
+ check_mesh_support(dev[0], secure=True)
+ addr0 = dev[0].own_addr()
+ addr1 = dev[1].own_addr()
+ dev[0].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[0])
+ dev[0].set_network(id, "no_auto_peer", "1")
+ dev[0].mesh_group_add(id)
+
+ dev[1].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[1])
+ dev[1].set_network(id, "no_auto_peer", "1")
+ dev[1].mesh_group_add(id)
+
+ # Check for mesh joined
+ check_mesh_group_added(dev[0])
+ check_mesh_group_added(dev[1])
+
+ # Check for peer connected
+ ev = dev[0].wait_event(["will not initiate new peer link"], timeout=10)
+ if ev is None:
+ raise Exception("Missing no-initiate message")
+ if "OK" not in dev[0].request("MESH_PEER_ADD " + addr1):
+ raise Exception("MESH_PEER_ADD failed")
+ check_mesh_peer_connected(dev[0])
+ check_mesh_peer_connected(dev[1])
+
+ pmksa0 = dev[0].get_pmksa(addr1)
+ pmksa1 = dev[1].get_pmksa(addr0)
+ if pmksa0 is None or pmksa1 is None:
+ raise Exception("No PMKSA cache entry created")
+ if pmksa0['pmkid'] != pmksa1['pmkid']:
+ raise Exception("PMKID mismatch in PMKSA cache entries")
+
+ if "OK" not in dev[0].request("MESH_PEER_REMOVE " + addr1):
+ raise Exception("Failed to remove peer")
+
+ if "OK" not in dev[1].request("PMKSA_FLUSH"):
+ raise Exception("Failed to flush PMKSA cache")
+
+ ev = dev[0].wait_event(["will not initiate new peer link"], timeout=10)
+ if ev is None:
+ raise Exception("Missing no-initiate message (2)")
+ if "OK" not in dev[0].request("MESH_PEER_ADD " + addr1):
+ raise Exception("MESH_PEER_ADD failed (2)")
+ check_mesh_peer_connected(dev[0])
+ check_mesh_peer_connected(dev[1])
+
+ pmksa0c = dev[0].get_pmksa(addr1)
+ pmksa1c = dev[1].get_pmksa(addr0)
+ if pmksa0c is None or pmksa1c is None:
+ raise Exception("No PMKSA cache entry created (2)")
+ if pmksa0c['pmkid'] != pmksa1c['pmkid']:
+ raise Exception("PMKID mismatch in PMKSA cache entries")
+ if pmksa0['pmkid'] == pmksa0c['pmkid']:
+ raise Exception("PMKID did not change")
+
+ hwsim_utils.test_connectivity(dev[0], dev[1])
+
+def test_mesh_pmksa_caching_oom(dev, apdev):
+ """Secure mesh network and PMKSA caching failing due to OOM"""
+ check_mesh_support(dev[0], secure=True)
+ addr0 = dev[0].own_addr()
+ addr1 = dev[1].own_addr()
+ dev[0].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[0])
+ dev[0].set_network(id, "no_auto_peer", "1")
+ dev[0].mesh_group_add(id)
+
+ dev[1].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[1])
+ dev[1].set_network(id, "no_auto_peer", "1")
+ dev[1].mesh_group_add(id)
+
+ # Check for mesh joined
+ check_mesh_group_added(dev[0])
+ check_mesh_group_added(dev[1])
+
+ # Check for peer connected
+ ev = dev[0].wait_event(["will not initiate new peer link"], timeout=10)
+ if ev is None:
+ raise Exception("Missing no-initiate message")
+ if "OK" not in dev[0].request("MESH_PEER_ADD " + addr1):
+ raise Exception("MESH_PEER_ADD failed")
+ check_mesh_peer_connected(dev[0])
+ check_mesh_peer_connected(dev[1])
+
+ if "OK" not in dev[0].request("MESH_PEER_REMOVE " + addr1):
+ raise Exception("Failed to remove peer")
+ pmksa0b = dev[0].get_pmksa(addr1)
+ if pmksa0b is None:
+ raise Exception("PMKSA cache entry not maintained")
+
+ ev = dev[0].wait_event(["will not initiate new peer link"], timeout=10)
+ if ev is None:
+ raise Exception("Missing no-initiate message (2)")
+
+ with alloc_fail(dev[0], 1, "wpa_auth_sta_init;mesh_rsn_auth_sae_sta"):
+ if "OK" not in dev[0].request("MESH_PEER_ADD " + addr1):
+ raise Exception("MESH_PEER_ADD failed (2)")
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+
+def test_mesh_oom(dev, apdev):
+ """Mesh network setup failing due to OOM"""
+ check_mesh_support(dev[0], secure=True)
+ dev[0].request("SET sae_groups ")
+
+ with alloc_fail(dev[0], 1, "mesh_config_create"):
+ add_open_mesh_network(dev[0])
+ ev = dev[0].wait_event(["Failed to init mesh"])
+ if ev is None:
+ raise Exception("Init failure not reported")
+
+ with alloc_fail(dev[0], 4, "=wpa_supplicant_mesh_init"):
+ add_open_mesh_network(dev[0], basic_rates="60 120 240")
+ ev = dev[0].wait_event(["Failed to init mesh"])
+ if ev is None:
+ raise Exception("Init failure not reported")
+
+ for i in range(1, 66):
+ dev[0].dump_monitor()
+ logger.info("Test instance %d" % i)
+ try:
+ with alloc_fail(dev[0], i, "wpa_supplicant_mesh_init"):
+ add_open_mesh_network(dev[0])
+ wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
+ ev = dev[0].wait_event(["Failed to init mesh",
+ "MESH-GROUP-STARTED"])
+ if ev is None:
+ raise Exception("Init failure not reported")
+ except Exception, e:
+ if i < 15:
+ raise
+ logger.info("Ignore no-oom for i=%d" % i)
+
+ with alloc_fail(dev[0], 5, "=wpa_supplicant_mesh_init"):
+ id = add_mesh_secure_net(dev[0])
+ dev[0].mesh_group_add(id)
+ ev = dev[0].wait_event(["Failed to init mesh"])
+ if ev is None:
+ raise Exception("Init failure not reported")
+
+def test_mesh_add_interface_oom(dev):
+ """wpa_supplicant mesh with dynamic interface addition failing"""
+ check_mesh_support(dev[0])
+ for i in range(1, 3):
+ mesh = None
+ try:
+ with alloc_fail(dev[0], i, "wpas_mesh_add_interface"):
+ mesh = dev[0].request("MESH_INTERFACE_ADD").strip()
+ finally:
+ if mesh and mesh != "FAIL":
+ dev[0].request("MESH_GROUP_REMOVE " + mesh)
+
+def test_mesh_scan_oom(dev):
+ """wpa_supplicant mesh scan results and OOM"""
+ check_mesh_support(dev[0])
+ add_open_mesh_network(dev[0])
+ check_mesh_group_added(dev[0])
+ for i in range(5):
+ dev[1].scan(freq="2412")
+ res = dev[1].request("SCAN_RESULTS")
+ if "[MESH]" in res:
+ break
+ for r in res.splitlines():
+ if "[MESH]" in r:
+ break
+ bssid = r.split('\t')[0]
+
+ bss = dev[1].get_bss(bssid)
+ if bss is None:
+ raise Exception("Could not get BSS entry for mesh")
+
+ for i in range(1, 3):
+ with alloc_fail(dev[1], i, "mesh_attr_text"):
+ bss = dev[1].get_bss(bssid)
+ if bss and "mesh_id" in bss:
+ raise Exception("Unexpected BSS result during OOM")
+
+def test_mesh_drv_fail(dev, apdev):
+ """Mesh network setup failing due to driver command failure"""
+ check_mesh_support(dev[0], secure=True)
+ dev[0].request("SET sae_groups ")
+
+ with fail_test(dev[0], 1, "nl80211_join_mesh"):
+ add_open_mesh_network(dev[0])
+ ev = dev[0].wait_event(["mesh join error"])
+ if ev is None:
+ raise Exception("Join failure not reported")
+
+ dev[0].dump_monitor()
+ with fail_test(dev[0], 1, "wpa_driver_nl80211_if_add"):
+ if "FAIL" not in dev[0].request("MESH_INTERFACE_ADD").strip():
+ raise Exception("Interface added unexpectedly")
+
+ dev[0].dump_monitor()
+ with fail_test(dev[0], 1, "wpa_driver_nl80211_init_mesh"):
+ add_open_mesh_network(dev[0])
+ ev = dev[0].wait_event(["Could not join mesh"])
+ if ev is None:
+ raise Exception("Join failure not reported")
+
+def test_mesh_sae_groups_invalid(dev, apdev):
+ """Mesh with invalid SAE group configuration"""
+ check_mesh_support(dev[0], secure=True)
+
+ dev[0].request("SET sae_groups 25")
+ id = add_mesh_secure_net(dev[0])
+ dev[0].mesh_group_add(id)
+
+ dev[1].request("SET sae_groups 123 122 121")
+ id = add_mesh_secure_net(dev[1])
+ dev[1].mesh_group_add(id)
+
+ check_mesh_group_added(dev[0])
+ check_mesh_group_added(dev[1])
+
+ ev = dev[0].wait_event(["new peer notification"], timeout=10)
+ if ev is None:
+ raise Exception("dev[0] did not see peer")
+ ev = dev[1].wait_event(["new peer notification"], timeout=10)
+ if ev is None:
+ raise Exception("dev[1] did not see peer")
+
+ ev = dev[0].wait_event(["MESH-PEER-CONNECTED"], timeout=0.1)
+ if ev is not None:
+ raise Exception("Unexpected connection(0)")
+
+ ev = dev[1].wait_event(["MESH-PEER-CONNECTED"], timeout=0.01)
+ if ev is not None:
+ raise Exception("Unexpected connection(1)")
+
+ # Additional coverage in mesh_rsn_sae_group() with non-zero
+ # wpa_s->mesh_rsn->sae_group_index.
+ dev[0].dump_monitor()
+ dev[1].dump_monitor()
+ id = add_mesh_secure_net(dev[2])
+ dev[2].mesh_group_add(id)
+ check_mesh_group_added(dev[2])
+ check_mesh_peer_connected(dev[0])
+ check_mesh_peer_connected(dev[2])
+ ev = dev[1].wait_event(["new peer notification"], timeout=10)
+ if ev is None:
+ raise Exception("dev[1] did not see peer(2)")
+ dev[0].dump_monitor()
+ dev[1].dump_monitor()
+ dev[2].dump_monitor()
+
+ dev[0].request("SET sae_groups ")
+ dev[1].request("SET sae_groups ")
+
+def test_mesh_sae_failure(dev, apdev):
+ """Mesh and local SAE failures"""
+ check_mesh_support(dev[0], secure=True)
+
+ dev[0].request("SET sae_groups ")
+ dev[1].request("SET sae_groups ")
+
+ funcs = [ (1, "=mesh_rsn_auth_sae_sta", True),
+ (1, "mesh_rsn_build_sae_commit;mesh_rsn_auth_sae_sta", False),
+ (1, "auth_sae_init_committed;mesh_rsn_auth_sae_sta", True),
+ (1, "=mesh_rsn_protect_frame", True),
+ (2, "=mesh_rsn_protect_frame", True),
+ (1, "aes_siv_encrypt;mesh_rsn_protect_frame", True),
+ (1, "=mesh_rsn_process_ampe", True),
+ (1, "aes_siv_decrypt;mesh_rsn_process_ampe", True) ]
+ for count, func, success in funcs:
+ id = add_mesh_secure_net(dev[0])
+ dev[0].mesh_group_add(id)
+
+ with alloc_fail(dev[1], count, func):
+ id = add_mesh_secure_net(dev[1])
+ dev[1].mesh_group_add(id)
+ check_mesh_group_added(dev[0])
+ check_mesh_group_added(dev[1])
+ if success:
+ # retry is expected to work
+ check_mesh_peer_connected(dev[0])
+ check_mesh_peer_connected(dev[1])
+ else:
+ wait_fail_trigger(dev[1], "GET_ALLOC_FAIL")
+ dev[0].mesh_group_remove()
+ dev[1].mesh_group_remove()
+ check_mesh_group_removed(dev[0])
+ check_mesh_group_removed(dev[1])
+
+def test_mesh_failure(dev, apdev):
+ """Mesh and local failures"""
+ check_mesh_support(dev[0])
+
+ funcs = [ (1, "ap_sta_add;mesh_mpm_add_peer", True),
+ (1, "wpabuf_alloc;mesh_mpm_send_plink_action", True) ]
+ for count, func, success in funcs:
+ add_open_mesh_network(dev[0])
+
+ with alloc_fail(dev[1], count, func):
+ add_open_mesh_network(dev[1])
+ check_mesh_group_added(dev[0])
+ check_mesh_group_added(dev[1])
+ if success:
+ # retry is expected to work
+ check_mesh_peer_connected(dev[0])
+ check_mesh_peer_connected(dev[1])
+ else:
+ wait_fail_trigger(dev[1], "GET_ALLOC_FAIL")
+ dev[0].mesh_group_remove()
+ dev[1].mesh_group_remove()
+ check_mesh_group_removed(dev[0])
+ check_mesh_group_removed(dev[1])
+
+ funcs = [ (1, "mesh_mpm_init_link", True) ]
+ for count, func, success in funcs:
+ add_open_mesh_network(dev[0])
+
+ with fail_test(dev[1], count, func):
+ add_open_mesh_network(dev[1])
+ check_mesh_group_added(dev[0])
+ check_mesh_group_added(dev[1])
+ if success:
+ # retry is expected to work
+ check_mesh_peer_connected(dev[0])
+ check_mesh_peer_connected(dev[1])
+ else:
+ wait_fail_trigger(dev[1], "GET_FAIL")
+ dev[0].mesh_group_remove()
+ dev[1].mesh_group_remove()
+ check_mesh_group_removed(dev[0])
+ check_mesh_group_removed(dev[1])
+
+def test_mesh_invalid_frequency(dev, apdev):
+ """Mesh and invalid frequency configuration"""
+ check_mesh_support(dev[0])
+ add_open_mesh_network(dev[0], freq=None)
+ ev = dev[0].wait_event(["MESH-GROUP-STARTED",
+ "Could not join mesh"])
+ if ev is None or "Could not join mesh" not in ev:
+ raise Exception("Mesh join failure not reported")
+ dev[0].request("REMOVE_NETWORK all")
+
+ add_open_mesh_network(dev[0], freq="2413")
+ ev = dev[0].wait_event(["MESH-GROUP-STARTED",
+ "Could not join mesh"])
+ if ev is None or "Could not join mesh" not in ev:
+ raise Exception("Mesh join failure not reported")
+
+def test_mesh_default_beacon_int(dev, apdev):
+ """Mesh and default beacon interval"""
+ check_mesh_support(dev[0])
+ try:
+ dev[0].request("SET beacon_int 200")
+ add_open_mesh_network(dev[0])
+ check_mesh_group_added(dev[0])
+ finally:
+ dev[0].request("SET beacon_int 0")
+
+def test_mesh_scan_parse_error(dev, apdev):
+ """Mesh scan element parse error"""
+ check_mesh_support(dev[0])
+ params = { "ssid": "open",
+ "beacon_int": "2000" }
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+ hapd.set('vendor_elements', 'dd0201')
+ for i in range(10):
+ dev[0].scan(freq=2412)
+ if bssid in dev[0].request("SCAN_RESULTS"):
+ break
+ # This will fail in IE parsing due to the truncated IE in the Probe
+ # Response frame.
+ bss = dev[0].request("BSS " + bssid)
+
+def test_mesh_missing_mic(dev, apdev):
+ """Secure mesh network and missing MIC"""
+ check_mesh_support(dev[0], secure=True)
+
+ dev[0].request("SET ext_mgmt_frame_handling 1")
+ dev[0].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[0])
+ dev[0].mesh_group_add(id)
+
+ dev[1].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[1])
+ dev[1].mesh_group_add(id)
+
+ # Check for mesh joined
+ check_mesh_group_added(dev[0])
+ check_mesh_group_added(dev[1])
+
+ count = 0
+ remove_mic = True
+ while True:
+ count += 1
+ if count > 15:
+ raise Exception("Did not see Action frames")
+ rx_msg = dev[0].mgmt_rx()
+ if rx_msg is None:
+ ev = dev[1].wait_event(["MESH-PEER-CONNECTED"], timeout=0.01)
+ if ev:
+ break
+ raise Exception("MGMT-RX timeout")
+ if rx_msg['subtype'] == 13:
+ payload = rx_msg['payload']
+ frame = rx_msg['frame']
+ (categ, action) = struct.unpack('BB', payload[0:2])
+ if categ == 15 and action == 1 and remove_mic:
+ # Mesh Peering Open
+ pos = frame.find('\x8c\x10')
+ if not pos:
+ raise Exception("Could not find MIC element")
+ logger.info("Found MIC at %d" % pos)
+ # Remove MIC
+ rx_msg['frame'] = frame[0:pos]
+ remove_mic = False
+ if "OK" not in dev[0].request("MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(rx_msg['freq'], rx_msg['datarate'], rx_msg['ssi_signal'], rx_msg['frame'].encode('hex'))):
+ raise Exception("MGMT_RX_PROCESS failed")
+ ev = dev[1].wait_event(["MESH-PEER-CONNECTED"], timeout=0.01)
+ if ev:
+ break
+
+def test_mesh_pmkid_mismatch(dev, apdev):
+ """Secure mesh network and PMKID mismatch"""
+ check_mesh_support(dev[0], secure=True)
+ addr0 = dev[0].own_addr()
+ addr1 = dev[1].own_addr()
+ dev[0].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[0])
+ dev[0].set_network(id, "no_auto_peer", "1")
+ dev[0].mesh_group_add(id)
+
+ dev[1].request("SET sae_groups ")
+ id = add_mesh_secure_net(dev[1])
+ dev[1].set_network(id, "no_auto_peer", "1")
+ dev[1].mesh_group_add(id)
+
+ # Check for mesh joined
+ check_mesh_group_added(dev[0])
+ check_mesh_group_added(dev[1])
+
+ # Check for peer connected
+ ev = dev[0].wait_event(["will not initiate new peer link"], timeout=10)
+ if ev is None:
+ raise Exception("Missing no-initiate message")
+ if "OK" not in dev[0].request("MESH_PEER_ADD " + addr1):
+ raise Exception("MESH_PEER_ADD failed")
+ check_mesh_peer_connected(dev[0])
+ check_mesh_peer_connected(dev[1])
+
+ if "OK" not in dev[0].request("MESH_PEER_REMOVE " + addr1):
+ raise Exception("Failed to remove peer")
+
+ ev = dev[0].wait_event(["will not initiate new peer link"], timeout=10)
+ if ev is None:
+ raise Exception("Missing no-initiate message (2)")
+ dev[0].dump_monitor()
+ dev[1].dump_monitor()
+ dev[0].request("SET ext_mgmt_frame_handling 1")
+ if "OK" not in dev[0].request("MESH_PEER_ADD " + addr1):
+ raise Exception("MESH_PEER_ADD failed (2)")
+
+ count = 0
+ break_pmkid = True
+ while True:
+ count += 1
+ if count > 50:
+ raise Exception("Did not see Action frames")
+ rx_msg = dev[0].mgmt_rx()
+ if rx_msg is None:
+ ev = dev[1].wait_event(["MESH-PEER-CONNECTED"], timeout=0.1)
+ if ev:
+ break
+ raise Exception("MGMT-RX timeout")
+ if rx_msg['subtype'] == 13:
+ payload = rx_msg['payload']
+ frame = rx_msg['frame']
+ (categ, action) = struct.unpack('BB', payload[0:2])
+ if categ == 15 and action == 1 and break_pmkid:
+ # Mesh Peering Open
+ pos = frame.find('\x75\x14')
+ if not pos:
+ raise Exception("Could not find Mesh Peering Management element")
+ logger.info("Found Mesh Peering Management element at %d" % pos)
+ # Break PMKID to hit "Mesh RSN: Invalid PMKID (Chosen PMK did
+ # not match calculated PMKID)"
+ rx_msg['frame'] = frame[0:pos + 6] + '\x00\x00\x00\x00' + frame[pos + 10:]
+ break_pmkid = False
+ if "OK" not in dev[0].request("MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(rx_msg['freq'], rx_msg['datarate'], rx_msg['ssi_signal'], rx_msg['frame'].encode('hex'))):
+ raise Exception("MGMT_RX_PROCESS failed")
+ ev = dev[1].wait_event(["MESH-PEER-CONNECTED"], timeout=0.01)
+ if ev:
+ break
+
+def test_mesh_peering_proto(dev, apdev):
+ """Mesh peering management protocol testing"""
+ check_mesh_support(dev[0])
+
+ dev[0].request("SET ext_mgmt_frame_handling 1")
+ add_open_mesh_network(dev[0], beacon_int=160)
+ add_open_mesh_network(dev[1], beacon_int=160)
+
+ count = 0
+ test = 1
+ while True:
+ count += 1
+ if count > 50:
+ raise Exception("Did not see Action frames")
+ rx_msg = dev[0].mgmt_rx()
+ if rx_msg is None:
+ ev = dev[1].wait_event(["MESH-PEER-CONNECTED"], timeout=0.01)
+ if ev:
+ break
+ raise Exception("MGMT-RX timeout")
+ if rx_msg['subtype'] == 13:
+ payload = rx_msg['payload']
+ frame = rx_msg['frame']
+ (categ, action) = struct.unpack('BB', payload[0:2])
+ if categ == 15 and action == 1 and test == 1:
+ # Mesh Peering Open
+ pos = frame.find('\x75\x04')
+ if not pos:
+ raise Exception("Could not find Mesh Peering Management element")
+ logger.info("Found Mesh Peering Management element at %d" % pos)
+ # Remove the element to hit
+ # "MPM: No Mesh Peering Management element"
+ rx_msg['frame'] = frame[0:pos]
+ test += 1
+ elif categ == 15 and action == 1 and test == 2:
+ # Mesh Peering Open
+ pos = frame.find('\x72\x0e')
+ if not pos:
+ raise Exception("Could not find Mesh ID element")
+ logger.info("Found Mesh ID element at %d" % pos)
+ # Remove the element to hit
+ # "MPM: No Mesh ID or Mesh Configuration element"
+ rx_msg['frame'] = frame[0:pos] + frame[pos + 16:]
+ test += 1
+ elif categ == 15 and action == 1 and test == 3:
+ # Mesh Peering Open
+ pos = frame.find('\x72\x0e')
+ if not pos:
+ raise Exception("Could not find Mesh ID element")
+ logger.info("Found Mesh ID element at %d" % pos)
+ # Replace Mesh ID to hit "MPM: Mesh ID or Mesh Configuration
+ # element do not match local MBSS"
+ rx_msg['frame'] = frame[0:pos] + '\x72\x0etest-test-test' + frame[pos + 16:]
+ test += 1
+ elif categ == 15 and action == 1 and test == 4:
+ # Mesh Peering Open
+ # Remove IEs to hit
+ # "MPM: Ignore too short action frame 1 ie_len 0"
+ rx_msg['frame'] = frame[0:26]
+ test += 1
+ elif categ == 15 and action == 1 and test == 5:
+ # Mesh Peering Open
+ # Truncate IEs to hit
+ # "MPM: Failed to parse PLINK IEs"
+ rx_msg['frame'] = frame[0:30]
+ test += 1
+ elif categ == 15 and action == 1 and test == 6:
+ # Mesh Peering Open
+ pos = frame.find('\x75\x04')
+ if not pos:
+ raise Exception("Could not find Mesh Peering Management element")
+ logger.info("Found Mesh Peering Management element at %d" % pos)
+ # Truncate the element to hit
+ # "MPM: Invalid peer mgmt ie" and
+ # "MPM: Mesh parsing rejected frame"
+ rx_msg['frame'] = frame[0:pos] + '\x75\x00\x00\x00' + frame[pos + 6:]
+ test += 1
+ if "OK" not in dev[0].request("MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(rx_msg['freq'], rx_msg['datarate'], rx_msg['ssi_signal'], rx_msg['frame'].encode('hex'))):
+ raise Exception("MGMT_RX_PROCESS failed")
+ ev = dev[1].wait_event(["MESH-PEER-CONNECTED"], timeout=0.01)
+ if ev:
+ break
+
+ if test != 7:
+ raise Exception("Not all test frames completed")
+
+def test_mesh_mpm_init_proto(dev, apdev):
+ """Mesh peering management protocol testing for peer addition"""
+ check_mesh_support(dev[0])
+ add_open_mesh_network(dev[0])
+ check_mesh_group_added(dev[0])
+ dev[0].dump_monitor()
+
+ dev[0].request("SET ext_mgmt_frame_handling 1")
+
+ addr = "020000000100"
+ hdr = "d000ac00020000000000" + addr + addr + "1000"
+ fixed = "0f010000"
+ supp_rates = "010802040b168c129824"
+ ext_supp_rates = "3204b048606c"
+ mesh_id = "720e777061732d6d6573682d6f70656e"
+ mesh_conf = "710701010001000009"
+ mpm = "75040000079d"
+ ht_capab = "2d1a7c001bffff000000000000000000000100000000000000000000"
+ ht_oper = "3d160b000000000000000000000000000000000000000000"
+
+ dev[0].request("NOTE no supported rates")
+ frame = hdr + fixed + ext_supp_rates + mesh_id + mesh_conf + mpm + ht_capab + ht_oper
+ if "OK" not in dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=%s" % frame):
+ raise Exception("MGMT_RX_PROCESS failed")
+
+ dev[0].request("NOTE Invalid supported rates element length 33+0")
+ long_supp_rates = "012100112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00"
+ frame = hdr + fixed + long_supp_rates + mesh_id + mesh_conf + mpm + ht_capab + ht_oper
+ if "OK" not in dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=%s" % frame):
+ raise Exception("MGMT_RX_PROCESS failed")
+
+ dev[0].request("NOTE Too short mesh config")
+ short_mesh_conf = "710401010001"
+ frame = hdr + fixed + supp_rates + mesh_id + short_mesh_conf + mpm + ht_capab + ht_oper
+ if "OK" not in dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=%s" % frame):
+ raise Exception("MGMT_RX_PROCESS failed")
+
+ dev[0].request("NOTE Add STA failure")
+ frame = hdr + fixed + supp_rates + ext_supp_rates + mesh_id + mesh_conf + mpm + ht_capab + ht_oper
+ with fail_test(dev[0], 1, "wpa_driver_nl80211_sta_add"):
+ if "OK" not in dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=%s" % frame):
+ raise Exception("MGMT_RX_PROCESS failed")
+
+ dev[0].request("NOTE Send Action failure")
+ with fail_test(dev[0], 1, "driver_nl80211_send_action"):
+ if "OK" not in dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=%s" % frame):
+ raise Exception("MGMT_RX_PROCESS failed")
+
+ dev[0].request("NOTE Set STA failure")
+ addr = "020000000101"
+ hdr = "d000ac00020000000000" + addr + addr + "1000"
+ frame = hdr + fixed + supp_rates + ext_supp_rates + mesh_id + mesh_conf + mpm + ht_capab + ht_oper
+ with fail_test(dev[0], 2, "wpa_driver_nl80211_sta_add"):
+ if "OK" not in dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=%s" % frame):
+ raise Exception("MGMT_RX_PROCESS failed")
+
+ dev[0].request("NOTE ap_sta_add OOM")
+ addr = "020000000102"
+ hdr = "d000ac00020000000000" + addr + addr + "1000"
+ frame = hdr + fixed + supp_rates + ext_supp_rates + mesh_id + mesh_conf + mpm + ht_capab + ht_oper
+ with alloc_fail(dev[0], 1, "ap_sta_add"):
+ if "OK" not in dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=%s" % frame):
+ raise Exception("MGMT_RX_PROCESS failed")
+
+ dev[0].request("NOTE hostapd_get_aid() failure")
+ addr = "020000000103"
+ hdr = "d000ac00020000000000" + addr + addr + "1000"
+ frame = hdr + fixed + supp_rates + ext_supp_rates + mesh_id + mesh_conf + mpm + ht_capab + ht_oper
+ with fail_test(dev[0], 1, "hostapd_get_aid"):
+ if "OK" not in dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=%s" % frame):
+ raise Exception("MGMT_RX_PROCESS failed")
+
+ if "OK" not in dev[0].request("MESH_PEER_REMOVE 02:00:00:00:01:00"):
+ raise Exception("Failed to remove peer")
+ if "FAIL" not in dev[0].request("MESH_PEER_REMOVE 02:00:00:00:01:02"):
+ raise Exception("Unexpected MESH_PEER_REMOVE success")
+ if "FAIL" not in dev[1].request("MESH_PEER_REMOVE 02:00:00:00:01:02"):
+ raise Exception("Unexpected MESH_PEER_REMOVE success(2)")
+ if "FAIL" not in dev[1].request("MESH_PEER_ADD 02:00:00:00:01:02"):
+ raise Exception("Unexpected MESH_PEER_ADD success")
+
+def test_mesh_holding(dev, apdev):
+ """Mesh MPM FSM and HOLDING state event OPN_ACPT"""
+ check_mesh_support(dev[0])
+ add_open_mesh_network(dev[0])
+ add_open_mesh_network(dev[1])
+ check_mesh_group_added(dev[0])
+ check_mesh_group_added(dev[1])
+ check_mesh_peer_connected(dev[0])
+ check_mesh_peer_connected(dev[1])
+
+ addr0 = dev[0].own_addr()
+ addr1 = dev[1].own_addr()
+
+ dev[0].request("SET ext_mgmt_frame_handling 1")
+ if "OK" not in dev[0].request("MESH_PEER_REMOVE " + addr1):
+ raise Exception("Failed to remove peer")
+
+ rx_msg = dev[0].mgmt_rx()
+ if rx_msg is None:
+ raise Exception("MGMT-RX timeout")
+ if rx_msg['subtype'] != 13:
+ raise Exception("Unexpected management frame")
+ payload = rx_msg['payload']
+ (categ, action) = struct.unpack('BB', payload[0:2])
+ if categ != 0x0f or action != 0x03:
+ raise Exception("Did not see Mesh Peering Close")
+
+ peer_lid = payload[-6:-4].encode("hex")
+ my_lid = payload[-4:-2].encode("hex")
+
+ # Drop Mesh Peering Close and instead, process an unexpected Mesh Peering
+ # Open to trigger transmission of another Mesh Peering Close in the HOLDING
+ # state based on an OPN_ACPT event.
+
+ dst = addr0.replace(':', '')
+ src = addr1.replace(':', '')
+ hdr = "d000ac00" + dst + src + src + "1000"
+ fixed = "0f010000"
+ supp_rates = "010802040b168c129824"
+ ext_supp_rates = "3204b048606c"
+ mesh_id = "720e777061732d6d6573682d6f70656e"
+ mesh_conf = "710701010001000009"
+ mpm = "7504" + my_lid + peer_lid
+ ht_capab = "2d1a7c001bffff000000000000000000000100000000000000000000"
+ ht_oper = "3d160b000000000000000000000000000000000000000000"
+
+ frame = hdr + fixed + supp_rates + ext_supp_rates + mesh_id + mesh_conf + mpm + ht_capab + ht_oper
+ if "OK" not in dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=%s" % frame):
+ raise Exception("MGMT_RX_PROCESS failed")
+ time.sleep(0.1)
+
+def test_mesh_cnf_rcvd_event_cls_acpt(dev, apdev):
+ """Mesh peering management protocol testing - CLS_ACPT event in CNF_RCVD"""
+ check_mesh_support(dev[0])
+ add_open_mesh_network(dev[0])
+ check_mesh_group_added(dev[0])
+ dev[0].dump_monitor()
+
+ dev[0].request("SET ext_mgmt_frame_handling 1")
+ add_open_mesh_network(dev[1])
+ check_mesh_group_added(dev[1])
+
+ addr0 = dev[0].own_addr()
+ addr1 = dev[1].own_addr()
+
+ rx_msg = dev[0].mgmt_rx()
+ # Drop Mesh Peering Open
+
+ rx_msg = dev[0].mgmt_rx()
+ # Allow Mesh Peering Confirm to go through
+ if "OK" not in dev[0].request("MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(rx_msg['freq'], rx_msg['datarate'], rx_msg['ssi_signal'], rx_msg['frame'].encode('hex'))):
+ raise Exception("MGMT_RX_PROCESS failed")
+
+ payload = rx_msg['payload']
+ peer_lid = payload[51:53].encode("hex")
+ my_lid = payload[53:55].encode("hex")
+
+ dst = addr0.replace(':', '')
+ src = addr1.replace(':', '')
+ hdr = "d000ac00" + dst + src + src + "1000"
+ fixed = "0f03"
+ mesh_id = "720e777061732d6d6573682d6f70656e"
+ mpm = "75080000" + peer_lid + my_lid + "3700"
+ frame = hdr + fixed + mesh_id + mpm
+
+ # Inject Mesh Peering Close to hit "state CNF_RCVD event CLS_ACPT" to
+ # HOLDING transition.
+ if "OK" not in dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + frame):
+ raise Exception("MGMT_RX_PROCESS failed")
+
+def test_mesh_opn_snt_event_cls_acpt(dev, apdev):
+ """Mesh peering management protocol testing - CLS_ACPT event in OPN_SNT"""
+ check_mesh_support(dev[0])
+ add_open_mesh_network(dev[0])
+ check_mesh_group_added(dev[0])
+ dev[0].dump_monitor()
+
+ dev[0].request("SET ext_mgmt_frame_handling 1")
+ add_open_mesh_network(dev[1])
+ check_mesh_group_added(dev[1])
+
+ addr0 = dev[0].own_addr()
+ addr1 = dev[1].own_addr()
+
+ rx_msg = dev[0].mgmt_rx()
+ # Drop Mesh Peering Open
+
+ rx_msg = dev[0].mgmt_rx()
+ # Drop Mesh Peering Confirm
+
+ payload = rx_msg['payload']
+ peer_lid = "0000"
+ my_lid = payload[53:55].encode("hex")
+
+ dst = addr0.replace(':', '')
+ src = addr1.replace(':', '')
+ hdr = "d000ac00" + dst + src + src + "1000"
+ fixed = "0f03"
+ mesh_id = "720e777061732d6d6573682d6f70656e"
+ mpm = "75080000" + peer_lid + my_lid + "3700"
+ frame = hdr + fixed + mesh_id + mpm
+
+ # Inject Mesh Peering Close to hit "state OPN_SNTevent CLS_ACPT" to
+ # HOLDING transition.
+ if "OK" not in dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + frame):
+ raise Exception("MGMT_RX_PROCESS failed")
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+from remotehost import remote_compatible
import logging
logger = logging.getLogger()
import struct
for ac in acm_list:
params["wmm_ac_%s_acm" % (ac.lower())] = "1"
- return hostapd.add_ap(apdev['ifname'], params)
+ return hostapd.add_ap(apdev, params)
def test_tspec(dev, apdev):
"""Basic addts/delts tests"""
hapd.set("ext_mgmt_frame_handling", "0")
+@remote_compatible
def test_tspec_not_enabled(dev, apdev):
"""addts failing if AP does not support WMM"""
params = { "ssid": "wmm_no_ac",
"hw_mode": "g",
"channel": "11",
"wmm_enabled" : "0" }
- hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+ hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect("wmm_no_ac", key_mgmt="NONE", scan_freq="2462")
status = dev[0].request("WMM_AC_STATUS")
if "Not associated to a WMM AP, WMM AC is Disabled" not in status:
msg['payload'] = struct.pack('BBBB', 17, 2, 0, 0)
hapd.mgmt_tx(msg)
+@remote_compatible
def test_tspec_ap_roam_open(dev, apdev):
"""Roam between two open APs while having tspecs"""
hapd0 = add_wmm_ap(apdev[0], ["VO", "VI"])
dev[0].roam(apdev[0]['bssid'])
hwsim_utils.test_connectivity(dev[0], hapd0)
+@remote_compatible
def test_tspec_reassoc(dev, apdev):
"""Reassociation to same BSS while having tspecs"""
hapd0 = add_wmm_ap(apdev[0], ["VO", "VI"])
if wait:
# wait a bit to make it more likely for wlantest sniffer to have
# captured and written the results into a file that we can process here
- time.sleep(1)
+ time.sleep(0.1)
try:
arg = [ "tshark", "-r", filename,
# See README for more details.
import os
+import time
+import remotehost
def get_ifnames():
ifnames = []
if self._dev.request("GET_FAIL") != "0:%s" % self._funcs:
raise Exception("Test failure did not trigger")
+def wait_fail_trigger(dev, cmd, note="Failure not triggered"):
+ for i in range(0, 40):
+ if dev.request(cmd).startswith("0:"):
+ break
+ if i == 39:
+ raise Exception(note)
+ time.sleep(0.05)
+
def require_under_vm():
with open('/proc/1/cmdline', 'r') as f:
cmd = f.read()
res = dev.get_capability("fips")
if res and 'FIPS' in res:
raise HwsimSkip(reason)
+
+def get_phy(ap, ifname=None):
+ phy = "phy3"
+ try:
+ hostname = ap['hostname']
+ except:
+ hostname = None
+ host = remotehost.Host(hostname)
+
+ if ifname == None:
+ ifname = ap['ifname']
+ status, buf = host.execute(["iw", "dev", ifname, "info"])
+ if status != 0:
+ raise Exception("iw " + ifname + " info failed")
+ lines = buf.split("\n")
+ for line in lines:
+ if "wiphy" in line:
+ words = line.split()
+ phy = "phy" + words[1]
+ break
+ return phy
# needed for tracing
mount debugfs -t debugfs /sys/kernel/debug
+export PATH=/usr/sbin:$PATH
+
# reboot on any sort of crash
sysctl kernel.panic_on_oops=1
sysctl kernel.panic=1
TESTDIR=$(sed 's/.*testdir=\([^ ]*\) .*/\1/' /proc/cmdline)
TIMEWARP=$(sed 's/.*timewarp=\([^ ]*\) .*/\1/' /proc/cmdline)
EPATH=$(sed 's/.*EPATH=\([^ ]*\) .*/\1/' /proc/cmdline)
-ARGS=$(sed 's/.*ARGS=//' /proc/cmdline)
+ARGS=$(sed 's/.*ARGS=\([^ ]*\)\( \|$\).*/\1/' /proc/cmdline)
# create /dev entries we need
mknod -m 660 /dev/ttyS0 c 4 64
mknod -m 660 /dev/random c 1 8
mknod -m 660 /dev/urandom c 1 9
mknod -m 666 /dev/null c 1 3
+mknod -m 666 /dev/kmsg c 1 11
test -f /sys/class/misc/rfkill/dev && \
mknod -m 660 /dev/rfkill c $(cat /sys/class/misc/rfkill/dev | tr ':' ' ')
ln -s /proc/self/fd/0 /dev/stdin
mkdir /tmp/logs
mount -t 9p -o trans=virtio,rw logshare /tmp/logs
+# allow access to any outside directory (e.g. /tmp) we also have
+mkdir /tmp/host
+mount --bind / /tmp/host
+
if [ "$TIMEWARP" = "1" ] ; then
(
while sleep 1 ; do
dbus-daemon --config-file=$TESTDIR/vm/dbus.conf --fork
cd $TESTDIR
- ./run-all.sh $ARGS </dev/ttyS0 >/dev/ttyS0 2>&1
+ ./run-all.sh $(cat /tmp/host$ARGS) </dev/ttyS0 >/dev/ttyS0 2>&1
if test -d /sys/kernel/debug/gcov ; then
cp -ar /sys/kernel/debug/gcov /tmp/logs/
# these are broken as they're updated while being read ...
"ap_vht160",
"dfs_radar",
"dfs",
+ "dfs_ht40_minus",
"grpform_cred_ready_timeout",
"hostapd_oom_wpa2_eap_connect",
"wpas_ap_dfs",
help="run tests under valgrind")
p.add_argument('params', nargs='*')
args = p.parse_args()
+
+ dir = os.environ.get('HWSIM_TEST_LOG_DIR', '/tmp/hwsim-test-logs')
+ try:
+ os.makedirs(dir)
+ except:
+ pass
+
num_servers = args.num_servers
rerun_failures = not args.no_retry
if args.debug:
extra_args += [ '--long' ]
if args.codecov:
print "Code coverage - build separate binaries"
- logdir = "/tmp/hwsim-test-logs/" + str(timestamp)
+ logdir = os.path.join(dir, str(timestamp))
os.makedirs(logdir)
subprocess.check_call([os.path.join(scriptsdir, 'build-codecov.sh'),
logdir])
if len(tests) == 0:
sys.exit("No test cases selected")
- dir = '/tmp/hwsim-test-logs'
- try:
- os.mkdir(dir)
- except:
- pass
-
if args.shuffle:
from random import shuffle
shuffle(tests)
for i in range(0, num_servers):
if len(vm[i]['failed']) == 0:
continue
- print "./parallel-vm.py -1 1",
+ print "./vm-run.sh",
+ if args.long:
+ print "--long",
skip = len(vm[i]['fail_seq'])
skip -= min(skip, 30)
for t in vm[i]['fail_seq']:
fi
shift
-LOGS=/tmp/hwsim-test-logs
+if [ -n "$HWSIM_TEST_LOG_DIR" ] ; then
+ LOGS="$HWSIM_TEST_LOG_DIR"
+else
+ LOGS=/tmp/hwsim-test-logs
+fi
mkdir -p $LOGS
DATE=$(date +%s)
#!/bin/sh
+EPATH=$(sed 's/.*EPATH=\([^ ]*\) .*/\1/' /proc/cmdline)
+PATH=/tmp/bin:$EPATH:$PATH
+
# assume this was a call for CRDA,
# if not then it won't find a COUNTRY
# environment variable and exit
TESTDIR=$(pwd)/../
fi
-LOGS=/tmp/hwsim-test-logs
+if [ -n "$HWSIM_TEST_LOG_DIR" ] ; then
+ LOGS="$HWSIM_TEST_LOG_DIR"
+else
+ LOGS=/tmp/hwsim-test-logs
+fi
# increase the memory size if you want to run with valgrind, 512 MB works
MEMORY=192
echo "Starting test run in a virtual machine"
-kvm \
+KVM=kvm
+for kvmprog in kvm qemu-kvm; do
+ if $kvmprog --version &> /dev/null; then
+ KVM=$kvmprog
+ break
+ fi
+done
+
+argsfile=$(mktemp)
+if [ $? -ne 0 ] ; then
+ exit 2
+fi
+function finish {
+ rm -f $argsfile
+}
+trap finish EXIT
+
+echo "$RUN_TEST_ARGS" > $argsfile
+
+$KVM \
-kernel $KERNEL -smp 4 \
$KVMARGS -m $MEMORY -nographic \
-fsdev local,security_model=none,id=fsdev-root,path=/$ROTAG \
-fsdev local,security_model=none,id=fsdev-logs,path="$LOGDIR",writeout=immediate \
-device virtio-9p-pci,id=fs-logs,fsdev=fsdev-logs,mount_tag=logshare \
-monitor null -serial stdio -serial file:$LOGDIR/console \
- -append "mac80211_hwsim.support_p2p_device=0 mac80211_hwsim.channels=$CHANNELS mac80211_hwsim.radios=7 init=$CMD testdir=$TESTDIR timewarp=$TIMEWARP console=$KVMOUT root=/dev/root rootflags=trans=virtio,version=9p2000.u ro rootfstype=9p EPATH=$EPATH ARGS=$RUN_TEST_ARGS"
+ -append "mac80211_hwsim.support_p2p_device=0 mac80211_hwsim.channels=$CHANNELS mac80211_hwsim.radios=7 init=$CMD testdir=$TESTDIR timewarp=$TIMEWARP console=$KVMOUT root=/dev/root rootflags=trans=virtio,version=9p2000.u ro rootfstype=9p EPATH=$EPATH ARGS=$argsfile"
if [ $CODECOV = "yes" ]; then
echo "Preparing code coverage reports"
# This software may be distributed under the terms of the BSD license.
# See README for more details.
+import re
import os
+import posixpath
import time
import subprocess
import logging
logger = logging.getLogger()
class Wlantest:
+ remote_host = None
+ setup_params = None
+ exe_thread = None
+ exe_res = []
+ monitor_mod = None
+ setup_done = False
+
+ @classmethod
+ def stop_remote_wlantest(cls):
+ if cls.exe_thread is None:
+ # Local flow - no need for remote operations
+ return
+
+ cls.remote_host.execute(["killall", "-9", "wlantest"])
+ cls.remote_host.wait_execute_complete(cls.exe_thread, 5)
+ cls.exe_thread = None
+ cls.exe_res = []
+
+ @classmethod
+ def reset_remote_wlantest(cls):
+ cls.stop_remote_wlantest()
+ cls.remote_host = None
+ cls.setup_params = None
+ cls.exe_thread = None
+ cls.exe_res = []
+ cls.monitor_mod = None
+ cls.setup_done = False
+
+ @classmethod
+ def start_remote_wlantest(cls):
+ if cls.remote_host is None:
+ # Local flow - no need for remote operations
+ return
+ if cls.exe_thread is not None:
+ raise Exception("Cannot start wlantest twice")
+
+ log_dir = cls.setup_params['log_dir']
+ ifaces = re.split('; | |, ', cls.remote_host.ifname)
+ ifname = ifaces[0]
+ exe = cls.setup_params["wlantest"]
+ tc_name = cls.setup_params["tc_name"]
+ base_log_name = tc_name + "_wlantest_" + \
+ cls.remote_host.name + "_" + ifname
+ log_file = posixpath.join(log_dir, base_log_name + ".log")
+ pcap_file = posixpath.join(log_dir, base_log_name + ".pcapng")
+ cmd = "{} -i {} -n {} -c -dtN -L {}".format(exe, ifname,
+ pcap_file, log_file)
+ cls.remote_host.add_log(log_file)
+ cls.remote_host.add_log(pcap_file)
+ cls.exe_thread = cls.remote_host.execute_run(cmd.split(), cls.exe_res)
+ # Give wlantest a chance to start working
+ time.sleep(1)
+
+ @classmethod
+ def register_remote_wlantest(cls, host, setup_params, monitor_mod):
+ if cls.remote_host is not None:
+ raise Exception("Cannot register remote wlantest twice")
+ cls.remote_host = host
+ cls.setup_params = setup_params
+ cls.monitor_mod = monitor_mod
+ status, buf = host.execute(["which", setup_params['wlantest']])
+ if status != 0:
+ raise Exception(host.name + " - wlantest: " + buf)
+ status, buf = host.execute(["which", setup_params['wlantest_cli']])
+ if status != 0:
+ raise Exception(host.name + " - wlantest_cli: " + buf)
+
+ @classmethod
+ def chan_from_wpa(cls, wpa, is_p2p=False):
+ if cls.monitor_mod is None:
+ return
+ m = cls.monitor_mod
+ return m.setup(cls.remote_host, [m.get_monitor_params(wpa, is_p2p)])
+
+ @classmethod
+ def setup(cls, wpa, is_p2p=False):
+ cls.chan_from_wpa(wpa, is_p2p)
+ cls.start_remote_wlantest()
+ cls.setup_done = True
+
def __init__(self):
+ if not self.setup_done:
+ raise Exception("Cannot create Wlantest instance before setup()")
if os.path.isfile('../../wlantest/wlantest_cli'):
self.wlantest_cli = '../../wlantest/wlantest_cli'
else:
self.wlantest_cli = 'wlantest_cli'
+ def cli_cmd(self, params):
+ if self.remote_host is not None:
+ exe = self.setup_params["wlantest_cli"]
+ ret = self.remote_host.execute([exe] + params)
+ if ret[0] != 0:
+ raise Exception("wlantest_cli failed")
+ return ret[1]
+ else:
+ return subprocess.check_output([self.wlantest_cli] + params)
+
def flush(self):
- res = subprocess.check_output([self.wlantest_cli, "flush"])
+ res = self.cli_cmd(["flush"])
if "FAIL" in res:
raise Exception("wlantest_cli flush failed")
def relog(self):
- res = subprocess.check_output([self.wlantest_cli, "relog"])
+ res = self.cli_cmd(["relog"])
if "FAIL" in res:
raise Exception("wlantest_cli relog failed")
def add_passphrase(self, passphrase):
- res = subprocess.check_output([self.wlantest_cli, "add_passphrase",
- passphrase])
+ res = self.cli_cmd(["add_passphrase", passphrase])
if "FAIL" in res:
raise Exception("wlantest_cli add_passphrase failed")
def add_wepkey(self, key):
- res = subprocess.check_output([self.wlantest_cli, "add_wepkey", key])
+ res = self.cli_cmd(["add_wepkey", key])
if "FAIL" in res:
raise Exception("wlantest_cli add_key failed")
def info_bss(self, field, bssid):
- res = subprocess.check_output([self.wlantest_cli, "info_bss",
- field, bssid])
+ res = self.cli_cmd(["info_bss", field, bssid])
if "FAIL" in res:
raise Exception("Could not get BSS info from wlantest for " + bssid)
return res
def get_bss_counter(self, field, bssid):
try:
- res = subprocess.check_output([self.wlantest_cli, "get_bss_counter",
- field, bssid]);
+ res = self.cli_cmd(["get_bss_counter", field, bssid])
except Exception, e:
return 0
if "FAIL" in res:
return int(res)
def clear_bss_counters(self, bssid):
- subprocess.call([self.wlantest_cli, "clear_bss_counters", bssid],
- stdout=open('/dev/null', 'w'));
+ self.cli_cmd(["clear_bss_counters", bssid])
def info_sta(self, field, bssid, addr):
- res = subprocess.check_output([self.wlantest_cli, "info_sta",
- field, bssid, addr])
+ res = self.cli_cmd(["info_sta", field, bssid, addr])
if "FAIL" in res:
raise Exception("Could not get STA info from wlantest for " + addr)
return res
def get_sta_counter(self, field, bssid, addr):
- res = subprocess.check_output([self.wlantest_cli, "get_sta_counter",
- field, bssid, addr]);
+ res = self.cli_cmd(["get_sta_counter", field, bssid, addr])
if "FAIL" in res:
raise Exception("wlantest_cli command failed")
return int(res)
def clear_sta_counters(self, bssid, addr):
- res = subprocess.check_output([self.wlantest_cli, "clear_sta_counters",
- bssid, addr]);
+ res = self.cli_cmd(["clear_sta_counters", bssid, addr])
if "FAIL" in res:
raise Exception("wlantest_cli command failed")
def tdls_clear(self, bssid, addr1, addr2):
- res = subprocess.check_output([self.wlantest_cli, "clear_tdls_counters",
- bssid, addr1, addr2]);
+ self.cli_cmd(["clear_tdls_counters", bssid, addr1, addr2])
def get_tdls_counter(self, field, bssid, addr1, addr2):
- res = subprocess.check_output([self.wlantest_cli, "get_tdls_counter",
- field, bssid, addr1, addr2]);
+ res = self.cli_cmd(["get_tdls_counter", field, bssid, addr1, addr2])
if "FAIL" in res:
raise Exception("wlantest_cli command failed")
return int(res)
raise Exception("Unexpected STA key_mgmt")
def get_tx_tid(self, bssid, addr, tid):
- res = subprocess.check_output([self.wlantest_cli, "get_tx_tid",
- bssid, addr, str(tid)]);
+ res = self.cli_cmd(["get_tx_tid", bssid, addr, str(tid)])
if "FAIL" in res:
raise Exception("wlantest_cli command failed")
return int(res)
def get_rx_tid(self, bssid, addr, tid):
- res = subprocess.check_output([self.wlantest_cli, "get_rx_tid",
- bssid, addr, str(tid)]);
+ res = self.cli_cmd(["get_rx_tid", bssid, addr, str(tid)])
if "FAIL" in res:
raise Exception("wlantest_cli command failed")
return int(res)
import binascii
import re
import struct
-import subprocess
import wpaspy
+import remotehost
+import subprocess
logger = logging.getLogger()
wpas_ctrl = '/var/run/wpa_supplicant'
class WpaSupplicant:
- def __init__(self, ifname=None, global_iface=None):
+ def __init__(self, ifname=None, global_iface=None, hostname=None,
+ port=9877, global_port=9878):
+ self.hostname = hostname
self.group_ifname = None
self.gctrl_mon = None
+ self.host = remotehost.Host(hostname, ifname)
+ self._group_dbg = None
if ifname:
- self.set_ifname(ifname)
+ self.set_ifname(ifname, hostname, port)
+ res = self.get_driver_status()
+ if 'capa.flags' in res and int(res['capa.flags'], 0) & 0x20000000:
+ self.p2p_dev_ifname = 'p2p-dev-' + self.ifname
+ else:
+ self.p2p_dev_ifname = ifname
else:
self.ifname = None
self.global_iface = global_iface
if global_iface:
- self.global_ctrl = wpaspy.Ctrl(global_iface)
- self.global_mon = wpaspy.Ctrl(global_iface)
+ if hostname != None:
+ self.global_ctrl = wpaspy.Ctrl(hostname, global_port)
+ self.global_mon = wpaspy.Ctrl(hostname, global_port)
+ self.global_dbg = hostname + "/" + str(global_port) + "/"
+ else:
+ self.global_ctrl = wpaspy.Ctrl(global_iface)
+ self.global_mon = wpaspy.Ctrl(global_iface)
+ self.global_dbg = ""
self.global_mon.attach()
else:
self.global_mon = None
+ def cmd_execute(self, cmd_array, shell=False):
+ if self.hostname is None:
+ if shell:
+ cmd = ' '.join(cmd_array)
+ else:
+ cmd = cmd_array
+ proc = subprocess.Popen(cmd, stderr=subprocess.STDOUT,
+ stdout=subprocess.PIPE, shell=shell)
+ out = proc.communicate()[0]
+ ret = proc.returncode
+ return ret, out
+ else:
+ return self.host.execute(cmd_array)
+
+ def terminate(self):
+ if self.global_mon:
+ self.global_mon.detach()
+ self.global_mon = None
+ self.global_ctrl.terminate()
+ self.global_ctrl = None
+
def close_ctrl(self):
if self.global_mon:
self.global_mon.detach()
self.global_ctrl = None
self.remove_ifname()
- def set_ifname(self, ifname):
+ def set_ifname(self, ifname, hostname=None, port=9877):
self.ifname = ifname
- self.ctrl = wpaspy.Ctrl(os.path.join(wpas_ctrl, ifname))
- self.mon = wpaspy.Ctrl(os.path.join(wpas_ctrl, ifname))
+ if hostname != None:
+ self.ctrl = wpaspy.Ctrl(hostname, port)
+ self.mon = wpaspy.Ctrl(hostname, port)
+ self.host = remotehost.Host(hostname, ifname)
+ self.dbg = hostname + "/" + ifname
+ else:
+ self.ctrl = wpaspy.Ctrl(os.path.join(wpas_ctrl, ifname))
+ self.mon = wpaspy.Ctrl(os.path.join(wpas_ctrl, ifname))
+ self.dbg = ifname
self.mon.attach()
def remove_ifname(self):
self.ctrl = None
self.ifname = None
+ def get_ctrl_iface_port(self, ifname):
+ if self.hostname is None:
+ return None
+
+ res = self.global_request("INTERFACES ctrl")
+ lines = res.splitlines()
+ found = False
+ for line in lines:
+ words = line.split()
+ if words[0] == ifname:
+ found = True
+ break
+ if not found:
+ raise Exception("Could not find UDP port for " + ifname)
+ res = line.find("ctrl_iface=udp:")
+ if res == -1:
+ raise Exception("Wrong ctrl_interface format")
+ words = line.split(":")
+ return int(words[1])
+
def interface_add(self, ifname, config="", driver="nl80211",
drv_params=None, br_ifname=None, create=False,
- set_ifname=True, all_params=False):
- try:
- groups = subprocess.check_output(["id"])
- group = "admin" if "(admin)" in groups else "adm"
- except Exception, e:
+ set_ifname=True, all_params=False, if_type=None):
+ status, groups = self.host.execute(["id"])
+ if status != 0:
group = "admin"
+ group = "admin" if "(admin)" in groups else "adm"
cmd = "INTERFACE_ADD " + ifname + "\t" + config + "\t" + driver + "\tDIR=/var/run/wpa_supplicant GROUP=" + group
if drv_params:
cmd = cmd + '\t' + drv_params
if not drv_params:
cmd += '\t'
cmd += '\tcreate'
+ if if_type:
+ cmd += '\t' + if_type
if all_params and not create:
if not br_ifname:
cmd += '\t'
if "FAIL" in self.global_request(cmd):
raise Exception("Failed to add a dynamic wpa_supplicant interface")
if not create and set_ifname:
- self.set_ifname(ifname)
+ port = self.get_ctrl_iface_port(ifname)
+ self.set_ifname(ifname, self.hostname, port)
+ res = self.get_driver_status()
+ if 'capa.flags' in res and int(res['capa.flags'], 0) & 0x20000000:
+ self.p2p_dev_ifname = 'p2p-dev-' + self.ifname
+ else:
+ self.p2p_dev_ifname = ifname
def interface_remove(self, ifname):
self.remove_ifname()
self.global_request("INTERFACE_REMOVE " + ifname)
def request(self, cmd, timeout=10):
- logger.debug(self.ifname + ": CTRL: " + cmd)
+ logger.debug(self.dbg + ": CTRL: " + cmd)
return self.ctrl.request(cmd, timeout=timeout)
def global_request(self, cmd):
if self.global_iface is None:
- self.request(cmd)
+ return self.request(cmd)
else:
ifname = self.ifname or self.global_iface
- logger.debug(ifname + ": CTRL(global): " + cmd)
+ logger.debug(self.global_dbg + ifname + ": CTRL(global): " + cmd)
return self.global_ctrl.request(cmd)
+ @property
+ def group_dbg(self):
+ if self._group_dbg is not None:
+ return self._group_dbg
+ if self.group_ifname is None:
+ raise Exception("Cannot have group_dbg without group_ifname")
+ if self.hostname is None:
+ self._group_dbg = self.group_ifname
+ else:
+ self._group_dbg = self.hostname + "/" + self.group_ifname
+ return self._group_dbg
+
def group_request(self, cmd):
if self.group_ifname and self.group_ifname != self.ifname:
- logger.debug(self.group_ifname + ": CTRL: " + cmd)
- gctrl = wpaspy.Ctrl(os.path.join(wpas_ctrl, self.group_ifname))
+ if self.hostname is None:
+ gctrl = wpaspy.Ctrl(os.path.join(wpas_ctrl, self.group_ifname))
+ else:
+ port = self.get_ctrl_iface_port(self.group_ifname)
+ gctrl = wpaspy.Ctrl(self.hostname, port)
+ logger.debug(self.group_dbg + ": CTRL(group): " + cmd)
return gctrl.request(cmd)
return self.request(cmd)
if not "OK" in res:
logger.info("FLUSH to " + self.ifname + " failed: " + res)
self.global_request("REMOVE_NETWORK all")
- self.global_request("SET p2p_add_cli_chan 0")
- self.global_request("SET p2p_no_go_freq ")
- self.global_request("SET p2p_pref_chan ")
self.global_request("SET p2p_no_group_iface 1")
- self.global_request("SET p2p_go_intent 7")
self.global_request("P2P_FLUSH")
- self.request("SET ignore_old_scan_res 0")
if self.gctrl_mon:
try:
self.gctrl_mon.detach()
if iter == 60:
logger.error(self.ifname + ": Driver scan state did not clear")
print "Trying to clear cfg80211/mac80211 scan state"
- try:
- cmd = ["ifconfig", self.ifname, "down"]
- subprocess.call(cmd)
- except subprocess.CalledProcessError, e:
- logger.info("ifconfig failed: " + str(e.returncode))
- logger.info(e.output)
- try:
- cmd = ["ifconfig", self.ifname, "up"]
- subprocess.call(cmd)
- except subprocess.CalledProcessError, e:
- logger.info("ifconfig failed: " + str(e.returncode))
- logger.info(e.output)
+ status, buf = self.host.execute(["ifconfig", self.ifname, "down"])
+ if status != 0:
+ logger.info("ifconfig failed: " + buf)
+ logger.info(status)
+ status, buf = self.host.execute(["ifconfig", self.ifname, "up"])
+ if status != 0:
+ logger.info("ifconfig failed: " + buf)
+ logger.info(status)
if iter > 0:
# The ongoing scan could have discovered BSSes or P2P peers
logger.info("Run FLUSH again since scan was in progress")
raise Exception("SET_NETWORK failed")
return None
+ def p2pdev_request(self, cmd):
+ return self.global_request("IFNAME=" + self.p2p_dev_ifname + " " + cmd)
+
+ def p2pdev_add_network(self):
+ id = self.p2pdev_request("ADD_NETWORK")
+ if "FAIL" in id:
+ raise Exception("p2pdev ADD_NETWORK failed")
+ return int(id)
+
+ def p2pdev_set_network(self, id, field, value):
+ res = self.p2pdev_request("SET_NETWORK " + str(id) + " " + field + " " + value)
+ if "FAIL" in res:
+ raise Exception("p2pdev SET_NETWORK failed")
+ return None
+
+ def p2pdev_set_network_quoted(self, id, field, value):
+ res = self.p2pdev_request("SET_NETWORK " + str(id) + " " + field + ' "' + value + '"')
+ if "FAIL" in res:
+ raise Exception("p2pdev SET_NETWORK failed")
+ return None
+
def list_networks(self, p2p=False):
if p2p:
res = self.global_request("LIST_NETWORKS")
quoted = [ "realm", "username", "password", "domain", "imsi",
"excluded_ssid", "milenage", "ca_cert", "client_cert",
"private_key", "domain_suffix_match", "provisioning_sp",
- "roaming_partner", "phase1", "phase2" ]
+ "roaming_partner", "phase1", "phase2", "private_key_passwd" ]
for field in quoted:
if field in params:
self.set_cred_quoted(id, field, params[field])
if field in params:
self.set_cred(id, field, params[field])
- return id;
+ return id
def select_network(self, id, freq=None):
if freq:
raise Exception("MESH_GROUP_REMOVE failed")
return None
- def connect_network(self, id, timeout=10):
+ def connect_network(self, id, timeout=None):
+ if timeout is None:
+ timeout = 10 if self.hostname is None else 60
self.dump_monitor()
self.select_network(id)
self.wait_connected(timeout=timeout)
return None
def get_mcc(self):
- mcc = int(self.get_driver_status_field('capa.num_multichan_concurrent'))
- return 1 if mcc < 2 else mcc
+ mcc = int(self.get_driver_status_field('capa.num_multichan_concurrent'))
+ return 1 if mcc < 2 else mcc
def get_mib(self):
res = self.request("MIB")
def p2p_listen(self):
return self.global_request("P2P_LISTEN")
+ def p2p_ext_listen(self, period, interval):
+ return self.global_request("P2P_EXT_LISTEN %d %d" % (period, interval))
+
+ def p2p_cancel_ext_listen(self):
+ return self.global_request("P2P_EXT_LISTEN")
+
def p2p_find(self, social=False, progressive=False, dev_id=None,
dev_type=None, delay=None, freq=None):
cmd = "P2P_FIND"
return True
return "[PROBE_REQ_ONLY]" not in res
- def discover_peer(self, peer, full=True, timeout=15, social=True, force_find=False):
+ def discover_peer(self, peer, full=True, timeout=15, social=True,
+ force_find=False, freq=None):
logger.info(self.ifname + ": Trying to discover peer " + peer)
if not force_find and self.peer_known(peer, full):
return True
- self.p2p_find(social)
+ self.p2p_find(social, freq=freq)
count = 0
while count < timeout * 4:
time.sleep(0.25)
res['ifname'] = s[2]
self.group_ifname = s[2]
try:
- self.gctrl_mon = wpaspy.Ctrl(os.path.join(wpas_ctrl, self.group_ifname))
+ if self.hostname is None:
+ self.gctrl_mon = wpaspy.Ctrl(os.path.join(wpas_ctrl,
+ self.group_ifname))
+ else:
+ port = self.get_ctrl_iface_port(self.group_ifname)
+ self.gctrl_mon = wpaspy.Ctrl(self.hostname, port)
self.gctrl_mon.attach()
except:
logger.debug("Could not open monitor socket for group interface")
return res
- def p2p_go_neg_auth(self, peer, pin, method, go_intent=None, persistent=False, freq=None):
+ def p2p_go_neg_auth(self, peer, pin, method, go_intent=None,
+ persistent=False, freq=None, freq2=None,
+ max_oper_chwidth=None, ht40=False, vht=False):
if not self.discover_peer(peer):
raise Exception("Peer " + peer + " not found")
self.dump_monitor()
cmd = cmd + ' go_intent=' + str(go_intent)
if freq:
cmd = cmd + ' freq=' + str(freq)
+ if freq2:
+ cmd = cmd + ' freq2=' + str(freq2)
+ if max_oper_chwidth:
+ cmd = cmd + ' max_oper_chwidth=' + str(max_oper_chwidth)
+ if ht40:
+ cmd = cmd + ' ht40'
+ if vht:
+ cmd = cmd + ' vht'
if persistent:
cmd = cmd + " persistent"
if "OK" in self.global_request(cmd):
def p2p_go_neg_auth_result(self, timeout=1, expect_failure=False):
go_neg_res = None
ev = self.wait_global_event(["P2P-GO-NEG-SUCCESS",
- "P2P-GO-NEG-FAILURE"], timeout);
+ "P2P-GO-NEG-FAILURE"], timeout)
if ev is None:
if expect_failure:
return None
raise Exception("Group formation timed out")
if "P2P-GO-NEG-SUCCESS" in ev:
go_neg_res = ev
- ev = self.wait_global_event(["P2P-GROUP-STARTED"], timeout);
+ ev = self.wait_global_event(["P2P-GROUP-STARTED"], timeout)
if ev is None:
if expect_failure:
return None
self.dump_monitor()
return self.group_form_result(ev, expect_failure, go_neg_res)
- def p2p_go_neg_init(self, peer, pin, method, timeout=0, go_intent=None, expect_failure=False, persistent=False, persistent_id=None, freq=None, provdisc=False, wait_group=True):
+ def p2p_go_neg_init(self, peer, pin, method, timeout=0, go_intent=None,
+ expect_failure=False, persistent=False,
+ persistent_id=None, freq=None, provdisc=False,
+ wait_group=True, freq2=None, max_oper_chwidth=None,
+ ht40=False, vht=False):
if not self.discover_peer(peer):
raise Exception("Peer " + peer + " not found")
self.dump_monitor()
cmd = "P2P_CONNECT " + peer + " " + pin + " " + method
else:
cmd = "P2P_CONNECT " + peer + " " + method
- if go_intent:
+ if go_intent is not None:
cmd = cmd + ' go_intent=' + str(go_intent)
if freq:
cmd = cmd + ' freq=' + str(freq)
+ if freq2:
+ cmd = cmd + ' freq2=' + str(freq2)
+ if max_oper_chwidth:
+ cmd = cmd + ' max_oper_chwidth=' + str(max_oper_chwidth)
+ if ht40:
+ cmd = cmd + ' ht40'
+ if vht:
+ cmd = cmd + ' vht'
if persistent:
cmd = cmd + " persistent"
elif persistent_id:
cmd = cmd + " provdisc"
if "OK" in self.global_request(cmd):
if timeout == 0:
- self.dump_monitor()
return None
go_neg_res = None
ev = self.wait_global_event(["P2P-GO-NEG-SUCCESS",
while True:
while self.mon.pending():
ev = self.mon.recv()
- logger.debug(self.ifname + ": " + ev)
+ logger.debug(self.dbg + ": " + ev)
for event in events:
if event in ev:
return ev
while True:
while self.global_mon.pending():
ev = self.global_mon.recv()
- logger.debug(self.ifname + "(global): " + ev)
+ logger.debug(self.global_dbg + self.ifname + "(global): " + ev)
for event in events:
if event in ev:
return ev
while True:
while self.gctrl_mon.pending():
ev = self.gctrl_mon.recv()
- logger.debug(self.group_ifname + ": " + ev)
+ logger.debug(self.group_dbg + "(group): " + ev)
for event in events:
if event in ev:
return ev
except:
pass
self.gctrl_mon = None
- ev = self.wait_global_event(["P2P-GROUP-REMOVED"], timeout=3)
+ timeout = 3 if self.hostname is None else 10
+ ev = self.wait_global_event(["P2P-GROUP-REMOVED"], timeout=timeout)
if ev is None:
raise Exception("Group removal event timed out")
if "reason=GO_ENDING_SESSION" not in ev:
raise Exception("Unexpected group removal reason")
def dump_monitor(self):
+ count_iface = 0
+ count_global = 0
while self.mon.pending():
ev = self.mon.recv()
- logger.debug(self.ifname + ": " + ev)
+ logger.debug(self.dbg + ": " + ev)
+ count_iface += 1
while self.global_mon and self.global_mon.pending():
ev = self.global_mon.recv()
- logger.debug(self.ifname + "(global): " + ev)
+ logger.debug(self.global_dbg + self.ifname + "(global): " + ev)
+ count_global += 1
+ return (count_iface, count_global)
def remove_group(self, ifname=None):
if self.gctrl_mon:
def p2p_connect_group(self, go_addr, pin, timeout=0, social=False,
freq=None):
self.dump_monitor()
- if not self.discover_peer(go_addr, social=social):
+ if not self.discover_peer(go_addr, social=social, freq=freq):
if social or not self.discover_peer(go_addr, social=social):
raise Exception("GO " + go_addr + " not found")
+ self.p2p_stop_find()
self.dump_monitor()
cmd = "P2P_CONNECT " + go_addr + " " + pin + " join"
if freq:
if timeout == 0:
self.dump_monitor()
return None
- ev = self.wait_global_event(["P2P-GROUP-STARTED"], timeout)
+ ev = self.wait_global_event(["P2P-GROUP-STARTED",
+ "P2P-GROUP-FORMATION-FAILURE"],
+ timeout)
if ev is None:
raise Exception("Joining the group timed out")
+ if "P2P-GROUP-STARTED" not in ev:
+ raise Exception("Failed to join the group")
self.dump_monitor()
return self.group_form_result(ev)
raise Exception("P2P_CONNECT(join) failed")
"disable_ht40", "disable_sgi", "disable_ldpc",
"ht40_intolerant", "update_identifier", "mac_addr",
"erp", "bg_scan_period", "bssid_blacklist",
- "bssid_whitelist", "mem_only_psk", "eap_workaround" ]
+ "bssid_whitelist", "mem_only_psk", "eap_workaround",
+ "engine" ]
for field in not_quoted:
if field in kwargs and kwargs[field]:
self.set_network(id, field, kwargs[field])
return res.split(' ')
def get_bss(self, bssid, ifname=None):
- if not ifname or ifname == self.ifname:
+ if not ifname or ifname == self.ifname:
res = self.request("BSS " + bssid)
elif ifname == self.group_ifname:
res = self.group_request("BSS " + bssid)
if field != "freq":
raise Exception("Unexpected MGMT-RX event format: " + ev)
msg['freq'] = val
+
+ field,val = items[2].split('=')
+ if field != "datarate":
+ raise Exception("Unexpected MGMT-RX event format: " + ev)
+ msg['datarate'] = val
+
+ field,val = items[3].split('=')
+ if field != "ssi_signal":
+ raise Exception("Unexpected MGMT-RX event format: " + ev)
+ msg['ssi_signal'] = val
+
frame = binascii.unhexlify(items[4])
msg['frame'] = frame
raise Exception(error)
return ev
- def wait_disconnected(self, timeout=10, error="Disconnection timed out"):
+ def wait_disconnected(self, timeout=None, error="Disconnection timed out"):
+ if timeout is None:
+ timeout = 10 if self.hostname is None else 30
ev = self.wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=timeout)
if ev is None:
raise Exception(error)
return vals
def asp_provision(self, peer, adv_id, adv_mac, session_id, session_mac,
- method="1000", info="", status=None, cpt=None):
+ method="1000", info="", status=None, cpt=None, role=None):
if status is None:
cmd = "P2P_ASP_PROVISION"
params = "info='%s' method=%s" % (info, method)
cmd = "P2P_ASP_PROVISION_RESP"
params = "status=%d" % status
+ if role is not None:
+ params += " role=" + role
if cpt is not None:
params += " cpt=" + cpt
struct ieee80211_hdr *hdr;
size_t plen;
- plen = len + igtk_len == 32 ? 26 : 18;
+ plen = len + (igtk_len == 32 ? 26 : 18);
prot = os_malloc(plen);
if (prot == NULL)
return NULL;
}
+static void ccmp_aad_nonce_pv1(const u8 *hdr, const u8 *a1, const u8 *a2,
+ const u8 *a3, const u8 *pn,
+ u8 *aad, size_t *aad_len, u8 *nonce)
+{
+ u16 fc, type;
+ u8 *pos;
+
+ nonce[0] = BIT(5); /* PV1 */
+ /* TODO: Priority for QMF; 0 is used for Data frames */
+
+ fc = WPA_GET_LE16(hdr);
+ type = (fc & (BIT(2) | BIT(3) | BIT(4))) >> 2;
+
+ if (type == 1)
+ nonce[0] |= 0x10; /* Management */
+
+ fc &= ~(BIT(10) | BIT(11) | BIT(13) | BIT(14) | BIT(15));
+ fc |= BIT(12);
+ WPA_PUT_LE16(aad, fc);
+ pos = aad + 2;
+ if (type == 0 || type == 3) {
+ const u8 *sc;
+
+ os_memcpy(pos, a1, ETH_ALEN);
+ pos += ETH_ALEN;
+ os_memcpy(pos, a2, ETH_ALEN);
+ pos += ETH_ALEN;
+
+ if (type == 0) {
+ /* Either A1 or A2 contains SID */
+ sc = hdr + 2 + 2 + ETH_ALEN;
+ } else {
+ /* Both A1 and A2 contain full addresses */
+ sc = hdr + 2 + 2 * ETH_ALEN;
+ }
+ /* SC with Sequence Number subfield (bits 4-15 of the Sequence
+ * Control field) masked to 0. */
+ *pos++ = *sc & 0x0f;
+ *pos++ = 0;
+
+ if (a3) {
+ os_memcpy(pos, a3, ETH_ALEN);
+ pos += ETH_ALEN;
+ }
+ }
+
+ *aad_len = pos - aad;
+
+ os_memcpy(nonce + 1, a2, ETH_ALEN);
+ nonce[7] = pn[5]; /* PN5 */
+ nonce[8] = pn[4]; /* PN4 */
+ nonce[9] = pn[3]; /* PN3 */
+ nonce[10] = pn[2]; /* PN2 */
+ nonce[11] = pn[1]; /* PN1 */
+ nonce[12] = pn[0]; /* PN0 */
+}
+
+
u8 * ccmp_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr,
const u8 *data, size_t data_len, size_t *decrypted_len)
{
}
+u8 * ccmp_encrypt_pv1(const u8 *tk, const u8 *a1, const u8 *a2, const u8 *a3,
+ const u8 *frame, size_t len,
+ size_t hdrlen, const u8 *pn, int keyid,
+ size_t *encrypted_len)
+{
+ u8 aad[24], nonce[13];
+ size_t aad_len, plen;
+ u8 *crypt, *pos;
+ struct ieee80211_hdr *hdr;
+
+ if (len < hdrlen || hdrlen < 12)
+ return NULL;
+ plen = len - hdrlen;
+
+ crypt = os_malloc(hdrlen + plen + 8 + AES_BLOCK_SIZE);
+ if (crypt == NULL)
+ return NULL;
+
+ os_memcpy(crypt, frame, hdrlen);
+ hdr = (struct ieee80211_hdr *) crypt;
+ hdr->frame_control |= host_to_le16(BIT(12)); /* Protected Frame */
+ pos = crypt + hdrlen;
+
+ os_memset(aad, 0, sizeof(aad));
+ ccmp_aad_nonce_pv1(crypt, a1, a2, a3, pn, aad, &aad_len, nonce);
+ wpa_hexdump(MSG_EXCESSIVE, "CCMP AAD", aad, aad_len);
+ wpa_hexdump(MSG_EXCESSIVE, "CCMP nonce", nonce, sizeof(nonce));
+
+ if (aes_ccm_ae(tk, 16, nonce, 8, frame + hdrlen, plen, aad, aad_len,
+ pos, pos + plen) < 0) {
+ os_free(crypt);
+ return NULL;
+ }
+
+ wpa_hexdump(MSG_EXCESSIVE, "CCMP encrypted", crypt + hdrlen, plen);
+
+ *encrypted_len = hdrlen + plen + 8;
+
+ return crypt;
+}
+
+
u8 * ccmp_256_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr,
const u8 *data, size_t data_len, size_t *decrypted_len)
{
write_pcap_with_radiotap(wt, data, hdr->caplen);
else
pcap_dump(wt->write_pcap_dumper, hdr, data);
+ if (wt->pcap_no_buffer)
+ pcap_dump_flush(wt->write_pcap_dumper);
}
if (hdr->caplen < hdr->len) {
add_note(wt, MSG_DEBUG, "pcap: Dropped incomplete "
*/
#include "utils/includes.h"
-#include <linux/if_ether.h>
#include "utils/common.h"
#include "common/defs.h"
#include "utils/common.h"
#include "utils/eloop.h"
+#include "common/ieee802_11_defs.h"
#include "wlantest.h"
}
+static void test_vector_ccmp_pv1(void)
+{
+ u8 tk[] = { 0xc9, 0x7c, 0x1f, 0x67, 0xce, 0x37, 0x11, 0x85,
+ 0x51, 0x4a, 0x8a, 0x19, 0xf2, 0xbd, 0xd5, 0x2f };
+ u8 pn[8];
+ u8 frame1[] = {
+ 0x61, 0x00, 0xa2, 0xae, 0xa5, 0xb8, 0xfc, 0xba,
+ 0x07, 0x00, 0x80, 0x33,
+ 0xf8, 0xba, 0x1a, 0x55, 0xd0, 0x2f, 0x85, 0xae,
+ 0x96, 0x7b, 0xb6, 0x2f, 0xb6, 0xcd, 0xa8, 0xeb,
+ 0x7e, 0x78, 0xa0, 0x50
+ };
+ u8 frame2[] = {
+ 0x61, 0x00, 0xa2, 0xae, 0xa5, 0xb8, 0xfc, 0xba,
+ 0x07, 0x20, 0x80, 0x33, 0x02, 0xd2, 0xe1, 0x28,
+ 0xa5, 0x7c,
+ 0xf8, 0xba, 0x1a, 0x55, 0xd0, 0x2f, 0x85, 0xae,
+ 0x96, 0x7b, 0xb6, 0x2f, 0xb6, 0xcd, 0xa8, 0xeb,
+ 0x7e, 0x78, 0xa0, 0x50
+ };
+ u8 frame3[] = {
+ 0x6d, 0x00, 0xa2, 0xae, 0xa5, 0xb8, 0xfc, 0xba,
+ 0x52, 0x30, 0xf1, 0x84, 0x44, 0x08, 0x80, 0x33,
+ 0xf8, 0xba, 0x1a, 0x55, 0xd0, 0x2f, 0x85, 0xae,
+ 0x96, 0x7b, 0xb6, 0x2f, 0xb6, 0xcd, 0xa8, 0xeb,
+ 0x7e, 0x78, 0xa0, 0x50
+ };
+ u8 *enc;
+ size_t enc_len;
+ u8 fcs[4];
+ u8 bssid[ETH_ALEN] = { 0xa2, 0xae, 0xa5, 0xb8, 0xfc, 0xba };
+ u8 da[ETH_ALEN] = { 0x02, 0xd2, 0xe1, 0x28, 0xa5, 0x7c };
+ u8 sa[ETH_ALEN] = { 0x52, 0x30, 0xf1, 0x84, 0x44, 0x08 };
+ u16 aid = 7;
+ u32 bpn = 123;
+ u16 sc = 0x3380;
+ int key_id = 0;
+ u16 fc;
+ int tid = 3;
+ u16 sid;
+
+ wpa_printf(MSG_INFO,
+ "\nIEEE P802.11ah/D10.0, J.6.4 CCMP PV1 test vectors\n");
+
+ wpa_printf(MSG_INFO, "BSSID: " MACSTR, MAC2STR(bssid));
+ wpa_printf(MSG_INFO, "DA: " MACSTR, MAC2STR(da));
+ wpa_printf(MSG_INFO, "SA: " MACSTR, MAC2STR(sa));
+ wpa_printf(MSG_INFO, "Association ID: %u", aid);
+ wpa_printf(MSG_INFO, "Base PN: %u (0x%08x)", bpn, bpn);
+ wpa_printf(MSG_INFO, "SC = 0x%04x (FragNum=%u SeqNum=%u)",
+ sc, WLAN_GET_SEQ_FRAG(sc), WLAN_GET_SEQ_SEQ(sc));
+ wpa_printf(MSG_INFO, "TID = %u", tid);
+ wpa_printf(MSG_INFO, "Key ID: %u", key_id);
+ wpa_hexdump(MSG_INFO, "TK", tk, sizeof(tk));
+ wpa_printf(MSG_INFO, "PN = SC||BPN");
+ WPA_PUT_LE16(&pn[0], sc);
+ WPA_PUT_LE32(&pn[2], bpn);
+ wpa_hexdump(MSG_INFO, "PN (PN0..PN5)", pn, sizeof(pn));
+
+ wpa_printf(MSG_INFO,
+ "\nPV1 test vector #1:\nHeader compression used and A3 was previously stored at the receiver\n");
+ fc = WPA_GET_LE16(frame1);
+ wpa_printf(MSG_INFO,
+ "FC=0x%04x (PV=%u Type=%u PTID/Subtype=%u From_DS=%u More_Fragments=%u Power_Management=%u More_Data=%u Protected_Frame=%u End_of_SP=%u Relayed_Frame=%u Ack_Policy=%u)",
+ fc,
+ fc & WLAN_FC_PVER,
+ (fc & (BIT(2) | BIT(3) | BIT(4))) >> 2,
+ (fc & (BIT(5) | BIT(6) | BIT(7))) >> 5,
+ !!(fc & BIT(8)),
+ !!(fc & BIT(9)),
+ !!(fc & BIT(10)),
+ !!(fc & BIT(11)),
+ !!(fc & BIT(12)),
+ !!(fc & BIT(13)),
+ !!(fc & BIT(14)),
+ !!(fc & BIT(15)));
+ wpa_printf(MSG_INFO, "A1=" MACSTR, MAC2STR(&frame1[2]));
+ sid = WPA_GET_LE16(&frame1[8]);
+ wpa_printf(MSG_INFO,
+ "A2=%02x %02x (SID: AID=%u A3_Present=%u A4_Present=%u A-MSDU=%u); corresponds to 52:30:f1:84:44:08 in uncompressed header",
+ frame1[8], frame1[9],
+ sid & ~(BIT(13) | BIT(14) | BIT(15)),
+ !!(sid & BIT(13)),
+ !!(sid & BIT(14)),
+ !!(sid & BIT(15)));
+ sc = WPA_GET_LE16(&frame1[10]);
+ wpa_printf(MSG_INFO, "Sequence Control: %02x %02x (FN=%u SN=%u)",
+ frame1[10], frame1[11],
+ WLAN_GET_SEQ_FRAG(sc), WLAN_GET_SEQ_SEQ(sc));
+ wpa_printf(MSG_INFO, "A3 not present; corresponds to 02:d2:e1:28:a5:7c in uncompressed header");
+ wpa_printf(MSG_INFO, "A4 not present");
+ wpa_hexdump(MSG_INFO, "Plaintext Frame Header", frame1, 12);
+ wpa_hexdump(MSG_INFO, "Plaintext Frame Body",
+ frame1 + 12, sizeof(frame1) - 12);
+
+ enc = ccmp_encrypt_pv1(tk, &frame1[2], sa, da, frame1, sizeof(frame1),
+ 12, pn, key_id, &enc_len);
+ if (enc == NULL) {
+ wpa_printf(MSG_ERROR, "Failed to encrypt CCMP frame");
+ return;
+ }
+
+ wpa_hexdump(MSG_INFO, "Encrypted Frame Header", enc, 12);
+ wpa_hexdump(MSG_INFO, "Encrypted Frame Frame Body",
+ enc + 12, enc_len - 12);
+ WPA_PUT_LE32(fcs, crc32(enc, enc_len));
+ wpa_hexdump(MSG_INFO, "Encrypted Frame FCS", fcs, sizeof(fcs));
+
+ wpa_printf(MSG_INFO,
+ "\nPV1 test vector #2:\nHeader compression used and A3 was not previously stored at the receiver\n");
+ fc = WPA_GET_LE16(frame2);
+ wpa_printf(MSG_INFO,
+ "FC=0x%04x (PV=%u Type=%u PTID/Subtype=%u From_DS=%u More_Fragments=%u Power_Management=%u More_Data=%u Protected_Frame=%u End_of_SP=%u Relayed_Frame=%u Ack_Policy=%u)",
+ fc,
+ fc & WLAN_FC_PVER,
+ (fc & (BIT(2) | BIT(3) | BIT(4))) >> 2,
+ (fc & (BIT(5) | BIT(6) | BIT(7))) >> 5,
+ !!(fc & BIT(8)),
+ !!(fc & BIT(9)),
+ !!(fc & BIT(10)),
+ !!(fc & BIT(11)),
+ !!(fc & BIT(12)),
+ !!(fc & BIT(13)),
+ !!(fc & BIT(14)),
+ !!(fc & BIT(15)));
+ wpa_printf(MSG_INFO, "A1=" MACSTR, MAC2STR(&frame2[2]));
+ sid = WPA_GET_LE16(&frame2[8]);
+ wpa_printf(MSG_INFO,
+ "A2=%02x %02x (SID: AID=%u A3_Present=%u A4_Present=%u A-MSDU=%u); corresponds to 52:30:f1:84:44:08 in uncompressed header",
+ frame2[8], frame2[9],
+ sid & ~(BIT(13) | BIT(14) | BIT(15)),
+ !!(sid & BIT(13)),
+ !!(sid & BIT(14)),
+ !!(sid & BIT(15)));
+ sc = WPA_GET_LE16(&frame2[10]);
+ wpa_printf(MSG_INFO, "Sequence Control: %02x %02x (FN=%u SN=%u)",
+ frame2[10], frame2[11],
+ WLAN_GET_SEQ_FRAG(sc), WLAN_GET_SEQ_SEQ(sc));
+ wpa_printf(MSG_INFO, "A3=" MACSTR, MAC2STR(&frame2[12]));
+ wpa_printf(MSG_INFO, "A4 not present");
+ wpa_hexdump(MSG_INFO, "Plaintext Frame Header", frame2, 18);
+ wpa_hexdump(MSG_INFO, "Plaintext Frame Body",
+ frame2 + 18, sizeof(frame2) - 18);
+
+ enc = ccmp_encrypt_pv1(tk, &frame2[2], sa, &frame2[12],
+ frame2, sizeof(frame2), 18, pn, key_id,
+ &enc_len);
+ if (enc == NULL) {
+ wpa_printf(MSG_ERROR, "Failed to encrypt CCMP frame");
+ return;
+ }
+
+ wpa_hexdump(MSG_INFO, "Encrypted Frame Header", enc, 18);
+ wpa_hexdump(MSG_INFO, "Encrypted Frame Frame Body",
+ enc + 18, enc_len - 18);
+ WPA_PUT_LE32(fcs, crc32(enc, enc_len));
+ wpa_hexdump(MSG_INFO, "Encrypted Frame FCS", fcs, sizeof(fcs));
+
+ wpa_printf(MSG_INFO,
+ "\nPV1 test vector #3:\nType 3 frame from SA to DA(=BSSID) (i.e., no separate DA in this example)\n");
+ fc = WPA_GET_LE16(frame3);
+ wpa_printf(MSG_INFO,
+ "FC=0x%04x (PV=%u Type=%u PTID/Subtype=%u From_DS=%u More_Fragments=%u Power_Management=%u More_Data=%u Protected_Frame=%u End_of_SP=%u Relayed_Frame=%u Ack_Policy=%u)",
+ fc,
+ fc & WLAN_FC_PVER,
+ (fc & (BIT(2) | BIT(3) | BIT(4))) >> 2,
+ (fc & (BIT(5) | BIT(6) | BIT(7))) >> 5,
+ !!(fc & BIT(8)),
+ !!(fc & BIT(9)),
+ !!(fc & BIT(10)),
+ !!(fc & BIT(11)),
+ !!(fc & BIT(12)),
+ !!(fc & BIT(13)),
+ !!(fc & BIT(14)),
+ !!(fc & BIT(15)));
+ wpa_printf(MSG_INFO, "A1=" MACSTR, MAC2STR(&frame3[2]));
+ wpa_printf(MSG_INFO, "A2=" MACSTR, MAC2STR(&frame3[8]));
+ sc = WPA_GET_LE16(&frame3[14]);
+ wpa_printf(MSG_INFO, "Sequence Control: %02x %02x (FN=%u SN=%u)",
+ frame3[14], frame3[15],
+ WLAN_GET_SEQ_FRAG(sc), WLAN_GET_SEQ_SEQ(sc));
+ wpa_printf(MSG_INFO,
+ "A3 not present; corresponds to 02:d2:e1:28:a5:7c in uncompressed header");
+ wpa_printf(MSG_INFO, "A4 not present");
+ wpa_hexdump(MSG_INFO, "Plaintext Frame Header", frame3, 16);
+ wpa_hexdump(MSG_INFO, "Plaintext Frame Body",
+ frame3 + 16, sizeof(frame3) - 16);
+
+ enc = ccmp_encrypt_pv1(tk, &frame3[2], &frame3[8], da,
+ frame3, sizeof(frame3), 16, pn, key_id,
+ &enc_len);
+ if (enc == NULL) {
+ wpa_printf(MSG_ERROR, "Failed to encrypt CCMP frame");
+ return;
+ }
+
+ wpa_hexdump(MSG_INFO, "Encrypted Frame Header", enc, 16);
+ wpa_hexdump(MSG_INFO, "Encrypted Frame Frame Body",
+ enc + 16, enc_len - 16);
+ WPA_PUT_LE32(fcs, crc32(enc, enc_len));
+ wpa_hexdump(MSG_INFO, "Encrypted Frame FCS", fcs, sizeof(fcs));
+
+ wpa_debug_level = MSG_INFO;
+}
+
+
static void test_vector_bip(void)
{
u8 igtk[] = {
test_vector_tkip();
test_vector_ccmp();
+ test_vector_ccmp_pv1();
test_vector_bip();
test_vector_ccmp_mgmt();
errors += test_vector_gcmp();
static void usage(void)
{
- printf("wlantest [-cddhqqFt] [-i<ifname>] [-r<pcap file>] "
+ printf("wlantest [-cddhqqFNt] [-i<ifname>] [-r<pcap file>] "
"[-p<passphrase>]\n"
" [-I<wired ifname>] [-R<wired pcap file>] "
"[-P<RADIUS shared secret>]\n"
wlantest_init(&wt);
for (;;) {
- c = getopt(argc, argv, "cdf:Fhi:I:L:n:p:P:qr:R:tT:w:W:");
+ c = getopt(argc, argv, "cdf:Fhi:I:L:n:Np:P:qr:R:tT:w:W:");
if (c < 0)
break;
switch (c) {
case 'n':
wt.pcapng_file = optarg;
break;
+ case 'N':
+ wt.pcap_no_buffer = 1;
+ break;
case 'p':
add_passphrase(&wt, optarg);
break;
int last_mgmt_valid;
unsigned int assume_fcs:1;
+ unsigned int pcap_no_buffer:1;
char *notes[MAX_NOTES];
size_t num_notes;
const u8 *data, size_t data_len, size_t *decrypted_len);
u8 * ccmp_encrypt(const u8 *tk, u8 *frame, size_t len, size_t hdrlen, u8 *qos,
u8 *pn, int keyid, size_t *encrypted_len);
+u8 * ccmp_encrypt_pv1(const u8 *tk, const u8 *a1, const u8 *a2, const u8 *a3,
+ const u8 *frame, size_t len,
+ size_t hdrlen, const u8 *pn, int keyid,
+ size_t *encrypted_len);
void ccmp_get_pn(u8 *pn, const u8 *data);
u8 * ccmp_256_decrypt(const u8 *tk, const struct ieee80211_hdr *hdr,
const u8 *data, size_t data_len, size_t *decrypted_len);
h.caplen = len;
h.len = len;
pcap_dump(wt->write_pcap_dumper, &h, buf);
+ if (wt->pcap_no_buffer)
+ pcap_dump_flush(wt->write_pcap_dumper);
}
h.caplen = len;
h.len = len;
pcap_dump(wt->write_pcap_dumper, &h, buf);
+ if (wt->pcap_no_buffer)
+ pcap_dump_flush(wt->write_pcap_dumper);
}
desc.link_type = LINKTYPE_IEEE802_11_RADIO;
desc.snap_len = 65535;
fwrite(&desc, sizeof(desc), 1, wt->pcapng);
+ if (wt->pcap_no_buffer)
+ fflush(wt->pcapng);
return 0;
}
*block_len = pkt->block_total_len = pos - (u8 *) pkt;
fwrite(pkt, pos - (u8 *) pkt, 1, wt->pcapng);
+ if (wt->pcap_no_buffer)
+ fflush(wt->pcapng);
os_free(pkt);
}
*block_len = pkt->block_total_len = pos - (u8 *) pkt;
fwrite(pkt, pos - (u8 *) pkt, 1, wt->pcapng);
+ if (wt->pcap_no_buffer)
+ fflush(wt->pcapng);
os_free(pkt);
L_CFLAGS += -mabi=aapcs-linux
endif
+# C++ flags for binder interface
+L_CPPFLAGS := -std=c++11 -Wall -Werror
+# TODO: Remove these allowed warnings later.
+L_CPPFLAGS += -Wno-unused-variable -Wno-unused-parameter
+L_CPPFLAGS += -Wno-unused-private-field
+
INCLUDES = $(LOCAL_PATH)
INCLUDES += $(LOCAL_PATH)/src
INCLUDES += $(LOCAL_PATH)/src/common
INCLUDES += $(LOCAL_PATH)/src/tls
INCLUDES += $(LOCAL_PATH)/src/utils
INCLUDES += $(LOCAL_PATH)/src/wps
-INCLUDES += external/openssl/include
INCLUDES += system/security/keystore/include
ifdef CONFIG_DRIVER_NL80211
ifneq ($(wildcard external/libnl),)
OBJS_c = wpa_cli.c src/common/wpa_ctrl.c
OBJS_c += src/utils/wpa_debug.c
OBJS_c += src/utils/common.c
+OBJS_c += src/common/cli.c
OBJS_d =
OBJS_priv =
ifdef CONFIG_IBSS_RSN
NEED_RSN_AUTHENTICATOR=y
L_CFLAGS += -DCONFIG_IBSS_RSN
+L_CFLAGS += -DCONFIG_NO_VLAN
OBJS += ibss_rsn.c
endif
else
L_CFLAGS += -DEAP_TLS
OBJS += src/eap_peer/eap_tls.c
-OBJS_h += src/eap_server/eap_server_tls.c
endif
TLS_FUNCS=y
CONFIG_IEEE8021X_EAPOL=y
L_CFLAGS += -DEAP_UNAUTH_TLS
ifndef CONFIG_EAP_TLS
OBJS += src/eap_peer/eap_tls.c
-OBJS_h += src/eap_server/eap_server_tls.c
TLS_FUNCS=y
endif
CONFIG_IEEE8021X_EAPOL=y
L_CFLAGS += -DEAP_PEAP
OBJS += src/eap_peer/eap_peap.c
OBJS += src/eap_common/eap_peap_common.c
-OBJS_h += src/eap_server/eap_server_peap.c
endif
TLS_FUNCS=y
CONFIG_IEEE8021X_EAPOL=y
else
L_CFLAGS += -DEAP_TTLS
OBJS += src/eap_peer/eap_ttls.c
-OBJS_h += src/eap_server/eap_server_ttls.c
endif
TLS_FUNCS=y
ifndef CONFIG_FIPS
else
L_CFLAGS += -DEAP_MD5
OBJS += src/eap_peer/eap_md5.c
-OBJS_h += src/eap_server/eap_server_md5.c
endif
CHAP=y
CONFIG_IEEE8021X_EAPOL=y
L_CFLAGS += -DEAP_MSCHAPv2
OBJS += src/eap_peer/eap_mschapv2.c
OBJS += src/eap_peer/mschapv2.c
-OBJS_h += src/eap_server/eap_server_mschapv2.c
endif
MS_FUNCS=y
CONFIG_IEEE8021X_EAPOL=y
else
L_CFLAGS += -DEAP_GTC
OBJS += src/eap_peer/eap_gtc.c
-OBJS_h += src/eap_server/eap_server_gtc.c
endif
CONFIG_IEEE8021X_EAPOL=y
endif
else
L_CFLAGS += -DEAP_SIM
OBJS += src/eap_peer/eap_sim.c
-OBJS_h += src/eap_server/eap_server_sim.c
endif
CONFIG_IEEE8021X_EAPOL=y
CONFIG_EAP_SIM_COMMON=y
else
L_CFLAGS += -DEAP_PSK
OBJS += src/eap_peer/eap_psk.c src/eap_common/eap_psk_common.c
-OBJS_h += src/eap_server/eap_server_psk.c
endif
CONFIG_IEEE8021X_EAPOL=y
NEED_AES=y
else
L_CFLAGS += -DEAP_AKA
OBJS += src/eap_peer/eap_aka.c
-OBJS_h += src/eap_server/eap_server_aka.c
endif
CONFIG_IEEE8021X_EAPOL=y
CONFIG_EAP_SIM_COMMON=y
ifdef CONFIG_EAP_SIM_COMMON
OBJS += src/eap_common/eap_sim_common.c
-OBJS_h += src/eap_server/eap_sim_db.c
NEED_AES=y
NEED_FIPS186_2_PRF=y
endif
L_CFLAGS += -DEAP_FAST
OBJS += src/eap_peer/eap_fast.c src/eap_peer/eap_fast_pac.c
OBJS += src/eap_common/eap_fast_common.c
-OBJS_h += src/eap_server/eap_server_fast.c
endif
TLS_FUNCS=y
CONFIG_IEEE8021X_EAPOL=y
else
L_CFLAGS += -DEAP_PAX
OBJS += src/eap_peer/eap_pax.c src/eap_common/eap_pax_common.c
-OBJS_h += src/eap_server/eap_server_pax.c
endif
CONFIG_IEEE8021X_EAPOL=y
endif
else
L_CFLAGS += -DEAP_SAKE
OBJS += src/eap_peer/eap_sake.c src/eap_common/eap_sake_common.c
-OBJS_h += src/eap_server/eap_server_sake.c
endif
CONFIG_IEEE8021X_EAPOL=y
endif
else
L_CFLAGS += -DEAP_GPSK
OBJS += src/eap_peer/eap_gpsk.c src/eap_common/eap_gpsk_common.c
-OBJS_h += src/eap_server/eap_server_gpsk.c
endif
CONFIG_IEEE8021X_EAPOL=y
ifdef CONFIG_EAP_GPSK_SHA256
ifdef CONFIG_EAP_PWD
L_CFLAGS += -DEAP_PWD
OBJS += src/eap_peer/eap_pwd.c src/eap_common/eap_pwd_common.c
-OBJS_h += src/eap_server/eap_server_pwd.c
CONFIG_IEEE8021X_EAPOL=y
NEED_SHA256=y
endif
else
L_CFLAGS += -DEAP_EKE
OBJS += src/eap_peer/eap_eke.c src/eap_common/eap_eke_common.c
-OBJS_h += src/eap_server/eap_server_eke.c
endif
CONFIG_IEEE8021X_EAPOL=y
NEED_DH_GROUPS=y
OBJS += src/wps/wps_dev_attr.c
OBJS += src/wps/wps_enrollee.c
OBJS += src/wps/wps_registrar.c
-OBJS_h += src/eap_server/eap_server_wsc.c
CONFIG_IEEE8021X_EAPOL=y
NEED_DH_GROUPS=y
NEED_SHA256=y
L_CFLAGS += -DEAP_IKEV2
OBJS += src/eap_peer/eap_ikev2.c src/eap_peer/ikev2.c
OBJS += src/eap_common/eap_ikev2_common.c src/eap_common/ikev2_common.c
-OBJS_h += src/eap_server/eap_server_ikev2.c
-OBJS_h += src/eap_server/ikev2.c
endif
CONFIG_IEEE8021X_EAPOL=y
NEED_DH_GROUPS=y
else
L_CFLAGS += -DEAP_VENDOR_TEST
OBJS += src/eap_peer/eap_vendor_test.c
-OBJS_h += src/eap_server/eap_server_vendor_test.c
endif
CONFIG_IEEE8021X_EAPOL=y
endif
L_CFLAGS += -DEAP_TNC
OBJS += src/eap_peer/eap_tnc.c
OBJS += src/eap_peer/tncc.c
-OBJS_h += src/eap_server/eap_server_tnc.c
-OBJS_h += src/eap_server/tncs.c
NEED_BASE64=y
ifndef CONFIG_NATIVE_WINDOWS
ifndef CONFIG_DRIVER_BSD
OBJS += src/ap/beacon.c
OBJS += src/ap/bss_load.c
OBJS += src/ap/eap_user_db.c
+OBJS += src/ap/neighbor_db.c
+OBJS += src/ap/rrm.c
ifdef CONFIG_IEEE80211N
OBJS += src/ap/ieee802_11_ht.c
ifdef CONFIG_IEEE80211AC
ifdef CONFIG_WNM
OBJS += src/ap/wnm_ap.c
endif
+ifdef CONFIG_MBO
+OBJS += src/ap/mbo_ap.c
+endif
ifdef CONFIG_CTRL_IFACE
OBJS += src/ap/ctrl_iface_ap.c
endif
endif
endif
+ifdef CONFIG_MBO
+OBJS += mbo.c
+L_CFLAGS += -DCONFIG_MBO
+endif
+
ifdef NEED_AP_MLME
OBJS += src/ap/wmm.c
OBJS += src/ap/ap_list.c
endif
endif
-ifdef CONFIG_EAP_SERVER
-L_CFLAGS += -DEAP_SERVER
-OBJS_h += src/eap_server/eap_server.c
-OBJS_h += src/eap_server/eap_server_identity.c
-OBJS_h += src/eap_server/eap_server_methods.c
-endif
-
-ifdef CONFIG_RADIUS_CLIENT
-OBJS_h += src/utils/ip_addr.c
-OBJS_h += src/radius/radius.c
-OBJS_h += src/radius/radius_client.c
-endif
-
-ifdef CONFIG_AUTHENTICATOR
-OBJS_h += src/eapol_auth/eapol_auth_sm.c
-OBJS_h += src/ap/ieee802_1x.c
-endif
-
-ifdef CONFIG_WPA_AUTHENTICATOR
-OBJS_h += src/ap/wpa_auth.c
-OBJS_h += src/ap/wpa_auth_ie.c
-OBJS_h += src/ap/pmksa_cache_auth.c
-ifdef CONFIG_IEEE80211R
-OBJS_h += src/ap/wpa_auth_ft.c
-endif
-ifdef CONFIG_PEERKEY
-OBJS_h += src/ap/peerkey_auth.c
-endif
+ifdef CONFIG_ACS
+L_CFLAGS += -DCONFIG_ACS
+OBJS += src/ap/acs.c
+LIBS += -lm
endif
ifdef CONFIG_PCSC
NEED_DES=y
# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, EAP_TTLS, and EAP_FAST)
OBJS += src/eap_peer/eap_tls_common.c
-OBJS_h += src/eap_server/eap_server_tls_common.c
ifndef CONFIG_FIPS
NEED_TLS_PRF=y
NEED_SHA1=y
ifdef TLS_FUNCS
L_CFLAGS += -DEAP_TLS_OPENSSL
OBJS += src/crypto/tls_openssl.c
+OBJS += src/crypto/tls_openssl_ocsp.c
LIBS += -lssl
endif
OBJS += src/crypto/crypto_openssl.c
OBJS += src/tls/tlsv1_client.c
OBJS += src/tls/tlsv1_client_write.c
OBJS += src/tls/tlsv1_client_read.c
+OBJS += src/tls/tlsv1_client_ocsp.c
OBJS += src/tls/asn1.c
OBJS += src/tls/rsa.c
OBJS += src/tls/x509v3.c
CONFIG_INTERNAL_MD4=y
CONFIG_INTERNAL_MD5=y
CONFIG_INTERNAL_SHA256=y
+CONFIG_INTERNAL_SHA384=y
+CONFIG_INTERNAL_SHA512=y
CONFIG_INTERNAL_RC4=y
CONFIG_INTERNAL_DH_GROUP5=y
endif
ifdef CONFIG_INTERNAL_SHA256
SHA256OBJS += src/crypto/sha256-internal.c
endif
+ifdef CONFIG_INTERNAL_SHA384
+L_CFLAGS += -DCONFIG_INTERNAL_SHA384
+SHA256OBJS += src/crypto/sha384-internal.c
+endif
+ifdef CONFIG_INTERNAL_SHA512
+L_CFLAGS += -DCONFIG_INTERNAL_SHA512
+SHA256OBJS += src/crypto/sha512-internal.c
+endif
ifdef NEED_TLS_PRF_SHA256
SHA256OBJS += src/crypto/sha256-tlsprf.c
endif
ifdef NEED_HMAC_SHA256_KDF
+L_CFLAGS += -DCONFIG_HMAC_SHA256_KDF
SHA256OBJS += src/crypto/sha256-kdf.c
endif
OBJS += $(SHA256OBJS)
L_CFLAGS += -DCONFIG_CTRL_IFACE
ifeq ($(CONFIG_CTRL_IFACE), unix)
L_CFLAGS += -DCONFIG_CTRL_IFACE_UNIX
+OBJS += src/common/ctrl_iface_common.c
endif
ifeq ($(CONFIG_CTRL_IFACE), udp)
L_CFLAGS += -DCONFIG_CTRL_IFACE_UDP
DBUS_OBJS += dbus/dbus_old_handlers_wps.c
endif
DBUS_OBJS += dbus/dbus_dict_helpers.c
-ifndef DBUS_LIBS
-DBUS_LIBS := $(shell $(PKG_CONFIG) --libs dbus-1)
-endif
-ifndef DBUS_INCLUDE
-DBUS_INCLUDE := $(shell $(PKG_CONFIG) --cflags dbus-1)
-endif
DBUS_CFLAGS += $(DBUS_INCLUDE)
endif
ifdef CONFIG_P2P
DBUS_OBJS += dbus/dbus_new_handlers_p2p.c
endif
-ifndef DBUS_LIBS
-DBUS_LIBS := $(shell $(PKG_CONFIG) --libs dbus-1)
-endif
-ifndef DBUS_INCLUDE
-DBUS_INCLUDE := $(shell $(PKG_CONFIG) --cflags dbus-1)
-endif
ifdef CONFIG_CTRL_IFACE_DBUS_INTRO
DBUS_OBJS += dbus/dbus_new_introspect.c
DBUS_CFLAGS += -DCONFIG_CTRL_IFACE_DBUS_INTRO
OBJS += $(DBUS_OBJS)
L_CFLAGS += $(DBUS_CFLAGS)
-LIBS += $(DBUS_LIBS)
+
+ifdef CONFIG_CTRL_IFACE_BINDER
+WPA_SUPPLICANT_USE_BINDER=y
+L_CFLAGS += -DCONFIG_BINDER -DCONFIG_CTRL_IFACE_BINDER
+endif
ifdef CONFIG_READLINE
OBJS_c += src/utils/edit_readline.c
OBJS += src/drivers/driver_common.c
-OBJS_wpa_rm := ctrl_iface.c ctrl_iface_unix.c
-OBJS_wpa := $(filter-out $(OBJS_wpa_rm),$(OBJS)) $(OBJS_h) tests/test_wpa.c
-ifdef CONFIG_AUTHENTICATOR
-OBJS_wpa += tests/link_test.c
-endif
-OBJS_wpa += $(OBJS_l2)
OBJS += wpa_supplicant.c events.c blacklist.c wpas_glue.c scan.c
OBJS_t := $(OBJS) $(OBJS_l2) eapol_test.c
OBJS_t += src/radius/radius_client.c
ifeq ($(CONFIG_TLS), openssl)
LOCAL_SHARED_LIBRARIES += libcrypto libssl libkeystore_binder
endif
+
+# With BoringSSL we need libkeystore-engine in order to provide access to
+# keystore keys.
+ifneq (,$(wildcard external/boringssl/flavor.mk))
+LOCAL_SHARED_LIBRARIES += libkeystore-engine
+endif
+
ifdef CONFIG_DRIVER_NL80211
ifneq ($(wildcard external/libnl),)
LOCAL_SHARED_LIBRARIES += libnl
LOCAL_CFLAGS := $(L_CFLAGS)
LOCAL_SRC_FILES := $(OBJS)
LOCAL_C_INCLUDES := $(INCLUDES)
+ifeq ($(DBUS), y)
+LOCAL_SHARED_LIBRARIES += libdbus
+endif
+ifeq ($(WPA_SUPPLICANT_USE_BINDER), y)
+LOCAL_SHARED_LIBRARIES += libbinder libutils
+LOCAL_STATIC_LIBRARIES += libwpa_binder libwpa_binder_interface
+endif
include $(BUILD_EXECUTABLE)
########################
LOCAL_COPY_HEADERS := src/common/wpa_ctrl.h
LOCAL_COPY_HEADERS += src/common/qca-vendor.h
include $(BUILD_SHARED_LIBRARY)
+
+ifeq ($(WPA_SUPPLICANT_USE_BINDER), y)
+### Binder interface library ###
+########################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libwpa_binder_interface
+LOCAL_AIDL_INCLUDES := \
+ $(LOCAL_PATH)/binder \
+ frameworks/native/aidl/binder
+LOCAL_EXPORT_C_INCLUDE_DIRS := \
+ $(LOCAL_PATH)/binder
+LOCAL_CPPFLAGS := $(L_CPPFLAGS)
+LOCAL_SRC_FILES := \
+ binder/binder_constants.cpp \
+ binder/fi/w1/wpa_supplicant/ISupplicant.aidl \
+ binder/fi/w1/wpa_supplicant/ISupplicantCallbacks.aidl \
+ binder/fi/w1/wpa_supplicant/IIface.aidl
+LOCAL_SHARED_LIBRARIES := libbinder
+include $(BUILD_STATIC_LIBRARY)
+
+### Binder service library ###
+########################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libwpa_binder
+LOCAL_CPPFLAGS := $(L_CPPFLAGS)
+LOCAL_CFLAGS := $(L_CFLAGS)
+LOCAL_C_INCLUDES := $(INCLUDES)
+LOCAL_SRC_FILES := \
+ binder/binder.cpp binder/binder_manager.cpp \
+ binder/supplicant.cpp binder/iface.cpp
+LOCAL_SHARED_LIBRARIES := \
+ libbinder \
+ libutils
+LOCAL_STATIC_LIBRARIES := libwpa_binder_interface
+include $(BUILD_STATIC_LIBRARY)
+
+endif # BINDER == y
ChangeLog for wpa_supplicant
+2016-10-02 - v2.6
+ * fixed WNM Sleep Mode processing when PMF is not enabled
+ [http://w1.fi/security/2015-6/] (CVE-2015-5310)
+ * fixed EAP-pwd last fragment validation
+ [http://w1.fi/security/2015-7/] (CVE-2015-5315)
+ * fixed EAP-pwd unexpected Confirm message processing
+ [http://w1.fi/security/2015-8/] (CVE-2015-5316)
+ * fixed WPS configuration update vulnerability with malformed passphrase
+ [http://w1.fi/security/2016-1/] (CVE-2016-4476)
+ * fixed configuration update vulnerability with malformed parameters set
+ over the local control interface
+ [http://w1.fi/security/2016-1/] (CVE-2016-4477)
+ * fixed TK configuration to the driver in EAPOL-Key 3/4 retry case
+ * extended channel switch support for P2P GO
+ * started to throttle control interface event message bursts to avoid
+ issues with monitor sockets running out of buffer space
+ * mesh mode fixes/improvements
+ - generate proper AID for peer
+ - enable WMM by default
+ - add VHT support
+ - fix PMKID derivation
+ - improve robustness on various exchanges
+ - fix peer link counting in reconnect case
+ - improve mesh joining behavior
+ - allow DTIM period to be configured
+ - allow HT to be disabled (disable_ht=1)
+ - add MESH_PEER_ADD and MESH_PEER_REMOVE commands
+ - add support for PMKSA caching
+ - add minimal support for SAE group negotiation
+ - allow pairwise/group cipher to be configured in the network profile
+ - use ieee80211w profile parameter to enable/disable PMF and derive
+ a separate TX IGTK if PMF is enabled instead of using MGTK
+ incorrectly
+ - fix AEK and MTK derivation
+ - remove GTKdata and IGTKdata from Mesh Peering Confirm/Close
+ - note: these changes are not fully backwards compatible for secure
+ (RSN) mesh network
+ * fixed PMKID derivation with SAE
+ * added support for requesting and fetching arbitrary ANQP-elements
+ without internal support in wpa_supplicant for the specific element
+ (anqp[265]=<hexdump> in "BSS <BSSID>" command output)
+ * P2P
+ - filter control characters in group client device names to be
+ consistent with other P2P peer cases
+ - support VHT 80+80 MHz and 160 MHz
+ - indicate group completion in P2P Client role after data association
+ instead of already after the WPS provisioning step
+ - improve group-join operation to use SSID, if known, to filter BSS
+ entries
+ - added optional ssid=<hexdump> argument to P2P_CONNECT for join case
+ - added P2P_GROUP_MEMBER command to fetch client interface address
+ * P2PS
+ - fix follow-on PD Response behavior
+ - fix PD Response generation for unknown peer
+ - fix persistent group reporting
+ - add channel policy to PD Request
+ - add group SSID to the P2PS-PROV-DONE event
+ - allow "P2P_CONNECT <addr> p2ps" to be used without specifying the
+ default PIN
+ * BoringSSL
+ - support for OCSP stapling
+ - support building of h20-osu-client
+ * D-Bus
+ - add ExpectDisconnect()
+ - add global config parameters as properties
+ - add SaveConfig()
+ - add VendorElemAdd(), VendorElemGet(), VendorElemRem()
+ * fixed Suite B 192-bit AKM to use proper PMK length
+ (note: this makes old releases incompatible with the fixed behavior)
+ * improved PMF behavior for cases where the AP and STA has different
+ configuration by not trying to connect in some corner cases where the
+ connection cannot succeed
+ * added option to reopen debug log (e.g., to rotate the file) upon
+ receipt of SIGHUP signal
+ * EAP-pwd: added support for Brainpool Elliptic Curves
+ (with OpenSSL 1.0.2 and newer)
+ * fixed EAPOL reauthentication after FT protocol run
+ * fixed FTIE generation for 4-way handshake after FT protocol run
+ * extended INTERFACE_ADD command to allow certain type (sta/ap)
+ interface to be created
+ * fixed and improved various FST operations
+ * added 80+80 MHz and 160 MHz VHT support for IBSS/mesh
+ * fixed SIGNAL_POLL in IBSS and mesh cases
+ * added an option to abort an ongoing scan (used to speed up connection
+ and can also be done with the new ABORT_SCAN command)
+ * TLS client
+ - do not verify CA certificates when ca_cert is not specified
+ - support validating server certificate hash
+ - support SHA384 and SHA512 hashes
+ - add signature_algorithms extension into ClientHello
+ - support TLS v1.2 signature algorithm with SHA384 and SHA512
+ - support server certificate probing
+ - allow specific TLS versions to be disabled with phase2 parameter
+ - support extKeyUsage
+ - support PKCS #5 v2.0 PBES2
+ - support PKCS #5 with PKCS #12 style key decryption
+ - minimal support for PKCS #12
+ - support OCSP stapling (including ocsp_multi)
+ * OpenSSL
+ - support OpenSSL 1.1 API changes
+ - drop support for OpenSSL 0.9.8
+ - drop support for OpenSSL 1.0.0
+ * added support for multiple schedule scan plans (sched_scan_plans)
+ * added support for external server certificate chain validation
+ (tls_ext_cert_check=1 in the network profile phase1 parameter)
+ * made phase2 parser more strict about correct use of auth=<val> and
+ autheap=<val> values
+ * improved GAS offchannel operations with comeback request
+ * added SIGNAL_MONITOR command to request signal strength monitoring
+ events
+ * added command for retrieving HS 2.0 icons with in-memory storage
+ (REQ_HS20_ICON, GET_HS20_ICON, DEL_HS20_ICON commands and
+ RX-HS20-ICON event)
+ * enabled ACS support for AP mode operations with wpa_supplicant
+ * EAP-PEAP: fixed interoperability issue with Windows 2012r2 server
+ ("Invalid Compound_MAC in cryptobinding TLV")
+ * EAP-TTLS: fixed success after fragmented final Phase 2 message
+ * VHT: added interoperability workaround for 80+80 and 160 MHz channels
+ * WNM: workaround for broken AP operating class behavior
+ * added kqueue(2) support for eloop (CONFIG_ELOOP_KQUEUE)
+ * nl80211:
+ - add support for full station state operations
+ - do not add NL80211_ATTR_SMPS_MODE attribute if HT is disabled
+ - add NL80211_ATTR_PREV_BSSID with Connect command
+ - fix IEEE 802.1X/WEP EAP reauthentication and rekeying to use
+ unencrypted EAPOL frames
+ * added initial MBO support; number of extensions to WNM BSS Transition
+ Management
+ * added support for PBSS/PCP and P2P on 60 GHz
+ * Interworking: add credential realm to EAP-TLS identity
+ * fixed EAPOL-Key Request Secure bit to be 1 if PTK is set
+ * HS 2.0: add support for configuring frame filters
+ * added POLL_STA command to check connectivity in AP mode
+ * added initial functionality for location related operations
+ * started to ignore pmf=1/2 parameter for non-RSN networks
+ * added wps_disabled=1 network profile parameter to allow AP mode to
+ be started without enabling WPS
+ * wpa_cli: added action script support for AP-ENABLED and AP-DISABLED
+ events
+ * improved Public Action frame addressing
+ - add gas_address3 configuration parameter to control Address 3
+ behavior
+ * number of small fixes
+
2015-09-27 - v2.5
* fixed P2P validation of SSID element length before copying it
[http://w1.fi/security/2015-1/] (CVE-2015-1863)
CFLAGS = -MMD -O2 -Wall -g
endif
+ifdef LIBS
+# If LIBS is set with some global build system defaults, clone those for
+# LIBS_c and LIBS_p to cover wpa_passphrase and wpa_cli as well.
+ifndef LIBS_c
+LIBS_c := $(LIBS)
+endif
+ifndef LIBS_p
+LIBS_p := $(LIBS)
+endif
+endif
+
export LIBDIR ?= /usr/local/lib/
export INCDIR ?= /usr/local/include/
export BINDIR ?= /usr/local/sbin/
-include .config
+ifndef CONFIG_NO_GITVER
+# Add VERSION_STR postfix for builds from a git repository
+ifeq ($(wildcard ../.git),../.git)
+GITVER := $(shell git describe --dirty=+)
+ifneq ($(GITVER),)
+CFLAGS += -DGIT_VERSION_STR_POSTFIX=\"-$(GITVER)\"
+endif
+endif
+endif
+
ifdef CONFIG_TESTING_OPTIONS
CFLAGS += -DCONFIG_TESTING_OPTIONS
CONFIG_WPS_TESTING=y
OBJS_c = wpa_cli.o ../src/common/wpa_ctrl.o
OBJS_c += ../src/utils/wpa_debug.o
OBJS_c += ../src/utils/common.o
+OBJS_c += ../src/common/cli.o
OBJS += wmm_ac.o
ifndef CONFIG_OS
CFLAGS += -DCONFIG_ELOOP_EPOLL
endif
+ifdef CONFIG_ELOOP_KQUEUE
+CFLAGS += -DCONFIG_ELOOP_KQUEUE
+endif
+
ifdef CONFIG_EAPOL_TEST
CFLAGS += -Werror -DEAPOL_TEST
endif
NEED_RC4=y
else
CFLAGS += -DCONFIG_NO_WPA
+ifeq ($(CONFIG_TLS), internal)
+NEED_SHA1=y
+NEED_MD5=y
+endif
endif
ifdef CONFIG_IBSS_RSN
NEED_RSN_AUTHENTICATOR=y
CFLAGS += -DCONFIG_IBSS_RSN
+CFLAGS += -DCONFIG_NO_VLAN
OBJS += ibss_rsn.o
endif
+ifdef CONFIG_MATCH_IFACE
+CFLAGS += -DCONFIG_MATCH_IFACE
+endif
+
ifdef CONFIG_P2P
OBJS += p2p_supplicant.o
OBJS += p2p_supplicant_sd.o
else
CFLAGS += -DEAP_TLS
OBJS += ../src/eap_peer/eap_tls.o
-OBJS_h += ../src/eap_server/eap_server_tls.o
endif
TLS_FUNCS=y
CONFIG_IEEE8021X_EAPOL=y
CFLAGS += -DEAP_UNAUTH_TLS
ifndef CONFIG_EAP_TLS
OBJS += ../src/eap_peer/eap_tls.o
-OBJS_h += ../src/eap_server/eap_server_tls.o
TLS_FUNCS=y
endif
CONFIG_IEEE8021X_EAPOL=y
CFLAGS += -DEAP_PEAP
OBJS += ../src/eap_peer/eap_peap.o
OBJS += ../src/eap_common/eap_peap_common.o
-OBJS_h += ../src/eap_server/eap_server_peap.o
endif
TLS_FUNCS=y
CONFIG_IEEE8021X_EAPOL=y
else
CFLAGS += -DEAP_TTLS
OBJS += ../src/eap_peer/eap_ttls.o
-OBJS_h += ../src/eap_server/eap_server_ttls.o
endif
TLS_FUNCS=y
ifndef CONFIG_FIPS
else
CFLAGS += -DEAP_MD5
OBJS += ../src/eap_peer/eap_md5.o
-OBJS_h += ../src/eap_server/eap_server_md5.o
endif
CHAP=y
CONFIG_IEEE8021X_EAPOL=y
CFLAGS += -DEAP_MSCHAPv2
OBJS += ../src/eap_peer/eap_mschapv2.o
OBJS += ../src/eap_peer/mschapv2.o
-OBJS_h += ../src/eap_server/eap_server_mschapv2.o
endif
MS_FUNCS=y
CONFIG_IEEE8021X_EAPOL=y
else
CFLAGS += -DEAP_GTC
OBJS += ../src/eap_peer/eap_gtc.o
-OBJS_h += ../src/eap_server/eap_server_gtc.o
endif
CONFIG_IEEE8021X_EAPOL=y
endif
else
CFLAGS += -DEAP_SIM
OBJS += ../src/eap_peer/eap_sim.o
-OBJS_h += ../src/eap_server/eap_server_sim.o
endif
CONFIG_IEEE8021X_EAPOL=y
CONFIG_EAP_SIM_COMMON=y
else
CFLAGS += -DEAP_PSK
OBJS += ../src/eap_peer/eap_psk.o ../src/eap_common/eap_psk_common.o
-OBJS_h += ../src/eap_server/eap_server_psk.o
endif
CONFIG_IEEE8021X_EAPOL=y
NEED_AES=y
else
CFLAGS += -DEAP_AKA
OBJS += ../src/eap_peer/eap_aka.o
-OBJS_h += ../src/eap_server/eap_server_aka.o
endif
CONFIG_IEEE8021X_EAPOL=y
CONFIG_EAP_SIM_COMMON=y
ifdef CONFIG_EAP_SIM_COMMON
OBJS += ../src/eap_common/eap_sim_common.o
-OBJS_h += ../src/eap_server/eap_sim_db.o
NEED_AES=y
NEED_FIPS186_2_PRF=y
endif
CFLAGS += -DEAP_FAST
OBJS += ../src/eap_peer/eap_fast.o ../src/eap_peer/eap_fast_pac.o
OBJS += ../src/eap_common/eap_fast_common.o
-OBJS_h += ../src/eap_server/eap_server_fast.o
endif
TLS_FUNCS=y
CONFIG_IEEE8021X_EAPOL=y
else
CFLAGS += -DEAP_PAX
OBJS += ../src/eap_peer/eap_pax.o ../src/eap_common/eap_pax_common.o
-OBJS_h += ../src/eap_server/eap_server_pax.o
endif
CONFIG_IEEE8021X_EAPOL=y
endif
else
CFLAGS += -DEAP_SAKE
OBJS += ../src/eap_peer/eap_sake.o ../src/eap_common/eap_sake_common.o
-OBJS_h += ../src/eap_server/eap_server_sake.o
endif
CONFIG_IEEE8021X_EAPOL=y
endif
else
CFLAGS += -DEAP_GPSK
OBJS += ../src/eap_peer/eap_gpsk.o ../src/eap_common/eap_gpsk_common.o
-OBJS_h += ../src/eap_server/eap_server_gpsk.o
endif
CONFIG_IEEE8021X_EAPOL=y
ifdef CONFIG_EAP_GPSK_SHA256
ifdef CONFIG_EAP_PWD
CFLAGS += -DEAP_PWD
OBJS += ../src/eap_peer/eap_pwd.o ../src/eap_common/eap_pwd_common.o
-OBJS_h += ../src/eap_server/eap_server_pwd.o
CONFIG_IEEE8021X_EAPOL=y
NEED_SHA256=y
endif
else
CFLAGS += -DEAP_EKE
OBJS += ../src/eap_peer/eap_eke.o ../src/eap_common/eap_eke_common.o
-OBJS_h += ../src/eap_server/eap_server_eke.o
endif
CONFIG_IEEE8021X_EAPOL=y
NEED_DH_GROUPS=y
OBJS += ../src/wps/wps_dev_attr.o
OBJS += ../src/wps/wps_enrollee.o
OBJS += ../src/wps/wps_registrar.o
-OBJS_h += ../src/eap_server/eap_server_wsc.o
CONFIG_IEEE8021X_EAPOL=y
NEED_DH_GROUPS=y
NEED_SHA256=y
CFLAGS += -DEAP_IKEV2
OBJS += ../src/eap_peer/eap_ikev2.o ../src/eap_peer/ikev2.o
OBJS += ../src/eap_common/eap_ikev2_common.o ../src/eap_common/ikev2_common.o
-OBJS_h += ../src/eap_server/eap_server_ikev2.o
-OBJS_h += ../src/eap_server/ikev2.o
endif
CONFIG_IEEE8021X_EAPOL=y
NEED_DH_GROUPS=y
else
CFLAGS += -DEAP_VENDOR_TEST
OBJS += ../src/eap_peer/eap_vendor_test.o
-OBJS_h += ../src/eap_server/eap_server_vendor_test.o
endif
CONFIG_IEEE8021X_EAPOL=y
endif
CFLAGS += -DEAP_TNC
OBJS += ../src/eap_peer/eap_tnc.o
OBJS += ../src/eap_peer/tncc.o
-OBJS_h += ../src/eap_server/eap_server_tnc.o
-OBJS_h += ../src/eap_server/tncs.o
NEED_BASE64=y
ifndef CONFIG_NATIVE_WINDOWS
ifndef CONFIG_DRIVER_BSD
OBJS += ../src/ap/beacon.o
OBJS += ../src/ap/bss_load.o
OBJS += ../src/ap/eap_user_db.o
+OBJS += ../src/ap/neighbor_db.o
+OBJS += ../src/ap/rrm.o
ifdef CONFIG_IEEE80211N
OBJS += ../src/ap/ieee802_11_ht.o
ifdef CONFIG_IEEE80211AC
ifdef CONFIG_WNM
OBJS += ../src/ap/wnm_ap.o
endif
+ifdef CONFIG_MBO
+OBJS += ../src/ap/mbo_ap.o
+endif
ifdef CONFIG_CTRL_IFACE
OBJS += ../src/ap/ctrl_iface_ap.o
endif
endif
endif
+ifdef CONFIG_MBO
+OBJS += mbo.o
+CFLAGS += -DCONFIG_MBO
+endif
+
ifdef NEED_AP_MLME
OBJS += ../src/ap/wmm.o
OBJS += ../src/ap/ap_list.o
endif
endif
-ifdef CONFIG_EAP_SERVER
-CFLAGS += -DEAP_SERVER
-OBJS_h += ../src/eap_server/eap_server.o
-OBJS_h += ../src/eap_server/eap_server_identity.o
-OBJS_h += ../src/eap_server/eap_server_methods.o
-endif
-
-ifdef CONFIG_RADIUS_CLIENT
-OBJS_h += ../src/utils/ip_addr.o
-OBJS_h += ../src/radius/radius.o
-OBJS_h += ../src/radius/radius_client.o
-endif
-
-ifdef CONFIG_AUTHENTICATOR
-OBJS_h += ../src/eapol_auth/eapol_auth_sm.o
-OBJS_h += ../src/ap/ieee802_1x.o
-endif
-
-ifdef CONFIG_WPA_AUTHENTICATOR
-OBJS_h += ../src/ap/wpa_auth.o
-OBJS_h += ../src/ap/wpa_auth_ie.o
-OBJS_h += ../src/ap/pmksa_cache_auth.o
-ifdef CONFIG_IEEE80211R
-OBJS_h += ../src/ap/wpa_auth_ft.o
-endif
-ifdef CONFIG_PEERKEY
-OBJS_h += ../src/ap/peerkey_auth.o
-endif
+ifdef CONFIG_ACS
+CFLAGS += -DCONFIG_ACS
+OBJS += ../src/ap/acs.o
+LIBS += -lm
endif
ifdef CONFIG_PCSC
#dynamic symbol loading that is now used in pcsc_funcs.c
#LIBS += -lwinscard
else
+ifdef CONFIG_OSX
+LIBS += -framework PCSC
+else
LIBS += -lpcsclite -lpthread
endif
endif
+endif
ifdef CONFIG_SIM_SIMULATOR
CFLAGS += -DCONFIG_SIM_SIMULATOR
NEED_DES=y
# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, EAP_TTLS, and EAP_FAST)
OBJS += ../src/eap_peer/eap_tls_common.o
-OBJS_h += ../src/eap_server/eap_server_tls_common.o
ifndef CONFIG_FIPS
NEED_TLS_PRF=y
NEED_SHA1=y
ifdef TLS_FUNCS
CFLAGS += -DEAP_TLS_OPENSSL
OBJS += ../src/crypto/tls_openssl.o
+OBJS += ../src/crypto/tls_openssl_ocsp.o
LIBS += -lssl
endif
OBJS += ../src/crypto/crypto_openssl.o
OBJS += ../src/tls/tlsv1_client.o
OBJS += ../src/tls/tlsv1_client_write.o
OBJS += ../src/tls/tlsv1_client_read.o
+OBJS += ../src/tls/tlsv1_client_ocsp.o
OBJS += ../src/tls/asn1.o
OBJS += ../src/tls/rsa.o
OBJS += ../src/tls/x509v3.o
CONFIG_INTERNAL_MD4=y
CONFIG_INTERNAL_MD5=y
CONFIG_INTERNAL_SHA256=y
+CONFIG_INTERNAL_SHA384=y
+CONFIG_INTERNAL_SHA512=y
CONFIG_INTERNAL_RC4=y
CONFIG_INTERNAL_DH_GROUP5=y
endif
ifdef CONFIG_INTERNAL_SHA256
SHA256OBJS += ../src/crypto/sha256-internal.o
endif
+ifdef CONFIG_INTERNAL_SHA384
+CFLAGS += -DCONFIG_INTERNAL_SHA384
+SHA256OBJS += ../src/crypto/sha384-internal.o
+endif
+ifdef CONFIG_INTERNAL_SHA512
+CFLAGS += -DCONFIG_INTERNAL_SHA512
+SHA256OBJS += ../src/crypto/sha512-internal.o
+endif
ifdef NEED_TLS_PRF_SHA256
SHA256OBJS += ../src/crypto/sha256-tlsprf.o
endif
ifdef NEED_HMAC_SHA256_KDF
+CFLAGS += -DCONFIG_HMAC_SHA256_KDF
OBJS += ../src/crypto/sha256-kdf.o
endif
OBJS += $(SHA256OBJS)
CFLAGS += -DCONFIG_CTRL_IFACE
ifeq ($(CONFIG_CTRL_IFACE), unix)
CFLAGS += -DCONFIG_CTRL_IFACE_UNIX
+OBJS += ../src/common/ctrl_iface_common.o
endif
ifeq ($(CONFIG_CTRL_IFACE), udp)
CFLAGS += -DCONFIG_CTRL_IFACE_UDP
DBUS_INCLUDE := $(shell $(PKG_CONFIG) --cflags dbus-1)
endif
DBUS_CFLAGS += $(DBUS_INCLUDE)
+DBUS_INTERFACE=fi.epitest.hostap.WPASupplicant
endif
ifdef CONFIG_CTRL_IFACE_DBUS_NEW
DBUS_CFLAGS += -DCONFIG_CTRL_IFACE_DBUS_INTRO
endif
DBUS_CFLAGS += $(DBUS_INCLUDE)
+DBUS_INTERFACE=fi.w1.wpa_supplicant1
endif
ifdef DBUS
ifdef CONFIG_READLINE
OBJS_c += ../src/utils/edit_readline.o
-LIBS_c += -lncurses -lreadline
+LIBS_c += -lreadline -lncurses
else
ifdef CONFIG_WPA_CLI_EDIT
OBJS_c += ../src/utils/edit.o
CFLAGS += -DCONFIG_IPV6
endif
+ifdef CONFIG_NO_LINUX_PACKET_SOCKET_WAR
+CFLAGS += -DCONFIG_NO_LINUX_PACKET_SOCKET_WAR
+endif
+
ifdef NEED_BASE64
OBJS += ../src/utils/base64.o
endif
OBJS += ../src/drivers/driver_common.o
OBJS_priv += ../src/drivers/driver_common.o
-OBJS_wpa_rm := ctrl_iface.o ctrl_iface_unix.o
-OBJS_wpa := $(filter-out $(OBJS_wpa_rm),$(OBJS)) $(OBJS_h) tests/test_wpa.o
-ifdef CONFIG_AUTHENTICATOR
-OBJS_wpa += tests/link_test.o
-endif
-OBJS_wpa += $(OBJS_l2)
OBJS += wpa_supplicant.o events.o blacklist.o wpas_glue.o scan.o
OBJS_t := $(OBJS) $(OBJS_l2) eapol_test.o
OBJS_t += ../src/radius/radius_client.o
OBJS += $(FST_OBJS)
OBJS_t += $(FST_OBJS)
OBJS_t2 += $(FST_OBJS)
+OBJS_nfc += $(FST_OBJS)
endif
ifndef LDO
LIBCTRL += ../src/common/wpa_ctrl.o
LIBCTRL += ../src/utils/os_$(CONFIG_OS).o
+LIBCTRL += ../src/utils/common.o
LIBCTRL += ../src/utils/wpa_debug.o
LIBCTRLSO += ../src/common/wpa_ctrl.c
LIBCTRLSO += ../src/utils/os_$(CONFIG_OS).c
+LIBCTRLSO += ../src/utils/common.c
LIBCTRLSO += ../src/utils/wpa_debug.c
libwpa_client.a: $(LIBCTRL)
@$(E) " CC $@ ($^)"
$(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -fPIC $^
-link_test: $(OBJS) $(OBJS_h) tests/link_test.o
- $(Q)$(LDO) $(LDFLAGS) -o link_test $(OBJS) $(OBJS_h) tests/link_test.o $(LIBS)
+libwpa_test1: libwpa_test.o libwpa_client.a
+ $(Q)$(LDO) $(LDFLAGS) -o libwpa_test1 libwpa_test.o libwpa_client.a $(LIBS_c)
@$(E) " LD " $@
-test_wpa: $(OBJS_wpa) $(OBJS_h)
- $(Q)$(LDO) $(LDFLAGS) -o test_wpa $(OBJS_wpa) $(LIBS)
+libwpa_test2: libwpa_test.o libwpa_client.so
+ $(Q)$(LDO) $(LDFLAGS) -o libwpa_test2 libwpa_test.o -L. -lwpa_client $(LIBS_c)
@$(E) " LD " $@
nfc_pw_token: $(OBJS_nfc)
endif
%.service: %.service.in
- $(Q)sed -e 's|\@BINDIR\@|$(BINDIR)|g' $< >$@
+ $(Q)sed -e 's|\@BINDIR\@|$(BINDIR)|g' \
+ -e 's|\@DBUS_INTERFACE\@|$(DBUS_INTERFACE)|g' $< >$@
@$(E) " sed" $<
%@.service: %.service.arg.in
- $(Q)sed -e 's|\@BINDIR\@|$(BINDIR)|g' $< >$@
+ $(Q)sed -e 's|\@BINDIR\@|$(BINDIR)|g' \
+ -e 's|\@DBUS_INTERFACE\@|$(DBUS_INTERFACE)|g' $< >$@
@$(E) " sed" $<
wpa_supplicant.exe: wpa_supplicant
wpa_gui-qt4: wpa_gui-qt4/Makefile wpa_gui-qt4/lang/wpa_gui_de.qm
$(MAKE) -C wpa_gui-qt4
-TEST_EAP_SIM_COMMON_OBJS = $(SHA1OBJS) $(MD5OBJS) \
- ../src/utils/common.o ../src/utils/os_unix.o \
- ../src/utils/wpa_debug.o $(AESOBJS) \
- tests/test_eap_sim_common.o
-test-eap_sim_common: $(TEST_EAP_SIM_COMMON_OBJS)
- $(LDO) $(LDFLAGS) -o $@ $(TEST_EAP_SIM_COMMON_OBJS) $(LIBS)
- ./test-eap_sim_common
- rm test-eap_sim_common
-
-tests: test-eap_sim_common
-
FIPSDIR=/usr/local/ssl/fips-2.0
FIPSLD=$(FIPSDIR)/bin/fipsld
fips:
rm -rf lcov-html
rm -f libwpa_client.a
rm -f libwpa_client.so
+ rm -f libwpa_test1 libwpa_test2
-include $(OBJS:%.o=%.d)
WPA Supplicant
==============
-Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi> and contributors
+Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
This program is licensed under the BSD license (the one with
* EAP-TTLS/CHAP
* EAP-SIM
* EAP-AKA
+ * EAP-AKA'
* EAP-PSK
* EAP-PAX
* EAP-SAKE
* EAP-IKEv2
* EAP-GPSK
+ * EAP-pwd
* LEAP (note: requires special support from the driver for IEEE 802.11
authentication)
(following methods are supported, but since they do not generate keying
Optional libraries for EAP-TLS, EAP-PEAP, and EAP-TTLS:
-- OpenSSL (tested with 0.9.7c and 0.9.7d, and 0.9.8 versions; assumed to
+- OpenSSL (tested with 1.0.1 and 1.0.2 versions; assumed to
work with most relatively recent versions; this is likely to be
available with most distributions, http://www.openssl.org/)
- GnuTLS
- internal TLSv1 implementation
-TLS options for EAP-FAST:
-- OpenSSL 0.9.8d _with_ openssl-0.9.8d-tls-extensions.patch applied
- (i.e., the default OpenSSL package does not include support for
- extensions needed for EAP-FAST)
-- internal TLSv1 implementation
-
One of these libraries is needed when EAP-TLS, EAP-PEAP, EAP-TTLS, or
EAP-FAST support is enabled. WPA-PSK mode does not require this or EAPOL/EAP
implementation. A configuration file, .config, for compilation is
802.1X/EAPOL and EAP state machines and all EAP methods. Including
TLS, PEAP, or TTLS will require linking wpa_supplicant with OpenSSL
library for TLS implementation. Alternatively, GnuTLS or the internal
-TLSv1 implementation can be used for TLS functionaly.
+TLSv1 implementation can be used for TLS functionality.
CONFIG_IEEE8021X_EAPOL=y
CONFIG_EAP_MD5=y
CONFIG_EAP_OTP=y
CONFIG_EAP_SIM=y
CONFIG_EAP_AKA=y
+CONFIG_EAP_AKA_PRIME=y
CONFIG_EAP_PSK=y
CONFIG_EAP_SAKE=y
CONFIG_EAP_GPSK=y
CONFIG_EAP_PAX=y
CONFIG_EAP_LEAP=y
CONFIG_EAP_IKEV2=y
+CONFIG_EAP_PWD=y
Following option can be used to include GSM SIM/USIM interface for GSM/UMTS
-authentication algorithm (for EAP-SIM/EAP-AKA). This requires pcsc-lite
+authentication algorithm (for EAP-SIM/EAP-AKA/EAP-AKA'). This requires pcsc-lite
(http://www.linuxnet.com/) for smart card access.
CONFIG_PCSC=y
--------------------
usage:
- wpa_supplicant [-BddfhKLqqtuvwW] [-P<pid file>] [-g<global ctrl>] \
+ wpa_supplicant [-BddfhKLqqtuvW] [-P<pid file>] [-g<global ctrl>] \
[-G<group>] \
-i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] [-p<driver_param>] \
- [-b<br_ifname> [-N -i<ifname> -c<conf> [-C<ctrl>] [-D<driver>] \
+ [-b<br_ifname> [-MN -i<ifname> -c<conf> [-C<ctrl>] [-D<driver>] \
[-p<driver_param>] [-b<br_ifname>] [-m<P2P Device config file>] ...
options:
-q = decrease debugging verbosity (-qq even less)
-u = enable DBus control interface
-v = show version
- -w = wait for interface to be added, if needed
-W = wait for a control interface monitor before starting
+ -M = start describing matching interface
-N = start describing new interface
-m = Configuration file for the P2P Device
-c wpa2.conf -i wlan1 -D wext
+If the interfaces on which wpa_supplicant is to run are not known or do
+not exist, wpa_supplicant can match an interface when it arrives. Each
+matched interface is separated with -M argument and the -i argument now
+allows for pattern matching.
+
+As an example, the following command would start wpa_supplicant for a
+specific wired interface called lan0, any interface starting with wlan
+and lastly any other interface. Each match has its own configuration
+file, and for the wired interface a specific driver has also been given.
+
+wpa_supplicant \
+ -M -c wpa_wired.conf -ilan0 -D wired \
+ -M -c wpa1.conf -iwlan* \
+ -M -c wpa2.conf
+
+
If the interface is added in a Linux bridge (e.g., br0), the bridge
interface needs to be configured to wpa_supplicant in addition to the
main interface:
Configuration file can include one or more network blocks, e.g., one
for each used SSID. wpa_supplicant will automatically select the best
-betwork based on the order of network blocks in the configuration
+network based on the order of network blocks in the configuration
file, network security level (WPA/WPA2 is preferred), and signal
strength.
One wpa_cli process in "action" mode needs to be started for each
interface. For example, the following command starts wpa_cli for the
-default ingterface (-i can be used to select the interface in case of
+default interface (-i can be used to select the interface in case of
more than one interface being used at the same time):
wpa_cli -a/sbin/wpa_action.sh -B
the operation has been completed, "RADIO_WORK done <id>" is used to
indicate that to wpa_supplicant. This allows other radio works to be
performed. If this command is forgotten (e.g., due to the external
-program terminating), wpa_supplicant will time out the radio owrk item
-and send "EXT-RADIO-WORK-TIMEOUT <id>" event ot indicate that this has
+program terminating), wpa_supplicant will time out the radio work item
+and send "EXT-RADIO-WORK-TIMEOUT <id>" event to indicate that this has
happened. "RADIO_WORK done <id>" can also be used to cancel items that
have not yet been started.
#
# sp_priority: Credential priority within a provisioning SP
# This is the priority of the credential among all credentials
-# provisionined by the same SP (i.e., for entries that have identical
+# provisioned by the same SP (i.e., for entries that have identical
# provisioning_sp value). The range of this priority is 0-255 with 0
# being the highest and 255 the lower priority.
#
<3>RX-ANQP 02:00:00:00:01:00 Roaming Consortium list
<3>RX-HS20-ANQP 02:00:00:00:01:00 HS Capability List
<3>ANQP fetch completed
+
+
+Hotspot 2.0 Rel 2 online signup and OSEN
+----------------------------------------
+
+Following parameters can be used to create a network profile for
+link-layer protected Hotspot 2.0 online signup connection with
+OSEN. Note that ssid and identify (NAI) values need to be set based on
+the information for the selected provider in the OSU Providers list
+ANQP-element.
+
+network={
+ ssid="HS 2.0 OSU"
+ proto=OSEN
+ key_mgmt=OSEN
+ pairwise=CCMP
+ group=GTK_NOT_USED
+ eap=WFA-UNAUTH-TLS
+ identity="anonymous@example.com"
+ ca_cert="osu-ca.pem"
+ ocsp=2
+}
+
+
+Hotspot 2.0 connection with external network selection
+------------------------------------------------------
+
+When an component controlling wpa_supplicant takes care of Interworking
+network selection, following configuration and network profile
+parameters can be used to configure a temporary network profile for a
+Hotspot 2.0 connection (e.g., with SET, ADD_NETWORK, SET_NETWORK, and
+SELECT_NETWORK control interface commands):
+
+interworking=1
+hs20=1
+auto_interworking=0
+
+network={
+ ssid="test-hs20"
+ proto=RSN
+ key_mgmt=WPA-EAP
+ pairwise=CCMP
+ anonymous_identity="anonymous@example.com"
+ identity="hs20-test@example.com"
+ password="password"
+ ca_cert="ca.pem"
+ eap=TTLS
+ phase2="auth=MSCHAPV2"
+ update_identifier=54321
+ #ocsp=2
+}
+
+
+These parameters are set based on the PPS MO credential and/or NAI Realm
+list ANQP-element:
+
+anonymous_identity: Credential/UsernamePassword/Username with username part
+ replaced with "anonymous"
+identity: Credential/UsernamePassword/Username
+password: Credential/UsernamePassword/Password
+update_identifier: PPS/UpdateIdentifier
+ca_cert: from the downloaded trust root based on PPS information
+eap: Credential/UsernamePassword/EAPMethod or NAI Realm list
+phase2: Credential/UsernamePassword/EAPMethod or NAI Realm list
+ocsp: Credential/CheckAAAServerCertStatus
p2p_connect <peer device address> <pbc|pin|PIN#|p2ps> [display|keypad|p2ps]
[persistent|persistent=<network id>] [join|auth]
[go_intent=<0..15>] [freq=<in MHz>] [ht40] [vht] [provdisc] [auto]
+ [ssid=<hexdump>]
Start P2P group formation with a discovered P2P peer. This includes
optional group owner negotiation, group interface setup, provisioning,
out whether the peer device is operating as a GO and if so, use
join-a-group operation rather than GO Negotiation.
+"ssid=<hexdump>" can be used to specify the Group SSID for join
+operations. This allows the P2P Client interface to filter scan results
+based on SSID to avoid selecting an incorrect BSS entry in case the same
+P2P Device or Interface address have been used in multiple groups
+recently.
+
P2PS attribute changes to p2p_connect command:
P2PS supports two WPS provisioning methods namely PIN method and P2PS default.
-The remaining paramters hold same role as in legacy P2P. In case of P2PS default
-config method "p2ps" keyword is added in p2p_connect command.
+The remaining parameters hold same role as in legacy P2P. In case of P2PS
+default config method "p2ps" keyword is added in p2p_connect command.
For example:
p2p_connect 02:0a:f5:85:11:00 12345670 p2ps persistent join
p2p_cancel
Cancel an ongoing P2P group formation and joining-a-group related
-operation. This operations unauthorizes the specific peer device (if any
+operation. This operation unauthorizes the specific peer device (if any
had been authorized to start group formation), stops P2P find (if in
progress), stops pending operations for join-a-group, and removes the
P2P group interface (if one was used) that is in the WPS provisioning
Disable/enable managed P2P Device operations. This is disabled by
default.
-p2p_set listen_channel <1/6/11>
+p2p_set listen_channel <channel> [<op_class>]
Set P2P Listen channel. This is mainly meant for testing purposes and
changing the Listen channel during normal operations can result in
protocol failures.
+When specifying a social channel on the 2.4 GHz band (1/6/11) there is
+no need to specify the operating class since it defaults to 81. When
+specifying a social channel on the 60 GHz band (2), specify the 60 GHz
+operating class (180).
+
p2p_set ssid_postfix <postfix>
Set postfix string to be added to the automatically generated P2P SSID
Disabled(default)/enables use of per-client PSK in the P2P groups. This
can be used to request GO to assign a unique PSK for each client during
WPS provisioning. When enabled, this allow clients to be removed from
-the group securily with p2p_remove_client command since that client's
+the group securely with p2p_remove_client command since that client's
PSK is removed at the same time to prevent it from connecting back using
the old PSK. When per-client PSK is not used, the client can still be
disconnected, but it will be able to re-join the group since the PSK it
#CONFIG_DRIVER_NL80211=y
CONFIG_LIBNL20=y
+# QCA vendor extensions to nl80211
+CONFIG_DRIVER_NL80211_QCA=y
+
# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
#CONFIG_DRIVER_BSD=y
#CFLAGS += -I/usr/local/include
# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL,
# the OpenSSL library must be patched (openssl-0.9.8d-tls-extensions.patch)
# to add the needed functions.
-CONFIG_EAP_FAST=y
+#CONFIG_EAP_FAST=y
# EAP-GTC
CONFIG_EAP_GTC=y
# Add introspection support for new DBus control interface
#CONFIG_CTRL_IFACE_DBUS_INTRO=y
+# Add support for Binder control interface
+# Only applicable for Android platforms.
+#CONFIG_CTRL_IFACE_BINDER=y
+
# Add support for loading EAP methods dynamically as shared libraries.
# When this option is enabled, each EAP method can be either included
# statically (CONFIG_EAP_<method>=y) or dynamically (CONFIG_EAP_<method>=dyn).
# Enable Fast Session Transfer (FST)
#CONFIG_FST=y
+# Support Multi Band Operation
+#CONFIG_MBO=y
+
include $(wildcard $(LOCAL_PATH)/android_config_*.inc)
if (!conf->secondary_channel)
goto no_vht;
- center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, channel);
+ switch (conf->vht_oper_chwidth) {
+ case VHT_CHANWIDTH_80MHZ:
+ case VHT_CHANWIDTH_80P80MHZ:
+ center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, channel);
+ break;
+ case VHT_CHANWIDTH_160MHZ:
+ center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel);
+ break;
+ default:
+ /*
+ * conf->vht_oper_chwidth might not be set for non-P2P GO cases,
+ * try oper_cwidth 160 MHz first then VHT 80 MHz, if 160 MHz is
+ * not supported.
+ */
+ conf->vht_oper_chwidth = VHT_CHANWIDTH_160MHZ;
+ center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel);
+ if (!center_chan) {
+ conf->vht_oper_chwidth = VHT_CHANWIDTH_80MHZ;
+ center_chan = wpas_p2p_get_vht80_center(wpa_s, mode,
+ channel);
+ }
+ break;
+ }
if (!center_chan)
goto no_vht;
- /* Use 80 MHz channel */
- conf->vht_oper_chwidth = 1;
conf->vht_oper_centr_freq_seg0_idx = center_chan;
return;
conf->vht_oper_centr_freq_seg0_idx =
conf->channel + conf->secondary_channel * 2;
#endif /* CONFIG_P2P */
+ conf->vht_oper_chwidth = VHT_CHANWIDTH_USE_HT;
}
#endif /* CONFIG_IEEE80211N */
-void wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid,
- struct hostapd_config *conf)
+int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
+ struct hostapd_config *conf)
{
+ conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency,
+ &conf->channel);
+
+ if (conf->hw_mode == NUM_HOSTAPD_MODES) {
+ wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz",
+ ssid->frequency);
+ return -1;
+ }
+
/* TODO: enable HT40 if driver supports it;
* drop to 11b if driver does not support 11g */
}
}
#endif /* CONFIG_IEEE80211N */
+
+ return 0;
}
os_strlcpy(bss->iface, wpa_s->ifname, sizeof(bss->iface));
- conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency,
- &conf->channel);
- if (conf->hw_mode == NUM_HOSTAPD_MODES) {
- wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz",
- ssid->frequency);
+ if (wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf))
+ return -1;
+
+ if (ssid->pbss > 1) {
+ wpa_printf(MSG_ERROR, "Invalid pbss value(%d) for AP mode",
+ ssid->pbss);
return -1;
}
+ bss->pbss = ssid->pbss;
- wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf);
+#ifdef CONFIG_ACS
+ if (ssid->acs) {
+ /* Setting channel to 0 in order to enable ACS */
+ conf->channel = 0;
+ wpa_printf(MSG_DEBUG, "Use automatic channel selection");
+ }
+#endif /* CONFIG_ACS */
if (ieee80211_is_dfs(ssid->frequency) && wpa_s->conf->country[0]) {
conf->ieee80211h = 1;
bss->force_per_enrollee_psk = wpa_s->global->p2p_per_sta_psk;
if (ssid->p2p_group) {
- os_memcpy(bss->ip_addr_go, wpa_s->parent->conf->ip_addr_go, 4);
- os_memcpy(bss->ip_addr_mask, wpa_s->parent->conf->ip_addr_mask,
+ os_memcpy(bss->ip_addr_go, wpa_s->p2pdev->conf->ip_addr_go, 4);
+ os_memcpy(bss->ip_addr_mask, wpa_s->p2pdev->conf->ip_addr_mask,
4);
os_memcpy(bss->ip_addr_start,
- wpa_s->parent->conf->ip_addr_start, 4);
- os_memcpy(bss->ip_addr_end, wpa_s->parent->conf->ip_addr_end,
+ wpa_s->p2pdev->conf->ip_addr_start, 4);
+ os_memcpy(bss->ip_addr_end, wpa_s->p2pdev->conf->ip_addr_end,
4);
}
#endif /* CONFIG_P2P */
if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt))
bss->wpa = ssid->proto;
- bss->wpa_key_mgmt = ssid->key_mgmt;
+ if (ssid->key_mgmt == DEFAULT_KEY_MGMT)
+ bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
+ else
+ bss->wpa_key_mgmt = ssid->key_mgmt;
bss->wpa_pairwise = ssid->pairwise_cipher;
if (ssid->psk_set) {
bin_clear_free(bss->ssid.wpa_psk, sizeof(*bss->ssid.wpa_psk));
return -1;
os_memcpy(bss->ssid.wpa_psk->psk, ssid->psk, PMK_LEN);
bss->ssid.wpa_psk->group = 1;
+ bss->ssid.wpa_psk_set = 1;
} else if (ssid->passphrase) {
bss->ssid.wpa_passphrase = os_strdup(ssid->passphrase);
} else if (ssid->wep_key_len[0] || ssid->wep_key_len[1] ||
conf->beacon_int = wpa_s->conf->beacon_int;
#ifdef CONFIG_P2P
- if (wpa_s->conf->p2p_go_ctwindow > conf->beacon_int) {
- wpa_printf(MSG_INFO,
- "CTWindow (%d) is bigger than beacon interval (%d) - avoid configuring it",
- wpa_s->conf->p2p_go_ctwindow, conf->beacon_int);
- conf->p2p_go_ctwindow = 0;
- } else {
- conf->p2p_go_ctwindow = wpa_s->conf->p2p_go_ctwindow;
+ if (ssid->mode == WPAS_MODE_P2P_GO ||
+ ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
+ if (wpa_s->conf->p2p_go_ctwindow > conf->beacon_int) {
+ wpa_printf(MSG_INFO,
+ "CTWindow (%d) is bigger than beacon interval (%d) - avoid configuring it",
+ wpa_s->conf->p2p_go_ctwindow,
+ conf->beacon_int);
+ conf->p2p_go_ctwindow = 0;
+ } else {
+ conf->p2p_go_ctwindow = wpa_s->conf->p2p_go_ctwindow;
+ }
}
#endif /* CONFIG_P2P */
!(bss->wpa & 2)))
goto no_wps; /* WPS2 does not allow WPA/TKIP-only
* configuration */
+ if (ssid->wps_disabled)
+ goto no_wps;
bss->eap_server = 1;
if (!ssid->ignore_broadcast_ssid)
os_memcpy(bss->uuid, wpa_s->conf->uuid, WPS_UUID_LEN);
os_memcpy(bss->os_version, wpa_s->conf->os_version, 4);
bss->pbc_in_m1 = wpa_s->conf->pbc_in_m1;
+ if (ssid->eap.fragment_size != DEFAULT_FRAGMENT_SIZE)
+ bss->fragment_size = ssid->eap.fragment_size;
no_wps:
#endif /* CONFIG_WPS */
wpabuf_dup(wpa_s->conf->ap_vendor_elements);
}
+ bss->ftm_responder = wpa_s->conf->ftm_responder;
+ bss->ftm_initiator = wpa_s->conf->ftm_initiator;
+
return 0;
}
if (event == WPS_EV_FAIL) {
struct wps_event_fail *fail = &data->fail;
- if (wpa_s->parent && wpa_s->parent != wpa_s &&
+ if (wpa_s->p2pdev && wpa_s->p2pdev != wpa_s &&
wpa_s == wpa_s->global->p2p_group_formation) {
/*
* src/ap/wps_hostapd.c has already sent this on the
* main interface, so only send on the parent interface
* here if needed.
*/
- wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL
+ wpa_msg(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_FAIL
"msg=%d config_error=%d",
fail->msg, fail->config_error);
}
{
struct wpa_supplicant *wpa_s = ctx;
+#ifdef CONFIG_ACS
+ if (wpa_s->current_ssid && wpa_s->current_ssid->acs)
+ wpa_s->assoc_freq = wpa_s->ap_iface->freq;
+#endif /* CONFIG_ACS */
+
wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
if (wpa_s->ap_configured_cb)
params.p2p = 1;
#endif /* CONFIG_P2P */
- if (wpa_s->parent->set_ap_uapsd)
- params.uapsd = wpa_s->parent->ap_uapsd;
+ if (wpa_s->p2pdev->set_ap_uapsd)
+ params.uapsd = wpa_s->p2pdev->ap_uapsd;
else if (params.p2p && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD))
params.uapsd = 1; /* mandatory for P2P GO */
else
if (ieee80211_is_dfs(params.freq.freq))
params.freq.freq = 0; /* set channel after CAC */
+ if (params.p2p)
+ wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_GO);
+ else
+ wpa_drv_get_ext_capa(wpa_s, WPA_IF_AP_BSS);
+
if (wpa_drv_associate(wpa_s, ¶ms) < 0) {
wpa_msg(wpa_s, MSG_INFO, "Failed to start AP functionality");
return -1;
}
- wpa_s->ap_iface = hapd_iface = os_zalloc(sizeof(*wpa_s->ap_iface));
+ wpa_s->ap_iface = hapd_iface = hostapd_alloc_iface();
if (hapd_iface == NULL)
return -1;
hapd_iface->owner = wpa_s;
return -1;
}
+ /* Use the maximum oper channel width if it's given. */
+ if (ssid->max_oper_chwidth)
+ conf->vht_oper_chwidth = ssid->max_oper_chwidth;
+
+ ieee80211_freq_to_chan(ssid->vht_center_freq2,
+ &conf->vht_oper_centr_freq_seg1_idx);
+
os_memcpy(wpa_s->ap_iface->conf->wmm_ac_params,
wpa_s->conf->wmm_ac_params,
sizeof(wpa_s->conf->wmm_ac_params));
}
hapd_iface->bss[i]->msg_ctx = wpa_s;
- hapd_iface->bss[i]->msg_ctx_parent = wpa_s->parent;
+ hapd_iface->bss[i]->msg_ctx_parent = wpa_s->p2pdev;
hapd_iface->bss[i]->public_action_cb = ap_public_action_rx;
hapd_iface->bss[i]->public_action_cb_ctx = wpa_s;
hapd_iface->bss[i]->vendor_action_cb = ap_vendor_action_rx;
return -1;
if (pin == NULL) {
- unsigned int rpin = wps_generate_pin();
+ unsigned int rpin;
+
+ if (wps_generate_pin(&rpin) < 0)
+ return -1;
ret_len = os_snprintf(buf, buflen, "%08d", rpin);
if (os_snprintf_error(buflen, ret_len))
return -1;
if (wpa_s->ap_iface == NULL)
return NULL;
hapd = wpa_s->ap_iface->bss[0];
- pin = wps_generate_pin();
+ if (wps_generate_pin(&pin) < 0)
+ return NULL;
os_snprintf(pin_txt, sizeof(pin_txt), "%08u", pin);
os_free(hapd->conf->ap_pin);
hapd->conf->ap_pin = os_strdup(pin_txt);
hapd = wpa_s->ap_iface->bss[0];
wps = hapd->wps;
- if (wpa_s->parent->conf->wps_nfc_dh_pubkey == NULL ||
- wpa_s->parent->conf->wps_nfc_dh_privkey == NULL) {
+ if (wpa_s->p2pdev->conf->wps_nfc_dh_pubkey == NULL ||
+ wpa_s->p2pdev->conf->wps_nfc_dh_privkey == NULL) {
wpa_printf(MSG_DEBUG, "P2P: No NFC DH key known");
return -1;
}
wpabuf_free(wps->dh_pubkey);
wpabuf_free(wps->dh_privkey);
wps->dh_privkey = wpabuf_dup(
- wpa_s->parent->conf->wps_nfc_dh_privkey);
+ wpa_s->p2pdev->conf->wps_nfc_dh_privkey);
wps->dh_pubkey = wpabuf_dup(
- wpa_s->parent->conf->wps_nfc_dh_pubkey);
+ wpa_s->p2pdev->conf->wps_nfc_dh_pubkey);
if (wps->dh_privkey == NULL || wps->dh_pubkey == NULL) {
wps->dh_ctx = NULL;
wpabuf_free(wps->dh_pubkey);
hapd = wpa_s->ap_iface->bss[0];
return hostapd_ctrl_iface_stop_ap(hapd);
}
+
+
+int wpas_ap_pmksa_cache_list(struct wpa_supplicant *wpa_s, char *buf,
+ size_t len)
+{
+ size_t reply_len = 0, i;
+ char ap_delimiter[] = "---- AP ----\n";
+ char mesh_delimiter[] = "---- mesh ----\n";
+ size_t dlen;
+
+ if (wpa_s->ap_iface) {
+ dlen = os_strlen(ap_delimiter);
+ if (dlen > len - reply_len)
+ return reply_len;
+ os_memcpy(&buf[reply_len], ap_delimiter, dlen);
+ reply_len += dlen;
+
+ for (i = 0; i < wpa_s->ap_iface->num_bss; i++) {
+ reply_len += hostapd_ctrl_iface_pmksa_list(
+ wpa_s->ap_iface->bss[i],
+ &buf[reply_len], len - reply_len);
+ }
+ }
+
+ if (wpa_s->ifmsh) {
+ dlen = os_strlen(mesh_delimiter);
+ if (dlen > len - reply_len)
+ return reply_len;
+ os_memcpy(&buf[reply_len], mesh_delimiter, dlen);
+ reply_len += dlen;
+
+ reply_len += hostapd_ctrl_iface_pmksa_list(
+ wpa_s->ifmsh->bss[0], &buf[reply_len],
+ len - reply_len);
+ }
+
+ return reply_len;
+}
+
+
+void wpas_ap_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
+{
+ size_t i;
+
+ if (wpa_s->ap_iface) {
+ for (i = 0; i < wpa_s->ap_iface->num_bss; i++)
+ hostapd_ctrl_iface_pmksa_flush(wpa_s->ap_iface->bss[i]);
+ }
+
+ if (wpa_s->ifmsh)
+ hostapd_ctrl_iface_pmksa_flush(wpa_s->ifmsh->bss[0]);
+}
#endif /* CONFIG_CTRL_IFACE */
const struct wpabuf *pw, const u8 *pubkey_hash);
struct hostapd_config;
-void wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid,
- struct hostapd_config *conf);
+int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
+ struct hostapd_config *conf);
int wpas_ap_stop_ap(struct wpa_supplicant *wpa_s);
+int wpas_ap_pmksa_cache_list(struct wpa_supplicant *wpa_s, char *buf,
+ size_t len);
+void wpas_ap_pmksa_cache_flush(struct wpa_supplicant *wpa_s);
+
void wpas_event_dfs_radar_detected(struct wpa_supplicant *wpa_s,
struct dfs_event *radar);
void wpas_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
/*
* WPA Supplicant - auto scan
* Copyright (c) 2012, Intel Corporation. All rights reserved.
+ * Copyright 2015 Intel Deutschland GmbH
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
#include "scan.h"
#include "autoscan.h"
-#ifdef CONFIG_AUTOSCAN_EXPONENTIAL
-extern const struct autoscan_ops autoscan_exponential_ops;
-#endif /* CONFIG_AUTOSCAN_EXPONENTIAL */
-
-#ifdef CONFIG_AUTOSCAN_PERIODIC
-extern const struct autoscan_ops autoscan_periodic_ops;
-#endif /* CONFIG_AUTOSCAN_PERIODIC */
static const struct autoscan_ops * autoscan_modules[] = {
#ifdef CONFIG_AUTOSCAN_EXPONENTIAL
size_t nlen;
int i;
const struct autoscan_ops *ops = NULL;
+ struct sched_scan_plan *scan_plans;
+
+ /* Give preference to scheduled scan plans if supported/configured */
+ if (wpa_s->sched_scan_plans)
+ return 0;
if (wpa_s->autoscan && wpa_s->autoscan_priv)
return 0;
return -1;
}
+ scan_plans = os_malloc(sizeof(*wpa_s->sched_scan_plans));
+ if (!scan_plans)
+ return -1;
+
wpa_s->autoscan_params = NULL;
wpa_s->autoscan_priv = ops->init(wpa_s, params);
- if (wpa_s->autoscan_priv == NULL)
+ if (!wpa_s->autoscan_priv) {
+ os_free(scan_plans);
return -1;
+ }
+
+ scan_plans[0].interval = 5;
+ scan_plans[0].iterations = 0;
+ os_free(wpa_s->sched_scan_plans);
+ wpa_s->sched_scan_plans = scan_plans;
+ wpa_s->sched_scan_plans_num = 1;
wpa_s->autoscan = ops;
wpa_printf(MSG_DEBUG, "autoscan: Initialized module '%s' with "
wpa_s->autoscan_priv = NULL;
wpa_s->scan_interval = 5;
- wpa_s->sched_scan_interval = 0;
+
+ os_free(wpa_s->sched_scan_plans);
+ wpa_s->sched_scan_plans = NULL;
+ wpa_s->sched_scan_plans_num = 0;
}
}
return -1;
wpa_s->scan_interval = interval;
- wpa_s->sched_scan_interval = interval;
+ wpa_s->sched_scan_plans[0].interval = interval;
request_scan(wpa_s);
}
int autoscan_notify_scan(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res);
+/* Available autoscan modules */
+
+#ifdef CONFIG_AUTOSCAN_EXPONENTIAL
+extern const struct autoscan_ops autoscan_exponential_ops;
+#endif /* CONFIG_AUTOSCAN_EXPONENTIAL */
+
+#ifdef CONFIG_AUTOSCAN_PERIODIC
+extern const struct autoscan_ops autoscan_periodic_ops;
+#endif /* CONFIG_AUTOSCAN_PERIODIC */
+
#else /* CONFIG_AUTOSCAN */
static inline int autoscan_init(struct wpa_supplicant *wpa_s, int req_scan)
#include "config_ssid.h"
#include "bgscan.h"
-#ifdef CONFIG_BGSCAN_SIMPLE
-extern const struct bgscan_ops bgscan_simple_ops;
-#endif /* CONFIG_BGSCAN_SIMPLE */
-#ifdef CONFIG_BGSCAN_LEARN
-extern const struct bgscan_ops bgscan_learn_ops;
-#endif /* CONFIG_BGSCAN_LEARN */
static const struct bgscan_ops * bgscan_modules[] = {
#ifdef CONFIG_BGSCAN_SIMPLE
int current_signal, int current_noise,
int current_txrate);
+/* Available bgscan modules */
+
+#ifdef CONFIG_BGSCAN_SIMPLE
+extern const struct bgscan_ops bgscan_simple_ops;
+#endif /* CONFIG_BGSCAN_SIMPLE */
+#ifdef CONFIG_BGSCAN_LEARN
+extern const struct bgscan_ops bgscan_learn_ops;
+#endif /* CONFIG_BGSCAN_LEARN */
+
#else /* CONFIG_BGSCAN */
static inline int bgscan_init(struct wpa_supplicant *wpa_s,
#include "utils/eloop.h"
#include "common/ieee802_11_defs.h"
#include "drivers/driver.h"
+#include "eap_peer/eap.h"
#include "wpa_supplicant_i.h"
#include "config.h"
#include "notify.h"
anqp = os_zalloc(sizeof(*anqp));
if (anqp == NULL)
return NULL;
+#ifdef CONFIG_INTERWORKING
+ dl_list_init(&anqp->anqp_elems);
+#endif /* CONFIG_INTERWORKING */
anqp->users = 1;
return anqp;
}
#define ANQP_DUP(f) if (anqp->f) n->f = wpabuf_dup(anqp->f)
#ifdef CONFIG_INTERWORKING
+ dl_list_init(&n->anqp_elems);
ANQP_DUP(capability_list);
ANQP_DUP(venue_name);
ANQP_DUP(network_auth_type);
*/
static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp)
{
+#ifdef CONFIG_INTERWORKING
+ struct wpa_bss_anqp_elem *elem;
+#endif /* CONFIG_INTERWORKING */
+
if (anqp == NULL)
return;
wpabuf_free(anqp->nai_realm);
wpabuf_free(anqp->anqp_3gpp);
wpabuf_free(anqp->domain_name);
+
+ while ((elem = dl_list_first(&anqp->anqp_elems,
+ struct wpa_bss_anqp_elem, list))) {
+ dl_list_del(&elem->list);
+ wpabuf_free(elem->payload);
+ os_free(elem);
+ }
#endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_HS20
wpabuf_free(anqp->hs20_capability_list);
}
-static void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
- const char *reason)
+void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
+ const char *reason)
{
if (wpa_s->last_scan_res) {
unsigned int i;
}
+static int wpa_bss_is_wps_candidate(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss)
+{
+#ifdef CONFIG_WPS
+ struct wpa_ssid *ssid;
+ struct wpabuf *wps_ie;
+ int pbc = 0, ret;
+
+ wps_ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
+ if (!wps_ie)
+ return 0;
+
+ if (wps_is_selected_pbc_registrar(wps_ie)) {
+ pbc = 1;
+ } else if (!wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1)) {
+ wpabuf_free(wps_ie);
+ return 0;
+ }
+
+ for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
+ if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS))
+ continue;
+ if (ssid->ssid_len &&
+ (ssid->ssid_len != bss->ssid_len ||
+ os_memcmp(ssid->ssid, bss->ssid, ssid->ssid_len) != 0))
+ continue;
+
+ if (pbc)
+ ret = eap_is_wps_pbc_enrollee(&ssid->eap);
+ else
+ ret = eap_is_wps_pin_enrollee(&ssid->eap);
+ wpabuf_free(wps_ie);
+ return ret;
+ }
+ wpabuf_free(wps_ie);
+#endif /* CONFIG_WPS */
+
+ return 0;
+}
+
+
static int wpa_bss_known(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
{
struct wpa_ssid *ssid;
struct wpa_bss *bss;
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
- if (!wpa_bss_known(wpa_s, bss)) {
+ if (!wpa_bss_known(wpa_s, bss) &&
+ !wpa_bss_is_wps_candidate(wpa_s, bss)) {
wpa_bss_remove(wpa_s, bss, __func__);
return 0;
}
struct wpa_bss *bss, *n;
os_get_reltime(&wpa_s->last_scan);
- if (!new_scan)
+ if ((info && info->aborted) || !new_scan)
return; /* do not expire entries without new scan */
dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
*/
const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie)
{
- const u8 *end, *pos;
-
- pos = (const u8 *) (bss + 1);
- end = pos + bss->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 *) (bss + 1), bss->ie_len, ie);
}
pos = (const u8 *) (bss + 1);
end = pos + bss->ie_len;
- 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 &&
vendor_type == WPA_GET_BE32(&pos[2]))
pos += bss->ie_len;
end = pos + bss->beacon_ie_len;
- 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 &&
vendor_type == WPA_GET_BE32(&pos[2]))
pos = (const u8 *) (bss + 1);
end = pos + bss->ie_len;
- 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 &&
vendor_type == WPA_GET_BE32(&pos[2]))
pos += bss->ie_len;
end = pos + bss->beacon_ie_len;
- 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 &&
vendor_type == WPA_GET_BE32(&pos[2]))
#define WPA_BSS_ASSOCIATED BIT(5)
#define WPA_BSS_ANQP_FETCH_TRIED BIT(6)
+struct wpa_bss_anqp_elem {
+ struct dl_list list;
+ u16 infoid;
+ struct wpabuf *payload;
+};
+
/**
* struct wpa_bss_anqp - ANQP data for a BSS entry (struct wpa_bss)
*/
struct wpabuf *nai_realm;
struct wpabuf *anqp_3gpp;
struct wpabuf *domain_name;
+ struct dl_list anqp_elems; /* list of struct wpa_bss_anqp_elem */
#endif /* CONFIG_INTERWORKING */
#ifdef CONFIG_HS20
struct wpabuf *hs20_capability_list;
void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s,
struct wpa_scan_res *res,
struct os_reltime *fetch_time);
+void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
+ const char *reason);
void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info,
int new_scan);
int wpa_bss_init(struct wpa_supplicant *wpa_s);
return bss->freq > 45000;
}
+/**
+ * Test whether a BSS is a PBSS.
+ * This checks whether a BSS is a DMG-band PBSS. PBSS is used for P2P DMG
+ * network.
+ */
+static inline int bss_is_pbss(struct wpa_bss *bss)
+{
+ return bss_is_dmg(bss) &&
+ (bss->caps & IEEE80211_CAP_DMG_MASK) == IEEE80211_CAP_DMG_PBSS;
+}
+
static inline void wpa_bss_update_level(struct wpa_bss *bss, int new_level)
{
if (bss != NULL && new_level < 0)
/* Configuration variable name */
char *name;
- /* Parser function for this variable */
+ /* Parser function for this variable. The parser functions return 0 or 1
+ * to indicate success. Value 0 indicates that the parameter value may
+ * have changed while value 1 means that the value did not change.
+ * Error cases (failure to parse the string) are indicated by returning
+ * -1. */
int (*parser)(const struct parse_data *data, struct wpa_ssid *ssid,
int line, const char *value);
struct wpa_ssid *ssid,
int line, const char *value)
{
- size_t res_len, *dst_len;
+ size_t res_len, *dst_len, prev_len;
char **dst, *tmp;
if (os_strcmp(value, "NULL") == 0) {
set:
dst = (char **) (((u8 *) ssid) + (long) data->param1);
dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2);
+
+ if (data->param2)
+ prev_len = *dst_len;
+ else if (*dst)
+ prev_len = os_strlen(*dst);
+ else
+ prev_len = 0;
+ if ((*dst == NULL && tmp == NULL) ||
+ (*dst && tmp && prev_len == res_len &&
+ os_memcmp(*dst, tmp, res_len) == 0)) {
+ /* No change to the previously configured value */
+ os_free(tmp);
+ return 1;
+ }
+
os_free(*dst);
*dst = tmp;
if (data->param2)
line, value);
return -1;
}
+
+ if (*dst == val)
+ return 1;
*dst = val;
wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst);
}
wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",
(u8 *) value, len);
+ if (has_ctrl_char((u8 *) value, len)) {
+ wpa_printf(MSG_ERROR,
+ "Line %d: Invalid passphrase character",
+ line);
+ return -1;
+ }
if (ssid->passphrase && os_strlen(ssid->passphrase) == len &&
- os_memcmp(ssid->passphrase, value, len) == 0)
- return 0;
+ os_memcmp(ssid->passphrase, value, len) == 0) {
+ /* No change to the previously configured value */
+ return 1;
+ }
ssid->psk_set = 0;
str_clear_free(ssid->passphrase);
ssid->passphrase = dup_binstr(value, len);
errors++;
}
+ if (!errors && ssid->proto == val)
+ return 1;
wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val);
ssid->proto = val;
return errors ? -1 : 0;
errors++;
}
+ if (!errors && ssid->key_mgmt == val)
+ return 1;
wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val);
ssid->key_mgmt = val;
return errors ? -1 : 0;
static int wpa_config_parse_cipher(int line, const char *value)
{
+#ifdef CONFIG_NO_WPA
+ return -1;
+#else /* CONFIG_NO_WPA */
int val = wpa_parse_cipher(value);
if (val < 0) {
wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
return -1;
}
return val;
+#endif /* CONFIG_NO_WPA */
}
#ifndef NO_CONFIG_WRITE
static char * wpa_config_write_cipher(int cipher)
{
+#ifdef CONFIG_NO_WPA
+ return NULL;
+#else /* CONFIG_NO_WPA */
char *buf = os_zalloc(50);
if (buf == NULL)
return NULL;
}
return buf;
+#endif /* CONFIG_NO_WPA */
}
#endif /* NO_CONFIG_WRITE */
return -1;
}
+ if (ssid->pairwise_cipher == val)
+ return 1;
wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val);
ssid->pairwise_cipher = val;
return 0;
return -1;
}
+ if (ssid->group_cipher == val)
+ return 1;
wpa_printf(MSG_MSGDUMP, "group: 0x%x", val);
ssid->group_cipher = val;
return 0;
errors++;
}
+ if (!errors && ssid->auth_alg == val)
+ return 1;
wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val);
ssid->auth_alg = val;
return errors ? -1 : 0;
methods[num_methods].method = EAP_TYPE_NONE;
num_methods++;
+ if (!errors && ssid->eap.eap_methods) {
+ struct eap_method_type *prev_m;
+ size_t i, j, prev_methods, match = 0;
+
+ prev_m = ssid->eap.eap_methods;
+ for (i = 0; prev_m[i].vendor != EAP_VENDOR_IETF ||
+ prev_m[i].method != EAP_TYPE_NONE; i++) {
+ /* Count the methods */
+ }
+ prev_methods = i + 1;
+
+ for (i = 0; prev_methods == num_methods && i < prev_methods;
+ i++) {
+ for (j = 0; j < num_methods; j++) {
+ if (prev_m[i].vendor == methods[j].vendor &&
+ prev_m[i].method == methods[j].method) {
+ match++;
+ break;
+ }
+ }
+ }
+ if (match == num_methods) {
+ os_free(methods);
+ return 1;
+ }
+ }
wpa_hexdump(MSG_MSGDUMP, "eap methods",
(u8 *) methods, num_methods * sizeof(*methods));
os_free(ssid->eap.eap_methods);
u8 *hash;
if (os_strcmp(value, "NULL") == 0) {
+ if (!ssid->eap.password)
+ return 1; /* Already unset */
wpa_printf(MSG_DEBUG, "Unset configuration string 'password'");
bin_clear_free(ssid->eap.password, ssid->eap.password_len);
ssid->eap.password = NULL;
wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16);
+ if (ssid->eap.password && ssid->eap.password_len == 16 &&
+ os_memcmp(ssid->eap.password, hash, 16) == 0 &&
+ (ssid->eap.flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH)) {
+ bin_clear_free(hash, 16);
+ return 1;
+ }
bin_clear_free(ssid->eap.password, ssid->eap.password_len);
ssid->eap.password = hash;
ssid->eap.password_len = 16;
{ FUNC(auth_alg) },
{ FUNC(scan_freq) },
{ FUNC(freq_list) },
+ { INT_RANGE(max_oper_chwidth, VHT_CHANWIDTH_USE_HT,
+ VHT_CHANWIDTH_80P80MHZ) },
#ifdef IEEE8021X_EAPOL
{ FUNC(eap) },
{ STR_LENe(identity) },
{ INT_RANGE(mixed_cell, 0, 1) },
{ INT_RANGE(frequency, 0, 65000) },
{ INT_RANGE(fixed_freq, 0, 1) },
+#ifdef CONFIG_ACS
+ { INT_RANGE(acs, 0, 1) },
+#endif /* CONFIG_ACS */
#ifdef CONFIG_MESH
{ FUNC(mesh_basic_rates) },
{ INT(dot11MeshMaxRetries) },
{ INT(dot11MeshHoldingTimeout) },
#endif /* CONFIG_MESH */
{ INT(wpa_ptk_rekey) },
+ { INT(group_rekey) },
{ STR(bgscan) },
{ INT_RANGE(ignore_broadcast_ssid, 0, 2) },
#ifdef CONFIG_P2P
{ INT(update_identifier) },
#endif /* CONFIG_HS20 */
{ INT_RANGE(mac_addr, 0, 2) },
+ { INT_RANGE(pbss, 0, 2) },
+ { INT_RANGE(wps_disabled, 0, 1) },
};
#undef OFFSET
os_free(config->bgscan);
os_free(config->wowlan_triggers);
os_free(config->fst_group_id);
+ os_free(config->sched_scan_plans);
+#ifdef CONFIG_MBO
+ os_free(config->non_pref_chan);
+#endif /* CONFIG_MBO */
+
os_free(config);
}
* @var: Variable name, e.g., "ssid"
* @value: Variable value
* @line: Line number in configuration file or 0 if not used
- * Returns: 0 on success, -1 on failure
+ * Returns: 0 on success with possible change in the value, 1 on success with
+ * no change to previously configured value, or -1 on failure
*
* This function can be used to set network configuration variables based on
* both the configuration file and management interface input. The value
if (os_strcmp(var, field->name) != 0)
continue;
- if (field->parser(field, ssid, line, value)) {
+ ret = field->parser(field, ssid, line, value);
+ if (ret < 0) {
if (line) {
wpa_printf(MSG_ERROR, "Line %d: failed to "
"parse %s '%s'.", line, var, value);
return props;
err:
- value = *props;
- while (value)
- os_free(value++);
+ for (i = 0; props[i]; i++)
+ os_free(props[i]);
os_free(props);
return NULL;
#endif /* NO_CONFIG_WRITE */
for (i = 0; i < NUM_SSID_FIELDS; i++) {
const struct parse_data *field = &ssid_fields[i];
- if (os_strcmp(var, field->name) == 0)
- return field->writer(field, ssid);
+ if (os_strcmp(var, field->name) == 0) {
+ char *ret = field->writer(field, ssid);
+
+ if (ret && has_newline(ret)) {
+ wpa_printf(MSG_ERROR,
+ "Found newline in value for %s; not returning it",
+ var);
+ os_free(ret);
+ ret = NULL;
+ }
+
+ return ret;
+ }
}
return NULL;
if (os_strcmp(var, "password") == 0 &&
os_strncmp(value, "ext:", 4) == 0) {
+ if (has_newline(value))
+ return -1;
str_clear_free(cred->password);
cred->password = os_strdup(value);
cred->ext_password = 1;
}
val = wpa_config_parse_string(value, &len);
- if (val == NULL) {
+ if (val == NULL ||
+ (os_strcmp(var, "excluded_ssid") != 0 &&
+ os_strcmp(var, "roaming_consortium") != 0 &&
+ os_strcmp(var, "required_roaming_consortium") != 0 &&
+ has_newline(val))) {
wpa_printf(MSG_ERROR, "Line %d: invalid field '%s' string "
"value '%s'.", line, var, value);
+ os_free(val);
return -1;
}
config->rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME;
config->key_mgmt_offload = DEFAULT_KEY_MGMT_OFFLOAD;
config->cert_in_cb = DEFAULT_CERT_IN_CB;
+ config->wpa_rsc_relaxation = DEFAULT_WPA_RSC_RELAXATION;
+
+#ifdef CONFIG_MBO
+ config->mbo_cell_capa = DEFAULT_MBO_CELL_CAPA;
+#endif /* CONFIG_MBO */
if (ctrl_interface)
config->ctrl_interface = os_strdup(ctrl_interface);
return -1;
}
+ if (has_newline(pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid %s value with newline",
+ line, data->name);
+ return -1;
+ }
+
tmp = os_strdup(pos);
if (tmp == NULL)
return -1;
struct wpa_config *config, int line,
const char *pos)
{
- size_t len;
struct wpabuf **dst, *tmp;
- len = os_strlen(pos);
- if (len & 0x01)
- return -1;
-
- tmp = wpabuf_alloc(len / 2);
- if (tmp == NULL)
+ tmp = wpabuf_parse_bin(pos);
+ if (!tmp)
return -1;
- if (hexstr2bin(pos, wpabuf_put(tmp, len / 2), len / 2)) {
- wpabuf_free(tmp);
- return -1;
- }
-
dst = (struct wpabuf **) (((u8 *) config) + (long) data->param1);
wpabuf_free(*dst);
*dst = tmp;
{ INT_RANGE(fst_priority, 1, FST_MAX_PRIO_VALUE), 0 },
{ INT_RANGE(fst_llt, 1, FST_MAX_LLT_MS), 0 },
#endif /* CONFIG_FST */
+ { INT_RANGE(wpa_rsc_relaxation, 0, 1), 0 },
+ { STR(sched_scan_plans), CFG_CHANGED_SCHED_SCAN_PLANS },
+#ifdef CONFIG_MBO
+ { STR(non_pref_chan), 0 },
+ { INT_RANGE(mbo_cell_capa, MBO_CELL_CAPA_AVAILABLE,
+ MBO_CELL_CAPA_NOT_SUPPORTED), 0 },
+#endif /*CONFIG_MBO */
+ { INT(gas_address3), 0 },
+ { INT_RANGE(ftm_responder, 0, 1), 0 },
+ { INT_RANGE(ftm_initiator, 0, 1), 0 },
};
#undef FUNC
}
+int wpa_config_get_num_global_field_names(void)
+{
+ return NUM_GLOBAL_FIELDS;
+}
+
+
+const char * wpa_config_get_global_field_name(unsigned int i, int *no_var)
+{
+ if (i >= NUM_GLOBAL_FIELDS)
+ return NULL;
+
+ if (no_var)
+ *no_var = !global_fields[i].param1;
+ return global_fields[i].name;
+}
+
+
int wpa_config_process_global(struct wpa_config *config, char *pos, int line)
{
size_t i;
#define DEFAULT_KEY_MGMT_OFFLOAD 1
#define DEFAULT_CERT_IN_CB 1
#define DEFAULT_P2P_GO_CTWINDOW 0
+#define DEFAULT_WPA_RSC_RELAXATION 1
+#define DEFAULT_MBO_CELL_CAPA MBO_CELL_CAPA_NOT_SUPPORTED
#include "config_ssid.h"
#include "wps/wps.h"
#define CFG_CHANGED_EXT_PW_BACKEND BIT(14)
#define CFG_CHANGED_NFC_PASSWORD_TOKEN BIT(15)
#define CFG_CHANGED_P2P_PASSPHRASE_LEN BIT(16)
+#define CFG_CHANGED_SCHED_SCAN_PLANS BIT(17)
/**
* struct wpa_config - wpa_supplicant configuration data
* frequency list of the local device and the peer device.
*
* @P2P_GO_FREQ_MOVE_STAY: Prefer to stay on the current frequency.
+ *
+ * @P2P_GO_FREQ_MOVE_SCM_ECSA: Same as
+ * P2P_GO_FREQ_MOVE_SCM_PEER_SUPPORTS but a transition is possible only
+ * if all the group members advertise eCSA support.
*/
enum {
P2P_GO_FREQ_MOVE_SCM = 0,
P2P_GO_FREQ_MOVE_SCM_PEER_SUPPORTS = 1,
P2P_GO_FREQ_MOVE_STAY = 2,
- P2P_GO_FREQ_MOVE_MAX = P2P_GO_FREQ_MOVE_STAY,
+ P2P_GO_FREQ_MOVE_SCM_ECSA = 3,
+ P2P_GO_FREQ_MOVE_MAX = P2P_GO_FREQ_MOVE_SCM_ECSA,
} p2p_go_freq_change_policy;
#define DEFAULT_P2P_GO_FREQ_MOVE P2P_GO_FREQ_MOVE_STAY
*
* By default, PMF is disabled unless enabled by the per-network
* ieee80211w=1 or ieee80211w=2 parameter. pmf=1/2 can be used to change
- * this default behavior.
+ * this default behavior for RSN network (this is not applicable for
+ * non-RSN cases).
*/
enum mfp_options pmf;
* interface.
*/
int fst_llt;
+
+ /**
+ * wpa_rsc_relaxation - RSC relaxation on GTK installation
+ *
+ * Values:
+ * 0 - use the EAPOL-Key RSC value on GTK installation
+ * 1 - use the null RSC if a bogus RSC value is detected in message 3
+ * of 4-Way Handshake or message 1 of Group Key Handshake.
+ */
+ int wpa_rsc_relaxation;
+
+ /**
+ * sched_scan_plans - Scan plans for scheduled scan
+ *
+ * Each scan plan specifies the interval between scans and the number of
+ * iterations. The last scan plan only specifies the scan interval and
+ * will be run infinitely.
+ *
+ * format: <interval:iterations> <interval2:iterations2> ... <interval>
+ */
+ char *sched_scan_plans;
+
+#ifdef CONFIG_MBO
+ /**
+ * non_pref_chan - Non-preferred channels list, separated by spaces.
+ *
+ * format: op_class:chan:preference:reason<:detail>
+ * Detail is optional.
+ */
+ char *non_pref_chan;
+
+ /**
+ * mbo_cell_capa - Cellular capabilities for MBO
+ */
+ enum mbo_cellular_capa mbo_cell_capa;
+#endif /* CONFIG_MBO */
+
+ /**
+ * gas_address3 - GAS Address3 field behavior
+ *
+ * Values:
+ * 0 - P2P specification (Address3 = AP BSSID)
+ * 1 = IEEE 802.11 standard compliant (Address3 = Wildcard BSSID when
+ * sent to not-associated AP; if associated, AP BSSID)
+ */
+ int gas_address3;
+
+ /**
+ * ftm_responder - Publish FTM (fine timing measurement)
+ * responder functionality
+ *
+ * Values:
+ * 0 - do not publish FTM responder functionality (Default)
+ * 1 - publish FTM responder functionality in
+ * bit 70 of Extended Capabilities element
+ * Note, actual FTM responder operation is managed outside
+ * wpa_supplicant.
+ */
+ int ftm_responder;
+
+ /**
+ * ftm_initiator - Publish FTM (fine timing measurement)
+ * initiator functionality
+ *
+ * Values:
+ * 0 - do not publish FTM initiator functionality (Default)
+ * 1 - publish FTM initiator functionality in
+ * bit 71 of Extended Capabilities element
+ * Note, actual FTM initiator operation is managed outside
+ * wpa_supplicant.
+ */
+ int ftm_initiator;
};
/* Prototypes for common functions from config.c */
int wpa_config_process_global(struct wpa_config *config, char *pos, int line);
+int wpa_config_get_num_global_field_names(void);
+
+const char * wpa_config_get_global_field_name(unsigned int i, int *no_var);
/* Prototypes for backend specific functions from the selected config_*.c */
INT(no_auto_peer);
INT(frequency);
INT(fixed_freq);
+#ifdef CONFIG_ACS
+ INT(acs);
+#endif /* CONFIG_ACS */
write_int(f, "proactive_key_caching", ssid->proactive_key_caching, -1);
INT(disabled);
INT(peerkey);
INT(mixed_cell);
+ INT(max_oper_chwidth);
+ INT(pbss);
+ INT(wps_disabled);
#ifdef CONFIG_IEEE80211W
write_int(f, "ieee80211w", ssid->ieee80211w,
MGMT_FRAME_PROTECTION_DEFAULT);
INT_DEF(dot11MeshHoldingTimeout, DEFAULT_MESH_HOLDING_TIMEOUT);
#endif /* CONFIG_MESH */
INT(wpa_ptk_rekey);
+ INT(group_rekey);
INT(ignore_broadcast_ssid);
#ifdef CONFIG_HT_OVERRIDES
INT_DEF(disable_ht, DEFAULT_DISABLE_HT);
if (config->p2p_go_freq_change_policy != DEFAULT_P2P_GO_FREQ_MOVE)
fprintf(f, "p2p_go_freq_change_policy=%u\n",
config->p2p_go_freq_change_policy);
+ if (WPA_GET_BE32(config->ip_addr_go))
+ fprintf(f, "ip_addr_go=%u.%u.%u.%u\n",
+ config->ip_addr_go[0], config->ip_addr_go[1],
+ config->ip_addr_go[2], config->ip_addr_go[3]);
+ if (WPA_GET_BE32(config->ip_addr_mask))
+ fprintf(f, "ip_addr_mask=%u.%u.%u.%u\n",
+ config->ip_addr_mask[0], config->ip_addr_mask[1],
+ config->ip_addr_mask[2], config->ip_addr_mask[3]);
+ if (WPA_GET_BE32(config->ip_addr_start))
+ fprintf(f, "ip_addr_start=%u.%u.%u.%u\n",
+ config->ip_addr_start[0], config->ip_addr_start[1],
+ config->ip_addr_start[2], config->ip_addr_start[3]);
+ if (WPA_GET_BE32(config->ip_addr_end))
+ fprintf(f, "ip_addr_end=%u.%u.%u.%u\n",
+ config->ip_addr_end[0], config->ip_addr_end[1],
+ config->ip_addr_end[2], config->ip_addr_end[3]);
#endif /* CONFIG_P2P */
if (config->country[0] && config->country[1]) {
fprintf(f, "country=%c%c\n",
if (config->wps_priority)
fprintf(f, "wps_priority=%d\n", config->wps_priority);
+
+ if (config->wpa_rsc_relaxation != DEFAULT_WPA_RSC_RELAXATION)
+ fprintf(f, "wpa_rsc_relaxation=%d\n",
+ config->wpa_rsc_relaxation);
+
+ if (config->sched_scan_plans)
+ fprintf(f, "sched_scan_plans=%s\n", config->sched_scan_plans);
+
+#ifdef CONFIG_MBO
+ if (config->non_pref_chan)
+ fprintf(f, "non_pref_chan=%s\n", config->non_pref_chan);
+ if (config->mbo_cell_capa != DEFAULT_MBO_CELL_CAPA)
+ fprintf(f, "mbo_cell_capa=%u\n", config->mbo_cell_capa);
+#endif /* CONFIG_MBO */
+
+ if (config->gas_address3)
+ fprintf(f, "gas_address3=%d\n", config->gas_address3);
+
+ if (config->ftm_responder)
+ fprintf(f, "ftm_responder=%d\n", config->ftm_responder);
+ if (config->ftm_initiator)
+ fprintf(f, "ftm_initiator=%d\n", config->ftm_initiator);
}
#endif /* CONFIG_NO_CONFIG_WRITE */
} mode;
/**
+ * pbss - Whether to use PBSS. Relevant to DMG networks only.
+ * 0 = do not use PBSS
+ * 1 = use PBSS
+ * 2 = don't care (not allowed in AP mode)
+ * Used together with mode configuration. When mode is AP, it
+ * means to start a PCP instead of a regular AP. When mode is INFRA it
+ * means connect to a PCP instead of AP. In this mode you can also
+ * specify 2 (don't care) meaning connect to either AP or PCP.
+ * P2P_GO and P2P_GROUP_FORMATION modes must use PBSS in DMG network.
+ */
+ int pbss;
+
+ /**
* disabled - Whether this network is currently disabled
*
* 0 = this network can be used (default).
*/
int fixed_freq;
+#ifdef CONFIG_ACS
+ /**
+ * ACS - Automatic Channel Selection for AP mode
+ *
+ * If present, it will be handled together with frequency.
+ * frequency will be used to determine hardware mode only, when it is
+ * used for both hardware mode and channel when used alone. This will
+ * force the channel to be set to 0, thus enabling ACS.
+ */
+ int acs;
+#endif /* CONFIG_ACS */
+
/**
* mesh_basic_rates - BSS Basic rate set for mesh network
*
int vht;
+ u8 max_oper_chwidth;
+
+ unsigned int vht_center_freq2;
+
/**
* wpa_ptk_rekey - Maximum lifetime for PTK in seconds
*
int wpa_ptk_rekey;
/**
+ * group_rekey - Group rekeying time in seconds
+ *
+ * This value, if non-zero, is used as the dot11RSNAConfigGroupRekeyTime
+ * parameter when operating in Authenticator role in IBSS.
+ */
+ int group_rekey;
+
+ /**
* scan_freq - Array of frequencies to scan or %NULL for all
*
* This is an optional zero-terminated array of frequencies in
* this MBSS will trigger a peering attempt.
*/
int no_auto_peer;
+
+ /**
+ * wps_disabled - WPS disabled in AP mode
+ *
+ * 0 = WPS enabled and configured (default)
+ * 1 = WPS disabled
+ */
+ int wps_disabled;
};
#endif /* CONFIG_SSID_H */
#ifdef CONFIG_HS20
INT(update_identifier);
#endif /* CONFIG_HS20 */
+ INT(group_rekey);
#undef STR
#undef INT
#include "utils/common.h"
#include "utils/eloop.h"
#include "utils/uuid.h"
+#include "utils/module_tests.h"
#include "common/version.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
static int wpa_supplicant_global_iface_list(struct wpa_global *global,
char *buf, int len);
static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
+ const char *input,
char *buf, int len);
static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s,
char *val);
}
+static int wpas_ctrl_iface_set_lci(struct wpa_supplicant *wpa_s,
+ const char *cmd)
+{
+ struct wpabuf *lci;
+
+ if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) {
+ wpabuf_free(wpa_s->lci);
+ wpa_s->lci = NULL;
+ return 0;
+ }
+
+ lci = wpabuf_parse_bin(cmd);
+ if (!lci)
+ return -1;
+
+ if (os_get_reltime(&wpa_s->lci_time)) {
+ wpabuf_free(lci);
+ return -1;
+ }
+
+ wpabuf_free(wpa_s->lci);
+ wpa_s->lci = lci;
+
+ return 0;
+}
+
+
static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
char *cmd)
{
wps_corrupt_pkhash = atoi(value);
wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
wps_corrupt_pkhash);
+ } else if (os_strcasecmp(cmd, "wps_force_auth_types") == 0) {
+ if (value[0] == '\0') {
+ wps_force_auth_types_in_use = 0;
+ } else {
+ wps_force_auth_types = strtol(value, NULL, 0);
+ wps_force_auth_types_in_use = 1;
+ }
+ } else if (os_strcasecmp(cmd, "wps_force_encr_types") == 0) {
+ if (value[0] == '\0') {
+ wps_force_encr_types_in_use = 0;
+ } else {
+ wps_force_encr_types = strtol(value, NULL, 0);
+ wps_force_encr_types_in_use = 1;
+ }
#endif /* CONFIG_WPS_TESTING */
} else if (os_strcasecmp(cmd, "ampdu") == 0) {
if (wpa_drv_ampdu(wpa_s, atoi(value)) < 0)
#ifdef CONFIG_TDLS
#ifdef CONFIG_TDLS_TESTING
} else if (os_strcasecmp(cmd, "tdls_testing") == 0) {
- extern unsigned int tdls_testing;
tdls_testing = strtol(value, NULL, 0);
wpa_printf(MSG_DEBUG, "TDLS: tdls_testing=0x%x", tdls_testing);
#endif /* CONFIG_TDLS_TESTING */
wpa_s->extra_roc_dur = atoi(value);
} else if (os_strcasecmp(cmd, "test_failure") == 0) {
wpa_s->test_failure = atoi(value);
+ } else if (os_strcasecmp(cmd, "p2p_go_csa_on_inv") == 0) {
+ wpa_s->p2p_go_csa_on_inv = !!atoi(value);
+ } else if (os_strcasecmp(cmd, "ignore_auth_resp") == 0) {
+ wpa_s->ignore_auth_resp = !!atoi(value);
+ } else if (os_strcasecmp(cmd, "ignore_assoc_disallow") == 0) {
+ wpa_s->ignore_assoc_disallow = !!atoi(value);
+ } else if (os_strcasecmp(cmd, "reject_btm_req_reason") == 0) {
+ wpa_s->reject_btm_req_reason = atoi(value);
#endif /* CONFIG_TESTING_OPTIONS */
#ifndef CONFIG_NO_CONFIG_BLOBS
} else if (os_strcmp(cmd, "blob") == 0) {
#endif /* CONFIG_NO_CONFIG_BLOBS */
} else if (os_strcasecmp(cmd, "setband") == 0) {
ret = wpas_ctrl_set_band(wpa_s, value);
+#ifdef CONFIG_MBO
+ } else if (os_strcasecmp(cmd, "non_pref_chan") == 0) {
+ ret = wpas_mbo_update_non_pref_chan(wpa_s, value);
+ } else if (os_strcasecmp(cmd, "mbo_cell_capa") == 0) {
+ wpas_mbo_update_cell_capa(wpa_s, atoi(value));
+#endif /* CONFIG_MBO */
+ } else if (os_strcasecmp(cmd, "lci") == 0) {
+ ret = wpas_ctrl_iface_set_lci(wpa_s, value);
} else {
value[-1] = '=';
ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
if (os_strcmp(cmd, "any") == 0)
_bssid = NULL;
else if (os_strcmp(cmd, "get") == 0) {
- ret = wps_generate_pin();
+ if (wps_generate_pin((unsigned int *) &ret) < 0)
+ return -1;
goto done;
} else if (hwaddr_aton(cmd, bssid)) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
"mode=P2P GO - group "
"formation\n");
break;
+ case WPAS_MODE_MESH:
+ ret = os_snprintf(pos, end - pos,
+ "mode=mesh\n");
+ break;
default:
ret = 0;
break;
return 0;
}
+
+static int wpa_supplicant_ctrl_iface_mesh_peer_remove(
+ struct wpa_supplicant *wpa_s, char *cmd)
+{
+ u8 addr[ETH_ALEN];
+
+ if (hwaddr_aton(cmd, addr) < 0)
+ return -1;
+
+ return wpas_mesh_peer_remove(wpa_s, addr);
+}
+
+
+static int wpa_supplicant_ctrl_iface_mesh_peer_add(
+ struct wpa_supplicant *wpa_s, char *cmd)
+{
+ u8 addr[ETH_ALEN];
+ int duration;
+ char *pos;
+
+ pos = os_strstr(cmd, " duration=");
+ if (pos) {
+ *pos = '\0';
+ duration = atoi(pos + 10);
+ } else {
+ duration = -1;
+ }
+
+ if (hwaddr_aton(cmd, addr))
+ return -1;
+
+ return wpas_mesh_peer_add(wpa_s, addr, duration);
+}
+
#endif /* CONFIG_MESH */
wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
- ssid = wpa_config_add_network(wpa_s->conf);
+ ssid = wpa_supplicant_add_network(wpa_s);
if (ssid == NULL)
return -1;
- wpas_notify_network_added(wpa_s, ssid);
-
- ssid->disabled = 1;
- wpa_config_set_network_defaults(ssid);
-
ret = os_snprintf(buf, buflen, "%d\n", ssid->id);
if (os_snprintf_error(buflen, ret))
return -1;
{
int id;
struct wpa_ssid *ssid;
- int was_disabled;
+ int result;
/* cmd: "<network id>" or "all" */
if (os_strcmp(cmd, "all") == 0) {
id = atoi(cmd);
wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
- ssid = wpa_config_get_network(wpa_s->conf, id);
- if (ssid)
- wpas_notify_network_removed(wpa_s, ssid);
- if (ssid == NULL) {
+ result = wpa_supplicant_remove_network(wpa_s, id);
+ if (result == -1) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
"id=%d", id);
return -1;
}
-
- if (wpa_s->last_ssid == ssid)
- wpa_s->last_ssid = NULL;
-
- if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
-#ifdef CONFIG_SME
- wpa_s->sme.prev_bssid_set = 0;
-#endif /* CONFIG_SME */
- /*
- * Invalidate the EAP session cache if the current or
- * previously used network is removed.
- */
- eapol_sm_invalidate_cached_session(wpa_s->eapol);
- }
-
- if (ssid == wpa_s->current_ssid) {
- wpa_sm_set_config(wpa_s->wpa, NULL);
- eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
-
- if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
- wpa_s->own_disconnect_req = 1;
- wpa_supplicant_deauthenticate(wpa_s,
- WLAN_REASON_DEAUTH_LEAVING);
- }
-
- was_disabled = ssid->disabled;
-
- if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
+ if (result == -2) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Not able to remove the "
"network id=%d", id);
return -1;
}
-
- if (!was_disabled && wpa_s->sched_scanning) {
- wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to remove "
- "network from filters");
- wpa_supplicant_cancel_sched_scan(wpa_s);
- wpa_supplicant_req_scan(wpa_s, 0, 0);
- }
-
return 0;
}
struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
char *name, char *value)
{
- if (wpa_config_set(ssid, name, value, 0) < 0) {
+ int ret;
+
+ ret = wpa_config_set(ssid, name, value, 0);
+ if (ret < 0) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
"variable '%s'", name);
return -1;
}
+ if (ret == 1)
+ return 0; /* No change to the previously configured value */
if (os_strcmp(name, "bssid") != 0 &&
- os_strcmp(name, "priority") != 0)
+ os_strcmp(name, "priority") != 0) {
wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
- if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL) {
- /*
- * Invalidate the EAP session cache if anything in the current
- * or previously used configuration changes.
- */
- eapol_sm_invalidate_cached_session(wpa_s->eapol);
+ if (wpa_s->current_ssid == ssid ||
+ wpa_s->current_ssid == NULL) {
+ /*
+ * Invalidate the EAP session cache if anything in the
+ * current or previously used configuration changes.
+ */
+ eapol_sm_invalidate_cached_session(wpa_s->eapol);
+ }
}
if ((os_strcmp(name, "psk") == 0 &&
}
#endif /* CONFIG_FIPS */
+#ifdef CONFIG_ACS
+ if (os_strcmp(field, "acs") == 0) {
+ res = os_snprintf(buf, buflen, "ACS");
+ if (os_snprintf_error(buflen, res))
+ return -1;
+ return res;
+ }
+#endif /* CONFIG_ACS */
+
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
field);
if (mask & WPA_BSS_MASK_P2P_SCAN) {
ie = (const u8 *) (bss + 1);
ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end);
- if (ret < 0 || ret >= end - pos)
+ if (ret >= end - pos)
return 0;
- pos += ret;
+ if (ret > 0)
+ pos += ret;
}
#endif /* CONFIG_P2P */
#ifdef CONFIG_INTERWORKING
if ((mask & WPA_BSS_MASK_INTERNETW) && bss->anqp) {
struct wpa_bss_anqp *anqp = bss->anqp;
+ struct wpa_bss_anqp_elem *elem;
+
pos = anqp_add_hex(pos, end, "anqp_capability_list",
anqp->capability_list);
pos = anqp_add_hex(pos, end, "anqp_venue_name",
pos = anqp_add_hex(pos, end, "hs20_osu_providers_list",
anqp->hs20_osu_providers_list);
#endif /* CONFIG_HS20 */
+
+ dl_list_for_each(elem, &anqp->anqp_elems,
+ struct wpa_bss_anqp_elem, list) {
+ char title[20];
+
+ os_snprintf(title, sizeof(title), "anqp[%u]",
+ elem->infoid);
+ pos = anqp_add_hex(pos, end, title, elem->payload);
+ }
}
#endif /* CONFIG_INTERWORKING */
if (mask & WPA_BSS_MASK_MESH_SCAN) {
ie = (const u8 *) (bss + 1);
ret = wpas_mesh_scan_result_text(ie, bss->ie_len, pos, end);
- if (ret < 0 || ret >= end - pos)
+ if (ret >= end - pos)
return 0;
- pos += ret;
+ if (ret > 0)
+ pos += ret;
}
#endif /* CONFIG_MESH */
return -1;
}
- if (isblank(*last)) {
+ if (isblank((unsigned char) *last)) {
i++;
break;
}
}
+static int parse_freq(int chwidth, int freq2)
+{
+ if (freq2 < 0)
+ return -1;
+ if (freq2)
+ return VHT_CHANWIDTH_80P80MHZ;
+
+ switch (chwidth) {
+ case 0:
+ case 20:
+ case 40:
+ return VHT_CHANWIDTH_USE_HT;
+ case 80:
+ return VHT_CHANWIDTH_80MHZ;
+ case 160:
+ return VHT_CHANWIDTH_160MHZ;
+ default:
+ wpa_printf(MSG_DEBUG, "Unknown max oper bandwidth: %d",
+ chwidth);
+ return -1;
+ }
+}
+
+
static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
char *buf, size_t buflen)
{
int go_intent = -1;
int freq = 0;
int pd;
- int ht40, vht;
+ int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
+ u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL;
+ size_t group_ssid_len = 0;
if (!wpa_s->global->p2p_init_wpa_s)
return -1;
/* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps]
* [persistent|persistent=<network id>]
* [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc]
- * [ht40] [vht] [auto] */
+ * [ht40] [vht] [auto] [ssid=<hexdump>] */
if (hwaddr_aton(cmd, addr))
return -1;
return -1;
}
+ pos2 = os_strstr(pos, " freq2=");
+ if (pos2)
+ freq2 = atoi(pos2 + 7);
+
+ pos2 = os_strstr(pos, " max_oper_chwidth=");
+ if (pos2)
+ chwidth = atoi(pos2 + 18);
+
+ max_oper_chwidth = parse_freq(chwidth, freq2);
+ if (max_oper_chwidth < 0)
+ return -1;
+
+ pos2 = os_strstr(pos, " ssid=");
+ if (pos2) {
+ char *end;
+
+ pos2 += 6;
+ end = os_strchr(pos2, ' ');
+ if (!end)
+ group_ssid_len = os_strlen(pos2) / 2;
+ else
+ group_ssid_len = (end - pos2) / 2;
+ if (group_ssid_len == 0 || group_ssid_len > SSID_MAX_LEN ||
+ hexstr2bin(pos2, _group_ssid, group_ssid_len) < 0)
+ return -1;
+ group_ssid = _group_ssid;
+ }
+
if (os_strncmp(pos, "pin", 3) == 0) {
/* Request random PIN (to be displayed) and enable the PIN */
wps_method = WPS_PIN_DISPLAY;
} else if (os_strncmp(pos, "pbc", 3) == 0) {
wps_method = WPS_PBC;
+ } else if (os_strstr(pos, "p2ps") != NULL) {
+ wps_method = WPS_P2PS;
} else {
pin = pos;
pos = os_strchr(pin, ' ');
*pos++ = '\0';
if (os_strncmp(pos, "display", 7) == 0)
wps_method = WPS_PIN_DISPLAY;
- else if (os_strncmp(pos, "p2ps", 4) == 0)
- wps_method = WPS_P2PS;
}
if (!wps_pin_str_valid(pin)) {
os_memcpy(buf, "FAIL-INVALID-PIN\n", 17);
new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
persistent_group, automatic, join,
- auth, go_intent, freq, persistent_id, pd,
- ht40, vht);
+ auth, go_intent, freq, freq2, persistent_id,
+ pd, ht40, vht, max_oper_chwidth,
+ group_ssid, group_ssid_len);
if (new_pin == -2) {
os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
return 25;
struct wpa_ssid *ssid;
u8 *_peer = NULL, peer[ETH_ALEN];
int freq = 0, pref_freq = 0;
- int ht40, vht;
+ int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
id = atoi(cmd);
pos = os_strstr(cmd, " peer=");
ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
vht;
- return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40, vht,
- pref_freq);
+ pos = os_strstr(cmd, "freq2=");
+ if (pos)
+ freq2 = atoi(pos + 6);
+
+ pos = os_strstr(cmd, " max_oper_chwidth=");
+ if (pos)
+ chwidth = atoi(pos + 18);
+
+ max_oper_chwidth = parse_freq(chwidth, freq2);
+ if (max_oper_chwidth < 0)
+ return -1;
+
+ return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
+ max_oper_chwidth, pref_freq);
}
static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
- int id, int freq, int ht40, int vht)
+ int id, int freq, int vht_center_freq2,
+ int ht40, int vht, int vht_chwidth)
{
struct wpa_ssid *ssid;
return -1;
}
- return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, ht40, vht,
- NULL, 0, 0);
+ return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq,
+ vht_center_freq2, 0, ht40, vht,
+ vht_chwidth, NULL, 0, 0);
}
int freq = 0, persistent = 0, group_id = -1;
int vht = wpa_s->conf->p2p_go_vht;
int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
+ int max_oper_chwidth, chwidth = 0, freq2 = 0;
char *token, *context = NULL;
while ((token = str_token(cmd, " ", &context))) {
if (sscanf(token, "freq=%d", &freq) == 1 ||
- sscanf(token, "persistent=%d", &group_id) == 1) {
+ sscanf(token, "freq2=%d", &freq2) == 1 ||
+ sscanf(token, "persistent=%d", &group_id) == 1 ||
+ sscanf(token, "max_oper_chwidth=%d", &chwidth) == 1) {
continue;
} else if (os_strcmp(token, "ht40") == 0) {
ht40 = 1;
}
}
+ max_oper_chwidth = parse_freq(chwidth, freq2);
+ if (max_oper_chwidth < 0)
+ return -1;
+
if (group_id >= 0)
return p2p_ctrl_group_add_persistent(wpa_s, group_id,
- freq, ht40, vht);
+ freq, freq2, ht40, vht,
+ max_oper_chwidth);
+
+ return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht,
+ max_oper_chwidth);
+}
+
+
+static int p2p_ctrl_group_member(struct wpa_supplicant *wpa_s, const char *cmd,
+ char *buf, size_t buflen)
+{
+ u8 dev_addr[ETH_ALEN];
+ struct wpa_ssid *ssid;
+ int res;
+ const u8 *iaddr;
+
+ ssid = wpa_s->current_ssid;
+ if (!wpa_s->global->p2p || !ssid || ssid->mode != WPAS_MODE_P2P_GO ||
+ hwaddr_aton(cmd, dev_addr))
+ return -1;
- return wpas_p2p_group_add(wpa_s, persistent, freq, ht40, vht);
+ iaddr = p2p_group_get_client_interface_addr(wpa_s->p2p_group, dev_addr);
+ if (!iaddr)
+ return -1;
+ res = os_snprintf(buf, buflen, MACSTR, MAC2STR(iaddr));
+ if (os_snprintf_error(buflen, res))
+ return -1;
+ return res;
}
}
if (os_strcmp(cmd, "listen_channel") == 0) {
- return p2p_set_listen_channel(wpa_s->global->p2p, 81,
- atoi(param), 1);
+ char *pos;
+ u8 channel, op_class;
+
+ channel = atoi(param);
+ pos = os_strchr(param, ' ');
+ op_class = pos ? atoi(pos) : 81;
+
+ return p2p_set_listen_channel(wpa_s->global->p2p, op_class,
+ channel, 1);
}
if (os_strcmp(cmd, "ssid_postfix") == 0) {
return 0;
}
+
+static int p2p_ctrl_iface_p2p_lo_start(struct wpa_supplicant *wpa_s, char *cmd)
+{
+ int freq = 0, period = 0, interval = 0, count = 0;
+
+ if (sscanf(cmd, "%d %d %d %d", &freq, &period, &interval, &count) != 4)
+ {
+ wpa_printf(MSG_DEBUG,
+ "CTRL: Invalid P2P LO Start parameter: '%s'", cmd);
+ return -1;
+ }
+
+ return wpas_p2p_lo_start(wpa_s, freq, period, interval, count);
+}
+
#endif /* CONFIG_P2P */
u16 id[MAX_ANQP_INFO_ID];
size_t num_id = 0;
u32 subtypes = 0;
+ int get_cell_pref = 0;
used = hwaddr_aton2(dst, dst_addr);
if (used < 0)
#else /* CONFIG_HS20 */
return -1;
#endif /* CONFIG_HS20 */
+ } else if (os_strncmp(pos, "mbo:", 4) == 0) {
+#ifdef CONFIG_MBO
+ int num = atoi(pos + 4);
+ if (num != MBO_ANQP_SUBTYPE_CELL_CONN_PREF)
+ return -1;
+ get_cell_pref = 1;
+#else /* CONFIG_MBO */
+ return -1;
+#endif /* CONFIG_MBO */
} else {
id[num_id] = atoi(pos);
if (id[num_id])
if (num_id == 0)
return -1;
- return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes);
+ return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes,
+ get_cell_pref);
}
if (subtypes == 0)
return -1;
- return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0);
+ return hs20_anqp_send_req(wpa_s, dst_addr, subtypes, NULL, 0, 0);
}
ret = hs20_anqp_send_req(wpa_s, addr,
BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
- buf, len);
+ buf, len, 0);
os_free(buf);
ret = hs20_anqp_send_req(wpa_s, dst_addr,
BIT(HS20_STYPE_NAI_HOME_REALM_QUERY),
- buf, len);
+ buf, len, 0);
os_free(buf);
return ret;
}
-static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd)
+static int get_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd, char *reply,
+ int buflen)
+{
+ u8 dst_addr[ETH_ALEN];
+ int used;
+ char *ctx = NULL, *icon, *poffset, *psize;
+
+ used = hwaddr_aton2(cmd, dst_addr);
+ if (used < 0)
+ return -1;
+ cmd += used;
+
+ icon = str_token(cmd, " ", &ctx);
+ poffset = str_token(cmd, " ", &ctx);
+ psize = str_token(cmd, " ", &ctx);
+ if (!icon || !poffset || !psize)
+ return -1;
+
+ wpa_s->fetch_osu_icon_in_progress = 0;
+ return hs20_get_icon(wpa_s, dst_addr, icon, atoi(poffset), atoi(psize),
+ reply, buflen);
+}
+
+
+static int del_hs20_icon(struct wpa_supplicant *wpa_s, char *cmd)
+{
+ u8 dst_addr[ETH_ALEN];
+ int used;
+ char *icon;
+
+ if (!cmd[0])
+ return hs20_del_icon(wpa_s, NULL, NULL);
+
+ used = hwaddr_aton2(cmd, dst_addr);
+ if (used < 0)
+ return -1;
+
+ while (cmd[used] == ' ')
+ used++;
+ icon = cmd[used] ? &cmd[used] : NULL;
+
+ return hs20_del_icon(wpa_s, dst_addr, icon);
+}
+
+
+static int hs20_icon_request(struct wpa_supplicant *wpa_s, char *cmd, int inmem)
{
u8 dst_addr[ETH_ALEN];
int used;
wpa_s->fetch_osu_icon_in_progress = 0;
return hs20_anqp_send_req(wpa_s, dst_addr, BIT(HS20_STYPE_ICON_REQUEST),
- (u8 *) icon, os_strlen(icon));
+ (u8 *) icon, os_strlen(icon), inmem);
}
#endif /* CONFIG_HS20 */
static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd)
{
- int query_reason;
+ int query_reason, list = 0;
query_reason = atoi(cmd);
- wpa_printf(MSG_DEBUG, "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d",
- query_reason);
+ cmd = os_strchr(cmd, ' ');
+ if (cmd) {
+ cmd++;
+ if (os_strncmp(cmd, "list", 4) == 0) {
+ list = 1;
+ } else {
+ wpa_printf(MSG_DEBUG, "WNM Query: Invalid option %s",
+ cmd);
+ return -1;
+ }
+ }
- return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason);
+ wpa_printf(MSG_DEBUG,
+ "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d%s",
+ query_reason, list ? " candidate list" : "");
+
+ return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason, list);
}
#endif /* CONFIG_WNM */
}
+static int wpas_ctrl_iface_signal_monitor(struct wpa_supplicant *wpa_s,
+ const char *cmd)
+{
+ const char *pos;
+ int threshold = 0;
+ int hysteresis = 0;
+
+ if (wpa_s->bgscan && wpa_s->bgscan_priv) {
+ wpa_printf(MSG_DEBUG,
+ "Reject SIGNAL_MONITOR command - bgscan is active");
+ return -1;
+ }
+ pos = os_strstr(cmd, "THRESHOLD=");
+ if (pos)
+ threshold = atoi(pos + 10);
+ pos = os_strstr(cmd, "HYSTERESIS=");
+ if (pos)
+ hysteresis = atoi(pos + 11);
+ return wpa_drv_signal_monitor(wpa_s, threshold, hysteresis);
+}
+
+
static int wpas_ctrl_iface_get_pref_freq_list(
struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
{
}
+static int wpas_ctrl_iface_driver_flags(struct wpa_supplicant *wpa_s,
+ char *buf, size_t buflen)
+{
+ int ret, i;
+ char *pos, *end;
+
+ ret = os_snprintf(buf, buflen, "%016llX:\n",
+ (long long unsigned) wpa_s->drv_flags);
+ if (os_snprintf_error(buflen, ret))
+ return -1;
+
+ pos = buf + ret;
+ end = buf + buflen;
+
+ for (i = 0; i < 64; i++) {
+ if (wpa_s->drv_flags & (1LLU << i)) {
+ ret = os_snprintf(pos, end - pos, "%s\n",
+ driver_flag_to_string(1LLU << i));
+ if (os_snprintf_error(end - pos, ret))
+ return -1;
+ pos += ret;
+ }
+ }
+
+ return pos - buf;
+}
+
+
static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
size_t buflen)
{
/* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
vendor_id = strtoul(cmd, &pos, 16);
- if (!isblank(*pos))
+ if (!isblank((unsigned char) *pos))
return -EINVAL;
subcmd = strtoul(pos, &pos, 10);
if (*pos != '\0') {
- if (!isblank(*pos++))
+ if (!isblank((unsigned char) *pos++))
return -EINVAL;
data_len = os_strlen(pos);
}
wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state");
+ wpas_abort_ongoing_scan(wpa_s);
+
+ if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
+ /*
+ * Avoid possible auto connect re-connection on getting
+ * disconnected due to state flush.
+ */
+ wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
+ }
+
#ifdef CONFIG_P2P
+ wpas_p2p_group_remove(p2p_wpa_s, "*");
wpas_p2p_cancel(p2p_wpa_s);
p2p_ctrl_flush(p2p_wpa_s);
- wpas_p2p_group_remove(p2p_wpa_s, "*");
wpas_p2p_service_flush(p2p_wpa_s);
p2p_wpa_s->global->p2p_disabled = 0;
p2p_wpa_s->global->p2p_per_sta_psk = 0;
p2p_wpa_s->global->p2p_go_avoid_freq.range = NULL;
p2p_wpa_s->global->p2p_go_avoid_freq.num = 0;
p2p_wpa_s->global->pending_p2ps_group = 0;
+ p2p_wpa_s->global->pending_p2ps_group_freq = 0;
#endif /* CONFIG_P2P */
#ifdef CONFIG_WPS_TESTING
wps_version_number = 0x20;
wps_testing_dummy_cred = 0;
wps_corrupt_pkhash = 0;
+ wps_force_auth_types_in_use = 0;
+ wps_force_encr_types_in_use = 0;
#endif /* CONFIG_WPS_TESTING */
#ifdef CONFIG_WPS
wpa_s->wps_fragment_size = 0;
#ifdef CONFIG_TDLS
#ifdef CONFIG_TDLS_TESTING
- extern unsigned int tdls_testing;
tdls_testing = 0;
#endif /* CONFIG_TDLS_TESTING */
wpa_drv_tdls_oper(wpa_s, TDLS_ENABLE, NULL);
wpa_s->next_ssid = NULL;
#ifdef CONFIG_INTERWORKING
+#ifdef CONFIG_HS20
hs20_cancel_fetch_osu(wpa_s);
+ hs20_del_icon(wpa_s, NULL, NULL);
+#endif /* CONFIG_HS20 */
#endif /* CONFIG_INTERWORKING */
wpa_s->ext_mgmt_frame_handling = 0;
#ifdef CONFIG_TESTING_OPTIONS
wpa_s->extra_roc_dur = 0;
wpa_s->test_failure = WPAS_TEST_FAILURE_NONE;
+ wpa_s->p2p_go_csa_on_inv = 0;
+ wpa_s->ignore_auth_resp = 0;
+ wpa_s->ignore_assoc_disallow = 0;
+ wpa_s->reject_btm_req_reason = 0;
+ wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL);
#endif /* CONFIG_TESTING_OPTIONS */
wpa_s->disconnected = 0;
}
eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
+ wpa_s->wnmsleep_used = 0;
+
+#ifdef CONFIG_SME
+ wpa_s->sme.last_unprot_disconnect.sec = 0;
+#endif /* CONFIG_SME */
}
eloop_cancel_timeout(wpas_ctrl_radio_work_timeout,
work, NULL);
+ /*
+ * work->type points to a buffer in ework, so need to replace
+ * that here with a fixed string to avoid use of freed memory
+ * in debug prints.
+ */
+ work->type = "freed-ext-work";
+ work->ctx = NULL;
os_free(ework);
return;
}
}
+static int wpas_ctrl_iface_mgmt_rx_process(struct wpa_supplicant *wpa_s,
+ char *cmd)
+{
+ char *pos, *param;
+ size_t len;
+ u8 *buf;
+ int freq = 0, datarate = 0, ssi_signal = 0;
+ union wpa_event_data event;
+
+ if (!wpa_s->ext_mgmt_frame_handling)
+ return -1;
+
+ /* freq=<MHz> datarate=<val> ssi_signal=<val> frame=<frame hexdump> */
+
+ wpa_printf(MSG_DEBUG, "External MGMT RX process: %s", cmd);
+
+ pos = cmd;
+ param = os_strstr(pos, "freq=");
+ if (param) {
+ param += 5;
+ freq = atoi(param);
+ }
+
+ param = os_strstr(pos, " datarate=");
+ if (param) {
+ param += 10;
+ datarate = atoi(param);
+ }
+
+ param = os_strstr(pos, " ssi_signal=");
+ if (param) {
+ param += 12;
+ ssi_signal = atoi(param);
+ }
+
+ param = os_strstr(pos, " frame=");
+ if (param == NULL)
+ return -1;
+ param += 7;
+
+ len = os_strlen(param);
+ if (len & 1)
+ return -1;
+ len /= 2;
+
+ buf = os_malloc(len);
+ if (buf == NULL)
+ return -1;
+
+ if (hexstr2bin(param, buf, len) < 0) {
+ os_free(buf);
+ return -1;
+ }
+
+ os_memset(&event, 0, sizeof(event));
+ event.rx_mgmt.freq = freq;
+ event.rx_mgmt.frame = buf;
+ event.rx_mgmt.frame_len = len;
+ event.rx_mgmt.ssi_signal = ssi_signal;
+ event.rx_mgmt.datarate = datarate;
+ wpa_s->ext_mgmt_frame_handling = 0;
+ wpa_supplicant_event(wpa_s, EVENT_RX_MGMT, &event);
+ wpa_s->ext_mgmt_frame_handling = 1;
+
+ os_free(buf);
+
+ return 0;
+}
+
+
static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd)
{
char *pos, *param;
#define HWSIM_PACKETLEN 1500
#define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
-void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
+static void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
+ size_t len)
{
struct wpa_supplicant *wpa_s = ctx;
const struct ether_header *eth;
char *cmd)
{
int enabled = atoi(cmd);
+ char *pos;
+ const char *ifname;
if (!enabled) {
if (wpa_s->l2_test) {
if (wpa_s->l2_test)
return 0;
- wpa_s->l2_test = l2_packet_init(wpa_s->ifname, wpa_s->own_addr,
+ pos = os_strstr(cmd, " ifname=");
+ if (pos)
+ ifname = pos + 8;
+ else
+ ifname = wpa_s->ifname;
+
+ wpa_s->l2_test = l2_packet_init(ifname, wpa_s->own_addr,
ETHERTYPE_IP, wpas_data_test_rx,
wpa_s, 1);
if (wpa_s->l2_test == NULL)
static int wpas_ctrl_test_alloc_fail(struct wpa_supplicant *wpa_s, char *cmd)
{
#ifdef WPA_TRACE_BFD
- extern char wpa_trace_fail_func[256];
- extern unsigned int wpa_trace_fail_after;
char *pos;
wpa_trace_fail_after = atoi(cmd);
char *buf, size_t buflen)
{
#ifdef WPA_TRACE_BFD
- extern char wpa_trace_fail_func[256];
- extern unsigned int wpa_trace_fail_after;
-
return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
wpa_trace_fail_func);
#else /* WPA_TRACE_BFD */
static int wpas_ctrl_test_fail(struct wpa_supplicant *wpa_s, char *cmd)
{
#ifdef WPA_TRACE_BFD
- extern char wpa_trace_test_fail_func[256];
- extern unsigned int wpa_trace_test_fail_after;
char *pos;
wpa_trace_test_fail_after = atoi(cmd);
char *buf, size_t buflen)
{
#ifdef WPA_TRACE_BFD
- extern char wpa_trace_test_fail_func[256];
- extern unsigned int wpa_trace_test_fail_after;
-
return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after,
wpa_trace_test_fail_func);
#else /* WPA_TRACE_BFD */
#endif /* WPA_TRACE_BFD */
}
-#endif /* CONFIG_TESTING_OPTIONS */
-
-static void wpas_ctrl_vendor_elem_update(struct wpa_supplicant *wpa_s)
+static void wpas_ctrl_event_test_cb(void *eloop_ctx, void *timeout_ctx)
{
- unsigned int i;
- char buf[30];
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+ int i, count = (intptr_t) timeout_ctx;
- wpa_printf(MSG_DEBUG, "Update vendor elements");
+ wpa_printf(MSG_DEBUG, "TEST: Send %d control interface event messages",
+ count);
+ for (i = 0; i < count; i++) {
+ wpa_msg_ctrl(wpa_s, MSG_INFO, "TEST-EVENT-MESSAGE %d/%d",
+ i + 1, count);
+ }
+}
- for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
- if (wpa_s->vendor_elem[i]) {
- int res;
- res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
- if (!os_snprintf_error(sizeof(buf), res)) {
- wpa_hexdump_buf(MSG_DEBUG, buf,
- wpa_s->vendor_elem[i]);
- }
- }
- }
+static int wpas_ctrl_event_test(struct wpa_supplicant *wpa_s, const char *cmd)
+{
+ int count;
-#ifdef CONFIG_P2P
- if (wpa_s->parent == wpa_s &&
- wpa_s->global->p2p &&
- !wpa_s->global->p2p_disabled)
- p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
-#endif /* CONFIG_P2P */
+ count = atoi(cmd);
+ if (count <= 0)
+ return -1;
+
+ return eloop_register_timeout(0, 0, wpas_ctrl_event_test_cb, wpa_s,
+ (void *) (intptr_t) count);
}
-static struct wpa_supplicant *
-wpas_ctrl_vendor_elem_iface(struct wpa_supplicant *wpa_s,
- enum wpa_vendor_elem_frame frame)
+static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s,
+ const char *cmd)
{
- switch (frame) {
-#ifdef CONFIG_P2P
- case VENDOR_ELEM_PROBE_REQ_P2P:
- case VENDOR_ELEM_PROBE_RESP_P2P:
- case VENDOR_ELEM_PROBE_RESP_P2P_GO:
- case VENDOR_ELEM_BEACON_P2P_GO:
- case VENDOR_ELEM_P2P_PD_REQ:
- case VENDOR_ELEM_P2P_PD_RESP:
- case VENDOR_ELEM_P2P_GO_NEG_REQ:
- case VENDOR_ELEM_P2P_GO_NEG_RESP:
- case VENDOR_ELEM_P2P_GO_NEG_CONF:
- case VENDOR_ELEM_P2P_INV_REQ:
- case VENDOR_ELEM_P2P_INV_RESP:
- case VENDOR_ELEM_P2P_ASSOC_REQ:
- return wpa_s->parent;
-#endif /* CONFIG_P2P */
- default:
- return wpa_s;
+ struct wpabuf *buf;
+ size_t len;
+
+ len = os_strlen(cmd);
+ if (len & 1)
+ return -1;
+ len /= 2;
+
+ if (len == 0) {
+ buf = NULL;
+ } else {
+ buf = wpabuf_alloc(len);
+ if (buf == NULL)
+ return -1;
+
+ if (hexstr2bin(cmd, wpabuf_put(buf, len), len) < 0) {
+ wpabuf_free(buf);
+ return -1;
+ }
}
+
+ wpa_sm_set_test_assoc_ie(wpa_s->wpa, buf);
+ return 0;
}
+#endif /* CONFIG_TESTING_OPTIONS */
+
static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
{
frame = atoi(pos);
if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
return -1;
- wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
+ wpa_s = wpas_vendor_elem(wpa_s, frame);
pos = os_strchr(pos, ' ');
if (pos == NULL)
if (wpa_s->vendor_elem[frame] == NULL) {
wpa_s->vendor_elem[frame] = buf;
- wpas_ctrl_vendor_elem_update(wpa_s);
+ wpas_vendor_elem_update(wpa_s);
return 0;
}
wpabuf_put_buf(wpa_s->vendor_elem[frame], buf);
wpabuf_free(buf);
- wpas_ctrl_vendor_elem_update(wpa_s);
+ wpas_vendor_elem_update(wpa_s);
return 0;
}
if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
return -1;
- wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
+ wpa_s = wpas_vendor_elem(wpa_s, frame);
if (wpa_s->vendor_elem[frame] == NULL)
return 0;
size_t len;
u8 *buf;
struct ieee802_11_elems elems;
- u8 *ie, *end;
+ int res;
frame = atoi(pos);
if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
return -1;
- wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
+ wpa_s = wpas_vendor_elem(wpa_s, frame);
pos = os_strchr(pos, ' ');
if (pos == NULL)
if (*pos == '*') {
wpabuf_free(wpa_s->vendor_elem[frame]);
wpa_s->vendor_elem[frame] = NULL;
- wpas_ctrl_vendor_elem_update(wpa_s);
+ wpas_vendor_elem_update(wpa_s);
return 0;
}
return -1;
}
- ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
- end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
-
- for (; ie + 1 < end; ie += 2 + ie[1]) {
- if (ie + len > end)
- break;
- if (os_memcmp(ie, buf, len) != 0)
- continue;
-
- if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
- wpabuf_free(wpa_s->vendor_elem[frame]);
- wpa_s->vendor_elem[frame] = NULL;
- } else {
- os_memmove(ie, ie + len,
- end - (ie + len));
- wpa_s->vendor_elem[frame]->used -= len;
- }
- os_free(buf);
- wpas_ctrl_vendor_elem_update(wpa_s);
- return 0;
- }
-
+ res = wpas_vendor_elem_remove(wpa_s, frame, buf, len);
os_free(buf);
-
- return -1;
+ return res;
}
static void wpas_ctrl_neighbor_rep_cb(void *ctx, struct wpabuf *neighbor_rep)
{
struct wpa_supplicant *wpa_s = ctx;
+ size_t len;
+ const u8 *data;
- if (neighbor_rep) {
- wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_RXED
- "length=%u",
- (unsigned int) wpabuf_len(neighbor_rep));
- wpabuf_free(neighbor_rep);
- } else {
+ /*
+ * Neighbor Report element (IEEE P802.11-REVmc/D5.0)
+ * BSSID[6]
+ * BSSID Information[4]
+ * Operating Class[1]
+ * Channel Number[1]
+ * PHY Type[1]
+ * Optional Subelements[variable]
+ */
+#define NR_IE_MIN_LEN (ETH_ALEN + 4 + 1 + 1 + 1)
+
+ if (!neighbor_rep || wpabuf_len(neighbor_rep) == 0) {
wpa_msg_ctrl(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_FAILED);
+ goto out;
+ }
+
+ data = wpabuf_head_u8(neighbor_rep);
+ len = wpabuf_len(neighbor_rep);
+
+ while (len >= 2 + NR_IE_MIN_LEN) {
+ const u8 *nr;
+ char lci[256 * 2 + 1];
+ char civic[256 * 2 + 1];
+ u8 nr_len = data[1];
+ const u8 *pos = data, *end;
+
+ if (pos[0] != WLAN_EID_NEIGHBOR_REPORT ||
+ nr_len < NR_IE_MIN_LEN) {
+ wpa_printf(MSG_DEBUG,
+ "CTRL: Invalid Neighbor Report element: id=%u len=%u",
+ data[0], nr_len);
+ goto out;
+ }
+
+ if (2U + nr_len > len) {
+ wpa_printf(MSG_DEBUG,
+ "CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u",
+ data[0], len, nr_len);
+ goto out;
+ }
+ pos += 2;
+ end = pos + nr_len;
+
+ nr = pos;
+ pos += NR_IE_MIN_LEN;
+
+ lci[0] = '\0';
+ civic[0] = '\0';
+ while (end - pos > 2) {
+ u8 s_id, s_len;
+
+ s_id = *pos++;
+ s_len = *pos++;
+ if (s_len > end - pos)
+ goto out;
+ if (s_id == WLAN_EID_MEASURE_REPORT && s_len > 3) {
+ /* Measurement Token[1] */
+ /* Measurement Report Mode[1] */
+ /* Measurement Type[1] */
+ /* Measurement Report[variable] */
+ switch (pos[2]) {
+ case MEASURE_TYPE_LCI:
+ if (lci[0])
+ break;
+ wpa_snprintf_hex(lci, sizeof(lci),
+ pos, s_len);
+ break;
+ case MEASURE_TYPE_LOCATION_CIVIC:
+ if (civic[0])
+ break;
+ wpa_snprintf_hex(civic, sizeof(civic),
+ pos, s_len);
+ break;
+ }
+ }
+
+ pos += s_len;
+ }
+
+ wpa_msg(wpa_s, MSG_INFO, RRM_EVENT_NEIGHBOR_REP_RXED
+ "bssid=" MACSTR
+ " info=0x%x op_class=%u chan=%u phy_type=%u%s%s%s%s",
+ MAC2STR(nr), WPA_GET_LE32(nr + ETH_ALEN),
+ nr[ETH_ALEN + 4], nr[ETH_ALEN + 5],
+ nr[ETH_ALEN + 6],
+ lci[0] ? " lci=" : "", lci,
+ civic[0] ? " civic=" : "", civic);
+
+ data = end;
+ len -= 2 + nr_len;
}
+
+out:
+ wpabuf_free(neighbor_rep);
}
-static int wpas_ctrl_iface_send_neigbor_rep(struct wpa_supplicant *wpa_s,
- char *cmd)
+static int wpas_ctrl_iface_send_neighbor_rep(struct wpa_supplicant *wpa_s,
+ char *cmd)
{
- struct wpa_ssid ssid;
- struct wpa_ssid *ssid_p = NULL;
- int ret = 0;
+ struct wpa_ssid_value ssid, *ssid_p = NULL;
+ int ret, lci = 0, civic = 0;
+ char *ssid_s;
- if (os_strncmp(cmd, " ssid=", 6) == 0) {
- ssid.ssid_len = os_strlen(cmd + 6);
- if (ssid.ssid_len > SSID_MAX_LEN)
+ ssid_s = os_strstr(cmd, "ssid=");
+ if (ssid_s) {
+ if (ssid_parse(ssid_s + 5, &ssid)) {
+ wpa_printf(MSG_ERROR,
+ "CTRL: Send Neighbor Report: bad SSID");
return -1;
- ssid.ssid = (u8 *) (cmd + 6);
+ }
+
ssid_p = &ssid;
+
+ /*
+ * Move cmd after the SSID text that may include "lci" or
+ * "civic".
+ */
+ cmd = os_strchr(ssid_s + 6, ssid_s[5] == '"' ? '"' : ' ');
+ if (cmd)
+ cmd++;
+
}
- ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p,
+ if (cmd && os_strstr(cmd, "lci"))
+ lci = 1;
+
+ if (cmd && os_strstr(cmd, "civic"))
+ civic = 1;
+
+ ret = wpas_rrm_send_neighbor_rep_request(wpa_s, ssid_p, lci, civic,
wpas_ctrl_neighbor_rep_cb,
wpa_s);
}
} else if (wpa_s->sched_scanning &&
(type & MAC_ADDR_RAND_SCHED_SCAN)) {
- /* simulate timeout to restart the sched scan */
- wpa_s->sched_scan_timed_out = 1;
- wpa_s->prev_sched_ssid = NULL;
- wpa_supplicant_cancel_sched_scan(wpa_s);
+ wpas_scan_restart_sched_scan(wpa_s);
}
return 0;
}
wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN,
addr, mask);
- if (wpa_s->sched_scanning && !wpa_s->pno) {
- /* simulate timeout to restart the sched scan */
- wpa_s->sched_scan_timed_out = 1;
- wpa_s->prev_sched_ssid = NULL;
- wpa_supplicant_cancel_sched_scan(wpa_s);
- }
+ if (wpa_s->sched_scanning && !wpa_s->pno)
+ wpas_scan_restart_sched_scan(wpa_s);
}
if (type & MAC_ADDR_RAND_PNO) {
}
+static int wpas_ctrl_iface_pmksa(struct wpa_supplicant *wpa_s,
+ char *buf, size_t buflen)
+{
+ size_t reply_len;
+
+ reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, buf, buflen);
+#ifdef CONFIG_AP
+ reply_len += wpas_ap_pmksa_cache_list(wpa_s, &buf[reply_len],
+ buflen - reply_len);
+#endif /* CONFIG_AP */
+ return reply_len;
+}
+
+
+static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s)
+{
+ wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
+#ifdef CONFIG_AP
+ wpas_ap_pmksa_cache_flush(wpa_s);
+#endif /* CONFIG_AP */
+}
+
+
static int wpas_ctrl_cmd_debug_level(const char *cmd)
{
if (os_strcmp(cmd, "PING") == 0 ||
reply_len = wpa_supplicant_ctrl_iface_status(
wpa_s, buf + 6, reply, reply_size);
} else if (os_strcmp(buf, "PMKSA") == 0) {
- reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
- reply_size);
+ reply_len = wpas_ctrl_iface_pmksa(wpa_s, reply, reply_size);
} else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
- wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
+ wpas_ctrl_iface_pmksa_flush(wpa_s);
} else if (os_strncmp(buf, "SET ", 4) == 0) {
if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
reply_len = -1;
if (wpa_supplicant_ctrl_iface_mesh_group_remove(wpa_s,
buf + 18))
reply_len = -1;
+ } else if (os_strncmp(buf, "MESH_PEER_REMOVE ", 17) == 0) {
+ if (wpa_supplicant_ctrl_iface_mesh_peer_remove(wpa_s, buf + 17))
+ reply_len = -1;
+ } else if (os_strncmp(buf, "MESH_PEER_ADD ", 14) == 0) {
+ if (wpa_supplicant_ctrl_iface_mesh_peer_add(wpa_s, buf + 14))
+ reply_len = -1;
#endif /* CONFIG_MESH */
#ifdef CONFIG_P2P
} else if (os_strncmp(buf, "P2P_FIND ", 9) == 0) {
} else if (os_strncmp(buf, "P2P_GROUP_ADD ", 14) == 0) {
if (p2p_ctrl_group_add(wpa_s, buf + 14))
reply_len = -1;
+ } else if (os_strncmp(buf, "P2P_GROUP_MEMBER ", 17) == 0) {
+ reply_len = p2p_ctrl_group_member(wpa_s, buf + 17, reply,
+ reply_size);
} else if (os_strncmp(buf, "P2P_PROV_DISC ", 14) == 0) {
if (p2p_ctrl_prov_disc(wpa_s, buf + 14))
reply_len = -1;
} else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) {
if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0)
reply_len = -1;
+ } else if (os_strncmp(buf, "P2P_LO_START ", 13) == 0) {
+ if (p2p_ctrl_iface_p2p_lo_start(wpa_s, buf + 13))
+ reply_len = -1;
+ } else if (os_strcmp(buf, "P2P_LO_STOP") == 0) {
+ if (wpas_p2p_lo_stop(wpa_s))
+ reply_len = -1;
#endif /* CONFIG_P2P */
#ifdef CONFIG_WIFI_DISPLAY
} else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
if (hs20_get_nai_home_realm_list(wpa_s, buf + 29) < 0)
reply_len = -1;
} else if (os_strncmp(buf, "HS20_ICON_REQUEST ", 18) == 0) {
- if (hs20_icon_request(wpa_s, buf + 18) < 0)
+ if (hs20_icon_request(wpa_s, buf + 18, 0) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "REQ_HS20_ICON ", 14) == 0) {
+ if (hs20_icon_request(wpa_s, buf + 14, 1) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "GET_HS20_ICON ", 14) == 0) {
+ reply_len = get_hs20_icon(wpa_s, buf + 14, reply, reply_size);
+ } else if (os_strncmp(buf, "DEL_HS20_ICON ", 14) == 0) {
+ if (del_hs20_icon(wpa_s, buf + 14) < 0)
reply_len = -1;
} else if (os_strcmp(buf, "FETCH_OSU") == 0) {
- if (hs20_fetch_osu(wpa_s) < 0)
+ if (hs20_fetch_osu(wpa_s, 0) < 0)
+ reply_len = -1;
+ } else if (os_strcmp(buf, "FETCH_OSU no-scan") == 0) {
+ if (hs20_fetch_osu(wpa_s, 1) < 0)
reply_len = -1;
} else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) {
hs20_cancel_fetch_osu(wpa_s);
reply_len = wpa_supplicant_ctrl_iface_list_networks(
wpa_s, NULL, reply, reply_size);
} else if (os_strcmp(buf, "DISCONNECT") == 0) {
-#ifdef CONFIG_SME
- wpa_s->sme.prev_bssid_set = 0;
-#endif /* CONFIG_SME */
- wpa_s->reassociate = 0;
- wpa_s->disconnected = 1;
- wpa_supplicant_cancel_sched_scan(wpa_s);
- wpa_supplicant_cancel_scan(wpa_s);
- wpa_supplicant_deauthenticate(wpa_s,
- WLAN_REASON_DEAUTH_LEAVING);
- eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
+ wpas_request_disconnection(wpa_s);
} else if (os_strcmp(buf, "SCAN") == 0) {
wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
} else if (os_strncmp(buf, "SCAN ", 5) == 0) {
} else if (os_strcmp(buf, "SCAN_RESULTS") == 0) {
reply_len = wpa_supplicant_ctrl_iface_scan_results(
wpa_s, reply, reply_size);
+ } else if (os_strcmp(buf, "ABORT_SCAN") == 0) {
+ if (wpas_abort_ongoing_scan(wpa_s) < 0)
+ reply_len = -1;
} else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
reply_len = -1;
} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
reply_len = wpa_supplicant_global_iface_list(
wpa_s->global, reply, reply_size);
- } else if (os_strcmp(buf, "INTERFACES") == 0) {
+ } else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
reply_len = wpa_supplicant_global_iface_interfaces(
- wpa_s->global, reply, reply_size);
+ wpa_s->global, buf + 10, reply, reply_size);
} else if (os_strncmp(buf, "BSS ", 4) == 0) {
reply_len = wpa_supplicant_ctrl_iface_bss(
wpa_s, buf + 4, reply, reply_size);
} else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
reply_size);
+ } else if (os_strncmp(buf, "SIGNAL_MONITOR", 14) == 0) {
+ if (wpas_ctrl_iface_signal_monitor(wpa_s, buf + 14))
+ reply_len = -1;
} else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) {
reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply,
reply_size);
if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
reply_len = -1;
#endif /* CONFIG_AUTOSCAN */
+ } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
+ reply_len = wpas_ctrl_iface_driver_flags(wpa_s, reply,
+ reply_size);
#ifdef ANDROID
} else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
reply_len = -1;
} else if (os_strcmp(buf, "MGMT_TX_DONE") == 0) {
wpas_ctrl_iface_mgmt_tx_done(wpa_s);
+ } else if (os_strncmp(buf, "MGMT_RX_PROCESS ", 16) == 0) {
+ if (wpas_ctrl_iface_mgmt_rx_process(wpa_s, buf + 16) < 0)
+ reply_len = -1;
} else if (os_strncmp(buf, "DRIVER_EVENT ", 13) == 0) {
if (wpas_ctrl_iface_driver_event(wpa_s, buf + 13) < 0)
reply_len = -1;
reply_len = -1;
} else if (os_strcmp(buf, "GET_FAIL") == 0) {
reply_len = wpas_ctrl_get_fail(wpa_s, reply, reply_size);
+ } else if (os_strncmp(buf, "EVENT_TEST ", 11) == 0) {
+ if (wpas_ctrl_event_test(wpa_s, buf + 11) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "TEST_ASSOC_IE ", 14) == 0) {
+ if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0)
+ reply_len = -1;
#endif /* CONFIG_TESTING_OPTIONS */
} else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) {
if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0)
if (wpas_ctrl_vendor_elem_remove(wpa_s, buf + 19) < 0)
reply_len = -1;
} else if (os_strncmp(buf, "NEIGHBOR_REP_REQUEST", 20) == 0) {
- if (wpas_ctrl_iface_send_neigbor_rep(wpa_s, buf + 20))
+ if (wpas_ctrl_iface_send_neighbor_rep(wpa_s, buf + 20))
reply_len = -1;
} else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
wpas_ctrl_iface_erp_flush(wpa_s);
struct wpa_supplicant *wpa_s;
unsigned int create_iface = 0;
u8 mac_addr[ETH_ALEN];
+ enum wpa_driver_if_type type = WPA_IF_STATION;
/*
* <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
- * TAB<bridge_ifname>[TAB<create>]
+ * TAB<bridge_ifname>[TAB<create>[TAB<interface_type>]]
*/
wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
if (!extra[0])
break;
- if (os_strcmp(extra, "create") == 0)
+ if (os_strcmp(extra, "create") == 0) {
create_iface = 1;
- else {
+ if (!pos)
+ break;
+
+ if (os_strcmp(pos, "sta") == 0) {
+ type = WPA_IF_STATION;
+ } else if (os_strcmp(pos, "ap") == 0) {
+ type = WPA_IF_AP_BSS;
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "INTERFACE_ADD unsupported interface type: '%s'",
+ pos);
+ return -1;
+ }
+ } else {
wpa_printf(MSG_DEBUG,
"INTERFACE_ADD unsupported extra parameter: '%s'",
extra);
iface.ifname);
if (!global->ifaces)
return -1;
- if (wpa_drv_if_add(global->ifaces, WPA_IF_STATION, iface.ifname,
+ if (wpa_drv_if_add(global->ifaces, type, iface.ifname,
NULL, NULL, NULL, mac_addr, NULL) < 0) {
wpa_printf(MSG_ERROR,
"CTRL_IFACE interface creation failed");
static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
+ const char *input,
char *buf, int len)
{
int res;
char *pos, *end;
struct wpa_supplicant *wpa_s;
+ int show_ctrl = 0;
+
+ if (input)
+ show_ctrl = !!os_strstr(input, "ctrl");
wpa_s = global->ifaces;
pos = buf;
end = buf + len;
while (wpa_s) {
- res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
+ if (show_ctrl)
+ res = os_snprintf(pos, end - pos, "%s ctrl_iface=%s\n",
+ wpa_s->ifname,
+ wpa_s->conf->ctrl_interface ?
+ wpa_s->conf->ctrl_interface : "N/A");
+ else
+ res = os_snprintf(pos, end - pos, "%s\n",
+ wpa_s->ifname);
+
if (os_snprintf_error(end - pos, res)) {
*pos = '\0';
break;
"P2P_LISTEN ",
"P2P_GROUP_REMOVE ",
"P2P_GROUP_ADD ",
+ "P2P_GROUP_MEMBER ",
"P2P_PROV_DISC ",
"P2P_SERV_DISC_REQ ",
"P2P_SERV_DISC_CANCEL_REQ ",
} else if (os_strcmp(buf, "INTERFACE_LIST") == 0) {
reply_len = wpa_supplicant_global_iface_list(
global, reply, reply_size);
- } else if (os_strcmp(buf, "INTERFACES") == 0) {
+ } else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
reply_len = wpa_supplicant_global_iface_interfaces(
- global, reply, reply_size);
+ global, buf + 10, reply, reply_size);
#ifdef CONFIG_FST
} else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
reply_len = wpas_global_ctrl_iface_fst_attach(global, buf + 11,
reply_size);
#ifdef CONFIG_MODULE_TESTS
} else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
- int wpas_module_tests(void);
if (wpas_module_tests() < 0)
reply_len = -1;
#endif /* CONFIG_MODULE_TESTS */
/*
* WPA Supplicant / UDP socket -based control interface
- * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
u8 cookie[COOKIE_LEN];
};
+struct ctrl_iface_global_priv {
+ int sock;
+ struct wpa_ctrl_dst *ctrl_dst;
+ u8 cookie[COOKIE_LEN];
+};
-static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
+
+static void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s,
+ const char *ifname, int sock,
+ struct wpa_ctrl_dst **head,
int level, const char *buf,
size_t len);
-static int wpa_supplicant_ctrl_iface_attach(struct ctrl_iface_priv *priv,
+static void wpas_ctrl_iface_free_dst(struct wpa_ctrl_dst *dst)
+{
+ struct wpa_ctrl_dst *prev;
+
+ while (dst) {
+ prev = dst;
+ dst = dst->next;
+ os_free(prev);
+ }
+}
+
+
+static int wpa_supplicant_ctrl_iface_attach(struct wpa_ctrl_dst **head,
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
struct sockaddr_in6 *from,
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
os_memcpy(&dst->addr, from, sizeof(*from));
dst->addrlen = fromlen;
dst->debug_level = MSG_INFO;
- dst->next = priv->ctrl_dst;
- priv->ctrl_dst = dst;
+ dst->next = *head;
+ *head = dst;
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d",
inet_ntop(AF_INET6, &from->sin6_addr, addr, sizeof(*from)),
}
-static int wpa_supplicant_ctrl_iface_detach(struct ctrl_iface_priv *priv,
+static int wpa_supplicant_ctrl_iface_detach(struct wpa_ctrl_dst **head,
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
struct sockaddr_in6 *from,
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
char addr[INET6_ADDRSTRLEN];
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
- dst = priv->ctrl_dst;
+ dst = *head;
while (dst) {
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
if (from->sin6_port == dst->addr.sin6_port &&
ntohs(from->sin_port));
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
if (prev == NULL)
- priv->ctrl_dst = dst->next;
+ *head = dst->next;
else
prev->next = dst->next;
os_free(dst);
pos++;
if (os_strcmp(pos, "ATTACH") == 0) {
- if (wpa_supplicant_ctrl_iface_attach(priv, &from, fromlen))
+ if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst,
+ &from, fromlen))
reply_len = 1;
else {
new_attached = 1;
reply_len = 2;
}
} else if (os_strcmp(pos, "DETACH") == 0) {
- if (wpa_supplicant_ctrl_iface_detach(priv, &from, fromlen))
+ if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst,
+ &from, fromlen))
reply_len = 1;
else
reply_len = 2;
const char *txt, size_t len)
{
struct wpa_supplicant *wpa_s = ctx;
- if (wpa_s == NULL || wpa_s->ctrl_iface == NULL)
+
+ if (!wpa_s)
return;
- wpa_supplicant_ctrl_iface_send(wpa_s->ctrl_iface, level, txt, len);
+
+ if (type != WPA_MSG_NO_GLOBAL && wpa_s->global->ctrl_iface) {
+ struct ctrl_iface_global_priv *priv = wpa_s->global->ctrl_iface;
+
+ if (priv->ctrl_dst) {
+ wpa_supplicant_ctrl_iface_send(
+ wpa_s,
+ type != WPA_MSG_PER_INTERFACE ?
+ NULL : wpa_s->ifname,
+ priv->sock, &priv->ctrl_dst, level, txt, len);
+ }
+ }
+
+ if (type == WPA_MSG_ONLY_GLOBAL || !wpa_s->ctrl_iface)
+ return;
+
+ wpa_supplicant_ctrl_iface_send(wpa_s, NULL, wpa_s->ctrl_iface->sock,
+ &wpa_s->ctrl_iface->ctrl_dst,
+ level, txt, len);
}
wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
{
struct ctrl_iface_priv *priv;
+ char port_str[40];
int port = WPA_CTRL_IFACE_PORT;
+ char *pos;
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
struct sockaddr_in6 addr;
int domain = PF_INET6;
if (wpa_s->conf->ctrl_interface == NULL)
return priv;
+ pos = os_strstr(wpa_s->conf->ctrl_interface, "udp:");
+ if (pos) {
+ pos += 4;
+ port = atoi(pos);
+ if (port <= 0) {
+ wpa_printf(MSG_ERROR, "Invalid ctrl_iface UDP port: %s",
+ wpa_s->conf->ctrl_interface);
+ goto fail;
+ }
+ }
+
priv->sock = socket(domain, SOCK_DGRAM, 0);
if (priv->sock < 0) {
wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
goto fail;
}
+ /* Update the ctrl_interface value to match the selected port */
+ os_snprintf(port_str, sizeof(port_str), "udp:%d", port);
+ os_free(wpa_s->conf->ctrl_interface);
+ wpa_s->conf->ctrl_interface = os_strdup(port_str);
+ if (!wpa_s->conf->ctrl_interface) {
+ wpa_msg(wpa_s, MSG_ERROR, "Failed to malloc ctrl_interface");
+ goto fail;
+ }
+
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
wpa_msg(wpa_s, MSG_DEBUG, "ctrl_iface_init UDP port: %d", port);
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
{
- struct wpa_ctrl_dst *dst, *prev;
-
if (priv->sock > -1) {
eloop_unregister_read_sock(priv->sock);
if (priv->ctrl_dst) {
priv->sock = -1;
}
- dst = priv->ctrl_dst;
- while (dst) {
- prev = dst;
- dst = dst->next;
- os_free(prev);
- }
+ wpas_ctrl_iface_free_dst(priv->ctrl_dst);
os_free(priv);
}
-static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
+static void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s,
+ const char *ifname, int sock,
+ struct wpa_ctrl_dst **head,
int level, const char *buf,
size_t len)
{
struct wpa_ctrl_dst *dst, *next;
- char levelstr[10];
+ char levelstr[64];
int idx;
char *sbuf;
int llen;
char addr[INET6_ADDRSTRLEN];
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
- dst = priv->ctrl_dst;
- if (priv->sock < 0 || dst == NULL)
+ dst = *head;
+ if (sock < 0 || dst == NULL)
return;
- os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
+ if (ifname)
+ os_snprintf(levelstr, sizeof(levelstr), "IFACE=%s <%d>",
+ ifname, level);
+ else
+ os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
llen = os_strlen(levelstr);
sbuf = os_malloc(llen + len);
inet_ntoa(dst->addr.sin_addr),
ntohs(dst->addr.sin_port));
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
- if (sendto(priv->sock, sbuf, llen + len, 0,
+ if (sendto(sock, sbuf, llen + len, 0,
(struct sockaddr *) &dst->addr,
sizeof(dst->addr)) < 0) {
wpa_printf(MSG_ERROR,
dst->errors++;
if (dst->errors > 10) {
wpa_supplicant_ctrl_iface_detach(
- priv, &dst->addr,
+ head, &dst->addr,
dst->addrlen);
}
} else
/* Global ctrl_iface */
-struct ctrl_iface_global_priv {
- int sock;
- u8 cookie[COOKIE_LEN];
-};
-
-
static char *
wpa_supplicant_global_get_cookie(struct ctrl_iface_global_priv *priv,
size_t *reply_len)
struct ctrl_iface_global_priv *priv = sock_ctx;
char buf[256], *pos;
int res;
+#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
+ struct sockaddr_in6 from;
+#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
struct sockaddr_in from;
+#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
socklen_t fromlen = sizeof(from);
- char *reply;
+ char *reply = NULL;
size_t reply_len;
u8 cookie[COOKIE_LEN];
}
#ifndef CONFIG_CTRL_IFACE_UDP_REMOTE
+#ifndef CONFIG_CTRL_IFACE_UDP_IPV6
if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) {
/*
* The OS networking stack is expected to drop this kind of
"source %s", inet_ntoa(from.sin_addr));
return;
}
+#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
buf[res] = '\0';
while (*pos == ' ')
pos++;
- reply = wpa_supplicant_global_ctrl_iface_process(global, pos,
- &reply_len);
+ if (os_strcmp(pos, "ATTACH") == 0) {
+ if (wpa_supplicant_ctrl_iface_attach(&priv->ctrl_dst,
+ &from, fromlen))
+ reply_len = 1;
+ else
+ reply_len = 2;
+ } else if (os_strcmp(pos, "DETACH") == 0) {
+ if (wpa_supplicant_ctrl_iface_detach(&priv->ctrl_dst,
+ &from, fromlen))
+ reply_len = 1;
+ else
+ reply_len = 2;
+ } else {
+ reply = wpa_supplicant_global_ctrl_iface_process(global, pos,
+ &reply_len);
+ }
done:
if (reply) {
sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
fromlen);
os_free(reply);
- } else if (reply_len) {
+ } else if (reply_len == 1) {
sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
fromlen);
+ } else if (reply_len == 2) {
+ sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from,
+ fromlen);
}
}
{
struct ctrl_iface_global_priv *priv;
struct sockaddr_in addr;
+ char *pos;
int port = WPA_GLOBAL_CTRL_IFACE_PORT;
priv = os_zalloc(sizeof(*priv));
wpa_printf(MSG_DEBUG, "Global control interface '%s'",
global->params.ctrl_interface);
+ pos = os_strstr(global->params.ctrl_interface, "udp:");
+ if (pos) {
+ pos += 4;
+ port = atoi(pos);
+ if (port <= 0) {
+ wpa_printf(MSG_ERROR, "Invalid global ctrl UDP port %s",
+ global->params.ctrl_interface);
+ goto fail;
+ }
+ }
+
priv->sock = socket(PF_INET, SOCK_DGRAM, 0);
if (priv->sock < 0) {
wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
port++;
if ((port - WPA_GLOBAL_CTRL_IFACE_PORT) <
- WPA_GLOBAL_CTRL_IFACE_PORT_LIMIT)
+ WPA_GLOBAL_CTRL_IFACE_PORT_LIMIT && !pos)
goto try_again;
wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
goto fail;
eloop_register_read_sock(priv->sock,
wpa_supplicant_global_ctrl_iface_receive,
global, priv);
+ wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
return priv;
eloop_unregister_read_sock(priv->sock);
close(priv->sock);
}
+
+ wpas_ctrl_iface_free_dst(priv->ctrl_dst);
os_free(priv);
}
#include <fcntl.h>
#ifdef __linux__
#include <sys/ioctl.h>
-#include <linux/sockios.h>
#endif /* __linux__ */
#ifdef ANDROID
#include <cutils/sockets.h>
#include "utils/common.h"
#include "utils/eloop.h"
#include "utils/list.h"
+#include "common/ctrl_iface_common.h"
#include "eapol_supp/eapol_supp_sm.h"
#include "config.h"
#include "wpa_supplicant_i.h"
/* Per-interface ctrl_iface */
-/**
- * struct wpa_ctrl_dst - Internal data structure of control interface monitors
- *
- * This structure is used to store information about registered control
- * interface monitors into struct wpa_supplicant. This data is private to
- * ctrl_iface_unix.c and should not be touched directly from other files.
- */
-struct wpa_ctrl_dst {
- struct dl_list list;
- struct sockaddr_un addr;
- socklen_t addrlen;
- int debug_level;
- int errors;
-};
-
-
struct ctrl_iface_priv {
struct wpa_supplicant *wpa_s;
int sock;
struct dl_list ctrl_dst;
int android_control_socket;
+ struct dl_list msg_queue;
+ unsigned int throttle_count;
};
int sock;
struct dl_list ctrl_dst;
int android_control_socket;
+ struct dl_list msg_queue;
+ unsigned int throttle_count;
+};
+
+struct ctrl_iface_msg {
+ struct dl_list list;
+ struct wpa_supplicant *wpa_s;
+ int level;
+ enum wpa_msg_type type;
+ const char *txt;
+ size_t len;
};
if (getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sndbuf, &optlen) < 0)
sndbuf = -1;
- if (ioctl(sock, SIOCOUTQ, &outq) < 0)
+ if (ioctl(sock, TIOCOUTQ, &outq) < 0)
outq = -1;
wpa_printf(level,
static int wpa_supplicant_ctrl_iface_attach(struct dl_list *ctrl_dst,
- struct sockaddr_un *from,
+ struct sockaddr_storage *from,
socklen_t fromlen, int global)
{
- struct wpa_ctrl_dst *dst;
- char addr_txt[200];
-
- dst = os_zalloc(sizeof(*dst));
- if (dst == NULL)
- return -1;
- os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
- dst->addrlen = fromlen;
- dst->debug_level = MSG_INFO;
- dl_list_add(ctrl_dst, &dst->list);
- printf_encode(addr_txt, sizeof(addr_txt),
- (u8 *) from->sun_path,
- fromlen - offsetof(struct sockaddr_un, sun_path));
- wpa_printf(MSG_DEBUG, "CTRL_IFACE %smonitor attached %s",
- global ? "global " : "", addr_txt);
- return 0;
+ return ctrl_iface_attach(ctrl_dst, from, fromlen);
}
static int wpa_supplicant_ctrl_iface_detach(struct dl_list *ctrl_dst,
- struct sockaddr_un *from,
+ 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 (fromlen == dst->addrlen &&
- os_memcmp(from->sun_path, dst->addr.sun_path,
- fromlen - offsetof(struct sockaddr_un, sun_path))
- == 0) {
- char addr_txt[200];
- printf_encode(addr_txt, sizeof(addr_txt),
- (u8 *) from->sun_path,
- fromlen -
- offsetof(struct sockaddr_un, sun_path));
- wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached %s",
- addr_txt);
- dl_list_del(&dst->list);
- os_free(dst);
- return 0;
- }
- }
- return -1;
+ return ctrl_iface_detach(ctrl_dst, from, fromlen);
}
static int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv,
- struct sockaddr_un *from,
+ struct sockaddr_storage *from,
socklen_t fromlen,
char *level)
{
- struct wpa_ctrl_dst *dst;
-
wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
- dl_list_for_each(dst, &priv->ctrl_dst, struct wpa_ctrl_dst, list) {
- if (fromlen == dst->addrlen &&
- os_memcmp(from->sun_path, dst->addr.sun_path,
- fromlen - offsetof(struct sockaddr_un, sun_path))
- == 0) {
- char addr_txt[200];
- dst->debug_level = atoi(level);
- printf_encode(addr_txt, sizeof(addr_txt),
- (u8 *) from->sun_path, fromlen -
- offsetof(struct sockaddr_un, sun_path));
- wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor level to %d for %s",
- dst->debug_level, addr_txt);
- return 0;
- }
- }
-
- return -1;
+ return ctrl_iface_level(&priv->ctrl_dst, from, fromlen, level);
}
struct ctrl_iface_priv *priv = sock_ctx;
char buf[4096];
int res;
- struct sockaddr_un from;
+ struct sockaddr_storage from;
socklen_t fromlen = sizeof(from);
char *reply = NULL, *reply_buf = NULL;
size_t reply_len = 0;
}
+static int wpas_ctrl_iface_throttle(int sock)
+{
+#ifdef __linux__
+ socklen_t optlen;
+ int sndbuf, outq;
+
+ optlen = sizeof(sndbuf);
+ sndbuf = 0;
+ if (getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sndbuf, &optlen) < 0 ||
+ ioctl(sock, TIOCOUTQ, &outq) < 0 ||
+ sndbuf <= 0 || outq < 0)
+ return 0;
+ return outq > sndbuf / 2;
+#else /* __linux__ */
+ return 0;
+#endif /* __linux__ */
+}
+
+
+static void wpas_ctrl_msg_send_pending_global(struct wpa_global *global)
+{
+ struct ctrl_iface_global_priv *gpriv;
+ struct ctrl_iface_msg *msg;
+
+ gpriv = global->ctrl_iface;
+ while (gpriv && !dl_list_empty(&gpriv->msg_queue) &&
+ !wpas_ctrl_iface_throttle(gpriv->sock)) {
+ msg = dl_list_first(&gpriv->msg_queue, struct ctrl_iface_msg,
+ list);
+ if (!msg)
+ break;
+ dl_list_del(&msg->list);
+ wpa_supplicant_ctrl_iface_send(
+ msg->wpa_s,
+ msg->type != WPA_MSG_PER_INTERFACE ?
+ NULL : msg->wpa_s->ifname,
+ gpriv->sock, &gpriv->ctrl_dst, msg->level,
+ msg->txt, msg->len, NULL, gpriv);
+ os_free(msg);
+ }
+}
+
+
+static void wpas_ctrl_msg_send_pending_iface(struct wpa_supplicant *wpa_s)
+{
+ struct ctrl_iface_priv *priv;
+ struct ctrl_iface_msg *msg;
+
+ priv = wpa_s->ctrl_iface;
+ while (priv && !dl_list_empty(&priv->msg_queue) &&
+ !wpas_ctrl_iface_throttle(priv->sock)) {
+ msg = dl_list_first(&priv->msg_queue, struct ctrl_iface_msg,
+ list);
+ if (!msg)
+ break;
+ dl_list_del(&msg->list);
+ wpa_supplicant_ctrl_iface_send(wpa_s, NULL, priv->sock,
+ &priv->ctrl_dst, msg->level,
+ msg->txt, msg->len, priv, NULL);
+ os_free(msg);
+ }
+}
+
+
+static void wpas_ctrl_msg_queue_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+ struct ctrl_iface_priv *priv;
+ struct ctrl_iface_global_priv *gpriv;
+ int sock = -1, gsock = -1;
+
+ wpas_ctrl_msg_send_pending_global(wpa_s->global);
+ wpas_ctrl_msg_send_pending_iface(wpa_s);
+
+ priv = wpa_s->ctrl_iface;
+ if (priv && !dl_list_empty(&priv->msg_queue))
+ sock = priv->sock;
+
+ gpriv = wpa_s->global->ctrl_iface;
+ if (gpriv && !dl_list_empty(&gpriv->msg_queue))
+ gsock = gpriv->sock;
+
+ if (sock > -1 || gsock > -1) {
+ /* Continue pending message transmission from a timeout */
+ wpa_printf(MSG_MSGDUMP,
+ "CTRL: Had to throttle pending event message transmission for (sock %d gsock %d)",
+ sock, gsock);
+ eloop_register_timeout(0, 20000, wpas_ctrl_msg_queue_timeout,
+ wpa_s, NULL);
+ }
+}
+
+
+static void wpas_ctrl_msg_queue(struct dl_list *queue,
+ struct wpa_supplicant *wpa_s, int level,
+ enum wpa_msg_type type,
+ const char *txt, size_t len)
+{
+ struct ctrl_iface_msg *msg;
+
+ msg = os_zalloc(sizeof(*msg) + len);
+ if (!msg)
+ return;
+
+ msg->wpa_s = wpa_s;
+ msg->level = level;
+ msg->type = type;
+ os_memcpy(msg + 1, txt, len);
+ msg->txt = (const char *) (msg + 1);
+ msg->len = len;
+ dl_list_add_tail(queue, &msg->list);
+ eloop_cancel_timeout(wpas_ctrl_msg_queue_timeout, wpa_s, NULL);
+ eloop_register_timeout(0, 0, wpas_ctrl_msg_queue_timeout, wpa_s, NULL);
+}
+
+
+static void wpas_ctrl_msg_queue_limit(unsigned int throttle_count,
+ struct dl_list *queue)
+{
+ struct ctrl_iface_msg *msg;
+
+ if (throttle_count < 2000)
+ return;
+
+ msg = dl_list_first(queue, struct ctrl_iface_msg, list);
+ if (msg) {
+ wpa_printf(MSG_DEBUG, "CTRL: Dropped oldest pending message");
+ dl_list_del(&msg->list);
+ os_free(msg);
+ }
+}
+
+
static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
enum wpa_msg_type type,
const char *txt, size_t len)
{
struct wpa_supplicant *wpa_s = ctx;
+ struct ctrl_iface_priv *priv;
+ struct ctrl_iface_global_priv *gpriv;
if (wpa_s == NULL)
return;
- if (type != WPA_MSG_NO_GLOBAL && wpa_s->global->ctrl_iface) {
- struct ctrl_iface_global_priv *priv = wpa_s->global->ctrl_iface;
- if (!dl_list_empty(&priv->ctrl_dst)) {
+ gpriv = wpa_s->global->ctrl_iface;
+
+ if (type != WPA_MSG_NO_GLOBAL && gpriv &&
+ !dl_list_empty(&gpriv->ctrl_dst)) {
+ if (!dl_list_empty(&gpriv->msg_queue) ||
+ wpas_ctrl_iface_throttle(gpriv->sock)) {
+ if (gpriv->throttle_count == 0) {
+ wpa_printf(MSG_MSGDUMP,
+ "CTRL: Had to throttle global event message for sock %d",
+ gpriv->sock);
+ }
+ gpriv->throttle_count++;
+ wpas_ctrl_msg_queue_limit(gpriv->throttle_count,
+ &gpriv->msg_queue);
+ wpas_ctrl_msg_queue(&gpriv->msg_queue, wpa_s, level,
+ type, txt, len);
+ } else {
+ if (gpriv->throttle_count) {
+ wpa_printf(MSG_MSGDUMP,
+ "CTRL: Had to throttle %u global event message(s) for sock %d",
+ gpriv->throttle_count, gpriv->sock);
+ }
+ gpriv->throttle_count = 0;
wpa_supplicant_ctrl_iface_send(
wpa_s,
type != WPA_MSG_PER_INTERFACE ?
NULL : wpa_s->ifname,
- priv->sock, &priv->ctrl_dst, level, txt, len,
- NULL, priv);
+ gpriv->sock, &gpriv->ctrl_dst, level,
+ txt, len, NULL, gpriv);
}
}
- if (type == WPA_MSG_ONLY_GLOBAL || wpa_s->ctrl_iface == NULL)
- return;
- wpa_supplicant_ctrl_iface_send(wpa_s, NULL, wpa_s->ctrl_iface->sock,
- &wpa_s->ctrl_iface->ctrl_dst,
- level, txt, len, wpa_s->ctrl_iface,
- NULL);
+ priv = wpa_s->ctrl_iface;
+
+ if (type != WPA_MSG_ONLY_GLOBAL && priv) {
+ if (!dl_list_empty(&priv->msg_queue) ||
+ wpas_ctrl_iface_throttle(priv->sock)) {
+ if (priv->throttle_count == 0) {
+ wpa_printf(MSG_MSGDUMP,
+ "CTRL: Had to throttle event message for sock %d",
+ priv->sock);
+ }
+ priv->throttle_count++;
+ wpas_ctrl_msg_queue_limit(priv->throttle_count,
+ &priv->msg_queue);
+ wpas_ctrl_msg_queue(&priv->msg_queue, wpa_s, level,
+ type, txt, len);
+ } else {
+ if (priv->throttle_count) {
+ wpa_printf(MSG_MSGDUMP,
+ "CTRL: Had to throttle %u event message(s) for sock %d",
+ priv->throttle_count, priv->sock);
+ }
+ priv->throttle_count = 0;
+ wpa_supplicant_ctrl_iface_send(wpa_s, NULL, priv->sock,
+ &priv->ctrl_dst, level,
+ txt, len, priv, NULL);
+ }
+ }
}
if (priv == NULL)
return NULL;
dl_list_init(&priv->ctrl_dst);
+ dl_list_init(&priv->msg_queue);
priv->wpa_s = wpa_s;
priv->sock = -1;
void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
{
struct wpa_ctrl_dst *dst, *prev;
+ struct ctrl_iface_msg *msg, *prev_msg;
+ struct ctrl_iface_global_priv *gpriv;
if (priv->sock > -1) {
char *fname;
free_dst:
dl_list_for_each_safe(dst, prev, &priv->ctrl_dst, struct wpa_ctrl_dst,
- list)
+ list) {
+ dl_list_del(&dst->list);
os_free(dst);
+ }
+ dl_list_for_each_safe(msg, prev_msg, &priv->msg_queue,
+ struct ctrl_iface_msg, list) {
+ dl_list_del(&msg->list);
+ os_free(msg);
+ }
+ gpriv = priv->wpa_s->global->ctrl_iface;
+ if (gpriv) {
+ dl_list_for_each_safe(msg, prev_msg, &gpriv->msg_queue,
+ struct ctrl_iface_msg, list) {
+ if (msg->wpa_s == priv->wpa_s) {
+ dl_list_del(&msg->list);
+ os_free(msg);
+ }
+ }
+ }
+ eloop_cancel_timeout(wpas_ctrl_msg_queue_timeout, priv->wpa_s, NULL);
os_free(priv);
}
dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) {
int _errno;
- char addr_txt[200];
+ char txt[200];
if (level < dst->debug_level)
continue;
- printf_encode(addr_txt, sizeof(addr_txt),
- (u8 *) dst->addr.sun_path, dst->addrlen -
- offsetof(struct sockaddr_un, sun_path));
msg.msg_name = (void *) &dst->addr;
msg.msg_namelen = dst->addrlen;
wpas_ctrl_sock_debug("ctrl_sock-sendmsg", sock, buf, len);
if (sendmsg(sock, &msg, MSG_DONTWAIT) >= 0) {
- wpa_printf(MSG_MSGDUMP,
- "CTRL_IFACE monitor sent successfully to %s",
- addr_txt);
+ sockaddr_print(MSG_MSGDUMP,
+ "CTRL_IFACE monitor sent successfully to",
+ &dst->addr, dst->addrlen);
dst->errors = 0;
continue;
}
_errno = errno;
- wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor[%s]: %d - %s",
- addr_txt, errno, strerror(errno));
+ os_snprintf(txt, sizeof(txt), "CTRL_IFACE monitor: %d (%s) for",
+ _errno, strerror(_errno));
+ sockaddr_print(MSG_DEBUG, txt, &dst->addr, dst->addrlen);
dst->errors++;
if (dst->errors > 10 || _errno == ENOENT || _errno == EPERM) {
- wpa_printf(MSG_INFO, "CTRL_IFACE: Detach monitor %s that cannot receive messages",
- addr_txt);
+ sockaddr_print(MSG_INFO, "CTRL_IFACE: Detach monitor that cannot receive messages:",
+ &dst->addr, dst->addrlen);
wpa_supplicant_ctrl_iface_detach(ctrl_dst, &dst->addr,
dst->addrlen);
}
{
char buf[256];
int res;
- struct sockaddr_un from;
+ struct sockaddr_storage from;
socklen_t fromlen = sizeof(from);
+ if (priv->sock == -1)
+ return;
+
for (;;) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor to "
"attach", priv->wpa_s->ifname);
struct ctrl_iface_global_priv *priv = sock_ctx;
char buf[4096];
int res;
- struct sockaddr_un from;
+ struct sockaddr_storage from;
socklen_t fromlen = sizeof(from);
char *reply = NULL, *reply_buf = NULL;
size_t reply_len;
if (priv == NULL)
return NULL;
dl_list_init(&priv->ctrl_dst);
+ dl_list_init(&priv->msg_queue);
priv->global = global;
priv->sock = -1;
wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
{
struct wpa_ctrl_dst *dst, *prev;
+ struct ctrl_iface_msg *msg, *prev_msg;
if (priv->sock >= 0) {
eloop_unregister_read_sock(priv->sock);
if (priv->global->params.ctrl_interface)
unlink(priv->global->params.ctrl_interface);
dl_list_for_each_safe(dst, prev, &priv->ctrl_dst, struct wpa_ctrl_dst,
- list)
+ list) {
+ dl_list_del(&dst->list);
os_free(dst);
+ }
+ dl_list_for_each_safe(msg, prev_msg, &priv->msg_queue,
+ struct ctrl_iface_msg, list) {
+ dl_list_del(&msg->list);
+ os_free(msg);
+ }
os_free(priv);
}
<policy context="default">
<deny own="fi.epitest.hostap.WPASupplicant"/>
<deny send_destination="fi.epitest.hostap.WPASupplicant"/>
- <deny send_interface="fi.epitest.hostap.WPASupplicant"/>
<deny own="fi.w1.wpa_supplicant1"/>
<deny send_destination="fi.w1.wpa_supplicant1"/>
- <deny send_interface="fi.w1.wpa_supplicant1"/>
<deny receive_sender="fi.w1.wpa_supplicant1" receive_type="signal"/>
</policy>
</busconfig>
#include <dbus/dbus.h>
+struct wpa_dbus_property_desc;
+
struct wpas_dbus_priv {
DBusConnection *con;
int should_dispatch;
u32 next_objid;
int dbus_new_initialized;
-#if defined(CONFIG_CTRL_IFACE_DBUS_NEW) && defined(CONFIG_AP)
+#if defined(CONFIG_CTRL_IFACE_DBUS_NEW)
+ struct wpa_dbus_property_desc *all_interface_properties;
+ int globals_start;
+#if defined(CONFIG_AP)
int dbus_noc_refcnt;
-#endif /* CONFIG_CTRL_IFACE_DBUS_NEW && CONFIG_AP */
+#endif /* CONFIG_AP */
+#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
};
#endif /* DBUS_COMMON_I_H */
/**
- * Add a byte entry to the dict.
- *
- * @param iter_dict A valid DBusMessageIter returned from
- * wpa_dbus_dict_open_write()
- * @param key The key of the dict item
- * @param value The byte value
- * @return TRUE on success, FALSE on failure
- *
- */
-dbus_bool_t wpa_dbus_dict_append_byte(DBusMessageIter *iter_dict,
- const char *key, const char value)
-{
- return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_BYTE,
- &value);
-}
-
-
-/**
* Add a boolean entry to the dict.
*
* @param iter_dict A valid DBusMessageIter returned from
/**
- * Add a 64-bit integer entry to the dict.
- *
- * @param iter_dict A valid DBusMessageIter returned from
- * wpa_dbus_dict_open_write()
- * @param key The key of the dict item
- * @param value The 64-bit integer value
- * @return TRUE on success, FALSE on failure
- *
- */
-dbus_bool_t wpa_dbus_dict_append_int64(DBusMessageIter *iter_dict,
- const char *key,
- const dbus_int64_t value)
-{
- return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT64,
- &value);
-}
-
-
-/**
- * Add a 64-bit unsigned integer entry to the dict.
- *
- * @param iter_dict A valid DBusMessageIter returned from
- * wpa_dbus_dict_open_write()
- * @param key The key of the dict item
- * @param value The 64-bit unsigned integer value
- * @return TRUE on success, FALSE on failure
- *
- */
-dbus_bool_t wpa_dbus_dict_append_uint64(DBusMessageIter *iter_dict,
- const char *key,
- const dbus_uint64_t value)
-{
- return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT64,
- &value);
-}
-
-
-/**
- * Add a double-precision floating point entry to the dict.
- *
- * @param iter_dict A valid DBusMessageIter returned from
- * wpa_dbus_dict_open_write()
- * @param key The key of the dict item
- * @param value The double-precision floating point value
- * @return TRUE on success, FALSE on failure
- *
- */
-dbus_bool_t wpa_dbus_dict_append_double(DBusMessageIter *iter_dict,
- const char *key, const double value)
-{
- return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_DOUBLE,
- &value);
-}
-
-
-/**
* Add a DBus object path entry to the dict.
*
* @param iter_dict A valid DBusMessageIter returned from
dbus_bool_t wpa_dbus_dict_append_string(DBusMessageIter *iter_dict,
const char *key, const char *value);
-dbus_bool_t wpa_dbus_dict_append_byte(DBusMessageIter *iter_dict,
- const char *key, const char value);
-
dbus_bool_t wpa_dbus_dict_append_bool(DBusMessageIter *iter_dict,
const char *key,
const dbus_bool_t value);
const char *key,
const dbus_uint32_t value);
-dbus_bool_t wpa_dbus_dict_append_int64(DBusMessageIter *iter_dict,
- const char *key,
- const dbus_int64_t value);
-
-dbus_bool_t wpa_dbus_dict_append_uint64(DBusMessageIter *iter_dict,
- const char *key,
- const dbus_uint64_t value);
-
-dbus_bool_t wpa_dbus_dict_append_double(DBusMessageIter *iter_dict,
- const char *key,
- const double value);
-
dbus_bool_t wpa_dbus_dict_append_object_path(DBusMessageIter *iter_dict,
const char *key,
const char *value);
cfg->ssid_len);
if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
wpas_dbus_signal_peer_groups_changed(
- data->wpa_s->parent, data->info->p2p_device_addr);
+ data->wpa_s->p2pdev, data->info->p2p_device_addr);
return 0;
}
wpa_s_go = wpas_get_p2p_client_iface(data->wpa_s,
info->p2p_device_addr);
if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
- wpas_dbus_signal_peer_groups_changed(data->wpa_s->parent,
+ wpas_dbus_signal_peer_groups_changed(data->wpa_s->p2pdev,
info->p2p_device_addr);
return;
}
* irrespective of the role (client/GO) of the current device
*
* @wpa_s: %wpa_supplicant network interface data
- * @ssid: SSID object
* @client: this device is P2P client
- * @network_id: network id of the group started, use instead of ssid->id
- * to account for persistent groups
+ * @persistent: 0 - non persistent group, 1 - persistent group
*/
void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
- const struct wpa_ssid *ssid,
- int client, int network_id)
+ int client, int persistent)
{
DBusMessage *msg;
DBusMessageIter iter, dict_iter;
wpa_s->dbus_new_path) ||
!wpa_dbus_dict_append_string(&dict_iter, "role",
client ? "client" : "GO") ||
+ !wpa_dbus_dict_append_bool(&dict_iter, "persistent", persistent) ||
!wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
wpa_s->dbus_groupobj_path) ||
!wpa_dbus_dict_close_write(&iter, &dict_iter)) {
}
dbus_connection_send(iface->con, msg, NULL);
+ dbus_message_unref(msg);
}
prop = "DisconnectReason";
flush = TRUE;
break;
+ case WPAS_DBUS_PROP_ASSOC_STATUS_CODE:
+ prop = "AssocStatusCode";
+ flush = TRUE;
+ break;
default:
wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
__func__, property);
END_ARGS
}
},
+ { "ExpectDisconnect", WPAS_DBUS_NEW_INTERFACE,
+ (WPADBusMethodHandler) wpas_dbus_handler_expect_disconnect,
+ {
+ END_ARGS
+ }
+ },
{ NULL, NULL, NULL, { END_ARGS } }
};
static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = {
{ "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s",
wpas_dbus_getter_debug_level,
- wpas_dbus_setter_debug_level
+ wpas_dbus_setter_debug_level,
+ NULL
},
{ "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
wpas_dbus_getter_debug_timestamp,
- wpas_dbus_setter_debug_timestamp
+ wpas_dbus_setter_debug_timestamp,
+ NULL
},
{ "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
wpas_dbus_getter_debug_show_keys,
- wpas_dbus_setter_debug_show_keys
+ wpas_dbus_setter_debug_show_keys,
+ NULL
},
{ "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
wpas_dbus_getter_interfaces,
+ NULL,
NULL
},
{ "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
wpas_dbus_getter_eap_methods,
+ NULL,
NULL
},
{ "Capabilities", WPAS_DBUS_NEW_INTERFACE, "as",
wpas_dbus_getter_global_capabilities,
+ NULL,
NULL
},
#ifdef CONFIG_WIFI_DISPLAY
{ "WFDIEs", WPAS_DBUS_NEW_INTERFACE, "ay",
wpas_dbus_getter_global_wfd_ies,
- wpas_dbus_setter_global_wfd_ies
+ wpas_dbus_setter_global_wfd_ies,
+ NULL
},
#endif /* CONFIG_WIFI_DISPLAY */
- { NULL, NULL, NULL, NULL, NULL }
+ { NULL, NULL, NULL, NULL, NULL, NULL }
};
static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
};
+static char * uscore_to_dbus(const char *uscore)
+{
+ const char *p = uscore;
+ char *str, *s;
+ dbus_bool_t last_was_uscore = TRUE;
+
+ s = str = os_zalloc(os_strlen(uscore) + 1);
+ if (!str)
+ return NULL;
+ while (p && *p) {
+ if (*p == '_') {
+ last_was_uscore = TRUE;
+ } else {
+ *s++ = last_was_uscore ? toupper(*p) : *p;
+ last_was_uscore = FALSE;
+ }
+ p++;
+ }
+
+ return str;
+}
+
+
+static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv);
+
+
+static void wpa_dbus_ctrl_iface_props_deinit(struct wpas_dbus_priv *priv)
+{
+ int idx = priv->globals_start;
+
+ /* Free all allocated property values */
+ while (priv->all_interface_properties[idx].dbus_property)
+ os_free((char *)
+ priv->all_interface_properties[idx++].dbus_property);
+ os_free((char *) priv->all_interface_properties);
+}
+
+
/**
* wpas_dbus_ctrl_iface_init - Initialize dbus control interface
* @global: Pointer to global data from wpa_supplicant_init()
* Returns: 0 on success or -1 on failure
*
- * Initialize the dbus control interface for wpa_supplicantand and start
+ * Initialize the dbus control interface for wpa_supplicant and start
* receiving commands from external programs over the bus.
*/
int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
struct wpa_dbus_object_desc *obj_desc;
int ret;
+ ret = wpa_dbus_ctrl_iface_props_init(priv);
+ if (ret < 0) {
+ wpa_printf(MSG_ERROR,
+ "dbus: Not enough memory to init interface properties");
+ return -1;
+ }
+
obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
if (!obj_desc) {
wpa_printf(MSG_ERROR,
"Not enough memory to create object description");
- return -1;
+ goto error;
}
wpas_dbus_register(obj_desc, priv->global, NULL,
ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
WPAS_DBUS_NEW_SERVICE,
obj_desc);
- if (ret < 0)
+ if (ret < 0) {
free_dbus_object_desc(obj_desc);
- else
- priv->dbus_new_initialized = 1;
+ goto error;
+ }
- return ret;
+ priv->dbus_new_initialized = 1;
+ return 0;
+
+error:
+ wpa_dbus_ctrl_iface_props_deinit(priv);
+ return -1;
}
/**
* wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
* wpa_supplicant
- * @iface: Pointer to dbus private data from wpas_dbus_init()
+ * @priv: Pointer to dbus private data from wpas_dbus_init()
*
* Deinitialize the dbus control interface that was initialized with
* wpas_dbus_ctrl_iface_init().
*/
-void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface)
+void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *priv)
{
- if (!iface->dbus_new_initialized)
+ if (!priv->dbus_new_initialized)
return;
wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
WPAS_DBUS_NEW_PATH);
- dbus_connection_unregister_object_path(iface->con,
- WPAS_DBUS_NEW_PATH);
+ dbus_connection_unregister_object_path(priv->con, WPAS_DBUS_NEW_PATH);
+ wpa_dbus_ctrl_iface_props_deinit(priv);
}
static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
{ "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
wpas_dbus_getter_network_properties,
- wpas_dbus_setter_network_properties
+ wpas_dbus_setter_network_properties,
+ NULL
},
{ "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
wpas_dbus_getter_enabled,
- wpas_dbus_setter_enabled
+ wpas_dbus_setter_enabled,
+ NULL
},
- { NULL, NULL, NULL, NULL, NULL }
+ { NULL, NULL, NULL, NULL, NULL, NULL }
};
static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
{ "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
wpas_dbus_getter_bss_ssid,
+ NULL,
NULL
},
{ "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
wpas_dbus_getter_bss_bssid,
+ NULL,
NULL
},
{ "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b",
wpas_dbus_getter_bss_privacy,
+ NULL,
NULL
},
{ "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s",
wpas_dbus_getter_bss_mode,
+ NULL,
NULL
},
{ "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n",
wpas_dbus_getter_bss_signal,
+ NULL,
NULL
},
{ "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q",
wpas_dbus_getter_bss_frequency,
+ NULL,
NULL
},
{ "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au",
wpas_dbus_getter_bss_rates,
+ NULL,
NULL
},
{ "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
wpas_dbus_getter_bss_wpa,
+ NULL,
NULL
},
{ "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
wpas_dbus_getter_bss_rsn,
+ NULL,
NULL
},
{ "WPS", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
wpas_dbus_getter_bss_wps,
+ NULL,
NULL
},
{ "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay",
wpas_dbus_getter_bss_ies,
+ NULL,
NULL
},
{ "Age", WPAS_DBUS_NEW_IFACE_BSS, "u",
wpas_dbus_getter_bss_age,
+ NULL,
NULL
},
- { NULL, NULL, NULL, NULL, NULL }
+ { NULL, NULL, NULL, NULL, NULL, NULL }
};
}
},
#endif /* CONFIG_TDLS */
+ { "VendorElemAdd", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_add,
+ {
+ { "frame_id", "i", ARG_IN },
+ { "ielems", "ay", ARG_IN },
+ END_ARGS
+ }
+ },
+ { "VendorElemGet", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_get,
+ {
+ { "frame_id", "i", ARG_IN },
+ { "ielems", "ay", ARG_OUT },
+ END_ARGS
+ }
+ },
+ { "VendorElemRem", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ (WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_remove,
+ {
+ { "frame_id", "i", ARG_IN },
+ { "ielems", "ay", ARG_IN },
+ END_ARGS
+ }
+ },
+#ifndef CONFIG_NO_CONFIG_WRITE
+ { "SaveConfig", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ (WPADBusMethodHandler) wpas_dbus_handler_save_config,
+ {
+ END_ARGS
+ }
+ },
+#endif /* CONFIG_NO_CONFIG_WRITE */
{ NULL, NULL, NULL, { END_ARGS } }
};
static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
{ "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
wpas_dbus_getter_capabilities,
+ NULL,
NULL
},
{ "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
wpas_dbus_getter_state,
+ NULL,
NULL
},
{ "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
wpas_dbus_getter_scanning,
+ NULL,
NULL
},
{ "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
wpas_dbus_getter_ap_scan,
- wpas_dbus_setter_ap_scan
+ wpas_dbus_setter_ap_scan,
+ NULL
},
{ "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
wpas_dbus_getter_bss_expire_age,
- wpas_dbus_setter_bss_expire_age
+ wpas_dbus_setter_bss_expire_age,
+ NULL
},
{ "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
wpas_dbus_getter_bss_expire_count,
- wpas_dbus_setter_bss_expire_count
+ wpas_dbus_setter_bss_expire_count,
+ NULL
},
{ "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
wpas_dbus_getter_country,
- wpas_dbus_setter_country
+ wpas_dbus_setter_country,
+ NULL
},
{ "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
wpas_dbus_getter_ifname,
+ NULL,
NULL
},
{ "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
wpas_dbus_getter_driver,
+ NULL,
NULL
},
{ "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
wpas_dbus_getter_bridge_ifname,
+ NULL,
+ NULL
+ },
+ { "ConfigFile", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
+ wpas_dbus_getter_config_file,
+ NULL,
NULL
},
{ "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
wpas_dbus_getter_current_bss,
+ NULL,
NULL
},
{ "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
wpas_dbus_getter_current_network,
+ NULL,
NULL
},
{ "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
wpas_dbus_getter_current_auth_mode,
+ NULL,
NULL
},
{ "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
wpas_dbus_getter_blobs,
+ NULL,
NULL
},
{ "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
wpas_dbus_getter_bsss,
+ NULL,
NULL
},
{ "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
wpas_dbus_getter_networks,
+ NULL,
NULL
},
{ "FastReauth", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
wpas_dbus_getter_fast_reauth,
- wpas_dbus_setter_fast_reauth
+ wpas_dbus_setter_fast_reauth,
+ NULL
},
{ "ScanInterval", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
wpas_dbus_getter_scan_interval,
- wpas_dbus_setter_scan_interval
+ wpas_dbus_setter_scan_interval,
+ NULL
},
{ "PKCS11EnginePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
wpas_dbus_getter_pkcs11_engine_path,
+ NULL,
NULL
},
{ "PKCS11ModulePath", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
wpas_dbus_getter_pkcs11_module_path,
+ NULL,
NULL
},
#ifdef CONFIG_WPS
{ "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
wpas_dbus_getter_process_credentials,
- wpas_dbus_setter_process_credentials
+ wpas_dbus_setter_process_credentials,
+ NULL
},
{ "ConfigMethods", WPAS_DBUS_NEW_IFACE_WPS, "s",
wpas_dbus_getter_config_methods,
- wpas_dbus_setter_config_methods
+ wpas_dbus_setter_config_methods,
+ NULL
},
#endif /* CONFIG_WPS */
#ifdef CONFIG_P2P
{ "P2PDeviceConfig", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "a{sv}",
wpas_dbus_getter_p2p_device_config,
- wpas_dbus_setter_p2p_device_config
+ wpas_dbus_setter_p2p_device_config,
+ NULL
},
{ "Peers", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
wpas_dbus_getter_p2p_peers,
+ NULL,
NULL
},
{ "Role", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "s",
wpas_dbus_getter_p2p_role,
+ NULL,
NULL
},
{ "Group", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
wpas_dbus_getter_p2p_group,
+ NULL,
NULL
},
{ "PeerGO", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "o",
wpas_dbus_getter_p2p_peergo,
+ NULL,
NULL
},
{ "PersistentGroups", WPAS_DBUS_NEW_IFACE_P2PDEVICE, "ao",
wpas_dbus_getter_persistent_groups,
+ NULL,
NULL
},
#endif /* CONFIG_P2P */
{ "DisconnectReason", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
wpas_dbus_getter_disconnect_reason,
+ NULL,
+ NULL
+ },
+ { "AssocStatusCode", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
+ wpas_dbus_getter_assoc_status_code,
+ NULL,
NULL
},
- { NULL, NULL, NULL, NULL, NULL }
+ { NULL, NULL, NULL, NULL, NULL, NULL }
};
static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
END_ARGS
}
},
+ { "DeviceFoundProperties", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+ {
+ { "path", "o", ARG_OUT },
+ { "properties", "a{sv}", ARG_OUT },
+ END_ARGS
+ }
+ },
{ "DeviceLost", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
{
{ "path", "o", ARG_OUT },
};
+static int wpa_dbus_ctrl_iface_props_init(struct wpas_dbus_priv *priv)
+{
+ size_t all_size;
+ unsigned int i, j, count, num_const, num_globals;
+ const char *global_name;
+ static const char * const ignored_globals[] = {
+ "bss_expiration_age", "bss_expiration_scan_count",
+ "ap_scan", "country", "fast_reauth",
+ "pkcs11_engine_path", "pkcs11_module_path"
+ };
+
+ /* wpas_dbus_interface_properties terminates with a NULL element */
+ num_const = ARRAY_SIZE(wpas_dbus_interface_properties) - 1;
+
+ num_globals = wpa_config_get_num_global_field_names();
+ priv->globals_start = num_const;
+
+ /* allocate enough for all properties + terminating NULL element */
+ all_size = (num_globals + num_const + 1) *
+ sizeof(wpas_dbus_interface_properties[0]);
+ priv->all_interface_properties = os_zalloc(all_size);
+ if (!priv->all_interface_properties) {
+ wpa_printf(MSG_ERROR,
+ "dbus: Not enough memory for interface properties");
+ return -1;
+ }
+
+ /* Copy constant interface properties to the start of the array */
+ os_memcpy(priv->all_interface_properties,
+ wpas_dbus_interface_properties,
+ sizeof(wpas_dbus_interface_properties));
+
+ /* Dynamically construct interface global properties */
+ for (i = 0, count = num_const; i < num_globals; i++) {
+ struct wpa_dbus_property_desc *desc;
+ int no_var = 0;
+
+ /* ignore globals that are actually just methods */
+ global_name = wpa_config_get_global_field_name(i, &no_var);
+ if (no_var)
+ continue;
+ /* Ignore fields already explicitly exposed */
+ for (j = 0; j < ARRAY_SIZE(ignored_globals); j++) {
+ if (os_strcmp(global_name, ignored_globals[j]) == 0)
+ break;
+ }
+ if (j < ARRAY_SIZE(ignored_globals))
+ continue;
+
+ desc = &priv->all_interface_properties[count++];
+ desc->dbus_property = uscore_to_dbus(global_name);
+ if (!desc->dbus_property) {
+ wpa_printf(MSG_ERROR,
+ "dbus: Not enough memory for D-Bus property name");
+ goto error;
+ }
+ desc->dbus_interface = WPAS_DBUS_NEW_IFACE_INTERFACE;
+ desc->type = "s";
+ desc->getter = wpas_dbus_getter_iface_global;
+ desc->setter = wpas_dbus_setter_iface_global;
+ desc->data = global_name;
+ }
+
+ return 0;
+
+error:
+ wpa_dbus_ctrl_iface_props_deinit(priv);
+ return -1;
+}
+
+
/**
* wpas_dbus_register_interface - Register an interface with D-Bus
* @wpa_s: wpa_supplicant interface structure
*/
int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
{
-
struct wpa_dbus_object_desc *obj_desc = NULL;
struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
int next;
}
wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
- wpas_dbus_interface_properties,
+ ctrl_iface->all_interface_properties,
wpas_dbus_interface_signals);
wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = {
{ "DeviceName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
wpas_dbus_getter_p2p_peer_device_name,
+ NULL,
NULL
},
{ "Manufacturer", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
wpas_dbus_getter_p2p_peer_manufacturer,
+ NULL,
NULL
},
{ "ModelName", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
wpas_dbus_getter_p2p_peer_modelname,
+ NULL,
NULL
},
{ "ModelNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
wpas_dbus_getter_p2p_peer_modelnumber,
+ NULL,
NULL
},
{ "SerialNumber", WPAS_DBUS_NEW_IFACE_P2P_PEER, "s",
wpas_dbus_getter_p2p_peer_serialnumber,
+ NULL,
NULL
},
{ "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
wpas_dbus_getter_p2p_peer_primary_device_type,
+ NULL,
NULL
},
{ "config_method", WPAS_DBUS_NEW_IFACE_P2P_PEER, "q",
wpas_dbus_getter_p2p_peer_config_method,
+ NULL,
NULL
},
{ "level", WPAS_DBUS_NEW_IFACE_P2P_PEER, "i",
wpas_dbus_getter_p2p_peer_level,
+ NULL,
NULL
},
{ "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
wpas_dbus_getter_p2p_peer_device_capability,
+ NULL,
NULL
},
{ "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y",
wpas_dbus_getter_p2p_peer_group_capability,
+ NULL,
NULL
},
{ "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
wpas_dbus_getter_p2p_peer_secondary_device_types,
+ NULL,
NULL
},
{ "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay",
wpas_dbus_getter_p2p_peer_vendor_extension,
+ NULL,
NULL
},
{ "IEs", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
wpas_dbus_getter_p2p_peer_ies,
+ NULL,
NULL
},
{ "DeviceAddress", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
wpas_dbus_getter_p2p_peer_device_address,
+ NULL,
NULL
},
{ "Groups", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ao",
wpas_dbus_getter_p2p_peer_groups,
+ NULL,
NULL
},
- { NULL, NULL, NULL, NULL, NULL }
+ { NULL, NULL, NULL, NULL, NULL, NULL }
};
static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = {
* In case of peer objects, it would be emitted by either
* the "interface object" or by "peer objects"
* @sig_name: signal name - DeviceFound
+ * @properties: Whether to add a second argument with object properties
*
- * Notify listeners about event related with newly found p2p peer device
+ * Notify listeners about event related with p2p peer device
*/
static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s,
const u8 *dev_addr, const char *interface,
- const char *sig_name)
+ const char *sig_name, int properties)
{
struct wpas_dbus_priv *iface;
DBusMessage *msg;
dbus_message_iter_init_append(msg, &iter);
path = peer_obj_path;
if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
- &path))
+ &path) ||
+ (properties && !wpa_dbus_get_object_properties(
+ iface, peer_obj_path, WPAS_DBUS_NEW_IFACE_P2P_PEER,
+ &iter)))
wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
else
dbus_connection_send(iface->con, msg, NULL);
{
wpas_dbus_signal_peer(wpa_s, dev_addr,
WPAS_DBUS_NEW_IFACE_P2PDEVICE,
- "DeviceFound");
+ "DeviceFound", FALSE);
+
+ wpas_dbus_signal_peer(wpa_s, dev_addr,
+ WPAS_DBUS_NEW_IFACE_P2PDEVICE,
+ "DeviceFoundProperties", TRUE);
}
/**
{
wpas_dbus_signal_peer(wpa_s, dev_addr,
WPAS_DBUS_NEW_IFACE_P2PDEVICE,
- "DeviceLost");
+ "DeviceLost", FALSE);
}
/**
static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = {
{ "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao",
wpas_dbus_getter_p2p_group_members,
+ NULL,
NULL
},
{ "Group", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "o",
wpas_dbus_getter_p2p_group,
+ NULL,
NULL
},
{ "Role", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
wpas_dbus_getter_p2p_role,
+ NULL,
NULL
},
{ "SSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
wpas_dbus_getter_p2p_group_ssid,
+ NULL,
NULL
},
{ "BSSID", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
wpas_dbus_getter_p2p_group_bssid,
+ NULL,
NULL
},
{ "Frequency", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "q",
wpas_dbus_getter_p2p_group_frequency,
+ NULL,
NULL
},
{ "Passphrase", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "s",
wpas_dbus_getter_p2p_group_passphrase,
+ NULL,
NULL
},
{ "PSK", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ay",
wpas_dbus_getter_p2p_group_psk,
+ NULL,
NULL
},
{ "WPSVendorExtensions", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "aay",
wpas_dbus_getter_p2p_group_vendor_ext,
- wpas_dbus_setter_p2p_group_vendor_ext
+ wpas_dbus_setter_p2p_group_vendor_ext,
+ NULL
},
- { NULL, NULL, NULL, NULL, NULL }
+ { NULL, NULL, NULL, NULL, NULL, NULL }
};
static const struct wpa_dbus_signal_desc wpas_dbus_p2p_group_signals[] = {
wpas_dbus_persistent_group_properties[] = {
{ "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}",
wpas_dbus_getter_persistent_group_properties,
- wpas_dbus_setter_persistent_group_properties
+ wpas_dbus_setter_persistent_group_properties,
+ NULL
},
- { NULL, NULL, NULL, NULL, NULL }
+ { NULL, NULL, NULL, NULL, NULL, NULL }
};
/* No signals intended for persistent group objects */
WPAS_DBUS_PROP_CURRENT_AUTH_MODE,
WPAS_DBUS_PROP_BSSS,
WPAS_DBUS_PROP_DISCONNECT_REASON,
+ WPAS_DBUS_PROP_ASSOC_STATUS_CODE,
};
enum wpas_dbus_bss_prop {
const u8 *src, u16 dev_passwd_id,
u8 go_intent);
void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
- const struct wpa_ssid *ssid,
- int client, int network_id);
+ int client, int persistent);
void wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant *wpa_s,
const char *reason);
void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s,
static inline void
wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
- const struct wpa_ssid *ssid,
- int client, int network_id)
+ int client, int persistent)
{
}
for (i = 0; i < array_len; i++) {
if (!dbus_message_iter_append_basic(&array_iter, type,
- array + i * element_size)) {
+ (const char *) array +
+ i * element_size)) {
dbus_set_error(error, DBUS_ERROR_FAILED,
"%s: failed to construct message 2.5",
__func__);
*
* Getter for "DebugLevel" property.
*/
-dbus_bool_t wpas_dbus_getter_debug_level(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_debug_level(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
const char *str;
int idx = wpa_debug_level;
*
* Getter for "DebugTimestamp" property.
*/
-dbus_bool_t wpas_dbus_getter_debug_timestamp(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_debug_timestamp(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
&wpa_debug_timestamp, error);
*
* Getter for "DebugShowKeys" property.
*/
-dbus_bool_t wpas_dbus_getter_debug_show_keys(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_debug_show_keys(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_BOOLEAN,
&wpa_debug_show_keys, error);
*
* Setter for "DebugLevel" property.
*/
-dbus_bool_t wpas_dbus_setter_debug_level(DBusMessageIter *iter,
- DBusError *error, void *user_data)
+dbus_bool_t wpas_dbus_setter_debug_level(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_global *global = user_data;
const char *str = NULL;
*
* Setter for "DebugTimestamp" property.
*/
-dbus_bool_t wpas_dbus_setter_debug_timestamp(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_setter_debug_timestamp(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_global *global = user_data;
dbus_bool_t val;
*
* Setter for "DebugShowKeys" property.
*/
-dbus_bool_t wpas_dbus_setter_debug_show_keys(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_setter_debug_show_keys(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_global *global = user_data;
dbus_bool_t val;
* by dbus clients to return list of registered interfaces objects
* paths
*/
-dbus_bool_t wpas_dbus_getter_interfaces(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_interfaces(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_global *global = user_data;
struct wpa_supplicant *wpa_s;
* Getter for "EapMethods" property. Handles requests
* by dbus clients to return list of strings with supported EAP methods
*/
-dbus_bool_t wpas_dbus_getter_eap_methods(DBusMessageIter *iter,
- DBusError *error, void *user_data)
+dbus_bool_t wpas_dbus_getter_eap_methods(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
char **eap_methods;
size_t num_items = 0;
* return a list of strings with supported capabilities like AP, RSN IBSS,
* and P2P that are determined at compile time.
*/
-dbus_bool_t wpas_dbus_getter_global_capabilities(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_global_capabilities(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
const char *capabilities[5] = { NULL, NULL, NULL, NULL, NULL };
size_t num_items = 0;
struct wpa_supplicant *wpa_s)
{
if (wpa_s->current_ssid != NULL) {
- wpa_s->disconnected = 1;
- wpa_supplicant_deauthenticate(wpa_s,
- WLAN_REASON_DEAUTH_LEAVING);
-
+ wpas_request_disconnection(wpa_s);
return NULL;
}
dbus_message_iter_init(message, &iter);
if (wpa_s->dbus_new_path)
- ssid = wpa_config_add_network(wpa_s->conf);
+ ssid = wpa_supplicant_add_network(wpa_s);
if (ssid == NULL) {
wpa_printf(MSG_ERROR, "%s[dbus]: can't add new interface.",
__func__);
"wpa_supplicant could not add a network on this interface.");
goto err;
}
- wpas_notify_network_added(wpa_s, ssid);
- ssid->disabled = 1;
- wpa_config_set_network_defaults(ssid);
dbus_error_init(&error);
if (!set_network_properties(wpa_s, ssid, &iter, &error)) {
/**
+ * wpas_dbus_handler_expect_disconnect - ExpectDisconnect
+ * @message: Pointer to incoming dbus message
+ * @global: %wpa_supplicant global data structure
+ * Returns: NULL
+ *
+ * Handler function for notifying system there will be a expected disconnect.
+ * This will prevent wpa_supplicant from adding blacklists upon next disconnect..
+ */
+DBusMessage * wpas_dbus_handler_expect_disconnect(DBusMessage *message,
+ struct wpa_global *global)
+{
+ struct wpa_supplicant *wpa_s = global->ifaces;
+
+ for (; wpa_s; wpa_s = wpa_s->next)
+ if (wpa_s->wpa_state >= WPA_ASSOCIATED)
+ wpa_s->own_disconnect_req = 1;
+ return NULL;
+}
+
+
+/**
* wpas_dbus_handler_reattach - Reattach to current AP
* @message: Pointer to incoming dbus message
* @wpa_s: wpa_supplicant structure for a network interface
const char *op;
char *iface, *net_id;
int id;
- struct wpa_ssid *ssid;
- int was_disabled;
+ int result;
dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
DBUS_TYPE_INVALID);
goto out;
}
- ssid = wpa_config_get_network(wpa_s->conf, id);
- if (ssid == NULL) {
+ result = wpa_supplicant_remove_network(wpa_s, id);
+ if (result == -1) {
reply = wpas_dbus_error_network_unknown(message);
goto out;
}
-
- was_disabled = ssid->disabled;
-
- wpas_notify_network_removed(wpa_s, ssid);
-
- if (ssid == wpa_s->current_ssid)
- wpa_supplicant_deauthenticate(wpa_s,
- WLAN_REASON_DEAUTH_LEAVING);
- else if (!was_disabled && wpa_s->sched_scanning) {
- wpa_printf(MSG_DEBUG,
- "Stop ongoing sched_scan to remove network from filters");
- wpa_supplicant_cancel_sched_scan(wpa_s);
- wpa_supplicant_req_scan(wpa_s, 0, 0);
- }
-
- if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
+ if (result == -2) {
wpa_printf(MSG_ERROR,
"%s[dbus]: error occurred when removing network %d",
__func__, id);
os_free(iface);
return reply;
#else /* IEEE8021X_EAPOL */
- wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
+ wpa_printf(MSG_DEBUG, "dbus: 802.1X not included");
return wpas_dbus_error_unknown_error(message, "802.1X not included");
#endif /* IEEE8021X_EAPOL */
}
#endif /* CONFIG_TDLS */
+#ifndef CONFIG_NO_CONFIG_WRITE
+/**
+ * wpas_dbus_handler_save_config - Save configuration to configuration file
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: NULL on Success, Otherwise errror message
+ *
+ * Handler function for "SaveConfig" method call of network interface.
+ */
+DBusMessage * wpas_dbus_handler_save_config(DBusMessage *message,
+ struct wpa_supplicant *wpa_s)
+{
+ int ret;
+
+ if (!wpa_s->conf->update_config) {
+ return wpas_dbus_error_unknown_error(
+ message,
+ "Not allowed to update configuration (update_config=0)");
+ }
+
+ ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
+ if (ret)
+ return wpas_dbus_error_unknown_error(
+ message, "Failed to update configuration");
+ return NULL;
+}
+#endif /* CONFIG_NO_CONFIG_WRITE */
+
+
/**
* wpas_dbus_handler_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
* @message: Pointer to incoming dbus message
*
* Getter for "Capabilities" property of an interface.
*/
-dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter,
- DBusError *error, void *user_data)
+dbus_bool_t wpas_dbus_getter_capabilities(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
struct wpa_driver_capa capa;
&iter_array) ||
!wpa_dbus_dict_string_array_add_element(
&iter_array, "infrastructure") ||
- !wpa_dbus_dict_string_array_add_element(
- &iter_array, "ad-hoc") ||
+ (res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_IBSS) &&
+ !wpa_dbus_dict_string_array_add_element(
+ &iter_array, "ad-hoc")) ||
(res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_AP) &&
!wpa_dbus_dict_string_array_add_element(
&iter_array, "ap")) ||
(res >= 0 && (capa.flags & WPA_DRIVER_FLAGS_P2P_CAPABLE) &&
+ !wpa_s->conf->p2p_disabled &&
!wpa_dbus_dict_string_array_add_element(
&iter_array, "p2p")) ||
!wpa_dbus_dict_end_string_array(&iter_dict,
*
* Getter for "State" property.
*/
-dbus_bool_t wpas_dbus_getter_state(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_state(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
const char *str_state;
*
* Getter for "scanning" property.
*/
-dbus_bool_t wpas_dbus_getter_scanning(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_scanning(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
*
* Getter function for "ApScan" property.
*/
-dbus_bool_t wpas_dbus_getter_ap_scan(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_ap_scan(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
*
* Setter function for "ApScan" property.
*/
-dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_setter_ap_scan(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
dbus_uint32_t ap_scan;
*
* Getter function for "FastReauth" property.
*/
-dbus_bool_t wpas_dbus_getter_fast_reauth(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_fast_reauth(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
dbus_bool_t fast_reauth = wpa_s->conf->fast_reauth ? TRUE : FALSE;
*
* Setter function for "FastReauth" property.
*/
-dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_setter_fast_reauth(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
dbus_bool_t fast_reauth;
* Getter for "DisconnectReason" property. The reason is negative if it is
* locally generated.
*/
-dbus_bool_t wpas_dbus_getter_disconnect_reason(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_disconnect_reason(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
dbus_int32_t reason = wpa_s->disconnect_reason;
/**
+ * wpas_dbus_getter_assoc_status_code - Get most recent failed assoc status code
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "AssocStatusCode" property.
+ */
+dbus_bool_t wpas_dbus_getter_assoc_status_code(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+ dbus_int32_t status_code = wpa_s->assoc_status_code;
+
+ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_INT32,
+ &status_code, error);
+}
+
+
+/**
* wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
* @iter: Pointer to incoming dbus message iter
* @error: Location to store error on failure
*
* Getter function for "BSSExpireAge" property.
*/
-dbus_bool_t wpas_dbus_getter_bss_expire_age(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_expire_age(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
*
* Setter function for "BSSExpireAge" property.
*/
-dbus_bool_t wpas_dbus_setter_bss_expire_age(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_setter_bss_expire_age(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
dbus_uint32_t expire_age;
*
* Getter function for "BSSExpireCount" property.
*/
-dbus_bool_t wpas_dbus_getter_bss_expire_count(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_expire_count(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_scan_count;
*
* Setter function for "BSSExpireCount" property.
*/
-dbus_bool_t wpas_dbus_setter_bss_expire_count(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_setter_bss_expire_count(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
dbus_uint32_t expire_count;
*
* Getter function for "Country" property.
*/
-dbus_bool_t wpas_dbus_getter_country(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_country(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
char country[3];
*
* Setter function for "Country" property.
*/
-dbus_bool_t wpas_dbus_setter_country(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_setter_country(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
const char *country;
*
* Getter function for "ScanInterval" property.
*/
-dbus_bool_t wpas_dbus_getter_scan_interval(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_scan_interval(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
dbus_int32_t scan_interval = wpa_s->scan_interval;
*
* Setter function for "ScanInterval" property.
*/
-dbus_bool_t wpas_dbus_setter_scan_interval(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_setter_scan_interval(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
dbus_int32_t scan_interval;
*
* Getter for "Ifname" property.
*/
-dbus_bool_t wpas_dbus_getter_ifname(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_ifname(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
const char *ifname = wpa_s->ifname;
*
* Getter for "Driver" property.
*/
-dbus_bool_t wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_driver(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
const char *driver;
*
* Getter for "CurrentBSS" property.
*/
-dbus_bool_t wpas_dbus_getter_current_bss(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_current_bss(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
*
* Getter for "CurrentNetwork" property.
*/
-dbus_bool_t wpas_dbus_getter_current_network(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_current_network(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
*
* Getter for "CurrentAuthMode" property.
*/
-dbus_bool_t wpas_dbus_getter_current_auth_mode(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_current_auth_mode(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
const char *eap_mode;
"EAP-%s", eap_mode);
auth_mode = eap_mode_buf;
- } else {
+ } else if (wpa_s->current_ssid) {
auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
wpa_s->current_ssid->proto);
+ } else {
+ auth_mode = "UNKNOWN";
}
return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
*
* Getter for "BridgeIfname" property.
*/
-dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_bridge_ifname(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
const char *bridge_ifname = wpa_s->bridge_ifname;
/**
+ * wpas_dbus_getter_config_file - Get interface configuration file path
+ * @iter: Pointer to incoming dbus message iter
+ * @error: Location to store error on failure
+ * @user_data: Function specific data
+ * Returns: TRUE on success, FALSE on failure
+ *
+ * Getter for "ConfigFile" property.
+ */
+dbus_bool_t wpas_dbus_getter_config_file(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+ char *confname = "";
+
+ if (wpa_s->confname)
+ confname = wpa_s->confname;
+
+ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING,
+ &confname, error);
+}
+
+
+/**
* wpas_dbus_getter_bsss - Get array of BSSs objects
* @iter: Pointer to incoming dbus message iter
* @error: Location to store error on failure
*
* Getter for "BSSs" property.
*/
-dbus_bool_t wpas_dbus_getter_bsss(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_bsss(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
struct wpa_bss *bss;
*
* Getter for "Networks" property.
*/
-dbus_bool_t wpas_dbus_getter_networks(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_networks(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
struct wpa_ssid *ssid;
*
* Getter for "PKCS11EnginePath" property.
*/
-dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
const char *pkcs11_engine_path;
*
* Getter for "PKCS11ModulePath" property.
*/
-dbus_bool_t wpas_dbus_getter_pkcs11_module_path(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_pkcs11_module_path(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
const char *pkcs11_module_path;
*
* Getter for "Blobs" property.
*/
-dbus_bool_t wpas_dbus_getter_blobs(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_blobs(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
DBusMessageIter variant_iter, dict_iter, entry_iter, array_iter;
}
+dbus_bool_t wpas_dbus_getter_iface_global(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+ int ret;
+ char buf[250];
+ char *p = buf;
+
+ if (!property_desc->data) {
+ dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
+ "Unhandled interface property %s",
+ property_desc->dbus_property);
+ return FALSE;
+ }
+
+ ret = wpa_config_get_value(property_desc->data, wpa_s->conf, buf,
+ sizeof(buf));
+ if (ret < 0)
+ *p = '\0';
+
+ return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_STRING, &p,
+ error);
+}
+
+
+dbus_bool_t wpas_dbus_setter_iface_global(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = user_data;
+ const char *new_value = NULL;
+ char buf[250];
+ size_t combined_len;
+ int ret;
+
+ if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING,
+ &new_value))
+ return FALSE;
+
+ combined_len = os_strlen(property_desc->data) + os_strlen(new_value) +
+ 3;
+ if (combined_len >= sizeof(buf)) {
+ dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
+ "Interface property %s value too large",
+ property_desc->dbus_property);
+ return FALSE;
+ }
+
+ if (!new_value[0])
+ new_value = "NULL";
+
+ ret = os_snprintf(buf, combined_len, "%s=%s", property_desc->data,
+ new_value);
+ if (os_snprintf_error(combined_len, ret)) {
+ dbus_set_error(error, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
+ "Failed to construct new interface property %s",
+ property_desc->dbus_property);
+ return FALSE;
+ }
+
+ if (wpa_config_process_global(wpa_s->conf, buf, -1)) {
+ dbus_set_error(error, DBUS_ERROR_INVALID_ARGS,
+ "Failed to set interface property %s",
+ property_desc->dbus_property);
+ return FALSE;
+ }
+
+ wpa_supplicant_update_config(wpa_s);
+ return TRUE;
+}
+
+
static struct wpa_bss * get_bss_helper(struct bss_handler_args *args,
DBusError *error, const char *func_name)
{
*
* Getter for "BSSID" property.
*/
-dbus_bool_t wpas_dbus_getter_bss_bssid(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_bssid(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct bss_handler_args *args = user_data;
struct wpa_bss *res;
*
* Getter for "SSID" property.
*/
-dbus_bool_t wpas_dbus_getter_bss_ssid(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_ssid(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct bss_handler_args *args = user_data;
struct wpa_bss *res;
*
* Getter for "Privacy" property.
*/
-dbus_bool_t wpas_dbus_getter_bss_privacy(DBusMessageIter *iter,
- DBusError *error, void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_privacy(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct bss_handler_args *args = user_data;
struct wpa_bss *res;
*
* Getter for "Mode" property.
*/
-dbus_bool_t wpas_dbus_getter_bss_mode(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_mode(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct bss_handler_args *args = user_data;
struct wpa_bss *res;
*
* Getter for "Level" property.
*/
-dbus_bool_t wpas_dbus_getter_bss_signal(DBusMessageIter *iter,
- DBusError *error, void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_signal(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct bss_handler_args *args = user_data;
struct wpa_bss *res;
*
* Getter for "Frequency" property.
*/
-dbus_bool_t wpas_dbus_getter_bss_frequency(DBusMessageIter *iter,
- DBusError *error, void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_frequency(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct bss_handler_args *args = user_data;
struct wpa_bss *res;
*
* Getter for "Rates" property.
*/
-dbus_bool_t wpas_dbus_getter_bss_rates(DBusMessageIter *iter,
- DBusError *error, void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_rates(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct bss_handler_args *args = user_data;
struct wpa_bss *res;
}
-static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter,
- struct wpa_ie_data *ie_data,
- DBusError *error)
+static dbus_bool_t wpas_dbus_get_bss_security_prop(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, struct wpa_ie_data *ie_data, DBusError *error)
{
DBusMessageIter iter_dict, variant_iter;
const char *group;
*
* Getter for "WPA" property.
*/
-dbus_bool_t wpas_dbus_getter_bss_wpa(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_wpa(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct bss_handler_args *args = user_data;
struct wpa_bss *res;
return FALSE;
}
- return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
+ return wpas_dbus_get_bss_security_prop(property_desc, iter, &wpa_data, error);
}
*
* Getter for "RSN" property.
*/
-dbus_bool_t wpas_dbus_getter_bss_rsn(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_rsn(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct bss_handler_args *args = user_data;
struct wpa_bss *res;
return FALSE;
}
- return wpas_dbus_get_bss_security_prop(iter, &wpa_data, error);
+ return wpas_dbus_get_bss_security_prop(property_desc, iter, &wpa_data, error);
}
*
* Getter for "WPS" property.
*/
-dbus_bool_t wpas_dbus_getter_bss_wps(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_wps(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct bss_handler_args *args = user_data;
struct wpa_bss *res;
*
* Getter for "IEs" property.
*/
-dbus_bool_t wpas_dbus_getter_bss_ies(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_ies(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct bss_handler_args *args = user_data;
struct wpa_bss *res;
*
* Getter for BSS age
*/
-dbus_bool_t wpas_dbus_getter_bss_age(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_bss_age(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct bss_handler_args *args = user_data;
struct wpa_bss *res;
*
* Getter for "enabled" property of a configured network.
*/
-dbus_bool_t wpas_dbus_getter_enabled(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_enabled(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct network_handler_args *net = user_data;
dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
*
* Setter for "Enabled" property of a configured network.
*/
-dbus_bool_t wpas_dbus_setter_enabled(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_setter_enabled(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct network_handler_args *net = user_data;
struct wpa_supplicant *wpa_s;
*
* Getter for "Properties" property of a configured network.
*/
-dbus_bool_t wpas_dbus_getter_network_properties(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_network_properties(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct network_handler_args *net = user_data;
DBusMessageIter variant_iter, dict_iter;
*
* Setter for "Properties" property of a configured network.
*/
-dbus_bool_t wpas_dbus_setter_network_properties(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_setter_network_properties(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct network_handler_args *net = user_data;
struct wpa_ssid *ssid = net->ssid;
}
#endif /* CONFIG_AP */
+
+
+DBusMessage * wpas_dbus_handler_vendor_elem_add(DBusMessage *message,
+ struct wpa_supplicant *wpa_s)
+{
+ u8 *ielems;
+ int len;
+ struct ieee802_11_elems elems;
+ dbus_int32_t frame_id;
+ DBusMessageIter iter, array;
+
+ dbus_message_iter_init(message, &iter);
+ dbus_message_iter_get_basic(&iter, &frame_id);
+ if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
+ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+ "Invalid ID");
+ }
+
+ dbus_message_iter_next(&iter);
+ dbus_message_iter_recurse(&iter, &array);
+ dbus_message_iter_get_fixed_array(&array, &ielems, &len);
+ if (!ielems || len == 0) {
+ return dbus_message_new_error(
+ message, DBUS_ERROR_INVALID_ARGS, "Invalid value");
+ }
+
+ if (ieee802_11_parse_elems(ielems, len, &elems, 0) == ParseFailed) {
+ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+ "Parse error");
+ }
+
+ wpa_s = wpas_vendor_elem(wpa_s, frame_id);
+ if (!wpa_s->vendor_elem[frame_id]) {
+ wpa_s->vendor_elem[frame_id] = wpabuf_alloc_copy(ielems, len);
+ wpas_vendor_elem_update(wpa_s);
+ return NULL;
+ }
+
+ if (wpabuf_resize(&wpa_s->vendor_elem[frame_id], len) < 0) {
+ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+ "Resize error");
+ }
+
+ wpabuf_put_data(wpa_s->vendor_elem[frame_id], ielems, len);
+ wpas_vendor_elem_update(wpa_s);
+ return NULL;
+}
+
+
+DBusMessage * wpas_dbus_handler_vendor_elem_get(DBusMessage *message,
+ struct wpa_supplicant *wpa_s)
+{
+ DBusMessage *reply;
+ DBusMessageIter iter, array_iter;
+ dbus_int32_t frame_id;
+ const u8 *elem;
+ size_t elem_len;
+
+ dbus_message_iter_init(message, &iter);
+ dbus_message_iter_get_basic(&iter, &frame_id);
+
+ if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
+ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+ "Invalid ID");
+ }
+
+ wpa_s = wpas_vendor_elem(wpa_s, frame_id);
+ if (!wpa_s->vendor_elem[frame_id]) {
+ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+ "ID value does not exist");
+ }
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ return wpas_dbus_error_no_memory(message);
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ elem = wpabuf_head_u8(wpa_s->vendor_elem[frame_id]);
+ elem_len = wpabuf_len(wpa_s->vendor_elem[frame_id]);
+
+ if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_BYTE_AS_STRING,
+ &array_iter) ||
+ !dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
+ &elem, elem_len) ||
+ !dbus_message_iter_close_container(&iter, &array_iter)) {
+ dbus_message_unref(reply);
+ reply = wpas_dbus_error_no_memory(message);
+ }
+
+ return reply;
+}
+
+
+DBusMessage * wpas_dbus_handler_vendor_elem_remove(DBusMessage *message,
+ struct wpa_supplicant *wpa_s)
+{
+ u8 *ielems;
+ int len;
+ struct ieee802_11_elems elems;
+ DBusMessageIter iter, array;
+ dbus_int32_t frame_id;
+
+ dbus_message_iter_init(message, &iter);
+ dbus_message_iter_get_basic(&iter, &frame_id);
+ if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
+ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+ "Invalid ID");
+ }
+
+ dbus_message_iter_next(&iter);
+ dbus_message_iter_recurse(&iter, &array);
+ dbus_message_iter_get_fixed_array(&array, &ielems, &len);
+ if (!ielems || len == 0) {
+ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+ "Invalid value");
+ }
+
+ wpa_s = wpas_vendor_elem(wpa_s, frame_id);
+
+ if (len == 1 && *ielems == '*') {
+ wpabuf_free(wpa_s->vendor_elem[frame_id]);
+ wpa_s->vendor_elem[frame_id] = NULL;
+ wpas_vendor_elem_update(wpa_s);
+ return NULL;
+ }
+
+ if (!wpa_s->vendor_elem[frame_id]) {
+ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+ "ID value does not exist");
+ }
+
+ if (ieee802_11_parse_elems(ielems, len, &elems, 0) == ParseFailed) {
+ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+ "Parse error");
+ }
+
+ if (wpas_vendor_elem_remove(wpa_s, frame_id, ielems, len) == 0)
+ return NULL;
+
+ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+ "Not found");
+}
#ifndef CTRL_IFACE_DBUS_NEW_HANDLERS_H
#define CTRL_IFACE_DBUS_NEW_HANDLERS_H
+#include "dbus_new_helpers.h"
+
struct network_handler_args {
struct wpa_supplicant *wpa_s;
struct wpa_ssid *ssid;
DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
struct wpa_global *global);
-dbus_bool_t wpas_dbus_getter_debug_level(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_debug_timestamp(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_debug_show_keys(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_setter_debug_level(DBusMessageIter *iter,
- DBusError *error, void *user_data);
-
-dbus_bool_t wpas_dbus_setter_debug_timestamp(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_setter_debug_show_keys(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_interfaces(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_eap_methods(DBusMessageIter *iter,
- DBusError *error, void *user_data);
-
-dbus_bool_t wpas_dbus_getter_global_capabilities(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
+DBusMessage * wpas_dbus_handler_expect_disconnect(DBusMessage *message,
+ struct wpa_global *global);
+
+DECLARE_ACCESSOR(wpas_dbus_getter_debug_level);
+DECLARE_ACCESSOR(wpas_dbus_getter_debug_timestamp);
+DECLARE_ACCESSOR(wpas_dbus_getter_debug_show_keys);
+DECLARE_ACCESSOR(wpas_dbus_setter_debug_level);
+DECLARE_ACCESSOR(wpas_dbus_setter_debug_timestamp);
+DECLARE_ACCESSOR(wpas_dbus_setter_debug_show_keys);
+DECLARE_ACCESSOR(wpas_dbus_getter_interfaces);
+DECLARE_ACCESSOR(wpas_dbus_getter_eap_methods);
+DECLARE_ACCESSOR(wpas_dbus_getter_global_capabilities);
+DECLARE_ACCESSOR(wpas_dbus_getter_iface_global);
+DECLARE_ACCESSOR(wpas_dbus_setter_iface_global);
DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message,
struct wpa_supplicant *wpa_s);
-dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter,
- DBusError *error, void *user_data);
-
-dbus_bool_t wpas_dbus_getter_state(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_scanning(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_ap_scan(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_setter_ap_scan(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_fast_reauth(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_setter_fast_reauth(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_disconnect_reason(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_bss_expire_age(DBusMessageIter *iter,
- DBusError *error, void *user_data);
-
-dbus_bool_t wpas_dbus_setter_bss_expire_age(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_bss_expire_count(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_setter_bss_expire_count(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_country(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_setter_country(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_scan_interval(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_setter_scan_interval(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_ifname(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_driver(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_bridge_ifname(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_current_bss(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_current_network(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_current_auth_mode(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_bsss(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_networks(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_pkcs11_engine_path(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_pkcs11_module_path(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_blobs(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_bss_bssid(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_bss_ssid(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_bss_privacy(DBusMessageIter *iter,
- DBusError *error, void *user_data);
-
-dbus_bool_t wpas_dbus_getter_bss_mode(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_bss_signal(DBusMessageIter *iter,
- DBusError *error, void *user_data);
-
-dbus_bool_t wpas_dbus_getter_bss_frequency(DBusMessageIter *iter,
- DBusError *error, void *user_data);
-
-dbus_bool_t wpas_dbus_getter_bss_rates(DBusMessageIter *iter,
- DBusError *error, void *user_data);
-
-dbus_bool_t wpas_dbus_getter_bss_wpa(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_bss_rsn(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_bss_wps(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_bss_ies(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_bss_age(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_enabled(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_setter_enabled(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_network_properties(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_setter_network_properties(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
+DECLARE_ACCESSOR(wpas_dbus_getter_capabilities);
+DECLARE_ACCESSOR(wpas_dbus_getter_state);
+DECLARE_ACCESSOR(wpas_dbus_getter_scanning);
+DECLARE_ACCESSOR(wpas_dbus_getter_ap_scan);
+DECLARE_ACCESSOR(wpas_dbus_setter_ap_scan);
+DECLARE_ACCESSOR(wpas_dbus_getter_fast_reauth);
+DECLARE_ACCESSOR(wpas_dbus_setter_fast_reauth);
+DECLARE_ACCESSOR(wpas_dbus_getter_disconnect_reason);
+DECLARE_ACCESSOR(wpas_dbus_getter_disassociate_reason);
+DECLARE_ACCESSOR(wpas_dbus_getter_assoc_status_code);
+DECLARE_ACCESSOR(wpas_dbus_getter_bss_expire_age);
+DECLARE_ACCESSOR(wpas_dbus_setter_bss_expire_age);
+DECLARE_ACCESSOR(wpas_dbus_getter_bss_expire_count);
+DECLARE_ACCESSOR(wpas_dbus_setter_bss_expire_count);
+DECLARE_ACCESSOR(wpas_dbus_getter_country);
+DECLARE_ACCESSOR(wpas_dbus_setter_country);
+DECLARE_ACCESSOR(wpas_dbus_getter_scan_interval);
+DECLARE_ACCESSOR(wpas_dbus_setter_scan_interval);
+DECLARE_ACCESSOR(wpas_dbus_getter_ifname);
+DECLARE_ACCESSOR(wpas_dbus_getter_driver);
+DECLARE_ACCESSOR(wpas_dbus_getter_bridge_ifname);
+DECLARE_ACCESSOR(wpas_dbus_getter_config_file);
+DECLARE_ACCESSOR(wpas_dbus_getter_current_bss);
+DECLARE_ACCESSOR(wpas_dbus_getter_current_network);
+DECLARE_ACCESSOR(wpas_dbus_getter_current_auth_mode);
+DECLARE_ACCESSOR(wpas_dbus_getter_bsss);
+DECLARE_ACCESSOR(wpas_dbus_getter_networks);
+DECLARE_ACCESSOR(wpas_dbus_getter_pkcs11_engine_path);
+DECLARE_ACCESSOR(wpas_dbus_getter_pkcs11_module_path);
+DECLARE_ACCESSOR(wpas_dbus_getter_blobs);
+DECLARE_ACCESSOR(wpas_dbus_getter_bss_bssid);
+DECLARE_ACCESSOR(wpas_dbus_getter_bss_ssid);
+DECLARE_ACCESSOR(wpas_dbus_getter_bss_privacy);
+DECLARE_ACCESSOR(wpas_dbus_getter_bss_mode);
+DECLARE_ACCESSOR(wpas_dbus_getter_bss_signal);
+DECLARE_ACCESSOR(wpas_dbus_getter_bss_frequency);
+DECLARE_ACCESSOR(wpas_dbus_getter_bss_rates);
+DECLARE_ACCESSOR(wpas_dbus_getter_bss_wpa);
+DECLARE_ACCESSOR(wpas_dbus_getter_bss_rsn);
+DECLARE_ACCESSOR(wpas_dbus_getter_bss_wps);
+DECLARE_ACCESSOR(wpas_dbus_getter_bss_ies);
+DECLARE_ACCESSOR(wpas_dbus_getter_bss_age);
+DECLARE_ACCESSOR(wpas_dbus_getter_enabled);
+DECLARE_ACCESSOR(wpas_dbus_setter_enabled);
+DECLARE_ACCESSOR(wpas_dbus_getter_network_properties);
+DECLARE_ACCESSOR(wpas_dbus_setter_network_properties);
DBusMessage * wpas_dbus_handler_wps_start(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_wps_cancel(DBusMessage *message,
struct wpa_supplicant *wpa_s);
-dbus_bool_t wpas_dbus_getter_process_credentials(DBusMessageIter *iter,
- DBusError *error, void *user_data);
-
-dbus_bool_t wpas_dbus_setter_process_credentials(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_config_methods(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_setter_config_methods(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
+DECLARE_ACCESSOR(wpas_dbus_getter_process_credentials);
+DECLARE_ACCESSOR(wpas_dbus_setter_process_credentials);
+DECLARE_ACCESSOR(wpas_dbus_getter_config_methods);
+DECLARE_ACCESSOR(wpas_dbus_setter_config_methods);
DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message,
struct wpa_supplicant *wpa_s);
DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
struct wpa_supplicant *wpa_s);
+DBusMessage * wpas_dbus_handler_vendor_elem_add(DBusMessage *message,
+ struct wpa_supplicant *wpa_s);
+DBusMessage * wpas_dbus_handler_vendor_elem_get(DBusMessage *message,
+ struct wpa_supplicant *wpa_s);
+DBusMessage * wpas_dbus_handler_vendor_elem_remove(
+ DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_handler_save_config(DBusMessage *message,
+ struct wpa_supplicant *wpa_s);
+
DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
const char *arg);
DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
goto inv_args;
if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0,
- NULL, 0, 0)) {
+ 0, 0, NULL, 0, 0)) {
reply = wpas_dbus_error_unknown_error(
message,
"Failed to reinvoke a persistent group");
goto out;
}
- } else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0))
+ } else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0, 0,
+ 0))
goto inv_args;
out:
new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
persistent_group, 0, join, authorize_only,
- go_intent, freq, -1, 0, 0, 0);
+ go_intent, freq, 0, -1, 0, 0, 0, 0, NULL, 0);
if (new_pin >= 0) {
char npin[9];
if (ssid == NULL || ssid->disabled != 2)
goto err;
- if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0) <
- 0) {
+ if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0, 0,
+ 0) < 0) {
reply = wpas_dbus_error_unknown_error(
message,
"Failed to reinvoke a persistent group");
* P2P Device property accessor methods.
*/
-dbus_bool_t wpas_dbus_getter_p2p_device_config(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_device_config(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
DBusMessageIter variant_iter, dict_iter;
}
-dbus_bool_t wpas_dbus_setter_p2p_device_config(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_setter_p2p_device_config(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
DBusMessageIter variant_iter, iter_dict;
if (os_strcmp(entry.key, "DeviceName") == 0) {
char *devname;
- if (entry.type != DBUS_TYPE_STRING)
+ if (entry.type != DBUS_TYPE_STRING ||
+ os_strlen(entry.str_value) > WPS_DEV_NAME_MAX_LEN)
goto error;
devname = os_strdup(entry.str_value);
}
-dbus_bool_t wpas_dbus_getter_p2p_peers(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_peers(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
struct p2p_data *p2p = wpa_s->global->p2p;
}
-dbus_bool_t wpas_dbus_getter_p2p_role(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_role(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
char *str;
}
-dbus_bool_t wpas_dbus_getter_p2p_group(DBusMessageIter *iter, DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_group(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
char path_buf[WPAS_DBUS_OBJECT_PATH_MAX];
}
-dbus_bool_t wpas_dbus_getter_p2p_peergo(DBusMessageIter *iter,
- DBusError *error, void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_peergo(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
char go_peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
* Peer object properties accessor methods
*/
-dbus_bool_t wpas_dbus_getter_p2p_peer_device_name(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_peer_device_name(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct peer_handler_args *peer_args = user_data;
const struct p2p_peer_info *info;
}
-dbus_bool_t wpas_dbus_getter_p2p_peer_manufacturer(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_peer_manufacturer(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct peer_handler_args *peer_args = user_data;
const struct p2p_peer_info *info;
}
-dbus_bool_t wpas_dbus_getter_p2p_peer_modelname(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_peer_modelname(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct peer_handler_args *peer_args = user_data;
const struct p2p_peer_info *info;
}
-dbus_bool_t wpas_dbus_getter_p2p_peer_modelnumber(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_peer_modelnumber(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct peer_handler_args *peer_args = user_data;
const struct p2p_peer_info *info;
}
-dbus_bool_t wpas_dbus_getter_p2p_peer_serialnumber(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_peer_serialnumber(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct peer_handler_args *peer_args = user_data;
const struct p2p_peer_info *info;
dbus_bool_t wpas_dbus_getter_p2p_peer_primary_device_type(
+ const struct wpa_dbus_property_desc *property_desc,
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct peer_handler_args *peer_args = user_data;
}
-dbus_bool_t wpas_dbus_getter_p2p_peer_config_method(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_peer_config_method(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct peer_handler_args *peer_args = user_data;
const struct p2p_peer_info *info;
}
-dbus_bool_t wpas_dbus_getter_p2p_peer_level(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_peer_level(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct peer_handler_args *peer_args = user_data;
const struct p2p_peer_info *info;
}
-dbus_bool_t wpas_dbus_getter_p2p_peer_device_capability(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_peer_device_capability(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct peer_handler_args *peer_args = user_data;
const struct p2p_peer_info *info;
}
-dbus_bool_t wpas_dbus_getter_p2p_peer_group_capability(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_peer_group_capability(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct peer_handler_args *peer_args = user_data;
const struct p2p_peer_info *info;
dbus_bool_t wpas_dbus_getter_p2p_peer_secondary_device_types(
+ const struct wpa_dbus_property_desc *property_desc,
DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct peer_handler_args *peer_args = user_data;
}
-dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
unsigned int i, num = 0;
}
-dbus_bool_t wpas_dbus_getter_p2p_peer_ies(DBusMessageIter *iter,
- DBusError *error, void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_peer_ies(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct peer_handler_args *peer_args = user_data;
const struct p2p_peer_info *info;
}
-dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct peer_handler_args *peer_args = user_data;
const struct p2p_peer_info *info;
}
-dbus_bool_t wpas_dbus_getter_p2p_peer_groups(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_peer_groups(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct peer_handler_args *peer_args = user_data;
const struct p2p_peer_info *info;
*
* Getter for "PersistentGroups" property.
*/
-dbus_bool_t wpas_dbus_getter_persistent_groups(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_persistent_groups(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
struct wpa_ssid *ssid;
*
* Getter for "Properties" property of a persistent group.
*/
-dbus_bool_t wpas_dbus_getter_persistent_group_properties(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_persistent_group_properties(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct network_handler_args *net = user_data;
/* Leveraging the fact that persistent group object is still
* represented in same manner as network within.
*/
- return wpas_dbus_getter_network_properties(iter, error, net);
+ return wpas_dbus_getter_network_properties(property_desc, iter, error, net);
}
*
* Setter for "Properties" property of a persistent group.
*/
-dbus_bool_t wpas_dbus_setter_persistent_group_properties(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_setter_persistent_group_properties(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct network_handler_args *net = user_data;
struct wpa_ssid *ssid = net->ssid;
* Group object properties accessor methods
*/
-dbus_bool_t wpas_dbus_getter_p2p_group_members(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_group_members(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
struct wpa_ssid *ssid;
}
-dbus_bool_t wpas_dbus_getter_p2p_group_ssid(DBusMessageIter *iter,
- DBusError *error, void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_group_ssid(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
}
-dbus_bool_t wpas_dbus_getter_p2p_group_bssid(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_group_bssid(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
u8 role = wpas_get_p2p_role(wpa_s);
}
-dbus_bool_t wpas_dbus_getter_p2p_group_frequency(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_group_frequency(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
u16 op_freq;
}
-dbus_bool_t wpas_dbus_getter_p2p_group_passphrase(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_group_passphrase(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
char *p_pass;
}
-dbus_bool_t wpas_dbus_getter_p2p_group_psk(DBusMessageIter *iter,
- DBusError *error, void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_group_psk(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
u8 *p_psk = NULL;
}
-dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
struct hostapd_data *hapd;
}
-dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
DBusMessageIter variant_iter, iter_dict, array_iter, sub;
#ifdef CONFIG_WIFI_DISPLAY
-dbus_bool_t wpas_dbus_getter_global_wfd_ies(DBusMessageIter *iter,
- DBusError *error, void *user_data)
+dbus_bool_t wpas_dbus_getter_global_wfd_ies(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_global *global = user_data;
struct wpabuf *ie;
}
-dbus_bool_t wpas_dbus_setter_global_wfd_ies(DBusMessageIter *iter,
- DBusError *error, void *user_data)
+dbus_bool_t wpas_dbus_setter_global_wfd_ies(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_global *global = user_data;
DBusMessageIter variant, array;
/*
* P2P Device property accessor methods.
*/
-dbus_bool_t wpas_dbus_setter_p2p_device_config(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_device_config(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_peers(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_role(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_group(DBusMessageIter *iter, DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_peergo(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
+DECLARE_ACCESSOR(wpas_dbus_setter_p2p_device_config);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_device_config);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peers);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_role);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peergo);
/*
* P2P Peer properties.
*/
-
-dbus_bool_t wpas_dbus_getter_p2p_peer_device_name(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_peer_manufacturer(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_peer_modelname(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_peer_modelnumber(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_peer_serialnumber(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_peer_primary_device_type(
- DBusMessageIter *iter, DBusError *error, void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_peer_config_method(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_peer_level(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_peer_device_capability(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_peer_group_capability(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_peer_secondary_device_types(
- DBusMessageIter *iter, DBusError *error, void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_peer_vendor_extension(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_peer_ies(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_peer_device_address(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_peer_groups(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_device_name);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_manufacturer);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_modelname);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_modelnumber);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_serialnumber);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_primary_device_type);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_config_method);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_level);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_device_capability);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_group_capability);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_secondary_device_types);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_vendor_extension);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_ies);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_device_address);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_peer_groups);
/*
* P2P Group properties
*/
-
-dbus_bool_t wpas_dbus_getter_p2p_group_members(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_group_ssid(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_group_bssid(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_group_frequency(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_group_passphrase(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_group_psk(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_p2p_group_vendor_ext(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_setter_p2p_group_vendor_ext(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group_members);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group_ssid);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group_bssid);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group_frequency);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group_passphrase);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group_psk);
+DECLARE_ACCESSOR(wpas_dbus_getter_p2p_group_vendor_ext);
+DECLARE_ACCESSOR(wpas_dbus_setter_p2p_group_vendor_ext);
/*
* P2P Persistent Groups and properties
*/
-
-dbus_bool_t wpas_dbus_getter_persistent_groups(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_getter_persistent_group_properties(DBusMessageIter *iter,
- DBusError *error, void *user_data);
-
-dbus_bool_t wpas_dbus_setter_persistent_group_properties(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
+DECLARE_ACCESSOR(wpas_dbus_getter_persistent_groups);
+DECLARE_ACCESSOR(wpas_dbus_getter_persistent_group_properties);
+DECLARE_ACCESSOR(wpas_dbus_setter_persistent_group_properties);
DBusMessage * wpas_dbus_handler_add_persistent_group(
DBusMessage *message, struct wpa_supplicant *wpa_s);
DBusMessage *message, struct wpa_supplicant *wpa_s);
#ifdef CONFIG_WIFI_DISPLAY
-
-dbus_bool_t wpas_dbus_getter_global_wfd_ies(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
-dbus_bool_t wpas_dbus_setter_global_wfd_ies(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
-
+DECLARE_ACCESSOR(wpas_dbus_getter_global_wfd_ies);
+DECLARE_ACCESSOR(wpas_dbus_setter_global_wfd_ies);
#endif /* CONFIG_WIFI_DISPLAY */
#endif /* DBUS_NEW_HANDLERS_P2P_H */
* @wpa_s: %wpa_supplicant data structure
* Returns: NULL on success or DBus error on failure
*
- * Handler for "Cancel" method call. Returns NULL if WPS cancel successfull
+ * Handler for "Cancel" method call. Returns NULL if WPS cancel successful
* or DBus error on WPS cancel failure
*/
DBusMessage * wpas_dbus_handler_wps_cancel(DBusMessage *message,
* true if wps_cred_processing configuration field is not equal to 1 or false
* if otherwise.
*/
-dbus_bool_t wpas_dbus_getter_process_credentials(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_process_credentials(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
dbus_bool_t process = wpa_s->conf->wps_cred_processing != 1;
* Setter for "ProcessCredentials" property. Sets credentials_processed on 2
* if boolean argument is true or on 1 if otherwise.
*/
-dbus_bool_t wpas_dbus_setter_process_credentials(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_setter_process_credentials(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
dbus_bool_t process_credentials, old_pc;
* Getter for "ConfigMethods" property. Returned boolean will be true if
* providing the relevant string worked, or false otherwise.
*/
-dbus_bool_t wpas_dbus_getter_config_methods(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_getter_config_methods(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
char *methods = wpa_s->conf->config_methods;
* Setter for "ConfigMethods" property. Sets the methods string, apply such
* change and returns true on success. Returns false otherwise.
*/
-dbus_bool_t wpas_dbus_setter_config_methods(DBusMessageIter *iter,
- DBusError *error,
- void *user_data)
+dbus_bool_t wpas_dbus_setter_config_methods(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data)
{
struct wpa_supplicant *wpa_s = user_data;
char *methods, *new_methods;
goto error;
/* An error getting a property fails the request entirely */
- if (!dsc->getter(&entry_iter, error, user_data)) {
+ if (!dsc->getter(dsc, &entry_iter, error, user_data)) {
wpa_printf(MSG_INFO,
"dbus: %s dbus_interface=%s dbus_property=%s getter failed",
__func__, dsc->dbus_interface,
dbus_message_iter_init_append(reply, &iter);
dbus_error_init(&error);
- if (dsc->getter(&iter, &error, user_data) == FALSE) {
+ if (dsc->getter(dsc, &iter, &error, user_data) == FALSE) {
dbus_message_unref(reply);
reply = wpas_dbus_reply_new_from_error(
message, &error, DBUS_ERROR_FAILED,
/* Iter will now point to the property's new value */
dbus_error_init(&error);
- if (dsc->setter(&iter, &error, user_data) == TRUE) {
+ if (dsc->setter(dsc, &iter, &error, user_data) == TRUE) {
/* Success */
reply = dbus_message_new_method_return(message);
} else {
return FALSE;
dbus_error_init(&error);
- if (!dsc->getter(&entry_iter, &error, obj_dsc->user_data)) {
+ if (!dsc->getter(dsc, &entry_iter, &error, obj_dsc->user_data))
+ {
if (dbus_error_is_set(&error)) {
wpa_printf(MSG_ERROR,
"dbus: %s: Cannot get new value of property %s: (%s) %s",
void *user_data);
typedef void (*WPADBusArgumentFreeFunction)(void *handler_arg);
-typedef dbus_bool_t (*WPADBusPropertyAccessor)(DBusMessageIter *iter,
- DBusError *error,
- void *user_data);
+struct wpa_dbus_property_desc;
+typedef dbus_bool_t (*WPADBusPropertyAccessor)(
+ const struct wpa_dbus_property_desc *property_desc,
+ DBusMessageIter *iter, DBusError *error, void *user_data);
+#define DECLARE_ACCESSOR(f) \
+dbus_bool_t f(const struct wpa_dbus_property_desc *property_desc, \
+ DBusMessageIter *iter, DBusError *error, void *user_data)
struct wpa_dbus_object_desc {
DBusConnection *connection;
WPADBusPropertyAccessor getter;
/* property setter function */
WPADBusPropertyAccessor setter;
+ /* other data */
+ const char *data;
};
if (!iface)
return NULL;
iface->dbus_interface = os_strdup(dbus_interface);
- iface->xml = wpabuf_alloc(6000);
+ iface->xml = wpabuf_alloc(15000);
if (iface->dbus_interface == NULL || iface->xml == NULL) {
os_free(iface->dbus_interface);
wpabuf_free(iface->xml);
DBusMessage *reply;
struct wpabuf *xml;
- xml = wpabuf_alloc(15000);
+ xml = wpabuf_alloc(20000);
if (xml == NULL)
return NULL;
char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
if (wpa_s->dbus_path)
- ssid = wpa_config_add_network(wpa_s->conf);
+ ssid = wpa_supplicant_add_network(wpa_s);
if (ssid == NULL) {
reply = dbus_message_new_error(
message, WPAS_ERROR_ADD_NETWORK_ERROR,
"wpa_supplicant could not add a network on this interface.");
goto out;
}
- wpas_notify_network_added(wpa_s, ssid);
- ssid->disabled = 1;
- wpa_config_set_network_defaults(ssid);
/* Construct the object path for this network. */
os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
const char *op;
char *iface = NULL, *net_id = NULL;
int id;
- struct wpa_ssid *ssid;
+ int result;
if (!dbus_message_get_args(message, NULL,
DBUS_TYPE_OBJECT_PATH, &op,
}
id = strtoul(net_id, NULL, 10);
- ssid = wpa_config_get_network(wpa_s->conf, id);
- if (ssid == NULL) {
+ result = wpa_supplicant_remove_network(wpa_s, id);
+ if (result == -1) {
reply = wpas_dbus_new_invalid_network_error(message);
goto out;
}
-
- wpas_notify_network_removed(wpa_s, ssid);
-
- if (ssid == wpa_s->current_ssid)
- wpa_supplicant_deauthenticate(wpa_s,
- WLAN_REASON_DEAUTH_LEAVING);
-
- if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
+ if (result == -2) {
reply = dbus_message_new_error(
message, WPAS_ERROR_REMOVE_NETWORK_ERROR,
"error removing the specified on this interface.");
DBusMessage * wpas_dbus_iface_disconnect(DBusMessage *message,
struct wpa_supplicant *wpa_s)
{
- wpa_s->disconnected = 1;
- wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+ wpas_request_disconnection(wpa_s);
return wpas_dbus_new_success_reply(message);
}
# Driver interface for Linux drivers using the nl80211 kernel interface
CONFIG_DRIVER_NL80211=y
+# QCA vendor extensions to nl80211
+#CONFIG_DRIVER_NL80211_QCA=y
+
# driver_nl80211.c requires libnl. If you are compiling it yourself
# you may need to point hostapd to your version of libnl.
#
# Should we use epoll instead of select? Select is used by default.
#CONFIG_ELOOP_EPOLL=y
+# Should we use kqueue instead of select? Select is used by default.
+#CONFIG_ELOOP_KQUEUE=y
+
# Select layer 2 packet implementation
# linux = Linux packet socket (default)
# pcap = libpcap/libdnet/WinPcap
# none = Empty template
#CONFIG_L2_PACKET=linux
+# Disable Linux packet socket workaround applicable for station interface
+# in a bridge for EAPOL frames. This should be uncommented only if the kernel
+# is known to not have the regression issue in packet socket behavior with
+# bridge interfaces (commit 'bridge: respect RFC2863 operational state')').
+#CONFIG_NO_LINUX_PACKET_SOCKET_WAR=y
+
# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
CONFIG_PEERKEY=y
# Hotspot 2.0
#CONFIG_HS20=y
+# Enable interface matching in wpa_supplicant
+#CONFIG_MATCH_IFACE=y
+
# Disable roaming in wpa_supplicant
#CONFIG_NO_ROAMING=y
# OS X builds. This is only for building eapol_test.
#CONFIG_OSX=y
+
+# Automatic Channel Selection
+# This will allow wpa_supplicant to pick the channel automatically when channel
+# is set to "0".
+#
+# TODO: Extend parser to be able to parse "channel=acs_survey" as an alternative
+# to "channel=0". This would enable us to eventually add other ACS algorithms in
+# similar way.
+#
+# Automatic selection is currently only done through initialization, later on
+# we hope to do background checks to keep us moving to more ideal channels as
+# time goes by. ACS is currently only supported through the nl80211 driver and
+# your driver must have survey dump capability that is filled by the driver
+# during scanning.
+#
+# TODO: In analogy to hostapd be able to customize the ACS survey algorithm with
+# a newly to create wpa_supplicant.conf variable acs_num_scans.
+#
+# Supported ACS drivers:
+# * ath9k
+# * ath5k
+# * ath10k
+#
+# For more details refer to:
+# http://wireless.kernel.org/en/users/Documentation/acs
+#CONFIG_ACS=y
+
+# Support Multi Band Operation
+#CONFIG_MBO=y
</refsect1>
<refsect1>
<title>Legal</title>
- <para>wpa_supplicant is copyright (c) 2003-2015,
+ <para>wpa_supplicant is copyright (c) 2003-2016,
Jouni Malinen <email>j@w1.fi</email> and
contributors.
All Rights Reserved.</para>
<refsect1>
<title>Legal</title>
- <para>wpa_supplicant is copyright (c) 2003-2015,
+ <para>wpa_supplicant is copyright (c) 2003-2016,
Jouni Malinen <email>j@w1.fi</email> and
contributors.
All Rights Reserved.</para>
</refsect1>
<refsect1>
<title>Legal</title>
- <para>wpa_supplicant is copyright (c) 2003-2015,
+ <para>wpa_supplicant is copyright (c) 2003-2016,
Jouni Malinen <email>j@w1.fi</email> and
contributors.
All Rights Reserved.</para>
</refsect1>
<refsect1>
<title>Legal</title>
- <para>wpa_supplicant is copyright (c) 2003-2015,
+ <para>wpa_supplicant is copyright (c) 2003-2016,
Jouni Malinen <email>j@w1.fi</email> and
contributors.
All Rights Reserved.</para>
</refsect1>
<refsect1>
<title>Legal</title>
- <para>wpa_supplicant is copyright (c) 2003-2015,
+ <para>wpa_supplicant is copyright (c) 2003-2016,
Jouni Malinen <email>j@w1.fi</email> and
contributors.
All Rights Reserved.</para>
</refsect1>
<refsect1>
<title>Legal</title>
- <para>wpa_supplicant is copyright (c) 2003-2015,
+ <para>wpa_supplicant is copyright (c) 2003-2016,
Jouni Malinen <email>j@w1.fi</email> and
contributors.
All Rights Reserved.</para>
</varlistentry>
<varlistentry>
- <term>-t</term>
- <listitem>
- <para>Include timestamp in debug messages.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
<term>-h</term>
<listitem>
<para>Help. Show a usage message.</para>
</refsect1>
<refsect1>
<title>Legal</title>
- <para>wpa_supplicant is copyright (c) 2003-2015,
+ <para>wpa_supplicant is copyright (c) 2003-2016,
Jouni Malinen <email>j@w1.fi</email> and
contributors.
All Rights Reserved.</para>
}
static inline int wpa_drv_sched_scan(struct wpa_supplicant *wpa_s,
- struct wpa_driver_scan_params *params,
- u32 interval)
+ struct wpa_driver_scan_params *params)
{
if (wpa_s->driver->sched_scan)
- return wpa_s->driver->sched_scan(wpa_s->drv_priv,
- params, interval);
+ return wpa_s->driver->sched_scan(wpa_s->drv_priv, params);
return -1;
}
return -1;
}
+static inline int wpa_drv_get_seqnum(struct wpa_supplicant *wpa_s,
+ const u8 *addr, int idx, u8 *seq)
+{
+ if (wpa_s->driver->get_seqnum)
+ return wpa_s->driver->get_seqnum(wpa_s->ifname, wpa_s->drv_priv,
+ addr, idx, seq);
+ return -1;
+}
+
static inline int wpa_drv_sta_deauth(struct wpa_supplicant *wpa_s,
const u8 *addr, int reason_code)
{
if (wpa_s->driver->send_mlme)
return wpa_s->driver->send_mlme(wpa_s->drv_priv,
data, data_len, noack,
- freq);
+ freq, NULL, 0);
return -1;
}
if (wpa_s->driver->if_add)
return wpa_s->driver->if_add(wpa_s->drv_priv, type, ifname,
addr, bss_ctx, NULL, force_ifname,
- if_addr, bridge, 0);
+ if_addr, bridge, 0, 0);
return -1;
}
}
static inline int wpa_drv_set_current_cipher_suite(struct wpa_supplicant *wpa_s,
- const u8 *cs, size_t cs_len)
+ u64 cs)
{
if (!wpa_s->driver->set_current_cipher_suite)
return -1;
- return wpa_s->driver->set_current_cipher_suite(wpa_s->drv_priv, cs,
- cs_len);
+ return wpa_s->driver->set_current_cipher_suite(wpa_s->drv_priv, cs);
}
static inline int wpa_drv_enable_controlled_port(struct wpa_supplicant *wpa_s,
return wpa_s->driver->set_prob_oper_freq(wpa_s->drv_priv, freq);
}
+static inline int wpa_drv_abort_scan(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s->driver->abort_scan)
+ return -1;
+ return wpa_s->driver->abort_scan(wpa_s->drv_priv);
+}
+
+static inline int wpa_drv_configure_frame_filters(struct wpa_supplicant *wpa_s,
+ u32 filters)
+{
+ if (!wpa_s->driver->configure_data_frame_filters)
+ return -1;
+ return wpa_s->driver->configure_data_frame_filters(wpa_s->drv_priv,
+ filters);
+}
+
+static inline int wpa_drv_get_ext_capa(struct wpa_supplicant *wpa_s,
+ enum wpa_driver_if_type type)
+{
+ if (!wpa_s->driver->get_ext_capab)
+ return -1;
+ return wpa_s->driver->get_ext_capab(wpa_s->drv_priv, type,
+ &wpa_s->extended_capa,
+ &wpa_s->extended_capa_mask,
+ &wpa_s->extended_capa_len);
+}
+
+static inline int wpa_drv_p2p_lo_start(struct wpa_supplicant *wpa_s,
+ unsigned int channel,
+ 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)
+{
+ if (!wpa_s->driver->p2p_lo_start)
+ return -1;
+ return wpa_s->driver->p2p_lo_start(wpa_s->drv_priv, channel, period,
+ interval, count, device_types,
+ dev_types_len, ies, ies_len);
+}
+
+static inline int wpa_drv_p2p_lo_stop(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s->driver->p2p_lo_stop)
+ return -1;
+ return wpa_s->driver->p2p_lo_stop(wpa_s->drv_priv);
+}
+
+static inline int wpa_drv_set_default_scan_ies(struct wpa_supplicant *wpa_s,
+ const u8 *ies, size_t len)
+{
+ if (!wpa_s->driver->set_default_scan_ies)
+ return -1;
+ return wpa_s->driver->set_default_scan_ies(wpa_s->drv_priv, ies, len);
+}
+
#endif /* DRIVER_I_H */
#include "common.h"
#include "utils/ext_password.h"
+#include "common/version.h"
#include "config.h"
#include "eapol_supp/eapol_supp_sm.h"
#include "eap_peer/eap.h"
return;
}
- radius_msg_make_authenticator(msg, (u8 *) e, sizeof(*e));
+ radius_msg_make_authenticator(msg);
hdr = (const struct eap_hdr *) eap;
pos = (const u8 *) (hdr + 1);
goto fail;
}
+ if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_SERVICE_TYPE) &&
+ !radius_msg_add_attr_int32(msg, RADIUS_ATTR_SERVICE_TYPE,
+ RADIUS_SERVICE_TYPE_FRAMED)) {
+ printf("Could not add Service-Type\n");
+ goto fail;
+ }
+
os_snprintf(buf, sizeof(buf), "%s", e->connect_info);
if (!find_extra_attr(e->extra_attrs, RADIUS_ATTR_CONNECT_INFO) &&
!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO,
static void usage(void)
{
printf("usage:\n"
- "eapol_test [-enWS] -c<conf> [-a<AS IP>] [-p<AS port>] "
+ "eapol_test [-enWSv] -c<conf> [-a<AS IP>] [-p<AS port>] "
"[-s<AS secret>]\\\n"
" [-r<count>] [-t<timeout>] [-C<Connect-Info>] \\\n"
" [-M<client MAC address>] [-o<server cert file] \\\n"
" -W = wait for a control interface monitor before starting\n"
" -S = save configuration after authentication\n"
" -n = no MPPE keys expected\n"
+ " -v = show version\n"
" -t<timeout> = sets timeout in seconds (default: 30 s)\n"
" -C<Connect-Info> = RADIUS Connect-Info (default: "
"CONNECT 11Mbps 802.11b)\n"
wpa_debug_show_keys = 1;
for (;;) {
- c = getopt(argc, argv, "a:A:c:C:ei:M:nN:o:p:P:r:R:s:St:T:W");
+ c = getopt(argc, argv, "a:A:c:C:ei:M:nN:o:p:P:r:R:s:St:T:vW");
if (c < 0)
break;
switch (c) {
ctrl_iface = optarg;
eapol_test.ctrl_iface = 1;
break;
+ case 'v':
+ printf("eapol_test v" VERSION_STR "\n");
+ return 0;
case 'W':
wait_for_monitor++;
break;
}
+#ifndef CONFIG_NO_SCAN_PROCESSING
/**
* wpas_reenabled_network_time - Time until first network is re-enabled
* @wpa_s: Pointer to wpa_supplicant data
return res;
}
+#endif /* CONFIG_NO_SCAN_PROCESSING */
void wpas_network_reenabled(void *eloop_ctx, void *timeout_ctx)
wpa_supplicant_ap_deinit(wpa_s);
#endif /* CONFIG_AP */
+#ifdef CONFIG_HS20
+ /* Clear possibly configured frame filters */
+ wpa_drv_configure_frame_filters(wpa_s, 0);
+#endif /* CONFIG_HS20 */
+
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
return;
wpa_s->key_mgmt = 0;
wpas_rrm_reset(wpa_s);
+ wpa_s->wnmsleep_used = 0;
}
break;
}
#endif /* CONFIG_IEEE80211W */
+ if ((ie.capabilities & WPA_CAPABILITY_MFPR) &&
+ wpas_get_ssid_pmf(wpa_s, ssid) ==
+ NO_MGMT_FRAME_PROTECTION) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip RSN IE - no mgmt frame protection enabled but AP requires it");
+ break;
+ }
+#ifdef CONFIG_MBO
+ if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
+ wpas_mbo_get_bss_attr(bss, MBO_ATTR_ID_AP_CAPA_IND) &&
+ wpas_get_ssid_pmf(wpa_s, ssid) !=
+ NO_MGMT_FRAME_PROTECTION) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip RSN IE - no mgmt frame protection enabled on MBO AP");
+ break;
+ }
+#endif /* CONFIG_MBO */
wpa_dbg(wpa_s, MSG_DEBUG, " selected based on RSN IE");
return 1;
}
+#ifdef CONFIG_IEEE80211W
+ if (wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - MFP Required but network not MFP Capable");
+ return 0;
+ }
+#endif /* CONFIG_IEEE80211W */
+
wpa_ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
while ((ssid->proto & WPA_PROTO_WPA) && wpa_ie) {
proto_match++;
}
-static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
- int i, struct wpa_bss *bss,
- struct wpa_ssid *group,
- int only_first_ssid)
+struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
+ int i, struct wpa_bss *bss,
+ struct wpa_ssid *group,
+ int only_first_ssid)
{
u8 wpa_ie_len, rsn_ie_len;
int wpa;
const u8 *ie;
struct wpa_ssid *ssid;
int osen;
+#ifdef CONFIG_MBO
+ const u8 *assoc_disallow;
+#endif /* CONFIG_MBO */
ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
wpa_ie_len = ie ? ie[1] : 0;
continue;
}
- if (!bss_is_ess(bss)) {
- wpa_dbg(wpa_s, MSG_DEBUG, " skip - not ESS network");
+ if (ssid->mode != IEEE80211_MODE_MESH && !bss_is_ess(bss) &&
+ !bss_is_pbss(bss)) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - not ESS, PBSS, or MBSS");
+ continue;
+ }
+
+ if (ssid->pbss != 2 && ssid->pbss != bss_is_pbss(bss)) {
+ wpa_dbg(wpa_s, MSG_DEBUG, " skip - PBSS mismatch (ssid %d bss %d)",
+ ssid->pbss, bss_is_pbss(bss));
continue;
}
continue;
}
+#ifdef CONFIG_MESH
+ if (ssid->mode == IEEE80211_MODE_MESH && ssid->frequency > 0 &&
+ ssid->frequency != bss->freq) {
+ wpa_dbg(wpa_s, MSG_DEBUG, " skip - frequency not allowed (mesh)");
+ continue;
+ }
+#endif /* CONFIG_MESH */
+
if (!rate_match(wpa_s, bss)) {
wpa_dbg(wpa_s, MSG_DEBUG, " skip - rate sets do "
"not match");
(unsigned int) diff.usec);
continue;
}
+#ifdef CONFIG_MBO
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->ignore_assoc_disallow)
+ goto skip_assoc_disallow;
+#endif /* CONFIG_TESTING_OPTIONS */
+ assoc_disallow = wpas_mbo_get_bss_attr(
+ bss, MBO_ATTR_ID_ASSOC_DISALLOW);
+ if (assoc_disallow && assoc_disallow[1] >= 1) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - MBO association disallowed (reason %u)",
+ assoc_disallow[2]);
+ continue;
+ }
+
+ if (wpa_is_bss_tmp_disallowed(wpa_s, bss->bssid)) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - MBO retry delay has not passed yet");
+ continue;
+ }
+#ifdef CONFIG_TESTING_OPTIONS
+ skip_assoc_disallow:
+#endif /* CONFIG_TESTING_OPTIONS */
+#endif /* CONFIG_MBO */
/* Matching configuration found */
return ssid;
struct wpa_bss *current_bss = NULL;
#ifndef CONFIG_NO_ROAMING
int min_diff;
+ int to_5ghz;
#endif /* CONFIG_NO_ROAMING */
if (wpa_s->reassociate)
return 1;
}
- if (current_bss->level < 0 && current_bss->level > selected->level) {
+ to_5ghz = selected->freq > 4000 && current_bss->freq < 4000;
+
+ if (current_bss->level < 0 &&
+ current_bss->level > selected->level + to_5ghz * 2) {
wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - Current BSS has better "
"signal level");
return 0;
else
min_diff = 5;
}
+ if (to_5ghz) {
+ /* Make it easier to move to 5 GHz band */
+ if (min_diff > 2)
+ min_diff -= 2;
+ else
+ min_diff = 0;
+ }
if (abs(current_bss->level - selected->level) < min_diff) {
wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - too small difference "
"in signal level");
return -1;
if (!own_request)
return -1;
+ if (data && data->scan_info.external_scan)
+ return -1;
wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results - try "
"scanning again");
wpa_supplicant_req_new_scan(wpa_s, 1, 0);
#endif /* CONFIG_NO_RANDOM_POOL */
if (own_request && wpa_s->scan_res_handler &&
- (wpa_s->own_scan_running || !wpa_s->radio->external_scan_running)) {
+ !(data && data->scan_info.external_scan)) {
void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res);
}
wpa_dbg(wpa_s, MSG_DEBUG, "New scan results available (own=%u ext=%u)",
- wpa_s->own_scan_running, wpa_s->radio->external_scan_running);
+ wpa_s->own_scan_running,
+ data ? data->scan_info.external_scan : 0);
if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
- wpa_s->manual_scan_use_id && wpa_s->own_scan_running) {
+ wpa_s->manual_scan_use_id && wpa_s->own_scan_running &&
+ own_request && !(data && data->scan_info.external_scan)) {
wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS "id=%u",
wpa_s->manual_scan_id);
wpa_s->manual_scan_use_id = 0;
wpas_notify_scan_done(wpa_s, 1);
- if (!wpa_s->own_scan_running && wpa_s->radio->external_scan_running) {
+ if (data && data->scan_info.external_scan) {
wpa_dbg(wpa_s, MSG_DEBUG, "Do not use results from externally requested scan operation for network selection");
wpa_scan_results_free(scan_res);
return 0;
wpas_wps_update_ap_info(wpa_s, scan_res);
+ if (wpa_s->wpa_state >= WPA_AUTHENTICATING &&
+ wpa_s->wpa_state < WPA_COMPLETED)
+ goto scan_work_done;
+
wpa_scan_results_free(scan_res);
- if (wpa_s->scan_work) {
+ if (own_request && wpa_s->scan_work) {
struct wpa_radio_work *work = wpa_s->scan_work;
wpa_s->scan_work = NULL;
radio_work_done(work);
scan_work_done:
wpa_scan_results_free(scan_res);
- if (wpa_s->scan_work) {
+ if (own_request && wpa_s->scan_work) {
struct wpa_radio_work *work = wpa_s->scan_work;
wpa_s->scan_work = NULL;
radio_work_done(work);
selected = wpa_supplicant_pick_network(wpa_s, &ssid);
+#ifdef CONFIG_MESH
+ if (wpa_s->ifmsh) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "Avoiding join because we already joined a mesh group");
+ return 0;
+ }
+#endif /* CONFIG_MESH */
+
if (selected) {
int skip;
skip = !wpa_supplicant_need_to_roam(wpa_s, selected, ssid);
return 0;
}
+ if (ssid != wpa_s->current_ssid &&
+ wpa_s->wpa_state >= WPA_AUTHENTICATING) {
+ wpa_s->own_disconnect_req = 1;
+ wpa_supplicant_deauthenticate(
+ wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+ }
+
if (wpa_supplicant_connect(wpa_s, selected, ssid) < 0) {
wpa_dbg(wpa_s, MSG_DEBUG, "Connect failed");
return -1;
*/
return 1;
} else {
-#ifdef CONFIG_MESH
- if (wpa_s->ifmsh) {
- wpa_msg(wpa_s, MSG_INFO,
- "Avoiding join because we already joined a mesh group");
- return 0;
- }
-#endif /* CONFIG_MESH */
wpa_dbg(wpa_s, MSG_DEBUG, "No suitable network found");
ssid = wpa_supplicant_pick_new_network(wpa_s);
if (ssid) {
#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_FST
+static int wpas_fst_update_mbie(struct wpa_supplicant *wpa_s,
+ const u8 *ie, size_t ie_len)
+{
+ struct mb_ies_info mb_ies;
+
+ if (!ie || !ie_len || !wpa_s->fst)
+ return -ENOENT;
+
+ os_memset(&mb_ies, 0, sizeof(mb_ies));
+
+ while (ie_len >= 2 && mb_ies.nof_ies < MAX_NOF_MB_IES_SUPPORTED) {
+ size_t len;
+
+ len = 2 + ie[1];
+ if (len > ie_len) {
+ wpa_hexdump(MSG_DEBUG, "FST: Truncated IE found",
+ ie, ie_len);
+ break;
+ }
+
+ if (ie[0] == WLAN_EID_MULTI_BAND) {
+ wpa_printf(MSG_DEBUG, "MB IE of %u bytes found",
+ (unsigned int) len);
+ mb_ies.ies[mb_ies.nof_ies].ie = ie + 2;
+ mb_ies.ies[mb_ies.nof_ies].ie_len = len - 2;
+ mb_ies.nof_ies++;
+ }
+
+ ie_len -= len;
+ ie += len;
+ }
+
+ if (mb_ies.nof_ies > 0) {
+ wpabuf_free(wpa_s->received_mb_ies);
+ wpa_s->received_mb_ies = mb_ies_by_info(&mb_ies);
+ return 0;
+ }
+
+ return -ENOENT;
+}
+#endif /* CONFIG_FST */
+
+
static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
union wpa_event_data *data)
{
}
if ((p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
(os_memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0)) ||
+ (p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 4 &&
+ (os_memcmp(&p[2], "\x50\x6F\x9A\x12", 4) == 0)) ||
(p[0] == WLAN_EID_RSN && p[1] >= 2)) {
if (wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, p, len))
break;
if (wpa_found || rsn_found)
wpa_s->ap_ies_from_associnfo = 1;
-#ifdef CONFIG_FST
- wpabuf_free(wpa_s->received_mb_ies);
- wpa_s->received_mb_ies = NULL;
- if (wpa_s->fst) {
- struct mb_ies_info mb_ies;
-
- wpa_printf(MSG_DEBUG, "Looking for MB IE");
- if (!mb_ies_info_by_ies(&mb_ies, data->assoc_info.resp_ies,
- data->assoc_info.resp_ies_len))
- wpa_s->received_mb_ies = mb_ies_by_info(&mb_ies);
- }
-#endif /* CONFIG_FST */
-
if (wpa_s->assoc_freq && data->assoc_info.freq &&
wpa_s->assoc_freq != data->assoc_info.freq) {
wpa_printf(MSG_DEBUG, "Operating frequency changed from "
}
+static void wpas_fst_update_mb_assoc(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
+{
+#ifdef CONFIG_FST
+ struct assoc_info *ai = data ? &data->assoc_info : NULL;
+ struct wpa_bss *bss = wpa_s->current_bss;
+ const u8 *ieprb, *iebcn;
+
+ wpabuf_free(wpa_s->received_mb_ies);
+ wpa_s->received_mb_ies = NULL;
+
+ if (ai &&
+ !wpas_fst_update_mbie(wpa_s, ai->resp_ies, ai->resp_ies_len)) {
+ wpa_printf(MSG_DEBUG,
+ "FST: MB IEs updated from Association Response frame");
+ return;
+ }
+
+ if (ai &&
+ !wpas_fst_update_mbie(wpa_s, ai->beacon_ies, ai->beacon_ies_len)) {
+ wpa_printf(MSG_DEBUG,
+ "FST: MB IEs updated from association event Beacon IEs");
+ return;
+ }
+
+ if (!bss)
+ return;
+
+ ieprb = (const u8 *) (bss + 1);
+ iebcn = ieprb + bss->ie_len;
+
+ if (!wpas_fst_update_mbie(wpa_s, ieprb, bss->ie_len))
+ wpa_printf(MSG_DEBUG, "FST: MB IEs updated from bss IE");
+ else if (!wpas_fst_update_mbie(wpa_s, iebcn, bss->beacon_ie_len))
+ wpa_printf(MSG_DEBUG, "FST: MB IEs updated from bss beacon IE");
+#endif /* CONFIG_FST */
+}
+
+
static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
union wpa_event_data *data)
{
u8 bssid[ETH_ALEN];
- int ft_completed;
+ int ft_completed, already_authorized;
int new_bss = 0;
#ifdef CONFIG_AP
"WPA/RSN IEs not updated");
}
+ wpas_fst_update_mb_assoc(wpa_s, data);
+
#ifdef CONFIG_SME
os_memcpy(wpa_s->sme.prev_bssid, bssid, ETH_ALEN);
wpa_s->sme.prev_bssid_set = 1;
if (wpa_s->l2)
l2_packet_notify_auth_start(wpa_s->l2);
+ already_authorized = data && data->assoc_info.authorized;
+
/*
* Set portEnabled first to FALSE in order to get EAP state machine out
* of the SUCCESS state and eapSuccess cleared. Without this, EAPOL PAE
* AUTHENTICATED without ever giving chance to EAP state machine to
* reset the state.
*/
- if (!ft_completed) {
+ if (!ft_completed && !already_authorized) {
eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
}
- if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || ft_completed)
+ if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || ft_completed ||
+ already_authorized)
eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
/* 802.1X::portControl = Auto */
eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE);
wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE &&
wpa_s->ibss_rsn == NULL) {
- wpa_s->ibss_rsn = ibss_rsn_init(wpa_s);
+ wpa_s->ibss_rsn = ibss_rsn_init(wpa_s, wpa_s->current_ssid);
if (!wpa_s->ibss_rsn) {
wpa_msg(wpa_s, MSG_INFO, "Failed to init IBSS RSN");
wpa_supplicant_deauthenticate(
struct wpa_bss *fast_reconnect = NULL;
struct wpa_ssid *fast_reconnect_ssid = NULL;
struct wpa_ssid *last_ssid;
+ struct wpa_bss *curr = NULL;
authenticating = wpa_s->wpa_state == WPA_AUTHENTICATING;
os_memcpy(prev_pending_bssid, wpa_s->pending_bssid, ETH_ALEN);
return;
}
+ if (!wpa_s->disconnected && wpa_s->wpa_state >= WPA_AUTHENTICATING &&
+ reason_code == WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY &&
+ locally_generated)
+ /*
+ * Remove the inactive AP (which is probably out of range) from
+ * the BSS list after marking disassociation. In particular
+ * mac80211-based drivers use the
+ * WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY reason code in
+ * locally generated disconnection events for cases where the
+ * AP does not reply anymore.
+ */
+ curr = wpa_s->current_bss;
+
if (could_be_psk_mismatch(wpa_s, reason_code, locally_generated)) {
wpa_msg(wpa_s, MSG_INFO, "WPA: 4-Way Handshake failed - "
"pre-shared key may be incorrect");
if (!wpa_s->disconnected &&
(!wpa_s->auto_reconnect_disabled ||
wpa_s->key_mgmt == WPA_KEY_MGMT_WPS ||
- wpas_wps_searching(wpa_s))) {
+ wpas_wps_searching(wpa_s) ||
+ wpas_wps_reenable_networks_pending(wpa_s))) {
wpa_dbg(wpa_s, MSG_DEBUG, "Auto connect enabled: try to "
"reconnect (wps=%d/%d wpa_state=%d)",
wpa_s->key_mgmt == WPA_KEY_MGMT_WPS,
last_ssid = wpa_s->current_ssid;
wpa_supplicant_mark_disassoc(wpa_s);
+ if (curr)
+ wpa_bss_remove(wpa_s, curr, "Connection to AP lost");
+
if (authenticating && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)) {
sme_disassoc_while_authenticating(wpa_s, prev_pending_bssid);
wpa_s->current_ssid = last_ssid;
!disallowed_bssid(wpa_s, fast_reconnect->bssid) &&
!disallowed_ssid(wpa_s, fast_reconnect->ssid,
fast_reconnect->ssid_len) &&
- !wpas_temp_disabled(wpa_s, fast_reconnect_ssid)) {
+ !wpas_temp_disabled(wpa_s, fast_reconnect_ssid) &&
+ !wpa_is_bss_tmp_disallowed(wpa_s, fast_reconnect->bssid)) {
#ifndef CONFIG_NO_SCAN_PROCESSING
wpa_dbg(wpa_s, MSG_DEBUG, "Try to reconnect to the same BSS");
if (wpa_supplicant_connect(wpa_s, fast_reconnect,
}
#endif /* CONFIG_P2P */
+#ifdef CONFIG_MATCH_IFACE
+ if (wpa_s->matched) {
+ wpa_supplicant_remove_iface(wpa_s->global, wpa_s, 0);
+ break;
+ }
+#endif /* CONFIG_MATCH_IFACE */
+
#ifdef CONFIG_TERMINATE_ONLASTIF
/* check if last interface */
if (!any_interfaces(wpa_s->global->ifaces))
{
struct wpa_supplicant *ifs;
- wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REGDOM_CHANGE "init=%s type=%s%s%s",
+ /*
+ * To allow backwards compatibility with higher level layers that
+ * assumed the REGDOM_CHANGE event is sent over the initially added
+ * interface. Find the highest parent of this interface and use it to
+ * send the event.
+ */
+ for (ifs = wpa_s; ifs->parent && ifs != ifs->parent; ifs = ifs->parent)
+ ;
+
+ wpa_msg(ifs, MSG_INFO, WPA_EVENT_REGDOM_CHANGE "init=%s type=%s%s%s",
reg_init_str(info->initiator), reg_type_str(info->type),
info->alpha2[0] ? " alpha2=" : "",
info->alpha2[0] ? info->alpha2 : "");
free_hw_features(ifs);
ifs->hw.modes = wpa_drv_get_hw_feature_data(
ifs, &ifs->hw.num_modes, &ifs->hw.flags);
- }
- /* Restart sched_scan with updated channel list */
- if (wpa_s->sched_scanning) {
- wpa_dbg(wpa_s, MSG_DEBUG,
- "Channel list changed restart sched scan.");
- wpa_supplicant_cancel_sched_scan(wpa_s);
- wpa_supplicant_req_scan(wpa_s, 0, 0);
+ /* Restart PNO/sched_scan with updated channel list */
+ if (ifs->pno) {
+ wpas_stop_pno(ifs);
+ wpas_start_pno(ifs);
+ } else if (ifs->sched_scanning && !ifs->pno_sched_pending) {
+ wpa_dbg(ifs, MSG_DEBUG,
+ "Channel list changed - restart sched_scan");
+ wpas_scan_restart_sched_scan(ifs);
+ }
}
wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DRIVER);
#endif /* CONFIG_INTERWORKING */
if (category == WLAN_ACTION_RADIO_MEASUREMENT &&
+ payload[0] == WLAN_RRM_RADIO_MEASUREMENT_REQUEST) {
+ wpas_rrm_handle_radio_measurement_request(wpa_s, mgmt->sa,
+ payload + 1,
+ plen - 1);
+ return;
+ }
+
+ if (category == WLAN_ACTION_RADIO_MEASUREMENT &&
payload[0] == WLAN_RRM_NEIGHBOR_REPORT_RESPONSE) {
wpas_rrm_process_neighbor_rep(wpa_s, payload + 1, plen - 1);
return;
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED &&
event != EVENT_INTERFACE_ENABLED &&
event != EVENT_INTERFACE_STATUS &&
+ event != EVENT_SCAN_RESULTS &&
event != EVENT_SCHED_SCAN_STOPPED) {
wpa_dbg(wpa_s, MSG_DEBUG,
"Ignore event %s (%d) while interface is disabled",
switch (event) {
case EVENT_AUTH:
+#ifdef CONFIG_FST
+ if (!wpas_fst_update_mbie(wpa_s, data->auth.ies,
+ data->auth.ies_len))
+ wpa_printf(MSG_DEBUG,
+ "FST: MB IEs updated from auth IE");
+#endif /* CONFIG_FST */
sme_event_auth(wpa_s, data);
break;
case EVENT_ASSOC:
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->ignore_auth_resp) {
+ wpa_printf(MSG_INFO,
+ "EVENT_ASSOC - ignore_auth_resp active!");
+ break;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
wpa_supplicant_event_assoc(wpa_s, data);
if (data && data->assoc_info.authorized)
wpa_supplicant_event_assoc_auth(wpa_s, data);
+ if (data) {
+ wpa_msg(wpa_s, MSG_INFO,
+ WPA_EVENT_SUBNET_STATUS_UPDATE "status=%u",
+ data->assoc_info.subnet_status);
+ }
break;
case EVENT_DISASSOC:
wpas_event_disassoc(wpa_s,
data ? &data->disassoc_info : NULL);
break;
case EVENT_DEAUTH:
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->ignore_auth_resp) {
+ wpa_printf(MSG_INFO,
+ "EVENT_DEAUTH - ignore_auth_resp active!");
+ break;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
wpas_event_deauth(wpa_s,
data ? &data->deauth_info : NULL);
break;
break;
#ifndef CONFIG_NO_SCAN_PROCESSING
case EVENT_SCAN_STARTED:
- os_get_reltime(&wpa_s->scan_start_time);
- if (wpa_s->own_scan_requested) {
+ if (wpa_s->own_scan_requested ||
+ (data && !data->scan_info.external_scan)) {
struct os_reltime diff;
+ os_get_reltime(&wpa_s->scan_start_time);
os_reltime_sub(&wpa_s->scan_start_time,
&wpa_s->scan_trigger_time, &diff);
wpa_dbg(wpa_s, MSG_DEBUG, "Own scan request started a scan in %ld.%06ld seconds",
}
break;
case EVENT_SCAN_RESULTS:
- if (os_reltime_initialized(&wpa_s->scan_start_time)) {
+ if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+ wpa_s->scan_res_handler = NULL;
+ wpa_s->own_scan_running = 0;
+ wpa_s->radio->external_scan_running = 0;
+ wpa_s->last_scan_req = NORMAL_SCAN_REQ;
+ break;
+ }
+
+ if (!(data && data->scan_info.external_scan) &&
+ os_reltime_initialized(&wpa_s->scan_start_time)) {
struct os_reltime now, diff;
os_get_reltime(&now);
os_reltime_sub(&now, &wpa_s->scan_start_time, &diff);
}
if (wpa_supplicant_event_scan_results(wpa_s, data))
break; /* interface may have been removed */
- wpa_s->own_scan_running = 0;
- wpa_s->radio->external_scan_running = 0;
+ if (!(data && data->scan_info.external_scan))
+ wpa_s->own_scan_running = 0;
+ if (data && data->scan_info.nl_scan_event)
+ wpa_s->radio->external_scan_running = 0;
radio_work_check_next(wpa_s);
break;
#endif /* CONFIG_NO_SCAN_PROCESSING */
case EVENT_ASSOC_REJECT:
if (data->assoc_reject.bssid)
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
- "bssid=" MACSTR " status_code=%u",
+ "bssid=" MACSTR " status_code=%u%s",
MAC2STR(data->assoc_reject.bssid),
- data->assoc_reject.status_code);
+ data->assoc_reject.status_code,
+ data->assoc_reject.timed_out ? " timeout" : "");
else
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
- "status_code=%u",
- data->assoc_reject.status_code);
+ "status_code=%u%s",
+ data->assoc_reject.status_code,
+ data->assoc_reject.timed_out ? " timeout" : "");
+ wpa_s->assoc_status_code = data->assoc_reject.status_code;
+ wpas_notify_assoc_status_code(wpa_s);
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
sme_event_assoc_reject(wpa_s, data);
else {
#endif /* CONFIG_AP */
#ifdef CONFIG_OFFCHANNEL
wpa_dbg(wpa_s, MSG_DEBUG, "EVENT_TX_STATUS pending_dst="
- MACSTR, MAC2STR(wpa_s->parent->pending_action_dst));
+ MACSTR, MAC2STR(wpa_s->p2pdev->pending_action_dst));
/*
* Catch TX status events for Action frames we sent via group
- * interface in GO mode.
+ * interface in GO mode, or via standalone AP interface.
+ * Note, wpa_s->p2pdev will be the same as wpa_s->parent,
+ * except when the primary interface is used as a GO interface
+ * (for drivers which do not have group interface concurrency)
*/
if (data->tx_status.type == WLAN_FC_TYPE_MGMT &&
data->tx_status.stype == WLAN_FC_STYPE_ACTION &&
- os_memcmp(wpa_s->parent->pending_action_dst,
+ os_memcmp(wpa_s->p2pdev->pending_action_dst,
data->tx_status.dst, ETH_ALEN) == 0) {
offchannel_send_action_tx_status(
- wpa_s->parent, data->tx_status.dst,
+ wpa_s->p2pdev, data->tx_status.dst,
data->tx_status.data,
data->tx_status.data_len,
data->tx_status.ack ?
data->rx_from_unknown.wds);
break;
case EVENT_CH_SWITCH:
- if (!data)
- break;
- if (!wpa_s->ap_iface) {
- wpa_dbg(wpa_s, MSG_DEBUG, "AP: Ignore channel switch "
- "event in non-AP mode");
+ if (!data || !wpa_s->current_ssid)
break;
+
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CHANNEL_SWITCH
+ "freq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d",
+ data->ch_switch.freq,
+ data->ch_switch.ht_enabled,
+ data->ch_switch.ch_offset,
+ channel_width_to_string(data->ch_switch.ch_width),
+ data->ch_switch.cf1,
+ data->ch_switch.cf2);
+
+ wpa_s->assoc_freq = data->ch_switch.freq;
+ wpa_s->current_ssid->frequency = data->ch_switch.freq;
+
+ if (wpa_s->current_ssid->mode == WPAS_MODE_AP ||
+ wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO ||
+ wpa_s->current_ssid->mode ==
+ WPAS_MODE_P2P_GROUP_FORMATION) {
+ wpas_ap_ch_switch(wpa_s, data->ch_switch.freq,
+ data->ch_switch.ht_enabled,
+ data->ch_switch.ch_offset,
+ data->ch_switch.ch_width,
+ data->ch_switch.cf1,
+ data->ch_switch.cf2);
}
- wpas_ap_ch_switch(wpa_s, data->ch_switch.freq,
- data->ch_switch.ht_enabled,
- data->ch_switch.ch_offset,
- data->ch_switch.ch_width,
- data->ch_switch.cf1,
- data->ch_switch.cf2);
+ wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_CS);
break;
#ifdef NEED_AP_MLME
case EVENT_DFS_RADAR_DETECTED:
#endif /* CONFIG_AP */
#ifdef CONFIG_P2P
if (stype == WLAN_FC_STYPE_PROBE_REQ &&
- data->rx_mgmt.frame_len > 24) {
+ data->rx_mgmt.frame_len > IEEE80211_HDRLEN) {
const u8 *src = mgmt->sa;
- const u8 *ie = mgmt->u.probe_req.variable;
- size_t ie_len = data->rx_mgmt.frame_len -
- (mgmt->u.probe_req.variable -
- data->rx_mgmt.frame);
+ const u8 *ie;
+ size_t ie_len;
+
+ ie = data->rx_mgmt.frame + IEEE80211_HDRLEN;
+ ie_len = data->rx_mgmt.frame_len -
+ IEEE80211_HDRLEN;
wpas_p2p_probe_req_rx(
wpa_s, src, mgmt->da,
mgmt->bssid, ie, ie_len,
}
if (stype == WLAN_FC_STYPE_PROBE_REQ &&
- data->rx_mgmt.frame_len > 24) {
- const u8 *ie = mgmt->u.probe_req.variable;
- size_t ie_len = data->rx_mgmt.frame_len -
- (mgmt->u.probe_req.variable -
- data->rx_mgmt.frame);
+ data->rx_mgmt.frame_len > IEEE80211_HDRLEN) {
+ const u8 *ie;
+ size_t ie_len;
+
+ ie = data->rx_mgmt.frame + IEEE80211_HDRLEN;
+ ie_len = data->rx_mgmt.frame_len - IEEE80211_HDRLEN;
wpas_notify_preq(wpa_s, mgmt->sa, mgmt->da,
mgmt->bssid, ie, ie_len,
wpa_s, WLAN_REASON_DEAUTH_LEAVING, 1);
}
wpa_supplicant_mark_disassoc(wpa_s);
+ wpa_bss_flush(wpa_s);
radio_remove_works(wpa_s, NULL, 0);
wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED);
data->driver_gtk_rekey.replay_ctr);
break;
case EVENT_SCHED_SCAN_STOPPED:
- wpa_s->pno = 0;
wpa_s->sched_scanning = 0;
- resched = wpa_s->scanning;
+ resched = wpa_s->scanning && wpas_scan_scheduled(wpa_s);
wpa_supplicant_notify_scanning(wpa_s, 0);
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
break;
/*
+ * If the driver stopped scanning without being requested to,
+ * request a new scan to continue scanning for networks.
+ */
+ if (!wpa_s->sched_scan_stop_req &&
+ wpa_s->wpa_state == WPA_SCANNING) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Restart scanning after unexpected sched_scan stop event");
+ wpa_supplicant_req_scan(wpa_s, 1, 0);
+ break;
+ }
+
+ wpa_s->sched_scan_stop_req = 0;
+
+ /*
* Start a new sched scan to continue searching for more SSIDs
* either if timed out or PNO schedule scan is pending.
*/
data->mesh_peer.ie_len);
#endif /* CONFIG_MESH */
break;
+ case EVENT_SURVEY:
+#ifdef CONFIG_AP
+ if (!wpa_s->ap_iface)
+ break;
+ hostapd_event_get_survey(wpa_s->ap_iface,
+ &data->survey_results);
+#endif /* CONFIG_AP */
+ break;
+ case EVENT_ACS_CHANNEL_SELECTED:
+#ifdef CONFIG_ACS
+ if (!wpa_s->ap_iface)
+ break;
+ hostapd_acs_channel_selected(wpa_s->ap_iface->bss[0],
+ &data->acs_selected_channels);
+#endif /* CONFIG_ACS */
+ break;
+ case EVENT_P2P_LO_STOP:
+#ifdef CONFIG_P2P
+ wpa_s->p2p_lo_started = 0;
+ wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_LISTEN_OFFLOAD_STOP
+ P2P_LISTEN_OFFLOAD_STOP_REASON "reason=%d",
+ data->p2p_lo_stop.reason_code);
+#endif /* CONFIG_P2P */
+ break;
default:
wpa_msg(wpa_s, MSG_INFO, "Unknown event %d", event);
break;
}
}
+
+
+void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
+ union wpa_event_data *data)
+{
+ struct wpa_supplicant *wpa_s;
+
+ if (event != EVENT_INTERFACE_STATUS)
+ return;
+
+ wpa_s = wpa_supplicant_get_iface(ctx, data->interface_status.ifname);
+ if (wpa_s && wpa_s->driver->get_ifindex) {
+ unsigned int ifindex;
+
+ ifindex = wpa_s->driver->get_ifindex(wpa_s->drv_priv);
+ if (ifindex != data->interface_status.ifindex) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "interface status ifindex %d mismatch (%d)",
+ ifindex, data->interface_status.ifindex);
+ return;
+ }
+ }
+#ifdef CONFIG_MATCH_IFACE
+ else if (data->interface_status.ievent == EVENT_INTERFACE_ADDED) {
+ struct wpa_interface *wpa_i;
+
+ wpa_i = wpa_supplicant_match_iface(
+ ctx, data->interface_status.ifname);
+ if (!wpa_i)
+ return;
+ wpa_s = wpa_supplicant_add_iface(ctx, wpa_i, NULL);
+ os_free(wpa_i);
+ if (wpa_s)
+ wpa_s->matched = 1;
+ }
+#endif /* CONFIG_MATCH_IFACE */
+
+ if (wpa_s)
+ wpa_supplicant_event(wpa_s, event, data);
+}
#include "common/wpa_ctrl.h"
#include "rsn_supp/wpa.h"
#include "wpa_supplicant_i.h"
+#include "config.h"
#include "driver_i.h"
#include "offchannel.h"
#include "gas_query.h"
/** GAS query timeout in seconds */
#define GAS_QUERY_TIMEOUT_PERIOD 2
+/* GAS query wait-time / duration in ms */
+#define GAS_QUERY_WAIT_TIME_INITIAL 1000
+#define GAS_QUERY_WAIT_TIME_COMEBACK 150
/**
* struct gas_query_pending - Pending GAS query
u8 next_frag_id;
unsigned int wait_comeback:1;
unsigned int offchannel_tx_started:1;
+ unsigned int retry:1;
int freq;
u16 status_code;
struct wpabuf *req;
static void gas_query_tx_comeback_timeout(void *eloop_data, void *user_ctx);
static void gas_query_timeout(void *eloop_data, void *user_ctx);
+static void gas_query_rx_comeback_timeout(void *eloop_data, void *user_ctx);
+static void gas_query_tx_initial_req(struct gas_query *gas,
+ struct gas_query_pending *query);
+static int gas_query_new_dialog_token(struct gas_query *gas, const u8 *dst);
static int ms_from_time(struct os_reltime *last)
return "PEER_ERROR";
case GAS_QUERY_INTERNAL_ERROR:
return "INTERNAL_ERROR";
- case GAS_QUERY_CANCELLED:
- return "CANCELLED";
case GAS_QUERY_DELETED_AT_DEINIT:
return "DELETED_AT_DEINIT";
}
offchannel_send_action_done(gas->wpa_s);
eloop_cancel_timeout(gas_query_tx_comeback_timeout, gas, query);
eloop_cancel_timeout(gas_query_timeout, gas, query);
+ eloop_cancel_timeout(gas_query_rx_comeback_timeout, gas, query);
dl_list_del(&query->list);
query->cb(query->ctx, query->addr, query->dialog_token, result,
query->adv_proto, query->resp, query->status_code);
eloop_cancel_timeout(gas_query_timeout, gas, query);
eloop_register_timeout(GAS_QUERY_TIMEOUT_PERIOD, 0,
gas_query_timeout, gas, query);
+ if (query->wait_comeback && !query->retry) {
+ eloop_cancel_timeout(gas_query_rx_comeback_timeout,
+ gas, query);
+ eloop_register_timeout(
+ 0, (GAS_QUERY_WAIT_TIME_COMEBACK + 10) * 1000,
+ gas_query_rx_comeback_timeout, gas, query);
+ }
}
if (result == OFFCHANNEL_SEND_ACTION_FAILED) {
eloop_cancel_timeout(gas_query_timeout, gas, query);
static int gas_query_tx(struct gas_query *gas, struct gas_query_pending *query,
- struct wpabuf *req)
+ struct wpabuf *req, unsigned int wait_time)
{
- unsigned int wait_time;
int res, prot = pmf_in_use(gas->wpa_s, query->addr);
+ const u8 *bssid;
+ const u8 wildcard_bssid[ETH_ALEN] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
wpa_printf(MSG_DEBUG, "GAS: Send action frame to " MACSTR " len=%u "
"freq=%d prot=%d", MAC2STR(query->addr),
*categ = WLAN_ACTION_PROTECTED_DUAL;
}
os_get_reltime(&query->last_oper);
- wait_time = 1000;
if (gas->wpa_s->max_remain_on_chan &&
wait_time > gas->wpa_s->max_remain_on_chan)
wait_time = gas->wpa_s->max_remain_on_chan;
+ if (!gas->wpa_s->conf->gas_address3 ||
+ (gas->wpa_s->current_ssid &&
+ gas->wpa_s->wpa_state >= WPA_ASSOCIATED &&
+ os_memcmp(query->addr, gas->wpa_s->bssid, ETH_ALEN) == 0))
+ bssid = query->addr;
+ else
+ bssid = wildcard_bssid;
res = offchannel_send_action(gas->wpa_s, query->freq, query->addr,
- gas->wpa_s->own_addr, query->addr,
+ gas->wpa_s->own_addr, bssid,
wpabuf_head(req), wpabuf_len(req),
wait_time, gas_query_tx_status, 0);
if (res == 0)
struct gas_query_pending *query)
{
struct wpabuf *req;
+ unsigned int wait_time;
req = gas_build_comeback_req(query->dialog_token);
if (req == NULL) {
return;
}
- if (gas_query_tx(gas, query, req) < 0) {
+ wait_time = (query->retry || !query->offchannel_tx_started) ?
+ GAS_QUERY_WAIT_TIME_INITIAL : GAS_QUERY_WAIT_TIME_COMEBACK;
+
+ if (gas_query_tx(gas, query, req, wait_time) < 0) {
wpa_printf(MSG_DEBUG, "GAS: Failed to send Action frame to "
MACSTR, MAC2STR(query->addr));
gas_query_done(gas, query, GAS_QUERY_INTERNAL_ERROR);
}
+static void gas_query_rx_comeback_timeout(void *eloop_data, void *user_ctx)
+{
+ struct gas_query *gas = eloop_data;
+ struct gas_query_pending *query = user_ctx;
+ int dialog_token;
+
+ wpa_printf(MSG_DEBUG,
+ "GAS: No response to comeback request received (retry=%u)",
+ query->retry);
+ if (gas->current != query || query->retry)
+ return;
+ dialog_token = gas_query_new_dialog_token(gas, query->addr);
+ if (dialog_token < 0)
+ return;
+ wpa_printf(MSG_DEBUG,
+ "GAS: Retry GAS query due to comeback response timeout");
+ query->retry = 1;
+ query->dialog_token = dialog_token;
+ *(wpabuf_mhead_u8(query->req) + 2) = dialog_token;
+ query->wait_comeback = 0;
+ query->next_frag_id = 0;
+ wpabuf_free(query->adv_proto);
+ query->adv_proto = NULL;
+ eloop_cancel_timeout(gas_query_tx_comeback_timeout, gas, query);
+ eloop_cancel_timeout(gas_query_timeout, gas, query);
+ gas_query_tx_initial_req(gas, query);
+}
+
+
static void gas_query_tx_comeback_timeout(void *eloop_data, void *user_ctx)
{
struct gas_query *gas = eloop_data;
{
unsigned int secs, usecs;
+ if (comeback_delay > 1 && query->offchannel_tx_started) {
+ offchannel_send_action_done(gas->wpa_s);
+ query->offchannel_tx_started = 0;
+ }
+
secs = (comeback_delay * 1024) / 1000000;
usecs = comeback_delay * 1024 - secs * 1000000;
wpa_printf(MSG_DEBUG, "GAS: Send comeback request to " MACSTR
"comeback_delay=%u)",
MAC2STR(query->addr), query->dialog_token, frag_id,
more_frags, comeback_delay);
+ eloop_cancel_timeout(gas_query_rx_comeback_timeout, gas, query);
if ((size_t) 2 + adv_proto[1] != wpabuf_len(query->adv_proto) ||
os_memcmp(adv_proto, wpabuf_head(query->adv_proto),
if (gas == NULL || len < 4)
return -1;
+ pos = data;
+ action = *pos++;
+ dialog_token = *pos++;
+
+ if (action != WLAN_PA_GAS_INITIAL_RESP &&
+ action != WLAN_PA_GAS_COMEBACK_RESP)
+ return -1; /* Not a GAS response */
+
prot = categ == WLAN_ACTION_PROTECTED_DUAL;
- pmf = pmf_in_use(gas->wpa_s, bssid);
+ pmf = pmf_in_use(gas->wpa_s, sa);
if (prot && !pmf) {
wpa_printf(MSG_DEBUG, "GAS: Drop unexpected protected GAS frame when PMF is disabled");
return 0;
return 0;
}
- pos = data;
- action = *pos++;
- dialog_token = *pos++;
-
- if (action != WLAN_PA_GAS_INITIAL_RESP &&
- action != WLAN_PA_GAS_COMEBACK_RESP)
- return -1; /* Not a GAS response */
-
query = gas_query_get_pending(gas, sa, dialog_token);
if (query == NULL) {
wpa_printf(MSG_DEBUG, "GAS: No pending query found for " MACSTR
}
gas->work = work;
+ gas_query_tx_initial_req(gas, query);
+}
- if (gas_query_tx(gas, query, query->req) < 0) {
+
+static void gas_query_tx_initial_req(struct gas_query *gas,
+ struct gas_query_pending *query)
+{
+ if (gas_query_tx(gas, query, query->req,
+ GAS_QUERY_WAIT_TIME_INITIAL) < 0) {
wpa_printf(MSG_DEBUG, "GAS: Failed to send Action frame to "
MACSTR, MAC2STR(query->addr));
- gas_query_free(query, 1);
+ gas_query_done(gas, query, GAS_QUERY_INTERNAL_ERROR);
return;
}
gas->current = query;
query->dialog_token);
eloop_register_timeout(GAS_QUERY_TIMEOUT_PERIOD, 0,
gas_query_timeout, gas, query);
+}
+
+
+static int gas_query_new_dialog_token(struct gas_query *gas, const u8 *dst)
+{
+ static int next_start = 0;
+ int dialog_token;
+ for (dialog_token = 0; dialog_token < 256; dialog_token++) {
+ if (gas_query_dialog_token_available(
+ gas, dst, (next_start + dialog_token) % 256))
+ break;
+ }
+ if (dialog_token == 256)
+ return -1; /* Too many pending queries */
+ dialog_token = (next_start + dialog_token) % 256;
+ next_start = (dialog_token + 1) % 256;
+ return dialog_token;
}
{
struct gas_query_pending *query;
int dialog_token;
- static int next_start = 0;
if (wpabuf_len(req) < 3)
return -1;
- for (dialog_token = 0; dialog_token < 256; dialog_token++) {
- if (gas_query_dialog_token_available(
- gas, dst, (next_start + dialog_token) % 256))
- break;
- }
- if (dialog_token == 256)
- return -1; /* Too many pending queries */
- dialog_token = (next_start + dialog_token) % 256;
- next_start = (dialog_token + 1) % 256;
+ dialog_token = gas_query_new_dialog_token(gas, dst);
+ if (dialog_token < 0)
+ return -1;
query = os_zalloc(sizeof(*query));
if (query == NULL)
if (radio_add_work(gas->wpa_s, freq, "gas-query", 0, gas_query_start_cb,
query) < 0) {
+ query->req = NULL; /* caller will free this in error case */
gas_query_free(query, 1);
return -1;
}
return dialog_token;
}
-
-
-/**
- * gas_query_cancel - Cancel a pending GAS query
- * @gas: GAS query data from gas_query_init()
- * @dst: Destination MAC address for the query
- * @dialog_token: Dialog token from gas_query_req()
- */
-void gas_query_cancel(struct gas_query *gas, const u8 *dst, u8 dialog_token)
-{
- struct gas_query_pending *query;
-
- query = gas_query_get_pending(gas, dst, dialog_token);
- if (query)
- gas_query_done(gas, query, GAS_QUERY_CANCELLED);
-
-}
GAS_QUERY_TIMEOUT,
GAS_QUERY_PEER_ERROR,
GAS_QUERY_INTERNAL_ERROR,
- GAS_QUERY_CANCELLED,
GAS_QUERY_DELETED_AT_DEINIT
};
const struct wpabuf *adv_proto,
const struct wpabuf *resp, u16 status_code),
void *ctx);
-void gas_query_cancel(struct gas_query *gas, const u8 *dst, u8 dialog_token);
#else /* CONFIG_GAS */
#include "gas_query.h"
#include "interworking.h"
#include "hs20_supplicant.h"
+#include "base64.h"
#define OSU_MAX_ITEMS 10
};
+void hs20_configure_frame_filters(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_bss *bss = wpa_s->current_bss;
+ u8 *bssid = wpa_s->bssid;
+ const u8 *ie;
+ const u8 *ext_capa;
+ u32 filter = 0;
+
+ if (!bss || !is_hs20_network(wpa_s, wpa_s->current_ssid, bss)) {
+ wpa_printf(MSG_DEBUG,
+ "Not configuring frame filtering - BSS " MACSTR
+ " is not a Hotspot 2.0 network", MAC2STR(bssid));
+ return;
+ }
+
+ ie = wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE);
+
+ /* Check if DGAF disabled bit is zero (5th byte in the IE) */
+ if (!ie || ie[1] < 5)
+ wpa_printf(MSG_DEBUG,
+ "Not configuring frame filtering - Can't extract DGAF bit");
+ else if (!(ie[6] & HS20_DGAF_DISABLED))
+ filter |= WPA_DATA_FRAME_FILTER_FLAG_GTK;
+
+ ext_capa = wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB);
+ if (!ext_capa || ext_capa[1] < 2) {
+ wpa_printf(MSG_DEBUG,
+ "Not configuring frame filtering - Can't extract Proxy ARP bit");
+ return;
+ }
+
+ /* Check if Proxy ARP is enabled (2nd byte in the IE) */
+ if (ext_capa[3] & BIT(4))
+ filter |= WPA_DATA_FRAME_FILTER_FLAG_ARP |
+ WPA_DATA_FRAME_FILTER_FLAG_NA;
+
+ wpa_drv_configure_frame_filters(wpa_s, filter);
+}
+
+
void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id)
{
u8 conf;
}
-struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload,
- size_t payload_len)
+static struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload,
+ size_t payload_len)
{
struct wpabuf *buf;
int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes,
- const u8 *payload, size_t payload_len)
+ const u8 *payload, size_t payload_len, int inmem)
{
struct wpabuf *buf;
int ret = 0;
int freq;
struct wpa_bss *bss;
int res;
+ struct icon_entry *icon_entry;
bss = wpa_bss_get_bssid(wpa_s, dst);
if (!bss) {
if (res < 0) {
wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request");
wpabuf_free(buf);
- ret = -1;
+ return -1;
} else
wpa_printf(MSG_DEBUG, "ANQP: Query started with dialog token "
"%u", res);
+ if (inmem) {
+ icon_entry = os_zalloc(sizeof(struct icon_entry));
+ if (!icon_entry)
+ return -1;
+ os_memcpy(icon_entry->bssid, dst, ETH_ALEN);
+ icon_entry->file_name = os_malloc(payload_len + 1);
+ if (!icon_entry->file_name) {
+ os_free(icon_entry);
+ return -1;
+ }
+ os_memcpy(icon_entry->file_name, payload, payload_len);
+ icon_entry->file_name[payload_len] = '\0';
+ icon_entry->dialog_token = res;
+
+ dl_list_add(&wpa_s->icon_head, &icon_entry->list);
+ }
+
return ret;
}
+static struct icon_entry * hs20_find_icon(struct wpa_supplicant *wpa_s,
+ const u8 *bssid,
+ const char *file_name)
+{
+ struct icon_entry *icon;
+
+ dl_list_for_each(icon, &wpa_s->icon_head, struct icon_entry, list) {
+ if (os_memcmp(icon->bssid, bssid, ETH_ALEN) == 0 &&
+ os_strcmp(icon->file_name, file_name) == 0 && icon->image)
+ return icon;
+ }
+
+ return NULL;
+}
+
+
+int hs20_get_icon(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ const char *file_name, size_t offset, size_t size,
+ char *reply, size_t buf_len)
+{
+ struct icon_entry *icon;
+ size_t out_size;
+ unsigned char *b64;
+ size_t b64_size;
+ int reply_size;
+
+ wpa_printf(MSG_DEBUG, "HS20: Get icon " MACSTR " %s @ %u +%u (%u)",
+ MAC2STR(bssid), file_name, (unsigned int) offset,
+ (unsigned int) size, (unsigned int) buf_len);
+
+ icon = hs20_find_icon(wpa_s, bssid, file_name);
+ if (!icon || !icon->image || offset >= icon->image_len)
+ return -1;
+ if (size > icon->image_len - offset)
+ size = icon->image_len - offset;
+ out_size = buf_len - 3 /* max base64 padding */;
+ if (size * 4 > out_size * 3)
+ size = out_size * 3 / 4;
+ if (size == 0)
+ return -1;
+
+ b64 = base64_encode(&icon->image[offset], size, &b64_size);
+ if (b64 && buf_len >= b64_size) {
+ os_memcpy(reply, b64, b64_size);
+ reply_size = b64_size;
+ } else {
+ reply_size = -1;
+ }
+ os_free(b64);
+ return reply_size;
+}
+
+
+static void hs20_free_icon_entry(struct icon_entry *icon)
+{
+ wpa_printf(MSG_DEBUG, "HS20: Free stored icon from " MACSTR
+ " dialog_token=%u file_name=%s image_len=%u",
+ MAC2STR(icon->bssid), icon->dialog_token,
+ icon->file_name ? icon->file_name : "N/A",
+ (unsigned int) icon->image_len);
+ os_free(icon->file_name);
+ os_free(icon->image);
+ os_free(icon);
+}
+
+
+int hs20_del_icon(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ const char *file_name)
+{
+ struct icon_entry *icon, *tmp;
+ int count = 0;
+
+ if (!bssid)
+ wpa_printf(MSG_DEBUG, "HS20: Delete all stored icons");
+ else if (!file_name)
+ wpa_printf(MSG_DEBUG, "HS20: Delete all stored icons for "
+ MACSTR, MAC2STR(bssid));
+ else
+ wpa_printf(MSG_DEBUG, "HS20: Delete stored icons for "
+ MACSTR " file name %s", MAC2STR(bssid), file_name);
+
+ dl_list_for_each_safe(icon, tmp, &wpa_s->icon_head, struct icon_entry,
+ list) {
+ if ((!bssid || os_memcmp(icon->bssid, bssid, ETH_ALEN) == 0) &&
+ (!file_name ||
+ os_strcmp(icon->file_name, file_name) == 0)) {
+ dl_list_del(&icon->list);
+ hs20_free_icon_entry(icon);
+ count++;
+ }
+ }
+ return count == 0 ? -1 : 0;
+}
+
+
static void hs20_set_osu_access_permission(const char *osu_dir,
const char *fname)
{
}
}
+
+static void hs20_remove_duplicate_icons(struct wpa_supplicant *wpa_s,
+ struct icon_entry *new_icon)
+{
+ struct icon_entry *icon, *tmp;
+
+ dl_list_for_each_safe(icon, tmp, &wpa_s->icon_head, struct icon_entry,
+ list) {
+ if (icon == new_icon)
+ continue;
+ if (os_memcmp(icon->bssid, new_icon->bssid, ETH_ALEN) == 0 &&
+ os_strcmp(icon->file_name, new_icon->file_name) == 0) {
+ dl_list_del(&icon->list);
+ hs20_free_icon_entry(icon);
+ }
+ }
+}
+
+
static int hs20_process_icon_binary_file(struct wpa_supplicant *wpa_s,
const u8 *sa, const u8 *pos,
- size_t slen)
+ size_t slen, u8 dialog_token)
{
char fname[256];
int png;
FILE *f;
u16 data_len;
+ struct icon_entry *icon;
+
+ dl_list_for_each(icon, &wpa_s->icon_head, struct icon_entry, list) {
+ if (icon->dialog_token == dialog_token && !icon->image &&
+ os_memcmp(icon->bssid, sa, ETH_ALEN) == 0) {
+ icon->image = os_malloc(slen);
+ if (!icon->image)
+ return -1;
+ os_memcpy(icon->image, pos, slen);
+ icon->image_len = slen;
+ hs20_remove_duplicate_icons(wpa_s, icon);
+ wpa_msg(wpa_s, MSG_INFO,
+ RX_HS20_ICON MACSTR " %s %u",
+ MAC2STR(sa), icon->file_name,
+ (unsigned int) icon->image_len);
+ return 0;
+ }
+ }
- wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR " Icon Binary File",
+ wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR " Icon Binary File",
MAC2STR(sa));
if (slen < 4) {
}
fclose(f);
- wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP-ICON %s", fname);
+ wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP_ICON "%s", fname);
return 0;
}
void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss, const u8 *sa,
- const u8 *data, size_t slen)
+ const u8 *data, size_t slen, u8 dialog_token)
{
const u8 *pos = data;
u8 subtype;
switch (subtype) {
case HS20_STYPE_CAPABILITY_LIST:
- wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
" HS Capability List", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "HS Capability List", pos, slen);
if (anqp) {
}
break;
case HS20_STYPE_OPERATOR_FRIENDLY_NAME:
- wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
" Operator Friendly Name", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "oper friendly name", pos, slen);
if (anqp) {
"Metrics value from " MACSTR, MAC2STR(sa));
break;
}
- wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
" WAN Metrics %02x:%u:%u:%u:%u:%u", MAC2STR(sa),
pos[0], WPA_GET_LE32(pos + 1), WPA_GET_LE32(pos + 5),
pos[9], pos[10], WPA_GET_LE16(pos + 11));
}
break;
case HS20_STYPE_CONNECTION_CAPABILITY:
- wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
" Connection Capability", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "conn capability", pos, slen);
if (anqp) {
}
break;
case HS20_STYPE_OPERATING_CLASS:
- wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
" Operating Class", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "Operating Class", pos, slen);
if (anqp) {
}
break;
case HS20_STYPE_OSU_PROVIDERS_LIST:
- wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
" OSU Providers list", MAC2STR(sa));
wpa_s->num_prov_found++;
if (anqp) {
}
break;
case HS20_STYPE_ICON_BINARY_FILE:
- ret = hs20_process_icon_binary_file(wpa_s, sa, pos, slen);
+ ret = hs20_process_icon_binary_file(wpa_s, sa, pos, slen,
+ dialog_token);
if (wpa_s->fetch_osu_icon_in_progress) {
hs20_osu_icon_fetch_result(wpa_s, ret);
eloop_cancel_timeout(hs20_continue_icon_fetch,
wpa_s->conf->osu_dir);
f = fopen(fname, "w");
if (f == NULL) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "Could not write OSU provider information");
hs20_free_osu_prov(wpa_s);
+ wpa_s->fetch_anqp_in_progress = 0;
return;
}
if (hs20_anqp_send_req(wpa_s, osu->bssid,
BIT(HS20_STYPE_ICON_REQUEST),
(u8 *) icon->filename,
- os_strlen(icon->filename)) < 0) {
+ os_strlen(icon->filename),
+ 0) < 0) {
icon->failed = 1;
continue;
}
prov->osu_ssid_len = osu_ssid_len;
/* OSU Friendly Name Length */
- if (pos + 2 > end) {
+ if (end - pos < 2) {
wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU "
"Friendly Name Length");
return;
pos += len2;
/* OSU Friendly Name Duples */
- while (pos2 + 4 <= pos && prov->friendly_name_count < OSU_MAX_ITEMS) {
+ while (pos - pos2 >= 4 && prov->friendly_name_count < OSU_MAX_ITEMS) {
struct osu_lang_string *f;
- if (pos2 + 1 + pos2[0] > pos || pos2[0] < 3) {
+ if (1 + pos2[0] > pos - pos2 || pos2[0] < 3) {
wpa_printf(MSG_DEBUG, "Invalid OSU Friendly Name");
break;
}
}
/* OSU Server URI */
- if (pos + 1 > end) {
+ if (end - pos < 1) {
wpa_printf(MSG_DEBUG,
"HS 2.0: Not enough room for OSU Server URI length");
return;
pos += uri_len;
/* OSU Method list */
- if (pos + 1 > end) {
+ if (end - pos < 1) {
wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU Method "
"list length");
return;
}
/* Icons Available Length */
- if (pos + 2 > end) {
+ if (end - pos < 2) {
wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for Icons "
"Available Length");
return;
struct osu_icon *icon = &prov->icon[prov->icon_count];
u8 flen;
- if (pos2 + 2 + 2 + 3 + 1 + 1 > pos) {
+ if (2 + 2 + 3 + 1 + 1 > pos - pos2) {
wpa_printf(MSG_DEBUG, "HS 2.0: Invalid Icon Metadata");
break;
}
os_memcpy(icon->lang, pos2, 3);
pos2 += 3;
- flen = pos2[0];
- if (flen > pos - pos2 - 1) {
+ flen = *pos2++;
+ if (flen > pos - pos2) {
wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon Type");
break;
}
- os_memcpy(icon->icon_type, pos2 + 1, flen);
- pos2 += 1 + flen;
+ os_memcpy(icon->icon_type, pos2, flen);
+ pos2 += flen;
- if (pos2 + 1 > pos) {
+ if (pos - pos2 < 1) {
wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon "
"Filename length");
break;
}
- flen = pos2[0];
- if (flen > pos - pos2 - 1) {
+ flen = *pos2++;
+ if (flen > pos - pos2) {
wpa_printf(MSG_DEBUG, "HS 2.0: Not room for Icon "
"Filename");
break;
}
- os_memcpy(icon->filename, pos2 + 1, flen);
- pos2 += 1 + flen;
+ os_memcpy(icon->filename, pos2, flen);
+ pos2 += flen;
prov->icon_count++;
}
/* OSU_NAI */
- if (pos + 1 > end) {
+ if (end - pos < 1) {
wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU_NAI");
return;
}
- osu_nai_len = pos[0];
- if (osu_nai_len > end - pos - 1) {
+ osu_nai_len = *pos++;
+ if (osu_nai_len > end - pos) {
wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU_NAI");
return;
}
- os_memcpy(prov->osu_nai, pos + 1, osu_nai_len);
- pos += 1 + osu_nai_len;
+ os_memcpy(prov->osu_nai, pos, osu_nai_len);
+ pos += osu_nai_len;
/* OSU Service Description Length */
- if (pos + 2 > end) {
+ if (end - pos < 2) {
wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for OSU "
"Service Description Length");
return;
pos += len2;
/* OSU Service Description Duples */
- while (pos2 + 4 <= pos && prov->serv_desc_count < OSU_MAX_ITEMS) {
+ while (pos - pos2 >= 4 && prov->serv_desc_count < OSU_MAX_ITEMS) {
struct osu_lang_string *f;
u8 descr_len;
- descr_len = pos2[0];
- if (descr_len > pos - pos2 - 1 || descr_len < 3) {
+ descr_len = *pos2++;
+ if (descr_len > pos - pos2 || descr_len < 3) {
wpa_printf(MSG_DEBUG, "Invalid OSU Service "
"Description");
break;
}
f = &prov->serv_desc[prov->serv_desc_count++];
- os_memcpy(f->lang, pos2 + 1, 3);
- os_memcpy(f->text, pos2 + 1 + 3, descr_len - 3);
- pos2 += 1 + descr_len;
+ os_memcpy(f->lang, pos2, 3);
+ os_memcpy(f->text, pos2 + 3, descr_len - 3);
+ pos2 += descr_len;
}
wpa_printf(MSG_DEBUG, "HS 2.0: Added OSU Provider through " MACSTR,
end = pos + wpabuf_len(prov_anqp);
/* OSU SSID */
- if (pos + 1 > end)
+ if (end - pos < 1)
continue;
- if (pos + 1 + pos[0] > end) {
+ if (1 + pos[0] > end - pos) {
wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for "
"OSU SSID");
continue;
osu_ssid = pos;
pos += osu_ssid_len;
- if (pos + 1 > end) {
+ if (end - pos < 1) {
wpa_printf(MSG_DEBUG, "HS 2.0: Not enough room for "
"Number of OSU Providers");
continue;
num_providers);
/* OSU Providers */
- while (pos + 2 < end && num_providers > 0) {
+ while (end - pos > 2 && num_providers > 0) {
num_providers--;
len = WPA_GET_LE16(pos);
pos += 2;
}
-int hs20_fetch_osu(struct wpa_supplicant *wpa_s)
+int hs20_fetch_osu(struct wpa_supplicant *wpa_s, int skip_scan)
{
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
wpa_printf(MSG_DEBUG, "HS 2.0: Cannot start fetch_osu - "
wpa_msg(wpa_s, MSG_INFO, "Starting OSU provisioning information fetch");
wpa_s->num_osu_scans = 0;
wpa_s->num_prov_found = 0;
- hs20_start_osu_scan(wpa_s);
+ if (skip_scan) {
+ wpa_s->network_select = 0;
+ wpa_s->fetch_all_anqp = 1;
+ wpa_s->fetch_osu_info = 1;
+ wpa_s->fetch_osu_icon_in_progress = 0;
+
+ interworking_start_fetch_anqp(wpa_s);
+ } else {
+ hs20_start_osu_scan(wpa_s);
+ }
return 0;
}
}
+void hs20_init(struct wpa_supplicant *wpa_s)
+{
+ dl_list_init(&wpa_s->icon_head);
+}
+
+
void hs20_deinit(struct wpa_supplicant *wpa_s)
{
eloop_cancel_timeout(hs20_continue_icon_fetch, wpa_s, NULL);
hs20_free_osu_prov(wpa_s);
+ if (wpa_s->icon_head.next)
+ hs20_del_icon(wpa_s, NULL, NULL);
}
#ifndef HS20_SUPPLICANT_H
#define HS20_SUPPLICANT_H
+void hs20_configure_frame_filters(struct wpa_supplicant *wpa_s);
void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id);
int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes,
- const u8 *payload, size_t payload_len);
-struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload,
- size_t payload_len);
+ const u8 *payload, size_t payload_len, int inmem);
void hs20_put_anqp_req(u32 stypes, const u8 *payload, size_t payload_len,
struct wpabuf *buf);
void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss, const u8 *sa,
- const u8 *data, size_t slen);
+ const u8 *data, size_t slen, u8 dialog_token);
int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
struct wpa_bss *bss);
int hs20_get_pps_mo_id(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
void hs20_free_osu_prov(struct wpa_supplicant *wpa_s);
void hs20_next_osu_icon(struct wpa_supplicant *wpa_s);
void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s);
-int hs20_fetch_osu(struct wpa_supplicant *wpa_s);
+int hs20_fetch_osu(struct wpa_supplicant *wpa_s, int skip_scan);
void hs20_cancel_fetch_osu(struct wpa_supplicant *wpa_s);
void hs20_icon_fetch_failed(struct wpa_supplicant *wpa_s);
void hs20_start_osu_scan(struct wpa_supplicant *wpa_s);
+void hs20_init(struct wpa_supplicant *wpa_s);
void hs20_deinit(struct wpa_supplicant *wpa_s);
+int hs20_get_icon(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ const char *file_name, size_t offset, size_t size,
+ char *reply, size_t buf_len);
+int hs20_del_icon(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ const char *file_name);
#endif /* HS20_SUPPLICANT_H */
peer->supp = wpa_sm_init(ctx);
if (peer->supp == NULL) {
wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed");
+ os_free(ctx);
return -1;
}
wpa_sm_set_param(peer->supp, WPA_PARAM_PAIRWISE, WPA_CIPHER_CCMP);
wpa_sm_set_param(peer->supp, WPA_PARAM_GROUP, WPA_CIPHER_CCMP);
wpa_sm_set_param(peer->supp, WPA_PARAM_KEY_MGMT, WPA_KEY_MGMT_PSK);
- wpa_sm_set_pmk(peer->supp, psk, PMK_LEN, NULL);
+ wpa_sm_set_pmk(peer->supp, psk, PMK_LEN, NULL, NULL);
peer->supp_ie_len = sizeof(peer->supp_ie);
if (wpa_sm_set_assoc_wpa_ie_default(peer->supp, peer->supp_ie,
static int ibss_rsn_auth_init_group(struct ibss_rsn *ibss_rsn,
- const u8 *own_addr)
+ const u8 *own_addr, struct wpa_ssid *ssid)
{
struct wpa_auth_config conf;
struct wpa_auth_callbacks cb;
conf.rsn_pairwise = WPA_CIPHER_CCMP;
conf.wpa_group = WPA_CIPHER_CCMP;
conf.eapol_version = 2;
- conf.wpa_group_rekey = 600;
+ conf.wpa_group_rekey = ssid->group_rekey ? ssid->group_rekey : 600;
os_memset(&cb, 0, sizeof(cb));
cb.ctx = ibss_rsn;
}
-struct ibss_rsn * ibss_rsn_init(struct wpa_supplicant *wpa_s)
+struct ibss_rsn * ibss_rsn_init(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
{
struct ibss_rsn *ibss_rsn;
return NULL;
ibss_rsn->wpa_s = wpa_s;
- if (ibss_rsn_auth_init_group(ibss_rsn, wpa_s->own_addr) < 0) {
+ if (ibss_rsn_auth_init_group(ibss_rsn, wpa_s->own_addr, ssid) < 0) {
ibss_rsn_deinit(ibss_rsn);
return NULL;
}
};
-struct ibss_rsn * ibss_rsn_init(struct wpa_supplicant *wpa_s);
+struct ibss_rsn * ibss_rsn_init(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid);
void ibss_rsn_deinit(struct ibss_rsn *ibss_rsn);
int ibss_rsn_start(struct ibss_rsn *ibss_rsn, const u8 *addr);
void ibss_rsn_stop(struct ibss_rsn *ibss_rsn, const u8 *peermac);
u8 elen, auth_count, a;
const u8 *e_end;
- if (pos + 3 > end) {
+ if (end - pos < 3) {
wpa_printf(MSG_DEBUG, "No room for EAP Method fixed fields");
return NULL;
}
elen = *pos++;
- if (pos + elen > end || elen < 2) {
+ if (elen > end - pos || elen < 2) {
wpa_printf(MSG_DEBUG, "No room for EAP Method subfield");
return NULL;
}
for (a = 0; a < auth_count; a++) {
u8 id, len;
- if (pos + 2 > end || pos + 2 + pos[1] > end) {
- wpa_printf(MSG_DEBUG, "No room for Authentication "
- "Parameter subfield");
+ if (end - pos < 2) {
+ wpa_printf(MSG_DEBUG,
+ "No room for Authentication Parameter subfield header");
return NULL;
}
id = *pos++;
len = *pos++;
+ if (len > end - pos) {
+ wpa_printf(MSG_DEBUG,
+ "No room for Authentication Parameter subfield");
+ return NULL;
+ }
switch (id) {
case NAI_REALM_EAP_AUTH_NON_EAP_INNER_AUTH:
len = WPA_GET_LE16(pos); /* NAI Realm Data field Length */
pos += 2;
- if (pos + len > end || len < 3) {
+ if (len > end - pos || len < 3) {
wpa_printf(MSG_DEBUG, "No room for NAI Realm Data "
"(len=%u; left=%u)",
len, (unsigned int) (end - pos));
r->encoding = *pos++;
realm_len = *pos++;
- if (pos + realm_len > f_end) {
+ if (realm_len > f_end - pos) {
wpa_printf(MSG_DEBUG, "No room for NAI Realm "
"(len=%u; left=%u)",
realm_len, (unsigned int) (f_end - pos));
return NULL;
pos += realm_len;
- if (pos + 1 > f_end) {
+ if (f_end - pos < 1) {
wpa_printf(MSG_DEBUG, "No room for EAP Method Count");
return NULL;
}
r->eap_count = *pos++;
wpa_printf(MSG_DEBUG, "EAP Count: %u", r->eap_count);
- if (pos + r->eap_count * 3 > f_end) {
+ if (r->eap_count * 3 > f_end - pos) {
wpa_printf(MSG_DEBUG, "No room for EAP Methods");
return NULL;
}
return 0;
pos = wpabuf_head_u8(anqp);
end = pos + wpabuf_len(anqp);
- if (pos + 2 > end)
+ if (end - pos < 2)
return 0;
if (*pos != 0) {
wpa_printf(MSG_DEBUG, "Unsupported GUD version 0x%x", *pos);
}
pos++;
udhl = *pos++;
- if (pos + udhl > end) {
+ if (udhl > end - pos) {
wpa_printf(MSG_DEBUG, "Invalid UDHL");
return 0;
}
plmn[0], plmn[1], plmn[2], plmn2[0], plmn2[1], plmn2[2],
imsi, mnc_len);
- while (pos + 2 <= end) {
+ while (end - pos >= 2) {
u8 iei, len;
const u8 *l_end;
iei = *pos++;
len = *pos++ & 0x7f;
- if (pos + len > end)
+ if (len > end - pos)
break;
l_end = pos + len;
pos, len);
num = *pos++;
for (i = 0; i < num; i++) {
- if (pos + 3 > l_end)
+ if (l_end - pos < 3)
break;
if (os_memcmp(pos, plmn, 3) == 0 ||
os_memcmp(pos, plmn2, 3) == 0)
if (!key_mgmt)
key_mgmt = wpa_s->conf->pmf != NO_MGMT_FRAME_PROTECTION ?
"WPA-EAP WPA-EAP-SHA256" : "WPA-EAP";
- if (wpa_config_set(ssid, "key_mgmt", key_mgmt, 0) < 0)
- return -1;
- if (wpa_config_set(ssid, "proto", "RSN", 0) < 0)
- return -1;
- if (wpa_config_set(ssid, "pairwise", "CCMP", 0) < 0)
+ if (wpa_config_set(ssid, "key_mgmt", key_mgmt, 0) < 0 ||
+ wpa_config_set(ssid, "proto", "RSN", 0) < 0 ||
+ wpa_config_set(ssid, "pairwise", "CCMP", 0) < 0)
return -1;
return 0;
}
* OI #1, [OI #2], [OI #3]
*/
- if (pos + 2 > end)
+ if (end - pos < 2)
return 0;
pos++; /* skip Number of ANQP OIs */
lens = *pos++;
- if (pos + (lens & 0x0f) + (lens >> 4) > end)
+ if ((lens & 0x0f) + (lens >> 4) > end - pos)
return 0;
if ((lens & 0x0f) == rc_len && os_memcmp(pos, rc_id, rc_len) == 0)
/* Set of <OI Length, OI> duples */
while (pos < end) {
len = *pos++;
- if (pos + len > end)
+ if (len > end - pos)
break;
if (len == rc_len && os_memcmp(pos, rc_id, rc_len) == 0)
return 1;
static int cred_below_min_backhaul(struct wpa_supplicant *wpa_s,
struct wpa_cred *cred, struct wpa_bss *bss)
{
+#ifdef CONFIG_HS20
int res;
unsigned int dl_bandwidth, ul_bandwidth;
const u8 *wan;
if (cred->min_ul_bandwidth_roaming > ul_bandwidth)
return 1;
}
+#endif /* CONFIG_HS20 */
return 0;
}
}
+#ifdef CONFIG_HS20
+
static int has_proto_match(const u8 *pos, const u8 *end, u8 proto)
{
- while (pos + 4 <= end) {
+ while (end - pos >= 4) {
if (pos[0] == proto && pos[3] == 1 /* Open */)
return 1;
pos += 4;
static int has_proto_port_match(const u8 *pos, const u8 *end, u8 proto,
u16 port)
{
- while (pos + 4 <= end) {
+ while (end - pos >= 4) {
if (pos[0] == proto && WPA_GET_LE16(&pos[1]) == port &&
pos[3] == 1 /* Open */)
return 1;
return 0;
}
+#endif /* CONFIG_HS20 */
+
static int cred_conn_capab_missing(struct wpa_supplicant *wpa_s,
struct wpa_cred *cred, struct wpa_bss *bss)
{
+#ifdef CONFIG_HS20
int res;
const u8 *capab, *end;
unsigned int i, j;
}
}
}
+#endif /* CONFIG_HS20 */
return 0;
}
os_free(anon);
}
- if (cred->username && cred->username[0] &&
+ if (!ttls && cred->username && cred->username[0] && cred->realm &&
+ !os_strchr(cred->username, '@')) {
+ char *id;
+ size_t buflen;
+ int res;
+
+ buflen = os_strlen(cred->username) + 1 +
+ os_strlen(cred->realm) + 1;
+
+ id = os_malloc(buflen);
+ if (!id)
+ return -1;
+ os_snprintf(id, buflen, "%s@%s", cred->username, cred->realm);
+ res = wpa_config_set_quoted(ssid, "identity", id);
+ os_free(id);
+ if (res < 0)
+ return -1;
+ } else if (cred->username && cred->username[0] &&
wpa_config_set_quoted(ssid, "identity", cred->username) < 0)
return -1;
}
-static int interworking_connect_helper(struct wpa_supplicant *wpa_s,
- struct wpa_bss *bss, int allow_excluded,
- int only_add)
+int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
+ int only_add)
{
struct wpa_cred *cred, *cred_rc, *cred_3gpp;
struct wpa_ssid *ssid;
struct nai_realm_eap *eap = NULL;
u16 count, i;
char buf[100];
- int excluded = 0, *excl = allow_excluded ? &excluded : NULL;
+ int excluded = 0, *excl = &excluded;
const char *name;
if (wpa_s->conf->cred == NULL || bss == NULL)
}
wpa_printf(MSG_DEBUG, "Interworking: Considering BSS " MACSTR
- " for connection (allow_excluded=%d)",
- MAC2STR(bss->bssid), allow_excluded);
+ " for connection",
+ MAC2STR(bss->bssid));
if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) {
/*
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: Highest roaming consortium matching credential priority %d sp_priority %d",
cred_rc->priority, cred_rc->sp_priority);
- if (allow_excluded && excl && !(*excl))
+ if (excl && !(*excl))
excl = NULL;
}
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: Highest NAI Realm list matching credential priority %d sp_priority %d",
cred->priority, cred->sp_priority);
- if (allow_excluded && excl && !(*excl))
+ if (excl && !(*excl))
excl = NULL;
}
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: Highest 3GPP matching credential priority %d sp_priority %d",
cred_3gpp->priority, cred_3gpp->sp_priority);
- if (allow_excluded && excl && !(*excl))
+ if (excl && !(*excl))
excl = NULL;
}
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: Highest roaming consortium matching credential priority %d sp_priority %d (ignore BW)",
cred_rc->priority, cred_rc->sp_priority);
- if (allow_excluded && excl && !(*excl))
+ if (excl && !(*excl))
excl = NULL;
}
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: Highest NAI Realm list matching credential priority %d sp_priority %d (ignore BW)",
cred->priority, cred->sp_priority);
- if (allow_excluded && excl && !(*excl))
+ if (excl && !(*excl))
excl = NULL;
}
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: Highest 3GPP matching credential priority %d sp_priority %d (ignore BW)",
cred_3gpp->priority, cred_3gpp->sp_priority);
- if (allow_excluded && excl && !(*excl))
+ if (excl && !(*excl))
excl = NULL;
}
}
}
-int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
- int only_add)
-{
- return interworking_connect_helper(wpa_s, bss, 1, only_add);
-}
-
-
#ifdef PCSC_FUNCS
static int interworking_pcsc_read_imsi(struct wpa_supplicant *wpa_s)
{
pos = wpabuf_head(domain_names);
end = pos + wpabuf_len(domain_names);
- while (pos + 1 < end) {
- if (pos + 1 + pos[0] > end)
+ while (end - pos > 1) {
+ u8 elen;
+
+ elen = *pos++;
+ if (elen > end - pos)
break;
wpa_hexdump_ascii(MSG_DEBUG, "Interworking: AP domain name",
- pos + 1, pos[0]);
- if (pos[0] == len &&
- os_strncasecmp(domain, (const char *) (pos + 1), len) == 0)
+ pos, elen);
+ if (elen == len &&
+ os_strncasecmp(domain, (const char *) pos, len) == 0)
return 1;
- if (!exact_match && pos[0] > len && pos[pos[0] - len] == '.') {
- const char *ap = (const char *) (pos + 1);
- int offset = pos[0] - len;
+ if (!exact_match && elen > len && pos[elen - len - 1] == '.') {
+ const char *ap = (const char *) pos;
+ int offset = elen - len;
+
if (os_strncasecmp(domain, ap + offset, len) == 0)
return 1;
}
- pos += 1 + pos[0];
+ pos += elen;
}
return 0;
return;
}
+#ifdef CONFIG_HS20
if (wpa_s->fetch_osu_icon_in_progress) {
wpa_printf(MSG_DEBUG, "Interworking: Next icon (in progress)");
hs20_next_osu_icon(wpa_s);
return;
}
+#endif /* CONFIG_HS20 */
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
if (!(bss->caps & IEEE80211_CAP_ESS))
}
if (found == 0) {
+#ifdef CONFIG_HS20
if (wpa_s->fetch_osu_info) {
if (wpa_s->num_prov_found == 0 &&
wpa_s->fetch_osu_waiting_scan &&
hs20_osu_icon_fetch(wpa_s);
return;
}
+#endif /* CONFIG_HS20 */
wpa_msg(wpa_s, MSG_INFO, "ANQP fetch completed");
wpa_s->fetch_anqp_in_progress = 0;
if (wpa_s->network_select)
int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
- u16 info_ids[], size_t num_ids, u32 subtypes)
+ u16 info_ids[], size_t num_ids, u32 subtypes,
+ int get_cell_pref)
{
struct wpabuf *buf;
- struct wpabuf *hs20_buf = NULL;
+ struct wpabuf *extra_buf = NULL;
int ret = 0;
int freq;
struct wpa_bss *bss;
#ifdef CONFIG_HS20
if (subtypes != 0) {
- hs20_buf = wpabuf_alloc(100);
- if (hs20_buf == NULL)
+ extra_buf = wpabuf_alloc(100);
+ if (extra_buf == NULL)
return -1;
- hs20_put_anqp_req(subtypes, NULL, 0, hs20_buf);
+ hs20_put_anqp_req(subtypes, NULL, 0, extra_buf);
}
#endif /* CONFIG_HS20 */
- buf = anqp_build_req(info_ids, num_ids, hs20_buf);
- wpabuf_free(hs20_buf);
+#ifdef CONFIG_MBO
+ if (get_cell_pref) {
+ struct wpabuf *mbo;
+
+ mbo = mbo_build_anqp_buf(wpa_s, bss);
+ if (mbo) {
+ if (wpabuf_resize(&extra_buf, wpabuf_len(mbo))) {
+ wpabuf_free(extra_buf);
+ return -1;
+ }
+ wpabuf_put_buf(extra_buf, mbo);
+ wpabuf_free(mbo);
+ }
+ }
+#endif /* CONFIG_MBO */
+
+ buf = anqp_build_req(info_ids, num_ids, extra_buf);
+ wpabuf_free(extra_buf);
if (buf == NULL)
return -1;
}
+static void anqp_add_extra(struct wpa_supplicant *wpa_s,
+ struct wpa_bss_anqp *anqp, u16 info_id,
+ const u8 *data, size_t slen)
+{
+ struct wpa_bss_anqp_elem *tmp, *elem = NULL;
+
+ if (!anqp)
+ return;
+
+ dl_list_for_each(tmp, &anqp->anqp_elems, struct wpa_bss_anqp_elem,
+ list) {
+ if (tmp->infoid == info_id) {
+ elem = tmp;
+ break;
+ }
+ }
+
+ if (!elem) {
+ elem = os_zalloc(sizeof(*elem));
+ if (!elem)
+ return;
+ elem->infoid = info_id;
+ dl_list_add(&anqp->anqp_elems, &elem->list);
+ } else {
+ wpabuf_free(elem->payload);
+ }
+
+ elem->payload = wpabuf_alloc_copy(data, slen);
+ if (!elem->payload) {
+ dl_list_del(&elem->list);
+ os_free(elem);
+ }
+}
+
+
static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss, const u8 *sa,
u16 info_id,
- const u8 *data, size_t slen)
+ const u8 *data, size_t slen,
+ u8 dialog_token)
{
const u8 *pos = data;
struct wpa_bss_anqp *anqp = NULL;
switch (info_id) {
case ANQP_CAPABILITY_LIST:
- wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
" ANQP Capability list", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Capability list",
pos, slen);
}
break;
case ANQP_VENUE_NAME:
- wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
" Venue Name", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Venue Name", pos, slen);
if (anqp) {
}
break;
case ANQP_NETWORK_AUTH_TYPE:
- wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
" Network Authentication Type information",
MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Network Authentication "
}
break;
case ANQP_ROAMING_CONSORTIUM:
- wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
" Roaming Consortium list", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Roaming Consortium",
pos, slen);
}
break;
case ANQP_IP_ADDR_TYPE_AVAILABILITY:
- wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
" IP Address Type Availability information",
MAC2STR(sa));
wpa_hexdump(MSG_MSGDUMP, "ANQP: IP Address Availability",
}
break;
case ANQP_NAI_REALM:
- wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
" NAI Realm list", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "ANQP: NAI Realm", pos, slen);
if (anqp) {
}
break;
case ANQP_3GPP_CELLULAR_NETWORK:
- wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
" 3GPP Cellular Network information", MAC2STR(sa));
wpa_hexdump_ascii(MSG_DEBUG, "ANQP: 3GPP Cellular Network",
pos, slen);
}
break;
case ANQP_DOMAIN_NAME:
- wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+ wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
" Domain Name list", MAC2STR(sa));
wpa_hexdump_ascii(MSG_MSGDUMP, "ANQP: Domain Name", pos, slen);
if (anqp) {
switch (type) {
case HS20_ANQP_OUI_TYPE:
hs20_parse_rx_hs20_anqp_resp(wpa_s, bss, sa,
- pos, slen);
+ pos, slen,
+ dialog_token);
break;
default:
wpa_msg(wpa_s, MSG_DEBUG,
default:
wpa_msg(wpa_s, MSG_DEBUG,
"Interworking: Unsupported ANQP Info ID %u", info_id);
+ anqp_add_extra(wpa_s, anqp, info_id, data, slen);
break;
}
}
" dialog_token=%u result=%d status_code=%u",
MAC2STR(dst), dialog_token, result, status_code);
if (result != GAS_QUERY_SUCCESS) {
+#ifdef CONFIG_HS20
if (wpa_s->fetch_osu_icon_in_progress)
hs20_icon_fetch_failed(wpa_s);
+#endif /* CONFIG_HS20 */
anqp_result = "FAILURE";
goto out;
}
pos[1] < 2 || pos[3] != ACCESS_NETWORK_QUERY_PROTOCOL) {
wpa_msg(wpa_s, MSG_DEBUG,
"ANQP: Unexpected Advertisement Protocol in response");
+#ifdef CONFIG_HS20
if (wpa_s->fetch_osu_icon_in_progress)
hs20_icon_fetch_failed(wpa_s);
+#endif /* CONFIG_HS20 */
anqp_result = "INVALID_FRAME";
goto out;
}
goto out_parse_done;
}
interworking_parse_rx_anqp_resp(wpa_s, bss, dst, info_id, pos,
- slen);
+ slen, dialog_token);
pos += slen;
}
out_parse_done:
+#ifdef CONFIG_HS20
hs20_notify_parse_done(wpa_s);
+#endif /* CONFIG_HS20 */
out:
wpa_msg(wpa_s, MSG_INFO, ANQP_QUERY_DONE "addr=" MACSTR " result=%s",
MAC2STR(dst), anqp_result);
enum gas_query_result;
int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
- u16 info_ids[], size_t num_ids, u32 subtypes);
+ u16 info_ids[], size_t num_ids, u32 subtypes,
+ int get_cell_pref);
void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token,
enum gas_query_result result,
const struct wpabuf *adv_proto,
" -B = run daemon in the background\n"
" -c = Configuration file\n"
" -C = ctrl_interface parameter (only used if -c is not)\n"
- " -i = interface name\n"
- " -I = additional configuration file\n"
" -d = increase debugging verbosity (-dd even more)\n"
" -D = driver name (can be multiple drivers: nl80211,wext)\n"
- " -e = entropy file\n");
+ " -e = entropy file\n"
#ifdef CONFIG_DEBUG_FILE
- printf(" -f = log output to debug file instead of stdout\n");
+ " -f = log output to debug file instead of stdout\n"
#endif /* CONFIG_DEBUG_FILE */
- printf(" -g = global ctrl_interface\n"
+ " -g = global ctrl_interface\n"
" -G = global ctrl_interface group\n"
- " -K = include keys (passwords, etc.) in debug output\n");
-#ifdef CONFIG_DEBUG_SYSLOG
- printf(" -s = log output to syslog instead of stdout\n");
-#endif /* CONFIG_DEBUG_SYSLOG */
-#ifdef CONFIG_DEBUG_LINUX_TRACING
- printf(" -T = record to Linux tracing in addition to logging\n");
- printf(" (records all messages regardless of debug verbosity)\n");
-#endif /* CONFIG_DEBUG_LINUX_TRACING */
- printf(" -t = include timestamp in debug messages\n"
" -h = show this help text\n"
+ " -i = interface name\n"
+ " -I = additional configuration file\n"
+ " -K = include keys (passwords, etc.) in debug output\n"
" -L = show license (BSD)\n"
+#ifdef CONFIG_P2P
+ " -m = Configuration file for the P2P Device interface\n"
+#endif /* CONFIG_P2P */
+#ifdef CONFIG_MATCH_IFACE
+ " -M = start describing new matching interface\n"
+#endif /* CONFIG_MATCH_IFACE */
+ " -N = start describing new interface\n"
" -o = override driver parameter for new interfaces\n"
" -O = override ctrl_interface parameter for new interfaces\n"
" -p = driver parameters\n"
" -P = PID file\n"
- " -q = decrease debugging verbosity (-qq even less)\n");
+ " -q = decrease debugging verbosity (-qq even less)\n"
+#ifdef CONFIG_DEBUG_SYSLOG
+ " -s = log output to syslog instead of stdout\n"
+#endif /* CONFIG_DEBUG_SYSLOG */
+ " -t = include timestamp in debug messages\n"
+#ifdef CONFIG_DEBUG_LINUX_TRACING
+ " -T = record to Linux tracing in addition to logging\n"
+ " (records all messages regardless of debug verbosity)\n"
+#endif /* CONFIG_DEBUG_LINUX_TRACING */
#ifdef CONFIG_DBUS
- printf(" -u = enable DBus control interface\n");
+ " -u = enable DBus control interface\n"
#endif /* CONFIG_DBUS */
- printf(" -v = show version\n"
- " -W = wait for a control interface monitor before starting\n"
-#ifdef CONFIG_P2P
- " -m = Configuration file for the P2P Device interface\n"
-#endif /* CONFIG_P2P */
- " -N = start describing new interface\n");
+ " -v = show version\n"
+ " -W = wait for a control interface monitor before starting\n");
printf("example:\n"
" wpa_supplicant -D%s -iwlan0 -c/etc/wpa_supplicant.conf\n",
}
+#ifdef CONFIG_MATCH_IFACE
+static int wpa_supplicant_init_match(struct wpa_global *global)
+{
+ /*
+ * The assumption is that the first driver is the primary driver and
+ * will handle the arrival / departure of interfaces.
+ */
+ if (wpa_drivers[0]->global_init && !global->drv_priv[0]) {
+ global->drv_priv[0] = wpa_drivers[0]->global_init(global);
+ if (!global->drv_priv[0]) {
+ wpa_printf(MSG_ERROR,
+ "Failed to initialize driver '%s'",
+ wpa_drivers[0]->name);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+#endif /* CONFIG_MATCH_IFACE */
+
+
int main(int argc, char *argv[])
{
int c, i;
for (;;) {
c = getopt(argc, argv,
- "b:Bc:C:D:de:f:g:G:hi:I:KLm:No:O:p:P:qsTtuvW");
+ "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW");
if (c < 0)
break;
switch (c) {
case 'W':
params.wait_for_monitor++;
break;
+#ifdef CONFIG_MATCH_IFACE
+ case 'M':
+ params.match_iface_count++;
+ iface = os_realloc_array(params.match_ifaces,
+ params.match_iface_count,
+ sizeof(struct wpa_interface));
+ if (!iface)
+ goto out;
+ params.match_ifaces = iface;
+ iface = ¶ms.match_ifaces[params.match_iface_count -
+ 1];
+ os_memset(iface, 0, sizeof(*iface));
+ break;
+#endif /* CONFIG_MATCH_IFACE */
case 'N':
iface_count++;
iface = os_realloc_array(ifaces, iface_count,
ifaces[i].ctrl_interface == NULL) ||
ifaces[i].ifname == NULL) {
if (iface_count == 1 && (params.ctrl_interface ||
+#ifdef CONFIG_MATCH_IFACE
+ params.match_iface_count ||
+#endif /* CONFIG_MATCH_IFACE */
params.dbus_ctrl_interface))
break;
usage();
}
}
+#ifdef CONFIG_MATCH_IFACE
+ if (exitcode == 0)
+ exitcode = wpa_supplicant_init_match(global);
+#endif /* CONFIG_MATCH_IFACE */
+
if (exitcode == 0)
exitcode = wpa_supplicant_run(global);
out:
wpa_supplicant_fd_workaround(0);
os_free(ifaces);
+#ifdef CONFIG_MATCH_IFACE
+ os_free(params.match_ifaces);
+#endif /* CONFIG_MATCH_IFACE */
os_free(params.pid_file);
os_program_deinit();
}
-static struct mesh_conf * mesh_config_create(struct wpa_ssid *ssid)
+static struct mesh_conf * mesh_config_create(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
{
struct mesh_conf *conf;
+ int cipher;
conf = os_zalloc(sizeof(struct mesh_conf));
if (!conf)
MESH_CONF_SEC_AMPE;
else
conf->security |= MESH_CONF_SEC_NONE;
+ conf->ieee80211w = ssid->ieee80211w;
+ if (conf->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) {
+ if (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)
+ conf->ieee80211w = wpa_s->conf->pmf;
+ else
+ conf->ieee80211w = NO_MGMT_FRAME_PROTECTION;
+ }
+
+ cipher = wpa_pick_pairwise_cipher(ssid->pairwise_cipher, 0);
+ if (cipher < 0 || cipher == WPA_CIPHER_TKIP) {
+ wpa_msg(wpa_s, MSG_INFO, "mesh: Invalid pairwise cipher");
+ os_free(conf);
+ return NULL;
+ }
+ conf->pairwise_cipher = cipher;
+
+ cipher = wpa_pick_group_cipher(ssid->group_cipher);
+ if (cipher < 0 || cipher == WPA_CIPHER_TKIP ||
+ cipher == WPA_CIPHER_GTK_NOT_USED) {
+ wpa_msg(wpa_s, MSG_INFO, "mesh: Invalid group cipher");
+ os_free(conf);
+ return NULL;
+ }
+
+ conf->group_cipher = cipher;
+ if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION)
+ conf->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
/* defaults */
conf->mesh_pp_id = MESH_PATH_PROTOCOL_HWMP;
ifmsh->bss[0] = bss = os_zalloc(sizeof(struct hostapd_data));
if (!bss)
goto out_free;
+ dl_list_init(&bss->nr_db);
os_memcpy(bss->own_addr, wpa_s->own_addr, ETH_ALEN);
bss->driver = wpa_s->driver;
wpa_s->conf->dot11RSNASAERetransPeriod;
os_strlcpy(bss->conf->iface, wpa_s->ifname, sizeof(bss->conf->iface));
- mconf = mesh_config_create(ssid);
+ mconf = mesh_config_create(wpa_s, ssid);
if (!mconf)
goto out_free;
ifmsh->mconf = mconf;
/* need conf->hw_mode for supported rates. */
- if (ssid->frequency == 0) {
- conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
- conf->channel = 1;
- } else {
- conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency,
- &conf->channel);
- }
+ conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency, &conf->channel);
if (conf->hw_mode == NUM_HOSTAPD_MODES) {
wpa_printf(MSG_ERROR, "Unsupported mesh mode frequency: %d MHz",
ssid->frequency);
goto out_free;
}
+ if (ssid->ht40)
+ conf->secondary_channel = ssid->ht40;
+ if (conf->hw_mode == HOSTAPD_MODE_IEEE80211A && ssid->vht) {
+ conf->vht_oper_chwidth = ssid->max_oper_chwidth;
+ switch (conf->vht_oper_chwidth) {
+ case VHT_CHANWIDTH_80MHZ:
+ case VHT_CHANWIDTH_80P80MHZ:
+ ieee80211_freq_to_chan(
+ ssid->frequency,
+ &conf->vht_oper_centr_freq_seg0_idx);
+ conf->vht_oper_centr_freq_seg0_idx += ssid->ht40 * 2;
+ break;
+ case VHT_CHANWIDTH_160MHZ:
+ ieee80211_freq_to_chan(
+ ssid->frequency,
+ &conf->vht_oper_centr_freq_seg0_idx);
+ conf->vht_oper_centr_freq_seg0_idx += ssid->ht40 * 2;
+ conf->vht_oper_centr_freq_seg0_idx += 40 / 5;
+ break;
+ }
+ ieee80211_freq_to_chan(ssid->vht_center_freq2,
+ &conf->vht_oper_centr_freq_seg1_idx);
+ }
if (ssid->mesh_basic_rates == NULL) {
/*
wpa_supplicant_mesh_deinit(wpa_s);
+ wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
+ wpa_s->group_cipher = WPA_CIPHER_NONE;
+ wpa_s->mgmt_group_cipher = 0;
+
os_memset(¶ms, 0, sizeof(params));
params.meshid = ssid->ssid;
params.meshid_len = ssid->ssid_len;
ibss_mesh_setup_freq(wpa_s, ssid, ¶ms.freq);
wpa_s->mesh_ht_enabled = !!params.freq.ht_enabled;
+ wpa_s->mesh_vht_enabled = !!params.freq.vht_enabled;
+ if (params.freq.ht_enabled && params.freq.sec_channel_offset)
+ ssid->ht40 = params.freq.sec_channel_offset;
+ if (wpa_s->mesh_vht_enabled) {
+ ssid->vht = 1;
+ switch (params.freq.bandwidth) {
+ case 80:
+ if (params.freq.center_freq2) {
+ ssid->max_oper_chwidth = VHT_CHANWIDTH_80P80MHZ;
+ ssid->vht_center_freq2 =
+ params.freq.center_freq2;
+ } else {
+ ssid->max_oper_chwidth = VHT_CHANWIDTH_80MHZ;
+ }
+ break;
+ case 160:
+ ssid->max_oper_chwidth = VHT_CHANWIDTH_160MHZ;
+ break;
+ default:
+ ssid->max_oper_chwidth = VHT_CHANWIDTH_USE_HT;
+ break;
+ }
+ }
if (ssid->beacon_int > 0)
params.beacon_int = ssid->beacon_int;
else if (wpa_s->conf->beacon_int > 0)
params.beacon_int = wpa_s->conf->beacon_int;
- params.max_peer_links = wpa_s->conf->max_peer_links;
+ if (ssid->dtim_period > 0)
+ params.dtim_period = ssid->dtim_period;
+ else if (wpa_s->conf->dtim_period > 0)
+ params.dtim_period = wpa_s->conf->dtim_period;
+ params.conf.max_peer_links = wpa_s->conf->max_peer_links;
if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
params.flags |= WPA_DRIVER_MESH_FLAG_SAE_AUTH;
if (wpa_s->conf->user_mpm) {
params.flags |= WPA_DRIVER_MESH_FLAG_USER_MPM;
- params.conf.flags &= ~WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS;
+ params.conf.auto_plinks = 0;
} else {
params.flags |= WPA_DRIVER_MESH_FLAG_DRIVER_MPM;
- params.conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS;
+ params.conf.auto_plinks = 1;
}
params.conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity;
goto out;
}
+ if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
+ wpa_s->pairwise_cipher = wpa_s->mesh_rsn->pairwise_cipher;
+ wpa_s->group_cipher = wpa_s->mesh_rsn->group_cipher;
+ wpa_s->mgmt_group_cipher = wpa_s->mesh_rsn->mgmt_group_cipher;
+ }
+
if (wpa_s->ifmsh) {
params.ies = wpa_s->ifmsh->mconf->rsn_ie;
params.ie_len = wpa_s->ifmsh->mconf->rsn_ie_len;
params.basic_rates = wpa_s->ifmsh->basic_rates;
+ params.conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE;
+ params.conf.ht_opmode = wpa_s->ifmsh->bss[0]->iface->ht_op_mode;
}
wpa_msg(wpa_s, MSG_INFO, "joining mesh %s",
wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
ret = wpa_drv_join_mesh(wpa_s, ¶ms);
if (ret)
- wpa_msg(wpa_s, MSG_ERROR, "mesh join error=%d\n", ret);
+ wpa_msg(wpa_s, MSG_ERROR, "mesh join error=%d", ret);
/* hostapd sets the interface down until we associate */
wpa_drv_set_operstate(wpa_s, 1);
+ if (!ret)
+ wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
+
out:
return ret;
}
if (!mesh_wpa_s) {
wpa_printf(MSG_ERROR,
"mesh: Failed to create new wpa_supplicant interface");
- wpa_supplicant_remove_iface(wpa_s->global, wpa_s, 0);
+ wpa_drv_if_remove(wpa_s, WPA_IF_MESH, ifname);
return -1;
}
mesh_wpa_s->mesh_if_created = 1;
return 0;
}
+
+
+int wpas_mesh_peer_remove(struct wpa_supplicant *wpa_s, const u8 *addr)
+{
+ return mesh_mpm_close_peer(wpa_s, addr);
+}
+
+
+int wpas_mesh_peer_add(struct wpa_supplicant *wpa_s, const u8 *addr,
+ int duration)
+{
+ return mesh_mpm_connect_peer(wpa_s, addr, duration);
+}
char *end);
int wpas_mesh_add_interface(struct wpa_supplicant *wpa_s, char *ifname,
size_t len);
+int wpas_mesh_peer_remove(struct wpa_supplicant *wpa_s, const u8 *addr);
+int wpas_mesh_peer_add(struct wpa_supplicant *wpa_s, const u8 *addr,
+ int duration);
#ifdef CONFIG_MESH
#include "ap/hostapd.h"
#include "ap/sta_info.h"
#include "ap/ieee802_11.h"
+#include "ap/wpa_auth.h"
#include "wpa_supplicant_i.h"
#include "driver_i.h"
#include "mesh_mpm.h"
#include "mesh_rsn.h"
struct mesh_peer_mgmt_ie {
- const u8 *proto_id;
- const u8 *llid;
- const u8 *plid;
- const u8 *reason;
- const u8 *pmk;
+ const u8 *proto_id; /* Mesh Peering Protocol Identifier (2 octets) */
+ const u8 *llid; /* Local Link ID (2 octets) */
+ const u8 *plid; /* Peer Link ID (conditional, 2 octets) */
+ const u8 *reason; /* Reason Code (conditional, 2 octets) */
+ const u8 *chosen_pmk; /* Chosen PMK (optional, 16 octets) */
};
static void plink_timer(void *eloop_ctx, void *user_data);
PLINK_UNDEFINED,
OPN_ACPT,
OPN_RJCT,
- OPN_IGNR,
CNF_ACPT,
CNF_RJCT,
- CNF_IGNR,
CLS_ACPT,
- CLS_IGNR
+ REQ_RJCT
};
static const char * const mplstate[] = {
- [PLINK_LISTEN] = "LISTEN",
- [PLINK_OPEN_SENT] = "OPEN_SENT",
- [PLINK_OPEN_RCVD] = "OPEN_RCVD",
+ [0] = "UNINITIALIZED",
+ [PLINK_IDLE] = "IDLE",
+ [PLINK_OPN_SNT] = "OPN_SNT",
+ [PLINK_OPN_RCVD] = "OPN_RCVD",
[PLINK_CNF_RCVD] = "CNF_RCVD",
[PLINK_ESTAB] = "ESTAB",
[PLINK_HOLDING] = "HOLDING",
[PLINK_UNDEFINED] = "UNDEFINED",
[OPN_ACPT] = "OPN_ACPT",
[OPN_RJCT] = "OPN_RJCT",
- [OPN_IGNR] = "OPN_IGNR",
[CNF_ACPT] = "CNF_ACPT",
[CNF_RJCT] = "CNF_RJCT",
- [CNF_IGNR] = "CNF_IGNR",
[CLS_ACPT] = "CLS_ACPT",
- [CLS_IGNR] = "CLS_IGNR"
+ [REQ_RJCT] = "REQ_RJCT",
};
{
os_memset(mpm_ie, 0, sizeof(*mpm_ie));
- /* remove optional PMK at end */
- if (len >= 16) {
- len -= 16;
- mpm_ie->pmk = ie + len - 16;
+ /* Remove optional Chosen PMK field at end */
+ if (len >= SAE_PMKID_LEN) {
+ mpm_ie->chosen_pmk = ie + len - SAE_PMKID_LEN;
+ len -= SAE_PMKID_LEN;
}
if ((action_field == PLINK_OPEN && len != 4) ||
len -= 2;
}
- /* plid, present for confirm, and possibly close */
- if (len)
+ /* Peer Link ID, present for confirm, and possibly close */
+ if (len >= 2)
mpm_ie->plid = ie;
return 0;
sta->my_lid = llid;
sta->peer_lid = 0;
+ sta->peer_aid = 0;
/*
* We do not use wpa_mesh_set_plink_state() here because there is no
* entry in kernel yet.
*/
- sta->plink_state = PLINK_LISTEN;
+ sta->plink_state = PLINK_IDLE;
}
struct hostapd_data *bss = ifmsh->bss[0];
struct mesh_conf *conf = ifmsh->mconf;
u8 supp_rates[2 + 2 + 32];
-#ifdef CONFIG_IEEE80211N
- u8 ht_capa_oper[2 + 26 + 2 + 22];
-#endif /* CONFIG_IEEE80211N */
u8 *pos, *cat;
u8 ie_len, add_plid = 0;
int ret;
2 + 22; /* HT operation */
}
#endif /* CONFIG_IEEE80211N */
+#ifdef CONFIG_IEEE80211AC
+ if (type != PLINK_CLOSE && wpa_s->mesh_vht_enabled) {
+ buf_len += 2 + 12 + /* VHT Capabilities */
+ 2 + 5; /* VHT Operation */
+ }
+#endif /* CONFIG_IEEE80211AC */
if (type != PLINK_CLOSE)
buf_len += conf->rsn_ie_len; /* RSN IE */
/* aid */
if (type == PLINK_CONFIRM)
- wpabuf_put_le16(buf, sta->peer_lid);
+ wpabuf_put_le16(buf, sta->aid);
/* IE: supp + ext. supp rates */
pos = hostapd_eid_supp_rates(bss, supp_rates);
/* TODO: Add Connected to Mesh Gate/AS subfields */
wpabuf_put_u8(buf, info);
/* always forwarding & accepting plinks for now */
- wpabuf_put_u8(buf, 0x1 | 0x8);
+ wpabuf_put_u8(buf, MESH_CAP_ACCEPT_ADDITIONAL_PEER |
+ MESH_CAP_FORWARDING);
} else { /* Peer closing frame */
/* IE: Mesh ID */
wpabuf_put_u8(buf, WLAN_EID_MESH_ID);
#ifdef CONFIG_IEEE80211N
if (type != PLINK_CLOSE && wpa_s->mesh_ht_enabled) {
+ u8 ht_capa_oper[2 + 26 + 2 + 22];
+
pos = hostapd_eid_ht_capabilities(bss, ht_capa_oper);
pos = hostapd_eid_ht_operation(bss, pos);
wpabuf_put_data(buf, ht_capa_oper, pos - ht_capa_oper);
}
#endif /* CONFIG_IEEE80211N */
+#ifdef CONFIG_IEEE80211AC
+ if (type != PLINK_CLOSE && wpa_s->mesh_vht_enabled) {
+ u8 vht_capa_oper[2 + 12 + 2 + 5];
+
+ pos = hostapd_eid_vht_capabilities(bss, vht_capa_oper, 0);
+ pos = hostapd_eid_vht_operation(bss, pos);
+ wpabuf_put_data(buf, vht_capa_oper, pos - vht_capa_oper);
+ }
+#endif /* CONFIG_IEEE80211AC */
if (ampe && mesh_rsn_protect_frame(wpa_s->mesh_rsn, sta, cat, buf)) {
wpa_msg(wpa_s, MSG_INFO,
goto fail;
}
+ wpa_msg(wpa_s, MSG_DEBUG, "Mesh MPM: Sending peering frame type %d to "
+ MACSTR " (my_lid=0x%x peer_lid=0x%x)",
+ type, MAC2STR(sta->addr), sta->my_lid, sta->peer_lid);
ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0,
sta->addr, wpa_s->own_addr, wpa_s->own_addr,
wpabuf_head(buf), wpabuf_len(buf), 0);
struct hostapd_sta_add_params params;
int ret;
+ wpa_msg(wpa_s, MSG_DEBUG, "MPM set " MACSTR " from %s into %s",
+ MAC2STR(sta->addr), mplstate[sta->plink_state],
+ mplstate[state]);
sta->plink_state = state;
os_memset(¶ms, 0, sizeof(params));
params.addr = sta->addr;
params.plink_state = state;
+ params.peer_aid = sta->peer_aid;
params.set = 1;
- wpa_msg(wpa_s, MSG_DEBUG, "MPM set " MACSTR " into %s",
- MAC2STR(sta->addr), mplstate[state]);
ret = wpa_drv_sta_add(wpa_s, ¶ms);
if (ret) {
wpa_msg(wpa_s, MSG_ERROR, "Driver failed to set " MACSTR
struct sta_info *sta = user_data;
u16 reason = 0;
struct mesh_conf *conf = wpa_s->ifmsh->mconf;
+ struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
switch (sta->plink_state) {
- case PLINK_OPEN_RCVD:
- case PLINK_OPEN_SENT:
+ case PLINK_OPN_RCVD:
+ case PLINK_OPN_SNT:
/* retry timer */
if (sta->mpm_retries < conf->dot11MeshMaxRetries) {
eloop_register_timeout(
break;
case PLINK_HOLDING:
/* holding timer */
+
+ if (sta->mesh_sae_pmksa_caching) {
+ wpa_printf(MSG_DEBUG, "MPM: Peer " MACSTR
+ " looks like it does not support mesh SAE PMKSA caching, so remove the cached entry for it",
+ MAC2STR(sta->addr));
+ wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
+ }
mesh_mpm_fsm_restart(wpa_s, sta);
break;
default:
}
-int mesh_mpm_plink_close(struct hostapd_data *hapd,
- struct sta_info *sta, void *ctx)
+static int mesh_mpm_plink_close(struct hostapd_data *hapd, struct sta_info *sta,
+ void *ctx)
{
struct wpa_supplicant *wpa_s = ctx;
int reason = WLAN_REASON_MESH_PEERING_CANCELLED;
}
+int mesh_mpm_close_peer(struct wpa_supplicant *wpa_s, const u8 *addr)
+{
+ struct hostapd_data *hapd;
+ struct sta_info *sta;
+
+ if (!wpa_s->ifmsh) {
+ wpa_msg(wpa_s, MSG_INFO, "Mesh is not prepared yet");
+ return -1;
+ }
+
+ hapd = wpa_s->ifmsh->bss[0];
+ sta = ap_get_sta(hapd, addr);
+ if (!sta) {
+ wpa_msg(wpa_s, MSG_INFO, "No such mesh peer");
+ return -1;
+ }
+
+ return mesh_mpm_plink_close(hapd, sta, wpa_s) == 0 ? 0 : -1;
+}
+
+
+static void peer_add_timer(void *eloop_ctx, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+ struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
+
+ os_memset(hapd->mesh_required_peer, 0, ETH_ALEN);
+}
+
+
+int mesh_mpm_connect_peer(struct wpa_supplicant *wpa_s, const u8 *addr,
+ int duration)
+{
+ struct wpa_ssid *ssid = wpa_s->current_ssid;
+ struct hostapd_data *hapd;
+ struct sta_info *sta;
+ struct mesh_conf *conf;
+
+ if (!wpa_s->ifmsh) {
+ wpa_msg(wpa_s, MSG_INFO, "Mesh is not prepared yet");
+ return -1;
+ }
+
+ if (!ssid || !ssid->no_auto_peer) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "This command is available only with no_auto_peer mesh network");
+ return -1;
+ }
+
+ hapd = wpa_s->ifmsh->bss[0];
+ conf = wpa_s->ifmsh->mconf;
+
+ sta = ap_get_sta(hapd, addr);
+ if (!sta) {
+ wpa_msg(wpa_s, MSG_INFO, "No such mesh peer");
+ return -1;
+ }
+
+ if ((PLINK_OPN_SNT <= sta->plink_state &&
+ sta->plink_state <= PLINK_ESTAB) ||
+ (sta->sae && sta->sae->state > SAE_NOTHING)) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "Specified peer is connecting/connected");
+ return -1;
+ }
+
+ if (conf->security == MESH_CONF_SEC_NONE) {
+ mesh_mpm_plink_open(wpa_s, sta, PLINK_OPN_SNT);
+ } else {
+ mesh_rsn_auth_sae_sta(wpa_s, sta);
+ os_memcpy(hapd->mesh_required_peer, addr, ETH_ALEN);
+ eloop_register_timeout(duration == -1 ? 10 : duration, 0,
+ peer_add_timer, wpa_s, NULL);
+ }
+
+ return 0;
+}
+
+
void mesh_mpm_deinit(struct wpa_supplicant *wpa_s, struct hostapd_iface *ifmsh)
{
struct hostapd_data *hapd = ifmsh->bss[0];
hapd->num_plinks = 0;
hostapd_free_stas(hapd);
+ eloop_cancel_timeout(peer_add_timer, wpa_s, NULL);
}
if (!sta->my_lid)
mesh_mpm_init_link(wpa_s, sta);
- mesh_mpm_plink_open(wpa_s, sta, PLINK_OPEN_SENT);
+ mesh_mpm_plink_open(wpa_s, sta, PLINK_OPN_SNT);
}
/*
struct sta_info *sta;
int ret;
+ if (elems->mesh_config_len >= 7 &&
+ !(elems->mesh_config[6] & MESH_CAP_ACCEPT_ADDITIONAL_PEER)) {
+ wpa_msg(wpa_s, MSG_DEBUG,
+ "mesh: Ignore a crowded peer " MACSTR,
+ MAC2STR(addr));
+ return NULL;
+ }
+
sta = ap_get_sta(data, addr);
if (!sta) {
sta = ap_sta_add(data, addr);
return NULL;
}
+ /* Set WMM by default since Mesh STAs are QoS STAs */
+ sta->flags |= WLAN_STA_WMM;
+
/* initialize sta */
if (copy_supp_rates(wpa_s, sta, elems)) {
ap_free_sta(data, sta);
return NULL;
}
- mesh_mpm_init_link(wpa_s, sta);
+ if (!sta->my_lid)
+ mesh_mpm_init_link(wpa_s, sta);
#ifdef CONFIG_IEEE80211N
copy_sta_ht_capab(data, sta, elems->ht_capabilities);
update_ht_state(data, sta);
#endif /* CONFIG_IEEE80211N */
+#ifdef CONFIG_IEEE80211AC
+ copy_sta_vht_capab(data, sta, elems->vht_capabilities);
+ set_sta_vht_opmode(data, sta, elems->vht_opmode_notif);
+#endif /* CONFIG_IEEE80211AC */
+
+ if (hostapd_get_aid(data, sta) < 0) {
+ wpa_msg(wpa_s, MSG_ERROR, "No AIDs available");
+ ap_free_sta(data, sta);
+ return NULL;
+ }
+
/* insert into driver */
os_memset(¶ms, 0, sizeof(params));
params.supp_rates = sta->supported_rates;
params.supp_rates_len = sta->supported_rates_len;
params.addr = addr;
params.plink_state = sta->plink_state;
- params.aid = sta->peer_lid;
+ params.aid = sta->aid;
+ params.peer_aid = sta->peer_aid;
params.listen_interval = 100;
params.ht_capabilities = sta->ht_capabilities;
+ params.vht_capabilities = sta->vht_capabilities;
params.flags |= WPA_STA_WMM;
params.flags_mask |= WPA_STA_AUTHENTICATED;
if (conf->security == MESH_CONF_SEC_NONE) {
if (!sta)
return;
- if (ssid && ssid->no_auto_peer) {
+ if (ssid && ssid->no_auto_peer &&
+ (is_zero_ether_addr(data->mesh_required_peer) ||
+ os_memcmp(data->mesh_required_peer, addr, ETH_ALEN) != 0)) {
wpa_msg(wpa_s, MSG_INFO, "will not initiate new peer link with "
MACSTR " because of no_auto_peer", MAC2STR(addr));
if (data->mesh_pending_auth) {
return;
}
- if (conf->security == MESH_CONF_SEC_NONE)
- mesh_mpm_plink_open(wpa_s, sta, PLINK_OPEN_SENT);
- else
+ if (conf->security == MESH_CONF_SEC_NONE) {
+ if (sta->plink_state < PLINK_OPN_SNT ||
+ sta->plink_state > PLINK_ESTAB)
+ mesh_mpm_plink_open(wpa_s, sta, PLINK_OPN_SNT);
+ } else {
mesh_rsn_auth_sae_sta(wpa_s, sta);
+ }
}
MAC2STR(sta->addr));
if (conf->security & MESH_CONF_SEC_AMPE) {
- wpa_drv_set_key(wpa_s, WPA_ALG_CCMP, sta->addr, 0, 0,
- seq, sizeof(seq), sta->mtk, sizeof(sta->mtk));
- wpa_drv_set_key(wpa_s, WPA_ALG_CCMP, sta->addr, 1, 0,
- seq, sizeof(seq),
- sta->mgtk, sizeof(sta->mgtk));
- wpa_drv_set_key(wpa_s, WPA_ALG_IGTK, sta->addr, 4, 0,
- seq, sizeof(seq),
- sta->mgtk, sizeof(sta->mgtk));
-
- wpa_hexdump_key(MSG_DEBUG, "mtk:", sta->mtk, sizeof(sta->mtk));
- wpa_hexdump_key(MSG_DEBUG, "mgtk:",
- sta->mgtk, sizeof(sta->mgtk));
+ wpa_hexdump_key(MSG_DEBUG, "mesh: MTK", sta->mtk, sta->mtk_len);
+ wpa_drv_set_key(wpa_s, wpa_cipher_to_alg(conf->pairwise_cipher),
+ sta->addr, 0, 0, seq, sizeof(seq),
+ sta->mtk, sta->mtk_len);
+
+ wpa_hexdump_key(MSG_DEBUG, "mesh: RX MGTK Key RSC",
+ sta->mgtk_rsc, sizeof(sta->mgtk_rsc));
+ wpa_hexdump_key(MSG_DEBUG, "mesh: RX MGTK",
+ sta->mgtk, sta->mgtk_len);
+ wpa_drv_set_key(wpa_s, wpa_cipher_to_alg(conf->group_cipher),
+ sta->addr, sta->mgtk_key_id, 0,
+ sta->mgtk_rsc, sizeof(sta->mgtk_rsc),
+ sta->mgtk, sta->mgtk_len);
+
+ if (sta->igtk_len) {
+ wpa_hexdump_key(MSG_DEBUG, "mesh: RX IGTK Key RSC",
+ sta->igtk_rsc, sizeof(sta->igtk_rsc));
+ wpa_hexdump_key(MSG_DEBUG, "mesh: RX IGTK",
+ sta->igtk, sta->igtk_len);
+ wpa_drv_set_key(
+ wpa_s,
+ wpa_cipher_to_alg(conf->mgmt_group_cipher),
+ sta->addr, sta->igtk_key_id, 0,
+ sta->igtk_rsc, sizeof(sta->igtk_rsc),
+ sta->igtk, sta->igtk_len);
+ }
}
wpa_mesh_set_plink_state(wpa_s, sta, PLINK_ESTAB);
hapd->num_plinks++;
sta->flags |= WLAN_STA_ASSOC;
+ sta->mesh_sae_pmksa_caching = 0;
+ eloop_cancel_timeout(peer_add_timer, wpa_s, NULL);
+ peer_add_timer(wpa_s, NULL);
eloop_cancel_timeout(plink_timer, wpa_s, sta);
/* Send ctrl event */
- wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_PEER_CONNECTED MACSTR,
- MAC2STR(sta->addr));
+ wpa_msg(wpa_s, MSG_INFO, MESH_PEER_CONNECTED MACSTR,
+ MAC2STR(sta->addr));
}
static void mesh_mpm_fsm(struct wpa_supplicant *wpa_s, struct sta_info *sta,
- enum plink_event event)
+ enum plink_event event, u16 reason)
{
struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
struct mesh_conf *conf = wpa_s->ifmsh->mconf;
- u16 reason = 0;
wpa_msg(wpa_s, MSG_DEBUG, "MPM " MACSTR " state %s event %s",
MAC2STR(sta->addr), mplstate[sta->plink_state],
mplevent[event]);
switch (sta->plink_state) {
- case PLINK_LISTEN:
+ case PLINK_IDLE:
switch (event) {
case CLS_ACPT:
mesh_mpm_fsm_restart(wpa_s, sta);
break;
case OPN_ACPT:
- mesh_mpm_plink_open(wpa_s, sta, PLINK_OPEN_RCVD);
+ mesh_mpm_plink_open(wpa_s, sta, PLINK_OPN_RCVD);
mesh_mpm_send_plink_action(wpa_s, sta, PLINK_CONFIRM,
0);
break;
+ case REQ_RJCT:
+ mesh_mpm_send_plink_action(wpa_s, sta,
+ PLINK_CLOSE, reason);
+ break;
default:
break;
}
break;
- case PLINK_OPEN_SENT:
+ case PLINK_OPN_SNT:
switch (event) {
case OPN_RJCT:
case CNF_RJCT:
- reason = WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION;
+ if (!reason)
+ reason = WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION;
/* fall-through */
case CLS_ACPT:
wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING);
break;
case OPN_ACPT:
/* retry timer is left untouched */
- wpa_mesh_set_plink_state(wpa_s, sta, PLINK_OPEN_RCVD);
+ wpa_mesh_set_plink_state(wpa_s, sta, PLINK_OPN_RCVD);
mesh_mpm_send_plink_action(wpa_s, sta,
PLINK_CONFIRM, 0);
break;
case CNF_ACPT:
wpa_mesh_set_plink_state(wpa_s, sta, PLINK_CNF_RCVD);
+ eloop_cancel_timeout(plink_timer, wpa_s, sta);
eloop_register_timeout(
conf->dot11MeshConfirmTimeout / 1000,
(conf->dot11MeshConfirmTimeout % 1000) * 1000,
break;
}
break;
- case PLINK_OPEN_RCVD:
+ case PLINK_OPN_RCVD:
switch (event) {
case OPN_RJCT:
case CNF_RJCT:
- reason = WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION;
+ if (!reason)
+ reason = WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION;
/* fall-through */
case CLS_ACPT:
wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING);
switch (event) {
case OPN_RJCT:
case CNF_RJCT:
- reason = WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION;
+ if (!reason)
+ reason = WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION;
/* fall-through */
case CLS_ACPT:
wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING);
PLINK_CLOSE, reason);
break;
case OPN_ACPT:
+ if (conf->security & MESH_CONF_SEC_AMPE)
+ mesh_rsn_derive_mtk(wpa_s, sta);
mesh_mpm_plink_estab(wpa_s, sta);
mesh_mpm_send_plink_action(wpa_s, sta,
PLINK_CONFIRM, 0);
break;
case PLINK_ESTAB:
switch (event) {
+ case OPN_RJCT:
+ case CNF_RJCT:
case CLS_ACPT:
wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING);
- reason = WLAN_REASON_MESH_CLOSE_RCVD;
+ if (!reason)
+ reason = WLAN_REASON_MESH_CLOSE_RCVD;
eloop_register_timeout(
conf->dot11MeshHoldingTimeout / 1000,
" closed with reason %d",
MAC2STR(sta->addr), reason);
- wpa_msg_ctrl(wpa_s, MSG_INFO,
- MESH_PEER_DISCONNECTED MACSTR,
- MAC2STR(sta->addr));
+ wpa_msg(wpa_s, MSG_INFO, MESH_PEER_DISCONNECTED MACSTR,
+ MAC2STR(sta->addr));
hapd->num_plinks--;
struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
struct mesh_conf *mconf = wpa_s->ifmsh->mconf;
struct sta_info *sta;
- u16 plid = 0, llid = 0;
+ u16 plid = 0, llid = 0, aid = 0;
enum plink_event event;
struct ieee802_11_elems elems;
struct mesh_peer_mgmt_ie peer_mgmt_ie;
const u8 *ies;
size_t ie_len;
int ret;
+ u16 reason = 0;
if (mgmt->u.action.category != WLAN_ACTION_SELF_PROTECTED)
return;
ie_len -= 2;
}
if (action_field == PLINK_CONFIRM) {
- wpa_printf(MSG_DEBUG, "MPM: AID 0x%x", WPA_GET_LE16(ies));
+ aid = WPA_GET_LE16(ies);
+ wpa_printf(MSG_DEBUG, "MPM: AID 0x%x", aid);
ies += 2; /* aid */
ie_len -= 2;
}
llid = WPA_GET_LE16(peer_mgmt_ie.plid);
wpa_printf(MSG_DEBUG, "MPM: plid=0x%x llid=0x%x", plid, llid);
+ if (action_field == PLINK_CLOSE)
+ wpa_printf(MSG_DEBUG, "MPM: close reason=%u",
+ WPA_GET_LE16(peer_mgmt_ie.reason));
+
sta = ap_get_sta(hapd, mgmt->sa);
/*
* open mesh, then go ahead and add the peer before proceeding.
*/
if (!sta && action_field == PLINK_OPEN &&
- !(mconf->security & MESH_CONF_SEC_AMPE))
+ (!(mconf->security & MESH_CONF_SEC_AMPE) ||
+ wpa_auth_pmksa_get(hapd->wpa_auth, mgmt->sa)))
sta = mesh_mpm_add_peer(wpa_s, mgmt->sa, &elems);
if (!sta) {
if (!sta->my_lid)
mesh_mpm_init_link(wpa_s, sta);
- if ((mconf->security & MESH_CONF_SEC_AMPE) &&
- mesh_rsn_process_ampe(wpa_s, sta, &elems,
- &mgmt->u.action.category,
- ies, ie_len)) {
- wpa_printf(MSG_DEBUG, "MPM: RSN process rejected frame");
- return;
+ if (mconf->security & MESH_CONF_SEC_AMPE) {
+ int res;
+
+ res = mesh_rsn_process_ampe(wpa_s, sta, &elems,
+ &mgmt->u.action.category,
+ peer_mgmt_ie.chosen_pmk,
+ ies, ie_len);
+ if (res) {
+ wpa_printf(MSG_DEBUG,
+ "MPM: RSN process rejected frame (res=%d)",
+ res);
+ if (action_field == PLINK_OPEN && res == -2) {
+ /* AES-SIV decryption failed */
+ mesh_mpm_fsm(wpa_s, sta, OPN_RJCT,
+ WLAN_REASON_MESH_INVALID_GTK);
+ }
+ return;
+ }
}
if (sta->plink_state == PLINK_BLOCKED) {
switch (action_field) {
case PLINK_OPEN:
if (plink_free_count(hapd) == 0) {
- event = OPN_IGNR;
+ event = REQ_RJCT;
+ reason = WLAN_REASON_MESH_MAX_PEERS;
wpa_printf(MSG_INFO,
"MPM: Peer link num over quota(%d)",
hapd->max_plinks);
} else if (sta->peer_lid && sta->peer_lid != plid) {
- event = OPN_IGNR;
+ wpa_printf(MSG_DEBUG,
+ "MPM: peer_lid mismatch: 0x%x != 0x%x",
+ sta->peer_lid, plid);
+ return; /* no FSM event */
} else {
sta->peer_lid = plid;
event = OPN_ACPT;
break;
case PLINK_CONFIRM:
if (plink_free_count(hapd) == 0) {
- event = CNF_IGNR;
+ event = REQ_RJCT;
+ reason = WLAN_REASON_MESH_MAX_PEERS;
wpa_printf(MSG_INFO,
"MPM: Peer link num over quota(%d)",
hapd->max_plinks);
} else if (sta->my_lid != llid ||
(sta->peer_lid && sta->peer_lid != plid)) {
- event = CNF_IGNR;
+ wpa_printf(MSG_DEBUG,
+ "MPM: lid mismatch: my_lid: 0x%x != 0x%x or peer_lid: 0x%x != 0x%x",
+ sta->my_lid, llid, sta->peer_lid, plid);
+ return; /* no FSM event */
} else {
if (!sta->peer_lid)
sta->peer_lid = plid;
+ sta->peer_aid = aid;
event = CNF_ACPT;
}
break;
* restarted.
*/
event = CLS_ACPT;
- else if (sta->peer_lid != plid)
- event = CLS_IGNR;
- else if (peer_mgmt_ie.plid && sta->my_lid != llid)
- event = CLS_IGNR;
- else
+ else if (sta->peer_lid != plid) {
+ wpa_printf(MSG_DEBUG,
+ "MPM: peer_lid mismatch: 0x%x != 0x%x",
+ sta->peer_lid, plid);
+ return; /* no FSM event */
+ } else if (peer_mgmt_ie.plid && sta->my_lid != llid) {
+ wpa_printf(MSG_DEBUG,
+ "MPM: my_lid mismatch: 0x%x != 0x%x",
+ sta->my_lid, llid);
+ return; /* no FSM event */
+ } else {
event = CLS_ACPT;
+ }
break;
default:
/*
*/
return;
}
- mesh_mpm_fsm(wpa_s, sta, event);
+ mesh_mpm_fsm(wpa_s, sta, event, reason);
}
/* called by ap_free_sta */
-void mesh_mpm_free_sta(struct sta_info *sta)
+void mesh_mpm_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
{
+ if (sta->plink_state == PLINK_ESTAB)
+ hapd->num_plinks--;
eloop_cancel_timeout(plink_timer, ELOOP_ALL_CTX, sta);
eloop_cancel_timeout(mesh_auth_timer, ELOOP_ALL_CTX, sta);
}
struct ieee802_11_elems *elems);
void mesh_mpm_deinit(struct wpa_supplicant *wpa_s, struct hostapd_iface *ifmsh);
void mesh_mpm_auth_peer(struct wpa_supplicant *wpa_s, const u8 *addr);
-void mesh_mpm_free_sta(struct sta_info *sta);
+void mesh_mpm_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
void wpa_mesh_set_plink_state(struct wpa_supplicant *wpa_s,
struct sta_info *sta,
enum mesh_plink_state state);
+int mesh_mpm_close_peer(struct wpa_supplicant *wpa_s, const u8 *addr);
+int mesh_mpm_connect_peer(struct wpa_supplicant *wpa_s, const u8 *addr,
+ int duration);
#ifdef CONFIG_MESH
#define MESH_AUTH_TIMEOUT 10
#define MESH_AUTH_RETRY 3
-#define MESH_AUTH_BLOCK_DURATION 3600
void mesh_auth_timer(void *eloop_ctx, void *user_data)
{
struct wpa_supplicant *wpa_s = eloop_ctx;
struct sta_info *sta = user_data;
+ struct hostapd_data *hapd;
if (sta->sae->state != SAE_ACCEPTED) {
wpa_printf(MSG_DEBUG, "AUTH: Re-authenticate with " MACSTR
if (sta->sae_auth_retry < MESH_AUTH_RETRY) {
mesh_rsn_auth_sae_sta(wpa_s, sta);
} else {
+ hapd = wpa_s->ifmsh->bss[0];
+
if (sta->sae_auth_retry > MESH_AUTH_RETRY) {
- ap_free_sta(wpa_s->ifmsh->bss[0], sta);
+ ap_free_sta(hapd, sta);
return;
}
/* block the STA if exceeded the number of attempts */
wpa_mesh_set_plink_state(wpa_s, sta, PLINK_BLOCKED);
sta->sae->state = SAE_NOTHING;
- if (wpa_s->mesh_auth_block_duration <
- MESH_AUTH_BLOCK_DURATION)
- wpa_s->mesh_auth_block_duration += 60;
- eloop_register_timeout(wpa_s->mesh_auth_block_duration,
- 0, mesh_auth_timer, wpa_s, sta);
wpa_msg(wpa_s, MSG_INFO, MESH_SAE_AUTH_BLOCKED "addr="
MACSTR " duration=%d",
MAC2STR(sta->addr),
- wpa_s->mesh_auth_block_duration);
+ hapd->conf->ap_max_inactivity);
}
sta->sae_auth_retry++;
}
}
-static int __mesh_rsn_auth_init(struct mesh_rsn *rsn, const u8 *addr)
+static int __mesh_rsn_auth_init(struct mesh_rsn *rsn, const u8 *addr,
+ enum mfp_options ieee80211w)
{
struct wpa_auth_config conf;
struct wpa_auth_callbacks cb;
wpa_printf(MSG_DEBUG, "AUTH: Initializing group state machine");
os_memset(&conf, 0, sizeof(conf));
- conf.wpa = 2;
+ conf.wpa = WPA_PROTO_RSN;
conf.wpa_key_mgmt = WPA_KEY_MGMT_SAE;
- conf.wpa_pairwise = WPA_CIPHER_CCMP;
- conf.rsn_pairwise = WPA_CIPHER_CCMP;
- conf.wpa_group = WPA_CIPHER_CCMP;
+ conf.wpa_pairwise = rsn->pairwise_cipher;
+ conf.rsn_pairwise = rsn->pairwise_cipher;
+ conf.wpa_group = rsn->group_cipher;
conf.eapol_version = 0;
conf.wpa_group_rekey = -1;
+#ifdef CONFIG_IEEE80211W
+ conf.ieee80211w = ieee80211w;
+ if (ieee80211w != NO_MGMT_FRAME_PROTECTION)
+ conf.group_mgmt_cipher = rsn->mgmt_group_cipher;
+#endif /* CONFIG_IEEE80211W */
os_memset(&cb, 0, sizeof(cb));
cb.ctx = rsn;
}
/* TODO: support rekeying */
- if (random_get_bytes(rsn->mgtk, 16) < 0) {
- wpa_deinit(rsn->auth);
+ rsn->mgtk_len = wpa_cipher_key_len(conf.wpa_group);
+ if (random_get_bytes(rsn->mgtk, rsn->mgtk_len) < 0)
return -1;
- }
+ rsn->mgtk_key_id = 1;
- /* group mgmt */
- wpa_drv_set_key(rsn->wpa_s, WPA_ALG_IGTK, NULL, 4, 1,
- seq, sizeof(seq), rsn->mgtk, sizeof(rsn->mgtk));
+#ifdef CONFIG_IEEE80211W
+ if (ieee80211w != NO_MGMT_FRAME_PROTECTION) {
+ rsn->igtk_len = wpa_cipher_key_len(conf.group_mgmt_cipher);
+ if (random_get_bytes(rsn->igtk, rsn->igtk_len) < 0)
+ return -1;
+ rsn->igtk_key_id = 4;
+
+ /* group mgmt */
+ wpa_hexdump_key(MSG_DEBUG, "mesh: Own TX IGTK",
+ rsn->igtk, rsn->igtk_len);
+ wpa_drv_set_key(rsn->wpa_s,
+ wpa_cipher_to_alg(rsn->mgmt_group_cipher), NULL,
+ rsn->igtk_key_id, 1,
+ seq, sizeof(seq), rsn->igtk, rsn->igtk_len);
+ }
+#endif /* CONFIG_IEEE80211W */
/* group privacy / data frames */
- wpa_drv_set_key(rsn->wpa_s, WPA_ALG_CCMP, NULL, 1, 1,
- seq, sizeof(seq), rsn->mgtk, sizeof(rsn->mgtk));
+ wpa_hexdump_key(MSG_DEBUG, "mesh: Own TX MGTK",
+ rsn->mgtk, rsn->mgtk_len);
+ wpa_drv_set_key(rsn->wpa_s, wpa_cipher_to_alg(rsn->group_cipher), NULL,
+ rsn->mgtk_key_id, 1, seq, sizeof(seq),
+ rsn->mgtk, rsn->mgtk_len);
return 0;
}
static void mesh_rsn_deinit(struct mesh_rsn *rsn)
{
os_memset(rsn->mgtk, 0, sizeof(rsn->mgtk));
+ rsn->mgtk_len = 0;
+ os_memset(rsn->igtk, 0, sizeof(rsn->igtk));
+ rsn->igtk_len = 0;
if (rsn->auth)
wpa_deinit(rsn->auth);
}
if (mesh_rsn == NULL)
return NULL;
mesh_rsn->wpa_s = wpa_s;
+ mesh_rsn->pairwise_cipher = conf->pairwise_cipher;
+ mesh_rsn->group_cipher = conf->group_cipher;
+ mesh_rsn->mgmt_group_cipher = conf->mgmt_group_cipher;
- if (__mesh_rsn_auth_init(mesh_rsn, wpa_s->own_addr) < 0) {
+ if (__mesh_rsn_auth_init(mesh_rsn, wpa_s->own_addr,
+ conf->ieee80211w) < 0) {
mesh_rsn_deinit(mesh_rsn);
os_free(mesh_rsn);
return NULL;
{
struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
struct wpa_ssid *ssid = wpa_s->current_ssid;
+ struct rsn_pmksa_cache_entry *pmksa;
unsigned int rnd;
int ret;
return -1;
}
+ pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, sta->addr);
+ if (pmksa) {
+ if (!sta->wpa_sm)
+ sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
+ sta->addr, NULL);
+ if (!sta->wpa_sm) {
+ wpa_printf(MSG_ERROR,
+ "mesh: Failed to initialize RSN state machine");
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "AUTH: Mesh PMKSA cache entry found for " MACSTR
+ " - try to use PMKSA caching instead of new SAE authentication",
+ MAC2STR(sta->addr));
+ wpa_auth_pmksa_set_to_sm(pmksa, sta->wpa_sm, hapd->wpa_auth,
+ sta->sae->pmkid, sta->sae->pmk);
+ sae_accept_sta(hapd, sta);
+ sta->mesh_sae_pmksa_caching = 1;
+ return 0;
+ }
+ sta->mesh_sae_pmksa_caching = 0;
+
if (mesh_rsn_build_sae_commit(wpa_s, ssid, sta))
return -1;
"AUTH: started authentication with SAE peer: " MACSTR,
MAC2STR(sta->addr));
- wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
ret = auth_sae_init_committed(hapd, sta);
if (ret)
return ret;
void mesh_rsn_get_pmkid(struct mesh_rsn *rsn, struct sta_info *sta, u8 *pmkid)
{
- /* don't expect wpa auth to cache the pmkid for now */
- rsn_pmkid(sta->sae->pmk, PMK_LEN, rsn->wpa_s->own_addr,
- sta->addr, pmkid,
- wpa_key_mgmt_sha256(wpa_auth_sta_key_mgmt(sta->wpa_sm)));
+ os_memcpy(pmkid, sta->sae->pmkid, SAE_PMKID_LEN);
}
{
u8 *myaddr = rsn->wpa_s->own_addr;
u8 *peer = sta->addr;
- u8 *addr1 = peer, *addr2 = myaddr;
- u8 context[AES_BLOCK_SIZE];
+ u8 *addr1, *addr2;
+ u8 context[RSN_SELECTOR_LEN + 2 * ETH_ALEN], *ptr = context;
- /* SAE */
- RSN_SELECTOR_PUT(context, wpa_cipher_to_suite(0, WPA_CIPHER_GCMP));
+ /*
+ * AEK = KDF-Hash-256(PMK, "AEK Derivation", Selected AKM Suite ||
+ * min(localMAC, peerMAC) || max(localMAC, peerMAC))
+ */
+ /* Selected AKM Suite: SAE */
+ RSN_SELECTOR_PUT(ptr, RSN_AUTH_KEY_MGMT_SAE);
+ ptr += RSN_SELECTOR_LEN;
if (os_memcmp(myaddr, peer, ETH_ALEN) < 0) {
addr1 = myaddr;
addr2 = peer;
+ } else {
+ addr1 = peer;
+ addr2 = myaddr;
}
- os_memcpy(context + 4, addr1, ETH_ALEN);
- os_memcpy(context + 10, addr2, ETH_ALEN);
+ os_memcpy(ptr, addr1, ETH_ALEN);
+ ptr += ETH_ALEN;
+ os_memcpy(ptr, addr2, ETH_ALEN);
sha256_prf(sta->sae->pmk, sizeof(sta->sae->pmk), "AEK Derivation",
context, sizeof(context), sta->aek, sizeof(sta->aek));
{
u8 *ptr;
u8 *min, *max;
- u16 min_lid, max_lid;
- size_t nonce_len = sizeof(sta->my_nonce);
- size_t lid_len = sizeof(sta->my_lid);
u8 *myaddr = wpa_s->own_addr;
u8 *peer = sta->addr;
- /* 2 nonces, 2 linkids, akm suite, 2 mac addrs */
- u8 context[64 + 4 + 4 + 12];
-
+ u8 context[2 * WPA_NONCE_LEN + 2 * 2 + RSN_SELECTOR_LEN + 2 * ETH_ALEN];
+
+ /*
+ * MTK = KDF-Hash-Length(PMK, "Temporal Key Derivation", min(localNonce,
+ * peerNonce) || max(localNonce, peerNonce) || min(localLinkID,
+ * peerLinkID) || max(localLinkID, peerLinkID) || Selected AKM Suite ||
+ * min(localMAC, peerMAC) || max(localMAC, peerMAC))
+ */
ptr = context;
- if (os_memcmp(sta->my_nonce, sta->peer_nonce, nonce_len) < 0) {
+ if (os_memcmp(sta->my_nonce, sta->peer_nonce, WPA_NONCE_LEN) < 0) {
min = sta->my_nonce;
max = sta->peer_nonce;
} else {
min = sta->peer_nonce;
max = sta->my_nonce;
}
- os_memcpy(ptr, min, nonce_len);
- os_memcpy(ptr + nonce_len, max, nonce_len);
- ptr += 2 * nonce_len;
+ os_memcpy(ptr, min, WPA_NONCE_LEN);
+ ptr += WPA_NONCE_LEN;
+ os_memcpy(ptr, max, WPA_NONCE_LEN);
+ ptr += WPA_NONCE_LEN;
if (sta->my_lid < sta->peer_lid) {
- min_lid = host_to_le16(sta->my_lid);
- max_lid = host_to_le16(sta->peer_lid);
+ WPA_PUT_LE16(ptr, sta->my_lid);
+ ptr += 2;
+ WPA_PUT_LE16(ptr, sta->peer_lid);
+ ptr += 2;
} else {
- min_lid = host_to_le16(sta->peer_lid);
- max_lid = host_to_le16(sta->my_lid);
+ WPA_PUT_LE16(ptr, sta->peer_lid);
+ ptr += 2;
+ WPA_PUT_LE16(ptr, sta->my_lid);
+ ptr += 2;
}
- os_memcpy(ptr, &min_lid, lid_len);
- os_memcpy(ptr + lid_len, &max_lid, lid_len);
- ptr += 2 * lid_len;
- /* SAE */
- RSN_SELECTOR_PUT(ptr, wpa_cipher_to_suite(0, WPA_CIPHER_GCMP));
- ptr += 4;
+ /* Selected AKM Suite: SAE */
+ RSN_SELECTOR_PUT(ptr, RSN_AUTH_KEY_MGMT_SAE);
+ ptr += RSN_SELECTOR_LEN;
if (os_memcmp(myaddr, peer, ETH_ALEN) < 0) {
min = myaddr;
max = myaddr;
}
os_memcpy(ptr, min, ETH_ALEN);
- os_memcpy(ptr + ETH_ALEN, max, ETH_ALEN);
+ ptr += ETH_ALEN;
+ os_memcpy(ptr, max, ETH_ALEN);
- sha256_prf(sta->sae->pmk, sizeof(sta->sae->pmk),
+ sta->mtk_len = wpa_cipher_key_len(wpa_s->mesh_rsn->pairwise_cipher);
+ sha256_prf(sta->sae->pmk, SAE_PMK_LEN,
"Temporal Key Derivation", context, sizeof(context),
- sta->mtk, sizeof(sta->mtk));
+ sta->mtk, sta->mtk_len);
return 0;
}
void mesh_rsn_init_ampe_sta(struct wpa_supplicant *wpa_s, struct sta_info *sta)
{
- if (random_get_bytes(sta->my_nonce, 32) < 0) {
+ if (random_get_bytes(sta->my_nonce, WPA_NONCE_LEN) < 0) {
wpa_printf(MSG_INFO, "mesh: Failed to derive random nonce");
/* TODO: How to handle this more cleanly? */
}
- os_memset(sta->peer_nonce, 0, 32);
+ os_memset(sta->peer_nonce, 0, WPA_NONCE_LEN);
mesh_rsn_derive_aek(wpa_s->mesh_rsn, sta);
}
{
struct ieee80211_ampe_ie *ampe;
u8 const *ie = wpabuf_head_u8(buf) + wpabuf_len(buf);
- u8 *ampe_ie = NULL, *mic_ie = NULL, *mic_payload;
+ u8 *ampe_ie, *pos, *mic_payload;
const u8 *aad[] = { rsn->wpa_s->own_addr, sta->addr, cat };
const size_t aad_len[] = { ETH_ALEN, ETH_ALEN, ie - cat };
int ret = 0;
+ size_t len;
+
+ len = sizeof(*ampe);
+ if (cat[1] == PLINK_OPEN)
+ len += rsn->mgtk_len + WPA_KEY_RSC_LEN + 4;
+#ifdef CONFIG_IEEE80211W
+ if (cat[1] == PLINK_OPEN && rsn->igtk_len)
+ len += 2 + 6 + rsn->igtk_len;
+#endif /* CONFIG_IEEE80211W */
- if (AES_BLOCK_SIZE + 2 + sizeof(*ampe) + 2 > wpabuf_tailroom(buf)) {
+ if (2 + AES_BLOCK_SIZE + 2 + len > wpabuf_tailroom(buf)) {
wpa_printf(MSG_ERROR, "protect frame: buffer too small");
return -EINVAL;
}
- ampe_ie = os_zalloc(2 + sizeof(*ampe));
+ ampe_ie = os_zalloc(2 + len);
if (!ampe_ie) {
wpa_printf(MSG_ERROR, "protect frame: out of memory");
return -ENOMEM;
}
- mic_ie = os_zalloc(2 + AES_BLOCK_SIZE);
- if (!mic_ie) {
- wpa_printf(MSG_ERROR, "protect frame: out of memory");
- ret = -ENOMEM;
- goto free;
- }
-
/* IE: AMPE */
ampe_ie[0] = WLAN_EID_AMPE;
- ampe_ie[1] = sizeof(*ampe);
+ ampe_ie[1] = len;
ampe = (struct ieee80211_ampe_ie *) (ampe_ie + 2);
RSN_SELECTOR_PUT(ampe->selected_pairwise_suite,
- wpa_cipher_to_suite(WPA_PROTO_RSN, WPA_CIPHER_CCMP));
- os_memcpy(ampe->local_nonce, sta->my_nonce, 32);
- os_memcpy(ampe->peer_nonce, sta->peer_nonce, 32);
- /* incomplete: see 13.5.4 */
+ RSN_CIPHER_SUITE_CCMP);
+ os_memcpy(ampe->local_nonce, sta->my_nonce, WPA_NONCE_LEN);
+ os_memcpy(ampe->peer_nonce, sta->peer_nonce, WPA_NONCE_LEN);
+
+ pos = (u8 *) (ampe + 1);
+ if (cat[1] != PLINK_OPEN)
+ goto skip_keys;
+
+ /* TODO: Key Replay Counter[8] optionally for
+ * Mesh Group Key Inform/Acknowledge frames */
+
/* TODO: static mgtk for now since we don't support rekeying! */
- os_memcpy(ampe->mgtk, rsn->mgtk, 16);
- /* TODO: Populate Key RSC */
- /* expire in 13 decades or so */
- os_memset(ampe->key_expiration, 0xff, 4);
+ /*
+ * GTKdata[variable]:
+ * MGTK[variable] || Key RSC[8] || GTKExpirationTime[4]
+ */
+ os_memcpy(pos, rsn->mgtk, rsn->mgtk_len);
+ pos += rsn->mgtk_len;
+ wpa_drv_get_seqnum(rsn->wpa_s, NULL, rsn->mgtk_key_id, pos);
+ pos += WPA_KEY_RSC_LEN;
+ /* Use fixed GTKExpirationTime for now */
+ WPA_PUT_LE32(pos, 0xffffffff);
+ pos += 4;
+
+#ifdef CONFIG_IEEE80211W
+ /*
+ * IGTKdata[variable]:
+ * Key ID[2], IPN[6], IGTK[variable]
+ */
+ if (rsn->igtk_len) {
+ WPA_PUT_LE16(pos, rsn->igtk_key_id);
+ pos += 2;
+ wpa_drv_get_seqnum(rsn->wpa_s, NULL, rsn->igtk_key_id, pos);
+ pos += 6;
+ os_memcpy(pos, rsn->igtk, rsn->igtk_len);
+ }
+#endif /* CONFIG_IEEE80211W */
+
+skip_keys:
+ wpa_hexdump_key(MSG_DEBUG, "mesh: Plaintext AMPE element",
+ ampe_ie, 2 + len);
/* IE: MIC */
- mic_ie[0] = WLAN_EID_MIC;
- mic_ie[1] = AES_BLOCK_SIZE;
- wpabuf_put_data(buf, mic_ie, 2);
+ wpabuf_put_u8(buf, WLAN_EID_MIC);
+ wpabuf_put_u8(buf, AES_BLOCK_SIZE);
/* MIC field is output ciphertext */
/* encrypt after MIC */
- mic_payload = (u8 *) wpabuf_put(buf, 2 + sizeof(*ampe) +
- AES_BLOCK_SIZE);
+ mic_payload = wpabuf_put(buf, 2 + len + AES_BLOCK_SIZE);
- if (aes_siv_encrypt(sta->aek, ampe_ie, 2 + sizeof(*ampe), 3,
+ if (aes_siv_encrypt(sta->aek, ampe_ie, 2 + len, 3,
aad, aad_len, mic_payload)) {
wpa_printf(MSG_ERROR, "protect frame: failed to encrypt");
ret = -ENOMEM;
- goto free;
}
-free:
os_free(ampe_ie);
- os_free(mic_ie);
return ret;
}
int mesh_rsn_process_ampe(struct wpa_supplicant *wpa_s, struct sta_info *sta,
struct ieee802_11_elems *elems, const u8 *cat,
+ const u8 *chosen_pmk,
const u8 *start, size_t elems_len)
{
int ret = 0;
struct ieee80211_ampe_ie *ampe;
- u8 null_nonce[32] = {};
+ u8 null_nonce[WPA_NONCE_LEN] = {};
u8 ampe_eid;
u8 ampe_ie_len;
- u8 *ampe_buf, *crypt = NULL;
+ u8 *ampe_buf, *crypt = NULL, *pos, *end;
size_t crypt_len;
const u8 *aad[] = { sta->addr, wpa_s->own_addr, cat };
const size_t aad_len[] = { ETH_ALEN, ETH_ALEN,
(elems->mic - 2) - cat };
+ size_t key_len;
+
+ if (!sta->sae) {
+ struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
+
+ if (!wpa_auth_pmksa_get(hapd->wpa_auth, sta->addr)) {
+ wpa_printf(MSG_INFO,
+ "Mesh RSN: SAE is not prepared yet");
+ return -1;
+ }
+ mesh_rsn_auth_sae_sta(wpa_s, sta);
+ }
+
+ if (chosen_pmk && os_memcmp(chosen_pmk, sta->sae->pmkid, PMKID_LEN)) {
+ wpa_msg(wpa_s, MSG_DEBUG,
+ "Mesh RSN: Invalid PMKID (Chosen PMK did not match calculated PMKID)");
+ return -1;
+ }
if (!elems->mic || elems->mic_len < AES_BLOCK_SIZE) {
wpa_msg(wpa_s, MSG_DEBUG, "Mesh RSN: missing mic ie");
return -1;
crypt_len = elems_len - (elems->mic - start);
- if (crypt_len < 2) {
+ if (crypt_len < 2 + AES_BLOCK_SIZE) {
wpa_msg(wpa_s, MSG_DEBUG, "Mesh RSN: missing ampe ie");
return -1;
}
if (aes_siv_decrypt(sta->aek, crypt, crypt_len, 3,
aad, aad_len, ampe_buf)) {
wpa_printf(MSG_ERROR, "Mesh RSN: frame verification failed!");
- ret = -1;
+ ret = -2;
goto free;
}
+ crypt_len -= AES_BLOCK_SIZE;
+ wpa_hexdump_key(MSG_DEBUG, "mesh: Decrypted AMPE element",
+ ampe_buf, crypt_len);
+
ampe_eid = *ampe_buf++;
ampe_ie_len = *ampe_buf++;
if (ampe_eid != WLAN_EID_AMPE ||
+ (size_t) 2 + ampe_ie_len > crypt_len ||
ampe_ie_len < sizeof(struct ieee80211_ampe_ie)) {
wpa_msg(wpa_s, MSG_DEBUG, "Mesh RSN: invalid ampe ie");
ret = -1;
}
ampe = (struct ieee80211_ampe_ie *) ampe_buf;
- if (os_memcmp(ampe->peer_nonce, null_nonce, 32) != 0 &&
- os_memcmp(ampe->peer_nonce, sta->my_nonce, 32) != 0) {
+ pos = (u8 *) (ampe + 1);
+ end = ampe_buf + ampe_ie_len;
+ if (os_memcmp(ampe->peer_nonce, null_nonce, WPA_NONCE_LEN) != 0 &&
+ os_memcmp(ampe->peer_nonce, sta->my_nonce, WPA_NONCE_LEN) != 0) {
wpa_msg(wpa_s, MSG_DEBUG, "Mesh RSN: invalid peer nonce");
ret = -1;
goto free;
}
os_memcpy(sta->peer_nonce, ampe->local_nonce,
sizeof(ampe->local_nonce));
- os_memcpy(sta->mgtk, ampe->mgtk, sizeof(ampe->mgtk));
- /* todo parse mgtk expiration */
+ /* TODO: Key Replay Counter[8] in Mesh Group Key Inform/Acknowledge
+ * frames */
+
+ /*
+ * GTKdata shall not be included in Mesh Peering Confirm. While the
+ * standard does not state the same about IGTKdata, that same constraint
+ * needs to apply for it. It makes no sense to include the keys in Mesh
+ * Peering Close frames either, so while the standard does not seem to
+ * have a shall statement for these, they are described without
+ * mentioning GTKdata.
+ *
+ * An earlier implementation used to add GTKdata to both Mesh Peering
+ * Open and Mesh Peering Confirm frames, so ignore the possibly present
+ * GTKdata frame without rejecting the frame as a backwards
+ * compatibility mechanism.
+ */
+ if (cat[1] != PLINK_OPEN) {
+ if (end > pos) {
+ wpa_hexdump_key(MSG_DEBUG,
+ "mesh: Ignore unexpected GTKdata(etc.) fields in the end of AMPE element in Mesh Peering Confirm/Close",
+ pos, end - pos);
+ }
+ goto free;
+ }
+
+ /*
+ * GTKdata[variable]:
+ * MGTK[variable] || Key RSC[8] || GTKExpirationTime[4]
+ */
+ sta->mgtk_key_id = 1; /* FIX: Where to get Key ID? */
+ key_len = wpa_cipher_key_len(wpa_s->mesh_rsn->group_cipher);
+ if ((int) key_len + WPA_KEY_RSC_LEN + 4 > end - pos) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "mesh: Truncated AMPE element");
+ ret = -1;
+ goto free;
+ }
+ sta->mgtk_len = key_len;
+ os_memcpy(sta->mgtk, pos, sta->mgtk_len);
+ wpa_hexdump_key(MSG_DEBUG, "mesh: GTKdata - MGTK",
+ sta->mgtk, sta->mgtk_len);
+ pos += sta->mgtk_len;
+ wpa_hexdump(MSG_DEBUG, "mesh: GTKdata - MGTK - Key RSC",
+ pos, WPA_KEY_RSC_LEN);
+ os_memcpy(sta->mgtk_rsc, pos, sizeof(sta->mgtk_rsc));
+ pos += WPA_KEY_RSC_LEN;
+ wpa_printf(MSG_DEBUG,
+ "mesh: GTKdata - MGTK - GTKExpirationTime: %u seconds",
+ WPA_GET_LE32(pos));
+ pos += 4;
+
+#ifdef CONFIG_IEEE80211W
+ /*
+ * IGTKdata[variable]:
+ * Key ID[2], IPN[6], IGTK[variable]
+ */
+ key_len = wpa_cipher_key_len(wpa_s->mesh_rsn->mgmt_group_cipher);
+ if (end - pos >= (int) (2 + 6 + key_len)) {
+ sta->igtk_key_id = WPA_GET_LE16(pos);
+ wpa_printf(MSG_DEBUG, "mesh: IGTKdata - Key ID %u",
+ sta->igtk_key_id);
+ pos += 2;
+ os_memcpy(sta->igtk_rsc, pos, sizeof(sta->igtk_rsc));
+ wpa_hexdump(MSG_DEBUG, "mesh: IGTKdata - IPN",
+ sta->igtk_rsc, sizeof(sta->igtk_rsc));
+ pos += 6;
+ os_memcpy(sta->igtk, pos, key_len);
+ sta->igtk_len = key_len;
+ wpa_hexdump_key(MSG_DEBUG, "mesh: IGTKdata - IGTK",
+ sta->igtk, sta->igtk_len);
+ }
+#endif /* CONFIG_IEEE80211W */
+
free:
os_free(crypt);
return ret;
struct mesh_rsn {
struct wpa_supplicant *wpa_s;
struct wpa_authenticator *auth;
- u8 mgtk[16];
+ unsigned int pairwise_cipher;
+ unsigned int group_cipher;
+ u8 mgtk[WPA_TK_MAX_LEN];
+ size_t mgtk_len;
+ u8 mgtk_key_id;
+ unsigned int mgmt_group_cipher;
+ u8 igtk_key_id;
+ u8 igtk[WPA_TK_MAX_LEN];
+ size_t igtk_len;
#ifdef CONFIG_SAE
struct wpabuf *sae_token;
int sae_group_index;
const u8 *cat, struct wpabuf *buf);
int mesh_rsn_process_ampe(struct wpa_supplicant *wpa_s, struct sta_info *sta,
struct ieee802_11_elems *elems, const u8 *cat,
+ const u8 *chosen_pmk,
const u8 *start, size_t elems_len);
void mesh_auth_timer(void *eloop_ctx, void *user_data);
#include "config.h"
#include "wpa_supplicant_i.h"
#include "wps_supplicant.h"
+#include "binder/binder.h"
#include "dbus/dbus_common.h"
#include "dbus/dbus_old.h"
#include "dbus/dbus_new.h"
}
#endif /* CONFIG_DBUS */
+#ifdef CONFIG_BINDER
+ global->binder = wpas_binder_init(global);
+ if (!global->binder)
+ return -1;
+#endif /* CONFIG_BINDER */
+
return 0;
}
if (global->dbus)
wpas_dbus_deinit(global->dbus);
#endif /* CONFIG_DBUS */
+
+#ifdef CONFIG_BINDER
+ if (global->binder)
+ wpas_binder_deinit(global->binder);
+#endif /* CONFIG_BINDER */
}
}
+void wpas_notify_assoc_status_code(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->p2p_mgmt)
+ return;
+
+ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_ASSOC_STATUS_CODE);
+}
+
+
void wpas_notify_network_changed(struct wpa_supplicant *wpa_s)
{
if (wpa_s->p2p_mgmt)
void wpas_notify_p2p_group_started(struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid, int network_id,
+ struct wpa_ssid *ssid, int persistent,
int client)
{
/* Notify a group has been started */
wpas_dbus_register_p2p_group(wpa_s, ssid);
- wpas_dbus_signal_p2p_group_started(wpa_s, ssid, client, network_id);
+ wpas_dbus_signal_p2p_group_started(wpa_s, client, persistent);
}
enum wpa_states new_state,
enum wpa_states old_state);
void wpas_notify_disconnect_reason(struct wpa_supplicant *wpa_s);
+void wpas_notify_assoc_status_code(struct wpa_supplicant *wpa_s);
void wpas_notify_network_changed(struct wpa_supplicant *wpa_s);
void wpas_notify_ap_scan_changed(struct wpa_supplicant *wpa_s);
void wpas_notify_bssid_changed(struct wpa_supplicant *wpa_s);
u16 config_methods,
unsigned int generated_pin);
void wpas_notify_p2p_group_started(struct wpa_supplicant *wpa_s,
- struct wpa_ssid *ssid, int network_id,
+ struct wpa_ssid *ssid, int persistent,
int client);
void wpas_notify_p2p_group_formation_failure(struct wpa_supplicant *wpa_s,
const char *reason);
{
struct wpa_supplicant *iface;
- if (os_memcmp(src, wpa_s->own_addr, ETH_ALEN) == 0)
+ if (os_memcmp(src, wpa_s->own_addr, ETH_ALEN) == 0) {
+#ifdef CONFIG_P2P
+ if (wpa_s->p2p_mgmt && wpa_s != wpa_s->parent &&
+ wpa_s->parent->ap_iface &&
+ os_memcmp(wpa_s->parent->own_addr,
+ wpa_s->own_addr, ETH_ALEN) == 0 &&
+ wpabuf_len(wpa_s->pending_action_tx) >= 2 &&
+ *wpabuf_head_u8(wpa_s->pending_action_tx) !=
+ WLAN_ACTION_PUBLIC) {
+ /*
+ * When P2P Device interface has same MAC address as
+ * the GO interface, make sure non-Public Action frames
+ * are sent through the GO interface. The P2P Device
+ * interface can only send Public Action frames.
+ */
+ wpa_printf(MSG_DEBUG,
+ "P2P: Use GO interface %s instead of interface %s for Action TX",
+ wpa_s->parent->ifname, wpa_s->ifname);
+ return wpa_s->parent;
+ }
+#endif /* CONFIG_P2P */
return wpa_s;
+ }
/*
* Try to find a group interface that matches with the source address.
}
wpa_printf(MSG_DEBUG, "Off-channel: Sending pending Action frame to "
- MACSTR " using interface %s",
- MAC2STR(wpa_s->pending_action_dst), iface->ifname);
+ MACSTR " using interface %s (pending_action_tx=%p)",
+ MAC2STR(wpa_s->pending_action_dst), iface->ifname,
+ wpa_s->pending_action_tx);
res = wpa_drv_send_action(iface, wpa_s->pending_action_freq, 0,
wpa_s->pending_action_dst,
wpa_s->pending_action_src,
return;
}
- wpa_printf(MSG_DEBUG, "Off-channel: Delete matching pending action frame");
-
+ wpa_printf(MSG_DEBUG,
+ "Off-channel: Delete matching pending action frame (dst="
+ MACSTR " pending_action_tx=%p)", MAC2STR(dst),
+ wpa_s->pending_action_tx);
+ wpa_hexdump_buf(MSG_MSGDUMP, "Pending TX frame",
+ wpa_s->pending_action_tx);
wpabuf_free(wpa_s->pending_action_tx);
wpa_s->pending_action_tx = NULL;
if (wpa_s->pending_action_tx) {
wpa_printf(MSG_DEBUG, "Off-channel: Dropped pending Action "
- "frame TX to " MACSTR,
- MAC2STR(wpa_s->pending_action_dst));
+ "frame TX to " MACSTR " (pending_action_tx=%p)",
+ MAC2STR(wpa_s->pending_action_dst),
+ wpa_s->pending_action_tx);
+ wpa_hexdump_buf(MSG_MSGDUMP, "Pending TX frame",
+ wpa_s->pending_action_tx);
wpabuf_free(wpa_s->pending_action_tx);
}
wpa_s->pending_action_tx_done = 0;
os_memcpy(wpa_s->pending_action_bssid, bssid, ETH_ALEN);
wpa_s->pending_action_freq = freq;
wpa_s->pending_action_no_cck = no_cck;
+ wpa_printf(MSG_DEBUG,
+ "Off-channel: Stored pending action frame (dst=" MACSTR
+ " pending_action_tx=%p)",
+ MAC2STR(dst), wpa_s->pending_action_tx);
+ wpa_hexdump_buf(MSG_MSGDUMP, "Pending TX frame",
+ wpa_s->pending_action_tx);
if (freq != 0 && wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) {
struct wpa_supplicant *iface;
*/
void offchannel_clear_pending_action_tx(struct wpa_supplicant *wpa_s)
{
+ wpa_printf(MSG_DEBUG,
+ "Off-channel: Clear pending Action frame TX (pending_action_tx=%p",
+ wpa_s->pending_action_tx);
wpabuf_free(wpa_s->pending_action_tx);
wpa_s->pending_action_tx = NULL;
}
*/
#define P2P_GO_FREQ_CHANGE_TIME 5
+/**
+ * Defines CSA parameters which are used when GO evacuates the no longer valid
+ * channel (and if the driver supports channel switch).
+ */
+#define P2P_GO_CSA_COUNT 7
+#define P2P_GO_CSA_BLOCK_TX 0
+
#ifndef P2P_MAX_CLIENT_IDLE
/*
* How many seconds to try to reconnect to the GO when connection in P2P client
int go);
static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s, int freq,
const u8 *ssid, size_t ssid_len);
+static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq,
+ int *force_freq, int *pref_freq, int go,
+ unsigned int *pref_freq_list,
+ unsigned int *num_pref_freq);
static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq,
const u8 *ssid, size_t ssid_len);
static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx);
int social_channels_freq[] = { 2412, 2437, 2462, 60480 };
size_t ielen;
u8 *n, i;
+ unsigned int bands;
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1;
if (wps_ie == NULL)
goto fail;
- ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
- ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen);
- if (ies == NULL) {
- wpabuf_free(wps_ie);
- goto fail;
- }
- wpabuf_put_buf(ies, wps_ie);
- wpabuf_free(wps_ie);
-
- p2p_scan_ie(wpa_s->global->p2p, ies, dev_id);
-
- params->p2p_probe = 1;
- n = os_malloc(wpabuf_len(ies));
- if (n == NULL) {
- wpabuf_free(ies);
- goto fail;
- }
- os_memcpy(n, wpabuf_head(ies), wpabuf_len(ies));
- params->extra_ies = n;
- params->extra_ies_len = wpabuf_len(ies);
- wpabuf_free(ies);
-
switch (type) {
case P2P_SCAN_SOCIAL:
params->freqs = os_calloc(ARRAY_SIZE(social_channels_freq) + 1,
break;
}
+ ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
+ ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen);
+ if (ies == NULL) {
+ wpabuf_free(wps_ie);
+ goto fail;
+ }
+ wpabuf_put_buf(ies, wps_ie);
+ wpabuf_free(wps_ie);
+
+ bands = wpas_get_bands(wpa_s, params->freqs);
+ p2p_scan_ie(wpa_s->global->p2p, ies, dev_id, bands);
+
+ params->p2p_probe = 1;
+ n = os_malloc(wpabuf_len(ies));
+ if (n == NULL) {
+ wpabuf_free(ies);
+ goto fail;
+ }
+ os_memcpy(n, wpabuf_head(ies), wpabuf_len(ies));
+ params->extra_ies = n;
+ params->extra_ies_len = wpabuf_len(ies);
+ wpabuf_free(ies);
+
radio_remove_works(wpa_s, "p2p-scan", 0);
if (radio_add_work(wpa_s, 0, "p2p-scan", 0, wpas_p2p_trigger_scan_cb,
params) < 0)
}
+static unsigned int p2p_is_active_persistent_group(struct wpa_supplicant *wpa_s)
+{
+ return !wpa_s->p2p_mgmt && wpa_s->current_ssid &&
+ !wpa_s->current_ssid->disabled &&
+ wpa_s->current_ssid->p2p_group &&
+ wpa_s->current_ssid->p2p_persistent_group;
+}
+
+
+static unsigned int p2p_is_active_persistent_go(struct wpa_supplicant *wpa_s)
+{
+ return p2p_is_active_persistent_group(wpa_s) &&
+ wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO;
+}
+
+
/* Find an interface for a P2P group where we are the GO */
static struct wpa_supplicant *
wpas_p2p_get_go_group(struct wpa_supplicant *wpa_s)
{
struct wpa_supplicant *save = NULL;
- struct wpa_ssid *s;
if (!wpa_s)
return NULL;
for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
- for (s = wpa_s->conf->ssid; s; s = s->next) {
- if (s->disabled || !s->p2p_group ||
- s->mode != WPAS_MODE_P2P_GO)
- continue;
+ if (!p2p_is_active_persistent_go(wpa_s))
+ continue;
- /* Prefer a group with connected clients */
- if (p2p_get_group_num_members(wpa_s->p2p_group))
- return wpa_s;
- save = wpa_s;
- }
+ /* Prefer a group with connected clients */
+ if (p2p_get_group_num_members(wpa_s->p2p_group))
+ return wpa_s;
+ save = wpa_s;
}
/* No group with connected clients, so pick the one without (if any) */
}
-/* Find an active P2P group where we are the GO */
-static struct wpa_ssid * wpas_p2p_group_go_ssid(struct wpa_supplicant *wpa_s,
- u8 *bssid)
+static unsigned int p2p_is_active_persistent_cli(struct wpa_supplicant *wpa_s)
{
- struct wpa_ssid *s, *empty = NULL;
+ return p2p_is_active_persistent_group(wpa_s) &&
+ wpa_s->current_ssid->mode == WPAS_MODE_INFRA;
+}
- if (!wpa_s)
- return 0;
+/* Find an interface for a P2P group where we are the P2P Client */
+static struct wpa_supplicant *
+wpas_p2p_get_cli_group(struct wpa_supplicant *wpa_s)
+{
for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
- for (s = wpa_s->conf->ssid; s; s = s->next) {
- if (s->disabled || !s->p2p_group ||
- s->mode != WPAS_MODE_P2P_GO)
- continue;
-
- os_memcpy(bssid, wpa_s->own_addr, ETH_ALEN);
- if (p2p_get_group_num_members(wpa_s->p2p_group))
- return s;
- empty = s;
- }
+ if (p2p_is_active_persistent_cli(wpa_s))
+ return wpa_s;
}
- return empty;
+ return NULL;
}
}
-static u8 p2ps_group_capability(void *ctx, u8 incoming, u8 role)
+static u8 p2ps_group_capability(void *ctx, u8 incoming, u8 role,
+ unsigned int *force_freq,
+ unsigned int *pref_freq)
{
- struct wpa_supplicant *wpa_s = ctx, *tmp_wpa_s;
+ struct wpa_supplicant *wpa_s = ctx;
struct wpa_ssid *s;
u8 conncap = P2PS_SETUP_NONE;
unsigned int owned_members = 0;
- unsigned int owner = 0;
- unsigned int client = 0;
- struct wpa_supplicant *go_wpa_s;
+ struct wpa_supplicant *go_wpa_s, *cli_wpa_s;
struct wpa_ssid *persistent_go;
int p2p_no_group_iface;
+ unsigned int pref_freq_list[P2P_MAX_PREF_CHANNELS], size;
wpa_printf(MSG_DEBUG, "P2P: Conncap - in:%d role:%d", incoming, role);
+ if (force_freq)
+ *force_freq = 0;
+ if (pref_freq)
+ *pref_freq = 0;
+
+ size = P2P_MAX_PREF_CHANNELS;
+ if (force_freq && pref_freq &&
+ !wpas_p2p_setup_freqs(wpa_s, 0, (int *) force_freq,
+ (int *) pref_freq, 0, pref_freq_list, &size))
+ wpas_p2p_set_own_freq_preference(wpa_s,
+ *force_freq ? *force_freq :
+ *pref_freq);
+
/*
* For non-concurrent capable devices:
* If persistent_go, then no new.
* If client, then no GO.
*/
go_wpa_s = wpas_p2p_get_go_group(wpa_s);
+ if (go_wpa_s)
+ owned_members = p2p_get_group_num_members(go_wpa_s->p2p_group);
persistent_go = wpas_p2p_get_persistent_go(wpa_s);
p2p_no_group_iface = !wpas_p2p_create_iface(wpa_s);
+ cli_wpa_s = wpas_p2p_get_cli_group(wpa_s);
- wpa_printf(MSG_DEBUG, "P2P: GO(iface)=%p persistent(ssid)=%p",
- go_wpa_s, persistent_go);
-
- for (tmp_wpa_s = wpa_s->global->ifaces; tmp_wpa_s;
- tmp_wpa_s = tmp_wpa_s->next) {
- for (s = tmp_wpa_s->conf->ssid; s; s = s->next) {
- wpa_printf(MSG_DEBUG,
- "P2P: sup:%p ssid:%p disabled:%d p2p:%d mode:%d",
- tmp_wpa_s, s, s->disabled,
- s->p2p_group, s->mode);
- if (!s->disabled && s->p2p_group) {
- if (s->mode == WPAS_MODE_P2P_GO) {
- owned_members +=
- p2p_get_group_num_members(
- tmp_wpa_s->p2p_group);
- owner++;
- } else
- client++;
- }
- }
- }
+ wpa_printf(MSG_DEBUG,
+ "P2P: GO(iface)=%p members=%u CLI(iface)=%p persistent(ssid)=%p",
+ go_wpa_s, owned_members, cli_wpa_s, persistent_go);
/* If not concurrent, restrict our choices */
if (p2p_no_group_iface) {
wpa_printf(MSG_DEBUG, "P2P: p2p_no_group_iface");
- if (client)
+ if (cli_wpa_s)
return P2PS_SETUP_NONE;
if (go_wpa_s) {
/* If a required role has been specified, handle it here */
if (role && role != P2PS_SETUP_NEW) {
switch (incoming) {
+ case P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_NEW:
+ case P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_CLIENT:
+ /*
+ * Peer has an active GO, so if the role allows it and
+ * we do not have any active roles, become client.
+ */
+ if ((role & P2PS_SETUP_CLIENT) && !go_wpa_s &&
+ !cli_wpa_s)
+ return P2PS_SETUP_CLIENT;
+
+ /* fall through */
+
case P2PS_SETUP_NONE:
case P2PS_SETUP_NEW:
- case P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_CLIENT:
- case P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_NEW:
conncap = role;
goto grp_owner;
* Must be a complimentary role - cannot be a client to
* more than one peer.
*/
- if (incoming == role || client)
+ if (incoming == role || cli_wpa_s)
return P2PS_SETUP_NONE;
return P2PS_SETUP_CLIENT;
switch (incoming) {
case P2PS_SETUP_NONE:
case P2PS_SETUP_NEW:
- if (client)
+ if (cli_wpa_s)
conncap = P2PS_SETUP_GROUP_OWNER;
else if (!owned_members)
conncap = P2PS_SETUP_NEW;
break;
case P2PS_SETUP_GROUP_OWNER:
- if (!client)
+ if (!cli_wpa_s)
conncap = P2PS_SETUP_CLIENT;
break;
case P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_NEW:
case P2PS_SETUP_GROUP_OWNER | P2PS_SETUP_CLIENT:
- if (client)
+ if (cli_wpa_s)
conncap = P2PS_SETUP_GROUP_OWNER;
else {
u8 r;
(!incoming && (conncap & P2PS_SETUP_NEW))) {
if (go_wpa_s && p2p_client_limit_reached(go_wpa_s->p2p_group))
conncap &= ~P2PS_SETUP_GROUP_OWNER;
- wpa_printf(MSG_DEBUG, "P2P: GOs:%d members:%d conncap:%d",
- owner, owned_members, conncap);
s = wpas_p2p_get_persistent_go(wpa_s);
-
- if (!s && !owner && p2p_no_group_iface) {
+ if (!s && !go_wpa_s && p2p_no_group_iface) {
p2p_set_intended_addr(wpa_s->global->p2p,
+ wpa_s->p2p_mgmt ?
+ wpa_s->parent->own_addr :
wpa_s->own_addr);
- } else if (!s && !owner) {
+ } else if (!s && !go_wpa_s) {
if (wpas_p2p_add_group_interface(wpa_s,
WPA_IF_P2P_GO) < 0) {
wpa_printf(MSG_ERROR,
if (wpa_s->cross_connect_in_use) {
wpa_s->cross_connect_in_use = 0;
- wpa_msg_global(wpa_s->parent, MSG_INFO,
+ wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
wpa_s->ifname, wpa_s->cross_connect_uplink);
}
break;
}
if (removal_reason != P2P_GROUP_REMOVAL_SILENT) {
- wpa_msg_global(wpa_s->parent, MSG_INFO,
+ wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
P2P_EVENT_GROUP_REMOVED "%s %s%s",
wpa_s->ifname, gtype, reason);
}
if (eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL) > 0)
wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group idle timeout");
if (eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
- wpa_s->parent, NULL) > 0) {
+ wpa_s->p2pdev, NULL) > 0) {
wpa_printf(MSG_DEBUG, "P2P: Cancelled P2P group formation "
"timeout");
wpa_s->p2p_in_provisioning = 0;
return 1;
}
+ /*
+ * The primary interface was used for P2P group operations, so
+ * need to reset its p2pdev.
+ */
+ wpa_s->p2pdev = wpa_s->parent;
+
if (!wpa_s->p2p_go_group_formation_completed) {
wpa_s->global->p2p_group_formation = NULL;
wpa_s->p2p_in_provisioning = 0;
"go_dev_addr=" MACSTR,
MAC2STR(bssid), group_capab, MAC2STR(go_dev_addr));
- return group_capab & P2P_GROUP_CAPAB_PERSISTENT_GROUP;
+ return !!(group_capab & P2P_GROUP_CAPAB_PERSISTENT_GROUP);
}
s->auth_alg = WPA_AUTH_ALG_OPEN;
s->key_mgmt = WPA_KEY_MGMT_PSK;
s->proto = WPA_PROTO_RSN;
- s->pairwise_cipher = WPA_CIPHER_CCMP;
+ s->pbss = ssid->pbss;
+ s->pairwise_cipher = ssid->pbss ? WPA_CIPHER_GCMP : WPA_CIPHER_CCMP;
s->export_keys = 1;
if (ssid->passphrase) {
os_free(s->passphrase);
* Include PSK/passphrase only in the control interface message and
* leave it out from the debug log entry.
*/
- wpa_msg_global_ctrl(wpa_s->parent, MSG_INFO,
+ wpa_msg_global_ctrl(wpa_s->p2pdev, MSG_INFO,
P2P_EVENT_GROUP_STARTED
"%s %s ssid=\"%s\" freq=%d%s%s%s%s%s go_dev_addr="
MACSTR "%s%s",
int client;
int persistent;
u8 go_dev_addr[ETH_ALEN];
- int network_id = -1;
/*
* This callback is likely called for the main interface. Update wpa_s
wpa_s->group_formation_reported = 1;
if (!success) {
- wpa_msg_global(wpa_s->parent, MSG_INFO,
+ wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
P2P_EVENT_GROUP_FORMATION_FAILURE);
wpas_notify_p2p_group_formation_failure(wpa_s, "");
if (already_deleted)
return;
}
- wpa_msg_global(wpa_s->parent, MSG_INFO,
+ wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
P2P_EVENT_GROUP_FORMATION_SUCCESS);
ssid = wpa_s->current_ssid;
}
if (persistent)
- network_id = wpas_p2p_store_persistent_group(wpa_s->parent,
- ssid, go_dev_addr);
+ wpas_p2p_store_persistent_group(wpa_s->p2pdev,
+ ssid, go_dev_addr);
else {
os_free(wpa_s->global->add_psk);
wpa_s->global->add_psk = NULL;
}
- if (network_id < 0 && ssid)
- network_id = ssid->id;
+
if (!client) {
- wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 0);
+ wpas_notify_p2p_group_started(wpa_s, ssid, persistent, 0);
os_get_reltime(&wpa_s->global->p2p_go_wait_client);
}
}
};
+static void wpas_p2p_free_send_action_work(struct wpa_supplicant *wpa_s)
+{
+ struct send_action_work *awork = wpa_s->p2p_send_action_work->ctx;
+
+ wpa_printf(MSG_DEBUG,
+ "P2P: Free Action frame radio work @%p (freq=%u dst="
+ MACSTR " src=" MACSTR " bssid=" MACSTR " wait_time=%u)",
+ wpa_s->p2p_send_action_work, awork->freq,
+ MAC2STR(awork->dst), MAC2STR(awork->src),
+ MAC2STR(awork->bssid), awork->wait_time);
+ wpa_hexdump(MSG_DEBUG, "P2P: Freeing pending Action frame",
+ awork->buf, awork->len);
+ os_free(awork);
+ wpa_s->p2p_send_action_work->ctx = NULL;
+ radio_work_done(wpa_s->p2p_send_action_work);
+ wpa_s->p2p_send_action_work = NULL;
+}
+
+
static void wpas_p2p_send_action_work_timeout(void *eloop_ctx,
void *timeout_ctx)
{
return;
wpa_printf(MSG_DEBUG, "P2P: Send Action frame radio work timed out");
- os_free(wpa_s->p2p_send_action_work->ctx);
- radio_work_done(wpa_s->p2p_send_action_work);
- wpa_s->p2p_send_action_work = NULL;
+ wpas_p2p_free_send_action_work(wpa_s);
}
{
if (wpa_s->p2p_send_action_work) {
struct send_action_work *awork;
+
awork = wpa_s->p2p_send_action_work->ctx;
+ wpa_printf(MSG_DEBUG,
+ "P2P: Clear Action TX work @%p (wait_time=%u)",
+ wpa_s->p2p_send_action_work, awork->wait_time);
if (awork->wait_time == 0) {
- os_free(awork);
- radio_work_done(wpa_s->p2p_send_action_work);
- wpa_s->p2p_send_action_work = NULL;
+ wpas_p2p_free_send_action_work(wpa_s);
} else {
/*
* In theory, this should not be needed, but number of
wpa_s->pending_pd_before_join = 0;
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No ACK for PD Req "
"during p2p_connect-auto");
- wpa_msg_global(wpa_s->parent, MSG_INFO,
+ wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
P2P_EVENT_FALLBACK_TO_GO_NEG
"reason=no-ACK-to-PD-Req");
wpas_p2p_fallback_to_go_neg(wpa_s, 0);
} else if (res->wps_method == WPS_NFC) {
wpas_wps_start_nfc(wpa_s, res->peer_device_addr,
res->peer_interface_addr,
- wpa_s->parent->p2p_oob_dev_pw,
- wpa_s->parent->p2p_oob_dev_pw_id, 1,
- wpa_s->parent->p2p_oob_dev_pw_id ==
+ wpa_s->p2pdev->p2p_oob_dev_pw,
+ wpa_s->p2pdev->p2p_oob_dev_pw_id, 1,
+ wpa_s->p2pdev->p2p_oob_dev_pw_id ==
DEV_PW_NFC_CONNECTION_HANDOVER ?
- wpa_s->parent->p2p_peer_oob_pubkey_hash :
+ wpa_s->p2pdev->p2p_peer_oob_pubkey_hash :
NULL,
NULL, 0, 0);
#endif /* CONFIG_WPS_NFC */
if (!wpa_s->ap_iface)
return;
- persistent = wpas_p2p_get_persistent(wpa_s->parent, NULL, ssid->ssid,
+ persistent = wpas_p2p_get_persistent(wpa_s->p2pdev, NULL, ssid->ssid,
ssid->ssid_len);
if (persistent == NULL)
return;
static void p2p_config_write(struct wpa_supplicant *wpa_s)
{
#ifndef CONFIG_NO_CONFIG_WRITE
- if (wpa_s->parent->conf->update_config &&
- wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf))
+ if (wpa_s->p2pdev->conf->update_config &&
+ wpa_config_write(wpa_s->p2pdev->confname, wpa_s->p2pdev->conf))
wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
#endif /* CONFIG_NO_CONFIG_WRITE */
}
struct wpa_supplicant *wpa_s = ctx;
struct p2p_go_neg_results *params = data;
struct wpa_ssid *ssid;
- int network_id = -1;
+
+ wpa_s->ap_configured_cb = NULL;
+ wpa_s->ap_configured_cb_ctx = NULL;
+ wpa_s->ap_configured_cb_data = NULL;
+ if (!wpa_s->go_params) {
+ wpa_printf(MSG_ERROR,
+ "P2P: p2p_go_configured() called with wpa_s->go_params == NULL");
+ return;
+ }
p2p_go_save_group_common_freqs(wpa_s, params);
p2p_go_dump_common_freqs(wpa_s);
params->persistent_group, "");
wpa_s->group_formation_reported = 1;
- if (wpa_s->parent->p2ps_method_config_any) {
- if (is_zero_ether_addr(wpa_s->parent->p2ps_join_addr)) {
+ if (wpa_s->p2pdev->p2ps_method_config_any) {
+ if (is_zero_ether_addr(wpa_s->p2pdev->p2ps_join_addr)) {
wpa_dbg(wpa_s, MSG_DEBUG,
"P2PS: Setting default PIN for ANY");
wpa_supplicant_ap_wps_pin(wpa_s, NULL,
} else {
wpa_dbg(wpa_s, MSG_DEBUG,
"P2PS: Setting default PIN for " MACSTR,
- MAC2STR(wpa_s->parent->p2ps_join_addr));
+ MAC2STR(wpa_s->p2pdev->p2ps_join_addr));
wpa_supplicant_ap_wps_pin(
- wpa_s, wpa_s->parent->p2ps_join_addr,
+ wpa_s, wpa_s->p2pdev->p2ps_join_addr,
"12345670", NULL, 0, 0);
}
- wpa_s->parent->p2ps_method_config_any = 0;
+ wpa_s->p2pdev->p2ps_method_config_any = 0;
}
os_get_reltime(&wpa_s->global->p2p_go_wait_client);
if (params->persistent_group) {
- network_id = wpas_p2p_store_persistent_group(
- wpa_s->parent, ssid,
+ wpas_p2p_store_persistent_group(
+ wpa_s->p2pdev, ssid,
wpa_s->global->p2p_dev_addr);
wpas_p2p_add_psk_list(wpa_s, ssid);
}
- if (network_id < 0)
- network_id = ssid->id;
- wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 0);
+
+ wpas_notify_p2p_group_started(wpa_s, ssid,
+ params->persistent_group, 0);
wpas_p2p_cross_connect_setup(wpa_s);
wpas_p2p_set_group_idle_timeout(wpa_s);
wpa_s->p2p_go_group_formation_completed = 0;
wpa_s->global->p2p_group_formation = wpa_s;
eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
- wpa_s->parent, NULL);
+ wpa_s->p2pdev, NULL);
eloop_register_timeout(
wpa_s->p2p_first_connection_timeout, 0,
wpas_p2p_group_formation_timeout,
- wpa_s->parent, NULL);
+ wpa_s->p2pdev, NULL);
}
return;
params->peer_device_addr);
#ifdef CONFIG_WPS_NFC
} else if (params->wps_method == WPS_NFC) {
- if (wpa_s->parent->p2p_oob_dev_pw_id !=
+ if (wpa_s->p2pdev->p2p_oob_dev_pw_id !=
DEV_PW_NFC_CONNECTION_HANDOVER &&
- !wpa_s->parent->p2p_oob_dev_pw) {
+ !wpa_s->p2pdev->p2p_oob_dev_pw) {
wpa_printf(MSG_DEBUG, "P2P: No NFC Dev Pw known");
return;
}
wpas_ap_wps_add_nfc_pw(
- wpa_s, wpa_s->parent->p2p_oob_dev_pw_id,
- wpa_s->parent->p2p_oob_dev_pw,
- wpa_s->parent->p2p_peer_oob_pk_hash_known ?
- wpa_s->parent->p2p_peer_oob_pubkey_hash : NULL);
+ wpa_s, wpa_s->p2pdev->p2p_oob_dev_pw_id,
+ wpa_s->p2pdev->p2p_oob_dev_pw,
+ wpa_s->p2pdev->p2p_peer_oob_pk_hash_known ?
+ wpa_s->p2pdev->p2p_peer_oob_pubkey_hash : NULL);
#endif /* CONFIG_WPS_NFC */
} else if (wpa_s->p2p_pin[0])
wpa_supplicant_ap_wps_pin(wpa_s, params->peer_interface_addr,
wpa_config_set_network_defaults(ssid);
ssid->temporary = 1;
ssid->p2p_group = 1;
- ssid->p2p_persistent_group = params->persistent_group;
+ ssid->p2p_persistent_group = !!params->persistent_group;
ssid->mode = group_formation ? WPAS_MODE_P2P_GROUP_FORMATION :
WPAS_MODE_P2P_GO;
ssid->frequency = params->freq;
ssid->ht40 = params->ht40;
ssid->vht = params->vht;
+ ssid->max_oper_chwidth = params->max_oper_chwidth;
+ ssid->vht_center_freq2 = params->vht_center_freq2;
ssid->ssid = os_zalloc(params->ssid_len + 1);
if (ssid->ssid) {
os_memcpy(ssid->ssid, params->ssid, params->ssid_len);
*/
ssid->pairwise_cipher = WPA_CIPHER_GCMP;
ssid->group_cipher = WPA_CIPHER_GCMP;
+ /* P2P GO in 60 GHz is always a PCP (PBSS) */
+ ssid->pbss = 1;
}
if (os_strlen(params->passphrase) > 0) {
ssid->passphrase = os_strdup(params->passphrase);
os_memcpy(ssid->psk, params->psk, sizeof(ssid->psk));
else if (ssid->passphrase)
wpa_config_update_psk(ssid);
- ssid->ap_max_inactivity = wpa_s->parent->conf->p2p_go_max_inactivity;
+ ssid->ap_max_inactivity = wpa_s->p2pdev->conf->p2p_go_max_inactivity;
wpa_s->ap_configured_cb = p2p_go_configured;
wpa_s->ap_configured_cb_ctx = wpa_s;
d = dst->conf;
s = src->conf;
-#define C(n) if (s->n) d->n = os_strdup(s->n)
+#define C(n) \
+do { \
+ if (s->n && !d->n) \
+ d->n = os_strdup(s->n); \
+} while (0)
+
C(device_name);
C(manufacturer);
C(model_name);
d->disable_scan_offload = s->disable_scan_offload;
d->passive_scan = s->passive_scan;
- if (s->wps_nfc_dh_privkey && s->wps_nfc_dh_pubkey) {
+ if (s->wps_nfc_dh_privkey && s->wps_nfc_dh_pubkey &&
+ !d->wps_nfc_pw_from_config) {
+ wpabuf_free(d->wps_nfc_dh_privkey);
+ wpabuf_free(d->wps_nfc_dh_pubkey);
d->wps_nfc_dh_privkey = wpabuf_dup(s->wps_nfc_dh_privkey);
d->wps_nfc_dh_pubkey = wpabuf_dup(s->wps_nfc_dh_pubkey);
}
int already_deleted)
{
eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
- wpa_s->parent, NULL);
+ wpa_s->p2pdev, NULL);
if (wpa_s->global->p2p)
p2p_group_formation_failed(wpa_s->global->p2p);
wpas_group_formation_completed(wpa_s, 0, already_deleted);
{
wpa_printf(MSG_DEBUG, "P2P: Reject group formation due to WPS provisioning failure");
eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
- wpa_s->parent, NULL);
+ wpa_s->p2pdev, NULL);
eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout,
- wpa_s->parent, NULL);
+ wpa_s->p2pdev, NULL);
wpa_s->global->p2p_fail_on_wps_complete = 0;
}
return;
/* Speed up group formation timeout since this cannot succeed */
eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
- wpa_s->parent, NULL);
+ wpa_s->p2pdev, NULL);
eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout,
- wpa_s->parent, NULL);
+ wpa_s->p2pdev, NULL);
}
static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
{
struct wpa_supplicant *wpa_s = ctx;
+ struct wpa_supplicant *group_wpa_s;
if (wpa_s->off_channel_freq || wpa_s->roc_waiting_drv_freq) {
wpa_drv_cancel_remain_on_channel(wpa_s);
res->ht40 = 1;
if (wpa_s->p2p_go_vht)
res->vht = 1;
+ res->max_oper_chwidth = wpa_s->p2p_go_max_oper_chwidth;
+ res->vht_center_freq2 = wpa_s->p2p_go_vht_center_freq2;
wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_SUCCESS "role=%s "
"freq=%d ht40=%d peer_dev=" MACSTR " peer_iface=" MACSTR
}
if (wpa_s->create_p2p_iface) {
- struct wpa_supplicant *group_wpa_s =
+ group_wpa_s =
wpas_p2p_init_group_interface(wpa_s, res->role_go);
if (group_wpa_s == NULL) {
wpas_p2p_remove_pending_group_interface(wpa_s);
wpas_p2p_group_formation_failed(wpa_s, 1);
return;
}
- if (group_wpa_s != wpa_s) {
- os_memcpy(group_wpa_s->p2p_pin, wpa_s->p2p_pin,
- sizeof(group_wpa_s->p2p_pin));
- group_wpa_s->p2p_wps_method = wpa_s->p2p_wps_method;
- }
os_memset(wpa_s->pending_interface_addr, 0, ETH_ALEN);
wpa_s->pending_interface_name[0] = '\0';
- group_wpa_s->p2p_in_provisioning = 1;
-
- if (res->role_go) {
- wpas_start_wps_go(group_wpa_s, res, 1);
- } else {
- os_get_reltime(&group_wpa_s->scan_min_time);
- wpas_start_wps_enrollee(group_wpa_s, res);
- }
} else {
- wpa_s->p2p_in_provisioning = 1;
- wpa_s->global->p2p_group_formation = wpa_s;
+ group_wpa_s = wpa_s->parent;
+ wpa_s->global->p2p_group_formation = group_wpa_s;
+ if (group_wpa_s != wpa_s)
+ wpas_p2p_clone_config(group_wpa_s, wpa_s);
+ }
- if (res->role_go) {
- wpas_start_wps_go(wpa_s, res, 1);
- } else {
- os_get_reltime(&wpa_s->scan_min_time);
- wpas_start_wps_enrollee(ctx, res);
- }
+ group_wpa_s->p2p_in_provisioning = 1;
+ group_wpa_s->p2pdev = wpa_s;
+ if (group_wpa_s != wpa_s) {
+ os_memcpy(group_wpa_s->p2p_pin, wpa_s->p2p_pin,
+ sizeof(group_wpa_s->p2p_pin));
+ group_wpa_s->p2p_wps_method = wpa_s->p2p_wps_method;
+ }
+ if (res->role_go) {
+ wpas_start_wps_go(group_wpa_s, res, 1);
+ } else {
+ os_get_reltime(&group_wpa_s->scan_min_time);
+ wpas_start_wps_enrollee(group_wpa_s, res);
}
wpa_s->p2p_long_listen = 0;
static void wpas_find_stopped(void *ctx)
{
struct wpa_supplicant *wpa_s = ctx;
+
+ if (wpa_s->p2p_scan_work && wpas_abort_ongoing_scan(wpa_s) < 0)
+ wpa_printf(MSG_DEBUG, "P2P: Abort ongoing scan failed");
+
wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_FIND_STOPPED);
wpas_notify_p2p_find_stopped(wpa_s);
}
params[sizeof(params) - 1] = '\0';
if (config_methods & WPS_CONFIG_DISPLAY) {
- generated_pin = wps_generate_pin();
+ if (wps_generate_pin(&generated_pin) < 0) {
+ wpa_printf(MSG_DEBUG, "P2P: Could not generate PIN");
+ wpas_notify_p2p_provision_discovery(
+ wpa_s, peer, 0 /* response */,
+ P2P_PROV_DISC_INFO_UNAVAILABLE, 0, 0);
+ return;
+ }
wpas_prov_disc_local_display(wpa_s, peer, params,
generated_pin);
} else if (config_methods & WPS_CONFIG_KEYPAD)
if (config_methods & WPS_CONFIG_DISPLAY)
wpas_prov_disc_local_keypad(wpa_s, peer, params);
else if (config_methods & WPS_CONFIG_KEYPAD) {
- generated_pin = wps_generate_pin();
+ if (wps_generate_pin(&generated_pin) < 0) {
+ wpa_printf(MSG_DEBUG, "P2P: Could not generate PIN");
+ wpas_notify_p2p_provision_discovery(
+ wpa_s, peer, 0 /* response */,
+ P2P_PROV_DISC_INFO_UNAVAILABLE, 0, 0);
+ return;
+ }
wpas_prov_disc_local_display(wpa_s, peer, params,
generated_pin);
} else if (config_methods & WPS_CONFIG_PUSHBUTTON)
if (wpa_s->p2p_fallback_to_go_neg) {
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: PD for p2p_connect-auto "
"failed - fall back to GO Negotiation");
- wpa_msg_global(wpa_s->parent, MSG_INFO,
+ wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
P2P_EVENT_FALLBACK_TO_GO_NEG
"reason=PD-failed");
wpas_p2p_fallback_to_go_neg(wpa_s, 0);
}
+static int wpas_sta_check_ecsa(struct hostapd_data *hapd,
+ struct sta_info *sta, void *ctx)
+{
+ int *ecsa_support = ctx;
+
+ *ecsa_support &= sta->ecsa_supported;
+
+ return 0;
+}
+
+
+/* Check if all the peers support eCSA */
+static int wpas_p2p_go_clients_support_ecsa(struct wpa_supplicant *wpa_s)
+{
+ int ecsa_support = 1;
+
+ ap_for_each_sta(wpa_s->ap_iface->bss[0], wpas_sta_check_ecsa,
+ &ecsa_support);
+
+ return ecsa_support;
+}
+
+
/**
* Pick the best frequency to use from all the currently used frequencies.
*/
"invitation");
return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
}
- os_memcpy(group_bssid, wpa_s->own_addr, ETH_ALEN);
+ if (wpa_s->p2p_mgmt)
+ os_memcpy(group_bssid, wpa_s->parent->own_addr,
+ ETH_ALEN);
+ else
+ os_memcpy(group_bssid, wpa_s->own_addr, ETH_ALEN);
} else if (s->mode == WPAS_MODE_P2P_GO) {
*go = 1;
if (wpas_p2p_add_group_interface(wpa_s, WPA_IF_P2P_GO) < 0)
MAC2STR(sa), op_freq, wpa_ssid_txt(ssid, ssid_len));
if (s) {
int go = s->mode == WPAS_MODE_P2P_GO;
+ if (go) {
+ wpa_msg_global(wpa_s, MSG_INFO,
+ P2P_EVENT_INVITATION_ACCEPTED
+ "sa=" MACSTR
+ " persistent=%d freq=%d",
+ MAC2STR(sa), s->id, op_freq);
+ } else {
+ wpa_msg_global(wpa_s, MSG_INFO,
+ P2P_EVENT_INVITATION_ACCEPTED
+ "sa=" MACSTR
+ " persistent=%d",
+ MAC2STR(sa), s->id);
+ }
wpas_p2p_group_add_persistent(
- wpa_s, s, go, 0, op_freq, 0, 0, NULL,
+ wpa_s, s, go, 0, op_freq, 0, 0, 0, 0, NULL,
go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0,
1);
} else if (bssid) {
wpa_s->user_initiated_pd = 0;
+ wpa_msg_global(wpa_s, MSG_INFO,
+ P2P_EVENT_INVITATION_ACCEPTED
+ "sa=" MACSTR " go_dev_addr=" MACSTR
+ " bssid=" MACSTR " unknown-network",
+ MAC2STR(sa), MAC2STR(go_dev_addr),
+ MAC2STR(bssid));
wpas_p2p_join(wpa_s, bssid, go_dev_addr,
wpa_s->p2p_wps_method, 0, op_freq,
ssid, ssid_len);
if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO ||
!ssid->p2p_persistent_group)
return; /* Not operating as a GO in persistent group */
- ssid = wpas_p2p_get_persistent(wpa_s->parent, peer,
+ ssid = wpas_p2p_get_persistent(wpa_s->p2pdev, peer,
ssid->ssid, ssid->ssid_len);
wpas_remove_persistent_peer(wpa_s, ssid, peer, 1);
}
wpa_printf(MSG_DEBUG, "P2P: Invitation result - status=%d peer=" MACSTR,
status, MAC2STR(peer));
if (wpa_s->pending_invite_ssid_id == -1) {
+ struct wpa_supplicant *group_if =
+ wpa_s->global->p2p_invite_group;
+
if (status == P2P_SC_FAIL_UNKNOWN_GROUP)
wpas_remove_persistent_client(wpa_s, peer);
- return; /* Invitation to active group */
+
+ /*
+ * Invitation to an active group. If this is successful and we
+ * are the GO, set the client wait to postpone some concurrent
+ * operations and to allow provisioning and connection to happen
+ * more quickly.
+ */
+ if (status == P2P_SC_SUCCESS &&
+ group_if && group_if->current_ssid &&
+ group_if->current_ssid->mode == WPAS_MODE_P2P_GO) {
+ os_get_reltime(&wpa_s->global->p2p_go_wait_client);
+#ifdef CONFIG_TESTING_OPTIONS
+ if (group_if->p2p_go_csa_on_inv) {
+ wpa_printf(MSG_DEBUG,
+ "Testing: force P2P GO CSA after invitation");
+ eloop_cancel_timeout(
+ wpas_p2p_reconsider_moving_go,
+ wpa_s, NULL);
+ eloop_register_timeout(
+ 0, 50000,
+ wpas_p2p_reconsider_moving_go,
+ wpa_s, NULL);
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+ }
+ return;
}
if (status == P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE) {
ssid->mode == WPAS_MODE_P2P_GO,
wpa_s->p2p_persistent_go_freq,
freq,
+ wpa_s->p2p_go_vht_center_freq2,
wpa_s->p2p_go_ht40, wpa_s->p2p_go_vht,
+ wpa_s->p2p_go_max_oper_chwidth,
channels,
ssid->mode == WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
}
-static struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
- u16 num_modes,
- enum hostapd_hw_mode mode)
-{
- u16 i;
-
- for (i = 0; i < num_modes; i++) {
- if (modes[i].mode == mode)
- return &modes[i];
- }
-
- return NULL;
-}
-
-
enum chan_allowed {
NOT_ALLOWED, NO_IR, ALLOWED
};
}
-struct p2p_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 } bw;
-};
-
-static const struct p2p_oper_class_map op_class[] = {
- { HOSTAPD_MODE_IEEE80211G, 81, 1, 13, 1, BW20 },
-#if 0 /* Do not enable HT40 on 2 GHz for now */
- { HOSTAPD_MODE_IEEE80211G, 83, 1, 9, 1, BW40PLUS },
- { HOSTAPD_MODE_IEEE80211G, 84, 5, 13, 1, BW40MINUS },
-#endif
- { HOSTAPD_MODE_IEEE80211A, 115, 36, 48, 4, BW20 },
- { HOSTAPD_MODE_IEEE80211A, 124, 149, 161, 4, BW20 },
- { HOSTAPD_MODE_IEEE80211A, 125, 149, 169, 4, BW20 },
- { HOSTAPD_MODE_IEEE80211A, 116, 36, 44, 8, BW40PLUS },
- { HOSTAPD_MODE_IEEE80211A, 117, 40, 48, 8, BW40MINUS },
- { HOSTAPD_MODE_IEEE80211A, 126, 149, 157, 8, BW40PLUS },
- { HOSTAPD_MODE_IEEE80211A, 127, 153, 161, 8, BW40MINUS },
-
- /*
- * 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
- * has_channel() fail). wpas_p2p_verify_80mhz() should take care of
- * removing invalid channels.
- */
- { HOSTAPD_MODE_IEEE80211A, 128, 36, 161, 4, BW80 },
- { HOSTAPD_MODE_IEEE80211AD, 180, 1, 4, 1, BW2160 },
- { -1, 0, 0, 0, 0, BW20 }
-};
-
-
static int wpas_p2p_get_center_80mhz(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode,
u8 channel)
{
u8 center_channels[] = { 42, 58, 106, 122, 138, 155 };
- unsigned int i;
+ size_t i;
if (mode->mode != HOSTAPD_MODE_IEEE80211A)
return 0;
}
+static int wpas_p2p_get_center_160mhz(struct wpa_supplicant *wpa_s,
+ struct hostapd_hw_modes *mode,
+ u8 channel)
+{
+ u8 center_channels[] = { 50, 114 };
+ unsigned int i;
+
+ if (mode->mode != HOSTAPD_MODE_IEEE80211A)
+ return 0;
+
+ for (i = 0; i < ARRAY_SIZE(center_channels); i++)
+ /*
+ * In 160 MHz, the bandwidth "spans" 28 channels (e.g., 36-64),
+ * so the center channel is 14 channels away from the start/end.
+ */
+ if (channel >= center_channels[i] - 14 &&
+ channel <= center_channels[i] + 14)
+ return center_channels[i];
+
+ return 0;
+}
+
+
+static enum chan_allowed wpas_p2p_verify_160mhz(struct wpa_supplicant *wpa_s,
+ struct hostapd_hw_modes *mode,
+ u8 channel, u8 bw)
+{
+ u8 center_chan;
+ int i, flags;
+ enum chan_allowed res, ret = ALLOWED;
+
+ center_chan = wpas_p2p_get_center_160mhz(wpa_s, mode, channel);
+ if (!center_chan)
+ return NOT_ALLOWED;
+ /* VHT 160 MHz uses DFS channels in most countries. */
+
+ /* Check all the channels are available */
+ for (i = 0; i < 8; i++) {
+ int adj_chan = center_chan - 14 + i * 4;
+
+ res = has_channel(wpa_s->global, mode, adj_chan, &flags);
+ if (res == NOT_ALLOWED)
+ return NOT_ALLOWED;
+
+ if (res == NO_IR)
+ ret = NO_IR;
+
+ if (i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_150))
+ return NOT_ALLOWED;
+ if (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_130))
+ return NOT_ALLOWED;
+ if (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_110))
+ return NOT_ALLOWED;
+ if (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_90))
+ return NOT_ALLOWED;
+ if (i == 4 && !(flags & HOSTAPD_CHAN_VHT_90_70))
+ return NOT_ALLOWED;
+ if (i == 5 && !(flags & HOSTAPD_CHAN_VHT_110_50))
+ return NOT_ALLOWED;
+ if (i == 6 && !(flags & HOSTAPD_CHAN_VHT_130_30))
+ return NOT_ALLOWED;
+ if (i == 7 && !(flags & HOSTAPD_CHAN_VHT_150_10))
+ return NOT_ALLOWED;
+ }
+
+ return ret;
+}
+
+
static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode,
u8 channel, u8 bw)
res2 = has_channel(wpa_s->global, mode, channel + 4, NULL);
} else if (bw == BW80) {
res2 = wpas_p2p_verify_80mhz(wpa_s, mode, channel, bw);
+ } else if (bw == BW160) {
+ res2 = wpas_p2p_verify_160mhz(wpa_s, mode, channel, bw);
}
if (res == NOT_ALLOWED || res2 == NOT_ALLOWED)
cla = cli_cla = 0;
- for (op = 0; op_class[op].op_class; op++) {
- const struct p2p_oper_class_map *o = &op_class[op];
+ for (op = 0; global_op_class[op].op_class; op++) {
+ const struct oper_class_map *o = &global_op_class[op];
u8 ch;
struct p2p_reg_class *reg = NULL, *cli_reg = NULL;
+ if (o->p2p == NO_P2P_SUPP)
+ continue;
+
mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, o->mode);
if (mode == NULL)
continue;
int op;
enum chan_allowed ret;
- for (op = 0; op_class[op].op_class; op++) {
- const struct p2p_oper_class_map *o = &op_class[op];
+ for (op = 0; global_op_class[op].op_class; op++) {
+ const struct oper_class_map *o = &global_op_class[op];
u8 ch;
+ if (o->p2p == NO_P2P_SUPP)
+ continue;
+
for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
if (o->mode != HOSTAPD_MODE_IEEE80211A ||
(o->bw != BW40PLUS && o->bw != BW40MINUS) ||
}
+int wpas_p2p_get_vht160_center(struct wpa_supplicant *wpa_s,
+ struct hostapd_hw_modes *mode, u8 channel)
+{
+ if (!wpas_p2p_verify_channel(wpa_s, mode, channel, BW160))
+ return 0;
+ return wpas_p2p_get_center_160mhz(wpa_s, mode, channel);
+}
+
+
static int wpas_get_noa(void *ctx, const u8 *interface_addr, u8 *buf,
size_t buf_len)
{
return -1;
}
+ p2pdev_wpa_s->p2pdev = p2pdev_wpa_s;
wpa_s->pending_interface_name[0] = '\0';
return 0;
}
static int wpas_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)
{
struct wpa_supplicant *wpa_s = ctx;
+ struct wpa_supplicant *go;
struct wpa_ssid *s;
- u8 bssid[ETH_ALEN];
/*
* group_iface will be set to 1 only if a dedicated interface for P2P
* that the pending interface should be used.
*/
*group_iface = 0;
- s = wpas_p2p_group_go_ssid(wpa_s, bssid);
- if (!s) {
+
+ if (freq)
+ *freq = 0;
+
+ go = wpas_p2p_get_go_group(wpa_s);
+ if (!go) {
s = wpas_p2p_get_persistent_go(wpa_s);
*group_iface = wpas_p2p_create_iface(wpa_s);
if (s)
- os_memcpy(bssid, s->bssid, ETH_ALEN);
+ os_memcpy(intended_addr, s->bssid, ETH_ALEN);
else
return 0;
+ } else {
+ s = go->current_ssid;
+ os_memcpy(intended_addr, go->own_addr, ETH_ALEN);
+ if (freq)
+ *freq = go->assoc_freq;
}
- os_memcpy(intended_addr, bssid, ETH_ALEN);
os_memcpy(ssid, s->ssid, s->ssid_len);
*ssid_len = s->ssid_len;
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)
{
struct wpa_supplicant *wpa_s = ctx;
u8 mac[ETH_ALEN];
- struct wpa_ssid *persistent_go, *stale, *s;
+ struct wpa_ssid *persistent_go, *stale, *s = NULL;
int save_config = 0;
struct wpa_supplicant *go_wpa_s;
char feat_cap_str[256];
}
/* Clean up stale persistent groups with this device */
- s = wpas_p2p_get_persistent(wpa_s, dev, persist_ssid,
- persist_ssid_size);
+ if (persist_ssid && persist_ssid_size)
+ s = wpas_p2p_get_persistent(wpa_s, dev, persist_ssid,
+ persist_ssid_size);
if (persist_ssid && s && s->mode != WPAS_MODE_P2P_GO &&
is_zero_ether_addr(grp_mac)) {
go_ifname[0] = '\0';
if (!go_wpa_s) {
wpa_s->global->pending_p2ps_group = 1;
+ wpa_s->global->pending_p2ps_group_freq = freq;
if (!wpas_p2p_create_iface(wpa_s))
os_memcpy(go_ifname, wpa_s->ifname,
wpa_s, P2P_SC_FAIL_UNKNOWN_GROUP,
dev, adv_mac, ses_mac,
grp_mac, adv_id, ses_id, 0, 0,
- NULL, 0, 0, 0, NULL, NULL, 0);
+ NULL, 0, 0, 0, NULL, NULL, 0, 0,
+ NULL, 0);
return;
}
if (response_done && persistent_go) {
wpas_p2p_group_add_persistent(
wpa_s, persistent_go,
- 0, 0, 0, 0, 0, NULL,
+ 0, 0, freq, 0, 0, 0, 0, NULL,
persistent_go->mode ==
WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
0, 0);
} else if (response_done) {
- wpas_p2p_group_add(wpa_s, 1, 0, 0, 0);
+ wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0);
}
if (passwd_id == DEV_PW_P2PS_DEFAULT) {
}
if (conncap == P2PS_SETUP_CLIENT) {
+ char ssid_hex[32 * 2 + 1];
+
+ if (group_ssid)
+ wpa_snprintf_hex(ssid_hex, sizeof(ssid_hex),
+ group_ssid, group_ssid_len);
+ else
+ ssid_hex[0] = '\0';
wpa_msg_global(wpa_s, MSG_INFO,
P2P_EVENT_P2PS_PROVISION_DONE MACSTR
" status=%d conncap=%x"
" adv_id=%x adv_mac=" MACSTR
" session=%x mac=" MACSTR
- " dev_passwd_id=%d join=" MACSTR "%s",
+ " dev_passwd_id=%d join=" MACSTR "%s%s%s",
MAC2STR(dev), status, conncap,
adv_id, MAC2STR(adv_mac),
ses_id, MAC2STR(ses_mac),
- passwd_id, MAC2STR(grp_mac), feat_cap_str);
+ passwd_id, MAC2STR(grp_mac), feat_cap_str,
+ group_ssid ? " group_ssid=" : "", ssid_hex);
} else {
wpa_msg_global(wpa_s, MSG_INFO,
P2P_EVENT_P2PS_PROVISION_DONE MACSTR
{
struct wpa_supplicant *wpa_s = ctx;
struct wpa_ssid *persistent_go;
+ unsigned int freq;
if (!wpa_s->global->pending_p2ps_group)
return 0;
+ freq = wpa_s->global->pending_p2ps_group_freq;
+ wpa_s->global->pending_p2ps_group_freq = 0;
wpa_s->global->pending_p2ps_group = 0;
if (wpas_p2p_get_go_group(wpa_s))
if (persistent_go) {
wpas_p2p_group_add_persistent(
- wpa_s, persistent_go, 0, 0, 0, 0, 0, NULL,
+ wpa_s, persistent_go, 0, 0, 0, 0, 0, 0, 0, NULL,
persistent_go->mode == WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 0);
} else {
- wpas_p2p_group_add(wpa_s, 1, 0, 0, 0);
+ wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0);
}
return 1;
static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s)
{
- if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
- wpa_s->conf->p2p_no_group_iface)
+ if (wpa_s->conf->p2p_no_group_iface)
return 0; /* separate interface disabled per configuration */
if (wpa_s->drv_flags &
(WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE |
MAC2STR(wpa_s->pending_join_dev_addr));
return;
}
- wpa_msg_global(wpa_s->parent, MSG_INFO,
+ wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
P2P_EVENT_GROUP_FORMATION_FAILURE);
wpas_notify_p2p_group_formation_failure(wpa_s, "");
}
if (join < 0) {
wpa_printf(MSG_DEBUG, "P2P: Peer was not found to be "
"running a GO -> use GO Negotiation");
- wpa_msg_global(wpa_s->parent, MSG_INFO,
+ wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
P2P_EVENT_FALLBACK_TO_GO_NEG
"reason=peer-not-running-GO");
wpas_p2p_connect(wpa_s, wpa_s->pending_join_dev_addr,
wpa_s->p2p_persistent_group, 0, 0, 0,
wpa_s->p2p_go_intent,
wpa_s->p2p_connect_freq,
+ wpa_s->p2p_go_vht_center_freq2,
wpa_s->p2p_persistent_id,
wpa_s->p2p_pd_before_go_neg,
wpa_s->p2p_go_ht40,
- wpa_s->p2p_go_vht);
+ wpa_s->p2p_go_vht,
+ wpa_s->p2p_go_max_oper_chwidth,
+ NULL, 0);
return;
}
"try to join the group", join ? "" :
" in older scan");
if (!join) {
- wpa_msg_global(wpa_s->parent, MSG_INFO,
+ wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
P2P_EVENT_FALLBACK_TO_GO_NEG_ENABLED);
wpa_s->p2p_fallback_to_go_neg = 1;
}
bss = wpa_bss_get(wpa_s, wpa_s->pending_join_iface_addr,
wpa_s->p2p_join_ssid,
wpa_s->p2p_join_ssid_len);
- }
- if (!bss) {
+ } else if (!bss) {
wpa_printf(MSG_DEBUG, "P2P: Trying to find target GO BSS entry based on BSSID "
MACSTR, MAC2STR(wpa_s->pending_join_iface_addr));
bss = wpa_bss_get_bssid_latest(wpa_s,
u16 method;
if (wpas_check_freq_conflict(wpa_s, freq) > 0) {
- wpa_msg_global(wpa_s->parent, MSG_INFO,
+ wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
P2P_EVENT_GROUP_FORMATION_FAILURE
"reason=FREQ_CONFLICT");
wpas_notify_p2p_group_formation_failure(
start:
/* Start join operation immediately */
- wpas_p2p_join_start(wpa_s, 0, NULL, 0);
+ wpas_p2p_join_start(wpa_s, 0, wpa_s->p2p_join_ssid,
+ wpa_s->p2p_join_ssid_len);
}
struct wpabuf *wps_ie, *ies;
size_t ielen;
int freqs[2] = { 0, 0 };
+ unsigned int bands;
os_memset(¶ms, 0, sizeof(params));
return;
}
- ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
- ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen);
- if (ies == NULL) {
- wpabuf_free(wps_ie);
- wpas_p2p_scan_res_join(wpa_s, NULL);
- return;
- }
- wpabuf_put_buf(ies, wps_ie);
- wpabuf_free(wps_ie);
-
- p2p_scan_ie(wpa_s->global->p2p, ies, NULL);
-
- params.p2p_probe = 1;
- params.extra_ies = wpabuf_head(ies);
- params.extra_ies_len = wpabuf_len(ies);
-
if (!freq) {
int oper_freq;
/*
params.freqs = freqs;
}
+ ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
+ ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen);
+ if (ies == NULL) {
+ wpabuf_free(wps_ie);
+ wpas_p2p_scan_res_join(wpa_s, NULL);
+ return;
+ }
+ wpabuf_put_buf(ies, wps_ie);
+ wpabuf_free(wps_ie);
+
+ bands = wpas_get_bands(wpa_s, freqs);
+ p2p_scan_ie(wpa_s->global->p2p, ies, NULL, bands);
+
+ params.p2p_probe = 1;
+ params.extra_ies = wpabuf_head(ies);
+ params.extra_ies_len = wpabuf_len(ies);
+
/*
* Run a scan to update BSS table and start Provision Discovery once
* the new scan results become available.
res.ssid_len = ssid_len;
os_memcpy(res.ssid, ssid, ssid_len);
} else {
- bss = wpa_bss_get_bssid_latest(wpa_s,
- wpa_s->pending_join_iface_addr);
+ if (ssid && ssid_len) {
+ bss = wpa_bss_get(wpa_s, wpa_s->pending_join_iface_addr,
+ ssid, ssid_len);
+ } else {
+ bss = wpa_bss_get_bssid_latest(
+ wpa_s, wpa_s->pending_join_iface_addr);
+ }
if (bss) {
res.freq = bss->freq;
res.ssid_len = bss->ssid_len;
wpa_printf(MSG_DEBUG, "P2P: Join target GO operating frequency from BSS table: %d MHz (SSID %s)",
bss->freq,
wpa_ssid_txt(bss->ssid, bss->ssid_len));
+ } else if (ssid && ssid_len) {
+ res.ssid_len = ssid_len;
+ os_memcpy(res.ssid, ssid, ssid_len);
+ wpa_printf(MSG_DEBUG, "P2P: Join target GO (SSID %s)",
+ wpa_ssid_txt(ssid, ssid_len));
}
}
* initiating Group Owner negotiation
* @go_intent: GO Intent or -1 to use default
* @freq: Frequency for the group or 0 for auto-selection
+ * @freq2: Center frequency of segment 1 for the GO operating in VHT 80P80 mode
* @persistent_id: Persistent group credentials to use for forcing GO
* parameters or -1 to generate new values (SSID/passphrase)
* @pd: Whether to send Provision Discovery prior to GO Negotiation as an
* interoperability workaround when initiating group formation
* @ht40: Start GO with 40 MHz channel width
* @vht: Start GO with VHT support
+ * @vht_chwidth: Channel width supported by GO operating with VHT support
+ * (VHT_CHANWIDTH_*).
+ * @group_ssid: Specific Group SSID for join or %NULL if not set
+ * @group_ssid_len: Length of @group_ssid in octets
* Returns: 0 or new PIN (if pin was %NULL) on success, -1 on unspecified
* failure, -2 on failure due to channel not currently available,
* -3 if forced channel is not supported
int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
const char *pin, enum p2p_wps_method wps_method,
int persistent_group, int auto_join, int join, int auth,
- int go_intent, int freq, int persistent_id, int pd,
- int ht40, int vht)
+ int go_intent, int freq, unsigned int vht_center_freq2,
+ int persistent_id, int pd, int ht40, int vht,
+ unsigned int vht_chwidth, const u8 *group_ssid,
+ size_t group_ssid_len)
{
int force_freq = 0, pref_freq = 0;
int ret = 0, res;
wpa_s->global->p2p_fail_on_wps_complete = 0;
wpa_s->global->pending_p2ps_group = 0;
+ wpa_s->global->pending_p2ps_group_freq = 0;
wpa_s->p2ps_method_config_any = 0;
if (go_intent < 0)
wpa_s->p2p_pd_before_go_neg = !!pd;
wpa_s->p2p_go_ht40 = !!ht40;
wpa_s->p2p_go_vht = !!vht;
+ wpa_s->p2p_go_vht_center_freq2 = vht_center_freq2;
+ wpa_s->p2p_go_max_oper_chwidth = vht_chwidth;
if (pin)
os_strlcpy(wpa_s->p2p_pin, pin, sizeof(wpa_s->p2p_pin));
else if (wps_method == WPS_PIN_DISPLAY) {
- ret = wps_generate_pin();
+ if (wps_generate_pin((unsigned int *) &ret) < 0)
+ return -1;
res = os_snprintf(wpa_s->p2p_pin, sizeof(wpa_s->p2p_pin),
"%08d", ret);
if (os_snprintf_error(sizeof(wpa_s->p2p_pin), res))
wpa_s->p2p_pin[sizeof(wpa_s->p2p_pin) - 1] = '\0';
wpa_printf(MSG_DEBUG, "P2P: Randomly generated PIN: %s",
wpa_s->p2p_pin);
+ } else if (wps_method == WPS_P2PS) {
+ /* Force the P2Ps default PIN to be used */
+ os_strlcpy(wpa_s->p2p_pin, "12345670", sizeof(wpa_s->p2p_pin));
} else
wpa_s->p2p_pin[0] = '\0';
}
wpa_s->user_initiated_pd = 1;
if (wpas_p2p_join(wpa_s, iface_addr, dev_addr, wps_method,
- auto_join, freq, NULL, 0) < 0)
+ auto_join, freq,
+ group_ssid, group_ssid_len) < 0)
return -1;
return ret;
}
if_addr = wpa_s->pending_interface_addr;
} else {
- if_addr = wpa_s->own_addr;
+ if (wpa_s->p2p_mgmt)
+ if_addr = wpa_s->parent->own_addr;
+ else
+ if_addr = wpa_s->own_addr;
os_memset(wpa_s->go_dev_addr, 0, ETH_ALEN);
}
static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
struct p2p_go_neg_results *params,
- int freq, int ht40, int vht,
+ int freq, int vht_center_freq2, int ht40,
+ int vht, int max_oper_chwidth,
const struct p2p_channels *channels)
{
struct wpa_used_freq_data *freqs;
unsigned int cand;
unsigned int num, i;
+ int ignore_no_freqs = 0;
+ int unused_channels = wpas_p2p_num_unused_channels(wpa_s) > 0;
os_memset(params, 0, sizeof(*params));
params->role_go = 1;
params->ht40 = ht40;
params->vht = vht;
-
- if (wpa_s->p2p_group_common_freqs_num)
- wpa_printf(MSG_DEBUG, "P2P: %s called for an active GO",
- __func__);
+ params->max_oper_chwidth = max_oper_chwidth;
+ params->vht_center_freq2 = vht_center_freq2;
freqs = os_calloc(wpa_s->num_multichan_concurrent,
sizeof(struct wpa_used_freq_data));
if (!freqs)
return -1;
- num = wpas_p2p_valid_oper_freqs(wpa_s, freqs,
- wpa_s->num_multichan_concurrent);
+ num = get_shared_radio_freqs_data(wpa_s, freqs,
+ wpa_s->num_multichan_concurrent);
+
+ if (wpa_s->current_ssid &&
+ wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO &&
+ wpa_s->wpa_state == WPA_COMPLETED) {
+ wpa_printf(MSG_DEBUG, "P2P: %s called for an active GO",
+ __func__);
+
+ /*
+ * If the frequency selection is done for an active P2P GO that
+ * is not sharing a frequency, allow to select a new frequency
+ * even if there are no unused frequencies as we are about to
+ * move the P2P GO so its frequency can be re-used.
+ */
+ for (i = 0; i < num; i++) {
+ if (freqs[i].freq == wpa_s->current_ssid->frequency &&
+ freqs[i].flags == 0) {
+ ignore_no_freqs = 1;
+ break;
+ }
+ }
+ }
/* try using the forced freq */
if (freq) {
}
}
- if (wpas_p2p_num_unused_channels(wpa_s) <= 0) {
+ if (!ignore_no_freqs && !unused_channels) {
wpa_printf(MSG_DEBUG,
"P2P: Cannot force GO on freq (%d MHz) as all the channels are in use",
freq);
}
/* consider using one of the shared frequencies */
- if (num) {
+ if (num &&
+ (!wpa_s->conf->p2p_ignore_shared_freq || !unused_channels)) {
cand = wpas_p2p_pick_best_used_freq(wpa_s, freqs, num);
if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
wpa_printf(MSG_DEBUG,
"P2P: Use shared freq (%d MHz) for GO",
- freq);
+ cand);
params->freq = cand;
goto success;
}
freqs[i].freq)) {
wpa_printf(MSG_DEBUG,
"P2P: Use shared freq (%d MHz) for GO",
- freq);
+ freqs[i].freq);
params->freq = freqs[i].freq;
goto success;
}
}
}
- if (wpas_p2p_num_unused_channels(wpa_s) <= 0) {
+ if (!ignore_no_freqs && !unused_channels) {
wpa_printf(MSG_DEBUG,
"P2P: Cannot force GO on any of the channels we are already using");
goto fail;
struct wpa_supplicant *group_wpa_s;
if (!wpas_p2p_create_iface(wpa_s)) {
- wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use same interface for group "
- "operations");
+ if (wpa_s->p2p_mgmt) {
+ /*
+ * We may be called on the p2p_dev interface which
+ * cannot be used for group operations, so always use
+ * the primary interface.
+ */
+ wpa_s->parent->p2pdev = wpa_s;
+ wpa_s = wpa_s->parent;
+ }
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "P2P: Use primary interface for group operations");
wpa_s->p2p_first_connection_timeout = 0;
+ if (wpa_s != wpa_s->p2pdev)
+ wpas_p2p_clone_config(wpa_s, wpa_s->p2pdev);
return wpa_s;
}
* @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
* @persistent_group: Whether to create a persistent group
* @freq: Frequency for the group or 0 to indicate no hardcoding
+ * @vht_center_freq2: segment_1 center frequency for GO operating in VHT 80P80
* @ht40: Start GO with 40 MHz channel width
* @vht: Start GO with VHT support
+ * @vht_chwidth: channel bandwidth for GO operating with VHT support
* Returns: 0 on success, -1 on failure
*
* This function creates a new P2P group with the local end as the Group Owner,
* i.e., without using Group Owner Negotiation.
*/
int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
- int freq, int ht40, int vht)
+ int freq, int vht_center_freq2, int ht40, int vht,
+ int max_oper_chwidth)
{
struct p2p_go_neg_results params;
if (freq < 0)
return -1;
- if (wpas_p2p_init_go_params(wpa_s, ¶ms, freq, ht40, vht, NULL))
+ if (wpas_p2p_init_go_params(wpa_s, ¶ms, freq, vht_center_freq2,
+ ht40, vht, max_oper_chwidth, NULL))
return -1;
if (params.freq &&
!p2p_supported_freq_go(wpa_s->global->p2p, params.freq)) {
wpa_config_set_network_defaults(ssid);
ssid->temporary = 1;
ssid->proto = WPA_PROTO_RSN;
- ssid->pairwise_cipher = WPA_CIPHER_CCMP;
- ssid->group_cipher = WPA_CIPHER_CCMP;
+ ssid->pbss = params->pbss;
+ ssid->pairwise_cipher = params->pbss ? WPA_CIPHER_GCMP :
+ WPA_CIPHER_CCMP;
+ ssid->group_cipher = params->pbss ? WPA_CIPHER_GCMP : WPA_CIPHER_CCMP;
ssid->key_mgmt = WPA_KEY_MGMT_PSK;
ssid->ssid = os_malloc(params->ssid_len);
if (ssid->ssid == NULL) {
wpa_s->show_group_started = 1;
wpa_s->p2p_in_invitation = 1;
wpa_s->p2p_invite_go_freq = freq;
+ wpa_s->p2p_go_group_formation_completed = 0;
+ wpa_s->global->p2p_group_formation = wpa_s;
- eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->parent,
+ eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->p2pdev,
NULL);
eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT, 0,
wpas_p2p_group_formation_timeout,
- wpa_s->parent, NULL);
+ wpa_s->p2pdev, NULL);
wpa_supplicant_select_network(wpa_s, ssid);
return 0;
int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, int addr_allocated,
- int force_freq, int neg_freq, int ht40,
- int vht, const struct p2p_channels *channels,
+ int force_freq, int neg_freq,
+ int vht_center_freq2, int ht40,
+ int vht, int max_oper_chwidth,
+ const struct p2p_channels *channels,
int connection_timeout, int force_scan)
{
struct p2p_go_neg_results params;
"already running");
if (go == 0 &&
eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
- wpa_s->parent, NULL)) {
+ wpa_s->p2pdev, NULL)) {
/*
* This can happen if Invitation Response frame was lost
* and the peer (GO of a persistent group) tries to
"P2P: Reschedule group formation timeout since peer is still trying to invite us");
eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT, 0,
wpas_p2p_group_formation_timeout,
- wpa_s->parent, NULL);
+ wpa_s->p2pdev, NULL);
}
return 0;
}
return -1;
}
- if (wpas_p2p_init_go_params(wpa_s, ¶ms, freq, ht40, vht, channels))
+ if (wpas_p2p_init_go_params(wpa_s, ¶ms, freq, vht_center_freq2,
+ ht40, vht, max_oper_chwidth, channels))
return -1;
params.role_go = 1;
struct p2p_group *group;
struct p2p_group_config *cfg;
- if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
+ if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL ||
+ !ssid->p2p_group)
return NULL;
cfg = os_zalloc(sizeof(*cfg));
cfg->cb_ctx = wpa_s;
cfg->ie_update = wpas_p2p_ie_update;
cfg->idle_update = wpas_p2p_idle_update;
+ cfg->ip_addr_alloc = WPA_GET_BE32(wpa_s->p2pdev->conf->ip_addr_start)
+ != 0;
group = p2p_group_init(wpa_s->global->p2p, cfg);
if (group == NULL)
p2p_clear_provisioning_info(wpa_s->global->p2p, go_dev_addr);
}
- eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->parent,
+ eloop_cancel_timeout(wpas_p2p_group_formation_timeout, wpa_s->p2pdev,
NULL);
wpa_s->p2p_go_group_formation_completed = 1;
if (ssid && ssid->mode == WPAS_MODE_INFRA) {
P2P_MAX_INITIAL_CONN_WAIT);
eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT, 0,
wpas_p2p_group_formation_timeout,
- wpa_s->parent, NULL);
+ wpa_s->p2pdev, NULL);
+ /* Complete group formation on successful data connection. */
+ wpa_s->p2p_go_group_formation_completed = 0;
} else if (ssid) {
/*
* Use a separate timeout for initial data connection to
P2P_MAX_INITIAL_CONN_WAIT_GO);
eloop_register_timeout(P2P_MAX_INITIAL_CONN_WAIT_GO, 0,
wpas_p2p_group_formation_timeout,
- wpa_s->parent, NULL);
+ wpa_s->p2pdev, NULL);
/*
* Complete group formation on first successful data connection
*/
wpa_s->global->p2p_fail_on_wps_complete = 1;
eloop_deplete_timeout(0, 50000,
wpas_p2p_group_formation_timeout,
- wpa_s->parent, NULL);
+ wpa_s->p2pdev, NULL);
}
}
u16 config_methods;
wpa_s->global->pending_p2ps_group = 0;
+ wpa_s->global->pending_p2ps_group_freq = 0;
wpa_s->p2p_fallback_to_go_neg = 0;
wpa_s->pending_pd_use = NORMAL_PD;
if (p2ps_prov && use == WPAS_P2P_PD_FOR_ASP) {
p2ps_prov->conncap = p2ps_group_capability(
- wpa_s, P2PS_SETUP_NONE, p2ps_prov->role);
+ wpa_s, P2PS_SETUP_NONE, p2ps_prov->role,
+ &p2ps_prov->force_freq, &p2ps_prov->pref_freq);
+
wpa_printf(MSG_DEBUG,
"P2P: %s conncap: %d - ASP parsed: %x %x %d %s",
__func__, p2ps_prov->conncap,
if (!offchannel_pending_action_tx(wpa_s))
return;
- wpas_p2p_action_tx_clear(wpa_s);
+ if (wpa_s->p2p_send_action_work) {
+ wpas_p2p_free_send_action_work(wpa_s);
+ eloop_cancel_timeout(wpas_p2p_send_action_work_timeout,
+ wpa_s, NULL);
+ offchannel_send_action_done(wpa_s);
+ }
wpa_printf(MSG_DEBUG, "P2P: Drop pending Action TX due to new "
"operation request");
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1;
+ if (wpa_s->p2p_lo_started) {
+ wpa_printf(MSG_DEBUG,
+ "P2P: Cannot start P2P listen, it is offloaded");
+ return -1;
+ }
+
wpa_supplicant_cancel_sched_scan(wpa_s);
wpas_p2p_clear_pending_action_tx(wpa_s);
return 0;
switch (p2p_probe_req_rx(wpa_s->global->p2p, addr, dst, bssid,
- ie, ie_len, rx_freq)) {
+ ie, ie_len, rx_freq, wpa_s->p2p_lo_started)) {
case P2P_PREQ_NOT_P2P:
wpas_notify_preq(wpa_s, addr, dst, bssid, ie, ie_len,
ssi_signal);
void wpas_p2p_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ies)
{
+ unsigned int bands;
+
if (wpa_s->global->p2p_disabled)
return;
if (wpa_s->global->p2p == NULL)
return;
- p2p_scan_ie(wpa_s->global->p2p, ies, NULL);
+ bands = wpas_get_bands(wpa_s, NULL);
+ p2p_scan_ie(wpa_s->global->p2p, ies, NULL, bands);
}
/* Invite to reinvoke a persistent group */
int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
- int ht40, int vht, int pref_freq)
+ int vht_center_freq2, int ht40, int vht, int max_chwidth,
+ int pref_freq)
{
enum p2p_invite_role role;
u8 *bssid = NULL;
wpa_s->p2p_persistent_go_freq = freq;
wpa_s->p2p_go_ht40 = !!ht40;
+ wpa_s->p2p_go_vht = !!vht;
+ wpa_s->p2p_go_max_oper_chwidth = max_chwidth;
+ wpa_s->p2p_go_vht_center_freq2 = vht_center_freq2;
if (ssid->mode == WPAS_MODE_P2P_GO) {
role = P2P_INVITE_ROLE_GO;
if (peer_addr == NULL) {
return -1;
}
bssid = wpa_s->pending_interface_addr;
- } else
+ } else if (wpa_s->p2p_mgmt)
+ bssid = wpa_s->parent->own_addr;
+ else
bssid = wpa_s->own_addr;
} else {
role = P2P_INVITE_ROLE_CLIENT;
pref_freq_list, &size);
if (res)
return res;
- p2p_set_own_pref_freq_list(wpa_s->global->p2p, pref_freq_list, size);
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1;
+ p2p_set_own_pref_freq_list(wpa_s->global->p2p, pref_freq_list, size);
+
if (wpa_s->parent->conf->p2p_ignore_shared_freq &&
no_pref_freq_given && pref_freq > 0 &&
wpa_s->num_multichan_concurrent > 1 &&
wpa_s->p2p_persistent_go_freq = 0;
wpa_s->p2p_go_ht40 = 0;
wpa_s->p2p_go_vht = 0;
+ wpa_s->p2p_go_vht_center_freq2 = 0;
+ wpa_s->p2p_go_max_oper_chwidth = 0;
for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
if (os_strcmp(wpa_s->ifname, ifname) == 0)
wpa_s->global->p2p_invite_group = wpa_s;
persistent = ssid->p2p_persistent_group &&
- wpas_p2p_get_persistent(wpa_s->parent, peer_addr,
+ wpas_p2p_get_persistent(wpa_s->p2pdev, peer_addr,
ssid->ssid, ssid->ssid_len);
if (ssid->mode == WPAS_MODE_P2P_GO) {
freq = wpa_s->current_bss ? wpa_s->current_bss->freq :
(int) wpa_s->assoc_freq;
}
- wpa_s->parent->pending_invite_ssid_id = -1;
+ wpa_s->p2pdev->pending_invite_ssid_id = -1;
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1;
{
struct wpa_ssid *ssid = wpa_s->current_ssid;
u8 go_dev_addr[ETH_ALEN];
- int network_id = -1;
int persistent;
int freq;
u8 ip[3 * 4];
if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION) {
eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
- wpa_s->parent, NULL);
+ wpa_s->p2pdev, NULL);
}
if (!wpa_s->show_group_started || !ssid)
return;
wpa_s->show_group_started = 0;
+ if (!wpa_s->p2p_go_group_formation_completed &&
+ wpa_s->global->p2p_group_formation == wpa_s) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "P2P: Marking group formation completed on client on data connection");
+ wpa_s->p2p_go_group_formation_completed = 1;
+ wpa_s->global->p2p_group_formation = NULL;
+ wpa_s->p2p_in_provisioning = 0;
+ wpa_s->p2p_in_invitation = 0;
+ }
os_memset(go_dev_addr, 0, ETH_ALEN);
if (ssid->bssid_set)
ip_addr);
if (persistent)
- network_id = wpas_p2p_store_persistent_group(wpa_s->parent,
- ssid, go_dev_addr);
- if (network_id < 0)
- network_id = ssid->id;
- wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 1);
+ wpas_p2p_store_persistent_group(wpa_s->p2pdev,
+ ssid, go_dev_addr);
+
+ wpas_notify_p2p_group_started(wpa_s, ssid, persistent, 1);
}
iface->cross_connect_enabled = 0;
iface->cross_connect_in_use = 0;
- wpa_msg_global(iface->parent, MSG_INFO,
+ wpa_msg_global(iface->p2pdev, MSG_INFO,
P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
iface->ifname,
iface->cross_connect_uplink);
continue;
iface->cross_connect_in_use = 1;
- wpa_msg_global(iface->parent, MSG_INFO,
+ wpa_msg_global(iface->p2pdev, MSG_INFO,
P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s",
iface->ifname, iface->cross_connect_uplink);
}
if (!iface->cross_connect_in_use)
continue;
- wpa_msg_global(iface->parent, MSG_INFO,
+ wpa_msg_global(iface->p2pdev, MSG_INFO,
P2P_EVENT_CROSS_CONNECT_DISABLE "%s %s",
iface->ifname, iface->cross_connect_uplink);
iface->cross_connect_in_use = 0;
break;
wpa_s->cross_connect_in_use = 1;
- wpa_msg_global(wpa_s->parent, MSG_INFO,
+ wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
P2P_EVENT_CROSS_CONNECT_ENABLE "%s %s",
wpa_s->ifname, wpa_s->cross_connect_uplink);
break;
wpa_printf(MSG_DEBUG, "P2P: Terminate connection due to WPS PBC "
"session overlap");
- if (wpa_s != wpa_s->parent)
- wpa_msg_ctrl(wpa_s->parent, MSG_INFO, WPS_EVENT_OVERLAP);
+ if (wpa_s != wpa_s->p2pdev)
+ wpa_msg_ctrl(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_OVERLAP);
wpas_p2p_group_formation_failed(wpa_s, 0);
return 1;
}
wpa_s->ifname);
found = 1;
eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
- wpa_s->parent, NULL);
+ wpa_s->p2pdev, NULL);
if (wpa_s->p2p_in_provisioning) {
wpas_group_formation_completed(wpa_s, 0, 0);
break;
wpa_s->ifname);
found = 1;
wpas_p2p_group_formation_failed(wpa_s, 0);
+ break;
}
}
{
if (wpa_s->p2p_in_provisioning && ssid->p2p_group &&
eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
- wpa_s->parent, NULL) > 0) {
+ wpa_s->p2pdev, NULL) > 0) {
/**
* Remove the network by scheduling the group formation
* timeout to happen immediately. The teardown code
wpa_printf(MSG_DEBUG, "P2P: Canceled group formation due to "
"P2P group network getting removed");
eloop_register_timeout(0, 0, wpas_p2p_group_formation_timeout,
- wpa_s->parent, NULL);
+ wpa_s->p2pdev, NULL);
}
}
const u8 *addr)
{
if (eloop_cancel_timeout(wpas_p2p_group_formation_timeout,
- wpa_s->parent, NULL) > 0) {
+ wpa_s->p2pdev, NULL) > 0) {
/*
* This can happen if WPS provisioning step is not terminated
* cleanly (e.g., P2P Client does not send WSC_Done). Since the
wpas_p2p_connect(wpa_s, wpa_s->pending_join_dev_addr, wpa_s->p2p_pin,
wpa_s->p2p_wps_method, wpa_s->p2p_persistent_group, 0,
0, 0, wpa_s->p2p_go_intent, wpa_s->p2p_connect_freq,
+ wpa_s->p2p_go_vht_center_freq2,
wpa_s->p2p_persistent_id,
wpa_s->p2p_pd_before_go_neg,
wpa_s->p2p_go_ht40,
- wpa_s->p2p_go_vht);
+ wpa_s->p2p_go_vht,
+ wpa_s->p2p_go_max_oper_chwidth, NULL, 0);
return ret;
}
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: GO not found for p2p_connect-auto - "
"fallback to GO Negotiation");
- wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_FALLBACK_TO_GO_NEG
+ wpa_msg_global(wpa_s->p2pdev, MSG_INFO, P2P_EVENT_FALLBACK_TO_GO_NEG
"reason=GO-not-found");
res = wpas_p2p_fallback_to_go_neg(wpa_s, 1);
return;
}
- persistent = wpas_p2p_get_persistent(wpa_s->parent, NULL, ssid->ssid,
+ persistent = wpas_p2p_get_persistent(wpa_s->p2pdev, NULL, ssid->ssid,
ssid->ssid_len);
if (!persistent) {
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Could not find persistent group information to store the new PSK");
os_free(last);
}
- wpas_p2p_remove_psk_entry(wpa_s->parent, persistent,
+ wpas_p2p_remove_psk_entry(wpa_s->p2pdev, persistent,
p2p_dev_addr ? p2p_dev_addr : mac_addr,
p2p_dev_addr == NULL);
if (p2p_dev_addr) {
}
dl_list_add(&persistent->psk_list, &p->list);
- if (wpa_s->parent->conf->update_config &&
- wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf))
+ if (wpa_s->p2pdev->conf->update_config &&
+ wpa_config_write(wpa_s->p2pdev->confname, wpa_s->p2pdev->conf))
wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration");
}
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Two 4-way handshake failures for a P2P group - go_dev_addr="
MACSTR, MAC2STR(go_dev_addr));
- persistent = wpas_p2p_get_persistent(wpa_s->parent, go_dev_addr,
+ persistent = wpas_p2p_get_persistent(wpa_s->p2pdev, go_dev_addr,
ssid->ssid,
ssid->ssid_len);
if (persistent == NULL || persistent->mode != WPAS_MODE_INFRA) {
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: No matching persistent group stored");
goto disconnect;
}
- wpa_msg_global(wpa_s->parent, MSG_INFO,
+ wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
P2P_EVENT_PERSISTENT_PSK_FAIL "%d",
persistent->id);
disconnect:
return wpas_p2p_connect(wpa_s, params->peer->p2p_device_addr, NULL,
WPS_NFC, 0, 0, 1, 0, wpa_s->conf->p2p_go_intent,
- params->go_freq, -1, 0, 1, 1);
+ params->go_freq, wpa_s->p2p_go_vht_center_freq2,
+ -1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
+ params->go_ssid_len ? params->go_ssid : NULL,
+ params->go_ssid_len);
}
return -1;
}
- if (wpa_s->parent->p2p_oob_dev_pw_id !=
+ if (wpa_s->p2pdev->p2p_oob_dev_pw_id !=
DEV_PW_NFC_CONNECTION_HANDOVER &&
- !wpa_s->parent->p2p_oob_dev_pw) {
+ !wpa_s->p2pdev->p2p_oob_dev_pw) {
wpa_printf(MSG_DEBUG, "P2P: No NFC Dev Pw known");
return -1;
}
res = wpas_ap_wps_add_nfc_pw(
- wpa_s, wpa_s->parent->p2p_oob_dev_pw_id,
- wpa_s->parent->p2p_oob_dev_pw,
- wpa_s->parent->p2p_peer_oob_pk_hash_known ?
- wpa_s->parent->p2p_peer_oob_pubkey_hash : NULL);
+ wpa_s, wpa_s->p2pdev->p2p_oob_dev_pw_id,
+ wpa_s->p2pdev->p2p_oob_dev_pw,
+ wpa_s->p2pdev->p2p_peer_oob_pk_hash_known ?
+ wpa_s->p2pdev->p2p_peer_oob_pubkey_hash : NULL);
if (res)
return res;
wpa_s->global->p2p_invite_group = wpa_s;
persistent = ssid->p2p_persistent_group &&
- wpas_p2p_get_persistent(wpa_s->parent,
+ wpas_p2p_get_persistent(wpa_s->p2pdev,
params->peer->p2p_device_addr,
ssid->ssid, ssid->ssid_len);
- wpa_s->parent->pending_invite_ssid_id = -1;
+ wpa_s->p2pdev->pending_invite_ssid_id = -1;
return p2p_invite(wpa_s->global->p2p, params->peer->p2p_device_addr,
P2P_INVITE_ROLE_ACTIVE_GO, wpa_s->own_addr,
ssid->ssid, ssid->ssid_len, ssid->frequency,
wpa_s->global->p2p_dev_addr, persistent, 0,
- wpa_s->parent->p2p_oob_dev_pw_id);
+ wpa_s->p2pdev->p2p_oob_dev_pw_id);
}
"connection handover");
return wpas_p2p_connect(wpa_s, params->peer->p2p_device_addr, NULL,
WPS_NFC, 0, 0, 0, 0, wpa_s->conf->p2p_go_intent,
- forced_freq, -1, 0, 1, 1);
+ forced_freq, wpa_s->p2p_go_vht_center_freq2,
+ -1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
+ NULL, 0);
}
"connection handover");
res = wpas_p2p_connect(wpa_s, params->peer->p2p_device_addr, NULL,
WPS_NFC, 0, 0, 0, 1, wpa_s->conf->p2p_go_intent,
- forced_freq, -1, 0, 1, 1);
+ forced_freq, wpa_s->p2p_go_vht_center_freq2,
+ -1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth,
+ NULL, 0);
if (res)
return res;
}
if_addr = wpa_s->pending_interface_addr;
- } else
+ } else if (wpa_s->p2p_mgmt)
+ if_addr = wpa_s->parent->own_addr;
+ else
if_addr = wpa_s->own_addr;
wpa_s->p2p_nfc_tag_enabled = enabled;
static int wpas_p2p_move_go_csa(struct wpa_supplicant *wpa_s)
{
+ struct hostapd_config *conf;
+ struct p2p_go_neg_results params;
+ struct csa_settings csa_settings;
+ struct wpa_ssid *current_ssid = wpa_s->current_ssid;
+ int old_freq = current_ssid->frequency;
+ int ret;
+
if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP_CSA)) {
wpa_dbg(wpa_s, MSG_DEBUG, "CSA is not enabled");
return -1;
}
- /* TODO: Add CSA support */
- wpa_dbg(wpa_s, MSG_DEBUG, "Moving GO with CSA is not implemented");
- return -1;
+ /*
+ * TODO: This function may not always work correctly. For example,
+ * when we have a running GO and a BSS on a DFS channel.
+ */
+ if (wpas_p2p_init_go_params(wpa_s, ¶ms, 0, 0, 0, 0, 0, NULL)) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "P2P CSA: Failed to select new frequency for GO");
+ return -1;
+ }
+
+ if (current_ssid->frequency == params.freq) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "P2P CSA: Selected same frequency - not moving GO");
+ return 0;
+ }
+
+ conf = hostapd_config_defaults();
+ if (!conf) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "P2P CSA: Failed to allocate default config");
+ return -1;
+ }
+
+ current_ssid->frequency = params.freq;
+ if (wpa_supplicant_conf_ap_ht(wpa_s, current_ssid, conf)) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "P2P CSA: Failed to create new GO config");
+ ret = -1;
+ goto out;
+ }
+
+ if (conf->hw_mode != wpa_s->ap_iface->current_mode->mode) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "P2P CSA: CSA to a different band is not supported");
+ ret = -1;
+ goto out;
+ }
+
+ os_memset(&csa_settings, 0, sizeof(csa_settings));
+ csa_settings.cs_count = P2P_GO_CSA_COUNT;
+ csa_settings.block_tx = P2P_GO_CSA_BLOCK_TX;
+ csa_settings.freq_params.freq = params.freq;
+ csa_settings.freq_params.sec_channel_offset = conf->secondary_channel;
+ csa_settings.freq_params.ht_enabled = conf->ieee80211n;
+ csa_settings.freq_params.bandwidth = conf->secondary_channel ? 40 : 20;
+
+ if (conf->ieee80211ac) {
+ int freq1 = 0, freq2 = 0;
+ u8 chan, opclass;
+
+ if (ieee80211_freq_to_channel_ext(params.freq,
+ conf->secondary_channel,
+ conf->vht_oper_chwidth,
+ &opclass, &chan) ==
+ NUM_HOSTAPD_MODES) {
+ wpa_printf(MSG_ERROR, "P2P CSA: Bad freq");
+ ret = -1;
+ goto out;
+ }
+
+ if (conf->vht_oper_centr_freq_seg0_idx)
+ freq1 = ieee80211_chan_to_freq(
+ NULL, opclass,
+ conf->vht_oper_centr_freq_seg0_idx);
+
+ if (conf->vht_oper_centr_freq_seg1_idx)
+ freq2 = ieee80211_chan_to_freq(
+ NULL, opclass,
+ conf->vht_oper_centr_freq_seg1_idx);
+
+ if (freq1 < 0 || freq2 < 0) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "P2P CSA: Selected invalid VHT center freqs");
+ ret = -1;
+ goto out;
+ }
+
+ csa_settings.freq_params.vht_enabled = conf->ieee80211ac;
+ csa_settings.freq_params.center_freq1 = freq1;
+ csa_settings.freq_params.center_freq2 = freq2;
+
+ switch (conf->vht_oper_chwidth) {
+ case VHT_CHANWIDTH_80MHZ:
+ case VHT_CHANWIDTH_80P80MHZ:
+ csa_settings.freq_params.bandwidth = 80;
+ break;
+ case VHT_CHANWIDTH_160MHZ:
+ csa_settings.freq_params.bandwidth = 160;
+ break;
+ }
+ }
+
+ ret = ap_switch_channel(wpa_s, &csa_settings);
+out:
+ current_ssid->frequency = old_freq;
+ hostapd_config_free(conf);
+ return ret;
}
wpa_supplicant_ap_deinit(wpa_s);
/* Reselect the GO frequency */
- if (wpas_p2p_init_go_params(wpa_s, ¶ms, 0, 0, 0, NULL)) {
+ if (wpas_p2p_init_go_params(wpa_s, ¶ms, 0, 0, 0, 0, 0, NULL)) {
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Failed to reselect freq");
wpas_p2p_group_delete(wpa_s,
P2P_GROUP_REMOVAL_GO_LEAVE_CHANNEL);
wpas_p2p_go_update_common_freqs(wpa_s);
+ /* Do not move GO in the middle of a CSA */
+ if (hostapd_csa_in_progress(wpa_s->ap_iface)) {
+ wpa_printf(MSG_DEBUG,
+ "P2P: CSA is in progress - not moving GO");
+ return;
+ }
+
/*
* First, try a channel switch flow. If it is not supported or fails,
* take down the GO and bring it up again.
P2P_GO_FREQ_MOVE_SCM_PEER_SUPPORTS &&
wpas_p2p_go_is_peer_freq(wpa_s, freqs[i].freq)) {
policy_move = 1;
+ } else if ((wpa_s->conf->p2p_go_freq_change_policy ==
+ P2P_GO_FREQ_MOVE_SCM_ECSA) &&
+ wpas_p2p_go_is_peer_freq(wpa_s, freqs[i].freq)) {
+ if (!p2p_get_group_num_members(wpa_s->p2p_group)) {
+ policy_move = 1;
+ } else if ((wpa_s->drv_flags &
+ WPA_DRIVER_FLAGS_AP_CSA) &&
+ wpas_p2p_go_clients_support_ecsa(wpa_s)) {
+ u8 chan;
+
+ /*
+ * We do not support CSA between bands, so move
+ * GO only within the same band.
+ */
+ if (wpa_s->ap_iface->current_mode->mode ==
+ ieee80211_freq_to_chan(freqs[i].freq,
+ &chan))
+ policy_move = 1;
+ }
}
}
return;
}
+ /*
+ * Do not consider moving GO if it is in the middle of a CSA. When the
+ * CSA is finished this flow should be retriggered.
+ */
+ if (hostapd_csa_in_progress(wpa_s->ap_iface)) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "P2P: Not initiating a GO frequency change - CSA is in progress");
+ return;
+ }
+
if (invalid_freq && !wpas_p2p_disallowed_freq(wpa_s->global, freq))
timeout = P2P_GO_FREQ_CHANGE_TIME;
else
wpa_s->ap_iface->bss[0]->p2p_group = NULL;
wpas_p2p_group_deinit(wpa_s);
}
+
+
+int wpas_p2p_lo_start(struct wpa_supplicant *wpa_s, unsigned int freq,
+ unsigned int period, unsigned int interval,
+ unsigned int count)
+{
+ struct p2p_data *p2p = wpa_s->global->p2p;
+ u8 *device_types;
+ size_t dev_types_len;
+ struct wpabuf *buf;
+ int ret;
+
+ if (wpa_s->p2p_lo_started) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "P2P Listen offload is already started");
+ return 0;
+ }
+
+ if (wpa_s->global->p2p == NULL ||
+ !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD)) {
+ wpa_printf(MSG_DEBUG, "P2P: Listen offload not supported");
+ return -1;
+ }
+
+ if (!p2p_supported_freq(wpa_s->global->p2p, freq)) {
+ wpa_printf(MSG_ERROR, "P2P: Input channel not supported: %u",
+ freq);
+ return -1;
+ }
+
+ /* Get device type */
+ dev_types_len = (wpa_s->conf->num_sec_device_types + 1) *
+ WPS_DEV_TYPE_LEN;
+ device_types = os_malloc(dev_types_len);
+ if (!device_types)
+ return -1;
+ os_memcpy(device_types, wpa_s->conf->device_type, WPS_DEV_TYPE_LEN);
+ os_memcpy(&device_types[WPS_DEV_TYPE_LEN], wpa_s->conf->sec_device_type,
+ wpa_s->conf->num_sec_device_types * WPS_DEV_TYPE_LEN);
+
+ /* Get Probe Response IE(s) */
+ buf = p2p_build_probe_resp_template(p2p, freq);
+ if (!buf) {
+ os_free(device_types);
+ return -1;
+ }
+
+ ret = wpa_drv_p2p_lo_start(wpa_s, freq, period, interval, count,
+ device_types, dev_types_len,
+ wpabuf_mhead_u8(buf), wpabuf_len(buf));
+ if (ret < 0)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "P2P: Failed to start P2P listen offload");
+
+ os_free(device_types);
+ wpabuf_free(buf);
+
+ if (ret == 0) {
+ wpa_s->p2p_lo_started = 1;
+
+ /* Stop current P2P listen if any */
+ wpas_stop_listen(wpa_s);
+ }
+
+ return ret;
+}
+
+
+int wpas_p2p_lo_stop(struct wpa_supplicant *wpa_s)
+{
+ int ret;
+
+ if (!wpa_s->p2p_lo_started)
+ return 0;
+
+ ret = wpa_drv_p2p_lo_stop(wpa_s);
+ if (ret < 0)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "P2P: Failed to stop P2P listen offload");
+
+ wpa_s->p2p_lo_started = 0;
+ return ret;
+}
const u8 *peer_dev_addr);
int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
const char *pin, enum p2p_wps_method wps_method,
- int persistent_group, int auto_join, int join,
- int auth, int go_intent, int freq, int persistent_id,
- int pd, int ht40, int vht);
+ int persistent_group, int auto_join, int join, int auth,
+ int go_intent, int freq, unsigned int vht_center_freq2,
+ int persistent_id, int pd, int ht40, int vht,
+ unsigned int vht_chwidth, const u8 *group_ssid,
+ size_t group_ssid_len);
int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s,
int freq, struct wpa_ssid *ssid);
int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
- int freq, int ht40, int vht);
+ int freq, int vht_center_freq2, int ht40, int vht,
+ int max_oper_chwidth);
int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, int addr_allocated,
- int force_freq, int neg_freq, int ht40,
- int vht, const struct p2p_channels *channels,
+ int force_freq, int neg_freq,
+ int vht_center_freq2, int ht40,
+ int vht, int max_oper_chwidth,
+ const struct p2p_channels *channels,
int connection_timeout, int force_scan);
struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr);
int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
- int ht40, int vht, int pref_freq);
+ int vht_center_freq2, int ht40, int vht,
+ int max_oper_chwidth, int pref_freq);
int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
const u8 *peer_addr, const u8 *go_dev_addr);
int wpas_p2p_presence_req(struct wpa_supplicant *wpa_s, u32 duration1,
struct hostapd_hw_modes *mode, u8 channel);
int wpas_p2p_get_vht80_center(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode, u8 channel);
+int wpas_p2p_get_vht160_center(struct wpa_supplicant *wpa_s,
+ struct hostapd_hw_modes *mode, u8 channel);
unsigned int wpas_p2p_search_delay(struct wpa_supplicant *wpa_s);
void wpas_p2p_new_psk_cb(struct wpa_supplicant *wpa_s, const u8 *mac_addr,
const u8 *p2p_dev_addr,
void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s,
struct wps_event_fail *fail);
int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname);
+int wpas_p2p_lo_start(struct wpa_supplicant *wpa_s, unsigned int freq,
+ unsigned int period, unsigned int interval,
+ unsigned int count);
+int wpas_p2p_lo_stop(struct wpa_supplicant *wpa_s);
#else /* CONFIG_P2P */
u8 *spos_tmp;
/* Offset */
- if (*spos + 2 > end) {
+ if (end - *spos < 2) {
wpa_printf(MSG_DEBUG, "P2P: No room for full "
"DNS offset field");
return -1;
return 0;
(*spos)++;
- if (*spos + len > end) {
+ if (len > end - *spos) {
wpa_printf(MSG_DEBUG, "P2P: Invalid domain name "
"sequence - no room for label with length "
"%u", len);
return -1;
}
- if (*upos + len + 2 > uend)
+ if (len + 2 > uend - *upos)
return -2;
os_memcpy(*upos, *spos, len);
if (resp == NULL)
return;
- while (pos + 1 < end) {
+ while (end - pos > 1) {
wpa_printf(MSG_DEBUG, "P2P: Service Request TLV");
slen = WPA_GET_LE16(pos);
pos += 2;
- if (pos + slen > end || slen < 2) {
+ if (slen > end - pos || slen < 2) {
wpa_printf(MSG_DEBUG, "P2P: Unexpected Query Data "
"length");
wpabuf_free(resp);
u8 svc_len;
/* Sanity check fixed length+svc_str */
- if (pos + 6 >= tlv_end)
+ if (6 >= tlv_end - pos)
break;
svc_len = pos[6];
- if (pos + svc_len + 10 > tlv_end)
+ if (svc_len + 10 > tlv_end - pos)
break;
/* Advertisement ID */
}
}
- while (pos < end) {
+ while (end - pos >= 2) {
u8 srv_proto, srv_trans_id, status;
wpa_printf(MSG_DEBUG, "P2P: Service Response TLV");
slen = WPA_GET_LE16(pos);
pos += 2;
- if (pos + slen > end || slen < 3) {
+ if (slen > end - pos || slen < 3) {
wpa_printf(MSG_DEBUG, "P2P: Unexpected Response Data "
"length");
return;
if (wpa_s->current_ssid == NULL) {
wpa_s->current_ssid = ssid;
- if (wpa_s->current_ssid != NULL)
- wpas_notify_network_changed(wpa_s);
+ wpas_notify_network_changed(wpa_s);
}
wpa_supplicant_initiate_eapol(wpa_s);
wpa_dbg(wpa_s, MSG_DEBUG, "Already associated with a configured "
wps = 1;
*req_type = wpas_wps_get_req_type(ssid);
- if (!ssid->eap.phase1)
- continue;
-
- if (os_strstr(ssid->eap.phase1, "pbc=1"))
+ if (ssid->eap.phase1 && os_strstr(ssid->eap.phase1, "pbc=1"))
return 2;
}
if (wpas_update_random_addr_disassoc(wpa_s) < 0) {
wpa_msg(wpa_s, MSG_INFO,
"Failed to assign random MAC address for a scan");
+ wpa_scan_free_params(params);
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_FAILED "ret=-1");
radio_work_done(work);
return;
}
}
ctx = wpa_scan_clone_params(params);
- if (ctx == NULL)
- return -1;
-
- if (radio_add_work(wpa_s, 0, "scan", 0, wpas_trigger_scan_cb, ctx) < 0)
+ if (!ctx ||
+ radio_add_work(wpa_s, 0, "scan", 0, wpas_trigger_scan_cb, ctx) < 0)
{
wpa_scan_free_params(ctx);
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_FAILED "ret=-1");
return -1;
}
}
-int wpa_supplicant_start_sched_scan(struct wpa_supplicant *wpa_s,
- struct wpa_driver_scan_params *params,
- int interval)
+static int
+wpa_supplicant_start_sched_scan(struct wpa_supplicant *wpa_s,
+ struct wpa_driver_scan_params *params)
{
int ret;
wpa_supplicant_notify_scanning(wpa_s, 1);
- ret = wpa_drv_sched_scan(wpa_s, params, interval * 1000);
+ ret = wpa_drv_sched_scan(wpa_s, params);
if (ret)
wpa_supplicant_notify_scanning(wpa_s, 0);
else
}
-int wpa_supplicant_stop_sched_scan(struct wpa_supplicant *wpa_s)
+static int wpa_supplicant_stop_sched_scan(struct wpa_supplicant *wpa_s)
{
int ret;
#endif /* CONFIG_INTERWORKING */
+void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s)
+{
+ struct wpabuf *default_ies = NULL;
+ u8 ext_capab[18];
+ int ext_capab_len;
+ enum wpa_driver_if_type type = WPA_IF_STATION;
+
+#ifdef CONFIG_P2P
+ if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT)
+ type = WPA_IF_P2P_CLIENT;
+#endif /* CONFIG_P2P */
+
+ wpa_drv_get_ext_capa(wpa_s, type);
+
+ ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
+ sizeof(ext_capab));
+ if (ext_capab_len > 0 &&
+ wpabuf_resize(&default_ies, ext_capab_len) == 0)
+ wpabuf_put_data(default_ies, ext_capab, ext_capab_len);
+
+#ifdef CONFIG_MBO
+ /* Send cellular capabilities for potential MBO STAs */
+ if (wpabuf_resize(&default_ies, 9) == 0)
+ wpas_mbo_scan_ie(wpa_s, default_ies);
+#endif /* CONFIG_MBO */
+
+ if (default_ies)
+ wpa_drv_set_default_scan_ies(wpa_s, wpabuf_head(default_ies),
+ wpabuf_len(default_ies));
+ wpabuf_free(default_ies);
+}
+
+
static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s)
{
struct wpabuf *extra_ie = NULL;
enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO;
#endif /* CONFIG_WPS */
+#ifdef CONFIG_P2P
+ if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT)
+ wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
+ else
+#endif /* CONFIG_P2P */
+ wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
+
ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
sizeof(ext_capab));
if (ext_capab_len > 0 &&
wpabuf_put_buf(extra_ie, wpa_s->fst_ies);
#endif /* CONFIG_FST */
+#ifdef CONFIG_MBO
+ /* Send cellular capabilities for potential MBO STAs */
+ if (wpabuf_resize(&extra_ie, 9) == 0)
+ wpas_mbo_scan_ie(wpa_s, extra_ie);
+#endif /* CONFIG_MBO */
+
+ if (wpa_s->vendor_elem[VENDOR_ELEM_PROBE_REQ]) {
+ struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_PROBE_REQ];
+
+ if (wpabuf_resize(&extra_ie, wpabuf_len(buf)) == 0)
+ wpabuf_put_buf(extra_ie, buf);
+ }
+
return extra_ie;
}
#endif /* CONFIG_P2P */
-static struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
- u16 num_modes,
- enum hostapd_hw_mode mode)
-{
- u16 i;
-
- for (i = 0; i < num_modes; i++) {
- if (modes[i].mode == mode)
- return &modes[i];
- }
-
- return NULL;
-}
-
-
static void wpa_setband_scan_freqs_list(struct wpa_supplicant *wpa_s,
enum hostapd_hw_mode band,
struct wpa_driver_scan_params *params)
unsigned int i;
struct wpa_ssid *ssid;
+ /*
+ * For devices with max_ssids greater than 1, leave the last slot empty
+ * for adding the wildcard scan entry.
+ */
+ max_ssids = max_ssids > 1 ? max_ssids - 1 : max_ssids;
+
for (i = 0; i < wpa_s->scan_id_count; i++) {
unsigned int j;
* slot for the zero-terminator.
*/
params.freqs = os_malloc(sizeof(int) * 2);
- if (params.freqs == NULL) {
- wpa_dbg(wpa_s, MSG_ERROR, "Memory allocation failed");
- return;
+ if (params.freqs) {
+ params.freqs[0] = wpa_s->assoc_freq;
+ params.freqs[1] = 0;
}
- params.freqs[0] = wpa_s->assoc_freq;
- params.freqs[1] = 0;
/*
* Reset the reattach flag so that we fall back to full scan if
}
}
+ if (!is_zero_ether_addr(wpa_s->next_scan_bssid)) {
+ struct wpa_bss *bss;
+
+ params.bssid = wpa_s->next_scan_bssid;
+ bss = wpa_bss_get_bssid_latest(wpa_s, params.bssid);
+ if (bss && bss->ssid_len && params.num_ssids == 1 &&
+ params.ssids[0].ssid_len == 0) {
+ params.ssids[0].ssid = bss->ssid;
+ params.ssids[0].ssid_len = bss->ssid_len;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Scan a previously specified BSSID " MACSTR
+ " and SSID %s",
+ MAC2STR(params.bssid),
+ wpa_ssid_txt(bss->ssid, bss->ssid_len));
+ } else {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Scan a previously specified BSSID " MACSTR,
+ MAC2STR(params.bssid));
+ }
+ }
+
scan_params = ¶ms;
scan:
#ifdef CONFIG_INTERWORKING
wpa_s->interworking_fast_assoc_tried = 0;
#endif /* CONFIG_INTERWORKING */
+ if (params.bssid)
+ os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN);
}
}
unsigned int max_sched_scan_ssids;
int wildcard = 0;
int need_ssids;
+ struct sched_scan_plan scan_plan;
if (!wpa_s->sched_scan_supported)
return -1;
if (max_sched_scan_ssids < 1 || wpa_s->conf->disable_scan_offload)
return -1;
+ wpa_s->sched_scan_stop_req = 0;
+
if (wpa_s->sched_scanning) {
wpa_dbg(wpa_s, MSG_DEBUG, "Already sched scanning");
return 0;
if (!ssid || !wpa_s->prev_sched_ssid) {
wpa_dbg(wpa_s, MSG_DEBUG, "Beginning of SSID list");
- if (wpa_s->conf->sched_scan_interval)
- wpa_s->sched_scan_interval =
- wpa_s->conf->sched_scan_interval;
- if (wpa_s->sched_scan_interval == 0)
- wpa_s->sched_scan_interval = 10;
wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2;
wpa_s->first_sched_scan = 1;
ssid = wpa_s->conf->ssid;
scan_params = ¶ms;
scan:
- if (ssid || !wpa_s->first_sched_scan) {
+ wpa_s->sched_scan_timed_out = 0;
+
+ /*
+ * We cannot support multiple scan plans if the scan request includes
+ * too many SSID's, so in this case use only the last scan plan and make
+ * it run infinitely. It will be stopped by the timeout.
+ */
+ if (wpa_s->sched_scan_plans_num == 1 ||
+ (wpa_s->sched_scan_plans_num && !ssid && wpa_s->first_sched_scan)) {
+ params.sched_scan_plans = wpa_s->sched_scan_plans;
+ params.sched_scan_plans_num = wpa_s->sched_scan_plans_num;
+ } else if (wpa_s->sched_scan_plans_num > 1) {
wpa_dbg(wpa_s, MSG_DEBUG,
- "Starting sched scan: interval %d timeout %d",
- wpa_s->sched_scan_interval, wpa_s->sched_scan_timeout);
+ "Too many SSIDs. Default to using single scheduled_scan plan");
+ params.sched_scan_plans =
+ &wpa_s->sched_scan_plans[wpa_s->sched_scan_plans_num -
+ 1];
+ params.sched_scan_plans_num = 1;
} else {
+ if (wpa_s->conf->sched_scan_interval)
+ scan_plan.interval = wpa_s->conf->sched_scan_interval;
+ else
+ scan_plan.interval = 10;
+
+ if (scan_plan.interval > wpa_s->max_sched_scan_plan_interval) {
+ wpa_printf(MSG_WARNING,
+ "Scan interval too long(%u), use the maximum allowed(%u)",
+ scan_plan.interval,
+ wpa_s->max_sched_scan_plan_interval);
+ scan_plan.interval =
+ wpa_s->max_sched_scan_plan_interval;
+ }
+
+ scan_plan.iterations = 0;
+ params.sched_scan_plans = &scan_plan;
+ params.sched_scan_plans_num = 1;
+ }
+
+ if (ssid || !wpa_s->first_sched_scan) {
wpa_dbg(wpa_s, MSG_DEBUG,
- "Starting sched scan: interval %d (no timeout)",
- wpa_s->sched_scan_interval);
+ "Starting sched scan: interval %u timeout %d",
+ params.sched_scan_plans[0].interval,
+ wpa_s->sched_scan_timeout);
+ } else {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Starting sched scan (no timeout)");
}
wpa_setband_scan_freqs(wpa_s, scan_params);
}
}
- ret = wpa_supplicant_start_sched_scan(wpa_s, scan_params,
- wpa_s->sched_scan_interval);
+ ret = wpa_supplicant_start_sched_scan(wpa_s, scan_params);
wpabuf_free(extra_ie);
os_free(params.filter_ssids);
if (ret) {
wpa_s, NULL);
wpa_s->first_sched_scan = 0;
wpa_s->sched_scan_timeout /= 2;
- wpa_s->sched_scan_interval *= 2;
- if (wpa_s->sched_scan_timeout < wpa_s->sched_scan_interval) {
- wpa_s->sched_scan_interval = 10;
+ params.sched_scan_plans[0].interval *= 2;
+ if ((unsigned int) wpa_s->sched_scan_timeout <
+ params.sched_scan_plans[0].interval ||
+ params.sched_scan_plans[0].interval >
+ wpa_s->max_sched_scan_plan_interval) {
+ params.sched_scan_plans[0].interval = 10;
wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2;
}
}
if (!wpa_s->sched_scanning)
return;
+ if (wpa_s->sched_scanning)
+ wpa_s->sched_scan_stop_req = 1;
+
wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling sched scan");
eloop_cancel_timeout(wpa_supplicant_sched_scan_timeout, wpa_s, NULL);
wpa_supplicant_stop_sched_scan(wpa_s);
*/
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);
}
pos = (const u8 *) (res + 1);
end = pos + res->ie_len;
- 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 &&
vendor_type == WPA_GET_BE32(&pos[2]))
pos += res->ie_len;
end = pos + res->beacon_ie_len;
- 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 &&
vendor_type == WPA_GET_BE32(&pos[2]))
pos = (const u8 *) (res + 1);
end = pos + res->ie_len;
- 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 &&
vendor_type == WPA_GET_BE32(&pos[2]))
}
-static void filter_scan_res(struct wpa_supplicant *wpa_s,
- struct wpa_scan_results *res)
+void filter_scan_res(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_results *res)
{
size_t i, j;
/*
* Noise floor values to use when we have signal strength
- * measurements, but no noise floor measurments. These values were
+ * measurements, but no noise floor measurements. These values were
* measured in an office environment with many APs.
*/
#define DEFAULT_NOISE_FLOOR_2GHZ (-89)
#define DEFAULT_NOISE_FLOOR_5GHZ (-92)
-static void scan_snr(struct wpa_scan_res *res)
+void scan_snr(struct wpa_scan_res *res)
{
if (res->flags & WPA_SCAN_NOISE_INVALID) {
res->noise = IS_5GHZ(res->freq) ?
}
-static void scan_est_throughput(struct wpa_supplicant *wpa_s,
- struct wpa_scan_res *res)
+void scan_est_throughput(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_res *res)
{
enum local_hw_capab capab = wpa_s->hw_capab;
int rate; /* max legacy rate in 500 kb/s units */
wpa_s->scan_work = NULL;
radio_work_done(work);
}
+
+ if (wpa_s->wpa_state == WPA_SCANNING)
+ wpa_supplicant_set_state(wpa_s, wpa_s->scan_prev_wpa_state);
}
params->only_new_results = src->only_new_results;
params->low_priority = src->low_priority;
+ if (src->sched_scan_plans_num > 0) {
+ params->sched_scan_plans =
+ os_malloc(sizeof(*src->sched_scan_plans) *
+ src->sched_scan_plans_num);
+ if (!params->sched_scan_plans)
+ goto failed;
+
+ os_memcpy(params->sched_scan_plans, src->sched_scan_plans,
+ sizeof(*src->sched_scan_plans) *
+ src->sched_scan_plans_num);
+ params->sched_scan_plans_num = src->sched_scan_plans_num;
+ }
+
if (src->mac_addr_rand) {
params->mac_addr_rand = src->mac_addr_rand;
params->mac_addr_mask = mac_addr + ETH_ALEN;
}
}
+
+ if (src->bssid) {
+ u8 *bssid;
+
+ bssid = os_malloc(ETH_ALEN);
+ if (!bssid)
+ goto failed;
+ os_memcpy(bssid, src->bssid, ETH_ALEN);
+ params->bssid = bssid;
+ }
+
return params;
failed:
os_free((u8 *) params->extra_ies);
os_free(params->freqs);
os_free(params->filter_ssids);
+ os_free(params->sched_scan_plans);
/*
* Note: params->mac_addr_mask points to same memory allocation and
*/
os_free((u8 *) params->mac_addr);
+ os_free((u8 *) params->bssid);
+
os_free(params);
}
int wpas_start_pno(struct wpa_supplicant *wpa_s)
{
- int ret, interval, prio;
+ int ret, prio;
size_t i, num_ssid, num_match_ssid;
struct wpa_ssid *ssid;
struct wpa_driver_scan_params params;
+ struct sched_scan_plan scan_plan;
+ unsigned int max_sched_scan_ssids;
if (!wpa_s->sched_scan_supported)
return -1;
+ if (wpa_s->max_sched_scan_ssids > WPAS_MAX_SCAN_SSIDS)
+ max_sched_scan_ssids = WPAS_MAX_SCAN_SSIDS;
+ else
+ max_sched_scan_ssids = wpa_s->max_sched_scan_ssids;
+ if (max_sched_scan_ssids < 1)
+ return -1;
+
if (wpa_s->pno || wpa_s->pno_sched_pending)
return 0;
}
}
+ if (wpa_s->sched_scan_stop_req) {
+ wpa_printf(MSG_DEBUG,
+ "Schedule PNO after previous sched scan has stopped");
+ wpa_s->pno_sched_pending = 1;
+ return 0;
+ }
+
os_memset(¶ms, 0, sizeof(params));
num_ssid = num_match_ssid = 0;
num_ssid++;
}
- if (num_ssid > WPAS_MAX_SCAN_SSIDS) {
+ if (num_ssid > max_sched_scan_ssids) {
wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from "
- "%u", WPAS_MAX_SCAN_SSIDS, (unsigned int) num_ssid);
- num_ssid = WPAS_MAX_SCAN_SSIDS;
+ "%u", max_sched_scan_ssids, (unsigned int) num_ssid);
+ num_ssid = max_sched_scan_ssids;
}
if (num_match_ssid > wpa_s->max_match_sets) {
if (wpa_s->conf->filter_rssi)
params.filter_rssi = wpa_s->conf->filter_rssi;
- interval = wpa_s->conf->sched_scan_interval ?
- wpa_s->conf->sched_scan_interval : 10;
+ if (wpa_s->sched_scan_plans_num) {
+ params.sched_scan_plans = wpa_s->sched_scan_plans;
+ params.sched_scan_plans_num = wpa_s->sched_scan_plans_num;
+ } else {
+ /* Set one scan plan that will run infinitely */
+ if (wpa_s->conf->sched_scan_interval)
+ scan_plan.interval = wpa_s->conf->sched_scan_interval;
+ else
+ scan_plan.interval = 10;
+
+ scan_plan.iterations = 0;
+ params.sched_scan_plans = &scan_plan;
+ params.sched_scan_plans_num = 1;
+ }
if (params.freqs == NULL && wpa_s->manual_sched_scan_freqs) {
wpa_dbg(wpa_s, MSG_DEBUG, "Limit sched scan to specified channels");
}
}
- ret = wpa_supplicant_start_sched_scan(wpa_s, ¶ms, interval);
+ ret = wpa_supplicant_start_sched_scan(wpa_s, ¶ms);
os_free(params.filter_ssids);
if (ret == 0)
wpa_s->pno = 1;
return 0;
ret = wpa_supplicant_stop_sched_scan(wpa_s);
+ wpa_s->sched_scan_stop_req = 1;
wpa_s->pno = 0;
wpa_s->pno_sched_pending = 0;
wpa_s->mac_addr_rand_enable |= type;
return 0;
}
+
+
+int wpas_abort_ongoing_scan(struct wpa_supplicant *wpa_s)
+{
+ int scan_work = !!wpa_s->scan_work;
+
+#ifdef CONFIG_P2P
+ scan_work |= !!wpa_s->p2p_scan_work;
+#endif /* CONFIG_P2P */
+
+ if (scan_work && wpa_s->own_scan_running) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "Abort an ongoing scan");
+ return wpa_drv_abort_scan(wpa_s);
+ }
+
+ return 0;
+}
+
+
+int wpas_sched_scan_plans_set(struct wpa_supplicant *wpa_s, const char *cmd)
+{
+ struct sched_scan_plan *scan_plans = NULL;
+ const char *token, *context = NULL;
+ unsigned int num = 0;
+
+ if (!cmd)
+ return -1;
+
+ if (!cmd[0]) {
+ wpa_printf(MSG_DEBUG, "Clear sched scan plans");
+ os_free(wpa_s->sched_scan_plans);
+ wpa_s->sched_scan_plans = NULL;
+ wpa_s->sched_scan_plans_num = 0;
+ return 0;
+ }
+
+ while ((token = cstr_token(cmd, " ", &context))) {
+ int ret;
+ struct sched_scan_plan *scan_plan, *n;
+
+ n = os_realloc_array(scan_plans, num + 1, sizeof(*scan_plans));
+ if (!n)
+ goto fail;
+
+ scan_plans = n;
+ scan_plan = &scan_plans[num];
+ num++;
+
+ ret = sscanf(token, "%u:%u", &scan_plan->interval,
+ &scan_plan->iterations);
+ if (ret <= 0 || ret > 2 || !scan_plan->interval) {
+ wpa_printf(MSG_ERROR,
+ "Invalid sched scan plan input: %s", token);
+ goto fail;
+ }
+
+ if (scan_plan->interval > wpa_s->max_sched_scan_plan_interval) {
+ wpa_printf(MSG_WARNING,
+ "scan plan %u: Scan interval too long(%u), use the maximum allowed(%u)",
+ num, scan_plan->interval,
+ wpa_s->max_sched_scan_plan_interval);
+ scan_plan->interval =
+ wpa_s->max_sched_scan_plan_interval;
+ }
+
+ if (ret == 1) {
+ scan_plan->iterations = 0;
+ break;
+ }
+
+ if (!scan_plan->iterations) {
+ wpa_printf(MSG_ERROR,
+ "scan plan %u: Number of iterations cannot be zero",
+ num);
+ goto fail;
+ }
+
+ if (scan_plan->iterations >
+ wpa_s->max_sched_scan_plan_iterations) {
+ wpa_printf(MSG_WARNING,
+ "scan plan %u: Too many iterations(%u), use the maximum allowed(%u)",
+ num, scan_plan->iterations,
+ wpa_s->max_sched_scan_plan_iterations);
+ scan_plan->iterations =
+ wpa_s->max_sched_scan_plan_iterations;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "scan plan %u: interval=%u iterations=%u",
+ num, scan_plan->interval, scan_plan->iterations);
+ }
+
+ if (!scan_plans) {
+ wpa_printf(MSG_ERROR, "Invalid scan plans entry");
+ goto fail;
+ }
+
+ if (cstr_token(cmd, " ", &context) || scan_plans[num - 1].iterations) {
+ wpa_printf(MSG_ERROR,
+ "All scan plans but the last must specify a number of iterations");
+ goto fail;
+ }
+
+ wpa_printf(MSG_DEBUG, "scan plan %u (last plan): interval=%u",
+ num, scan_plans[num - 1].interval);
+
+ if (num > wpa_s->max_sched_scan_plans) {
+ wpa_printf(MSG_WARNING,
+ "Too many scheduled scan plans (only %u supported)",
+ wpa_s->max_sched_scan_plans);
+ wpa_printf(MSG_WARNING,
+ "Use only the first %u scan plans, and the last one (in infinite loop)",
+ wpa_s->max_sched_scan_plans - 1);
+ os_memcpy(&scan_plans[wpa_s->max_sched_scan_plans - 1],
+ &scan_plans[num - 1], sizeof(*scan_plans));
+ num = wpa_s->max_sched_scan_plans;
+ }
+
+ os_free(wpa_s->sched_scan_plans);
+ wpa_s->sched_scan_plans = scan_plans;
+ wpa_s->sched_scan_plans_num = num;
+
+ return 0;
+
+fail:
+ os_free(scan_plans);
+ wpa_printf(MSG_ERROR, "invalid scan plans list");
+ return -1;
+}
+
+
+/**
+ * wpas_scan_reset_sched_scan - Reset sched_scan state
+ * @wpa_s: Pointer to wpa_supplicant data
+ *
+ * This function is used to cancel a running scheduled scan and to reset an
+ * internal scan state to continue with a regular scan on the following
+ * wpa_supplicant_req_scan() calls.
+ */
+void wpas_scan_reset_sched_scan(struct wpa_supplicant *wpa_s)
+{
+ wpa_s->normal_scans = 0;
+ if (wpa_s->sched_scanning) {
+ wpa_s->sched_scan_timed_out = 0;
+ wpa_s->prev_sched_ssid = NULL;
+ wpa_supplicant_cancel_sched_scan(wpa_s);
+ }
+}
+
+
+void wpas_scan_restart_sched_scan(struct wpa_supplicant *wpa_s)
+{
+ /* simulate timeout to restart the sched scan */
+ wpa_s->sched_scan_timed_out = 1;
+ wpa_s->prev_sched_ssid = NULL;
+ wpa_supplicant_cancel_sched_scan(wpa_s);
+}
void scan_only_handler(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res);
int wpas_scan_scheduled(struct wpa_supplicant *wpa_s);
-int wpa_supplicant_start_sched_scan(struct wpa_supplicant *wpa_s,
- struct wpa_driver_scan_params *params,
- int interval);
-int wpa_supplicant_stop_sched_scan(struct wpa_supplicant *wpa_s);
struct wpa_driver_scan_params *
wpa_scan_clone_params(const struct wpa_driver_scan_params *src);
void wpa_scan_free_params(struct wpa_driver_scan_params *params);
int wpas_start_pno(struct wpa_supplicant *wpa_s);
int wpas_stop_pno(struct wpa_supplicant *wpa_s);
+void wpas_scan_reset_sched_scan(struct wpa_supplicant *wpa_s);
+void wpas_scan_restart_sched_scan(struct wpa_supplicant *wpa_s);
void wpas_mac_addr_rand_scan_clear(struct wpa_supplicant *wpa_s,
unsigned int type);
int wpas_mac_addr_rand_scan_set(struct wpa_supplicant *wpa_s,
unsigned int type, const u8 *addr,
const u8 *mask);
+int wpas_abort_ongoing_scan(struct wpa_supplicant *wpa_s);
+void filter_scan_res(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_results *res);
+void scan_snr(struct wpa_scan_res *res);
+void scan_est_throughput(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_res *res);
+void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s);
#endif /* SCAN_H */
return;
}
- if (!(wpa_s->drv_rrm_flags &
- WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES) ||
- !(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_QUIET)) {
+ if (!((wpa_s->drv_rrm_flags &
+ WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES) &&
+ (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_QUIET)) &&
+ !(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_RRM)) {
wpa_printf(MSG_DEBUG,
"RRM: Insufficient RRM support in driver - do not use RRM");
return;
if (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)
*pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT;
+ if (wpa_s->lci)
+ pos[1] |= WLAN_RRM_CAPS_LCI_MEASUREMENT;
+
wpa_s->sme.assoc_req_ie_len += rrm_ie_len + 2;
wpa_s->rrm.rrm_used = 1;
}
u8 ext_capab[18];
int ext_capab_len;
int skip_auth;
+#ifdef CONFIG_MBO
+ const u8 *mbo;
+#endif /* CONFIG_MBO */
if (bss == NULL) {
wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for "
}
#endif /* CONFIG_P2P */
-#ifdef CONFIG_HS20
- if (is_hs20_network(wpa_s, ssid, bss)) {
- struct wpabuf *hs20;
- hs20 = wpabuf_alloc(20);
- if (hs20) {
- int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
- size_t len;
-
- wpas_hs20_add_indication(hs20, pps_mo_id);
- len = sizeof(wpa_s->sme.assoc_req_ie) -
- wpa_s->sme.assoc_req_ie_len;
- if (wpabuf_len(hs20) <= len) {
- os_memcpy(wpa_s->sme.assoc_req_ie +
- wpa_s->sme.assoc_req_ie_len,
- wpabuf_head(hs20), wpabuf_len(hs20));
- wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20);
- }
- wpabuf_free(hs20);
- }
- }
-#endif /* CONFIG_HS20 */
-
#ifdef CONFIG_FST
if (wpa_s->fst_ies) {
int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
}
#endif /* CONFIG_FST */
+ sme_auth_handle_rrm(wpa_s, bss);
+
+#ifdef CONFIG_MBO
+ mbo = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
+ if (mbo) {
+ int len;
+
+ len = wpas_mbo_supp_op_class_ie(
+ wpa_s, bss->freq,
+ wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
+ sizeof(wpa_s->sme.assoc_req_ie) -
+ wpa_s->sme.assoc_req_ie_len);
+ if (len > 0)
+ wpa_s->sme.assoc_req_ie_len += len;
+ }
+#endif /* CONFIG_MBO */
+
+ if (params.p2p)
+ wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
+ else
+ wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
+
ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
sizeof(ext_capab));
if (ext_capab_len > 0) {
os_memcpy(pos, ext_capab, ext_capab_len);
}
+#ifdef CONFIG_HS20
+ if (is_hs20_network(wpa_s, ssid, bss)) {
+ struct wpabuf *hs20;
+
+ hs20 = wpabuf_alloc(20);
+ if (hs20) {
+ int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
+ size_t len;
+
+ wpas_hs20_add_indication(hs20, pps_mo_id);
+ len = sizeof(wpa_s->sme.assoc_req_ie) -
+ wpa_s->sme.assoc_req_ie_len;
+ if (wpabuf_len(hs20) <= len) {
+ os_memcpy(wpa_s->sme.assoc_req_ie +
+ wpa_s->sme.assoc_req_ie_len,
+ wpabuf_head(hs20), wpabuf_len(hs20));
+ wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20);
+ }
+ wpabuf_free(hs20);
+ }
+ }
+#endif /* CONFIG_HS20 */
+
if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
size_t len;
}
}
- sme_auth_handle_rrm(wpa_s, bss);
+#ifdef CONFIG_MBO
+ if (mbo) {
+ int len;
+
+ len = wpas_mbo_ie(wpa_s, wpa_s->sme.assoc_req_ie +
+ wpa_s->sme.assoc_req_ie_len,
+ sizeof(wpa_s->sme.assoc_req_ie) -
+ wpa_s->sme.assoc_req_ie_len);
+ if (len >= 0)
+ wpa_s->sme.assoc_req_ie_len += len;
+ }
+#endif /* CONFIG_MBO */
#ifdef CONFIG_SAE
if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE &&
if (old_ssid != wpa_s->current_ssid)
wpas_notify_network_changed(wpa_s);
+#ifdef CONFIG_HS20
+ hs20_configure_frame_filters(wpa_s);
+#endif /* CONFIG_HS20 */
+
#ifdef CONFIG_P2P
/*
* If multi-channel concurrency is not supported, check for any
radio_remove_works(wpa_s, "sme-connect", 0);
}
+ wpas_abort_ongoing_scan(wpa_s);
+
cwork = os_zalloc(sizeof(*cwork));
if (cwork == NULL)
return;
wpa_printf(MSG_DEBUG, "SME: SAE completed - setting PMK for "
"4-way handshake");
wpa_sm_set_pmk(wpa_s->wpa, wpa_s->sme.sae.pmk, PMK_LEN,
- wpa_s->pending_bssid);
+ wpa_s->sme.sae.pmkid, wpa_s->pending_bssid);
}
#endif /* CONFIG_SAE */
if (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group)
params.p2p = 1;
- if (wpa_s->parent->set_sta_uapsd)
- params.uapsd = wpa_s->parent->sta_uapsd;
+ if (wpa_s->p2pdev->set_sta_uapsd)
+ params.uapsd = wpa_s->p2pdev->sta_uapsd;
else
params.uapsd = -1;
}
-static struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
- u16 num_modes,
- enum hostapd_hw_mode mode)
-{
- u16 i;
-
- for (i = 0; i < num_modes; i++) {
- if (modes[i].mode == mode)
- return &modes[i];
- }
-
- return NULL;
-}
-
-
static void wpa_obss_scan_freqs_list(struct wpa_supplicant *wpa_s,
struct wpa_driver_scan_params *params)
{
nbuf = os_realloc_array(wpa_s->sme.sa_query_trans_id,
wpa_s->sme.sa_query_count + 1,
WLAN_SA_QUERY_TR_ID_LEN);
- if (nbuf == NULL)
+ if (nbuf == NULL) {
+ sme_stop_sa_query(wpa_s);
return;
+ }
if (wpa_s->sme.sa_query_count == 0) {
/* Starting a new SA Query procedure */
os_get_reltime(&wpa_s->sme.sa_query_start);
if (os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) {
wpa_printf(MSG_DEBUG, "Could not generate SA Query ID");
+ sme_stop_sa_query(wpa_s);
return;
}
[Service]
Type=dbus
-BusName=fi.epitest.hostap.WPASupplicant
+BusName=@DBUS_INTERFACE@
ExecStart=@BINDIR@/wpa_supplicant -u
[Install]
WantedBy=multi-user.target
-Alias=dbus-fi.epitest.hostap.WPASupplicant.service
+Alias=dbus-@DBUS_INTERFACE@.service
+++ /dev/null
-/*
- * Dummy functions to allow link_test to be linked. The need for these
- * functions should be removed to allow IEEE 802.1X/EAPOL authenticator to
- * be built outside hostapd.
- */
-
-#include "includes.h"
-
-#include "common.h"
-
-
-struct hostapd_data;
-struct sta_info;
-struct rsn_pmksa_cache_entry;
-struct eapol_state_machine;
-struct hostapd_eap_user;
-struct hostapd_bss_config;
-struct hostapd_vlan;
-
-
-struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta)
-{
- return NULL;
-}
-
-
-int ap_for_each_sta(struct hostapd_data *hapd,
- int (*cb)(struct hostapd_data *hapd, struct sta_info *sta,
- void *ctx),
- void *ctx)
-{
- return 0;
-}
-
-
-void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta,
- u32 session_timeout)
-{
-}
-
-
-int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
- int old_vlanid)
-{
- return 0;
-}
-
-
-void rsn_preauth_finished(struct hostapd_data *hapd, struct sta_info *sta,
- int success)
-{
-}
-
-
-void rsn_preauth_send(struct hostapd_data *hapd, struct sta_info *sta,
- u8 *buf, size_t len)
-{
-}
-
-
-void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta)
-{
-}
-
-
-void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry,
- struct eapol_state_machine *eapol)
-{
-}
-
-
-const struct hostapd_eap_user *
-hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity,
- size_t identity_len, int phase2)
-{
- return NULL;
-}
-
-
-const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id)
-{
- return NULL;
-}
+++ /dev/null
-/*
- * Test program for EAP-SIM PRF
- * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "eap_common/eap_sim_common.c"
-
-
-static int test_eap_sim_prf(void)
-{
- /* http://csrc.nist.gov/encryption/dss/Examples-1024bit.pdf */
- u8 xkey[] = {
- 0xbd, 0x02, 0x9b, 0xbe, 0x7f, 0x51, 0x96, 0x0b,
- 0xcf, 0x9e, 0xdb, 0x2b, 0x61, 0xf0, 0x6f, 0x0f,
- 0xeb, 0x5a, 0x38, 0xb6
- };
- u8 w[] = {
- 0x20, 0x70, 0xb3, 0x22, 0x3d, 0xba, 0x37, 0x2f,
- 0xde, 0x1c, 0x0f, 0xfc, 0x7b, 0x2e, 0x3b, 0x49,
- 0x8b, 0x26, 0x06, 0x14, 0x3c, 0x6c, 0x18, 0xba,
- 0xcb, 0x0f, 0x6c, 0x55, 0xba, 0xbb, 0x13, 0x78,
- 0x8e, 0x20, 0xd7, 0x37, 0xa3, 0x27, 0x51, 0x16
- };
- u8 buf[40];
-
- printf("Testing EAP-SIM PRF (FIPS 186-2 + change notice 1)\n");
- eap_sim_prf(xkey, buf, sizeof(buf));
- if (memcmp(w, buf, sizeof(w)) != 0) {
- printf("eap_sim_prf failed\n");
- return 1;
- }
-
- return 0;
-}
-
-
-int main(int argc, char *argv[])
-{
- int errors = 0;
-
- errors += test_eap_sim_prf();
-
- return errors;
-}
+++ /dev/null
-/*
- * Test program for combined WPA authenticator/supplicant
- * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "includes.h"
-
-#include "common.h"
-#include "eloop.h"
-#include "common/ieee802_11_defs.h"
-#include "../config.h"
-#include "rsn_supp/wpa.h"
-#include "rsn_supp/wpa_ie.h"
-#include "ap/wpa_auth.h"
-
-
-struct wpa {
- u8 auth_addr[ETH_ALEN];
- u8 supp_addr[ETH_ALEN];
- u8 psk[PMK_LEN];
-
- /* from authenticator */
- u8 auth_eapol_dst[ETH_ALEN];
- u8 *auth_eapol;
- size_t auth_eapol_len;
-
- /* from supplicant */
- u8 *supp_eapol;
- size_t supp_eapol_len;
-
- struct wpa_sm *supp;
- struct wpa_authenticator *auth_group;
- struct wpa_state_machine *auth;
-
- struct wpa_ssid ssid;
- u8 supp_ie[80];
- size_t supp_ie_len;
-};
-
-
-static int supp_get_bssid(void *ctx, u8 *bssid)
-{
- struct wpa *wpa = ctx;
- wpa_printf(MSG_DEBUG, "SUPP: %s", __func__);
- os_memcpy(bssid, wpa->auth_addr, ETH_ALEN);
- return 0;
-}
-
-
-static void supp_set_state(void *ctx, enum wpa_states state)
-{
- wpa_printf(MSG_DEBUG, "SUPP: %s(state=%d)", __func__, state);
-}
-
-
-static void auth_eapol_rx(void *eloop_data, void *user_ctx)
-{
- struct wpa *wpa = eloop_data;
-
- wpa_printf(MSG_DEBUG, "AUTH: RX EAPOL frame");
- wpa_receive(wpa->auth_group, wpa->auth, wpa->supp_eapol,
- wpa->supp_eapol_len);
-}
-
-
-static int supp_ether_send(void *ctx, const u8 *dest, u16 proto, const u8 *buf,
- size_t len)
-{
- struct wpa *wpa = ctx;
-
- wpa_printf(MSG_DEBUG, "SUPP: %s(dest=" MACSTR " proto=0x%04x "
- "len=%lu)",
- __func__, MAC2STR(dest), proto, (unsigned long) len);
-
- os_free(wpa->supp_eapol);
- wpa->supp_eapol = os_malloc(len);
- if (wpa->supp_eapol == NULL)
- return -1;
- os_memcpy(wpa->supp_eapol, buf, len);
- wpa->supp_eapol_len = len;
- eloop_register_timeout(0, 0, auth_eapol_rx, wpa, NULL);
-
- return 0;
-}
-
-
-static u8 * supp_alloc_eapol(void *ctx, u8 type, const void *data,
- u16 data_len, size_t *msg_len, void **data_pos)
-{
- struct ieee802_1x_hdr *hdr;
-
- wpa_printf(MSG_DEBUG, "SUPP: %s(type=%d data_len=%d)",
- __func__, type, data_len);
-
- *msg_len = sizeof(*hdr) + data_len;
- hdr = os_malloc(*msg_len);
- if (hdr == NULL)
- return NULL;
-
- hdr->version = 2;
- hdr->type = type;
- hdr->length = host_to_be16(data_len);
-
- if (data)
- os_memcpy(hdr + 1, data, data_len);
- else
- os_memset(hdr + 1, 0, data_len);
-
- if (data_pos)
- *data_pos = hdr + 1;
-
- return (u8 *) hdr;
-}
-
-
-static int supp_get_beacon_ie(void *ctx)
-{
- struct wpa *wpa = ctx;
- const u8 *ie;
- size_t ielen;
-
- wpa_printf(MSG_DEBUG, "SUPP: %s", __func__);
-
- ie = wpa_auth_get_wpa_ie(wpa->auth_group, &ielen);
- if (ie == NULL || ielen < 1)
- return -1;
- if (ie[0] == WLAN_EID_RSN)
- return wpa_sm_set_ap_rsn_ie(wpa->supp, ie, 2 + ie[1]);
- return wpa_sm_set_ap_wpa_ie(wpa->supp, ie, 2 + ie[1]);
-}
-
-
-static int supp_set_key(void *ctx, enum wpa_alg alg,
- const u8 *addr, int key_idx, int set_tx,
- const u8 *seq, size_t seq_len,
- const u8 *key, size_t key_len)
-{
- wpa_printf(MSG_DEBUG, "SUPP: %s(alg=%d addr=" MACSTR " key_idx=%d "
- "set_tx=%d)",
- __func__, alg, MAC2STR(addr), key_idx, set_tx);
- wpa_hexdump(MSG_DEBUG, "SUPP: set_key - seq", seq, seq_len);
- wpa_hexdump(MSG_DEBUG, "SUPP: set_key - key", key, key_len);
- return 0;
-}
-
-
-static int supp_mlme_setprotection(void *ctx, const u8 *addr,
- int protection_type, int key_type)
-{
- wpa_printf(MSG_DEBUG, "SUPP: %s(addr=" MACSTR " protection_type=%d "
- "key_type=%d)",
- __func__, MAC2STR(addr), protection_type, key_type);
- return 0;
-}
-
-
-static void supp_cancel_auth_timeout(void *ctx)
-{
- wpa_printf(MSG_DEBUG, "SUPP: %s", __func__);
-}
-
-
-static int supp_init(struct wpa *wpa)
-{
- struct wpa_sm_ctx *ctx = os_zalloc(sizeof(*ctx));
- if (ctx == NULL)
- return -1;
-
- ctx->ctx = wpa;
- ctx->msg_ctx = wpa;
- ctx->set_state = supp_set_state;
- ctx->get_bssid = supp_get_bssid;
- ctx->ether_send = supp_ether_send;
- ctx->get_beacon_ie = supp_get_beacon_ie;
- ctx->alloc_eapol = supp_alloc_eapol;
- ctx->set_key = supp_set_key;
- ctx->mlme_setprotection = supp_mlme_setprotection;
- ctx->cancel_auth_timeout = supp_cancel_auth_timeout;
- wpa->supp = wpa_sm_init(ctx);
- if (wpa->supp == NULL) {
- wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed");
- return -1;
- }
-
- wpa_sm_set_own_addr(wpa->supp, wpa->supp_addr);
- wpa_sm_set_param(wpa->supp, WPA_PARAM_RSN_ENABLED, 1);
- wpa_sm_set_param(wpa->supp, WPA_PARAM_PROTO, WPA_PROTO_RSN);
- wpa_sm_set_param(wpa->supp, WPA_PARAM_PAIRWISE, WPA_CIPHER_CCMP);
- wpa_sm_set_param(wpa->supp, WPA_PARAM_GROUP, WPA_CIPHER_CCMP);
- wpa_sm_set_param(wpa->supp, WPA_PARAM_KEY_MGMT, WPA_KEY_MGMT_PSK);
- wpa_sm_set_pmk(wpa->supp, wpa->psk, PMK_LEN);
-
- wpa->supp_ie_len = sizeof(wpa->supp_ie);
- if (wpa_sm_set_assoc_wpa_ie_default(wpa->supp, wpa->supp_ie,
- &wpa->supp_ie_len) < 0) {
- wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_set_assoc_wpa_ie_default()"
- " failed");
- return -1;
- }
-
- wpa_sm_notify_assoc(wpa->supp, wpa->auth_addr);
-
- return 0;
-}
-
-
-static void auth_logger(void *ctx, const u8 *addr, logger_level level,
- const char *txt)
-{
- if (addr)
- wpa_printf(MSG_DEBUG, "AUTH: " MACSTR " - %s",
- MAC2STR(addr), txt);
- else
- wpa_printf(MSG_DEBUG, "AUTH: %s", txt);
-}
-
-
-static void supp_eapol_rx(void *eloop_data, void *user_ctx)
-{
- struct wpa *wpa = eloop_data;
-
- wpa_printf(MSG_DEBUG, "SUPP: RX EAPOL frame");
- wpa_sm_rx_eapol(wpa->supp, wpa->auth_addr, wpa->auth_eapol,
- wpa->auth_eapol_len);
-}
-
-
-static int auth_send_eapol(void *ctx, const u8 *addr, const u8 *data,
- size_t data_len, int encrypt)
-{
- struct wpa *wpa = ctx;
-
- wpa_printf(MSG_DEBUG, "AUTH: %s(addr=" MACSTR " data_len=%lu "
- "encrypt=%d)",
- __func__, MAC2STR(addr), (unsigned long) data_len, encrypt);
-
- os_free(wpa->auth_eapol);
- wpa->auth_eapol = os_malloc(data_len);
- if (wpa->auth_eapol == NULL)
- return -1;
- os_memcpy(wpa->auth_eapol_dst, addr, ETH_ALEN);
- os_memcpy(wpa->auth_eapol, data, data_len);
- wpa->auth_eapol_len = data_len;
- eloop_register_timeout(0, 0, supp_eapol_rx, wpa, NULL);
-
- return 0;
-}
-
-
-static const u8 * auth_get_psk(void *ctx, const u8 *addr, const u8 *prev_psk)
-{
- struct wpa *wpa = ctx;
- wpa_printf(MSG_DEBUG, "AUTH: %s (addr=" MACSTR " prev_psk=%p)",
- __func__, MAC2STR(addr), prev_psk);
- if (prev_psk)
- return NULL;
- return wpa->psk;
-}
-
-
-static int auth_init_group(struct wpa *wpa)
-{
- struct wpa_auth_config conf;
- struct wpa_auth_callbacks cb;
-
- wpa_printf(MSG_DEBUG, "AUTH: Initializing group state machine");
-
- os_memset(&conf, 0, sizeof(conf));
- conf.wpa = 2;
- conf.wpa_key_mgmt = WPA_KEY_MGMT_PSK;
- conf.wpa_pairwise = WPA_CIPHER_CCMP;
- conf.rsn_pairwise = WPA_CIPHER_CCMP;
- conf.wpa_group = WPA_CIPHER_CCMP;
- conf.eapol_version = 2;
-
- os_memset(&cb, 0, sizeof(cb));
- cb.ctx = wpa;
- cb.logger = auth_logger;
- cb.send_eapol = auth_send_eapol;
- cb.get_psk = auth_get_psk;
-
- wpa->auth_group = wpa_init(wpa->auth_addr, &conf, &cb);
- if (wpa->auth_group == NULL) {
- wpa_printf(MSG_DEBUG, "AUTH: wpa_init() failed");
- return -1;
- }
-
- return 0;
-}
-
-
-static int auth_init(struct wpa *wpa)
-{
- wpa->auth = wpa_auth_sta_init(wpa->auth_group, wpa->supp_addr, NULL);
- if (wpa->auth == NULL) {
- wpa_printf(MSG_DEBUG, "AUTH: wpa_auth_sta_init() failed");
- return -1;
- }
-
- if (wpa_validate_wpa_ie(wpa->auth_group, wpa->auth, wpa->supp_ie,
- wpa->supp_ie_len, NULL, 0) != WPA_IE_OK) {
- wpa_printf(MSG_DEBUG, "AUTH: wpa_validate_wpa_ie() failed");
- return -1;
- }
-
- wpa_auth_sm_event(wpa->auth, WPA_ASSOC);
-
- wpa_auth_sta_associated(wpa->auth_group, wpa->auth);
-
- return 0;
-}
-
-
-static void deinit(struct wpa *wpa)
-{
- wpa_auth_sta_deinit(wpa->auth);
- wpa_sm_deinit(wpa->supp);
- wpa_deinit(wpa->auth_group);
- os_free(wpa->auth_eapol);
- wpa->auth_eapol = NULL;
- os_free(wpa->supp_eapol);
- wpa->supp_eapol = NULL;
-}
-
-
-int main(int argc, char *argv[])
-{
- struct wpa wpa;
-
- if (os_program_init())
- return -1;
-
- os_memset(&wpa, 0, sizeof(wpa));
- os_memset(wpa.auth_addr, 0x12, ETH_ALEN);
- os_memset(wpa.supp_addr, 0x32, ETH_ALEN);
- os_memset(wpa.psk, 0x44, PMK_LEN);
-
- wpa_debug_level = 0;
- wpa_debug_show_keys = 1;
-
- if (eloop_init()) {
- wpa_printf(MSG_ERROR, "Failed to initialize event loop");
- return -1;
- }
-
- if (auth_init_group(&wpa) < 0)
- return -1;
-
- if (supp_init(&wpa) < 0)
- return -1;
-
- if (auth_init(&wpa) < 0)
- return -1;
-
- wpa_printf(MSG_DEBUG, "Starting eloop");
- eloop_run();
- wpa_printf(MSG_DEBUG, "eloop done");
-
- deinit(&wpa);
-
- eloop_destroy();
-
- os_program_deinit();
-
- return 0;
-}
*/
struct wmm_ac_addts_request {
/*
- * dialog token - Used to link the recived ADDTS response with this
+ * dialog token - Used to link the received ADDTS response with this
* saved ADDTS request when ADDTS response is being handled
*/
u8 dialog_token;
#define MAX_TFS_IE_LEN 1024
#define WNM_MAX_NEIGHBOR_REPORT 10
+#define WNM_SCAN_RESULT_AGE 2 /* 2 seconds */
/* get the TFS IE from driver */
static int ieee80211_11_get_tfs_ie(struct wpa_supplicant *wpa_s, u8 *buf,
/* set the TFS IE to driver */
static int ieee80211_11_set_tfs_ie(struct wpa_supplicant *wpa_s,
- const u8 *addr, u8 *buf, u16 *buf_len,
+ const u8 *addr, const u8 *buf, u16 buf_len,
enum wnm_oper oper)
{
+ u16 len = buf_len;
+
wpa_printf(MSG_DEBUG, "%s: TFS set operation %d", __func__, oper);
- return wpa_drv_wnm_oper(wpa_s, oper, addr, buf, buf_len);
+ return wpa_drv_wnm_oper(wpa_s, oper, addr, (u8 *) buf, &len);
}
if (res < 0)
wpa_printf(MSG_DEBUG, "Failed to send WNM-Sleep Request "
"(action=%d, intval=%d)", action, intval);
+ else
+ wpa_s->wnmsleep_used = 1;
os_free(wnmsleep_ie);
os_free(wnmtfs_ie);
static void wnm_sleep_mode_enter_success(struct wpa_supplicant *wpa_s,
- u8 *tfsresp_ie_start,
- u8 *tfsresp_ie_end)
+ const u8 *tfsresp_ie_start,
+ const u8 *tfsresp_ie_end)
{
wpa_drv_wnm_oper(wpa_s, WNM_SLEEP_ENTER_CONFIRM,
wpa_s->bssid, NULL, NULL);
/* pass the TFS Resp IE(s) to driver for processing */
if (ieee80211_11_set_tfs_ie(wpa_s, wpa_s->bssid,
tfsresp_ie_start,
- &tfsresp_ie_len,
+ tfsresp_ie_len,
WNM_SLEEP_TFS_RESP_IE_SET))
wpa_printf(MSG_DEBUG, "WNM: Fail to set TFS Resp IE");
}
end = ptr + key_len_total;
wpa_hexdump_key(MSG_DEBUG, "WNM: Key Data", ptr, key_len_total);
- while (ptr + 1 < end) {
- if (ptr + 2 + ptr[1] > end) {
+ if (key_len_total && !wpa_sm_pmf_enabled(wpa_s->wpa)) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "WNM: Ignore Key Data in WNM-Sleep Mode Response - PMF not enabled");
+ return;
+ }
+
+ while (end - ptr > 1) {
+ if (2 + ptr[1] > end - ptr) {
wpa_printf(MSG_DEBUG, "WNM: Invalid Key Data element "
"length");
if (end > ptr) {
* Action [1] | Dialog Token [1] | Key Data Len [2] | Key Data |
* WNM-Sleep Mode IE | TFS Response IE
*/
- u8 *pos = (u8 *) frm; /* point to payload after the action field */
+ const u8 *pos = frm; /* point to payload after the action field */
u16 key_len_total;
struct wnm_sleep_element *wnmsleep_ie = NULL;
/* multiple TFS Resp IE (assuming consecutive) */
- u8 *tfsresp_ie_start = NULL;
- u8 *tfsresp_ie_end = NULL;
+ const u8 *tfsresp_ie_start = NULL;
+ const u8 *tfsresp_ie_end = NULL;
size_t left;
+ if (!wpa_s->wnmsleep_used) {
+ wpa_printf(MSG_DEBUG,
+ "WNM: Ignore WNM-Sleep Mode Response frame since WNM-Sleep Mode has not been used in this association");
+ return;
+ }
+
if (len < 3)
return;
key_len_total = WPA_GET_LE16(frm + 1);
return;
}
pos += 3 + key_len_total;
- while (pos - frm < len) {
+ while (pos - frm + 1 < len) {
u8 ie_len = *(pos + 1);
- if (pos + 2 + ie_len > frm + len) {
+ if (2 + ie_len > frm + len - pos) {
wpa_printf(MSG_INFO, "WNM: Invalid IE len %u", ie_len);
break;
}
wpa_hexdump(MSG_DEBUG, "WNM: Element", pos, 2 + ie_len);
- if (*pos == WLAN_EID_WNMSLEEP)
+ if (*pos == WLAN_EID_WNMSLEEP && ie_len >= 4)
wnmsleep_ie = (struct wnm_sleep_element *) pos;
else if (*pos == WLAN_EID_TFS_RESP) {
if (!tfsresp_ie_start)
{
struct wpa_bss *bss = wpa_s->current_bss;
const char *country = NULL;
+ int freq;
if (bss) {
const u8 *elem = wpa_bss_get_ie(bss, WLAN_EID_COUNTRY);
country = (const char *) (elem + 2);
}
- return ieee80211_chan_to_freq(country, op_class, chan);
+ freq = ieee80211_chan_to_freq(country, op_class, chan);
+ if (freq <= 0 && op_class == 0) {
+ /*
+ * Some APs do not advertise correct operating class
+ * information. Try to determine the most likely operating
+ * frequency based on the channel number.
+ */
+ if (chan >= 1 && chan <= 13)
+ freq = 2407 + chan * 5;
+ else if (chan == 14)
+ freq = 2484;
+ else if (chan >= 36 && chan <= 169)
+ freq = 5000 + chan * 5;
+ }
+ return freq;
}
static struct wpa_bss *
-compare_scan_neighbor_results(struct wpa_supplicant *wpa_s)
+compare_scan_neighbor_results(struct wpa_supplicant *wpa_s, os_time_t age_secs)
{
u8 i;
struct wpa_bss *target;
if (!bss)
- return 0;
+ return NULL;
wpa_printf(MSG_DEBUG, "WNM: Current BSS " MACSTR " RSSI %d",
MAC2STR(wpa_s->bssid), bss->level);
continue;
}
+ if (age_secs) {
+ struct os_reltime now;
+
+ if (os_get_reltime(&now) == 0 &&
+ os_reltime_expired(&now, &target->last_update,
+ age_secs)) {
+ wpa_printf(MSG_DEBUG,
+ "Candidate BSS is more than %ld seconds old",
+ age_secs);
+ continue;
+ }
+ }
+
if (bss->ssid_len != target->ssid_len ||
os_memcmp(bss->ssid, target->ssid, bss->ssid_len) != 0) {
/*
continue;
}
+ if (wpa_s->current_ssid &&
+ !wpa_scan_res_match(wpa_s, 0, target, wpa_s->current_ssid,
+ 1)) {
+ wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
+ " (pref %d) does not match the current network profile",
+ MAC2STR(nei->bssid),
+ nei->preference_present ? nei->preference :
+ -1);
+ continue;
+ }
+
+ if (wpa_is_bss_tmp_disallowed(wpa_s, target->bssid)) {
+ wpa_printf(MSG_DEBUG,
+ "MBO: Candidate BSS " MACSTR
+ " retry delay is not over yet",
+ MAC2STR(nei->bssid));
+ continue;
+ }
+
if (target->level < bss->level && target->level < -80) {
wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
" (pref %d) does not have sufficient signal level (%d)",
}
+static int wpa_bss_ies_eq(struct wpa_bss *a, struct wpa_bss *b, u8 eid)
+{
+ const u8 *ie_a, *ie_b;
+
+ if (!a || !b)
+ return 0;
+
+ ie_a = wpa_bss_get_ie(a, eid);
+ ie_b = wpa_bss_get_ie(b, eid);
+
+ if (!ie_a || !ie_b || ie_a[1] != ie_b[1])
+ return 0;
+
+ return os_memcmp(ie_a, ie_b, ie_a[1]) == 0;
+}
+
+
+static u32 wnm_get_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
+{
+ u32 info = 0;
+
+ info |= NEI_REP_BSSID_INFO_AP_UNKNOWN_REACH;
+
+ /*
+ * Leave the security and key scope bits unset to indicate that the
+ * security information is not available.
+ */
+
+ if (bss->caps & WLAN_CAPABILITY_SPECTRUM_MGMT)
+ info |= NEI_REP_BSSID_INFO_SPECTRUM_MGMT;
+ if (bss->caps & WLAN_CAPABILITY_QOS)
+ info |= NEI_REP_BSSID_INFO_QOS;
+ if (bss->caps & WLAN_CAPABILITY_APSD)
+ info |= NEI_REP_BSSID_INFO_APSD;
+ if (bss->caps & WLAN_CAPABILITY_RADIO_MEASUREMENT)
+ info |= NEI_REP_BSSID_INFO_RM;
+ if (bss->caps & WLAN_CAPABILITY_DELAYED_BLOCK_ACK)
+ info |= NEI_REP_BSSID_INFO_DELAYED_BA;
+ if (bss->caps & WLAN_CAPABILITY_IMM_BLOCK_ACK)
+ info |= NEI_REP_BSSID_INFO_IMM_BA;
+ if (wpa_bss_ies_eq(bss, wpa_s->current_bss, WLAN_EID_MOBILITY_DOMAIN))
+ info |= NEI_REP_BSSID_INFO_MOBILITY_DOMAIN;
+ if (wpa_bss_ies_eq(bss, wpa_s->current_bss, WLAN_EID_HT_CAP))
+ info |= NEI_REP_BSSID_INFO_HT;
+
+ return info;
+}
+
+
+static int wnm_add_nei_rep(u8 *buf, size_t len, const u8 *bssid, u32 bss_info,
+ u8 op_class, u8 chan, u8 phy_type, u8 pref)
+{
+ u8 *pos = buf;
+
+ if (len < 18) {
+ wpa_printf(MSG_DEBUG,
+ "WNM: Not enough room for Neighbor Report element");
+ return -1;
+ }
+
+ *pos++ = WLAN_EID_NEIGHBOR_REPORT;
+ /* length: 13 for basic neighbor report + 3 for preference subelement */
+ *pos++ = 16;
+ os_memcpy(pos, bssid, ETH_ALEN);
+ pos += ETH_ALEN;
+ WPA_PUT_LE32(pos, bss_info);
+ pos += 4;
+ *pos++ = op_class;
+ *pos++ = chan;
+ *pos++ = phy_type;
+ *pos++ = WNM_NEIGHBOR_BSS_TRANSITION_CANDIDATE;
+ *pos++ = 1;
+ *pos++ = pref;
+ return pos - buf;
+}
+
+
+static int wnm_nei_rep_add_bss(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss, u8 *buf, size_t len,
+ u8 pref)
+{
+ const u8 *ie;
+ u8 op_class, chan;
+ int sec_chan = 0, vht = 0;
+ enum phy_type phy_type;
+ u32 info;
+ struct ieee80211_ht_operation *ht_oper = NULL;
+ struct ieee80211_vht_operation *vht_oper = NULL;
+
+ ie = wpa_bss_get_ie(bss, WLAN_EID_HT_OPERATION);
+ if (ie && ie[1] >= 2) {
+ ht_oper = (struct ieee80211_ht_operation *) (ie + 2);
+
+ if (ht_oper->ht_param & HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
+ sec_chan = 1;
+ else if (ht_oper->ht_param &
+ HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
+ sec_chan = -1;
+ }
+
+ ie = wpa_bss_get_ie(bss, WLAN_EID_VHT_OPERATION);
+ if (ie && ie[1] >= 1) {
+ vht_oper = (struct ieee80211_vht_operation *) (ie + 2);
+
+ if (vht_oper->vht_op_info_chwidth == VHT_CHANWIDTH_80MHZ ||
+ vht_oper->vht_op_info_chwidth == VHT_CHANWIDTH_160MHZ ||
+ vht_oper->vht_op_info_chwidth == VHT_CHANWIDTH_80P80MHZ)
+ vht = vht_oper->vht_op_info_chwidth;
+ }
+
+ if (ieee80211_freq_to_channel_ext(bss->freq, sec_chan, vht, &op_class,
+ &chan) == NUM_HOSTAPD_MODES) {
+ wpa_printf(MSG_DEBUG,
+ "WNM: Cannot determine operating class and channel");
+ return -2;
+ }
+
+ phy_type = ieee80211_get_phy_type(bss->freq, (ht_oper != NULL),
+ (vht_oper != NULL));
+ if (phy_type == PHY_TYPE_UNSPECIFIED) {
+ wpa_printf(MSG_DEBUG,
+ "WNM: Cannot determine BSS phy type for Neighbor Report");
+ return -2;
+ }
+
+ info = wnm_get_bss_info(wpa_s, bss);
+
+ return wnm_add_nei_rep(buf, len, bss->bssid, info, op_class, chan,
+ phy_type, pref);
+}
+
+
+static int wnm_add_cand_list(struct wpa_supplicant *wpa_s, u8 *buf, size_t len)
+{
+ u8 *pos = buf;
+ unsigned int i, pref = 255;
+ struct os_reltime now;
+ struct wpa_ssid *ssid = wpa_s->current_ssid;
+
+ if (!ssid)
+ return 0;
+
+ /*
+ * TODO: Define when scan results are no longer valid for the candidate
+ * list.
+ */
+ os_get_reltime(&now);
+ if (os_reltime_expired(&now, &wpa_s->last_scan, 10))
+ return 0;
+
+ wpa_printf(MSG_DEBUG,
+ "WNM: Add candidate list to BSS Transition Management Response frame");
+ for (i = 0; i < wpa_s->last_scan_res_used && pref; i++) {
+ struct wpa_bss *bss = wpa_s->last_scan_res[i];
+ int res;
+
+ if (wpa_scan_res_match(wpa_s, i, bss, ssid, 1)) {
+ res = wnm_nei_rep_add_bss(wpa_s, bss, pos, len, pref--);
+ if (res == -2)
+ continue; /* could not build entry for BSS */
+ if (res < 0)
+ break; /* no more room for candidates */
+ if (pref == 1)
+ break;
+
+ pos += res;
+ len -= res;
+ }
+ }
+
+ wpa_hexdump(MSG_DEBUG,
+ "WNM: BSS Transition Management Response candidate list",
+ buf, pos - buf);
+
+ return pos - buf;
+}
+
+
static void wnm_send_bss_transition_mgmt_resp(
struct wpa_supplicant *wpa_s, u8 dialog_token,
enum bss_trans_mgmt_status_code status, u8 delay,
const u8 *target_bssid)
{
- u8 buf[1000], *pos;
+ u8 buf[2000], *pos;
struct ieee80211_mgmt *mgmt;
size_t len;
int res;
pos += ETH_ALEN;
}
+ if (status == WNM_BSS_TM_ACCEPT)
+ pos += wnm_add_cand_list(wpa_s, pos, buf + sizeof(buf) - pos);
+
+#ifdef CONFIG_MBO
+ if (status != WNM_BSS_TM_ACCEPT) {
+ pos += wpas_mbo_ie_bss_trans_reject(
+ wpa_s, pos, buf + sizeof(buf) - pos,
+ MBO_TRANSITION_REJECT_REASON_UNSPECIFIED);
+ }
+#endif /* CONFIG_MBO */
+
len = pos - (u8 *) &mgmt->u.action.category;
res = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
}
+static void wnm_bss_tm_connect(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss, struct wpa_ssid *ssid,
+ int after_new_scan)
+{
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WNM: Transition to BSS " MACSTR
+ " based on BSS Transition Management Request (old BSSID "
+ MACSTR " after_new_scan=%d)",
+ MAC2STR(bss->bssid), MAC2STR(wpa_s->bssid), after_new_scan);
+
+ /* Send the BSS Management Response - Accept */
+ if (wpa_s->wnm_reply) {
+ wpa_s->wnm_reply = 0;
+ wpa_printf(MSG_DEBUG,
+ "WNM: Sending successful BSS Transition Management Response");
+ wnm_send_bss_transition_mgmt_resp(wpa_s,
+ wpa_s->wnm_dialog_token,
+ WNM_BSS_TM_ACCEPT,
+ 0, bss->bssid);
+ }
+
+ if (bss == wpa_s->current_bss) {
+ wpa_printf(MSG_DEBUG,
+ "WNM: Already associated with the preferred candidate");
+ wnm_deallocate_memory(wpa_s);
+ return;
+ }
+
+ wpa_s->reassociate = 1;
+ wpa_printf(MSG_DEBUG, "WNM: Issuing connect");
+ wpa_supplicant_connect(wpa_s, bss, ssid);
+ wnm_deallocate_memory(wpa_s);
+}
+
+
int wnm_scan_process(struct wpa_supplicant *wpa_s, int reply_on_fail)
{
struct wpa_bss *bss;
if (!wpa_s->wnm_neighbor_report_elements)
return 0;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WNM: Process scan results for BSS Transition Management");
if (os_reltime_before(&wpa_s->wnm_cand_valid_until,
&wpa_s->scan_trigger_time)) {
wpa_printf(MSG_DEBUG, "WNM: Previously stored BSS transition candidate list is not valid anymore - drop it");
}
/* Compare the Neighbor Report and scan results */
- bss = compare_scan_neighbor_results(wpa_s);
+ bss = compare_scan_neighbor_results(wpa_s, 0);
if (!bss) {
wpa_printf(MSG_DEBUG, "WNM: No BSS transition candidate match found");
status = WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES;
}
/* Associate to the network */
- /* Send the BSS Management Response - Accept */
- if (wpa_s->wnm_reply) {
- wpa_s->wnm_reply = 0;
- wnm_send_bss_transition_mgmt_resp(wpa_s,
- wpa_s->wnm_dialog_token,
- WNM_BSS_TM_ACCEPT,
- 0, bss->bssid);
- }
-
- if (bss == wpa_s->current_bss) {
- wpa_printf(MSG_DEBUG,
- "WNM: Already associated with the preferred candidate");
- return 1;
- }
-
- wpa_s->reassociate = 1;
- wpa_supplicant_connect(wpa_s, bss, ssid);
- wnm_deallocate_memory(wpa_s);
+ wnm_bss_tm_connect(wpa_s, bss, ssid, 1);
return 1;
send_bss_resp_fail:
}
+static int wnm_fetch_scan_results(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_scan_results *scan_res;
+ struct wpa_bss *bss;
+ struct wpa_ssid *ssid = wpa_s->current_ssid;
+ u8 i, found = 0;
+ size_t j;
+
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WNM: Fetch current scan results from the driver for checking transition candidates");
+ scan_res = wpa_drv_get_scan_results2(wpa_s);
+ if (!scan_res) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "WNM: Failed to get scan results");
+ return 0;
+ }
+
+ if (scan_res->fetch_time.sec == 0)
+ os_get_reltime(&scan_res->fetch_time);
+
+ filter_scan_res(wpa_s, scan_res);
+
+ for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++) {
+ struct neighbor_report *nei;
+
+ nei = &wpa_s->wnm_neighbor_report_elements[i];
+ if (nei->preference_present && nei->preference == 0)
+ continue;
+
+ for (j = 0; j < scan_res->num; j++) {
+ struct wpa_scan_res *res;
+ const u8 *ssid_ie;
+
+ res = scan_res->res[j];
+ if (os_memcmp(nei->bssid, res->bssid, ETH_ALEN) != 0 ||
+ res->age > WNM_SCAN_RESULT_AGE * 1000)
+ continue;
+ bss = wpa_s->current_bss;
+ ssid_ie = wpa_scan_get_ie(res, WLAN_EID_SSID);
+ if (bss && ssid_ie &&
+ (bss->ssid_len != ssid_ie[1] ||
+ os_memcmp(bss->ssid, ssid_ie + 2,
+ bss->ssid_len) != 0))
+ continue;
+
+ /* Potential candidate found */
+ found = 1;
+ scan_snr(res);
+ scan_est_throughput(wpa_s, res);
+ wpa_bss_update_scan_res(wpa_s, res,
+ &scan_res->fetch_time);
+ }
+ }
+
+ wpa_scan_results_free(scan_res);
+ if (!found) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WNM: No transition candidate matches existing scan results");
+ return 0;
+ }
+
+ bss = compare_scan_neighbor_results(wpa_s, WNM_SCAN_RESULT_AGE);
+ if (!bss) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WNM: Comparison of scan results against transition candidates did not find matches");
+ return 0;
+ }
+
+ /* Associate to the network */
+ wnm_bss_tm_connect(wpa_s, bss, ssid, 0);
+ return 1;
+}
+
+
static void ieee802_11_rx_bss_trans_mgmt_req(struct wpa_supplicant *wpa_s,
const u8 *pos, const u8 *end,
int reply)
{
unsigned int beacon_int;
u8 valid_int;
+#ifdef CONFIG_MBO
+ const u8 *vendor;
+#endif /* CONFIG_MBO */
- if (pos + 5 > end)
+ if (end - pos < 5)
return;
if (wpa_s->current_bss)
wpa_s->wnm_dialog_token, wpa_s->wnm_mode,
wpa_s->wnm_dissoc_timer, valid_int);
+#if defined(CONFIG_MBO) && defined(CONFIG_TESTING_OPTIONS)
+ if (wpa_s->reject_btm_req_reason) {
+ wpa_printf(MSG_INFO,
+ "WNM: Testing - reject BSS Transition Management Request: reject_btm_req_reason=%d",
+ wpa_s->reject_btm_req_reason);
+ wnm_send_bss_transition_mgmt_resp(wpa_s,
+ wpa_s->wnm_dialog_token,
+ wpa_s->reject_btm_req_reason,
+ 0, NULL);
+ return;
+ }
+#endif /* CONFIG_MBO && CONFIG_TESTING_OPTIONS */
+
pos += 5;
if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED) {
- if (pos + 12 > end) {
+ if (end - pos < 12) {
wpa_printf(MSG_DEBUG, "WNM: Too short BSS TM Request");
return;
}
if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT) {
char url[256];
- if (pos + 1 > end || pos + 1 + pos[0] > end) {
+ if (end - pos < 1 || 1 + pos[0] > end - pos) {
wpa_printf(MSG_DEBUG, "WNM: Invalid BSS Transition "
"Management Request (URL)");
return;
}
}
+#ifdef CONFIG_MBO
+ vendor = get_ie(pos, end - pos, WLAN_EID_VENDOR_SPECIFIC);
+ if (vendor)
+ wpas_mbo_ie_trans_req(wpa_s, vendor + 2, vendor[1]);
+#endif /* CONFIG_MBO */
+
if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED) {
unsigned int valid_ms;
if (wpa_s->wnm_neighbor_report_elements == NULL)
return;
- while (pos + 2 <= end &&
+ while (end - pos >= 2 &&
wpa_s->wnm_num_neighbor_report < WNM_MAX_NEIGHBOR_REPORT)
{
u8 tag = *pos++;
wpa_printf(MSG_DEBUG, "WNM: Neighbor report tag %u",
tag);
- if (pos + len > end) {
+ if (len > end - pos) {
wpa_printf(MSG_DEBUG, "WNM: Truncated request");
return;
}
rep = &wpa_s->wnm_neighbor_report_elements[
wpa_s->wnm_num_neighbor_report];
wnm_parse_neighbor_report(wpa_s, pos, len, rep);
+ wpa_s->wnm_num_neighbor_report++;
}
pos += len;
- wpa_s->wnm_num_neighbor_report++;
}
+
+ if (!wpa_s->wnm_num_neighbor_report) {
+ wpa_printf(MSG_DEBUG,
+ "WNM: Candidate list included bit is set, but no candidates found");
+ wnm_send_bss_transition_mgmt_resp(
+ wpa_s, wpa_s->wnm_dialog_token,
+ WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES,
+ 0, NULL);
+ return;
+ }
+
wnm_sort_cand_list(wpa_s);
wnm_dump_cand_list(wpa_s);
valid_ms = valid_int * beacon_int * 128 / 125;
wpa_s->wnm_cand_valid_until.usec %= 1000000;
os_memcpy(wpa_s->wnm_cand_from_bss, wpa_s->bssid, ETH_ALEN);
+ /*
+ * Fetch the latest scan results from the kernel and check for
+ * candidates based on those results first. This can help in
+ * finding more up-to-date information should the driver has
+ * done some internal scanning operations after the last scan
+ * result update in wpa_supplicant.
+ */
+ if (wnm_fetch_scan_results(wpa_s) > 0)
+ return;
+
+ /*
+ * Try to use previously received scan results, if they are
+ * recent enough to use for a connection.
+ */
if (wpa_s->last_scan_res_used > 0) {
struct os_reltime now;
}
wnm_set_scan_freqs(wpa_s);
+ if (wpa_s->wnm_num_neighbor_report == 1) {
+ os_memcpy(wpa_s->next_scan_bssid,
+ wpa_s->wnm_neighbor_report_elements[0].bssid,
+ ETH_ALEN);
+ wpa_printf(MSG_DEBUG,
+ "WNM: Scan only for a specific BSSID since there is only a single candidate "
+ MACSTR, MAC2STR(wpa_s->next_scan_bssid));
+ }
wpa_supplicant_req_scan(wpa_s, 0, 0);
} else if (reply) {
enum bss_trans_mgmt_status_code status;
int wnm_send_bss_transition_mgmt_query(struct wpa_supplicant *wpa_s,
- u8 query_reason)
+ u8 query_reason, int cand_list)
{
- u8 buf[1000], *pos;
+ u8 buf[2000], *pos;
struct ieee80211_mgmt *mgmt;
size_t len;
int ret;
wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Query to "
- MACSTR " query_reason=%u",
- MAC2STR(wpa_s->bssid), query_reason);
+ MACSTR " query_reason=%u%s",
+ MAC2STR(wpa_s->bssid), query_reason,
+ cand_list ? " candidate list" : "");
mgmt = (struct ieee80211_mgmt *) buf;
os_memset(&buf, 0, sizeof(buf));
mgmt->u.action.u.bss_tm_query.query_reason = query_reason;
pos = mgmt->u.action.u.bss_tm_query.variable;
+ if (cand_list)
+ pos += wnm_add_cand_list(wpa_s, pos, buf + sizeof(buf) - pos);
+
len = pos - (u8 *) &mgmt->u.action.category;
ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
pos = data;
end = data + len;
- while (pos + 1 < end) {
+ while (end - pos > 1) {
ie = *pos++;
ie_len = *pos++;
wpa_printf(MSG_DEBUG, "WNM: WFA subelement %u len %u",
url = NULL;
osu_method = 1;
} else {
- if (pos + url_len + 1 > ie_end) {
+ if (url_len + 1 > ie_end - pos) {
wpa_printf(MSG_DEBUG, "WNM: Not enough room for Server URL (len=%u) and Server Method (left %d)",
url_len,
(int) (ie_end - pos));
"Imminent - Reason Code %u "
"Re-Auth Delay %u URL Length %u",
code, reauth_delay, url_len);
- if (pos + url_len > ie_end)
+ if (url_len > ie_end - pos)
break;
url = os_malloc(url_len + 1);
if (url == NULL)
const struct ieee80211_mgmt *mgmt, size_t len);
int wnm_send_bss_transition_mgmt_query(struct wpa_supplicant *wpa_s,
- u8 query_reason);
+ u8 query_reason, int cand_list);
void wnm_deallocate_memory(struct wpa_supplicant *wpa_s);
/*
* WPA Supplicant - command line interface for wpa_supplicant daemon
- * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
#include <dirent.h>
#endif /* CONFIG_CTRL_IFACE_UNIX */
+#include "common/cli.h"
#include "common/wpa_ctrl.h"
#include "utils/common.h"
#include "utils/eloop.h"
static const char *const wpa_cli_version =
"wpa_cli v" VERSION_STR "\n"
-"Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> and contributors";
-
-
-static const char *const wpa_cli_license =
-"This software may be distributed under the terms of the BSD license.\n"
-"See README for more details.\n";
-
-static const char *const wpa_cli_full_license =
-"This software may be distributed under the terms of the BSD license.\n"
-"\n"
-"Redistribution and use in source and binary forms, with or without\n"
-"modification, are permitted provided that the following conditions are\n"
-"met:\n"
-"\n"
-"1. Redistributions of source code must retain the above copyright\n"
-" notice, this list of conditions and the following disclaimer.\n"
-"\n"
-"2. Redistributions in binary form must reproduce the above copyright\n"
-" notice, this list of conditions and the following disclaimer in the\n"
-" documentation and/or other materials provided with the distribution.\n"
-"\n"
-"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
-" names of its contributors may be used to endorse or promote products\n"
-" derived from this software without specific prior written permission.\n"
-"\n"
-"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
-"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
-"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
-"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
-"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
-"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
-"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
-"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
-"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
-"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
-"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
-"\n";
+"Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi> and contributors";
+
+#define VENDOR_ELEM_FRAME_ID \
+ " 0: Probe Req (P2P), 1: Probe Resp (P2P) , 2: Probe Resp (GO), " \
+ "3: Beacon (GO), 4: PD Req, 5: PD Resp, 6: GO Neg Req, " \
+ "7: GO Neg Resp, 8: GO Neg Conf, 9: Inv Req, 10: Inv Resp, " \
+ "11: Assoc Req (P2P), 12: Assoc Resp (P2P)"
static struct wpa_ctrl *ctrl_conn;
static struct wpa_ctrl *mon_conn;
static int interactive = 0;
static char *ifname_prefix = NULL;
-struct cli_txt_entry {
- struct dl_list list;
- char *txt;
-};
-
static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
}
-static void cli_txt_list_free(struct cli_txt_entry *e)
-{
- dl_list_del(&e->list);
- os_free(e->txt);
- os_free(e);
-}
-
-
-static void cli_txt_list_flush(struct dl_list *list)
-{
- struct cli_txt_entry *e;
- while ((e = dl_list_first(list, struct cli_txt_entry, list)))
- cli_txt_list_free(e);
-}
-
-
-static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
- const char *txt)
-{
- struct cli_txt_entry *e;
- dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
- if (os_strcmp(e->txt, txt) == 0)
- return e;
- }
- return NULL;
-}
-
-
-static void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
-{
- struct cli_txt_entry *e;
- e = cli_txt_list_get(txt_list, txt);
- if (e)
- cli_txt_list_free(e);
-}
-
-
-static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
-{
- u8 addr[ETH_ALEN];
- char buf[18];
- if (hwaddr_aton(txt, addr) < 0)
- return;
- os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
- cli_txt_list_del(txt_list, buf);
-}
-
-
-#ifdef CONFIG_P2P
-static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt,
- int separator)
-{
- const char *end;
- char *buf;
- end = os_strchr(txt, separator);
- if (end == NULL)
- end = txt + os_strlen(txt);
- buf = dup_binstr(txt, end - txt);
- if (buf == NULL)
- return;
- cli_txt_list_del(txt_list, buf);
- os_free(buf);
-}
-#endif /* CONFIG_P2P */
-
-
-static int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
-{
- struct cli_txt_entry *e;
- e = cli_txt_list_get(txt_list, txt);
- if (e)
- return 0;
- e = os_zalloc(sizeof(*e));
- if (e == NULL)
- return -1;
- e->txt = os_strdup(txt);
- if (e->txt == NULL) {
- os_free(e);
- return -1;
- }
- dl_list_add(txt_list, &e->list);
- return 0;
-}
-
-
-#ifdef CONFIG_P2P
-static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
-{
- u8 addr[ETH_ALEN];
- char buf[18];
- if (hwaddr_aton(txt, addr) < 0)
- return -1;
- os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
- return cli_txt_list_add(txt_list, buf);
-}
-#endif /* CONFIG_P2P */
-
-
-static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt,
- int separator)
-{
- const char *end;
- char *buf;
- int ret;
- end = os_strchr(txt, separator);
- if (end == NULL)
- end = txt + os_strlen(txt);
- buf = dup_binstr(txt, end - txt);
- if (buf == NULL)
- return -1;
- ret = cli_txt_list_add(txt_list, buf);
- os_free(buf);
- return ret;
-}
-
-
-static char ** cli_txt_list_array(struct dl_list *txt_list)
-{
- unsigned int i, count = dl_list_len(txt_list);
- char **res;
- struct cli_txt_entry *e;
-
- res = os_calloc(count + 1, sizeof(char *));
- if (res == NULL)
- return NULL;
-
- i = 0;
- dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
- res[i] = os_strdup(e->txt);
- if (res[i] == NULL)
- break;
- i++;
- }
-
- return res;
-}
-
-
-static int get_cmd_arg_num(const char *str, int pos)
-{
- int arg = 0, i;
-
- for (i = 0; i <= pos; i++) {
- if (str[i] != ' ') {
- arg++;
- while (i <= pos && str[i] != ' ')
- i++;
- }
- }
-
- if (arg > 0)
- arg--;
- return arg;
-}
-
-
-static int str_starts(const char *src, const char *match)
-{
- return os_strncmp(src, match, os_strlen(match)) == 0;
-}
-
-
static int wpa_cli_show_event(const char *event)
{
const char *start;
}
-static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
- char *argv[])
-{
- int i, res;
- char *pos, *end;
-
- pos = buf;
- end = buf + buflen;
-
- res = os_snprintf(pos, end - pos, "%s", cmd);
- if (os_snprintf_error(end - pos, res))
- goto fail;
- pos += res;
-
- for (i = 0; i < argc; i++) {
- res = os_snprintf(pos, end - pos, " %s", argv[i]);
- if (os_snprintf_error(end - pos, res))
- goto fail;
- pos += res;
- }
-
- buf[buflen - 1] = '\0';
- return 0;
-
-fail:
- printf("Too long command\n");
- return -1;
-}
-
-
static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
int argc, char *argv[])
{
static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
- printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
+ printf("%s\n\n%s\n", wpa_cli_version, cli_full_license);
return 0;
}
"tdls_external_control", "osu_dir", "wowlan_triggers",
"p2p_search_delay", "mac_addr", "rand_addr_lifetime",
"preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
- "reassoc_same_bss_optim", "wps_priority"
+ "reassoc_same_bss_optim", "wps_priority",
+#ifdef CONFIG_TESTING_OPTIONS
+ "ignore_auth_resp",
+#endif /* CONFIG_TESTING_OPTIONS */
};
int i, num_fields = ARRAY_SIZE(fields);
}
+static int wpa_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "DRIVER_FLAGS");
+}
+
+
static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
"ssid", "scan_ssid", "bssid", "bssid_blacklist",
"bssid_whitelist", "psk", "proto", "key_mgmt",
"bg_scan_period", "pairwise", "group", "auth_alg", "scan_freq",
- "freq_list",
+ "freq_list", "max_oper_chwidth",
#ifdef IEEE8021X_EAPOL
"eap", "identity", "anonymous_identity", "password", "ca_cert",
"ca_path", "client_cert", "private_key", "private_key_passwd",
#ifdef CONFIG_HS20
"update_identifier",
#endif /* CONFIG_HS20 */
- "mac_addr"
+ "mac_addr", "pbss", "wps_disabled"
};
}
+static int wpa_cli_cmd_abort_scan(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "ABORT_SCAN");
+}
+
+
static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
}
+static char ** wpa_cli_complete_get_capability(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ const char *fields[] = {
+ "eap", "pairwise", "group", "group_mgmt", "key_mgmt",
+ "proto", "auth_alg", "modes", "channels", "freq",
+#ifdef CONFIG_TDLS
+ "tdls",
+#endif /* CONFIG_TDLS */
+#ifdef CONFIG_ERP
+ "erp",
+#endif /* CONFIG_ERP */
+#ifdef CONFIG_FIPS
+ "fips",
+#endif /* CONFIG_FIPS */
+#ifdef CONFIG_ACS
+ "acs",
+#endif /* CONFIG_ACS */
+ };
+ int i, num_fields = ARRAY_SIZE(fields);
+ char **res = NULL;
+
+ if (arg == 1) {
+ res = os_calloc(num_fields + 1, sizeof(char *));
+ if (res == NULL)
+ return NULL;
+ for (i = 0; i < num_fields; i++) {
+ res[i] = os_strdup(fields[i]);
+ if (res[i] == NULL)
+ return res;
+ }
+ }
+ if (arg == 2) {
+ res = os_calloc(1 + 1, sizeof(char *));
+ if (res == NULL)
+ return NULL;
+ res[0] = os_strdup("strict");
+ }
+ return res;
+}
+
+
static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
{
printf("Available interfaces:\n");
/*
* INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
- * <driver_param>TAB<bridge_name>[TAB<create>]
+ * <driver_param>TAB<bridge_name>[TAB<create>[TAB<type>]]
*/
res = os_snprintf(cmd, sizeof(cmd),
- "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s\t%s",
+ "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s\t%s\t%s",
argv[0],
argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
- argc > 5 ? argv[5] : "", argc > 6 ? argv[6] : "");
+ argc > 5 ? argv[5] : "", argc > 6 ? argv[6] : "",
+ argc > 7 ? argv[7] : "");
if (os_snprintf_error(sizeof(cmd), res))
return -1;
cmd[sizeof(cmd) - 1] = '\0';
printf("Not connected to hostapd - command dropped.\n");
return -1;
}
+ if (ifname_prefix) {
+ os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
+ ifname_prefix, cmd);
+ buf[sizeof(buf) - 1] = '\0';
+ cmd = buf;
+ }
len = sizeof(buf) - 1;
ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
wpa_cli_msg_cb);
return wpa_cli_cmd(ctrl, "MESH_GROUP_REMOVE", 1, argc, argv);
}
+
+static int wpa_cli_cmd_mesh_peer_remove(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "MESH_PEER_REMOVE", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_mesh_peer_add(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "MESH_PEER_ADD", 1, argc, argv);
+}
+
#endif /* CONFIG_MESH */
}
+static int wpa_cli_cmd_p2p_group_member(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "P2P_GROUP_MEMBER", 1, argc, argv);
+}
+
+
static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
}
+
+static int wpa_cli_cmd_vendor_elem_add(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "VENDOR_ELEM_ADD", 2, argc, argv);
+}
+
+
+static int wpa_cli_cmd_vendor_elem_get(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "VENDOR_ELEM_GET", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_vendor_elem_remove(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "VENDOR_ELEM_REMOVE", 2, argc, argv);
+}
+
#endif /* CONFIG_P2P */
#ifdef CONFIG_WIFI_DISPLAY
}
+static int wpa_cli_cmd_signal_monitor(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "SIGNAL_MONITOR", 0, argc, argv);
+}
+
+
static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
}
+static int wpa_cli_cmd_p2p_lo_start(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "P2P_LO_START", 4, argc, argv);
+}
+
+
+static int wpa_cli_cmd_p2p_lo_stop(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "P2P_LO_STOP", 0, argc, argv);
+}
+
+
enum wpa_cli_cmd_flags {
cli_cmd_flag_none = 0x00,
cli_cmd_flag_sensitive = 0x01
{ "get", wpa_cli_cmd_get, wpa_cli_complete_get,
cli_cmd_flag_none,
"<name> = get information" },
+ { "driver_flags", wpa_cli_cmd_driver_flags, NULL,
+ cli_cmd_flag_none,
+ "= list driver flags" },
{ "logon", wpa_cli_cmd_logon, NULL,
cli_cmd_flag_none,
"= IEEE 802.1X EAPOL state machine logon" },
{ "scan_results", wpa_cli_cmd_scan_results, NULL,
cli_cmd_flag_none,
"= get latest scan results" },
+ { "abort_scan", wpa_cli_cmd_abort_scan, NULL,
+ cli_cmd_flag_none,
+ "= request ongoing scan to be aborted" },
{ "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
cli_cmd_flag_none,
"<<idx> | <bssid>> = get detailed scan result info" },
- { "get_capability", wpa_cli_cmd_get_capability, NULL,
- cli_cmd_flag_none,
+ { "get_capability", wpa_cli_cmd_get_capability,
+ wpa_cli_complete_get_capability, cli_cmd_flag_none,
"<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
"= get capabilities" },
{ "reconfigure", wpa_cli_cmd_reconfigure, NULL,
{ "interface_add", wpa_cli_cmd_interface_add, NULL,
cli_cmd_flag_none,
"<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
- " <bridge_name> = adds new interface, all parameters but <ifname>\n"
- " are optional" },
+ " <bridge_name> <create> <type> = adds new interface, all "
+ "parameters but\n"
+ " <ifname> are optional. Supported types are station ('sta') and "
+ "AP ('ap')" },
{ "interface_remove", wpa_cli_cmd_interface_remove, NULL,
cli_cmd_flag_none,
"<ifname> = removes the interface" },
{ "mesh_group_remove", wpa_cli_cmd_mesh_group_remove, NULL,
cli_cmd_flag_none,
"<ifname> = Remove mesh group interface" },
+ { "mesh_peer_remove", wpa_cli_cmd_mesh_peer_remove, NULL,
+ cli_cmd_flag_none,
+ "<addr> = Remove a mesh peer" },
+ { "mesh_peer_add", wpa_cli_cmd_mesh_peer_add, NULL,
+ cli_cmd_flag_none,
+ "<addr> [duration=<seconds>] = Add a mesh peer" },
#endif /* CONFIG_MESH */
#ifdef CONFIG_P2P
{ "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
"<ifname> = remove P2P group interface (terminate group if GO)" },
{ "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
"[ht40] = add a new P2P group (local end as GO)" },
+ { "p2p_group_member", wpa_cli_cmd_p2p_group_member, NULL,
+ cli_cmd_flag_none,
+ "<dev_addr> = Get peer interface address on local GO using peer Device Address" },
{ "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
"<addr> <method> = request provisioning discovery" },
{ "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
"<address|iface=address> = remove a peer from all groups" },
+ { "vendor_elem_add", wpa_cli_cmd_vendor_elem_add, NULL,
+ cli_cmd_flag_none,
+ "<frame id> <hexdump of elem(s)> = add vendor specific IEs to frame(s)\n"
+ VENDOR_ELEM_FRAME_ID },
+ { "vendor_elem_get", wpa_cli_cmd_vendor_elem_get, NULL,
+ cli_cmd_flag_none,
+ "<frame id> = get vendor specific IE(s) to frame(s)\n"
+ VENDOR_ELEM_FRAME_ID },
+ { "vendor_elem_remove", wpa_cli_cmd_vendor_elem_remove, NULL,
+ cli_cmd_flag_none,
+ "<frame id> <hexdump of elem(s)> = remove vendor specific IE(s) in frame(s)\n"
+ VENDOR_ELEM_FRAME_ID },
#endif /* CONFIG_P2P */
#ifdef CONFIG_WIFI_DISPLAY
{ "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
{ "signal_poll", wpa_cli_cmd_signal_poll, NULL,
cli_cmd_flag_none,
"= get signal parameters" },
+ { "signal_monitor", wpa_cli_cmd_signal_monitor, NULL,
+ cli_cmd_flag_none,
+ "= set signal monitor parameters" },
{ "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
cli_cmd_flag_none,
"= get TX/RX packet counters" },
{ "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
"<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
{ "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
- "<query reason> = Send BSS Transition Management Query" },
+ "<query reason> [list] = Send BSS Transition Management Query" },
#endif /* CONFIG_WNM */
{ "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
"<params..> = Sent unprocessed command" },
},
{ "neighbor_rep_request",
wpa_cli_cmd_neighbor_rep_request, NULL, cli_cmd_flag_none,
- "[ssid=<SSID>] = Trigger request to AP for neighboring AP report "
- "(with optional given SSID, default: current SSID)"
+ "[ssid=<SSID>] [lci] [civic] = Trigger request to AP for neighboring AP report (with optional given SSID in hex or enclosed in double quotes, default: current SSID; with optional LCI and location civic request)"
},
{ "erp_flush", wpa_cli_cmd_erp_flush, NULL, cli_cmd_flag_none,
"= flush ERP keys" },
{ "get_pref_freq_list", wpa_cli_cmd_get_pref_freq_list, NULL,
cli_cmd_flag_none,
"<interface type> = retrieve preferred freq list for the specified interface type" },
+ { "p2p_lo_start", wpa_cli_cmd_p2p_lo_start, NULL,
+ cli_cmd_flag_none,
+ "<freq> <period> <interval> <count> = start P2P listen offload" },
+ { "p2p_lo_stop", wpa_cli_cmd_p2p_lo_stop, NULL,
+ cli_cmd_flag_none,
+ "= stop P2P listen offload" },
{ NULL, NULL, NULL, cli_cmd_flag_none, NULL }
};
}
-static int str_match(const char *a, const char *b)
-{
- return os_strncmp(a, b, os_strlen(b)) == 0;
-}
-
-
static int wpa_cli_exec(const char *program, const char *arg1,
const char *arg2)
{
size_t len;
int res;
+ /* If no interface is specified, set the global */
+ if (!arg1)
+ arg1 = "global";
+
len = os_strlen(arg1) + os_strlen(arg2) + 2;
arg = os_malloc(len);
if (arg == NULL)
pos = prev;
}
- if (str_match(pos, WPA_EVENT_CONNECTED)) {
+ if (str_starts(pos, WPA_EVENT_CONNECTED)) {
int new_id = -1;
os_unsetenv("WPA_ID");
os_unsetenv("WPA_ID_STR");
wpa_cli_last_id = new_id;
wpa_cli_exec(action_file, ifname, "CONNECTED");
}
- } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
+ } else if (str_starts(pos, WPA_EVENT_DISCONNECTED)) {
if (wpa_cli_connected) {
wpa_cli_connected = 0;
wpa_cli_exec(action_file, ifname, "DISCONNECTED");
}
- } else if (str_match(pos, MESH_GROUP_STARTED)) {
+ } else if (str_starts(pos, AP_EVENT_ENABLED)) {
+ wpa_cli_exec(action_file, ctrl_ifname, pos);
+ } else if (str_starts(pos, AP_EVENT_DISABLED)) {
+ wpa_cli_exec(action_file, ctrl_ifname, pos);
+ } else if (str_starts(pos, MESH_GROUP_STARTED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
- } else if (str_match(pos, MESH_GROUP_REMOVED)) {
+ } else if (str_starts(pos, MESH_GROUP_REMOVED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
- } else if (str_match(pos, MESH_PEER_CONNECTED)) {
+ } else if (str_starts(pos, MESH_PEER_CONNECTED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
- } else if (str_match(pos, MESH_PEER_DISCONNECTED)) {
+ } else if (str_starts(pos, MESH_PEER_DISCONNECTED)) {
wpa_cli_exec(action_file, ctrl_ifname, pos);
- } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
+ } else if (str_starts(pos, P2P_EVENT_GROUP_STARTED)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
+ } else if (str_starts(pos, P2P_EVENT_GROUP_REMOVED)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
+ } else if (str_starts(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
+ } else if (str_starts(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
+ } else if (str_starts(pos, P2P_EVENT_GO_NEG_FAILURE)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
+ } else if (str_starts(pos, WPS_EVENT_SUCCESS)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, WPS_EVENT_FAIL)) {
+ } else if (str_starts(pos, WPS_EVENT_FAIL)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, AP_STA_CONNECTED)) {
+ } else if (str_starts(pos, AP_STA_CONNECTED)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, AP_STA_DISCONNECTED)) {
+ } else if (str_starts(pos, AP_STA_DISCONNECTED)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
+ } else if (str_starts(pos, ESS_DISASSOC_IMMINENT)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
+ } else if (str_starts(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
+ } else if (str_starts(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
wpa_cli_exec(action_file, ifname, pos);
- } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
+ } else if (str_starts(pos, WPA_EVENT_TERMINATING)) {
printf("wpa_supplicant is terminating - stop monitoring\n");
wpa_cli_quit = 1;
}
pos = msg;
}
- if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
+ if (str_starts(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
edit_clear_line();
printf("\rConnection to wpa_supplicant lost - trying to "
"reconnect\n");
}
}
-#define max_args 10
-
-static int tokenize_cmd(char *cmd, char *argv[])
-{
- char *pos;
- int argc = 0;
-
- pos = cmd;
- for (;;) {
- while (*pos == ' ')
- pos++;
- if (*pos == '\0')
- break;
- argv[argc] = pos;
- argc++;
- if (argc == max_args)
- break;
- if (*pos == '"') {
- char *pos2 = os_strrchr(pos, '"');
- if (pos2)
- pos = pos2 + 1;
- }
- while (*pos != '\0' && *pos != ' ')
- pos++;
- if (*pos == ' ')
- *pos++ = '\0';
- }
-
- return argc;
-}
-
static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
{
if (ctrl_ifname == NULL)
ctrl_ifname = wpa_cli_get_default_ifname();
- if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
+ if (wpa_cli_open_connection(ctrl_ifname, 1)) {
if (!warning_displayed) {
printf("Could not connect to wpa_supplicant: "
"%s - re-trying\n",
interactive = (argc == optind) && (action_file == NULL);
if (interactive)
- printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
+ printf("%s\n\n%s\n\n", wpa_cli_version, cli_license);
if (eloop_init())
return -1;
}
}
- if (daemonize && os_daemonize(pid_file))
+ if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
return -1;
if (action_file)
char *sock_name;
int fd;
+ void *ctx;
+
const struct wpa_driver_ops *driver;
void *drv_priv;
void *drv_global_priv;
struct sockaddr_un l2_addr;
};
+struct wpa_priv_global {
+ struct wpa_priv_interface *interfaces;
+};
+
static void wpa_priv_cmd_register(struct wpa_priv_interface *iface,
struct sockaddr_un *from)
if (iface->driver->init2) {
if (iface->driver->global_init) {
- iface->drv_global_priv = iface->driver->global_init();
+ iface->drv_global_priv =
+ iface->driver->global_init(iface->ctx);
if (!iface->drv_global_priv) {
wpa_printf(MSG_INFO,
"Failed to initialize driver global context");
static struct wpa_priv_interface *
-wpa_priv_interface_init(const char *dir, const char *params)
+wpa_priv_interface_init(void *ctx, const char *dir, const char *params)
{
struct wpa_priv_interface *iface;
char *pos;
if (iface == NULL)
return NULL;
iface->fd = -1;
+ iface->ctx = ctx;
len = pos - params;
iface->driver_name = dup_binstr(params, len);
}
+void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
+ union wpa_event_data *data)
+{
+ struct wpa_priv_global *global = ctx;
+ struct wpa_priv_interface *iface;
+
+ if (event != EVENT_INTERFACE_STATUS)
+ return;
+
+ for (iface = global->interfaces; iface; iface = iface->next) {
+ if (os_strcmp(iface->ifname, data->interface_status.ifname) ==
+ 0)
+ break;
+ }
+ if (iface && iface->driver->get_ifindex) {
+ unsigned int ifindex;
+
+ ifindex = iface->driver->get_ifindex(iface->drv_priv);
+ if (ifindex != data->interface_status.ifindex) {
+ wpa_printf(MSG_DEBUG,
+ "%s: interface status ifindex %d mismatch (%d)",
+ iface->ifname, ifindex,
+ data->interface_status.ifindex);
+ return;
+ }
+ }
+ if (iface)
+ wpa_supplicant_event(iface, event, data);
+}
+
+
void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
const u8 *buf, size_t len)
{
static void usage(void)
{
printf("wpa_priv v" VERSION_STR "\n"
- "Copyright (c) 2007-2009, Jouni Malinen <j@w1.fi> and "
+ "Copyright (c) 2007-2016, Jouni Malinen <j@w1.fi> and "
"contributors\n"
"\n"
"usage:\n"
char *pid_file = NULL;
int daemonize = 0;
char *ctrl_dir = "/var/run/wpa_priv";
- struct wpa_priv_interface *interfaces = NULL, *iface;
+ struct wpa_priv_global global;
+ struct wpa_priv_interface *iface;
if (os_program_init())
return -1;
wpa_priv_fd_workaround();
+ os_memset(&global, 0, sizeof(global));
+ global.interfaces = NULL;
+
for (;;) {
c = getopt(argc, argv, "Bc:dP:");
if (c < 0)
for (i = optind; i < argc; i++) {
wpa_printf(MSG_DEBUG, "Adding driver:interface %s", argv[i]);
- iface = wpa_priv_interface_init(ctrl_dir, argv[i]);
+ iface = wpa_priv_interface_init(&global, ctrl_dir, argv[i]);
if (iface == NULL)
goto out;
- iface->next = interfaces;
- interfaces = iface;
+ iface->next = global.interfaces;
+ global.interfaces = iface;
}
- if (daemonize && os_daemonize(pid_file))
+ if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
goto out;
eloop_register_signal_terminate(wpa_priv_terminate, NULL);
ret = 0;
out:
- iface = interfaces;
+ iface = global.interfaces;
while (iface) {
struct wpa_priv_interface *prev = iface;
iface = iface->next;
/*
* WPA Supplicant
- * Copyright (c) 2003-2015, 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.
*/
#include "includes.h"
+#ifdef CONFIG_MATCH_IFACE
+#include <net/if.h>
+#include <fnmatch.h>
+#endif /* CONFIG_MATCH_IFACE */
#include "common.h"
#include "crypto/random.h"
const char *const wpa_supplicant_version =
"wpa_supplicant v" VERSION_STR "\n"
-"Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi> and contributors";
const char *const wpa_supplicant_license =
"This software may be distributed under the terms of the BSD license.\n"
{
struct wpa_supplicant *wpa_s = eloop_ctx;
const u8 *bssid = wpa_s->bssid;
- if (is_zero_ether_addr(bssid))
+ if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
+ (wpa_s->wpa_state == WPA_AUTHENTICATING ||
+ wpa_s->wpa_state == WPA_ASSOCIATING))
bssid = wpa_s->pending_bssid;
wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
MAC2STR(bssid));
}
+static void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_bss_tmp_disallowed *bss, *prev;
+
+ dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed,
+ struct wpa_bss_tmp_disallowed, list) {
+ dl_list_del(&bss->list);
+ os_free(bss);
+ }
+}
+
+
static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
{
int i;
wpa_s->last_scan_res = NULL;
#ifdef CONFIG_HS20
+ if (wpa_s->drv_priv)
+ wpa_drv_configure_frame_filters(wpa_s, 0);
hs20_deinit(wpa_s);
#endif /* CONFIG_HS20 */
}
wmm_ac_notify_disassoc(wpa_s);
+
+ wpa_s->sched_scan_plans_num = 0;
+ os_free(wpa_s->sched_scan_plans);
+ wpa_s->sched_scan_plans = NULL;
+
+#ifdef CONFIG_MBO
+ wpa_s->non_pref_chan_num = 0;
+ os_free(wpa_s->non_pref_chan);
+ wpa_s->non_pref_chan = NULL;
+#endif /* CONFIG_MBO */
+
+ free_bss_tmp_disallowed(wpa_s);
+
+ wpabuf_free(wpa_s->lci);
+ wpa_s->lci = NULL;
}
wpa_supplicant_terminate_proc(global);
}
}
+
+ if (wpa_debug_reopen_file() < 0) {
+ /* Ignore errors since we cannot really do much to fix this */
+ wpa_printf(MSG_DEBUG, "Could not reopen debug log file");
+ }
}
return -1;
}
+#ifdef CONFIG_NO_WPA
+ wpa_s->group_cipher = WPA_CIPHER_NONE;
+ wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
+#else /* CONFIG_NO_WPA */
sel = ie.group_cipher & ssid->group_cipher;
wpa_s->group_cipher = wpa_pick_group_cipher(sel);
if (wpa_s->group_cipher < 0) {
}
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
wpa_cipher_txt(wpa_s->pairwise_cipher));
+#endif /* CONFIG_NO_WPA */
sel = ie.key_mgmt & ssid->key_mgmt;
#ifdef CONFIG_SAE
int psk_set = 0;
if (ssid->psk_set) {
- wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL);
+ wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL,
+ NULL);
psk_set = 1;
}
#ifndef CONFIG_NO_PBKDF2
4096, psk, PMK_LEN);
wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
psk, PMK_LEN);
- wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
+ wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL);
psk_set = 1;
os_memset(psk, 0, sizeof(psk));
}
wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
"external passphrase)",
psk, PMK_LEN);
- wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
+ wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
+ NULL);
psk_set = 1;
os_memset(psk, 0, sizeof(psk));
} else
ext_password_free(pw);
return -1;
}
- wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
+ wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL,
+ NULL);
psk_set = 1;
os_memset(psk, 0, sizeof(psk));
} else {
if (wpa_s->conf->hs20)
*pos |= 0x40; /* Bit 46 - WNM-Notification */
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_MBO
+ *pos |= 0x40; /* Bit 46 - WNM-Notification */
+#endif /* CONFIG_MBO */
break;
case 6: /* Bits 48-55 */
break;
+ case 7: /* Bits 56-63 */
+ break;
+ case 8: /* Bits 64-71 */
+ if (wpa_s->conf->ftm_responder)
+ *pos |= 0x40; /* Bit 70 - FTM responder */
+ if (wpa_s->conf->ftm_initiator)
+ *pos |= 0x80; /* Bit 71 - FTM initiator */
+ break;
}
}
u8 *pos = buf;
u8 len = 6, i;
+ if (len < 9 &&
+ (wpa_s->conf->ftm_initiator || wpa_s->conf->ftm_responder))
+ len = 9;
if (len < wpa_s->extended_capa_len)
len = wpa_s->extended_capa_len;
if (buflen < (size_t) len + 2) {
struct wpa_connect_work *cwork;
int rand_style;
+ wpa_s->own_disconnect_req = 0;
+
+ /*
+ * If we are starting a new connection, any previously pending EAPOL
+ * RX cannot be valid anymore.
+ */
+ wpabuf_free(wpa_s->pending_eapol_rx);
+ wpa_s->pending_eapol_rx = NULL;
+
if (ssid->mac_addr == -1)
rand_style = wpa_s->conf->mac_addr;
else
wmm_ac_clear_saved_tspecs(wpa_s);
wpa_s->reassoc_same_bss = 0;
+ wpa_s->reassoc_same_ess = 0;
if (wpa_s->last_ssid == ssid) {
wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
+ wpa_s->reassoc_same_ess = 1;
if (wpa_s->current_bss && wpa_s->current_bss == bss) {
wmm_ac_save_tspecs(wpa_s);
wpa_s->reassoc_same_bss = 1;
return;
}
wpa_s->current_bss = bss;
- wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_GROUP_STARTED
- "ssid=\"%s\" id=%d",
- wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
- ssid->id);
+ wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
+ wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
+ ssid->id);
#else /* CONFIG_MESH */
wpa_msg(wpa_s, MSG_ERROR,
"mesh mode support not included in the build");
return;
}
+ wpas_abort_ongoing_scan(wpa_s);
+
cwork = os_zalloc(sizeof(*cwork));
if (cwork == NULL)
return;
}
+static int drv_supports_vht(struct wpa_supplicant *wpa_s,
+ const struct wpa_ssid *ssid)
+{
+ enum hostapd_hw_mode hw_mode;
+ struct hostapd_hw_modes *mode = NULL;
+ u8 channel;
+ int i;
+
+#ifdef CONFIG_HT_OVERRIDES
+ if (ssid->disable_ht)
+ return 0;
+#endif /* CONFIG_HT_OVERRIDES */
+
+ hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
+ if (hw_mode == NUM_HOSTAPD_MODES)
+ return 0;
+ for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
+ if (wpa_s->hw.modes[i].mode == hw_mode) {
+ mode = &wpa_s->hw.modes[i];
+ break;
+ }
+ }
+
+ if (!mode)
+ return 0;
+
+ return mode->vht_capab != 0;
+}
+
+
void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
const struct wpa_ssid *ssid,
struct hostapd_freq_params *freq)
struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
u8 channel;
int i, chan_idx, ht40 = -1, res, obss_scan = 1;
- unsigned int j;
+ unsigned int j, k;
struct hostapd_freq_params vht_freq;
+ int chwidth, seg0, seg1;
+ u32 vht_caps = 0;
freq->freq = ssid->frequency;
if (!mode)
return;
+#ifdef CONFIG_HT_OVERRIDES
+ if (ssid->disable_ht) {
+ freq->ht_enabled = 0;
+ return;
+ }
+#endif /* CONFIG_HT_OVERRIDES */
+
freq->ht_enabled = ht_supported(mode);
if (!freq->ht_enabled)
return;
if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
return;
+#ifdef CONFIG_HT_OVERRIDES
+ if (ssid->disable_ht40)
+ return;
+#endif /* CONFIG_HT_OVERRIDES */
+
/* Check/setup HT40+/HT40- */
for (j = 0; j < ARRAY_SIZE(ht40plus); j++) {
if (ht40plus[j] == channel) {
freq->channel = pri_chan->chan;
- switch (ht40) {
- case -1:
+ if (ht40 == -1) {
if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
return;
- freq->sec_channel_offset = -1;
- break;
- case 1:
+ } else {
if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS))
return;
- freq->sec_channel_offset = 1;
- break;
- default:
- break;
}
+ freq->sec_channel_offset = ht40;
- if (freq->sec_channel_offset && obss_scan) {
+ if (obss_scan) {
struct wpa_scan_results *scan_res;
scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
"IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
freq->channel, freq->sec_channel_offset);
- /* Not sure if mesh is ready for VHT */
- if (ssid->mode != WPAS_MODE_IBSS)
+ if (!drv_supports_vht(wpa_s, ssid))
return;
/* For IBSS check VHT_IBSS flag */
- if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
+ if (ssid->mode == WPAS_MODE_IBSS &&
+ !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
return;
vht_freq = *freq;
return;
}
+ chwidth = VHT_CHANWIDTH_80MHZ;
+ seg0 = vht80[j] + 6;
+ seg1 = 0;
+
+ if (ssid->max_oper_chwidth == VHT_CHANWIDTH_80P80MHZ) {
+ /* setup center_freq2, bandwidth */
+ for (k = 0; k < ARRAY_SIZE(vht80); k++) {
+ /* Only accept 80 MHz segments separated by a gap */
+ if (j == k || abs(vht80[j] - vht80[k]) == 16)
+ continue;
+ for (i = vht80[k]; i < vht80[k] + 16; i += 4) {
+ struct hostapd_channel_data *chan;
+
+ chan = hw_get_channel_chan(mode, i, NULL);
+ if (!chan)
+ continue;
+
+ if (chan->flag & (HOSTAPD_CHAN_DISABLED |
+ HOSTAPD_CHAN_NO_IR |
+ HOSTAPD_CHAN_RADAR))
+ continue;
+
+ /* Found a suitable second segment for 80+80 */
+ chwidth = VHT_CHANWIDTH_80P80MHZ;
+ vht_caps |=
+ VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
+ seg1 = vht80[k] + 6;
+ }
+
+ if (chwidth == VHT_CHANWIDTH_80P80MHZ)
+ break;
+ }
+ } else if (ssid->max_oper_chwidth == VHT_CHANWIDTH_160MHZ) {
+ if (freq->freq == 5180) {
+ chwidth = VHT_CHANWIDTH_160MHZ;
+ vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
+ seg0 = 50;
+ } else if (freq->freq == 5520) {
+ chwidth = VHT_CHANWIDTH_160MHZ;
+ vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
+ seg0 = 114;
+ }
+ }
+
if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
freq->channel, freq->ht_enabled,
vht_freq.vht_enabled,
freq->sec_channel_offset,
- VHT_CHANWIDTH_80MHZ,
- vht80[j] + 6, 0, 0) != 0)
+ chwidth, seg0, seg1, vht_caps) != 0)
return;
*freq = vht_freq;
int wep_keys_set = 0;
int assoc_failed = 0;
struct wpa_ssid *old_ssid;
+ u8 prev_bssid[ETH_ALEN];
#ifdef CONFIG_HT_OVERRIDES
struct ieee80211_ht_capabilities htcaps;
struct ieee80211_ht_capabilities htcaps_mask;
struct ieee80211_vht_capabilities vhtcaps;
struct ieee80211_vht_capabilities vhtcaps_mask;
#endif /* CONFIG_VHT_OVERRIDES */
+#ifdef CONFIG_MBO
+ const u8 *mbo = NULL;
+#endif /* CONFIG_MBO */
if (deinit) {
if (work->started) {
return;
}
+ os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN);
os_memset(¶ms, 0, sizeof(params));
wpa_s->reassociate = 0;
wpa_s->eap_expected_failure = 0;
} else {
wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
- os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
+ if (bss)
+ os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
+ else
+ os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
}
if (!wpa_s->pno)
wpa_supplicant_cancel_sched_scan(wpa_s);
os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
#endif /* CONFIG_P2P */
-#ifdef CONFIG_HS20
- if (is_hs20_network(wpa_s, ssid, bss)) {
- struct wpabuf *hs20;
- hs20 = wpabuf_alloc(20);
- if (hs20) {
- int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
- size_t len;
-
- wpas_hs20_add_indication(hs20, pps_mo_id);
- len = sizeof(wpa_ie) - wpa_ie_len;
- if (wpabuf_len(hs20) <= len) {
- os_memcpy(wpa_ie + wpa_ie_len,
- wpabuf_head(hs20), wpabuf_len(hs20));
- wpa_ie_len += wpabuf_len(hs20);
- }
- wpabuf_free(hs20);
+#ifdef CONFIG_MBO
+ if (bss) {
+ mbo = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
+ if (mbo) {
+ int len;
+
+ len = wpas_mbo_supp_op_class_ie(wpa_s, bss->freq,
+ wpa_ie + wpa_ie_len,
+ sizeof(wpa_ie) -
+ wpa_ie_len);
+ if (len > 0)
+ wpa_ie_len += len;
}
}
-#endif /* CONFIG_HS20 */
+#endif /* CONFIG_MBO */
/*
* Workaround: Add Extended Capabilities element only if the AP
* element in all cases, it is justifiable to skip it to avoid
* interoperability issues.
*/
+ if (ssid->p2p_group)
+ wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
+ else
+ wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
+
if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
u8 ext_capab[18];
int ext_capab_len;
}
}
+#ifdef CONFIG_HS20
+ if (is_hs20_network(wpa_s, ssid, bss)) {
+ struct wpabuf *hs20;
+
+ hs20 = wpabuf_alloc(20);
+ if (hs20) {
+ int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
+ size_t len;
+
+ wpas_hs20_add_indication(hs20, pps_mo_id);
+ len = sizeof(wpa_ie) - wpa_ie_len;
+ if (wpabuf_len(hs20) <= len) {
+ os_memcpy(wpa_ie + wpa_ie_len,
+ wpabuf_head(hs20), wpabuf_len(hs20));
+ wpa_ie_len += wpabuf_len(hs20);
+ }
+ wpabuf_free(hs20);
+
+ hs20_configure_frame_filters(wpa_s);
+ }
+ }
+#endif /* CONFIG_HS20 */
+
if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
size_t len;
}
#endif /* CONFIG_FST */
+#ifdef CONFIG_MBO
+ if (mbo) {
+ int len;
+
+ len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len,
+ sizeof(wpa_ie) - wpa_ie_len);
+ if (len >= 0)
+ wpa_ie_len += len;
+ }
+#endif /* CONFIG_MBO */
+
wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
use_crypt = 1;
cipher_pairwise = wpa_s->pairwise_cipher;
}
params.bssid_hint = bss->bssid;
params.freq_hint = bss->freq;
+ params.pbss = bss_is_pbss(bss);
} else {
params.ssid = ssid->ssid;
params.ssid_len = ssid->ssid_len;
+ params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0;
}
if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
params.p2p = ssid->p2p_group;
- if (wpa_s->parent->set_sta_uapsd)
- params.uapsd = wpa_s->parent->sta_uapsd;
+ if (wpa_s->p2pdev->set_sta_uapsd)
+ params.uapsd = wpa_s->p2pdev->sta_uapsd;
else
params.uapsd = -1;
}
#endif /* CONFIG_P2P */
+ if (wpa_s->reassoc_same_ess && !is_zero_ether_addr(prev_bssid) &&
+ wpa_s->current_ssid)
+ params.prev_bssid = prev_bssid;
+
ret = wpa_drv_associate(wpa_s, ¶ms);
if (ret < 0) {
wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
}
old_ssid = wpa_s->current_ssid;
wpa_s->current_ssid = ssid;
- if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set)
+
+ if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
wpa_s->current_bss = bss;
+#ifdef CONFIG_HS20
+ hs20_configure_frame_filters(wpa_s);
+#endif /* CONFIG_HS20 */
+ }
+
wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
wpa_supplicant_initiate_eapol(wpa_s);
if (old_ssid != wpa_s->current_ssid)
MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
- if (!is_zero_ether_addr(wpa_s->bssid))
- addr = wpa_s->bssid;
- else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
- (wpa_s->wpa_state == WPA_AUTHENTICATING ||
- wpa_s->wpa_state == WPA_ASSOCIATING))
+ if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
+ (wpa_s->wpa_state == WPA_AUTHENTICATING ||
+ wpa_s->wpa_state == WPA_ASSOCIATING))
addr = wpa_s->pending_bssid;
+ else if (!is_zero_ether_addr(wpa_s->bssid))
+ addr = wpa_s->bssid;
else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
/*
* When using driver-based BSS selection, we may not know the
#ifdef CONFIG_MESH
if (wpa_s->ifmsh) {
- wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
- wpa_s->ifname);
+ wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s",
+ wpa_s->ifname);
wpa_supplicant_leave_mesh(wpa_s);
}
#endif /* CONFIG_MESH */
/**
+ * wpa_supplicant_add_network - Add a new network
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: The new network configuration or %NULL if operation failed
+ *
+ * This function performs the following operations:
+ * 1. Adds a new network.
+ * 2. Send network addition notification.
+ * 3. Marks the network disabled.
+ * 4. Set network default parameters.
+ */
+struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_ssid *ssid;
+
+ ssid = wpa_config_add_network(wpa_s->conf);
+ if (!ssid)
+ return NULL;
+ wpas_notify_network_added(wpa_s, ssid);
+ ssid->disabled = 1;
+ wpa_config_set_network_defaults(ssid);
+
+ return ssid;
+}
+
+
+/**
+ * wpa_supplicant_remove_network - Remove a configured network based on id
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * @id: Unique network id to search for
+ * Returns: 0 on success, or -1 if the network was not found, -2 if the network
+ * could not be removed
+ *
+ * This function performs the following operations:
+ * 1. Removes the network.
+ * 2. Send network removal notification.
+ * 3. Update internal state machines.
+ * 4. Stop any running sched scans.
+ */
+int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id)
+{
+ struct wpa_ssid *ssid;
+ int was_disabled;
+
+ ssid = wpa_config_get_network(wpa_s->conf, id);
+ if (!ssid)
+ return -1;
+ wpas_notify_network_removed(wpa_s, ssid);
+
+ if (wpa_s->last_ssid == ssid)
+ wpa_s->last_ssid = NULL;
+
+ if (ssid == wpa_s->current_ssid || !wpa_s->current_ssid) {
+#ifdef CONFIG_SME
+ wpa_s->sme.prev_bssid_set = 0;
+#endif /* CONFIG_SME */
+ /*
+ * Invalidate the EAP session cache if the current or
+ * previously used network is removed.
+ */
+ eapol_sm_invalidate_cached_session(wpa_s->eapol);
+ }
+
+ if (ssid == wpa_s->current_ssid) {
+ wpa_sm_set_config(wpa_s->wpa, NULL);
+ eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
+
+ if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
+ wpa_s->own_disconnect_req = 1;
+ wpa_supplicant_deauthenticate(wpa_s,
+ WLAN_REASON_DEAUTH_LEAVING);
+ }
+
+ was_disabled = ssid->disabled;
+
+ if (wpa_config_remove_network(wpa_s->conf, id) < 0)
+ return -2;
+
+ if (!was_disabled && wpa_s->sched_scanning) {
+ wpa_printf(MSG_DEBUG,
+ "Stop ongoing sched_scan to remove network from filters");
+ wpa_supplicant_cancel_sched_scan(wpa_s);
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+ }
+
+ return 0;
+}
+
+
+/**
* wpa_supplicant_enable_network - Mark a configured network as enabled
* @wpa_s: wpa_supplicant structure for a network interface
* @ssid: wpa_ssid structure for a configured network or %NULL
wpas_notify_network_enabled_changed(wpa_s, other_ssid);
}
- if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
+ if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid &&
+ wpa_s->wpa_state >= WPA_AUTHENTICATING) {
/* We are already associated with the selected network */
wpa_printf(MSG_DEBUG, "Already associated with the "
"selected network - do nothing");
if (wpa_s->connect_without_scan ||
wpa_supplicant_fast_associate(wpa_s) != 1) {
wpa_s->scan_req = NORMAL_SCAN_REQ;
+ wpas_scan_reset_sched_scan(wpa_s);
wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
}
struct wpa_global *global = wpa_s->global;
if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
- global->drv_priv[i] = wpa_drivers[i]->global_init();
+ global->drv_priv[i] = wpa_drivers[i]->global_init(global);
if (global->drv_priv[i] == NULL) {
wpa_printf(MSG_ERROR, "Failed to initialize driver "
"'%s'", wpa_drivers[i]->name);
wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
+#ifdef CONFIG_TESTING_OPTIONS
+ if (wpa_s->ignore_auth_resp) {
+ wpa_printf(MSG_INFO, "RX EAPOL - ignore_auth_resp active!");
+ return;
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+
#ifdef CONFIG_PEERKEY
if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
wpa_s->current_ssid->peerkey &&
wpa_s->scan_interval = 5;
wpa_s->new_connection = 1;
wpa_s->parent = parent ? parent : wpa_s;
+ wpa_s->p2pdev = wpa_s->parent;
wpa_s->sched_scanning = 0;
+ dl_list_init(&wpa_s->bss_tmp_disallowed);
+
return wpa_s;
}
if (!vhtcaps || !vhtcaps_mask)
return;
- vhtcaps->vht_capabilities_info = ssid->vht_capa;
- vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
+ vhtcaps->vht_capabilities_info = host_to_le32(ssid->vht_capa);
+ vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask);
#ifdef CONFIG_HT_OVERRIDES
/* if max ampdu is <= 3, we have to make the HT cap the same */
#define OVERRIDE_MCS(i) \
if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
- 3 << 2 * (i - 1); \
+ host_to_le16(3 << 2 * (i - 1)); \
vhtcaps->vht_supported_mcs_set.tx_map |= \
- ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
+ host_to_le16(ssid->vht_tx_mcs_nss_ ##i << \
+ 2 * (i - 1)); \
} \
if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
- 3 << 2 * (i - 1); \
+ host_to_le16(3 << 2 * (i - 1)); \
vhtcaps->vht_supported_mcs_set.rx_map |= \
- ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
+ host_to_le16(ssid->vht_rx_mcs_nss_ ##i << \
+ 2 * (i - 1)); \
}
OVERRIDE_MCS(1);
}
-const u8 * wpas_fst_get_peer_first(void *ctx, struct fst_get_peer_ctx **get_ctx,
- Boolean mb_only)
+static const u8 * wpas_fst_get_peer_first(void *ctx,
+ struct fst_get_peer_ctx **get_ctx,
+ Boolean mb_only)
{
struct wpa_supplicant *wpa_s = ctx;
}
-const u8 * wpas_fst_get_peer_next(void *ctx, struct fst_get_peer_ctx **get_ctx,
- Boolean mb_only)
+static const u8 * wpas_fst_get_peer_next(void *ctx,
+ struct fst_get_peer_ctx **get_ctx,
+ Boolean mb_only)
{
return NULL;
}
}
+enum wpa_radio_work_band wpas_freq_to_band(int freq)
+{
+ if (freq < 3000)
+ return BAND_2_4_GHZ;
+ if (freq > 50000)
+ return BAND_60_GHZ;
+ return BAND_5_GHZ;
+}
+
+
+unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs)
+{
+ int i;
+ unsigned int band = 0;
+
+ if (freqs) {
+ /* freqs are specified for the radio work */
+ for (i = 0; freqs[i]; i++)
+ band |= wpas_freq_to_band(freqs[i]);
+ } else {
+ /*
+ * freqs are not specified, implies all
+ * the supported freqs by HW
+ */
+ for (i = 0; i < wpa_s->hw.num_modes; i++) {
+ if (wpa_s->hw.modes[i].num_channels != 0) {
+ if (wpa_s->hw.modes[i].mode ==
+ HOSTAPD_MODE_IEEE80211B ||
+ wpa_s->hw.modes[i].mode ==
+ HOSTAPD_MODE_IEEE80211G)
+ band |= BAND_2_4_GHZ;
+ else if (wpa_s->hw.modes[i].mode ==
+ HOSTAPD_MODE_IEEE80211A)
+ band |= BAND_5_GHZ;
+ else if (wpa_s->hw.modes[i].mode ==
+ HOSTAPD_MODE_IEEE80211AD)
+ band |= BAND_60_GHZ;
+ else if (wpa_s->hw.modes[i].mode ==
+ HOSTAPD_MODE_IEEE80211ANY)
+ band = BAND_2_4_GHZ | BAND_5_GHZ |
+ BAND_60_GHZ;
+ }
+ }
+ }
+
+ return band;
+}
+
+
static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
const char *rn)
{
}
#endif /* CONFIG_P2P */
+ if (work->started) {
+ work->wpa_s->radio->num_active_works--;
+ wpa_dbg(work->wpa_s, MSG_DEBUG,
+ "radio_work_free('%s'@%p: num_active_works --> %u",
+ work->type, work,
+ work->wpa_s->radio->num_active_works);
+ }
+
dl_list_del(&work->list);
os_free(work);
}
+static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
+{
+ struct wpa_radio_work *active_work = NULL;
+ struct wpa_radio_work *tmp;
+
+ /* Get the active work to know the type and band. */
+ dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
+ if (tmp->started) {
+ active_work = tmp;
+ break;
+ }
+ }
+
+ if (!active_work) {
+ /* No active work, start one */
+ radio->num_active_works = 0;
+ dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
+ list) {
+ if (os_strcmp(tmp->type, "scan") == 0 &&
+ radio->external_scan_running &&
+ (((struct wpa_driver_scan_params *)
+ tmp->ctx)->only_new_results ||
+ tmp->wpa_s->clear_driver_scan_cache))
+ continue;
+ return tmp;
+ }
+ return NULL;
+ }
+
+ if (os_strcmp(active_work->type, "sme-connect") == 0 ||
+ os_strcmp(active_work->type, "connect") == 0) {
+ /*
+ * If the active work is either connect or sme-connect,
+ * do not parallelize them with other radio works.
+ */
+ wpa_dbg(active_work->wpa_s, MSG_DEBUG,
+ "Do not parallelize radio work with %s",
+ active_work->type);
+ return NULL;
+ }
+
+ dl_list_for_each(tmp, &radio->work, struct wpa_radio_work, list) {
+ if (tmp->started)
+ continue;
+
+ /*
+ * If connect or sme-connect are enqueued, parallelize only
+ * those operations ahead of them in the queue.
+ */
+ if (os_strcmp(tmp->type, "connect") == 0 ||
+ os_strcmp(tmp->type, "sme-connect") == 0)
+ break;
+
+ /*
+ * Check that the radio works are distinct and
+ * on different bands.
+ */
+ if (os_strcmp(active_work->type, tmp->type) != 0 &&
+ (active_work->bands != tmp->bands)) {
+ /*
+ * If a scan has to be scheduled through nl80211 scan
+ * interface and if an external scan is already running,
+ * do not schedule the scan since it is likely to get
+ * rejected by kernel.
+ */
+ if (os_strcmp(tmp->type, "scan") == 0 &&
+ radio->external_scan_running &&
+ (((struct wpa_driver_scan_params *)
+ tmp->ctx)->only_new_results ||
+ tmp->wpa_s->clear_driver_scan_cache))
+ continue;
+
+ wpa_dbg(active_work->wpa_s, MSG_DEBUG,
+ "active_work:%s new_work:%s",
+ active_work->type, tmp->type);
+ return tmp;
+ }
+ }
+
+ /* Did not find a radio work to schedule in parallel. */
+ return NULL;
+}
+
+
static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_radio *radio = eloop_ctx;
struct wpa_supplicant *wpa_s;
work = dl_list_first(&radio->work, struct wpa_radio_work, list);
- if (work == NULL)
+ if (work == NULL) {
+ radio->num_active_works = 0;
return;
-
- if (work->started)
- return; /* already started and still in progress */
+ }
wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
radio_list);
- if (wpa_s && wpa_s->radio->external_scan_running) {
- wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
- return;
+
+ if (!(wpa_s &&
+ wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)) {
+ if (work->started)
+ return; /* already started and still in progress */
+
+ if (wpa_s && wpa_s->radio->external_scan_running) {
+ wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
+ return;
+ }
+ } else {
+ work = NULL;
+ if (radio->num_active_works < MAX_ACTIVE_WORKS) {
+ /* get the work to schedule next */
+ work = radio_work_get_next_work(radio);
+ }
+ if (!work)
+ return;
}
+ wpa_s = work->wpa_s;
os_get_reltime(&now);
os_reltime_sub(&now, &work->time, &diff);
- wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Starting radio work '%s'@%p after %ld.%06ld second wait",
work->type, work, diff.sec, diff.usec);
work->started = 1;
work->time = now;
+ radio->num_active_works++;
+
work->cb(work, 0);
+
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS) &&
+ radio->num_active_works < MAX_ACTIVE_WORKS)
+ radio_work_check_next(wpa_s);
}
void (*cb)(struct wpa_radio_work *work, int deinit),
void *ctx)
{
+ struct wpa_radio *radio = wpa_s->radio;
struct wpa_radio_work *work;
int was_empty;
work->cb = cb;
work->ctx = ctx;
+ if (freq)
+ work->bands = wpas_freq_to_band(freq);
+ else if (os_strcmp(type, "scan") == 0 ||
+ os_strcmp(type, "p2p-scan") == 0)
+ work->bands = wpas_get_bands(wpa_s,
+ ((struct wpa_driver_scan_params *)
+ ctx)->freqs);
+ else
+ work->bands = wpas_get_bands(wpa_s, NULL);
+
was_empty = dl_list_empty(&wpa_s->radio->work);
if (next)
dl_list_add(&wpa_s->radio->work, &work->list);
if (was_empty) {
wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
radio_work_check_next(wpa_s);
+ } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS)
+ && radio->num_active_works < MAX_ACTIVE_WORKS) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Try to schedule a radio work (num_active_works=%u)",
+ radio->num_active_works);
+ radio_work_check_next(wpa_s);
}
return 0;
wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
wpa_s->max_scan_ssids = capa.max_scan_ssids;
wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
+ wpa_s->max_sched_scan_plans = capa.max_sched_scan_plans;
+ wpa_s->max_sched_scan_plan_interval =
+ capa.max_sched_scan_plan_interval;
+ wpa_s->max_sched_scan_plan_iterations =
+ capa.max_sched_scan_plan_iterations;
wpa_s->sched_scan_supported = capa.sched_scan_supported;
wpa_s->max_match_sets = capa.max_match_sets;
wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
wpas_rrm_reset(wpa_s);
+ wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
+
+#ifdef CONFIG_HS20
+ hs20_init(wpa_s);
+#endif /* CONFIG_HS20 */
+#ifdef CONFIG_MBO
+ wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan);
+#endif /* CONFIG_MBO */
+
+ wpa_supplicant_set_default_scan_ies(wpa_s);
+
return 0;
}
iface = global->ifaces;
while (iface) {
+ if (iface->p2pdev == wpa_s)
+ iface->p2pdev = iface->parent;
if (iface == wpa_s || iface->parent != wpa_s) {
iface = iface->next;
continue;
}
+#ifdef CONFIG_MATCH_IFACE
+
+/**
+ * wpa_supplicant_match_iface - Match an interface description to a name
+ * @global: Pointer to global data from wpa_supplicant_init()
+ * @ifname: Name of the interface to match
+ * Returns: Pointer to the created interface description or %NULL on failure
+ */
+struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
+ const char *ifname)
+{
+ int i;
+ struct wpa_interface *iface, *miface;
+
+ for (i = 0; i < global->params.match_iface_count; i++) {
+ miface = &global->params.match_ifaces[i];
+ if (!miface->ifname ||
+ fnmatch(miface->ifname, ifname, 0) == 0) {
+ iface = os_zalloc(sizeof(*iface));
+ if (!iface)
+ return NULL;
+ *iface = *miface;
+ iface->ifname = ifname;
+ return iface;
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ * wpa_supplicant_match_existing - Match existing interfaces
+ * @global: Pointer to global data from wpa_supplicant_init()
+ * Returns: 0 on success, -1 on failure
+ */
+static int wpa_supplicant_match_existing(struct wpa_global *global)
+{
+ struct if_nameindex *ifi, *ifp;
+ struct wpa_supplicant *wpa_s;
+ struct wpa_interface *iface;
+
+ ifp = if_nameindex();
+ if (!ifp) {
+ wpa_printf(MSG_ERROR, "if_nameindex: %s", strerror(errno));
+ return -1;
+ }
+
+ for (ifi = ifp; ifi->if_name; ifi++) {
+ wpa_s = wpa_supplicant_get_iface(global, ifi->if_name);
+ if (wpa_s)
+ continue;
+ iface = wpa_supplicant_match_iface(global, ifi->if_name);
+ if (iface) {
+ wpa_s = wpa_supplicant_add_iface(global, iface, NULL);
+ os_free(iface);
+ if (wpa_s)
+ wpa_s->matched = 1;
+ }
+ }
+
+ if_freenameindex(ifp);
+ return 0;
+}
+
+#endif /* CONFIG_MATCH_IFACE */
+
+
/**
* wpa_supplicant_add_iface - Add a new network interface
* @global: Pointer to global data from wpa_supplicant_init()
if (params->override_ctrl_interface)
global->params.override_ctrl_interface =
os_strdup(params->override_ctrl_interface);
+#ifdef CONFIG_MATCH_IFACE
+ global->params.match_iface_count = params->match_iface_count;
+ if (params->match_iface_count) {
+ global->params.match_ifaces =
+ os_calloc(params->match_iface_count,
+ sizeof(struct wpa_interface));
+ os_memcpy(global->params.match_ifaces,
+ params->match_ifaces,
+ params->match_iface_count *
+ sizeof(struct wpa_interface));
+ }
+#endif /* CONFIG_MATCH_IFACE */
#ifdef CONFIG_P2P
if (params->conf_p2p_dev)
global->params.conf_p2p_dev =
struct wpa_supplicant *wpa_s;
if (global->params.daemonize &&
- wpa_supplicant_daemon(global->params.pid_file))
+ (wpa_supplicant_daemon(global->params.pid_file) ||
+ eloop_sock_requeue()))
+ return -1;
+
+#ifdef CONFIG_MATCH_IFACE
+ if (wpa_supplicant_match_existing(global))
return -1;
+#endif
if (global->params.wait_for_monitor) {
for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
- if (wpa_s->ctrl_iface)
+ if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
wpa_supplicant_ctrl_iface_wait(
wpa_s->ctrl_iface);
}
os_free(global->params.ctrl_interface_group);
os_free(global->params.override_driver);
os_free(global->params.override_ctrl_interface);
+#ifdef CONFIG_MATCH_IFACE
+ os_free(global->params.match_ifaces);
+#endif /* CONFIG_MATCH_IFACE */
#ifdef CONFIG_P2P
os_free(global->params.conf_p2p_dev);
#endif /* CONFIG_P2P */
if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
wpas_init_ext_pw(wpa_s);
+ if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS)
+ wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans);
+
#ifdef CONFIG_WPS
wpas_wps_update_config(wpa_s);
#endif /* CONFIG_WPS */
if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
wpa_supplicant_req_scan(wpa_s, 0, 0);
break;
+ case WPA_CTRL_REQ_EXT_CERT_CHECK:
+ if (eap->pending_ext_cert_check != PENDING_CHECK)
+ return -1;
+ if (os_strcmp(value, "good") == 0)
+ eap->pending_ext_cert_check = EXT_CERT_CHECK_GOOD;
+ else if (os_strcmp(value, "bad") == 0)
+ eap->pending_ext_cert_check = EXT_CERT_CHECK_BAD;
+ else
+ return -1;
+ break;
default:
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
return -1;
return NO_MGMT_FRAME_PROTECTION;
}
+ if (ssid &&
+ (ssid->key_mgmt &
+ ~(WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPS |
+ WPA_KEY_MGMT_IEEE8021X_NO_WPA)) == 0) {
+ /*
+ * Do not use the default PMF value for non-RSN networks
+ * since PMF is available only with RSN and pmf=2
+ * configuration would otherwise prevent connections to
+ * all open networks.
+ */
+ return NO_MGMT_FRAME_PROTECTION;
+ }
+
return wpa_s->conf->pmf;
}
}
+/**
+ * wpas_request_disconnection - Request disconnection
+ * @wpa_s: Pointer to the network interface
+ *
+ * This function is used to request disconnection from the currently connected
+ * network. This will stop any ongoing scans and initiate deauthentication.
+ */
+void wpas_request_disconnection(struct wpa_supplicant *wpa_s)
+{
+#ifdef CONFIG_SME
+ wpa_s->sme.prev_bssid_set = 0;
+#endif /* CONFIG_SME */
+ wpa_s->reassociate = 0;
+ wpa_s->disconnected = 1;
+ wpa_supplicant_cancel_sched_scan(wpa_s);
+ wpa_supplicant_cancel_scan(wpa_s);
+ wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+ eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
+}
+
+
void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title,
struct wpa_used_freq_data *freqs_data,
unsigned int len)
#define ECANCELED -1
#endif
+/* Measurement Request element + Location Subject + Maximum Age subelement */
+#define MEASURE_REQUEST_LCI_LEN (3 + 1 + 4)
+/* Measurement Request element + Location Civic Request */
+#define MEASURE_REQUEST_CIVIC_LEN (3 + 5)
+
+
/**
* wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP
* @wpa_s: Pointer to wpa_supplicant
* @ssid: if not null, this is sent in the request. Otherwise, no SSID IE
* is sent in the request.
+ * @lci: if set, neighbor request will include LCI request
+ * @civic: if set, neighbor request will include civic location request
* @cb: Callback function to be called once the requested report arrives, or
* timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds.
* In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's
* Request must contain a callback function.
*/
int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
- const struct wpa_ssid *ssid,
+ const struct wpa_ssid_value *ssid,
+ int lci, int civic,
void (*cb)(void *ctx,
struct wpabuf *neighbor_rep),
void *cb_ctx)
}
/* 3 = action category + action code + dialog token */
- buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0));
+ buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0) +
+ (lci ? 2 + MEASURE_REQUEST_LCI_LEN : 0) +
+ (civic ? 2 + MEASURE_REQUEST_CIVIC_LEN : 0));
if (buf == NULL) {
wpa_printf(MSG_DEBUG,
"RRM: Failed to allocate Neighbor Report Request");
wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len);
}
+ if (lci) {
+ /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
+ wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
+ wpabuf_put_u8(buf, MEASURE_REQUEST_LCI_LEN);
+
+ /*
+ * Measurement token; nonzero number that is unique among the
+ * Measurement Request elements in a particular frame.
+ */
+ wpabuf_put_u8(buf, 1); /* Measurement Token */
+
+ /*
+ * Parallel, Enable, Request, and Report bits are 0, Duration is
+ * reserved.
+ */
+ wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
+ wpabuf_put_u8(buf, MEASURE_TYPE_LCI); /* Measurement Type */
+
+ /* IEEE P802.11-REVmc/D5.0 9.4.2.21.10 - LCI request */
+ /* Location Subject */
+ wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
+
+ /* Optional Subelements */
+ /*
+ * IEEE P802.11-REVmc/D5.0 Figure 9-170
+ * The Maximum Age subelement is required, otherwise the AP can
+ * send only data that was determined after receiving the
+ * request. Setting it here to unlimited age.
+ */
+ wpabuf_put_u8(buf, LCI_REQ_SUBELEM_MAX_AGE);
+ wpabuf_put_u8(buf, 2);
+ wpabuf_put_le16(buf, 0xffff);
+ }
+
+ if (civic) {
+ /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */
+ wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST);
+ wpabuf_put_u8(buf, MEASURE_REQUEST_CIVIC_LEN);
+
+ /*
+ * Measurement token; nonzero number that is unique among the
+ * Measurement Request elements in a particular frame.
+ */
+ wpabuf_put_u8(buf, 2); /* Measurement Token */
+
+ /*
+ * Parallel, Enable, Request, and Report bits are 0, Duration is
+ * reserved.
+ */
+ wpabuf_put_u8(buf, 0); /* Measurement Request Mode */
+ /* Measurement Type */
+ wpabuf_put_u8(buf, MEASURE_TYPE_LOCATION_CIVIC);
+
+ /* IEEE P802.11-REVmc/D5.0 9.4.2.21.14:
+ * Location Civic request */
+ /* Location Subject */
+ wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE);
+ wpabuf_put_u8(buf, 0); /* Civic Location Type: IETF RFC 4776 */
+ /* Location Service Interval Units: Seconds */
+ wpabuf_put_u8(buf, 0);
+ /* Location Service Interval: 0 - Only one report is requested
+ */
+ wpabuf_put_le16(buf, 0);
+ /* No optional subelements */
+ }
+
wpa_s->rrm.next_neighbor_rep_token++;
if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
}
+static struct wpabuf * wpas_rrm_build_lci_report(struct wpa_supplicant *wpa_s,
+ const u8 *request, size_t len,
+ struct wpabuf *report)
+{
+ u8 token, type, subject;
+ u16 max_age = 0;
+ struct os_reltime t, diff;
+ unsigned long diff_l;
+ u8 *ptoken;
+ const u8 *subelem;
+
+ if (!wpa_s->lci || len < 3 + 4)
+ return report;
+
+ token = *request++;
+ /* Measurement request mode isn't used */
+ request++;
+ type = *request++;
+ subject = *request++;
+
+ wpa_printf(MSG_DEBUG,
+ "Measurement request token %u type %u location subject %u",
+ token, type, subject);
+
+ if (type != MEASURE_TYPE_LCI || subject != LOCATION_SUBJECT_REMOTE) {
+ wpa_printf(MSG_INFO,
+ "Not building LCI report - bad type or location subject");
+ return report;
+ }
+
+ /* Subelements are formatted exactly like elements */
+ subelem = get_ie(request, len, LCI_REQ_SUBELEM_MAX_AGE);
+ if (subelem && subelem[1] == 2)
+ max_age = WPA_GET_LE16(subelem + 2);
+
+ if (os_get_reltime(&t))
+ return report;
+
+ os_reltime_sub(&t, &wpa_s->lci_time, &diff);
+ /* LCI age is calculated in 10th of a second units. */
+ diff_l = diff.sec * 10 + diff.usec / 100000;
+
+ if (max_age != 0xffff && max_age < diff_l)
+ return report;
+
+ if (wpabuf_resize(&report, 2 + wpabuf_len(wpa_s->lci)))
+ return report;
+
+ wpabuf_put_u8(report, WLAN_EID_MEASURE_REPORT);
+ wpabuf_put_u8(report, wpabuf_len(wpa_s->lci));
+ /* We'll override user's measurement token */
+ ptoken = wpabuf_put(report, 0);
+ wpabuf_put_buf(report, wpa_s->lci);
+ *ptoken = token;
+
+ return report;
+}
+
+
+void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s,
+ const u8 *src,
+ const u8 *frame, size_t len)
+{
+ struct wpabuf *buf, *report;
+ u8 token;
+ const u8 *ie, *end;
+
+ if (wpa_s->wpa_state != WPA_COMPLETED) {
+ wpa_printf(MSG_INFO,
+ "RRM: Ignoring radio measurement request: Not associated");
+ return;
+ }
+
+ if (!wpa_s->rrm.rrm_used) {
+ wpa_printf(MSG_INFO,
+ "RRM: Ignoring radio measurement request: Not RRM network");
+ return;
+ }
+
+ if (len < 3) {
+ wpa_printf(MSG_INFO,
+ "RRM: Ignoring too short radio measurement request");
+ return;
+ }
+
+ end = frame + len;
+
+ token = *frame++;
+
+ /* Ignore number of repetitions because it's not used in LCI request */
+ frame += 2;
+
+ report = NULL;
+ while ((ie = get_ie(frame, end - frame, WLAN_EID_MEASURE_REQUEST)) &&
+ ie[1] >= 3) {
+ u8 msmt_type;
+
+ msmt_type = ie[4];
+ wpa_printf(MSG_DEBUG, "RRM request %d", msmt_type);
+
+ switch (msmt_type) {
+ case MEASURE_TYPE_LCI:
+ report = wpas_rrm_build_lci_report(wpa_s, ie + 2, ie[1],
+ report);
+ break;
+ default:
+ wpa_printf(MSG_INFO,
+ "RRM: Unsupported radio measurement request %d",
+ msmt_type);
+ break;
+ }
+
+ frame = ie + ie[1] + 2;
+ }
+
+ if (!report)
+ return;
+
+ buf = wpabuf_alloc(3 + wpabuf_len(report));
+ if (!buf) {
+ wpabuf_free(report);
+ return;
+ }
+
+ wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
+ wpabuf_put_u8(buf, WLAN_RRM_RADIO_MEASUREMENT_REPORT);
+ wpabuf_put_u8(buf, token);
+
+ wpabuf_put_buf(buf, report);
+ wpabuf_free(report);
+
+ if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
+ wpa_s->own_addr, wpa_s->bssid,
+ wpabuf_head(buf), wpabuf_len(buf), 0)) {
+ wpa_printf(MSG_ERROR,
+ "RRM: Radio measurement report failed: Sending Action frame failed");
+ }
+ wpabuf_free(buf);
+}
+
+
void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
const u8 *src,
const u8 *frame, size_t len,
}
wpabuf_free(buf);
}
+
+
+struct wpa_supplicant *
+wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
+{
+ switch (frame) {
+#ifdef CONFIG_P2P
+ case VENDOR_ELEM_PROBE_REQ_P2P:
+ case VENDOR_ELEM_PROBE_RESP_P2P:
+ case VENDOR_ELEM_PROBE_RESP_P2P_GO:
+ case VENDOR_ELEM_BEACON_P2P_GO:
+ case VENDOR_ELEM_P2P_PD_REQ:
+ case VENDOR_ELEM_P2P_PD_RESP:
+ case VENDOR_ELEM_P2P_GO_NEG_REQ:
+ case VENDOR_ELEM_P2P_GO_NEG_RESP:
+ case VENDOR_ELEM_P2P_GO_NEG_CONF:
+ case VENDOR_ELEM_P2P_INV_REQ:
+ case VENDOR_ELEM_P2P_INV_RESP:
+ case VENDOR_ELEM_P2P_ASSOC_REQ:
+ case VENDOR_ELEM_P2P_ASSOC_RESP:
+ return wpa_s->p2pdev;
+#endif /* CONFIG_P2P */
+ default:
+ return wpa_s;
+ }
+}
+
+
+void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
+{
+ unsigned int i;
+ char buf[30];
+
+ wpa_printf(MSG_DEBUG, "Update vendor elements");
+
+ for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
+ if (wpa_s->vendor_elem[i]) {
+ int res;
+
+ res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
+ if (!os_snprintf_error(sizeof(buf), res)) {
+ wpa_hexdump_buf(MSG_DEBUG, buf,
+ wpa_s->vendor_elem[i]);
+ }
+ }
+ }
+
+#ifdef CONFIG_P2P
+ if (wpa_s->parent == wpa_s &&
+ wpa_s->global->p2p &&
+ !wpa_s->global->p2p_disabled)
+ p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
+#endif /* CONFIG_P2P */
+}
+
+
+int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
+ const u8 *elem, size_t len)
+{
+ u8 *ie, *end;
+
+ ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
+ end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
+
+ for (; ie + 1 < end; ie += 2 + ie[1]) {
+ if (ie + len > end)
+ break;
+ if (os_memcmp(ie, elem, len) != 0)
+ continue;
+
+ if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
+ wpabuf_free(wpa_s->vendor_elem[frame]);
+ wpa_s->vendor_elem[frame] = NULL;
+ } else {
+ os_memmove(ie, ie + len, end - (ie + len));
+ wpa_s->vendor_elem[frame]->used -= len;
+ }
+ wpas_vendor_elem_update(wpa_s);
+ return 0;
+ }
+
+ return -1;
+}
+
+
+struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
+ u16 num_modes, enum hostapd_hw_mode mode)
+{
+ u16 i;
+
+ for (i = 0; i < num_modes; i++) {
+ if (modes[i].mode == mode)
+ return &modes[i];
+ }
+
+ return NULL;
+}
+
+
+static struct
+wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s,
+ const u8 *bssid)
+{
+ struct wpa_bss_tmp_disallowed *bss;
+
+ dl_list_for_each(bss, &wpa_s->bss_tmp_disallowed,
+ struct wpa_bss_tmp_disallowed, list) {
+ if (os_memcmp(bssid, bss->bssid, ETH_ALEN) == 0)
+ return bss;
+ }
+
+ return NULL;
+}
+
+
+void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ unsigned int sec)
+{
+ struct wpa_bss_tmp_disallowed *bss;
+ struct os_reltime until;
+
+ os_get_reltime(&until);
+ until.sec += sec;
+
+ bss = wpas_get_disallowed_bss(wpa_s, bssid);
+ if (bss) {
+ bss->disallowed_until = until;
+ return;
+ }
+
+ bss = os_malloc(sizeof(*bss));
+ if (!bss) {
+ wpa_printf(MSG_DEBUG,
+ "Failed to allocate memory for temp disallow BSS");
+ return;
+ }
+
+ bss->disallowed_until = until;
+ os_memcpy(bss->bssid, bssid, ETH_ALEN);
+ dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list);
+}
+
+
+int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid)
+{
+ struct wpa_bss_tmp_disallowed *bss = NULL, *tmp, *prev;
+ struct os_reltime now, age;
+
+ os_get_reltime(&now);
+
+ dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed,
+ struct wpa_bss_tmp_disallowed, list) {
+ if (!os_reltime_before(&now, &tmp->disallowed_until)) {
+ /* This BSS is not disallowed anymore */
+ dl_list_del(&tmp->list);
+ os_free(tmp);
+ continue;
+ }
+ if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
+ bss = tmp;
+ break;
+ }
+ }
+ if (!bss)
+ return 0;
+
+ os_reltime_sub(&bss->disallowed_until, &now, &age);
+ wpa_printf(MSG_DEBUG,
+ "BSS " MACSTR " disabled for %ld.%0ld seconds",
+ MAC2STR(bss->bssid), age.sec, age.usec);
+ return 1;
+}
# networks are found, a new IBSS or AP mode network is created.
ap_scan=1
+# Whether to force passive scan for network connection
+#
+# By default, scans will send out Probe Request frames on channels that allow
+# active scanning. This advertise the local station to the world. Normally this
+# is fine, but users may wish to do passive scanning where the radio should only
+# listen quietly for Beacon frames and not send any Probe Request frames. Actual
+# functionality may be driver dependent.
+#
+# This parameter can be used to force only passive scanning to be used
+# for network connection cases. It should be noted that this will slow
+# down scan operations and reduce likelihood of finding the AP. In
+# addition, some use cases will override this due to functional
+# requirements, e.g., for finding an AP that uses hidden SSID
+# (scan_ssid=1) or P2P device discovery.
+#
+# 0: Do normal scans (allow active scans) (default)
+# 1: Do passive scans.
+#passive_scan=0
+
# MPM residency
# By default, wpa_supplicant implements the mesh peering manager (MPM) for an
# open mesh. However, if the driver can implement the MPM, you may set this to
fast_reauth=1
# OpenSSL Engine support
-# These options can be used to load OpenSSL engines.
+# These options can be used to load OpenSSL engines in special or legacy
+# modes.
# The two engines that are supported currently are shown below:
# They are both from the opensc project (http://www.opensc.org/)
-# By default no engines are loaded.
+# By default the PKCS#11 engine is loaded if the client_cert or
+# private_key option appear to be a PKCS#11 URI, and these options
+# should not need to be used explicitly.
# make the opensc engine available
#opensc_engine_path=/usr/lib/opensc/engine_opensc.so
# make the pkcs11 engine available
#load_dynamic_eap=/usr/lib/wpa_supplicant/eap_md5.so
# Driver interface parameters
-# This field can be used to configure arbitrary driver interace parameters. The
+# This field can be used to configure arbitrary driver interface parameters. The
# format is specific to the selected driver interface. This field is not used
# in most cases.
#driver_param="field=value"
# up to the limit of 300 seconds (3, 9, 27 ... 300)
# For periodic module, parameters would be <fixed interval>
#autoscan=periodic:30
-# So a delay of 30 seconds will be applied between each scan
+# So a delay of 30 seconds will be applied between each scan.
+# Note: If sched_scan_plans are configured and supported by the driver,
+# autoscan is ignored.
# filter_ssids - SSID-based scan result filtering
# 0 = do not filter scan results (default)
# Protected Management Frames default
# This parameter can be used to set the default behavior for the ieee80211w
-# parameter. By default, PMF is disabled unless enabled with the global pmf=1/2
-# parameter or with the per-network ieee80211w=1/2 parameter. With pmf=1/2, PMF
-# is enabled/required by default, but can be disabled with the per-network
-# ieee80211w parameter.
+# parameter for RSN networks. By default, PMF is disabled unless enabled with
+# the global pmf=1/2 parameter or with the per-network ieee80211w=1/2 parameter.
+# With pmf=1/2, PMF is enabled/required by default, but can be disabled with the
+# per-network ieee80211w parameter. This global default value does not apply
+# for non-RSN networks (key_mgmt=NONE) since PMF is available only when using
+# RSN.
#pmf=0
# Enabled SAE finite cyclic groups in preference order
# matching network block
#auto_interworking=0
+# GAS Address3 field behavior
+# 0 = P2P specification (Address3 = AP BSSID); default
+# 1 = IEEE 802.11 standard compliant (Address3 = Wildcard BSSID when
+# sent to not-associated AP; if associated, AP BSSID)
+#gas_address3=0
+
+# Publish fine timing measurement (FTM) responder functionality in
+# the Extended Capabilities element bit 70.
+# Controls whether FTM responder functionality will be published by AP/STA.
+# Note that actual FTM responder operation is managed outside wpa_supplicant.
+# 0 = Do not publish; default
+# 1 = Publish
+#ftm_responder=0
+
+# Publish fine timing measurement (FTM) initiator functionality in
+# the Extended Capabilities element bit 71.
+# Controls whether FTM initiator functionality will be published by AP/STA.
+# Note that actual FTM initiator operation is managed outside wpa_supplicant.
+# 0 = Do not publish; default
+# 1 = Publish
+#ftm_initiator=0
+
# credential block
#
# Each credential used for automatic network selection is configured as a set
# (EAP-TLS). Full path to the file should be used since working
# directory may change when wpa_supplicant is run in the background.
#
+# Certificates from PKCS#11 tokens can be referenced by a PKCS#11 URI.
+#
+# For example: private_key="pkcs11:manufacturer=piv_II;id=%01"
+#
# Alternatively, a named configuration blob can be used by setting
# this to blob://blob_name.
#
# used since working directory may change when wpa_supplicant is run
# in the background.
#
+# Keys in PKCS#11 tokens can be referenced by a PKCS#11 URI.
+# For example: private_key="pkcs11:manufacturer=piv_II;id=%01"
+#
# Windows certificate store can be used by leaving client_cert out and
# configuring private_key in one of the following formats:
#
# 0 = do not use OCSP stapling (TLS certificate status extension)
# 1 = try to use OCSP stapling, but not require response
# 2 = require valid OCSP stapling response
+# 3 = require valid OCSP stapling response for all not-trusted
+# certificates in the server certificate chain
#
# sim_num: Identifier for which SIM to use in multi-SIM devices
#
# Hotspot 2.0
# hs20=1
+# Scheduled scan plans
+#
+# A space delimited list of scan plans. Each scan plan specifies the scan
+# interval and number of iterations, delimited by a colon. The last scan plan
+# will run infinitely and thus must specify only the interval and not the number
+# of iterations.
+#
+# The driver advertises the maximum number of scan plans supported. If more scan
+# plans than supported are configured, only the first ones are set (up to the
+# maximum supported). The last scan plan that specifies only the interval is
+# always set as the last plan.
+#
+# If the scan interval or the number of iterations for a scan plan exceeds the
+# maximum supported, it will be set to the maximum supported value.
+#
+# Format:
+# sched_scan_plans=<interval:iterations> <interval:iterations> ... <interval>
+#
+# Example:
+# sched_scan_plans=10:100 20:200 30
+
+# Multi Band Operation (MBO) non-preferred channels
+# A space delimited list of non-preferred channels where each channel is a colon
+# delimited list of values.
+# Format:
+# non_pref_chan=<oper_class>:<chan>:<preference>:<reason>
+# Example:
+# non_pref_chan="81:5:10:2 81:1:0:2 81:9:0:2"
+
+# MBO Cellular Data Capabilities
+# 1 = Cellular data connection available
+# 2 = Cellular data connection not available
+# 3 = Not cellular capable (default)
+#mbo_cell_capa=3
+
# network block
#
# Each network (usually AP's sharing the same SSID) is configured as a separate
# an IBSS network with the configured SSID is already present, the frequency of
# the network will be used instead of this configured value.
#
+# pbss: Whether to use PBSS. Relevant to IEEE 802.11ad networks only.
+# 0 = do not use PBSS
+# 1 = use PBSS
+# 2 = don't care (not allowed in AP mode)
+# Used together with mode configuration. When mode is AP, it means to start a
+# PCP instead of a regular AP. When mode is infrastructure it means connect
+# to a PCP instead of AP. In this mode you can also specify 2 (don't care)
+# which means connect to either PCP or AP.
+# P2P_GO and P2P_GROUP_FORMATION modes must use PBSS in IEEE 802.11ad network.
+# For more details, see IEEE Std 802.11ad-2012.
+#
# scan_freq: List of frequencies to scan
# Space-separated list of frequencies in MHz to scan when searching for this
# BSS. If the subset of channels used by the network is known, this option can
# IEEE8021X = IEEE 802.1X using EAP authentication and (optionally) dynamically
# generated WEP keys
# NONE = WPA is not used; plaintext or static WEP could be used
+# WPA-NONE = WPA-None for IBSS (deprecated; use proto=RSN key_mgmt=WPA-PSK
+# instead)
+# FT-PSK = Fast BSS Transition (IEEE 802.11r) with pre-shared key
+# FT-EAP = Fast BSS Transition (IEEE 802.11r) with EAP authentication
# WPA-PSK-SHA256 = Like WPA-PSK but using stronger SHA256-based algorithms
# WPA-EAP-SHA256 = Like WPA-EAP but using stronger SHA256-based algorithms
+# SAE = Simultaneous authentication of equals; pre-shared key/password -based
+# authentication with stronger security than WPA-PSK especially when using
+# not that strong password
+# FT-SAE = SAE with FT
+# WPA-EAP-SUITE-B = Suite B 128-bit level
+# WPA-EAP-SUITE-B-192 = Suite B 192-bit level
+# OSEN = Hotspot 2.0 Rel 2 online signup connection
# If not set, this defaults to: WPA-PSK WPA-EAP
#
# ieee80211w: whether management frame protection is enabled
# wpa_ptk_rekey: Maximum lifetime for PTK in seconds. This can be used to
# enforce rekeying of PTK to mitigate some attacks against TKIP deficiencies.
#
+# group_rekey: Group rekeying time in seconds. This value, if non-zero, is used
+# as the dot11RSNAConfigGroupRekeyTime parameter when operating in
+# Authenticator role in IBSS.
+#
# Following fields are only used with internal EAP implementation.
# eap: space-separated list of accepted EAP methods
-# MD5 = EAP-MD5 (unsecure and does not generate keying material ->
+# MD5 = EAP-MD5 (insecure and does not generate keying material ->
# cannot be used with WPA; to be used as a Phase 2 method
# with EAP-PEAP or EAP-TTLS)
# MSCHAPV2 = EAP-MSCHAPv2 (cannot be used separately with WPA; to be used
# automatically converted into DH params.
# subject_match: Substring to be matched against the subject of the
# authentication server certificate. If this string is set, the server
-# sertificate is only accepted if it contains this string in the subject.
+# 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@example.com
-# Note: Since this is a substring match, this cannot be used securily to
+# 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 or domain_match should be used
# instead.
# altsubject_match: 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.
# altSubjectName string is in following format: TYPE:VALUE
# Example: EMAIL:server@example.com
# Example: DNS:server.example.com;DNS:server2.example.com
# Following types are supported: EMAIL, DNS, URI
# domain_suffix_match: Constraint for server domain name. If set, this FQDN is
-# used as a suffix match requirement for the AAAserver certificate in
+# used as a suffix match requirement for the AAA server certificate in
# SubjectAltName dNSName element(s). If a matching dNSName is found, this
# constraint is met. If no dNSName values are present, this constraint is
# matched against SubjectName CN using same suffix match comparison.
# that have issues interoperating with updated TLS version)
# tls_disable_tlsv1_2=1 - disable use of TLSv1.2 (a workaround for AAA servers
# that have issues interoperating with updated TLS version)
+# tls_ext_cert_check=0 - No external server certificate validation (default)
+# tls_ext_cert_check=1 - External server certificate validation enabled; this
+# requires an external program doing validation of server certificate
+# chain when receiving CTRL-RSP-EXT_CERT_CHECK event from the control
+# interface and report the result of the validation with
+# CTRL-RSP_EXT_CERT_CHECK.
#
# Following certificate/private key fields are used in inner Phase2
# authentication when using EAP-TTLS or EAP-PEAP.
# 0 = do not use OCSP stapling (TLS certificate status extension)
# 1 = try to use OCSP stapling, but not require response
# 2 = require valid OCSP stapling response
+# 3 = require valid OCSP stapling response for all not-trusted
+# certificates in the server certificate chain
#
# openssl_ciphers: OpenSSL specific cipher configuration
# This can be used to override the global openssl_ciphers configuration
# number of authentication servers. Strict EAP conformance mode can be
# configured by disabling workarounds with eap_workaround=0.
+# update_identifier: PPS MO ID
+# (Hotspot 2.0 PerProviderSubscription/UpdateIdentifier)
+
# Station inactivity limit
#
# If a station does not send anything in ap_max_inactivity seconds, an
# Beacon interval (default: 100 TU)
#beacon_int=100
+# WPS in AP mode
+# 0 = WPS enabled and configured (default)
+# 1 = WPS disabled
+#wps_disabled=0
+
# MAC address policy
# 0 = use permanent MAC address
# 1 = use random MAC address for each ESS connection
##### Fast Session Transfer (FST) support #####################################
#
# The options in this section are only available when the build configuration
-# option CONFIG_FST is set while compiling hostapd. They allow this interface
-# to be a part of FST setup.
+# option CONFIG_FST is set while compiling wpa_supplicant. They allow this
+# interface to be a part of FST setup.
#
# FST is the transfer of a session from a channel to another channel, in the
# same or different frequency bands.
#
-# For detals, see IEEE Std 802.11ad-2012.
+# For details, see IEEE Std 802.11ad-2012.
# Identifier of an FST Group the interface belongs to.
#fst_group_id=bond0
group=CCMP TKIP
identity="user@example.com"
ca_cert="/etc/cert/ca.pem"
- client_cert="/etc/cert/user.pem"
-
- engine=1
-
- # The engine configured here must be available. Look at
- # OpenSSL engine support in the global section.
- # The key available through the engine must be the private key
- # matching the client certificate configured above.
-
- # use the opensc engine
- #engine_id="opensc"
- #key_id="45"
- # use the pkcs11 engine
- engine_id="pkcs11"
- key_id="id_45"
+ # Certificate and/or key identified by PKCS#11 URI (RFC7512)
+ client_cert="pkcs11:manufacturer=piv_II;id=%01"
+ private_key="pkcs11:manufacturer=piv_II;id=%01"
# Optional PIN configuration; this can be left out and PIN will be
# asked through the control interface
struct ctrl_iface_priv;
struct ctrl_iface_global_priv;
struct wpas_dbus_priv;
+struct wpas_binder_priv;
/**
* struct wpa_interface - Parameters for wpa_supplicant_add_iface()
char *conf_p2p_dev;
#endif /* CONFIG_P2P */
+#ifdef CONFIG_MATCH_IFACE
+ /**
+ * match_ifaces - Interface descriptions to match
+ */
+ struct wpa_interface *match_ifaces;
+
+ /**
+ * match_iface_count - Number of defined matching interfaces
+ */
+ int match_iface_count;
+#endif /* CONFIG_MATCH_IFACE */
};
struct p2p_srv_bonjour {
struct wpa_params params;
struct ctrl_iface_global_priv *ctrl_iface;
struct wpas_dbus_priv *dbus;
+ struct wpas_binder_priv *binder;
void **drv_priv;
size_t drv_count;
struct os_time suspend_time;
unsigned int p2p_24ghz_social_channels:1;
unsigned int pending_p2ps_group:1;
unsigned int pending_group_iface_for_p2ps:1;
+ unsigned int pending_p2ps_group_freq;
#ifdef CONFIG_WIFI_DISPLAY
int wifi_display;
char name[16]; /* from driver_ops get_radio_name() or empty if not
* available */
unsigned int external_scan_running:1;
+ unsigned int num_active_works;
struct dl_list ifaces; /* struct wpa_supplicant::radio_list entries */
struct dl_list work; /* struct wpa_radio_work::list entries */
};
+#define MAX_ACTIVE_WORKS 2
+
+
/**
* struct wpa_radio_work - Radio work item
*/
void *ctx;
unsigned int started:1;
struct os_reltime time;
+ unsigned int bands;
};
int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
unsigned int timeout;
};
+enum wpa_radio_work_band wpas_freq_to_band(int freq);
+unsigned int wpas_get_bands(struct wpa_supplicant *wpa_s, const int *freqs);
+
/**
* offchannel_send_action_result - Result of offchannel send Action frame
*/
u8 uuid[WPS_UUID_LEN];
};
-struct wpa_ssid_value {
- u8 ssid[SSID_MAX_LEN];
- size_t ssid_len;
-};
-
#define WPA_FREQ_USED_BY_INFRA_STATION BIT(0)
#define WPA_FREQ_USED_BY_P2P_CLIENT BIT(1)
WPAS_TEST_FAILURE_SCAN_TRIGGER,
};
+struct icon_entry {
+ struct dl_list list;
+ u8 bssid[ETH_ALEN];
+ u8 dialog_token;
+ char *file_name;
+ u8 *image;
+ size_t image_len;
+};
+
+struct wpa_bss_tmp_disallowed {
+ struct dl_list list;
+ u8 bssid[ETH_ALEN];
+ struct os_reltime disallowed_until;
+};
+
/**
* struct wpa_supplicant - Internal data for wpa_supplicant interface
*
struct wpa_radio *radio; /* shared radio context */
struct dl_list radio_list; /* list head: struct wpa_radio::ifaces */
struct wpa_supplicant *parent;
+ struct wpa_supplicant *p2pdev;
struct wpa_supplicant *next;
struct l2_packet_data *l2;
struct l2_packet_data *l2_br;
unsigned char own_addr[ETH_ALEN];
unsigned char perm_addr[ETH_ALEN];
char ifname[100];
+#ifdef CONFIG_MATCH_IFACE
+ int matched;
+#endif /* CONFIG_MATCH_IFACE */
#ifdef CONFIG_CTRL_IFACE_DBUS
char *dbus_path;
#endif /* CONFIG_CTRL_IFACE_DBUS */
char *preq_notify_peer;
#endif /* CONFIG_AP */
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
+#ifdef CONFIG_CTRL_IFACE_BINDER
+ const void *binder_object_key;
+#endif /* CONFIG_CTRL_IFACE_BINDER */
char bridge_ifname[16];
char *confname;
u8 pending_bssid[ETH_ALEN]; /* If wpa_state == WPA_ASSOCIATING, this
* field contains the target BSSID. */
int reassociate; /* reassociation requested */
- int reassoc_same_bss; /* reassociating to the same bss */
+ unsigned int reassoc_same_bss:1; /* reassociating to the same BSS */
+ unsigned int reassoc_same_ess:1; /* reassociating to the same ESS */
int disconnected; /* all connections disabled; i.e., do no reassociate
* before this has been cleared */
struct wpa_ssid *current_ssid;
struct wpa_ssid *prev_sched_ssid; /* last SSID used in sched scan */
int sched_scan_timeout;
- int sched_scan_interval;
int first_sched_scan;
int sched_scan_timed_out;
+ struct sched_scan_plan *sched_scan_plans;
+ size_t sched_scan_plans_num;
void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res);
struct wpa_radio_work *scan_work;
int scanning;
int sched_scanning;
+ unsigned int sched_scan_stop_req:1;
int new_connection;
int eapol_received; /* number of EAPOL packets received after the
#define MAX_SCAN_ID 16
int scan_id[MAX_SCAN_ID];
unsigned int scan_id_count;
+ u8 next_scan_bssid[ETH_ALEN];
struct wpa_ssid_value *ssids_from_scan_req;
unsigned int num_ssids_from_scan_req;
int max_scan_ssids;
int max_sched_scan_ssids;
+ unsigned int max_sched_scan_plans;
+ unsigned int max_sched_scan_plan_interval;
+ unsigned int max_sched_scan_plan_iterations;
int sched_scan_supported;
unsigned int max_match_sets;
unsigned int max_remain_on_chan;
unsigned int reattach:1; /* reassociation to the same BSS requested */
unsigned int mac_addr_changed:1;
unsigned int added_vif:1;
+ unsigned int wnmsleep_used:1;
struct os_reltime last_mac_addr_change;
int last_mac_addr_style;
int mesh_if_idx;
unsigned int mesh_if_created:1;
unsigned int mesh_ht_enabled:1;
- int mesh_auth_block_duration; /* sec */
+ unsigned int mesh_vht_enabled:1;
#endif /* CONFIG_MESH */
unsigned int off_channel_freq;
int *p2p_group_common_freqs;
unsigned int p2p_group_common_freqs_num;
u8 p2ps_join_addr[ETH_ALEN];
+
+ unsigned int p2p_go_max_oper_chwidth;
+ unsigned int p2p_go_vht_center_freq2;
+ int p2p_lo_started;
#endif /* CONFIG_P2P */
struct wpa_ssid *bgscan_ssid;
unsigned int fetch_osu_icon_in_progress:1;
struct wpa_bss *interworking_gas_bss;
unsigned int osu_icon_id;
+ struct dl_list icon_head; /* struct icon_entry */
struct osu_provider *osu_prov;
size_t osu_prov_count;
struct os_reltime osu_icon_fetch_start;
/* WLAN_REASON_* reason codes. Negative if locally generated. */
int disconnect_reason;
+ /* WLAN_STATUS_* status codes from (Re)Association Response frame. */
+ u16 assoc_status_code;
+
struct ext_password_data *ext_pw;
struct wpabuf *last_gas_resp, *prev_gas_resp;
struct l2_packet_data *l2_test;
unsigned int extra_roc_dur;
enum wpa_supplicant_test_failure test_failure;
+ unsigned int reject_btm_req_reason;
+ unsigned int p2p_go_csa_on_inv:1;
+ unsigned int ignore_auth_resp:1;
+ unsigned int ignore_assoc_disallow:1;
#endif /* CONFIG_TESTING_OPTIONS */
struct wmm_ac_assoc_data *wmm_ac_assoc_info;
const struct wpabuf *fst_ies;
struct wpabuf *received_mb_ies;
#endif /* CONFIG_FST */
+
+#ifdef CONFIG_MBO
+ /* Multiband operation non-preferred channel */
+ struct wpa_mbo_non_pref_channel {
+ enum mbo_non_pref_chan_reason reason;
+ u8 oper_class;
+ u8 chan;
+ u8 preference;
+ } *non_pref_chan;
+ size_t non_pref_chan_num;
+ u8 mbo_wnm_token;
+#endif /* CONFIG_MBO */
+
+ /*
+ * This should be under CONFIG_MBO, but it is left out to allow using
+ * the bss_temp_disallowed list for other purposes as well.
+ */
+ struct dl_list bss_tmp_disallowed;
+
+ /*
+ * Content of a measurement report element with type 8 (LCI),
+ * own location.
+ */
+ struct wpabuf *lci;
+ struct os_reltime lci_time;
};
void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
int reason_code);
+struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s);
+int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id);
void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
void wpa_show_license(void);
+struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global,
+ const char *ifname);
struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
struct wpa_interface *iface,
struct wpa_supplicant *parent);
int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
size_t ssid_len);
void wpas_request_connection(struct wpa_supplicant *wpa_s);
+void wpas_request_disconnection(struct wpa_supplicant *wpa_s);
int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen);
int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style);
int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s);
void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
const u8 *report, size_t report_len);
int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
- const struct wpa_ssid *ssid,
+ const struct wpa_ssid_value *ssid,
+ int lci, int civic,
void (*cb)(void *ctx,
struct wpabuf *neighbor_rep),
void *cb_ctx);
+void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s,
+ const u8 *src,
+ const u8 *frame, size_t len);
void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
const u8 *src,
const u8 *frame, size_t len,
int rssi);
+
+/* MBO functions */
+int wpas_mbo_ie(struct wpa_supplicant *wpa_s, u8 *buf, size_t len);
+const u8 * wpas_mbo_get_bss_attr(struct wpa_bss *bss, enum mbo_attr_id attr);
+int wpas_mbo_update_non_pref_chan(struct wpa_supplicant *wpa_s,
+ const char *non_pref_chan);
+void wpas_mbo_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ie);
+int wpas_mbo_supp_op_class_ie(struct wpa_supplicant *wpa_s, int freq, u8 *pos,
+ size_t len);
+void wpas_mbo_ie_trans_req(struct wpa_supplicant *wpa_s, const u8 *ie,
+ size_t len);
+size_t wpas_mbo_ie_bss_trans_reject(struct wpa_supplicant *wpa_s, u8 *pos,
+ size_t len,
+ enum mbo_transition_reject_reason reason);
+void wpas_mbo_update_cell_capa(struct wpa_supplicant *wpa_s, u8 mbo_cell_capa);
+struct wpabuf * mbo_build_anqp_buf(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss);
+
/**
* wpa_supplicant_ctrl_iface_ctrl_rsp_handle - Handle a control response
* @wpa_s: Pointer to wpa_supplicant data
void wpas_network_reenabled(void *eloop_ctx, void *timeout_ctx);
+void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s);
+struct wpa_supplicant * wpas_vendor_elem(struct wpa_supplicant *wpa_s,
+ enum wpa_vendor_elem_frame frame);
+int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
+ const u8 *elem, size_t len);
+
#ifdef CONFIG_FST
struct fst_wpa_obj;
#endif /* CONFIG_FST */
+int wpas_sched_scan_plans_set(struct wpa_supplicant *wpa_s, const char *cmd);
+
+struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
+ u16 num_modes, enum hostapd_hw_mode mode);
+
+void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ unsigned int sec);
+int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid);
+
+struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
+ int i, struct wpa_bss *bss,
+ struct wpa_ssid *group,
+ int only_first_ssid);
+
#endif /* WPA_SUPPLICANT_I_H */
return WPA_CTRL_REQ_SIM;
else if (os_strcmp(field, "PSK_PASSPHRASE") == 0)
return WPA_CTRL_REQ_PSK_PASSPHRASE;
+ else if (os_strcmp(field, "EXT_CERT_CHECK") == 0)
+ return WPA_CTRL_REQ_EXT_CERT_CHECK;
return WPA_CTRL_REQ_UNKNOWN;
}
*txt = "PSK or passphrase";
ret = "PSK_PASSPHRASE";
break;
+ case WPA_CTRL_REQ_EXT_CERT_CHECK:
+ *txt = "External server certificate validation";
+ ret = "EXT_CERT_CHECK";
+ break;
default:
break;
}
if (ssid == NULL)
return;
+ if (field == WPA_CTRL_REQ_EXT_CERT_CHECK)
+ ssid->eap.pending_ext_cert_check = PENDING_CHECK;
wpas_notify_network_request(wpa_s, ssid, field, default_txt);
field_name = wpa_supplicant_ctrl_req_to_string(field, default_txt,
wpa_drv_set_rekey_info(wpa_s, kek, kek_len, kck, kck_len, replay_ctr);
}
-#endif /* CONFIG_NO_WPA */
static int wpa_supplicant_key_mgmt_set_pmk(void *ctx, const u8 *pmk,
else
return 0;
}
+#endif /* CONFIG_NO_WPA */
int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
}
}
#endif /* CONFIG_P2P */
+ conf.wpa_rsc_relaxation = wpa_s->conf->wpa_rsc_relaxation;
}
wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL);
}
}
-static int wpas_set_current_cipher_suite(void *wpa_s, const u8 *cs,
- size_t cs_len)
+static int wpas_set_current_cipher_suite(void *wpa_s, u64 cs)
{
- return wpa_drv_set_current_cipher_suite(wpa_s, cs, cs_len);
+ return wpa_drv_set_current_cipher_suite(wpa_s, cs);
}
enum validate_frames vf,
enum confidentiality_offset co)
{
- return wpa_drv_create_receive_sc(wpa_s, channel, sci->addr, sci->port,
+ return wpa_drv_create_receive_sc(wpa_s, channel, sci->addr,
+ be_to_host16(sci->port),
conf_offset_val(co), vf);
}
const struct ieee802_1x_mka_sci *sci,
enum confidentiality_offset co)
{
- return wpa_drv_create_transmit_sc(wpa_s, channel, sci->addr, sci->port,
+ return wpa_drv_create_transmit_sc(wpa_s, channel, sci->addr,
+ be_to_host16(sci->port),
conf_offset_val(co));
}
#include "utils/includes.h"
#include "utils/common.h"
+#include "utils/module_tests.h"
#include "wpa_supplicant_i.h"
#include "blacklist.h"
ret = -1;
#ifdef CONFIG_WPS
- {
- int wps_module_tests(void);
- if (wps_module_tests() < 0)
- ret = -1;
- }
+ if (wps_module_tests() < 0)
+ ret = -1;
#endif /* CONFIG_WPS */
- {
- int utils_module_tests(void);
- if (utils_module_tests() < 0)
- ret = -1;
- }
-
- {
- int common_module_tests(void);
- if (common_module_tests() < 0)
- ret = -1;
- }
-
- {
- int crypto_module_tests(void);
- if (crypto_module_tests() < 0)
- ret = -1;
- }
+ if (utils_module_tests() < 0)
+ ret = -1;
+
+ if (common_module_tests() < 0)
+ ret = -1;
+
+ if (crypto_module_tests() < 0)
+ ret = -1;
return ret;
}
m2d->dev_password_id, m2d->config_error);
wpas_notify_wps_event_m2d(wpa_s, m2d);
#ifdef CONFIG_P2P
- if (wpa_s->parent && wpa_s->parent != wpa_s) {
- wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_M2D
+ if (wpa_s->p2pdev && wpa_s->p2pdev != wpa_s) {
+ wpa_msg(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_M2D
"dev_password_id=%d config_error=%d",
m2d->dev_password_id, m2d->config_error);
}
WPS_EVENT_FAIL "msg=%d config_error=%d reason=%d (%s)",
fail->msg, fail->config_error, fail->error_indication,
wps_ei_str(fail->error_indication));
- if (wpa_s->parent && wpa_s->parent != wpa_s)
- wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL
+ if (wpa_s->p2pdev && wpa_s->p2pdev != wpa_s)
+ wpa_msg(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_FAIL
"msg=%d config_error=%d reason=%d (%s)",
fail->msg, fail->config_error,
fail->error_indication,
wpa_msg(wpa_s, MSG_INFO,
WPS_EVENT_FAIL "msg=%d config_error=%d",
fail->msg, fail->config_error);
- if (wpa_s->parent && wpa_s->parent != wpa_s)
- wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL
+ if (wpa_s->p2pdev && wpa_s->p2pdev != wpa_s)
+ wpa_msg(wpa_s->p2pdev, MSG_INFO, WPS_EVENT_FAIL
"msg=%d config_error=%d",
fail->msg, fail->config_error);
}
}
+int wpas_wps_reenable_networks_pending(struct wpa_supplicant *wpa_s)
+{
+ return eloop_is_timeout_registered(wpas_wps_reenable_networks_cb,
+ wpa_s, NULL);
+}
+
+
static void wpa_supplicant_wps_event_success(struct wpa_supplicant *wpa_s)
{
wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_SUCCESS);
return -1;
ssid->temporary = 1;
ssid->p2p_group = p2p_group;
+ /*
+ * When starting a regular WPS process (not P2P group formation)
+ * the registrar/final station can be either AP or PCP
+ * so use a "don't care" value for the pbss flag.
+ */
+ if (!p2p_group)
+ ssid->pbss = 2;
#ifdef CONFIG_P2P
if (p2p_group && wpa_s->go_params && wpa_s->go_params->ssid_len) {
ssid->ssid = os_zalloc(wpa_s->go_params->ssid_len + 1);
ssid->ssid_len = wpa_s->go_params->ssid_len;
os_memcpy(ssid->ssid, wpa_s->go_params->ssid,
ssid->ssid_len);
+ if (wpa_s->go_params->freq > 56160) {
+ /* P2P in 60 GHz uses PBSS */
+ ssid->pbss = 1;
+ }
wpa_hexdump_ascii(MSG_DEBUG, "WPS: Use specific AP "
"SSID", ssid->ssid, ssid->ssid_len);
}
}
ssid->temporary = 1;
ssid->p2p_group = p2p_group;
+ /*
+ * When starting a regular WPS process (not P2P group formation)
+ * the registrar/final station can be either AP or PCP
+ * so use a "don't care" value for the pbss flag.
+ */
+ if (!p2p_group)
+ ssid->pbss = 2;
if (ssid_val) {
ssid->ssid = os_malloc(ssid_len);
if (ssid->ssid) {
ssid->ssid_len = wpa_s->go_params->ssid_len;
os_memcpy(ssid->ssid, wpa_s->go_params->ssid,
ssid->ssid_len);
+ if (wpa_s->go_params->freq > 56160) {
+ /* P2P in 60 GHz uses PBSS */
+ ssid->pbss = 1;
+ }
wpa_hexdump_ascii(MSG_DEBUG, "WPS: Use specific AP "
"SSID", ssid->ssid, ssid->ssid_len);
}
os_snprintf(val, sizeof(val), "\"dev_pw_id=%u%s\"",
dev_pw_id, hash);
} else {
- rpin = wps_generate_pin();
+ if (wps_generate_pin(&rpin) < 0) {
+ wpa_printf(MSG_DEBUG, "WPS: Could not generate PIN");
+ return -1;
+ }
os_snprintf(val, sizeof(val), "\"pin=%08d dev_pw_id=%u%s\"",
rpin, dev_pw_id, hash);
}
void wpas_wps_update_ap_info(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res);
void wpas_wps_notify_assoc(struct wpa_supplicant *wpa_s, const u8 *bssid);
+int wpas_wps_reenable_networks_pending(struct wpa_supplicant *wpa_s);
#else /* CONFIG_WPS */
{
}
+static inline int
+wpas_wps_reenable_networks_pending(struct wpa_supplicant *wpa_s)
+{
+ return 0;
+}
+
#endif /* CONFIG_WPS */
#endif /* WPS_SUPPLICANT_H */
# See README for more details.
import os
+import sys
import time
import wpaspy
wpas_ctrl = '/var/run/wpa_supplicant'
-def wpas_connect():
+def wpas_connect(host=None, port=9877):
ifaces = []
+
+ if host != None:
+ try:
+ wpas = wpaspy.Ctrl(host, port)
+ return wpas
+ except:
+ print "Could not connect to host: ", host
+ return None
+
if os.path.isdir(wpas_ctrl):
try:
ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)]
return None
-def main():
+def main(host=None, port=9877):
print "Testing wpa_supplicant control interface connection"
- wpas = wpas_connect()
+ wpas = wpas_connect(host, port)
if wpas is None:
return
print "Connected to wpa_supplicant"
print wpas.request('PING')
- mon = wpas_connect()
+ mon = wpas_connect(host, port)
if mon is None:
print "Could not open event monitor connection"
return
if __name__ == "__main__":
- main()
+ if len(sys.argv) > 2:
+ main(host=sys.argv[1], port=int(sys.argv[2]))
+ else:
+ main()
# See README for more details.
import os
+import stat
import socket
import select
counter = 0
class Ctrl:
- def __init__(self, path):
+ def __init__(self, path, port=9877):
global counter
self.started = False
self.attached = False
- self.s = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
- self.dest = path
- self.local = "/tmp/wpa_ctrl_" + str(os.getpid()) + '-' + str(counter)
- counter += 1
- self.s.bind(self.local)
+ self.path = path
+ self.port = port
+
try:
- self.s.connect(self.dest)
- except Exception, e:
- self.s.close()
- os.unlink(self.local)
- raise
+ mode = os.stat(path).st_mode
+ if stat.S_ISSOCK(mode):
+ self.udp = False
+ else:
+ self.udp = True
+ except:
+ self.udp = True
+
+ if not self.udp:
+ self.s = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
+ self.dest = path
+ self.local = "/tmp/wpa_ctrl_" + str(os.getpid()) + '-' + str(counter)
+ counter += 1
+ self.s.bind(self.local)
+ try:
+ self.s.connect(self.dest)
+ except Exception, e:
+ self.s.close()
+ os.unlink(self.local)
+ raise
+ else:
+ try:
+ self.s = None
+ ai_list = socket.getaddrinfo(path, port, socket.AF_INET,
+ socket.SOCK_DGRAM)
+ for af, socktype, proto, cn, sockaddr in ai_list:
+ self.sockaddr = sockaddr
+ break
+ self.s = socket.socket(af, socktype)
+ self.s.settimeout(5)
+ self.s.sendto("GET_COOKIE", sockaddr)
+ reply, server = self.s.recvfrom(4096)
+ self.cookie = reply
+ self.port = port
+ except:
+ print "connect exception ", path, str(port)
+ if self.s != None:
+ self.s.close()
+ raise
self.started = True
def __del__(self):
pass
if self.started:
self.s.close()
- os.unlink(self.local)
+ if not self.udp:
+ os.unlink(self.local)
self.started = False
def request(self, cmd, timeout=10):
- self.s.send(cmd)
+ if self.udp:
+ self.s.sendto(self.cookie + cmd, self.sockaddr)
+ else:
+ self.s.send(cmd)
[r, w, e] = select.select([self.s], [], [], timeout)
if r:
return self.s.recv(4096)
return None
raise Exception("DETACH failed")
+ def terminate(self):
+ if self.attached:
+ try:
+ self.detach()
+ except Exception, e:
+ # Need to ignore this to allow the socket to be closed
+ self.attached = False
+ self.request("TERMINATE")
+ self.close()
+
def pending(self, timeout=0):
[r, w, e] = select.select([self.s], [], [], timeout)
if r:
--- /dev/null
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQC+HobkeQPB0ZTV1LOxKJB2+7imzW0c0Uj0CJpn//mmVLEZKd8p
+G83xb2YB59t5zsA5KiUTJpQMLHtaLIEPlO5R0HXmRtsXRqcViw5XD7BUdmMSyoYY
+vBrDFsBwCdZrQzm4mClGrMtqrTiIOwfcgc069h32L+8d166KttHnsxUCuQIDAQAB
+AoGAEPKDr8Yh0ZsvG0iUpAwrpI+XzDavrUvypt5FdVPaGzudddLHs9BosUbu3uie
+JeOKOw5Is8ZSmCs267jf4FW0UKtgpnHGK2H0ba0iramzz07oK48V4y7C7nS3eJr/
+Oen6H9BW4DNXreFZ5yTRFOiQ4eD1pHqR/M/bBieDfRjakgECQQDfgiYYInio4TmM
+9q/h1q5T1bGgajz5U4GInd0K2diNqVoGhSTAyRRGauH+68tPQuX7WCM1VE/lZfZL
+4/dlOaRhAkEA2cHNkrFh4CAlXgtCub+psmT032AIFDEpNNT0K22XIE8savYNqs8w
+aGPurrwGQflxCB19boiaKEcW5FQDkff9WQJAbUznNiw9V1D05OOKNWXX0HWTLMBn
+WwIkOVwByZmo1fX4aXHY/FIZESqZpCFJRlSPxS9f4Gd/vs3y+T/dLupWYQJAJDGX
+RrOfDg6px1jdzVvzC8jF/r7KePi23aYrs3Ayt1cRjfG50dNAO4moqXhtHdglFnE4
+YP/ph5pRTsA8G635eQJBAKbh0zB4HqFI2PmnKsShFBPNkK5x17nAZlYNJf2Ip4Ii
+2Gjxyx4H0iBVgFYLsLB6hRBkOPpx6Jl8mJXOtFXb8lE=
+-----END RSA PRIVATE KEY-----
--- /dev/null
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 15624081837803162867 (0xd8d3e3a6cbe3ccf3)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=FI, O=w1.fi, CN=Root CA
+ Validity
+ Not Before: Dec 23 19:37:36 2015 GMT
+ Not After : Dec 22 19:37:36 2025 GMT
+ Subject: C=FI, O=w1.fi, CN=Server Intermediate CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:de:58:ac:e3:d8:7e:40:f6:84:2a:49:24:49:5a:
+ f7:c8:23:08:b9:6c:d9:07:01:69:8f:77:28:71:42:
+ a2:eb:ae:86:10:c6:31:61:9a:14:88:44:0a:68:bf:
+ 6e:a2:46:41:e9:6f:a2:89:fb:0b:f3:e1:b8:30:bf:
+ e5:80:5e:f9:61:8d:6e:ac:e2:f7:28:e7:9e:44:28:
+ b8:e4:6e:87:76:a9:d7:ac:ed:11:3f:de:c3:dd:41:
+ c3:45:82:09:c3:a7:4c:e6:df:2b:88:1e:44:ce:e2:
+ a7:29:53:f6:13:96:ad:6c:2e:93:00:28:42:77:bc:
+ 73:6e:86:e7:5b:e8:eb:e9:37:1d:63:e7:ea:05:5a:
+ 71:28:f0:81:0b:4c:3f:dd:73:f8:db:13:a8:f0:5f:
+ 6f:6f:e5:1b:c7:94:7f:57:c5:dc:66:26:0c:5a:71:
+ 7a:e3:d2:3e:7a:a6:59:46:03:61:78:89:84:3d:ef:
+ 22:9c:f8:c2:22:75:c4:0c:ef:fb:e4:fa:6f:b8:11:
+ db:aa:92:9b:6c:23:4e:6e:e5:55:d2:41:47:18:95:
+ c6:7d:17:be:6d:ab:39:a1:38:61:fd:f9:22:95:69:
+ f3:9e:28:fd:8a:c8:58:72:3c:91:c2:22:d9:fb:b2:
+ 54:0f:9a:17:27:88:df:60:f5:de:fc:95:9f:25:c6:
+ 64:81
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 84:09:8B:55:1F:7D:2F:0F:28:D7:9C:EC:54:4E:9F:11:97:55:D9:B9
+ X509v3 Authority Key Identifier:
+ keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:0
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ bd:22:63:3d:a7:e5:ce:c9:f5:66:1f:77:5f:d5:24:e3:68:dc:
+ a4:07:80:3e:5e:b1:2c:96:88:39:ad:00:4c:aa:9d:0b:ed:f3:
+ 6d:df:9d:2f:97:d2:77:8b:ba:d0:9c:0f:a6:5e:60:b8:0f:e1:
+ 96:b1:61:25:48:69:81:64:a8:5c:82:58:0b:f3:d0:a9:4e:8b:
+ 90:fc:2f:67:57:da:72:dc:3c:eb:c2:20:19:05:8d:42:0d:14:
+ cf:00:db:59:00:ea:f0:76:3e:ca:85:b1:05:e5:b8:5f:0b:46:
+ c7:3c:a1:d9:5c:4d:b9:24:e7:d6:2b:3d:0d:eb:c3:88:d8:3a:
+ f6:60
+-----BEGIN CERTIFICATE-----
+MIIC1TCCAj6gAwIBAgIJANjT46bL48zzMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNTEy
+MjMxOTM3MzZaFw0yNTEyMjIxOTM3MzZaMD4xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
+DAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVybWVkaWF0ZSBDQTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBAN5YrOPYfkD2hCpJJEla98gjCLls2QcB
+aY93KHFCouuuhhDGMWGaFIhECmi/bqJGQelvoon7C/PhuDC/5YBe+WGNbqzi9yjn
+nkQouORuh3ap16ztET/ew91Bw0WCCcOnTObfK4geRM7ipylT9hOWrWwukwAoQne8
+c26G51vo6+k3HWPn6gVacSjwgQtMP91z+NsTqPBfb2/lG8eUf1fF3GYmDFpxeuPS
+PnqmWUYDYXiJhD3vIpz4wiJ1xAzv++T6b7gR26qSm2wjTm7lVdJBRxiVxn0Xvm2r
+OaE4Yf35IpVp854o/YrIWHI8kcIi2fuyVA+aFyeI32D13vyVnyXGZIECAwEAAaNm
+MGQwHQYDVR0OBBYEFIQJi1UffS8PKNec7FROnxGXVdm5MB8GA1UdIwQYMBaAFLiS
+3v2KGLMww59V8zNdtMgpikEUMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/
+BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4GBAL0iYz2n5c7J9WYfd1/VJONo3KQHgD5e
+sSyWiDmtAEyqnQvt823fnS+X0neLutCcD6ZeYLgP4ZaxYSVIaYFkqFyCWAvz0KlO
+i5D8L2dX2nLcPOvCIBkFjUINFM8A21kA6vB2PsqFsQXluF8LRsc8odlcTbkk59Yr
+PQ3rw4jYOvZg
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 15624081837803162817 (0xd8d3e3a6cbe3ccc1)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=FI, O=w1.fi, CN=Root CA
+ Validity
+ Not Before: Jun 29 16:41:22 2013 GMT
+ Not After : Jun 27 16:41:22 2023 GMT
+ Subject: C=FI, O=w1.fi, CN=Root CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:be:1e:86:e4:79:03:c1:d1:94:d5:d4:b3:b1:28:
+ 90:76:fb:b8:a6:cd:6d:1c:d1:48:f4:08:9a:67:ff:
+ f9:a6:54:b1:19:29:df:29:1b:cd:f1:6f:66:01:e7:
+ db:79:ce:c0:39:2a:25:13:26:94:0c:2c:7b:5a:2c:
+ 81:0f:94:ee:51:d0:75:e6:46:db:17:46:a7:15:8b:
+ 0e:57:0f:b0:54:76:63:12:ca:86:18:bc:1a:c3:16:
+ c0:70:09:d6:6b:43:39:b8:98:29:46:ac:cb:6a:ad:
+ 38:88:3b:07:dc:81:cd:3a:f6:1d:f6:2f:ef:1d:d7:
+ ae:8a:b6:d1:e7:b3:15:02:b9
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14
+ X509v3 Authority Key Identifier:
+ keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 1a:cf:77:60:44:43:c4:55:0e:99:e0:89:aa:b9:d3:7b:32:b7:
+ 5c:9c:7c:ca:fe:8c:d4:94:c6:5e:f3:83:19:5f:29:59:68:a4:
+ 4f:dc:04:2e:b8:71:c0:6d:3b:ae:01:e4:b9:88:99:cc:ce:82:
+ be:6a:28:c2:ac:6a:94:c6:87:90:ed:85:3c:10:71:c5:ff:3c:
+ 70:64:e2:41:62:31:ea:86:7b:11:8c:93:ea:c6:f3:f3:4e:f9:
+ d4:f2:81:90:d7:f4:fa:a1:91:6e:d4:dd:15:3e:26:3b:ac:1e:
+ c3:c2:1f:ed:bb:34:bf:cb:b2:67:c6:c6:51:e8:51:22:b4:f3:
+ 92:e8
+-----BEGIN CERTIFICATE-----
+MIICLDCCAZWgAwIBAgIJANjT46bL48zBMA0GCSqGSIb3DQEBBQUAMC8xCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xMzA2
+MjkxNjQxMjJaFw0yMzA2MjcxNjQxMjJaMC8xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
+DAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAvh6G5HkDwdGU1dSzsSiQdvu4ps1tHNFI9AiaZ//5plSxGSnfKRvN8W9m
+Aefbec7AOSolEyaUDCx7WiyBD5TuUdB15kbbF0anFYsOVw+wVHZjEsqGGLwawxbA
+cAnWa0M5uJgpRqzLaq04iDsH3IHNOvYd9i/vHdeuirbR57MVArkCAwEAAaNQME4w
+HQYDVR0OBBYEFLiS3v2KGLMww59V8zNdtMgpikEUMB8GA1UdIwQYMBaAFLiS3v2K
+GLMww59V8zNdtMgpikEUMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEA
+Gs93YERDxFUOmeCJqrnTezK3XJx8yv6M1JTGXvODGV8pWWikT9wELrhxwG07rgHk
+uYiZzM6CvmoowqxqlMaHkO2FPBBxxf88cGTiQWIx6oZ7EYyT6sbz80751PKBkNf0
++qGRbtTdFT4mO6wew8If7bs0v8uyZ8bGUehRIrTzkug=
+-----END CERTIFICATE-----
--- /dev/null
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 15624081837803162867 (0xd8d3e3a6cbe3ccf3)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=FI, O=w1.fi, CN=Root CA
+ Validity
+ Not Before: Dec 23 19:37:36 2015 GMT
+ Not After : Dec 22 19:37:36 2025 GMT
+ Subject: C=FI, O=w1.fi, CN=Server Intermediate CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:de:58:ac:e3:d8:7e:40:f6:84:2a:49:24:49:5a:
+ f7:c8:23:08:b9:6c:d9:07:01:69:8f:77:28:71:42:
+ a2:eb:ae:86:10:c6:31:61:9a:14:88:44:0a:68:bf:
+ 6e:a2:46:41:e9:6f:a2:89:fb:0b:f3:e1:b8:30:bf:
+ e5:80:5e:f9:61:8d:6e:ac:e2:f7:28:e7:9e:44:28:
+ b8:e4:6e:87:76:a9:d7:ac:ed:11:3f:de:c3:dd:41:
+ c3:45:82:09:c3:a7:4c:e6:df:2b:88:1e:44:ce:e2:
+ a7:29:53:f6:13:96:ad:6c:2e:93:00:28:42:77:bc:
+ 73:6e:86:e7:5b:e8:eb:e9:37:1d:63:e7:ea:05:5a:
+ 71:28:f0:81:0b:4c:3f:dd:73:f8:db:13:a8:f0:5f:
+ 6f:6f:e5:1b:c7:94:7f:57:c5:dc:66:26:0c:5a:71:
+ 7a:e3:d2:3e:7a:a6:59:46:03:61:78:89:84:3d:ef:
+ 22:9c:f8:c2:22:75:c4:0c:ef:fb:e4:fa:6f:b8:11:
+ db:aa:92:9b:6c:23:4e:6e:e5:55:d2:41:47:18:95:
+ c6:7d:17:be:6d:ab:39:a1:38:61:fd:f9:22:95:69:
+ f3:9e:28:fd:8a:c8:58:72:3c:91:c2:22:d9:fb:b2:
+ 54:0f:9a:17:27:88:df:60:f5:de:fc:95:9f:25:c6:
+ 64:81
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 84:09:8B:55:1F:7D:2F:0F:28:D7:9C:EC:54:4E:9F:11:97:55:D9:B9
+ X509v3 Authority Key Identifier:
+ keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:0
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ bd:22:63:3d:a7:e5:ce:c9:f5:66:1f:77:5f:d5:24:e3:68:dc:
+ a4:07:80:3e:5e:b1:2c:96:88:39:ad:00:4c:aa:9d:0b:ed:f3:
+ 6d:df:9d:2f:97:d2:77:8b:ba:d0:9c:0f:a6:5e:60:b8:0f:e1:
+ 96:b1:61:25:48:69:81:64:a8:5c:82:58:0b:f3:d0:a9:4e:8b:
+ 90:fc:2f:67:57:da:72:dc:3c:eb:c2:20:19:05:8d:42:0d:14:
+ cf:00:db:59:00:ea:f0:76:3e:ca:85:b1:05:e5:b8:5f:0b:46:
+ c7:3c:a1:d9:5c:4d:b9:24:e7:d6:2b:3d:0d:eb:c3:88:d8:3a:
+ f6:60
+-----BEGIN CERTIFICATE-----
+MIIC1TCCAj6gAwIBAgIJANjT46bL48zzMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNTEy
+MjMxOTM3MzZaFw0yNTEyMjIxOTM3MzZaMD4xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
+DAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVybWVkaWF0ZSBDQTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBAN5YrOPYfkD2hCpJJEla98gjCLls2QcB
+aY93KHFCouuuhhDGMWGaFIhECmi/bqJGQelvoon7C/PhuDC/5YBe+WGNbqzi9yjn
+nkQouORuh3ap16ztET/ew91Bw0WCCcOnTObfK4geRM7ipylT9hOWrWwukwAoQne8
+c26G51vo6+k3HWPn6gVacSjwgQtMP91z+NsTqPBfb2/lG8eUf1fF3GYmDFpxeuPS
+PnqmWUYDYXiJhD3vIpz4wiJ1xAzv++T6b7gR26qSm2wjTm7lVdJBRxiVxn0Xvm2r
+OaE4Yf35IpVp854o/YrIWHI8kcIi2fuyVA+aFyeI32D13vyVnyXGZIECAwEAAaNm
+MGQwHQYDVR0OBBYEFIQJi1UffS8PKNec7FROnxGXVdm5MB8GA1UdIwQYMBaAFLiS
+3v2KGLMww59V8zNdtMgpikEUMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/
+BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4GBAL0iYz2n5c7J9WYfd1/VJONo3KQHgD5e
+sSyWiDmtAEyqnQvt823fnS+X0neLutCcD6ZeYLgP4ZaxYSVIaYFkqFyCWAvz0KlO
+i5D8L2dX2nLcPOvCIBkFjUINFM8A21kA6vB2PsqFsQXluF8LRsc8odlcTbkk59Yr
+PQ3rw4jYOvZg
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN CERTIFICATE REQUEST-----
+MIICljCCAX4CAQAwUTELMAkGA1UEBhMCRkkxETAPBgNVBAcMCEhlbHNpbmtpMQ4w
+DAYDVQQKDAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVybWVkaWF0ZSBDQTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN5YrOPYfkD2hCpJJEla98gj
+CLls2QcBaY93KHFCouuuhhDGMWGaFIhECmi/bqJGQelvoon7C/PhuDC/5YBe+WGN
+bqzi9yjnnkQouORuh3ap16ztET/ew91Bw0WCCcOnTObfK4geRM7ipylT9hOWrWwu
+kwAoQne8c26G51vo6+k3HWPn6gVacSjwgQtMP91z+NsTqPBfb2/lG8eUf1fF3GYm
+DFpxeuPSPnqmWUYDYXiJhD3vIpz4wiJ1xAzv++T6b7gR26qSm2wjTm7lVdJBRxiV
+xn0Xvm2rOaE4Yf35IpVp854o/YrIWHI8kcIi2fuyVA+aFyeI32D13vyVnyXGZIEC
+AwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQCdd8AniQQQA4urnrqdR9hQlFY5JxUU
+OtGqkRGb8pTJAfxU8hgmAhbHmPw7qhNnZNqr2i/p8A1UcwCuU7Sx2StszIjyuEQJ
+SteaUpvLUWM/KrlqBH4VTcHFGsZWEJ+gMhBJwJuET6mtZFdm84HALJClIysx973p
+d6i92H93ew3RuMF/erMnCPNjt0Pe8QWU/tpwsVD/SBGbqg8PCShqySNO9P+P1pAb
+wIPInq3ox2E6RStFnIY8MES5sTUFWAxh3MNYY8OuVcuun2R0Yk0jy/wmmaWzcXS+
+sOj48LNyptGk8SAS1Yxu8lUfj3p77eZZqUqLorj/hdoqfnMOnCx7NOww
+-----END CERTIFICATE REQUEST-----
--- /dev/null
+V 251220193736Z 8020A0407F798AB8 unknown /C=FI/O=w1.fi/CN=server.w1.fi
+R 251220193736Z 151223193736Z 8020A0407F798AB9 unknown /C=FI/O=w1.fi/CN=server-revoked.w1.fi
--- /dev/null
+unique_subject = yes
--- /dev/null
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 9232555434986539704 (0x8020a0407f798ab8)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=FI, O=w1.fi, CN=Server Intermediate CA
+ Validity
+ Not Before: Dec 23 19:37:36 2015 GMT
+ Not After : Dec 20 19:37:36 2025 GMT
+ Subject: C=FI, O=w1.fi, CN=server.w1.fi
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:e4:88:a5:93:02:5b:bc:54:68:46:fa:73:7d:33:
+ 30:47:45:5c:49:5f:3c:51:5f:9b:fe:c5:14:10:26:
+ 3d:0f:e3:c2:b2:17:84:d3:3e:12:a8:b2:7b:02:1a:
+ 8a:8b:e9:f4:41:1e:fc:f3:49:2d:c6:d4:88:27:81:
+ d0:86:f3:b9:c0:0a:2a:28:45:00:32:c3:18:22:f6:
+ 99:37:f1:74:8d:ac:54:47:73:e5:b6:d3:e7:f8:80:
+ 99:75:f5:19:19:eb:19:70:df:92:53:b1:61:38:ff:
+ 7f:cf:8b:bd:e1:7f:50:5b:d0:95:30:a3:37:6b:8a:
+ 72:06:a7:e8:39:e2:a4:78:43:98:91:cd:30:88:34:
+ 5b:aa:9e:a2:9f:26:d5:e1:5b:86:4d:01:a4:c2:65:
+ cd:27:94:be:e2:f5:73:5d:c4:60:98:f1:75:11:94:
+ 09:0d:9d:04:7f:ef:1a:9d:5f:f0:4a:3f:88:d7:76:
+ 2e:9b:d6:2a:c6:94:09:37:0a:37:24:92:91:9d:18:
+ 0f:ea:4e:d4:e4:9d:45:38:5a:ba:d8:df:b6:15:6f:
+ ac:ff:6c:41:ac:d7:c0:0a:55:ec:81:ca:9a:59:40:
+ 55:8b:a4:77:13:df:fa:c3:b5:ee:ef:87:41:8d:94:
+ d0:c0:96:41:b4:3a:04:b6:6b:6a:56:93:f4:67:7e:
+ 27:e1
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Subject Key Identifier:
+ 4B:81:85:B4:88:41:0D:D4:15:D3:48:0E:F4:A9:99:14:2D:B1:DB:93
+ X509v3 Authority Key Identifier:
+ keyid:84:09:8B:55:1F:7D:2F:0F:28:D7:9C:EC:54:4E:9F:11:97:55:D9:B9
+
+ X509v3 Subject Alternative Name: critical
+ DNS:server.w1.fi
+ X509v3 Extended Key Usage: critical
+ TLS Web Server Authentication
+ X509v3 Key Usage:
+ Digital Signature, Key Encipherment
+ Signature Algorithm: sha256WithRSAEncryption
+ 49:2a:14:22:16:2c:12:f5:4e:06:f3:c2:1e:ac:54:07:5d:86:
+ 16:3e:6c:a0:73:e1:a6:d7:c3:49:1f:80:0d:b6:54:22:77:ce:
+ 39:dd:f6:f6:9f:62:ff:d5:27:7f:c3:92:73:b9:a7:ce:87:5a:
+ e3:bc:52:b3:0a:99:eb:91:56:b6:78:01:c3:0e:4b:ca:8a:04:
+ ee:5c:56:05:ef:7a:cb:21:f9:eb:8a:38:12:50:c7:6e:a8:1f:
+ 0e:81:81:a6:2d:ea:35:94:24:db:76:77:df:ea:41:4c:af:7e:
+ 29:9d:d5:e6:e3:12:78:19:92:ed:35:b9:99:19:a9:d6:cb:f8:
+ a7:21:fb:8e:a7:39:dc:e1:ab:3d:ba:12:87:ba:1c:08:e6:8a:
+ 21:96:44:44:8a:61:0f:70:00:d0:cb:63:93:a4:fa:cc:75:a3:
+ fd:e8:af:33:24:80:4a:d9:b9:2a:a1:20:0b:62:0b:17:6c:9a:
+ 7c:8b:fd:9e:ff:be:b2:51:5e:e9:3a:cc:28:22:63:44:69:7f:
+ 6d:1f:08:14:a4:32:d0:1f:f9:c3:8d:28:1a:76:12:00:3c:b3:
+ 38:13:ca:67:17:79:c6:de:5d:b7:9d:f8:e3:64:f7:b3:a0:5c:
+ e5:6e:fc:10:f3:53:d6:70:38:c2:6f:87:ab:07:1c:64:ff:30:
+ d8:3a:1e:75
+-----BEGIN CERTIFICATE-----
+MIIDiDCCAnCgAwIBAgIJAIAgoEB/eYq4MA0GCSqGSIb3DQEBCwUAMD4xCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVybWVk
+aWF0ZSBDQTAeFw0xNTEyMjMxOTM3MzZaFw0yNTEyMjAxOTM3MzZaMDQxCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEVMBMGA1UEAwwMc2VydmVyLncxLmZpMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5IilkwJbvFRoRvpzfTMwR0Vc
+SV88UV+b/sUUECY9D+PCsheE0z4SqLJ7AhqKi+n0QR7880ktxtSIJ4HQhvO5wAoq
+KEUAMsMYIvaZN/F0jaxUR3PlttPn+ICZdfUZGesZcN+SU7FhOP9/z4u94X9QW9CV
+MKM3a4pyBqfoOeKkeEOYkc0wiDRbqp6inybV4VuGTQGkwmXNJ5S+4vVzXcRgmPF1
+EZQJDZ0Ef+8anV/wSj+I13Yum9YqxpQJNwo3JJKRnRgP6k7U5J1FOFq62N+2FW+s
+/2xBrNfAClXsgcqaWUBVi6R3E9/6w7Xu74dBjZTQwJZBtDoEtmtqVpP0Z34n4QID
+AQABo4GSMIGPMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFEuBhbSIQQ3UFdNIDvSp
+mRQtsduTMB8GA1UdIwQYMBaAFIQJi1UffS8PKNec7FROnxGXVdm5MBoGA1UdEQEB
+/wQQMA6CDHNlcnZlci53MS5maTAWBgNVHSUBAf8EDDAKBggrBgEFBQcDATALBgNV
+HQ8EBAMCBaAwDQYJKoZIhvcNAQELBQADggEBAEkqFCIWLBL1Tgbzwh6sVAddhhY+
+bKBz4abXw0kfgA22VCJ3zjnd9vafYv/VJ3/DknO5p86HWuO8UrMKmeuRVrZ4AcMO
+S8qKBO5cVgXvessh+euKOBJQx26oHw6BgaYt6jWUJNt2d9/qQUyvfimd1ebjEngZ
+ku01uZkZqdbL+Kch+46nOdzhqz26Eoe6HAjmiiGWRESKYQ9wANDLY5Ok+sx1o/3o
+rzMkgErZuSqhIAtiCxdsmnyL/Z7/vrJRXuk6zCgiY0Rpf20fCBSkMtAf+cONKBp2
+EgA8szgTymcXecbeXbed+ONk97OgXOVu/BDzU9ZwOMJvh6sHHGT/MNg6HnU=
+-----END CERTIFICATE-----
--- /dev/null
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 9232555434986539705 (0x8020a0407f798ab9)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=FI, O=w1.fi, CN=Server Intermediate CA
+ Validity
+ Not Before: Dec 23 19:37:36 2015 GMT
+ Not After : Dec 20 19:37:36 2025 GMT
+ Subject: C=FI, O=w1.fi, CN=server-revoked.w1.fi
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:ac:5c:ae:06:36:4a:65:e0:db:0b:3c:28:13:08:
+ 8b:90:66:43:6f:c8:b2:3b:fa:41:bd:1a:10:10:fb:
+ e9:05:6a:ba:42:90:4d:2e:cf:b1:b9:c3:73:f5:fc:
+ ac:4c:18:e9:44:73:69:5e:2d:83:63:d1:29:e5:59:
+ 55:a8:bf:b0:1c:7a:0d:17:18:b0:38:21:af:cb:6d:
+ a9:6b:9d:a2:88:0e:1c:ee:1a:a5:9f:3c:27:ea:fe:
+ 8f:9b:94:df:12:3c:34:bb:bf:6c:d0:6c:6b:46:ad:
+ bc:ff:88:ae:d8:4d:8b:9f:34:50:25:c4:96:be:25:
+ 42:06:c8:b3:8e:21:a5:fd:a3:82:f9:74:78:46:56:
+ 8d:0b:f0:c4:fa:1a:0e:f5:34:22:53:fd:43:37:a3:
+ 47:fd:9f:a2:bc:d0:60:25:a8:db:93:f7:0c:88:fe:
+ 79:52:f2:07:f1:de:fc:66:6e:fe:da:10:76:6c:d0:
+ 87:8c:ef:dd:40:6d:82:7c:d1:39:b2:17:d6:07:cf:
+ 1a:5a:39:12:ed:49:4f:d9:c7:91:40:ab:73:f7:54:
+ 3c:a5:7d:9f:bb:0c:47:77:0e:d9:61:e5:1b:14:65:
+ 4e:38:c5:a7:8a:ee:32:be:05:25:94:a0:7f:96:09:
+ 59:1b:04:08:42:6b:50:6b:95:7a:78:f6:ec:f4:f6:
+ 4d:43
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Subject Key Identifier:
+ 0D:49:37:45:42:77:90:25:BA:9B:67:DB:F6:DC:61:D2:53:5B:C6:BC
+ X509v3 Authority Key Identifier:
+ keyid:84:09:8B:55:1F:7D:2F:0F:28:D7:9C:EC:54:4E:9F:11:97:55:D9:B9
+
+ X509v3 Subject Alternative Name: critical
+ DNS:server-revoked.w1.fi
+ X509v3 Extended Key Usage: critical
+ TLS Web Server Authentication
+ X509v3 Key Usage:
+ Digital Signature, Key Encipherment
+ Signature Algorithm: sha256WithRSAEncryption
+ 22:c6:72:08:84:a9:e9:19:77:ea:6a:06:68:43:8b:e7:72:af:
+ 9c:a2:47:b9:6f:b6:cb:11:17:89:0a:42:52:14:58:9e:3c:01:
+ fd:e7:fc:a2:0d:85:a5:b5:8c:27:d5:5e:b2:47:05:05:f9:56:
+ b6:0b:e2:28:f3:1d:75:5e:13:eb:ec:a0:76:2b:d9:ed:99:84:
+ 08:6d:64:71:13:b6:02:81:b3:c2:7e:b8:b6:00:98:4f:26:ea:
+ f1:67:5b:35:2a:26:d0:ca:a8:fb:eb:21:fb:f1:d6:5a:63:42:
+ 01:5f:b3:59:3d:f8:e0:4d:94:3a:3a:82:46:02:9d:81:2c:ef:
+ e5:46:c7:99:f4:2f:43:ad:85:fc:2c:ca:0b:6b:48:01:ac:d7:
+ f7:da:0e:16:c4:10:18:14:83:9c:85:90:75:ef:66:9f:65:42:
+ e5:e7:8c:16:ac:f6:60:61:d7:5f:a0:21:cd:8a:85:d4:a0:f2:
+ 8e:17:0e:38:5e:31:12:ac:24:b5:67:61:9d:15:84:0b:fc:84:
+ 8a:d4:29:90:3d:4b:23:48:19:6b:f7:26:1f:fe:b9:b9:f1:6e:
+ 70:ac:ec:31:60:be:7d:6f:58:7e:c1:47:61:a7:b0:4b:b2:fd:
+ 62:06:c5:97:43:28:39:a5:c5:60:51:c0:46:9d:6b:e4:1a:ed:
+ 0c:a6:51:8a
+-----BEGIN CERTIFICATE-----
+MIIDmDCCAoCgAwIBAgIJAIAgoEB/eYq5MA0GCSqGSIb3DQEBCwUAMD4xCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVybWVk
+aWF0ZSBDQTAeFw0xNTEyMjMxOTM3MzZaFw0yNTEyMjAxOTM3MzZaMDwxCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEdMBsGA1UEAwwUc2VydmVyLXJldm9rZWQu
+dzEuZmkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsXK4GNkpl4NsL
+PCgTCIuQZkNvyLI7+kG9GhAQ++kFarpCkE0uz7G5w3P1/KxMGOlEc2leLYNj0Snl
+WVWov7Aceg0XGLA4Ia/LbalrnaKIDhzuGqWfPCfq/o+blN8SPDS7v2zQbGtGrbz/
+iK7YTYufNFAlxJa+JUIGyLOOIaX9o4L5dHhGVo0L8MT6Gg71NCJT/UM3o0f9n6K8
+0GAlqNuT9wyI/nlS8gfx3vxmbv7aEHZs0IeM791AbYJ80TmyF9YHzxpaORLtSU/Z
+x5FAq3P3VDylfZ+7DEd3Dtlh5RsUZU44xaeK7jK+BSWUoH+WCVkbBAhCa1BrlXp4
+9uz09k1DAgMBAAGjgZowgZcwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUDUk3RUJ3
+kCW6m2fb9txh0lNbxrwwHwYDVR0jBBgwFoAUhAmLVR99Lw8o15zsVE6fEZdV2bkw
+IgYDVR0RAQH/BBgwFoIUc2VydmVyLXJldm9rZWQudzEuZmkwFgYDVR0lAQH/BAww
+CgYIKwYBBQUHAwEwCwYDVR0PBAQDAgWgMA0GCSqGSIb3DQEBCwUAA4IBAQAixnII
+hKnpGXfqagZoQ4vncq+coke5b7bLEReJCkJSFFiePAH95/yiDYWltYwn1V6yRwUF
++Va2C+Io8x11XhPr7KB2K9ntmYQIbWRxE7YCgbPCfri2AJhPJurxZ1s1KibQyqj7
+6yH78dZaY0IBX7NZPfjgTZQ6OoJGAp2BLO/lRseZ9C9DrYX8LMoLa0gBrNf32g4W
+xBAYFIOchZB172afZULl54wWrPZgYddfoCHNioXUoPKOFw44XjESrCS1Z2GdFYQL
+/ISK1CmQPUsjSBlr9yYf/rm58W5wrOwxYL59b1h+wUdhp7BLsv1iBsWXQyg5pcVg
+UcBGnWvkGu0MplGK
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDeWKzj2H5A9oQq
+SSRJWvfIIwi5bNkHAWmPdyhxQqLrroYQxjFhmhSIRApov26iRkHpb6KJ+wvz4bgw
+v+WAXvlhjW6s4vco555EKLjkbod2qdes7RE/3sPdQcNFggnDp0zm3yuIHkTO4qcp
+U/YTlq1sLpMAKEJ3vHNuhudb6OvpNx1j5+oFWnEo8IELTD/dc/jbE6jwX29v5RvH
+lH9XxdxmJgxacXrj0j56pllGA2F4iYQ97yKc+MIidcQM7/vk+m+4EduqkptsI05u
+5VXSQUcYlcZ9F75tqzmhOGH9+SKVafOeKP2KyFhyPJHCItn7slQPmhcniN9g9d78
+lZ8lxmSBAgMBAAECggEAYEOYJtVWZB3WvtAH69J8sKOqZU1g8Q2FfF2kntSw4MUg
+uiZ0vsMM3KpIr20iIxOz+bMhdgfA9wfkzQZoAJod8kRfhG6Hf6g3916CHjRUZeXG
+wNGqxDJYLnUIbBGO1KycOOCqYjZoqAGtSdFWGskDsHDBqDHGBT0L5PB3Pm2rpb4u
+JQV2Dcvqjf8MfDBGsyKx7+L+EtMXhcgUCQ4vRtvCvNV+Xl4wL37l1/OkfIPTWkQE
+FpkBMy+/cvB8H6rmlAxp6t8EV9rbgyt9OW86+gf1q4U7VM6VUXFGjFvGwji9OkgA
+UnwrdX0IryG/ruuKzIb6eBEb5hRoluGqHphptiX8IQKBgQD5/QazeInpiHkfZpm5
+obgLYtLHkQuewVIZVFhVAle07AaZ2748lRMu/UHo0YITS1mLK8AA7xVi+NjwIbg0
+WpoBQ4V6k7U/+PfLygFYbTB+vTreH6Za/zIpEXjYudemt5Xgjva+YEM5/rYNkNgH
+d0Dcbuq1D5OgsEWs/S3jlPzWJQKBgQDjsXrj1wO8yYokv9kGETVN9604lYFNfTnD
+HwAcEanCa+Ist6TpMZOK7QV78rmR5bxymLKI6UPCvrdqhLb+BuTl2GrSvrSeNwk4
+zAHi25MapTQxssJMtom88htbBIJ/P+0iEXKKXIRzIi0UXRNfoE5lwQZlHUdFHtlK
+xUvnrgXALQKBgQCva2JcZeVAvsdfxXtxy41+T+Zgq+Nfj4CwzYL+hBpPlqA7Lvub
+P3CqtISffwSrzWAUTKr6/MohHUX9m2vLMRiIcn0juqqhLW+UzTeMeXJiPR8l50ew
+6wqjzuLiEebF0mWVojx68sm51IajllRBSOl2xU5lp3yMcaUy8qZU4KNbEQKBgBnu
+lLhuPJa7vWgCEY2HWDLRCoFvRZK1uGZomXKY8GScNN4y7C1C4DLqW72KH2hmadgD
+XBILvxPm9KzFALJdxqQGyePGpHuAeSRm17AmodJfDlq6qTZjc7x5NnRfRx2HAlLm
++cyYTN1v/wJat2Ikt8kO+tN5SiytHsJNRh/UygLhAoGAXctGrFNl7a/cg0b7zr8O
+0t7UcaqXRpYHFTOaijL3WkI7Ps4us14lmkWvkM1iUjCyPtBCRNeYXu5HxENIn4p5
+RixqYvO1DO/9TYNL/fXReqtVEgYz8ygAmasRf7NSJxO1ByhCiJ+rxRXCTFic/GPU
+k5WGvSSepCUM2RpqXVWsm44=
+-----END PRIVATE KEY-----
--- /dev/null
+8020A0407F798ABA
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCsXK4GNkpl4NsL
+PCgTCIuQZkNvyLI7+kG9GhAQ++kFarpCkE0uz7G5w3P1/KxMGOlEc2leLYNj0Snl
+WVWov7Aceg0XGLA4Ia/LbalrnaKIDhzuGqWfPCfq/o+blN8SPDS7v2zQbGtGrbz/
+iK7YTYufNFAlxJa+JUIGyLOOIaX9o4L5dHhGVo0L8MT6Gg71NCJT/UM3o0f9n6K8
+0GAlqNuT9wyI/nlS8gfx3vxmbv7aEHZs0IeM791AbYJ80TmyF9YHzxpaORLtSU/Z
+x5FAq3P3VDylfZ+7DEd3Dtlh5RsUZU44xaeK7jK+BSWUoH+WCVkbBAhCa1BrlXp4
+9uz09k1DAgMBAAECggEBAIodPemGaXlXg85t5uLRjxwnhdQ2KvQ6paDFGKizY1bO
+3e/mt6JSFWT4hJxRWzMjJxCNtpobuFQsz/iS7DvrVlCLUJ/4TYS9IaPN/NtaFloV
+jQMS4TJGvunkD+koktOG4O6tBqHArvmU0ISm3ww+nyn0fmC1NeGp802CV7cFqYAi
+y5QT6FhBZYRGj8v+YH9I06Os+tr6C0tKdy5J5nMrbHa64XZulHn/McbeDImtnBfy
+5aLOMIZjlat6nYjMC9dhAuDXKXodnmBW4Jq889UVbg+kgtu9r8Uga5Wx+IBKiieM
+vjHOtJPCb4fHTjCl19G7D5WsXy4r/JNQyUQXlSLpO+kCgYEA4cTzLQ5D8WVsUBOp
+cOZBi93AdbQvbbC7HhkMiFACmhs1cQhgvMXVgjdxt1NcX33tZ9kK8dnx41kp0/ey
+/8JEJM5DI1RFqPIBkXi50RY32uazi7azoSAx0xvmkXvdpTdBUB5BjMHbqzxQZhgH
+D4gtC93o2C53z1StE0Dr37b3zNcCgYEAw3EA+PN+y6Y5e13GLC9M0NSK1gFutCEK
+RqhpCWG1NqJgKMcDTaqPyb74ky9JkAVlFA7WQUUOHInbY+ZCnRLRpgNzbvOgQd33
+g7e5kyHcYsdizZrn3qRKPqocmtFNIjs6xNYufdbMvEU66E752WQOq+TZI89vYkPB
+E0uEyzcq6XUCgYAEIWVNirhFf1SG9oUgEqZaV7lArgY8HIKf31dyWvxhM2Q76CpU
+6c2pLzh+YSEMgjJItxjTKeiZ/zSbsylsMnKqtbdWuyD3IU5UCgBkSeLFt3jLcpFA
+vmUK9rS2Lqz0a9lfDN6oI5fQPy89Xu0qJJSmZe3vnpIEkgkElCh8lE1eSwKBgQC4
+Y7oeJmSfMEGVMcDRWQLpF02xYIKYcX+ncCZBEq0MUZ/VeQWV1fB4z7Ln8jo+Jcja
+ZrEfvU32AN463zhDx0iCj0juCe5NlmR6IfF0bgLmMuT1xEs0k930RzxbmFJklGr6
+4HPWh7x7d/l+yVwSDMOGy49NqNyWYgQb9yjfLTpQLQKBgAM+hF/wgbDpA7GGP1ww
+c9kouaXkylPHJWab28Gr2Ef9ixZjQ/RQrcc71H8e4/ZFAgTN0hclxQMdH2mo6ocC
+cEyxajAci8QaX7RDKZUppsP9vbZk+7HTgyaCo2vh5xOPAeeTzOPhFSoxUhFfj+cP
+Ybdr61y8Ug/YwixvsB0eZtLt
+-----END PRIVATE KEY-----
--- /dev/null
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 9232555434986539705 (0x8020a0407f798ab9)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=FI, O=w1.fi, CN=Server Intermediate CA
+ Validity
+ Not Before: Dec 23 19:37:36 2015 GMT
+ Not After : Dec 20 19:37:36 2025 GMT
+ Subject: C=FI, O=w1.fi, CN=server-revoked.w1.fi
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:ac:5c:ae:06:36:4a:65:e0:db:0b:3c:28:13:08:
+ 8b:90:66:43:6f:c8:b2:3b:fa:41:bd:1a:10:10:fb:
+ e9:05:6a:ba:42:90:4d:2e:cf:b1:b9:c3:73:f5:fc:
+ ac:4c:18:e9:44:73:69:5e:2d:83:63:d1:29:e5:59:
+ 55:a8:bf:b0:1c:7a:0d:17:18:b0:38:21:af:cb:6d:
+ a9:6b:9d:a2:88:0e:1c:ee:1a:a5:9f:3c:27:ea:fe:
+ 8f:9b:94:df:12:3c:34:bb:bf:6c:d0:6c:6b:46:ad:
+ bc:ff:88:ae:d8:4d:8b:9f:34:50:25:c4:96:be:25:
+ 42:06:c8:b3:8e:21:a5:fd:a3:82:f9:74:78:46:56:
+ 8d:0b:f0:c4:fa:1a:0e:f5:34:22:53:fd:43:37:a3:
+ 47:fd:9f:a2:bc:d0:60:25:a8:db:93:f7:0c:88:fe:
+ 79:52:f2:07:f1:de:fc:66:6e:fe:da:10:76:6c:d0:
+ 87:8c:ef:dd:40:6d:82:7c:d1:39:b2:17:d6:07:cf:
+ 1a:5a:39:12:ed:49:4f:d9:c7:91:40:ab:73:f7:54:
+ 3c:a5:7d:9f:bb:0c:47:77:0e:d9:61:e5:1b:14:65:
+ 4e:38:c5:a7:8a:ee:32:be:05:25:94:a0:7f:96:09:
+ 59:1b:04:08:42:6b:50:6b:95:7a:78:f6:ec:f4:f6:
+ 4d:43
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Subject Key Identifier:
+ 0D:49:37:45:42:77:90:25:BA:9B:67:DB:F6:DC:61:D2:53:5B:C6:BC
+ X509v3 Authority Key Identifier:
+ keyid:84:09:8B:55:1F:7D:2F:0F:28:D7:9C:EC:54:4E:9F:11:97:55:D9:B9
+
+ X509v3 Subject Alternative Name: critical
+ DNS:server-revoked.w1.fi
+ X509v3 Extended Key Usage: critical
+ TLS Web Server Authentication
+ X509v3 Key Usage:
+ Digital Signature, Key Encipherment
+ Signature Algorithm: sha256WithRSAEncryption
+ 22:c6:72:08:84:a9:e9:19:77:ea:6a:06:68:43:8b:e7:72:af:
+ 9c:a2:47:b9:6f:b6:cb:11:17:89:0a:42:52:14:58:9e:3c:01:
+ fd:e7:fc:a2:0d:85:a5:b5:8c:27:d5:5e:b2:47:05:05:f9:56:
+ b6:0b:e2:28:f3:1d:75:5e:13:eb:ec:a0:76:2b:d9:ed:99:84:
+ 08:6d:64:71:13:b6:02:81:b3:c2:7e:b8:b6:00:98:4f:26:ea:
+ f1:67:5b:35:2a:26:d0:ca:a8:fb:eb:21:fb:f1:d6:5a:63:42:
+ 01:5f:b3:59:3d:f8:e0:4d:94:3a:3a:82:46:02:9d:81:2c:ef:
+ e5:46:c7:99:f4:2f:43:ad:85:fc:2c:ca:0b:6b:48:01:ac:d7:
+ f7:da:0e:16:c4:10:18:14:83:9c:85:90:75:ef:66:9f:65:42:
+ e5:e7:8c:16:ac:f6:60:61:d7:5f:a0:21:cd:8a:85:d4:a0:f2:
+ 8e:17:0e:38:5e:31:12:ac:24:b5:67:61:9d:15:84:0b:fc:84:
+ 8a:d4:29:90:3d:4b:23:48:19:6b:f7:26:1f:fe:b9:b9:f1:6e:
+ 70:ac:ec:31:60:be:7d:6f:58:7e:c1:47:61:a7:b0:4b:b2:fd:
+ 62:06:c5:97:43:28:39:a5:c5:60:51:c0:46:9d:6b:e4:1a:ed:
+ 0c:a6:51:8a
+-----BEGIN CERTIFICATE-----
+MIIDmDCCAoCgAwIBAgIJAIAgoEB/eYq5MA0GCSqGSIb3DQEBCwUAMD4xCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVybWVk
+aWF0ZSBDQTAeFw0xNTEyMjMxOTM3MzZaFw0yNTEyMjAxOTM3MzZaMDwxCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEdMBsGA1UEAwwUc2VydmVyLXJldm9rZWQu
+dzEuZmkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsXK4GNkpl4NsL
+PCgTCIuQZkNvyLI7+kG9GhAQ++kFarpCkE0uz7G5w3P1/KxMGOlEc2leLYNj0Snl
+WVWov7Aceg0XGLA4Ia/LbalrnaKIDhzuGqWfPCfq/o+blN8SPDS7v2zQbGtGrbz/
+iK7YTYufNFAlxJa+JUIGyLOOIaX9o4L5dHhGVo0L8MT6Gg71NCJT/UM3o0f9n6K8
+0GAlqNuT9wyI/nlS8gfx3vxmbv7aEHZs0IeM791AbYJ80TmyF9YHzxpaORLtSU/Z
+x5FAq3P3VDylfZ+7DEd3Dtlh5RsUZU44xaeK7jK+BSWUoH+WCVkbBAhCa1BrlXp4
+9uz09k1DAgMBAAGjgZowgZcwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUDUk3RUJ3
+kCW6m2fb9txh0lNbxrwwHwYDVR0jBBgwFoAUhAmLVR99Lw8o15zsVE6fEZdV2bkw
+IgYDVR0RAQH/BBgwFoIUc2VydmVyLXJldm9rZWQudzEuZmkwFgYDVR0lAQH/BAww
+CgYIKwYBBQUHAwEwCwYDVR0PBAQDAgWgMA0GCSqGSIb3DQEBCwUAA4IBAQAixnII
+hKnpGXfqagZoQ4vncq+coke5b7bLEReJCkJSFFiePAH95/yiDYWltYwn1V6yRwUF
++Va2C+Io8x11XhPr7KB2K9ntmYQIbWRxE7YCgbPCfri2AJhPJurxZ1s1KibQyqj7
+6yH78dZaY0IBX7NZPfjgTZQ6OoJGAp2BLO/lRseZ9C9DrYX8LMoLa0gBrNf32g4W
+xBAYFIOchZB172afZULl54wWrPZgYddfoCHNioXUoPKOFw44XjESrCS1Z2GdFYQL
+/ISK1CmQPUsjSBlr9yYf/rm58W5wrOwxYL59b1h+wUdhp7BLsv1iBsWXQyg5pcVg
+UcBGnWvkGu0MplGK
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN CERTIFICATE REQUEST-----
+MIIClDCCAXwCAQAwTzELMAkGA1UEBhMCRkkxETAPBgNVBAcMCEhlbHNpbmtpMQ4w
+DAYDVQQKDAV3MS5maTEdMBsGA1UEAwwUc2VydmVyLXJldm9rZWQudzEuZmkwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsXK4GNkpl4NsLPCgTCIuQZkNv
+yLI7+kG9GhAQ++kFarpCkE0uz7G5w3P1/KxMGOlEc2leLYNj0SnlWVWov7Aceg0X
+GLA4Ia/LbalrnaKIDhzuGqWfPCfq/o+blN8SPDS7v2zQbGtGrbz/iK7YTYufNFAl
+xJa+JUIGyLOOIaX9o4L5dHhGVo0L8MT6Gg71NCJT/UM3o0f9n6K80GAlqNuT9wyI
+/nlS8gfx3vxmbv7aEHZs0IeM791AbYJ80TmyF9YHzxpaORLtSU/Zx5FAq3P3VDyl
+fZ+7DEd3Dtlh5RsUZU44xaeK7jK+BSWUoH+WCVkbBAhCa1BrlXp49uz09k1DAgMB
+AAGgADANBgkqhkiG9w0BAQsFAAOCAQEAUcB51hlCnud4M8uQMv74+6VpPykm7srA
+f+kX1or6J1hRrpdUENDydBG/WavyKJmJ4FEb+SS3K+BDoLCObGwazOcFPvJWlT8S
+8h8vX5BC+zqLqqjtBv6BJ6Wkb3s/3yhMpGJtrEHShxQTagkqsqSV+nRcnqR/9Ufw
+/pHVZ+2sc0Q+dzY+aOmHw+XKkczeI73/j8odhf+a5yTyt6DmUgPRsCOhrBPAlakb
+rHzhfnziYI2pS4/q8Ok5LyFAiBjYp5HFvHEwfjb/3o4bLFTpbDDsJoeyX0ddFFhb
+fZUhqGHYHMIGR5RXJ685RXg39f7PN8/YPIq4wAjGb9qpkwCbqUJPOA==
+-----END CERTIFICATE REQUEST-----
--- /dev/null
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 15624081837803162867 (0xd8d3e3a6cbe3ccf3)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=FI, O=w1.fi, CN=Root CA
+ Validity
+ Not Before: Dec 23 19:37:36 2015 GMT
+ Not After : Dec 22 19:37:36 2025 GMT
+ Subject: C=FI, O=w1.fi, CN=Server Intermediate CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:de:58:ac:e3:d8:7e:40:f6:84:2a:49:24:49:5a:
+ f7:c8:23:08:b9:6c:d9:07:01:69:8f:77:28:71:42:
+ a2:eb:ae:86:10:c6:31:61:9a:14:88:44:0a:68:bf:
+ 6e:a2:46:41:e9:6f:a2:89:fb:0b:f3:e1:b8:30:bf:
+ e5:80:5e:f9:61:8d:6e:ac:e2:f7:28:e7:9e:44:28:
+ b8:e4:6e:87:76:a9:d7:ac:ed:11:3f:de:c3:dd:41:
+ c3:45:82:09:c3:a7:4c:e6:df:2b:88:1e:44:ce:e2:
+ a7:29:53:f6:13:96:ad:6c:2e:93:00:28:42:77:bc:
+ 73:6e:86:e7:5b:e8:eb:e9:37:1d:63:e7:ea:05:5a:
+ 71:28:f0:81:0b:4c:3f:dd:73:f8:db:13:a8:f0:5f:
+ 6f:6f:e5:1b:c7:94:7f:57:c5:dc:66:26:0c:5a:71:
+ 7a:e3:d2:3e:7a:a6:59:46:03:61:78:89:84:3d:ef:
+ 22:9c:f8:c2:22:75:c4:0c:ef:fb:e4:fa:6f:b8:11:
+ db:aa:92:9b:6c:23:4e:6e:e5:55:d2:41:47:18:95:
+ c6:7d:17:be:6d:ab:39:a1:38:61:fd:f9:22:95:69:
+ f3:9e:28:fd:8a:c8:58:72:3c:91:c2:22:d9:fb:b2:
+ 54:0f:9a:17:27:88:df:60:f5:de:fc:95:9f:25:c6:
+ 64:81
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 84:09:8B:55:1F:7D:2F:0F:28:D7:9C:EC:54:4E:9F:11:97:55:D9:B9
+ X509v3 Authority Key Identifier:
+ keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:0
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ bd:22:63:3d:a7:e5:ce:c9:f5:66:1f:77:5f:d5:24:e3:68:dc:
+ a4:07:80:3e:5e:b1:2c:96:88:39:ad:00:4c:aa:9d:0b:ed:f3:
+ 6d:df:9d:2f:97:d2:77:8b:ba:d0:9c:0f:a6:5e:60:b8:0f:e1:
+ 96:b1:61:25:48:69:81:64:a8:5c:82:58:0b:f3:d0:a9:4e:8b:
+ 90:fc:2f:67:57:da:72:dc:3c:eb:c2:20:19:05:8d:42:0d:14:
+ cf:00:db:59:00:ea:f0:76:3e:ca:85:b1:05:e5:b8:5f:0b:46:
+ c7:3c:a1:d9:5c:4d:b9:24:e7:d6:2b:3d:0d:eb:c3:88:d8:3a:
+ f6:60
+-----BEGIN CERTIFICATE-----
+MIIC1TCCAj6gAwIBAgIJANjT46bL48zzMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNTEy
+MjMxOTM3MzZaFw0yNTEyMjIxOTM3MzZaMD4xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
+DAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVybWVkaWF0ZSBDQTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBAN5YrOPYfkD2hCpJJEla98gjCLls2QcB
+aY93KHFCouuuhhDGMWGaFIhECmi/bqJGQelvoon7C/PhuDC/5YBe+WGNbqzi9yjn
+nkQouORuh3ap16ztET/ew91Bw0WCCcOnTObfK4geRM7ipylT9hOWrWwukwAoQne8
+c26G51vo6+k3HWPn6gVacSjwgQtMP91z+NsTqPBfb2/lG8eUf1fF3GYmDFpxeuPS
+PnqmWUYDYXiJhD3vIpz4wiJ1xAzv++T6b7gR26qSm2wjTm7lVdJBRxiVxn0Xvm2r
+OaE4Yf35IpVp854o/YrIWHI8kcIi2fuyVA+aFyeI32D13vyVnyXGZIECAwEAAaNm
+MGQwHQYDVR0OBBYEFIQJi1UffS8PKNec7FROnxGXVdm5MB8GA1UdIwQYMBaAFLiS
+3v2KGLMww59V8zNdtMgpikEUMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/
+BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4GBAL0iYz2n5c7J9WYfd1/VJONo3KQHgD5e
+sSyWiDmtAEyqnQvt823fnS+X0neLutCcD6ZeYLgP4ZaxYSVIaYFkqFyCWAvz0KlO
+i5D8L2dX2nLcPOvCIBkFjUINFM8A21kA6vB2PsqFsQXluF8LRsc8odlcTbkk59Yr
+PQ3rw4jYOvZg
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 9232555434986539705 (0x8020a0407f798ab9)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=FI, O=w1.fi, CN=Server Intermediate CA
+ Validity
+ Not Before: Dec 23 19:37:36 2015 GMT
+ Not After : Dec 20 19:37:36 2025 GMT
+ Subject: C=FI, O=w1.fi, CN=server-revoked.w1.fi
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:ac:5c:ae:06:36:4a:65:e0:db:0b:3c:28:13:08:
+ 8b:90:66:43:6f:c8:b2:3b:fa:41:bd:1a:10:10:fb:
+ e9:05:6a:ba:42:90:4d:2e:cf:b1:b9:c3:73:f5:fc:
+ ac:4c:18:e9:44:73:69:5e:2d:83:63:d1:29:e5:59:
+ 55:a8:bf:b0:1c:7a:0d:17:18:b0:38:21:af:cb:6d:
+ a9:6b:9d:a2:88:0e:1c:ee:1a:a5:9f:3c:27:ea:fe:
+ 8f:9b:94:df:12:3c:34:bb:bf:6c:d0:6c:6b:46:ad:
+ bc:ff:88:ae:d8:4d:8b:9f:34:50:25:c4:96:be:25:
+ 42:06:c8:b3:8e:21:a5:fd:a3:82:f9:74:78:46:56:
+ 8d:0b:f0:c4:fa:1a:0e:f5:34:22:53:fd:43:37:a3:
+ 47:fd:9f:a2:bc:d0:60:25:a8:db:93:f7:0c:88:fe:
+ 79:52:f2:07:f1:de:fc:66:6e:fe:da:10:76:6c:d0:
+ 87:8c:ef:dd:40:6d:82:7c:d1:39:b2:17:d6:07:cf:
+ 1a:5a:39:12:ed:49:4f:d9:c7:91:40:ab:73:f7:54:
+ 3c:a5:7d:9f:bb:0c:47:77:0e:d9:61:e5:1b:14:65:
+ 4e:38:c5:a7:8a:ee:32:be:05:25:94:a0:7f:96:09:
+ 59:1b:04:08:42:6b:50:6b:95:7a:78:f6:ec:f4:f6:
+ 4d:43
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Subject Key Identifier:
+ 0D:49:37:45:42:77:90:25:BA:9B:67:DB:F6:DC:61:D2:53:5B:C6:BC
+ X509v3 Authority Key Identifier:
+ keyid:84:09:8B:55:1F:7D:2F:0F:28:D7:9C:EC:54:4E:9F:11:97:55:D9:B9
+
+ X509v3 Subject Alternative Name: critical
+ DNS:server-revoked.w1.fi
+ X509v3 Extended Key Usage: critical
+ TLS Web Server Authentication
+ X509v3 Key Usage:
+ Digital Signature, Key Encipherment
+ Signature Algorithm: sha256WithRSAEncryption
+ 22:c6:72:08:84:a9:e9:19:77:ea:6a:06:68:43:8b:e7:72:af:
+ 9c:a2:47:b9:6f:b6:cb:11:17:89:0a:42:52:14:58:9e:3c:01:
+ fd:e7:fc:a2:0d:85:a5:b5:8c:27:d5:5e:b2:47:05:05:f9:56:
+ b6:0b:e2:28:f3:1d:75:5e:13:eb:ec:a0:76:2b:d9:ed:99:84:
+ 08:6d:64:71:13:b6:02:81:b3:c2:7e:b8:b6:00:98:4f:26:ea:
+ f1:67:5b:35:2a:26:d0:ca:a8:fb:eb:21:fb:f1:d6:5a:63:42:
+ 01:5f:b3:59:3d:f8:e0:4d:94:3a:3a:82:46:02:9d:81:2c:ef:
+ e5:46:c7:99:f4:2f:43:ad:85:fc:2c:ca:0b:6b:48:01:ac:d7:
+ f7:da:0e:16:c4:10:18:14:83:9c:85:90:75:ef:66:9f:65:42:
+ e5:e7:8c:16:ac:f6:60:61:d7:5f:a0:21:cd:8a:85:d4:a0:f2:
+ 8e:17:0e:38:5e:31:12:ac:24:b5:67:61:9d:15:84:0b:fc:84:
+ 8a:d4:29:90:3d:4b:23:48:19:6b:f7:26:1f:fe:b9:b9:f1:6e:
+ 70:ac:ec:31:60:be:7d:6f:58:7e:c1:47:61:a7:b0:4b:b2:fd:
+ 62:06:c5:97:43:28:39:a5:c5:60:51:c0:46:9d:6b:e4:1a:ed:
+ 0c:a6:51:8a
+-----BEGIN CERTIFICATE-----
+MIIDmDCCAoCgAwIBAgIJAIAgoEB/eYq5MA0GCSqGSIb3DQEBCwUAMD4xCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVybWVk
+aWF0ZSBDQTAeFw0xNTEyMjMxOTM3MzZaFw0yNTEyMjAxOTM3MzZaMDwxCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEdMBsGA1UEAwwUc2VydmVyLXJldm9rZWQu
+dzEuZmkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsXK4GNkpl4NsL
+PCgTCIuQZkNvyLI7+kG9GhAQ++kFarpCkE0uz7G5w3P1/KxMGOlEc2leLYNj0Snl
+WVWov7Aceg0XGLA4Ia/LbalrnaKIDhzuGqWfPCfq/o+blN8SPDS7v2zQbGtGrbz/
+iK7YTYufNFAlxJa+JUIGyLOOIaX9o4L5dHhGVo0L8MT6Gg71NCJT/UM3o0f9n6K8
+0GAlqNuT9wyI/nlS8gfx3vxmbv7aEHZs0IeM791AbYJ80TmyF9YHzxpaORLtSU/Z
+x5FAq3P3VDylfZ+7DEd3Dtlh5RsUZU44xaeK7jK+BSWUoH+WCVkbBAhCa1BrlXp4
+9uz09k1DAgMBAAGjgZowgZcwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUDUk3RUJ3
+kCW6m2fb9txh0lNbxrwwHwYDVR0jBBgwFoAUhAmLVR99Lw8o15zsVE6fEZdV2bkw
+IgYDVR0RAQH/BBgwFoIUc2VydmVyLXJldm9rZWQudzEuZmkwFgYDVR0lAQH/BAww
+CgYIKwYBBQUHAwEwCwYDVR0PBAQDAgWgMA0GCSqGSIb3DQEBCwUAA4IBAQAixnII
+hKnpGXfqagZoQ4vncq+coke5b7bLEReJCkJSFFiePAH95/yiDYWltYwn1V6yRwUF
++Va2C+Io8x11XhPr7KB2K9ntmYQIbWRxE7YCgbPCfri2AJhPJurxZ1s1KibQyqj7
+6yH78dZaY0IBX7NZPfjgTZQ6OoJGAp2BLO/lRseZ9C9DrYX8LMoLa0gBrNf32g4W
+xBAYFIOchZB172afZULl54wWrPZgYddfoCHNioXUoPKOFw44XjESrCS1Z2GdFYQL
+/ISK1CmQPUsjSBlr9yYf/rm58W5wrOwxYL59b1h+wUdhp7BLsv1iBsWXQyg5pcVg
+UcBGnWvkGu0MplGK
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDkiKWTAlu8VGhG
++nN9MzBHRVxJXzxRX5v+xRQQJj0P48KyF4TTPhKosnsCGoqL6fRBHvzzSS3G1Ign
+gdCG87nACiooRQAywxgi9pk38XSNrFRHc+W20+f4gJl19RkZ6xlw35JTsWE4/3/P
+i73hf1Bb0JUwozdrinIGp+g54qR4Q5iRzTCINFuqnqKfJtXhW4ZNAaTCZc0nlL7i
+9XNdxGCY8XURlAkNnQR/7xqdX/BKP4jXdi6b1irGlAk3CjckkpGdGA/qTtTknUU4
+WrrY37YVb6z/bEGs18AKVeyByppZQFWLpHcT3/rDte7vh0GNlNDAlkG0OgS2a2pW
+k/RnfifhAgMBAAECggEAA+GSNknu9ubUEoiEV5b79enmpFRauOMPyibcrV2I4fEz
+SET/+3ptZLILRsDeo3uoq0Z0c0lF3r+TRGB/Axu2ht1lU+PAGhyYF1fqyDlwiktn
+7wK33wAAS4cblBZCg98rQnB5krRLe2VTbVnpMqAv5C9JqVbMRSZHw3csiXcg5e3v
+urH5A90pwFY/1DG68JS+HCLxvorO5EIfeTSBg1F54FHBCQ6Yjr232uXAUez5hv5/
+zX6oxw2zarKMgNiosy5FCoGEUECCfvM2tiXjfZ0DBmZgF/c6Alg+J8gYFVJzSX+x
+xAyL9o3LYddSdDnGBiMm4SU8oUxvnUgrZ+xhnyL69QKBgQD9717EmTLKBna4wX+d
+PM03yIv2ZpFESd4VuxZMyTOO64CMD75n1V/r1V44xIQa7M5QwfD+NmTjW/QyJ0EN
+F5mJYavXc56nlV4wVQJC2/NnyOScjKEIXu/QmEPwTm/NqEqCFs6XGpftigjB+FIO
+Te/PmOVFSDCE+JkOF3Fls55iMwKBgQDmZGW/duaEL4qMnDO51hSz+qv9mZNXoPzg
+DWzmraOikp1zSTjaLzRy6w8bbHTqTZDG68hJ/knW2boD0pDqmuUzS6ADnV7P0fVT
+mOolwmKdGO3axyIsStuhPKaaHv28X0+y2qhUkK7hYJ2yeZIQ/259D75g0BNozjO5
+1sKEsW+BmwKBgBgZu9jU4WkjK+llFAOMXb3Jnt8H5QmiKR3O39Lx1Z7e4xhn9h5M
+tgnf+k1Q+WjEyOAJSCIYb4LUm1yXNSlU8BGF35VXN9uX5ZSYvNoznepfurLQ9geh
+WwllKi2IhDv0mP23xGu67mhxDVu7ga4x32zIihoFO/Wi0oPv3adVYNbZAoGBAOMF
+VwVdYjQqrHl1ibq66teWUFeqNvgIGGWmlQKRY0bU9fUd17mW/jWmzdIWAvbFy71X
+pJrUyWm+TX9qw4WJcAQlpt0o+r4Jg5YGfeMLMiTe5bHIuzGt6dFtdDU2CIzP1jbF
+I02A6/IFRB8TkAzTxcnR86RuJFIHrgyXREGAngG1AoGBAOR/fBPsVAf2MsfGyX7l
+JpHkHgfmAldfRammmGxV2c+NJ/cWjkN/1p8KaiqINP08FemC7Rxvu8Nhm50qOLRM
+iq2KeDCaHoUp9waX7T+WzKbT+jEdcyXeu2DlN8AIyTNjDrVyZil0NbZfQFbR8nWR
+0VX+Eq8Oxrl+pRza/6f62K7s
+-----END PRIVATE KEY-----
--- /dev/null
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 9232555434986539704 (0x8020a0407f798ab8)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=FI, O=w1.fi, CN=Server Intermediate CA
+ Validity
+ Not Before: Dec 23 19:37:36 2015 GMT
+ Not After : Dec 20 19:37:36 2025 GMT
+ Subject: C=FI, O=w1.fi, CN=server.w1.fi
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:e4:88:a5:93:02:5b:bc:54:68:46:fa:73:7d:33:
+ 30:47:45:5c:49:5f:3c:51:5f:9b:fe:c5:14:10:26:
+ 3d:0f:e3:c2:b2:17:84:d3:3e:12:a8:b2:7b:02:1a:
+ 8a:8b:e9:f4:41:1e:fc:f3:49:2d:c6:d4:88:27:81:
+ d0:86:f3:b9:c0:0a:2a:28:45:00:32:c3:18:22:f6:
+ 99:37:f1:74:8d:ac:54:47:73:e5:b6:d3:e7:f8:80:
+ 99:75:f5:19:19:eb:19:70:df:92:53:b1:61:38:ff:
+ 7f:cf:8b:bd:e1:7f:50:5b:d0:95:30:a3:37:6b:8a:
+ 72:06:a7:e8:39:e2:a4:78:43:98:91:cd:30:88:34:
+ 5b:aa:9e:a2:9f:26:d5:e1:5b:86:4d:01:a4:c2:65:
+ cd:27:94:be:e2:f5:73:5d:c4:60:98:f1:75:11:94:
+ 09:0d:9d:04:7f:ef:1a:9d:5f:f0:4a:3f:88:d7:76:
+ 2e:9b:d6:2a:c6:94:09:37:0a:37:24:92:91:9d:18:
+ 0f:ea:4e:d4:e4:9d:45:38:5a:ba:d8:df:b6:15:6f:
+ ac:ff:6c:41:ac:d7:c0:0a:55:ec:81:ca:9a:59:40:
+ 55:8b:a4:77:13:df:fa:c3:b5:ee:ef:87:41:8d:94:
+ d0:c0:96:41:b4:3a:04:b6:6b:6a:56:93:f4:67:7e:
+ 27:e1
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Subject Key Identifier:
+ 4B:81:85:B4:88:41:0D:D4:15:D3:48:0E:F4:A9:99:14:2D:B1:DB:93
+ X509v3 Authority Key Identifier:
+ keyid:84:09:8B:55:1F:7D:2F:0F:28:D7:9C:EC:54:4E:9F:11:97:55:D9:B9
+
+ X509v3 Subject Alternative Name: critical
+ DNS:server.w1.fi
+ X509v3 Extended Key Usage: critical
+ TLS Web Server Authentication
+ X509v3 Key Usage:
+ Digital Signature, Key Encipherment
+ Signature Algorithm: sha256WithRSAEncryption
+ 49:2a:14:22:16:2c:12:f5:4e:06:f3:c2:1e:ac:54:07:5d:86:
+ 16:3e:6c:a0:73:e1:a6:d7:c3:49:1f:80:0d:b6:54:22:77:ce:
+ 39:dd:f6:f6:9f:62:ff:d5:27:7f:c3:92:73:b9:a7:ce:87:5a:
+ e3:bc:52:b3:0a:99:eb:91:56:b6:78:01:c3:0e:4b:ca:8a:04:
+ ee:5c:56:05:ef:7a:cb:21:f9:eb:8a:38:12:50:c7:6e:a8:1f:
+ 0e:81:81:a6:2d:ea:35:94:24:db:76:77:df:ea:41:4c:af:7e:
+ 29:9d:d5:e6:e3:12:78:19:92:ed:35:b9:99:19:a9:d6:cb:f8:
+ a7:21:fb:8e:a7:39:dc:e1:ab:3d:ba:12:87:ba:1c:08:e6:8a:
+ 21:96:44:44:8a:61:0f:70:00:d0:cb:63:93:a4:fa:cc:75:a3:
+ fd:e8:af:33:24:80:4a:d9:b9:2a:a1:20:0b:62:0b:17:6c:9a:
+ 7c:8b:fd:9e:ff:be:b2:51:5e:e9:3a:cc:28:22:63:44:69:7f:
+ 6d:1f:08:14:a4:32:d0:1f:f9:c3:8d:28:1a:76:12:00:3c:b3:
+ 38:13:ca:67:17:79:c6:de:5d:b7:9d:f8:e3:64:f7:b3:a0:5c:
+ e5:6e:fc:10:f3:53:d6:70:38:c2:6f:87:ab:07:1c:64:ff:30:
+ d8:3a:1e:75
+-----BEGIN CERTIFICATE-----
+MIIDiDCCAnCgAwIBAgIJAIAgoEB/eYq4MA0GCSqGSIb3DQEBCwUAMD4xCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVybWVk
+aWF0ZSBDQTAeFw0xNTEyMjMxOTM3MzZaFw0yNTEyMjAxOTM3MzZaMDQxCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEVMBMGA1UEAwwMc2VydmVyLncxLmZpMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5IilkwJbvFRoRvpzfTMwR0Vc
+SV88UV+b/sUUECY9D+PCsheE0z4SqLJ7AhqKi+n0QR7880ktxtSIJ4HQhvO5wAoq
+KEUAMsMYIvaZN/F0jaxUR3PlttPn+ICZdfUZGesZcN+SU7FhOP9/z4u94X9QW9CV
+MKM3a4pyBqfoOeKkeEOYkc0wiDRbqp6inybV4VuGTQGkwmXNJ5S+4vVzXcRgmPF1
+EZQJDZ0Ef+8anV/wSj+I13Yum9YqxpQJNwo3JJKRnRgP6k7U5J1FOFq62N+2FW+s
+/2xBrNfAClXsgcqaWUBVi6R3E9/6w7Xu74dBjZTQwJZBtDoEtmtqVpP0Z34n4QID
+AQABo4GSMIGPMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFEuBhbSIQQ3UFdNIDvSp
+mRQtsduTMB8GA1UdIwQYMBaAFIQJi1UffS8PKNec7FROnxGXVdm5MBoGA1UdEQEB
+/wQQMA6CDHNlcnZlci53MS5maTAWBgNVHSUBAf8EDDAKBggrBgEFBQcDATALBgNV
+HQ8EBAMCBaAwDQYJKoZIhvcNAQELBQADggEBAEkqFCIWLBL1Tgbzwh6sVAddhhY+
+bKBz4abXw0kfgA22VCJ3zjnd9vafYv/VJ3/DknO5p86HWuO8UrMKmeuRVrZ4AcMO
+S8qKBO5cVgXvessh+euKOBJQx26oHw6BgaYt6jWUJNt2d9/qQUyvfimd1ebjEngZ
+ku01uZkZqdbL+Kch+46nOdzhqz26Eoe6HAjmiiGWRESKYQ9wANDLY5Ok+sx1o/3o
+rzMkgErZuSqhIAtiCxdsmnyL/Z7/vrJRXuk6zCgiY0Rpf20fCBSkMtAf+cONKBp2
+EgA8szgTymcXecbeXbed+ONk97OgXOVu/BDzU9ZwOMJvh6sHHGT/MNg6HnU=
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN CERTIFICATE REQUEST-----
+MIICjDCCAXQCAQAwRzELMAkGA1UEBhMCRkkxETAPBgNVBAcMCEhlbHNpbmtpMQ4w
+DAYDVQQKDAV3MS5maTEVMBMGA1UEAwwMc2VydmVyLncxLmZpMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5IilkwJbvFRoRvpzfTMwR0VcSV88UV+b/sUU
+ECY9D+PCsheE0z4SqLJ7AhqKi+n0QR7880ktxtSIJ4HQhvO5wAoqKEUAMsMYIvaZ
+N/F0jaxUR3PlttPn+ICZdfUZGesZcN+SU7FhOP9/z4u94X9QW9CVMKM3a4pyBqfo
+OeKkeEOYkc0wiDRbqp6inybV4VuGTQGkwmXNJ5S+4vVzXcRgmPF1EZQJDZ0Ef+8a
+nV/wSj+I13Yum9YqxpQJNwo3JJKRnRgP6k7U5J1FOFq62N+2FW+s/2xBrNfAClXs
+gcqaWUBVi6R3E9/6w7Xu74dBjZTQwJZBtDoEtmtqVpP0Z34n4QIDAQABoAAwDQYJ
+KoZIhvcNAQELBQADggEBAE+hOOVtzHJvvrjl21A/gmdj5kRHYCijOGJ53ipY9mFX
+aIK9+kJ0Jrlm9cZGbxwTMwJpAyk+7yPl3K0euoToXf+vdLnYds/HGRonN66pXqmD
+QRZXGp6j58mBcmfiU1OB+6XRcLsYITaOaU9AvJ0jg9wkHISrN5uxfDG9QH//YYQ6
+aWzBfjUPAa+2trlmvI4tpC+w7sDHLa5WB5yBDm7HZ6UGwU5R7aMIZn2Hpe1BZS1u
+Xo86qqJpbt6RvR5QEb6+79+8fmt3onQvZ28+wheUdcUin0G/JP7Lfo9/tNzU/29v
+YJopHLeK1zNc6+lBwRTJiDbLC726H5dqZgxu9NNl8zg=
+-----END CERTIFICATE REQUEST-----
--- /dev/null
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 9232555434986539704 (0x8020a0407f798ab8)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=FI, O=w1.fi, CN=Server Intermediate CA
+ Validity
+ Not Before: Dec 23 19:37:36 2015 GMT
+ Not After : Dec 20 19:37:36 2025 GMT
+ Subject: C=FI, O=w1.fi, CN=server.w1.fi
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:e4:88:a5:93:02:5b:bc:54:68:46:fa:73:7d:33:
+ 30:47:45:5c:49:5f:3c:51:5f:9b:fe:c5:14:10:26:
+ 3d:0f:e3:c2:b2:17:84:d3:3e:12:a8:b2:7b:02:1a:
+ 8a:8b:e9:f4:41:1e:fc:f3:49:2d:c6:d4:88:27:81:
+ d0:86:f3:b9:c0:0a:2a:28:45:00:32:c3:18:22:f6:
+ 99:37:f1:74:8d:ac:54:47:73:e5:b6:d3:e7:f8:80:
+ 99:75:f5:19:19:eb:19:70:df:92:53:b1:61:38:ff:
+ 7f:cf:8b:bd:e1:7f:50:5b:d0:95:30:a3:37:6b:8a:
+ 72:06:a7:e8:39:e2:a4:78:43:98:91:cd:30:88:34:
+ 5b:aa:9e:a2:9f:26:d5:e1:5b:86:4d:01:a4:c2:65:
+ cd:27:94:be:e2:f5:73:5d:c4:60:98:f1:75:11:94:
+ 09:0d:9d:04:7f:ef:1a:9d:5f:f0:4a:3f:88:d7:76:
+ 2e:9b:d6:2a:c6:94:09:37:0a:37:24:92:91:9d:18:
+ 0f:ea:4e:d4:e4:9d:45:38:5a:ba:d8:df:b6:15:6f:
+ ac:ff:6c:41:ac:d7:c0:0a:55:ec:81:ca:9a:59:40:
+ 55:8b:a4:77:13:df:fa:c3:b5:ee:ef:87:41:8d:94:
+ d0:c0:96:41:b4:3a:04:b6:6b:6a:56:93:f4:67:7e:
+ 27:e1
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Subject Key Identifier:
+ 4B:81:85:B4:88:41:0D:D4:15:D3:48:0E:F4:A9:99:14:2D:B1:DB:93
+ X509v3 Authority Key Identifier:
+ keyid:84:09:8B:55:1F:7D:2F:0F:28:D7:9C:EC:54:4E:9F:11:97:55:D9:B9
+
+ X509v3 Subject Alternative Name: critical
+ DNS:server.w1.fi
+ X509v3 Extended Key Usage: critical
+ TLS Web Server Authentication
+ X509v3 Key Usage:
+ Digital Signature, Key Encipherment
+ Signature Algorithm: sha256WithRSAEncryption
+ 49:2a:14:22:16:2c:12:f5:4e:06:f3:c2:1e:ac:54:07:5d:86:
+ 16:3e:6c:a0:73:e1:a6:d7:c3:49:1f:80:0d:b6:54:22:77:ce:
+ 39:dd:f6:f6:9f:62:ff:d5:27:7f:c3:92:73:b9:a7:ce:87:5a:
+ e3:bc:52:b3:0a:99:eb:91:56:b6:78:01:c3:0e:4b:ca:8a:04:
+ ee:5c:56:05:ef:7a:cb:21:f9:eb:8a:38:12:50:c7:6e:a8:1f:
+ 0e:81:81:a6:2d:ea:35:94:24:db:76:77:df:ea:41:4c:af:7e:
+ 29:9d:d5:e6:e3:12:78:19:92:ed:35:b9:99:19:a9:d6:cb:f8:
+ a7:21:fb:8e:a7:39:dc:e1:ab:3d:ba:12:87:ba:1c:08:e6:8a:
+ 21:96:44:44:8a:61:0f:70:00:d0:cb:63:93:a4:fa:cc:75:a3:
+ fd:e8:af:33:24:80:4a:d9:b9:2a:a1:20:0b:62:0b:17:6c:9a:
+ 7c:8b:fd:9e:ff:be:b2:51:5e:e9:3a:cc:28:22:63:44:69:7f:
+ 6d:1f:08:14:a4:32:d0:1f:f9:c3:8d:28:1a:76:12:00:3c:b3:
+ 38:13:ca:67:17:79:c6:de:5d:b7:9d:f8:e3:64:f7:b3:a0:5c:
+ e5:6e:fc:10:f3:53:d6:70:38:c2:6f:87:ab:07:1c:64:ff:30:
+ d8:3a:1e:75
+-----BEGIN CERTIFICATE-----
+MIIDiDCCAnCgAwIBAgIJAIAgoEB/eYq4MA0GCSqGSIb3DQEBCwUAMD4xCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVybWVk
+aWF0ZSBDQTAeFw0xNTEyMjMxOTM3MzZaFw0yNTEyMjAxOTM3MzZaMDQxCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEVMBMGA1UEAwwMc2VydmVyLncxLmZpMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5IilkwJbvFRoRvpzfTMwR0Vc
+SV88UV+b/sUUECY9D+PCsheE0z4SqLJ7AhqKi+n0QR7880ktxtSIJ4HQhvO5wAoq
+KEUAMsMYIvaZN/F0jaxUR3PlttPn+ICZdfUZGesZcN+SU7FhOP9/z4u94X9QW9CV
+MKM3a4pyBqfoOeKkeEOYkc0wiDRbqp6inybV4VuGTQGkwmXNJ5S+4vVzXcRgmPF1
+EZQJDZ0Ef+8anV/wSj+I13Yum9YqxpQJNwo3JJKRnRgP6k7U5J1FOFq62N+2FW+s
+/2xBrNfAClXsgcqaWUBVi6R3E9/6w7Xu74dBjZTQwJZBtDoEtmtqVpP0Z34n4QID
+AQABo4GSMIGPMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFEuBhbSIQQ3UFdNIDvSp
+mRQtsduTMB8GA1UdIwQYMBaAFIQJi1UffS8PKNec7FROnxGXVdm5MBoGA1UdEQEB
+/wQQMA6CDHNlcnZlci53MS5maTAWBgNVHSUBAf8EDDAKBggrBgEFBQcDATALBgNV
+HQ8EBAMCBaAwDQYJKoZIhvcNAQELBQADggEBAEkqFCIWLBL1Tgbzwh6sVAddhhY+
+bKBz4abXw0kfgA22VCJ3zjnd9vafYv/VJ3/DknO5p86HWuO8UrMKmeuRVrZ4AcMO
+S8qKBO5cVgXvessh+euKOBJQx26oHw6BgaYt6jWUJNt2d9/qQUyvfimd1ebjEngZ
+ku01uZkZqdbL+Kch+46nOdzhqz26Eoe6HAjmiiGWRESKYQ9wANDLY5Ok+sx1o/3o
+rzMkgErZuSqhIAtiCxdsmnyL/Z7/vrJRXuk6zCgiY0Rpf20fCBSkMtAf+cONKBp2
+EgA8szgTymcXecbeXbed+ONk97OgXOVu/BDzU9ZwOMJvh6sHHGT/MNg6HnU=
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 15624081837803162867 (0xd8d3e3a6cbe3ccf3)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=FI, O=w1.fi, CN=Root CA
+ Validity
+ Not Before: Dec 23 19:37:36 2015 GMT
+ Not After : Dec 22 19:37:36 2025 GMT
+ Subject: C=FI, O=w1.fi, CN=Server Intermediate CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:de:58:ac:e3:d8:7e:40:f6:84:2a:49:24:49:5a:
+ f7:c8:23:08:b9:6c:d9:07:01:69:8f:77:28:71:42:
+ a2:eb:ae:86:10:c6:31:61:9a:14:88:44:0a:68:bf:
+ 6e:a2:46:41:e9:6f:a2:89:fb:0b:f3:e1:b8:30:bf:
+ e5:80:5e:f9:61:8d:6e:ac:e2:f7:28:e7:9e:44:28:
+ b8:e4:6e:87:76:a9:d7:ac:ed:11:3f:de:c3:dd:41:
+ c3:45:82:09:c3:a7:4c:e6:df:2b:88:1e:44:ce:e2:
+ a7:29:53:f6:13:96:ad:6c:2e:93:00:28:42:77:bc:
+ 73:6e:86:e7:5b:e8:eb:e9:37:1d:63:e7:ea:05:5a:
+ 71:28:f0:81:0b:4c:3f:dd:73:f8:db:13:a8:f0:5f:
+ 6f:6f:e5:1b:c7:94:7f:57:c5:dc:66:26:0c:5a:71:
+ 7a:e3:d2:3e:7a:a6:59:46:03:61:78:89:84:3d:ef:
+ 22:9c:f8:c2:22:75:c4:0c:ef:fb:e4:fa:6f:b8:11:
+ db:aa:92:9b:6c:23:4e:6e:e5:55:d2:41:47:18:95:
+ c6:7d:17:be:6d:ab:39:a1:38:61:fd:f9:22:95:69:
+ f3:9e:28:fd:8a:c8:58:72:3c:91:c2:22:d9:fb:b2:
+ 54:0f:9a:17:27:88:df:60:f5:de:fc:95:9f:25:c6:
+ 64:81
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 84:09:8B:55:1F:7D:2F:0F:28:D7:9C:EC:54:4E:9F:11:97:55:D9:B9
+ X509v3 Authority Key Identifier:
+ keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:0
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ bd:22:63:3d:a7:e5:ce:c9:f5:66:1f:77:5f:d5:24:e3:68:dc:
+ a4:07:80:3e:5e:b1:2c:96:88:39:ad:00:4c:aa:9d:0b:ed:f3:
+ 6d:df:9d:2f:97:d2:77:8b:ba:d0:9c:0f:a6:5e:60:b8:0f:e1:
+ 96:b1:61:25:48:69:81:64:a8:5c:82:58:0b:f3:d0:a9:4e:8b:
+ 90:fc:2f:67:57:da:72:dc:3c:eb:c2:20:19:05:8d:42:0d:14:
+ cf:00:db:59:00:ea:f0:76:3e:ca:85:b1:05:e5:b8:5f:0b:46:
+ c7:3c:a1:d9:5c:4d:b9:24:e7:d6:2b:3d:0d:eb:c3:88:d8:3a:
+ f6:60
+-----BEGIN CERTIFICATE-----
+MIIC1TCCAj6gAwIBAgIJANjT46bL48zzMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNTEy
+MjMxOTM3MzZaFw0yNTEyMjIxOTM3MzZaMD4xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
+DAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVybWVkaWF0ZSBDQTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBAN5YrOPYfkD2hCpJJEla98gjCLls2QcB
+aY93KHFCouuuhhDGMWGaFIhECmi/bqJGQelvoon7C/PhuDC/5YBe+WGNbqzi9yjn
+nkQouORuh3ap16ztET/ew91Bw0WCCcOnTObfK4geRM7ipylT9hOWrWwukwAoQne8
+c26G51vo6+k3HWPn6gVacSjwgQtMP91z+NsTqPBfb2/lG8eUf1fF3GYmDFpxeuPS
+PnqmWUYDYXiJhD3vIpz4wiJ1xAzv++T6b7gR26qSm2wjTm7lVdJBRxiVxn0Xvm2r
+OaE4Yf35IpVp854o/YrIWHI8kcIi2fuyVA+aFyeI32D13vyVnyXGZIECAwEAAaNm
+MGQwHQYDVR0OBBYEFIQJi1UffS8PKNec7FROnxGXVdm5MB8GA1UdIwQYMBaAFLiS
+3v2KGLMww59V8zNdtMgpikEUMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/
+BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4GBAL0iYz2n5c7J9WYfd1/VJONo3KQHgD5e
+sSyWiDmtAEyqnQvt823fnS+X0neLutCcD6ZeYLgP4ZaxYSVIaYFkqFyCWAvz0KlO
+i5D8L2dX2nLcPOvCIBkFjUINFM8A21kA6vB2PsqFsQXluF8LRsc8odlcTbkk59Yr
+PQ3rw4jYOvZg
+-----END CERTIFICATE-----
--- /dev/null
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 15624081837803162868 (0xd8d3e3a6cbe3ccf4)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=FI, O=w1.fi, CN=Root CA
+ Validity
+ Not Before: Dec 23 19:37:36 2015 GMT
+ Not After : Dec 22 19:37:36 2025 GMT
+ Subject: C=FI, O=w1.fi, CN=User Intermediate CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c3:2a:0d:f4:66:23:5d:96:91:f7:a0:be:b1:b0:
+ f7:9e:ae:ea:a6:72:91:f5:70:65:57:91:49:55:59:
+ 67:bb:d7:f5:9e:bc:66:b2:bf:cf:95:31:32:ae:db:
+ 9a:3b:43:e8:a5:8d:1f:8b:3b:e6:e8:e3:3b:b2:9d:
+ f0:58:62:ea:a3:8a:6f:c8:ed:01:ca:27:74:1c:0e:
+ 9e:28:5c:43:98:db:14:b8:72:07:9f:6b:27:28:25:
+ ce:a5:91:b7:b7:23:9a:35:ef:0e:b7:fc:9f:69:4d:
+ 10:2e:81:ab:9d:04:ba:2f:b4:eb:61:7d:fd:68:a1:
+ 11:6f:f4:16:42:16:99:20:38:24:04:2d:39:7c:74:
+ 67:14:b9:aa:26:7a:b2:d9:1e:ce:cd:8b:bc:8d:e3:
+ c7:58:9c:4a:f9:3a:7e:6c:38:f8:5f:1c:ec:05:4c:
+ e5:56:64:d4:08:d8:fa:db:17:d9:a1:e4:cf:b4:9d:
+ df:99:50:ce:fa:a4:af:af:c6:f7:f2:0e:c2:c5:7b:
+ 6c:f9:6c:eb:17:e5:c8:6e:5a:bf:eb:a6:b8:c0:f7:
+ 43:81:88:c3:d8:aa:a9:60:ac:a7:45:3f:5d:cb:8d:
+ 6c:48:92:2b:04:5a:c4:a8:32:b3:e9:6f:fe:8d:2d:
+ 65:c0:ea:c5:09:b2:30:b1:a3:2e:db:22:8a:49:b1:
+ fe:4f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ AC:C4:F6:07:9E:B2:E5:F1:66:7C:40:05:08:AA:DC:EF:8A:60:DA:C1
+ X509v3 Authority Key Identifier:
+ keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:0
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 0d:60:2b:fa:00:f2:5a:90:31:96:50:c8:9e:7f:60:02:99:c6:
+ 31:d4:93:86:9e:4c:24:15:b6:b2:31:49:21:79:ce:7f:92:86:
+ 1e:83:d8:a0:37:05:1b:89:2b:ef:0b:83:21:b0:37:8d:2f:7b:
+ 6b:7d:c6:04:1e:a2:c8:59:be:52:bf:47:ee:46:cb:45:8d:1f:
+ 7a:e4:d4:e5:54:60:5f:46:b0:ac:68:8a:26:57:ea:48:45:c1:
+ 07:7d:ee:10:9e:94:87:4c:7e:26:2e:f8:ad:03:e5:03:86:09:
+ 3e:48:0c:e0:04:2f:22:b4:e0:3a:b0:72:8c:e2:40:d2:cd:fb:
+ 8f:fa
+-----BEGIN CERTIFICATE-----
+MIIC0zCCAjygAwIBAgIJANjT46bL48z0MA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNTEy
+MjMxOTM3MzZaFw0yNTEyMjIxOTM3MzZaMDwxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
+DAV3MS5maTEdMBsGA1UEAwwUVXNlciBJbnRlcm1lZGlhdGUgQ0EwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDKg30ZiNdlpH3oL6xsPeeruqmcpH1cGVX
+kUlVWWe71/WevGayv8+VMTKu25o7Q+iljR+LO+bo4zuynfBYYuqjim/I7QHKJ3Qc
+Dp4oXEOY2xS4cgefaycoJc6lkbe3I5o17w63/J9pTRAugaudBLovtOthff1ooRFv
+9BZCFpkgOCQELTl8dGcUuaomerLZHs7Ni7yN48dYnEr5On5sOPhfHOwFTOVWZNQI
+2PrbF9mh5M+0nd+ZUM76pK+vxvfyDsLFe2z5bOsX5chuWr/rprjA90OBiMPYqqlg
+rKdFP13LjWxIkisEWsSoMrPpb/6NLWXA6sUJsjCxoy7bIopJsf5PAgMBAAGjZjBk
+MB0GA1UdDgQWBBSsxPYHnrLl8WZ8QAUIqtzvimDawTAfBgNVHSMEGDAWgBS4kt79
+ihizMMOfVfMzXbTIKYpBFDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQE
+AwIBBjANBgkqhkiG9w0BAQsFAAOBgQANYCv6APJakDGWUMief2ACmcYx1JOGnkwk
+FbayMUkhec5/koYeg9igNwUbiSvvC4MhsDeNL3trfcYEHqLIWb5Sv0fuRstFjR96
+5NTlVGBfRrCsaIomV+pIRcEHfe4QnpSHTH4mLvitA+UDhgk+SAzgBC8itOA6sHKM
+4kDSzfuP+g==
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 15624081837803162817 (0xd8d3e3a6cbe3ccc1)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=FI, O=w1.fi, CN=Root CA
+ Validity
+ Not Before: Jun 29 16:41:22 2013 GMT
+ Not After : Jun 27 16:41:22 2023 GMT
+ Subject: C=FI, O=w1.fi, CN=Root CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:be:1e:86:e4:79:03:c1:d1:94:d5:d4:b3:b1:28:
+ 90:76:fb:b8:a6:cd:6d:1c:d1:48:f4:08:9a:67:ff:
+ f9:a6:54:b1:19:29:df:29:1b:cd:f1:6f:66:01:e7:
+ db:79:ce:c0:39:2a:25:13:26:94:0c:2c:7b:5a:2c:
+ 81:0f:94:ee:51:d0:75:e6:46:db:17:46:a7:15:8b:
+ 0e:57:0f:b0:54:76:63:12:ca:86:18:bc:1a:c3:16:
+ c0:70:09:d6:6b:43:39:b8:98:29:46:ac:cb:6a:ad:
+ 38:88:3b:07:dc:81:cd:3a:f6:1d:f6:2f:ef:1d:d7:
+ ae:8a:b6:d1:e7:b3:15:02:b9
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14
+ X509v3 Authority Key Identifier:
+ keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 1a:cf:77:60:44:43:c4:55:0e:99:e0:89:aa:b9:d3:7b:32:b7:
+ 5c:9c:7c:ca:fe:8c:d4:94:c6:5e:f3:83:19:5f:29:59:68:a4:
+ 4f:dc:04:2e:b8:71:c0:6d:3b:ae:01:e4:b9:88:99:cc:ce:82:
+ be:6a:28:c2:ac:6a:94:c6:87:90:ed:85:3c:10:71:c5:ff:3c:
+ 70:64:e2:41:62:31:ea:86:7b:11:8c:93:ea:c6:f3:f3:4e:f9:
+ d4:f2:81:90:d7:f4:fa:a1:91:6e:d4:dd:15:3e:26:3b:ac:1e:
+ c3:c2:1f:ed:bb:34:bf:cb:b2:67:c6:c6:51:e8:51:22:b4:f3:
+ 92:e8
+-----BEGIN CERTIFICATE-----
+MIICLDCCAZWgAwIBAgIJANjT46bL48zBMA0GCSqGSIb3DQEBBQUAMC8xCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xMzA2
+MjkxNjQxMjJaFw0yMzA2MjcxNjQxMjJaMC8xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
+DAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
+gYkCgYEAvh6G5HkDwdGU1dSzsSiQdvu4ps1tHNFI9AiaZ//5plSxGSnfKRvN8W9m
+Aefbec7AOSolEyaUDCx7WiyBD5TuUdB15kbbF0anFYsOVw+wVHZjEsqGGLwawxbA
+cAnWa0M5uJgpRqzLaq04iDsH3IHNOvYd9i/vHdeuirbR57MVArkCAwEAAaNQME4w
+HQYDVR0OBBYEFLiS3v2KGLMww59V8zNdtMgpikEUMB8GA1UdIwQYMBaAFLiS3v2K
+GLMww59V8zNdtMgpikEUMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEA
+Gs93YERDxFUOmeCJqrnTezK3XJx8yv6M1JTGXvODGV8pWWikT9wELrhxwG07rgHk
+uYiZzM6CvmoowqxqlMaHkO2FPBBxxf88cGTiQWIx6oZ7EYyT6sbz80751PKBkNf0
++qGRbtTdFT4mO6wew8If7bs0v8uyZ8bGUehRIrTzkug=
+-----END CERTIFICATE-----
--- /dev/null
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 15624081837803162868 (0xd8d3e3a6cbe3ccf4)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=FI, O=w1.fi, CN=Root CA
+ Validity
+ Not Before: Dec 23 19:37:36 2015 GMT
+ Not After : Dec 22 19:37:36 2025 GMT
+ Subject: C=FI, O=w1.fi, CN=User Intermediate CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c3:2a:0d:f4:66:23:5d:96:91:f7:a0:be:b1:b0:
+ f7:9e:ae:ea:a6:72:91:f5:70:65:57:91:49:55:59:
+ 67:bb:d7:f5:9e:bc:66:b2:bf:cf:95:31:32:ae:db:
+ 9a:3b:43:e8:a5:8d:1f:8b:3b:e6:e8:e3:3b:b2:9d:
+ f0:58:62:ea:a3:8a:6f:c8:ed:01:ca:27:74:1c:0e:
+ 9e:28:5c:43:98:db:14:b8:72:07:9f:6b:27:28:25:
+ ce:a5:91:b7:b7:23:9a:35:ef:0e:b7:fc:9f:69:4d:
+ 10:2e:81:ab:9d:04:ba:2f:b4:eb:61:7d:fd:68:a1:
+ 11:6f:f4:16:42:16:99:20:38:24:04:2d:39:7c:74:
+ 67:14:b9:aa:26:7a:b2:d9:1e:ce:cd:8b:bc:8d:e3:
+ c7:58:9c:4a:f9:3a:7e:6c:38:f8:5f:1c:ec:05:4c:
+ e5:56:64:d4:08:d8:fa:db:17:d9:a1:e4:cf:b4:9d:
+ df:99:50:ce:fa:a4:af:af:c6:f7:f2:0e:c2:c5:7b:
+ 6c:f9:6c:eb:17:e5:c8:6e:5a:bf:eb:a6:b8:c0:f7:
+ 43:81:88:c3:d8:aa:a9:60:ac:a7:45:3f:5d:cb:8d:
+ 6c:48:92:2b:04:5a:c4:a8:32:b3:e9:6f:fe:8d:2d:
+ 65:c0:ea:c5:09:b2:30:b1:a3:2e:db:22:8a:49:b1:
+ fe:4f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ AC:C4:F6:07:9E:B2:E5:F1:66:7C:40:05:08:AA:DC:EF:8A:60:DA:C1
+ X509v3 Authority Key Identifier:
+ keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:0
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 0d:60:2b:fa:00:f2:5a:90:31:96:50:c8:9e:7f:60:02:99:c6:
+ 31:d4:93:86:9e:4c:24:15:b6:b2:31:49:21:79:ce:7f:92:86:
+ 1e:83:d8:a0:37:05:1b:89:2b:ef:0b:83:21:b0:37:8d:2f:7b:
+ 6b:7d:c6:04:1e:a2:c8:59:be:52:bf:47:ee:46:cb:45:8d:1f:
+ 7a:e4:d4:e5:54:60:5f:46:b0:ac:68:8a:26:57:ea:48:45:c1:
+ 07:7d:ee:10:9e:94:87:4c:7e:26:2e:f8:ad:03:e5:03:86:09:
+ 3e:48:0c:e0:04:2f:22:b4:e0:3a:b0:72:8c:e2:40:d2:cd:fb:
+ 8f:fa
+-----BEGIN CERTIFICATE-----
+MIIC0zCCAjygAwIBAgIJANjT46bL48z0MA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNTEy
+MjMxOTM3MzZaFw0yNTEyMjIxOTM3MzZaMDwxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
+DAV3MS5maTEdMBsGA1UEAwwUVXNlciBJbnRlcm1lZGlhdGUgQ0EwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDKg30ZiNdlpH3oL6xsPeeruqmcpH1cGVX
+kUlVWWe71/WevGayv8+VMTKu25o7Q+iljR+LO+bo4zuynfBYYuqjim/I7QHKJ3Qc
+Dp4oXEOY2xS4cgefaycoJc6lkbe3I5o17w63/J9pTRAugaudBLovtOthff1ooRFv
+9BZCFpkgOCQELTl8dGcUuaomerLZHs7Ni7yN48dYnEr5On5sOPhfHOwFTOVWZNQI
+2PrbF9mh5M+0nd+ZUM76pK+vxvfyDsLFe2z5bOsX5chuWr/rprjA90OBiMPYqqlg
+rKdFP13LjWxIkisEWsSoMrPpb/6NLWXA6sUJsjCxoy7bIopJsf5PAgMBAAGjZjBk
+MB0GA1UdDgQWBBSsxPYHnrLl8WZ8QAUIqtzvimDawTAfBgNVHSMEGDAWgBS4kt79
+ihizMMOfVfMzXbTIKYpBFDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQE
+AwIBBjANBgkqhkiG9w0BAQsFAAOBgQANYCv6APJakDGWUMief2ACmcYx1JOGnkwk
+FbayMUkhec5/koYeg9igNwUbiSvvC4MhsDeNL3trfcYEHqLIWb5Sv0fuRstFjR96
+5NTlVGBfRrCsaIomV+pIRcEHfe4QnpSHTH4mLvitA+UDhgk+SAzgBC8itOA6sHKM
+4kDSzfuP+g==
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN CERTIFICATE REQUEST-----
+MIIClDCCAXwCAQAwTzELMAkGA1UEBhMCRkkxETAPBgNVBAcMCEhlbHNpbmtpMQ4w
+DAYDVQQKDAV3MS5maTEdMBsGA1UEAwwUVXNlciBJbnRlcm1lZGlhdGUgQ0EwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDKg30ZiNdlpH3oL6xsPeeruqm
+cpH1cGVXkUlVWWe71/WevGayv8+VMTKu25o7Q+iljR+LO+bo4zuynfBYYuqjim/I
+7QHKJ3QcDp4oXEOY2xS4cgefaycoJc6lkbe3I5o17w63/J9pTRAugaudBLovtOth
+ff1ooRFv9BZCFpkgOCQELTl8dGcUuaomerLZHs7Ni7yN48dYnEr5On5sOPhfHOwF
+TOVWZNQI2PrbF9mh5M+0nd+ZUM76pK+vxvfyDsLFe2z5bOsX5chuWr/rprjA90OB
+iMPYqqlgrKdFP13LjWxIkisEWsSoMrPpb/6NLWXA6sUJsjCxoy7bIopJsf5PAgMB
+AAGgADANBgkqhkiG9w0BAQsFAAOCAQEAKYOesAY0nFSXY1Ez8q5cGRUa0YZWic1l
+NwF05zIFoD3loCWRiayzINJqwXvUO29X0c8W35hTIGHyGUzcc0iwtrjphlmpuimN
+AzL+NG1+TwfEQi+LL+e0lJnl2PIZkIN4cQDgTSdejU40sNRPWzD8w8EYHYAOJ4oU
+0TXfrIRJWBDZKFtjO2fcknf1beGN79ZOHxc6pCFdZ7pM2w3+mKbfysnVBZkDwavG
+SlIdL23QcD3Uj0vOrU+oOSGQKXamZrjjpmu647bcQ5XQr8kZbXWu6A4G24bxZ2rw
+S7Z7DVvLqGxJgSl8b72otGJqkszHiul2ZKHy25flrtGM0SBU+k9FEQ==
+-----END CERTIFICATE REQUEST-----
--- /dev/null
+V 251220193736Z E153BA3A7605DA1E unknown /C=FI/O=w1.fi/CN=user.w1.fi
--- /dev/null
+unique_subject = yes
--- /dev/null
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 16236525841851734558 (0xe153ba3a7605da1e)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=FI, O=w1.fi, CN=User Intermediate CA
+ Validity
+ Not Before: Dec 23 19:37:36 2015 GMT
+ Not After : Dec 20 19:37:36 2025 GMT
+ Subject: C=FI, O=w1.fi, CN=user.w1.fi
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c0:86:20:e5:06:5a:a8:47:2d:c9:5e:25:24:f7:
+ bf:a6:b6:44:50:99:8c:95:b5:6a:ad:74:b6:ba:ee:
+ 31:5e:b2:20:60:9a:b4:93:55:6d:15:0b:dc:5a:27:
+ 3f:df:c1:92:18:59:66:10:eb:47:1c:35:1f:08:dd:
+ eb:25:bd:21:9c:2d:48:34:5f:97:18:dc:83:28:db:
+ 14:8c:16:3b:5a:36:6a:50:63:e9:3b:e0:37:fd:f6:
+ a0:d6:40:af:ef:1e:99:1d:88:c1:4f:4b:92:25:53:
+ 28:cb:c4:b7:ce:ca:ca:26:af:2d:f7:e4:62:79:48:
+ 49:6a:82:33:b0:a6:c6:a5:17:33:88:93:77:36:b2:
+ 77:61:e0:55:de:2e:75:15:92:4c:e7:bf:11:ea:33:
+ 03:1e:4a:e6:18:38:16:34:f5:d9:ed:f8:0c:17:6f:
+ 78:65:ae:14:18:a3:0f:08:b6:e2:87:02:e4:eb:0f:
+ fb:81:d9:4b:90:ff:b3:fa:0f:d3:04:4d:b0:99:b4:
+ 2b:5e:fb:ad:04:2b:a7:d6:36:0d:17:e0:be:c0:43:
+ cf:e5:2e:f0:8e:87:88:60:b3:22:d8:03:59:53:50:
+ a6:69:ce:de:d0:c9:2e:f7:6d:9a:59:4d:99:dc:4b:
+ 3c:c2:15:8f:27:64:23:34:14:34:af:41:76:a5:6a:
+ 9a:0f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ X509v3 Subject Key Identifier:
+ 3E:35:E0:F9:A3:1E:2C:FA:DD:E7:8B:CE:58:06:38:20:5D:5E:71:D2
+ X509v3 Authority Key Identifier:
+ keyid:AC:C4:F6:07:9E:B2:E5:F1:66:7C:40:05:08:AA:DC:EF:8A:60:DA:C1
+
+ X509v3 Subject Alternative Name: critical
+ DNS:user.w1.fi
+ X509v3 Extended Key Usage:
+ TLS Web Client Authentication
+ X509v3 Key Usage:
+ Digital Signature, Key Encipherment
+ Signature Algorithm: sha256WithRSAEncryption
+ 7b:e9:eb:d7:d4:60:a8:08:62:71:61:dd:42:7d:e5:88:f4:24:
+ bb:3f:6b:a9:16:64:2d:fb:ce:8e:55:1c:f5:7e:b4:c3:74:de:
+ 96:e4:59:32:f4:aa:74:e2:ac:43:28:06:54:5d:f7:fe:87:31:
+ 3d:ac:45:d5:1c:51:7f:8c:f9:37:0b:66:94:a7:22:5f:d1:55:
+ bf:a4:82:c7:0a:50:bb:c7:18:cf:df:47:81:00:c4:d2:d7:12:
+ b0:83:2d:67:3f:80:b8:be:6f:c9:c5:76:9a:87:ef:3a:f6:0d:
+ 4f:24:d8:e7:06:6c:6e:ff:dc:5e:6e:21:a1:e7:26:f6:94:44:
+ 69:f4:b2:36:38:08:b1:df:07:fa:7a:53:b8:60:db:63:4b:4f:
+ e6:2a:42:ff:29:68:b5:99:3a:36:eb:26:05:76:d2:ab:e6:d0:
+ 7c:af:8c:a0:20:8b:50:6c:3b:bc:1a:53:6d:a7:c8:70:97:21:
+ 56:02:24:04:9b:63:2a:5d:b8:8c:e4:bf:e9:8f:58:cd:6e:99:
+ 47:3c:02:7b:63:67:c1:c7:32:53:cc:d5:cb:e9:a0:39:ef:f8:
+ 44:b7:f3:57:0c:b5:a7:23:3f:16:28:c6:02:14:b6:80:d8:33:
+ 42:0c:81:5c:ac:3f:13:d0:5b:4a:66:9f:33:ee:ac:56:fe:37:
+ 17:2b:03:40
+-----BEGIN CERTIFICATE-----
+MIIDfDCCAmSgAwIBAgIJAOFTujp2BdoeMA0GCSqGSIb3DQEBCwUAMDwxCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEdMBsGA1UEAwwUVXNlciBJbnRlcm1lZGlh
+dGUgQ0EwHhcNMTUxMjIzMTkzNzM2WhcNMjUxMjIwMTkzNzM2WjAyMQswCQYDVQQG
+EwJGSTEOMAwGA1UECgwFdzEuZmkxEzARBgNVBAMMCnVzZXIudzEuZmkwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAhiDlBlqoRy3JXiUk97+mtkRQmYyV
+tWqtdLa67jFesiBgmrSTVW0VC9xaJz/fwZIYWWYQ60ccNR8I3eslvSGcLUg0X5cY
+3IMo2xSMFjtaNmpQY+k74Df99qDWQK/vHpkdiMFPS5IlUyjLxLfOysomry335GJ5
+SElqgjOwpsalFzOIk3c2sndh4FXeLnUVkkznvxHqMwMeSuYYOBY09dnt+AwXb3hl
+rhQYow8ItuKHAuTrD/uB2UuQ/7P6D9METbCZtCte+60EK6fWNg0X4L7AQ8/lLvCO
+h4hgsyLYA1lTUKZpzt7QyS73bZpZTZncSzzCFY8nZCM0FDSvQXalapoPAgMBAAGj
+gYowgYcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUPjXg+aMeLPrd54vOWAY4IF1ecdIw
+HwYDVR0jBBgwFoAUrMT2B56y5fFmfEAFCKrc74pg2sEwGAYDVR0RAQH/BA4wDIIK
+dXNlci53MS5maTATBgNVHSUEDDAKBggrBgEFBQcDAjALBgNVHQ8EBAMCBaAwDQYJ
+KoZIhvcNAQELBQADggEBAHvp69fUYKgIYnFh3UJ95Yj0JLs/a6kWZC37zo5VHPV+
+tMN03pbkWTL0qnTirEMoBlRd9/6HMT2sRdUcUX+M+TcLZpSnIl/RVb+kgscKULvH
+GM/fR4EAxNLXErCDLWc/gLi+b8nFdpqH7zr2DU8k2OcGbG7/3F5uIaHnJvaURGn0
+sjY4CLHfB/p6U7hg22NLT+YqQv8paLWZOjbrJgV20qvm0HyvjKAgi1BsO7waU22n
+yHCXIVYCJASbYypduIzkv+mPWM1umUc8AntjZ8HHMlPM1cvpoDnv+ES381cMtacj
+PxYoxgIUtoDYM0IMgVysPxPQW0pmnzPurFb+NxcrA0A=
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDDKg30ZiNdlpH3
+oL6xsPeeruqmcpH1cGVXkUlVWWe71/WevGayv8+VMTKu25o7Q+iljR+LO+bo4zuy
+nfBYYuqjim/I7QHKJ3QcDp4oXEOY2xS4cgefaycoJc6lkbe3I5o17w63/J9pTRAu
+gaudBLovtOthff1ooRFv9BZCFpkgOCQELTl8dGcUuaomerLZHs7Ni7yN48dYnEr5
+On5sOPhfHOwFTOVWZNQI2PrbF9mh5M+0nd+ZUM76pK+vxvfyDsLFe2z5bOsX5chu
+Wr/rprjA90OBiMPYqqlgrKdFP13LjWxIkisEWsSoMrPpb/6NLWXA6sUJsjCxoy7b
+IopJsf5PAgMBAAECggEAMQpcP1F7CYVQYH0P7e6eCk3BwNmBO79md76WQtAYdOcr
+XRvSYpA4RTD7n1ynQMUrrI3tozsGJvcShSuSvWL9uuKKfF6x2G5ZisNRkqq8gahr
+aH2e1LxENp5pcslO9MIJegv8Etdz5y3qJwWGbgpGDr7TdsgF6Uiv7QXUof6zs5h3
+dri5y4tIbv+/OrEL9pz0x0wR1wFZ24huLLd+I4qHW+nSVynzRsb7dH76vvJRcj+o
+UUIXx0QASoiFyhTPL3kSIcLcwRW1WEkqQXSENj3765CewhpOVcbzUZQiHjPVdOmg
+6+CRptOGJMh5SGHzAbeABwkgeQ4LGWnPdL9B0ZClYQKBgQDk6tGncCWYELelrt9q
+D/bzTvTZADzxYKuOUmyiu9Wr6Lx3nbfJupf0kZSGZuTBOjOd8iQkI1edIWTZLgyY
+48oW2EggJTo5xmAaAdz82ItXpI0/Rt71QQqhcxsaT2uLIinBdox8wP6/DbnG57DJ
+6FcHOsVfAFAVk2sM8ZCK1XRjiwKBgQDaQPbUNGXg04D08jk+15FDlPYh/2TJNSc+
+SBOE1j7wlTNGr6Vcg7N34U+I8Zo/ci8CXQVAMlLd7UJR9UhPsU2ptMldziDPEn5d
+28CkoAmfw/vrcE8j12cuKUViJK6E/Fpvmbmb/cKrACj9qHd1QV7kXFemDKPEUlAe
+8zp4EqPYzQKBgB4NphCxbH4WU8Xwu2wVRHqU9xg2K8oUwvEgaRrERj0XhQa/Mg3N
+7X0yT6mFgKrNlVE7JPuJmEsMw0yv+v9niHSPWIi/2nETVjKT5Atd8o1DETgpecQB
+EgA4OGqv2pKdnZXElpUaUVeL2cP/TvpzAln0oUzjoZ/zhq5gWHWhqHIZAoGBANjt
+pyfGKNitAEj2FKX8dvrYLUgfY5qFhUrnMtdeZ1KSyVNhs5dfo9rsjDQOB4U2Rbkw
+oc5r9md0se1qQYRMM2gRM/BTt9J5jDZX/ILkOoycrGEX0OFL8Nc12CuzT+8IMA8q
+mQyNzZZPY26zqoBWCC4sBkYZ3BB+y/nnQV8lD8ulAoGAB0cwM8SWfP+u4M7qWGFV
+Dk448ODrEfwnbSABc6EavEJ0BL5h60AsXhV9FW6nxfB66Yt84DZm6YXS+9MElLVy
+jlql+Gbaj1Wawtwyzwk7Sl/vqtDwCRta+TP98kAm93Y9CVizlRH93kpNCoYAoDrA
+qN+IRKm0VOAaYV4NXrTTMWE=
+-----END PRIVATE KEY-----
--- /dev/null
+E153BA3A7605DA1F
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDAhiDlBlqoRy3J
+XiUk97+mtkRQmYyVtWqtdLa67jFesiBgmrSTVW0VC9xaJz/fwZIYWWYQ60ccNR8I
+3eslvSGcLUg0X5cY3IMo2xSMFjtaNmpQY+k74Df99qDWQK/vHpkdiMFPS5IlUyjL
+xLfOysomry335GJ5SElqgjOwpsalFzOIk3c2sndh4FXeLnUVkkznvxHqMwMeSuYY
+OBY09dnt+AwXb3hlrhQYow8ItuKHAuTrD/uB2UuQ/7P6D9METbCZtCte+60EK6fW
+Ng0X4L7AQ8/lLvCOh4hgsyLYA1lTUKZpzt7QyS73bZpZTZncSzzCFY8nZCM0FDSv
+QXalapoPAgMBAAECggEBAItIPkISv8GghTJ6htrg1elRUckR3VBtyDinCI/iRRti
+OORK6DrzAZDJXOhoHuDNVNmCy8GPxYlVsRckHbvWwZsQc31YbqLQ3Z7QKGRUrSnN
+1kpEjfcAduGn7KI0eFPBSjrAtkGcxaV1LT2GGwhjU6567AG8W7Wso1iHy8eQUIQc
+LKRJ6KYpDc019Ly01XRH8mNhmxo3hxpBzMxudiHua/9qXmsRGevsshxQ911wkPdO
+7Yr9bH1YJ7OvwOxxxAkNyRFAhWa7KPzvhsYX6KHEPTfTSv+3GCz5WLI//5NJ6NFB
+3E2ofJOrmxT6EG6hKzyoNzoUwqpbA2BiHhlSVvOjHhECgYEA4pfICLLh40DMdBc9
+LMnPsp7Sv6H1Lcv/SJr0sjI8ESa2WK+XQOKgfB7jxyBHoMYhlr4UxwtgFA2M0cIs
+4tfqv6zNKWmwB8VpUS+1kwaITtny8U4Kb7hQadpE0dXG84kb1aG3dsvK07aSTS6w
+cW/NPZ9mNQhQ1sYsqF0HzuNysvkCgYEA2YJ0qKvLEkzTGcU0y5CLvzb4ZEuhAc7X
+zzHRCNW61mmhNKR3QVEo3vzpKlxF3PbWJUwt0OOUkdyjbRE3yV0d4JCsNH6vRUmD
+CxafENHZgkuCDD9TrDWhSefhWc7ip3unGG8KdnkGYDe1lw7zIJW5g7GS41GORqDV
+gZngtyxJb0cCgYBQL5ZCPctiOFQh4PdtGh2+ACZkWlQBWOeGMg/V36ESELkGuVy1
+QX25btT8apfudS79wVZo+cWOUx06PZTU0cPpAKW5ugTpOxsB9/gxh2ZFQSuP6SYY
+Uwlh7DPebeBx3ltTRl8+Uu/76+fqGFOoUQA4hmgM7FxvJMI48nMI68RzQQKBgQCW
+BgAW8t9PUQPt63Kd0aZCDlVHQE7eY1/A/nhSorCLATJ6j9HdkHAjVcgxOpHJdcuA
+0EltofswnEFwkgarcfmQkdjlIFgd7zVeqYyvWj6vOwuJDQjWZ+tGgZSSkDsPEB/R
+n41U5+b46JPsjBgv6nWZmxpYhkEfAAIjsRIo5XgFMwKBgD6fAKGFelZuJ/W3uUYl
+swb0ks/L3CMmisMmPwafp4C9QB89xV8jtyDNhiIG1nCI54it9mKrPCASoPDrdJR5
+r2/yovQFWk1LIRqcfCjqV/2qVZo5Hdp7Ux/aI8N7/M1eEIgbq+RcZlFTclQ6fppt
+gBDXmqE8gFdegAGqv+OiifB5
+-----END PRIVATE KEY-----
--- /dev/null
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 16236525841851734558 (0xe153ba3a7605da1e)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=FI, O=w1.fi, CN=User Intermediate CA
+ Validity
+ Not Before: Dec 23 19:37:36 2015 GMT
+ Not After : Dec 20 19:37:36 2025 GMT
+ Subject: C=FI, O=w1.fi, CN=user.w1.fi
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c0:86:20:e5:06:5a:a8:47:2d:c9:5e:25:24:f7:
+ bf:a6:b6:44:50:99:8c:95:b5:6a:ad:74:b6:ba:ee:
+ 31:5e:b2:20:60:9a:b4:93:55:6d:15:0b:dc:5a:27:
+ 3f:df:c1:92:18:59:66:10:eb:47:1c:35:1f:08:dd:
+ eb:25:bd:21:9c:2d:48:34:5f:97:18:dc:83:28:db:
+ 14:8c:16:3b:5a:36:6a:50:63:e9:3b:e0:37:fd:f6:
+ a0:d6:40:af:ef:1e:99:1d:88:c1:4f:4b:92:25:53:
+ 28:cb:c4:b7:ce:ca:ca:26:af:2d:f7:e4:62:79:48:
+ 49:6a:82:33:b0:a6:c6:a5:17:33:88:93:77:36:b2:
+ 77:61:e0:55:de:2e:75:15:92:4c:e7:bf:11:ea:33:
+ 03:1e:4a:e6:18:38:16:34:f5:d9:ed:f8:0c:17:6f:
+ 78:65:ae:14:18:a3:0f:08:b6:e2:87:02:e4:eb:0f:
+ fb:81:d9:4b:90:ff:b3:fa:0f:d3:04:4d:b0:99:b4:
+ 2b:5e:fb:ad:04:2b:a7:d6:36:0d:17:e0:be:c0:43:
+ cf:e5:2e:f0:8e:87:88:60:b3:22:d8:03:59:53:50:
+ a6:69:ce:de:d0:c9:2e:f7:6d:9a:59:4d:99:dc:4b:
+ 3c:c2:15:8f:27:64:23:34:14:34:af:41:76:a5:6a:
+ 9a:0f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ X509v3 Subject Key Identifier:
+ 3E:35:E0:F9:A3:1E:2C:FA:DD:E7:8B:CE:58:06:38:20:5D:5E:71:D2
+ X509v3 Authority Key Identifier:
+ keyid:AC:C4:F6:07:9E:B2:E5:F1:66:7C:40:05:08:AA:DC:EF:8A:60:DA:C1
+
+ X509v3 Subject Alternative Name: critical
+ DNS:user.w1.fi
+ X509v3 Extended Key Usage:
+ TLS Web Client Authentication
+ X509v3 Key Usage:
+ Digital Signature, Key Encipherment
+ Signature Algorithm: sha256WithRSAEncryption
+ 7b:e9:eb:d7:d4:60:a8:08:62:71:61:dd:42:7d:e5:88:f4:24:
+ bb:3f:6b:a9:16:64:2d:fb:ce:8e:55:1c:f5:7e:b4:c3:74:de:
+ 96:e4:59:32:f4:aa:74:e2:ac:43:28:06:54:5d:f7:fe:87:31:
+ 3d:ac:45:d5:1c:51:7f:8c:f9:37:0b:66:94:a7:22:5f:d1:55:
+ bf:a4:82:c7:0a:50:bb:c7:18:cf:df:47:81:00:c4:d2:d7:12:
+ b0:83:2d:67:3f:80:b8:be:6f:c9:c5:76:9a:87:ef:3a:f6:0d:
+ 4f:24:d8:e7:06:6c:6e:ff:dc:5e:6e:21:a1:e7:26:f6:94:44:
+ 69:f4:b2:36:38:08:b1:df:07:fa:7a:53:b8:60:db:63:4b:4f:
+ e6:2a:42:ff:29:68:b5:99:3a:36:eb:26:05:76:d2:ab:e6:d0:
+ 7c:af:8c:a0:20:8b:50:6c:3b:bc:1a:53:6d:a7:c8:70:97:21:
+ 56:02:24:04:9b:63:2a:5d:b8:8c:e4:bf:e9:8f:58:cd:6e:99:
+ 47:3c:02:7b:63:67:c1:c7:32:53:cc:d5:cb:e9:a0:39:ef:f8:
+ 44:b7:f3:57:0c:b5:a7:23:3f:16:28:c6:02:14:b6:80:d8:33:
+ 42:0c:81:5c:ac:3f:13:d0:5b:4a:66:9f:33:ee:ac:56:fe:37:
+ 17:2b:03:40
+-----BEGIN CERTIFICATE-----
+MIIDfDCCAmSgAwIBAgIJAOFTujp2BdoeMA0GCSqGSIb3DQEBCwUAMDwxCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEdMBsGA1UEAwwUVXNlciBJbnRlcm1lZGlh
+dGUgQ0EwHhcNMTUxMjIzMTkzNzM2WhcNMjUxMjIwMTkzNzM2WjAyMQswCQYDVQQG
+EwJGSTEOMAwGA1UECgwFdzEuZmkxEzARBgNVBAMMCnVzZXIudzEuZmkwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAhiDlBlqoRy3JXiUk97+mtkRQmYyV
+tWqtdLa67jFesiBgmrSTVW0VC9xaJz/fwZIYWWYQ60ccNR8I3eslvSGcLUg0X5cY
+3IMo2xSMFjtaNmpQY+k74Df99qDWQK/vHpkdiMFPS5IlUyjLxLfOysomry335GJ5
+SElqgjOwpsalFzOIk3c2sndh4FXeLnUVkkznvxHqMwMeSuYYOBY09dnt+AwXb3hl
+rhQYow8ItuKHAuTrD/uB2UuQ/7P6D9METbCZtCte+60EK6fWNg0X4L7AQ8/lLvCO
+h4hgsyLYA1lTUKZpzt7QyS73bZpZTZncSzzCFY8nZCM0FDSvQXalapoPAgMBAAGj
+gYowgYcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUPjXg+aMeLPrd54vOWAY4IF1ecdIw
+HwYDVR0jBBgwFoAUrMT2B56y5fFmfEAFCKrc74pg2sEwGAYDVR0RAQH/BA4wDIIK
+dXNlci53MS5maTATBgNVHSUEDDAKBggrBgEFBQcDAjALBgNVHQ8EBAMCBaAwDQYJ
+KoZIhvcNAQELBQADggEBAHvp69fUYKgIYnFh3UJ95Yj0JLs/a6kWZC37zo5VHPV+
+tMN03pbkWTL0qnTirEMoBlRd9/6HMT2sRdUcUX+M+TcLZpSnIl/RVb+kgscKULvH
+GM/fR4EAxNLXErCDLWc/gLi+b8nFdpqH7zr2DU8k2OcGbG7/3F5uIaHnJvaURGn0
+sjY4CLHfB/p6U7hg22NLT+YqQv8paLWZOjbrJgV20qvm0HyvjKAgi1BsO7waU22n
+yHCXIVYCJASbYypduIzkv+mPWM1umUc8AntjZ8HHMlPM1cvpoDnv+ES381cMtacj
+PxYoxgIUtoDYM0IMgVysPxPQW0pmnzPurFb+NxcrA0A=
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN CERTIFICATE REQUEST-----
+MIICijCCAXICAQAwRTELMAkGA1UEBhMCRkkxETAPBgNVBAcMCEhlbHNpbmtpMQ4w
+DAYDVQQKDAV3MS5maTETMBEGA1UEAwwKdXNlci53MS5maTCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAMCGIOUGWqhHLcleJST3v6a2RFCZjJW1aq10trru
+MV6yIGCatJNVbRUL3FonP9/BkhhZZhDrRxw1Hwjd6yW9IZwtSDRflxjcgyjbFIwW
+O1o2alBj6TvgN/32oNZAr+8emR2IwU9LkiVTKMvEt87KyiavLffkYnlISWqCM7Cm
+xqUXM4iTdzayd2HgVd4udRWSTOe/EeozAx5K5hg4FjT12e34DBdveGWuFBijDwi2
+4ocC5OsP+4HZS5D/s/oP0wRNsJm0K177rQQrp9Y2DRfgvsBDz+Uu8I6HiGCzItgD
+WVNQpmnO3tDJLvdtmllNmdxLPMIVjydkIzQUNK9BdqVqmg8CAwEAAaAAMA0GCSqG
+SIb3DQEBCwUAA4IBAQCUmkpNMn0zJiThP+5G+GvjE4bf1zBPWCQ2jNu9ve5dAd6+
+og47aR2PAJWUmFYMfFBzAFxAVkXVwAMAzN7npwtSjTW9kVPxYHItrncopEzPjIOQ
+WHSH8nuYxNNYbbkq1/dvivcJVFk8gNCIFvnW8EKgtDfvDlYcyleWnYA343N7eeBc
+ujRiiRrZuADk7VFqWM0TdwUEytP/6FJIhB50Y3yDkGNx1KkAJuCU8eSx/aBg/2Si
+XPxDKAcVsESrCfFnHuaqN1+BXP5QXuuvR5N6EPt+C/Mv1VnV28uSkLzFO4PCN2pD
+ArGZjVzFM6Qegag10DPk8BmDuh3s+NydD29xUfbA
+-----END CERTIFICATE REQUEST-----
--- /dev/null
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 15624081837803162868 (0xd8d3e3a6cbe3ccf4)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=FI, O=w1.fi, CN=Root CA
+ Validity
+ Not Before: Dec 23 19:37:36 2015 GMT
+ Not After : Dec 22 19:37:36 2025 GMT
+ Subject: C=FI, O=w1.fi, CN=User Intermediate CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c3:2a:0d:f4:66:23:5d:96:91:f7:a0:be:b1:b0:
+ f7:9e:ae:ea:a6:72:91:f5:70:65:57:91:49:55:59:
+ 67:bb:d7:f5:9e:bc:66:b2:bf:cf:95:31:32:ae:db:
+ 9a:3b:43:e8:a5:8d:1f:8b:3b:e6:e8:e3:3b:b2:9d:
+ f0:58:62:ea:a3:8a:6f:c8:ed:01:ca:27:74:1c:0e:
+ 9e:28:5c:43:98:db:14:b8:72:07:9f:6b:27:28:25:
+ ce:a5:91:b7:b7:23:9a:35:ef:0e:b7:fc:9f:69:4d:
+ 10:2e:81:ab:9d:04:ba:2f:b4:eb:61:7d:fd:68:a1:
+ 11:6f:f4:16:42:16:99:20:38:24:04:2d:39:7c:74:
+ 67:14:b9:aa:26:7a:b2:d9:1e:ce:cd:8b:bc:8d:e3:
+ c7:58:9c:4a:f9:3a:7e:6c:38:f8:5f:1c:ec:05:4c:
+ e5:56:64:d4:08:d8:fa:db:17:d9:a1:e4:cf:b4:9d:
+ df:99:50:ce:fa:a4:af:af:c6:f7:f2:0e:c2:c5:7b:
+ 6c:f9:6c:eb:17:e5:c8:6e:5a:bf:eb:a6:b8:c0:f7:
+ 43:81:88:c3:d8:aa:a9:60:ac:a7:45:3f:5d:cb:8d:
+ 6c:48:92:2b:04:5a:c4:a8:32:b3:e9:6f:fe:8d:2d:
+ 65:c0:ea:c5:09:b2:30:b1:a3:2e:db:22:8a:49:b1:
+ fe:4f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ AC:C4:F6:07:9E:B2:E5:F1:66:7C:40:05:08:AA:DC:EF:8A:60:DA:C1
+ X509v3 Authority Key Identifier:
+ keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:0
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 0d:60:2b:fa:00:f2:5a:90:31:96:50:c8:9e:7f:60:02:99:c6:
+ 31:d4:93:86:9e:4c:24:15:b6:b2:31:49:21:79:ce:7f:92:86:
+ 1e:83:d8:a0:37:05:1b:89:2b:ef:0b:83:21:b0:37:8d:2f:7b:
+ 6b:7d:c6:04:1e:a2:c8:59:be:52:bf:47:ee:46:cb:45:8d:1f:
+ 7a:e4:d4:e5:54:60:5f:46:b0:ac:68:8a:26:57:ea:48:45:c1:
+ 07:7d:ee:10:9e:94:87:4c:7e:26:2e:f8:ad:03:e5:03:86:09:
+ 3e:48:0c:e0:04:2f:22:b4:e0:3a:b0:72:8c:e2:40:d2:cd:fb:
+ 8f:fa
+-----BEGIN CERTIFICATE-----
+MIIC0zCCAjygAwIBAgIJANjT46bL48z0MA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNTEy
+MjMxOTM3MzZaFw0yNTEyMjIxOTM3MzZaMDwxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
+DAV3MS5maTEdMBsGA1UEAwwUVXNlciBJbnRlcm1lZGlhdGUgQ0EwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDKg30ZiNdlpH3oL6xsPeeruqmcpH1cGVX
+kUlVWWe71/WevGayv8+VMTKu25o7Q+iljR+LO+bo4zuynfBYYuqjim/I7QHKJ3Qc
+Dp4oXEOY2xS4cgefaycoJc6lkbe3I5o17w63/J9pTRAugaudBLovtOthff1ooRFv
+9BZCFpkgOCQELTl8dGcUuaomerLZHs7Ni7yN48dYnEr5On5sOPhfHOwFTOVWZNQI
+2PrbF9mh5M+0nd+ZUM76pK+vxvfyDsLFe2z5bOsX5chuWr/rprjA90OBiMPYqqlg
+rKdFP13LjWxIkisEWsSoMrPpb/6NLWXA6sUJsjCxoy7bIopJsf5PAgMBAAGjZjBk
+MB0GA1UdDgQWBBSsxPYHnrLl8WZ8QAUIqtzvimDawTAfBgNVHSMEGDAWgBS4kt79
+ihizMMOfVfMzXbTIKYpBFDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQE
+AwIBBjANBgkqhkiG9w0BAQsFAAOBgQANYCv6APJakDGWUMief2ACmcYx1JOGnkwk
+FbayMUkhec5/koYeg9igNwUbiSvvC4MhsDeNL3trfcYEHqLIWb5Sv0fuRstFjR96
+5NTlVGBfRrCsaIomV+pIRcEHfe4QnpSHTH4mLvitA+UDhgk+SAzgBC8itOA6sHKM
+4kDSzfuP+g==
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 16236525841851734558 (0xe153ba3a7605da1e)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=FI, O=w1.fi, CN=User Intermediate CA
+ Validity
+ Not Before: Dec 23 19:37:36 2015 GMT
+ Not After : Dec 20 19:37:36 2025 GMT
+ Subject: C=FI, O=w1.fi, CN=user.w1.fi
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c0:86:20:e5:06:5a:a8:47:2d:c9:5e:25:24:f7:
+ bf:a6:b6:44:50:99:8c:95:b5:6a:ad:74:b6:ba:ee:
+ 31:5e:b2:20:60:9a:b4:93:55:6d:15:0b:dc:5a:27:
+ 3f:df:c1:92:18:59:66:10:eb:47:1c:35:1f:08:dd:
+ eb:25:bd:21:9c:2d:48:34:5f:97:18:dc:83:28:db:
+ 14:8c:16:3b:5a:36:6a:50:63:e9:3b:e0:37:fd:f6:
+ a0:d6:40:af:ef:1e:99:1d:88:c1:4f:4b:92:25:53:
+ 28:cb:c4:b7:ce:ca:ca:26:af:2d:f7:e4:62:79:48:
+ 49:6a:82:33:b0:a6:c6:a5:17:33:88:93:77:36:b2:
+ 77:61:e0:55:de:2e:75:15:92:4c:e7:bf:11:ea:33:
+ 03:1e:4a:e6:18:38:16:34:f5:d9:ed:f8:0c:17:6f:
+ 78:65:ae:14:18:a3:0f:08:b6:e2:87:02:e4:eb:0f:
+ fb:81:d9:4b:90:ff:b3:fa:0f:d3:04:4d:b0:99:b4:
+ 2b:5e:fb:ad:04:2b:a7:d6:36:0d:17:e0:be:c0:43:
+ cf:e5:2e:f0:8e:87:88:60:b3:22:d8:03:59:53:50:
+ a6:69:ce:de:d0:c9:2e:f7:6d:9a:59:4d:99:dc:4b:
+ 3c:c2:15:8f:27:64:23:34:14:34:af:41:76:a5:6a:
+ 9a:0f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ X509v3 Subject Key Identifier:
+ 3E:35:E0:F9:A3:1E:2C:FA:DD:E7:8B:CE:58:06:38:20:5D:5E:71:D2
+ X509v3 Authority Key Identifier:
+ keyid:AC:C4:F6:07:9E:B2:E5:F1:66:7C:40:05:08:AA:DC:EF:8A:60:DA:C1
+
+ X509v3 Subject Alternative Name: critical
+ DNS:user.w1.fi
+ X509v3 Extended Key Usage:
+ TLS Web Client Authentication
+ X509v3 Key Usage:
+ Digital Signature, Key Encipherment
+ Signature Algorithm: sha256WithRSAEncryption
+ 7b:e9:eb:d7:d4:60:a8:08:62:71:61:dd:42:7d:e5:88:f4:24:
+ bb:3f:6b:a9:16:64:2d:fb:ce:8e:55:1c:f5:7e:b4:c3:74:de:
+ 96:e4:59:32:f4:aa:74:e2:ac:43:28:06:54:5d:f7:fe:87:31:
+ 3d:ac:45:d5:1c:51:7f:8c:f9:37:0b:66:94:a7:22:5f:d1:55:
+ bf:a4:82:c7:0a:50:bb:c7:18:cf:df:47:81:00:c4:d2:d7:12:
+ b0:83:2d:67:3f:80:b8:be:6f:c9:c5:76:9a:87:ef:3a:f6:0d:
+ 4f:24:d8:e7:06:6c:6e:ff:dc:5e:6e:21:a1:e7:26:f6:94:44:
+ 69:f4:b2:36:38:08:b1:df:07:fa:7a:53:b8:60:db:63:4b:4f:
+ e6:2a:42:ff:29:68:b5:99:3a:36:eb:26:05:76:d2:ab:e6:d0:
+ 7c:af:8c:a0:20:8b:50:6c:3b:bc:1a:53:6d:a7:c8:70:97:21:
+ 56:02:24:04:9b:63:2a:5d:b8:8c:e4:bf:e9:8f:58:cd:6e:99:
+ 47:3c:02:7b:63:67:c1:c7:32:53:cc:d5:cb:e9:a0:39:ef:f8:
+ 44:b7:f3:57:0c:b5:a7:23:3f:16:28:c6:02:14:b6:80:d8:33:
+ 42:0c:81:5c:ac:3f:13:d0:5b:4a:66:9f:33:ee:ac:56:fe:37:
+ 17:2b:03:40
+-----BEGIN CERTIFICATE-----
+MIIDfDCCAmSgAwIBAgIJAOFTujp2BdoeMA0GCSqGSIb3DQEBCwUAMDwxCzAJBgNV
+BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEdMBsGA1UEAwwUVXNlciBJbnRlcm1lZGlh
+dGUgQ0EwHhcNMTUxMjIzMTkzNzM2WhcNMjUxMjIwMTkzNzM2WjAyMQswCQYDVQQG
+EwJGSTEOMAwGA1UECgwFdzEuZmkxEzARBgNVBAMMCnVzZXIudzEuZmkwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAhiDlBlqoRy3JXiUk97+mtkRQmYyV
+tWqtdLa67jFesiBgmrSTVW0VC9xaJz/fwZIYWWYQ60ccNR8I3eslvSGcLUg0X5cY
+3IMo2xSMFjtaNmpQY+k74Df99qDWQK/vHpkdiMFPS5IlUyjLxLfOysomry335GJ5
+SElqgjOwpsalFzOIk3c2sndh4FXeLnUVkkznvxHqMwMeSuYYOBY09dnt+AwXb3hl
+rhQYow8ItuKHAuTrD/uB2UuQ/7P6D9METbCZtCte+60EK6fWNg0X4L7AQ8/lLvCO
+h4hgsyLYA1lTUKZpzt7QyS73bZpZTZncSzzCFY8nZCM0FDSvQXalapoPAgMBAAGj
+gYowgYcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUPjXg+aMeLPrd54vOWAY4IF1ecdIw
+HwYDVR0jBBgwFoAUrMT2B56y5fFmfEAFCKrc74pg2sEwGAYDVR0RAQH/BA4wDIIK
+dXNlci53MS5maTATBgNVHSUEDDAKBggrBgEFBQcDAjALBgNVHQ8EBAMCBaAwDQYJ
+KoZIhvcNAQELBQADggEBAHvp69fUYKgIYnFh3UJ95Yj0JLs/a6kWZC37zo5VHPV+
+tMN03pbkWTL0qnTirEMoBlRd9/6HMT2sRdUcUX+M+TcLZpSnIl/RVb+kgscKULvH
+GM/fR4EAxNLXErCDLWc/gLi+b8nFdpqH7zr2DU8k2OcGbG7/3F5uIaHnJvaURGn0
+sjY4CLHfB/p6U7hg22NLT+YqQv8paLWZOjbrJgV20qvm0HyvjKAgi1BsO7waU22n
+yHCXIVYCJASbYypduIzkv+mPWM1umUc8AntjZ8HHMlPM1cvpoDnv+ES381cMtacj
+PxYoxgIUtoDYM0IMgVysPxPQW0pmnzPurFb+NxcrA0A=
+-----END CERTIFICATE-----
--- /dev/null
+#!/bin/sh
+
+OPENSSL=openssl
+
+echo
+echo "---[ Intermediate CA - Server ]-----------------------------------------"
+echo
+
+cat ec-ca-openssl.cnf |
+ sed "s/ec-ca/rootCA/" |
+ sed "s/#@CN@/commonName_default = Server Intermediate CA/" \
+ > openssl.cnf.tmp
+mkdir -p iCA-server/certs iCA-server/crl iCA-server/newcerts iCA-server/private
+touch iCA-server/index.txt
+$OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -keyout iCA-server/private/cakey.pem -out iCA-server/careq.pem -outform PEM -days 3652 -sha256
+$OPENSSL ca -config openssl.cnf.tmp -md sha256 -create_serial -out iCA-server/cacert.pem -days 3652 -batch -keyfile ca-key.pem -cert ca.pem -extensions v3_ca -outdir rootCA/newcerts -infiles iCA-server/careq.pem
+cat iCA-server/cacert.pem ca.pem > iCA-server/ca-and-root.pem
+rm openssl.cnf.tmp
+
+echo
+echo "---[ Intermediate CA - User ]-------------------------------------------"
+echo
+
+cat ec-ca-openssl.cnf |
+ sed "s/ec-ca/rootCA/" |
+ sed "s/#@CN@/commonName_default = User Intermediate CA/" \
+ > openssl.cnf.tmp
+mkdir -p iCA-user/certs iCA-user/crl iCA-user/newcerts iCA-user/private
+touch iCA-user/index.txt
+$OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -keyout iCA-user/private/cakey.pem -out iCA-user/careq.pem -outform PEM -days 3652 -sha256
+$OPENSSL ca -config openssl.cnf.tmp -md sha256 -create_serial -out iCA-user/cacert.pem -days 3652 -batch -keyfile ca-key.pem -cert ca.pem -extensions v3_ca -outdir rootCA/newcerts -infiles iCA-user/careq.pem
+cat iCA-user/cacert.pem ca.pem > iCA-user/ca-and-root.pem
+rm openssl.cnf.tmp
+
+echo
+echo "---[ Server ]-----------------------------------------------------------"
+echo
+
+cat ec-ca-openssl.cnf |
+ sed "s/ec-ca/iCA-server/" |
+ sed "s/#@CN@/commonName_default = server.w1.fi/" |
+ sed "s/#@ALTNAME@/subjectAltName=critical,DNS:server.w1.fi/" \
+ > openssl.cnf.tmp
+$OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -keyout iCA-server/server.key -out iCA-server/server.req -outform PEM -sha256
+$OPENSSL ca -config openssl.cnf.tmp -batch -keyfile iCA-server/private/cakey.pem -cert iCA-server/cacert.pem -create_serial -in iCA-server/server.req -out iCA-server/server.pem -extensions ext_server -md sha256
+cat iCA-server/cacert.pem iCA-server/server.pem > iCA-server/server_and_ica.pem
+rm openssl.cnf.tmp
+
+echo
+echo "---[ Server - revoked ]-------------------------------------------------"
+echo
+
+cat ec-ca-openssl.cnf |
+ sed "s/ec-ca/iCA-server/" |
+ sed "s/#@CN@/commonName_default = server-revoked.w1.fi/" |
+ sed "s/#@ALTNAME@/subjectAltName=critical,DNS:server-revoked.w1.fi/" \
+ > openssl.cnf.tmp
+$OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -keyout iCA-server/server-revoked.key -out iCA-server/server-revoked.req -outform PEM -sha256
+$OPENSSL ca -config openssl.cnf.tmp -batch -keyfile iCA-server/private/cakey.pem -cert iCA-server/cacert.pem -create_serial -in iCA-server/server-revoked.req -out iCA-server/server-revoked.pem -extensions ext_server -md sha256
+$OPENSSL ca -config openssl.cnf.tmp -revoke iCA-server/server-revoked.pem -keyfile iCA-server/private/cakey.pem -cert iCA-server/cacert.pem
+cat iCA-server/cacert.pem iCA-server/server-revoked.pem > iCA-server/server-revoked_and_ica.pem
+rm openssl.cnf.tmp
+
+echo
+echo "---[ User ]-----------------------------------------------------------"
+echo
+
+cat ec-ca-openssl.cnf |
+ sed "s/ec-ca/iCA-user/" |
+ sed "s/#@CN@/commonName_default = user.w1.fi/" |
+ sed "s/#@ALTNAME@/subjectAltName=critical,DNS:user.w1.fi/" \
+ > openssl.cnf.tmp
+$OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -keyout iCA-user/user.key -out iCA-user/user.req -outform PEM -sha256
+$OPENSSL ca -config openssl.cnf.tmp -batch -keyfile iCA-user/private/cakey.pem -cert iCA-user/cacert.pem -create_serial -in iCA-user/user.req -out iCA-user/user.pem -extensions ext_client -md sha256
+cat iCA-user/cacert.pem iCA-user/user.pem > iCA-user/user_and_ica.pem
+rm openssl.cnf.tmp
+
+echo
+echo "---[ Verify ]-----------------------------------------------------------"
+echo
+
+$OPENSSL verify -CAfile ca.pem iCA-server/cacert.pem
+$OPENSSL verify -CAfile ca.pem iCA-user/cacert.pem
+$OPENSSL verify -CAfile ca.pem -untrusted iCA-server/cacert.pem iCA-server/server.pem
+$OPENSSL verify -CAfile ca.pem -untrusted iCA-server/cacert.pem iCA-server/server-revoked.pem
+$OPENSSL verify -CAfile ca.pem iCA-user/cacert.pem
+$OPENSSL verify -CAfile ca.pem -untrusted iCA-user/cacert.pem iCA-user/user.pem
--- /dev/null
+V 251222193736Z D8D3E3A6CBE3CCF3 unknown /C=FI/O=w1.fi/CN=Server Intermediate CA
+V 251222193736Z D8D3E3A6CBE3CCF4 unknown /C=FI/O=w1.fi/CN=User Intermediate CA
--- /dev/null
+unique_subject = no
--- /dev/null
+D8D3E3A6CBE3CCF5
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MIIG/gIBADANBgkqhkiG9w0BAQEFAASCBugwggbkAgEAAoIBgQDm91jBTdZzl79p
+4ZPklcK5EoOMvj3++QdZ+7pFKmDFHX8qqfk6HXz4fkFXMYokV2pFvRh+i+wvbAPc
+OLI6cxSSSz02yspRkcN1hDlERfjIrMrJq5M5GgoT1F2zQ0Wc+inXDetgIG1QOb+q
+oQR3mxMCQLphohv8n2JkW6+Lmdt9zsx9tOQWjFSB3YFdcb4yhGP5sJ4n8EanpNdR
+k0NbdKffehDDxXUtb4O1U6i/H1NFA0/l/oN0IuhwXkdkv8ikdpPke+FqCp8H6CZM
+vZrC3ItJpIm+k/eXIyAvW4hag/75GfGeV7b4MnVegcylWtacFpaDRsklfAStMXd5
+EOiC4cmANIYupoZwfiSadthk9BbBqzRAcpvFljgFeUeR5N8St4B1noPwatoMuMzh
+WG28Iv/hNr8Rj/vzWznO0xp3lPckZPVHzrl08U1QSH9j6SqsmGMY1Y4riRGzNkUf
+o7eV9GB8kKp6oWM6TCuyRbMhS0LB/TNH3682oBJMEftK5HBiTf8CAwEAAQKCAYEA
+txfjyzGaTH5CZnxFklLKT46GrF7vpJ3jnwi37DahCgHNGpQuF0zjEdZ8k9OY0CBg
+BbLWpRLlA97b3IsxdrZd2287sqDl6+3ihdlw0Fer1eFszJxwFDc5P+j88qvkloGW
+A35sVgK+xXdSIsCMWwia9BE970Hkb8ol5KruKXupjT0PzKNGoT1TjLN85wfRIBjl
+bD3/0mdei21Yp7lXDzwWDEmm2ptAvekF/wu33PLHPxFWGFw/9yPpIZMLg6mpM/8u
+0lWjpuTuQZLAVU0yKag5mhRa9rwCqslxDZzNXYA7hUO57hT+diO1U447cdAEYzpF
+XUZrPBHUOlaRNd2f2INFAX3W0SraSTp3IX2KBd3daU2aSN6y4DMO4I9wJwJV4vrC
+1rnJB+e9DnBNUezhgpiDOE0+vOprrqGtXsdULgFuPd47b2eU4WWvFHeeKuMBgrRg
+iRSgaxButfFIryRhCYA88cXFG0qO3qNUPMmDTCRjS1S6rhQeP8dxN6kcJc+o/+Ep
+AoHBAP95nPrypMNYJAlQtlgYMbxyMRLz7HXLN/TklEtPMNsjK8LHIIa3v3uv8gbk
+1VmXc8oQa4NB8cu9CtX98fSwvbiuwXjhxFe0mMlg4QdkbCQYXj3CeDsE5PNO3aXK
+oIF1WzJZYN+KV/NgyCIP/hAgBBmDFcfgovJb3YvMGmC3/2MmP3+1tgsLabPXoJSZ
+Uqc7c5m9Tlm7NP8LAi/zRjFOD+b3BDIH8e8ADV02uAYe0fyCcihaf7ZYbiROG2KE
+BNlbgwKBwQDncNdXOgz9bb0C+HymH0LwB0KECt2NNN0DV1GXoH8IXEYtK4V2XJdU
+P63EtMfaUgk0vyL/pIWQLlyt9bW0Gnr0nDY3NiX2ctRnh6WUzKNrpdQmhquEWXXw
+pujDupY2O90lXeJdMhp2WWT+22IFMykwLY2sVBJzhXpY2lUd/EBgFiUpD8NRAt2V
+f98eJYd3lC1JEsrEgCQrvEzc+B9y7GHPm8YevJrIcNvYMjUXEMo8rmjd+GZC4SD/
+rZVcCBrYDtUCgcEA7fbkjye26zJNltO0lYgrw8GGDoZgyjP5skW8EA36jxRKrcp3
+dKTxWo+/3EYIqMQXGa+DxaaGSGWVE1DQsEB05/L3ydZZ4ewZqPJxiUY0KMb9+X8M
+KMVdUXkzojuEmDGtOc/hGTeuxsdug7Przi9UQkNE5YJLpX6GdbIvG8onu74jxZyH
+re/6jIccT24lfBo3iou30IM9URd6+RkcV87DpzqNkOCvrRSaXioa7bCFnjQPi6EI
+dtwV9AFBJtmb/q5rAoHAAt/l7NFtw+APDvBjK/ULccvFSbqQ0eYsMJRvEQEPUt1C
+ieEWgUfZIVTBJcZRDScjsiIFn0M93XKV+BsrLJd/m3YtPjZP9mWqubZ3mgeIqBeh
+MPFPRA+QZXLNRVEV+Ip5zrMB0sKCjaHCnV/AMexWwKBwOAm7SPAJev0LPZoaepcL
+0xy9Ak6UzfyOmuNAcX3Hqjavig1FZb2q/rueOGEzPc7jgRI6oe607FSDUEwHFwXb
+i5ZAPuho7oQLbN805iYZAoHAReFyMpjLEXOfyJQAOZb1BQHJ4U8AyYyPleXB/Bh1
+EmO+Qv3VhtqorN0g3t7XaupEqcPBRWQHxo8hlrP+6Rj4fVnT8gFYOb1QMmy5EW2b
+0sdt74xLv4LI6TLLZim+akYNuFxQbBnLHJgDXgjinM+jZfzve39Uhz7ojrFaySqW
+bRcQzciRgbHWrSxkLGq+gJDyjvKkszs4RN9J7LH+C8+BiyRhgxc2ZTja75bq5TQB
+Tohu1wDMgHHInYJkhZNxYIGX
+-----END PRIVATE KEY-----
--- /dev/null
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 14110776913249282218 (0xc3d38cd72b01a8aa)
+ Signature Algorithm: sha384WithRSAEncryption
+ Issuer: C=FI, L=Helsinki, O=w1.fi, CN=SHA384 and SHA512 Root CA
+ Validity
+ Not Before: Nov 29 22:33:25 2015 GMT
+ Not After : Nov 26 22:33:25 2025 GMT
+ Subject: C=FI, O=w1.fi, CN=sha384.server.w1.fi
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (3072 bit)
+ Modulus:
+ 00:e6:f7:58:c1:4d:d6:73:97:bf:69:e1:93:e4:95:
+ c2:b9:12:83:8c:be:3d:fe:f9:07:59:fb:ba:45:2a:
+ 60:c5:1d:7f:2a:a9:f9:3a:1d:7c:f8:7e:41:57:31:
+ 8a:24:57:6a:45:bd:18:7e:8b:ec:2f:6c:03:dc:38:
+ b2:3a:73:14:92:4b:3d:36:ca:ca:51:91:c3:75:84:
+ 39:44:45:f8:c8:ac:ca:c9:ab:93:39:1a:0a:13:d4:
+ 5d:b3:43:45:9c:fa:29:d7:0d:eb:60:20:6d:50:39:
+ bf:aa:a1:04:77:9b:13:02:40:ba:61:a2:1b:fc:9f:
+ 62:64:5b:af:8b:99:db:7d:ce:cc:7d:b4:e4:16:8c:
+ 54:81:dd:81:5d:71:be:32:84:63:f9:b0:9e:27:f0:
+ 46:a7:a4:d7:51:93:43:5b:74:a7:df:7a:10:c3:c5:
+ 75:2d:6f:83:b5:53:a8:bf:1f:53:45:03:4f:e5:fe:
+ 83:74:22:e8:70:5e:47:64:bf:c8:a4:76:93:e4:7b:
+ e1:6a:0a:9f:07:e8:26:4c:bd:9a:c2:dc:8b:49:a4:
+ 89:be:93:f7:97:23:20:2f:5b:88:5a:83:fe:f9:19:
+ f1:9e:57:b6:f8:32:75:5e:81:cc:a5:5a:d6:9c:16:
+ 96:83:46:c9:25:7c:04:ad:31:77:79:10:e8:82:e1:
+ c9:80:34:86:2e:a6:86:70:7e:24:9a:76:d8:64:f4:
+ 16:c1:ab:34:40:72:9b:c5:96:38:05:79:47:91:e4:
+ df:12:b7:80:75:9e:83:f0:6a:da:0c:b8:cc:e1:58:
+ 6d:bc:22:ff:e1:36:bf:11:8f:fb:f3:5b:39:ce:d3:
+ 1a:77:94:f7:24:64:f5:47:ce:b9:74:f1:4d:50:48:
+ 7f:63:e9:2a:ac:98:63:18:d5:8e:2b:89:11:b3:36:
+ 45:1f:a3:b7:95:f4:60:7c:90:aa:7a:a1:63:3a:4c:
+ 2b:b2:45:b3:21:4b:42:c1:fd:33:47:df:af:36:a0:
+ 12:4c:11:fb:4a:e4:70:62:4d:ff
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Subject Key Identifier:
+ C8:A6:E4:81:75:69:7C:09:1D:A1:E6:14:CE:62:65:4E:56:D8:92:79
+ X509v3 Authority Key Identifier:
+ keyid:0E:74:B5:09:EC:FB:FA:E7:BA:6B:1A:F6:2B:28:7E:A9:70:DA:D7:18
+
+ X509v3 Subject Alternative Name: critical
+ DNS:sha384.server.w1.fi
+ X509v3 Extended Key Usage: critical
+ TLS Web Server Authentication
+ X509v3 Key Usage:
+ Digital Signature, Key Encipherment
+ Signature Algorithm: sha384WithRSAEncryption
+ 04:da:fd:8c:4d:ae:05:1a:bc:39:7d:b4:6e:b1:fa:9e:6c:39:
+ a1:58:24:49:59:0b:2a:d9:2c:c3:64:93:07:72:b0:37:3e:24:
+ 9d:b0:b4:6e:d7:4c:75:57:74:1a:4a:f1:34:4f:83:3d:eb:b3:
+ 77:a0:b3:1a:90:f2:6b:57:7b:46:a2:cb:f4:31:d8:9f:e8:1f:
+ 5c:3f:b3:ac:ff:2d:c8:d5:f2:1b:dd:7c:9b:b8:7f:61:13:3a:
+ b1:14:82:4d:52:cf:d0:dc:6f:20:e7:94:06:6b:9f:6d:49:dc:
+ 41:9b:9e:66:41:d6:45:15:af:92:00:6d:75:5f:95:93:ec:29:
+ 7d:f9:a8:57:1a:16:a4:f9:9e:ac:e1:86:f2:d3:38:25:16:e3:
+ a1:f2:9f:3b:7e:a7:9b:b9:e7:24:0f:f3:da:66:c4:de:34:3c:
+ 75:58:b2:64:e2:d1:2e:6d:ac:f8:03:d9:d2:a9:b6:67:d9:98:
+ 51:76:b5:1f:a8:a0:5f:73:65:dd:52:04:88:f4:e6:d7:cb:94:
+ 83:ac:08:29:25:c5:aa:8a:44:6d:73:14:cf:9a:48:24:ab:46:
+ d1:85:ee:29:81:e6:23:03:82:57:34:2c:f8:e1:5f:03:53:79:
+ f7:ca:b3:58:2c:60:8f:52:d1:20:6e:f0:5a:f4:7e:52:fa:a8:
+ fa:4d:6c:a8:67:d6:da:a5:da:9c:54:c6:34:3a:ca:06:32:a8:
+ 45:3b:41:95:6e:81:07:9b:f4:fb:6a:4b:7c:ee:d5:7f:30:7e:
+ c2:39:8d:88:b4:c9:62:5f:14:3a:1c:48:9d:b6:06:d8:8e:12:
+ 1c:99:e0:d6:7a:a6:e4:0a:b4:23:33:98:3a:00:5b:2d:d2:0a:
+ 05:b8:9c:1f:9d:f0:1e:a0:d4:88:35:0e:47:bc:59:f3:f2:08:
+ 5e:f6:11:b2:53:b3:b4:80:c9:3b:18:e4:51:45:43:9b:7b:8f:
+ 7d:23:0b:2e:66:da:29:b9:0c:98:16:7a:2b:b5:a7:37:e1:f6:
+ 20:cc:06:56:50:7c:36:6b:f3:c8:00:08:7b:bb:df:4d:94:e1:
+ 04:49:7b:e7:c7:77:66:c1:42:59:f3:40:91:eb:c7:98:14:cc:
+ 3f:26:0d:7c:8a:c9:9e:ce:2e:82:99:5b:b3:9a:39:a4:56:8d:
+ 46:13:fa:dc:6e:a0:6d:43:68:05:53:78:c9:d7:dd:45:ca:b1:
+ 0f:ca:ef:e5:5f:54:8e:52:94:ee:4b:ab:0d:dd:02:81:e5:92:
+ d9:b8:6a:58:7f:14:f4:a7:9a:18:9c:51:4f:ec:5f:7e:6e:b1:
+ 4a:46:bf:5d:c7:4f:19:16:f5:df:0c:fc:92:4b:d8:23:e9:7b:
+ 43:38:82:5e:82:f7:04:e1
+-----BEGIN CERTIFICATE-----
+MIIFLDCCAxSgAwIBAgIJAMPTjNcrAaiqMA0GCSqGSIb3DQEBDAUAMFQxCzAJBgNV
+BAYTAkZJMREwDwYDVQQHDAhIZWxzaW5raTEOMAwGA1UECgwFdzEuZmkxIjAgBgNV
+BAMMGVNIQTM4NCBhbmQgU0hBNTEyIFJvb3QgQ0EwHhcNMTUxMTI5MjIzMzI1WhcN
+MjUxMTI2MjIzMzI1WjA7MQswCQYDVQQGEwJGSTEOMAwGA1UECgwFdzEuZmkxHDAa
+BgNVBAMME3NoYTM4NC5zZXJ2ZXIudzEuZmkwggGiMA0GCSqGSIb3DQEBAQUAA4IB
+jwAwggGKAoIBgQDm91jBTdZzl79p4ZPklcK5EoOMvj3++QdZ+7pFKmDFHX8qqfk6
+HXz4fkFXMYokV2pFvRh+i+wvbAPcOLI6cxSSSz02yspRkcN1hDlERfjIrMrJq5M5
+GgoT1F2zQ0Wc+inXDetgIG1QOb+qoQR3mxMCQLphohv8n2JkW6+Lmdt9zsx9tOQW
+jFSB3YFdcb4yhGP5sJ4n8EanpNdRk0NbdKffehDDxXUtb4O1U6i/H1NFA0/l/oN0
+IuhwXkdkv8ikdpPke+FqCp8H6CZMvZrC3ItJpIm+k/eXIyAvW4hag/75GfGeV7b4
+MnVegcylWtacFpaDRsklfAStMXd5EOiC4cmANIYupoZwfiSadthk9BbBqzRAcpvF
+ljgFeUeR5N8St4B1noPwatoMuMzhWG28Iv/hNr8Rj/vzWznO0xp3lPckZPVHzrl0
+8U1QSH9j6SqsmGMY1Y4riRGzNkUfo7eV9GB8kKp6oWM6TCuyRbMhS0LB/TNH3682
+oBJMEftK5HBiTf8CAwEAAaOBmTCBljAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTI
+puSBdWl8CR2h5hTOYmVOVtiSeTAfBgNVHSMEGDAWgBQOdLUJ7Pv657prGvYrKH6p
+cNrXGDAhBgNVHREBAf8EFzAVghNzaGEzODQuc2VydmVyLncxLmZpMBYGA1UdJQEB
+/wQMMAoGCCsGAQUFBwMBMAsGA1UdDwQEAwIFoDANBgkqhkiG9w0BAQwFAAOCAgEA
+BNr9jE2uBRq8OX20brH6nmw5oVgkSVkLKtksw2STB3KwNz4knbC0btdMdVd0Gkrx
+NE+DPeuzd6CzGpDya1d7RqLL9DHYn+gfXD+zrP8tyNXyG918m7h/YRM6sRSCTVLP
+0NxvIOeUBmufbUncQZueZkHWRRWvkgBtdV+Vk+wpffmoVxoWpPmerOGG8tM4JRbj
+ofKfO36nm7nnJA/z2mbE3jQ8dViyZOLRLm2s+APZ0qm2Z9mYUXa1H6igX3Nl3VIE
+iPTm18uUg6wIKSXFqopEbXMUz5pIJKtG0YXuKYHmIwOCVzQs+OFfA1N598qzWCxg
+j1LRIG7wWvR+Uvqo+k1sqGfW2qXanFTGNDrKBjKoRTtBlW6BB5v0+2pLfO7VfzB+
+wjmNiLTJYl8UOhxInbYG2I4SHJng1nqm5Aq0IzOYOgBbLdIKBbicH53wHqDUiDUO
+R7xZ8/IIXvYRslOztIDJOxjkUUVDm3uPfSMLLmbaKbkMmBZ6K7WnN+H2IMwGVlB8
+NmvzyAAIe7vfTZThBEl758d3ZsFCWfNAkevHmBTMPyYNfIrJns4ugplbs5o5pFaN
+RhP63G6gbUNoBVN4ydfdRcqxD8rv5V9UjlKU7kurDd0CgeWS2bhqWH8U9KeaGJxR
+T+xffm6xSka/XcdPGRb13wz8kkvYI+l7QziCXoL3BOE=
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MIIGnAIBADANBgkqhkiG9w0BAQEFAASCBoYwggaCAgEAAoIBaw1HuCl0ydhb9q0E
+epVENi+Gp7eksHMq2Rx97T29DDwFe8jpVlVWJ1b0oKq96+o6RSzYtp1UGhgSCXiw
+ZPZgrVmZAnJJJU9JceoJDl3PIhkDKfApKxz9LvrmajocRiezZoaTIKj31URKALae
+Id/aY/+ACoBBxIeZoH5g8zPDIg4jEPQJ8ul3WMfKY96vFne1SGjri5iwj72RV+9t
+Pi/jgNSEwgFvUIp/mxR9bT4EmfdXwFhDUlfb7YRA45fzewcualxQE1P+LX7919i5
+mz4zH+OQFvFRtx6VwHVq9Hea2Ix0k3/0JUl1arSbE8h3J5aO377wDUK9DDfjFc8t
+qV4S1rZaJo2Gw++sLni28HBj4iw9qOuLThVRuZA1uDiBvbap9VcJiiDy6RKyyE1X
+Y230W6bXOGKbcw4h1QDLoDOMxDJTXsVOzErCE6Be8K9SviwWFIpdF3xL1i+ddKhi
+dd/Kp59niREH4qvg68TUrQIDAQABAoIBawv9Rt9uh9gkVpSnaYAfIAhSOlLKhV7E
+PVTCv4+wgD4j+ThOqNnMOSIBIphjdHx3dQJi+KMbTZ+TkSd7oPrqFza/s/y32s41
+EXnoCSdaHH+WYqNml3zJe0ObCCZEZnXrOlGevKqvbMQFR5WXOB/gC82crF5Ugfim
+EsZmAssljTZUJDceUEbEr8tYBkgBrHgQmznWBaapKGxNrqUC7FTRwPqcjIY9F+qh
+/8FE535JKzOp7oYA6XNQDLCUMI5oALmc5lq/a9g+HQpr26LNxQW5fadOKQUwZFiJ
+nRtcQo6+JZzXdobH5FZ1oNi2uOHVSiQnnQgqhESJ6jLGWJxVUGXo6kqBWWmICF9D
+g07ky+mssXXCPvNwtG9Mc4yh2Mm+LzDJI1rgMgoA08N0j+q5fT8QzmDZEmM/Gzsf
+NP/GjsLIXE+KjMcILrxDtvbNRv/hx/ys9yQjK9+VR7+uZWmXYaxH3r7D8g5XHdBz
+5/XCpQKBtgPYnHvwMRsZsQZae25/FCUfBT97JmGhr8ifGv0dhSZKRcP4zNtGU4ow
+H6J/B/eecH6bVb4/ja/nSUlLIoAUqqJWWurXdkwZII3b3PzbkqkCnZayBy2x3OIi
+VE7bVUpCSz0EIyuUjqrwc/d3PqrIARwiuucbgXqC8gqaAEUoXQGRGGKoerZLv/dQ
+VyTlyjXDlJYLub7cLBBCo8mpii6AFbc0Js+1qZJfUp0D+12qlfu9qy1W3/efAoG2
+A3PuRMQtWn0q84o36zQaJRbMQlymiMOMQBzFmR8GUiAiXHUqPZgAPsvzs7RllCTL
+ItDiKMcpE6/6MN0ArmDHA5bnAnu29SkPRiD7rU/ZGTR2Y9uujj0DIBcNHS/bbDtT
+xEwFnshSz6vvpxu6DtJ8uvEf3wJyeZmdMJeDmrBnadqT2juZIseGHneHrjJK3ZyU
+iLRI0ulXAbziwxnkKj9QUaHK0XiSzjAAt5NRTLoALix0ittJgDMCgbYBnDEGgatN
+GRhO/Jony/N3BuF/jeKnhLS+XD1EMZOIUBeczw+TzIE0nKjhsiR3uVCG8CiZGKoM
+NdssX9P1orE8fMJbBhB0EyDZwm1lPdbMAlhOugDfVFKQKKb6zD+McuxkgtLmb666
+SSeDNdx6SniMes2b6pvt2dvSLF5olVk6Sq/WvYmBv3yB4JRa0ggxMcuGdSoxiKK5
+u+wthFhg1yZAKAkHc5mluVoweXZF5CAd321F8dSZKQKBtgEEpWTXqDv/nrOztSuA
+8JixMUf8RAseBnQ9R7MQJ+/9k8RJtEv3T1M1FsaN0kot00yP5bB6kc1BXfgcov/I
+f8a6L6JW0qtWES/vt+byHaVGCAcIF1/P8+T5hx9tJjmzAM9oT1vz3B9qpr9S+Lk4
+Lhl90pUTBqh+uJBEjUUG8WeQUXrPiidsSEshmfuuzs6sRkxNRRAUSFi11vQK5XHj
+u45mtASyli+AjiWTpiyGyFjVOQRdBz5rAoG1ErrUGzeHL9plx9NPsUgw2TMAt//g
+yu1a9yDl6oARMkWMXKFytPBwwBY6H0zE74qvVQVcxHEMLGTOiLTHU57meGfVbfW+
+ikWO82ztD30nSrQ2vH3sZjeftU98R7y8L+f9icNftUTo3oA1pU8QuOj+2J/ja2Pa
+ksRDoe8fqUCi3OhiG7dhBcuK4wc0p17qjmKS+fA/Ky4yV24LuxWp1ge737rjlrvm
+hoCJF/ERHMvfrviGjrs+Rg==
+-----END PRIVATE KEY-----
--- /dev/null
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 14110776913249282220 (0xc3d38cd72b01a8ac)
+ Signature Algorithm: sha384WithRSAEncryption
+ Issuer: C=FI, L=Helsinki, O=w1.fi, CN=SHA384 and SHA512 Root CA
+ Validity
+ Not Before: Nov 29 22:33:25 2015 GMT
+ Not After : Nov 26 22:33:25 2025 GMT
+ Subject: C=FI, O=w1.fi, CN=user-sha384
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2900 bit)
+ Modulus:
+ 0d:47:b8:29:74:c9:d8:5b:f6:ad:04:7a:95:44:36:
+ 2f:86:a7:b7:a4:b0:73:2a:d9:1c:7d:ed:3d:bd:0c:
+ 3c:05:7b:c8:e9:56:55:56:27:56:f4:a0:aa:bd:eb:
+ ea:3a:45:2c:d8:b6:9d:54:1a:18:12:09:78:b0:64:
+ f6:60:ad:59:99:02:72:49:25:4f:49:71:ea:09:0e:
+ 5d:cf:22:19:03:29:f0:29:2b:1c:fd:2e:fa:e6:6a:
+ 3a:1c:46:27:b3:66:86:93:20:a8:f7:d5:44:4a:00:
+ b6:9e:21:df:da:63:ff:80:0a:80:41:c4:87:99:a0:
+ 7e:60:f3:33:c3:22:0e:23:10:f4:09:f2:e9:77:58:
+ c7:ca:63:de:af:16:77:b5:48:68:eb:8b:98:b0:8f:
+ bd:91:57:ef:6d:3e:2f:e3:80:d4:84:c2:01:6f:50:
+ 8a:7f:9b:14:7d:6d:3e:04:99:f7:57:c0:58:43:52:
+ 57:db:ed:84:40:e3:97:f3:7b:07:2e:6a:5c:50:13:
+ 53:fe:2d:7e:fd:d7:d8:b9:9b:3e:33:1f:e3:90:16:
+ f1:51:b7:1e:95:c0:75:6a:f4:77:9a:d8:8c:74:93:
+ 7f:f4:25:49:75:6a:b4:9b:13:c8:77:27:96:8e:df:
+ be:f0:0d:42:bd:0c:37:e3:15:cf:2d:a9:5e:12:d6:
+ b6:5a:26:8d:86:c3:ef:ac:2e:78:b6:f0:70:63:e2:
+ 2c:3d:a8:eb:8b:4e:15:51:b9:90:35:b8:38:81:bd:
+ b6:a9:f5:57:09:8a:20:f2:e9:12:b2:c8:4d:57:63:
+ 6d:f4:5b:a6:d7:38:62:9b:73:0e:21:d5:00:cb:a0:
+ 33:8c:c4:32:53:5e:c5:4e:cc:4a:c2:13:a0:5e:f0:
+ af:52:be:2c:16:14:8a:5d:17:7c:4b:d6:2f:9d:74:
+ a8:62:75:df:ca:a7:9f:67:89:11:07:e2:ab:e0:eb:
+ c4:d4:ad
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ X509v3 Subject Key Identifier:
+ 85:5F:26:C0:68:70:33:79:E3:BA:57:A3:5F:52:94:38:F0:6E:53:05
+ X509v3 Authority Key Identifier:
+ keyid:0E:74:B5:09:EC:FB:FA:E7:BA:6B:1A:F6:2B:28:7E:A9:70:DA:D7:18
+
+ X509v3 Subject Alternative Name:
+ email:user-sha384@w1.fi
+ X509v3 Extended Key Usage:
+ TLS Web Client Authentication
+ X509v3 Key Usage:
+ Digital Signature, Key Encipherment
+ Signature Algorithm: sha384WithRSAEncryption
+ 81:95:03:32:e7:e5:e3:0e:22:0e:cc:a5:b5:96:3e:15:a8:6c:
+ f5:e2:1f:32:b9:09:71:b5:fa:f4:84:ae:e1:8c:d4:cb:ef:e3:
+ b4:58:aa:bd:bc:df:6a:9c:91:9b:5a:d4:e1:b0:1c:dc:dc:e9:
+ b6:68:71:83:e1:7e:1c:81:fd:a6:3b:14:67:1a:67:64:ed:a8:
+ 3c:43:2f:cf:e1:63:51:f0:9d:1d:e7:0c:0f:58:bc:bd:bf:af:
+ ee:55:f8:1f:5a:9e:1f:c2:74:f0:8a:e4:5f:b2:19:e3:e8:c2:
+ 5c:1c:39:f4:24:51:ae:d2:21:da:b8:12:97:ff:2a:d9:ff:61:
+ 02:31:1f:87:3b:14:0b:7b:9a:77:11:a8:83:25:38:6a:1d:89:
+ fc:48:75:8c:2f:38:a7:66:ee:a9:65:2c:d9:f8:bf:e0:12:d6:
+ b7:11:07:d0:72:a8:76:53:32:94:39:47:be:74:69:f6:6b:13:
+ 2f:eb:e1:a2:8e:32:43:0a:cc:13:ea:00:29:cc:99:7b:eb:5c:
+ 06:d5:4d:ef:6e:2a:96:6b:33:a3:6f:53:0c:59:4e:89:9b:56:
+ f6:a3:94:0d:7b:21:df:0e:af:b7:df:cf:56:98:81:02:9d:e2:
+ f1:29:90:2e:7f:be:4d:24:6f:46:8d:af:ff:f9:30:7b:40:48:
+ 1c:1b:68:6e:9f:ec:e2:33:51:7c:ed:ee:12:bb:3a:97:ce:85:
+ fe:d9:c3:0b:1a:a6:1b:12:bb:db:4f:f3:b1:e5:80:25:b9:62:
+ 7a:e9:8e:17:44:97:cc:54:bf:8e:c3:aa:37:b2:74:e9:58:9b:
+ d7:53:00:4d:82:c2:42:ba:c1:c2:7f:00:fa:da:06:dc:98:04:
+ 68:35:d6:3c:14:4e:dc:4d:e4:d8:b9:b5:e2:17:79:91:3b:d7:
+ c7:f1:ff:e7:a3:25:68:c4:96:29:c6:b9:45:e3:3d:1c:29:22:
+ 2f:0b:c7:8c:8e:b6:0a:0a:82:20:0b:50:ca:e6:c6:de:01:38:
+ f9:3b:31:e0:1c:85:11:bd:a9:9e:bf:8c:f7:f2:64:03:ca:60:
+ 16:2d:26:94:eb:9f:8a:d0:5e:1c:eb:3c:26:7e:03:84:d2:f0:
+ 5a:b3:8a:7b:86:86:67:ce:1e:c9:c8:ad:3b:0f:08:7f:3e:54:
+ fa:ad:e4:5e:3f:c1:cb:50:3a:dd:ba:b1:0e:d2:9b:88:46:17:
+ bb:67:cf:5c:11:f3:a3:f7:0b:95:ae:25:ce:3c:e9:ca:aa:46:
+ f8:a9:8c:cf:a9:cb:bc:00:94:a1:c7:02:98:1e:e5:b1:c7:e7:
+ 51:50:f7:5e:a5:c8:e9:ff:e0:50:17:cc:10:c5:f8:0a:68:ba:
+ ca:78:f8:1a:6c:ac:f2:10
+-----BEGIN CERTIFICATE-----
+MIIFAzCCAuugAwIBAgIJAMPTjNcrAaisMA0GCSqGSIb3DQEBDAUAMFQxCzAJBgNV
+BAYTAkZJMREwDwYDVQQHDAhIZWxzaW5raTEOMAwGA1UECgwFdzEuZmkxIjAgBgNV
+BAMMGVNIQTM4NCBhbmQgU0hBNTEyIFJvb3QgQ0EwHhcNMTUxMTI5MjIzMzI1WhcN
+MjUxMTI2MjIzMzI1WjAzMQswCQYDVQQGEwJGSTEOMAwGA1UECgwFdzEuZmkxFDAS
+BgNVBAMMC3VzZXItc2hhMzg0MIIBjDANBgkqhkiG9w0BAQEFAAOCAXkAMIIBdAKC
+AWsNR7gpdMnYW/atBHqVRDYvhqe3pLBzKtkcfe09vQw8BXvI6VZVVidW9KCqvevq
+OkUs2LadVBoYEgl4sGT2YK1ZmQJySSVPSXHqCQ5dzyIZAynwKSsc/S765mo6HEYn
+s2aGkyCo99VESgC2niHf2mP/gAqAQcSHmaB+YPMzwyIOIxD0CfLpd1jHymPerxZ3
+tUho64uYsI+9kVfvbT4v44DUhMIBb1CKf5sUfW0+BJn3V8BYQ1JX2+2EQOOX83sH
+LmpcUBNT/i1+/dfYuZs+Mx/jkBbxUbcelcB1avR3mtiMdJN/9CVJdWq0mxPIdyeW
+jt++8A1CvQw34xXPLaleEta2WiaNhsPvrC54tvBwY+IsPajri04VUbmQNbg4gb22
+qfVXCYog8ukSsshNV2Nt9Fum1zhim3MOIdUAy6AzjMQyU17FTsxKwhOgXvCvUr4s
+FhSKXRd8S9YvnXSoYnXfyqefZ4kRB+Kr4OvE1K0CAwEAAaOBjjCBizAJBgNVHRME
+AjAAMB0GA1UdDgQWBBSFXybAaHAzeeO6V6NfUpQ48G5TBTAfBgNVHSMEGDAWgBQO
+dLUJ7Pv657prGvYrKH6pcNrXGDAcBgNVHREEFTATgRF1c2VyLXNoYTM4NEB3MS5m
+aTATBgNVHSUEDDAKBggrBgEFBQcDAjALBgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQEM
+BQADggIBAIGVAzLn5eMOIg7MpbWWPhWobPXiHzK5CXG1+vSEruGM1Mvv47RYqr28
+32qckZta1OGwHNzc6bZocYPhfhyB/aY7FGcaZ2TtqDxDL8/hY1HwnR3nDA9YvL2/
+r+5V+B9anh/CdPCK5F+yGePowlwcOfQkUa7SIdq4Epf/Ktn/YQIxH4c7FAt7mncR
+qIMlOGodifxIdYwvOKdm7qllLNn4v+AS1rcRB9ByqHZTMpQ5R750afZrEy/r4aKO
+MkMKzBPqACnMmXvrXAbVTe9uKpZrM6NvUwxZTombVvajlA17Id8Or7ffz1aYgQKd
+4vEpkC5/vk0kb0aNr//5MHtASBwbaG6f7OIzUXzt7hK7OpfOhf7ZwwsaphsSu9tP
+87HlgCW5YnrpjhdEl8xUv47DqjeydOlYm9dTAE2CwkK6wcJ/APraBtyYBGg11jwU
+TtxN5Ni5teIXeZE718fx/+ejJWjElinGuUXjPRwpIi8Lx4yOtgoKgiALUMrmxt4B
+OPk7MeAchRG9qZ6/jPfyZAPKYBYtJpTrn4rQXhzrPCZ+A4TS8FqzinuGhmfOHsnI
+rTsPCH8+VPqt5F4/wctQOt26sQ7Sm4hGF7tnz1wR86P3C5WuJc486cqqRvipjM+p
+y7wAlKHHApge5bHH51FQ916lyOn/4FAXzBDF+Apousp4+BpsrPIQ
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQCgV1xtgG7ws5e4
+N+F5KfWrEMKzsP5P8PXVMiB6Rv/Wuzi1EHZjNdbUQuVV+hHRI1K2ReqXAeaNyhEE
+Jn42hGndcHKHfcAUTQWQWfCscP32Ti2YSViHD60sqZKr4agDoLkMR21BMHXgrU6W
+QED070WE0CbELVUtcb17oPh/ndh46Ftb5U6H5rpY8T13148xhNCh8yKAOcFfE9GW
+Z3mTMp+VxmcK72KL4Yga7bU3Uk5xHlFZ0rK1W0xItEi+SGfMLELalP6wAYMVtPAA
+iqepg3WSq5eNyZgTwq5jAuLP/4Bf1C7WhNveFE9WalJ3rrYEs7Rd+mOYm0QXcH8t
+IqC9UTUhfI3wJOpLGEfHieLHCDl8SYijET+hFFTYiU1jj4sQjAeY8VnC7/tmjJpC
+j6oNcbr57WwMxO/Xafo0JW3axZiyfDUlPShPbhyBjhq2/3wOKJUbeK/cY9J0CjW1
+5k8DYjSC0vGFwl4CRmhfN/5XeO9kGQR9kQjha59v2/gW4wKFnuqPyWyY4vWgcEmc
+8kqJqrkR61fwZ3H7G5ErMw/q/jR9tuqcTuRvQjh1LEtv2UxzNg68L73nhqT4UQRO
+uXkXPsUCN13Bgm3OzTul+zmbXtRlH/2oc+16IyzICj5VWpiZgC7D7Ljnlquvo1/3
+EitInFWjEl8kpsPJnBT4id/xrJHoywIDAQABAoICAFFF1ti+R/2D2ryKvqQOy7KJ
+DVfNuCpHJiSJgwLX6CgswAKvNIL3MExpGBvrZIqQkAVKDS27zeRC7zseU81IcuzG
+aZcZ+3mOzOotXJvbri7h06SkUNYs8Qd5cJnlCKfGGOYLcmqfqLBYyEPKj+JXQfKf
+G3dGzyz4wSXgIvV0ydwHUv+SjKrAHealaRXM0o00GBhuyCccn1KVFiBZlLsy5sch
+SOu3CUmD6NxVbwx6kL4vsuaHsQPSIimcEF87DjnkmYJ4EVyfd5VSIHD11yRKORc+
+GNTKwWYKwR/4v4TUqnpob9FWiKfZvZk8zU5S5XoeqKcWGtOop+wFnsD/E2DCv93K
+vbY0n5B5L5XFjtmBYuvdqXe4RH46ZgyePI3G6DSTCq5L8/+5pZlTeny4Vz77ecm8
+CU/4XOcYMIBZim9Fie4jQLpD4KNjKjhXLjpetNyHp3sIoghb90Qv5UdLZ6dnf4+D
+nxbg+tfvwltNfPgCvrOh3OcnSSLUSb5kSim0xpFtaH5QgAQhVaFaDY8GtaOnPyRG
+39XPwpAQXpt8EyW4omwtI8QL+/bciQNg0tVLHkxg7qOEPWGoaxvQbxT8EBGufRz9
+7qvl1ajGEAeaDY62HUssBW2+YhFKNLbzWBVO/S4AWPYPLMeAVQfFNVXWyS5www7P
+DfQXAt+rwLWwfvpW2C2BAoIBAQDVVXpIykVnUuQoRclLMnm8Z5DMfWOP/Oj3Em2z
+nKvnyM+rXEr7sT7XLAJa4aU0Fg27omUXZpNB6UDntWLOHXi+Zh3PgMd1CqdIclVK
+z6uGfK9TKHIQpYY7RLGcvBAjfnyv2KKcqBi2IQEXidoHLtZ2gQJJQ1Aoiw8gIQAe
+kZjXwcxlEgDdVR4+Zamj5QRfAG7Nd7PVl06gJNyCinS21/UFELz6hB4COgVjOPzr
+FvhoPrZE6QUNm76wFVXhYl9Taj/lM+0q5b88ZCJCqhma6aGOuVRaSpaTeRYC63ys
+oTYdUR5Cc7Z4h8iFW4S6Qs992MvH3k73R6/ad0o8kaUrZU1BAoIBAQDAaLP8jjc8
+4cDi3lNos0cSiF2OBazsCAsI5IRovkkugSDYK9FKOrQ0P8mFTsA+IapAe8gMIjZY
+ivRJ8dQ8beNhub9gULlNpp8VZ0QJV5jn1qp1vqW72ti28KcwPFTSmQZKMevwl6Bw
+t/s3RY3SndU3LJ1RdtZuhC9tgAGbH/Os524kvBc8sPjQkwRP8MABF/4XTS1aR7yO
+6kka1ZxJ32X7Chz7pO/IagTmAhJmbLkponWPtCvwlHx8SFE0dyC86snhb7CIr8B/
++1BBueTjUhrhADCm6X106hIgm7C2o9m+x92Y7KHM4yEjHEo8+VVC8WV5TmcXOqMM
+nqYCHeNn1tcLAoIBAQC9w2MbDJHf7uP0zt7XfPa8mIM84uyFUDsKS+I5OsvPSdkw
+XNB2QpvbWtJddQo24sckeLfjsOKcZpfNhJN3NNAKzVsHEU5a1jcnQkyMV14EKzTp
+i7irBhH49onnGYJhkEnpQZKkNwKEP6dxALZoXUl38BnQgYf0CH5T3gb1Kh4DDeh6
+nyEVwHk+l7/mgfj5aLEnI6tb+1N9MEzV8cMQQdk5wEHZtVvcLzBLqo2PsMcWM3J+
+qahNCpT8nH3gFlklIgXkI+R7nBIX7hprolNUcS28fy6Bgoeedr8VqdMk2+H/AgEg
+qz1MybucpGPUK0nWb9oU17L2U1YhxqrKZeO+TkYBAoIBAAu7Vp4jncKckUJEBBny
+NHcw0WODfRO3OdUE+f3Y/GVVgkcsBMrd4Xb+HK+AKcCgFN1xrrTusRmc/2Ay2poE
+qUSgKscYpPPTIQgRD9jx+mTIdgRP55MYuPYOnmMWiqV8pyGHAbfdxu6YiTzJhOg+
+r215zu3UrSZ38NxgXbizrgvw4Ipk3ZXZxJITJMQrDcoDSH7rOcSzcw/TwTldpPXs
+JS+1YicF24kAzeOoZK7SGkgrm7dzaOp2Y1DAqBLm4JwkRML2KHFtJfOnwzD+wLIL
+o4/sjwreWcPzMb/DPnckbnZvgVd9ti/j+XVGmFA3c7dtOJ645RhJfv+Z/M1MPT1r
+oBkCggEAWqkhZDArd1EqwauhCKwAb2Bp8IVd3rAyaBMtQZVebf467rMh0o4FaPZb
+a4oTZQEAAvlabbKiNW16kmdhzhXNIpgtsTQ1ZfagjHP3fPp0mz3XQiATudaxQBVH
+o7hKafsr2YJLWD03RO+hO2UPr/rLqN9+8/MlT5pityn1QZHpHf9qzliUhw/2zAjq
+kgygbM8UCEXl7zb7ptxaiPsxBn+ynwxgzibwLRHiePOfil8fD5hyE/5gRISrQidA
+VO5RzhqnD3kDH7Da8BPJt917CsgvZ+VffzDP4D/V+L1a/R1ldyXG+omn7qED1ui6
+V2qOAd4RYJFC9FFgNAWy22r3lSYw+g==
+-----END PRIVATE KEY-----
--- /dev/null
+-----BEGIN CERTIFICATE-----
+MIIFkTCCA3mgAwIBAgIJAPz9Jkl2amj5MA0GCSqGSIb3DQEBDQUAMFQxCzAJBgNV
+BAYTAkZJMREwDwYDVQQHDAhIZWxzaW5raTEOMAwGA1UECgwFdzEuZmkxIjAgBgNV
+BAMMGVNIQTM4NCBhbmQgU0hBNTEyIFJvb3QgQ0EwHhcNMTUxMTI5MjIzMzI0WhcN
+MjUxMTI2MjIzMzI0WjBUMQswCQYDVQQGEwJGSTERMA8GA1UEBwwISGVsc2lua2kx
+DjAMBgNVBAoMBXcxLmZpMSIwIAYDVQQDDBlTSEEzODQgYW5kIFNIQTUxMiBSb290
+IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAoFdcbYBu8LOXuDfh
+eSn1qxDCs7D+T/D11TIgekb/1rs4tRB2YzXW1ELlVfoR0SNStkXqlwHmjcoRBCZ+
+NoRp3XByh33AFE0FkFnwrHD99k4tmElYhw+tLKmSq+GoA6C5DEdtQTB14K1OlkBA
+9O9FhNAmxC1VLXG9e6D4f53YeOhbW+VOh+a6WPE9d9ePMYTQofMigDnBXxPRlmd5
+kzKflcZnCu9ii+GIGu21N1JOcR5RWdKytVtMSLRIvkhnzCxC2pT+sAGDFbTwAIqn
+qYN1kquXjcmYE8KuYwLiz/+AX9Qu1oTb3hRPVmpSd662BLO0XfpjmJtEF3B/LSKg
+vVE1IXyN8CTqSxhHx4nixwg5fEmIoxE/oRRU2IlNY4+LEIwHmPFZwu/7ZoyaQo+q
+DXG6+e1sDMTv12n6NCVt2sWYsnw1JT0oT24cgY4atv98DiiVG3iv3GPSdAo1teZP
+A2I0gtLxhcJeAkZoXzf+V3jvZBkEfZEI4Wufb9v4FuMChZ7qj8lsmOL1oHBJnPJK
+iaq5EetX8Gdx+xuRKzMP6v40fbbqnE7kb0I4dSxLb9lMczYOvC+954ak+FEETrl5
+Fz7FAjddwYJtzs07pfs5m17UZR/9qHPteiMsyAo+VVqYmYAuw+y455arr6Nf9xIr
+SJxVoxJfJKbDyZwU+Inf8ayR6MsCAwEAAaNmMGQwHQYDVR0OBBYEFA50tQns+/rn
+umsa9isofqlw2tcYMB8GA1UdIwQYMBaAFA50tQns+/rnumsa9isofqlw2tcYMBIG
+A1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDQUA
+A4ICAQCSG0Tk6pMvUxSMi9q4Bnq1jjMehEVZH6JHoADSjYDpRYj26Zjzd5k1qRua
+rdAlugMaV/Jq0kcebcvIRl1de0BPx7qfRzq39lSVDojtefjj824EsYj+rBssmwUZ
+e5XfXzxSmfEtT7Ot1PMLyCUCeg7JPr0dbdo7EVjh6XhYo0IlLsOJcKwfj/z74K14
+SlL1jXknhQgizCzt/gFkrdrFFCg0cCTjG5gKVHnn97GY61PI1CEMYGjkP2x7wv2o
+dJE09ElEPjrQOiShqfmfeUOuM6xmYzZFtVWp/M+tEQdL5WsBrN2dujHA+Ftf3xrF
+aRlGLFCzqlC+HU1CSsiI4gXXJT4Bp6WrVP/insAuuS/a8KQRkox8JvPBOqnYf/m4
+JvGJbhukEgbhUdUON4UtWwr3pTkt16SKmE3IdG/Umabi+bSkMmSzw3Iy12LOkrhT
+5OVbU+EwFolc6WUmp5VnhD/NtNdTvaTIjuujU4MyXkBfHvPj4bR62/cSXdGL4LzL
+UjlrFEN3RnFiF4/slrT4z4VRa4FqaYg+aRnMuGwPMHBjUTmyQp1yjF0kp/MYDGF7
+YO46+ep1pwx7zboB1nsKPdLzwEHvO7p6yBO2daEBCiE4RpedSjkpNhYgfHn4WVoX
+NPZChYbX8mGds3xnB6BGsfvzXEtCtmOGbDRIJm6aB7qTrfHiYA==
+-----END CERTIFICATE-----
--- /dev/null
+#!/bin/sh
+
+OPENSSL=openssl
+
+DIGEST="-sha512"
+DIGEST_CA="-md sha512"
+
+echo
+echo "---[ Root CA ]----------------------------------------------------------"
+echo
+
+cat ec-ca-openssl.cnf |
+ sed "s/#@CN@/commonName_default = SHA384 and SHA512 Root CA/" \
+ > ec-ca-openssl.cnf.tmp
+$OPENSSL req -config ec-ca-openssl.cnf.tmp -batch -x509 -new -newkey rsa:4096 -nodes -keyout sha512-ca.key -out sha512-ca.pem -outform PEM -days 3650 $DIGEST
+mkdir -p ec-ca/certs ec-ca/crl ec-ca/newcerts ec-ca/private
+touch ec-ca/index.txt
+rm ec-ca-openssl.cnf.tmp
+
+echo
+echo "---[ Server SHA-512 ]---------------------------------------------------"
+echo
+
+cat ec-ca-openssl.cnf |
+ sed "s/#@CN@/commonName_default = sha512.server.w1.fi/" |
+ sed "s/#@ALTNAME@/subjectAltName=critical,DNS:sha512.server.w1.fi/" \
+ > ec-ca-openssl.cnf.tmp
+$OPENSSL req -config ec-ca-openssl.cnf.tmp -batch -new -newkey rsa:3500 -nodes -keyout sha512-server.key -out sha512-server.req -outform PEM $DIGEST
+$OPENSSL ca -config ec-ca-openssl.cnf.tmp -batch -keyfile sha512-ca.key -cert sha512-ca.pem -create_serial -in sha512-server.req -out sha512-server.pem -extensions ext_server $DIGEST_CA
+rm ec-ca-openssl.cnf.tmp
+
+echo
+echo "---[ Server SHA-384 ]---------------------------------------------------"
+echo
+
+cat ec-ca-openssl.cnf |
+ sed "s/#@CN@/commonName_default = sha384.server.w1.fi/" |
+ sed "s/#@ALTNAME@/subjectAltName=critical,DNS:sha384.server.w1.fi/" \
+ > ec-ca-openssl.cnf.tmp
+$OPENSSL req -config ec-ca-openssl.cnf.tmp -batch -new -newkey rsa:3072 -nodes -keyout sha384-server.key -out sha384-server.req -outform PEM $DIGEST
+$OPENSSL ca -config ec-ca-openssl.cnf.tmp -batch -keyfile sha512-ca.key -cert sha512-ca.pem -create_serial -in sha384-server.req -out sha384-server.pem -extensions ext_server -md sha384
+rm ec-ca-openssl.cnf.tmp
+
+echo
+echo "---[ User SHA-512 ]-----------------------------------------------------"
+echo
+
+cat ec-ca-openssl.cnf |
+ sed "s/#@CN@/commonName_default = user-sha512/" |
+ sed "s/#@ALTNAME@/subjectAltName=email:user-sha512@w1.fi/" \
+ > ec-ca-openssl.cnf.tmp
+$OPENSSL req -config ec-ca-openssl.cnf.tmp -batch -new -newkey rsa:3400 -nodes -keyout sha512-user.key -out sha512-user.req -outform PEM -extensions ext_client $DIGEST
+$OPENSSL ca -config ec-ca-openssl.cnf.tmp -batch -keyfile sha512-ca.key -cert sha512-ca.pem -create_serial -in sha512-user.req -out sha512-user.pem -extensions ext_client $DIGEST_CA
+rm ec-ca-openssl.cnf.tmp
+
+echo
+echo "---[ User SHA-384 ]-----------------------------------------------------"
+echo
+
+cat ec-ca-openssl.cnf |
+ sed "s/#@CN@/commonName_default = user-sha384/" |
+ sed "s/#@ALTNAME@/subjectAltName=email:user-sha384@w1.fi/" \
+ > ec-ca-openssl.cnf.tmp
+$OPENSSL req -config ec-ca-openssl.cnf.tmp -batch -new -newkey rsa:2900 -nodes -keyout sha384-user.key -out sha384-user.req -outform PEM -extensions ext_client $DIGEST
+$OPENSSL ca -config ec-ca-openssl.cnf.tmp -batch -keyfile sha512-ca.key -cert sha512-ca.pem -create_serial -in sha384-user.req -out sha384-user.pem -extensions ext_client -md sha384
+rm ec-ca-openssl.cnf.tmp
+
+echo
+echo "---[ Verify ]-----------------------------------------------------------"
+echo
+
+$OPENSSL verify -CAfile sha512-ca.pem sha512-server.pem
+$OPENSSL verify -CAfile sha512-ca.pem sha384-server.pem
+$OPENSSL verify -CAfile sha512-ca.pem sha512-user.pem
+$OPENSSL verify -CAfile sha512-ca.pem sha384-user.pem
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MIIH7AIBADANBgkqhkiG9w0BAQEFAASCB9YwggfSAgEAAoIBtgyUrc5DYSg0X9fe
+xaXrNjYldxn7pZsOu+1u2RAbcNNKFPs+XFCihLMu/QnNxKv5+n7njugzUIoBg0I5
+Oydoi/rmXGCG6NBWWnm8KsqpC/WJ1aMldsFxi4oyKieBizGo+alsYgApzWp8LMwD
+NHdfk+fyGoyneJowKdGVO2BridD0abGCfBdztSta76bse8eb4wo8TEGYrbSkBTBV
+YFmpDRw5tLTzcPy300fmRD+PPm7QMY6F7i8s9Z2GwYJ3Ec30Fah4KhidtiwfllHW
+PLYu9ONl1J9OkuZVGOI+bh7FPV11ISx6r8r+Cz0YlkyG8qf4bbMPDcv3RYa/iCFV
+9BzMp++ySRNCzpV0+mSw5P842hTvXBBwCqgwTyL4+Vao9Pcf6TGISn3tESeJSecG
+plrTJ9xgey2RWkgRP+Cj0r2Jr8ijhKAntYmY/TxY9KjbgXu6CAvVXzB86hnVd9+F
++sT060f/cGXZ0ZF5EKcbEcqu2N+98fFU2Q2LeBxgzZ5jBAWGYKsZ58/dz+o9Df+B
+F4t0W4Wp5JPKdIbkTETUCwaNBtM1TvetKvZ30HZc/DxjLv0/QkE2ctZ4PwIDAQAB
+AoIBtglR7/y5T/W/7yz2HUhQmyW71aMLGWFopfI8x1O2cHwnCqoiRbN64oH4En87
+0DJzi46OLwF4WncSrdHWoisMuX7TP6ZG65zEDFzY+H6Qg4qQZRNrArJGUtC7Xx1L
+S/orK2HHKEbksQftHCa7TRgOV31ijyaaPq9DdQeN3aINqNiC6PYXK6UYFCQdRyNL
+WFvE8Yq4pumFmVIUnL900F877Ll3SpcvLgoaiMxgGzlW/jKLy9rA/3Y1gXQEy8DC
+Qw9nftACzXTVCYtgjzTrWKjC2qrH2p92Tz+R1VBuXUPZLMhCGGI9eYWdaaoCFsPy
+RRsDhLpExK+WcQyinPrhUinr8p8DsgL2Qn6LJCBRbSS7kYa4cT//e+ohsvelE+sv
+9nhUEpyndUW5FNm4fp29wi+mKfhFWlYXsMA5xJ2btcKZPH1iVuV3oPI6ykj2RSRc
+/ZfnXyyCKxnYlZ2mQCmB2HpU6gTwp7LJY6X//dODFtuuVXXdDKAQLTfcCIhBWcAW
+MRFjs7UeY9D+iiSmMH7NAgaWWLJUIVFKbRj6hItCjfJV/bub6kfy5AXmx9kAqv58
++muUMiWBHC15iQKB2z1ZBWNWFaa4fPlLUNo0orxDOv1vPUChs1D8SyD/7486XE9K
+VHolpWy6d/XmuQTFSbRs2E4XaWQNirXPG5FVpe4D8YnL57E1sITYTdqnYbeifZVb
++Wt+u89d4a1jEECFqHXUKixm0/kcl++UJwkYLm9eol5Ip8pp6OC6upht8p+8HHHr
+1lL4Alzwq/8iUkIy79BQQurcIAzAE2CBgzbU4Dc63yiyqRhepeOhqdCZDr35F1E3
+RxgsCsmKDIJQ2bV80Q+yrGVcR4Uz+oeG3MjAzsmQR4IvsU5jGSd2TQKB2zR/rWEJ
+WsVgMFiAyFdYI45x+bpG9tOuc6VHNX/7f0DeOlM/eXnvRwpvW9LDBwCXIkJkwOSx
+bMtlQge/RI0AwchzvEz3UMYpHYtaJmYCxUXLHc/ziYrNHfsZOVIIw1y6yrrfWGiV
+54nFdFRZx2aXZpPqa2oVUqxl3qkKEpPgLzQancS5xDcm14J65pCYbuodNkz02Buv
+8RzSakF+UJmLhBulMBHMgN0NGNnTYfomUFCb2/Plu/kK58raokOxiAgusCDgpgsR
+ohwdTjBb/GJ8VceGvooqBXVB9FJGuwKB2wn5zN9/YxvuShw7vBUPlBrrD8+gZCR7
+Zu5XaFwgYjM3OUWHf78xGfpZRCKPdyyobDjTrkTcl722WgUAfaofdFEFAST4LF/r
+rB2eEuLobwJugN9lymRJgn7Q9F6+iikD0wX+DzGTMwsCNE64F7Tp4rsnd12/kNFg
+cYcBtlANKPQCodmAkSSCwdedJ0rgqOGs6MRGGOuaCfgoz73UsaKb8S3p+9nhW4/j
+7DPc2QFbskMAG2OQipYKq2JkeW5DeXOCrXhRBKmi3NpzPl0FeCeI+tdaB9bKrJlj
+kfaRzQKB2xGoJ44NcWQU9+2sUrVdxYexOca2+2kysV6TVqEW2zPcCk3ZeWfTXFdc
+IMwAICjIrBMcg+vm6Kp4Af9NCydJa+OZWWmhfJ9JUNB/n46LvAG/UOWSCV6PolfD
+og2/OMXFZU34tGlokZk6ueds0q3kmfGB1GK3jTjCgmLkKl9l9TpXAV0bBa1u+Oi/
+oTBctGE1NgAoEU8um6+P7YDdlQovbF1H76Ts3SJ7tzH78GYL4NNbuFyNle0rB86o
+Pg76dMAbw80rAW2TnqxKBvQo2/fbzZXv8cHSZEeNyTiq5QKB2xDSGoN8kLg3VpUf
+tqhy60WuLPOlzrOmRPRFAPzT/tOqKSfa59/QXuXcZ1z3tI7DN0TLMGc9weNcytvD
+KJrZTtqsyjRrdpTQfMBzn3+sP4dXg9vw9fRmKOHLo323Vr4WPXeWBBkUGGCLr7qM
+Lw2iWNO64lwG7qOz53IVAkgQv4hHkpZdc5UKdFBef6OT+pgSG8MOEVkMfnGcqWh8
+dMbbIQ5xvHOhsplzQm/V2x7ucmFMaT/HO6FGSeIYmX/ZsWyBvfA5zJtAc79KGX0k
+Jer426hlmX1bSvfG1YJlXg==
+-----END PRIVATE KEY-----
--- /dev/null
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 14110776913249282217 (0xc3d38cd72b01a8a9)
+ Signature Algorithm: sha512WithRSAEncryption
+ Issuer: C=FI, L=Helsinki, O=w1.fi, CN=SHA384 and SHA512 Root CA
+ Validity
+ Not Before: Nov 29 22:33:25 2015 GMT
+ Not After : Nov 26 22:33:25 2025 GMT
+ Subject: C=FI, O=w1.fi, CN=sha512.server.w1.fi
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (3500 bit)
+ Modulus:
+ 0c:94:ad:ce:43:61:28:34:5f:d7:de:c5:a5:eb:36:
+ 36:25:77:19:fb:a5:9b:0e:bb:ed:6e:d9:10:1b:70:
+ d3:4a:14:fb:3e:5c:50:a2:84:b3:2e:fd:09:cd:c4:
+ ab:f9:fa:7e:e7:8e:e8:33:50:8a:01:83:42:39:3b:
+ 27:68:8b:fa:e6:5c:60:86:e8:d0:56:5a:79:bc:2a:
+ ca:a9:0b:f5:89:d5:a3:25:76:c1:71:8b:8a:32:2a:
+ 27:81:8b:31:a8:f9:a9:6c:62:00:29:cd:6a:7c:2c:
+ cc:03:34:77:5f:93:e7:f2:1a:8c:a7:78:9a:30:29:
+ d1:95:3b:60:6b:89:d0:f4:69:b1:82:7c:17:73:b5:
+ 2b:5a:ef:a6:ec:7b:c7:9b:e3:0a:3c:4c:41:98:ad:
+ b4:a4:05:30:55:60:59:a9:0d:1c:39:b4:b4:f3:70:
+ fc:b7:d3:47:e6:44:3f:8f:3e:6e:d0:31:8e:85:ee:
+ 2f:2c:f5:9d:86:c1:82:77:11:cd:f4:15:a8:78:2a:
+ 18:9d:b6:2c:1f:96:51:d6:3c:b6:2e:f4:e3:65:d4:
+ 9f:4e:92:e6:55:18:e2:3e:6e:1e:c5:3d:5d:75:21:
+ 2c:7a:af:ca:fe:0b:3d:18:96:4c:86:f2:a7:f8:6d:
+ b3:0f:0d:cb:f7:45:86:bf:88:21:55:f4:1c:cc:a7:
+ ef:b2:49:13:42:ce:95:74:fa:64:b0:e4:ff:38:da:
+ 14:ef:5c:10:70:0a:a8:30:4f:22:f8:f9:56:a8:f4:
+ f7:1f:e9:31:88:4a:7d:ed:11:27:89:49:e7:06:a6:
+ 5a:d3:27:dc:60:7b:2d:91:5a:48:11:3f:e0:a3:d2:
+ bd:89:af:c8:a3:84:a0:27:b5:89:98:fd:3c:58:f4:
+ a8:db:81:7b:ba:08:0b:d5:5f:30:7c:ea:19:d5:77:
+ df:85:fa:c4:f4:eb:47:ff:70:65:d9:d1:91:79:10:
+ a7:1b:11:ca:ae:d8:df:bd:f1:f1:54:d9:0d:8b:78:
+ 1c:60:cd:9e:63:04:05:86:60:ab:19:e7:cf:dd:cf:
+ ea:3d:0d:ff:81:17:8b:74:5b:85:a9:e4:93:ca:74:
+ 86:e4:4c:44:d4:0b:06:8d:06:d3:35:4e:f7:ad:2a:
+ f6:77:d0:76:5c:fc:3c:63:2e:fd:3f:42:41:36:72:
+ d6:78:3f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Subject Key Identifier:
+ 39:3B:83:DB:3C:59:8F:5C:66:D8:86:6A:22:F9:F6:6C:B4:29:37:A3
+ X509v3 Authority Key Identifier:
+ keyid:0E:74:B5:09:EC:FB:FA:E7:BA:6B:1A:F6:2B:28:7E:A9:70:DA:D7:18
+
+ X509v3 Subject Alternative Name: critical
+ DNS:sha512.server.w1.fi
+ X509v3 Extended Key Usage: critical
+ TLS Web Server Authentication
+ X509v3 Key Usage:
+ Digital Signature, Key Encipherment
+ Signature Algorithm: sha512WithRSAEncryption
+ 8f:42:08:a0:bc:c1:eb:50:ef:6a:26:b7:3e:54:a6:7a:ad:b0:
+ 66:d3:1d:4c:d4:bc:63:9f:f9:b8:58:ec:33:82:9a:7e:60:28:
+ e8:2b:ee:a6:51:46:7f:bf:c4:39:71:8e:a4:d8:11:88:2e:89:
+ 60:82:4a:d7:e9:a5:6e:cb:ec:4b:79:d4:48:3f:e3:fd:1f:e2:
+ 6f:7e:43:bf:63:ff:e3:ec:d3:82:7f:bd:2a:3a:66:45:50:d5:
+ f7:ea:5b:28:4c:b0:f8:89:8a:03:e3:22:6a:eb:ee:09:46:6a:
+ 8a:c6:c9:a7:62:41:ae:ea:42:5a:7c:16:0a:b3:33:51:5c:b7:
+ 26:51:68:cb:ec:7e:6e:7c:cd:1b:24:be:c9:91:53:0f:dc:d2:
+ e0:d3:df:18:05:ca:f6:98:bf:d2:d6:c2:88:8f:93:91:2d:7b:
+ 6d:3c:56:c2:0d:90:11:93:29:67:5e:c5:b7:c5:0f:e0:b3:09:
+ d6:60:ca:b5:d5:8d:ff:fd:57:6b:fb:05:23:62:8f:4e:bf:03:
+ bc:da:ba:81:a3:7f:53:f4:8f:d1:49:1c:e0:32:47:b6:b9:71:
+ d4:85:5e:a8:44:63:47:1d:9d:6b:34:eb:c5:da:02:2a:5a:07:
+ 5b:3f:0c:47:f2:a3:54:5d:e0:3a:0c:eb:77:3b:d5:fd:03:1e:
+ 01:f6:c5:68:3f:d6:ed:cb:f9:4c:03:06:65:a9:9a:39:6b:20:
+ d7:11:eb:62:c7:09:0d:b0:51:b4:49:ff:3e:02:7d:e4:a1:6b:
+ 36:bf:f3:04:33:1f:7e:b2:69:af:7d:bb:a8:ef:7f:7e:0b:d3:
+ 33:4f:8e:61:09:fa:a3:b9:d5:97:8c:0b:90:17:ce:72:52:2a:
+ de:b8:96:4d:36:c0:b8:d7:7d:9e:56:e0:38:6b:a7:02:a0:90:
+ 6f:e8:ee:4f:f2:26:f3:6b:a4:75:80:8f:b0:c4:1b:d4:37:49:
+ 75:4b:d9:ed:2b:11:3c:ed:a8:dd:4b:8f:01:60:4d:26:f4:2d:
+ 6b:74:d5:75:79:88:2f:18:5e:76:6c:80:2c:eb:da:e2:cc:46:
+ a1:67:89:f5:f6:29:35:ae:b2:f6:79:a8:c3:43:f6:6a:a3:39:
+ d7:64:65:b7:bd:a6:c9:2d:60:70:4b:d9:60:1b:a9:a6:5e:b0:
+ cd:88:02:ae:28:57:b0:46:44:1a:ad:dc:1f:bb:e3:90:db:3c:
+ 07:a1:bf:a9:31:1c:0d:97:37:78:80:8a:7f:f8:7a:60:0b:0f:
+ fe:d1:bc:38:ff:b3:72:72:80:e0:65:1d:86:90:b0:f6:7a:38:
+ 1b:7b:05:b7:d9:f9:44:3e:4a:1c:2b:d4:3a:cc:db:75:20:eb:
+ 6d:bf:22:4b:83:1c:4f:39
+-----BEGIN CERTIFICATE-----
+MIIFYTCCA0mgAwIBAgIJAMPTjNcrAaipMA0GCSqGSIb3DQEBDQUAMFQxCzAJBgNV
+BAYTAkZJMREwDwYDVQQHDAhIZWxzaW5raTEOMAwGA1UECgwFdzEuZmkxIjAgBgNV
+BAMMGVNIQTM4NCBhbmQgU0hBNTEyIFJvb3QgQ0EwHhcNMTUxMTI5MjIzMzI1WhcN
+MjUxMTI2MjIzMzI1WjA7MQswCQYDVQQGEwJGSTEOMAwGA1UECgwFdzEuZmkxHDAa
+BgNVBAMME3NoYTUxMi5zZXJ2ZXIudzEuZmkwggHXMA0GCSqGSIb3DQEBAQUAA4IB
+xAAwggG/AoIBtgyUrc5DYSg0X9fexaXrNjYldxn7pZsOu+1u2RAbcNNKFPs+XFCi
+hLMu/QnNxKv5+n7njugzUIoBg0I5Oydoi/rmXGCG6NBWWnm8KsqpC/WJ1aMldsFx
+i4oyKieBizGo+alsYgApzWp8LMwDNHdfk+fyGoyneJowKdGVO2BridD0abGCfBdz
+tSta76bse8eb4wo8TEGYrbSkBTBVYFmpDRw5tLTzcPy300fmRD+PPm7QMY6F7i8s
+9Z2GwYJ3Ec30Fah4KhidtiwfllHWPLYu9ONl1J9OkuZVGOI+bh7FPV11ISx6r8r+
+Cz0YlkyG8qf4bbMPDcv3RYa/iCFV9BzMp++ySRNCzpV0+mSw5P842hTvXBBwCqgw
+TyL4+Vao9Pcf6TGISn3tESeJSecGplrTJ9xgey2RWkgRP+Cj0r2Jr8ijhKAntYmY
+/TxY9KjbgXu6CAvVXzB86hnVd9+F+sT060f/cGXZ0ZF5EKcbEcqu2N+98fFU2Q2L
+eBxgzZ5jBAWGYKsZ58/dz+o9Df+BF4t0W4Wp5JPKdIbkTETUCwaNBtM1TvetKvZ3
+0HZc/DxjLv0/QkE2ctZ4PwIDAQABo4GZMIGWMAwGA1UdEwEB/wQCMAAwHQYDVR0O
+BBYEFDk7g9s8WY9cZtiGaiL59my0KTejMB8GA1UdIwQYMBaAFA50tQns+/rnumsa
+9isofqlw2tcYMCEGA1UdEQEB/wQXMBWCE3NoYTUxMi5zZXJ2ZXIudzEuZmkwFgYD
+VR0lAQH/BAwwCgYIKwYBBQUHAwEwCwYDVR0PBAQDAgWgMA0GCSqGSIb3DQEBDQUA
+A4ICAQCPQgigvMHrUO9qJrc+VKZ6rbBm0x1M1Lxjn/m4WOwzgpp+YCjoK+6mUUZ/
+v8Q5cY6k2BGILolggkrX6aVuy+xLedRIP+P9H+JvfkO/Y//j7NOCf70qOmZFUNX3
+6lsoTLD4iYoD4yJq6+4JRmqKxsmnYkGu6kJafBYKszNRXLcmUWjL7H5ufM0bJL7J
+kVMP3NLg098YBcr2mL/S1sKIj5ORLXttPFbCDZARkylnXsW3xQ/gswnWYMq11Y3/
+/Vdr+wUjYo9OvwO82rqBo39T9I/RSRzgMke2uXHUhV6oRGNHHZ1rNOvF2gIqWgdb
+PwxH8qNUXeA6DOt3O9X9Ax4B9sVoP9bty/lMAwZlqZo5ayDXEetixwkNsFG0Sf8+
+An3koWs2v/MEMx9+smmvfbuo739+C9MzT45hCfqjudWXjAuQF85yUireuJZNNsC4
+132eVuA4a6cCoJBv6O5P8ibza6R1gI+wxBvUN0l1S9ntKxE87ajdS48BYE0m9C1r
+dNV1eYgvGF52bIAs69rizEahZ4n19ik1rrL2eajDQ/ZqoznXZGW3vabJLWBwS9lg
+G6mmXrDNiAKuKFewRkQardwfu+OQ2zwHob+pMRwNlzd4gIp/+HpgCw/+0bw4/7Ny
+coDgZR2GkLD2ejgbewW32flEPkocK9Q6zNt1IOttvyJLgxxPOQ==
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN PRIVATE KEY-----
+MIIHtQIBADANBgkqhkiG9w0BAQEFAASCB58wggebAgEAAoIBqgDEVq3fqyK8sXHD
+9eeLAaxkWFeX9PoC8rLx/kuMBuEz/IuY1/JwkPPeOUUXn/fDNQCvS12aGtoyxBHE
+ucBF6j6ojz+tGS88Sfzvp+VTjbIdryyd+oMZondO4GIflxCTnY0GE+ZuUeltD9mX
+HkGEFwl1Jf9cB3iUXz6X5mTXSeXlmKHL4g34wDMtc+shaINM5G0gJEWl7qebruCp
+FFVpGkkjy+QzMpjnwSYJSaC31Y/w9QTjFERdfy0TwmATJ+7mPbhsQ6Rob5olyZBt
+6a4pXdjbJm/7RAW4ov11NV0aChHzAkv1hC62Gmp51PamFu7VrxrZ9TlzNGQnJied
+IqpuK0C/eap7zjtlbsgkkOwkKZiHWf7l/opJ8yWX524STzd+ekA5EoUr7YDd0Ig1
+UYkxvIsLIza7+hOyq6ugcNeZuurCOE4OG+GGTLFSpu+FqBfS/DqptZ3xxQINKugI
+g9srE1scoP8ZvKyclHgqLZPXJZM0fZnkPEzN9EK84vPH7D387cX2LMBO/6vudL/F
+VTDwdLSbvKw9lwsnNP7hiy8LUIqk+3vhClWztNwd4QIDAQABAoIBqX/9zZ1or914
+g6RuksHglmRX3spVzgHL+3GcB93Bwl+ke9Bovkg5hnDQvsTW6KpdzBN6OwuyA5pi
+jP7E5J3vRWeW8rjCGTPhO71zoyDj10BYqOpXm81DRympRu43CXxhkcRrhqVWSqhp
+U7ya4bTdW7H90klJKYb3zBM0A3sBVphk9ty1gcwuZ25zCc4elrGym5z/aFPyj1sD
+FrvCYKeCljl6uknR6zHxjP0y/U26L/qxj70Ewkh9FoKyDPWP68I2bBpPwka+sit+
+CeRNGNcosayzkv6m2BcPm3LZMzLouoWCkAszYhwXhAqSHQzFNqoCv/IW68qYGVgr
+XtKbDB/SYGbatP2+SIbPt3oW907yW/Zfv7hDvSZF3BNEVooPC6f6NWHTdGBLHCWJ
+1FvBWpSKF2uwy+s6aV2YTdB5S0myE7p9KlY/SZiHSNjWt16puC6mHyOpBc2yEGGi
+zCCANSxUEg1C6EKquk8bfJ/6WRnnEt96d5DFRFMKHDFEIxITThQDIcITuh8YLLBM
+fPDMc2HxSR5fyfkgR9wj7+hxHSoRmWNnnAnm2kr5SwMBAoHVDpslqXfYhhtcdrCm
+NqJpQxHqCYHiWLDCGl52Tjyq21quYQC4IDPk1qb9bIUjw9cYk0OlSY1tT+0z2DfG
+iN7lWSjVqlxXZihjQIkh1d2UV2SQHuAqnWnDSRwKjkWmDzLPFM4ZC52x7ZH54Rba
+iEnSDOy59Kuw05gE0+ia1AEROSmV5ROgFevEnwp3fX7/T0e9cEr5+z3LyNDY/6I4
+PHgBN9/OXhbBO+rWSFEEezQ8JEu5DfgZ9vAN8y3dNoRZcsYR/mafimygcVhKwySj
+hDi/lEoVcxIxAoHVDXE5jfRVrdKSIVMkngFuMM+p8IItpDDX3MHmFzqW8PDZu/BD
+VdqKa3Thc9f/rPwdUwOIFUfUxqIZum8n809rkAtBhxcases+E3NcHESulnM4kJNO
+gVS0TdfdaANeLXxd6zuXgxsxXU/omdqH2ZqlSFy2VvQncNJov1s6R6m5y22aOKdu
+fdgA9suzEh3PAHhqVRXGEGXakbJg/irVX15odZMn0jume5+2ajWyt6skoCR1UI9H
+FMHU5KS3mpFba7L1sG39dZS5C4R4sV3Vz4NpTtnTuKqxAoHVBcDn3RHwoSM2ESsU
+zoC7pkfwQT6Awx8d1vVO9RLA2xeliWCXJ1hJ1KSDP7RSmlqou5nyCj9DyDBQM+QE
+uPXUsoJ7aFhntT5DmrBqO6zFOofKnd7/6nI3Ex2QquqUt3f0SuXEx+aeqE7Qd/Jg
+sz8hFyZJOjBHv5IqlK8UDl89QZ84BLzuWrQ9B8k/uJfGSpyf6xQd1PJKzBg44ros
+HOXI1RG8YSPlioy/TE1dzoqNBl8tzmrlD3kQhbKTaV5JPgT4IZabUhPoP73f9W8B
+WpxgGzHzsRiBAoHVAiizU8dwk3CEo/GUqgQUzKYt50EhT4PAx+YkrIpuf9hPQE5A
+omNtZADrzQ1eNUxw8UpZ6wEUfaq/cyAzTHLvFb2ZErd1RCpCWCFpI+ksGWH8Lcxb
+CY6vPuly2CfiUm/tLcDuftI5RYF2HG/q7dpWvZ6WcrTYONiyljlyzNvHyZKa+Ip7
+xp6Q2RKyejBrdOniOjQ7EZsqVchOp8P9bUnegTPXa37FKInoZHqnb7R/N3FjnkLE
+6eKP7QE/tAWwp0WhDGs+EEqIxf7K28H0e1Xh7hYyWTChAoHVBn76/JDy92nDEWjG
+JkEJBeh88mT6ocKvFYbKrSAjBpFrPiTbHJ6Md0duRgvSB2ikGQnJfESz7Q/M5bdo
+Ssy0qH9Paugbye4FgVwQCECkfJkB3Ijn9VuR+8cdoCySXPzhWDU6UXh5taSvsHvT
+LRLyBjFC/6UTsElVCam28aujJmNI7X+LbXBij4a3J8nXO3BFqK8HIopeG2z1lyBi
+fgtLN2fTl6adq8lDYxoMBPmrEmob5lKwCPsOMCLz50WEacNK8CFZ6QUiwx1ZhJeA
+HR9JilLQkZRY
+-----END PRIVATE KEY-----
--- /dev/null
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 14110776913249282219 (0xc3d38cd72b01a8ab)
+ Signature Algorithm: sha512WithRSAEncryption
+ Issuer: C=FI, L=Helsinki, O=w1.fi, CN=SHA384 and SHA512 Root CA
+ Validity
+ Not Before: Nov 29 22:33:25 2015 GMT
+ Not After : Nov 26 22:33:25 2025 GMT
+ Subject: C=FI, O=w1.fi, CN=user-sha512
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (3400 bit)
+ Modulus:
+ 00:c4:56:ad:df:ab:22:bc:b1:71:c3:f5:e7:8b:01:
+ ac:64:58:57:97:f4:fa:02:f2:b2:f1:fe:4b:8c:06:
+ e1:33:fc:8b:98:d7:f2:70:90:f3:de:39:45:17:9f:
+ f7:c3:35:00:af:4b:5d:9a:1a:da:32:c4:11:c4:b9:
+ c0:45:ea:3e:a8:8f:3f:ad:19:2f:3c:49:fc:ef:a7:
+ e5:53:8d:b2:1d:af:2c:9d:fa:83:19:a2:77:4e:e0:
+ 62:1f:97:10:93:9d:8d:06:13:e6:6e:51:e9:6d:0f:
+ d9:97:1e:41:84:17:09:75:25:ff:5c:07:78:94:5f:
+ 3e:97:e6:64:d7:49:e5:e5:98:a1:cb:e2:0d:f8:c0:
+ 33:2d:73:eb:21:68:83:4c:e4:6d:20:24:45:a5:ee:
+ a7:9b:ae:e0:a9:14:55:69:1a:49:23:cb:e4:33:32:
+ 98:e7:c1:26:09:49:a0:b7:d5:8f:f0:f5:04:e3:14:
+ 44:5d:7f:2d:13:c2:60:13:27:ee:e6:3d:b8:6c:43:
+ a4:68:6f:9a:25:c9:90:6d:e9:ae:29:5d:d8:db:26:
+ 6f:fb:44:05:b8:a2:fd:75:35:5d:1a:0a:11:f3:02:
+ 4b:f5:84:2e:b6:1a:6a:79:d4:f6:a6:16:ee:d5:af:
+ 1a:d9:f5:39:73:34:64:27:26:27:9d:22:aa:6e:2b:
+ 40:bf:79:aa:7b:ce:3b:65:6e:c8:24:90:ec:24:29:
+ 98:87:59:fe:e5:fe:8a:49:f3:25:97:e7:6e:12:4f:
+ 37:7e:7a:40:39:12:85:2b:ed:80:dd:d0:88:35:51:
+ 89:31:bc:8b:0b:23:36:bb:fa:13:b2:ab:ab:a0:70:
+ d7:99:ba:ea:c2:38:4e:0e:1b:e1:86:4c:b1:52:a6:
+ ef:85:a8:17:d2:fc:3a:a9:b5:9d:f1:c5:02:0d:2a:
+ e8:08:83:db:2b:13:5b:1c:a0:ff:19:bc:ac:9c:94:
+ 78:2a:2d:93:d7:25:93:34:7d:99:e4:3c:4c:cd:f4:
+ 42:bc:e2:f3:c7:ec:3d:fc:ed:c5:f6:2c:c0:4e:ff:
+ ab:ee:74:bf:c5:55:30:f0:74:b4:9b:bc:ac:3d:97:
+ 0b:27:34:fe:e1:8b:2f:0b:50:8a:a4:fb:7b:e1:0a:
+ 55:b3:b4:dc:1d:e1
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ X509v3 Subject Key Identifier:
+ 2F:60:49:97:43:3C:7A:7E:22:C1:44:0B:43:78:D4:9D:7C:DF:A6:12
+ X509v3 Authority Key Identifier:
+ keyid:0E:74:B5:09:EC:FB:FA:E7:BA:6B:1A:F6:2B:28:7E:A9:70:DA:D7:18
+
+ X509v3 Subject Alternative Name:
+ email:user-sha512@w1.fi
+ X509v3 Extended Key Usage:
+ TLS Web Client Authentication
+ X509v3 Key Usage:
+ Digital Signature, Key Encipherment
+ Signature Algorithm: sha512WithRSAEncryption
+ 9d:58:98:97:95:49:c5:bc:be:f2:1d:01:65:ff:2b:5c:24:81:
+ 71:87:05:3e:11:1d:2f:f2:16:12:d3:0e:36:72:af:87:6b:81:
+ c1:7c:aa:c8:be:be:a7:90:2c:7b:35:7c:0f:8b:67:e2:9c:da:
+ 26:ad:09:fc:56:28:78:3b:3a:00:91:8d:f9:d1:39:a2:c5:3f:
+ e4:97:42:70:5c:93:93:23:5f:01:67:37:b7:d9:12:0c:14:dd:
+ 9d:73:be:9e:46:47:90:21:26:6d:0e:4c:af:0b:80:41:06:94:
+ 86:ef:49:66:1c:70:83:9c:1b:71:83:16:38:22:f5:a0:47:09:
+ bd:69:0f:9f:5b:19:1b:d4:44:f5:15:65:d5:6c:2b:d1:8c:c7:
+ 3a:f4:a7:22:b0:53:e0:27:ff:06:c6:37:a7:cf:a6:25:2a:d4:
+ 24:90:3e:46:59:6a:9b:dd:57:71:d1:79:3a:e2:6c:b5:22:19:
+ 0f:dd:e6:d4:04:eb:fc:65:98:da:fd:e3:7c:04:d6:a0:2a:9e:
+ 19:d8:aa:44:a7:8e:c6:7d:35:00:e5:ac:24:2f:ec:53:0a:7b:
+ 3d:bc:67:f3:23:95:fd:98:8b:ba:ac:e0:25:90:b2:38:e1:bb:
+ 62:a3:0c:39:bb:3b:79:40:53:91:20:10:86:88:f3:ae:ba:5a:
+ 7a:eb:61:72:4d:3b:cc:fc:1c:ff:86:fb:6a:83:b8:ca:9a:34:
+ dc:66:46:e7:d9:39:59:a1:91:a9:d2:b9:38:c7:84:b9:23:10:
+ a6:21:e3:de:a1:56:90:bd:63:48:c7:10:d6:2d:2d:e0:90:ba:
+ 19:3a:57:c4:ea:e4:d8:62:f3:84:c4:dd:a9:e9:fe:07:33:dc:
+ ed:7e:27:9d:4a:9e:d4:3d:12:35:84:f0:df:cf:d3:8d:7c:f8:
+ 2d:cd:2b:24:70:92:40:b1:9f:38:b5:b1:34:b5:47:1b:19:6c:
+ 5a:a2:ce:04:5a:e6:ce:a4:18:11:88:2c:d6:53:80:3d:87:88:
+ 5b:89:63:47:0e:ed:52:7b:49:7f:0b:31:66:9c:54:5f:08:7d:
+ d7:e3:6e:6c:d6:12:a0:a8:cf:d9:69:6a:53:10:bf:67:d6:0c:
+ 2e:8e:6a:9a:35:c6:0a:bd:ee:28:2b:9f:d9:af:89:0f:19:5f:
+ 23:d2:f8:ce:04:69:78:a8:a3:33:3d:dc:d7:09:77:cb:51:8c:
+ 80:0e:aa:07:60:34:32:b1:b7:e6:04:1c:5d:8e:53:1f:be:fe:
+ 49:8a:21:a2:d8:f0:f8:ce:70:a4:b7:6e:90:ec:9d:68:f7:33:
+ 08:67:59:d7:ff:f6:20:00:f5:51:79:66:e6:35:bd:29:85:62:
+ d3:e1:3a:1c:b3:8c:ef:8d
+-----BEGIN CERTIFICATE-----
+MIIFQjCCAyqgAwIBAgIJAMPTjNcrAairMA0GCSqGSIb3DQEBDQUAMFQxCzAJBgNV
+BAYTAkZJMREwDwYDVQQHDAhIZWxzaW5raTEOMAwGA1UECgwFdzEuZmkxIjAgBgNV
+BAMMGVNIQTM4NCBhbmQgU0hBNTEyIFJvb3QgQ0EwHhcNMTUxMTI5MjIzMzI1WhcN
+MjUxMTI2MjIzMzI1WjAzMQswCQYDVQQGEwJGSTEOMAwGA1UECgwFdzEuZmkxFDAS
+BgNVBAMMC3VzZXItc2hhNTEyMIIByzANBgkqhkiG9w0BAQEFAAOCAbgAMIIBswKC
+AaoAxFat36sivLFxw/XniwGsZFhXl/T6AvKy8f5LjAbhM/yLmNfycJDz3jlFF5/3
+wzUAr0tdmhraMsQRxLnAReo+qI8/rRkvPEn876flU42yHa8snfqDGaJ3TuBiH5cQ
+k52NBhPmblHpbQ/Zlx5BhBcJdSX/XAd4lF8+l+Zk10nl5Zihy+IN+MAzLXPrIWiD
+TORtICRFpe6nm67gqRRVaRpJI8vkMzKY58EmCUmgt9WP8PUE4xREXX8tE8JgEyfu
+5j24bEOkaG+aJcmQbemuKV3Y2yZv+0QFuKL9dTVdGgoR8wJL9YQuthpqedT2phbu
+1a8a2fU5czRkJyYnnSKqbitAv3mqe847ZW7IJJDsJCmYh1n+5f6KSfMll+duEk83
+fnpAORKFK+2A3dCINVGJMbyLCyM2u/oTsquroHDXmbrqwjhODhvhhkyxUqbvhagX
+0vw6qbWd8cUCDSroCIPbKxNbHKD/GbysnJR4Ki2T1yWTNH2Z5DxMzfRCvOLzx+w9
+/O3F9izATv+r7nS/xVUw8HS0m7ysPZcLJzT+4YsvC1CKpPt74QpVs7TcHeECAwEA
+AaOBjjCBizAJBgNVHRMEAjAAMB0GA1UdDgQWBBQvYEmXQzx6fiLBRAtDeNSdfN+m
+EjAfBgNVHSMEGDAWgBQOdLUJ7Pv657prGvYrKH6pcNrXGDAcBgNVHREEFTATgRF1
+c2VyLXNoYTUxMkB3MS5maTATBgNVHSUEDDAKBggrBgEFBQcDAjALBgNVHQ8EBAMC
+BaAwDQYJKoZIhvcNAQENBQADggIBAJ1YmJeVScW8vvIdAWX/K1wkgXGHBT4RHS/y
+FhLTDjZyr4drgcF8qsi+vqeQLHs1fA+LZ+Kc2iatCfxWKHg7OgCRjfnROaLFP+SX
+QnBck5MjXwFnN7fZEgwU3Z1zvp5GR5AhJm0OTK8LgEEGlIbvSWYccIOcG3GDFjgi
+9aBHCb1pD59bGRvURPUVZdVsK9GMxzr0pyKwU+An/wbGN6fPpiUq1CSQPkZZapvd
+V3HReTribLUiGQ/d5tQE6/xlmNr943wE1qAqnhnYqkSnjsZ9NQDlrCQv7FMKez28
+Z/Mjlf2Yi7qs4CWQsjjhu2KjDDm7O3lAU5EgEIaI8666WnrrYXJNO8z8HP+G+2qD
+uMqaNNxmRufZOVmhkanSuTjHhLkjEKYh496hVpC9Y0jHENYtLeCQuhk6V8Tq5Nhi
+84TE3anp/gcz3O1+J51KntQ9EjWE8N/P0418+C3NKyRwkkCxnzi1sTS1RxsZbFqi
+zgRa5s6kGBGILNZTgD2HiFuJY0cO7VJ7SX8LMWacVF8IfdfjbmzWEqCoz9lpalMQ
+v2fWDC6Oapo1xgq97igrn9mviQ8ZXyPS+M4EaXioozM93NcJd8tRjIAOqgdgNDKx
+t+YEHF2OUx++/kmKIaLY8PjOcKS3bpDsnWj3MwhnWdf/9iAA9VF5ZuY1vSmFYtPh
+OhyzjO+N
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIt5s8O/vC7Z0CAggA
+MBQGCCqGSIb3DQMHBAh1l9fSi61IRASCAoDGCULhl5nYsWTyimj9idh/1z78xJu6
+Q+Ap6u/UiEQh3riX5DYojJPZfYTJ44IOh/Jfbv/ipr4IynDnAiZyhs8NWYAXTk2i
+U5yb1Zsf3lRxKQG8u8BhkxDdUs9GSbajvF81fWkZVpMQw1aBWVxRfXlNrqx0ObZD
+HdxyJX/wGMlV41r50LlyMOH9fiULX0ylGI9HtTNkxmUWtj9F7ATHp7qPdFGMoWzV
+LOoR5KqGmi4WhE3t+02wmlyeSXe4T4kiLGZ6T7sR6szjNHUFkWgwe2oFfd0HZDvO
+wC1HoUKeRM/c4bP+HtNo6ZeudSbXd4p822WvqbKgDldXqeq5KUHye6hQfF06E/mH
+2GnHLiGBvgMIOERitm9OTW4V2hPDGOVsyfu/fUdWoo0AoLmfDStRk7zqt8mkpRyZ
+sfqltTvbCYA9E1GT86WjF+Ugq2iEITf9rQZAyAb6pNM2CWyLGihjKhXRvR19w0rQ
+33KlccnDwbZMCwBV6njWnNYF5ir3gWMDvTaC+DGUbACNHo3hVQyHWEi7X5YdbBy/
+1Y94+5pbGohTQRWuMmwzc5sFWeweewoXWBsauK4EU5P4WxT3D8iCr96qsftmTn2V
+tD3k2W4vXBcqZkIswllqSQDYSnaxnSe/cUoYm3iehZRQutZ0PaBWmOy6jmJpEU/Q
+RTWsu7zyD/18o+yxkZR68eQn11zbIuBWjj1xDeqmjbYkh8XDC1Q6fVeFJxF9mhyF
+ttK/SPXuqyBi8eX13ViPEbIVOLpsr6S2ig3hN0/OIWVPblchYEXy1+VV4nwhA8Np
+J89pD8vfbcVTDjHCu9HhcMdT/zFsWehe8yw5zM3WsGx6NB/xJS2onRhs
+-----END ENCRYPTED PRIVATE KEY-----
--- /dev/null
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICoTAbBgkqhkiG9w0BBQMwDgQIJ5xD8pUUfDsCAggABIICgKaalc1M4urq1NJ8
+AJoiuAcp1sNon6FUdDUtcQNFnG9H9/nt5FseYBA4tlRtJq1Qj9ow04VViJB9guTp
+kxEt2onIyPSwblGtwkM0mboyVilmqyWEPWzI2T59nphWTnLfSmBSs756k581duks
+qtaIm+yvUyI1cA1BHHaOhMApgNFzI7OFkAto55OG7kfJgcmMj1gSjSpNJ6XsofEp
+BYLl9yPzbAF/Cxci7zTiKhYe/FbvW6qEJw+EKk5L+nKx+UlP7Ssjr+rhmeB142pb
+7x4Zbelyo4SipWSpru7dZEyKFd/ZcXByoORjQT8sQaF36zVXmmv6gURKrWlznfFz
+WwaeeI+4erld98A4tXuRjwmGbkzYnUNjq1cz2y7zvW34Dgse6KaP1iOsvmHA7K+j
+hJI4jJFHvCRDGxIFZm4qZPBapPWqlN6vRJSVAX7YASqRcaNO2m6Y0umUgCtab2uF
+k4D3ahHMg0XtcLvEr0HaklGWT5YIkcDuH+Los2NwSn1z5Q4nLnmLBfmfm75oKv1O
+X/f627b4MLQxAnrcjQ2Wk0sL4a+Rnbenbi7MlyqA7Gz9fxLQdB7qrRehAiJxo+3e
+ddhvsZ9pgZeUY+o/QkX4t4oxG09BhGVF5l+d46FU6hgPjFeRiSt7st5SdU2MK4la
+Kqw6a7rDpfhb6WLMsnJyN0JwOaoOoy4UOpZYrdvSHwDvHur8YScd2DsPLMQMs0Zo
+1mjfsYiElQLRk/wSjpyqBw/3ULFTsM17Z4mTgvTdDzBd5UycvbGJ/tnDV0cpXuJg
+FVboPYqrGk5ChPePubyRa2e57HFQVu7kjzuS9NSdnKr/IVEr9Qn9OkRmprpm5Y6J
+PgfA5wA=
+-----END ENCRYPTED PRIVATE KEY-----
--- /dev/null
+driver=nl80211
+
+hw_mode=g
+channel=1
+ieee80211n=1
+
+interface=wlan3
+ctrl_interface=/var/run/hostapd
+
+ssid=bss-1
+dynamic_vlan=1
+vlan_tagged_interface=dummy0
+vlan_bridge=brvlan
+wpa=2
+wpa_key_mgmt=WPA-EAP
+rsn_pairwise=CCMP
+ieee8021x=1
+auth_server_addr=127.0.0.1
+auth_server_port=18128
+auth_server_shared_secret=radius
+nas_identifier=nas.w1.fi
+vlan_naming=1
+per_sta_vif=1
+
+bss=wlan3-2
+bssid=02:00:00:00:03:01
+ctrl_interface=/var/run/hostapd
+ssid=bss-2
+
+dynamic_vlan=1
+vlan_tagged_interface=dummy0
+vlan_bridge=brvlan
+wpa=2
+wpa_key_mgmt=WPA-EAP
+rsn_pairwise=CCMP
+ieee8021x=1
+auth_server_addr=127.0.0.1
+auth_server_port=18128
+auth_server_shared_secret=radius
+nas_identifier=nas.w1.fi
+vlan_naming=1
+per_sta_vif=1
--- /dev/null
+# P2P helper functions
+# Copyright (c) 2013-2015, Jouni Malinen <j@w1.fi>
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+
+import logging
+logger = logging.getLogger()
+import threading
+import time
+import Queue
+
+import hwsim_utils
+
+MGMT_SUBTYPE_PROBE_REQ = 4
+MGMT_SUBTYPE_ACTION = 13
+ACTION_CATEG_PUBLIC = 4
+
+P2P_GO_NEG_REQ = 0
+P2P_GO_NEG_RESP = 1
+P2P_GO_NEG_CONF = 2
+P2P_INVITATION_REQ = 3
+P2P_INVITATION_RESP = 4
+P2P_DEV_DISC_REQ = 5
+P2P_DEV_DISC_RESP = 6
+P2P_PROV_DISC_REQ = 7
+P2P_PROV_DISC_RESP = 8
+
+P2P_ATTR_STATUS = 0
+P2P_ATTR_MINOR_REASON_CODE = 1
+P2P_ATTR_CAPABILITY = 2
+P2P_ATTR_DEVICE_ID = 3
+P2P_ATTR_GROUP_OWNER_INTENT = 4
+P2P_ATTR_CONFIGURATION_TIMEOUT = 5
+P2P_ATTR_LISTEN_CHANNEL = 6
+P2P_ATTR_GROUP_BSSID = 7
+P2P_ATTR_EXT_LISTEN_TIMING = 8
+P2P_ATTR_INTENDED_INTERFACE_ADDR = 9
+P2P_ATTR_MANAGEABILITY = 10
+P2P_ATTR_CHANNEL_LIST = 11
+P2P_ATTR_NOTICE_OF_ABSENCE = 12
+P2P_ATTR_DEVICE_INFO = 13
+P2P_ATTR_GROUP_INFO = 14
+P2P_ATTR_GROUP_ID = 15
+P2P_ATTR_INTERFACE = 16
+P2P_ATTR_OPERATING_CHANNEL = 17
+P2P_ATTR_INVITATION_FLAGS = 18
+P2P_ATTR_OOB_GO_NEG_CHANNEL = 19
+P2P_ATTR_SERVICE_HASH = 21
+P2P_ATTR_SESSION_INFORMATION_DATA = 22
+P2P_ATTR_CONNECTION_CAPABILITY = 23
+P2P_ATTR_ADVERTISEMENT_ID = 24
+P2P_ATTR_ADVERTISED_SERVICE = 25
+P2P_ATTR_SESSION_ID = 26
+P2P_ATTR_FEATURE_CAPABILITY = 27
+P2P_ATTR_PERSISTENT_GROUP = 28
+P2P_ATTR_VENDOR_SPECIFIC = 221
+
+P2P_SC_SUCCESS = 0
+P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE = 1
+P2P_SC_FAIL_INCOMPATIBLE_PARAMS = 2
+P2P_SC_FAIL_LIMIT_REACHED = 3
+P2P_SC_FAIL_INVALID_PARAMS = 4
+P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE = 5
+P2P_SC_FAIL_PREV_PROTOCOL_ERROR = 6
+P2P_SC_FAIL_NO_COMMON_CHANNELS = 7
+P2P_SC_FAIL_UNKNOWN_GROUP = 8
+P2P_SC_FAIL_BOTH_GO_INTENT_15 = 9
+P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD = 10
+P2P_SC_FAIL_REJECTED_BY_USER = 11
+
+WSC_ATTR_CONFIG_METHODS = 0x1008
+
+WLAN_EID_SSID = 0
+WLAN_EID_SUPP_RATES = 1
+WLAN_EID_VENDOR_SPECIFIC = 221
+
+def go_neg_pin_authorized_persistent(i_dev, r_dev, i_intent=None, r_intent=None,
+ i_method='enter', r_method='display',
+ test_data=True, r_listen=True):
+ if r_listen:
+ r_dev.p2p_listen()
+ i_dev.p2p_listen()
+ pin = r_dev.wps_read_pin()
+ logger.info("Start GO negotiation " + i_dev.ifname + " -> " + r_dev.ifname)
+ r_dev.p2p_go_neg_auth(i_dev.p2p_dev_addr(), pin, r_method,
+ go_intent=r_intent, persistent=True)
+ if r_listen:
+ r_dev.p2p_listen()
+ i_res = i_dev.p2p_go_neg_init(r_dev.p2p_dev_addr(), pin, i_method,
+ timeout=20, go_intent=i_intent,
+ persistent=True)
+ r_res = r_dev.p2p_go_neg_auth_result()
+ logger.debug("i_res: " + str(i_res))
+ logger.debug("r_res: " + str(r_res))
+ r_dev.dump_monitor()
+ i_dev.dump_monitor()
+ logger.info("Group formed")
+ if test_data:
+ hwsim_utils.test_connectivity_p2p(r_dev, i_dev)
+ return [i_res, r_res]
+
+def terminate_group(go, cli):
+ logger.info("Terminate persistent group")
+ go.remove_group()
+ cli.wait_go_ending_session()
+
+def invite(inv, resp, extra=None, persistent_reconnect=True, use_listen=True):
+ addr = resp.p2p_dev_addr()
+ if persistent_reconnect:
+ resp.global_request("SET persistent_reconnect 1")
+ else:
+ resp.global_request("SET persistent_reconnect 0")
+ if use_listen:
+ resp.p2p_listen()
+ else:
+ resp.p2p_find(social=True)
+ if not inv.discover_peer(addr, social=True):
+ raise Exception("Peer " + addr + " not found")
+ inv.dump_monitor()
+ peer = inv.get_peer(addr)
+ cmd = "P2P_INVITE persistent=" + peer['persistent'] + " peer=" + addr
+ if extra:
+ cmd = cmd + " " + extra
+ inv.global_request(cmd)
+
+def check_result(go, cli):
+ ev = go.wait_global_event(["P2P-GROUP-STARTED",
+ "Failed to start AP functionality"], timeout=30)
+ if ev is None:
+ raise Exception("Timeout on group re-invocation (on GO)")
+ if "P2P-GROUP-STARTED" not in ev:
+ raise Exception("GO failed to start the group for re-invocation")
+ if "[PERSISTENT]" not in ev:
+ raise Exception("Re-invoked group not marked persistent")
+ go_res = go.group_form_result(ev)
+ if go_res['role'] != 'GO':
+ raise Exception("Persistent group GO did not become GO")
+ if not go_res['persistent']:
+ raise Exception("Persistent group not re-invoked as persistent (GO)")
+ ev = cli.wait_global_event(["P2P-GROUP-STARTED"], timeout=30)
+ if ev is None:
+ raise Exception("Timeout on group re-invocation (on client)")
+ if "[PERSISTENT]" not in ev:
+ raise Exception("Re-invoked group not marked persistent")
+ cli_res = cli.group_form_result(ev)
+ if cli_res['role'] != 'client':
+ raise Exception("Persistent group client did not become client")
+ if not cli_res['persistent']:
+ raise Exception("Persistent group not re-invoked as persistent (cli)")
+ return [go_res, cli_res]
+
+def form(go, cli, test_data=True, reverse_init=False, r_listen=True):
+ logger.info("Form a persistent group")
+ if reverse_init:
+ [i_res, r_res] = go_neg_pin_authorized_persistent(i_dev=cli, i_intent=0,
+ r_dev=go, r_intent=15,
+ test_data=test_data,
+ r_listen=r_listen)
+ else:
+ [i_res, r_res] = go_neg_pin_authorized_persistent(i_dev=go, i_intent=15,
+ r_dev=cli, r_intent=0,
+ test_data=test_data,
+ r_listen=r_listen)
+ if not i_res['persistent'] or not r_res['persistent']:
+ raise Exception("Formed group was not persistent")
+ terminate_group(go, cli)
+ if reverse_init:
+ return r_res
+ else:
+ return i_res
+
+def invite_from_cli(go, cli, terminate=True):
+ logger.info("Re-invoke persistent group from client")
+ invite(cli, go)
+ [go_res, cli_res] = check_result(go, cli)
+ hwsim_utils.test_connectivity_p2p(go, cli)
+ if terminate:
+ terminate_group(go, cli)
+ return [go_res, cli_res]
+
+def invite_from_go(go, cli, terminate=True):
+ logger.info("Re-invoke persistent group from GO")
+ invite(go, cli)
+ [go_res, cli_res] = check_result(go, cli)
+ hwsim_utils.test_connectivity_p2p(go, cli)
+ if terminate:
+ terminate_group(go, cli)
+ return [go_res, cli_res]
+
+def autogo(go, freq=None, persistent=None):
+ logger.info("Start autonomous GO " + go.ifname)
+ res = go.p2p_start_go(freq=freq, persistent=persistent)
+ logger.debug("res: " + str(res))
+ return res
+
+def connect_cli(go, client, social=False, freq=None):
+ logger.info("Try to connect the client to the GO")
+ pin = client.wps_read_pin()
+ go.p2p_go_authorize_client(pin)
+ res = client.p2p_connect_group(go.p2p_dev_addr(), pin, timeout=60,
+ social=social, freq=freq)
+ logger.info("Client connected")
+ hwsim_utils.test_connectivity_p2p(go, client)
+ return res
+
+def check_grpform_results(i_res, r_res):
+ if i_res['result'] != 'success' or r_res['result'] != 'success':
+ raise Exception("Failed group formation")
+ if i_res['ssid'] != r_res['ssid']:
+ raise Exception("SSID mismatch")
+ if i_res['freq'] != r_res['freq']:
+ raise Exception("freq mismatch")
+ if 'go_neg_freq' in r_res and i_res['go_neg_freq'] != r_res['go_neg_freq']:
+ raise Exception("go_neg_freq mismatch")
+ if i_res['freq'] != i_res['go_neg_freq']:
+ raise Exception("freq/go_neg_freq mismatch")
+ if i_res['role'] != i_res['go_neg_role']:
+ raise Exception("role/go_neg_role mismatch")
+ if 'go_neg_role' in r_res and r_res['role'] != r_res['go_neg_role']:
+ raise Exception("role/go_neg_role mismatch")
+ if i_res['go_dev_addr'] != r_res['go_dev_addr']:
+ raise Exception("GO Device Address mismatch")
+
+def go_neg_init(i_dev, r_dev, pin, i_method, i_intent, res):
+ logger.debug("Initiate GO Negotiation from i_dev")
+ try:
+ i_res = i_dev.p2p_go_neg_init(r_dev.p2p_dev_addr(), pin, i_method, timeout=20, go_intent=i_intent)
+ logger.debug("i_res: " + str(i_res))
+ except Exception, e:
+ i_res = None
+ logger.info("go_neg_init thread caught an exception from p2p_go_neg_init: " + str(e))
+ res.put(i_res)
+
+def go_neg_pin(i_dev, r_dev, i_intent=None, r_intent=None, i_method='enter', r_method='display'):
+ r_dev.p2p_listen()
+ i_dev.p2p_listen()
+ pin = r_dev.wps_read_pin()
+ logger.info("Start GO negotiation " + i_dev.ifname + " -> " + r_dev.ifname)
+ r_dev.dump_monitor()
+ res = Queue.Queue()
+ t = threading.Thread(target=go_neg_init, args=(i_dev, r_dev, pin, i_method, i_intent, res))
+ t.start()
+ logger.debug("Wait for GO Negotiation Request on r_dev")
+ ev = r_dev.wait_global_event(["P2P-GO-NEG-REQUEST"], timeout=15)
+ if ev is None:
+ raise Exception("GO Negotiation timed out")
+ r_dev.dump_monitor()
+ logger.debug("Re-initiate GO Negotiation from r_dev")
+ r_res = r_dev.p2p_go_neg_init(i_dev.p2p_dev_addr(), pin, r_method, go_intent=r_intent, timeout=20)
+ logger.debug("r_res: " + str(r_res))
+ r_dev.dump_monitor()
+ t.join()
+ i_res = res.get()
+ if i_res is None:
+ raise Exception("go_neg_init thread failed")
+ logger.debug("i_res: " + str(i_res))
+ logger.info("Group formed")
+ hwsim_utils.test_connectivity_p2p(r_dev, i_dev)
+ i_dev.dump_monitor()
+ return [i_res, r_res]
+
+def go_neg_pin_authorized(i_dev, r_dev, i_intent=None, r_intent=None,
+ expect_failure=False, i_go_neg_status=None,
+ i_method='enter', r_method='display', test_data=True,
+ i_freq=None, r_freq=None,
+ i_freq2=None, r_freq2=None,
+ i_max_oper_chwidth=None, r_max_oper_chwidth=None,
+ i_ht40=False, i_vht=False, r_ht40=False, r_vht=False):
+ i_dev.p2p_listen()
+ pin = r_dev.wps_read_pin()
+ logger.info("Start GO negotiation " + i_dev.ifname + " -> " + r_dev.ifname)
+ r_dev.p2p_go_neg_auth(i_dev.p2p_dev_addr(), pin, r_method,
+ go_intent=r_intent, freq=r_freq, freq2=r_freq2,
+ max_oper_chwidth=r_max_oper_chwidth, ht40=r_ht40,
+ vht=r_vht)
+ r_dev.p2p_listen()
+ i_res = i_dev.p2p_go_neg_init(r_dev.p2p_dev_addr(), pin, i_method,
+ timeout=20, go_intent=i_intent,
+ expect_failure=expect_failure, freq=i_freq,
+ freq2=i_freq2,
+ max_oper_chwidth=i_max_oper_chwidth,
+ ht40=i_ht40, vht=i_vht)
+ r_res = r_dev.p2p_go_neg_auth_result(expect_failure=expect_failure)
+ logger.debug("i_res: " + str(i_res))
+ logger.debug("r_res: " + str(r_res))
+ r_dev.dump_monitor()
+ i_dev.dump_monitor()
+ if i_go_neg_status:
+ if i_res['result'] != 'go-neg-failed':
+ raise Exception("Expected GO Negotiation failure not reported")
+ if i_res['status'] != i_go_neg_status:
+ raise Exception("Expected GO Negotiation status not seen")
+ if expect_failure:
+ return
+ logger.info("Group formed")
+ if test_data:
+ hwsim_utils.test_connectivity_p2p(r_dev, i_dev)
+ return [i_res, r_res]
+
+def go_neg_init_pbc(i_dev, r_dev, i_intent, res, freq, provdisc):
+ logger.debug("Initiate GO Negotiation from i_dev")
+ try:
+ i_res = i_dev.p2p_go_neg_init(r_dev.p2p_dev_addr(), None, "pbc",
+ timeout=20, go_intent=i_intent, freq=freq,
+ provdisc=provdisc)
+ logger.debug("i_res: " + str(i_res))
+ except Exception, e:
+ i_res = None
+ logger.info("go_neg_init_pbc thread caught an exception from p2p_go_neg_init: " + str(e))
+ res.put(i_res)
+
+def go_neg_pbc(i_dev, r_dev, i_intent=None, r_intent=None, i_freq=None, r_freq=None, provdisc=False, r_listen=False):
+ if r_listen:
+ r_dev.p2p_listen()
+ else:
+ r_dev.p2p_find(social=True)
+ i_dev.p2p_find(social=True)
+ logger.info("Start GO negotiation " + i_dev.ifname + " -> " + r_dev.ifname)
+ r_dev.dump_monitor()
+ res = Queue.Queue()
+ t = threading.Thread(target=go_neg_init_pbc, args=(i_dev, r_dev, i_intent, res, i_freq, provdisc))
+ t.start()
+ logger.debug("Wait for GO Negotiation Request on r_dev")
+ ev = r_dev.wait_global_event(["P2P-GO-NEG-REQUEST"], timeout=15)
+ if ev is None:
+ raise Exception("GO Negotiation timed out")
+ r_dev.dump_monitor()
+ # Allow some time for the GO Neg Resp to go out before initializing new
+ # GO Negotiation.
+ time.sleep(0.2)
+ logger.debug("Re-initiate GO Negotiation from r_dev")
+ r_res = r_dev.p2p_go_neg_init(i_dev.p2p_dev_addr(), None, "pbc",
+ go_intent=r_intent, timeout=20, freq=r_freq)
+ logger.debug("r_res: " + str(r_res))
+ r_dev.dump_monitor()
+ t.join()
+ i_res = res.get()
+ if i_res is None:
+ raise Exception("go_neg_init_pbc thread failed")
+ logger.debug("i_res: " + str(i_res))
+ logger.info("Group formed")
+ hwsim_utils.test_connectivity_p2p(r_dev, i_dev)
+ i_dev.dump_monitor()
+ return [i_res, r_res]
+
+def go_neg_pbc_authorized(i_dev, r_dev, i_intent=None, r_intent=None,
+ expect_failure=False, i_freq=None, r_freq=None):
+ i_dev.p2p_listen()
+ logger.info("Start GO negotiation " + i_dev.ifname + " -> " + r_dev.ifname)
+ r_dev.p2p_go_neg_auth(i_dev.p2p_dev_addr(), None, "pbc",
+ go_intent=r_intent, freq=r_freq)
+ r_dev.p2p_listen()
+ i_res = i_dev.p2p_go_neg_init(r_dev.p2p_dev_addr(), None, "pbc", timeout=20,
+ go_intent=i_intent,
+ expect_failure=expect_failure, freq=i_freq)
+ r_res = r_dev.p2p_go_neg_auth_result(expect_failure=expect_failure)
+ logger.debug("i_res: " + str(i_res))
+ logger.debug("r_res: " + str(r_res))
+ r_dev.dump_monitor()
+ i_dev.dump_monitor()
+ if expect_failure:
+ return
+ logger.info("Group formed")
+ return [i_res, r_res]
+
+def remove_group(dev1, dev2):
+ dev1.remove_group()
+ try:
+ dev2.remove_group()
+ except:
+ pass
--- /dev/null
+# Host class
+# Copyright (c) 2016, Qualcomm Atheros, Inc.
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+
+import logging
+import subprocess
+import threading
+
+logger = logging.getLogger()
+
+def remote_compatible(func):
+ func.remote_compatible = True
+ return func
+
+def execute_thread(command, reply):
+ cmd = ' '.join(command)
+ logger.debug("thread run: " + cmd)
+ try:
+ status = 0
+ buf = subprocess.check_output(command, stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ status = e.returncode
+ buf = e.output
+
+ logger.debug("thread cmd: " + cmd)
+ logger.debug("thread exit status: " + str(status))
+ logger.debug("thread exit buf: " + str(buf))
+ reply.append(status)
+ reply.append(buf)
+
+class Host():
+ def __init__(self, host=None, ifname=None, port=None, name="", user="root"):
+ self.host = host
+ self.name = name
+ self.user = user
+ self.monitors = []
+ self.monitor_thread = None
+ self.logs = []
+ self.ifname = ifname
+ self.port = port
+ self.dev = None
+ if self.name == "" and host != None:
+ self.name = host
+
+ def local_execute(self, command):
+ logger.debug("execute: " + str(command))
+ try:
+ status = 0
+ buf = subprocess.check_output(command, stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ status = e.returncode
+ buf = e.output
+
+ logger.debug("status: " + str(status))
+ logger.debug("buf: " + str(buf))
+ return status, buf
+
+ def execute(self, command):
+ if self.host is None:
+ return self.local_execute(command)
+
+ cmd = ["ssh", self.user + "@" + self.host, ' '.join(command)]
+ _cmd = self.name + " execute: " + ' '.join(cmd)
+ logger.debug(_cmd)
+ try:
+ status = 0
+ buf = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ status = e.returncode
+ buf = e.output
+
+ logger.debug(self.name + " status: " + str(status))
+ logger.debug(self.name + " buf: " + str(buf))
+ return status, buf
+
+ # async execute
+ def execute_run(self, command, res):
+ if self.host is None:
+ cmd = command
+ else:
+ cmd = ["ssh", self.user + "@" + self.host, ' '.join(command)]
+ _cmd = self.name + " execute_run: " + ' '.join(cmd)
+ logger.debug(_cmd)
+ t = threading.Thread(target = execute_thread, args=(cmd, res))
+ t.start()
+ return t
+
+ def wait_execute_complete(self, t, wait=None):
+ if wait == None:
+ wait_str = "infinite"
+ else:
+ wait_str = str(wait) + "s"
+
+ logger.debug(self.name + " wait_execute_complete(" + wait_str + "): ")
+ if t.isAlive():
+ t.join(wait)
+
+ def add_log(self, log_file):
+ self.logs.append(log_file)
+
+ def get_logs(self, local_log_dir=None):
+ for log in self.logs:
+ if local_log_dir:
+ self.local_execute(["scp", self.user + "@[" + self.host + "]:" + log, local_log_dir])
+ self.execute(["rm", log])
+ del self.logs[:]
--- /dev/null
+# Hotspot 2.0 filtering tests
+# Copyright (c) 2015, Intel Deutschland GmbH
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+
+import hostapd
+import hwsim_utils
+import socket
+import subprocess
+import binascii
+from utils import HwsimSkip, require_under_vm
+import os
+import time
+from test_ap_hs20 import build_arp, build_na, hs20_ap_params
+from test_ap_hs20 import interworking_select, interworking_connect
+import struct
+import logging
+logger = logging.getLogger()
+
+class IPAssign(object):
+ def __init__(self, iface, addr, ipv6=False):
+ self._iface = iface
+ self._addr = addr
+ self._cmd = ['ip']
+ if ipv6:
+ self._cmd.append('-6')
+ self._cmd.append('addr')
+ self._ipv6 = ipv6
+ def __enter__(self):
+ subprocess.call(self._cmd + ['add', self._addr, 'dev', self._iface])
+ if self._ipv6:
+ # wait for DAD to finish
+ while True:
+ o = subprocess.check_output(self._cmd + ['show', 'tentative', 'dev', self._iface])
+ if not self._addr in o:
+ break
+ time.sleep(0.1)
+ def __exit__(self, type, value, traceback):
+ subprocess.call(self._cmd + ['del', self._addr, 'dev', self._iface])
+
+def hs20_filters_connect(dev, apdev, disable_dgaf=False, proxy_arp=False):
+ bssid = apdev[0]['bssid']
+ params = hs20_ap_params()
+ params['hessid'] = bssid
+
+ # Do not disable dgaf, to test that the station drops unicast IP packets
+ # encrypted with GTK.
+ params['disable_dgaf'] = '0'
+ params['proxy_arp'] = '1'
+ params['ap_isolate'] = '1'
+ params['bridge'] = 'ap-br0'
+
+ try:
+ hapd = hostapd.add_ap(apdev[0], params)
+ except:
+ # For now, do not report failures due to missing kernel support.
+ raise HwsimSkip("Could not start hostapd - assume proxyarp not supported in the kernel")
+
+ subprocess.call(['brctl', 'setfd', 'ap-br0', '0'])
+ subprocess.call(['ip', 'link', 'set', 'dev', 'ap-br0', 'up'])
+
+ dev[0].hs20_enable()
+
+ id = dev[0].add_cred_values({ 'realm': "example.com",
+ 'username': "hs20-test",
+ 'password': "password",
+ 'ca_cert': "auth_serv/ca.pem",
+ 'domain': "example.com",
+ 'update_identifier': "1234" })
+ interworking_select(dev[0], bssid, "home", freq="2412")
+ interworking_connect(dev[0], bssid, "TTLS")
+
+ time.sleep(0.1)
+
+ return dev[0], hapd
+
+def _test_ip4_gtk_drop(devs, apdevs, params, dst):
+ require_under_vm()
+ procfile = '/proc/sys/net/ipv4/conf/%s/drop_unicast_in_l2_multicast' % devs[0].ifname
+ if not os.path.exists(procfile):
+ raise HwsimSkip("kernel doesn't have capability")
+
+ [dev, hapd] = hs20_filters_connect(devs, apdevs)
+ with IPAssign(dev.ifname, '10.0.0.1/24'):
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ s.bind(("10.0.0.1", 12345))
+ s.settimeout(0.1)
+
+ pkt = dst
+ pkt += hapd.own_addr().replace(':', '')
+ pkt += '0800'
+ pkt += '45000020786840004011ae600a0000040a000001'
+ pkt += '30393039000c0000'
+ pkt += '61736466' # "asdf"
+ if "OK" not in hapd.request('DATA_TEST_FRAME ' + pkt):
+ raise Exception("DATA_TEST_FRAME failed")
+ try:
+ logger.info(s.recvfrom(1024))
+ logger.info("procfile=" + procfile + " val=" + open(procfile,'r').read().rstrip())
+ raise Exception("erroneously received frame!")
+ except socket.timeout:
+ # this is the expected behaviour
+ pass
+
+def test_ip4_gtk_drop_bcast(devs, apdevs, params):
+ _test_ip4_gtk_drop(devs, apdevs, params, dst='ffffffffffff')
+
+def test_ip4_gtk_drop_mcast(devs, apdevs, params):
+ _test_ip4_gtk_drop(devs, apdevs, params, dst='ff0000000000')
+
+def _test_ip6_gtk_drop(devs, apdevs, params, dst):
+ require_under_vm()
+ dev = devs[0]
+ procfile = '/proc/sys/net/ipv6/conf/%s/drop_unicast_in_l2_multicast' % devs[0].ifname
+ if not os.path.exists(procfile):
+ raise HwsimSkip("kernel doesn't have capability")
+
+ [dev, hapd] = hs20_filters_connect(devs, apdevs)
+
+ with IPAssign(dev.ifname, 'fdaa::1/48', ipv6=True):
+ s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
+ s.bind(("fdaa::1", 12345))
+ s.settimeout(0.1)
+
+ pkt = dst
+ pkt += hapd.own_addr().replace(':', '')
+ pkt += '86dd'
+ pkt += '60000000000c1140fdaa0000000000000000000000000002fdaa0000000000000000000000000001'
+ pkt += '30393039000cde31'
+ pkt += '61736466' # "asdf"
+ if "OK" not in hapd.request('DATA_TEST_FRAME ' + pkt):
+ raise Exception("DATA_TEST_FRAME failed")
+ try:
+ logger.info(s.recvfrom(1024))
+ logger.info("procfile=" + procfile + " val=" + open(procfile,'r').read().rstrip())
+ raise Exception("erroneously received frame!")
+ except socket.timeout:
+ # this is the expected behaviour
+ pass
+
+def test_ip6_gtk_drop_bcast(devs, apdevs, params):
+ _test_ip6_gtk_drop(devs, apdevs, params, dst='ffffffffffff')
+
+def test_ip6_gtk_drop_mcast(devs, apdevs, params):
+ _test_ip6_gtk_drop(devs, apdevs, params, dst='ff0000000000')
+
+def test_ip4_drop_gratuitous_arp(devs, apdevs, params):
+ require_under_vm()
+ procfile = '/proc/sys/net/ipv4/conf/%s/drop_gratuitous_arp' % devs[0].ifname
+ if not os.path.exists(procfile):
+ raise HwsimSkip("kernel doesn't have capability")
+
+ [dev, hapd] = hs20_filters_connect(devs, apdevs)
+
+ with IPAssign(dev.ifname, '10.0.0.2/24'):
+ # add an entry that can be updated by gratuitous ARP
+ subprocess.call(['ip', 'neigh', 'add', '10.0.0.1', 'lladdr', '02:00:00:00:00:ff', 'nud', 'reachable', 'dev', dev.ifname])
+ # wait for lock-time
+ time.sleep(1)
+ try:
+ ap_addr = hapd.own_addr()
+ cl_addr = dev.own_addr()
+ pkt = build_arp(cl_addr, ap_addr, 2, ap_addr, '10.0.0.1', ap_addr, '10.0.0.1')
+ pkt = binascii.hexlify(pkt)
+
+ if "OK" not in hapd.request('DATA_TEST_FRAME ' + pkt):
+ raise Exception("DATA_TEST_FRAME failed")
+
+ if hapd.own_addr() in subprocess.check_output(['ip', 'neigh', 'show']):
+ raise Exception("gratuitous ARP frame updated erroneously")
+ finally:
+ subprocess.call(['ip', 'neigh', 'del', '10.0.0.1', 'dev', dev.ifname])
+
+def test_ip6_drop_unsolicited_na(devs, apdevs, params):
+ require_under_vm()
+ procfile = '/proc/sys/net/ipv6/conf/%s/drop_unsolicited_na' % devs[0].ifname
+ if not os.path.exists(procfile):
+ raise HwsimSkip("kernel doesn't have capability")
+
+ [dev, hapd] = hs20_filters_connect(devs, apdevs)
+
+ with IPAssign(dev.ifname, 'fdaa::1/48', ipv6=True):
+ # add an entry that can be updated by unsolicited NA
+ subprocess.call(['ip', '-6', 'neigh', 'add', 'fdaa::2', 'lladdr', '02:00:00:00:00:ff', 'nud', 'reachable', 'dev', dev.ifname])
+ try:
+ ap_addr = hapd.own_addr()
+ cl_addr = dev.own_addr()
+ pkt = build_na(ap_addr, 'fdaa::2', 'ff02::1', 'fdaa::2', flags=0x20,
+ opt=binascii.unhexlify('0201' + ap_addr.replace(':', '')))
+ pkt = binascii.hexlify(pkt)
+
+ if "OK" not in hapd.request('DATA_TEST_FRAME ' + pkt):
+ raise Exception("DATA_TEST_FRAME failed")
+
+ if hapd.own_addr() in subprocess.check_output(['ip', 'neigh', 'show']):
+ raise Exception("unsolicited NA frame updated erroneously")
+ finally:
+ subprocess.call(['ip', '-6', 'neigh', 'del', 'fdaa::2', 'dev', dev.ifname])
--- /dev/null
+# MBO tests
+# Copyright (c) 2016, Intel Deutschland GmbH
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+
+from remotehost import remote_compatible
+import logging
+logger = logging.getLogger()
+
+import hostapd
+import os
+import time
+
+import hostapd
+from tshark import run_tshark
+from utils import alloc_fail, fail_test
+
+def set_reg(country_code, apdev0=None, apdev1=None, dev0=None):
+ if apdev0:
+ hostapd.cmd_execute(apdev0, ['iw', 'reg', 'set', country_code])
+ if apdev1:
+ hostapd.cmd_execute(apdev1, ['iw', 'reg', 'set', country_code])
+ if dev0:
+ dev0.cmd_execute(['iw', 'reg', 'set', country_code])
+
+def run_mbo_supp_oper_classes(dev, apdev, hapd, hapd2, country):
+ """MBO and supported operating classes"""
+ addr = dev[0].own_addr()
+
+ res2 = None
+ res5 = None
+
+ dev[0].flush_scan_cache()
+ dev[0].dump_monitor()
+
+ logger.info("Country: " + country)
+ set_reg(country, apdev[0], apdev[1], dev[0])
+ for j in range(5):
+ ev = dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=5)
+ if ev is None:
+ raise Exception("No regdom change event")
+ if "alpha2=" + country in ev:
+ break
+ dev[0].dump_monitor()
+ dev[1].dump_monitor()
+ dev[2].dump_monitor()
+ if hapd:
+ hapd.set("country_code", country)
+ hapd.enable()
+ dev[0].scan_for_bss(hapd.own_addr(), 5180, force_scan=True)
+ dev[0].connect("test-wnm-mbo", key_mgmt="NONE", scan_freq="5180")
+ sta = hapd.get_sta(addr)
+ res5 = sta['supp_op_classes'][2:]
+ dev[0].request("REMOVE_NETWORK all")
+ hapd.disable()
+ dev[0].wait_disconnected()
+ dev[0].dump_monitor()
+
+ hapd2.set("country_code", country)
+ hapd2.enable()
+ dev[0].scan_for_bss(hapd2.own_addr(), 2412, force_scan=True)
+ dev[0].connect("test-wnm-mbo-2", key_mgmt="NONE", scan_freq="2412")
+ sta = hapd2.get_sta(addr)
+ res2 = sta['supp_op_classes'][2:]
+ dev[0].request("REMOVE_NETWORK all")
+ hapd2.disable()
+ dev[0].wait_disconnected()
+ dev[0].dump_monitor()
+
+ return res2, res5
+
+def test_mbo_supp_oper_classes(dev, apdev):
+ """MBO and supported operating classes"""
+ params = { 'ssid': "test-wnm-mbo",
+ 'mbo': '1',
+ "country_code": "US",
+ 'ieee80211d': '1',
+ "ieee80211n": "1",
+ "hw_mode": "a",
+ "channel": "36" }
+ hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
+
+ params = { 'ssid': "test-wnm-mbo-2",
+ 'mbo': '1',
+ "country_code": "US",
+ 'ieee80211d': '1',
+ "ieee80211n": "1",
+ "hw_mode": "g",
+ "channel": "1" }
+ hapd2 = hostapd.add_ap(apdev[1], params, no_enable=True)
+
+ try:
+ za2, za5 = run_mbo_supp_oper_classes(dev, apdev, hapd, hapd2, "ZA")
+ fi2, fi5 = run_mbo_supp_oper_classes(dev, apdev, hapd, hapd2, "FI")
+ us2, us5 = run_mbo_supp_oper_classes(dev, apdev, hapd, hapd2, "US")
+ jp2, jp5 = run_mbo_supp_oper_classes(dev, apdev, hapd, hapd2, "JP")
+ bd2, bd5 = run_mbo_supp_oper_classes(dev, apdev, None, hapd2, "BD")
+ kz2, kz5 = run_mbo_supp_oper_classes(dev, apdev, None, hapd2, "KZ")
+ finally:
+ dev[0].dump_monitor()
+ set_reg("00", apdev[0], apdev[1], dev[0])
+ ev = dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=1)
+
+ za = "515354737475767778797a7b808182"
+ fi = "515354737475767778797a7b808182"
+ us = "515354737475767778797a7b7c7d7e7f808182"
+ jp = "51525354737475767778797a7b808182"
+ bd = "5153547c7d7e7f80"
+ kz = "515354"
+
+ tests = [ ("ZA", za, za2, za5, True),
+ ("FI", fi, fi2, fi5, True),
+ ("US", us, us2, us5, True),
+ ("JP", jp, jp2, jp5, True),
+ ("BD", bd, bd2, bd5, False),
+ ("KZ", kz, kz2, kz5, False) ]
+ for country, expected, res2, res5, inc5 in tests:
+ # For now, allow operating class 129 to be missing since not all
+ # installed regdb files include the 160 MHz channels.
+ expected2 = expected.replace('808182', '8082')
+ # For now, allow operating classes 121-123 to be missing since not all
+ # installed regdb files include the related US DFS channels.
+ expected2 = expected2.replace('78797a7b7c', '787c')
+ if res2 != expected and res2 != expected2:
+ raise Exception("Unexpected supp_op_class string (country=%s, 2.4 GHz): %s (expected: %s)" % (country, res2, expected))
+ if inc5 and res5 != expected and res5 != expected2:
+ raise Exception("Unexpected supp_op_class string (country=%s, 5 GHz): %s (expected: %s)" % (country, res5, expected))
+
+def test_mbo_assoc_disallow(dev, apdev, params):
+ """MBO and association disallowed"""
+ hapd1 = hostapd.add_ap(apdev[0], { "ssid": "MBO", "mbo": "1" })
+ hapd2 = hostapd.add_ap(apdev[1], { "ssid": "MBO", "mbo": "1" })
+
+ logger.debug("Set mbo_assoc_disallow with invalid value")
+ if "FAIL" not in hapd1.request("SET mbo_assoc_disallow 2"):
+ raise Exception("Set mbo_assoc_disallow for AP1 succeeded unexpectedly with value 2")
+
+ logger.debug("Disallow associations to AP1 and allow association to AP2")
+ if "OK" not in hapd1.request("SET mbo_assoc_disallow 1"):
+ raise Exception("Failed to set mbo_assoc_disallow for AP1")
+ if "OK" not in hapd2.request("SET mbo_assoc_disallow 0"):
+ raise Exception("Failed to set mbo_assoc_disallow for AP2")
+
+ dev[0].connect("MBO", key_mgmt="NONE", scan_freq="2412")
+
+ out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"),
+ "wlan.fc.type == 0 && wlan.fc.type_subtype == 0x00",
+ wait=False)
+ if "Destination address: " + hapd1.own_addr() in out:
+ raise Exception("Association request sent to disallowed AP")
+
+ timestamp = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"),
+ "wlan.fc.type_subtype == 0x00",
+ display=['frame.time'], wait=False)
+
+ logger.debug("Allow associations to AP1 and disallow associations to AP2")
+ if "OK" not in hapd1.request("SET mbo_assoc_disallow 0"):
+ raise Exception("Failed to set mbo_assoc_disallow for AP1")
+ if "OK" not in hapd2.request("SET mbo_assoc_disallow 1"):
+ raise Exception("Failed to set mbo_assoc_disallow for AP2")
+
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected()
+
+ # Force new scan, so the assoc_disallowed indication is updated */
+ dev[0].request("FLUSH")
+
+ dev[0].connect("MBO", key_mgmt="NONE", scan_freq="2412")
+
+ filter = 'wlan.fc.type == 0 && wlan.fc.type_subtype == 0x00 && frame.time > "' + timestamp.rstrip() + '"'
+ out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"),
+ filter, wait=False)
+ if "Destination address: " + hapd2.own_addr() in out:
+ raise Exception("Association request sent to disallowed AP 2")
+
+def test_mbo_assoc_disallow_ignore(dev, apdev):
+ """MBO and ignoring disallowed association"""
+ try:
+ _test_mbo_assoc_disallow_ignore(dev, apdev)
+ finally:
+ dev[0].request("SCAN_INTERVAL 5")
+
+def _test_mbo_assoc_disallow_ignore(dev, apdev):
+ hapd1 = hostapd.add_ap(apdev[0], { "ssid": "MBO", "mbo": "1" })
+ if "OK" not in hapd1.request("SET mbo_assoc_disallow 1"):
+ raise Exception("Failed to set mbo_assoc_disallow for AP1")
+
+ if "OK" not in dev[0].request("SCAN_INTERVAL 1"):
+ raise Exception("Failed to set scan interval")
+ dev[0].connect("MBO", key_mgmt="NONE", scan_freq="2412", wait_connect=False)
+ ev = dev[0].wait_event(["CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=10)
+ if ev is None:
+ raise Exception("CTRL-EVENT-NETWORK-NOT-FOUND not seen")
+
+ if "OK" not in dev[0].request("SET ignore_assoc_disallow 1"):
+ raise Exception("Failed to set ignore_assoc_disallow")
+ ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT"], timeout=10)
+ if ev is None:
+ raise Exception("CTRL-EVENT-ASSOC-REJECT not seen")
+ if "status_code=17" not in ev:
+ raise Exception("Unexpected association reject reason: " + ev)
+
+ if "OK" not in hapd1.request("SET mbo_assoc_disallow 0"):
+ raise Exception("Failed to set mbo_assoc_disallow for AP1")
+ dev[0].wait_connected()
+
+@remote_compatible
+def test_mbo_cell_capa_update(dev, apdev):
+ """MBO cellular data capability update"""
+ ssid = "test-wnm-mbo"
+ params = { 'ssid': ssid, 'mbo': '1' }
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+ if "OK" not in dev[0].request("SET mbo_cell_capa 1"):
+ raise Exception("Failed to set STA as cellular data capable")
+
+ dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412")
+
+ addr = dev[0].own_addr()
+ sta = hapd.get_sta(addr)
+ if 'mbo_cell_capa' not in sta or sta['mbo_cell_capa'] != '1':
+ raise Exception("mbo_cell_capa missing after association")
+
+ if "OK" not in dev[0].request("SET mbo_cell_capa 3"):
+ raise Exception("Failed to set STA as cellular data not-capable")
+ # Duplicate update for additional code coverage
+ if "OK" not in dev[0].request("SET mbo_cell_capa 3"):
+ raise Exception("Failed to set STA as cellular data not-capable")
+
+ time.sleep(0.2)
+ sta = hapd.get_sta(addr)
+ if 'mbo_cell_capa' not in sta:
+ raise Exception("mbo_cell_capa missing after update")
+ if sta['mbo_cell_capa'] != '3':
+ raise Exception("mbo_cell_capa not updated properly")
+
+@remote_compatible
+def test_mbo_cell_capa_update_pmf(dev, apdev):
+ """MBO cellular data capability update with PMF required"""
+ ssid = "test-wnm-mbo"
+ passphrase = "12345678"
+ params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
+ params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
+ params["ieee80211w"] = "2"
+ params['mbo'] = '1'
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+ if "OK" not in dev[0].request("SET mbo_cell_capa 1"):
+ raise Exception("Failed to set STA as cellular data capable")
+
+ dev[0].connect(ssid, psk=passphrase, key_mgmt="WPA-PSK-SHA256",
+ proto="WPA2", ieee80211w="2", scan_freq="2412")
+
+ addr = dev[0].own_addr()
+ sta = hapd.get_sta(addr)
+ if 'mbo_cell_capa' not in sta or sta['mbo_cell_capa'] != '1':
+ raise Exception("mbo_cell_capa missing after association")
+
+ if "OK" not in dev[0].request("SET mbo_cell_capa 3"):
+ raise Exception("Failed to set STA as cellular data not-capable")
+
+ time.sleep(0.2)
+ sta = hapd.get_sta(addr)
+ if 'mbo_cell_capa' not in sta:
+ raise Exception("mbo_cell_capa missing after update")
+ if sta['mbo_cell_capa'] != '3':
+ raise Exception("mbo_cell_capa not updated properly")
+
+def test_mbo_wnm_token_wrap(dev, apdev):
+ """MBO WNM token wrap around"""
+ ssid = "test-wnm-mbo"
+ params = { 'ssid': ssid, 'mbo': '1' }
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+
+ dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412")
+
+ # Trigger transmission of 256 WNM-Notification frames to wrap around the
+ # 8-bit mbo_wnm_token counter.
+ for i in range(128):
+ if "OK" not in dev[0].request("SET mbo_cell_capa 1"):
+ raise Exception("Failed to set STA as cellular data capable")
+ if "OK" not in dev[0].request("SET mbo_cell_capa 3"):
+ raise Exception("Failed to set STA as cellular data not-capable")
+
+@remote_compatible
+def test_mbo_non_pref_chan(dev, apdev):
+ """MBO non-preferred channel list"""
+ ssid = "test-wnm-mbo"
+ params = { 'ssid': ssid, 'mbo': '1' }
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+ if "FAIL" not in dev[0].request("SET non_pref_chan 81:7:200:99"):
+ raise Exception("Invalid non_pref_chan value accepted")
+ if "FAIL" not in dev[0].request("SET non_pref_chan 81:15:200:3"):
+ raise Exception("Invalid non_pref_chan value accepted")
+ if "FAIL" not in dev[0].request("SET non_pref_chan 81:7:200:3 81:7:201:3"):
+ raise Exception("Invalid non_pref_chan value accepted")
+ if "OK" not in dev[0].request("SET non_pref_chan 81:7:200:3"):
+ raise Exception("Failed to set non-preferred channel list")
+ if "OK" not in dev[0].request("SET non_pref_chan 81:7:200:1 81:9:100:2"):
+ raise Exception("Failed to set non-preferred channel list")
+
+ dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412")
+
+ addr = dev[0].own_addr()
+ sta = hapd.get_sta(addr)
+ logger.debug("STA: " + str(sta))
+ if 'non_pref_chan[0]' not in sta:
+ raise Exception("Missing non_pref_chan[0] value (assoc)")
+ if sta['non_pref_chan[0]'] != '81:200:1:7':
+ raise Exception("Unexpected non_pref_chan[0] value (assoc)")
+ if 'non_pref_chan[1]' not in sta:
+ raise Exception("Missing non_pref_chan[1] value (assoc)")
+ if sta['non_pref_chan[1]'] != '81:100:2:9':
+ raise Exception("Unexpected non_pref_chan[1] value (assoc)")
+ if 'non_pref_chan[2]' in sta:
+ raise Exception("Unexpected non_pref_chan[2] value (assoc)")
+
+ if "OK" not in dev[0].request("SET non_pref_chan 81:9:100:2"):
+ raise Exception("Failed to update non-preferred channel list")
+ time.sleep(0.1)
+ sta = hapd.get_sta(addr)
+ logger.debug("STA: " + str(sta))
+ if 'non_pref_chan[0]' not in sta:
+ raise Exception("Missing non_pref_chan[0] value (update 1)")
+ if sta['non_pref_chan[0]'] != '81:100:2:9':
+ raise Exception("Unexpected non_pref_chan[0] value (update 1)")
+ if 'non_pref_chan[1]' in sta:
+ raise Exception("Unexpected non_pref_chan[1] value (update 1)")
+
+ if "OK" not in dev[0].request("SET non_pref_chan 81:9:100:2 81:10:100:2 81:8:100:2 81:7:100:1 81:5:100:1"):
+ raise Exception("Failed to update non-preferred channel list")
+ time.sleep(0.1)
+ sta = hapd.get_sta(addr)
+ logger.debug("STA: " + str(sta))
+ if 'non_pref_chan[0]' not in sta:
+ raise Exception("Missing non_pref_chan[0] value (update 2)")
+ if sta['non_pref_chan[0]'] != '81:100:1:7,5':
+ raise Exception("Unexpected non_pref_chan[0] value (update 2)")
+ if 'non_pref_chan[1]' not in sta:
+ raise Exception("Missing non_pref_chan[1] value (update 2)")
+ if sta['non_pref_chan[1]'] != '81:100:2:9,10,8':
+ raise Exception("Unexpected non_pref_chan[1] value (update 2)")
+ if 'non_pref_chan[2]' in sta:
+ raise Exception("Unexpected non_pref_chan[2] value (update 2)")
+
+ if "OK" not in dev[0].request("SET non_pref_chan 81:5:90:2 82:14:91:2"):
+ raise Exception("Failed to update non-preferred channel list")
+ time.sleep(0.1)
+ sta = hapd.get_sta(addr)
+ logger.debug("STA: " + str(sta))
+ if 'non_pref_chan[0]' not in sta:
+ raise Exception("Missing non_pref_chan[0] value (update 3)")
+ if sta['non_pref_chan[0]'] != '81:90:2:5':
+ raise Exception("Unexpected non_pref_chan[0] value (update 3)")
+ if 'non_pref_chan[1]' not in sta:
+ raise Exception("Missing non_pref_chan[1] value (update 3)")
+ if sta['non_pref_chan[1]'] != '82:91:2:14':
+ raise Exception("Unexpected non_pref_chan[1] value (update 3)")
+ if 'non_pref_chan[2]' in sta:
+ raise Exception("Unexpected non_pref_chan[2] value (update 3)")
+
+ if "OK" not in dev[0].request("SET non_pref_chan "):
+ raise Exception("Failed to update non-preferred channel list")
+ time.sleep(0.1)
+ sta = hapd.get_sta(addr)
+ logger.debug("STA: " + str(sta))
+ if 'non_pref_chan[0]' in sta:
+ raise Exception("Unexpected non_pref_chan[0] value (update 4)")
+
+@remote_compatible
+def test_mbo_sta_supp_op_classes(dev, apdev):
+ """MBO STA supported operating classes"""
+ ssid = "test-wnm-mbo"
+ params = { 'ssid': ssid, 'mbo': '1' }
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412")
+
+ addr = dev[0].own_addr()
+ sta = hapd.get_sta(addr)
+ logger.debug("STA: " + str(sta))
+ if 'supp_op_classes' not in sta:
+ raise Exception("No supp_op_classes")
+ supp = bytearray(sta['supp_op_classes'].decode("hex"))
+ if supp[0] != 81:
+ raise Exception("Unexpected current operating class %d" % supp[0])
+ if 115 not in supp:
+ raise Exception("Operating class 115 missing")
+
+def test_mbo_failures(dev, apdev):
+ """MBO failure cases"""
+ ssid = "test-wnm-mbo"
+ params = { 'ssid': ssid, 'mbo': '1' }
+ hapd = hostapd.add_ap(apdev[0], params)
+
+ with alloc_fail(dev[0], 1, "wpas_mbo_ie"):
+ dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412")
+
+ with alloc_fail(dev[0], 1, "wpas_mbo_send_wnm_notification"):
+ if "OK" not in dev[0].request("SET mbo_cell_capa 1"):
+ raise Exception("Failed to set STA as cellular data capable")
+ with fail_test(dev[0], 1, "wpas_mbo_send_wnm_notification"):
+ if "OK" not in dev[0].request("SET mbo_cell_capa 3"):
+ raise Exception("Failed to set STA as cellular data not-capable")
+ with alloc_fail(dev[0], 1, "wpas_mbo_update_non_pref_chan"):
+ if "FAIL" not in dev[0].request("SET non_pref_chan 81:7:200:3"):
+ raise Exception("non_pref_chan value accepted during OOM")
+ with alloc_fail(dev[0], 2, "wpas_mbo_update_non_pref_chan"):
+ if "FAIL" not in dev[0].request("SET non_pref_chan 81:7:200:3"):
+ raise Exception("non_pref_chan value accepted during OOM")
+
+def test_mbo_wnm_bss_tm_ie_parsing(dev, apdev):
+ """MBO BSS transition request MBO IE parsing"""
+ ssid = "test-wnm-mbo"
+ params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
+ hapd = hostapd.add_ap(apdev[0], params)
+ bssid = apdev[0]['bssid']
+ addr = dev[0].own_addr()
+ dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK",
+ proto="WPA2", ieee80211w="0", scan_freq="2412")
+
+ dev[0].request("SET ext_mgmt_frame_handling 1")
+ hdr = "d0003a01" + addr.replace(':', '') + bssid.replace(':', '') + bssid.replace(':', '') + "3000"
+ btm_hdr = "0a070100030001"
+
+ tests = [ ("Truncated attribute in MBO IE", "dd06506f9a160101"),
+ ("Unexpected cell data capa attribute length in MBO IE",
+ "dd09506f9a160501030500"),
+ ("Unexpected transition reason attribute length in MBO IE",
+ "dd06506f9a160600"),
+ ("Unexpected assoc retry delay attribute length in MBO IE",
+ "dd0c506f9a160100080200000800"),
+ ("Unknown attribute id 255 in MBO IE",
+ "dd06506f9a16ff00") ]
+
+ for test, mbo_ie in tests:
+ logger.info(test)
+ dev[0].request("NOTE " + test)
+ frame = hdr + btm_hdr + mbo_ie
+ if "OK" not in dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + frame):
+ raise Exception("MGMT_RX_PROCESS failed")
+
+ logger.info("Unexpected association retry delay")
+ dev[0].request("NOTE Unexpected association retry delay")
+ btm_hdr = "0a070108030001112233445566778899aabbcc"
+ mbo_ie = "dd08506f9a1608020000"
+ frame = hdr + btm_hdr + mbo_ie
+ if "OK" not in dev[0].request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + frame):
+ raise Exception("MGMT_RX_PROCESS failed")
+
+ dev[0].request("SET ext_mgmt_frame_handling 0")
--- /dev/null
+# Radio measurement
+# Copyright(c) 2013 - 2016 Intel Mobile Communications GmbH.
+# Copyright(c) 2011 - 2016 Intel Corporation. All rights reserved.
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+
+import re
+import logging
+logger = logging.getLogger()
+
+import hostapd
+from utils import HwsimSkip
+
+nr="00112233445500000000510107"
+lci="01000800101298c0b512926666f6c2f1001c00004104050000c00012"
+civic="01000b0011223344556677889900998877665544332211aabbccddeeff"
+
+def check_nr_results(dev, bssids=None, lci=False, civic=False):
+ if bssids is None:
+ ev = dev.wait_event(["RRM-NEIGHBOR-REP-REQUEST-FAILED" ], timeout=10)
+ if ev is None:
+ raise Exception("RRM neighbor report failure not received")
+ return
+
+ received = []
+ for bssid in bssids:
+ ev = dev.wait_event(["RRM-NEIGHBOR-REP-RECEIVED"], timeout=10)
+ if ev is None:
+ raise Exception("RRM report result not indicated")
+ received.append(ev)
+
+ for bssid in bssids:
+ found = False
+ for r in received:
+ if "RRM-NEIGHBOR-REP-RECEIVED bssid=" + bssid in r:
+ if lci and "lci=" not in r:
+ raise Exception("LCI data not reported for %s" % bssid)
+ if civic and "civic=" not in r:
+ raise Exception("civic data not reported for %s" % bssid)
+ received.remove(r)
+ found = True
+ break
+ if not found:
+ raise Exception("RRM report result for %s not indicated" % bssid)
+
+def test_rrm_neighbor_db(dev, apdev):
+ """hostapd ctrl_iface SET_NEIGHBOR"""
+ params = { "ssid": "test", "rrm_neighbor_report": "1" }
+ hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+
+ # Bad BSSID
+ if "FAIL" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:gg ssid=\"test1\" nr=" + nr):
+ raise Exception("Set neighbor succeeded unexpectedly")
+
+ # Bad SSID
+ if "FAIL" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:55 ssid=test1 nr=" + nr):
+ raise Exception("Set neighbor succeeded unexpectedly")
+
+ # No SSID
+ if "FAIL" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:55 nr=" + nr):
+ raise Exception("Set neighbor succeeded unexpectedly")
+
+ # No NR
+ if "FAIL" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\""):
+ raise Exception("Set neighbor succeeded unexpectedly")
+
+ # Odd length of NR
+ if "FAIL" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\" nr=" + nr[:-1]):
+ raise Exception("Set neighbor succeeded unexpectedly")
+
+ # No entry yet in database
+ if "FAIL" not in hapd.request("REMOVE_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\""):
+ raise Exception("Remove neighbor succeeded unexpectedly")
+
+ # Add a neighbor entry
+ if "OK" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\" nr=" + nr + " lci=" + lci + " civic=" + civic):
+ raise Exception("Set neighbor failed")
+
+ # Another BSSID with the same SSID
+ if "OK" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:56 ssid=\"test1\" nr=" + nr + " lci=" + lci + " civic=" + civic):
+ raise Exception("Set neighbor failed")
+
+ # Fewer parameters
+ if "OK" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\" nr=" + nr):
+ raise Exception("Set neighbor failed")
+
+ # SSID in hex format
+ if "OK" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:55 ssid=7465737431 nr=" + nr):
+ raise Exception("Set neighbor failed")
+
+ # With more parameters
+ if "OK" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\" nr=" + nr + " civic=" + civic):
+ raise Exception("Set neighbor failed")
+
+ # With all parameters
+ if "OK" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\" nr=" + nr + " lci=" + lci + " civic=" + civic):
+ raise Exception("Set neighbor failed")
+
+ # Another SSID on the same BSSID
+ if "OK" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:55 ssid=\"test2\" nr=" + nr + " lci=" + lci):
+ raise Exception("Set neighbor failed")
+
+ if "OK" not in hapd.request("REMOVE_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\""):
+ raise Exception("Remove neighbor failed")
+
+ if "OK" not in hapd.request("REMOVE_NEIGHBOR 00:11:22:33:44:56 ssid=\"test1\""):
+ raise Exception("Remove neighbor failed")
+
+ if "OK" not in hapd.request("REMOVE_NEIGHBOR 00:11:22:33:44:55 ssid=\"test2\""):
+ raise Exception("Remove neighbor failed")
+
+ # Double remove
+ if "FAIL" not in hapd.request("REMOVE_NEIGHBOR 00:11:22:33:44:55 ssid=\"test1\""):
+ raise Exception("Remove neighbor succeeded unexpectedly")
+
+def test_rrm_neighbor_rep_req(dev, apdev):
+ """wpa_supplicant ctrl_iface NEIGHBOR_REP_REQUEST"""
+ nr1="00112233445500000000510107"
+ nr2="00112233445600000000510107"
+ nr3="dd112233445500000000510107"
+
+ params = { "ssid": "test" }
+ hostapd.add_ap(apdev[0]['ifname'], params)
+ params = { "ssid": "test2", "rrm_neighbor_report": "1" }
+ hapd = hostapd.add_ap(apdev[1]['ifname'], params)
+
+ bssid1 = apdev[1]['bssid']
+
+ dev[0].connect("test", key_mgmt="NONE", scan_freq="2412")
+ if "FAIL" not in dev[0].request("NEIGHBOR_REP_REQUEST"):
+ raise Exception("Request succeeded unexpectedly (AP without RRM)")
+ if "FAIL" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"abcdef\""):
+ raise Exception("Request succeeded unexpectedly (AP without RRM 2)")
+ dev[0].request("DISCONNECT")
+
+ rrm = int(dev[0].get_driver_status_field("capa.rrm_flags"), 16)
+ if rrm & 0x5 != 0x5 and rrm & 0x10 != 0x10:
+ raise HwsimSkip("Required RRM capabilities are not supported")
+
+ dev[0].connect("test2", key_mgmt="NONE", scan_freq="2412")
+
+ if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST"):
+ raise Exception("Request failed")
+ check_nr_results(dev[0], [bssid1])
+
+ if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST lci"):
+ raise Exception("Request failed")
+ check_nr_results(dev[0], [bssid1])
+
+ if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST lci civic"):
+ raise Exception("Request failed")
+ check_nr_results(dev[0], [bssid1])
+
+ if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test3\""):
+ raise Exception("Request failed")
+ check_nr_results(dev[0])
+
+ if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test3\" lci civic"):
+ raise Exception("Request failed")
+ check_nr_results(dev[0])
+
+ if "OK" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:55 ssid=\"test3\" nr=" + nr1 + " lci=" + lci + " civic=" + civic):
+ raise Exception("Set neighbor failed")
+ if "OK" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:56 ssid=\"test3\" nr=" + nr2 + " lci=" + lci + " civic=" + civic):
+ raise Exception("Set neighbor failed")
+ if "OK" not in hapd.request("SET_NEIGHBOR 00:11:22:33:44:56 ssid=\"test4\" nr=" + nr2 + " lci=" + lci + " civic=" + civic):
+ raise Exception("Set neighbor failed")
+ if "OK" not in hapd.request("SET_NEIGHBOR dd:11:22:33:44:55 ssid=\"test5\" nr=" + nr3 + " lci=" + lci):
+ raise Exception("Set neighbor failed")
+
+ if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test3\""):
+ raise Exception("Request failed")
+ check_nr_results(dev[0], ["00:11:22:33:44:55", "00:11:22:33:44:56"])
+
+ if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test3\" lci"):
+ raise Exception("Request failed")
+ check_nr_results(dev[0], ["00:11:22:33:44:55", "00:11:22:33:44:56"],
+ lci=True)
+
+ if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test3\" civic"):
+ raise Exception("Request failed")
+ check_nr_results(dev[0], ["00:11:22:33:44:55", "00:11:22:33:44:56"],
+ civic=True)
+
+ if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test3\" lci civic"):
+ raise Exception("Request failed")
+ check_nr_results(dev[0], ["00:11:22:33:44:55", "00:11:22:33:44:56"],
+ lci=True, civic=True)
+
+ if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test4\""):
+ raise Exception("Request failed")
+ check_nr_results(dev[0], ["00:11:22:33:44:56"])
+
+ if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test4\" lci"):
+ raise Exception("Request failed")
+ check_nr_results(dev[0], ["00:11:22:33:44:56"], lci=True)
+
+ if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test4\" civic"):
+ raise Exception("Request failed")
+ check_nr_results(dev[0], ["00:11:22:33:44:56"], civic=True)
+
+ if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test4\" lci civic"):
+ raise Exception("Request failed")
+ check_nr_results(dev[0], ["00:11:22:33:44:56"], lci=True, civic=True)
+
+ if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test5\""):
+ raise Exception("Request failed")
+ check_nr_results(dev[0], ["dd:11:22:33:44:55"])
+
+ if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test5\" lci"):
+ raise Exception("Request failed")
+ check_nr_results(dev[0], ["dd:11:22:33:44:55"], lci=True)
+
+ if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test5\" civic"):
+ raise Exception("Request failed")
+ check_nr_results(dev[0], ["dd:11:22:33:44:55"])
+
+ if "OK" not in dev[0].request("NEIGHBOR_REP_REQUEST ssid=\"test5\" lci civic"):
+ raise Exception("Request failed")
+ check_nr_results(dev[0], ["dd:11:22:33:44:55"], lci=True)
+
+def test_rrm_lci_req(dev, apdev):
+ """hostapd lci request"""
+
+ rrm = int(dev[0].get_driver_status_field("capa.rrm_flags"), 16)
+ if rrm & 0x5 != 0x5 and rrm & 0x10 != 0x10:
+ raise HwsimSkip("Required RRM capabilities are not supported")
+
+ params = { "ssid": "rrm", "rrm_neighbor_report": "1" }
+ hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+
+ # station not specified
+ if "FAIL" not in hapd.request("REQ_LCI "):
+ raise Exception("REQ_LCI with no station succeeded unexpectedly")
+
+ # station that is not connected specified
+ if "FAIL" not in hapd.request("REQ_LCI " + dev[0].own_addr()):
+ raise Exception("REQ_LCI succeeded unexpectedly (station not connected)")
+
+ dev[0].request("SET LCI ")
+ dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
+
+ # station connected without LCI
+ if "FAIL" not in hapd.request("REQ_LCI " + dev[0].own_addr()):
+ raise Exception("REQ_LCI succeeded unexpectedly (station without lci)")
+
+ dev[0].request("DISCONNECT")
+ dev[0].wait_disconnected(timeout=2)
+
+ dev[0].request("SET LCI " + lci)
+
+ dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
+
+ # station connected with LCI
+ if "OK" not in hapd.request("REQ_LCI " + dev[0].own_addr()):
+ raise Exception("REQ_LCI failed unexpectedly")
+
+def test_rrm_ftm_range_req(dev, apdev):
+ """hostapd FTM range request command"""
+
+ rrm = int(dev[0].get_driver_status_field("capa.rrm_flags"), 16)
+ if rrm & 0x5 != 0x5 and rrm & 0x10 != 0x10:
+ raise HwsimSkip("Required RRM capabilities are not supported")
+
+ params = { "ssid": "rrm", "rrm_neighbor_report": "1" }
+ hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+
+ # station not specified
+ if "FAIL" not in hapd.request("REQ_RANGE "):
+ raise Exception("REQ_RANGE with no station succeeded unexpectedly")
+
+ # station that is not connected specified
+ if "FAIL" not in hapd.request("REQ_RANGE " + dev[0].own_addr()):
+ raise Exception("REQ_RANGE succeeded unexpectedly (station not connected)")
+
+ # No responders specified
+ if "FAIL" not in hapd.request("REQ_RANGE " + dev[0].own_addr() + " 10 10"):
+ raise Exception("REQ_RANGE succeeded unexpectedly (no responder)")
+
+ # Bad responder address
+ if "FAIL" not in hapd.request("REQ_RANGE " + dev[0].own_addr() + " 10 10 00:11:22:33:44:"):
+ raise Exception("REQ_RANGE succeeded unexpectedly (bad responder address)")
+
+ # Bad responder address
+ if "FAIL" not in hapd.request("REQ_RANGE " + dev[0].own_addr() + " 10 10 00:11:22:33:44:55 00:11:22:33:44"):
+ raise Exception("REQ_RANGE succeeded unexpectedly (bad responder address 2)")
+
+ # Bad min_ap value
+ if "FAIL" not in hapd.request("REQ_RANGE " + dev[0].own_addr() + " 20 10 00:11:22:33:44:55"):
+ raise Exception("REQ_RANGE succeeded unexpectedly (invalid min_ap value)")
+
+ # Bad rand value
+ if "FAIL" not in hapd.request("REQ_RANGE " + dev[0].own_addr() + " 10 300 00:11:22:33:44:55"):
+ raise Exception("REQ_RANGE succeeded unexpectedly (invalid rand value)")
+
+ dev[0].connect("rrm", key_mgmt="NONE", scan_freq="2412")
+
+ # Responder not in database
+ # Note: this check would pass since the station does not support FTM range
+ # request and not because the responder is not in the database.
+ if "FAIL" not in hapd.request("REQ_RANGE " + dev[0].own_addr() + " 10 10 00:11:22:33:44:55"):
+ raise Exception("REQ_RANGE succeeded unexpectedly (responder not in database)")
+
+def test_rrm_ftm_capa_indication(dev, apdev):
+ """FTM capability indication"""
+ try:
+ _test_rrm_ftm_capa_indication(dev, apdev)
+ finally:
+ dev[0].request("SET ftm_initiator 0")
+ dev[0].request("SET ftm_responder 0")
+
+def _test_rrm_ftm_capa_indication(dev, apdev):
+ params = { "ssid": "ftm",
+ "ftm_responder": "1",
+ "ftm_initiator": "1", }
+ hapd = hostapd.add_ap(apdev[0]['ifname'], params)
+
+ if "OK" not in dev[0].request("SET ftm_initiator 1"):
+ raise Exception("could not set ftm_initiator")
+ if "OK" not in dev[0].request("SET ftm_responder 1"):
+ raise Exception("could not set ftm_responder")
+ dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412, force_scan=True)
--- /dev/null
+# wmediumd sanity checks
+# Copyright (c) 2015, Intel Deutschland GmbH
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+
+import tempfile, os, subprocess, errno
+from utils import HwsimSkip
+from test_ap_open import _test_ap_open
+
+CFG = """
+ifaces :
+{
+ ids = ["%s", "%s" ];
+ links = (
+ (0, 1, 30)
+ );
+};
+"""
+
+def test_wmediumd_simple(dev, apdev):
+ """test a simple wmediumd configuration"""
+ fd, fn = tempfile.mkstemp()
+ try:
+ f = os.fdopen(fd, 'w')
+ f.write(CFG % (apdev[0]['bssid'], dev[0].own_addr()))
+ f.close()
+ try:
+ p = subprocess.Popen(['wmediumd', '-c', fn],
+ stdout=open('/dev/null', 'a'),
+ stderr=subprocess.STDOUT)
+ except OSError, e:
+ if e.errno == errno.ENOENT:
+ raise HwsimSkip("wmediumd not available")
+ raise
+ try:
+ _test_ap_open(dev, apdev)
+ finally:
+ p.terminate()
+ p.wait()
+ # test that releasing hwsim works correctly
+ _test_ap_open(dev, apdev)
+ finally:
+ os.unlink(fn)
--- /dev/null
+# Environment configuration
+# Copyright (c) 2016, Tieto Corporation
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+
+#
+# Currently static definition, in the future this could be a config file,
+# or even common database with host management.
+#
+
+import logging
+logger = logging.getLogger()
+
+#
+# You can put your settings in cfg.py file with setup_params, devices
+# definitions in the format as below. In other case HWSIM cfg will be used.
+#
+setup_params = { "setup_hw" : "./tests/setup_hw.sh",
+ "hostapd" : "./tests/hostapd",
+ "wpa_supplicant" : "./tests/wpa_supplicant",
+ "iperf" : "iperf",
+ "wlantest" : "./tests/wlantest",
+ "wlantest_cli" : "./tests/wlantest_cli",
+ "country" : "US",
+ "log_dir" : "/tmp/",
+ "ipv4_test_net" : "192.168.12.0",
+ "trace_start" : "./tests/trace_start.sh",
+ "trace_stop" : "./tests/trace_stop.sh",
+ "perf_start" : "./tests/perf_start.sh",
+ "perf_stop" : "./tests/perf_stop.sh" }
+
+#
+#devices = [{"hostname": "192.168.254.58", "ifname" : "wlan0", "port": "9877", "name" : "t2-ath9k", "flags" : "AP_HT40 STA_HT40"},
+# {"hostname": "192.168.254.58", "ifname" : "wlan1", "port": "9877", "name" : "t2-ath10k", "flags" : "AP_VHT80"},
+# {"hostname": "192.168.254.58", "ifname" : "wlan3", "port": "9877", "name" : "t2-intel7260", "flags" : "STA_VHT80"},
+# {"hostname": "192.168.254.55", "ifname" : "wlan0, wlan1, wlan2", "port": "", "name" : "t3-monitor"},
+# {"hostname": "192.168.254.50", "ifname" : "wlan0", "port": "9877", "name" : "t1-ath9k"},
+# {"hostname": "192.168.254.50", "ifname" : "wlan1", "port": "9877", "name" : "t1-ath10k"}]
+
+#
+# HWSIM - ifaces available after modprobe mac80211_hwsim
+#
+devices = [{"hostname": "localhost", "ifname": "wlan0", "port": "9868", "name": "hwsim0", "flags": "AP_VHT80 STA_VHT80"},
+ {"hostname": "localhost", "ifname": "wlan1", "port": "9878", "name": "hwsim1", "flags": "AP_VHT80 STA_VHT80"},
+ {"hostname": "localhost", "ifname": "wlan2", "port": "9888", "name": "hwsim2", "flags": "AP_VHT80 STA_VHT80"},
+ {"hostname": "localhost", "ifname": "wlan3", "port": "9898", "name": "hwsim3", "flags": "AP_VHT80 STA_VHT80"},
+ {"hostname": "localhost", "ifname": "wlan4", "port": "9908", "name": "hwsim4", "flags": "AP_VHT80 STA_VHT80"}]
+
+
+def get_setup_params(filename="cfg.py"):
+ try:
+ mod = __import__(filename.split(".")[0])
+ return mod.setup_params
+ except:
+ logger.debug("__import__(" + filename + ") failed, using static settings")
+ pass
+ return setup_params
+
+def get_devices(filename="cfg.py"):
+ try:
+ mod = __import__(filename.split(".")[0])
+ return mod.devices
+ except:
+ logger.debug("__import__(" + filename + ") failed, using static settings")
+ pass
+ return devices
+
+def get_device(devices, name=None, flags=None, lock=False):
+ if name is None and flags is None:
+ raise Exception("Failed to get device")
+ for device in devices:
+ if device['name'] == name:
+ return device
+ for device in devices:
+ try:
+ device_flags = device['flags']
+ if device_flags.find(flags) != -1:
+ return device
+ except:
+ pass
+ raise Exception("Failed to get device " + name)
+
+def put_device(devices, name):
+ pass
--- /dev/null
+# Hwsim wrapper
+# Copyright (c) 2016, Tieto Corporation
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+
+import remotehost
+from wpasupplicant import WpaSupplicant
+import hostapd
+import config
+import rutils
+import monitor
+import traceback
+import wlantest
+
+import logging
+logger = logging.getLogger()
+
+def run_hwsim_test(devices, setup_params, refs, duts, monitors, hwsim_test):
+ try:
+ ref_hosts = []
+ dut_hosts = []
+ dev = []
+ apdev = []
+
+ # get hosts
+ for ref in refs:
+ ref_host = rutils.get_host(devices, ref)
+ ref_hosts.append(ref_host)
+ for dut in duts:
+ dut_host = rutils.get_host(devices, dut)
+ dut_hosts.append(dut_host)
+
+ # setup log dir
+ local_log_dir = setup_params['local_log_dir']
+
+ # setup hw before test
+ rutils.setup_hw(ref_hosts, setup_params)
+ rutils.setup_hw(dut_hosts, setup_params)
+
+ # run monitors if requested/possible
+ for ref_host in ref_hosts:
+ monitor.add(ref_host, monitors)
+ monitor.run(ref_host, setup_params)
+ for dut_host in dut_hosts:
+ monitor.add(dut_host, monitors)
+ monitor.run(dut_host, setup_params)
+
+ monitor_hosts = monitor.create(devices, setup_params, refs, duts,
+ monitors)
+ mon = None
+ if len(monitor_hosts) > 0:
+ mon = monitor_hosts[0]
+ wlantest.Wlantest.reset_remote_wlantest()
+ wlantest.Wlantest.register_remote_wlantest(mon, setup_params,
+ monitor)
+
+ # run hostapd/wpa_supplicant
+ for ref_host in ref_hosts:
+ rutils.run_wpasupplicant(ref_host, setup_params)
+ wpas = WpaSupplicant(hostname=ref_host.host, global_iface="udp",
+ global_port=ref_host.port)
+ wpas.interface_add(ref_host.ifname)
+ dev.append(wpas)
+ for dut_host in dut_hosts:
+ rutils.run_hostapd(dut_host, setup_params)
+ dut_host.dev['bssid'] = rutils.get_mac_addr(dut_host)
+ apdev.append(dut_host.dev)
+
+ # run hwsim test/currently only 2 params tests
+ if hwsim_test.func_code.co_argcount == 1:
+ hwsim_test(dev)
+ elif hwsim_test.func_code.co_argcount == 2:
+ hwsim_test(dev, apdev)
+ else:
+ raise Exception("more than 2 arguments required")
+
+ # hostapd/wpa_supplicant cleanup
+ for wpas in dev:
+ wpas.interface_remove(wpas.host.ifname)
+ wpas.terminate()
+ dev = []
+
+ # remove monitors
+ for ref_host in ref_hosts:
+ monitor.remove(ref_host)
+ for dut_host in dut_hosts:
+ monitor.remove(dut_host)
+
+ for ref_host in ref_hosts:
+ ref_host.execute(["killall", "wpa_supplicant"])
+ ref_host.get_logs(local_log_dir)
+ for dut_host in dut_hosts:
+ dut_host.execute(["killall", "hostapd"])
+ dut_host.get_logs(local_log_dir)
+ if mon is not None:
+ wlantest.Wlantest.reset_remote_wlantest()
+ mon.get_logs(local_log_dir)
+
+ return ""
+ except:
+ logger.info(traceback.format_exc())
+ for wpas in dev:
+ try:
+ wpas.interface_remove(wpas.host.ifname)
+ wpas.terminate()
+ except:
+ pass
+
+ for ref_host in ref_hosts:
+ monitor.remove(ref_host)
+ for dut_host in dut_hosts:
+ monitor.remove(dut_host)
+
+ for ref_host in ref_hosts:
+ ref_host.execute(["killall", "wpa_supplicant"])
+ ref_host.get_logs(local_log_dir)
+ for dut_host in dut_hosts:
+ dut_host.execute(["killall", "hostapd"])
+ dut_host.get_logs(local_log_dir)
+ if mon is not None:
+ wlantest.Wlantest.reset_remote_wlantest()
+ mon.get_logs(local_log_dir)
+ raise
--- /dev/null
+# Monitor support
+# Copyright (c) 2016, Tieto Corporation
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+
+import time
+from remotehost import Host
+import config
+import rutils
+import re
+import traceback
+import logging
+logger = logging.getLogger()
+import hostapd
+
+# standalone monitor with multi iface support
+def create(devices, setup_params, refs, duts, monitors):
+ mons = []
+ mhosts = []
+ hosts = duts + refs
+
+ # choose only standalone monitors
+ for monitor in monitors:
+ if monitor not in hosts and monitor != "all":
+ mons.append(monitor)
+
+ for mon in mons:
+ dev = config.get_device(devices, mon)
+ if dev is None:
+ continue
+
+ host = Host(host = dev['hostname'],
+ ifname = dev['ifname'],
+ port = dev['port'],
+ name = dev['name'])
+
+ try:
+ host.execute(["iw", "reg", "set", setup_params['country']])
+ rutils.setup_hw_host(host, setup_params, True)
+ except:
+ pass
+ mhosts.append(host)
+
+ return mhosts
+
+def destroy(devices, hosts):
+ for host in hosts:
+ stop(host)
+ for monitor in host.monitors:
+ host.execute(["ifconfig", monitor, "down"])
+
+def setup(host, monitor_params):
+ if host is None:
+ return
+
+ ifaces = re.split('; | |, ', host.ifname)
+ count = 0
+ for param in monitor_params:
+ try:
+ iface = ifaces[count]
+ except:
+ logger.debug(traceback.format_exc())
+ break
+ host.execute(["ifconfig", iface, " down"])
+ host.execute(["iw", iface, "set type monitor"])
+ host.execute(["ifconfig", iface, "up"])
+ status, buf = host.execute(["iw", iface, "set", "freq", param['freq'],
+ param['bw'], param['center_freq1'],
+ param['center_freq2']])
+ if status != 0:
+ logger.debug("Could not setup monitor interface: " + buf)
+ continue
+ host.monitors.append(iface)
+ count = count + 1
+
+def run(host, setup_params):
+ monitor_res = []
+ log_monitor = ""
+ if host is None:
+ return None
+ if len(host.monitors) == 0:
+ return None
+ try:
+ log_dir = setup_params['log_dir']
+ tc_name = setup_params['tc_name']
+ except:
+ return None
+
+ tshark = "tshark"
+ for monitor in host.monitors:
+ host.execute(["ifconfig", monitor, "up"])
+ tshark = tshark + " -i " + monitor
+ log_monitor = log_monitor + "_" + monitor
+
+ log = log_dir + tc_name + "_" + host.name + log_monitor + ".pcap"
+ host.add_log(log)
+ thread = host.execute_run([tshark, "-w", log], monitor_res)
+ host.thread = thread
+
+
+def stop(host):
+ if host is None:
+ return
+ if len(host.monitors) == 0:
+ return
+ if host.thread is None:
+ return
+
+ host.execute(["killall", "-s", "INT", "tshark"])
+ host.wait_execute_complete(host.thread, 5)
+ if host.thread.isAlive():
+ raise Exception("tshark still alive")
+ host.thread = None
+
+# Add monitor to existing interface
+def add(host, monitors):
+ if host is None:
+ return
+
+ for monitor in monitors:
+ if monitor != "all" and monitor != host.name:
+ continue
+ mon = "mon_" + host.ifname
+ status, buf = host.execute(["iw", host.ifname, "interface", "add", mon,
+ "type", "monitor"])
+ if status == 0:
+ host.monitors.append(mon)
+ host.execute(["ifconfig", mon, "up"])
+ else:
+ logger.debug("Could not add monitor for " + host.name)
+
+def remove(host):
+ stop(host)
+ for monitor in host.monitors:
+ host.execute(["iw", monitor, "del"])
+ host.monitors.remove(monitor)
+
+
+# get monitor params from hostapd/wpa_supplicant
+def get_monitor_params(wpa, is_p2p=False):
+ if is_p2p:
+ get_status_field_f = wpa.get_group_status_field
+ else:
+ get_status_field_f = wpa.get_status_field
+ freq = get_status_field_f("freq")
+ bw = "20"
+ center_freq1=""
+ center_freq2=""
+
+ vht_oper_chwidth = get_status_field_f("vht_oper_chwidth")
+ secondary_channel = get_status_field_f("secondary_channel")
+ vht_oper_centr_freq_seg0_idx = get_status_field_f("vht_oper_centr_freq_seg0_idx")
+ vht_oper_centr_freq_seg1_idx = get_status_field_f("vht_oper_centr_freq_seg1_idx")
+ if vht_oper_chwidth == "0" or vht_oper_chwidth is None:
+ if secondary_channel == "1":
+ bw = "40"
+ center_freq1 = str(int(freq) + 10)
+ elif secondary_channel == "-1":
+ center_freq1 = str(int(freq) - 10)
+ else:
+ pass
+ elif vht_oper_chwidth == "1":
+ bw = "80"
+ center_freq1 = str(int(vht_oper_centr_freq_seg0_idx) * 5 + 5000)
+ elif vht_oper_chwidth == "2":
+ bw = "160"
+ center_freq1 = str(int(vht_oper_centr_freq_seg0_idx) * 5 + 5000)
+ elif vht_oper_chwidth == "3":
+ bw = "80+80"
+ center_freq1 = str(int(vht_oper_centr_freq_seg0_idx) * 5 + 5000)
+ center_freq2 = str(int(vht_oper_centr_freq_seg1_idx) * 5 + 5000)
+ else:
+ pass
+
+ monitor_params = { "freq" : freq,
+ "bw" : bw,
+ "center_freq1" : center_freq1,
+ "center_freq2" : center_freq2 }
+
+ return monitor_params
--- /dev/null
+#!/usr/bin/env python2
+#
+# Remote test case executor
+# Copyright (c) 2016, Tieto Corporation
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+
+import os
+import re
+import sys
+import time
+import traceback
+import getopt
+from datetime import datetime
+
+import logging
+logger = logging.getLogger()
+
+scriptsdir = os.path.dirname(os.path.realpath(sys.modules[__name__].__file__))
+sys.path.append(os.path.join(scriptsdir, '..', '..', 'wpaspy'))
+sys.path.append(os.path.join(scriptsdir, '..', 'hwsim'))
+
+import wpaspy
+import config
+from test_devices import show_devices
+from test_devices import check_devices
+from rutils import TestSkip
+from utils import HwsimSkip
+from hwsim_wrapper import run_hwsim_test
+
+def usage():
+ print "USAGE: " + sys.argv[0] + " -t devices"
+ print "USAGE: " + sys.argv[0] + " -t check_devices"
+ print "USAGE: " + sys.argv[0] + " -d <dut_name> -t <all|sanity|tests_to_run> [-r <ref_name>] [-c <cfg_file.py>] [-m <all|monitor_name>] [-h hwsim_tests][-R][-T][-P][-v]"
+ print "USAGE: " + sys.argv[0]
+
+def get_devices(devices, duts, refs, monitors):
+ for dut in duts:
+ config.get_device(devices, dut, lock=True)
+ for ref in refs:
+ config.get_device(devices, ref, lock=True)
+ for monitor in monitors:
+ if monitor == "all":
+ continue
+ if monitor in duts:
+ continue
+ if monitor in refs:
+ continue
+ config.get_device(devices, monitor, lock=True)
+
+def put_devices(devices, duts, refs, monitors):
+ for dut in duts:
+ config.put_device(devices, dut)
+ for ref in refs:
+ config.put_device(devices, ref)
+ for monitor in monitors:
+ if monitor == "all":
+ continue
+ if monitor in duts:
+ continue
+ if monitor in refs:
+ continue
+ config.put_device(devices, monitor)
+
+def main():
+ duts = []
+ refs = []
+ monitors = []
+ filter_keys = []
+ requested_tests = ["help"]
+ requested_hwsim_tests = []
+ hwsim_tests = []
+ cfg_file = "cfg.py"
+ log_dir = "./logs/"
+ verbose = False
+ trace = False
+ restart = False
+ perf = False
+
+ # parse input parameters
+ try:
+ opts, args = getopt.getopt(sys.argv[1:], "d:r:t:l:k:c:m:h:vRPT",
+ ["dut=", "ref=", "tests=", "log-dir=",
+ "cfg=", "key=", "monitor=", "hwsim="])
+ except getopt.GetoptError as err:
+ print(err)
+ usage()
+ sys.exit(2)
+
+ for option, argument in opts:
+ if option == "-v":
+ verbose = True
+ elif option == "-R":
+ restart = True
+ elif option == "-T":
+ trace = True
+ elif option == "-P":
+ perf = True
+ elif option in ("-d", "--dut"):
+ duts.append(argument)
+ elif option in ("-r", "--ref"):
+ refs.append(argument)
+ elif option in ("-t", "--tests"):
+ requested_tests = re.split('; | |, ', argument)
+ elif option in ("-l", "--log-dir"):
+ log_dir = argument
+ elif option in ("-k", "--key"):
+ filter_keys.append(argument)
+ elif option in ("-m", "--monitor"):
+ monitors.append(argument)
+ elif option in ("-c", "--cfg"):
+ cfg_file = argument
+ elif option in ("-h", "--hwsim"):
+ requested_hwsim_tests = re.split('; | |, ', argument)
+ else:
+ assert False, "unhandled option"
+
+ # get env configuration
+ setup_params = config.get_setup_params(cfg_file)
+ devices = config.get_devices(cfg_file)
+
+ # put logs in log_dir
+ symlink = os.path.join(log_dir, "current");
+ if os.path.exists(symlink):
+ os.unlink(symlink)
+ log_dir = os.path.join(log_dir, time.strftime("%Y_%m_%d_%H_%M_%S"))
+ if not os.path.exists(log_dir):
+ os.makedirs(log_dir)
+ os.symlink(os.path.join("../", log_dir), symlink)
+
+ # setup restart/trace/perf request
+ setup_params['local_log_dir'] = log_dir
+ setup_params['restart_device'] = restart
+ setup_params['trace'] = trace
+ setup_params['perf'] = perf
+
+ # configure logger
+ logger.setLevel(logging.DEBUG)
+
+ stdout_handler = logging.StreamHandler()
+ stdout_handler.setLevel(logging.WARNING)
+ if verbose:
+ stdout_handler.setLevel(logging.DEBUG)
+ logger.addHandler(stdout_handler)
+
+ formatter = logging.Formatter('%(asctime)s - %(message)s')
+ file_name = os.path.join(log_dir, 'run-tests.log')
+ log_handler = logging.FileHandler(file_name)
+ log_handler.setLevel(logging.DEBUG)
+ log_handler.setFormatter(formatter)
+ logger.addHandler(log_handler)
+
+ # import available tests
+ tests = []
+ failed = []
+ test_modules = []
+ files = os.listdir(scriptsdir)
+ for t in files:
+ m = re.match(r'(test_.*)\.py$', t)
+ if m:
+ mod = __import__(m.group(1))
+ test_modules.append(mod.__name__.replace('test_', '', 1))
+ for key,val in mod.__dict__.iteritems():
+ if key.startswith("test_"):
+ tests.append(val)
+ test_names = list(set([t.__name__.replace('test_', '', 1) for t in tests]))
+
+ # import test_*
+ files = os.listdir("../hwsim/")
+ for t in files:
+ m = re.match(r'(test_.*)\.py$', t)
+ if m:
+ mod = __import__(m.group(1))
+ test_modules.append(mod.__name__.replace('test_', '', 1))
+ for key,val in mod.__dict__.iteritems():
+ if key.startswith("test_"):
+ hwsim_tests.append(val)
+
+ # setup hwsim tests
+ hwsim_tests_to_run = []
+ if len(requested_hwsim_tests) > 0:
+ # apply filters
+ for filter_key in filter_keys:
+ filtered_tests = []
+ for hwsim_test in hwsim_tests:
+ if re.search(filter_key, hwsim_test.__name__):
+ filtered_tests.append(hwsim_test)
+ hwsim_tests = filtered_tests
+
+ # setup hwsim_test we should run
+ if requested_hwsim_tests[0] == "all":
+ hwsim_tests_to_run = hwsim_tests
+ elif requested_hwsim_tests[0] == "remote":
+ hwsim_tests_to_run = [t for t in hwsim_tests
+ if hasattr(t, "remote_compatible") and
+ t.remote_compatible]
+ else:
+ for test in requested_hwsim_tests:
+ t = None
+ for tt in hwsim_tests:
+ name = tt.__name__.replace('test_', '', 1)
+ if name == test and tt.func_code.co_argcount <= 2:
+ t = tt
+ break
+ if not t:
+ logger.warning("hwsim test case: " + test + " NOT-FOUND")
+ continue
+ hwsim_tests_to_run.append(t)
+
+ # sort the list
+ test_names.sort()
+ tests.sort()
+
+ # print help
+ if requested_tests[0] == "help" and len(requested_hwsim_tests) == 0:
+ usage()
+ print "\nAvailable Devices:"
+ for device in devices:
+ print "\t", device['name']
+ print "\nAvailable tests:"
+ for test in test_names:
+ print "\t", test
+ print "\nAvailable hwsim tests:"
+ for hwsim_test in hwsim_tests:
+ print "\t", hwsim_test.__name__.replace('test_', '', 1)
+ return
+
+ # show/check devices
+ if requested_tests[0] == "devices":
+ show_devices(devices, setup_params)
+ return
+
+ # apply filters
+ for filter_key in filter_keys:
+ filtered_tests = []
+ for test in tests:
+ if re.search(filter_key, test.__name__):
+ filtered_tests.append(test)
+ tests = filtered_tests
+
+ # setup test we should run
+ tests_to_run = []
+ if requested_tests[0] == "all":
+ tests_to_run = tests
+ if requested_tests[0] == "help":
+ pass
+ elif requested_tests[0] == "sanity":
+ for test in tests:
+ if test.__name__.startswith("test_sanity_"):
+ tests_to_run.append(test)
+ else:
+ for test in requested_tests:
+ t = None
+ for tt in tests:
+ name = tt.__name__.replace('test_', '', 1)
+ if name == test:
+ t = tt
+ break
+ if not t:
+ logger.warning("test case: " + test + " NOT-FOUND")
+ continue
+ tests_to_run.append(t)
+
+ # lock devices
+ try:
+ get_devices(devices, duts, refs, monitors)
+ except Exception, e:
+ logger.warning("get devices failed: " + str(e))
+ logger.info(traceback.format_exc())
+ put_devices(devices, duts, refs, monitors)
+ return
+ except:
+ logger.warning("get devices failed")
+ logger.info(traceback.format_exc())
+ put_devices(devices, duts, refs, monitors)
+ return
+
+ # now run test cases
+ for dut in duts:
+ logger.warning("DUT: " + str(dut))
+ for ref in refs:
+ logger.warning("REF: " + str(ref))
+ for monitor in monitors:
+ logger.warning("MON: " + str(monitor))
+
+ # run check_devices at begining
+ logger.warning("RUN check_devices")
+ try:
+ check_devices(devices, setup_params, refs, duts, monitors)
+ except Exception, e:
+ logger.warning("FAILED: " + str(e))
+ logger.info(traceback.format_exc())
+ put_devices(devices, duts, refs, monitors)
+ return
+ except:
+ logger.warning("FAILED")
+ logger.info(traceback.format_exc())
+ put_devices(devices, duts, refs, monitors)
+ return
+ logger.warning("PASS")
+
+ test_no = 1
+ for test in tests_to_run:
+ try:
+ start = datetime.now()
+ setup_params['tc_name'] = test.__name__.replace('test_', '', 1)
+ logger.warning("START - " + setup_params['tc_name'] + " (" + str(test_no) + "/" + str(len(tests_to_run)) + ")")
+ if test.__doc__:
+ logger.info("Test: " + test.__doc__)
+
+ # run tc
+ res = test(devices, setup_params, refs, duts, monitors)
+
+ end = datetime.now()
+ logger.warning("PASS (" + res + ") - " + str((end - start).total_seconds()) + "s")
+ except KeyboardInterrupt:
+ put_devices(devices, duts, refs, monitors)
+ raise
+ except TestSkip, e:
+ end = datetime.now()
+ logger.warning("SKIP (" + str(e) + ") - " + str((end - start).total_seconds()) + "s")
+ except Exception, e:
+ end = datetime.now()
+ logger.warning("FAILED (" + str(e) + ") - " + str((end - start).total_seconds()) + "s")
+ logger.info(traceback.format_exc())
+ failed.append(test.__name__.replace('test_', '', 1))
+ except:
+ end = datetime.now()
+ logger.warning("FAILED - " + str((end - start).total_seconds()) + "s")
+ logger.info(traceback.format_exc())
+ failed.append(test.__name__.replace('test_', '', 1))
+ test_no += 1
+
+ test_no = 1
+ for hwsim_test in hwsim_tests_to_run:
+ try:
+ start = datetime.now()
+ setup_params['tc_name'] = hwsim_test.__name__.replace('test_', '', 1)
+ logger.warning("START - " + setup_params['tc_name'] + " (" + str(test_no) + "/" + str(len(hwsim_tests_to_run)) + ")")
+ res = run_hwsim_test(devices, setup_params, refs, duts, monitors, hwsim_test)
+ end = datetime.now()
+ logger.warning("PASS (" + res + ") - " + str((end - start).total_seconds()) + "s")
+ except KeyboardInterrupt:
+ put_devices(devices, duts, refs, monitors)
+ raise
+ except HwsimSkip,e:
+ end = datetime.now()
+ logger.warning("SKIP (" + str(e) + ") - " + str((end - start).total_seconds()) + "s")
+ failed.append(hwsim_test.__name__.replace('test_', '', 1))
+ except Exception, e:
+ end = datetime.now()
+ logger.warning("FAILED (" + str(e) + ") - " + str((end - start).total_seconds()) + "s")
+ logger.info(traceback.format_exc())
+ failed.append(hwsim_test.__name__.replace('test_', '', 1))
+ except:
+ end = datetime.now()
+ logger.warning("FAILED - " + str((end - start).total_seconds()) + "s")
+ logger.info(traceback.format_exc())
+ failed.append(hwsim_test.__name__.replace('test_', '', 1))
+ test_no += 1
+
+ # unlock devices
+ put_devices(devices, duts, refs, monitors)
+
+ if len(failed) > 0:
+ logger.warning("Failed test cases:")
+ for test in failed:
+ logger.warning("\t" + test)
+
+
+if __name__ == "__main__":
+ main()
--- /dev/null
+# Utils
+# Copyright (c) 2016, Tieto Corporation
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+
+import re
+import time
+from remotehost import Host
+import hostapd
+import config
+
+class TestSkip(Exception):
+ def __init__(self, reason):
+ self.reason = reason
+ def __str__(self):
+ return self.reason
+
+# get host based on name
+def get_host(devices, dev_name):
+ dev = config.get_device(devices, dev_name)
+ host = Host(host = dev['hostname'],
+ ifname = dev['ifname'],
+ port = dev['port'],
+ name = dev['name'])
+ host.dev = dev
+ return host
+
+# Run setup_hw - hardware specific
+def setup_hw_host_iface(host, iface, setup_params, force_restart=False):
+ try:
+ setup_hw = setup_params['setup_hw']
+ restart = ""
+ try:
+ if setup_params['restart_device'] == True:
+ restart = "-R"
+ except:
+ pass
+
+ if force_restart:
+ restart = "-R"
+
+ host.execute([setup_hw, "-I", iface, restart])
+ except:
+ pass
+
+def setup_hw_host(host, setup_params, force_restart=False):
+ ifaces = re.split('; | |, ', host.ifname)
+ for iface in ifaces:
+ setup_hw_host_iface(host, iface, setup_params, force_restart)
+
+def setup_hw(hosts, setup_params, force_restart=False):
+ for host in hosts:
+ setup_hw_host(host, setup_params, force_restart)
+
+# get traces - hw specific
+def trace_start(hosts, setup_params):
+ for host in hosts:
+ trace_start_stop(host, setup_params, start=True)
+
+def trace_stop(hosts, setup_params):
+ for host in hosts:
+ trace_start_stop(host, setup_params, start=False)
+
+def trace_start_stop(host, setup_params, start):
+ if setup_params['trace'] == False:
+ return
+ try:
+ start_trace = setup_params['trace_start']
+ stop_trace = setup_params['trace_stop']
+ if start:
+ cmd = start_trace
+ else:
+ cmd = stop_trace
+ trace_dir = setup_params['log_dir'] + host.ifname + "/remote_traces"
+ host.add_log(trace_dir + "/*")
+ host.execute([cmd, "-I", host.ifname, "-D", trace_dir])
+ except:
+ pass
+
+# get perf
+def perf_start(hosts, setup_params):
+ for host in hosts:
+ perf_start_stop(host, setup_params, start=True)
+
+def perf_stop(hosts, setup_params):
+ for host in hosts:
+ perf_start_stop(host, setup_params, start=False)
+
+def perf_start_stop(host, setup_params, start):
+ if setup_params['perf'] == False:
+ return
+ try:
+ perf_start = setup_params['perf_start']
+ perf_stop = setup_params['perf_stop']
+ if start:
+ cmd = perf_start
+ else:
+ cmd = perf_stop
+ perf_dir = setup_params['log_dir'] + host.ifname + "/remote_perf"
+ host.add_log(perf_dir + "/*")
+ host.execute([cmd, "-I", host.ifname, "-D", perf_dir])
+ except:
+ pass
+
+# hostapd/wpa_supplicant helpers
+def run_hostapd(host, setup_params):
+ log_file = None
+ try:
+ tc_name = setup_params['tc_name']
+ log_dir = setup_params['log_dir']
+ log_file = log_dir + tc_name + "_hostapd_" + host.name + "_" + host.ifname + ".log"
+ host.execute(["rm", log_file])
+ log = " -f " + log_file
+ except:
+ log = ""
+
+ if log_file:
+ host.add_log(log_file)
+ status, buf = host.execute([setup_params['hostapd'], "-B", "-ddt", "-g", "udp:" + host.port, log])
+ if status != 0:
+ raise Exception("Could not run hostapd: " + buf)
+
+def run_wpasupplicant(host, setup_params):
+ log_file = None
+ try:
+ tc_name = setup_params['tc_name']
+ log_dir = setup_params['log_dir']
+ log_file = log_dir + tc_name + "_wpa_supplicant_" + host.name + "_" + host.ifname + ".log"
+ host.execute(["rm", log_file])
+ log = " -f " + log_file
+ except:
+ log = ""
+
+ if log_file:
+ host.add_log(log_file)
+ status, buf = host.execute([setup_params['wpa_supplicant'], "-B", "-ddt", "-g", "udp:" + host.port, log])
+ if status != 0:
+ raise Exception("Could not run wpa_supplicant: " + buf)
+
+def get_ap_params(channel="1", bw="HT20", country="US", security="open", ht_capab=None, vht_capab=None):
+ ssid = "test_" + channel + "_" + security + "_" + bw
+
+ if bw == "b_only":
+ params = hostapd.b_only_params(channel, ssid, country)
+ elif bw == "g_only":
+ params = hostapd.g_only_params(channel, ssid, country)
+ elif bw == "g_only_wmm":
+ params = hostapd.g_only_params(channel, ssid, country)
+ params['wmm_enabled'] = "1"
+ elif bw == "a_only":
+ params = hostapd.a_only_params(channel, ssid, country)
+ elif bw == "a_only_wmm":
+ params = hostapd.a_only_params(channel, ssid, country)
+ params['wmm_enabled'] = "1"
+ elif bw == "HT20":
+ params = hostapd.ht20_params(channel, ssid, country)
+ if ht_capab:
+ try:
+ params['ht_capab'] = params['ht_capab'] + ht_capab
+ except:
+ params['ht_capab'] = ht_capab
+ elif bw == "HT40+":
+ params = hostapd.ht40_plus_params(channel, ssid, country)
+ if ht_capab:
+ params['ht_capab'] = params['ht_capab'] + ht_capab
+ elif bw == "HT40-":
+ params = hostapd.ht40_minus_params(channel, ssid, country)
+ if ht_capab:
+ params['ht_capab'] = params['ht_capab'] + ht_capab
+ elif bw == "VHT80":
+ params = hostapd.ht40_plus_params(channel, ssid, country)
+ if ht_capab:
+ params['ht_capab'] = params['ht_capab'] + ht_capab
+ if vht_capab:
+ try:
+ params['vht_capab'] = params['vht_capab'] + vht_capab
+ except:
+ params['vht_capab'] = vht_capab
+ params['ieee80211ac'] = "1"
+ params['vht_oper_chwidth'] = "1"
+ params['vht_oper_centr_freq_seg0_idx'] = str(int(channel) + 6)
+ else:
+ params = {}
+
+ # now setup security params
+ if security == "tkip":
+ sec_params = hostapd.wpa_params(passphrase="testtest")
+ elif security == "ccmp":
+ sec_params = hostapd.wpa2_params(passphrase="testtest")
+ elif security == "mixed":
+ sec_params = hostapd.wpa_mixed_params(passphrase="testtest")
+ elif security == "wep":
+ sec_params = { "wep_key0" : "123456789a",
+ "wep_default_key" : "0",
+ "auth_algs" : "1"}
+ elif security == "wep_shared":
+ sec_params = { "wep_key0" : "123456789a",
+ "wep_default_key" : "0",
+ "auth_algs" : "2" }
+ else:
+ sec_params = {}
+
+ params.update(sec_params)
+
+ return params
+
+# ip helpers
+def get_ipv4(client, ifname=None):
+ if ifname is None:
+ ifname = client.ifname
+ status, buf = client.execute(["ifconfig", ifname])
+ lines = buf.splitlines()
+
+ for line in lines:
+ res = line.find("inet addr:")
+ if res != -1:
+ break
+
+ if res != -1:
+ words = line.split()
+ addr = words[1].split(":")
+ return addr[1]
+
+ return "unknown"
+
+def get_ipv6(client, ifname=None):
+ res = -1
+ if ifname is None:
+ ifname = client.ifname
+ status, buf = client.execute(["ifconfig", ifname])
+ lines = buf.splitlines()
+
+ for line in lines:
+ res = line.find("Scope:Link")
+ if res != -1:
+ break
+
+ if res != -1:
+ words = line.split()
+ if words[0] == "inet6" and words[1] == "addr:":
+ addr_mask = words[2]
+ addr = addr_mask.split("/")
+ return addr[0]
+
+ return "unknown"
+
+def get_ip(client, addr_type="ipv6", iface=None):
+ if addr_type == "ipv6":
+ return get_ipv6(client, iface)
+ elif addr_type == "ipv4":
+ return get_ipv4(client, iface)
+ else:
+ return "unknown addr_type: " + addr_type
+
+def get_ipv4_addr(setup_params, number):
+ try:
+ ipv4_base = setup_params['ipv4_test_net']
+ except:
+ ipv4_base = "172.16.12.0"
+
+ parts = ipv4_base.split('.')
+ ipv4 = parts[0] + "." + parts[1] + "." + parts[2] + "." + str(number)
+
+ return ipv4
+
+def get_mac_addr(host, iface=None):
+ if iface == None:
+ iface = host.ifname
+ status, buf = host.execute(["ifconfig", iface])
+ if status != 0:
+ raise Exception("ifconfig " + iface)
+ words = buf.split()
+ found = 0
+ for word in words:
+ if found == 1:
+ return word
+ if word == "HWaddr":
+ found = 1
+ raise Exception("Could not find HWaddr")
+
+# connectivity/ping helpers
+def get_ping_packet_loss(ping_res):
+ loss_line = ""
+ lines = ping_res.splitlines()
+ for line in lines:
+ if line.find("packet loss") != -1:
+ loss_line = line
+ break;
+
+ if loss_line == "":
+ return "100%"
+
+ sections = loss_line.split(",")
+
+ for section in sections:
+ if section.find("packet loss") != -1:
+ words = section.split()
+ return words[0]
+
+ return "100%"
+
+def ac_to_ping_ac(qos):
+ if qos == "be":
+ qos_param = "0x00"
+ elif qos == "bk":
+ qos_param = "0x20"
+ elif qos == "vi":
+ qos_param = "0xA0"
+ elif qos == "vo":
+ qos_param = "0xE0"
+ else:
+ qos_param = "0x00"
+ return qos_param
+
+def ping_run(host, ip, result, ifname=None, addr_type="ipv4", deadline="5", qos=None):
+ if ifname is None:
+ ifname = host.ifname
+ if addr_type == "ipv6":
+ ping = ["ping6"]
+ else:
+ ping = ["ping"]
+
+ ping = ping + ["-w", deadline, "-I", ifname]
+ if qos:
+ ping = ping + ["-Q", ac_to_ping_ac(qos)]
+ ping = ping + [ip]
+
+ flush_arp_cache(host)
+
+ thread = host.execute_run(ping, result)
+ return thread
+
+def ping_wait(host, thread, timeout=None):
+ host.wait_execute_complete(thread, timeout)
+ if thread.isAlive():
+ raise Exception("ping thread still alive")
+
+def flush_arp_cache(host):
+ host.execute(["ip", "-s", "-s", "neigh", "flush", "all"])
+
+def check_connectivity(a, b, addr_type = "ipv4", deadline="5", qos=None):
+ addr_a = get_ip(a, addr_type)
+ addr_b = get_ip(b, addr_type)
+
+ if addr_type == "ipv4":
+ ping = ["ping"]
+ else:
+ ping = ["ping6"]
+
+ ping_a_b = ping + ["-w", deadline, "-I", a.ifname]
+ ping_b_a = ping + ["-w", deadline, "-I", b.ifname]
+ if qos:
+ ping_a_b = ping_a_b + ["-Q", ac_to_ping_ac(qos)]
+ ping_b_a = ping_b_a + ["-Q", ac_to_ping_ac(qos)]
+ ping_a_b = ping_a_b + [addr_b]
+ ping_b_a = ping_b_a + [addr_a]
+
+ # Clear arp cache
+ flush_arp_cache(a)
+ flush_arp_cache(b)
+
+ status, buf = a.execute(ping_a_b)
+ if status == 2 and ping == "ping6":
+ # tentative possible for a while, try again
+ time.sleep(3)
+ status, buf = a.execute(ping_a_b)
+ if status != 0:
+ raise Exception("ping " + a.name + "/" + a.ifname + " >> " + b.name + "/" + b.ifname)
+
+ a_b = get_ping_packet_loss(buf)
+
+ # Clear arp cache
+ flush_arp_cache(a)
+ flush_arp_cache(b)
+
+ status, buf = b.execute(ping_b_a)
+ if status != 0:
+ raise Exception("ping " + b.name + "/" + b.ifname + " >> " + a.name + "/" + a.ifname)
+
+ b_a = get_ping_packet_loss(buf)
+
+ if int(a_b[:-1]) > 40:
+ raise Exception("Too high packet lost: " + a_b)
+
+ if int(b_a[:-1]) > 40:
+ raise Exception("Too high packet lost: " + b_a)
+
+ return a_b, b_a
+
+
+# iperf helpers
+def get_iperf_speed(iperf_res, pattern="Mbits/sec"):
+ lines = iperf_res.splitlines()
+ sum_line = ""
+ last_line = ""
+ count = 0
+ res = -1
+
+ # first find last SUM line
+ for line in lines:
+ res = line.find("[SUM]")
+ if res != -1:
+ sum_line = line
+
+ # next check SUM status
+ if sum_line != "":
+ words = sum_line.split()
+ for word in words:
+ res = word.find(pattern)
+ if res != -1:
+ return words[count - 1] + " " + pattern
+ count = count + 1
+
+ # no SUM - one thread - find last line
+ for line in lines:
+ res = line.find(pattern)
+ if res != -1:
+ last_line = line
+
+ if last_line == "":
+ return "0 " + pattern
+
+ count = 0
+ words = last_line.split()
+ for word in words:
+ res = word.find(pattern)
+ if res != -1:
+ return words[count - 1] + " " + pattern
+ break;
+ count = count + 1
+ return "0 " + pattern
+
+def ac_to_iperf_ac(qos):
+ if qos == "be":
+ qos_param = "0x00"
+ elif qos == "bk":
+ qos_param = "0x20"
+ elif qos == "vi":
+ qos_param = "0xA0"
+ elif qos == "vo":
+ qos_param = "0xE0"
+ else:
+ qos_param = "0x00"
+ return qos_param
+
+def iperf_run(server, client, server_ip, client_res, server_res,
+ l4="udp", bw="30M", test_time="30", parallel="5",
+ qos="be", param=" -i 5 ", ifname=None, l3="ipv4",
+ port="5001", iperf="iperf"):
+ if ifname == None:
+ ifname = client.ifname
+
+ if iperf == "iperf":
+ iperf_server = [iperf]
+ elif iperf == "iperf3":
+ iperf_server = [iperf, "-1"]
+
+ if l3 == "ipv4":
+ iperf_client = [iperf, "-c", server_ip, "-p", port]
+ iperf_server = iperf_server + ["-p", port]
+ elif l3 == "ipv6":
+ iperf_client = [iperf, "-V", "-c", server_ip + "%" + ifname, "-p", port]
+ iperf_server = iperf_server + ["-V", "-p", port]
+ else:
+ return -1, -1
+
+ iperf_server = iperf_server + ["-s", "-f", "m", param]
+ iperf_client = iperf_client + ["-f", "m", "-t", test_time]
+
+ if parallel != "1":
+ iperf_client = iperf_client + ["-P", parallel]
+
+ if l4 == "udp":
+ if iperf != "iperf3":
+ iperf_server = iperf_server + ["-u"]
+ iperf_client = iperf_client + ["-u", "-b", bw]
+
+ if qos:
+ iperf_client = iperf_client + ["-Q", ac_to_iperf_ac(qos)]
+
+ flush_arp_cache(server)
+ flush_arp_cache(client)
+
+ server_thread = server.execute_run(iperf_server, server_res)
+ time.sleep(1)
+ client_thread = client.execute_run(iperf_client, client_res)
+
+ return server_thread, client_thread
+
+def iperf_wait(server, client, server_thread, client_thread, timeout=None, iperf="iperf"):
+ client.wait_execute_complete(client_thread, timeout)
+ if client_thread.isAlive():
+ raise Exception("iperf client thread still alive")
+
+ server.wait_execute_complete(server_thread, 5)
+ if server_thread.isAlive():
+ server.execute(["killall", "-s", "INT", iperf])
+ time.sleep(1)
+
+ server.wait_execute_complete(server_thread, 5)
+ if server_thread.isAlive():
+ raise Execption("iperf server thread still alive")
+
+ return
+
+def run_tp_test(server, client, l3="ipv4", iperf="iperf", l4="tcp", test_time="10", parallel="5",
+ qos="be", bw="30M", ifname=None, port="5001"):
+ client_res = []
+ server_res = []
+
+ server_ip = get_ip(server, l3)
+ time.sleep(1)
+ server_thread, client_thread = iperf_run(server, client, server_ip, client_res, server_res,
+ l3=l3, iperf=iperf, l4=l4, test_time=test_time,
+ parallel=parallel, qos=qos, bw=bw, ifname=ifname,
+ port=port)
+ iperf_wait(server, client, server_thread, client_thread, iperf=iperf, timeout=int(test_time) + 10)
+
+ if client_res[0] != 0:
+ raise Exception(iperf + " client: " + client_res[1])
+ if server_res[0] != 0:
+ raise Exception(iperf + " server: " + server_res[1])
+ if client_res[1] is None:
+ raise Exception(iperf + " client result issue")
+ if server_res[1] is None:
+ raise Exception(iperf + " server result issue")
+
+ if iperf == "iperf":
+ result = server_res[1]
+ if iperf == "iperf3":
+ result = client_res[1]
+
+ speed = get_iperf_speed(result)
+ return speed
+
+def get_iperf_bw(bw, parallel, spacial_streams=2):
+ if bw == "b_only":
+ max_tp = 11
+ elif bw == "g_only" or bw == "g_only_wmm" or bw == "a_only" or bw == "a_only_wmm":
+ max_tp = 54
+ elif bw == "HT20":
+ max_tp = 72 * spacial_streams
+ elif bw == "HT40+" or bw == "HT40-":
+ max_tp = 150 * spacial_streams
+ elif bw == "VHT80":
+ max_tp = 433 * spacial_streams
+ else:
+ max_tp = 150
+
+ max_tp = 1.2 * max_tp
+
+ return str(int(max_tp/int(parallel))) + "M"
--- /dev/null
+#!/usr/bin/env python2
+#
+# Show/check devices
+# Copyright (c) 2016, Tieto Corporation
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+
+import time
+import traceback
+import config
+import os
+import sys
+import getopt
+import re
+
+import logging
+logger = logging.getLogger()
+
+import rutils
+from remotehost import Host
+from wpasupplicant import WpaSupplicant
+import hostapd
+
+def show_devices(devices, setup_params):
+ """Show/check available devices"""
+ print "Devices:"
+ for device in devices:
+ host = rutils.get_host(devices, device['name'])
+ # simple check if authorized_keys works correctly
+ status, buf = host.execute(["id"])
+ if status != 0:
+ print "[" + host.name + "] - ssh communication: FAILED"
+ continue
+ else:
+ print "[" + host.name + "] - ssh communication: OK"
+ # check setup_hw works correctly
+ rutils.setup_hw_host(host, setup_params)
+
+ # show uname
+ status, buf = host.execute(["uname", "-s", "-n", "-r", "-m", "-o"])
+ print "\t" + buf
+ # show ifconfig
+ ifaces = re.split('; | |, ', host.ifname)
+ for iface in ifaces:
+ status, buf = host.execute(["ifconfig", iface])
+ if status != 0:
+ print "\t" + iface + " failed\n"
+ continue
+ lines = buf.splitlines()
+ for line in lines:
+ print "\t" + line
+ # check hostapd, wpa_supplicant, iperf exist
+ status, buf = host.execute([setup_params['wpa_supplicant'], "-v"])
+ if status != 0:
+ print "\t" + setup_params['wpa_supplicant'] + " not find\n"
+ continue
+ lines = buf.splitlines()
+ for line in lines:
+ print "\t" + line
+ print ""
+ status, buf = host.execute([setup_params['hostapd'], "-v"])
+ if status != 1:
+ print "\t" + setup_params['hostapd'] + " not find\n"
+ continue
+ lines = buf.splitlines()
+ for line in lines:
+ print "\t" + line
+ print ""
+ status, buf = host.execute([setup_params['iperf'], "-v"])
+ if status != 0 and status != 1:
+ print "\t" + setup_params['iperf'] + " not find\n"
+ continue
+ lines = buf.splitlines()
+ for line in lines:
+ print "\t" + line
+ print ""
+
+def check_device(devices, setup_params, dev_name, monitor=False):
+ host = rutils.get_host(devices, dev_name)
+ # simple check if authorized_keys works correctly
+ status, buf = host.execute(["id"])
+ if status != 0:
+ raise Exception(dev_name + " - ssh communication FAILED: " + buf)
+
+ rutils.setup_hw_host(host, setup_params)
+
+ ifaces = re.split('; | |, ', host.ifname)
+ # check interfaces (multi for monitor)
+ for iface in ifaces:
+ status, buf = host.execute(["ifconfig", iface])
+ if status != 0:
+ raise Exception(dev_name + " ifconfig " + iface + " failed: " + buf)
+
+ # monitor doesn't need wpa_supplicant/hostapd ...
+ if monitor == True:
+ return
+
+ status, buf = host.execute(["ls", "-l", setup_params['wpa_supplicant']])
+ if status != 0:
+ raise Exception(dev_name + " - wpa_supplicant: " + buf)
+
+ status, buf = host.execute(["ls", "-l", setup_params['hostapd']])
+ if status != 0:
+ raise Exception(dev_name + " - hostapd: " + buf)
+
+ status, buf = host.execute(["which", setup_params['iperf']])
+ if status != 0:
+ raise Exception(dev_name + " - iperf: " + buf)
+
+ status, buf = host.execute(["which", "tshark"])
+ if status != 0:
+ logger.debug(dev_name + " - tshark: " + buf)
+
+def check_devices(devices, setup_params, refs, duts, monitors):
+ """Check duts/refs/monitors devices"""
+ for dut in duts:
+ check_device(devices, setup_params, dut)
+ for ref in refs:
+ check_device(devices, setup_params, ref)
+ for monitor in monitors:
+ if monitor == "all":
+ continue
+ check_device(devices, setup_params, monitor, monitor=True)
--- /dev/null
+# Example test case
+# Copyright (c) 2016, Tieto Corporation
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+
+import remotehost
+from wpasupplicant import WpaSupplicant
+import hostapd
+import config
+import rutils
+import monitor
+
+import logging
+logger = logging.getLogger()
+
+def test_example(devices, setup_params, refs, duts, monitors):
+ """TC example - simple connect and ping test"""
+ try:
+ sta = None
+ ap = None
+ hapd = None
+ wpas = None
+ mon = None
+
+ # get hosts based on name
+ sta = rutils.get_host(devices, duts[0])
+ ap = rutils.get_host(devices, refs[0])
+
+ # setup log dir
+ local_log_dir = setup_params['local_log_dir']
+
+ # setup hw before test
+ rutils.setup_hw([sta, ap], setup_params)
+
+ # run traces if requested
+ rutils.trace_start([sta], setup_params)
+
+ # run perf if requested
+ rutils.perf_start([sta], setup_params)
+
+ # run hostapd/wpa_supplicant
+ rutils.run_wpasupplicant(sta, setup_params)
+ rutils.run_hostapd(ap, setup_params)
+
+ # get ap_params
+ ap_params = rutils.get_ap_params(channel="1", bw="HT20", country="US",
+ security="open")
+
+ # Add monitors if requested
+ monitor_hosts = monitor.create(devices, setup_params, refs, duts,
+ monitors)
+ if len(monitor_hosts) > 0:
+ mon = monitor_hosts[0]
+ monitor.add(sta, monitors)
+ monitor.add(ap, monitors)
+
+ # connect to hostapd/wpa_supplicant UDP CTRL iface
+ hapd = hostapd.add_ap(ap.dev, ap_params)
+ freq = hapd.get_status_field("freq")
+ wpas = WpaSupplicant(hostname = sta.host, global_iface="udp",
+ global_port = sta.port)
+ wpas.interface_add(sta.ifname)
+
+ # setup standalone monitor based on hapd; could be multi interface
+ # monitor
+ monitor_param = monitor.get_monitor_params(hapd)
+ monitor.setup(mon, [monitor_param])
+
+ # run monitors
+ monitor.run(sta, setup_params)
+ monitor.run(ap, setup_params)
+ monitor.run(mon, setup_params)
+
+ # connect wpa_supplicant to hostapd
+ wpas.connect(ap_params['ssid'], key_mgmt="NONE", scan_freq=freq)
+
+ # run ping test
+ ap_sta, sta_ap = rutils.check_connectivity(ap, sta, "ipv6")
+
+ # remove/destroy monitors
+ monitor.remove(sta)
+ monitor.remove(ap)
+ monitor.destroy(devices, monitor_hosts)
+
+ # hostapd/wpa_supplicant cleanup
+ wpas.interface_remove(sta.ifname)
+ wpas.terminate()
+
+ hapd.close_ctrl()
+ hostapd.remove_bss(ap.dev)
+ hostapd.terminate(ap.dev)
+
+ # stop perf
+ rutils.perf_stop([sta], setup_params)
+
+ # stop traces
+ rutils.trace_stop([sta], setup_params)
+
+ # get wpa_supplicant/hostapd/tshark logs
+ sta.get_logs(local_log_dir)
+ ap.get_logs(local_log_dir)
+ if mon:
+ mon.get_logs(local_log_dir)
+
+ return "packet_loss: " + ap_sta + ", " + sta_ap
+ except:
+ rutils.perf_stop([sta], setup_params)
+ rutils.trace_stop([sta], setup_params)
+ if wpas:
+ try:
+ wpas.interface_remove(sta.ifname)
+ wpas.terminate()
+ except:
+ pass
+ if hapd:
+ try:
+ hapd.close_ctrl()
+ hostapd.remove_bss(ap.dev)
+ hostapd.terminate(ap.dev)
+ except:
+ pass
+ if mon:
+ monitor.destroy(devices, monitor_hosts)
+ mon.get_logs(local_log_dir)
+
+ if sta:
+ monitor.remove(sta)
+ dmesg = setup_params['log_dir'] + setup_params['tc_name'] + "_" + sta.name + "_" + sta.ifname + ".dmesg"
+ sta.execute(["dmesg", "-c", ">", dmesg])
+ sta.add_log(dmesg)
+ sta.get_logs(local_log_dir)
+ sta.execute(["ifconfig", sta.ifname, "down"])
+ if ap:
+ monitor.remove(ap)
+ dmesg = setup_params['log_dir'] + setup_params['tc_name'] + "_" + ap.name + "_" + ap.ifname + ".dmesg"
+ ap.execute(["dmesg", "-c", ">", dmesg])
+ ap.add_log(dmesg)
+ ap.get_logs(local_log_dir)
+ ap.execute(["ifconfig", ap.ifname, " down"])
+ raise
--- /dev/null
+BasedOnStyle: LLVM
+IndentWidth: 8
+UseTab: Always
+BreakBeforeBraces: Mozilla
+AllowShortIfStatementsOnASingleLine: false
+IndentCaseLabels: false
+AccessModifierOffset: -8
+AlignAfterOpenBracket: AlwaysBreak
+SortIncludes: false
--- /dev/null
+/*
+ * binder interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+
+#include "binder_manager.h"
+
+extern "C" {
+#include "binder.h"
+#include "binder_i.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "utils/includes.h"
+}
+
+void wpas_binder_sock_handler(int sock, void *eloop_ctx, void *sock_ctx)
+{
+ struct wpa_global *global = (wpa_global *)eloop_ctx;
+ struct wpas_binder_priv *priv = (wpas_binder_priv *)sock_ctx;
+
+ wpa_printf(
+ MSG_DEBUG, "Processing binder events on FD %d", priv->binder_fd);
+ android::IPCThreadState::self()->handlePolledCommands();
+}
+
+struct wpas_binder_priv *wpas_binder_init(struct wpa_global *global)
+{
+ struct wpas_binder_priv *priv;
+ wpa_supplicant_binder::BinderManager *binder_manager;
+
+ priv = (wpas_binder_priv *)os_zalloc(sizeof(*priv));
+ if (!priv)
+ return NULL;
+ priv->global = global;
+
+ android::ProcessState::self()->setThreadPoolMaxThreadCount(0);
+ android::IPCThreadState::self()->disableBackgroundScheduling(true);
+ android::IPCThreadState::self()->setupPolling(&priv->binder_fd);
+ wpa_printf(MSG_INFO, "Process binder events on FD %d", priv->binder_fd);
+ if (priv->binder_fd < 0)
+ goto err;
+ /* Look for read events from the binder socket in the eloop. */
+ if (eloop_register_read_sock(
+ priv->binder_fd, wpas_binder_sock_handler, global, priv) < 0)
+ goto err;
+
+ binder_manager = wpa_supplicant_binder::BinderManager::getInstance();
+ if (!binder_manager)
+ goto err;
+ binder_manager->registerBinderService(global);
+ /* We may not need to store this binder manager reference in the
+ * global data strucure because we've made it a singleton class. */
+ priv->binder_manager = (void *)binder_manager;
+
+ return priv;
+
+err:
+ wpas_binder_deinit(priv);
+ return NULL;
+}
+
+void wpas_binder_deinit(struct wpas_binder_priv *priv)
+{
+ if (!priv)
+ return;
+
+ wpa_supplicant_binder::BinderManager::destroyInstance();
+ eloop_unregister_read_sock(priv->binder_fd);
+ android::IPCThreadState::shutdown();
+}
+
+int wpas_binder_register_interface(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s->global->binder)
+ return 1;
+
+ wpa_supplicant_binder::BinderManager *binder_manager =
+ wpa_supplicant_binder::BinderManager::getInstance();
+ if (!binder_manager)
+ return 1;
+
+ return binder_manager->registerInterface(wpa_s);
+}
+
+int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s->global->binder)
+ return 1;
+
+ wpa_supplicant_binder::BinderManager *binder_manager =
+ wpa_supplicant_binder::BinderManager::getInstance();
+ if (!binder_manager)
+ return 1;
+
+ return binder_manager->unregisterInterface(wpa_s);
+}
--- /dev/null
+/*
+ * binder interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_BINDER_BINDER_H
+#define WPA_SUPPLICANT_BINDER_BINDER_H
+
+#ifdef _cplusplus
+extern "C" {
+#endif /* _cplusplus */
+
+/**
+ * This is the binder RPC interface entry point to the wpa_supplicant core.
+ * This initializes the binder driver & BinderManager instance and then forwards
+ * all the notifcations from the supplicant core to the BinderManager.
+ */
+struct wpas_binder_priv;
+struct wpa_global;
+
+struct wpas_binder_priv *wpas_binder_init(struct wpa_global *global);
+void wpas_binder_deinit(struct wpas_binder_priv *priv);
+
+#ifdef CONFIG_CTRL_IFACE_BINDER
+int wpas_binder_register_interface(struct wpa_supplicant *wpa_s);
+int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s);
+#else /* CONFIG_CTRL_IFACE_BINDER */
+static inline int wpas_binder_register_interface(struct wpa_supplicant *wpa_s)
+{
+ return 0;
+}
+static inline int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s)
+{
+ return 0;
+}
+#endif /* CONFIG_CTRL_IFACE_BINDER */
+
+#ifdef _cplusplus
+}
+#endif /* _cplusplus */
+
+#endif /* WPA_SUPPLICANT_BINDER_BINDER_H */
--- /dev/null
+/*
+ * binder interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "binder_constants.h"
+
+namespace wpa_supplicant_binder {
+namespace binder_constants {
+
+const char kServiceName[] = "wpa_supplicant";
+
+} /* namespace binder_constants */
+} /* namespace wpa_supplicant_binder */
--- /dev/null
+/*
+ * binder interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_BINDER_BINDER_CONSTANTS_H
+#define WPA_SUPPLICANT_BINDER_BINDER_CONSTANTS_H
+
+namespace wpa_supplicant_binder {
+namespace binder_constants {
+
+extern const char kServiceName[];
+
+} /* namespace binder_constants */
+} /* namespace wpa_supplicant_binder */
+
+#endif /* WPA_SUPPLICANT_BINDER_BINDER_CONSTANTS_H */
--- /dev/null
+/*
+ * binder interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef BINDER_I_H
+#define BINDER_I_H
+
+#ifdef _cplusplus
+extern "C" {
+#endif // _cplusplus
+
+struct wpas_binder_priv
+{
+ int binder_fd;
+ struct wpa_global *global;
+ void *binder_manager;
+};
+
+#ifdef _cplusplus
+}
+#endif /* _cplusplus */
+
+#endif /* BINDER_I_H */
--- /dev/null
+/*
+ * binder interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include <binder/IServiceManager.h>
+
+#include "binder_constants.h"
+#include "binder_manager.h"
+
+extern "C" {
+#include "utils/common.h"
+#include "utils/includes.h"
+}
+
+namespace wpa_supplicant_binder {
+
+BinderManager *BinderManager::instance_ = NULL;
+
+BinderManager *BinderManager::getInstance()
+{
+ if (!instance_)
+ instance_ = new BinderManager();
+ return instance_;
+}
+
+void BinderManager::destroyInstance()
+{
+ if (instance_)
+ delete instance_;
+ instance_ = NULL;
+}
+
+int BinderManager::registerBinderService(struct wpa_global *global)
+{
+ /* Create the main binder service object and register with
+ * system service manager. */
+ supplicant_object_ = new Supplicant(global);
+ android::String16 service_name(binder_constants::kServiceName);
+ android::defaultServiceManager()->addService(
+ service_name, android::IInterface::asBinder(supplicant_object_));
+ return 0;
+}
+
+int BinderManager::registerInterface(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s)
+ return 1;
+
+ /* Using the corresponding wpa_supplicant pointer as key to our
+ * object map. */
+ const void *iface_key = wpa_s;
+
+ /* Return failure if we already have an object for that iface_key. */
+ if (iface_object_map_.find(iface_key) != iface_object_map_.end())
+ return 1;
+
+ iface_object_map_[iface_key] = new Iface(wpa_s);
+ if (!iface_object_map_[iface_key].get())
+ return 1;
+
+ wpa_s->binder_object_key = iface_key;
+
+ return 0;
+}
+
+int BinderManager::unregisterInterface(struct wpa_supplicant *wpa_s)
+{
+ if (!wpa_s || !wpa_s->binder_object_key)
+ return 1;
+
+ const void *iface_key = wpa_s;
+ if (iface_object_map_.find(iface_key) == iface_object_map_.end())
+ return 1;
+
+ /* Delete the corresponding iface object from our map. */
+ iface_object_map_.erase(iface_key);
+ wpa_s->binder_object_key = NULL;
+ return 0;
+}
+
+int BinderManager::getIfaceBinderObjectByKey(
+ const void *iface_object_key,
+ android::sp<fi::w1::wpa_supplicant::IIface> *iface_object)
+{
+ if (!iface_object_key || !iface_object)
+ return 1;
+
+ if (iface_object_map_.find(iface_object_key) == iface_object_map_.end())
+ return 1;
+
+ *iface_object = iface_object_map_[iface_object_key];
+ return 0;
+}
+
+} /* namespace wpa_supplicant_binder */
--- /dev/null
+/*
+ * binder interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_BINDER_BINDER_MANAGER_H
+#define WPA_SUPPLICANT_BINDER_BINDER_MANAGER_H
+
+#include <map>
+#include <string>
+
+#include "iface.h"
+#include "supplicant.h"
+
+struct wpa_global;
+struct wpa_supplicant;
+
+namespace wpa_supplicant_binder {
+
+/**
+ * BinderManager is responsible for managing the lifetime of all
+ * binder objects created by wpa_supplicant. This is a singleton
+ * class which is created by the supplicant core and can be used
+ * to get references to the binder objects.
+ */
+class BinderManager
+{
+public:
+ static BinderManager *getInstance();
+ static void destroyInstance();
+ int registerBinderService(struct wpa_global *global);
+ int registerInterface(struct wpa_supplicant *wpa_s);
+ int unregisterInterface(struct wpa_supplicant *wpa_s);
+ int getIfaceBinderObjectByKey(
+ const void *iface_object_key,
+ android::sp<fi::w1::wpa_supplicant::IIface> *iface_object);
+
+private:
+ BinderManager() = default;
+ ~BinderManager() = default;
+
+ /* Singleton instance of this class. */
+ static BinderManager *instance_;
+ /* The main binder service object. */
+ android::sp<Supplicant> supplicant_object_;
+ /* Map of all the interface specific binder objects controlled by
+ * wpa_supplicant. This map is keyed in by the corresponding
+ * wpa_supplicant structure pointer. */
+ std::map<const void *, android::sp<Iface>> iface_object_map_;
+};
+
+} /* namespace wpa_supplicant_binder */
+
+#endif /* WPA_SUPPLICANT_BINDER_BINDER_MANAGER_H */
--- /dev/null
+/*
+ * binder interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+package fi.w1.wpa_supplicant;
+
+/**
+ * Interface exposed by wpa_supplicant for each network interface it controls.
+ */
+interface IIface {
+}
--- /dev/null
+/*
+ * WPA Supplicant - binder interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+package fi.w1.wpa_supplicant;
+
+import android.os.PersistableBundle;
+import fi.w1.wpa_supplicant.IIface;
+
+/**
+ * Interface exposed by the wpa_supplicant binder service registered
+ * with the service manager with name: fi.w1.wpa_supplicant.
+ */
+interface ISupplicant {
+ /* Error values returned by the service to RPC method calls. */
+ const int ERROR_INVALID_ARGS = 1;
+ const int ERROR_UNKNOWN = 2;
+ const int ERROR_IFACE_EXISTS = 3;
+ const int ERROR_IFACE_UNKNOWN = 4;
+
+ /**
+ * Registers a wireless interface in wpa_supplicant.
+ *
+ * @param args A dictionary with arguments used to add the interface to
+ * wpa_supplicant.
+ * The dictionary may contain the following entries:
+ * Ifname(String) Name of the network interface to control, e.g.,
+ * wlan0.
+ * BridgeIfname(String) Name of the bridge interface to control, e.g.,
+ * br0.
+ * Driver(String) Driver name which the interface uses, e.g., nl80211.
+ * ConfigFile(String) Configuration file path.
+ *
+ * @return Binder object representing the interface.
+ */
+ IIface CreateInterface(in PersistableBundle args);
+
+ /**
+ * Deregisters a wireless interface from wpa_supplicant.
+ *
+ * @param ifname Name of the network interface, e.g., wlan0
+ */
+ void RemoveInterface(in @utf8InCpp String ifname);
+
+ /**
+ * Gets a binder object for the interface corresponding to ifname
+ * which wpa_supplicant already controls.
+ *
+ * @param ifname Name of the network interface, e.g., wlan0
+ *
+ * @return Binder object representing the interface.
+ */
+ IIface GetInterface(in @utf8InCpp String ifname);
+}
--- /dev/null
+/*
+ * binder interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+package fi.w1.wpa_supplicant;
+
+import android.os.PersistableBundle;
+
+/**
+ * Callback Interface exposed by the wpa_supplicant service. Clients need
+ * to host an instance of this binder object and pass a reference of the object
+ * to wpa_supplicant via the registerCallbacksObject method.
+ */
+interface ISupplicantCallbacks {
+}
--- /dev/null
+/*
+ * binder interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "iface.h"
+
+namespace wpa_supplicant_binder {
+
+Iface::Iface(struct wpa_supplicant *wpa_s) : wpa_s_(wpa_s) {}
+
+} /* namespace wpa_supplicant_binder */
--- /dev/null
+/*
+ * binder interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_BINDER_IFACE_H
+#define WPA_SUPPLICANT_BINDER_IFACE_H
+
+#include "fi/w1/wpa_supplicant/BnIface.h"
+
+extern "C" {
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "../wpa_supplicant_i.h"
+}
+
+namespace wpa_supplicant_binder {
+
+/**
+ * Implementation of Iface binder object. Each unique binder
+ * object is used for control operations on a specific interface
+ * controlled by wpa_supplicant.
+ */
+class Iface : public fi::w1::wpa_supplicant::BnIface
+{
+public:
+ Iface(struct wpa_supplicant *wpa_s);
+ virtual ~Iface() = default;
+
+private:
+ /* Raw pointer to the structure maintained by the core for this
+ * interface. */
+ struct wpa_supplicant *wpa_s_;
+};
+
+} /* namespace wpa_supplicant_binder */
+
+#endif /* WPA_SUPPLICANT_BINDER_IFACE_H */
--- /dev/null
+/*
+ * binder interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "supplicant.h"
+#include "binder_manager.h"
+
+namespace wpa_supplicant_binder {
+
+Supplicant::Supplicant(struct wpa_global *global) : wpa_global_(global) {}
+
+android::binder::Status Supplicant::CreateInterface(
+ const android::os::PersistableBundle ¶ms,
+ android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return)
+{
+ android::String16 driver, ifname, confname, bridge_ifname;
+
+ /* Check if required Ifname argument is missing */
+ if (!params.getString(android::String16("Ifname"), &ifname))
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_INVALID_ARGS,
+ android::String8("Ifname missing in params."));
+ /* Retrieve the remaining params from the dictionary */
+ params.getString(android::String16("Driver"), &driver);
+ params.getString(android::String16("ConfigFile"), &confname);
+ params.getString(android::String16("BridgeIfname"), &bridge_ifname);
+
+ /*
+ * Try to get the wpa_supplicant record for this iface, return
+ * an error if we already control it.
+ */
+ if (wpa_supplicant_get_iface(
+ wpa_global_, android::String8(ifname).string()) != NULL)
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_IFACE_EXISTS,
+ android::String8("wpa_supplicant already controls this "
+ "interface."));
+
+ android::binder::Status status;
+ struct wpa_supplicant *wpa_s = NULL;
+ struct wpa_interface iface;
+
+ os_memset(&iface, 0, sizeof(iface));
+ iface.driver = os_strdup(android::String8(driver).string());
+ iface.ifname = os_strdup(android::String8(ifname).string());
+ iface.confname = os_strdup(android::String8(confname).string());
+ iface.bridge_ifname =
+ os_strdup(android::String8(bridge_ifname).string());
+ /* Otherwise, have wpa_supplicant attach to it. */
+ wpa_s = wpa_supplicant_add_iface(wpa_global_, &iface, NULL);
+ /* The supplicant core creates a corresponding binder object via
+ * BinderManager when |wpa_supplicant_add_iface| is called. */
+ if (!wpa_s || !wpa_s->binder_object_key) {
+ status = android::binder::Status::fromServiceSpecificError(
+ ERROR_UNKNOWN,
+ android::String8(
+ "wpa_supplicant couldn't grab this interface."));
+ } else {
+ BinderManager *binder_manager = BinderManager::getInstance();
+
+ if (!binder_manager ||
+ binder_manager->getIfaceBinderObjectByKey(
+ wpa_s->binder_object_key, aidl_return))
+ status =
+ android::binder::Status::fromServiceSpecificError(
+ ERROR_UNKNOWN,
+ android::String8("wpa_supplicant encountered a "
+ "binder error."));
+ else
+ status = android::binder::Status::ok();
+ }
+ os_free((void *)iface.driver);
+ os_free((void *)iface.ifname);
+ os_free((void *)iface.confname);
+ os_free((void *)iface.bridge_ifname);
+ return status;
+}
+
+android::binder::Status Supplicant::RemoveInterface(const std::string &ifname)
+{
+ struct wpa_supplicant *wpa_s;
+
+ wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str());
+ if (!wpa_s || !wpa_s->binder_object_key)
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_IFACE_UNKNOWN,
+ android::String8("wpa_supplicant does not control this "
+ "interface."));
+ if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0))
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_UNKNOWN,
+ android::String8(
+ "wpa_supplicant couldn't remove this interface."));
+ return android::binder::Status::ok();
+}
+
+android::binder::Status Supplicant::GetInterface(
+ const std::string &ifname,
+ android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return)
+{
+ struct wpa_supplicant *wpa_s;
+
+ wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str());
+ if (!wpa_s || !wpa_s->binder_object_key)
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_IFACE_UNKNOWN,
+ android::String8(
+ "wpa_supplicant does not control this interface."));
+
+ BinderManager *binder_manager = BinderManager::getInstance();
+ if (!binder_manager ||
+ binder_manager->getIfaceBinderObjectByKey(
+ wpa_s->binder_object_key, aidl_return))
+ return android::binder::Status::fromServiceSpecificError(
+ ERROR_UNKNOWN,
+ android::String8(
+ "wpa_supplicant encountered a binder error."));
+
+ return android::binder::Status::ok();
+}
+
+} /* namespace wpa_supplicant_binder */
--- /dev/null
+/*
+ * binder interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_BINDER_SUPPLICANT_H
+#define WPA_SUPPLICANT_BINDER_SUPPLICANT_H
+
+#include "fi/w1/wpa_supplicant/BnSupplicant.h"
+#include "fi/w1/wpa_supplicant/IIface.h"
+#include "fi/w1/wpa_supplicant/ISupplicantCallbacks.h"
+
+extern "C" {
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "../wpa_supplicant_i.h"
+}
+
+namespace wpa_supplicant_binder {
+
+/**
+ * Implementation of the supplicant binder object. This binder
+ * object is used core for global control operations on
+ * wpa_supplicant.
+ */
+class Supplicant : public fi::w1::wpa_supplicant::BnSupplicant
+{
+public:
+ Supplicant(struct wpa_global *global);
+ virtual ~Supplicant() = default;
+
+ android::binder::Status CreateInterface(
+ const android::os::PersistableBundle ¶ms,
+ android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return) override;
+ android::binder::Status
+ RemoveInterface(const std::string &ifname) override;
+ android::binder::Status GetInterface(
+ const std::string &ifname,
+ android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return) override;
+
+private:
+ /* Raw pointer to the global structure maintained by the core. */
+ struct wpa_global *wpa_global_;
+ /* All the callback objects registered by the clients. */
+ std::vector<android::sp<fi::w1::wpa_supplicant::ISupplicantCallbacks>>
+ callbacks_;
+};
+
+} /* namespace wpa_supplicant_binder */
+
+#endif /* WPA_SUPPLICANT_BINDER_SUPPLICANT_H */
--- /dev/null
+/*
+ * libwpa_test - Test program for libwpa_client.* library linking
+ * 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.
+ */
+
+#include "includes.h"
+
+#include "common/wpa_ctrl.h"
+
+int main(int argc, char *argv[])
+{
+ struct wpa_ctrl *ctrl;
+
+ ctrl = wpa_ctrl_open("foo");
+ if (!ctrl)
+ return -1;
+ if (wpa_ctrl_attach(ctrl) == 0)
+ wpa_ctrl_detach(ctrl);
+ if (wpa_ctrl_pending(ctrl)) {
+ char buf[10];
+ size_t len;
+
+ len = sizeof(buf);
+ wpa_ctrl_recv(ctrl, buf, &len);
+ }
+ wpa_ctrl_close(ctrl);
+
+ return 0;
+}
--- /dev/null
+/*
+ * wpa_supplicant - MBO
+ *
+ * Copyright(c) 2015 Intel Deutschland GmbH
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "common/ieee802_11_defs.h"
+#include "common/gas.h"
+#include "config.h"
+#include "wpa_supplicant_i.h"
+#include "driver_i.h"
+#include "bss.h"
+#include "scan.h"
+
+/* type + length + oui + oui type */
+#define MBO_IE_HEADER 6
+
+
+static int wpas_mbo_validate_non_pref_chan(u8 oper_class, u8 chan, u8 reason)
+{
+ if (reason > MBO_NON_PREF_CHAN_REASON_INT_INTERFERENCE)
+ return -1;
+
+ /* Only checking the validity of the channel and oper_class */
+ if (ieee80211_chan_to_freq(NULL, oper_class, chan) == -1)
+ return -1;
+
+ return 0;
+}
+
+
+const u8 * wpas_mbo_get_bss_attr(struct wpa_bss *bss, enum mbo_attr_id attr)
+{
+ const u8 *mbo, *end;
+
+ if (!bss)
+ return NULL;
+
+ mbo = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
+ if (!mbo)
+ return NULL;
+
+ end = mbo + 2 + mbo[1];
+ mbo += MBO_IE_HEADER;
+
+ return get_ie(mbo, end - mbo, attr);
+}
+
+
+static void wpas_mbo_non_pref_chan_attr_body(struct wpa_supplicant *wpa_s,
+ struct wpabuf *mbo,
+ u8 start, u8 end)
+{
+ u8 i;
+
+ wpabuf_put_u8(mbo, wpa_s->non_pref_chan[start].oper_class);
+
+ for (i = start; i < end; i++)
+ wpabuf_put_u8(mbo, wpa_s->non_pref_chan[i].chan);
+
+ wpabuf_put_u8(mbo, wpa_s->non_pref_chan[start].preference);
+ wpabuf_put_u8(mbo, wpa_s->non_pref_chan[start].reason);
+}
+
+
+static void wpas_mbo_non_pref_chan_attr(struct wpa_supplicant *wpa_s,
+ struct wpabuf *mbo, u8 start, u8 end)
+{
+ size_t size = end - start + 3;
+
+ if (size + 2 > wpabuf_tailroom(mbo))
+ return;
+
+ wpabuf_put_u8(mbo, MBO_ATTR_ID_NON_PREF_CHAN_REPORT);
+ wpabuf_put_u8(mbo, size); /* Length */
+
+ wpas_mbo_non_pref_chan_attr_body(wpa_s, mbo, start, end);
+}
+
+
+static void wpas_mbo_non_pref_chan_subelem_hdr(struct wpabuf *mbo, u8 len)
+{
+ wpabuf_put_u8(mbo, WLAN_EID_VENDOR_SPECIFIC);
+ wpabuf_put_u8(mbo, len); /* Length */
+ wpabuf_put_be24(mbo, OUI_WFA);
+ wpabuf_put_u8(mbo, MBO_ATTR_ID_NON_PREF_CHAN_REPORT);
+}
+
+
+static void wpas_mbo_non_pref_chan_subelement(struct wpa_supplicant *wpa_s,
+ struct wpabuf *mbo, u8 start,
+ u8 end)
+{
+ size_t size = end - start + 7;
+
+ if (size + 2 > wpabuf_tailroom(mbo))
+ return;
+
+ wpas_mbo_non_pref_chan_subelem_hdr(mbo, size);
+ wpas_mbo_non_pref_chan_attr_body(wpa_s, mbo, start, end);
+}
+
+
+static void wpas_mbo_non_pref_chan_attrs(struct wpa_supplicant *wpa_s,
+ struct wpabuf *mbo, int subelement)
+{
+ u8 i, start = 0;
+ struct wpa_mbo_non_pref_channel *start_pref;
+
+ if (!wpa_s->non_pref_chan || !wpa_s->non_pref_chan_num) {
+ if (subelement)
+ wpas_mbo_non_pref_chan_subelem_hdr(mbo, 4);
+ return;
+ }
+ start_pref = &wpa_s->non_pref_chan[0];
+
+ for (i = 1; i <= wpa_s->non_pref_chan_num; i++) {
+ struct wpa_mbo_non_pref_channel *non_pref = NULL;
+
+ if (i < wpa_s->non_pref_chan_num)
+ non_pref = &wpa_s->non_pref_chan[i];
+ if (!non_pref ||
+ non_pref->oper_class != start_pref->oper_class ||
+ non_pref->reason != start_pref->reason ||
+ non_pref->preference != start_pref->preference) {
+ if (subelement)
+ wpas_mbo_non_pref_chan_subelement(wpa_s, mbo,
+ start, i);
+ else
+ wpas_mbo_non_pref_chan_attr(wpa_s, mbo, start,
+ i);
+
+ if (!non_pref)
+ return;
+
+ start = i;
+ start_pref = non_pref;
+ }
+ }
+}
+
+
+int wpas_mbo_ie(struct wpa_supplicant *wpa_s, u8 *buf, size_t len)
+{
+ struct wpabuf *mbo;
+ int res;
+
+ if (len < MBO_IE_HEADER + 3 + 7)
+ return 0;
+
+ /* Leave room for the MBO IE header */
+ mbo = wpabuf_alloc(len - MBO_IE_HEADER);
+ if (!mbo)
+ return 0;
+
+ /* Add non-preferred channels attribute */
+ wpas_mbo_non_pref_chan_attrs(wpa_s, mbo, 0);
+
+ /*
+ * Send cellular capabilities attribute even if AP does not advertise
+ * cellular capabilities.
+ */
+ wpabuf_put_u8(mbo, MBO_ATTR_ID_CELL_DATA_CAPA);
+ wpabuf_put_u8(mbo, 1);
+ wpabuf_put_u8(mbo, wpa_s->conf->mbo_cell_capa);
+
+ res = mbo_add_ie(buf, len, wpabuf_head_u8(mbo), wpabuf_len(mbo));
+ if (!res)
+ wpa_printf(MSG_ERROR, "Failed to add MBO IE");
+
+ wpabuf_free(mbo);
+ return res;
+}
+
+
+static void wpas_mbo_send_wnm_notification(struct wpa_supplicant *wpa_s,
+ const u8 *data, size_t len)
+{
+ struct wpabuf *buf;
+ int res;
+
+ /*
+ * Send WNM-Notification Request frame only in case of a change in
+ * non-preferred channels list during association, if the AP supports
+ * MBO.
+ */
+ if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_bss ||
+ !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE))
+ return;
+
+ buf = wpabuf_alloc(4 + len);
+ if (!buf)
+ return;
+
+ wpabuf_put_u8(buf, WLAN_ACTION_WNM);
+ wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ);
+ wpa_s->mbo_wnm_token++;
+ if (wpa_s->mbo_wnm_token == 0)
+ wpa_s->mbo_wnm_token++;
+ wpabuf_put_u8(buf, wpa_s->mbo_wnm_token);
+ wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); /* Type */
+
+ wpabuf_put_data(buf, data, len);
+
+ res = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
+ wpa_s->own_addr, wpa_s->bssid,
+ wpabuf_head(buf), wpabuf_len(buf), 0);
+ if (res < 0)
+ wpa_printf(MSG_DEBUG,
+ "Failed to send WNM-Notification Request frame with non-preferred channel list");
+
+ wpabuf_free(buf);
+}
+
+
+static void wpas_mbo_non_pref_chan_changed(struct wpa_supplicant *wpa_s)
+{
+ struct wpabuf *buf;
+
+ buf = wpabuf_alloc(512);
+ if (!buf)
+ return;
+
+ wpas_mbo_non_pref_chan_attrs(wpa_s, buf, 1);
+ wpas_mbo_send_wnm_notification(wpa_s, wpabuf_head_u8(buf),
+ wpabuf_len(buf));
+ wpabuf_free(buf);
+}
+
+
+static int wpa_non_pref_chan_is_eq(struct wpa_mbo_non_pref_channel *a,
+ struct wpa_mbo_non_pref_channel *b)
+{
+ return a->oper_class == b->oper_class && a->chan == b->chan;
+}
+
+
+/*
+ * wpa_non_pref_chan_cmp - Compare two channels for sorting
+ *
+ * In MBO IE non-preferred channel subelement we can put many channels in an
+ * attribute if they are in the same operating class and have the same
+ * preference and reason. To make it easy for the functions that build
+ * the IE attributes and WNM Request subelements, save the channels sorted
+ * by their oper_class and reason.
+ */
+static int wpa_non_pref_chan_cmp(const void *_a, const void *_b)
+{
+ const struct wpa_mbo_non_pref_channel *a = _a, *b = _b;
+
+ if (a->oper_class != b->oper_class)
+ return a->oper_class - b->oper_class;
+ if (a->reason != b->reason)
+ return a->reason - b->reason;
+ return a->preference - b->preference;
+}
+
+
+int wpas_mbo_update_non_pref_chan(struct wpa_supplicant *wpa_s,
+ const char *non_pref_chan)
+{
+ char *cmd, *token, *context = NULL;
+ struct wpa_mbo_non_pref_channel *chans = NULL, *tmp_chans;
+ size_t num = 0, size = 0;
+ unsigned i;
+
+ wpa_printf(MSG_DEBUG, "MBO: Update non-preferred channels, non_pref_chan=%s",
+ non_pref_chan ? non_pref_chan : "N/A");
+
+ /*
+ * The shortest channel configuration is 10 characters - commas, 3
+ * colons, and 4 values that one of them (oper_class) is 2 digits or
+ * more.
+ */
+ if (!non_pref_chan || os_strlen(non_pref_chan) < 10)
+ goto update;
+
+ cmd = os_strdup(non_pref_chan);
+ if (!cmd)
+ return -1;
+
+ while ((token = str_token(cmd, " ", &context))) {
+ struct wpa_mbo_non_pref_channel *chan;
+ int ret;
+ unsigned int _oper_class;
+ unsigned int _chan;
+ unsigned int _preference;
+ unsigned int _reason;
+
+ if (num == size) {
+ size = size ? size * 2 : 1;
+ tmp_chans = os_realloc_array(chans, size,
+ sizeof(*chans));
+ if (!tmp_chans) {
+ wpa_printf(MSG_ERROR,
+ "Couldn't reallocate non_pref_chan");
+ goto fail;
+ }
+ chans = tmp_chans;
+ }
+
+ chan = &chans[num];
+
+ ret = sscanf(token, "%u:%u:%u:%u", &_oper_class,
+ &_chan, &_preference, &_reason);
+ if (ret != 4 ||
+ _oper_class > 255 || _chan > 255 ||
+ _preference > 255 || _reason > 65535 ) {
+ wpa_printf(MSG_ERROR, "Invalid non-pref chan input %s",
+ token);
+ goto fail;
+ }
+ chan->oper_class = _oper_class;
+ chan->chan = _chan;
+ chan->preference = _preference;
+ chan->reason = _reason;
+
+ if (wpas_mbo_validate_non_pref_chan(chan->oper_class,
+ chan->chan, chan->reason)) {
+ wpa_printf(MSG_ERROR,
+ "Invalid non_pref_chan: oper class %d chan %d reason %d",
+ chan->oper_class, chan->chan, chan->reason);
+ goto fail;
+ }
+
+ for (i = 0; i < num; i++)
+ if (wpa_non_pref_chan_is_eq(chan, &chans[i]))
+ break;
+ if (i != num) {
+ wpa_printf(MSG_ERROR,
+ "oper class %d chan %d is duplicated",
+ chan->oper_class, chan->chan);
+ goto fail;
+ }
+
+ num++;
+ }
+
+ os_free(cmd);
+
+ if (chans) {
+ qsort(chans, num, sizeof(struct wpa_mbo_non_pref_channel),
+ wpa_non_pref_chan_cmp);
+ }
+
+update:
+ os_free(wpa_s->non_pref_chan);
+ wpa_s->non_pref_chan = chans;
+ wpa_s->non_pref_chan_num = num;
+ wpas_mbo_non_pref_chan_changed(wpa_s);
+
+ return 0;
+
+fail:
+ os_free(chans);
+ os_free(cmd);
+ return -1;
+}
+
+
+void wpas_mbo_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ie)
+{
+ wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC);
+ wpabuf_put_u8(ie, 7);
+ wpabuf_put_be24(ie, OUI_WFA);
+ wpabuf_put_u8(ie, MBO_OUI_TYPE);
+
+ wpabuf_put_u8(ie, MBO_ATTR_ID_CELL_DATA_CAPA);
+ wpabuf_put_u8(ie, 1);
+ wpabuf_put_u8(ie, wpa_s->conf->mbo_cell_capa);
+}
+
+
+enum chan_allowed {
+ NOT_ALLOWED, ALLOWED
+};
+
+static enum chan_allowed allow_channel(struct hostapd_hw_modes *mode, u8 chan,
+ unsigned int *flags)
+{
+ int i;
+
+ for (i = 0; i < mode->num_channels; i++) {
+ if (mode->channels[i].chan == chan)
+ break;
+ }
+
+ if (i == mode->num_channels ||
+ (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED))
+ return NOT_ALLOWED;
+
+ if (flags)
+ *flags = mode->channels[i].flag;
+
+ return ALLOWED;
+}
+
+
+static int get_center_80mhz(struct hostapd_hw_modes *mode, u8 channel)
+{
+ u8 center_channels[] = {42, 58, 106, 122, 138, 155};
+ size_t i;
+
+ if (mode->mode != HOSTAPD_MODE_IEEE80211A)
+ return 0;
+
+ for (i = 0; i < ARRAY_SIZE(center_channels); i++) {
+ /*
+ * In 80 MHz, the bandwidth "spans" 12 channels (e.g., 36-48),
+ * so the center channel is 6 channels away from the start/end.
+ */
+ if (channel >= center_channels[i] - 6 &&
+ channel <= center_channels[i] + 6)
+ return center_channels[i];
+ }
+
+ return 0;
+}
+
+
+static enum chan_allowed verify_80mhz(struct hostapd_hw_modes *mode, u8 channel)
+{
+ u8 center_chan;
+ unsigned int i;
+
+ center_chan = get_center_80mhz(mode, channel);
+ if (!center_chan)
+ return NOT_ALLOWED;
+
+ /* check all the channels are available */
+ for (i = 0; i < 4; i++) {
+ unsigned int flags;
+ u8 adj_chan = center_chan - 6 + i * 4;
+
+ if (allow_channel(mode, adj_chan, &flags) == NOT_ALLOWED)
+ return NOT_ALLOWED;
+
+ if ((i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_70)) ||
+ (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_50)) ||
+ (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_30)) ||
+ (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_10)))
+ return NOT_ALLOWED;
+ }
+
+ return ALLOWED;
+}
+
+
+static int get_center_160mhz(struct hostapd_hw_modes *mode, u8 channel)
+{
+ u8 center_channels[] = { 50, 114 };
+ unsigned int i;
+
+ if (mode->mode != HOSTAPD_MODE_IEEE80211A)
+ return 0;
+
+ for (i = 0; i < ARRAY_SIZE(center_channels); i++) {
+ /*
+ * In 160 MHz, the bandwidth "spans" 28 channels (e.g., 36-64),
+ * so the center channel is 14 channels away from the start/end.
+ */
+ if (channel >= center_channels[i] - 14 &&
+ channel <= center_channels[i] + 14)
+ return center_channels[i];
+ }
+
+ return 0;
+}
+
+
+static enum chan_allowed verify_160mhz(struct hostapd_hw_modes *mode,
+ u8 channel)
+{
+ u8 center_chan;
+ unsigned int i;
+
+ center_chan = get_center_160mhz(mode, channel);
+ if (!center_chan)
+ return NOT_ALLOWED;
+
+ /* Check all the channels are available */
+ for (i = 0; i < 8; i++) {
+ unsigned int flags;
+ u8 adj_chan = center_chan - 14 + i * 4;
+
+ if (allow_channel(mode, adj_chan, &flags) == NOT_ALLOWED)
+ return NOT_ALLOWED;
+
+ if ((i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_150)) ||
+ (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_130)) ||
+ (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_110)) ||
+ (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_90)) ||
+ (i == 4 && !(flags & HOSTAPD_CHAN_VHT_90_70)) ||
+ (i == 5 && !(flags & HOSTAPD_CHAN_VHT_110_50)) ||
+ (i == 6 && !(flags & HOSTAPD_CHAN_VHT_130_30)) ||
+ (i == 7 && !(flags & HOSTAPD_CHAN_VHT_150_10)))
+ return NOT_ALLOWED;
+ }
+
+ return ALLOWED;
+}
+
+
+static enum chan_allowed verify_channel(struct hostapd_hw_modes *mode,
+ u8 channel, u8 bw)
+{
+ unsigned int flag = 0;
+ enum chan_allowed res, res2;
+
+ res2 = res = allow_channel(mode, channel, &flag);
+ if (bw == BW40MINUS) {
+ if (!(flag & HOSTAPD_CHAN_HT40MINUS))
+ return NOT_ALLOWED;
+ res2 = allow_channel(mode, channel - 4, NULL);
+ } else if (bw == BW40PLUS) {
+ if (!(flag & HOSTAPD_CHAN_HT40PLUS))
+ return NOT_ALLOWED;
+ res2 = allow_channel(mode, channel + 4, NULL);
+ } else if (bw == BW80) {
+ /*
+ * channel is a center channel and as such, not necessarily a
+ * valid 20 MHz channels. Override earlier allow_channel()
+ * result and use only the 80 MHz specific version.
+ */
+ res2 = res = verify_80mhz(mode, channel);
+ } else if (bw == BW160) {
+ /*
+ * channel is a center channel and as such, not necessarily a
+ * valid 20 MHz channels. Override earlier allow_channel()
+ * result and use only the 160 MHz specific version.
+ */
+ res2 = res = verify_160mhz(mode, channel);
+ } else if (bw == BW80P80) {
+ /*
+ * channel is a center channel and as such, not necessarily a
+ * valid 20 MHz channels. Override earlier allow_channel()
+ * result and use only the 80 MHz specific version.
+ */
+ res2 = res = verify_80mhz(mode, channel);
+ }
+
+ if (res == NOT_ALLOWED || res2 == NOT_ALLOWED)
+ return NOT_ALLOWED;
+
+ return ALLOWED;
+}
+
+
+static int wpas_op_class_supported(struct wpa_supplicant *wpa_s,
+ const struct oper_class_map *op_class)
+{
+ int chan;
+ size_t i;
+ struct hostapd_hw_modes *mode;
+ int found;
+
+ mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op_class->mode);
+ if (!mode)
+ return 0;
+
+ if (op_class->op_class == 128) {
+ u8 channels[] = { 42, 58, 106, 122, 138, 155 };
+
+ for (i = 0; i < ARRAY_SIZE(channels); i++) {
+ if (verify_channel(mode, channels[i], op_class->bw) ==
+ ALLOWED)
+ return 1;
+ }
+
+ return 0;
+ }
+
+ if (op_class->op_class == 129) {
+ /* Check if either 160 MHz channels is allowed */
+ return verify_channel(mode, 50, op_class->bw) == ALLOWED ||
+ verify_channel(mode, 114, op_class->bw) == ALLOWED;
+ }
+
+ if (op_class->op_class == 130) {
+ /* Need at least two non-contiguous 80 MHz segments */
+ found = 0;
+
+ if (verify_channel(mode, 42, op_class->bw) == ALLOWED ||
+ verify_channel(mode, 58, op_class->bw) == ALLOWED)
+ found++;
+ if (verify_channel(mode, 106, op_class->bw) == ALLOWED ||
+ verify_channel(mode, 122, op_class->bw) == ALLOWED ||
+ verify_channel(mode, 138, op_class->bw) == ALLOWED)
+ found++;
+ if (verify_channel(mode, 106, op_class->bw) == ALLOWED &&
+ verify_channel(mode, 138, op_class->bw) == ALLOWED)
+ found++;
+ if (verify_channel(mode, 155, op_class->bw) == ALLOWED)
+ found++;
+
+ if (found >= 2)
+ return 1;
+
+ return 0;
+ }
+
+ found = 0;
+ for (chan = op_class->min_chan; chan <= op_class->max_chan;
+ chan += op_class->inc) {
+ if (verify_channel(mode, chan, op_class->bw) == ALLOWED) {
+ found = 1;
+ break;
+ }
+ }
+
+ return found;
+}
+
+
+int wpas_mbo_supp_op_class_ie(struct wpa_supplicant *wpa_s, int freq, u8 *pos,
+ size_t len)
+{
+ struct wpabuf *buf;
+ u8 op, current, chan;
+ u8 *ie_len;
+ int res;
+
+ /*
+ * Assume 20 MHz channel for now.
+ * TODO: Use the secondary channel and VHT channel width that will be
+ * used after association.
+ */
+ if (ieee80211_freq_to_channel_ext(freq, 0, VHT_CHANWIDTH_USE_HT,
+ ¤t, &chan) == NUM_HOSTAPD_MODES)
+ return 0;
+
+ /*
+ * Need 3 bytes for EID, length, and current operating class, plus
+ * 1 byte for every other supported operating class.
+ */
+ buf = wpabuf_alloc(global_op_class_size + 3);
+ if (!buf)
+ return 0;
+
+ wpabuf_put_u8(buf, WLAN_EID_SUPPORTED_OPERATING_CLASSES);
+ /* Will set the length later, putting a placeholder */
+ ie_len = wpabuf_put(buf, 1);
+ wpabuf_put_u8(buf, current);
+
+ for (op = 0; global_op_class[op].op_class; op++) {
+ if (wpas_op_class_supported(wpa_s, &global_op_class[op]))
+ wpabuf_put_u8(buf, global_op_class[op].op_class);
+ }
+
+ *ie_len = wpabuf_len(buf) - 2;
+ if (*ie_len < 2 || wpabuf_len(buf) > len) {
+ wpa_printf(MSG_ERROR,
+ "Failed to add supported operating classes IE");
+ res = 0;
+ } else {
+ os_memcpy(pos, wpabuf_head(buf), wpabuf_len(buf));
+ res = wpabuf_len(buf);
+ wpa_hexdump_buf(MSG_DEBUG,
+ "MBO: Added supported operating classes IE",
+ buf);
+ }
+
+ wpabuf_free(buf);
+ return res;
+}
+
+
+void wpas_mbo_ie_trans_req(struct wpa_supplicant *wpa_s, const u8 *mbo_ie,
+ size_t len)
+{
+ const u8 *pos, *cell_pref = NULL, *reason = NULL;
+ u8 id, elen;
+ u16 disallowed_sec = 0;
+
+ if (len <= 4 || WPA_GET_BE24(mbo_ie) != OUI_WFA ||
+ mbo_ie[3] != MBO_OUI_TYPE)
+ return;
+
+ pos = mbo_ie + 4;
+ len -= 4;
+
+ while (len >= 2) {
+ id = *pos++;
+ elen = *pos++;
+ len -= 2;
+
+ if (elen > len)
+ goto fail;
+
+ switch (id) {
+ case MBO_ATTR_ID_CELL_DATA_PREF:
+ if (elen != 1)
+ goto fail;
+
+ if (wpa_s->conf->mbo_cell_capa ==
+ MBO_CELL_CAPA_AVAILABLE)
+ cell_pref = pos;
+ else
+ wpa_printf(MSG_DEBUG,
+ "MBO: Station does not support Cellular data connection");
+ break;
+ case MBO_ATTR_ID_TRANSITION_REASON:
+ if (elen != 1)
+ goto fail;
+
+ reason = pos;
+ break;
+ case MBO_ATTR_ID_ASSOC_RETRY_DELAY:
+ if (elen != 2)
+ goto fail;
+
+ if (wpa_s->wnm_mode &
+ WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED) {
+ wpa_printf(MSG_DEBUG,
+ "MBO: Unexpected association retry delay, BSS is terminating");
+ goto fail;
+ } else if (wpa_s->wnm_mode &
+ WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
+ disallowed_sec = WPA_GET_LE16(pos);
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "MBO: Association retry delay attribute not in disassoc imminent mode");
+ }
+
+ break;
+ case MBO_ATTR_ID_AP_CAPA_IND:
+ case MBO_ATTR_ID_NON_PREF_CHAN_REPORT:
+ case MBO_ATTR_ID_CELL_DATA_CAPA:
+ case MBO_ATTR_ID_ASSOC_DISALLOW:
+ case MBO_ATTR_ID_TRANSITION_REJECT_REASON:
+ wpa_printf(MSG_DEBUG,
+ "MBO: Attribute %d should not be included in BTM Request frame",
+ id);
+ break;
+ default:
+ wpa_printf(MSG_DEBUG, "MBO: Unknown attribute id %u",
+ id);
+ return;
+ }
+
+ pos += elen;
+ len -= elen;
+ }
+
+ if (cell_pref)
+ wpa_msg(wpa_s, MSG_INFO, MBO_CELL_PREFERENCE "preference=%u",
+ *cell_pref);
+
+ if (reason)
+ wpa_msg(wpa_s, MSG_INFO, MBO_TRANSITION_REASON "reason=%u",
+ *reason);
+
+ if (disallowed_sec && wpa_s->current_bss)
+ wpa_bss_tmp_disallow(wpa_s, wpa_s->current_bss->bssid,
+ disallowed_sec);
+
+ return;
+fail:
+ wpa_printf(MSG_DEBUG, "MBO IE parsing failed (id=%u len=%u left=%zu)",
+ id, elen, len);
+}
+
+
+size_t wpas_mbo_ie_bss_trans_reject(struct wpa_supplicant *wpa_s, u8 *pos,
+ size_t len,
+ enum mbo_transition_reject_reason reason)
+{
+ u8 reject_attr[3];
+
+ reject_attr[0] = MBO_ATTR_ID_TRANSITION_REJECT_REASON;
+ reject_attr[1] = 1;
+ reject_attr[2] = reason;
+
+ return mbo_add_ie(pos, len, reject_attr, sizeof(reject_attr));
+}
+
+
+void wpas_mbo_update_cell_capa(struct wpa_supplicant *wpa_s, u8 mbo_cell_capa)
+{
+ u8 cell_capa[7];
+
+ if (wpa_s->conf->mbo_cell_capa == mbo_cell_capa) {
+ wpa_printf(MSG_DEBUG,
+ "MBO: Cellular capability already set to %u",
+ mbo_cell_capa);
+ return;
+ }
+
+ wpa_s->conf->mbo_cell_capa = mbo_cell_capa;
+
+ cell_capa[0] = WLAN_EID_VENDOR_SPECIFIC;
+ cell_capa[1] = 5; /* Length */
+ WPA_PUT_BE24(cell_capa + 2, OUI_WFA);
+ cell_capa[5] = MBO_ATTR_ID_CELL_DATA_CAPA;
+ cell_capa[6] = mbo_cell_capa;
+
+ wpas_mbo_send_wnm_notification(wpa_s, cell_capa, 7);
+ wpa_supplicant_set_default_scan_ies(wpa_s);
+}
+
+
+struct wpabuf * mbo_build_anqp_buf(struct wpa_supplicant *wpa_s,
+ struct wpa_bss *bss)
+{
+ struct wpabuf *anqp_buf;
+ u8 *len_pos;
+
+ if (!wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE)) {
+ wpa_printf(MSG_INFO, "MBO: " MACSTR
+ " does not support MBO - cannot request MBO ANQP elements from it",
+ MAC2STR(bss->bssid));
+ return NULL;
+ }
+
+ anqp_buf = wpabuf_alloc(10);
+ if (!anqp_buf)
+ return NULL;
+
+ len_pos = gas_anqp_add_element(anqp_buf, ANQP_VENDOR_SPECIFIC);
+ wpabuf_put_be24(anqp_buf, OUI_WFA);
+ wpabuf_put_u8(anqp_buf, MBO_ANQP_OUI_TYPE);
+
+ wpabuf_put_u8(anqp_buf, MBO_ANQP_SUBTYPE_CELL_CONN_PREF);
+ gas_anqp_set_element_len(anqp_buf, len_pos);
+
+ return anqp_buf;
+}