Import wpa_supplicant/hostapd commit 9d9b42306541

Start tracking upstream development of hostapd and wpa_supplicant more
closely.  The last upstream release is from August 2019.  Keeping up
with upstream development will make importing releases less exciting.

Discussed with: cy
Sponsored by:	Rubicon Communications, LLC ("Netgate")
This commit is contained in:
Philip Paeps 2021-03-19 11:13:37 +08:00
parent 9e114a3b99
commit f8262d7d8a
1011 changed files with 241297 additions and 22009 deletions

8
.gitignore vendored Normal file
View file

@ -0,0 +1,8 @@
*.pyc
*~
tests/hwsim/logs
tests/remote/logs
wpaspy/build
**/parallel-vm.log
tags
build/

10
Android.mk Normal file
View file

@ -0,0 +1,10 @@
LOCAL_PATH:= $(call my-dir)
ifneq ($(filter VER_0_8_X VER_2_1_DEVEL,$(WPA_SUPPLICANT_VERSION)),)
# The order of the 2 Android.mks does matter!
# TODO: Clean up the Android.mks, reset all the temporary variables at the
# end of each Android.mk, so that one Android.mk doesn't depend on variables
# set up in the other Android.mk.
include $(LOCAL_PATH)/hostapd/Android.mk \
$(LOCAL_PATH)/wpa_supplicant/Android.mk
endif

View file

@ -56,6 +56,9 @@ In general, the best way of generating a suitable formatted patch file
is by committing the changes to a cloned git repository and using git
format-patch. The patch can then be sent, e.g., with git send-email.
A list of pending patches waiting for review is available in
Patchwork: https://patchwork.ozlabs.org/project/hostap/list/
History of license and contributions terms
------------------------------------------
@ -140,7 +143,7 @@ The license terms used for hostap.git files
Modified BSD license (no advertisement clause):
Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> and contributors
Copyright (c) 2002-2021, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
Redistribution and use in source and binary forms, with or without

47
build_release Executable file
View file

@ -0,0 +1,47 @@
#!/bin/sh
set -e
if [ -z "$1" ]; then
echo "build_release <version>"
exit 1
fi
TMP=tmp.build_release
RELDIR=`pwd`/Release
VER=$1
NOW=`date +%Y-%m-%d`
echo "Version: $VER - $NOW"
DATEw=`head -n 3 wpa_supplicant/ChangeLog | tail -n 1 | sed "s/ .*//"`
DATEh=`head -n 3 hostapd/ChangeLog | tail -n 1 | sed "s/ .*//"`
if [ "$DATEw" != "$NOW" -o "$DATEh" != "$NOW" ]; then
echo "NOTE! Date mismatch in ChangeLog: wpa_supplicant $DATEw hostapd $DATEh != $NOW"
fi
if [ -r $TMP ]; then
echo "Temporary directory '$TMP' exists. Remove it before running this."
exit 1
fi
mkdir $TMP
mkdir -p $RELDIR
git archive --format=tar --prefix=wpa-$VER/ HEAD \
README COPYING CONTRIBUTIONS src wpa_supplicant hostapd hs20 |
gzip > $RELDIR/wpa-$VER.tar.gz
git archive --format=tar --prefix=hostapd-$VER/ HEAD \
README COPYING CONTRIBUTIONS src hostapd |
gzip > $RELDIR/hostapd-$VER.tar.gz
git archive --format=tar --prefix=wpa_supplicant-$VER/ HEAD \
README COPYING CONTRIBUTIONS src wpa_supplicant hs20/client |
tar --directory=$TMP -xf -
cd $TMP
make -C wpa_supplicant-$VER/wpa_supplicant/doc/docbook man
rm -f wpa_supplicant-$VER/wpa_supplicant/doc/docbook/manpage.{links,refs}
tar czf $RELDIR/wpa_supplicant-$VER.tar.gz wpa_supplicant-$VER
cd ..
rm -r $TMP

14
doc/.gitignore vendored Normal file
View file

@ -0,0 +1,14 @@
doxygen.warnings
hostapd.eps
hostapd.png
html
latex
p2p_arch.eps
p2p_arch.png
p2p_arch2.eps
p2p_arch2.png
p2p_sm.eps
p2p_sm.png
wpa_supplicant.eps
wpa_supplicant.png
wpa_supplicant-devel.pdf

42
doc/Makefile Normal file
View file

@ -0,0 +1,42 @@
all: docs
%.eps: %.fig
fig2dev -L eps $*.fig $*.eps
%.png: %.fig
fig2dev -L png -m 3 $*.fig | pngtopnm | pnmscale 0.4 | pnmtopng \
> $*.png
%.png: %.dot
dot $*.dot -Tpng -o $*.png
%.eps: %.dot
dot $*.dot -Tps -o $*.eps
_wpa_supplicant.png: wpa_supplicant.png
cp $< $@
_wpa_supplicant.eps: wpa_supplicant.eps
cp $< $@
docs-pics: wpa_supplicant.png wpa_supplicant.eps hostapd.png hostapd.eps p2p_sm.png p2p_sm.eps p2p_arch.png p2p_arch.eps p2p_arch2.png p2p_arch2.eps _wpa_supplicant.png _wpa_supplicant.eps
docs: docs-pics
(cd ..; doxygen doc/doxygen.conf; cd doc)
$(MAKE) -C latex
cp latex/refman.pdf wpa_supplicant-devel.pdf
html: docs-pics
(cd ..; doxygen doc/doxygen.conf; cd doc)
clean:
rm -f *~
rm -f wpa_supplicant.eps wpa_supplicant.png
rm -f _wpa_supplicant.png _wpa_supplicant.eps
rm -f hostapd.eps hostapd.png
rm -f p2p_sm.eps p2p_sm.png
rm -f p2p_arch.eps p2p_arch.png
rm -f p2p_arch2.eps p2p_arch2.png
rm -f doxygen.warnings
rm -rf html latex
rm -f wpa_supplicant-devel.pdf

315
doc/code_structure.doxygen Normal file
View file

@ -0,0 +1,315 @@
/**
\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 tls_func "TLS library" |
\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 \ref driver.h and
all hardware/driver dependent functionality is implemented in
driver_*.c.
\section _wpa_supplicant_core wpa_supplicant core functionality
\ref wpa_supplicant.c
Program initialization, main control loop
\ref wpa_supplicant/main.c
main() for UNIX-like operating systems and MinGW (Windows); this
uses command line arguments to configure wpa_supplicant
\ref events.c
Driver event processing; \ref wpa_supplicant_event() and related functions
\ref wpa_supplicant_i.h
Internal definitions for wpa_supplicant core; should not be
included into independent modules
\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:
\ref eloop.c and \ref eloop.h
Event loop (select() loop with registerable timeouts, socket read
callbacks, and signal callbacks)
\ref common.c and \ref common.h
Common helper functions
\ref defs.h
Definitions shared by multiple files
\ref l2_packet.h, \ref l2_packet_linux.c, and \ref 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. \ref l2_packet_linux.c uses Linux
packet sockets and \ref l2_packet_pcap.c has a more portable version using
libpcap and libdnet.
\ref pcsc_funcs.c and \ref pcsc_funcs.h
Wrapper for PC/SC lite SIM and smart card readers
\ref 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
\ref version.h
Version number definitions
\section crypto_func Cryptographic functions
\ref md5.c and \ref md5.h
MD5 (replaced with a crypto library if TLS support is included)
HMAC-MD5 (keyed checksum for message authenticity validation)
\ref rc4.c and \ref rc4.h
RC4 (broadcast/default key encryption)
\ref sha1.c and \ref 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)
\ref sha256.c and \ref sha256.h
SHA-256 (replaced with a crypto library if TLS support is included)
\ref aes-wrap.c, \ref aes_wrap.h, \ref 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
\ref crypto.h
Definition of crypto library wrapper
\ref crypto_openssl.c
Wrapper functions for libcrypto (OpenSSL)
\ref crypto_internal.c
Wrapper functions for internal crypto implementation
\ref crypto_gnutls.c
Wrapper functions for libgcrypt (used by GnuTLS)
\ref ms_funcs.c and \ref ms_funcs.h
Helper functions for MSCHAPV2 and LEAP
\ref tls.h
Definition of TLS library wrapper
\ref tls_none.c
Dummy implementation of TLS library wrapper for cases where TLS
functionality is not included.
\ref tls_openssl.c
TLS library wrapper for openssl
\ref tls_internal.c
TLS library for internal TLS implementation
\ref tls_gnutls.c
TLS library wrapper for GnuTLS
\section tls_func TLS library
\ref asn1.c and \ref asn1.h
ASN.1 DER parsing
\ref bignum.c and \ref bignum.h
Big number math
\ref rsa.c and \ref rsa.h
RSA
\ref x509v3.c and \ref x509v3.h
X.509v3 certificate parsing and processing
\ref tlsv1_client.c, \ref tlsv1_client.h
TLSv1 client (RFC 2246)
\ref tlsv1_client_i.h
Internal structures for TLSv1 client
\ref tlsv1_client_read.c
TLSv1 client: read handshake messages
\ref tlsv1_client_write.c
TLSv1 client: write handshake messages
\ref tlsv1_common.c and \ref tlsv1_common.h
Common TLSv1 routines and definitions
\ref tlsv1_cred.c and \ref tlsv1_cred.h
TLSv1 credentials
\ref tlsv1_record.c and \ref tlsv1_record.h
TLSv1 record protocol
\section configuration Configuration
\ref config_ssid.h
Definition of per network configuration items
\ref config.h
Definition of the wpa_supplicant configuration
\ref config.c
Configuration parser and common functions
\ref wpa_supplicant/config_file.c
Configuration backend for text files (e.g., wpa_supplicant.conf)
\ref config_winreg.c
Configuration backend for Windows registry
\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.
\ref wpa_supplicant/ctrl_iface.c and \ref wpa_supplicant/ctrl_iface.h
wpa_supplicant-side of the control interface
\ref ctrl_iface_unix.c
UNIX domain sockets -based control interface backend
\ref ctrl_iface_udp.c
UDP sockets -based control interface backend
\ref ctrl_iface_named_pipe.c
Windows named pipes -based control interface backend
\ref wpa_ctrl.c and \ref wpa_ctrl.h
Library functions for external programs to provide access to the
wpa_supplicant control interface
\ref wpa_cli.c
Example program for using wpa_supplicant control interface
\section wpa_code WPA supplicant
\ref wpa.c and \ref wpa.h
WPA state machine and 4-Way/Group Key Handshake processing
\ref preauth.c and \ref preauth.h
PMKSA caching and pre-authentication (RSN/WPA2)
\ref wpa_i.h
Internal definitions for WPA code; not to be included to other modules.
\section eap_peer EAP peer
\ref eap_peer_module "EAP peer implementation" is a separate module that
can be used by other programs than just wpa_supplicant.
\ref eap.c and \ref eap.h
EAP state machine and method interface
\ref eap_defs.h
Common EAP definitions
\ref eap_i.h
Internal definitions for EAP state machine and EAP methods; not to be
included in other modules
\ref eap_sim_common.c and \ref eap_sim_common.h
Common code for EAP-SIM and EAP-AKA
\ref eap_tls_common.c and \ref eap_tls_common.h
Common code for EAP-PEAP, EAP-TTLS, and EAP-FAST
\ref eap_ttls.c and \ref eap_ttls.h
EAP-TTLS
\ref eap_pax.c, \ref eap_pax_common.h, \ref eap_pax_common.c
EAP-PAX
\ref eap_psk.c, \ref eap_psk_common.h, \ref eap_psk_common.c
EAP-PSK (note: this is not needed for WPA-PSK)
\ref eap_sake.c, \ref eap_sake_common.h, \ref eap_sake_common.c
EAP-SAKE
\ref eap_gpsk.c, \ref eap_gpsk_common.h, \ref eap_gpsk_common.c
EAP-GPSK
\ref eap_aka.c, \ref eap_fast.c, \ref eap_gtc.c, \ref eap_leap.c,
\ref eap_md5.c, \ref eap_mschapv2.c, \ref eap_otp.c, \ref eap_peap.c,
\ref eap_sim.c, \ref eap_tls.c
Other EAP method implementations
\section eapol_supp EAPOL supplicant
\ref eapol_supp_sm.c and \ref eapol_supp_sm.h
EAPOL supplicant state machine and IEEE 802.1X processing
\section win_port Windows port
\ref ndis_events.c
Code for receiving NdisMIndicateStatus() events and delivering them to
wpa_supplicant \ref driver_ndis.c in more easier to use form
\ref win_if_list.c
External program for listing current network interface
\section test_programs Test programs
\ref radius_client.c and \ref radius_client.h
RADIUS authentication client implementation for eapol_test
\ref radius.c and \ref radius.h
RADIUS message processing for eapol_test
\ref eapol_test.c
Standalone EAP testing tool with integrated RADIUS authentication
client
\ref preauth_test.c
Standalone RSN pre-authentication tool
\ref wpa_passphrase.c
WPA ASCII passphrase to PSK conversion
*/

1054
doc/ctrl_iface.doxygen Normal file

File diff suppressed because it is too large Load diff

2394
doc/dbus.doxygen Normal file

File diff suppressed because it is too large Load diff

90
doc/directories.doxygen Normal file
View file

@ -0,0 +1,90 @@
/**
\dir hostapd hostapd
hostapd-specific code for configuration, control interface, and AP
management.
\dir src/common Common functionality
This module includes IEEE 802.11, IEEE 802.1X, and WPA related
functionality that is shared between AP and station modes.
\dir src/crypto Cryptographical functionality and wrappers
This module defines crypto and tls interfaces to provide portability
layer for different crypto/TLS libraries. Wrappers for number of
libraries are also included here. In addition, internal implementation
of various crypto functions are provided as an alternative for an
external library and to extend some algorithms.
\dir src/drivers Driver wrappers
This directory includes the driver interface definition and all the
driver wrappers that can be used to interact with different drivers
without making rest of the software dependent on which particular
driver is used.
\dir src/eap_common Common EAP functionality for server and peer
\dir src/eap_peer EAP peer
\dir src/eap_server EAP server
\dir src/eapol_auth EAPOL authenticator
\dir src/eapol_supp EAPOL supplicant
\dir src/l2_packet Layer 2 packet interface
This module defines an interface for layer 2 (link layer) packet
sendinf and receiving. All the wrappers for supported mechanisms are
also included here. This is used to port packet access for new
operating systems without having to make rest of the source code
depend on which OS network stack is used.
\dir src/radius RADIUS
RADIUS module includes RADIUS message building and parsing
functionality and separate RADIUS client and server functions.
\dir src/rsn_supp IEEE 802.11 RSN and WPA supplicant
\dir src/tls Internal TLS server and client implementation
This module can be used as an alternative to using an external TLS
library.
\dir src/utils Utility functions
Independent set of helper functions that most other components
use. This includes portability wrappers and helpers for common tasks.
\dir src/wps Wi-Fi Protected Setup
This directory includes Wi-Fi Protected Setup functions for Registrar
(both internal in an AP and an External Registrar and
Enrollee. Minimal UPnP and HTTP functionality is also provided for the
functionality needed to implement Wi-Fi Protected Setup.
\dir wpa_supplicant wpa_supplicant
wpa_supplicant-specific code for configuration, control interface, and
client management.
*/

1547
doc/doxygen.conf Normal file

File diff suppressed because it is too large Load diff

180
doc/driver_wrapper.doxygen Normal file
View file

@ -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 \ref 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 \ref driver.h. These functions are registered by filling struct
\ref 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, \ref wpa_supplicant_event(), and its parameters are
documented in \ref driver.h. In addition, a pointer to the 'struct
\ref wpa_driver_ops' needs to be registered in \ref 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
\ref 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.,
\ref driver_hostap.c. These files need to define struct \ref wpa_driver_ops
entry that will be used in \ref wpa_supplicant.c when calling driver
functions. struct \ref wpa_driver_ops entries are registered in \ref 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. \ref driver_hostap.c and \ref driver_wext.c include a complete
implementation for Linux drivers that use wpa_supplicant-based control
of WPA IE and roaming. \ref driver_ndis.c (with help from \ref 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 (\ref 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
\ref 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
\ref driver.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 \ref driver.h (\ref wpa_supplicant_event() function
and enum \ref 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 larger 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)
*/

87
doc/eap.doxygen Normal file
View file

@ -0,0 +1,87 @@
/**
\page eap_peer_module EAP peer implementation
Extensible Authentication Protocol (EAP) is an authentication framework
defined in RFC 3748. 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., \ref 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 the build
(Makefile) and the EAP method registration list in the
\ref eap_peer_register_methods() function of \ref eap_methods.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 \ref eap_i.h. struct
\ref 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.
It is recommended that the EAP methods would use generic helper
functions, \ref eap_msg_alloc() and \ref eap_hdr_validate() when processing
messages. This allows code sharing and can avoid missing some of the
needed validation steps for received packets. In addition, these
functions make it easier to change between expanded and legacy EAP
header, if needed.
When adding an EAP method that uses a vendor specific EAP type
(Expanded Type as defined in RFC 3748, Chapter 5.7), the new method
must be registered by passing vendor id instead of EAP_VENDOR_IETF to
\ref eap_peer_method_alloc(). These methods must not try to emulate
expanded types by registering a legacy EAP method for type 254. See
\ref eap_vendor_test.c for an example of an EAP method implementation that
is implemented as an expanded type.
\section used_eap_library Using EAP implementation as a library
The Git repository has an eap_example directory that contains an
example showing how EAP peer and server code from wpa_supplicant and
hostapd can be used as a library. The example program initializes both
an EAP server and an EAP peer entities and then runs through an
EAP-PEAP/MSCHAPv2 authentication.
\ref eap_example_peer.c shows the initialization and glue code needed to
control the EAP peer implementation. \ref eap_example_server.c does the
same for EAP server. \ref eap_example.c is an example that ties in both the
EAP server and client parts to allow an EAP authentication to be
shown.
In this example, the EAP messages are passed between the server and
the peer are passed by direct function calls within the same process.
In practice, server and peer functionalities would likely reside in
separate devices and the EAP messages would be transmitted between the
devices based on an external protocol. For example, in IEEE 802.11
uses IEEE 802.1X EAPOL state machines to control the transmission of
EAP messages and WiMax supports optional PMK EAP authentication
mechanism that transmits EAP messages as defined in IEEE 802.16e.
The EAP library links in number of helper functions from \ref src/utils and
\ref src/crypto directories. Most of these are suitable as-is, but it may
be desirable to replace the debug output code in \ref src/utils/wpa_debug.c
by dropping this file from the library and re-implementing the
functions there in a way that better fits in with the main
application.
*/

56
doc/eap_server.doxygen Normal file
View file

@ -0,0 +1,56 @@
/**
\page eap_server_module EAP server implementation
Extensible Authentication Protocol (EAP) is an authentication framework
defined in RFC 3748. hostapd uses a separate code module for EAP server
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 server state
machine and methods. As such, this RFC provides useful information for
understanding the EAP server implementation in hostapd.
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_server_<name of the method>.c, e.g., \ref eap_server_md5.c. All EAP
methods use the same interface between the server 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 the build
(Makefile) and the EAP method registration list in the
\ref eap_server_register_methods() function of \ref eap_server_methods.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 \ref eap_i.h. struct
\ref 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.
It is recommended that the EAP methods would use generic helper
functions, \ref eap_msg_alloc() and \ref eap_hdr_validate() when processing
messages. This allows code sharing and can avoid missing some of the
needed validation steps for received packets. In addition, these
functions make it easier to change between expanded and legacy EAP
header, if needed.
When adding an EAP method that uses a vendor specific EAP type
(Expanded Type as defined in RFC 3748, Chapter 5.7), the new method
must be registered by passing vendor id instead of EAP_VENDOR_IETF to
\ref eap_server_method_alloc(). These methods must not try to emulate
expanded types by registering a legacy EAP method for type 254. See
\ref eap_server_vendor_test.c for an example of an EAP method implementation that
is implemented as an expanded type.
*/

264
doc/hostapd.fig Normal file
View file

@ -0,0 +1,264 @@
#FIG 3.2
Landscape
Center
Inches
Letter
100.00
Single
-2
1200 2
6 1875 4050 2925 4350
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
1875 4050 2925 4050 2925 4350 1875 4350 1875 4050
4 0 0 50 -1 0 12 0.0000 4 180 735 2025 4275 l2_packet\001
-6
6 4725 1200 5925 1500
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
4725 1200 5925 1200 5925 1500 4725 1500 4725 1200
4 0 0 50 -1 0 12 0.0000 4 135 1005 4800 1425 GUI frontend\001
-6
6 6000 2700 7200 3225
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
6000 2700 7200 2700 7200 3225 6000 3225 6000 2700
4 0 0 50 -1 0 12 0.0000 4 135 975 6075 2925 WPA/WPA2\001
4 0 0 50 -1 0 12 0.0000 4 135 1065 6075 3150 state machine\001
-6
6 6000 4950 7200 5475
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
6000 4950 7200 4950 7200 5475 6000 5475 6000 4950
4 0 0 50 -1 0 12 0.0000 4 135 360 6075 5175 EAP\001
4 0 0 50 -1 0 12 0.0000 4 135 1065 6075 5400 state machine\001
-6
6 4350 3900 5025 4425
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
4350 3900 5025 3900 5025 4425 4350 4425 4350 3900
4 0 0 50 -1 0 12 0.0000 4 105 420 4500 4125 event\001
4 0 0 50 -1 0 12 0.0000 4 180 315 4500 4350 loop\001
-6
6 4275 2550 5100 2850
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
4275 2550 5100 2550 5100 2850 4275 2850 4275 2550
4 0 0 50 -1 0 12 0.0000 4 135 450 4425 2775 ctrl i/f\001
-6
6 6000 3900 7200 4425
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
6000 3900 7200 3900 7200 4425 6000 4425 6000 3900
4 0 0 50 -1 0 12 0.0000 4 135 600 6075 4125 EAPOL\001
4 0 0 50 -1 0 12 0.0000 4 135 1065 6075 4350 state machine\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
6 3450 1200 4575 1500
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
3450 1200 4575 1200 4575 1500 3450 1500 3450 1200
4 0 0 50 -1 0 12 0.0000 4 180 870 3600 1425 hostapd_cli\001
-6
6 3525 7800 5775 8100
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
3525 7800 5775 7800 5775 8100 3525 8100 3525 7800
4 0 0 50 -1 0 12 0.0000 4 135 2145 3600 8025 kernel network device driver\001
-6
6 4275 6000 5100 6300
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
4275 6000 5100 6000 5100 6300 4275 6300 4275 6000
4 0 0 50 -1 0 12 0.0000 4 135 630 4350 6225 driver i/f\001
-6
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
4 0 0 50 -1 0 12 0.0000 4 135 735 8250 4950 EAP-TLS\001
-6
6 9300 4725 10350 5025
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
9300 4725 10350 4725 10350 5025 9300 5025 9300 4725
4 0 0 50 -1 0 12 0.0000 4 135 810 9375 4950 EAP-MD5\001
-6
6 8175 5100 9225 5400
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
8175 5100 9225 5100 9225 5400 8175 5400 8175 5100
4 0 0 50 -1 0 12 0.0000 4 135 885 8250 5325 EAP-PEAP\001
-6
6 9300 5100 10350 5400
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
9300 5100 10350 5100 10350 5400 9300 5400 9300 5100
4 0 0 50 -1 0 12 0.0000 4 135 840 9375 5325 EAP-TTLS\001
-6
6 8175 5475 9225 5775
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
8175 5475 9225 5475 9225 5775 8175 5775 8175 5475
4 0 0 50 -1 0 12 0.0000 4 135 780 8250 5700 EAP-GTC\001
-6
6 8175 5850 9225 6150
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
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 6225 9225 6525
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
8175 6225 9225 6225 9225 6525 8175 6525 8175 6225
4 0 0 50 -1 0 12 0.0000 4 135 765 8250 6450 EAP-PSK\001
-6
6 9300 5850 10350 6150
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
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 9300 5475 10350 5775
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
9300 5475 10350 5475 10350 5775 9300 5775 9300 5475
4 0 0 50 -1 0 12 0.0000 4 135 795 9375 5700 EAP-PAX\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 8700 3450 9375 3750
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
8700 3450 9375 3450 9375 3750 8700 3750 8700 3450
4 0 0 50 -1 0 12 0.0000 4 150 480 8775 3675 crypto\001
-6
6 9600 3450 10275 3750
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
9600 3450 10275 3450 10275 3750 9600 3750 9600 3450
4 0 0 50 -1 0 12 0.0000 4 135 315 9750 3675 TLS\001
-6
6 6000 5775 7200 6300
6 6000 5775 7200 6300
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
6000 5775 7200 5775 7200 6300 6000 6300 6000 5775
4 0 0 50 -1 0 12 0.0000 4 135 690 6075 6000 RADIUS\001
-6
4 0 0 50 -1 0 12 0.0000 4 90 480 6075 6225 server\001
-6
6 8100 2250 8925 2775
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
8100 2250 8925 2250 8925 2775 8100 2775 8100 2250
4 0 0 50 -1 0 12 0.0000 4 135 690 8175 2475 RADIUS\001
4 0 0 50 -1 0 12 0.0000 4 135 420 8175 2700 client\001
-6
6 3150 5475 4425 5775
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
3150 5475 4425 5475 4425 5775 3150 5775 3150 5475
4 0 0 50 -1 0 12 0.0000 4 135 990 3300 5700 driver events\001
-6
6 1950 5550 2625 6075
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
1950 5550 2625 5550 2625 6075 1950 6075 1950 5550
4 0 0 50 -1 0 12 0.0000 4 135 540 2025 5775 Station\001
4 0 0 50 -1 0 12 0.0000 4 135 375 2025 6000 table\001
-6
6 1875 4725 2925 5250
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
1875 4725 2925 4725 2925 5250 1875 5250 1875 4725
4 0 0 50 -1 0 12 0.0000 4 135 960 1950 4950 IEEE 802.11\001
4 0 0 50 -1 0 12 0.0000 4 135 555 1950 5175 MLME\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
4500 2550 3900 1500
2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
4800 2550 5400 1500
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
2925 4200 4350 4200
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
5025 3900 6000 3000
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
5025 4200 6000 4200
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
4650 6000 4650 4425
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
6600 4425 6600 4950
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
6600 3225 6600 3900
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
7200 5250 8100 5250
2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2
9075 4425 9075 3750
2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2
7200 3000 8700 3525
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
4650 3900 4650 2850
2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2
7200 4125 8700 3675
2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2
6000 4350 5025 6000
2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2
6000 3150 4875 6000
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
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 3750
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 5475
2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
2250 7200 4200 7800
2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
7200 7200 5100 7800
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
2775 6900 3675 6900 3675 7200 2775 7200 2775 6900
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
3750 6900 4650 6900 4650 7200 3750 7200 3750 6900
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4
2250 6900 2250 6600 7200 6600 7200 6900
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
3225 6900 3225 6600
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
4200 6900 4200 6600
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
5175 6900 5175 6600
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
6150 6900 6150 6600
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
4650 6600 4650 6300
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
1800 6900 2700 6900 2700 7200 1800 7200 1800 6900
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
4725 6900 5625 6900 5625 7200 4725 7200 4725 6900
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
5700 6900 6600 6900 6600 7200 5700 7200 5700 6900
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
6675 6900 7800 6900 7800 7200 6675 7200 6675 6900
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
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
6600 5475 6600 5775
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
5025 4425 6000 5775
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 3
4800 3900 5925 2550 8100 2550
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
7200 3900 8475 2775
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
9450 2250 10425 2250 10425 2775 9450 2775 9450 2250
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
8925 2475 9450 2475
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
2325 5550 2325 5250
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
2925 4950 4350 4275
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 3
2850 4725 5775 2400 8100 2400
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 720 1637 2371 hostapd\001
4 0 0 50 -1 0 12 0.0000 4 180 600 3825 7125 prism54\001
4 0 0 50 -1 0 12 0.0000 4 180 510 1875 7125 hostap\001
4 0 0 50 -1 0 12 0.0000 4 135 600 2850 7125 nl80211\001
4 0 0 50 -1 0 12 0.0000 4 135 270 4800 7125 bsd\001
4 0 0 50 -1 0 12 0.0000 4 105 300 6750 7125 test\001
4 0 0 50 -1 0 12 0.0000 4 135 420 5775 7125 wired\001
4 0 0 50 -1 0 12 0.0000 4 135 1050 8700 4650 EAP methods\001
4 0 0 50 -1 0 12 0.0000 4 135 690 9525 2475 RADIUS\001
4 0 0 50 -1 0 12 0.0000 4 180 825 9525 2700 accounting\001

View file

@ -0,0 +1,66 @@
/**
\page hostapd_ctrl_iface_page hostapd control interface
hostapd implements a control interface that can be used by
external programs to control the operations of the hostapd
daemon and to get status information and event notifications. There is
a small C library, in a form of a single C file, \ref 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 \ref wpa_ctrl.h to interact with
wpa_supplicant. This library can also be used with C++. \ref hostapd_cli.c
is an example program using this library.
There are multiple mechanisms for inter-process communication. For
example, Linux version of hostapd is using UNIX domain sockets for the
control interface. The use of the functions defined in \ref 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 hostapd should link in \ref wpa_ctrl.c. This
allows them to use helper functions to open connection to the control
interface with \ref wpa_ctrl_open() and to send commands with
\ref wpa_ctrl_request().
hostapd 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
hostapd. These can be executed using \ref wpa_ctrl_request().
Unsolicited event messages are sent by hostapd 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 \ref 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.
\ref 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 \ref 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. \ref wpa_cli.c 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 \ref wpa_ctrl_close(). If the connection was used for
unsolicited event messages, it should be first detached by calling
\ref wpa_ctrl_detach().
\section ctrl_iface_cmds Control interface commands
Following commands can be used with \ref wpa_ctrl_request():
\subsection ctrl_iface_PING PING
This command can be used to test whether hostapd is replying
to the control interface commands. The expected reply is \c PONG if the
connection is open and hostapd is processing commands.
*/

95
doc/mainpage.doxygen Normal file
View file

@ -0,0 +1,95 @@
/**
\mainpage Developers' documentation for wpa_supplicant and hostapd
The goal of this documentation and comments in the source code is to
give enough information for other developers to understand how
wpa_supplicant and hostapd have been implemented, how they can be
modified, how new drivers can be supported, and how the source code
can be ported to other operating systems. If any information is
missing, feel free to contact Jouni Malinen <j@w1.fi> for more
information. Contributions as patch files are also very welcome at the
same address. Please note that this software is licensed under the
BSD license (the one with advertisement clause removed). All
contributions to wpa_supplicant and hostapd are expected to use
compatible licensing terms.
The source code and read-only access to the combined wpa_supplicant
and hostapd Git repository is available from the project home page at
http://w1.fi/wpa_supplicant/. This developers' documentation is also
available as a PDF file from
http://w1.fi/wpa_supplicant/wpa_supplicant-devel.pdf .
\section _wpa_supplicant 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 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_peer_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
\section _hostapd hostapd
hostapd includes IEEE 802.11 access point management (authentication /
association), IEEE 802.1X/WPA/WPA2 Authenticator, EAP server, and
RADIUS authentication server functionality. It can be build with
various configuration option, e.g., a standalone AP management
solution or a RADIUS authentication server with support for number of
EAP methods.
The design goal for hostapd 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_server_module "EAP server implementation".
Similarly, RADIUS authentication server is in its own separate module.
Both IEEE 802.1X and RADIUS authentication server can use EAP server
functionality.
hostapd implements a \ref hostapd_ctrl_iface_page "control interface"
that can be used by external programs to control the operations of the
hostapdt 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 hostapd.png "hostapd modules"
\image latex hostapd.eps "hostapd modules" width=15cm
*/

471
doc/p2p.doxygen Normal file
View file

@ -0,0 +1,471 @@
/**
\page p2p Wi-Fi Direct - P2P module
Wi-Fi Direct functionality is implemented any many levels in the WLAN
stack from low-level driver operations to high-level GUI design. This
document covers the parts that can be user by wpa_supplicant. However,
it should be noted that alternative designs are also possible, so some
of the functionality may reside in other components in the system.
The driver (or WLAN firmware/hardware) is expected to handle low-level
operations related to P2P Power Management and channel scheduling. In
addition, support for virtual network interface and data frame
processing is done inside the driver. Configuration for these
low-level operations is defined in the driver interface:
src/drivers/driver.h. This defines both the commands and events used to
interact with the driver.
P2P module implements higher layer functionality for management P2P
groups. It takes care of Device Discovery, Service Discovery, Group
Owner Negotiation, P2P Invitation. In addition, it maintains
information about neighboring P2P Devices. This module could be used
in designs that do not use wpa_supplicant and it could also reside
inside the driver/firmware component. P2P module API is defined in
\ref src/p2p/p2p.h.
Provisioning step of Group Formation is implemented using WPS
(\ref src/wps/wps.h).
wpa_supplicant includes code in interact with both the P2P module
(\ref wpa_supplicant/p2p_supplicant.c) and WPS
(\ref wpa_supplicant/wps_supplicant.c). The driver operations are passed
through these files, i.e., core P2P or WPS code does not interact
directly with the driver interface.
\section p2p_arch P2P architecture
P2P functionality affects many areas of the system architecture. This
section shows couple of examples on the location of main P2P
components. In the diagrams below, green arrows are used to show
communication paths from the P2P module to upper layer management
functionality and all the way to a GUI that user could use to manage
P2P connections. Blue arrows show the path taken for lower layer
operations. Glue code is used to bind the P2P module API to the rest
of the system to provide access both towards upper and lower layer
functionality.
\subsection p2p_arch_mac80211 P2P architecture with Linux/mac80211/ath9k
An architecture where the P2P module resides inside the
wpa_supplicant process is used with Linux mac80211-based drivers,
e.g., ath9k. The following diagram shows the main components related
to P2P functionality in such an architecture.
\image html p2p_arch.png "P2P module within wpa_supplicant"
\image latex p2p_arch.eps "P2P module within wpa_supplicant" width=15cm
\subsection p2p_arch_umac P2P architecture with UMAC
The following diagram shows the main components related to P2P
functionality in an architecture where the P2P module resides inside
the kernel IEEE 802.11 stack (UMAC in the figure).
\image html p2p_arch2.png "P2P module in kernel
\image latex p2p_arch2.eps "P2P module in kernel" width=15cm
\section p2p_module P2P module
P2P module manages discovery and group formation with a single state
machine, i.e., only a single operation per device can be in progress
at any given time. The following diagram describes the P2P state
machine. For clarity, it does not include state transitions on
operation timeouts to the IDLE state. The states that are marked with
dotted ellipse are listed for clarity to describe the protocol
functionality for Device Discovery phase, but are not used in the
implementation (the SEARCH state is used to manage the initial Scan
and the alternating Listen and Search states within Find).
\image html p2p_sm.png "P2P module state machine"
\image latex p2p_sm.eps "P2P module state machine" width=15cm
\subsection p2p_module_api P2P module API
P2P module API is defined in \ref src/p2p/p2p.h. The API consists of
functions for requesting operations and for providing event
notifications. Similar set of callback functions are configured with
struct p2p_config to provide callback functions that P2P module can
use to request operations and to provide event notifications. In
addition, there are number of generic helper functions that can be
used for P2P related operations.
These are the main functions for an upper layer management entity to
request P2P operations:
- \ref p2p_find()
- \ref p2p_stop_find()
- \ref p2p_listen()
- \ref p2p_connect()
- \ref p2p_reject()
- \ref p2p_prov_disc_req()
- \ref p2p_sd_request()
- \ref p2p_sd_cancel_request()
- \ref p2p_sd_response()
- \ref p2p_sd_service_update()
- \ref p2p_invite()
These are the main callback functions for P2P module to provide event
notifications to the upper layer management entity:
- \ref p2p_config::dev_found()
- \ref p2p_config::go_neg_req_rx()
- \ref p2p_config::go_neg_completed()
- \ref p2p_config::sd_request()
- \ref p2p_config::sd_response()
- \ref p2p_config::prov_disc_req()
- \ref p2p_config::prov_disc_resp()
- \ref p2p_config::invitation_process()
- \ref p2p_config::invitation_received()
- \ref p2p_config::invitation_result()
The P2P module uses following functions to request lower layer driver
operations:
- \ref p2p_config::p2p_scan()
- \ref p2p_config::send_probe_resp()
- \ref p2p_config::send_action()
- \ref p2p_config::send_action_done()
- \ref p2p_config::start_listen()
- \ref p2p_config::stop_listen()
Events from lower layer driver operations are delivered to the P2P
module with following functions:
- \ref p2p_probe_req_rx()
- \ref p2p_rx_action()
- \ref p2p_scan_res_handler()
- \ref p2p_scan_res_handled()
- \ref p2p_send_action_cb()
- \ref p2p_listen_cb()
In addition to the per-device state, the P2P module maintains
per-group state for group owners. This is initialized with a call to
p2p_group_init() when a group is created and deinitialized with
p2p_group_deinit(). The upper layer GO management entity uses
following functions to interact with the P2P per-group state:
- \ref p2p_group_notif_assoc()
- \ref p2p_group_notif_disassoc()
- \ref p2p_group_notif_formation_done()
- \ref p2p_group_match_dev_type()
The P2P module will use following callback function to update P2P IE
for GO Beacon and Probe Response frames:
- \ref p2p_group_config::ie_update()
\section p2p_driver P2P driver operations (low-level interface)
The following driver wrapper functions are needed for P2P in addition
to the standard station/AP mode operations when the P2P module resides
within wpa_supplicant:
- \ref wpa_driver_ops::if_add()
- \ref wpa_driver_ops::if_remove()
- \ref wpa_driver_ops::remain_on_channel()
- \ref wpa_driver_ops::cancel_remain_on_channel()
- \ref wpa_driver_ops::send_action()
- \ref wpa_driver_ops::probe_req_report()
The following driver wrapper events are needed for P2P in addition to
the standard station/AP mode events when the P2P module resides within
wpa_supplicant:
- \ref wpa_event_type::EVENT_RX_MGMT
- \ref wpa_event_type::EVENT_REMAIN_ON_CHANNEL
- \ref wpa_event_type::EVENT_CANCEL_REMAIN_ON_CHANNEL
- \ref wpa_event_type::EVENT_RX_PROBE_REQ
\section p2p_go_neg P2P device discovery and group formation
This section shows an example sequence of operations that can be used
to implement P2P device discovery and group formation. The function
calls are described based on the P2P module API. The exact design for
the glue code outside the P2P module depends on the architecture used
in the system.
An upper layer management entity starts P2P device discovery by
calling \ref p2p_find(). The P2P module start the discovery by requesting a
full scan to be completed by calling \ref p2p_config::p2p_scan(). Results
from the scan will be reported by calling \ref p2p_scan_res_handler() and
after last result, the scan result processing is terminated with a
call to \ref p2p_scan_res_handled(). The P2P peers that are found during
the full scan are reported with the \ref p2p_config::dev_found() callback.
After the full scan, P2P module start alternating between Listen and
Search states until the device discovery operation times out or
terminated, e.g., with a call to \ref p2p_stop_find().
When going into the Listen state, the P2P module requests the driver
to be configured to be awake on the listen channel with a call to
\ref p2p_config::start_listen(). The glue code using the P2P module may
implement this, e.g., by using remain-on-channel low-level driver
functionality for off-channel operation. Once the driver is available
on the requested channel, notification of this is delivered by calling
\ref p2p_listen_cb(). The Probe Request frames that are received during the
Listen period are delivered to the P2P module by calling
\ref p2p_config::p2p_probe_req_rx() and P2P module request a response to
these to be sent by using \ref p2p_config::send_probe_resp() callback
function. If a group owner negotiation from another P2P device is
received during the device discovery phase, that is indicated to the
upper layer code with the \ref p2p_config::go_neg_req_tx() callback.
The Search state is implemented by using the normal scan interface,
i.e., the P2P module will call \ref p2p_config::p2p_scan() just like in the
full scan phase described. Similarly, scan results from the search
operation will be delivered to the P2P module using the
\ref p2p_scan_res_handler() and \ref p2p_scan_res_handled() functions.
Once the upper layer management entity has found a peer with which it
wants to connect by forming a new group, it initiates group owner
negotiation by calling \ref p2p_connect(). Before doing this, the upper
layer code is responsible for asking the user to provide the PIN to be
used during the provisioning step with the peer or the push button
press for PBC mode. The glue code will need to figure out the intended
interface address for the group before group owner negotiation can be
started.
Optional Provision Discovery mechanism can be used to request the peer
to display a PIN for the local device to enter (and vice versa). Upper
layer management entity can request the specific mechanism by calling
\ref p2p_prov_disc_req(). The response to this will be reported with the
\ref p2p_config::prov_disc_resp() callback. If the peer device started
Provision Discovery, an accepted request will be reported with the
\ref p2p_config::prov_disc_req() callback. The P2P module will
automatically accept the Provision Discovery for display and keypad
methods, but it is up to the upper layer manegement entity to actually
generate the PIN and to configure it with following \ref p2p_connect() call
to actually authorize the connection.
The P2P module will use \ref p2p_config::send_action() callback to request
lower layer code to transmit an Action frame during group owner
negotiation. \ref p2p_send_action_cb() is used to report the result of
transmission. If the peer is not reachable, the P2P module will try to
find it by alternating between Action frame send and Listen
states. The Listen state for this phase will be used similarly to the
Listen state during device discovery as described above.
Once the group owner negotiation has been completed, its results will
be reported with the \ref p2p_config::go_neg_completed() callback. The
upper layer management code or the glue code using the P2P module API
is responsible for creating a new group interface and starting
provisioning step at this point by configuring WPS Registrar or
Enrollee functionality based on the reported group owner negotiation
results. The upper layer code is also responsible for timing out WPS
provisioning if it cannot be completed in 15 seconds.
Successful completion of the WPS provisioning is reported with a call
to \ref p2p_wps_success_cb(). The P2P module will clear its group formation
state at this point and allows new group formation attempts to be
started. The upper layer management code is responsible for configuring
the GO to accept associations from devices and the client to connect to
the GO with the provisioned credentials. GO is also responsible for
calling \ref p2p_group_notif_formation_done() as described below.
If the WPS provisioning step fails or times out, this is reported with
a call to \ref p2p_group_formation_failed(). The P2P module will clear its
group formation state at this point and allows new group formation
attempts to be started. The upper layer management code is responsible
for removing the group interface for the failed group.
\section p2p_sd P2P service discovery
P2P protocol includes service discovery functionality that can be used
to discover which services are provided by the peers before forming a
group. This leverages the Generic Advertisement Service (GAS) protocol
from IEEE 802.11u and P2P vendor-specific contents inside the Native
GAS messages.
The P2P module takes care of GAS encapsulation, fragmentation, and
actual transmission and reception of the Action frames needed for
service discovery. The user of the P2P module is responsible for
providing P2P specific Service Request TLV(s) for queries and Service
Response TLV(s) for responses.
\subsection p2p_sd_query Querying services of peers
Service discovery is implemented by processing pending queries as a
part of the device discovery phase. \ref p2p_sd_request() function is used
to schedule service discovery queries to a specific peer or to all
discovered peers. \ref p2p_sd_cancel_request() can be used to cancel a
scheduled query. Queries that are specific to a single peer will be
removed automatically after the response has been received.
After the service discovery queries have been queued, device discovery
is started with a call to \ref p2p_find(). The pending service discovery
queries are then sent whenever a peer is discovered during the find
operation. Responses to the queries will be reported with the
\ref p2p_config::sd_response() callback.
\subsection p2p_sd_response Replying to service discovery queries from peers
The received service discovery requests will be indicated with the
\ref p2p_config::sd_request() callback. The response to the query is sent
by calling \ref p2p_sd_response().
\subsection p2p_sd_indicator Service update indicator
P2P service discovery provides a mechanism to notify peers about
changes in available services. This works by incrementing Service
Update Indicator value whenever there is a change in the
services. This value is included in all SD request and response
frames. The value received from the peers will be included in the
\ref p2p_config::sd_request() and \ref p2p_config::sd_response() callbacks. The
value to be sent to the peers is incremented with a call to
\ref p2p_sd_service_update() whenever availability of the local services
changes.
\section p2p_go P2P group owner
This section describes how P2P module can be used for managing
per-group information in a group owner. The function calls are
described based on the P2P module API. The exact design for the glue
code outside the P2P module depends on the architecture used in the
system.
When a P2P group interface is created in group owner role, per-group
data is initialized with \ref p2p_group_init(). This call provides a
pointer to the per-device P2P module context and configures the
per-group operation. The configured \ref p2p_group_config::ie_update()
callback is used to set the initial P2P IE for Beacon and Probe
Response frames in the group owner. The AP mode implementation may use
this information to add IEs into the frames.
Once the group formation has been completed (or if it is skipped in
case of manual group setup), \ref p2p_group_notif_formation_done() is
called. This will allow the P2P module to update the P2P IE for
Beacon and Probe Response frames.
The SME/MLME code that managements IEEE 802.11 association processing
needs to inform P2P module whenever a P2P client associates or
disassociates with the group. This is done by calling
\ref p2p_group_notif_assoc() and \ref p2p_group_notif_disassoc(). The P2P module
manages a list of group members and updates the P2P Group Information
subelement in the P2P IE based on the information from the P2P
clients. The \ref p2p_group_config::ie_update() callback is used whenever
the P2P IE in Probe Response frames needs to be changed.
The SME/MLME code that takes care of replying to Probe Request frames
can use \ref p2p_group_match_dev_type() to check whether the Probe Request
frame request a reply only from groups that include a specific device
type in one of the clients or GO. A match will be reported if the
Probe Request does not request a specific device type, so this
function can be used to filter or received Probe Request frames and
only the ones that result in non-zero return value need to be replied.
When the P2P group interface for GO role is removed,
\ref p2p_group_deinit() is used to deinitialize the per-group P2P module
state.
\section p2p_ctrl_iface P2P control interface
wpa_supplicant \ref ctrl_iface_page "control interface" can be used
to manage P2P functionality from an external program (e.g., a GUI or a
system configuration manager). This interface can be used directly
through the control interface backend mechanism (e.g., local domain
sockets on Linux) or with help of wpa_cli (e.g., from a script).
The following P2P-related commands are available:
- \ref ctrl_iface_P2P_FIND P2P_FIND
- \ref ctrl_iface_P2P_STOP_FIND P2P_STOP_FIND
- \ref ctrl_iface_P2P_CONNECT P2P_CONNECT
- \ref ctrl_iface_P2P_LISTEN P2P_LISTEN
- \ref ctrl_iface_P2P_GROUP_REMOVE P2P_GROUP_REMOVE
- \ref ctrl_iface_P2P_GROUP_ADD P2P_GROUP_ADD
- \ref ctrl_iface_P2P_PROV_DISC P2P_PROV_DISC
- \ref ctrl_iface_P2P_SERV_DISC_REQ P2P_SERV_DISC_REQ
- \ref ctrl_iface_P2P_SERV_DISC_CANCEL_REQ P2P_SERV_DISC_CANCEL_REQ
- \ref ctrl_iface_P2P_SERV_DISC_RESP P2P_SERV_DISC_RESP
- \ref ctrl_iface_P2P_SERVICE_UPDATE P2P_SERVICE_UPDATE
- \ref ctrl_iface_P2P_SERV_DISC_EXTERNAL P2P_SERV_DISC_EXTERNAL
- \ref ctrl_iface_P2P_REJECT P2P_REJECT
- \ref ctrl_iface_P2P_INVITE P2P_INVITE
The following P2P-related events are used:
- \ref ctrl_iface_event_P2P_EVENT_DEVICE_FOUND P2P-DEVICE-FOUND
- \ref ctrl_iface_event_P2P_EVENT_GO_NEG_REQUEST P2P-GO-NEG-REQUEST
- \ref ctrl_iface_event_P2P_EVENT_GO_NEG_SUCCESS P2P-GO-NEG-SUCCESS
- \ref ctrl_iface_event_P2P_EVENT_GO_NEG_FAILURE P2P-GO-NEG-FAILURE
- \ref ctrl_iface_event_P2P_EVENT_GROUP_FORMATION_SUCCESS P2P-GROUP-FORMATION-SUCCESS
- \ref ctrl_iface_event_P2P_EVENT_GROUP_FORMATION_FAILURE P2P-GROUP-FORMATION-FAILURE
- \ref ctrl_iface_event_P2P_EVENT_GROUP_STARTED P2P-GROUP-STARTED
- \ref ctrl_iface_event_P2P_EVENT_GROUP_REMOVED P2P-GROUP-REMOVED
- \ref ctrl_iface_event_P2P_EVENT_PROV_DISC_SHOW_PIN P2P-PROV-DISC-SHOW-PIN
- \ref ctrl_iface_event_P2P_EVENT_PROV_DISC_ENTER_PIN P2P-PROV-DISC-ENTER-PIN
- \ref ctrl_iface_event_P2P_EVENT_SERV_DISC_REQ P2P-SERV-DISC-REQ
- \ref ctrl_iface_event_P2P_EVENT_SERV_DISC_RESP P2P-SERV-DISC-RESP
- \ref ctrl_iface_event_P2P_EVENT_INVITATION_RECEIVED P2P-INVITATION-RECEIVED
- \ref ctrl_iface_event_P2P_EVENT_INVITATION_RESULT P2P-INVITATION-RESULT
\subsection p2p_wpa_gui GUI example (wpa_gui)
wpa_gui has an example implementation of a GUI that could be used to
manage P2P operations. The P2P related functionality is contained
mostly in wpa_supplicant/wpa_gui-qt4/peers.cpp and it shows how the
control interface commands and events can be used.
\subsection p2p_wpa_cli wpa_cli example
wpa_cli can be used to control wpa_supplicant in interactive
mode. The following sessions show examples of commands used for
device discovery and group formation. The lines starting with "> " are
commands from the user (followed by command result indication) and
lines starting with "<2>" are event messages from wpa_supplicant.
P2P device "Wireless Client":
\verbatim
> p2p_find
OK
> <2>P2P-DEVICE-FOUND 02:40:61:c2:f3:b7 p2p_dev_addr=02:40:61:c2:f3:b7
pri_dev_type=1-0050F204-1 name='Wireless Client 2' config_methods=0x18c
dev_capab=0x1 group_capab=0x0
<2>P2P-GO-NEG-REQUEST 02:40:61:c2:f3:b7
<2>P2P-GO-NEG-REQUEST 02:40:61:c2:f3:b7
> p2p_connect 02:40:61:c2:f3:b7 pbc
OK
<2>P2P-GO-NEG-SUCCESS
<2>P2P-GROUP-FORMATION-SUCCESS
<2>P2P-GROUP-STARTED sta0-p2p-0 client DIRECT-vM
> interface
Available interfaces:
sta0-p2p-0
sta0
> p2p_group_remove sta0-p2p-0
<2>P2P-GROUP-REMOVED sta0-p2p-0 client
OK
> term
OK
\endverbatim
P2P device "Wireless Client2" (which ended up operating in GO role):
\verbatim
> p2p_find
OK
<2>P2P-DEVICE-FOUND 02:f0:bc:44:87:62 p2p_dev_addr=02:f0:bc:44:87:62
pri_dev_type=1-0050F204-1 name='Wireless Client' config_methods=0x18c
dev_capab=0x1 group_capab=0x0
> p2p_connect 02:f0:bc:44:87:62 pbc
OK
<2>P2P-GO-NEG-SUCCESS
<2>P2P-GROUP-FORMATION-SUCCESS
<2>P2P-GROUP-STARTED sta1-p2p-0 GO DIRECT-vM
> interface
Available interfaces:
sta1-p2p-0
sta1
> p2p_group_remove sta1-p2p-0
<2>P2P-GROUP-REMOVED sta1-p2p-0 GO
OK
> term
OK
\endverbatim
*/

85
doc/p2p_arch.dot Normal file
View file

@ -0,0 +1,85 @@
digraph p2p_arch {
ranksep=.75;
size = "7.5,7.5";
edge [dir=none];
subgraph cluster_wpa_gui {
label = "wpa_gui";
status -> Qt;
scan -> Qt;
network -> Qt;
Qt -> peers;
Qt -> WPS;
Qt -> gui_ctrl;
gui_ctrl [label="ctrl i/f"];
}
subgraph cluster_wpa_supplicant {
label = "wpa_supplicant"
ctrl_iface [label="ctrl i/f"];
authenticator [label="Authenticator"];
supplicant [label="Supplicant"];
driver_iface [label="driver i/f"];
p2p_module [label="P2P\nmodule"];
wps_registrar [label="WPS\nRegistrar"];
wps_enrollee [label="WPS\nEnrollee"];
mgmt_entity [label="Management\nentity"];
ctrl_iface -> mgmt_entity;
p2p_module -> mgmt_entity;
wps_registrar -> mgmt_entity;
wps_enrollee -> mgmt_entity;
mgmt_entity -> authenticator;
mgmt_entity -> supplicant;
mgmt_entity -> driver_iface;
{ rank = same; mgmt_entity; p2p_module; }
}
subgraph cluster_wpa_cli {
label = "wpa_cli -a"
wpa_cli_action;
}
subgraph cluster_dnsmasq {
label = "dnsmasq"
dnsmasq;
}
subgraph cluster_dhclient {
label = "dhclient"
dhclient;
}
subgraph cluster_kernel {
label = "Linux kernel"
cfg80211 -> mac80211;
netdev -> mac80211;
mac80211 -> ath9k;
}
gui_ctrl -> ctrl_iface;
wpa_cli_action -> ctrl_iface;
driver_iface -> cfg80211;
wpa_cli_action -> dnsmasq;
wpa_cli_action -> dhclient;
dnsmasq -> netdev;
dhclient -> netdev;
edge [color=blue,dir=both];
p2p_module -> mgmt_entity -> driver_iface -> cfg80211 -> mac80211 -> ath9k;
edge [color=green,dir=both];
peers -> Qt -> gui_ctrl -> ctrl_iface -> mgmt_entity -> p2p_module;
}

85
doc/p2p_arch2.dot Normal file
View file

@ -0,0 +1,85 @@
digraph p2p_arch2 {
ranksep=.75;
size = "7.5,7.5";
edge [dir=none];
subgraph cluster_wpa_gui {
label = "wpa_gui";
status -> Qt;
scan -> Qt;
network -> Qt;
Qt -> peers;
Qt -> WPS;
Qt -> gui_ctrl;
gui_ctrl [label="ctrl i/f"];
}
subgraph cluster_wpa_supplicant {
label = "wpa_supplicant"
ctrl_iface [label="ctrl i/f"];
authenticator [label="Authenticator"];
supplicant [label="Supplicant"];
driver_iface [label="driver i/f"];
wps_registrar [label="WPS\nRegistrar"];
wps_enrollee [label="WPS\nEnrollee"];
mgmt_entity [label="Management\nentity"];
ctrl_iface -> mgmt_entity;
wps_registrar -> mgmt_entity;
wps_enrollee -> mgmt_entity;
mgmt_entity -> authenticator;
mgmt_entity -> supplicant;
mgmt_entity -> driver_iface;
}
subgraph cluster_wpa_cli {
label = "wpa_cli -a"
wpa_cli_action;
}
subgraph cluster_dnsmasq {
label = "dnsmasq"
dnsmasq;
}
subgraph cluster_dhclient {
label = "dhclient"
dhclient;
}
subgraph cluster_kernel {
label = "Kernel"
ioctl -> umac;
netdev -> umac;
umac -> p2p_module;
p2p_module [label="P2P\nmodule"];
umac -> driver;
{ rank = same; umac; p2p_module; }
}
gui_ctrl -> ctrl_iface;
wpa_cli_action -> ctrl_iface;
driver_iface -> ioctl;
wpa_cli_action -> dnsmasq;
wpa_cli_action -> dhclient;
dnsmasq -> netdev;
dhclient -> netdev;
edge [color=blue,dir=both];
p2p_module -> umac -> driver;
edge [color=green,dir=both];
peers -> Qt -> gui_ctrl -> ctrl_iface -> mgmt_entity -> driver_iface -> ioctl -> umac -> p2p_module;
}

62
doc/p2p_sm.dot Normal file
View file

@ -0,0 +1,62 @@
digraph p2p {
ranksep=.75;
size = "8.5,7.5";
start -> IDLE;
start [label="Init",shape=none];
/* Discovery: Scan followed by Find(SEARCH,LISTEN) */
subgraph cluster_0 {
label="Discovery";
color=lightgrey;
node [color=blue];
/* SCAN and LISTEN currently not used in the implementation */
SCAN [style=dotted];
LISTEN [style=dotted];
SCAN -> LISTEN;
LISTEN -> SEARCH -> LISTEN [style=dotted];
SEARCH -> SD_DURING_FIND [label="Peer SD capab\nand no info", weight=100];
SD_DURING_FIND -> SEARCH [label="RX SD Resp\nor timeout", weight=100];
SEARCH -> PROV_DISC_DURING_FIND [label="Prov Disc cmd\nand no Resp", weight=100];
PROV_DISC_DURING_FIND -> SEARCH [label="RX Prov Disc Resp\nor timeout", weight=100];
}
/* Group Formation */
subgraph cluster_1 {
label="Group Formation";
color=lightgrey;
node [color=green];
CONNECT -> CONNECT_LISTEN [style=dotted,weight=100];
CONNECT_LISTEN -> CONNECT [style=dotted,weight=100];
CONNECT -> WAIT_PEER_IDLE [label="RX GO Neg Resp\n(info unavail)"];
WAIT_PEER_IDLE -> WAIT_PEER_CONNECT [style=dotted,weight=100];
WAIT_PEER_CONNECT -> WAIT_PEER_IDLE [style=dotted,weight=100];
CONNECT -> GO_NEG [label="RX GO Neg Resp\n(success)", weight=10];
CONNECT_LISTEN -> GO_NEG [label="RX GO Neg Req or\nTX GO Neg Resp"];
WAIT_PEER_CONNECT -> GO_NEG [label="RX GO Neg Req"];
GO_NEG -> PROVISIONING [label="TX/RX GO Neg Conf"];
}
PROVISIONING -> IDLE [label="WPS\nsuccess"];
/* External triggers */
IDLE -> SCAN [label="Find cmd",weight=20];
IDLE -> CONNECT [label="Connect cmd",weight=20];
IDLE -> LISTEN_ONLY [label="Listen cmd"];
/* Timeouts */
/*
edge [color=red];
WAIT_PEER_IDLE -> IDLE [label="timeout", weight=0];
WAIT_PEER_CONNECT -> IDLE [label="timeout", weight=0];
CONNECT -> IDLE [label="timeout", weight=0];
CONNECT_LISTEN -> IDLE [label="timeout", weight=0];
GO_NEG -> IDLE [label="timeout", weight=0];
PROVISIONING -> IDLE [label="timeout", weight=0];
LISTEN_ONLY -> IDLE [label="timeout", weight=0];
SEARCH -> IDLE [label="timeout", weight=0];
*/
}

209
doc/porting.doxygen Normal file
View file

@ -0,0 +1,209 @@
/**
\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, the code has been
ported to number of other operating systems like VxWorks, PalmOS,
Windows CE, and Windows Mobile. 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 ansi_c_extra Extra functions on top of ANSI C
wpa_supplicant is mostly using ANSI C functions that are available on
most targets. However, couple of additional functions that are common
on modern UNIX systems are used. Number of these are listed with
prototypes in \ref common.h (the \verbatim #ifdef CONFIG_ANSI_C_EXTRA \endverbatim
block). These functions may need to be implemented or at least defined
as macros to native functions in the target OS or C library.
Many of the common ANSI C functions are used through a wrapper
definitions in \ref os.h to allow these to be replaced easily with a
platform specific version in case standard C libraries are not
available. In addition, \ref os.h defines couple of common platform
specific functions that are implemented in \ref os_unix.c for UNIX like
targets and in \ref os_win32.c for Win32 API. If the target platform does
not support either of these examples, a new os_*.c file may need to be
added.
Unless OS_NO_C_LIB_DEFINES is defined, the standard ANSI C and POSIX
functions are used by defining the os_*() wrappers to use them
directly in order to avoid extra cost in size and speed. If the target
platform needs different versions of the functions, \ref os.h can be
modified to define the suitable macros or alternatively,
OS_NO_C_LIB_DEFINES may be defined for the build and the wrapper
functions can then be implemented in a new os_*.c wrapper file.
\ref common.h defines number of helper macros for handling integers of
different size and byte order. Suitable version of these definitions
may need to be added for the target platform.
\section configuration_backend Configuration backend
wpa_supplicant implements a configuration interface that allows the
backend to be easily replaced in order to read configuration data from
a suitable source depending on the target platform. \ref config.c
implements the generic code that can be shared with all configuration
backends. Each backend is implemented in its own config_*.c file.
The included \ref config_file.c backend uses a text file for configuration
and \ref config_winreg.c uses Windows registry. These files can be used as
an example for a new configuration backend if the target platform uses
different mechanism for configuration parameters. In addition,
\ref config_none.c can be used as an empty starting point for building a
new configuration backend.
\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. \ref 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 (\ref l2_packet_linux.c), more portable
version using libpcap/libdnet libraries (\ref l2_packet_pcap.c; this
supports WinPcap, too), and FreeBSD specific version of libpcap
interface (\ref l2_packet_freebsd.c).
If the target operating system is supported by libpcap (receiving) and
libdnet (sending), \ref 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, for hostapd,
struct \ref wpa_driver_ops::hapd_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. \ref 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
\ref wpa_supplicant/ctrl_iface.c. Matching client side is implemented as a control
interface library in \ref 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.
\ref 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. \ref wpa_supplicant/main.c is also a
good example on how the initialization process should be done.
The supplicant initialization functions are defined in
\ref 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
\ref wpa_supplicant_init(). After this, existing network interfaces can be
added with \ref wpa_supplicant_add_iface(). \ref wpa_supplicant_run() is then
used to start the main event loop. Once this returns at program
termination time, \ref wpa_supplicant_deinit() is used to release global
context data.
\ref wpa_supplicant_add_iface() and \ref 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.
\section simple_build Simple build example
One way to start a porting project is to begin with a very simple
build of wpa_supplicant with WPA-PSK support and once that is
building correctly, start adding features.
Following command can be used to build very simple version of
wpa_supplicant:
\verbatim
cc -o wpa_supplicant config.c eloop.c common.c md5.c rc4.c sha1.c \
config_none.c l2_packet_none.c tls_none.c wpa.c preauth.c \
aes_wrap.c wpa_supplicant.c events.c main_none.c drivers.c
\endverbatim
The end result is not really very useful since it uses empty functions
for configuration parsing and layer 2 packet access and does not
include a driver interface. However, this is a good starting point
since the build is complete in the sense that all functions are
present and this is easy to configure to a build system by just
including the listed C files.
Once this version can be build successfully, the end result can be
made functional by adding a proper program entry point (main*.c),
driver interface (driver_*.c and matching CONFIG_DRIVER_* define for
registration in \ref drivers.c), configuration parser/writer (config_*.c),
and layer 2 packet access implementation (l2_packet_*.c). After these
components have been added, the end result should be a working
WPA/WPA2-PSK enabled supplicant.
After the basic functionality has been verified to work, more features
can be added by linking in more files and defining C pre-processor
defines. Currently, the best source of information for what options
are available and which files needs to be included is in the Makefile
used for building the supplicant with make. Similar configuration will
be needed for build systems that either use different type of make
tool or a GUI-based project configuration.
*/

201
doc/testing_tools.doxygen Normal file
View file

@ -0,0 +1,201 @@
/**
\page testing_tools Testing and development tools
[ \ref eapol_test "eapol_test" |
\ref preauth_test "preauth_test" |
\ref unit_tests "Unit tests" |
\ref wpa_trace "Tracing code" ]
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 [-nWS] -c<conf> [-a<AS IP>] [-p<AS port>] [-s<AS secret>] \
[-r<count>] [-t<timeout>] [-C<Connect-Info>] \
[-M<client MAC address>]
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
-S = save configuration after authentiation
-n = no MPPE keys expected
-t<timeout> = sets timeout in seconds (default: 30 s)
-C<Connect-Info> = RADIUS Connect-Info (default: CONNECT 11Mbps 802.11b)
-M<client MAC address> = Set own MAC address (Calling-Station-Id,
default: 02:00:00:00:00:01)
\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 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.
The test programs are collected in the tests subdirectory. All
automated unit tests can be run with
\verbatim
make run-tests
\endverbatim
This make target builds and runs each test and terminates with zero
exit code if all tests were completed successfully.
\section wpa_trace Tracing code for developer debuggin
wpa_supplicant and hostapd can be built with tracing code that will
track and analyze memory allocations and other resource registrations
and certain API uses. If incorrect use is detected, a backtrace of the
call location (and/or allocation location) is shown. This can also be
used to detect certain categories of memory leaks and report them
automatically when the program is terminated. The report will also
include information about forgotten eloop events.
The trace code can be enabled with CONFIG_WPA_TRACE=y build
option. More verbose backtrace information can be generated if libbfd
is available and the binaries are not stripped of symbol
information. This is enabled with CONFIG_WPA_TRACE_BFD=y.
For example, a memory leak (forgotten os_free() call) would show up
like this when the program is terminated:
\verbatim
MEMLEAK[0x82d200]: len 128
WPA_TRACE: memleak - START
[0]: ./wpa_supplicant(os_malloc+0x59) [0x41a5e9]
os_malloc() ../src/utils/os_unix.c:359
[1]: ./wpa_supplicant(os_zalloc+0x16) [0x41a676]
os_zalloc() ../src/utils/os_unix.c:418
[2]: ./wpa_supplicant(wpa_supplicant_init+0x38) [0x48b508]
wpa_supplicant_init() wpa_supplicant.c:2315
[3]: ./wpa_supplicant(main+0x2f3) [0x491073]
main() main.c:252
WPA_TRACE: memleak - END
MEMLEAK: total 128 bytes
\endverbatim
Another type of error that can be detected is freeing of memory area
that was registered for some use and is still be referenced:
\verbatim
WPA_TRACE: Freeing referenced memory - START
[2]: ./wpa_supplicant(os_free+0x5c) [0x41a53c]
os_free() ../src/utils/os_unix.c:411
[3]: ./wpa_supplicant(wpa_supplicant_remove_iface+0x30) [0x48b380]
wpa_supplicant_remove_iface() wpa_supplicant.c:2259
[4]: ./wpa_supplicant(wpa_supplicant_deinit+0x20) [0x48b3e0]
wpa_supplicant_deinit() wpa_supplicant.c:2430
[5]: ./wpa_supplicant(main+0x357) [0x4910d7]
main() main.c:276
WPA_TRACE: Freeing referenced memory - END
WPA_TRACE: Reference registration - START
[1]: ./wpa_supplicant [0x41c040]
eloop_trace_sock_add_ref() ../src/utils/eloop.c:94
[2]: ./wpa_supplicant(wpa_supplicant_ctrl_iface_deinit+0x17) [0x473247]
wpa_supplicant_ctrl_iface_deinit() ctrl_iface_unix.c:436
[3]: ./wpa_supplicant [0x48b21c]
wpa_supplicant_cleanup() wpa_supplicant.c:378
wpa_supplicant_deinit_iface() wpa_supplicant.c:2155
[4]: ./wpa_supplicant(wpa_supplicant_remove_iface+0x30) [0x48b380]
wpa_supplicant_remove_iface() wpa_supplicant.c:2259
[5]: ./wpa_supplicant(wpa_supplicant_deinit+0x20) [0x48b3e0]
wpa_supplicant_deinit() wpa_supplicant.c:2430
[6]: ./wpa_supplicant(main+0x357) [0x4910d7]
main() main.c:276
WPA_TRACE: Reference registration - END
Aborted
\endverbatim
This type of error results in showing backtraces for both the location
where the incorrect freeing happened and the location where the memory
area was marked referenced.
*/

247
doc/wpa_supplicant.fig Normal file
View file

@ -0,0 +1,247 @@
#FIG 3.2
Landscape
Center
Inches
Letter
100.00
Single
-2
1200 2
6 1875 4050 2925 4350
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
1875 4050 2925 4050 2925 4350 1875 4350 1875 4050
4 0 0 50 -1 0 12 0.0000 4 180 735 2025 4275 l2_packet\001
-6
6 3450 1200 4275 1500
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
3450 1200 4275 1200 4275 1500 3450 1500 3450 1200
4 0 0 50 -1 0 12 0.0000 4 180 585 3600 1425 wpa_cli\001
-6
6 4725 1200 5925 1500
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
4725 1200 5925 1200 5925 1500 4725 1500 4725 1200
4 0 0 50 -1 0 12 0.0000 4 135 1005 4800 1425 GUI frontend\001
-6
6 6000 2700 7200 3225
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
6000 2700 7200 2700 7200 3225 6000 3225 6000 2700
4 0 0 50 -1 0 12 0.0000 4 135 975 6075 2925 WPA/WPA2\001
4 0 0 50 -1 0 12 0.0000 4 135 1065 6075 3150 state machine\001
-6
6 6000 4950 7200 5475
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
6000 4950 7200 4950 7200 5475 6000 5475 6000 4950
4 0 0 50 -1 0 12 0.0000 4 135 360 6075 5175 EAP\001
4 0 0 50 -1 0 12 0.0000 4 135 1065 6075 5400 state machine\001
-6
6 8700 3000 9375 3300
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
8700 3000 9375 3000 9375 3300 8700 3300 8700 3000
4 0 0 50 -1 0 12 0.0000 4 150 480 8775 3225 crypto\001
-6
6 4350 3900 5025 4425
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
4350 3900 5025 3900 5025 4425 4350 4425 4350 3900
4 0 0 50 -1 0 12 0.0000 4 105 420 4500 4125 event\001
4 0 0 50 -1 0 12 0.0000 4 180 315 4500 4350 loop\001
-6
6 4275 2550 5100 2850
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
4275 2550 5100 2550 5100 2850 4275 2850 4275 2550
4 0 0 50 -1 0 12 0.0000 4 135 450 4425 2775 ctrl i/f\001
-6
6 6000 3900 7200 4425
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
6000 3900 7200 3900 7200 4425 6000 4425 6000 3900
4 0 0 50 -1 0 12 0.0000 4 135 600 6075 4125 EAPOL\001
4 0 0 50 -1 0 12 0.0000 4 135 1065 6075 4350 state machine\001
-6
6 1800 6000 7800 8100
6 1800 6000 7800 7200
6 1800 6900 2700 7200
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
1800 6900 2700 6900 2700 7200 1800 7200 1800 6900
4 0 0 50 -1 0 12 0.0000 4 105 375 1875 7125 wext\001
-6
6 4725 6900 5625 7200
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
4725 6900 5625 6900 5625 7200 4725 7200 4725 6900
4 0 0 50 -1 0 12 0.0000 4 135 555 4800 7125 hermes\001
-6
6 6675 6900 7800 7200
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
6675 6900 7800 6900 7800 7200 6675 7200 6675 6900
4 0 0 50 -1 0 12 0.0000 4 180 930 6750 7125 ndiswrapper\001
-6
6 5700 6900 6600 7200
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
5700 6900 6600 6900 6600 7200 5700 7200 5700 6900
4 0 0 50 -1 0 12 0.0000 4 135 420 5775 7125 atmel\001
-6
6 4275 6000 5100 6300
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
4275 6000 5100 6000 5100 6300 4275 6300 4275 6000
4 0 0 50 -1 0 12 0.0000 4 135 630 4350 6225 driver i/f\001
-6
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
2775 6900 3675 6900 3675 7200 2775 7200 2775 6900
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
3750 6900 4650 6900 4650 7200 3750 7200 3750 6900
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4
2250 6900 2250 6600 7200 6600 7200 6900
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
3225 6900 3225 6600
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
4200 6900 4200 6600
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
5175 6900 5175 6600
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
6150 6900 6150 6600
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
4650 6600 4650 6300
4 0 0 50 -1 0 12 0.0000 4 180 510 2850 7125 hostap\001
4 0 0 50 -1 0 12 0.0000 4 135 600 3825 7125 nl80211\001
-6
6 3525 7800 5775 8100
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
3525 7800 5775 7800 5775 8100 3525 8100 3525 7800
4 0 0 50 -1 0 12 0.0000 4 135 2145 3600 8025 kernel network device driver\001
-6
2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
2250 7200 4200 7800
2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
7200 7200 5100 7800
-6
6 9600 3000 10275 3300
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
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 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
4 0 0 50 -1 0 12 0.0000 4 135 735 8250 4950 EAP-TLS\001
-6
6 9300 4725 10350 5025
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
9300 4725 10350 4725 10350 5025 9300 5025 9300 4725
4 0 0 50 -1 0 12 0.0000 4 135 810 9375 4950 EAP-MD5\001
-6
6 8175 5100 9225 5400
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
8175 5100 9225 5100 9225 5400 8175 5400 8175 5100
4 0 0 50 -1 0 12 0.0000 4 135 885 8250 5325 EAP-PEAP\001
-6
6 9300 5100 10350 5400
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
9300 5100 10350 5100 10350 5400 9300 5400 9300 5100
4 0 0 50 -1 0 12 0.0000 4 135 840 9375 5325 EAP-TTLS\001
-6
6 8175 5475 9225 5775
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
8175 5475 9225 5475 9225 5775 8175 5775 8175 5475
4 0 0 50 -1 0 12 0.0000 4 135 780 8250 5700 EAP-GTC\001
-6
6 9300 5475 10350 5775
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
9300 5475 10350 5475 10350 5775 9300 5775 9300 5475
4 0 0 50 -1 0 12 0.0000 4 135 765 9375 5700 EAP-OTP\001
-6
6 8175 5850 9225 6150
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
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 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
4 0 0 50 -1 0 12 0.0000 4 135 465 9375 6450 LEAP\001
-6
6 8175 6225 9225 6525
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
8175 6225 9225 6225 9225 6525 8175 6525 8175 6225
4 0 0 50 -1 0 12 0.0000 4 135 765 8250 6450 EAP-PSK\001
-6
6 9300 5850 10350 6150
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
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 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
4500 2550 3900 1500
2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
4800 2550 5400 1500
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
2925 4200 4350 4200
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
5025 3900 6000 3000
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
5025 4200 6000 4200
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
4650 6000 4650 4425
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
6600 4425 6600 4950
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
6600 3225 6600 3900
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
7200 5250 8100 5250
2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2
9075 4425 9075 3300
2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2
7200 3000 8700 3150
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
4650 3900 4650 2850
2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2
7200 4125 8700 3300
2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2
6000 4350 5025 6000
2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2
6000 3150 4875 6000
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
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 210 1440 1637 2371 wpa_supplicant\001

4
eap_example/.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
*.d
eap_example
libeap.so
libeap.a

119
eap_example/Makefile Normal file
View file

@ -0,0 +1,119 @@
ALL=eap_example
include ../src/build.rules
CFLAGS += -I.
CFLAGS += -I../src
CFLAGS += -I../src/utils
EAP_LIBS += ../src/utils/libutils.a
EAP_LIBS += ../src/crypto/libcrypto.a
EAP_LIBS += ../src/tls/libtls.a
OBJS_both += ../src/eap_common/eap_peap_common.o
OBJS_both += ../src/eap_common/eap_psk_common.o
OBJS_both += ../src/eap_common/eap_pax_common.o
OBJS_both += ../src/eap_common/eap_sake_common.o
OBJS_both += ../src/eap_common/eap_gpsk_common.o
OBJS_both += ../src/eap_common/chap.o
OBJS_peer += ../src/eap_peer/eap_tls.o
OBJS_peer += ../src/eap_peer/eap_peap.o
OBJS_peer += ../src/eap_peer/eap_ttls.o
OBJS_peer += ../src/eap_peer/eap_md5.o
OBJS_peer += ../src/eap_peer/eap_mschapv2.o
OBJS_peer += ../src/eap_peer/mschapv2.o
OBJS_peer += ../src/eap_peer/eap_otp.o
OBJS_peer += ../src/eap_peer/eap_gtc.o
OBJS_peer += ../src/eap_peer/eap_leap.o
OBJS_peer += ../src/eap_peer/eap_psk.o
OBJS_peer += ../src/eap_peer/eap_pax.o
OBJS_peer += ../src/eap_peer/eap_sake.o
OBJS_peer += ../src/eap_peer/eap_gpsk.o
OBJS_peer += ../src/eap_peer/eap.o
OBJS_peer += ../src/eap_common/eap_common.o
OBJS_peer += ../src/eap_peer/eap_methods.o
OBJS_peer += ../src/eap_peer/eap_tls_common.o
CFLAGS += -DEAP_TLS
CFLAGS += -DEAP_PEAP
CFLAGS += -DEAP_TTLS
CFLAGS += -DEAP_MD5
CFLAGS += -DEAP_MSCHAPv2
CFLAGS += -DEAP_GTC
CFLAGS += -DEAP_OTP
CFLAGS += -DEAP_LEAP
CFLAGS += -DEAP_PSK
CFLAGS += -DEAP_PAX
CFLAGS += -DEAP_SAKE
CFLAGS += -DEAP_GPSK -DEAP_GPSK_SHA256
CFLAGS += -DEAP_SERVER_IDENTITY
CFLAGS += -DEAP_SERVER_TLS
CFLAGS += -DEAP_SERVER_PEAP
CFLAGS += -DEAP_SERVER_TTLS
CFLAGS += -DEAP_SERVER_MD5
CFLAGS += -DEAP_SERVER_MSCHAPV2
CFLAGS += -DEAP_SERVER_GTC
CFLAGS += -DEAP_SERVER_PSK
CFLAGS += -DEAP_SERVER_PAX
CFLAGS += -DEAP_SERVER_SAKE
CFLAGS += -DEAP_SERVER_GPSK -DEAP_SERVER_GPSK_SHA256
CFLAGS += -DIEEE8021X_EAPOL
# Optional components to add EAP server support
OBJS_server += ../src/eap_server/eap_server_tls.o
OBJS_server += ../src/eap_server/eap_server_peap.o
OBJS_server += ../src/eap_server/eap_server_ttls.o
OBJS_server += ../src/eap_server/eap_server_md5.o
OBJS_server += ../src/eap_server/eap_server_mschapv2.o
OBJS_server += ../src/eap_server/eap_server_gtc.o
OBJS_server += ../src/eap_server/eap_server_psk.o
OBJS_server += ../src/eap_server/eap_server_pax.o
OBJS_server += ../src/eap_server/eap_server_sake.o
OBJS_server += ../src/eap_server/eap_server_gpsk.o
OBJS_server += ../src/eap_server/eap_server.o
OBJS_server += ../src/eap_server/eap_server_identity.o
OBJS_server += ../src/eap_server/eap_server_methods.o
OBJS_server += ../src/eap_server/eap_server_tls_common.o
CFLAGS += -DEAP_SERVER
OBJS_lib=$(OBJS_both) $(OBJS_peer) $(OBJS_server)
_OBJS_VAR := OBJS_lib
include ../src/objs.mk
OBJS_ex = eap_example.o eap_example_peer.o eap_example_server.o
_OBJS_VAR := OBJS_ex
include ../src/objs.mk
_OBJS_VAR := EAP_LIBS
include ../src/objs.mk
ifneq ($(CONFIG_SOLIB), yes)
LIBEAP = libeap.a
libeap.a: $(EAP_LIBS) $(OBJS_lib)
$(AR) crT libeap.a $^
$(RANLIB) libeap.a
else
CFLAGS += -fPIC -DPIC
LDFLAGS += -shared
LIBEAP = libeap.so
libeap.so: $(EAP_LIBS) $(OBJS_lib)
$(LDO) $(LDFLAGS) $^ -o $(LIBEAP)
endif
eap_example: $(OBJS_ex) $(LIBEAP)
$(LDO) $(LDFLAGS) -o eap_example $(OBJS_ex) -L. -leap $(LIBS)
clean: common-clean
rm -f core *~ *.o *.d libeap.a libeap.so
-include $(OBJS:%.o=%.d)

42
eap_example/README Normal file
View file

@ -0,0 +1,42 @@
EAP peer/server library and example program
Copyright (c) 2007, Jouni Malinen <j@w1.fi>
This software may be distributed under the terms of the BSD license.
See the parent directory README for more details.
The interfaces of the EAP server/peer implementation are based on RFC
4137 (EAP State Machines). This RFC is coordinated with the state
machines defined in IEEE 802.1X-2004. hostapd and wpa_supplicant
include implementation of the IEEE 802.1X EAPOL state machines and the
interface between them and EAP. However, the EAP implementation can be
used with other protocols, too, by providing a compatible interface
which maps the EAPOL<->EAP variables to another protocol.
This directory contains an example showing how EAP peer and server
code from wpa_supplicant and hostapd can be used as a library. The
example program initializes both an EAP server and an EAP peer
entities and then runs through an EAP-PEAP/MSCHAPv2 authentication.
eap_example_peer.c shows the initialization and glue code needed to
control the EAP peer implementation. eap_example_server.c does the
same for EAP server. eap_example.c is an example that ties in both the
EAP server and client parts to allow an EAP authentication to be
shown.
In this example, the EAP messages are passed between the server and
the peer are passed by direct function calls within the same process.
In practice, server and peer functionalities would likely reside in
separate devices and the EAP messages would be transmitted between the
devices based on an external protocol. For example, in IEEE 802.11
uses IEEE 802.1X EAPOL state machines to control the transmission of
EAP messages and WiMax supports optional PMK EAP authentication
mechanism that transmits EAP messages as defined in IEEE 802.16e.
The EAP library links in number of helper functions from src/utils and
src/crypto directories. Most of these are suitable as-is, but it may
be desirable to replace the debug output code in src/utils/wpa_debug.c
by dropping this file from the library and re-implementing the
functions there in a way that better fits in with the main
application.

55
eap_example/ca.pem Normal file
View file

@ -0,0 +1,55 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 15624081837803162817 (0xd8d3e3a6cbe3ccc1)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=FI, O=w1.fi, CN=Root CA
Validity
Not Before: Jun 29 16:41:22 2013 GMT
Not After : Jun 27 16:41:22 2023 GMT
Subject: C=FI, O=w1.fi, CN=Root CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (1024 bit)
Modulus:
00:be:1e:86:e4:79:03:c1:d1:94:d5:d4:b3:b1:28:
90:76:fb:b8:a6:cd:6d:1c:d1:48:f4:08:9a:67:ff:
f9:a6:54:b1:19:29:df:29:1b:cd:f1:6f:66:01:e7:
db:79:ce:c0:39:2a:25:13:26:94:0c:2c:7b:5a:2c:
81:0f:94:ee:51:d0:75:e6:46:db:17:46:a7:15:8b:
0e:57:0f:b0:54:76:63:12:ca:86:18:bc:1a:c3:16:
c0:70:09:d6:6b:43:39:b8:98:29:46:ac:cb:6a:ad:
38:88:3b:07:dc:81:cd:3a:f6:1d:f6:2f:ef:1d:d7:
ae:8a:b6:d1:e7:b3:15:02:b9
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14
X509v3 Authority Key Identifier:
keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14
X509v3 Basic Constraints:
CA:TRUE
Signature Algorithm: sha1WithRSAEncryption
1a:cf:77:60:44:43:c4:55:0e:99:e0:89:aa:b9:d3:7b:32:b7:
5c:9c:7c:ca:fe:8c:d4:94:c6:5e:f3:83:19:5f:29:59:68:a4:
4f:dc:04:2e:b8:71:c0:6d:3b:ae:01:e4:b9:88:99:cc:ce:82:
be:6a:28:c2:ac:6a:94:c6:87:90:ed:85:3c:10:71:c5:ff:3c:
70:64:e2:41:62:31:ea:86:7b:11:8c:93:ea:c6:f3:f3:4e:f9:
d4:f2:81:90:d7:f4:fa:a1:91:6e:d4:dd:15:3e:26:3b:ac:1e:
c3:c2:1f:ed:bb:34:bf:cb:b2:67:c6:c6:51:e8:51:22:b4:f3:
92:e8
-----BEGIN CERTIFICATE-----
MIICLDCCAZWgAwIBAgIJANjT46bL48zBMA0GCSqGSIb3DQEBBQUAMC8xCzAJBgNV
BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xMzA2
MjkxNjQxMjJaFw0yMzA2MjcxNjQxMjJaMC8xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
DAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
gYkCgYEAvh6G5HkDwdGU1dSzsSiQdvu4ps1tHNFI9AiaZ//5plSxGSnfKRvN8W9m
Aefbec7AOSolEyaUDCx7WiyBD5TuUdB15kbbF0anFYsOVw+wVHZjEsqGGLwawxbA
cAnWa0M5uJgpRqzLaq04iDsH3IHNOvYd9i/vHdeuirbR57MVArkCAwEAAaNQME4w
HQYDVR0OBBYEFLiS3v2KGLMww59V8zNdtMgpikEUMB8GA1UdIwQYMBaAFLiS3v2K
GLMww59V8zNdtMgpikEUMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEA
Gs93YERDxFUOmeCJqrnTezK3XJx8yv6M1JTGXvODGV8pWWikT9wELrhxwG07rgHk
uYiZzM6CvmoowqxqlMaHkO2FPBBxxf88cGTiQWIx6oZ7EYyT6sbz80751PKBkNf0
+qGRbtTdFT4mO6wew8If7bs0v8uyZ8bGUehRIrTzkug=
-----END CERTIFICATE-----

5
eap_example/dh.conf Normal file
View file

@ -0,0 +1,5 @@
-----BEGIN DH PARAMETERS-----
MIGHAoGBAP3V8IHq3H2DUlYywsvjYNuS17eCdt0mJo6/os6PHqdhgkMrPxF9u4Gr
qKXq9e6GqmZYdjta30N3FkXaV924BJ0xOqb2TntiKg4u50/l6hSUneWt6UFBaizd
XrqjNFIme/5RXMZ7RglXliBpCepAaFLMcKhOS4ulUyYYHSy+oqRjAgEC
-----END DH PARAMETERS-----

47
eap_example/eap_example.c Normal file
View file

@ -0,0 +1,47 @@
/*
* Example application showing how EAP peer and server code from
* wpa_supplicant/hostapd can be used as a library. This example program
* initializes both an EAP server and an EAP peer entities and then runs
* through an EAP-PEAP/MSCHAPv2 authentication.
* Copyright (c) 2007, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
int eap_example_peer_init(void);
void eap_example_peer_deinit(void);
int eap_example_peer_step(void);
int eap_example_server_init(void);
void eap_example_server_deinit(void);
int eap_example_server_step(void);
int main(int argc, char *argv[])
{
int res_s, res_p;
wpa_debug_level = 0;
if (eap_example_peer_init() < 0 ||
eap_example_server_init() < 0)
return -1;
do {
printf("---[ server ]--------------------------------\n");
res_s = eap_example_server_step();
printf("---[ peer ]----------------------------------\n");
res_p = eap_example_peer_step();
} while (res_s || res_p);
eap_example_peer_deinit();
eap_example_server_deinit();
return 0;
}

View file

@ -0,0 +1,377 @@
/*
* Example application showing how EAP peer code from wpa_supplicant can be
* used as a library.
* Copyright (c) 2007, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "eap_peer/eap.h"
#include "eap_peer/eap_config.h"
#include "wpabuf.h"
void eap_example_server_rx(const u8 *data, size_t data_len);
struct eap_peer_ctx {
bool eapSuccess;
bool eapRestart;
bool eapFail;
bool eapResp;
bool eapNoResp;
bool eapReq;
bool portEnabled;
bool altAccept; /* for EAP */
bool altReject; /* for EAP */
bool eapTriggerStart;
struct wpabuf *eapReqData; /* for EAP */
unsigned int idleWhile; /* for EAP state machine */
struct eap_peer_config eap_config;
struct eap_sm *eap;
};
static struct eap_peer_ctx eap_ctx;
static struct eap_peer_config * peer_get_config(void *ctx)
{
struct eap_peer_ctx *peer = ctx;
return &peer->eap_config;
}
static bool peer_get_bool(void *ctx, enum eapol_bool_var variable)
{
struct eap_peer_ctx *peer = ctx;
if (peer == NULL)
return false;
switch (variable) {
case EAPOL_eapSuccess:
return peer->eapSuccess;
case EAPOL_eapRestart:
return peer->eapRestart;
case EAPOL_eapFail:
return peer->eapFail;
case EAPOL_eapResp:
return peer->eapResp;
case EAPOL_eapNoResp:
return peer->eapNoResp;
case EAPOL_eapReq:
return peer->eapReq;
case EAPOL_portEnabled:
return peer->portEnabled;
case EAPOL_altAccept:
return peer->altAccept;
case EAPOL_altReject:
return peer->altReject;
case EAPOL_eapTriggerStart:
return peer->eapTriggerStart;
}
return false;
}
static void peer_set_bool(void *ctx, enum eapol_bool_var variable, bool value)
{
struct eap_peer_ctx *peer = ctx;
if (peer == NULL)
return;
switch (variable) {
case EAPOL_eapSuccess:
peer->eapSuccess = value;
break;
case EAPOL_eapRestart:
peer->eapRestart = value;
break;
case EAPOL_eapFail:
peer->eapFail = value;
break;
case EAPOL_eapResp:
peer->eapResp = value;
break;
case EAPOL_eapNoResp:
peer->eapNoResp = value;
break;
case EAPOL_eapReq:
peer->eapReq = value;
break;
case EAPOL_portEnabled:
peer->portEnabled = value;
break;
case EAPOL_altAccept:
peer->altAccept = value;
break;
case EAPOL_altReject:
peer->altReject = value;
break;
case EAPOL_eapTriggerStart:
peer->eapTriggerStart = value;
break;
}
}
static unsigned int peer_get_int(void *ctx, enum eapol_int_var variable)
{
struct eap_peer_ctx *peer = ctx;
if (peer == NULL)
return 0;
switch (variable) {
case EAPOL_idleWhile:
return peer->idleWhile;
}
return 0;
}
static void peer_set_int(void *ctx, enum eapol_int_var variable,
unsigned int value)
{
struct eap_peer_ctx *peer = ctx;
if (peer == NULL)
return;
switch (variable) {
case EAPOL_idleWhile:
peer->idleWhile = value;
break;
}
}
static struct wpabuf * peer_get_eapReqData(void *ctx)
{
struct eap_peer_ctx *peer = ctx;
if (peer == NULL || peer->eapReqData == NULL)
return NULL;
return peer->eapReqData;
}
static void peer_set_config_blob(void *ctx, struct wpa_config_blob *blob)
{
printf("TODO: %s\n", __func__);
}
static const struct wpa_config_blob *
peer_get_config_blob(void *ctx, const char *name)
{
printf("TODO: %s\n", __func__);
return NULL;
}
static void peer_notify_pending(void *ctx)
{
printf("TODO: %s\n", __func__);
}
static int eap_peer_register_methods(void)
{
int ret = 0;
#ifdef EAP_MD5
if (ret == 0)
ret = eap_peer_md5_register();
#endif /* EAP_MD5 */
#ifdef EAP_TLS
if (ret == 0)
ret = eap_peer_tls_register();
#endif /* EAP_TLS */
#ifdef EAP_MSCHAPv2
if (ret == 0)
ret = eap_peer_mschapv2_register();
#endif /* EAP_MSCHAPv2 */
#ifdef EAP_PEAP
if (ret == 0)
ret = eap_peer_peap_register();
#endif /* EAP_PEAP */
#ifdef EAP_TTLS
if (ret == 0)
ret = eap_peer_ttls_register();
#endif /* EAP_TTLS */
#ifdef EAP_GTC
if (ret == 0)
ret = eap_peer_gtc_register();
#endif /* EAP_GTC */
#ifdef EAP_OTP
if (ret == 0)
ret = eap_peer_otp_register();
#endif /* EAP_OTP */
#ifdef EAP_SIM
if (ret == 0)
ret = eap_peer_sim_register();
#endif /* EAP_SIM */
#ifdef EAP_LEAP
if (ret == 0)
ret = eap_peer_leap_register();
#endif /* EAP_LEAP */
#ifdef EAP_PSK
if (ret == 0)
ret = eap_peer_psk_register();
#endif /* EAP_PSK */
#ifdef EAP_AKA
if (ret == 0)
ret = eap_peer_aka_register();
#endif /* EAP_AKA */
#ifdef EAP_AKA_PRIME
if (ret == 0)
ret = eap_peer_aka_prime_register();
#endif /* EAP_AKA_PRIME */
#ifdef EAP_FAST
if (ret == 0)
ret = eap_peer_fast_register();
#endif /* EAP_FAST */
#ifdef EAP_PAX
if (ret == 0)
ret = eap_peer_pax_register();
#endif /* EAP_PAX */
#ifdef EAP_SAKE
if (ret == 0)
ret = eap_peer_sake_register();
#endif /* EAP_SAKE */
#ifdef EAP_GPSK
if (ret == 0)
ret = eap_peer_gpsk_register();
#endif /* EAP_GPSK */
#ifdef EAP_WSC
if (ret == 0)
ret = eap_peer_wsc_register();
#endif /* EAP_WSC */
#ifdef EAP_IKEV2
if (ret == 0)
ret = eap_peer_ikev2_register();
#endif /* EAP_IKEV2 */
#ifdef EAP_VENDOR_TEST
if (ret == 0)
ret = eap_peer_vendor_test_register();
#endif /* EAP_VENDOR_TEST */
#ifdef EAP_TNC
if (ret == 0)
ret = eap_peer_tnc_register();
#endif /* EAP_TNC */
return ret;
}
static struct eapol_callbacks eap_cb;
static struct eap_config eap_conf;
int eap_example_peer_init(void)
{
if (eap_peer_register_methods() < 0)
return -1;
os_memset(&eap_ctx, 0, sizeof(eap_ctx));
eap_ctx.eap_config.identity = (u8 *) os_strdup("user");
eap_ctx.eap_config.identity_len = 4;
eap_ctx.eap_config.password = (u8 *) os_strdup("password");
eap_ctx.eap_config.password_len = 8;
eap_ctx.eap_config.cert.ca_cert = os_strdup("ca.pem");
eap_ctx.eap_config.fragment_size = 1398;
os_memset(&eap_cb, 0, sizeof(eap_cb));
eap_cb.get_config = peer_get_config;
eap_cb.get_bool = peer_get_bool;
eap_cb.set_bool = peer_set_bool;
eap_cb.get_int = peer_get_int;
eap_cb.set_int = peer_set_int;
eap_cb.get_eapReqData = peer_get_eapReqData;
eap_cb.set_config_blob = peer_set_config_blob;
eap_cb.get_config_blob = peer_get_config_blob;
eap_cb.notify_pending = peer_notify_pending;
os_memset(&eap_conf, 0, sizeof(eap_conf));
eap_ctx.eap = eap_peer_sm_init(&eap_ctx, &eap_cb, &eap_ctx, &eap_conf);
if (eap_ctx.eap == NULL)
return -1;
/* Enable "port" to allow authentication */
eap_ctx.portEnabled = true;
return 0;
}
void eap_example_peer_deinit(void)
{
eap_peer_sm_deinit(eap_ctx.eap);
eap_peer_unregister_methods();
wpabuf_free(eap_ctx.eapReqData);
os_free(eap_ctx.eap_config.identity);
os_free(eap_ctx.eap_config.password);
os_free(eap_ctx.eap_config.cert.ca_cert);
}
int eap_example_peer_step(void)
{
int res;
res = eap_peer_sm_step(eap_ctx.eap);
if (eap_ctx.eapResp) {
struct wpabuf *resp;
printf("==> Response\n");
eap_ctx.eapResp = false;
resp = eap_get_eapRespData(eap_ctx.eap);
if (resp) {
/* Send EAP response to the server */
eap_example_server_rx(wpabuf_head(resp),
wpabuf_len(resp));
wpabuf_free(resp);
}
}
if (eap_ctx.eapSuccess) {
res = 0;
if (eap_key_available(eap_ctx.eap)) {
const u8 *key;
size_t key_len;
key = eap_get_eapKeyData(eap_ctx.eap, &key_len);
wpa_hexdump(MSG_DEBUG, "EAP keying material",
key, key_len);
}
}
return res;
}
void eap_example_peer_rx(const u8 *data, size_t data_len)
{
/* Make received EAP message available to the EAP library */
eap_ctx.eapReq = true;
wpabuf_free(eap_ctx.eapReqData);
eap_ctx.eapReqData = wpabuf_alloc_copy(data, data_len);
}

View file

@ -0,0 +1,300 @@
/*
* Example application showing how EAP server code from hostapd can be used as
* a library.
* Copyright (c) 2007, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "crypto/tls.h"
#include "eap_server/eap.h"
#include "wpabuf.h"
void eap_example_peer_rx(const u8 *data, size_t data_len);
struct eap_server_ctx {
struct eap_eapol_interface *eap_if;
struct eap_sm *eap;
void *tls_ctx;
};
static struct eap_server_ctx eap_ctx;
static int server_get_eap_user(void *ctx, const u8 *identity,
size_t identity_len, int phase2,
struct eap_user *user)
{
os_memset(user, 0, sizeof(*user));
if (!phase2) {
/* Only allow EAP-PEAP as the Phase 1 method */
user->methods[0].vendor = EAP_VENDOR_IETF;
user->methods[0].method = EAP_TYPE_PEAP;
return 0;
}
if (identity_len != 4 || identity == NULL ||
os_memcmp(identity, "user", 4) != 0) {
printf("Unknown user\n");
return -1;
}
/* Only allow EAP-MSCHAPv2 as the Phase 2 method */
user->methods[0].vendor = EAP_VENDOR_IETF;
user->methods[0].method = EAP_TYPE_MSCHAPV2;
user->password = (u8 *) os_strdup("password");
user->password_len = 8;
return 0;
}
static const char * server_get_eap_req_id_text(void *ctx, size_t *len)
{
*len = 0;
return NULL;
}
static struct eapol_callbacks eap_cb;
static struct eap_config eap_conf;
static int eap_example_server_init_tls(void)
{
struct tls_config tconf;
struct tls_connection_params tparams;
os_memset(&tconf, 0, sizeof(tconf));
eap_ctx.tls_ctx = tls_init(&tconf);
if (eap_ctx.tls_ctx == NULL)
return -1;
os_memset(&tparams, 0, sizeof(tparams));
tparams.ca_cert = "ca.pem";
tparams.client_cert = "server.pem";
/* tparams.private_key = "server.key"; */
tparams.private_key = "server-key.pem";
/* tparams.private_key_passwd = "whatever"; */
tparams.dh_file = "dh.conf";
if (tls_global_set_params(eap_ctx.tls_ctx, &tparams)) {
printf("Failed to set TLS parameters\n");
return -1;
}
if (tls_global_set_verify(eap_ctx.tls_ctx, 0, 1)) {
printf("Failed to set check_crl\n");
return -1;
}
return 0;
}
static int eap_server_register_methods(void)
{
int ret = 0;
#ifdef EAP_SERVER_IDENTITY
if (ret == 0)
ret = eap_server_identity_register();
#endif /* EAP_SERVER_IDENTITY */
#ifdef EAP_SERVER_MD5
if (ret == 0)
ret = eap_server_md5_register();
#endif /* EAP_SERVER_MD5 */
#ifdef EAP_SERVER_TLS
if (ret == 0)
ret = eap_server_tls_register();
#endif /* EAP_SERVER_TLS */
#ifdef EAP_SERVER_MSCHAPV2
if (ret == 0)
ret = eap_server_mschapv2_register();
#endif /* EAP_SERVER_MSCHAPV2 */
#ifdef EAP_SERVER_PEAP
if (ret == 0)
ret = eap_server_peap_register();
#endif /* EAP_SERVER_PEAP */
#ifdef EAP_SERVER_TLV
if (ret == 0)
ret = eap_server_tlv_register();
#endif /* EAP_SERVER_TLV */
#ifdef EAP_SERVER_GTC
if (ret == 0)
ret = eap_server_gtc_register();
#endif /* EAP_SERVER_GTC */
#ifdef EAP_SERVER_TTLS
if (ret == 0)
ret = eap_server_ttls_register();
#endif /* EAP_SERVER_TTLS */
#ifdef EAP_SERVER_SIM
if (ret == 0)
ret = eap_server_sim_register();
#endif /* EAP_SERVER_SIM */
#ifdef EAP_SERVER_AKA
if (ret == 0)
ret = eap_server_aka_register();
#endif /* EAP_SERVER_AKA */
#ifdef EAP_SERVER_AKA_PRIME
if (ret == 0)
ret = eap_server_aka_prime_register();
#endif /* EAP_SERVER_AKA_PRIME */
#ifdef EAP_SERVER_PAX
if (ret == 0)
ret = eap_server_pax_register();
#endif /* EAP_SERVER_PAX */
#ifdef EAP_SERVER_PSK
if (ret == 0)
ret = eap_server_psk_register();
#endif /* EAP_SERVER_PSK */
#ifdef EAP_SERVER_SAKE
if (ret == 0)
ret = eap_server_sake_register();
#endif /* EAP_SERVER_SAKE */
#ifdef EAP_SERVER_GPSK
if (ret == 0)
ret = eap_server_gpsk_register();
#endif /* EAP_SERVER_GPSK */
#ifdef EAP_SERVER_VENDOR_TEST
if (ret == 0)
ret = eap_server_vendor_test_register();
#endif /* EAP_SERVER_VENDOR_TEST */
#ifdef EAP_SERVER_FAST
if (ret == 0)
ret = eap_server_fast_register();
#endif /* EAP_SERVER_FAST */
#ifdef EAP_SERVER_WSC
if (ret == 0)
ret = eap_server_wsc_register();
#endif /* EAP_SERVER_WSC */
#ifdef EAP_SERVER_IKEV2
if (ret == 0)
ret = eap_server_ikev2_register();
#endif /* EAP_SERVER_IKEV2 */
#ifdef EAP_SERVER_TNC
if (ret == 0)
ret = eap_server_tnc_register();
#endif /* EAP_SERVER_TNC */
return ret;
}
int eap_example_server_init(void)
{
struct eap_session_data eap_sess;
if (eap_server_register_methods() < 0)
return -1;
os_memset(&eap_ctx, 0, sizeof(eap_ctx));
if (eap_example_server_init_tls() < 0)
return -1;
os_memset(&eap_cb, 0, sizeof(eap_cb));
eap_cb.get_eap_user = server_get_eap_user;
eap_cb.get_eap_req_id_text = server_get_eap_req_id_text;
os_memset(&eap_conf, 0, sizeof(eap_conf));
eap_conf.eap_server = 1;
eap_conf.ssl_ctx = eap_ctx.tls_ctx;
os_memset(&eap_sess, 0, sizeof(eap_sess));
eap_ctx.eap = eap_server_sm_init(&eap_ctx, &eap_cb, &eap_conf,
&eap_sess);
if (eap_ctx.eap == NULL)
return -1;
eap_ctx.eap_if = eap_get_interface(eap_ctx.eap);
/* Enable "port" and request EAP to start authentication. */
eap_ctx.eap_if->portEnabled = true;
eap_ctx.eap_if->eapRestart = true;
return 0;
}
void eap_example_server_deinit(void)
{
eap_server_sm_deinit(eap_ctx.eap);
eap_server_unregister_methods();
tls_deinit(eap_ctx.tls_ctx);
}
int eap_example_server_step(void)
{
int res, process = 0;
res = eap_server_sm_step(eap_ctx.eap);
if (eap_ctx.eap_if->eapReq) {
printf("==> Request\n");
process = 1;
eap_ctx.eap_if->eapReq = 0;
}
if (eap_ctx.eap_if->eapSuccess) {
printf("==> Success\n");
process = 1;
res = 0;
eap_ctx.eap_if->eapSuccess = 0;
if (eap_ctx.eap_if->eapKeyAvailable) {
wpa_hexdump(MSG_DEBUG, "EAP keying material",
eap_ctx.eap_if->eapKeyData,
eap_ctx.eap_if->eapKeyDataLen);
}
}
if (eap_ctx.eap_if->eapFail) {
printf("==> Fail\n");
process = 1;
eap_ctx.eap_if->eapFail = 0;
}
if (process && eap_ctx.eap_if->eapReqData) {
/* Send EAP request to the peer */
eap_example_peer_rx(wpabuf_head(eap_ctx.eap_if->eapReqData),
wpabuf_len(eap_ctx.eap_if->eapReqData));
}
return res;
}
void eap_example_server_rx(const u8 *data, size_t data_len)
{
/* Make received EAP message available to the EAP library */
wpabuf_free(eap_ctx.eap_if->eapRespData);
eap_ctx.eap_if->eapRespData = wpabuf_alloc_copy(data, data_len);
if (eap_ctx.eap_if->eapRespData)
eap_ctx.eap_if->eapResp = true;
}

View file

@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQC6oHdVIhSFVWWbZCyt7ZvdZTHJ2mBQzjjWNNzovBueMOcS41Ns
ye1IA3mBaZjOirh3RzZFz8bg8XsecYlU9wHMIq2gQrGoNZ5gqjqYUdD/H+6+jQpj
+6I5F/JkYfZlAjJ5dOGf0YllVanDIJ6/aVaz908/qVTC2o88r/J1VPp+gQIDAQAB
AoGAR/C5b3DOtkMgAtGPw5AXiDWNBsGOZTfJgxEnovN4Nfel64sDyqjgNeVY/kDl
baDd0OT7j9ezU1zi1+5uQPlikFSvzgpdLgQhKkvWLzzehafb2uVaJ4VsRqS3WXK8
RE06cYx4VQRkvQvMAXWsuua9pw36OrlpQnm3HlAbrks8Mm0CQQDgMEu2WPMWP2wj
Q8735zbj7D0AxEFlcegPZr/QZ3qU//G0HL35FG18lsuTbDzesrf7apo3W1BBQLjS
ZSNtyNsLAkEA1Ru6aEy/Cj2u1GYHu1u/RcshKC+W7rdVT0wDeiSTUzKafZNiwVhY
1Epk4k5HnHB327ysTI1LiOzUMMmuNYUkIwJAKUkbmFAXLCCv5GqnYcXluOGXdl2u
AWWRq8xrRJDZ5TihJV8pqQYXB5upj9Od/hEBir5d+hXJ2Mp3ft97P8t+cwJAGeWQ
tXP+EySDxlPPxLjVeYnBsbx2vvOQbl5yXblsHcQcef4bFhvCT6nqsIWKtjwElLNM
zNCuySjecD9R6DcRuQJBAJWrpgny77wP29x1WQ/29J8ZJfxe4N5wAj1SePBVNgZ3
gfm1O+c6niNwe8RnfQimppLrrR+qK33te2SPGXiwi6g=
-----END RSA PRIVATE KEY-----

16
eap_example/server.key Normal file
View file

@ -0,0 +1,16 @@
-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALqgd1UiFIVVZZtk
LK3tm91lMcnaYFDOONY03Oi8G54w5xLjU2zJ7UgDeYFpmM6KuHdHNkXPxuDxex5x
iVT3AcwiraBCsag1nmCqOphR0P8f7r6NCmP7ojkX8mRh9mUCMnl04Z/RiWVVqcMg
nr9pVrP3Tz+pVMLajzyv8nVU+n6BAgMBAAECgYBH8LlvcM62QyAC0Y/DkBeINY0G
wY5lN8mDESei83g196XriwPKqOA15Vj+QOVtoN3Q5PuP17NTXOLX7m5A+WKQVK/O
Cl0uBCEqS9YvPN6Fp9va5VonhWxGpLdZcrxETTpxjHhVBGS9C8wBday65r2nDfo6
uWlCebceUBuuSzwybQJBAOAwS7ZY8xY/bCNDzvfnNuPsPQDEQWVx6A9mv9BnepT/
8bQcvfkUbXyWy5NsPN6yt/tqmjdbUEFAuNJlI23I2wsCQQDVG7poTL8KPa7UZge7
W79FyyEoL5but1VPTAN6JJNTMpp9k2LBWFjUSmTiTkeccHfbvKxMjUuI7NQwya41
hSQjAkApSRuYUBcsIK/kaqdhxeW44Zd2Xa4BZZGrzGtEkNnlOKElXympBhcHm6mP
053+EQGKvl36FcnYynd+33s/y35zAkAZ5ZC1c/4TJIPGU8/EuNV5icGxvHa+85Bu
XnJduWwdxBx5/hsWG8JPqeqwhYq2PASUs0zM0K7JKN5wP1HoNxG5AkEAlaumCfLv
vA/b3HVZD/b0nxkl/F7g3nACPVJ48FU2BneB+bU75zqeI3B7xGd9CKamkuutH6or
fe17ZI8ZeLCLqA==
-----END PRIVATE KEY-----

64
eap_example/server.pem Normal file
View file

@ -0,0 +1,64 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 15624081837803162903 (0xd8d3e3a6cbe3cd17)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=FI, O=w1.fi, CN=Root CA
Validity
Not Before: Oct 3 22:13:55 2018 GMT
Not After : Oct 3 22:13:55 2019 GMT
Subject: C=FI, O=w1.fi, CN=server.w1.fi
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (1024 bit)
Modulus:
00:ba:a0:77:55:22:14:85:55:65:9b:64:2c:ad:ed:
9b:dd:65:31:c9:da:60:50:ce:38:d6:34:dc:e8:bc:
1b:9e:30:e7:12:e3:53:6c:c9:ed:48:03:79:81:69:
98:ce:8a:b8:77:47:36:45:cf:c6:e0:f1:7b:1e:71:
89:54:f7:01:cc:22:ad:a0:42:b1:a8:35:9e:60:aa:
3a:98:51:d0:ff:1f:ee:be:8d:0a:63:fb:a2:39:17:
f2:64:61:f6:65:02:32:79:74:e1:9f:d1:89:65:55:
a9:c3:20:9e:bf:69:56:b3:f7:4f:3f:a9:54:c2:da:
8f:3c:af:f2:75:54:fa:7e:81
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
X509v3 Subject Key Identifier:
31:4F:10:5C:67:9F:BE:4E:88:D6:DC:C5:AB:9E:12:88:86:69:02:4F
X509v3 Authority Key Identifier:
keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14
Authority Information Access:
OCSP - URI:http://server.w1.fi:8888/
X509v3 Subject Alternative Name:
DNS:server.w1.fi
X509v3 Extended Key Usage:
TLS Web Server Authentication
Signature Algorithm: sha256WithRSAEncryption
b6:98:ae:d9:9b:9a:44:49:b2:06:ee:af:36:83:cb:cd:cb:c9:
f3:38:6d:65:cb:e9:81:d2:25:dd:76:12:5c:da:3f:a1:0e:11:
a5:04:ed:05:29:2d:66:94:82:a2:80:67:d1:d8:78:71:72:5f:
10:c3:51:a2:7b:f5:0b:5f:ec:70:12:99:cb:65:6f:50:7f:2b:
05:7c:b4:d7:1b:21:77:66:47:33:f3:a7:d6:fb:ce:97:fe:5f:
fd:df:1f:1d:6f:ef:22:5a:c6:78:d2:2b:07:1e:55:ec:80:62:
06:7a:be:6a:0d:4d:96:c2:d5:df:76:56:b0:85:6a:f8:a0:27:
62:31
-----BEGIN CERTIFICATE-----
MIIClTCCAf6gAwIBAgIJANjT46bL480XMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV
BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xODEw
MDMyMjEzNTVaFw0xOTEwMDMyMjEzNTVaMDQxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK
DAV3MS5maTEVMBMGA1UEAwwMc2VydmVyLncxLmZpMIGfMA0GCSqGSIb3DQEBAQUA
A4GNADCBiQKBgQC6oHdVIhSFVWWbZCyt7ZvdZTHJ2mBQzjjWNNzovBueMOcS41Ns
ye1IA3mBaZjOirh3RzZFz8bg8XsecYlU9wHMIq2gQrGoNZ5gqjqYUdD/H+6+jQpj
+6I5F/JkYfZlAjJ5dOGf0YllVanDIJ6/aVaz908/qVTC2o88r/J1VPp+gQIDAQAB
o4GzMIGwMAkGA1UdEwQCMAAwHQYDVR0OBBYEFDFPEFxnn75OiNbcxaueEoiGaQJP
MB8GA1UdIwQYMBaAFLiS3v2KGLMww59V8zNdtMgpikEUMDUGCCsGAQUFBwEBBCkw
JzAlBggrBgEFBQcwAYYZaHR0cDovL3NlcnZlci53MS5maTo4ODg4LzAXBgNVHREE
EDAOggxzZXJ2ZXIudzEuZmkwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcN
AQELBQADgYEAtpiu2ZuaREmyBu6vNoPLzcvJ8zhtZcvpgdIl3XYSXNo/oQ4RpQTt
BSktZpSCooBn0dh4cXJfEMNRonv1C1/scBKZy2VvUH8rBXy01xshd2ZHM/On1vvO
l/5f/d8fHW/vIlrGeNIrBx5V7IBiBnq+ag1NlsLV33ZWsIVq+KAnYjE=
-----END CERTIFICATE-----

5
hostapd/.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
.config
hostapd
hostapd_cli
hlr_auc_gw
nt_password_hash

View file

@ -145,6 +145,7 @@ OBJS += src/utils/wpa_debug.c
OBJS += src/utils/wpabuf.c
OBJS += src/utils/os_$(CONFIG_OS).c
OBJS += src/utils/ip_addr.c
OBJS += src/utils/crc32.c
OBJS += src/common/ieee802_11_common.c
OBJS += src/common/wpa_common.c
@ -205,18 +206,12 @@ endif
L_CFLAGS += -DCONFIG_CTRL_IFACE -DCONFIG_CTRL_IFACE_UNIX
ifdef CONFIG_IAPP
L_CFLAGS += -DCONFIG_IAPP
OBJS += src/ap/iapp.c
endif
ifdef CONFIG_RSN_PREAUTH
L_CFLAGS += -DCONFIG_RSN_PREAUTH
CONFIG_L2_PACKET=y
endif
ifdef CONFIG_HS20
NEED_AES_OMAC1=y
CONFIG_PROXYARP=y
endif
@ -226,8 +221,6 @@ endif
ifdef CONFIG_SUITEB
L_CFLAGS += -DCONFIG_SUITEB
NEED_SHA256=y
NEED_AES_OMAC1=y
endif
ifdef CONFIG_SUITEB192
@ -238,24 +231,14 @@ endif
ifdef CONFIG_OCV
L_CFLAGS += -DCONFIG_OCV
OBJS += src/common/ocv.c
CONFIG_IEEE80211W=y
endif
ifdef CONFIG_IEEE80211W
L_CFLAGS += -DCONFIG_IEEE80211W
NEED_SHA256=y
NEED_AES_OMAC1=y
endif
ifdef CONFIG_IEEE80211R
L_CFLAGS += -DCONFIG_IEEE80211R -DCONFIG_IEEE80211R_AP
OBJS += src/ap/wpa_auth_ft.c
NEED_SHA256=y
NEED_AES_OMAC1=y
NEED_AES_UNWRAP=y
NEED_AES_SIV=y
NEED_ETH_P_OUI=y
NEED_SHA256=y
NEED_HMAC_SHA256_KDF=y
endif
@ -267,8 +250,13 @@ endif
ifdef CONFIG_SAE
L_CFLAGS += -DCONFIG_SAE
OBJS += src/common/sae.c
ifdef CONFIG_SAE_PK
L_CFLAGS += -DCONFIG_SAE_PK
OBJS += src/common/sae_pk.c
endif
NEED_ECC=y
NEED_DH_GROUPS=y
NEED_HMAC_SHA256_KDF=y
NEED_DRAGONFLY=y
endif
@ -278,7 +266,6 @@ NEED_ECC=y
NEED_HMAC_SHA256_KDF=y
NEED_HMAC_SHA384_KDF=y
NEED_HMAC_SHA512_KDF=y
NEED_SHA256=y
NEED_SHA384=y
NEED_SHA512=y
endif
@ -299,10 +286,6 @@ L_CFLAGS += -DCONFIG_WNM -DCONFIG_WNM_AP
OBJS += src/ap/wnm_ap.c
endif
ifdef CONFIG_IEEE80211N
L_CFLAGS += -DCONFIG_IEEE80211N
endif
ifdef CONFIG_IEEE80211AC
L_CFLAGS += -DCONFIG_IEEE80211AC
endif
@ -331,6 +314,14 @@ OBJS += src/fst/fst_ctrl_iface.c
endif
endif
ifdef CONFIG_WEP
L_CFLAGS += -DCONFIG_WEP
endif
ifdef CONFIG_NO_TKIP
L_CFLAGS += -DCONFIG_NO_TKIP
endif
include $(LOCAL_PATH)/src/drivers/drivers.mk
@ -413,7 +404,6 @@ ifdef CONFIG_EAP_AKA
L_CFLAGS += -DEAP_SERVER_AKA
OBJS += src/eap_server/eap_server_aka.c
CONFIG_EAP_SIM_COMMON=y
NEED_SHA256=y
NEED_AES_CBC=y
endif
@ -424,7 +414,7 @@ endif
ifdef CONFIG_EAP_SIM_COMMON
OBJS += src/eap_common/eap_sim_common.c
# Example EAP-SIM/AKA interface for GSM/UMTS authentication. This can be
# replaced with another file implementating the interface specified in
# replaced with another file implementing the interface specified in
# eap_sim_db.h.
OBJS += src/eap_server/eap_sim_db.c
NEED_FIPS186_2_PRF=y
@ -438,7 +428,6 @@ endif
ifdef CONFIG_EAP_PSK
L_CFLAGS += -DEAP_SERVER_PSK
OBJS += src/eap_server/eap_server_psk.c src/eap_common/eap_psk_common.c
NEED_AES_OMAC1=y
NEED_AES_ENCBLOCK=y
NEED_AES_EAX=y
endif
@ -454,14 +443,11 @@ OBJS += src/eap_server/eap_server_gpsk.c src/eap_common/eap_gpsk_common.c
ifdef CONFIG_EAP_GPSK_SHA256
L_CFLAGS += -DEAP_GPSK_SHA256
endif
NEED_SHA256=y
NEED_AES_OMAC1=y
endif
ifdef CONFIG_EAP_PWD
L_CFLAGS += -DEAP_SERVER_PWD
OBJS += src/eap_server/eap_server_pwd.c src/eap_common/eap_pwd_common.c
NEED_SHA256=y
NEED_ECC=y
NEED_DRAGONFLY=y
endif
@ -494,6 +480,8 @@ OBJS += src/eap_common/eap_teap_common.c
TLS_FUNCS=y
NEED_T_PRF=y
NEED_SHA384=y
NEED_TLS_PRF_SHA256=y
NEED_TLS_PRF_SHA384=y
NEED_AES_UNWRAP=y
endif
@ -511,7 +499,6 @@ OBJS += src/wps/wps_dev_attr.c
OBJS += src/wps/wps_enrollee.c
OBJS += src/wps/wps_registrar.c
NEED_DH_GROUPS=y
NEED_SHA256=y
NEED_BASE64=y
NEED_AES_CBC=y
NEED_MODEXP=y
@ -554,23 +541,40 @@ endif
ifdef CONFIG_DPP
L_CFLAGS += -DCONFIG_DPP
OBJS += src/common/dpp.c
OBJS += src/common/dpp_auth.c
OBJS += src/common/dpp_backup.c
OBJS += src/common/dpp_crypto.c
OBJS += src/common/dpp_pkex.c
OBJS += src/common/dpp_reconfig.c
OBJS += src/common/dpp_tcp.c
OBJS += src/ap/dpp_hostapd.c
OBJS += src/ap/gas_query_ap.c
NEED_AES_SIV=y
NEED_HMAC_SHA256_KDF=y
NEED_HMAC_SHA384_KDF=y
NEED_HMAC_SHA512_KDF=y
NEED_SHA256=y
NEED_SHA384=y
NEED_SHA512=y
NEED_ECC=y
NEED_JSON=y
NEED_GAS=y
NEED_BASE64=y
NEED_ASN1=y
ifdef CONFIG_DPP2
L_CFLAGS += -DCONFIG_DPP2
endif
endif
ifdef CONFIG_PASN
L_CFLAGS += -DCONFIG_PASN
L_CFLAGS += -DCONFIG_PTKSA_CACHE
NEED_HMAC_SHA256_KDF=y
NEED_HMAC_SHA384_KDF=y
NEED_SHA256=y
NEED_SHA384=y
OBJS += src/common/ptksa_cache.c
endif
ifdef CONFIG_EAP_IKEV2
L_CFLAGS += -DEAP_SERVER_IKEV2
OBJS += src/eap_server/eap_server_ikev2.c src/eap_server/ikev2.c
@ -639,7 +643,6 @@ endif
ifdef CONFIG_TLSV12
L_CFLAGS += -DCONFIG_TLSV12
NEED_SHA256=y
endif
ifeq ($(CONFIG_TLS), openssl)
@ -653,7 +656,6 @@ HOBJS += src/crypto/crypto_openssl.c
ifdef NEED_FIPS186_2_PRF
OBJS += src/crypto/fips_prf_openssl.c
endif
NEED_SHA256=y
NEED_TLS_PRF_SHA256=y
LIBS += -lcrypto
LIBS_h += -lcrypto
@ -705,13 +707,12 @@ OBJS += src/tls/tlsv1_cred.c
OBJS += src/tls/tlsv1_server.c
OBJS += src/tls/tlsv1_server_write.c
OBJS += src/tls/tlsv1_server_read.c
OBJS += src/tls/asn1.c
OBJS += src/tls/rsa.c
OBJS += src/tls/x509v3.c
OBJS += src/tls/pkcs1.c
OBJS += src/tls/pkcs5.c
OBJS += src/tls/pkcs8.c
NEED_SHA256=y
NEED_ASN1=y
NEED_BASE64=y
NEED_TLS_PRF=y
ifdef CONFIG_TLSV12
@ -806,12 +807,10 @@ endif
ifdef NEED_AES_EAX
AESOBJS += src/crypto/aes-eax.c
NEED_AES_CTR=y
NEED_AES_OMAC1=y
endif
ifdef NEED_AES_SIV
AESOBJS += src/crypto/aes-siv.c
NEED_AES_CTR=y
NEED_AES_OMAC1=y
endif
ifdef NEED_AES_CTR
AESOBJS += src/crypto/aes-ctr.c
@ -819,9 +818,7 @@ endif
ifdef NEED_AES_ENCBLOCK
AESOBJS += src/crypto/aes-encblock.c
endif
ifdef NEED_AES_OMAC1
AESOBJS += src/crypto/aes-omac1.c
endif
ifdef NEED_AES_UNWRAP
ifneq ($(CONFIG_TLS), openssl)
NEED_AES_DEC=y
@ -909,7 +906,6 @@ endif
endif
endif
ifdef NEED_SHA256
L_CFLAGS += -DCONFIG_SHA256
ifneq ($(CONFIG_TLS), openssl)
ifneq ($(CONFIG_TLS), gnutls)
@ -923,6 +919,9 @@ endif
ifdef NEED_TLS_PRF_SHA256
OBJS += src/crypto/sha256-tlsprf.c
endif
ifdef NEED_TLS_PRF_SHA384
OBJS += src/crypto/sha384-tlsprf.c
endif
ifdef NEED_HMAC_SHA256_KDF
OBJS += src/crypto/sha256-kdf.c
endif
@ -932,7 +931,6 @@ endif
ifdef NEED_HMAC_SHA512_KDF
OBJS += src/crypto/sha512-kdf.c
endif
endif
ifdef NEED_SHA384
L_CFLAGS += -DCONFIG_SHA384
ifneq ($(CONFIG_TLS), openssl)
@ -964,6 +962,10 @@ L_CFLAGS += -DCONFIG_INTERNAL_SHA512
OBJS += src/crypto/sha512-internal.c
endif
ifdef NEED_ASN1
OBJS += src/tls/asn1.c
endif
ifdef NEED_DH_GROUPS
OBJS += src/crypto/dh_groups.c
endif
@ -1022,9 +1024,7 @@ OBJS += src/ap/hw_features.c
OBJS += src/ap/dfs.c
L_CFLAGS += -DNEED_AP_MLME
endif
ifdef CONFIG_IEEE80211N
OBJS += src/ap/ieee802_11_ht.c
endif
ifdef CONFIG_IEEE80211AC
OBJS += src/ap/ieee802_11_vht.c

View file

@ -362,7 +362,7 @@ ChangeLog for hostapd
* RADIUS server functionality
- add minimal RADIUS accounting server support (hostapd-as-server);
this is mainly to enable testing coverage with hwsim scripts
- allow authentication log to be written into SQLite databse
- allow authentication log to be written into SQLite database
- added option for TLS protocol testing of an EAP peer by simulating
various misbehaviors/known attacks
- MAC ACL support for testing purposes
@ -668,7 +668,7 @@ ChangeLog for hostapd
* fixed HT Capabilities IE with nl80211 drivers
* moved generic AP functionality code into src/ap
* WPS: handle Selected Registrar as union of info from all Registrars
* remove obsolte Prism54.org driver wrapper
* remove obsolete Prism54.org driver wrapper
* added internal debugging mechanism with backtrace support and memory
allocation/freeing validation, etc. tests (CONFIG_WPA_TRACE=y)
* EAP-FAST server: piggyback Phase 2 start with the end of Phase 1

View file

@ -1,10 +1,7 @@
ifndef CC
CC=gcc
endif
ALL=hostapd hostapd_cli
CONFIG_FILE = .config
ifndef CFLAGS
CFLAGS = -MMD -O2 -Wall -g
endif
include ../src/build.rules
ifdef LIBS
# If LIBS is set with some global build system defaults, clone those for
@ -19,6 +16,9 @@ endif
ifndef LIBS_n
LIBS_n := $(LIBS)
endif
ifndef LIBS_s
LIBS_s := $(LIBS)
endif
endif
CFLAGS += $(EXTRA_CFLAGS)
@ -27,8 +27,6 @@ CFLAGS += -I$(abspath ../src/utils)
export BINDIR ?= /usr/local/bin/
-include .config
ifndef CONFIG_NO_GITVER
# Add VERSION_STR postfix for builds from a git repository
ifeq ($(wildcard ../.git),../.git)
@ -121,6 +119,8 @@ CFLAGS += -DPACKAGE="hostapd" -DWPA_TRACE_BFD
LIBS += -lbfd -ldl -liberty -lz
LIBS_c += -lbfd -ldl -liberty -lz
LIBS_h += -lbfd -ldl -liberty -lz
LIBS_n += -lbfd -ldl -liberty -lz
LIBS_s += -lbfd -ldl -liberty -lz
endif
endif
@ -157,6 +157,7 @@ OBJS_c += ../src/utils/wpa_debug.o
OBJS += ../src/utils/wpabuf.o
OBJS += ../src/utils/os_$(CONFIG_OS).o
OBJS += ../src/utils/ip_addr.o
OBJS += ../src/utils/crc32.o
OBJS += ../src/common/ieee802_11_common.o
OBJS += ../src/common/wpa_common.o
@ -248,18 +249,12 @@ ifndef CONFIG_NO_CTRL_IFACE
CFLAGS += -DCONFIG_CTRL_IFACE
endif
ifdef CONFIG_IAPP
CFLAGS += -DCONFIG_IAPP
OBJS += ../src/ap/iapp.o
endif
ifdef CONFIG_RSN_PREAUTH
CFLAGS += -DCONFIG_RSN_PREAUTH
CONFIG_L2_PACKET=y
endif
ifdef CONFIG_HS20
NEED_AES_OMAC1=y
CONFIG_PROXYARP=y
endif
@ -269,8 +264,6 @@ endif
ifdef CONFIG_SUITEB
CFLAGS += -DCONFIG_SUITEB
NEED_SHA256=y
NEED_AES_OMAC1=y
endif
ifdef CONFIG_SUITEB192
@ -281,24 +274,14 @@ endif
ifdef CONFIG_OCV
CFLAGS += -DCONFIG_OCV
OBJS += ../src/common/ocv.o
CONFIG_IEEE80211W=y
endif
ifdef CONFIG_IEEE80211W
CFLAGS += -DCONFIG_IEEE80211W
NEED_SHA256=y
NEED_AES_OMAC1=y
endif
ifdef CONFIG_IEEE80211R
CFLAGS += -DCONFIG_IEEE80211R -DCONFIG_IEEE80211R_AP
OBJS += ../src/ap/wpa_auth_ft.o
NEED_SHA256=y
NEED_AES_OMAC1=y
NEED_AES_UNWRAP=y
NEED_AES_SIV=y
NEED_ETH_P_OUI=y
NEED_SHA256=y
NEED_HMAC_SHA256_KDF=y
endif
@ -310,8 +293,13 @@ endif
ifdef CONFIG_SAE
CFLAGS += -DCONFIG_SAE
OBJS += ../src/common/sae.o
ifdef CONFIG_SAE_PK
CFLAGS += -DCONFIG_SAE_PK
OBJS += ../src/common/sae_pk.o
endif
NEED_ECC=y
NEED_DH_GROUPS=y
NEED_HMAC_SHA256_KDF=y
NEED_AP_MLME=y
NEED_DRAGONFLY=y
endif
@ -322,7 +310,6 @@ NEED_ECC=y
NEED_HMAC_SHA256_KDF=y
NEED_HMAC_SHA384_KDF=y
NEED_HMAC_SHA512_KDF=y
NEED_SHA256=y
NEED_SHA384=y
NEED_SHA512=y
endif
@ -348,10 +335,6 @@ CFLAGS += -DCONFIG_WNM -DCONFIG_WNM_AP
OBJS += ../src/ap/wnm_ap.o
endif
ifdef CONFIG_IEEE80211N
CFLAGS += -DCONFIG_IEEE80211N
endif
ifdef CONFIG_IEEE80211AC
CFLAGS += -DCONFIG_IEEE80211AC
endif
@ -391,7 +374,6 @@ endif
ifdef CONFIG_ERP
CFLAGS += -DCONFIG_ERP
NEED_SHA256=y
NEED_HMAC_SHA256_KDF=y
endif
@ -452,7 +434,6 @@ ifdef CONFIG_EAP_AKA
CFLAGS += -DEAP_SERVER_AKA
OBJS += ../src/eap_server/eap_server_aka.o
CONFIG_EAP_SIM_COMMON=y
NEED_SHA256=y
NEED_AES_CBC=y
endif
@ -463,7 +444,7 @@ endif
ifdef CONFIG_EAP_SIM_COMMON
OBJS += ../src/eap_common/eap_sim_common.o
# Example EAP-SIM/AKA interface for GSM/UMTS authentication. This can be
# replaced with another file implementating the interface specified in
# replaced with another file implementing the interface specified in
# eap_sim_db.h.
OBJS += ../src/eap_server/eap_sim_db.o
NEED_FIPS186_2_PRF=y
@ -477,7 +458,6 @@ endif
ifdef CONFIG_EAP_PSK
CFLAGS += -DEAP_SERVER_PSK
OBJS += ../src/eap_server/eap_server_psk.o ../src/eap_common/eap_psk_common.o
NEED_AES_OMAC1=y
NEED_AES_ENCBLOCK=y
NEED_AES_EAX=y
endif
@ -493,14 +473,11 @@ OBJS += ../src/eap_server/eap_server_gpsk.o ../src/eap_common/eap_gpsk_common.o
ifdef CONFIG_EAP_GPSK_SHA256
CFLAGS += -DEAP_GPSK_SHA256
endif
NEED_SHA256=y
NEED_AES_OMAC1=y
endif
ifdef CONFIG_EAP_PWD
CFLAGS += -DEAP_SERVER_PWD
OBJS += ../src/eap_server/eap_server_pwd.o ../src/eap_common/eap_pwd_common.o
NEED_SHA256=y
NEED_ECC=y
NEED_DRAGONFLY=y
endif
@ -533,6 +510,8 @@ OBJS += ../src/eap_common/eap_teap_common.o
TLS_FUNCS=y
NEED_T_PRF=y
NEED_SHA384=y
NEED_TLS_PRF_SHA256=y
NEED_TLS_PRF_SHA384=y
NEED_AES_UNWRAP=y
endif
@ -550,7 +529,6 @@ OBJS += ../src/wps/wps_dev_attr.o
OBJS += ../src/wps/wps_enrollee.o
OBJS += ../src/wps/wps_registrar.o
NEED_DH_GROUPS=y
NEED_SHA256=y
NEED_BASE64=y
NEED_AES_CBC=y
NEED_MODEXP=y
@ -593,23 +571,40 @@ endif
ifdef CONFIG_DPP
CFLAGS += -DCONFIG_DPP
OBJS += ../src/common/dpp.o
OBJS += ../src/common/dpp_auth.o
OBJS += ../src/common/dpp_backup.o
OBJS += ../src/common/dpp_crypto.o
OBJS += ../src/common/dpp_pkex.o
OBJS += ../src/common/dpp_reconfig.o
OBJS += ../src/common/dpp_tcp.o
OBJS += ../src/ap/dpp_hostapd.o
OBJS += ../src/ap/gas_query_ap.o
NEED_AES_SIV=y
NEED_HMAC_SHA256_KDF=y
NEED_HMAC_SHA384_KDF=y
NEED_HMAC_SHA512_KDF=y
NEED_SHA256=y
NEED_SHA384=y
NEED_SHA512=y
NEED_ECC=y
NEED_JSON=y
NEED_GAS=y
NEED_BASE64=y
NEED_ASN1=y
ifdef CONFIG_DPP2
CFLAGS += -DCONFIG_DPP2
endif
endif
ifdef CONFIG_PASN
CFLAGS += -DCONFIG_PASN
CFLAGS += -DCONFIG_PTKSA_CACHE
NEED_HMAC_SHA256_KDF=y
NEED_HMAC_SHA384_KDF=y
NEED_SHA256=y
NEED_SHA384=y
OBJS += ../src/common/ptksa_cache.o
endif
ifdef CONFIG_EAP_IKEV2
CFLAGS += -DEAP_SERVER_IKEV2
OBJS += ../src/eap_server/eap_server_ikev2.o ../src/eap_server/ikev2.o
@ -687,7 +682,6 @@ endif
ifdef CONFIG_TLSV12
CFLAGS += -DCONFIG_TLSV12
NEED_SHA256=y
endif
ifeq ($(CONFIG_TLS), wolfssl)
@ -701,7 +695,6 @@ HOBJS += ../src/crypto/crypto_wolfssl.o
ifdef NEED_FIPS186_2_PRF
OBJS += ../src/crypto/fips_prf_wolfssl.o
endif
NEED_SHA256=y
NEED_TLS_PRF_SHA256=y
LIBS += -lwolfssl -lm
LIBS_h += -lwolfssl -lm
@ -720,17 +713,19 @@ LIBS += -lssl
endif
OBJS += ../src/crypto/crypto_openssl.o
HOBJS += ../src/crypto/crypto_openssl.o
SOBJS += ../src/crypto/crypto_openssl.o
ifdef NEED_FIPS186_2_PRF
OBJS += ../src/crypto/fips_prf_openssl.o
endif
NEED_SHA256=y
NEED_TLS_PRF_SHA256=y
LIBS += -lcrypto
LIBS_h += -lcrypto
LIBS_n += -lcrypto
LIBS_s += -lcrypto
ifdef CONFIG_TLS_ADD_DL
LIBS += -ldl
LIBS_h += -ldl
LIBS_s += -ldl
endif
ifndef CONFIG_TLS_DEFAULT_CIPHERS
CONFIG_TLS_DEFAULT_CIPHERS = "DEFAULT:!EXP:!LOW"
@ -781,13 +776,12 @@ OBJS += ../src/tls/tlsv1_cred.o
OBJS += ../src/tls/tlsv1_server.o
OBJS += ../src/tls/tlsv1_server_write.o
OBJS += ../src/tls/tlsv1_server_read.o
OBJS += ../src/tls/asn1.o
OBJS += ../src/tls/rsa.o
OBJS += ../src/tls/x509v3.o
OBJS += ../src/tls/pkcs1.o
OBJS += ../src/tls/pkcs5.o
OBJS += ../src/tls/pkcs8.o
NEED_SHA256=y
NEED_ASN1=y
NEED_BASE64=y
NEED_TLS_PRF=y
ifdef CONFIG_TLSV12
@ -858,13 +852,12 @@ OBJS += ../src/tls/tlsv1_cred.o
OBJS += ../src/tls/tlsv1_server.o
OBJS += ../src/tls/tlsv1_server_write.o
OBJS += ../src/tls/tlsv1_server_read.o
OBJS += ../src/tls/asn1.o
OBJS += ../src/tls/rsa.o
OBJS += ../src/tls/x509v3.o
OBJS += ../src/tls/pkcs1.o
OBJS += ../src/tls/pkcs5.o
OBJS += ../src/tls/pkcs8.o
NEED_SHA256=y
NEED_ASN1=y
NEED_BASE64=y
NEED_TLS_PRF=y
ifdef CONFIG_TLSV12
@ -925,12 +918,10 @@ endif
ifdef NEED_AES_EAX
AESOBJS += ../src/crypto/aes-eax.o
NEED_AES_CTR=y
NEED_AES_OMAC1=y
endif
ifdef NEED_AES_SIV
AESOBJS += ../src/crypto/aes-siv.o
NEED_AES_CTR=y
NEED_AES_OMAC1=y
endif
ifdef NEED_AES_CTR
AESOBJS += ../src/crypto/aes-ctr.o
@ -938,13 +929,11 @@ endif
ifdef NEED_AES_ENCBLOCK
AESOBJS += ../src/crypto/aes-encblock.o
endif
ifdef NEED_AES_OMAC1
ifneq ($(CONFIG_TLS), linux)
ifneq ($(CONFIG_TLS), wolfssl)
AESOBJS += ../src/crypto/aes-omac1.o
endif
endif
endif
ifdef NEED_AES_UNWRAP
ifneq ($(CONFIG_TLS), openssl)
ifneq ($(CONFIG_TLS), linux)
@ -1050,7 +1039,6 @@ endif
endif
endif
ifdef NEED_SHA256
CFLAGS += -DCONFIG_SHA256
ifneq ($(CONFIG_TLS), openssl)
ifneq ($(CONFIG_TLS), linux)
@ -1068,6 +1056,9 @@ endif
ifdef NEED_TLS_PRF_SHA256
OBJS += ../src/crypto/sha256-tlsprf.o
endif
ifdef NEED_TLS_PRF_SHA384
OBJS += ../src/crypto/sha384-tlsprf.o
endif
ifdef NEED_HMAC_SHA256_KDF
OBJS += ../src/crypto/sha256-kdf.o
endif
@ -1077,7 +1068,6 @@ endif
ifdef NEED_HMAC_SHA512_KDF
OBJS += ../src/crypto/sha512-kdf.o
endif
endif
ifdef NEED_SHA384
CFLAGS += -DCONFIG_SHA384
ifneq ($(CONFIG_TLS), openssl)
@ -1115,6 +1105,10 @@ CFLAGS += -DCONFIG_INTERNAL_SHA512
OBJS += ../src/crypto/sha512-internal.o
endif
ifdef NEED_ASN1
OBJS += ../src/tls/asn1.o
endif
ifdef NEED_DH_GROUPS
OBJS += ../src/crypto/dh_groups.o
endif
@ -1180,9 +1174,7 @@ OBJS += ../src/ap/hw_features.o
OBJS += ../src/ap/dfs.o
CFLAGS += -DNEED_AP_MLME
endif
ifdef CONFIG_IEEE80211N
OBJS += ../src/ap/ieee802_11_ht.o
endif
ifdef CONFIG_IEEE80211AC
OBJS += ../src/ap/ieee802_11_vht.o
@ -1269,60 +1261,33 @@ OBJS += ../src/fst/fst_ctrl_iface.o
endif
endif
ALL=hostapd hostapd_cli
all: verify_config $(ALL)
Q=@
E=echo
ifeq ($(V), 1)
Q=
E=true
endif
ifeq ($(QUIET), 1)
Q=@
E=true
ifdef CONFIG_WEP
CFLAGS += -DCONFIG_WEP
endif
ifdef CONFIG_CODE_COVERAGE
%.o: %.c
@$(E) " CC " $<
$(Q)cd $(dir $@); $(CC) -c -o $(notdir $@) $(CFLAGS) $(notdir $<)
else
%.o: %.c
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
@$(E) " CC " $<
ifdef CONFIG_NO_TKIP
CFLAGS += -DCONFIG_NO_TKIP
endif
verify_config:
@if [ ! -r .config ]; then \
echo 'Building hostapd requires a configuration file'; \
echo '(.config). See README for more instructions. You can'; \
echo 'run "cp defconfig .config" to create an example'; \
echo 'configuration.'; \
exit 1; \
fi
$(DESTDIR)$(BINDIR)/%: %
install -D $(<) $(@)
install: $(addprefix $(DESTDIR)$(BINDIR)/,$(ALL))
../src/drivers/build.hostapd:
@if [ -f ../src/drivers/build.wpa_supplicant ]; then \
$(MAKE) -C ../src/drivers clean; \
fi
@touch ../src/drivers/build.hostapd
_OBJS_VAR := OBJS
include ../src/objs.mk
BCHECK=../src/drivers/build.hostapd
hostapd: $(BCHECK) $(OBJS)
hostapd: $(OBJS)
$(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
@$(E) " LD " $@
ifdef CONFIG_WPA_TRACE
OBJS_c += ../src/utils/trace.o
endif
_OBJS_VAR := OBJS_c
include ../src/objs.mk
hostapd_cli: $(OBJS_c)
$(Q)$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c)
@$(E) " LD " $@
@ -1345,7 +1310,6 @@ NOBJS += ../src/utils/wpa_debug.o
NOBJS += ../src/utils/wpabuf.o
ifdef CONFIG_WPA_TRACE
NOBJS += ../src/utils/trace.o
LIBS_n += -lbfd
endif
HOBJS += hlr_auc_gw.o ../src/utils/common.o ../src/utils/wpa_debug.o ../src/utils/os_$(CONFIG_OS).o ../src/utils/wpabuf.o ../src/crypto/milenage.o
@ -1358,6 +1322,35 @@ ifeq ($(CONFIG_TLS), linux)
HOBJS += ../src/crypto/crypto_linux.o
endif
SOBJS += sae_pk_gen.o
SOBJS += ../src/utils/common.o
SOBJS += ../src/utils/os_$(CONFIG_OS).o
SOBJS += ../src/utils/base64.o
SOBJS += ../src/utils/wpa_debug.o
SOBJS += ../src/utils/wpabuf.o
ifdef CONFIG_WPA_TRACE
SOBJS += ../src/utils/trace.o
endif
SOBJS += ../src/common/ieee802_11_common.o
SOBJS += ../src/common/sae.o
SOBJS += ../src/common/sae_pk.o
SOBJS += ../src/common/dragonfly.o
SOBJS += $(AESOBJS)
SOBJS += ../src/crypto/sha256-prf.o
SOBJS += ../src/crypto/sha384-prf.o
SOBJS += ../src/crypto/sha512-prf.o
SOBJS += ../src/crypto/dh_groups.o
SOBJS += ../src/crypto/sha256-kdf.o
SOBJS += ../src/crypto/sha384-kdf.o
SOBJS += ../src/crypto/sha512-kdf.o
_OBJS_VAR := NOBJS
include ../src/objs.mk
_OBJS_VAR := HOBJS
include ../src/objs.mk
_OBJS_VAR := SOBJS
include ../src/objs.mk
nt_password_hash: $(NOBJS)
$(Q)$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n)
@$(E) " LD " $@
@ -1366,15 +1359,17 @@ hlr_auc_gw: $(HOBJS)
$(Q)$(CC) $(LDFLAGS) -o hlr_auc_gw $(HOBJS) $(LIBS_h)
@$(E) " LD " $@
sae_pk_gen: $(SOBJS)
$(Q)$(CC) $(LDFLAGS) -o sae_pk_gen $(SOBJS) $(LIBS_s)
@$(E) " LD " $@
.PHONY: lcov-html
lcov-html:
lcov -c -d .. > lcov.info
lcov -c -d $(BUILDDIR) > lcov.info
genhtml lcov.info --output-directory lcov-html
clean:
$(MAKE) -C ../src clean
rm -f core *~ *.o hostapd hostapd_cli nt_password_hash hlr_auc_gw
rm -f *.d *.gcno *.gcda *.gcov
clean: common-clean
rm -f core *~ nt_password_hash hlr_auc_gw
rm -f sae_pk_gen
rm -f lcov.info
rm -rf lcov-html
-include $(OBJS:%.o=%.d)

View file

@ -28,6 +28,9 @@ CONFIG_LIBNL20=y
# QCA vendor extensions to nl80211
CONFIG_DRIVER_NL80211_QCA=y
# Broadcom vendor extensions to nl80211
#CONFIG_DRIVER_NL80211_BRCM=y
# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
#CONFIG_DRIVER_BSD=y
#CFLAGS += -I/usr/local/include
@ -38,18 +41,9 @@ CONFIG_DRIVER_NL80211_QCA=y
# Driver interface for no driver (e.g., RADIUS server only)
#CONFIG_DRIVER_NONE=y
# IEEE 802.11F/IAPP
#CONFIG_IAPP=y
# WPA2/IEEE 802.11i RSN pre-authentication
#CONFIG_RSN_PREAUTH=y
# IEEE 802.11w (management frame protection)
# This version is an experimental implementation based on IEEE 802.11w/D1.0
# draft and is subject to change since the standard has not yet been finalized.
# Driver support is also needed for IEEE 802.11w.
CONFIG_IEEE80211W=y
# Support Operating Channel Validation
#CONFIG_OCV=y
@ -134,9 +128,6 @@ CONFIG_IPV6=y
# the IEEE 802.11 Management capability (e.g., FreeBSD/net80211)
#CONFIG_DRIVER_RADIUS_ACL=y
# IEEE 802.11n (High Throughput) support
CONFIG_IEEE80211N=y
# Remove debugging code that is printing out debug messages to stdout.
# This can be used to reduce the size of the hostapd considerably if debugging
# code is not needed.
@ -196,7 +187,7 @@ CONFIG_AP=y
#CONFIG_FST=y
# Multiband Operation support
# These extentions facilitate efficient use of multiple frequency bands
# These extensions facilitate efficient use of multiple frequency bands
# available to the AP and the devices that may associate with it.
#CONFIG_MBO=y
@ -213,3 +204,11 @@ CONFIG_WPA_CLI_EDIT=y
# /dev/urandom earlier in boot' seeds /dev/urandom with that entropy before
# either wpa_supplicant or hostapd are run.
CONFIG_NO_RANDOM_POOL=y
# Wired equivalent privacy (WEP)
# WEP is an obsolete cryptographic data confidentiality algorithm that is not
# considered secure. It should not be used for anything anymore. The
# functionality needed to use WEP is available in the current hostapd
# release under this optional build parameter. This functionality is subject to
# be completely removed in a future release.
CONFIG_WEP=y

View file

@ -14,6 +14,7 @@
#include "utils/common.h"
#include "utils/uuid.h"
#include "common/ieee802_11_defs.h"
#include "common/sae.h"
#include "crypto/sha256.h"
#include "crypto/tls.h"
#include "drivers/driver.h"
@ -340,7 +341,7 @@ static int hostapd_config_read_eap_user(const char *fname,
struct hostapd_radius_attr *attr, *a;
attr = hostapd_parse_radius_attr(buf + 19);
if (attr == NULL) {
wpa_printf(MSG_ERROR, "Invalid radius_auth_req_attr: %s",
wpa_printf(MSG_ERROR, "Invalid radius_accept_attr: %s",
buf + 19);
user = NULL; /* already in the BSS list */
goto failed;
@ -711,12 +712,10 @@ static int hostapd_config_parse_key_mgmt(int line, const char *value)
val |= WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
#endif /* CONFIG_SHA384 */
#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_IEEE80211W
else if (os_strcmp(start, "WPA-PSK-SHA256") == 0)
val |= WPA_KEY_MGMT_PSK_SHA256;
else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_SAE
else if (os_strcmp(start, "SAE") == 0)
val |= WPA_KEY_MGMT_SAE;
@ -755,6 +754,10 @@ static int hostapd_config_parse_key_mgmt(int line, const char *value)
else if (os_strcmp(start, "OSEN") == 0)
val |= WPA_KEY_MGMT_OSEN;
#endif /* CONFIG_HS20 */
#ifdef CONFIG_PASN
else if (os_strcmp(start, "PASN") == 0)
val |= WPA_KEY_MGMT_PASN;
#endif /* CONFIG_PASN */
else {
wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
line, start);
@ -795,6 +798,7 @@ static int hostapd_config_parse_cipher(int line, const char *value)
}
#ifdef CONFIG_WEP
static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
char *val)
{
@ -845,6 +849,7 @@ static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
return 0;
}
#endif /* CONFIG_WEP */
static int hostapd_parse_chanlist(struct hostapd_config *conf, char *val)
@ -942,104 +947,6 @@ static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname)
}
/* convert floats with one decimal place to value*10 int, i.e.,
* "1.5" will return 15 */
static int hostapd_config_read_int10(const char *value)
{
int i, d;
char *pos;
i = atoi(value);
pos = os_strchr(value, '.');
d = 0;
if (pos) {
pos++;
if (*pos >= '0' && *pos <= '9')
d = *pos - '0';
}
return i * 10 + d;
}
static int valid_cw(int cw)
{
return (cw == 1 || cw == 3 || cw == 7 || cw == 15 || cw == 31 ||
cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023 ||
cw == 2047 || cw == 4095 || cw == 8191 || cw == 16383 ||
cw == 32767);
}
enum {
IEEE80211_TX_QUEUE_DATA0 = 0, /* used for EDCA AC_VO data */
IEEE80211_TX_QUEUE_DATA1 = 1, /* used for EDCA AC_VI data */
IEEE80211_TX_QUEUE_DATA2 = 2, /* used for EDCA AC_BE data */
IEEE80211_TX_QUEUE_DATA3 = 3 /* used for EDCA AC_BK data */
};
static int hostapd_config_tx_queue(struct hostapd_config *conf,
const char *name, const char *val)
{
int num;
const char *pos;
struct hostapd_tx_queue_params *queue;
/* skip 'tx_queue_' prefix */
pos = name + 9;
if (os_strncmp(pos, "data", 4) == 0 &&
pos[4] >= '0' && pos[4] <= '9' && pos[5] == '_') {
num = pos[4] - '0';
pos += 6;
} else if (os_strncmp(pos, "after_beacon_", 13) == 0 ||
os_strncmp(pos, "beacon_", 7) == 0) {
wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name);
return 0;
} else {
wpa_printf(MSG_ERROR, "Unknown tx_queue name '%s'", pos);
return -1;
}
if (num >= NUM_TX_QUEUES) {
/* for backwards compatibility, do not trigger failure */
wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name);
return 0;
}
queue = &conf->tx_queue[num];
if (os_strcmp(pos, "aifs") == 0) {
queue->aifs = atoi(val);
if (queue->aifs < 0 || queue->aifs > 255) {
wpa_printf(MSG_ERROR, "Invalid AIFS value %d",
queue->aifs);
return -1;
}
} else if (os_strcmp(pos, "cwmin") == 0) {
queue->cwmin = atoi(val);
if (!valid_cw(queue->cwmin)) {
wpa_printf(MSG_ERROR, "Invalid cwMin value %d",
queue->cwmin);
return -1;
}
} else if (os_strcmp(pos, "cwmax") == 0) {
queue->cwmax = atoi(val);
if (!valid_cw(queue->cwmax)) {
wpa_printf(MSG_ERROR, "Invalid cwMax value %d",
queue->cwmax);
return -1;
}
} else if (os_strcmp(pos, "burst") == 0) {
queue->burst = hostapd_config_read_int10(val);
} else {
wpa_printf(MSG_ERROR, "Unknown tx_queue field '%s'", pos);
return -1;
}
return 0;
}
#ifdef CONFIG_IEEE80211R_AP
static int rkh_derive_key(const char *pos, u8 *key, size_t key_len)
@ -1153,7 +1060,6 @@ static int add_r1kh(struct hostapd_bss_config *bss, char *value)
#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_IEEE80211N
static int hostapd_config_ht_capab(struct hostapd_config *conf,
const char *capab)
{
@ -1173,14 +1079,6 @@ static int hostapd_config_ht_capab(struct hostapd_config *conf,
}
if (!os_strstr(capab, "[HT40+]") && !os_strstr(capab, "[HT40-]"))
conf->secondary_channel = 0;
if (os_strstr(capab, "[SMPS-STATIC]")) {
conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK;
conf->ht_capab |= HT_CAP_INFO_SMPS_STATIC;
}
if (os_strstr(capab, "[SMPS-DYNAMIC]")) {
conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK;
conf->ht_capab |= HT_CAP_INFO_SMPS_DYNAMIC;
}
if (os_strstr(capab, "[GF]"))
conf->ht_capab |= HT_CAP_INFO_GREEN_FIELD;
if (os_strstr(capab, "[SHORT-GI-20]"))
@ -1214,7 +1112,6 @@ static int hostapd_config_ht_capab(struct hostapd_config *conf,
return 0;
}
#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_IEEE80211AC
@ -1323,6 +1220,32 @@ static u8 set_he_cap(int val, u8 mask)
return (u8) (mask & (val << find_bit_offset(mask)));
}
static int hostapd_parse_he_srg_bitmap(u8 *bitmap, char *val)
{
int bitpos;
char *pos, *end;
os_memset(bitmap, 0, 8);
pos = val;
while (*pos != '\0') {
end = os_strchr(pos, ' ');
if (end)
*end = '\0';
bitpos = atoi(pos);
if (bitpos < 0 || bitpos > 64)
return -1;
bitmap[bitpos / 8] |= BIT(bitpos % 8);
if (!end)
break;
pos = end + 1;
}
return 0;
}
#endif /* CONFIG_IEEE80211AX */
@ -2300,6 +2223,35 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val)
pw->vlan_id = atoi(pos2);
}
#ifdef CONFIG_SAE_PK
pos2 = os_strstr(pos, "|pk=");
if (pos2) {
const char *epos;
char *tmp;
if (!end)
end = pos2;
pos2 += 4;
epos = os_strchr(pos2, '|');
if (epos) {
tmp = os_malloc(epos - pos2 + 1);
if (!tmp)
goto fail;
os_memcpy(tmp, pos2, epos - pos2);
tmp[epos - pos2] = '\0';
} else {
tmp = os_strdup(pos2);
if (!tmp)
goto fail;
}
pw->pk = sae_parse_pk(tmp);
str_clear_free(tmp);
if (!pw->pk)
goto fail;
}
#endif /* CONFIG_SAE_PK */
pos2 = os_strstr(pos, "|id=");
if (pos2) {
if (!end)
@ -2322,6 +2274,18 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val)
pw->password[end - val] = '\0';
}
#ifdef CONFIG_SAE_PK
if (pw->pk &&
#ifdef CONFIG_TESTING_OPTIONS
!bss->sae_pk_password_check_skip &&
#endif /* CONFIG_TESTING_OPTIONS */
!sae_pk_valid_password(pw->password)) {
wpa_printf(MSG_INFO,
"Invalid SAE password for a SAE-PK sae_password entry");
goto fail;
}
#endif /* CONFIG_SAE_PK */
pw->next = bss->sae_passwords;
bss->sae_passwords = pw;
@ -2329,6 +2293,9 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val)
fail:
str_clear_free(pw->password);
os_free(pw->identifier);
#ifdef CONFIG_SAE_PK
sae_deinit_pk(pw->pk);
#endif /* CONFIG_SAE_PK */
os_free(pw);
return -1;
}
@ -2473,6 +2440,13 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "skip_inactivity_poll") == 0) {
bss->skip_inactivity_poll = atoi(pos);
} else if (os_strcmp(buf, "country_code") == 0) {
if (pos[0] < 'A' || pos[0] > 'Z' ||
pos[1] < 'A' || pos[1] > 'Z') {
wpa_printf(MSG_ERROR,
"Line %d: Invalid country_code '%s'",
line, pos);
return 1;
}
os_memcpy(conf->country, pos, 2);
} else if (os_strcmp(buf, "country3") == 0) {
conf->country[2] = strtol(pos, NULL, 16);
@ -2547,6 +2521,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->tls_session_lifetime = atoi(pos);
} else if (os_strcmp(buf, "tls_flags") == 0) {
bss->tls_flags = parse_tls_flags(pos);
} else if (os_strcmp(buf, "max_auth_rounds") == 0) {
bss->max_auth_rounds = atoi(pos);
} else if (os_strcmp(buf, "max_auth_rounds_short") == 0) {
bss->max_auth_rounds_short = atoi(pos);
} else if (os_strcmp(buf, "ocsp_stapling_response") == 0) {
os_free(bss->ocsp_stapling_response);
bss->ocsp_stapling_response = os_strdup(pos);
@ -2611,7 +2589,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "eap_teap_auth") == 0) {
int val = atoi(pos);
if (val < 0 || val > 1) {
if (val < 0 || val > 2) {
wpa_printf(MSG_ERROR,
"Line %d: Invalid eap_teap_auth value",
line);
@ -2620,6 +2598,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->eap_teap_auth = val;
} else if (os_strcmp(buf, "eap_teap_pac_no_inner") == 0) {
bss->eap_teap_pac_no_inner = atoi(pos);
} else if (os_strcmp(buf, "eap_teap_separate_result") == 0) {
bss->eap_teap_separate_result = atoi(pos);
} else if (os_strcmp(buf, "eap_teap_id") == 0) {
bss->eap_teap_id = atoi(pos);
#endif /* EAP_SERVER_TEAP */
#ifdef EAP_SERVER_SIM
} else if (os_strcmp(buf, "eap_sim_db") == 0) {
@ -2668,6 +2650,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "erp_domain") == 0) {
os_free(bss->erp_domain);
bss->erp_domain = os_strdup(pos);
#ifdef CONFIG_WEP
} else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) {
int val = atoi(pos);
@ -2695,6 +2678,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line, bss->wep_rekeying_period);
return 1;
}
#endif /* CONFIG_WEP */
} else if (os_strcmp(buf, "eap_reauth_period") == 0) {
bss->eap_reauth_period = atoi(pos);
if (bss->eap_reauth_period < 0) {
@ -2706,8 +2690,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->eapol_key_index_workaround = atoi(pos);
#ifdef CONFIG_IAPP
} else if (os_strcmp(buf, "iapp_interface") == 0) {
bss->ieee802_11f = 1;
os_strlcpy(bss->iapp_iface, pos, sizeof(bss->iapp_iface));
wpa_printf(MSG_INFO, "DEPRECATED: iapp_interface not used");
#endif /* CONFIG_IAPP */
} else if (os_strcmp(buf, "own_ip_addr") == 0) {
if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) {
@ -2728,6 +2711,9 @@ static int hostapd_config_fill(struct hostapd_config *conf,
return 1;
}
bss->radius->force_client_addr = 1;
} else if (os_strcmp(buf, "radius_client_dev") == 0) {
os_free(bss->radius->force_client_dev);
bss->radius->force_client_dev = os_strdup(pos);
} else if (os_strcmp(buf, "auth_server_addr") == 0) {
if (hostapd_config_read_radius_addr(
&bss->radius->auth_servers,
@ -2870,6 +2856,16 @@ static int hostapd_config_fill(struct hostapd_config *conf,
}
} else if (os_strcmp(buf, "wpa") == 0) {
bss->wpa = atoi(pos);
} else if (os_strcmp(buf, "extended_key_id") == 0) {
int val = atoi(pos);
if (val < 0 || val > 2) {
wpa_printf(MSG_ERROR,
"Line %d: Invalid extended_key_id=%d; allowed range 0..2",
line, val);
return 1;
}
bss->extended_key_id = val;
} else if (os_strcmp(buf, "wpa_group_rekey") == 0) {
bss->wpa_group_rekey = atoi(pos);
bss->wpa_group_rekey_set = 1;
@ -2879,6 +2875,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->wpa_gmk_rekey = atoi(pos);
} else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) {
bss->wpa_ptk_rekey = atoi(pos);
} else if (os_strcmp(buf, "wpa_deny_ptk0_rekey") == 0) {
bss->wpa_deny_ptk0_rekey = atoi(pos);
if (bss->wpa_deny_ptk0_rekey < 0 ||
bss->wpa_deny_ptk0_rekey > 2) {
wpa_printf(MSG_ERROR,
"Line %d: Invalid wpa_deny_ptk0_rekey=%d; allowed range 0..2",
line, bss->wpa_deny_ptk0_rekey);
return 1;
}
} else if (os_strcmp(buf, "wpa_group_update_count") == 0) {
char *endp;
unsigned long val = strtoul(pos, &endp, 0);
@ -3131,6 +3136,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
}
} else if (os_strcmp(buf, "acs_exclude_dfs") == 0) {
conf->acs_exclude_dfs = atoi(pos);
} else if (os_strcmp(buf, "op_class") == 0) {
conf->op_class = atoi(pos);
} else if (os_strcmp(buf, "channel") == 0) {
if (os_strcmp(pos, "acs_survey") == 0) {
#ifndef CONFIG_ACS
@ -3145,12 +3152,25 @@ static int hostapd_config_fill(struct hostapd_config *conf,
conf->channel = atoi(pos);
conf->acs = conf->channel == 0;
}
} else if (os_strcmp(buf, "edmg_channel") == 0) {
conf->edmg_channel = atoi(pos);
} else if (os_strcmp(buf, "enable_edmg") == 0) {
conf->enable_edmg = atoi(pos);
} else if (os_strcmp(buf, "chanlist") == 0) {
if (hostapd_parse_chanlist(conf, pos)) {
wpa_printf(MSG_ERROR, "Line %d: invalid channel list",
line);
return 1;
}
} else if (os_strcmp(buf, "freqlist") == 0) {
if (freq_range_list_parse(&conf->acs_freq_list, pos)) {
wpa_printf(MSG_ERROR, "Line %d: invalid frequency list",
line);
return 1;
}
conf->acs_freq_list_present = 1;
} else if (os_strcmp(buf, "acs_exclude_6ghz_non_psc") == 0) {
conf->acs_exclude_6ghz_non_psc = atoi(pos);
} else if (os_strcmp(buf, "beacon_int") == 0) {
int val = atoi(pos);
/* MIB defines range as 1..65535, but very small values
@ -3272,6 +3292,16 @@ static int hostapd_config_fill(struct hostapd_config *conf,
}
conf->rate_type = BEACON_RATE_VHT;
conf->beacon_rate = val;
} else if (os_strncmp(pos, "he:", 3) == 0) {
val = atoi(pos + 3);
if (val < 0 || val > 11) {
wpa_printf(MSG_ERROR,
"Line %d: invalid beacon_rate HE-MCS %d",
line, val);
return 1;
}
conf->rate_type = BEACON_RATE_HE;
conf->beacon_rate = val;
} else {
val = atoi(pos);
if (val < 10 || val > 10000) {
@ -3292,6 +3322,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->ignore_broadcast_ssid = atoi(pos);
} else if (os_strcmp(buf, "no_probe_resp_if_max_sta") == 0) {
bss->no_probe_resp_if_max_sta = atoi(pos);
#ifdef CONFIG_WEP
} else if (os_strcmp(buf, "wep_default_key") == 0) {
bss->ssid.wep.idx = atoi(pos);
if (bss->ssid.wep.idx > 3) {
@ -3310,6 +3341,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line, buf);
return 1;
}
#endif /* CONFIG_WEP */
#ifndef CONFIG_NO_VLAN
} else if (os_strcmp(buf, "dynamic_vlan") == 0) {
bss->ssid.dynamic_vlan = atoi(pos);
@ -3341,7 +3373,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "ap_table_expiration_time") == 0) {
conf->ap_table_expiration_time = atoi(pos);
} else if (os_strncmp(buf, "tx_queue_", 9) == 0) {
if (hostapd_config_tx_queue(conf, buf, pos)) {
if (hostapd_config_tx_queue(conf->tx_queue, buf, pos)) {
wpa_printf(MSG_ERROR, "Line %d: invalid TX queue item",
line);
return 1;
@ -3372,7 +3404,6 @@ static int hostapd_config_fill(struct hostapd_config *conf,
}
} else if (os_strcmp(buf, "use_driver_iface_addr") == 0) {
conf->use_driver_iface_addr = atoi(pos);
#ifdef CONFIG_IEEE80211W
} else if (os_strcmp(buf, "ieee80211w") == 0) {
bss->ieee80211w = atoi(pos);
} else if (os_strcmp(buf, "group_mgmt_cipher") == 0) {
@ -3389,6 +3420,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line, pos);
return 1;
}
} else if (os_strcmp(buf, "beacon_prot") == 0) {
bss->beacon_prot = atoi(pos);
} else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) {
bss->assoc_sa_query_max_timeout = atoi(pos);
if (bss->assoc_sa_query_max_timeout == 0) {
@ -3403,14 +3436,12 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line);
return 1;
}
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_OCV
} else if (os_strcmp(buf, "ocv") == 0) {
bss->ocv = atoi(pos);
if (bss->ocv && !bss->ieee80211w)
bss->ieee80211w = 1;
#endif /* CONFIG_OCV */
#ifdef CONFIG_IEEE80211N
} else if (os_strcmp(buf, "ieee80211n") == 0) {
conf->ieee80211n = atoi(pos);
} else if (os_strcmp(buf, "ht_capab") == 0) {
@ -3423,7 +3454,6 @@ static int hostapd_config_fill(struct hostapd_config *conf,
conf->require_ht = atoi(pos);
} else if (os_strcmp(buf, "obss_interval") == 0) {
conf->obss_interval = atoi(pos);
#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_IEEE80211AC
} else if (os_strcmp(buf, "ieee80211ac") == 0) {
conf->ieee80211ac = atoi(pos);
@ -3456,7 +3486,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "he_mu_beamformer") == 0) {
conf->he_phy_capab.he_mu_beamformer = atoi(pos);
} else if (os_strcmp(buf, "he_bss_color") == 0) {
conf->he_op.he_bss_color = atoi(pos);
conf->he_op.he_bss_color = atoi(pos) & 0x3f;
conf->he_op.he_bss_color_disabled = 0;
} else if (os_strcmp(buf, "he_bss_color_partial") == 0) {
conf->he_op.he_bss_color_partial = atoi(pos);
} else if (os_strcmp(buf, "he_default_pe_duration") == 0) {
conf->he_op.he_default_pe_duration = atoi(pos);
} else if (os_strcmp(buf, "he_twt_required") == 0) {
@ -3550,19 +3583,53 @@ static int hostapd_config_fill(struct hostapd_config *conf,
conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_TIMER_IDX] =
atoi(pos) & 0xff;
} else if (os_strcmp(buf, "he_spr_sr_control") == 0) {
conf->spr.sr_control = atoi(pos) & 0xff;
conf->spr.sr_control = atoi(pos) & 0x1f;
} else if (os_strcmp(buf, "he_spr_non_srg_obss_pd_max_offset") == 0) {
conf->spr.non_srg_obss_pd_max_offset = atoi(pos);
} else if (os_strcmp(buf, "he_spr_srg_obss_pd_min_offset") == 0) {
conf->spr.srg_obss_pd_min_offset = atoi(pos);
} else if (os_strcmp(buf, "he_spr_srg_obss_pd_max_offset") == 0) {
conf->spr.srg_obss_pd_max_offset = atoi(pos);
} else if (os_strcmp(buf, "he_spr_srg_bss_colors") == 0) {
if (hostapd_parse_he_srg_bitmap(
conf->spr.srg_bss_color_bitmap, pos)) {
wpa_printf(MSG_ERROR,
"Line %d: Invalid srg bss colors list '%s'",
line, pos);
return 1;
}
} else if (os_strcmp(buf, "he_spr_srg_partial_bssid") == 0) {
if (hostapd_parse_he_srg_bitmap(
conf->spr.srg_partial_bssid_bitmap, pos)) {
wpa_printf(MSG_ERROR,
"Line %d: Invalid srg partial bssid list '%s'",
line, pos);
return 1;
}
} else if (os_strcmp(buf, "he_oper_chwidth") == 0) {
conf->he_oper_chwidth = atoi(pos);
} else if (os_strcmp(buf, "he_oper_centr_freq_seg0_idx") == 0) {
conf->he_oper_centr_freq_seg0_idx = atoi(pos);
} else if (os_strcmp(buf, "he_oper_centr_freq_seg1_idx") == 0) {
conf->he_oper_centr_freq_seg1_idx = atoi(pos);
} else if (os_strcmp(buf, "he_6ghz_max_mpdu") == 0) {
conf->he_6ghz_max_mpdu = atoi(pos);
} else if (os_strcmp(buf, "he_6ghz_max_ampdu_len_exp") == 0) {
conf->he_6ghz_max_ampdu_len_exp = atoi(pos);
} else if (os_strcmp(buf, "he_6ghz_rx_ant_pat") == 0) {
conf->he_6ghz_rx_ant_pat = atoi(pos);
} else if (os_strcmp(buf, "he_6ghz_tx_ant_pat") == 0) {
conf->he_6ghz_tx_ant_pat = atoi(pos);
} else if (os_strcmp(buf, "unsol_bcast_probe_resp_interval") == 0) {
int val = atoi(pos);
if (val < 0 || val > 20) {
wpa_printf(MSG_ERROR,
"Line %d: invalid unsol_bcast_probe_resp_interval value",
line);
return 1;
}
bss->unsol_bcast_probe_resp_interval = val;
#endif /* CONFIG_IEEE80211AX */
} else if (os_strcmp(buf, "max_listen_interval") == 0) {
bss->max_listen_interval = atoi(pos);
@ -3744,6 +3811,9 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "server_id") == 0) {
os_free(bss->server_id);
bss->server_id = os_strdup(pos);
} else if (os_strcmp(buf, "wps_application_ext") == 0) {
wpabuf_free(bss->wps_application_ext);
bss->wps_application_ext = wpabuf_parse_bin(pos);
#ifdef CONFIG_WPS_NFC
} else if (os_strcmp(buf, "wps_nfc_dev_pw_id") == 0) {
bss->wps_nfc_dev_pw_id = atoi(pos);
@ -4144,9 +4214,53 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->own_ie_override = tmp;
} else if (os_strcmp(buf, "sae_reflection_attack") == 0) {
bss->sae_reflection_attack = atoi(pos);
} else if (os_strcmp(buf, "sae_commit_status") == 0) {
bss->sae_commit_status = atoi(pos);
} else if (os_strcmp(buf, "sae_pk_omit") == 0) {
bss->sae_pk_omit = atoi(pos);
} else if (os_strcmp(buf, "sae_pk_password_check_skip") == 0) {
bss->sae_pk_password_check_skip = atoi(pos);
} else if (os_strcmp(buf, "sae_commit_override") == 0) {
wpabuf_free(bss->sae_commit_override);
bss->sae_commit_override = wpabuf_parse_bin(pos);
} else if (os_strcmp(buf, "rsne_override_eapol") == 0) {
wpabuf_free(bss->rsne_override_eapol);
bss->rsne_override_eapol = wpabuf_parse_bin(pos);
} else if (os_strcmp(buf, "rsnxe_override_eapol") == 0) {
wpabuf_free(bss->rsnxe_override_eapol);
bss->rsnxe_override_eapol = wpabuf_parse_bin(pos);
} else if (os_strcmp(buf, "rsne_override_ft") == 0) {
wpabuf_free(bss->rsne_override_ft);
bss->rsne_override_ft = wpabuf_parse_bin(pos);
} else if (os_strcmp(buf, "rsnxe_override_ft") == 0) {
wpabuf_free(bss->rsnxe_override_ft);
bss->rsnxe_override_ft = wpabuf_parse_bin(pos);
} else if (os_strcmp(buf, "gtk_rsc_override") == 0) {
wpabuf_free(bss->gtk_rsc_override);
bss->gtk_rsc_override = wpabuf_parse_bin(pos);
} else if (os_strcmp(buf, "igtk_rsc_override") == 0) {
wpabuf_free(bss->igtk_rsc_override);
bss->igtk_rsc_override = wpabuf_parse_bin(pos);
} else if (os_strcmp(buf, "no_beacon_rsnxe") == 0) {
bss->no_beacon_rsnxe = atoi(pos);
} else if (os_strcmp(buf, "skip_prune_assoc") == 0) {
bss->skip_prune_assoc = atoi(pos);
} else if (os_strcmp(buf, "ft_rsnxe_used") == 0) {
bss->ft_rsnxe_used = atoi(pos);
} else if (os_strcmp(buf, "oci_freq_override_eapol_m3") == 0) {
bss->oci_freq_override_eapol_m3 = atoi(pos);
} else if (os_strcmp(buf, "oci_freq_override_eapol_g1") == 0) {
bss->oci_freq_override_eapol_g1 = atoi(pos);
} else if (os_strcmp(buf, "oci_freq_override_saquery_req") == 0) {
bss->oci_freq_override_saquery_req = atoi(pos);
} else if (os_strcmp(buf, "oci_freq_override_saquery_resp") == 0) {
bss->oci_freq_override_saquery_resp = atoi(pos);
} else if (os_strcmp(buf, "oci_freq_override_ft_assoc") == 0) {
bss->oci_freq_override_ft_assoc = atoi(pos);
} else if (os_strcmp(buf, "oci_freq_override_fils_assoc") == 0) {
bss->oci_freq_override_fils_assoc = atoi(pos);
} else if (os_strcmp(buf, "oci_freq_override_wnm_sleep") == 0) {
bss->oci_freq_override_wnm_sleep = atoi(pos);
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_SAE
} else if (os_strcmp(buf, "sae_password") == 0) {
@ -4162,8 +4276,9 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "assocresp_elements") == 0) {
if (parse_wpabuf_hex(line, buf, &bss->assocresp_elements, pos))
return 1;
} else if (os_strcmp(buf, "sae_anti_clogging_threshold") == 0) {
bss->sae_anti_clogging_threshold = atoi(pos);
} else if (os_strcmp(buf, "sae_anti_clogging_threshold") == 0 ||
os_strcmp(buf, "anti_clogging_threshold") == 0) {
bss->anti_clogging_threshold = atoi(pos);
} else if (os_strcmp(buf, "sae_sync") == 0) {
bss->sae_sync = atoi(pos);
} else if (os_strcmp(buf, "sae_groups") == 0) {
@ -4175,6 +4290,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
}
} else if (os_strcmp(buf, "sae_require_mfp") == 0) {
bss->sae_require_mfp = atoi(pos);
} else if (os_strcmp(buf, "sae_confirm_immediate") == 0) {
bss->sae_confirm_immediate = atoi(pos);
} else if (os_strcmp(buf, "sae_pwe") == 0) {
bss->sae_pwe = atoi(pos);
} else if (os_strcmp(buf, "local_pwr_constraint") == 0) {
int val = atoi(pos);
if (val < 0 || val > 255) {
@ -4318,12 +4437,24 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->dhcp_server_port = atoi(pos);
} else if (os_strcmp(buf, "dhcp_relay_port") == 0) {
bss->dhcp_relay_port = atoi(pos);
} else if (os_strcmp(buf, "fils_discovery_min_interval") == 0) {
bss->fils_discovery_min_int = atoi(pos);
} else if (os_strcmp(buf, "fils_discovery_max_interval") == 0) {
bss->fils_discovery_max_int = atoi(pos);
#endif /* CONFIG_FILS */
} else if (os_strcmp(buf, "multicast_to_unicast") == 0) {
bss->multicast_to_unicast = atoi(pos);
} else if (os_strcmp(buf, "broadcast_deauth") == 0) {
bss->broadcast_deauth = atoi(pos);
} else if (os_strcmp(buf, "notify_mgmt_frames") == 0) {
bss->notify_mgmt_frames = atoi(pos);
#ifdef CONFIG_DPP
} else if (os_strcmp(buf, "dpp_name") == 0) {
os_free(bss->dpp_name);
bss->dpp_name = os_strdup(pos);
} else if (os_strcmp(buf, "dpp_mud_url") == 0) {
os_free(bss->dpp_mud_url);
bss->dpp_mud_url = os_strdup(pos);
} else if (os_strcmp(buf, "dpp_connector") == 0) {
os_free(bss->dpp_connector);
bss->dpp_connector = os_strdup(pos);
@ -4339,6 +4470,18 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "dpp_controller") == 0) {
if (hostapd_dpp_controller_parse(bss, pos))
return 1;
} else if (os_strcmp(buf, "dpp_configurator_connectivity") == 0) {
bss->dpp_configurator_connectivity = atoi(pos);
} else if (os_strcmp(buf, "dpp_pfs") == 0) {
int val = atoi(pos);
if (val < 0 || val > 2) {
wpa_printf(MSG_ERROR,
"Line %d: Invalid dpp_pfs value '%s'",
line, pos);
return -1;
}
bss->dpp_pfs = val;
#endif /* CONFIG_DPP2 */
#endif /* CONFIG_DPP */
#ifdef CONFIG_OWE
@ -4372,9 +4515,11 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line, pos);
return 1;
}
} else if (os_strcmp(buf, "owe_ptk_workaround") == 0) {
bss->owe_ptk_workaround = atoi(pos);
#endif /* CONFIG_OWE */
} else if (os_strcmp(buf, "coloc_intf_reporting") == 0) {
bss->coloc_intf_reporting = atoi(pos);
#endif /* CONFIG_OWE */
} else if (os_strcmp(buf, "multi_ap") == 0) {
int val = atoi(pos);
@ -4389,8 +4534,12 @@ static int hostapd_config_fill(struct hostapd_config *conf,
conf->rssi_reject_assoc_rssi = atoi(pos);
} else if (os_strcmp(buf, "rssi_reject_assoc_timeout") == 0) {
conf->rssi_reject_assoc_timeout = atoi(pos);
} else if (os_strcmp(buf, "rssi_ignore_probe_request") == 0) {
conf->rssi_ignore_probe_request = atoi(pos);
} else if (os_strcmp(buf, "pbss") == 0) {
bss->pbss = atoi(pos);
} else if (os_strcmp(buf, "transition_disable") == 0) {
bss->transition_disable = strtol(pos, NULL, 16);
#ifdef CONFIG_AIRTIME_POLICY
} else if (os_strcmp(buf, "airtime_mode") == 0) {
int val = atoi(pos);
@ -4506,6 +4655,27 @@ static int hostapd_config_fill(struct hostapd_config *conf,
}
bss->mka_psk_set |= MKA_PSK_SET_CKN;
#endif /* CONFIG_MACSEC */
} else if (os_strcmp(buf, "disable_11n") == 0) {
bss->disable_11n = !!atoi(pos);
} else if (os_strcmp(buf, "disable_11ac") == 0) {
bss->disable_11ac = !!atoi(pos);
} else if (os_strcmp(buf, "disable_11ax") == 0) {
bss->disable_11ax = !!atoi(pos);
#ifdef CONFIG_PASN
#ifdef CONFIG_TESTING_OPTIONS
} else if (os_strcmp(buf, "force_kdk_derivation") == 0) {
bss->force_kdk_derivation = atoi(pos);
} else if (os_strcmp(buf, "pasn_corrupt_mic") == 0) {
bss->pasn_corrupt_mic = atoi(pos);
#endif /* CONFIG_TESTING_OPTIONS */
} else if (os_strcmp(buf, "pasn_groups") == 0) {
if (hostapd_parse_intlist(&bss->pasn_groups, pos)) {
wpa_printf(MSG_ERROR,
"Line %d: Invalid pasn_groups value '%s'",
line, pos);
return 1;
}
#endif /* CONFIG_PASN */
} else {
wpa_printf(MSG_ERROR,
"Line %d: unknown configuration item '%s'",

File diff suppressed because it is too large Load diff

View file

@ -44,15 +44,9 @@ CONFIG_LIBNL32=y
# Driver interface for no driver (e.g., RADIUS server only)
#CONFIG_DRIVER_NONE=y
# IEEE 802.11F/IAPP
CONFIG_IAPP=y
# WPA2/IEEE 802.11i RSN pre-authentication
CONFIG_RSN_PREAUTH=y
# IEEE 802.11w (management frame protection)
CONFIG_IEEE80211W=y
# Support Operating Channel Validation
#CONFIG_OCV=y
@ -154,9 +148,6 @@ CONFIG_IPV6=y
# the IEEE 802.11 Management capability (e.g., FreeBSD/net80211)
#CONFIG_DRIVER_RADIUS_ACL=y
# IEEE 802.11n (High Throughput) support
#CONFIG_IEEE80211N=y
# Wireless Network Management (IEEE Std 802.11v-2011)
# Note: This is experimental and not complete implementation.
#CONFIG_WNM=y
@ -355,12 +346,12 @@ CONFIG_IPV6=y
# * ath10k
#
# For more details refer to:
# http://wireless.kernel.org/en/users/Documentation/acs
# https://wireless.wiki.kernel.org/en/users/documentation/acs
#
#CONFIG_ACS=y
# Multiband Operation support
# These extentions facilitate efficient use of multiple frequency bands
# These extensions facilitate efficient use of multiple frequency bands
# available to the AP and the devices that may associate with it.
#CONFIG_MBO=y
@ -389,3 +380,25 @@ CONFIG_IPV6=y
# Override default value for the wpa_disable_eapol_key_retries configuration
# parameter. See that parameter in hostapd.conf for more details.
#CFLAGS += -DDEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES=1
# Wired equivalent privacy (WEP)
# WEP is an obsolete cryptographic data confidentiality algorithm that is not
# considered secure. It should not be used for anything anymore. The
# functionality needed to use WEP is available in the current hostapd
# release under this optional build parameter. This functionality is subject to
# be completely removed in a future release.
#CONFIG_WEP=y
# Remove all TKIP functionality
# TKIP is an old cryptographic data confidentiality algorithm that is not
# considered secure. It should not be used anymore. For now, the default hostapd
# build includes this to allow mixed mode WPA+WPA2 networks to be enabled, but
# that functionality is subject to be removed in the future.
#CONFIG_NO_TKIP=y
# Pre-Association Security Negotiation (PASN)
# Experimental implementation based on IEEE P802.11z/D2.6 and the protocol
# design is still subject to change. As such, this should not yet be enabled in
# production use.
# This requires CONFIG_IEEE80211W=y to be enabled, too.
#CONFIG_PASN=y

View file

@ -41,7 +41,6 @@ interface=wlan0
# bit 2 (4) = RADIUS
# bit 3 (8) = WPA
# bit 4 (16) = driver interface
# bit 5 (32) = IAPP
# bit 6 (64) = MLME
#
# Levels (minimum value for logged events):
@ -73,7 +72,7 @@ ctrl_interface=/var/run/hostapd
# 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, hostapd is configured to use gid 0 (root). If you
# want to allow non-root users to use the contron interface, add a new group
# 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.
#
@ -147,7 +146,8 @@ ssid=test
# Operation mode (a = IEEE 802.11a (5 GHz), b = IEEE 802.11b (2.4 GHz),
# g = IEEE 802.11g (2.4 GHz), ad = IEEE 802.11ad (60 GHz); a/g options are used
# with IEEE 802.11n (HT), too, to specify band). For IEEE 802.11ac (VHT), this
# needs to be set to hw_mode=a. When using ACS (see channel parameter), a
# needs to be set to hw_mode=a. For IEEE 802.11ax (HE) on 6 GHz this needs
# to be set to hw_mode=a. When using ACS (see channel parameter), a
# special value "any" can be used to indicate that any support band can be used.
# This special case is currently supported only with drivers with which
# offloaded ACS is used.
@ -164,8 +164,14 @@ hw_mode=g
# which will enable the ACS survey based algorithm.
channel=1
# Global operating class (IEEE 802.11, Annex E, Table E-4)
# This option allows hostapd to specify the operating class of the channel
# configured with the channel parameter. channel and op_class together can
# uniquely identify channels across different bands, including the 6 GHz band.
#op_class=131
# ACS tuning - Automatic Channel Selection
# See: http://wireless.kernel.org/en/users/Documentation/acs
# See: https://wireless.wiki.kernel.org/en/users/documentation/acs
#
# You can customize the ACS survey algorithm with following variables:
#
@ -199,11 +205,26 @@ channel=1
#chanlist=100 104 108 112 116
#chanlist=1 6 11-13
# Frequency list restriction. This option allows hostapd to select one of the
# provided frequencies when a frequency should be automatically selected.
# Frequency list can be provided as range using hyphen ('-') or individual
# frequencies can be specified by comma (',') separated values
# Default: all frequencies allowed in selected hw_mode
#freqlist=2437,5955,5975
#freqlist=2437,5985-6105
# Exclude DFS channels from ACS
# This option can be used to exclude all DFS channels from the ACS channel list
# in cases where the driver supports DFS channels.
#acs_exclude_dfs=1
# Include only preferred scan channels from 6 GHz band for ACS
# This option can be used to include only preferred scan channels in the 6 GHz
# band. This can be useful in particular for devices that operate only a 6 GHz
# BSS without a collocated 2.4/5 GHz BSS.
# Default behavior is to include all PSC and non-PSC channels.
#acs_exclude_6ghz_non_psc=1
# Beacon interval in kus (1.024 ms) (default: 100; range 15..65535)
beacon_int=100
@ -258,6 +279,8 @@ fragm_threshold=-1
# beacon_rate=ht:<HT MCS>
# VHT:
# beacon_rate=vht:<VHT MCS>
# HE:
# beacon_rate=he:<HE MCS>
#
# For example, beacon_rate=10 for 1 Mbps or beacon_rate=60 for 6 Mbps (OFDM).
#beacon_rate=10
@ -550,6 +573,10 @@ wmm_ac_vo_acm=0
# Default: 1 (enabled)
#broadcast_deauth=1
# Get notifications for received Management frames on control interface
# Default: 0 (disabled)
#notify_mgmt_frames=0
##### IEEE 802.11n related configuration ######################################
# ieee80211n: Whether IEEE 802.11n (HT) is enabled
@ -559,6 +586,9 @@ wmm_ac_vo_acm=0
# Note: hw_mode=g (2.4 GHz) and hw_mode=a (5 GHz) is used to specify the band.
#ieee80211n=1
# disable_11n: Boolean (0/1) to disable HT for a specific BSS
#disable_11n=0
# ht_capab: HT capabilities (list of flags)
# LDPC coding capability: [LDPC] = supported
# Supported channel width set: [HT40-] = both 20 MHz and 40 MHz with secondary
@ -577,8 +607,6 @@ wmm_ac_vo_acm=0
# channels if needed or creation of 40 MHz channel maybe rejected based
# on overlapping BSSes. These changes are done automatically when hostapd
# is setting up the 40 MHz channel.
# Spatial Multiplexing (SM) Power Save: [SMPS-STATIC] or [SMPS-DYNAMIC]
# (SMPS disabled if neither is set)
# HT-greenfield: [GF] (disabled if not set)
# Short GI for 20 MHz: [SHORT-GI-20] (disabled if not set)
# Short GI for 40 MHz: [SHORT-GI-40] (disabled if not set)
@ -613,6 +641,9 @@ wmm_ac_vo_acm=0
# Note: hw_mode=a is used to specify that 5 GHz band is used with VHT.
#ieee80211ac=1
# disable_11ac: Boolean (0/1) to disable VHT for a specific BSS
#disable_11ac=0
# vht_capab: VHT capabilities (list of flags)
#
# vht_max_mpdu_len: [MAX-MPDU-7991] [MAX-MPDU-11454]
@ -767,6 +798,9 @@ wmm_ac_vo_acm=0
# 1 = enabled
#ieee80211ax=1
# disable_11ax: Boolean (0/1) to disable HE for a specific BSS
#disable_11ax=0
#he_su_beamformer: HE single user beamformer support
# 0 = not supported (default)
# 1 = supported
@ -785,6 +819,9 @@ wmm_ac_vo_acm=0
# he_bss_color: BSS color (1-63)
#he_bss_color=1
# he_bss_color_partial: BSS color AID equation
#he_bss_color_partial=0
#he_default_pe_duration: The duration of PE field in an HE PPDU in us
# Possible values are 0 us (default), 4 us, 8 us, 12 us, and 16 us
#he_default_pe_duration=0
@ -800,6 +837,11 @@ wmm_ac_vo_acm=0
#he_rts_threshold=0
# HE operating channel information; see matching vht_* parameters for details.
# On the 6 GHz band the center freq calculation starts from 5.950 GHz offset.
# For example idx=3 would result in 5965 MHz center frequency. In addition,
# he_oper_chwidth is ignored, and the channel width is derived from the
# configured operating class or center frequency indexes (see
# IEEE P802.11ax/D6.1 Annex E, Table E-4).
#he_oper_chwidth
#he_oper_centr_freq_seg0_idx
#he_oper_centr_freq_seg1_idx
@ -839,6 +881,65 @@ wmm_ac_vo_acm=0
#he_spr_non_srg_obss_pd_max_offset
#he_spr_srg_obss_pd_min_offset
#he_spr_srg_obss_pd_max_offset
#
# SPR SRG BSS Color
# This config represents SRG BSS Color Bitmap field of Spatial Reuse Parameter
# Set element that indicates the BSS color values used by members of the
# SRG of which the transmitting STA is a member. The value is in range of 0-63.
#he_spr_srg_bss_colors=1 2 10 63
#
# SPR SRG Partial BSSID
# This config represents SRG Partial BSSID Bitmap field of Spatial Reuse
# Parameter Set element that indicates the Partial BSSID values used by members
# of the SRG of which the transmitting STA is a member. The value range
# corresponds to one of the 64 possible values of BSSID[39:44], where the lowest
# numbered bit corresponds to Partial BSSID value 0 and the highest numbered bit
# corresponds to Partial BSSID value 63.
#he_spr_srg_partial_bssid=0 1 3 63
#
#he_6ghz_max_mpdu: Maximum MPDU Length of HE 6 GHz band capabilities.
# Indicates maximum MPDU length
# 0 = 3895 octets
# 1 = 7991 octets
# 2 = 11454 octets (default)
#he_6ghz_max_mpdu=2
#
#he_6ghz_max_ampdu_len_exp: Maximum A-MPDU Length Exponent of HE 6 GHz band
# capabilities. Indicates the maximum length of A-MPDU pre-EOF padding that
# the STA can receive. This field is an integer in the range of 0 to 7.
# The length defined by this field is equal to
# 2 pow(13 + Maximum A-MPDU Length Exponent) -1 octets
# 0 = AMPDU length of 8k
# 1 = AMPDU length of 16k
# 2 = AMPDU length of 32k
# 3 = AMPDU length of 65k
# 4 = AMPDU length of 131k
# 5 = AMPDU length of 262k
# 6 = AMPDU length of 524k
# 7 = AMPDU length of 1048k (default)
#he_6ghz_max_ampdu_len_exp=7
#
#he_6ghz_rx_ant_pat: Rx Antenna Pattern Consistency of HE 6 GHz capability.
# Indicates the possibility of Rx antenna pattern change
# 0 = Rx antenna pattern might change during the lifetime of an association
# 1 = Rx antenna pattern does not change during the lifetime of an association
# (default)
#he_6ghz_rx_ant_pat=1
#
#he_6ghz_tx_ant_pat: Tx Antenna Pattern Consistency of HE 6 GHz capability.
# Indicates the possibility of Tx antenna pattern change
# 0 = Tx antenna pattern might change during the lifetime of an association
# 1 = Tx antenna pattern does not change during the lifetime of an association
# (default)
#he_6ghz_tx_ant_pat=1
# Unsolicited broadcast Probe Response transmission settings
# This is for the 6 GHz band only. If the interval is set to a non-zero value,
# the AP schedules unsolicited broadcast Probe Response frames to be
# transmitted for in-band discovery. Refer to
# IEEE P802.11ax/D8.0 26.17.2.3.2, AP behavior for fast passive scanning.
# Valid range: 0..20 TUs; default is 0 (disabled)
#unsol_bcast_probe_resp_interval=0
##### IEEE 802.1X-2004 related configuration ##################################
@ -877,6 +978,8 @@ eapol_key_index_workaround=0
# EAP reauthentication period in seconds (default: 3600 seconds; 0 = disable
# reauthentication).
# Note: Reauthentications may enforce a disconnection, check the related
# parameter wpa_deny_ptk0_rekey for details.
#eap_reauth_period=3600
# Use PAE group address (01:80:c2:00:00:03) instead of individual target
@ -1012,7 +1115,7 @@ eap_server=0
#check_crl=1
# Specify whether to ignore certificate CRL validity time mismatches with
# errors X509_V_ERR_CERT_HAS_EXPIRED and X509_V_ERR_CERT_NOT_YET_VALID.
# errors X509_V_ERR_CRL_HAS_EXPIRED and X509_V_ERR_CRL_NOT_YET_VALID.
#
# 0 = ignore errors
# 1 = do not ignore errors (default)
@ -1081,6 +1184,12 @@ eap_server=0
# [ENABLE-TLSv1.3] = enable TLSv1.3 (experimental - disabled by default)
#tls_flags=[flag1][flag2]...
# Maximum number of EAP message rounds with data (default: 100)
#max_auth_rounds=100
# Maximum number of short EAP message rounds (default: 50)
#max_auth_rounds_short=50
# Cached OCSP stapling response (DER encoded)
# If set, this file is sent as a certificate status response by the EAP server
# if the EAP peer requests certificate status in the ClientHello message.
@ -1167,7 +1276,7 @@ eap_server=0
# should be unique across all issuing servers. In theory, this is a variable
# length field, but due to some existing implementations requiring A-ID to be
# 16 octets in length, it is strongly recommended to use that length for the
# field to provid interoperability with deployed peer implementations. This
# field to provide interoperability with deployed peer implementations. This
# field is configured in hex format.
#eap_fast_a_id=101112131415161718191a1b1c1d1e1f
@ -1194,6 +1303,8 @@ eap_server=0
# EAP-TEAP authentication type
# 0 = inner EAP (default)
# 1 = Basic-Password-Auth
# 2 = Do not require Phase 2 authentication if client can be authenticated
# during Phase 1
#eap_teap_auth=0
# EAP-TEAP authentication behavior when using PAC
@ -1201,6 +1312,20 @@ eap_server=0
# 1 = skip inner authentication (inner EAP/Basic-Password-Auth)
#eap_teap_pac_no_inner=0
# EAP-TEAP behavior with Result TLV
# 0 = include with Intermediate-Result TLV (default)
# 1 = send in a separate message (for testing purposes)
#eap_teap_separate_result=0
# EAP-TEAP identities
# 0 = allow any identity type (default)
# 1 = require user identity
# 2 = require machine identity
# 3 = request user identity; accept either user or machine identity
# 4 = request machine identity; accept either user or machine identity
# 5 = require both user and machine identity
#eap_teap_id=0
# EAP-SIM and EAP-AKA protected success/failure indication using AT_RESULT_IND
# (default: 0 = disabled).
#eap_sim_aka_result_ind=1
@ -1223,11 +1348,6 @@ eap_server=0
# Whether to enable ERP on the EAP server.
#eap_server_erp=1
##### IEEE 802.11f - Inter-Access Point Protocol (IAPP) #######################
# Interface to be used for IAPP broadcast packets
#iapp_interface=eth0
##### RADIUS client configuration #############################################
# for IEEE 802.1X with external Authentication Server, IEEE 802.11
@ -1261,6 +1381,12 @@ own_ip_addr=127.0.0.1
# used, e.g., when the device has multiple IP addresses.
#radius_client_addr=127.0.0.1
# RADIUS client forced local interface. Helps run properly with VRF
# Default is none set which allows the network stack to pick the appropriate
# interface automatically.
# Example below binds to eth0
#radius_client_dev=eth0
# RADIUS authentication server
#auth_server_addr=127.0.0.1
#auth_server_port=1812
@ -1466,6 +1592,17 @@ own_ip_addr=127.0.0.1
# wpa_key_mgmt=SAE for WPA3-Personal instead of wpa_key_mgmt=WPA-PSK).
#wpa=2
# Extended Key ID support for Individually Addressed frames
#
# Extended Key ID allows to rekey PTK keys without the impacts the "normal"
# PTK rekeying with only a single Key ID 0 has. It can only be used when the
# driver supports it and RSN/WPA2 is used with a CCMP/GCMP pairwise cipher.
#
# 0 = force off, i.e., use only Key ID 0 (default)
# 1 = enable and use Extended Key ID support when possible
# 2 = identical to 1 but start with Key ID 1 when possible
#extended_key_id=0
# WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit
# secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase
# (8..63 characters) that will be converted to PSK. This conversion uses SSID
@ -1566,8 +1703,26 @@ own_ip_addr=127.0.0.1
# Maximum lifetime for PTK in seconds. This can be used to enforce rekeying of
# PTK to mitigate some attacks against TKIP deficiencies.
# Warning: PTK rekeying is buggy with many drivers/devices and with such
# devices, the only secure method to rekey the PTK without Extended Key ID
# support requires a disconnection. Check the related parameter
# wpa_deny_ptk0_rekey for details.
#wpa_ptk_rekey=600
# Workaround for PTK rekey issues
#
# PTK0 rekeys (rekeying the PTK without "Extended Key ID for Individually
# Addressed Frames") can degrade the security and stability with some cards.
# To avoid such issues hostapd can replace those PTK rekeys (including EAP
# reauthentications) with disconnects.
#
# Available options:
# 0 = always rekey when configured/instructed (default)
# 1 = only rekey when the local driver is explicitly indicating it can perform
# this operation without issues
# 2 = never allow PTK0 rekeys
#wpa_deny_ptk0_rekey=0
# The number of times EAPOL-Key Message 1/4 and Message 3/4 in the RSN 4-Way
# Handshake are retried per 4-Way Handshake attempt.
# (dot11RSNAConfigPairwiseUpdateCount)
@ -1618,6 +1773,12 @@ own_ip_addr=127.0.0.1
# 1 = optional
# 2 = required
#ieee80211w=0
# The most common configuration options for this based on the PMF (protected
# management frames) certification program are:
# PMF enabled: ieee80211w=1 and wpa_key_mgmt=WPA-EAP WPA-EAP-SHA256
# PMF required: ieee80211w=2 and wpa_key_mgmt=WPA-EAP-SHA256
# (and similarly for WPA-PSK and WPA-PSK-SHA256 if WPA2-Personal is used)
# WPA3-Personal-only mode: ieee80211w=2 and wpa_key_mgmt=SAE
# Group management cipher suite
# Default: AES-128-CMAC (BIP)
@ -1630,6 +1791,13 @@ own_ip_addr=127.0.0.1
# available in deployed devices.
#group_mgmt_cipher=AES-128-CMAC
# Beacon Protection (management frame protection for Beacon frames)
# This depends on management frame protection being enabled (ieee80211w != 0)
# and beacon protection support indication from the driver.
# 0 = disabled (default)
# 1 = enabled
#beacon_prot=0
# Association SA Query maximum timeout (in TU = 1.024 ms; for MFP)
# (maximum time to wait for a SA Query response)
# dot11AssociationSAQueryMaximumTimeout, 1...4294967295
@ -1642,9 +1810,25 @@ own_ip_addr=127.0.0.1
# ocv: Operating Channel Validation
# This is a countermeasure against multi-channel man-in-the-middle attacks.
# Enabling this depends on the driver's support for OCV when the driver SME is
# used. If hostapd SME is used, this will be enabled just based on this
# configuration.
# Enabling this automatically also enables ieee80211w, if not yet enabled.
# 0 = disabled (default)
# 1 = enabled
# 2 = enabled in workaround mode - Allow STA that claims OCV capability to
# connect even if the STA doesn't send OCI or negotiate PMF. This
# workaround is to improve interoperability with legacy STAs which are
# wrongly copying reserved bits of RSN capabilities from the AP's
# RSNE into (Re)Association Request frames. When this configuration is
# enabled, the AP considers STA is OCV capable only when the STA indicates
# MFP capability in (Re)Association Request frames and sends OCI in
# EAPOL-Key msg 2/4/FT Reassociation Request frame/FILS (Re)Association
# Request frame; otherwise, the AP disables OCV for the current connection
# with the STA. Enabling this workaround mode reduced OCV protection to
# some extend since it allows misbehavior to go through. As such, this
# should be enabled only if interoperability with misbehaving STAs is
# needed.
#ocv=1
# disable_pmksa_caching: Disable PMKSA caching
@ -1676,7 +1860,7 @@ own_ip_addr=127.0.0.1
# be followed by optional peer MAC address (dot11RSNAConfigPasswordPeerMac) and
# by optional password identifier (dot11RSNAConfigPasswordIdentifier). In
# addition, an optional VLAN ID specification can be used to bind the station
# to the specified VLAN whenver the specific SAE password entry is used.
# to the specified VLAN whenever the specific SAE password entry is used.
#
# If the peer MAC address is not included or is set to the wildcard address
# (ff:ff:ff:ff:ff:ff), the entry is available for any station to use. If a
@ -1691,7 +1875,8 @@ own_ip_addr=127.0.0.1
# special meaning of removing all previously added entries.
#
# sae_password uses the following encoding:
#<password/credential>[|mac=<peer mac>][|vlanid=<VLAN ID>][|id=<identifier>]
#<password/credential>[|mac=<peer mac>][|vlanid=<VLAN ID>]
#[|pk=<m:ECPrivateKey-base64>][|id=<identifier>]
# Examples:
#sae_password=secret
#sae_password=really secret|mac=ff:ff:ff:ff:ff:ff
@ -1701,10 +1886,11 @@ own_ip_addr=127.0.0.1
# SAE threshold for anti-clogging mechanism (dot11RSNASAEAntiCloggingThreshold)
# This parameter defines how many open SAE instances can be in progress at the
# same time before the anti-clogging mechanism is taken into use.
#sae_anti_clogging_threshold=5
#sae_anti_clogging_threshold=5 (deprecated)
#anti_clogging_threshold=5
# Maximum number of SAE synchronization errors (dot11RSNASAESync)
# The offending SAe peer will be disconnected if more than this many
# The offending SAE peer will be disconnected if more than this many
# synchronization errors happen.
#sae_sync=5
@ -1729,6 +1915,23 @@ own_ip_addr=127.0.0.1
# MFP while SAE stations are required to negotiate MFP if sae_require_mfp=1.
#sae_require_mfp=0
# SAE Confirm behavior
# By default, AP will send out only SAE Commit message in response to a received
# SAE Commit message. This parameter can be set to 1 to override that behavior
# to send both SAE Commit and SAE Confirm messages without waiting for the STA
# to send its SAE Confirm message first.
#sae_confirm_immediate=0
# SAE mechanism for PWE derivation
# 0 = hunting-and-pecking loop only (default without password identifier)
# 1 = hash-to-element only (default with password identifier)
# 2 = both hunting-and-pecking loop and hash-to-element enabled
# Note: The default value is likely to change from 0 to 2 once the new
# hash-to-element mechanism has received more interoperability testing.
# When using SAE password identifier, the hash-to-element mechanism is used
# regardless of the sae_pwe parameter value.
#sae_pwe=0
# FILS Cache Identifier (16-bit value in hexdump format)
#fils_cache_id=0011
@ -1753,6 +1956,19 @@ own_ip_addr=127.0.0.1
# http://www.iana.org/assignments/ipsec-registry/ipsec-registry.xml#ipsec-registry-10
#owe_groups=19 20 21
# OWE PTK derivation workaround
# Initial OWE implementation used SHA256 when deriving the PTK for all OWE
# groups. This was supposed to change to SHA384 for group 20 and SHA512 for
# group 21. This parameter can be used to enable workaround for interoperability
# with stations that use SHA256 with groups 20 and 21. By default (0) only the
# appropriate hash function is accepted. When workaround is enabled (1), the
# appropriate hash function is tried first and if that fails, SHA256-based PTK
# derivation is attempted. This workaround can result in reduced security for
# groups 20 and 21, but is required for interoperability with older
# implementations. There is no impact to group 19 behavior. The workaround is
# disabled by default and can be enabled by uncommenting the following line.
#owe_ptk_workaround=1
# OWE transition mode configuration
# Pointer to the matching open/OWE BSS
#owe_transition_bssid=<bssid>
@ -1790,6 +2006,38 @@ own_ip_addr=127.0.0.1
# default: 30 TUs (= 30.72 milliseconds)
#fils_hlp_wait_time=30
# FILS Discovery frame transmission minimum and maximum interval settings.
# If fils_discovery_max_interval is non-zero, the AP enables FILS Discovery
# frame transmission. These values use TUs as the unit and have allowed range
# of 0-10000. fils_discovery_min_interval defaults to 20.
#fils_discovery_min_interval=20
#fils_discovery_max_interval=0
# Transition Disable indication
# The AP can notify authenticated stations to disable transition mode in their
# network profiles when the network has completed transition steps, i.e., once
# sufficiently large number of APs in the ESS have been updated to support the
# more secure alternative. When this indication is used, the stations are
# expected to automatically disable transition mode and less secure security
# options. This includes use of WEP, TKIP (including use of TKIP as the group
# cipher), and connections without PMF.
# Bitmap bits:
# bit 0 (0x01): WPA3-Personal (i.e., disable WPA2-Personal = WPA-PSK and only
# allow SAE to be used)
# bit 1 (0x02): SAE-PK (disable SAE without use of SAE-PK)
# bit 2 (0x04): WPA3-Enterprise (move to requiring PMF)
# bit 3 (0x08): Enhanced Open (disable use of open network; require OWE)
# (default: 0 = do not include Transition Disable KDE)
#transition_disable=0x01
# PASN ECDH groups
# PASN implementations are required to support group 19 (NIST P-256). If this
# parameter is not set, only group 19 is supported by default. This
# configuration parameter can be used to specify a limited set of allowed
# groups. The group values are listed in the IANA registry:
# http://www.iana.org/assignments/ipsec-registry/ipsec-registry.xml#ipsec-registry-10
#pasn_groups=19 20 21
##### IEEE 802.11r configuration ##############################################
# Mobility Domain identifier (dot11FTMobilityDomainID, MDID)
@ -1833,7 +2081,7 @@ own_ip_addr=127.0.0.1
# Wildcard entry:
# Upon receiving a response from R0KH, it will be added to this list, so
# subsequent requests won't be broadcast. If R0KH does not reply, it will be
# blacklisted.
# temporarily blocked (see rkh_neg_timeout).
#r0kh=ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff
# List of R1KHs in the same Mobility Domain
@ -1889,7 +2137,7 @@ own_ip_addr=127.0.0.1
#ft_psk_generate_local=0
##### Neighbor table ##########################################################
# Maximum number of entries kept in AP table (either for neigbor table or for
# Maximum number of entries kept in AP table (either for neighbor table or for
# detecting Overlapping Legacy BSS Condition). The oldest entry will be
# removed when adding a new entry that would make the list grow over this
# limit. Note! WFA certification for IEEE 802.11g requires that OLBC is
@ -2143,6 +2391,13 @@ own_ip_addr=127.0.0.1
#wps_nfc_dh_privkey: Hexdump of DH Private Key
#wps_nfc_dev_pw: Hexdump of Device Password
# Application Extension attribute for Beacon and Probe Response frames
# This parameter can be used to add application extension into WPS IE. The
# contents of this parameter starts with 16-octet (32 hexdump characters) of
# UUID to identify the specific application and that is followed by the actual
# application specific data.
#wps_application_ext=<hexdump>
##### Wi-Fi Direct (P2P) ######################################################
# Enable P2P Device management
@ -2151,6 +2406,31 @@ own_ip_addr=127.0.0.1
# Allow cross connection
#allow_cross_connection=1
##### Device Provisioning Protocol (DPP) ######################################
# Name for Enrollee's DPP Configuration Request
#dpp_name=Test
# MUD URL for Enrollee's DPP Configuration Request (optional)
#dpp_mud_url=https://example.com/mud
#dpp_connector
#dpp_netaccesskey
#dpp_netaccesskey_expiry
#dpp_csign
#dpp_controller
# Configurator Connectivity indication
# 0: no Configurator is currently connected (default)
# 1: advertise that a Configurator is available
#dpp_configurator_connectivity=0
# DPP PFS
# 0: allow PFS to be used or not used (default)
# 1: require PFS to be used (note: not compatible with DPP R1)
# 2: do not allow PFS to be used
#dpp_pfs=0
#### TDLS (IEEE 802.11z-2010) #################################################
# Prohibit use of TDLS in this BSS
@ -2531,7 +2811,7 @@ own_ip_addr=127.0.0.1
# Default is 0 = OCE disabled
#oce=0
# RSSI-based assocition rejection
# RSSI-based association rejection
#
# Reject STA association if RSSI is below given threshold (in dBm)
# Allowed range: -60 to -90 dBm; default = 0 (rejection disabled)
@ -2546,6 +2826,10 @@ own_ip_addr=127.0.0.1
# threshold (range: 0..255, default=30).
#rssi_reject_assoc_timeout=30
# Ignore Probe Request frames if RSSI is below given threshold (in dBm)
# Allowed range: -60 to -90 dBm; default = 0 (rejection disabled)
#rssi_ignore_probe_request=-75
##### Fast Session Transfer (FST) support #####################################
#
# The options in this section are only available when the build configuration
@ -2638,6 +2922,19 @@ own_ip_addr=127.0.0.1
# airtime.
#airtime_bss_limit=1
##### EDMG support ############################################################
#
# Enable EDMG capability for AP mode in the 60 GHz band. Default value is false.
# To configure channel bonding for an EDMG AP use edmg_channel below.
# If enable_edmg is set and edmg_channel is not set, EDMG CB1 will be
# configured.
#enable_edmg=1
#
# Configure channel bonding for AP mode in the 60 GHz band.
# This parameter is relevant only if enable_edmg is set.
# Default value is 0 (no channel bonding).
#edmg_channel=9
##### TESTING OPTIONS #########################################################
#
# The options in this section are only available when the build configuration

View file

@ -7,9 +7,15 @@
# keyid=<keyid_string>
# An optional VLAN ID can be specified by prefixing the line with
# vlanid=<VLAN ID>.
# An optional WPS tag can be added by prefixing the line with
# wps=<0/1> (default: 0). Any matching entry with that tag will be used when
# generating a PSK for a WPS Enrollee instead of generating a new random
# per-Enrollee PSK.
00:00:00:00:00:00 secret passphrase
00:11:22:33:44:55 another passphrase
00:22:33:44:55:66 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
keyid=example_id 00:11:22:33:44:77 passphrase with keyid
vlanid=3 00:00:00:00:00:00 passphrase with vlanid
wps=1 00:00:00:00:00:00 passphrase for WPS
wps=1 11:22:33:44:55:00 dev-specific passphrase for WPS
00:00:00:00:00:00 another passphrase for all STAs

View file

@ -54,7 +54,7 @@ static void usage(void)
fprintf(stderr, "%s\n", hostapd_cli_version);
fprintf(stderr,
"\n"
"usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
"usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvBr] "
"[-a<path>] \\\n"
" [-P<pid file>] [-G<ping interval>] [command..]\n"
"\n"
@ -68,6 +68,9 @@ static void usage(void)
" -a<file> run in daemon mode executing the action file "
"based on events\n"
" from hostapd\n"
" -r try to reconnect when client socket is "
"disconnected.\n"
" This is useful only when used with -a.\n"
" -B run a daemon in the background\n"
" -i<ifname> Interface to listen on (default: first "
"interface found in the\n"
@ -401,7 +404,6 @@ static int hostapd_cli_cmd_signature(struct wpa_ctrl *ctrl, int argc,
#endif /* CONFIG_TAXONOMY */
#ifdef CONFIG_IEEE80211W
static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@ -414,7 +416,6 @@ static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
return wpa_ctrl_command(ctrl, buf);
}
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_WPS
@ -974,7 +975,7 @@ static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
dir = opendir(ctrl_iface_dir);
if (dir == NULL) {
printf("Control interface directory '%s' could not be "
"openned.\n", ctrl_iface_dir);
"opened.\n", ctrl_iface_dir);
return;
}
@ -1226,14 +1227,15 @@ static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
char cmd[256];
int res;
if (argc < 2 || argc > 3) {
if (argc < 2 || argc > 4) {
printf("Invalid vendor command\n"
"usage: <vendor id> <command id> [<hex formatted command argument>]\n");
"usage: <vendor id> <command id> [<hex formatted command argument>] [nested=<0|1>]\n");
return -1;
}
res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
argc == 3 ? argv[2] : "");
res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s%s%s", argv[0],
argv[1], argc >= 3 ? argv[2] : "",
argc == 4 ? " " : "", argc == 4 ? argv[3] : "");
if (os_snprintf_error(sizeof(cmd), res)) {
printf("Too long VENDOR command.\n");
return -1;
@ -1311,24 +1313,17 @@ static int hostapd_cli_cmd_set_neighbor(struct wpa_ctrl *ctrl, int argc,
}
static int hostapd_cli_cmd_show_neighbor(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
return wpa_ctrl_command(ctrl, "SHOW_NEIGHBOR");
}
static int hostapd_cli_cmd_remove_neighbor(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
char cmd[400];
int res;
if (argc != 2) {
printf("Invalid remove_neighbor command: needs 2 arguments\n");
return -1;
}
res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NEIGHBOR %s %s",
argv[0], argv[1]);
if (os_snprintf_error(sizeof(cmd), res)) {
printf("Too long REMOVE_NEIGHBOR command.\n");
return -1;
}
return wpa_ctrl_command(ctrl, cmd);
return hostapd_cli_cmd(ctrl, "REMOVE_NEIGHBOR", 1, argc, argv);
}
@ -1408,6 +1403,13 @@ static int hostapd_cli_cmd_dpp_bootstrap_info(struct wpa_ctrl *ctrl, int argc,
}
static int hostapd_cli_cmd_dpp_bootstrap_set(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
return hostapd_cli_cmd(ctrl, "DPP_BOOTSTRAP_SET", 1, argc, argv);
}
static int hostapd_cli_cmd_dpp_auth_init(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@ -1470,6 +1472,37 @@ static int hostapd_cli_cmd_dpp_pkex_remove(struct wpa_ctrl *ctrl, int argc,
return hostapd_cli_cmd(ctrl, "DPP_PKEX_REMOVE", 1, argc, argv);
}
#ifdef CONFIG_DPP2
static int hostapd_cli_cmd_dpp_controller_start(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
return hostapd_cli_cmd(ctrl, "DPP_CONTROLLER_START", 1, argc, argv);
}
static int hostapd_cli_cmd_dpp_controller_stop(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
return wpa_ctrl_command(ctrl, "DPP_CONTROLLER_STOP");
}
static int hostapd_cli_cmd_dpp_chirp(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
return hostapd_cli_cmd(ctrl, "DPP_CHIRP", 1, argc, argv);
}
static int hostapd_cli_cmd_dpp_stop_chirp(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
return wpa_ctrl_command(ctrl, "DPP_STOP_CHIRP");
}
#endif /* CONFIG_DPP2 */
#endif /* CONFIG_DPP */
@ -1508,6 +1541,14 @@ static int hostapd_cli_cmd_reload_wpa_psk(struct wpa_ctrl *ctrl, int argc,
}
#ifdef ANDROID
static int hostapd_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
return hostapd_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
}
#endif /* ANDROID */
struct hostapd_cli_cmd {
const char *cmd;
int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
@ -1542,10 +1583,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
{ "signature", hostapd_cli_cmd_signature, hostapd_complete_stations,
"<addr> = get taxonomy signature for a station" },
#endif /* CONFIG_TAXONOMY */
#ifdef CONFIG_IEEE80211W
{ "sa_query", hostapd_cli_cmd_sa_query, hostapd_complete_stations,
"<addr> = send SA Query to a station" },
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_WPS
{ "wps_pin", hostapd_cli_cmd_wps_pin, NULL,
"<uuid> <pin> [timeout] [addr] = add WPS Enrollee PIN" },
@ -1637,8 +1676,10 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
{ "set_neighbor", hostapd_cli_cmd_set_neighbor, NULL,
"<addr> <ssid=> <nr=> [lci=] [civic=] [stat]\n"
" = add AP to neighbor database" },
{ "show_neighbor", hostapd_cli_cmd_show_neighbor, NULL,
" = show neighbor database entries" },
{ "remove_neighbor", hostapd_cli_cmd_remove_neighbor, NULL,
"<addr> <ssid=> = remove AP from neighbor database" },
"<addr> [ssid=<hex>] = remove AP from neighbor database" },
{ "req_lci", hostapd_cli_cmd_req_lci, hostapd_complete_stations,
"<addr> = send LCI request to a station"},
{ "req_range", hostapd_cli_cmd_req_range, NULL,
@ -1656,6 +1697,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
"<id> = get DPP bootstrap URI" },
{ "dpp_bootstrap_info", hostapd_cli_cmd_dpp_bootstrap_info, NULL,
"<id> = show DPP bootstrap information" },
{ "dpp_bootstrap_set", hostapd_cli_cmd_dpp_bootstrap_set, NULL,
"<id> [conf=..] [ssid=<SSID>] [ssid_charset=#] [psk=<PSK>] [pass=<passphrase>] [configurator=<id>] [conn_status=#] [akm_use_selector=<0|1>] [group_id=..] [expiry=#] [csrattrs=..] = set DPP configurator parameters" },
{ "dpp_auth_init", hostapd_cli_cmd_dpp_auth_init, NULL,
"peer=<id> [own=<id>] = initiate DPP bootstrapping" },
{ "dpp_listen", hostapd_cli_cmd_dpp_listen, NULL,
@ -1676,6 +1719,16 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
"add PKEX code" },
{ "dpp_pkex_remove", hostapd_cli_cmd_dpp_pkex_remove, NULL,
"*|<id> = remove DPP pkex information" },
#ifdef CONFIG_DPP2
{ "dpp_controller_start", hostapd_cli_cmd_dpp_controller_start, NULL,
"[tcp_port=<port>] [role=..] = start DPP controller" },
{ "dpp_controller_stop", hostapd_cli_cmd_dpp_controller_stop, NULL,
"= stop DPP controller" },
{ "dpp_chirp", hostapd_cli_cmd_dpp_chirp, NULL,
"own=<BI ID> iter=<count> = start DPP chirp" },
{ "dpp_stop_chirp", hostapd_cli_cmd_dpp_stop_chirp, NULL,
"= stop DPP chirp" },
#endif /* CONFIG_DPP2 */
#endif /* CONFIG_DPP */
{ "accept_acl", hostapd_cli_cmd_accept_macacl, NULL,
"=Add/Delete/Show/Clear accept MAC ACL" },
@ -1687,6 +1740,10 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
"<addr> [req_mode=] <measurement request hexdump> = send a Beacon report request to a station" },
{ "reload_wpa_psk", hostapd_cli_cmd_reload_wpa_psk, NULL,
"= reload wpa_psk_file only" },
#ifdef ANDROID
{ "driver", hostapd_cli_cmd_driver, NULL,
"<driver sub command> [<hex formatted data>] = send driver command data" },
#endif /* ANDROID */
{ NULL, NULL, NULL, NULL }
};
@ -2011,12 +2068,13 @@ int main(int argc, char *argv[])
int warning_displayed = 0;
int c;
int daemonize = 0;
int reconnect = 0;
if (os_program_init())
return -1;
for (;;) {
c = getopt(argc, argv, "a:BhG:i:p:P:s:v");
c = getopt(argc, argv, "a:BhG:i:p:P:rs:v");
if (c < 0)
break;
switch (c) {
@ -2045,6 +2103,9 @@ int main(int argc, char *argv[])
case 'P':
pid_file = optarg;
break;
case 'r':
reconnect = 1;
break;
case 's':
client_socket_dir = optarg;
break;
@ -2087,8 +2148,7 @@ int main(int argc, char *argv[])
printf("Connection established.\n");
break;
}
if (!interactive) {
if (!interactive && !reconnect) {
perror("Failed to connect to hostapd - "
"wpa_ctrl_open");
return -1;
@ -2106,8 +2166,14 @@ int main(int argc, char *argv[])
return -1;
if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
return -1;
if (interactive)
if (reconnect && action_file && ctrl_ifname) {
while (!hostapd_cli_quit) {
if (ctrl_conn)
hostapd_cli_action(ctrl_conn);
os_sleep(1, 0);
hostapd_cli_reconnect(ctrl_ifname);
}
} else if (interactive)
hostapd_cli_interactive();
else if (action_file)
hostapd_cli_action(ctrl_conn);

View file

@ -81,9 +81,6 @@ static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
case HOSTAPD_MODULE_DRIVER:
module_str = "DRIVER";
break;
case HOSTAPD_MODULE_IAPP:
module_str = "IAPP";
break;
case HOSTAPD_MODULE_MLME:
module_str = "MLME";
break;
@ -221,7 +218,7 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
struct wowlan_triggers *triggs;
iface->drv_flags = capa.flags;
iface->smps_modes = capa.smps_modes;
iface->drv_flags2 = capa.flags2;
iface->probe_resp_offloads = capa.probe_resp_offloads;
/*
* Use default extended capa values from per-radio information
@ -263,7 +260,7 @@ hostapd_interface_init(struct hapd_interfaces *interfaces, const char *if_name,
struct hostapd_iface *iface;
int k;
wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname);
wpa_printf(MSG_DEBUG, "Configuration file: %s", config_fname);
iface = hostapd_init(interfaces, config_fname);
if (!iface)
return NULL;
@ -454,11 +451,12 @@ static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize,
static void show_version(void)
{
fprintf(stderr,
"hostapd v" VERSION_STR "\n"
"hostapd v%s\n"
"User space daemon for IEEE 802.11 AP management,\n"
"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
"Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> "
"and contributors\n");
"and contributors\n",
VERSION_STR);
}
@ -676,7 +674,10 @@ int main(int argc, char *argv[])
#endif /* CONFIG_ETH_P_OUI */
#ifdef CONFIG_DPP
os_memset(&dpp_conf, 0, sizeof(dpp_conf));
/* TODO: dpp_conf.msg_ctx? */
dpp_conf.cb_ctx = &interfaces;
#ifdef CONFIG_DPP2
dpp_conf.remove_bi = hostapd_dpp_remove_bi;
#endif /* CONFIG_DPP2 */
interfaces.dpp = dpp_global_init(&dpp_conf);
if (!interfaces.dpp)
return -1;
@ -771,7 +772,7 @@ int main(int argc, char *argv[])
if (log_file)
wpa_debug_open_file(log_file);
else
if (!log_file && !wpa_debug_syslog)
wpa_debug_setup_stdout();
#ifdef CONFIG_DEBUG_SYSLOG
if (wpa_debug_syslog)
@ -905,8 +906,11 @@ int main(int argc, char *argv[])
!!(interfaces.iface[i]->drv_flags &
WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
hostapd_interface_deinit_free(interfaces.iface[i]);
interfaces.iface[i] = NULL;
}
os_free(interfaces.iface);
interfaces.iface = NULL;
interfaces.count = 0;
#ifdef CONFIG_DPP
dpp_global_deinit(interfaces.dpp);

196
hostapd/sae_pk_gen.c Normal file
View file

@ -0,0 +1,196 @@
/*
* SAE-PK password/modifier generator
* Copyright (c) 2020, The Linux Foundation
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
#include "utils/common.h"
#include "utils/base64.h"
#include "crypto/crypto.h"
#include "common/sae.h"
int main(int argc, char *argv[])
{
char *der = NULL;
size_t der_len;
struct crypto_ec_key *key = NULL;
struct wpabuf *pub = NULL;
u8 *data = NULL, *m;
size_t data_len;
char *b64 = NULL, *pw = NULL, *pos, *src;
int sec, j;
int ret = -1;
u8 hash[SAE_MAX_HASH_LEN];
char hash_hex[2 * SAE_MAX_HASH_LEN + 1];
u8 pw_base_bin[SAE_MAX_HASH_LEN];
u8 *dst;
int group;
size_t hash_len;
unsigned long long i, expected;
char m_hex[2 * SAE_PK_M_LEN + 1];
u32 sec_1b, val20;
wpa_debug_level = MSG_INFO;
if (os_program_init() < 0)
goto fail;
if (argc != 4) {
fprintf(stderr,
"usage: sae_pk_gen <DER ECPrivateKey file> <Sec:3|5> <SSID>\n");
goto fail;
}
sec = atoi(argv[2]);
if (sec != 3 && sec != 5) {
fprintf(stderr,
"Invalid Sec value (allowed values: 3 and 5)\n");
goto fail;
}
sec_1b = sec == 3;
expected = 1;
for (j = 0; j < sec; j++)
expected *= 256;
der = os_readfile(argv[1], &der_len);
if (!der) {
fprintf(stderr, "Could not read %s: %s\n",
argv[1], strerror(errno));
goto fail;
}
key = crypto_ec_key_parse_priv((u8 *) der, der_len);
if (!key) {
fprintf(stderr, "Could not parse ECPrivateKey\n");
goto fail;
}
pub = crypto_ec_key_get_subject_public_key(key);
if (!pub) {
fprintf(stderr, "Failed to build SubjectPublicKey\n");
goto fail;
}
group = crypto_ec_key_group(key);
switch (group) {
case 19:
hash_len = 32;
break;
case 20:
hash_len = 48;
break;
case 21:
hash_len = 64;
break;
default:
fprintf(stderr, "Unsupported private key group\n");
goto fail;
}
data_len = os_strlen(argv[3]) + SAE_PK_M_LEN + wpabuf_len(pub);
data = os_malloc(data_len);
if (!data) {
fprintf(stderr, "No memory for data buffer\n");
goto fail;
}
os_memcpy(data, argv[3], os_strlen(argv[3]));
m = data + os_strlen(argv[3]);
if (os_get_random(m, SAE_PK_M_LEN) < 0) {
fprintf(stderr, "Could not generate random Modifier M\n");
goto fail;
}
os_memcpy(m + SAE_PK_M_LEN, wpabuf_head(pub), wpabuf_len(pub));
fprintf(stderr, "Searching for a suitable Modifier M value\n");
for (i = 0;; i++) {
if (sae_hash(hash_len, data, data_len, hash) < 0) {
fprintf(stderr, "Hash failed\n");
goto fail;
}
if (hash[0] == 0 && hash[1] == 0) {
if ((hash[2] & 0xf0) == 0)
fprintf(stderr, "\r%3.2f%%",
100.0 * (double) i / (double) expected);
for (j = 2; j < sec; j++) {
if (hash[j])
break;
}
if (j == sec)
break;
}
inc_byte_array(m, SAE_PK_M_LEN);
}
if (wpa_snprintf_hex(m_hex, sizeof(m_hex), m, SAE_PK_M_LEN) < 0 ||
wpa_snprintf_hex(hash_hex, sizeof(hash_hex), hash, hash_len) < 0)
goto fail;
fprintf(stderr, "\nFound a valid hash in %llu iterations: %s\n",
i + 1, hash_hex);
b64 = base64_encode(der, der_len, NULL);
if (!b64)
goto fail;
src = pos = b64;
while (*src) {
if (*src != '\n')
*pos++ = *src;
src++;
}
*pos = '\0';
/* Skip 8*Sec bits and add Sec_1b as the every 20th bit starting with
* one. */
os_memset(pw_base_bin, 0, sizeof(pw_base_bin));
dst = pw_base_bin;
for (j = 0; j < 8 * (int) hash_len / 20; j++) {
val20 = sae_pk_get_be19(hash + sec);
val20 |= sec_1b << 19;
sae_pk_buf_shift_left_19(hash + sec, hash_len - sec);
if (j & 1) {
*dst |= (val20 >> 16) & 0x0f;
dst++;
*dst++ = (val20 >> 8) & 0xff;
*dst++ = val20 & 0xff;
} else {
*dst++ = (val20 >> 12) & 0xff;
*dst++ = (val20 >> 4) & 0xff;
*dst = (val20 << 4) & 0xf0;
}
}
if (wpa_snprintf_hex(hash_hex, sizeof(hash_hex),
pw_base_bin, hash_len - sec) >= 0)
fprintf(stderr, "PasswordBase binary data for base32: %s",
hash_hex);
pw = sae_pk_base32_encode(pw_base_bin, 20 * 3 - 5);
if (!pw)
goto fail;
printf("# SAE-PK password/M/private key for Sec=%d.\n", sec);
printf("sae_password=%s|pk=%s:%s\n", pw, m_hex, b64);
printf("# Longer passwords can be used for improved security at the cost of usability:\n");
for (j = 4; j <= ((int) hash_len * 8 + 5 - 8 * sec) / 19; j++) {
os_free(pw);
pw = sae_pk_base32_encode(pw_base_bin, 20 * j - 5);
if (pw)
printf("# %s\n", pw);
}
ret = 0;
fail:
os_free(der);
wpabuf_free(pub);
crypto_ec_key_deinit(key);
os_free(data);
os_free(b64);
os_free(pw);
os_program_deinit();
return ret;
}

View file

@ -1,28 +1,6 @@
all: hs20-osu-client
ALL=hs20-osu-client
ifndef CC
CC=gcc
endif
ifndef LDO
LDO=$(CC)
endif
ifeq ($(QUIET), 1)
Q=@
E=true
else
Q=@
E=echo
ifeq ($(V), 1)
Q=
E=true
endif
endif
ifndef CFLAGS
CFLAGS = -MMD -O2 -Wall -g
endif
include ../../src/build.rules
CFLAGS += -I../../src/utils
CFLAGS += -I../../src/common
@ -30,8 +8,17 @@ CFLAGS += -I../../src
ifndef CONFIG_NO_BROWSER
ifndef CONFIG_BROWSER_SYSTEM
TEST_WK := $(shell pkg-config --silence-errors --cflags webkitgtk-3.0)
ifeq ($(TEST_WK),)
# Try webkit2
GTKCFLAGS := $(shell pkg-config --cflags gtk+-3.0 webkit2gtk-4.0)
GTKLIBS := $(shell pkg-config --libs gtk+-3.0 webkit2gtk-4.0)
CFLAGS += -DUSE_WEBKIT2
else
GTKCFLAGS := $(shell pkg-config --cflags gtk+-3.0 webkitgtk-3.0)
GTKLIBS := $(shell pkg-config --libs gtk+-3.0 webkitgtk-3.0)
endif
CFLAGS += $(GTKCFLAGS)
LIBS += $(GTKLIBS)
endif
@ -84,23 +71,11 @@ CFLAGS += -DEAP_TLS_OPENSSL
OBJS += ../../src/crypto/tls_openssl_ocsp.o
LIBS += -lssl -lcrypto
_OBJS_VAR := OBJS
include ../../src/objs.mk
hs20-osu-client: $(OBJS)
$(Q)$(LDO) $(LDFLAGS) -o hs20-osu-client $(OBJS) $(LIBS)
@$(E) " LD " $@
%.o: %.c
$(Q)$(CC) -c -o $@ $(CFLAGS) $<
@$(E) " CC " $<
clean:
rm -f core *~ *.o *.d hs20-osu-client
rm -f ../../src/utils/*.o
rm -f ../../src/utils/*.d
rm -f ../../src/common/*.o
rm -f ../../src/common/*.d
rm -f ../../src/crypto/*.o
rm -f ../../src/crypto/*.d
rm -f ../../src/wps/*.o
rm -f ../../src/wps/*.d
-include $(OBJS:%.o=%.d)
clean: common-clean
rm -f core *~

View file

@ -158,7 +158,7 @@ int est_load_cacerts(struct hs20_osu_client *ctx, const char *url)
return -1;
}
pkcs7 = base64_decode((unsigned char *) resp, resp_len, &pkcs7_len);
pkcs7 = base64_decode(resp, resp_len, &pkcs7_len);
if (pkcs7 && pkcs7_len < resp_len / 2) {
wpa_printf(MSG_INFO, "Too short base64 decode (%u bytes; downloaded %u bytes) - assume this was binary",
(unsigned int) pkcs7_len, (unsigned int) resp_len);
@ -639,8 +639,7 @@ int est_build_csr(struct hs20_osu_client *ctx, const char *url)
return -1;
}
attrs = base64_decode((unsigned char *) resp, resp_len,
&attrs_len);
attrs = base64_decode(resp, resp_len, &attrs_len);
os_free(resp);
if (attrs == NULL) {
@ -734,7 +733,7 @@ int est_simple_enroll(struct hs20_osu_client *ctx, const char *url,
}
wpa_printf(MSG_DEBUG, "EST simpleenroll response: %s", resp);
pkcs7 = base64_decode((unsigned char *) resp, resp_len, &pkcs7_len);
pkcs7 = base64_decode(resp, resp_len, &pkcs7_len);
if (pkcs7 == NULL) {
wpa_printf(MSG_INFO, "EST workaround - Could not decode base64, assume this is DER encoded PKCS7");
pkcs7 = os_malloc(resp_len);

View file

@ -407,7 +407,7 @@ static int oma_dm_exec_browser(struct hs20_osu_client *ctx, xml_node_t *exec)
wpa_printf(MSG_INFO, "Data: %s", data);
wpa_printf(MSG_INFO, "Launch browser to URI '%s'", data);
write_summary(ctx, "Launch browser to URI '%s'", data);
res = hs20_web_browser(data);
res = hs20_web_browser(data, 1);
xml_node_get_text_free(ctx->xml, data);
if (res > 0) {
wpa_printf(MSG_INFO, "User response in browser completed successfully");

View file

@ -310,7 +310,7 @@ static int download_cert(struct hs20_osu_client *ctx, xml_node_t *params,
size_t len;
u8 digest1[SHA256_MAC_LEN], digest2[SHA256_MAC_LEN];
int res;
unsigned char *b64;
char *b64;
FILE *f;
url_node = get_node(ctx->xml, params, "CertURL");
@ -364,7 +364,7 @@ static int download_cert(struct hs20_osu_client *ctx, xml_node_t *params,
return -1;
}
b64 = base64_encode((unsigned char *) cert, len, NULL);
b64 = base64_encode(cert, len, NULL);
os_free(cert);
if (b64 == NULL)
return -1;
@ -2233,7 +2233,7 @@ static int osu_connect(struct hs20_osu_client *ctx, const char *bssid,
wpa_ctrl_close(mon);
if (res < 0) {
wpa_printf(MSG_INFO, "Could not connect");
wpa_printf(MSG_INFO, "Could not connect to OSU network");
write_summary(ctx, "Could not connect to OSU network");
wpa_printf(MSG_INFO, "Remove OSU network connection");
snprintf(buf, sizeof(buf), "REMOVE_NETWORK %d", id);
@ -2406,7 +2406,7 @@ static int cmd_osu_select(struct hs20_osu_client *ctx, const char *dir,
snprintf(fname, sizeof(fname), "file://%s/osu-providers.html", dir);
write_summary(ctx, "Start web browser with OSU provider selection page");
ret = hs20_web_browser(fname);
ret = hs20_web_browser(fname, 0);
selected:
if (ret > 0 && (size_t) ret <= osu_count) {
@ -2907,7 +2907,7 @@ static char * get_hostname(const char *url)
static int osu_cert_cb(void *_ctx, struct http_cert *cert)
{
struct hs20_osu_client *ctx = _ctx;
unsigned int i, j;
size_t i, j;
int found;
char *host = NULL;
@ -3002,7 +3002,7 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert)
size_t name_len = os_strlen(name);
wpa_printf(MSG_INFO,
"[%i] Looking for icon file name '%s' match",
"[%zu] Looking for icon file name '%s' match",
j, name);
for (i = 0; i < cert->num_logo; i++) {
struct http_logo *logo = &cert->logo[i];
@ -3010,7 +3010,7 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert)
char *pos;
wpa_printf(MSG_INFO,
"[%i] Comparing to '%s' uri_len=%d name_len=%d",
"[%zu] Comparing to '%s' uri_len=%d name_len=%d",
i, logo->uri, (int) uri_len, (int) name_len);
if (uri_len < 1 + name_len) {
wpa_printf(MSG_INFO, "URI Length is too short");
@ -3044,7 +3044,7 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert)
if (logo->hash_len != 32) {
wpa_printf(MSG_INFO,
"[%i][%i] Icon hash length invalid (should be 32): %d",
"[%zu][%zu] Icon hash length invalid (should be 32): %d",
j, i, (int) logo->hash_len);
continue;
}
@ -3054,7 +3054,7 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert)
}
wpa_printf(MSG_DEBUG,
"[%u][%u] Icon hash did not match", j, i);
"[%zu][%zu] Icon hash did not match", j, i);
wpa_hexdump_ascii(MSG_DEBUG, "logo->hash",
logo->hash, 32);
wpa_hexdump_ascii(MSG_DEBUG, "ctx->icon_hash[j]",
@ -3152,7 +3152,7 @@ static void check_workarounds(struct hs20_osu_client *ctx)
static void usage(void)
{
printf("usage: hs20-osu-client [-dddqqKt] [-S<station ifname>] \\\n"
printf("usage: hs20-osu-client [-dddqqKtT] [-S<station ifname>] \\\n"
" [-w<wpa_supplicant ctrl_iface dir>] "
"[-r<result file>] [-f<debug file>] \\\n"
" [-s<summary file>] \\\n"
@ -3198,7 +3198,7 @@ int main(int argc, char *argv[])
return -1;
for (;;) {
c = getopt(argc, argv, "df:hKNo:O:qr:s:S:tw:x:");
c = getopt(argc, argv, "df:hKNo:O:qr:s:S:tTw:x:");
if (c < 0)
break;
switch (c) {
@ -3236,6 +3236,9 @@ int main(int argc, char *argv[])
case 't':
wpa_debug_timestamp++;
break;
case 'T':
ctx.ignore_tls = 1;
break;
case 'w':
wpas_ctrl_path = optarg;
break;
@ -3403,7 +3406,7 @@ int main(int argc, char *argv[])
wpa_printf(MSG_INFO, "Launch web browser to URL %s",
argv[optind + 1]);
ret = hs20_web_browser(argv[optind + 1]);
ret = hs20_web_browser(argv[optind + 1], ctx.ignore_tls);
wpa_printf(MSG_INFO, "Web browser result: %d", ret);
} else if (strcmp(argv[optind], "parse_cert") == 0) {
if (argc - optind < 2) {

View file

@ -50,6 +50,8 @@ struct hs20_osu_client {
const char *osu_ssid; /* Enforced OSU_SSID for testing purposes */
#define WORKAROUND_OCSP_OPTIONAL 0x00000001
unsigned long int workarounds;
int ignore_tls; /* whether to ignore TLS validation issues with HTTPS
* server certificate */
};

View file

@ -547,7 +547,7 @@ static int hs20_spp_exec(struct hs20_osu_client *ctx, xml_node_t *exec,
}
wpa_printf(MSG_INFO, "Launch browser to URI '%s'", uri);
write_summary(ctx, "Launch browser to URI '%s'", uri);
res = hs20_web_browser(uri);
res = hs20_web_browser(uri, 1);
xml_node_get_text_free(ctx->xml, uri);
if (res > 0) {
wpa_printf(MSG_INFO, "User response in browser completed successfully - sessionid='%s'",

1
hs20/server/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
hs20_spp_server

42
hs20/server/Makefile Normal file
View file

@ -0,0 +1,42 @@
ALL=hs20_spp_server
include ../../src/build.rules
CFLAGS += -I../../src
CFLAGS += -I../../src/utils
CFLAGS += -I../../src/crypto
LIBS += -lsqlite3
# Using glibc < 2.17 requires -lrt for clock_gettime()
LIBS += -lrt
ifndef CONFIG_NO_GITVER
# Add VERSION_STR postfix for builds from a git repository
ifeq ($(wildcard ../../.git),../../.git)
GITVER := $(shell git describe --dirty=+)
ifneq ($(GITVER),)
CFLAGS += -DGIT_VERSION_STR_POSTFIX=\"-$(GITVER)\"
endif
endif
endif
OBJS=spp_server.o
OBJS += hs20_spp_server.o
OBJS += ../../src/utils/xml-utils.o
OBJS += ../../src/utils/base64.o
OBJS += ../../src/utils/common.o
OBJS += ../../src/utils/os_unix.o
OBJS += ../../src/utils/wpa_debug.o
OBJS += ../../src/crypto/md5-internal.o
CFLAGS += $(shell xml2-config --cflags)
LIBS += $(shell xml2-config --libs)
OBJS += ../../src/utils/xml_libxml2.o
_OBJS_VAR := OBJS
include ../../src/objs.mk
hs20_spp_server: $(OBJS)
$(LDO) $(LDFLAGS) -o hs20_spp_server $(OBJS) $(LIBS)
clean: common-clean
rm -f core *~

13
hs20/server/ca/clean.sh Executable file
View file

@ -0,0 +1,13 @@
#!/bin/sh
for i in server-client server server-revoked user ocsp; do
rm -f $i.csr $i.key $i.pem
done
rm -f openssl.cnf.tmp
if [ -d demoCA ]; then
rm -r demoCA
fi
rm -f ca.pem logo.asn1 logo.der server.der ocsp-server-cache.der
rm -f my-openssl.cnf my-openssl-root.cnf
#rm -r rootCA

View file

@ -0,0 +1,17 @@
asn1 = SEQUENCE:attrs
[attrs]
#oid1 = OID:challengePassword
attr1 = SEQUENCE:extreq
oid2 = OID:sha256WithRSAEncryption
[extreq]
oid = OID:extensionRequest
vals = SET:extreqvals
[extreqvals]
oid1 = OID:macAddress
#oid2 = OID:imei
#oid3 = OID:meid
#oid4 = OID:DevId

4
hs20/server/ca/est-csrattrs.sh Executable file
View file

@ -0,0 +1,4 @@
#!/bin/sh
openssl asn1parse -genconf est-csrattrs.cnf -out est-csrattrs.der -oid hs20.oid
base64 est-csrattrs.der > est-attrs.b64

7
hs20/server/ca/hs20.oid Normal file
View file

@ -0,0 +1,7 @@
1.3.6.1.1.1.1.22 macAddress
1.2.840.113549.1.9.14 extensionRequest
1.3.6.1.4.1.40808.1.1.1 id-wfa-hotspot-friendlyName
1.3.6.1.4.1.40808.1.1.2 id-kp-HS2.0Auth
1.3.6.1.4.1.40808.1.1.3 imei
1.3.6.1.4.1.40808.1.1.4 meid
1.3.6.1.4.1.40808.1.1.5 DevId

11
hs20/server/ca/ocsp-req.sh Executable file
View file

@ -0,0 +1,11 @@
#!/bin/sh
for i in *.pem; do
echo "===[ $i ]==================="
openssl ocsp -text -CAfile ca.pem -verify_other demoCA/cacert.pem -trust_other -issuer demoCA/cacert.pem -cert $i -url http://localhost:8888/
# openssl ocsp -text -CAfile rootCA/cacert.pem -issuer demoCA/cacert.pem -cert $i -url http://localhost:8888/
# openssl ocsp -text -CAfile rootCA/cacert.pem -verify_other demoCA/cacert.pem -trust_other -issuer demoCA/cacert.pem -cert $i -url http://localhost:8888/
# openssl ocsp -text -CAfile rootCA/cacert.pem -VAfile ca.pem -trust_other -issuer demoCA/cacert.pem -cert $i -url http://localhost:8888/
done

View file

@ -0,0 +1,3 @@
#!/bin/sh
openssl ocsp -index demoCA/index.txt -port 8888 -nmin 5 -rsigner demoCA/cacert.pem -rkey demoCA/private/cakey-plain.pem -CA demoCA/cacert.pem -resp_no_certs -text

View file

@ -0,0 +1,3 @@
#!/bin/sh
openssl ocsp -index demoCA/index.txt -port 8888 -nmin 5 -rsigner ocsp.pem -rkey ocsp.key -CA demoCA/cacert.pem -text -ignore_err

View file

@ -0,0 +1,11 @@
#!/bin/sh
# NOTE: You may need to replace 'localhost' with your OCSP server hostname.
openssl ocsp \
-no_nonce \
-CAfile ca.pem \
-verify_other demoCA/cacert.pem \
-issuer demoCA/cacert.pem \
-cert server.pem \
-url http://localhost:8888/ \
-respout ocsp-server-cache.der

View file

@ -0,0 +1,125 @@
# OpenSSL configuration file for Hotspot 2.0 PKI (Root CA)
HOME = .
RANDFILE = $ENV::HOME/.rnd
oid_section = new_oids
[ new_oids ]
#logotypeoid=1.3.6.1.5.5.7.1.12
####################################################################
[ ca ]
default_ca = CA_default # The default ca section
####################################################################
[ CA_default ]
dir = ./rootCA # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.
#unique_subject = no # Set to 'no' to allow creation of
# several certificates with same subject
new_certs_dir = $dir/newcerts # default place for new certs.
certificate = $dir/cacert.pem # The CA certificate
serial = $dir/serial # The current serial number
crlnumber = $dir/crlnumber # the current crl number
# must be commented out to leave a V1 CRL
crl = $dir/crl.pem # The current CRL
private_key = $dir/private/cakey.pem# The private key
RANDFILE = $dir/private/.rand # private random number file
x509_extensions = usr_cert # The extentions to add to the cert
name_opt = ca_default # Subject Name options
cert_opt = ca_default # Certificate field options
default_days = 365 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = default # use public key default MD
preserve = no # keep passed DN ordering
policy = policy_match
# For the CA policy
[ policy_match ]
countryName = match
stateOrProvinceName = optional
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
####################################################################
[ req ]
default_bits = 2048
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca # The extentions to add to the self signed cert
input_password = @PASSWORD@
output_password = @PASSWORD@
string_mask = utf8only
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = US
countryName_min = 2
countryName_max = 2
localityName = Locality Name (eg, city)
localityName_default = Tuusula
0.organizationName = Organization Name (eg, company)
0.organizationName_default = WFA Hotspot 2.0
##organizationalUnitName = Organizational Unit Name (eg, section)
#organizationalUnitName_default =
#@OU@
commonName = Common Name (e.g. server FQDN or YOUR name)
#@CN@
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 64
[ req_attributes ]
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName=DNS:example.com,DNS:another.example.com
[ v3_ca ]
# Hotspot 2.0 PKI requirements
subjectKeyIdentifier=hash
basicConstraints = critical,CA:true
keyUsage = critical, cRLSign, keyCertSign
[ crl_ext ]
# issuerAltName=issuer:copy
authorityKeyIdentifier=keyid:always
[ v3_OCSP ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = OCSPSigning

200
hs20/server/ca/openssl.cnf Normal file
View file

@ -0,0 +1,200 @@
# OpenSSL configuration file for Hotspot 2.0 PKI (Intermediate CA)
HOME = .
RANDFILE = $ENV::HOME/.rnd
oid_section = new_oids
[ new_oids ]
#logotypeoid=1.3.6.1.5.5.7.1.12
####################################################################
[ ca ]
default_ca = CA_default # The default ca section
####################################################################
[ CA_default ]
dir = ./demoCA # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.
#unique_subject = no # Set to 'no' to allow creation of
# several certificates with same subject
new_certs_dir = $dir/newcerts # default place for new certs.
certificate = $dir/cacert.pem # The CA certificate
serial = $dir/serial # The current serial number
crlnumber = $dir/crlnumber # the current crl number
# must be commented out to leave a V1 CRL
crl = $dir/crl.pem # The current CRL
private_key = $dir/private/cakey.pem# The private key
RANDFILE = $dir/private/.rand # private random number file
x509_extensions = ext_client # The extentions to add to the cert
name_opt = ca_default # Subject Name options
cert_opt = ca_default # Certificate field options
# Extension copying option: use with caution.
copy_extensions = copy
default_days = 365 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = default # use public key default MD
preserve = no # keep passed DN ordering
policy = policy_match
# For the CA policy
[ policy_match ]
countryName = supplied
stateOrProvinceName = optional
organizationName = supplied
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_osu_server ]
countryName = match
stateOrProvinceName = optional
organizationName = match
organizationalUnitName = supplied
commonName = supplied
emailAddress = optional
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
####################################################################
[ req ]
default_bits = 2048
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca # The extentions to add to the self signed cert
input_password = @PASSWORD@
output_password = @PASSWORD@
string_mask = utf8only
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = FI
countryName_min = 2
countryName_max = 2
localityName = Locality Name (eg, city)
localityName_default = Tuusula
0.organizationName = Organization Name (eg, company)
0.organizationName_default = @DOMAIN@
##organizationalUnitName = Organizational Unit Name (eg, section)
#organizationalUnitName_default =
#@OU@
commonName = Common Name (e.g. server FQDN or YOUR name)
#@CN@
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 64
[ req_attributes ]
[ v3_ca ]
# Hotspot 2.0 PKI requirements
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, cRLSign, keyCertSign
authorityInfoAccess = OCSP;URI:@OCSP_URI@
# For SP intermediate CA
#subjectAltName=critical,otherName:1.3.6.1.4.1.40808.1.1.1;UTF8String:engExample OSU
#nameConstraints=permitted;DNS:.@DOMAIN@
#1.3.6.1.5.5.7.1.12=ASN1:SEQUENCE:LogotypeExtn
[ v3_osu_server ]
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, keyEncipherment
#@ALTNAME@
#logotypeoid=ASN1:SEQUENCE:LogotypeExtn
1.3.6.1.5.5.7.1.12=ASN1:SEQUENCE:LogotypeExtn
[LogotypeExtn]
communityLogos=EXP:0,SEQUENCE:LogotypeInfo
[LogotypeInfo]
# note: implicit tag converted to explicit for CHOICE
direct=EXP:0,SEQUENCE:LogotypeData
[LogotypeData]
image=SEQUENCE:LogotypeImage
[LogotypeImage]
imageDetails=SEQUENCE:LogotypeDetails
imageInfo=SEQUENCE:LogotypeImageInfo
[LogotypeDetails]
mediaType=IA5STRING:image/png
logotypeHash=SEQUENCE:HashAlgAndValues
logotypeURI=SEQUENCE:URI
[HashAlgAndValues]
value1=SEQUENCE:HashAlgAndValueSHA256
#value2=SEQUENCE:HashAlgAndValueSHA1
[HashAlgAndValueSHA256]
hashAlg=SEQUENCE:sha256_alg
hashValue=FORMAT:HEX,OCTETSTRING:@LOGO_HASH256@
[HashAlgAndValueSHA1]
hashAlg=SEQUENCE:sha1_alg
hashValue=FORMAT:HEX,OCTETSTRING:@LOGO_HASH1@
[sha256_alg]
algorithm=OID:sha256
[sha1_alg]
algorithm=OID:sha1
[URI]
uri=IA5STRING:@LOGO_URI@
[LogotypeImageInfo]
# default value color(1), component optional
#type=IMP:0,INTEGER:1
fileSize=INTEGER:7549
xSize=INTEGER:128
ySize=INTEGER:80
language=IMP:4,IA5STRING:zxx
[ crl_ext ]
# issuerAltName=issuer:copy
authorityKeyIdentifier=keyid:always
[ v3_OCSP ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = OCSPSigning
[ ext_client ]
basicConstraints=CA:FALSE
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
authorityInfoAccess = OCSP;URI:@OCSP_URI@
#@ALTNAME@
extendedKeyUsage = clientAuth
[ ext_server ]
# Hotspot 2.0 PKI requirements
basicConstraints=critical, CA:FALSE
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
authorityInfoAccess = OCSP;URI:@OCSP_URI@
#@ALTNAME@
extendedKeyUsage = critical, serverAuth
keyUsage = critical, keyEncipherment

209
hs20/server/ca/setup.sh Executable file
View file

@ -0,0 +1,209 @@
#!/bin/sh
if [ -z "$OPENSSL" ]; then
OPENSSL=openssl
fi
export OPENSSL_CONF=$PWD/openssl.cnf
PASS=whatever
if [ -z "$DOMAIN" ]; then
DOMAIN=w1.fi
fi
COMPANY=w1.fi
OPER_ENG="engw1.fi TESTING USE"
OPER_FI="finw1.fi TESTIKÄYTTÖ"
CNR="Hotspot 2.0 Trust Root CA - 99"
CNO="ocsp.$DOMAIN"
CNV="osu-revoked.$DOMAIN"
CNOC="osu-client.$DOMAIN"
OSU_SERVER_HOSTNAME="osu.$DOMAIN"
DEBUG=0
OCSP_URI="http://$CNO:8888/"
LOGO_URI="http://osu.w1.fi/w1fi_logo.png"
LOGO_HASH256="4532f7ec36424381617c03c6ce87b55a51d6e7177ffafda243cebf280a68954d"
LOGO_HASH1="5e1d5085676eede6b02da14d31c523ec20ffba0b"
# Command line overrides
USAGE=$( cat <<EOF
Usage:\n
# -c: Company name, used to generate Subject name CN for Intermediate CA\n
# -C: Subject name CN of the Root CA ($CNR)\n
# -D: Enable debugging (set -x, etc)\n
# -g: Logo sha1 hash ($LOGO_HASH1)\n
# -G: Logo sha256 hash ($LOGO_HASH256)\n
# -h: Show this help message\n
# -l: Logo URI ($LOGO_URI)\n
# -m: Domain ($DOMAIN)\n
# -o: Subject name CN for OSU-Client Server ($CNOC)\n
# -O: Subject name CN for OCSP Server ($CNO)\n
# -p: passphrase for private keys ($PASS)\n
# -r: Operator-english ($OPER_ENG)\n
# -R: Operator-finish ($OPER_FI)\n
# -S: OSU Server name ($OSU_SERVER_HOSTNAME)\n
# -u: OCSP-URI ($OCSP_URI)\n
# -V: Subject name CN for OSU-Revoked Server ($CNV)\n
EOF
)
while getopts "c:C:Dg:G:l:m:o:O:p:r:R:S:u:V:h" flag
do
case $flag in
c) COMPANY=$OPTARG;;
C) CNR=$OPTARG;;
D) DEBUG=1;;
g) LOGO_HASH1=$OPTARG;;
G) LOGO_HASH256=$OPTARG;;
h) echo -e $USAGE; exit 0;;
l) LOGO_URI=$OPTARG;;
m) DOMAIN=$OPTARG;;
o) CNOC=$OPTARG;;
O) CNO=$OPTARG;;
p) PASS=$OPTARG;;
r) OPER_ENG=$OPTARG;;
R) OPER_FI=$OPTARG;;
S) OSU_SERVER_HOSTNAME=$OPTARG;;
u) OCSP_URI=$OPTARG;;
V) CNV=$OPTARG;;
*) echo "Unknown flag: $flag"; echo -e $USAGE; exit 1;;
esac
done
fail()
{
echo "$*"
exit 1
}
echo
echo "---[ Root CA ]----------------------------------------------------------"
echo
if [ $DEBUG = 1 ]
then
set -x
fi
# Set the passphrase and some other common config accordingly.
cat openssl-root.cnf | sed "s/@PASSWORD@/$PASS/" \
> my-openssl-root.cnf
cat openssl.cnf | sed "s/@PASSWORD@/$PASS/" |
sed "s,@OCSP_URI@,$OCSP_URI," |
sed "s,@LOGO_URI@,$LOGO_URI," |
sed "s,@LOGO_HASH1@,$LOGO_HASH1," |
sed "s,@LOGO_HASH256@,$LOGO_HASH256," |
sed "s/@DOMAIN@/$DOMAIN/" \
> my-openssl.cnf
cat my-openssl-root.cnf | sed "s/#@CN@/commonName_default = $CNR/" > openssl.cnf.tmp
mkdir -p rootCA/certs rootCA/crl rootCA/newcerts rootCA/private
touch rootCA/index.txt
if [ -e rootCA/private/cakey.pem ]; then
echo " * Use existing Root CA"
else
echo " * Generate Root CA private key"
$OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:4096 -keyout rootCA/private/cakey.pem -out rootCA/careq.pem || fail "Failed to generate Root CA private key"
echo " * Sign Root CA certificate"
$OPENSSL ca -config openssl.cnf.tmp -md sha256 -create_serial -out rootCA/cacert.pem -days 10957 -batch -keyfile rootCA/private/cakey.pem -passin pass:$PASS -selfsign -extensions v3_ca -outdir rootCA/newcerts -infiles rootCA/careq.pem || fail "Failed to sign Root CA certificate"
$OPENSSL x509 -in rootCA/cacert.pem -out rootCA/cacert.der -outform DER || fail "Failed to create rootCA DER"
sha256sum rootCA/cacert.der > rootCA/cacert.fingerprint || fail "Failed to create rootCA fingerprint"
fi
if [ ! -e rootCA/crlnumber ]; then
echo 00 > rootCA/crlnumber
fi
echo
echo "---[ Intermediate CA ]--------------------------------------------------"
echo
cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $COMPANY Hotspot 2.0 Intermediate CA/" > openssl.cnf.tmp
mkdir -p demoCA/certs demoCA/crl demoCA/newcerts demoCA/private
touch demoCA/index.txt
if [ -e demoCA/private/cakey.pem ]; then
echo " * Use existing Intermediate CA"
else
echo " * Generate Intermediate CA private key"
$OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -keyout demoCA/private/cakey.pem -out demoCA/careq.pem || fail "Failed to generate Intermediate CA private key"
echo " * Sign Intermediate CA certificate"
$OPENSSL ca -config openssl.cnf.tmp -md sha256 -create_serial -out demoCA/cacert.pem -days 3652 -batch -keyfile rootCA/private/cakey.pem -cert rootCA/cacert.pem -passin pass:$PASS -extensions v3_ca -infiles demoCA/careq.pem || fail "Failed to sign Intermediate CA certificate"
# horrible from security view point, but for testing purposes since OCSP responder does not seem to support -passin
openssl rsa -in demoCA/private/cakey.pem -out demoCA/private/cakey-plain.pem -passin pass:$PASS
$OPENSSL x509 -in demoCA/cacert.pem -out demoCA/cacert.der -outform DER || fail "Failed to create demoCA DER."
sha256sum demoCA/cacert.der > demoCA/cacert.fingerprint || fail "Failed to create demoCA fingerprint"
fi
if [ ! -e demoCA/crlnumber ]; then
echo 00 > demoCA/crlnumber
fi
echo
echo "OCSP responder"
echo
cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $CNO/" > openssl.cnf.tmp
$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out ocsp.csr -keyout ocsp.key -extensions v3_OCSP
$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -keyfile demoCA/private/cakey.pem -passin pass:$PASS -in ocsp.csr -out ocsp.pem -days 730 -extensions v3_OCSP || fail "Could not generate ocsp.pem"
echo
echo "---[ Server - to be revoked ] ------------------------------------------"
echo
cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $CNV/" > openssl.cnf.tmp
$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out server-revoked.csr -keyout server-revoked.key
$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in server-revoked.csr -out server-revoked.pem -key $PASS -days 730 -extensions ext_server
$OPENSSL ca -revoke server-revoked.pem -key $PASS
echo
echo "---[ Server - with client ext key use ] ---------------------------------"
echo "---[ Only used for negative-testing for OSU-client implementation ] -----"
echo
cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $CNOC/" > openssl.cnf.tmp
$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out server-client.csr -keyout server-client.key || fail "Could not create server-client.key"
$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in server-client.csr -out server-client.pem -key $PASS -days 730 -extensions ext_client || fail "Could not create server-client.pem"
echo
echo "---[ User ]-------------------------------------------------------------"
echo
cat my-openssl.cnf | sed "s/#@CN@/commonName_default = User/" > openssl.cnf.tmp
$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out user.csr -keyout user.key || fail "Could not create user.key"
$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in user.csr -out user.pem -key $PASS -days 730 -extensions ext_client || fail "Could not create user.pem"
echo
echo "---[ Server ]-----------------------------------------------------------"
echo
ALT="DNS:$OSU_SERVER_HOSTNAME"
ALT="$ALT,otherName:1.3.6.1.4.1.40808.1.1.1;UTF8String:$OPER_ENG"
ALT="$ALT,otherName:1.3.6.1.4.1.40808.1.1.1;UTF8String:$OPER_FI"
cat my-openssl.cnf |
sed "s/#@CN@/commonName_default = $OSU_SERVER_HOSTNAME/" |
sed "s/^##organizationalUnitName/organizationalUnitName/" |
sed "s/#@OU@/organizationalUnitName_default = Hotspot 2.0 Online Sign Up Server/" |
sed "s/#@ALTNAME@/subjectAltName=critical,$ALT/" \
> openssl.cnf.tmp
echo $OPENSSL req -config $PWD/openssl.cnf.tmp -batch -sha256 -new -newkey rsa:2048 -nodes -out server.csr -keyout server.key -reqexts v3_osu_server
$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -sha256 -new -newkey rsa:2048 -nodes -out server.csr -keyout server.key -reqexts v3_osu_server || fail "Failed to generate server request"
$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in server.csr -out server.pem -key $PASS -days 730 -extensions ext_server -policy policy_osu_server || fail "Failed to sign server certificate"
#dump logotype details for debugging
$OPENSSL x509 -in server.pem -out server.der -outform DER
openssl asn1parse -in server.der -inform DER | grep HEX | tail -1 | sed 's/.*://' | xxd -r -p > logo.der
openssl asn1parse -in logo.der -inform DER > logo.asn1
echo
echo "---[ CRL ]---------------------------------------------------------------"
echo
$OPENSSL ca -config $PWD/my-openssl.cnf -gencrl -md sha256 -out demoCA/crl/crl.pem -passin pass:$PASS
echo
echo "---[ Verify ]------------------------------------------------------------"
echo
$OPENSSL verify -CAfile rootCA/cacert.pem demoCA/cacert.pem
$OPENSSL verify -CAfile rootCA/cacert.pem -untrusted demoCA/cacert.pem *.pem
cat rootCA/cacert.pem demoCA/cacert.pem > ca.pem

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

View file

@ -0,0 +1,262 @@
Hotspot 2.0 OSU server
======================
The information in this document is based on the assumption that Ubuntu
16.04 server (64-bit) distribution is used and the web server is
Apache2. Neither of these are requirements for the installation, but if
other combinations are used, the package names and configuration
parameters may need to be adjusted.
NOTE: This implementation and the example configuration here is meant
only for testing purposes in a lab environment. This design is not
secure to be installed in a publicly available Internet server without
considerable amount of modification and review for security issues.
Build dependencies
------------------
Ubuntu 16.04 server
- default installation
- upgraded to latest package versions
sudo apt-get update
sudo apt-get upgrade
Packages needed for running the service:
sudo apt-get install sqlite3
sudo apt-get install apache2
sudo apt-get install php-sqlite3 php-xml libapache2-mod-php
Additional packages needed for building the components:
sudo apt-get install build-essential
sudo apt-get install libsqlite3-dev
sudo apt-get install libssl-dev
sudo apt-get install libxml2-dev
Installation location
---------------------
Select a location for the installation root directory. The example here
assumes /home/user/hs20-server to be used, but this can be changed by
editing couple of files as indicated below.
sudo mkdir -p /home/user/hs20-server
sudo chown $USER /home/user/hs20-server
mkdir -p /home/user/hs20-server/spp
mkdir -p /home/user/hs20-server/AS
Build
-----
# hostapd as RADIUS server
cd hostapd
#example build configuration
cat > .config <<EOF
CONFIG_DRIVER_NONE=y
CONFIG_PKCS12=y
CONFIG_RADIUS_SERVER=y
CONFIG_EAP=y
CONFIG_EAP_TLS=y
CONFIG_EAP_MSCHAPV2=y
CONFIG_EAP_PEAP=y
CONFIG_EAP_GTC=y
CONFIG_EAP_TTLS=y
CONFIG_EAP_SIM=y
CONFIG_EAP_AKA=y
CONFIG_EAP_AKA_PRIME=y
CONFIG_SQLITE=y
CONFIG_HS20=y
EOF
make hostapd hlr_auc_gw
cp hostapd hlr_auc_gw /home/user/hs20-server/AS
# build hs20_spp_server
cd ../hs20/server
make clean
make
cp hs20_spp_server /home/user/hs20-server/spp
# prepare database (web server user/group needs to have write access)
mkdir -p /home/user/hs20-server/AS/DB
sudo chgrp www-data /home/user/hs20-server/AS/DB
sudo chmod g+w /home/user/hs20-server/AS/DB
sqlite3 /home/user/hs20-server/AS/DB/eap_user.db < sql.txt
sudo chgrp www-data /home/user/hs20-server/AS/DB/eap_user.db
sudo chmod g+w /home/user/hs20-server/AS/DB/eap_user.db
# add example configuration (note: need to update URLs to match the system)
sqlite3 /home/user/hs20-server/AS/DB/eap_user.db < sql-example.txt
# copy PHP scripts
# Modify config.php if different installation directory is used.
# Modify PHP scripts to get the desired behavior for user interaction (or use
# the examples as-is for initial testing).
cp -r www /home/user/hs20-server
# Create /home/user/hs20-server/terms-and-conditions file (HTML segment to be
# inserted within the BODY section of the page).
cat > /home/user/hs20-server/terms-and-conditions <<EOF
<P>Terms and conditions..</P>
EOF
# Build local keys and certs
cd ca
# Display help options.
./setup.sh -h
# Remove old keys, fill in appropriate values, and generate your keys.
# For instance:
./clean.sh
rm -fr rootCA"
old_hostname=myserver.local
./setup.sh -C "Hotspot 2.0 Trust Root CA - CT" \
-o $old_hostname-osu-client \
-O $old_hostname-oscp -p lanforge -S $old_hostname \
-V $old_hostname-osu-revoked \
-m local -u http://$old_hostname:8888/
# Configure subscription policies
mkdir -p /home/user/hs20-server/spp/policy
cat > /home/user/hs20-server/spp/policy/default.xml <<EOF
<Policy>
<PolicyUpdate>
<UpdateInterval>30</UpdateInterval>
<UpdateMethod>ClientInitiated</UpdateMethod>
<Restriction>Unrestricted</Restriction>
<URI>https://policy-server.osu.example.com/hs20/spp.php</URI>
</PolicyUpdate>
</Policy>
EOF
# Install Hotspot 2.0 SPP and OMA DM XML schema/DTD files
# XML schema for SPP
# Copy the latest XML schema into /home/user/hs20-server/spp/spp.xsd
# OMA DM Device Description Framework DTD
# Copy into /home/user/hs20-server/spp/dm_ddf-v1_2.dtd
# http://www.openmobilealliance.org/tech/DTD/dm_ddf-v1_2.dtd
# Configure RADIUS authentication service
# Note: Change the URL to match the setup
# Note: Install AAA server key/certificate and root CA in Key directory
cat > /home/user/hs20-server/AS/as-sql.conf <<EOF
driver=none
radius_server_clients=as.radius_clients
eap_server=1
eap_user_file=sqlite:DB/eap_user.db
ca_cert=Key/ca.pem
server_cert=Key/server.pem
private_key=Key/server.key
private_key_passwd=passphrase
eap_sim_db=unix:/tmp/hlr_auc_gw.sock db=eap_sim.db
subscr_remediation_url=https://subscription-server.osu.example.com/hs20/spp.php
EOF
# Set RADIUS passphrase for the APs
# Note: Modify to match the setup
cat > /home/user/hs20-server/AS/as.radius_clients <<EOF
0.0.0.0/0 radius
EOF
Start RADIUS authentication server
----------------------------------
cd /home/user/hs20-server/AS
./hostapd -B as-sql.conf
OSEN RADIUS server configuration notes
The OSEN RADIUS server config file should have the 'ocsp_stapling_response'
configuration in it. For example:
# hostapd-radius config for the radius used by the OSEN AP
interface=eth0#0
driver=none
logger_syslog=-1
logger_syslog_level=2
logger_stdout=-1
logger_stdout_level=2
ctrl_interface=/var/run/hostapd
ctrl_interface_group=0
eap_server=1
eap_user_file=/home/user/hs20-server/AS/hostapd-osen.eap_user
server_id=ben-ota-2-osen
radius_server_auth_port=1811
radius_server_clients=/home/user/hs20-server/AS/hostap.radius_clients
ca_cert=/home/user/hs20-server/ca/ca.pem
server_cert=/home/user/hs20-server/ca/server.pem
private_key=/home/user/hs20-server/ca/server.key
private_key_passwd=whatever
ocsp_stapling_response=/home/user/hs20-server/ca/ocsp-server-cache.der
The /home/user/hs20-server/AS/hostapd-osen.eap_user file should look
similar to this, and should coorelate with the osu_nai entry in
the non-OSEN VAP config file. For instance:
# cat hostapd-osen.eap_user
# For OSEN authentication (Hotspot 2.0 Release 2)
"osen@w1.fi" WFA-UNAUTH-TLS
# Run OCSP server:
cd /home/user/hs20-server/ca
./ocsp-responder.sh&
# Update cache (This should be run periodically)
./ocsp-update-cache.sh
Configure web server
--------------------
Edit /etc/apache2/sites-available/default-ssl
Add following block just before "SSL Engine Switch" line":
Alias /hs20/ "/home/user/hs20-server/www/"
<Directory "/home/user/hs20-server/www/">
Options Indexes MultiViews FollowSymLinks
AllowOverride None
Require all granted
SSLOptions +StdEnvVars
</Directory>
Update SSL configuration to use the OSU server certificate/key.
They keys and certs are called 'server.key' and 'server.pem' from
ca/setup.sh.
To support subscription remediation using client certificates, set
"SSLVerifyClient optional" and configure the trust root CA(s) for the
client certificates with SSLCACertificateFile.
Enable default-ssl site and restart Apache2:
sudo a2ensite default-ssl
sudo a2enmod ssl
sudo service apache2 restart
Management UI
-------------
The sample PHP scripts include a management UI for testing
purposes. That is available at https://<server>/hs20/users.php
AP configuration
----------------
APs can now be configured to use the OSU server as the RADIUS
authentication server. In addition, the OSU Provider List ANQP element
should be configured to use the SPP (SOAP+XML) option and with the
following Server URL:
https://<server>/hs20/spp.php/signup?realm=example.com

View file

@ -0,0 +1,207 @@
/*
* Hotspot 2.0 SPP server - standalone version
* Copyright (c) 2012-2013, Qualcomm Atheros, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include <time.h>
#include <sqlite3.h>
#include "common.h"
#include "common/version.h"
#include "xml-utils.h"
#include "spp_server.h"
static void write_timestamp(FILE *f)
{
time_t t;
struct tm *tm;
time(&t);
tm = localtime(&t);
fprintf(f, "%04u-%02u-%02u %02u:%02u:%02u ",
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
}
void debug_print(struct hs20_svc *ctx, int print, const char *fmt, ...)
{
va_list ap;
if (ctx->debug_log == NULL)
return;
write_timestamp(ctx->debug_log);
va_start(ap, fmt);
vfprintf(ctx->debug_log, fmt, ap);
va_end(ap);
fprintf(ctx->debug_log, "\n");
}
void debug_dump_node(struct hs20_svc *ctx, const char *title, xml_node_t *node)
{
char *str;
if (ctx->debug_log == NULL)
return;
str = xml_node_to_str(ctx->xml, node);
if (str == NULL)
return;
write_timestamp(ctx->debug_log);
fprintf(ctx->debug_log, "%s: '%s'\n", title, str);
os_free(str);
}
static int process(struct hs20_svc *ctx)
{
int dmacc = 0;
xml_node_t *soap, *spp, *resp;
char *user, *realm, *post, *str;
ctx->addr = getenv("HS20ADDR");
if (ctx->addr)
debug_print(ctx, 1, "Connection from %s", ctx->addr);
ctx->test = getenv("HS20TEST");
if (ctx->test)
debug_print(ctx, 1, "Requested test functionality: %s",
ctx->test);
user = getenv("HS20USER");
if (user && strlen(user) == 0)
user = NULL;
realm = getenv("HS20REALM");
if (realm == NULL) {
debug_print(ctx, 1, "HS20REALM not set");
return -1;
}
post = getenv("HS20POST");
if (post == NULL) {
debug_print(ctx, 1, "HS20POST not set");
return -1;
}
ctx->imsi = getenv("HS20IMSI");
if (ctx->imsi)
debug_print(ctx, 1, "IMSI %s", ctx->imsi);
ctx->eap_method = getenv("HS20EAPMETHOD");
if (ctx->eap_method)
debug_print(ctx, 1, "EAP method %s", ctx->eap_method);
ctx->id_hash = getenv("HS20IDHASH");
if (ctx->id_hash)
debug_print(ctx, 1, "ID-HASH %s", ctx->id_hash);
soap = xml_node_from_buf(ctx->xml, post);
if (soap == NULL) {
debug_print(ctx, 1, "Could not parse SOAP data");
return -1;
}
debug_dump_node(ctx, "Received SOAP message", soap);
spp = soap_get_body(ctx->xml, soap);
if (spp == NULL) {
debug_print(ctx, 1, "Could not get SPP message");
xml_node_free(ctx->xml, soap);
return -1;
}
debug_dump_node(ctx, "Received SPP message", spp);
resp = hs20_spp_server_process(ctx, spp, user, realm, dmacc);
xml_node_free(ctx->xml, soap);
if (resp == NULL && user == NULL) {
debug_print(ctx, 1, "Request HTTP authentication");
return 2; /* Request authentication */
}
if (resp == NULL) {
debug_print(ctx, 1, "No response");
return -1;
}
soap = soap_build_envelope(ctx->xml, resp);
if (soap == NULL) {
debug_print(ctx, 1, "SOAP envelope building failed");
return -1;
}
str = xml_node_to_str(ctx->xml, soap);
xml_node_free(ctx->xml, soap);
if (str == NULL) {
debug_print(ctx, 1, "Could not get node string");
return -1;
}
printf("%s", str);
free(str);
return 0;
}
static void usage(void)
{
printf("usage:\n"
"hs20_spp_server -r<root directory> [-f<debug log>]\n");
}
int main(int argc, char *argv[])
{
struct hs20_svc ctx;
int ret;
os_memset(&ctx, 0, sizeof(ctx));
for (;;) {
int c = getopt(argc, argv, "f:r:v");
if (c < 0)
break;
switch (c) {
case 'f':
if (ctx.debug_log)
break;
ctx.debug_log = fopen(optarg, "a");
if (ctx.debug_log == NULL) {
printf("Could not write to %s\n", optarg);
return -1;
}
break;
case 'r':
ctx.root_dir = optarg;
break;
case 'v':
printf("hs20_spp_server v%s\n", VERSION_STR);
return 0;
default:
usage();
return -1;
}
}
if (ctx.root_dir == NULL) {
usage();
return -1;
}
ctx.xml = xml_node_init_ctx(&ctx, NULL);
if (ctx.xml == NULL)
return -1;
if (hs20_spp_server_init(&ctx) < 0) {
xml_node_deinit_ctx(ctx.xml);
return -1;
}
ret = process(&ctx);
debug_print(&ctx, 1, "process() --> %d", ret);
xml_node_deinit_ctx(ctx.xml);
hs20_spp_server_deinit(&ctx);
if (ctx.debug_log)
fclose(ctx.debug_log);
return ret;
}

2933
hs20/server/spp_server.c Normal file

File diff suppressed because it is too large Load diff

36
hs20/server/spp_server.h Normal file
View file

@ -0,0 +1,36 @@
/*
* Hotspot 2.0 SPP server
* Copyright (c) 2012-2013, Qualcomm Atheros, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef SPP_SERVER_H
#define SPP_SERVER_H
struct hs20_svc {
const void *ctx;
struct xml_node_ctx *xml;
char *root_dir;
FILE *debug_log;
sqlite3 *db;
const char *addr;
const char *test;
const char *imsi;
const char *eap_method;
const char *id_hash;
};
void debug_print(struct hs20_svc *ctx, int print, const char *fmt, ...)
__attribute__ ((format (printf, 3, 4)));
void debug_dump_node(struct hs20_svc *ctx, const char *title, xml_node_t *node);
xml_node_t * hs20_spp_server_process(struct hs20_svc *ctx, xml_node_t *node,
const char *auth_user,
const char *auth_realm, int dmacc);
int hs20_spp_server_init(struct hs20_svc *ctx);
void hs20_spp_server_deinit(struct hs20_svc *ctx);
#endif /* SPP_SERVER_H */

View file

@ -0,0 +1,17 @@
INSERT INTO osu_config(realm,field,value) VALUES('example.com','fqdn','example.com');
INSERT INTO osu_config(realm,field,value) VALUES('example.com','friendly_name','Example Operator');
INSERT INTO osu_config(realm,field,value) VALUES('example.com','spp_http_auth_url','https://subscription-server.osu.example.com/hs20/spp.php?realm=example.com');
INSERT INTO osu_config(realm,field,value) VALUES('example.com','trust_root_cert_url','https://osu-server.osu.example.com/hs20/files/spp-root-ca.der');
INSERT INTO osu_config(realm,field,value) VALUES('example.com','trust_root_cert_fingerprint','5b393a9246865569485c2605c3304e48212b449367858299beba9384c4cf4647');
INSERT INTO osu_config(realm,field,value) VALUES('example.com','aaa_trust_root_cert_url','https://osu-server.osu.example.com/hs20/files/aaa-root-ca.der');
INSERT INTO osu_config(realm,field,value) VALUES('example.com','aaa_trust_root_cert_fingerprint','5b393a9246865569485c2605c3304e48212b449367858299beba9384c4cf4647');
INSERT INTO osu_config(realm,field,value) VALUES('example.com','free_account','free');
INSERT INTO osu_config(realm,field,value) VALUES('example.com','policy_url','https://subscription-server.osu.example.com/hs20/spp.php?realm=example.com');
INSERT INTO osu_config(realm,field,value) VALUES('example.com','remediation_url','https://subscription-server.osu.example.com/hs20/remediation.php?session_id=');
INSERT INTO osu_config(realm,field,value) VALUES('example.com','free_remediation_url','https://subscription-server.osu.example.com/hs20/free-remediation.php?session_id=');
INSERT INTO osu_config(realm,field,value) VALUES('example.com','signup_url','https://subscription-server.osu.example.com/hs20/signup.php?session_id=');
INSERT INTO users(identity,realm,methods,password,phase2,shared) VALUES('free','example.com','TTLS-MSCHAPV2','free',1,1);
INSERT INTO wildcards(identity,methods) VALUES('','TTLS,TLS');

108
hs20/server/sql.txt Normal file
View file

@ -0,0 +1,108 @@
CREATE TABLE eventlog(
user TEXT,
realm TEXT,
sessionid TEXT COLLATE NOCASE,
timestamp TEXT,
notes TEXT,
dump TEXT,
addr TEXT
);
CREATE TABLE sessions(
timestamp TEXT,
id TEXT COLLATE NOCASE,
user TEXT,
realm TEXT,
password TEXT,
machine_managed BOOLEAN,
operation INTEGER,
type TEXT,
pps TEXT,
redirect_uri TEXT,
devinfo TEXT,
devdetail TEXT,
cert TEXT,
cert_pem TEXT,
mac_addr TEXT,
osu_user TEXT,
osu_password TEXT,
eap_method TEXT,
mobile_identifier_hash TEXT,
test TEXT
);
CREATE index sessions_id_index ON sessions(id);
CREATE TABLE osu_config(
realm TEXT,
field TEXT,
value TEXT
);
CREATE TABLE users(
identity TEXT PRIMARY KEY,
methods TEXT,
password TEXT,
machine_managed BOOLEAN,
remediation TEXT,
phase2 INTEGER,
realm TEXT,
policy TEXT,
devinfo TEXT,
devdetail TEXT,
pps TEXT,
fetch_pps INTEGER,
osu_user TEXT,
osu_password TEXT,
shared INTEGER,
cert TEXT,
cert_pem TEXT,
t_c_timestamp INTEGER,
mac_addr TEXT,
last_msk TEXT,
polupd_done TEXT,
subrem TEXT
);
CREATE TABLE wildcards(
identity TEXT PRIMARY KEY,
methods TEXT
);
CREATE TABLE authlog(
timestamp TEXT,
session TEXT,
nas_ip TEXT,
username TEXT,
note TEXT
);
CREATE TABLE pending_tc(
mac_addr TEXT PRIMARY KEY,
identity TEXT
);
CREATE TABLE current_sessions(
mac_addr TEXT PRIMARY KEY,
identity TEXT,
start_time TEXT,
nas TEXT,
hs20_t_c_filtering BOOLEAN,
waiting_coa_ack BOOLEAN,
coa_ack_received BOOLEAN
);
CREATE TABLE cert_enroll(
mac_addr TEXT PRIMARY KEY,
user TEXT,
realm TEXT,
serialnum TEXT
);
CREATE TABLE sim_provisioning(
mobile_identifier_hash TEXT PRIMARY KEY,
imsi TEXT,
mac_addr TEXT,
eap_method TEXT,
timestamp TEXT
);

View file

@ -0,0 +1,50 @@
<?php
require('config.php');
$db = new PDO($osu_db);
if (!$db) {
die($sqliteerror);
}
if (isset($_POST["id"]))
$id = preg_replace("/[^a-fA-F0-9]/", "", $_POST["id"]);
else
die("Missing session id");
if (strlen($id) < 32)
die("Invalid session id");
$row = $db->query("SELECT rowid,* FROM sessions WHERE id='$id'")->fetch();
if ($row == false) {
die("Session not found");
}
$uri = $row['redirect_uri'];
$rowid = $row['rowid'];
$realm = $row['realm'];
$row = $db->query("SELECT value FROM osu_config WHERE realm='$realm' AND field='free_account'")->fetch();
if (!$row || strlen($row['value']) == 0) {
die("Free account disabled");
}
$user = $row['value'];
$row = $db->query("SELECT password FROM users WHERE identity='$user' AND realm='$realm'")->fetch();
if (!$row)
die("Free account not found");
$pw = $row['password'];
if (!$db->exec("UPDATE sessions SET user='$user', password='$pw', realm='$realm', machine_managed='1' WHERE rowid=$rowid")) {
die("Failed to update session database");
}
$db->exec("INSERT INTO eventlog(user,realm,sessionid,timestamp,notes) " .
"VALUES ('$user', '$realm', '$id', " .
"strftime('%Y-%m-%d %H:%M:%f','now'), " .
"'completed user input response for a new PPS MO')");
header("Location: $uri", true, 302);
?>

View file

@ -0,0 +1,56 @@
<?php
require('config.php');
$db = new PDO($osu_db);
if (!$db) {
die($sqliteerror);
}
if (isset($_POST["id"]))
$id = preg_replace("/[^a-fA-F0-9]/", "", $_POST["id"]);
else
die("Missing session id");
$user = $_POST["user"];
$pw = $_POST["password"];
if (strlen($id) < 32 || !isset($user) || !isset($pw)) {
die("Invalid POST data");
}
if (strlen($user) < 1 || strncasecmp($user, "cert-", 5) == 0) {
echo "<html><body><p><red>Invalid username</red></p>\n";
echo "<a href=\"signup.php?session_id=$id\">Try again</a>\n";
echo "</body></html>\n";
exit;
}
$row = $db->query("SELECT rowid,* FROM sessions WHERE id='$id'")->fetch();
if ($row == false) {
die("Session not found");
}
$realm = $row['realm'];
$userrow = $db->query("SELECT identity FROM users WHERE identity='$user' AND realm='$realm'")->fetch();
if ($userrow) {
echo "<html><body><p><red>Selected username is not available</red></p>\n";
echo "<a href=\"signup.php?session_id=$id\">Try again</a>\n";
echo "</body></html>\n";
exit;
}
$uri = $row['redirect_uri'];
$rowid = $row['rowid'];
if (!$db->exec("UPDATE sessions SET user='$user', password='$pw', realm='$realm', type='password' WHERE rowid=$rowid")) {
die("Failed to update session database");
}
$db->exec("INSERT INTO eventlog(user,realm,sessionid,timestamp,notes) " .
"VALUES ('$user', '$realm', '$id', " .
"strftime('%Y-%m-%d %H:%M:%f','now'), " .
"'completed user input response for a new PPS MO')");
header("Location: $uri", true, 302);
?>

View file

@ -0,0 +1,39 @@
<?php
require('config.php');
$db = new PDO($osu_db);
if (!$db) {
die($sqliteerror);
}
if (isset($_GET["id"]))
$id = preg_replace("/[^a-fA-F0-9]/", "", $_GET["id"]);
else
die("Missing session id");
if (strlen($id) < 32)
die("Invalid session id");
$row = $db->query("SELECT rowid,* FROM sessions WHERE id='$id'")->fetch();
if ($row == false) {
die("Session not found");
}
$uri = $row['redirect_uri'];
$rowid = $row['rowid'];
$realm = $row['realm'];
$user = sha1(mt_rand());
if (!$db->exec("UPDATE sessions SET user='$user', type='cert' WHERE rowid=$rowid")) {
die("Failed to update session database");
}
$db->exec("INSERT INTO eventlog(user,realm,sessionid,timestamp,notes) " .
"VALUES ('', '$realm', '$id', " .
"strftime('%Y-%m-%d %H:%M:%f','now'), " .
"'completed user input response for client certificate enrollment')");
header("Location: $uri", true, 302);
?>

View file

@ -0,0 +1,7 @@
<?php
$osu_root = "/home/user/hs20-server";
$osu_db = "sqlite:$osu_root/AS/DB/eap_user.db";
$t_c_file = "$osu_root/terms-and-conditions";
$t_c_timestamp = 123456789;
$hostapd_ctrl = "udg:///home/user/hs20-server/AS/ctrl/as"
?>

232
hs20/server/www/est.php Normal file
View file

@ -0,0 +1,232 @@
<?php
require('config.php');
$params = explode("/", $_SERVER["PATH_INFO"], 3);
$realm = $params[1];
$cmd = $params[2];
$method = $_SERVER["REQUEST_METHOD"];
unset($user);
unset($rowid);
$db = new PDO($osu_db);
if (!$db) {
error_log("EST: Could not access database");
die("Could not access database");
}
if (!empty($_SERVER['PHP_AUTH_DIGEST'])) {
$needed = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1,
'uri'=>1, 'response'=>1);
$data = array();
$keys = implode('|', array_keys($needed));
preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@',
$_SERVER['PHP_AUTH_DIGEST'], $matches, PREG_SET_ORDER);
foreach ($matches as $m) {
$data[$m[1]] = $m[3] ? $m[3] : $m[4];
unset($needed[$m[1]]);
}
if ($needed) {
error_log("EST: Missing auth parameter");
die('Authentication failed');
}
$user = $data['username'];
if (strlen($user) < 1) {
error_log("EST: Empty username");
die('Authentication failed');
}
$sql = "SELECT rowid,password,operation FROM sessions " .
"WHERE user='$user' AND realm='$realm'";
$q = $db->query($sql);
if (!$q) {
error_log("EST: Session not found for user=$user realm=$realm");
die("Session not found");
}
$row = $q->fetch();
if (!$row) {
error_log("EST: Session fetch failed for user=$user realm=$realm");
die('Session not found');
}
$rowid = $row['rowid'];
$oper = $row['operation'];
if ($oper != '5') {
error_log("EST: Unexpected operation $oper for user=$user realm=$realm");
die("Session not found");
}
$pw = $row['password'];
if (strlen($pw) < 1) {
error_log("EST: Empty password for user=$user realm=$realm");
die('Authentication failed');
}
$A1 = md5($user . ':' . $realm . ':' . $pw);
$A2 = md5($method . ':' . $data['uri']);
$resp = md5($A1 . ':' . $data['nonce'] . ':' . $data['nc'] . ':' .
$data['cnonce'] . ':' . $data['qop'] . ':' . $A2);
if ($data['response'] != $resp) {
error_log("EST: Incorrect authentication response for user=$user realm=$realm");
die('Authentication failed');
}
} else if (isset($_SERVER["SSL_CLIENT_VERIFY"]) &&
$_SERVER["SSL_CLIENT_VERIFY"] == "SUCCESS" &&
isset($_SERVER["SSL_CLIENT_M_SERIAL"])) {
$user = "cert-" . $_SERVER["SSL_CLIENT_M_SERIAL"];
$sql = "SELECT rowid,password,operation FROM sessions " .
"WHERE user='$user' AND realm='$realm'";
$q = $db->query($sql);
if (!$q) {
error_log("EST: Session not found for user=$user realm=$realm");
die("Session not found");
}
$row = $q->fetch();
if (!$row) {
error_log("EST: Session fetch failed for user=$user realm=$realm");
die('Session not found');
}
$rowid = $row['rowid'];
$oper = $row['operation'];
if ($oper != '10') {
error_log("EST: Unexpected operation $oper for user=$user realm=$realm");
die("Session not found");
}
}
if ($method == "GET" && $cmd == "cacerts") {
$fname = "$osu_root/est/$realm-cacerts.pkcs7";
if (!file_exists($fname)) {
error_log("EST: cacerts - unknown realm $realm");
die("Unknown realm");
}
header("Content-Transfer-Encoding: base64");
header("Content-Type: application/pkcs7-mime");
$data = file_get_contents($fname);
echo wordwrap(base64_encode($data), 72, "\n", true);
echo "\n";
error_log("EST: cacerts");
} else if ($method == "GET" && $cmd == "csrattrs") {
header("Content-Transfer-Encoding: base64");
header("Content-Type: application/csrattrs");
readfile("$osu_root/est/est-attrs.b64");
error_log("EST: csrattrs");
} else if ($method == "POST" &&
($cmd == "simpleenroll" || $cmd == "simplereenroll")) {
$reenroll = $cmd == "simplereenroll";
if (!$reenroll && (!isset($user) || strlen($user) == 0)) {
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Digest realm="'.$realm.
'",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');
error_log("EST: simpleenroll - require authentication");
die('Authentication required');
}
if ($reenroll &&
(!isset($user) ||
!isset($_SERVER["SSL_CLIENT_VERIFY"]) ||
$_SERVER["SSL_CLIENT_VERIFY"] != "SUCCESS")) {
header('HTTP/1.1 403 Forbidden');
error_log("EST: simplereenroll - require certificate authentication");
die('Authentication required');
}
if (!isset($_SERVER["CONTENT_TYPE"])) {
error_log("EST: simpleenroll without Content-Type");
die("Missing Content-Type");
}
if (!stristr($_SERVER["CONTENT_TYPE"], "application/pkcs10")) {
error_log("EST: simpleenroll - unexpected Content-Type: " .
$_SERVER["CONTENT_TYPE"]);
die("Unexpected Content-Type");
}
$data = file_get_contents("php://input");
error_log("EST: simpleenroll - POST data from php://input: " . $data);
$req = base64_decode($data);
if ($req == FALSE) {
error_log("EST: simpleenroll - Invalid base64-encoded PKCS#10 data");
die("Invalid base64-encoded PKCS#10 data");
}
$cadir = "$osu_root/est";
$reqfile = "$cadir/tmp/cert-req.pkcs10";
$f = fopen($reqfile, "wb");
fwrite($f, $req);
fclose($f);
$req_pem = "$reqfile.pem";
if (file_exists($req_pem))
unlink($req_pem);
exec("openssl req -in $reqfile -inform DER -out $req_pem -outform PEM");
if (!file_exists($req_pem)) {
error_log("EST: simpleenroll - Failed to parse certificate request");
die("Failed to parse certificate request");
}
/* FIX: validate request and add HS 2.0 extensions to cert */
$cert_pem = "$cadir/tmp/req-signed.pem";
if (file_exists($cert_pem))
unlink($cert_pem);
exec("openssl x509 -req -in $req_pem -CAkey $cadir/cakey.pem -out $cert_pem -CA $cadir/cacert.pem -CAserial $cadir/serial -days 365 -text");
if (!file_exists($cert_pem)) {
error_log("EST: simpleenroll - Failed to sign certificate");
die("Failed to sign certificate");
}
$cert = file_get_contents($cert_pem);
$handle = popen("openssl x509 -in $cert_pem -serial -noout", "r");
$serial = fread($handle, 200);
pclose($handle);
$pattern = "/serial=(?P<snhex>[0-9a-fA-F:]*)/m";
preg_match($pattern, $serial, $matches);
if (!isset($matches['snhex']) || strlen($matches['snhex']) < 1) {
error_log("EST: simpleenroll - Could not get serial number");
die("Could not get serial number");
}
$sn = str_replace(":", "", strtoupper($matches['snhex']));
$user = "cert-$sn";
error_log("EST: user = $user");
$cert_der = "$cadir/tmp/req-signed.der";
if (file_exists($cert_der))
unlink($cert_der);
exec("openssl x509 -in $cert_pem -inform PEM -out $cert_der -outform DER");
if (!file_exists($cert_der)) {
error_log("EST: simpleenroll - Failed to convert certificate");
die("Failed to convert certificate");
}
$der = file_get_contents($cert_der);
$fingerprint = hash("sha256", $der);
error_log("EST: sha256(DER cert): $fingerprint");
$pkcs7 = "$cadir/tmp/est-client.pkcs7";
if (file_exists($pkcs7))
unlink($pkcs7);
exec("openssl crl2pkcs7 -nocrl -certfile $cert_pem -out $pkcs7 -outform DER");
if (!file_exists($pkcs7)) {
error_log("EST: simpleenroll - Failed to prepare PKCS#7 file");
die("Failed to prepare PKCS#7 file");
}
if (!$db->exec("UPDATE sessions SET user='$user', cert='$fingerprint', cert_pem='$cert' WHERE rowid=$rowid")) {
error_log("EST: simpleenroll - Failed to update session database");
die("Failed to update session database");
}
header("Content-Transfer-Encoding: base64");
header("Content-Type: application/pkcs7-mime");
$data = file_get_contents($pkcs7);
$resp = wordwrap(base64_encode($data), 72, "\n", true);
echo $resp . "\n";
error_log("EST: simpleenroll - PKCS#7 response: " . $resp);
} else {
header("HTTP/1.0 404 Not Found");
error_log("EST: Unexpected method or path");
die("Unexpected method or path");
}
?>

View file

@ -0,0 +1,19 @@
<html>
<head>
<title>Hotspot 2.0 - public and free hotspot - remediation</title>
</head>
<body>
<h3>Hotspot 2.0 - public and free hotspot</h3>
<p>Terms and conditions have changed. You need to accept the new terms
to continue using this network.</p>
<p>Terms and conditions..</p>
<?php
echo "<a href=\"redirect.php?id=" . $_GET["session_id"] . "\">Accept</a><br>\n";
?>
</body>
</html>

23
hs20/server/www/free.php Normal file
View file

@ -0,0 +1,23 @@
<html>
<head>
<title>Hotspot 2.0 - public and free hotspot</title>
</head>
<body>
<?php
$id = $_GET["session_id"];
echo "<h3>Hotspot 2.0 - public and free hotspot</h3>\n";
echo "<form action=\"add-free.php\" method=\"POST\">\n";
echo "<input type=\"hidden\" name=\"id\" value=\"$id\">\n";
?>
<p>Terms and conditions..</p>
<input type="submit" value="Accept">
</form>
</body>
</html>

View file

@ -0,0 +1,32 @@
<?php
require('config.php');
$db = new PDO($osu_db);
if (!$db) {
die($sqliteerror);
}
if (isset($_GET["id"]))
$id = preg_replace("/[^a-fA-F0-9]/", "", $_GET["id"]);
else
$id = 0;
$row = $db->query("SELECT rowid,* FROM sessions WHERE id='$id'")->fetch();
if ($row == false) {
die("Session not found");
}
$uri = $row['redirect_uri'];
header("Location: $uri", true, 302);
$user = $row['user'];
$realm = $row['realm'];
$db->exec("INSERT INTO eventlog(user,realm,sessionid,timestamp,notes) " .
"VALUES ('$user', '$realm', '$id', " .
"strftime('%Y-%m-%d %H:%M:%f','now'), " .
"'redirected after user input')");
?>

View file

@ -0,0 +1,41 @@
<?php
require('config.php');
$db = new PDO($osu_db);
if (!$db) {
die($sqliteerror);
}
if (isset($_POST["id"]))
$id = preg_replace("/[^a-fA-F0-9]/", "", $_POST["id"]);
else
die("Missing session id");
$pw = $_POST["password"];
if (strlen($id) < 32 || !isset($pw)) {
die("Invalid POST data");
}
$row = $db->query("SELECT rowid,* FROM sessions WHERE id='$id'")->fetch();
if ($row == false) {
die("Session not found");
}
$user = $row['user'];
$realm = $row['realm'];
$uri = $row['redirect_uri'];
$rowid = $row['rowid'];
if (!$db->exec("UPDATE sessions SET password='$pw' WHERE rowid=$rowid")) {
die("Failed to update session database");
}
$db->exec("INSERT INTO eventlog(user,realm,sessionid,timestamp,notes) " .
"VALUES ('$user', '$realm', '$id', " .
"strftime('%Y-%m-%d %H:%M:%f','now'), " .
"'completed user input response for subscription remediation')");
header("Location: $uri", true, 302);
?>

View file

@ -0,0 +1,55 @@
<html>
<head>
<title>Hotspot 2.0 subscription remediation</title>
</head>
<body>
<?php
require('config.php');
$db = new PDO($osu_db);
if (!$db) {
die($sqliteerror);
}
if (isset($_GET["session_id"]))
$id = preg_replace("/[^a-fA-F0-9]/", "", $_GET["session_id"]);
else
$id = 0;
echo "SessionID: " . $id . "<br>\n";
$row = $db->query("SELECT * FROM sessions WHERE id='$id'")->fetch();
if ($row == false) {
die("Session not found");
}
$username = $row['user'];
echo "User: " . $username . "@" . $row['realm'] . "<br>\n";
$user = $db->query("SELECT machine_managed,methods FROM users WHERE identity='$username'")->fetch();
if ($user == false) {
die("User not found");
}
echo "<hr><br>\n";
$cert = $user['methods'] == "TLS" || strncmp($username, "cert-", 5) == 0;
if ($cert) {
echo "<a href=\"redirect.php?id=" . $_GET["session_id"] . "\">Complete user subscription remediation</a><br>\n";
} else if ($user['machine_managed'] == "1") {
echo "<a href=\"redirect.php?id=" . $_GET["session_id"] . "\">Complete user subscription remediation</a><br>\n";
echo "This will provide a new machine-generated password.<br>\n";
} else {
echo "<form action=\"remediation-pw.php\" method=\"POST\">\n";
echo "<input type=\"hidden\" name=\"id\" value=\"$id\">\n";
echo "New password: <input type=\"password\" name=\"password\"><br>\n";
echo "<input type=\"submit\" value=\"Change password\">\n";
echo "</form>\n";
}
?>
</body>
</html>

View file

@ -0,0 +1,59 @@
<html>
<head>
<title>Hotspot 2.0 signup</title>
</head>
<body>
<?php
$id = $_GET["session_id"];
require('config.php');
$db = new PDO($osu_db);
if (!$db) {
die($sqliteerror);
}
$row = $db->query("SELECT realm,test FROM sessions WHERE id='$id'")->fetch();
if ($row == false) {
die("Session not found for id: $id");
}
$realm = $row['realm'];
$test = $row['test'];
if (strlen($test) > 0) {
echo "<p style=\"color:#FF0000\">Special test functionality: $test</red></big></p>\n";
}
echo "<h3>Sign up for a subscription - $realm</h3>\n";
echo "<p>This page can be used to select between three different types of subscriptions for testing purposes.</p>\n";
echo "<h4>Option 1 - shared free access credential</h4>\n";
$row = $db->query("SELECT value FROM osu_config WHERE realm='$realm' AND field='free_account'")->fetch();
if ($row && strlen($row['value']) > 0) {
echo "<p><a href=\"free.php?session_id=$id\">Sign up for free access</a></p>\n";
}
echo "<h4>Option 2 - username/password credential</h4>\n";
echo "<form action=\"add-mo.php\" method=\"POST\">\n";
echo "<input type=\"hidden\" name=\"id\" value=\"$id\">\n";
?>
Select a username and password. Leave password empty to get automatically
generated and machine managed password.<br>
Username: <input type="text" name="user"><br>
Password: <input type="password" name="password"><br>
<input type="submit" value="Complete subscription registration">
</form>
<?php
echo "<h4>Option 3 - client certificate credential</h4>\n";
echo "<p><a href=\"cert-enroll.php?id=$id\">Enroll a client certificate</a></p>\n"
?>
</body>
</html>

168
hs20/server/www/spp.php Normal file
View file

@ -0,0 +1,168 @@
<?php
require('config.php');
if (!stristr($_SERVER["CONTENT_TYPE"], "application/soap+xml")) {
error_log("spp.php - Unexpected Content-Type " . $_SERVER["CONTENT_TYPE"]);
die("Unexpected Content-Type");
}
if ($_SERVER["REQUEST_METHOD"] != "POST") {
error_log("spp.php - Unexpected method " . $_SERVER["REQUEST_METHOD"]);
die("Unexpected method");
}
if (isset($_GET["realm"])) {
$realm = $_GET["realm"];
$realm = PREG_REPLACE("/[^0-9a-zA-Z\.\-]/i", '', $realm);
} else {
error_log("spp.php - Realm not specified");
die("Realm not specified");
}
if (isset($_GET["test"]))
$test = PREG_REPLACE("/[^0-9a-zA-Z\_\-]/i", '', $_GET["test"]);
else
$test = "";
unset($user);
putenv("HS20CERT");
if (!empty($_SERVER['PHP_AUTH_DIGEST'])) {
$needed = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1,
'uri'=>1, 'response'=>1);
$data = array();
$keys = implode('|', array_keys($needed));
preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@',
$_SERVER['PHP_AUTH_DIGEST'], $matches, PREG_SET_ORDER);
foreach ($matches as $m) {
$data[$m[1]] = $m[3] ? $m[3] : $m[4];
unset($needed[$m[1]]);
}
if ($needed) {
error_log("spp.php - Authentication failed - missing: " . print_r($needed));
die('Authentication failed');
}
$user = $data['username'];
if (strlen($user) < 1) {
error_log("spp.php - Authentication failed - empty username");
die('Authentication failed');
}
$db = new PDO($osu_db);
if (!$db) {
error_log("spp.php - Could not access database");
die("Could not access database");
}
$row = $db->query("SELECT password FROM users " .
"WHERE identity='$user' AND realm='$realm'")->fetch();
if (!$row) {
$row = $db->query("SELECT osu_password FROM users " .
"WHERE osu_user='$user' AND realm='$realm'")->fetch();
$pw = $row['osu_password'];
} else
$pw = $row['password'];
if (!$row) {
error_log("spp.php - Authentication failed - user '$user' not found");
die('Authentication failed');
}
if (strlen($pw) < 1) {
error_log("spp.php - Authentication failed - empty password");
die('Authentication failed');
}
$A1 = md5($user . ':' . $realm . ':' . $pw);
$A2 = md5($_SERVER['REQUEST_METHOD'] . ':' . $data['uri']);
$resp = md5($A1 . ':' . $data['nonce'] . ':' . $data['nc'] . ':' .
$data['cnonce'] . ':' . $data['qop'] . ':' . $A2);
if ($data['response'] != $resp) {
error_log("Authentication failure - response mismatch");
die('Authentication failed');
}
} else if (isset($_SERVER["SSL_CLIENT_VERIFY"]) &&
$_SERVER["SSL_CLIENT_VERIFY"] == "SUCCESS" &&
isset($_SERVER["SSL_CLIENT_M_SERIAL"])) {
$user = "cert-" . $_SERVER["SSL_CLIENT_M_SERIAL"];
putenv("HS20CERT=yes");
} else if (isset($_GET["hotspot2dot0-mobile-identifier-hash"])) {
$id_hash = $_GET["hotspot2dot0-mobile-identifier-hash"];
$id_hash = PREG_REPLACE("/[^0-9a-h]/i", '', $id_hash);
$db = new PDO($osu_db);
if (!$db) {
error_log("spp.php - Could not access database");
die("Could not access database");
}
$row = $db->query("SELECT * FROM sim_provisioning " .
"WHERE mobile_identifier_hash='$id_hash'")->fetch();
if (!$row) {
error_log("spp.php - SIM provisioning failed - mobile_identifier_hash not found");
die('SIM provisioning failed - mobile_identifier_hash not found');
}
$imsi = $row['imsi'];
$mac_addr = $row['mac_addr'];
$eap_method = $row['eap_method'];
$row = $db->query("SELECT COUNT(*) FROM osu_config " .
"WHERE realm='$realm'")->fetch();
if (!$row || intval($row[0]) < 1) {
error_log("spp.php - SIM provisioning failed - realm $realm not found");
die('SIM provisioning failed');
}
error_log("spp.php - SIM provisioning for IMSI $imsi");
putenv("HS20SIMPROV=yes");
putenv("HS20IMSI=$imsi");
putenv("HS20MACADDR=$mac_addr");
putenv("HS20EAPMETHOD=$eap_method");
putenv("HS20IDHASH=$id_hash");
} else if (!isset($_SERVER["PATH_INFO"]) ||
$_SERVER["PATH_INFO"] != "/signup") {
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Digest realm="'.$realm.
'",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');
error_log("spp.php - Authentication required (not signup)");
die('Authentication required (not signup)');
}
if (isset($user) && strlen($user) > 0)
putenv("HS20USER=$user");
else
putenv("HS20USER");
putenv("HS20REALM=$realm");
$postdata = file_get_contents("php://input");
putenv("HS20POST=$postdata");
$addr = $_SERVER["REMOTE_ADDR"];
putenv("HS20ADDR=$addr");
putenv("HS20TEST=$test");
$last = exec("$osu_root/spp/hs20_spp_server -r$osu_root -f/tmp/hs20_spp_server.log", $output, $ret);
if ($ret == 2) {
if (empty($_SERVER['PHP_AUTH_DIGEST'])) {
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Digest realm="'.$realm.
'",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');
error_log("spp.php - Authentication required (ret 2)");
die('Authentication required');
} else {
error_log("spp.php - Unexpected authentication error");
die("Unexpected authentication error");
}
}
if ($ret != 0) {
error_log("spp.php - Failed to process SPP request");
die("Failed to process SPP request");
}
//error_log("spp.php: Response: " . implode($output));
header("Content-Type: application/soap+xml");
echo implode($output);
?>

87
hs20/server/www/terms.php Normal file
View file

@ -0,0 +1,87 @@
<?php
require('config.php');
function print_header()
{
echo "<html>\n";
echo "<head><title>HS 2.0 Terms and Conditions</title></head>\n";
echo "<body>\n";
}
$db = new PDO($osu_db);
if (!$db) {
die($sqliteerror);
}
if (!isset($_GET["addr"])) {
die("Missing addr parameter");
}
$addr = $_GET["addr"];
$accept = isset($_GET["accept"]) && $_GET["accept"] == "yes";
$res = $db->prepare("SELECT identity FROM pending_tc WHERE mac_addr=?");
$res->execute(array($addr));
$row = $res->fetch();
if (!$row) {
die("No pending session for the specified MAC address");
}
$identity = $row[0];
if (!$accept) {
print_header();
echo "<p>Accept the following terms and conditions by clicking here: <a href=\"terms.php?addr=$addr&accept=yes\">Accept</a></p>\n<hr>\n";
readfile($t_c_file);
} else {
$res = $db->prepare("UPDATE users SET t_c_timestamp=? WHERE identity=?");
if (!$res->execute(array($t_c_timestamp, $identity))) {
die("Failed to update user account.");
}
$res = $db->prepare("DELETE FROM pending_tc WHERE mac_addr=?");
$res->execute(array($addr));
$fp = fsockopen($hostapd_ctrl);
if (!$fp) {
die("Could not connect to hostapd(AS)");
}
fwrite($fp, "DAC_REQUEST coa $addr t_c_clear");
fclose($fp);
$waiting = true;
$ack = false;
for ($i = 1; $i <= 10; $i++) {
$res = $db->prepare("SELECT waiting_coa_ack,coa_ack_received FROM current_sessions WHERE mac_addr=?");
$res->execute(array($addr));
$row = $res->fetch();
if (!$row) {
die("No current session for the specified MAC address");
}
if (strlen($row[0]) > 0)
$waiting = $row[0] == 1;
if (strlen($row[1]) > 0)
$ack = $row[1] == 1;
$res->closeCursor();
if (!$waiting)
break;
sleep(1);
}
if ($ack) {
header('X-WFA-Hotspot20-Filtering: removed');
print_header();
echo "<p>Terms and conditions were accepted.</p>\n";
echo "<P>Filtering disabled.</P>\n";
} else {
print_header();
echo "<P>Failed to disable filtering.</P>\n";
}
}
?>
</body>
</html>

377
hs20/server/www/users.php Normal file
View file

@ -0,0 +1,377 @@
<?php
require('config.php');
$db = new PDO($osu_db);
if (!$db) {
die($sqliteerror);
}
if (isset($_GET["id"])) {
$id = $_GET["id"];
if (!is_numeric($id))
$id = 0;
} else
$id = 0;
if (isset($_GET["cmd"]))
$cmd = $_GET["cmd"];
else
$cmd = '';
if ($cmd == 'eventlog' && $id > 0) {
$row = $db->query("SELECT dump FROM eventlog WHERE rowid=$id")->fetch();
$dump = $row['dump'];
if ($dump[0] == '<') {
header("Content-type: text/xml");
echo "<?xml version=\"1.0\"?>\n";
echo $dump;
} else {
header("Content-type: text/plain");
echo $dump;
}
exit;
}
if ($cmd == 'mo' && $id > 0) {
$mo = $_GET["mo"];
if (!isset($mo))
exit;
if ($mo != "devinfo" && $mo != "devdetail" && $mo != "pps")
exit;
$row = $db->query("SELECT $mo FROM users WHERE rowid=$id")->fetch();
header("Content-type: text/xml");
echo "<?xml version=\"1.0\"?>\n";
echo $row[$mo];
exit;
}
if ($cmd == 'cert' && $id > 0) {
$row = $db->query("SELECT cert_pem FROM users WHERE rowid=$id")->fetch();
header("Content-type: text/plain");
echo $row['cert_pem'];
exit;
}
?>
<html>
<head><title>HS 2.0 users</title></head>
<body>
<?php
if ($cmd == 'subrem-clear' && $id > 0) {
$db->exec("UPDATE users SET remediation='' WHERE rowid=$id");
}
if ($cmd == 'subrem-add-user' && $id > 0) {
$db->exec("UPDATE users SET remediation='user' WHERE rowid=$id");
}
if ($cmd == 'subrem-add-machine' && $id > 0) {
$db->exec("UPDATE users SET remediation='machine' WHERE rowid=$id");
}
if ($cmd == 'subrem-add-reenroll' && $id > 0) {
$db->exec("UPDATE users SET remediation='reenroll' WHERE rowid=$id");
}
if ($cmd == 'subrem-add-policy' && $id > 0) {
$db->exec("UPDATE users SET remediation='policy' WHERE rowid=$id");
}
if ($cmd == 'subrem-add-free' && $id > 0) {
$db->exec("UPDATE users SET remediation='free' WHERE rowid=$id");
}
if ($cmd == 'fetch-pps-on' && $id > 0) {
$db->exec("UPDATE users SET fetch_pps=1 WHERE rowid=$id");
}
if ($cmd == 'fetch-pps-off' && $id > 0) {
$db->exec("UPDATE users SET fetch_pps=0 WHERE rowid=$id");
}
if ($cmd == 'reset-pw' && $id > 0) {
$db->exec("UPDATE users SET password='ChangeMe' WHERE rowid=$id");
}
if ($cmd == "policy" && $id > 0 && isset($_GET["policy"])) {
$policy = $_GET["policy"];
if ($policy == "no-policy" ||
is_readable("$osu_root/spp/policy/$policy.xml")) {
$db->exec("UPDATE users SET policy='$policy' WHERE rowid=$id");
}
}
if ($cmd == "account-type" && $id > 0 && isset($_GET["type"])) {
$type = $_GET["type"];
if ($type == "shared")
$db->exec("UPDATE users SET shared=1 WHERE rowid=$id");
if ($type == "default")
$db->exec("UPDATE users SET shared=0 WHERE rowid=$id");
}
if ($cmd == "set-osu-cred" && $id > 0) {
$osu_user = $_POST["osu_user"];
$osu_password = $_POST["osu_password"];
if (strlen($osu_user) == 0)
$osu_password = "";
$db->exec("UPDATE users SET osu_user='$osu_user', osu_password='$osu_password' WHERE rowid=$id");
}
if ($cmd == 'clear-t-c' && $id > 0) {
$db->exec("UPDATE users SET t_c_timestamp=NULL WHERE rowid=$id");
}
$dump = 0;
if ($id > 0) {
if (isset($_GET["dump"])) {
$dump = $_GET["dump"];
if (!is_numeric($dump))
$dump = 0;
} else
$dump = 0;
echo "[<a href=\"users.php\">All users</a>] ";
if ($dump == 0)
echo "[<a href=\"users.php?id=$id&dump=1\">Include debug dump</a>] ";
else
echo "[<a href=\"users.php?id=$id\">Without debug dump</a>] ";
echo "<br>\n";
$row = $db->query("SELECT rowid,* FROM users WHERE rowid=$id")->fetch();
echo "<H3>" . $row['identity'] . "@" . $row['realm'] . "</H3>\n";
echo "MO: ";
if (strlen($row['devinfo']) > 0) {
echo "[<a href=\"users.php?cmd=mo&id=$id&mo=devinfo\">DevInfo</a>]\n";
}
if (strlen($row['devdetail']) > 0) {
echo "[<a href=\"users.php?cmd=mo&id=$id&mo=devdetail\">DevDetail</a>]\n";
}
if (strlen($row['pps']) > 0) {
echo "[<a href=\"users.php?cmd=mo&id=$id&mo=pps\">PPS</a>]\n";
}
if (strlen($row['cert_pem']) > 0) {
echo "[<a href=\"users.php?cmd=cert&id=$id\">Certificate</a>]\n";
}
echo "<BR>\n";
echo "Fetch PPS MO: ";
if ($row['fetch_pps'] == "1") {
echo "On next connection " .
"[<a href=\"users.php?cmd=fetch-pps-off&id=$id\">" .
"do not fetch</a>]<br>\n";
} else {
echo "Do not fetch " .
"[<a href=\"users.php?cmd=fetch-pps-on&id=$id\">" .
"request fetch</a>]<br>\n";
}
$cert = $row['cert'];
if (strlen($cert) > 0) {
echo "Certificate fingerprint: $cert<br>\n";
}
echo "Remediation: ";
$rem = $row['remediation'];
if ($rem == "") {
echo "Not required";
echo " [<a href=\"users.php?cmd=subrem-add-user&id=" .
$row['rowid'] . "\">add:user</a>]";
echo " [<a href=\"users.php?cmd=subrem-add-machine&id=" .
$row['rowid'] . "\">add:machine</a>]";
if ($row['methods'] == 'TLS') {
echo " [<a href=\"users.php?cmd=subrem-add-reenroll&id=" .
$row['rowid'] . "\">add:reenroll</a>]";
}
echo " [<a href=\"users.php?cmd=subrem-add-policy&id=" .
$row['rowid'] . "\">add:policy</a>]";
echo " [<a href=\"users.php?cmd=subrem-add-free&id=" .
$row['rowid'] . "\">add:free</a>]";
} else if ($rem == "user") {
echo "User [<a href=\"users.php?cmd=subrem-clear&id=" .
$row['rowid'] . "\">clear</a>]";
} else if ($rem == "policy") {
echo "Policy [<a href=\"users.php?cmd=subrem-clear&id=" .
$row['rowid'] . "\">clear</a>]";
} else if ($rem == "free") {
echo "Free [<a href=\"users.php?cmd=subrem-clear&id=" .
$row['rowid'] . "\">clear</a>]";
} else if ($rem == "reenroll") {
echo "Reenroll [<a href=\"users.php?cmd=subrem-clear&id=" .
$row['rowid'] . "\">clear</a>]";
} else {
echo "Machine [<a href=\"users.php?cmd=subrem-clear&id=" .
$row['rowid'] . "\">clear</a>]";
}
echo "<br>\n";
if (strncmp($row['identity'], "cert-", 5) != 0)
echo "Machine managed: " . ($row['machine_managed'] == "1" ? "TRUE" : "FALSE") . "<br>\n";
echo "<form>Policy: <select name=\"policy\" " .
"onChange=\"window.location='users.php?cmd=policy&id=" .
$row['rowid'] . "&policy=' + this.value;\">\n";
echo "<option value=\"" . $row['policy'] . "\" selected>" . $row['policy'] .
"</option>\n";
$files = scandir("$osu_root/spp/policy");
foreach ($files as $file) {
if (!preg_match("/.xml$/", $file))
continue;
if ($file == $row['policy'] . ".xml")
continue;
$p = substr($file, 0, -4);
echo "<option value=\"$p\">$p</option>\n";
}
echo "<option value=\"no-policy\">no policy</option>\n";
echo "</select></form>\n";
echo "<form>Account type: <select name=\"type\" " .
"onChange=\"window.location='users.php?cmd=account-type&id=" .
$row['rowid'] . "&type=' + this.value;\">\n";
if ($row['shared'] > 0) {
$default_sel = "";
$shared_sel = " selected";
} else {
$default_sel = " selected";
$shared_sel = "";
}
echo "<option value=\"default\"$default_sel>default</option>\n";
echo "<option value=\"shared\"$shared_sel>shared</option>\n";
echo "</select></form>\n";
echo "Phase 2 method(s): " . $row['methods'] . "<br>\n";
echo "<br>\n";
echo "<a href=\"users.php?cmd=reset-pw&id=" .
$row['rowid'] . "\">Reset AAA password</a><br>\n";
echo "<br>\n";
echo "<form action=\"users.php?cmd=set-osu-cred&id=" . $row['rowid'] .
"\" method=\"POST\">\n";
echo "OSU credentials (if username empty, AAA credentials are used):<br>\n";
echo "username: <input type=\"text\" name=\"osu_user\" value=\"" .
$row['osu_user'] . "\">\n";
echo "password: <input type=\"password\" name=\"osu_password\">\n";
echo "<input type=\"submit\" value=\"Set OSU credentials\">\n";
echo "</form>\n";
if (strlen($row['t_c_timestamp']) > 0) {
echo "<br>\n";
echo "<a href=\"users.php?cmd=clear-t-c&id=" .
$row['rowid'] .
"\">Clear Terms and Conditions acceptance</a><br>\n";
}
echo "<hr>\n";
$user = $row['identity'];
$osu_user = $row['osu_user'];
$realm = $row['realm'];
}
if ($id > 0 || ($id == 0 && $cmd == 'eventlog')) {
if ($id == 0) {
echo "[<a href=\"users.php\">All users</a>] ";
echo "<br>\n";
}
echo "<table border=1>\n";
echo "<tr>";
if ($id == 0) {
echo "<th>user<th>realm";
}
echo "<th>time<th>address<th>sessionID<th>notes";
if ($dump > 0)
echo "<th>dump";
echo "\n";
if (isset($_GET["limit"])) {
$limit = $_GET["limit"];
if (!is_numeric($limit))
$limit = 20;
} else
$limit = 20;
if ($id == 0)
$res = $db->query("SELECT rowid,* FROM eventlog ORDER BY timestamp DESC LIMIT $limit");
else if (strlen($osu_user) > 0)
$res = $db->query("SELECT rowid,* FROM eventlog WHERE (user='$user' OR user='$osu_user') AND realm='$realm' ORDER BY timestamp DESC LIMIT $limit");
else
$res = $db->query("SELECT rowid,* FROM eventlog WHERE user='$user' AND realm='$realm' ORDER BY timestamp DESC LIMIT $limit");
foreach ($res as $row) {
echo "<tr>";
if ($id == 0) {
echo "<td>" . $row['user'] . "\n";
echo "<td>" . $row['realm'] . "\n";
}
echo "<td>" . $row['timestamp'] . "\n";
echo "<td>" . $row['addr'] . "\n";
echo "<td>" . $row['sessionid'] . "\n";
echo "<td>" . $row['notes'] . "\n";
$d = $row['dump'];
if (strlen($d) > 0) {
echo "[<a href=\"users.php?cmd=eventlog&id=" . $row['rowid'] .
"\">";
if ($d[0] == '<')
echo "XML";
else
echo "txt";
echo "</a>]\n";
if ($dump > 0)
echo "<td>" . htmlspecialchars($d) . "\n";
}
}
echo "</table>\n";
}
if ($id == 0 && $cmd != 'eventlog') {
echo "[<a href=\"users.php?cmd=eventlog&limit=50\">Eventlog</a>] ";
echo "<br>\n";
echo "<table border=1 cellspacing=0 cellpadding=0>\n";
echo "<tr><th>User<th>Realm<th><small>Remediation</small><th>Policy<th><small>Account type</small><th><small>Phase 2 method(s)</small><th>DevId<th>MAC Address<th>T&C\n";
$res = $db->query('SELECT rowid,* FROM users WHERE (phase2=1 OR methods=\'TLS\') ORDER BY identity');
foreach ($res as $row) {
echo "<tr><td><a href=\"users.php?id=" . $row['rowid'] . "\"> " .
$row['identity'] . " </a>";
echo "<td>" . $row['realm'];
$rem = $row['remediation'];
echo "<td>";
if ($rem == "") {
echo "-";
} else if ($rem == "user") {
echo "User";
} else if ($rem == "policy") {
echo "Policy";
} else if ($rem == "free") {
echo "Free";
} else if ($rem == "reenroll") {
echo "Reenroll";
} else {
echo "Machine";
}
echo "<td>" . $row['policy'];
if ($row['shared'] > 0)
echo "<td>shared";
else
echo "<td>default";
echo "<td><small>" . $row['methods'] . "</small>";
echo "<td>";
$xml = xml_parser_create();
xml_parse_into_struct($xml, $row['devinfo'], $devinfo);
foreach($devinfo as $k) {
if ($k['tag'] == 'DEVID') {
echo "<small>" . $k['value'] . "</small>";
break;
}
}
echo "<td><small>" . $row['mac_addr'] . "</small>";
echo "<td><small>" . $row['t_c_timestamp'] . "</small>";
echo "\n";
}
echo "</table>\n";
}
?>
</html>

2
radius_example/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*.d
radius_example

28
radius_example/Makefile Normal file
View file

@ -0,0 +1,28 @@
ALL=radius_example
include ../src/build.rules
CFLAGS += -I.
CFLAGS += -I../src
CFLAGS += -I../src/utils
LIBS = ../src/radius/libradius.a
LIBS += ../src/crypto/libcrypto.a
LIBS += ../src/utils/libutils.a
LLIBS = -lrt
#CLAGS += -DCONFIG_IPV6
OBJS_ex = radius_example.o
_OBJS_VAR := OBJS_ex
include ../src/objs.mk
_OBJS_VAR := LIBS
include ../src/objs.mk
radius_example: $(OBJS_ex) $(LIBS)
$(LDO) $(LDFLAGS) -o radius_example $(OBJS_ex) $(LIBS) $(LLIBS)
clean: common-clean
rm -f core *~ *.o *.d

35
radius_example/README Normal file
View file

@ -0,0 +1,35 @@
Example application using RADIUS client as a library
Copyright (c) 2007, Jouni Malinen <j@w1.fi>
This software may be distributed under the terms of the BSD license.
See the parent directory README for more details.
This directory contains an example showing how the RADIUS client
functionality from hostapd can be used as a library in another
program. The example program initializes the RADIUS client and send a
Access-Request using User-Name and User-Password attributes. A reply
from the RADIUS authentication server will be processed and it is used
as a trigger to terminate the example program.
The RADIUS library links in couple of helper functions from src/utils and
src/crypto directories. Most of these are suitable as-is, but it may
be desirable to replace the debug output code in src/utils/wpa_debug.c
by dropping this file from the library and re-implementing the
functions there in a way that better fits in with the main
application.
RADIUS client implementation takes care of receiving messages,
timeouts, and retransmissions of packets. Consequently, it requires
functionality for registering timeouts and received packet
notifications. This is implemented using the generic event loop
implementation (see src/utils/eloop.h).
The main application may either use the included event loop
implementation or alternatively, implement eloop_* wrapper functions
to use whatever event loop design is used in the main program. This
would involve removing src/utils/eloop.o from the library and
implementing following functions defines in src/utils/eloop.h:
eloop_register_timeout(), eloop_cancel_timeout(),
eloop_register_read_sock(), eloop_unregister_read_sock(), and
eloop_terminated().

View file

@ -0,0 +1,153 @@
/*
* Example application using RADIUS client as a library
* Copyright (c) 2007, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "eloop.h"
#include "radius/radius.h"
#include "radius/radius_client.h"
struct radius_ctx {
struct radius_client_data *radius;
struct hostapd_radius_servers conf;
u8 radius_identifier;
struct in_addr own_ip_addr;
};
static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
int level, const char *txt, size_t len)
{
printf("%s\n", txt);
}
/* Process the RADIUS frames from Authentication Server */
static RadiusRxResult receive_auth(struct radius_msg *msg,
struct radius_msg *req,
const u8 *shared_secret,
size_t shared_secret_len,
void *data)
{
/* struct radius_ctx *ctx = data; */
printf("Received RADIUS Authentication message; code=%d\n",
radius_msg_get_hdr(msg)->code);
/* We're done for this example, so request eloop to terminate. */
eloop_terminate();
return RADIUS_RX_PROCESSED;
}
static void start_example(void *eloop_ctx, void *timeout_ctx)
{
struct radius_ctx *ctx = eloop_ctx;
struct radius_msg *msg;
printf("Sending a RADIUS authentication message\n");
ctx->radius_identifier = radius_client_get_id(ctx->radius);
msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST,
ctx->radius_identifier);
if (msg == NULL) {
printf("Could not create net RADIUS packet\n");
return;
}
radius_msg_make_authenticator(msg);
if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME,
(u8 *) "user", 4)) {
printf("Could not add User-Name\n");
radius_msg_free(msg);
return;
}
if (!radius_msg_add_attr_user_password(
msg, (u8 *) "password", 8,
ctx->conf.auth_server->shared_secret,
ctx->conf.auth_server->shared_secret_len)) {
printf("Could not add User-Password\n");
radius_msg_free(msg);
return;
}
if (!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
(u8 *) &ctx->own_ip_addr, 4)) {
printf("Could not add NAS-IP-Address\n");
radius_msg_free(msg);
return;
}
if (radius_client_send(ctx->radius, msg, RADIUS_AUTH, NULL) < 0)
radius_msg_free(msg);
}
int main(int argc, char *argv[])
{
struct radius_ctx ctx;
struct hostapd_radius_server *srv;
if (os_program_init())
return -1;
hostapd_logger_register_cb(hostapd_logger_cb);
os_memset(&ctx, 0, sizeof(ctx));
inet_aton("127.0.0.1", &ctx.own_ip_addr);
if (eloop_init()) {
printf("Failed to initialize event loop\n");
return -1;
}
srv = os_zalloc(sizeof(*srv));
if (srv == NULL)
return -1;
srv->addr.af = AF_INET;
srv->port = 1812;
if (hostapd_parse_ip_addr("127.0.0.1", &srv->addr) < 0) {
printf("Failed to parse IP address\n");
return -1;
}
srv->shared_secret = (u8 *) os_strdup("radius");
srv->shared_secret_len = 6;
ctx.conf.auth_server = ctx.conf.auth_servers = srv;
ctx.conf.num_auth_servers = 1;
ctx.conf.msg_dumps = 1;
ctx.radius = radius_client_init(&ctx, &ctx.conf);
if (ctx.radius == NULL) {
printf("Failed to initialize RADIUS client\n");
return -1;
}
if (radius_client_register(ctx.radius, RADIUS_AUTH, receive_auth,
&ctx) < 0) {
printf("Failed to register RADIUS authentication handler\n");
return -1;
}
eloop_register_timeout(0, 0, start_example, &ctx, NULL);
eloop_run();
radius_client_deinit(ctx.radius);
os_free(srv->shared_secret);
os_free(srv);
eloop_destroy();
os_program_deinit();
return 0;
}

View file

@ -5,8 +5,8 @@ all:
for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d; done
clean:
for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d clean; done
rm -f *~
$(Q)for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d clean; done
$(Q)rm -f *~
install:
for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d install; done

View file

@ -1,13 +1,3 @@
all: libap.a
clean:
rm -f *~ *.o *.d *.gcno *.gcda *.gcov libap.a
install:
@echo Nothing to be made.
include ../lib.rules
CFLAGS += -DHOSTAPD
CFLAGS += -DNEED_AP_MLME
CFLAGS += -DCONFIG_ETH_P_OUI
@ -15,11 +5,9 @@ CFLAGS += -DCONFIG_HS20
CFLAGS += -DCONFIG_INTERWORKING
CFLAGS += -DCONFIG_IEEE80211R
CFLAGS += -DCONFIG_IEEE80211R_AP
CFLAGS += -DCONFIG_IEEE80211W
CFLAGS += -DCONFIG_WPS
CFLAGS += -DCONFIG_PROXYARP
CFLAGS += -DCONFIG_IPV6
CFLAGS += -DCONFIG_IAPP
CFLAGS += -DCONFIG_AIRTIME_POLICY
LIB_OBJS= \
@ -42,7 +30,6 @@ LIB_OBJS= \
hostapd.o \
hs20.o \
hw_features.o \
iapp.o \
ieee802_11_auth.o \
ieee802_11.o \
ieee802_11_ht.o \
@ -70,7 +57,4 @@ LIB_OBJS= \
wps_hostapd.o \
x_snoop.o
libap.a: $(LIB_OBJS)
$(AR) crT $@ $?
-include $(OBJS:%.o=%.d)
include ../lib.rules

View file

@ -261,13 +261,13 @@ static void acs_clean_chan_surveys(struct hostapd_channel_data *chan)
}
void acs_cleanup(struct hostapd_iface *iface)
static void acs_cleanup_mode(struct hostapd_hw_modes *mode)
{
int i;
struct hostapd_channel_data *chan;
for (i = 0; i < iface->current_mode->num_channels; i++) {
chan = &iface->current_mode->channels[i];
for (i = 0; i < mode->num_channels; i++) {
chan = &mode->channels[i];
if (chan->flag & HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED)
acs_clean_chan_surveys(chan);
@ -276,6 +276,15 @@ void acs_cleanup(struct hostapd_iface *iface)
chan->flag |= HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED;
chan->min_nf = 0;
}
}
void acs_cleanup(struct hostapd_iface *iface)
{
int i;
for (i = 0; i < iface->num_hw_features; i++)
acs_cleanup_mode(&iface->hw_features[i]);
iface->chans_surveyed = 0;
iface->acs_num_completed_scans = 0;
@ -453,21 +462,35 @@ static int acs_survey_list_is_sufficient(struct hostapd_channel_data *chan)
}
static int acs_surveys_are_sufficient(struct hostapd_iface *iface)
static int acs_surveys_are_sufficient_mode(struct hostapd_hw_modes *mode)
{
int i;
struct hostapd_channel_data *chan;
int valid = 0;
for (i = 0; i < iface->current_mode->num_channels; i++) {
chan = &iface->current_mode->channels[i];
for (i = 0; i < mode->num_channels; i++) {
chan = &mode->channels[i];
if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
acs_survey_list_is_sufficient(chan))
valid++;
return 1;
}
/* We need at least survey data for one channel */
return !!valid;
return 0;
}
static int acs_surveys_are_sufficient(struct hostapd_iface *iface)
{
int i;
struct hostapd_hw_modes *mode;
for (i = 0; i < iface->num_hw_features; i++) {
mode = &iface->hw_features[i];
if (!hostapd_hw_skip_mode(iface, mode) &&
acs_surveys_are_sufficient_mode(mode))
return 1;
}
return 0;
}
@ -489,14 +512,25 @@ static int is_in_chanlist(struct hostapd_iface *iface,
}
static void acs_survey_all_chans_intereference_factor(
struct hostapd_iface *iface)
static int is_in_freqlist(struct hostapd_iface *iface,
struct hostapd_channel_data *chan)
{
if (!iface->conf->acs_freq_list.num)
return 1;
return freq_range_list_includes(&iface->conf->acs_freq_list,
chan->freq);
}
static void acs_survey_mode_interference_factor(
struct hostapd_iface *iface, struct hostapd_hw_modes *mode)
{
int i;
struct hostapd_channel_data *chan;
for (i = 0; i < iface->current_mode->num_channels; i++) {
chan = &iface->current_mode->channels[i];
for (i = 0; i < mode->num_channels; i++) {
chan = &mode->channels[i];
if (!acs_usable_chan(chan))
continue;
@ -504,6 +538,9 @@ static void acs_survey_all_chans_intereference_factor(
if (!is_in_chanlist(iface, chan))
continue;
if (!is_in_freqlist(iface, chan))
continue;
wpa_printf(MSG_DEBUG, "ACS: Survey analysis for channel %d (%d MHz)",
chan->chan, chan->freq);
@ -515,14 +552,28 @@ static void acs_survey_all_chans_intereference_factor(
}
static struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface,
int freq)
static void acs_survey_all_chans_interference_factor(
struct hostapd_iface *iface)
{
int i;
struct hostapd_hw_modes *mode;
for (i = 0; i < iface->num_hw_features; i++) {
mode = &iface->hw_features[i];
if (!hostapd_hw_skip_mode(iface, mode))
acs_survey_mode_interference_factor(iface, mode);
}
}
static struct hostapd_channel_data *
acs_find_chan_mode(struct hostapd_hw_modes *mode, int freq)
{
struct hostapd_channel_data *chan;
int i;
for (i = 0; i < iface->current_mode->num_channels; i++) {
chan = &iface->current_mode->channels[i];
for (i = 0; i < mode->num_channels; i++) {
chan = &mode->channels[i];
if (chan->flag & HOSTAPD_CHAN_DISABLED)
continue;
@ -535,6 +586,26 @@ static struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface,
}
static struct hostapd_channel_data *
acs_find_chan(struct hostapd_iface *iface, int freq)
{
int i;
struct hostapd_hw_modes *mode;
struct hostapd_channel_data *chan;
for (i = 0; i < iface->num_hw_features; i++) {
mode = &iface->hw_features[i];
if (!hostapd_hw_skip_mode(iface, mode)) {
chan = acs_find_chan_mode(mode, freq);
if (chan)
return chan;
}
}
return NULL;
}
static int is_24ghz_mode(enum hostapd_hw_mode mode)
{
return mode == HOSTAPD_MODE_IEEE80211B ||
@ -565,58 +636,24 @@ static int is_common_24ghz_chan(int chan)
#define ACS_24GHZ_PREFER_1_6_11 0.8
#endif /* ACS_24GHZ_PREFER_1_6_11 */
/*
* At this point it's assumed chan->interface_factor has been computed.
* This function should be reusable regardless of interference computation
* option (survey, BSS, spectral, ...). chan->interference factor must be
* summable (i.e., must be always greater than zero).
*/
static struct hostapd_channel_data *
acs_find_ideal_chan(struct hostapd_iface *iface)
static void
acs_find_ideal_chan_mode(struct hostapd_iface *iface,
struct hostapd_hw_modes *mode,
int n_chans, u32 bw,
struct hostapd_channel_data **rand_chan,
struct hostapd_channel_data **ideal_chan,
long double *ideal_factor)
{
struct hostapd_channel_data *chan, *adj_chan, *ideal_chan = NULL,
*rand_chan = NULL;
long double factor, ideal_factor = 0;
struct hostapd_channel_data *chan, *adj_chan = NULL;
long double factor;
int i, j;
int n_chans = 1;
u32 bw;
unsigned int k;
/* TODO: HT40- support */
if (iface->conf->ieee80211n &&
iface->conf->secondary_channel == -1) {
wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+");
return NULL;
}
if (iface->conf->ieee80211n &&
iface->conf->secondary_channel)
n_chans = 2;
if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
switch (hostapd_get_oper_chwidth(iface->conf)) {
case CHANWIDTH_80MHZ:
n_chans = 4;
break;
case CHANWIDTH_160MHZ:
n_chans = 8;
break;
}
}
bw = num_chan_to_bw(n_chans);
/* TODO: VHT/HE80+80. Update acs_adjust_center_freq() too. */
wpa_printf(MSG_DEBUG,
"ACS: Survey analysis for selected bandwidth %d MHz", bw);
for (i = 0; i < iface->current_mode->num_channels; i++) {
for (i = 0; i < mode->num_channels; i++) {
double total_weight;
struct acs_bias *bias, tmp_bias;
chan = &iface->current_mode->channels[i];
chan = &mode->channels[i];
/* Since in the current ACS implementation the first channel is
* always a primary channel, skip channels not available as
@ -628,6 +665,9 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
if (!is_in_chanlist(iface, chan))
continue;
if (!is_in_freqlist(iface, chan))
continue;
if (!chan_bw_allowed(chan, bw, 1, 1)) {
wpa_printf(MSG_DEBUG,
"ACS: Channel %d: BW %u is not supported",
@ -637,7 +677,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
/* HT40 on 5 GHz has a limited set of primary channels as per
* 11n Annex J */
if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
iface->conf->ieee80211n &&
iface->conf->secondary_channel &&
!acs_usable_ht40_chan(chan)) {
@ -646,7 +686,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
continue;
}
if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
(iface->conf->ieee80211ac || iface->conf->ieee80211ax)) {
if (hostapd_get_oper_chwidth(iface->conf) ==
CHANWIDTH_80MHZ &&
@ -698,7 +738,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
/* 2.4 GHz has overlapping 20 MHz channels. Include adjacent
* channel interference factor. */
if (is_24ghz_mode(iface->current_mode->mode)) {
if (is_24ghz_mode(mode->mode)) {
for (j = 0; j < n_chans; j++) {
adj_chan = acs_find_chan(iface, chan->freq +
(j * 20) - 5);
@ -744,7 +784,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
break;
bias = NULL;
}
} else if (is_24ghz_mode(iface->current_mode->mode) &&
} else if (is_24ghz_mode(mode->mode) &&
is_common_24ghz_chan(chan->chan)) {
tmp_bias.channel = chan->chan;
tmp_bias.bias = ACS_24GHZ_PREFER_1_6_11;
@ -763,14 +803,71 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
}
if (acs_usable_chan(chan) &&
(!ideal_chan || factor < ideal_factor)) {
ideal_factor = factor;
ideal_chan = chan;
(!*ideal_chan || factor < *ideal_factor)) {
*ideal_factor = factor;
*ideal_chan = chan;
}
/* This channel would at least be usable */
if (!rand_chan)
rand_chan = chan;
if (!(*rand_chan))
*rand_chan = chan;
}
}
/*
* At this point it's assumed chan->interference_factor has been computed.
* This function should be reusable regardless of interference computation
* option (survey, BSS, spectral, ...). chan->interference factor must be
* summable (i.e., must be always greater than zero).
*/
static struct hostapd_channel_data *
acs_find_ideal_chan(struct hostapd_iface *iface)
{
struct hostapd_channel_data *ideal_chan = NULL,
*rand_chan = NULL;
long double ideal_factor = 0;
int i;
int n_chans = 1;
u32 bw;
struct hostapd_hw_modes *mode;
/* TODO: HT40- support */
if (iface->conf->ieee80211n &&
iface->conf->secondary_channel == -1) {
wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+");
return NULL;
}
if (iface->conf->ieee80211n &&
iface->conf->secondary_channel)
n_chans = 2;
if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
switch (hostapd_get_oper_chwidth(iface->conf)) {
case CHANWIDTH_80MHZ:
n_chans = 4;
break;
case CHANWIDTH_160MHZ:
n_chans = 8;
break;
}
}
bw = num_chan_to_bw(n_chans);
/* TODO: VHT/HE80+80. Update acs_adjust_center_freq() too. */
wpa_printf(MSG_DEBUG,
"ACS: Survey analysis for selected bandwidth %d MHz", bw);
for (i = 0; i < iface->num_hw_features; i++) {
mode = &iface->hw_features[i];
if (!hostapd_hw_skip_mode(iface, mode))
acs_find_ideal_chan_mode(iface, mode, n_chans, bw,
&rand_chan, &ideal_chan,
&ideal_factor);
}
if (ideal_chan) {
@ -826,7 +923,7 @@ static int acs_study_survey_based(struct hostapd_iface *iface)
return -1;
}
acs_survey_all_chans_intereference_factor(iface);
acs_survey_all_chans_interference_factor(iface);
return 0;
}
@ -862,6 +959,7 @@ static void acs_study(struct hostapd_iface *iface)
}
iface->conf->channel = ideal_chan->chan;
iface->freq = ideal_chan->freq;
if (iface->conf->ieee80211ac || iface->conf->ieee80211ax)
acs_adjust_center_freq(iface);
@ -917,31 +1015,67 @@ static void acs_scan_complete(struct hostapd_iface *iface)
}
static int acs_request_scan(struct hostapd_iface *iface)
static int * acs_request_scan_add_freqs(struct hostapd_iface *iface,
struct hostapd_hw_modes *mode,
int *freq)
{
struct wpa_driver_scan_params params;
struct hostapd_channel_data *chan;
int i, *freq;
int i;
os_memset(&params, 0, sizeof(params));
params.freqs = os_calloc(iface->current_mode->num_channels + 1,
sizeof(params.freqs[0]));
if (params.freqs == NULL)
return -1;
freq = params.freqs;
for (i = 0; i < iface->current_mode->num_channels; i++) {
chan = &iface->current_mode->channels[i];
for (i = 0; i < mode->num_channels; i++) {
chan = &mode->channels[i];
if (chan->flag & HOSTAPD_CHAN_DISABLED)
continue;
if (!is_in_chanlist(iface, chan))
continue;
if (!is_in_freqlist(iface, chan))
continue;
*freq++ = chan->freq;
}
return freq;
}
static int acs_request_scan(struct hostapd_iface *iface)
{
struct wpa_driver_scan_params params;
int i, *freq;
int num_channels;
struct hostapd_hw_modes *mode;
os_memset(&params, 0, sizeof(params));
num_channels = 0;
for (i = 0; i < iface->num_hw_features; i++) {
mode = &iface->hw_features[i];
if (!hostapd_hw_skip_mode(iface, mode))
num_channels += mode->num_channels;
}
params.freqs = os_calloc(num_channels + 1, sizeof(params.freqs[0]));
if (params.freqs == NULL)
return -1;
freq = params.freqs;
for (i = 0; i < iface->num_hw_features; i++) {
mode = &iface->hw_features[i];
if (!hostapd_hw_skip_mode(iface, mode))
freq = acs_request_scan_add_freqs(iface, mode, freq);
}
*freq = 0;
if (params.freqs == freq) {
wpa_printf(MSG_ERROR, "ACS: No available channels found");
os_free(params.freqs);
return -1;
}
iface->scan_cb = acs_scan_complete;
wpa_printf(MSG_DEBUG, "ACS: Scanning %d / %d",
@ -971,7 +1105,8 @@ enum hostapd_chan_status acs_init(struct hostapd_iface *iface)
return HOSTAPD_CHAN_ACS;
}
if (!iface->current_mode)
if (!iface->current_mode &&
iface->conf->hw_mode != HOSTAPD_MODE_IEEE80211ANY)
return HOSTAPD_CHAN_INVALID;
acs_cleanup(iface);

View file

@ -134,8 +134,8 @@ static void update_airtime_weights(void *eloop_data, void *user_data)
unsigned int num_sta_min = 0, num_sta_prod = 1, num_sta_sum = 0,
wt_sum = 0;
unsigned int quantum;
Boolean all_div_min = TRUE;
Boolean apply_limit = iface->conf->airtime_mode == AIRTIME_MODE_DYNAMIC;
bool all_div_min = true;
bool apply_limit = iface->conf->airtime_mode == AIRTIME_MODE_DYNAMIC;
int wt, num_bss = 0, max_wt = 0;
size_t i;
@ -169,7 +169,7 @@ static void update_airtime_weights(void *eloop_data, void *user_data)
* integers. */
if (bss->num_backlogged_sta &&
bss->num_backlogged_sta % num_sta_min > 0)
all_div_min = FALSE;
all_div_min = false;
/* If we're in LIMIT mode, we only apply the weight
* scaling when the BSS(es) marked as limited would a
@ -178,7 +178,7 @@ static void update_airtime_weights(void *eloop_data, void *user_data)
if (!apply_limit && bss->conf->airtime_limit) {
if (bss->num_backlogged_sta * wt_sum >
bss->conf->airtime_weight * num_sta_sum)
apply_limit = TRUE;
apply_limit = true;
}
}
if (all_div_min)

View file

@ -16,6 +16,7 @@
#include "common/ieee802_1x_defs.h"
#include "common/eapol_common.h"
#include "common/dhcp.h"
#include "common/sae.h"
#include "eap_common/eap_wsc_common.h"
#include "eap_server/eap.h"
#include "wpa_auth.h"
@ -53,23 +54,33 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
bss->logger_syslog = (unsigned int) -1;
bss->logger_stdout = (unsigned int) -1;
#ifdef CONFIG_WEP
bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED;
bss->wep_rekeying_period = 300;
/* use key0 in individual key and key1 in broadcast key */
bss->broadcast_key_idx_min = 1;
bss->broadcast_key_idx_max = 2;
#else /* CONFIG_WEP */
bss->auth_algs = WPA_AUTH_ALG_OPEN;
#endif /* CONFIG_WEP */
bss->eap_reauth_period = 3600;
bss->wpa_group_rekey = 600;
bss->wpa_gmk_rekey = 86400;
bss->wpa_deny_ptk0_rekey = PTK0_REKEY_ALLOW_ALWAYS;
bss->wpa_group_update_count = 4;
bss->wpa_pairwise_update_count = 4;
bss->wpa_disable_eapol_key_retries =
DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES;
bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
#ifdef CONFIG_NO_TKIP
bss->wpa_pairwise = WPA_CIPHER_CCMP;
bss->wpa_group = WPA_CIPHER_CCMP;
#else /* CONFIG_NO_TKIP */
bss->wpa_pairwise = WPA_CIPHER_TKIP;
bss->wpa_group = WPA_CIPHER_TKIP;
#endif /* CONFIG_NO_TKIP */
bss->rsn_pairwise = 0;
bss->max_num_sta = MAX_STA_COUNT;
@ -86,11 +97,9 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
bss->pwd_group = 19; /* ECC: GF(p=256) */
#ifdef CONFIG_IEEE80211W
bss->assoc_sa_query_max_timeout = 1000;
bss->assoc_sa_query_retry_timeout = 201;
bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
#endif /* CONFIG_IEEE80211W */
#ifdef EAP_SERVER_FAST
/* both anonymous and authenticated provisioning */
bss->eap_fast_prov = 3;
@ -112,7 +121,7 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
bss->radius_das_time_window = 300;
bss->sae_anti_clogging_threshold = 5;
bss->anti_clogging_threshold = 5;
bss->sae_sync = 5;
bss->gas_frag_limit = 1400;
@ -122,6 +131,7 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
bss->fils_hlp_wait_time = 30;
bss->dhcp_server_port = DHCP_SERVER_PORT;
bss->dhcp_relay_port = DHCP_SERVER_PORT;
bss->fils_discovery_min_int = 20;
#endif /* CONFIG_FILS */
bss->broadcast_deauth = 1;
@ -135,6 +145,9 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
* completed and tested with other implementations. */
bss->tls_flags = TLS_CONN_DISABLE_TLSv1_3;
bss->max_auth_rounds = 100;
bss->max_auth_rounds_short = 50;
bss->send_probe_response = 1;
#ifdef CONFIG_HS20
@ -148,6 +161,10 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
/* Default to strict CRL checking. */
bss->check_crl_strict = 1;
#ifdef CONFIG_TESTING_OPTIONS
bss->sae_commit_status = -1;
#endif /* CONFIG_TESTING_OPTIONS */
}
@ -249,6 +266,13 @@ struct hostapd_config * hostapd_config_defaults(void)
HE_OPERATION_RTS_THRESHOLD_OFFSET;
/* Set default basic MCS/NSS set to single stream MCS 0-7 */
conf->he_op.he_basic_mcs_nss_set = 0xfffc;
conf->he_op.he_bss_color_disabled = 1;
conf->he_op.he_bss_color_partial = 0;
conf->he_op.he_bss_color = 1;
conf->he_6ghz_max_mpdu = 2;
conf->he_6ghz_max_ampdu_len_exp = 7;
conf->he_6ghz_rx_ant_pat = 1;
conf->he_6ghz_tx_ant_pat = 1;
#endif /* CONFIG_IEEE80211AX */
/* The third octet of the country string uses an ASCII space character
@ -299,6 +323,7 @@ static int hostapd_config_read_wpa_psk(const char *fname,
while (fgets(buf, sizeof(buf), f)) {
int vlan_id = 0;
int wps = 0;
line++;
@ -329,6 +354,8 @@ static int hostapd_config_read_wpa_psk(const char *fname,
value = "";
if (!os_strcmp(name, "keyid")) {
keyid = value;
} else if (!os_strcmp(name, "wps")) {
wps = atoi(value);
} else if (!os_strcmp(name, "vlanid")) {
vlan_id = atoi(value);
} else {
@ -346,8 +373,9 @@ static int hostapd_config_read_wpa_psk(const char *fname,
if (!token)
token = "";
if (hwaddr_aton(token, addr)) {
wpa_printf(MSG_ERROR, "Invalid MAC address '%s' on "
"line %d in '%s'", token, line, fname);
wpa_printf(MSG_ERROR,
"Invalid MAC address '%s' on line %d in '%s'",
token, line, fname);
ret = -1;
break;
}
@ -375,16 +403,17 @@ static int hostapd_config_read_wpa_psk(const char *fname,
ok = 0;
len = os_strlen(pos);
if (len == 64 && hexstr2bin(pos, psk->psk, PMK_LEN) == 0)
if (len == 2 * PMK_LEN &&
hexstr2bin(pos, psk->psk, PMK_LEN) == 0)
ok = 1;
else if (len >= 8 && len < 64) {
pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len,
4096, psk->psk, PMK_LEN);
else if (len >= 8 && len < 64 &&
pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len,
4096, psk->psk, PMK_LEN) == 0)
ok = 1;
}
if (!ok) {
wpa_printf(MSG_ERROR, "Invalid PSK '%s' on line %d in "
"'%s'", pos, line, fname);
wpa_printf(MSG_ERROR,
"Invalid PSK '%s' on line %d in '%s'",
pos, line, fname);
os_free(psk);
ret = -1;
break;
@ -402,6 +431,8 @@ static int hostapd_config_read_wpa_psk(const char *fname,
}
}
psk->wps = wps;
psk->next = ssid->wpa_psk;
ssid->wpa_psk = psk;
}
@ -433,10 +464,53 @@ static int hostapd_derive_psk(struct hostapd_ssid *ssid)
}
int hostapd_setup_sae_pt(struct hostapd_bss_config *conf)
{
#ifdef CONFIG_SAE
struct hostapd_ssid *ssid = &conf->ssid;
struct sae_password_entry *pw;
if ((conf->sae_pwe == 0 && !hostapd_sae_pw_id_in_use(conf) &&
!hostapd_sae_pk_in_use(conf)) ||
conf->sae_pwe == 3 ||
!wpa_key_mgmt_sae(conf->wpa_key_mgmt))
return 0; /* PT not needed */
sae_deinit_pt(ssid->pt);
ssid->pt = NULL;
if (ssid->wpa_passphrase) {
ssid->pt = sae_derive_pt(conf->sae_groups, ssid->ssid,
ssid->ssid_len,
(const u8 *) ssid->wpa_passphrase,
os_strlen(ssid->wpa_passphrase),
NULL);
if (!ssid->pt)
return -1;
}
for (pw = conf->sae_passwords; pw; pw = pw->next) {
sae_deinit_pt(pw->pt);
pw->pt = sae_derive_pt(conf->sae_groups, ssid->ssid,
ssid->ssid_len,
(const u8 *) pw->password,
os_strlen(pw->password),
pw->identifier);
if (!pw->pt)
return -1;
}
#endif /* CONFIG_SAE */
return 0;
}
int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf)
{
struct hostapd_ssid *ssid = &conf->ssid;
if (hostapd_setup_sae_pt(conf) < 0)
return -1;
if (ssid->wpa_passphrase != NULL) {
if (ssid->wpa_psk != NULL) {
wpa_printf(MSG_DEBUG, "Using pre-configured WPA PSK "
@ -581,6 +655,7 @@ void hostapd_config_free_eap_users(struct hostapd_eap_user *user)
}
#ifdef CONFIG_WEP
static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
{
int i;
@ -589,6 +664,7 @@ static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
keys->key[i] = NULL;
}
}
#endif /* CONFIG_WEP */
void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **l)
@ -642,6 +718,12 @@ static void hostapd_config_free_sae_passwords(struct hostapd_bss_config *conf)
pw = pw->next;
str_clear_free(tmp->password);
os_free(tmp->identifier);
#ifdef CONFIG_SAE
sae_deinit_pt(tmp->pt);
#endif /* CONFIG_SAE */
#ifdef CONFIG_SAE_PK
sae_deinit_pk(tmp->pk);
#endif /* CONFIG_SAE_PK */
os_free(tmp);
}
}
@ -674,10 +756,15 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
str_clear_free(conf->ssid.wpa_passphrase);
os_free(conf->ssid.wpa_psk_file);
#ifdef CONFIG_WEP
hostapd_config_free_wep(&conf->ssid.wep);
#endif /* CONFIG_WEP */
#ifdef CONFIG_FULL_DYNAMIC_VLAN
os_free(conf->ssid.vlan_tagged_interface);
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
#ifdef CONFIG_SAE
sae_deinit_pt(conf->ssid.pt);
#endif /* CONFIG_SAE */
hostapd_config_free_eap_users(conf->eap_user);
os_free(conf->eap_user_sqlite);
@ -692,6 +779,7 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
conf->radius->num_auth_servers);
hostapd_config_free_radius(conf->radius->acct_servers,
conf->radius->num_acct_servers);
os_free(conf->radius->force_client_dev);
}
hostapd_config_free_radius_attr(conf->radius_auth_req_attr);
hostapd_config_free_radius_attr(conf->radius_acct_req_attr);
@ -765,6 +853,7 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
os_free(conf->upc);
for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
wpabuf_free(conf->wps_vendor_ext[i]);
wpabuf_free(conf->wps_application_ext);
wpabuf_free(conf->wps_nfc_dh_pubkey);
wpabuf_free(conf->wps_nfc_dh_privkey);
wpabuf_free(conf->wps_nfc_dev_pw);
@ -832,6 +921,12 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
#ifdef CONFIG_TESTING_OPTIONS
wpabuf_free(conf->own_ie_override);
wpabuf_free(conf->sae_commit_override);
wpabuf_free(conf->rsne_override_eapol);
wpabuf_free(conf->rsnxe_override_eapol);
wpabuf_free(conf->rsne_override_ft);
wpabuf_free(conf->rsnxe_override_ft);
wpabuf_free(conf->gtk_rsc_override);
wpabuf_free(conf->igtk_rsc_override);
#endif /* CONFIG_TESTING_OPTIONS */
os_free(conf->no_probe_resp_if_seen_on);
@ -840,6 +935,8 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
hostapd_config_free_fils_realms(conf);
#ifdef CONFIG_DPP
os_free(conf->dpp_name);
os_free(conf->dpp_mud_url);
os_free(conf->dpp_connector);
wpabuf_free(conf->dpp_netaccesskey);
wpabuf_free(conf->dpp_csign);
@ -864,6 +961,10 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
}
#endif /* CONFIG_AIRTIME_POLICY */
#ifdef CONFIG_PASN
os_free(conf->pasn_groups);
#endif /* CONFIG_PASN */
os_free(conf);
}
@ -885,6 +986,7 @@ void hostapd_config_free(struct hostapd_config *conf)
os_free(conf->supported_rates);
os_free(conf->basic_rates);
os_free(conf->acs_ch_list.range);
os_free(conf->acs_freq_list.range);
os_free(conf->driver_params);
#ifdef CONFIG_ACS
os_free(conf->acs_chan_bias);
@ -1027,10 +1129,85 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
}
#ifdef CONFIG_SAE_PK
static bool hostapd_sae_pk_password_without_pk(struct hostapd_bss_config *bss)
{
struct sae_password_entry *pw;
bool res = false;
if (bss->ssid.wpa_passphrase &&
#ifdef CONFIG_TESTING_OPTIONS
!bss->sae_pk_password_check_skip &&
#endif /* CONFIG_TESTING_OPTIONS */
sae_pk_valid_password(bss->ssid.wpa_passphrase))
res = true;
for (pw = bss->sae_passwords; pw; pw = pw->next) {
if (!pw->pk &&
#ifdef CONFIG_TESTING_OPTIONS
!bss->sae_pk_password_check_skip &&
#endif /* CONFIG_TESTING_OPTIONS */
sae_pk_valid_password(pw->password))
return true;
if (bss->ssid.wpa_passphrase && res && pw->pk &&
os_strcmp(bss->ssid.wpa_passphrase, pw->password) == 0)
res = false;
}
return res;
}
#endif /* CONFIG_SAE_PK */
static bool hostapd_config_check_bss_6g(struct hostapd_bss_config *bss)
{
if (bss->wpa != WPA_PROTO_RSN) {
wpa_printf(MSG_ERROR,
"Pre-RSNA security methods are not allowed in 6 GHz");
return false;
}
if (bss->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED) {
wpa_printf(MSG_ERROR,
"Management frame protection is required in 6 GHz");
return false;
}
if (bss->wpa_key_mgmt & (WPA_KEY_MGMT_PSK |
WPA_KEY_MGMT_FT_PSK |
WPA_KEY_MGMT_PSK_SHA256)) {
wpa_printf(MSG_ERROR, "Invalid AKM suite for 6 GHz");
return false;
}
if (bss->rsn_pairwise & (WPA_CIPHER_WEP40 |
WPA_CIPHER_WEP104 |
WPA_CIPHER_TKIP)) {
wpa_printf(MSG_ERROR,
"Invalid pairwise cipher suite for 6 GHz");
return false;
}
if (bss->wpa_group & (WPA_CIPHER_WEP40 |
WPA_CIPHER_WEP104 |
WPA_CIPHER_TKIP)) {
wpa_printf(MSG_ERROR, "Invalid group cipher suite for 6 GHz");
return false;
}
return true;
}
static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
struct hostapd_config *conf,
int full_config)
{
if (full_config && is_6ghz_op_class(conf->op_class) &&
!hostapd_config_check_bss_6g(bss))
return -1;
if (full_config && bss->ieee802_1x && !bss->eap_server &&
!bss->radius->auth_servers) {
wpa_printf(MSG_ERROR, "Invalid IEEE 802.1X configuration (no "
@ -1038,6 +1215,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
return -1;
}
#ifdef CONFIG_WEP
if (bss->wpa) {
int wep, i;
@ -1055,6 +1233,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
return -1;
}
}
#endif /* CONFIG_WEP */
if (full_config && bss->wpa &&
bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
@ -1102,52 +1281,75 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
}
#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_IEEE80211N
if (full_config && conf->ieee80211n &&
conf->hw_mode == HOSTAPD_MODE_IEEE80211B) {
bss->disable_11n = 1;
bss->disable_11n = true;
wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not "
"allowed, disabling HT capabilities");
}
#ifdef CONFIG_WEP
if (full_config && conf->ieee80211n &&
bss->ssid.security_policy == SECURITY_STATIC_WEP) {
bss->disable_11n = 1;
bss->disable_11n = true;
wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not "
"allowed, disabling HT capabilities");
}
#endif /* CONFIG_WEP */
if (full_config && conf->ieee80211n && bss->wpa &&
!(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
!(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256)))
{
bss->disable_11n = 1;
bss->disable_11n = true;
wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 "
"requires CCMP/GCMP to be enabled, disabling HT "
"capabilities");
}
#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_IEEE80211AC
#ifdef CONFIG_WEP
if (full_config && conf->ieee80211ac &&
bss->ssid.security_policy == SECURITY_STATIC_WEP) {
bss->disable_11ac = 1;
bss->disable_11ac = true;
wpa_printf(MSG_ERROR,
"VHT (IEEE 802.11ac) with WEP is not allowed, disabling VHT capabilities");
}
#endif /* CONFIG_WEP */
if (full_config && conf->ieee80211ac && bss->wpa &&
!(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
!(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256)))
{
bss->disable_11ac = 1;
bss->disable_11ac = true;
wpa_printf(MSG_ERROR,
"VHT (IEEE 802.11ac) with WPA/WPA2 requires CCMP/GCMP to be enabled, disabling VHT capabilities");
}
#endif /* CONFIG_IEEE80211AC */
#ifdef CONFIG_IEEE80211AX
#ifdef CONFIG_WEP
if (full_config && conf->ieee80211ax &&
bss->ssid.security_policy == SECURITY_STATIC_WEP) {
bss->disable_11ax = true;
wpa_printf(MSG_ERROR,
"HE (IEEE 802.11ax) with WEP is not allowed, disabling HE capabilities");
}
#endif /* CONFIG_WEP */
if (full_config && conf->ieee80211ax && bss->wpa &&
!(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
!(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256)))
{
bss->disable_11ax = true;
wpa_printf(MSG_ERROR,
"HE (IEEE 802.11ax) with WPA/WPA2 requires CCMP/GCMP to be enabled, disabling HE capabilities");
}
#endif /* CONFIG_IEEE80211AX */
#ifdef CONFIG_WPS
if (full_config && bss->wps_state && bss->ignore_broadcast_ssid) {
wpa_printf(MSG_INFO, "WPS: ignore_broadcast_ssid "
@ -1155,12 +1357,14 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
bss->wps_state = 0;
}
#ifdef CONFIG_WEP
if (full_config && bss->wps_state &&
bss->ssid.wep.keys_set && bss->wpa == 0) {
wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be "
"disabled");
bss->wps_state = 0;
}
#endif /* CONFIG_WEP */
if (full_config && bss->wps_state && bss->wpa &&
(!(bss->wpa & 2) ||
@ -1204,6 +1408,15 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
}
#endif /* CONFIG_OCV */
#ifdef CONFIG_SAE_PK
if (full_config && hostapd_sae_pk_in_use(bss) &&
hostapd_sae_pk_password_without_pk(bss)) {
wpa_printf(MSG_ERROR,
"SAE-PK: SAE password uses SAE-PK style, but does not have PK configured");
return -1;
}
#endif /* CONFIG_SAE_PK */
return 0;
}
@ -1284,11 +1497,13 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config)
void hostapd_set_security_params(struct hostapd_bss_config *bss,
int full_config)
{
#ifdef CONFIG_WEP
if (bss->individual_wep_key_len == 0) {
/* individual keys are not use; can use key idx0 for
* broadcast keys */
bss->broadcast_key_idx_min = 0;
}
#endif /* CONFIG_WEP */
if ((bss->wpa & 2) && bss->rsn_pairwise == 0)
bss->rsn_pairwise = bss->wpa_pairwise;
@ -1314,6 +1529,7 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss,
} else if (bss->ieee802_1x) {
int cipher = WPA_CIPHER_NONE;
bss->ssid.security_policy = SECURITY_IEEE_802_1X;
#ifdef CONFIG_WEP
bss->ssid.wep.default_len = bss->default_wep_key_len;
if (full_config && bss->default_wep_key_len) {
cipher = bss->default_wep_key_len >= 13 ?
@ -1324,11 +1540,13 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss,
else
cipher = WPA_CIPHER_WEP40;
}
#endif /* CONFIG_WEP */
bss->wpa_group = cipher;
bss->wpa_pairwise = cipher;
bss->rsn_pairwise = cipher;
if (full_config)
bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
#ifdef CONFIG_WEP
} else if (bss->ssid.wep.keys_set) {
int cipher = WPA_CIPHER_WEP40;
if (bss->ssid.wep.len[0] >= 13)
@ -1339,6 +1557,7 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss,
bss->rsn_pairwise = cipher;
if (full_config)
bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE;
#endif /* CONFIG_WEP */
} else if (bss->osen) {
bss->ssid.security_policy = SECURITY_OSEN;
bss->wpa_group = WPA_CIPHER_CCMP;
@ -1377,3 +1596,38 @@ int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf)
return 2;
return with_id;
}
bool hostapd_sae_pk_in_use(struct hostapd_bss_config *conf)
{
#ifdef CONFIG_SAE_PK
struct sae_password_entry *pw;
for (pw = conf->sae_passwords; pw; pw = pw->next) {
if (pw->pk)
return true;
}
#endif /* CONFIG_SAE_PK */
return false;
}
#ifdef CONFIG_SAE_PK
bool hostapd_sae_pk_exclusively(struct hostapd_bss_config *conf)
{
bool with_pk = false;
struct sae_password_entry *pw;
if (conf->ssid.wpa_passphrase)
return false;
for (pw = conf->sae_passwords; pw; pw = pw->next) {
if (!pw->pk)
return false;
with_pk = true;
}
return with_pk;
}
#endif /* CONFIG_SAE_PK */

View file

@ -67,6 +67,7 @@ struct hostapd_radius_servers;
struct ft_remote_r0kh;
struct ft_remote_r1kh;
#ifdef CONFIG_WEP
#define NUM_WEP_KEYS 4
struct hostapd_wep_keys {
u8 idx;
@ -75,10 +76,13 @@ struct hostapd_wep_keys {
int keys_set;
size_t default_len; /* key length used for dynamic key generation */
};
#endif /* CONFIG_WEP */
typedef enum hostap_security_policy {
SECURITY_PLAINTEXT = 0,
#ifdef CONFIG_WEP
SECURITY_STATIC_WEP = 1,
#endif /* CONFIG_WEP */
SECURITY_IEEE_802_1X = 2,
SECURITY_WPA_PSK = 3,
SECURITY_WPA = 4,
@ -88,6 +92,7 @@ typedef enum hostap_security_policy {
struct hostapd_ssid {
u8 ssid[SSID_MAX_LEN];
size_t ssid_len;
u32 short_ssid;
unsigned int ssid_set:1;
unsigned int utf8_ssid:1;
unsigned int wpa_passphrase_set:1;
@ -99,8 +104,11 @@ struct hostapd_ssid {
struct hostapd_wpa_psk *wpa_psk;
char *wpa_passphrase;
char *wpa_psk_file;
struct sae_pt *pt;
#ifdef CONFIG_WEP
struct hostapd_wep_keys wep;
#endif /* CONFIG_WEP */
#define DYNAMIC_VLAN_DISABLED 0
#define DYNAMIC_VLAN_OPTIONAL 1
@ -150,6 +158,7 @@ struct hostapd_wpa_psk {
struct hostapd_wpa_psk *next;
int group;
char keyid[KEYID_LEN];
int wps;
u8 psk[PMK_LEN];
u8 addr[ETH_ALEN];
u8 p2p_dev_addr[ETH_ALEN];
@ -188,15 +197,6 @@ struct hostapd_radius_attr {
#define NUM_TX_QUEUES 4
struct hostapd_tx_queue_params {
int aifs;
int cwmin;
int cwmax;
int burst; /* maximum burst time in 0.1 ms, i.e., 10 = 1 ms */
};
#define MAX_ROAMING_CONSORTIUM_LEN 15
struct hostapd_roaming_consortium {
@ -251,6 +251,8 @@ struct sae_password_entry {
char *identifier;
u8 peer_addr[ETH_ALEN];
int vlan_id;
struct sae_pt *pt;
struct sae_pk *pk;
};
struct dpp_controller_conf {
@ -317,18 +319,16 @@ struct hostapd_bss_config {
size_t eap_req_id_text_len;
int eapol_key_index_workaround;
#ifdef CONFIG_WEP
size_t default_wep_key_len;
int individual_wep_key_len;
int wep_rekeying_period;
int broadcast_key_idx_min, broadcast_key_idx_max;
#endif /* CONFIG_WEP */
int eap_reauth_period;
int erp_send_reauth_start;
char *erp_domain;
int ieee802_11f; /* use IEEE 802.11f (IAPP) */
char iapp_iface[IFNAMSIZ + 1]; /* interface used with IAPP broadcast
* frames */
enum macaddr_acl {
ACCEPT_UNLESS_DENIED = 0,
DENY_UNLESS_ACCEPTED = 1,
@ -346,15 +346,15 @@ struct hostapd_bss_config {
* algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */
int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */
int extended_key_id;
int wpa_key_mgmt;
#ifdef CONFIG_IEEE80211W
enum mfp_options ieee80211w;
int group_mgmt_cipher;
int beacon_prot;
/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
unsigned int assoc_sa_query_max_timeout;
/* dot11AssociationSAQueryRetryTimeout (in TUs) */
int assoc_sa_query_retry_timeout;
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_OCV
int ocv; /* Operating Channel Validation */
#endif /* CONFIG_OCV */
@ -371,6 +371,7 @@ struct hostapd_bss_config {
int wpa_strict_rekey;
int wpa_gmk_rekey;
int wpa_ptk_rekey;
enum ptk0_rekey_handling wpa_deny_ptk0_rekey;
u32 wpa_group_update_count;
u32 wpa_pairwise_update_count;
int wpa_disable_eapol_key_retries;
@ -415,6 +416,8 @@ struct hostapd_bss_config {
unsigned int crl_reload_interval;
unsigned int tls_session_lifetime;
unsigned int tls_flags;
unsigned int max_auth_rounds;
unsigned int max_auth_rounds_short;
char *ocsp_stapling_response;
char *ocsp_stapling_response_multi;
char *dh_file;
@ -429,6 +432,8 @@ struct hostapd_bss_config {
int pac_key_refresh_time;
int eap_teap_auth;
int eap_teap_pac_no_inner;
int eap_teap_separate_result;
int eap_teap_id;
int eap_sim_aka_result_ind;
int eap_sim_id;
int tnc;
@ -497,6 +502,7 @@ struct hostapd_bss_config {
char *model_url;
char *upc;
struct wpabuf *wps_vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
struct wpabuf *wps_application_ext;
int wps_nfc_pw_from_config;
int wps_nfc_dev_pw_id;
struct wpabuf *wps_nfc_dh_pubkey;
@ -525,8 +531,9 @@ struct hostapd_bss_config {
#define TDLS_PROHIBIT BIT(0)
#define TDLS_PROHIBIT_CHAN_SWITCH BIT(1)
int tdls;
int disable_11n;
int disable_11ac;
bool disable_11n;
bool disable_11ac;
bool disable_11ax;
/* IEEE 802.11v */
int time_advertisement;
@ -648,9 +655,11 @@ struct hostapd_bss_config {
struct wpabuf *vendor_elements;
struct wpabuf *assocresp_elements;
unsigned int sae_anti_clogging_threshold;
unsigned int anti_clogging_threshold;
unsigned int sae_sync;
int sae_require_mfp;
int sae_confirm_immediate;
int sae_pwe;
int *sae_groups;
struct sae_password_entry *sae_passwords;
@ -661,7 +670,26 @@ struct hostapd_bss_config {
u8 bss_load_test_set;
struct wpabuf *own_ie_override;
int sae_reflection_attack;
int sae_commit_status;
int sae_pk_omit;
int sae_pk_password_check_skip;
struct wpabuf *sae_commit_override;
struct wpabuf *rsne_override_eapol;
struct wpabuf *rsnxe_override_eapol;
struct wpabuf *rsne_override_ft;
struct wpabuf *rsnxe_override_ft;
struct wpabuf *gtk_rsc_override;
struct wpabuf *igtk_rsc_override;
int no_beacon_rsnxe;
int skip_prune_assoc;
int ft_rsnxe_used;
unsigned int oci_freq_override_eapol_m3;
unsigned int oci_freq_override_eapol_g1;
unsigned int oci_freq_override_saquery_req;
unsigned int oci_freq_override_saquery_resp;
unsigned int oci_freq_override_ft_assoc;
unsigned int oci_freq_override_fils_assoc;
unsigned int oci_freq_override_wnm_sleep;
#endif /* CONFIG_TESTING_OPTIONS */
#define MESH_ENABLED BIT(0)
@ -702,19 +730,27 @@ struct hostapd_bss_config {
unsigned int fils_hlp_wait_time;
u16 dhcp_server_port;
u16 dhcp_relay_port;
u32 fils_discovery_min_int;
u32 fils_discovery_max_int;
#endif /* CONFIG_FILS */
int multicast_to_unicast;
int broadcast_deauth;
int notify_mgmt_frames;
#ifdef CONFIG_DPP
char *dpp_name;
char *dpp_mud_url;
char *dpp_connector;
struct wpabuf *dpp_netaccesskey;
unsigned int dpp_netaccesskey_expiry;
struct wpabuf *dpp_csign;
#ifdef CONFIG_DPP2
struct dpp_controller_conf *dpp_controller;
int dpp_configurator_connectivity;
int dpp_pfs;
#endif /* CONFIG_DPP2 */
#endif /* CONFIG_DPP */
@ -724,12 +760,15 @@ struct hostapd_bss_config {
size_t owe_transition_ssid_len;
char owe_transition_ifname[IFNAMSIZ + 1];
int *owe_groups;
int owe_ptk_workaround;
#endif /* CONFIG_OWE */
int coloc_intf_reporting;
u8 send_probe_response;
u8 transition_disable;
#define BACKHAUL_BSS 1
#define FRONTHAUL_BSS 2
int multi_ap; /* bitmap of BACKHAUL_BSS, FRONTHAUL_BSS */
@ -827,15 +866,32 @@ struct hostapd_bss_config {
*/
u8 mka_psk_set;
#endif /* CONFIG_MACSEC */
#ifdef CONFIG_PASN
#ifdef CONFIG_TESTING_OPTIONS
/*
* Normally, KDK should be derived if and only if both sides support
* secure LTF. Allow forcing KDK derivation for testing purposes.
*/
int force_kdk_derivation;
/* If set, corrupt the MIC in the 2nd Authentication frame of PASN */
int pasn_corrupt_mic;
#endif /* CONFIG_TESTING_OPTIONS */
int *pasn_groups;
#endif /* CONFIG_PASN */
unsigned int unsol_bcast_probe_resp_interval;
};
/**
* struct he_phy_capabilities_info - HE PHY capabilities
*/
struct he_phy_capabilities_info {
Boolean he_su_beamformer;
Boolean he_su_beamformee;
Boolean he_mu_beamformer;
bool he_su_beamformer;
bool he_su_beamformee;
bool he_mu_beamformer;
};
/**
@ -843,6 +899,8 @@ struct he_phy_capabilities_info {
*/
struct he_operation {
u8 he_bss_color;
u8 he_bss_color_disabled;
u8 he_bss_color_partial;
u8 he_default_pe_duration;
u8 he_twt_required;
u16 he_rts_threshold;
@ -857,8 +915,8 @@ struct spatial_reuse {
u8 non_srg_obss_pd_max_offset;
u8 srg_obss_pd_min_offset;
u8 srg_obss_pd_max_offset;
u8 srg_obss_color_bitmap;
u8 srg_obss_color_partial_bitmap;
u8 srg_bss_color_bitmap[8];
u8 srg_partial_bssid_bitmap[8];
};
/**
@ -871,11 +929,17 @@ struct hostapd_config {
u16 beacon_int;
int rts_threshold;
int fragm_threshold;
u8 op_class;
u8 channel;
int enable_edmg;
u8 edmg_channel;
u8 acs;
struct wpa_freq_range_list acs_ch_list;
struct wpa_freq_range_list acs_freq_list;
u8 acs_freq_list_present;
int acs_exclude_dfs;
enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */
int acs_exclude_6ghz_non_psc;
enum {
LONG_PREAMBLE = 0,
SHORT_PREAMBLE = 1
@ -987,6 +1051,10 @@ struct hostapd_config {
u8 he_oper_chwidth;
u8 he_oper_centr_freq_seg0_idx;
u8 he_oper_centr_freq_seg1_idx;
u8 he_6ghz_max_mpdu;
u8 he_6ghz_max_ampdu_len_exp;
u8 he_6ghz_rx_ant_pat;
u8 he_6ghz_tx_ant_pat;
#endif /* CONFIG_IEEE80211AX */
/* VHT enable/disable config from CHAN_SWITCH */
@ -994,8 +1062,14 @@ struct hostapd_config {
#define CH_SWITCH_VHT_DISABLED BIT(1)
unsigned int ch_switch_vht_config;
/* HE enable/disable config from CHAN_SWITCH */
#define CH_SWITCH_HE_ENABLED BIT(0)
#define CH_SWITCH_HE_DISABLED BIT(1)
unsigned int ch_switch_he_config;
int rssi_reject_assoc_rssi;
int rssi_reject_assoc_timeout;
int rssi_ignore_probe_request;
#ifdef CONFIG_AIRTIME_POLICY
enum {
@ -1100,5 +1174,8 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config);
void hostapd_set_security_params(struct hostapd_bss_config *bss,
int full_config);
int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf);
bool hostapd_sae_pk_in_use(struct hostapd_bss_config *conf);
bool hostapd_sae_pk_exclusively(struct hostapd_bss_config *conf);
int hostapd_setup_sae_pt(struct hostapd_bss_config *conf);
#endif /* HOSTAPD_CONFIG_H */

View file

@ -10,6 +10,7 @@
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "common/hw_features_common.h"
#include "wps/wps.h"
#include "p2p/p2p.h"
@ -107,6 +108,10 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
goto fail;
#endif /* CONFIG_FILS */
pos = hostapd_eid_rsnxe(hapd, buf, sizeof(buf));
if (add_buf_data(&assocresp, buf, pos - buf) < 0)
goto fail;
if (add_buf(&beacon, hapd->wps_beacon_ie) < 0 ||
add_buf(&proberesp, hapd->wps_probe_resp_ie) < 0)
goto fail;
@ -305,9 +310,7 @@ int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
params.wpa_pairwise = hapd->conf->wpa_pairwise;
params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt;
params.rsn_preauth = hapd->conf->rsn_preauth;
#ifdef CONFIG_IEEE80211W
params.ieee80211w = hapd->conf->ieee80211w;
#endif /* CONFIG_IEEE80211W */
}
return hostapd_set_ieee8021x(hapd, &params);
}
@ -348,7 +351,7 @@ int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
u16 auth_alg)
{
if (hapd->driver == NULL || hapd->driver->add_sta_node == NULL)
return 0;
return -EOPNOTSUPP;
return hapd->driver->add_sta_node(hapd->drv_priv, addr, auth_alg);
}
@ -415,6 +418,7 @@ int hostapd_sta_add(struct hostapd_data *hapd,
const struct ieee80211_vht_capabilities *vht_capab,
const struct ieee80211_he_capabilities *he_capab,
size_t he_capab_len,
const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab,
u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps,
int set)
{
@ -436,6 +440,7 @@ int hostapd_sta_add(struct hostapd_data *hapd,
params.vht_capabilities = vht_capab;
params.he_capab = he_capab;
params.he_capab_len = he_capab_len;
params.he_6ghz_capab = he_6ghz_capab;
params.vht_opmode_enabled = !!(flags & WLAN_STA_VHT_OPMODE_ENABLED);
params.vht_opmode = vht_opmode;
params.flags = hostapd_sta_flags_to_drv(flags);
@ -540,7 +545,8 @@ int hostapd_flush(struct hostapd_data *hapd)
int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
int freq, int channel, int ht_enabled, int vht_enabled,
int freq, int channel, int edmg, u8 edmg_channel,
int ht_enabled, int vht_enabled,
int he_enabled,
int sec_channel_offset, int oper_chwidth,
int center_segment0, int center_segment1)
@ -548,7 +554,8 @@ int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
struct hostapd_freq_params data;
struct hostapd_hw_modes *cmode = hapd->iface->current_mode;
if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled,
if (hostapd_set_freq_params(&data, mode, freq, channel, edmg,
edmg_channel, ht_enabled,
vht_enabled, he_enabled, sec_channel_offset,
oper_chwidth,
center_segment0, center_segment1,
@ -583,7 +590,7 @@ int hostapd_set_frag(struct hostapd_data *hapd, int frag)
int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
int total_flags, int flags_or, int flags_and)
{
if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL)
if (!hapd->driver || !hapd->drv_priv || !hapd->driver->sta_set_flags)
return 0;
return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags,
flags_or, flags_and);
@ -645,6 +652,12 @@ int hostapd_drv_none(struct hostapd_data *hapd)
}
bool hostapd_drv_nl80211(struct hostapd_data *hapd)
{
return hapd->driver && os_strcmp(hapd->driver->name, "nl80211") == 0;
}
int hostapd_driver_scan(struct hostapd_data *hapd,
struct wpa_driver_scan_params *params)
{
@ -675,36 +688,41 @@ int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
enum wpa_alg alg, const u8 *addr,
int key_idx, int set_tx,
int key_idx, int vlan_id, int set_tx,
const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len)
const u8 *key, size_t key_len, enum key_flag key_flag)
{
struct wpa_driver_set_key_params params;
if (hapd->driver == NULL || hapd->driver->set_key == NULL)
return 0;
return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr,
key_idx, set_tx, seq, seq_len, key,
key_len);
os_memset(&params, 0, sizeof(params));
params.ifname = ifname;
params.alg = alg;
params.addr = addr;
params.key_idx = key_idx;
params.set_tx = set_tx;
params.seq = seq;
params.seq_len = seq_len;
params.key = key;
params.key_len = key_len;
params.vlan_id = vlan_id;
params.key_flag = key_flag;
return hapd->driver->set_key(hapd->drv_priv, &params);
}
int hostapd_drv_send_mlme(struct hostapd_data *hapd,
const void *msg, size_t len, int noack)
const void *msg, size_t len, int noack,
const u16 *csa_offs, size_t csa_offs_len,
int no_encrypt)
{
if (!hapd->driver || !hapd->driver->send_mlme || !hapd->drv_priv)
return 0;
return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
NULL, 0);
}
int hostapd_drv_send_mlme_csa(struct hostapd_data *hapd,
const void *msg, size_t len, int noack,
const u16 *csa_offs, size_t csa_offs_len)
{
if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
return 0;
return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
csa_offs, csa_offs_len);
csa_offs, csa_offs_len, no_encrypt, 0);
}
@ -810,7 +828,8 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
return -1;
}
if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled,
if (hostapd_set_freq_params(&data, mode, freq, channel, 0, 0,
ht_enabled,
vht_enabled, he_enabled, sec_channel_offset,
oper_chwidth, center_segment0,
center_segment1,
@ -850,10 +869,24 @@ static void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd,
for (i = 0; i < mode->num_channels; i++) {
struct hostapd_channel_data *chan = &mode->channels[i];
if ((acs_ch_list_all ||
freq_range_list_includes(&hapd->iface->conf->acs_ch_list,
chan->chan)) &&
!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
if (!acs_ch_list_all &&
(hapd->iface->conf->acs_freq_list.num &&
!freq_range_list_includes(
&hapd->iface->conf->acs_freq_list,
chan->freq)))
continue;
if (!acs_ch_list_all &&
(!hapd->iface->conf->acs_freq_list_present &&
hapd->iface->conf->acs_ch_list.num &&
!freq_range_list_includes(
&hapd->iface->conf->acs_ch_list,
chan->chan)))
continue;
if (is_6ghz_freq(chan->freq) &&
hapd->iface->conf->acs_exclude_6ghz_non_psc &&
!is_6ghz_psc_frequency(chan->freq))
continue;
if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
!(hapd->iface->conf->acs_exclude_dfs &&
(chan->flag & HOSTAPD_CHAN_RADAR)))
int_array_add_unique(freq_list, chan->freq);
@ -879,10 +912,9 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
{
struct drv_acs_params params;
int ret, i, acs_ch_list_all = 0;
u8 *channels = NULL;
unsigned int num_channels = 0;
struct hostapd_hw_modes *mode;
int *freq_list = NULL;
enum hostapd_hw_mode selected_mode;
if (hapd->driver == NULL || hapd->driver->do_acs == NULL)
return 0;
@ -894,42 +926,27 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
* If no chanlist config parameter is provided, include all enabled
* channels of the selected hw_mode.
*/
if (!hapd->iface->conf->acs_ch_list.num)
acs_ch_list_all = 1;
if (hapd->iface->conf->acs_freq_list_present)
acs_ch_list_all = !hapd->iface->conf->acs_freq_list.num;
else
acs_ch_list_all = !hapd->iface->conf->acs_ch_list.num;
mode = hapd->iface->current_mode;
if (mode) {
channels = os_malloc(mode->num_channels);
if (channels == NULL)
return -1;
if (hapd->iface->current_mode)
selected_mode = hapd->iface->current_mode->mode;
else
selected_mode = HOSTAPD_MODE_IEEE80211ANY;
for (i = 0; i < mode->num_channels; i++) {
struct hostapd_channel_data *chan = &mode->channels[i];
if (!acs_ch_list_all &&
!freq_range_list_includes(
&hapd->iface->conf->acs_ch_list,
chan->chan))
continue;
if (hapd->iface->conf->acs_exclude_dfs &&
(chan->flag & HOSTAPD_CHAN_RADAR))
continue;
if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) {
channels[num_channels++] = chan->chan;
int_array_add_unique(&freq_list, chan->freq);
}
}
} else {
for (i = 0; i < hapd->iface->num_hw_features; i++) {
mode = &hapd->iface->hw_features[i];
hostapd_get_hw_mode_any_channels(hapd, mode,
acs_ch_list_all,
&freq_list);
}
for (i = 0; i < hapd->iface->num_hw_features; i++) {
mode = &hapd->iface->hw_features[i];
if (selected_mode != HOSTAPD_MODE_IEEE80211ANY &&
selected_mode != mode->mode)
continue;
hostapd_get_hw_mode_any_channels(hapd, mode, acs_ch_list_all,
&freq_list);
}
params.ch_list = channels;
params.ch_list_len = num_channels;
params.freq_list = freq_list;
params.edmg_enabled = hapd->iface->conf->enable_edmg;
params.ht_enabled = !!(hapd->iface->conf->ieee80211n);
params.ht40_enabled = !!(hapd->iface->conf->ht_capab &
@ -953,8 +970,11 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
params.ch_width = 160;
}
if (hapd->iface->conf->op_class)
params.ch_width = op_class_to_bandwidth(
hapd->iface->conf->op_class);
ret = hapd->driver->do_acs(hapd->drv_priv, &params);
os_free(channels);
os_free(freq_list);
return ret;
}
@ -968,3 +988,11 @@ int hostapd_drv_update_dh_ie(struct hostapd_data *hapd, const u8 *peer,
return hapd->driver->update_dh_ie(hapd->drv_priv, peer, reason_code,
ie, ielen);
}
int hostapd_drv_dpp_listen(struct hostapd_data *hapd, bool enable)
{
if (!hapd->driver || !hapd->driver->dpp_listen || !hapd->drv_priv)
return 0;
return hapd->driver->dpp_listen(hapd->drv_priv, enable);
}

View file

@ -43,6 +43,7 @@ int hostapd_sta_add(struct hostapd_data *hapd,
const struct ieee80211_vht_capabilities *vht_capab,
const struct ieee80211_he_capabilities *he_capab,
size_t he_capab_len,
const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab,
u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps,
int set);
int hostapd_set_privacy(struct hostapd_data *hapd, int enabled);
@ -62,7 +63,8 @@ int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
const u8 *addr, int idx, u8 *seq);
int hostapd_flush(struct hostapd_data *hapd);
int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
int freq, int channel, int ht_enabled, int vht_enabled,
int freq, int channel, int edmg, u8 edmg_channel,
int ht_enabled, int vht_enabled,
int he_enabled, int sec_channel_offset, int oper_chwidth,
int center_segment0, int center_segment1);
int hostapd_set_rts(struct hostapd_data *hapd, int rts);
@ -79,6 +81,7 @@ hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
u16 *flags, u8 *dfs_domain);
int hostapd_driver_commit(struct hostapd_data *hapd);
int hostapd_drv_none(struct hostapd_data *hapd);
bool hostapd_drv_nl80211(struct hostapd_data *hapd);
int hostapd_driver_scan(struct hostapd_data *hapd,
struct wpa_driver_scan_params *params);
struct wpa_scan_results * hostapd_driver_get_scan_results(
@ -88,14 +91,13 @@ int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
int hostapd_drv_set_key(const char *ifname,
struct hostapd_data *hapd,
enum wpa_alg alg, const u8 *addr,
int key_idx, int set_tx,
int key_idx, int vlan_id, int set_tx,
const u8 *seq, size_t seq_len,
const u8 *key, size_t key_len);
const u8 *key, size_t key_len, enum key_flag key_flag);
int hostapd_drv_send_mlme(struct hostapd_data *hapd,
const void *msg, size_t len, int noack);
int hostapd_drv_send_mlme_csa(struct hostapd_data *hapd,
const void *msg, size_t len, int noack,
const u16 *csa_offs, size_t csa_offs_len);
const void *msg, size_t len, int noack,
const u16 *csa_offs, size_t csa_offs_len,
int no_encrypt);
int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
const u8 *addr, int reason);
int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
@ -132,6 +134,7 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface,
int hostapd_drv_do_acs(struct hostapd_data *hapd);
int hostapd_drv_update_dh_ie(struct hostapd_data *hapd, const u8 *peer,
u16 reason_code, const u8 *ie, size_t ielen);
int hostapd_drv_dpp_listen(struct hostapd_data *hapd, bool enable);
#include "drivers/driver.h"
@ -348,12 +351,13 @@ static inline int hostapd_drv_br_set_net_param(struct hostapd_data *hapd,
static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd,
int vendor_id, int subcmd,
const u8 *data, size_t data_len,
enum nested_attr nested_attr_flag,
struct wpabuf *buf)
{
if (hapd->driver == NULL || hapd->driver->vendor_cmd == NULL)
return -1;
return hapd->driver->vendor_cmd(hapd->drv_priv, vendor_id, subcmd, data,
data_len, buf);
data_len, nested_attr_flag, buf);
}
static inline int hostapd_drv_stop_ap(struct hostapd_data *hapd)
@ -381,4 +385,22 @@ hostapd_drv_send_external_auth_status(struct hostapd_data *hapd,
return hapd->driver->send_external_auth_status(hapd->drv_priv, params);
}
static inline int
hostapd_drv_set_band(struct hostapd_data *hapd, u32 band_mask)
{
if (!hapd->driver || !hapd->drv_priv || !hapd->driver->set_band)
return -1;
return hapd->driver->set_band(hapd->drv_priv, band_mask);
}
#ifdef ANDROID
static inline int hostapd_drv_driver_cmd(struct hostapd_data *hapd,
char *cmd, char *buf, size_t buf_len)
{
if (!hapd->driver->driver_cmd)
return -1;
return hapd->driver->driver_cmd(hapd->drv_priv, cmd, buf, buf_len);
}
#endif /* ANDROID */
#endif /* AP_DRV_OPS */

Some files were not shown because too many files have changed in this diff Show more