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