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.Properties;
24 import java.util.Iterator;
25
26 import javax.naming.Context;
27 import javax.naming.NamingException;
28 import javax.naming.ldap.InitialLdapContext;
29 import javax.naming.ldap.Control;
30
31 import org.apache.ldap.common.exception.LdapConfigurationException;
32 import org.apache.ldap.common.name.LdapName;
33 import org.apache.ldap.common.util.PropertiesUtils;
34 import org.apache.ldap.server.protocol.LdapProtocolProvider;
35 import org.apache.mina.common.TransportType;
36 import org.apache.mina.registry.Service;
37 import org.apache.mina.registry.ServiceRegistry;
38 import org.apache.mina.registry.SimpleServiceRegistry;
39 import org.apache.kerberos.service.KdcConfiguration;
40 import org.apache.kerberos.protocol.KerberosProtocolProvider;
41 import org.apache.kerberos.store.PrincipalStore;
42 import org.apache.kerberos.store.JndiPrincipalStoreImpl;
43
44
45 /***
46 * Adds additional bootstrapping for server socket listeners when firing
47 * up the server.
48 *
49 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
50 * @version $Rev: 168482 $
51 * @see javax.naming.spi.InitialContextFactory
52 */
53 public class ServerContextFactory extends CoreContextFactory
54 {
55 /*** the default LDAP port to use */
56 private static final int LDAP_PORT = 389;
57
58 private static final ServiceRegistry DEFAULT_MINA_REGISTRY;
59
60 private static Service ldapService;
61
62 private static Service kerberosService;
63
64 private static ServiceRegistry minaRegistry;
65
66
67 static
68 {
69 ServiceRegistry tmp = null;
70
71 try
72 {
73 tmp = new SimpleServiceRegistry();
74 }
75 catch( IOException e )
76 {
77 e.printStackTrace();
78 }
79
80 DEFAULT_MINA_REGISTRY = tmp;
81 }
82
83
84
85
86
87
88 /***
89 * Checks first for a shutdown operation and if so stops the server. Otherwise
90 * it initializes the networking subsystem starting up the mina registery and
91 * other protocol provider services if enabled including the LDAP provider.
92 *
93 * @param env the JNDI environment parameters
94 * @return the new LDAP context to be wrapped by InitialContext
95 * @throws NamingException if there are problems starting or stopping the server
96 */
97 public Context getInitialContext( Hashtable env ) throws NamingException
98 {
99 Context ctx = null;
100
101 if ( env.containsKey( EnvKeys.SHUTDOWN ) )
102 {
103 if ( this.provider == null )
104 {
105 return new DeadContext();
106 }
107
108 try
109 {
110 this.provider.shutdown();
111
112 if ( minaRegistry != null )
113 {
114 if ( ldapService != null )
115 {
116 minaRegistry.unbind( ldapService );
117
118 ldapService = null;
119 }
120
121 if ( kerberosService != null )
122 {
123 minaRegistry.unbind( kerberosService );
124
125 kerberosService = null;
126 }
127 }
128 }
129 catch( NamingException ne )
130 {
131 throw ne;
132 }
133 catch( Throwable t )
134 {
135 NamingException ne = new NamingException( "Failed to shutdown." );
136
137 ne.setRootCause( t );
138
139 throw ne;
140 }
141 finally
142 {
143 ctx = new DeadContext();
144
145 provider = null;
146
147 initialEnv = null;
148 }
149
150 return ctx;
151 }
152
153 ctx = super.getInitialContext( env );
154
155
156
157 if ( initialEnv != null && ! initialEnv.containsKey( EnvKeys.DISABLE_PROTOCOL ) )
158 {
159 setupRegistry();
160
161 startLdapProtocol();
162
163 if ( initialEnv.containsKey( EnvKeys.ENABLE_KERBEROS ) )
164 {
165 startKerberosProtocol();
166 }
167 }
168
169 return ctx;
170 }
171
172
173 /***
174 * Starts up the MINA registry so various protocol providers can be started.
175 *
176 * @throws NamingException if there is a problem initializing the registry
177 */
178 private void setupRegistry() throws NamingException
179 {
180 ServiceRegistry registry = null;
181
182 if ( initialEnv.containsKey( EnvKeys.PASSTHRU ) )
183 {
184 registry = ( ServiceRegistry ) initialEnv.get( EnvKeys.PASSTHRU );
185
186 if ( registry != null )
187 {
188 initialEnv.put( EnvKeys.PASSTHRU, "Handoff Succeeded!" );
189 }
190 }
191
192 if( DEFAULT_MINA_REGISTRY == null )
193 {
194 throw new NamingException( "Default MINA service registry is not available." );
195 }
196
197 if( registry == null )
198 {
199 registry = DEFAULT_MINA_REGISTRY;
200 }
201
202 minaRegistry = registry;
203 }
204
205
206 /***
207 * Starts the Kerberos protocol provider which is backed by the LDAP store.
208 *
209 * @throws NamingException if there are problems starting up the Kerberos provider
210 */
211 private void startKerberosProtocol() throws NamingException
212 {
213
214
215
216
217
218 Properties props = new Properties();
219
220 Iterator list = initialEnv.keySet().iterator();
221
222 while ( list.hasNext() )
223 {
224 String key = ( String ) list.next();
225
226 if ( initialEnv.get( key ) instanceof String )
227 {
228 props.setProperty( key, ( String ) initialEnv.get( key ) );
229 }
230 }
231
232 KdcConfiguration config = new KdcConfiguration( props );
233
234 int port = PropertiesUtils.get( initialEnv, KdcConfiguration.KERBEROS_PORT_KEY, KdcConfiguration.DEFAULT_KERBEROS_PORT );
235
236 Service service= new Service( "kerberos", TransportType.DATAGRAM, new InetSocketAddress( port ) );
237
238 InitialLdapContext ctx = new InitialLdapContext( initialEnv, new Control[]{} );
239
240 Object baseStr = initialEnv.get( JndiPrincipalStoreImpl.KDC_STORE_SEARCHBASE );
241
242 if ( baseStr == null )
243 {
244 throw new LdapConfigurationException( "Trying to start kerberos service without setting " + JndiPrincipalStoreImpl.KDC_STORE_SEARCHBASE );
245 }
246
247 LdapName base = new LdapName( ( String ) baseStr );
248
249 PrincipalStore store = new JndiPrincipalStoreImpl( ctx, base );
250
251 try
252 {
253 minaRegistry.bind( service, new KerberosProtocolProvider( config, store ) );
254
255 kerberosService = service;
256 }
257 catch ( IOException e )
258 {
259 e.printStackTrace();
260 }
261 }
262
263
264 /***
265 * Starts up the LDAP protocol provider to service LDAP requests
266 *
267 * @throws NamingException if there are problems starting the LDAP provider
268 */
269 private void startLdapProtocol() throws NamingException
270 {
271 int port = PropertiesUtils.get( initialEnv, EnvKeys.LDAP_PORT, LDAP_PORT );
272
273 Service service = new Service( "ldap", TransportType.SOCKET, new InetSocketAddress( port ) );
274
275 try
276 {
277 minaRegistry.bind( service, new LdapProtocolProvider( ( Hashtable ) initialEnv.clone() ) );
278
279 ldapService = service;
280 }
281 catch ( IOException e )
282 {
283 String msg = "Failed to bind the LDAP protocol service to the service registry: " + service;
284
285 LdapConfigurationException lce = new LdapConfigurationException( msg );
286
287 lce.setRootCause( e );
288
289 throw lce;
290 }
291 }
292 }