« Return to Thread: RE: JNDIRealm

Re: JNDIRealm

by Seth Leger :: Rate this Message:

Reply to Author | View in Thread

This patch will have some offset problems because it's off of my working
copy of the JNDIRealm class. But you should be able to get the general
idea of what's going on here.

-- Seth

Henri Gomez wrote:

> Do you have a patch against the current JNDIRealm ?
>
> 2008/4/22, Seth Leger <seth.leger@...>:
>  
>> Henri Gomez wrote:
>>
>>    
>>> I do some search today and debugged TC 6.0.x trunk from my eclipse.
>>> Authentification works great and the only remaining problem it so
>>> setup roles in AD for users.
>>>
>>> I used :
>>>
>>>    <Realm
>>>      
>> className="org.apache.catalina.realm.JNDIRealm"
>>    
>>>         connectionURL="ldap://ldap.mycorp.com:389"
>>>         alternateURL="ldap://ldap.mycorp.com:389"
>>>
>>>      
>> connectionName="cn=someldapaccounttobind,ou=MyCorp
>>    
>>> Users,dc=mycorp,dc=com"
>>>
>>>      
>> connectionPassword="someldapaccounttobindpassword"
>>    
>>>           userBase="ou=MyCorp Users,dc=mycorp,dc=com"
>>>           userSearch="(sAMAccountName={0})"
>>>           userSubtree="true"
>>>           referrals="follow"
>>>           userRoleName="memberOf"
>>>           debug="true"
>>>           />
>>>
>>>
>>>      
>>  Yes, this use case will work with the current Tomcat 6.0.X JNDIRealm code
>> because your Active Directory administrator has given you search credentials
>> for the Active Directory server
>> (cn=someldapaccounttobind,ou=MyCorpUsers,dc=mycorp,dc=com/someldapaccounttobindpassword).
>> But not all Active Directory administrators are willing to give out a set of
>> credentials like this (for instance, a strict, enterprise environment where
>> password access is strictly controlled).
>>
>>  My patch removes that requirement from the JNDIRealm. Instead of relying on
>> a hard-coded value for authentication, it can fall back to using the
>> credentials being supplied to the authenticate() call to perform the JNDI
>> search (which will succeed because users have permissions to view their own
>> LDAP object instance, as far as I know this is always true). The password is
>> never stored; it is only transmitted at login time to the server (and this
>> transmission can be protected from interception with LDAP over SSL).
>>
>>  It's a pretty minor change, written similarly to the way that the current
>> JNDIRealm code retries during connection timeouts.
>>
>>  Seth Leger
>>  Sr. Software Engineer
>>  Raritan, Inc.
>>
>> ---------------------------------------------------------------------
>>  To unsubscribe, e-mail: dev-unsubscribe@...
>>  For additional commands, e-mail: dev-help@...
>>
>>
>>    
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@...
> For additional commands, e-mail: dev-help@...
>
>
>  

Index: JNDIRealm.java
===================================================================
@@ -943,7 +943,7 @@
                  curUserPattern < userPatternFormatArray.length;
                  curUserPattern++) {
                 // Retrieve user information
-                User user = getUser(context, username);
+                User user = getUser(context, username, credentials);
                 if (user != null) {
                     try {
                         // Check the user's credentials
@@ -968,7 +968,7 @@
             return null;
         } else {
             // Retrieve user information
-            User user = getUser(context, username);
+            User user = getUser(context, username, credentials);
             if (user == null)
                 return (null);
 
@@ -1001,7 +1001,7 @@
      *
      * @exception NamingException if a directory server error occurs
      */
-    protected User getUser(DirContext context, String username)
+    protected User getUser(DirContext context, String username, String credentials)
         throws NamingException {
 
         User user = null;
@@ -1017,7 +1017,7 @@
 
         // Use pattern or search for user entry
         if (userPatternFormatArray != null) {
-            user = getUserByPattern(context, username, attrIds);
+            user = getUserByPattern(context, username, credentials, attrIds);
         } else {
             user = getUserBySearch(context, username, attrIds);
         }
@@ -1041,6 +1041,7 @@
      */
     protected User getUserByPattern(DirContext context,
                                               String username,
+                                              String credentials,
                                               String[] attrIds)
         throws NamingException {
 
@@ -1056,6 +1057,32 @@
             attrs = context.getAttributes(dn, attrIds);
         } catch (NameNotFoundException e) {
             return (null);
+        } catch (NamingException e) {
+            // If the getAttributes() call fails, try it again with the
+            // credentials of the user that we're searching for
+            try {
+                // Set up security environment to bind as the user
+                context.addToEnvironment(Context.SECURITY_PRINCIPAL, dn);
+                context.addToEnvironment(Context.SECURITY_CREDENTIALS, credentials);
+
+                attrs = context.getAttributes(dn, attrIds);
+            } finally {
+                // Restore the original security environment
+                if (connectionName != null) {
+                    context.addToEnvironment(Context.SECURITY_PRINCIPAL,
+                                             connectionName);
+                } else {
+                    context.removeFromEnvironment(Context.SECURITY_PRINCIPAL);
+                }
+
+                if (connectionPassword != null) {
+                    context.addToEnvironment(Context.SECURITY_CREDENTIALS,
+                                             connectionPassword);
+                }
+                else {
+                    context.removeFromEnvironment(Context.SECURITY_CREDENTIALS);
+                }
+            }
         }
         if (attrs == null)
             return (null);
@@ -1628,7 +1655,7 @@
                                                   String username)
         throws NamingException {
         
-        User user = getUser(context, username);
+        User user = getUser(context, username, null);
         
         return new GenericPrincipal(this, user.username, user.password ,
                 getRoles(context, user));


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@...
For additional commands, e-mail: dev-help@...

 « Return to Thread: RE: JNDIRealm