| /* |
| * Copyright (C) 2009 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.certinstaller; |
| |
| import android.content.Intent; |
| import android.os.Bundle; |
| import android.os.Environment; |
| import android.preference.PreferenceActivity; |
| import android.security.Credentials; |
| import android.security.KeyChain; |
| import android.util.Log; |
| import android.widget.Toast; |
| |
| import java.io.File; |
| import java.io.FileFilter; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| |
| /** |
| * Base class that deals with certificate files on the SD card. |
| */ |
| public class CertFile extends PreferenceActivity implements FileFilter { |
| static final int CERT_READ_ERROR = R.string.cert_read_error; |
| static final int CERT_TOO_LARGE_ERROR = R.string.cert_too_large_error; |
| static final int CERT_FILE_MISSING_ERROR = R.string.cert_missing_error; |
| |
| static final String DOWNLOAD_DIR = "download"; |
| |
| private static final String TAG = "CertFile"; |
| |
| private static final String CERT_FILE_KEY = "cf"; |
| private static final int MAX_FILE_SIZE = 1000000; |
| protected static final int REQUEST_INSTALL_CODE = 1; |
| |
| private File mCertFile; |
| |
| @Override |
| protected void onSaveInstanceState(Bundle outStates) { |
| super.onSaveInstanceState(outStates); |
| if (mCertFile != null) { |
| outStates.putString(CERT_FILE_KEY, mCertFile.getAbsolutePath()); |
| } |
| } |
| |
| @Override |
| protected void onRestoreInstanceState(Bundle savedStates) { |
| super.onRestoreInstanceState(savedStates); |
| String path = savedStates.getString(CERT_FILE_KEY); |
| if (path != null) { |
| mCertFile = new File(path); |
| } |
| } |
| |
| @Override |
| protected void onActivityResult(int requestCode, int resultCode, Intent data) { |
| if (requestCode == REQUEST_INSTALL_CODE) { |
| boolean success = (resultCode == RESULT_OK |
| && (mCertFile == null || Util.deleteFile(mCertFile))); |
| onInstallationDone(success); |
| mCertFile = null; |
| } else { |
| Log.w(TAG, "unknown request code: " + requestCode); |
| } |
| } |
| |
| /** |
| * Called when installation is done. |
| * |
| * @param success true if installation is done successfully |
| */ |
| protected void onInstallationDone(boolean success) { |
| if (success) { |
| setResult(RESULT_OK); |
| } |
| } |
| |
| /** |
| * Called when an error occurs when reading a certificate file. |
| * |
| * @param errorId one of {@link #CERT_READ_ERROR}, |
| * {@link #CERT_TOO_LARGE_ERROR} and {@link #CERT_FILE_MISSING_ERROR} |
| */ |
| protected void onError(int errorId) { |
| } |
| |
| /** |
| * Returns a list of certificate files found on the SD card. |
| */ |
| protected List<File> getAllCertFiles() { |
| List<File> allFiles = new ArrayList<File>(); |
| File root = Environment.getExternalStorageDirectory(); |
| |
| File download = new File(root, DOWNLOAD_DIR); |
| if (download != null) { |
| File[] files = download.listFiles(this); |
| if (files != null) { |
| Collections.addAll(allFiles, files); |
| } |
| } |
| |
| File[] files = root.listFiles(this); |
| if (files != null) { |
| Collections.addAll(allFiles, files); |
| } |
| |
| return allFiles; |
| } |
| |
| /** |
| * Invokes {@link CertInstaller} to install the certificate(s) in the file. |
| * |
| * @param file the certificate file |
| */ |
| protected void installFromFile(File file) { |
| Log.d(TAG, "install cert from " + file); |
| |
| String fileName = file.getName(); |
| Bundle bundle = getIntent().getExtras(); |
| |
| final String name; |
| final int installAsUid; |
| if (bundle == null) { |
| name = fileName; |
| installAsUid = -1; |
| } else { |
| name = bundle.getString(KeyChain.EXTRA_NAME, fileName); |
| installAsUid = bundle.getInt(Credentials.EXTRA_INSTALL_AS_UID, -1); |
| } |
| |
| if (file.exists()) { |
| if (file.length() < MAX_FILE_SIZE) { |
| byte[] data = Util.readFile(file); |
| if (data == null) { |
| toastError(CERT_READ_ERROR); |
| onError(CERT_READ_ERROR); |
| return; |
| } |
| mCertFile = file; |
| install(fileName, name, installAsUid, data); |
| } else { |
| Log.w(TAG, "cert file is too large: " + file.length()); |
| toastError(CERT_TOO_LARGE_ERROR); |
| onError(CERT_TOO_LARGE_ERROR); |
| } |
| } else { |
| Log.w(TAG, "cert file does not exist"); |
| toastError(CERT_FILE_MISSING_ERROR); |
| onError(CERT_FILE_MISSING_ERROR); |
| } |
| } |
| |
| @Override public boolean accept(File file) { |
| if (!file.isDirectory()) { |
| return isFileAcceptable(file.getPath()); |
| } else { |
| return false; |
| } |
| } |
| |
| protected boolean isFileAcceptable(String path) { |
| return (path.endsWith(Credentials.EXTENSION_CRT) || |
| path.endsWith(Credentials.EXTENSION_P12) || |
| path.endsWith(Credentials.EXTENSION_CER) || |
| path.endsWith(Credentials.EXTENSION_PFX)); |
| } |
| |
| protected boolean isSdCardPresent() { |
| return Environment.getExternalStorageState().equals( |
| Environment.MEDIA_MOUNTED); |
| } |
| |
| private void install(String fileName, String name, int uid, byte[] value) { |
| Intent intent = new Intent(this, CertInstaller.class); |
| intent.putExtra(KeyChain.EXTRA_NAME, name); |
| intent.putExtra(Credentials.EXTRA_INSTALL_AS_UID, uid); |
| if (fileName.endsWith(Credentials.EXTENSION_PFX) |
| || fileName.endsWith(Credentials.EXTENSION_P12)) { |
| intent.putExtra(KeyChain.EXTRA_PKCS12, value); |
| } else if (fileName.endsWith(Credentials.EXTENSION_CER) |
| || fileName.endsWith(Credentials.EXTENSION_CRT)) { |
| intent.putExtra(KeyChain.EXTRA_CERTIFICATE, value); |
| } else { |
| throw new AssertionError(fileName); |
| } |
| startActivityForResult(intent, REQUEST_INSTALL_CODE); |
| } |
| |
| private void toastError(int msgId) { |
| Toast.makeText(this, msgId, Toast.LENGTH_LONG).show(); |
| } |
| } |