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:
parent
9e114a3b99
commit
f8262d7d8a
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
*.pyc
|
||||
*~
|
||||
tests/hwsim/logs
|
||||
tests/remote/logs
|
||||
wpaspy/build
|
||||
**/parallel-vm.log
|
||||
tags
|
||||
build/
|
10
Android.mk
Normal file
10
Android.mk
Normal 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
|
@ -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
47
build_release
Executable 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
14
doc/.gitignore
vendored
Normal 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
42
doc/Makefile
Normal 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
315
doc/code_structure.doxygen
Normal 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
1054
doc/ctrl_iface.doxygen
Normal file
File diff suppressed because it is too large
Load Diff
2394
doc/dbus.doxygen
Normal file
2394
doc/dbus.doxygen
Normal file
File diff suppressed because it is too large
Load Diff
90
doc/directories.doxygen
Normal file
90
doc/directories.doxygen
Normal 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
1547
doc/doxygen.conf
Normal file
File diff suppressed because it is too large
Load Diff
180
doc/driver_wrapper.doxygen
Normal file
180
doc/driver_wrapper.doxygen
Normal 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
87
doc/eap.doxygen
Normal 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
56
doc/eap_server.doxygen
Normal 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
264
doc/hostapd.fig
Normal 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
|
66
doc/hostapd_ctrl_iface.doxygen
Normal file
66
doc/hostapd_ctrl_iface.doxygen
Normal 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
95
doc/mainpage.doxygen
Normal 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
471
doc/p2p.doxygen
Normal 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
85
doc/p2p_arch.dot
Normal 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
85
doc/p2p_arch2.dot
Normal 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
62
doc/p2p_sm.dot
Normal 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
209
doc/porting.doxygen
Normal 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
201
doc/testing_tools.doxygen
Normal 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
247
doc/wpa_supplicant.fig
Normal 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
4
eap_example/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
*.d
|
||||
eap_example
|
||||
libeap.so
|
||||
libeap.a
|
119
eap_example/Makefile
Normal file
119
eap_example/Makefile
Normal 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
42
eap_example/README
Normal 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
55
eap_example/ca.pem
Normal 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
5
eap_example/dh.conf
Normal 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
47
eap_example/eap_example.c
Normal 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;
|
||||
}
|
377
eap_example/eap_example_peer.c
Normal file
377
eap_example/eap_example_peer.c
Normal 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);
|
||||
}
|
300
eap_example/eap_example_server.c
Normal file
300
eap_example/eap_example_server.c
Normal 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;
|
||||
}
|
15
eap_example/server-key.pem
Normal file
15
eap_example/server-key.pem
Normal 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
16
eap_example/server.key
Normal 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
64
eap_example/server.pem
Normal 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
5
hostapd/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
.config
|
||||
hostapd
|
||||
hostapd_cli
|
||||
hlr_auc_gw
|
||||
nt_password_hash
|
@ -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
|
||||
|
@ -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
|
||||
|
197
hostapd/Makefile
197
hostapd/Makefile
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
196
hostapd/sae_pk_gen.c
Normal 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;
|
||||
}
|
@ -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 *~
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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) {
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
|
||||
|
@ -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
1
hs20/server/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
hs20_spp_server
|
42
hs20/server/Makefile
Normal file
42
hs20/server/Makefile
Normal 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
13
hs20/server/ca/clean.sh
Executable 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
|
17
hs20/server/ca/est-csrattrs.cnf
Normal file
17
hs20/server/ca/est-csrattrs.cnf
Normal 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
4
hs20/server/ca/est-csrattrs.sh
Executable 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
7
hs20/server/ca/hs20.oid
Normal 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
11
hs20/server/ca/ocsp-req.sh
Executable 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
|
3
hs20/server/ca/ocsp-responder-ica.sh
Executable file
3
hs20/server/ca/ocsp-responder-ica.sh
Executable 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
|
3
hs20/server/ca/ocsp-responder.sh
Executable file
3
hs20/server/ca/ocsp-responder.sh
Executable 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
|
11
hs20/server/ca/ocsp-update-cache.sh
Executable file
11
hs20/server/ca/ocsp-update-cache.sh
Executable 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
|
125
hs20/server/ca/openssl-root.cnf
Normal file
125
hs20/server/ca/openssl-root.cnf
Normal 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
200
hs20/server/ca/openssl.cnf
Normal 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
209
hs20/server/ca/setup.sh
Executable 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
|
BIN
hs20/server/ca/w1fi_logo.png
Normal file
BIN
hs20/server/ca/w1fi_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.4 KiB |
262
hs20/server/hs20-osu-server.txt
Normal file
262
hs20/server/hs20-osu-server.txt
Normal 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
|
207
hs20/server/hs20_spp_server.c
Normal file
207
hs20/server/hs20_spp_server.c
Normal 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
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
36
hs20/server/spp_server.h
Normal 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 */
|
17
hs20/server/sql-example.txt
Normal file
17
hs20/server/sql-example.txt
Normal 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
108
hs20/server/sql.txt
Normal 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
|
||||
);
|
50
hs20/server/www/add-free.php
Normal file
50
hs20/server/www/add-free.php
Normal 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);
|
||||
|
||||
?>
|
56
hs20/server/www/add-mo.php
Normal file
56
hs20/server/www/add-mo.php
Normal 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);
|
||||
|
||||
?>
|
39
hs20/server/www/cert-enroll.php
Normal file
39
hs20/server/www/cert-enroll.php
Normal 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);
|
||||
|
||||
?>
|
7
hs20/server/www/config.php
Normal file
7
hs20/server/www/config.php
Normal 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
232
hs20/server/www/est.php
Normal 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");
|
||||
}
|
||||
|
||||
?>
|
19
hs20/server/www/free-remediation.php
Normal file
19
hs20/server/www/free-remediation.php
Normal 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
23
hs20/server/www/free.php
Normal 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>
|
32
hs20/server/www/redirect.php
Normal file
32
hs20/server/www/redirect.php
Normal 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')");
|
||||
|
||||
?>
|
41
hs20/server/www/remediation-pw.php
Normal file
41
hs20/server/www/remediation-pw.php
Normal 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);
|
||||
|
||||
?>
|
55
hs20/server/www/remediation.php
Normal file
55
hs20/server/www/remediation.php
Normal 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>
|
59
hs20/server/www/signup.php
Normal file
59
hs20/server/www/signup.php
Normal 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
168
hs20/server/www/spp.php
Normal 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
87
hs20/server/www/terms.php
Normal 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
377
hs20/server/www/users.php
Normal 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
2
radius_example/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*.d
|
||||
radius_example
|
28
radius_example/Makefile
Normal file
28
radius_example/Makefile
Normal 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
35
radius_example/README
Normal 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().
|
153
radius_example/radius_example.c
Normal file
153
radius_example/radius_example.c
Normal 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;
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
307
src/ap/acs.c
307
src/ap/acs.c
@ -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(¶ms, 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(¶ms, 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);
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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, ¶ms);
|
||||
}
|
||||
@ -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(¶ms, 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, ¶ms);
|
||||
}
|
||||
|
||||
|
||||
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, ¶ms);
|
||||
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);
|
||||
}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user