12bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee/* 22bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee * Copyright (C) 2015 The Android Open Source Project 32bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee * 42bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee * Licensed under the Apache License, Version 2.0 (the "License"); 52bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee * you may not use this file except in compliance with the License. 62bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee * You may obtain a copy of the License at 72bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee * 82bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee * http://www.apache.org/licenses/LICENSE-2.0 92bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee * 102bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee * Unless required by applicable law or agreed to in writing, software 112bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee * distributed under the License is distributed on an "AS IS" BASIS, 122bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee * See the License for the specific language governing permissions and 142bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee * limitations under the License. 152bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee */ 162bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 172bd92d5d0685144aad566b9d29454fb519ff0371Robin Leepackage com.android.settings.vpn2; 182bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 192bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.app.AlertDialog; 202bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.app.Dialog; 212bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.app.DialogFragment; 222bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.content.Context; 232bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.content.DialogInterface; 242bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.content.res.Resources; 252bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.net.ConnectivityManager; 262bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.os.Bundle; 272bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.security.Credentials; 282bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.security.KeyStore; 292bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.text.TextUtils; 302bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.view.LayoutInflater; 312bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.view.View; 322bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.widget.ArrayAdapter; 332bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.widget.ListView; 342bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport android.widget.Toast; 352bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 362bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport com.android.internal.net.VpnProfile; 372bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport com.android.settings.R; 382bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport com.google.android.collect.Lists; 392bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 402bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport java.util.ArrayList; 412bd92d5d0685144aad566b9d29454fb519ff0371Robin Leeimport java.util.List; 422bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 432bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee/** 442bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee * Dialog to configure always-on VPN. 452bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee */ 462bd92d5d0685144aad566b9d29454fb519ff0371Robin Leepublic class LockdownConfigFragment extends DialogFragment { 472bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee private List<VpnProfile> mProfiles; 482bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee private List<CharSequence> mTitles; 492bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee private int mCurrentIndex; 502bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 512bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee private static final String TAG_LOCKDOWN = "lockdown"; 522bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 532bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee private static class TitleAdapter extends ArrayAdapter<CharSequence> { 542bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee public TitleAdapter(Context context, List<CharSequence> objects) { 552bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee super(context, com.android.internal.R.layout.select_dialog_singlechoice_material, 562bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee android.R.id.text1, objects); 572bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } 582bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } 592bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 602bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee public static void show(VpnSettings parent) { 612bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee if (!parent.isAdded()) return; 622bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 632bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee final LockdownConfigFragment dialog = new LockdownConfigFragment(); 642bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee dialog.show(parent.getFragmentManager(), TAG_LOCKDOWN); 652bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } 662bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 672bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee private static String getStringOrNull(KeyStore keyStore, String key) { 682bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee if (!keyStore.isUnlocked()) { 692bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee return null; 702bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } 712bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee final byte[] value = keyStore.get(key); 722bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee return value == null ? null : new String(value); 732bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } 742bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 752bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee private void initProfiles(KeyStore keyStore, Resources res) { 762bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee final String lockdownKey = getStringOrNull(keyStore, Credentials.LOCKDOWN_VPN); 772bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 782bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee mProfiles = VpnSettings.loadVpnProfiles(keyStore, VpnProfile.TYPE_PPTP); 792bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee mTitles = new ArrayList<>(1 + mProfiles.size()); 802bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee mTitles.add(res.getText(R.string.vpn_lockdown_none)); 812bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 822bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee mCurrentIndex = 0; 832bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee for (VpnProfile profile : mProfiles) { 842bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee if (TextUtils.equals(profile.key, lockdownKey)) { 852bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee mCurrentIndex = mTitles.size(); 862bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } 872bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee mTitles.add(profile.name); 882bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } 892bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } 902bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 912bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee @Override 922bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee public Dialog onCreateDialog(Bundle savedInstanceState) { 932bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee final Context context = getActivity(); 942bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee final KeyStore keyStore = KeyStore.getInstance(); 952bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 962bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee initProfiles(keyStore, context.getResources()); 972bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 982bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee final AlertDialog.Builder builder = new AlertDialog.Builder(context); 992bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee final LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext()); 1002bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 1012bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee builder.setTitle(R.string.vpn_menu_lockdown); 1022bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 1032bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee final View view = dialogInflater.inflate(R.layout.vpn_lockdown_editor, null, false); 1042bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee final ListView listView = (ListView) view.findViewById(android.R.id.list); 1052bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); 1062bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee listView.setAdapter(new TitleAdapter(context, mTitles)); 1072bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee listView.setItemChecked(mCurrentIndex, true); 1082bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee builder.setView(view); 1092bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 1102bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { 1112bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee @Override 1122bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee public void onClick(DialogInterface dialog, int which) { 1132bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee final int newIndex = listView.getCheckedItemPosition(); 1142bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee if (mCurrentIndex == newIndex) return; 1152bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 1162bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee if (newIndex == 0) { 1172bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee keyStore.delete(Credentials.LOCKDOWN_VPN); 1182bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } else { 1192bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee final VpnProfile profile = mProfiles.get(newIndex - 1); 1202bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee if (!profile.isValidLockdownProfile()) { 1212bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee Toast.makeText(context, R.string.vpn_lockdown_config_error, 1222bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee Toast.LENGTH_LONG).show(); 1232bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee return; 1242bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } 1252bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee keyStore.put(Credentials.LOCKDOWN_VPN, profile.key.getBytes(), 1262bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED); 1272bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } 1282bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 1292bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee // kick profiles since we changed them 1302bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee ConnectivityManager.from(getActivity()).updateLockdownVpn(); 1312bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } 1322bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee }); 1332bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 1342bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee return builder.create(); 1352bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee } 1362bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee} 1372bd92d5d0685144aad566b9d29454fb519ff0371Robin Lee 138