001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 *
019 */
020package org.apache.directory.server.ldap;
021
022
023import java.io.IOException;
024import java.security.KeyStore;
025import java.util.ArrayList;
026import java.util.Collection;
027import java.util.HashMap;
028import java.util.HashSet;
029import java.util.Iterator;
030import java.util.List;
031import java.util.Map;
032import java.util.Set;
033
034import javax.net.ssl.KeyManagerFactory;
035import javax.net.ssl.TrustManager;
036import javax.net.ssl.TrustManagerFactory;
037
038import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
039import org.apache.directory.api.ldap.model.constants.Loggers;
040import org.apache.directory.api.ldap.model.constants.SaslQoP;
041import org.apache.directory.api.ldap.model.exception.LdapConfigurationException;
042import org.apache.directory.api.ldap.model.exception.LdapException;
043import org.apache.directory.api.ldap.model.message.AbandonRequest;
044import org.apache.directory.api.ldap.model.message.AddRequest;
045import org.apache.directory.api.ldap.model.message.AddResponse;
046import org.apache.directory.api.ldap.model.message.BindRequest;
047import org.apache.directory.api.ldap.model.message.BindResponse;
048import org.apache.directory.api.ldap.model.message.CompareRequest;
049import org.apache.directory.api.ldap.model.message.CompareResponse;
050import org.apache.directory.api.ldap.model.message.DeleteRequest;
051import org.apache.directory.api.ldap.model.message.DeleteResponse;
052import org.apache.directory.api.ldap.model.message.ExtendedRequest;
053import org.apache.directory.api.ldap.model.message.ExtendedResponse;
054import org.apache.directory.api.ldap.model.message.IntermediateResponse;
055import org.apache.directory.api.ldap.model.message.ModifyDnRequest;
056import org.apache.directory.api.ldap.model.message.ModifyDnResponse;
057import org.apache.directory.api.ldap.model.message.ModifyRequest;
058import org.apache.directory.api.ldap.model.message.ModifyResponse;
059import org.apache.directory.api.ldap.model.message.SearchRequest;
060import org.apache.directory.api.ldap.model.message.SearchResultDone;
061import org.apache.directory.api.ldap.model.message.SearchResultEntry;
062import org.apache.directory.api.ldap.model.message.SearchResultReference;
063import org.apache.directory.api.ldap.model.message.UnbindRequest;
064import org.apache.directory.api.ldap.model.message.extended.NoticeOfDisconnect;
065import org.apache.directory.server.core.api.DirectoryService;
066import org.apache.directory.server.core.api.partition.PartitionNexus;
067import org.apache.directory.server.core.security.CertificateUtil;
068import org.apache.directory.server.i18n.I18n;
069import org.apache.directory.server.ldap.handlers.LdapRequestHandler;
070import org.apache.directory.server.ldap.handlers.LdapResponseHandler;
071import org.apache.directory.server.ldap.handlers.extended.StartTlsHandler;
072import org.apache.directory.server.ldap.handlers.request.AbandonRequestHandler;
073import org.apache.directory.server.ldap.handlers.request.AddRequestHandler;
074import org.apache.directory.server.ldap.handlers.request.BindRequestHandler;
075import org.apache.directory.server.ldap.handlers.request.CompareRequestHandler;
076import org.apache.directory.server.ldap.handlers.request.DeleteRequestHandler;
077import org.apache.directory.server.ldap.handlers.request.ExtendedRequestHandler;
078import org.apache.directory.server.ldap.handlers.request.ModifyDnRequestHandler;
079import org.apache.directory.server.ldap.handlers.request.ModifyRequestHandler;
080import org.apache.directory.server.ldap.handlers.request.SearchRequestHandler;
081import org.apache.directory.server.ldap.handlers.request.UnbindRequestHandler;
082import org.apache.directory.server.ldap.handlers.response.AddResponseHandler;
083import org.apache.directory.server.ldap.handlers.response.BindResponseHandler;
084import org.apache.directory.server.ldap.handlers.response.CompareResponseHandler;
085import org.apache.directory.server.ldap.handlers.response.DeleteResponseHandler;
086import org.apache.directory.server.ldap.handlers.response.ExtendedResponseHandler;
087import org.apache.directory.server.ldap.handlers.response.IntermediateResponseHandler;
088import org.apache.directory.server.ldap.handlers.response.ModifyDnResponseHandler;
089import org.apache.directory.server.ldap.handlers.response.ModifyResponseHandler;
090import org.apache.directory.server.ldap.handlers.response.SearchResultDoneHandler;
091import org.apache.directory.server.ldap.handlers.response.SearchResultEntryHandler;
092import org.apache.directory.server.ldap.handlers.response.SearchResultReferenceHandler;
093import org.apache.directory.server.ldap.handlers.sasl.MechanismHandler;
094import org.apache.directory.server.ldap.handlers.ssl.LdapsInitializer;
095import org.apache.directory.server.ldap.replication.consumer.PingerThread;
096import org.apache.directory.server.ldap.replication.consumer.ReplicationConsumer;
097import org.apache.directory.server.ldap.replication.consumer.ReplicationStatusEnum;
098import org.apache.directory.server.ldap.replication.provider.ReplicationRequestHandler;
099import org.apache.directory.server.protocol.shared.DirectoryBackedService;
100import org.apache.directory.server.protocol.shared.transport.TcpTransport;
101import org.apache.directory.server.protocol.shared.transport.Transport;
102import org.apache.directory.server.protocol.shared.transport.UdpTransport;
103import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
104import org.apache.mina.core.filterchain.IoFilterChainBuilder;
105import org.apache.mina.core.future.WriteFuture;
106import org.apache.mina.core.service.IoHandler;
107import org.apache.mina.core.session.IoEventType;
108import org.apache.mina.core.session.IoSession;
109import org.apache.mina.filter.codec.ProtocolCodecFactory;
110import org.apache.mina.filter.codec.ProtocolCodecFilter;
111import org.apache.mina.filter.executor.ExecutorFilter;
112import org.apache.mina.filter.executor.UnorderedThreadPoolExecutor;
113import org.apache.mina.handler.demux.MessageHandler;
114import org.apache.mina.transport.socket.AbstractSocketSessionConfig;
115import org.apache.mina.transport.socket.SocketAcceptor;
116import org.slf4j.Logger;
117import org.slf4j.LoggerFactory;
118import org.slf4j.MDC;
119
120
121/**
122 * An LDAP protocol provider implementation which dynamically associates
123 * handlers.
124 *
125 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
126 */
127public class LdapServer extends DirectoryBackedService
128{
129    /** logger for this class */
130    private static final Logger LOG = LoggerFactory.getLogger( LdapServer.class );
131
132    /** Logger for the replication consumer */
133    private static final Logger CONSUMER_LOG = LoggerFactory.getLogger( Loggers.CONSUMER_LOG.getName() );
134
135    /** Value (0) for configuration where size limit is unlimited. */
136    public static final long NO_SIZE_LIMIT = 0;
137
138    /** Value (0) for configuration where time limit is unlimited. */
139    public static final int NO_TIME_LIMIT = 0;
140
141    /** the constant service name of this ldap protocol provider **/
142    public static final String SERVICE_NAME = "ldap";
143
144    /** The default maximum size limit. */
145    private static final long MAX_SIZE_LIMIT_DEFAULT = 100;
146
147    /** The default maximum time limit. */
148    private static final int MAX_TIME_LIMIT_DEFAULT = 10000;
149
150    /** The default service pid. */
151    private static final String SERVICE_PID_DEFAULT = "org.apache.directory.server.ldap";
152
153    /** The default service name. */
154    private static final String SERVICE_NAME_DEFAULT = "ApacheDS LDAP Service";
155
156    /** the session manager for this LdapServer */
157    private LdapSessionManager ldapSessionManager = new LdapSessionManager();
158
159    /** a set of supported controls */
160    private Set<String> supportedControls;
161
162    /**
163     * The maximum size limit.
164     * @see {@link LdapServer#MAX_SIZE_LIMIT_DEFAULT }
165     */
166    private long maxSizeLimit = MAX_SIZE_LIMIT_DEFAULT;
167
168    /**
169     * The maximum time limit.
170     * @see {@link LdapServer#MAX_TIME_LIMIT_DEFAULT }
171     */
172    private int maxTimeLimit = MAX_TIME_LIMIT_DEFAULT;
173
174    /** The maximum size for an incoming PDU */
175    private int maxPDUSize = Integer.MAX_VALUE;
176
177    /** If LDAPS is activated : the external Keystore file, if defined */
178    private String keystoreFile;
179
180    /** If LDAPS is activated : the certificate password */
181    private String certificatePassword;
182
183    /** The extended operation handlers. */
184    private final Collection<ExtendedOperationHandler<? extends ExtendedRequest, ? extends ExtendedResponse>> extendedOperationHandlers =
185        new ArrayList<>();
186
187    /** The supported authentication mechanisms. */
188    private Map<String, MechanismHandler> saslMechanismHandlers = new HashMap<>();
189
190    /** The name of this host, validated during SASL negotiation. */
191    private String saslHost = "ldap.example.com";
192
193    /** The service principal, used by GSSAPI. */
194    private String saslPrincipal = "ldap/ldap.example.com@EXAMPLE.COM";
195
196    /** The quality of protection (QoP), used by DIGEST-MD5 and GSSAPI. */
197    private Set<String> saslQop;
198    private String saslQopString;
199
200    /** The list of realms serviced by this host. */
201    private List<String> saslRealms;
202
203    /** The protocol handlers */
204    // MessageReceived handlers
205    private LdapRequestHandler<AbandonRequest> abandonRequestHandler;
206    private LdapRequestHandler<AddRequest> addRequestHandler;
207    private LdapRequestHandler<BindRequest> bindRequestHandler;
208    private LdapRequestHandler<CompareRequest> compareRequestHandler;
209    private LdapRequestHandler<DeleteRequest> deleteRequestHandler;
210    private ExtendedRequestHandler extendedRequestHandler;
211    private LdapRequestHandler<ModifyRequest> modifyRequestHandler;
212    private LdapRequestHandler<ModifyDnRequest> modifyDnRequestHandler;
213    private LdapRequestHandler<SearchRequest> searchRequestHandler;
214    private LdapRequestHandler<UnbindRequest> unbindRequestHandler;
215
216    // MessageSent handlers
217    private LdapResponseHandler<AddResponse> addResponseHandler;
218    private LdapResponseHandler<BindResponse> bindResponseHandler;
219    private LdapResponseHandler<CompareResponse> compareResponseHandler;
220    private LdapResponseHandler<DeleteResponse> deleteResponseHandler;
221    private ExtendedResponseHandler extendedResponseHandler;
222    private LdapResponseHandler<ModifyResponse> modifyResponseHandler;
223    private LdapResponseHandler<IntermediateResponse> intermediateResponseHandler;
224    private LdapResponseHandler<ModifyDnResponse> modifyDnResponseHandler;
225    private LdapResponseHandler<SearchResultEntry> searchResultEntryHandler;
226    private LdapResponseHandler<SearchResultReference> searchResultReferenceHandler;
227    private LdapResponseHandler<SearchResultDone> searchResultDoneHandler;
228
229    /** the underlying provider codec factory */
230    private ProtocolCodecFactory codecFactory = LdapApiServiceFactory.getSingleton().getProtocolCodecFactory();
231
232    /** the MINA protocol handler */
233    private final LdapProtocolHandler handler = new LdapProtocolHandler( this );
234
235    /** tracks start state of the server */
236    private boolean started;
237
238    /**
239     * Whether or not confidentiality (TLS secured connection) is required:
240     * disabled by default.
241     */
242    private boolean confidentialityRequired;
243
244    private List<IoFilterChainBuilder> chainBuilders = new ArrayList<>();
245
246    /** The handler responsible for the replication */
247    private ReplicationRequestHandler replicationReqHandler;
248
249    /** The list of replication consumers */
250    private List<ReplicationConsumer> replConsumers;
251
252    private KeyManagerFactory keyManagerFactory;
253    private TrustManager[] trustManagers;
254
255    /** the time interval between subsequent pings to each replication provider */
256    private int pingerSleepTime;
257
258    /**
259     * the list of cipher suites to be used in LDAPS and StartTLS
260     * @deprecated See the {@link TcpTransport} class that contains this list
261     **/
262    @Deprecated
263    private List<String> enabledCipherSuites = new ArrayList<>();
264
265
266    /**
267     * Creates an LDAP protocol provider.
268     */
269    public LdapServer()
270    {
271        super.setEnabled( true );
272        super.setServiceId( SERVICE_PID_DEFAULT );
273        super.setServiceName( SERVICE_NAME_DEFAULT );
274
275        saslQop = new HashSet<>();
276        saslQop.add( SaslQoP.AUTH.getValue() );
277        saslQop.add( SaslQoP.AUTH_INT.getValue() );
278        saslQop.add( SaslQoP.AUTH_CONF.getValue() );
279        saslQopString = SaslQoP.AUTH.getValue() + ',' + SaslQoP.AUTH_INT.getValue() + ','
280            + SaslQoP.AUTH_CONF.getValue();
281
282        saslRealms = new ArrayList<>();
283        saslRealms.add( "example.com" );
284
285        this.supportedControls = new HashSet<>();
286    }
287
288
289    /**
290     * Install the LDAP request handlers.
291     */
292    private void installDefaultHandlers()
293    {
294        if ( getAbandonRequestHandler() == null )
295        {
296            setAbandonHandler( new AbandonRequestHandler() );
297        }
298
299        if ( getAddRequestHandler() == null )
300        {
301            setAddHandlers( new AddRequestHandler(), new AddResponseHandler() );
302        }
303
304        if ( getBindRequestHandler() == null )
305        {
306            BindRequestHandler bindRequestHandler = new BindRequestHandler();
307            bindRequestHandler.setSaslMechanismHandlers( saslMechanismHandlers );
308
309            setBindHandlers( bindRequestHandler, new BindResponseHandler() );
310        }
311
312        if ( getCompareRequestHandler() == null )
313        {
314            setCompareHandlers( new CompareRequestHandler(), new CompareResponseHandler() );
315        }
316
317        if ( getDeleteRequestHandler() == null )
318        {
319            setDeleteHandlers( new DeleteRequestHandler(), new DeleteResponseHandler() );
320        }
321
322        if ( getExtendedRequestHandler() == null )
323        {
324            setExtendedHandlers( new ExtendedRequestHandler(), new ExtendedResponseHandler() );
325        }
326
327        if ( getIntermediateResponseHandler() == null )
328        {
329            setIntermediateHandler( new IntermediateResponseHandler() );
330        }
331
332        if ( getModifyRequestHandler() == null )
333        {
334            setModifyHandlers( new ModifyRequestHandler(), new ModifyResponseHandler() );
335        }
336
337        if ( getModifyDnRequestHandler() == null )
338        {
339            setModifyDnHandlers( new ModifyDnRequestHandler(), new ModifyDnResponseHandler() );
340        }
341
342        if ( getSearchRequestHandler() == null )
343        {
344            setSearchHandlers( new SearchRequestHandler(),
345                new SearchResultEntryHandler(),
346                new SearchResultReferenceHandler(),
347                new SearchResultDoneHandler() );
348        }
349
350        if ( getUnbindRequestHandler() == null )
351        {
352            setUnbindHandler( new UnbindRequestHandler() );
353        }
354    }
355
356
357    /**
358     * reloads the SSL context by replacing the existing SslFilter
359     * with a new SslFilter after reloading the keystore.
360     *
361     * Note: should be called to reload the keystore after changing the digital certificate.
362     * @throws Exception If the SSLContext can't be reloaded
363     */
364    public void reloadSslContext() throws Exception
365    {
366        if ( !started )
367        {
368            return;
369        }
370
371        LOG.info( "reloading SSL context..." );
372
373        keyManagerFactory = CertificateUtil.loadKeyStore( keystoreFile, certificatePassword );
374
375        String sslFilterName = "sslFilter";
376
377        for ( IoFilterChainBuilder chainBuilder : chainBuilders )
378        {
379            DefaultIoFilterChainBuilder dfcb = ( ( DefaultIoFilterChainBuilder ) chainBuilder );
380
381            if ( dfcb.contains( sslFilterName ) )
382            {
383                // Get the TcpTransport
384                TcpTransport tcpTransport = null;
385
386                for ( Transport transport : getTransports() )
387                {
388                    if ( transport instanceof TcpTransport )
389                    {
390                        tcpTransport = ( TcpTransport ) transport;
391                        break;
392                    }
393                }
394
395                DefaultIoFilterChainBuilder newChain = ( DefaultIoFilterChainBuilder ) LdapsInitializer
396                    .init( this, tcpTransport );
397                dfcb.replace( sslFilterName, newChain.get( sslFilterName ) );
398                newChain = null;
399            }
400        }
401
402        StartTlsHandler handler = ( StartTlsHandler ) getExtendedOperationHandler( StartTlsHandler.EXTENSION_OID );
403
404        if ( handler != null )
405        {
406            handler.setLdapServer( this );
407        }
408
409        LOG.info( "reloaded SSL context successfully" );
410    }
411
412
413    /**
414     * @throws IOException if we cannot bind to the specified port
415     * @throws Exception if the LDAP server cannot be started
416     */
417    @Override
418    public void start() throws Exception
419    {
420        if ( !isEnabled() )
421        {
422            return;
423        }
424
425        keyManagerFactory = CertificateUtil.loadKeyStore( keystoreFile, certificatePassword );
426
427        if ( trustManagers == null )
428        {
429            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm() );
430            trustManagerFactory.init( ( KeyStore ) null );
431            trustManagers = trustManagerFactory.getTrustManagers();
432        }
433
434        /*
435         * The server is now initialized, we can
436         * install the default requests handlers, which need
437         * access to the DirectoryServer instance.
438         */
439        installDefaultHandlers();
440
441        PartitionNexus nexus = getDirectoryService().getPartitionNexus();
442
443        for ( ExtendedOperationHandler<? extends ExtendedRequest, ? extends ExtendedResponse> h : extendedOperationHandlers )
444        {
445            LOG.info( "Added Extended Request Handler: {}", h.getOid() );
446            h.setLdapServer( this );
447            nexus.registerSupportedExtensions( h.getExtensionOids() );
448        }
449
450        nexus.registerSupportedSaslMechanisms( saslMechanismHandlers.keySet() );
451
452        // Install the replication handler if we have one
453        startReplicationProducer();
454
455        for ( Transport transport : transports )
456        {
457            if ( !( transport instanceof TcpTransport ) )
458            {
459                LOG.warn( "Cannot listen on an UDP transport : {}", transport );
460                continue;
461            }
462
463            IoFilterChainBuilder chain;
464
465            if ( transport.isSSLEnabled() )
466            {
467                chain = LdapsInitializer.init( this, ( TcpTransport ) transport );
468            }
469            else
470            {
471                chain = new DefaultIoFilterChainBuilder();
472            }
473
474            // Inject the codec into the chain
475            ( ( DefaultIoFilterChainBuilder ) chain ).addLast( "codec", new ProtocolCodecFilter( this
476                .getProtocolCodecFactory() ) );
477
478            // Now inject an ExecutorFilter for the write operations
479            // We use the same number of thread than the number of IoProcessor
480            // (NOTE : this has to be double checked)
481            ( ( DefaultIoFilterChainBuilder ) chain ).addLast( "executor", new ExecutorFilter(
482                new UnorderedThreadPoolExecutor( transport.getNbThreads() ), IoEventType.MESSAGE_RECEIVED ) );
483
484            /*
485            // Trace all the incoming and outgoing message to the console
486            ( ( DefaultIoFilterChainBuilder ) chain ).addLast( "logger", new IoFilterAdapter()
487                {
488                    public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception
489                    {
490                        System.out.println( ">>> Message received : " + message );
491                        nextFilter.messageReceived(session, message);
492                    }
493
494                    public void filterWrite(NextFilter nextFilter, IoSession session,
495                            WriteRequest writeRequest) throws Exception
496                    {
497                        System.out.println( "<<< Message sent : " + writeRequest.getMessage() );
498                        nextFilter.filterWrite(session, writeRequest);
499                    }
500                });
501            */
502
503            startNetwork( transport, chain );
504        }
505
506        // And start the replication consumers on this server
507        // these should be started only after starting the network see DIRSERVER-1894
508        startReplicationConsumers();
509
510        started = true;
511
512        LOG.info( "Ldap service started." );
513    }
514
515
516    /**
517     * Install the replication handler if we have one
518     */
519    public void startReplicationProducer()
520    {
521        if ( replicationReqHandler != null )
522        {
523            replicationReqHandler.start( this );
524            ( ( SearchRequestHandler ) getSearchRequestHandler() ).setReplicationReqHandler( replicationReqHandler );
525        }
526    }
527
528
529    /**
530     * {@inheritDoc}
531     */
532    @Override
533    public void stop()
534    {
535        try
536        {
537            for ( Transport transport : transports )
538            {
539                if ( !( transport instanceof TcpTransport ) )
540                {
541                    continue;
542                }
543
544                // we should unbind the service before we begin sending the notice
545                // of disconnect so new connections are not formed while we process
546                List<WriteFuture> writeFutures = new ArrayList<>();
547
548                // If the socket has already been unbound as with a successful
549                // GracefulShutdownRequest then this will complain that the service
550                // is not bound - this is ok because the GracefulShutdown has already
551                // sent notices to to the existing active sessions
552                List<IoSession> sessions;
553
554                try
555                {
556                    sessions = new ArrayList<>( getSocketAcceptor( transport ).getManagedSessions().values() );
557                }
558                catch ( IllegalArgumentException e )
559                {
560                    LOG.warn( "Seems like the LDAP service ({}) has already been unbound.", getPort() );
561                    return;
562                }
563
564                
565                // Kill the chain executor
566                ExecutorFilter executorFilter = ( ExecutorFilter ) transport.getAcceptor().getFilterChain().get( "executor" );
567                ( ( UnorderedThreadPoolExecutor ) executorFilter.getExecutor() ).shutdownNow();
568
569                // Shutdown the transport
570                getSocketAcceptor( transport ).dispose();
571
572                if ( LOG.isInfoEnabled() )
573                {
574                    LOG.info( "Unbind of an LDAP service ({}) is complete.", getPort() );
575                    LOG.info( "Sending notice of disconnect to existing clients sessions." );
576                }
577
578                // Send Notification of Disconnection messages to all connected clients.
579                if ( sessions != null )
580                {
581                    for ( IoSession session : sessions )
582                    {
583                        writeFutures.add( session.write( NoticeOfDisconnect.UNAVAILABLE ) );
584                    }
585                }
586
587                // And close the connections when the NoDs are sent.
588                Iterator<IoSession> sessionIt = sessions.iterator();
589
590                for ( WriteFuture future : writeFutures )
591                {
592                    future.await( 1000L );
593                    sessionIt.next().closeNow();
594                }
595
596                if ( replicationReqHandler != null )
597                {
598                    replicationReqHandler.stop();
599                }
600            }
601
602            // Stop the replication consumers
603            stopConsumers();
604        }
605        catch ( Exception e )
606        {
607            LOG.warn( "Failed to sent NoD.", e );
608        }
609
610        started = false;
611        LOG.info( "Ldap service stopped." );
612    }
613
614
615    private void startNetwork( Transport transport, IoFilterChainBuilder chainBuilder ) throws Exception
616    {
617        if ( transport.getBackLog() < 0 )
618        {
619            // Set the backlog to the default value when it's below 0
620            transport.setBackLog( 50 );
621        }
622
623        chainBuilders.add( chainBuilder );
624
625        try
626        {
627            SocketAcceptor acceptor = getSocketAcceptor( transport );
628
629            // Now, configure the acceptor
630            // Disable the disconnection of the clients on unbind
631            acceptor.setCloseOnDeactivation( false );
632
633            // No Nagle's algorithm
634            acceptor.getSessionConfig().setTcpNoDelay( true );
635
636            // Inject the chain
637            acceptor.setFilterChainBuilder( chainBuilder );
638
639            // Inject the protocol handler
640            acceptor.setHandler( getHandler() );
641
642            ( ( AbstractSocketSessionConfig ) acceptor.getSessionConfig() ).setReadBufferSize( 64 * 1024 );
643            ( ( AbstractSocketSessionConfig ) acceptor.getSessionConfig() ).setSendBufferSize( 64 * 1024 );
644
645            // Bind to the configured address
646            acceptor.bind();
647
648            // We are done !
649            started = true;
650
651            if ( LOG.isInfoEnabled() )
652            {
653                LOG.info( "Successful bind of an LDAP Service ({}) is completed.", transport.getPort() );
654            }
655        }
656        catch ( IOException e )
657        {
658            String msg = I18n.err( I18n.ERR_171, transport.getPort() );
659            LdapConfigurationException lce = new LdapConfigurationException( msg );
660            lce.setCause( e );
661            LOG.error( msg, e );
662            throw lce;
663        }
664    }
665
666
667    /**
668     * Starts the replication consumers
669     *
670     * @throws LdapException If the consumer can't be started
671     */
672    public void startReplicationConsumers() throws Exception
673    {
674        if ( ( replConsumers != null ) && !replConsumers.isEmpty() )
675        {
676            final PingerThread pingerThread = new PingerThread( pingerSleepTime );
677            pingerThread.start();
678
679            for ( final ReplicationConsumer consumer : replConsumers )
680            {
681                consumer.init( getDirectoryService() );
682
683                Runnable consumerTask = new Runnable()
684                {
685                    @Override
686                    public void run()
687                    {
688                        try
689                        {
690                            while ( true )
691                            {
692                                if ( CONSUMER_LOG.isDebugEnabled() )
693                                {
694                                    MDC.put( "Replica", consumer.getId() );
695                                }
696
697                                LOG.info( "starting the replication consumer with {}", consumer );
698                                CONSUMER_LOG.info( "starting the replication consumer with {}", consumer );
699                                boolean isConnected = consumer.connect( ReplicationConsumer.NOW );
700
701                                if ( isConnected )
702                                {
703                                    pingerThread.addConsumer( consumer );
704
705                                    // We are now connected, start the replication
706                                    ReplicationStatusEnum status = null;
707
708                                    do
709                                    {
710                                        status = consumer.startSync();
711                                    }
712                                    while ( status == ReplicationStatusEnum.REFRESH_REQUIRED );
713
714                                    if ( status == ReplicationStatusEnum.STOPPED )
715                                    {
716                                        // Exit the loop
717                                        break;
718                                    }
719                                }
720                            }
721                        }
722                        catch ( Exception e )
723                        {
724                            LOG.error( "Failed to start consumer {}", consumer );
725                            CONSUMER_LOG.error( "Failed to start consumer  {}", consumer );
726                            throw new RuntimeException( e );
727                        }
728                    }
729                };
730
731                Thread consumerThread = new Thread( consumerTask );
732                consumerThread.setDaemon( true );
733                consumerThread.start();
734            }
735        }
736    }
737
738
739    /**
740     * stops the replication consumers
741     */
742    private void stopConsumers()
743    {
744        if ( replConsumers != null )
745        {
746            for ( ReplicationConsumer consumer : replConsumers )
747            {
748                LOG.info( "stopping the consumer with id {}", consumer.getId() );
749                consumer.stop();
750            }
751        }
752    }
753
754
755    public String getName()
756    {
757        return SERVICE_NAME;
758    }
759
760
761    public IoHandler getHandler()
762    {
763        return handler;
764    }
765
766
767    public LdapSessionManager getLdapSessionManager()
768    {
769        return ldapSessionManager;
770    }
771
772
773    public ProtocolCodecFactory getProtocolCodecFactory()
774    {
775        return codecFactory;
776    }
777
778
779    // ------------------------------------------------------------------------
780    // Configuration Methods
781    // ------------------------------------------------------------------------
782
783    /**
784     * Registers the specified {@link ExtendedOperationHandler} to this
785     * protocol provider to provide a specific LDAP extended operation.
786     *
787     * @param eoh an extended operation handler
788     * @throws Exception on failure to add the handler
789     */
790    public void addExtendedOperationHandler( ExtendedOperationHandler<? extends ExtendedRequest,
791            ? extends ExtendedResponse> eoh ) throws LdapException
792    {
793        if ( started )
794        {
795            eoh.setLdapServer( this );
796            PartitionNexus nexus = getDirectoryService().getPartitionNexus();
797            nexus.registerSupportedExtensions( eoh.getExtensionOids() );
798        }
799        else
800        {
801            extendedOperationHandlers.add( eoh );
802        }
803    }
804
805
806    /**
807     * Deregister an {@link ExtendedOperationHandler} with the specified <tt>oid</tt>
808     * from this protocol provider.
809     *
810     * @param oid the numeric identifier for the extended operation associated with
811     * the handler to remove
812     */
813    public void removeExtendedOperationHandler( String oid )
814    {
815        // need to do something like this to make this work right
816        //            DefaultPartitionNexus nexus = getDirectoryService().getPartitionNexus();
817        //            nexus.unregisterSupportedExtensions( eoh.getExtensionOids() );
818
819        ExtendedOperationHandler<?, ?> handler = null;
820
821        for ( ExtendedOperationHandler<?, ?> extendedOperationHandler : extendedOperationHandlers )
822        {
823            if ( extendedOperationHandler.getOid().equals( oid ) )
824            {
825                handler = extendedOperationHandler;
826                break;
827            }
828        }
829
830        extendedOperationHandlers.remove( handler );
831    }
832
833
834    /**
835     * Returns an {@link ExtendedOperationHandler} with the specified <tt>oid</tt>
836     * which is registered to this protocol provider.
837     *
838     * @param oid the oid of the extended request of associated with the extended
839     * request handler
840     * @return the exnteded operation handler
841     */
842    public ExtendedOperationHandler<? extends ExtendedRequest, ? extends ExtendedResponse> getExtendedOperationHandler(
843        String oid )
844    {
845        for ( ExtendedOperationHandler<? extends ExtendedRequest, ? extends ExtendedResponse>
846                extendedOperationHandler : extendedOperationHandlers )
847        {
848            if ( extendedOperationHandler.getOid().equals( oid ) )
849            {
850                return extendedOperationHandler;
851            }
852        }
853
854        return null;
855    }
856
857
858    /**
859     * Sets the mode for this LdapServer to accept requests with or without a
860     * TLS secured connection via either StartTLS extended operations or using
861     * LDAPS.
862     *
863     * @param confidentialityRequired true to require confidentiality
864     */
865    public void setConfidentialityRequired( boolean confidentialityRequired )
866    {
867        this.confidentialityRequired = confidentialityRequired;
868    }
869
870
871    /**
872     * Gets whether or not TLS secured connections are required to perform
873     * operations on this LdapServer.
874     *
875     * @return true if TLS secured connections are required, false otherwise
876     */
877    public boolean isConfidentialityRequired()
878    {
879        return confidentialityRequired;
880    }
881
882
883    /**
884     * Returns <tt>true</tt> if LDAPS is enabled.
885     *
886     * @param transport The LDAP transport
887     * @return <tt>true</tt> if LDAPS is enabled.
888     */
889    public boolean isEnableLdaps( Transport transport )
890    {
891        return transport.isSSLEnabled();
892    }
893
894
895    /**
896     * Sets the maximum size limit in number of entries to return for search.
897     *
898     * @param maxSizeLimit the maximum number of entries to return for search
899     */
900    public void setMaxSizeLimit( long maxSizeLimit )
901    {
902        this.maxSizeLimit = maxSizeLimit;
903    }
904
905
906    /**
907     * Returns the maximum size limit in number of entries to return for search.
908     *
909     * @return The maximum size limit.
910     */
911    public long getMaxSizeLimit()
912    {
913        return maxSizeLimit;
914    }
915
916
917    /**
918     * Sets the maximum time limit in milliseconds to conduct a search.
919     *
920     * @param maxTimeLimit the maximum length of time in milliseconds for search
921     */
922    public void setMaxTimeLimit( int maxTimeLimit )
923    {
924        this.maxTimeLimit = maxTimeLimit; //TODO review the time parameters used all over the server and convert to seconds
925    }
926
927
928    /**
929     * Returns the maximum time limit in milliseconds to conduct a search.
930     *
931     * @return The maximum time limit in milliseconds for search
932     */
933    public int getMaxTimeLimit()
934    {
935        return maxTimeLimit;
936    }
937
938
939    /**
940     * Gets the {@link ExtendedOperationHandler}s.
941     *
942     * @return A collection of {@link ExtendedOperationHandler}s.
943     */
944    public Collection<ExtendedOperationHandler<? extends ExtendedRequest, ? extends ExtendedResponse>> getExtendedOperationHandlers()
945    {
946        return new ArrayList<>(
947            extendedOperationHandlers );
948    }
949
950
951    /**
952     * Sets the {@link ExtendedOperationHandler}s.
953     *
954     * @param handlers A collection of {@link ExtendedOperationHandler}s.
955     */
956    public void setExtendedOperationHandlers(
957        Collection<ExtendedOperationHandler<ExtendedRequest, ExtendedResponse>> handlers )
958    {
959        this.extendedOperationHandlers.clear();
960        this.extendedOperationHandlers.addAll( handlers );
961    }
962
963
964    /**
965     * Returns the FQDN of this SASL host, validated during SASL negotiation.
966     *
967     * @return The FQDN of this SASL host, validated during SASL negotiation.
968     */
969    public String getSaslHost()
970    {
971        return saslHost;
972    }
973
974
975    /**
976     * Sets the FQDN of this SASL host, validated during SASL negotiation.
977     *
978     * @param saslHost The FQDN of this SASL host, validated during SASL negotiation.
979     */
980    public void setSaslHost( String saslHost )
981    {
982        this.saslHost = saslHost;
983    }
984
985
986    /**
987     * Returns the Kerberos principal name for this LDAP service, used by GSSAPI.
988     *
989     * @return The Kerberos principal name for this LDAP service, used by GSSAPI.
990     */
991    public String getSaslPrincipal()
992    {
993        return saslPrincipal;
994    }
995
996
997    /**
998     * Sets the Kerberos principal name for this LDAP service, used by GSSAPI.
999     *
1000     * @param saslPrincipal The Kerberos principal name for this LDAP service, used by GSSAPI.
1001     */
1002    public void setSaslPrincipal( String saslPrincipal )
1003    {
1004        this.saslPrincipal = saslPrincipal;
1005    }
1006
1007
1008    /**
1009     * Returns the quality-of-protection, used by DIGEST-MD5 and GSSAPI.
1010     *
1011     * @return The quality-of-protection, used by DIGEST-MD5 and GSSAPI.
1012     */
1013    public String getSaslQopString()
1014    {
1015        return saslQopString;
1016    }
1017
1018
1019    /**
1020     * Returns the Set of quality-of-protection, used by DIGEST-MD5 and GSSAPI.
1021     *
1022     * @return The quality-of-protection, used by DIGEST-MD5 and GSSAPI.
1023     */
1024    public Set<String> getSaslQop()
1025    {
1026        return saslQop;
1027    }
1028
1029
1030    /**
1031     * Returns the realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI.
1032     *
1033     * @return The realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI.
1034     */
1035    public List<String> getSaslRealms()
1036    {
1037        return saslRealms;
1038    }
1039
1040
1041    /**
1042     * Sets the realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI.
1043     *
1044    * @param saslRealms The realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI.
1045     */
1046    public void setSaslRealms( List<String> saslRealms )
1047    {
1048        this.saslRealms = saslRealms;
1049    }
1050
1051
1052    /**
1053     * @return the supported SASL mechanisms
1054     */
1055    public Map<String, MechanismHandler> getSaslMechanismHandlers()
1056    {
1057        return saslMechanismHandlers;
1058    }
1059
1060
1061    public void setSaslMechanismHandlers( Map<String, MechanismHandler> saslMechanismHandlers )
1062    {
1063        this.saslMechanismHandlers = saslMechanismHandlers;
1064    }
1065
1066
1067    public MechanismHandler addSaslMechanismHandler( String mechanism, MechanismHandler handler )
1068    {
1069        return this.saslMechanismHandlers.put( mechanism, handler );
1070    }
1071
1072
1073    public MechanismHandler removeSaslMechanismHandler( String mechanism )
1074    {
1075        return this.saslMechanismHandlers.remove( mechanism );
1076    }
1077
1078
1079    public MechanismHandler getMechanismHandler( String mechanism )
1080    {
1081        return this.saslMechanismHandlers.get( mechanism );
1082    }
1083
1084
1085    public Set<String> getSupportedMechanisms()
1086    {
1087        return saslMechanismHandlers.keySet();
1088    }
1089
1090
1091    @Override
1092    public void setDirectoryService( DirectoryService directoryService )
1093    {
1094        super.setDirectoryService( directoryService );
1095        Iterator<String> itr = directoryService.getLdapCodecService().registeredRequestControls();
1096
1097        while ( itr.hasNext() )
1098        {
1099            supportedControls.add( itr.next() );
1100        }
1101
1102        itr = directoryService.getLdapCodecService().registeredResponseControls();
1103
1104        while ( itr.hasNext() )
1105        {
1106            supportedControls.add( itr.next() );
1107        }
1108    }
1109
1110
1111    public Set<String> getSupportedControls()
1112    {
1113        return supportedControls;
1114    }
1115
1116
1117    /**
1118     * @return The MessageReceived handler for the AbandonRequest
1119     */
1120    public MessageHandler<AbandonRequest> getAbandonRequestHandler()
1121    {
1122        return abandonRequestHandler;
1123    }
1124
1125
1126    /**
1127     * Inject the MessageReceived handler into the IoHandler
1128     *
1129     * @param abandonRequestdHandler The AbandonRequest message received handler
1130     */
1131    public void setAbandonHandler( LdapRequestHandler<AbandonRequest> abandonRequestdHandler )
1132    {
1133        this.handler.removeReceivedMessageHandler( AbandonRequest.class );
1134        this.abandonRequestHandler = abandonRequestdHandler;
1135        this.abandonRequestHandler.setLdapServer( this );
1136        this.handler.addReceivedMessageHandler( AbandonRequest.class, this.abandonRequestHandler );
1137    }
1138
1139
1140    /**
1141     * @return The MessageReceived handler for the AddRequest
1142     */
1143    public LdapRequestHandler<AddRequest> getAddRequestHandler()
1144    {
1145        return addRequestHandler;
1146    }
1147
1148
1149    /**
1150     * @return The MessageSent handler for the AddResponse
1151     */
1152    public LdapResponseHandler<AddResponse> getAddResponseHandler()
1153    {
1154        return addResponseHandler;
1155    }
1156
1157
1158    /**
1159     * Inject the MessageReceived and MessageSent handler into the IoHandler
1160     *
1161     * @param addRequestHandler The AddRequest message received handler
1162     * @param addResponseHandler The AddResponse message sent handler
1163     */
1164    public void setAddHandlers( LdapRequestHandler<AddRequest> addRequestHandler,
1165        LdapResponseHandler<AddResponse> addResponseHandler )
1166    {
1167        this.handler.removeReceivedMessageHandler( AddRequest.class );
1168        this.addRequestHandler = addRequestHandler;
1169        this.addRequestHandler.setLdapServer( this );
1170        this.handler.addReceivedMessageHandler( AddRequest.class, this.addRequestHandler );
1171
1172        this.handler.removeSentMessageHandler( AddResponse.class );
1173        this.addResponseHandler = addResponseHandler;
1174        this.addResponseHandler.setLdapServer( this );
1175        this.handler.addSentMessageHandler( AddResponse.class, this.addResponseHandler );
1176    }
1177
1178
1179    /**
1180     * @return The MessageReceived handler for the BindRequest
1181     */
1182    public LdapRequestHandler<BindRequest> getBindRequestHandler()
1183    {
1184        return bindRequestHandler;
1185    }
1186
1187
1188    /**
1189     * @return The MessageSent handler for the BindResponse
1190     */
1191    public LdapResponseHandler<BindResponse> getBindResponseHandler()
1192    {
1193        return bindResponseHandler;
1194    }
1195
1196
1197    /**
1198     * Inject the MessageReceived and MessageSent handler into the IoHandler
1199     *
1200     * @param bindRequestHandler The BindRequest message received handler
1201     * @param bindResponseHandler The BindResponse message sent handler
1202     */
1203    public void setBindHandlers( LdapRequestHandler<BindRequest> bindRequestHandler,
1204        LdapResponseHandler<BindResponse> bindResponseHandler )
1205    {
1206        handler.removeReceivedMessageHandler( BindRequest.class );
1207        this.bindRequestHandler = bindRequestHandler;
1208        this.bindRequestHandler.setLdapServer( this );
1209        handler.addReceivedMessageHandler( BindRequest.class, this.bindRequestHandler );
1210
1211        handler.removeSentMessageHandler( BindResponse.class );
1212        this.bindResponseHandler = bindResponseHandler;
1213        this.bindResponseHandler.setLdapServer( this );
1214        handler.addSentMessageHandler( BindResponse.class, this.bindResponseHandler );
1215    }
1216
1217
1218    /**
1219     * @return The MessageReceived handler for the CompareRequest
1220     */
1221    public LdapRequestHandler<CompareRequest> getCompareRequestHandler()
1222    {
1223        return compareRequestHandler;
1224    }
1225
1226
1227    /**
1228     * @return The MessageSent handler for the CompareResponse
1229     */
1230    public LdapResponseHandler<CompareResponse> getCompareResponseHandler()
1231    {
1232        return compareResponseHandler;
1233    }
1234
1235
1236    /**
1237     * Inject the MessageReceived and MessageSent handler into the IoHandler
1238     *
1239     * @param compareRequestHandler The CompareRequest message received handler
1240     * @param compareResponseHandler The CompareResponse message sent handler
1241     */
1242    public void setCompareHandlers( LdapRequestHandler<CompareRequest> compareRequestHandler,
1243        LdapResponseHandler<CompareResponse> compareResponseHandler )
1244    {
1245        handler.removeReceivedMessageHandler( CompareRequest.class );
1246        this.compareRequestHandler = compareRequestHandler;
1247        this.compareRequestHandler.setLdapServer( this );
1248        this.handler.addReceivedMessageHandler( CompareRequest.class, this.compareRequestHandler );
1249
1250        handler.removeReceivedMessageHandler( CompareResponse.class );
1251        this.compareResponseHandler = compareResponseHandler;
1252        this.compareResponseHandler.setLdapServer( this );
1253        this.handler.addSentMessageHandler( CompareResponse.class, this.compareResponseHandler );
1254    }
1255
1256
1257    /**
1258     * @return The MessageReceived handler for the DeleteRequest
1259     */
1260    public LdapRequestHandler<DeleteRequest> getDeleteRequestHandler()
1261    {
1262        return deleteRequestHandler;
1263    }
1264
1265
1266    /**
1267     * @return The MessageSent handler for the DeleteResponse
1268     */
1269    public LdapResponseHandler<DeleteResponse> getDeleteResponseHandler()
1270    {
1271        return deleteResponseHandler;
1272    }
1273
1274
1275    /**
1276     * Inject the MessageReceived and MessageSent handler into the IoHandler
1277     *
1278     * @param deleteRequestHandler The DeleteRequest message received handler
1279     * @param deleteResponseHandler The DeleteResponse message sent handler
1280     */
1281    public void setDeleteHandlers( LdapRequestHandler<DeleteRequest> deleteRequestHandler,
1282        LdapResponseHandler<DeleteResponse> deleteResponseHandler )
1283    {
1284        handler.removeReceivedMessageHandler( DeleteRequest.class );
1285        this.deleteRequestHandler = deleteRequestHandler;
1286        this.deleteRequestHandler.setLdapServer( this );
1287        this.handler.addReceivedMessageHandler( DeleteRequest.class, this.deleteRequestHandler );
1288
1289        handler.removeSentMessageHandler( DeleteResponse.class );
1290        this.deleteResponseHandler = deleteResponseHandler;
1291        this.deleteResponseHandler.setLdapServer( this );
1292        this.handler.addSentMessageHandler( DeleteResponse.class, this.deleteResponseHandler );
1293    }
1294
1295
1296    /**
1297     * @return The MessageReceived handler for the ExtendedRequest
1298     */
1299    public LdapRequestHandler<ExtendedRequest> getExtendedRequestHandler()
1300    {
1301        return extendedRequestHandler;
1302    }
1303
1304
1305    /**
1306     * @return The MessageSent handler for the ExtendedResponse
1307     */
1308    public LdapResponseHandler<ExtendedResponse> getExtendedResponseHandler()
1309    {
1310        return extendedResponseHandler;
1311    }
1312
1313
1314    /**
1315     * Inject the MessageReceived and MessageSent handler into the IoHandler
1316     *
1317     * @param extendedRequestHandler The ExtendedRequest message received handler
1318     * @param extendedResponseHandler The ExtendedResponse message sent handler
1319     */
1320    @SuppressWarnings(
1321        { "unchecked", "rawtypes" })
1322    public void setExtendedHandlers( ExtendedRequestHandler extendedRequestHandler,
1323        ExtendedResponseHandler extendedResponseHandler )
1324    {
1325        handler.removeReceivedMessageHandler( ExtendedRequest.class );
1326        this.extendedRequestHandler = extendedRequestHandler;
1327        this.extendedRequestHandler.setLdapServer( this );
1328        this.handler.addReceivedMessageHandler( ExtendedRequest.class,
1329            this.extendedRequestHandler );
1330
1331        handler.removeSentMessageHandler( ExtendedResponse.class );
1332        this.extendedResponseHandler = extendedResponseHandler;
1333        this.extendedResponseHandler.setLdapServer( this );
1334        this.handler.addSentMessageHandler( ExtendedResponse.class, this.extendedResponseHandler );
1335    }
1336
1337
1338    /**
1339     * @return The MessageSent handler for the IntermediateResponse
1340     */
1341    public LdapResponseHandler<IntermediateResponse> getIntermediateResponseHandler()
1342    {
1343        return intermediateResponseHandler;
1344    }
1345
1346
1347    /**
1348     * Inject the MessageReceived and MessageSent handler into the IoHandler
1349     *
1350     * @param intermediateResponseHandler The IntermediateResponse message sent handler
1351     */
1352    public void setIntermediateHandler( LdapResponseHandler<IntermediateResponse> intermediateResponseHandler )
1353    {
1354        handler.removeSentMessageHandler( IntermediateResponse.class );
1355        this.intermediateResponseHandler = intermediateResponseHandler;
1356        this.intermediateResponseHandler.setLdapServer( this );
1357        this.handler.addSentMessageHandler( IntermediateResponse.class, this.intermediateResponseHandler );
1358    }
1359
1360
1361    /**
1362     * @return The MessageReceived handler for the ModifyRequest
1363     */
1364    public LdapRequestHandler<ModifyRequest> getModifyRequestHandler()
1365    {
1366        return modifyRequestHandler;
1367    }
1368
1369
1370    /**
1371     * @return The MessageSent handler for the ModifyResponse
1372     */
1373    public LdapResponseHandler<ModifyResponse> getModifyResponseHandler()
1374    {
1375        return modifyResponseHandler;
1376    }
1377
1378
1379    /**
1380     * Inject the MessageReceived and MessageSent handler into the IoHandler
1381     *
1382     * @param modifyRequestHandler The ModifyRequest message received handler
1383     * @param modifyResponseHandler The ModifyResponse message sent handler
1384     */
1385    public void setModifyHandlers( LdapRequestHandler<ModifyRequest> modifyRequestHandler,
1386        LdapResponseHandler<ModifyResponse> modifyResponseHandler )
1387    {
1388        handler.removeReceivedMessageHandler( ModifyRequest.class );
1389        this.modifyRequestHandler = modifyRequestHandler;
1390        this.modifyRequestHandler.setLdapServer( this );
1391        this.handler.addReceivedMessageHandler( ModifyRequest.class, this.modifyRequestHandler );
1392
1393        handler.removeSentMessageHandler( ModifyResponse.class );
1394        this.modifyResponseHandler = modifyResponseHandler;
1395        this.modifyResponseHandler.setLdapServer( this );
1396        this.handler.addSentMessageHandler( ModifyResponse.class, this.modifyResponseHandler );
1397    }
1398
1399
1400    /**
1401     * @return The MessageSent handler for the ModifyDnRequest
1402     */
1403    public LdapRequestHandler<ModifyDnRequest> getModifyDnRequestHandler()
1404    {
1405        return modifyDnRequestHandler;
1406    }
1407
1408
1409    /**
1410     * @return The MessageSent handler for the ModifyDnResponse
1411     */
1412    public LdapResponseHandler<ModifyDnResponse> getModifyDnResponseHandler()
1413    {
1414        return modifyDnResponseHandler;
1415    }
1416
1417
1418    /**
1419     * Inject the MessageReceived and MessageSent handler into the IoHandler
1420     *
1421     * @param modifyDnRequestHandler The ModifyDnRequest message received handler
1422     * @param modifyDnResponseHandler The ModifyDnResponse message sent handler
1423     */
1424    public void setModifyDnHandlers( LdapRequestHandler<ModifyDnRequest> modifyDnRequestHandler,
1425        LdapResponseHandler<ModifyDnResponse> modifyDnResponseHandler )
1426    {
1427        handler.removeReceivedMessageHandler( ModifyDnRequest.class );
1428        this.modifyDnRequestHandler = modifyDnRequestHandler;
1429        this.modifyDnRequestHandler.setLdapServer( this );
1430        this.handler.addReceivedMessageHandler( ModifyDnRequest.class, this.modifyDnRequestHandler );
1431
1432        handler.removeSentMessageHandler( ModifyDnResponse.class );
1433        this.modifyDnResponseHandler = modifyDnResponseHandler;
1434        this.modifyDnResponseHandler.setLdapServer( this );
1435        this.handler.addSentMessageHandler( ModifyDnResponse.class, this.modifyDnResponseHandler );
1436    }
1437
1438
1439    /**
1440     * @return The MessageReceived handler for the SearchRequest
1441     */
1442    public LdapRequestHandler<SearchRequest> getSearchRequestHandler()
1443    {
1444        return searchRequestHandler;
1445    }
1446
1447
1448    /**
1449     * @return The MessageSent handler for the SearchResultEntry
1450     */
1451    public LdapResponseHandler<SearchResultEntry> getSearchResultEntryHandler()
1452    {
1453        return searchResultEntryHandler;
1454    }
1455
1456
1457    /**
1458     * @return The MessageSent handler for the SearchResultReference
1459     */
1460    public LdapResponseHandler<SearchResultReference> getSearchResultReferenceHandler()
1461    {
1462        return searchResultReferenceHandler;
1463    }
1464
1465
1466    /**
1467     * @return The MessageSent handler for the SearchResultDone
1468     */
1469    public LdapResponseHandler<SearchResultDone> getSearchResultDoneHandler()
1470    {
1471        return searchResultDoneHandler;
1472    }
1473
1474
1475    /**
1476     * Inject the MessageReceived and MessageSent handler into the IoHandler
1477     *
1478     * @param searchRequestHandler The SearchRequest message received handler
1479     * @param searchResultEntryHandler The SearchResultEntry message sent handler
1480     * @param searchResultReferenceHandler The SearchResultReference message sent handler
1481     * @param searchResultDoneHandler The SearchResultDone message sent handler
1482     */
1483    public void setSearchHandlers( LdapRequestHandler<SearchRequest> searchRequestHandler,
1484        LdapResponseHandler<SearchResultEntry> searchResultEntryHandler,
1485        LdapResponseHandler<SearchResultReference> searchResultReferenceHandler,
1486        LdapResponseHandler<SearchResultDone> searchResultDoneHandler
1487        )
1488    {
1489        this.handler.removeReceivedMessageHandler( SearchRequest.class );
1490        this.searchRequestHandler = searchRequestHandler;
1491        this.searchRequestHandler.setLdapServer( this );
1492        this.handler.addReceivedMessageHandler( SearchRequest.class, this.searchRequestHandler );
1493
1494        this.handler.removeSentMessageHandler( SearchResultEntry.class );
1495        this.searchResultEntryHandler = searchResultEntryHandler;
1496        this.searchResultEntryHandler.setLdapServer( this );
1497        this.handler.addSentMessageHandler( SearchResultEntry.class, this.searchResultEntryHandler );
1498
1499        this.handler.removeSentMessageHandler( SearchResultReference.class );
1500        this.searchResultReferenceHandler = searchResultReferenceHandler;
1501        this.searchResultReferenceHandler.setLdapServer( this );
1502        this.handler.addSentMessageHandler( SearchResultReference.class, this.searchResultReferenceHandler );
1503
1504        this.handler.removeSentMessageHandler( SearchResultDone.class );
1505        this.searchResultDoneHandler = searchResultDoneHandler;
1506        this.searchResultDoneHandler.setLdapServer( this );
1507        this.handler.addSentMessageHandler( SearchResultDone.class, this.searchResultDoneHandler );
1508    }
1509
1510
1511    /**
1512     * @return The MessageReceived handler for the UnbindRequest
1513     */
1514    public LdapRequestHandler<UnbindRequest> getUnbindRequestHandler()
1515    {
1516        return unbindRequestHandler;
1517    }
1518
1519
1520    /**
1521     * Inject the MessageReceived handler into the IoHandler
1522     *
1523     * @param unbindRequestHandler The UnbindRequest message received handler
1524     */
1525    public void setUnbindHandler( LdapRequestHandler<UnbindRequest> unbindRequestHandler )
1526    {
1527        this.handler.removeReceivedMessageHandler( UnbindRequest.class );
1528        this.unbindRequestHandler = unbindRequestHandler;
1529        this.unbindRequestHandler.setLdapServer( this );
1530        this.handler.addReceivedMessageHandler( UnbindRequest.class, this.unbindRequestHandler );
1531    }
1532
1533
1534    /**
1535     * @return The underlying TCP transport port, or -1 if no transport has been
1536     * initialized
1537     */
1538    public int getPort()
1539    {
1540        if ( transports == null )
1541        {
1542            return -1;
1543        }
1544
1545        for ( Transport transport : transports )
1546        {
1547            if ( transport instanceof UdpTransport )
1548            {
1549                continue;
1550            }
1551
1552            if ( !transport.isSSLEnabled() )
1553            {
1554                return transport.getPort();
1555            }
1556        }
1557
1558        return -1;
1559    }
1560
1561
1562    /**
1563     * @return The underlying SSL enabled TCP transport port, or -1 if no transport has been
1564     * initialized
1565     */
1566    public int getPortSSL()
1567    {
1568        if ( transports == null )
1569        {
1570            return -1;
1571        }
1572
1573        for ( Transport transport : transports )
1574        {
1575            if ( transport instanceof UdpTransport )
1576            {
1577                continue;
1578            }
1579
1580            if ( transport.isSSLEnabled() )
1581            {
1582                return transport.getPort();
1583            }
1584        }
1585
1586        return -1;
1587    }
1588
1589
1590    @Override
1591    public boolean isStarted()
1592    {
1593        return started;
1594    }
1595
1596
1597    /**
1598     */
1599    @Override
1600    public void setStarted( boolean started )
1601    {
1602        this.started = started;
1603    }
1604
1605
1606    /**
1607     * @return The keystore path
1608     */
1609    public String getKeystoreFile()
1610    {
1611        return keystoreFile;
1612    }
1613
1614
1615    /**
1616     * Set the external keystore path
1617     * @param keystoreFile The external keystore path
1618     */
1619    public void setKeystoreFile( String keystoreFile )
1620    {
1621        this.keystoreFile = keystoreFile;
1622    }
1623
1624
1625    /**
1626     * @return The certificate password
1627     */
1628    public String getCertificatePassword()
1629    {
1630        return certificatePassword;
1631    }
1632
1633
1634    /**
1635     * Set the certificate password.
1636     * @param certificatePassword the certificate password
1637     */
1638    public void setCertificatePassword( String certificatePassword )
1639    {
1640        this.certificatePassword = certificatePassword;
1641    }
1642
1643
1644    public void setReplicationReqHandler( ReplicationRequestHandler replicationProvider )
1645    {
1646        this.replicationReqHandler = replicationProvider;
1647    }
1648
1649
1650    public ReplicationRequestHandler getReplicationReqHandler()
1651    {
1652        return replicationReqHandler;
1653    }
1654
1655
1656    public void setReplConsumers( List<ReplicationConsumer> replConsumers )
1657    {
1658        this.replConsumers = replConsumers;
1659    }
1660
1661
1662    /**
1663     * @return the key manager factory of the server keystore
1664     */
1665    public KeyManagerFactory getKeyManagerFactory()
1666    {
1667        return keyManagerFactory;
1668    }
1669
1670    /**
1671     * @return the trust managers of the server
1672     */
1673    public TrustManager[] getTrustManagers()
1674    {
1675        return trustManagers;
1676    }
1677
1678    public void setTrustManagers( TrustManager[] trustManagers )
1679    {
1680        this.trustManagers = trustManagers;
1681    }
1682
1683    /**
1684     * @return The maximum allowed size for an incoming PDU
1685     */
1686    public int getMaxPDUSize()
1687    {
1688        return maxPDUSize;
1689    }
1690
1691
1692    /**
1693     * Set the maximum allowed size for an incoming PDU
1694     * @param maxPDUSize A positive number of bytes for the PDU. A negative or
1695     * null value will be transformed to {@link Integer#MAX_VALUE}
1696     */
1697    public void setMaxPDUSize( int maxPDUSize )
1698    {
1699        if ( maxPDUSize <= 0 )
1700        {
1701            maxPDUSize = Integer.MAX_VALUE;
1702        }
1703
1704        this.maxPDUSize = maxPDUSize;
1705    }
1706
1707
1708    /**
1709     * @return the number of seconds pinger thread sleeps between subsequent pings
1710     */
1711    public int getReplPingerSleepTime()
1712    {
1713        return pingerSleepTime;
1714    }
1715
1716
1717    /**
1718     * The number of seconds pinger thread should sleep before pinging the providers
1719     *
1720     * @param pingerSleepTime The delay between 2 pings
1721     */
1722    public void setReplPingerSleepTime( int pingerSleepTime )
1723    {
1724        this.pingerSleepTime = pingerSleepTime;
1725    }
1726
1727
1728    /**
1729     * Gives the list of enabled cipher suites
1730     * <br>
1731     * This method has been deprecated, please set this list in the TcpTransport class
1732     * <br>
1733     *
1734     * @return The list of ciphers that can be used
1735     * @deprecated Set this list in the {@link TcpTransport} class
1736     */
1737    @Deprecated
1738    public List<String> getEnabledCipherSuites()
1739    {
1740        return enabledCipherSuites;
1741    }
1742
1743
1744    /**
1745     * Sets the list of cipher suites to be used in LDAPS and StartTLS
1746     * <br>
1747     * This method has been deprecated, please set this list in the TcpTransport class
1748     * <br>
1749     *
1750     * @param enabledCipherSuites if null the default cipher suites will be used
1751     * @deprecated Get this list from the {@link TcpTransport} class
1752     */
1753    @Deprecated
1754    public void setEnabledCipherSuites( List<String> enabledCipherSuites )
1755    {
1756        this.enabledCipherSuites = enabledCipherSuites;
1757    }
1758
1759
1760    /**
1761     * @see Object#toString()
1762     */
1763    @Override
1764    public String toString()
1765    {
1766        StringBuilder sb = new StringBuilder();
1767
1768        sb.append( "LdapServer[" ).append( getServiceName() ).append( "], listening on :" ).append( '\n' );
1769
1770        if ( getTransports() != null )
1771        {
1772            for ( Transport transport : getTransports() )
1773            {
1774                sb.append( "    " ).append( transport ).append( '\n' );
1775            }
1776        }
1777
1778        return sb.toString();
1779    }
1780}