From 5c2454cde182118a3619e905b8add2c21e14070d Mon Sep 17 00:00:00 2001 From: Gustav Sennton Date: Thu, 17 Dec 2015 15:49:33 +0000 Subject: [PATCH] Allow several valid signatures per WebView provider. If one of the signatures match the package signature the package is considered valid. This makes it possible to match signatures in user builds for both signed and unsigned builds. Bug: 26220882 Change-Id: Ie2e7567bf518d4859d68b5fdf5b9833fcdaa7670 --- core/java/android/webkit/WebViewFactory.java | 23 +++++++++++++++++-- .../android/webkit/WebViewProviderInfo.java | 23 ++++++++++++------- core/res/res/xml/config_webview_packages.xml | 3 ++- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java index 01d15664f24a1..6aa5e2f573bd3 100644 --- a/core/java/android/webkit/WebViewFactory.java +++ b/core/java/android/webkit/WebViewFactory.java @@ -133,6 +133,25 @@ public final class WebViewFactory { private static String TAG_DESCRIPTION = "description"; private static String TAG_SIGNATURE = "signature"; + /** + * Reads all signatures at the current depth (within the current provider) from the XML parser. + */ + private static String[] readSignatures(XmlResourceParser parser) throws IOException, + XmlPullParserException { + List signatures = new ArrayList(); + int outerDepth = parser.getDepth(); + while(XmlUtils.nextElementWithin(parser, outerDepth)) { + if (parser.getName().equals(TAG_SIGNATURE)) { + // Parse the value within the signature tag + String signature = parser.nextText(); + signatures.add(signature); + } else { + Log.e(LOGTAG, "Found an element in a webview provider that is not a signature"); + } + } + return signatures.toArray(new String[signatures.size()]); + } + /** * Returns all packages declared in the framework resources as potential WebView providers. * @hide @@ -161,9 +180,9 @@ public final class WebViewFactory { throw new MissingWebViewPackageException( "WebView provider in framework resources missing description"); } - String signature = parser.getAttributeValue(null, TAG_SIGNATURE); webViewProviders.add( - new WebViewProviderInfo(packageName, description, signature)); + new WebViewProviderInfo(packageName, description, + readSignatures(parser))); } else { Log.e(LOGTAG, "Found an element that is not a webview provider"); diff --git a/core/java/android/webkit/WebViewProviderInfo.java b/core/java/android/webkit/WebViewProviderInfo.java index d5e3a230919b5..7bad6521b7340 100644 --- a/core/java/android/webkit/WebViewProviderInfo.java +++ b/core/java/android/webkit/WebViewProviderInfo.java @@ -40,10 +40,10 @@ public class WebViewProviderInfo implements Parcelable { public WebViewPackageNotFoundException(Exception e) { super(e); } } - public WebViewProviderInfo(String packageName, String description, String signature) { + public WebViewProviderInfo(String packageName, String description, String[] signatures) { this.packageName = packageName; this.description = description; - this.signature = signature; + this.signatures = signatures; } private boolean hasValidSignature() { @@ -53,7 +53,7 @@ public class WebViewProviderInfo implements Parcelable { try { // If no signature is declared, instead check whether the package is included in the // system. - if (signature == null) + if (signatures == null || signatures.length == 0) return getPackageInfo().applicationInfo.isSystemApp(); packageSignatures = getPackageInfo().signatures; @@ -62,8 +62,15 @@ public class WebViewProviderInfo implements Parcelable { } if (packageSignatures.length != 1) return false; - final byte[] releaseSignature = Base64.decode(signature, Base64.DEFAULT); - return Arrays.equals(releaseSignature, packageSignatures[0].toByteArray()); + + final byte[] packageSignature = packageSignatures[0].toByteArray(); + // Return whether the package signature matches any of the valid signatures + for (String signature : signatures) { + final byte[] validSignature = Base64.decode(signature, Base64.DEFAULT); + if (Arrays.equals(packageSignature, validSignature)) + return true; + } + return false; } /** @@ -109,7 +116,7 @@ public class WebViewProviderInfo implements Parcelable { private WebViewProviderInfo(Parcel in) { packageName = in.readString(); description = in.readString(); - signature = in.readString(); + signatures = in.createStringArray(); packageInfo = null; } @@ -122,14 +129,14 @@ public class WebViewProviderInfo implements Parcelable { public void writeToParcel(Parcel out, int flags) { out.writeString(packageName); out.writeString(description); - out.writeString(signature); + out.writeStringArray(signatures); } // fields read from framework resource public String packageName; public String description; - private String signature; + private String[] signatures; private PackageInfo packageInfo; // flags declaring we want extra info from the package manager diff --git a/core/res/res/xml/config_webview_packages.xml b/core/res/res/xml/config_webview_packages.xml index 6f9c58d2f9b72..fd443c15702d5 100644 --- a/core/res/res/xml/config_webview_packages.xml +++ b/core/res/res/xml/config_webview_packages.xml @@ -16,5 +16,6 @@ - + +