diff --git a/data/files/keystore.jks b/data/files/keystore.jks index 469d8a5..8f35af0 100644 Binary files a/data/files/keystore.jks and b/data/files/keystore.jks differ diff --git a/data/files/keystore_exampledotcom.jks b/data/files/keystore_exampledotcom.jks new file mode 100644 index 0000000..1d33aad Binary files /dev/null and b/data/files/keystore_exampledotcom.jks differ diff --git a/data/files/truststore.jks b/data/files/truststore.jks index 9c5d703..03dd2a3 100644 Binary files a/data/files/truststore.jks and b/data/files/truststore.jks differ diff --git a/itests/hive-unit/src/main/java/org/apache/hive/jdbc/miniHS2/MiniHS2.java b/itests/hive-unit/src/main/java/org/apache/hive/jdbc/miniHS2/MiniHS2.java index adb8a71..096c76f 100644 --- a/itests/hive-unit/src/main/java/org/apache/hive/jdbc/miniHS2/MiniHS2.java +++ b/itests/hive-unit/src/main/java/org/apache/hive/jdbc/miniHS2/MiniHS2.java @@ -300,8 +300,9 @@ public CLIServiceClient getServiceClientInternal() { /** * return connection URL for this server instance * @return + * @throws Exception */ - public String getJdbcURL() { + public String getJdbcURL() throws Exception { return getJdbcURL("default"); } @@ -309,8 +310,9 @@ public String getJdbcURL() { * return connection URL for this server instance * @param dbName - DB name to be included in the URL * @return + * @throws Exception */ - public String getJdbcURL(String dbName) { + public String getJdbcURL(String dbName) throws Exception { return getJdbcURL(dbName, ""); } @@ -319,8 +321,9 @@ public String getJdbcURL(String dbName) { * @param dbName - DB name to be included in the URL * @param sessionConfExt - Addional string to be appended to sessionConf part of url * @return + * @throws Exception */ - public String getJdbcURL(String dbName, String sessionConfExt) { + public String getJdbcURL(String dbName, String sessionConfExt) throws Exception { return getJdbcURL(dbName, sessionConfExt, ""); } @@ -330,22 +333,32 @@ public String getJdbcURL(String dbName, String sessionConfExt) { * @param sessionConfExt - Addional string to be appended to sessionConf part of url * @param hiveConfExt - Additional string to be appended to HiveConf part of url (excluding the ?) * @return + * @throws Exception */ - public String getJdbcURL(String dbName, String sessionConfExt, String hiveConfExt) { + public String getJdbcURL(String dbName, String sessionConfExt, String hiveConfExt) + throws Exception { sessionConfExt = (sessionConfExt == null ? "" : sessionConfExt); hiveConfExt = (hiveConfExt == null ? "" : hiveConfExt); - String krbConfig = ""; + // Strip the leading ";" if provided + // (this is the assumption with which we're going to start configuring sessionConfExt) + if (sessionConfExt.startsWith(";")) { + sessionConfExt = sessionConfExt.substring(1); + } if (isUseMiniKdc()) { - krbConfig = ";principal=" + serverPrincipal; + sessionConfExt = "principal=" + serverPrincipal + ";" + sessionConfExt; } if (isHttpTransportMode()) { - hiveConfExt = "hive.server2.transport.mode=http;hive.server2.thrift.http.path=cliservice;" - + hiveConfExt; + sessionConfExt = "transportMode=http;httpPath=cliservice" + ";" + sessionConfExt; + } + String baseJdbcURL = getBaseJdbcURL(); + baseJdbcURL = baseJdbcURL + dbName; + if (!sessionConfExt.isEmpty()) { + baseJdbcURL = baseJdbcURL + ";" + sessionConfExt; } - if (!hiveConfExt.trim().equals("")) { - hiveConfExt = "?" + hiveConfExt; + if ((hiveConfExt != null) && (!hiveConfExt.trim().isEmpty())) { + baseJdbcURL = baseJdbcURL + "?" + hiveConfExt; } - return getBaseJdbcURL() + dbName + krbConfig + sessionConfExt + hiveConfExt; + return baseJdbcURL; } /** diff --git a/itests/hive-unit/src/test/java/org/apache/hive/jdbc/TestJdbcWithLocalClusterSpark.java b/itests/hive-unit/src/test/java/org/apache/hive/jdbc/TestJdbcWithLocalClusterSpark.java index f649fc2..cabddea 100644 --- a/itests/hive-unit/src/test/java/org/apache/hive/jdbc/TestJdbcWithLocalClusterSpark.java +++ b/itests/hive-unit/src/test/java/org/apache/hive/jdbc/TestJdbcWithLocalClusterSpark.java @@ -92,7 +92,7 @@ public static void beforeTest() throws Exception { } // setup DB - private static void createDb() throws SQLException { + private static void createDb() throws Exception { Connection conn = DriverManager. getConnection(miniHS2.getJdbcURL(), System.getProperty("user.name"), "bar"); Statement stmt2 = conn.createStatement(); diff --git a/itests/hive-unit/src/test/java/org/apache/hive/jdbc/TestJdbcWithMiniMr.java b/itests/hive-unit/src/test/java/org/apache/hive/jdbc/TestJdbcWithMiniMr.java index bcd65a9..637e51a 100644 --- a/itests/hive-unit/src/test/java/org/apache/hive/jdbc/TestJdbcWithMiniMr.java +++ b/itests/hive-unit/src/test/java/org/apache/hive/jdbc/TestJdbcWithMiniMr.java @@ -83,7 +83,7 @@ public static void beforeTest() throws Exception { } // setup DB - private static void createDb() throws SQLException { + private static void createDb() throws Exception { Connection conn = DriverManager. getConnection(miniHS2.getJdbcURL(), System.getProperty("user.name"), "bar"); Statement stmt2 = conn.createStatement(); diff --git a/itests/hive-unit/src/test/java/org/apache/hive/jdbc/TestMultiSessionsHS2WithLocalClusterSpark.java b/itests/hive-unit/src/test/java/org/apache/hive/jdbc/TestMultiSessionsHS2WithLocalClusterSpark.java index 0c3479d..3427c5c 100644 --- a/itests/hive-unit/src/test/java/org/apache/hive/jdbc/TestMultiSessionsHS2WithLocalClusterSpark.java +++ b/itests/hive-unit/src/test/java/org/apache/hive/jdbc/TestMultiSessionsHS2WithLocalClusterSpark.java @@ -101,7 +101,7 @@ public static void beforeTest() throws Exception { } // setup DB - private static void createDb() throws SQLException { + private static void createDb() throws Exception { Connection conn = DriverManager. getConnection(miniHS2.getJdbcURL(), System.getProperty("user.name"), "bar"); Statement stmt2 = conn.createStatement(); @@ -124,7 +124,7 @@ public void tearDown() throws Exception { closeConnection(); } - private void createConnection() throws SQLException { + private void createConnection() throws Exception { Connection connection = DriverManager.getConnection(miniHS2.getJdbcURL(dbName), System.getProperty("user.name"), "bar"); Statement statement = connection.createStatement(); @@ -215,8 +215,7 @@ public Void call() throws Exception { }; } - private void testKvQuery(String queryStr, String resultVal) - throws SQLException { + private void testKvQuery(String queryStr, String resultVal) throws Exception { createConnection(); verifyResult(queryStr, resultVal, 2); closeConnection(); diff --git a/itests/hive-unit/src/test/java/org/apache/hive/jdbc/TestSSL.java b/itests/hive-unit/src/test/java/org/apache/hive/jdbc/TestSSL.java index 28a3777..39c8361 100644 --- a/itests/hive-unit/src/test/java/org/apache/hive/jdbc/TestSSL.java +++ b/itests/hive-unit/src/test/java/org/apache/hive/jdbc/TestSSL.java @@ -18,6 +18,7 @@ package org.apache.hive.jdbc; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.File; @@ -46,9 +47,10 @@ public class TestSSL { private static final Logger LOG = LoggerFactory.getLogger(TestSSL.class); - private static final String KEY_STORE_NAME = "keystore.jks"; + private static final String LOCALHOST_KEY_STORE_NAME = "keystore.jks"; + private static final String EXAMPLEDOTCOM_KEY_STORE_NAME = "keystore_exampledotcom.jks"; private static final String TRUST_STORE_NAME = "truststore.jks"; - private static final String KEY_STORE_PASSWORD = "HiveJdbc"; + private static final String KEY_STORE_TRUST_STORE_PASSWORD = "HiveJdbc"; private static final String JAVA_TRUST_STORE_PROP = "javax.net.ssl.trustStore"; private static final String JAVA_TRUST_STORE_PASS_PROP = "javax.net.ssl.trustStorePassword"; private static final String HS2_BINARY_MODE = "binary"; @@ -62,8 +64,9 @@ private Connection hs2Conn = null; private String dataFileDir = conf.get("test.data.files"); private Map confOverlay; - private final String SSL_CONN_PARAMS = ";ssl=true;sslTrustStore=" + URLEncoder.encode(dataFileDir + File.separator + - TRUST_STORE_NAME) + ";trustStorePassword=" + KEY_STORE_PASSWORD; + private final String SSL_CONN_PARAMS = ";ssl=true;sslTrustStore=" + + URLEncoder.encode(dataFileDir + File.separator + TRUST_STORE_NAME) + ";trustStorePassword=" + + KEY_STORE_TRUST_STORE_PASSWORD; @BeforeClass public static void beforeTest() throws Exception { @@ -112,8 +115,10 @@ private int execCommand(String cmd) throws Exception { @Test public void testSSLVersion() throws Exception { Assume.assumeTrue(execCommand("which openssl") == 0); // we need openssl - Assume.assumeTrue(System.getProperty("os.name").toLowerCase() - .contains("linux")); // we depend on linux openssl exit codes + Assume.assumeTrue(System.getProperty("os.name").toLowerCase().contains("linux")); // we depend + // on linux + // openssl + // exit codes setSslConfOverlay(confOverlay); // Test in binary mode @@ -122,16 +127,15 @@ public void testSSLVersion() throws Exception { miniHS2.start(confOverlay); // make SSL connection - hs2Conn = DriverManager.getConnection(miniHS2.getJdbcURL() + ";ssl=true;sslTrustStore=" + - dataFileDir + File.separator + TRUST_STORE_NAME + ";trustStorePassword=" + - KEY_STORE_PASSWORD, System.getProperty("user.name"), "bar"); + hs2Conn = + DriverManager.getConnection(miniHS2.getJdbcURL() + ";ssl=true;sslTrustStore=" + dataFileDir + + File.separator + TRUST_STORE_NAME + ";trustStorePassword=" + + KEY_STORE_TRUST_STORE_PASSWORD, System.getProperty("user.name"), "bar"); hs2Conn.close(); - Assert.assertEquals("Expected exit code of 1", 1, - execCommand("openssl s_client -connect " + miniHS2.getHost() + ":" + miniHS2.getBinaryPort() - + " -ssl2 < /dev/null")); - Assert.assertEquals("Expected exit code of 1", 1, - execCommand("openssl s_client -connect " + miniHS2.getHost() + ":" + miniHS2.getBinaryPort() - + " -ssl3 < /dev/null")); + Assert.assertEquals("Expected exit code of 1", 1, execCommand("openssl s_client -connect " + + miniHS2.getHost() + ":" + miniHS2.getBinaryPort() + " -ssl2 < /dev/null")); + Assert.assertEquals("Expected exit code of 1", 1, execCommand("openssl s_client -connect " + + miniHS2.getHost() + ":" + miniHS2.getBinaryPort() + " -ssl3 < /dev/null")); miniHS2.stop(); // Test in http mode @@ -139,12 +143,12 @@ public void testSSLVersion() throws Exception { miniHS2.start(confOverlay); // make SSL connection try { - hs2Conn = DriverManager.getConnection(miniHS2.getJdbcURL() + - ";ssl=true;sslTrustStore=" + dataFileDir + File.separator + - TRUST_STORE_NAME + ";trustStorePassword=" + KEY_STORE_PASSWORD + - "?hive.server2.transport.mode=" + HS2_HTTP_MODE + - ";hive.server2.thrift.http.path=" + HS2_HTTP_ENDPOINT, - System.getProperty("user.name"), "bar"); + hs2Conn = + DriverManager.getConnection(miniHS2.getJdbcURL() + ";ssl=true;sslTrustStore=" + + dataFileDir + File.separator + TRUST_STORE_NAME + ";trustStorePassword=" + + KEY_STORE_TRUST_STORE_PASSWORD + "?hive.server2.transport.mode=" + HS2_HTTP_MODE + + ";hive.server2.thrift.http.path=" + HS2_HTTP_ENDPOINT, + System.getProperty("user.name"), "bar"); Assert.fail("Expected SQLException during connect"); } catch (SQLException e) { LOG.info("Expected exception: " + e, e); @@ -181,7 +185,7 @@ public void testInvalidConfig() throws Exception { } System.setProperty(JAVA_TRUST_STORE_PROP, dataFileDir + File.separator + TRUST_STORE_NAME ); - System.setProperty(JAVA_TRUST_STORE_PASS_PROP, KEY_STORE_PASSWORD); + System.setProperty(JAVA_TRUST_STORE_PASS_PROP, KEY_STORE_TRUST_STORE_PASSWORD); try { hs2Conn = DriverManager.getConnection(miniHS2.getJdbcURL() + ";ssl=true", System.getProperty("user.name"), "bar"); @@ -291,7 +295,7 @@ public void testSSLConnectionWithProperty() throws Exception { miniHS2.start(confOverlay); System.setProperty(JAVA_TRUST_STORE_PROP, dataFileDir + File.separator + TRUST_STORE_NAME ); - System.setProperty(JAVA_TRUST_STORE_PASS_PROP, KEY_STORE_PASSWORD); + System.setProperty(JAVA_TRUST_STORE_PASS_PROP, KEY_STORE_TRUST_STORE_PASSWORD); // make SSL connection hs2Conn = DriverManager.getConnection(miniHS2.getJdbcURL() + ";ssl=true", System.getProperty("user.name"), "bar"); @@ -375,6 +379,55 @@ public void testSSLFetchHttp() throws Exception { hs2Conn.close(); } + /*** + * Test a new connection when server sends a certificate with wrong CN + * (sends a certificate for www.example.com instead of localhost) + * Opening a new connection with this wrong certificate should fail + * @throws Exception + */ + @Test + public void testConnectionWrongCertCN() throws Exception { + // This call sets the default ssl params including the correct keystore in the server config + setSslConfOverlay(confOverlay); + // Replace default keystore with keystore for www.example.com + confOverlay.put(ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PATH.varname, dataFileDir + File.separator + + EXAMPLEDOTCOM_KEY_STORE_NAME); + // Binary (TCP) mode + setBinaryConfOverlay(confOverlay); + miniHS2.start(confOverlay); + try { + hs2Conn = + DriverManager.getConnection(miniHS2.getJdbcURL("default", SSL_CONN_PARAMS), + System.getProperty("user.name"), "bar"); + fail("SSL connection, with the server providing wrong certifcate (with CN www.example.com, " + + "instead of localhost), should fail"); + } catch (SQLException e) { + // Expected error: should throw java.security.cert.CertificateException + assertEquals("08S01", e.getSQLState().trim()); + assertTrue(e.toString().contains("java.security.cert.CertificateException")); + } + + miniHS2.stop(); + + // Http mode + setHttpConfOverlay(confOverlay); + miniHS2.start(confOverlay); + try { + hs2Conn = + DriverManager.getConnection(miniHS2.getJdbcURL("default", SSL_CONN_PARAMS), + System.getProperty("user.name"), "bar"); + fail("SSL connection, with the server providing wrong certifcate (with CN www.example.com, " + + "instead of localhost), should fail"); + } catch (SQLException e) { + // Expected error: should throw javax.net.ssl.SSLPeerUnverifiedException + assertEquals("08S01", e.getSQLState().trim()); + assertTrue(e.toString().contains("javax.net.ssl.SSLPeerUnverifiedException")); + } + // Revert to default keystore path + confOverlay.put(ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PATH.varname, dataFileDir + File.separator + + LOCALHOST_KEY_STORE_NAME); + } + private void setupTestTableWithData(String tableName, Path dataFilePath, Connection hs2Conn) throws Exception { Statement stmt = hs2Conn.createStatement(); @@ -393,9 +446,9 @@ private void setupTestTableWithData(String tableName, Path dataFilePath, private void setSslConfOverlay(Map confOverlay) { confOverlay.put(ConfVars.HIVE_SERVER2_USE_SSL.varname, "true"); confOverlay.put(ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PATH.varname, - dataFileDir + File.separator + KEY_STORE_NAME); + dataFileDir + File.separator + LOCALHOST_KEY_STORE_NAME); confOverlay.put(ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PASSWORD.varname, - KEY_STORE_PASSWORD); + KEY_STORE_TRUST_STORE_PASSWORD); } private void clearSslConfOverlay(Map confOverlay) { diff --git a/itests/hive-unit/src/test/java/org/apache/hive/jdbc/authorization/TestHS2AuthzContext.java b/itests/hive-unit/src/test/java/org/apache/hive/jdbc/authorization/TestHS2AuthzContext.java index 0bb3c0a..c43776b 100644 --- a/itests/hive-unit/src/test/java/org/apache/hive/jdbc/authorization/TestHS2AuthzContext.java +++ b/itests/hive-unit/src/test/java/org/apache/hive/jdbc/authorization/TestHS2AuthzContext.java @@ -101,7 +101,7 @@ public void testAuthzContextContentsCmdProcessorCmd() throws Exception { verifyContextContents("dfs -ls /", "-ls /"); } - private void verifyContextContents(final String cmd, String ctxCmd) throws SQLException, + private void verifyContextContents(final String cmd, String ctxCmd) throws Exception, HiveAuthzPluginException, HiveAccessControlException { Connection hs2Conn = getConnection("user1"); Statement stmt = hs2Conn.createStatement(); @@ -126,7 +126,7 @@ private void verifyContextContents(final String cmd, String ctxCmd) throws SQLEx } - private Connection getConnection(String userName) throws SQLException { + private Connection getConnection(String userName) throws Exception { return DriverManager.getConnection(miniHS2.getJdbcURL(), userName, "bar"); } diff --git a/itests/hive-unit/src/test/java/org/apache/hive/jdbc/authorization/TestJdbcMetadataApiAuth.java b/itests/hive-unit/src/test/java/org/apache/hive/jdbc/authorization/TestJdbcMetadataApiAuth.java index 19b311d..692bfa0 100644 --- a/itests/hive-unit/src/test/java/org/apache/hive/jdbc/authorization/TestJdbcMetadataApiAuth.java +++ b/itests/hive-unit/src/test/java/org/apache/hive/jdbc/authorization/TestJdbcMetadataApiAuth.java @@ -253,7 +253,7 @@ private void assertErrorContains(SQLException e, String deniedErr) { } } - private static Connection getConnection(String userName) throws SQLException { + private static Connection getConnection(String userName) throws Exception { return DriverManager.getConnection(miniHS2.getJdbcURL(), userName, "bar"); } diff --git a/itests/hive-unit/src/test/java/org/apache/hive/jdbc/authorization/TestJdbcWithSQLAuthorization.java b/itests/hive-unit/src/test/java/org/apache/hive/jdbc/authorization/TestJdbcWithSQLAuthorization.java index dacde45..5e653ec 100644 --- a/itests/hive-unit/src/test/java/org/apache/hive/jdbc/authorization/TestJdbcWithSQLAuthorization.java +++ b/itests/hive-unit/src/test/java/org/apache/hive/jdbc/authorization/TestJdbcWithSQLAuthorization.java @@ -126,7 +126,7 @@ public void testAuthorization1() throws Exception { } } - private Connection getConnection(String userName) throws SQLException { + private Connection getConnection(String userName) throws Exception { return DriverManager.getConnection(miniHS2.getJdbcURL(), userName, "bar"); } diff --git a/jdbc/src/java/org/apache/hive/jdbc/HiveConnection.java b/jdbc/src/java/org/apache/hive/jdbc/HiveConnection.java index 8fb1d12..bfc8869 100644 --- a/jdbc/src/java/org/apache/hive/jdbc/HiveConnection.java +++ b/jdbc/src/java/org/apache/hive/jdbc/HiveConnection.java @@ -84,11 +84,13 @@ import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.socket.ConnectionSocketFactory; -import org.apache.http.conn.ssl.SSLSocketFactory; +import org.apache.http.conn.ssl.DefaultHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.BasicHttpClientConnectionManager; +import org.apache.http.ssl.SSLContexts; import org.apache.thrift.TException; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.transport.THttpClient; @@ -326,30 +328,29 @@ private CloseableHttpClient getHttpClient(Boolean useSsl) throws SQLException { if (isCookieEnabled) { // Create a http client with a retry mechanism when the server returns a status code of 401. httpClientBuilder = - HttpClients.custom().setServiceUnavailableRetryStrategy( - new ServiceUnavailableRetryStrategy() { - - @Override - public boolean retryRequest( - final HttpResponse response, - final int executionCount, - final HttpContext context) { - int statusCode = response.getStatusLine().getStatusCode(); - boolean ret = statusCode == 401 && executionCount <= 1; - - // Set the context attribute to true which will be interpreted by the request interceptor - if (ret) { - context.setAttribute(Utils.HIVE_SERVER2_RETRY_KEY, Utils.HIVE_SERVER2_RETRY_TRUE); - } - return ret; - } - - @Override - public long getRetryInterval() { - // Immediate retry - return 0; - } - }); + HttpClients.custom().setServiceUnavailableRetryStrategy( + new ServiceUnavailableRetryStrategy() { + @Override + public boolean retryRequest(final HttpResponse response, final int executionCount, + final HttpContext context) { + int statusCode = response.getStatusLine().getStatusCode(); + boolean ret = statusCode == 401 && executionCount <= 1; + + // Set the context attribute to true which will be interpreted by the request + // interceptor + if (ret) { + context.setAttribute(Utils.HIVE_SERVER2_RETRY_KEY, + Utils.HIVE_SERVER2_RETRY_TRUE); + } + return ret; + } + + @Override + public long getRetryInterval() { + // Immediate retry + return 0; + } + }); } else { httpClientBuilder = HttpClientBuilder.create(); } @@ -362,46 +363,36 @@ public long getRetryInterval() { String sslTrustStorePassword = sessConfMap.get( JdbcConnectionParams.SSL_TRUST_STORE_PASSWORD); KeyStore sslTrustStore; - SSLSocketFactory socketFactory; - + SSLConnectionSocketFactory socketFactory; + SSLContext sslContext; /** - * The code within the try block throws: - * 1. SSLInitializationException - * 2. KeyStoreException - * 3. IOException - * 4. NoSuchAlgorithmException - * 5. CertificateException - * 6. KeyManagementException - * 7. UnrecoverableKeyException - * We don't want the client to retry on any of these, hence we catch all - * and throw a SQLException. + * The code within the try block throws: SSLInitializationException, KeyStoreException, + * IOException, NoSuchAlgorithmException, CertificateException, KeyManagementException & + * UnrecoverableKeyException. We don't want the client to retry on any of these, + * hence we catch all and throw a SQLException. */ try { - if (useTwoWaySSL != null && - useTwoWaySSL.equalsIgnoreCase(JdbcConnectionParams.TRUE)) { + if (useTwoWaySSL != null && useTwoWaySSL.equalsIgnoreCase(JdbcConnectionParams.TRUE)) { socketFactory = getTwoWaySSLSocketFactory(); } else if (sslTrustStorePath == null || sslTrustStorePath.isEmpty()) { // Create a default socket factory based on standard JSSE trust material - socketFactory = SSLSocketFactory.getSocketFactory(); + socketFactory = SSLConnectionSocketFactory.getSocketFactory(); } else { // Pick trust store config from the given path sslTrustStore = KeyStore.getInstance(JdbcConnectionParams.SSL_TRUST_STORE_TYPE); sslTrustStore.load(new FileInputStream(sslTrustStorePath), - sslTrustStorePassword.toCharArray()); - socketFactory = new SSLSocketFactory(sslTrustStore); + sslTrustStorePassword.toCharArray()); + sslContext = SSLContexts.custom().loadTrustMaterial(sslTrustStore, null).build(); + socketFactory = + new SSLConnectionSocketFactory(sslContext, new DefaultHostnameVerifier(null)); } - socketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); - final Registry registry = - RegistryBuilder.create() - .register("https", socketFactory) - .build(); - + RegistryBuilder. create().register("https", socketFactory) + .build(); httpClientBuilder.setConnectionManager(new BasicHttpClientConnectionManager(registry)); - } - catch (Exception e) { - String msg = "Could not create an https connection to " + - jdbcUriString + ". " + e.getMessage(); + } catch (Exception e) { + String msg = + "Could not create an https connection to " + jdbcUriString + ". " + e.getMessage(); throw new SQLException(msg, " 08S01", e); } } @@ -492,8 +483,8 @@ private TTransport createBinaryTransport() throws SQLException, TTransportExcept return transport; } - SSLSocketFactory getTwoWaySSLSocketFactory() throws SQLException { - SSLSocketFactory socketFactory = null; + SSLConnectionSocketFactory getTwoWaySSLSocketFactory() throws SQLException { + SSLConnectionSocketFactory socketFactory = null; try { KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance( @@ -528,7 +519,7 @@ SSLSocketFactory getTwoWaySSLSocketFactory() throws SQLException { SSLContext context = SSLContext.getInstance("TLS"); context.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom()); - socketFactory = new SSLSocketFactory(context); + socketFactory = new SSLConnectionSocketFactory(context); } catch (Exception e) { throw new SQLException("Error while initializing 2 way ssl socket factory ", e); } 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 1e6ac4f..d0c0df9 100644 --- a/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java +++ b/service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java @@ -26,7 +26,9 @@ import java.util.List; import java.util.Map; +import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLSocket; import javax.security.auth.login.LoginException; import javax.security.sasl.Sasl; @@ -217,7 +219,9 @@ public static TTransport getSocketTransport(String host, int port, int loginTime public static TTransport getSSLSocket(String host, int port, int loginTimeout) throws TTransportException { - return TSSLTransportFactory.getClientSocket(host, port, loginTimeout); + // The underlying SSLSocket object is bound to host:port with the given SO_TIMEOUT + TSocket tSSLSocket = TSSLTransportFactory.getClientSocket(host, port, loginTimeout); + return getSSLSocketWithHttps(tSSLSocket); } public static TTransport getSSLSocket(String host, int port, int loginTimeout, @@ -226,7 +230,20 @@ public static TTransport getSSLSocket(String host, int port, int loginTimeout, new TSSLTransportFactory.TSSLTransportParameters(); params.setTrustStore(trustStorePath, trustStorePassWord); params.requireClientAuth(true); - return TSSLTransportFactory.getClientSocket(host, port, loginTimeout, params); + // The underlying SSLSocket object is bound to host:port with the given SO_TIMEOUT and + // SSLContext created with the given params + TSocket tSSLSocket = TSSLTransportFactory.getClientSocket(host, port, loginTimeout, params); + return getSSLSocketWithHttps(tSSLSocket); + } + + // Using endpoint identification algorithm as HTTPS enables us to do + // CNAMEs/subjectAltName verification + private static TSocket getSSLSocketWithHttps(TSocket tSSLSocket) throws TTransportException { + SSLSocket sslSocket = (SSLSocket) tSSLSocket.getSocket(); + SSLParameters sslParams = sslSocket.getSSLParameters(); + sslParams.setEndpointIdentificationAlgorithm("HTTPS"); + sslSocket.setSSLParameters(sslParams); + return new TSocket(sslSocket); } public static TServerSocket getServerSocket(String hiveHost, int portNum)