Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connection when both "Force Enryption" and "Extended Protection" are active #963

Open
michaelenglert opened this issue Feb 13, 2019 · 53 comments
Assignees
Labels
Enhancement An enhancement to the driver. Lower priority than bugs. External Issue is due to an external source we do not control.

Comments

@michaelenglert
Copy link

michaelenglert commented Feb 13, 2019

Question

I'm trying to connect to a SQL Server (2012) using Windows Authentication where both Force Enryption is set to true and Extended Protection is set to required.

What I'm getting on the Client side is:

Login failed. The login is from an untrusted domain and cannot
be used with Windows authentication.
ClientConnectionId:<redacted>

Server side:

SSPI handshake failed with error code 0x80090346, state 46 while 
establishing a connection with integrated security; the connection 
has been closed. Reason: The Channel Bindings from this client are
missing or do not match the established Transport Layer Security (TLS) 
Channel. The service might be under attack, or the data provider
or client operating system might need to be upgraded to support
Extended Protection. Closing the connection. Client's supplied SSPI
channel bindings were incorrect
[CLIENT: <redacted>]

I've tried many different configuration options (client side) including:

  • sslProtocol all options
  • trustStore alongside trustStorePassword with a self signed cert
  • trustServerCertificate
  • serverSpn alongside corresponding server setting
  • encrypt

All results in the same error combination. OS instances are identical on Windows Sever 2012 R2 latest SP.

Any hints would be highly appreciated.

Thanks
Michael

@michaelenglert michaelenglert added the Question Used when a question is asked, as opposed to an issue being raised label Feb 13, 2019
@cheenamalhotra
Copy link
Member

Hi @michaelenglert

Please confirm if Client (Windows Server 2012 R2 in your case) has enabled Extended Protection support.

This blog will be worth looking into on how to enable it:
https://blogs.technet.microsoft.com/srd/2009/12/08/extended-protection-for-authentication/

More details about Windows Update required for Extended Protection support: https://support.microsoft.com/en-us/help/973917/description-of-the-update-that-implements-extended-protection-for-auth

@michaelenglert
Copy link
Author

Hi @cheenamalhotra,

confirmed as this is enabled by default in Windows Server 2012 R2.

@cheenamalhotra
Copy link
Member

cheenamalhotra commented Feb 14, 2019

Just to put myself better on this, the error you are receiving "The login is from an untrusted domain and cannot be used with Windows authentication" is coming due to lack of configuration on client side.

From the links above, you may wanna check

  • if extended protection is enabled by setting the value of the registry key HKLM\System\CurrentControlSet\Control\LSA\SuppressExtendedProtection to 0 on Client OS.
  • if SPN as provided in serverSPN connection property is registered in <extendedProtection> section of ApplicationHost.config file on server.

Since you are working with Kerberos negotiation, it is expected to be supported by default, further configuration for LmCompatibilityLevel may not be mandatory.

On the contrary, please also confirm:

  • Connection succeeds on disabling Extended Protection on Server and Kerberos setup is done properly.
  • What happens if a test application attempts connection from the same OS where SQL Server is present.

Please also provide your connection string with repro code if possible in a standalone Java class.

@michaelenglert
Copy link
Author

thanks for helping @cheenamalhotra

Using this Connection String jdbc:sqlserver://192.168.56.101:1433;serverSpn=MSSQLSvc/WIN-097Q29SOILR.corp.michi.com:1433;integratedSecurity=true;authenticationScheme=JavaKerberos;trustServerCertificate=true

  • Force Enryption is set to false --> Successful connection
  • Force Enryption is set to false --> Errors happen as seen above

I've checked the Kerberos setup using the Kerberos config tool and also registered the registry key HKLM\System\CurrentControlSet\Control\LSA\SuppressExtendedProtection to 0

@cheenamalhotra
Copy link
Member

Hi @michaelenglert

I hope you wanted to mention error occurs if Force Encryption is set to true and are you not passing encrypt=true in connection string?

@michaelenglert
Copy link
Author

Hi @cheenamalhotra

I'm sorry. I lost track of all the different setups. Same error happens also with encrypt=true in

@michaelenglert
Copy link
Author

Hi @cheenamalhotra it would be great if you have another hint for me :-)

@cheenamalhotra
Copy link
Member

Hi @michaelenglert

I'll try to reproduce this in my environment, as I'm not entirely sure if this is a configuration problem or something else. Let me know if you have any pointers to problem root cause.

@michaelenglert
Copy link
Author

that would be awesome @cheenamalhotra there is not much I did on the setup. Here's what I did on the Server side:

  • Basic Windows Server 2012 R2 Installation
  • Basic SQL Server 2012 Installation
  • Installed Active Directory on the same host
  • Configured Active Directory User to "Trust this User for delegation"
  • Configured Active Directory Computer to "Trust this computer for delegation"
  • Set Extended Protection for SQL Server to Required
  • Set Force Encryption for SQL Server to Yes - if set no No it works
  • Created a self signed certificate and configured the SQL Server to use it - also tried without it

On the Client Side I tried/used:

  • serverSpn=serverSpn
  • integratedSecurity=true
  • authenticationScheme=JavaKerberos
  • trustServerCertificate=true
  • encrypt=true
  • trustStore=storeName
  • trustStorePassword=storePassword

@cheenamalhotra
Copy link
Member

Thanks @michaelenglert for the details.

Out of curiosity, have you tried to connect with any of the other SQL Server drivers?

@cheenamalhotra
Copy link
Member

cheenamalhotra commented Feb 25, 2019

Hi @michaelenglert

I configured Force Protocol Encryption + Extended Protection on SQL Server 2012 and am able to connect using Kerberos.

I could connect with below properties set using SQLServerDataSource.

TrustStore trustStore = new TrustStore();
SQLServerDataSource ds = new SQLServerDataSource();
ds.setServerName("<your server name>");
ds.setTrustStore(trustStore.getFileName());
ds.setTrustStorePassword(TrustStore.TRUST_STORE_PASSWORD);
ds.setIntegratedSecurity(true);
ds.setEncrypt(true);
try (Connection con = ds.getConnection()) {
     System.out.println("Connected");
}

Also, it works without adding ds.setAuthenticationScheme("JavaKerberos"); as default Negotiation is set to Kerberos.

@cheenamalhotra
Copy link
Member

cheenamalhotra commented Feb 25, 2019

I followed same steps defined in https://blogs.technet.microsoft.com/srd/2009/12/08/extended-protection-for-authentication/ for configuring Client and Server. No extra configurations were needed.

On the contrary, if you face any problems with Certificate validation, you may try to provide "trustServerCertificate=true" in connection and can avoid setting any TrustStore.

@cheenamalhotra
Copy link
Member

Ok, looks like I am able to reproduce the error now, but the issue isn't dependent on Force Encryption Turned On/Off but on Extended Protection when set to "Required" on SQL Server Instance configuration window.

Anyways, I'll investigate more into it and let you know soon!

@cheenamalhotra
Copy link
Member

Hi @michaelenglert

Upon investigations I discovered that in order to work with both Extended Protection and Encryption on Connection, client needs to supply Channel Binding which is accomplished by the client transferring the SPN and the CBT to the server in a tamperproof fashion. In absence of which server will not accept any requests from client. More details can be found here.

As of now, the driver does not implement Channel Binding and thus this combination of Extended Protection + Force Encryption during connection is not supported. Turning one of them OFF will result in a successful connection, as you must have figured out too.

@michaelenglert
Copy link
Author

Hi @cheenamalhotra

Thanks. I really appreciate that you took the time to investigate this!!

Does it make sense to convert this question to an enhancement request then?!

Thanks again
Michael

@cheenamalhotra cheenamalhotra added Enhancement An enhancement to the driver. Lower priority than bugs. and removed Question Used when a question is asked, as opposed to an issue being raised labels Feb 27, 2019
@michaelenglert
Copy link
Author

thanks @cheenamalhotra

@salen2000
Copy link

Hi @cheenamalhotra
I encountered the exactly problem.
I don't quite understand the statement you post above,
"As of now, the driver does not implement Channel Binding and thus this combination of Extended Protection + Force Encryption during connection is not supported."
My question is
in order to make the connection support both "Extended Protection + Force Encryption", what should I do on the client side?

thank you in advance!

@rene-ye
Copy link
Member

rene-ye commented Aug 22, 2019

Hi @salen2000, you can't do anything on the client side as of now. Changes to the driver are needed to make this work.

@salen2000
Copy link

Hi @salen2000, you can't do anything on the client side as of now. Changes to the driver are needed to make this work.

Thanks Rene,
I found some article mentioned the "Extended Protection" is only supported by "SQL Native Client" (i.e. one of the driver, that only support ODBC and OLE DB), however, because I am using JDBC (another driver) to connect to SQL server.
Can I conclude, by using JDBC as of now, I cannot connect SQL Server with both "Extended Protection + Force Encryption" enabled?
This is the link about SQL Native Client
https://docs.microsoft.com/en-us/sql/relational-databases/native-client/sql-server-native-client?view=sql-server-2017
This is the link about Extended Protection only Support SQL Server Native Client
https://docs.microsoft.com/en-us/sql/tools/configuration-manager/protocols-for-mssqlserver-properties-advanced-tab?view=sql-server-2017

@cheenamalhotra
Copy link
Member

cheenamalhotra commented Aug 23, 2019

Hi @salen2000

Yes that is true for JDBC Driver, as I mentioned above as well, not with NTLM and Kerberos authentication. Other authentication modes are unaffected.

@ricardoaviz
Copy link

Hello cheenamalhotra,
Thanks for all valuable contributions from you side on this issue.

Do we have anyone working on this issue?

This is stuck now for 8 months and I don’t see any solution or roadmap to solve this.

Is it possible to prioritize this?

Thanks!
With best regards,

Ricardo Aviz
Siemens

@David-Engel
Copy link
Collaborator

@ricardoaviz Adding channel binding support (and thus, extended protection support) to the JDBC driver is on our future roadmap, but we do not have a specific timeline for it at this time. I've bumped it up the list a bit and I do think it's an important security feature but we'll have to see where it makes the cut when planning future releases.

@vinaykariyappa1
Copy link

com.microsoft.sqlserver.jdbc.SQLServerException: Login failed. The login is from an untrusted domain and cannot be used with Windows authentication. ClientConnectionId:dd5204e9-85ad-4625-be53-758b67062a5c
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:262)

Is this issue is resolved in any other new version of JDBC driver...

@ricardoaviz
Copy link

Hi Vinay,

What is your post about?

Can you please clarify your post?

Tks

@vinaykariyappa1
Copy link

Jre version we are using 1.8
Jdbc we are using 7.2
jdbc:sqlserver://;servername=server_name;integratedSecurity=true;
placed sqljdbc_auth.dll to C:\Program Files\Java\jre\bin and C:\Program Files\Java\jdk\bin folder.
getting below error "This Driver is not configured for integrated authentication". kindly help to resolve this issue.
will JDBC driver support integratedSecurity????

@ulvii
Copy link
Contributor

ulvii commented Mar 11, 2020

Hi @vinaykariyappa1 ,
Driver already supports Windows integrated authentication, try setting -Djava.library.path=path_to_DLL in your VM arguments.

@David-Engel
Copy link
Collaborator

@postfach33 There are no updates to share at this time. This issue is still in the backlog.

@mariush17
Copy link

@David-Engel and @peterbae Is there any timeline to implement the channel binding feature into the JDBC driver? We are working with Java in a Linux environment and need to access SQL Server databases with Extended Protection and Forced Encryption as this is a requirement from our organization. The implementation of the channel binding feature would help us a lot!

@David-Engel
Copy link
Collaborator

@mariush17 I'm sorry, there is no current timeline for this feature in the JDBC driver.

@juantarquino-ssb
Copy link

@David-Engel any news on adding support for channel binding feature into the JDBC driver?

@VeryVerySpicy
Copy link
Contributor

@juantarquino-ssb
Sorry but no update as of yet.

@juantarquino-ssb
Copy link

Is there any workaround for using integrated authentication with servers that have those two things enabled? or an alternative driver that does support channel binding for sql server? This issue is preventing us from using Java internally to connect to sql servers because we need to use integrated authentication in Windows.

@lilgreenbird
Copy link
Contributor

Hi @juantarquino-ssb

Channel binding support is on our radar, however unfortunately it did not make the cut for this semester, we will look will into this again when we plan for the next semester.

fyi, we do take into account user requests when we do planning, so if there is any feature you would like implemented we encourage you do fill out our survey. Thanks.

@tkyc
Copy link
Member

tkyc commented Jul 20, 2022

Just an update for those following the thread, we are still in the middle of investigating this.

From my initial investigation, to enable channel bindings in the driver I applied the following fix to the intAuthHandShake to KerbAuthentication.java file:

InetAddress initiator = InetAddress.getLocalHost();
InetAddress acceptor = InetAddress.getByName(con.activeConnectionProperties
                    .getProperty(SQLServerDriverStringProperty.SERVER_NAME.toString()));

ChannelBinding cb = new ChannelBinding(initiator, acceptor, null);
peerContext.setChannelBinding(cb);

However, the above change doesn't seem to have an impact and I still receive the login error. I'll continually post updates as I investigate.

Updates (I'll post brief updates in this post to avoid spam)

  • Aug 17th 2022 - Issue is still on my radar, investigating the difference between the JDBC driver and other drivers to narrow down cause
  • Sep 12th 2022 - This might not seem as trivial to implement as I initially thought. From what I learned, the channel binding negotiation needs to happen during the TLS handshake (not after, which was what I was doing). When I looked at how the other drivers implemented this, they all used native cpp code to do so through the SSPI api which takes care of TLS and channel binding altogether. Doing so natively in Java (what we want) isn't as straightforward, as there isn't an equivalent existing api that takes care of TLS and channel binding altogether (likely it will be a solution from scratch, which I'm still researching on since I have zero domain knowledge on this topic).
  • Sep 19th - After more research, I found out that bc-java provides a channel binding API. Using this API I fetched the CBT for tls-unique (from looking at other drivers, that's the tls channel binding type). However, login is still failing. I'm still trying to understand the reason.
  • Sep 20th - Channel binding for NTLM is working. I'm still in progress of trying to get it working for kerberos.

@Neustradamus
Copy link

@ all: It is official for TLS 1.3 Binding!

Details:

  • tls-unique for TLS =< 1.2
  • tls-exporter for TLS = 1.3

Thanks in advance.

@dineubr
Copy link

dineubr commented Sep 12, 2022

Just an update for those following the thread, we are still in the middle of investigating this.

From my initial investigation, to enable channel bindings in the driver I applied the following fix to the intAuthHandShake to KerbAuthentication.java file:

InetAddress initiator = InetAddress.getLocalHost();
InetAddress acceptor = InetAddress.getByName(con.activeConnectionProperties
                    .getProperty(SQLServerDriverStringProperty.SERVER_NAME.toString()));

ChannelBinding cb = new ChannelBinding(initiator, acceptor, null);
peerContext.setChannelBinding(cb);

However, the above change doesn't seem to have an impact and I still receive the login error. I'll continually post updates as I investigate.

Updates (I'll post brief updates in this post to avoid spam)

  • Aug 17th 2022 - Issue is still on my radar, investigating the difference between the JDBC driver and other drivers to narrow down cause

Hi @tkyc,
Would you have any updates regarding this investigation?

Regards,
Dineu

@Jeffery-Wasty
Copy link
Contributor

Hi @dineubr,

We're still working on this. Terry released an update in an edit to his most recent comment:

Updates (I'll post brief updates in this post to avoid spam)

  • Aug 17th 2022 - Issue is still on my radar, investigating the difference between the JDBC driver and other drivers to narrow down cause

@tkyc
Copy link
Member

tkyc commented Sep 28, 2022

Hey all, this will be the final update on channel binding/extended protection.

Channel binding is fully implemented and is proven to be working within the JDBC driver. However, there are still a few caveats to the implementation. As of right now, we are limited by the JDK. The JDK does not provide a way to get the clientVerifyData byte array in the TLS finished message (this byte array is used to calculate the channel binding information which is passed to the server in authentication). There was a ticket/request to expose the clientVerifyData byte array in the JDK, but it was rejected. However, it is possible to get around this by using reflection or using bouncy-castle's API to get the clientVerifyData.

In the case of reflection, it is too fragile and will require more overhead on our part to maintain (eg. we'll need to test this on all driver supported JDKs and even then it might only work on a select few specific JDK versions). And, since reflection is used, we need to use the --add-opens and --add-exports flags during runtime otherwise an exception is thrown.

In the case of using the bouncy-castle API, after discussing with the team, we'll need an approval from the security team which isn't likely to happen (we had past issues getting approval to use bouncy-castle). Regardless, even if bouncy-castle was approved for use, it only solves part of the problem (exposing the clientVerifyData for use). We would still need to use the --add-exports flag at runtime to expose the internal JDK class TlsChannelBindingImpl for use (again, this is another problem with the JDK).

For now, we'll need put this feature on hold as we are limited by the JDK.

TL;DR

Channel binding is implemented and is proven to be working, but isn't likely to be merged because of JDK blockers.

Reflection is used to get clientVerifyData byte array which is used to calculate channel binding data to send to server (JDK doesn't expose clientVerifyData from the TLS finished message).

  • Reflection is fragile and breaks easily if JDK code changes
  • Increased overhead on our part in maintaining and testing channel binding code
  • Support of channel binding would likely be in a select JDK versions if it becomes supported long term
  • Need to use flag during runtime for reflection of specific JDK class at runtime
  • Bouncy-castle can be used to get the clientVerifyData, but security team disapproves use.

Need to use flag at runtime to import internal JDK ChannelBinding class TlsChannelBindingImpl to zero address field byte arrays. (zeroing the address field byte arrays is a channel binding implementation detail within the driver).

  • The addressType field of the ChannelBinding object must be 0, but in the computeChannelBindings call in the JDK it's set to 255. To get around this, if a channel binding object is instantiated as TlsChannelBindingImpl it will be set to 0. However, TlsChannelBindingImpl isn't exposed publicly by the JDK.

Wiki doc with more details about channel binding feature

@lilgreenbird lilgreenbird added the External Issue is due to an external source we do not control. label Oct 11, 2022
@martin-guth
Copy link

I stumbled across this issue as well. A pity that it is now waiting on external factors.
Please clarify: I have tested with the following configs at the server:

  • Force Encryption: On; Exteded Protection:Required ---> Error (as detailed above)...was to be expected
  • Force Encryption: On; Extended Protection: Allowed --> Same error ...why?
  • Force Encryption: On; Extended Protection: Off --> works without error

Why is Extended Protection: Allowed not possible? AFAIK this is the setting at the server side which does not enforce Extended Protection.

@David-Engel
Copy link
Collaborator

Java is missing public APIs that allow channel binding to be implemented. The POC described above was accomplished via methods that are not suitable to production-level code.

@user1oc
Copy link

user1oc commented Jan 31, 2024

Hi are there any updates on this issue?
As per the last comment from @David-Engel and @tkyc, this feature was put on hold.

@David-Engel
Copy link
Collaborator

@user1oc No new updates. Lack of appropriate public Java APIs is still a blocker for this issue. I don't see that changing any time soon.

@ecki
Copy link
Contributor

ecki commented Feb 2, 2024

BTW it’s also an issue for http and ldap and really needs reconsideration on openjdk level. Maybe escalate it to the Microsoft Java team?

@tkyc
Copy link
Member

tkyc commented Feb 2, 2024

@ecki Yeah, we've considered that as an option, but for now even with support from the Microsoft Java team I don't see the openjdk team consenting to the required Java API changes to make this happen as these types of changes were requested in the past.

@ecki
Copy link
Contributor

ecki commented Feb 2, 2024

Force Encryption: On; Extended Protection: Allowed --> Same error ...why?

@martin-guth thats indeed problematic, I suspect the SSPI on the client think it can/should negotiate it and then Java does not add the token therefore corrupting the handshake which the server uses to abort. Would maybe a good idea to filter it out in the driver so it does not get negotiated.

@github-project-automation github-project-automation bot moved this to To be triaged in MSSQL JDBC Aug 28, 2024
@Jeffery-Wasty Jeffery-Wasty moved this from To be triaged to Backlog in MSSQL JDBC Aug 28, 2024
@postfach33
Copy link

I would actually relabel the Issue from 'Enhancement' to 'Security Issue' as we are forced to downgrade the complete Instance, because if just 1 Client still can't use Channel binding nowadays, all other clients have to use the downgraded security as well.

@ADror-Quest
Copy link

any update on when this will be fixed?

@lilgreenbird
Copy link
Contributor

hi @ADror-Quest

Unfortunately we don't have a timeline to address this as this feature is still currently blocked by a lack of TLS APIs in Java required to implement it.

We did work on this in a feature branch where we worked around this using reflection (channel-bindings) or Bouncy Castle (channel-bindings-bc) . These are not official solutions they will not be merged however you are welcome to take a look and build a version of the driver for your needs but please be aware this is not something that we officially support. Until there is a proper API available in Java this will not be something that will be supported in the driver.

@ecki
Copy link
Contributor

ecki commented Feb 2, 2025

If the driver Not yet accept Channel binding, it should not propose it (i.e. Filter the Bit out in the negotiation message), otherwise the opportunistic („allowed“) setting does not work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement An enhancement to the driver. Lower priority than bugs. External Issue is due to an external source we do not control.
Projects
Status: Backlog
Development

No branches or pull requests