Apache9 commented on code in PR #4724:
URL: https://github.com/apache/hbase/pull/4724#discussion_r974435240


##########
hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/tls/HBaseTrustManager.java:
##########
@@ -0,0 +1,160 @@
+/*
+ * 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.hadoop.hbase.io.crypto.tls;
+
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.X509ExtendedTrustManager;
+import org.apache.yetus.audience.InterfaceAudience;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A custom TrustManager that supports hostname verification We attempt to 
perform verification
+ * using just the IP address first and if that fails will attempt to perform a 
reverse DNS lookup
+ * and verify using the hostname. This file has been copied from the Apache 
ZooKeeper project.
+ * @see <a href=
+ *      
"https://github.com/apache/zookeeper/blob/c74658d398cdc1d207aa296cb6e20de00faec03e/zookeeper-server/src/main/java/org/apache/zookeeper/common/ZKTrustManager.java";>Base
+ *      revision</a>
+ */
[email protected]
+public class HBaseTrustManager extends X509ExtendedTrustManager {
+
+  private static final Logger LOG = 
LoggerFactory.getLogger(HBaseTrustManager.class);
+
+  private final X509ExtendedTrustManager x509ExtendedTrustManager;
+  private final boolean serverHostnameVerificationEnabled;
+  private final boolean clientHostnameVerificationEnabled;
+
+  private final HBaseHostnameVerifier hostnameVerifier;
+
+  /**
+   * Instantiate a new HBaseTrustManager.
+   * @param x509ExtendedTrustManager          The trustmanager to use for
+   *                                          
checkClientTrusted/checkServerTrusted logic
+   * @param serverHostnameVerificationEnabled If true, this TrustManager 
should verify hostnames of
+   *                                          servers that this instance 
connects to.
+   * @param clientHostnameVerificationEnabled If true, the hostname of a 
client connecting to this
+   *                                          machine will be verified.
+   */
+  HBaseTrustManager(X509ExtendedTrustManager x509ExtendedTrustManager,
+    boolean serverHostnameVerificationEnabled, boolean 
clientHostnameVerificationEnabled) {
+    this.x509ExtendedTrustManager = x509ExtendedTrustManager;
+    this.serverHostnameVerificationEnabled = serverHostnameVerificationEnabled;
+    this.clientHostnameVerificationEnabled = clientHostnameVerificationEnabled;
+    this.hostnameVerifier = new HBaseHostnameVerifier();
+  }
+
+  @Override
+  public X509Certificate[] getAcceptedIssuers() {
+    return x509ExtendedTrustManager.getAcceptedIssuers();
+  }
+
+  @Override
+  public void checkClientTrusted(X509Certificate[] chain, String authType, 
Socket socket)
+    throws CertificateException {
+    x509ExtendedTrustManager.checkClientTrusted(chain, authType, socket);
+    if (clientHostnameVerificationEnabled) {
+      performHostVerification(socket.getInetAddress(), chain[0]);
+    }
+  }
+
+  @Override
+  public void checkServerTrusted(X509Certificate[] chain, String authType, 
Socket socket)
+    throws CertificateException {
+    x509ExtendedTrustManager.checkServerTrusted(chain, authType, socket);
+    if (serverHostnameVerificationEnabled) {
+      performHostVerification(socket.getInetAddress(), chain[0]);
+    }
+  }
+
+  @Override
+  public void checkClientTrusted(X509Certificate[] chain, String authType, 
SSLEngine engine)
+    throws CertificateException {
+    x509ExtendedTrustManager.checkClientTrusted(chain, authType, engine);
+    if (clientHostnameVerificationEnabled) {
+      try {
+        performHostVerification(InetAddress.getByName(engine.getPeerHost()), 
chain[0]);
+      } catch (UnknownHostException e) {
+        throw new CertificateException("Failed to verify host", e);
+      }
+    }
+  }
+
+  @Override
+  public void checkServerTrusted(X509Certificate[] chain, String authType, 
SSLEngine engine)
+    throws CertificateException {
+    x509ExtendedTrustManager.checkServerTrusted(chain, authType, engine);
+    if (serverHostnameVerificationEnabled) {
+      try {
+        performHostVerification(InetAddress.getByName(engine.getPeerHost()), 
chain[0]);
+      } catch (UnknownHostException e) {
+        throw new CertificateException("Failed to verify host", e);
+      }
+    }
+  }
+
+  @Override
+  public void checkClientTrusted(X509Certificate[] chain, String authType)
+    throws CertificateException {
+    x509ExtendedTrustManager.checkClientTrusted(chain, authType);
+  }
+
+  @Override
+  public void checkServerTrusted(X509Certificate[] chain, String authType)
+    throws CertificateException {
+    x509ExtendedTrustManager.checkServerTrusted(chain, authType);
+  }
+
+  /**
+   * Compares peer's hostname with the one stored in the provided client 
certificate. Performs
+   * verification with the help of provided HostnameVerifier.
+   * @param inetAddress Peer's inet address.
+   * @param certificate Peer's certificate
+   * @throws CertificateException Thrown if the provided certificate doesn't 
match the peer
+   *                              hostname.
+   */
+  private void performHostVerification(InetAddress inetAddress, 
X509Certificate certificate)
+    throws CertificateException {
+    String hostAddress = "";
+    String hostName = "";
+    try {
+      hostAddress = inetAddress.getHostAddress();
+      hostnameVerifier.verify(hostAddress, certificate);
+    } catch (SSLException addressVerificationException) {
+      try {

Review Comment:
   For a client, usually we need to use reverse dns to get its hostname, but 
for a server, usually we will use a hostname when connecting, so we should just 
check the host name first? But probably the algo here only adds an extra 
verification, as we will create the InetAddress with hostname so there is no 
reverse lookup when calling inetAddress.getHostName.



##########
hbase-common/src/main/java/org/apache/hadoop/hbase/io/crypto/tls/HBaseHostnameVerifier.java:
##########
@@ -0,0 +1,368 @@
+/*
+ * 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.hadoop.hbase.io.crypto.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 java.util.Objects;
+import java.util.regex.Pattern;
+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 org.apache.yetus.audience.InterfaceAudience;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * When enabled in {@link X509Util}, handles verifying that the hostname of a 
peer matches the
+ * certificate it presents.
+ * <p/>
+ * This file has been copied from the Apache ZooKeeper project.
+ * @see <a href=

Review Comment:
   I think this file is mainly copy of the one in HttpClient?
   
   
https://github.com/apache/httpcomponents-client/blob/master/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/DefaultHostnameVerifier.java



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to