View Javadoc

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          * Looks like KdcConfiguration takes properties and we use Hashtable for JNDI
116          * so I'm copying over the String based properties into a new Properties obj.
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         // construct the configuration, get the port, create the service, and prepare kdc objects
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 //        Service service = new Service( "ldap", TransportType.SOCKET, new InetSocketAddress( port ) );
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 }