Files
app_Settings/src/com/android/settings/wifi/WifiUtils.java
Les Lee 3bb2a81042 wifi setting: Add psk length check
Frameworks move psk ascii password length check from API level to
framework internal. Add the check code in Setting side to avoid breaking
the unit test.

Bug: 223513510
Test: atest -c WifiUtilsTest
Change-Id: I7c78eb367fdcbbc11bbb7169ba8f2edc720ad071
2022-03-09 16:28:30 +08:00

244 lines
9.7 KiB
Java

/*
* 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.settings.wifi;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.NetworkCapabilities;
import android.net.wifi.ScanResult;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.WifiConfiguration;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.text.TextUtils;
import com.android.settings.Utils;
import com.android.wifitrackerlib.WifiEntry;
import java.nio.charset.StandardCharsets;
/** A utility class for Wi-Fi functions. */
public class WifiUtils extends com.android.settingslib.wifi.WifiUtils {
private static final int SSID_ASCII_MIN_LENGTH = 1;
private static final int SSID_ASCII_MAX_LENGTH = 32;
private static final int PSK_PASSPHRASE_ASCII_MIN_LENGTH = 8;
private static final int PSK_PASSPHRASE_ASCII_MAX_LENGTH = 63;
public static boolean isSSIDTooLong(String ssid) {
if (TextUtils.isEmpty(ssid)) {
return false;
}
return ssid.getBytes(StandardCharsets.UTF_8).length > SSID_ASCII_MAX_LENGTH;
}
public static boolean isSSIDTooShort(String ssid) {
if (TextUtils.isEmpty(ssid)) {
return true;
}
return ssid.length() < SSID_ASCII_MIN_LENGTH;
}
/**
* Check if the hotspot password is valid.
*/
public static boolean isHotspotPasswordValid(String password, int securityType) {
final SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
try {
if (securityType == SoftApConfiguration.SECURITY_TYPE_WPA2_PSK
|| securityType == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION) {
if (password.length() < PSK_PASSPHRASE_ASCII_MIN_LENGTH
|| password.length() > PSK_PASSPHRASE_ASCII_MAX_LENGTH) {
return false;
}
}
configBuilder.setPassphrase(password, securityType);
} catch (IllegalArgumentException e) {
return false;
}
return true;
}
/**
* This method is a stripped and negated version of WifiConfigStore.canModifyNetwork.
*
* @param context Context of caller
* @param config The WiFi config.
* @return true if Settings cannot modify the config due to lockDown.
*/
public static boolean isNetworkLockedDown(Context context, WifiConfiguration config) {
if (config == null) {
return false;
}
final DevicePolicyManager dpm =
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
final PackageManager pm = context.getPackageManager();
final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
// Check if device has DPM capability. If it has and dpm is still null, then we
// treat this case with suspicion and bail out.
if (pm.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN) && dpm == null) {
return true;
}
boolean isConfigEligibleForLockdown = false;
if (dpm != null) {
final ComponentName deviceOwner = dpm.getDeviceOwnerComponentOnAnyUser();
if (deviceOwner != null) {
final int deviceOwnerUserId = dpm.getDeviceOwnerUserId();
try {
final int deviceOwnerUid = pm.getPackageUidAsUser(deviceOwner.getPackageName(),
deviceOwnerUserId);
isConfigEligibleForLockdown = deviceOwnerUid == config.creatorUid;
} catch (PackageManager.NameNotFoundException e) {
// don't care
}
} else if (dpm.isOrganizationOwnedDeviceWithManagedProfile()) {
int profileOwnerUserId = Utils.getManagedProfileId(um, UserHandle.myUserId());
final ComponentName profileOwner = dpm.getProfileOwnerAsUser(profileOwnerUserId);
if (profileOwner != null) {
try {
final int profileOwnerUid = pm.getPackageUidAsUser(
profileOwner.getPackageName(), profileOwnerUserId);
isConfigEligibleForLockdown = profileOwnerUid == config.creatorUid;
} catch (PackageManager.NameNotFoundException e) {
// don't care
}
}
}
}
if (!isConfigEligibleForLockdown) {
return false;
}
final ContentResolver resolver = context.getContentResolver();
final boolean isLockdownFeatureEnabled = Settings.Global.getInt(resolver,
Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 0) != 0;
return isLockdownFeatureEnabled;
}
/** Returns true if the provided NetworkCapabilities indicate a captive portal network. */
public static boolean canSignIntoNetwork(NetworkCapabilities capabilities) {
return (capabilities != null
&& capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL));
}
/**
* Provides a simple way to generate a new {@link WifiConfiguration} obj from
* {@link ScanResult} or {@link WifiEntry}. Either {@code wifiEntry} or {@code scanResult
* } input should be not null for retrieving information, otherwise will throw
* IllegalArgumentException.
* This method prefers to take {@link WifiEntry} input in priority. Therefore this method
* will take {@link WifiEntry} input as preferred data extraction source when you input
* both {@link WifiEntry} and {@link ScanResult}, and ignore {@link ScanResult} input.
*
* Duplicated and simplified method from {@link WifiConfigController#getConfig()}.
* TODO(b/120827021): Should be removed if the there is have a common one in shared place (e.g.
* SettingsLib).
*
* @param wifiEntry Input data for retrieving WifiConfiguration.
* @param scanResult Input data for retrieving WifiConfiguration.
* @return WifiConfiguration obj based on input.
*/
public static WifiConfiguration getWifiConfig(WifiEntry wifiEntry, ScanResult scanResult) {
if (wifiEntry == null && scanResult == null) {
throw new IllegalArgumentException(
"At least one of WifiEntry and ScanResult input is required.");
}
final WifiConfiguration config = new WifiConfiguration();
final int security;
if (wifiEntry == null) {
config.SSID = "\"" + scanResult.SSID + "\"";
security = getWifiEntrySecurity(scanResult);
} else {
if (wifiEntry.getWifiConfiguration() == null) {
config.SSID = "\"" + wifiEntry.getSsid() + "\"";
} else {
config.networkId = wifiEntry.getWifiConfiguration().networkId;
config.hiddenSSID = wifiEntry.getWifiConfiguration().hiddenSSID;
}
security = wifiEntry.getSecurity();
}
switch (security) {
case WifiEntry.SECURITY_NONE:
config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN);
break;
case WifiEntry.SECURITY_WEP:
config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_WEP);
break;
case WifiEntry.SECURITY_PSK:
config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
break;
case WifiEntry.SECURITY_EAP_SUITE_B:
config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B);
break;
case WifiEntry.SECURITY_EAP:
config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
break;
case WifiEntry.SECURITY_SAE:
config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
break;
case WifiEntry.SECURITY_OWE:
config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE);
break;
default:
break;
}
return config;
}
/**
* Gets security value from ScanResult.
*
* @param result ScanResult
* @return Related security value based on {@link WifiEntry}.
*/
public static int getWifiEntrySecurity(ScanResult result) {
if (result.capabilities.contains("WEP")) {
return WifiEntry.SECURITY_WEP;
} else if (result.capabilities.contains("SAE")) {
return WifiEntry.SECURITY_SAE;
} else if (result.capabilities.contains("PSK")) {
return WifiEntry.SECURITY_PSK;
} else if (result.capabilities.contains("EAP_SUITE_B_192")) {
return WifiEntry.SECURITY_EAP_SUITE_B;
} else if (result.capabilities.contains("EAP")) {
return WifiEntry.SECURITY_EAP;
} else if (result.capabilities.contains("OWE")) {
return WifiEntry.SECURITY_OWE;
}
return WifiEntry.SECURITY_NONE;
}
}