1310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh/* 2310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * Copyright (C) 2011 The Android Open Source Project 3310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * 4310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * Licensed under the Apache License, Version 2.0 (the "License"); 5310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * you may not use this file except in compliance with the License. 6310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * You may obtain a copy of the License at 7310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * 8310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * http://www.apache.org/licenses/LICENSE-2.0 9310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * 10310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * Unless required by applicable law or agreed to in writing, software 11310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * distributed under the License is distributed on an "AS IS" BASIS, 12310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * See the License for the specific language governing permissions and 14310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh * limitations under the License. 15310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh */ 16310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 17310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehpackage com.android.settings.vpn2; 18310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 19310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport com.android.settings.R; 20310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 21310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.content.Context; 22310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.content.DialogInterface; 23bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yehimport android.net.IConnectivityManager; 24413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yehimport android.net.LinkProperties; 25f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yehimport android.net.RouteInfo; 26310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.os.Bundle; 27310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.os.Handler; 28310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.os.Message; 29bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yehimport android.os.ServiceManager; 30310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.preference.Preference; 31310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.preference.PreferenceGroup; 32310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.security.Credentials; 33310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.security.KeyStore; 34310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.util.Log; 35310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.view.ContextMenu; 36310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.view.ContextMenu.ContextMenuInfo; 37310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.view.Menu; 38310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.view.MenuItem; 39310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.view.View; 40310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport android.widget.AdapterView.AdapterContextMenuInfo; 41310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 4297fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yehimport com.android.internal.net.LegacyVpnInfo; 43d95ec871138ebb367cfd8b67b4814438ac30c628Chia-chi Yehimport com.android.internal.net.VpnConfig; 44310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport com.android.settings.SettingsPreferenceFragment; 45310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 46f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yehimport java.net.Inet4Address; 47413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yehimport java.nio.charset.Charsets; 48d95ec871138ebb367cfd8b67b4814438ac30c628Chia-chi Yehimport java.util.Arrays; 49310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehimport java.util.HashMap; 50310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 51310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yehpublic class VpnSettings extends SettingsPreferenceFragment implements 52310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh Handler.Callback, Preference.OnPreferenceClickListener, 53310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh DialogInterface.OnClickListener, DialogInterface.OnDismissListener { 54310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 55310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh private static final String TAG = "VpnSettings"; 56310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 5797fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh private final IConnectivityManager mService = IConnectivityManager.Stub 5897fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh .asInterface(ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); 59310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh private final KeyStore mKeyStore = KeyStore.getInstance(); 60310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh private boolean mUnlocking = false; 61310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 62310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh private HashMap<String, VpnPreference> mPreferences; 63310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh private VpnDialog mDialog; 64bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh 65bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh private Handler mUpdater; 6697fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh private LegacyVpnInfo mInfo; 67bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh 68bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh // The key of the profile for the current ContextMenu. 69310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh private String mSelectedKey; 70310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 71310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh @Override 72310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh public void onCreate(Bundle savedState) { 73310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh super.onCreate(savedState); 74310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh addPreferencesFromResource(R.xml.vpn_settings2); 75d501b5c963c0cbcc9c666f502229599464eaf3fdChia-chi Yeh getPreferenceScreen().setOrderingAsAdded(false); 76310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 77310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if (savedState != null) { 78310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh VpnProfile profile = VpnProfile.decode(savedState.getString("VpnKey"), 79310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh savedState.getByteArray("VpnProfile")); 80310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if (profile != null) { 81310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mDialog = new VpnDialog(getActivity(), this, profile, 82310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh savedState.getBoolean("VpnEditing")); 83310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 84310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 85310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 86310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 87310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh @Override 88310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh public void onSaveInstanceState(Bundle savedState) { 89310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh // We do not save view hierarchy, as they are just profiles. 90310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if (mDialog != null) { 91310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh VpnProfile profile = mDialog.getProfile(); 92310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh savedState.putString("VpnKey", profile.key); 93310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh savedState.putByteArray("VpnProfile", profile.encode()); 94310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh savedState.putBoolean("VpnEditing", mDialog.isEditing()); 95310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 96310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh // else? 97310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 98310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 99310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh @Override 100310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh public void onResume() { 101310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh super.onResume(); 102310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 103310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh // Check KeyStore here, so others do not need to deal with it. 104310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if (mKeyStore.state() != KeyStore.State.UNLOCKED) { 105310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if (!mUnlocking) { 106310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh // Let us unlock KeyStore. See you later! 107310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh Credentials.getInstance().unlock(getActivity()); 108310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } else { 109310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh // We already tried, but it is still not working! 110d68dbe29bb0a6639bfd95449eb28e7d4b174a3feChia-chi Yeh finishFragment(); 111310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 112310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mUnlocking = !mUnlocking; 113310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh return; 114310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 115310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 116310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh // Now KeyStore is always unlocked. Reset the flag. 117310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mUnlocking = false; 118310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 119310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh // Currently we are the only user of profiles in KeyStore. 120310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh // Assuming KeyStore and KeyGuard do the right thing, we can 121310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh // safely cache profiles in the memory. 122310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if (mPreferences == null) { 123310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mPreferences = new HashMap<String, VpnPreference>(); 124d501b5c963c0cbcc9c666f502229599464eaf3fdChia-chi Yeh PreferenceGroup group = getPreferenceScreen(); 125310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 126310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh String[] keys = mKeyStore.saw(Credentials.VPN); 127310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if (keys != null && keys.length > 0) { 128310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh Context context = getActivity(); 129310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 130310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh for (String key : keys) { 131310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh VpnProfile profile = VpnProfile.decode(key, 132310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mKeyStore.get(Credentials.VPN + key)); 133310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if (profile == null) { 134310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh Log.w(TAG, "bad profile: key = " + key); 135310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mKeyStore.delete(Credentials.VPN + key); 136310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } else { 137310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh VpnPreference preference = new VpnPreference(context, profile); 138310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mPreferences.put(key, preference); 139d501b5c963c0cbcc9c666f502229599464eaf3fdChia-chi Yeh group.addPreference(preference); 140310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 141310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 142310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 143d501b5c963c0cbcc9c666f502229599464eaf3fdChia-chi Yeh group.findPreference("add_network").setOnPreferenceClickListener(this); 144310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 145310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 146310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh // Show the dialog if there is one. 147310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if (mDialog != null) { 148310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mDialog.setOnDismissListener(this); 149310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mDialog.show(); 150310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 151310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 152310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh // Start monitoring. 153bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh if (mUpdater == null) { 154bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh mUpdater = new Handler(this); 155310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 156bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh mUpdater.sendEmptyMessage(0); 157310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 158310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh // Register for context menu. Hmmm, getListView() is hidden? 159310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh registerForContextMenu(getListView()); 160310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 161310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 162310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh @Override 163310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh public void onPause() { 164310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh super.onPause(); 165310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 166310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh // Hide the dialog if there is one. 167310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if (mDialog != null) { 168310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mDialog.setOnDismissListener(null); 169310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mDialog.dismiss(); 170310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 171310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 172310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh // Unregister for context menu. 1736d4334be691815cd9615b0fdebb756999a9c06a3Chia-chi Yeh if (getView() != null) { 1746d4334be691815cd9615b0fdebb756999a9c06a3Chia-chi Yeh unregisterForContextMenu(getListView()); 1756d4334be691815cd9615b0fdebb756999a9c06a3Chia-chi Yeh } 176310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 177310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 178310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh @Override 179310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh public void onDismiss(DialogInterface dialog) { 180310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh // Here is the exit of a dialog. 181310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mDialog = null; 182310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 183310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 184310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh @Override 185310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh public void onClick(DialogInterface dialog, int button) { 186310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if (button == DialogInterface.BUTTON_POSITIVE) { 187310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh // Always save the profile. 188310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh VpnProfile profile = mDialog.getProfile(); 189310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mKeyStore.put(Credentials.VPN + profile.key, profile.encode()); 190310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 191310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh // Update the preference. 192310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh VpnPreference preference = mPreferences.get(profile.key); 193310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if (preference != null) { 194310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh disconnect(profile.key); 195310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh preference.update(profile); 196310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } else { 197310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh preference = new VpnPreference(getActivity(), profile); 198310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mPreferences.put(profile.key, preference); 199310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh getPreferenceScreen().addPreference(preference); 200310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 201310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 202310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh // If we are not editing, connect! 203310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if (!mDialog.isEditing()) { 204413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh try { 205413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh connect(profile); 206413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh } catch (Exception e) { 207413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh Log.e(TAG, "connect", e); 208413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh } 209310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 210310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 211310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 212310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 213310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh @Override 214310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo info) { 215310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if (mDialog != null) { 216310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh Log.v(TAG, "onCreateContextMenu() is called when mDialog != null"); 217310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh return; 218310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 219310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 220310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if (info instanceof AdapterContextMenuInfo) { 221310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh Preference preference = (Preference) getListView().getItemAtPosition( 222310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh ((AdapterContextMenuInfo) info).position); 223310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if (preference instanceof VpnPreference) { 224310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh VpnProfile profile = ((VpnPreference) preference).getProfile(); 225310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mSelectedKey = profile.key; 226310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh menu.setHeaderTitle(profile.name); 227310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh menu.add(Menu.NONE, R.string.vpn_menu_edit, 0, R.string.vpn_menu_edit); 228310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh menu.add(Menu.NONE, R.string.vpn_menu_delete, 0, R.string.vpn_menu_delete); 229310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 230310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 231310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 232310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 233310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh @Override 234310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh public boolean onContextItemSelected(MenuItem item) { 235310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if (mDialog != null) { 236310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh Log.v(TAG, "onContextItemSelected() is called when mDialog != null"); 237310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh return false; 238310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 239310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 240310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh VpnPreference preference = mPreferences.get(mSelectedKey); 241310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if (preference == null) { 242310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh Log.v(TAG, "onContextItemSelected() is called but no preference is found"); 243310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh return false; 244310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 245310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 246310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh switch (item.getItemId()) { 247310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh case R.string.vpn_menu_edit: 248310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mDialog = new VpnDialog(getActivity(), this, preference.getProfile(), true); 249310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mDialog.setOnDismissListener(this); 250310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mDialog.show(); 251310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh return true; 252310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh case R.string.vpn_menu_delete: 253310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh disconnect(mSelectedKey); 254310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh getPreferenceScreen().removePreference(preference); 255310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mPreferences.remove(mSelectedKey); 256310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mKeyStore.delete(Credentials.VPN + mSelectedKey); 257310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh return true; 258310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 259310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh return false; 260310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 261310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 262310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh @Override 263310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh public boolean onPreferenceClick(Preference preference) { 264310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if (mDialog != null) { 265310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh Log.v(TAG, "onPreferenceClick() is called when mDialog != null"); 266310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh return true; 267310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 268310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 269310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if (preference instanceof VpnPreference) { 27097fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh VpnProfile profile = ((VpnPreference) preference).getProfile(); 27197fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh if (mInfo != null && profile.key.equals(mInfo.key) && 27297fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh mInfo.state == LegacyVpnInfo.STATE_CONNECTED) { 27397fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh try { 27497fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh mInfo.intent.send(); 27597fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh return true; 27697fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh } catch (Exception e) { 27797fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh // ignore 27897fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh } 27997fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh } 28097fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh mDialog = new VpnDialog(getActivity(), this, profile, false); 281310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } else { 282310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh // Generate a new key. Here we just use the current time. 283310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh long millis = System.currentTimeMillis(); 284310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh while (mPreferences.containsKey(Long.toHexString(millis))) { 285310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh ++millis; 286310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 287310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mDialog = new VpnDialog(getActivity(), this, 288310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh new VpnProfile(Long.toHexString(millis)), true); 289310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 290310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mDialog.setOnDismissListener(this); 291310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mDialog.show(); 292310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh return true; 293310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 294310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 295310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh @Override 296310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh public boolean handleMessage(Message message) { 297bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh mUpdater.removeMessages(0); 298310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 299310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if (isResumed()) { 30097fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh try { 30197fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh LegacyVpnInfo info = mService.getLegacyVpnInfo(); 30297fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh if (mInfo != null) { 30397fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh VpnPreference preference = mPreferences.get(mInfo.key); 30497fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh if (preference != null) { 30597fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh preference.update(-1); 30697fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh } 30797fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh mInfo = null; 30897fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh } 30997fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh if (info != null) { 31097fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh VpnPreference preference = mPreferences.get(info.key); 31197fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh if (preference != null) { 31297fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh preference.update(info.state); 31397fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh mInfo = info; 31497fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh } 31597fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh } 31697fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh } catch (Exception e) { 31797fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh // ignore 31897fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh } 319bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh mUpdater.sendEmptyMessageDelayed(0, 1000); 320310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 321310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh return true; 322310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 323310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 324f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh private String[] getDefaultNetwork() throws Exception { 325413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh LinkProperties network = mService.getActiveLinkProperties(); 326f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh if (network == null) { 327f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh throw new IllegalStateException("Network is not available"); 328f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh } 329f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh String interfaze = network.getInterfaceName(); 330413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh if (interfaze == null) { 331f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh throw new IllegalStateException("Cannot get the default interface"); 332f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh } 333f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh String gateway = null; 334f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh for (RouteInfo route : network.getRoutes()) { 335f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh // Currently legacy VPN only works on IPv4. 336f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh if (route.isDefaultRoute() && route.getGateway() instanceof Inet4Address) { 337f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh gateway = route.getGateway().getHostAddress(); 338f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh break; 339f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh } 340f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh } 341f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh if (gateway == null) { 342f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh throw new IllegalStateException("Cannot get the default gateway"); 343413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh } 344f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh return new String[] {interfaze, gateway}; 345f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh } 346f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh 347f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh private void connect(VpnProfile profile) throws Exception { 348f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh // Get the default interface and the default gateway. 349f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh String[] network = getDefaultNetwork(); 350f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh String interfaze = network[0]; 351f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh String gateway = network[1]; 352413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh 353413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh // Load certificates. 354413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh String privateKey = ""; 355413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh String userCert = ""; 356413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh String caCert = ""; 357f5317a151bef8d93f7a640fe46c6dcde6baa258dChia-chi Yeh String serverCert = ""; 358413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh if (!profile.ipsecUserCert.isEmpty()) { 359413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh byte[] value = mKeyStore.get(Credentials.USER_PRIVATE_KEY + profile.ipsecUserCert); 360413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh privateKey = (value == null) ? null : new String(value, Charsets.UTF_8); 361413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh value = mKeyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecUserCert); 362413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh userCert = (value == null) ? null : new String(value, Charsets.UTF_8); 363413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh } 364413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh if (!profile.ipsecCaCert.isEmpty()) { 365413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh byte[] value = mKeyStore.get(Credentials.CA_CERTIFICATE + profile.ipsecCaCert); 366413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh caCert = (value == null) ? null : new String(value, Charsets.UTF_8); 367413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh } 368f5317a151bef8d93f7a640fe46c6dcde6baa258dChia-chi Yeh if (!profile.ipsecServerCert.isEmpty()) { 369f5317a151bef8d93f7a640fe46c6dcde6baa258dChia-chi Yeh byte[] value = mKeyStore.get(Credentials.USER_CERTIFICATE + profile.ipsecServerCert); 370f5317a151bef8d93f7a640fe46c6dcde6baa258dChia-chi Yeh serverCert = (value == null) ? null : new String(value, Charsets.UTF_8); 371f5317a151bef8d93f7a640fe46c6dcde6baa258dChia-chi Yeh } 372f5317a151bef8d93f7a640fe46c6dcde6baa258dChia-chi Yeh if (privateKey == null || userCert == null || caCert == null || serverCert == null) { 373413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh // TODO: find out a proper way to handle this. Delete these keys? 374413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh throw new IllegalStateException("Cannot load credentials"); 375413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh } 376413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh 377413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh // Prepare arguments for racoon. 378bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh String[] racoon = null; 379bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh switch (profile.type) { 380bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh case VpnProfile.TYPE_L2TP_IPSEC_PSK: 381bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh racoon = new String[] { 3826d4334be691815cd9615b0fdebb756999a9c06a3Chia-chi Yeh interfaze, profile.server, "udppsk", profile.ipsecIdentifier, 3836d4334be691815cd9615b0fdebb756999a9c06a3Chia-chi Yeh profile.ipsecSecret, "1701", 384bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh }; 385bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh break; 386bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh case VpnProfile.TYPE_L2TP_IPSEC_RSA: 387bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh racoon = new String[] { 388f5317a151bef8d93f7a640fe46c6dcde6baa258dChia-chi Yeh interfaze, profile.server, "udprsa", privateKey, userCert, 389f5317a151bef8d93f7a640fe46c6dcde6baa258dChia-chi Yeh caCert, serverCert, "1701", 390bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh }; 391bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh break; 392bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh case VpnProfile.TYPE_IPSEC_XAUTH_PSK: 393f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh racoon = new String[] { 394f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh interfaze, profile.server, "xauthpsk", profile.ipsecIdentifier, 3956d4334be691815cd9615b0fdebb756999a9c06a3Chia-chi Yeh profile.ipsecSecret, profile.username, profile.password, "", gateway, 396f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh }; 397bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh break; 398bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh case VpnProfile.TYPE_IPSEC_XAUTH_RSA: 399f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh racoon = new String[] { 400f5317a151bef8d93f7a640fe46c6dcde6baa258dChia-chi Yeh interfaze, profile.server, "xauthrsa", privateKey, userCert, 401f5317a151bef8d93f7a640fe46c6dcde6baa258dChia-chi Yeh caCert, serverCert, profile.username, profile.password, "", gateway, 402f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh }; 403bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh break; 404bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh case VpnProfile.TYPE_IPSEC_HYBRID_RSA: 405f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh racoon = new String[] { 406f5317a151bef8d93f7a640fe46c6dcde6baa258dChia-chi Yeh interfaze, profile.server, "hybridrsa", 407f5317a151bef8d93f7a640fe46c6dcde6baa258dChia-chi Yeh caCert, serverCert, profile.username, profile.password, "", gateway, 408f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh }; 409bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh break; 410bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh } 411bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh 412413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh // Prepare arguments for mtpd. 413bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh String[] mtpd = null; 414bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh switch (profile.type) { 415bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh case VpnProfile.TYPE_PPTP: 416bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh mtpd = new String[] { 417f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh interfaze, "pptp", profile.server, "1723", 418bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh "name", profile.username, "password", profile.password, 419bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh "linkname", "vpn", "refuse-eap", "nodefaultroute", 420bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400", 421f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh (profile.mppe ? "+mppe" : "nomppe"), 422bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh }; 423bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh break; 424bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh case VpnProfile.TYPE_L2TP_IPSEC_PSK: 425bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh case VpnProfile.TYPE_L2TP_IPSEC_RSA: 426bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh mtpd = new String[] { 427f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh interfaze, "l2tp", profile.server, "1701", profile.l2tpSecret, 428bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh "name", profile.username, "password", profile.password, 429bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh "linkname", "vpn", "refuse-eap", "nodefaultroute", 430bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh "usepeerdns", "idle", "1800", "mtu", "1400", "mru", "1400", 431bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh }; 432bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh break; 433bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh } 434bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh 435d95ec871138ebb367cfd8b67b4814438ac30c628Chia-chi Yeh VpnConfig config = new VpnConfig(); 436d5a5de4de6df9ebd979c11bbd1e850f787b3ffeeChia-chi Yeh config.user = profile.key; 437f35130dd79c100097025585c0b5a5ebbd38a414eChia-chi Yeh config.interfaze = interfaze; 4385c9e37c295a0219731882eca7a8805a08a439c34Chia-chi Yeh config.session = profile.name; 439d95ec871138ebb367cfd8b67b4814438ac30c628Chia-chi Yeh config.routes = profile.routes; 440d68dbe29bb0a6639bfd95449eb28e7d4b174a3feChia-chi Yeh if (!profile.dnsServers.isEmpty()) { 441d68dbe29bb0a6639bfd95449eb28e7d4b174a3feChia-chi Yeh config.dnsServers = Arrays.asList(profile.dnsServers.split(" +")); 442d68dbe29bb0a6639bfd95449eb28e7d4b174a3feChia-chi Yeh } 443d95ec871138ebb367cfd8b67b4814438ac30c628Chia-chi Yeh if (!profile.searchDomains.isEmpty()) { 444d68dbe29bb0a6639bfd95449eb28e7d4b174a3feChia-chi Yeh config.searchDomains = Arrays.asList(profile.searchDomains.split(" +")); 445d95ec871138ebb367cfd8b67b4814438ac30c628Chia-chi Yeh } 446d95ec871138ebb367cfd8b67b4814438ac30c628Chia-chi Yeh 447413b171159cec5ad1e7b3cf4f1f842b5f2debc05Chia-chi Yeh mService.startLegacyVpn(config, racoon, mtpd); 448310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 449310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 450310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh private void disconnect(String key) { 45197fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh if (mInfo != null && key.equals(mInfo.key)) { 45297fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh try { 45397fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh mService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN); 45497fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh } catch (Exception e) { 45597fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh // ignore 45697fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh } 45797fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh } 458310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 459310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 460310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh private class VpnPreference extends Preference { 461310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh private VpnProfile mProfile; 46297fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh private int mState = -1; 463310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 464310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh VpnPreference(Context context, VpnProfile profile) { 465310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh super(context); 466310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh setPersistent(false); 46797fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh setOrder(0); 468310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh setOnPreferenceClickListener(VpnSettings.this); 469310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 470310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mProfile = profile; 471310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh update(); 472310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 473310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 474310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh VpnProfile getProfile() { 475310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh return mProfile; 476310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 477310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 478310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh void update(VpnProfile profile) { 479310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh mProfile = profile; 480310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh update(); 481310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 482310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 48397fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh void update(int state) { 48497fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh mState = state; 48597fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh update(); 48697fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh } 48797fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh 488310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh void update() { 48997fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh if (mState < 0) { 490310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh String[] types = getContext().getResources() 491310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh .getStringArray(R.array.vpn_types_long); 492310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh setSummary(types[mProfile.type]); 49397fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh } else { 49497fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh String[] states = getContext().getResources() 49597fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh .getStringArray(R.array.vpn_states); 49697fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh setSummary(states[mState]); 497310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 498310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh setTitle(mProfile.name); 49997fd85fd9776f3fb5c35217e82bcbcb5aea8416dChia-chi Yeh notifyHierarchyChanged(); 500310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 501310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh 502310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh @Override 503310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh public int compareTo(Preference preference) { 504bbb5094be6673929bcb808cdeaf748a73be4dbf0Chia-chi Yeh int result = -1; 505310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if (preference instanceof VpnPreference) { 506310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh VpnPreference another = (VpnPreference) preference; 507310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh if ((result = another.mState - mState) == 0 && 508310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh (result = mProfile.name.compareTo(another.mProfile.name)) == 0 && 509310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh (result = mProfile.type - another.mProfile.type) == 0) { 510310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh result = mProfile.key.compareTo(another.mProfile.key); 511310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 512310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 513310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh return result; 514310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 515310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh } 516310d619acba5cd1f7c8a55aa7906ed4f1c011bd8Chia-chi Yeh} 517