This is a replacement for station's static select_akm_suite. This was
done because wiphy can make a much more intellegent decision about the
akm suite by checking the wiphy supported features e.g. SAE support.
This allows a connection to hybrid WPA2/WPA3 AP's if SAE is not
supported in the kernel.
Set a default GTK cipher type same as our current PTK type, generate a
random GTK when the first STA connects and set it up in the kernel, then
pass the values that EAPoL is going to need to the handshake_state.
In netdev_set_powered also check that no NL80211_CMD_SET_INTERFACE is in
progress because once it returned we would overwrite
netdev->set_powered_cmd_id (could also add a check there but it seems
more logical to just disallow Powered property changes while Mode is
being changed, since we also disallow Mode changes while Powered is
being changed.)
Since device object no longer creates / destroys station objects, use
station_find inside ap directed roam events to direct these to the
station interface.
Add places to store the GTK data, index and RSC in struct
handshake_state and add a setter function for these fields. We may want
to also convert install_gtk to use these fields similar to install_ptk.
As a consequence of the previous commit, netdev watches are always
called when the device object is valid. As a result, we can drop the
netdev_get_device calls and checks from individual AP/AdHoc/Station/WSC
netdev watches
Instead of creating the Station interface in device.c create it directly
on the netdev watch event the same way that the AP and AdHoc interfaces
are created and freed. This fixes some minor incosistencies, for
example station_free was previously called twice, once from device.c and
once from the netdev watch.
device.c would previously keep the pointer returned by station_create()
but that pointer was not actually useful so remove it. Autotests still
seem to pass.
Call netdev_disconnect() to make netdev forget any of station.c's
callbacks for connections or transitions in progress or established.
Otherwise station.c will crash as soon as we're connected and try to
change interface mode:
==17601== Invalid read of size 8
==17601== at 0x11DFA0: station_disconnect_event (station.c:775)
==17601== by 0x11DFA0: station_netdev_event (station.c:1570)
==17601== by 0x115D18: netdev_disconnect_event (netdev.c:868)
==17601== by 0x115D18: netdev_mlme_notify (netdev.c:3403)
==17601== by 0x14E287: l_queue_foreach (queue.c:441)
==17601== by 0x1558B4: process_multicast (genl.c:469)
==17601== by 0x1558B4: received_data (genl.c:532)
==17601== by 0x152888: io_callback (io.c:123)
==17601== by 0x151BCD: l_main_iterate (main.c:376)
==17601== by 0x151C9B: l_main_run (main.c:423)
==17601== by 0x10FE20: main (main.c:489)
Since the interfaces are not supposed to exist when the device is DOWN
(we destroy the interfaces on NETDEV_WATCH_EVENT_DOWN too), don't
create the interfaces if the device hasn't been brought up yet.
When we detect a new device we either bring it down and then up or only
up. The IFF_UP flag in netdev->ifi_flags is updated before that, then
we send the two rtnl commands and then fire the NETDEV_WATCH_EVENT_NEW
event if either the bring up succeeded or -ERFKILL was returned, so the
device may either be UP or DOWN at that point.
It seems that a RTNL NEWLINK notification is usually received before
the RTNL command callback but I don't think this is guaranteed so update
the IFF_UP flag in the callbacks so that the NETDEV_WATCH_EVENT_NEW
handlers can reliably use netdev_get_is_up()
The NL80211_ATTR_KEY_DEFAULT_TYPES attribute is only parsed by the
kernel if either NL80211_ATTR_KEY_DEFAULT or
NL80211_ATTR_KEY_DEFAULT_MGMT are also present, however these are only
used with NL80211_CMD_SET_KEY and ignored for NEW_KEY. As far as I
understand the default key concept only makes sense for a Tx key because
on Rx all keys can be tried, so we don't need this for client mode. The
kernel decides whether the NEW_KEY is for unicast or multicast based on
whether NL80211_ATTR_KEY_MAC was supplied.
device password was read from settings using l_settings_get_string which
returns a newly-allocated string due to un-escape semantics. However,
when assigning wsc->device_password, we strdup-ed the password again
unnecessarily.
==1069== 14 bytes in 2 blocks are definitely lost in loss record 1 of 1
==1069== at 0x4C2AF0F: malloc (vg_replace_malloc.c:299)
==1069== by 0x16696A: l_malloc (util.c:62)
==1069== by 0x16B14B: unescape_value (settings.c:108)
==1069== by 0x16D12C: l_settings_get_string (settings.c:971)
==1069== by 0x149680: eap_wsc_load_settings (eap-wsc.c:1270)
==1069== by 0x146113: eap_load_settings (eap.c:556)
==1069== by 0x12E079: eapol_start (eapol.c:2022)
==1069== by 0x1143A5: netdev_connect_event (netdev.c:1728)
==1069== by 0x118751: netdev_mlme_notify (netdev.c:3406)
==1069== by 0x1734F1: notify_handler (genl.c:454)
==1069== by 0x168987: l_queue_foreach (queue.c:441)
==1069== by 0x173561: process_multicast (genl.c:469)
wsc_pin_is_valid allows two types of PINs through:
1. 4 digit numeric PIN
2. 8 digit numeric PIN
The current code always calls wsc_pin_is_checksum_valid to determine
whether a DEFAULT or USER_SPECIFIED PIN is used. However, this function
is not safe to call on 4 digit PINs and causes a buffer overflow.
Add simple checks to treat 4 digit PINs as DEFAULT PINs and do not call
wsc_pin_is_checksum_valid on these.
Reported-By: Matthias Gerstner <matthias.gerstner@suse.de>
EAP-WSC handles 4 digit, 8 digit and out-of-band Device passwords. The
latter in particular can be anything, so drop the mandatory minimum
password length check here.
This also has the effect of enabling 4-digit PINs to actually work as
they are intended.
The struct allows to support multiple types of the tunneled methods.
Previously, EAP-TTLS was supporting only the eap based ones.
This patch is also starts to move some of the phase 2 EAP
functionality into the new structure.
Boiled down, FT over SAE is no different than FT over PSK, apart from
the different AKM suite. The bulk of this change fixes the current
netdev/station logic related to SAE by rebuilding the RSNE and adding
the MDE if present in the handshake to match what the PSK logic does.
A common function was introduced into station which will rebuild the
handshake rsne's for a target network. This is used for both new
network connections as well as fast transitions.
To prepare for FT over SAE, several case/if statements needed to include
IE_RSN_AKM_SUITE_FT_OVER_SAE. Also a new macro was introduced to remove
duplicate if statement code checking for both FT_OVER_SAE and SAE AKM's.
All the watchlist notify macros were broken in that they did not check
that the watchlist item was still valid before calling it. This only
came into play when a watchlist was being notified and one of the notify
functions removed an item from the same watchlist. It appears this was
already thought of since watchlist_remove checks 'in_notify' and will
mark the item's id as stale (0), but that id never got checked in the
notify macros.
This fixes testAdHoc valgrind warning:
==3347== Invalid read of size 4
==3347== at 0x416612: eapol_rx_auth_packet (eapol.c:1871)
==3347== by 0x416DD4: __eapol_rx_packet (eapol.c:2334)
==3347== by 0x40725B: netdev_pae_read (netdev.c:3515)
==3347== by 0x440958: io_callback (io.c:123)
==3347== by 0x43FDED: l_main_iterate (main.c:376)
==3347== by 0x43FEAB: l_main_run (main.c:423)
==3347== by 0x40377A: main (main.c:489)
...
In the case of the open networks with hidden SSIDs
the settings object is already created.
Valgrind:
==4084== at 0x4C2EB6B: malloc (vg_replace_malloc.c:299)
==4084== by 0x43B44D: l_malloc (util.c:62)
==4084== by 0x43E3FA: l_settings_new (settings.c:83)
==4084== by 0x41D101: network_connect_new_hidden_network (network.c:1053)
==4084== by 0x4105B7: station_hidden_network_scan_results (station.c:1733)
==4084== by 0x419817: scan_finished (scan.c:1165)
==4084== by 0x419CAA: get_scan_done (scan.c:1191)
==4084== by 0x443562: destroy_request (genl.c:139)
==4084== by 0x4437F7: process_unicast (genl.c:424)
==4084== by 0x4437F7: received_data (genl.c:534)
==4084== by 0x440958: io_callback (io.c:123)
==4084== by 0x43FDED: l_main_iterate (main.c:376)
==4084== by 0x43FEAB: l_main_run (main.c:423)