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.net.Uri; 21 import android.os.Bundle; 22 import android.security.Credentials; 23 import android.security.KeyChain; 24 import android.util.Log; 25 import android.widget.Toast; 26 27 import java.io.ByteArrayOutputStream; 28 import java.io.File; 29 import java.io.IOException; 30 import java.io.InputStream; 31 import java.util.List; 32 33 import libcore.io.IoUtils; 34 35 /** 36 * The main class for installing certificates to the system keystore. It reacts 37 * to the public {@link Credentials#INSTALL_ACTION} intent. 38 */ 39 public class CertInstallerMain extends CertFile implements Runnable { 40 @Override onCreate(Bundle savedInstanceState)41 protected void onCreate(Bundle savedInstanceState) { 42 super.onCreate(savedInstanceState); 43 if (savedInstanceState != null) { 44 return; 45 } 46 47 new Thread(new Runnable() { 48 @Override 49 public void run() { 50 // don't want to call startActivityForResult() (invoked in 51 // installFromFile()) here as it makes the new activity (thus 52 // the whole display) get stuck for about 5 seconds 53 runOnUiThread(CertInstallerMain.this); 54 } 55 }).start(); 56 } 57 58 @Override run()59 public void run() { 60 Intent intent = getIntent(); 61 String action = (intent == null) ? null : intent.getAction(); 62 63 if (Credentials.INSTALL_ACTION.equals(action)) { 64 Bundle bundle = intent.getExtras(); 65 // If bundle is empty of any actual credentials, install from external storage. 66 // Otherwise, pass extras to CertInstaller to install those credentials. 67 // Either way, we use KeyChain.EXTRA_NAME as the default name if available. 68 if (bundle == null 69 || bundle.isEmpty() 70 || (bundle.size() == 1 && bundle.containsKey(KeyChain.EXTRA_NAME))) { 71 if (!isSdCardPresent()) { 72 Toast.makeText(this, R.string.sdcard_not_present, 73 Toast.LENGTH_SHORT).show(); 74 } else { 75 List<File> allFiles = getAllCertFiles(); 76 if (allFiles.isEmpty()) { 77 Toast.makeText(this, R.string.no_cert_file_found, 78 Toast.LENGTH_SHORT).show(); 79 } else if (allFiles.size() == 1) { 80 installFromFile(allFiles.get(0)); 81 return; 82 } else { 83 Intent newIntent = new Intent(this, CertFileList.class); 84 newIntent.putExtras(intent); 85 startActivityForResult(newIntent, REQUEST_INSTALL_CODE); 86 return; 87 } 88 } 89 } else { 90 Intent newIntent = new Intent(this, CertInstaller.class); 91 newIntent.putExtras(intent); 92 startActivityForResult(newIntent, REQUEST_INSTALL_CODE); 93 return; 94 } 95 } else if (Intent.ACTION_VIEW.equals(action)) { 96 Uri data = intent.getData(); 97 String type = intent.getType(); 98 if ((data != null) && (type != null)) { 99 byte[] payload = null; 100 InputStream is = null; 101 try { 102 is = getContentResolver().openInputStream(data); 103 ByteArrayOutputStream out = new ByteArrayOutputStream(); 104 byte[] buffer = new byte[1024]; 105 int read = 0; 106 while ((read = is.read(buffer)) > 0) { 107 out.write(buffer, 0, read); 108 } 109 out.flush(); 110 payload = out.toByteArray(); 111 } catch (IOException ignored) { 112 // Not much we can do - it will be logged below as an error. 113 } finally { 114 IoUtils.closeQuietly(is); 115 } 116 if (payload == null) { 117 Log.e("CertInstaller", "Unable to read stream for for certificate"); 118 } else { 119 installByType(type, payload); 120 } 121 } 122 } 123 finish(); 124 } 125 installByType(String type, byte[] value)126 private void installByType(String type, byte[] value) { 127 Intent intent = new Intent(this, CertInstaller.class); 128 if ("application/x-pkcs12".equals(type)) { 129 intent.putExtra(KeyChain.EXTRA_PKCS12, value); 130 } else if ("application/x-x509-ca-cert".equals(type) 131 || "application/x-x509-user-cert".equals(type)) { 132 intent.putExtra(KeyChain.EXTRA_CERTIFICATE, value); 133 } else { 134 throw new AssertionError("Unknown type: " + type); 135 } 136 startActivityForResult(intent, REQUEST_INSTALL_CODE); 137 } 138 139 @Override onInstallationDone(boolean success)140 protected void onInstallationDone(boolean success) { 141 super.onInstallationDone(success); 142 finish(); 143 } 144 145 @Override onError(int errorId)146 protected void onError(int errorId) { 147 finish(); 148 } 149 } 150