Skip to content

Commit

Permalink
Merge branch 'dev' into fix-callable-statement-exception-when-SP-not-…
Browse files Browse the repository at this point in the history
…exist
  • Loading branch information
xiangyushawn authored Apr 26, 2017
2 parents 0ff5900 + 616472b commit bed1305
Show file tree
Hide file tree
Showing 11 changed files with 656 additions and 105 deletions.
21 changes: 0 additions & 21 deletions src/main/java/com/microsoft/sqlserver/jdbc/AuthenticationJNI.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,18 +87,6 @@ static FedAuthDllInfo getAccessTokenForWindowsIntegrated(String stsURL,
return dllInfo;
}

static FedAuthDllInfo getAccessToken(String userName,
String password,
String stsURL,
String servicePrincipalName,
String clientConnectionId,
String clientId,
long expirationFileTime) throws DLLException {
FedAuthDllInfo dllInfo = ADALGetAccessToken(userName, password, stsURL, servicePrincipalName, clientConnectionId, clientId,
expirationFileTime, authLogger);
return dllInfo;
}

// InitDNSName should be called to initialize the DNSName before calling this function
byte[] GenerateClientContext(byte[] pin,
boolean[] done) throws SQLServerException {
Expand Down Expand Up @@ -184,15 +172,6 @@ private native static FedAuthDllInfo ADALGetAccessTokenForWindowsIntegrated(Stri
long expirationFileTime,
java.util.logging.Logger log);

private native static FedAuthDllInfo ADALGetAccessToken(String userName,
String password,
String stsURL,
String servicePrincipalName,
String clientConnectionId,
String clientId,
long expirationFileTime,
java.util.logging.Logger log);

native static byte[] DecryptColumnEncryptionKey(String masterKeyPath,
String encryptionAlgorithm,
byte[] encryptedColumnEncryptionKey) throws DLLException;
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -4707,6 +4707,9 @@ void writeTVPRows(TVP value) throws SQLServerException {
case VARCHAR:
case NCHAR:
case NVARCHAR:
case LONGVARCHAR:
case LONGNVARCHAR:
case SQLXML:
isShortValue = (2L * columnPair.getValue().precision) <= DataTypes.SHORT_VARTYPE_MAX_BYTES;
isNull = (null == currentColumnStringValue);
dataLength = isNull ? 0 : currentColumnStringValue.length() * 2;
Expand Down Expand Up @@ -4743,6 +4746,7 @@ else if (DataTypes.UNKNOWN_STREAM_LENGTH == dataLength)

case BINARY:
case VARBINARY:
case LONGVARBINARY:
// Handle conversions as done in other types.
isShortValue = columnPair.getValue().precision <= DataTypes.SHORT_VARTYPE_MAX_BYTES;
isNull = (null == currentObject);
Expand Down Expand Up @@ -4912,6 +4916,9 @@ void writeTVPColumnMetaData(TVP value) throws SQLServerException {
case VARCHAR:
case NCHAR:
case NVARCHAR:
case LONGVARCHAR:
case LONGNVARCHAR:
case SQLXML:
writeByte(TDSType.NVARCHAR.byteValue());
isShortValue = (2L * pair.getValue().precision) <= DataTypes.SHORT_VARTYPE_MAX_BYTES;
// Use PLP encoding on Yukon and later with long values
Expand All @@ -4931,6 +4938,7 @@ void writeTVPColumnMetaData(TVP value) throws SQLServerException {

case BINARY:
case VARBINARY:
case LONGVARBINARY:
writeByte(TDSType.BIGVARBINARY.byteValue());
isShortValue = pair.getValue().precision <= DataTypes.SHORT_VARTYPE_MAX_BYTES;
// Use PLP encoding on Yukon and later with long values
Expand Down
65 changes: 65 additions & 0 deletions src/main/java/com/microsoft/sqlserver/jdbc/JaasConfiguration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Microsoft JDBC Driver for SQL Server
*
* Copyright(c) Microsoft Corporation All rights reserved.
*
* This program is made available under the terms of the MIT License. See the LICENSE file in the project root for more information.
*/
package com.microsoft.sqlserver.jdbc;

import java.util.HashMap;
import java.util.Map;

import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;

/**
* This class overrides JAAS Configuration and always provide a configuration is not defined for default configuration.
*/
public class JaasConfiguration extends Configuration {

private final Configuration delegate;
private AppConfigurationEntry[] defaultValue;

private static AppConfigurationEntry[] generateDefaultConfiguration() {
if (Util.isIBM()) {
Map<String, String> confDetailsWithoutPassword = new HashMap<String, String>();
confDetailsWithoutPassword.put("useDefaultCcache", "true");
Map<String, String> confDetailsWithPassword = new HashMap<String, String>();
// We generated a two configurations fallback that is suitable for password and password-less authentication
// See https://www.ibm.com/support/knowledgecenter/SSYKE2_8.0.0/com.ibm.java.security.component.80.doc/security-component/jgssDocs/jaas_login_user.html
final String ibmLoginModule = "com.ibm.security.auth.module.Krb5LoginModule";
return new AppConfigurationEntry[] {
new AppConfigurationEntry(ibmLoginModule, AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT, confDetailsWithoutPassword),
new AppConfigurationEntry(ibmLoginModule, AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT, confDetailsWithPassword)};
}
else {
Map<String, String> confDetails = new HashMap<String, String>();
confDetails.put("useTicketCache", "true");
return new AppConfigurationEntry[] {new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule",
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, confDetails)};
}
}

/**
* Package protected constructor.
*
* @param delegate
* a possibly null delegate
*/
JaasConfiguration(Configuration delegate) {
this.delegate = delegate;
this.defaultValue = generateDefaultConfiguration();
}

@Override
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
AppConfigurationEntry[] conf = delegate == null ? null : delegate.getAppConfigurationEntry(name);
// We return our configuration only if user requested default one
// In case where user did request another JAAS Configuration name, we expect he knows what he is doing.
if (conf == null && name.equals(SQLServerDriverStringProperty.JAAS_CONFIG_NAME.getDefaultValue())) {
return defaultValue;
}
return conf;
}
}
83 changes: 6 additions & 77 deletions src/main/java/com/microsoft/sqlserver/jdbc/KerbAuthentication.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,13 @@
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.naming.NamingException;
import javax.security.auth.Subject;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
Expand All @@ -44,7 +41,6 @@
* KerbAuthentication for int auth.
*/
final class KerbAuthentication extends SSPIAuthentication {
private final static String CONFIGNAME = "SQLJDBCDriver";
private final static java.util.logging.Logger authLogger = java.util.logging.Logger
.getLogger("com.microsoft.sqlserver.jdbc.internals.KerbAuthentication");

Expand All @@ -57,78 +53,9 @@ final class KerbAuthentication extends SSPIAuthentication {
private GSSContext peerContext = null;

static {
// The driver on load will look to see if there is a configuration set for the SQLJDBCDriver, if not it will install its
// own configuration. Note it is possible that there is a configuration exists but it does not contain a configuration entry
// for the driver in that case, we will override the configuration but will flow the configuration requests to existing
// config for anything other than SQLJDBCDriver
//
class SQLJDBCDriverConfig extends Configuration {
Configuration current = null;
AppConfigurationEntry[] driverConf;

SQLJDBCDriverConfig() {
try {
current = Configuration.getConfiguration();
}
catch (SecurityException e) {
// if we cant get the configuration, it is likely that no configuration has been specified. So go ahead and set the config
authLogger.finer(toString() + " No configurations provided, setting driver default");
}
AppConfigurationEntry[] config = null;

if (null != current) {
config = current.getAppConfigurationEntry(CONFIGNAME);
}
// If there is user provided configuration we leave use that and not install our configuration
if (null == config) {
if (authLogger.isLoggable(Level.FINER))
authLogger.finer(toString() + " SQLJDBCDriver configuration entry is not provided, setting driver default");

AppConfigurationEntry appConf;
if (Util.isIBM()) {
Map<String, String> confDetails = new HashMap<String, String>();
confDetails.put("useDefaultCcache", "true");
confDetails.put("moduleBanner", "false");
appConf = new AppConfigurationEntry("com.ibm.security.auth.module.Krb5LoginModule",
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, confDetails);
if (authLogger.isLoggable(Level.FINER))
authLogger.finer(toString() + " Setting IBM Krb5LoginModule");
}
else {
Map<String, String> confDetails = new HashMap<String, String>();
confDetails.put("useTicketCache", "true");
appConf = new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule",
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, confDetails);
if (authLogger.isLoggable(Level.FINER))
authLogger.finer(toString() + " Setting Sun Krb5LoginModule");
}
driverConf = new AppConfigurationEntry[1];
driverConf[0] = appConf;
Configuration.setConfiguration(this);
}

}

public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
// we should only handle anything that is related to our part, everything else is handled by the configuration
// already existing configuration if there is one.
if (name.equals(CONFIGNAME)) {
return driverConf;
}
else {
if (null != current)
return current.getAppConfigurationEntry(name);
else
return null;
}
}

public void refresh() {
if (null != current)
current.refresh();
}
}
SQLJDBCDriverConfig driverconfig = new SQLJDBCDriverConfig();
// Overrides the default JAAS configuration loader.
// This one will forward to the default one in all cases but the default configuration is empty.
Configuration.setConfiguration(new JaasConfiguration(Configuration.getConfiguration()));
}

private void intAuthInit() throws SQLServerException {
Expand All @@ -148,13 +75,15 @@ private void intAuthInit() throws SQLServerException {
peerContext.requestInteg(true);
}
else {
String configName = con.activeConnectionProperties.getProperty(SQLServerDriverStringProperty.JAAS_CONFIG_NAME.toString(),
SQLServerDriverStringProperty.JAAS_CONFIG_NAME.getDefaultValue());
Subject currentSubject = null;
KerbCallback callback = new KerbCallback(con);
try {
AccessControlContext context = AccessController.getContext();
currentSubject = Subject.getSubject(context);
if (null == currentSubject) {
lc = new LoginContext(CONFIGNAME, callback);
lc = new LoginContext(configName, callback);
lc.login();
// per documentation LoginContext will instantiate a new subject.
currentSubject = lc.getSubject();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,9 @@ ServerPortPlaceHolder getRoutingInfo() {
}

// Permission targets
// currently only callAbort is implemented
private static final String callAbortPerm = "callAbort";

private static final String SET_NETWORK_TIMEOUT_PERM = "setNetworkTimeout";

private boolean sendStringParametersAsUnicode = SQLServerDriverBooleanProperty.SEND_STRING_PARAMETERS_AS_UNICODE.getDefaultValue(); // see
// connection
Expand Down Expand Up @@ -4689,6 +4690,20 @@ public void setNetworkTimeout(Executor executor,
}

checkClosed();

// check for setNetworkTimeout permission
SecurityManager secMgr = System.getSecurityManager();
if (secMgr != null) {
try {
SQLPermission perm = new SQLPermission(SET_NETWORK_TIMEOUT_PERM);
secMgr.checkPermission(perm);
}
catch (SecurityException ex) {
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_permissionDenied"));
Object[] msgArgs = {SET_NETWORK_TIMEOUT_PERM};
SQLServerException.makeFromDriverError(this, this, form.format(msgArgs), null, true);
}
}

try {
tdsChannel.setNetworkTimeout(timeout);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,27 @@ public int getSocketTimeout() {
return getIntProperty(connectionProps, SQLServerDriverIntProperty.SOCKET_TIMEOUT.toString(), defaultTimeOut);
}

/**
* Sets the login configuration file for Kerberos authentication. This
* overrides the default configuration <i> SQLJDBCDriver </i>
*
* @param configurationName
*/
public void setJASSConfigurationName(String configurationName) {
setStringProperty(connectionProps, SQLServerDriverStringProperty.JAAS_CONFIG_NAME.toString(),
configurationName);
}

/**
* Retrieves the login configuration file for Kerberos authentication.
*
* @return
*/
public String getJASSConfigurationName() {
return getStringProperty(connectionProps, SQLServerDriverStringProperty.JAAS_CONFIG_NAME.toString(),
SQLServerDriverStringProperty.JAAS_CONFIG_NAME.getDefaultValue());
}

// responseBuffering controls the driver's buffering of responses from SQL Server.
// Possible values are:
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ else if (val instanceof OffsetTime)

case BINARY:
case VARBINARY:
case LONGVARBINARY:
bValueNull = (null == val);
nValueLen = bValueNull ? 0 : ((byte[]) val).length;

Expand All @@ -230,6 +231,9 @@ else if (val instanceof OffsetTime)
case VARCHAR:
case NCHAR:
case NVARCHAR:
case LONGVARCHAR:
case LONGNVARCHAR:
case SQLXML:
bValueNull = (null == val);
nValueLen = bValueNull ? 0 : (2 * ((String) val).length());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ public String toString() {
}
}



enum SQLServerDriverStringProperty
{
APPLICATION_INTENT ("applicationIntent", ApplicationIntent.READ_WRITE.toString()),
Expand All @@ -226,6 +228,7 @@ enum SQLServerDriverStringProperty
FAILOVER_PARTNER ("failoverPartner", ""),
HOSTNAME_IN_CERTIFICATE ("hostNameInCertificate", ""),
INSTANCE_NAME ("instanceName", ""),
JAAS_CONFIG_NAME ("jaasConfigurationName", "SQLJDBCDriver"),
PASSWORD ("password", ""),
RESPONSE_BUFFERING ("responseBuffering", "adaptive"),
SELECT_METHOD ("selectMethod", "direct"),
Expand Down Expand Up @@ -377,6 +380,7 @@ public final class SQLServerDriver implements java.sql.Driver {
new SQLServerDriverPropertyInfo(SQLServerDriverBooleanProperty.FIPS.toString(), Boolean.toString(SQLServerDriverBooleanProperty.FIPS.getDefaultValue()), false, TRUE_FALSE),
new SQLServerDriverPropertyInfo(SQLServerDriverBooleanProperty.ENABLE_PREPARE_ON_FIRST_PREPARED_STATEMENT.toString(), Boolean.toString(SQLServerConnection.getDefaultEnablePrepareOnFirstPreparedStatementCall()), false, TRUE_FALSE),
new SQLServerDriverPropertyInfo(SQLServerDriverIntProperty.SERVER_PREPARED_STATEMENT_DISCARD_THRESHOLD.toString(), Integer.toString(SQLServerConnection.getDefaultServerPreparedStatementDiscardThreshold()), false, null),
new SQLServerDriverPropertyInfo(SQLServerDriverStringProperty.JAAS_CONFIG_NAME.toString(), SQLServerDriverStringProperty.JAAS_CONFIG_NAME.getDefaultValue(), false, null),
};

// Properties that can only be set by using Properties.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -382,5 +382,6 @@ 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."},
};
}
Loading

0 comments on commit bed1305

Please sign in to comment.