001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 *
019 */
020 package org.apache.directory.server.ldap.handlers.bind.digestMD5;
021
022
023 import org.apache.directory.server.core.CoreSession;
024 import org.apache.directory.server.ldap.LdapServer;
025 import org.apache.directory.server.ldap.LdapSession;
026 import org.apache.directory.server.ldap.handlers.bind.AbstractMechanismHandler;
027 import org.apache.directory.server.ldap.handlers.bind.SaslConstants;
028 import org.apache.directory.shared.ldap.constants.SupportedSaslMechanisms;
029 import org.apache.directory.shared.ldap.message.InternalBindRequest;
030
031 import javax.security.auth.callback.CallbackHandler;
032 import javax.security.sasl.Sasl;
033 import javax.security.sasl.SaslServer;
034
035 import java.util.HashMap;
036 import java.util.Map;
037
038
039 /**
040 * The DIGEST-MD5 mechanism handler.
041 *
042 * @org.apache.xbean.XBean
043 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
044 * @version $Rev$, $Date$
045 */
046 public class DigestMd5MechanismHandler extends AbstractMechanismHandler
047 {
048 /**
049 * Create a list of all the configured realms.
050 *
051 * @param ldapServer the LdapServer for which we want to get the realms
052 * @return a list of realms, separated by spaces
053 */
054 private String getActiveRealms( LdapServer ldapServer )
055 {
056 StringBuilder realms = new StringBuilder();
057 boolean isFirst = true;
058
059 for ( String realm:ldapServer.getSaslRealms() )
060 {
061 if ( isFirst )
062 {
063 isFirst = false;
064 }
065 else
066 {
067 realms.append( ' ' );
068 }
069
070 realms.append( realm );
071 }
072
073 return realms.toString();
074 }
075
076
077
078 public SaslServer handleMechanism( LdapSession ldapSession, InternalBindRequest bindRequest ) throws Exception
079 {
080 SaslServer ss = (SaslServer)ldapSession.getSaslProperty( SaslConstants.SASL_SERVER );
081
082 if ( ss == null )
083 {
084 CoreSession adminSession = ldapSession.getLdapServer().getDirectoryService().getAdminSession();
085
086 CallbackHandler callbackHandler = new DigestMd5CallbackHandler( ldapSession, adminSession, bindRequest );
087
088 ss = Sasl.createSaslServer(
089 SupportedSaslMechanisms.DIGEST_MD5,
090 SaslConstants.LDAP_PROTOCOL,
091 (String)ldapSession.getSaslProperty( SaslConstants.SASL_HOST ),
092 (Map<String, String>)ldapSession.getSaslProperty( SaslConstants.SASL_PROPS ),
093 callbackHandler );
094 ldapSession.putSaslProperty( SaslConstants.SASL_SERVER, ss );
095 }
096
097 return ss;
098 }
099
100
101 /**
102 * {@inheritDoc}
103 */
104 public void init( LdapSession ldapSession )
105 {
106 // Store the host in the ldap session
107 String saslHost = ldapSession.getLdapServer().getSaslHost();
108 String userBaseDn = ldapSession.getLdapServer().getSearchBaseDn();
109
110
111 ldapSession.putSaslProperty( SaslConstants.SASL_HOST, saslHost );
112 ldapSession.putSaslProperty( SaslConstants.SASL_USER_BASE_DN, userBaseDn );
113
114 Map<String, String> saslProps = new HashMap<String, String>();
115 saslProps.put( Sasl.QOP, ldapSession.getLdapServer().getSaslQopString() );
116 saslProps.put( "com.sun.security.sasl.digest.realm", getActiveRealms( ldapSession.getLdapServer() ) );
117 ldapSession.putSaslProperty( SaslConstants.SASL_PROPS, saslProps );
118 }
119
120
121 /**
122 * Remove the Host, UserBaseDn, props and Mechanism property.
123 *
124 * @param ldapSession the LdapSession instance
125 */
126 public void cleanup( LdapSession ldapSession )
127 {
128 // Inject the Sasl Filter
129 insertSaslFilter( ldapSession );
130
131 // and cleanup the useless informations
132 ldapSession.removeSaslProperty( SaslConstants.SASL_HOST );
133 ldapSession.removeSaslProperty( SaslConstants.SASL_USER_BASE_DN );
134 ldapSession.removeSaslProperty( SaslConstants.SASL_MECH );
135 ldapSession.removeSaslProperty( SaslConstants.SASL_PROPS );
136 ldapSession.removeSaslProperty( SaslConstants.SASL_AUTHENT_USER );
137 }
138 }