am 1aa64b53: am ae18171a: Change certificate policy.

Merge commit '1aa64b53eb9b3cc7904705076a015a5cd0e3b536' into kraken

* commit '1aa64b53eb9b3cc7904705076a015a5cd0e3b536':
  Change certificate policy.
This commit is contained in:
Suchi Amalapurapu
2010-03-31 23:22:56 -07:00
committed by Android Git Automerger
24 changed files with 464 additions and 188 deletions

View File

@@ -15,6 +15,7 @@
--> -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="internalOnly"
package="com.android.frameworks.coretests"> package="com.android.frameworks.coretests">
<permission android:name="com.android.frameworks.coretests.permission.TEST_GRANTED" <permission android:name="com.android.frameworks.coretests.permission.TEST_GRANTED"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -23,10 +23,18 @@ import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources; import android.content.res.Resources;
import android.content.res.Resources.NotFoundException; import android.content.res.Resources.NotFoundException;
import android.net.Uri; import android.net.Uri;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.Suppress;
import android.util.DisplayMetrics;
import android.util.Log;
import android.os.Environment; import android.os.Environment;
import android.os.FileUtils; import android.os.FileUtils;
import android.os.IBinder; import android.os.IBinder;
@@ -497,6 +505,15 @@ public class PackageManagerTests extends AndroidTestCase {
} }
} }
private PackageParser.Package getParsedPackage(String outFileName, int rawResId) {
PackageManager pm = mContext.getPackageManager();
File filesDir = mContext.getFilesDir();
File outFile = new File(filesDir, outFileName);
Uri packageURI = getInstallablePackage(rawResId, outFile);
PackageParser.Package pkg = parsePackage(packageURI);
return pkg;
}
/* /*
* Utility function that reads a apk bundled as a raw resource * Utility function that reads a apk bundled as a raw resource
* copies it into own data directory and invokes * copies it into own data directory and invokes
@@ -529,7 +546,9 @@ public class PackageManagerTests extends AndroidTestCase {
if (fail) { if (fail) {
assertTrue(invokeInstallPackageFail(packageURI, flags, assertTrue(invokeInstallPackageFail(packageURI, flags,
pkg.packageName, result)); pkg.packageName, result));
assertNotInstalled(pkg.packageName); if ((flags & PackageManager.INSTALL_REPLACE_EXISTING) == 0) {
assertNotInstalled(pkg.packageName);
}
} else { } else {
InstallReceiver receiver = new InstallReceiver(pkg.packageName); InstallReceiver receiver = new InstallReceiver(pkg.packageName);
assertTrue(invokeInstallPackage(packageURI, flags, assertTrue(invokeInstallPackage(packageURI, flags,
@@ -621,7 +640,7 @@ public class PackageManagerTests extends AndroidTestCase {
* PackageManager api to install first and then replace it * PackageManager api to install first and then replace it
* again. * again.
*/ */
public void replaceFromRawResource(int flags) { private void sampleReplaceFromRawResource(int flags) {
InstallParams ip = sampleInstallFromRawResource(flags, false); InstallParams ip = sampleInstallFromRawResource(flags, false);
boolean replace = ((flags & PackageManager.INSTALL_REPLACE_EXISTING) != 0); boolean replace = ((flags & PackageManager.INSTALL_REPLACE_EXISTING) != 0);
Log.i(TAG, "replace=" + replace); Log.i(TAG, "replace=" + replace);
@@ -648,28 +667,28 @@ public class PackageManagerTests extends AndroidTestCase {
} }
public void testReplaceFailNormalInternal() { public void testReplaceFailNormalInternal() {
replaceFromRawResource(0); sampleReplaceFromRawResource(0);
} }
public void testReplaceFailFwdLockedInternal() { public void testReplaceFailFwdLockedInternal() {
replaceFromRawResource(PackageManager.INSTALL_FORWARD_LOCK); sampleReplaceFromRawResource(PackageManager.INSTALL_FORWARD_LOCK);
} }
public void testReplaceFailSdcard() { public void testReplaceFailSdcard() {
replaceFromRawResource(PackageManager.INSTALL_EXTERNAL); sampleReplaceFromRawResource(PackageManager.INSTALL_EXTERNAL);
} }
public void testReplaceNormalInternal() { public void testReplaceNormalInternal() {
replaceFromRawResource(PackageManager.INSTALL_REPLACE_EXISTING); sampleReplaceFromRawResource(PackageManager.INSTALL_REPLACE_EXISTING);
} }
public void testReplaceFwdLockedInternal() { public void testReplaceFwdLockedInternal() {
replaceFromRawResource(PackageManager.INSTALL_REPLACE_EXISTING | sampleReplaceFromRawResource(PackageManager.INSTALL_REPLACE_EXISTING |
PackageManager.INSTALL_FORWARD_LOCK); PackageManager.INSTALL_FORWARD_LOCK);
} }
public void testReplaceSdcard() { public void testReplaceSdcard() {
replaceFromRawResource(PackageManager.INSTALL_REPLACE_EXISTING | sampleReplaceFromRawResource(PackageManager.INSTALL_REPLACE_EXISTING |
PackageManager.INSTALL_EXTERNAL); PackageManager.INSTALL_EXTERNAL);
} }
@@ -1014,6 +1033,19 @@ public class PackageManagerTests extends AndroidTestCase {
outFile.delete(); outFile.delete();
} }
} }
void cleanUpInstall(String pkgName) {
if (pkgName == null) {
return;
}
Log.i(TAG, "Deleting package : " + pkgName);
try {
ApplicationInfo info = getPm().getApplicationInfo(pkgName,
PackageManager.GET_UNINSTALLED_PACKAGES);
if (info != null) {
getPm().deletePackage(pkgName, null, 0);
}
} catch (NameNotFoundException e) {}
}
public void testManifestInstallLocationInternal() { public void testManifestInstallLocationInternal() {
installFromRawResource("install.apk", R.raw.install_loc_internal, installFromRawResource("install.apk", R.raw.install_loc_internal,
@@ -2152,6 +2184,360 @@ public class PackageManagerTests extends AndroidTestCase {
} }
} }
/*
* The following series of tests are related to upgrading apps with
* different certificates.
*/
private int APP1_UNSIGNED = R.raw.install_app1_unsigned;
private int APP1_CERT1 = R.raw.install_app1_cert1;
private int APP1_CERT2 = R.raw.install_app1_cert2;
private int APP1_CERT1_CERT2 = R.raw.install_app1_cert1_cert2;
private int APP1_CERT3_CERT4 = R.raw.install_app1_cert3_cert4;
private int APP1_CERT3 = R.raw.install_app1_cert3;
private int APP2_UNSIGNED = R.raw.install_app2_unsigned;
private int APP2_CERT1 = R.raw.install_app2_cert1;
private int APP2_CERT2 = R.raw.install_app2_cert2;
private int APP2_CERT1_CERT2 = R.raw.install_app2_cert1_cert2;
private int APP2_CERT3 = R.raw.install_app2_cert3;
private InstallParams replaceCerts(int apk1, int apk2, boolean cleanUp, boolean fail, int retCode) {
int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
String apk1Name = "install1.apk";
String apk2Name = "install2.apk";
PackageParser.Package pkg1 = getParsedPackage(apk1Name, apk1);
try {
InstallParams ip = installFromRawResource(apk1Name, apk1, 0, false,
false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
installFromRawResource(apk2Name, apk2, rFlags, false,
fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
return ip;
} catch (Exception e) {
failStr(e.getMessage());
} finally {
if (cleanUp) {
cleanUpInstall(pkg1.packageName);
}
}
return null;
}
/*
* Test that an app signed with two certificates can be upgraded by the
* same app signed with two certificates.
*/
public void testReplaceMatchAllCerts() {
replaceCerts(APP1_CERT1_CERT2, APP1_CERT1_CERT2, true, false, -1);
}
/*
* Test that an app signed with two certificates cannot be upgraded
* by an app signed with a different certificate.
*/
public void testReplaceMatchNoCerts1() {
replaceCerts(APP1_CERT1_CERT2, APP1_CERT3, true, true,
PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES);
}
/*
* Test that an app signed with two certificates cannot be upgraded
* by an app signed with a different certificate.
*/
public void testReplaceMatchNoCerts2() {
replaceCerts(APP1_CERT1_CERT2, APP1_CERT3_CERT4, true, true,
PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES);
}
/*
* Test that an app signed with two certificates cannot be upgraded by
* an app signed with a subset of initial certificates.
*/
public void testReplaceMatchSomeCerts1() {
replaceCerts(APP1_CERT1_CERT2, APP1_CERT1, true, true,
PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES);
}
/*
* Test that an app signed with two certificates cannot be upgraded by
* an app signed with the last certificate.
*/
public void testReplaceMatchSomeCerts2() {
replaceCerts(APP1_CERT1_CERT2, APP1_CERT2, true, true,
PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES);
}
/*
* Test that an app signed with a certificate can be upgraded by app
* signed with a superset of certificates.
*/
public void testReplaceMatchMoreCerts() {
replaceCerts(APP1_CERT1, APP1_CERT1_CERT2, true, true,
PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES);
}
/*
* Test that an app signed with a certificate can be upgraded by app
* signed with a superset of certificates. Then verify that the an app
* signed with the original set of certs cannot upgrade the new one.
*/
public void testReplaceMatchMoreCertsReplaceSomeCerts() {
InstallParams ip = replaceCerts(APP1_CERT1, APP1_CERT1_CERT2, false, true,
PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES);
try {
int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
installFromRawResource("install.apk", APP1_CERT1, rFlags, false,
false, -1,
PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
} catch (Exception e) {
failStr(e.getMessage());
} finally {
if (ip != null) {
cleanUpInstall(ip);
}
}
}
/*
* The following tests are related to testing the checkSignatures
* api.
*/
private void checkSignatures(int apk1, int apk2, int expMatchResult) {
checkSharedSignatures(apk1, apk2, true, false, -1, expMatchResult);
}
public void testCheckSignaturesAllMatch() {
int apk1 = APP1_CERT1_CERT2;
int apk2 = APP2_CERT1_CERT2;
checkSignatures(apk1, apk2, PackageManager.SIGNATURE_MATCH);
}
public void testCheckSignaturesNoMatch() {
int apk1 = APP1_CERT1;
int apk2 = APP2_CERT2;
checkSignatures(apk1, apk2, PackageManager.SIGNATURE_NO_MATCH);
}
public void testCheckSignaturesSomeMatch1() {
int apk1 = APP1_CERT1_CERT2;
int apk2 = APP2_CERT1;
checkSignatures(apk1, apk2, PackageManager.SIGNATURE_NO_MATCH);
}
public void testCheckSignaturesSomeMatch2() {
int apk1 = APP1_CERT1_CERT2;
int apk2 = APP2_CERT2;
checkSignatures(apk1, apk2, PackageManager.SIGNATURE_NO_MATCH);
}
public void testCheckSignaturesMoreMatch() {
int apk1 = APP1_CERT1;
int apk2 = APP2_CERT1_CERT2;
checkSignatures(apk1, apk2, PackageManager.SIGNATURE_NO_MATCH);
}
public void testCheckSignaturesUnknown() {
int apk1 = APP1_CERT1_CERT2;
int apk2 = APP2_CERT1_CERT2;
String apk1Name = "install1.apk";
String apk2Name = "install2.apk";
InstallParams ip1 = null;
try {
ip1 = installFromRawResource(apk1Name, apk1, 0, false,
false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
PackageManager pm = mContext.getPackageManager();
// Delete app2
File filesDir = mContext.getFilesDir();
File outFile = new File(filesDir, apk2Name);
int rawResId = apk2;
Uri packageURI = getInstallablePackage(rawResId, outFile);
PackageParser.Package pkg = parsePackage(packageURI);
getPm().deletePackage(pkg.packageName, null, 0);
// Check signatures now
int match = mContext.getPackageManager().checkSignatures(
ip1.pkg.packageName, pkg.packageName);
assertEquals(PackageManager.SIGNATURE_UNKNOWN_PACKAGE, match);
} finally {
if (ip1 != null) {
cleanUpInstall(ip1);
}
}
}
public void testInstallNoCertificates() {
int apk1 = APP1_UNSIGNED;
String apk1Name = "install1.apk";
InstallParams ip1 = null;
try {
installFromRawResource(apk1Name, apk1, 0, false,
true, PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES,
PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
} finally {
}
}
/* The following tests are related to apps using shared uids signed
* with different certs.
*/
private int SHARED1_UNSIGNED = R.raw.install_shared1_unsigned;
private int SHARED1_CERT1 = R.raw.install_shared1_cert1;
private int SHARED1_CERT2 = R.raw.install_shared1_cert2;
private int SHARED1_CERT1_CERT2 = R.raw.install_shared1_cert1_cert2;
private int SHARED2_UNSIGNED = R.raw.install_shared2_unsigned;
private int SHARED2_CERT1 = R.raw.install_shared2_cert1;
private int SHARED2_CERT2 = R.raw.install_shared2_cert2;
private int SHARED2_CERT1_CERT2 = R.raw.install_shared2_cert1_cert2;
private void checkSharedSignatures(int apk1, int apk2, boolean cleanUp, boolean fail, int retCode, int expMatchResult) {
String apk1Name = "install1.apk";
String apk2Name = "install2.apk";
PackageParser.Package pkg1 = getParsedPackage(apk1Name, apk1);
PackageParser.Package pkg2 = getParsedPackage(apk2Name, apk2);
try {
// Clean up before testing first.
cleanUpInstall(pkg1.packageName);
cleanUpInstall(pkg2.packageName);
installFromRawResource(apk1Name, apk1, 0, false,
false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
if (fail) {
installFromRawResource(apk2Name, apk2, 0, false,
true, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
} else {
installFromRawResource(apk2Name, apk2, 0, false,
false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
int match = mContext.getPackageManager().checkSignatures(
pkg1.packageName, pkg2.packageName);
assertEquals(expMatchResult, match);
}
} finally {
if (cleanUp) {
cleanUpInstall(pkg1.packageName);
cleanUpInstall(pkg2.packageName);
}
}
}
public void testCheckSignaturesSharedAllMatch() {
int apk1 = SHARED1_CERT1_CERT2;
int apk2 = SHARED2_CERT1_CERT2;
boolean fail = false;
int retCode = -1;
int expMatchResult = PackageManager.SIGNATURE_MATCH;
checkSharedSignatures(apk1, apk2, true, fail, retCode, expMatchResult);
}
public void testCheckSignaturesSharedNoMatch() {
int apk1 = SHARED1_CERT1;
int apk2 = SHARED2_CERT2;
boolean fail = true;
int retCode = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
int expMatchResult = -1;
checkSharedSignatures(apk1, apk2, true, fail, retCode, expMatchResult);
}
/*
* Test that an app signed with cert1 and cert2 cannot be replaced when signed with cert1 alone.
*/
public void testCheckSignaturesSharedSomeMatch1() {
int apk1 = SHARED1_CERT1_CERT2;
int apk2 = SHARED2_CERT1;
boolean fail = true;
int retCode = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
int expMatchResult = -1;
checkSharedSignatures(apk1, apk2, true, fail, retCode, expMatchResult);
}
/*
* Test that an app signed with cert1 and cert2 cannot be replaced when signed with cert2 alone.
*/
public void testCheckSignaturesSharedSomeMatch2() {
int apk1 = SHARED1_CERT1_CERT2;
int apk2 = SHARED2_CERT2;
boolean fail = true;
int retCode = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
int expMatchResult = -1;
checkSharedSignatures(apk1, apk2, true, fail, retCode, expMatchResult);
}
public void testCheckSignaturesSharedUnknown() {
int apk1 = SHARED1_CERT1_CERT2;
int apk2 = SHARED2_CERT1_CERT2;
String apk1Name = "install1.apk";
String apk2Name = "install2.apk";
InstallParams ip1 = null;
try {
ip1 = installFromRawResource(apk1Name, apk1, 0, false,
false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
PackageManager pm = mContext.getPackageManager();
// Delete app2
PackageParser.Package pkg = getParsedPackage(apk2Name, apk2);
getPm().deletePackage(pkg.packageName, null, 0);
// Check signatures now
int match = mContext.getPackageManager().checkSignatures(
ip1.pkg.packageName, pkg.packageName);
assertEquals(PackageManager.SIGNATURE_UNKNOWN_PACKAGE, match);
} finally {
if (ip1 != null) {
cleanUpInstall(ip1);
}
}
}
public void testReplaceFirstSharedMatchAllCerts() {
int apk1 = SHARED1_CERT1;
int apk2 = SHARED2_CERT1;
int rapk1 = SHARED1_CERT1;
checkSignatures(apk1, apk2, PackageManager.SIGNATURE_MATCH);
replaceCerts(apk1, rapk1, true, false, -1);
}
public void testReplaceSecondSharedMatchAllCerts() {
int apk1 = SHARED1_CERT1;
int apk2 = SHARED2_CERT1;
int rapk2 = SHARED2_CERT1;
checkSignatures(apk1, apk2, PackageManager.SIGNATURE_MATCH);
replaceCerts(apk2, rapk2, true, false, -1);
}
public void testReplaceFirstSharedMatchSomeCerts() {
int apk1 = SHARED1_CERT1_CERT2;
int apk2 = SHARED2_CERT1_CERT2;
int rapk1 = SHARED1_CERT1;
boolean fail = true;
int retCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
installFromRawResource("install.apk", rapk1, PackageManager.INSTALL_REPLACE_EXISTING, true,
fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
public void testReplaceSecondSharedMatchSomeCerts() {
int apk1 = SHARED1_CERT1_CERT2;
int apk2 = SHARED2_CERT1_CERT2;
int rapk2 = SHARED2_CERT1;
boolean fail = true;
int retCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
installFromRawResource("install.apk", rapk2, PackageManager.INSTALL_REPLACE_EXISTING, true,
fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
public void testReplaceFirstSharedMatchNoCerts() {
int apk1 = SHARED1_CERT1;
int apk2 = SHARED2_CERT1;
int rapk1 = SHARED1_CERT2;
boolean fail = true;
int retCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
installFromRawResource("install.apk", rapk1, PackageManager.INSTALL_REPLACE_EXISTING, true,
fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
public void testReplaceSecondSharedMatchNoCerts() {
int apk1 = SHARED1_CERT1;
int apk2 = SHARED2_CERT1;
int rapk2 = SHARED2_CERT2;
boolean fail = true;
int retCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
installFromRawResource("install.apk", rapk2, PackageManager.INSTALL_REPLACE_EXISTING, true,
fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
public void testReplaceFirstSharedMatchMoreCerts() {
int apk1 = SHARED1_CERT1;
int apk2 = SHARED2_CERT1;
int rapk1 = SHARED1_CERT1_CERT2;
boolean fail = true;
int retCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
installFromRawResource("install.apk", rapk1, PackageManager.INSTALL_REPLACE_EXISTING, true,
fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
public void testReplaceSecondSharedMatchMoreCerts() {
int apk1 = SHARED1_CERT1;
int apk2 = SHARED2_CERT1;
int rapk2 = SHARED2_CERT1_CERT2;
boolean fail = true;
int retCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
checkSharedSignatures(apk1, apk2, false, false, -1, PackageManager.SIGNATURE_MATCH);
installFromRawResource("install.apk", rapk2, PackageManager.INSTALL_REPLACE_EXISTING, true,
fail, retCode, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
/*---------- Recommended install location tests ----*/ /*---------- Recommended install location tests ----*/
/* /*
* TODO's * TODO's

View File

@@ -1835,21 +1835,19 @@ class PackageManagerService extends IPackageManager.Stub {
if (s2 == null) { if (s2 == null) {
return PackageManager.SIGNATURE_SECOND_NOT_SIGNED; return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
} }
final int N1 = s1.length; HashSet<Signature> set1 = new HashSet<Signature>();
final int N2 = s2.length; for (Signature sig : s1) {
for (int i=0; i<N1; i++) { set1.add(sig);
boolean match = false;
for (int j=0; j<N2; j++) {
if (s1[i].equals(s2[j])) {
match = true;
break;
}
}
if (!match) {
return PackageManager.SIGNATURE_NO_MATCH;
}
} }
return PackageManager.SIGNATURE_MATCH; HashSet<Signature> set2 = new HashSet<Signature>();
for (Signature sig : s2) {
set2.add(sig);
}
// Make sure s2 contains all signatures in s1.
if (set1.equals(set2)) {
return PackageManager.SIGNATURE_MATCH;
}
return PackageManager.SIGNATURE_NO_MATCH;
} }
public String[] getPackagesForUid(int uid) { public String[] getPackagesForUid(int uid) {
@@ -2501,6 +2499,9 @@ class PackageManagerService extends IPackageManager.Stub {
mLastScanError = pp.getParseError(); mLastScanError = pp.getParseError();
return false; return false;
} }
} else {
// Lets implicitly assign existing certificates.
pkg.mSignatures = ps.signatures.mSignatures;
} }
} }
return true; return true;
@@ -2629,28 +2630,27 @@ class PackageManagerService extends IPackageManager.Stub {
} }
private boolean verifySignaturesLP(PackageSetting pkgSetting, private boolean verifySignaturesLP(PackageSetting pkgSetting,
PackageParser.Package pkg, int parseFlags, boolean updateSignature) { PackageParser.Package pkg) {
if (pkg.mSignatures != null) { if (pkgSetting.signatures.mSignatures != null) {
if (!pkgSetting.signatures.updateSignatures(pkg.mSignatures, // Already existing package. Make sure signatures match
updateSignature)) { if (checkSignaturesLP(pkgSetting.signatures.mSignatures, pkg.mSignatures) !=
Slog.e(TAG, "Package " + pkg.packageName PackageManager.SIGNATURE_MATCH) {
+ " signatures do not match the previously installed version; ignoring!");
mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
return false;
}
if (pkgSetting.sharedUser != null) {
if (!pkgSetting.sharedUser.signatures.mergeSignatures(
pkg.mSignatures, updateSignature)) {
Slog.e(TAG, "Package " + pkg.packageName Slog.e(TAG, "Package " + pkg.packageName
+ " has no signatures that match those in shared user " + " signatures do not match the previously installed version; ignoring!");
+ pkgSetting.sharedUser.name + "; ignoring!"); mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
return false; return false;
} }
}
// Check for shared user signatures
if (pkgSetting.sharedUser != null && pkgSetting.sharedUser.signatures.mSignatures != null) {
if (checkSignaturesLP(pkgSetting.sharedUser.signatures.mSignatures,
pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
Slog.e(TAG, "Package " + pkg.packageName
+ " has no signatures that match those in shared user "
+ pkgSetting.sharedUser.name + "; ignoring!");
mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
return false;
} }
} else {
pkg.mSignatures = pkgSetting.signatures.mSignatures;
} }
return true; return true;
} }
@@ -2996,10 +2996,8 @@ class PackageManagerService extends IPackageManager.Stub {
pkg.applicationInfo.uid = pkgSetting.userId; pkg.applicationInfo.uid = pkgSetting.userId;
pkg.mExtras = pkgSetting; pkg.mExtras = pkgSetting;
if (!verifySignaturesLP(pkgSetting, pkg, parseFlags, if (!verifySignaturesLP(pkgSetting, pkg)) {
(scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) { if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
return null; return null;
} }
// The signature has changed, but this package is in the system // The signature has changed, but this package is in the system
@@ -3011,8 +3009,9 @@ class PackageManagerService extends IPackageManager.Stub {
// associated with an overall shared user, which doesn't seem all // associated with an overall shared user, which doesn't seem all
// that unreasonable. // that unreasonable.
if (pkgSetting.sharedUser != null) { if (pkgSetting.sharedUser != null) {
if (!pkgSetting.sharedUser.signatures.mergeSignatures( if (checkSignaturesLP(pkgSetting.sharedUser.signatures.mSignatures,
pkg.mSignatures, false)) { pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
Log.w(TAG, "Signature mismatch for shared user : " + pkgSetting.sharedUser);
mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
return null; return null;
} }
@@ -5543,7 +5542,7 @@ class PackageManagerService extends IPackageManager.Stub {
// First find the old package info and check signatures // First find the old package info and check signatures
synchronized(mPackages) { synchronized(mPackages) {
oldPackage = mPackages.get(pkgName); oldPackage = mPackages.get(pkgName);
if (checkSignaturesLP(pkg.mSignatures, oldPackage.mSignatures) if (checkSignaturesLP(oldPackage.mSignatures, pkg.mSignatures)
!= PackageManager.SIGNATURE_MATCH) { != PackageManager.SIGNATURE_MATCH) {
res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
return; return;
@@ -5571,7 +5570,6 @@ class PackageManagerService extends IPackageManager.Stub {
oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName); oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName);
} }
parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
// First delete the existing package while retaining the data directory // First delete the existing package while retaining the data directory
if (!deletePackageLI(pkgName, true, PackageManager.DONT_DELETE_DATA, if (!deletePackageLI(pkgName, true, PackageManager.DONT_DELETE_DATA,
res.removedInfo)) { res.removedInfo)) {
@@ -5595,20 +5593,7 @@ class PackageManagerService extends IPackageManager.Stub {
} }
} }
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
// If we deleted an exisiting package, the old source and resource files that we
// were keeping around in case we needed them (see below) can now be deleted.
// This info will be set on the res.removedInfo to clean up later on as post
// install action.
//update signature on the new package setting
//this should always succeed, since we checked the
//signature earlier.
synchronized(mPackages) {
verifySignaturesLP(mSettings.mPackages.get(pkgName), pkg,
parseFlags, true);
}
} else {
// remove package from internal structures. Note that we want deletePackageX to // remove package from internal structures. Note that we want deletePackageX to
// delete the package data and cache directories that it created in // delete the package data and cache directories that it created in
// scanPackageLocked, unless those directories existed before we even tried to // scanPackageLocked, unless those directories existed before we even tried to
@@ -5627,19 +5612,23 @@ class PackageManagerService extends IPackageManager.Stub {
Slog.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName); Slog.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
return; return;
} }
PackageInstalledInfo restoreRes = new PackageInstalledInfo();
restoreRes.removedInfo = new PackageRemovedInfo();
// Parse old package // Parse old package
parseFlags &= ~PackageManager.INSTALL_REPLACE_EXISTING; boolean oldOnSd = isExternal(deletedPackage);
scanPackageLI(restoreFile, parseFlags, scanMode); int oldParseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY |
(isForwardLocked(deletedPackage) ? PackageParser.PARSE_FORWARD_LOCK : 0) |
(oldOnSd ? PackageParser.PARSE_ON_SDCARD : 0);
int oldScanMode = (oldOnSd ? 0 : SCAN_MONITOR) | SCAN_UPDATE_SIGNATURE;
if (scanPackageLI(restoreFile, oldParseFlags, oldScanMode) == null) {
Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade");
return;
}
// Restore of old package succeeded. Update permissions.
synchronized (mPackages) { synchronized (mPackages) {
updatePermissionsLP(deletedPackage.packageName, deletedPackage, updatePermissionsLP(deletedPackage.packageName, deletedPackage,
true, false); true, false);
mSettings.writeLP(); mSettings.writeLP();
} }
if (restoreRes.returnCode != PackageManager.INSTALL_SUCCEEDED) { Slog.i(TAG, "Successfully restored package : " + pkgName + " after failed upgrade");
Slog.e(TAG, "Failed restoring pkg : " + pkgName + " after failed upgrade");
}
} }
} }
} }
@@ -5691,15 +5680,7 @@ class PackageManagerService extends IPackageManager.Stub {
updatedSettings = true; updatedSettings = true;
} }
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
//update signature on the new package setting
//this should always succeed, since we checked the
//signature earlier.
synchronized(mPackages) {
verifySignaturesLP(mSettings.mPackages.get(packageName), pkg,
parseFlags, true);
}
} else {
// Re installation failed. Restore old information // Re installation failed. Restore old information
// Remove new pkg information // Remove new pkg information
if (newPackage != null) { if (newPackage != null) {
@@ -5781,7 +5762,7 @@ class PackageManagerService extends IPackageManager.Stub {
boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0); boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0); boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0);
boolean replace = false; boolean replace = false;
int scanMode = SCAN_MONITOR | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE int scanMode = (onSd ? 0 : SCAN_MONITOR) | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
| (newInstall ? SCAN_NEW_INSTALL : 0); | (newInstall ? SCAN_NEW_INSTALL : 0);
// Result object to be returned // Result object to be returned
res.returnCode = PackageManager.INSTALL_SUCCEEDED; res.returnCode = PackageManager.INSTALL_SUCCEEDED;
@@ -5911,6 +5892,10 @@ class PackageManagerService extends IPackageManager.Stub {
return ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0); return ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
} }
private boolean isExternal(PackageParser.Package pkg) {
return ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
}
private void extractPublicFiles(PackageParser.Package newPackage, private void extractPublicFiles(PackageParser.Package newPackage,
File publicZipFile) throws IOException { File publicZipFile) throws IOException {
final ZipOutputStream publicZipOutStream = final ZipOutputStream publicZipOutStream =
@@ -7345,101 +7330,6 @@ class PackageManagerService extends IPackageManager.Stub {
} }
} }
/**
* If any of the given 'sigs' is contained in the existing signatures,
* then completely replace the current signatures with the ones in
* 'sigs'. This is used for updating an existing package to a newly
* installed version.
*/
boolean updateSignatures(Signature[] sigs, boolean update) {
if (mSignatures == null) {
if (update) {
assignSignatures(sigs);
}
return true;
}
if (sigs == null) {
return false;
}
for (int i=0; i<sigs.length; i++) {
Signature sig = sigs[i];
for (int j=0; j<mSignatures.length; j++) {
if (mSignatures[j].equals(sig)) {
if (update) {
assignSignatures(sigs);
}
return true;
}
}
}
return false;
}
/**
* If any of the given 'sigs' is contained in the existing signatures,
* then add in any new signatures found in 'sigs'. This is used for
* including a new package into an existing shared user id.
*/
boolean mergeSignatures(Signature[] sigs, boolean update) {
if (mSignatures == null) {
if (update) {
assignSignatures(sigs);
}
return true;
}
if (sigs == null) {
return false;
}
Signature[] added = null;
int addedCount = 0;
boolean haveMatch = false;
for (int i=0; i<sigs.length; i++) {
Signature sig = sigs[i];
boolean found = false;
for (int j=0; j<mSignatures.length; j++) {
if (mSignatures[j].equals(sig)) {
found = true;
haveMatch = true;
break;
}
}
if (!found) {
if (added == null) {
added = new Signature[sigs.length];
}
added[i] = sig;
addedCount++;
}
}
if (!haveMatch) {
// Nothing matched -- reject the new signatures.
return false;
}
if (added == null) {
// Completely matched -- nothing else to do.
return true;
}
// Add additional signatures in.
if (update) {
Signature[] total = new Signature[addedCount+mSignatures.length];
System.arraycopy(mSignatures, 0, total, 0, mSignatures.length);
int j = mSignatures.length;
for (int i=0; i<added.length; i++) {
if (added[i] != null) {
total[j] = added[i];
j++;
}
}
mSignatures = total;
}
return true;
}
private void assignSignatures(Signature[] sigs) { private void assignSignatures(Signature[] sigs) {
if (sigs == null) { if (sigs == null) {
mSignatures = null; mSignatures = null;
@@ -8227,6 +8117,15 @@ class PackageManagerService extends IPackageManager.Stub {
if (pkg.mVersionCode != p.versionCode) { if (pkg.mVersionCode != p.versionCode) {
p.versionCode = pkg.mVersionCode; p.versionCode = pkg.mVersionCode;
} }
// Update signatures if needed.
if (p.signatures.mSignatures == null) {
p.signatures.assignSignatures(pkg.mSignatures);
}
// If this app defines a shared user id initialize
// the shared user signatures as well.
if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) {
p.sharedUser.signatures.assignSignatures(pkg.mSignatures);
}
addPackageSettingLP(p, pkg.packageName, p.sharedUser); addPackageSettingLP(p, pkg.packageName, p.sharedUser);
} }
@@ -9655,22 +9554,12 @@ class PackageManagerService extends IPackageManager.Stub {
// Parse package // Parse package
int parseFlags = PackageParser.PARSE_CHATTY | int parseFlags = PackageParser.PARSE_CHATTY |
PackageParser.PARSE_ON_SDCARD | mDefParseFlags; PackageParser.PARSE_ON_SDCARD | mDefParseFlags;
PackageParser pp = new PackageParser(codePath);
pp.setSeparateProcesses(mSeparateProcesses);
final PackageParser.Package pkg = pp.parsePackage(new File(codePath),
codePath, mMetrics, parseFlags);
pp = null;
doGc = true; doGc = true;
// Check for parse errors
if (pkg == null) {
Slog.e(TAG, "Parse error when installing install pkg : "
+ args.cid + " from " + args.cachePath);
continue;
}
setApplicationInfoPaths(pkg, codePath, codePath);
synchronized (mInstallLock) { synchronized (mInstallLock) {
final PackageParser.Package pkg = scanPackageLI(new File(codePath),
parseFlags, 0);
// Scan the package // Scan the package
if (scanPackageLI(pkg, parseFlags, SCAN_MONITOR) != null) { if (pkg != null) {
synchronized (mPackages) { synchronized (mPackages) {
retCode = PackageManager.INSTALL_SUCCEEDED; retCode = PackageManager.INSTALL_SUCCEEDED;
pkgList.add(pkg.packageName); pkgList.add(pkg.packageName);
@@ -9678,8 +9567,8 @@ class PackageManagerService extends IPackageManager.Stub {
args.doPostInstall(PackageManager.INSTALL_SUCCEEDED); args.doPostInstall(PackageManager.INSTALL_SUCCEEDED);
} }
} else { } else {
Slog.i(TAG, "Failed to install pkg: " + Slog.i(TAG, "Failed to install pkg from " +
pkg.packageName + " from sdcard"); codePath + " from sdcard");
} }
} }