Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Purpose:

...

This

...

document

...

is

...

a

...

sampleon

...

how

...

to

...

resolve

...

http://www.ja-sig.org/issues/browse/CAS-664.

...

Environment:

...

Server:

...

Fedora

...

10

...

+

...

CAS

...

3.3.1

...

+

...

Tomcat

...

5.5.27

...

+

...

OpenLDAP

...

2.4.12

...

+

...

Cyrus

...

SASL

...

2.1.22

...

Client:

...

Fedora

...

10

...

+

...

Firefox

...

3

...

(in

...

the

...

same

...

computor

...

with

...

Server)

...

Realm:

...

dell-d830

...

Config OpenLDAP DIGEST-MD5

...

1.

...

Edit

...

/etc/slapd.conf,

...

add

...

the

...

following:

...

Code Block

password-hash {CLEARTEXT}
sasl-realm dell-d830

authz-regexp
    uid=(\[^,\]*),cn=dell-d830,cn=digest-md5,cn=auth
    ldap:///o=langhua,c=cn??sub?(uid=$1)



h4. 

2.

...

/etc/init.d/ldap

...

restart

3.

...

Add

...

a

...

user

...

to

...

OpenLDAP

...

uid=test,ou=beijing,o=langhua,c=cn

...

userPassword

...

is

...

111111

...

Config

...

SASL

...

DIGEST-MD5

...

1.

...

Add

...

a

...

user

...

to

...

SASL

Code Block

*saslpasswd2 \-c test*

Password: *111111*

Again (for verification): *111111*

h4. 

2.

...

Test

...

SASL

...

DIGEST-MD5

...

Open

...

a

...

console

...

and

...

run:

...

Code Block
*sasl2-sample-server*

Console output:

trying 2, 1, 6
trying 10, 1, 6
bind: Address already in use
 

Open

...

another

...

console

...

and

...

run:

Code Block

*sasl2-sample-client \-m DIGEST-MD5 localhost*

Console output:

receiving capability list... recv:
{53}
PLAIN CRAM-MD5 ANONYMOUS LOGIN NTLM GSSAPI DIGEST-MD5
PLAIN CRAM-MD5 ANONYMOUS LOGIN NTLM GSSAPI DIGEST-MD5
send:
{10}
DIGEST-MD5
send:
{1}
N
recv:
{114}
nonce="i7iU89Jmqj2S8BmExkXbkTwV8TaMdOrh1T803Q2UHw4=",realm="dell-d830",qop="auth",charset=utf-8,algorithm=md5-sess
please enter an authentication id:
please enter an authorization id: *test*
Password: *111111*
send:
{231}
username="test",realm="dell-d830",nonce="i7iU89Jmqj2S8BmExkXbkTwV8TaMdOrh1T803Q2UHw4=",cnonce="h3prPJs4mCG0XAUJNiEhlISg0BjgS2UcRenpY6S3IuI=",nc=00000001,qop=auth,digest-uri="rcmd/localhost",response=e8f55dabc929152361c6cdcbb0d22532
recv:
{40}
rspauth=44285575e382f452e158665a2727a493
send:
{0}

successful authentication
closing connection
 

DIGEST-MD5

...

is

...

ok.

...

Config

...

CAS

1.

...

Create

...

/cas-server-support-ldap/src/main/java/org/jasig/cas/adaptors/ldap/BindLdapDigestMd5AuthenticationHandler.java

...

:=|=}
Code Block
title
BindLdapDigestMd5AuthenticationHandler.java
borderStyle
solid
/*
 * Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
 * distributed with this file and available online at
 * http://www.ja-sig.org/products/cas/overview/license/
 */
package org.jasig.cas.adaptors.ldap;

import org.jasig.cas.authentication.handler.AuthenticationException;
import org.jasig.cas.authentication.principal.UsernamePasswordCredentials;
import org.inspektr.common.ioc.annotation.IsIn;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;

/**
 * Handler to do LDAP bind.
 * 
 * @author Scott Battaglia
 * @version $Revision: 44152 $ $Date: 2008-08-13 15:18:57 -0400 (Wed, 13 Aug
 *          2008) $
 * @since 3.0.3
 */
public class BindLdapDigestMd5AuthenticationHandler extends
		AbstractLdapDigestMd5AuthenticationHandler {

	/** The default maximum number of results to return. */
	private static final int DEFAULT_MAX_NUMBER_OF_RESULTS = 1000;

	/** The default timeout. */
	private static final int DEFAULT_TIMEOUT = 1000;

	/** The search base to find the user under. */
	private String searchBase;

	/** The scope. */
	@IsIn( { SearchControls.OBJECT_SCOPE, SearchControls.ONELEVEL_SCOPE,
			SearchControls.SUBTREE_SCOPE })
	private int scope = SearchControls.SUBTREE_SCOPE;

	/** The maximum number of results to return. */
	private int maxNumberResults = DEFAULT_MAX_NUMBER_OF_RESULTS;

	/** The amount of time to wait. */
	private int timeout = DEFAULT_TIMEOUT;

	/** Boolean of whether multiple accounts are allowed. */
	private boolean allowMultipleAccounts;

	protected final boolean authenticateUsernamePasswordInternal(
			final UsernamePasswordCredentials credentials)
			throws AuthenticationException {

		DirContext context;

		context = this.getContextSource().getDirContext(
				credentials.getUsername(), credentials.getPassword());

		if (context == null) {
			return false;
		}

		return true;
	}

	protected String composeCompleteDnToCheck(final String dn,
			final UsernamePasswordCredentials credentials) {
		return dn;
	}

	private final SearchControls getSearchControls() {
		final SearchControls constraints = new SearchControls();
		constraints.setSearchScope(this.scope);
		constraints.setReturningAttributes(new String[0]);
		constraints.setTimeLimit(this.timeout);
		constraints.setCountLimit(this.maxNumberResults);

		return constraints;
	}

	/**
	 * Method to return whether multiple accounts are allowed.
	 * 
	 * @return true if multiple accounts are allowed, false otherwise.
	 */
	protected boolean isAllowMultipleAccounts() {
		return this.allowMultipleAccounts;
	}

	/**
	 * Method to return the max number of results allowed.
	 *

	 * @return the maximum number of results.
	 */
	protected int getMaxNumberResults() {
		return this.maxNumberResults;
	}

	/**
	 * Method to return the scope.
	 * 
	 * @return the scope
	 */
	protected int getScope() {
		return this.scope;
	}

	/**
	 * Method to return the search base.
	 * 
	 * @return the search base.
	 */
	protected String getSearchBase() {
		return this.searchBase;
	}

	/**
	 * Method to return the timeout.
	 *

	 * @return the timeout.
	 */
	protected int getTimeout() {
		return this.timeout;
	}

	public final void setScope(final int scope) {
		this.scope = scope;
	}

	/**
	 * @param allowMultipleAccounts
	 *            The allowMultipleAccounts to set.
	 */
	public void setAllowMultipleAccounts(final boolean allowMultipleAccounts) {
		this.allowMultipleAccounts = allowMultipleAccounts;
	}

	/**
	 * @param maxNumberResults
	 *            The maxNumberResults to set.
	 */
	public final void setMaxNumberResults(final int maxNumberResults) {
		this.maxNumberResults = maxNumberResults;
	}

	/**
	 * @param searchBase
	 *            The searchBase to set.
	 */
	public final void setSearchBase(final String searchBase) {
		this.searchBase = searchBase;
	}

	/**
	 * @param timeout
	 *            The timeout to set.
	 */
	public final void setTimeout(final int timeout) {
		this.timeout = timeout;
	}
}
{code}

2. Create /cas-server-support-ldap/src/main/java/org/jasig/cas/adaptors/ldap/AbstractLdapDigestMd5AuthenticationHandler.java

Code Block
titleAbstractLdapDigestMd5AuthenticationHandler.java

/*
 * Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
 * distributed with this file and available online at
 * http://www.ja-sig.org/products/cas/overview/license/
 */
package org.jasig.cas.adaptors.ldap;

import org.jasig.cas.adaptors.ldap.util.AuthenticatedLdapDigestMd5ContextSource;
import org.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;
import org.inspektr.common.ioc.annotation.NotNull;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.util.Assert;

/**
 * Abstract class to handle common LDAP functionality.
 *
 * @author Scott Battaglia
 * @version $Revision: 42776 $ $Date: 2008-01-04 09:15:42 -0500 (Fri, 04 Jan 2008) $
 * @since 3.0.3
 */
public abstract class AbstractLdapDigestMd5AuthenticationHandler extends
    AbstractUsernamePasswordAuthenticationHandler implements InitializingBean {

    /** LdapTemplate to execute ldap queries. */
    @NotNull
    private LdapTemplate ldapTemplate;

    /** Instance of ContextSource */
    @NotNull
    private AuthenticatedLdapDigestMd5ContextSource contextSource;

    /** The filter path to the uid of the user. */
    @NotNull
    private String filter;

    /** Whether the LdapTemplate should ignore partial results. */
    private boolean ignorePartialResultException = false;

    /**
     * Method to set the datasource and generate a JdbcTemplate.
     *
     * @param contextSource the datasource to use.
     */
    public final void setContextSource(final AuthenticatedLdapDigestMd5ContextSource contextSource) {
        this.contextSource = contextSource;
        this.ldapTemplate = new LdapTemplate(contextSource);
    }

    public final void setIgnorePartialResultException(final boolean ignorePartialResultException) {
        this.ignorePartialResultException = ignorePartialResultException;
    }

    /**
     * Method to return the LdapTemplate
     *
     * @return a fully created LdapTemplate.
     */
    protected final LdapTemplate getLdapTemplate() {
        return this.ldapTemplate;
    }

    protected final AuthenticatedLdapDigestMd5ContextSource getContextSource() {
        return this.contextSource;
    }

    protected final String getFilter() {
        return this.filter;
    }

    public final void afterPropertiesSet() throws Exception {
        Assert.isTrue(this.filter.contains("%u"), "filter must contain %u");
        this.ldapTemplate.setIgnorePartialResultException(this.ignorePartialResultException);
    }

    /**
     * @param filter The filter to set.
     */
    public final void setFilter(final String filter) {
        this.filter = filter;
    }
}

3. Create /cas-server-support-ldap/src/main/java/org/jasig/cas/adaptors/ldap/util/AbstractLdapDigestMd5AuthenticationHandler.java

Code Block
titleAbstractLdapDigestMd5AuthenticationHandler.java

/*
 * Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
 * distributed with this file and available online at
 * http://www.ja-sig.org/products/cas/overview/license/
 */
package org.jasig.cas.adaptors.ldap.util;

import org.springframework.ldap.core.support.LdapContextSource;

import javax.naming.Context;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import java.util.Enumeration;
import java.util.Hashtable;

public class AuthenticatedLdapDigestMd5ContextSource extends LdapContextSource {

	private DirContext context;

	public Hashtable<String, String> environment;

	public DirContext getDirContext(final String principal,
			final String credentials) {
		environment = (Hashtable) getAnonymousEnv().clone();

		String authenMethod = environment.get(Context.SECURITY_AUTHENTICATION);
		if (authenMethod == null) {
			environment.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5");
		}
		String providerUrl = environment.get(Context.PROVIDER_URL);

		if (providerUrl == null) {
			environment.put(Context.PROVIDER_URL, assembleProviderUrlString(getUrls()));
		}

		Enumeration keys = environment.keys();
		while (keys.hasMoreElements()) {
			String key = (String) keys.nextElement();
			System.setProperty(key, environment.get(key));
		}

		environment.put(Context.SECURITY_PRINCIPAL, principal);
		environment.put(Context.SECURITY_CREDENTIALS, credentials);

        try {
			// Create the initial directory context
			context = new InitialDirContext(environment);
		} catch (Exception e) {
			System.err.println("Authentication failed: " + e);
			context = null;
		}
		return context;
	}

}

4. Build a new cas-server-support-ldap-3.3.1.jar and deploy it in CAS

5. Config deployerConfigContext.xml

Fill the new methods into the deployerConfigContext.xml.

Code Block

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC  "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<!--
	| deployerConfigContext.xml centralizes into one file some of the declarative configuration that
	| all CAS deployers will need to modify.
	|
	| This file declares some of the Spring-managed JavaBeans that make up a CAS deployment.
	| The beans declared in this file are instantiated at context initialization time by the Spring
	| ContextLoaderListener declared in web.xml.  It finds this file because this
	| file is among those declared in the context parameter "contextConfigLocation".
	|
	| By far the most common change you will need to make in this file is to change the last bean
	| declaration to replace the default SimpleTestUsernamePasswordAuthenticationHandler with
	| one implementing your approach for authenticating usernames and passwords.
	+-->
<beans>
	<!--
		| This bean declares our AuthenticationManager.  The CentralAuthenticationService service bean
		| declared in applicationContext.xml picks up this AuthenticationManager by reference to its id,
		| "authenticationManager".  Most deployers will be able to use the default AuthenticationManager
		| implementation and so do not need to change the class of this bean.  We include the whole
		| AuthenticationManager here in the userConfigContext.xml so that you can see the things you will
		| need to change in context.
		+-->
	<bean id="authenticationManager"
		class="org.jasig.cas.authentication.AuthenticationManagerImpl">
		<!--
			| This is the List of CredentialToPrincipalResolvers that identify what Principal is trying to authenticate.
			| The AuthenticationManagerImpl considers them in order, finding a CredentialToPrincipalResolver which
			| supports the presented credentials.
			|
			| AuthenticationManagerImpl uses these resolvers for two purposes.  First, it uses them to identify the Principal
			| attempting to authenticate to CAS /login .  In the default configuration, it is the DefaultCredentialsToPrincipalResolver
			| that fills this role.  If you are using some other kind of credentials than UsernamePasswordCredentials, you will need to replace
			| DefaultCredentialsToPrincipalResolver with a CredentialsToPrincipalResolver that supports the credentials you are
			| using.
			|
			| Second, AuthenticationManagerImpl uses these resolvers to identify a service requesting a proxy granting ticket.
			| In the default configuration, it is the HttpBasedServiceCredentialsToPrincipalResolver that serves this purpose.
			| You will need to change this list if you are identifying services by something more or other than their callback URL.
			+-->
		<property name="credentialsToPrincipalResolvers">
			<list>
				<!--
					| UsernamePasswordCredentialsToPrincipalResolver supports the UsernamePasswordCredentials that we use for /login
					| by default and produces SimplePrincipal instances conveying the username from the credentials.
					|
					| If you've changed your LoginFormAction to use credentials other than UsernamePasswordCredentials then you will also
					| need to change this bean declaration (or add additional declarations) to declare a CredentialsToPrincipalResolver that supports the
					| Credentials you are using.
					+-->
				<bean
					class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver" />
				<!--
					| HttpBasedServiceCredentialsToPrincipalResolver supports HttpBasedCredentials.  It supports the CAS 2.0 approach of
					| authenticating services by SSL callback, extracting the callback URL from the Credentials and representing it as a
					| SimpleService identified by that callback URL.
					|
					| If you are representing services by something more or other than an HTTPS URL whereat they are able to
					| receive a proxy callback, you will need to change this bean declaration (or add additional declarations).
					+-->
				<bean
					class="org.jasig.cas.authentication.principal.HttpBasedServiceCredentialsToPrincipalResolver" />
			</list>
		</property>

		<!--
			| Whereas CredentialsToPrincipalResolvers identify who it is some Credentials might authenticate,
			| AuthenticationHandlers actually authenticate credentials.  Here we declare the AuthenticationHandlers that
			| authenticate the Principals that the CredentialsToPrincipalResolvers identified.  CAS will try these handlers in turn
			| until it finds one that both supports the Credentials presented and succeeds in authenticating.
			+-->
		<property name="authenticationHandlers">
			<list>
				<!--
					| This is the authentication handler that authenticates services by means of callback via SSL, thereby validating
					| a server side SSL certificate.
					+-->
				<bean
					class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler" />

				<!--
					| This is the authentication handler declaration that every CAS deployer will need to change before deploying CAS
					| into production.  The default SimpleTestUsernamePasswordAuthenticationHandler authenticates UsernamePasswordCredentials
					| where the username equals the password.  You will need to replace this with an AuthenticationHandler that implements your
					| local authentication strategy.  You might accomplish this by coding a new such handler and declaring
					| edu.someschool.its.cas.MySpecialHandler here, or you might use one of the handlers provided in the adaptors modules.
					+-->
				<bean
					class="org.jasig.cas.adaptors.ldap.BindLdapDigestMd5AuthenticationHandler">
					<property name="filter" value="uid:caseExactmatch:=%u" />
					<property name="searchBase" value="o=langhua,c=cn" />
					<property
						name="contextSource"
						ref="contextSource" />
				</bean>
			</list>
		</property>
	</bean>

	<bean id="contextSource" class="org.jasig.cas.adaptors.ldap.util.AuthenticatedLdapDigestMd5ContextSource">
		<property name="anonymousReadOnly" value="true" />
		<property name="pooled" value="true" />
		<property name="urls">
			<list>
				<value>ldap://localhost:389/</value>
			</list>
		</property>
		<property name="baseEnvironmentProperties">
			<map>
        		</map>
		</property>
	</bean>

	<!--
	This bean defines the security roles for the Services Management application.  Simple deployments can use the in-memory version.
	More robust deployments will want to use another option, such as the Jdbc version.

	The name of this should remain "userDetailsService" in order for Acegi to find it.

	To use this, you should add an entry similar to the following between the two value tags:
	battags=notused,ROLE_ADMIN

	where battags is the username you want to grant access to.  You can put one entry per line.
	 -->
	<bean id="userDetailsService" class="org.springframework.security.userdetails.memory.InMemoryDaoImpl">
		<property name="userMap">
			<value>

		    </value>
		</property>
	</bean>

	<!--
	Bean that defines the attributes that a service may return.  This example uses the Stub/Mock version.  A real implementation
	may go against a database or LDAP server.  The id should remain "attributeRepository" though.
	 -->
	<bean id="attributeRepository"
		class="org.jasig.services.persondir.support.StubPersonAttributeDao">
		<property name="backingMap">
			<map>
				<entry key="uid" value="uid" />
				<entry key="eduPersonAffiliation" value="eduPersonAffiliation" />
				<entry key="groupMembership" value="groupMembership" />
			</map>
		</property>
	</bean>

	<!--
	Sample, in-memory data store for the ServiceRegistry. A real implementation
	would probably want to replace this with the JPA-backed ServiceRegistry DAO
	The name of this bean should remain "serviceRegistryDao".
	 -->
	<bean
		id="serviceRegistryDao"
		class="org.jasig.cas.services.InMemoryServiceRegistryDaoImpl" />
</beans>

6. Restart CAS

Login CAS

Visit http://localhost:8080/cas/login, enter test/111111 to login. This should be successful. Here is a piece of ldap log to show the ldap login procedure:

Code Block

Feb  8 03:48:47 localhost slapd[11389]: daemon: activity on 1 descriptor
Feb  8 03:48:47 localhost slapd[11389]: daemon: activity on:
Feb  8 03:48:47 localhost slapd[11389]: 
Feb  8 03:48:47 localhost slapd[11389]: slap_listener_activate(7): 
Feb  8 03:48:47 localhost slapd[11389]: >>> slap_listener(ldap:///)
Feb  8 03:48:47 localhost slapd[11389]: daemon: listen=7, new connection on 12
Feb  8 03:48:47 localhost slapd[11389]: daemon: added 12r (active) listener=(nil)
Feb  8 03:48:47 localhost slapd[11389]: daemon: epoll: listen=7 active_threads=0 tvp=zero
Feb  8 03:48:47 localhost slapd[11389]: daemon: epoll: listen=8 active_threads=0 tvp=zero
Feb  8 03:48:47 localhost slapd[11389]: daemon: activity on 1 descriptor
Feb  8 03:48:47 localhost slapd[11389]: daemon: activity on:
Feb  8 03:48:47 localhost slapd[11389]: 
Feb  8 03:48:47 localhost slapd[11389]: daemon: epoll: listen=7 active_threads=0 tvp=zero
Feb  8 03:48:47 localhost slapd[11389]: daemon: epoll: listen=8 active_threads=0 tvp=zero
Feb  8 03:48:47 localhost slapd[11389]: daemon: activity on 1 descriptor
Feb  8 03:48:47 localhost slapd[11389]: daemon: activity on:
Feb  8 03:48:47 localhost slapd[11389]:  12r
Feb  8 03:48:47 localhost slapd[11389]: 
Feb  8 03:48:47 localhost slapd[11389]: daemon: read active on 12
Feb  8 03:48:47 localhost slapd[11389]: connection_get(12)
Feb  8 03:48:47 localhost slapd[11389]: connection_get(12): got connid=0
Feb  8 03:48:47 localhost slapd[11389]: connection_read(12): checking for input on id=0
Feb  8 03:48:47 localhost slapd[11389]: conn=0 op=0 do_bind
Feb  8 03:48:47 localhost slapd[11389]: >>> dnPrettyNormal: <>
Feb  8 03:48:47 localhost slapd[11389]: <<< dnPrettyNormal: <>, <>
Feb  8 03:48:47 localhost slapd[11389]: do_bind: dn () SASL mech DIGEST-MD5
Feb  8 03:48:47 localhost slapd[11389]: ==> sasl_bind: dn="" mech=DIGEST-MD5 datalen=0
Feb  8 03:48:47 localhost slapd[11389]: SASL [conn=0] Debug: DIGEST-MD5 server step 1
Feb  8 03:48:47 localhost slapd[11389]: send_ldap_sasl: err=14 len=182
Feb  8 03:48:47 localhost slapd[11389]: send_ldap_response: msgid=1 tag=97 err=14
Feb  8 03:48:47 localhost slapd[11389]: <== slap_sasl_bind: rc=14
Feb  8 03:48:47 localhost slapd[11389]: daemon: epoll: listen=7 active_threads=0 tvp=zero
Feb  8 03:48:47 localhost slapd[11389]: daemon: epoll: listen=8 active_threads=0 tvp=zero
Feb  8 03:48:47 localhost slapd[11389]: daemon: activity on 1 descriptor
Feb  8 03:48:47 localhost slapd[11389]: daemon: activity on:
Feb  8 03:48:47 localhost slapd[11389]: 
Feb  8 03:48:47 localhost slapd[11389]: daemon: epoll: listen=7 active_threads=0 tvp=zero
Feb  8 03:48:47 localhost slapd[11389]: daemon: epoll: listen=8 active_threads=0 tvp=zero
Feb  8 03:48:47 localhost slapd[11389]: daemon: activity on 1 descriptor
Feb  8 03:48:47 localhost slapd[11389]: daemon: activity on:
Feb  8 03:48:47 localhost slapd[11389]:  12r
Feb  8 03:48:47 localhost slapd[11389]: 
Feb  8 03:48:47 localhost slapd[11389]: daemon: read active on 12
Feb  8 03:48:47 localhost slapd[11389]: connection_get(12)
Feb  8 03:48:47 localhost slapd[11389]: connection_get(12): got connid=0
Feb  8 03:48:47 localhost slapd[11389]: connection_read(12): checking for input on id=0
Feb  8 03:48:47 localhost slapd[11389]: conn=0 op=1 do_bind
Feb  8 03:48:47 localhost slapd[11389]: >>> dnPrettyNormal: <>
Feb  8 03:48:47 localhost slapd[11389]: <<< dnPrettyNormal: <>, <>
Feb  8 03:48:47 localhost slapd[11389]: do_bind: dn () SASL mech DIGEST-MD5
Feb  8 03:48:47 localhost slapd[11389]: ==> sasl_bind: dn="" mech=<continuing> datalen=255
Feb  8 03:48:47 localhost slapd[11389]: SASL [conn=0] Debug: DIGEST-MD5 server step 2
Feb  8 03:48:47 localhost slapd[11389]: SASL Canonicalize [conn=0]: authcid="test1"
Feb  8 03:48:47 localhost slapd[11389]: slap_sasl_getdn: conn 0 id=test1 [len=5]
Feb  8 03:48:47 localhost slapd[11389]: slap_sasl_getdn: u:id converted to uid=test1,cn=dell-d830,cn=DIGEST-MD5,cn=auth
Feb  8 03:48:47 localhost slapd[11389]: >>> dnNormalize: <uid=test1,cn=dell-d830,cn=DIGEST-MD5,cn=auth>
Feb  8 03:48:47 localhost slapd[11389]: <<< dnNormalize: <uid=test1,cn=dell-d830,cn=digest-md5,cn=auth>
Feb  8 03:48:47 localhost slapd[11389]: ==>slap_sasl2dn: converting SASL name uid=test1,cn=dell-d830,cn=digest-md5,cn=auth to a DN
Feb  8 03:48:47 localhost slapd[11389]: [rw] authid: "uid=test1,cn=dell-d830,cn=digest-md5,cn=auth" -> "ldap:///o=langhua,c=cn??sub?(uid=test1)"
Feb  8 03:48:47 localhost slapd[11389]: slap_parseURI: parsing ldap:///o=langhua,c=cn??sub?(uid=test1)
Feb  8 03:48:47 localhost slapd[11389]: str2filter "(uid=test1)"
Feb  8 03:48:47 localhost slapd[11389]: begin get_filter
Feb  8 03:48:47 localhost slapd[11389]: EQUALITY
Feb  8 03:48:47 localhost slapd[11389]: end get_filter 0
Feb  8 03:48:47 localhost slapd[11389]: >>> dnNormalize: <o=langhua,c=cn>
Feb  8 03:48:47 localhost slapd[11389]: <<< dnNormalize: <o=langhua,c=cn>
Feb  8 03:48:47 localhost slapd[11389]: slap_sasl2dn: performing internal search (base=o=langhua,c=cn, scope=2)
Feb  8 03:48:47 localhost slapd[11389]: => bdb_search
Feb  8 03:48:47 localhost slapd[11389]: bdb_dn2entry("o=langhua,c=cn")
Feb  8 03:48:47 localhost slapd[11389]: => bdb_dn2id("o=langhua,c=cn")
Feb  8 03:48:47 localhost slapd[11389]: <= bdb_dn2id: got id=0x1
Feb  8 03:48:47 localhost slapd[11389]: entry_decode: "o=langhua,c=cn"
Feb  8 03:48:47 localhost slapd[11389]: <= entry_decode(o=langhua,c=cn)
Feb  8 03:48:47 localhost slapd[11389]: => access_allowed: auth access to "o=langhua,c=cn" "entry" requested
Feb  8 03:48:47 localhost slapd[11389]: => slap_access_allowed: backend default auth access granted to "(anonymous)"
Feb  8 03:48:47 localhost slapd[11389]: => access_allowed: auth access granted by read(=rscxd)
Feb  8 03:48:47 localhost slapd[11389]: search_candidates: base="o=langhua,c=cn" (0x00000001) scope=2
Feb  8 03:48:47 localhost slapd[11389]: => bdb_dn2idl("o=langhua,c=cn")
Feb  8 03:48:47 localhost slapd[11389]: => bdb_filter_candidates
Feb  8 03:48:47 localhost slapd[11389]: #011AND
Feb  8 03:48:47 localhost slapd[11389]: => bdb_list_candidates 0xa0
Feb  8 03:48:47 localhost slapd[11389]: => bdb_filter_candidates
Feb  8 03:48:47 localhost slapd[11389]: #011OR
Feb  8 03:48:47 localhost slapd[11389]: => bdb_list_candidates 0xa1
Feb  8 03:48:47 localhost slapd[11389]: => bdb_filter_candidates
Feb  8 03:48:47 localhost slapd[11389]: #011EQUALITY
Feb  8 03:48:47 localhost slapd[11389]: => bdb_equality_candidates (objectClass)
Feb  8 03:48:47 localhost slapd[11389]: => key_read
Feb  8 03:48:47 localhost slapd[11389]: bdb_idl_fetch_key: [b49d1940]
Feb  8 03:48:47 localhost slapd[11389]: <= bdb_index_read: failed (-30989)
Feb  8 03:48:47 localhost slapd[11389]: <= bdb_equality_candidates: id=0, first=0, last=0
Feb  8 03:48:47 localhost slapd[11389]: <= bdb_filter_candidates: id=0 first=0 last=0
Feb  8 03:48:47 localhost slapd[11389]: => bdb_filter_candidates
Feb  8 03:48:47 localhost slapd[11389]: #011EQUALITY
Feb  8 03:48:47 localhost slapd[11389]: => bdb_equality_candidates (uid)
Feb  8 03:48:47 localhost slapd[11389]: => key_read
Feb  8 03:48:47 localhost slapd[11389]: bdb_idl_fetch_key: [36e55cac]
Feb  8 03:48:47 localhost slapd[11389]: <= bdb_index_read 1 candidates
Feb  8 03:48:47 localhost slapd[11389]: <= bdb_equality_candidates: id=1, first=79, last=79
Feb  8 03:48:47 localhost slapd[11389]: <= bdb_filter_candidates: id=1 first=79 last=79
Feb  8 03:48:47 localhost slapd[11389]: <= bdb_list_candidates: id=1 first=79 last=79
Feb  8 03:48:47 localhost slapd[11389]: <= bdb_filter_candidates: id=1 first=79 last=79
Feb  8 03:48:47 localhost slapd[11389]: <= bdb_list_candidates: id=1 first=79 last=79
Feb  8 03:48:47 localhost slapd[11389]: <= bdb_filter_candidates: id=1 first=79 last=79
Feb  8 03:48:47 localhost slapd[11389]: bdb_search_candidates: id=1 first=79 last=79
Feb  8 03:48:47 localhost slapd[11389]: entry_decode: "uid=test1,ou=beijing,o=langhua,c=cn"
Feb  8 03:48:47 localhost slapd[11389]: <= entry_decode(uid=test1,ou=beijing,o=langhua,c=cn)
Feb  8 03:48:47 localhost slapd[11389]: => bdb_dn2id("ou=beijing,o=langhua,c=cn")
Feb  8 03:48:47 localhost slapd[11389]: <= bdb_dn2id: got id=0x3
Feb  8 03:48:47 localhost slapd[11389]: => bdb_dn2id("uid=test1,ou=beijing,o=langhua,c=cn")
Feb  8 03:48:47 localhost slapd[11389]: <= bdb_dn2id: got id=0x4f
Feb  8 03:48:47 localhost slapd[11389]: => test_filter
Feb  8 03:48:47 localhost slapd[11389]:     EQUALITY
Feb  8 03:48:47 localhost slapd[11389]: => access_allowed: auth access to "uid=test1,ou=beijing,o=langhua,c=cn" "uid" requested
Feb  8 03:48:47 localhost slapd[11389]: => slap_access_allowed: backend default auth access granted to "(anonymous)"
Feb  8 03:48:47 localhost slapd[11389]: => access_allowed: auth access granted by read(=rscxd)
Feb  8 03:48:47 localhost slapd[11389]: <= test_filter 6
Feb  8 03:48:47 localhost slapd[11389]: send_ldap_result: conn=0 op=1 p=3
Feb  8 03:48:47 localhost slapd[11389]: send_ldap_result: err=0 matched="" text=""
Feb  8 03:48:47 localhost slapd[11389]: <==slap_sasl2dn: Converted SASL name to uid=test1,ou=beijing,o=langhua,c=cn
Feb  8 03:48:47 localhost slapd[11389]: slap_sasl_getdn: dn:id converted to uid=test1,ou=beijing,o=langhua,c=cn
Feb  8 03:48:47 localhost slapd[11389]: SASL Canonicalize [conn=0]: slapAuthcDN="uid=test1,ou=beijing,o=langhua,c=cn"
Feb  8 03:48:47 localhost slapd[11389]: => bdb_search
Feb  8 03:48:47 localhost slapd[11389]: bdb_dn2entry("uid=test1,ou=beijing,o=langhua,c=cn")
Feb  8 03:48:47 localhost slapd[11389]: => access_allowed: auth access to "uid=test1,ou=beijing,o=langhua,c=cn" "entry" requested
Feb  8 03:48:47 localhost slapd[11389]: => slap_access_allowed: backend default auth access granted to "(anonymous)"
Feb  8 03:48:47 localhost slapd[11389]: => access_allowed: auth access granted by read(=rscxd)
Feb  8 03:48:47 localhost slapd[11389]: base_candidates: base: "uid=test1,ou=beijing,o=langhua,c=cn" (0x0000004f)
Feb  8 03:48:47 localhost slapd[11389]: => test_filter
Feb  8 03:48:47 localhost slapd[11389]:     PRESENT
Feb  8 03:48:47 localhost slapd[11389]: => access_allowed: auth access to "uid=test1,ou=beijing,o=langhua,c=cn" "objectClass" requested
Feb  8 03:48:47 localhost slapd[11389]: => slap_access_allowed: backend default auth access granted to "(anonymous)"
Feb  8 03:48:47 localhost slapd[11389]: => access_allowed: auth access granted by read(=rscxd)
Feb  8 03:48:47 localhost slapd[11389]: <= test_filter 6
Feb  8 03:48:47 localhost slapd[11389]: slap_ap_lookup: str2ad(cmusaslsecretDIGEST-MD5): attribute type undefined
Feb  8 03:48:47 localhost slapd[11389]: send_ldap_result: conn=0 op=1 p=3
Feb  8 03:48:47 localhost slapd[11389]: send_ldap_result: err=0 matched="" text=""
Feb  8 03:48:47 localhost slapd[11389]: SASL Canonicalize [conn=0]: authzid="test1"
Feb  8 03:48:47 localhost slapd[11389]: SASL proxy authorize [conn=0]: authcid="test1@dell-d830" authzid="test1@dell-d830"
Feb  8 03:48:47 localhost slapd[11389]: SASL Authorize [conn=0]:  proxy authorization allowed authzDN=""
Feb  8 03:48:47 localhost slapd[11389]: daemon: epoll: listen=7 active_threads=0 tvp=zero
Feb  8 03:48:47 localhost slapd[11389]: daemon: epoll: listen=8 active_threads=0 tvp=zero
Feb  8 03:48:47 localhost slapd[11389]: daemon: activity on 1 descriptor
Feb  8 03:48:47 localhost slapd[11389]: daemon: activity on:
Feb  8 03:48:47 localhost slapd[11389]: 
Feb  8 03:48:47 localhost slapd[11389]: daemon: epoll: listen=7 active_threads=0 tvp=zero
Feb  8 03:48:47 localhost slapd[11389]: daemon: epoll: listen=8 active_threads=0 tvp=zero
Feb  8 03:48:47 localhost slapd[11389]: send_ldap_sasl: err=0 len=40
Feb  8 03:48:47 localhost slapd[11389]: do_bind: SASL/DIGEST-MD5 bind: dn="uid=test1,ou=beijing,o=langhua,c=cn" sasl_ssf=0
Feb  8 03:48:47 localhost slapd[11389]: send_ldap_response: msgid=2 tag=97 err=0
Feb  8 03:48:47 localhost slapd[11389]: <== slap_sasl_bind: rc=0

That's it. Good luck!

Shi Yusen/Beijing Langhua Ltd. http://www.langhua.cn/