diff --git a/distribution/server/src/assemble/LICENSE.bin.txt b/distribution/server/src/assemble/LICENSE.bin.txt index 3d7fe8260a71e..13d63e4f73038 100644 --- a/distribution/server/src/assemble/LICENSE.bin.txt +++ b/distribution/server/src/assemble/LICENSE.bin.txt @@ -435,9 +435,6 @@ The Apache Software License, Version 2.0 - org.eclipse.jetty.websocket-websocket-servlet-9.4.29.v20200521.jar * SnakeYaml -- org.yaml-snakeyaml-1.26.jar * RocksDB - org.rocksdb-rocksdbjni-5.13.3.jar - * HttpClient - - org.apache.httpcomponents-httpclient-4.5.5.jar - - org.apache.httpcomponents-httpcore-4.4.9.jar * Google Error Prone Annotations - com.google.errorprone-error_prone_annotations-2.1.3.jar * OkHttp - com.squareup.okhttp-okhttp-2.5.0.jar * Okio - com.squareup.okio-okio-1.13.0.jar diff --git a/pom.xml b/pom.xml index 4bbaee034eff3..14c3b15b36923 100644 --- a/pom.xml +++ b/pom.xml @@ -160,7 +160,6 @@ flexible messaging model and an intuitive client API. 5.3.2 1.9.13 0.16 - 4.5.5 2.12.1 1.48 3.6 @@ -236,12 +235,6 @@ flexible messaging model and an intuitive client API. - - org.apache.httpcomponents - httpclient - ${httpcomponents.version} - - org.testng testng diff --git a/pulsar-broker-shaded/pom.xml b/pulsar-broker-shaded/pom.xml index 90f32111840eb..66c44b17eb4e6 100644 --- a/pulsar-broker-shaded/pom.xml +++ b/pulsar-broker-shaded/pom.xml @@ -97,9 +97,6 @@ org.hdrhistogram:* com.github.zafarkhaja:java-semver org.aspectj:* - org.apache.httpcomponents:httpclient - commons-logging:commons-logging - org.apache.httpcomponents:httpcore org.apache.avro:avro org.codehaus.jackson:jackson-core-asl @@ -118,12 +115,6 @@ ** - - commons-logging:commons-logging - - ** - - @@ -295,10 +286,6 @@ com.wordnik org.apache.pulsar.shade.com.worknik - - org.apache.http - org.apache.pulsar.shade.org.apache.http - org.apache.avro org.apache.pulsar.shade.org.apache.avro diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiTlsAuthTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiTlsAuthTest.java index f2a3aaa2128e8..0d3961313f85b 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiTlsAuthTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiTlsAuthTest.java @@ -20,9 +20,10 @@ import com.google.common.collect.ImmutableSet; +import java.security.cert.X509Certificate; import java.util.List; import java.util.Optional; -import java.security.cert.X509Certificate; + import javax.net.ssl.SSLContext; import javax.ws.rs.NotAuthorizedException; import javax.ws.rs.client.Client; @@ -32,7 +33,7 @@ import javax.ws.rs.core.MediaType; import lombok.extern.slf4j.Slf4j; -import org.apache.http.conn.ssl.NoopHostnameVerifier; + import org.apache.pulsar.broker.auth.MockedPulsarServiceBaseTest; import org.apache.pulsar.client.admin.PulsarAdmin; import org.apache.pulsar.client.admin.PulsarAdminException; @@ -40,6 +41,7 @@ import org.apache.pulsar.client.api.Producer; import org.apache.pulsar.client.api.PulsarClient; import org.apache.pulsar.client.api.Schema; +import org.apache.pulsar.client.impl.tls.NoopHostnameVerifier; import org.apache.pulsar.common.policies.data.AuthAction; import org.apache.pulsar.common.policies.data.ClusterData; import org.apache.pulsar.common.policies.data.TenantInfo; diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/web/WebServiceTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/web/WebServiceTest.java index b9577e677e851..fa976b344dc18 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/web/WebServiceTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/web/WebServiceTest.java @@ -51,12 +51,6 @@ import lombok.Cleanup; import org.apache.commons.lang3.StringUtils; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.entity.ByteArrayEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; import org.apache.pulsar.broker.MockedBookKeeperClientFactory; import org.apache.pulsar.broker.PulsarService; import org.apache.pulsar.broker.ServiceConfiguration; @@ -71,6 +65,10 @@ import org.apache.pulsar.zookeeper.MockedZooKeeperClientFactoryImpl; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.ZooDefs; +import org.asynchttpclient.AsyncHttpClient; +import org.asynchttpclient.BoundRequestBuilder; +import org.asynchttpclient.DefaultAsyncHttpClient; +import org.asynchttpclient.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.Assert; @@ -215,19 +213,20 @@ public void testMaxRequestSize() throws Exception { String url = pulsar.getWebServiceAddress() + "/admin/v2/tenants/my-tenant" + System.currentTimeMillis(); @Cleanup - CloseableHttpClient client = HttpClients.createDefault(); - HttpPut httpPut = new HttpPut(url); - httpPut.setHeader("Content-Type", "application/json"); - httpPut.setHeader("Accept", "application/json"); + AsyncHttpClient client = new DefaultAsyncHttpClient(); + + BoundRequestBuilder builder = client.preparePut(url) + .setHeader("Accept", "application/json") + .setHeader("Content-Type", "application/json"); // HTTP server is configured to reject everything > 10K TenantInfo info1 = new TenantInfo(); info1.setAdminRoles(Collections.singleton(StringUtils.repeat("*", 20 * 1024))); - httpPut.setEntity(new ByteArrayEntity(ObjectMapperFactory.getThreadLocal().writeValueAsBytes(info1))); + builder.setBody(ObjectMapperFactory.getThreadLocal().writeValueAsBytes(info1)); + Response res = builder.execute().get(); - CloseableHttpResponse response = client.execute(httpPut); // This should have failed - assertEquals(response.getStatusLine().getStatusCode(), 400); + assertEquals(res.getStatusCode(), 400); // Create local cluster String localCluster = "test"; @@ -237,17 +236,18 @@ public void testMaxRequestSize() throws Exception { TenantInfo info2 = new TenantInfo(); info2.setAdminRoles(Collections.singleton(StringUtils.repeat("*", 1 * 1024))); info2.setAllowedClusters(Sets.newHashSet(localCluster)); - httpPut.setEntity(new ByteArrayEntity(ObjectMapperFactory.getThreadLocal().writeValueAsBytes(info2))); + builder.setBody(ObjectMapperFactory.getThreadLocal().writeValueAsBytes(info2)); - response = client.execute(httpPut); - assertEquals(response.getStatusLine().getStatusCode(), 204); + Response res2 = builder.execute().get(); + assertEquals(res2.getStatusCode(), 204); // Simple GET without content size should go through - HttpGet httpGet = new HttpGet(url); - httpGet.setHeader("Content-Type", "application/json"); - httpGet.setHeader("Accept", "application/json"); - response = client.execute(httpGet); - assertEquals(response.getStatusLine().getStatusCode(), 200); + Response res3 = client.prepareGet(url) + .setHeader("Accept", "application/json") + .setHeader("Content-Type", "application/json") + .execute() + .get(); + assertEquals(res3.getStatusCode(), 200); } private String makeHttpRequest(boolean useTls, boolean useAuth) throws Exception { diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/AuthenticationTlsHostnameVerificationTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/AuthenticationTlsHostnameVerificationTest.java index 0d3f4123a4fc7..27902d53300e3 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/AuthenticationTlsHostnameVerificationTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/AuthenticationTlsHostnameVerificationTest.java @@ -29,12 +29,12 @@ import java.util.Set; import java.util.concurrent.TimeUnit; -import org.apache.http.conn.ssl.DefaultHostnameVerifier; -import org.apache.http.conn.util.PublicSuffixMatcher; import org.apache.pulsar.broker.authentication.AuthenticationProviderBasic; import org.apache.pulsar.broker.authentication.AuthenticationProviderTls; import org.apache.pulsar.client.admin.PulsarAdmin; import org.apache.pulsar.client.impl.auth.AuthenticationTls; +import org.apache.pulsar.client.impl.tls.PublicSuffixMatcher; +import org.apache.pulsar.client.impl.tls.TlsHostnameVerifier; import org.apache.pulsar.common.policies.data.ClusterData; import org.apache.pulsar.common.policies.data.TenantInfo; import org.slf4j.Logger; @@ -237,7 +237,7 @@ public void testTlsSyncProducerAndConsumerCorrectBrokerHost() throws Exception { @Test public void testDefaultHostVerifier() throws Exception { log.info("-- Starting {} test --", methodName); - Method matchIdentityStrict = DefaultHostnameVerifier.class.getDeclaredMethod("matchIdentityStrict", + Method matchIdentityStrict = TlsHostnameVerifier.class.getDeclaredMethod("matchIdentityStrict", String.class, String.class, PublicSuffixMatcher.class); matchIdentityStrict.setAccessible(true); Assert.assertTrue((boolean) matchIdentityStrict.invoke(null, "pulsar", "pulsar", null)); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/AdminApiKeyStoreTlsAuthTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/AdminApiKeyStoreTlsAuthTest.java index ab2833dfbd00f..b802240dcee52 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/AdminApiKeyStoreTlsAuthTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/AdminApiKeyStoreTlsAuthTest.java @@ -23,26 +23,30 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; + import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; + import javax.net.ssl.SSLContext; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.GenericType; import javax.ws.rs.core.MediaType; + import lombok.extern.slf4j.Slf4j; -import org.apache.http.conn.ssl.NoopHostnameVerifier; + import org.apache.pulsar.broker.authentication.AuthenticationProviderTls; import org.apache.pulsar.client.admin.PulsarAdmin; import org.apache.pulsar.client.admin.PulsarAdminException; import org.apache.pulsar.client.admin.internal.JacksonConfigurator; import org.apache.pulsar.client.api.ProducerConsumerBase; import org.apache.pulsar.client.impl.auth.AuthenticationKeyStoreTls; +import org.apache.pulsar.client.impl.tls.NoopHostnameVerifier; import org.apache.pulsar.common.policies.data.ClusterData; import org.apache.pulsar.common.policies.data.TenantInfo; import org.apache.pulsar.common.util.keystoretls.KeyStoreSSLContext; diff --git a/pulsar-client-admin-shaded/pom.xml b/pulsar-client-admin-shaded/pom.xml index 2e27b04dbc4da..52db2278ef44e 100644 --- a/pulsar-client-admin-shaded/pom.xml +++ b/pulsar-client-admin-shaded/pom.xml @@ -84,7 +84,6 @@ com.squareup.*:* com.google.*:* commons-*:* - org.apache.httpcomponents:* org.eclipse.jetty:* com.google.auth:* org.jvnet.mimepull:* @@ -207,10 +206,6 @@ org.eclipse.jetty org.apache.pulsar.shade.org.eclipse.jetty - - org.apache.http - org.apache.pulsar.shade.org.apache.http - org.objenesis org.apache.pulsar.shade.org.objenesis diff --git a/pulsar-client-all/pom.xml b/pulsar-client-all/pom.xml index ff901b91bc482..1ebfc709dffff 100644 --- a/pulsar-client-all/pom.xml +++ b/pulsar-client-all/pom.xml @@ -141,7 +141,6 @@ com.squareup.*:* com.google.*:* commons-*:* - org.apache.httpcomponents:* org.eclipse.jetty:* com.google.auth:* org.jvnet.mimepull:* @@ -168,12 +167,6 @@ ** - - commons-logging:commons-logging - - ** - - @@ -215,10 +208,6 @@ com.yahoo org.apache.pulsar.shade.com.yahoo - - org.apache.http - org.apache.pulsar.shade.org.apache.http - org.eclipse.jetty org.apache.pulsar.shade.org.eclipse @@ -283,10 +272,6 @@ org.eclipse.jetty org.apache.pulsar.shade.org.eclipse.jetty - - org.apache.http - org.apache.pulsar.shade.org.apache.http - org.objenesis org.apache.pulsar.shade.org.objenesis diff --git a/pulsar-client-kafka-compat/pulsar-client-kafka-shaded/pom.xml b/pulsar-client-kafka-compat/pulsar-client-kafka-shaded/pom.xml index cfa2d24233e83..463b4968dbc52 100644 --- a/pulsar-client-kafka-compat/pulsar-client-kafka-shaded/pom.xml +++ b/pulsar-client-kafka-compat/pulsar-client-kafka-shaded/pom.xml @@ -89,9 +89,6 @@ org.apache.pulsar:pulsar-common org.apache.bookkeeper:circe-checksum com.yahoo.datasketches:sketches-core - org.apache.httpcomponents:httpclient - commons-logging:commons-logging - org.apache.httpcomponents:httpcore org.eclipse.jetty:* com.yahoo.datasketches:* commons-*:* @@ -108,12 +105,6 @@ - - commons-logging:commons-logging - - ** - - org.apache.pulsar:pulsar-client-original @@ -169,10 +160,6 @@ com.yahoo.sketches org.apache.pulsar.shade.com.yahoo.sketches - - org.apache.http - org.apache.pulsar.shade.org.apache.http - org.eclipse.jetty org.apache.pulsar.shade.org.eclipse diff --git a/pulsar-client-kafka-compat/pulsar-client-kafka-shaded_0_8/pom.xml b/pulsar-client-kafka-compat/pulsar-client-kafka-shaded_0_8/pom.xml index b7468e50b31b3..de5bff158aa41 100644 --- a/pulsar-client-kafka-compat/pulsar-client-kafka-shaded_0_8/pom.xml +++ b/pulsar-client-kafka-compat/pulsar-client-kafka-shaded_0_8/pom.xml @@ -89,9 +89,6 @@ org.apache.pulsar:pulsar-common org.apache.bookkeeper:circe-checksum com.yahoo.datasketches:sketches-core - org.apache.httpcomponents:httpclient - commons-logging:commons-logging - org.apache.httpcomponents:httpcore org.eclipse.jetty:* com.yahoo.datasketches:* commons-*:* @@ -108,12 +105,6 @@ - - commons-logging:commons-logging - - ** - - org.apache.pulsar:pulsar-client-original @@ -327,10 +318,6 @@ com.yahoo.sketches org.apache.pulsar.shade.com.yahoo.sketches - - org.apache.http - org.apache.pulsar.shade.org.apache.http - org.eclipse.jetty org.apache.pulsar.shade.org.eclipse diff --git a/pulsar-client-kafka-compat/pulsar-client-kafka-shaded_0_9/pom.xml b/pulsar-client-kafka-compat/pulsar-client-kafka-shaded_0_9/pom.xml index 8bb7c44204702..4980544c8fa51 100644 --- a/pulsar-client-kafka-compat/pulsar-client-kafka-shaded_0_9/pom.xml +++ b/pulsar-client-kafka-compat/pulsar-client-kafka-shaded_0_9/pom.xml @@ -85,9 +85,6 @@ org.apache.pulsar:pulsar-common org.apache.bookkeeper:circe-checksum com.yahoo.datasketches:sketches-core - org.apache.httpcomponents:httpclient - commons-logging:commons-logging - org.apache.httpcomponents:httpcore org.eclipse.jetty:* com.yahoo.datasketches:* commons-*:* @@ -104,12 +101,6 @@ - - commons-logging:commons-logging - - ** - - org.apache.pulsar:pulsar-client-original @@ -165,10 +156,6 @@ com.yahoo.sketches org.apache.pulsar.shade.com.yahoo.sketches - - org.apache.http - org.apache.pulsar.shade.org.apache.http - org.eclipse.jetty org.apache.pulsar.shade.org.eclipse diff --git a/pulsar-client-shaded/pom.xml b/pulsar-client-shaded/pom.xml index 16affa56060a1..22bebe1b26f5d 100644 --- a/pulsar-client-shaded/pom.xml +++ b/pulsar-client-shaded/pom.xml @@ -132,9 +132,6 @@ org.apache.pulsar:pulsar-common org.apache.bookkeeper:circe-checksum com.yahoo.datasketches:sketches-core - org.apache.httpcomponents:httpclient - commons-logging:commons-logging - org.apache.httpcomponents:httpcore org.objenesis:* org.yaml:snakeyaml @@ -167,12 +164,6 @@ ** - - commons-logging:commons-logging - - ** - - @@ -214,10 +205,6 @@ com.yahoo.sketches org.apache.pulsar.shade.com.yahoo.sketches - - org.apache.http - org.apache.pulsar.shade.org.apache.http - org.eclipse.jetty org.apache.pulsar.shade.org.eclipse diff --git a/pulsar-client/pom.xml b/pulsar-client/pom.xml index 69bb9ede4b614..a52465c21129e 100644 --- a/pulsar-client/pom.xml +++ b/pulsar-client/pom.xml @@ -104,17 +104,6 @@ gson - - org.apache.httpcomponents - httpclient - - - * - * - - - - @@ -158,18 +147,6 @@ jcip-annotations - - - commons-logging - commons-logging - 1.1.1 - - - org.apache.httpcomponents - httpcore - 4.4.9 - - ${project.groupId} diff --git a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ClientCnx.java b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ClientCnx.java index 28c880f85e0cd..2b60d486fdbd1 100644 --- a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ClientCnx.java +++ b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ClientCnx.java @@ -52,7 +52,6 @@ import lombok.Getter; import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.lang3.tuple.Pair; -import org.apache.http.conn.ssl.DefaultHostnameVerifier; import org.apache.pulsar.PulsarVersion; import org.apache.pulsar.client.api.Authentication; import org.apache.pulsar.client.api.AuthenticationDataProvider; @@ -60,6 +59,7 @@ import org.apache.pulsar.client.api.PulsarClientException.TimeoutException; import org.apache.pulsar.client.impl.BinaryProtoLookupService.LookupDataResult; import org.apache.pulsar.client.impl.conf.ClientConfigurationData; +import org.apache.pulsar.client.impl.tls.TlsHostnameVerifier; import org.apache.pulsar.common.api.AuthData; import org.apache.pulsar.common.api.proto.PulsarApi; import org.apache.pulsar.common.protocol.Commands; @@ -142,7 +142,7 @@ public class ClientCnx extends PulsarHandler { protected String remoteHostName = null; private boolean isTlsHostnameVerificationEnable; - private static final DefaultHostnameVerifier HOSTNAME_VERIFIER = new DefaultHostnameVerifier(); + private static final TlsHostnameVerifier HOSTNAME_VERIFIER = new TlsHostnameVerifier(); private ScheduledFuture timeoutTask; diff --git a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/DomainType.java b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/DomainType.java new file mode 100644 index 0000000000000..5ed4f67cb9193 --- /dev/null +++ b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/DomainType.java @@ -0,0 +1,31 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.pulsar.client.impl.tls; + +/** + * Domain types differentiated by Mozilla Public Suffix List. + * + * @since 4.5 + */ +public enum DomainType { + + UNKNOWN, ICANN, PRIVATE + +} diff --git a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/InetAddressUtils.java b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/InetAddressUtils.java new file mode 100644 index 0000000000000..1a9bf61f7c13d --- /dev/null +++ b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/InetAddressUtils.java @@ -0,0 +1,117 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * From Apache HTTP client + */ + +package org.apache.pulsar.client.impl.tls; + +import java.util.regex.Pattern; + +/** + * A collection of utilities relating to InetAddresses. + * + * @since 4.0 + */ +public class InetAddressUtils { + + private InetAddressUtils() { + } + + private static final String IPV4_BASIC_PATTERN_STRING = + "(([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){1}" + // initial first field, 1-255 + "(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){2}" + // following 2 fields, 0-255 followed by . + "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])"; // final field, 0-255 + + private static final Pattern IPV4_PATTERN = + Pattern.compile("^" + IPV4_BASIC_PATTERN_STRING + "$"); + + private static final Pattern IPV4_MAPPED_IPV6_PATTERN = // TODO does not allow for redundant leading zeros + Pattern.compile("^::[fF]{4}:" + IPV4_BASIC_PATTERN_STRING + "$"); + + private static final Pattern IPV6_STD_PATTERN = + Pattern.compile( + "^[0-9a-fA-F]{1,4}(:[0-9a-fA-F]{1,4}){7}$"); + + private static final Pattern IPV6_HEX_COMPRESSED_PATTERN = + Pattern.compile( + "^(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,5})?)" + // 0-6 hex fields + "::" + + "(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,5})?)$"); // 0-6 hex fields + + /* + * The above pattern is not totally rigorous as it allows for more than 7 hex fields in total + */ + private static final char COLON_CHAR = ':'; + + // Must not have more than 7 colons (i.e. 8 fields) + private static final int MAX_COLON_COUNT = 7; + + /** + * Checks whether the parameter is a valid IPv4 address + * + * @param input the address string to check for validity + * @return true if the input parameter is a valid IPv4 address + */ + public static boolean isIPv4Address(final String input) { + return IPV4_PATTERN.matcher(input).matches(); + } + + public static boolean isIPv4MappedIPv64Address(final String input) { + return IPV4_MAPPED_IPV6_PATTERN.matcher(input).matches(); + } + + /** + * Checks whether the parameter is a valid standard (non-compressed) IPv6 address + * + * @param input the address string to check for validity + * @return true if the input parameter is a valid standard (non-compressed) IPv6 address + */ + public static boolean isIPv6StdAddress(final String input) { + return IPV6_STD_PATTERN.matcher(input).matches(); + } + + /** + * Checks whether the parameter is a valid compressed IPv6 address + * + * @param input the address string to check for validity + * @return true if the input parameter is a valid compressed IPv6 address + */ + public static boolean isIPv6HexCompressedAddress(final String input) { + int colonCount = 0; + for(int i = 0; i < input.length(); i++) { + if (input.charAt(i) == COLON_CHAR) { + colonCount++; + } + } + return colonCount <= MAX_COLON_COUNT && IPV6_HEX_COMPRESSED_PATTERN.matcher(input).matches(); + } + + /** + * Checks whether the parameter is a valid IPv6 address (including compressed). + * + * @param input the address string to check for validity + * @return true if the input parameter is a valid standard or compressed IPv6 address + */ + public static boolean isIPv6Address(final String input) { + return isIPv6StdAddress(input) || isIPv6HexCompressedAddress(input); + } + +} diff --git a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/NoopHostnameVerifier.java b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/NoopHostnameVerifier.java new file mode 100644 index 0000000000000..7962e3e2cb57c --- /dev/null +++ b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/NoopHostnameVerifier.java @@ -0,0 +1,43 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * From Apache HTTP client + */ + +package org.apache.pulsar.client.impl.tls; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLSession; + +public class NoopHostnameVerifier implements HostnameVerifier { + + public static final NoopHostnameVerifier INSTANCE = new NoopHostnameVerifier(); + + @Override + public boolean verify(final String s, final SSLSession sslSession) { + return true; + } + + @Override + public final String toString() { + return "NO_OP"; + } + +} diff --git a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/PublicSuffixList.java b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/PublicSuffixList.java new file mode 100644 index 0000000000000..eb1671ace54bc --- /dev/null +++ b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/PublicSuffixList.java @@ -0,0 +1,59 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * From Apache HTTP client + */ + +package org.apache.pulsar.client.impl.tls; + +import java.util.Collections; +import java.util.List; + +import lombok.Data; + +/** + * Public suffix is a set of DNS names or wildcards concatenated with dots. It represents the part of a domain name + * which is not under the control of the individual registrant + *

+ * An up-to-date list of suffixes can be obtained from publicsuffix.org + * + * @since 4.4 + */ +@Data +public final class PublicSuffixList { + + private final DomainType type; + private final List rules; + private final List exceptions; + + /** + * @since 4.5 + */ + public PublicSuffixList(final DomainType type, final List rules, final List exceptions) { + this.type = type; + this.rules = Collections.unmodifiableList(rules); + this.exceptions = Collections + .unmodifiableList(exceptions != null ? exceptions : Collections. emptyList()); + } + + public PublicSuffixList(final List rules, final List exceptions) { + this(DomainType.UNKNOWN, rules, exceptions); + } +} diff --git a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/PublicSuffixMatcher.java b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/PublicSuffixMatcher.java new file mode 100644 index 0000000000000..05d2ecaec8715 --- /dev/null +++ b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/PublicSuffixMatcher.java @@ -0,0 +1,192 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * From Apache HTTP client + */ + +package org.apache.pulsar.client.impl.tls; + +import java.net.IDN; +import java.util.Collection; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Utility class that can test if DNS names match the content of the Public Suffix List. + *

+ * An up-to-date list of suffixes can be obtained from + * publicsuffix.org + * + * @see org.apache.pulsar.client.impl.tls.PublicSuffixList + * + * @since 4.4 + */ +public final class PublicSuffixMatcher { + + private final Map rules; + private final Map exceptions; + + public PublicSuffixMatcher(final Collection rules, final Collection exceptions) { + this(DomainType.UNKNOWN, rules, exceptions); + } + + /** + * @since 4.5 + */ + public PublicSuffixMatcher( + final DomainType domainType, final Collection rules, final Collection exceptions) { + this.rules = new ConcurrentHashMap(rules.size()); + for (final String rule: rules) { + this.rules.put(rule, domainType); + } + this.exceptions = new ConcurrentHashMap(); + if (exceptions != null) { + for (final String exception: exceptions) { + this.exceptions.put(exception, domainType); + } + } + } + + /** + * @since 4.5 + */ + public PublicSuffixMatcher(final Collection lists) { + this.rules = new ConcurrentHashMap(); + this.exceptions = new ConcurrentHashMap(); + for (final PublicSuffixList list: lists) { + final DomainType domainType = list.getType(); + final List rules = list.getRules(); + for (final String rule: rules) { + this.rules.put(rule, domainType); + } + final List exceptions = list.getExceptions(); + if (exceptions != null) { + for (final String exception: exceptions) { + this.exceptions.put(exception, domainType); + } + } + } + } + + private static boolean hasEntry(final Map map, final String rule, final DomainType expectedType) { + if (map == null) { + return false; + } + final DomainType domainType = map.get(rule); + if (domainType == null) { + return false; + } else { + return expectedType == null || domainType.equals(expectedType); + } + } + + private boolean hasRule(final String rule, final DomainType expectedType) { + return hasEntry(this.rules, rule, expectedType); + } + + private boolean hasException(final String exception, final DomainType expectedType) { + return hasEntry(this.exceptions, exception, expectedType); + } + + /** + * Returns registrable part of the domain for the given domain name or {@code null} + * if given domain represents a public suffix. + * + * @param domain + * @return domain root + */ + public String getDomainRoot(final String domain) { + return getDomainRoot(domain, null); + } + + /** + * Returns registrable part of the domain for the given domain name or {@code null} + * if given domain represents a public suffix. + * + * @param domain + * @param expectedType expected domain type or {@code null} if any. + * @return domain root + * + * @since 4.5 + */ + public String getDomainRoot(final String domain, final DomainType expectedType) { + if (domain == null) { + return null; + } + if (domain.startsWith(".")) { + return null; + } + String domainName = null; + String segment = domain.toLowerCase(Locale.ROOT); + while (segment != null) { + + // An exception rule takes priority over any other matching rule. + if (hasException(IDN.toUnicode(segment), expectedType)) { + return segment; + } + + if (hasRule(IDN.toUnicode(segment), expectedType)) { + break; + } + + final int nextdot = segment.indexOf('.'); + final String nextSegment = nextdot != -1 ? segment.substring(nextdot + 1) : null; + + if (nextSegment != null) { + if (hasRule("*." + IDN.toUnicode(nextSegment), expectedType)) { + break; + } + } + if (nextdot != -1) { + domainName = segment; + } + segment = nextSegment; + } + return domainName; + } + + /** + * Tests whether the given domain matches any of entry from the public suffix list. + */ + public boolean matches(final String domain) { + return matches(domain, null); + } + + /** + * Tests whether the given domain matches any of entry from the public suffix list. + * + * @param domain + * @param expectedType expected domain type or {@code null} if any. + * @return {@code true} if the given domain matches any of the public suffixes. + * + * @since 4.5 + */ + public boolean matches(final String domain, final DomainType expectedType) { + if (domain == null) { + return false; + } + final String domainRoot = getDomainRoot( + domain.startsWith(".") ? domain.substring(1) : domain, expectedType); + return domainRoot == null; + } + +} diff --git a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/SubjectName.java b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/SubjectName.java new file mode 100644 index 0000000000000..2885b884b9f7b --- /dev/null +++ b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/SubjectName.java @@ -0,0 +1,44 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * From Apache HTTP client + */ + +package org.apache.pulsar.client.impl.tls; + +import lombok.Data; + +@Data +final class SubjectName { + + static final int DNS = 2; + static final int IP = 7; + + private final String value; + private final int type; + + static SubjectName IP(final String value) { + return new SubjectName(value, IP); + } + + static SubjectName DNS(final String value) { + return new SubjectName(value, DNS); + } +} diff --git a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/TlsHostnameVerifier.java b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/TlsHostnameVerifier.java new file mode 100644 index 0000000000000..535765659602f --- /dev/null +++ b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/tls/TlsHostnameVerifier.java @@ -0,0 +1,319 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * From Apache HTTP client + */ + +package org.apache.pulsar.client.impl.tls; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.security.cert.Certificate; +import java.security.cert.CertificateParsingException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.NoSuchElementException; + +import javax.naming.InvalidNameException; +import javax.naming.NamingException; +import javax.naming.directory.Attribute; +import javax.naming.directory.Attributes; +import javax.naming.ldap.LdapName; +import javax.naming.ldap.Rdn; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSession; +import javax.security.auth.x500.X500Principal; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class TlsHostnameVerifier implements HostnameVerifier { + + enum HostNameType { + + IPv4(7), IPv6(7), DNS(2); + + final int subjectType; + + HostNameType(final int subjectType) { + this.subjectType = subjectType; + } + } + + private final PublicSuffixMatcher publicSuffixMatcher; + + public TlsHostnameVerifier(final PublicSuffixMatcher publicSuffixMatcher) { + this.publicSuffixMatcher = publicSuffixMatcher; + } + + public TlsHostnameVerifier() { + this(null); + } + + @Override + public boolean verify(final String host, final SSLSession session) { + try { + final Certificate[] certs = session.getPeerCertificates(); + final X509Certificate x509 = (X509Certificate) certs[0]; + verify(host, x509); + return true; + } catch (final SSLException ex) { + if (log.isDebugEnabled()) { + log.debug(ex.getMessage(), ex); + } + return false; + } + } + + public void verify( + final String host, final X509Certificate cert) throws SSLException { + final HostNameType hostType = determineHostFormat(host); + final List subjectAlts = getSubjectAltNames(cert); + if (subjectAlts != null && !subjectAlts.isEmpty()) { + switch (hostType) { + case IPv4: + matchIPAddress(host, subjectAlts); + break; + case IPv6: + matchIPv6Address(host, subjectAlts); + break; + default: + matchDNSName(host, subjectAlts, this.publicSuffixMatcher); + } + } else { + // CN matching has been deprecated by rfc2818 and can be used + // as fallback only when no subjectAlts are available + final X500Principal subjectPrincipal = cert.getSubjectX500Principal(); + final String cn = extractCN(subjectPrincipal.getName(X500Principal.RFC2253)); + if (cn == null) { + throw new SSLException("Certificate subject for <" + host + "> doesn't contain " + + "a common name and does not have alternative names"); + } + matchCN(host, cn, this.publicSuffixMatcher); + } + } + + static void matchIPAddress(final String host, final List subjectAlts) throws SSLException { + for (int i = 0; i < subjectAlts.size(); i++) { + final SubjectName subjectAlt = subjectAlts.get(i); + if (subjectAlt.getType() == SubjectName.IP) { + if (host.equals(subjectAlt.getValue())) { + return; + } + } + } + throw new SSLPeerUnverifiedException("Certificate for <" + host + "> doesn't match any " + + "of the subject alternative names: " + subjectAlts); + } + + static void matchIPv6Address(final String host, final List subjectAlts) throws SSLException { + final String normalisedHost = normaliseAddress(host); + for (int i = 0; i < subjectAlts.size(); i++) { + final SubjectName subjectAlt = subjectAlts.get(i); + if (subjectAlt.getType() == SubjectName.IP) { + final String normalizedSubjectAlt = normaliseAddress(subjectAlt.getValue()); + if (normalisedHost.equals(normalizedSubjectAlt)) { + return; + } + } + } + throw new SSLPeerUnverifiedException("Certificate for <" + host + "> doesn't match any " + + "of the subject alternative names: " + subjectAlts); + } + + static void matchDNSName(final String host, final List subjectAlts, + final PublicSuffixMatcher publicSuffixMatcher) throws SSLException { + final String normalizedHost = host.toLowerCase(Locale.ROOT); + for (int i = 0; i < subjectAlts.size(); i++) { + final SubjectName subjectAlt = subjectAlts.get(i); + if (subjectAlt.getType() == SubjectName.DNS) { + final String normalizedSubjectAlt = subjectAlt.getValue().toLowerCase(Locale.ROOT); + if (matchIdentityStrict(normalizedHost, normalizedSubjectAlt, publicSuffixMatcher)) { + return; + } + } + } + throw new SSLPeerUnverifiedException("Certificate for <" + host + "> doesn't match any " + + "of the subject alternative names: " + subjectAlts); + } + + static void matchCN(final String host, final String cn, + final PublicSuffixMatcher publicSuffixMatcher) throws SSLException { + final String normalizedHost = host.toLowerCase(Locale.ROOT); + final String normalizedCn = cn.toLowerCase(Locale.ROOT); + if (!matchIdentityStrict(normalizedHost, normalizedCn, publicSuffixMatcher)) { + throw new SSLPeerUnverifiedException("Certificate for <" + host + "> doesn't match " + + "common name of the certificate subject: " + cn); + } + } + + static boolean matchDomainRoot(final String host, final String domainRoot) { + if (domainRoot == null) { + return false; + } + return host.endsWith(domainRoot) && (host.length() == domainRoot.length() + || host.charAt(host.length() - domainRoot.length() - 1) == '.'); + } + + private static boolean matchIdentity(final String host, final String identity, + final PublicSuffixMatcher publicSuffixMatcher, + final boolean strict) { + if (publicSuffixMatcher != null && host.contains(".")) { + if (!matchDomainRoot(host, publicSuffixMatcher.getDomainRoot(identity, DomainType.ICANN))) { + return false; + } + } + + // RFC 2818, 3.1. Server Identity + // "...Names may contain the wildcard + // character * which is considered to match any single domain name + // component or component fragment..." + // Based on this statement presuming only singular wildcard is legal + final int asteriskIdx = identity.indexOf('*'); + if (asteriskIdx != -1) { + final String prefix = identity.substring(0, asteriskIdx); + final String suffix = identity.substring(asteriskIdx + 1); + if (!prefix.isEmpty() && !host.startsWith(prefix)) { + return false; + } + if (!suffix.isEmpty() && !host.endsWith(suffix)) { + return false; + } + // Additional sanity checks on content selected by wildcard can be done here + if (strict) { + final String remainder = host.substring( + prefix.length(), host.length() - suffix.length()); + if (remainder.contains(".")) { + return false; + } + } + return true; + } + return host.equalsIgnoreCase(identity); + } + + static boolean matchIdentity(final String host, final String identity, + final PublicSuffixMatcher publicSuffixMatcher) { + return matchIdentity(host, identity, publicSuffixMatcher, false); + } + + static boolean matchIdentity(final String host, final String identity) { + return matchIdentity(host, identity, null, false); + } + + static boolean matchIdentityStrict(final String host, final String identity, + final PublicSuffixMatcher publicSuffixMatcher) { + return matchIdentity(host, identity, publicSuffixMatcher, true); + } + + static boolean matchIdentityStrict(final String host, final String identity) { + return matchIdentity(host, identity, null, true); + } + + static String extractCN(final String subjectPrincipal) throws SSLException { + if (subjectPrincipal == null) { + return null; + } + try { + final LdapName subjectDN = new LdapName(subjectPrincipal); + final List rdns = subjectDN.getRdns(); + for (int i = rdns.size() - 1; i >= 0; i--) { + final Rdn rds = rdns.get(i); + final Attributes attributes = rds.toAttributes(); + final Attribute cn = attributes.get("cn"); + if (cn != null) { + try { + final Object value = cn.get(); + if (value != null) { + return value.toString(); + } + } catch (final NoSuchElementException ignore) { + // ignore exception + } catch (final NamingException ignore) { + // ignore exception + } + } + } + return null; + } catch (final InvalidNameException e) { + throw new SSLException(subjectPrincipal + " is not a valid X500 distinguished name"); + } + } + + static HostNameType determineHostFormat(final String host) { + if (InetAddressUtils.isIPv4Address(host)) { + return HostNameType.IPv4; + } + String s = host; + if (s.startsWith("[") && s.endsWith("]")) { + s = host.substring(1, host.length() - 1); + } + if (InetAddressUtils.isIPv6Address(s)) { + return HostNameType.IPv6; + } + return HostNameType.DNS; + } + + static List getSubjectAltNames(final X509Certificate cert) { + try { + final Collection> entries = cert.getSubjectAlternativeNames(); + if (entries == null) { + return Collections.emptyList(); + } + final List result = new ArrayList(); + for (final List entry : entries) { + final Integer type = entry.size() >= 2 ? (Integer) entry.get(0) : null; + if (type != null) { + final Object o = entry.get(1); + if (o instanceof String) { + result.add(new SubjectName((String) o, type.intValue())); + } else if (o instanceof byte[]) { + // TODO ASN.1 DER encoded form + } + } + } + return result; + } catch (final CertificateParsingException ignore) { + return Collections.emptyList(); + } + } + + /* + * Normalize IPv6 or DNS name. + */ + static String normaliseAddress(final String hostname) { + if (hostname == null) { + return hostname; + } + try { + final InetAddress inetAddress = InetAddress.getByName(hostname); + return inetAddress.getHostAddress(); + } catch (final UnknownHostException unexpected) { // Should not happen, because we check for IPv6 address above + return hostname; + } + } + +} diff --git a/pulsar-functions/localrun-shaded/pom.xml b/pulsar-functions/localrun-shaded/pom.xml index ff1579047a169..680c6e40923a3 100644 --- a/pulsar-functions/localrun-shaded/pom.xml +++ b/pulsar-functions/localrun-shaded/pom.xml @@ -80,10 +80,6 @@ com.google org.apache.pulsar.functions.runtime.shaded.com.google - - org.apache.http - org.apache.pulsar.functions.runtime.shaded.org.apache.http - org.apache.jute org.apache.pulsar.functions.runtime.shaded.org.apache.jute @@ -254,10 +250,6 @@ jline org.apache.pulsar.functions.runtime.shaded.jline - - commons-logging - org.apache.pulsar.functions.runtime.shaded.commons-logging - org.bouncycastle org.apache.pulsar.functions.runtime.shaded.org.bouncycastle diff --git a/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/DirectProxyHandler.java b/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/DirectProxyHandler.java index e786ba8b69208..23d3ecb2aedca 100644 --- a/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/DirectProxyHandler.java +++ b/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/DirectProxyHandler.java @@ -36,27 +36,28 @@ import io.netty.handler.ssl.SslHandler; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.FutureListener; -import java.util.function.Supplier; -import lombok.Getter; import java.net.URI; import java.net.URISyntaxException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; import javax.net.ssl.SSLSession; -import org.apache.http.conn.ssl.DefaultHostnameVerifier; +import lombok.Getter; + import org.apache.pulsar.PulsarVersion; import org.apache.pulsar.client.api.Authentication; import org.apache.pulsar.client.api.AuthenticationDataProvider; +import org.apache.pulsar.client.impl.tls.TlsHostnameVerifier; import org.apache.pulsar.common.allocator.PulsarByteBufAllocator; import org.apache.pulsar.common.api.AuthData; +import org.apache.pulsar.common.api.proto.PulsarApi.CommandAuthChallenge; +import org.apache.pulsar.common.api.proto.PulsarApi.CommandConnected; import org.apache.pulsar.common.protocol.Commands; import org.apache.pulsar.common.protocol.PulsarDecoder; import org.apache.pulsar.common.stats.Rate; -import org.apache.pulsar.common.api.proto.PulsarApi.CommandAuthChallenge; -import org.apache.pulsar.common.api.proto.PulsarApi.CommandConnected; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -342,7 +343,7 @@ private boolean verifyTlsHostName(String hostname, ChannelHandlerContext ctx) { SSLSession sslSession = null; if (sslHandler != null) { sslSession = ((SslHandler) sslHandler).engine().getSession(); - return (new DefaultHostnameVerifier()).verify(hostname, sslSession); + return (new TlsHostnameVerifier()).verify(hostname, sslSession); } return false; } diff --git a/pulsar-sql/presto-pulsar/pom.xml b/pulsar-sql/presto-pulsar/pom.xml index 73dd85686fc7b..dd92cc8e7a6f2 100644 --- a/pulsar-sql/presto-pulsar/pom.xml +++ b/pulsar-sql/presto-pulsar/pom.xml @@ -124,7 +124,6 @@ javax.annotation:* org.glassfish.hk2*:* - org.apache.httpcomponents:* org.eclipse.jetty:* @@ -158,10 +157,6 @@ org.eclipse.jetty org.apache.pulsar.shade.org.eclipse.jetty - - org.apache.http - org.apache.pulsar.shade.org.apache.http -