mirror of
https://github.com/freebsd/freebsd-src
synced 2024-07-21 18:27:22 +00:00
wpa: Import wpa 2.10
The long awaited wpa 2.10 is finally here.
This commit is contained in:
parent
7b54fad807
commit
03f33dd077
8
.gitignore
vendored
8
.gitignore
vendored
|
@ -1,8 +0,0 @@
|
|||
*.pyc
|
||||
*~
|
||||
tests/hwsim/logs
|
||||
tests/remote/logs
|
||||
wpaspy/build
|
||||
**/parallel-vm.log
|
||||
tags
|
||||
build/
|
10
Android.mk
10
Android.mk
|
@ -1,10 +0,0 @@
|
|||
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
|
|
@ -143,7 +143,7 @@ The license terms used for hostap.git files
|
|||
|
||||
Modified BSD license (no advertisement clause):
|
||||
|
||||
Copyright (c) 2002-2021, Jouni Malinen <j@w1.fi> and contributors
|
||||
Copyright (c) 2002-2022, Jouni Malinen <j@w1.fi> and contributors
|
||||
All Rights Reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
2
COPYING
2
COPYING
|
@ -1,7 +1,7 @@
|
|||
wpa_supplicant and hostapd
|
||||
--------------------------
|
||||
|
||||
Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> and contributors
|
||||
Copyright (c) 2002-2022, Jouni Malinen <j@w1.fi> and contributors
|
||||
All Rights Reserved.
|
||||
|
||||
|
||||
|
|
2
README
2
README
|
@ -1,7 +1,7 @@
|
|||
wpa_supplicant and hostapd
|
||||
--------------------------
|
||||
|
||||
Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> and contributors
|
||||
Copyright (c) 2002-2022, Jouni Malinen <j@w1.fi> and contributors
|
||||
All Rights Reserved.
|
||||
|
||||
These programs are licensed under the BSD license (the one with
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
#!/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
14
doc/.gitignore
vendored
|
@ -1,14 +0,0 @@
|
|||
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
42
doc/Makefile
|
@ -1,42 +0,0 @@
|
|||
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
|
|
@ -1,315 +0,0 @@
|
|||
/**
|
||||
\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 Linux packet socket
|
||||
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
|
||||
Stub 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
|
||||
|
||||
*/
|
File diff suppressed because it is too large
Load diff
2428
doc/dbus.doxygen
2428
doc/dbus.doxygen
File diff suppressed because it is too large
Load diff
|
@ -1,90 +0,0 @@
|
|||
/**
|
||||
|
||||
\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
1547
doc/doxygen.conf
File diff suppressed because it is too large
Load diff
|
@ -1,180 +0,0 @@
|
|||
/**
|
||||
\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)
|
||||
*/
|
|
@ -1,87 +0,0 @@
|
|||
/**
|
||||
\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.
|
||||
|
||||
*/
|
|
@ -1,56 +0,0 @@
|
|||
/**
|
||||
\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
264
doc/hostapd.fig
|
@ -1,264 +0,0 @@
|
|||
#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
|
|
@ -1,66 +0,0 @@
|
|||
/**
|
||||
\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.
|
||||
|
||||
*/
|
|
@ -1,95 +0,0 @@
|
|||
/**
|
||||
\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
471
doc/p2p.doxygen
|
@ -1,471 +0,0 @@
|
|||
/**
|
||||
\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 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
|
||||
|
||||
*/
|
|
@ -1,85 +0,0 @@
|
|||
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;
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
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;
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
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];
|
||||
*/
|
||||
}
|
|
@ -1,209 +0,0 @@
|
|||
/**
|
||||
\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.
|
||||
|
||||
*/
|
|
@ -1,201 +0,0 @@
|
|||
/**
|
||||
\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.
|
||||
|
||||
*/
|
|
@ -1,247 +0,0 @@
|
|||
#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
4
eap_example/.gitignore
vendored
|
@ -1,4 +0,0 @@
|
|||
*.d
|
||||
eap_example
|
||||
libeap.so
|
||||
libeap.a
|
|
@ -1,119 +0,0 @@
|
|||
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)
|
|
@ -1,42 +0,0 @@
|
|||
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.
|
|
@ -1,55 +0,0 @@
|
|||
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-----
|
|
@ -1,5 +0,0 @@
|
|||
-----BEGIN DH PARAMETERS-----
|
||||
MIGHAoGBAP3V8IHq3H2DUlYywsvjYNuS17eCdt0mJo6/os6PHqdhgkMrPxF9u4Gr
|
||||
qKXq9e6GqmZYdjta30N3FkXaV924BJ0xOqb2TntiKg4u50/l6hSUneWt6UFBaizd
|
||||
XrqjNFIme/5RXMZ7RglXliBpCepAaFLMcKhOS4ulUyYYHSy+oqRjAgEC
|
||||
-----END DH PARAMETERS-----
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
|
@ -1,377 +0,0 @@
|
|||
/*
|
||||
* 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);
|
||||
}
|
|
@ -1,300 +0,0 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
-----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-----
|
|
@ -1,16 +0,0 @@
|
|||
-----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-----
|
|
@ -1,64 +0,0 @@
|
|||
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-----
|
|
@ -1,5 +1,48 @@
|
|||
ChangeLog for hostapd
|
||||
|
||||
2022-01-16 - v2.10
|
||||
* SAE changes
|
||||
- improved protection against side channel attacks
|
||||
[https://w1.fi/security/2022-1/]
|
||||
- added option send SAE Confirm immediately (sae_config_immediate=1)
|
||||
after SAE Commit
|
||||
- added support for the hash-to-element mechanism (sae_pwe=1 or
|
||||
sae_pwe=2)
|
||||
- fixed PMKSA caching with OKC
|
||||
- added support for SAE-PK
|
||||
* EAP-pwd changes
|
||||
- improved protection against side channel attacks
|
||||
[https://w1.fi/security/2022-1/]
|
||||
* fixed WPS UPnP SUBSCRIBE handling of invalid operations
|
||||
[https://w1.fi/security/2020-1/]
|
||||
* fixed PMF disconnection protection bypass
|
||||
[https://w1.fi/security/2019-7/]
|
||||
* added support for using OpenSSL 3.0
|
||||
* fixed various issues in experimental support for EAP-TEAP server
|
||||
* added configuration (max_auth_rounds, max_auth_rounds_short) to
|
||||
increase the maximum number of EAP message exchanges (mainly to
|
||||
support cases with very large certificates) for the EAP server
|
||||
* added support for DPP release 2 (Wi-Fi Device Provisioning Protocol)
|
||||
* extended HE (IEEE 802.11ax) support, including 6 GHz support
|
||||
* removed obsolete IAPP functionality
|
||||
* fixed EAP-FAST server with TLS GCM/CCM ciphers
|
||||
* dropped support for libnl 1.1
|
||||
* added support for nl80211 control port for EAPOL frame TX/RX
|
||||
* fixed OWE key derivation with groups 20 and 21; this breaks backwards
|
||||
compatibility for these groups while the default group 19 remains
|
||||
backwards compatible; owe_ptk_workaround=1 can be used to enabled a
|
||||
a workaround for the group 20/21 backwards compatibility
|
||||
* added support for Beacon protection
|
||||
* added support for Extended Key ID for pairwise keys
|
||||
* removed WEP support from the default build (CONFIG_WEP=y can be used
|
||||
to enable it, if really needed)
|
||||
* added a build option to remove TKIP support (CONFIG_NO_TKIP=y)
|
||||
* added support for Transition Disable mechanism to allow the AP to
|
||||
automatically disable transition mode to improve security
|
||||
* added support for PASN
|
||||
* added EAP-TLS server support for TLS 1.3 (disabled by default for now)
|
||||
* a large number of other fixes, cleanup, and extensions
|
||||
|
||||
2019-08-07 - v2.9
|
||||
* SAE changes
|
||||
- disable use of groups using Brainpool curves
|
||||
|
|
|
@ -2,7 +2,7 @@ hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP
|
|||
Authenticator and RADIUS authentication server
|
||||
================================================================
|
||||
|
||||
Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> and contributors
|
||||
Copyright (c) 2002-2022, Jouni Malinen <j@w1.fi> and contributors
|
||||
All Rights Reserved.
|
||||
|
||||
This program is licensed under the BSD license (the one with
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* hostapd - command line interface for hostapd daemon
|
||||
* Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2022, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
|
@ -21,7 +21,7 @@
|
|||
|
||||
static const char *const hostapd_cli_version =
|
||||
"hostapd_cli v" VERSION_STR "\n"
|
||||
"Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi> and contributors";
|
||||
"Copyright (c) 2004-2022, Jouni Malinen <j@w1.fi> and contributors";
|
||||
|
||||
static struct wpa_ctrl *ctrl_conn;
|
||||
static int hostapd_cli_quit = 0;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* hostapd / main()
|
||||
* Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2022, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
|
@ -454,7 +454,7 @@ static void show_version(void)
|
|||
"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> "
|
||||
"Copyright (c) 2002-2022, Jouni Malinen <j@w1.fi> "
|
||||
"and contributors\n",
|
||||
VERSION_STR);
|
||||
}
|
||||
|
|
4
hs20/client/.gitignore
vendored
4
hs20/client/.gitignore
vendored
|
@ -1,4 +0,0 @@
|
|||
hs20-osu-client
|
||||
SP
|
||||
osu-ca.pem
|
||||
spp.xsd
|
|
@ -1,81 +0,0 @@
|
|||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
INCLUDES = $(LOCAL_PATH)
|
||||
INCLUDES += $(LOCAL_PATH)/../../src/utils
|
||||
INCLUDES += $(LOCAL_PATH)/../../src/common
|
||||
INCLUDES += $(LOCAL_PATH)/../../src
|
||||
INCLUDES += external/libxml2/include
|
||||
INCLUDES += external/curl/include
|
||||
INCLUDES += external/webkit/Source/WebKit/gtk
|
||||
|
||||
# We try to keep this compiling against older platform versions.
|
||||
# The new icu location (external/icu) exports its own headers, but
|
||||
# the older versions in external/icu4c don't, and we need to add those
|
||||
# headers to the include path by hand.
|
||||
ifeq ($(wildcard external/icu),)
|
||||
INCLUDES += external/icu4c/common
|
||||
else
|
||||
# The LOCAL_EXPORT_C_INCLUDE_DIRS from ICU did not seem to fully resolve the
|
||||
# build (e.g., "mm -B" failed to build, but following that with "mm" allowed
|
||||
# the build to complete). For now, add the include directory manually here for
|
||||
# Android 5.0.
|
||||
ver = $(filter 5.0%,$(PLATFORM_VERSION))
|
||||
ifneq (,$(strip $(ver)))
|
||||
INCLUDES += external/icu/icu4c/source/common
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
L_CFLAGS += -DCONFIG_CTRL_IFACE
|
||||
L_CFLAGS += -DCONFIG_CTRL_IFACE_UNIX
|
||||
L_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/misc/wifi/sockets\"
|
||||
|
||||
OBJS = spp_client.c
|
||||
OBJS += oma_dm_client.c
|
||||
OBJS += osu_client.c
|
||||
OBJS += est.c
|
||||
OBJS += ../../src/common/wpa_ctrl.c
|
||||
OBJS += ../../src/common/wpa_helpers.c
|
||||
OBJS += ../../src/utils/xml-utils.c
|
||||
#OBJS += ../../src/utils/browser-android.c
|
||||
OBJS += ../../src/utils/browser-wpadebug.c
|
||||
OBJS += ../../src/utils/wpabuf.c
|
||||
OBJS += ../../src/utils/eloop.c
|
||||
OBJS += ../../src/wps/httpread.c
|
||||
OBJS += ../../src/wps/http_server.c
|
||||
OBJS += ../../src/utils/xml_libxml2.c
|
||||
OBJS += ../../src/utils/http_curl.c
|
||||
OBJS += ../../src/utils/base64.c
|
||||
OBJS += ../../src/utils/os_unix.c
|
||||
L_CFLAGS += -DCONFIG_DEBUG_FILE
|
||||
OBJS += ../../src/utils/wpa_debug.c
|
||||
OBJS += ../../src/utils/common.c
|
||||
OBJS += ../../src/crypto/crypto_internal.c
|
||||
OBJS += ../../src/crypto/md5-internal.c
|
||||
OBJS += ../../src/crypto/sha1-internal.c
|
||||
OBJS += ../../src/crypto/sha256-internal.c
|
||||
OBJS += ../../src/crypto/tls_openssl_ocsp.c
|
||||
|
||||
L_CFLAGS += -DEAP_TLS_OPENSSL
|
||||
|
||||
L_CFLAGS += -Wno-unused-parameter
|
||||
|
||||
|
||||
########################
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := hs20-osu-client
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := libc libcutils
|
||||
LOCAL_SHARED_LIBRARIES += libcrypto libssl
|
||||
#LOCAL_SHARED_LIBRARIES += libxml2
|
||||
LOCAL_STATIC_LIBRARIES += libxml2
|
||||
LOCAL_SHARED_LIBRARIES += libicuuc
|
||||
LOCAL_SHARED_LIBRARIES += libcurl
|
||||
|
||||
LOCAL_CFLAGS := $(L_CFLAGS)
|
||||
LOCAL_SRC_FILES := $(OBJS)
|
||||
LOCAL_C_INCLUDES := $(INCLUDES)
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
########################
|
|
@ -1,81 +0,0 @@
|
|||
ALL=hs20-osu-client
|
||||
|
||||
include ../../src/build.rules
|
||||
|
||||
CFLAGS += -I../../src/utils
|
||||
CFLAGS += -I../../src/common
|
||||
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
|
||||
endif
|
||||
|
||||
OBJS=spp_client.o
|
||||
OBJS += oma_dm_client.o
|
||||
OBJS += osu_client.o
|
||||
OBJS += est.o
|
||||
OBJS += ../../src/utils/xml-utils.o
|
||||
CFLAGS += -DCONFIG_CTRL_IFACE
|
||||
CFLAGS += -DCONFIG_CTRL_IFACE_UNIX
|
||||
OBJS += ../../src/common/wpa_ctrl.o ../../src/common/wpa_helpers.o
|
||||
ifdef CONFIG_NO_BROWSER
|
||||
CFLAGS += -DCONFIG_NO_BROWSER
|
||||
else
|
||||
ifdef CONFIG_BROWSER_SYSTEM
|
||||
OBJS += ../../src/utils/eloop.o
|
||||
OBJS += ../../src/utils/wpabuf.o
|
||||
OBJS += ../../src/wps/httpread.o
|
||||
OBJS += ../../src/wps/http_server.o
|
||||
OBJS += ../../src/utils/browser-system.o
|
||||
else
|
||||
OBJS += ../../src/utils/browser.o
|
||||
endif
|
||||
endif
|
||||
OBJS += ../../src/utils/xml_libxml2.o
|
||||
OBJS += ../../src/utils/http_curl.o
|
||||
OBJS += ../../src/utils/base64.o
|
||||
OBJS += ../../src/utils/os_unix.o
|
||||
CFLAGS += -DCONFIG_DEBUG_FILE
|
||||
OBJS += ../../src/utils/wpa_debug.o
|
||||
OBJS += ../../src/utils/common.o
|
||||
OBJS += ../../src/crypto/crypto_internal.o
|
||||
OBJS += ../../src/crypto/md5-internal.o
|
||||
OBJS += ../../src/crypto/sha1-internal.o
|
||||
OBJS += ../../src/crypto/sha256-internal.o
|
||||
|
||||
CFLAGS += $(shell xml2-config --cflags)
|
||||
LIBS += $(shell xml2-config --libs)
|
||||
|
||||
# Allow static/custom linking of libcurl.
|
||||
ifdef CUST_CURL_LINKAGE
|
||||
LIBS += ${CUST_CURL_LINKAGE}
|
||||
else
|
||||
LIBS += -lcurl
|
||||
endif
|
||||
|
||||
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 " $@
|
||||
|
||||
clean: common-clean
|
||||
rm -f core *~
|
|
@ -1,47 +0,0 @@
|
|||
<DevDetail xmlns="urn:oma:mo:oma-dm-devdetail:1.0">
|
||||
<Ext>
|
||||
<org.wi-fi>
|
||||
<Wi-Fi>
|
||||
<EAPMethodList>
|
||||
<EAPMethod1>
|
||||
<EAPType>13</EAPType>
|
||||
</EAPMethod1>
|
||||
<EAPMethod2>
|
||||
<EAPType>21</EAPType>
|
||||
<InnerMethod>MS-CHAP-V2</InnerMethod>
|
||||
</EAPMethod2>
|
||||
<EAPMethod3>
|
||||
<EAPType>18</EAPType>
|
||||
</EAPMethod3>
|
||||
<EAPMethod4>
|
||||
<EAPType>23</EAPType>
|
||||
</EAPMethod4>
|
||||
<EAPMethod5>
|
||||
<EAPType>50</EAPType>
|
||||
</EAPMethod5>
|
||||
</EAPMethodList>
|
||||
<ManufacturingCertificate>false</ManufacturingCertificate>
|
||||
<Wi-FiMACAddress>020102030405</Wi-FiMACAddress>
|
||||
<IMSI>310026000000000</IMSI>
|
||||
<IMEI_MEID>imei:490123456789012</IMEI_MEID>
|
||||
<ClientTriggerRedirectURI>http://localhost:12345/</ClientTriggerRedirectURI>
|
||||
<Ops>
|
||||
<launchBrowserToURI></launchBrowserToURI>
|
||||
<negotiateClientCertTLS></negotiateClientCertTLS>
|
||||
<getCertificate></getCertificate>
|
||||
</Ops>
|
||||
</Wi-Fi>
|
||||
</org.wi-fi>
|
||||
</Ext>
|
||||
<URI>
|
||||
<MaxDepth>0</MaxDepth>
|
||||
<MaxTotLen>0</MaxTotLen>
|
||||
<MaxSegLen>0</MaxSegLen>
|
||||
</URI>
|
||||
<DevType>MobilePhone</DevType>
|
||||
<OEM>Manufacturer</OEM>
|
||||
<FwV>1.0</FwV>
|
||||
<SwV>1.0</SwV>
|
||||
<HwV>1.0</HwV>
|
||||
<LrgObj>false</LrgObj>
|
||||
</DevDetail>
|
|
@ -1,7 +0,0 @@
|
|||
<DevInfo xmlns="urn:oma:mo:oma-dm-devinfo:1.0">
|
||||
<DevId>urn:Example:HS20-station:123456</DevId>
|
||||
<Man>Manufacturer</Man>
|
||||
<Mod>HS20-station</Mod>
|
||||
<DmV>1.2</DmV>
|
||||
<Lang>en</Lang>
|
||||
</DevInfo>
|
|
@ -1,769 +0,0 @@
|
|||
/*
|
||||
* Hotspot 2.0 OSU client - EST client
|
||||
* Copyright (c) 2012-2014, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/pkcs7.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/opensslv.h>
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
#include <openssl/buf.h>
|
||||
#endif /* OPENSSL_IS_BORINGSSL */
|
||||
|
||||
#include "common.h"
|
||||
#include "utils/base64.h"
|
||||
#include "utils/xml-utils.h"
|
||||
#include "utils/http-utils.h"
|
||||
#include "osu_client.h"
|
||||
|
||||
|
||||
static int pkcs7_to_cert(struct hs20_osu_client *ctx, const u8 *pkcs7,
|
||||
size_t len, char *pem_file, char *der_file)
|
||||
{
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
CBS pkcs7_cbs;
|
||||
#else /* OPENSSL_IS_BORINGSSL */
|
||||
PKCS7 *p7 = NULL;
|
||||
const unsigned char *p = pkcs7;
|
||||
#endif /* OPENSSL_IS_BORINGSSL */
|
||||
STACK_OF(X509) *certs;
|
||||
int i, num, ret = -1;
|
||||
BIO *out = NULL;
|
||||
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
certs = sk_X509_new_null();
|
||||
if (!certs)
|
||||
goto fail;
|
||||
CBS_init(&pkcs7_cbs, pkcs7, len);
|
||||
if (!PKCS7_get_certificates(certs, &pkcs7_cbs)) {
|
||||
wpa_printf(MSG_INFO, "Could not parse PKCS#7 object: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
write_result(ctx, "Could not parse PKCS#7 object from EST");
|
||||
goto fail;
|
||||
}
|
||||
#else /* OPENSSL_IS_BORINGSSL */
|
||||
p7 = d2i_PKCS7(NULL, &p, len);
|
||||
if (p7 == NULL) {
|
||||
wpa_printf(MSG_INFO, "Could not parse PKCS#7 object: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
write_result(ctx, "Could not parse PKCS#7 object from EST");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
switch (OBJ_obj2nid(p7->type)) {
|
||||
case NID_pkcs7_signed:
|
||||
certs = p7->d.sign->cert;
|
||||
break;
|
||||
case NID_pkcs7_signedAndEnveloped:
|
||||
certs = p7->d.signed_and_enveloped->cert;
|
||||
break;
|
||||
default:
|
||||
certs = NULL;
|
||||
break;
|
||||
}
|
||||
#endif /* OPENSSL_IS_BORINGSSL */
|
||||
|
||||
if (!certs || ((num = sk_X509_num(certs)) == 0)) {
|
||||
wpa_printf(MSG_INFO, "No certificates found in PKCS#7 object");
|
||||
write_result(ctx, "No certificates found in PKCS#7 object");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (der_file) {
|
||||
FILE *f = fopen(der_file, "wb");
|
||||
if (f == NULL)
|
||||
goto fail;
|
||||
i2d_X509_fp(f, sk_X509_value(certs, 0));
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
if (pem_file) {
|
||||
out = BIO_new(BIO_s_file());
|
||||
if (out == NULL ||
|
||||
BIO_write_filename(out, pem_file) <= 0)
|
||||
goto fail;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
X509 *cert = sk_X509_value(certs, i);
|
||||
X509_print(out, cert);
|
||||
PEM_write_bio_X509(out, cert);
|
||||
BIO_puts(out, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
fail:
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
if (certs)
|
||||
sk_X509_pop_free(certs, X509_free);
|
||||
#else /* OPENSSL_IS_BORINGSSL */
|
||||
PKCS7_free(p7);
|
||||
#endif /* OPENSSL_IS_BORINGSSL */
|
||||
if (out)
|
||||
BIO_free_all(out);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int est_load_cacerts(struct hs20_osu_client *ctx, const char *url)
|
||||
{
|
||||
char *buf, *resp;
|
||||
size_t buflen;
|
||||
unsigned char *pkcs7;
|
||||
size_t pkcs7_len, resp_len;
|
||||
int res;
|
||||
|
||||
buflen = os_strlen(url) + 100;
|
||||
buf = os_malloc(buflen);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
os_snprintf(buf, buflen, "%s/cacerts", url);
|
||||
wpa_printf(MSG_INFO, "Download EST cacerts from %s", buf);
|
||||
write_summary(ctx, "Download EST cacerts from %s", buf);
|
||||
ctx->no_osu_cert_validation = 1;
|
||||
http_ocsp_set(ctx->http, 1);
|
||||
res = http_download_file(ctx->http, buf, "Cert/est-cacerts.txt",
|
||||
ctx->ca_fname);
|
||||
http_ocsp_set(ctx->http,
|
||||
(ctx->workarounds & WORKAROUND_OCSP_OPTIONAL) ? 1 : 2);
|
||||
ctx->no_osu_cert_validation = 0;
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_INFO, "Failed to download EST cacerts from %s",
|
||||
buf);
|
||||
write_result(ctx, "Failed to download EST cacerts from %s",
|
||||
buf);
|
||||
os_free(buf);
|
||||
return -1;
|
||||
}
|
||||
os_free(buf);
|
||||
|
||||
resp = os_readfile("Cert/est-cacerts.txt", &resp_len);
|
||||
if (resp == NULL) {
|
||||
wpa_printf(MSG_INFO, "Could not read Cert/est-cacerts.txt");
|
||||
write_result(ctx, "Could not read EST cacerts");
|
||||
return -1;
|
||||
}
|
||||
|
||||
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);
|
||||
os_free(pkcs7);
|
||||
pkcs7 = NULL;
|
||||
}
|
||||
if (pkcs7 == NULL) {
|
||||
wpa_printf(MSG_INFO, "EST workaround - Could not decode base64, assume this is DER encoded PKCS7");
|
||||
pkcs7 = os_malloc(resp_len);
|
||||
if (pkcs7) {
|
||||
os_memcpy(pkcs7, resp, resp_len);
|
||||
pkcs7_len = resp_len;
|
||||
}
|
||||
}
|
||||
os_free(resp);
|
||||
|
||||
if (pkcs7 == NULL) {
|
||||
wpa_printf(MSG_INFO, "Could not fetch PKCS7 cacerts");
|
||||
write_result(ctx, "Could not fetch EST PKCS#7 cacerts");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = pkcs7_to_cert(ctx, pkcs7, pkcs7_len, "Cert/est-cacerts.pem",
|
||||
NULL);
|
||||
os_free(pkcs7);
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_INFO, "Could not parse CA certs from PKCS#7 cacerts response");
|
||||
write_result(ctx, "Could not parse CA certs from EST PKCS#7 cacerts response");
|
||||
return -1;
|
||||
}
|
||||
unlink("Cert/est-cacerts.txt");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CsrAttrs ::= SEQUENCE SIZE (0..MAX) OF AttrOrOID
|
||||
*
|
||||
* AttrOrOID ::= CHOICE {
|
||||
* oid OBJECT IDENTIFIER,
|
||||
* attribute Attribute }
|
||||
*
|
||||
* Attribute ::= SEQUENCE {
|
||||
* type OBJECT IDENTIFIER,
|
||||
* values SET SIZE(1..MAX) OF OBJECT IDENTIFIER }
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
ASN1_OBJECT *type;
|
||||
STACK_OF(ASN1_OBJECT) *values;
|
||||
} Attribute;
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
union {
|
||||
ASN1_OBJECT *oid;
|
||||
Attribute *attribute;
|
||||
} d;
|
||||
} AttrOrOID;
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_IS_BORINGSSL)
|
||||
DEFINE_STACK_OF(AttrOrOID)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
STACK_OF(AttrOrOID) *attrs;
|
||||
} CsrAttrs;
|
||||
|
||||
ASN1_SEQUENCE(Attribute) = {
|
||||
ASN1_SIMPLE(Attribute, type, ASN1_OBJECT),
|
||||
ASN1_SET_OF(Attribute, values, ASN1_OBJECT)
|
||||
} ASN1_SEQUENCE_END(Attribute);
|
||||
|
||||
ASN1_CHOICE(AttrOrOID) = {
|
||||
ASN1_SIMPLE(AttrOrOID, d.oid, ASN1_OBJECT),
|
||||
ASN1_SIMPLE(AttrOrOID, d.attribute, Attribute)
|
||||
} ASN1_CHOICE_END(AttrOrOID);
|
||||
|
||||
ASN1_CHOICE(CsrAttrs) = {
|
||||
ASN1_SEQUENCE_OF(CsrAttrs, attrs, AttrOrOID)
|
||||
} ASN1_CHOICE_END(CsrAttrs);
|
||||
|
||||
IMPLEMENT_ASN1_FUNCTIONS(CsrAttrs);
|
||||
|
||||
|
||||
static void add_csrattrs_oid(struct hs20_osu_client *ctx, ASN1_OBJECT *oid,
|
||||
STACK_OF(X509_EXTENSION) *exts)
|
||||
{
|
||||
char txt[100];
|
||||
int res;
|
||||
|
||||
if (!oid)
|
||||
return;
|
||||
|
||||
res = OBJ_obj2txt(txt, sizeof(txt), oid, 1);
|
||||
if (res < 0 || res >= (int) sizeof(txt))
|
||||
return;
|
||||
|
||||
if (os_strcmp(txt, "1.2.840.113549.1.9.7") == 0) {
|
||||
wpa_printf(MSG_INFO, "TODO: csrattr challengePassword");
|
||||
} else if (os_strcmp(txt, "1.2.840.113549.1.1.11") == 0) {
|
||||
wpa_printf(MSG_INFO, "csrattr sha256WithRSAEncryption");
|
||||
} else {
|
||||
wpa_printf(MSG_INFO, "Ignore unsupported csrattr oid %s", txt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void add_csrattrs_ext_req(struct hs20_osu_client *ctx,
|
||||
STACK_OF(ASN1_OBJECT) *values,
|
||||
STACK_OF(X509_EXTENSION) *exts)
|
||||
{
|
||||
char txt[100];
|
||||
int i, num, res;
|
||||
|
||||
num = sk_ASN1_OBJECT_num(values);
|
||||
for (i = 0; i < num; i++) {
|
||||
ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(values, i);
|
||||
|
||||
res = OBJ_obj2txt(txt, sizeof(txt), oid, 1);
|
||||
if (res < 0 || res >= (int) sizeof(txt))
|
||||
continue;
|
||||
|
||||
if (os_strcmp(txt, "1.3.6.1.1.1.1.22") == 0) {
|
||||
wpa_printf(MSG_INFO, "TODO: extReq macAddress");
|
||||
} else if (os_strcmp(txt, "1.3.6.1.4.1.40808.1.1.3") == 0) {
|
||||
wpa_printf(MSG_INFO, "TODO: extReq imei");
|
||||
} else if (os_strcmp(txt, "1.3.6.1.4.1.40808.1.1.4") == 0) {
|
||||
wpa_printf(MSG_INFO, "TODO: extReq meid");
|
||||
} else if (os_strcmp(txt, "1.3.6.1.4.1.40808.1.1.5") == 0) {
|
||||
wpa_printf(MSG_INFO, "TODO: extReq DevId");
|
||||
} else {
|
||||
wpa_printf(MSG_INFO, "Ignore unsupported cstattr extensionsRequest %s",
|
||||
txt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void add_csrattrs_attr(struct hs20_osu_client *ctx, Attribute *attr,
|
||||
STACK_OF(X509_EXTENSION) *exts)
|
||||
{
|
||||
char txt[100], txt2[100];
|
||||
int i, num, res;
|
||||
|
||||
if (!attr || !attr->type || !attr->values)
|
||||
return;
|
||||
|
||||
res = OBJ_obj2txt(txt, sizeof(txt), attr->type, 1);
|
||||
if (res < 0 || res >= (int) sizeof(txt))
|
||||
return;
|
||||
|
||||
if (os_strcmp(txt, "1.2.840.113549.1.9.14") == 0) {
|
||||
add_csrattrs_ext_req(ctx, attr->values, exts);
|
||||
return;
|
||||
}
|
||||
|
||||
num = sk_ASN1_OBJECT_num(attr->values);
|
||||
for (i = 0; i < num; i++) {
|
||||
ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(attr->values, i);
|
||||
|
||||
res = OBJ_obj2txt(txt2, sizeof(txt2), oid, 1);
|
||||
if (res < 0 || res >= (int) sizeof(txt2))
|
||||
continue;
|
||||
|
||||
wpa_printf(MSG_INFO, "Ignore unsupported cstattr::attr %s oid %s",
|
||||
txt, txt2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void add_csrattrs(struct hs20_osu_client *ctx, CsrAttrs *csrattrs,
|
||||
STACK_OF(X509_EXTENSION) *exts)
|
||||
{
|
||||
int i, num;
|
||||
|
||||
if (!csrattrs || ! csrattrs->attrs)
|
||||
return;
|
||||
|
||||
#ifdef OPENSSL_IS_BORINGSSL
|
||||
num = sk_num(CHECKED_CAST(_STACK *, STACK_OF(AttrOrOID) *,
|
||||
csrattrs->attrs));
|
||||
for (i = 0; i < num; i++) {
|
||||
AttrOrOID *ao = sk_value(
|
||||
CHECKED_CAST(_STACK *, const STACK_OF(AttrOrOID) *,
|
||||
csrattrs->attrs), i);
|
||||
switch (ao->type) {
|
||||
case 0:
|
||||
add_csrattrs_oid(ctx, ao->d.oid, exts);
|
||||
break;
|
||||
case 1:
|
||||
add_csrattrs_attr(ctx, ao->d.attribute, exts);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else /* OPENSSL_IS_BORINGSSL */
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_IS_BORINGSSL)
|
||||
num = sk_AttrOrOID_num(csrattrs->attrs);
|
||||
#else
|
||||
num = SKM_sk_num(AttrOrOID, csrattrs->attrs);
|
||||
#endif
|
||||
for (i = 0; i < num; i++) {
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(OPENSSL_IS_BORINGSSL)
|
||||
AttrOrOID *ao = sk_AttrOrOID_value(csrattrs->attrs, i);
|
||||
#else
|
||||
AttrOrOID *ao = SKM_sk_value(AttrOrOID, csrattrs->attrs, i);
|
||||
#endif
|
||||
switch (ao->type) {
|
||||
case 0:
|
||||
add_csrattrs_oid(ctx, ao->d.oid, exts);
|
||||
break;
|
||||
case 1:
|
||||
add_csrattrs_attr(ctx, ao->d.attribute, exts);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* OPENSSL_IS_BORINGSSL */
|
||||
}
|
||||
|
||||
|
||||
static int generate_csr(struct hs20_osu_client *ctx, char *key_pem,
|
||||
char *csr_pem, char *est_req, char *old_cert,
|
||||
CsrAttrs *csrattrs)
|
||||
{
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
RSA *rsa;
|
||||
X509_REQ *req = NULL;
|
||||
int ret = -1;
|
||||
unsigned int val;
|
||||
X509_NAME *subj = NULL;
|
||||
char name[100];
|
||||
STACK_OF(X509_EXTENSION) *exts = NULL;
|
||||
X509_EXTENSION *ex;
|
||||
BIO *out;
|
||||
CONF *ctmp = NULL;
|
||||
|
||||
wpa_printf(MSG_INFO, "Generate RSA private key");
|
||||
write_summary(ctx, "Generate RSA private key");
|
||||
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
|
||||
if (!pctx)
|
||||
return -1;
|
||||
|
||||
if (EVP_PKEY_keygen_init(pctx) <= 0)
|
||||
goto fail;
|
||||
|
||||
if (EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, 2048) <= 0)
|
||||
goto fail;
|
||||
|
||||
if (EVP_PKEY_keygen(pctx, &pkey) <= 0)
|
||||
goto fail;
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
pctx = NULL;
|
||||
|
||||
rsa = EVP_PKEY_get1_RSA(pkey);
|
||||
if (rsa == NULL)
|
||||
goto fail;
|
||||
|
||||
if (key_pem) {
|
||||
FILE *f = fopen(key_pem, "wb");
|
||||
if (f == NULL)
|
||||
goto fail;
|
||||
if (!PEM_write_RSAPrivateKey(f, rsa, NULL, NULL, 0, NULL,
|
||||
NULL)) {
|
||||
wpa_printf(MSG_INFO, "Could not write private key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
fclose(f);
|
||||
goto fail;
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
wpa_printf(MSG_INFO, "Generate CSR");
|
||||
write_summary(ctx, "Generate CSR");
|
||||
req = X509_REQ_new();
|
||||
if (req == NULL)
|
||||
goto fail;
|
||||
|
||||
if (old_cert) {
|
||||
FILE *f;
|
||||
X509 *cert;
|
||||
int res;
|
||||
|
||||
f = fopen(old_cert, "r");
|
||||
if (f == NULL)
|
||||
goto fail;
|
||||
cert = PEM_read_X509(f, NULL, NULL, NULL);
|
||||
fclose(f);
|
||||
|
||||
if (cert == NULL)
|
||||
goto fail;
|
||||
res = X509_REQ_set_subject_name(req,
|
||||
X509_get_subject_name(cert));
|
||||
X509_free(cert);
|
||||
if (!res)
|
||||
goto fail;
|
||||
} else {
|
||||
os_get_random((u8 *) &val, sizeof(val));
|
||||
os_snprintf(name, sizeof(name), "cert-user-%u", val);
|
||||
subj = X509_NAME_new();
|
||||
if (subj == NULL ||
|
||||
!X509_NAME_add_entry_by_txt(subj, "CN", MBSTRING_ASC,
|
||||
(unsigned char *) name,
|
||||
-1, -1, 0) ||
|
||||
!X509_REQ_set_subject_name(req, subj))
|
||||
goto fail;
|
||||
X509_NAME_free(subj);
|
||||
subj = NULL;
|
||||
}
|
||||
|
||||
if (!X509_REQ_set_pubkey(req, pkey))
|
||||
goto fail;
|
||||
|
||||
exts = sk_X509_EXTENSION_new_null();
|
||||
if (!exts)
|
||||
goto fail;
|
||||
|
||||
ex = X509V3_EXT_nconf_nid(ctmp, NULL, NID_basic_constraints,
|
||||
"CA:FALSE");
|
||||
if (ex == NULL ||
|
||||
!sk_X509_EXTENSION_push(exts, ex))
|
||||
goto fail;
|
||||
|
||||
ex = X509V3_EXT_nconf_nid(ctmp, NULL, NID_key_usage,
|
||||
"nonRepudiation,digitalSignature,keyEncipherment");
|
||||
if (ex == NULL ||
|
||||
!sk_X509_EXTENSION_push(exts, ex))
|
||||
goto fail;
|
||||
|
||||
ex = X509V3_EXT_nconf_nid(ctmp, NULL, NID_ext_key_usage,
|
||||
"1.3.6.1.4.1.40808.1.1.2");
|
||||
if (ex == NULL ||
|
||||
!sk_X509_EXTENSION_push(exts, ex))
|
||||
goto fail;
|
||||
|
||||
add_csrattrs(ctx, csrattrs, exts);
|
||||
|
||||
if (!X509_REQ_add_extensions(req, exts))
|
||||
goto fail;
|
||||
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
|
||||
exts = NULL;
|
||||
|
||||
if (!X509_REQ_sign(req, pkey, EVP_sha256()))
|
||||
goto fail;
|
||||
|
||||
out = BIO_new(BIO_s_mem());
|
||||
if (out) {
|
||||
char *txt;
|
||||
size_t rlen;
|
||||
|
||||
#if !defined(ANDROID) || !defined(OPENSSL_IS_BORINGSSL)
|
||||
X509_REQ_print(out, req);
|
||||
#endif
|
||||
rlen = BIO_ctrl_pending(out);
|
||||
txt = os_malloc(rlen + 1);
|
||||
if (txt) {
|
||||
int res = BIO_read(out, txt, rlen);
|
||||
if (res > 0) {
|
||||
txt[res] = '\0';
|
||||
wpa_printf(MSG_MSGDUMP, "OpenSSL: Certificate request:\n%s",
|
||||
txt);
|
||||
}
|
||||
os_free(txt);
|
||||
}
|
||||
BIO_free(out);
|
||||
}
|
||||
|
||||
if (csr_pem) {
|
||||
FILE *f = fopen(csr_pem, "w");
|
||||
if (f == NULL)
|
||||
goto fail;
|
||||
#if !defined(ANDROID) || !defined(OPENSSL_IS_BORINGSSL)
|
||||
X509_REQ_print_fp(f, req);
|
||||
#endif
|
||||
if (!PEM_write_X509_REQ(f, req)) {
|
||||
fclose(f);
|
||||
goto fail;
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
if (est_req) {
|
||||
BIO *mem = BIO_new(BIO_s_mem());
|
||||
BUF_MEM *ptr;
|
||||
char *pos, *end, *buf_end;
|
||||
FILE *f;
|
||||
|
||||
if (mem == NULL)
|
||||
goto fail;
|
||||
if (!PEM_write_bio_X509_REQ(mem, req)) {
|
||||
BIO_free(mem);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
BIO_get_mem_ptr(mem, &ptr);
|
||||
pos = ptr->data;
|
||||
buf_end = pos + ptr->length;
|
||||
|
||||
/* Remove START/END lines */
|
||||
while (pos < buf_end && *pos != '\n')
|
||||
pos++;
|
||||
if (pos == buf_end) {
|
||||
BIO_free(mem);
|
||||
goto fail;
|
||||
}
|
||||
pos++;
|
||||
|
||||
end = pos;
|
||||
while (end < buf_end && *end != '-')
|
||||
end++;
|
||||
|
||||
f = fopen(est_req, "w");
|
||||
if (f == NULL) {
|
||||
BIO_free(mem);
|
||||
goto fail;
|
||||
}
|
||||
fwrite(pos, end - pos, 1, f);
|
||||
fclose(f);
|
||||
|
||||
BIO_free(mem);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
fail:
|
||||
if (exts)
|
||||
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
|
||||
if (subj)
|
||||
X509_NAME_free(subj);
|
||||
if (req)
|
||||
X509_REQ_free(req);
|
||||
if (pkey)
|
||||
EVP_PKEY_free(pkey);
|
||||
if (pctx)
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int est_build_csr(struct hs20_osu_client *ctx, const char *url)
|
||||
{
|
||||
char *buf;
|
||||
size_t buflen;
|
||||
int res;
|
||||
char old_cert_buf[200];
|
||||
char *old_cert = NULL;
|
||||
CsrAttrs *csrattrs = NULL;
|
||||
|
||||
buflen = os_strlen(url) + 100;
|
||||
buf = os_malloc(buflen);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
os_snprintf(buf, buflen, "%s/csrattrs", url);
|
||||
wpa_printf(MSG_INFO, "Download csrattrs from %s", buf);
|
||||
write_summary(ctx, "Download EST csrattrs from %s", buf);
|
||||
ctx->no_osu_cert_validation = 1;
|
||||
http_ocsp_set(ctx->http, 1);
|
||||
res = http_download_file(ctx->http, buf, "Cert/est-csrattrs.txt",
|
||||
ctx->ca_fname);
|
||||
http_ocsp_set(ctx->http,
|
||||
(ctx->workarounds & WORKAROUND_OCSP_OPTIONAL) ? 1 : 2);
|
||||
ctx->no_osu_cert_validation = 0;
|
||||
os_free(buf);
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_INFO, "Failed to download EST csrattrs - assume no extra attributes are needed");
|
||||
} else {
|
||||
size_t resp_len;
|
||||
char *resp;
|
||||
unsigned char *attrs;
|
||||
const unsigned char *pos;
|
||||
size_t attrs_len;
|
||||
|
||||
resp = os_readfile("Cert/est-csrattrs.txt", &resp_len);
|
||||
if (resp == NULL) {
|
||||
wpa_printf(MSG_INFO, "Could not read csrattrs");
|
||||
return -1;
|
||||
}
|
||||
|
||||
attrs = base64_decode(resp, resp_len, &attrs_len);
|
||||
os_free(resp);
|
||||
|
||||
if (attrs == NULL) {
|
||||
wpa_printf(MSG_INFO, "Could not base64 decode csrattrs");
|
||||
return -1;
|
||||
}
|
||||
unlink("Cert/est-csrattrs.txt");
|
||||
|
||||
pos = attrs;
|
||||
csrattrs = d2i_CsrAttrs(NULL, &pos, attrs_len);
|
||||
os_free(attrs);
|
||||
if (csrattrs == NULL) {
|
||||
wpa_printf(MSG_INFO, "Failed to parse csrattrs ASN.1");
|
||||
/* Continue assuming no additional requirements */
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->client_cert_present) {
|
||||
os_snprintf(old_cert_buf, sizeof(old_cert_buf),
|
||||
"SP/%s/client-cert.pem", ctx->fqdn);
|
||||
old_cert = old_cert_buf;
|
||||
}
|
||||
|
||||
res = generate_csr(ctx, "Cert/privkey-plain.pem", "Cert/est-req.pem",
|
||||
"Cert/est-req.b64", old_cert, csrattrs);
|
||||
if (csrattrs)
|
||||
CsrAttrs_free(csrattrs);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int est_simple_enroll(struct hs20_osu_client *ctx, const char *url,
|
||||
const char *user, const char *pw)
|
||||
{
|
||||
char *buf, *resp, *req, *req2;
|
||||
size_t buflen, resp_len, len, pkcs7_len;
|
||||
unsigned char *pkcs7;
|
||||
char client_cert_buf[200];
|
||||
char client_key_buf[200];
|
||||
const char *client_cert = NULL, *client_key = NULL;
|
||||
int res;
|
||||
|
||||
req = os_readfile("Cert/est-req.b64", &len);
|
||||
if (req == NULL) {
|
||||
wpa_printf(MSG_INFO, "Could not read Cert/req.b64");
|
||||
return -1;
|
||||
}
|
||||
req2 = os_realloc(req, len + 1);
|
||||
if (req2 == NULL) {
|
||||
os_free(req);
|
||||
return -1;
|
||||
}
|
||||
req2[len] = '\0';
|
||||
req = req2;
|
||||
wpa_printf(MSG_DEBUG, "EST simpleenroll request: %s", req);
|
||||
|
||||
buflen = os_strlen(url) + 100;
|
||||
buf = os_malloc(buflen);
|
||||
if (buf == NULL) {
|
||||
os_free(req);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ctx->client_cert_present) {
|
||||
os_snprintf(buf, buflen, "%s/simplereenroll", url);
|
||||
os_snprintf(client_cert_buf, sizeof(client_cert_buf),
|
||||
"SP/%s/client-cert.pem", ctx->fqdn);
|
||||
client_cert = client_cert_buf;
|
||||
os_snprintf(client_key_buf, sizeof(client_key_buf),
|
||||
"SP/%s/client-key.pem", ctx->fqdn);
|
||||
client_key = client_key_buf;
|
||||
} else
|
||||
os_snprintf(buf, buflen, "%s/simpleenroll", url);
|
||||
wpa_printf(MSG_INFO, "EST simpleenroll URL: %s", buf);
|
||||
write_summary(ctx, "EST simpleenroll URL: %s", buf);
|
||||
ctx->no_osu_cert_validation = 1;
|
||||
http_ocsp_set(ctx->http, 1);
|
||||
resp = http_post(ctx->http, buf, req, "application/pkcs10",
|
||||
"Content-Transfer-Encoding: base64",
|
||||
ctx->ca_fname, user, pw, client_cert, client_key,
|
||||
&resp_len);
|
||||
http_ocsp_set(ctx->http,
|
||||
(ctx->workarounds & WORKAROUND_OCSP_OPTIONAL) ? 1 : 2);
|
||||
ctx->no_osu_cert_validation = 0;
|
||||
os_free(buf);
|
||||
if (resp == NULL) {
|
||||
wpa_printf(MSG_INFO, "EST certificate enrollment failed");
|
||||
write_result(ctx, "EST certificate enrollment failed");
|
||||
return -1;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "EST simpleenroll response: %s", resp);
|
||||
|
||||
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);
|
||||
if (pkcs7) {
|
||||
os_memcpy(pkcs7, resp, resp_len);
|
||||
pkcs7_len = resp_len;
|
||||
}
|
||||
}
|
||||
os_free(resp);
|
||||
|
||||
if (pkcs7 == NULL) {
|
||||
wpa_printf(MSG_INFO, "Failed to parse simpleenroll base64 response");
|
||||
write_result(ctx, "Failed to parse EST simpleenroll base64 response");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = pkcs7_to_cert(ctx, pkcs7, pkcs7_len, "Cert/est_cert.pem",
|
||||
"Cert/est_cert.der");
|
||||
os_free(pkcs7);
|
||||
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_INFO, "EST: Failed to extract certificate from PKCS7 file");
|
||||
write_result(ctx, "EST: Failed to extract certificate from EST PKCS7 file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_INFO, "EST simple%senroll completed successfully",
|
||||
ctx->client_cert_present ? "re" : "");
|
||||
write_summary(ctx, "EST simple%senroll completed successfully",
|
||||
ctx->client_cert_present ? "re" : "");
|
||||
|
||||
return 0;
|
||||
}
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,121 +0,0 @@
|
|||
/*
|
||||
* Hotspot 2.0 - OSU client
|
||||
* Copyright (c) 2013-2014, Qualcomm Atheros, Inc.
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSU_CLIENT_H
|
||||
#define OSU_CLIENT_H
|
||||
|
||||
#define SPP_NS_URI "http://www.wi-fi.org/specifications/hotspot2dot0/v1.0/spp"
|
||||
|
||||
#define URN_OMA_DM_DEVINFO "urn:oma:mo:oma-dm-devinfo:1.0"
|
||||
#define URN_OMA_DM_DEVDETAIL "urn:oma:mo:oma-dm-devdetail:1.0"
|
||||
#define URN_HS20_DEVDETAIL_EXT "urn:wfa:mo-ext:hotspot2dot0-devdetail-ext:1.0"
|
||||
#define URN_HS20_PPS "urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0"
|
||||
|
||||
|
||||
#define MAX_OSU_VALS 10
|
||||
|
||||
struct osu_lang_text {
|
||||
char lang[4];
|
||||
char text[253];
|
||||
};
|
||||
|
||||
struct hs20_osu_client {
|
||||
struct xml_node_ctx *xml;
|
||||
struct http_ctx *http;
|
||||
int no_reconnect;
|
||||
char pps_fname[300];
|
||||
char *devid;
|
||||
const char *result_file;
|
||||
const char *summary_file;
|
||||
const char *ifname;
|
||||
const char *ca_fname;
|
||||
int no_osu_cert_validation; /* for EST operations */
|
||||
char *fqdn;
|
||||
char *server_url;
|
||||
struct osu_lang_text friendly_name[MAX_OSU_VALS];
|
||||
size_t friendly_name_count;
|
||||
size_t icon_count;
|
||||
char icon_filename[MAX_OSU_VALS][256];
|
||||
u8 icon_hash[MAX_OSU_VALS][32];
|
||||
int pps_cred_set;
|
||||
int pps_updated;
|
||||
int client_cert_present;
|
||||
char **server_dnsname;
|
||||
size_t server_dnsname_count;
|
||||
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 */
|
||||
};
|
||||
|
||||
|
||||
/* osu_client.c */
|
||||
|
||||
void write_result(struct hs20_osu_client *ctx, const char *fmt, ...)
|
||||
__attribute__ ((format (printf, 2, 3)));
|
||||
void write_summary(struct hs20_osu_client *ctx, const char *fmt, ...)
|
||||
__attribute__ ((format (printf, 2, 3)));
|
||||
|
||||
void debug_dump_node(struct hs20_osu_client *ctx, const char *title,
|
||||
xml_node_t *node);
|
||||
int osu_get_certificate(struct hs20_osu_client *ctx, xml_node_t *getcert);
|
||||
int hs20_add_pps_mo(struct hs20_osu_client *ctx, const char *uri,
|
||||
xml_node_t *add_mo, char *fname, size_t fname_len);
|
||||
void get_user_pw(struct hs20_osu_client *ctx, xml_node_t *pps,
|
||||
const char *alt_loc, char **user, char **pw);
|
||||
int update_pps_file(struct hs20_osu_client *ctx, const char *pps_fname,
|
||||
xml_node_t *pps);
|
||||
void cmd_set_pps(struct hs20_osu_client *ctx, const char *pps_fname);
|
||||
|
||||
|
||||
/* spp_client.c */
|
||||
|
||||
void spp_sub_rem(struct hs20_osu_client *ctx, const char *address,
|
||||
const char *pps_fname,
|
||||
const char *client_cert, const char *client_key,
|
||||
const char *cred_username, const char *cred_password,
|
||||
xml_node_t *pps);
|
||||
void spp_pol_upd(struct hs20_osu_client *ctx, const char *address,
|
||||
const char *pps_fname,
|
||||
const char *client_cert, const char *client_key,
|
||||
const char *cred_username, const char *cred_password,
|
||||
xml_node_t *pps);
|
||||
int cmd_prov(struct hs20_osu_client *ctx, const char *url);
|
||||
int cmd_sim_prov(struct hs20_osu_client *ctx, const char *url);
|
||||
|
||||
|
||||
/* oma_dm_client.c */
|
||||
|
||||
int cmd_oma_dm_prov(struct hs20_osu_client *ctx, const char *url);
|
||||
int cmd_oma_dm_sim_prov(struct hs20_osu_client *ctx, const char *url);
|
||||
void oma_dm_sub_rem(struct hs20_osu_client *ctx, const char *address,
|
||||
const char *pps_fname,
|
||||
const char *client_cert, const char *client_key,
|
||||
const char *cred_username, const char *cred_password,
|
||||
xml_node_t *pps);
|
||||
void oma_dm_pol_upd(struct hs20_osu_client *ctx, const char *address,
|
||||
const char *pps_fname,
|
||||
const char *client_cert, const char *client_key,
|
||||
const char *cred_username, const char *cred_password,
|
||||
xml_node_t *pps);
|
||||
void cmd_oma_dm_sub_rem(struct hs20_osu_client *ctx, const char *address,
|
||||
const char *pps_fname);
|
||||
void cmd_oma_dm_add(struct hs20_osu_client *ctx, const char *pps_fname,
|
||||
const char *add_fname);
|
||||
void cmd_oma_dm_replace(struct hs20_osu_client *ctx, const char *pps_fname,
|
||||
const char *replace_fname);
|
||||
|
||||
/* est.c */
|
||||
|
||||
int est_load_cacerts(struct hs20_osu_client *ctx, const char *url);
|
||||
int est_build_csr(struct hs20_osu_client *ctx, const char *url);
|
||||
int est_simple_enroll(struct hs20_osu_client *ctx, const char *url,
|
||||
const char *user, const char *pw);
|
||||
|
||||
#endif /* OSU_CLIENT_H */
|
File diff suppressed because it is too large
Load diff
1
hs20/server/.gitignore
vendored
1
hs20/server/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
hs20_spp_server
|
|
@ -1,42 +0,0 @@
|
|||
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 *~
|
|
@ -1,13 +0,0 @@
|
|||
#!/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
|
|
@ -1,17 +0,0 @@
|
|||
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
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
openssl asn1parse -genconf est-csrattrs.cnf -out est-csrattrs.der -oid hs20.oid
|
||||
base64 est-csrattrs.der > est-attrs.b64
|
|
@ -1,7 +0,0 @@
|
|||
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
|
|
@ -1,11 +0,0 @@
|
|||
#!/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
|
|
@ -1,3 +0,0 @@
|
|||
#!/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
|
|
@ -1,3 +0,0 @@
|
|||
#!/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
|
|
@ -1,11 +0,0 @@
|
|||
#!/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
|
|
@ -1,125 +0,0 @@
|
|||
# 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
|
|
@ -1,200 +0,0 @@
|
|||
# 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
|
|
@ -1,209 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
if [ -z "$OPENSSL" ]; then
|
||||
OPENSSL=openssl
|
||||
fi
|
||||
export OPENSSL_CONF=$PWD/openssl.cnf
|
||||
PASS=whatever
|
||||
if [ -z "$DOMAIN" ]; then
|
||||
DOMAIN=w1.fi
|
||||
fi
|
||||
COMPANY=w1.fi
|
||||
OPER_ENG="engw1.fi TESTING USE"
|
||||
OPER_FI="finw1.fi TESTIKÄYTTÖ"
|
||||
CNR="Hotspot 2.0 Trust Root CA - 99"
|
||||
CNO="ocsp.$DOMAIN"
|
||||
CNV="osu-revoked.$DOMAIN"
|
||||
CNOC="osu-client.$DOMAIN"
|
||||
OSU_SERVER_HOSTNAME="osu.$DOMAIN"
|
||||
DEBUG=0
|
||||
OCSP_URI="http://$CNO:8888/"
|
||||
LOGO_URI="http://osu.w1.fi/w1fi_logo.png"
|
||||
LOGO_HASH256="4532f7ec36424381617c03c6ce87b55a51d6e7177ffafda243cebf280a68954d"
|
||||
LOGO_HASH1="5e1d5085676eede6b02da14d31c523ec20ffba0b"
|
||||
|
||||
# Command line overrides
|
||||
USAGE=$( cat <<EOF
|
||||
Usage:\n
|
||||
# -c: Company name, used to generate Subject name CN for Intermediate CA\n
|
||||
# -C: Subject name CN of the Root CA ($CNR)\n
|
||||
# -D: Enable debugging (set -x, etc)\n
|
||||
# -g: Logo sha1 hash ($LOGO_HASH1)\n
|
||||
# -G: Logo sha256 hash ($LOGO_HASH256)\n
|
||||
# -h: Show this help message\n
|
||||
# -l: Logo URI ($LOGO_URI)\n
|
||||
# -m: Domain ($DOMAIN)\n
|
||||
# -o: Subject name CN for OSU-Client Server ($CNOC)\n
|
||||
# -O: Subject name CN for OCSP Server ($CNO)\n
|
||||
# -p: passphrase for private keys ($PASS)\n
|
||||
# -r: Operator-english ($OPER_ENG)\n
|
||||
# -R: Operator-finish ($OPER_FI)\n
|
||||
# -S: OSU Server name ($OSU_SERVER_HOSTNAME)\n
|
||||
# -u: OCSP-URI ($OCSP_URI)\n
|
||||
# -V: Subject name CN for OSU-Revoked Server ($CNV)\n
|
||||
EOF
|
||||
)
|
||||
|
||||
while getopts "c:C:Dg:G:l:m:o:O:p:r:R:S:u:V:h" flag
|
||||
do
|
||||
case $flag in
|
||||
c) COMPANY=$OPTARG;;
|
||||
C) CNR=$OPTARG;;
|
||||
D) DEBUG=1;;
|
||||
g) LOGO_HASH1=$OPTARG;;
|
||||
G) LOGO_HASH256=$OPTARG;;
|
||||
h) echo -e $USAGE; exit 0;;
|
||||
l) LOGO_URI=$OPTARG;;
|
||||
m) DOMAIN=$OPTARG;;
|
||||
o) CNOC=$OPTARG;;
|
||||
O) CNO=$OPTARG;;
|
||||
p) PASS=$OPTARG;;
|
||||
r) OPER_ENG=$OPTARG;;
|
||||
R) OPER_FI=$OPTARG;;
|
||||
S) OSU_SERVER_HOSTNAME=$OPTARG;;
|
||||
u) OCSP_URI=$OPTARG;;
|
||||
V) CNV=$OPTARG;;
|
||||
*) echo "Unknown flag: $flag"; echo -e $USAGE; exit 1;;
|
||||
esac
|
||||
done
|
||||
|
||||
fail()
|
||||
{
|
||||
echo "$*"
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo
|
||||
echo "---[ Root CA ]----------------------------------------------------------"
|
||||
echo
|
||||
|
||||
if [ $DEBUG = 1 ]
|
||||
then
|
||||
set -x
|
||||
fi
|
||||
|
||||
# Set the passphrase and some other common config accordingly.
|
||||
cat openssl-root.cnf | sed "s/@PASSWORD@/$PASS/" \
|
||||
> my-openssl-root.cnf
|
||||
|
||||
cat openssl.cnf | sed "s/@PASSWORD@/$PASS/" |
|
||||
sed "s,@OCSP_URI@,$OCSP_URI," |
|
||||
sed "s,@LOGO_URI@,$LOGO_URI," |
|
||||
sed "s,@LOGO_HASH1@,$LOGO_HASH1," |
|
||||
sed "s,@LOGO_HASH256@,$LOGO_HASH256," |
|
||||
sed "s/@DOMAIN@/$DOMAIN/" \
|
||||
> my-openssl.cnf
|
||||
|
||||
|
||||
cat my-openssl-root.cnf | sed "s/#@CN@/commonName_default = $CNR/" > openssl.cnf.tmp
|
||||
mkdir -p rootCA/certs rootCA/crl rootCA/newcerts rootCA/private
|
||||
touch rootCA/index.txt
|
||||
if [ -e rootCA/private/cakey.pem ]; then
|
||||
echo " * Use existing Root CA"
|
||||
else
|
||||
echo " * Generate Root CA private key"
|
||||
$OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:4096 -keyout rootCA/private/cakey.pem -out rootCA/careq.pem || fail "Failed to generate Root CA private key"
|
||||
echo " * Sign Root CA certificate"
|
||||
$OPENSSL ca -config openssl.cnf.tmp -md sha256 -create_serial -out rootCA/cacert.pem -days 10957 -batch -keyfile rootCA/private/cakey.pem -passin pass:$PASS -selfsign -extensions v3_ca -outdir rootCA/newcerts -infiles rootCA/careq.pem || fail "Failed to sign Root CA certificate"
|
||||
$OPENSSL x509 -in rootCA/cacert.pem -out rootCA/cacert.der -outform DER || fail "Failed to create rootCA DER"
|
||||
sha256sum rootCA/cacert.der > rootCA/cacert.fingerprint || fail "Failed to create rootCA fingerprint"
|
||||
fi
|
||||
if [ ! -e rootCA/crlnumber ]; then
|
||||
echo 00 > rootCA/crlnumber
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "---[ Intermediate CA ]--------------------------------------------------"
|
||||
echo
|
||||
|
||||
cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $COMPANY Hotspot 2.0 Intermediate CA/" > openssl.cnf.tmp
|
||||
mkdir -p demoCA/certs demoCA/crl demoCA/newcerts demoCA/private
|
||||
touch demoCA/index.txt
|
||||
if [ -e demoCA/private/cakey.pem ]; then
|
||||
echo " * Use existing Intermediate CA"
|
||||
else
|
||||
echo " * Generate Intermediate CA private key"
|
||||
$OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -keyout demoCA/private/cakey.pem -out demoCA/careq.pem || fail "Failed to generate Intermediate CA private key"
|
||||
echo " * Sign Intermediate CA certificate"
|
||||
$OPENSSL ca -config openssl.cnf.tmp -md sha256 -create_serial -out demoCA/cacert.pem -days 3652 -batch -keyfile rootCA/private/cakey.pem -cert rootCA/cacert.pem -passin pass:$PASS -extensions v3_ca -infiles demoCA/careq.pem || fail "Failed to sign Intermediate CA certificate"
|
||||
# horrible from security view point, but for testing purposes since OCSP responder does not seem to support -passin
|
||||
openssl rsa -in demoCA/private/cakey.pem -out demoCA/private/cakey-plain.pem -passin pass:$PASS
|
||||
$OPENSSL x509 -in demoCA/cacert.pem -out demoCA/cacert.der -outform DER || fail "Failed to create demoCA DER."
|
||||
sha256sum demoCA/cacert.der > demoCA/cacert.fingerprint || fail "Failed to create demoCA fingerprint"
|
||||
fi
|
||||
if [ ! -e demoCA/crlnumber ]; then
|
||||
echo 00 > demoCA/crlnumber
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "OCSP responder"
|
||||
echo
|
||||
|
||||
cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $CNO/" > openssl.cnf.tmp
|
||||
$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out ocsp.csr -keyout ocsp.key -extensions v3_OCSP
|
||||
$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -keyfile demoCA/private/cakey.pem -passin pass:$PASS -in ocsp.csr -out ocsp.pem -days 730 -extensions v3_OCSP || fail "Could not generate ocsp.pem"
|
||||
|
||||
echo
|
||||
echo "---[ Server - to be revoked ] ------------------------------------------"
|
||||
echo
|
||||
|
||||
cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $CNV/" > openssl.cnf.tmp
|
||||
$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out server-revoked.csr -keyout server-revoked.key
|
||||
$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in server-revoked.csr -out server-revoked.pem -key $PASS -days 730 -extensions ext_server
|
||||
$OPENSSL ca -revoke server-revoked.pem -key $PASS
|
||||
|
||||
echo
|
||||
echo "---[ Server - with client ext key use ] ---------------------------------"
|
||||
echo "---[ Only used for negative-testing for OSU-client implementation ] -----"
|
||||
echo
|
||||
|
||||
cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $CNOC/" > openssl.cnf.tmp
|
||||
$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out server-client.csr -keyout server-client.key || fail "Could not create server-client.key"
|
||||
$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in server-client.csr -out server-client.pem -key $PASS -days 730 -extensions ext_client || fail "Could not create server-client.pem"
|
||||
|
||||
echo
|
||||
echo "---[ User ]-------------------------------------------------------------"
|
||||
echo
|
||||
|
||||
cat my-openssl.cnf | sed "s/#@CN@/commonName_default = User/" > openssl.cnf.tmp
|
||||
$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out user.csr -keyout user.key || fail "Could not create user.key"
|
||||
$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in user.csr -out user.pem -key $PASS -days 730 -extensions ext_client || fail "Could not create user.pem"
|
||||
|
||||
echo
|
||||
echo "---[ Server ]-----------------------------------------------------------"
|
||||
echo
|
||||
|
||||
ALT="DNS:$OSU_SERVER_HOSTNAME"
|
||||
ALT="$ALT,otherName:1.3.6.1.4.1.40808.1.1.1;UTF8String:$OPER_ENG"
|
||||
ALT="$ALT,otherName:1.3.6.1.4.1.40808.1.1.1;UTF8String:$OPER_FI"
|
||||
|
||||
cat my-openssl.cnf |
|
||||
sed "s/#@CN@/commonName_default = $OSU_SERVER_HOSTNAME/" |
|
||||
sed "s/^##organizationalUnitName/organizationalUnitName/" |
|
||||
sed "s/#@OU@/organizationalUnitName_default = Hotspot 2.0 Online Sign Up Server/" |
|
||||
sed "s/#@ALTNAME@/subjectAltName=critical,$ALT/" \
|
||||
> openssl.cnf.tmp
|
||||
echo $OPENSSL req -config $PWD/openssl.cnf.tmp -batch -sha256 -new -newkey rsa:2048 -nodes -out server.csr -keyout server.key -reqexts v3_osu_server
|
||||
$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -sha256 -new -newkey rsa:2048 -nodes -out server.csr -keyout server.key -reqexts v3_osu_server || fail "Failed to generate server request"
|
||||
$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in server.csr -out server.pem -key $PASS -days 730 -extensions ext_server -policy policy_osu_server || fail "Failed to sign server certificate"
|
||||
|
||||
#dump logotype details for debugging
|
||||
$OPENSSL x509 -in server.pem -out server.der -outform DER
|
||||
openssl asn1parse -in server.der -inform DER | grep HEX | tail -1 | sed 's/.*://' | xxd -r -p > logo.der
|
||||
openssl asn1parse -in logo.der -inform DER > logo.asn1
|
||||
|
||||
|
||||
echo
|
||||
echo "---[ CRL ]---------------------------------------------------------------"
|
||||
echo
|
||||
|
||||
$OPENSSL ca -config $PWD/my-openssl.cnf -gencrl -md sha256 -out demoCA/crl/crl.pem -passin pass:$PASS
|
||||
|
||||
echo
|
||||
echo "---[ Verify ]------------------------------------------------------------"
|
||||
echo
|
||||
|
||||
$OPENSSL verify -CAfile rootCA/cacert.pem demoCA/cacert.pem
|
||||
$OPENSSL verify -CAfile rootCA/cacert.pem -untrusted demoCA/cacert.pem *.pem
|
||||
|
||||
cat rootCA/cacert.pem demoCA/cacert.pem > ca.pem
|
Binary file not shown.
Before Width: | Height: | Size: 7.4 KiB |
|
@ -1,262 +0,0 @@
|
|||
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
|
|
@ -1,207 +0,0 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* 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 */
|
|
@ -1,17 +0,0 @@
|
|||
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');
|
|
@ -1,108 +0,0 @@
|
|||
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
|
||||
);
|
|
@ -1,50 +0,0 @@
|
|||
<?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);
|
||||
|
||||
?>
|
|
@ -1,56 +0,0 @@
|
|||
<?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);
|
||||
|
||||
?>
|
|
@ -1,39 +0,0 @@
|
|||
<?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);
|
||||
|
||||
?>
|
|
@ -1,7 +0,0 @@
|
|||
<?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"
|
||||
?>
|
|
@ -1,232 +0,0 @@
|
|||
<?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");
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,19 +0,0 @@
|
|||
<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>
|
|
@ -1,23 +0,0 @@
|
|||
<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>
|
|
@ -1,32 +0,0 @@
|
|||
<?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')");
|
||||
|
||||
?>
|
|
@ -1,41 +0,0 @@
|
|||
<?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);
|
||||
|
||||
?>
|
|
@ -1,55 +0,0 @@
|
|||
<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>
|
|
@ -1,59 +0,0 @@
|
|||
<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>
|
|
@ -1,168 +0,0 @@
|
|||
<?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);
|
||||
|
||||
?>
|
|
@ -1,87 +0,0 @@
|
|||
<?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>
|
|
@ -1,377 +0,0 @@
|
|||
<?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
2
radius_example/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
|||
*.d
|
||||
radius_example
|
|
@ -1,28 +0,0 @@
|
|||
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
|
|
@ -1,35 +0,0 @@
|
|||
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().
|
|
@ -1,153 +0,0 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
|
@ -213,3 +213,37 @@ int dragonfly_generate_scalar(const struct crypto_bignum *order,
|
|||
"dragonfly: Unable to get randomness for own scalar");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* res = sqrt(val) */
|
||||
int dragonfly_sqrt(struct crypto_ec *ec, const struct crypto_bignum *val,
|
||||
struct crypto_bignum *res)
|
||||
{
|
||||
const struct crypto_bignum *prime;
|
||||
struct crypto_bignum *tmp, *one;
|
||||
int ret = 0;
|
||||
u8 prime_bin[DRAGONFLY_MAX_ECC_PRIME_LEN];
|
||||
size_t prime_len;
|
||||
|
||||
/* For prime p such that p = 3 mod 4, sqrt(w) = w^((p+1)/4) mod p */
|
||||
|
||||
prime = crypto_ec_get_prime(ec);
|
||||
prime_len = crypto_ec_prime_len(ec);
|
||||
tmp = crypto_bignum_init();
|
||||
one = crypto_bignum_init_uint(1);
|
||||
|
||||
if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin),
|
||||
prime_len) < 0 ||
|
||||
(prime_bin[prime_len - 1] & 0x03) != 3 ||
|
||||
!tmp || !one ||
|
||||
/* tmp = (p+1)/4 */
|
||||
crypto_bignum_add(prime, one, tmp) < 0 ||
|
||||
crypto_bignum_rshift(tmp, 2, tmp) < 0 ||
|
||||
/* res = sqrt(val) */
|
||||
crypto_bignum_exptmod(val, tmp, prime, res) < 0)
|
||||
ret = -1;
|
||||
|
||||
crypto_bignum_deinit(tmp, 0);
|
||||
crypto_bignum_deinit(one, 0);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -27,5 +27,7 @@ int dragonfly_generate_scalar(const struct crypto_bignum *order,
|
|||
struct crypto_bignum *_rand,
|
||||
struct crypto_bignum *_mask,
|
||||
struct crypto_bignum *scalar);
|
||||
int dragonfly_sqrt(struct crypto_ec *ec, const struct crypto_bignum *val,
|
||||
struct crypto_bignum *res);
|
||||
|
||||
#endif /* DRAGONFLY_H */
|
||||
|
|
|
@ -1462,6 +1462,11 @@ enum qca_wlan_vendor_attr_p2p_listen_offload {
|
|||
* Used with event to notify the puncture pattern selected in ACS operation.
|
||||
* Encoding for this attribute will follow the convention used in the Disabled
|
||||
* Subchannel Bitmap field of the EHT Operation IE.
|
||||
*
|
||||
* @QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED: Flag attribute.
|
||||
* Used with command to configure ACS operation for EHT mode.
|
||||
* Disable (flag attribute not present) - EHT disabled and
|
||||
* Enable (flag attribute present) - EHT enabled.
|
||||
*/
|
||||
enum qca_wlan_vendor_attr_acs_offload {
|
||||
QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0,
|
||||
|
@ -1483,6 +1488,7 @@ enum qca_wlan_vendor_attr_acs_offload {
|
|||
QCA_WLAN_VENDOR_ATTR_ACS_EDMG_ENABLED = 16,
|
||||
QCA_WLAN_VENDOR_ATTR_ACS_EDMG_CHANNEL = 17,
|
||||
QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP = 18,
|
||||
QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED = 19,
|
||||
|
||||
/* keep last */
|
||||
QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST,
|
||||
|
@ -1788,36 +1794,53 @@ enum qca_access_policy {
|
|||
};
|
||||
|
||||
/**
|
||||
* enum qca_vendor_attr_get_tsf: Vendor attributes for TSF capture
|
||||
* @QCA_WLAN_VENDOR_ATTR_TSF_CMD: enum qca_tsf_operation (u32)
|
||||
* @QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE: Unsigned 64 bit TSF timer value
|
||||
* @QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE: Unsigned 64 bit Synchronized
|
||||
* SOC timer value at TSF capture
|
||||
* enum qca_vendor_attr_tsf_cmd: Vendor attributes for TSF capture
|
||||
* @QCA_WLAN_VENDOR_ATTR_TSF_CMD: Required (u32)
|
||||
* Specify the TSF command. Possible values are defined in
|
||||
* &enum qca_tsf_cmd.
|
||||
* @QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE: Optional (u64)
|
||||
* This attribute contains TSF timer value. This attribute is only available
|
||||
* in %QCA_TSF_GET or %QCA_TSF_SYNC_GET response.
|
||||
* @QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE: Optional (u64)
|
||||
* This attribute contains SOC timer value at TSF capture. This attribute is
|
||||
* only available in %QCA_TSF_GET or %QCA_TSF_SYNC_GET response.
|
||||
* @QCA_WLAN_VENDOR_ATTR_TSF_SYNC_INTERVAL: Optional (u32)
|
||||
* This attribute is used to provide TSF sync interval and only applicable when
|
||||
* TSF command is %QCA_TSF_SYNC_START. If this attribute is not provided, the
|
||||
* driver will use the default value. Time unit is in milliseconds.
|
||||
*/
|
||||
enum qca_vendor_attr_tsf_cmd {
|
||||
QCA_WLAN_VENDOR_ATTR_TSF_INVALID = 0,
|
||||
QCA_WLAN_VENDOR_ATTR_TSF_CMD,
|
||||
QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE,
|
||||
QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE,
|
||||
QCA_WLAN_VENDOR_ATTR_TSF_SYNC_INTERVAL,
|
||||
QCA_WLAN_VENDOR_ATTR_TSF_AFTER_LAST,
|
||||
QCA_WLAN_VENDOR_ATTR_TSF_MAX =
|
||||
QCA_WLAN_VENDOR_ATTR_TSF_AFTER_LAST - 1
|
||||
};
|
||||
|
||||
/**
|
||||
* enum qca_tsf_operation: TSF driver commands
|
||||
* enum qca_tsf_cmd: TSF driver commands
|
||||
* @QCA_TSF_CAPTURE: Initiate TSF Capture
|
||||
* @QCA_TSF_GET: Get TSF capture value
|
||||
* @QCA_TSF_SYNC_GET: Initiate TSF capture and return with captured value
|
||||
* @QCA_TSF_AUTO_REPORT_ENABLE: Used in STA mode only. Once set, the target
|
||||
* will automatically send TSF report to the host. To query
|
||||
* QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY, this operation needs to be
|
||||
* %QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY, this operation needs to be
|
||||
* initiated first.
|
||||
* @QCA_TSF_AUTO_REPORT_DISABLE: Used in STA mode only. Once set, the target
|
||||
* will not automatically send TSF report to the host. If
|
||||
* QCA_TSF_AUTO_REPORT_ENABLE is initiated and
|
||||
* QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY is not queried anymore, this
|
||||
* %QCA_TSF_AUTO_REPORT_ENABLE is initiated and
|
||||
* %QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY is not queried anymore, this
|
||||
* operation needs to be initiated.
|
||||
* @QCA_TSF_SYNC_START: Start periodic TSF sync feature. The driver periodically
|
||||
* fetches TSF and host time mapping from the firmware with interval configured
|
||||
* through the %QCA_WLAN_VENDOR_ATTR_TSF_SYNC_INTERVAL attribute. If the
|
||||
* interval value is not provided the driver will use the default value. The
|
||||
* userspace can query the TSF and host time mapping via the %QCA_TSF_GET
|
||||
* command.
|
||||
* @QCA_TSF_SYNC_STOP: Stop periodic TSF sync feature.
|
||||
*/
|
||||
enum qca_tsf_cmd {
|
||||
QCA_TSF_CAPTURE,
|
||||
|
@ -1825,6 +1848,8 @@ enum qca_tsf_cmd {
|
|||
QCA_TSF_SYNC_GET,
|
||||
QCA_TSF_AUTO_REPORT_ENABLE,
|
||||
QCA_TSF_AUTO_REPORT_DISABLE,
|
||||
QCA_TSF_SYNC_START,
|
||||
QCA_TSF_SYNC_STOP,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -290,14 +290,16 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
|
|||
int pwd_seed_odd = 0;
|
||||
u8 prime[SAE_MAX_ECC_PRIME_LEN];
|
||||
size_t prime_len;
|
||||
struct crypto_bignum *x = NULL, *qr = NULL, *qnr = NULL;
|
||||
struct crypto_bignum *x = NULL, *y = NULL, *qr = NULL, *qnr = NULL;
|
||||
u8 x_bin[SAE_MAX_ECC_PRIME_LEN];
|
||||
u8 x_cand_bin[SAE_MAX_ECC_PRIME_LEN];
|
||||
u8 qr_bin[SAE_MAX_ECC_PRIME_LEN];
|
||||
u8 qnr_bin[SAE_MAX_ECC_PRIME_LEN];
|
||||
u8 x_y[2 * SAE_MAX_ECC_PRIME_LEN];
|
||||
int res = -1;
|
||||
u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
|
||||
* mask */
|
||||
unsigned int is_eq;
|
||||
|
||||
os_memset(x_bin, 0, sizeof(x_bin));
|
||||
|
||||
|
@ -396,25 +398,42 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (!sae->tmp->pwe_ecc)
|
||||
sae->tmp->pwe_ecc = crypto_ec_point_init(sae->tmp->ec);
|
||||
if (!sae->tmp->pwe_ecc)
|
||||
res = -1;
|
||||
else
|
||||
res = crypto_ec_point_solve_y_coord(sae->tmp->ec,
|
||||
sae->tmp->pwe_ecc, x,
|
||||
pwd_seed_odd);
|
||||
if (res < 0) {
|
||||
/*
|
||||
* This should not happen since we already checked that there
|
||||
* is a result.
|
||||
*/
|
||||
/* y = sqrt(x^3 + ax + b) mod p
|
||||
* if LSB(save) == LSB(y): PWE = (x, y)
|
||||
* else: PWE = (x, p - y)
|
||||
*
|
||||
* Calculate y and the two possible values for PWE and after that,
|
||||
* use constant time selection to copy the correct alternative.
|
||||
*/
|
||||
y = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x);
|
||||
if (!y ||
|
||||
dragonfly_sqrt(sae->tmp->ec, y, y) < 0 ||
|
||||
crypto_bignum_to_bin(y, x_y, SAE_MAX_ECC_PRIME_LEN,
|
||||
prime_len) < 0 ||
|
||||
crypto_bignum_sub(sae->tmp->prime, y, y) < 0 ||
|
||||
crypto_bignum_to_bin(y, x_y + SAE_MAX_ECC_PRIME_LEN,
|
||||
SAE_MAX_ECC_PRIME_LEN, prime_len) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "SAE: Could not solve y");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
is_eq = const_time_eq(pwd_seed_odd, x_y[prime_len - 1] & 0x01);
|
||||
const_time_select_bin(is_eq, x_y, x_y + SAE_MAX_ECC_PRIME_LEN,
|
||||
prime_len, x_y + prime_len);
|
||||
os_memcpy(x_y, x_bin, prime_len);
|
||||
wpa_hexdump_key(MSG_DEBUG, "SAE: PWE", x_y, 2 * prime_len);
|
||||
crypto_ec_point_deinit(sae->tmp->pwe_ecc, 1);
|
||||
sae->tmp->pwe_ecc = crypto_ec_point_from_bin(sae->tmp->ec, x_y);
|
||||
if (!sae->tmp->pwe_ecc) {
|
||||
wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE");
|
||||
res = -1;
|
||||
}
|
||||
|
||||
fail:
|
||||
forced_memzero(x_y, sizeof(x_y));
|
||||
crypto_bignum_deinit(qr, 0);
|
||||
crypto_bignum_deinit(qnr, 0);
|
||||
crypto_bignum_deinit(y, 1);
|
||||
os_free(stub_password);
|
||||
bin_clear_free(tmp_password, password_len);
|
||||
crypto_bignum_deinit(x, 1);
|
||||
|
@ -747,19 +766,9 @@ static struct crypto_ec_point * sswu(struct crypto_ec *ec, int group,
|
|||
const_time_select_bin(is_qr, bin1, bin2, prime_len, x_y);
|
||||
wpa_hexdump_key(MSG_DEBUG, "SSWU: x = CSEL(l, x1, x2)", x_y, prime_len);
|
||||
|
||||
/* y = sqrt(v)
|
||||
* For prime p such that p = 3 mod 4 --> v^((p+1)/4) */
|
||||
if (crypto_bignum_to_bin(prime, bin1, sizeof(bin1), prime_len) < 0)
|
||||
goto fail;
|
||||
if ((bin1[prime_len - 1] & 0x03) != 3) {
|
||||
wpa_printf(MSG_DEBUG, "SSWU: prime does not have p = 3 mod 4");
|
||||
goto fail;
|
||||
}
|
||||
/* y = sqrt(v) */
|
||||
y = crypto_bignum_init();
|
||||
if (!y ||
|
||||
crypto_bignum_add(prime, one, t1) < 0 ||
|
||||
crypto_bignum_rshift(t1, 2, t1) < 0 ||
|
||||
crypto_bignum_exptmod(v, t1, prime, y) < 0)
|
||||
if (!y || dragonfly_sqrt(ec, v, y) < 0)
|
||||
goto fail;
|
||||
debug_print_bignum("SSWU: y = sqrt(v)", y, prime_len);
|
||||
|
||||
|
|
|
@ -9,6 +9,6 @@
|
|||
#define GIT_VERSION_STR_POSTFIX ""
|
||||
#endif /* GIT_VERSION_STR_POSTFIX */
|
||||
|
||||
#define VERSION_STR "2.10-devel" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX
|
||||
#define VERSION_STR "2.10" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX
|
||||
|
||||
#endif /* VERSION_H */
|
||||
|
|
|
@ -882,18 +882,6 @@ int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p,
|
|||
*/
|
||||
int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p);
|
||||
|
||||
/**
|
||||
* crypto_ec_point_solve_y_coord - Solve y coordinate for an x coordinate
|
||||
* @e: EC context from crypto_ec_init()
|
||||
* @p: EC point to use for the returning the result
|
||||
* @x: x coordinate
|
||||
* @y_bit: y-bit (0 or 1) for selecting the y value to use
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
|
||||
struct crypto_ec_point *p,
|
||||
const struct crypto_bignum *x, int y_bit);
|
||||
|
||||
/**
|
||||
* crypto_ec_point_compute_y_sqr - Compute y^2 = x^3 + ax + b
|
||||
* @e: EC context from crypto_ec_init()
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
#include <openssl/x509.h>
|
||||
#include <openssl/pem.h>
|
||||
#endif /* CONFIG_ECC */
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
#include <openssl/provider.h>
|
||||
#endif /* OpenSSL version >= 3.0 */
|
||||
|
||||
#include "common.h"
|
||||
#include "utils/const_time.h"
|
||||
|
@ -117,6 +120,26 @@ static const unsigned char * ASN1_STRING_get0_data(const ASN1_STRING *x)
|
|||
}
|
||||
#endif /* OpenSSL version < 1.1.0 */
|
||||
|
||||
|
||||
void openssl_load_legacy_provider(void)
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
static bool loaded = false;
|
||||
OSSL_PROVIDER *legacy;
|
||||
|
||||
if (loaded)
|
||||
return;
|
||||
|
||||
legacy = OSSL_PROVIDER_load(NULL, "legacy");
|
||||
|
||||
if (legacy) {
|
||||
OSSL_PROVIDER_load(NULL, "default");
|
||||
loaded = true;
|
||||
}
|
||||
#endif /* OpenSSL version >= 3.0 */
|
||||
}
|
||||
|
||||
|
||||
static BIGNUM * get_group5_prime(void)
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
|
||||
|
@ -223,6 +246,7 @@ static int openssl_digest_vector(const EVP_MD *type, size_t num_elem,
|
|||
#ifndef CONFIG_FIPS
|
||||
int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
openssl_load_legacy_provider();
|
||||
return openssl_digest_vector(EVP_md4(), num_elem, addr, len, mac);
|
||||
}
|
||||
#endif /* CONFIG_FIPS */
|
||||
|
@ -234,6 +258,8 @@ int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
|
|||
int i, plen, ret = -1;
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
|
||||
openssl_load_legacy_provider();
|
||||
|
||||
/* Add parity bits to the key */
|
||||
next = 0;
|
||||
for (i = 0; i < 7; i++) {
|
||||
|
@ -271,6 +297,8 @@ int rc4_skip(const u8 *key, size_t keylen, size_t skip,
|
|||
int res = -1;
|
||||
unsigned char skip_buf[16];
|
||||
|
||||
openssl_load_legacy_provider();
|
||||
|
||||
ctx = EVP_CIPHER_CTX_new();
|
||||
if (!ctx ||
|
||||
!EVP_CipherInit_ex(ctx, EVP_rc4(), NULL, NULL, NULL, 1) ||
|
||||
|
@ -1923,48 +1951,27 @@ int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p)
|
|||
}
|
||||
|
||||
|
||||
int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
|
||||
struct crypto_ec_point *p,
|
||||
const struct crypto_bignum *x, int y_bit)
|
||||
{
|
||||
if (TEST_FAIL())
|
||||
return -1;
|
||||
if (!EC_POINT_set_compressed_coordinates_GFp(e->group, (EC_POINT *) p,
|
||||
(const BIGNUM *) x, y_bit,
|
||||
e->bnctx) ||
|
||||
!EC_POINT_is_on_curve(e->group, (EC_POINT *) p, e->bnctx))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct crypto_bignum *
|
||||
crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
|
||||
const struct crypto_bignum *x)
|
||||
{
|
||||
BIGNUM *tmp, *tmp2, *y_sqr = NULL;
|
||||
BIGNUM *tmp;
|
||||
|
||||
if (TEST_FAIL())
|
||||
return NULL;
|
||||
|
||||
tmp = BN_new();
|
||||
tmp2 = BN_new();
|
||||
|
||||
/* y^2 = x^3 + ax + b */
|
||||
if (tmp && tmp2 &&
|
||||
/* y^2 = x^3 + ax + b = (x^2 + a)x + b */
|
||||
if (tmp &&
|
||||
BN_mod_sqr(tmp, (const BIGNUM *) x, e->prime, e->bnctx) &&
|
||||
BN_mod_add_quick(tmp, e->a, tmp, e->prime) &&
|
||||
BN_mod_mul(tmp, tmp, (const BIGNUM *) x, e->prime, e->bnctx) &&
|
||||
BN_mod_mul(tmp2, e->a, (const BIGNUM *) x, e->prime, e->bnctx) &&
|
||||
BN_mod_add_quick(tmp2, tmp2, tmp, e->prime) &&
|
||||
BN_mod_add_quick(tmp2, tmp2, e->b, e->prime)) {
|
||||
y_sqr = tmp2;
|
||||
tmp2 = NULL;
|
||||
}
|
||||
BN_mod_add_quick(tmp, tmp, e->b, e->prime))
|
||||
return (struct crypto_bignum *) tmp;
|
||||
|
||||
BN_clear_free(tmp);
|
||||
BN_clear_free(tmp2);
|
||||
|
||||
return (struct crypto_bignum *) y_sqr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2480,12 +2487,13 @@ struct crypto_ec_key * crypto_ec_key_gen(int group)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
eckey = EVP_PKEY_get0_EC_KEY(key);
|
||||
eckey = EVP_PKEY_get1_EC_KEY(key);
|
||||
if (!eckey) {
|
||||
key = NULL;
|
||||
goto fail;
|
||||
}
|
||||
EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
|
||||
EC_KEY_free(eckey);
|
||||
|
||||
fail:
|
||||
EC_KEY_free(ec_params);
|
||||
|
@ -2595,12 +2603,34 @@ struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key)
|
|||
unsigned char *der = NULL;
|
||||
int der_len;
|
||||
struct wpabuf *buf;
|
||||
EC_KEY *eckey;
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
EVP_PKEY *tmp;
|
||||
#endif /* OpenSSL version >= 3.0 */
|
||||
|
||||
eckey = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) key);
|
||||
if (!eckey)
|
||||
return NULL;
|
||||
|
||||
/* For now, all users expect COMPRESSED form */
|
||||
EC_KEY_set_conv_form(EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key),
|
||||
POINT_CONVERSION_COMPRESSED);
|
||||
EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
tmp = EVP_PKEY_new();
|
||||
if (!tmp)
|
||||
return NULL;
|
||||
if (EVP_PKEY_set1_EC_KEY(tmp, eckey) != 1) {
|
||||
EVP_PKEY_free(tmp);
|
||||
return NULL;
|
||||
}
|
||||
key = (struct crypto_ec_key *) tmp;
|
||||
#endif /* OpenSSL version >= 3.0 */
|
||||
|
||||
der_len = i2d_PUBKEY((EVP_PKEY *) key, &der);
|
||||
EC_KEY_free(eckey);
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
EVP_PKEY_free(tmp);
|
||||
#endif /* OpenSSL version >= 3.0 */
|
||||
if (der_len <= 0) {
|
||||
wpa_printf(MSG_INFO, "OpenSSL: i2d_PUBKEY() failed: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
|
@ -2623,7 +2653,7 @@ struct wpabuf * crypto_ec_key_get_ecprivate_key(struct crypto_ec_key *key,
|
|||
struct wpabuf *buf;
|
||||
unsigned int key_flags;
|
||||
|
||||
eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key);
|
||||
eckey = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) key);
|
||||
if (!eckey)
|
||||
return NULL;
|
||||
|
||||
|
@ -2637,6 +2667,7 @@ struct wpabuf * crypto_ec_key_get_ecprivate_key(struct crypto_ec_key *key,
|
|||
EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED);
|
||||
|
||||
der_len = i2d_ECPrivateKey(eckey, &der);
|
||||
EC_KEY_free(eckey);
|
||||
if (der_len <= 0)
|
||||
return NULL;
|
||||
buf = wpabuf_alloc_copy(der, der_len);
|
||||
|
@ -2697,7 +2728,7 @@ struct wpabuf * crypto_ec_key_get_pubkey_point(struct crypto_ec_key *key,
|
|||
const struct crypto_ec_point *
|
||||
crypto_ec_key_get_public_key(struct crypto_ec_key *key)
|
||||
{
|
||||
EC_KEY *eckey;
|
||||
const EC_KEY *eckey;
|
||||
|
||||
eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key);
|
||||
if (!eckey)
|
||||
|
@ -2709,7 +2740,7 @@ crypto_ec_key_get_public_key(struct crypto_ec_key *key)
|
|||
const struct crypto_bignum *
|
||||
crypto_ec_key_get_private_key(struct crypto_ec_key *key)
|
||||
{
|
||||
EC_KEY *eckey;
|
||||
const EC_KEY *eckey;
|
||||
|
||||
eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key);
|
||||
if (!eckey)
|
||||
|
|
|
@ -1630,30 +1630,6 @@ int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p)
|
|||
}
|
||||
|
||||
|
||||
int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
|
||||
struct crypto_ec_point *p,
|
||||
const struct crypto_bignum *x, int y_bit)
|
||||
{
|
||||
byte buf[1 + 2 * MAX_ECC_BYTES];
|
||||
int ret;
|
||||
int prime_len = crypto_ec_prime_len(e);
|
||||
|
||||
if (TEST_FAIL())
|
||||
return -1;
|
||||
|
||||
buf[0] = y_bit ? ECC_POINT_COMP_ODD : ECC_POINT_COMP_EVEN;
|
||||
ret = crypto_bignum_to_bin(x, buf + 1, prime_len, prime_len);
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
ret = wc_ecc_import_point_der(buf, 1 + 2 * ret, e->key.idx,
|
||||
(ecc_point *) p);
|
||||
if (ret != 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct crypto_bignum *
|
||||
crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
|
||||
const struct crypto_bignum *x)
|
||||
|
|
|
@ -957,6 +957,10 @@ void * tls_init(const struct tls_config *conf)
|
|||
const char *ciphers;
|
||||
|
||||
if (tls_openssl_ref_count == 0) {
|
||||
void openssl_load_legacy_provider(void);
|
||||
|
||||
openssl_load_legacy_provider();
|
||||
|
||||
tls_global = context = tls_context_new(conf);
|
||||
if (context == NULL)
|
||||
return NULL;
|
||||
|
@ -3019,13 +3023,23 @@ static int tls_set_conn_flags(struct tls_connection *conn, unsigned int flags,
|
|||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
|
||||
!defined(LIBRESSL_VERSION_NUMBER) && \
|
||||
!defined(OPENSSL_IS_BORINGSSL)
|
||||
if ((flags & (TLS_CONN_ENABLE_TLSv1_0 | TLS_CONN_ENABLE_TLSv1_1)) &&
|
||||
SSL_get_security_level(ssl) >= 2) {
|
||||
/*
|
||||
* Need to drop to security level 1 to allow TLS versions older
|
||||
* than 1.2 to be used when explicitly enabled in configuration.
|
||||
*/
|
||||
SSL_set_security_level(conn->ssl, 1);
|
||||
{
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
int need_level = 0;
|
||||
#else
|
||||
int need_level = 1;
|
||||
#endif
|
||||
|
||||
if ((flags &
|
||||
(TLS_CONN_ENABLE_TLSv1_0 | TLS_CONN_ENABLE_TLSv1_1)) &&
|
||||
SSL_get_security_level(ssl) > need_level) {
|
||||
/*
|
||||
* Need to drop to security level 1 (or 0 with OpenSSL
|
||||
* 3.0) to allow TLS versions older than 1.2 to be used
|
||||
* when explicitly enabled in configuration.
|
||||
*/
|
||||
SSL_set_security_level(conn->ssl, need_level);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -127,7 +127,8 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
|
|||
u8 qr_or_qnr_bin[MAX_ECC_PRIME_LEN];
|
||||
u8 x_bin[MAX_ECC_PRIME_LEN];
|
||||
u8 prime_bin[MAX_ECC_PRIME_LEN];
|
||||
struct crypto_bignum *tmp2 = NULL;
|
||||
u8 x_y[2 * MAX_ECC_PRIME_LEN];
|
||||
struct crypto_bignum *tmp2 = NULL, *y = NULL;
|
||||
struct crypto_hash *hash;
|
||||
unsigned char pwe_digest[SHA256_MAC_LEN], *prfbuf = NULL, ctr;
|
||||
int ret = 0, res;
|
||||
|
@ -139,6 +140,7 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
|
|||
u8 found_ctr = 0, is_odd = 0;
|
||||
int cmp_prime;
|
||||
unsigned int in_range;
|
||||
unsigned int is_eq;
|
||||
|
||||
if (grp->pwe)
|
||||
return -1;
|
||||
|
@ -151,11 +153,6 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
|
|||
if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin),
|
||||
primebytelen) < 0)
|
||||
return -1;
|
||||
grp->pwe = crypto_ec_point_init(grp->group);
|
||||
if (!grp->pwe) {
|
||||
wpa_printf(MSG_INFO, "EAP-pwd: unable to create bignums");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((prfbuf = os_malloc(primebytelen)) == NULL) {
|
||||
wpa_printf(MSG_INFO, "EAP-pwd: unable to malloc space for prf "
|
||||
|
@ -261,10 +258,37 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
|
|||
*/
|
||||
crypto_bignum_deinit(x_candidate, 1);
|
||||
x_candidate = crypto_bignum_init_set(x_bin, primebytelen);
|
||||
if (!x_candidate ||
|
||||
crypto_ec_point_solve_y_coord(grp->group, grp->pwe, x_candidate,
|
||||
is_odd) != 0) {
|
||||
wpa_printf(MSG_INFO, "EAP-pwd: Could not solve for y");
|
||||
if (!x_candidate)
|
||||
goto fail;
|
||||
|
||||
/* y = sqrt(x^3 + ax + b) mod p
|
||||
* if LSB(y) == LSB(pwd-seed): PWE = (x, y)
|
||||
* else: PWE = (x, p - y)
|
||||
*
|
||||
* Calculate y and the two possible values for PWE and after that,
|
||||
* use constant time selection to copy the correct alternative.
|
||||
*/
|
||||
y = crypto_ec_point_compute_y_sqr(grp->group, x_candidate);
|
||||
if (!y ||
|
||||
dragonfly_sqrt(grp->group, y, y) < 0 ||
|
||||
crypto_bignum_to_bin(y, x_y, MAX_ECC_PRIME_LEN, primebytelen) < 0 ||
|
||||
crypto_bignum_sub(prime, y, y) < 0 ||
|
||||
crypto_bignum_to_bin(y, x_y + MAX_ECC_PRIME_LEN,
|
||||
MAX_ECC_PRIME_LEN, primebytelen) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "SAE: Could not solve y");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Constant time selection of the y coordinate from the two
|
||||
* options */
|
||||
is_eq = const_time_eq(is_odd, x_y[primebytelen - 1] & 0x01);
|
||||
const_time_select_bin(is_eq, x_y, x_y + MAX_ECC_PRIME_LEN,
|
||||
primebytelen, x_y + primebytelen);
|
||||
os_memcpy(x_y, x_bin, primebytelen);
|
||||
wpa_hexdump_key(MSG_DEBUG, "EAP-pwd: PWE", x_y, 2 * primebytelen);
|
||||
grp->pwe = crypto_ec_point_from_bin(grp->group, x_y);
|
||||
if (!grp->pwe) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-pwd: Could not generate PWE");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -289,6 +313,7 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
|
|||
/* cleanliness and order.... */
|
||||
crypto_bignum_deinit(x_candidate, 1);
|
||||
crypto_bignum_deinit(tmp2, 1);
|
||||
crypto_bignum_deinit(y, 1);
|
||||
crypto_bignum_deinit(qr, 1);
|
||||
crypto_bignum_deinit(qnr, 1);
|
||||
bin_clear_free(prfbuf, primebytelen);
|
||||
|
@ -296,6 +321,7 @@ int compute_password_element(EAP_PWD_group *grp, u16 num,
|
|||
os_memset(qnr_bin, 0, sizeof(qnr_bin));
|
||||
os_memset(qr_or_qnr_bin, 0, sizeof(qr_or_qnr_bin));
|
||||
os_memset(pwe_digest, 0, sizeof(pwe_digest));
|
||||
forced_memzero(x_y, sizeof(x_y));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
3
tests/.gitignore
vendored
3
tests/.gitignore
vendored
|
@ -1,3 +0,0 @@
|
|||
test-*
|
||||
!test-*.[ch]
|
||||
!test-*.sh
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue