CertFile.java revision d674440a49f278793aa2a2bb01c231f8cea7f8c0
13e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan/* 23e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * Copyright (C) 2009 The Android Open Source Project 33e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * 43e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * Licensed under the Apache License, Version 2.0 (the "License"); 53e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * you may not use this file except in compliance with the License. 63e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * You may obtain a copy of the License at 73e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * 83e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * http://www.apache.org/licenses/LICENSE-2.0 93e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * 103e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * Unless required by applicable law or agreed to in writing, software 113e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * distributed under the License is distributed on an "AS IS" BASIS, 123e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * See the License for the specific language governing permissions and 143e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * limitations under the License. 153e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan */ 163e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan 173e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyanpackage com.android.certinstaller; 183e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan 193e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyanimport android.app.Activity; 203e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyanimport android.content.Intent; 213e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyanimport android.os.Bundle; 223e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyanimport android.os.Environment; 233e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyanimport android.preference.PreferenceActivity; 243e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyanimport android.security.Credentials; 253e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyanimport android.util.Log; 263e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyanimport android.widget.Toast; 273e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan 283e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyanimport java.io.File; 293e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyanimport java.io.FileFilter; 303e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyanimport java.io.IOException; 313e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyanimport java.util.ArrayList; 323e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyanimport java.util.Collections; 333e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyanimport java.util.List; 343e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan 353e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan/** 363e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * Base class that deals with certificate files on the SD card. 373e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan */ 383e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyanpublic class CertFile extends PreferenceActivity implements FileFilter { 393e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan static final int CERT_READ_ERROR = R.string.cert_read_error; 403e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan static final int CERT_TOO_LARGE_ERROR = R.string.cert_too_large_error; 413e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan static final int CERT_FILE_MISSING_ERROR = R.string.cert_missing_error; 423e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan 433e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan static final String DOWNLOAD_DIR = "download"; 443e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan 453e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan private static final String TAG = "CertFile"; 463e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan 477b4cee910e1e755d2f0468a5f79aaa97e926a3a9Hung-ying Tyan private static final String CERT_EXT = ".crt"; 487b4cee910e1e755d2f0468a5f79aaa97e926a3a9Hung-ying Tyan private static final String PKCS12_EXT = ".p12"; 497b4cee910e1e755d2f0468a5f79aaa97e926a3a9Hung-ying Tyan 503e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan private static final String CERT_FILE_KEY = "cf"; 513e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan private static final int MAX_FILE_SIZE = 1000000; 523e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan private static final int REQUEST_INSTALL_CODE = 1; 533e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan 543e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan private File mCertFile; 553e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan 563e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan @Override 573e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan protected void onSaveInstanceState(Bundle outStates) { 583e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan super.onSaveInstanceState(outStates); 593e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan if (mCertFile != null) { 603e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan outStates.putString(CERT_FILE_KEY, mCertFile.getAbsolutePath()); 613e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan } 623e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan } 633e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan 643e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan @Override 653e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan protected void onRestoreInstanceState(Bundle savedStates) { 663e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan super.onRestoreInstanceState(savedStates); 673e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan String path = savedStates.getString(CERT_FILE_KEY); 683e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan if (path != null) mCertFile = new File(path); 693e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan } 703e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan 713e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan @Override 723e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan protected void onActivityResult(int requestCode, int resultCode, Intent data) { 733e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan if (requestCode == REQUEST_INSTALL_CODE) { 74d674440a49f278793aa2a2bb01c231f8cea7f8c0Hung-ying Tyan onInstallationDone((resultCode == RESULT_OK) 75d674440a49f278793aa2a2bb01c231f8cea7f8c0Hung-ying Tyan && Util.deleteFile(mCertFile)); 763e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan mCertFile = null; 773e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan } else { 783e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan Log.w(TAG, "unknown request code: " + requestCode); 793e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan } 803e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan } 813e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan 823e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan /** 833e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * Called when installation is done. 843e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * 853e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * @param success true if installation is done successfully 863e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan */ 873e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan protected void onInstallationDone(boolean success) { 883e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan } 893e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan 903e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan /** 913e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * Called when an error occurs when reading a certificate file. 923e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * 933e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * @param errorId one of {@link #CERT_READ_ERROR}, 943e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * {@link #CERT_TOO_LARGE_ERROR} and {@link #CERT_FILE_MISSING_ERROR} 953e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan */ 963e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan protected void onError(int errorId) { 973e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan } 983e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan 993e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan /** 1003e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * Returns a list of certificate files found on the SD card. 1013e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan */ 1023e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan protected List<File> getAllCertFiles() { 1033e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan List<File> allFiles = new ArrayList<File>(); 1043e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan File root = Environment.getExternalStorageDirectory(); 1053e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan File download = new File(root, DOWNLOAD_DIR); 1063e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan Collections.addAll(allFiles, download.listFiles(this)); 1073e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan Collections.addAll(allFiles, root.listFiles(this)); 1083e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan return allFiles; 1093e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan } 1103e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan 1113e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan /** 1123e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * Invokes {@link CertInstaller} to install the certificate(s) in the file. 1133e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * 1143e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan * @param file the certificate file 1153e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan */ 1163e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan protected void installFromFile(File file) { 1173e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan Log.d(TAG, "install cert from " + file); 1183e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan 1193e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan if (file.exists()) { 1203e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan if (file.length() < MAX_FILE_SIZE) { 1213e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan byte[] data = Util.readFile(file); 1223e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan if (data == null) { 1233e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan toastError(CERT_READ_ERROR); 1243e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan onError(CERT_READ_ERROR); 1253e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan return; 1263e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan } 1273e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan mCertFile = file; 1283e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan install(file.getName(), data); 1293e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan } else { 1303e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan Log.w(TAG, "cert file is too large: " + file.length()); 1313e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan toastError(CERT_TOO_LARGE_ERROR); 1323e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan onError(CERT_TOO_LARGE_ERROR); 1333e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan } 1343e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan } else { 1353e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan Log.w(TAG, "cert file does not exist"); 1363e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan toastError(CERT_FILE_MISSING_ERROR); 1373e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan onError(CERT_FILE_MISSING_ERROR); 1383e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan } 1393e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan } 1403e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan 1413e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan public boolean accept(File file) { 1423e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan if (!file.isDirectory()) { 1437b4cee910e1e755d2f0468a5f79aaa97e926a3a9Hung-ying Tyan return isFileAcceptable(file.getPath()); 1443e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan } else { 1453e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan return false; 1463e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan } 1473e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan } 1483e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan 1497b4cee910e1e755d2f0468a5f79aaa97e926a3a9Hung-ying Tyan protected boolean isFileAcceptable(String path) { 1507b4cee910e1e755d2f0468a5f79aaa97e926a3a9Hung-ying Tyan return (path.endsWith(PKCS12_EXT) || path.endsWith(CERT_EXT)); 1517b4cee910e1e755d2f0468a5f79aaa97e926a3a9Hung-ying Tyan } 1527b4cee910e1e755d2f0468a5f79aaa97e926a3a9Hung-ying Tyan 153d674440a49f278793aa2a2bb01c231f8cea7f8c0Hung-ying Tyan protected boolean isSdCardPresent() { 154d674440a49f278793aa2a2bb01c231f8cea7f8c0Hung-ying Tyan return Environment.getExternalStorageState().equals( 155d674440a49f278793aa2a2bb01c231f8cea7f8c0Hung-ying Tyan Environment.MEDIA_MOUNTED); 156d674440a49f278793aa2a2bb01c231f8cea7f8c0Hung-ying Tyan } 157d674440a49f278793aa2a2bb01c231f8cea7f8c0Hung-ying Tyan 1583e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan private void install(String fileName, byte[] value) { 1593e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan Intent intent = new Intent(this, CertInstaller.class); 1603e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan intent.putExtra(CredentialHelper.CERT_NAME_KEY, fileName); 1617b4cee910e1e755d2f0468a5f79aaa97e926a3a9Hung-ying Tyan if (fileName.endsWith(PKCS12_EXT)) { 1627b4cee910e1e755d2f0468a5f79aaa97e926a3a9Hung-ying Tyan intent.putExtra(Credentials.PKCS12, value); 1637b4cee910e1e755d2f0468a5f79aaa97e926a3a9Hung-ying Tyan } else { 1647b4cee910e1e755d2f0468a5f79aaa97e926a3a9Hung-ying Tyan intent.putExtra(Credentials.CERTIFICATE, value); 1657b4cee910e1e755d2f0468a5f79aaa97e926a3a9Hung-ying Tyan } 1663e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan startActivityForResult(intent, REQUEST_INSTALL_CODE); 1673e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan } 1683e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan 1693e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan private void toastError(int msgId) { 1703e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan Toast.makeText(this, msgId, Toast.LENGTH_LONG).show(); 1713e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan } 1723e722cadf66802194267460fe5de77e6c18530ebHung-ying Tyan} 173