blob: 9b10c07d47069df404e885c0402f8ca96f743b5f [file] [log] [blame]
/*
* 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.net.Uri;
import android.os.Bundle;
import android.security.Credentials;
import android.security.KeyChain;
import android.util.Log;
import android.widget.Toast;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import libcore.io.IoUtils;
/**
* The main class for installing certificates to the system keystore. It reacts
* to the public {@link Credentials#INSTALL_ACTION} intent.
*/
public class CertInstallerMain extends CertFile implements Runnable {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
return;
}
new Thread(new Runnable() {
@Override
public void run() {
// don't want to call startActivityForResult() (invoked in
// installFromFile()) here as it makes the new activity (thus
// the whole display) get stuck for about 5 seconds
runOnUiThread(CertInstallerMain.this);
}
}).start();
}
@Override
public void run() {
Intent intent = getIntent();
String action = (intent == null) ? null : intent.getAction();
if (Credentials.INSTALL_ACTION.equals(action)
|| Credentials.INSTALL_AS_USER_ACTION.equals(action)) {
Bundle bundle = intent.getExtras();
/*
* There is a special INSTALL_AS_USER action that this activity is
* aliased to, but you have to have a permission to call it. If the
* caller got here any other way, remove the extra that we allow in
* that INSTALL_AS_USER path.
*/
if (bundle != null && !Credentials.INSTALL_AS_USER_ACTION.equals(action)) {
bundle.remove(Credentials.EXTRA_INSTALL_AS_UID);
}
// If bundle is empty of any actual credentials, install from external storage.
// Otherwise, pass extras to CertInstaller to install those credentials.
// Either way, we use KeyChain.EXTRA_NAME as the default name if available.
if (bundle == null
|| bundle.isEmpty()
|| (bundle.size() == 1
&& (bundle.containsKey(KeyChain.EXTRA_NAME)
|| bundle.containsKey(Credentials.EXTRA_INSTALL_AS_UID)))) {
if (!isSdCardPresent()) {
Toast.makeText(this, R.string.sdcard_not_present,
Toast.LENGTH_SHORT).show();
} else {
List<File> allFiles = getAllCertFiles();
if (allFiles.isEmpty()) {
Toast.makeText(this, R.string.no_cert_file_found,
Toast.LENGTH_SHORT).show();
} else if (allFiles.size() == 1) {
installFromFile(allFiles.get(0));
return;
} else {
Intent newIntent = new Intent(this, CertFileList.class);
newIntent.putExtras(intent);
startActivityForResult(newIntent, REQUEST_INSTALL_CODE);
return;
}
}
} else {
Intent newIntent = new Intent(this, CertInstaller.class);
newIntent.putExtras(intent);
startActivityForResult(newIntent, REQUEST_INSTALL_CODE);
return;
}
} else if (Intent.ACTION_VIEW.equals(action)) {
Uri data = intent.getData();
String type = intent.getType();
if ((data != null) && (type != null)) {
byte[] payload = null;
InputStream is = null;
try {
is = getContentResolver().openInputStream(data);
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int read = 0;
while ((read = is.read(buffer)) > 0) {
out.write(buffer, 0, read);
}
out.flush();
payload = out.toByteArray();
} catch (IOException ignored) {
// Not much we can do - it will be logged below as an error.
} finally {
IoUtils.closeQuietly(is);
}
if (payload == null) {
Log.e("CertInstaller", "Unable to read stream for for certificate");
} else {
installByType(type, payload);
}
}
}
finish();
}
private void installByType(String type, byte[] value) {
Intent intent = new Intent(this, CertInstaller.class);
if ("application/x-pkcs12".equals(type)) {
intent.putExtra(KeyChain.EXTRA_PKCS12, value);
} else if ("application/x-x509-ca-cert".equals(type)
|| "application/x-x509-user-cert".equals(type)) {
intent.putExtra(KeyChain.EXTRA_CERTIFICATE, value);
} else {
throw new AssertionError("Unknown type: " + type);
}
startActivityForResult(intent, REQUEST_INSTALL_CODE);
}
@Override
protected void onInstallationDone(boolean success) {
super.onInstallationDone(success);
finish();
}
@Override
protected void onError(int errorId) {
finish();
}
}