blob: cd489536ec0ebe7defcfcb9ef56ce4a978cc2d1f [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.wifi;
import android.annotation.NonNull;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import com.android.server.wifi.util.ScanResultUtil;
import java.util.Objects;
/**
* Class to store the info needed to match a scan result to the provided network configuration.
*/
public class ScanResultMatchInfo {
/**
* SSID of the network.
*/
public String networkSsid;
/**
* Security Type of the network.
*/
public @WifiConfiguration.SecurityType int networkType;
/**
* Special flag for PSK-SAE in transition mode
*/
public boolean pskSaeInTransitionMode;
/**
* Special flag for OWE in transition mode
*/
public boolean oweInTransitionMode;
/**
* True if created from a scan result
*/
private boolean mFromScanResult = false;
/**
* Fetch network type from network configuration.
*/
private static @WifiConfiguration.SecurityType int getNetworkType(WifiConfiguration config) {
if (WifiConfigurationUtil.isConfigForSaeNetwork(config)) {
return WifiConfiguration.SECURITY_TYPE_SAE;
} else if (WifiConfigurationUtil.isConfigForPskNetwork(config)) {
return WifiConfiguration.SECURITY_TYPE_PSK;
} else if (WifiConfigurationUtil.isConfigForWapiPskNetwork(config)) {
return WifiConfiguration.SECURITY_TYPE_WAPI_PSK;
} else if (WifiConfigurationUtil.isConfigForWapiCertNetwork(config)) {
return WifiConfiguration.SECURITY_TYPE_WAPI_CERT;
} else if (WifiConfigurationUtil.isConfigForEapNetwork(config)) {
return WifiConfiguration.SECURITY_TYPE_EAP;
} else if (WifiConfigurationUtil.isConfigForEapSuiteBNetwork(config)) {
return WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B;
} else if (WifiConfigurationUtil.isConfigForWepNetwork(config)) {
return WifiConfiguration.SECURITY_TYPE_WEP;
} else if (WifiConfigurationUtil.isConfigForOweNetwork(config)) {
return WifiConfiguration.SECURITY_TYPE_OWE;
} else if (WifiConfigurationUtil.isConfigForOpenNetwork(config)) {
return WifiConfiguration.SECURITY_TYPE_OPEN;
}
throw new IllegalArgumentException("Invalid WifiConfiguration: " + config);
}
/**
* Get the ScanResultMatchInfo for the given WifiConfiguration
*/
public static ScanResultMatchInfo fromWifiConfiguration(WifiConfiguration config) {
ScanResultMatchInfo info = new ScanResultMatchInfo();
info.networkSsid = config.SSID;
info.networkType = getNetworkType(config);
return info;
}
/**
* Fetch network type from scan result.
*/
private static @WifiConfiguration.SecurityType int getNetworkType(ScanResult scanResult) {
if (ScanResultUtil.isScanResultForSaeNetwork(scanResult)) {
return WifiConfiguration.SECURITY_TYPE_SAE;
} else if (ScanResultUtil.isScanResultForWapiPskNetwork(scanResult)) {
return WifiConfiguration.SECURITY_TYPE_WAPI_PSK;
} else if (ScanResultUtil.isScanResultForWapiCertNetwork(scanResult)) {
return WifiConfiguration.SECURITY_TYPE_WAPI_CERT;
} else if (ScanResultUtil.isScanResultForPskNetwork(scanResult)) {
return WifiConfiguration.SECURITY_TYPE_PSK;
} else if (ScanResultUtil.isScanResultForEapSuiteBNetwork(scanResult)) {
return WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B;
} else if (ScanResultUtil.isScanResultForEapNetwork(scanResult)) {
return WifiConfiguration.SECURITY_TYPE_EAP;
} else if (ScanResultUtil.isScanResultForWepNetwork(scanResult)) {
return WifiConfiguration.SECURITY_TYPE_WEP;
} else if (ScanResultUtil.isScanResultForOweNetwork(scanResult)) {
return WifiConfiguration.SECURITY_TYPE_OWE;
} else if (ScanResultUtil.isScanResultForOpenNetwork(scanResult)) {
return WifiConfiguration.SECURITY_TYPE_OPEN;
} else {
throw new IllegalArgumentException("Invalid ScanResult: " + scanResult);
}
}
/**
* Get the ScanResultMatchInfo for the given ScanResult
*/
public static ScanResultMatchInfo fromScanResult(ScanResult scanResult) {
ScanResultMatchInfo info = new ScanResultMatchInfo();
// Scan result ssid's are not quoted, hence add quotes.
// TODO: This matching algo works only if the scan result contains a string SSID.
// However, according to our public documentation ths {@link WifiConfiguration#SSID} can
// either have a hex string or quoted ASCII string SSID.
info.networkSsid = ScanResultUtil.createQuotedSSID(scanResult.SSID);
info.networkType = getNetworkType(scanResult);
info.oweInTransitionMode = false;
info.pskSaeInTransitionMode = false;
info.mFromScanResult = true;
if (info.networkType == WifiConfiguration.SECURITY_TYPE_SAE) {
// Note that scan result util will always choose the highest security protocol.
info.pskSaeInTransitionMode =
ScanResultUtil.isScanResultForPskSaeTransitionNetwork(scanResult);
} else if (info.networkType == WifiConfiguration.SECURITY_TYPE_OWE) {
// Note that scan result util will always choose OWE.
info.oweInTransitionMode =
ScanResultUtil.isScanResultForOweTransitionNetwork(scanResult);
}
return info;
}
/**
* Checks for equality of network type.
*/
public boolean networkTypeEquals(@NonNull ScanResultMatchInfo other,
boolean saeAutoUpgradeEnabled) {
boolean networkTypeEquals;
// Detect <SSID, PSK+SAE> scan result and say it is equal to <SSID, PSK> configuration
if (other.pskSaeInTransitionMode && networkType == WifiConfiguration.SECURITY_TYPE_PSK
|| (pskSaeInTransitionMode
&& other.networkType == WifiConfiguration.SECURITY_TYPE_PSK)) {
networkTypeEquals = true;
} else if ((networkType == WifiConfiguration.SECURITY_TYPE_OPEN
&& other.oweInTransitionMode) || (oweInTransitionMode
&& other.networkType == WifiConfiguration.SECURITY_TYPE_OPEN)) {
// Special case we treat Enhanced Open and Open as equals. This is done to support the
// case where a saved network is Open but we found an OWE in transition network.
networkTypeEquals = true;
} else if ((saeAutoUpgradeEnabled)
&& ((mFromScanResult && networkType == WifiConfiguration.SECURITY_TYPE_SAE
&& other.networkType == WifiConfiguration.SECURITY_TYPE_PSK)
|| (other.mFromScanResult
&& other.networkType == WifiConfiguration.SECURITY_TYPE_SAE
&& networkType == WifiConfiguration.SECURITY_TYPE_PSK))) {
// Allow upgrading WPA2 PSK connections to WPA3 SAE AP
networkTypeEquals = true;
} else {
networkTypeEquals = networkType == other.networkType;
}
return networkTypeEquals;
}
@Override
public boolean equals(Object otherObj) {
return matchForNetworkSelection(otherObj, false);
}
/**
* Match two ScanResultMatchInfo objects while considering configuration in overlays
*
* @param otherObj Other object to compare against
* @param saeAutoUpgradeEnabled A boolean that indicates if WPA3 auto upgrade feature is enabled
* @return true if objects are equal for network selection purposes, false otherwise
*/
public boolean matchForNetworkSelection(Object otherObj, boolean saeAutoUpgradeEnabled) {
if (this == otherObj) {
return true;
} else if (!(otherObj instanceof ScanResultMatchInfo)) {
return false;
}
ScanResultMatchInfo other = (ScanResultMatchInfo) otherObj;
if (!Objects.equals(networkSsid, other.networkSsid)) {
return false;
}
return networkTypeEquals(other, saeAutoUpgradeEnabled);
}
@Override
public int hashCode() {
return Objects.hash(networkSsid);
}
@Override
public String toString() {
return "ScanResultMatchInfo: SSID: " + networkSsid + ", type: " + networkType
+ ", WPA3 in transition mode: " + pskSaeInTransitionMode
+ ", OWE in transition mode: " + oweInTransitionMode + ", from scan result: "
+ mFromScanResult;
}
}