I am connecting to a MS SQL Server instance (e.g. SQLSRV_1) using Kerberos authentication and attempting to execute a query referencing a linked server (e.g. SQLSRV_2).
jTDS connection string:
dbc:jtds:sqlserver://SQLSRV_1/database1;domain=mydomain;useKerberos=true;
I have confirmed that the established jTDS connection is using Kerberos.
SELECT net_transport, auth_scheme FROM sys.dm_exec_connections WHERE session_id = @@spid
returns:
net_transport = TCP; auth_scheme = KERBEROS
Queries referencing the SQL Server instance (SQLSRV_1) to which the initial connection is established do succeed. However, when querying the linked server's tables, I receive a java.sql.SQLException: Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'. I believe this is due to the "double hop" scenario, where the initiating client's credentials are not being correctly passed along to the remote/linked server (i.e. SQLSRV_2).
I believe that the MS SQL Servers (SQLSRV_1 and SQLSRV_2) and the Active Directory (user) account are confirmed correctly to support Kerberos authentication and this "double hop" scenario. For example, I can log into SQLSRV_1 using Windows authentication from MS Management Studio using the said AD account - confirming that the established Management Studio connection is indeed using Kerberos - and excute the test query against the linked server (SQLSRV_2) with no issue.
sample linked server test query:
select * from SQLSRV_2.database2.dbo.mytable
I reviewed and subsequently modifiied the jTDS (v.1.3.1) source code to set the initiating client's Credential Delegation flag to true when creating and initializing the GSS Context to the MS SQL Service. Doing so resolves the noted anonymous login SQLException seen when querying the linked server (SQLSRV_2).
See class net.sourceforge.jtds.jdbc.TdsCore, method createGssToken().
GSSName serverName = manager.createName( "MSSQLSvc/" + host + ":" + port, nameType );
Logger.println( "GSS: Using SPN " + serverName );
_gssContext = manager.createContext( serverName, mech, null, GSSContext.DEFAULT_LIFETIME );
_gssContext.requestMutualAuth( true ); // FIXME: may fail, check via _gssContext.getMutualAuthState()
** _gssContext.requestCredDeleg(true); //added**
Has anyone encountered a similar authentication issue against MS SQL linked servers when using the jTDS driver's Kerberos authentication support? Are there additional jTDS driver (or Java) settings/properties that can be specified to support credential delegation when the GSS Context is established?
I can provide detailed specifics on the environment tested and tested output. The general environment is listed as below -
jTDS v1.3.1
MS SQL Server (Microsoft SQL Server 2008 R2 (SP3) - 10.50.6220.0 (X64)
Kerberos 5 (specifying kerberos configuration and login files).
Java 1.8 (jre1.8.0_131)
Java VM arguments:
-Djava.security.krb5.debug=true
-Djava.security.krb5.conf=krb5.conf
-Djava.security.auth.login.config=login.conf
-Djavax.security.auth.useSubjectCredsOnly=false
Thank you,
-Rob
Hi Rob,,
I have exact same issue like you described.
Also, I have noticed that if I execute same procedure (which goes and fetches data from another linked sql server making this a double hop) using Microsoft JDBC driver procedure executes without a problem - and if I execute the same thing now using JTDS driver, it will also work, but will stop working after ~30 minutes.
I have checked Microsoft JDBC driver code and they also set 'credentials delegation' to true: https://github.com/Microsoft/mssql-jdbc/blob/dev/src/main/java/com/microsoft/sqlserver/jdbc/KerbAuthentication.java#L123
My plan is to modify JTDS code to support sql double hop by settings credentials delegation same way you did, but would be nice if this fix was applied here in official jtds version.
Not really sure if this will happen and who can do it?
Regards,
Mario
Last edit: Mario Zagar 2018-04-03