Am 2021-09-14 um 18:23 schrieb Tim Miller Dyck:
Hello,

I wanted to report an issue with Tomcat LDAP user authentication lookups with 
Tomcat container Kerberos security that I found in our environment when 
upgrading to version Tomcat 9.0.52 from 9.0.30 and what configuration settings 
bypassed the problem.

Here is our base pre-Tomcat upgrade configuration which was working for both 
LDAP user authentication and with Kerberos-enabled authentication (e.g. with 
the Tomcat Manager app).


   *   Tomcat 9.0.30 running on Windows Server 2019
   *   Microsoft OpenJDK packaging, build 11.0.12+7 64-bit
   *   Tomcat is authenticating users using LDAP queries to Windows Server 
2012R2 Active Directory controllers
   *   Tomcat server.xml LDAP configuration:

         <Realm className="org.apache.catalina.realm.JNDIRealm"

                 connectionURL="ldaps://dc1.myorg.com:636"

                 alternateURL="ldaps://dc2.myorg.com:636"

                 connectionName="dedicated-tomcat-ldap-u...@myorg.com"

                 connectionPassword="user-secret-password"

                 userBase="dc=myorg,dc=com"

                 userSearch="(&amp;(objectClass=user)(sAMAccountName={0}))"

                 userSubtree="true"

                 roleBase="dc=myorg,dc=com"

                 roleSearch="(&amp;(objectClass=group)(member={0}))"

                 roleSubtree="true"

                 roleNested="true"

                 roleName="cn"

                 adCompat="true"

         />


   *   We have some web apps that use Tomcat container Kerberos authentication, 
e.g. we configure the Tomcat Manager app WEB-INF\web.xml with


   <!-- Define the Login Configuration for this Application -->

   <login-config>

     <!-- Customization: switch Manager app authentication to use SPNEGO 
(Kerberos) to get transparent authentication instead of using BASIC auth with a login 
popup -->

     <auth-method>SPNEGO</auth-method>

     <realm-name>Tomcat Manager Application</realm-name>

   </login-config>

The same configuration was then upgraded to Tomcat 9.0.52 with otherwise all 
the same overall configuration in place (Kerberos settings, Java settings, cert 
settings, etc.).

The following problem then appeared when trying to log into the Manager app 
using SPNEGO/Kerberos (and also our web apps using Tomcat container Kerberos 
authentication).

From the Tomcat stderr file:


14-Sep-2021 07:00:32.196 SEVERE [https-jsse-nio-443-exec-10] 
org.apache.catalina.realm.JNDIRealm.getPrincipal Exception performing 
authentication

javax.naming.NamingException: LDAP connection has been closed; remaining name 
'dc=myorg,dc=com'

at java.naming/com.sun.jndi.ldap.LdapRequest.getReplyBer(LdapRequest.java:133)

at java.naming/com.sun.jndi.ldap.Connection.readReply(Connection.java:443)

at java.naming/com.sun.jndi.ldap.LdapClient.getSearchReply(LdapClient.java:639)

at java.naming/com.sun.jndi.ldap.LdapClient.search(LdapClient.java:562)

at java.naming/com.sun.jndi.ldap.LdapCtx.doSearch(LdapCtx.java:2014)

at java.naming/com.sun.jndi.ldap.LdapCtx.searchAux(LdapCtx.java:1873)

at java.naming/com.sun.jndi.ldap.LdapCtx.c_search(LdapCtx.java:1798)

at 
java.naming/com.sun.jndi.toolkit.ctx.ComponentDirContext.p_search(ComponentDirContext.java:392)

at 
java.naming/com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:358)

at 
java.naming/com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:341)

at 
java.naming/javax.naming.directory.InitialDirContext.search(InitialDirContext.java:267)

at org.apache.catalina.realm.JNDIRealm.getUserBySearch(JNDIRealm.java:1610)

at org.apache.catalina.realm.JNDIRealm.getUser(JNDIRealm.java:1447)

at org.apache.catalina.realm.JNDIRealm.getUser(JNDIRealm.java:1376)

at org.apache.catalina.realm.JNDIRealm.getPrincipal(JNDIRealm.java:2352)

at org.apache.catalina.realm.JNDIRealm.getPrincipal(JNDIRealm.java:2288)

at org.apache.catalina.realm.JNDIRealm.getPrincipal(JNDIRealm.java:2269)

at org.apache.catalina.realm.RealmBase.authenticate(RealmBase.java:504)

at org.apache.catalina.realm.CombinedRealm.authenticate(CombinedRealm.java:365)

at org.apache.catalina.realm.LockOutRealm.authenticate(LockOutRealm.java:194)

...

In testing with Tomcat ver. 9.0.52, I found the following:


   *   Using Manager with basic auth but still with LDAP user lookups worked - 
only Kerberos-enabled apps had problems with LDAP auth
   *   Switching our connectionURLs to use non-encrypted LDAP instead of LDAPS 
caused the problem to be resolved and LDAP+Kerberos to work again so it was 
something to do with use of SSL with LDAP (but we only want to use LDAPS, of 
course, for security)
   *   In the LDAP server.xml configuration, as per Tomcat documentation, these 
two settings are the defaults if not otherwise specified:

useDelegatedCredential="true"

spnegoDelegationQop="auth-conf "

      *   As per documentation, these settings cause a users's Kerberos 
credentials to be used for the LDAP lookup (if Kerberos credentials are 
available to Tomcat) instead of the specific LDAP connection username and 
password in the JNDIRealm configuration.
   *   I tried setting stripRealmForGss="false" (the default is true, where the 
domain is stripped from the username) - but has the same problem with both true and false 
settings
   *   I tried adding only the line spnegoDelegationQop="auth" and this caused 
the problem to be resolved with Kerberos+LDAP working again
      *   The options for spnegoDelegationQop are auth-conf (default, "authentication plus integrity and 
confidentiality protection"), auth-int ("authentication plus integrity") and auth 
("authentication only").
      *   I also tried auth-int, but this had the same 
"org.apache.catalina.realm.JNDIRealm.getPrincipal Exception performing 
authentication" error
   *   I then tested by adding only the line useDelegatedCredential="false" and 
this also caused the problem to be resolved with Kerberos+LDAP working again (presumably 
by having our Tomcat LDAP user used always for LDAP connection authentication and not 
using the end user's Kerberos credential for the LDAP connection)

As additional information, if relevant, our Windows domain controllers have the 
following LDAP connection security setting:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters\LdapEnforceChannelBinding
 = 1

From the Microsoft KB article at 
https://support.microsoft.com/en-us/topic/use-the-ldapenforcechannelbinding-registry-entry-to-make-ldap-authentication-over-ssl-tls-more-secure-e9ecfa27-5e57-8519-6ba3-d2c06b21812e
DWORD value: 1 indicates enabled, when supported. All clients that are running 
on a version of Windows that has been updated to support channel binding tokens 
(CBT) must provide channel binding information to the server. Clients that are 
running a version of Windows that has not been updated to support CBT do not 
have to do so. This is an intermediate option that allows for application 
compatibility.

I also tested previous versions of Tomcat and found the LDAP+Kerberos problem 
described started with Tomcat v9.0.31 (and worked with Tomcat v9.0.30).

My conclusion so far is that when using LDAP+Kerberos with Tomcat 9.0.52, the 
spnegoDelegationQop values of auth-conf and auth-int don't successfully 
authenticate any longer against our Windows domain controllers, but Tomcat 
9.0.30 (using the default auth-conf setting as I had not specified this setting 
at all) did authenticate successfully. Given that the problem starts with the 
auth-int setting, maybe the issue is the Kerberos delegation integrity 
connection setting.

Going through the Tomcat changelogs, the bug report could be related as it 
describes changes in this code area first released in Tomcat v9.0.31: 
https://bz.apache.org/bugzilla/show_bug.cgi?id=64011


This may well be some subtle interaction between Tomcat, the JVM and our Active 
Directory servers and may not be a Tomcat problem at all. I wanted to report it 
for comment and to let others know who may find the same issue in their own 
environments what worked for me so far.

It is very hard to answer to your requst because you mix a lot of things which do not belong together.
E.g.,
> javax.naming.NamingException: LDAP connection has been closed; remaining name 'dc=myorg,dc=com'
>
> at java.naming/com.sun.jndi.ldap.LdapRequest.getReplyBer(LdapRequest.java:133)

The other side or a middle box dropped the TCP connection. Likely RST sent. Nothing special. You are subject to bug: https://bugs.openjdk.java.net/browse/JDK-8273402 I have reported recently. Tomcat cannot properly recover from. If you have channels, try to have this fix backported to 8, 11 and 17. See my post "JNDIRealm does not retry on read timeouts or closed connections" from two weeks ago.

What is your actual request here? How to make LDAPS work? How to achieve LDAP Channel Binding? How to use Kerberos authentication without credential delegation?


M

PS: The JNDIRealm is way too generic to properly be usable with Active Directory

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to