aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Leffler <sam@FreeBSD.org>2006-03-07 05:26:33 +0000
committerSam Leffler <sam@FreeBSD.org>2006-03-07 05:26:33 +0000
commit4e0922e888407f6dd91546a040e26125317fcfd8 (patch)
tree0c0ff34569d807e7bceb062a6210ce68490a8764
parente00d94fa7cb16ece7a61c444a75fef8ff3926446 (diff)
downloadsrc-4e0922e888407f6dd91546a040e26125317fcfd8.tar.gz
src-4e0922e888407f6dd91546a040e26125317fcfd8.zip
Import of WPA supplicant 0.4.8
Notes
Notes: svn path=/vendor/wpa_supplicant/dist/; revision=156369
-rw-r--r--contrib/wpa_supplicant/ChangeLog294
-rw-r--r--contrib/wpa_supplicant/Makefile196
-rw-r--r--contrib/wpa_supplicant/README209
-rw-r--r--contrib/wpa_supplicant/aes.c555
-rw-r--r--contrib/wpa_supplicant/aes_wrap.c231
-rw-r--r--contrib/wpa_supplicant/aes_wrap.h41
-rw-r--r--contrib/wpa_supplicant/base64.c198
-rw-r--r--contrib/wpa_supplicant/base64.h23
-rw-r--r--contrib/wpa_supplicant/common.c73
-rw-r--r--contrib/wpa_supplicant/common.h88
-rw-r--r--contrib/wpa_supplicant/config.c1272
-rw-r--r--contrib/wpa_supplicant/config.h296
-rw-r--r--contrib/wpa_supplicant/config_file.c695
-rw-r--r--contrib/wpa_supplicant/config_ssid.h703
-rw-r--r--contrib/wpa_supplicant/config_types.h14
-rw-r--r--contrib/wpa_supplicant/crypto.c109
-rw-r--r--contrib/wpa_supplicant/crypto.h117
-rw-r--r--contrib/wpa_supplicant/crypto_gnutls.c163
-rw-r--r--contrib/wpa_supplicant/ctrl_iface.c1105
-rw-r--r--contrib/wpa_supplicant/ctrl_iface.h33
-rw-r--r--contrib/wpa_supplicant/defconfig32
-rw-r--r--contrib/wpa_supplicant/defs.h121
-rw-r--r--contrib/wpa_supplicant/doc/code_structure.doxygen264
-rw-r--r--contrib/wpa_supplicant/doc/ctrl_iface.doxygen409
-rw-r--r--contrib/wpa_supplicant/doc/docbook/Makefile25
-rw-r--r--contrib/wpa_supplicant/doc/docbook/wpa_background.884
-rw-r--r--contrib/wpa_supplicant/doc/docbook/wpa_background.sgml101
-rw-r--r--contrib/wpa_supplicant/doc/docbook/wpa_cli.8202
-rw-r--r--contrib/wpa_supplicant/doc/docbook/wpa_cli.sgml330
-rw-r--r--contrib/wpa_supplicant/doc/docbook/wpa_passphrase.839
-rw-r--r--contrib/wpa_supplicant/doc/docbook/wpa_passphrase.sgml72
-rw-r--r--contrib/wpa_supplicant/doc/docbook/wpa_supplicant.8544
-rw-r--r--contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.5230
-rw-r--r--contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml244
-rw-r--r--contrib/wpa_supplicant/doc/docbook/wpa_supplicant.sgml761
-rw-r--r--contrib/wpa_supplicant/doc/doxygen.fast243
-rw-r--r--contrib/wpa_supplicant/doc/doxygen.full230
-rw-r--r--contrib/wpa_supplicant/doc/driver_wrapper.doxygen180
-rw-r--r--contrib/wpa_supplicant/doc/eap.doxygen38
-rwxr-xr-xcontrib/wpa_supplicant/doc/kerneldoc2doxygen.pl129
-rw-r--r--contrib/wpa_supplicant/doc/mainpage.doxygen56
-rw-r--r--contrib/wpa_supplicant/doc/porting.doxygen121
-rw-r--r--contrib/wpa_supplicant/doc/testing_tools.doxygen288
-rw-r--r--contrib/wpa_supplicant/doc/wpa_supplicant.fig42
-rw-r--r--contrib/wpa_supplicant/driver.h281
-rw-r--r--contrib/wpa_supplicant/driver_hostap.h153
-rw-r--r--contrib/wpa_supplicant/driver_ndis.c137
-rw-r--r--contrib/wpa_supplicant/driver_ndis.h15
-rw-r--r--contrib/wpa_supplicant/driver_wired.c271
-rw-r--r--contrib/wpa_supplicant/drivers.c8
-rw-r--r--contrib/wpa_supplicant/eap.c705
-rw-r--r--contrib/wpa_supplicant/eap.h222
-rw-r--r--contrib/wpa_supplicant/eap_aka.c93
-rw-r--r--contrib/wpa_supplicant/eap_defs.h31
-rw-r--r--contrib/wpa_supplicant/eap_fast.c343
-rw-r--r--contrib/wpa_supplicant/eap_gtc.c51
-rw-r--r--contrib/wpa_supplicant/eap_i.h182
-rw-r--r--contrib/wpa_supplicant/eap_leap.c82
-rw-r--r--contrib/wpa_supplicant/eap_md5.c45
-rw-r--r--contrib/wpa_supplicant/eap_mschapv2.c251
-rw-r--r--contrib/wpa_supplicant/eap_otp.c28
-rw-r--r--contrib/wpa_supplicant/eap_pax.c510
-rw-r--r--contrib/wpa_supplicant/eap_pax_common.c152
-rw-r--r--contrib/wpa_supplicant/eap_pax_common.h84
-rw-r--r--contrib/wpa_supplicant/eap_peap.c99
-rw-r--r--contrib/wpa_supplicant/eap_psk.c262
-rw-r--r--contrib/wpa_supplicant/eap_psk_common.c57
-rw-r--r--contrib/wpa_supplicant/eap_psk_common.h92
-rw-r--r--contrib/wpa_supplicant/eap_sim.c88
-rw-r--r--contrib/wpa_supplicant/eap_sim_common.c78
-rw-r--r--contrib/wpa_supplicant/eap_sim_common.h35
-rw-r--r--contrib/wpa_supplicant/eap_testing.txt90
-rw-r--r--contrib/wpa_supplicant/eap_tls.c91
-rw-r--r--contrib/wpa_supplicant/eap_tls_common.c315
-rw-r--r--contrib/wpa_supplicant/eap_tls_common.h25
-rw-r--r--contrib/wpa_supplicant/eap_tlv.c28
-rw-r--r--contrib/wpa_supplicant/eap_tlv.h20
-rw-r--r--contrib/wpa_supplicant/eap_ttls.c115
-rw-r--r--contrib/wpa_supplicant/eap_ttls.h14
-rw-r--r--contrib/wpa_supplicant/eapol_sm.c520
-rw-r--r--contrib/wpa_supplicant/eapol_sm.h202
-rw-r--r--contrib/wpa_supplicant/eapol_test.c529
-rw-r--r--contrib/wpa_supplicant/eloop.c21
-rw-r--r--contrib/wpa_supplicant/eloop.h137
-rw-r--r--contrib/wpa_supplicant/events.c759
-rw-r--r--contrib/wpa_supplicant/examples/ieee8021x.conf13
-rw-r--r--contrib/wpa_supplicant/examples/plaintext.conf8
-rw-r--r--contrib/wpa_supplicant/examples/wep.conf11
-rw-r--r--contrib/wpa_supplicant/examples/wpa-psk-tkip.conf12
-rw-r--r--contrib/wpa_supplicant/examples/wpa2-eap-ccmp.conf15
-rw-r--r--contrib/wpa_supplicant/hostapd.h38
-rw-r--r--contrib/wpa_supplicant/l2_packet.h109
-rw-r--r--contrib/wpa_supplicant/main.c250
-rw-r--r--contrib/wpa_supplicant/md5.c146
-rw-r--r--contrib/wpa_supplicant/md5.h46
-rw-r--r--contrib/wpa_supplicant/ms_funcs.c200
-rw-r--r--contrib/wpa_supplicant/ms_funcs.h51
-rw-r--r--contrib/wpa_supplicant/openssl-tls-extensions.patch513
-rw-r--r--contrib/wpa_supplicant/pcsc_funcs.c47
-rw-r--r--contrib/wpa_supplicant/pcsc_funcs.h20
-rw-r--r--contrib/wpa_supplicant/preauth.c934
-rw-r--r--contrib/wpa_supplicant/preauth.h132
-rw-r--r--contrib/wpa_supplicant/preauth_test.c387
-rw-r--r--contrib/wpa_supplicant/radius.c219
-rw-r--r--contrib/wpa_supplicant/radius.h18
-rw-r--r--contrib/wpa_supplicant/radius_client.c845
-rw-r--r--contrib/wpa_supplicant/radius_client.h118
-rw-r--r--contrib/wpa_supplicant/rc4.c32
-rw-r--r--contrib/wpa_supplicant/rc4.h19
-rw-r--r--contrib/wpa_supplicant/sha1.c202
-rw-r--r--contrib/wpa_supplicant/sha1.h45
-rw-r--r--contrib/wpa_supplicant/tls.h317
-rw-r--r--contrib/wpa_supplicant/tls_gnutls.c792
-rw-r--r--contrib/wpa_supplicant/tls_none.c8
-rw-r--r--contrib/wpa_supplicant/tls_openssl.c1614
-rw-r--r--contrib/wpa_supplicant/tls_schannel.c738
-rw-r--r--contrib/wpa_supplicant/todo.txt43
-rw-r--r--contrib/wpa_supplicant/version.h2
-rw-r--r--contrib/wpa_supplicant/wpa.c2721
-rw-r--r--contrib/wpa_supplicant/wpa.h302
-rw-r--r--contrib/wpa_supplicant/wpa_cli.c589
-rw-r--r--contrib/wpa_supplicant/wpa_ctrl.c18
-rw-r--r--contrib/wpa_supplicant/wpa_ctrl.h172
-rw-r--r--contrib/wpa_supplicant/wpa_gui-qt4/eventhistory.ui125
-rw-r--r--contrib/wpa_supplicant/wpa_gui-qt4/eventhistory.ui.h41
-rw-r--r--contrib/wpa_supplicant/wpa_gui-qt4/main.cpp30
-rw-r--r--contrib/wpa_supplicant/wpa_gui-qt4/networkconfig.ui455
-rw-r--r--contrib/wpa_supplicant/wpa_gui-qt4/networkconfig.ui.h513
-rw-r--r--contrib/wpa_supplicant/wpa_gui-qt4/scanresults.ui179
-rw-r--r--contrib/wpa_supplicant/wpa_gui-qt4/scanresults.ui.h101
-rwxr-xr-xcontrib/wpa_supplicant/wpa_gui-qt4/setup-mingw-cross-compiling11
-rw-r--r--contrib/wpa_supplicant/wpa_gui-qt4/userdatarequest.ui163
-rw-r--r--contrib/wpa_supplicant/wpa_gui-qt4/userdatarequest.ui.h70
-rw-r--r--contrib/wpa_supplicant/wpa_gui-qt4/wpa_gui.pro41
-rw-r--r--contrib/wpa_supplicant/wpa_gui-qt4/wpagui.ui464
-rw-r--r--contrib/wpa_supplicant/wpa_gui-qt4/wpagui.ui.h651
-rw-r--r--contrib/wpa_supplicant/wpa_gui-qt4/wpamsg.h28
-rw-r--r--contrib/wpa_supplicant/wpa_gui/eventhistory.ui125
-rw-r--r--contrib/wpa_supplicant/wpa_gui/eventhistory.ui.h41
-rw-r--r--contrib/wpa_supplicant/wpa_gui/main.cpp30
-rw-r--r--contrib/wpa_supplicant/wpa_gui/networkconfig.ui455
-rw-r--r--contrib/wpa_supplicant/wpa_gui/networkconfig.ui.h513
-rw-r--r--contrib/wpa_supplicant/wpa_gui/scanresults.ui179
-rw-r--r--contrib/wpa_supplicant/wpa_gui/scanresults.ui.h101
-rw-r--r--contrib/wpa_supplicant/wpa_gui/userdatarequest.ui163
-rw-r--r--contrib/wpa_supplicant/wpa_gui/userdatarequest.ui.h70
-rw-r--r--contrib/wpa_supplicant/wpa_gui/wpa_gui.pro31
-rw-r--r--contrib/wpa_supplicant/wpa_gui/wpagui.ui464
-rw-r--r--contrib/wpa_supplicant/wpa_gui/wpagui.ui.h651
-rw-r--r--contrib/wpa_supplicant/wpa_gui/wpamsg.h27
-rw-r--r--contrib/wpa_supplicant/wpa_i.h197
-rw-r--r--contrib/wpa_supplicant/wpa_passphrase.c31
-rw-r--r--contrib/wpa_supplicant/wpa_supplicant.c2009
-rw-r--r--contrib/wpa_supplicant/wpa_supplicant.conf199
-rw-r--r--contrib/wpa_supplicant/wpa_supplicant.h235
-rw-r--r--contrib/wpa_supplicant/wpa_supplicant_i.h408
156 files changed, 32479 insertions, 6489 deletions
diff --git a/contrib/wpa_supplicant/ChangeLog b/contrib/wpa_supplicant/ChangeLog
index 09d5b6121551..4ed9e261dfb6 100644
--- a/contrib/wpa_supplicant/ChangeLog
+++ b/contrib/wpa_supplicant/ChangeLog
@@ -1,32 +1,294 @@
ChangeLog for wpa_supplicant
-2005-06-10 - v0.3.9
- * modified the EAP workaround that accepts EAP-Success with incorrect
- Identifier to be even less strict about verification in order to
- interoperate with some authentication servers
- * fixed RSN IE in 4-Way Handshake message 2/4 for the case where
- Authenticator rejects PMKSA caching attempt and the driver is not
- using assoc_info events
- * fixed a possible double free in EAP-TTLS fast-reauthentication when
- identity or password is entered through control interface
- * added -P<pid file> argument for wpa_supplicant to write the current
- process id into a file
- * driver_madwifi: fixed association in plaintext mode
- * driver_madwifi: added preliminary support for compiling against 'BSD'
- branch of madwifi CVS tree
- * added EAP workaround for PEAPv1 session resumption: allow outer,
+2006-02-08 - v0.4.8
+ * fixed PC/SC code to use correct length for GSM AUTH command buffer
+ and to not use pioRecvPci with SCardTransmit() calls; these were not
+ causing visible problems with pcsc-lite, but Windows Winscard.dll
+ refused the previously used parameters; this fixes EAP-SIM and
+ EAP-AKA authentication using SIM/USIM card under Windows
+ * added support for EAP-FAST key derivation using other ciphers than
+ RC4-128-SHA for authentication and AES128-SHA for provisioning
+ * fixed EAP-SIM and EAP-AKA pseudonym and fast re-authentication to
+ decrypt AT_ENCR_DATA attributes correctly
+ * added support for configuring CA certificate as DER file and as a
+ configuration blob
+ * fixed private key configuration as configuration blob and added
+ support for using PKCS#12 as a blob
+ * fixed cygwin build
+ * added support for loading trusted CA certificates from Windows
+ certificate store: ca_cert="cert_store://<name>", where <name> is
+ likely CA (Intermediate CA certificates) or ROOT (root certificates)
+ * fixed TLS library deinitialization after RSN pre-authentication not
+ to disable TLS library for normal authentication
+ * fixed PMKSA cache processing not to trigger deauthentication if the
+ current PMKSA cache entry is replaced with a valid new entry
+ * fixed PC/SC initialization for ap_scan != 1 modes (this fixes
+ EAP-SIM and EAP-AKA with real SIM/USIM card when using ap_scan=0 or
+ ap_scan=2)
+ * do not try to use USIM APDUs when initializing PC/SC for SIM card
+ access for a network that has not enabled EAP-AKA
+
+2005-11-20 - v0.4.7 (beginning of 0.4.x stable releases)
+ * l2_packet_pcap: fixed wired IEEE 802.1X authentication with libpcap
+ and WinPcap to receive frames sent to PAE group address
+ * disable EAP state machine when IEEE 802.1X authentication is not used
+ in order to get rid of bogus "EAP failed" messages
+ * fixed OpenSSL error reporting to go through all pending errors to
+ avoid confusing reports of old errors being reported at later point
+ during handshake
+ * fixed configuration file updating to not write empty variables
+ (e.g., proto or key_mgmt) that the file parser would not accept
+ * fixed ADD_NETWORK ctrl_iface command to use the same default values
+ for variables as empty network definitions read from config file
+ would get
+ * fixed EAP state machine to not discard EAP-Failure messages in many
+ cases (e.g., during TLS handshake)
+ * fixed a infinite loop in private key reading if the configured file
+ cannot be parsed successfully
+ * driver_madwifi: added support for madwifi-ng
+ * wpa_gui: do not display password/PSK field contents
+ * wpa_gui: added CA certificate configuration
+ * driver_ndis: fixed scan request in ap_scan=2 mode not to change SSID
+ * driver_ndis: include Beacon IEs in AssocInfo in order to notice if
+ the new AP is using different WPA/RSN IE
+ * use longer timeout for IEEE 802.11 association to avoid problems with
+ drivers that may take more than five second to associate
+
+2005-10-27 - v0.4.6
+ * allow fallback to WPA, if mixed WPA+WPA2 networks have mismatch in
+ RSN IE, but WPA IE would match with wpa_supplicant configuration
+ * added support for named configuration blobs in order to avoid having
+ to use file system for external files (e.g., certificates);
+ variables can be set to "blob://<blob name>" instead of file path to
+ use a named blob; supported fields: pac_file, client_cert,
+ private_key
+ * fixed RSN pre-authentication (it was broken in the clean up of WPA
+ state machine interface in v0.4.5)
+ * driver_madwifi: set IEEE80211_KEY_GROUP flag for group keys to make
+ sure the driver configures broadcast decryption correctly
+ * added ca_path (and ca_path2) configuration variables that can be used
+ to configure OpenSSL CA path, e.g., /etc/ssl/certs, for using the
+ system-wide trusted CA list
+ * added support for starting wpa_supplicant without a configuration
+ file (-C argument must be used to set ctrl_interface parameter for
+ this case; in addition, -p argument can be used to provide
+ driver_param; these new arguments can also be used with a
+ configuration to override the values from the configuration)
+ * added global control interface that can be optionally used for adding
+ and removing network interfaces dynamically (-g command line argument
+ for both wpa_supplicant and wpa_cli) without having to restart
+ wpa_supplicant process
+ * wpa_gui:
+ - try to save configuration whenever something is modified
+ - added WEP key configuration
+ - added possibility to edit the current network configuration
+ * driver_ndis: fixed driver polling not to increase frequency on each
+ received EAPOL frame due to incorrectly cancelled timeout
+ * added simple configuration file examples (in examples subdirectory)
+ * fixed driver_wext.c to filter wireless events based on ifindex to
+ avoid interfaces receiving events from other interfaces
+ * delay sending initial EAPOL-Start couple of seconds to speed up
+ authentication for the most common case of Authenticator starting
+ EAP authentication immediately after association
+
+2005-09-25 - v0.4.5
+ * added a workaround for clearing keys with ndiswrapper to allow
+ roaming from WPA enabled AP to plaintext one
+ * added docbook documentation (doc/docbook) that can be used to
+ generate, e.g., man pages
+ * l2_packet_linux: use socket type SOCK_DGRAM instead of SOCK_RAW for
+ PF_PACKET in order to prepare for network devices that do not use
+ Ethernet headers (e.g., network stack with native IEEE 802.11 frames)
+ * use receipt of EAPOL-Key frame as a lower layer success indication
+ for EAP state machine to allow recovery from dropped EAP-Success
+ frame
+ * cleaned up internal EAPOL frame processing by not including link
+ layer (Ethernet) header during WPA and EAPOL/EAP processing; this
+ header is added only when transmitted the frame; this makes it easier
+ to use wpa_supplicant on link layers that use different header than
+ Ethernet
+ * updated EAP-PSK to use draft 9 by default since this can now be
+ tested with hostapd; removed support for draft 3, including
+ server_nai configuration option from network blocks
+ * driver_wired: add PAE address to the multicast address list in order
+ to be able to receive EAPOL frames with drivers that do not include
+ these multicast addresses by default
+ * driver_wext: add support for WE-19
+ * added support for multiple configuration backends (CONFIG_BACKEND
+ option); currently, only 'file' is supported (i.e., the format used
+ in wpa_supplicant.conf)
+ * added support for updating configuration ('wpa_cli save_config');
+ this is disabled by default and can be enabled with global
+ update_config=1 variable in wpa_supplicant.conf; this allows wpa_cli
+ and wpa_gui to store the configuration changes in a permanent store
+ * added GET_NETWORK ctrl_iface command
+ (e.g., 'wpa_cli get_network 0 ssid')
+
+2005-08-21 - v0.4.4
+ * replaced OpenSSL patch for EAP-FAST support
+ (openssl-tls-extensions.patch) with a more generic and correct
+ patch (the new patch is not compatible with the previous one, so the
+ OpenSSL library will need to be patched with the new patch in order
+ to be able to build wpa_supplicant with EAP-FAST support)
+ * added support for using Windows certificate store (through CryptoAPI)
+ for client certificate and private key operations (EAP-TLS)
+ (see wpa_supplicant.conf for more information on how to configure
+ this with private_key)
+ * ported wpa_gui to Windows
+ * added Qt4 version of wpa_gui (wpa_gui-qt4 directory); this can be
+ built with the open source version of the Qt4 for Windows
+ * allow non-WPA modes (e.g., IEEE 802.1X with dynamic WEP) to be used
+ with drivers that do not support WPA
+ * ndis_events: fixed Windows 2000 support
+ * added support for enabling/disabling networks from the list of all
+ configured networks ('wpa_cli enable_network <network id>' and
+ 'wpa_cli disable_network <network id>')
+ * added support for adding and removing network from the current
+ configuration ('wpa_cli add_network' and 'wpa_cli remove_network
+ <network id>'); added networks are disabled by default and they can
+ be enabled with enable_network command once the configuration is done
+ for the new network; note: configuration file is not yet updated, so
+ these new networks are lost when wpa_supplicant is restarted
+ * added support for setting network configuration parameters through
+ the control interface, for example:
+ wpa_cli set_network 0 ssid "\"my network\""
+ * fixed parsing of strings that include both " and # within double
+ quoted area (e.g., "start"#end")
+ * added EAP workaround for PEAP session resumption: allow outer,
i.e., not tunneled, EAP-Success to terminate session since; this can
be disabled with eap_workaround=0
+ (this was allowed for PEAPv1 before, but now it is also allowed for
+ PEAPv0 since at least one RADIUS authentication server seems to be
+ doing this for PEAPv0, too)
+ * wpa_gui: added preliminary support for adding new networks to the
+ wpa_supplicant configuration (double click on the scan results to
+ open network configuration)
+
+2005-06-26 - v0.4.3
+ * removed interface for external EAPOL/EAP supplicant (e.g.,
+ Xsupplicant), (CONFIG_XSUPPLICANT_IFACE) since it is not required
+ anymore and is unlikely to be used by anyone
+ * driver_ndis: fixed WinPcap 3.0 support
+ * fixed build with CONFIG_DNET_PCAP=y on Linux
+ * l2_packet: moved different implementations into separate files
+ (l2_packet_*.c)
+
+2005-06-12 - v0.4.2
* driver_ipw: updated driver structures to match with ipw2200-1.0.4
(note: ipw2100-1.1.0 is likely to require an update to work with
this)
+ * added support for using ap_scan=2 mode with multiple network blocks;
+ wpa_supplicant will go through the networks one by one until the
+ driver reports a successful association; this uses the same order for
+ networks as scan_ssid=1 scans, i.e., the priority field is ignored
+ and the network block order in the file is used instead
+ * fixed a potential issue in RSN pre-authentication ending up using
+ freed memory if pre-authentication times out
+ * added support for matching alternative subject name extensions of the
+ authentication server certificate; new configuration variables
+ altsubject_match and altsubject_match2
+ * driver_ndis: added support for IEEE 802.1X authentication with wired
+ NDIS drivers
+ * added support for querying private key password (EAP-TLS) through the
+ control interface (wpa_cli/wpa_gui) if one is not included in the
+ configuration file
* driver_broadcom: fixed couple of memory leaks in scan result
processing
+ * EAP-PAX is now registered as EAP type 46
+ * fixed EAP-PAX MAC calculation
+ * fixed EAP-PAX CK and ICK key derivation
+ * added support for using password with EAP-PAX (as an alternative to
+ entering key with eappsk); SHA-1 hash of the password will be used as
+ the key in this case
+ * added support for arbitrary driver interface parameters through the
+ configuration file with a new driver_param field; this adds a new
+ driver_ops function set_param()
+ * added possibility to override l2_packet module with driver interface
+ API (new send_eapol handler); this can be used to implement driver
+ specific TX/RX functions for EAPOL frames
+ * fixed ctrl_interface_group processing for the case where gid is
+ entered as a number, not group name
+ * driver_test: added support for testing hostapd with wpa_supplicant
+ by using test driver interface without any kernel drivers or network
+ cards
+
+2005-05-22 - v0.4.1
+ * driver_madwifi: fixed WPA/WPA2 mode configuration to allow EAPOL
+ packets to be encrypted; this was apparently broken by the changed
+ ioctl order in v0.4.0
+ * driver_madwifi: added preliminary support for compiling against 'BSD'
+ branch of madwifi CVS tree
+ * added support for EAP-MSCHAPv2 password retries within the same EAP
+ authentication session
+ * added support for password changes with EAP-MSCHAPv2 (used when the
+ password has expired)
+ * added support for reading additional certificates from PKCS#12 files
+ and adding them to the certificate chain
+ * fixed association with IEEE 802.1X (no WPA) when dynamic WEP keys
+ were used
+ * fixed a possible double free in EAP-TTLS fast-reauthentication when
+ identity or password is entered through control interface
+ * display EAP Notification messages to user through control interface
+ with "CTRL-EVENT-EAP-NOTIFICATION" prefix
+ * added GUI version of wpa_cli, wpa_gui; this is not build
+ automatically with 'make'; use 'make wpa_gui' to build (this requires
+ Qt development tools)
+ * added 'disconnect' command to control interface for setting
+ wpa_supplicant in state where it will not associate before
+ 'reassociate' command has been used
+ * added support for selecting a network from the list of all configured
+ networks ('wpa_cli select_network <network id>'; this disabled all
+ other networks; to re-enable, 'wpa_cli select_network any')
+ * added support for getting scan results through control interface
+ * added EAP workaround for PEAPv1 session resumption: allow outer,
+ i.e., not tunneled, EAP-Success to terminate session since; this can
+ be disabled with eap_workaround=0
-2005-02-13 - v0.3.8
+2005-04-25 - v0.4.0 (beginning of 0.4.x development releases)
+ * added a new build time option, CONFIG_NO_STDOUT_DEBUG, that can be
+ used to reduce the size of the wpa_supplicant considerably if
+ debugging code is not needed
* fixed EAPOL-Key validation to drop packets with invalid Key Data
Length; such frames could have crashed wpa_supplicant due to buffer
overflow
+ * added support for wired authentication (IEEE 802.1X on wired
+ Ethernet); driver interface 'wired'
+ * obsoleted set_wpa() handler in the driver interface API (it can be
+ replaced by moving enable/disable functionality into init()/deinit())
+ (calls to set_wpa() are still present for backwards compatibility,
+ but they may be removed in the future)
+ * driver_madwifi: fixed association in plaintext mode
+ * modified the EAP workaround that accepts EAP-Success with incorrect
+ Identifier to be even less strict about verification in order to
+ interoperate with some authentication servers
+ * added support for sending TLS alerts
+ * added support for 'any' SSID wildcard; if ssid is not configured or
+ is set to an empty string, any SSID will be accepted for non-WPA AP
+ * added support for asking PIN (for SIM) from frontends (e.g.,
+ wpa_cli); if a PIN is needed, but not included in the configuration
+ file, a control interface request is sent and EAP processing is
+ delayed until the PIN is available
+ * added support for using external devices (e.g., a smartcard) for
+ private key operations in EAP-TLS (CONFIG_SMARTCARD=y in .config);
+ new wpa_supplicant.conf variables:
+ - global: opensc_engine_path, pkcs11_engine_path, pkcs11_module_path
+ - network: engine, engine_id, key_id
+ * added experimental support for EAP-PAX
+ * added monitor mode for wpa_cli (-a<path to a program to run>) that
+ allows external commands (e.g., shell scripts) to be run based on
+ wpa_supplicant events, e.g., when authentication has been completed
+ and data connection is ready; other related wpa_cli arguments:
+ -B (run in background), -P (write PID file); wpa_supplicant has a new
+ command line argument (-W) that can be used to make it wait until a
+ control interface command is received in order to avoid missing
+ events
+ * added support for opportunistic WPA2 PMKSA key caching (disabled by
+ default, can be enabled with proactive_key_caching=1)
+ * fixed RSN IE in 4-Way Handshake message 2/4 for the case where
+ Authenticator rejects PMKSA caching attempt and the driver is not
+ using assoc_info events
+ * added -P<pid file> argument for wpa_supplicant to write the current
+ process id into a file
2005-02-12 - v0.3.7 (beginning of 0.3.x stable releases)
* added new phase1 option parameter, include_tls_length=1, to force
diff --git a/contrib/wpa_supplicant/Makefile b/contrib/wpa_supplicant/Makefile
index fa912436c86e..d8fd3edda01c 100644
--- a/contrib/wpa_supplicant/Makefile
+++ b/contrib/wpa_supplicant/Makefile
@@ -7,7 +7,7 @@ CFLAGS = -MMD -O2 -Wall -g
endif
# Include directories for CVS version
-CFLAGS += -I../driver/modules -I../utils -I../hostapd
+CFLAGS += -I. -I../utils -I../hostapd
ALL=wpa_supplicant wpa_passphrase wpa_cli
@@ -37,7 +37,7 @@ install: all
OBJS = config.o \
eloop.o common.o md5.o \
- rc4.o sha1.o aes_wrap.o
+ rc4.o sha1.o
OBJS_p = wpa_passphrase.o sha1.o md5.o
OBJS_c = wpa_cli.o wpa_ctrl.o
@@ -47,9 +47,18 @@ ifdef CONFIG_EAPOL_TEST
CFLAGS += -Werror -DEAPOL_TEST
endif
+ifndef CONFIG_BACKEND
+CONFIG_BACKEND=file
+endif
+
+ifeq ($(CONFIG_BACKEND), file)
+OBJS += config_file.o base64.o
+CFLAGS += -DCONFIG_BACKEND_FILE
+endif
+
ifdef CONFIG_DRIVER_HOSTAP
CFLAGS += -DCONFIG_DRIVER_HOSTAP
-OBJS += driver_hostap.o
+OBJS_d += driver_hostap.o
CONFIG_WIRELESS_EXTENSION=y
endif
@@ -60,73 +69,88 @@ endif
ifdef CONFIG_DRIVER_PRISM54
CFLAGS += -DCONFIG_DRIVER_PRISM54
-OBJS += driver_prism54.o
+OBJS_d += driver_prism54.o
CONFIG_WIRELESS_EXTENSION=y
endif
ifdef CONFIG_DRIVER_HERMES
CFLAGS += -DCONFIG_DRIVER_HERMES
-OBJS += driver_hermes.o
+OBJS_d += driver_hermes.o
CONFIG_WIRELESS_EXTENSION=y
endif
ifdef CONFIG_DRIVER_MADWIFI
CFLAGS += -DCONFIG_DRIVER_MADWIFI
-OBJS += driver_madwifi.o
+OBJS_d += driver_madwifi.o
CONFIG_WIRELESS_EXTENSION=y
endif
ifdef CONFIG_DRIVER_ATMEL
CFLAGS += -DCONFIG_DRIVER_ATMEL
-OBJS += driver_atmel.o
+OBJS_d += driver_atmel.o
CONFIG_WIRELESS_EXTENSION=y
endif
ifdef CONFIG_DRIVER_NDISWRAPPER
CFLAGS += -DCONFIG_DRIVER_NDISWRAPPER
-OBJS += driver_ndiswrapper.o
+OBJS_d += driver_ndiswrapper.o
CONFIG_WIRELESS_EXTENSION=y
endif
ifdef CONFIG_DRIVER_BROADCOM
CFLAGS += -DCONFIG_DRIVER_BROADCOM
-OBJS += driver_broadcom.o
+OBJS_d += driver_broadcom.o
endif
ifdef CONFIG_DRIVER_IPW
CFLAGS += -DCONFIG_DRIVER_IPW
-OBJS += driver_ipw.o
+OBJS_d += driver_ipw.o
CONFIG_WIRELESS_EXTENSION=y
endif
ifdef CONFIG_DRIVER_BSD
CFLAGS += -DCONFIG_DRIVER_BSD
-OBJS += driver_bsd.o
+OBJS_d += driver_bsd.o
CONFIG_DNET_PCAP=y
+CONFIG_L2_FREEBSD=y
endif
ifdef CONFIG_DRIVER_NDIS
CFLAGS += -DCONFIG_DRIVER_NDIS
-OBJS += driver_ndis.o driver_ndis_.o
+OBJS_d += driver_ndis.o driver_ndis_.o
CONFIG_DNET_PCAP=y
CONFIG_WINPCAP=y
endif
+ifdef CONFIG_DRIVER_WIRED
+CFLAGS += -DCONFIG_DRIVER_WIRED
+OBJS_d += driver_wired.o
+endif
+
ifdef CONFIG_DRIVER_TEST
CFLAGS += -DCONFIG_DRIVER_TEST
-OBJS += driver_test.o
+OBJS_d += driver_test.o
endif
ifdef CONFIG_DNET_PCAP
CFLAGS += -DUSE_DNET_PCAP
ifdef CONFIG_WINPCAP
+OBJS += l2_packet_pcap.o
CFLAGS += -DCONFIG_WINPCAP
LIBS += -lwpcap -lpacket
LIBS_w += -lwpcap
else
+ifdef CONFIG_L2_FREEBSD
+OBJS += l2_packet_freebsd.o
+LIBS += -lpcap
+else
+OBJS += l2_packet_pcap.o
LIBS += -ldnet -lpcap
endif
endif
+else
+OBJS += l2_packet_linux.o
+endif
ifdef CONFIG_EAP_TLS
# EAP-TLS
@@ -209,8 +233,9 @@ endif
ifdef CONFIG_EAP_PSK
# EAP-PSK
CFLAGS += -DEAP_PSK
-OBJS += eap_psk.o
+OBJS += eap_psk.o eap_psk_common.o
CONFIG_IEEE8021X_EAPOL=y
+NEED_AES=y
endif
ifdef CONFIG_EAP_AKA
@@ -223,6 +248,7 @@ endif
ifdef CONFIG_EAP_SIM_COMMON
OBJS += eap_sim_common.o
+NEED_AES=y
endif
ifdef CONFIG_EAP_TLV
@@ -238,6 +264,13 @@ OBJS += eap_fast.o
TLS_FUNCS=y
endif
+ifdef CONFIG_EAP_PAX
+# EAP-PAX
+CFLAGS += -DEAP_PAX
+OBJS += eap_pax.o eap_pax_common.o
+CONFIG_IEEE8021X_EAPOL=y
+endif
+
ifdef CONFIG_IEEE8021X_EAPOL
# IEEE 802.1X/EAPOL state machines (e.g., for RADIUS authentication)
CFLAGS += -DIEEE8021X_EAPOL
@@ -252,12 +285,38 @@ OBJS += pcsc_funcs.o
LIBS += -lpcsclite -lpthread
endif
+ifndef CONFIG_TLS
+CONFIG_TLS=openssl
+endif
+
ifdef TLS_FUNCS
-# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, and EAP_TTLS)
+# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, EAP_TTLS, and EAP_FAST)
CFLAGS += -DEAP_TLS_FUNCS
-OBJS += eap_tls_common.o tls_openssl.o
+OBJS += eap_tls_common.o
+ifeq ($(CONFIG_TLS), openssl)
+OBJS += tls_openssl.o
LIBS += -lssl -lcrypto
LIBS_p += -lcrypto
+endif
+ifeq ($(CONFIG_TLS), gnutls)
+OBJS += tls_gnutls.o
+LIBS += -lgnutls -lgcrypt -lgpg-error
+LIBS_p += -lgcrypt
+endif
+ifeq ($(CONFIG_TLS), schannel)
+OBJS += tls_schannel.o
+# Using OpenSSL for crypto at the moment; to be replaced
+LIBS += -lcrypto
+LIBS_p += -lcrypto
+endif
+ifdef CONFIG_SMARTCARD
+ifndef CONFIG_NATIVE_WINDOWS
+ifndef CONFIG_L2_FREEBSD
+LIBS += -ldl
+endif
+endif
+endif
+NEED_CRYPTO=y
else
OBJS += tls_none.o
endif
@@ -266,16 +325,49 @@ ifdef CONFIG_PKCS12
CFLAGS += -DPKCS12_FUNCS
endif
+ifdef CONFIG_SMARTCARD
+CFLAGS += -DCONFIG_SMARTCARD
+endif
+
ifdef MS_FUNCS
+OBJS += ms_funcs.o
+NEED_CRYPTO=y
+endif
+
+ifdef NEED_CRYPTO
ifndef TLS_FUNCS
+ifeq ($(CONFIG_TLS), openssl)
LIBS += -lcrypto
+LIBS_p += -lcrypto
+endif
+ifeq ($(CONFIG_TLS), gnutls)
+LIBS += -lgcrypt
+LIBS_p += -lgcrypt
+endif
+ifeq ($(CONFIG_TLS), schannel)
+# Using OpenSSL for crypto at the moment; to be replaced
+LIBS += -lcrypto
+LIBS_p += -lcrypto
+endif
+endif
+ifeq ($(CONFIG_TLS), openssl)
+OBJS += crypto.o
+OBJS_p += crypto.o
+endif
+ifeq ($(CONFIG_TLS), gnutls)
+OBJS += crypto_gnutls.o
+OBJS_p += crypto_gnutls.o
+endif
+ifeq ($(CONFIG_TLS), schannel)
+# Using OpenSSL for crypto at the moment; to be replaced
+OBJS += crypto.o
+OBJS_p += crypto.o
endif
-OBJS += ms_funcs.o crypto.o
endif
ifdef CONFIG_WIRELESS_EXTENSION
CFLAGS += -DCONFIG_WIRELESS_EXTENSION
-OBJS += driver_wext.o
+OBJS_d += driver_wext.o
endif
ifdef CONFIG_CTRL_IFACE
@@ -283,10 +375,6 @@ CFLAGS += -DCONFIG_CTRL_IFACE
OBJS += ctrl_iface.o
endif
-ifdef CONFIG_XSUPPLICANT_IFACE
-CFLAGS += -DCONFIG_XSUPPLICANT_IFACE
-endif
-
ifdef CONFIG_READLINE
CFLAGS += -DCONFIG_READLINE
LIBS_c += -lncurses -lreadline
@@ -294,13 +382,34 @@ endif
ifdef CONFIG_NATIVE_WINDOWS
CFLAGS += -DCONFIG_NATIVE_WINDOWS -DCONFIG_CTRL_IFACE_UDP
-LIBS += -lws2_32 -lgdi32
+LIBS += -lws2_32 -lgdi32 -lcrypt32
LIBS_c += -lws2_32
endif
+ifdef CONFIG_NO_STDOUT_DEBUG
+CFLAGS += -DCONFIG_NO_STDOUT_DEBUG
+endif
+
+ifdef CONFIG_IPV6
+# for eapol_test only
+CFLAGS += -DCONFIG_IPV6
+endif
+
+ifndef CONFIG_NO_WPA
+OBJS += wpa.o preauth.o
+NEED_AES=y
+else
+CFLAGS += -DCONFIG_NO_WPA
+endif
+
+ifdef NEED_AES
+OBJS += aes_wrap.o
+endif
+
+OBJS += wpa_supplicant.o events.o
OBJS_t := $(OBJS) eapol_test.o radius.o radius_client.o
-OBJS_t2 := $(OBJS) preauth_test.o l2_packet.o
-OBJS += wpa_supplicant.o wpa.o l2_packet.o drivers.o
+OBJS_t2 := $(OBJS) preauth_test.o
+OBJS += main.o drivers.o $(OBJS_d)
wpa_supplicant: .config $(OBJS)
$(CC) -o wpa_supplicant $(OBJS) $(LIBS)
@@ -342,30 +451,38 @@ wpa_passphrase.exe: wpa_passphrase
mv -f $< $@
win_if_list.exe: win_if_list
mv -f $< $@
+eapol_test.exe: eapol_test
+ mv -f $< $@
WINALL=wpa_supplicant.exe wpa_cli.exe wpa_passphrase.exe win_if_list.exe
windows-bin: $(WINALL)
$(STRIP) $(WINALL)
+wpa_gui/Makefile:
+ qmake -o wpa_gui/Makefile wpa_gui/wpa_gui.pro
+
+wpa_gui: wpa_gui/Makefile
+ $(MAKE) -C wpa_gui
+
TEST_SRC_MS_FUNCS = ms_funcs.c crypto.c sha1.c md5.c
test-ms_funcs: $(TEST_SRC_MS_FUNCS)
$(CC) -o test-ms_funcs -Wall -Werror $(TEST_SRC_MS_FUNCS) \
- -DTEST_MAIN_MS_FUNCS -lcrypto -I../hostapd
+ -DTEST_MAIN_MS_FUNCS -lcrypto -I../hostapd -I.
./test-ms_funcs
rm test-ms_funcs
TEST_SRC_SHA1 = sha1.c
test-sha1: $(TEST_SRC_SHA1)
$(CC) -o test-sha1 -Wall -Werror $(TEST_SRC_SHA1) \
- -DTEST_MAIN -I../hostad
+ -DTEST_MAIN -I../hostad -I.
./test-sha1
rm test-sha1
TEST_SRC_AES_WRAP = aes_wrap.c
test-aes_wrap: $(TEST_SRC_AES_WRAP)
$(CC) -o test-aes_wrap -Wall -Werror $(TEST_SRC_AES_WRAP) \
- -DTEST_MAIN -I../hostad
+ -DTEST_MAIN -I../hostad -I.
./test-aes_wrap
rm test-aes_wrap
@@ -373,7 +490,7 @@ TEST_SRC_EAP_SIM_COMMON = eap_sim_common.c sha1.c md5.c \
aes_wrap.c common.c
test-eap_sim_common: $(TEST_SRC_EAP_SIM_COMMON)
$(CC) -o test-eap_sim_common -Wall -Werror $(TEST_SRC_EAP_SIM_COMMON) \
- -DTEST_MAIN_EAP_SIM_COMMON -I../hostapd
+ -DTEST_MAIN_EAP_SIM_COMMON -I../hostapd -I.
./test-eap_sim_common
rm test-eap_sim_common
@@ -382,4 +499,25 @@ tests: test-ms_funcs test-sha1 test-aes_wrap test-eap_sim_common
clean:
rm -f core *~ *.o *.d $(ALL) $(WINALL)
+%.eps: %.fig
+ fig2dev -L eps $*.fig $*.eps
+
+%.png: %.fig
+ fig2dev -L png -m 3 $*.fig | pngtopnm | pnmscale 0.4 | pnmtopng \
+ > $*.png
+
+docs-pics: doc/wpa_supplicant.png doc/wpa_supplicant.eps
+
+docs: docs-pics
+ doxygen doc/doxygen.full
+ $(MAKE) -C doc/latex
+ cp doc/latex/refman.pdf wpa_supplicant-devel.pdf
+
+docs-fast: docs-pics
+ doxygen doc/doxygen.fast
+
+clean-docs:
+ rm -rf doc/latex doc/html
+ rm -f doc/wpa_supplicant.{eps,png} wpa_supplicant-devel.pdf
+
-include $(OBJS:%.o=%.d)
diff --git a/contrib/wpa_supplicant/README b/contrib/wpa_supplicant/README
index bab25d586725..831756b12c25 100644
--- a/contrib/wpa_supplicant/README
+++ b/contrib/wpa_supplicant/README
@@ -1,7 +1,7 @@
WPA Supplicant
==============
-Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi> and
+Copyright (c) 2003-2006, Jouni Malinen <jkmaline@cc.hut.fi> and
contributors
All Rights Reserved.
@@ -89,6 +89,7 @@ Supported WPA/IEEE 802.11i features:
* EAP-SIM
* EAP-AKA
* EAP-PSK
+ * EAP-PAX
* LEAP (note: requires special support from the driver for IEEE 802.11
authentication)
(following methods are supported, but since they do not generate keying
@@ -97,8 +98,6 @@ Supported WPA/IEEE 802.11i features:
* EAP-MSCHAPv2
* EAP-GTC
* EAP-OTP
- Alternatively, an external program, e.g., Xsupplicant, can be used for EAP
- authentication.
- key management for CCMP, TKIP, WEP104, WEP40
- RSN/WPA2 (IEEE 802.11i)
* pre-authentication
@@ -112,6 +111,7 @@ Requirements
Current hardware/software requirements:
- Linux kernel 2.4.x or 2.6.x with Linux Wireless Extensions v15 or newer
- FreeBSD 6-CURRENT
+- NetBSD-current
- Microsoft Windows with WinPcap (at least WinXP, may work with other versions)
- drivers:
Host AP driver for Prism2/2.5/3 (development snapshot/v0.2.x)
@@ -164,8 +164,10 @@ Current hardware/software requirements:
used with IEEE 802.1X (i.e., not WPA) when using ap_scan=0 option in
configuration file.
+ Wired Ethernet drivers (with ap_scan=0)
+
BSD net80211 layer (e.g., Atheros driver)
- At the moment, this is for FreeBSD 6-CURRENT branch.
+ At the moment, this is for FreeBSD 6-CURRENT branch and NetBSD-current.
Windows NDIS
The current Windows port requires WinPcap (http://winpcap.polito.it/).
@@ -173,7 +175,8 @@ Current hardware/software requirements:
wpa_supplicant was designed to be portable for different drivers and
operating systems. Hopefully, support for more wlan cards and OSes will be
-added in the future. See developer.txt for more information about the
+added in the future. See developer's documentation
+(http://hostap.epitest.fi/wpa_supplicant/devel/) for more information about the
design of wpa_supplicant and porting to other drivers. One main goal
is to add full WPA/WPA2 support to Linux wireless extensions to allow
new drivers to be supported without having to implement new
@@ -221,8 +224,7 @@ networks that require some kind of security. Task group I (Security)
of IEEE 802.11 working group (http://www.ieee802.org/11/) has worked
to address the flaws of the base standard and has in practice
completed its work in May 2004. The IEEE 802.11i amendment to the IEEE
-802.11 standard was approved in June 2004 and this amendment is likely
-to be published in July 2004.
+802.11 standard was approved in June 2004 and published in July 2004.
Wi-Fi Alliance (http://www.wi-fi.org/) used a draft version of the
IEEE 802.11i work (draft 3.0) to define a subset of the security
@@ -277,14 +279,6 @@ robust encryption algorithm (CCMP: AES in Counter mode with CBC-MAC)
to replace TKIP and optimizations for handoff (reduced number of
messages in initial key handshake, pre-authentication, and PMKSA caching).
-Some wireless LAN vendors are already providing support for CCMP in
-their WPA products. There is no "official" interoperability
-certification for CCMP and/or mixed modes using both TKIP and CCMP, so
-some interoperability issues can be expected even though many
-combinations seem to be working with equipment from different vendors.
-Certification for WPA2 is likely to start during the second half of
-2004.
-
wpa_supplicant
@@ -307,9 +301,9 @@ Following steps are used when associating with an AP using WPA:
- wpa_supplicant selects a BSS based on its configuration
- wpa_supplicant requests the kernel driver to associate with the chosen
BSS
-- If WPA-EAP: integrated IEEE 802.1X Supplicant or external Xsupplicant
- completes EAP authentication with the authentication server (proxied
- by the Authenticator in the AP)
+- If WPA-EAP: integrated IEEE 802.1X Supplicant completes EAP
+ authentication with the authentication server (proxied by the
+ Authenticator in the AP)
- If WPA-EAP: master key is received from the IEEE 802.1X Supplicant
- If WPA-PSK: wpa_supplicant uses PSK as the master session key
- wpa_supplicant completes WPA 4-Way Handshake and Group Key Handshake
@@ -352,6 +346,7 @@ CONFIG_EAP_OTP=y
CONFIG_EAP_SIM=y
CONFIG_EAP_AKA=y
CONFIG_EAP_PSK=y
+CONFIG_EAP_PAX=y
CONFIG_EAP_LEAP=y
Following option can be used to include GSM SIM/USIM interface for GSM/UMTS
@@ -366,13 +361,12 @@ interface with libpcap/libdnet.
CONFIG_DNET_PCAP=y
Following options can be added to .config to select which driver
-interfaces are included. Prism54.org driver is not yet complete and
-Hermes driver interface needs to be downloaded from Agere (see above).
-Most Linux driver need to include CONFIG_WIRELESS_EXTENSION.
+interfaces are included. Hermes driver interface needs to be downloaded
+from Agere (see above). CONFIG_WIRELESS_EXTENSION will be used
+automatically if any of the selected drivers need it.
CONFIG_WIRELESS_EXTENSION=y
CONFIG_DRIVER_HOSTAP=y
-CONFIG_DRIVER_PRISM54=y
CONFIG_DRIVER_HERMES=y
CONFIG_DRIVER_MADWIFI=y
CONFIG_DRIVER_ATMEL=y
@@ -387,7 +381,6 @@ Following example includes all features and driver interfaces that are
included in the wpa_supplicant package:
CONFIG_DRIVER_HOSTAP=y
-CONFIG_DRIVER_PRISM54=y
CONFIG_DRIVER_HERMES=y
CONFIG_DRIVER_MADWIFI=y
CONFIG_DRIVER_ATMEL=y
@@ -409,6 +402,7 @@ CONFIG_EAP_OTP=y
CONFIG_EAP_SIM=y
CONFIG_EAP_AKA=y
CONFIG_EAP_PSK=y
+CONFIG_EAP_PAX=y
CONFIG_EAP_LEAP=y
CONFIG_PCSC=y
@@ -463,8 +457,6 @@ options:
-d = increase debugging verbosity (-dd even more)
-K = include keys (passwords, etc.) in debug output
-t = include timestamp in debug messages
- -e = use external IEEE 802.1X Supplicant (e.g., xsupplicant)
- (this disables the internal Supplicant)
-h = show this help text
-L = show license (GPL and BSD)
-q = decrease debugging verbosity (-qq even less)
@@ -475,8 +467,6 @@ options:
drivers:
hostap = Host AP driver (Intersil Prism2/2.5/3) [default]
(this can also be used with Linuxant DriverLoader)
- prism54 = Prism54.org driver (Intersil Prism GT/Duette/Indigo)
- not yet fully implemented
hermes = Agere Systems Inc. driver (Hermes-I/Hermes-II)
madwifi = MADWIFI 802.11 support (Atheros, etc.)
atmel = ATMEL AT76C5XXx (USB, PCMCIA)
@@ -484,6 +474,7 @@ drivers:
ndiswrapper = Linux ndiswrapper
broadcom = Broadcom wl.o driver
ipw = Intel ipw2100/2200 driver
+ wired = wpa_supplicant wired Ethernet driver
bsd = BSD 802.11 support (Atheros, etc.)
ndis = Windows NDIS driver
@@ -647,6 +638,21 @@ network={
}
+6) Authentication for wired Ethernet. This can be used with 'wired' interface
+ (-Dwired on command line).
+
+ctrl_interface=/var/run/wpa_supplicant
+ctrl_interface_group=wheel
+ap_scan=0
+network={
+ key_mgmt=IEEE8021X
+ eap=MD5
+ identity="user"
+ password="password"
+ eapol_flags=0
+}
+
+
Certificates
------------
@@ -681,7 +687,7 @@ wpa_supplicant. It is used to query current status, change
configuration, trigger events, and request interactive user input.
wpa_cli can show the current authentication status, selected security
-mode, dot11 and dot1x MIBs, etc. In addition, it can configuring some
+mode, dot11 and dot1x MIBs, etc. In addition, it can configure some
variables like EAPOL state machine parameters and trigger events like
reassociation and IEEE 802.1X logoff/logon. wpa_cli provides a user
interface to request authentication information, like username and
@@ -757,11 +763,83 @@ wpa_cli commands
preauthenticate <BSSID> = force preauthentication
identity <network id> <identity> = configure identity for an SSID
password <network id> <password> = configure password for an SSID
+ pin <network id> <pin> = configure pin for an SSID
otp <network id> <password> = configure one-time-password for an SSID
+ passphrase <network id> <passphrase> = configure private key passphrase
+ for an SSID
+ bssid <network id> <BSSID> = set preferred BSSID for an SSID
+ list_networks = list configured networks
+ select_network <network id> = select a network (disable others)
+ enable_network <network id> = enable a network
+ disable_network <network id> = disable a network
+ add_network = add a network
+ remove_network <network id> = remove a network
+ set_network <network id> <variable> <value> = set network variables (shows
+ list of variables when run without arguments)
+ get_network <network id> <variable> = get network variables
+ save_config = save the current configuration
+ disconnect = disconnect and wait for reassociate command before connecting
+ scan = request new BSS scan
+ scan_results = get latest scan results
+ get_capability <eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies
terminate = terminate wpa_supplicant
quit = exit wpa_cli
+wpa_cli command line options
+
+wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] [-a<action file>] \
+ [-P<pid file>] [-g<global ctrl>] [command..]
+ -h = help (show this usage text)
+ -v = shown version information
+ -a = run in daemon mode executing the action file based on events from
+ wpa_supplicant
+ -B = run a daemon in the background
+ default path: /var/run/wpa_supplicant
+ default interface: first interface found in socket path
+
+
+Using wpa_cli to run external program on connect/disconnect
+-----------------------------------------------------------
+
+wpa_cli can used to run external programs whenever wpa_supplicant
+connects or disconnects from a network. This can be used, e.g., to
+update network configuration and/or trigget DHCP client to update IP
+addresses, etc.
+
+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
+more than one interface being used at the same time):
+
+wpa_cli -a/sbin/wpa_action.sh -B
+
+The action file (-a option, /sbin/wpa_action.sh in this example) will
+be executed whenever wpa_supplicant completes authentication (connect
+event) or detects disconnection). The action script will be called
+with two command line arguments: interface name and event (CONNECTED
+or DISCONNECTED). If the action script needs to get more information
+about the current network, it can use 'wpa_cli status' to query
+wpa_supplicant for more information.
+
+Following example can be used as a simple template for an action
+script:
+
+#!/bin/sh
+
+IFNAME=$1
+CMD=$2
+
+if [ "$CMD" == "CONNECTED" ]; then
+ SSID=`wpa_cli -i$IFNAME status | grep ^ssid= | cut -f2- -d=`
+ # configure network, signal DHCP client, etc.
+fi
+
+if [ "$CMD" == "DISCONNECTED" ]; then
+ # remove network configuration, if needed
+fi
+
+
Integrating with pcmcia-cs/cardmgr scripts
------------------------------------------
@@ -804,55 +882,38 @@ started--and will then negotiate keys with the AP.
-Optional integration with Xsupplicant
--------------------------------------
-
-wpa_supplicant has an integrated IEEE 802.1X Supplicant that supports
-most commonly used EAP methods. In addition, wpa_supplicant has an
-experimental interface for integrating it with Xsupplicant
-(http://www.open1x.org/) for the WPA with EAP authentication.
-
-When using WPA-EAP, both wpa_supplicant and Xsupplicant must be
-configured with the network security policy. See Xsupplicant documents
-for information about its configuration. Please also note, that a new
-command line option -W (enable WPA) must be used when starting
-xsupplicant.
-
-Example configuration for xsupplicant:
-
-network_list = all
-default_netname = jkm
-
-jkm
-{
- type = wireless
- allow_types = eap_peap
- identity = <BEGIN_ID>jkm<END_ID>
- eap-peap {
- random_file = /dev/urandom
- root_cert = /home/jkm/CA.pem
- chunk_size = 1398
- allow_types = eap_mschapv2
- eap-mschapv2 {
- username = <BEGIN_UNAME>jkm<END_UNAME>
- password = <BEGIN_PASS>jkm<END_PASS>
- }
- }
-}
+Dynamic interface add and operation without configuration files
+---------------------------------------------------------------
+wpa_supplicant can be started without any configuration files or
+network interfaces. When used in this way, a global (i.e., per
+wpa_supplicant process) control interface is used to add and remove
+network interfaces. Each network interface can then be configured
+through a per-network interface control interface. For example,
+following commands show how to start wpa_supplicant without any
+network interfaces and then add a network interface and configure a
+network (SSID):
-Example configuration for wpa_supplicant:
+# Start wpa_supplicant in the background
+wpa_supplicant -g/var/run/wpa_supplicant-global -B
-network={
- ssid="jkm"
- key_mgmt=WPA-EAP
-}
+# Add a new interface (wlan0, no configuration file, driver=wext, and
+# enable control interface)
+wpa_cli -g/var/run/wpa_supplicant-global interface_add wlan0 \
+ "" wext /var/run/wpa_supplicant
+# Configure a network using the newly added network interface:
+wpa_cli -iwlan0 add_network
+wpa_cli -iwlan0 set_network 0 ssid '"test"'
+wpa_cli -iwlan0 set_network 0 key_mgmt WPA-PSK
+wpa_cli -iwlan0 set_network 0 psk '"12345678"'
+wpa_cli -iwlan0 set_network 0 pairwise TKIP
+wpa_cli -iwlan0 set_network 0 group TKIP
+wpa_cli -iwlan0 set_network 0 proto WPA
+wpa_cli -iwlan0 enable_network 0
-Both wpa_supplicant and xsupplicant need to be started. Please remember
-to add '-W' option for xsupplicant in order to provide keying material
-for wpa_supplicant and '-e' option for wpa_supplicant to disable internal
-IEEE 802.1X implementation.
+# At this point, the new network interface should start trying to associate
+# with the WPA-PSK network using SSID test.
-wpa_supplicant -iwlan0 -cwpa_supplicant.conf -e
-xsupplicant -iwlan0 -cxsupplicant.conf -W
+# Remove network interface
+wpa_cli -g/var/run/wpa_supplicant-global interface_remove wlan0
diff --git a/contrib/wpa_supplicant/aes.c b/contrib/wpa_supplicant/aes.c
index eabebd074653..ce94778dd62e 100644
--- a/contrib/wpa_supplicant/aes.c
+++ b/contrib/wpa_supplicant/aes.c
@@ -1,8 +1,15 @@
/*
+ * AES (Rijndael) cipher
+ *
* Modifications to public domain implementation:
* - support only 128-bit keys
* - cleanup
- * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
+ * - use C pre-processor to make it easier to change S table access
+ * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at
+ * cost of reduced throughput (quite small difference on Pentium 4,
+ * 10-25% when using -O1 or -O2 optimization)
+ *
+ * Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -14,7 +21,7 @@
* See README and COPYING for more details.
*/
-/**
+/*
* rijndael-alg-fst.c
*
* @version 3.0 (December 2000)
@@ -40,7 +47,8 @@
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#define FULL_UNROLL
+/* #define FULL_UNROLL */
+#define AES_SMALL_TABLES
/*
@@ -123,6 +131,7 @@ static const u32 Te0[256] = {
0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
};
+#ifndef AES_SMALL_TABLES
static const u32 Te1[256] = {
0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
@@ -388,6 +397,7 @@ static const u32 Te4[256] = {
0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
};
+#endif /* AES_SMALL_TABLES */
static const u32 Td0[256] = {
0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
@@ -454,6 +464,7 @@ static const u32 Td0[256] = {
0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
};
+#ifndef AES_SMALL_TABLES
static const u32 Td1[256] = {
0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
@@ -724,6 +735,116 @@ static const u32 rcon[] = {
0x10000000, 0x20000000, 0x40000000, 0x80000000,
0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
};
+#else /* AES_SMALL_TABLES */
+static const u8 Td4s[256] = {
+ 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U,
+ 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU,
+ 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U,
+ 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU,
+ 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU,
+ 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU,
+ 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U,
+ 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U,
+ 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U,
+ 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U,
+ 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU,
+ 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U,
+ 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU,
+ 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U,
+ 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U,
+ 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU,
+ 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU,
+ 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U,
+ 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U,
+ 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU,
+ 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U,
+ 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU,
+ 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U,
+ 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U,
+ 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U,
+ 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU,
+ 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU,
+ 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU,
+ 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U,
+ 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U,
+ 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U,
+ 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU,
+};
+static const u8 rcons[] = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36
+ /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+#endif /* AES_SMALL_TABLES */
+
+
+#ifndef AES_SMALL_TABLES
+
+#define RCON(i) rcon[(i)]
+
+#define TE0(i) Te0[((i) >> 24) & 0xff]
+#define TE1(i) Te1[((i) >> 16) & 0xff]
+#define TE2(i) Te2[((i) >> 8) & 0xff]
+#define TE3(i) Te3[(i) & 0xff]
+#define TE41(i) (Te4[((i) >> 24) & 0xff] & 0xff000000)
+#define TE42(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000)
+#define TE43(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00)
+#define TE44(i) (Te4[(i) & 0xff] & 0x000000ff)
+#define TE421(i) (Te4[((i) >> 16) & 0xff] & 0xff000000)
+#define TE432(i) (Te4[((i) >> 8) & 0xff] & 0x00ff0000)
+#define TE443(i) (Te4[(i) & 0xff] & 0x0000ff00)
+#define TE414(i) (Te4[((i) >> 24) & 0xff] & 0x000000ff)
+#define TE4(i) (Te4[(i)] & 0x000000ff)
+
+#define TD0(i) Td0[((i) >> 24) & 0xff]
+#define TD1(i) Td1[((i) >> 16) & 0xff]
+#define TD2(i) Td2[((i) >> 8) & 0xff]
+#define TD3(i) Td3[(i) & 0xff]
+#define TD41(i) (Td4[((i) >> 24) & 0xff] & 0xff000000)
+#define TD42(i) (Td4[((i) >> 16) & 0xff] & 0x00ff0000)
+#define TD43(i) (Td4[((i) >> 8) & 0xff] & 0x0000ff00)
+#define TD44(i) (Td4[(i) & 0xff] & 0x000000ff)
+#define TD0_(i) Td0[(i) & 0xff]
+#define TD1_(i) Td1[(i) & 0xff]
+#define TD2_(i) Td2[(i) & 0xff]
+#define TD3_(i) Td3[(i) & 0xff]
+
+#else /* AES_SMALL_TABLES */
+
+#define RCON(i) (rcons[(i)] << 24)
+
+static inline u32 rotr(u32 val, int bits)
+{
+ return (val >> bits) | (val << (32 - bits));
+}
+
+#define TE0(i) Te0[((i) >> 24) & 0xff]
+#define TE1(i) rotr(Te0[((i) >> 16) & 0xff], 8)
+#define TE2(i) rotr(Te0[((i) >> 8) & 0xff], 16)
+#define TE3(i) rotr(Te0[(i) & 0xff], 24)
+#define TE41(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000)
+#define TE42(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000)
+#define TE43(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00)
+#define TE44(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff)
+#define TE421(i) ((Te0[((i) >> 16) & 0xff] << 8) & 0xff000000)
+#define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000)
+#define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00)
+#define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff)
+#define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff)
+
+#define TD0(i) Td0[((i) >> 24) & 0xff]
+#define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8)
+#define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16)
+#define TD3(i) rotr(Td0[(i) & 0xff], 24)
+#define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24)
+#define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16)
+#define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8)
+#define TD44(i) (Td4s[(i) & 0xff])
+#define TD0_(i) Td0[(i) & 0xff]
+#define TD1_(i) rotr(Td0[(i) & 0xff], 8)
+#define TD2_(i) rotr(Td0[(i) & 0xff], 16)
+#define TD3_(i) rotr(Td0[(i) & 0xff], 24)
+
+#endif /* AES_SMALL_TABLES */
#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
@@ -755,11 +876,8 @@ void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[])
for (i = 0; i < 10; i++) {
temp = rk[3];
rk[4] = rk[0] ^
- (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
- (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
- (Te4[(temp ) & 0xff] & 0x0000ff00) ^
- (Te4[(temp >> 24) ] & 0x000000ff) ^
- rcon[i];
+ TE421(temp) ^ TE432(temp) ^ TE443(temp) ^ TE414(temp) ^
+ RCON(i);
rk[5] = rk[1] ^ rk[4];
rk[6] = rk[2] ^ rk[5];
rk[7] = rk[3] ^ rk[6];
@@ -790,33 +908,19 @@ void rijndaelKeySetupDec(u32 rk[/*44*/], const u8 cipherKey[])
* first and the last: */
for (i = 1; i < Nr; i++) {
rk += 4;
- rk[0] =
- Td0[Te4[(rk[0] >> 24) ] & 0xff] ^
- Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^
- Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^
- Td3[Te4[(rk[0] ) & 0xff] & 0xff];
- rk[1] =
- Td0[Te4[(rk[1] >> 24) ] & 0xff] ^
- Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^
- Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^
- Td3[Te4[(rk[1] ) & 0xff] & 0xff];
- rk[2] =
- Td0[Te4[(rk[2] >> 24) ] & 0xff] ^
- Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^
- Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^
- Td3[Te4[(rk[2] ) & 0xff] & 0xff];
- rk[3] =
- Td0[Te4[(rk[3] >> 24) ] & 0xff] ^
- Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^
- Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^
- Td3[Te4[(rk[3] ) & 0xff] & 0xff];
+ for (j = 0; j < 4; j++) {
+ rk[j] = TD0_(TE4((rk[j] >> 24) )) ^
+ TD1_(TE4((rk[j] >> 16) & 0xff)) ^
+ TD2_(TE4((rk[j] >> 8) & 0xff)) ^
+ TD3_(TE4((rk[j] ) & 0xff));
+ }
}
}
void rijndaelEncrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16])
{
u32 s0, s1, s2, s3, t0, t1, t2, t3;
- int Nr = 10;
+ const int Nr = 10;
#ifndef FULL_UNROLL
int r;
#endif /* ?FULL_UNROLL */
@@ -829,153 +933,61 @@ void rijndaelEncrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16])
s1 = GETU32(pt + 4) ^ rk[1];
s2 = GETU32(pt + 8) ^ rk[2];
s3 = GETU32(pt + 12) ^ rk[3];
+
+#define ROUND(i,d,s) \
+d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \
+d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \
+d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \
+d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3]
+
#ifdef FULL_UNROLL
- /* round 1: */
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7];
- /* round 2: */
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8];
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];
- /* round 3: */
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15];
- /* round 4: */
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16];
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];
- /* round 5: */
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23];
- /* round 6: */
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24];
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];
- /* round 7: */
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31];
- /* round 8: */
- s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32];
- s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];
- s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];
- s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];
- /* round 9: */
- t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];
- t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];
- t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];
- t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];
- rk += Nr << 2;
+
+ ROUND(1,t,s);
+ ROUND(2,s,t);
+ ROUND(3,t,s);
+ ROUND(4,s,t);
+ ROUND(5,t,s);
+ ROUND(6,s,t);
+ ROUND(7,t,s);
+ ROUND(8,s,t);
+ ROUND(9,t,s);
+
+ rk += Nr << 2;
+
#else /* !FULL_UNROLL */
- /*
- * Nr - 1 full rounds:
- */
- r = Nr >> 1;
- for (;;) {
- t0 =
- Te0[(s0 >> 24) ] ^
- Te1[(s1 >> 16) & 0xff] ^
- Te2[(s2 >> 8) & 0xff] ^
- Te3[(s3 ) & 0xff] ^
- rk[4];
- t1 =
- Te0[(s1 >> 24) ] ^
- Te1[(s2 >> 16) & 0xff] ^
- Te2[(s3 >> 8) & 0xff] ^
- Te3[(s0 ) & 0xff] ^
- rk[5];
- t2 =
- Te0[(s2 >> 24) ] ^
- Te1[(s3 >> 16) & 0xff] ^
- Te2[(s0 >> 8) & 0xff] ^
- Te3[(s1 ) & 0xff] ^
- rk[6];
- t3 =
- Te0[(s3 >> 24) ] ^
- Te1[(s0 >> 16) & 0xff] ^
- Te2[(s1 >> 8) & 0xff] ^
- Te3[(s2 ) & 0xff] ^
- rk[7];
- rk += 8;
- if (--r == 0) {
- break;
- }
+ /* Nr - 1 full rounds: */
+ r = Nr >> 1;
+ for (;;) {
+ ROUND(1,t,s);
+ rk += 8;
+ if (--r == 0)
+ break;
+ ROUND(0,s,t);
+ }
- s0 =
- Te0[(t0 >> 24) ] ^
- Te1[(t1 >> 16) & 0xff] ^
- Te2[(t2 >> 8) & 0xff] ^
- Te3[(t3 ) & 0xff] ^
- rk[0];
- s1 =
- Te0[(t1 >> 24) ] ^
- Te1[(t2 >> 16) & 0xff] ^
- Te2[(t3 >> 8) & 0xff] ^
- Te3[(t0 ) & 0xff] ^
- rk[1];
- s2 =
- Te0[(t2 >> 24) ] ^
- Te1[(t3 >> 16) & 0xff] ^
- Te2[(t0 >> 8) & 0xff] ^
- Te3[(t1 ) & 0xff] ^
- rk[2];
- s3 =
- Te0[(t3 >> 24) ] ^
- Te1[(t0 >> 16) & 0xff] ^
- Te2[(t1 >> 8) & 0xff] ^
- Te3[(t2 ) & 0xff] ^
- rk[3];
- }
#endif /* ?FULL_UNROLL */
- /*
+
+#undef ROUND
+
+ /*
* apply last round and
* map cipher state to byte array block:
*/
- s0 =
- (Te4[(t0 >> 24) ] & 0xff000000) ^
- (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
- (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^
- (Te4[(t3 ) & 0xff] & 0x000000ff) ^
- rk[0];
+ s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0];
PUTU32(ct , s0);
- s1 =
- (Te4[(t1 >> 24) ] & 0xff000000) ^
- (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
- (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^
- (Te4[(t0 ) & 0xff] & 0x000000ff) ^
- rk[1];
+ s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1];
PUTU32(ct + 4, s1);
- s2 =
- (Te4[(t2 >> 24) ] & 0xff000000) ^
- (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
- (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^
- (Te4[(t1 ) & 0xff] & 0x000000ff) ^
- rk[2];
+ s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2];
PUTU32(ct + 8, s2);
- s3 =
- (Te4[(t3 >> 24) ] & 0xff000000) ^
- (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
- (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^
- (Te4[(t2 ) & 0xff] & 0x000000ff) ^
- rk[3];
+ s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3];
PUTU32(ct + 12, s3);
}
void rijndaelDecrypt(const u32 rk[/*44*/], const u8 ct[16], u8 pt[16])
{
u32 s0, s1, s2, s3, t0, t1, t2, t3;
- int Nr = 10;
+ const int Nr = 10;
#ifndef FULL_UNROLL
int r;
#endif /* ?FULL_UNROLL */
@@ -984,149 +996,110 @@ void rijndaelDecrypt(const u32 rk[/*44*/], const u8 ct[16], u8 pt[16])
* map byte array block to cipher state
* and add initial round key:
*/
- s0 = GETU32(ct ) ^ rk[0];
- s1 = GETU32(ct + 4) ^ rk[1];
- s2 = GETU32(ct + 8) ^ rk[2];
- s3 = GETU32(ct + 12) ^ rk[3];
+ s0 = GETU32(ct ) ^ rk[0];
+ s1 = GETU32(ct + 4) ^ rk[1];
+ s2 = GETU32(ct + 8) ^ rk[2];
+ s3 = GETU32(ct + 12) ^ rk[3];
+
+#define ROUND(i,d,s) \
+d##0 = TD0(s##0) ^ TD1(s##3) ^ TD2(s##2) ^ TD3(s##1) ^ rk[4 * i]; \
+d##1 = TD0(s##1) ^ TD1(s##0) ^ TD2(s##3) ^ TD3(s##2) ^ rk[4 * i + 1]; \
+d##2 = TD0(s##2) ^ TD1(s##1) ^ TD2(s##0) ^ TD3(s##3) ^ rk[4 * i + 2]; \
+d##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3]
+
#ifdef FULL_UNROLL
- /* round 1: */
- t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4];
- t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5];
- t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6];
- t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7];
- /* round 2: */
- s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8];
- s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9];
- s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10];
- s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11];
- /* round 3: */
- t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12];
- t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13];
- t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14];
- t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15];
- /* round 4: */
- s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16];
- s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17];
- s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18];
- s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19];
- /* round 5: */
- t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20];
- t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21];
- t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22];
- t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23];
- /* round 6: */
- s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24];
- s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25];
- s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26];
- s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27];
- /* round 7: */
- t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28];
- t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29];
- t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30];
- t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31];
- /* round 8: */
- s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32];
- s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33];
- s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34];
- s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35];
- /* round 9: */
- t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36];
- t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37];
- t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38];
- t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39];
+
+ ROUND(1,t,s);
+ ROUND(2,s,t);
+ ROUND(3,t,s);
+ ROUND(4,s,t);
+ ROUND(5,t,s);
+ ROUND(6,s,t);
+ ROUND(7,t,s);
+ ROUND(8,s,t);
+ ROUND(9,t,s);
+
rk += Nr << 2;
+
#else /* !FULL_UNROLL */
- /*
- * Nr - 1 full rounds:
- */
- r = Nr >> 1;
- for (;;) {
- t0 =
- Td0[(s0 >> 24) ] ^
- Td1[(s3 >> 16) & 0xff] ^
- Td2[(s2 >> 8) & 0xff] ^
- Td3[(s1 ) & 0xff] ^
- rk[4];
- t1 =
- Td0[(s1 >> 24) ] ^
- Td1[(s0 >> 16) & 0xff] ^
- Td2[(s3 >> 8) & 0xff] ^
- Td3[(s2 ) & 0xff] ^
- rk[5];
- t2 =
- Td0[(s2 >> 24) ] ^
- Td1[(s1 >> 16) & 0xff] ^
- Td2[(s0 >> 8) & 0xff] ^
- Td3[(s3 ) & 0xff] ^
- rk[6];
- t3 =
- Td0[(s3 >> 24) ] ^
- Td1[(s2 >> 16) & 0xff] ^
- Td2[(s1 >> 8) & 0xff] ^
- Td3[(s0 ) & 0xff] ^
- rk[7];
- rk += 8;
- if (--r == 0) {
- break;
- }
+ /* Nr - 1 full rounds: */
+ r = Nr >> 1;
+ for (;;) {
+ ROUND(1,t,s);
+ rk += 8;
+ if (--r == 0)
+ break;
+ ROUND(0,s,t);
+ }
- s0 =
- Td0[(t0 >> 24) ] ^
- Td1[(t3 >> 16) & 0xff] ^
- Td2[(t2 >> 8) & 0xff] ^
- Td3[(t1 ) & 0xff] ^
- rk[0];
- s1 =
- Td0[(t1 >> 24) ] ^
- Td1[(t0 >> 16) & 0xff] ^
- Td2[(t3 >> 8) & 0xff] ^
- Td3[(t2 ) & 0xff] ^
- rk[1];
- s2 =
- Td0[(t2 >> 24) ] ^
- Td1[(t1 >> 16) & 0xff] ^
- Td2[(t0 >> 8) & 0xff] ^
- Td3[(t3 ) & 0xff] ^
- rk[2];
- s3 =
- Td0[(t3 >> 24) ] ^
- Td1[(t2 >> 16) & 0xff] ^
- Td2[(t1 >> 8) & 0xff] ^
- Td3[(t0 ) & 0xff] ^
- rk[3];
- }
#endif /* ?FULL_UNROLL */
- /*
+
+#undef ROUND
+
+ /*
* apply last round and
* map cipher state to byte array block:
*/
- s0 =
- (Td4[(t0 >> 24) ] & 0xff000000) ^
- (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
- (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^
- (Td4[(t1 ) & 0xff] & 0x000000ff) ^
- rk[0];
+ s0 = TD41(t0) ^ TD42(t3) ^ TD43(t2) ^ TD44(t1) ^ rk[0];
PUTU32(pt , s0);
- s1 =
- (Td4[(t1 >> 24) ] & 0xff000000) ^
- (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
- (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^
- (Td4[(t2 ) & 0xff] & 0x000000ff) ^
- rk[1];
+ s1 = TD41(t1) ^ TD42(t0) ^ TD43(t3) ^ TD44(t2) ^ rk[1];
PUTU32(pt + 4, s1);
- s2 =
- (Td4[(t2 >> 24) ] & 0xff000000) ^
- (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
- (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^
- (Td4[(t3 ) & 0xff] & 0x000000ff) ^
- rk[2];
+ s2 = TD41(t2) ^ TD42(t1) ^ TD43(t0) ^ TD44(t3) ^ rk[2];
PUTU32(pt + 8, s2);
- s3 =
- (Td4[(t3 >> 24) ] & 0xff000000) ^
- (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
- (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^
- (Td4[(t0 ) & 0xff] & 0x000000ff) ^
- rk[3];
+ s3 = TD41(t3) ^ TD42(t2) ^ TD43(t1) ^ TD44(t0) ^ rk[3];
PUTU32(pt + 12, s3);
}
+
+
+
+/* Generic wrapper functions for AES functions */
+
+void * aes_encrypt_init(const u8 *key, size_t len)
+{
+ u32 *rk;
+ if (len != 16)
+ return NULL;
+ rk = malloc(4 * 44);
+ if (rk == NULL)
+ return NULL;
+ rijndaelKeySetupEnc(rk, key);
+ return rk;
+}
+
+
+void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
+{
+ rijndaelEncrypt(ctx, plain, crypt);
+}
+
+
+void aes_encrypt_deinit(void *ctx)
+{
+ free(ctx);
+}
+
+
+void * aes_decrypt_init(const u8 *key, size_t len)
+{
+ u32 *rk;
+ if (len != 16)
+ return NULL;
+ rk = malloc(4 * 44);
+ if (rk == NULL)
+ return NULL;
+ rijndaelKeySetupDec(rk, key);
+ return rk;
+}
+
+
+void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
+{
+ rijndaelDecrypt(ctx, crypt, plain);
+}
+
+
+void aes_decrypt_deinit(void *ctx)
+{
+ free(ctx);
+}
diff --git a/contrib/wpa_supplicant/aes_wrap.c b/contrib/wpa_supplicant/aes_wrap.c
index dbcc136517e7..a5925ca2ec47 100644
--- a/contrib/wpa_supplicant/aes_wrap.c
+++ b/contrib/wpa_supplicant/aes_wrap.c
@@ -1,10 +1,13 @@
/*
- * AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
- * One-Key CBC MAC (OMAC1) hash with AES-128
- * AES-128 CTR mode encryption
- * AES-128 EAX mode encryption/decryption
- * AES-128 CBC
- * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
+ * AES-based functions
+ *
+ * - AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ * - One-Key CBC MAC (OMAC1) hash with AES-128
+ * - AES-128 CTR mode encryption
+ * - AES-128 EAX mode encryption/decryption
+ * - AES-128 CBC
+ *
+ * Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -21,43 +24,26 @@
#include <string.h>
#include "common.h"
#include "aes_wrap.h"
+#include "crypto.h"
-#ifdef EAP_TLS_FUNCS
-
-#include <openssl/aes.h>
-
-#else /* EAP_TLS_FUNCS */
-
+#ifndef EAP_TLS_FUNCS
#include "aes.c"
-
-struct aes_key_st {
- u32 rk[44];
-};
-typedef struct aes_key_st AES_KEY;
-
-#define AES_set_encrypt_key(userKey, bits, key) \
- rijndaelKeySetupEnc((key)->rk, (userKey))
-#define AES_set_decrypt_key(userKey, bits, key) \
- rijndaelKeySetupDec((key)->rk, (userKey))
-#define AES_encrypt(in, out, key) \
- rijndaelEncrypt((key)->rk, in, out)
-#define AES_decrypt(in, out, key) \
- rijndaelDecrypt((key)->rk, in, out)
-
#endif /* EAP_TLS_FUNCS */
-/*
- * @kek: key encryption key (KEK)
- * @n: length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes
- * @plain: plaintext key to be wrapped, n * 64 bit
- * @cipher: wrapped key, (n + 1) * 64 bit
+/**
+ * aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ * @kek: Key encryption key (KEK)
+ * @n: Length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes
+ * @plain: Plaintext key to be wrapped, n * 64 bit
+ * @cipher: Wrapped key, (n + 1) * 64 bit
+ * Returns: 0 on success, -1 on failure
*/
-void aes_wrap(u8 *kek, int n, u8 *plain, u8 *cipher)
+int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher)
{
u8 *a, *r, b[16];
int i, j;
- AES_KEY key;
+ void *ctx;
a = cipher;
r = cipher + 8;
@@ -66,7 +52,9 @@ void aes_wrap(u8 *kek, int n, u8 *plain, u8 *cipher)
memset(a, 0xa6, 8);
memcpy(r, plain, 8 * n);
- AES_set_encrypt_key(kek, 128, &key);
+ ctx = aes_encrypt_init(kek, 16);
+ if (ctx == NULL)
+ return -1;
/* 2) Calculate intermediate values.
* For j = 0 to 5
@@ -80,40 +68,47 @@ void aes_wrap(u8 *kek, int n, u8 *plain, u8 *cipher)
for (i = 1; i <= n; i++) {
memcpy(b, a, 8);
memcpy(b + 8, r, 8);
- AES_encrypt(b, b, &key);
+ aes_encrypt(ctx, b, b);
memcpy(a, b, 8);
a[7] ^= n * j + i;
memcpy(r, b + 8, 8);
r += 8;
}
}
+ aes_encrypt_deinit(ctx);
/* 3) Output the results.
*
* These are already in @cipher due to the location of temporary
* variables.
*/
+
+ return 0;
}
-/*
- * @kek: key encryption key (KEK)
- * @n: length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes
- * @cipher: wrapped key to be unwrapped, (n + 1) * 64 bit
- * @plain: plaintext key, n * 64 bit
+/**
+ * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ * @kek: Key encryption key (KEK)
+ * @n: Length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes
+ * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bit
+ * @plain: Plaintext key, n * 64 bit
+ * Returns: 0 on success, -1 on failure (e.g., integrity verification failed)
*/
-int aes_unwrap(u8 *kek, int n, u8 *cipher, u8 *plain)
+int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain)
{
u8 a[8], *r, b[16];
int i, j;
- AES_KEY key;
+ void *ctx;
/* 1) Initialize variables. */
memcpy(a, cipher, 8);
r = plain;
memcpy(r, cipher + 8, 8 * n);
- AES_set_decrypt_key(kek, 128, &key);
+ ctx = aes_decrypt_init(kek, 16);
+ if (ctx == NULL)
+ return -1;
/* 2) Compute intermediate values.
* For j = 5 to 0
@@ -129,12 +124,13 @@ int aes_unwrap(u8 *kek, int n, u8 *cipher, u8 *plain)
b[7] ^= n * j + i;
memcpy(b + 8, r, 8);
- AES_decrypt(b, b, &key);
+ aes_decrypt(ctx, b, b);
memcpy(a, b, 8);
memcpy(r, b + 8, 8);
r -= 8;
}
}
+ aes_decrypt_deinit(ctx);
/* 3) Output results.
*
@@ -165,27 +161,37 @@ static void gf_mulx(u8 *pad)
}
-void omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
+/**
+ * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128
+ * @key: Key for the hash operation
+ * @data: Data buffer for which a MAC is determined
+ * @data: Length of data buffer in bytes
+ * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
+ * Returns: 0 on success, -1 on failure
+ */
+int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
{
- AES_KEY akey;
+ void *ctx;
u8 cbc[BLOCK_SIZE], pad[BLOCK_SIZE];
const u8 *pos = data;
int i;
size_t left = data_len;
- AES_set_encrypt_key(key, 128, &akey);
+ ctx = aes_encrypt_init(key, 16);
+ if (ctx == NULL)
+ return -1;
memset(cbc, 0, BLOCK_SIZE);
while (left >= BLOCK_SIZE) {
for (i = 0; i < BLOCK_SIZE; i++)
cbc[i] ^= *pos++;
if (left > BLOCK_SIZE)
- AES_encrypt(cbc, cbc, &akey);
+ aes_encrypt(ctx, cbc, cbc);
left -= BLOCK_SIZE;
}
memset(pad, 0, BLOCK_SIZE);
- AES_encrypt(pad, pad, &akey);
+ aes_encrypt(ctx, pad, pad);
gf_mulx(pad);
if (left || data_len == 0) {
@@ -197,32 +203,55 @@ void omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
for (i = 0; i < BLOCK_SIZE; i++)
pad[i] ^= cbc[i];
- AES_encrypt(pad, mac, &akey);
+ aes_encrypt(ctx, pad, mac);
+ aes_encrypt_deinit(ctx);
+ return 0;
}
-void aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out)
+/**
+ * aes_128_encrypt_block - Perform one AES 128-bit block operation
+ * @key: Key for AES
+ * @in: Input data (16 bytes)
+ * @out: Output of the AES block operation (16 bytes)
+ * Returns: 0 on success, -1 on failure
+ */
+int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out)
{
- AES_KEY akey;
- AES_set_encrypt_key(key, 128, &akey);
- AES_encrypt(in, out, &akey);
+ void *ctx;
+ ctx = aes_encrypt_init(key, 16);
+ if (ctx == NULL)
+ return -1;
+ aes_encrypt(ctx, in, out);
+ aes_encrypt_deinit(ctx);
+ return 0;
}
-void aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
- u8 *data, size_t data_len)
+/**
+ * aes_128_ctr_encrypt - AES-128 CTR mode encryption
+ * @key: Key for encryption (16 bytes)
+ * @nonce: Nonce for counter mode (16 bytes)
+ * @data: Data to encrypt in-place
+ * @data_len: Length of data in bytes
+ * Returns: 0 on success, -1 on failure
+ */
+int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
+ u8 *data, size_t data_len)
{
- AES_KEY akey;
+ void *ctx;
size_t len, left = data_len;
int i;
u8 *pos = data;
u8 counter[BLOCK_SIZE], buf[BLOCK_SIZE];
- AES_set_encrypt_key(key, 128, &akey);
+ ctx = aes_encrypt_init(key, 16);
+ if (ctx == NULL)
+ return -1;
memcpy(counter, nonce, BLOCK_SIZE);
while (left > 0) {
- AES_encrypt(counter, buf, &akey);
+ aes_encrypt(ctx, counter, buf);
len = (left < BLOCK_SIZE) ? left : BLOCK_SIZE;
for (i = 0; i < len; i++)
@@ -236,9 +265,23 @@ void aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
break;
}
}
+ aes_encrypt_deinit(ctx);
+ return 0;
}
+/**
+ * aes_128_eax_encrypt - AES-128 EAX mode encryption
+ * @key: Key for encryption (16 bytes)
+ * @nonce: Nonce for counter mode
+ * @nonce_len: Nonce length in bytes
+ * @hdr: Header data to be authenticity protected
+ * @hdr_len: Length of the header data bytes
+ * @data: Data to encrypt in-place
+ * @data_len: Length of data in bytes
+ * @tag: 16-byte tag value
+ * Returns: 0 on success, -1 on failure
+ */
int aes_128_eax_encrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
const u8 *hdr, size_t hdr_len,
u8 *data, size_t data_len, u8 *tag)
@@ -284,6 +327,18 @@ int aes_128_eax_encrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
}
+/**
+ * aes_128_eax_decrypt - AES-128 EAX mode decryption
+ * @key: Key for decryption (16 bytes)
+ * @nonce: Nonce for counter mode
+ * @nonce_len: Nonce length in bytes
+ * @hdr: Header data to be authenticity protected
+ * @hdr_len: Length of the header data bytes
+ * @data: Data to encrypt in-place
+ * @data_len: Length of data in bytes
+ * @tag: 16-byte tag value
+ * Returns: 0 on success, -1 on failure, -2 if tag does not match
+ */
int aes_128_eax_decrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
const u8 *hdr, size_t hdr_len,
u8 *data, size_t data_len, const u8 *tag)
@@ -332,48 +387,70 @@ int aes_128_eax_decrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
}
-void aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data,
- size_t data_len)
+/**
+ * aes_128_cbc_encrypt - AES-128 CBC encryption
+ * @key: Encryption key
+ * @iv: Encryption IV for CBC mode (16 bytes)
+ * @data: Data to encrypt in-place
+ * @data_len: Length of data in bytes (must be divisible by 16)
+ * Returns: 0 on success, -1 on failure
+ */
+int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
{
- AES_KEY akey;
+ void *ctx;
u8 cbc[BLOCK_SIZE];
u8 *pos = data;
int i, j, blocks;
- AES_set_encrypt_key(key, 128, &akey);
+ ctx = aes_encrypt_init(key, 16);
+ if (ctx == NULL)
+ return -1;
memcpy(cbc, iv, BLOCK_SIZE);
blocks = data_len / BLOCK_SIZE;
for (i = 0; i < blocks; i++) {
for (j = 0; j < BLOCK_SIZE; j++)
cbc[j] ^= pos[j];
- AES_encrypt(cbc, cbc, &akey);
+ aes_encrypt(ctx, cbc, cbc);
memcpy(pos, cbc, BLOCK_SIZE);
pos += BLOCK_SIZE;
}
+ aes_encrypt_deinit(ctx);
+ return 0;
}
-void aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data,
- size_t data_len)
+/**
+ * aes_128_cbc_decrypt - AES-128 CBC decryption
+ * @key: Decryption key
+ * @iv: Decryption IV for CBC mode (16 bytes)
+ * @data: Data to decrypt in-place
+ * @data_len: Length of data in bytes (must be divisible by 16)
+ * Returns: 0 on success, -1 on failure
+ */
+int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
{
- AES_KEY akey;
+ void *ctx;
u8 cbc[BLOCK_SIZE], tmp[BLOCK_SIZE];
u8 *pos = data;
int i, j, blocks;
- AES_set_decrypt_key(key, 128, &akey);
+ ctx = aes_decrypt_init(key, 16);
+ if (ctx == NULL)
+ return -1;
memcpy(cbc, iv, BLOCK_SIZE);
blocks = data_len / BLOCK_SIZE;
for (i = 0; i < blocks; i++) {
memcpy(tmp, pos, BLOCK_SIZE);
- AES_decrypt(pos, pos, &akey);
+ aes_decrypt(ctx, pos, pos);
for (j = 0; j < BLOCK_SIZE; j++)
pos[j] ^= cbc[j];
memcpy(cbc, tmp, BLOCK_SIZE);
pos += BLOCK_SIZE;
}
+ aes_decrypt_deinit(ctx);
+ return 0;
}
@@ -388,25 +465,28 @@ static void test_aes_perf(void)
const int num_iters = 10;
int i;
unsigned int start, end;
- AES_KEY akey;
u8 key[16], pt[16], ct[16];
+ void *ctx;
printf("keySetupEnc:");
for (i = 0; i < num_iters; i++) {
rdtscll(start);
- AES_set_encrypt_key(key, 128, &akey);
+ ctx = aes_encrypt_init(key, 16);
rdtscll(end);
+ aes_encrypt_deinit(ctx);
printf(" %d", end - start);
}
printf("\n");
printf("Encrypt:");
+ ctx = aes_encrypt_init(key, 16);
for (i = 0; i < num_iters; i++) {
rdtscll(start);
- AES_encrypt(pt, ct, &akey);
+ aes_encrypt(ctx, pt, ct);
rdtscll(end);
printf(" %d", end - start);
}
+ aes_encrypt_deinit(ctx);
printf("\n");
}
#endif /* __i386__ */
@@ -599,7 +679,10 @@ int main(int argc, char *argv[])
int ret = 0, i;
struct omac1_test_vector *tv;
- aes_wrap(kek, 2, plain, result);
+ if (aes_wrap(kek, 2, plain, result)) {
+ printf("AES-WRAP-128-128 reported failure\n");
+ ret++;
+ }
if (memcmp(result, crypt, 24) != 0) {
printf("AES-WRAP-128-128 failed\n");
ret++;
diff --git a/contrib/wpa_supplicant/aes_wrap.h b/contrib/wpa_supplicant/aes_wrap.h
index 70e83ea09d73..cb1a53967761 100644
--- a/contrib/wpa_supplicant/aes_wrap.h
+++ b/contrib/wpa_supplicant/aes_wrap.h
@@ -1,21 +1,42 @@
+/*
+ * AES-based functions
+ *
+ * - AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ * - One-Key CBC MAC (OMAC1) hash with AES-128
+ * - AES-128 CTR mode encryption
+ * - AES-128 EAX mode encryption/decryption
+ * - AES-128 CBC
+ *
+ * Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
#ifndef AES_WRAP_H
#define AES_WRAP_H
-void aes_wrap(u8 *kek, int n, u8 *plain, u8 *cipher);
-int aes_unwrap(u8 *kek, int n, u8 *cipher, u8 *plain);
-void omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac);
-void aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out);
-void aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
- u8 *data, size_t data_len);
+int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher);
+int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain);
+int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac);
+int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out);
+int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
+ u8 *data, size_t data_len);
int aes_128_eax_encrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
const u8 *hdr, size_t hdr_len,
u8 *data, size_t data_len, u8 *tag);
int aes_128_eax_decrypt(const u8 *key, const u8 *nonce, size_t nonce_len,
const u8 *hdr, size_t hdr_len,
u8 *data, size_t data_len, const u8 *tag);
-void aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data,
- size_t data_len);
-void aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data,
- size_t data_len);
+int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data,
+ size_t data_len);
+int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data,
+ size_t data_len);
#endif /* AES_WRAP_H */
diff --git a/contrib/wpa_supplicant/base64.c b/contrib/wpa_supplicant/base64.c
new file mode 100644
index 000000000000..2717e30c6980
--- /dev/null
+++ b/contrib/wpa_supplicant/base64.c
@@ -0,0 +1,198 @@
+/*
+ * Base64 encoding/decoding (RFC1341)
+ * Copyright (c) 2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "base64.h"
+
+static const unsigned char base64_table[64] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/**
+ * base64_encode - Base64 encode
+ * @src: Data to be encoded
+ * @len: Length of the data to be encoded
+ * @out_len: Pointer to output length variable, or %NULL if not used
+ * Returns: Allocated buffer of out_len bytes of encoded data,
+ * or %NULL on failure
+ *
+ * Caller is responsible for freeing the returned buffer. Returned buffer is
+ * nul terminated to make it easier to use as a C string. The nul terminator is
+ * not included in out_len.
+ */
+unsigned char * base64_encode(const unsigned char *src, size_t len,
+ size_t *out_len)
+{
+ unsigned char *out, *pos;
+ const unsigned char *end, *in;
+ size_t olen;
+ int line_len;
+
+ olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */
+ olen += olen / 72; /* line feeds */
+ olen++; /* nul termination */
+ out = malloc(olen);
+ if (out == NULL)
+ return NULL;
+
+ end = src + len;
+ in = src;
+ pos = out;
+ line_len = 0;
+ while (end - in >= 3) {
+ *pos++ = base64_table[in[0] >> 2];
+ *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
+ *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)];
+ *pos++ = base64_table[in[2] & 0x3f];
+ in += 3;
+ line_len += 4;
+ if (line_len >= 72) {
+ *pos++ = '\n';
+ line_len = 0;
+ }
+ }
+
+ if (end - in) {
+ *pos++ = base64_table[in[0] >> 2];
+ if (end - in == 1) {
+ *pos++ = base64_table[(in[0] & 0x03) << 4];
+ *pos++ = '=';
+ } else {
+ *pos++ = base64_table[((in[0] & 0x03) << 4) |
+ (in[1] >> 4)];
+ *pos++ = base64_table[(in[1] & 0x0f) << 2];
+ }
+ *pos++ = '=';
+ line_len += 4;
+ }
+
+ if (line_len)
+ *pos++ = '\n';
+
+ *pos = '\0';
+ if (out_len)
+ *out_len = pos - out;
+ return out;
+}
+
+
+/**
+ * base64_decode - Base64 decode
+ * @src: Data to be decoded
+ * @len: Length of the data to be decoded
+ * @out_len: Pointer to output length variable
+ * Returns: Allocated buffer of out_len bytes of decoded data,
+ * or %NULL on failure
+ *
+ * Caller is responsible for freeing the returned buffer.
+ */
+unsigned char * base64_decode(const unsigned char *src, size_t len,
+ size_t *out_len)
+{
+ unsigned char dtable[256], *out, *pos, in[4], block[4], tmp;
+ size_t i, count, olen;
+
+ memset(dtable, 0x80, 256);
+ for (i = 0; i < sizeof(base64_table); i++)
+ dtable[base64_table[i]] = i;
+ dtable['='] = 0;
+
+ count = 0;
+ for (i = 0; i < len; i++) {
+ if (dtable[src[i]] != 0x80)
+ count++;
+ }
+
+ if (count % 4)
+ return NULL;
+
+ olen = count / 4 * 3;
+ pos = out = malloc(count);
+ if (out == NULL)
+ return NULL;
+
+ count = 0;
+ for (i = 0; i < len; i++) {
+ tmp = dtable[src[i]];
+ if (tmp == 0x80)
+ continue;
+
+ in[count] = src[i];
+ block[count] = tmp;
+ count++;
+ if (count == 4) {
+ *pos++ = (block[0] << 2) | (block[1] >> 4);
+ *pos++ = (block[1] << 4) | (block[2] >> 2);
+ *pos++ = (block[2] << 6) | block[3];
+ count = 0;
+ }
+ }
+
+ if (pos > out) {
+ if (in[2] == '=')
+ pos -= 2;
+ else if (in[3] == '=')
+ pos--;
+ }
+
+ *out_len = pos - out;
+ return out;
+}
+
+
+#ifdef TEST_MAIN
+#include <stdio.h>
+
+int main(int argc, char *argv[])
+{
+ FILE *f;
+ size_t len, elen;
+ unsigned char *buf, *e;
+
+ if (argc != 4) {
+ printf("Usage: base64 <encode|decode> <in file> <out file>\n");
+ return -1;
+ }
+
+ f = fopen(argv[2], "r");
+ if (f == NULL)
+ return -1;
+ fseek(f, 0, SEEK_END);
+ len = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ buf = malloc(len);
+ if (buf == NULL) {
+ fclose(f);
+ return -1;
+ }
+ fread(buf, 1, len, f);
+ fclose(f);
+
+ if (strcmp(argv[1], "encode") == 0)
+ e = base64_encode(buf, len, &elen);
+ else
+ e = base64_decode(buf, len, &elen);
+ if (e == NULL)
+ return -2;
+ f = fopen(argv[3], "w");
+ if (f == NULL)
+ return -3;
+ fwrite(e, 1, elen, f);
+ fclose(f);
+ free(e);
+
+ return 0;
+}
+#endif /* TEST_MAIN */
diff --git a/contrib/wpa_supplicant/base64.h b/contrib/wpa_supplicant/base64.h
new file mode 100644
index 000000000000..7043328f678e
--- /dev/null
+++ b/contrib/wpa_supplicant/base64.h
@@ -0,0 +1,23 @@
+/*
+ * Base64 encoding/decoding (RFC1341)
+ * Copyright (c) 2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef BASE64_H
+#define BASE64_h
+
+unsigned char * base64_encode(const unsigned char *src, size_t len,
+ size_t *out_len);
+unsigned char * base64_decode(const unsigned char *src, size_t len,
+ size_t *out_len);
+
+#endif /* BASE64_H */
diff --git a/contrib/wpa_supplicant/common.c b/contrib/wpa_supplicant/common.c
index 071ffe87c1d1..4b756d8f9292 100644
--- a/contrib/wpa_supplicant/common.c
+++ b/contrib/wpa_supplicant/common.c
@@ -1,6 +1,5 @@
/*
- * Host AP (software wireless LAN access point) user space daemon for
- * Host AP kernel driver / common helper functions, etc.
+ * wpa_supplicant/hostapd / common helper functions, etc.
* Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
*
* This program is free software; you can redistribute it and/or modify
@@ -22,6 +21,10 @@
#include <ctype.h>
#include <time.h>
#include <sys/time.h>
+#ifdef CONFIG_NATIVE_WINDOWS
+#include <winsock2.h>
+#include <wincrypt.h>
+#endif /* CONFIG_NATIVE_WINDOWS */
#include "common.h"
@@ -34,12 +37,17 @@ int wpa_debug_timestamp = 0;
int hostapd_get_rand(u8 *buf, size_t len)
{
#ifdef CONFIG_NATIVE_WINDOWS
- int i;
- /* FIX: use more secure pseudo random number generator */
- for (i = 0; i < len; i++) {
- buf[i] = rand();
- }
- return 0;
+ HCRYPTPROV prov;
+ BOOL ret;
+
+ if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT))
+ return -1;
+
+ ret = CryptGenRandom(prov, len, buf);
+ CryptReleaseContext(prov, 0);
+
+ return ret ? 0 : -1;
#else /* CONFIG_NATIVE_WINDOWS */
FILE *f;
size_t rc;
@@ -93,6 +101,12 @@ static int hex2byte(const char *hex)
}
+/**
+ * hwaddr_aton - Convert ASCII string to MAC address
+ * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
+ * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
+ * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
+ */
int hwaddr_aton(const char *txt, u8 *addr)
{
int i;
@@ -115,6 +129,14 @@ int hwaddr_aton(const char *txt, u8 *addr)
}
+/**
+ * hexstr2bin - Convert ASCII hex string into binary data
+ * @hex: ASCII hex string (e.g., "01ab")
+ * @buf: Buffer for the binary data
+ * @len: Length of the text to convert in bytes (of buf); hex will be double
+ * this size
+ * Returns: 0 on success, -1 on failure (invalid hex string)
+ */
int hexstr2bin(const char *hex, u8 *buf, size_t len)
{
int i, a;
@@ -171,6 +193,15 @@ char * rel2abs_path(const char *rel_path)
}
+/**
+ * inc_byte_array - Increment arbitrary length byte array by one
+ * @counter: Pointer to byte array
+ * @len: Length of the counter in bytes
+ *
+ * This function increments the last byte of the counter by one and continues
+ * rolling over to more significant bytes if the byte was incremented from
+ * 0xff to 0x00.
+ */
void inc_byte_array(u8 *counter, size_t len)
{
int pos = len - 1;
@@ -201,7 +232,9 @@ void fprint_char(FILE *f, char c)
}
-static void wpa_debug_print_timestamp(void)
+#ifndef CONFIG_NO_STDOUT_DEBUG
+
+void wpa_debug_print_timestamp(void)
{
struct timeval tv;
char buf[16];
@@ -218,6 +251,17 @@ static void wpa_debug_print_timestamp(void)
}
+/**
+ * wpa_printf - conditional printf
+ * @level: priority level (MSG_*) of the message
+ * @fmt: printf format string, followed by optional arguments
+ *
+ * This function is used to print conditional debugging and error messages. The
+ * output may be directed to stdout, stderr, and/or syslog based on
+ * configuration.
+ *
+ * Note: New line '\n' is added to the end of the text when printing to stdout.
+ */
void wpa_printf(int level, char *fmt, ...)
{
va_list ap;
@@ -240,7 +284,9 @@ static void _wpa_hexdump(int level, const char *title, const u8 *buf,
return;
wpa_debug_print_timestamp();
printf("%s - hexdump(len=%lu):", title, (unsigned long) len);
- if (show) {
+ if (buf == NULL) {
+ printf(" [NULL]");
+ } else if (show) {
for (i = 0; i < len; i++)
printf(" %02x", buf[i]);
} else {
@@ -276,6 +322,11 @@ static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
title, (unsigned long) len);
return;
}
+ if (buf == NULL) {
+ printf("%s - hexdump_ascii(len=%lu): [NULL]\n",
+ title, (unsigned long) len);
+ return;
+ }
printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len);
while (len) {
llen = len > line_len ? line_len : len;
@@ -312,6 +363,8 @@ void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
_wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
}
+#endif /* CONFIG_NO_STDOUT_DEBUG */
+
#ifdef CONFIG_NATIVE_WINDOWS
diff --git a/contrib/wpa_supplicant/common.h b/contrib/wpa_supplicant/common.h
index 0f154e901bff..4bece7f6ecd9 100644
--- a/contrib/wpa_supplicant/common.h
+++ b/contrib/wpa_supplicant/common.h
@@ -1,11 +1,26 @@
+/*
+ * wpa_supplicant/hostapd / common helper functions, etc.
+ * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
#ifndef COMMON_H
#define COMMON_H
#ifdef __linux__
#include <endian.h>
#include <byteswap.h>
-#endif
-#ifdef __FreeBSD__
+#endif /* __linux__ */
+
+#if defined(__FreeBSD__) || defined(__NetBSD__)
#include <sys/types.h>
#include <sys/endian.h>
#define __BYTE_ORDER _BYTE_ORDER
@@ -14,10 +29,9 @@
#define bswap_16 bswap16
#define bswap_32 bswap32
#define bswap_64 bswap64
-#endif
+#endif /* defined(__FreeBSD__) || defined(__NetBSD__) */
#ifdef CONFIG_NATIVE_WINDOWS
-#include <winsock.h>
#include <winsock2.h>
static inline int daemon(int nochdir, int noclose)
@@ -54,6 +68,18 @@ struct timezone {
int gettimeofday(struct timeval *tv, struct timezone *tz);
+static inline long int random(void)
+{
+ return rand();
+}
+
+typedef int gid_t;
+typedef int socklen_t;
+
+#ifndef MSG_DONTWAIT
+#define MSG_DONTWAIT 0 /* not supported */
+#endif
+
#endif /* CONFIG_NATIVE_WINDOWS */
#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS)
@@ -104,6 +130,21 @@ static inline unsigned int wpa_swap_32(unsigned int v)
#endif /* __CYGWIN__ */
+/* Macros for handling unaligned 16-bit variables */
+#define WPA_GET_BE16(a) ((u16) (((a)[0] << 8) | (a)[1]))
+#define WPA_PUT_BE16(a, val) \
+ do { \
+ (a)[0] = ((u16) (val)) >> 8; \
+ (a)[1] = ((u16) (val)) & 0xff; \
+ } while (0)
+
+#define WPA_GET_LE16(a) ((u16) (((a)[1] << 8) | (a)[0]))
+#define WPA_PUT_LE16(a, val) \
+ do { \
+ (a)[1] = ((u16) (val)) >> 8; \
+ (a)[0] = ((u16) (val)) & 0xff; \
+ } while (0)
+
#ifndef ETH_ALEN
#define ETH_ALEN 6
@@ -134,6 +175,26 @@ void fprint_char(FILE *f, char c);
enum { MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR };
+#ifdef CONFIG_NO_STDOUT_DEBUG
+
+#define wpa_debug_print_timestamp() do { } while (0)
+#define wpa_printf(args...) do { } while (0)
+#define wpa_hexdump(args...) do { } while (0)
+#define wpa_hexdump_key(args...) do { } while (0)
+#define wpa_hexdump_ascii(args...) do { } while (0)
+#define wpa_hexdump_ascii_key(args...) do { } while (0)
+
+#else /* CONFIG_NO_STDOUT_DEBUG */
+
+/**
+ * wpa_debug_printf_timestamp - Print timestamp for debug output
+ *
+ * This function prints a timestamp in <seconds from 1970>.<microsoconds>
+ * format if debug output has been configured to include timestamps in debug
+ * messages.
+ */
+void wpa_debug_print_timestamp(void);
+
/**
* wpa_printf - conditional printf
* @level: priority level (MSG_*) of the message
@@ -153,11 +214,11 @@ __attribute__ ((format (printf, 2, 3)));
* @level: priority level (MSG_*) of the message
* @title: title of for the message
* @buf: data buffer to be dumped
- * @len: length of the @buf
+ * @len: length of the buf
*
* This function is used to print conditional debugging and error messages. The
* output may be directed to stdout, stderr, and/or syslog based on
- * configuration. The contents of @buf is printed out has hex dump.
+ * configuration. The contents of buf is printed out has hex dump.
*/
void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len);
@@ -166,11 +227,11 @@ void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len);
* @level: priority level (MSG_*) of the message
* @title: title of for the message
* @buf: data buffer to be dumped
- * @len: length of the @buf
+ * @len: length of the buf
*
* This function is used to print conditional debugging and error messages. The
* output may be directed to stdout, stderr, and/or syslog based on
- * configuration. The contents of @buf is printed out has hex dump. This works
+ * configuration. The contents of buf is printed out has hex dump. This works
* like wpa_hexdump(), but by default, does not include secret keys (passwords,
* etc.) in debug output.
*/
@@ -181,11 +242,11 @@ void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len);
* @level: priority level (MSG_*) of the message
* @title: title of for the message
* @buf: data buffer to be dumped
- * @len: length of the @buf
+ * @len: length of the buf
*
* This function is used to print conditional debugging and error messages. The
* output may be directed to stdout, stderr, and/or syslog based on
- * configuration. The contents of @buf is printed out has hex dump with both
+ * configuration. The contents of buf is printed out has hex dump with both
* the hex numbers and ASCII characters (for printable range) are shown. 16
* bytes per line will be shown.
*/
@@ -197,11 +258,11 @@ void wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
* @level: priority level (MSG_*) of the message
* @title: title of for the message
* @buf: data buffer to be dumped
- * @len: length of the @buf
+ * @len: length of the buf
*
* This function is used to print conditional debugging and error messages. The
* output may be directed to stdout, stderr, and/or syslog based on
- * configuration. The contents of @buf is printed out has hex dump with both
+ * configuration. The contents of buf is printed out has hex dump with both
* the hex numbers and ASCII characters (for printable range) are shown. 16
* bytes per line will be shown. This works like wpa_hexdump_ascii(), but by
* default, does not include secret keys (passwords, etc.) in debug output.
@@ -209,6 +270,9 @@ void wpa_hexdump_ascii(int level, const char *title, const u8 *buf,
void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf,
size_t len);
+#endif /* CONFIG_NO_STDOUT_DEBUG */
+
+
#ifdef EAPOL_TEST
#define WPA_ASSERT(a) \
do { \
diff --git a/contrib/wpa_supplicant/config.c b/contrib/wpa_supplicant/config.c
index 26307cf3f80b..2bba4ab22171 100644
--- a/contrib/wpa_supplicant/config.c
+++ b/contrib/wpa_supplicant/config.c
@@ -1,5 +1,5 @@
/*
- * WPA Supplicant / Configuration file parser
+ * WPA Supplicant / Configuration parser and common functions
* Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi>
*
* This program is free software; you can redistribute it and/or modify
@@ -18,63 +18,40 @@
#include "common.h"
#include "wpa.h"
-#include "config.h"
#include "sha1.h"
#include "wpa_supplicant.h"
#include "eapol_sm.h"
#include "eap.h"
+#include "l2_packet.h"
#include "config.h"
+/*
+ * Structure for network configuration parsing. This data is used to implement
+ * a generic parser for each network block variable. The table of configuration
+ * variables is defined below in this file (ssid_fields[]).
+ */
struct parse_data {
+ /* Configuration variable name */
char *name;
- int (*parser)(struct parse_data *data, int line, const char *value);
- void *param1, *param2, *param3, *param4;
- struct wpa_ssid *ssid;
- int key_data;
-};
+ /* Parser function for this variable */
+ int (*parser)(const struct parse_data *data, struct wpa_ssid *ssid,
+ int line, const char *value);
-static char * wpa_config_get_line(char *s, int size, FILE *stream, int *line)
-{
- char *pos, *end, *sstart;
-
- while (fgets(s, size, stream)) {
- (*line)++;
- s[size - 1] = '\0';
- pos = s;
-
- while (*pos == ' ' || *pos == '\t' || *pos == '\r')
- pos++;
- if (*pos == '#' || *pos == '\n' || *pos == '\0' ||
- *pos == '\r')
- continue;
-
- /* Remove # comments unless they are within a double quoted
- * string. Remove trailing white space. */
- sstart = strchr(pos, '"');
- if (sstart)
- sstart = strchr(sstart + 1, '"');
- if (!sstart)
- sstart = pos;
- end = strchr(sstart, '#');
- if (end)
- *end-- = '\0';
- else
- end = pos + strlen(pos) - 1;
- while (end > pos &&
- (*end == '\n' || *end == ' ' || *end == '\t' ||
- *end == '\r')) {
- *end-- = '\0';
- }
- if (*pos == '\0')
- continue;
+ /* Writer function (i.e., to get the variable in text format from
+ * internal presentation). */
+ char * (*writer)(const struct parse_data *data, struct wpa_ssid *ssid);
- return pos;
- }
+ /* Variable specific parameters for the parser. */
+ void *param1, *param2, *param3, *param4;
- return NULL;
-}
+ /* 0 = this variable can be included in debug output
+ * 1 = this variable contains key/private data and it must not be
+ * included in debug output unless explicitly requested
+ */
+ int key_data;
+};
static char * wpa_config_parse_string(const char *value, size_t *len)
@@ -90,7 +67,7 @@ static char * wpa_config_parse_string(const char *value, size_t *len)
return strdup(value);
} else {
u8 *str;
- int hlen = strlen(value);
+ size_t hlen = strlen(value);
if (hlen % 1)
return NULL;
*len = hlen / 2;
@@ -106,14 +83,15 @@ static char * wpa_config_parse_string(const char *value, size_t *len)
}
-static int wpa_config_parse_str(struct parse_data *data,
+static int wpa_config_parse_str(const struct parse_data *data,
+ struct wpa_ssid *ssid,
int line, const char *value)
{
size_t res_len, *dst_len;
char **dst;
- dst = (char **) (((u8 *) data->ssid) + (long) data->param1);
- dst_len = (size_t *) (((u8 *) data->ssid) + (long) data->param2);
+ dst = (char **) (((u8 *) ssid) + (long) data->param1);
+ dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2);
free(*dst);
*dst = wpa_config_parse_string(value, &res_len);
@@ -155,12 +133,91 @@ static int wpa_config_parse_str(struct parse_data *data,
}
-static int wpa_config_parse_int(struct parse_data *data,
+static int is_hex(const u8 *data, size_t len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (data[i] < 32 || data[i] >= 127)
+ return 1;
+ }
+ return 0;
+}
+
+
+static char * wpa_config_write_string_ascii(const u8 *value, size_t len)
+{
+ int i;
+ char *buf, *pos, *end;
+
+ pos = buf = malloc(len + 3);
+ if (buf == NULL)
+ return NULL;
+ end = buf + len + 3;
+ pos += snprintf(pos, end - pos, "\"");
+ for (i = 0; i < len; i++)
+ pos += snprintf(pos, end - pos, "%c", value[i]);
+ pos += snprintf(pos, end - pos, "\"");
+
+ return buf;
+}
+
+
+static char * wpa_config_write_string_hex(const u8 *value, size_t len)
+{
+ int i;
+ char *buf, *pos, *end;
+
+ pos = buf = malloc(2 * len + 1);
+ if (buf == NULL)
+ return NULL;
+ memset(buf, 0, 2 * len + 1);
+ end = buf + 2 * len + 1;
+ for (i = 0; i < len; i++)
+ pos += snprintf(pos, end - pos, "%02x", value[i]);
+
+ return buf;
+}
+
+
+static char * wpa_config_write_string(const u8 *value, size_t len)
+{
+ if (value == NULL)
+ return NULL;
+
+ if (is_hex(value, len))
+ return wpa_config_write_string_hex(value, len);
+ else
+ return wpa_config_write_string_ascii(value, len);
+}
+
+
+static char * wpa_config_write_str(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ size_t len;
+ char **src;
+
+ src = (char **) (((u8 *) ssid) + (long) data->param1);
+ if (*src == NULL)
+ return NULL;
+
+ if (data->param2)
+ len = *((size_t *) (((u8 *) ssid) + (long) data->param2));
+ else
+ len = strlen(*src);
+
+ return wpa_config_write_string((const u8 *) *src, len);
+}
+
+
+static int wpa_config_parse_int(const struct parse_data *data,
+ struct wpa_ssid *ssid,
int line, const char *value)
{
int *dst;
- dst = (int *) (((u8 *) data->ssid) + (long) data->param1);
+ dst = (int *) (((u8 *) ssid) + (long) data->param1);
*dst = atoi(value);
wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst);
@@ -184,26 +241,60 @@ static int wpa_config_parse_int(struct parse_data *data,
}
-static int wpa_config_parse_bssid(struct parse_data *data, int line,
+static char * wpa_config_write_int(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ int *src;
+ char *value;
+
+ src = (int *) (((u8 *) ssid) + (long) data->param1);
+
+ value = malloc(20);
+ if (value == NULL)
+ return NULL;
+ snprintf(value, 20, "%d", *src);
+ return value;
+}
+
+
+static int wpa_config_parse_bssid(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
const char *value)
{
- if (hwaddr_aton(value, data->ssid->bssid)) {
+ if (hwaddr_aton(value, ssid->bssid)) {
wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID '%s'.",
line, value);
return -1;
}
- data->ssid->bssid_set = 1;
- wpa_hexdump(MSG_MSGDUMP, "BSSID", data->ssid->bssid, ETH_ALEN);
+ ssid->bssid_set = 1;
+ wpa_hexdump(MSG_MSGDUMP, "BSSID", ssid->bssid, ETH_ALEN);
return 0;
}
-static int wpa_config_parse_psk(struct parse_data *data, int line,
+static char * wpa_config_write_bssid(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ char *value;
+
+ if (!ssid->bssid_set)
+ return NULL;
+
+ value = malloc(20);
+ if (value == NULL)
+ return NULL;
+ snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid));
+ return value;
+}
+
+
+static int wpa_config_parse_psk(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
const char *value)
{
if (*value == '"') {
char *pos;
- int len;
+ size_t len;
value++;
pos = strrchr(value, '"');
@@ -212,29 +303,45 @@ static int wpa_config_parse_psk(struct parse_data *data, int line,
len = strlen(value);
if (len < 8 || len > 63) {
wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase "
- "length %d (expected: 8..63) '%s'.",
- line, len, value);
+ "length %lu (expected: 8..63) '%s'.",
+ line, (unsigned long) len, value);
return -1;
}
wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)",
(u8 *) value, len);
- data->ssid->passphrase = strdup(value);
- return data->ssid->passphrase == NULL ? -1 : 0;
+ ssid->passphrase = strdup(value);
+ return ssid->passphrase == NULL ? -1 : 0;
}
- if (hexstr2bin(value, data->ssid->psk, PMK_LEN) ||
+ if (hexstr2bin(value, ssid->psk, PMK_LEN) ||
value[PMK_LEN * 2] != '\0') {
wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
line, value);
return -1;
}
- data->ssid->psk_set = 1;
- wpa_hexdump_key(MSG_MSGDUMP, "PSK", data->ssid->psk, PMK_LEN);
+ ssid->psk_set = 1;
+ wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN);
return 0;
}
-static int wpa_config_parse_proto(struct parse_data *data, int line,
+static char * wpa_config_write_psk(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ if (ssid->passphrase)
+ return wpa_config_write_string_ascii(
+ (const u8 *) ssid->passphrase,
+ strlen(ssid->passphrase));
+
+ if (ssid->psk_set)
+ return wpa_config_write_string_hex(ssid->psk, PMK_LEN);
+
+ return NULL;
+}
+
+
+static int wpa_config_parse_proto(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
const char *value)
{
int val = 0, last, errors = 0;
@@ -279,12 +386,39 @@ static int wpa_config_parse_proto(struct parse_data *data, int line,
}
wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val);
- data->ssid->proto = val;
+ ssid->proto = val;
return errors ? -1 : 0;
}
-static int wpa_config_parse_key_mgmt(struct parse_data *data, int line,
+static char * wpa_config_write_proto(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ int first = 1;
+ char *buf, *pos, *end;
+
+ pos = buf = malloc(10);
+ if (buf == NULL)
+ return NULL;
+ memset(buf, 0, 10);
+ end = buf + 10;
+
+ if (ssid->proto & WPA_PROTO_WPA) {
+ pos += snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
+ first = 0;
+ }
+
+ if (ssid->proto & WPA_PROTO_RSN) {
+ pos += snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
+ first = 0;
+ }
+
+ return buf;
+}
+
+
+static int wpa_config_parse_key_mgmt(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
const char *value)
{
int val = 0, last, errors = 0;
@@ -334,11 +468,54 @@ static int wpa_config_parse_key_mgmt(struct parse_data *data, int line,
}
wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val);
- data->ssid->key_mgmt = val;
+ ssid->key_mgmt = val;
return errors ? -1 : 0;
}
+static char * wpa_config_write_key_mgmt(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ int first = 1;
+ char *buf, *pos, *end;
+
+ pos = buf = malloc(50);
+ if (buf == NULL)
+ return NULL;
+ memset(buf, 0, 50);
+ end = buf + 50;
+
+ if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
+ pos += snprintf(pos, end - pos, "%sWPA-PSK", first ? "" : " ");
+ first = 0;
+ }
+
+ if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
+ pos += snprintf(pos, end - pos, "%sWPA-EAP", first ? "" : " ");
+ first = 0;
+ }
+
+ if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
+ pos += snprintf(pos, end - pos, "%sIEEE8021X",
+ first ? "" : " ");
+ first = 0;
+ }
+
+ if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) {
+ pos += snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
+ first = 0;
+ }
+
+ if (ssid->key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
+ pos += snprintf(pos, end - pos, "%sWPA-NONE",
+ first ? "" : " ");
+ first = 0;
+ }
+
+ return buf;
+}
+
+
static int wpa_config_parse_cipher(int line, const char *value)
{
int val = 0, last;
@@ -391,7 +568,48 @@ static int wpa_config_parse_cipher(int line, const char *value)
}
-static int wpa_config_parse_pairwise(struct parse_data *data, int line,
+static char * wpa_config_write_cipher(int cipher)
+{
+ int first = 1;
+ char *buf, *pos, *end;
+
+ pos = buf = malloc(50);
+ if (buf == NULL)
+ return NULL;
+ memset(buf, 0, 50);
+ end = buf + 50;
+
+ if (cipher & WPA_CIPHER_CCMP) {
+ pos += snprintf(pos, end - pos, "%sCCMP", first ? "" : " ");
+ first = 0;
+ }
+
+ if (cipher & WPA_CIPHER_TKIP) {
+ pos += snprintf(pos, end - pos, "%sTKIP", first ? "" : " ");
+ first = 0;
+ }
+
+ if (cipher & WPA_CIPHER_WEP104) {
+ pos += snprintf(pos, end - pos, "%sWEP104", first ? "" : " ");
+ first = 0;
+ }
+
+ if (cipher & WPA_CIPHER_WEP40) {
+ pos += snprintf(pos, end - pos, "%sWEP40", first ? "" : " ");
+ first = 0;
+ }
+
+ if (cipher & WPA_CIPHER_NONE) {
+ pos += snprintf(pos, end - pos, "%sNONE", first ? "" : " ");
+ first = 0;
+ }
+
+ return buf;
+}
+
+
+static int wpa_config_parse_pairwise(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
const char *value)
{
int val;
@@ -405,12 +623,20 @@ static int wpa_config_parse_pairwise(struct parse_data *data, int line,
}
wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val);
- data->ssid->pairwise_cipher = val;
+ ssid->pairwise_cipher = val;
return 0;
}
-static int wpa_config_parse_group(struct parse_data *data, int line,
+static char * wpa_config_write_pairwise(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ return wpa_config_write_cipher(ssid->pairwise_cipher);
+}
+
+
+static int wpa_config_parse_group(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
const char *value)
{
int val;
@@ -425,12 +651,20 @@ static int wpa_config_parse_group(struct parse_data *data, int line,
}
wpa_printf(MSG_MSGDUMP, "group: 0x%x", val);
- data->ssid->group_cipher = val;
+ ssid->group_cipher = val;
return 0;
}
-static int wpa_config_parse_auth_alg(struct parse_data *data, int line,
+static char * wpa_config_write_group(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ return wpa_config_write_cipher(ssid->group_cipher);
+}
+
+
+static int wpa_config_parse_auth_alg(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
const char *value)
{
int val = 0, last, errors = 0;
@@ -476,12 +710,44 @@ static int wpa_config_parse_auth_alg(struct parse_data *data, int line,
}
wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val);
- data->ssid->auth_alg = val;
+ ssid->auth_alg = val;
return errors ? -1 : 0;
}
-static int wpa_config_parse_eap(struct parse_data *data, int line,
+static char * wpa_config_write_auth_alg(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ int first = 1;
+ char *buf, *pos, *end;
+
+ pos = buf = malloc(30);
+ if (buf == NULL)
+ return NULL;
+ memset(buf, 0, 30);
+ end = buf + 30;
+
+ if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) {
+ pos += snprintf(pos, end - pos, "%sOPEN", first ? "" : " ");
+ first = 0;
+ }
+
+ if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) {
+ pos += snprintf(pos, end - pos, "%sSHARED", first ? "" : " ");
+ first = 0;
+ }
+
+ if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) {
+ pos += snprintf(pos, end - pos, "%sLEAP", first ? "" : " ");
+ first = 0;
+ }
+
+ return buf;
+}
+
+
+static int wpa_config_parse_eap(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
const char *value)
{
int last, errors = 0;
@@ -520,9 +786,9 @@ static int wpa_config_parse_eap(struct parse_data *data, int line,
"See README for more information.");
errors++;
} else if (methods[num_methods] == EAP_TYPE_LEAP)
- data->ssid->leap++;
+ ssid->leap++;
else
- data->ssid->non_leap++;
+ ssid->non_leap++;
num_methods++;
if (last)
break;
@@ -540,11 +806,41 @@ static int wpa_config_parse_eap(struct parse_data *data, int line,
num_methods++;
wpa_hexdump(MSG_MSGDUMP, "eap methods", methods, num_methods);
- data->ssid->eap_methods = methods;
+ ssid->eap_methods = methods;
return errors ? -1 : 0;
}
+static char * wpa_config_write_eap(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ int first = 1;
+ char *buf, *pos, *end;
+ const u8 *eap_methods = ssid->eap_methods;
+ const char *name;
+
+ if (eap_methods == NULL)
+ return NULL;
+
+ pos = buf = malloc(100);
+ if (buf == NULL)
+ return NULL;
+ memset(buf, 0, 100);
+ end = buf + 100;
+
+ while (*eap_methods != EAP_TYPE_NONE) {
+ name = eap_get_name(*eap_methods);
+ if (name)
+ pos += snprintf(pos, end - pos, "%s%s",
+ first ? "" : " ", name);
+ first = 0;
+ eap_methods++;
+ }
+
+ return buf;
+}
+
+
static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line,
const char *value, int idx)
{
@@ -570,54 +866,140 @@ static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line,
}
-static int wpa_config_parse_wep_key0(struct parse_data *data, int line,
+static int wpa_config_parse_wep_key0(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
const char *value)
{
- return wpa_config_parse_wep_key(data->ssid->wep_key[0],
- &data->ssid->wep_key_len[0], line,
+ return wpa_config_parse_wep_key(ssid->wep_key[0],
+ &ssid->wep_key_len[0], line,
value, 0);
}
-static int wpa_config_parse_wep_key1(struct parse_data *data, int line,
+static int wpa_config_parse_wep_key1(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
const char *value)
{
- return wpa_config_parse_wep_key(data->ssid->wep_key[1],
- &data->ssid->wep_key_len[1], line,
+ return wpa_config_parse_wep_key(ssid->wep_key[1],
+ &ssid->wep_key_len[1], line,
value, 1);
}
-static int wpa_config_parse_wep_key2(struct parse_data *data, int line,
+static int wpa_config_parse_wep_key2(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
const char *value)
{
- return wpa_config_parse_wep_key(data->ssid->wep_key[2],
- &data->ssid->wep_key_len[2], line,
+ return wpa_config_parse_wep_key(ssid->wep_key[2],
+ &ssid->wep_key_len[2], line,
value, 2);
}
-static int wpa_config_parse_wep_key3(struct parse_data *data, int line,
+static int wpa_config_parse_wep_key3(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
const char *value)
{
- return wpa_config_parse_wep_key(data->ssid->wep_key[3],
- &data->ssid->wep_key_len[3], line,
+ return wpa_config_parse_wep_key(ssid->wep_key[3],
+ &ssid->wep_key_len[3], line,
value, 3);
}
+static char * wpa_config_write_wep_key(struct wpa_ssid *ssid, int idx)
+{
+ if (ssid->wep_key_len[idx] == 0)
+ return NULL;
+ return wpa_config_write_string(ssid->wep_key[idx],
+ ssid->wep_key_len[idx]);
+}
+
+
+static char * wpa_config_write_wep_key0(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ return wpa_config_write_wep_key(ssid, 0);
+}
+
+
+static char * wpa_config_write_wep_key1(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ return wpa_config_write_wep_key(ssid, 1);
+}
+
+
+static char * wpa_config_write_wep_key2(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ return wpa_config_write_wep_key(ssid, 2);
+}
+
+
+static char * wpa_config_write_wep_key3(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ return wpa_config_write_wep_key(ssid, 3);
+}
+
+
+/* Helper macros for network block parser */
+
+/* OFFSET: Get offset of a variable within the wpa_ssid structure */
#define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v)
-#define STR(f) .name = #f, .parser = wpa_config_parse_str, .param1 = OFFSET(f)
+
+/* STR: Define a string variable for an ASCII string; f = field name */
+#define STR(f) .name = #f, .parser = wpa_config_parse_str, \
+ .writer = wpa_config_write_str, .param1 = OFFSET(f)
+
+/* STR_LEN: Define a string variable with a separate variable for storing the
+ * data length. Unlike STR(), this can be used to store arbitrary binary data
+ * (i.e., even nul termination character). */
#define STR_LEN(f) STR(f), .param2 = OFFSET(f ## _len)
+
+/* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length
+ * explicitly specified. */
#define STR_RANGE(f, min, max) STR_LEN(f), .param3 = (void *) (min), \
.param4 = (void *) (max)
+
+
+/* INT: Define an integer variable */
#define INT(f) .name = #f, .parser = wpa_config_parse_int, \
+ .writer = wpa_config_write_int, \
.param1 = OFFSET(f), .param2 = (void *) 0
+
+/* INT: Define an integer variable with allowed value range */
#define INT_RANGE(f, min, max) INT(f), .param3 = (void *) (min), \
.param4 = (void *) (max)
-#define FUNC(f) .name = #f, .parser = wpa_config_parse_ ## f
-static struct parse_data ssid_fields[] = {
+/* FUNC: Define a configuration variable that uses a custom function for
+ * parsing and writing the value. */
+#define FUNC(f) .name = #f, .parser = wpa_config_parse_ ## f, \
+ .writer = wpa_config_write_ ## f
+
+/*
+ * Table of network configuration variables. This table is used to parse each
+ * network configuration variable, e.g., each line in wpa_supplicant.conf file
+ * that is insider a network block.
+ *
+ * This table is generated using the helper macros defined above and with
+ * generous help from the C pre-processor. The field name is stored as a string
+ * into .name and for STR and INT types, the offset of the target buffer within
+ * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar
+ * offset to the field containing the length of the configuration variable.
+ * .param3 and .param4 can be used to mark the allowed range (length for STR
+ * and value for INT).
+ *
+ * For each configuration line in wpa_supplicant.conf, the parser goes through
+ * this table and select the entry that matches with the field name. The parser
+ * function (.parser) is then called to parse the actual value of the field.
+ *
+ * This kind of mechanism makes it easy to add new configuration parameters,
+ * since only one line needs to be added into this table and in struct wpa_ssid
+ * definitions if the new variable is either a string or integer. More complex
+ * types will need to use their own parser and writer functions.
+ */
+static const struct parse_data ssid_fields[] = {
{ STR_RANGE(ssid, 0, MAX_SSID_LEN) },
{ INT_RANGE(scan_ssid, 0, 1) },
{ FUNC(bssid) },
@@ -632,24 +1014,30 @@ static struct parse_data ssid_fields[] = {
{ STR_LEN(anonymous_identity) },
{ STR_RANGE(eappsk, EAP_PSK_LEN, EAP_PSK_LEN), .key_data = 1 },
{ STR_LEN(nai) },
- { STR_LEN(server_nai) },
{ STR_LEN(password), .key_data = 1 },
{ STR(ca_cert) },
+ { STR(ca_path) },
{ STR(client_cert) },
{ STR(private_key) },
{ STR(private_key_passwd), .key_data = 1 },
{ STR(dh_file) },
{ STR(subject_match) },
+ { STR(altsubject_match) },
{ STR(ca_cert2) },
+ { STR(ca_path2) },
{ STR(client_cert2) },
{ STR(private_key2) },
{ STR(private_key2_passwd), .key_data = 1 },
{ STR(dh_file2) },
{ STR(subject_match2) },
+ { STR(altsubject_match2) },
{ STR(phase1) },
{ STR(phase2) },
{ STR(pcsc) },
{ STR(pin), .key_data = 1 },
+ { STR(engine_id) },
+ { STR(key_id) },
+ { INT(engine) },
{ INT(eapol_flags) },
{ FUNC(wep_key0), .key_data = 1 },
{ FUNC(wep_key1), .key_data = 1 },
@@ -660,6 +1048,8 @@ static struct parse_data ssid_fields[] = {
{ INT(eap_workaround) },
{ STR(pac_file) },
{ INT_RANGE(mode, 0, 1) },
+ { INT_RANGE(proactive_key_caching, 0, 1) },
+ { INT_RANGE(disabled, 0, 1) },
};
#undef OFFSET
@@ -672,119 +1062,18 @@ static struct parse_data ssid_fields[] = {
#define NUM_SSID_FIELDS (sizeof(ssid_fields) / sizeof(ssid_fields[0]))
-static struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id)
-{
- struct wpa_ssid *ssid;
- int errors = 0, i, end = 0;
- char buf[256], *pos, *pos2;
-
- wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new network block",
- *line);
- ssid = (struct wpa_ssid *) malloc(sizeof(*ssid));
- if (ssid == NULL)
- return NULL;
- memset(ssid, 0, sizeof(*ssid));
- ssid->id = id;
-
- ssid->proto = WPA_PROTO_WPA | WPA_PROTO_RSN;
- ssid->pairwise_cipher = WPA_CIPHER_CCMP | WPA_CIPHER_TKIP;
- ssid->group_cipher = WPA_CIPHER_CCMP | WPA_CIPHER_TKIP |
- WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40;
- ssid->key_mgmt = WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X;
- ssid->eapol_flags = EAPOL_FLAG_REQUIRE_KEY_UNICAST |
- EAPOL_FLAG_REQUIRE_KEY_BROADCAST;
- ssid->eap_workaround = (unsigned int) -1;
-
- while ((pos = wpa_config_get_line(buf, sizeof(buf), f, line))) {
- if (strcmp(pos, "}") == 0) {
- end = 1;
- break;
- }
-
- pos2 = strchr(pos, '=');
- if (pos2 == NULL) {
- wpa_printf(MSG_ERROR, "Line %d: Invalid SSID line "
- "'%s'.", *line, pos);
- errors++;
- continue;
- }
-
- *pos2++ = '\0';
- if (*pos2 == '"') {
- if (strchr(pos2 + 1, '"') == NULL) {
- wpa_printf(MSG_ERROR, "Line %d: invalid "
- "quotation '%s'.", *line, pos2);
- errors++;
- continue;
- }
- }
-
- for (i = 0; i < NUM_SSID_FIELDS; i++) {
- struct parse_data *field = &ssid_fields[i];
- if (strcmp(pos, field->name) != 0)
- continue;
-
- field->ssid = ssid;
- if (field->parser(field, *line, pos2)) {
- wpa_printf(MSG_ERROR, "Line %d: failed to "
- "parse %s '%s'.", *line, pos, pos2);
- errors++;
- }
- break;
- }
- if (i == NUM_SSID_FIELDS) {
- wpa_printf(MSG_ERROR, "Line %d: unknown network field "
- "'%s'.", *line, pos);
- errors++;
- }
- }
-
- if (!end) {
- wpa_printf(MSG_ERROR, "Line %d: network block was not "
- "terminated properly.", *line);
- errors++;
- }
-
- if (ssid->passphrase) {
- if (ssid->psk_set) {
- wpa_printf(MSG_ERROR, "Line %d: both PSK and "
- "passphrase configured.", *line);
- errors++;
- }
- pbkdf2_sha1(ssid->passphrase,
- (char *) ssid->ssid, ssid->ssid_len, 4096,
- ssid->psk, PMK_LEN);
- wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
- ssid->psk, PMK_LEN);
- ssid->psk_set = 1;
- }
-
- if ((ssid->key_mgmt & WPA_KEY_MGMT_PSK) && !ssid->psk_set) {
- wpa_printf(MSG_ERROR, "Line %d: WPA-PSK accepted for key "
- "management, but no PSK configured.", *line);
- errors++;
- }
-
- if ((ssid->group_cipher & WPA_CIPHER_CCMP) &&
- !(ssid->pairwise_cipher & WPA_CIPHER_CCMP)) {
- /* Group cipher cannot be stronger than the pairwise cipher. */
- wpa_printf(MSG_DEBUG, "Line %d: removed CCMP from group cipher"
- " list since it was not allowed for pairwise "
- "cipher", *line);
- ssid->group_cipher &= ~WPA_CIPHER_CCMP;
- }
-
- if (errors) {
- free(ssid);
- ssid = NULL;
- }
-
- return ssid;
-}
-
-
-static int wpa_config_add_prio_network(struct wpa_config *config,
- struct wpa_ssid *ssid)
+/**
+ * wpa_config_add_prio_network - Add a network to priority lists
+ * @config: Configuration data from wpa_config_read()
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is used to add a network block to the priority list of
+ * networks. This must be called for each network when reading in the full
+ * configuration. In addition, this can be used indirectly when updating
+ * priorities by calling wpa_config_update_prio_list().
+ */
+int wpa_config_add_prio_network(struct wpa_config *config,
+ struct wpa_ssid *ssid)
{
int prio;
struct wpa_ssid *prev, **nlist;
@@ -821,181 +1110,125 @@ static int wpa_config_add_prio_network(struct wpa_config *config,
}
-struct wpa_config * wpa_config_read(const char *config_file)
+/**
+ * wpa_config_update_prio_list - Update network priority list
+ * @config: Configuration data from wpa_config_read()
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is called to update the priority list of networks in the
+ * configuration when a network is being added or removed. This is also called
+ * if a priority for a network is changed.
+ */
+static int wpa_config_update_prio_list(struct wpa_config *config)
{
- FILE *f;
- char buf[256], *pos;
- int errors = 0, line = 0;
- struct wpa_ssid *ssid, *tail = NULL, *head = NULL;
- struct wpa_config *config;
- int id = 0, prio;
-
- config = malloc(sizeof(*config));
- if (config == NULL)
- return NULL;
- memset(config, 0, sizeof(*config));
- config->eapol_version = 1;
- config->ap_scan = 1;
- config->fast_reauth = 1;
- wpa_printf(MSG_DEBUG, "Reading configuration file '%s'",
- config_file);
- f = fopen(config_file, "r");
- if (f == NULL) {
- free(config);
- return NULL;
- }
+ struct wpa_ssid *ssid;
+ int ret = 0;
- while ((pos = wpa_config_get_line(buf, sizeof(buf), f, &line))) {
- if (strcmp(pos, "network={") == 0) {
- ssid = wpa_config_read_network(f, &line, id++);
- if (ssid == NULL) {
- wpa_printf(MSG_ERROR, "Line %d: failed to "
- "parse network block.", line);
- errors++;
- continue;
- }
- if (head == NULL) {
- head = tail = ssid;
- } else {
- tail->next = ssid;
- tail = ssid;
- }
- if (wpa_config_add_prio_network(config, ssid)) {
- wpa_printf(MSG_ERROR, "Line %d: failed to add "
- "network block to priority list.",
- line);
- errors++;
- continue;
- }
-#ifdef CONFIG_CTRL_IFACE
- } else if (strncmp(pos, "ctrl_interface=", 15) == 0) {
- free(config->ctrl_interface);
- config->ctrl_interface = strdup(pos + 15);
- wpa_printf(MSG_DEBUG, "ctrl_interface='%s'",
- config->ctrl_interface);
-#ifndef CONFIG_CTRL_IFACE_UDP
- } else if (strncmp(pos, "ctrl_interface_group=", 21) == 0) {
- struct group *grp;
- char *endp;
- const char *group = pos + 21;
-
- grp = getgrnam(group);
- if (grp) {
- config->ctrl_interface_gid = grp->gr_gid;
- config->ctrl_interface_gid_set = 1;
- wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d"
- " (from group name '%s')",
- (int) config->ctrl_interface_gid,
- group);
- continue;
- }
+ free(config->pssid);
+ config->pssid = NULL;
+ config->num_prio = 0;
- /* Group name not found - try to parse this as gid */
- config->ctrl_interface_gid = strtol(group, &endp, 10);
- if (*group == '\0' || *endp != '\0') {
- wpa_printf(MSG_DEBUG, "Line %d: Invalid group "
- "'%s'", line, group);
- errors++;
- continue;
- }
- wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
- (int) config->ctrl_interface_gid);
-#endif /* CONFIG_CTRL_IFACE_UDP */
-#endif /* CONFIG_CTRL_IFACE */
- } else if (strncmp(pos, "eapol_version=", 14) == 0) {
- config->eapol_version = atoi(pos + 14);
- if (config->eapol_version < 1 ||
- config->eapol_version > 2) {
- wpa_printf(MSG_ERROR, "Line %d: Invalid EAPOL "
- "version (%d): '%s'.",
- line, config->eapol_version, pos);
- errors++;
- continue;
- }
- wpa_printf(MSG_DEBUG, "eapol_version=%d",
- config->eapol_version);
- } else if (strncmp(pos, "ap_scan=", 8) == 0) {
- config->ap_scan = atoi(pos + 8);
- wpa_printf(MSG_DEBUG, "ap_scan=%d", config->ap_scan);
- } else if (strncmp(pos, "fast_reauth=", 12) == 0) {
- config->fast_reauth = atoi(pos + 12);
- wpa_printf(MSG_DEBUG, "fast_reauth=%d",
- config->fast_reauth);
- } else {
- wpa_printf(MSG_ERROR, "Line %d: Invalid configuration "
- "line '%s'.", line, pos);
- errors++;
- continue;
- }
+ ssid = config->ssid;
+ while (ssid) {
+ ssid->pnext = NULL;
+ if (wpa_config_add_prio_network(config, ssid) < 0)
+ ret = -1;
+ ssid = ssid->next;
}
- fclose(f);
+ return ret;
+}
- config->ssid = head;
- for (prio = 0; prio < config->num_prio; prio++) {
- ssid = config->pssid[prio];
- wpa_printf(MSG_DEBUG, "Priority group %d",
- ssid->priority);
- while (ssid) {
- wpa_printf(MSG_DEBUG, " id=%d ssid='%s'",
- ssid->id,
- wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
- ssid = ssid->pnext;
- }
- }
- if (errors) {
- wpa_config_free(config);
- config = NULL;
- head = NULL;
- }
- return config;
+/**
+ * wpa_config_free_ssid - Free network/ssid configuration data
+ * @ssid: Configuration data for the network
+ *
+ * This function frees all resources allocated for the netowkr configuration
+ * data.
+ */
+void wpa_config_free_ssid(struct wpa_ssid *ssid)
+{
+ free(ssid->ssid);
+ free(ssid->passphrase);
+ free(ssid->eap_methods);
+ free(ssid->identity);
+ free(ssid->anonymous_identity);
+ free(ssid->eappsk);
+ free(ssid->nai);
+ free(ssid->password);
+ free(ssid->ca_cert);
+ free(ssid->ca_path);
+ free(ssid->client_cert);
+ free(ssid->private_key);
+ free(ssid->private_key_passwd);
+ free(ssid->dh_file);
+ free(ssid->subject_match);
+ free(ssid->altsubject_match);
+ free(ssid->ca_cert2);
+ free(ssid->ca_path2);
+ free(ssid->client_cert2);
+ free(ssid->private_key2);
+ free(ssid->private_key2_passwd);
+ free(ssid->dh_file2);
+ free(ssid->subject_match2);
+ free(ssid->altsubject_match2);
+ free(ssid->phase1);
+ free(ssid->phase2);
+ free(ssid->pcsc);
+ free(ssid->pin);
+ free(ssid->engine_id);
+ free(ssid->key_id);
+ free(ssid->otp);
+ free(ssid->pending_req_otp);
+ free(ssid->pac_file);
+ free(ssid->new_password);
+ free(ssid);
}
+/**
+ * wpa_config_free - Free configuration data
+ * @config: Configuration data from wpa_config_read()
+ *
+ * This function frees all resources allocated for the configuration data by
+ * wpa_config_read().
+ */
void wpa_config_free(struct wpa_config *config)
{
+ struct wpa_config_blob *blob, *prevblob;
struct wpa_ssid *ssid, *prev = NULL;
ssid = config->ssid;
while (ssid) {
prev = ssid;
ssid = ssid->next;
- free(prev->ssid);
- free(prev->passphrase);
- free(prev->eap_methods);
- free(prev->identity);
- free(prev->anonymous_identity);
- free(prev->eappsk);
- free(prev->nai);
- free(prev->server_nai);
- free(prev->password);
- free(prev->ca_cert);
- free(prev->client_cert);
- free(prev->private_key);
- free(prev->private_key_passwd);
- free(prev->dh_file);
- free(prev->subject_match);
- free(prev->ca_cert2);
- free(prev->client_cert2);
- free(prev->private_key2);
- free(prev->private_key2_passwd);
- free(prev->dh_file2);
- free(prev->subject_match2);
- free(prev->phase1);
- free(prev->phase2);
- free(prev->pcsc);
- free(prev->pin);
- free(prev->otp);
- free(prev->pending_req_otp);
- free(prev->pac_file);
- free(prev);
+ wpa_config_free_ssid(prev);
}
+
+ blob = config->blobs;
+ prevblob = NULL;
+ while (blob) {
+ prevblob = blob;
+ blob = blob->next;
+ wpa_config_free_blob(prevblob);
+ }
+
free(config->ctrl_interface);
+ free(config->opensc_engine_path);
+ free(config->pkcs11_engine_path);
+ free(config->pkcs11_module_path);
+ free(config->driver_param);
free(config->pssid);
free(config);
}
+/**
+ * wpa_config_allowed_eap_method - Check whether EAP method is allowed
+ * @ssid: Pointer to a configuration data
+ * @method: EAP type
+ * Returns: 1 = allowed EAP method, 0 = not allowed
+ */
int wpa_config_allowed_eap_method(struct wpa_ssid *ssid, int method)
{
u8 *pos;
@@ -1013,39 +1246,306 @@ int wpa_config_allowed_eap_method(struct wpa_ssid *ssid, int method)
}
-const char * wpa_cipher_txt(int cipher)
+/**
+ * wpa_config_get_network - Get configured network based on id
+ * @config: Configuration data from wpa_config_read()
+ * @id: Unique network id to search for
+ * Returns: Network configuration or %NULL if not found
+ */
+struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id)
{
- switch (cipher) {
- case WPA_CIPHER_NONE:
- return "NONE";
- case WPA_CIPHER_WEP40:
- return "WEP-40";
- case WPA_CIPHER_WEP104:
- return "WEP-104";
- case WPA_CIPHER_TKIP:
- return "TKIP";
- case WPA_CIPHER_CCMP:
- return "CCMP";
- default:
- return "UNKNOWN";
+ struct wpa_ssid *ssid;
+
+ ssid = config->ssid;
+ while (ssid) {
+ if (id == ssid->id)
+ break;
+ ssid = ssid->next;
}
+
+ return ssid;
}
-const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
+/**
+ * wpa_config_add_network - Add a new network with empty configuration
+ * @config: Configuration data from wpa_config_read()
+ * Returns: The new network configuration or %NULL if operation failed
+ */
+struct wpa_ssid * wpa_config_add_network(struct wpa_config *config)
{
- switch (key_mgmt) {
- case WPA_KEY_MGMT_IEEE8021X:
- return proto == WPA_PROTO_RSN ?
- "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP";
- case WPA_KEY_MGMT_PSK:
- return proto == WPA_PROTO_RSN ?
- "WPA2-PSK" : "WPA-PSK";
- case WPA_KEY_MGMT_NONE:
- return "NONE";
- case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
- return "IEEE 802.1X (no WPA)";
- default:
- return "UNKNOWN";
+ int id;
+ struct wpa_ssid *ssid, *last = NULL;
+
+ id = -1;
+ ssid = config->ssid;
+ while (ssid) {
+ if (ssid->id > id)
+ id = ssid->id;
+ last = ssid;
+ ssid = ssid->next;
}
+ id++;
+
+ ssid = malloc(sizeof(*ssid));
+ if (ssid == NULL)
+ return NULL;
+ memset(ssid, 0, sizeof(*ssid));
+ ssid->id = id;
+ if (last)
+ last->next = ssid;
+ else
+ config->ssid = ssid;
+
+ wpa_config_update_prio_list(config);
+
+ return ssid;
+}
+
+
+/**
+ * wpa_config_remove_network - Remove a configured network based on id
+ * @config: Configuration data from wpa_config_read()
+ * @id: Unique network id to search for
+ * Returns: 0 on success, or -1 if the network was not found
+ */
+int wpa_config_remove_network(struct wpa_config *config, int id)
+{
+ struct wpa_ssid *ssid, *prev = NULL;
+
+ ssid = config->ssid;
+ while (ssid) {
+ if (id == ssid->id)
+ break;
+ prev = ssid;
+ ssid = ssid->next;
+ }
+
+ if (ssid == NULL)
+ return -1;
+
+ if (prev)
+ prev->next = ssid->next;
+ else
+ config->ssid = ssid->next;
+
+ wpa_config_update_prio_list(config);
+ wpa_config_free_ssid(ssid);
+ return 0;
+}
+
+
+/**
+ * wpa_config_set_network_defaults - Set network default values
+ * @ssid: Pointer to a network configuration data
+ */
+void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
+{
+ ssid->proto = DEFAULT_PROTO;
+ ssid->pairwise_cipher = DEFAULT_PAIRWISE;
+ ssid->group_cipher = DEFAULT_GROUP;
+ ssid->key_mgmt = DEFAULT_KEY_MGMT;
+ ssid->eapol_flags = DEFAULT_EAPOL_FLAGS;
+ ssid->eap_workaround = DEFAULT_EAP_WORKAROUND;
+}
+
+
+/**
+ * wpa_config_set - Set a variable in network configuration
+ * @ssid: Pointer to a network configuration data
+ * @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
+ *
+ * This function can be used to set network configuration variables based on
+ * both the configuration file and management interface input. The value
+ * parameter must be in the same format as the text-based configuration file is
+ * using. For example, strings are using double quotation marks.
+ */
+int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
+ int line)
+{
+ int i, ret = 0;
+
+ if (ssid == NULL || var == NULL || value == NULL)
+ return -1;
+
+ for (i = 0; i < NUM_SSID_FIELDS; i++) {
+ const struct parse_data *field = &ssid_fields[i];
+ if (strcmp(var, field->name) != 0)
+ continue;
+
+ if (field->parser(field, ssid, line, value)) {
+ if (line) {
+ wpa_printf(MSG_ERROR, "Line %d: failed to "
+ "parse %s '%s'.", line, var, value);
+ }
+ ret = -1;
+ }
+ break;
+ }
+ if (i == NUM_SSID_FIELDS) {
+ if (line) {
+ wpa_printf(MSG_ERROR, "Line %d: unknown network field "
+ "'%s'.", line, var);
+ }
+ ret = -1;
+ }
+
+ return ret;
+}
+
+
+/**
+ * wpa_config_get - Get a variable in network configuration
+ * @ssid: Pointer to a network configuration data
+ * @var: Variable name, e.g., "ssid"
+ * Returns: Value of the variable or %NULL on failure
+ *
+ * This function can be used to get network configuration variables. The
+ * returned value is a copy of the configuration variable in text format, i.e,.
+ * the same format that the text-based configuration file and wpa_config_set()
+ * are using for the value. The caller is responsible for freeing the returned
+ * value.
+ */
+char * wpa_config_get(struct wpa_ssid *ssid, const char *var)
+{
+ int i;
+
+ if (ssid == NULL || var == NULL)
+ return NULL;
+
+ for (i = 0; i < NUM_SSID_FIELDS; i++) {
+ const struct parse_data *field = &ssid_fields[i];
+ if (strcmp(var, field->name) == 0)
+ return field->writer(field, ssid);
+ }
+
+ return NULL;
+}
+
+
+/**
+ * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID
+ * @ssid: Pointer to a network configuration data
+ *
+ * This function must be called to update WPA PSK when either SSID or the
+ * passphrase has changed for the network configuration.
+ */
+void wpa_config_update_psk(struct wpa_ssid *ssid)
+{
+ pbkdf2_sha1(ssid->passphrase,
+ (char *) ssid->ssid, ssid->ssid_len, 4096,
+ ssid->psk, PMK_LEN);
+ wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
+ ssid->psk, PMK_LEN);
+ ssid->psk_set = 1;
+}
+
+
+/**
+ * wpa_config_get_blob - Get a named configuration blob
+ * @config: Configuration data from wpa_config_read()
+ * @name: Name of the blob
+ * Returns: Pointer to blob data or %NULL if not found
+ */
+const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config,
+ const char *name)
+{
+ struct wpa_config_blob *blob = config->blobs;
+
+ while (blob) {
+ if (strcmp(blob->name, name) == 0)
+ return blob;
+ blob = blob->next;
+ }
+ return NULL;
+}
+
+
+/**
+ * wpa_config_set_blob - Set or add a named configuration blob
+ * @config: Configuration data from wpa_config_read()
+ * @blob: New value for the blob
+ *
+ * Adds a new configuration blob or replaces the current value of an existing
+ * blob.
+ */
+void wpa_config_set_blob(struct wpa_config *config,
+ struct wpa_config_blob *blob)
+{
+ wpa_config_remove_blob(config, blob->name);
+ blob->next = config->blobs;
+ config->blobs = blob;
+}
+
+
+/**
+ * wpa_config_free_blob - Free blob data
+ * @blob: Pointer to blob to be freed
+ */
+void wpa_config_free_blob(struct wpa_config_blob *blob)
+{
+ if (blob) {
+ free(blob->name);
+ free(blob->data);
+ free(blob);
+ }
+}
+
+
+/**
+ * wpa_config_remove_blob - Remove a named configuration blob
+ * @config: Configuration data from wpa_config_read()
+ * @name: Name of the blob to remove
+ * Returns: 0 if blob was removed or -1 if blob was not found
+ */
+int wpa_config_remove_blob(struct wpa_config *config, const char *name)
+{
+ struct wpa_config_blob *pos = config->blobs, *prev = NULL;
+
+ while (pos) {
+ if (strcmp(pos->name, name) == 0) {
+ if (prev)
+ prev->next = pos->next;
+ else
+ config->blobs = pos->next;
+ wpa_config_free_blob(pos);
+ return 0;
+ }
+ prev = pos;
+ pos = pos->next;
+ }
+
+ return -1;
+}
+
+
+/**
+ * wpa_config_alloc_empty - Allocate an empty configuration
+ * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain
+ * socket
+ * @driver_param: Driver parameters
+ * Returns: Pointer to allocated configuration data or %NULL on failure
+ */
+struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
+ const char *driver_param)
+{
+ struct wpa_config *config;
+
+ config = malloc(sizeof(*config));
+ if (config == NULL)
+ return NULL;
+ memset(config, 0, sizeof(*config));
+ config->eapol_version = DEFAULT_EAPOL_VERSION;
+ config->ap_scan = DEFAULT_AP_SCAN;
+ config->fast_reauth = DEFAULT_FAST_REAUTH;
+
+ if (ctrl_interface)
+ config->ctrl_interface = strdup(ctrl_interface);
+ if (driver_param)
+ config->driver_param = strdup(driver_param);
+
+ return config;
}
diff --git a/contrib/wpa_supplicant/config.h b/contrib/wpa_supplicant/config.h
index 13deb3e3cb58..bd479b6b4fb4 100644
--- a/contrib/wpa_supplicant/config.h
+++ b/contrib/wpa_supplicant/config.h
@@ -1,3 +1,17 @@
+/*
+ * WPA Supplicant / Configuration file structures
+ * Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
#ifndef CONFIG_H
#define CONFIG_H
@@ -7,27 +21,297 @@
#endif /* CONFIG_CTRL_IFACE_UDP */
#endif /* CONFIG_CTRL_IFACE */
+#define DEFAULT_EAPOL_VERSION 1
+#define DEFAULT_AP_SCAN 1
+#define DEFAULT_FAST_REAUTH 1
+
#include "config_ssid.h"
+/**
+ * struct wpa_config_blob - Named configuration blob
+ *
+ * This data structure is used to provide storage for binary objects to store
+ * abstract information like certificates and private keys inlined with the
+ * configuration data.
+ */
+struct wpa_config_blob {
+ /**
+ * name - Blob name
+ */
+ char *name;
+
+ /**
+ * data - Pointer to binary data
+ */
+ u8 *data;
+
+ /**
+ * len - Length of binary data
+ */
+ size_t len;
+
+ /**
+ * next - Pointer to next blob in the configuration
+ */
+ struct wpa_config_blob *next;
+};
+
+
+/**
+ * struct wpa_config - wpa_supplicant configuration data
+ *
+ * This data structure is presents the per-interface (radio) configuration
+ * data. In many cases, there is only one struct wpa_config instance, but if
+ * more than one network interface is being controlled, one instance is used
+ * for each.
+ */
struct wpa_config {
- struct wpa_ssid *ssid; /* global network list */
- struct wpa_ssid **pssid; /* per priority network lists (in priority
- * order) */
- int num_prio; /* number of different priorities */
+ /**
+ * ssid - Head of the global network list
+ *
+ * This is the head for the list of all the configured networks.
+ */
+ struct wpa_ssid *ssid;
+
+ /**
+ * pssid - Per-priority network lists (in priority order)
+ */
+ struct wpa_ssid **pssid;
+
+ /**
+ * num_prio - Number of different priorities used in the pssid lists
+ *
+ * This indicates how many per-priority network lists are included in
+ * pssid.
+ */
+ int num_prio;
+
+ /**
+ * eapol_version - IEEE 802.1X/EAPOL version number
+ *
+ * wpa_supplicant is implemented based on IEEE Std 802.1X-2004 which
+ * defines EAPOL version 2. However, there are many APs that do not
+ * handle the new version number correctly (they seem to drop the
+ * frames completely). In order to make wpa_supplicant interoperate
+ * with these APs, the version number is set to 1 by default. This
+ * configuration value can be used to set it to the new version (2).
+ */
int eapol_version;
+
+ /**
+ * ap_scan - AP scanning/selection
+ *
+ * By default, wpa_supplicant requests driver to perform AP
+ * scanning and then uses the scan results to select a
+ * suitable AP. Another alternative is to allow the driver to
+ * take care of AP scanning and selection and use
+ * wpa_supplicant just to process EAPOL frames based on IEEE
+ * 802.11 association information from the driver.
+ *
+ * 1: wpa_supplicant initiates scanning and AP selection (default).
+ *
+ * 0: Driver takes care of scanning, AP selection, and IEEE 802.11
+ * association parameters (e.g., WPA IE generation); this mode can
+ * also be used with non-WPA drivers when using IEEE 802.1X mode;
+ * do not try to associate with APs (i.e., external program needs
+ * to control association). This mode must also be used when using
+ * wired Ethernet drivers.
+ *
+ * 2: like 0, but associate with APs using security policy and SSID
+ * (but not BSSID); this can be used, e.g., with ndiswrapper and NDIS
+ * drivers to enable operation with hidden SSIDs and optimized roaming;
+ * in this mode, the network blocks in the configuration are tried
+ * one by one until the driver reports successful association; each
+ * network block should have explicit security policy (i.e., only one
+ * option in the lists) for key_mgmt, pairwise, group, proto variables.
+ */
int ap_scan;
- char *ctrl_interface; /* directory for UNIX domain sockets */
+
+ /**
+ * ctrl_interface - Directory for UNIX domain sockets
+ *
+ * This variable is used to configure where the UNIX domain sockets
+ * for the control interface are created. If UDP-based ctrl_iface is
+ * used, this variable can be set to any string (i.e., %NULL is not
+ * allowed).
+ */
+ char *ctrl_interface;
+
#ifdef CONFIG_CTRL_IFACE
#ifndef CONFIG_CTRL_IFACE_UDP
+ /**
+ * ctrl_interface_gid - Group identity for the UNIX domain sockets
+ *
+ * Access control for the control interface can be configured
+ * by setting the directory to allow only members of a group
+ * to use sockets. This way, it is possible to run
+ * wpa_supplicant as root (since it needs to change network
+ * configuration and open raw sockets) and still allow GUI/CLI
+ * components to be run as non-root users. However, since the
+ * control interface can be used to change the network
+ * configuration, this access needs to be protected in many
+ * cases. By default, wpa_supplicant is configured to use gid
+ * 0 (root). If you want to allow non-root users to use the
+ * control interface, add a new group and change this value to
+ * match with that group. Add users that should have control
+ * interface access to this group.
+ */
gid_t ctrl_interface_gid;
#endif /* CONFIG_CTRL_IFACE_UDP */
+ /**
+ * ctrl_interface_gid_set - Whether ctrl_interface_gid is used
+ *
+ * If this variable is zero, ctrl_interface_gid value is not used and
+ * group will not be changed from the value it got by default
+ * when the directory or socket was created.
+ */
int ctrl_interface_gid_set;
#endif /* CONFIG_CTRL_IFACE */
+
+ /**
+ * fast_reauth - EAP fast re-authentication (session resumption)
+ *
+ * By default, fast re-authentication is enabled for all EAP methods
+ * that support it. This variable can be used to disable fast
+ * re-authentication (by setting fast_reauth=0). Normally, there is no
+ * need to disable fast re-authentication.
+ */
int fast_reauth;
+
+ /**
+ * opensc_engine_path - Path to the OpenSSL engine for opensc
+ *
+ * This is an OpenSSL specific configuration option for loading OpenSC
+ * engine (engine_opensc.so); if %NULL, this engine is not loaded.
+ */
+ char *opensc_engine_path;
+
+ /**
+ * pkcs11_engine_path - Path to the OpenSSL engine for PKCS#11
+ *
+ * This is an OpenSSL specific configuration option for loading PKCS#11
+ * engine (engine_pkcs11.so); if %NULL, this engine is not loaded.
+ */
+ char *pkcs11_engine_path;
+
+ /**
+ * pkcs11_module_path - Path to the OpenSSL OpenSC/PKCS#11 module
+ *
+ * This is an OpenSSL specific configuration option for configuring
+ * path to OpenSC/PKCS#11 engine (opensc-pkcs11.so); if %NULL, this
+ * module is not loaded.
+ */
+ char *pkcs11_module_path;
+
+ /**
+ * driver_param - Driver interface parameters
+ *
+ * This text string is passed to the selected driver interface with the
+ * optional struct wpa_driver_ops::set_param() handler. This can be
+ * used to configure driver specific options without having to add new
+ * driver interface functionality.
+ */
+ char *driver_param;
+
+ /**
+ * dot11RSNAConfigPMKLifetime - Maximum lifetime of a PMK
+ *
+ * dot11 MIB variable for the maximum lifetime of a PMK in the PMK
+ * cache (unit: seconds).
+ */
+ unsigned int dot11RSNAConfigPMKLifetime;
+
+ /**
+ * dot11RSNAConfigPMKReauthThreshold - PMK re-authentication threshold
+ *
+ * dot11 MIB variable for the percentage of the PMK lifetime
+ * that should expire before an IEEE 802.1X reauthentication occurs.
+ */
+ unsigned int dot11RSNAConfigPMKReauthThreshold;
+
+ /**
+ * dot11RSNAConfigSATimeout - Security association timeout
+ *
+ * dot11 MIB variable for the maximum time a security association
+ * shall take to set up (unit: seconds).
+ */
+ unsigned int dot11RSNAConfigSATimeout;
+
+ /**
+ * update_config - Is wpa_supplicant allowed to update configuration
+ *
+ * This variable control whether wpa_supplicant is allow to re-write
+ * its configuration with wpa_config_write(). If this is zero,
+ * configuration data is only changed in memory and the external data
+ * is not overriden. If this is non-zero, wpa_supplicant will update
+ * the configuration data (e.g., a file) whenever configuration is
+ * changed. This update may replace the old configuration which can
+ * remove comments from it in case of a text file configuration.
+ */
+ int update_config;
+
+ /**
+ * blobs - Configuration blobs
+ */
+ struct wpa_config_blob *blobs;
};
-struct wpa_config * wpa_config_read(const char *config_file);
+/* Protypes for common functions from config.c */
+
void wpa_config_free(struct wpa_config *ssid);
+void wpa_config_free_ssid(struct wpa_ssid *ssid);
+struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id);
+struct wpa_ssid * wpa_config_add_network(struct wpa_config *config);
+int wpa_config_remove_network(struct wpa_config *config, int id);
+void wpa_config_set_network_defaults(struct wpa_ssid *ssid);
+int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value,
+ int line);
+char * wpa_config_get(struct wpa_ssid *ssid, const char *var);
+void wpa_config_update_psk(struct wpa_ssid *ssid);
+int wpa_config_add_prio_network(struct wpa_config *config,
+ struct wpa_ssid *ssid);
+
+const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config,
+ const char *name);
+void wpa_config_set_blob(struct wpa_config *config,
+ struct wpa_config_blob *blob);
+void wpa_config_free_blob(struct wpa_config_blob *blob);
+int wpa_config_remove_blob(struct wpa_config *config, const char *name);
+struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
+ const char *driver_param);
+
+
+/* Prototypes for backend specific functions from the selected config_*.c */
+
+/**
+ * wpa_config_read - Read and parse configuration database
+ * @name: Name of the configuration (e.g., path and file name for the
+ * configuration file)
+ * Returns: Pointer to allocated configuration data or %NULL on failure
+ *
+ * This function reads configuration data, parses its contents, and allocates
+ * data structures needed for storing configuration information. The allocated
+ * data can be freed with wpa_config_free().
+ *
+ * Each configuration backend needs to implement this function.
+ */
+struct wpa_config * wpa_config_read(const char *name);
+
+/**
+ * wpa_config_write - Write or update configuration data
+ * @name: Name of the configuration (e.g., path and file name for the
+ * configuration file)
+ * @config: Configuration data from wpa_config_read()
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function write all configuration data into an external database (e.g.,
+ * a text file) in a format that can be read with wpa_config_read(). This can
+ * be used to allow wpa_supplicant to update its configuration, e.g., when a
+ * new network is added or a password is changed.
+ *
+ * Each configuration backend needs to implement this function.
+ */
+int wpa_config_write(const char *name, struct wpa_config *config);
#endif /* CONFIG_H */
diff --git a/contrib/wpa_supplicant/config_file.c b/contrib/wpa_supplicant/config_file.c
new file mode 100644
index 000000000000..b203893d7547
--- /dev/null
+++ b/contrib/wpa_supplicant/config_file.c
@@ -0,0 +1,695 @@
+/*
+ * WPA Supplicant / Configuration backend: text file
+ * Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ *
+ * This file implements a configuration backend for text files. All the
+ * configuration information is stored in a text file that uses a format
+ * described in the sample configuration file, wpa_supplicant.conf.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "common.h"
+#include "wpa.h"
+#include "wpa_supplicant.h"
+#include "config.h"
+#include "base64.h"
+
+
+static char * wpa_config_get_line(char *s, int size, FILE *stream, int *line)
+{
+ char *pos, *end, *sstart;
+
+ while (fgets(s, size, stream)) {
+ (*line)++;
+ s[size - 1] = '\0';
+ pos = s;
+
+ while (*pos == ' ' || *pos == '\t' || *pos == '\r')
+ pos++;
+ if (*pos == '#' || *pos == '\n' || *pos == '\0' ||
+ *pos == '\r')
+ continue;
+
+ /* Remove # comments unless they are within a double quoted
+ * string. Remove trailing white space. */
+ sstart = strchr(pos, '"');
+ if (sstart)
+ sstart = strrchr(sstart + 1, '"');
+ if (!sstart)
+ sstart = pos;
+ end = strchr(sstart, '#');
+ if (end)
+ *end-- = '\0';
+ else
+ end = pos + strlen(pos) - 1;
+ while (end > pos &&
+ (*end == '\n' || *end == ' ' || *end == '\t' ||
+ *end == '\r')) {
+ *end-- = '\0';
+ }
+ if (*pos == '\0')
+ continue;
+
+ return pos;
+ }
+
+ return NULL;
+}
+
+
+static struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id)
+{
+ struct wpa_ssid *ssid;
+ int errors = 0, end = 0;
+ char buf[256], *pos, *pos2;
+
+ wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new network block",
+ *line);
+ ssid = (struct wpa_ssid *) malloc(sizeof(*ssid));
+ if (ssid == NULL)
+ return NULL;
+ memset(ssid, 0, sizeof(*ssid));
+ ssid->id = id;
+
+ wpa_config_set_network_defaults(ssid);
+
+ while ((pos = wpa_config_get_line(buf, sizeof(buf), f, line))) {
+ if (strcmp(pos, "}") == 0) {
+ end = 1;
+ break;
+ }
+
+ pos2 = strchr(pos, '=');
+ if (pos2 == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid SSID line "
+ "'%s'.", *line, pos);
+ errors++;
+ continue;
+ }
+
+ *pos2++ = '\0';
+ if (*pos2 == '"') {
+ if (strchr(pos2 + 1, '"') == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid "
+ "quotation '%s'.", *line, pos2);
+ errors++;
+ continue;
+ }
+ }
+
+ if (wpa_config_set(ssid, pos, pos2, *line) < 0)
+ errors++;
+ }
+
+ if (!end) {
+ wpa_printf(MSG_ERROR, "Line %d: network block was not "
+ "terminated properly.", *line);
+ errors++;
+ }
+
+ if (ssid->passphrase) {
+ if (ssid->psk_set) {
+ wpa_printf(MSG_ERROR, "Line %d: both PSK and "
+ "passphrase configured.", *line);
+ errors++;
+ }
+ wpa_config_update_psk(ssid);
+ }
+
+ if ((ssid->key_mgmt & WPA_KEY_MGMT_PSK) && !ssid->psk_set) {
+ wpa_printf(MSG_ERROR, "Line %d: WPA-PSK accepted for key "
+ "management, but no PSK configured.", *line);
+ errors++;
+ }
+
+ if ((ssid->group_cipher & WPA_CIPHER_CCMP) &&
+ !(ssid->pairwise_cipher & WPA_CIPHER_CCMP)) {
+ /* Group cipher cannot be stronger than the pairwise cipher. */
+ wpa_printf(MSG_DEBUG, "Line %d: removed CCMP from group cipher"
+ " list since it was not allowed for pairwise "
+ "cipher", *line);
+ ssid->group_cipher &= ~WPA_CIPHER_CCMP;
+ }
+
+ if (errors) {
+ free(ssid);
+ ssid = NULL;
+ }
+
+ return ssid;
+}
+
+
+static struct wpa_config_blob * wpa_config_read_blob(FILE *f, int *line,
+ const char *name)
+{
+ struct wpa_config_blob *blob;
+ char buf[256], *pos;
+ unsigned char *encoded = NULL, *nencoded;
+ int end = 0;
+ size_t encoded_len = 0, len;
+
+ wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new named blob '%s'",
+ *line, name);
+
+ while ((pos = wpa_config_get_line(buf, sizeof(buf), f, line))) {
+ if (strcmp(pos, "}") == 0) {
+ end = 1;
+ break;
+ }
+
+ len = strlen(pos);
+ nencoded = realloc(encoded, encoded_len + len);
+ if (nencoded == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: not enough memory for "
+ "blob", *line);
+ free(encoded);
+ return NULL;
+ }
+ encoded = nencoded;
+ memcpy(encoded + encoded_len, pos, len);
+ encoded_len += len;
+ }
+
+ if (!end) {
+ wpa_printf(MSG_ERROR, "Line %d: blob was not terminated "
+ "properly", *line);
+ free(encoded);
+ return NULL;
+ }
+
+ blob = malloc(sizeof(*blob));
+ if (blob == NULL) {
+ free(encoded);
+ return NULL;
+ }
+ memset(blob, 0, sizeof(*blob));
+ blob->name = strdup(name);
+ blob->data = base64_decode(encoded, encoded_len, &blob->len);
+ free(encoded);
+
+ if (blob->name == NULL || blob->data == NULL) {
+ wpa_config_free_blob(blob);
+ return NULL;
+ }
+
+ return blob;
+}
+
+
+struct wpa_config * wpa_config_read(const char *name)
+{
+ FILE *f;
+ char buf[256], *pos;
+ int errors = 0, line = 0;
+ struct wpa_ssid *ssid, *tail = NULL, *head = NULL;
+ struct wpa_config *config;
+ int id = 0, prio;
+
+ config = wpa_config_alloc_empty(NULL, NULL);
+ if (config == NULL)
+ return NULL;
+ wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name);
+ f = fopen(name, "r");
+ if (f == NULL) {
+ free(config);
+ return NULL;
+ }
+
+ while ((pos = wpa_config_get_line(buf, sizeof(buf), f, &line))) {
+ if (strcmp(pos, "network={") == 0) {
+ ssid = wpa_config_read_network(f, &line, id++);
+ if (ssid == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: failed to "
+ "parse network block.", line);
+ errors++;
+ continue;
+ }
+ if (head == NULL) {
+ head = tail = ssid;
+ } else {
+ tail->next = ssid;
+ tail = ssid;
+ }
+ if (wpa_config_add_prio_network(config, ssid)) {
+ wpa_printf(MSG_ERROR, "Line %d: failed to add "
+ "network block to priority list.",
+ line);
+ errors++;
+ continue;
+ }
+ } else if (strncmp(pos, "blob-base64-", 12) == 0) {
+ char *name = pos + 12, *name_end;
+ struct wpa_config_blob *blob;
+
+ name_end = strchr(name, '=');
+ if (name_end == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: no blob name "
+ "terminator", line);
+ errors++;
+ continue;
+ }
+ *name_end = '\0';
+
+ blob = wpa_config_read_blob(f, &line, name);
+ if (blob == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: failed to read"
+ " blob %s", line, name);
+ errors++;
+ continue;
+ }
+ wpa_config_set_blob(config, blob);
+#ifdef CONFIG_CTRL_IFACE
+ } else if (strncmp(pos, "ctrl_interface=", 15) == 0) {
+ free(config->ctrl_interface);
+ config->ctrl_interface = strdup(pos + 15);
+ wpa_printf(MSG_DEBUG, "ctrl_interface='%s'",
+ config->ctrl_interface);
+#ifndef CONFIG_CTRL_IFACE_UDP
+ } else if (strncmp(pos, "ctrl_interface_group=", 21) == 0) {
+ struct group *grp;
+ char *endp;
+ const char *group = pos + 21;
+
+ grp = getgrnam(group);
+ if (grp) {
+ config->ctrl_interface_gid = grp->gr_gid;
+ config->ctrl_interface_gid_set = 1;
+ wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d"
+ " (from group name '%s')",
+ (int) config->ctrl_interface_gid,
+ group);
+ continue;
+ }
+
+ /* Group name not found - try to parse this as gid */
+ config->ctrl_interface_gid = strtol(group, &endp, 10);
+ if (*group == '\0' || *endp != '\0') {
+ wpa_printf(MSG_DEBUG, "Line %d: Invalid group "
+ "'%s'", line, group);
+ errors++;
+ continue;
+ }
+ config->ctrl_interface_gid_set = 1;
+ wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
+ (int) config->ctrl_interface_gid);
+#endif /* CONFIG_CTRL_IFACE_UDP */
+#endif /* CONFIG_CTRL_IFACE */
+ } else if (strncmp(pos, "eapol_version=", 14) == 0) {
+ config->eapol_version = atoi(pos + 14);
+ if (config->eapol_version < 1 ||
+ config->eapol_version > 2) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid EAPOL "
+ "version (%d): '%s'.",
+ line, config->eapol_version, pos);
+ errors++;
+ continue;
+ }
+ wpa_printf(MSG_DEBUG, "eapol_version=%d",
+ config->eapol_version);
+ } else if (strncmp(pos, "ap_scan=", 8) == 0) {
+ config->ap_scan = atoi(pos + 8);
+ wpa_printf(MSG_DEBUG, "ap_scan=%d", config->ap_scan);
+ } else if (strncmp(pos, "fast_reauth=", 12) == 0) {
+ config->fast_reauth = atoi(pos + 12);
+ wpa_printf(MSG_DEBUG, "fast_reauth=%d",
+ config->fast_reauth);
+ } else if (strncmp(pos, "opensc_engine_path=", 19) == 0) {
+ free(config->opensc_engine_path);
+ config->opensc_engine_path = strdup(pos + 19);
+ wpa_printf(MSG_DEBUG, "opensc_engine_path='%s'",
+ config->opensc_engine_path);
+ } else if (strncmp(pos, "pkcs11_engine_path=", 19) == 0) {
+ free(config->pkcs11_engine_path);
+ config->pkcs11_engine_path = strdup(pos + 19);
+ wpa_printf(MSG_DEBUG, "pkcs11_engine_path='%s'",
+ config->pkcs11_engine_path);
+ } else if (strncmp(pos, "pkcs11_module_path=", 19) == 0) {
+ free(config->pkcs11_module_path);
+ config->pkcs11_module_path = strdup(pos + 19);
+ wpa_printf(MSG_DEBUG, "pkcs11_module_path='%s'",
+ config->pkcs11_module_path);
+ } else if (strncmp(pos, "driver_param=", 13) == 0) {
+ free(config->driver_param);
+ config->driver_param = strdup(pos + 13);
+ wpa_printf(MSG_DEBUG, "driver_param='%s'",
+ config->driver_param);
+ } else if (strncmp(pos, "dot11RSNAConfigPMKLifetime=", 27) ==
+ 0) {
+ config->dot11RSNAConfigPMKLifetime = atoi(pos + 27);
+ wpa_printf(MSG_DEBUG, "dot11RSNAConfigPMKLifetime=%d",
+ config->dot11RSNAConfigPMKLifetime);
+ } else if (strncmp(pos, "dot11RSNAConfigPMKReauthThreshold=",
+ 34) ==
+ 0) {
+ config->dot11RSNAConfigPMKReauthThreshold =
+ atoi(pos + 34);
+ wpa_printf(MSG_DEBUG,
+ "dot11RSNAConfigPMKReauthThreshold=%d",
+ config->dot11RSNAConfigPMKReauthThreshold);
+ } else if (strncmp(pos, "dot11RSNAConfigSATimeout=", 25) ==
+ 0) {
+ config->dot11RSNAConfigSATimeout = atoi(pos + 25);
+ wpa_printf(MSG_DEBUG, "dot11RSNAConfigSATimeout=%d",
+ config->dot11RSNAConfigSATimeout);
+ } else if (strncmp(pos, "update_config=", 14) == 0) {
+ config->update_config = atoi(pos + 14);
+ wpa_printf(MSG_DEBUG, "update_config=%d",
+ config->update_config);
+ } else {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid configuration "
+ "line '%s'.", line, pos);
+ errors++;
+ continue;
+ }
+ }
+
+ fclose(f);
+
+ config->ssid = head;
+ for (prio = 0; prio < config->num_prio; prio++) {
+ ssid = config->pssid[prio];
+ wpa_printf(MSG_DEBUG, "Priority group %d",
+ ssid->priority);
+ while (ssid) {
+ wpa_printf(MSG_DEBUG, " id=%d ssid='%s'",
+ ssid->id,
+ wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
+ ssid = ssid->pnext;
+ }
+ }
+ if (errors) {
+ wpa_config_free(config);
+ config = NULL;
+ head = NULL;
+ }
+
+ return config;
+}
+
+
+static void write_str(FILE *f, const char *field, struct wpa_ssid *ssid)
+{
+ char *value = wpa_config_get(ssid, field);
+ if (value == NULL)
+ return;
+ fprintf(f, "\t%s=%s\n", field, value);
+ free(value);
+}
+
+
+static void write_int(FILE *f, const char *field, int value, int def)
+{
+ if (value == def)
+ return;
+ fprintf(f, "\t%s=%d\n", field, value);
+}
+
+
+static void write_bssid(FILE *f, struct wpa_ssid *ssid)
+{
+ char *value = wpa_config_get(ssid, "bssid");
+ if (value == NULL)
+ return;
+ fprintf(f, "\tbssid=%s\n", value);
+ free(value);
+}
+
+
+static void write_psk(FILE *f, struct wpa_ssid *ssid)
+{
+ char *value = wpa_config_get(ssid, "psk");
+ if (value == NULL)
+ return;
+ fprintf(f, "\tpsk=%s\n", value);
+ free(value);
+}
+
+
+static void write_proto(FILE *f, struct wpa_ssid *ssid)
+{
+ char *value;
+
+ if (ssid->proto == DEFAULT_PROTO)
+ return;
+
+ value = wpa_config_get(ssid, "proto");
+ if (value == NULL)
+ return;
+ if (value[0])
+ fprintf(f, "\tproto=%s\n", value);
+ free(value);
+}
+
+
+static void write_key_mgmt(FILE *f, struct wpa_ssid *ssid)
+{
+ char *value;
+
+ if (ssid->key_mgmt == DEFAULT_KEY_MGMT)
+ return;
+
+ value = wpa_config_get(ssid, "key_mgmt");
+ if (value == NULL)
+ return;
+ if (value[0])
+ fprintf(f, "\tkey_mgmt=%s\n", value);
+ free(value);
+}
+
+
+static void write_pairwise(FILE *f, struct wpa_ssid *ssid)
+{
+ char *value;
+
+ if (ssid->pairwise_cipher == DEFAULT_PAIRWISE)
+ return;
+
+ value = wpa_config_get(ssid, "pairwise");
+ if (value == NULL)
+ return;
+ if (value[0])
+ fprintf(f, "\tpairwise=%s\n", value);
+ free(value);
+}
+
+
+static void write_group(FILE *f, struct wpa_ssid *ssid)
+{
+ char *value;
+
+ if (ssid->group_cipher == DEFAULT_GROUP)
+ return;
+
+ value = wpa_config_get(ssid, "group");
+ if (value == NULL)
+ return;
+ if (value[0])
+ fprintf(f, "\tgroup=%s\n", value);
+ free(value);
+}
+
+
+static void write_auth_alg(FILE *f, struct wpa_ssid *ssid)
+{
+ char *value;
+
+ if (ssid->auth_alg == 0)
+ return;
+
+ value = wpa_config_get(ssid, "auth_alg");
+ if (value == NULL)
+ return;
+ if (value[0])
+ fprintf(f, "\tauth_alg=%s\n", value);
+ free(value);
+}
+
+
+static void write_eap(FILE *f, struct wpa_ssid *ssid)
+{
+ char *value;
+
+ value = wpa_config_get(ssid, "eap");
+ if (value == NULL)
+ return;
+
+ if (value[0])
+ fprintf(f, "\teap=%s\n", value);
+ free(value);
+}
+
+
+static void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid)
+{
+ char field[20], *value;
+
+ snprintf(field, sizeof(field), "wep_key%d", idx);
+ value = wpa_config_get(ssid, field);
+ if (value) {
+ fprintf(f, "\t%s=%s\n", field, value);
+ free(value);
+ }
+}
+
+
+static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
+{
+ int i;
+
+#define STR(t) write_str(f, #t, ssid)
+#define INT(t) write_int(f, #t, ssid->t, 0)
+#define INT_DEF(t, def) write_int(f, #t, ssid->t, def)
+
+ STR(ssid);
+ INT(scan_ssid);
+ write_bssid(f, ssid);
+ write_psk(f, ssid);
+ write_proto(f, ssid);
+ write_key_mgmt(f, ssid);
+ write_pairwise(f, ssid);
+ write_group(f, ssid);
+ write_auth_alg(f, ssid);
+ write_eap(f, ssid);
+ STR(identity);
+ STR(anonymous_identity);
+ STR(eappsk);
+ STR(nai);
+ STR(password);
+ STR(ca_cert);
+ STR(client_cert);
+ STR(private_key);
+ STR(private_key_passwd);
+ STR(dh_file);
+ STR(subject_match);
+ STR(altsubject_match);
+ STR(ca_cert2);
+ STR(client_cert2);
+ STR(private_key2);
+ STR(private_key2_passwd);
+ STR(dh_file2);
+ STR(subject_match2);
+ STR(altsubject_match2);
+ STR(phase1);
+ STR(phase2);
+ STR(pcsc);
+ STR(pin);
+ STR(engine_id);
+ STR(key_id);
+ INT(engine);
+ INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS);
+ for (i = 0; i < 4; i++)
+ write_wep_key(f, i, ssid);
+ INT(wep_tx_keyidx);
+ INT(priority);
+ INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND);
+ STR(pac_file);
+ INT(mode);
+ INT(proactive_key_caching);
+ INT(disabled);
+
+#undef STR
+#undef INT
+#undef INT_DEF
+}
+
+
+static int wpa_config_write_blob(FILE *f, struct wpa_config_blob *blob)
+{
+ unsigned char *encoded;
+
+ encoded = base64_encode(blob->data, blob->len, NULL);
+ if (encoded == NULL)
+ return -1;
+
+ fprintf(f, "\nblob-base64-%s={\n%s}\n", blob->name, encoded);
+ free(encoded);
+ return 0;
+}
+
+
+int wpa_config_write(const char *name, struct wpa_config *config)
+{
+ FILE *f;
+ struct wpa_ssid *ssid;
+ struct wpa_config_blob *blob;
+ int ret = 0;
+
+ wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name);
+
+
+ f = fopen(name, "w");
+ if (f == NULL) {
+ wpa_printf(MSG_DEBUG, "Failed to open '%s' for writing", name);
+ return -1;
+ }
+
+#ifdef CONFIG_CTRL_IFACE
+ if (config->ctrl_interface)
+ fprintf(f, "ctrl_interface=%s\n", config->ctrl_interface);
+#ifndef CONFIG_CTRL_IFACE_UDP
+ if (config->ctrl_interface_gid_set) {
+ fprintf(f, "ctrl_interface_group=%d\n",
+ (int) config->ctrl_interface_gid);
+ }
+#endif /* CONFIG_CTRL_IFACE_UDP */
+#endif /* CONFIG_CTRL_IFACE */
+ if (config->eapol_version != DEFAULT_EAPOL_VERSION)
+ fprintf(f, "eapol_version=%d\n", config->eapol_version);
+ if (config->ap_scan != DEFAULT_AP_SCAN)
+ fprintf(f, "ap_scan=%d\n", config->ap_scan);
+ if (config->fast_reauth != DEFAULT_FAST_REAUTH)
+ fprintf(f, "fast_reauth=%d\n", config->fast_reauth);
+ if (config->opensc_engine_path)
+ fprintf(f, "opensc_engine_path=%s\n",
+ config->opensc_engine_path);
+ if (config->pkcs11_engine_path)
+ fprintf(f, "pkcs11_engine_path=%s\n",
+ config->pkcs11_engine_path);
+ if (config->pkcs11_module_path)
+ fprintf(f, "pkcs11_module_path=%s\n",
+ config->pkcs11_module_path);
+ if (config->driver_param)
+ fprintf(f, "driver_param=%s\n", config->driver_param);
+ if (config->dot11RSNAConfigPMKLifetime)
+ fprintf(f, "dot11RSNAConfigPMKLifetime=%d\n",
+ config->dot11RSNAConfigPMKLifetime);
+ if (config->dot11RSNAConfigPMKReauthThreshold)
+ fprintf(f, "dot11RSNAConfigPMKReauthThreshold=%d\n",
+ config->dot11RSNAConfigPMKReauthThreshold);
+ if (config->dot11RSNAConfigSATimeout)
+ fprintf(f, "dot11RSNAConfigSATimeout=%d\n",
+ config->dot11RSNAConfigSATimeout);
+ if (config->update_config)
+ fprintf(f, "update_config=%d\n", config->update_config);
+
+ for (ssid = config->ssid; ssid; ssid = ssid->next) {
+ fprintf(f, "\nnetwork={\n");
+ wpa_config_write_network(f, ssid);
+ fprintf(f, "}\n");
+ }
+
+ for (blob = config->blobs; blob; blob = blob->next) {
+ ret = wpa_config_write_blob(f, blob);
+ if (ret)
+ break;
+ }
+
+ fclose(f);
+
+ wpa_printf(MSG_DEBUG, "Configuration file '%s' written %ssuccessfully",
+ name, ret ? "un" : "");
+ return ret;
+}
diff --git a/contrib/wpa_supplicant/config_ssid.h b/contrib/wpa_supplicant/config_ssid.h
index 44bc98947ced..14dc0f47dadc 100644
--- a/contrib/wpa_supplicant/config_ssid.h
+++ b/contrib/wpa_supplicant/config_ssid.h
@@ -1,3 +1,17 @@
+/*
+ * WPA Supplicant / Network configuration structures
+ * Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
#ifndef CONFIG_SSID_H
#define CONFIG_SSID_H
@@ -24,86 +38,731 @@
#define PMK_LEN 32
#define EAP_PSK_LEN 16
+
+#define DEFAULT_EAP_WORKAROUND ((unsigned int) -1)
+#define DEFAULT_EAPOL_FLAGS (EAPOL_FLAG_REQUIRE_KEY_UNICAST | \
+ EAPOL_FLAG_REQUIRE_KEY_BROADCAST)
+#define DEFAULT_PROTO (WPA_PROTO_WPA | WPA_PROTO_RSN)
+#define DEFAULT_KEY_MGMT (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X)
+#define DEFAULT_PAIRWISE (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP)
+#define DEFAULT_GROUP (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | \
+ WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40)
+
+/**
+ * struct wpa_ssid - Network configuration data
+ *
+ * This structure includes all the configuration variables for a network. This
+ * data is included in the per-interface configuration data as an element of
+ * the network list, struct wpa_config::ssid. Each network block in the
+ * configuration is mapped to a struct wpa_ssid instance.
+ */
struct wpa_ssid {
- struct wpa_ssid *next; /* next network in global list */
- struct wpa_ssid *pnext; /* next network in per-priority list */
- int id; /* unique id for ctrl_iface */
+ /**
+ * next - Next network in global list
+ *
+ * This pointer can be used to iterate over all networks. The head of
+ * this list is stored in the ssid field of struct wpa_config.
+ */
+ struct wpa_ssid *next;
+
+ /**
+ * pnext - Next network in per-priority list
+ *
+ * This pointer can be used to iterate over all networks in the same
+ * priority class. The heads of these list are stored in the pssid
+ * fields of struct wpa_config.
+ */
+ struct wpa_ssid *pnext;
+
+ /**
+ * id - Unique id for the network
+ *
+ * This identifier is used as a unique identifier for each network
+ * block when using the control interface. Each network is allocated an
+ * id when it is being created, either when reading the configuration
+ * file or when a new network is added through the control interface.
+ */
+ int id;
+
+ /**
+ * priority - Priority group
+ *
+ * By default, all networks will get same priority group (0). If some
+ * of the networks are more desirable, this field can be used to change
+ * the order in which wpa_supplicant goes through the networks when
+ * selecting a BSS. The priority groups will be iterated in decreasing
+ * priority (i.e., the larger the priority value, the sooner the
+ * network is matched against the scan results). Within each priority
+ * group, networks will be selected based on security policy, signal
+ * strength, etc.
+ *
+ * Please note that AP scanning with scan_ssid=1 and ap_scan=2 mode are
+ * not using this priority to select the order for scanning. Instead,
+ * they try the networks in the order that used in the configuration
+ * file.
+ */
int priority;
+
+ /**
+ * ssid - Service set identifier (network name)
+ *
+ * This is the SSID for the network. For wireless interfaces, this is
+ * used to select which network will be used. If set to %NULL (or
+ * ssid_len=0), any SSID can be used. For wired interfaces, this must
+ * be set to %NULL. Note: SSID may contain any characters, even nul
+ * (ASCII 0) and as such, this should not be assumed to be a nul
+ * terminated string. ssid_len defines how many characters are valid
+ * and the ssid field is not guaranteed to be nul terminated.
+ */
u8 *ssid;
+
+ /**
+ * ssid_len - Length of the SSID
+ */
size_t ssid_len;
+
+ /**
+ * bssid - BSSID
+ *
+ * If set, this network block is used only when associating with the AP
+ * using the configured BSSID
+ */
u8 bssid[ETH_ALEN];
+
+ /**
+ * bssid_set - Whether BSSID is configured for this network
+ */
int bssid_set;
+
+ /**
+ * psk - WPA pre-shared key (256 bits)
+ */
u8 psk[PMK_LEN];
+
+ /**
+ * psk_set - Whether PSK field is configured
+ */
int psk_set;
+
+ /**
+ * passphrase - WPA ASCII passphrase
+ *
+ * If this is set, psk will be generated using the SSID and passphrase
+ * configured for the network. ASCII passphrase must be between 8 and
+ * 63 characters (inclusive).
+ */
char *passphrase;
- /* Bitfields of allowed Pairwise/Group Ciphers, WPA_CIPHER_* */
+
+ /**
+ * pairwise_cipher - Bitfield of allowed pairwise ciphers, WPA_CIPHER_*
+ */
int pairwise_cipher;
+
+ /**
+ * group_cipher - Bitfield of allowed group ciphers, WPA_CIPHER_*
+ */
int group_cipher;
+
+ /**
+ * key_mgmt - Bitfield of allowed key management protocols
+ *
+ * WPA_KEY_MGMT_*
+ */
int key_mgmt;
- int proto; /* Bitfield of allowed protocols (WPA_PROTO_*) */
- int auth_alg; /* Bitfield of allow authentication algorithms
- * (WPA_AUTH_ALG_*) */
- int scan_ssid; /* scan this SSID with Probe Requests */
- u8 *identity; /* EAP Identity */
+
+ /**
+ * proto - Bitfield of allowed protocols, WPA_PROTO_*
+ */
+ int proto;
+
+ /**
+ * auth_alg - Bitfield of allowed authentication algorithms
+ *
+ * WPA_AUTH_ALG_*
+ */
+ int auth_alg;
+
+ /**
+ * scan_ssid - Scan this SSID with Probe Requests
+ *
+ * scan_ssid can be used to scan for APs using hidden SSIDs.
+ * Note: Many drivers do not support this. ap_mode=2 can be used with
+ * such drivers to use hidden SSIDs.
+ */
+ int scan_ssid;
+
+ /**
+ * identity - EAP Identity
+ */
+ u8 *identity;
+
+ /**
+ * identity_len - EAP Identity length
+ */
size_t identity_len;
- u8 *anonymous_identity; /* Anonymous EAP Identity (for unencrypted use
- * with EAP types that support different
- * tunnelled identity, e.g., EAP-TTLS) */
+
+ /**
+ * anonymous_identity - Anonymous EAP Identity
+ *
+ * This field is used for unencrypted use with EAP types that support
+ * different tunnelled identity, e.g., EAP-TTLS, in order to reveal the
+ * real identity (identity field) only to the authentication server.
+ */
+ u8 *anonymous_identity;
+
+ /**
+ * anonymous_identity_len - Length of anonymous_identity
+ */
size_t anonymous_identity_len;
+
+ /**
+ * eappsk - EAP-PSK pre-shared key
+ */
u8 *eappsk;
+
+ /**
+ * eappsk_len - EAP-PSK pre-shared key length
+ *
+ * This field is always 16 for the current version of EAP-PSK.
+ */
size_t eappsk_len;
+
+ /**
+ * nai - User NAI (for EAP-PSK)
+ */
u8 *nai;
+
+ /**
+ * nai_len - Length of nai field
+ */
size_t nai_len;
- u8 *server_nai;
- size_t server_nai_len;
+
+ /**
+ * password - Password string for EAP
+ */
u8 *password;
+
+ /**
+ * password_len - Length of password field
+ */
size_t password_len;
+
+ /**
+ * ca_cert - File path to CA certificate file (PEM/DER)
+ *
+ * This file can have one or more trusted CA certificates. If ca_cert
+ * and ca_path are not included, server certificate will not be
+ * verified. This is insecure and a trusted CA certificate should
+ * always be configured when using EAP-TLS/TTLS/PEAP. Full path to the
+ * file should be used since working directory may change when
+ * wpa_supplicant is run in the background.
+ *
+ * Alternatively, a named configuration blob can be used by setting
+ * this to blob://<blob name>.
+ *
+ * On Windows, trusted CA certificates can be loaded from the system
+ * certificate store by setting this to cert_store://<name>, e.g.,
+ * ca_cert="cert_store://CA" or ca_cert="cert_store://ROOT".
+ */
u8 *ca_cert;
+
+ /**
+ * ca_path - Directory path for CA certificate files (PEM)
+ *
+ * This path may contain multiple CA certificates in OpenSSL format.
+ * Common use for this is to point to system trusted CA list which is
+ * often installed into directory like /etc/ssl/certs. If configured,
+ * these certificates are added to the list of trusted CAs. ca_cert
+ * may also be included in that case, but it is not required.
+ */
+ u8 *ca_path;
+
+ /**
+ * client_cert - File path to client certificate file (PEM/DER)
+ *
+ * This field is used with EAP method that use TLS authentication.
+ * Usually, this is only configured for EAP-TLS, even though this could
+ * in theory be used with EAP-TTLS and EAP-PEAP, too. Full path to the
+ * file should be used since working directory may change when
+ * wpa_supplicant is run in the background.
+ *
+ * Alternatively, a named configuration blob can be used by setting
+ * this to blob://<blob name>.
+ */
u8 *client_cert;
+
+ /**
+ * private_key - File path to client private key file (PEM/DER/PFX)
+ *
+ * When PKCS#12/PFX file (.p12/.pfx) is used, client_cert should be
+ * commented out. Both the private key and certificate will be read
+ * from the PKCS#12 file in this case. Full path to the file should be
+ * used since working directory may change when wpa_supplicant is run
+ * in the background.
+ *
+ * Windows certificate store can be used by leaving client_cert out and
+ * configuring private_key in one of the following formats:
+ *
+ * cert://substring_to_match
+ *
+ * hash://certificate_thumbprint_in_hex
+ *
+ * For example: private_key="hash://63093aa9c47f56ae88334c7b65a4"
+ *
+ * Alternatively, a named configuration blob can be used by setting
+ * this to blob://<blob name>.
+ */
u8 *private_key;
+
+ /**
+ * private_key_passwd - Password for private key file
+ *
+ * If left out, this will be asked through control interface.
+ */
u8 *private_key_passwd;
+
+ /**
+ * 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 not use this configuration. However, it is
+ * possible setup RSA to use ephemeral DH key exchange. In addition,
+ * ciphers with DSA keys always use ephemeral DH keys. This can be used
+ * to achieve forward secrecy. If the file is in DSA parameters format,
+ * it will be automatically converted into DH params. Full path to the
+ * file should be used since working directory may change when
+ * wpa_supplicant is run in the background.
+ *
+ * Alternatively, a named configuration blob can be used by setting
+ * this to blob://<blob name>.
+ */
u8 *dh_file;
+
+ /**
+ * 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
+ * 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
+ */
u8 *subject_match;
+
+ /**
+ * altsubject_match - Constraint for server certificate alt. subject
+ *
+ * This substring is matched against the alternative subject name of
+ * the authentication server certificate. If this string is set, the
+ * server sertificate is only accepted if it contains this string in an
+ * alternative subject name extension.
+ *
+ * altSubjectName string is in following format: TYPE:VALUE
+ *
+ * Example: DNS:server.example.com
+ *
+ * Following types are supported: EMAIL, DNS, URI
+ */
+ u8 *altsubject_match;
+
+ /**
+ * ca_cert2 - File path to CA certificate file (PEM/DER) (Phase 2)
+ *
+ * This file can have one or more trusted CA certificates. If ca_cert2
+ * and ca_path2 are not included, server certificate will not be
+ * verified. This is insecure and a trusted CA certificate should
+ * always be configured. Full path to the file should be used since
+ * working directory may change when wpa_supplicant is run in the
+ * background.
+ *
+ * This field is like ca_cert, but used for phase 2 (inside
+ * EAP-TTLS/PEAP/FAST tunnel) authentication.
+ *
+ * Alternatively, a named configuration blob can be used by setting
+ * this to blob://<blob name>.
+ */
u8 *ca_cert2;
+
+ /**
+ * ca_path2 - Directory path for CA certificate files (PEM) (Phase 2)
+ *
+ * This path may contain multiple CA certificates in OpenSSL format.
+ * Common use for this is to point to system trusted CA list which is
+ * often installed into directory like /etc/ssl/certs. If configured,
+ * these certificates are added to the list of trusted CAs. ca_cert
+ * may also be included in that case, but it is not required.
+ *
+ * This field is like ca_path, but used for phase 2 (inside
+ * EAP-TTLS/PEAP/FAST tunnel) authentication.
+ */
+ u8 *ca_path2;
+
+ /**
+ * client_cert2 - File path to client certificate file
+ *
+ * This field is like client_cert, but used for phase 2 (inside
+ * EAP-TTLS/PEAP/FAST tunnel) authentication. Full path to the
+ * file should be used since working directory may change when
+ * wpa_supplicant is run in the background.
+ *
+ * Alternatively, a named configuration blob can be used by setting
+ * this to blob://<blob name>.
+ */
u8 *client_cert2;
+
+ /**
+ * private_key2 - File path to client private key file
+ *
+ * This field is like private_key, but used for phase 2 (inside
+ * EAP-TTLS/PEAP/FAST tunnel) authentication. Full path to the
+ * file should be used since working directory may change when
+ * wpa_supplicant is run in the background.
+ *
+ * Alternatively, a named configuration blob can be used by setting
+ * this to blob://<blob name>.
+ */
u8 *private_key2;
+
+ /**
+ * private_key2_passwd - Password for private key file
+ *
+ * This field is like private_key_passwd, but used for phase 2 (inside
+ * EAP-TTLS/PEAP/FAST tunnel) authentication.
+ */
u8 *private_key2_passwd;
+
+ /**
+ * dh_file2 - File path to DH/DSA parameters file (in PEM format)
+ *
+ * This field is like dh_file, but used for phase 2 (inside
+ * EAP-TTLS/PEAP/FAST tunnel) authentication. Full path to the
+ * file should be used since working directory may change when
+ * wpa_supplicant is run in the background.
+ *
+ * Alternatively, a named configuration blob can be used by setting
+ * this to blob://<blob name>.
+ */
u8 *dh_file2;
+
+ /**
+ * subject_match2 - Constraint for server certificate subject
+ *
+ * This field is like subject_match, but used for phase 2 (inside
+ * EAP-TTLS/PEAP/FAST tunnel) authentication.
+ */
u8 *subject_match2;
- u8 *eap_methods; /* zero (EAP_TYPE_NONE) terminated list of allowed
- * EAP methods or NULL = any */
+
+ /**
+ * altsubject_match2 - Constraint for server certificate alt. subject
+ *
+ * This field is like altsubject_match, but used for phase 2 (inside
+ * EAP-TTLS/PEAP/FAST tunnel) authentication.
+ */
+ u8 *altsubject_match2;
+
+ /**
+ * eap_methods - Allowed EAP methods
+ *
+ * Zero (EAP_TYPE_NONE) terminated list of allowed EAP methods or %NULL
+ * if all methods are accepted.
+ */
+ u8 *eap_methods;
+
+ /**
+ * phase1 - Phase 1 (outer authentication) parameters
+ *
+ * String with field-value pairs, e.g., "peapver=0" or
+ * "peapver=1 peaplabel=1".
+ *
+ * 'peapver' can be used to force which PEAP version (0 or 1) is used.
+ *
+ * 'peaplabel=1' can be used to force new label, "client PEAP
+ * encryption", to be used during key derivation when PEAPv1 or newer.
+ *
+ * Most existing PEAPv1 implementation seem to be using the old label,
+ * "client EAP encryption", and wpa_supplicant is now using that as the
+ * default value.
+ *
+ * Some servers, e.g., Radiator, may require peaplabel=1 configuration
+ * to interoperate with PEAPv1; see eap_testing.txt for more details.
+ *
+ * 'peap_outer_success=0' can be used to terminate PEAP authentication
+ * on tunneled EAP-Success. This is required with some RADIUS servers
+ * that implement draft-josefsson-pppext-eap-tls-eap-05.txt (e.g.,
+ * Lucent NavisRadius v4.4.0 with PEAP in "IETF Draft 5" mode).
+ *
+ * include_tls_length=1 can be used to force wpa_supplicant to include
+ * TLS Message Length field in all TLS messages even if they are not
+ * fragmented.
+ *
+ * sim_min_num_chal=3 can be used to configure EAP-SIM to require three
+ * challenges (by default, it accepts 2 or 3).
+ *
+ * fast_provisioning=1 can be used to enable in-line provisioning of
+ * EAP-FAST credentials (PAC)
+ */
char *phase1;
+
+ /**
+ * phase2 - Phase2 (inner authentication with TLS tunnel) parameters
+ *
+ * String with field-value pairs, e.g., "auth=MSCHAPV2" for EAP-PEAP or
+ * "autheap=MSCHAPV2 autheap=MD5" for EAP-TTLS.
+ */
char *phase2;
+
+ /**
+ * pcsc - Parameters for PC/SC smartcard interface for USIM and GSM SIM
+ *
+ * This field is used to configure PC/SC smartcard interface.
+ * Currently, the only configuration is whether this field is %NULL (do
+ * not use PC/SC) or non-NULL (e.g., "") to enable PC/SC.
+ *
+ * This field is used for EAP-SIM and EAP-AKA.
+ */
char *pcsc;
+
+ /**
+ * pin - PIN for USIM, GSM SIM, and smartcards
+ *
+ * This field is used to configure PIN for SIM and smartcards for
+ * EAP-SIM and EAP-AKA. In addition, this is used with EAP-TLS if a
+ * smartcard is used for private key operations.
+ *
+ * If left out, this will be asked through control interface.
+ */
char *pin;
+ /**
+ * engine - Enable OpenSSL engine (e.g., for smartcard access)
+ *
+ * This is used if private key operations for EAP-TLS are performed
+ * using a smartcard.
+ */
+ int engine;
+
+ /**
+ * engine_id - Engine ID for OpenSSL engine
+ *
+ * "opensc" to select OpenSC engine or "pkcs11" to select PKCS#11
+ * engine.
+ *
+ * This is used if private key operations for EAP-TLS are performed
+ * using a smartcard.
+ */
+ char *engine_id;
+
+ /**
+ * key_id - Key ID for OpenSSL engine
+ *
+ * This is used if private key operations for EAP-TLS are performed
+ * using a smartcard.
+ */
+ char *key_id;
+
#define EAPOL_FLAG_REQUIRE_KEY_UNICAST BIT(0)
#define EAPOL_FLAG_REQUIRE_KEY_BROADCAST BIT(1)
- int eapol_flags; /* bit field of IEEE 802.1X/EAPOL options */
+ /**
+ * eapol_flags - Bit field of IEEE 802.1X/EAPOL options (EAPOL_FLAG_*)
+ */
+ int eapol_flags;
#define NUM_WEP_KEYS 4
#define MAX_WEP_KEY_LEN 16
+ /**
+ * wep_key - WEP keys
+ */
u8 wep_key[NUM_WEP_KEYS][MAX_WEP_KEY_LEN];
+
+ /**
+ * wep_key_len - WEP key lengths
+ */
size_t wep_key_len[NUM_WEP_KEYS];
+
+ /**
+ * wep_tx_keyidx - Default key index for TX frames using WEP
+ */
int wep_tx_keyidx;
- /* Per SSID variables that are not read from the configuration file */
+ /**
+ * proactive_key_caching - Enable proactive key caching
+ *
+ * This field can be used to enable proactive key caching which is also
+ * known as opportunistic PMKSA caching for WPA2. This is disabled (0)
+ * by default. Enable by setting this to 1.
+ *
+ * Proactive key caching is used to make supplicant assume that the APs
+ * are using the same PMK and generate PMKSA cache entries without
+ * doing RSN pre-authentication. This requires support from the AP side
+ * and is normally used with wireless switches that co-locate the
+ * authenticator.
+ */
+ int proactive_key_caching;
+
+ /**
+ * otp - One-time-password
+ *
+ * This field should not be set in configuration step. It is only used
+ * internally when OTP is entered through the control interface.
+ */
u8 *otp;
+
+ /**
+ * otp_len - Length of the otp field
+ */
size_t otp_len;
- int pending_req_identity, pending_req_password;
+
+ /**
+ * pending_req_identity - Whether there is a pending identity request
+ *
+ * This field should not be set in configuration step. It is only used
+ * internally when control interface is used to request needed
+ * information.
+ */
+ int pending_req_identity;
+
+ /**
+ * pending_req_password - Whether there is a pending password request
+ *
+ * This field should not be set in configuration step. It is only used
+ * internally when control interface is used to request needed
+ * information.
+ */
+ int pending_req_password;
+
+ /**
+ * pending_req_pin - Whether there is a pending PIN request
+ *
+ * This field should not be set in configuration step. It is only used
+ * internally when control interface is used to request needed
+ * information.
+ */
+ int pending_req_pin;
+
+ /**
+ * pending_req_new_password - Pending password update request
+ *
+ * This field should not be set in configuration step. It is only used
+ * internally when control interface is used to request needed
+ * information.
+ */
+ int pending_req_new_password;
+
+ /**
+ * pending_req_passphrase - Pending passphrase request
+ *
+ * This field should not be set in configuration step. It is only used
+ * internally when control interface is used to request needed
+ * information.
+ */
+ int pending_req_passphrase;
+
+ /**
+ * pending_req_otp - Whether there is a pending OTP request
+ *
+ * This field should not be set in configuration step. It is only used
+ * internally when control interface is used to request needed
+ * information.
+ */
char *pending_req_otp;
+
+ /**
+ * pending_req_otp_len - Length of the pending OTP request
+ */
size_t pending_req_otp_len;
- int leap, non_leap;
+ /**
+ * leap - Number of EAP methods using LEAP
+ *
+ * This field should be set to 1 if LEAP is enabled. This is used to
+ * select IEEE 802.11 authentication algorithm.
+ */
+ int leap;
+
+ /**
+ * non_leap - Number of EAP methods not using LEAP
+ *
+ * This field should be set to >0 if any EAP method other than LEAP is
+ * enabled. This is used to select IEEE 802.11 authentication
+ * algorithm.
+ */
+ int non_leap;
+
+ /**
+ * eap_workaround - EAP workarounds enabled
+ *
+ * wpa_supplicant supports number of "EAP workarounds" to work around
+ * interoperability issues with incorrectly behaving authentication
+ * servers. This is recommended to be enabled by default because some
+ * of the issues are present in large number of authentication servers.
+ *
+ * Strict EAP conformance mode can be configured by disabling
+ * workarounds with eap_workaround = 0.
+ */
unsigned int eap_workaround;
+ /**
+ * pac_file - File path or blob name for the PAC entries (EAP-FAST)
+ *
+ * wpa_supplicant will need to be able to create this file and write
+ * updates to it when PAC is being provisioned or refreshed. Full path
+ * to the file should be used since working directory may change when
+ * wpa_supplicant is run in the background.
+ * Alternatively, a named configuration blob can be used by setting
+ * this to blob://<blob name>.
+ */
char *pac_file;
+ /**
+ * mode - IEEE 802.11 operation mode (Infrastucture/IBSS)
+ *
+ * 0 = infrastructure (Managed) mode, i.e., associate with an AP.
+ *
+ * 1 = IBSS (ad-hoc, peer-to-peer)
+ *
+ * Note: IBSS can only be used with key_mgmt NONE (plaintext and
+ * static WEP) and key_mgmt=WPA-NONE (fixed group key TKIP/CCMP). In
+ * addition, ap_scan has to be set to 2 for IBSS. WPA-None requires
+ * following network block options: proto=WPA, key_mgmt=WPA-NONE,
+ * pairwise=NONE, group=TKIP (or CCMP, but not both), and psk must also
+ * be set (either directly or using ASCII passphrase).
+ */
int mode;
+
+ /**
+ * mschapv2_retry - MSCHAPv2 retry in progress
+ *
+ * This field is used internally by EAP-MSCHAPv2 and should not be set
+ * as part of configuration.
+ */
+ int mschapv2_retry;
+
+ /**
+ * new_password - New password for password update
+ *
+ * This field is used during MSCHAPv2 password update. This is normally
+ * requested from the user through the control interface and not set
+ * from configuration.
+ */
+ u8 *new_password;
+
+ /**
+ * new_password_len - Length of new_password field
+ */
+ size_t new_password_len;
+
+ /**
+ * disabled - Whether this network is currently disabled
+ *
+ * 0 = this network can be used (default).
+ * 1 = this network block is disabled (can be enabled through
+ * ctrl_iface, e.g., with wpa_cli or wpa_gui).
+ */
+ int disabled;
};
int wpa_config_allowed_eap_method(struct wpa_ssid *ssid, int method);
-const char * wpa_cipher_txt(int cipher);
-const char * wpa_key_mgmt_txt(int key_mgmt, int proto);
#endif /* CONFIG_SSID_H */
diff --git a/contrib/wpa_supplicant/config_types.h b/contrib/wpa_supplicant/config_types.h
new file mode 100644
index 000000000000..12b57cb4acf1
--- /dev/null
+++ b/contrib/wpa_supplicant/config_types.h
@@ -0,0 +1,14 @@
+#ifndef CONFIG_TYPES_H
+#define CONFIG_TYPES_H
+
+struct hostapd_ip_addr {
+ union {
+ struct in_addr v4;
+#ifdef CONFIG_IPV6
+ struct in6_addr v6;
+#endif /* CONFIG_IPV6 */
+ } u;
+ int af; /* AF_INET / AF_INET6 */
+};
+
+#endif /* CONFIG_TYPES_H */
diff --git a/contrib/wpa_supplicant/crypto.c b/contrib/wpa_supplicant/crypto.c
index cd278e0fae59..b4c81892c66e 100644
--- a/contrib/wpa_supplicant/crypto.c
+++ b/contrib/wpa_supplicant/crypto.c
@@ -12,11 +12,17 @@
* See README and COPYING for more details.
*/
+#include <string.h>
+#include <sys/types.h>
+
#include <openssl/md4.h>
+#include <openssl/md5.h>
+#include <openssl/sha.h>
#include <openssl/des.h>
+#include <openssl/aes.h>
#include "common.h"
-
+#include "crypto.h"
#if OPENSSL_VERSION_NUMBER < 0x00907000
#define DES_key_schedule des_key_schedule
@@ -27,7 +33,7 @@
#endif /* openssl < 0.9.7 */
-void md4_vector(size_t num_elem, const u8 *addr[], size_t *len, u8 *mac)
+void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
{
MD4_CTX ctx;
int i;
@@ -39,17 +45,6 @@ void md4_vector(size_t num_elem, const u8 *addr[], size_t *len, u8 *mac)
}
-void md4(const u8 *addr, size_t len, u8 *mac)
-{
- md4_vector(1, &addr, &len, mac);
-}
-
-
-/**
- * @clear: 8 octets (in)
- * @key: 7 octets (in) (no parity bits included)
- * @cypher: 8 octets (out)
- */
void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
{
u8 pkey[8], next, tmp;
@@ -69,3 +64,91 @@ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
DES_ecb_encrypt((DES_cblock *) clear, (DES_cblock *) cypher, &ks,
DES_ENCRYPT);
}
+
+
+#ifdef EAP_TLS_FUNCS
+void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+{
+ MD5_CTX ctx;
+ int i;
+
+ MD5_Init(&ctx);
+ for (i = 0; i < num_elem; i++)
+ MD5_Update(&ctx, addr[i], len[i]);
+ MD5_Final(mac, &ctx);
+}
+
+
+void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+{
+ SHA_CTX ctx;
+ int i;
+
+ SHA1_Init(&ctx);
+ for (i = 0; i < num_elem; i++)
+ SHA1_Update(&ctx, addr[i], len[i]);
+ SHA1_Final(mac, &ctx);
+}
+
+
+void sha1_transform(u8 *state, const u8 data[64])
+{
+ SHA_CTX context;
+ memset(&context, 0, sizeof(context));
+ memcpy(&context.h0, state, 5 * 4);
+ SHA1_Transform(&context, data);
+ memcpy(state, &context.h0, 5 * 4);
+}
+
+
+void * aes_encrypt_init(const u8 *key, size_t len)
+{
+ AES_KEY *ak;
+ ak = malloc(sizeof(*ak));
+ if (ak == NULL)
+ return NULL;
+ if (AES_set_encrypt_key(key, 8 * len, ak) < 0) {
+ free(ak);
+ return NULL;
+ }
+ return ak;
+}
+
+
+void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
+{
+ AES_encrypt(plain, crypt, ctx);
+}
+
+
+void aes_encrypt_deinit(void *ctx)
+{
+ free(ctx);
+}
+
+
+void * aes_decrypt_init(const u8 *key, size_t len)
+{
+ AES_KEY *ak;
+ ak = malloc(sizeof(*ak));
+ if (ak == NULL)
+ return NULL;
+ if (AES_set_decrypt_key(key, 8 * len, ak) < 0) {
+ free(ak);
+ return NULL;
+ }
+ return ak;
+}
+
+
+void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
+{
+ AES_decrypt(crypt, plain, ctx);
+}
+
+
+void aes_decrypt_deinit(void *ctx)
+{
+ free(ctx);
+}
+#endif /* EAP_TLS_FUNCS */
diff --git a/contrib/wpa_supplicant/crypto.h b/contrib/wpa_supplicant/crypto.h
index 3e1a0e5cd3f8..e664861afe71 100644
--- a/contrib/wpa_supplicant/crypto.h
+++ b/contrib/wpa_supplicant/crypto.h
@@ -1,8 +1,123 @@
+/*
+ * WPA Supplicant / wrapper functions for crypto libraries
+ * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ *
+ * This file defines the cryptographic functions that need to be implemented
+ * for wpa_supplicant and hostapd. When TLS is not used, internal
+ * implementation of MD5, SHA1, and AES is used and no external libraries are
+ * required. When TLS is enabled (e.g., by enabling EAP-TLS or EAP-PEAP), the
+ * crypto library used by the TLS implementation is expected to be used for
+ * non-TLS needs, too, in order to save space by not implementing these
+ * functions twice.
+ *
+ * Wrapper code for using each crypto library is in its own file (crypto*.c)
+ * and one of these files is build and linked in to provide the functions
+ * defined here.
+ */
+
#ifndef CRYPTO_H
#define CRYPTO_H
+/**
+ * md4_vector - MD4 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
+ */
void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac);
-void md4(const u8 *addr, size_t len, u8 *mac);
+
+/**
+ * md5_vector - MD5 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
+ */
+void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac);
+
+/**
+ * sha1_vector - SHA-1 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
+ */
+void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len,
+ u8 *mac);
+
+/**
+ * sha1_transform - Perform one SHA-1 transform step
+ * @state: SHA-1 state
+ * @data: Input data for the SHA-1 transform
+ *
+ * This function is used to implement random number generation specified in
+ * NIST FIPS Publication 186-2 for EAP-SIM. This PRF uses a function that is
+ * similar to SHA-1, but has different message padding and as such, access to
+ * just part of the SHA-1 is needed.
+ */
+void sha1_transform(u8 *state, const u8 data[64]);
+
+/**
+ * des_encrypt - Encrypt one block with DES
+ * @clear: 8 octets (in)
+ * @key: 7 octets (in) (no parity bits included)
+ * @cypher: 8 octets (out)
+ */
void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher);
+/**
+ * aes_encrypt_init - Initialize AES for encryption
+ * @key: Encryption key
+ * @len: Key length in bytes (usually 16, i.e., 128 bits)
+ * Returns: Pointer to context data or %NULL on failure
+ */
+void * aes_encrypt_init(const u8 *key, size_t len);
+
+/**
+ * aes_encrypt - Encrypt one AES block
+ * @ctx: Context pointer from aes_encrypt_init()
+ * @plain: Plaintext data to be encrypted (16 bytes)
+ * @crypt: Buffer for the encrypted data (16 bytes)
+ */
+void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt);
+
+/**
+ * aes_encrypt_deinit - Deinitialize AES encryption
+ * @ctx: Context pointer from aes_encrypt_init()
+ */
+void aes_encrypt_deinit(void *ctx);
+
+/**
+ * aes_decrypt_init - Initialize AES for decryption
+ * @key: Decryption key
+ * @len: Key length in bytes (usually 16, i.e., 128 bits)
+ * Returns: Pointer to context data or %NULL on failure
+ */
+void * aes_decrypt_init(const u8 *key, size_t len);
+
+/**
+ * aes_decrypt - Decrypt one AES block
+ * @ctx: Context pointer from aes_encrypt_init()
+ * @crypt: Encrypted data (16 bytes)
+ * @plain: Buffer for the decrypted data (16 bytes)
+ */
+void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain);
+
+/**
+ * aes_decrypt_deinit - Deinitialize AES decryption
+ * @ctx: Context pointer from aes_encrypt_init()
+ */
+void aes_decrypt_deinit(void *ctx);
+
+
#endif /* CRYPTO_H */
diff --git a/contrib/wpa_supplicant/crypto_gnutls.c b/contrib/wpa_supplicant/crypto_gnutls.c
new file mode 100644
index 000000000000..15f9b54ae804
--- /dev/null
+++ b/contrib/wpa_supplicant/crypto_gnutls.c
@@ -0,0 +1,163 @@
+/*
+ * WPA Supplicant / wrapper functions for libgcrypt
+ * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <gcrypt.h>
+
+#include "common.h"
+#include "crypto.h"
+
+void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+{
+ gcry_md_hd_t hd;
+ unsigned char *p;
+ int i;
+
+ if (gcry_md_open(&hd, GCRY_MD_MD4, 0) != GPG_ERR_NO_ERROR)
+ return;
+ for (i = 0; i < num_elem; i++)
+ gcry_md_write(hd, addr[i], len[i]);
+ p = gcry_md_read(hd, GCRY_MD_MD4);
+ if (p)
+ memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD4));
+ gcry_md_close(hd);
+}
+
+
+void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
+{
+ gcry_cipher_hd_t hd;
+ u8 pkey[8], next, tmp;
+ int i;
+
+ /* Add parity bits to the key */
+ next = 0;
+ for (i = 0; i < 7; i++) {
+ tmp = key[i];
+ pkey[i] = (tmp >> i) | next | 1;
+ next = tmp << (7 - i);
+ }
+ pkey[i] = next | 1;
+
+ gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+ gcry_err_code(gcry_cipher_setkey(hd, pkey, 8));
+ gcry_cipher_encrypt(hd, cypher, 8, clear, 8);
+ gcry_cipher_close(hd);
+}
+
+
+#ifdef EAP_TLS_FUNCS
+void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+{
+ gcry_md_hd_t hd;
+ unsigned char *p;
+ int i;
+
+ if (gcry_md_open(&hd, GCRY_MD_MD5, 0) != GPG_ERR_NO_ERROR)
+ return;
+ for (i = 0; i < num_elem; i++)
+ gcry_md_write(hd, addr[i], len[i]);
+ p = gcry_md_read(hd, GCRY_MD_MD5);
+ if (p)
+ memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD5));
+ gcry_md_close(hd);
+}
+
+
+void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+{
+ gcry_md_hd_t hd;
+ unsigned char *p;
+ int i;
+
+ if (gcry_md_open(&hd, GCRY_MD_SHA1, 0) != GPG_ERR_NO_ERROR)
+ return;
+ for (i = 0; i < num_elem; i++)
+ gcry_md_write(hd, addr[i], len[i]);
+ p = gcry_md_read(hd, GCRY_MD_SHA1);
+ if (p)
+ memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_SHA1));
+ gcry_md_close(hd);
+}
+
+
+void sha1_transform(u8 *state, const u8 data[64])
+{
+ /* FIX: how to do this with libgcrypt? */
+}
+
+
+void * aes_encrypt_init(const u8 *key, size_t len)
+{
+ gcry_cipher_hd_t hd;
+
+ if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) !=
+ GPG_ERR_NO_ERROR) {
+ printf("cipher open failed\n");
+ return NULL;
+ }
+ if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) {
+ printf("setkey failed\n");
+ gcry_cipher_close(hd);
+ return NULL;
+ }
+
+ return hd;
+}
+
+
+void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
+{
+ gcry_cipher_hd_t hd = ctx;
+ gcry_cipher_encrypt(hd, crypt, 16, plain, 16);
+}
+
+
+void aes_encrypt_deinit(void *ctx)
+{
+ gcry_cipher_hd_t hd = ctx;
+ gcry_cipher_close(hd);
+}
+
+
+void * aes_decrypt_init(const u8 *key, size_t len)
+{
+ gcry_cipher_hd_t hd;
+
+ if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) !=
+ GPG_ERR_NO_ERROR)
+ return NULL;
+ if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) {
+ gcry_cipher_close(hd);
+ return NULL;
+ }
+
+ return hd;
+}
+
+
+void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
+{
+ gcry_cipher_hd_t hd = ctx;
+ gcry_cipher_decrypt(hd, plain, 16, crypt, 16);
+}
+
+
+void aes_decrypt_deinit(void *ctx)
+{
+ gcry_cipher_hd_t hd = ctx;
+ gcry_cipher_close(hd);
+}
+#endif /* EAP_TLS_FUNCS */
diff --git a/contrib/wpa_supplicant/ctrl_iface.c b/contrib/wpa_supplicant/ctrl_iface.c
index 25cf0dbcbde7..01ea456af134 100644
--- a/contrib/wpa_supplicant/ctrl_iface.c
+++ b/contrib/wpa_supplicant/ctrl_iface.c
@@ -1,5 +1,5 @@
/*
- * WPA Supplicant / UNIX domain socket -based control interface
+ * WPA Supplicant / UNIX domain and UDP socket -based control interface
* Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
*
* This program is free software; you can redistribute it and/or modify
@@ -21,6 +21,8 @@
#include <errno.h>
#ifndef CONFIG_NATIVE_WINDOWS
#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
#include <sys/un.h>
#include <sys/uio.h>
#endif /* CONFIG_NATIVE_WINDOWS */
@@ -34,12 +36,11 @@
#include "wpa_supplicant_i.h"
#include "ctrl_iface.h"
#include "l2_packet.h"
+#include "preauth.h"
+#include "wpa_ctrl.h"
+#include "eap.h"
-#ifdef CONFIG_NATIVE_WINDOWS
-typedef int socklen_t;
-#endif /* CONFIG_NATIVE_WINDOWS */
-
#ifdef CONFIG_CTRL_IFACE_UDP
#define CTRL_IFACE_SOCK struct sockaddr_in
#else /* CONFIG_CTRL_IFACE_UDP */
@@ -47,6 +48,13 @@ typedef int socklen_t;
#endif /* CONFIG_CTRL_IFACE_UDP */
+/**
+ * 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.c and should not be touched directly from other files.
+ */
struct wpa_ctrl_dst {
struct wpa_ctrl_dst *next;
CTRL_IFACE_SOCK addr;
@@ -56,33 +64,11 @@ struct wpa_ctrl_dst {
};
-static const char * wpa_state_txt(int state)
-{
- switch (state) {
- case WPA_DISCONNECTED:
- return "DISCONNECTED";
- case WPA_SCANNING:
- return "SCANNING";
- case WPA_ASSOCIATING:
- return "ASSOCIATING";
- case WPA_ASSOCIATED:
- return "ASSOCIATED";
- case WPA_4WAY_HANDSHAKE:
- return "4WAY_HANDSHAKE";
- case WPA_GROUP_HANDSHAKE:
- return "GROUP_HANDSHAKE";
- case WPA_COMPLETED:
- return "COMPLETED";
- default:
- return "UNKNOWN";
- }
-}
-
-
static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
char *cmd)
{
char *value;
+ int ret = 0;
value = strchr(cmd, ' ');
if (value == NULL)
@@ -102,9 +88,21 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
} else if (strcasecmp(cmd, "EAPOL::maxStart") == 0) {
eapol_sm_configure(wpa_s->eapol,
-1, -1, -1, atoi(value));
+ } else if (strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
+ if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
+ atoi(value)))
+ ret = -1;
+ } else if (strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") == 0) {
+ if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
+ atoi(value)))
+ ret = -1;
+ } else if (strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
+ if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
+ ret = -1;
} else
- return -1;
- return 0;
+ ret = -1;
+
+ return ret;
}
@@ -120,8 +118,8 @@ static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
}
wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
- rsn_preauth_deinit(wpa_s);
- if (rsn_preauth_init(wpa_s, bssid))
+ rsn_preauth_deinit(wpa_s->wpa);
+ if (rsn_preauth_init(wpa_s->wpa, bssid, wpa_s->current_ssid))
return -1;
return 0;
@@ -252,13 +250,7 @@ static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
(u8 *) pos, strlen(pos));
- ssid = wpa_s->conf->ssid;
- while (ssid) {
- if (id == ssid->id)
- break;
- ssid = ssid->next;
- }
-
+ ssid = wpa_config_get_network(wpa_s->conf, id);
if (ssid == NULL) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
"to update", id);
@@ -279,6 +271,19 @@ static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
ssid->pending_req_password = 0;
if (ssid == wpa_s->current_ssid)
wpa_s->reassociate = 1;
+ } else if (strcmp(rsp, "NEW_PASSWORD") == 0) {
+ free(ssid->new_password);
+ ssid->new_password = (u8 *) strdup(pos);
+ ssid->new_password_len = strlen(pos);
+ ssid->pending_req_new_password = 0;
+ if (ssid == wpa_s->current_ssid)
+ wpa_s->reassociate = 1;
+ } else if (strcmp(rsp, "PIN") == 0) {
+ free(ssid->pin);
+ ssid->pin = strdup(pos);
+ ssid->pending_req_pin = 0;
+ if (ssid == wpa_s->current_ssid)
+ wpa_s->reassociate = 1;
} else if (strcmp(rsp, "OTP") == 0) {
free(ssid->otp);
ssid->otp = (u8 *) strdup(pos);
@@ -286,6 +291,12 @@ static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
free(ssid->pending_req_otp);
ssid->pending_req_otp = NULL;
ssid->pending_req_otp_len = 0;
+ } else if (strcmp(rsp, "PASSPHRASE") == 0) {
+ free(ssid->private_key_passwd);
+ ssid->private_key_passwd = (u8 *) strdup(pos);
+ ssid->pending_req_passphrase = 0;
+ if (ssid == wpa_s->current_ssid)
+ wpa_s->reassociate = 1;
} else {
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp);
return -1;
@@ -299,46 +310,626 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
const char *params,
char *buf, size_t buflen)
{
- char *pos, *end;
+ char *pos, *end, tmp[30];
int res, verbose;
verbose = strcmp(params, "-VERBOSE") == 0;
pos = buf;
end = buf + buflen;
- pos += snprintf(pos, end - pos, "bssid=" MACSTR "\n",
- MAC2STR(wpa_s->bssid));
- if (wpa_s->current_ssid) {
- pos += snprintf(pos, end - pos, "ssid=%s\n",
- wpa_ssid_txt(wpa_s->current_ssid->ssid,
- wpa_s->current_ssid->ssid_len));
- }
- pos += snprintf(pos, end - pos,
- "pairwise_cipher=%s\n"
- "group_cipher=%s\n"
- "key_mgmt=%s\n"
- "wpa_state=%s\n",
- wpa_cipher_txt(wpa_s->pairwise_cipher),
- wpa_cipher_txt(wpa_s->group_cipher),
- wpa_key_mgmt_txt(wpa_s->key_mgmt, wpa_s->proto),
- wpa_state_txt(wpa_s->wpa_state));
-
- res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, verbose);
- if (res >= 0)
- pos += res;
+ if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
+ pos += snprintf(pos, end - pos, "bssid=" MACSTR "\n",
+ MAC2STR(wpa_s->bssid));
+ if (wpa_s->current_ssid) {
+ pos += snprintf(pos, end - pos, "ssid=%s\n",
+ wpa_ssid_txt(wpa_s->current_ssid->ssid,
+ wpa_s->current_ssid->
+ ssid_len));
+ }
+
+ pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
+ }
+ pos += snprintf(pos, end - pos, "wpa_state=%s\n",
+ wpa_supplicant_state_txt(wpa_s->wpa_state));
+
+ if (wpa_s->l2 &&
+ l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0)
+ pos += snprintf(pos, end - pos, "ip_address=%s\n", tmp);
- if (wpa_s->preauth_eapol) {
- pos += snprintf(pos, end - pos, "Pre-authentication "
- "EAPOL state machines:\n");
- res = eapol_sm_get_status(wpa_s->preauth_eapol,
- pos, end - pos, verbose);
+ if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
+ wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
+ res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
+ verbose);
if (res >= 0)
pos += res;
}
+ res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
+ if (res >= 0)
+ pos += res;
+
+ return pos - buf;
+}
+
+
+static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
+ char *cmd)
+{
+ char *pos;
+ int id;
+ struct wpa_ssid *ssid;
+ u8 bssid[ETH_ALEN];
+
+ /* cmd: "<network id> <BSSID>" */
+ pos = strchr(cmd, ' ');
+ if (pos == NULL)
+ return -1;
+ *pos++ = '\0';
+ id = atoi(cmd);
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
+ if (hwaddr_aton(pos, bssid)) {
+ wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
+ return -1;
+ }
+
+ ssid = wpa_config_get_network(wpa_s->conf, id);
+ if (ssid == NULL) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
+ "to update", id);
+ return -1;
+ }
+
+ memcpy(ssid->bssid, bssid, ETH_ALEN);
+ ssid->bssid_set =
+ memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0;
+
+
+ return 0;
+}
+
+
+static int wpa_supplicant_ctrl_iface_list_networks(
+ struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
+{
+ char *pos, *end;
+ struct wpa_ssid *ssid;
+
+ pos = buf;
+ end = buf + buflen;
+ pos += snprintf(pos, end - pos, "network id / ssid / bssid / flags\n");
+
+ ssid = wpa_s->conf->ssid;
+ while (ssid) {
+ pos += snprintf(pos, end - pos, "%d\t%s",
+ ssid->id,
+ wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
+ if (ssid->bssid_set) {
+ pos += snprintf(pos, end - pos, "\t" MACSTR,
+ MAC2STR(ssid->bssid));
+ } else {
+ pos += snprintf(pos, end - pos, "\tany");
+ }
+ pos += snprintf(pos, end - pos, "\t%s%s",
+ ssid == wpa_s->current_ssid ? "[CURRENT]" : "",
+ ssid->disabled ? "[DISABLED]" : "");
+ pos += snprintf(pos, end - pos, "\n");
+
+ ssid = ssid->next;
+ }
+
return pos - buf;
}
+static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
+{
+ int first = 1;
+ pos += snprintf(pos, end - pos, "-");
+ if (cipher & WPA_CIPHER_NONE) {
+ pos += snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
+ first = 0;
+ }
+ if (cipher & WPA_CIPHER_WEP40) {
+ pos += snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
+ first = 0;
+ }
+ if (cipher & WPA_CIPHER_WEP104) {
+ pos += snprintf(pos, end - pos, "%sWEP104", first ? "" : "+");
+ first = 0;
+ }
+ if (cipher & WPA_CIPHER_TKIP) {
+ pos += snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
+ first = 0;
+ }
+ if (cipher & WPA_CIPHER_CCMP) {
+ pos += snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
+ first = 0;
+ }
+ return pos;
+}
+
+
+static char * wpa_supplicant_ie_txt(struct wpa_supplicant *wpa_s,
+ char *pos, char *end, const char *proto,
+ const u8 *ie, size_t ie_len)
+{
+ struct wpa_ie_data data;
+ int first;
+
+ pos += snprintf(pos, end - pos, "[%s-", proto);
+
+ if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
+ pos += snprintf(pos, end - pos, "?]");
+ return pos;
+ }
+
+ first = 1;
+ if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
+ pos += snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
+ first = 0;
+ }
+ if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
+ pos += snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
+ first = 0;
+ }
+ if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
+ pos += snprintf(pos, end - pos, "%sNone", first ? "" : "+");
+ first = 0;
+ }
+
+ pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
+
+ if (data.capabilities & WPA_CAPABILITY_PREAUTH)
+ pos += snprintf(pos, end - pos, "-preauth");
+
+ pos += snprintf(pos, end - pos, "]");
+
+ return pos;
+}
+
+
+static int wpa_supplicant_ctrl_iface_scan_results(
+ struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
+{
+ char *pos, *end;
+ struct wpa_scan_result *res;
+ int i;
+
+ if (wpa_s->scan_results == NULL &&
+ wpa_supplicant_get_scan_results(wpa_s) < 0)
+ return 0;
+
+ pos = buf;
+ end = buf + buflen;
+ pos += snprintf(pos, end - pos, "bssid / frequency / signal level / "
+ "flags / ssid\n");
+
+ for (i = 0; i < wpa_s->num_scan_results; i++) {
+ res = &wpa_s->scan_results[i];
+ pos += snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
+ MAC2STR(res->bssid), res->freq, res->level);
+ if (res->wpa_ie_len) {
+ pos = wpa_supplicant_ie_txt(wpa_s, pos, end, "WPA",
+ res->wpa_ie,
+ res->wpa_ie_len);
+ }
+ if (res->rsn_ie_len) {
+ pos = wpa_supplicant_ie_txt(wpa_s, pos, end, "WPA2",
+ res->rsn_ie,
+ res->rsn_ie_len);
+ }
+ if (!res->wpa_ie_len && !res->rsn_ie_len &&
+ res->caps & IEEE80211_CAP_PRIVACY)
+ pos += snprintf(pos, end - pos, "[WEP]");
+ if (res->caps & IEEE80211_CAP_IBSS)
+ pos += snprintf(pos, end - pos, "[IBSS]");
+
+ pos += snprintf(pos, end - pos, "\t%s",
+ wpa_ssid_txt(res->ssid, res->ssid_len));
+
+ pos += snprintf(pos, end - pos, "\n");
+ }
+
+ return pos - buf;
+}
+
+
+static int wpa_supplicant_ctrl_iface_select_network(
+ struct wpa_supplicant *wpa_s, char *cmd)
+{
+ int id;
+ struct wpa_ssid *ssid;
+
+ /* cmd: "<network id>" or "any" */
+ if (strcmp(cmd, "any") == 0) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
+ ssid = wpa_s->conf->ssid;
+ while (ssid) {
+ ssid->disabled = 0;
+ ssid = ssid->next;
+ }
+ wpa_s->reassociate = 1;
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+ return 0;
+ }
+
+ id = atoi(cmd);
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
+
+ ssid = wpa_config_get_network(wpa_s->conf, id);
+ if (ssid == NULL) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
+ "id=%d", id);
+ return -1;
+ }
+
+ if (ssid != wpa_s->current_ssid && wpa_s->current_ssid)
+ wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
+
+ /* Mark all other networks disabled and trigger reassociation */
+ ssid = wpa_s->conf->ssid;
+ while (ssid) {
+ ssid->disabled = id != ssid->id;
+ ssid = ssid->next;
+ }
+ wpa_s->reassociate = 1;
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+
+ return 0;
+}
+
+
+static int wpa_supplicant_ctrl_iface_enable_network(
+ struct wpa_supplicant *wpa_s, char *cmd)
+{
+ int id;
+ struct wpa_ssid *ssid;
+
+ /* cmd: "<network id>" */
+ id = atoi(cmd);
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
+
+ ssid = wpa_config_get_network(wpa_s->conf, id);
+ if (ssid == NULL) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
+ "id=%d", id);
+ return -1;
+ }
+
+ if (wpa_s->current_ssid == NULL && ssid->disabled) {
+ /*
+ * Try to reassociate since there is no current configuration
+ * and a new network was made available. */
+ wpa_s->reassociate = 1;
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+ }
+ ssid->disabled = 0;
+
+ return 0;
+}
+
+
+static int wpa_supplicant_ctrl_iface_disable_network(
+ struct wpa_supplicant *wpa_s, char *cmd)
+{
+ int id;
+ struct wpa_ssid *ssid;
+
+ /* cmd: "<network id>" */
+ id = atoi(cmd);
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
+
+ ssid = wpa_config_get_network(wpa_s->conf, id);
+ if (ssid == NULL) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
+ "id=%d", id);
+ return -1;
+ }
+
+ if (ssid == wpa_s->current_ssid)
+ wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
+ ssid->disabled = 1;
+
+ return 0;
+}
+
+
+static int wpa_supplicant_ctrl_iface_add_network(
+ struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
+{
+ struct wpa_ssid *ssid;
+
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
+
+ ssid = wpa_config_add_network(wpa_s->conf);
+ if (ssid == NULL)
+ return -1;
+ ssid->disabled = 1;
+ wpa_config_set_network_defaults(ssid);
+
+ return snprintf(buf, buflen, "%d\n", ssid->id);
+}
+
+
+static int wpa_supplicant_ctrl_iface_remove_network(
+ struct wpa_supplicant *wpa_s, char *cmd)
+{
+ int id;
+ struct wpa_ssid *ssid;
+
+ /* cmd: "<network id>" */
+ 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 == NULL ||
+ wpa_config_remove_network(wpa_s->conf, id) < 0) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
+ "id=%d", id);
+ return -1;
+ }
+
+ if (ssid == wpa_s->current_ssid)
+ wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
+
+ return 0;
+}
+
+
+static int wpa_supplicant_ctrl_iface_set_network(
+ struct wpa_supplicant *wpa_s, char *cmd)
+{
+ int id;
+ struct wpa_ssid *ssid;
+ char *name, *value;
+
+ /* cmd: "<network id> <variable name> <value>" */
+ name = strchr(cmd, ' ');
+ if (name == NULL)
+ return -1;
+ *name++ = '\0';
+
+ value = strchr(name, ' ');
+ if (value == NULL)
+ return -1;
+ *value++ = '\0';
+
+ id = atoi(cmd);
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s' "
+ "value='%s'", id, name, value);
+
+ ssid = wpa_config_get_network(wpa_s->conf, id);
+ if (ssid == NULL) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
+ "id=%d", id);
+ return -1;
+ }
+
+ if (wpa_config_set(ssid, name, value, 0) < 0) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
+ "variable '%s' to '%s'", name, value);
+ return -1;
+ }
+
+ if ((strcmp(name, "psk") == 0 && value[0] == '"' && ssid->ssid_len) ||
+ (strcmp(name, "ssid") == 0 && ssid->passphrase))
+ wpa_config_update_psk(ssid);
+
+ return 0;
+}
+
+
+static int wpa_supplicant_ctrl_iface_get_network(
+ struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
+{
+ int id;
+ struct wpa_ssid *ssid;
+ char *name, *value;
+
+ /* cmd: "<network id> <variable name>" */
+ name = strchr(cmd, ' ');
+ if (name == NULL)
+ return -1;
+ *name++ = '\0';
+
+ id = atoi(cmd);
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
+ id, name);
+
+ ssid = wpa_config_get_network(wpa_s->conf, id);
+ if (ssid == NULL) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
+ "id=%d", id);
+ return -1;
+ }
+
+ value = wpa_config_get(ssid, name);
+ if (value == NULL) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
+ "variable '%s'", name);
+ return -1;
+ }
+
+ snprintf(buf, buflen, "%s", value);
+
+ free(value);
+
+ return strlen(buf);
+}
+
+
+static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
+{
+ int ret;
+
+ if (!wpa_s->conf->update_config) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
+ "to update configuration (update_config=0)");
+ return -1;
+ }
+
+ ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
+ "update configuration");
+ } else {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
+ " updated");
+ }
+
+ return ret;
+}
+
+
+static int wpa_supplicant_ctrl_iface_get_capability(
+ struct wpa_supplicant *wpa_s, const char *field, char *buf,
+ size_t buflen)
+{
+ struct wpa_driver_capa capa;
+ int res, first = 1;
+ char *pos, *end;
+
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'", field);
+
+ if (strcmp(field, "eap") == 0) {
+ return eap_get_names(buf, buflen);
+ }
+
+ res = wpa_drv_get_capa(wpa_s, &capa);
+
+ pos = buf;
+ end = pos + buflen;
+
+ if (strcmp(field, "pairwise") == 0) {
+ if (res < 0)
+ return snprintf(buf, buflen, "CCMP TKIP NONE");
+
+ if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
+ pos += snprintf(pos, end - pos, "%sCCMP",
+ first ? "" : " ");
+ first = 0;
+ }
+
+ if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
+ pos += snprintf(pos, end - pos, "%sTKIP",
+ first ? "" : " ");
+ first = 0;
+ }
+
+ if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
+ pos += snprintf(pos, end - pos, "%sNONE",
+ first ? "" : " ");
+ first = 0;
+ }
+
+ return pos - buf;
+ }
+
+ if (strcmp(field, "group") == 0) {
+ if (res < 0)
+ return snprintf(buf, buflen, "CCMP TKIP WEP104 WEP40");
+
+ if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
+ pos += snprintf(pos, end - pos, "%sCCMP",
+ first ? "" : " ");
+ first = 0;
+ }
+
+ if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
+ pos += snprintf(pos, end - pos, "%sTKIP",
+ first ? "" : " ");
+ first = 0;
+ }
+
+ if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
+ pos += snprintf(pos, end - pos, "%sWEP104",
+ first ? "" : " ");
+ first = 0;
+ }
+
+ if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
+ pos += snprintf(pos, end - pos, "%sWEP40",
+ first ? "" : " ");
+ first = 0;
+ }
+
+ return pos - buf;
+ }
+
+ if (strcmp(field, "key_mgmt") == 0) {
+ if (res < 0) {
+ return snprintf(buf, buflen, "WPA-PSK WPA-EAP "
+ "IEEE8021X WPA-NONE NONE");
+ }
+
+ pos += snprintf(pos, end - pos, "NONE IEEE8021X");
+
+ if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
+ WPA_DRIVER_CAPA_KEY_MGMT_WPA2))
+ pos += snprintf(pos, end - pos, " WPA-EAP");
+
+ if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
+ WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK))
+ pos += snprintf(pos, end - pos, " WPA-PSK");
+
+ if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE)
+ pos += snprintf(pos, end - pos, " WPA-NONE");
+
+ return pos - buf;
+ }
+
+ if (strcmp(field, "proto") == 0) {
+ if (res < 0)
+ return snprintf(buf, buflen, "RSN WPA");
+
+ if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
+ WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
+ pos += snprintf(pos, end - pos, "%sRSN",
+ first ? "" : " ");
+ first = 0;
+ }
+
+ if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
+ WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
+ pos += snprintf(pos, end - pos, "%sWPA",
+ first ? "" : " ");
+ first = 0;
+ }
+
+ return pos - buf;
+ }
+
+ if (strcmp(field, "auth_alg") == 0) {
+ if (res < 0)
+ return snprintf(buf, buflen, "OPEN SHARED LEAP");
+
+ if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
+ pos += snprintf(pos, end - pos, "%sOPEN",
+ first ? "" : " ");
+ first = 0;
+ }
+
+ if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
+ pos += snprintf(pos, end - pos, "%sSHARED",
+ first ? "" : " ");
+ first = 0;
+ }
+
+ if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
+ pos += snprintf(pos, end - pos, "%sLEAP",
+ first ? "" : " ");
+ first = 0;
+ }
+
+ return pos - buf;
+ }
+
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
+ field);
+
+ return -1;
+}
+
+
static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
void *sock_ctx)
{
@@ -359,7 +950,7 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
return;
}
buf[res] = '\0';
- if (strncmp(buf, "CTRL-RSP-", 9) == 0) {
+ if (strncmp(buf, WPA_CTRL_RSP, strlen(WPA_CTRL_RSP)) == 0) {
wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
(u8 *) buf, res);
} else {
@@ -380,7 +971,7 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
memcpy(reply, "PONG\n", 5);
reply_len = 5;
} else if (strcmp(buf, "MIB") == 0) {
- reply_len = wpa_get_mib(wpa_s, reply, reply_size);
+ reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
if (reply_len >= 0) {
res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
reply_size - reply_len);
@@ -393,7 +984,7 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
reply_len = wpa_supplicant_ctrl_iface_status(
wpa_s, buf + 6, reply, reply_size);
} else if (strcmp(buf, "PMKSA") == 0) {
- reply_len = pmksa_cache_list(wpa_s, reply, reply_size);
+ reply_len = pmksa_cache_list(wpa_s->wpa, reply, reply_size);
} else if (strncmp(buf, "SET ", 4) == 0) {
if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
reply_len = -1;
@@ -402,6 +993,7 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
} else if (strcmp(buf, "LOGOFF") == 0) {
eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
} else if (strcmp(buf, "REASSOCIATE") == 0) {
+ wpa_s->disconnected = 0;
wpa_s->reassociate = 1;
wpa_supplicant_req_scan(wpa_s, 0, 0);
} else if (strncmp(buf, "PREAUTH ", 8) == 0) {
@@ -419,8 +1011,9 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
if (wpa_supplicant_ctrl_iface_level(wpa_s, &from, fromlen,
buf + 6))
reply_len = -1;
- } else if (strncmp(buf, "CTRL-RSP-", 9) == 0) {
- if (wpa_supplicant_ctrl_iface_ctrl_rsp(wpa_s, buf + 9))
+ } else if (strncmp(buf, WPA_CTRL_RSP, strlen(WPA_CTRL_RSP)) == 0) {
+ if (wpa_supplicant_ctrl_iface_ctrl_rsp(
+ wpa_s, buf + strlen(WPA_CTRL_RSP)))
reply_len = -1;
else
ctrl_rsp = 1;
@@ -429,6 +1022,48 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
reply_len = -1;
} else if (strcmp(buf, "TERMINATE") == 0) {
eloop_terminate();
+ } else if (strncmp(buf, "BSSID ", 6) == 0) {
+ if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
+ reply_len = -1;
+ } else if (strcmp(buf, "LIST_NETWORKS") == 0) {
+ reply_len = wpa_supplicant_ctrl_iface_list_networks(
+ wpa_s, reply, reply_size);
+ } else if (strcmp(buf, "DISCONNECT") == 0) {
+ wpa_s->disconnected = 1;
+ wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
+ } else if (strcmp(buf, "SCAN") == 0) {
+ wpa_s->scan_req = 2;
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+ } else if (strcmp(buf, "SCAN_RESULTS") == 0) {
+ reply_len = wpa_supplicant_ctrl_iface_scan_results(
+ wpa_s, reply, reply_size);
+ } else if (strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
+ if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
+ reply_len = -1;
+ } else if (strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
+ if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
+ reply_len = -1;
+ } else if (strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
+ if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
+ reply_len = -1;
+ } else if (strcmp(buf, "ADD_NETWORK") == 0) {
+ reply_len = wpa_supplicant_ctrl_iface_add_network(
+ wpa_s, reply, reply_size);
+ } else if (strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
+ if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
+ reply_len = -1;
+ } else if (strncmp(buf, "SET_NETWORK ", 12) == 0) {
+ if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
+ reply_len = -1;
+ } else if (strncmp(buf, "GET_NETWORK ", 12) == 0) {
+ reply_len = wpa_supplicant_ctrl_iface_get_network(
+ wpa_s, buf + 12, reply, reply_size);
+ } else if (strcmp(buf, "SAVE_CONFIG") == 0) {
+ if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
+ reply_len = -1;
+ } else if (strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
+ reply_len = wpa_supplicant_ctrl_iface_get_capability(
+ wpa_s, buf + 15, reply, reply_size);
} else {
memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
@@ -448,6 +1083,7 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
}
+#ifndef CONFIG_CTRL_IFACE_UDP
static char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s)
{
char *buf;
@@ -477,13 +1113,24 @@ static char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s)
#endif /* __CYGWIN__ */
return buf;
}
+#endif /* CONFIG_CTRL_IFACE_UDP */
+/**
+ * wpa_supplicant_ctrl_iface_init - Initialize control interface
+ * @wpa_s: Pointer to wpa_supplicant data
+ * Returns: 0 on success, -1 on failure
+ *
+ * Initialize the control interface and start receiving commands from external
+ * programs.
+ */
int wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
{
CTRL_IFACE_SOCK addr;
int s = -1;
+#ifndef CONFIG_CTRL_IFACE_UDP
char *fname = NULL;
+#endif /* CONFIG_CTRL_IFACE_UDP */
wpa_s->ctrl_sock = -1;
@@ -500,9 +1147,9 @@ int wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl((127 << 24) | 1);
- addr.sin_port = htons(9877);
+ addr.sin_port = htons(WPA_CTRL_IFACE_PORT);
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- perror("bind(AF_UNIX)");
+ perror("bind(AF_INET)");
goto fail;
}
#else /* CONFIG_CTRL_IFACE_UDP */
@@ -592,20 +1239,31 @@ int wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
fail:
if (s >= 0)
close(s);
+#ifndef CONFIG_CTRL_IFACE_UDP
if (fname) {
unlink(fname);
free(fname);
}
+#endif /* CONFIG_CTRL_IFACE_UDP */
return -1;
}
+/**
+ * wpa_supplicant_ctrl_iface_deinit - Deinitialize control interface
+ * @wpa_s: Pointer to wpa_supplicant data
+ *
+ * Deinitialize the control interface that was initialized with
+ * wpa_supplicant_ctrl_iface_init().
+ */
void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s)
{
struct wpa_ctrl_dst *dst, *prev;
if (wpa_s->ctrl_sock > -1) {
+#ifndef CONFIG_CTRL_IFACE_UDP
char *fname;
+#endif /* CONFIG_CTRL_IFACE_UDP */
eloop_unregister_read_sock(wpa_s->ctrl_sock);
if (wpa_s->ctrl_dst) {
/*
@@ -619,6 +1277,7 @@ void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s)
}
close(wpa_s->ctrl_sock);
wpa_s->ctrl_sock = -1;
+#ifndef CONFIG_CTRL_IFACE_UDP
fname = wpa_supplicant_ctrl_iface_path(wpa_s);
if (fname)
unlink(fname);
@@ -633,6 +1292,7 @@ void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s)
perror("rmdir[ctrl_interface]");
}
}
+#endif /* CONFIG_CTRL_IFACE_UDP */
}
dst = wpa_s->ctrl_dst;
@@ -644,6 +1304,15 @@ void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s)
}
+/**
+ * wpa_supplicant_ctrl_iface_send - Send a control interface packet to monitors
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @level: Priority level of the message
+ * @buf: Message data
+ * @len: Message length
+ *
+ * Send a packet to all monitor programs attached to the control interface.
+ */
void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, int level,
char *buf, size_t len)
{
@@ -678,9 +1347,7 @@ void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, int level,
if (sendto(wpa_s->ctrl_sock, sbuf, llen + len, 0,
(struct sockaddr *) &dst->addr,
sizeof(dst->addr)) < 0) {
- fprintf(stderr, "CTRL_IFACE monitor[%d]: ",
- idx);
- perror("sendto");
+ perror("sendto(CTRL_IFACE monitor)");
dst->errors++;
if (dst->errors > 10) {
wpa_supplicant_ctrl_iface_detach(
@@ -720,9 +1387,7 @@ void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, int level,
msg.msg_name = &dst->addr;
msg.msg_namelen = dst->addrlen;
if (sendmsg(wpa_s->ctrl_sock, &msg, 0) < 0) {
- fprintf(stderr, "CTRL_IFACE monitor[%d]: ",
- idx);
- perror("sendmsg");
+ perror("sendmsg(CTRL_IFACE monitor)");
dst->errors++;
if (dst->errors > 10) {
wpa_supplicant_ctrl_iface_detach(
@@ -737,3 +1402,287 @@ void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, int level,
}
#endif /* CONFIG_CTRL_IFACE_UDP */
}
+
+
+/**
+ * wpa_supplicant_ctrl_iface_wait - Wait for ctrl_iface monitor
+ * @wpa_s: Pointer to wpa_supplicant data
+ *
+ * Wait until the first message from an external program using the control
+ * interface is received. This function can be used to delay normal startup
+ * processing to allow control interface programs to attach with
+ * %wpa_supplicant before normal operations are started.
+ */
+void wpa_supplicant_ctrl_iface_wait(struct wpa_supplicant *wpa_s)
+{
+ fd_set rfds;
+
+ if (wpa_s->ctrl_sock < 0)
+ return;
+
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor",
+ wpa_s->ifname);
+
+ FD_ZERO(&rfds);
+ FD_SET(wpa_s->ctrl_sock, &rfds);
+ select(wpa_s->ctrl_sock + 1, &rfds, NULL, NULL, NULL);
+}
+
+
+static int wpa_supplicant_global_iface_add(struct wpa_global *global,
+ char *cmd)
+{
+ struct wpa_interface iface;
+ char *pos;
+
+ /*
+ * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
+ */
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
+
+ memset(&iface, 0, sizeof(iface));
+
+ do {
+ iface.ifname = pos = cmd;
+ pos = strchr(pos, '\t');
+ if (pos)
+ *pos++ = '\0';
+ if (iface.ifname[0] == '\0')
+ return -1;
+ if (pos == NULL)
+ break;
+
+ iface.confname = pos;
+ pos = strchr(pos, '\t');
+ if (pos)
+ *pos++ = '\0';
+ if (iface.confname[0] == '\0')
+ iface.confname = NULL;
+ if (pos == NULL)
+ break;
+
+ iface.driver = pos;
+ pos = strchr(pos, '\t');
+ if (pos)
+ *pos++ = '\0';
+ if (iface.driver[0] == '\0')
+ iface.driver = NULL;
+ if (pos == NULL)
+ break;
+
+ iface.ctrl_interface = pos;
+ pos = strchr(pos, '\t');
+ if (pos)
+ *pos++ = '\0';
+ if (iface.ctrl_interface[0] == '\0')
+ iface.ctrl_interface = NULL;
+ if (pos == NULL)
+ break;
+
+ iface.driver_param = pos;
+ pos = strchr(pos, '\t');
+ if (pos)
+ *pos++ = '\0';
+ if (iface.driver_param[0] == '\0')
+ iface.driver_param = NULL;
+ if (pos == NULL)
+ break;
+ } while (0);
+
+ if (wpa_supplicant_get_iface(global, iface.ifname))
+ return -1;
+
+ return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
+}
+
+
+static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
+ char *cmd)
+{
+ struct wpa_supplicant *wpa_s;
+
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
+
+ wpa_s = wpa_supplicant_get_iface(global, cmd);
+ if (wpa_s == NULL)
+ return -1;
+ return wpa_supplicant_remove_iface(global, wpa_s);
+}
+
+
+static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx,
+ void *sock_ctx)
+{
+ struct wpa_global *global = eloop_ctx;
+ char buf[256];
+ int res;
+ CTRL_IFACE_SOCK from;
+ socklen_t fromlen = sizeof(from);
+ char *reply;
+ const int reply_size = 2048;
+ int reply_len;
+
+ res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
+ (struct sockaddr *) &from, &fromlen);
+ if (res < 0) {
+ perror("recvfrom(ctrl_iface)");
+ return;
+ }
+ buf[res] = '\0';
+ wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface", (u8 *) buf, res);
+
+ reply = malloc(reply_size);
+ if (reply == NULL) {
+ sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
+ fromlen);
+ return;
+ }
+
+ memcpy(reply, "OK\n", 3);
+ reply_len = 3;
+
+ if (strcmp(buf, "PING") == 0) {
+ memcpy(reply, "PONG\n", 5);
+ reply_len = 5;
+ } else if (strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
+ if (wpa_supplicant_global_iface_add(global, buf + 14))
+ reply_len = -1;
+ } else if (strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
+ if (wpa_supplicant_global_iface_remove(global, buf + 17))
+ reply_len = -1;
+ } else {
+ memcpy(reply, "UNKNOWN COMMAND\n", 16);
+ reply_len = 16;
+ }
+
+ if (reply_len < 0) {
+ memcpy(reply, "FAIL\n", 5);
+ reply_len = 5;
+ }
+ sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
+ free(reply);
+}
+
+
+/**
+ * wpa_supplicant_global_ctrl_iface_init - Initialize global control interface
+ * @global: Pointer to global data from wpa_supplicant_init()
+ * Returns: 0 on success, -1 on failure
+ *
+ * Initialize the global control interface and start receiving commands from
+ * external programs.
+ */
+int wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
+{
+ CTRL_IFACE_SOCK addr;
+ int s = -1;
+#ifndef CONFIG_CTRL_IFACE_UDP
+ char *fname = NULL;
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
+ global->ctrl_sock = -1;
+
+ if (global->params.ctrl_interface == NULL)
+ return 0;
+
+ wpa_printf(MSG_DEBUG, "Global control interface '%s'",
+ global->params.ctrl_interface);
+
+#ifdef CONFIG_CTRL_IFACE_UDP
+ s = socket(PF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ perror("socket(PF_INET)");
+ goto fail;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl((127 << 24) | 1);
+ addr.sin_port = htons(WPA_GLOBAL_CTRL_IFACE_PORT);
+ if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ perror("bind(AF_INET)");
+ goto fail;
+ }
+#else /* CONFIG_CTRL_IFACE_UDP */
+ s = socket(PF_UNIX, SOCK_DGRAM, 0);
+ if (s < 0) {
+ perror("socket(PF_UNIX)");
+ goto fail;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, global->params.ctrl_interface,
+ sizeof(addr.sun_path));
+ if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ perror("bind(PF_UNIX)");
+ if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
+ " allow connections - assuming it was left"
+ "over from forced program termination");
+ if (unlink(global->params.ctrl_interface) < 0) {
+ perror("unlink[ctrl_iface]");
+ wpa_printf(MSG_ERROR, "Could not unlink "
+ "existing ctrl_iface socket '%s'",
+ global->params.ctrl_interface);
+ goto fail;
+ }
+ if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
+ 0) {
+ perror("bind(PF_UNIX)");
+ goto fail;
+ }
+ wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
+ "ctrl_iface socket '%s'",
+ global->params.ctrl_interface);
+ } else {
+ wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
+ "be in use - cannot override it");
+ wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
+ "not used anymore",
+ global->params.ctrl_interface);
+ goto fail;
+ }
+ }
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
+ global->ctrl_sock = s;
+ eloop_register_read_sock(s, wpa_supplicant_global_ctrl_iface_receive,
+ global, NULL);
+
+ return 0;
+
+fail:
+ if (s >= 0)
+ close(s);
+#ifndef CONFIG_CTRL_IFACE_UDP
+ if (fname) {
+ unlink(fname);
+ free(fname);
+ }
+#endif /* CONFIG_CTRL_IFACE_UDP */
+ return -1;
+}
+
+
+/**
+ * wpa_supplicant_global_ctrl_iface_deinit - Deinitialize global ctrl interface
+ * @global: Pointer to global data from wpa_supplicant_init()
+ *
+ * Deinitialize the global control interface that was initialized with
+ * wpa_supplicant_global_ctrl_iface_init().
+ */
+void wpa_supplicant_global_ctrl_iface_deinit(struct wpa_global *global)
+{
+ if (global->ctrl_sock < 0)
+ return;
+
+ eloop_unregister_read_sock(global->ctrl_sock);
+ close(global->ctrl_sock);
+ global->ctrl_sock = -1;
+
+#ifndef CONFIG_CTRL_IFACE_UDP
+ if (global->params.ctrl_interface)
+ unlink(global->params.ctrl_interface);
+#endif /* CONFIG_CTRL_IFACE_UDP */
+}
diff --git a/contrib/wpa_supplicant/ctrl_iface.h b/contrib/wpa_supplicant/ctrl_iface.h
index d7ad6dfe670a..affa6040a7e8 100644
--- a/contrib/wpa_supplicant/ctrl_iface.h
+++ b/contrib/wpa_supplicant/ctrl_iface.h
@@ -1,3 +1,17 @@
+/*
+ * WPA Supplicant / UNIX domain socket -based control interface
+ * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
#ifndef CTRL_IFACE_H
#define CTRL_IFACE_H
@@ -7,6 +21,9 @@ int wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s);
void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s);
void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, int level,
char *buf, size_t len);
+void wpa_supplicant_ctrl_iface_wait(struct wpa_supplicant *wpa_s);
+int wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global);
+void wpa_supplicant_global_ctrl_iface_deinit(struct wpa_global *global);
#else /* CONFIG_CTRL_IFACE */
@@ -26,6 +43,22 @@ wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, int level,
{
}
+static inline void
+wpa_supplicant_ctrl_iface_wait(struct wpa_supplicant *wpa_s)
+{
+}
+
+static inline int
+wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
+{
+ return 0;
+}
+
+static inline void
+wpa_supplicant_global_ctrl_iface_deinit(struct wpa_global *global)
+{
+}
+
#endif /* CONFIG_CTRL_IFACE */
#endif /* CTRL_IFACE_H */
diff --git a/contrib/wpa_supplicant/defconfig b/contrib/wpa_supplicant/defconfig
index 7e8e3811d06f..be013b48df10 100644
--- a/contrib/wpa_supplicant/defconfig
+++ b/contrib/wpa_supplicant/defconfig
@@ -50,7 +50,9 @@ CONFIG_DRIVER_HOSTAP=y
#CFLAGS += -I../madwifi/wpa
# Driver interface for Prism54 driver
-CONFIG_DRIVER_PRISM54=y
+# (Note: Prism54 is not yet supported, i.e., this will not work as-is and is
+# for developers only)
+#CONFIG_DRIVER_PRISM54=y
# Driver interface for ndiswrapper
#CONFIG_DRIVER_NDISWRAPPER=y
@@ -88,6 +90,9 @@ CONFIG_DRIVER_WEXT=y
# Driver interface for development testing
#CONFIG_DRIVER_TEST=y
+# Driver interface for wired Ethernet drivers
+CONFIG_DRIVER_WIRED=y
+
# Enable IEEE 802.1X Supplicant (automatically included if any EAP method is
# included)
CONFIG_IEEE8021X_EAPOL=y
@@ -119,6 +124,9 @@ CONFIG_EAP_OTP=y
# EAP-PSK (experimental; this is _not_ needed for WPA-PSK)
#CONFIG_EAP_PSK=y
+# EAP-PAX
+#CONFIG_EAP_PAX=y
+
# LEAP
CONFIG_EAP_LEAP=y
@@ -129,6 +137,10 @@ CONFIG_EAP_LEAP=y
# a file that usually has extension .p12 or .pfx)
CONFIG_PKCS12=y
+# Smartcard support (i.e., private key on a smartcard), e.g., with openssl
+# engine.
+CONFIG_SMARTCARD=y
+
# PC/SC interface for smartcards (USIM, GSM SIM)
# Enable this if EAP-SIM or EAP-AKA is included
#CONFIG_PCSC=y
@@ -143,12 +155,22 @@ CONFIG_PKCS12=y
# Include control interface for external programs, e.g, wpa_cli
CONFIG_CTRL_IFACE=y
-# Include interface for using external supplicant (Xsupplicant) for EAP
-# authentication
-#CONFIG_XSUPPLICANT_IFACE=y
-
# Include support for GNU Readline and History Libraries in wpa_cli.
# When building a wpa_cli binary for distribution, please note that these
# libraries are licensed under GPL and as such, BSD license may not apply for
# the resulting binary.
#CONFIG_READLINE=y
+
+# Remove debugging code that is printing out debug message to stdout.
+# This can be used to reduce the size of the wpa_supplicant considerably
+# if debugging code is not needed. The size reduction can be around 35%
+# (e.g., 90 kB).
+#CONFIG_NO_STDOUT_DEBUG=y
+
+# Remove WPA support, e.g., for wired-only IEEE 802.1X supplicant, to save
+# 35-50 kB in code size.
+#CONFIG_NO_WPA=y
+
+# Select configuration backend:
+# file = text file (e.g., wpa_supplicant.conf)
+CONFIG_BACKEND=file
diff --git a/contrib/wpa_supplicant/defs.h b/contrib/wpa_supplicant/defs.h
index a5a515c552f5..6f9881d71d03 100644
--- a/contrib/wpa_supplicant/defs.h
+++ b/contrib/wpa_supplicant/defs.h
@@ -1,14 +1,131 @@
+/*
+ * WPA Supplicant - Common definitions
+ * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
#ifndef DEFS_H
#define DEFS_H
-#ifdef CONFIG_NATIVE_WINDOWS
#ifdef FALSE
#undef FALSE
#endif
#ifdef TRUE
#undef TRUE
#endif
-#endif /* CONFIG_NATIVE_WINDOWS */
typedef enum { FALSE = 0, TRUE = 1 } Boolean;
+
+typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg;
+typedef enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP,
+ CIPHER_WEP104 } wpa_cipher;
+typedef enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE,
+ KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE } wpa_key_mgmt;
+
+/**
+ * enum wpa_states - wpa_supplicant state
+ *
+ * These enumeration values are used to indicate the current wpa_supplicant
+ * state (wpa_s->wpa_state). The current state can be retrieved with
+ * wpa_supplicant_get_state() function and the state can be changed by calling
+ * wpa_supplicant_set_state(). In WPA state machine (wpa.c and preauth.c), the
+ * wrapper functions wpa_sm_get_state() and wpa_sm_set_state() should be used
+ * to access the state variable.
+ */
+typedef enum {
+ /**
+ * WPA_DISCONNECTED - Disconnected state
+ *
+ * This state indicates that client is not associated, but is likely to
+ * start looking for an access point. This state is entered when a
+ * connection is lost.
+ */
+ WPA_DISCONNECTED,
+
+ /**
+ * WPA_INACTIVE - Inactive state (wpa_supplicant disabled)
+ *
+ * This state is entered if there are no enabled networks in the
+ * configuration. wpa_supplicant is not trying to associate with a new
+ * network and external interaction (e.g., ctrl_iface call to add or
+ * enable a network) is needed to start association.
+ */
+ WPA_INACTIVE,
+
+ /**
+ * WPA_SCANNING - Scanning for a network
+ *
+ * This state is entered when wpa_supplicant starts scanning for a
+ * network.
+ */
+ WPA_SCANNING,
+
+ /**
+ * WPA_ASSOCIATING - Trying to associate with a BSS/SSID
+ *
+ * This state is entered when wpa_supplicant has found a suitable BSS
+ * to associate with and the driver is configured to try to associate
+ * with this BSS in ap_scan=1 mode. When using ap_scan=2 mode, this
+ * state is entered when the driver is configured to try to associate
+ * with a network using the configured SSID and security policy.
+ */
+ WPA_ASSOCIATING,
+
+ /**
+ * WPA_ASSOCIATED - Association completed
+ *
+ * This state is entered when the driver reports that association has
+ * been successfully completed with an AP. If IEEE 802.1X is used
+ * (with or without WPA/WPA2), wpa_supplicant remains in this state
+ * until the IEEE 802.1X/EAPOL authentication has been completed.
+ */
+ WPA_ASSOCIATED,
+
+ /**
+ * WPA_4WAY_HANDSHAKE - WPA 4-Way Key Handshake in progress
+ *
+ * This state is entered when WPA/WPA2 4-Way Handshake is started. In
+ * case of WPA-PSK, this happens when receiving the first EAPOL-Key
+ * frame after association. In case of WPA-EAP, this state is entered
+ * when the IEEE 802.1X/EAPOL authentication has been completed.
+ */
+ WPA_4WAY_HANDSHAKE,
+
+ /**
+ * WPA_GROUP_HANDSHAKE - WPA Group Key Handshake in progress
+ *
+ * This state is entered when 4-Way Key Handshake has been completed
+ * (i.e., when the supplicant sends out message 4/4) and when Group
+ * Key rekeying is started by the AP (i.e., when supplicant receives
+ * message 1/2).
+ */
+ WPA_GROUP_HANDSHAKE,
+
+ /**
+ * WPA_COMPLETED - All authentication completed
+ *
+ * This state is entered when the full authentication process is
+ * completed. In case of WPA2, this happens when the 4-Way Handshake is
+ * successfully completed. With WPA, this state is entered after the
+ * Group Key Handshake; with IEEE 802.1X (non-WPA) connection is
+ * completed after dynamic keys are received (or if not used, after
+ * the EAP authentication has been completed). With static WEP keys and
+ * plaintext connections, this state is entered when an association
+ * has been completed.
+ *
+ * This state indicates that the supplicant has completed its
+ * processing for the association phase and that data connection is
+ * fully configured.
+ */
+ WPA_COMPLETED
+} wpa_states;
+
#endif /* DEFS_H */
diff --git a/contrib/wpa_supplicant/doc/code_structure.doxygen b/contrib/wpa_supplicant/doc/code_structure.doxygen
new file mode 100644
index 000000000000..6a32e590e223
--- /dev/null
+++ b/contrib/wpa_supplicant/doc/code_structure.doxygen
@@ -0,0 +1,264 @@
+/**
+\page code_structure Structure of the source code
+
+[ \ref wpa_supplicant_core "wpa_supplicant core functionality" |
+\ref generic_helper_func "Generic helper functions" |
+\ref crypto_func "Cryptographic functions" |
+\ref configuration "Configuration" |
+\ref ctrl_iface "Control interface" |
+\ref wpa_code "WPA supplicant" |
+\ref eap_peer "EAP peer" |
+\ref eapol_supp "EAPOL supplicant" |
+\ref win_port "Windows port" |
+\ref test_programs "Test programs" ]
+
+%wpa_supplicant implementation is divided into number of independent
+modules. Core code includes functionality for controlling the network
+selection, association, and configuration. Independent modules include
+WPA code (key handshake, PMKSA caching, pre-authentication), EAPOL
+state machine, and EAP state machine and methods. In addition, there
+are number of separate files for generic helper functions.
+
+Both WPA and EAPOL/EAP state machines can be used separately in other
+programs than %wpa_supplicant. As an example, the included test
+programs eapol_test and preauth_test are using these modules.
+
+\ref driver_wrapper "Driver interface API" is defined in driver.h and
+all hardware/driver dependent functionality is implemented in
+driver_*.c.
+
+
+\section wpa_supplicant_core wpa_supplicant core functionality
+
+wpa_supplicant.c
+ Program initialization, main control loop
+
+main.c
+ main() for UNIX-like operating systems and MinGW (Windows); this
+ uses command line arguments to configure wpa_supplicant
+
+events.c
+ Driver event processing; wpa_supplicant_event() and related functions
+
+wpa_supplicant_i.h
+ Internal definitions for %wpa_supplicant core; should not be
+ included into independent modules
+
+wpa_supplicant.h
+ Definitions for driver event data and message logging
+
+
+\section generic_helper_func Generic helper functions
+
+%wpa_supplicant uses generic helper functions some of which are shared
+with with hostapd. The following C files are currently used:
+
+eloop.c and eloop.h
+ Event loop (select() loop with registerable timeouts, socket read
+ callbacks, and signal callbacks)
+
+common.c and common.h
+ Common helper functions
+
+defs.h
+ Definitions shared by multiple files
+
+l2_packet.h, l2_packet_linux.c, and l2_packet_pcap.c
+ Layer 2 (link) access wrapper (includes native Linux implementation
+ and wrappers for libdnet/libpcap). A new l2_packet implementation
+ may need to be added when porting to new operating systems that are
+ not supported by libdnet/libpcap. Makefile can be used to select which
+ l2_packet implementation is included. l2_packet_linux.c uses Linux
+ packet sockets and l2_packet_pcap.c has a more portable version using
+ libpcap and libdnet.
+
+pcsc_funcs.c and pcsc_funcs.h
+ Wrapper for PC/SC lite SIM and smart card readers
+
+priv_netlink.h
+ Private version of netlink definitions from Linux kernel header files;
+ this could be replaced with C library header file once suitable
+ version becomes commonly available
+
+version.h
+ Version number definitions
+
+wireless_copy.h
+ Private version of Linux wireless extensions definitions from kernel
+ header files; this could be replaced with C library header file once
+ suitable version becomes commonly available
+
+
+\section crypto_func Cryptographic functions
+
+md5.c and md5.h
+ MD5 (replaced with a crypto library if TLS support is included)
+ HMAC-MD5 (keyed checksum for message authenticity validation)
+
+rc4.c and rc4.h
+ RC4 (broadcast/default key encryption)
+
+sha1.c and sha1.h
+ SHA-1 (replaced with a crypto library if TLS support is included)
+ HMAC-SHA-1 (keyed checksum for message authenticity validation)
+ PRF-SHA-1 (pseudorandom (key/nonce generation) function)
+ PBKDF2-SHA-1 (ASCII passphrase to shared secret)
+ T-PRF (for EAP-FAST)
+ TLS-PRF (RFC 2246)
+
+aes_wrap.c, aes_wrap.h, aes.c
+ AES (replaced with a crypto library if TLS support is included),
+ AES Key Wrap Algorithm with 128-bit KEK, RFC3394 (broadcast/default
+ key encryption),
+ One-Key CBC MAC (OMAC1) hash with AES-128,
+ AES-128 CTR mode encryption,
+ AES-128 EAX mode encryption/decryption,
+ AES-128 CBC
+
+crypto.h
+ Definition of crypto library wrapper
+
+crypto.c
+ Wrapper functions for libcrypto (OpenSSL)
+
+crypto_gnutls.c
+ Wrapper functions for libgcrypt (used by GnuTLS)
+
+ms_funcs.c and ms_funcs.h
+ Helper functions for MSCHAPV2 and LEAP
+
+tls.h
+ Definition of TLS library wrapper
+
+tls_none.c
+ Dummy implementation of TLS library wrapper for cases where TLS
+ functionality is not included.
+
+tls_openssl.c
+ TLS library wrapper for openssl
+
+tls_gnutls.c
+ TLS library wrapper for GnuTLS
+
+
+\section configuration Configuration
+
+config_ssid.h
+ Definition of per network configuration items
+
+config.h
+ Definition of the %wpa_supplicant configuration
+
+config.c
+ Configuration parser and common functions
+
+config_file.c
+ Configuration backend for text files (e.g., wpa_supplicant.conf)
+
+
+\section ctrl_iface Control interface
+
+%wpa_supplicant has a \ref ctrl_iface_page "control interface"
+that can be used to get status
+information and manage operations from external programs. An example
+command line interface (wpa_cli) and GUI (wpa_gui) for this interface
+are included in the %wpa_supplicant distribution.
+
+ctrl_iface.c and ctrl_iface.h
+ %wpa_supplicant-side of the control interface
+
+wpa_ctrl.c and wpa_ctrl.h
+ Library functions for external programs to provide access to the
+ %wpa_supplicant control interface
+
+wpa_cli.c
+ Example program for using %wpa_supplicant control interface
+
+
+\section wpa_code WPA supplicant
+
+wpa.c and wpa.h
+ WPA state machine and 4-Way/Group Key Handshake processing
+
+preauth.c and preauth.h
+ PMKSA caching and pre-authentication (RSN/WPA2)
+
+wpa_i.h
+ Internal definitions for WPA code; not to be included to other modules.
+
+\section eap_peer EAP peer
+
+\ref eap_module "EAP peer implementation" is a separate module that
+can be used by other programs than just %wpa_supplicant.
+
+eap.c and eap.h
+ EAP state machine and method interface
+
+eap_defs.h
+ Common EAP definitions
+
+eap_i.h
+ Internal definitions for EAP state machine and EAP methods; not to be
+ included in other modules
+
+eap_sim_common.c and eap_sim_common.h
+ Common code for EAP-SIM and EAP-AKA
+
+eap_tls_common.c and eap_tls_common.h
+ Common code for EAP-PEAP, EAP-TTLS, and EAP-FAST
+
+eap_tlv.c and eap_tlv.h
+ EAP-TLV code for EAP-PEAP and EAP-FAST
+
+eap_ttls.c and eap_ttls.h
+ EAP-TTLS
+
+eap_pax.c, eap_pax_common.h, eap_pax_common.c
+ EAP-PAX
+
+eap_psk.c, eap_psk_common.h, eap_psk_common.c
+ EAP-PSK (note: this is not needed for WPA-PSK)
+
+eap_aka.c, eap_fast.c, eap_gtc.c, eap_leap.c, eap_md5.c, eap_mschapv2.c,
+eap_otp.c, eap_peap.c, eap_sim.c, eap_tls.c
+ Other EAP method implementations
+
+
+\section eapol_supp EAPOL supplicant
+
+eapol_sm.c and eapol_sm.h
+ EAPOL supplicant state machine and IEEE 802.1X processing
+
+
+\section win_port Windows port
+
+ndis_events.cpp
+ External program for receiving NdisMIndicateStatus() events and
+ delivering them to %wpa_supplicant in more easier to use form
+
+win_if_list.c
+ External program for listing current network interface
+
+
+\section test_programs Test programs
+
+radius_client.c and radius_client.h
+ RADIUS authentication client implementation for eapol_test
+
+radius.c and radius.h
+ RADIUS message processing for eapol_test
+
+config_types.h and hostapd.h
+ Minimal version of hostapd header files for eapol_test
+
+eapol_test.c
+ Standalone EAP testing tool with integrated RADIUS authentication
+ client
+
+preauth_test.c
+ Standalone RSN pre-authentication tool
+
+wpa_passphrase.c
+ WPA ASCII passphrase to PSK conversion
+
+*/
diff --git a/contrib/wpa_supplicant/doc/ctrl_iface.doxygen b/contrib/wpa_supplicant/doc/ctrl_iface.doxygen
new file mode 100644
index 000000000000..fd1b9c406bab
--- /dev/null
+++ b/contrib/wpa_supplicant/doc/ctrl_iface.doxygen
@@ -0,0 +1,409 @@
+/**
+\page ctrl_iface_page Control interface
+
+%wpa_supplicant implements a control interface that can be used by
+external programs to control the operations of the %wpa_supplicant
+daemon and to get status information and event notifications. There is
+a small C library, in a form of a single C file, wpa_ctrl.c, that
+provides helper functions to facilitate the use of the control
+interface. External programs can link this file into them and then use
+the library functions documented in wpa_ctrl.h to interact with
+%wpa_supplicant. This library can also be used with C++. wpa_cli.c and
+wpa_gui are example programs using this library.
+
+There are multiple mechanisms for inter-process communication. For
+example, Linux version of %wpa_supplicant is using UNIX domain sockets
+for the control interface and Windows version UDP sockets. The use of
+the functions defined in wpa_ctrl.h can be used to hide the details of
+the used IPC from external programs.
+
+
+\section using_ctrl_iface Using the control interface
+
+External programs, e.g., a GUI or a configuration utility, that need to
+communicate with %wpa_supplicant should link in wpa_ctrl.c. This
+allows them to use helper functions to open connection to the control
+interface with wpa_ctrl_open() and to send commands with
+wpa_ctrl_request().
+
+%wpa_supplicant uses the control interface for two types of communication:
+commands and unsolicited event messages. Commands are a pair of
+messages, a request from the external program and a response from
+%wpa_supplicant. These can be executed using wpa_ctrl_request().
+Unsolicited event messages are sent by %wpa_supplicant to the control
+interface connection without specific request from the external program
+for receiving each message. However, the external program needs to
+attach to the control interface with wpa_ctrl_attach() to receive these
+unsolicited messages.
+
+If the control interface connection is used both for commands and
+unsolicited event messages, there is potential for receiving an
+unsolicited message between the command request and response.
+wpa_ctrl_request() caller will need to supply a callback, msg_cb,
+for processing these messages. Often it is easier to open two
+control interface connections by calling wpa_ctrl_open() twice and
+then use one of the connections for commands and the other one for
+unsolicited messages. This way command request/response pairs will
+not be broken by unsolicited messages. wpa_cli is an example of how
+to use only one connection for both purposes and wpa_gui demonstrates
+how to use two separate connections.
+
+Once the control interface connection is not needed anymore, it should
+be closed by calling wpa_ctrl_close(). If the connection was used for
+unsolicited event messages, it should be first detached by calling
+wpa_ctrl_detach().
+
+
+\section ctrl_iface_cmds Control interface commands
+
+Following commands can be used with wpa_ctrl_request():
+
+\subsection ctrl_iface_PING PING
+
+This command can be used to test whether %wpa_supplicant is replying
+to the control interface commands. The expected reply is \c PONG if the
+connection is open and %wpa_supplicant is processing commands.
+
+
+\subsection ctrl_iface_MIB MIB
+
+Request a list of MIB variables (dot1x, dot11). The output is a text
+block with each line in \c variable=value format. For example:
+
+\verbatim
+dot11RSNAOptionImplemented=TRUE
+dot11RSNAPreauthenticationImplemented=TRUE
+dot11RSNAEnabled=FALSE
+dot11RSNAPreauthenticationEnabled=FALSE
+dot11RSNAConfigVersion=1
+dot11RSNAConfigPairwiseKeysSupported=5
+dot11RSNAConfigGroupCipherSize=128
+dot11RSNAConfigPMKLifetime=43200
+dot11RSNAConfigPMKReauthThreshold=70
+dot11RSNAConfigNumberOfPTKSAReplayCounters=1
+dot11RSNAConfigSATimeout=60
+dot11RSNAAuthenticationSuiteSelected=00-50-f2-2
+dot11RSNAPairwiseCipherSelected=00-50-f2-4
+dot11RSNAGroupCipherSelected=00-50-f2-4
+dot11RSNAPMKIDUsed=
+dot11RSNAAuthenticationSuiteRequested=00-50-f2-2
+dot11RSNAPairwiseCipherRequested=00-50-f2-4
+dot11RSNAGroupCipherRequested=00-50-f2-4
+dot11RSNAConfigNumberOfGTKSAReplayCounters=0
+dot11RSNA4WayHandshakeFailures=0
+dot1xSuppPaeState=5
+dot1xSuppHeldPeriod=60
+dot1xSuppAuthPeriod=30
+dot1xSuppStartPeriod=30
+dot1xSuppMaxStart=3
+dot1xSuppSuppControlledPortStatus=Authorized
+dot1xSuppBackendPaeState=2
+dot1xSuppEapolFramesRx=0
+dot1xSuppEapolFramesTx=440
+dot1xSuppEapolStartFramesTx=2
+dot1xSuppEapolLogoffFramesTx=0
+dot1xSuppEapolRespFramesTx=0
+dot1xSuppEapolReqIdFramesRx=0
+dot1xSuppEapolReqFramesRx=0
+dot1xSuppInvalidEapolFramesRx=0
+dot1xSuppEapLengthErrorFramesRx=0
+dot1xSuppLastEapolFrameVersion=0
+dot1xSuppLastEapolFrameSource=00:00:00:00:00:00
+\endverbatim
+
+
+\subsection ctrl_iface_STATUS STATUS
+
+Request current WPA/EAPOL/EAP status information. The output is a text
+block with each line in \c variable=value format. For example:
+
+\verbatim
+bssid=02:00:01:02:03:04
+ssid=test network
+pairwise_cipher=CCMP
+group_cipher=CCMP
+key_mgmt=WPA-PSK
+wpa_state=COMPLETED
+ip_address=192.168.1.21
+Supplicant PAE state=AUTHENTICATED
+suppPortStatus=Authorized
+EAP state=SUCCESS
+\endverbatim
+
+
+\subsection ctrl_iface_STATUS-VERBOSE STATUS-VERBOSE
+
+Same as STATUS, but with more verbosity (i.e., more \c variable=value pairs).
+
+\verbatim
+bssid=02:00:01:02:03:04
+ssid=test network
+pairwise_cipher=CCMP
+group_cipher=CCMP
+key_mgmt=WPA-PSK
+wpa_state=COMPLETED
+ip_address=192.168.1.21
+Supplicant PAE state=AUTHENTICATED
+suppPortStatus=Authorized
+heldPeriod=60
+authPeriod=30
+startPeriod=30
+maxStart=3
+portControl=Auto
+Supplicant Backend state=IDLE
+EAP state=SUCCESS
+reqMethod=0
+methodState=NONE
+decision=COND_SUCC
+ClientTimeout=60
+\endverbatim
+
+
+\subsection ctrl_iface_PMKSA PMKSA
+
+Show PMKSA cache
+
+\verbatim
+Index / AA / PMKID / expiration (in seconds) / opportunistic
+1 / 02:00:01:02:03:04 / 000102030405060708090a0b0c0d0e0f / 41362 / 0
+2 / 02:00:01:33:55:77 / 928389281928383b34afb34ba4212345 / 362 / 1
+\endverbatim
+
+
+\subsection ctrl_iface_SET SET <variable> <value>
+
+Set variables:
+- EAPOL::heldPeriod
+- EAPOL::authPeriod
+- EAPOL::startPeriod
+- EAPOL::maxStart
+- dot11RSNAConfigPMKLifetime
+- dot11RSNAConfigPMKReauthThreshold
+- dot11RSNAConfigSATimeout
+
+Example command:
+\verbatim
+SET EAPOL::heldPeriod 45
+\endverbatim
+
+
+\subsection ctrl_iface_LOGON LOGON
+
+IEEE 802.1X EAPOL state machine logon.
+
+
+\subsection ctrl_iface_LOGOFF LOGOFF
+
+IEEE 802.1X EAPOL state machine logoff.
+
+
+\subsection ctrl_iface_REASSOCIATE REASSOCIATE
+
+Force reassociation.
+
+
+\subsection ctrl_iface_PREAUTH PREAUTH <BSSID>
+
+Start pre-authentication with the given BSSID.
+
+
+\subsection ctrl_iface_ATTACH ATTACH
+
+Attach the connection as a monitor for unsolicited events. This can
+be done with wpa_ctrl_attach().
+
+
+\subsection ctrl_iface_DETACH DETACH
+
+Detach the connection as a monitor for unsolicited events. This can
+be done with wpa_ctrl_detach().
+
+
+\subsection ctrl_iface_LEVEL LEVEL <debug level>
+
+Change debug level.
+
+
+\subsection ctrl_iface_RECONFIGURE RECONFIGURE
+
+Force %wpa_supplicant to re-read its configuration data.
+
+
+\subsection ctrl_iface_TERMINATE TERMINATE
+
+Terminate %wpa_supplicant process.
+
+
+\subsection ctrl_iface_BSSID BSSID <network id> <BSSID>
+
+Set preferred BSSID for a network. Network id can be received from the
+\c LIST_NETWORKS command output.
+
+
+\subsection ctrl_iface_LIST_NETWORKS LIST_NETWORKS
+
+List configured networks.
+
+\verbatim
+network id / ssid / bssid / flags
+0 example network any [CURRENT]
+\endverbatim
+
+(note: fields are separated with tabs)
+
+
+\subsection ctrl_iface_DISCONNECT DISCONNECT
+
+Disconnect and wait for \c REASSOCIATE command before connecting.
+
+
+\subsection ctrl_iface_SCAN SCAN
+
+Request a new BSS scan.
+
+
+\subsection ctrl_iface_SCAN_RESULTS SCAN_RESULTS
+
+Get the latest scan results.
+
+\verbatim
+bssid / frequency / signal level / flags / ssid
+00:09:5b:95:e0:4e 2412 208 [WPA-PSK-CCMP] jkm private
+02:55:24:33:77:a3 2462 187 [WPA-PSK-TKIP] testing
+00:09:5b:95:e0:4f 2412 209 jkm guest
+\endverbatim
+
+(note: fields are separated with tabs)
+
+
+\subsection ctrl_iface_SELECT_NETWORK SELECT_NETWORK <network id>
+
+Select a network (disable others). Network id can be received from the
+\c LIST_NETWORKS command output.
+
+
+\subsection ctrl_iface_ENABLE_NETWORK ENABLE_NETWORK <network id>
+
+Enable a network. Network id can be received from the
+\c LIST_NETWORKS command output.
+
+
+\subsection ctrl_iface_DISABLE_NETWORK DISABLE_NETWORK <network id>
+
+Disable a network. Network id can be received from the
+\c LIST_NETWORKS command output.
+
+
+\subsection ctrl_iface_ADD_NETWORK ADD_NETWORK
+
+Add a new network. This command creates a new network with empty
+configuration. The new network is disabled and once it has been
+configured it can be enabled with \c ENABLE_NETWORK command. \c ADD_NETWORK
+returns the network id of the new network or FAIL on failure.
+
+
+\subsection ctrl_iface_REMOVE_NETWORK REMOVE_NETWORK <network id>
+
+Remove a network. Network id can be received from the
+\c LIST_NETWORKS command output.
+
+
+\subsection ctrl_iface_SET_NETWORK SET_NETWORK <network id> <variable> <value>
+
+Set network variables. Network id can be received from the
+\c LIST_NETWORKS command output.
+
+This command uses the same variables and data formats as the
+configuration file. See example wpa_supplicant.conf for more details.
+
+- ssid (network name, SSID)
+- psk (WPA passphrase or pre-shared key)
+- key_mgmt (key management protocol)
+- identity (EAP identity)
+- password (EAP password)
+- ...
+
+
+\subsection ctrl_iface_GET_NETWORK GET_NETWORK <network id> <variable>
+
+Get network variables. Network id can be received from the
+\c LIST_NETWORKS command output.
+
+
+\subsection ctrl_iface_SAVE_CONFIG SAVE_CONFIG
+
+Save the current configuration.
+
+
+\section ctrl_iface_interactive Interactive requests
+
+If %wpa_supplicant needs additional information during authentication
+(e.g., password), it will use a specific prefix, \c CTRL-REQ-
+(\a WPA_CTRL_REQ macro) in an unsolicited event message. An external
+program, e.g., a GUI, can provide such information by using
+\c CTRL-RSP- (\a WPA_CTRL_RSP macro) prefix in a command with matching
+field name.
+
+The following fields can be requested in this way from the user:
+- IDENTITY (EAP identity/user name)
+- PASSWORD (EAP password)
+- NEW_PASSWORD (New password if the server is requesting password change)
+- PIN (PIN code for accessing a SIM or smartcard)
+- OTP (one-time password; like password, but the value is used only once)
+- PASSPHRASE (passphrase for a private key file)
+
+\verbatim
+CTRL-REQ-<field name>-<network id>-<human readable text>
+CTRL-RSP-<field name>-<network id>-<value>
+\endverbatim
+
+For example, request from %wpa_supplicant:
+\verbatim
+CTRL-REQ-PASSWORD-1-Password needed for SSID test-network
+\endverbatim
+
+And a matching reply from the GUI:
+\verbatim
+CTRL-RSP-PASSWORD-1-secret
+\endverbatim
+
+
+\subsection ctrl_iface_GET_CAPABILITY GET_CAPABILITY <option>
+
+Get list of supported functionality (eap, pairwise, group,
+proto). Supported functionality is shown as space separate lists of
+values used in the same format as in %wpa_supplicant configuration.
+
+Example request/reply pairs:
+
+\verbatim
+GET_CAPABILITY eap
+AKA FAST GTC LEAP MD5 MSCHAPV2 OTP PAX PEAP PSK SIM TLS TTLS
+\endverbatim
+
+\verbatim
+GET_CAPABILITY pairwise
+CCMP TKIP NONE
+\endverbatim
+
+\verbatim
+GET_CAPABILITY group
+CCMP TKIP WEP104 WEP40
+\endverbatim
+
+\verbatim
+GET_CAPABILITY key_mgmt
+WPA-PSK WPA-EAP IEEE8021X NONE
+\endverbatim
+
+\verbatim
+GET_CAPABILITY proto
+RSN WPA
+\endverbatim
+
+\verbatim
+GET_CAPABILITY auth_alg
+OPEN SHARED LEAP
+\endverbatim
+
+*/
diff --git a/contrib/wpa_supplicant/doc/docbook/Makefile b/contrib/wpa_supplicant/doc/docbook/Makefile
new file mode 100644
index 000000000000..15c019c960b2
--- /dev/null
+++ b/contrib/wpa_supplicant/doc/docbook/Makefile
@@ -0,0 +1,25 @@
+all: man html pdf
+
+FILES += wpa_background
+FILES += wpa_cli
+FILES += wpa_passphrase
+FILES += wpa_supplicant.conf
+FILES += wpa_supplicant
+
+man:
+ for i in $(FILES); do docbook2man $$i.sgml; done
+
+html:
+ for i in $(FILES); do docbook2html $$i.sgml && \
+ mv index.html $$i.html; done
+
+pdf:
+ for i in $(FILES); do docbook2pdf $$i.sgml; done
+
+
+clean:
+ rm -f wpa_background.8 wpa_cli.8 wpa_passphrase.8 wpa_supplicant.8
+ rm -f wpa_supplicant.conf.5
+ rm -f manpage.links manpage.refs
+ rm -f $(FILES:%=%.pdf)
+ rm -f $(FILES:%=%.html)
diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_background.8 b/contrib/wpa_supplicant/doc/docbook/wpa_background.8
new file mode 100644
index 000000000000..3a7be2817c26
--- /dev/null
+++ b/contrib/wpa_supplicant/doc/docbook/wpa_background.8
@@ -0,0 +1,84 @@
+.\" This manpage has been automatically generated by docbook2man
+.\" from a DocBook document. This tool can be found at:
+.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/>
+.\" Please send any bug reports, improvements, comments, patches,
+.\" etc. to Steve Cheng <steve@ggi-project.org>.
+.TH "WPA_BACKGROUND" "8" "08 February 2006" "" ""
+
+.SH NAME
+wpa_background \- Background information on Wi-Fi Protected Access and IEEE 802.11i
+.SH "WPA"
+.PP
+The original security mechanism of IEEE 802.11 standard was
+not designed to be strong and has proven to be insufficient for
+most networks that require some kind of security. Task group I
+(Security) of IEEE 802.11 working group
+(http://www.ieee802.org/11/) has worked to address the flaws of
+the base standard and has in practice completed its work in May
+2004. The IEEE 802.11i amendment to the IEEE 802.11 standard was
+approved in June 2004 and published in July 2004.
+.PP
+Wi-Fi Alliance (http://www.wi-fi.org/) used a draft version
+of the IEEE 802.11i work (draft 3.0) to define a subset of the
+security enhancements that can be implemented with existing wlan
+hardware. This is called Wi-Fi Protected Access<TM> (WPA). This
+has now become a mandatory component of interoperability testing
+and certification done by Wi-Fi Alliance. Wi-Fi provides
+information about WPA at its web site
+(http://www.wi-fi.org/OpenSection/protected_access.asp).
+.PP
+IEEE 802.11 standard defined wired equivalent privacy (WEP)
+algorithm for protecting wireless networks. WEP uses RC4 with
+40-bit keys, 24-bit initialization vector (IV), and CRC32 to
+protect against packet forgery. All these choices have proven to
+be insufficient: key space is too small against current attacks,
+RC4 key scheduling is insufficient (beginning of the pseudorandom
+stream should be skipped), IV space is too small and IV reuse
+makes attacks easier, there is no replay protection, and non-keyed
+authentication does not protect against bit flipping packet
+data.
+.PP
+WPA is an intermediate solution for the security issues. It
+uses Temporal Key Integrity Protocol (TKIP) to replace WEP. TKIP
+is a compromise on strong security and possibility to use existing
+hardware. It still uses RC4 for the encryption like WEP, but with
+per-packet RC4 keys. In addition, it implements replay protection,
+keyed packet authentication mechanism (Michael MIC).
+.PP
+Keys can be managed using two different mechanisms. WPA can
+either use an external authentication server (e.g., RADIUS) and
+EAP just like IEEE 802.1X is using or pre-shared keys without need
+for additional servers. Wi-Fi calls these "WPA-Enterprise" and
+"WPA-Personal", respectively. Both mechanisms will generate a
+master session key for the Authenticator (AP) and Supplicant
+(client station).
+.PP
+WPA implements a new key handshake (4-Way Handshake and
+Group Key Handshake) for generating and exchanging data encryption
+keys between the Authenticator and Supplicant. This handshake is
+also used to verify that both Authenticator and Supplicant know
+the master session key. These handshakes are identical regardless
+of the selected key management mechanism (only the method for
+generating master session key changes).
+.SH "IEEE 802.11I / WPA2"
+.PP
+The design for parts of IEEE 802.11i that were not included
+in WPA has finished (May 2004) and this amendment to IEEE 802.11
+was approved in June 2004. Wi-Fi Alliance is using the final IEEE
+802.11i as a new version of WPA called WPA2. This includes, e.g.,
+support for more robust encryption algorithm (CCMP: AES in Counter
+mode with CBC-MAC) to replace TKIP and optimizations for handoff
+(reduced number of messages in initial key handshake,
+pre-authentication, and PMKSA caching).
+.SH "SEE ALSO"
+.PP
+\fBwpa_supplicant\fR(8)
+.SH "LEGAL"
+.PP
+wpa_supplicant is copyright (c) 2003-2005,
+Jouni Malinen <jkmaline@cc.hut.fi> and
+contributors.
+All Rights Reserved.
+.PP
+This program is dual-licensed under both the GPL version 2
+and BSD license. Either license may be used at your option.
diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_background.sgml b/contrib/wpa_supplicant/doc/docbook/wpa_background.sgml
new file mode 100644
index 000000000000..dc6436025393
--- /dev/null
+++ b/contrib/wpa_supplicant/doc/docbook/wpa_background.sgml
@@ -0,0 +1,101 @@
+<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+
+<refentry>
+ <refmeta>
+ <refentrytitle>wpa_background</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>wpa_background</refname>
+ <refpurpose>Background information on Wi-Fi Protected Access and IEEE 802.11i</refpurpose>
+ </refnamediv>
+ <refsect1>
+ <title>WPA</title>
+
+ <para>The original security mechanism of IEEE 802.11 standard was
+ not designed to be strong and has proven to be insufficient for
+ most networks that require some kind of security. Task group I
+ (Security) of IEEE 802.11 working group
+ (http://www.ieee802.org/11/) has worked to address the flaws of
+ the base standard and has in practice completed its work in May
+ 2004. The IEEE 802.11i amendment to the IEEE 802.11 standard was
+ approved in June 2004 and published in July 2004.</para>
+
+ <para>Wi-Fi Alliance (http://www.wi-fi.org/) used a draft version
+ of the IEEE 802.11i work (draft 3.0) to define a subset of the
+ security enhancements that can be implemented with existing wlan
+ hardware. This is called Wi-Fi Protected Access&lt;TM&gt; (WPA). This
+ has now become a mandatory component of interoperability testing
+ and certification done by Wi-Fi Alliance. Wi-Fi provides
+ information about WPA at its web site
+ (http://www.wi-fi.org/OpenSection/protected_access.asp).</para>
+
+ <para>IEEE 802.11 standard defined wired equivalent privacy (WEP)
+ algorithm for protecting wireless networks. WEP uses RC4 with
+ 40-bit keys, 24-bit initialization vector (IV), and CRC32 to
+ protect against packet forgery. All these choices have proven to
+ be insufficient: key space is too small against current attacks,
+ RC4 key scheduling is insufficient (beginning of the pseudorandom
+ stream should be skipped), IV space is too small and IV reuse
+ makes attacks easier, there is no replay protection, and non-keyed
+ authentication does not protect against bit flipping packet
+ data.</para>
+
+ <para>WPA is an intermediate solution for the security issues. It
+ uses Temporal Key Integrity Protocol (TKIP) to replace WEP. TKIP
+ is a compromise on strong security and possibility to use existing
+ hardware. It still uses RC4 for the encryption like WEP, but with
+ per-packet RC4 keys. In addition, it implements replay protection,
+ keyed packet authentication mechanism (Michael MIC).</para>
+
+ <para>Keys can be managed using two different mechanisms. WPA can
+ either use an external authentication server (e.g., RADIUS) and
+ EAP just like IEEE 802.1X is using or pre-shared keys without need
+ for additional servers. Wi-Fi calls these "WPA-Enterprise" and
+ "WPA-Personal", respectively. Both mechanisms will generate a
+ master session key for the Authenticator (AP) and Supplicant
+ (client station).</para>
+
+ <para>WPA implements a new key handshake (4-Way Handshake and
+ Group Key Handshake) for generating and exchanging data encryption
+ keys between the Authenticator and Supplicant. This handshake is
+ also used to verify that both Authenticator and Supplicant know
+ the master session key. These handshakes are identical regardless
+ of the selected key management mechanism (only the method for
+ generating master session key changes).</para>
+ </refsect1>
+
+ <refsect1>
+ <title>IEEE 802.11i / WPA2</title>
+
+ <para>The design for parts of IEEE 802.11i that were not included
+ in WPA has finished (May 2004) and this amendment to IEEE 802.11
+ was approved in June 2004. Wi-Fi Alliance is using the final IEEE
+ 802.11i as a new version of WPA called WPA2. This includes, e.g.,
+ support for more robust encryption algorithm (CCMP: AES in Counter
+ mode with CBC-MAC) to replace TKIP and optimizations for handoff
+ (reduced number of messages in initial key handshake,
+ pre-authentication, and PMKSA caching).</para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry>
+ <refentrytitle>wpa_supplicant</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Legal</title>
+ <para>wpa_supplicant is copyright (c) 2003-2005,
+ Jouni Malinen <email>jkmaline@cc.hut.fi</email> and
+ contributors.
+ All Rights Reserved.</para>
+
+ <para>This program is dual-licensed under both the GPL version 2
+ and BSD license. Either license may be used at your option.</para>
+ </refsect1>
+</refentry>
diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_cli.8 b/contrib/wpa_supplicant/doc/docbook/wpa_cli.8
new file mode 100644
index 000000000000..ad039b548b31
--- /dev/null
+++ b/contrib/wpa_supplicant/doc/docbook/wpa_cli.8
@@ -0,0 +1,202 @@
+.\" This manpage has been automatically generated by docbook2man
+.\" from a DocBook document. This tool can be found at:
+.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/>
+.\" Please send any bug reports, improvements, comments, patches,
+.\" etc. to Steve Cheng <steve@ggi-project.org>.
+.TH "WPA_CLI" "8" "08 February 2006" "" ""
+
+.SH NAME
+wpa_cli \- WPA command line client
+.SH SYNOPSIS
+
+\fBwpa_cli\fR [ \fB-p \fIpath to ctrl sockets\fB\fR ] [ \fB-i \fIifname\fB\fR ] [ \fB-hvB\fR ] [ \fB-a \fIaction file\fB\fR ] [ \fB-P \fIpid file\fB\fR ] [ \fB\fIcommand ...\fB\fR ]
+
+.SH "OVERVIEW"
+.PP
+wpa_cli is a text-based frontend program for interacting
+with wpa_supplicant. It is used to query current status, change
+configuration, trigger events, and request interactive user
+input.
+.PP
+wpa_cli can show the current authentication status, selected
+security mode, dot11 and dot1x MIBs, etc. In addition, it can
+configure some variables like EAPOL state machine parameters and
+trigger events like reassociation and IEEE 802.1X
+logoff/logon. wpa_cli provides a user interface to request
+authentication information, like username and password, if these
+are not included in the configuration. This can be used to
+implement, e.g., one-time-passwords or generic token card
+authentication where the authentication is based on a
+challenge-response that uses an external device for generating the
+response.
+.PP
+The control interface of wpa_supplicant can be configured to
+allow non-root user access (ctrl_interface_group in the
+configuration file). This makes it possible to run wpa_cli with a
+normal user account.
+.PP
+wpa_cli supports two modes: interactive and command
+line. Both modes share the same command set and the main
+difference is in interactive mode providing access to unsolicited
+messages (event messages, username/password requests).
+.PP
+Interactive mode is started when wpa_cli is executed without
+including the command as a command line parameter. Commands are
+then entered on the wpa_cli prompt. In command line mode, the same
+commands are entered as command line arguments for wpa_cli.
+.SH "INTERACTIVE AUTHENTICATION PARAMETERS REQUEST"
+.PP
+When wpa_supplicant need authentication parameters, like
+username and password, which are not present in the configuration
+file, it sends a request message to all attached frontend programs,
+e.g., wpa_cli in interactive mode. wpa_cli shows these requests
+with "CTRL-REQ-<type>-<id>:<text>"
+prefix. <type> is IDENTITY, PASSWORD, or OTP
+(one-time-password). <id> is a unique identifier for the
+current network. <text> is description of the request. In
+case of OTP request, it includes the challenge from the
+authentication server.
+.PP
+The reply to these requests can be given with 'identity',
+'password', and 'otp' commands. <id> needs to be copied from the
+the matching request. 'password' and 'otp' commands can be used
+regardless of whether the request was for PASSWORD or OTP. The
+main difference between these two commands is that values given
+with 'password' are remembered as long as wpa_supplicant is
+running whereas values given with 'otp' are used only once and
+then forgotten, i.e., wpa_supplicant will ask frontend for a new
+value for every use. This can be used to implement
+one-time-password lists and generic token card -based
+authentication.
+.PP
+Example request for password and a matching reply:
+.sp
+.RS
+
+.nf
+CTRL-REQ-PASSWORD-1:Password needed for SSID foobar
+> password 1 mysecretpassword
+.fi
+.RE
+.PP
+Example request for generic token card challenge-response:
+.sp
+.RS
+
+.nf
+CTRL-REQ-OTP-2:Challenge 1235663 needed for SSID foobar
+> otp 2 9876
+.fi
+.RE
+.SH "COMMAND ARGUMENTS"
+.TP
+\fB-p path\fR
+Change the path where control sockets should
+be found.
+.TP
+\fB-i ifname\fR
+Specify the interface that is being
+configured. By default, choose the first interface found with
+a control socket in the socket path.
+.TP
+\fB-h\fR
+Help. Show a usage message.
+.TP
+\fB-v\fR
+Show version information.
+.TP
+\fB-B\fR
+Run as a daemon in the background.
+.TP
+\fB-a file\fR
+Run in daemon mode executing the action file
+based on events from wpa_supplicant. The specified file will
+be executed with the first argument set to interface name and
+second to "CONNECT" or "DISCONNECT" depending on the event.
+This can be used
+.TP
+\fB-P file\fR
+Set the location of the PID
+file.
+.TP
+\fBcommand\fR
+Run a command. The available commands are
+listed in the next section.
+.SH "COMMANDS"
+.PP
+The following commands are available:
+.TP
+\fBstatus\fR
+get current WPA/EAPOL/EAP status
+.TP
+\fBmib\fR
+get MIB variables (dot1x, dot11)
+.TP
+\fBhelp\fR
+show this usage help
+.TP
+\fBinterface [ifname]\fR
+show interfaces/select interface
+.TP
+\fBlevel <debug level>\fR
+change debug level
+.TP
+\fBlicense\fR
+show full wpa_cli license
+.TP
+\fBlogoff\fR
+IEEE 802.1X EAPOL state machine logoff
+.TP
+\fBlogon\fR
+IEEE 802.1X EAPOL state machine logon
+.TP
+\fBset\fR
+set variables (shows list of variables when run without arguments)
+.TP
+\fBpmksa\fR
+show PMKSA cache
+.TP
+\fBreassociate\fR
+force reassociation
+.TP
+\fBreconfigure\fR
+force wpa_supplicant to re-read its configuration file
+.TP
+\fBpreauthenticate <BSSID>\fR
+force preauthentication
+.TP
+\fBidentity <network id> <identity>\fR
+configure identity for an SSID
+.TP
+\fBpassword <network id> <password>\fR
+configure password for an SSID
+.TP
+\fBpin <network id> <pin>\fR
+configure pin for an SSID
+.TP
+\fBotp <network id> <password>\fR
+configure one-time-password for an SSID
+.TP
+\fBbssid *lt;network id> <BSSID>\fR
+set preferred BSSID for an SSID
+.TP
+\fBlist_networks\fR
+list configured networks
+.TP
+\fBterminate\fR
+terminate \fBwpa_supplicant\fR
+.TP
+\fBquit\fR
+exit wpa_cli
+.SH "SEE ALSO"
+.PP
+\fBwpa_supplicant\fR(8)
+.SH "LEGAL"
+.PP
+wpa_supplicant is copyright (c) 2003-2005,
+Jouni Malinen <jkmaline@cc.hut.fi> and
+contributors.
+All Rights Reserved.
+.PP
+This program is dual-licensed under both the GPL version 2
+and BSD license. Either license may be used at your option.
diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_cli.sgml b/contrib/wpa_supplicant/doc/docbook/wpa_cli.sgml
new file mode 100644
index 000000000000..e8042397a7d7
--- /dev/null
+++ b/contrib/wpa_supplicant/doc/docbook/wpa_cli.sgml
@@ -0,0 +1,330 @@
+<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+
+<refentry>
+ <refmeta>
+ <refentrytitle>wpa_cli</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>wpa_cli</refname>
+
+ <refpurpose>WPA command line client</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>wpa_cli</command>
+ <arg>-p <replaceable>path to ctrl sockets</replaceable></arg>
+ <arg>-i <replaceable>ifname</replaceable></arg>
+ <arg>-hvB</arg>
+ <arg>-a <replaceable>action file</replaceable></arg>
+ <arg>-P <replaceable>pid file</replaceable></arg>
+ <arg><replaceable>command ...</replaceable></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Overview</title>
+
+ <para>wpa_cli is a text-based frontend program for interacting
+ with wpa_supplicant. It is used to query current status, change
+ configuration, trigger events, and request interactive user
+ input.</para>
+
+ <para>wpa_cli can show the current authentication status, selected
+ security mode, dot11 and dot1x MIBs, etc. In addition, it can
+ configure some variables like EAPOL state machine parameters and
+ trigger events like reassociation and IEEE 802.1X
+ logoff/logon. wpa_cli provides a user interface to request
+ authentication information, like username and password, if these
+ are not included in the configuration. This can be used to
+ implement, e.g., one-time-passwords or generic token card
+ authentication where the authentication is based on a
+ challenge-response that uses an external device for generating the
+ response.</para>
+
+ <para>The control interface of wpa_supplicant can be configured to
+ allow non-root user access (ctrl_interface_group in the
+ configuration file). This makes it possible to run wpa_cli with a
+ normal user account.</para>
+
+ <para>wpa_cli supports two modes: interactive and command
+ line. Both modes share the same command set and the main
+ difference is in interactive mode providing access to unsolicited
+ messages (event messages, username/password requests).</para>
+
+ <para>Interactive mode is started when wpa_cli is executed without
+ including the command as a command line parameter. Commands are
+ then entered on the wpa_cli prompt. In command line mode, the same
+ commands are entered as command line arguments for wpa_cli.</para>
+ </refsect1>
+ <refsect1>
+ <title>Interactive authentication parameters request</title>
+
+ <para>When wpa_supplicant need authentication parameters, like
+ username and password, which are not present in the configuration
+ file, it sends a request message to all attached frontend programs,
+ e.g., wpa_cli in interactive mode. wpa_cli shows these requests
+ with "CTRL-REQ-&lt;type&gt;-&lt;id&gt;:&lt;text&gt;"
+ prefix. &lt;type&gt; is IDENTITY, PASSWORD, or OTP
+ (one-time-password). &lt;id&gt; is a unique identifier for the
+ current network. &lt;text&gt; is description of the request. In
+ case of OTP request, it includes the challenge from the
+ authentication server.</para>
+
+ <para>The reply to these requests can be given with 'identity',
+ 'password', and 'otp' commands. &lt;id&gt; needs to be copied from the
+ the matching request. 'password' and 'otp' commands can be used
+ regardless of whether the request was for PASSWORD or OTP. The
+ main difference between these two commands is that values given
+ with 'password' are remembered as long as wpa_supplicant is
+ running whereas values given with 'otp' are used only once and
+ then forgotten, i.e., wpa_supplicant will ask frontend for a new
+ value for every use. This can be used to implement
+ one-time-password lists and generic token card -based
+ authentication.</para>
+
+ <para>Example request for password and a matching reply:</para>
+
+<blockquote><programlisting>
+CTRL-REQ-PASSWORD-1:Password needed for SSID foobar
+> password 1 mysecretpassword
+</programlisting></blockquote>
+
+ <para>Example request for generic token card challenge-response:</para>
+
+<blockquote><programlisting>
+CTRL-REQ-OTP-2:Challenge 1235663 needed for SSID foobar
+> otp 2 9876
+</programlisting></blockquote>
+
+ </refsect1>
+ <refsect1>
+ <title>Command Arguments</title>
+ <variablelist>
+ <varlistentry>
+ <term>-p path</term>
+
+ <listitem><para>Change the path where control sockets should
+ be found.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-i ifname</term>
+
+ <listitem><para>Specify the interface that is being
+ configured. By default, choose the first interface found with
+ a control socket in the socket path.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-h</term>
+ <listitem><para>Help. Show a usage message.</para></listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>-v</term>
+ <listitem><para>Show version information.</para></listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>-B</term>
+ <listitem><para>Run as a daemon in the background.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-a file</term>
+
+ <listitem><para>Run in daemon mode executing the action file
+ based on events from wpa_supplicant. The specified file will
+ be executed with the first argument set to interface name and
+ second to "CONNECT" or "DISCONNECT" depending on the event.
+ This can be used </para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-P file</term>
+
+ <listitem><para>Set the location of the PID
+ file.</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>command</term>
+
+ <listitem><para>Run a command. The available commands are
+ listed in the next section.</para></listitem>
+
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+ <refsect1>
+ <title>Commands</title>
+ <para>The following commands are available:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term>status</term>
+ <listitem>
+ <para>get current WPA/EAPOL/EAP status</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>mib</term>
+ <listitem>
+ <para>get MIB variables (dot1x, dot11)</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>help</term>
+ <listitem>
+ <para>show this usage help</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>interface [ifname]</term>
+ <listitem>
+ <para>show interfaces/select interface</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>level &lt;debug level&gt;</term>
+ <listitem>
+ <para>change debug level</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>license</term>
+ <listitem>
+ <para>show full wpa_cli license</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>logoff</term>
+ <listitem>
+ <para>IEEE 802.1X EAPOL state machine logoff</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>logon</term>
+ <listitem>
+ <para>IEEE 802.1X EAPOL state machine logon</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>set</term>
+ <listitem>
+ <para>set variables (shows list of variables when run without arguments)</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>pmksa</term>
+ <listitem>
+ <para>show PMKSA cache</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>reassociate</term>
+ <listitem>
+ <para>force reassociation</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>reconfigure</term>
+ <listitem>
+ <para>force wpa_supplicant to re-read its configuration file</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>preauthenticate &lt;BSSID&gt;</term>
+ <listitem>
+ <para>force preauthentication</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>identity &lt;network id&gt; &lt;identity&gt;</term>
+ <listitem>
+ <para>configure identity for an SSID</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>password &lt;network id&gt; &lt;password&gt;</term>
+ <listitem>
+ <para>configure password for an SSID</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>pin &lt;network id&gt; &lt;pin&gt;</term>
+ <listitem>
+ <para>configure pin for an SSID</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>otp &lt;network id&gt; &lt;password&gt;</term>
+ <listitem>
+ <para>configure one-time-password for an SSID</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>bssid *lt;network id&gt; &lt;BSSID&gt;</term>
+ <listitem>
+ <para>set preferred BSSID for an SSID</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>list_networks</term>
+ <listitem>
+ <para>list configured networks</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>terminate</term>
+ <listitem>
+ <para>terminate <command>wpa_supplicant</command></para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>quit</term>
+ <listitem><para>exit wpa_cli</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry>
+ <refentrytitle>wpa_supplicant</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>Legal</title>
+ <para>wpa_supplicant is copyright (c) 2003-2005,
+ Jouni Malinen <email>jkmaline@cc.hut.fi</email> and
+ contributors.
+ All Rights Reserved.</para>
+
+ <para>This program is dual-licensed under both the GPL version 2
+ and BSD license. Either license may be used at your option.</para>
+ </refsect1>
+</refentry>
diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_passphrase.8 b/contrib/wpa_supplicant/doc/docbook/wpa_passphrase.8
new file mode 100644
index 000000000000..11e0f85bb863
--- /dev/null
+++ b/contrib/wpa_supplicant/doc/docbook/wpa_passphrase.8
@@ -0,0 +1,39 @@
+.\" This manpage has been automatically generated by docbook2man
+.\" from a DocBook document. This tool can be found at:
+.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/>
+.\" Please send any bug reports, improvements, comments, patches,
+.\" etc. to Steve Cheng <steve@ggi-project.org>.
+.TH "WPA_PASSPHRASE" "8" "08 February 2006" "" ""
+
+.SH NAME
+wpa_passphrase \- Set WPA passphrase for a SSID
+.SH SYNOPSIS
+
+\fBwpa_passphrase\fR [ \fB\fIssid\fB\fR ] [ \fB\fIpassphrase\fB\fR ]
+
+.SH "OVERVIEW"
+.PP
+\fBwpa_passphrase\fR pre-computes PSK entries for
+network configuration blocks of a
+\fIwpa_supplicant.conf\fR file.
+.SH "OPTIONS"
+.TP
+\fBssid\fR
+The SSID whose passphrase should be derived.
+.TP
+\fBpassphrase\fR
+The passphrase to use. If not included on the command line,
+passphrase will be read from standard input.
+.SH "SEE ALSO"
+.PP
+\fBwpa_supplicant.conf\fR(5)
+\fBwpa_supplicant\fR(8)
+.SH "LEGAL"
+.PP
+wpa_supplicant is copyright (c) 2003-2005,
+Jouni Malinen <jkmaline@cc.hut.fi> and
+contributors.
+All Rights Reserved.
+.PP
+This program is dual-licensed under both the GPL version 2
+and BSD license. Either license may be used at your option.
diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_passphrase.sgml b/contrib/wpa_supplicant/doc/docbook/wpa_passphrase.sgml
new file mode 100644
index 000000000000..1380a74d910e
--- /dev/null
+++ b/contrib/wpa_supplicant/doc/docbook/wpa_passphrase.sgml
@@ -0,0 +1,72 @@
+<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+
+<refentry>
+ <refmeta>
+ <refentrytitle>wpa_passphrase</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>wpa_passphrase</refname>
+ <refpurpose>Set WPA passphrase for a SSID</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>wpa_passphrase</command>
+ <arg><replaceable>ssid</replaceable></arg>
+ <arg><replaceable>passphrase</replaceable></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Overview</title>
+
+ <para><command>wpa_passphrase</command> pre-computes PSK entries for
+ network configuration blocks of a
+ <filename>wpa_supplicant.conf</filename> file.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Options</title>
+ <variablelist>
+ <varlistentry>
+ <term>ssid</term>
+ <listitem>
+ <para>The SSID whose passphrase should be derived.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>passphrase</term>
+ <listitem>
+ <para>The passphrase to use. If not included on the command line,
+ passphrase will be read from standard input.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry>
+ <refentrytitle>wpa_supplicant.conf</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </citerefentry>
+ <citerefentry>
+ <refentrytitle>wpa_supplicant</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>
+ </para>
+
+ </refsect1>
+ <refsect1>
+ <title>Legal</title>
+ <para>wpa_supplicant is copyright (c) 2003-2005,
+ Jouni Malinen <email>jkmaline@cc.hut.fi</email> and
+ contributors.
+ All Rights Reserved.</para>
+
+ <para>This program is dual-licensed under both the GPL version 2
+ and BSD license. Either license may be used at your option.</para>
+ </refsect1>
+</refentry>
diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.8 b/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.8
new file mode 100644
index 000000000000..fcd738b9203c
--- /dev/null
+++ b/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.8
@@ -0,0 +1,544 @@
+.\" This manpage has been automatically generated by docbook2man
+.\" from a DocBook document. This tool can be found at:
+.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/>
+.\" Please send any bug reports, improvements, comments, patches,
+.\" etc. to Steve Cheng <steve@ggi-project.org>.
+.TH "WPA_SUPPLICANT" "8" "08 February 2006" "" ""
+
+.SH NAME
+wpa_supplicant \- Wi-Fi Protected Access client and IEEE 802.1X supplicant
+.SH SYNOPSIS
+
+\fBwpa_supplicant\fR [ \fB-BddehLqqvw\fR ] [ \fB-i\fIifname\fB\fR ] [ \fB-c\fIconfig file\fB\fR ] [ \fB-D\fIdriver\fB\fR ]
+
+.SH "OVERVIEW"
+.PP
+Wireless networks do not require physical access to the network equipment
+in the same way as wired networks. This makes it easier for unauthorized
+users to passively monitor a network and capture all transmitted frames.
+In addition, unauthorized use of the network is much easier. In many cases,
+this can happen even without user's explicit knowledge since the wireless
+LAN adapter may have been configured to automatically join any available
+network.
+.PP
+Link-layer encryption can be used to provide a layer of security for
+wireless networks. The original wireless LAN standard, IEEE 802.11,
+included a simple encryption mechanism, WEP. However, that proved to
+be flawed in many areas and network protected with WEP cannot be consider
+secure. IEEE 802.1X authentication and frequently changed dynamic WEP keys
+can be used to improve the network security, but even that has inherited
+security issues due to the use of WEP for encryption. Wi-Fi Protected
+Access and IEEE 802.11i amendment to the wireless LAN standard introduce
+a much improvement mechanism for securing wireless networks. IEEE 802.11i
+enabled networks that are using CCMP (encryption mechanism based on strong
+cryptographic algorithm AES) can finally be called secure used for
+applications which require efficient protection against unauthorized
+access.
+.PP
+\fBwpa_supplicant\fR is an implementation of
+the WPA Supplicant component, i.e., the part that runs in the
+client stations. It implements WPA key negotiation with a WPA
+Authenticator and EAP authentication with Authentication
+Server. In addition, it controls the roaming and IEEE 802.11
+authentication/association of the wireless LAN driver.
+.PP
+\fBwpa_supplicant\fR is designed to be a
+"daemon" program that runs in the background and acts as the
+backend component controlling the wireless
+connection. \fBwpa_supplicant\fR supports separate
+frontend programs and an example text-based frontend,
+\fBwpa_cli\fR, is included with
+wpa_supplicant.
+.PP
+Before wpa_supplicant can do its work, the network interface
+must be available. That means that the physical device must be
+present and enabled, and the driver for the device must have be
+loaded. Note, however, that the '-w' option of the wpa_supplicant
+daemon instructs the daemon to continue running and to wait for
+the interface to become available. Without the '-w' option, the
+daemon will exit immediately if the device is not already
+available.
+.PP
+After \fBwpa_supplicant\fR has configured the
+network device, higher level configuration such as DHCP may
+proceed. There are a variety of ways to integrate wpa_supplicant
+into a machine's networking scripts, a few of which are described
+in sections below.
+.PP
+The following steps are used when associating with an AP
+using WPA:
+.TP 0.2i
+\(bu
+\fBwpa_supplicant\fR requests the kernel
+driver to scan neighboring BSSes
+.TP 0.2i
+\(bu
+\fBwpa_supplicant\fR selects a BSS based on
+its configuration
+.TP 0.2i
+\(bu
+\fBwpa_supplicant\fR requests the kernel
+driver to associate with the chosen BSS
+.TP 0.2i
+\(bu
+If WPA-EAP: integrated IEEE 802.1X Supplicant or
+external Xsupplicant completes EAP authentication with the
+authentication server (proxied by the Authenticator in the
+AP)
+.TP 0.2i
+\(bu
+If WPA-EAP: master key is received from the IEEE 802.1X
+Supplicant
+.TP 0.2i
+\(bu
+If WPA-PSK: \fBwpa_supplicant\fR uses PSK
+as the master session key
+.TP 0.2i
+\(bu
+\fBwpa_supplicant\fR completes WPA 4-Way
+Handshake and Group Key Handshake with the Authenticator
+(AP)
+.TP 0.2i
+\(bu
+\fBwpa_supplicant\fR configures encryption
+keys for unicast and broadcast
+.TP 0.2i
+\(bu
+normal data packets can be transmitted and received
+.SH "SUPPORTED FEATURES"
+.PP
+Supported WPA/IEEE 802.11i features:
+.TP 0.2i
+\(bu
+WPA-PSK ("WPA-Personal")
+.TP 0.2i
+\(bu
+WPA with EAP (e.g., with RADIUS authentication server)
+("WPA-Enterprise") Following authentication methods are
+supported with an integrate IEEE 802.1X Supplicant:
+.RS
+.TP 0.2i
+\(bu
+EAP-TLS
+.RE
+.RS
+.TP 0.2i
+\(bu
+EAP-PEAP/MSCHAPv2 (both PEAPv0 and PEAPv1)
+.TP 0.2i
+\(bu
+EAP-PEAP/TLS (both PEAPv0 and PEAPv1)
+.TP 0.2i
+\(bu
+EAP-PEAP/GTC (both PEAPv0 and PEAPv1)
+.TP 0.2i
+\(bu
+EAP-PEAP/OTP (both PEAPv0 and PEAPv1)
+.TP 0.2i
+\(bu
+EAP-PEAP/MD5-Challenge (both PEAPv0 and PEAPv1)
+.TP 0.2i
+\(bu
+EAP-TTLS/EAP-MD5-Challenge
+.TP 0.2i
+\(bu
+EAP-TTLS/EAP-GTC
+.TP 0.2i
+\(bu
+EAP-TTLS/EAP-OTP
+.TP 0.2i
+\(bu
+EAP-TTLS/EAP-MSCHAPv2
+.TP 0.2i
+\(bu
+EAP-TTLS/EAP-TLS
+.TP 0.2i
+\(bu
+EAP-TTLS/MSCHAPv2
+.TP 0.2i
+\(bu
+EAP-TTLS/MSCHAP
+.TP 0.2i
+\(bu
+EAP-TTLS/PAP
+.TP 0.2i
+\(bu
+EAP-TTLS/CHAP
+.TP 0.2i
+\(bu
+EAP-SIM
+.TP 0.2i
+\(bu
+EAP-AKA
+.TP 0.2i
+\(bu
+EAP-PSK
+.TP 0.2i
+\(bu
+EAP-PAX
+.TP 0.2i
+\(bu
+LEAP (note: requires special support from
+the driver for IEEE 802.11 authentication)
+.TP 0.2i
+\(bu
+(following methods are supported, but since
+they do not generate keying material, they cannot be used
+with WPA or IEEE 802.1X WEP keying)
+.TP 0.2i
+\(bu
+EAP-MD5-Challenge
+.TP 0.2i
+\(bu
+EAP-MSCHAPv2
+.TP 0.2i
+\(bu
+EAP-GTC
+.TP 0.2i
+\(bu
+EAP-OTP
+.RE
+.TP 0.2i
+\(bu
+key management for CCMP, TKIP, WEP104, WEP40
+.TP 0.2i
+\(bu
+RSN/WPA2 (IEEE 802.11i)
+.RS
+.TP 0.2i
+\(bu
+pre-authentication
+.TP 0.2i
+\(bu
+PMKSA caching
+.RE
+.SH "AVAILABLE DRIVERS"
+.PP
+The available drivers to specify with the -D option are:
+.TP
+\fBhostap\fR
+(default) Host AP driver (Intersil Prism2/2.5/3).
+(this can also be used with Linuxant DriverLoader).
+.TP
+\fBhermes\fR
+Agere Systems Inc. driver (Hermes-I/Hermes-II).
+.TP
+\fBmadwifi\fR
+MADWIFI 802.11 support (Atheros, etc.).
+.TP
+\fBatmel\fR
+ATMEL AT76C5XXx (USB, PCMCIA).
+.TP
+\fBwext\fR
+Linux wireless extensions (generic).
+.TP
+\fBndiswrapper\fR
+Linux ndiswrapper.
+.TP
+\fBbroadcom\fR
+Broadcom wl.o driver.
+.TP
+\fBipw\fR
+Intel ipw2100/2200 driver.
+.TP
+\fBwired\fR
+wpa_supplicant wired Ethernet driver
+.TP
+\fBbsd\fR
+BSD 802.11 support (Atheros, etc.).
+.TP
+\fBndis\fR
+Windows NDIS driver.
+.SH "COMMAND LINE OPTIONS"
+.TP
+\fB-B\fR
+Run daemon in the background.
+.TP
+\fB-i ifname\fR
+Interface to listen on.
+.TP
+\fB-c filename\fR
+Path to configuration file.
+.TP
+\fB-D driver\fR
+Driver to use. See the available options below.
+.TP
+\fB-d\fR
+Increase debugging verbosity (-dd even more).
+.TP
+\fB-K\fR
+Include keys (passwords, etc.) in debug output.
+.TP
+\fB-t\fR
+Include timestamp in debug messages.
+.TP
+\fB-e\fR
+Use external IEEE 802.1X Supplicant (e.g.,
+\fBxsupplicant\fR) (this disables the internal
+Supplicant).
+.TP
+\fB-h\fR
+Help. Show a usage message.
+.TP
+\fB-L\fR
+Show license (GPL and BSD).
+.TP
+\fB-q\fR
+Decrease debugging verbosity (-qq even less).
+.TP
+\fB-v\fR
+Show version.
+.TP
+\fB-w\fR
+wait for interface to be added, if needed. normally,
+\fBwpa_supplicant\fR will exit if the interface
+is not there yet.
+.TP
+\fB-N\fR
+Start describing new interface.
+.SH "EXAMPLES"
+.PP
+In most common cases, \fBwpa_supplicant\fR is
+started with:
+.sp
+.RS
+
+.nf
+wpa_supplicant -Bw -c/etc/wpa_supplicant.conf -iwlan0
+.fi
+.RE
+.PP
+This makes the process fork into background and wait for the wlan0
+interface if it is not available at startup time.
+.PP
+The easiest way to debug problems, and to get debug log for
+bug reports, is to start \fBwpa_supplicant\fR on
+foreground with debugging enabled:
+.sp
+.RS
+
+.nf
+wpa_supplicant -c/etc/wpa_supplicant.conf -iwlan0 -d
+.fi
+.RE
+.PP
+\fBwpa_supplicant\fR can control multiple
+interfaces (radios) either by running one process for each
+interface separately or by running just one process and list of
+options at command line. Each interface is separated with -N
+argument. As an example, following command would start
+wpa_supplicant for two interfaces:
+.sp
+.RS
+
+.nf
+wpa_supplicant \\
+ -c wpa1.conf -i wlan0 -D hostap -N \\
+ -c wpa2.conf -i ath0 -D madwifi
+.fi
+.RE
+.SH "OS REQUIREMENTS"
+.PP
+Current hardware/software requirements:
+.TP 0.2i
+\(bu
+Linux kernel 2.4.x or 2.6.x with Linux Wireless
+Extensions v15 or newer
+.TP 0.2i
+\(bu
+FreeBSD 6-CURRENT
+.TP 0.2i
+\(bu
+Microsoft Windows with WinPcap (at least WinXP, may work
+with other versions)
+.SH "SUPPORTED DRIVERS"
+.TP
+\fBHost AP driver for Prism2/2.5/3 (development snapshot/v0.2.x)\fR
+(http://hostap.epitest.fi/) Driver needs to be set in
+Managed mode ('iwconfig wlan0 mode managed'). Please note
+that station firmware version needs to be 1.7.0 or newer to
+work in WPA mode.
+.TP
+\fBLinuxant DriverLoader\fR
+(http://www.linuxant.com/driverloader/)
+with Windows NDIS driver for your wlan card supporting WPA.
+.TP
+\fBAgere Systems Inc. Linux Driver\fR
+(http://www.agere.com/support/drivers/) Please note
+that the driver interface file (driver_hermes.c) and hardware
+specific include files are not included in the wpa_supplicant
+distribution. You will need to copy these from the source
+package of the Agere driver.
+.TP
+\fBmadwifi driver for cards based on Atheros chip set (ar521x)\fR
+(http://sourceforge.net/projects/madwifi/) Please
+note that you will need to modify the wpa_supplicant .config
+file to use the correct path for the madwifi driver root
+directory (CFLAGS += -I../madwifi/wpa line in example
+defconfig).
+.TP
+\fBATMEL AT76C5XXx driver for USB and PCMCIA cards\fR
+(http://atmelwlandriver.sourceforge.net/).
+.TP
+\fBLinux ndiswrapper\fR
+(http://ndiswrapper.sourceforge.net/) with Windows
+NDIS driver.
+.TP
+\fBBroadcom wl.o driver\fR
+This is a generic Linux driver for Broadcom IEEE
+802.11a/g cards. However, it is proprietary driver that is
+not publicly available except for couple of exceptions, mainly
+Broadcom-based APs/wireless routers that use Linux. The driver
+binary can be downloaded, e.g., from Linksys support site
+(http://www.linksys.com/support/gpl.asp) for Linksys
+WRT54G. The GPL tarball includes cross-compiler and the needed
+header file, wlioctl.h, for compiling wpa_supplicant. This
+driver support in wpa_supplicant is expected to work also with
+other devices based on Broadcom driver (assuming the driver
+includes client mode support).
+.TP
+\fB Intel ipw2100 driver\fR
+(http://sourceforge.net/projects/ipw2100/)
+.TP
+\fBIntel ipw2200 driver\fR
+(http://sourceforge.net/projects/ipw2200/)
+.TP
+\fBLinux wireless extensions\fR
+In theory, any driver that supports Linux wireless
+extensions can be used with IEEE 802.1X (i.e., not WPA) when
+using ap_scan=0 option in configuration file.
+.TP
+\fBWired Ethernet drivers\fR
+Use ap_scan=0.
+.TP
+\fBBSD net80211 layer (e.g., Atheros driver)\fR
+At the moment, this is for FreeBSD 6-CURRENT branch.
+.TP
+\fBWindows NDIS\fR
+The current Windows port requires WinPcap
+(http://winpcap.polito.it/). See README-Windows.txt for more
+information.
+.PP
+wpa_supplicant was designed to be portable for different
+drivers and operating systems. Hopefully, support for more wlan
+cards and OSes will be added in the future. See developer.txt for
+more information about the design of wpa_supplicant and porting to
+other drivers. One main goal is to add full WPA/WPA2 support to
+Linux wireless extensions to allow new drivers to be supported
+without having to implement new driver-specific interface code in
+wpa_supplicant.
+.SH "ARCHITECTURE"
+.PP
+The
+\fBwpa_supplicant\fR system consists of the following
+components:
+.TP
+\fB\fIwpa_supplicant.conf\fB \fR
+the configuration file describing all networks that the
+user wants the computer to connect to.
+.TP
+\fBwpa_supplicant\fR
+the program that directly interacts with the
+network interface.
+.TP
+\fBwpa_cli\fR
+the
+client program that provides a high-level interface to the
+functionality of the daemon.
+.TP
+\fBwpa_passphrase\fR
+a utility needed to construct
+\fIwpa_supplicant.conf\fR files that include
+encrypted passwords.
+.SH "QUICK START"
+.PP
+First, make a configuration file, e.g.
+\fI/etc/wpa_supplicant.conf\fR, that describes the networks
+you are interested in. See \fBwpa_supplicant\fR(5)
+for details.
+.PP
+Once the configuration is ready, you can test whether the
+configuration works by running \fBwpa_supplicant\fR
+with following command to start it on foreground with debugging
+enabled:
+.sp
+.RS
+
+.nf
+wpa_supplicant -iwlan0 -c/etc/wpa_supplicant.conf -d
+
+.fi
+.RE
+.PP
+Assuming everything goes fine, you can start using following
+command to start \fBwpa_supplicant\fR on background
+without debugging:
+.sp
+.RS
+
+.nf
+wpa_supplicant -iwlan0 -c/etc/wpa_supplicant.conf -B
+
+.fi
+.RE
+.PP
+Please note that if you included more than one driver
+interface in the build time configuration (.config), you may need
+to specify which interface to use by including -D<driver
+name> option on the command line.
+.SH "INTERFACE TO PCMCIA-CS/CARDMRG"
+.PP
+For example, following small changes to pcmcia-cs scripts
+can be used to enable WPA support:
+.PP
+Add MODE="Managed" and WPA="y" to the network scheme in
+\fI/etc/pcmcia/wireless.opts\fR\&.
+.PP
+Add the following block to the end of 'start' action handler
+in \fI/etc/pcmcia/wireless\fR:
+.sp
+.RS
+
+.nf
+if [ "$WPA" = "y" -a -x /usr/local/bin/wpa_supplicant ]; then
+ /usr/local/bin/wpa_supplicant -Bw -c/etc/wpa_supplicant.conf -i$DEVICE
+fi
+
+.fi
+.RE
+.PP
+Add the following block to the end of 'stop' action handler
+(may need to be separated from other actions) in
+\fI/etc/pcmcia/wireless\fR:
+.sp
+.RS
+
+.nf
+if [ "$WPA" = "y" -a -x /usr/local/bin/wpa_supplicant ]; then
+ killall wpa_supplicant
+fi
+
+.fi
+.RE
+.PP
+This will make \fBcardmgr\fR start
+\fBwpa_supplicant\fR when the card is plugged
+in. \fBwpa_supplicant\fR will wait until the
+interface is set up--either when a static IP address is configured
+or when DHCP client is started--and will then negotiate keys with
+the AP.
+.SH "SEE ALSO"
+.PP
+\fBwpa_background\fR(8)
+\fBwpa_supplicant.conf\fR(5)
+\fBwpa_cli\fR(8)
+\fBwpa_passphrase\fR(8)
+.SH "LEGAL"
+.PP
+wpa_supplicant is copyright (c) 2003-2005,
+Jouni Malinen <jkmaline@cc.hut.fi> and
+contributors.
+All Rights Reserved.
+.PP
+This program is dual-licensed under both the GPL version 2
+and BSD license. Either license may be used at your option.
diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.5 b/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.5
new file mode 100644
index 000000000000..d5e5c62b6489
--- /dev/null
+++ b/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.5
@@ -0,0 +1,230 @@
+.\" This manpage has been automatically generated by docbook2man
+.\" from a DocBook document. This tool can be found at:
+.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/>
+.\" Please send any bug reports, improvements, comments, patches,
+.\" etc. to Steve Cheng <steve@ggi-project.org>.
+.TH "WPA_SUPPLICANT.CONF" "5" "08 February 2006" "" ""
+
+.SH NAME
+wpa_supplicant.conf \- configuration file for wpa_supplicant
+.SH "OVERVIEW"
+.PP
+\fBwpa_supplicant\fR is configured using a text
+file that lists all accepted networks and security policies,
+including pre-shared keys. See the example configuration file,
+probably in \fB/usr/share/doc/wpa_supplicant/\fR, for
+detailed information about the configuration format and supported
+fields.
+.PP
+All file paths in this configuration file should use full
+(absolute, not relative to working directory) path in order to allow
+working directory to be changed. This can happen if wpa_supplicant is
+run in the background.
+.PP
+Changes to configuration file can be reloaded be sending
+SIGHUP signal to \fBwpa_supplicant\fR ('killall -HUP
+wpa_supplicant'). Similarly, reloading can be triggered with
+'wpa_cli reconfigure' command.
+.PP
+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 file, network security level (WPA/WPA2 is
+prefered), and signal strength.
+.SH "QUICK EXAMPLES"
+.TP 3
+1.
+WPA-Personal (PSK) as home network and WPA-Enterprise with
+EAP-TLS as work network.
+.sp
+.RS
+
+.nf
+# allow frontend (e.g., wpa_cli) to be used by all users in 'wheel' group
+ctrl_interface=/var/run/wpa_supplicant
+ctrl_interface_group=wheel
+#
+# home network; allow all valid ciphers
+network={
+ ssid="home"
+ scan_ssid=1
+ key_mgmt=WPA-PSK
+ psk="very secret passphrase"
+}
+#
+# work network; use EAP-TLS with WPA; allow only CCMP and TKIP ciphers
+network={
+ ssid="work"
+ scan_ssid=1
+ key_mgmt=WPA-EAP
+ pairwise=CCMP TKIP
+ group=CCMP TKIP
+ eap=TLS
+ identity="user@example.com"
+ ca_cert="/etc/cert/ca.pem"
+ client_cert="/etc/cert/user.pem"
+ private_key="/etc/cert/user.prv"
+ private_key_passwd="password"
+}
+.fi
+.RE
+.TP 3
+2.
+WPA-RADIUS/EAP-PEAP/MSCHAPv2 with RADIUS servers that
+use old peaplabel (e.g., Funk Odyssey and SBR, Meetinghouse
+Aegis, Interlink RAD-Series)
+.sp
+.RS
+
+.nf
+ctrl_interface=/var/run/wpa_supplicant
+ctrl_interface_group=wheel
+network={
+ ssid="example"
+ scan_ssid=1
+ key_mgmt=WPA-EAP
+ eap=PEAP
+ identity="user@example.com"
+ password="foobar"
+ ca_cert="/etc/cert/ca.pem"
+ phase1="peaplabel=0"
+ phase2="auth=MSCHAPV2"
+}
+.fi
+.RE
+.TP 3
+3.
+EAP-TTLS/EAP-MD5-Challenge configuration with anonymous
+identity for the unencrypted use. Real identity is sent only
+within an encrypted TLS tunnel.
+.sp
+.RS
+
+.nf
+ctrl_interface=/var/run/wpa_supplicant
+ctrl_interface_group=wheel
+network={
+ ssid="example"
+ scan_ssid=1
+ key_mgmt=WPA-EAP
+ eap=TTLS
+ identity="user@example.com"
+ anonymous_identity="anonymous@example.com"
+ password="foobar"
+ ca_cert="/etc/cert/ca.pem"
+ phase2="auth=MD5"
+}
+.fi
+.RE
+.TP 3
+4.
+IEEE 802.1X (i.e., no WPA) with dynamic WEP keys
+(require both unicast and broadcast); use EAP-TLS for
+authentication
+.sp
+.RS
+
+.nf
+ctrl_interface=/var/run/wpa_supplicant
+ctrl_interface_group=wheel
+network={
+ ssid="1x-test"
+ scan_ssid=1
+ key_mgmt=IEEE8021X
+ eap=TLS
+ identity="user@example.com"
+ ca_cert="/etc/cert/ca.pem"
+ client_cert="/etc/cert/user.pem"
+ private_key="/etc/cert/user.prv"
+ private_key_passwd="password"
+ eapol_flags=3
+}
+.fi
+.RE
+.TP 3
+5.
+Catch all example that allows more or less all
+configuration modes. The configuration options are used based
+on what security policy is used in the selected SSID. This is
+mostly for testing and is not recommended for normal
+use.
+.sp
+.RS
+
+.nf
+ctrl_interface=/var/run/wpa_supplicant
+ctrl_interface_group=wheel
+network={
+ ssid="example"
+ scan_ssid=1
+ key_mgmt=WPA-EAP WPA-PSK IEEE8021X NONE
+ pairwise=CCMP TKIP
+ group=CCMP TKIP WEP104 WEP40
+ psk="very secret passphrase"
+ eap=TTLS PEAP TLS
+ identity="user@example.com"
+ password="foobar"
+ ca_cert="/etc/cert/ca.pem"
+ client_cert="/etc/cert/user.pem"
+ private_key="/etc/cert/user.prv"
+ private_key_passwd="password"
+ phase1="peaplabel=0"
+ ca_cert2="/etc/cert/ca2.pem"
+ client_cert2="/etc/cer/user.pem"
+ private_key2="/etc/cer/user.prv"
+ private_key2_passwd="password"
+}
+.fi
+.RE
+.TP 3
+6.
+Authentication for wired Ethernet. This can be used with
+'wired' interface (-Dwired on command line).
+.sp
+.RS
+
+.nf
+ctrl_interface=/var/run/wpa_supplicant
+ctrl_interface_group=wheel
+ap_scan=0
+network={
+ key_mgmt=IEEE8021X
+ eap=MD5
+ identity="user"
+ password="password"
+ eapol_flags=0
+}
+.fi
+.RE
+.SH "CERTIFICATES"
+.PP
+Some EAP authentication methods require use of
+certificates. EAP-TLS uses both server side and client
+certificates whereas EAP-PEAP and EAP-TTLS only require the server
+side certificate. When client certificate is used, a matching
+private key file has to also be included in configuration. If the
+private key uses a passphrase, this has to be configured in
+wpa_supplicant.conf ("private_key_passwd").
+.PP
+wpa_supplicant supports X.509 certificates in PEM and DER
+formats. User certificate and private key can be included in the
+same file.
+.PP
+If the user certificate and private key is received in
+PKCS#12/PFX format, they need to be converted to suitable PEM/DER
+format for wpa_supplicant. This can be done, e.g., with following
+commands:
+.sp
+.RS
+
+.nf
+# convert client certificate and private key to PEM format
+openssl pkcs12 -in example.pfx -out user.pem -clcerts
+# convert CA certificate (if included in PFX file) to PEM format
+openssl pkcs12 -in example.pfx -out ca.pem -cacerts -nokeys
+.fi
+.RE
+.SH "SEE ALSO"
+.PP
+\fBwpa_supplicant\fR(8)
+\fBopenssl\fR(1)
diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml b/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml
new file mode 100644
index 000000000000..dbd9e37f552f
--- /dev/null
+++ b/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml
@@ -0,0 +1,244 @@
+<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+<refentry>
+ <refmeta>
+ <refentrytitle>wpa_supplicant.conf</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>wpa_supplicant.conf</refname>
+ <refpurpose>configuration file for wpa_supplicant</refpurpose>
+ </refnamediv>
+ <refsect1>
+ <title>Overview</title>
+
+ <para><command>wpa_supplicant</command> is configured using a text
+ file that lists all accepted networks and security policies,
+ including pre-shared keys. See the example configuration file,
+ probably in <command>/usr/share/doc/wpa_supplicant/</command>, for
+ detailed information about the configuration format and supported
+ fields.</para>
+
+ <para>All file paths in this configuration file should use full
+ (absolute, not relative to working directory) path in order to allow
+ working directory to be changed. This can happen if wpa_supplicant is
+ run in the background.</para>
+
+ <para>Changes to configuration file can be reloaded be sending
+ SIGHUP signal to <command>wpa_supplicant</command> ('killall -HUP
+ wpa_supplicant'). Similarly, reloading can be triggered with
+ 'wpa_cli reconfigure' command.</para>
+
+ <para>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 file, network security level (WPA/WPA2 is
+ prefered), and signal strength.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Quick Examples</title>
+
+ <orderedlist>
+ <listitem>
+
+ <para>WPA-Personal (PSK) as home network and WPA-Enterprise with
+ EAP-TLS as work network.</para>
+
+<blockquote><programlisting>
+# allow frontend (e.g., wpa_cli) to be used by all users in 'wheel' group
+ctrl_interface=/var/run/wpa_supplicant
+ctrl_interface_group=wheel
+#
+# home network; allow all valid ciphers
+network={
+ ssid="home"
+ scan_ssid=1
+ key_mgmt=WPA-PSK
+ psk="very secret passphrase"
+}
+#
+# work network; use EAP-TLS with WPA; allow only CCMP and TKIP ciphers
+network={
+ ssid="work"
+ scan_ssid=1
+ key_mgmt=WPA-EAP
+ pairwise=CCMP TKIP
+ group=CCMP TKIP
+ eap=TLS
+ identity="user@example.com"
+ ca_cert="/etc/cert/ca.pem"
+ client_cert="/etc/cert/user.pem"
+ private_key="/etc/cert/user.prv"
+ private_key_passwd="password"
+}
+</programlisting></blockquote>
+ </listitem>
+
+ <listitem>
+ <para>WPA-RADIUS/EAP-PEAP/MSCHAPv2 with RADIUS servers that
+ use old peaplabel (e.g., Funk Odyssey and SBR, Meetinghouse
+ Aegis, Interlink RAD-Series)</para>
+
+<blockquote><programlisting>
+ctrl_interface=/var/run/wpa_supplicant
+ctrl_interface_group=wheel
+network={
+ ssid="example"
+ scan_ssid=1
+ key_mgmt=WPA-EAP
+ eap=PEAP
+ identity="user@example.com"
+ password="foobar"
+ ca_cert="/etc/cert/ca.pem"
+ phase1="peaplabel=0"
+ phase2="auth=MSCHAPV2"
+}
+</programlisting></blockquote>
+ </listitem>
+
+ <listitem>
+ <para>EAP-TTLS/EAP-MD5-Challenge configuration with anonymous
+ identity for the unencrypted use. Real identity is sent only
+ within an encrypted TLS tunnel.</para>
+
+
+<blockquote><programlisting>
+ctrl_interface=/var/run/wpa_supplicant
+ctrl_interface_group=wheel
+network={
+ ssid="example"
+ scan_ssid=1
+ key_mgmt=WPA-EAP
+ eap=TTLS
+ identity="user@example.com"
+ anonymous_identity="anonymous@example.com"
+ password="foobar"
+ ca_cert="/etc/cert/ca.pem"
+ phase2="auth=MD5"
+}
+</programlisting></blockquote>
+
+ </listitem>
+
+ <listitem>
+ <para>IEEE 802.1X (i.e., no WPA) with dynamic WEP keys
+ (require both unicast and broadcast); use EAP-TLS for
+ authentication</para>
+
+<blockquote><programlisting>
+ctrl_interface=/var/run/wpa_supplicant
+ctrl_interface_group=wheel
+network={
+ ssid="1x-test"
+ scan_ssid=1
+ key_mgmt=IEEE8021X
+ eap=TLS
+ identity="user@example.com"
+ ca_cert="/etc/cert/ca.pem"
+ client_cert="/etc/cert/user.pem"
+ private_key="/etc/cert/user.prv"
+ private_key_passwd="password"
+ eapol_flags=3
+}
+</programlisting></blockquote>
+ </listitem>
+
+
+ <listitem>
+ <para>Catch all example that allows more or less all
+ configuration modes. The configuration options are used based
+ on what security policy is used in the selected SSID. This is
+ mostly for testing and is not recommended for normal
+ use.</para>
+
+<blockquote><programlisting>
+ctrl_interface=/var/run/wpa_supplicant
+ctrl_interface_group=wheel
+network={
+ ssid="example"
+ scan_ssid=1
+ key_mgmt=WPA-EAP WPA-PSK IEEE8021X NONE
+ pairwise=CCMP TKIP
+ group=CCMP TKIP WEP104 WEP40
+ psk="very secret passphrase"
+ eap=TTLS PEAP TLS
+ identity="user@example.com"
+ password="foobar"
+ ca_cert="/etc/cert/ca.pem"
+ client_cert="/etc/cert/user.pem"
+ private_key="/etc/cert/user.prv"
+ private_key_passwd="password"
+ phase1="peaplabel=0"
+ ca_cert2="/etc/cert/ca2.pem"
+ client_cert2="/etc/cer/user.pem"
+ private_key2="/etc/cer/user.prv"
+ private_key2_passwd="password"
+}
+</programlisting></blockquote>
+ </listitem>
+
+ <listitem>
+ <para>Authentication for wired Ethernet. This can be used with
+ 'wired' interface (-Dwired on command line).</para>
+
+<blockquote><programlisting>
+ctrl_interface=/var/run/wpa_supplicant
+ctrl_interface_group=wheel
+ap_scan=0
+network={
+ key_mgmt=IEEE8021X
+ eap=MD5
+ identity="user"
+ password="password"
+ eapol_flags=0
+}
+</programlisting></blockquote>
+ </listitem>
+ </orderedlist>
+
+
+
+
+
+ </refsect1>
+ <refsect1>
+ <title>Certificates</title>
+
+ <para>Some EAP authentication methods require use of
+ certificates. EAP-TLS uses both server side and client
+ certificates whereas EAP-PEAP and EAP-TTLS only require the server
+ side certificate. When client certificate is used, a matching
+ private key file has to also be included in configuration. If the
+ private key uses a passphrase, this has to be configured in
+ wpa_supplicant.conf ("private_key_passwd").</para>
+
+ <para>wpa_supplicant supports X.509 certificates in PEM and DER
+ formats. User certificate and private key can be included in the
+ same file.</para>
+
+ <para>If the user certificate and private key is received in
+ PKCS#12/PFX format, they need to be converted to suitable PEM/DER
+ format for wpa_supplicant. This can be done, e.g., with following
+ commands:</para>
+<blockquote><programlisting>
+# convert client certificate and private key to PEM format
+openssl pkcs12 -in example.pfx -out user.pem -clcerts
+# convert CA certificate (if included in PFX file) to PEM format
+openssl pkcs12 -in example.pfx -out ca.pem -cacerts -nokeys
+</programlisting></blockquote>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry>
+ <refentrytitle>wpa_supplicant</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>
+ <citerefentry>
+ <refentrytitle>openssl</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </citerefentry>
+ </para>
+ </refsect1>
+</refentry>
diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.sgml b/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
new file mode 100644
index 000000000000..cb35abf31e47
--- /dev/null
+++ b/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
@@ -0,0 +1,761 @@
+<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+
+<refentry>
+ <refmeta>
+ <refentrytitle>wpa_supplicant</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </refmeta>
+ <refnamediv>
+ <refname>wpa_supplicant</refname>
+ <refpurpose>Wi-Fi Protected Access client and IEEE 802.1X supplicant</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>wpa_supplicant</command>
+ <arg>-BddehLqqvw</arg>
+ <arg>-i<replaceable>ifname</replaceable></arg>
+ <arg>-c<replaceable>config file</replaceable></arg>
+ <arg>-D<replaceable>driver</replaceable></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+ <refsect1>
+ <title>Overview</title>
+
+ <para>
+ Wireless networks do not require physical access to the network equipment
+ in the same way as wired networks. This makes it easier for unauthorized
+ users to passively monitor a network and capture all transmitted frames.
+ In addition, unauthorized use of the network is much easier. In many cases,
+ this can happen even without user's explicit knowledge since the wireless
+ LAN adapter may have been configured to automatically join any available
+ network.
+ </para>
+
+ <para>
+ Link-layer encryption can be used to provide a layer of security for
+ wireless networks. The original wireless LAN standard, IEEE 802.11,
+ included a simple encryption mechanism, WEP. However, that proved to
+ be flawed in many areas and network protected with WEP cannot be consider
+ secure. IEEE 802.1X authentication and frequently changed dynamic WEP keys
+ can be used to improve the network security, but even that has inherited
+ security issues due to the use of WEP for encryption. Wi-Fi Protected
+ Access and IEEE 802.11i amendment to the wireless LAN standard introduce
+ a much improvement mechanism for securing wireless networks. IEEE 802.11i
+ enabled networks that are using CCMP (encryption mechanism based on strong
+ cryptographic algorithm AES) can finally be called secure used for
+ applications which require efficient protection against unauthorized
+ access.
+ </para>
+
+ <para><command>wpa_supplicant</command> is an implementation of
+ the WPA Supplicant component, i.e., the part that runs in the
+ client stations. It implements WPA key negotiation with a WPA
+ Authenticator and EAP authentication with Authentication
+ Server. In addition, it controls the roaming and IEEE 802.11
+ authentication/association of the wireless LAN driver.</para>
+
+ <para><command>wpa_supplicant</command> is designed to be a
+ "daemon" program that runs in the background and acts as the
+ backend component controlling the wireless
+ connection. <command>wpa_supplicant</command> supports separate
+ frontend programs and an example text-based frontend,
+ <command>wpa_cli</command>, is included with
+ wpa_supplicant.</para>
+
+ <para>Before wpa_supplicant can do its work, the network interface
+ must be available. That means that the physical device must be
+ present and enabled, and the driver for the device must have be
+ loaded. Note, however, that the '-w' option of the wpa_supplicant
+ daemon instructs the daemon to continue running and to wait for
+ the interface to become available. Without the '-w' option, the
+ daemon will exit immediately if the device is not already
+ available.</para>
+
+ <para>After <command>wpa_supplicant</command> has configured the
+ network device, higher level configuration such as DHCP may
+ proceed. There are a variety of ways to integrate wpa_supplicant
+ into a machine's networking scripts, a few of which are described
+ in sections below.</para>
+
+ <para>The following steps are used when associating with an AP
+ using WPA:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><command>wpa_supplicant</command> requests the kernel
+ driver to scan neighboring BSSes</para>
+ </listitem>
+
+ <listitem>
+ <para><command>wpa_supplicant</command> selects a BSS based on
+ its configuration</para>
+ </listitem>
+
+ <listitem>
+ <para><command>wpa_supplicant</command> requests the kernel
+ driver to associate with the chosen BSS</para>
+ </listitem>
+
+ <listitem>
+ <para>If WPA-EAP: integrated IEEE 802.1X Supplicant or
+ external Xsupplicant completes EAP authentication with the
+ authentication server (proxied by the Authenticator in the
+ AP)</para>
+ </listitem>
+
+ <listitem>
+ <para>If WPA-EAP: master key is received from the IEEE 802.1X
+ Supplicant</para>
+ </listitem>
+
+ <listitem>
+ <para>If WPA-PSK: <command>wpa_supplicant</command> uses PSK
+ as the master session key</para>
+ </listitem>
+
+ <listitem>
+ <para><command>wpa_supplicant</command> completes WPA 4-Way
+ Handshake and Group Key Handshake with the Authenticator
+ (AP)</para>
+ </listitem>
+
+ <listitem>
+ <para><command>wpa_supplicant</command> configures encryption
+ keys for unicast and broadcast</para>
+ </listitem>
+
+ <listitem>
+ <para>normal data packets can be transmitted and received</para>
+ </listitem>
+ </itemizedlist>
+ </refsect1>
+
+ <refsect1>
+ <title>Supported Features</title>
+ <para>Supported WPA/IEEE 802.11i features:</para>
+ <itemizedlist>
+ <listitem>
+ <para>WPA-PSK ("WPA-Personal")</para>
+ </listitem>
+
+ <listitem>
+ <para>WPA with EAP (e.g., with RADIUS authentication server)
+ ("WPA-Enterprise") Following authentication methods are
+ supported with an integrate IEEE 802.1X Supplicant:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>EAP-TLS</para>
+ </listitem>
+ </itemizedlist>
+
+ <itemizedlist>
+ <listitem>
+ <para>EAP-PEAP/MSCHAPv2 (both PEAPv0 and PEAPv1)</para>
+ </listitem>
+
+
+ <listitem>
+ <para>EAP-PEAP/TLS (both PEAPv0 and PEAPv1)</para>
+ </listitem>
+
+ <listitem>
+ <para>EAP-PEAP/GTC (both PEAPv0 and PEAPv1)</para>
+ </listitem>
+
+ <listitem>
+ <para>EAP-PEAP/OTP (both PEAPv0 and PEAPv1)</para>
+ </listitem>
+
+ <listitem>
+ <para>EAP-PEAP/MD5-Challenge (both PEAPv0 and PEAPv1)</para>
+ </listitem>
+
+ <listitem>
+ <para>EAP-TTLS/EAP-MD5-Challenge</para>
+ </listitem>
+
+ <listitem>
+ <para>EAP-TTLS/EAP-GTC</para>
+ </listitem>
+
+ <listitem><para>EAP-TTLS/EAP-OTP</para></listitem>
+
+ <listitem><para>EAP-TTLS/EAP-MSCHAPv2</para></listitem>
+
+ <listitem><para>EAP-TTLS/EAP-TLS</para></listitem>
+
+ <listitem><para>EAP-TTLS/MSCHAPv2</para></listitem>
+
+ <listitem><para>EAP-TTLS/MSCHAP</para></listitem>
+
+ <listitem><para>EAP-TTLS/PAP</para></listitem>
+
+ <listitem><para>EAP-TTLS/CHAP</para></listitem>
+
+ <listitem><para>EAP-SIM</para></listitem>
+
+ <listitem><para>EAP-AKA</para></listitem>
+
+ <listitem><para>EAP-PSK</para></listitem>
+
+ <listitem><para>EAP-PAX</para></listitem>
+
+ <listitem><para>LEAP (note: requires special support from
+ the driver for IEEE 802.11 authentication)</para></listitem>
+
+ <listitem><para>(following methods are supported, but since
+ they do not generate keying material, they cannot be used
+ with WPA or IEEE 802.1X WEP keying)</para></listitem>
+
+ <listitem><para>EAP-MD5-Challenge </para></listitem>
+
+ <listitem><para>EAP-MSCHAPv2</para></listitem>
+
+ <listitem><para>EAP-GTC</para></listitem>
+
+ <listitem><para>EAP-OTP</para></listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>key management for CCMP, TKIP, WEP104, WEP40</para>
+ </listitem>
+
+ <listitem>
+ <para>RSN/WPA2 (IEEE 802.11i)</para>
+ <itemizedlist>
+ <listitem>
+ <para>pre-authentication</para>
+ </listitem>
+
+ <listitem>
+ <para>PMKSA caching</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ </refsect1>
+
+ <refsect1>
+ <title>Available Drivers</title>
+ <para>The available drivers to specify with the -D option are:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term>hostap</term>
+ <listitem>
+ <para>(default) Host AP driver (Intersil Prism2/2.5/3).
+ (this can also be used with Linuxant DriverLoader).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>hermes</term>
+ <listitem>
+ <para>Agere Systems Inc. driver (Hermes-I/Hermes-II).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>madwifi</term>
+ <listitem>
+ <para>MADWIFI 802.11 support (Atheros, etc.).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>atmel</term>
+ <listitem>
+ <para>ATMEL AT76C5XXx (USB, PCMCIA).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>wext</term>
+ <listitem>
+ <para>Linux wireless extensions (generic).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>ndiswrapper</term>
+ <listitem>
+ <para>Linux ndiswrapper.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>broadcom</term>
+ <listitem>
+ <para>Broadcom wl.o driver.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>ipw</term>
+ <listitem>
+ <para>Intel ipw2100/2200 driver.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>wired</term>
+ <listitem>
+ <para>wpa_supplicant wired Ethernet driver</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>bsd</term>
+ <listitem>
+ <para>BSD 802.11 support (Atheros, etc.).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>ndis</term>
+ <listitem>
+ <para>Windows NDIS driver.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Command Line Options</title>
+ <variablelist>
+ <varlistentry>
+ <term>-B</term>
+ <listitem>
+ <para>Run daemon in the background.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-i ifname</term>
+ <listitem>
+ <para>Interface to listen on.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c filename</term>
+ <listitem>
+ <para>Path to configuration file.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-D driver</term>
+ <listitem>
+ <para>Driver to use. See the available options below.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-d</term>
+ <listitem>
+ <para>Increase debugging verbosity (-dd even more).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-K</term>
+ <listitem>
+ <para>Include keys (passwords, etc.) in debug output.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t</term>
+ <listitem>
+ <para>Include timestamp in debug messages.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-e</term>
+ <listitem>
+ <para>Use external IEEE 802.1X Supplicant (e.g.,
+ <command>xsupplicant</command>) (this disables the internal
+ Supplicant).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>Help. Show a usage message.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-L</term>
+ <listitem>
+ <para>Show license (GPL and BSD).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-q</term>
+ <listitem>
+ <para>Decrease debugging verbosity (-qq even less).</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>-v</term>
+ <listitem>
+ <para>Show version.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-w</term>
+ <listitem>
+ <para>wait for interface to be added, if needed. normally,
+ <command>wpa_supplicant</command> will exit if the interface
+ is not there yet.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-N</term>
+ <listitem>
+ <para>Start describing new interface.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Examples</title>
+
+ <para>In most common cases, <command>wpa_supplicant</command> is
+ started with:</para>
+
+<blockquote><programlisting>
+wpa_supplicant -Bw -c/etc/wpa_supplicant.conf -iwlan0
+</programlisting></blockquote>
+
+ <para>This makes the process fork into background and wait for the wlan0
+ interface if it is not available at startup time.</para>
+
+ <para>The easiest way to debug problems, and to get debug log for
+ bug reports, is to start <command>wpa_supplicant</command> on
+ foreground with debugging enabled:</para>
+
+<blockquote><programlisting>
+wpa_supplicant -c/etc/wpa_supplicant.conf -iwlan0 -d
+</programlisting></blockquote>
+
+ <para><command>wpa_supplicant</command> can control multiple
+ interfaces (radios) either by running one process for each
+ interface separately or by running just one process and list of
+ options at command line. Each interface is separated with -N
+ argument. As an example, following command would start
+ wpa_supplicant for two interfaces:</para>
+
+<blockquote><programlisting>
+wpa_supplicant \
+ -c wpa1.conf -i wlan0 -D hostap -N \
+ -c wpa2.conf -i ath0 -D madwifi
+</programlisting></blockquote>
+ </refsect1>
+
+ <refsect1>
+ <title>OS Requirements</title>
+ <para>Current hardware/software requirements:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Linux kernel 2.4.x or 2.6.x with Linux Wireless
+ Extensions v15 or newer</para>
+ </listitem>
+
+
+ <listitem>
+ <para>FreeBSD 6-CURRENT</para>
+ </listitem>
+
+ <listitem>
+ <para>Microsoft Windows with WinPcap (at least WinXP, may work
+ with other versions)</para>
+ </listitem>
+ </itemizedlist>
+ </refsect1>
+
+ <refsect1>
+ <title>Supported Drivers</title>
+ <variablelist>
+ <varlistentry>
+ <term>Host AP driver for Prism2/2.5/3 (development
+ snapshot/v0.2.x)</term>
+ <listitem>
+ <para> (http://hostap.epitest.fi/) Driver needs to be set in
+ Managed mode ('iwconfig wlan0 mode managed'). Please note
+ that station firmware version needs to be 1.7.0 or newer to
+ work in WPA mode.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Linuxant DriverLoader</term>
+ <listitem>
+ <para>(http://www.linuxant.com/driverloader/)
+ with Windows NDIS driver for your wlan card supporting WPA.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Agere Systems Inc. Linux Driver</term>
+ <listitem>
+ <para> (http://www.agere.com/support/drivers/) Please note
+ that the driver interface file (driver_hermes.c) and hardware
+ specific include files are not included in the wpa_supplicant
+ distribution. You will need to copy these from the source
+ package of the Agere driver.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>madwifi driver for cards based on Atheros chip set (ar521x)</term>
+ <listitem>
+ <para> (http://sourceforge.net/projects/madwifi/) Please
+ note that you will need to modify the wpa_supplicant .config
+ file to use the correct path for the madwifi driver root
+ directory (CFLAGS += -I../madwifi/wpa line in example
+ defconfig).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>ATMEL AT76C5XXx driver for USB and PCMCIA cards</term>
+ <listitem>
+ <para> (http://atmelwlandriver.sourceforge.net/).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Linux ndiswrapper</term>
+ <listitem>
+ <para> (http://ndiswrapper.sourceforge.net/) with Windows
+ NDIS driver.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Broadcom wl.o driver</term>
+ <listitem>
+ <para> This is a generic Linux driver for Broadcom IEEE
+ 802.11a/g cards. However, it is proprietary driver that is
+ not publicly available except for couple of exceptions, mainly
+ Broadcom-based APs/wireless routers that use Linux. The driver
+ binary can be downloaded, e.g., from Linksys support site
+ (http://www.linksys.com/support/gpl.asp) for Linksys
+ WRT54G. The GPL tarball includes cross-compiler and the needed
+ header file, wlioctl.h, for compiling wpa_supplicant. This
+ driver support in wpa_supplicant is expected to work also with
+ other devices based on Broadcom driver (assuming the driver
+ includes client mode support).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term> Intel ipw2100 driver</term>
+ <listitem>
+ <para> (http://sourceforge.net/projects/ipw2100/)</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Intel ipw2200 driver</term>
+ <listitem>
+ <para> (http://sourceforge.net/projects/ipw2200/)</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Linux wireless extensions</term>
+ <listitem>
+ <para>In theory, any driver that supports Linux wireless
+ extensions can be used with IEEE 802.1X (i.e., not WPA) when
+ using ap_scan=0 option in configuration file.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Wired Ethernet drivers</term>
+ <listitem>
+ <para>Use ap_scan=0.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>BSD net80211 layer (e.g., Atheros driver)</term>
+ <listitem>
+ <para>At the moment, this is for FreeBSD 6-CURRENT branch.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Windows NDIS</term>
+ <listitem>
+ <para>The current Windows port requires WinPcap
+ (http://winpcap.polito.it/). See README-Windows.txt for more
+ information.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+
+ <para>wpa_supplicant was designed to be portable for different
+ drivers and operating systems. Hopefully, support for more wlan
+ cards and OSes will be added in the future. See developer.txt for
+ more information about the design of wpa_supplicant and porting to
+ other drivers. One main goal is to add full WPA/WPA2 support to
+ Linux wireless extensions to allow new drivers to be supported
+ without having to implement new driver-specific interface code in
+ wpa_supplicant.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>Architecture</title> <para>The
+ <command>wpa_supplicant</command> system consists of the following
+ components:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><filename>wpa_supplicant.conf</filename> </term>
+ <listitem>
+ <para>the configuration file describing all networks that the
+ user wants the computer to connect to. </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>wpa_supplicant</command></term>
+ <listitem><para>the program that directly interacts with the
+ network interface. </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>wpa_cli</command></term> <listitem><para> the
+ client program that provides a high-level interface to the
+ functionality of the daemon. </para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><command>wpa_passphrase</command></term>
+ <listitem><para>a utility needed to construct
+ <filename>wpa_supplicant.conf</filename> files that include
+ encrypted passwords.</para></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>Quick Start</title>
+
+ <para>First, make a configuration file, e.g.
+ <filename>/etc/wpa_supplicant.conf</filename>, that describes the networks
+ you are interested in. See <citerefentry>
+ <refentrytitle>wpa_supplicant</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </citerefentry>
+ for details.</para>
+
+ <para>Once the configuration is ready, you can test whether the
+ configuration works by running <command>wpa_supplicant</command>
+ with following command to start it on foreground with debugging
+ enabled:</para>
+
+ <blockquote><programlisting>
+wpa_supplicant -iwlan0 -c/etc/wpa_supplicant.conf -d
+ </programlisting></blockquote>
+
+ <para>Assuming everything goes fine, you can start using following
+ command to start <command>wpa_supplicant</command> on background
+ without debugging:</para>
+
+ <blockquote><programlisting>
+wpa_supplicant -iwlan0 -c/etc/wpa_supplicant.conf -B
+ </programlisting></blockquote>
+
+ <para>Please note that if you included more than one driver
+ interface in the build time configuration (.config), you may need
+ to specify which interface to use by including -D&lt;driver
+ name&gt; option on the command line.</para>
+
+ <!-- XXX at this point, the page could include a little script
+ based on wpa_cli to wait for a connection and then run
+ dhclient -->
+
+ </refsect1>
+
+ <refsect1>
+ <title>Interface to pcmcia-cs/cardmrg</title>
+
+ <para>For example, following small changes to pcmcia-cs scripts
+ can be used to enable WPA support:</para>
+
+ <para>Add MODE="Managed" and WPA="y" to the network scheme in
+ <filename>/etc/pcmcia/wireless.opts</filename>.</para>
+
+ <para>Add the following block to the end of 'start' action handler
+ in <filename>/etc/pcmcia/wireless</filename>:</para>
+
+ <blockquote><programlisting>
+if [ "$WPA" = "y" -a -x /usr/local/bin/wpa_supplicant ]; then
+ /usr/local/bin/wpa_supplicant -Bw -c/etc/wpa_supplicant.conf -i$DEVICE
+fi
+ </programlisting></blockquote>
+
+
+ <para>Add the following block to the end of 'stop' action handler
+ (may need to be separated from other actions) in
+ <filename>/etc/pcmcia/wireless</filename>:</para>
+
+ <blockquote><programlisting>
+if [ "$WPA" = "y" -a -x /usr/local/bin/wpa_supplicant ]; then
+ killall wpa_supplicant
+fi
+ </programlisting></blockquote>
+
+ <para>This will make <command>cardmgr</command> start
+ <command>wpa_supplicant</command> when the card is plugged
+ in. <command>wpa_supplicant</command> will wait until the
+ interface is set up--either when a static IP address is configured
+ or when DHCP client is started--and will then negotiate keys with
+ the AP.</para>
+ </refsect1>
+
+ <refsect1>
+ <title>See Also</title>
+ <para>
+ <citerefentry>
+ <refentrytitle>wpa_background</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>
+ <citerefentry>
+ <refentrytitle>wpa_supplicant.conf</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </citerefentry>
+ <citerefentry>
+ <refentrytitle>wpa_cli</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>
+ <citerefentry>
+ <refentrytitle>wpa_passphrase</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>Legal</title>
+ <para>wpa_supplicant is copyright (c) 2003-2005,
+ Jouni Malinen <email>jkmaline@cc.hut.fi</email> and
+ contributors.
+ All Rights Reserved.</para>
+
+ <para>This program is dual-licensed under both the GPL version 2
+ and BSD license. Either license may be used at your option.</para>
+ </refsect1>
+</refentry>
diff --git a/contrib/wpa_supplicant/doc/doxygen.fast b/contrib/wpa_supplicant/doc/doxygen.fast
new file mode 100644
index 000000000000..2eb9d27c386b
--- /dev/null
+++ b/contrib/wpa_supplicant/doc/doxygen.fast
@@ -0,0 +1,243 @@
+# Doxyfile 1.4.1
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = wpa_supplicant
+PROJECT_NUMBER = 0.4.x
+OUTPUT_DIRECTORY = doc
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+USE_WINDOWS_ENCODING = NO
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH =
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = NO
+JAVADOC_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP = NO
+INHERIT_DOCS = YES
+DISTRIBUTE_GROUP_DOC = NO
+TAB_SIZE = 8
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = YES
+OPTIMIZE_OUTPUT_JAVA = NO
+SUBGROUPING = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = NO
+EXTRACT_LOCAL_CLASSES = YES
+EXTRACT_LOCAL_METHODS = NO
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = YES
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+SORT_BRIEF_DOCS = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = YES
+SHOW_DIRECTORIES = NO
+FILE_VERSION_FILTER =
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = YES
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = . \
+ ../hostapd/aes.c \
+ ../hostapd/rc4.c \
+ ../hostapd/rc4.h \
+ ../hostapd/md5.c \
+ ../hostapd/md5.h \
+ ../hostapd/sha1.c \
+ ../hostapd/sha1.h \
+ ../hostapd/common.c \
+ ../hostapd/common.h \
+ ../hostapd/eloop.c \
+ ../hostapd/eloop.h \
+ ../hostapd/aes_wrap.c \
+ ../hostapd/aes_wrap.h
+FILE_PATTERNS = *.c *.h *.doxygen
+RECURSIVE = YES
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS = *
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH = doc
+INPUT_FILTER = kerneldoc2doxygen.pl
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = YES
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = YES
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION = NO
+VERBATIM_HEADERS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = YES
+COLS_IN_ALPHA_INDEX = 3
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = NO
+ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = YES
+USE_PDFLATEX = YES
+LATEX_BATCHMODE = NO
+LATEX_HIDE_INDICES = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
+XML_OUTPUT = xml
+XML_SCHEMA =
+XML_DTD =
+XML_PROGRAMLISTING = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED = IEEE8021X_EAPOL
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE =
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = NO
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = NO
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+GROUP_GRAPHS = YES
+UML_LOOK = NO
+TEMPLATE_RELATIONS = NO
+INCLUDE_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
+CALL_GRAPH = YES
+GRAPHICAL_HIERARCHY = YES
+DIRECTORY_GRAPH = NO
+DOT_IMAGE_FORMAT = png
+DOT_PATH =
+DOTFILE_DIRS =
+MAX_DOT_GRAPH_WIDTH = 1024
+MAX_DOT_GRAPH_HEIGHT = 1024
+MAX_DOT_GRAPH_DEPTH = 1000
+DOT_TRANSPARENT = NO
+DOT_MULTI_TARGETS = NO
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
diff --git a/contrib/wpa_supplicant/doc/doxygen.full b/contrib/wpa_supplicant/doc/doxygen.full
new file mode 100644
index 000000000000..69cec656f7f0
--- /dev/null
+++ b/contrib/wpa_supplicant/doc/doxygen.full
@@ -0,0 +1,230 @@
+# Doxyfile 1.4.1
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = wpa_supplicant
+PROJECT_NUMBER = 0.4.x
+OUTPUT_DIRECTORY = doc
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+USE_WINDOWS_ENCODING = NO
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH =
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = NO
+JAVADOC_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP = NO
+INHERIT_DOCS = YES
+DISTRIBUTE_GROUP_DOC = NO
+TAB_SIZE = 8
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = YES
+OPTIMIZE_OUTPUT_JAVA = NO
+SUBGROUPING = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = NO
+EXTRACT_LOCAL_CLASSES = YES
+EXTRACT_LOCAL_METHODS = NO
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = YES
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+SORT_BRIEF_DOCS = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = YES
+SHOW_DIRECTORIES = NO
+FILE_VERSION_FILTER =
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = YES
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = .
+FILE_PATTERNS = *.c *.h *.doxygen
+RECURSIVE = YES
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS = *
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH = doc
+INPUT_FILTER = kerneldoc2doxygen.pl
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = YES
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = YES
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION = NO
+VERBATIM_HEADERS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = YES
+COLS_IN_ALPHA_INDEX = 3
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = NO
+ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = YES
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = YES
+USE_PDFLATEX = YES
+LATEX_BATCHMODE = NO
+LATEX_HIDE_INDICES = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
+XML_OUTPUT = xml
+XML_SCHEMA =
+XML_DTD =
+XML_PROGRAMLISTING = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED = IEEE8021X_EAPOL
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE =
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = NO
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = YES
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+GROUP_GRAPHS = YES
+UML_LOOK = NO
+TEMPLATE_RELATIONS = NO
+INCLUDE_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
+CALL_GRAPH = YES
+GRAPHICAL_HIERARCHY = YES
+DIRECTORY_GRAPH = NO
+DOT_IMAGE_FORMAT = png
+DOT_PATH =
+DOTFILE_DIRS =
+MAX_DOT_GRAPH_WIDTH = 1024
+MAX_DOT_GRAPH_HEIGHT = 1024
+MAX_DOT_GRAPH_DEPTH = 1000
+DOT_TRANSPARENT = NO
+DOT_MULTI_TARGETS = NO
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = YES
diff --git a/contrib/wpa_supplicant/doc/driver_wrapper.doxygen b/contrib/wpa_supplicant/doc/driver_wrapper.doxygen
new file mode 100644
index 000000000000..232739a0688b
--- /dev/null
+++ b/contrib/wpa_supplicant/doc/driver_wrapper.doxygen
@@ -0,0 +1,180 @@
+/**
+\page driver_wrapper Driver wrapper implementation (driver.h, drivers.c)
+
+All hardware and driver dependent functionality is in separate C files
+that implement defined wrapper functions. Other parts
+of the %wpa_supplicant are designed to be hardware, driver, and operating
+system independent.
+
+Driver wrappers need to implement whatever calls are used in the
+target operating system/driver for controlling wireless LAN
+devices. As an example, in case of Linux, these are mostly some glue
+code and ioctl() calls and netlink message parsing for Linux Wireless
+Extensions (WE). Since features required for WPA were added only recently to
+Linux Wireless Extensions (in version 18), some driver specific code is used
+in number of driver interface implementations. These driver dependent parts
+can be replaced with generic code in driver_wext.c once the target driver
+includes full support for WE-18. After that, all Linux drivers, at
+least in theory, could use the same driver wrapper code.
+
+A driver wrapper needs to implement some or all of the functions
+defined in driver.h. These functions are registered by filling struct
+wpa_driver_ops with function pointers. Hardware independent parts of
+%wpa_supplicant will call these functions to control the driver/wlan
+card. In addition, support for driver events is required. The event
+callback function, wpa_supplicant_event(), and its parameters are
+documented in wpa_supplicant.h. In addition, a pointer to the 'struct
+wpa_driver_ops' needs to be registered in drivers.c file.
+
+When porting to other operating systems, the driver wrapper should be
+modified to use the native interface of the target OS. It is possible
+that some extra requirements for the interface between the driver
+wrapper and generic %wpa_supplicant code are discovered during porting
+to a new operating system. These will be addressed on case by case
+basis by modifying the interface and updating the other driver
+wrappers for this. The goal is to avoid changing this interface
+without very good reasons in order to limit the number of changes
+needed to other wrappers and hardware independent parts of
+%wpa_supplicant. When changes are required, recommended way is to
+make them in backwards compatible way that allows existing driver
+interface implementations to be compiled without any modification.
+
+Generic Linux Wireless Extensions functions are implemented in
+driver_wext.c. All Linux driver wrappers can use these when the kernel
+driver supports the generic ioctl()s and wireless events. Driver
+specific functions are implemented in separate C files, e.g.,
+driver_hostap.c. These files need to define struct wpa_driver_ops
+entry that will be used in wpa_supplicant.c when calling driver
+functions. struct wpa_driver_ops entries are registered in drivers.c.
+
+In general, it is likely to be useful to first take a look at couple
+of driver interface examples before starting on implementing a new
+one. driver_hostap.c and driver_wext.c include a complete
+implementation for Linux drivers that use %wpa_supplicant-based control
+of WPA IE and roaming. driver_ndis.c (with help from driver_ndis_.c)
+is an example of a complete interface for Windows NDIS interface for
+drivers that generate WPA IE themselves and decide when to roam. These
+example implementations include full support for all security modes.
+
+
+\section driver_req Driver requirements for WPA
+
+WPA introduces new requirements for the device driver. At least some
+of these need to be implemented in order to provide enough support for
+%wpa_supplicant.
+
+\subsection driver_tkip_ccmp TKIP/CCMP
+
+WPA requires that the pairwise cipher suite (encryption algorithm for
+unicast data packets) is TKIP or CCMP. These are new encryption
+protocols and thus, the driver will need to be modified to support
+them. Depending on the used wlan hardware, some parts of these may be
+implemented by the hardware/firmware.
+
+Specification for both TKIP and CCMP is available from IEEE (IEEE
+802.11i amendment). Fully functional, hardware independent
+implementation of both encryption protocols is also available in Host
+AP driver (driver/modules/hostap_{tkip,ccmp}.c). In addition, Linux 2.6
+kernel tree has generic implementations for WEP, TKIP, and CCMP that can
+be used in Linux drivers.
+
+The driver will also need to provide configuration mechanism to allow
+user space programs to configure TKIP and CCMP. Linux Wireless Extensions
+v18 added support for configuring these algorithms and
+individual/non-default keys. If the target kernel does not include WE-18,
+private ioctls can be used to provide similar functionality.
+
+\subsection driver_roaming Roaming control and scanning support
+
+%wpa_supplicant can optionally control AP selection based on the
+information received from Beacon and/or Probe Response frames
+(ap_scan=1 mode in configuration). This means that the driver should
+support external control for scan process. In case of Linux, use of
+new Wireless Extensions scan support (i.e., 'iwlist wlan0 scan') is
+recommended. The current driver wrapper (driver_wext.c) uses this for
+scan results.
+
+Scan results must also include the WPA information element. Support for
+this was added in WE-18. With older versions, a custom event can be used
+to provide the full WPA IE (including element id and length) as a hex
+string that is included in the scan results.
+
+%wpa_supplicant needs to also be able to request the driver to
+associate with a specific BSS. Current Host AP driver and matching
+driver_hostap.c wrapper uses following sequence for this
+request. Similar/identical mechanism should be usable also with other
+drivers.
+
+- set WPA IE for AssocReq with private ioctl
+- set SSID with SIOCSIWESSID
+- set channel/frequency with SIOCSIWFREQ
+- set BSSID with SIOCSIWAP
+ (this last ioctl will trigger the driver to request association)
+
+\subsection driver_wpa_ie WPA IE generation
+
+%wpa_supplicant selects which cipher suites and key management suites
+are used. Based on this information, it generates a WPA IE. This is
+provided to the driver interface in the associate call. This does not
+match with Windows NDIS drivers which generate the WPA IE
+themselves.
+
+%wpa_supplicant allows Windows NDIS-like behavior by providing the
+selected cipher and key management suites in the associate call. If
+the driver generates its own WPA IE and that differs from the one
+generated by %wpa_supplicant, the driver has to inform %wpa_supplicant
+about the used WPA IE (i.e., the one it used in (Re)Associate
+Request). This notification is done using EVENT_ASSOCINFO event (see
+wpa_supplicant.h). %wpa_supplicant is normally configured to use
+ap_scan=2 mode with drivers that control WPA IE generation and roaming.
+
+\subsection driver_events Driver events
+
+%wpa_supplicant needs to receive event callbacks when certain events
+occur (association, disassociation, Michael MIC failure, scan results
+available, PMKSA caching candidate). These events and the callback
+details are defined in wpa_supplicant.h (wpa_supplicant_event() function
+and enum wpa_event_type).
+
+On Linux, association and disassociation can use existing Wireless
+Extensions event that is reporting new AP with SIOCGIWAP
+event. Similarly, completion of a scan can be reported with SIOCGIWSCAN
+event.
+
+Michael MIC failure event was added in WE-18. Older versions of Wireless
+Extensions will need to use a custom event. Host AP driver used a custom
+event with following contents: MLME-MICHAELMICFAILURE.indication(keyid=#
+broadcast/unicast addr=addr2). This is the recommended format until
+the driver can be moved to use WE-18 mechanism.
+
+\subsection driver_wext_summary Summary of Linux Wireless Extensions use
+
+AP selection depends on ap_scan configuration:
+
+ap_scan=1:
+
+- %wpa_supplicant requests scan with SIOCSIWSCAN
+- driver reports scan complete with wireless event SIOCGIWSCAN
+- %wpa_supplicant reads scan results with SIOCGIWSCAN (multiple call if
+ a larget buffer is needed)
+- %wpa_supplicant decides which AP to use based on scan results
+- %wpa_supplicant configures driver to associate with the selected BSS
+ (SIOCSIWMODE, SIOCSIWGENIE, SIOCSIWAUTH, SIOCSIWFREQ,
+ SIOCSIWESSID, SIOCSIWAP)
+
+ap_scan=2:
+
+- %wpa_supplicant configures driver to associate with an SSID
+ (SIOCSIWMODE, SIOCSIWGENIE, SIOCSIWAUTH, SIOCSIWESSID)
+
+
+After this, both modes use similar steps:
+
+- optionally (or required for drivers that generate WPA/RSN IE for
+ (Re)AssocReq), driver reports association parameters (AssocReq IEs)
+ with wireless event IWEVASSOCREQIE (and optionally IWEVASSOCRESPIE)
+- driver reports association with wireless event SIOCGIWAP
+- %wpa_supplicant takes care of EAPOL frame handling (validating
+ information from associnfo and if needed, from scan results if WPA/RSN
+ IE from the Beacon frame is not reported through associnfo)
+*/
diff --git a/contrib/wpa_supplicant/doc/eap.doxygen b/contrib/wpa_supplicant/doc/eap.doxygen
new file mode 100644
index 000000000000..e1ae9c047cf2
--- /dev/null
+++ b/contrib/wpa_supplicant/doc/eap.doxygen
@@ -0,0 +1,38 @@
+/**
+\page eap_module EAP peer implementation
+
+%wpa_supplicant uses a separate code module for EAP peer
+implementation. This module was designed to use only a minimal set of
+direct function calls (mainly, to debug/event functions) in order for
+it to be usable in other programs. The design of the EAP
+implementation is based loosely on RFC 4137. The state machine is
+defined in this RFC and so is the interface between the peer state
+machine and methods. As such, this RFC provides useful information for
+understanding the EAP peer implementation in %wpa_supplicant.
+
+Some of the terminology used in EAP state machine is referring to
+EAPOL (IEEE 802.1X), but there is no strict requirement on the lower
+layer being IEEE 802.1X if EAP module is built for other programs than
+%wpa_supplicant. These terms should be understood to refer to the
+lower layer as defined in RFC 4137.
+
+
+\section adding_eap_methods Adding EAP methods
+
+Each EAP method is implemented as a separate module, usually as one C
+file named eap_<name of the method>.c, e.g., eap_md5.c. All EAP
+methods use the same interface between the peer state machine and
+method specific functions. This allows new EAP methods to be added
+without modifying the core EAP state machine implementation.
+
+New EAP methods need to be registered by adding them into build
+(Makefile) and EAP method table in the beginning of eap.c. Each EAP
+method should use a build-time configuration option, e.g., EAP_TLS, in
+order to make it possible to select which of the methods are included
+in the build.
+
+EAP methods must implement the interface defined in eap_i.h. struct
+eap_method defines the needed function pointers that each EAP method
+must provide. In addition, the EAP type and name are registered using
+this structure. This interface is based on section 4.4 of RFC 4137.
+*/
diff --git a/contrib/wpa_supplicant/doc/kerneldoc2doxygen.pl b/contrib/wpa_supplicant/doc/kerneldoc2doxygen.pl
new file mode 100755
index 000000000000..d46f7bd07868
--- /dev/null
+++ b/contrib/wpa_supplicant/doc/kerneldoc2doxygen.pl
@@ -0,0 +1,129 @@
+#!/usr/bin/perl -w
+#
+##########################################################################
+# Convert kernel-doc style comments to Doxygen comments.
+##########################################################################
+#
+# This script reads a C source file from stdin, and writes
+# to stdout. Normal usage:
+#
+# $ mv file.c file.c.gtkdoc
+# $ kerneldoc2doxygen.pl <file.c.gtkdoc >file.c
+#
+# Or to do the same thing with multiple files:
+# $ perl -i.gtkdoc kerneldoc2doxygen.pl *.c *.h
+#
+# This script may also be suitable for use as a Doxygen input filter,
+# but that has not been tested.
+#
+# Back up your source files before using this script!!
+#
+##########################################################################
+# Copyright (C) 2003 Jonathan Foster <jon@jon-foster.co.uk>
+# Copyright (C) 2005 Jouni Malinen <jkmaline@cc.hut.fi>
+# (modified for kerneldoc format used in wpa_supplicant)
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+# or look at http://www.gnu.org/licenses/gpl.html
+##########################################################################
+
+
+##########################################################################
+#
+# This function converts a single comment from gtk-doc to Doxygen format.
+# The parameter does not include the opening or closing lines
+# (i.e. given a comment like this:
+# "/**\n"
+# " * FunctionName:\n"
+# " * @foo: This describes the foo parameter\n"
+# " * @bar: This describes the bar parameter\n"
+# " * @Returns: This describes the return value\n"
+# " *\n"
+# " * This describes the function.\n"
+# " */\n"
+# This function gets:
+# " * FunctionName:\n"
+# " * @foo: This describes the foo parameter\n"
+# " * @bar: This describes the bar parameter\n"
+# " * @Returns: This describes the return value\n"
+# " *\n"
+# " * This describes the function.\n"
+# And it returns:
+# " * This describes the function.\n"
+# " *\n"
+# " * @param foo This describes the foo parameter\n"
+# " * @param bar This describes the bar parameter\n"
+# " * @return This describes the return value\n"
+# )
+#
+sub fixcomment {
+ $t = $_[0];
+
+ # " * func: foo" --> "\brief foo\n"
+ # " * struct bar: foo" --> "\brief foo\n"
+ # If this fails, not a kernel-doc comment ==> return unmodified.
+ ($t =~ s/^[\t ]*\*[\t ]*(struct )?([^ \t\n]*) - ([^\n]*)/\\brief $3\n/s)
+ or return $t;
+
+ # " * Returns: foo" --> "\return foo"
+ $t =~ s/\n[\t ]*\*[\t ]*Returns:/\n\\return/sig;
+
+ # " * @foo: bar" --> "\param foo bar"
+ # Handle two common typos: No ":", or "," instead of ":".
+ $t =~ s/\n[\t ]*\*[\t ]*\@([^ :,]*)[:,]?[\t ]*/\n\\param $1 /sg;
+
+ return $t;
+}
+
+##########################################################################
+# Start of main code
+
+# Read entire stdin into memory - one multi-line string.
+$_ = do { local $/; <> };
+
+s{^/\*\n \*}{/\*\* \\file\n\\brief};
+s{ \* Copyright}{\\par Copyright\nCopyright};
+
+# Fix any comments like "/*************" so they don't match.
+# "/***" ===> "/* *"
+s{/\*\*\*}{/\* \*}gs;
+
+# The main comment-detection code.
+s{
+ ( # $1 = Open comment
+ /\*\* # Open comment
+ (?!\*) # Do not match /*** (redundant due to fixup above).
+ [\t ]*\n? # If 1st line is whitespace, match the lot (including the newline).
+ )
+ (.*?) # $2 = Body of comment (multi-line)
+ ( # $3 = Close comment
+ ( # If possible, match the whitespace before the close-comment
+ (?<=\n) # This part only matches after a newline
+ [\t ]* # Eat whitespace
+ )?
+ \*/ # Close comment
+ )
+ }
+ {
+ $1 . fixcomment($2) . $3
+ }gesx;
+# ^^^^ Modes: g - Global, match all occurances.
+# e - Evaluate the replacement as an expression.
+# s - Single-line - allows the pattern to match across newlines.
+# x - eXtended pattern, ignore embedded whitespace
+# and allow comments.
+
+# Write results to stdout
+print $_;
+
diff --git a/contrib/wpa_supplicant/doc/mainpage.doxygen b/contrib/wpa_supplicant/doc/mainpage.doxygen
new file mode 100644
index 000000000000..56882f44fe1d
--- /dev/null
+++ b/contrib/wpa_supplicant/doc/mainpage.doxygen
@@ -0,0 +1,56 @@
+/**
+\mainpage Developers' documentation for %wpa_supplicant
+
+%wpa_supplicant is a WPA Supplicant for Linux, BSD and Windows with
+support for WPA and WPA2 (IEEE 802.11i / RSN). Supplicant is the IEEE
+802.1X/WPA component that is used in the client stations. It
+implements key negotiation with a WPA Authenticator and it can optionally
+control roaming and IEEE 802.11 authentication/association of the wlan
+driver.
+
+The goal of this documentation and comments in the source code is to
+give enough information for other developers to understand how
+%wpa_supplicant has been implemented, how it can be modified, how new
+drivers can be supported, and how %wpa_supplicant can be ported to
+other operating systems. If any information is missing, feel free to
+contact Jouni Malinen <jkmaline@cc.hut.fi> for more
+information. Contributions as patch files are also very welcome at the
+same address. Please note that %wpa_supplicant is licensed under dual
+license, GPLv2 or BSD at user's choice. All contributions to
+%wpa_supplicant are expected to use compatible licensing terms.
+
+The source code and read-only access to %wpa_supplicant CVS repository
+is available from the project home page at
+http://hostap.epitest.fi/wpa_supplicant/. This developers' documentation
+is also available as a PDF file from
+http://hostap.epitest.fi/wpa_supplicant/wpa_supplicant-devel.pdf .
+
+The design goal for %wpa_supplicant was to use hardware, driver, and
+OS independent, portable C code for all WPA functionality. The source
+code is divided into separate C files as shown on the \ref
+code_structure "code structure page". All hardware/driver specific
+functionality is in separate files that implement a \ref
+driver_wrapper "well-defined driver API". Information about porting
+to different target boards and operating systems is available on
+the \ref porting "porting page".
+
+EAPOL (IEEE 802.1X) state machines are implemented as a separate
+module that interacts with \ref eap_module "EAP peer implementation".
+In addition to programs aimed at normal production use,
+%wpa_supplicant source tree includes number of \ref testing_tools
+"testing and development tools" that make it easier to test the
+programs without having to setup a full test setup with wireless
+cards. These tools can also be used to implement automatic test
+suites.
+
+%wpa_supplicant implements a
+\ref ctrl_iface_page "control interface" that can be used by
+external programs to control the operations of the %wpa_supplicant
+daemon and to get status information and event notifications. There is
+a small C library that provides helper functions to facilitate the use of the
+control interface. This library can also be used with C++.
+
+\image html wpa_supplicant.png "wpa_supplicant modules"
+\image latex wpa_supplicant.eps "wpa_supplicant modules" width=15cm
+
+*/
diff --git a/contrib/wpa_supplicant/doc/porting.doxygen b/contrib/wpa_supplicant/doc/porting.doxygen
new file mode 100644
index 000000000000..db64a11b536e
--- /dev/null
+++ b/contrib/wpa_supplicant/doc/porting.doxygen
@@ -0,0 +1,121 @@
+/**
+\page porting Porting to different target boards and operating systems
+
+%wpa_supplicant was designed to be easily portable to different
+hardware (board, CPU) and software (OS, drivers) targets. It is
+already used with number of operating systems and numerous wireless
+card models and drivers. The main %wpa_supplicant repository includes
+support for Linux, FreeBSD, and Windows. In addition, at least VxWorks
+and PalmOS are supported in separate repositories. On the hardware
+side, %wpa_supplicant is used on various systems: desktops, laptops,
+PDAs, and embedded devices with CPUs including x86, PowerPC,
+arm/xscale, and MIPS. Both big and little endian configurations are
+supported.
+
+
+\section driver_iface_porting Driver interface
+
+Unless the target OS and driver is already supported, most porting
+projects have to implement a driver wrapper. This may be done by
+adding a new driver interface module or modifying an existing module
+(driver_*.c) if the new target is similar to one of them. \ref
+driver_wrapper "Driver wrapper implementation" describes the details
+of the driver interface and discusses the tasks involved in porting
+this part of %wpa_supplicant.
+
+
+\section l2_packet_porting l2_packet (link layer access)
+
+%wpa_supplicant needs to have access to sending and receiving layer 2
+(link layer) packets with two Ethertypes: EAP-over-LAN (EAPOL) 0x888e
+and RSN pre-authentication 0x88c7. l2_packet.h defines the interfaces
+used for this in the core %wpa_supplicant implementation.
+
+If the target operating system supports a generic mechanism for link
+layer access, that is likely the best mechanism for providing the
+needed functionality for %wpa_supplicant. Linux packet socket is an
+example of such a generic mechanism. If this is not available, a
+separate interface may need to be implemented to the network stack or
+driver. This is usually an intermediate or protocol driver that is
+operating between the device driver and the OS network stack. If such
+a mechanism is not feasible, the interface can also be implemented
+directly in the device driver.
+
+The main %wpa_supplicant repository includes l2_packet implementations
+for Linux using packet sockets (l2_packet_linux.c), more portable
+version using libpcap/libdnet libraries (l2_packet_pcap.c; this
+supports WinPcap, too), and FreeBSD specific version of libpcap
+interface (l2_packet_freebsd.c).
+
+If the target operating system is supported by libpcap (receiving) and
+libdnet (sending), l2_packet_pcap.c can likely be used with minimal or
+no changes. If this is not a case or a proprietary interface for link
+layer is required, a new l2_packet module may need to be
+added. Alternatively, struct wpa_driver_ops::send_eapol() handler can
+be used to override the l2_packet library if the link layer access is
+integrated with the driver interface implementation.
+
+
+\section eloop_porting Event loop
+
+%wpa_supplicant uses a single process/thread model and an event loop
+to provide callbacks on events (registered timeout, received packet,
+signal). eloop.h defines the event loop interface. eloop.c is an
+implementation of such an event loop using select() and sockets. This
+is suitable for most UNIX/POSIX systems. When porting to other
+operating systems, it may be necessary to replace that implementation
+with OS specific mechanisms that provide similar functionality.
+
+
+\section ctrl_iface_porting Control interface
+
+%wpa_supplicant uses a \ref ctrl_iface_page "control interface"
+to allow external processed
+to get status information and to control the operations. Currently,
+this is implemented with socket based communication; both UNIX domain
+sockets and UDP sockets are supported. If the target OS does not
+support sockets, this interface will likely need to be modified to use
+another mechanism like message queues. The control interface is
+optional component, so it is also possible to run %wpa_supplicant
+without porting this part.
+
+The %wpa_supplicant side of the control interface is implemented in
+ctrl_iface.c. Matching client side is implemented as a control
+interface library in wpa_ctrl.c.
+
+
+\section entry_point Program entry point
+
+%wpa_supplicant defines a set of functions that can be used to
+initialize main supplicant processing. Each operating system has a
+mechanism for starting new processing or threads. This is usually a
+function with a specific set of arguments and calling convention. This
+function is responsible on initializing %wpa_supplicant.
+
+main.c includes an entry point for UNIX-like operating system, i.e.,
+main() function that uses command line arguments for setting
+parameters for %wpa_supplicant. When porting to other operating
+systems, similar OS-specific entry point implementation is needed. It
+can be implemented in a new file that is then linked with
+%wpa_supplicant instead of main.o. main.c is also a good example on
+how the initialization process should be done.
+
+The supplicant initialization functions are defined in
+wpa_supplicant_i.h. In most cases, the entry point function should
+start by fetching configuration parameters. After this, a global
+%wpa_supplicant context is initialized with a call to
+wpa_supplicant_init(). After this, existing network interfaces can be
+added with wpa_supplicant_add_iface(). wpa_supplicant_run() is then
+used to start the main event loop. Once this returns at program
+termination time, wpa_supplicant_deinit() is used to release global
+context data.
+
+wpa_supplicant_add_iface() and wpa_supplicant_remove_iface() can be
+used dynamically to add and remove interfaces based on when
+%wpa_supplicant processing is needed for them. This can be done, e.g.,
+when hotplug network adapters are being inserted and ejected. It is
+also possible to do this when a network interface is being
+enabled/disabled if it is desirable that %wpa_supplicant processing
+for the interface is fully enabled/disabled at the same time.
+
+*/
diff --git a/contrib/wpa_supplicant/doc/testing_tools.doxygen b/contrib/wpa_supplicant/doc/testing_tools.doxygen
new file mode 100644
index 000000000000..c1e24082a0f8
--- /dev/null
+++ b/contrib/wpa_supplicant/doc/testing_tools.doxygen
@@ -0,0 +1,288 @@
+/**
+\page testing_tools Testing and development tools
+
+[ \ref eapol_test "eapol_test" |
+\ref preauth_test "preauth_test" |
+\ref driver_test "driver_test" |
+\ref unit_tests "Unit tests" ]
+
+%wpa_supplicant source tree includes number of testing and development
+tools that make it easier to test the programs without having to setup
+a full test setup with wireless cards. In addition, these tools can be
+used to implement automatic tests suites.
+
+\section eapol_test eapol_test - EAP peer and RADIUS client testing
+
+eapol_test is a program that links together the same EAP peer
+implementation that %wpa_supplicant is using and the RADIUS
+authentication client code from hostapd. In addition, it has minimal
+glue code to combine these two components in similar ways to IEEE
+802.1X/EAPOL Authenticator state machines. In other words, it
+integrates IEEE 802.1X Authenticator (normally, an access point) and
+IEEE 802.1X Supplicant (normally, a wireless client) together to
+generate a single program that can be used to test EAP methods without
+having to setup an access point and a wireless client.
+
+The main uses for eapol_test are in interoperability testing of EAP
+methods against RADIUS servers and in development testing for new EAP
+methods. It can be easily used to automate EAP testing for
+interoperability and regression since the program can be run from
+shell scripts without require additional test components apart from a
+RADIUS server. For example, the automated EAP tests described in
+eap_testing.txt are implemented with eapol_test. Similarly, eapol_test
+could be used to implement an automated regression test suite for a
+RADIUS authentication server.
+
+eapol_test uses the same build time configuration file, .config, as
+%wpa_supplicant. This file is used to select which EAP methods are
+included in eapol_test. This program is not built with the default
+Makefile target, so a separate make command needs to be used to
+compile the tool:
+
+\verbatim
+make eapol_test
+\endverbatim
+
+The resulting eapol_test binary has following command like options:
+
+\verbatim
+usage:
+eapol_test [-nW] -c<conf> [-a<AS IP>] [-p<AS port>] [-s<AS secret>] [-r<count>]
+eapol_test scard
+eapol_test sim <PIN> <num triplets> [debug]
+
+options:
+ -c<conf> = configuration file
+ -a<AS IP> = IP address of the authentication server, default 127.0.0.1
+ -p<AS port> = UDP port of the authentication server, default 1812
+ -s<AS secret> = shared secret with the authentication server, default 'radius'
+ -r<count> = number of re-authentications
+ -W = wait for a control interface monitor before starting
+ -n = no MPPE keys expected
+\endverbatim
+
+
+As an example,
+\verbatim
+eapol_test -ctest.conf -a127.0.0.1 -p1812 -ssecret -r1
+\endverbatim
+tries to complete EAP authentication based on the network
+configuration from test.conf against the RADIUS server running on the
+local host. A re-authentication is triggered to test fast
+re-authentication. The configuration file uses the same format for
+network blocks as %wpa_supplicant.
+
+
+\section preauth_test preauth_test - WPA2 pre-authentication and EAP peer testing
+
+preauth_test is similar to eapol_test in the sense that in combines
+EAP peer implementation with something else, in this case, with WPA2
+pre-authentication. This tool can be used to test pre-authentication
+based on the code that %wpa_supplicant is using. As such, it tests
+both the %wpa_supplicant implementation and the functionality of an
+access point.
+
+preauth_test is built with:
+
+\verbatim
+make preauth_test
+\endverbatim
+
+and it uses following command line arguments:
+
+\verbatim
+usage: preauth_test <conf> <target MAC address> <ifname>
+\endverbatim
+
+For example,
+\verbatim
+preauth_test test.conf 02:11:22:33:44:55 eth0
+\endverbatim
+would use network configuration from test.conf to try to complete
+pre-authentication with AP using BSSID 02:11:22:33:44:55. The
+pre-authentication packets would be sent using the eth0 interface.
+
+
+\section driver_test driver_test - driver interface for testing wpa_supplicant
+
+%wpa_supplicant was designed to support number of different ways to
+communicate with a network device driver. This design uses \ref
+driver_wrapper "driver interface API" and number of driver interface
+implementations. One of these is driver_test.c, i.e., a test driver
+interface that is actually not using any drivers. Instead, it provides
+a mechanism for running %wpa_supplicant without having to have a
+device driver or wireless LAN hardware for that matter.
+
+driver_test can be used to talk directly with hostapd's driver_test
+component to create a test setup where one or more clients and access
+points can be tested within one test host and without having to have
+multiple wireless cards. This makes it easier to test the core code in
+%wpa_supplicant, and hostapd for that matter. Since driver_test uses
+the same driver API than any other driver interface implementation,
+the core code of %wpa_supplicant and hostapd can be tested with the
+same coverage as one would get when using real wireless cards. The
+only area that is not tested is the driver interface implementation
+(driver_*.c).
+
+Having the possibility to use simulated network components makes it
+much easier to do development testing while adding new features and to
+reproduce reported bugs. As such, it is often easiest to just do most
+of the development and bug fixing without using real hardware. Once
+the driver_test setup has been used to implement a new feature or fix
+a bug, the end result can be verified with wireless LAN cards. In many
+cases, this may even be unnecessary, depending on what area the
+feature/bug is relating to. Of course, changes to driver interfaces
+will still require use of real hardware.
+
+Since multiple components can be run within a single host, testing of
+complex network configuration, e.g., large number of clients
+association with an access point, becomes quite easy. All the tests
+can also be automated without having to resort to complex test setup
+using remote access to multiple computers.
+
+driver_test can be included in the %wpa_supplicant build in the same
+way as any other driver interface, i.e., by adding the following line
+into .config:
+
+\verbatim
+CONFIG_DRIVER_TEST=y
+\endverbatim
+
+When running %wpa_supplicant, the test interface is selected by using
+\a -Dtest command line argument. The interface name (\a -i argument)
+can be selected arbitrarily, i.e., it does not need to match with any
+existing network interface. The interface name is used to generate a
+MAC address, so when using multiple clients, each should use a
+different interface, e.g., \a sta1, \a sta2, and so on.
+
+%wpa_supplicant and hostapd are configured in the same way as they
+would be for normal use. Following example shows a simple test setup
+for WPA-PSK.
+
+hostapd is configured with following psk-test.conf configuration file:
+
+\verbatim
+driver=test
+
+interface=ap1
+logger_stdout=-1
+logger_stdout_level=0
+debug=2
+dump_file=/tmp/hostapd.dump
+
+test_socket=/tmp/Test/ap1
+
+ssid=jkm-test-psk
+
+wpa=1
+wpa_key_mgmt=WPA-PSK
+wpa_pairwise=TKIP
+wpa_passphrase=12345678
+\endverbatim
+
+and started with following command:
+
+\verbatim
+hostapd psk-test.conf
+\endverbatim
+
+%wpa_supplicant uses following configuration file:
+
+\verbatim
+driver_param=test_socket=/tmp/Test/ap1
+
+network={
+ ssid="jkm-test-psk"
+ key_mgmt=WPA-PSK
+ psk="12345678"
+}
+\endverbatim
+
+%wpa_supplicant can then be started with following command:
+
+\verbatim
+wpa_supplicant -Dtest -cpsk-test.conf -ista1 -ddK
+\endverbatim
+
+If run without debug information, i.e., with
+
+\verbatim
+wpa_supplicant -Dtest -cpsk-test.conf -ista1
+\endverbatim
+
+%wpa_supplicant completes authentication and prints following events:
+
+\verbatim
+Trying to associate with 02:b8:a6:62:08:5a (SSID='jkm-test-psk' freq=0 MHz)
+Associated with 02:b8:a6:62:08:5a
+WPA: Key negotiation completed with 02:b8:a6:62:08:5a [PTK=TKIP GTK=TKIP]
+CTRL-EVENT-CONNECTED - Connection to 02:b8:a6:62:08:5a completed (auth)
+\endverbatim
+
+If test setup is using multiple clients, it is possible to run
+multiple %wpa_supplicant processes. Alternatively, the support for
+multiple interfaces can be used with just one process to save some
+resources on single-CPU systems. For example, following command runs
+two clients:
+
+\verbatim
+./wpa_supplicant -Dtest -cpsk-test.conf -ista1 \
+ -N -Dtest -cpsk-test.conf -ista2
+\endverbatim
+
+This shows following event log:
+
+\verbatim
+Trying to associate with 02:b8:a6:62:08:5a (SSID='jkm-test-psk' freq=0 MHz)
+Associated with 02:b8:a6:62:08:5a
+WPA: Key negotiation completed with 02:b8:a6:62:08:5a [PTK=TKIP GTK=TKIP]
+CTRL-EVENT-CONNECTED - Connection to 02:b8:a6:62:08:5a completed (auth)
+Trying to associate with 02:b8:a6:62:08:5a (SSID='jkm-test-psk' freq=0 MHz)
+Associated with 02:b8:a6:62:08:5a
+WPA: Key negotiation completed with 02:b8:a6:62:08:5a [PTK=TKIP GTK=TKIP]
+CTRL-EVENT-CONNECTED - Connection to 02:b8:a6:62:08:5a completed (auth)
+\endverbatim
+
+hostapd shows this with following events:
+
+\verbatim
+ap1: STA 02:b5:64:63:30:63 IEEE 802.11: associated
+ap1: STA 02:b5:64:63:30:63 WPA: pairwise key handshake completed (WPA)
+ap1: STA 02:b5:64:63:30:63 WPA: group key handshake completed (WPA)
+ap1: STA 02:2a:c4:18:5b:f3 IEEE 802.11: associated
+ap1: STA 02:2a:c4:18:5b:f3 WPA: pairwise key handshake completed (WPA)
+ap1: STA 02:2a:c4:18:5b:f3 WPA: group key handshake completed (WPA)
+\endverbatim
+
+By default, driver_param is simulating a driver that uses the WPA/RSN
+IE generated by %wpa_supplicant. Driver-generated IE and AssocInfo
+events can be tested by adding \a use_associnfo=1 to the \a driver_param
+line in the configuration file. For example:
+
+\verbatim
+driver_param=test_socket=/tmp/Test/ap1 use_associnfo=1
+\endverbatim
+
+
+\section unit_tests Unit tests
+
+Number of the components (.c files) used in %wpa_supplicant define
+their own unit tests for automated validation of the basic
+functionality. Most of the tests for cryptographic algorithms are
+using standard test vectors to validate functionality. These tests can
+be useful especially when verifying port to a new CPU target.
+
+In most cases, these tests are implemented in the end of the same file
+with functions that are normally commented out, but ca be included by
+defining a pre-processor variable when building the file separately.
+The details of the needed build options are included in the Makefile
+(test-* targets). All automated unit tests can be run with
+
+\verbatim
+make tests
+\endverbatim
+
+This make target builds and runs each test and terminates with zero
+exit code if all tests were completed successfully.
+
+*/
diff --git a/contrib/wpa_supplicant/doc/wpa_supplicant.fig b/contrib/wpa_supplicant/doc/wpa_supplicant.fig
index dc1d9dfcf738..06abfb54b61b 100644
--- a/contrib/wpa_supplicant/doc/wpa_supplicant.fig
+++ b/contrib/wpa_supplicant/doc/wpa_supplicant.fig
@@ -117,7 +117,7 @@ Single
9600 3000 10275 3000 10275 3300 9600 3300 9600 3000
4 0 0 50 -1 0 12 0.0000 4 135 315 9750 3225 TLS\001
-6
-6 8100 4425 10425 6975
+6 8100 4425 10425 7350
6 8175 4725 9225 5025
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
8175 4725 9225 4725 9225 5025 8175 5025 8175 4725
@@ -153,11 +153,6 @@ Single
8175 5850 9225 5850 9225 6150 8175 6150 8175 5850
4 0 0 50 -1 0 12 0.0000 4 135 750 8250 6075 EAP-SIM\001
-6
-6 8175 6600 9675 6900
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
- 8175 6600 9675 6600 9675 6900 8175 6900 8175 6600
-4 0 0 50 -1 0 12 0.0000 4 135 1365 8250 6825 EAP-MSCHAPv2\001
--6
6 9300 6225 10350 6525
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
9300 6225 10350 6225 10350 6525 9300 6525 9300 6225
@@ -173,10 +168,35 @@ Single
9300 5850 10350 5850 10350 6150 9300 6150 9300 5850
4 0 0 50 -1 0 12 0.0000 4 135 825 9375 6075 EAP-AKA\001
-6
+6 8175 6975 9675 7275
+2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
+ 8175 6975 9675 6975 9675 7275 8175 7275 8175 6975
+4 0 0 50 -1 0 12 0.0000 4 135 1365 8250 7200 EAP-MSCHAPv2\001
+-6
+6 9300 6600 10350 6900
+2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
+ 9300 6600 10350 6600 10350 6900 9300 6900 9300 6600
+4 0 0 50 -1 0 12 0.0000 4 135 870 9375 6825 EAP-FAST\001
+-6
+6 8175 6600 9225 6900
+2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
+ 8175 6600 9225 6600 9225 6900 8175 6900 8175 6600
+4 0 0 50 -1 0 12 0.0000 4 135 795 8250 6825 EAP-PAX\001
+-6
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
- 8100 6975 10425 6975 10425 4425 8100 4425 8100 6975
+ 8100 7350 10425 7350 10425 4425 8100 4425 8100 7350
4 0 0 50 -1 0 12 0.0000 4 135 1050 8700 4650 EAP methods\001
-6
+6 2775 5025 4050 5325
+2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
+ 2775 5025 4050 5025 4050 5325 2775 5325 2775 5025
+4 0 0 50 -1 0 12 0.0000 4 135 990 2925 5250 driver events\001
+-6
+6 2775 3150 4050 3450
+2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
+ 2775 3150 4050 3150 4050 3450 2775 3450 2775 3150
+4 0 0 50 -1 0 12 0.0000 4 180 990 2925 3375 configuration\001
+-6
2 1 1 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2
1275 4200 1875 4200
2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
@@ -213,9 +233,15 @@ Single
1500 2100 10800 2100 10800 7500 1500 7500 1500 2100
2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2
9900 4425 9900 3300
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 1
+ 4350 3900
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+ 4350 3900 4050 3450
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+ 4350 4425 4050 5025
4 0 0 50 -1 0 12 0.0000 4 135 915 375 3975 EAPOL and\001
4 0 0 50 -1 0 12 0.0000 4 180 630 375 4200 pre-auth\001
4 0 0 50 -1 0 12 0.0000 4 180 810 375 4425 ethertypes\001
4 0 0 50 -1 0 12 0.0000 4 135 1050 375 4650 from/to kernel\001
4 0 0 50 -1 0 12 0.0000 4 135 1920 3675 1875 frontend control interface\001
-4 0 0 50 -1 2 14 0.0000 4 195 1425 1637 2371 wpa_supplicant\001
+4 0 0 50 -1 2 14 0.0000 4 210 1440 1637 2371 wpa_supplicant\001
diff --git a/contrib/wpa_supplicant/driver.h b/contrib/wpa_supplicant/driver.h
index da28014c9270..9864e9b8ae3c 100644
--- a/contrib/wpa_supplicant/driver.h
+++ b/contrib/wpa_supplicant/driver.h
@@ -1,13 +1,23 @@
+/*
+ * WPA Supplicant - driver interface definition
+ * Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
#ifndef DRIVER_H
#define DRIVER_H
#define WPA_SUPPLICANT_DRIVER_VERSION 2
-typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg;
-typedef enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP,
- CIPHER_WEP104 } wpa_cipher;
-typedef enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE,
- KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE } wpa_key_mgmt;
+#include "defs.h"
#define AUTH_ALG_OPEN_SYSTEM 0x01
#define AUTH_ALG_SHARED_KEY 0x02
@@ -16,7 +26,31 @@ typedef enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE,
#define IEEE80211_MODE_INFRA 0
#define IEEE80211_MODE_IBSS 1
+#define IEEE80211_CAP_ESS 0x0001
+#define IEEE80211_CAP_IBSS 0x0002
+#define IEEE80211_CAP_PRIVACY 0x0010
+
#define SSID_MAX_WPA_IE_LEN 40
+/**
+ * struct wpa_scan_result - Scan results
+ * @bssid: BSSID
+ * @ssid: SSID
+ * @ssid_len: length of the ssid
+ * @wpa_ie: WPA IE
+ * @wpa_ie_len: length of the wpa_ie
+ * @rsn_ie: RSN IE
+ * @rsn_ie_len: length of the RSN IE
+ * @freq: frequency of the channel in MHz (e.g., 2412 = channel 1)
+ * @caps: capability information field in host byte order
+ * @qual: signal quality
+ * @noise: noise level
+ * @level: signal level
+ * @maxrate: maximum supported rate
+ *
+ * This structure is used as a generic format for scan results from the
+ * driver. Each driver interface implementation is responsible for converting
+ * the driver or OS specific scan results into this format.
+ */
struct wpa_scan_result {
u8 bssid[ETH_ALEN];
u8 ssid[32];
@@ -25,40 +59,57 @@ struct wpa_scan_result {
size_t wpa_ie_len;
u8 rsn_ie[SSID_MAX_WPA_IE_LEN];
size_t rsn_ie_len;
- int freq; /* MHz */
- int caps; /* e.g. privacy */
- int qual; /* signal quality */
+ int freq;
+ u16 caps;
+ int qual;
int noise;
int level;
int maxrate;
};
-/* Parameters for associate driver_ops. */
+/**
+ * struct wpa_driver_associate_params - Association parameters
+ * Data for struct wpa_driver_ops::associate().
+ */
struct wpa_driver_associate_params {
- /* BSSID of the selected AP */
+ /**
+ * bssid - BSSID of the selected AP
+ * This can be %NULL, if ap_scan=2 mode is used and the driver is
+ * responsible for selecting with which BSS to associate. */
const u8 *bssid;
- /* The selected SSID and its length in bytes */
+ /**
+ * ssid - The selected SSID
+ */
const u8 *ssid;
size_t ssid_len;
- /* frequency that the selected AP is using (in MHz as
- * reported in the scan results) */
+ /**
+ * freq - Frequency of the channel the selected AP is using
+ * Frequency that the selected AP is using (in MHz as
+ * reported in the scan results)
+ */
int freq;
- /* WPA information element to be included in (Re)Association
+ /**
+ * wpa_ie - WPA information element for (Re)Association Request
+ * WPA information element to be included in (Re)Association
* Request (including information element id and length). Use
* of this WPA IE is optional. If the driver generates the WPA
- * IE, it can use @pairwise_suite, @group_suite, and
- * @key_mgmt_suite to select proper algorithms. In this case,
+ * IE, it can use pairwise_suite, group_suite, and
+ * key_mgmt_suite to select proper algorithms. In this case,
* the driver has to notify wpa_supplicant about the used WPA
* IE by generating an event that the interface code will
* convert into EVENT_ASSOCINFO data (see wpa_supplicant.h).
- * When using WPA2/IEEE 802.11i, @wpa_ie is used for RSN IE
+ * When using WPA2/IEEE 802.11i, wpa_ie is used for RSN IE
* instead. The driver can determine which version is used by
* looking at the first byte of the IE (0xdd for WPA, 0x30 for
- * WPA2/RSN). @wpa_ie_len: length of the @wpa_ie */
+ * WPA2/RSN).
+ */
const u8 *wpa_ie;
+ /**
+ * wpa_ie_len - length of the wpa_ie
+ */
size_t wpa_ie_len;
/* The selected pairwise/group cipher and key management
@@ -67,10 +118,21 @@ struct wpa_driver_associate_params {
wpa_cipher group_suite;
wpa_key_mgmt key_mgmt_suite;
- int auth_alg; /* bit field of AUTH_ALG_* */
- int mode; /* IEEE80211_MODE_* */
+ /**
+ * auth_alg - Allowed authentication algorithms
+ * Bit field of AUTH_ALG_*
+ */
+ int auth_alg;
+
+ /**
+ * mode - Operation mode (infra/ibss) IEEE80211_MODE_*
+ */
+ int mode;
};
+/**
+ * struct wpa_driver_capa - Driver capability information
+ */
struct wpa_driver_capa {
#define WPA_DRIVER_CAPA_KEY_MGMT_WPA 0x00000001
#define WPA_DRIVER_CAPA_KEY_MGMT_WPA2 0x00000002
@@ -97,33 +159,40 @@ struct wpa_driver_capa {
};
+/**
+ * struct wpa_driver_ops - Driver interface API definition
+ *
+ * This structure defines the API that each driver interface needs to implement
+ * for core wpa_supplicant code. All driver specific functionality is captured
+ * in this wrapper.
+ */
struct wpa_driver_ops {
- /* name of the driver interface */
+ /** Name of the driver interface */
const char *name;
- /* one line description of the driver interface */
+ /** One line description of the driver interface */
const char *desc;
/**
- * get_bssid - get the current BSSID
+ * get_bssid - Get the current BSSID
* @priv: private driver interface data
* @bssid: buffer for BSSID (ETH_ALEN = 6 bytes)
*
* Returns: 0 on success, -1 on failure
*
- * Query kernel driver for the current BSSID and copy it to @bssid.
- * Setting @bssid to 00:00:00:00:00:00 is recommended if the STA is not
+ * Query kernel driver for the current BSSID and copy it to bssid.
+ * Setting bssid to 00:00:00:00:00:00 is recommended if the STA is not
* associated.
*/
int (*get_bssid)(void *priv, u8 *bssid);
/**
- * get_ssid - get the current SSID
+ * get_ssid - Get the current SSID
* @priv: private driver interface data
* @ssid: buffer for SSID (at least 32 bytes)
*
- * Returns: length of the SSID on success, -1 on failure
+ * Returns: Length of the SSID on success, -1 on failure
*
- * Query kernel driver for the current SSID and copy it to @ssid.
+ * Query kernel driver for the current SSID and copy it to ssid.
* Returning zero is recommended if the STA is not associated.
*
* Note: SSID is an array of octets, i.e., it is not nul terminated and
@@ -134,35 +203,44 @@ struct wpa_driver_ops {
int (*get_ssid)(void *priv, u8 *ssid);
/**
- * set_wpa - enable/disable WPA support
+ * set_wpa - Enable/disable WPA support (OBSOLETE)
* @priv: private driver interface data
* @enabled: 1 = enable, 0 = disable
*
* Returns: 0 on success, -1 on failure
*
+ * Note: This function is included for backwards compatibility. This is
+ * called only just after init and just before deinit, so these
+ * functions can be used to implement same functionality and the driver
+ * interface need not define this function.
+ *
* Configure the kernel driver to enable/disable WPA support. This may
* be empty function, if WPA support is always enabled. Common
* configuration items are WPA IE (clearing it when WPA support is
- * disabled), Privacy flag for capability field, roaming mode (need to
- * allow wpa_supplicant to control roaming).
+ * disabled), Privacy flag configuration for capability field (note:
+ * this the value need to set in associate handler to allow plaintext
+ * mode to be used) when trying to associate with, roaming mode (can
+ * allow wpa_supplicant to control roaming if ap_scan=1 is used;
+ * however, drivers can also implement roaming if desired, especially
+ * ap_scan=2 mode is used for this).
*/
int (*set_wpa)(void *priv, int enabled);
/**
- * set_key - configure encryption key
+ * set_key - Configure encryption key
* @priv: private driver interface data
* @alg: encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP,
* %WPA_ALG_TKIP, %WPA_ALG_CCMP); %WPA_ALG_NONE clears the key.
* @addr: address of the peer STA or ff:ff:ff:ff:ff:ff for
* broadcast/default keys
- * @key_idx: key index (0..3), always 0 for unicast keys
+ * @key_idx: key index (0..3), usually 0 for unicast keys
* @set_tx: configure this key as the default Tx key (only used when
* driver does not support separate unicast/individual key
- * @seq: sequence number/packet number, @seq_len octets, the next
+ * @seq: sequence number/packet number, seq_len octets, the next
* packet number to be used for in replay protection; configured
* for Rx keys (in most cases, this is only used with broadcast
* keys and set to zero for unicast keys)
- * @seq_len: length of the @seq, depends on the algorithm:
+ * @seq_len: length of the seq, depends on the algorithm:
* TKIP: 6 octets, CCMP: 6 octets
* @key: key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key,
* 8-byte Rx Mic Key
@@ -173,25 +251,33 @@ struct wpa_driver_ops {
*
* Configure the given key for the kernel driver. If the driver
* supports separate individual keys (4 default keys + 1 individual),
- * @addr can be used to determine whether the key is default or
+ * addr can be used to determine whether the key is default or
* individual. If only 4 keys are supported, the default key with key
* index 0 is used as the individual key. STA must be configured to use
- * it as the default Tx key (@set_tx is set) and accept Rx for all the
+ * it as the default Tx key (set_tx is set) and accept Rx for all the
* key indexes. In most cases, WPA uses only key indexes 1 and 2 for
* broadcast keys, so key index 0 is available for this kind of
* configuration.
+ *
+ * Please note that TKIP keys include separate TX and RX MIC keys and
+ * some drivers may expect them in different order than wpa_supplicant
+ * is using. If the TX/RX keys are swapped, all TKIP encrypted packets
+ * will tricker Michael MIC errors. This can be fixed by changing the
+ * order of MIC keys by swapping te bytes 16..23 and 24..31 of the key
+ * in driver_*.c set_key() implementation, see driver_ndis.c for an
+ * example on how this can be done.
*/
int (*set_key)(void *priv, 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);
/**
- * init - initialize driver interface
+ * init - Initialize driver interface
* @ctx: context to be used when calling wpa_supplicant functions,
* e.g., wpa_supplicant_event()
* @ifname: interface name, e.g., wlan0
*
- * Return: pointer to private data, %NULL on failure
+ * Returns: Pointer to private data, %NULL on failure
*
* Initialize driver interface, including event processing for kernel
* driver events (e.g., associated, scan results, Michael MIC failure).
@@ -211,9 +297,8 @@ struct wpa_driver_ops {
void * (*init)(void *ctx, const char *ifname);
/**
- * deinit - deinitialize driver interface
- * @priv: pointer to private data (from matching
- * wpa_driver_events_init())
+ * deinit - Deinitialize driver interface
+ * @priv: private driver interface data from init()
*
* Shut down driver interface and processing of driver events. Free
* private data buffer if one was allocated in init() handler.
@@ -221,11 +306,23 @@ struct wpa_driver_ops {
void (*deinit)(void *priv);
/**
- * set_countermeasures - enable/disable TKIP countermeasures
+ * set_param - Set driver configuration parameters
+ * @priv: private driver interface data from init()
+ * @param: driver specific configuration parameters
+ *
+ * Returns: 0 on success, -1 on failure
+ *
+ * Optional handler for notifying driver interface about configuration
+ * parameters (driver_param).
+ */
+ int (*set_param)(void *priv, const char *param);
+
+ /**
+ * set_countermeasures - Enable/disable TKIP countermeasures
* @priv: private driver interface data
* @enabled: 1 = countermeasures enabled, 0 = disabled
*
- * Return: 0 on success, -1 on failure
+ * Returns: 0 on success, -1 on failure
*
* Configure TKIP countermeasures. When these are enabled, the driver
* should drop all received and queued frames that are using TKIP.
@@ -233,11 +330,11 @@ struct wpa_driver_ops {
int (*set_countermeasures)(void *priv, int enabled);
/**
- * set_drop_unencrypted - enable/disable unencrypted frame filtering
+ * set_drop_unencrypted - Enable/disable unencrypted frame filtering
* @priv: private driver interface data
* @enabled: 1 = unencrypted Tx/Rx frames will be dropped, 0 = disabled
*
- * Return: 0 on success, -1 on failure
+ * Returns: 0 on success, -1 on failure
*
* Configure the driver to drop all non-EAPOL frames (both receive and
* transmit paths). Unencrypted EAPOL frames (ethertype 0x888e) must
@@ -246,14 +343,14 @@ struct wpa_driver_ops {
int (*set_drop_unencrypted)(void *priv, int enabled);
/**
- * scan - request the driver to initiate scan
+ * scan - Request the driver to initiate scan
* @priv: private driver interface data
* @ssid: specific SSID to scan for (ProbeReq) or %NULL to scan for
* all SSIDs (either active scan with broadcast SSID or passive
* scan
* @ssid_len: length of the SSID
*
- * Return: 0 on success, -1 on failure
+ * Returns: 0 on success, -1 on failure
*
* Once the scan results are ready, the driver should report scan
* results event for wpa_supplicant which will eventually request the
@@ -262,14 +359,15 @@ struct wpa_driver_ops {
int (*scan)(void *priv, const u8 *ssid, size_t ssid_len);
/**
- * get_scan_results - fetch the latest scan results
+ * get_scan_results - Fetch the latest scan results
* @priv: private driver interface data
* @results: pointer to buffer for scan results
* @max_size: maximum number of entries (buffer size)
*
- * Return: number of scan result entries used on success, -1 on failure
+ * Returns: Number of scan result entries used on success, -1 on
+ * failure
*
- * If scan results include more than @max_size BSSes, @max_size will be
+ * If scan results include more than max_size BSSes, max_size will be
* returned and the remaining entries will not be included in the
* buffer.
*/
@@ -278,39 +376,39 @@ struct wpa_driver_ops {
size_t max_size);
/**
- * deauthenticate - request driver to deauthenticate
+ * deauthenticate - Request driver to deauthenticate
* @priv: private driver interface data
* @addr: peer address (BSSID of the AP)
* @reason_code: 16-bit reason code to be sent in the deauthentication
* frame
*
- * Return: 0 on success, -1 on failure
+ * Returns: 0 on success, -1 on failure
*/
int (*deauthenticate)(void *priv, const u8 *addr, int reason_code);
/**
- * disassociate - request driver to disassociate
+ * disassociate - Request driver to disassociate
* @priv: private driver interface data
* @addr: peer address (BSSID of the AP)
* @reason_code: 16-bit reason code to be sent in the disassociation
* frame
*
- * Return: 0 on success, -1 on failure
+ * Returns: 0 on success, -1 on failure
*/
int (*disassociate)(void *priv, const u8 *addr, int reason_code);
/**
- * associate - request driver to associate
+ * associate - Request driver to associate
* @priv: private driver interface data
* @params: association parameters
*
- * Return: 0 on success, -1 on failure
+ * Returns: 0 on success, -1 on failure
*/
int (*associate)(void *priv,
struct wpa_driver_associate_params *params);
/**
- * set_auth_alg - set IEEE 802.11 authentication algorithm
+ * set_auth_alg - Set IEEE 802.11 authentication algorithm
* @priv: private driver interface data
* @auth_alg: bit field of AUTH_ALG_*
*
@@ -326,43 +424,43 @@ struct wpa_driver_ops {
* associate() params, so set_auth_alg may not be needed in case of
* most drivers.
*
- * Return: 0 on success, -1 on failure
+ * Returns: 0 on success, -1 on failure
*/
int (*set_auth_alg)(void *priv, int auth_alg);
/**
- * add_pmkid - add PMKSA cache entry to the driver
+ * add_pmkid - Add PMKSA cache entry to the driver
* @priv: private driver interface data
* @bssid: BSSID for the PMKSA cache entry
* @pmkid: PMKID for the PMKSA cache entry
*
- * Return: 0 on success, -1 on failure
+ * Returns: 0 on success, -1 on failure
*
* This function is called when a new PMK is received, as a result of
* either normal authentication or RSN pre-authentication.
*
- * If the driver generates RSN IE, i.e., it does not use @wpa_ie in
+ * If the driver generates RSN IE, i.e., it does not use wpa_ie in
* associate(), add_pmkid() can be used to add new PMKSA cache entries
- * in the driver. If the driver uses @wpa_ie from wpa_supplicant, this
+ * in the driver. If the driver uses wpa_ie from wpa_supplicant, this
* driver_ops function does not need to be implemented. Likewise, if
* the driver does not support WPA, this function is not needed.
*/
int (*add_pmkid)(void *priv, const u8 *bssid, const u8 *pmkid);
/**
- * remove_pmkid - remove PMKSA cache entry to the driver
+ * remove_pmkid - Remove PMKSA cache entry to the driver
* @priv: private driver interface data
* @bssid: BSSID for the PMKSA cache entry
* @pmkid: PMKID for the PMKSA cache entry
*
- * Return: 0 on success, -1 on failure
+ * Returns: 0 on success, -1 on failure
*
* This function is called when the supplicant drops a PMKSA cache
* entry for any reason.
*
- * If the driver generates RSN IE, i.e., it does not use @wpa_ie in
+ * If the driver generates RSN IE, i.e., it does not use wpa_ie in
* associate(), remove_pmkid() can be used to synchronize PMKSA caches
- * between the driver and wpa_supplicant. If the driver uses @wpa_ie
+ * between the driver and wpa_supplicant. If the driver uses wpa_ie
* from wpa_supplicant, this driver_ops function does not need to be
* implemented. Likewise, if the driver does not support WPA, this
* function is not needed.
@@ -370,17 +468,17 @@ struct wpa_driver_ops {
int (*remove_pmkid)(void *priv, const u8 *bssid, const u8 *pmkid);
/**
- * flush_pmkid - flush PMKSA cache
+ * flush_pmkid - Flush PMKSA cache
* @priv: private driver interface data
*
- * Return: 0 on success, -1 on failure
+ * Returns: 0 on success, -1 on failure
*
* This function is called when the supplicant drops all PMKSA cache
* entries for any reason.
*
- * If the driver generates RSN IE, i.e., it does not use @wpa_ie in
+ * If the driver generates RSN IE, i.e., it does not use wpa_ie in
* associate(), remove_pmkid() can be used to synchronize PMKSA caches
- * between the driver and wpa_supplicant. If the driver uses @wpa_ie
+ * between the driver and wpa_supplicant. If the driver uses wpa_ie
* from wpa_supplicant, this driver_ops function does not need to be
* implemented. Likewise, if the driver does not support WPA, this
* function is not needed.
@@ -388,17 +486,17 @@ struct wpa_driver_ops {
int (*flush_pmkid)(void *priv);
/**
- * flush_pmkid - flush PMKSA cache
+ * flush_pmkid - Flush PMKSA cache
* @priv: private driver interface data
*
- * Return: 0 on success, -1 on failure
+ * Returns: 0 on success, -1 on failure
*
* Get driver/firmware/hardware capabilities.
*/
int (*get_capa)(void *priv, struct wpa_driver_capa *capa);
/**
- * poll - poll driver for association information
+ * poll - Poll driver for association information
* @priv: private driver interface data
*
* This is an option callback that can be used when the driver does not
@@ -412,25 +510,50 @@ struct wpa_driver_ops {
void (*poll)(void *priv);
/**
- * get_ifname - get interface name
+ * get_ifname - Get interface name
+ * @priv: private driver interface data
+ *
+ * Returns: Pointer to the interface name. This can differ from the
+ * interface name used in init() call.
*
* This optional function can be used to allow the driver interface to
* replace the interface name with something else, e.g., based on an
* interface mapping from a more descriptive name.
- *
- * Returns a pointer to the interface name. This can differ from the
- * interface name used in init() call.
*/
const char * (*get_ifname)(void *priv);
/**
- * get_mac_addr - get own MAC address
+ * get_mac_addr - Get own MAC address
+ * @priv: private driver interface data
+ *
+ * Returns: Pointer to own MAC address or %NULL on failure
*
* This optional function can be used to get the own MAC address of the
* device from the driver interface code. This is only needed if the
* l2_packet implementation for the OS does not provide easy access to
* a MAC address. */
const u8 * (*get_mac_addr)(void *priv);
+
+ /**
+ * send_eapol - Optional function for sending EAPOL packets
+ * @priv: private driver interface data
+ * @dest: Destination MAC address
+ * @proto: Ethertype
+ * @data: EAPOL packet starting with IEEE 802.1X header
+ * @data_len: Size of the EAPOL packet
+ *
+ * Returns: 0 on success, -1 on failure
+ *
+ * This optional function can be used to override l2_packet operations
+ * with driver specific functionality. If this function pointer is set,
+ * l2_packet module is not used at all and the driver interface code is
+ * responsible for receiving and sending all EAPOL packets. The
+ * received EAPOL packets are sent to core code by calling
+ * wpa_supplicant_rx_eapol(). The driver interface is required to
+ * implement get_mac_addr() handler if send_eapol() is used.
+ */
+ int (*send_eapol)(void *priv, const u8 *dest, u16 proto,
+ const u8 *data, size_t data_len);
};
#endif /* DRIVER_H */
diff --git a/contrib/wpa_supplicant/driver_hostap.h b/contrib/wpa_supplicant/driver_hostap.h
new file mode 100644
index 000000000000..76791055bd31
--- /dev/null
+++ b/contrib/wpa_supplicant/driver_hostap.h
@@ -0,0 +1,153 @@
+/*
+ * WPA Supplicant - driver interaction with Linux Host AP driver
+ * Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef HOSTAP_DRIVER_H
+#define HOSTAP_DRIVER_H
+
+#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0)
+#define PRISM2_IOCTL_RESET (SIOCIWFIRSTPRIV + 6)
+#define PRISM2_IOCTL_HOSTAPD (SIOCDEVPRIVATE + 14)
+
+/* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes: */
+enum {
+ /* PRISM2_PARAM_PTYPE = 1, */ /* REMOVED 2003-10-22 */
+ PRISM2_PARAM_TXRATECTRL = 2,
+ PRISM2_PARAM_BEACON_INT = 3,
+ PRISM2_PARAM_PSEUDO_IBSS = 4,
+ PRISM2_PARAM_ALC = 5,
+ /* PRISM2_PARAM_TXPOWER = 6, */ /* REMOVED 2003-10-22 */
+ PRISM2_PARAM_DUMP = 7,
+ PRISM2_PARAM_OTHER_AP_POLICY = 8,
+ PRISM2_PARAM_AP_MAX_INACTIVITY = 9,
+ PRISM2_PARAM_AP_BRIDGE_PACKETS = 10,
+ PRISM2_PARAM_DTIM_PERIOD = 11,
+ PRISM2_PARAM_AP_NULLFUNC_ACK = 12,
+ PRISM2_PARAM_MAX_WDS = 13,
+ PRISM2_PARAM_AP_AUTOM_AP_WDS = 14,
+ PRISM2_PARAM_AP_AUTH_ALGS = 15,
+ PRISM2_PARAM_MONITOR_ALLOW_FCSERR = 16,
+ PRISM2_PARAM_HOST_ENCRYPT = 17,
+ PRISM2_PARAM_HOST_DECRYPT = 18,
+ PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX = 19,
+ PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX = 20,
+ PRISM2_PARAM_HOST_ROAMING = 21,
+ PRISM2_PARAM_BCRX_STA_KEY = 22,
+ PRISM2_PARAM_IEEE_802_1X = 23,
+ PRISM2_PARAM_ANTSEL_TX = 24,
+ PRISM2_PARAM_ANTSEL_RX = 25,
+ PRISM2_PARAM_MONITOR_TYPE = 26,
+ PRISM2_PARAM_WDS_TYPE = 27,
+ PRISM2_PARAM_HOSTSCAN = 28,
+ PRISM2_PARAM_AP_SCAN = 29,
+ PRISM2_PARAM_ENH_SEC = 30,
+ PRISM2_PARAM_IO_DEBUG = 31,
+ PRISM2_PARAM_BASIC_RATES = 32,
+ PRISM2_PARAM_OPER_RATES = 33,
+ PRISM2_PARAM_HOSTAPD = 34,
+ PRISM2_PARAM_HOSTAPD_STA = 35,
+ PRISM2_PARAM_WPA = 36,
+ PRISM2_PARAM_PRIVACY_INVOKED = 37,
+ PRISM2_PARAM_TKIP_COUNTERMEASURES = 38,
+ PRISM2_PARAM_DROP_UNENCRYPTED = 39,
+ PRISM2_PARAM_SCAN_CHANNEL_MASK = 40,
+};
+
+/* PRISM2_IOCTL_HOSTAPD ioctl() cmd: */
+enum {
+ PRISM2_HOSTAPD_FLUSH = 1,
+ PRISM2_HOSTAPD_ADD_STA = 2,
+ PRISM2_HOSTAPD_REMOVE_STA = 3,
+ PRISM2_HOSTAPD_GET_INFO_STA = 4,
+ /* REMOVED: PRISM2_HOSTAPD_RESET_TXEXC_STA = 5, */
+ PRISM2_SET_ENCRYPTION = 6,
+ PRISM2_GET_ENCRYPTION = 7,
+ PRISM2_HOSTAPD_SET_FLAGS_STA = 8,
+ PRISM2_HOSTAPD_GET_RID = 9,
+ PRISM2_HOSTAPD_SET_RID = 10,
+ PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR = 11,
+ PRISM2_HOSTAPD_SET_GENERIC_ELEMENT = 12,
+ PRISM2_HOSTAPD_MLME = 13,
+ PRISM2_HOSTAPD_SCAN_REQ = 14,
+ PRISM2_HOSTAPD_STA_CLEAR_STATS = 15,
+};
+
+#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024
+#define PRISM2_HOSTAPD_RID_HDR_LEN \
+((int) (&((struct prism2_hostapd_param *) 0)->u.rid.data))
+#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \
+((int) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data))
+
+/* Maximum length for algorithm names (-1 for nul termination) used in ioctl()
+ */
+#define HOSTAP_CRYPT_ALG_NAME_LEN 16
+
+
+struct prism2_hostapd_param {
+ u32 cmd;
+ u8 sta_addr[ETH_ALEN];
+ union {
+ struct {
+ u16 aid;
+ u16 capability;
+ u8 tx_supp_rates;
+ } add_sta;
+ struct {
+ u32 inactive_sec;
+ } get_info_sta;
+ struct {
+ u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN];
+ u32 flags;
+ u32 err;
+ u8 idx;
+ u8 seq[8]; /* sequence counter (set: RX, get: TX) */
+ u16 key_len;
+ u8 key[0];
+ } crypt;
+ struct {
+ u32 flags_and;
+ u32 flags_or;
+ } set_flags_sta;
+ struct {
+ u16 rid;
+ u16 len;
+ u8 data[0];
+ } rid;
+ struct {
+ u8 len;
+ u8 data[0];
+ } generic_elem;
+ struct {
+#define MLME_STA_DEAUTH 0
+#define MLME_STA_DISASSOC 1
+ u16 cmd;
+ u16 reason_code;
+ } mlme;
+ struct {
+ u8 ssid_len;
+ u8 ssid[32];
+ } scan_req;
+ } u;
+};
+
+#define HOSTAP_CRYPT_FLAG_SET_TX_KEY 0x01
+#define HOSTAP_CRYPT_FLAG_PERMANENT 0x02
+
+#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2
+#define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3
+#define HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED 4
+#define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5
+#define HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED 6
+#define HOSTAP_CRYPT_ERR_CARD_CONF_FAILED 7
+
+#endif /* HOSTAP_DRIVER_H */
diff --git a/contrib/wpa_supplicant/driver_ndis.c b/contrib/wpa_supplicant/driver_ndis.c
index 1dba95adcc18..5ad2a31b0198 100644
--- a/contrib/wpa_supplicant/driver_ndis.c
+++ b/contrib/wpa_supplicant/driver_ndis.c
@@ -393,6 +393,20 @@ static int wpa_driver_ndis_get_bssid(void *priv, u8 *bssid)
{
struct wpa_driver_ndis_data *drv = priv;
+ if (drv->wired) {
+ /*
+ * Report PAE group address as the "BSSID" for wired
+ * connection.
+ */
+ bssid[0] = 0x01;
+ bssid[1] = 0x80;
+ bssid[2] = 0xc2;
+ bssid[3] = 0x00;
+ bssid[4] = 0x00;
+ bssid[5] = 0x03;
+ return 0;
+ }
+
return ndis_get_oid(drv, OID_802_11_BSSID, bssid, ETH_ALEN) < 0 ?
-1 : 0;
}
@@ -406,8 +420,13 @@ static int wpa_driver_ndis_get_ssid(void *priv, u8 *ssid)
int res;
res = ndis_get_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf));
- if (!res) {
+ if (res < 4) {
wpa_printf(MSG_DEBUG, "NDIS: Failed to get SSID");
+ if (drv->wired) {
+ wpa_printf(MSG_DEBUG, "NDIS: Allow get_ssid failure "
+ "with a wired interface");
+ return 0;
+ }
return -1;
}
memcpy(ssid, buf.Ssid, buf.SsidLength);
@@ -423,6 +442,12 @@ static int wpa_driver_ndis_set_ssid(struct wpa_driver_ndis_data *drv,
memset(&buf, 0, sizeof(buf));
buf.SsidLength = ssid_len;
memcpy(buf.Ssid, ssid, ssid_len);
+ /*
+ * Make sure radio is marked enabled here so that scan request will not
+ * force SSID to be changed to a random one in order to enable radio at
+ * that point.
+ */
+ drv->radio_enabled = 1;
return ndis_set_oid(drv, OID_802_11_SSID, (char *) &buf, sizeof(buf));
}
@@ -562,7 +587,7 @@ static int wpa_driver_ndis_get_scan_results(void *priv,
memcpy(results[i].ssid, bss->Ssid.Ssid, bss->Ssid.SsidLength);
results[i].ssid_len = bss->Ssid.SsidLength;
if (bss->Privacy)
- results[i].caps = 1; /* FIX? */
+ results[i].caps |= IEEE80211_CAP_PRIVACY;
results[i].level = (int) bss->Rssi;
results[i].freq = bss->Configuration.DSConfig / 1000;
for (j = 0; j < sizeof(bss->SupportedRates); j++) {
@@ -574,6 +599,8 @@ static int wpa_driver_ndis_get_scan_results(void *priv,
}
wpa_driver_ndis_get_ies(&results[i], bss->IEs, bss->IELength);
pos += bss->Length;
+ if (pos > (char *) b + blen)
+ break;
}
free(b);
@@ -928,10 +955,12 @@ static int wpa_driver_ndis_flush_pmkid(void *priv)
static int wpa_driver_ndis_get_associnfo(struct wpa_driver_ndis_data *drv)
{
- char buf[512];
+ char buf[512], *pos;
NDIS_802_11_ASSOCIATION_INFORMATION *ai;
- int len;
+ int len, i;
union wpa_event_data data;
+ NDIS_802_11_BSSID_LIST_EX *b;
+ size_t blen;
len = ndis_get_oid(drv, OID_802_11_ASSOCIATION_INFORMATION, buf,
sizeof(buf));
@@ -990,8 +1019,47 @@ static int wpa_driver_ndis_get_associnfo(struct wpa_driver_ndis_data *drv)
data.assoc_info.req_ies_len = ai->RequestIELength;
data.assoc_info.resp_ies = buf + ai->OffsetResponseIEs;
data.assoc_info.resp_ies_len = ai->ResponseIELength;
+
+ blen = 65535;
+ b = malloc(blen);
+ if (b == NULL)
+ goto skip_scan_results;
+ memset(b, 0, blen);
+ len = ndis_get_oid(drv, OID_802_11_BSSID_LIST, (char *) b, blen);
+ if (len < 0) {
+ wpa_printf(MSG_DEBUG, "NDIS: failed to get scan results");
+ free(b);
+ b = NULL;
+ goto skip_scan_results;
+ }
+ wpa_printf(MSG_DEBUG, "NDIS: %d BSSID items to process for AssocInfo",
+ (unsigned int) b->NumberOfItems);
+
+ pos = (char *) &b->Bssid[0];
+ for (i = 0; i < b->NumberOfItems; i++) {
+ NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos;
+ if (memcmp(drv->bssid, bss->MacAddress, ETH_ALEN) == 0 &&
+ bss->IELength > sizeof(NDIS_802_11_FIXED_IEs)) {
+ data.assoc_info.beacon_ies =
+ ((u8 *) bss->IEs) +
+ sizeof(NDIS_802_11_FIXED_IEs);
+ data.assoc_info.beacon_ies_len =
+ bss->IELength - sizeof(NDIS_802_11_FIXED_IEs);
+ wpa_hexdump(MSG_MSGDUMP, "NDIS: Beacon IEs",
+ data.assoc_info.beacon_ies,
+ data.assoc_info.beacon_ies_len);
+ break;
+ }
+ pos += bss->Length;
+ if (pos > (char *) b + blen)
+ break;
+ }
+
+skip_scan_results:
wpa_supplicant_event(drv->ctx, EVENT_ASSOCINFO, &data);
+ free(b);
+
return 0;
}
@@ -1001,6 +1069,9 @@ static void wpa_driver_ndis_poll_timeout(void *eloop_ctx, void *timeout_ctx)
struct wpa_driver_ndis_data *drv = eloop_ctx;
u8 bssid[ETH_ALEN];
+ if (drv->wired)
+ return;
+
if (wpa_driver_ndis_get_bssid(drv, bssid)) {
/* Disconnected */
if (memcmp(drv->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN)
@@ -1339,39 +1410,63 @@ static const u8 * wpa_driver_ndis_get_mac_addr(void *priv)
static int wpa_driver_ndis_get_names(struct wpa_driver_ndis_data *drv)
{
- PTSTR names, pos;
+ PTSTR names, pos, pos2;
ULONG len;
BOOLEAN res;
- const int MAX_ADAPTERS = 16;
+ const int MAX_ADAPTERS = 32;
char *name[MAX_ADAPTERS];
char *desc[MAX_ADAPTERS];
int num_name, num_desc, i, found_name, found_desc;
size_t dlen;
- len = 1024;
+ wpa_printf(MSG_DEBUG, "NDIS: Packet.dll version: %s",
+ PacketGetVersion());
+
+ len = 8192;
names = malloc(len);
if (names == NULL)
return -1;
memset(names, 0, len);
res = PacketGetAdapterNames(names, &len);
- if (!res && len > 1024) {
+ if (!res && len > 8192) {
free(names);
names = malloc(len);
if (names == NULL)
return -1;
memset(names, 0, len);
res = PacketGetAdapterNames(names, &len);
- if (!res) {
- free(names);
- return -1;
- }
+ }
+
+ if (!res) {
+ wpa_printf(MSG_ERROR, "NDIS: Failed to get adapter list "
+ "(PacketGetAdapterNames)");
+ free(names);
+ return -1;
}
/* wpa_hexdump_ascii(MSG_DEBUG, "NDIS: AdapterNames", names, len); */
+ if (names[0] && names[1] == '\0' && names[2] && names[3] == '\0') {
+ wpa_printf(MSG_DEBUG, "NDIS: Looks like adapter names are in "
+ "UNICODE");
+ /* Convert to ASCII */
+ pos2 = pos = names;
+ while (pos2 < names + len) {
+ if (pos2[0] == '\0' && pos2[1] == '\0' &&
+ pos2[2] == '\0' && pos2[3] == '\0') {
+ pos2 += 4;
+ break;
+ }
+ *pos++ = pos2[0];
+ pos2 += 2;
+ }
+ memcpy(pos + 2, names, pos - names);
+ pos += 2;
+ } else
+ pos = names;
+
num_name = 0;
- pos = names;
while (pos < names + len) {
name[num_name] = pos;
while (*pos && pos < names + len)
@@ -1420,6 +1515,13 @@ static int wpa_driver_ndis_get_names(struct wpa_driver_ndis_data *drv)
}
}
+ /*
+ * Windows 98 with Packet.dll 3.0 alpha3 does not include adapter
+ * descriptions. Fill in dummy descriptors to work around this.
+ */
+ while (num_desc < num_name)
+ desc[num_desc++] = "dummy description";
+
if (num_name != num_desc) {
wpa_printf(MSG_DEBUG, "NDIS: mismatch in adapter name and "
"description counts (%d != %d)",
@@ -1537,6 +1639,13 @@ static void * wpa_driver_ndis_init(void *ctx, const char *ifname)
"OID_802_11_INFRASTRUCTURE_MODE (%d)",
(int) mode);
/* Try to continue anyway */
+
+ if (!drv->has_capability && drv->capa.enc == 0) {
+ wpa_printf(MSG_DEBUG, "NDIS: Driver did not provide "
+ "any wireless capabilities - assume it is "
+ "a wired interface");
+ drv->wired = 1;
+ }
}
return drv;
@@ -1565,7 +1674,7 @@ static void wpa_driver_ndis_deinit(void *priv)
}
-struct wpa_driver_ops wpa_driver_ndis_ops = {
+const struct wpa_driver_ops wpa_driver_ndis_ops = {
.name = "ndis",
.desc = "Windows NDIS driver",
.init = wpa_driver_ndis_init,
diff --git a/contrib/wpa_supplicant/driver_ndis.h b/contrib/wpa_supplicant/driver_ndis.h
index a79afcbfcf2d..7906fdc5b04e 100644
--- a/contrib/wpa_supplicant/driver_ndis.h
+++ b/contrib/wpa_supplicant/driver_ndis.h
@@ -1,3 +1,17 @@
+/*
+ * WPA Supplicant - Windows/NDIS driver interface
+ * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
#ifndef DRIVER_NDIS_H
#define DRIVER_NDIS_H
@@ -21,6 +35,7 @@ struct wpa_driver_ndis_data {
struct ndis_pmkid_entry *pmkid;
int event_sock;
char *adapter_desc;
+ int wired;
};
#endif /* DRIVER_NDIS_H */
diff --git a/contrib/wpa_supplicant/driver_wired.c b/contrib/wpa_supplicant/driver_wired.c
new file mode 100644
index 000000000000..359a21b481bd
--- /dev/null
+++ b/contrib/wpa_supplicant/driver_wired.c
@@ -0,0 +1,271 @@
+/*
+ * WPA Supplicant - wired Ethernet driver interface
+ * Copyright (c) 2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netpacket/packet.h>
+#include <net/if.h>
+
+#include "common.h"
+#include "driver.h"
+#include "wpa_supplicant.h"
+
+
+static const u8 pae_group_addr[ETH_ALEN] =
+{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
+
+
+struct wpa_driver_wired_data {
+ void *ctx;
+ int pf_sock;
+ char ifname[IFNAMSIZ + 1];
+ int membership, multi, iff_allmulti, iff_up;
+};
+
+
+static int wpa_driver_wired_set_wpa(void *priv, int enabled)
+{
+ return 0;
+}
+
+
+static int wpa_driver_wired_get_ssid(void *priv, u8 *ssid)
+{
+ ssid[0] = 0;
+ return 0;
+}
+
+
+static int wpa_driver_wired_get_bssid(void *priv, u8 *bssid)
+{
+ /* Report PAE group address as the "BSSID" for wired connection. */
+ memcpy(bssid, pae_group_addr, ETH_ALEN);
+ return 0;
+}
+
+
+static int wpa_driver_wired_get_ifflags(const char *ifname, int *flags)
+{
+ struct ifreq ifr;
+ int s;
+
+ s = socket(PF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ perror("socket");
+ return -1;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+ if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
+ perror("ioctl[SIOCGIFFLAGS]");
+ close(s);
+ return -1;
+ }
+ close(s);
+ *flags = ifr.ifr_flags & 0xffff;
+ return 0;
+}
+
+
+static int wpa_driver_wired_set_ifflags(const char *ifname, int flags)
+{
+ struct ifreq ifr;
+ int s;
+
+ s = socket(PF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ perror("socket");
+ return -1;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+ ifr.ifr_flags = flags & 0xffff;
+ if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
+ perror("ioctl[SIOCSIFFLAGS]");
+ close(s);
+ return -1;
+ }
+ close(s);
+ return 0;
+}
+
+
+static int wpa_driver_wired_multi(const char *ifname, const u8 *addr, int add)
+{
+ struct ifreq ifr;
+ int s;
+
+ s = socket(PF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ perror("socket");
+ return -1;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+ ifr.ifr_hwaddr.sa_family = AF_UNSPEC;
+ memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN);
+
+ if (ioctl(s, add ? SIOCADDMULTI : SIOCDELMULTI, (caddr_t) &ifr) < 0) {
+ perror("ioctl[SIOC{ADD/DEL}MULTI]");
+ close(s);
+ return -1;
+ }
+ close(s);
+ return 0;
+}
+
+
+static int wpa_driver_wired_membership(struct wpa_driver_wired_data *drv,
+ const u8 *addr, int add)
+{
+#ifdef __linux__
+ struct packet_mreq mreq;
+
+ if (drv->pf_sock == -1)
+ return -1;
+
+ memset(&mreq, 0, sizeof(mreq));
+ mreq.mr_ifindex = if_nametoindex(drv->ifname);
+ mreq.mr_type = PACKET_MR_MULTICAST;
+ mreq.mr_alen = ETH_ALEN;
+ memcpy(mreq.mr_address, addr, ETH_ALEN);
+
+ if (setsockopt(drv->pf_sock, SOL_PACKET,
+ add ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP,
+ &mreq, sizeof(mreq)) < 0) {
+ perror("setsockopt");
+ return -1;
+ }
+ return 0;
+#else /* __linux__ */
+ return -1;
+#endif /* __linux__ */
+}
+
+
+static void * wpa_driver_wired_init(void *ctx, const char *ifname)
+{
+ struct wpa_driver_wired_data *drv;
+ int flags;
+
+ drv = malloc(sizeof(*drv));
+ if (drv == NULL)
+ return NULL;
+ memset(drv, 0, sizeof(*drv));
+ strncpy(drv->ifname, ifname, sizeof(drv->ifname));
+ drv->ctx = ctx;
+
+#ifdef __linux__
+ drv->pf_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
+ if (drv->pf_sock < 0)
+ perror("socket(PF_PACKET)");
+#else
+ drv->pf_sock = -1;
+#endif
+
+ if (wpa_driver_wired_get_ifflags(ifname, &flags) == 0 &&
+ !(flags & IFF_UP) &&
+ wpa_driver_wired_set_ifflags(ifname, flags | IFF_UP) == 0) {
+ drv->iff_up = 1;
+ }
+
+ if (wpa_driver_wired_membership(drv, pae_group_addr, 1) == 0) {
+ wpa_printf(MSG_DEBUG, "%s: Added multicast membership with "
+ "packet socket", __func__);
+ drv->membership = 1;
+ } else if (wpa_driver_wired_multi(ifname, pae_group_addr, 1) == 0) {
+ wpa_printf(MSG_DEBUG, "%s: Added multicast membership with "
+ "SIOCADDMULTI", __func__);
+ drv->multi = 1;
+ } else if (wpa_driver_wired_get_ifflags(ifname, &flags) < 0) {
+ wpa_printf(MSG_INFO, "%s: Could not get interface "
+ "flags", __func__);
+ free(drv);
+ return NULL;
+ } else if (flags & IFF_ALLMULTI) {
+ wpa_printf(MSG_DEBUG, "%s: Interface is already configured "
+ "for multicast", __func__);
+ } else if (wpa_driver_wired_set_ifflags(ifname,
+ flags | IFF_ALLMULTI) < 0) {
+ wpa_printf(MSG_INFO, "%s: Failed to enable allmulti",
+ __func__);
+ free(drv);
+ return NULL;
+ } else {
+ wpa_printf(MSG_DEBUG, "%s: Enabled allmulti mode",
+ __func__);
+ drv->iff_allmulti = 1;
+ }
+
+ return drv;
+}
+
+
+static void wpa_driver_wired_deinit(void *priv)
+{
+ struct wpa_driver_wired_data *drv = priv;
+ int flags;
+
+ if (drv->membership &&
+ wpa_driver_wired_membership(drv, pae_group_addr, 0) < 0) {
+ wpa_printf(MSG_DEBUG, "%s: Failed to remove PAE multicast "
+ "group (PACKET)", __func__);
+ }
+
+ if (drv->multi &&
+ wpa_driver_wired_multi(drv->ifname, pae_group_addr, 0) < 0) {
+ wpa_printf(MSG_DEBUG, "%s: Failed to remove PAE multicast "
+ "group (SIOCDELMULTI)", __func__);
+ }
+
+ if (drv->iff_allmulti &&
+ (wpa_driver_wired_get_ifflags(drv->ifname, &flags) < 0 ||
+ wpa_driver_wired_set_ifflags(drv->ifname,
+ flags & ~IFF_ALLMULTI) < 0)) {
+ wpa_printf(MSG_DEBUG, "%s: Failed to disable allmulti mode",
+ __func__);
+ }
+
+ if (drv->iff_up &&
+ wpa_driver_wired_get_ifflags(drv->ifname, &flags) == 0 &&
+ (flags & IFF_UP) &&
+ wpa_driver_wired_set_ifflags(drv->ifname, flags & ~IFF_UP) < 0) {
+ wpa_printf(MSG_DEBUG, "%s: Failed to set the interface down",
+ __func__);
+ }
+
+ if (drv->pf_sock != -1)
+ close(drv->pf_sock);
+
+ free(drv);
+}
+
+
+const struct wpa_driver_ops wpa_driver_wired_ops = {
+ .name = "wired",
+ .desc = "wpa_supplicant wired Ethernet driver",
+ .set_wpa = wpa_driver_wired_set_wpa,
+ .get_ssid = wpa_driver_wired_get_ssid,
+ .get_bssid = wpa_driver_wired_get_bssid,
+ .init = wpa_driver_wired_init,
+ .deinit = wpa_driver_wired_deinit,
+};
diff --git a/contrib/wpa_supplicant/drivers.c b/contrib/wpa_supplicant/drivers.c
index cb016ba803e5..4fd0509129a5 100644
--- a/contrib/wpa_supplicant/drivers.c
+++ b/contrib/wpa_supplicant/drivers.c
@@ -1,6 +1,6 @@
/*
* WPA Supplicant / driver interface list
- * Copyright (c) 2004, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -49,6 +49,9 @@ extern struct wpa_driver_ops wpa_driver_bsd_ops; /* driver_bsd.c */
#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_TEST
extern struct wpa_driver_ops wpa_driver_test_ops; /* driver_test.c */
#endif /* CONFIG_DRIVER_TEST */
@@ -89,6 +92,9 @@ struct wpa_driver_ops *wpa_supplicant_drivers[] =
#ifdef CONFIG_DRIVER_NDIS
&wpa_driver_ndis_ops,
#endif /* CONFIG_DRIVER_NDIS */
+#ifdef CONFIG_DRIVER_WIRED
+ &wpa_driver_wired_ops,
+#endif /* CONFIG_DRIVER_WIRED */
#ifdef CONFIG_DRIVER_TEST
&wpa_driver_test_ops,
#endif /* CONFIG_DRIVER_TEST */
diff --git a/contrib/wpa_supplicant/eap.c b/contrib/wpa_supplicant/eap.c
index 267907c27fe0..5d81870271bd 100644
--- a/contrib/wpa_supplicant/eap.c
+++ b/contrib/wpa_supplicant/eap.c
@@ -1,5 +1,5 @@
/*
- * WPA Supplicant / EAP state machines
+ * WPA Supplicant / EAP state machines (RFC 4137)
* Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
*
* This program is free software; you can redistribute it and/or modify
@@ -15,13 +15,16 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <ctype.h>
#include "common.h"
#include "eap_i.h"
#include "wpa_supplicant.h"
#include "config_ssid.h"
#include "tls.h"
-#include "md5.h"
+#include "crypto.h"
+#include "pcsc_funcs.h"
+#include "wpa_ctrl.h"
#define EAP_MAX_AUTH_ROUNDS 50
@@ -63,6 +66,9 @@ extern const struct eap_method eap_method_aka;
#ifdef EAP_FAST
extern const struct eap_method eap_method_fast;
#endif
+#ifdef EAP_PAX
+extern const struct eap_method eap_method_pax;
+#endif
static const struct eap_method *eap_methods[] =
{
@@ -102,10 +108,18 @@ static const struct eap_method *eap_methods[] =
#ifdef EAP_FAST
&eap_method_fast,
#endif
+#ifdef EAP_PAX
+ &eap_method_pax,
+#endif
};
#define NUM_EAP_METHODS (sizeof(eap_methods) / sizeof(eap_methods[0]))
+/**
+ * eap_sm_get_eap_methods - Get EAP method based on type number
+ * @method: EAP type number
+ * Returns: Pointer to EAP method of %NULL if not found
+ */
const struct eap_method * eap_sm_get_eap_methods(int method)
{
int i;
@@ -119,10 +133,11 @@ const struct eap_method * eap_sm_get_eap_methods(int method)
static Boolean eap_sm_allowMethod(struct eap_sm *sm, EapType method);
static u8 * eap_sm_buildNak(struct eap_sm *sm, int id, size_t *len);
-static void eap_sm_processIdentity(struct eap_sm *sm, u8 *req, size_t len);
-static void eap_sm_processNotify(struct eap_sm *sm, u8 *req, size_t len);
+static void eap_sm_processIdentity(struct eap_sm *sm, const u8 *req,
+ size_t len);
+static void eap_sm_processNotify(struct eap_sm *sm, const u8 *req, size_t len);
static u8 * eap_sm_buildNotify(struct eap_sm *sm, int id, size_t *len);
-static void eap_sm_parseEapReq(struct eap_sm *sm, u8 *req, size_t len);
+static void eap_sm_parseEapReq(struct eap_sm *sm, const u8 *req, size_t len);
static const char * eap_sm_method_state_txt(int state);
static const char * eap_sm_decision_txt(int decision);
@@ -219,12 +234,14 @@ SM_STATE(EAP, INITIALIZE)
eapol_set_bool(sm, EAPOL_eapRestart, FALSE);
sm->lastId = -1; /* new session - make sure this does not match with
* the first EAP-Packet */
- /* draft-ietf-eap-statemachine-02.pdf does not reset eapResp and
- * eapNoResp here. However, this seemed to be able to trigger cases
- * where both were set and if EAPOL state machine uses eapNoResp first,
- * it may end up not sending a real reply correctly. This occurred
- * when the workaround in FAIL state set eapNoResp = TRUE.. Maybe that
- * workaround needs to be fixed to do something else(?) */
+ /*
+ * RFC 4137 does not reset eapResp and eapNoResp here. However, this
+ * seemed to be able to trigger cases where both were set and if EAPOL
+ * state machine uses eapNoResp first, it may end up not sending a real
+ * reply correctly. This occurred when the workaround in FAIL state set
+ * eapNoResp = TRUE.. Maybe that workaround needs to be fixed to do
+ * something else(?)
+ */
eapol_set_bool(sm, EAPOL_eapResp, FALSE);
eapol_set_bool(sm, EAPOL_eapNoResp, FALSE);
sm->num_rounds = 0;
@@ -246,7 +263,7 @@ SM_STATE(EAP, IDLE)
SM_STATE(EAP, RECEIVED)
{
- u8 *eapReqData;
+ const u8 *eapReqData;
size_t eapReqDataLen;
SM_ENTRY(EAP, RECEIVED);
@@ -284,14 +301,35 @@ SM_STATE(EAP, GET_METHOD)
else
sm->eap_method_priv = sm->m->init(sm);
if (sm->eap_method_priv == NULL) {
- wpa_printf(MSG_DEBUG, "EAP: Failed to "
- "initialize EAP method %d",
- sm->selectedMethod);
+ struct wpa_ssid *config = eap_get_config(sm);
+ wpa_msg(sm->msg_ctx, MSG_INFO,
+ "EAP: Failed to initialize EAP method "
+ "%d (%s)",
+ sm->selectedMethod, sm->m->name);
sm->m = NULL;
sm->methodState = METHOD_NONE;
sm->selectedMethod = EAP_TYPE_NONE;
+ if (sm->reqMethod == EAP_TYPE_TLS &&
+ config &&
+ (config->pending_req_pin ||
+ config->pending_req_passphrase)) {
+ /*
+ * Return without generating Nak in
+ * order to allow entering of PIN code
+ * or passphrase to retry the current
+ * EAP packet.
+ */
+ wpa_printf(MSG_DEBUG, "EAP: Pending "
+ "PIN/passphrase request - "
+ "skip Nak");
+ return;
+ }
} else {
sm->methodState = METHOD_INIT;
+ wpa_msg(sm->msg_ctx, MSG_INFO,
+ WPA_EVENT_EAP_METHOD
+ "EAP method %d (%s) selected",
+ sm->selectedMethod, sm->m->name);
return;
}
}
@@ -381,7 +419,7 @@ SM_STATE(EAP, DISCARD)
SM_STATE(EAP, IDENTITY)
{
- u8 *eapReqData;
+ const u8 *eapReqData;
size_t eapReqDataLen;
SM_ENTRY(EAP, IDENTITY);
@@ -395,7 +433,7 @@ SM_STATE(EAP, IDENTITY)
SM_STATE(EAP, NOTIFICATION)
{
- u8 *eapReqData;
+ const u8 *eapReqData;
size_t eapReqDataLen;
SM_ENTRY(EAP, NOTIFICATION);
@@ -429,15 +467,24 @@ SM_STATE(EAP, SUCCESS)
if (sm->eapKeyData != NULL)
sm->eapKeyAvailable = TRUE;
eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
- /* draft-ietf-eap-statemachine-02.pdf does not clear eapReq here, but
- * this seems to be required to avoid processing the same request
- * twice when state machine is initialized. */
+
+ /*
+ * RFC 4137 does not clear eapReq here, but this seems to be required
+ * to avoid processing the same request twice when state machine is
+ * initialized.
+ */
eapol_set_bool(sm, EAPOL_eapReq, FALSE);
- /* draft-ietf-eap-statemachine-02.pdf does not set eapNoResp here, but
- * this seems to be required to get EAPOL Supplicant backend state
- * machine into SUCCESS state. In addition, either eapResp or eapNoResp
- * is required to be set after processing the received EAP frame. */
+
+ /*
+ * RFC 4137 does not set eapNoResp here, but this seems to be required
+ * to get EAPOL Supplicant backend state machine into SUCCESS state. In
+ * addition, either eapResp or eapNoResp is required to be set after
+ * processing the received EAP frame.
+ */
eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
+
+ wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
+ "EAP authentication completed successfully");
}
@@ -445,14 +492,23 @@ SM_STATE(EAP, FAILURE)
{
SM_ENTRY(EAP, FAILURE);
eapol_set_bool(sm, EAPOL_eapFail, TRUE);
- /* draft-ietf-eap-statemachine-02.pdf does not clear eapReq here, but
- * this seems to be required to avoid processing the same request
- * twice when state machine is initialized. */
+
+ /*
+ * RFC 4137 does not clear eapReq here, but this seems to be required
+ * to avoid processing the same request twice when state machine is
+ * initialized.
+ */
eapol_set_bool(sm, EAPOL_eapReq, FALSE);
- /* draft-ietf-eap-statemachine-02.pdf does not set eapNoResp here.
- * However, either eapResp or eapNoResp is required to be set after
- * processing the received EAP frame. */
+
+ /*
+ * RFC 4137 does not set eapNoResp here. However, either eapResp or
+ * eapNoResp is required to be set after processing the received EAP
+ * frame.
+ */
eapol_set_bool(sm, EAPOL_eapNoResp, TRUE);
+
+ wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
+ "EAP authentication failed");
}
@@ -461,9 +517,8 @@ static int eap_success_workaround(struct eap_sm *sm, int reqId, int lastId)
/*
* At least Microsoft IAS and Meetinghouse Aegis seem to be sending
* EAP-Success/Failure with lastId + 1 even though RFC 3748 and
- * draft-ietf-eap-statemachine-05.pdf require that reqId == lastId.
- * In addition, it looks like Ringmaster v2.1.2.0 would be using
- * lastId + 2 in EAP-Success.
+ * RFC 4137 require that reqId == lastId. In addition, it looks like
+ * Ringmaster v2.1.2.0 would be using lastId + 2 in EAP-Success.
*
* Accept this kind of Id if EAP workarounds are enabled. These are
* unauthenticated plaintext messages, so this should have minimal
@@ -490,13 +545,13 @@ SM_STEP(EAP)
if (eapol_get_bool(sm, EAPOL_eapRestart) &&
eapol_get_bool(sm, EAPOL_portEnabled))
SM_ENTER_GLOBAL(EAP, INITIALIZE);
- else if (!eapol_get_bool(sm, EAPOL_portEnabled))
+ else if (!eapol_get_bool(sm, EAPOL_portEnabled) || sm->force_disabled)
SM_ENTER_GLOBAL(EAP, DISABLED);
else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) {
if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) {
- wpa_printf(MSG_DEBUG, "EAP: more than %d "
- "authentication rounds - abort",
- EAP_MAX_AUTH_ROUNDS);
+ wpa_msg(sm->msg_ctx, MSG_INFO, "EAP: more than %d "
+ "authentication rounds - abort",
+ EAP_MAX_AUTH_ROUNDS);
sm->num_rounds++;
SM_ENTER_GLOBAL(EAP, FAILURE);
}
@@ -505,7 +560,8 @@ SM_STEP(EAP)
SM_ENTER(EAP, IDLE);
break;
case EAP_DISABLED:
- if (eapol_get_bool(sm, EAPOL_portEnabled))
+ if (eapol_get_bool(sm, EAPOL_portEnabled) &&
+ !sm->force_disabled)
SM_ENTER(EAP, INITIALIZE);
break;
case EAP_IDLE:
@@ -533,16 +589,18 @@ SM_STEP(EAP)
SM_ENTER(EAP, SUCCESS);
break;
case EAP_RECEIVED:
- duplicate = sm->reqId == sm->lastId;
+ duplicate = (sm->reqId == sm->lastId) && sm->rxReq;
if (sm->workaround && duplicate &&
memcmp(sm->req_md5, sm->last_md5, 16) != 0) {
- /* draft-ietf-eap-statemachine-05.txt uses
- * (reqId == lastId) as the only verification for
- * duplicate EAP requests. However, this misses cases
- * where the AS is incorrectly using the same id again;
- * and unfortunately, such implementations exist. Use
- * MD5 hash as an extra verification for the packets
- * being duplicate to workaround these issues. */
+ /*
+ * RFC 4137 uses (reqId == lastId) as the only
+ * verification for duplicate EAP requests. However,
+ * this misses cases where the AS is incorrectly using
+ * the same id again; and unfortunately, such
+ * implementations exist. Use MD5 hash as an extra
+ * verification for the packets being duplicate to
+ * workaround these issues.
+ */
wpa_printf(MSG_DEBUG, "EAP: AS used the same Id again,"
" but EAP packets were not identical");
wpa_printf(MSG_DEBUG, "EAP: workaround - assume this "
@@ -558,7 +616,9 @@ SM_STEP(EAP)
else if (sm->methodState != METHOD_CONT &&
((sm->rxFailure &&
sm->decision != DECISION_UNCOND_SUCC) ||
- (sm->rxSuccess && sm->decision == DECISION_FAIL)) &&
+ (sm->rxSuccess && sm->decision == DECISION_FAIL &&
+ (sm->selectedMethod != EAP_TYPE_LEAP ||
+ sm->methodState != METHOD_MAY_CONT))) &&
(sm->reqId == sm->lastId ||
eap_success_workaround(sm, sm->reqId, sm->lastId)))
SM_ENTER(EAP, FAILURE);
@@ -657,7 +717,8 @@ static u8 *eap_sm_buildNak(struct eap_sm *sm, int id, size_t *len)
*pos++ = EAP_TYPE_NAK;
for (i = 0; i < NUM_EAP_METHODS; i++) {
- if (wpa_config_allowed_eap_method(config,
+ if (eap_methods[i]->method != sm->reqMethod &&
+ wpa_config_allowed_eap_method(config,
eap_methods[i]->method)) {
*pos++ = eap_methods[i]->method;
(*len)++;
@@ -677,11 +738,16 @@ static u8 *eap_sm_buildNak(struct eap_sm *sm, int id, size_t *len)
}
-static void eap_sm_processIdentity(struct eap_sm *sm, u8 *req, size_t len)
+static void eap_sm_processIdentity(struct eap_sm *sm, const u8 *req,
+ size_t len)
{
- struct eap_hdr *hdr = (struct eap_hdr *) req;
- u8 *pos = (u8 *) (hdr + 1);
+ const struct eap_hdr *hdr = (const struct eap_hdr *) req;
+ const u8 *pos = (const u8 *) (hdr + 1);
pos++;
+
+ wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_STARTED
+ "EAP authentication started");
+
/* TODO: could save displayable message so that it can be shown to the
* user in case of interaction is required */
wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Identity data",
@@ -689,8 +755,77 @@ static void eap_sm_processIdentity(struct eap_sm *sm, u8 *req, size_t len)
}
-u8 *eap_sm_buildIdentity(struct eap_sm *sm, int id, size_t *len,
- int encrypted)
+static int eap_sm_imsi_identity(struct eap_sm *sm, struct wpa_ssid *ssid)
+{
+ int aka = 0;
+ char imsi[100];
+ size_t imsi_len;
+ u8 *pos = ssid->eap_methods;
+
+ imsi_len = sizeof(imsi);
+ if (scard_get_imsi(sm->scard_ctx, imsi, &imsi_len)) {
+ wpa_printf(MSG_WARNING, "Failed to get IMSI from SIM");
+ return -1;
+ }
+
+ wpa_hexdump_ascii(MSG_DEBUG, "IMSI", (u8 *) imsi, imsi_len);
+
+ while (pos && *pos != EAP_TYPE_NONE) {
+ if (*pos == EAP_TYPE_AKA) {
+ aka = 1;
+ break;
+ }
+ pos++;
+ }
+
+ free(ssid->identity);
+ ssid->identity = malloc(1 + imsi_len);
+ if (ssid->identity == NULL) {
+ wpa_printf(MSG_WARNING, "Failed to allocate buffer for "
+ "IMSI-based identity");
+ return -1;
+ }
+
+ ssid->identity[0] = aka ? '0' : '1';
+ memcpy(ssid->identity + 1, imsi, imsi_len);
+ ssid->identity_len = 1 + imsi_len;
+ return 0;
+}
+
+
+static int eap_sm_get_scard_identity(struct eap_sm *sm, struct wpa_ssid *ssid)
+{
+ if (scard_set_pin(sm->scard_ctx, ssid->pin)) {
+ /*
+ * Make sure the same PIN is not tried again in order to avoid
+ * blocking SIM.
+ */
+ free(ssid->pin);
+ ssid->pin = NULL;
+
+ wpa_printf(MSG_WARNING, "PIN validation failed");
+ eap_sm_request_pin(sm, ssid);
+ return -1;
+ }
+
+ return eap_sm_imsi_identity(sm, ssid);
+}
+
+
+/**
+ * eap_sm_buildIdentity - Build EAP-Identity/Response for the current network
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @id: EAP identifier for the packet
+ * @len: Pointer to variable that will be set to the length of the response
+ * @encrypted: Whether the packet is for enrypted tunnel (EAP phase 2)
+ * Returns: Pointer to the allocated EAP-Identity/Response packet or %NULL on
+ * failure
+ *
+ * This function allocates and builds an EAP-Identity/Response packet for the
+ * current network. The caller is responsible for freeing the returned data.
+ */
+u8 * eap_sm_buildIdentity(struct eap_sm *sm, int id, size_t *len,
+ int encrypted)
{
struct wpa_ssid *config = eap_get_config(sm);
struct eap_hdr *resp;
@@ -724,8 +859,17 @@ u8 *eap_sm_buildIdentity(struct eap_sm *sm, int id, size_t *len,
if (identity == NULL) {
wpa_printf(MSG_WARNING, "EAP: buildIdentity: identity "
"configuration was not available");
- eap_sm_request_identity(sm, config);
- return NULL;
+ if (config->pcsc) {
+ 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, config);
+ return NULL;
+ }
}
@@ -745,14 +889,33 @@ u8 *eap_sm_buildIdentity(struct eap_sm *sm, int id, size_t *len,
}
-static void eap_sm_processNotify(struct eap_sm *sm, u8 *req, size_t len)
+static void eap_sm_processNotify(struct eap_sm *sm, const u8 *req, size_t len)
{
- struct eap_hdr *hdr = (struct eap_hdr *) req;
- u8 *pos = (u8 *) (hdr + 1);
+ const struct eap_hdr *hdr = (const struct eap_hdr *) req;
+ const u8 *pos;
+ char *msg;
+ size_t msg_len;
+ int i;
+
+ pos = (const u8 *) (hdr + 1);
pos++;
- /* TODO: log the Notification Request and make it available for UI */
+
+ msg_len = be_to_host16(hdr->length);
+ if (msg_len < 5)
+ return;
+ msg_len -= 5;
wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Notification data",
- pos, be_to_host16(hdr->length) - 5);
+ pos, msg_len);
+
+ msg = malloc(msg_len + 1);
+ if (msg == NULL)
+ return;
+ for (i = 0; i < msg_len; i++)
+ msg[i] = isprint(pos[i]) ? (char) pos[i] : '_';
+ msg[msg_len] = '\0';
+ wpa_msg(sm->msg_ctx, MSG_INFO, "%s%s",
+ WPA_EVENT_EAP_NOTIFICATION, msg);
+ free(msg);
}
@@ -777,11 +940,10 @@ static u8 *eap_sm_buildNotify(struct eap_sm *sm, int id, size_t *len)
}
-static void eap_sm_parseEapReq(struct eap_sm *sm, u8 *req, size_t len)
+static void eap_sm_parseEapReq(struct eap_sm *sm, const u8 *req, size_t len)
{
- struct eap_hdr *hdr;
+ const struct eap_hdr *hdr;
size_t plen;
- MD5_CTX context;
sm->rxReq = sm->rxSuccess = sm->rxFailure = FALSE;
sm->reqId = 0;
@@ -790,7 +952,7 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, u8 *req, size_t len)
if (req == NULL || len < sizeof(*hdr))
return;
- hdr = (struct eap_hdr *) req;
+ hdr = (const struct eap_hdr *) req;
plen = be_to_host16(hdr->length);
if (plen > len) {
wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet "
@@ -802,9 +964,7 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, u8 *req, size_t len)
sm->reqId = hdr->identifier;
if (sm->workaround) {
- MD5Init(&context);
- MD5Update(&context, req, len);
- MD5Final(sm->req_md5, &context);
+ md5_vector(1, (const u8 **) &req, &len, sm->req_md5);
}
switch (hdr->code) {
@@ -843,10 +1003,22 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, u8 *req, size_t len)
}
-struct eap_sm *eap_sm_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb,
- void *msg_ctx)
+/**
+ * eap_sm_init - Allocate and initialize EAP state machine
+ * @eapol_ctx: Context data to be used with eapol_cb calls
+ * @eapol_cb: Pointer to EAPOL callback functions
+ * @msg_ctx: Context data for wpa_msg() calls
+ * @conf: EAP configuration
+ * Returns: Pointer to the allocated EAP state machine or %NULL on failure
+ *
+ * This function allocates and initializes an EAP state machine. In addition,
+ * this initializes TLS library for the new EAP state machine.
+ */
+struct eap_sm * eap_sm_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb,
+ void *msg_ctx, struct eap_config *conf)
{
struct eap_sm *sm;
+ struct tls_config tlsconf;
sm = malloc(sizeof(*sm));
if (sm == NULL)
@@ -857,7 +1029,11 @@ struct eap_sm *eap_sm_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb,
sm->msg_ctx = msg_ctx;
sm->ClientTimeout = 60;
- sm->ssl_ctx = tls_init();
+ memset(&tlsconf, 0, sizeof(tlsconf));
+ tlsconf.opensc_engine_path = conf->opensc_engine_path;
+ tlsconf.pkcs11_engine_path = conf->pkcs11_engine_path;
+ tlsconf.pkcs11_module_path = conf->pkcs11_module_path;
+ sm->ssl_ctx = tls_init(&tlsconf);
if (sm->ssl_ctx == NULL) {
wpa_printf(MSG_WARNING, "SSL: Failed to initialize TLS "
"context.");
@@ -869,6 +1045,13 @@ struct eap_sm *eap_sm_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb,
}
+/**
+ * eap_sm_deinit - Deinitialize and free an EAP state machine
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ *
+ * This function deinitializes EAP state machine and frees all allocated
+ * resources.
+ */
void eap_sm_deinit(struct eap_sm *sm)
{
if (sm == NULL)
@@ -882,6 +1065,15 @@ void eap_sm_deinit(struct eap_sm *sm)
}
+/**
+ * eap_sm_step - Step EAP state machine
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * Returns: 1 if EAP state was changed or 0 if not
+ *
+ * This function advances EAP state machine to a new state to match with the
+ * current variables. This should be called whenever variables used by the EAP
+ * state machine have changed.
+ */
int eap_sm_step(struct eap_sm *sm)
{
int res = 0;
@@ -895,10 +1087,15 @@ int eap_sm_step(struct eap_sm *sm)
}
+/**
+ * eap_sm_abort - Abort EAP authentication
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ *
+ * Release system resources that have been allocated for the authentication
+ * session without fully deinitializing the EAP state machine.
+ */
void eap_sm_abort(struct eap_sm *sm)
{
- /* release system resources that may have been allocated for the
- * authentication session */
free(sm->eapRespData);
sm->eapRespData = NULL;
free(sm->eapKeyData);
@@ -975,6 +1172,19 @@ static const char * eap_sm_decision_txt(int decision)
}
+/**
+ * eap_sm_get_status - Get EAP state machine status
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @buf: buffer for status information
+ * @buflen: maximum buffer length
+ * @verbose: whether to include verbose status information
+ * Returns: number of bytes written to buf.
+ *
+ * Query EAP state machine for status information. This function fills in a
+ * text area with current status information from the EAPOL state machine. If
+ * the buffer (buf) is not large enough, status information will be truncated
+ * to fit the buffer.
+ */
int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, int verbose)
{
int len;
@@ -1025,10 +1235,14 @@ int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, int verbose)
}
-typedef enum { TYPE_IDENTITY, TYPE_PASSWORD, TYPE_OTP } eap_ctrl_req_type;
+typedef enum {
+ TYPE_IDENTITY, TYPE_PASSWORD, TYPE_OTP, TYPE_PIN, TYPE_NEW_PASSWORD,
+ TYPE_PASSPHRASE
+} eap_ctrl_req_type;
static void eap_sm_request(struct eap_sm *sm, struct wpa_ssid *config,
- eap_ctrl_req_type type, char *msg, size_t msglen)
+ eap_ctrl_req_type type, const char *msg,
+ size_t msglen)
{
char *buf;
size_t buflen;
@@ -1050,6 +1264,16 @@ static void eap_sm_request(struct eap_sm *sm, struct wpa_ssid *config,
txt = "Password";
config->pending_req_password++;
break;
+ case TYPE_NEW_PASSWORD:
+ field = "NEW_PASSWORD";
+ txt = "New Password";
+ config->pending_req_new_password++;
+ break;
+ case TYPE_PIN:
+ field = "PIN";
+ txt = "PIN";
+ config->pending_req_pin++;
+ break;
case TYPE_OTP:
field = "OTP";
if (msg) {
@@ -1070,6 +1294,11 @@ static void eap_sm_request(struct eap_sm *sm, struct wpa_ssid *config,
txt = config->pending_req_otp;
}
break;
+ case TYPE_PASSPHRASE:
+ field = "PASSPHRASE";
+ txt = "Private key passphrase";
+ config->pending_req_passphrase++;
+ break;
default:
return;
}
@@ -1078,37 +1307,123 @@ static void eap_sm_request(struct eap_sm *sm, struct wpa_ssid *config,
buf = malloc(buflen);
if (buf == NULL)
return;
- len = snprintf(buf, buflen, "CTRL-REQ-%s-%d:%s needed for SSID ",
+ len = snprintf(buf, buflen, WPA_CTRL_REQ "%s-%d:%s needed for SSID ",
field, config->id, txt);
if (config->ssid && buflen > len + config->ssid_len) {
memcpy(buf + len, config->ssid, config->ssid_len);
len += config->ssid_len;
buf[len] = '\0';
}
- wpa_msg(sm->msg_ctx, MSG_INFO, buf);
+ wpa_msg(sm->msg_ctx, MSG_INFO, "%s", buf);
free(buf);
}
+/**
+ * eap_sm_request_identity - Request identity from user (ctrl_iface)
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @config: Pointer to the current network configuration
+ *
+ * EAP methods can call this function to request identity information for the
+ * current network. This is normally called when the identity is not included
+ * in the network configuration. The request will be sent to monitor programs
+ * through the control interface.
+ */
void eap_sm_request_identity(struct eap_sm *sm, struct wpa_ssid *config)
{
eap_sm_request(sm, config, TYPE_IDENTITY, NULL, 0);
}
+/**
+ * eap_sm_request_password - Request password from user (ctrl_iface)
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @config: Pointer to the current network configuration
+ *
+ * EAP methods can call this function to request password information for the
+ * current network. This is normally called when the password is not included
+ * in the network configuration. The request will be sent to monitor programs
+ * through the control interface.
+ */
void eap_sm_request_password(struct eap_sm *sm, struct wpa_ssid *config)
{
eap_sm_request(sm, config, TYPE_PASSWORD, NULL, 0);
}
+/**
+ * eap_sm_request_new_password - Request new password from user (ctrl_iface)
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @config: Pointer to the current network configuration
+ *
+ * EAP methods can call this function to request new password information for
+ * the current network. This is normally called when the EAP method indicates
+ * that the current password has expired and password change is required. The
+ * request will be sent to monitor programs through the control interface.
+ */
+void eap_sm_request_new_password(struct eap_sm *sm, struct wpa_ssid *config)
+{
+ eap_sm_request(sm, config, TYPE_NEW_PASSWORD, NULL, 0);
+}
+
+
+/**
+ * eap_sm_request_pin - Request SIM or smart card PIN from user (ctrl_iface)
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @config: Pointer to the current network configuration
+ *
+ * EAP methods can call this function to request SIM or smart card PIN
+ * information for the current network. This is normally called when the PIN is
+ * not included in the network configuration. The request will be sent to
+ * monitor programs through the control interface.
+ */
+void eap_sm_request_pin(struct eap_sm *sm, struct wpa_ssid *config)
+{
+ eap_sm_request(sm, config, TYPE_PIN, NULL, 0);
+}
+
+
+/**
+ * eap_sm_request_otp - Request one time password from user (ctrl_iface)
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @config: Pointer to the current network configuration
+ * @msg: Message to be displayed to the user when asking for OTP
+ * @msg_len: Length of the user displayable message
+ *
+ * EAP methods can call this function to request open time password (OTP) for
+ * the current network. The request will be sent to monitor programs through
+ * the control interface.
+ */
void eap_sm_request_otp(struct eap_sm *sm, struct wpa_ssid *config,
- char *msg, size_t msg_len)
+ const char *msg, size_t msg_len)
{
eap_sm_request(sm, config, TYPE_OTP, msg, msg_len);
}
+/**
+ * eap_sm_request_passphrase - Request passphrase from user (ctrl_iface)
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @config: Pointer to the current network configuration
+ *
+ * EAP methods can call this function to request passphrase for a private key
+ * for the current network. This is normally called when the passphrase is not
+ * included in the network configuration. The request will be sent to monitor
+ * programs through the control interface.
+ */
+void eap_sm_request_passphrase(struct eap_sm *sm, struct wpa_ssid *config)
+{
+ eap_sm_request(sm, config, TYPE_PASSPHRASE, NULL, 0);
+}
+
+
+/**
+ * eap_sm_notify_ctrl_attached - Notification of attached monitor
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ *
+ * Notify EAP state machines that a monitor was attached to the control
+ * interface to trigger re-sending of pending requests for user input.
+ */
void eap_sm_notify_ctrl_attached(struct eap_sm *sm)
{
struct wpa_ssid *config = eap_get_config(sm);
@@ -1124,11 +1439,25 @@ void eap_sm_notify_ctrl_attached(struct eap_sm *sm)
eap_sm_request_identity(sm, config);
if (config->pending_req_password)
eap_sm_request_password(sm, config);
+ if (config->pending_req_new_password)
+ eap_sm_request_new_password(sm, config);
if (config->pending_req_otp)
eap_sm_request_otp(sm, config, NULL, 0);
+ if (config->pending_req_pin)
+ eap_sm_request_pin(sm, config);
+ if (config->pending_req_passphrase)
+ eap_sm_request_passphrase(sm, config);
}
+/**
+ * eap_get_type - Get EAP type for the given EAP method name
+ * @name: EAP method name, e.g., TLS
+ * Returns: EAP method type or %EAP_TYPE_NONE if not found
+ *
+ * This function maps EAP type names into EAP type numbers based on the list of
+ * EAP methods included in the build.
+ */
u8 eap_get_type(const char *name)
{
int i;
@@ -1140,6 +1469,49 @@ u8 eap_get_type(const char *name)
}
+/**
+ * eap_get_name - Get EAP method name for the given EAP type
+ * @type: EAP method type
+ * Returns: EAP method name, e.g., TLS, or %NULL if not found
+ *
+ * This function maps EAP type numbers into EAP type names based on the list of
+ * EAP methods included in the build.
+ */
+const char * eap_get_name(EapType type)
+{
+ int i;
+ for (i = 0; i < NUM_EAP_METHODS; i++) {
+ if (eap_methods[i]->method == type)
+ return eap_methods[i]->name;
+ }
+ return NULL;
+}
+
+
+/**
+ * eap_get_names - Get space separated list of names for supported EAP methods
+ * @buf: Buffer for names
+ * @buflen: Buffer length
+ * Returns: Number of characters written into buf (not including nul
+ * termination)
+ */
+size_t eap_get_names(char *buf, size_t buflen)
+{
+ char *pos, *end;
+ int i;
+
+ pos = buf;
+ end = pos + buflen;
+
+ for (i = 0; i < NUM_EAP_METHODS; i++) {
+ pos += snprintf(pos, end - pos, "%s%s",
+ i == 0 ? "" : " ", eap_methods[i]->name);
+ }
+
+ return pos - buf;
+}
+
+
static int eap_allowed_phase2_type(int type)
{
return type != EAP_TYPE_PEAP && type != EAP_TYPE_TTLS &&
@@ -1147,6 +1519,15 @@ static int eap_allowed_phase2_type(int type)
}
+/**
+ * eap_get_phase2_type - Get EAP type for the given EAP phase 2 method name
+ * @name: EAP method name, e.g., MD5
+ * Returns: EAP method type or %EAP_TYPE_NONE if not found
+ *
+ * This function maps EAP type names into EAP type numbers that are allowed for
+ * Phase 2, i.e., for tunneled authentication. Phase 2 is used, e.g., with
+ * EAP-PEAP, EAP-TTLS, and EAP-FAST.
+ */
u8 eap_get_phase2_type(const char *name)
{
u8 type = eap_get_type(name);
@@ -1156,6 +1537,15 @@ u8 eap_get_phase2_type(const char *name)
}
+/**
+ * eap_get_phase2_types - Get list of allowed EAP phase 2 types
+ * @config: Pointer to a network configuration
+ * @count: Pointer to variable filled with number of returned EAP types
+ * Returns: Pointer to allocated type list or %NULL on failure
+ *
+ * This function generates an array of allowed EAP phase 2 (tunneled) types for
+ * the given network configuration.
+ */
u8 *eap_get_phase2_types(struct wpa_ssid *config, size_t *count)
{
u8 *buf, method;
@@ -1181,30 +1571,59 @@ u8 *eap_get_phase2_types(struct wpa_ssid *config, size_t *count)
}
+/**
+ * eap_set_fast_reauth - Update fast_reauth setting
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @enabled: 1 = fast reauthentication is enabled, 0 = disabled
+ */
void eap_set_fast_reauth(struct eap_sm *sm, int enabled)
{
sm->fast_reauth = enabled;
}
+/**
+ * eap_set_workaround - Update EAP workarounds setting
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @workaround: 1 = Enable EAP workarounds, 0 = Disable EAP workarounds
+ */
void eap_set_workaround(struct eap_sm *sm, unsigned int workaround)
{
sm->workaround = workaround;
}
+/**
+ * eap_get_config - Get current network configuration
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * Returns: Pointer to the current network configuration or %NULL if not found
+ */
struct wpa_ssid * eap_get_config(struct eap_sm *sm)
{
return sm->eapol_cb->get_config(sm->eapol_ctx);
}
+/**
+ * eap_key_available - Get key availability (eapKeyAvailable variable)
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * Returns: 1 if EAP keying material is available, 0 if not
+ */
int eap_key_available(struct eap_sm *sm)
{
return sm ? sm->eapKeyAvailable : 0;
}
+/**
+ * eap_notify_success - Notify EAP state machine about external success trigger
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ *
+ * This function is called when external event, e.g., successful completion of
+ * WPA-PSK key handshake, is indicating that EAP state machine should move to
+ * success state. This is mainly used with security modes that do not use EAP
+ * state machine (e.g., WPA-PSK).
+ */
void eap_notify_success(struct eap_sm *sm)
{
if (sm) {
@@ -1212,9 +1631,45 @@ void eap_notify_success(struct eap_sm *sm)
sm->EAP_state = EAP_SUCCESS;
}
}
+/**
+ * eap_notify_lower_layer_success - Notification of lower layer success
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ *
+ * Notify EAP state machines that a lower layer has detected a successful
+ * authentication. This is used to recover from dropped EAP-Success messages.
+ */
+void eap_notify_lower_layer_success(struct eap_sm *sm)
+{
+ if (sm == NULL)
+ return;
+ if (eapol_get_bool(sm, EAPOL_eapSuccess) ||
+ sm->decision == DECISION_FAIL ||
+ (sm->methodState != METHOD_MAY_CONT &&
+ sm->methodState != METHOD_DONE))
+ return;
-u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len)
+ if (sm->eapKeyData != NULL)
+ sm->eapKeyAvailable = TRUE;
+ eapol_set_bool(sm, EAPOL_eapSuccess, TRUE);
+ wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
+ "EAP authentication completed successfully (based on lower "
+ "layer success)");
+}
+
+
+/**
+ * eap_get_eapKeyData - Get master session key (MSK) from EAP state machine
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @len: Pointer to variable that will be set to number of bytes in the key
+ * Returns: Pointer to the EAP keying data or %NULL on failure
+ *
+ * Fetch EAP keying material (MSK, eapKeyData) from the EAP state machine. The
+ * key is available only after a successful authentication. EAP state machine
+ * continues to manage the key data and the caller must not change or free the
+ * returned data.
+ */
+const u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len)
{
if (sm == NULL || sm->eapKeyData == NULL) {
*len = 0;
@@ -1226,6 +1681,17 @@ u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len)
}
+/**
+ * eap_get_eapKeyData - Get EAP response data
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @len: Pointer to variable that will be set to the length of the response
+ * Returns: Pointer to the EAP response (eapRespData) or %NULL on failure
+ *
+ * Fetch EAP response (eapRespData) from the EAP state machine. This data is
+ * available when EAP state machine has processed an incoming EAP request. The
+ * EAP state machine does not maintain a reference to the response after this
+ * function is called and the caller is responsible for freeing the data.
+ */
u8 * eap_get_eapRespData(struct eap_sm *sm, size_t *len)
{
u8 *resp;
@@ -1244,8 +1710,91 @@ u8 * eap_get_eapRespData(struct eap_sm *sm, size_t *len)
}
+/**
+ * eap_sm_register_scard_ctx - Notification of smart card context
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @ctx: context data for smart card operations
+ *
+ * Notify EAP state machines of context data for smart card operations. This
+ * context data will be used as a parameter for scard_*() functions.
+ */
void eap_register_scard_ctx(struct eap_sm *sm, void *ctx)
{
if (sm)
sm->scard_ctx = ctx;
}
+
+
+/**
+ * eap_hdr_validate - Validate EAP header
+ * @eap_type: Expected EAP type number
+ * @msg: EAP frame (starting with EAP header)
+ * @msglen: Length of msg
+ * @plen: Pointer for return payload length
+ * Returns: Pointer to EAP payload (after type field), or %NULL on failure
+ *
+ * This is a helper function for EAP method implementations. This is usually
+ * called in the beginning of struct eap_method::process() function.
+ */
+const u8 * eap_hdr_validate(EapType eap_type, const u8 *msg, size_t msglen,
+ size_t *plen)
+{
+ const struct eap_hdr *hdr;
+ const u8 *pos;
+ size_t len;
+
+ hdr = (const struct eap_hdr *) msg;
+ pos = (const u8 *) (hdr + 1);
+ if (msglen < sizeof(*hdr) + 1 || *pos != eap_type) {
+ wpa_printf(MSG_INFO, "EAP: Invalid frame type");
+ return NULL;
+ }
+ len = be_to_host16(hdr->length);
+ if (len < sizeof(*hdr) + 1 || len > msglen) {
+ wpa_printf(MSG_INFO, "EAP: Invalid EAP length");
+ return NULL;
+ }
+ *plen = len - sizeof(*hdr) - 1;
+ return pos + 1;
+}
+
+
+/**
+ * eap_set_config_blob - Set or add a named configuration blob
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @blob: New value for the blob
+ *
+ * Adds a new configuration blob or replaces the current value of an existing
+ * blob.
+ */
+void eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob)
+{
+ sm->eapol_cb->set_config_blob(sm->eapol_ctx, blob);
+}
+
+
+/**
+ * eap_get_config_blob - Get a named configuration blob
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @name: Name of the blob
+ * Returns: Pointer to blob data or %NULL if not found
+ */
+const struct wpa_config_blob * eap_get_config_blob(struct eap_sm *sm,
+ const char *name)
+{
+ return sm->eapol_cb->get_config_blob(sm->eapol_ctx, name);
+}
+
+
+/**
+ * eap_set_force_disabled - Set force_disabled flag
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @disabled: 1 = EAP disabled, 0 = EAP enabled
+ *
+ * This function is used to force EAP state machine to be disabled when it is
+ * not in use (e.g., with WPA-PSK or plaintext connections).
+ */
+void eap_set_force_disabled(struct eap_sm *sm, int disabled)
+{
+ sm->force_disabled = disabled;
+}
diff --git a/contrib/wpa_supplicant/eap.h b/contrib/wpa_supplicant/eap.h
index 3d7cc7210d7a..e00e29bd9678 100644
--- a/contrib/wpa_supplicant/eap.h
+++ b/contrib/wpa_supplicant/eap.h
@@ -1,3 +1,17 @@
+/*
+ * WPA Supplicant / EAP state machine functions (RFC 4137)
+ * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
#ifndef EAP_H
#define EAP_H
@@ -6,55 +20,237 @@
struct eap_sm;
struct wpa_ssid;
+struct wpa_config_blob;
#ifdef IEEE8021X_EAPOL
+/**
+ * enum eapol_bool_var - EAPOL boolean state variables for EAP state machine
+ *
+ * These variables are used in the interface between EAP peer state machine and
+ * lower layer. These are defined in RFC 4137, Sect. 4.1. Lower layer code is
+ * expected to maintain these variables and register a callback functions for
+ * EAP state machine to get and set the variables.
+ */
enum eapol_bool_var {
- EAPOL_eapSuccess, EAPOL_eapRestart, EAPOL_eapFail, EAPOL_eapResp,
- EAPOL_eapNoResp, EAPOL_eapReq, EAPOL_portEnabled, EAPOL_altAccept,
+ /**
+ * EAPOL_eapSuccess - EAP SUCCESS state reached
+ *
+ * EAP state machine reads and writes this value.
+ */
+ EAPOL_eapSuccess,
+
+ /**
+ * EAPOL_eapRestart - Lower layer request to restart authentication
+ *
+ * Set to TRUE in lower layer, FALSE in EAP state machine.
+ */
+ EAPOL_eapRestart,
+
+ /**
+ * EAPOL_eapFail - EAP FAILURE state reached
+ *
+ * EAP state machine writes this value.
+ */
+ EAPOL_eapFail,
+
+ /**
+ * EAPOL_eapResp - Response to send
+ *
+ * Set to TRUE in EAP state machine, FALSE in lower layer.
+ */
+ EAPOL_eapResp,
+
+ /**
+ * EAPOL_eapNoResp - Request has been process; no response to send
+ *
+ * Set to TRUE in EAP state machine, FALSE in lower layer.
+ */
+ EAPOL_eapNoResp,
+
+ /**
+ * EAPOL_eapReq - EAP request available from lower layer
+ *
+ * Set to TRUE in lower layer, FALSE in EAP state machine.
+ */
+ EAPOL_eapReq,
+
+ /**
+ * EAPOL_portEnabled - Lower layer is ready for communication
+ *
+ * EAP state machines reads this value.
+ */
+ EAPOL_portEnabled,
+
+ /**
+ * EAPOL_altAccept - Alternate indication of success (RFC3748)
+ *
+ * EAP state machines reads this value.
+ */
+ EAPOL_altAccept,
+
+ /**
+ * EAPOL_altReject - Alternate indication of failure (RFC3748)
+ *
+ * EAP state machines reads this value.
+ */
EAPOL_altReject
};
+/**
+ * enum eapol_int_var - EAPOL integer state variables for EAP state machine
+ *
+ * These variables are used in the interface between EAP peer state machine and
+ * lower layer. These are defined in RFC 4137, Sect. 4.1. Lower layer code is
+ * expected to maintain these variables and register a callback functions for
+ * EAP state machine to get and set the variables.
+ */
enum eapol_int_var {
+ /**
+ * EAPOL_idleWhile - Outside time for EAP peer timeout
+ *
+ * This integer variable is used to provide an outside timer that the
+ * external (to EAP state machine) code must decrement by one every
+ * second until the value reaches zero. This is used in the same way as
+ * EAPOL state machine timers. EAP state machine reads and writes this
+ * value.
+ */
EAPOL_idleWhile
};
+/**
+ * struct eapol_callbacks - Callback functions from EAP to lower layer
+ *
+ * This structure defines the callback functions that EAP state machine
+ * requires from the lower layer (usually EAPOL state machine) for updating
+ * state variables and requesting information. eapol_ctx from eap_sm_init()
+ * call will be used as the ctx parameter for these callback functions.
+ */
struct eapol_callbacks {
+ /**
+ * get_config - Get pointer to the current network configuration
+ * @ctx: eapol_ctx from eap_sm_init() call
+ */
struct wpa_ssid * (*get_config)(void *ctx);
+
+ /**
+ * get_bool - Get a boolean EAPOL state variable
+ * @variable: EAPOL boolean variable to get
+ * Returns: Value of the EAPOL variable
+ */
Boolean (*get_bool)(void *ctx, enum eapol_bool_var variable);
+
+ /**
+ * set_bool - Set a boolean EAPOL state variable
+ * @ctx: eapol_ctx from eap_sm_init() call
+ * @variable: EAPOL boolean variable to set
+ * @value: Value for the EAPOL variable
+ */
void (*set_bool)(void *ctx, enum eapol_bool_var variable,
Boolean value);
+
+ /**
+ * get_int - Get an integer EAPOL state variable
+ * @ctx: eapol_ctx from eap_sm_init() call
+ * @variable: EAPOL integer variable to get
+ * Returns: Value of the EAPOL variable
+ */
unsigned int (*get_int)(void *ctx, enum eapol_int_var variable);
+
+ /**
+ * set_int - Set an integer EAPOL state variable
+ * @ctx: eapol_ctx from eap_sm_init() call
+ * @variable: EAPOL integer variable to set
+ * @value: Value for the EAPOL variable
+ */
void (*set_int)(void *ctx, enum eapol_int_var variable,
unsigned int value);
+
+ /**
+ * get_eapReqData - Get EAP-Request data
+ * @ctx: eapol_ctx from eap_sm_init() call
+ * @len: Pointer to variable that will be set to eapReqDataLen
+ * Returns: Reference to eapReqData (EAP state machine will not free
+ * this) or %NULL if eapReqData not available.
+ */
u8 * (*get_eapReqData)(void *ctx, size_t *len);
+
+ /**
+ * set_config_blob - Set named configuration blob
+ * @ctx: eapol_ctx from eap_sm_init() call
+ * @blob: New value for the blob
+ *
+ * Adds a new configuration blob or replaces the current value of an
+ * existing blob.
+ */
+ void (*set_config_blob)(void *ctx, struct wpa_config_blob *blob);
+
+ /**
+ * get_config_blob - Get a named configuration blob
+ * @ctx: eapol_ctx from eap_sm_init() call
+ * @name: Name of the blob
+ * Returns: Pointer to blob data or %NULL if not found
+ */
+ const struct wpa_config_blob * (*get_config_blob)(void *ctx,
+ const char *name);
+};
+
+/**
+ * struct eap_config - Configuration for EAP state machine
+ */
+struct eap_config {
+ /**
+ * opensc_engine_path - OpenSC engine for OpenSSL engine support
+ *
+ * Usually, path to engine_opensc.so.
+ */
+ const char *opensc_engine_path;
+ /**
+ * pkcs11_engine_path - PKCS#11 engine for OpenSSL engine support
+ *
+ * Usually, path to engine_pkcs11.so.
+ */
+ const char *pkcs11_engine_path;
+ /**
+ * pkcs11_module_path - OpenSC PKCS#11 module for OpenSSL engine
+ *
+ * Usually, path to opensc-pkcs11.so.
+ */
+ const char *pkcs11_module_path;
};
-struct eap_sm *eap_sm_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb,
- void *msg_ctx);
+struct eap_sm * eap_sm_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb,
+ void *msg_ctx, struct eap_config *conf);
void eap_sm_deinit(struct eap_sm *sm);
int eap_sm_step(struct eap_sm *sm);
void eap_sm_abort(struct eap_sm *sm);
int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen,
int verbose);
-u8 *eap_sm_buildIdentity(struct eap_sm *sm, int id, size_t *len,
- int encrypted);
+u8 * eap_sm_buildIdentity(struct eap_sm *sm, int id, size_t *len,
+ int encrypted);
const struct eap_method * eap_sm_get_eap_methods(int method);
void eap_sm_request_identity(struct eap_sm *sm, struct wpa_ssid *config);
void eap_sm_request_password(struct eap_sm *sm, struct wpa_ssid *config);
+void eap_sm_request_new_password(struct eap_sm *sm, struct wpa_ssid *config);
+void eap_sm_request_pin(struct eap_sm *sm, struct wpa_ssid *config);
void eap_sm_request_otp(struct eap_sm *sm, struct wpa_ssid *config,
- char *msg, size_t msg_len);
+ const char *msg, size_t msg_len);
+void eap_sm_request_passphrase(struct eap_sm *sm, struct wpa_ssid *config);
void eap_sm_notify_ctrl_attached(struct eap_sm *sm);
u8 eap_get_type(const char *name);
+const char * eap_get_name(EapType type);
+size_t eap_get_names(char *buf, size_t buflen);
u8 eap_get_phase2_type(const char *name);
u8 *eap_get_phase2_types(struct wpa_ssid *config, size_t *count);
void eap_set_fast_reauth(struct eap_sm *sm, int enabled);
void eap_set_workaround(struct eap_sm *sm, unsigned int workaround);
+void eap_set_force_disabled(struct eap_sm *sm, int disabled);
struct wpa_ssid * eap_get_config(struct eap_sm *sm);
int eap_key_available(struct eap_sm *sm);
void eap_notify_success(struct eap_sm *sm);
-u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len);
+void eap_notify_lower_layer_success(struct eap_sm *sm);
+const u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len);
u8 * eap_get_eapRespData(struct eap_sm *sm, size_t *len);
void eap_register_scard_ctx(struct eap_sm *sm, void *ctx);
@@ -65,6 +261,16 @@ static inline u8 eap_get_type(const char *name)
return EAP_TYPE_NONE;
}
+static inline const char * eap_get_name(EapType type)
+{
+ return NULL;
+}
+
+static inline size_t eap_get_names(char *buf, size_t buflen)
+{
+ return 0;
+}
+
#endif /* IEEE8021X_EAPOL */
#endif /* EAP_H */
diff --git a/contrib/wpa_supplicant/eap_aka.c b/contrib/wpa_supplicant/eap_aka.c
index 7fe6449ab896..b05cc72a9aa9 100644
--- a/contrib/wpa_supplicant/eap_aka.c
+++ b/contrib/wpa_supplicant/eap_aka.c
@@ -20,7 +20,7 @@
#include "eap_i.h"
#include "wpa_supplicant.h"
#include "config_ssid.h"
-#include "sha1.h"
+#include "crypto.h"
#include "pcsc_funcs.h"
#include "eap_sim_common.h"
@@ -211,7 +211,7 @@ static int eap_aka_learn_ids(struct eap_aka_data *data,
static u8 * eap_aka_client_error(struct eap_sm *sm, struct eap_aka_data *data,
- struct eap_hdr *req,
+ const struct eap_hdr *req,
size_t *respDataLen, int err)
{
struct eap_sim_msg *msg;
@@ -229,7 +229,7 @@ static u8 * eap_aka_client_error(struct eap_sm *sm, struct eap_aka_data *data,
static u8 * eap_aka_authentication_reject(struct eap_sm *sm,
struct eap_aka_data *data,
- struct eap_hdr *req,
+ const struct eap_hdr *req,
size_t *respDataLen)
{
struct eap_sim_msg *msg;
@@ -249,7 +249,7 @@ static u8 * eap_aka_authentication_reject(struct eap_sm *sm,
static u8 * eap_aka_synchronization_failure(struct eap_sm *sm,
struct eap_aka_data *data,
- struct eap_hdr *req,
+ const struct eap_hdr *req,
size_t *respDataLen)
{
struct eap_sim_msg *msg;
@@ -271,7 +271,7 @@ static u8 * eap_aka_synchronization_failure(struct eap_sm *sm,
static u8 * eap_aka_response_identity(struct eap_sm *sm,
struct eap_aka_data *data,
- struct eap_hdr *req,
+ const struct eap_hdr *req,
size_t *respDataLen,
enum eap_sim_id_req id_req)
{
@@ -300,7 +300,7 @@ static u8 * eap_aka_response_identity(struct eap_sm *sm,
eap_aka_clear_identities(data, CLEAR_EAP_ID);
wpa_printf(MSG_DEBUG, "Generating EAP-AKA Identity (id=%d)",
- req->identifier);
+ req->identifier);
msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier,
EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY);
@@ -317,13 +317,13 @@ static u8 * eap_aka_response_identity(struct eap_sm *sm,
static u8 * eap_aka_response_challenge(struct eap_sm *sm,
struct eap_aka_data *data,
- struct eap_hdr *req,
+ const struct eap_hdr *req,
size_t *respDataLen)
{
struct eap_sim_msg *msg;
wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d)",
- req->identifier);
+ req->identifier);
msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier,
EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE);
wpa_printf(MSG_DEBUG, " AT_RES");
@@ -337,7 +337,7 @@ static u8 * eap_aka_response_challenge(struct eap_sm *sm,
static u8 * eap_aka_response_reauth(struct eap_sm *sm,
struct eap_aka_data *data,
- struct eap_hdr *req,
+ const struct eap_hdr *req,
size_t *respDataLen, int counter_too_small)
{
struct eap_sim_msg *msg;
@@ -377,7 +377,7 @@ static u8 * eap_aka_response_reauth(struct eap_sm *sm,
static u8 * eap_aka_response_notification(struct eap_sm *sm,
struct eap_aka_data *data,
- struct eap_hdr *req,
+ const struct eap_hdr *req,
size_t *respDataLen,
u16 notification)
{
@@ -416,7 +416,8 @@ static u8 * eap_aka_response_notification(struct eap_sm *sm,
static u8 * eap_aka_process_identity(struct eap_sm *sm,
struct eap_aka_data *data,
- struct eap_hdr *req, size_t reqDataLen,
+ const struct eap_hdr *req,
+ size_t reqDataLen,
size_t *respDataLen,
struct eap_sim_attrs *attr)
{
@@ -458,7 +459,8 @@ static u8 * eap_aka_process_identity(struct eap_sm *sm,
static u8 * eap_aka_process_challenge(struct eap_sm *sm,
struct eap_aka_data *data,
- struct eap_hdr *req, size_t reqDataLen,
+ const struct eap_hdr *req,
+ size_t reqDataLen,
size_t *respDataLen,
struct eap_sim_attrs *attr)
{
@@ -512,8 +514,8 @@ static u8 * eap_aka_process_challenge(struct eap_sm *sm,
"derivation", identity, identity_len);
eap_aka_derive_mk(data, identity, identity_len);
eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk);
- if (eap_sim_verify_mac(data->k_aut, (u8 *) req, reqDataLen, attr->mac,
- (u8 *) "", 0)) {
+ if (eap_sim_verify_mac(data->k_aut, (const u8 *) req, reqDataLen,
+ attr->mac, (u8 *) "", 0)) {
wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message "
"used invalid AT_MAC");
return eap_aka_client_error(sm, data, req, respDataLen,
@@ -527,14 +529,17 @@ static u8 * eap_aka_process_challenge(struct eap_sm *sm,
CLEAR_EAP_ID);
if (attr->encr_data) {
- if (eap_sim_parse_encr(data->k_encr, attr->encr_data,
- attr->encr_data_len, attr->iv, &eattr,
- 0)) {
+ u8 *decrypted;
+ decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
+ attr->encr_data_len, attr->iv,
+ &eattr, 0);
+ if (decrypted == NULL) {
return eap_aka_client_error(
sm, data, req, respDataLen,
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
}
eap_aka_learn_ids(data, &eattr);
+ free(decrypted);
}
if (data->state != FAILURE)
@@ -551,11 +556,12 @@ static u8 * eap_aka_process_challenge(struct eap_sm *sm,
static int eap_aka_process_notification_reauth(struct eap_aka_data *data,
- struct eap_hdr *req,
+ const struct eap_hdr *req,
size_t reqDataLen,
struct eap_sim_attrs *attr)
{
struct eap_sim_attrs eattr;
+ u8 *decrypted;
if (attr->encr_data == NULL || attr->iv == NULL) {
wpa_printf(MSG_WARNING, "EAP-AKA: Notification message after "
@@ -563,8 +569,10 @@ static int eap_aka_process_notification_reauth(struct eap_aka_data *data,
return -1;
}
- if (eap_sim_parse_encr(data->k_encr, attr->encr_data,
- attr->encr_data_len, attr->iv, &eattr, 0)) {
+ decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
+ attr->encr_data_len, attr->iv, &eattr,
+ 0);
+ if (decrypted == NULL) {
wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
"data from notification message");
return -1;
@@ -574,15 +582,17 @@ static int eap_aka_process_notification_reauth(struct eap_aka_data *data,
wpa_printf(MSG_WARNING, "EAP-AKA: Counter in notification "
"message does not match with counter in reauth "
"message");
+ free(decrypted);
return -1;
}
+ free(decrypted);
return 0;
}
static int eap_aka_process_notification_auth(struct eap_aka_data *data,
- struct eap_hdr *req,
+ const struct eap_hdr *req,
size_t reqDataLen,
struct eap_sim_attrs *attr)
{
@@ -592,8 +602,8 @@ static int eap_aka_process_notification_auth(struct eap_aka_data *data,
return -1;
}
- if (eap_sim_verify_mac(data->k_aut, (u8 *) req, reqDataLen, attr->mac,
- (u8 *) "", 0)) {
+ if (eap_sim_verify_mac(data->k_aut, (const u8 *) req, reqDataLen,
+ attr->mac, (u8 *) "", 0)) {
wpa_printf(MSG_WARNING, "EAP-AKA: Notification message "
"used invalid AT_MAC");
return -1;
@@ -612,7 +622,7 @@ static int eap_aka_process_notification_auth(struct eap_aka_data *data,
static u8 * eap_aka_process_notification(struct eap_sm *sm,
struct eap_aka_data *data,
- struct eap_hdr *req,
+ const struct eap_hdr *req,
size_t reqDataLen,
size_t *respDataLen,
struct eap_sim_attrs *attr)
@@ -649,12 +659,13 @@ static u8 * eap_aka_process_notification(struct eap_sm *sm,
static u8 * eap_aka_process_reauthentication(struct eap_sm *sm,
struct eap_aka_data *data,
- struct eap_hdr *req,
+ const struct eap_hdr *req,
size_t reqDataLen,
size_t *respDataLen,
struct eap_sim_attrs *attr)
{
struct eap_sim_attrs eattr;
+ u8 *decrypted;
wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Reauthentication");
@@ -666,7 +677,7 @@ static u8 * eap_aka_process_reauthentication(struct eap_sm *sm,
}
data->reauth = 1;
- if (eap_sim_verify_mac(data->k_aut, (u8 *) req, reqDataLen,
+ if (eap_sim_verify_mac(data->k_aut, (const u8 *) req, reqDataLen,
attr->mac, (u8 *) "", 0)) {
wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication "
"did not have valid AT_MAC");
@@ -681,8 +692,10 @@ static u8 * eap_aka_process_reauthentication(struct eap_sm *sm,
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
}
- if (eap_sim_parse_encr(data->k_encr, attr->encr_data,
- attr->encr_data_len, attr->iv, &eattr, 0)) {
+ decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
+ attr->encr_data_len, attr->iv, &eattr,
+ 0);
+ if (decrypted == NULL) {
wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted "
"data from reauthentication message");
return eap_aka_client_error(sm, data, req, respDataLen,
@@ -693,6 +706,7 @@ static u8 * eap_aka_process_reauthentication(struct eap_sm *sm,
wpa_printf(MSG_INFO, "EAP-AKA: (encr) No%s%s in reauth packet",
!eattr.nonce_s ? " AT_NONCE_S" : "",
eattr.counter < 0 ? " AT_COUNTER" : "");
+ free(decrypted);
return eap_aka_client_error(sm, data, req, respDataLen,
EAP_AKA_UNABLE_TO_PROCESS_PACKET);
}
@@ -711,6 +725,7 @@ static u8 * eap_aka_process_reauthentication(struct eap_sm *sm,
data->last_eap_identity_len = data->reauth_id_len;
data->reauth_id = NULL;
data->reauth_id_len = 0;
+ free(decrypted);
return eap_aka_response_reauth(sm, data, req, respDataLen, 1);
}
data->counter = eattr.counter;
@@ -735,19 +750,21 @@ static u8 * eap_aka_process_reauthentication(struct eap_sm *sm,
"fast reauths performed - force fullauth");
eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
}
+ free(decrypted);
return eap_aka_response_reauth(sm, data, req, respDataLen, 0);
}
static u8 * eap_aka_process(struct eap_sm *sm, void *priv,
struct eap_method_ret *ret,
- u8 *reqData, size_t reqDataLen,
+ const u8 *reqData, size_t reqDataLen,
size_t *respDataLen)
{
struct eap_aka_data *data = priv;
struct wpa_ssid *config = eap_get_config(sm);
- struct eap_hdr *req;
- u8 *pos, subtype, *res;
+ const struct eap_hdr *req;
+ u8 subtype, *res;
+ const u8 *pos;
struct eap_sim_attrs attr;
size_t len;
@@ -759,21 +776,19 @@ static u8 * eap_aka_process(struct eap_sm *sm, void *priv,
return NULL;
}
- req = (struct eap_hdr *) reqData;
- pos = (u8 *) (req + 1);
- if (reqDataLen < sizeof(*req) + 4 || *pos != EAP_TYPE_AKA ||
- (len = be_to_host16(req->length)) > reqDataLen) {
- wpa_printf(MSG_INFO, "EAP-AKA: Invalid frame");
+ pos = eap_hdr_validate(EAP_TYPE_AKA, reqData, reqDataLen, &len);
+ if (pos == NULL || len < 1) {
ret->ignore = TRUE;
return NULL;
}
+ req = (const struct eap_hdr *) reqData;
+ len = be_to_host16(req->length);
ret->ignore = FALSE;
- ret->methodState = METHOD_CONT;
+ ret->methodState = METHOD_MAY_CONT;
ret->decision = DECISION_FAIL;
ret->allowNotifications = TRUE;
- pos++;
subtype = *pos++;
wpa_printf(MSG_DEBUG, "EAP-AKA: Subtype=%d", subtype);
pos += 2; /* Reserved */
@@ -818,7 +833,7 @@ done:
ret->decision = DECISION_FAIL;
ret->methodState = METHOD_DONE;
} else if (data->state == SUCCESS) {
- ret->decision = DECISION_UNCOND_SUCC;
+ ret->decision = DECISION_COND_SUCC;
ret->methodState = METHOD_DONE;
}
diff --git a/contrib/wpa_supplicant/eap_defs.h b/contrib/wpa_supplicant/eap_defs.h
index effe665f0919..9cd44905153d 100644
--- a/contrib/wpa_supplicant/eap_defs.h
+++ b/contrib/wpa_supplicant/eap_defs.h
@@ -1,3 +1,17 @@
+/*
+ * WPA Supplicant/hostapd / Shared EAP definitions
+ * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
#ifndef EAP_DEFS_H
#define EAP_DEFS_H
@@ -6,7 +20,7 @@
struct eap_hdr {
u8 code;
u8 identifier;
- u16 length; /* including code and identifier */
+ u16 length; /* including code and identifier; network byte order */
/* followed by length-4 octets of data */
} __attribute__ ((packed));
@@ -18,12 +32,12 @@ enum { EAP_CODE_REQUEST = 1, EAP_CODE_RESPONSE = 2, EAP_CODE_SUCCESS = 3,
typedef enum {
EAP_TYPE_NONE = 0,
- EAP_TYPE_IDENTITY = 1,
- EAP_TYPE_NOTIFICATION = 2,
- EAP_TYPE_NAK = 3 /* Response only */,
- EAP_TYPE_MD5 = 4,
- EAP_TYPE_OTP = 5 /* RFC 2284 */,
- EAP_TYPE_GTC = 6, /* RFC 2284 */
+ EAP_TYPE_IDENTITY = 1 /* RFC 3748 */,
+ EAP_TYPE_NOTIFICATION = 2 /* RFC 3748 */,
+ EAP_TYPE_NAK = 3 /* Response only, RFC 3748 */,
+ EAP_TYPE_MD5 = 4, /* RFC 3748 */
+ EAP_TYPE_OTP = 5 /* RFC 3748 */,
+ EAP_TYPE_GTC = 6, /* RFC 3748 */
EAP_TYPE_TLS = 13 /* RFC 2716 */,
EAP_TYPE_LEAP = 17 /* Cisco proprietary */,
EAP_TYPE_SIM = 18 /* draft-haverinen-pppext-eap-sim-12.txt */,
@@ -33,9 +47,10 @@ typedef enum {
EAP_TYPE_MSCHAPV2 = 26 /* draft-kamath-pppext-eap-mschapv2-00.txt */,
EAP_TYPE_TLV = 33 /* draft-josefsson-pppext-eap-tls-eap-07.txt */,
EAP_TYPE_FAST = 43 /* draft-cam-winget-eap-fast-00.txt */,
+ EAP_TYPE_PAX = 46, /* draft-clancy-eap-pax-04.txt */
EAP_TYPE_EXPANDED_NAK = 254 /* RFC 3748 */,
EAP_TYPE_PSK = 255 /* EXPERIMENTAL - type not yet allocated
- * draft-bersani-eap-psk-03 */
+ * draft-bersani-eap-psk-09 */
} EapType;
#endif /* EAP_DEFS_H */
diff --git a/contrib/wpa_supplicant/eap_fast.c b/contrib/wpa_supplicant/eap_fast.c
index 1c9c3ff2370f..ff8f76c69e73 100644
--- a/contrib/wpa_supplicant/eap_fast.c
+++ b/contrib/wpa_supplicant/eap_fast.c
@@ -24,10 +24,12 @@
#include "tls.h"
#include "eap_tlv.h"
#include "sha1.h"
+#include "config.h"
/* TODO:
* - encrypt PAC-Key in the PAC file
* - test session resumption and enable it if it interoperates
+ * - password change (pending mschapv2 packet; replay decrypted packet)
*/
#define EAP_FAST_VERSION 1
@@ -36,7 +38,8 @@
#define TLS_EXT_PAC_OPAQUE 35
-static char *pac_file_hdr = "wpa_supplicant EAP-FAST PAC file - version 1";
+static const char *pac_file_hdr =
+ "wpa_supplicant EAP-FAST PAC file - version 1";
static void eap_fast_deinit(struct eap_sm *sm, void *priv);
@@ -58,28 +61,18 @@ struct pac_tlv_hdr {
};
-/* draft-cam-winget-eap-fast-00.txt, 6.2 EAP-FAST Authentication Phase 1 */
+/* draft-cam-winget-eap-fast-02.txt:
+ * 6.2 EAP-FAST Authentication Phase 1: Key Derivations */
struct eap_fast_key_block_auth {
- /* RC4-128-SHA */
- u8 client_write_MAC_secret[20];
- u8 server_write_MAC_secret[20];
- u8 client_write_key[16];
- u8 server_write_key[16];
- /* u8 client_write_IV[0]; */
- /* u8 server_write_IV[0]; */
+ /* Extra key material after TLS key_block */
u8 session_key_seed[40];
};
-/* draft-cam-winget-eap-fast-00.txt, 7.3 EAP-FAST Provisioning Exchange */
+/* draft-cam-winget-eap-fast-provisioning-01.txt:
+ * 3.4 Key Derivations Used in the EAP-FAST Provisioning Exchange */
struct eap_fast_key_block_provisioning {
- /* AES128-SHA */
- u8 client_write_MAC_secret[20];
- u8 server_write_MAC_secret[20];
- u8 client_write_key[16];
- u8 server_write_key[16];
- u8 client_write_IV[16];
- u8 server_write_IV[16];
+ /* Extra key material after TLS key_block */
u8 session_key_seed[40];
u8 server_challenge[16];
u8 client_challenge[16];
@@ -249,12 +242,34 @@ static int eap_fast_add_pac(struct eap_fast_data *data,
}
-static int eap_fast_read_line(FILE *f, char *buf, size_t buf_len)
+struct eap_fast_read_ctx {
+ FILE *f;
+ const char *pos;
+ const char *end;
+};
+
+static int eap_fast_read_line(struct eap_fast_read_ctx *rc, char *buf,
+ size_t buf_len)
{
char *pos;
- if (fgets(buf, buf_len, f) == NULL) {
- return -1;
+ if (rc->f) {
+ if (fgets(buf, buf_len, rc->f) == NULL)
+ return -1;
+ } else {
+ const char *l_end;
+ size_t len;
+ if (rc->pos >= rc->end)
+ return -1;
+ l_end = rc->pos;
+ while (l_end < rc->end && *l_end != '\n')
+ l_end++;
+ len = l_end - rc->pos;
+ if (len >= buf_len)
+ len = buf_len - 1;
+ memcpy(buf, rc->pos, len);
+ buf[len] = '\0';
+ rc->pos = l_end + 1;
}
buf[buf_len - 1] = '\0';
@@ -293,9 +308,10 @@ static u8 * eap_fast_parse_hex(const char *value, size_t *len)
}
-static int eap_fast_load_pac(struct eap_fast_data *data, const char *pac_file)
+static int eap_fast_load_pac(struct eap_sm *sm, struct eap_fast_data *data,
+ const char *pac_file)
{
- FILE *f;
+ struct eap_fast_read_ctx rc;
struct eap_fast_pac *pac = NULL;
int count = 0;
char *buf, *pos;
@@ -305,11 +321,27 @@ static int eap_fast_load_pac(struct eap_fast_data *data, const char *pac_file)
if (pac_file == NULL)
return -1;
- f = fopen(pac_file, "r");
- if (f == NULL) {
- wpa_printf(MSG_INFO, "EAP-FAST: No PAC file '%s' - assume no "
- "PAC entries have been provisioned", pac_file);
- return 0;
+ memset(&rc, 0, sizeof(rc));
+
+ if (strncmp(pac_file, "blob://", 7) == 0) {
+ const struct wpa_config_blob *blob;
+ blob = eap_get_config_blob(sm, pac_file + 7);
+ if (blob == NULL) {
+ wpa_printf(MSG_INFO, "EAP-FAST: No PAC blob '%s' - "
+ "assume no PAC entries have been "
+ "provisioned", pac_file + 7);
+ return 0;
+ }
+ rc.pos = (char *) blob->data;
+ rc.end = (char *) blob->data + blob->len;
+ } else {
+ rc.f = fopen(pac_file, "r");
+ if (rc.f == NULL) {
+ wpa_printf(MSG_INFO, "EAP-FAST: No PAC file '%s' - "
+ "assume no PAC entries have been "
+ "provisioned", pac_file);
+ return 0;
+ }
}
buf = malloc(buf_len);
@@ -318,16 +350,17 @@ static int eap_fast_load_pac(struct eap_fast_data *data, const char *pac_file)
}
line++;
- if (eap_fast_read_line(f, buf, buf_len) < 0 ||
+ if (eap_fast_read_line(&rc, buf, buf_len) < 0 ||
strcmp(pac_file_hdr, buf) != 0) {
wpa_printf(MSG_INFO, "EAP-FAST: Unrecognized header line in "
"PAC file '%s'", pac_file);
free(buf);
- fclose(f);
+ if (rc.f)
+ fclose(rc.f);
return -1;
}
- while (eap_fast_read_line(f, buf, buf_len) == 0) {
+ while (eap_fast_read_line(&rc, buf, buf_len) == 0) {
line++;
pos = strchr(buf, '=');
if (pos) {
@@ -423,7 +456,8 @@ static int eap_fast_load_pac(struct eap_fast_data *data, const char *pac_file)
}
free(buf);
- fclose(f);
+ if (rc.f)
+ fclose(rc.f);
if (ret == 0) {
wpa_printf(MSG_DEBUG, "EAP-FAST: read %d PAC entries from "
@@ -434,67 +468,124 @@ static int eap_fast_load_pac(struct eap_fast_data *data, const char *pac_file)
}
-static void eap_fast_write(FILE *f, const char *field, const u8 *data,
+static void eap_fast_write(char **buf, char **pos, size_t *buf_len,
+ const char *field, const u8 *data,
size_t len, int txt)
{
int i;
+ size_t need;
- if (data == NULL)
+ if (data == NULL || *buf == NULL)
return;
- fprintf(f, "%s=", field);
+ need = strlen(field) + len * 2 + 30;
+ if (txt)
+ need += strlen(field) + len + 20;
+
+ if (*pos - *buf + need > *buf_len) {
+ char *nbuf = realloc(*buf, *buf_len + need);
+ if (nbuf == NULL) {
+ free(*buf);
+ *buf = NULL;
+ return;
+ }
+ *buf = nbuf;
+ *buf_len += need;
+ }
+
+ *pos += snprintf(*pos, *buf + *buf_len - *pos, "%s=", field);
for (i = 0; i < len; i++) {
- fprintf(f, "%02x", data[i]);
+ *pos += snprintf(*pos, *buf + *buf_len - *pos,
+ "%02x", data[i]);
}
- fprintf(f, "\n");
+ *pos += snprintf(*pos, *buf + *buf_len - *pos, "\n");
if (txt) {
- fprintf(f, "%s-txt=", field);
+ *pos += snprintf(*pos, *buf + *buf_len - *pos,
+ "%s-txt=", field);
for (i = 0; i < len; i++) {
- fprintf(f, "%c", data[i]);
+ *pos += snprintf(*pos, *buf + *buf_len - *pos,
+ "%c", data[i]);
}
- fprintf(f, "\n");
+ *pos += snprintf(*pos, *buf + *buf_len - *pos, "\n");
}
}
-static int eap_fast_save_pac(struct eap_fast_data *data, const char *pac_file)
+static int eap_fast_save_pac(struct eap_sm *sm, struct eap_fast_data *data,
+ const char *pac_file)
{
FILE *f;
struct eap_fast_pac *pac;
int count = 0;
+ char *buf, *pos;
+ size_t buf_len;
if (pac_file == NULL)
return -1;
- f = fopen(pac_file, "w");
- if (f == NULL) {
- wpa_printf(MSG_INFO, "EAP-FAST: Failed to open PAC file '%s' "
- "for writing", pac_file);
+ buf_len = 1024;
+ pos = buf = malloc(buf_len);
+ if (buf == NULL)
return -1;
- }
- fprintf(f, "%s\n", pac_file_hdr);
+ pos += snprintf(pos, buf + buf_len - pos, "%s\n", pac_file_hdr);
pac = data->pac;
while (pac) {
- fprintf(f, "START\n");
- eap_fast_write(f, "PAC-Key", pac->pac_key,
+ pos += snprintf(pos, buf + buf_len - pos, "START\n");
+ eap_fast_write(&buf, &pos, &buf_len, "PAC-Key", pac->pac_key,
EAP_FAST_PAC_KEY_LEN, 0);
- eap_fast_write(f, "PAC-Opaque", pac->pac_opaque,
- pac->pac_opaque_len, 0);
- eap_fast_write(f, "PAC-Info", pac->pac_info,
+ eap_fast_write(&buf, &pos, &buf_len, "PAC-Opaque",
+ pac->pac_opaque, pac->pac_opaque_len, 0);
+ eap_fast_write(&buf, &pos, &buf_len, "PAC-Info", pac->pac_info,
pac->pac_info_len, 0);
- eap_fast_write(f, "A-ID", pac->a_id, pac->a_id_len, 0);
- eap_fast_write(f, "I-ID", pac->i_id, pac->i_id_len, 1);
- eap_fast_write(f, "A-ID-Info", pac->a_id_info,
- pac->a_id_info_len, 1);
- fprintf(f, "END\n");
+ eap_fast_write(&buf, &pos, &buf_len, "A-ID", pac->a_id,
+ pac->a_id_len, 0);
+ eap_fast_write(&buf, &pos, &buf_len, "I-ID", pac->i_id,
+ pac->i_id_len, 1);
+ eap_fast_write(&buf, &pos, &buf_len, "A-ID-Info",
+ pac->a_id_info, pac->a_id_info_len, 1);
+ pos += snprintf(pos, buf + buf_len - pos, "END\n");
count++;
pac = pac->next;
+
+ if (buf == NULL) {
+ wpa_printf(MSG_DEBUG, "EAP-FAST: No memory for PAC "
+ "data");
+ return -1;
+ }
}
- fclose(f);
+ if (strncmp(pac_file, "blob://", 7) == 0) {
+ struct wpa_config_blob *blob;
+ blob = malloc(sizeof(*blob));
+ if (blob == NULL) {
+ free(buf);
+ return -1;
+ }
+ memset(blob, 0, sizeof(*blob));
+ blob->data = (u8 *) buf;
+ blob->len = pos - buf;
+ buf = NULL;
+ blob->name = strdup(pac_file + 7);
+ if (blob->name == NULL) {
+ wpa_config_free_blob(blob);
+ return -1;
+ }
+ eap_set_config_blob(sm, blob);
+ } else {
+ f = fopen(pac_file, "w");
+ if (f == NULL) {
+ wpa_printf(MSG_INFO, "EAP-FAST: Failed to open PAC "
+ "file '%s' for writing", pac_file);
+ free(buf);
+ return -1;
+ }
+ fprintf(f, "%s", buf);
+ free(buf);
+ fclose(f);
+ }
wpa_printf(MSG_DEBUG, "EAP-FAST: wrote %d PAC entries into '%s'",
count, pac_file);
@@ -590,7 +681,7 @@ static void * eap_fast_init(struct eap_sm *sm)
* TODO: consider making this configurable */
tls_connection_enable_workaround(sm->ssl_ctx, data->ssl.conn);
- if (eap_fast_load_pac(data, config->pac_file) < 0) {
+ if (eap_fast_load_pac(sm, data, config->pac_file) < 0) {
eap_fast_deinit(sm, data);
return NULL;
}
@@ -632,7 +723,7 @@ static void eap_fast_deinit(struct eap_sm *sm, void *priv)
static int eap_fast_encrypt(struct eap_sm *sm, struct eap_fast_data *data,
- int id, u8 *plain, size_t plain_len,
+ int id, const u8 *plain, size_t plain_len,
u8 **out_data, size_t *out_len)
{
int res;
@@ -799,32 +890,37 @@ static u8 * eap_fast_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
char *label, size_t len)
{
struct tls_keys keys;
- u8 *random;
+ u8 *rnd;
u8 *out;
+ int block_size;
if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
return NULL;
- out = malloc(len);
- random = malloc(keys.client_random_len + keys.server_random_len);
- if (out == NULL || random == NULL) {
+ block_size = tls_connection_get_keyblock_size(sm->ssl_ctx, data->conn);
+ if (block_size < 0)
+ return NULL;
+ out = malloc(block_size + len);
+ rnd = malloc(keys.client_random_len + keys.server_random_len);
+ if (out == NULL || rnd == NULL) {
free(out);
- free(random);
+ free(rnd);
return NULL;
}
- memcpy(random, keys.server_random, keys.server_random_len);
- memcpy(random + keys.server_random_len, keys.client_random,
+ memcpy(rnd, keys.server_random, keys.server_random_len);
+ memcpy(rnd + keys.server_random_len, keys.client_random,
keys.client_random_len);
wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: master_secret for key "
"expansion", keys.master_key, keys.master_key_len);
if (tls_prf(keys.master_key, keys.master_key_len,
- label, random, keys.client_random_len +
- keys.server_random_len, out, len)) {
- free(random);
+ label, rnd, keys.client_random_len +
+ keys.server_random_len, out, block_size + len)) {
+ free(rnd);
free(out);
return NULL;
}
- free(random);
+ free(rnd);
+ memmove(out, out + block_size, len);
return out;
}
@@ -836,6 +932,11 @@ static void eap_fast_derive_key_auth(struct eap_sm *sm,
data->key_block_a = (struct eap_fast_key_block_auth *)
eap_fast_derive_key(sm, &data->ssl, "key expansion",
sizeof(*data->key_block_a));
+ if (data->key_block_a == NULL) {
+ wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive "
+ "session_key_seed");
+ return;
+ }
wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: session_key_seed",
data->key_block_a->session_key_seed,
sizeof(data->key_block_a->session_key_seed));
@@ -878,7 +979,7 @@ static void eap_fast_derive_keys(struct eap_sm *sm, struct eap_fast_data *data)
static int eap_fast_phase2_request(struct eap_sm *sm,
struct eap_fast_data *data,
struct eap_method_ret *ret,
- struct eap_hdr *req,
+ const struct eap_hdr *req,
struct eap_hdr *hdr,
u8 **resp, size_t *resp_len)
{
@@ -1333,7 +1434,7 @@ static u8 * eap_fast_process_pac(struct eap_sm *sm, struct eap_fast_data *data,
}
eap_fast_add_pac(data, &entry);
- eap_fast_save_pac(data, config->pac_file);
+ eap_fast_save_pac(sm, data, config->pac_file);
if (data->provisioning) {
/* EAP-FAST provisioning does not provide keying material and
@@ -1356,12 +1457,13 @@ static u8 * eap_fast_process_pac(struct eap_sm *sm, struct eap_fast_data *data,
static int eap_fast_decrypt(struct eap_sm *sm, struct eap_fast_data *data,
- struct eap_method_ret *ret, struct eap_hdr *req,
- u8 *in_data, size_t in_len,
+ struct eap_method_ret *ret,
+ const struct eap_hdr *req,
+ const u8 *in_data, size_t in_len,
u8 **out_data, size_t *out_len)
{
u8 *in_decrypted, *pos, *end;
- int buf_len, len_decrypted, len, res;
+ int buf_len, len_decrypted, len;
struct eap_hdr *hdr;
u8 *resp = NULL;
size_t resp_len;
@@ -1371,13 +1473,17 @@ static int eap_fast_decrypt(struct eap_sm *sm, struct eap_fast_data *data,
int iresult = 0, result = 0;
struct eap_tlv_crypto_binding__tlv *crypto_binding = NULL;
size_t crypto_binding_len = 0;
+ const u8 *msg;
+ size_t msg_len;
+ int need_more_input;
wpa_printf(MSG_DEBUG, "EAP-FAST: received %lu bytes encrypted data for"
" Phase 2", (unsigned long) in_len);
- res = eap_tls_data_reassemble(sm, &data->ssl, &in_data, &in_len);
- if (res < 0 || res == 1)
- return res;
+ msg = eap_tls_data_reassemble(sm, &data->ssl, in_data, in_len,
+ &msg_len, &need_more_input);
+ if (msg == NULL)
+ return need_more_input ? 1 : -1;
buf_len = in_len;
if (data->ssl.tls_in_total > buf_len)
@@ -1393,7 +1499,7 @@ static int eap_fast_decrypt(struct eap_sm *sm, struct eap_fast_data *data,
}
len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
- in_data, in_len,
+ msg, msg_len,
in_decrypted, buf_len);
free(data->ssl.tls_in);
data->ssl.tls_in = NULL;
@@ -1417,11 +1523,12 @@ static int eap_fast_decrypt(struct eap_sm *sm, struct eap_fast_data *data,
pos = in_decrypted;
end = in_decrypted + len_decrypted;
- while (pos < end) {
+ while (pos + 4 < end) {
mandatory = pos[0] & 0x80;
- tlv_type = ((pos[0] & 0x3f) << 8) | pos[1];
- len = (pos[2] << 8) | pos[3];
- pos += 4;
+ tlv_type = WPA_GET_BE16(pos) & 0x3fff;
+ pos += 2;
+ len = WPA_GET_BE16(pos);
+ pos += 2;
if (pos + len > end) {
free(in_decrypted);
wpa_printf(MSG_INFO, "EAP-FAST: TLV overflow");
@@ -1447,7 +1554,7 @@ static int eap_fast_decrypt(struct eap_sm *sm, struct eap_fast_data *data,
result = EAP_TLV_RESULT_FAILURE;
break;
}
- result = (pos[0] << 16) | pos[1];
+ result = WPA_GET_BE16(pos);
if (result != EAP_TLV_RESULT_SUCCESS &&
result != EAP_TLV_RESULT_FAILURE) {
wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown "
@@ -1467,7 +1574,7 @@ static int eap_fast_decrypt(struct eap_sm *sm, struct eap_fast_data *data,
iresult = EAP_TLV_RESULT_FAILURE;
break;
}
- iresult = (pos[0] << 16) | pos[1];
+ iresult = WPA_GET_BE16(pos);
if (iresult != EAP_TLV_RESULT_SUCCESS &&
iresult != EAP_TLV_RESULT_FAILURE) {
wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown "
@@ -1584,7 +1691,7 @@ static int eap_fast_decrypt(struct eap_sm *sm, struct eap_fast_data *data,
if (!resp && pac && result != EAP_TLV_RESULT_SUCCESS) {
wpa_printf(MSG_DEBUG, "EAP-FAST: PAC TLV without Result TLV "
- "acnowledging success");
+ "acknowledging success");
resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0,
&resp_len);
if (!resp) {
@@ -1607,7 +1714,7 @@ static int eap_fast_decrypt(struct eap_sm *sm, struct eap_fast_data *data,
if (resp == NULL) {
wpa_printf(MSG_DEBUG, "EAP-FAST: No recognized TLVs - send "
"empty response packet");
- resp = malloc(0);
+ resp = malloc(1);
if (resp == NULL)
return 0;
resp_len = 0;
@@ -1628,65 +1735,25 @@ static int eap_fast_decrypt(struct eap_sm *sm, struct eap_fast_data *data,
static u8 * eap_fast_process(struct eap_sm *sm, void *priv,
struct eap_method_ret *ret,
- u8 *reqData, size_t reqDataLen,
+ const u8 *reqData, size_t reqDataLen,
size_t *respDataLen)
{
- struct eap_hdr *req;
- int left, res;
- unsigned int tls_msg_len;
- u8 flags, *pos, *resp, id;
+ const struct eap_hdr *req;
+ size_t left;
+ int res;
+ u8 flags, *resp, id;
+ const u8 *pos;
struct eap_fast_data *data = priv;
- if (tls_get_errors(sm->ssl_ctx)) {
- wpa_printf(MSG_INFO, "EAP-FAST: TLS errors detected");
- ret->ignore = TRUE;
- return NULL;
- }
-
- req = (struct eap_hdr *) reqData;
- pos = (u8 *) (req + 1);
- if (reqDataLen < sizeof(*req) + 2 || *pos != EAP_TYPE_FAST ||
- (left = host_to_be16(req->length)) > reqDataLen) {
- wpa_printf(MSG_INFO, "EAP-FAST: Invalid frame");
- ret->ignore = TRUE;
+ pos = eap_tls_process_init(sm, &data->ssl, EAP_TYPE_FAST, ret,
+ reqData, reqDataLen, &left, &flags);
+ if (pos == NULL)
return NULL;
- }
- left -= sizeof(struct eap_hdr);
+ req = (const struct eap_hdr *) reqData;
id = req->identifier;
- pos++;
- flags = *pos++;
- left -= 2;
- wpa_printf(MSG_DEBUG, "EAP-FAST: Received packet(len=%lu) - "
- "Flags 0x%02x", (unsigned long) reqDataLen, flags);
- if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
- if (left < 4) {
- wpa_printf(MSG_INFO, "EAP-FAST: Short frame with TLS "
- "length");
- ret->ignore = TRUE;
- return NULL;
- }
- tls_msg_len = (pos[0] << 24) | (pos[1] << 16) | (pos[2] << 8) |
- pos[3];
- wpa_printf(MSG_DEBUG, "EAP-FAST: TLS Message Length: %d",
- tls_msg_len);
- if (data->ssl.tls_in_left == 0) {
- data->ssl.tls_in_total = tls_msg_len;
- data->ssl.tls_in_left = tls_msg_len;
- free(data->ssl.tls_in);
- data->ssl.tls_in = NULL;
- data->ssl.tls_in_len = 0;
- }
- pos += 4;
- left -= 4;
- }
-
- ret->ignore = FALSE;
- ret->methodState = METHOD_CONT;
- ret->decision = DECISION_FAIL;
- ret->allowNotifications = TRUE;
if (flags & EAP_TLS_FLAGS_START) {
- u8 *a_id;
+ const u8 *a_id;
size_t a_id_len;
struct pac_tlv_hdr *hdr;
diff --git a/contrib/wpa_supplicant/eap_gtc.c b/contrib/wpa_supplicant/eap_gtc.c
index 42a7a49acaf1..3665746e6fd1 100644
--- a/contrib/wpa_supplicant/eap_gtc.c
+++ b/contrib/wpa_supplicant/eap_gtc.c
@@ -53,29 +53,27 @@ static void eap_gtc_deinit(struct eap_sm *sm, void *priv)
static u8 * eap_gtc_process(struct eap_sm *sm, void *priv,
struct eap_method_ret *ret,
- u8 *reqData, size_t reqDataLen,
+ const u8 *reqData, size_t reqDataLen,
size_t *respDataLen)
{
struct eap_gtc_data *data = priv;
struct wpa_ssid *config = eap_get_config(sm);
- struct eap_hdr *req, *resp;
- u8 *pos, *password;
- size_t password_len, len, msg_len;
-
- req = (struct eap_hdr *) reqData;
- pos = (u8 *) (req + 1);
- if (reqDataLen < sizeof(*req) + 1 || *pos != EAP_TYPE_GTC ||
- (len = be_to_host16(req->length)) > reqDataLen) {
- wpa_printf(MSG_INFO, "EAP-GTC: Invalid frame");
+ const struct eap_hdr *req;
+ struct eap_hdr *resp;
+ const u8 *pos, *password;
+ u8 *rpos;
+ size_t password_len, len;
+
+ pos = eap_hdr_validate(EAP_TYPE_GTC, reqData, reqDataLen, &len);
+ if (pos == NULL) {
ret->ignore = TRUE;
return NULL;
}
- pos++;
- msg_len = len - sizeof(*req) - 1;
- wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Request message",
- pos, msg_len);
+ req = (const struct eap_hdr *) reqData;
+
+ wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Request message", pos, len);
if (data->prefix &&
- (msg_len < 10 || memcmp(pos, "CHALLENGE=", 10) != 0)) {
+ (len < 10 || memcmp(pos, "CHALLENGE=", 10) != 0)) {
wpa_printf(MSG_DEBUG, "EAP-GTC: Challenge did not start with "
"expected prefix");
@@ -90,16 +88,15 @@ static u8 * eap_gtc_process(struct eap_sm *sm, void *priv,
resp->code = EAP_CODE_RESPONSE;
resp->identifier = req->identifier;
resp->length = host_to_be16(*respDataLen);
- pos = (u8 *) (resp + 1);
- *pos++ = EAP_TYPE_GTC;
+ rpos = (u8 *) (resp + 1);
+ *rpos++ = EAP_TYPE_GTC;
return (u8 *) resp;
}
if (config == NULL ||
(config->password == NULL && config->otp == NULL)) {
wpa_printf(MSG_INFO, "EAP-GTC: Password not configured");
- eap_sm_request_otp(sm, config, (char *) pos,
- len - sizeof(*req) - 1);
+ eap_sm_request_otp(sm, config, (const char *) pos, len);
ret->ignore = TRUE;
return NULL;
}
@@ -128,16 +125,16 @@ static u8 * eap_gtc_process(struct eap_sm *sm, void *priv,
resp->code = EAP_CODE_RESPONSE;
resp->identifier = req->identifier;
resp->length = host_to_be16(*respDataLen);
- pos = (u8 *) (resp + 1);
- *pos++ = EAP_TYPE_GTC;
+ rpos = (u8 *) (resp + 1);
+ *rpos++ = EAP_TYPE_GTC;
if (data->prefix) {
- memcpy(pos, "RESPONSE=", 9);
- pos += 9;
- memcpy(pos, config->identity, config->identity_len);
- pos += config->identity_len;
- *pos++ = '\0';
+ memcpy(rpos, "RESPONSE=", 9);
+ rpos += 9;
+ memcpy(rpos, config->identity, config->identity_len);
+ rpos += config->identity_len;
+ *rpos++ = '\0';
}
- memcpy(pos, password, password_len);
+ memcpy(rpos, password, password_len);
wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response",
(u8 *) (resp + 1) + 1,
*respDataLen - sizeof(struct eap_hdr) - 1);
diff --git a/contrib/wpa_supplicant/eap_i.h b/contrib/wpa_supplicant/eap_i.h
index c71981255783..d1345489339e 100644
--- a/contrib/wpa_supplicant/eap_i.h
+++ b/contrib/wpa_supplicant/eap_i.h
@@ -1,9 +1,23 @@
+/*
+ * WPA Supplicant / EAP state machines internal structures (RFC 4137)
+ * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
#ifndef EAP_I_H
#define EAP_I_H
#include "eap.h"
-/* draft-ietf-eap-statemachine-05.pdf - Peer state machine */
+/* RFC 4137 - EAP Peer state machine */
typedef enum {
DECISION_FAIL, DECISION_COND_SUCC, DECISION_UNCOND_SUCC
@@ -13,37 +27,190 @@ typedef enum {
METHOD_NONE, METHOD_INIT, METHOD_CONT, METHOD_MAY_CONT, METHOD_DONE
} EapMethodState;
+/**
+ * struct eap_method_ret - EAP return values from struct eap_method::process()
+ *
+ * These structure contains OUT variables for the interface between peer state
+ * machine and methods (RFC 4137, Sect. 4.2). eapRespData will be returned as
+ * the return value of struct eap_method::process() so it is not included in
+ * this structure.
+ */
struct eap_method_ret {
+ /**
+ * ignore - Whether method decided to drop the current packed (OUT)
+ */
Boolean ignore;
+
+ /**
+ * methodState - Method-specific state (IN/OUT)
+ */
EapMethodState methodState;
+
+ /**
+ * decision - Authentication decision (OUT)
+ */
EapDecision decision;
+
+ /**
+ * allowNotifications - Whether method allows notifications (OUT)
+ */
Boolean allowNotifications;
};
+/**
+ * struct eap_method - EAP method interface
+ * This structure defines the EAP method interface. Each method will need to
+ * register its own EAP type, EAP name, and set of function pointers for method
+ * specific operations. This interface is based on section 4.4 of RFC 4137.
+ */
struct eap_method {
+ /**
+ * method - EAP type number (EAP_TYPE_*)
+ */
EapType method;
+
+ /**
+ * name - Name of the method (e.g., "TLS")
+ */
const char *name;
+ /**
+ * init - Initialize an EAP method
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * Returns: Pointer to allocated private data, or %NULL on failure
+ *
+ * This function is used to initialize the EAP method explicitly
+ * instead of using METHOD_INIT state as specific in RFC 4137. The
+ * method is expected to initialize it method-specific state and return
+ * a pointer that will be used as the priv argument to other calls.
+ */
void * (*init)(struct eap_sm *sm);
+
+ /**
+ * deinit - Deinitialize an EAP method
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @priv: Pointer to private EAP method data from eap_method::init()
+ *
+ * Deinitialize the EAP method and free any allocated private data.
+ */
void (*deinit)(struct eap_sm *sm, void *priv);
+
+ /**
+ * process - Process an EAP request
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @priv: Pointer to private EAP method data from eap_method::init()
+ * @ret: Return values from EAP request validation and processing
+ * @reqData: EAP request to be processed (eapReqData)
+ * @reqDataLen: Length of the EAP request
+ * @respDataLen: Length of the returned EAP response
+ * Returns: Pointer to allocated EAP response packet (eapRespData)
+ *
+ * This function is a combination of m.check(), m.process(), and
+ * m.buildResp() procedures defined in section 4.4 of RFC 4137 In other
+ * words, this function validates the incoming request, processes it,
+ * and build a response packet. m.check() and m.process() return values
+ * are returned through struct eap_method_ret *ret variable. Caller is
+ * responsible for freeing the returned EAP response packet.
+ */
u8 * (*process)(struct eap_sm *sm, void *priv,
struct eap_method_ret *ret,
- u8 *reqData, size_t reqDataLen,
+ const u8 *reqData, size_t reqDataLen,
size_t *respDataLen);
+
+ /**
+ * isKeyAvailable - Find out whether EAP method has keying material
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @priv: Pointer to private EAP method data from eap_method::init()
+ * Returns: %TRUE if key material (eapKeyData) is available
+ */
Boolean (*isKeyAvailable)(struct eap_sm *sm, void *priv);
+
+ /**
+ * getKey - Get EAP method specific keying material (eapKeyData)
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @priv: Pointer to private EAP method data from eap_method::init()
+ * @len: Pointer to variable to store key length (eapKeyDataLen)
+ * Returns: Keying material (eapKeyData) or %NULL if not available
+ *
+ * This function can be used to get the keying material from the EAP
+ * method. The key may already be stored in the method-specific private
+ * data or this function may derive the key.
+ */
u8 * (*getKey)(struct eap_sm *sm, void *priv, size_t *len);
+
+ /**
+ * get_status - Get EAP method status
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @priv: Pointer to private EAP method data from eap_method::init()
+ * @buf: Buffer for status information
+ * @buflen: Maximum buffer length
+ * @verbose: Whether to include verbose status information
+ * Returns: Number of bytes written to buf
+ *
+ * Query EAP method for status information. This function fills in a
+ * text area with current status information from the EAP method. If
+ * the buffer (buf) is not large enough, status information will be
+ * truncated to fit the buffer.
+ */
int (*get_status)(struct eap_sm *sm, void *priv, char *buf,
size_t buflen, int verbose);
- /* Optional handlers for fast re-authentication */
+ /**
+ * has_reauth_data - Whether method is ready for fast reauthentication
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @priv: Pointer to private EAP method data from eap_method::init()
+ * Returns: %TRUE or %FALSE based on whether fast reauthentication is
+ * possible
+ *
+ * This function is an optional handler that only EAP methods
+ * supporting fast re-authentication need to implement.
+ */
Boolean (*has_reauth_data)(struct eap_sm *sm, void *priv);
+
+ /**
+ * deinit_for_reauth - Release data that is not needed for fast re-auth
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @priv: Pointer to private EAP method data from eap_method::init()
+ *
+ * This function is an optional handler that only EAP methods
+ * supporting fast re-authentication need to implement. This is called
+ * when authentication has been completed and EAP state machine is
+ * requesting that enough state information is maintained for fast
+ * re-authentication
+ */
void (*deinit_for_reauth)(struct eap_sm *sm, void *priv);
+
+ /**
+ * init_for_reauth - Prepare for start of fast re-authentication
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @priv: Pointer to private EAP method data from eap_method::init()
+ *
+ * This function is an optional handler that only EAP methods
+ * supporting fast re-authentication need to implement. This is called
+ * when EAP authentication is started and EAP state machine is
+ * requesting fast re-authentication to be used.
+ */
void * (*init_for_reauth)(struct eap_sm *sm, void *priv);
+
+ /**
+ * get_identity - Get method specific identity for re-authentication
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @priv: Pointer to private EAP method data from eap_method::init()
+ * @len: Length of the returned identity
+ * Returns: Pointer to the method specific identity or %NULL if default
+ * identity is to be used
+ *
+ * This function is an optional handler that only EAP methods
+ * that use method specific identity need to implement.
+ */
const u8 * (*get_identity)(struct eap_sm *sm, void *priv, size_t *len);
};
+/**
+ * struct eap_sm - EAP state machine data
+ */
struct eap_sm {
enum {
EAP_INITIALIZE, EAP_DISABLED, EAP_IDLE, EAP_RECEIVED,
@@ -76,7 +243,7 @@ struct eap_sm {
u8 *eapKeyData; /* peer to lower layer */
size_t eapKeyDataLen; /* peer to lower layer */
const struct eap_method *m; /* selected EAP method */
- /* not defined in draft-ietf-eap-statemachine-02 */
+ /* not defined in RFC 4137 */
Boolean changed;
void *eapol_ctx;
struct eapol_callbacks *eapol_cb;
@@ -101,6 +268,13 @@ struct eap_sm {
u8 *peer_challenge, *auth_challenge;
int num_rounds;
+ int force_disabled;
};
+const u8 * eap_hdr_validate(EapType eap_type, const u8 *msg, size_t msglen,
+ size_t *plen);
+void eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob);
+const struct wpa_config_blob *
+eap_get_config_blob(struct eap_sm *sm, const char *name);
+
#endif /* EAP_I_H */
diff --git a/contrib/wpa_supplicant/eap_leap.c b/contrib/wpa_supplicant/eap_leap.c
index 6409a6855f92..d0e5aab1d70f 100644
--- a/contrib/wpa_supplicant/eap_leap.c
+++ b/contrib/wpa_supplicant/eap_leap.c
@@ -21,7 +21,7 @@
#include "wpa_supplicant.h"
#include "config_ssid.h"
#include "ms_funcs.h"
-#include "md5.h"
+#include "crypto.h"
#define LEAP_VERSION 1
#define LEAP_CHALLENGE_LEN 8
@@ -68,18 +68,20 @@ static void eap_leap_deinit(struct eap_sm *sm, void *priv)
static u8 * eap_leap_process_request(struct eap_sm *sm, void *priv,
struct eap_method_ret *ret,
- u8 *reqData, size_t reqDataLen,
+ const u8 *reqData, size_t reqDataLen,
size_t *respDataLen)
{
struct eap_leap_data *data = priv;
struct wpa_ssid *config = eap_get_config(sm);
- struct eap_hdr *req, *resp;
- u8 *pos, *challenge, challenge_len;
+ const struct eap_hdr *req;
+ struct eap_hdr *resp;
+ const u8 *pos, *challenge;
+ u8 challenge_len, *rpos;
wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Request");
- req = (struct eap_hdr *) reqData;
- pos = (u8 *) (req + 1);
+ req = (const struct eap_hdr *) reqData;
+ pos = (const u8 *) (req + 1);
if (reqDataLen < sizeof(*req) + 4 || *pos != EAP_TYPE_LEAP) {
wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Request frame");
ret->ignore = TRUE;
@@ -121,17 +123,18 @@ static u8 * eap_leap_process_request(struct eap_sm *sm, void *priv,
resp->code = EAP_CODE_RESPONSE;
resp->identifier = req->identifier;
resp->length = host_to_be16(*respDataLen);
- pos = (u8 *) (resp + 1);
- *pos++ = EAP_TYPE_LEAP;
- *pos++ = LEAP_VERSION;
- *pos++ = 0; /* unused */
- *pos++ = LEAP_RESPONSE_LEN;
+ rpos = (u8 *) (resp + 1);
+ *rpos++ = EAP_TYPE_LEAP;
+ *rpos++ = LEAP_VERSION;
+ *rpos++ = 0; /* unused */
+ *rpos++ = LEAP_RESPONSE_LEN;
nt_challenge_response(challenge,
- config->password, config->password_len, pos);
- memcpy(data->peer_response, pos, LEAP_RESPONSE_LEN);
- wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Response", pos, LEAP_RESPONSE_LEN);
- pos += LEAP_RESPONSE_LEN;
- memcpy(pos, config->identity, config->identity_len);
+ config->password, config->password_len, rpos);
+ memcpy(data->peer_response, rpos, LEAP_RESPONSE_LEN);
+ wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Response",
+ rpos, LEAP_RESPONSE_LEN);
+ rpos += LEAP_RESPONSE_LEN;
+ memcpy(rpos, config->identity, config->identity_len);
data->state = LEAP_WAIT_SUCCESS;
@@ -141,12 +144,13 @@ static u8 * eap_leap_process_request(struct eap_sm *sm, void *priv,
static u8 * eap_leap_process_success(struct eap_sm *sm, void *priv,
struct eap_method_ret *ret,
- u8 *reqData, size_t reqDataLen,
+ const u8 *reqData, size_t reqDataLen,
size_t *respDataLen)
{
struct eap_leap_data *data = priv;
struct wpa_ssid *config = eap_get_config(sm);
- struct eap_hdr *req, *resp;
+ const struct eap_hdr *req;
+ struct eap_hdr *resp;
u8 *pos;
wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Success");
@@ -158,7 +162,7 @@ static u8 * eap_leap_process_success(struct eap_sm *sm, void *priv,
return NULL;
}
- req = (struct eap_hdr *) reqData;
+ req = (const struct eap_hdr *) reqData;
*respDataLen = sizeof(struct eap_hdr) + 1 + 3 + LEAP_CHALLENGE_LEN +
config->identity_len;
@@ -194,19 +198,20 @@ static u8 * eap_leap_process_success(struct eap_sm *sm, void *priv,
static u8 * eap_leap_process_response(struct eap_sm *sm, void *priv,
struct eap_method_ret *ret,
- u8 *reqData, size_t reqDataLen,
+ const u8 *reqData, size_t reqDataLen,
size_t *respDataLen)
{
struct eap_leap_data *data = priv;
struct wpa_ssid *config = eap_get_config(sm);
- struct eap_hdr *resp;
- u8 *pos, response_len, pw_hash[16], pw_hash_hash[16],
+ const struct eap_hdr *resp;
+ const u8 *pos;
+ u8 response_len, pw_hash[16], pw_hash_hash[16],
expected[LEAP_RESPONSE_LEN];
wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Response");
- resp = (struct eap_hdr *) reqData;
- pos = (u8 *) (resp + 1);
+ resp = (const struct eap_hdr *) reqData;
+ pos = (const u8 *) (resp + 1);
if (reqDataLen < sizeof(*resp) + 4 || *pos != EAP_TYPE_LEAP) {
wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Response frame");
ret->ignore = TRUE;
@@ -270,11 +275,11 @@ static u8 * eap_leap_process_response(struct eap_sm *sm, void *priv,
static u8 * eap_leap_process(struct eap_sm *sm, void *priv,
struct eap_method_ret *ret,
- u8 *reqData, size_t reqDataLen,
+ const u8 *reqData, size_t reqDataLen,
size_t *respDataLen)
{
struct wpa_ssid *config = eap_get_config(sm);
- struct eap_hdr *eap;
+ const struct eap_hdr *eap;
size_t len;
if (config == NULL || config->password == NULL) {
@@ -284,7 +289,7 @@ static u8 * eap_leap_process(struct eap_sm *sm, void *priv,
return NULL;
}
- eap = (struct eap_hdr *) reqData;
+ eap = (const struct eap_hdr *) reqData;
if (reqDataLen < sizeof(*eap) ||
(len = be_to_host16(eap->length)) > reqDataLen) {
@@ -295,7 +300,7 @@ static u8 * eap_leap_process(struct eap_sm *sm, void *priv,
ret->ignore = FALSE;
ret->allowNotifications = TRUE;
- ret->methodState = METHOD_CONT;
+ ret->methodState = METHOD_MAY_CONT;
ret->decision = DECISION_FAIL;
sm->leap_done = FALSE;
@@ -331,7 +336,8 @@ static u8 * eap_leap_getKey(struct eap_sm *sm, void *priv, size_t *len)
struct eap_leap_data *data = priv;
struct wpa_ssid *config = eap_get_config(sm);
u8 *key, pw_hash_hash[16], pw_hash[16];
- MD5_CTX context;
+ const u8 *addr[5];
+ size_t elen[5];