Regarding the dummy TrustManager point, in my experience trust and hostname verification are separate steps (at least in Java’s implementation of SSL). Here are some tests:
@Test public void selfSignedHostnameVerified() throws Exception { assertEquals(204, getResponseCode("cn=localhost", null, null)); } @Test public void selfSignedHostnameNotVerifiedHostHeaderNotSent() throws Exception { try { getResponseCode("cn=otherhostname", null, null); fail("Expected exception"); } catch (SSLHandshakeException expected) { assertEquals("No name matching localhost found", expected.getMessage()); } } @Test public void selfSignedHostnameNotVerifiedHostHeaderSent() throws Exception { try { getResponseCode("cn=otherhostname", "otherhostname", null); fail("Expected exception"); } catch (SSLHandshakeException expected) { assertEquals("No name matching localhost found", expected.getMessage()); } } @Test public void selfSignedHostnameVerifiedByCustomVerifier() throws Exception { assertEquals(204, getResponseCode("cn=otherhostname", "otherhostname", ((hostname, session) -> true))); } private int getResponseCode(String certName, String hostHeader, HostnameVerifier hostnameVerifier) throws Exception { var keystorePassword = "secret"; var keystoreFile = keystoreFileWithSelfSignedCertificate(certName, keystorePassword); var keystore = KeyStore.getInstance("PKCS12"); keystore.load(new ByteArrayInputStream(Files.readAllBytes(keystoreFile)), keystorePassword.toCharArray()); var keyManagerFactory = KeyManagerFactory.getInstance("SunX509"); keyManagerFactory.init(keystore, keystorePassword.toCharArray()); var serverContext = SSLContext.getInstance("TLSv1.3"); serverContext.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom()); int port = 8443; var server = HttpsServer.create(new InetSocketAddress("0.0.0.0", port), 100); server.setHttpsConfigurator(new HttpsConfigurator(serverContext)); server.createContext("/foo", exchange -> exchange.sendResponseHeaders(204, -1)); server.setExecutor(Executors.newSingleThreadExecutor()); server.start(); var clientContext = SSLContext.getInstance("TLSv1.3"); clientContext.init(null, new TrustManager[] { new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] certs, String authType) { } public void checkServerTrusted(X509Certificate[] certs, String authType) { } } }, new SecureRandom()); var originalDefaultSocketFactory = HttpsURLConnection.getDefaultSSLSocketFactory(); var originalHostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier(); try { HttpsURLConnection.setDefaultSSLSocketFactory(clientContext.getSocketFactory()); if (hostnameVerifier != null) { HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier); } var connection = (HttpsURLConnection) new URL("https://localhost:" + port + "/foo").openConnection(); if (hostHeader != null) { connection.addRequestProperty("Host", hostHeader); } connection.connect(); return connection.getResponseCode(); } finally { HttpsURLConnection.setDefaultSSLSocketFactory(originalDefaultSocketFactory); HttpsURLConnection.setDefaultHostnameVerifier(originalHostnameVerifier); Files.delete(keystoreFile); server.stop(1); } } > On Nov 2, 2018, at 1:26 AM, Michael McMahon <michael.x.mcma...@oracle.com> > wrote: > > There is a fix in progress for > https://bugs.openjdk.java.net/browse/JDK-8213189 > which will allow the "Host" header to be overridden, along with some of the > other currently > restricted ones. > > I don't follow the other point though. With a dummy TrustManager, the > contents of the > server's certificate is ignored and can contain anything, and be self-signed, > I believe. > > Michael > > On 01/11/2018, 19:50, Anders Wisch wrote: >> Yes, although this is more restrictive because it means I have to have >> common name or subject >> alternative names in the self-signed certificate for “localhost”, >> “localhost.localdomain”, >> “127.0.0.1”, or similar so that my requests get routed to the local server. >> Testing hostname-based >> redirects under SSL is also made difficult by the host header being on the >> restricted list. If >> the hostname verifier used the contents of the host header instead of the >> URI's host, and the host >> header was customizable, then a self-signed certificate with CN and SAN >> entries for all of the >> names in question would work (provided I supplied a dummy TrustManager like >> you suggested). >> >>> On Nov 1, 2018, at 11:45 AM, Michael McMahon<michael.x.mcma...@oracle.com> >>> wrote: >>> >>> You could also isolate the behavior to a specific SSLContext (and therefore >>> HttpClient) >>> by initializing the SSLContext with a dummy TrustManager (if it's only for >>> testing). >>> >>> - Michael. >>> >>> On 01/11/2018, 18:09, Anders Wisch wrote: >>>> Thankfully, all of my uses are for testing. To test hostname-based >>>> redirects or integration tests of >>>> server code under SSL I start short-lived servers that serve self-signed >>>> certificates. Test cases >>>> use HTTP clients that disable hostname verification, connect to a local >>>> address and port, and >>>> sometimes vary the contents of the “Host” header. Since tests can run in >>>> parallel to speed up suite >>>> execution and since other tests require secure hostname verification, it’s >>>> useful to be able to >>>> isolate the behavior. >>>> >>>>> On Nov 1, 2018, at 10:53 AM, Chris Hegarty<chris.hega...@oracle.com> >>>>> wrote: >>>>> >>>>> In order to evaluate this request, can you please provide >>>>> use-cases for such. What “secure” server are you trying >>>>> to connect to that is unwilling to identify itself in its >>>>> certificate. >>>>> >>>>> -Chris. >>>>> >>>>>> On 1 Nov 2018, at 17:48, Anders Wisch<and...@featureshock.com> wrote: >>>>>> >>>>>> Hi all, >>>>>> >>>>>> I think it should be possible to supply a custom >>>>>> javax.net.ssl.HostnameVerifier while building a >>>>>> java.net.http.HttpClient. While it is possible to disable standard >>>>>> hostname verification via the >>>>>> system property “jdk.internal.httpclient.disableHostnameVerification”, >>>>>> this doesn’t allow you to >>>>>> quarantine the behavior to a single HTTP client within the JVM. >>>>>> >>>>>> Thanks for your consideration, >>>>>> Anders Wisch >>>>>> >>>>>> >>