Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 23666059 authored by Hai Shalom's avatar Hai Shalom
Browse files

[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
parent 68c7aad7
Loading
Loading
Loading
Loading
+38 −9
Original line number Diff line number Diff line
@@ -154,12 +154,16 @@ public class UserCredentialsSettings extends SettingsPreferenceFragment
                        dialog.dismiss();
                    }
                };
                if (item.isSystem()) {
                    // TODO: a safe means of clearing wifi certificates. Configs refer to aliases
                // 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<Credential, Void, Credential[]> {
            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<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 class UserCredentialsSettings extends SettingsPreferenceFragment
        public boolean isSystem() {
            return UserHandle.getAppId(uid) == Process.SYSTEM_UID;
        }

        public String getAlias() { return alias; }

        public EnumSet<Type> getStoredTypes() {
            return storedTypes;
        }
    }
}