1f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom/* 2f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom * Copyright (C) 2011 The Android Open Source Project 3f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom * 4f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License"); 5f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom * you may not use this file except in compliance with the License. 6f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom * You may obtain a copy of the License at 7f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom * 8f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom * http://www.apache.org/licenses/LICENSE-2.0 9f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom * 10f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom * Unless required by applicable law or agreed to in writing, software 11f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS, 12f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom * See the License for the specific language governing permissions and 14f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom * limitations under the License. 15f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom */ 16f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 17f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrompackage com.android.settings; 18f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 19f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport android.app.AlertDialog; 20f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport android.app.Dialog; 21f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport android.app.Fragment; 22f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport android.content.DialogInterface; 23f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport android.net.http.SslCertificate; 24f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport android.os.AsyncTask; 25f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport android.os.Bundle; 26f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport android.os.RemoteException; 27f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport android.security.IKeyChainService; 28f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport android.security.KeyChain; 29f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport android.security.KeyChain.KeyChainConnection; 30f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport android.view.LayoutInflater; 31f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport android.view.View; 32f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport android.view.ViewGroup; 33f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport android.widget.AdapterView; 34f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport android.widget.BaseAdapter; 35f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport android.widget.Button; 36f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport android.widget.CheckBox; 37f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport android.widget.FrameLayout; 38f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport android.widget.ListView; 39729c6d99e21856558f3631d31537b8dca6bb2314Brian Carlstromimport android.widget.ProgressBar; 40f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport android.widget.TabHost; 41f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport android.widget.TextView; 42f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport java.security.cert.CertificateEncodingException; 43f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport java.security.cert.X509Certificate; 44f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport java.util.ArrayList; 45f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport java.util.Collections; 46f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport java.util.List; 47f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport java.util.Set; 48f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstromimport org.apache.harmony.xnet.provider.jsse.TrustedCertificateStore; 49f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 50ac45fb42b00f377e58f8dfd59e4807a3147cfb57Brian Carlstrompublic class TrustedCredentialsSettings extends Fragment { 51f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 52ac45fb42b00f377e58f8dfd59e4807a3147cfb57Brian Carlstrom private static final String TAG = "TrustedCredentialsSettings"; 53f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 54f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private enum Tab { 55f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom SYSTEM("system", 56f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom R.string.trusted_credentials_system_tab, 57f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom R.id.system_tab, 58f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom R.id.system_progress, 59f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom R.id.system_list, 60f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom true), 61f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom USER("user", 62f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom R.string.trusted_credentials_user_tab, 63f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom R.id.user_tab, 64f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom R.id.user_progress, 65f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom R.id.user_list, 66f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom false); 67f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 68f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private final String mTag; 69f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private final int mLabel; 70f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private final int mView; 71f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private final int mProgress; 72f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private final int mList; 73f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private final boolean mCheckbox; 74f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private Tab(String tag, int label, int view, int progress, int list, boolean checkbox) { 75f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom mTag = tag; 76f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom mLabel = label; 77f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom mView = view; 78f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom mProgress = progress; 79f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom mList = list; 80f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom mCheckbox = checkbox; 81f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 82f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private Set<String> getAliases(TrustedCertificateStore store) { 83f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom switch (this) { 84f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom case SYSTEM: 85f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return store.allSystemAliases(); 86f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom case USER: 87f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return store.userAliases(); 88f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 89f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom throw new AssertionError(); 90f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 91f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private boolean deleted(TrustedCertificateStore store, String alias) { 92f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom switch (this) { 93f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom case SYSTEM: 94f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return !store.containsAlias(alias); 95f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom case USER: 96f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return false; 97f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 98f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom throw new AssertionError(); 99f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 100f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private int getButtonLabel(CertHolder certHolder) { 101f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom switch (this) { 102f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom case SYSTEM: 103f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom if (certHolder.mDeleted) { 104f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return R.string.trusted_credentials_enable_label; 105f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 106f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return R.string.trusted_credentials_disable_label; 107f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom case USER: 108f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return R.string.trusted_credentials_remove_label; 109f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 110f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom throw new AssertionError(); 111f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 112f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private int getButtonConfirmation(CertHolder certHolder) { 113f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom switch (this) { 114f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom case SYSTEM: 115f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom if (certHolder.mDeleted) { 116f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return R.string.trusted_credentials_enable_confirmation; 117f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 118f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return R.string.trusted_credentials_disable_confirmation; 119f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom case USER: 120f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return R.string.trusted_credentials_remove_confirmation; 121f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 122f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom throw new AssertionError(); 123f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 124f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private void postOperationUpdate(boolean ok, CertHolder certHolder) { 125f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom if (ok) { 126f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom if (certHolder.mTab.mCheckbox) { 127f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom certHolder.mDeleted = !certHolder.mDeleted; 128f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } else { 129f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom certHolder.mAdapter.mCertHolders.remove(certHolder); 130f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 131f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom certHolder.mAdapter.notifyDataSetChanged(); 132f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } else { 133f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom // bail, reload to reset to known state 134f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom certHolder.mAdapter.load(); 135f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 136f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 137f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 138f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 139f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom // be careful not to use this on the UI thread since it is does file operations 140f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private final TrustedCertificateStore mStore = new TrustedCertificateStore(); 141f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 142f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private TabHost mTabHost; 143f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 144f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom @Override public View onCreateView( 145f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) { 146f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom mTabHost = (TabHost) inflater.inflate(R.layout.trusted_credentials, parent, false); 147f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom mTabHost.setup(); 148f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom addTab(Tab.SYSTEM); 149f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom // TODO add Install button on Tab.USER to go to CertInstaller like KeyChainActivity 150f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom addTab(Tab.USER); 151f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return mTabHost; 152f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 153f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 154f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private void addTab(Tab tab) { 155f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom TabHost.TabSpec systemSpec = mTabHost.newTabSpec(tab.mTag) 156f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom .setIndicator(getActivity().getString(tab.mLabel)) 157f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom .setContent(tab.mView); 158f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom mTabHost.addTab(systemSpec); 159f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 160f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom ListView lv = (ListView) mTabHost.findViewById(tab.mList); 161f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom final TrustedCertificateAdapter adapter = new TrustedCertificateAdapter(tab); 162f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom lv.setAdapter(adapter); 163f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { 164f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom @Override public void onItemClick(AdapterView<?> parent, View view, int pos, long id) { 165f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom showCertDialog(adapter.getItem(pos)); 166f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 167f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom }); 168f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 169f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 170f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private class TrustedCertificateAdapter extends BaseAdapter { 171f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private final List<CertHolder> mCertHolders = new ArrayList<CertHolder>(); 172f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private final Tab mTab; 173f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private TrustedCertificateAdapter(Tab tab) { 174f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom mTab = tab; 175f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom load(); 176f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 177f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private void load() { 178f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom new AliasLoader().execute(); 179f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 180f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom @Override public int getCount() { 181f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return mCertHolders.size(); 182f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 183f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom @Override public CertHolder getItem(int position) { 184f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return mCertHolders.get(position); 185f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 186f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom @Override public long getItemId(int position) { 187f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return position; 188f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 189f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom @Override public View getView(int position, View view, ViewGroup parent) { 190f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom ViewHolder holder; 191f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom if (view == null) { 192f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom LayoutInflater inflater = LayoutInflater.from(getActivity()); 193f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom view = inflater.inflate(R.layout.trusted_credential, parent, false); 194f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom holder = new ViewHolder(); 19510cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom holder.mSubjectPrimaryView = (TextView) 19610cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom view.findViewById(R.id.trusted_credential_subject_primary); 19710cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom holder.mSubjectSecondaryView = (TextView) 19810cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom view.findViewById(R.id.trusted_credential_subject_secondary); 199f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom holder.mCheckBox = (CheckBox) view.findViewById(R.id.trusted_credential_status); 200f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom view.setTag(holder); 201f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } else { 202f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom holder = (ViewHolder) view.getTag(); 203f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 204f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom CertHolder certHolder = mCertHolders.get(position); 20510cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom holder.mSubjectPrimaryView.setText(certHolder.mSubjectPrimary); 20610cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom holder.mSubjectSecondaryView.setText(certHolder.mSubjectSecondary); 207f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom if (mTab.mCheckbox) { 208f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom holder.mCheckBox.setChecked(!certHolder.mDeleted); 209f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom holder.mCheckBox.setVisibility(View.VISIBLE); 210f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 211f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return view; 212f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom }; 213f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 214729c6d99e21856558f3631d31537b8dca6bb2314Brian Carlstrom private class AliasLoader extends AsyncTask<Void, Integer, List<CertHolder>> { 215729c6d99e21856558f3631d31537b8dca6bb2314Brian Carlstrom ProgressBar mProgressBar; 216729c6d99e21856558f3631d31537b8dca6bb2314Brian Carlstrom View mList; 217f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom @Override protected void onPreExecute() { 218f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom View content = mTabHost.getTabContentView(); 219729c6d99e21856558f3631d31537b8dca6bb2314Brian Carlstrom mProgressBar = (ProgressBar) content.findViewById(mTab.mProgress); 220729c6d99e21856558f3631d31537b8dca6bb2314Brian Carlstrom mList = content.findViewById(mTab.mList); 221729c6d99e21856558f3631d31537b8dca6bb2314Brian Carlstrom mProgressBar.setVisibility(View.VISIBLE); 222729c6d99e21856558f3631d31537b8dca6bb2314Brian Carlstrom mList.setVisibility(View.GONE); 223f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 224f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom @Override protected List<CertHolder> doInBackground(Void... params) { 225f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom Set<String> aliases = mTab.getAliases(mStore); 226729c6d99e21856558f3631d31537b8dca6bb2314Brian Carlstrom int max = aliases.size(); 227729c6d99e21856558f3631d31537b8dca6bb2314Brian Carlstrom int progress = 0; 228729c6d99e21856558f3631d31537b8dca6bb2314Brian Carlstrom List<CertHolder> certHolders = new ArrayList<CertHolder>(max); 229f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom for (String alias : aliases) { 230f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom X509Certificate cert = (X509Certificate) mStore.getCertificate(alias, true); 231f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom certHolders.add(new CertHolder(mStore, 232f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom TrustedCertificateAdapter.this, 233f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom mTab, 234f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom alias, 235f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom cert)); 236729c6d99e21856558f3631d31537b8dca6bb2314Brian Carlstrom publishProgress(++progress, max); 237f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 238f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom Collections.sort(certHolders); 239f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return certHolders; 240f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 241729c6d99e21856558f3631d31537b8dca6bb2314Brian Carlstrom @Override protected void onProgressUpdate(Integer... progressAndMax) { 242729c6d99e21856558f3631d31537b8dca6bb2314Brian Carlstrom int progress = progressAndMax[0]; 243729c6d99e21856558f3631d31537b8dca6bb2314Brian Carlstrom int max = progressAndMax[1]; 244729c6d99e21856558f3631d31537b8dca6bb2314Brian Carlstrom if (max != mProgressBar.getMax()) { 245729c6d99e21856558f3631d31537b8dca6bb2314Brian Carlstrom mProgressBar.setMax(max); 246729c6d99e21856558f3631d31537b8dca6bb2314Brian Carlstrom } 247729c6d99e21856558f3631d31537b8dca6bb2314Brian Carlstrom mProgressBar.setProgress(progress); 248729c6d99e21856558f3631d31537b8dca6bb2314Brian Carlstrom } 249f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom @Override protected void onPostExecute(List<CertHolder> certHolders) { 250f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom mCertHolders.clear(); 251f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom mCertHolders.addAll(certHolders); 252f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom notifyDataSetChanged(); 253f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom View content = mTabHost.getTabContentView(); 254945e383833c77101eb415b28bad4d1c6dfe85485Brian Carlstrom mProgressBar.setVisibility(View.GONE); 255945e383833c77101eb415b28bad4d1c6dfe85485Brian Carlstrom mList.setVisibility(View.VISIBLE); 256945e383833c77101eb415b28bad4d1c6dfe85485Brian Carlstrom mProgressBar.setProgress(0); 257f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 258f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 259f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 260f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 261f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private static class CertHolder implements Comparable<CertHolder> { 262f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private final TrustedCertificateStore mStore; 263f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private final TrustedCertificateAdapter mAdapter; 264f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private final Tab mTab; 265f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private final String mAlias; 266f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private final X509Certificate mX509Cert; 267f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 268f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private final SslCertificate mSslCert; 26910cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom private final String mSubjectPrimary; 27010cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom private final String mSubjectSecondary; 271f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private boolean mDeleted; 272f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 273f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private CertHolder(TrustedCertificateStore store, 274f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom TrustedCertificateAdapter adapter, 275f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom Tab tab, 276f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom String alias, 277f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom X509Certificate x509Cert) { 278f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom mStore = store; 279f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom mAdapter = adapter; 280f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom mTab = tab; 281f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom mAlias = alias; 282f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom mX509Cert = x509Cert; 283f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 284f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom mSslCert = new SslCertificate(x509Cert); 285f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 286f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom String cn = mSslCert.getIssuedTo().getCName(); 287f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom String o = mSslCert.getIssuedTo().getOName(); 288f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom String ou = mSslCert.getIssuedTo().getUName(); 28910cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom // if we have a O, use O as primary subject, secondary prefer CN over OU 29010cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom // if we don't have an O, use CN as primary, empty secondary 29110cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom // if we don't have O or CN, use DName as primary, empty secondary 292f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom if (!o.isEmpty()) { 29310cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom if (!cn.isEmpty()) { 29410cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom mSubjectPrimary = o; 29510cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom mSubjectSecondary = cn; 29610cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom } else { 29710cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom mSubjectPrimary = o; 29810cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom mSubjectSecondary = ou; 299f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 300f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } else { 30110cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom if (!cn.isEmpty()) { 30210cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom mSubjectPrimary = cn; 30310cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom mSubjectSecondary = ""; 30410cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom } else { 30510cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom mSubjectPrimary = mSslCert.getIssuedTo().getDName(); 30610cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom mSubjectSecondary = ""; 30710cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom } 308f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 309f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom mDeleted = mTab.deleted(mStore, mAlias); 310f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 311f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom @Override public int compareTo(CertHolder o) { 31210cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom int primary = this.mSubjectPrimary.compareToIgnoreCase(o.mSubjectPrimary); 31310cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom if (primary != 0) { 31410cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom return primary; 31510cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom } 31610cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom return this.mSubjectSecondary.compareToIgnoreCase(o.mSubjectSecondary); 317f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 318f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom @Override public boolean equals(Object o) { 319f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom if (!(o instanceof CertHolder)) { 320f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return false; 321f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 322f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom CertHolder other = (CertHolder) o; 323f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return mAlias.equals(other.mAlias); 324f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 325f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom @Override public int hashCode() { 326f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return mAlias.hashCode(); 327f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 328f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 329f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 330f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private static class ViewHolder { 33110cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom private TextView mSubjectPrimaryView; 33210cc989346e1beda02a0dc5e0ca257734bbd21fcBrian Carlstrom private TextView mSubjectSecondaryView; 333f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private CheckBox mCheckBox; 334f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 335f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 336f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private void showCertDialog(final CertHolder certHolder) { 33791615cfa9ead46769ad3adc624b3bacb4906e4b2Brian Carlstrom View view = certHolder.mSslCert.inflateCertificateView(getActivity()); 338f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 339f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom builder.setTitle(com.android.internal.R.string.ssl_certificate); 340f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom builder.setView(view); 341f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { 342f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom @Override public void onClick(DialogInterface dialog, int id) { 343f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom dialog.dismiss(); 344f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 345f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom }); 346f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom final Dialog certDialog = builder.create(); 347f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 34891615cfa9ead46769ad3adc624b3bacb4906e4b2Brian Carlstrom ViewGroup body = (ViewGroup) view.findViewById(com.android.internal.R.id.body); 34991615cfa9ead46769ad3adc624b3bacb4906e4b2Brian Carlstrom LayoutInflater inflater = LayoutInflater.from(getActivity()); 35091615cfa9ead46769ad3adc624b3bacb4906e4b2Brian Carlstrom Button removeButton = (Button) inflater.inflate(R.layout.trusted_credential_details, 35191615cfa9ead46769ad3adc624b3bacb4906e4b2Brian Carlstrom body, 35291615cfa9ead46769ad3adc624b3bacb4906e4b2Brian Carlstrom false); 35391615cfa9ead46769ad3adc624b3bacb4906e4b2Brian Carlstrom body.addView(removeButton); 354f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom removeButton.setText(certHolder.mTab.getButtonLabel(certHolder)); 355f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom removeButton.setOnClickListener(new View.OnClickListener() { 356f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom @Override public void onClick(View v) { 357f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 358f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom builder.setMessage(certHolder.mTab.getButtonConfirmation(certHolder)); 359f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom builder.setPositiveButton( 360f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom android.R.string.yes, new DialogInterface.OnClickListener() { 361f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom @Override public void onClick(DialogInterface dialog, int id) { 362f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom new AliasOperation(certHolder).execute(); 363f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom dialog.dismiss(); 364f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom certDialog.dismiss(); 365f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 366f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom }); 367f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom builder.setNegativeButton( 368f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom android.R.string.no, new DialogInterface.OnClickListener() { 369f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom @Override public void onClick(DialogInterface dialog, int id) { 370f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom dialog.cancel(); 371f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 372f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom }); 373f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom AlertDialog alert = builder.create(); 374f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom alert.show(); 375f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 376f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom }); 377f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 378f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom certDialog.show(); 379f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 380f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom 381f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private class AliasOperation extends AsyncTask<Void, Void, Boolean> { 382f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private final CertHolder mCertHolder; 383f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom private AliasOperation(CertHolder certHolder) { 384f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom mCertHolder = certHolder; 385f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 386f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom @Override protected Boolean doInBackground(Void... params) { 387f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom try { 388f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom KeyChainConnection keyChainConnection = KeyChain.bind(getActivity()); 389f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom IKeyChainService service = keyChainConnection.getService(); 390f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom try { 391f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom if (mCertHolder.mDeleted) { 392f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom byte[] bytes = mCertHolder.mX509Cert.getEncoded(); 393f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom service.installCaCertificate(bytes); 394f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return true; 395f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } else { 396f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return service.deleteCaCertificate(mCertHolder.mAlias); 397f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 398f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } finally { 399f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom keyChainConnection.close(); 400f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 401f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } catch (CertificateEncodingException e) { 402f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return false; 403f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } catch (IllegalStateException e) { 404f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom // used by installCaCertificate to report errors 405f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return false; 406f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } catch (RemoteException e) { 407f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return false; 408f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } catch (InterruptedException e) { 409f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom Thread.currentThread().interrupt(); 410f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom return false; 411f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 412f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 413f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom @Override protected void onPostExecute(Boolean ok) { 414f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom mCertHolder.mTab.postOperationUpdate(ok, mCertHolder); 415f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 416f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom } 417f6f4e303abb8b7883713b0af8484c7767e6af84dBrian Carlstrom} 418