diff options
author | Pete Bentley <prb@google.com> | 2021-09-22 15:28:22 +0100 |
---|---|---|
committer | Pete Bentley <prb@google.com> | 2021-09-22 15:28:22 +0100 |
commit | 1cf553a35873f22ca9b01924ff4f20d50ea6f03e (patch) | |
tree | 7086360bfe465ce8029f3ac0cb69ea4dd693398b | |
parent | 492053efc421a99f6e4b7a04d688adc5ce34a5ea (diff) | |
download | conscrypt-1cf553a35873f22ca9b01924ff4f20d50ea6f03e.tar.gz |
[DO NOT MERGE] CTS 11: Work around ConscryptHostnameVerifier changed.
Part of a set of changes to Android 11 CTS to enable it to pass
with or without an Android 12-based Conscrypt module installed.
In the Android platform ConscryptHostnameVerifier is a private
API and the interface definition changed between Android 11
and Android 12. If an Android 12 module is present, then
use its internal method for wrapping HostnameVerifer objects
rather than rely on consistency between the CTS and module
definitions of ConscryptHostnameVerifier.
Bug: 195615915
Test: atest CtsLibcoreTestCases with and without a 12-based Conscrypt module
Change-Id: I4961cf38a1a841a254fdc8aadc3938715ad303c1
4 files changed, 91 insertions, 9 deletions
diff --git a/common/src/test/java/org/conscrypt/TrustManagerImplTest.java b/common/src/test/java/org/conscrypt/TrustManagerImplTest.java index 3d444713..e1cce50b 100644 --- a/common/src/test/java/org/conscrypt/TrustManagerImplTest.java +++ b/common/src/test/java/org/conscrypt/TrustManagerImplTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.IOException; +import java.lang.reflect.Method; import java.security.KeyStore; import java.security.Principal; import java.security.cert.Certificate; @@ -29,6 +30,7 @@ import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.List; import javax.net.ssl.HandshakeCompletedListener; +import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLPeerUnverifiedException; @@ -165,9 +167,13 @@ public class TrustManagerImplTest { // Override the global default hostname verifier with a Conscrypt-specific one that // always passes. Both scenarios should pass. - Conscrypt.setDefaultHostnameVerifier(new ConscryptHostnameVerifier() { - @Override public boolean verify(String s, SSLSession sslSession) { return true; } - }); + HostnameVerifier alwaysTrue = new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + }; + HttpsURLConnection.setDefaultHostnameVerifier(alwaysTrue); certs = tmi.getTrustedChainForServer(chain, "RSA", new FakeSSLSocket(new FakeSSLSession(badHostname, chain), params)); @@ -179,7 +185,7 @@ public class TrustManagerImplTest { // Now set an instance-specific verifier on the trust manager. The bad hostname should // fail again. - Conscrypt.setHostnameVerifier(tmi, new TestHostnameVerifier()); + Conscrypt.setHostnameVerifier(tmi, wrapVerifier(new TestHostnameVerifier())); try { tmi.getTrustedChainForServer(chain, "RSA", @@ -208,6 +214,29 @@ public class TrustManagerImplTest { } } + /* + * Wrap a HostnameVerifier in a ConscryptHostnameVerifier. + * In the Android platform ConscryptHostnameVerifier is a private API and the interface + * definition changed between Android 11 and Android 12. + * If an Android 12 Conscrypt module is present then there will also be a (non-public) + * method to wrap it with the correct interface. + * If an earlier module is present then the interface is the same as in the CTS 11 codebase + * and so we can just wrap it directly with an anonymous class. + * See also b/195615915 + */ + private ConscryptHostnameVerifier wrapVerifier(final HostnameVerifier verifier) throws Exception { + Method wrapMethod = TestUtils.findWrapVerifierMethod(); + if (wrapMethod != null) { + return (ConscryptHostnameVerifier) wrapMethod.invoke(null, verifier); + } + return new ConscryptHostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return verifier.verify(hostname, session); + } + }; + } + private X509TrustManager trustManager(X509Certificate ca) throws Exception { KeyStore keyStore = TestKeyStore.createKeyStore(); keyStore.setCertificateEntry("alias", ca); diff --git a/repackaged/common/src/test/java/com/android/org/conscrypt/TrustManagerImplTest.java b/repackaged/common/src/test/java/com/android/org/conscrypt/TrustManagerImplTest.java index bff0b7f1..f08a46a3 100644 --- a/repackaged/common/src/test/java/com/android/org/conscrypt/TrustManagerImplTest.java +++ b/repackaged/common/src/test/java/com/android/org/conscrypt/TrustManagerImplTest.java @@ -21,7 +21,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import com.android.org.conscrypt.java.security.TestKeyStore; import java.io.IOException; +import java.lang.reflect.Method; import java.security.KeyStore; import java.security.Principal; import java.security.cert.Certificate; @@ -30,6 +32,7 @@ import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.List; import javax.net.ssl.HandshakeCompletedListener; +import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLPeerUnverifiedException; @@ -37,7 +40,6 @@ import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSessionContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.X509TrustManager; -import com.android.org.conscrypt.java.security.TestKeyStore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -169,12 +171,13 @@ public class TrustManagerImplTest { // Override the global default hostname verifier with a Conscrypt-specific one that // always passes. Both scenarios should pass. - Conscrypt.setDefaultHostnameVerifier(new ConscryptHostnameVerifier() { + HostnameVerifier alwaysTrue = new HostnameVerifier() { @Override - public boolean verify(String s, SSLSession sslSession) { + public boolean verify(String hostname, SSLSession session) { return true; } - }); + }; + HttpsURLConnection.setDefaultHostnameVerifier(alwaysTrue); certs = tmi.getTrustedChainForServer(chain, "RSA", new FakeSSLSocket(new FakeSSLSession(badHostname, chain), params)); @@ -186,7 +189,7 @@ public class TrustManagerImplTest { // Now set an instance-specific verifier on the trust manager. The bad hostname should // fail again. - Conscrypt.setHostnameVerifier(tmi, new TestHostnameVerifier()); + Conscrypt.setHostnameVerifier(tmi, wrapVerifier(new TestHostnameVerifier())); try { tmi.getTrustedChainForServer(chain, "RSA", @@ -215,6 +218,30 @@ public class TrustManagerImplTest { } } + /* + * Wrap a HostnameVerifier in a ConscryptHostnameVerifier. + * In the Android platform ConscryptHostnameVerifier is a private API and the interface + * definition changed between Android 11 and Android 12. + * If an Android 12 Conscrypt module is present then there will also be a (non-public) + * method to wrap it with the correct interface. + * If an earlier module is present then the interface is the same as in the CTS 11 codebase + * and so we can just wrap it directly with an anonymous class. + * See also b/195615915 + */ + private ConscryptHostnameVerifier wrapVerifier(final HostnameVerifier verifier) + throws Exception { + Method wrapMethod = TestUtils.findWrapVerifierMethod(); + if (wrapMethod != null) { + return (ConscryptHostnameVerifier) wrapMethod.invoke(null, verifier); + } + return new ConscryptHostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return verifier.verify(hostname, session); + } + }; + } + private X509TrustManager trustManager(X509Certificate ca) throws Exception { KeyStore keyStore = TestKeyStore.createKeyStore(); keyStore.setCertificateEntry("alias", ca); diff --git a/repackaged/testing/src/main/java/com/android/org/conscrypt/TestUtils.java b/repackaged/testing/src/main/java/com/android/org/conscrypt/TestUtils.java index 222715fa..21d07909 100644 --- a/repackaged/testing/src/main/java/com/android/org/conscrypt/TestUtils.java +++ b/repackaged/testing/src/main/java/com/android/org/conscrypt/TestUtils.java @@ -49,6 +49,7 @@ import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; +import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngineResult; @@ -171,6 +172,18 @@ public final class TestUtils { Assume.assumeTrue("SHA2 with DSA signatures not available", available); } + private static Method findMethod(Class<?> cls, String methodName, Class<?>... methodParams) { + try { + return cls.getDeclaredMethod(methodName, methodParams); + } catch (NoSuchMethodException e) { + return null; + } + } + + public static Method findWrapVerifierMethod() { + return findMethod(Conscrypt.class, "wrapHostnameVerifier", HostnameVerifier.class); + } + public static InetAddress getLoopbackAddress() { try { Method method = InetAddress.class.getMethod("getLoopbackAddress"); diff --git a/testing/src/main/java/org/conscrypt/TestUtils.java b/testing/src/main/java/org/conscrypt/TestUtils.java index bfb9b272..a4a798ae 100644 --- a/testing/src/main/java/org/conscrypt/TestUtils.java +++ b/testing/src/main/java/org/conscrypt/TestUtils.java @@ -45,6 +45,7 @@ import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; +import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngineResult; @@ -169,6 +170,18 @@ public final class TestUtils { Assume.assumeTrue("SHA2 with DSA signatures not available", available); } + private static Method findMethod(Class<?> cls, String methodName, Class<?>... methodParams) { + try { + return cls.getDeclaredMethod(methodName, methodParams); + } catch (NoSuchMethodException e) { + return null; + } + } + + public static Method findWrapVerifierMethod() { + return findMethod(Conscrypt.class, "wrapHostnameVerifier", HostnameVerifier.class); + } + public static InetAddress getLoopbackAddress() { try { Method method = InetAddress.class.getMethod("getLoopbackAddress"); |