1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.ldap.server.jndi;
18
19
20 import java.io.IOException;
21 import java.net.InetSocketAddress;
22 import java.util.Hashtable;
23 import java.util.Iterator;
24 import java.util.Properties;
25
26 import javax.naming.NamingException;
27 import javax.naming.Context;
28 import javax.naming.directory.DirContext;
29 import javax.naming.ldap.Control;
30 import javax.naming.ldap.InitialLdapContext;
31 import javax.naming.ldap.LdapContext;
32
33 import org.apache.kerberos.protocol.KerberosProtocolProvider;
34 import org.apache.kerberos.service.KdcConfiguration;
35 import org.apache.kerberos.store.JndiPrincipalStoreImpl;
36 import org.apache.kerberos.store.PrincipalStore;
37 import org.apache.kerberos.sam.SamSubsystem;
38 import org.apache.ldap.common.exception.LdapConfigurationException;
39 import org.apache.ldap.common.name.LdapName;
40 import org.apache.ldap.common.util.PropertiesUtils;
41 import org.apache.ldap.common.util.NamespaceTools;
42 import org.apache.ldap.server.configuration.ServerStartupConfiguration;
43 import org.apache.ldap.server.protocol.LdapProtocolProvider;
44 import org.apache.mina.common.TransportType;
45 import org.apache.mina.registry.Service;
46 import org.apache.mina.registry.ServiceRegistry;
47 import org.apache.commons.logging.Log;
48 import org.apache.commons.logging.LogFactory;
49
50
51 /***
52 * Adds additional bootstrapping for server socket listeners when firing
53 * up the server.
54 *
55 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
56 * @version $Rev: 226451 $
57 * @see javax.naming.spi.InitialContextFactory
58 */
59 public class ServerContextFactory extends CoreContextFactory
60 {
61 private static Log log = LogFactory.getLog( ServerContextFactory.class.getName() );
62 private static Service ldapService;
63 private static Service kerberosService;
64 private static ServiceRegistry minaRegistry;
65
66
67 protected ServiceRegistry getMinaRegistry()
68 {
69 return minaRegistry;
70 }
71
72 public void afterShutdown( ContextFactoryService service )
73 {
74 if ( minaRegistry != null )
75 {
76 if ( ldapService != null )
77 {
78 minaRegistry.unbind( ldapService );
79 if ( log.isInfoEnabled() )
80 {
81 log.info( "Unbind of LDAP Service complete: " + ldapService );
82 }
83 ldapService = null;
84 }
85
86 if ( kerberosService != null )
87 {
88 minaRegistry.unbind( kerberosService );
89 if ( log.isInfoEnabled() )
90 {
91 log.info( "Unbind of KRB5 Service complete: " + kerberosService );
92 }
93 kerberosService = null;
94 }
95 }
96 }
97
98 public void afterStartup( ContextFactoryService service ) throws NamingException
99 {
100 ServerStartupConfiguration cfg =
101 ( ServerStartupConfiguration ) service.getConfiguration().getStartupConfiguration();
102 Hashtable env = service.getConfiguration().getEnvironment();
103
104 if ( cfg.isEnableNetworking() )
105 {
106 setupRegistry( cfg );
107 startLdapProtocol( cfg, env );
108
109 if ( cfg.isEnableKerberos() )
110 {
111 startKerberosProtocol( env );
112 }
113 }
114 }
115
116 /***
117 * Starts up the MINA registry so various protocol providers can be started.
118 */
119 private void setupRegistry( ServerStartupConfiguration cfg )
120 {
121 minaRegistry = cfg.getMinaServiceRegistry();
122 }
123
124
125 /***
126 * Starts the Kerberos protocol provider which is backed by the LDAP store.
127 *
128 * @throws NamingException if there are problems starting up the Kerberos provider
129 */
130 private void startKerberosProtocol( Hashtable env ) throws NamingException
131 {
132
133
134
135
136 Properties props = new Properties();
137 Iterator list = env.keySet().iterator();
138 while ( list.hasNext() )
139 {
140 String key = ( String ) list.next();
141
142 if ( env.get( key ) instanceof String )
143 {
144 props.setProperty( key, ( String ) env.get( key ) );
145 }
146 }
147
148
149 KdcConfiguration config = new KdcConfiguration( props );
150 int port = PropertiesUtils.get( env, KdcConfiguration.KERBEROS_PORT_KEY, KdcConfiguration.DEFAULT_KERBEROS_PORT );
151 Service service= new Service( "kerberos", TransportType.DATAGRAM, new InetSocketAddress( port ) );
152 LdapContext ctx = getBaseRealmContext( config, env );
153 PrincipalStore store = new JndiPrincipalStoreImpl( ctx, new LdapName( "ou=Users" ) );
154 SamSubsystem.getInstance().setUserContext( ( DirContext ) ctx, "ou=Users" );
155
156 try
157 {
158 minaRegistry.bind( service, new KerberosProtocolProvider( config, store ) );
159 kerberosService = service;
160 if ( log.isInfoEnabled() )
161 {
162 log.info( "Successful bind of KRB5 Service completed: " + kerberosService );
163 }
164 }
165 catch ( IOException e )
166 {
167 log.error( "Could not start the kerberos service on port " +
168 KdcConfiguration.DEFAULT_KERBEROS_PORT, e );
169 }
170 }
171
172
173 /***
174 * Maps a Kerberos Realm name to a position within the DIT. The primary realm of
175 * the KDC will use this area for configuration and for storing user entries.
176 *
177 * @param config the KDC's configuration
178 * @param env the JNDI environment properties
179 * @return the base context for the primary realm of the KDC
180 * @throws NamingException
181 */
182 private LdapContext getBaseRealmContext( KdcConfiguration config, Hashtable env ) throws NamingException
183 {
184 Hashtable cloned = ( Hashtable ) env.clone();
185 String dn = NamespaceTools.inferLdapName( config.getPrimaryRealm() );
186 cloned.put( Context.PROVIDER_URL, dn );
187
188 if ( log.isInfoEnabled() )
189 {
190 log.info( "Getting initial context for realm base at " + dn + " for " + config.getPrimaryRealm() );
191 }
192
193 return new InitialLdapContext( cloned, new Control[]{} );
194 }
195
196
197 /***
198 * Starts up the LDAP protocol provider to service LDAP requests
199 *
200 * @throws NamingException if there are problems starting the LDAP provider
201 */
202 private void startLdapProtocol( ServerStartupConfiguration cfg, Hashtable env ) throws NamingException
203 {
204 int port = cfg.getLdapPort();
205 Service service = new Service( "ldap", TransportType.SOCKET, new InetSocketAddress( port ) );
206
207 try
208 {
209 minaRegistry.bind( service, new LdapProtocolProvider( ( Hashtable ) env.clone() ) );
210 ldapService = service;
211 if ( log.isInfoEnabled() )
212 {
213 log.info( "Successful bind of LDAP Service completed: " + ldapService );
214 }
215 }
216 catch ( IOException e )
217 {
218 String msg = "Failed to bind the LDAP protocol service to the service registry: " + service;
219 LdapConfigurationException lce = new LdapConfigurationException( msg );
220 lce.setRootCause( e );
221 log.error( msg, e );
222 throw lce;
223 }
224 }
225 }