Merge "Add ability to install credentials as other UID"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 031cc72..b2880d6 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -5,6 +5,9 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <permission android:name="com.android.certinstaller.INSTALL_AS_USER"
+ android:protectionLevel="signature" />
+
<application android:label="@string/app_name"
android:allowBackup="false">
<activity android:name=".CertInstallerMain"
@@ -23,6 +26,15 @@
</intent-filter>
</activity>
+ <activity-alias android:name=".InstallCertAsUser"
+ android:targetActivity=".CertInstallerMain"
+ android:permission="com.android.certinstaller.INSTALL_AS_USER">
+ <intent-filter>
+ <action android:name="android.credentials.INSTALL_AS_USER" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity-alias>
+
<activity android:name=".CertInstaller"
android:theme="@style/Transparent"
android:configChanges="orientation|keyboardHidden"
diff --git a/src/com/android/certinstaller/CertFile.java b/src/com/android/certinstaller/CertFile.java
index 401c1a3..5b4bfbf 100644
--- a/src/com/android/certinstaller/CertFile.java
+++ b/src/com/android/certinstaller/CertFile.java
@@ -131,9 +131,17 @@
String fileName = file.getName();
Bundle bundle = getIntent().getExtras();
- String name = ((bundle == null)
- ? fileName
- : bundle.getString(KeyChain.EXTRA_NAME, fileName));
+
+ final String name;
+ final int installAsUid;
+ if (bundle == null) {
+ name = fileName;
+ installAsUid = -1;
+ } else {
+ name = bundle.getString(KeyChain.EXTRA_NAME, fileName);
+ installAsUid = bundle.getInt(Credentials.EXTRA_INSTALL_AS_UID, -1);
+ }
+
if (file.exists()) {
if (file.length() < MAX_FILE_SIZE) {
byte[] data = Util.readFile(file);
@@ -143,7 +151,7 @@
return;
}
mCertFile = file;
- install(fileName, name, data);
+ install(fileName, name, installAsUid, data);
} else {
Log.w(TAG, "cert file is too large: " + file.length());
toastError(CERT_TOO_LARGE_ERROR);
@@ -176,9 +184,10 @@
Environment.MEDIA_MOUNTED);
}
- private void install(String fileName, String name, byte[] value) {
+ private void install(String fileName, String name, int uid, byte[] value) {
Intent intent = new Intent(this, CertInstaller.class);
intent.putExtra(KeyChain.EXTRA_NAME, name);
+ intent.putExtra(Credentials.EXTRA_INSTALL_AS_UID, uid);
if (fileName.endsWith(Credentials.EXTENSION_PFX)
|| fileName.endsWith(Credentials.EXTENSION_P12)) {
intent.putExtra(KeyChain.EXTRA_PKCS12, value);
diff --git a/src/com/android/certinstaller/CertFileList.java b/src/com/android/certinstaller/CertFileList.java
index 5e2b681..1d32c26 100644
--- a/src/com/android/certinstaller/CertFileList.java
+++ b/src/com/android/certinstaller/CertFileList.java
@@ -21,6 +21,7 @@
import android.os.FileObserver;
import android.preference.Preference;
import android.preference.PreferenceScreen;
+import android.security.Credentials;
import android.util.Log;
import android.widget.Toast;
diff --git a/src/com/android/certinstaller/CertInstallerMain.java b/src/com/android/certinstaller/CertInstallerMain.java
index 7d7ed6e..9b10c07 100644
--- a/src/com/android/certinstaller/CertInstallerMain.java
+++ b/src/com/android/certinstaller/CertInstallerMain.java
@@ -60,14 +60,28 @@
Intent intent = getIntent();
String action = (intent == null) ? null : intent.getAction();
- if (Credentials.INSTALL_ACTION.equals(action)) {
+ 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.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();
diff --git a/src/com/android/certinstaller/CredentialHelper.java b/src/com/android/certinstaller/CredentialHelper.java
index f9c35eb..5f59387 100644
--- a/src/com/android/certinstaller/CredentialHelper.java
+++ b/src/com/android/certinstaller/CredentialHelper.java
@@ -64,6 +64,7 @@
private HashMap<String, byte[]> mBundle = new HashMap<String, byte[]>();
private String mName = "";
+ private int mUid = -1;
private PrivateKey mUserKey;
private X509Certificate mUserCert;
private List<X509Certificate> mCaCerts = new ArrayList<X509Certificate>();
@@ -83,6 +84,9 @@
mName = name;
}
+ mUid = bundle.getInt(Credentials.EXTRA_INSTALL_AS_UID, -1);
+ bundle.remove(Credentials.EXTRA_INSTALL_AS_UID);
+
Log.d(TAG, "# extras: " + bundle.size());
for (String key : bundle.keySet()) {
byte[] bytes = bundle.getByteArray(key);
@@ -249,6 +253,7 @@
// To prevent the private key from being sniffed, we explicitly spell
// out the intent receiver class.
intent.setClassName("com.android.settings", "com.android.settings.CredentialStorage");
+ intent.putExtra(Credentials.EXTRA_INSTALL_AS_UID, mUid);
try {
if (mUserKey != null) {
intent.putExtra(Credentials.EXTRA_USER_PRIVATE_KEY_NAME,