Allow trusted system certificates to be used in EAP network configs
am: 2b16cd3920

* commit '2b16cd3920f95b2cd5c2426d81b5e1584ffc682d':
  Allow trusted system certificates to be used in EAP network configs
diff --git a/res/layout/wifi_dialog.xml b/res/layout/wifi_dialog.xml
index 05c33d7..44523f4 100644
--- a/res/layout/wifi_dialog.xml
+++ b/res/layout/wifi_dialog.xml
@@ -175,6 +175,18 @@
                             android:inputType="textNoSuggestions" />
                 </LinearLayout>
 
+                <LinearLayout android:id="@+id/no_domain_warning"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:visibility="gone"
+                        style="@style/wifi_item" >
+                    <TextView
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            style="@style/wifi_item_warning"
+                            android:text="@string/wifi_no_domain_warning" />
+                </LinearLayout>
+
                 <LinearLayout android:id="@+id/l_user_cert"
                         android:layout_width="match_parent"
                         android:layout_height="wrap_content"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c0b0650..5d093f1 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1644,12 +1644,17 @@
     <string name="wifi_unspecified">Please select</string>
     <!-- Hint for multiple certificates being added to the configuration -->
     <string name="wifi_multiple_cert_added">(Multiple certificates added)</string>
+    <!-- Menu option for using trusted system CA certificates to validate EAP servers -->
+    <string name="wifi_use_system_certs">Use system certificates</string>
     <!-- Menu option for not providing an EAP user certificate -->
     <string name="wifi_do_not_provide_eap_user_cert">Do not provide</string>
     <!-- Menu option for not validating the EAP server -->
     <string name="wifi_do_not_validate_eap_server">Do not validate</string>
     <!-- Warning message displayed if user choses not to validate the EAP server -->
     <string name="wifi_do_not_validate_eap_server_warning">No certificate specified. Your connection will not be private.</string>
+    <!-- Warning message displayed if user does not specify a domain for the CA certificate.
+         Only displayed if the user also chooses to use system certificates. -->
+    <string name="wifi_no_domain_warning">Must specify a domain.</string>
     <!-- Substring of status line when Wi-Fi Protected Setup (WPS) is available and
          string is listed first [CHAR LIMIT=20]-->
     <string name="wifi_wps_available_first_item">WPS available</string>
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index e0079cb..fbdc4bf 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -77,6 +77,8 @@
         TextView.OnEditorActionListener, View.OnKeyListener{
     private static final String TAG = "WifiConfigController";
 
+    private static final String SYSTEM_CA_STORE_PATH = "/system/etc/security/cacerts";
+
     private final WifiConfigUiBase mConfigUi;
     private final View mView;
     private final AccessPoint mAccessPoint;
@@ -117,10 +119,7 @@
 
     private String mUnspecifiedCertString;
     private String mMultipleCertSetString;
-    private static final int UNSPECIFIED_CERT_INDEX = 0;
-    private static final int NO_CERT_INDEX = 1;
-    private static final int MULTIPLE_CERT_SET_INDEX = 2;
-
+    private String mUseSystemCertsString;
     private String mDoNotProvideEapUserCertString;
     private String mDoNotValidateEapServerString;
 
@@ -188,6 +187,7 @@
 
         mUnspecifiedCertString = mContext.getString(R.string.wifi_unspecified);
         mMultipleCertSetString = mContext.getString(R.string.wifi_multiple_cert_added);
+        mUseSystemCertsString = mContext.getString(R.string.wifi_use_system_certs);
         mDoNotProvideEapUserCertString =
             mContext.getString(R.string.wifi_do_not_provide_eap_user_cert);
         mDoNotValidateEapServerString =
@@ -397,28 +397,54 @@
             enabled = ipAndProxyFieldsAreValid();
         }
         if (mEapCaCertSpinner != null
-                && mView.findViewById(R.id.l_ca_cert).getVisibility() != View.GONE
-                && ((String) mEapCaCertSpinner.getSelectedItem()).equals(mUnspecifiedCertString)) {
-            enabled = false;
+                && mView.findViewById(R.id.l_ca_cert).getVisibility() != View.GONE) {
+            String caCertSelection = (String) mEapCaCertSpinner.getSelectedItem();
+            if (caCertSelection.equals(mUnspecifiedCertString)) {
+                // Disallow submit if the user has not selected a CA certificate for an EAP network
+                // configuration.
+                enabled = false;
+            }
+            if (caCertSelection.equals(mUseSystemCertsString)
+                    && mEapDomainView != null
+                    && mView.findViewById(R.id.l_domain).getVisibility() != View.GONE
+                    && TextUtils.isEmpty(mEapDomainView.getText().toString())) {
+                // Disallow submit if the user chooses to use system certificates for EAP server
+                // validation, but does not provide a domain.
+                enabled = false;
+            }
         }
         if (mEapUserCertSpinner != null
                 && mView.findViewById(R.id.l_user_cert).getVisibility() != View.GONE
                 && ((String) mEapUserCertSpinner.getSelectedItem())
                        .equals(mUnspecifiedCertString)) {
+            // Disallow submit if the user has not selected a user certificate for an EAP network
+            // configuration.
             enabled = false;
         }
         return enabled;
     }
 
-    void showWarningMessageIfAppropriate() {
+    void showWarningMessagesIfAppropriate() {
         mView.findViewById(R.id.no_ca_cert_warning).setVisibility(View.GONE);
+        mView.findViewById(R.id.no_domain_warning).setVisibility(View.GONE);
+
         if (mEapCaCertSpinner != null
-                && mView.findViewById(R.id.l_ca_cert).getVisibility() != View.GONE
-                && ((String) mEapCaCertSpinner.getSelectedItem())
-                        .equals(mDoNotValidateEapServerString)) {
-            // Display warning if user chooses not to validate the EAP server with a user-supplied
-            // CA certificate in an EAP network configuration.
-            mView.findViewById(R.id.no_ca_cert_warning).setVisibility(View.VISIBLE);
+                && mView.findViewById(R.id.l_ca_cert).getVisibility() != View.GONE) {
+            String caCertSelection = (String) mEapCaCertSpinner.getSelectedItem();
+            if (caCertSelection.equals(mDoNotValidateEapServerString)) {
+                // Display warning if user chooses not to validate the EAP server with a
+                // user-supplied CA certificate in an EAP network configuration.
+                mView.findViewById(R.id.no_ca_cert_warning).setVisibility(View.VISIBLE);
+            }
+            if (caCertSelection.equals(mUseSystemCertsString)
+                    && mEapDomainView != null
+                    && mView.findViewById(R.id.l_domain).getVisibility() != View.GONE
+                    && TextUtils.isEmpty(mEapDomainView.getText().toString())) {
+                // Display warning if user chooses to use pre-installed public CA certificates
+                // without restricting the server domain that these certificates can be used to
+                // validate.
+                mView.findViewById(R.id.no_domain_warning).setVisibility(View.VISIBLE);
+            }
         }
     }
 
@@ -518,7 +544,9 @@
                 } else {
                     config.enterpriseConfig.setDomainSuffixMatch(
                             mEapDomainView.getText().toString());
-                    if (caCert.equals(mMultipleCertSetString)) {
+                    if (caCert.equals(mUseSystemCertsString)) {
+                        config.enterpriseConfig.setCaPath(SYSTEM_CA_STORE_PATH);
+                    } else if (caCert.equals(mMultipleCertSetString)) {
                         if (mAccessPoint != null) {
                             if (!mAccessPoint.isSaved()) {
                                 Log.e(TAG, "Multiple certs can only be set "
@@ -745,15 +773,24 @@
             mEapCaCertSpinner = (Spinner) mView.findViewById(R.id.ca_cert);
             mEapCaCertSpinner.setOnItemSelectedListener(this);
             mEapDomainView = (TextView) mView.findViewById(R.id.domain);
+            mEapDomainView.addTextChangedListener(this);
             mEapUserCertSpinner = (Spinner) mView.findViewById(R.id.user_cert);
             mEapUserCertSpinner.setOnItemSelectedListener(this);
             mEapIdentityView = (TextView) mView.findViewById(R.id.identity);
             mEapAnonymousView = (TextView) mView.findViewById(R.id.anonymous);
 
-            loadCertificates(mEapCaCertSpinner, Credentials.CA_CERTIFICATE, false,
-                    mDoNotValidateEapServerString);
-            loadCertificates(mEapUserCertSpinner, Credentials.USER_PRIVATE_KEY, false,
-                    mDoNotProvideEapUserCertString);
+            loadCertificates(
+                    mEapCaCertSpinner,
+                    Credentials.CA_CERTIFICATE,
+                    mDoNotValidateEapServerString,
+                    false,
+                    true);
+            loadCertificates(
+                    mEapUserCertSpinner,
+                    Credentials.USER_PRIVATE_KEY,
+                    mDoNotProvideEapUserCertString,
+                    false,
+                    false);
 
             // Modifying an existing network
             if (mAccessPoint != null && mAccessPoint.isSaved()) {
@@ -783,16 +820,24 @@
                         mPhase2Spinner.setSelection(phase2Method);
                         break;
                 }
-                String[] caCerts = enterpriseConfig.getCaCertificateAliases();
-                if (caCerts == null) {
-                    setSelection(mEapCaCertSpinner, mDoNotValidateEapServerString);
-                } else if (caCerts.length == 1) {
-                    setSelection(mEapCaCertSpinner, caCerts[0]);
+                if (!TextUtils.isEmpty(enterpriseConfig.getCaPath())) {
+                    setSelection(mEapCaCertSpinner, mUseSystemCertsString);
                 } else {
-                    // Reload the cert spinner with an extra "multiple certificates added" item
-                    loadCertificates(mEapCaCertSpinner,
-                            Credentials.CA_CERTIFICATE, true, mDoNotValidateEapServerString);
-                    mEapCaCertSpinner.setSelection(MULTIPLE_CERT_SET_INDEX);
+                    String[] caCerts = enterpriseConfig.getCaCertificateAliases();
+                    if (caCerts == null) {
+                        setSelection(mEapCaCertSpinner, mDoNotValidateEapServerString);
+                    } else if (caCerts.length == 1) {
+                        setSelection(mEapCaCertSpinner, caCerts[0]);
+                    } else {
+                        // Reload the cert spinner with an extra "multiple certificates added" item.
+                        loadCertificates(
+                                mEapCaCertSpinner,
+                                Credentials.CA_CERTIFICATE,
+                                mDoNotValidateEapServerString,
+                                true,
+                                true);
+                        setSelection(mEapCaCertSpinner, mMultipleCertSetString);
+                    }
                 }
                 mEapDomainView.setText(enterpriseConfig.getDomainSuffixMatch());
                 String userCert = enterpriseConfig.getClientCertificateAlias();
@@ -916,7 +961,7 @@
 
     private void setCaCertInvisible() {
         mView.findViewById(R.id.l_ca_cert).setVisibility(View.GONE);
-        mEapCaCertSpinner.setSelection(UNSPECIFIED_CERT_INDEX);
+        setSelection(mEapCaCertSpinner, mUnspecifiedCertString);
     }
 
     private void setDomainInvisible() {
@@ -926,7 +971,7 @@
 
     private void setUserCertInvisible() {
         mView.findViewById(R.id.l_user_cert).setVisibility(View.GONE);
-        mEapUserCertSpinner.setSelection(UNSPECIFIED_CERT_INDEX);
+        setSelection(mEapUserCertSpinner, mUnspecifiedCertString);
     }
 
     private void setAnonymousIdentInvisible() {
@@ -1051,17 +1096,24 @@
     }
 
     private void loadCertificates(
-            Spinner spinner, String prefix, boolean showMultipleCerts, String noCertificateString) {
+            Spinner spinner,
+            String prefix,
+            String noCertificateString,
+            boolean showMultipleCerts,
+            boolean showUsePreinstalledCertOption) {
         final Context context = mConfigUi.getContext();
 
         ArrayList<String> certs = new ArrayList<String>();
-        certs.add(UNSPECIFIED_CERT_INDEX, mUnspecifiedCertString);
-        certs.add(NO_CERT_INDEX, noCertificateString);
+        certs.add(mUnspecifiedCertString);
         if (showMultipleCerts) {
-            certs.add(MULTIPLE_CERT_SET_INDEX, mMultipleCertSetString);
+            certs.add(mMultipleCertSetString);
+        }
+        if (showUsePreinstalledCertOption) {
+            certs.add(mUseSystemCertsString);
         }
         certs.addAll(
                 Arrays.asList(KeyStore.getInstance().list(prefix, android.os.Process.WIFI_UID)));
+        certs.add(noCertificateString);
 
         final ArrayAdapter<String> adapter = new ArrayAdapter<String>(
                 context, android.R.layout.simple_spinner_item,
@@ -1091,6 +1143,7 @@
     public void afterTextChanged(Editable s) {
         mTextViewChangedHandler.post(new Runnable() {
                 public void run() {
+                    showWarningMessagesIfAppropriate();
                     enableSubmitIfAppropriate();
                 }
             });
@@ -1159,7 +1212,7 @@
         } else {
             showIpConfigFields();
         }
-        showWarningMessageIfAppropriate();
+        showWarningMessagesIfAppropriate();
         enableSubmitIfAppropriate();
     }