OSDN Git Service

VpnSettings: add support for server certificates.
authorChia-chi Yeh <chiachi@android.com>
Wed, 7 Dec 2011 01:51:01 +0000 (17:51 -0800)
committerChia-chi Yeh <chiachi@android.com>
Wed, 7 Dec 2011 01:51:01 +0000 (17:51 -0800)
Bug: 5714397
Change-Id: I5ce13e244fba554bec31c4935571b09127b9270a

res/layout/vpn_dialog.xml
res/values/strings.xml
src/com/android/settings/vpn2/VpnDialog.java
src/com/android/settings/vpn2/VpnProfile.java
src/com/android/settings/vpn2/VpnSettings.java

index 841e093..034b6bf 100644 (file)
@@ -80,7 +80,7 @@
                         android:prompt="@string/vpn_ipsec_user_cert" />
             </LinearLayout>
 
-            <LinearLayout android:id="@+id/ipsec_ca"
+            <LinearLayout android:id="@+id/ipsec_peer"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:orientation="vertical"
@@ -88,6 +88,9 @@
                 <TextView style="@style/vpn_label" android:text="@string/vpn_ipsec_ca_cert"/>
                 <Spinner style="@style/vpn_value" android:id="@+id/ipsec_ca_cert"
                         android:prompt="@string/vpn_ipsec_ca_cert" />
+                <TextView style="@style/vpn_label" android:text="@string/vpn_ipsec_server_cert"/>
+                <Spinner style="@style/vpn_value" android:id="@+id/ipsec_server_cert"
+                        android:prompt="@string/vpn_ipsec_server_cert" />
             </LinearLayout>
 
             <CheckBox style="@style/vpn_value" android:id="@+id/show_options"
index aa3b94f..9a29122 100644 (file)
@@ -3658,6 +3658,8 @@ found in the list of installed apps.</string>
     <string name="vpn_ipsec_user_cert">IPSec user certificate</string>
     <!-- Selection label for the IPSec CA certificate of a VPN network. [CHAR LIMIT=40] -->
     <string name="vpn_ipsec_ca_cert">IPSec CA certificate</string>
+    <!-- Selection label for the IPSec server certificate of a VPN network. [CHAR LIMIT=40] -->
+    <string name="vpn_ipsec_server_cert">IPSec server certificate</string>
     <!-- Checkbox label to show advanced options of a VPN network. [CHAR LIMIT=40] -->
     <string name="vpn_show_options">Show advanced options</string>
     <!-- Input label for the DNS search domains of a VPN network. [CHAR LIMIT=40] -->
@@ -3676,6 +3678,8 @@ found in the list of installed apps.</string>
     <string name="vpn_not_used">(not used)</string>
     <!-- Option to not use a CA certificate to verify the VPN server. [CHAR LIMIT=40] -->
     <string name="vpn_no_ca_cert">(don\'t verify server)</string>
+    <!-- Option to use the server certificate received from the VPN server. [CHAR LIMIT=40] -->
+    <string name="vpn_no_server_cert">(received from server)</string>
 
     <!-- Button label to cancel chaning a VPN network. [CHAR LIMIT=40] -->
     <string name="vpn_cancel">Cancel</string>
index cce5e2d..aaae887 100644 (file)
@@ -61,6 +61,7 @@ class VpnDialog extends AlertDialog implements TextWatcher,
     private TextView mIpsecSecret;
     private Spinner mIpsecUserCert;
     private Spinner mIpsecCaCert;
+    private Spinner mIpsecServerCert;
     private CheckBox mSaveLogin;
 
     VpnDialog(Context context, DialogInterface.OnClickListener listener,
@@ -94,6 +95,7 @@ class VpnDialog extends AlertDialog implements TextWatcher,
         mIpsecSecret = (TextView) mView.findViewById(R.id.ipsec_secret);
         mIpsecUserCert = (Spinner) mView.findViewById(R.id.ipsec_user_cert);
         mIpsecCaCert = (Spinner) mView.findViewById(R.id.ipsec_ca_cert);
+        mIpsecServerCert = (Spinner) mView.findViewById(R.id.ipsec_server_cert);
         mSaveLogin = (CheckBox) mView.findViewById(R.id.save_login);
 
         // Second, copy values from the profile.
@@ -113,6 +115,8 @@ class VpnDialog extends AlertDialog implements TextWatcher,
                 0, mProfile.ipsecUserCert);
         loadCertificates(mIpsecCaCert, Credentials.CA_CERTIFICATE,
                 R.string.vpn_no_ca_cert, mProfile.ipsecCaCert);
+        loadCertificates(mIpsecServerCert, Credentials.USER_CERTIFICATE,
+                R.string.vpn_no_server_cert, mProfile.ipsecServerCert);
         mSaveLogin.setChecked(mProfile.saveLogin);
 
         // Third, add listeners to required fields.
@@ -215,7 +219,7 @@ class VpnDialog extends AlertDialog implements TextWatcher,
         mView.findViewById(R.id.l2tp).setVisibility(View.GONE);
         mView.findViewById(R.id.ipsec_psk).setVisibility(View.GONE);
         mView.findViewById(R.id.ipsec_user).setVisibility(View.GONE);
-        mView.findViewById(R.id.ipsec_ca).setVisibility(View.GONE);
+        mView.findViewById(R.id.ipsec_peer).setVisibility(View.GONE);
 
         // Then, unhide type-specific fields.
         switch (type) {
@@ -237,7 +241,7 @@ class VpnDialog extends AlertDialog implements TextWatcher,
                 mView.findViewById(R.id.ipsec_user).setVisibility(View.VISIBLE);
                 // fall through
             case VpnProfile.TYPE_IPSEC_HYBRID_RSA:
-                mView.findViewById(R.id.ipsec_ca).setVisibility(View.VISIBLE);
+                mView.findViewById(R.id.ipsec_peer).setVisibility(View.VISIBLE);
                 break;
         }
     }
@@ -363,6 +367,9 @@ class VpnDialog extends AlertDialog implements TextWatcher,
                 if (mIpsecCaCert.getSelectedItemPosition() != 0) {
                     profile.ipsecCaCert = (String) mIpsecCaCert.getSelectedItem();
                 }
+                if (mIpsecServerCert.getSelectedItemPosition() != 0) {
+                    profile.ipsecServerCert = (String) mIpsecServerCert.getSelectedItem();
+                }
                 break;
         }
 
index 3ee3af0..d4d0e79 100644 (file)
@@ -51,6 +51,7 @@ class VpnProfile implements Cloneable {
     String ipsecSecret = "";    // 11
     String ipsecUserCert = "";  // 12
     String ipsecCaCert = "";    // 13
+    String ipsecServerCert = "";// 14
 
     // Helper fields.
     boolean saveLogin = false;
@@ -66,8 +67,8 @@ class VpnProfile implements Cloneable {
             }
 
             String[] values = new String(value, Charsets.UTF_8).split("\0", -1);
-            // Currently it always has 14 fields.
-            if (values.length < 14) {
+            // There can be 14 or 15 values in ICS MR1.
+            if (values.length < 14 || values.length > 15) {
                 return null;
             }
 
@@ -89,6 +90,7 @@ class VpnProfile implements Cloneable {
             profile.ipsecSecret = values[11];
             profile.ipsecUserCert = values[12];
             profile.ipsecCaCert = values[13];
+            profile.ipsecServerCert = (values.length > 14) ? values[14] : "";
 
             profile.saveLogin = !profile.username.isEmpty() || !profile.password.isEmpty();
             return profile;
@@ -113,6 +115,7 @@ class VpnProfile implements Cloneable {
         builder.append('\0').append(ipsecSecret);
         builder.append('\0').append(ipsecUserCert);
         builder.append('\0').append(ipsecCaCert);
+        builder.append('\0').append(ipsecServerCert);
         return builder.toString().getBytes(Charsets.UTF_8);
     }
 }
index 0197333..655306a 100644 (file)
@@ -354,6 +354,7 @@ public class VpnSettings extends SettingsPreferenceFragment implements
         String privateKey = "";
         String userCert = "";
         String caCert = "";
+        String serverCert = "";
         if (!profile.ipsecUserCert.isEmpty()) {
             byte[] value = mKeyStore.get(Credentials.USER_PRIVATE_KEY + profile.ipsecUserCert);
             privateKey = (value == null) ? null : new String(value, Charsets.UTF_8);
@@ -364,7 +365,11 @@ public class VpnSettings extends SettingsPreferenceFragment implements
             byte[] value = mKeyStore.get(Credentials.CA_CERTIFICATE + profile.ipsecCaCert);
             caCert = (value == null) ? null : new String(value, Charsets.UTF_8);
         }
-        if (privateKey == null || userCert == null || caCert == null) {
+        if (!profile.ipsecServerCert.isEmpty()) {
+            byte[] value = mKeyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecServerCert);
+            serverCert = (value == null) ? null : new String(value, Charsets.UTF_8);
+        }
+        if (privateKey == null || userCert == null || caCert == null || serverCert == null) {
             // TODO: find out a proper way to handle this. Delete these keys?
             throw new IllegalStateException("Cannot load credentials");
         }
@@ -380,7 +385,8 @@ public class VpnSettings extends SettingsPreferenceFragment implements
                 break;
             case VpnProfile.TYPE_L2TP_IPSEC_RSA:
                 racoon = new String[] {
-                    interfaze, profile.server, "udprsa", privateKey, userCert, caCert, "1701",
+                    interfaze, profile.server, "udprsa", privateKey, userCert,
+                    caCert, serverCert, "1701",
                 };
                 break;
             case VpnProfile.TYPE_IPSEC_XAUTH_PSK:
@@ -391,14 +397,14 @@ public class VpnSettings extends SettingsPreferenceFragment implements
                 break;
             case VpnProfile.TYPE_IPSEC_XAUTH_RSA:
                 racoon = new String[] {
-                    interfaze, profile.server, "xauthrsa", privateKey, userCert, caCert,
-                    profile.username, profile.password, "", gateway,
+                    interfaze, profile.server, "xauthrsa", privateKey, userCert,
+                    caCert, serverCert, profile.username, profile.password, "", gateway,
                 };
                 break;
             case VpnProfile.TYPE_IPSEC_HYBRID_RSA:
                 racoon = new String[] {
-                    interfaze, profile.server, "hybridrsa", caCert,
-                    profile.username, profile.password, "", gateway,
+                    interfaze, profile.server, "hybridrsa",
+                    caCert, serverCert, profile.username, profile.password, "", gateway,
                 };
                 break;
         }