• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.certinstaller;
18 
19 import android.content.Intent;
20 import android.os.Bundle;
21 import android.os.Environment;
22 import android.preference.PreferenceActivity;
23 import android.security.Credentials;
24 import android.security.KeyChain;
25 import android.util.Log;
26 import android.widget.Toast;
27 
28 import java.io.File;
29 import java.io.FileFilter;
30 import java.util.ArrayList;
31 import java.util.Collections;
32 import java.util.List;
33 
34 /**
35  * Base class that deals with certificate files on the SD card.
36  */
37 public class CertFile extends PreferenceActivity implements FileFilter {
38     static final int CERT_READ_ERROR = R.string.cert_read_error;
39     static final int CERT_TOO_LARGE_ERROR = R.string.cert_too_large_error;
40     static final int CERT_FILE_MISSING_ERROR = R.string.cert_missing_error;
41 
42     static final String DOWNLOAD_DIR = "download";
43 
44     private static final String TAG = "CertFile";
45 
46     private static final String CERT_FILE_KEY = "cf";
47     private static final int MAX_FILE_SIZE = 1000000;
48     protected static final int REQUEST_INSTALL_CODE = 1;
49 
50     private File mCertFile;
51 
52     @Override
onSaveInstanceState(Bundle outStates)53     protected void onSaveInstanceState(Bundle outStates) {
54         super.onSaveInstanceState(outStates);
55         if (mCertFile != null) {
56             outStates.putString(CERT_FILE_KEY, mCertFile.getAbsolutePath());
57         }
58     }
59 
60     @Override
onRestoreInstanceState(Bundle savedStates)61     protected void onRestoreInstanceState(Bundle savedStates) {
62         super.onRestoreInstanceState(savedStates);
63         String path = savedStates.getString(CERT_FILE_KEY);
64         if (path != null) {
65             mCertFile = new File(path);
66         }
67     }
68 
69     @Override
onActivityResult(int requestCode, int resultCode, Intent data)70     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
71         if (requestCode == REQUEST_INSTALL_CODE) {
72             boolean success = (resultCode == RESULT_OK
73                                && (mCertFile == null || Util.deleteFile(mCertFile)));
74             onInstallationDone(success);
75             mCertFile = null;
76         } else {
77             Log.w(TAG, "unknown request code: " + requestCode);
78         }
79     }
80 
81     /**
82      * Called when installation is done.
83      *
84      * @param success true if installation is done successfully
85      */
onInstallationDone(boolean success)86     protected void onInstallationDone(boolean success) {
87         if (success) {
88             setResult(RESULT_OK);
89         }
90     }
91 
92     /**
93      * Called when an error occurs when reading a certificate file.
94      *
95      * @param errorId one of {@link #CERT_READ_ERROR},
96      *      {@link #CERT_TOO_LARGE_ERROR} and {@link #CERT_FILE_MISSING_ERROR}
97      */
onError(int errorId)98     protected void onError(int errorId) {
99     }
100 
101     /**
102      * Returns a list of certificate files found on the SD card.
103      */
getAllCertFiles()104     protected List<File> getAllCertFiles() {
105         List<File> allFiles = new ArrayList<File>();
106         File root = Environment.getExternalStorageDirectory();
107 
108         File download = new File(root, DOWNLOAD_DIR);
109         if (download != null) {
110             File[] files = download.listFiles(this);
111             if (files != null) {
112                 Collections.addAll(allFiles, files);
113             }
114         }
115 
116         File[] files = root.listFiles(this);
117         if (files != null) {
118             Collections.addAll(allFiles, files);
119         }
120 
121         return allFiles;
122     }
123 
124     /**
125      * Invokes {@link CertInstaller} to install the certificate(s) in the file.
126      *
127      * @param file the certificate file
128      */
installFromFile(File file)129     protected void installFromFile(File file) {
130         Log.d(TAG, "install cert from " + file);
131 
132         String fileName = file.getName();
133         Bundle bundle = getIntent().getExtras();
134         String name = ((bundle == null)
135                        ? fileName
136                        : bundle.getString(KeyChain.EXTRA_NAME, fileName));
137         if (file.exists()) {
138             if (file.length() < MAX_FILE_SIZE) {
139                 byte[] data = Util.readFile(file);
140                 if (data == null) {
141                     toastError(CERT_READ_ERROR);
142                     onError(CERT_READ_ERROR);
143                     return;
144                 }
145                 mCertFile = file;
146                 install(fileName, name, data);
147             } else {
148                 Log.w(TAG, "cert file is too large: " + file.length());
149                 toastError(CERT_TOO_LARGE_ERROR);
150                 onError(CERT_TOO_LARGE_ERROR);
151             }
152         } else {
153             Log.w(TAG, "cert file does not exist");
154             toastError(CERT_FILE_MISSING_ERROR);
155             onError(CERT_FILE_MISSING_ERROR);
156         }
157     }
158 
accept(File file)159     @Override public boolean accept(File file) {
160         if (!file.isDirectory()) {
161             return isFileAcceptable(file.getPath());
162         } else {
163             return false;
164         }
165     }
166 
isFileAcceptable(String path)167     protected boolean isFileAcceptable(String path) {
168         return (path.endsWith(Credentials.EXTENSION_CRT) ||
169                 path.endsWith(Credentials.EXTENSION_P12) ||
170                 path.endsWith(Credentials.EXTENSION_CER) ||
171                 path.endsWith(Credentials.EXTENSION_PFX));
172     }
173 
isSdCardPresent()174     protected boolean isSdCardPresent() {
175         return Environment.getExternalStorageState().equals(
176                 Environment.MEDIA_MOUNTED);
177     }
178 
install(String fileName, String name, byte[] value)179     private void install(String fileName, String name, byte[] value) {
180         Intent intent = new Intent(this, CertInstaller.class);
181         intent.putExtra(KeyChain.EXTRA_NAME, name);
182         if (fileName.endsWith(Credentials.EXTENSION_PFX)
183                 || fileName.endsWith(Credentials.EXTENSION_P12)) {
184             intent.putExtra(KeyChain.EXTRA_PKCS12, value);
185         } else if (fileName.endsWith(Credentials.EXTENSION_CER)
186                    || fileName.endsWith(Credentials.EXTENSION_CRT)) {
187             intent.putExtra(KeyChain.EXTRA_CERTIFICATE, value);
188         } else {
189             throw new AssertionError(fileName);
190         }
191         startActivityForResult(intent, REQUEST_INSTALL_CODE);
192     }
193 
toastError(int msgId)194     private void toastError(int msgId) {
195         Toast.makeText(this, msgId, Toast.LENGTH_LONG).show();
196     }
197 }
198