1 /**
2 *
3 * Copyright 2003-2004 The Apache Software Foundation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.geronimo.directory;
18
19 import java.io.IOException;
20 import java.net.InetAddress;
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.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35 import org.apache.kerberos.protocol.KerberosProtocolProvider;
36 import org.apache.kerberos.service.KdcConfiguration;
37 import org.apache.kerberos.store.JndiPrincipalStoreImpl;
38 import org.apache.kerberos.store.PrincipalStore;
39 import org.apache.kerberos.sam.SamSubsystem;
40 import org.apache.ldap.common.exception.LdapConfigurationException;
41 import org.apache.ldap.common.name.LdapName;
42 import org.apache.ldap.common.util.PropertiesUtils;
43 import org.apache.ldap.common.util.NamespaceTools;
44 import org.apache.ldap.server.jndi.ContextFactoryService;
45 import org.apache.ldap.server.jndi.CoreContextFactory;
46 import org.apache.ldap.server.protocol.LdapProtocolProvider;
47 import org.apache.mina.common.TransportType;
48 import org.apache.mina.registry.Service;
49 import org.apache.mina.registry.ServiceRegistry;
50
51
52 /**
53 * Adds additional bootstrapping for server socket listeners when firing
54 * up the server.
55 *
56 * @version $Rev: 355877 $ $Date: 2005-12-10 18:48:27 -0800 (Sat, 10 Dec 2005) $
57 * @see javax.naming.spi.InitialContextFactory
58 */
59 public class ServerContextFactory extends CoreContextFactory {
60 private static final Log log = LogFactory.getLog(ServerContextFactory.class);
61 private static Service ldapService;
62 private static Service kerberosService;
63 private static ServiceRegistry minaRegistry;
64
65 protected ServiceRegistry getMinaRegistry() {
66 return minaRegistry;
67 }
68
69 public void afterShutdown(ContextFactoryService service) {
70 if (minaRegistry != null) {
71 if (ldapService != null) {
72 minaRegistry.unbind(ldapService);
73 log.debug("Unbind of LDAP Service complete: " + ldapService);
74 ldapService = null;
75 }
76
77 if (kerberosService != null) {
78 minaRegistry.unbind(kerberosService);
79 log.debug("Unbind of KRB5 Service complete: " + kerberosService);
80 kerberosService = null;
81 }
82 }
83 }
84
85 public void afterStartup(ContextFactoryService service) throws NamingException {
86 ServerStartupConfiguration cfg =
87 (ServerStartupConfiguration) service.getConfiguration().getStartupConfiguration();
88 Hashtable env = service.getConfiguration().getEnvironment();
89
90 if (cfg.isEnableNetworking()) {
91 setupRegistry(cfg);
92 startLdapProtocol(cfg, env);
93
94 if (cfg.isEnableKerberos()) {
95 startKerberosProtocol(env);
96 }
97 }
98 }
99
100 /**
101 * Starts up the MINA registry so various protocol providers can be started.
102 */
103 private void setupRegistry(ServerStartupConfiguration cfg) {
104 minaRegistry = cfg.getMinaServiceRegistry();
105 }
106
107
108 /**
109 * Starts the Kerberos protocol provider which is backed by the LDAP store.
110 *
111 * @throws NamingException if there are problems starting up the Kerberos provider
112 */
113 private void startKerberosProtocol(Hashtable env) throws NamingException {
114
115
116
117
118 Properties props = new Properties();
119 Iterator list = env.keySet().iterator();
120 while (list.hasNext()) {
121 String key = (String) list.next();
122
123 if (env.get(key) instanceof String) {
124 props.setProperty(key, (String) env.get(key));
125 }
126 }
127
128
129 KdcConfiguration config = new KdcConfiguration(props);
130 int port = PropertiesUtils.get(env, KdcConfiguration.KERBEROS_PORT_KEY, KdcConfiguration.DEFAULT_KERBEROS_PORT);
131 Service service = new Service("kerberos", TransportType.DATAGRAM, new InetSocketAddress(port));
132 LdapContext ctx = getBaseRealmContext(config, env);
133 PrincipalStore store = new JndiPrincipalStoreImpl(ctx, new LdapName("ou=Users"));
134 SamSubsystem.getInstance().setUserContext((DirContext) ctx, "ou=Users");
135
136 try {
137 minaRegistry.bind(service, new KerberosProtocolProvider(config, store));
138 kerberosService = service;
139 log.debug("Successful bind of KRB5 Service completed: " + kerberosService);
140 }
141 catch (IOException e) {
142 log.error("Could not start the kerberos service on port " +
143 KdcConfiguration.DEFAULT_KERBEROS_PORT, e);
144 }
145 }
146
147
148 /**
149 * Maps a Kerberos Realm name to a position within the DIT. The primary realm of
150 * the KDC will use this area for configuration and for storing user entries.
151 *
152 * @param config the KDC's configuration
153 * @param env the JNDI environment properties
154 * @return the base context for the primary realm of the KDC
155 * @throws NamingException
156 */
157 private LdapContext getBaseRealmContext(KdcConfiguration config, Hashtable env) throws NamingException {
158 Hashtable cloned = (Hashtable) env.clone();
159 String dn = NamespaceTools.inferLdapName(config.getPrimaryRealm());
160 cloned.put(Context.PROVIDER_URL, dn);
161
162 log.debug("Getting initial context for realm base at " + dn + " for " + config.getPrimaryRealm());
163
164 return new InitialLdapContext(cloned, new Control[]{});
165 }
166
167
168 /**
169 * Starts up the LDAP protocol provider to service LDAP requests
170 *
171 * @throws NamingException if there are problems starting the LDAP provider
172 */
173 private void startLdapProtocol(ServerStartupConfiguration cfg, Hashtable env) throws NamingException {
174 int port = cfg.getLdapPort();
175 InetAddress host = cfg.getHost();
176 Service service = new Service("ldap", TransportType.SOCKET, new InetSocketAddress(host, port));
177
178
179 try {
180 minaRegistry.bind(service, new LdapProtocolProvider((Hashtable) env.clone()));
181 ldapService = service;
182 log.debug("Successful bind of LDAP Service completed: " + ldapService);
183 }
184 catch (IOException e) {
185 String msg = "Failed to bind the LDAP protocol service to the service registry: " + service;
186 LdapConfigurationException lce = new LdapConfigurationException(msg);
187 lce.setRootCause(e);
188 log.error(msg, e);
189 throw lce;
190 }
191 }
192 }