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