• 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.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                 || Credentials.INSTALL_AS_USER_ACTION.equals(action)) {
65             Bundle bundle = intent.getExtras();
66 
67             /*
68              * There is a special INSTALL_AS_USER action that this activity is
69              * aliased to, but you have to have a permission to call it. If the
70              * caller got here any other way, remove the extra that we allow in
71              * that INSTALL_AS_USER path.
72              */
73             if (bundle != null && !Credentials.INSTALL_AS_USER_ACTION.equals(action)) {
74                 bundle.remove(Credentials.EXTRA_INSTALL_AS_UID);
75             }
76 
77             // If bundle is empty of any actual credentials, install from external storage.
78             // Otherwise, pass extras to CertInstaller to install those credentials.
79             // Either way, we use KeyChain.EXTRA_NAME as the default name if available.
80             if (bundle == null
81                     || bundle.isEmpty()
82                     || (bundle.size() == 1
83                         && (bundle.containsKey(KeyChain.EXTRA_NAME)
84                             || bundle.containsKey(Credentials.EXTRA_INSTALL_AS_UID)))) {
85                 if (!isSdCardPresent()) {
86                     Toast.makeText(this, R.string.sdcard_not_present,
87                             Toast.LENGTH_SHORT).show();
88                 } else {
89                     List<File> allFiles = getAllCertFiles();
90                     if (allFiles.isEmpty()) {
91                         Toast.makeText(this, R.string.no_cert_file_found,
92                                 Toast.LENGTH_SHORT).show();
93                     } else if (allFiles.size() == 1) {
94                         installFromFile(allFiles.get(0));
95                         return;
96                     } else {
97                         Intent newIntent = new Intent(this, CertFileList.class);
98                         newIntent.putExtras(intent);
99                         startActivityForResult(newIntent, REQUEST_INSTALL_CODE);
100                         return;
101                     }
102                 }
103             } else {
104                 Intent newIntent = new Intent(this, CertInstaller.class);
105                 newIntent.putExtras(intent);
106                 startActivityForResult(newIntent, REQUEST_INSTALL_CODE);
107                 return;
108             }
109         } else if (Intent.ACTION_VIEW.equals(action)) {
110             Uri data = intent.getData();
111             String type = intent.getType();
112             if ((data != null) && (type != null)) {
113                 byte[] payload = null;
114                 InputStream is = null;
115                 try {
116                     is = getContentResolver().openInputStream(data);
117                     ByteArrayOutputStream out = new ByteArrayOutputStream();
118                     byte[] buffer = new byte[1024];
119                     int read = 0;
120                     while ((read = is.read(buffer)) > 0) {
121                         out.write(buffer, 0, read);
122                     }
123                     out.flush();
124                     payload = out.toByteArray();
125                 } catch (IOException ignored) {
126                     // Not much we can do - it will be logged below as an error.
127                 } finally {
128                     IoUtils.closeQuietly(is);
129                 }
130                 if (payload == null) {
131                     Log.e("CertInstaller", "Unable to read stream for for certificate");
132                 } else {
133                     installByType(type, payload);
134                 }
135             }
136         }
137         finish();
138     }
139 
installByType(String type, byte[] value)140     private void installByType(String type, byte[] value) {
141         Intent intent = new Intent(this, CertInstaller.class);
142         if ("application/x-pkcs12".equals(type)) {
143             intent.putExtra(KeyChain.EXTRA_PKCS12, value);
144         } else if ("application/x-x509-ca-cert".equals(type)
145                 || "application/x-x509-user-cert".equals(type)) {
146             intent.putExtra(KeyChain.EXTRA_CERTIFICATE, value);
147         } else {
148             throw new AssertionError("Unknown type: " + type);
149         }
150         startActivityForResult(intent, REQUEST_INSTALL_CODE);
151     }
152 
153     @Override
onInstallationDone(boolean success)154     protected void onInstallationDone(boolean success) {
155         super.onInstallationDone(success);
156         finish();
157     }
158 
159     @Override
onError(int errorId)160     protected void onError(int errorId) {
161         finish();
162     }
163 }
164