View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    * 
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   * 
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   * 
19   */
20  package org.apache.directory.server.kerberos.kdc;
21  
22  
23  import java.io.IOException;
24  
25  import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
26  import org.apache.directory.api.ldap.model.name.Dn;
27  import org.apache.directory.server.kerberos.KerberosConfig;
28  import org.apache.directory.server.kerberos.changepwd.ChangePasswordServer;
29  import org.apache.directory.server.kerberos.protocol.KerberosProtocolHandler;
30  import org.apache.directory.server.kerberos.protocol.codec.KerberosProtocolCodecFactory;
31  import org.apache.directory.server.kerberos.shared.replay.ReplayCache;
32  import org.apache.directory.server.kerberos.shared.replay.ReplayCacheImpl;
33  import org.apache.directory.server.kerberos.shared.store.PrincipalStore;
34  import org.apache.directory.server.protocol.shared.DirectoryBackedService;
35  import org.apache.directory.server.protocol.shared.transport.TcpTransport;
36  import org.apache.directory.server.protocol.shared.transport.Transport;
37  import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
38  import org.apache.mina.core.filterchain.IoFilterChainBuilder;
39  import org.apache.mina.core.service.IoAcceptor;
40  import org.apache.mina.filter.codec.ProtocolCodecFilter;
41  import org.apache.mina.transport.socket.AbstractDatagramSessionConfig;
42  import org.apache.mina.transport.socket.AbstractSocketSessionConfig;
43  //import org.apache.mina.transport.socket.AbstractSocketSessionConfig;
44  import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
45  import org.slf4j.Logger;
46  import org.slf4j.LoggerFactory;
47  
48  
49  /**
50   * Contains the configuration parameters for the Kerberos protocol provider.
51   *
52   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
53   */
54  public class KdcServer extends DirectoryBackedService
55  {
56      private static final long serialVersionUID = 522567370475574165L;
57  
58      /** logger for this class */
59      private static final Logger LOG = LoggerFactory.getLogger( KdcServer.class );
60  
61      /** The default kdc service name */
62      private static final String SERVICE_NAME = "Keydap Kerberos Service";
63  
64      /** the cache used for storing AS and TGS requests */
65      private ReplayCache replayCache;
66  
67      private KerberosConfig config;
68  
69      private ChangePasswordServer changePwdServer;
70  
71  
72      /**
73       * Creates a new instance of KdcServer with the default configuration.
74       */
75      public KdcServer()
76      {
77          this( new KerberosConfig() );
78      }
79  
80  
81      /**
82       * 
83       * Creates a new instance of KdcServer with the given config.
84       *
85       * @param config the kerberos server configuration
86       */
87      public KdcServer( KerberosConfig config )
88      {
89          this.config = config;
90          super.setServiceName( SERVICE_NAME );
91          super.setSearchBaseDn( config.getSearchBaseDn() );
92      }
93  
94  
95      /**
96       * @return the replayCache
97       */
98      public ReplayCache getReplayCache()
99      {
100         return replayCache;
101     }
102 
103 
104     /**
105      * @throws IOException if we cannot bind to the sockets
106      */
107     public void start() throws IOException, LdapInvalidDnException
108     {
109         PrincipalStore store;
110 
111         store = new DirectoryPrincipalStore( getDirectoryService(), new Dn( this.getSearchBaseDn() ) );
112 
113         LOG.debug( "initializing the kerberos replay cache" );
114 
115         replayCache = new ReplayCacheImpl( config.getAllowableClockSkew() );
116 
117         // Kerberos can use UDP or TCP
118         for ( Transport transport : transports )
119         {
120             IoAcceptor acceptor = transport.getAcceptor();
121 
122             // Now, configure the acceptor
123             // Inject the chain
124             IoFilterChainBuilder chainBuilder = new DefaultIoFilterChainBuilder();
125 
126             if ( transport instanceof TcpTransport )
127             {
128                 // Now, configure the acceptor
129                 // Disable the disconnection of the clients on unbind
130                 acceptor.setCloseOnDeactivation( false );
131 
132                 // No Nagle's algorithm
133                 ( ( NioSocketAcceptor ) acceptor ).getSessionConfig().setTcpNoDelay( true );
134 
135                 // Allow the port to be reused even if the socket is in TIME_WAIT state
136                 ( ( NioSocketAcceptor ) acceptor ).setReuseAddress( true );
137 
138                 // Set the buffer size to 32Kb, instead of 1Kb by default
139                 ( ( AbstractSocketSessionConfig ) acceptor.getSessionConfig() ).setReadBufferSize( 32 * 1024 );
140                 ( ( AbstractSocketSessionConfig ) acceptor.getSessionConfig() ).setSendBufferSize( 32 * 1024 );
141             }
142             else
143             {
144                 // Set the buffer size to 32Kb, instead of 1Kb by default
145                 ( ( AbstractDatagramSessionConfig ) acceptor.getSessionConfig() ).setReadBufferSize( 32 * 1024 );
146                 ( ( AbstractDatagramSessionConfig ) acceptor.getSessionConfig() ).setSendBufferSize( 32 * 1024 );
147             }
148 
149             // Inject the codec
150             ( ( DefaultIoFilterChainBuilder ) chainBuilder ).addFirst( "codec",
151                 new ProtocolCodecFilter(
152                     KerberosProtocolCodecFactory.getInstance() ) );
153 
154             acceptor.setFilterChainBuilder( chainBuilder );
155 
156             // Inject the protocol handler
157             acceptor.setHandler( new KerberosProtocolHandler( this, store ) );
158             
159 
160             // Bind to the configured address
161             acceptor.bind();
162         }
163 
164         LOG.info( "Kerberos service started." );
165 
166         if ( changePwdServer != null )
167         {
168             changePwdServer.setSearchBaseDn( this.getSearchBaseDn() );
169             changePwdServer.start();
170         }
171     }
172 
173 
174     public void stop()
175     {
176         for ( Transport transport : getTransports() )
177         {
178             IoAcceptor acceptor = transport.getAcceptor();
179 
180             if ( acceptor != null )
181             {
182                 acceptor.dispose();
183             }
184         }
185 
186         if ( replayCache != null )
187         {
188             replayCache.clear();
189         }
190 
191         LOG.info( "Kerberos service stopped." );
192 
193         if ( changePwdServer != null )
194         {
195             changePwdServer.stop();
196         }
197     }
198 
199 
200     /**
201      * gets the port number on which TCP transport is running
202      * @return the port number if TCP transport is enabled, -1 otherwise 
203      */
204     public int getTcpPort()
205     {
206         for ( Transport t : transports )
207         {
208             if ( t instanceof TcpTransport )
209             {
210                 return t.getPort();
211             }
212         }
213 
214         return -1;
215     }
216 
217 
218     /**
219      * @return the KDC server configuration
220      */
221     public KerberosConfig getConfig()
222     {
223         return config;
224     }
225 
226 
227     public ChangePasswordServer getChangePwdServer()
228     {
229         return changePwdServer;
230     }
231 
232 
233     public void setChangePwdServer( ChangePasswordServer changePwdServer )
234     {
235         this.changePwdServer = changePwdServer;
236     }
237 
238 
239     /**
240      * @see Object#toString()
241      */
242     public String toString()
243     {
244         StringBuilder sb = new StringBuilder();
245 
246         sb.append( "KDCServer[" ).append( getServiceName() ).append( "], listening on :" ).append( '\n' );
247 
248         if ( getTransports() != null )
249         {
250             for ( Transport transport : getTransports() )
251             {
252                 sb.append( "    " ).append( transport ).append( '\n' );
253             }
254         }
255 
256         return sb.toString();
257     }
258 }