From 236660590004487d65849ed44e4431cb038c42a0 Mon Sep 17 00:00:00 2001 From: Hai Shalom Date: Thu, 7 Mar 2019 15:54:25 -0800 Subject: [PATCH] [Wi-Fi] Do not delete certs when forgetting network Deleting EAP Wi-Fi configuration deletes shared credentials used by other configs. To resolve this issue the following changes were implemented: 1. When manually adding Wi-Fi certs from storage, Wi-Fi will not attempt to delete them when network is removed. 2. When apps use WifiEnterpriseConfig#setClientKeyEntry to add certs, they will be deleted if the network is removed. 3. Allow the user to delete Wi-Fi certs the same way that allows the user to add them. Make the "Remove" option available, and implement key store removal in settings. Bug: 30248175 Test: atest WifiEnterpriseConfigTest Test: Load certs, remove certs from credentials menu Test: Load cert, create 2 EAP networks that use it, forget one network Change-Id: I2015207d51188821da3397e1947e5eb6aefbf6e1 --- .../settings/UserCredentialsSettings.java | 47 +++++++++++++++---- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/src/com/android/settings/UserCredentialsSettings.java b/src/com/android/settings/UserCredentialsSettings.java index c30e51df668..d322819ba98 100644 --- a/src/com/android/settings/UserCredentialsSettings.java +++ b/src/com/android/settings/UserCredentialsSettings.java @@ -154,11 +154,15 @@ public class UserCredentialsSettings extends SettingsPreferenceFragment dialog.dismiss(); } }; - if (item.isSystem()) { - // TODO: a safe means of clearing wifi certificates. Configs refer to aliases - // directly so deleting certs will break dependent access points. - builder.setNegativeButton(R.string.trusted_credentials_remove_label, listener); - } + // TODO: b/127865361 + // a safe means of clearing wifi certificates. Configs refer to aliases + // directly so deleting certs will break dependent access points. + // However, Wi-Fi used to remove this certificate from storage if the network + // was removed, regardless if it is used in more than one network. + // It has been decided to allow removing certificates from this menu, as we + // assume that the user who manually adds certificates must have a way to + // manually remove them. + builder.setNegativeButton(R.string.trusted_credentials_remove_label, listener); } return builder.create(); } @@ -172,7 +176,8 @@ public class UserCredentialsSettings extends SettingsPreferenceFragment * Deletes all certificates and keys under a given alias. * * If the {@link Credential} is for a system alias, all active grants to the alias will be - * removed using {@link KeyChain}. + * removed using {@link KeyChain}. If the {@link Credential} is for Wi-Fi alias, all + * credentials and keys will be removed using {@link KeyStore}. */ private class RemoveCredentialsTask extends AsyncTask { private Context context; @@ -188,14 +193,32 @@ public class UserCredentialsSettings extends SettingsPreferenceFragment for (final Credential credential : credentials) { if (credential.isSystem()) { removeGrantsAndDelete(credential); - continue; + } else { + deleteWifiCredential(credential); } - throw new UnsupportedOperationException( - "Not implemented for wifi certificates. This should not be reachable."); } return credentials; } + private void deleteWifiCredential(final Credential credential) { + final KeyStore keyStore = KeyStore.getInstance(); + final EnumSet storedTypes = credential.getStoredTypes(); + + // Remove all Wi-Fi credentials + if (storedTypes.contains(Credential.Type.USER_KEY)) { + keyStore.delete(Credentials.USER_PRIVATE_KEY + credential.getAlias(), + Process.WIFI_UID); + } + if (storedTypes.contains(Credential.Type.USER_CERTIFICATE)) { + keyStore.delete(Credentials.USER_CERTIFICATE + credential.getAlias(), + Process.WIFI_UID); + } + if (storedTypes.contains(Credential.Type.CA_CERTIFICATE)) { + keyStore.delete(Credentials.CA_CERTIFICATE + credential.getAlias(), + Process.WIFI_UID); + } + } + private void removeGrantsAndDelete(final Credential credential) { final KeyChainConnection conn; try { @@ -488,5 +511,11 @@ public class UserCredentialsSettings extends SettingsPreferenceFragment public boolean isSystem() { return UserHandle.getAppId(uid) == Process.SYSTEM_UID; } + + public String getAlias() { return alias; } + + public EnumSet getStoredTypes() { + return storedTypes; + } } }