am cb41032d
: Merge change 26186 into eclair
Merge commit 'cb41032d85e2538c0a0a85f72656891c6203dc9b' into eclair-plus-aosp * commit 'cb41032d85e2538c0a0a85f72656891c6203dc9b': Settings: revise VpnSettings.
This commit is contained in:
@@ -24,7 +24,8 @@ import android.preference.EditTextPreference;
|
|||||||
import android.preference.ListPreference;
|
import android.preference.ListPreference;
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
import android.preference.PreferenceGroup;
|
import android.preference.PreferenceGroup;
|
||||||
import android.security.CertTool;
|
import android.security.Credentials;
|
||||||
|
import android.security.KeyStore;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,6 +34,8 @@ import android.text.TextUtils;
|
|||||||
class L2tpIpsecEditor extends L2tpEditor {
|
class L2tpIpsecEditor extends L2tpEditor {
|
||||||
private static final String TAG = L2tpIpsecEditor.class.getSimpleName();
|
private static final String TAG = L2tpIpsecEditor.class.getSimpleName();
|
||||||
|
|
||||||
|
private KeyStore mKeyStore = KeyStore.getInstance();
|
||||||
|
|
||||||
private ListPreference mUserCertificate;
|
private ListPreference mUserCertificate;
|
||||||
private ListPreference mCaCertificate;
|
private ListPreference mCaCertificate;
|
||||||
|
|
||||||
@@ -67,7 +70,7 @@ class L2tpIpsecEditor extends L2tpEditor {
|
|||||||
mUserCertificate = createListPreference(c,
|
mUserCertificate = createListPreference(c,
|
||||||
R.string.vpn_user_certificate_title,
|
R.string.vpn_user_certificate_title,
|
||||||
mProfile.getUserCertificate(),
|
mProfile.getUserCertificate(),
|
||||||
CertTool.getInstance().getAllUserCertificateKeys(),
|
mKeyStore.saw(Credentials.USER_CERTIFICATE),
|
||||||
new Preference.OnPreferenceChangeListener() {
|
new Preference.OnPreferenceChangeListener() {
|
||||||
public boolean onPreferenceChange(
|
public boolean onPreferenceChange(
|
||||||
Preference pref, Object newValue) {
|
Preference pref, Object newValue) {
|
||||||
@@ -86,7 +89,7 @@ class L2tpIpsecEditor extends L2tpEditor {
|
|||||||
mCaCertificate = createListPreference(c,
|
mCaCertificate = createListPreference(c,
|
||||||
R.string.vpn_ca_certificate_title,
|
R.string.vpn_ca_certificate_title,
|
||||||
mProfile.getCaCertificate(),
|
mProfile.getCaCertificate(),
|
||||||
CertTool.getInstance().getAllCaCertificateKeys(),
|
mKeyStore.saw(Credentials.CA_CERTIFICATE),
|
||||||
new Preference.OnPreferenceChangeListener() {
|
new Preference.OnPreferenceChangeListener() {
|
||||||
public boolean onPreferenceChange(
|
public boolean onPreferenceChange(
|
||||||
Preference pref, Object newValue) {
|
Preference pref, Object newValue) {
|
||||||
|
@@ -47,8 +47,8 @@ import android.preference.PreferenceCategory;
|
|||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.preference.PreferenceScreen;
|
import android.preference.PreferenceScreen;
|
||||||
import android.preference.Preference.OnPreferenceClickListener;
|
import android.preference.Preference.OnPreferenceClickListener;
|
||||||
import android.security.CertTool;
|
import android.security.Credentials;
|
||||||
import android.security.Keystore;
|
import android.security.KeyStore;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.ContextMenu;
|
import android.view.ContextMenu;
|
||||||
@@ -109,9 +109,8 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
|
|
||||||
private static final int NO_ERROR = VpnManager.VPN_ERROR_NO_ERROR;
|
private static final int NO_ERROR = VpnManager.VPN_ERROR_NO_ERROR;
|
||||||
|
|
||||||
private static final String NAMESPACE_VPN = "vpn";
|
private static final String KEY_PREFIX_IPSEC_PSK = Credentials.VPN + 'i';
|
||||||
private static final String KEY_PREFIX_IPSEC_PSK = "ipsk000";
|
private static final String KEY_PREFIX_L2TP_SECRET = Credentials.VPN + 'l';
|
||||||
private static final String KEY_PREFIX_L2TP_SECRET = "lscrt000";
|
|
||||||
|
|
||||||
private PreferenceScreen mAddVpn;
|
private PreferenceScreen mAddVpn;
|
||||||
private PreferenceCategory mVpnListContainer;
|
private PreferenceCategory mVpnListContainer;
|
||||||
@@ -129,6 +128,8 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
// states saved for unlocking keystore
|
// states saved for unlocking keystore
|
||||||
private Runnable mUnlockAction;
|
private Runnable mUnlockAction;
|
||||||
|
|
||||||
|
private KeyStore mKeyStore = KeyStore.getInstance();
|
||||||
|
|
||||||
private VpnManager mVpnManager = new VpnManager(this);
|
private VpnManager mVpnManager = new VpnManager(this);
|
||||||
|
|
||||||
private ConnectivityReceiver mConnectivityReceiver =
|
private ConnectivityReceiver mConnectivityReceiver =
|
||||||
@@ -172,7 +173,7 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
if ((mUnlockAction != null) && isKeystoreUnlocked()) {
|
if ((mUnlockAction != null) && isKeyStoreUnlocked()) {
|
||||||
Runnable action = mUnlockAction;
|
Runnable action = mUnlockAction;
|
||||||
mUnlockAction = null;
|
mUnlockAction = null;
|
||||||
runOnUiThread(action);
|
runOnUiThread(action);
|
||||||
@@ -402,13 +403,13 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needKeystoreToSave(p)) {
|
if (needKeyStoreToSave(p)) {
|
||||||
Runnable action = new Runnable() {
|
Runnable action = new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
onActivityResult(requestCode, resultCode, data);
|
onActivityResult(requestCode, resultCode, data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (!unlockKeystore(p, action)) return;
|
if (!unlockKeyStore(p, action)) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -610,22 +611,26 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
startActivityForResult(intent, REQUEST_SELECT_VPN_TYPE);
|
startActivityForResult(intent, REQUEST_SELECT_VPN_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isKeystoreUnlocked() {
|
private boolean isKeyStoreUnlocked() {
|
||||||
return (Keystore.getInstance().getState() == Keystore.UNLOCKED);
|
return mKeyStore.test() == KeyStore.NO_ERROR;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Returns true if the profile needs to access keystore
|
|
||||||
private boolean needKeystoreToSave(VpnProfile p) {
|
|
||||||
return needKeystoreToConnect(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the profile needs to access keystore
|
// Returns true if the profile needs to access keystore
|
||||||
private boolean needKeystoreToEdit(VpnProfile p) {
|
private boolean needKeyStoreToSave(VpnProfile p) {
|
||||||
switch (p.getType()) {
|
switch (p.getType()) {
|
||||||
case L2TP_IPSEC:
|
|
||||||
case L2TP_IPSEC_PSK:
|
case L2TP_IPSEC_PSK:
|
||||||
|
L2tpIpsecPskProfile pskProfile = (L2tpIpsecPskProfile) p;
|
||||||
|
String presharedKey = pskProfile.getPresharedKey();
|
||||||
|
if (!TextUtils.isEmpty(presharedKey)) return true;
|
||||||
|
// pass through
|
||||||
|
|
||||||
|
case L2TP:
|
||||||
|
L2tpProfile l2tpProfile = (L2tpProfile) p;
|
||||||
|
if (l2tpProfile.isSecretEnabled() &&
|
||||||
|
!TextUtils.isEmpty(l2tpProfile.getSecretString())) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
// pass through
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@@ -633,7 +638,7 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the profile needs to access keystore
|
// Returns true if the profile needs to access keystore
|
||||||
private boolean needKeystoreToConnect(VpnProfile p) {
|
private boolean needKeyStoreToConnect(VpnProfile p) {
|
||||||
switch (p.getType()) {
|
switch (p.getType()) {
|
||||||
case L2TP_IPSEC:
|
case L2TP_IPSEC:
|
||||||
case L2TP_IPSEC_PSK:
|
case L2TP_IPSEC_PSK:
|
||||||
@@ -648,37 +653,27 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if keystore is unlocked or keystore is not a concern
|
// Returns true if keystore is unlocked or keystore is not a concern
|
||||||
private boolean unlockKeystore(VpnProfile p, Runnable action) {
|
private boolean unlockKeyStore(VpnProfile p, Runnable action) {
|
||||||
if (isKeystoreUnlocked()) return true;
|
if (isKeyStoreUnlocked()) return true;
|
||||||
mUnlockAction = action;
|
mUnlockAction = action;
|
||||||
startActivity(
|
Credentials.getInstance().unlock(this);
|
||||||
new Intent(Keystore.ACTION_UNLOCK_CREDENTIAL_STORAGE));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startVpnEditor(final VpnProfile profile) {
|
private void startVpnEditor(final VpnProfile profile) {
|
||||||
if (needKeystoreToEdit(profile)) {
|
|
||||||
Runnable action = new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
startVpnEditor(profile);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (!unlockKeystore(profile, action)) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Intent intent = new Intent(this, VpnEditor.class);
|
Intent intent = new Intent(this, VpnEditor.class);
|
||||||
intent.putExtra(KEY_VPN_PROFILE, (Parcelable) profile);
|
intent.putExtra(KEY_VPN_PROFILE, (Parcelable) profile);
|
||||||
startActivityForResult(intent, REQUEST_ADD_OR_EDIT_PROFILE);
|
startActivityForResult(intent, REQUEST_ADD_OR_EDIT_PROFILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void connect(final VpnProfile p) {
|
private synchronized void connect(final VpnProfile p) {
|
||||||
if (needKeystoreToConnect(p)) {
|
if (needKeyStoreToConnect(p)) {
|
||||||
Runnable action = new Runnable() {
|
Runnable action = new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
connect(p);
|
connect(p);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (!unlockKeystore(p, action)) return;
|
if (!unlockKeyStore(p, action)) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!checkSecrets(p)) return;
|
if (!checkSecrets(p)) return;
|
||||||
@@ -888,43 +883,32 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
return mVpnManager.createVpnProfile(Enum.valueOf(VpnType.class, type));
|
return mVpnManager.createVpnProfile(Enum.valueOf(VpnType.class, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String keyNameForDaemon(String keyName) {
|
|
||||||
return NAMESPACE_VPN + "_" + keyName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean checkSecrets(VpnProfile p) {
|
private boolean checkSecrets(VpnProfile p) {
|
||||||
Keystore ks = Keystore.getInstance();
|
|
||||||
HashSet<String> secretSet = new HashSet<String>();
|
|
||||||
boolean secretMissing = false;
|
boolean secretMissing = false;
|
||||||
|
|
||||||
if (p instanceof L2tpIpsecProfile) {
|
if (p instanceof L2tpIpsecProfile) {
|
||||||
L2tpIpsecProfile certProfile = (L2tpIpsecProfile) p;
|
L2tpIpsecProfile certProfile = (L2tpIpsecProfile) p;
|
||||||
CertTool certTool = CertTool.getInstance();
|
|
||||||
Collections.addAll(secretSet, certTool.getAllCaCertificateKeys());
|
|
||||||
String cert = certProfile.getCaCertificate();
|
String cert = certProfile.getCaCertificate();
|
||||||
if (TextUtils.isEmpty(cert) || !secretSet.contains(cert)) {
|
if (TextUtils.isEmpty(cert) ||
|
||||||
|
!mKeyStore.contains(Credentials.CA_CERTIFICATE + cert)) {
|
||||||
certProfile.setCaCertificate(null);
|
certProfile.setCaCertificate(null);
|
||||||
secretMissing = true;
|
secretMissing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
secretSet.clear();
|
|
||||||
Collections.addAll(secretSet, certTool.getAllUserCertificateKeys());
|
|
||||||
cert = certProfile.getUserCertificate();
|
cert = certProfile.getUserCertificate();
|
||||||
if (TextUtils.isEmpty(cert) || !secretSet.contains(cert)) {
|
if (TextUtils.isEmpty(cert) ||
|
||||||
|
!mKeyStore.contains(Credentials.USER_CERTIFICATE + cert)) {
|
||||||
certProfile.setUserCertificate(null);
|
certProfile.setUserCertificate(null);
|
||||||
secretMissing = true;
|
secretMissing = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
secretSet.clear();
|
|
||||||
Collections.addAll(secretSet, ks.listKeys(NAMESPACE_VPN));
|
|
||||||
|
|
||||||
if (p instanceof L2tpIpsecPskProfile) {
|
if (p instanceof L2tpIpsecPskProfile) {
|
||||||
L2tpIpsecPskProfile pskProfile = (L2tpIpsecPskProfile) p;
|
L2tpIpsecPskProfile pskProfile = (L2tpIpsecPskProfile) p;
|
||||||
String presharedKey = pskProfile.getPresharedKey();
|
String presharedKey = pskProfile.getPresharedKey();
|
||||||
String keyName = KEY_PREFIX_IPSEC_PSK + p.getId();
|
String key = KEY_PREFIX_IPSEC_PSK + p.getId();
|
||||||
if (TextUtils.isEmpty(presharedKey)
|
if (TextUtils.isEmpty(presharedKey) || !mKeyStore.contains(key)) {
|
||||||
|| !secretSet.contains(keyName)) {
|
|
||||||
pskProfile.setPresharedKey(null);
|
pskProfile.setPresharedKey(null);
|
||||||
secretMissing = true;
|
secretMissing = true;
|
||||||
}
|
}
|
||||||
@@ -934,9 +918,8 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
L2tpProfile l2tpProfile = (L2tpProfile) p;
|
L2tpProfile l2tpProfile = (L2tpProfile) p;
|
||||||
if (l2tpProfile.isSecretEnabled()) {
|
if (l2tpProfile.isSecretEnabled()) {
|
||||||
String secret = l2tpProfile.getSecretString();
|
String secret = l2tpProfile.getSecretString();
|
||||||
String keyName = KEY_PREFIX_L2TP_SECRET + p.getId();
|
String key = KEY_PREFIX_L2TP_SECRET + p.getId();
|
||||||
if (TextUtils.isEmpty(secret)
|
if (TextUtils.isEmpty(secret) || !mKeyStore.contains(key)) {
|
||||||
|| !secretSet.contains(keyName)) {
|
|
||||||
l2tpProfile.setSecretString(null);
|
l2tpProfile.setSecretString(null);
|
||||||
secretMissing = true;
|
secretMissing = true;
|
||||||
}
|
}
|
||||||
@@ -953,35 +936,30 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void processSecrets(VpnProfile p) {
|
private void processSecrets(VpnProfile p) {
|
||||||
Keystore ks = Keystore.getInstance();
|
|
||||||
switch (p.getType()) {
|
switch (p.getType()) {
|
||||||
case L2TP_IPSEC_PSK:
|
case L2TP_IPSEC_PSK:
|
||||||
L2tpIpsecPskProfile pskProfile = (L2tpIpsecPskProfile) p;
|
L2tpIpsecPskProfile pskProfile = (L2tpIpsecPskProfile) p;
|
||||||
String presharedKey = pskProfile.getPresharedKey();
|
String presharedKey = pskProfile.getPresharedKey();
|
||||||
String keyName = KEY_PREFIX_IPSEC_PSK + p.getId();
|
String key = KEY_PREFIX_IPSEC_PSK + p.getId();
|
||||||
if (!TextUtils.isEmpty(presharedKey)) {
|
if (!TextUtils.isEmpty(presharedKey) &&
|
||||||
int ret = ks.put(NAMESPACE_VPN, keyName, presharedKey);
|
!mKeyStore.put(key, presharedKey)) {
|
||||||
if (ret != 0) {
|
Log.e(TAG, "keystore write failed: key=" + key);
|
||||||
Log.e(TAG, "keystore write failed: key=" + keyName);
|
|
||||||
}
|
}
|
||||||
}
|
pskProfile.setPresharedKey(key);
|
||||||
pskProfile.setPresharedKey(keyNameForDaemon(keyName));
|
|
||||||
// pass through
|
// pass through
|
||||||
|
|
||||||
case L2TP:
|
case L2TP:
|
||||||
L2tpProfile l2tpProfile = (L2tpProfile) p;
|
L2tpProfile l2tpProfile = (L2tpProfile) p;
|
||||||
keyName = KEY_PREFIX_L2TP_SECRET + p.getId();
|
key = KEY_PREFIX_L2TP_SECRET + p.getId();
|
||||||
if (l2tpProfile.isSecretEnabled()) {
|
if (l2tpProfile.isSecretEnabled()) {
|
||||||
String secret = l2tpProfile.getSecretString();
|
String secret = l2tpProfile.getSecretString();
|
||||||
if (!TextUtils.isEmpty(secret)) {
|
if (!TextUtils.isEmpty(secret) &&
|
||||||
int ret = ks.put(NAMESPACE_VPN, keyName, secret);
|
!mKeyStore.put(key, secret)) {
|
||||||
if (ret != 0) {
|
Log.e(TAG, "keystore write failed: key=" + key);
|
||||||
Log.e(TAG, "keystore write failed: key=" + keyName);
|
|
||||||
}
|
}
|
||||||
}
|
l2tpProfile.setSecretString(key);
|
||||||
l2tpProfile.setSecretString(keyNameForDaemon(keyName));
|
|
||||||
} else {
|
} else {
|
||||||
ks.remove(NAMESPACE_VPN, keyName);
|
mKeyStore.delete(key);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user