[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
diff --git a/src/com/android/settings/UserCredentialsSettings.java b/src/com/android/settings/UserCredentialsSettings.java
index c30e51d..d322819 100644
--- a/src/com/android/settings/UserCredentialsSettings.java
+++ b/src/com/android/settings/UserCredentialsSettings.java
@@ -154,11 +154,15 @@
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 @@
* 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<Credential, Void, Credential[]> {
private Context context;
@@ -188,14 +193,32 @@
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<Credential.Type> 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 boolean isSystem() {
return UserHandle.getAppId(uid) == Process.SYSTEM_UID;
}
+
+ public String getAlias() { return alias; }
+
+ public EnumSet<Type> getStoredTypes() {
+ return storedTypes;
+ }
}
}