This is an automated email from the ASF dual-hosted git repository.

prasanthj pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git


The following commit(s) were added to refs/heads/master by this push:
     new 24313ab  HIVE-21783: Avoid authentication for connection from the same 
domain (Ashutosh Bapat reviewed by Olli Draese, Prasanth Jayachandran)
24313ab is described below

commit 24313ab962b2881317bdcb50e67e90d3da3a5cc2
Author: Prasanth Jayachandran <prasan...@apache.org>
AuthorDate: Thu Jun 13 01:36:39 2019 -0700

    HIVE-21783: Avoid authentication for connection from the same domain 
(Ashutosh Bapat reviewed by Olli Draese, Prasanth Jayachandran)
---
 .../java/org/apache/hadoop/hive/conf/HiveConf.java |   8 +
 .../java/org/apache/hive/minikdc/MiniHiveKdc.java  |  23 ++-
 ...estImproperTrustDomainAuthenticationBinary.java |  28 +++
 .../TestImproperTrustDomainAuthenticationHttp.java |  28 +++
 .../auth/TestTrustDomainAuthenticationBinary.java  |  28 +++
 .../auth/TestTrustDomainAuthenticationHttp.java    |  28 +++
 .../auth/TrustDomainAuthenticationTest.java        | 192 +++++++++++++++++++++
 .../apache/hive/service/auth/HiveAuthFactory.java  |   5 +
 .../apache/hive/service/auth/PlainSaslHelper.java  |  54 ++++++
 .../hive/service/cli/thrift/ThriftHttpServlet.java |  53 ++++--
 10 files changed, 422 insertions(+), 25 deletions(-)

diff --git a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java 
b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java
index 2cea174..03a8019 100644
--- a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java
+++ b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java
@@ -3478,6 +3478,14 @@ public class HiveConf extends Configuration {
         "          (Use with property 
hive.server2.custom.authentication.class)\n" +
         "  PAM: Pluggable authentication module\n" +
         "  NOSASL:  Raw transport"),
+    HIVE_SERVER2_TRUSTED_DOMAIN("hive.server2.trusted.domain", "",
+        "Specifies the host or a domain to trust connections from. 
Authentication is skipped " +
+        "for any connection coming from a host whose hostname ends with the 
value of this" +
+        " property. If authentication is expected to be skipped for 
connections from " +
+        "only a given host, fully qualified hostname of that host should be 
specified. By default" +
+        " it is empty, which means that all the connections to HiveServer2 are 
authenticated. " +
+        "When it is non-empty, the client has to provide a Hive user name. Any 
password, if " +
+        "provided, will not be used when authentication is skipped."),
     
HIVE_SERVER2_ALLOW_USER_SUBSTITUTION("hive.server2.allow.user.substitution", 
true,
         "Allow alternate user to be specified as part of HiveServer2 open 
connection request."),
     
HIVE_SERVER2_KERBEROS_KEYTAB("hive.server2.authentication.kerberos.keytab", "",
diff --git 
a/itests/hive-minikdc/src/test/java/org/apache/hive/minikdc/MiniHiveKdc.java 
b/itests/hive-minikdc/src/test/java/org/apache/hive/minikdc/MiniHiveKdc.java
index 7d1192a..e604f90 100644
--- a/itests/hive-minikdc/src/test/java/org/apache/hive/minikdc/MiniHiveKdc.java
+++ b/itests/hive-minikdc/src/test/java/org/apache/hive/minikdc/MiniHiveKdc.java
@@ -36,6 +36,7 @@ import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.hive.jdbc.miniHS2.MiniHS2;
 
 import com.google.common.io.Files;
+import org.apache.hive.service.server.HiveServer2;
 
 /**
  * Wrapper around Hadoop's MiniKdc for use in hive tests.
@@ -178,15 +179,21 @@ public class MiniHiveKdc {
   * @return new MiniHS2 instance
   * @throws Exception
   */
- public static MiniHS2 getMiniHS2WithKerb(MiniHiveKdc miniHiveKdc, HiveConf 
hiveConf,
+  public static MiniHS2 getMiniHS2WithKerb(MiniHiveKdc miniHiveKdc, HiveConf 
hiveConf,
      String authType) throws Exception {
-   String hivePrincipal =
-       
miniHiveKdc.getFullyQualifiedServicePrincipal(MiniHiveKdc.HIVE_SERVICE_PRINCIPAL);
-   String hiveKeytab = miniHiveKdc.getKeyTabFile(
-       
miniHiveKdc.getServicePrincipalForUser(MiniHiveKdc.HIVE_SERVICE_PRINCIPAL));
-
-   return new MiniHS2.Builder().withConf(hiveConf).withMiniKdc(hivePrincipal, 
hiveKeytab).
-       withAuthenticationType(authType).build();
+    String hivePrincipal =
+            
miniHiveKdc.getFullyQualifiedServicePrincipal(MiniHiveKdc.HIVE_SERVICE_PRINCIPAL);
+    String hiveKeytab = miniHiveKdc.getKeyTabFile(
+            
miniHiveKdc.getServicePrincipalForUser(MiniHiveKdc.HIVE_SERVICE_PRINCIPAL));
+
+    MiniHS2.Builder miniHS2Builder = new MiniHS2.Builder()
+                                              .withConf(hiveConf)
+                                              .withMiniKdc(hivePrincipal, 
hiveKeytab)
+                                              
.withAuthenticationType(authType);
+    if (HiveServer2.isHTTPTransportMode(hiveConf)) {
+      miniHS2Builder.withHTTPTransport();
+    }
+    return miniHS2Builder.build();
  }
 
   /**
diff --git 
a/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestImproperTrustDomainAuthenticationBinary.java
 
b/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestImproperTrustDomainAuthenticationBinary.java
new file mode 100644
index 0000000..b7a8bec
--- /dev/null
+++ 
b/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestImproperTrustDomainAuthenticationBinary.java
@@ -0,0 +1,28 @@
+/*
+ * 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.hive.service.auth;
+
+import org.junit.BeforeClass;
+
+public class TestImproperTrustDomainAuthenticationBinary extends 
TrustDomainAuthenticationTest {
+
+    @BeforeClass
+    public static void setUp() throws Exception {
+        initialize(HS2_TRANSPORT_MODE_BINARY, false);
+    }
+}
diff --git 
a/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestImproperTrustDomainAuthenticationHttp.java
 
b/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestImproperTrustDomainAuthenticationHttp.java
new file mode 100644
index 0000000..57bcf4f
--- /dev/null
+++ 
b/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestImproperTrustDomainAuthenticationHttp.java
@@ -0,0 +1,28 @@
+/*
+ * 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.hive.service.auth;
+
+import org.junit.BeforeClass;
+
+public class TestImproperTrustDomainAuthenticationHttp extends 
TrustDomainAuthenticationTest {
+
+    @BeforeClass
+    public static void setUp() throws Exception {
+        initialize(HS2_TRANSPORT_MODE_HTTP, false);
+    }
+}
diff --git 
a/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestTrustDomainAuthenticationBinary.java
 
b/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestTrustDomainAuthenticationBinary.java
new file mode 100644
index 0000000..8f6d0b5
--- /dev/null
+++ 
b/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestTrustDomainAuthenticationBinary.java
@@ -0,0 +1,28 @@
+/*
+ * 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.hive.service.auth;
+
+import org.junit.BeforeClass;
+
+public class TestTrustDomainAuthenticationBinary extends 
TrustDomainAuthenticationTest {
+
+    @BeforeClass
+    public static void setUp() throws Exception {
+        initialize(HS2_TRANSPORT_MODE_BINARY, true);
+    }
+}
diff --git 
a/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestTrustDomainAuthenticationHttp.java
 
b/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestTrustDomainAuthenticationHttp.java
new file mode 100644
index 0000000..50b195a
--- /dev/null
+++ 
b/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TestTrustDomainAuthenticationHttp.java
@@ -0,0 +1,28 @@
+/*
+ * 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.hive.service.auth;
+
+import org.junit.BeforeClass;
+
+public class TestTrustDomainAuthenticationHttp extends 
TrustDomainAuthenticationTest {
+
+    @BeforeClass
+    public static void setUp() throws Exception {
+        initialize(HS2_TRANSPORT_MODE_HTTP, true);
+    }
+}
diff --git 
a/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TrustDomainAuthenticationTest.java
 
b/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TrustDomainAuthenticationTest.java
new file mode 100644
index 0000000..3eba95c
--- /dev/null
+++ 
b/itests/hive-unit/src/test/java/org/apache/hive/service/auth/TrustDomainAuthenticationTest.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.
+ */
+package org.apache.hive.service.auth;
+
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.apache.hive.service.server.HiveServer2;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.security.sasl.AuthenticationException;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class TrustDomainAuthenticationTest {
+  private static final Logger LOG = 
LoggerFactory.getLogger(TrustDomainAuthenticationTest.class);
+  private static HiveServer2 hiveserver2;
+  private static HiveConf hiveConf;
+  private static byte[] hiveConfBackup;
+  private static String correctUser = "hive";
+  private static String correctPassword = "passwd";
+  private static String wrongPassword = "wrong_password";
+  private static String wrongUser = "wrong_user";
+  static final String HS2_TRANSPORT_MODE_BINARY = "binary";
+  static final String HS2_TRANSPORT_MODE_HTTP = "http";
+  private static String hs2TransportMode;
+  private static boolean properTrustedDomain;
+
+  static void initialize(String transportMode, boolean useProperTrustedDomain) 
throws Exception {
+    Assert.assertNotNull(transportMode);
+    Assert.assertTrue(transportMode.equals(HS2_TRANSPORT_MODE_HTTP) ||
+            transportMode.equals(HS2_TRANSPORT_MODE_BINARY));
+    hs2TransportMode = transportMode;
+    properTrustedDomain = useProperTrustedDomain;
+
+    hiveConf = new HiveConf();
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    hiveConf.writeXml(baos);
+    baos.close();
+    hiveConfBackup = baos.toByteArray();
+    hiveConf.setVar(HiveConf.ConfVars.HIVE_SERVER2_TRANSPORT_MODE, 
hs2TransportMode);
+    hiveConf.setVar(HiveConf.ConfVars.HIVE_SERVER2_AUTHENTICATION, "CUSTOM");
+
+    // These tests run locally and hence all connections are from localhost. 
So, when we want to
+    // test whether trusted domain setting works, use "localhost". When we 
want to test
+    // otherwise, use some string other than that. Other authentication tests 
test empty trusted
+    // domain so that's not covered under these tests.
+    hiveConf.setVar(HiveConf.ConfVars.HIVE_SERVER2_TRUSTED_DOMAIN,
+            properTrustedDomain ? "localhost" : "no_such_domain");
+    hiveConf.setVar(HiveConf.ConfVars.HIVE_SERVER2_CUSTOM_AUTHENTICATION_CLASS,
+            
"org.apache.hive.service.auth.TrustDomainAuthenticationTest$SimpleAuthenticationProviderImpl");
+    FileOutputStream fos = new FileOutputStream(new 
File(hiveConf.getHiveSiteLocation().toURI()));
+    hiveConf.writeXml(fos);
+    fos.close();
+    hiveserver2 = new HiveServer2();
+    hiveserver2.init(hiveConf);
+    hiveserver2.start();
+    Thread.sleep(1000);
+    LOG.info("hiveServer2 start ......");
+  }
+
+  @AfterClass
+  public static void tearDown() throws Exception {
+    if(hiveConf != null && hiveConfBackup != null) {
+      FileOutputStream fos = new FileOutputStream(new 
File(hiveConf.getHiveSiteLocation().toURI()));
+      fos.write(hiveConfBackup);
+      fos.close();
+    }
+    if (hiveserver2 != null) {
+      hiveserver2.stop();
+      hiveserver2 = null;
+    }
+    Thread.sleep(1000);
+    LOG.info("hiveServer2 stop ......");
+  }
+
+  // TODO: This test doesn't work since getRemoteHost returns IP address 
instead of a host name
+  @Test
+  public void testTrustedDomainAuthentication() throws Exception {
+    String port = "10000";
+    String urlExtra = "";
+    if (hs2TransportMode.equals(HS2_TRANSPORT_MODE_HTTP)) {
+      port = "10001";
+      urlExtra = ";transportMode=http;httpPath=cliservice";
+    }
+
+    String url = "jdbc:hive2://localhost:" + port + "/default" + urlExtra;
+    Class.forName("org.apache.hive.jdbc.HiveDriver");
+
+    if (properTrustedDomain) {
+      testProperTrustedDomainAuthentication(url);
+    } else {
+      testImproperTrustedDomainAuthentication(url);
+    }
+  }
+
+  private void testProperTrustedDomainAuthentication(String url) throws 
SQLException {
+    // When the connection is from a trusted domain any connection is 
authentic irrespective of
+    // user and password
+    Connection connection = DriverManager.getConnection(url, correctUser, 
correctPassword);
+    connection.close();
+
+    connection = DriverManager.getConnection(url, wrongUser, correctPassword);
+    connection.close();
+
+    connection = DriverManager.getConnection(url, wrongUser, wrongPassword);
+    connection.close();
+
+    connection = DriverManager.getConnection(url, correctUser, wrongPassword);
+    connection.close();
+  }
+
+  private void testImproperTrustedDomainAuthentication(String url) throws 
Exception {
+    // When trusted domain doesn't match requests domain, only the connection 
with correct user
+    // and password goes through.
+    Connection connection = DriverManager.getConnection(url, correctUser, 
correctPassword);
+    connection.close();
+
+    String partErrorMessage = "Peer indicated failure: Error validating the 
login";
+    if (hs2TransportMode.equals(HS2_TRANSPORT_MODE_HTTP)) {
+      partErrorMessage = "HTTP Response code: 401";
+    }
+
+    try (Connection conn = DriverManager.getConnection(url, wrongUser, 
correctPassword)) {
+      Assert.fail("Expected Exception");
+    } catch (SQLException e) {
+      Assert.assertNotNull(e.getMessage());
+      Assert.assertTrue(e.getMessage(), 
e.getMessage().contains(partErrorMessage));
+    }
+
+    try (Connection conn = DriverManager.getConnection(url, wrongUser, 
wrongPassword)) {
+      Assert.fail("Expected Exception");
+    } catch (SQLException e) {
+      Assert.assertNotNull(e.getMessage());
+      Assert.assertTrue(e.getMessage(), 
e.getMessage().contains(partErrorMessage));
+    }
+
+    try (Connection conn = DriverManager.getConnection(url, correctUser, 
wrongPassword)) {
+      Assert.fail("Expected Exception");
+    } catch (SQLException e) {
+      Assert.assertNotNull(e.getMessage());
+      Assert.assertTrue(e.getMessage(), 
e.getMessage().contains(partErrorMessage));
+    }
+  }
+
+  public static class SimpleAuthenticationProviderImpl implements 
PasswdAuthenticationProvider {
+
+    private Map<String, String> userMap = new HashMap<String, String>();
+
+    public SimpleAuthenticationProviderImpl() {
+      init();
+    }
+
+    private void init(){
+      userMap.put(correctUser, correctPassword);
+    }
+
+    @Override
+    public void Authenticate(String user, String password) throws 
AuthenticationException {
+
+      if(!userMap.containsKey(user)){
+        throw new AuthenticationException("Invalid user : "+user);
+      }
+      if(!userMap.get(user).equals(password)){
+        throw new AuthenticationException("Invalid passwd : "+password);
+      }
+    }
+  }
+}
diff --git a/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java 
b/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java
index f5f6d49..e07cd7e 100644
--- a/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java
+++ b/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java
@@ -161,6 +161,11 @@ public class HiveAuthFactory {
     } else {
       throw new LoginException("Unsupported authentication type " + 
authTypeStr);
     }
+
+    String trustedDomain = HiveConf.getVar(conf, 
ConfVars.HIVE_SERVER2_TRUSTED_DOMAIN).trim();
+    if (!trustedDomain.isEmpty()) {
+      transportFactory = 
PlainSaslHelper.getDualPlainTransportFactory(transportFactory, trustedDomain);
+    }
     return transportFactory;
   }
 
diff --git a/service/src/java/org/apache/hive/service/auth/PlainSaslHelper.java 
b/service/src/java/org/apache/hive/service/auth/PlainSaslHelper.java
index 13a1a38..0742311 100644
--- a/service/src/java/org/apache/hive/service/auth/PlainSaslHelper.java
+++ b/service/src/java/org/apache/hive/service/auth/PlainSaslHelper.java
@@ -18,6 +18,7 @@
 package org.apache.hive.service.auth;
 
 import java.io.IOException;
+import java.net.InetAddress;
 import java.security.Security;
 import java.util.HashMap;
 
@@ -39,10 +40,14 @@ import org.apache.thrift.TProcessor;
 import org.apache.thrift.TProcessorFactory;
 import org.apache.thrift.transport.TSaslClientTransport;
 import org.apache.thrift.transport.TSaslServerTransport;
+import org.apache.thrift.transport.TSocket;
 import org.apache.thrift.transport.TTransport;
 import org.apache.thrift.transport.TTransportFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public final class PlainSaslHelper {
+  private static final Logger LOG = 
LoggerFactory.getLogger(PlainSaslHelper.class);
 
   public static TProcessorFactory getPlainProcessorFactory(ThriftCLIService 
service) {
     return new SQLPlainProcessorFactory(service);
@@ -65,16 +70,65 @@ public final class PlainSaslHelper {
     return saslFactory;
   }
 
+  static TTransportFactory getDualPlainTransportFactory(TTransportFactory 
otherTrans,
+                                                        String trustedDomain)
+          throws LoginException {
+    LOG.info("Created additional transport factory for skipping authentication 
when client " +
+            "connection is from the same domain.");
+    return new DualSaslTransportFactory(otherTrans, trustedDomain);
+  }
+
   public static TTransport getPlainTransport(String username, String password,
     TTransport underlyingTransport) throws SaslException {
     return new TSaslClientTransport("PLAIN", null, null, null, new 
HashMap<String, String>(),
       new PlainCallbackHandler(username, password), underlyingTransport);
   }
 
+  // Return true if the remote host is from the trusted domain, i.e. host URL 
has the same
+  // suffix as the trusted domain.
+  static public boolean isHostFromTrustedDomain(String remoteHost, String 
trustedDomain) {
+    return remoteHost.endsWith(trustedDomain);
+  }
+
   private PlainSaslHelper() {
     throw new UnsupportedOperationException("Can't initialize class");
   }
 
+  static final class DualSaslTransportFactory extends TTransportFactory {
+    TTransportFactory otherFactory;
+    TTransportFactory noAuthFactory;
+    String trustedDomain;
+
+    DualSaslTransportFactory(TTransportFactory otherFactory, String 
trustedDomain)
+            throws LoginException {
+      this.noAuthFactory = 
getPlainTransportFactory(AuthMethods.NONE.toString());
+      this.otherFactory = otherFactory;
+      this.trustedDomain = trustedDomain;
+    }
+
+    @Override
+    public TTransport getTransport(final TTransport trans) {
+      TSocket tSocket = null;
+      // Attempt to avoid authentication if only we can fetch the client IP 
address and it
+      // happens to be from the same domain as the server.
+      if (trans instanceof TSocket) {
+        tSocket = (TSocket) trans;
+      } else if (trans instanceof TSaslServerTransport) {
+        TSaslServerTransport saslTrans = (TSaslServerTransport) trans;
+        tSocket = (TSocket)(saslTrans.getUnderlyingTransport());
+      }
+      String remoteHost = tSocket != null ?
+              tSocket.getSocket().getInetAddress().getCanonicalHostName() : 
null;
+      if (remoteHost != null && isHostFromTrustedDomain(remoteHost, 
trustedDomain)) {
+        LOG.info("No authentication performed because the connecting host " + 
remoteHost + " is " +
+                "from the trusted domain " + trustedDomain);
+        return noAuthFactory.getTransport(trans);
+      }
+
+      return otherFactory.getTransport(trans);
+    }
+  }
+
   public static final class PlainServerCallbackHandler implements 
CallbackHandler {
 
     private final AuthMethods authMethod;
diff --git 
a/service/src/java/org/apache/hive/service/cli/thrift/ThriftHttpServlet.java 
b/service/src/java/org/apache/hive/service/cli/thrift/ThriftHttpServlet.java
index ff8f268..292723e 100644
--- a/service/src/java/org/apache/hive/service/cli/thrift/ThriftHttpServlet.java
+++ b/service/src/java/org/apache/hive/service/cli/thrift/ThriftHttpServlet.java
@@ -52,6 +52,7 @@ import org.apache.hive.service.auth.HiveAuthFactory;
 import org.apache.hive.service.auth.HttpAuthUtils;
 import org.apache.hive.service.auth.HttpAuthenticationException;
 import org.apache.hive.service.auth.PasswdAuthenticationProvider;
+import org.apache.hive.service.auth.PlainSaslHelper;
 import org.apache.hive.service.auth.ldap.HttpEmptyAuthenticationException;
 import org.apache.hive.service.cli.HiveSQLException;
 import org.apache.hive.service.cli.session.SessionManager;
@@ -137,6 +138,9 @@ public class ThriftHttpServlet extends TServlet {
           return;
         }
       }
+
+      clientIpAddress = request.getRemoteAddr();
+      LOG.debug("Client IP Address: " + clientIpAddress);
       // If the cookie based authentication is already enabled, parse the
       // request and validate the request cookies.
       if (isCookieAuthEnabled) {
@@ -146,25 +150,42 @@ public class ThriftHttpServlet extends TServlet {
           LOG.info("Could not validate cookie sent, will try to generate a new 
cookie");
         }
       }
-      // If the cookie based authentication is not enabled or the request does
-      // not have a valid cookie, use the kerberos or password based 
authentication
-      // depending on the server setup.
+      // If the cookie based authentication is not enabled or the request does 
not have a valid
+      // cookie, use authentication depending on the server setup.
       if (clientUserName == null) {
-        // For a kerberos setup
-        if (isKerberosAuthMode(authType)) {
-          String delegationToken = 
request.getHeader(HIVE_DELEGATION_TOKEN_HEADER);
-          // Each http request must have an Authorization header
-          if ((delegationToken != null) && (!delegationToken.isEmpty())) {
-            clientUserName = doTokenAuth(request, response);
-          } else {
-            clientUserName = doKerberosAuth(request);
+        String trustedDomain = HiveConf.getVar(hiveConf, 
ConfVars.HIVE_SERVER2_TRUSTED_DOMAIN).trim();
+
+        // Skip authentication if the connection is from the trusted domain, 
if specified.
+        // getRemoteHost may or may not return the FQDN of the remote host 
depending upon the
+        // HTTP server configuration. So, force a reverse DNS lookup.
+        String remoteHostName =
+                
InetAddress.getByName(request.getRemoteHost()).getCanonicalHostName();
+        if (!trustedDomain.isEmpty() &&
+                PlainSaslHelper.isHostFromTrustedDomain(remoteHostName, 
trustedDomain)) {
+          LOG.info("No authentication performed because the connecting host " 
+ remoteHostName +
+                  " is from the trusted domain " + trustedDomain);
+          // In order to skip authentication, we use auth type NOSASL to be 
consistent with the
+          // HiveAuthFactory defaults. In HTTP mode, it will also get us the 
user name from the
+          // HTTP request header.
+          clientUserName = doPasswdAuth(request, 
HiveAuthConstants.AuthTypes.NOSASL.getAuthName());
+        } else {
+          // For a kerberos setup
+          if (isKerberosAuthMode(authType)) {
+            String delegationToken = 
request.getHeader(HIVE_DELEGATION_TOKEN_HEADER);
+            // Each http request must have an Authorization header
+            if ((delegationToken != null) && (!delegationToken.isEmpty())) {
+              clientUserName = doTokenAuth(request, response);
+            } else {
+              clientUserName = doKerberosAuth(request);
+            }
+          }
+          // For password based authentication
+          else {
+            clientUserName = doPasswdAuth(request, authType);
           }
-        }
-        // For password based authentication
-        else {
-          clientUserName = doPasswdAuth(request, authType);
         }
       }
+      assert (clientUserName != null);
       LOG.debug("Client username: " + clientUserName);
 
       // Set the thread local username to be used for doAs if true
@@ -176,8 +197,6 @@ public class ThriftHttpServlet extends TServlet {
         SessionManager.setProxyUserName(doAsQueryParam);
       }
 
-      clientIpAddress = request.getRemoteAddr();
-      LOG.debug("Client IP Address: " + clientIpAddress);
       // Set the thread local ip address
       SessionManager.setIpAddress(clientIpAddress);
 

Reply via email to