Bug 63026 - JNDIRealm fails to authenticate user with 2 trailing spaces CN
Summary: JNDIRealm fails to authenticate user with 2 trailing spaces CN
Status: RESOLVED FIXED
Alias: None
Product: Tomcat 8
Classification: Unclassified
Component: Catalina (show other bugs)
Version: 8.0.33
Hardware: PC All
: P2 minor (vote)
Target Milestone: ----
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-12-20 18:06 UTC by Dave Anuszewski
Modified: 2019-01-23 15:22 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dave Anuszewski 2018-12-20 18:06:06 UTC
Using JNDIRealm to authenticate users against Microsoft Active Directory fails if the AD user object has 2 trailing spaces in it's cn.  Realm is configured with adCompat="true" and userSearch="(sAMAccountName={0})".  

Debugging through the code the getUserBySearch() method ldap search returns a result with only the last space escaped, but the method getDistinquishedName() returns a dn with both spaces escaped.  In this scenario the bindAsUser() method will return false resulting in an authentication failure.  If I modify the dn returned from getDistinquishedName() to only escape the last space in the cn the bindAsUser() method will return true and the authentication will be successful.
Comment 1 Christopher Schultz 2018-12-21 02:52:58 UTC
Sounds miserable.

Any reason this user's username includes two – or even one – trailing space?

Since you debugged so successfully, would you care to prepare a patch for the JNDIRealm?
Comment 2 Michael Osipov 2018-12-21 14:44:57 UTC
(In reply to Dave Anuszewski from comment #0)
> Using JNDIRealm to authenticate users against Microsoft Active Directory
> fails if the AD user object has 2 trailing spaces in it's cn.  Realm is
> configured with adCompat="true" and userSearch="(sAMAccountName={0})".  
> 
> Debugging through the code the getUserBySearch() method ldap search returns
> a result with only the last space escaped, but the method
> getDistinquishedName() returns a dn with both spaces escaped.  In this
> scenario the bindAsUser() method will return false resulting in an
> authentication failure.  If I modify the dn returned from
> getDistinquishedName() to only escape the last space in the cn the
> bindAsUser() method will return true and the authentication will be
> successful.

Out of curiousity, why do you plague your users with username and password where you could use SPNEGO?
Comment 3 Mark Thomas 2019-01-22 17:29:45 UTC
Which version of Windows are you using? I'm using my default AD test environment built with 2k8r2 and the UI won't allow creating of users where the CN has trailing spaces. Alternatively, how are you creating those users?
Comment 4 Mark Thomas 2019-01-22 17:33:41 UTC
Ah.

net user "bug63026 " pwd /ADD

does the trick. Interestingly, if you specify multiple spaces Windows only escapes the last one in the UI. I wonder if this is an AD issue. I'll dig further as I don't necessarily trust what the UI is showing me.
Comment 5 Mark Thomas 2019-01-22 22:32:16 UTC
RFC 4514 (string representation of distinguished names) states that a space at the beginning or end of a string must be escaped (there are other escaping requirements but I am ignoring them for this discussion). Other characters may be escaped.

Any character can be escaped with "\nn" sequences. Some characters may be escaped with "\"

AD correctly escapes a space if it is the first or last character using "\ ".

It appears that the additional escaping observed originates in Java.

AD accepts queries using the same "\ " escaping it uses but does not accept any additional "\ " escaping.

AD accepts queries that use optional "\nn" escaping.

RFC 4145 (string representation of search filters) only refers to "\nn" escaping.

I'm currently looking at options to address this issue.
Comment 6 Mark Thomas 2019-01-23 15:22:06 UTC
Fixed in:
- trunk for 9.0.15 onwards
- 8.5.x for 8.5.38 onwards
- 7.0.x for 7.0.93 onwards

I ended up adding a new option that forces DNs to use \nn escaping - forceDnHexEscape.