IIRC, JNDIRealm can perform its queries in different styles depending on configuration (thus allowing for a lot of common, but somewhat convoluted code)

You can connect to JNDIRealm with an "admin like" role where you are always bound as the admin and you are looking up attributes about the suer which needs security rights. Then there is the other way by binding as the user to check authentication and roles.

While this doesn't immediately answer the question below - thats how JNDIRealm is coded.

-Tim

John Hyun wrote:
Hi all,

I believe there is a bug in the way JNDIRealm performs a bindAsUser. When using JNDIRealm and "bind" mode the relevant setting in server.xml will look like:

<Realm className="org.apache.catalina.realm.JNDIRealm" debug="99"
    connectionURL="ldaps://xxx.xxx.xxx"
    userPattern="uid={0},ou=xxx,dc=xxx,dc=xxx"
    roleBase="ou=xxx,dc=xxx,dc=xxx"
    roleName="cn"
    roleSearch="(uniqueMember={0})" />

With my tomcat (5.5.15) installation configured this way, I find that I am able to authenticate with the server but JNDIRealm is unable to enumerate my group memberships. Looking at the source code I see the following section in JNDIRealm.java/bindAsUser():

-------------

        // Set up security environment to bind as the user
        context.addToEnvironment(Context.SECURITY_PRINCIPAL, dn);
context.addToEnvironment(Context.SECURITY_CREDENTIALS, credentials);

        // Elicit an LDAP bind operation
        boolean validated = false;
        try {
            if (containerLog.isTraceEnabled()) {
                containerLog.trace("  binding as "  + dn);
            }
            attr = context.getAttributes("", null);
            validated = true;
        }
        catch (AuthenticationException e) {
            if (containerLog.isTraceEnabled()) {
                containerLog.trace("  bind attempt failed");
            }
        }

        // 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);
        }

    return (validated);

-------------

What this essentially does is add the user's uid and password to the DirContext to perform a bind, but then removes the uid and password from the context afterwards. Later on in the code when a getRoles() is performed, the lookup fails because the security principal/credentials are empty.

As an experiment I supplied the connectionName and connectionPassword in the realm config and everything worked. This, however, defeats the purpose of using bind mode and not everyone will be able to use this workaround (password read restrictions, etc).

I don't know if the solution is to leave the the user's credentials in the context but it doesn't seem to be working the way it is now. Considering that I haven't seen anyone else with this problem I'm assuming either hardly anyone uses LDAP with Tomcat or that nobody uses bind mode. Another possibility is that my company's LDAP server is breaking the connection between the bind and role search, thus causing a reconnect and that's when the lack of credentials exposes the problem.


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to