From 017b0f1eac837d57c8c33b582b29518cc6e2ac09 Mon Sep 17 00:00:00 2001 From: edanidzerda <19670937+edanidzerda@users.noreply.github.com> Date: Tue, 13 Jun 2023 10:33:49 -0400 Subject: [PATCH] Added a new connection property "useDefaultJaasConfig" * New option to allow the JDBC driver to perform Kerberos authentication using its builtin JaasConfiguration(), to easily coexist with an external JAAS configuration that does not provide a SQLJDBCDriver Login module configuration. * Warning is printed if the jaasConfigurationName is non-default at the same time as useDefaultJaasConfig, as the jaasConfigurationName will not be used. --- .../sqlserver/jdbc/ISQLServerDataSource.java | 25 +++++++++++++++---- .../sqlserver/jdbc/KerbAuthentication.java | 20 ++++++++++++++- .../sqlserver/jdbc/SQLServerDataSource.java | 12 +++++++++ .../sqlserver/jdbc/SQLServerDriver.java | 6 ++++- .../sqlserver/jdbc/SQLServerResource.java | 3 ++- .../jdbc/SQLServerConnectionTest.java | 3 +++ 6 files changed, 61 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerDataSource.java b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerDataSource.java index a435666e1..019b79997 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerDataSource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/ISQLServerDataSource.java @@ -802,7 +802,7 @@ public interface ISQLServerDataSource extends javax.sql.CommonDataSource { int getSocketTimeout(); /** - * Sets the login configuration file for Kerberos authentication. This overrides the default configuration + * Sets the login configuration name for Kerberos authentication. This overrides the default configuration * SQLJDBCDriver * * @param configurationName @@ -814,7 +814,7 @@ public interface ISQLServerDataSource extends javax.sql.CommonDataSource { void setJASSConfigurationName(String configurationName); /** - * Returns the login configuration file for Kerberos authentication. + * Returns the login configuration name for Kerberos authentication. * * * @return login configuration file name @@ -825,7 +825,7 @@ public interface ISQLServerDataSource extends javax.sql.CommonDataSource { String getJASSConfigurationName(); /** - * Sets the login configuration file for Kerberos authentication. This overrides the default configuration + * Sets the login configuration name for Kerberos authentication. This overrides the default configuration * SQLJDBCDriver * * @@ -835,12 +835,27 @@ public interface ISQLServerDataSource extends javax.sql.CommonDataSource { void setJAASConfigurationName(String configurationName); /** - * Returns the login configuration file for Kerberos authentication. + * Returns the login configuration name for Kerberos authentication. * - * @return login configuration file name + * @return login configuration name */ String getJAASConfigurationName(); + /** + * Returns whether the default JAAS Configuration should be used + * + * @return useDefaultJaasConfig boolean value + */ + boolean getUseDefaultJaasConfig(); + + /** + * Sets whether the default JAAS Configuration will be used. This means the system-wide JAAS configuration + * is ignored to avoid conflicts with libraries that override the JAAS configuration. + * + * @param useDefaultJaasConfig + * boolean property to use the default JAAS configuration + */ + void setUseDefaultJaasConfig(boolean useDefaultJaasConfig); /** * Sets whether Fips Mode should be enabled/disabled on the connection. For FIPS enabled JVM this property should be * true. diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/KerbAuthentication.java b/src/main/java/com/microsoft/sqlserver/jdbc/KerbAuthentication.java index ffc016448..b58bb9fae 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/KerbAuthentication.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/KerbAuthentication.java @@ -73,13 +73,31 @@ private void initAuthInit() throws SQLServerException { String configName = con.activeConnectionProperties.getProperty( SQLServerDriverStringProperty.JAAS_CONFIG_NAME.toString(), SQLServerDriverStringProperty.JAAS_CONFIG_NAME.getDefaultValue()); + boolean useDefaultJaas = Boolean.parseBoolean(con.activeConnectionProperties.getProperty( + SQLServerDriverBooleanProperty.USE_DEFAULT_JAAS_CONFIG.toString(), + Boolean.toString(SQLServerDriverBooleanProperty.USE_DEFAULT_JAAS_CONFIG.getDefaultValue()))); + + if (!configName.equals( + SQLServerDriverStringProperty.JAAS_CONFIG_NAME.getDefaultValue()) && useDefaultJaas) { + // Reset configName to default -- useDefaultJaas setting takes priority over jaasConfigName + if (authLogger.isLoggable(Level.WARNING)) { + authLogger.warning(toString() + String.format( + "Using default JAAS configuration, configured %s=%s will not be used.", + SQLServerDriverStringProperty.JAAS_CONFIG_NAME, configName)); + } + configName = SQLServerDriverStringProperty.JAAS_CONFIG_NAME.getDefaultValue(); + } Subject currentSubject; KerbCallback callback = new KerbCallback(con); try { AccessControlContext context = AccessController.getContext(); currentSubject = Subject.getSubject(context); if (null == currentSubject) { - lc = new LoginContext(configName, callback); + if (useDefaultJaas) { + lc = new LoginContext(configName, null, callback, new JaasConfiguration(null)); + } else { + lc = new LoginContext(configName, callback); + } lc.login(); // per documentation LoginContext will instantiate a new subject. currentSubject = lc.getSubject(); diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java index b7e018112..216ef569a 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDataSource.java @@ -1030,6 +1030,18 @@ public String getJAASConfigurationName() { SQLServerDriverStringProperty.JAAS_CONFIG_NAME.getDefaultValue()); } + @Override + public boolean getUseDefaultJaasConfig() { + return getBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.USE_DEFAULT_JAAS_CONFIG.toString(), + SQLServerDriverBooleanProperty.USE_DEFAULT_JAAS_CONFIG.getDefaultValue()); + } + + @Override + public void setUseDefaultJaasConfig(boolean useDefaultJaasConfig) { + setBooleanProperty(connectionProps, SQLServerDriverBooleanProperty.USE_DEFAULT_JAAS_CONFIG.toString(), + useDefaultJaasConfig); + } + /** * @deprecated This method is deprecated. Use {@link SQLServerDataSource#setUser(String user)} instead. * diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java index 1bd92024c..966ffb079 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java @@ -693,7 +693,8 @@ enum SQLServerDriverBooleanProperty { USE_BULK_COPY_FOR_BATCH_INSERT("useBulkCopyForBatchInsert", false), USE_FMT_ONLY("useFmtOnly", false), SEND_TEMPORAL_DATATYPES_AS_STRING_FOR_BULK_COPY("sendTemporalDataTypesAsStringForBulkCopy", true), - DELAY_LOADING_LOBS("delayLoadingLobs", true); + DELAY_LOADING_LOBS("delayLoadingLobs", true), + USE_DEFAULT_JAAS_CONFIG("useDefaultJaasConfig", false); private final String name; private final boolean defaultValue; @@ -892,6 +893,9 @@ public final class SQLServerDriver implements java.sql.Driver { null), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.JAAS_CONFIG_NAME.toString(), SQLServerDriverStringProperty.JAAS_CONFIG_NAME.getDefaultValue(), false, null), + new SQLServerDriverPropertyInfo(SQLServerDriverBooleanProperty.USE_DEFAULT_JAAS_CONFIG.toString(), + Boolean.toString(SQLServerDriverBooleanProperty.USE_DEFAULT_JAAS_CONFIG.getDefaultValue()), false, + TRUE_FALSE), new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.SSL_PROTOCOL.toString(), SQLServerDriverStringProperty.SSL_PROTOCOL.getDefaultValue(), false, new String[] {SSLProtocol.TLS.toString(), SSLProtocol.TLS_V10.toString(), diff --git a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java index a9047e6bc..0652a4205 100644 --- a/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java +++ b/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerResource.java @@ -449,7 +449,8 @@ protected Object[][] getContents() { {"R_kerberosLoginFailedForUsername", "Cannot login with Kerberos principal {0}, check your credentials. {1}"}, {"R_kerberosLoginFailed", "Kerberos Login failed: {0} due to {1} ({2})"}, {"R_StoredProcedureNotFound", "Could not find stored procedure ''{0}''."}, - {"R_jaasConfigurationNamePropertyDescription", "Login configuration file for Kerberos authentication."}, + {"R_jaasConfigurationNamePropertyDescription", "Login configuration name for Kerberos authentication."}, + {"R_useDefaultJaasConfigPropertyDescription", "Use the default JAAS configuration for Kerberos authentication."}, {"R_AKVKeyNotFound", "Key not found: {0}"}, {"R_SQLVariantSupport", "SQL_VARIANT is not supported in versions of SQL Server before 2008."}, {"R_invalidProbbytes", "SQL_VARIANT: invalid probBytes for {0} type."}, diff --git a/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java b/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java index 52b1413c3..70336f8d3 100644 --- a/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java +++ b/src/test/java/com/microsoft/sqlserver/jdbc/SQLServerConnectionTest.java @@ -138,6 +138,9 @@ public void testDataSource() throws SQLServerException { ds.setJAASConfigurationName(stringPropValue); assertEquals(stringPropValue, ds.getJAASConfigurationName(), TestResource.getResource("R_valuesAreDifferent")); + ds.setUseDefaultJaasConfig(booleanPropValue); + assertEquals(booleanPropValue, ds.getUseDefaultJaasConfig(), TestResource.getResource("R_valuesAreDifferent")); + ds.setMSIClientId(stringPropValue); assertEquals(stringPropValue, ds.getMSIClientId(), TestResource.getResource("R_valuesAreDifferent"));