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 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 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 66 if ((bundle == null) || bundle.isEmpty()) { 67 if (!isSdCardPresent()) { 68 Toast.makeText(this, R.string.sdcard_not_present, 69 Toast.LENGTH_SHORT).show(); 70 } else { 71 List<File> allFiles = getAllCertFiles(); 72 if (allFiles.isEmpty()) { 73 Toast.makeText(this, R.string.no_cert_file_found, 74 Toast.LENGTH_SHORT).show(); 75 } else if (allFiles.size() == 1) { 76 installFromFile(allFiles.get(0)); 77 return; 78 } else { 79 startActivityForResult(new Intent(this, CertFileList.class), 80 REQUEST_INSTALL_CODE); 81 return; 82 } 83 } 84 } else { 85 Intent newIntent = new Intent(this, CertInstaller.class); 86 newIntent.putExtras(intent); 87 startActivityForResult(newIntent, REQUEST_INSTALL_CODE); 88 return; 89 } 90 } else if (Intent.ACTION_VIEW.equals(action)) { 91 Uri data = intent.getData(); 92 String type = intent.getType(); 93 if ((data != null) && (type != null)) { 94 byte[] payload = null; 95 InputStream is = null; 96 try { 97 is = getContentResolver().openInputStream(data); 98 ByteArrayOutputStream out = new ByteArrayOutputStream(); 99 byte[] buffer = new byte[1024]; 100 int read = 0; 101 while ((read = is.read(buffer)) > 0) { 102 out.write(buffer, 0, read); 103 } 104 out.flush(); 105 payload = out.toByteArray(); 106 } catch (IOException ignored) { 107 // Not much we can do - it will be logged below as an error. 108 } finally { 109 IoUtils.closeQuietly(is); 110 } 111 if (payload == null) { 112 Log.e("CertInstaller", "Unable to read stream for for certificate"); 113 } else { 114 installByType(type, payload); 115 } 116 } 117 } 118 finish(); 119 } 120 121 private void installByType(String type, byte[] value) { 122 Intent intent = new Intent(this, CertInstaller.class); 123 if ("application/x-pkcs12".equals(type)) { 124 intent.putExtra(KeyChain.EXTRA_PKCS12, value); 125 } else if ("application/x-x509-ca-cert".equals(type) 126 || "application/x-x509-user-cert".equals(type)) { 127 intent.putExtra(KeyChain.EXTRA_CERTIFICATE, value); 128 } else { 129 throw new AssertionError("Unknown type: " + type); 130 } 131 startActivityForResult(intent, REQUEST_INSTALL_CODE); 132 } 133 134 @Override 135 protected void onInstallationDone(boolean success) { 136 super.onInstallationDone(success); 137 finish(); 138 } 139 140 @Override 141 protected void onError(int errorId) { 142 finish(); 143 } 144 } 145