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