Updated JLDAPLoginModule - security fixes!

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Updated JLDAPLoginModule - security fixes!

Russell Howe
First off, a list of what (stupid!) things the previous module let happen:

* User could log in as '*' with no password!
* Attempted logins with a blank username and a blank password were
accepted if the LDAP server accepted anonymous binds, which most do!

The above holes were prevented by requiring the username to match a
regular expression (see the usernamePattern member variable). This
pattern can be overridden in the JAAS configuration.

This is a JAAS LoginModule for Jetty (although porting to other
containers should be fairly trivial).

Unlike other LDAP authentication modules, this uses the LDAP server's
authentication to verify the supplied credentials. The LoginModule
attempts to bind to the LDAP server using the supplied credentials, and
then if the bind is successful, uses the connection to search for role
memberships.

Configuration is both flexible and poorly documented :)

*IMPORTANT* the code currently does a CLEARTEXT, SIMPLE BIND. That is,
the bind credentials (i.e. password) is transmitted to the LDAP server
IN THE CLEAR. Adding SSL support will be trivial, I just haven't done it
yet - feel free.

This is still a work in progress, and I make no guarantees as to its
robustness. I strongly recommend that you read the code and understand
what it all does before using it. My time is limited and I haven't been
concentrating very hard on writing this, so major loopholes may remain!
In fact, I strongly suggest that you don't use this at all - write your own!

If you have any questions, please feel free to ask me via the list. I'll
be away from Saturday (Eurovision day!) until Wednesday though, so you
might not get a timely reply :)

You will need the Novell LDAP stuff, as I couldn't get LDAP searches
using the '&' operator to work via JNDI. If someone wants to tell me how
to do it, feel free!

--
Russell Howe
[hidden email]

Today's Nemi: http://www.metro.co.uk/img/pix/nemi_may20.jpg

// ========================================================================
// $Id: JLDAPLoginModule.java,v 1.3 2005/05/20 12:12:07 russell_howe Exp $
// Copyright 2005 Russell Howe, BMT Salvage Ltd.
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.Principal;
import java.security.acl.Group;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;

import com.novell.ldap.LDAPAttribute;
import com.novell.ldap.LDAPConnection;
import com.novell.ldap.LDAPConstraints;
import com.novell.ldap.LDAPEntry;
import com.novell.ldap.LDAPException;
import com.novell.ldap.LDAPExtendedOperation;
import com.novell.ldap.LDAPExtendedResponse;
import com.novell.ldap.LDAPSearchResults;
import com.novell.ldap.extensions.GetBindDNRequest;
import com.novell.ldap.extensions.GetBindDNResponse;

import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.mortbay.jaas.JAASGroup;
import org.mortbay.jaas.JAASPrincipal;
import org.mortbay.jaas.JAASRole;
import org.mortbay.jaas.callback.ObjectCallback;
import org.mortbay.util.Credential;
import org.mortbay.util.Loader;

/* ---------------------------------------------------- */
/** LDAPLoginModule
 * <p>JAAS LoginModule to validate the user by trying to bind
 * to an LDAP directory as the user using the Novell LDAP API.
 *
 * @version 1.3 Fri May 20 2005
 * @author Russell Howe
 */
public class JLDAPLoginModule implements LoginModule {
        private static Log log = LogFactory.getLog(JLDAPLoginModule.class);

        private CallbackHandler callbackHandler = null;

        private boolean authenticated = false;
        private boolean committed = false;
       
        private Hashtable jndiEnv;
        private Map roleMappings;
       
        private String bindDNBase = null;
        private String placeholder = null;
        private String roleNameAttribute = null;
        private String roleObjectClass = null;
        private String roleMembershipAttribute = null;
        private String userFilterBase = null;
        private String roleFilter = null;
        private String roleObjectAttribute = null;
        private String userIdAttribute = null;
        private String baseDN = null;
        private String hostname = null;
        String usernamePattern = "^([^*]|..+)$"; // Must me at least one character, but it can't be "*"
        // Default - can be over-ridden by the config.
        private int port = 389;
        private int ldapVersion = LDAPConnection.LDAP_V3;
       
        private Subject subject = null;
        private Principal principal = null;
        private javax.security.auth.x500.X500Principal x500Principal = null;
        private Credential credential = null;
        private Group roleGroup = null;
       
        /** Reset private member variables
         *
         */
        private void resetState() {
                log.debug("Resetting LoginModule. authenticated = " + authenticated
                        + ", committed = " + committed);
                principal = null;
                x500Principal = null;
                credential = null;
                roleGroup = null;
        }
       
        /** Abort login
         * @return
         * @exception LoginException
         */
        public boolean abort() throws LoginException
        {
                log.debug("abort() called");
                resetState();
               
                boolean retVal = (authenticated && committed);
               
                log.debug("abort() returning " + retVal);
               
                return retVal;
        }
       
        /** Commit the authenticated user
         * @return
         * @exception LoginException
         */
        public boolean commit() throws LoginException
        {
                log.debug("commit() called. authenticated = " + authenticated
                        + ", committed = " + committed);
               
                if (authenticated) {
                        log.debug("User " + principal + " logged in");
                        subject.getPrincipals().add(principal);
                       
                        if (x500Principal != null) {
                                log.debug("Adding X.500 Principal to Subject: " + x500Principal.getName());
                                subject.getPrincipals().add(x500Principal);
                        } else {
                                log.debug("User has no X.500 Principal");
                        }
                       
                        subject.getPrivateCredentials().add(credential);
                        subject.getPrincipals().add(roleGroup);
                        committed = true;
                } else {
                        resetState();
                        committed = false;
                }
               
                log.debug("commit() returning " + committed);
                return committed;
        }
       
        private static String applyRoleMappings(Map mapping, String role) {
                for (Iterator roleMappingIterator = mapping.keySet().iterator(); roleMappingIterator.hasNext();) {
                        String pattern = (String)roleMappingIterator.next();
                        if (role.matches(pattern)) {
                                String newRole = (String)mapping.get(pattern);
                                log.debug("Role '" + role + "' matches rewrite rule '" + pattern + "'. Role rewritten to '" + newRole + "'");
                                role = newRole;
                                break;
                        }
                }
               
                return role;
        }
       
        /** Authenticate the user.
         * @return
         * @exception LoginException
         */
        public boolean login() throws LoginException {
                log.debug("login() called");
                if (callbackHandler == null)
                        throw new LoginException ("No callback handler");
                Callback[] callbacks = new Callback[2];
                callbacks[0] = new NameCallback("Enter user name");
                callbacks[1] = new ObjectCallback();
               
                String webUserName;
                Object webCredential;
               
                try {
                        callbackHandler.handle(callbacks);
                       
                        webUserName = ((NameCallback)callbacks[0]).getName();
                        webCredential = ((ObjectCallback)callbacks[1]).getObject();
                } catch (UnsupportedCallbackException e) {
                        throw new LoginException(e.toString());
                } catch (java.io.IOException e) {
                        throw new LoginException(e.toString());
                }
               
                if (webUserName == null) {
                        log.warn("No username supplied - authentication failed,");
                        authenticated = false;
                        return authenticated;
                }
               
                if (!webUserName.matches(usernamePattern)) {
                        log.warn("User name of \"" + webUserName + "\" does not match usernamePattern of \"" + usernamePattern + "\"");
                        authenticated = false;
                        return authenticated;
                }
               
                if (webCredential == null) {
                        authenticated = false;
                        return authenticated;
                        /* throw new LoginFailedException()?? */
                }
               
                String bindDN = bindDNBase.replaceAll(placeholder, webUserName);
                String userFilter = null;
                if (userFilterBase != null)
                        userFilter = userFilterBase.replaceAll(placeholder, webUserName);
               
                log.debug("bindDN = " + bindDN);
                if (userFilter != null)
                        log.debug("userFilter = " + userFilter);
               
                // Try to bind to LDAP as the user
                LDAPConnection conn  = new LDAPConnection();
                try {
                        conn.connect(hostname, port);
                        conn.bind(ldapVersion, bindDN, ((String)webCredential).getBytes("UTF8"));

                        LDAPConstraints constraints = new LDAPConstraints();
                        constraints.setReferralFollowing(true);
                        conn.setConstraints(constraints);
                       
                        authenticated = true;
                        roleGroup = new JAASGroup(JAASGroup.ROLES);
                       
                        //LDAPExtendedResponse response = conn.extendedOperation(new GetBindDNRequest());
                       
                        LDAPEntry user = null;
                        /*
                         * There seem to be bugs in Novell's LDAP stuff, so I'm commenting this out.
                         * Neither OpenLDAP nor Active Directory seem to support the GetBindDN ext. operation anyway.
                         */
                        /*if (((response.getResultCode()) == LDAPException.SUCCESS)
                                        && (response instanceof GetBindDNResponse)) {
                                String bindDNResponse = ((GetBindDNResponse)response).getIdentity();
                                log.info("You were logged in as: " + bindDNResponse);
                               
                                user = conn.read(bindDNResponse);
                        } else {
                                log.warn("GetBindDN extended operation failed. Perhaps your LDAP server doesn't support it?");
                        */
                        {
                                String[] attributesToReturn = null;
                               
                                if (roleObjectClass == null) {
                                        attributesToReturn = new String[1];
                                        attributesToReturn[0] = roleNameAttribute;
                                }
                               
                                LDAPSearchResults results = conn.search(baseDN, LDAPConnection.SCOPE_SUB, userFilter, attributesToReturn, false);
                               
                                if (results.getCount() > 1)
                                        log.warn("Search for user (" + userFilter + ") returned more than one result!");
                               
                                if (results.hasMore()) {
                                        user = results.next();
                                } else {
                                        log.info("User not found: " + webUserName + ". Searched for '" + userFilter + "'");
                                }
                        }
                       
                        if (user == null) {
                                log.warn("Couldn't find the logged in user in LDAP! Won't be able to perform any role lookups");
                        } else {
                                log.debug("Found user in LDAP directory. dn: " + user.getDN());
                                x500Principal = new javax.security.auth.x500.X500Principal(user.getDN());
                                if (roleObjectClass == null) {
                                        // roles are attributes of the user
                                        LDAPAttribute roleAttribute = user.getAttribute(roleNameAttribute);
                                       
                                        for (Enumeration roleNames = roleAttribute.getStringValues(); roleNames.hasMoreElements();) {
                                                String roleName = (String)roleNames.nextElement();
                                               
                                                log.debug("User is in role '" + roleName + "'");
                                                roleName = applyRoleMappings(roleMappings, roleName);
                                                log.debug("After applying mapping, role is '" + roleName + "'");
                                               
                                                roleGroup.addMember(new JAASRole(roleName));
                                        }
                                } else {
                                        // roles are seperate objectClasses
                                        // A user U is a member of role R:
                                        //    iff that user's identity I (value of U's 'userIdAttribute' attribute)
                                        //    is one of the values of R's 'roleMembershipAttribute' attribute
                                        //
                                        // Behaviour when U has a multivalued 'userIdAttribute' is undefined (though it
                                        // probably should be!)
                                       
                                        String userIdentity = null;
                                        if ("dn".equalsIgnoreCase(userIdAttribute))
                                                userIdentity = user.getDN();
                                        else
                                                userIdentity = user.getAttribute(userIdAttribute).getStringValue();
                                        String roleFilter = "(&(objectClass=" + roleObjectClass + ")(" + roleMembershipAttribute + "=" + userIdentity + "))";
                                       
                                        String[] attributesToReturn = new String[1];
                                       
                                        if (roleNameAttribute == null || "dn".equalsIgnoreCase(roleNameAttribute))
                                                attributesToReturn[0] = LDAPConnection.NO_ATTRS;
                                        else
                                                attributesToReturn[0] = roleNameAttribute;
                                       
                                        log.debug("Searching for roles using '" + roleFilter + "'");
                                       
                                        LDAPSearchResults results = conn.search(baseDN, LDAPConnection.SCOPE_SUB, roleFilter , null /*attributesToReturn*/,
                                        /*
                                        * If we only need the DN of the object to get the group name, don't
                                        * bother retrieving attribute values
                                        */
                                        /*!"dn".equalsIgnoreCase(roleNameAttribute)*/ false);
                                       
                                        log.debug("Found " + results.getCount() + " roles.");
                                       
                                        while (results.hasMore()) {
                                                LDAPEntry role = results.next();
                                               
                                                String roleName = null;
                                               
                                                if ("dn".equalsIgnoreCase(roleNameAttribute))
                                                        roleName = role.getDN();
                                                else {
                                                        LDAPAttribute roleAttribute = role.getAttribute(roleNameAttribute);
                                                        if (roleAttribute == null)
                                                                log.debug("  role does not have a '" + roleNameAttribute + "' attribute");
                                                        else
                                                                roleName = roleAttribute.getStringValue();
                                                }
                                               
                                                if (roleName != null) {
                                                        log.debug("User is in role '" + roleName + "'");
                                                        roleName = applyRoleMappings(roleMappings, roleName);
                                                        log.debug("After applying mapping, role is '" + roleName + "'");
                                                       
                                                        roleGroup.addMember(new JAASRole(roleName));
                                                }
                                        }
                                }
                        }
                       
                        principal = new JAASPrincipal(webUserName);
                       
                        log.debug("LDAP authentication succeeded!");
                } catch (LDAPException e) {
                        log.error(e.toString());
                } catch (java.io.UnsupportedEncodingException e) {
                        log.error(e.toString());
                }
               
                log.debug("login() returning " + authenticated);
                return authenticated;
        }
       
       
        /** Logout authenticated user
         * @return
         * @exception LoginException
         */
        public boolean logout() throws LoginException {
                subject.getPrincipals().remove(principal);
                subject.getPrivateCredentials().remove(credential);
                subject.getPrincipals().remove(roleGroup);
               
                return true;
        }
       
       
        /** Init LoginModule.
         * Called once by JAAS after new instance created.
         * @param subject
         * @param callbackHandler
         * @param sharedState
         * @param options
         */
        public void initialize(Subject subject,
                        CallbackHandler callbackHandler,
                        Map sharedState,
                        Map options) {
                log.debug("initialize() called");
               
                /* Mandatory parameters */
                hostname = (String)options.get("hostname");
                baseDN = (String)options.get("baseDN");
                bindDNBase = (String)options.get("bindDN");
                if (options.get("usernamePattern") != null)
                        usernamePattern = (String)options.get("usernamePattern");
               
                /* Optional parameters - see below for defaults */
                String authMethod = (String)options.get("authmethod");
                placeholder = (String)options.get("placeholder");
                try {
                        if (null != options.get("port"))
                                port = Integer.parseInt((String)options.get("port"));
                } catch (Exception e) {
                        log.warn("Unable to parse \"port\" option as a number - defaulting to port " + port);
                }
               
                if (placeholder == null)
                        placeholder = "#USERNAME#";
               
                if (authMethod == null)
                        authMethod = "simple";
               
                /* Optional parameters without defaults (i.e. default is null ) */
                userFilterBase = (String)options.get("userFilter");
                userIdAttribute = (String)options.get("userIdAttribute");
                roleNameAttribute = (String)options.get("roleNameAttribute");
                roleObjectClass = (String)options.get("roleObjectClass");
                roleMembershipAttribute = (String)options.get("roleMembershipAttribute");
               
                /* Finally, load in the role mappings */
               
                int roleMappingCount = 0;
               
                roleMappings = new HashMap();
               
                while (options.get("role" + roleMappingCount + ".pattern") != null) {
                        String rolePattern = (String)options.get("role" + roleMappingCount + ".pattern");
                        String roleMappedTo = (String)options.get("role" + roleMappingCount + ".mappedTo");
                       
                        if (rolePattern == null || roleMappedTo == null) {
                                if (rolePattern == null)
                                        log.warn("Missing role" + roleMappingCount + ".pattern entry in JAAS configuration.");
                                if (roleMappedTo == null)
                                        log.warn("Missing role" + roleMappingCount + ".mappedTo entry in JAAS configuration.");
                                log.error("Ignored role" + roleMappingCount);
                        } else {
                                if (roleMappings.put(rolePattern, roleMappedTo) != null)
                                        log.warn("role" + roleMappingCount + " has the same pattern as a previous entry! Previous entry ignored. role" + roleMappingCount + " takes priority.");
                                else
                                        log.debug("Added role mapping from '" + rolePattern + "' to '" + roleMappedTo + "' (role" + roleMappingCount + ")");
                        }
                        roleMappingCount++;
                }
               
                log.debug("hostname = " + hostname);
                log.debug("baseDN = " + baseDN);
                log.debug("bindDN = " + bindDNBase);
                log.debug("usernamePattern = " + usernamePattern);
                log.debug("placeholder = " + placeholder);
                log.debug("authmethod = " + authMethod);
                log.debug("userIdAttribute = " + userIdAttribute);
                log.debug("userFilter = " + userFilterBase);
                log.debug("roleNameAttribute = " + roleNameAttribute);
                log.debug("roleObjectClass = " + roleObjectClass);
                log.debug("roleMembershipAttribute = " + roleMembershipAttribute);

                this.subject = subject;
                this.callbackHandler = callbackHandler;
        }
}

// Example JAAS config file for JLDAPLoginModule

some_realm {
// This looks up an account in LDAP and also places the user into a role
// named after the username.

// We use this for emulation of the 'old days' when whole groups of users
// shared the same login.
        org.wreckage.security.JLDAPLoginModule SUFFICIENT
        hostname="ldap-server.domain.com"
        // This is the pattern we use to create the bind DN for the LDAP server
        // If the bind succeeds, using the supplied credentials then a login
        // is considered successful and the LDAP server is queried for group
        // (role) membership (but only if at least roleNameAttribute is defined)
        bindDN="uid=#USERNAME#,ou=Legacy Usernames,dc=domain,dc=com"
        // Once logged in, we need to find the user's entry.
        // This is how we do it
        userFilter="(&(objectClass=account)(uid=#USERNAME#))"
        // A search needs a base
        baseDN="ou=Legacy Usernames,dc=domain,dc=com"
        userIdAttribute="uid"
        roleNameAttribute="uid"
        ;
// Standard POSIXy users and groups stored in LDAP using the OpenLDAP schemas
// as created by the migrationtools
        org.wreckage.security.JLDAPLoginModule SUFFICIENT
        hostname="ldap-server.domain.com"
        bindDN="uid=#USERNAME#,ou=Users,dc=domain,dc=com"
        baseDN="dc=domain,dc=com"
        userFilter="(&(objectClass=posixAccount)(uid=#USERNAME#))"
        // The user is referred in the group entries via the value that this
        // attribute has in the user's entry
        userIdAttribute="uid"
        // Roles are entries with this objectClass
        roleObjectClass="posixGroup"
        // The name of the role should be taken as the value of this attribute
        // of the role objectClass
        roleNameAttribute="cn"
        // A user is considered a member of the group if the group has one of
        // these attributes with a value of 'userIdAttribute' (see above)
        roleMembershipAttribute="memberUid"
        // We can rename roles as returned from LDAP
        role0.pattern="someGroupJavaDoesn'tKnowAbout"
        role0.mappedTo="someOtherGroup"
        ;
// One way to do it with Active Directory
        org.wreckage.security.JLDAPLoginModule SUFFICIENT
        // No, we don't yet do SSL. Patches welcome!
        hostname="active-directory.domain.com"
        // Yes, AD allows you to bind using this as a DN
        bindDN="#USERNAME#@domain.com"
        baseDN="dc=domain,dc=com"
        // Apparently objectCategory is a faster match than objectClass with AD
        userFilter="(&(objectCategory=user)(userPrincipalName=#USERNAME#@domain.com))"
        // The user is referred to by DN in the 'group' objectClass
        userIdAttribute="dn"
        // Groups in AD are of objectC{lass,ategory} 'group' in AD
        roleObjectClass="group"
        // The group's CN will do as its name
        roleNameAttribute="cn"
        // This (multi-valued) attribute of the 'group' objectClass contains
        // the DNs of users who are members of the group.
        roleMembershipAttribute="member"
        role0.pattern="Group 1"
        role0.mappedTo="role1"
        role1.pattern="Group 2"
        role1.mappedTo="role2"
        role2.pattern="Domain Users"
        role2.mappedTo="users"
        ;
// This is another way to do it with AD.
// Groups a user is a member of are available by looking at the 'memberOf'
// multi-valued attribute of the 'user' object.
// This is a bit quicker, as we don't need to go searching the directory for
// 'group' objects.
        org.wreckage.security.JLDAPLoginModule SUFFICIENT
        hostname="active-directory.domain.com"
        bindDN="#USERNAME#@domain.com"
        baseDN="dc=domain,dc=com"
        userFilter="(&(objectCategory=user)(userPrincipalName=#USERNAME#@domain.com))"
        roleNameAttribute="memberOf"
        role0.pattern="CN=Group 1,CN=Users,DC=domain,DC=com"
        role0.mappedTo="role1"
        role1.pattern="CN=Group 2,CN=Users,DC=domain,DC=com"
        role1.mappedTo="role2"
        ;
// Note that the AD ones should probably be duplicated for each domain
// controller, to allow logins to succeed if one goes down (I think that works
// - the LDAP stuff may possibly throw weird exceptions though. Please test!)
};

smime.p7s (4K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Updated JLDAPLoginModule - security fixes!

Russell Howe
Russell Howe wrote:
> You will need the Novell LDAP stuff

Which is available here!

http://www.openldap.org/jldap/

Just stick ldap.jar somewhere in the classpath.

--
Russell Howe
[hidden email]

Today's Nemi: http://www.metro.co.uk/img/pix/nemi_may20.jpg

smime.p7s (4K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Updated JLDAPLoginModule - searching with JNDI/LDAP

lwoggardner
In reply to this post by Russell Howe
Russell Howe wrote:

>
> You will need the Novell LDAP stuff, as I couldn't get LDAP searches
> using the '&' operator to work via JNDI. If someone wants to tell me how
> to do it, feel free!
>
>

The normal LDAP search syntax works for me using simple JNDI code.

ie "(&(objectClass=account)(uid=USERNAME))" passed into a search method similar to below.

I've used this kind of code to do this against OpenLDAP and SunOne/Netscape LDAP servers
but not against ActiveDirectory or Novell and not for anything requiring the robustness of a login module!

Cheers,
        Grant.

     public Collection search(String searchString) {

         DirContext dirContext = getDirectoryContext();

         try {

             NamingEnumeration names = dirContext.search("", searchString, new SearchControls());
             while (names.hasMoreElements()) {

                 Object nextElement = names.nextElement();
                 SearchResult searchResult = (SearchResult) nextElement;
                 //Now do whatever you want with searchResult.getAttributes());
                ...

             }
         } catch (NamingException e) {
             throw new RuntimeException("Naming exception searching for " + searchString, e);
         } finally {
             cleanup(dirContext);
         }

     private DirContext getDirectoryContext() {

         try {
             return (DirContext) new InitialDirContext(_env).lookup(_ldapUrlString);
         } catch (NamingException e) {
             throw new RuntimeException("Can't connect to ldap", e);
         }
     }




-------------------------------------------------------
This SF.Net email is sponsored by Oracle Space Sweepstakes
Want to be the first software developer in space?
Enter now for the Oracle Space Sweepstakes!
http://ads.osdn.com/?ad_id=7412&alloc_id=16344&op=click
_______________________________________________
jetty-discuss mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jetty-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Updated JLDAPLoginModule - searching with JNDI/LDAP

jan_bartel
Hi Russell,

Have you had a chance to look at Grant's suggestion yet? I'd like to
make a new Jetty release soon and I'd like to include the LDAP module,
but it needs to be pure JNDI api ....

thanks
Jan



Grant Gardner wrote:

> Russell Howe wrote:
>
>>
>> You will need the Novell LDAP stuff, as I couldn't get LDAP searches
>> using the '&' operator to work via JNDI. If someone wants to tell me how
>> to do it, feel free!
>>
>>
>
> The normal LDAP search syntax works for me using simple JNDI code.
>
> ie "(&(objectClass=account)(uid=USERNAME))" passed into a search method
> similar to below.
>
> I've used this kind of code to do this against OpenLDAP and
> SunOne/Netscape LDAP servers
> but not against ActiveDirectory or Novell and not for anything requiring
> the robustness of a login module!
>
> Cheers,
>     Grant.
>
>     public Collection search(String searchString) {
>
>         DirContext dirContext = getDirectoryContext();
>
>         try {
>
>             NamingEnumeration names = dirContext.search("",
> searchString, new SearchControls());
>             while (names.hasMoreElements()) {
>
>                 Object nextElement = names.nextElement();
>                 SearchResult searchResult = (SearchResult) nextElement;
>                 //Now do whatever you want with
> searchResult.getAttributes());
>         ...
>
>             }
>         } catch (NamingException e) {
>             throw new RuntimeException("Naming exception searching for "
> + searchString, e);
>         } finally {
>             cleanup(dirContext);
>         }
>
>     private DirContext getDirectoryContext() {
>
>         try {
>             return (DirContext) new
> InitialDirContext(_env).lookup(_ldapUrlString);
>         } catch (NamingException e) {
>             throw new RuntimeException("Can't connect to ldap", e);
>         }
>     }
>
>
>
>
> -------------------------------------------------------
> This SF.Net email is sponsored by Oracle Space Sweepstakes
> Want to be the first software developer in space?
> Enter now for the Oracle Space Sweepstakes!
> http://ads.osdn.com/?ad_id=7412&alloc_id=16344&op=click



-------------------------------------------------------
This SF.Net email is sponsored by Yahoo.
Introducing Yahoo! Search Developer Network - Create apps using Yahoo!
Search APIs Find out how you can build Yahoo! directly into your own
Applications - visit http://developer.yahoo.net/?fr=offad-ysdn-ostg-q22005
_______________________________________________
jetty-discuss mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jetty-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Updated JLDAPLoginModule - searching with JNDI/LDAP

Russell Howe
Jan Bartel wrote:
> Hi Russell,
>
> Have you had a chance to look at Grant's suggestion yet? I'd like to
> make a new Jetty release soon and I'd like to include the LDAP module,
> but it needs to be pure JNDI api ....

Not yet.. I was actually looking at LDAP stuff just now though, so let
me take a peek...

--
Russell Howe
[hidden email]

Today's Nemi: http://www.metro.co.uk/img/pix/nemi_may31.jpg

smime.p7s (4K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Re: Updated JLDAPLoginModule - searching with JNDI/LDAP

Russell Howe
In reply to this post by jan_bartel
Jan Bartel wrote:
> Hi Russell,
>
> Have you had a chance to look at Grant's suggestion yet? I'd like to
> make a new Jetty release soon and I'd like to include the LDAP module,
> but it needs to be pure JNDI api ....

Hm, well I've half got it working, but I'm falling asleep at the desk
here. Been a long couple of weeks.

I might have something that almost sorta works tomorrow though, and I
guess something that might not have so many loopholes the day after :)

--
Russell Howe
[hidden email]

Today's Nemi: http://www.metro.co.uk/img/pix/nemi_may31.jpg

smime.p7s (4K) Download Attachment