From 916bac8f2efe63f835c3331eb8ec1db596f35310 Mon Sep 17 00:00:00 2001 From: changbetty Date: Fri, 16 Apr 2021 14:58:55 +0800 Subject: [PATCH] Adding an option to install a certificate from the CA certificate menu For CA ceritificate we only can install in Network Preferences > Advaned > Install certificates. So we add the option for user to install when you setup the wifi network. After you install the certificate, you can see the certificate in your menu. Bug: 176998563 Test: manual test make RunSettingsRoboTests ROBOTEST_FILTER=WifiConfigController2Test Change-Id: I532b12f9277c6a15c649907fa3711c807566c88e --- .../settings/wifi/AddNetworkFragment.java | 8 +++- .../wifi/ConfigureWifiEntryFragment.java | 7 +++ .../settings/wifi/WifiConfigController2.java | 45 +++++++++++++++---- .../wifi/WifiConfigController2Test.java | 41 ++++++++++++++++- 4 files changed, 90 insertions(+), 11 deletions(-) diff --git a/src/com/android/settings/wifi/AddNetworkFragment.java b/src/com/android/settings/wifi/AddNetworkFragment.java index 2ed213b8d55..4adc6727614 100644 --- a/src/com/android/settings/wifi/AddNetworkFragment.java +++ b/src/com/android/settings/wifi/AddNetworkFragment.java @@ -85,6 +85,13 @@ public class AddNetworkFragment extends InstrumentedFragment implements WifiConf return rootView; } + @Override + public void onResume() { + super.onResume(); + mUIController.showSecurityFields( + /* refreshEapMethods */ false, /* refreshCertificates */ true); + } + @Override public void onViewStateRestored(Bundle savedInstanceState) { super.onViewStateRestored(savedInstanceState); @@ -110,7 +117,6 @@ public class AddNetworkFragment extends InstrumentedFragment implements WifiConf @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - if (requestCode == REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER) { if (resultCode != Activity.RESULT_OK) { return; diff --git a/src/com/android/settings/wifi/ConfigureWifiEntryFragment.java b/src/com/android/settings/wifi/ConfigureWifiEntryFragment.java index c36a2986168..d2f50903698 100644 --- a/src/com/android/settings/wifi/ConfigureWifiEntryFragment.java +++ b/src/com/android/settings/wifi/ConfigureWifiEntryFragment.java @@ -127,6 +127,13 @@ public class ConfigureWifiEntryFragment extends InstrumentedFragment implements return rootView; } + @Override + public void onResume() { + super.onResume(); + mUiController.showSecurityFields( + /* refreshEapMethods */ false, /* refreshCertificates */ true); + } + @Override public void onViewStateRestored(Bundle savedInstanceState) { super.onViewStateRestored(savedInstanceState); diff --git a/src/com/android/settings/wifi/WifiConfigController2.java b/src/com/android/settings/wifi/WifiConfigController2.java index 1967371e130..65ac451c849 100644 --- a/src/com/android/settings/wifi/WifiConfigController2.java +++ b/src/com/android/settings/wifi/WifiConfigController2.java @@ -16,7 +16,10 @@ package com.android.settings.wifi; +import android.app.Activity; +import android.content.ComponentName; import android.content.Context; +import android.content.Intent; import android.content.res.Resources; import android.net.InetAddresses; import android.net.IpConfiguration; @@ -32,6 +35,7 @@ import android.net.wifi.WifiEnterpriseConfig.Eap; import android.net.wifi.WifiEnterpriseConfig.Phase2; import android.net.wifi.WifiManager; import android.os.IBinder; +import android.os.UserHandle; import android.security.keystore.KeyProperties; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; @@ -144,6 +148,15 @@ public class WifiConfigController2 implements TextWatcher, UNDESIRED_CERTIFICATE_MACRANDSAPSECRET }; + /* These values are for install certificate */ + private static final String ACTION_INSTALL_CERTS = "android.credentials.INSTALL"; + private static final String PACKAGE_INSTALL_CERTS = "com.android.certinstaller"; + private static final String CLASS_INSTALL_CERTS = "com.android.certinstaller.CertInstallerMain"; + private static final String KEY_INSTALL_CERTIFICATE = "certificate_install_usage"; + private static final String INSTALL_CERTIFICATE_VALUE = "wifi"; + + protected int REQUEST_INSTALL_CERTS = 1; + /* Phase2 methods supported by PEAP are limited */ private ArrayAdapter mPhase2PeapAdapter; /* Phase2 methods supported by TTLS are limited */ @@ -159,12 +172,13 @@ public class WifiConfigController2 implements TextWatcher, private String mMultipleCertSetString; private String mUseSystemCertsString; private String mDoNotProvideEapUserCertString; + @VisibleForTesting String mInstallCertsString; private Spinner mSecuritySpinner; @VisibleForTesting Spinner mEapMethodSpinner; private int mLastShownEapMethod; @VisibleForTesting Spinner mEapSimSpinner; // For EAP-SIM, EAP-AKA and EAP-AKA-PRIME. - private Spinner mEapCaCertSpinner; + @VisibleForTesting Spinner mEapCaCertSpinner; private Spinner mEapOcspSpinner; private TextView mEapDomainView; private Spinner mPhase2Spinner; @@ -258,6 +272,7 @@ public class WifiConfigController2 implements TextWatcher, mUseSystemCertsString = mContext.getString(R.string.wifi_use_system_certs); mDoNotProvideEapUserCertString = mContext.getString(R.string.wifi_do_not_provide_eap_user_cert); + mInstallCertsString = mContext.getString(R.string.wifi_install_credentials); mSsidScanButton = (ImageButton) mView.findViewById(R.id.ssid_scanner_button); mIpSettingsSpinner = (Spinner) mView.findViewById(R.id.ip_settings); @@ -942,7 +957,7 @@ public class WifiConfigController2 implements TextWatcher, } } - private void showSecurityFields(boolean refreshEapMethods, boolean refreshCertificates) { + protected void showSecurityFields(boolean refreshEapMethods, boolean refreshCertificates) { if (mWifiEntrySecurity == WifiEntry.SECURITY_NONE || mWifiEntrySecurity == WifiEntry.SECURITY_OWE) { mView.findViewById(R.id.security_fields).setVisibility(View.GONE); @@ -1031,11 +1046,8 @@ public class WifiConfigController2 implements TextWatcher, mDoNotProvideEapUserCertString, false /* showMultipleCerts */, false /* showUsePreinstalledCertOption */); - // To avoid the user connects to a non-secure network unexpectedly, - // request using system trusted certificates by default - // unless the user explicitly chooses "Do not validate" or other - // CA certificates. - setSelection(mEapCaCertSpinner, mUseSystemCertsString); + + setSelection(mEapCaCertSpinner, mUnspecifiedCertString); } // Modifying an existing network @@ -1494,6 +1506,7 @@ public class WifiConfigController2 implements TextWatcher, } if (showUsePreinstalledCertOption) { certs.add(mUseSystemCertsString); + certs.add(mInstallCertsString); } if (choices != null && choices.size() != 0) { @@ -1658,9 +1671,13 @@ public class WifiConfigController2 implements TextWatcher, final int selectedItemPosition = mEapMethodSpinner.getSelectedItemPosition(); if (mLastShownEapMethod != selectedItemPosition) { mLastShownEapMethod = selectedItemPosition; - showSecurityFields(/* refreshEapMethods */ false, /* refreshCertificates */ true); + showSecurityFields(/* refreshEapMethods */false, /* refreshCertificates */ true); } } else if (parent == mEapCaCertSpinner) { + String selectedItem = parent.getItemAtPosition(position).toString(); + if (selectedItem.equals(mInstallCertsString)) { + startActivityForInstallCerts(); + } showSecurityFields(/* refreshEapMethods */ false, /* refreshCertificates */ false); } else if (parent == mPhase2Spinner && mEapMethodSpinner.getSelectedItemPosition() == WIFI_EAP_METHOD_PEAP) { @@ -1682,6 +1699,18 @@ public class WifiConfigController2 implements TextWatcher, // } + /** + * Start the install page for user to install the existing certificate. + */ + private void startActivityForInstallCerts() { + Intent intent = new Intent(ACTION_INSTALL_CERTS); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.setComponent(new ComponentName(PACKAGE_INSTALL_CERTS, CLASS_INSTALL_CERTS)); + intent.putExtra(KEY_INSTALL_CERTIFICATE, INSTALL_CERTIFICATE_VALUE); + + mContext.startActivity(intent); + } + /** * Make the characters of the password visible if show_password is checked. */ diff --git a/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java b/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java index d227ac1bb1d..ff0d7b24d08 100644 --- a/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java +++ b/tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java @@ -18,11 +18,17 @@ package com.android.settings.wifi; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.robolectric.Shadows.shadowOf; import android.content.Context; +import android.content.Intent; import android.content.res.Resources; import android.net.IpConfiguration; import android.net.wifi.WifiConfiguration; @@ -30,12 +36,14 @@ import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.WifiEnterpriseConfig.Eap; import android.net.wifi.WifiEnterpriseConfig.Phase2; import android.net.wifi.WifiManager; +import android.os.UserHandle; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.view.LayoutInflater; import android.view.View; import android.view.inputmethod.InputMethodManager; +import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.LinearLayout; @@ -54,6 +62,7 @@ import com.google.common.collect.ImmutableList; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; @@ -81,6 +90,7 @@ public class WifiConfigController2Test { private Spinner mHiddenSettingsSpinner; private Spinner mEapCaCertSpinner; private Spinner mEapUserCertSpinner; + private String mUnspecifiedCertString; private String mUseSystemCertsString; private String mDoNotProvideEapUserCertString; private ShadowSubscriptionManager mShadowSubscriptionManager; @@ -107,10 +117,16 @@ public class WifiConfigController2Test { private static final String SAVED_CA_CERT = "saved CA cert"; private static final String SAVED_USER_CERT = "saved user cert"; + private static final int POSITION_SYSTEM_CERT = 1; + private static final int POSITION_INSTALL_CERT = 2; + private static final String ACTION_INSTALL_CERTS = "android.credentials.INSTALL"; + private static final String KEY_INSTALL_CERTIFICATE = "certificate_install_usage"; + private static final String INSTALL_CERTIFICATE_VALUE = "wifi"; + @Before public void setUp() { MockitoAnnotations.initMocks(this); - mContext = RuntimeEnvironment.application; + mContext = spy(RuntimeEnvironment.application); when(mConfigUiBase.getContext()).thenReturn(mContext); when(mWifiEntry.getSecurity()).thenReturn(WifiEntry.SECURITY_PSK); mView = LayoutInflater.from(mContext).inflate(R.layout.wifi_dialog, null); @@ -119,6 +135,7 @@ public class WifiConfigController2Test { mEapCaCertSpinner = mView.findViewById(R.id.ca_cert); mEapUserCertSpinner = mView.findViewById(R.id.user_cert); mUseSystemCertsString = mContext.getString(R.string.wifi_use_system_certs); + mUnspecifiedCertString = mContext.getString(R.string.wifi_unspecified); mDoNotProvideEapUserCertString = mContext.getString(R.string.wifi_do_not_provide_eap_user_cert); ipSettingsSpinner.setSelection(DHCP); @@ -709,7 +726,6 @@ public class WifiConfigController2Test { Phase2.AKA_PRIME); } - @Test public void getEapConfig_withPeapPhase2Unknown_shouldContainNoneMethod() { setUpModifyingSavedPeapConfigController(); @@ -835,9 +851,30 @@ public class WifiConfigController2Test { public void loadCaCertificateValue_shouldPersistentAsDefault() { setUpModifyingSavedCertificateConfigController(null, null); + mEapCaCertSpinner.setSelection(POSITION_SYSTEM_CERT); assertThat(mEapCaCertSpinner.getSelectedItem()).isEqualTo(mUseSystemCertsString); } + @Test + public void onItemSelected_shouldPersistentInstallCertsAndStartInstallActivity() { + String installCertsString = "install_certs"; + Spinner eapCaCertSpinner = mock(Spinner.class); + AdapterView view = mock(AdapterView.class); + when(eapCaCertSpinner.getItemAtPosition(anyInt())).thenReturn(view); + when(view.toString()).thenReturn(installCertsString); + mController.mInstallCertsString = installCertsString; + mController.mEapCaCertSpinner = eapCaCertSpinner; + + mController.onItemSelected(eapCaCertSpinner, null, POSITION_INSTALL_CERT, 0); + + final ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Intent.class); + verify(mContext).startActivity(argumentCaptor.capture()); + final Intent intent = argumentCaptor.getValue(); + assertThat(intent.getAction()).isEqualTo(ACTION_INSTALL_CERTS); + assertThat(intent.getExtra(KEY_INSTALL_CERTIFICATE, "")) + .isEqualTo(INSTALL_CERTIFICATE_VALUE); + } + @Test public void loadSavedCaCertificateValue_shouldBeCorrectValue() { setUpModifyingSavedCertificateConfigController(SAVED_CA_CERT, null);