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:
password-hash
sasl-realm dell-d830
authz-regexp
uid=([^,]*),cn=dell-d830,cn=digest-md5,cn=auth
ldap:///o=langhua,c=cn??sub?(uid=$1)
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
saslpasswd2 -c test
Password: 111111
Again (for verification): 111111
2. Test SASL DIGEST-MD5
Open a console and run:
sasl2-sample-server
Console output:
trying 2, 1, 6
trying 10, 1, 6
bind: Address already in use
Open another console and run:
sasl2-sample-client -m DIGEST-MD5 localhost
Console output:
receiving capability list... recv:
PLAIN CRAM-MD5 ANONYMOUS LOGIN NTLM GSSAPI DIGEST-MD5
PLAIN CRAM-MD5 ANONYMOUS LOGIN NTLM GSSAPI DIGEST-MD5
send:
DIGEST-MD5
send:
N
recv:
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:
username="test",realm="dell-d830",nonce="i7iU89Jmqj2S8BmExkXbkTwV8TaMdOrh1T803Q2UHw4=",cnonce="h3prPJs4mCG0XAUJNiEhlISg0BjgS2UcRenpY6S3IuI=",nc=00000001,qop=auth,digest-uri="rcmd/localhost",response=e8f55dabc929152361c6cdcbb0d22532
recv:
rspauth=44285575e382f452e158665a2727a493
send:
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
/* * 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; } }