Wpa_supplicant is a widely used implementation of an IEEE 802.11i supplicant for Linux and other platforms. It implements WPA and WPA2 security protocols as well as RSN, PMKSA caching, pre-authentication, 802.11r, 802.11w, and Wi-Fi Protected Setup (WPS). Wpa_supplicant initializes interfaces by reading configuration files, setting up drivers via cfg80211 and libnl, and starting an event loop to monitor network events. It can access layer 2 packets using l2_packet to support functions like TDLS.
What is Wpa_supplicant
●From Wiki page: wpa_supplicant
● wpa_supplicant is widely used in Linux distributions and Android!
● These slides are based on 2.6-devel
wpa_supplicant is a free software implementation of an IEEE 802.11i supplicant for Linux,
FreeBSD, NetBSD, QNX, AROS, Microsoft Windows, Solaris, OS/2 (including eComStation) and
Haiku. In addition to being a fully featured WPA2 supplicant, it also implements WPA and older
wireless LAN security protocols. Features include:
● WPA and full IEEE 802.11i/RSN/WPA2
● WPA-PSK and WPA2-PSK ("WPA-Personal", pre-shared key)
● WPA with EAP ("WPA-Enterprise", for example with RADIUS authentication server)
● key management for CCMP, TKIP, WEP (both 104/128- and 40/64-bit)
● RSN: PMKSA caching, pre-authentication
● IEEE 802.11r
● IEEE 802.11w
● Wi-Fi Protected Setup (WPS)
4.
Usage
● wpa_supplicant
○ -D:driver type, cfg80211 or wext
○ -B: run as a daemon
○ -b: the bridge interface
○ -c: configure file path
○ -C: control interface
○ -d: decrease debug level (show more log)
○ -e: entropy file
○ -f: debug log file
○ -g: global control interface (ctrl_interface)
○ -G: the ctrl_interface will set to be owned by the specified group
○ -h: show usage
○ -i: interface
○ -I: another configuration file
○ -K: show key in debug log
5.
Usage
● wpa_supplicant
○ -L:show license
○ -m: p2p device configuration file
○ -o: override driver option
○ -O: override control interface option
○ -p: driver parameter
○ -P: PID file
○ -q: increase debug level (show less log)
○ -s: use syslog
○ -T: use Linux Tracing
○ -t: add timestamp in debug log
○ -u: dbus control interface
○ -v: show wpa_supplicant version
○ -W: defer the main event loop until first external program attaches wpa_supplicant
○ -N: combine multiple interface parameters
Init Step 1:wpa_supplicant_init()
1. Init debug log setting
a. If specified to dump log to file via -f parameter, then initialize the output file via
wpa_debug_open_file(). Otherwise, initialize the standard output for debug log via
wpa_debug_setup_stdout()
b. If specified to dump log to syslog via -s parameter, then initialize syslog setting via
wpa_debug_open_syslog()
c. If specified to dump log by Linux Tracing via -T parameter, then initialize the setting via
wpa_debug_open_linux_tracing()
2. Initialize EAP methods via eap_register_methods()
3. Initialize global ctrl_interface via wpa_supplicant_global_ctrl_iface_init()
a. Open socket for the ctrl_interface
b. Set the group permission if the group is specified by -G parameters
c. Register ctrl_interface reader socket via eloop_register_read_sock()
9.
Init Step 1:wpa_supplicant_init()
4. Initialize dbus via wpas_notify_supplicant_initialized()
5. Check global driver list wpa_drivers
6. Register a period timeout (10s) function wpas_periodic to:
a. P2P: check whether P2P peers expired via p2p_expire_peers()
b. STA: flush expired bss via wpa_bss_flush_by_age()
c. AP: check whether the acl is expired via ap_periodic()
10.
Init Step 2:wpa_supplicant_add_iface()
1. Allocate wpa_supplicant structure fo each interface
2. If the override driver option is set by -o parameter, override the driver
specified by -D parameter
3. If the override ctrl_interface option is set by -O parameter, override the
ctrl_interface specified by -C parameter
4. wpa_supplicant_init_iface()
a. Read configuration file via wpa_config_read if the file is specified by -c parameter; if not
specified, make default configrations
b. Read another configuration file vi wpa_config_read if the file is specified by -I parameter
c. If ctrl_interface and driver_param are specified by configuration file and comman line
parameter, use the one specified by command line
11.
Init Step 2:wpa_supplicant_add_iface()
5. wpas_init_driver()
a. Set the driver (e.g. cfg80211 driver)
b. Initialize driver via wpa_drv_init()
c. Setup driver parameter via wpa_drv_set_param() if specified by -p parameter
d. Add the interface into the wpa_s->radio_list via radio_add_interface()
6. Initialize wpa context via wpa_supplicant_init_wpa()
7. Initialize hw feature to wpa_s->hw.modes via
wpa_drv_get_hw_feature_data()
8. Get and setup driver capability via wpa_drv_get_capa()
9. etup bridge or trigger scan via wpa_supplicant_driver_init()
10. If the interface is not P2P device, initialize TDLS via wpa_tdls_init()
11. Set country via wpa_drv_set_country()
12.
Init Step 2:wpa_supplicant_add_iface()
12. Initialize WPS via wpas_wps_init()
13. Initialize EAPOL via wpa_supplicant_init_eapol()
14. Initialize the ctrl_iface of the interface via wpa_supplicant_ctrl_iface_init()
15. Initialize GAS query via gas_query_init()
16. Initialize P2P via wpas_p2p_init(), if the interface support P2P devic
operations
17. Set WOW settings via wpas_set_wowlan_triggers()
18. If support P2P device, try to add P2P device interface via
wpas_p2p_add_p2pdev_interface()
13.
Init Step 3:wpa_supplicant_run()
1. If -B parameter is assigned, run wpa_supplicant as daemon via
wpa_supplicant_daemon
2. If -W parameter is assigned, start the event loop after external program
starting to attach wpa_supplicant via wpa_supplicant_ctrl_iface_wait()
3. Register terminal signal SIGINT and SIGTERM handler via
eloop_register_signal_terminate
4. Register SIGHUP as reconfig signal via eloop_register_signal_reconfig()
5. Start event loop via eloop_run()
What is cfg80211and libnl
● cfg80211 is a configuration system in Linux kernel for manipulating
802.11 devices
● libnl is the bridge for user space and kernel space to interact with each
other during manipulating 802.11 devices
● nl80211 in kernel registers the generic netlink(nl) family “nl80211”
● wpa_supplicant in userspace calls libnl APIs to communicate with kernel
generic nl family “nl80211”
16.
Wpa_supplicant to kernelcf80211 via linbl
1. Initialize netlink connection via netlink_init()
2. Initialize the connection to kernel nl80211 via
wpa_driver_nl80211_init_nl_global()
a. Allocate nl handler via global->nl = nl_create_handle(global->nl_cb, "nl");
b. Resolve nl80211 via global->nl80211_id = genl_ctrl_resolve(global->nl, "nl80211");
c. Allocate event handler via global->nl_event = nl_create_handle(global->nl_cb, "event");
d. Add global->nl_event to “mlme”, “scan”, “regulatory”, “vendor” groups via:
i. ret = nl_get_multicast_id(global, "nl80211", "mlme");
ii. ret = nl_socket_add_membership(global->nl_event, ret);
e. Assign the global event handler via:
i. nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_global_event,
global);
f. Assign “mlme”, “scan”, “regulatory”, “vendor” event handler via:
i. nl80211_register_eloop_read(&global->nl_event, wpa_driver_nl80211_event_receive,
Why Need toAccess Layer 2 Packets
● To maintain the state machine of specified functions (e.g. TDLS),
wpa_supplicant needs to access layer 2(l2) packets
○ e.g. TDLS, many action frames are encapulated in layer 2 packets
19.
Take TDLS asExample
1. wpa_supplicant calls l2_packet_init() to initialize the connection to l2 and
monitor the specified l2 packets
a. Assign the rx_callback (wpa_supplicant_rx_tdls())function for specified protocol
b. Assign the rx handle function l2_packet_receive() which will invoke the rx_callback
int wpa_tdls_init(struct wpa_sm *sm)
{
if (sm == NULL)
return -1;
sm->l2_tdls = l2_packet_init(sm->bridge_ifname ? sm->bridge_ifname :
sm->ifname,
sm->own_addr,
ETH_P_80211_ENCAP, wpa_supplicant_rx_tdls,
sm, 0);
if (sm->l2_tdls == NULL) {
wpa_printf(MSG_ERROR, "TDLS: Failed to open l2_packet "
"connection");
return -1;
}
...
eloop_run()
● eloop keepsrunning is eloop.terminate is not set or any count of eloop.
reader, eloop.writer, eloop.exception is not zero
● During the while loop
○ Get first timout event in eloop.timeout list and calculate the remianing time to reach the
timeout
○ Call select() to wait for coming reader, writer, exception events
○ Call eloop_process_pending_signals() to process pending signal by calling their handlers
○ Get first timout event in eloop.timeout list, if the timeout fired, call the handler to process
the timeout event
○ If reader, writer, exception socekts are changed, skip previous select() results
○ Call eloop_sock_table_dispatch() to handle all the set reader, writer, exceptions events
23.
Reader, Writer, ExceptionsEvent Sources
● Reader event source
○ ctrl_iface connection
○ netlink connection between wpa_supplicant and nl80211
○ EAPOL Tx status in wpa_driver_nl80211_drv_init()
○ EAPOL socket in i802_init()
○ Socket for Monitor mode
○ …
● Writer event source
○ Dbus watch
○ http client
● Exception event source
○ Dbus watch