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