hostapd: fix hostapd RSN preauthentication PMKSA caching
authorFelix Fietkau <nbd@openwrt.org>
Tue, 8 Oct 2013 11:09:40 +0000 (11:09 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Tue, 8 Oct 2013 11:09:40 +0000 (11:09 +0000)
In 2009 OpenWrt's hostapd config added an "auth_cache" boolean
to be used to address a reported issue #12129 [0] on a forum [1].
The reported issue on the ticket is different that the one
described on the forum. The commit was r33359. This change broke
proper RSN preauthentication [2] [3] [4] expectations on hostapd's
configuration for WPA2 and this in turn disabled PMKSA caching and
Opportunistic Key Caching. This change:

  * Leaves the "auth_cache" to be used only for WPA networks for those
    looking to use this as a workaround to a reported issue but annotates
    a warning over its usage.

  * Separate "auth_cache" from WPA2 RSN preauthentication, leaving
    WPA2 RSN preauthentication to enabled only with "rsn_preauth" with
    the expected and recommended settings.

  * Adds a new WPA2 RSN preauthentication "rsn_preauth_testing" to
    be used when evaluating funcionality for WPA2 RSN preauthentication
    with the expected and recommended settings with the only difference
    so far with what should be enabled by default to disable Opportunistic
    Key Caching.

Disabling the PMKSA cache should mean the STA could not roam off and back
onto the AP that had PMKSA caching disabled and would require a full
authentication cycle. This fixes this for WPA2 networks with
RSN preauthentication enabled.

This change should be applied to AA as well as trunk.

  TL DR;

The issue described on the forum has to do with failure of a STA
being able to try to authenticate again with the AP if it failed
its first try. This may have been an issue with hostapd in 2009
but as per some tests I cannot reproduce this today on a WPA2
network.

The issue described on the ticket alludes to a security issue with the
design of using a Radius server to authenticate to an AP. The issue
vaguely alludes to the circumstances of zapping a user, deleting their
authentication credentials to log in to the network, and that if
RSN preauthentication is enabled with PMKSA caching that the user
that was zapped would still be able to authenticate.

Lets treat these as separate issues.

I cannot reproduce the first issue reported on the forums of not
being able to authenticate anymore on a WPA2 network.

The issue reported on the ticket modified WPA2 RSN preauthentication
by adding two fields to the hostapd configuration if auth_cache
was enabled:

  * disable_pmksa_caching=1
  * okc=0

The first one disables PMKSA authentication cache.
The second one disables Opportunistic Key Caching.

The issue reported on the ticket was fixed by implementing a workaround
in hostapd's configuration. Disabling PMKSA caching breaks proper use
of WPA2 RSN pre authentication. The usage of disable_pmksa_caching=1
prevents hostapd from adding PMKSA entries into its cache when a successful
802.1x authentication occurs. In practice RSN preauthentication would
trigger a STA to perform authentication with other APs on the same SSID,
it would then have its own supplicant PMKSA cache held. If a STA roams
between one AP to another no new authenitcation would need to be performed
as the new AP would already have authenticated the STA. The purpose of the
PMKSA cache on the AP side would be for the AP to use the same PMKID for
a STA when the STA roams off onto another BSSID and later comes back to it.

Disabling Opportunistic Key Caching could help the reported issue
as well but its not the correct place to address this. Opportunistic
Key Caching enables an AP with different interfaces to share the
PMKSA cache. Its a technical enhancement and disabling it would
be useful to let a testing suite properly test for RSN preauthentication
given that otherwise Opportunistic Key Caching would enable an
interface being tested to derive its own derive the PMKSA entry.
In production though okc=1 should be enabled to help with RSN
preauthentication.

The real fix for this particular issue outside of the scope of hostapd's
configuration and it should not be dealt with as a workaround to
its configuration and breaking expected RSN preauthentication and
technical optimizations. Revert this change and enable users to pick
and choose to enable or disable disable_pmksa_caching and okc expecting them
to instead have read clearly more what these do.

As for the core issure ported, the correct place to fix this is to
enable a sort of messaging between the RADIUS server and its peers
so that if caching for authentication is enabled that cache can be
cleared upon user credential updates. Updating a user password
(not just zapping a user) is another possible issue that would need
to be resolved here. Another part of the solution might be to reduce
the cache timing to account for any systematic limitations (RADIUS
server not able to ask peers to clear cache might be
one).

[0] https://dev.openwrt.org/changeset/33359
[1] https://forum.openwrt.org/viewtopic.php?id=19596
[2] http://wireless.kernel.org/en/users/Documentation/hostapd#IEEE_802.11i.2FRSN.2FWPA2_pre-authentication
[3] http://wireless.kernel.org/en/users/Documentation/wpa_supplicant#RSN_preauthentication
[4] http://wiki.openwrt.org/doc/recipes/rsn_preauthentication

Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
SVN-Revision: 38336

package/network/services/hostapd/files/hostapd.sh

index aace21ce6711da3407cefe67a7fc306e3aacbe0b..ce0f2271ded6c228b5d5cb86ad17d1684df8f5ec 100644 (file)
@@ -106,9 +106,13 @@ hostapd_set_bss_options() {
                        config_get auth_secret "$vif" auth_secret
                        [ -z "$auth_secret" ] && config_get auth_secret "$vif" key
                        append "$var" "auth_server_shared_secret=$auth_secret" "$N"
                        config_get auth_secret "$vif" auth_secret
                        [ -z "$auth_secret" ] && config_get auth_secret "$vif" key
                        append "$var" "auth_server_shared_secret=$auth_secret" "$N"
+                       # You don't really want to enable this unless you are doing
+                       # some corner case testing or are using OpenWrt as a work around
+                       # for some systematic issues.
                        config_get_bool auth_cache "$vif" auth_cache 0
                        config_get_bool auth_cache "$vif" auth_cache 0
-                       [ "$auth_cache" -gt 0 ] || append "$var" "disable_pmksa_caching=1" "$N"
-                       [ "$auth_cache" -gt 0 ] || append "$var" "okc=0" "$N"
+                       config_get rsn_preauth "$vif" rsn_preauth
+                       [ "$auth_cache" -gt 0 ] || [[ "$rsn_preauth" = 1 ]] || append "$var" "disable_pmksa_caching=1" "$N"
+                       [ "$auth_cache" -gt 0 ] || [[ "$rsn_preauth" = 1 ]] || append "$var" "okc=0" "$N"
                        config_get acct_server "$vif" acct_server
                        [ -n "$acct_server" ] && append "$var" "acct_server_addr=$acct_server" "$N"
                        config_get acct_port "$vif" acct_port
                        config_get acct_server "$vif" acct_server
                        [ -n "$acct_server" ] && append "$var" "acct_server_addr=$acct_server" "$N"
                        config_get acct_port "$vif" acct_port
@@ -209,12 +213,25 @@ hostapd_set_bss_options() {
 
        if [ "$wpa" -ge "2" ]
        then
 
        if [ "$wpa" -ge "2" ]
        then
-               # RSN -> allow preauthentication
-               config_get_bool rsn_preauth "$vif" rsn_preauth "$auth_cache"
+               # RSN -> allow preauthentication. You have two
+               # options, rsn_preauth for production or rsn_preauth_testing
+               # for validation / testing.
                if [ -n "$bridge" -a "$rsn_preauth" = 1 ]
                then
                        append "$var" "rsn_preauth=1" "$N"
                        append "$var" "rsn_preauth_interfaces=$bridge" "$N"
                if [ -n "$bridge" -a "$rsn_preauth" = 1 ]
                then
                        append "$var" "rsn_preauth=1" "$N"
                        append "$var" "rsn_preauth_interfaces=$bridge" "$N"
+                       append "$var" "okc=1" "$N"
+               else
+                       # RSN preauthentication testings hould disable
+                       # Opportunistic Key Caching (okc) as otherwise the PMKSA
+                       # entry for a test could come from the Opportunistic Key Caching
+                       config_get rsn_preauth_testing "$vif" rsn_preauth_testing
+                       if [ -n "$bridge" -a "$rsn_preauth_testing" = 1 ]
+                       then
+                               append "$var" "rsn_preauth=1" "$N"
+                               append "$var" "rsn_preauth_interfaces=$bridge" "$N"
+                               append "$var" "okc=0" "$N"
+                       fi
                fi
 
                # RSN -> allow management frame protection
                fi
 
                # RSN -> allow management frame protection