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 */
020 package org.apache.directory.server.ldap;
021
022
023 import java.io.FileInputStream;
024 import java.io.IOException;
025 import java.security.KeyStore;
026 import java.security.KeyStoreSpi;
027 import java.security.Provider;
028 import java.security.Security;
029 import java.util.ArrayList;
030 import java.util.Collection;
031 import java.util.HashMap;
032 import java.util.HashSet;
033 import java.util.Iterator;
034 import java.util.List;
035 import java.util.Map;
036 import java.util.Set;
037
038
039 import org.apache.directory.server.core.DirectoryService;
040 import org.apache.directory.server.core.partition.PartitionNexus;
041 import org.apache.directory.server.core.security.CoreKeyStoreSpi;
042 import org.apache.directory.server.ldap.handlers.LdapRequestHandler;
043 import org.apache.directory.server.ldap.handlers.AbandonHandler;
044 import org.apache.directory.server.ldap.handlers.AddHandler;
045 import org.apache.directory.server.ldap.handlers.BindHandler;
046 import org.apache.directory.server.ldap.handlers.CompareHandler;
047 import org.apache.directory.server.ldap.handlers.DeleteHandler;
048 import org.apache.directory.server.ldap.handlers.ExtendedHandler;
049 import org.apache.directory.server.ldap.handlers.ModifyDnHandler;
050 import org.apache.directory.server.ldap.handlers.ModifyHandler;
051 import org.apache.directory.server.ldap.handlers.SearchHandler;
052 import org.apache.directory.server.ldap.handlers.UnbindHandler;
053 import org.apache.directory.server.ldap.handlers.bind.MechanismHandler;
054 import org.apache.directory.server.ldap.handlers.ssl.LdapsInitializer;
055 import org.apache.directory.server.ldap.replication.ReplicationSystem;
056 import org.apache.directory.server.protocol.shared.DirectoryBackedService;
057 import org.apache.directory.server.protocol.shared.transport.TcpTransport;
058 import org.apache.directory.server.protocol.shared.transport.Transport;
059 import org.apache.directory.server.protocol.shared.transport.UdpTransport;
060 import org.apache.directory.shared.ldap.constants.SaslQoP;
061 import org.apache.directory.shared.ldap.exception.LdapConfigurationException;
062 import org.apache.directory.shared.ldap.message.InternalAbandonRequest;
063 import org.apache.directory.shared.ldap.message.InternalAddRequest;
064 import org.apache.directory.shared.ldap.message.InternalBindRequest;
065 import org.apache.directory.shared.ldap.message.InternalCompareRequest;
066 import org.apache.directory.shared.ldap.message.InternalDeleteRequest;
067 import org.apache.directory.shared.ldap.message.InternalExtendedRequest;
068 import org.apache.directory.shared.ldap.message.InternalModifyDnRequest;
069 import org.apache.directory.shared.ldap.message.InternalModifyRequest;
070 import org.apache.directory.shared.ldap.message.InternalSearchRequest;
071 import org.apache.directory.shared.ldap.message.InternalUnbindRequest;
072 import org.apache.directory.shared.ldap.message.control.CascadeControl;
073 import org.apache.directory.shared.ldap.message.control.EntryChangeControl;
074 import org.apache.directory.shared.ldap.message.control.ManageDsaITControl;
075 import org.apache.directory.shared.ldap.message.control.PagedSearchControl;
076 import org.apache.directory.shared.ldap.message.control.PersistentSearchControl;
077 import org.apache.directory.shared.ldap.message.control.SubentriesControl;
078 import org.apache.directory.shared.ldap.message.control.replication.SyncDoneValueControl;
079 import org.apache.directory.shared.ldap.message.control.replication.SyncInfoValueControl;
080 import org.apache.directory.shared.ldap.message.control.replication.SyncRequestValueControl;
081 import org.apache.directory.shared.ldap.message.control.replication.SyncStateValueControl;
082 import org.apache.directory.shared.ldap.message.extended.NoticeOfDisconnect;
083 import org.apache.directory.shared.ldap.util.StringTools;
084 import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
085 import org.apache.mina.core.filterchain.IoFilterChainBuilder;
086 import org.apache.mina.core.future.WriteFuture;
087 import org.apache.mina.core.service.IoHandler;
088 import org.apache.mina.core.session.IoEventType;
089 import org.apache.mina.core.session.IoSession;
090 import org.apache.mina.filter.codec.ProtocolCodecFactory;
091 import org.apache.mina.filter.codec.ProtocolCodecFilter;
092 import org.apache.mina.filter.executor.ExecutorFilter;
093 import org.apache.mina.filter.executor.UnorderedThreadPoolExecutor;
094 import org.apache.mina.handler.demux.MessageHandler;
095 import org.apache.mina.transport.socket.SocketAcceptor;
096 import org.slf4j.Logger;
097 import org.slf4j.LoggerFactory;
098
099
100 /**
101 * An LDAP protocol provider implementation which dynamically associates
102 * handlers.
103 *
104 * @org.apache.xbean.XBean
105 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
106 * @version $Rev: 688548 $
107 */
108 public class LdapServer extends DirectoryBackedService
109 {
110 private static final long serialVersionUID = 3757127143811666817L;
111
112 /** logger for this class */
113 private static final Logger LOG = LoggerFactory.getLogger( LdapServer.class.getName() );
114
115 /** Value (0) for configuration where size limit is unlimited. */
116 public static final int NO_SIZE_LIMIT = 0;
117
118 /** Value (0) for configuration where time limit is unlimited. */
119 public static final int NO_TIME_LIMIT = 0;
120
121 /** the constant service name of this ldap protocol provider **/
122 public static final String SERVICE_NAME = "ldap";
123
124 /** The default maximum size limit. */
125 private static final int MAX_SIZE_LIMIT_DEFAULT = 100;
126
127 /** The default maximum time limit. */
128 private static final int MAX_TIME_LIMIT_DEFAULT = 10000;
129
130 /** The default service pid. */
131 private static final String SERVICE_PID_DEFAULT = "org.apache.directory.server.ldap";
132
133 /** The default service name. */
134 private static final String SERVICE_NAME_DEFAULT = "ApacheDS LDAP Service";
135
136 /** The default IP port. */
137 private static final int DEFAULT_IP_PORT = 389;
138
139 /** the session manager for this LdapServer */
140 private LdapSessionManager ldapSessionManager = new LdapSessionManager();
141
142 /** a set of supported controls */
143 private Set<String> supportedControls;
144
145 /**
146 * The maximum size limit.
147 * @see {@link LdapServer#MAX_SIZE_LIMIT_DEFAULT }
148 */
149 private int maxSizeLimit = MAX_SIZE_LIMIT_DEFAULT;
150
151 /**
152 * The maximum time limit.
153 * @see {@link LdapServer#MAX_TIME_LIMIT_DEFAULT }
154 */
155 private int maxTimeLimit = MAX_TIME_LIMIT_DEFAULT;
156
157 /** If LDAPS is activated : the external Keystore file, if defined */
158 private String keystoreFile;
159
160 /** If LDAPS is activated : the certificate password */
161 private String certificatePassword;
162
163 /** Whether to allow anonymous access: enabled by default. */
164 private boolean allowAnonymousAccess = true;
165
166 /** The extended operation handlers. */
167 private final Collection<ExtendedOperationHandler> extendedOperationHandlers =
168 new ArrayList<ExtendedOperationHandler>();
169
170 /** The supported authentication mechanisms. */
171 private Map<String, MechanismHandler> saslMechanismHandlers =
172 new HashMap<String, MechanismHandler>();
173
174 /** The name of this host, validated during SASL negotiation. */
175 private String saslHost = "ldap.example.com";
176
177 /** The service principal, used by GSSAPI. */
178 private String saslPrincipal = "ldap/ldap.example.com@EXAMPLE.COM";
179
180 /** The quality of protection (QoP), used by DIGEST-MD5 and GSSAPI. */
181 private Set<String> saslQop;
182 private String saslQopString;
183
184 /** The list of realms serviced by this host. */
185 private List<String> saslRealms;
186
187 /** The potocol handlers */
188 private LdapRequestHandler<InternalAbandonRequest> abandonHandler;
189 private LdapRequestHandler<InternalAddRequest> addHandler;
190 private LdapRequestHandler<InternalBindRequest> bindHandler;
191 private LdapRequestHandler<InternalCompareRequest> compareHandler;
192 private LdapRequestHandler<InternalDeleteRequest> deleteHandler;
193 private LdapRequestHandler<InternalExtendedRequest> extendedHandler;
194 private LdapRequestHandler<InternalModifyRequest> modifyHandler;
195 private LdapRequestHandler<InternalModifyDnRequest> modifyDnHandler;
196 private LdapRequestHandler<InternalSearchRequest> searchHandler;
197 private LdapRequestHandler<InternalUnbindRequest> unbindHandler;
198
199
200 /** the underlying provider codec factory */
201 private ProtocolCodecFactory codecFactory;
202
203 /** the MINA protocol handler */
204 private final LdapProtocolHandler handler = new LdapProtocolHandler(this);
205
206 /** tracks start state of the server */
207 private boolean started;
208
209 /**
210 * Whether or not confidentiality (TLS secured connection) is required:
211 * disabled by default.
212 */
213 private boolean confidentialityRequired;
214
215
216 private ReplicationSystem replicationSystem;
217
218 /**
219 * Creates an LDAP protocol provider.
220 */
221 public LdapServer()
222 {
223 super.setEnabled( true );
224 super.setServiceId( SERVICE_PID_DEFAULT );
225 super.setServiceName( SERVICE_NAME_DEFAULT );
226
227 saslQop = new HashSet<String>();
228 saslQop.add( SaslQoP.QOP_AUTH );
229 saslQop.add( SaslQoP.QOP_AUTH_INT );
230 saslQop.add( SaslQoP.QOP_AUTH_CONF );
231 saslQopString = SaslQoP.QOP_AUTH + ',' + SaslQoP.QOP_AUTH_INT + ',' + SaslQoP.QOP_AUTH_CONF;
232
233 saslRealms = new ArrayList<String>();
234 saslRealms.add( "example.com" );
235
236 this.supportedControls = new HashSet<String>();
237 this.supportedControls.add( PersistentSearchControl.CONTROL_OID );
238 this.supportedControls.add( EntryChangeControl.CONTROL_OID );
239 this.supportedControls.add( SubentriesControl.CONTROL_OID );
240 this.supportedControls.add( ManageDsaITControl.CONTROL_OID );
241 this.supportedControls.add( CascadeControl.CONTROL_OID );
242 this.supportedControls.add( PagedSearchControl.CONTROL_OID );
243 // Replication controls
244 this.supportedControls.add( SyncDoneValueControl.CONTROL_OID );
245 this.supportedControls.add( SyncInfoValueControl.CONTROL_OID );
246 this.supportedControls.add( SyncRequestValueControl.CONTROL_OID );
247 this.supportedControls.add( SyncStateValueControl.CONTROL_OID );
248 }
249
250
251 /**
252 * Install the LDAP request handlers.
253 */
254 private void installDefaultHandlers()
255 {
256 if ( getAbandonHandler() == null )
257 {
258 setAbandonHandler( new AbandonHandler() );
259 }
260
261 if ( getAddHandler() == null )
262 {
263 setAddHandler( new AddHandler() );
264 }
265
266 if ( getBindHandler() == null )
267 {
268 BindHandler handler = new BindHandler();
269 handler.setSaslMechanismHandlers( saslMechanismHandlers );
270 setBindHandler( handler );
271 }
272
273 if ( getCompareHandler() == null )
274 {
275 setCompareHandler( new CompareHandler() );
276 }
277
278 if ( getDeleteHandler() == null )
279 {
280 setDeleteHandler( new DeleteHandler() );
281 }
282
283 if ( getExtendedHandler() == null )
284 {
285 setExtendedHandler( new ExtendedHandler() );
286 }
287
288 if ( getModifyHandler() == null )
289 {
290 setModifyHandler( new ModifyHandler() );
291 }
292
293 if ( getModifyDnHandler() == null )
294 {
295 setModifyDnHandler( new ModifyDnHandler() );
296 }
297
298 if ( getSearchHandler() == null )
299 {
300 setSearchHandler( new SearchHandler() );
301 }
302
303 if ( getUnbindHandler() == null )
304 {
305 setUnbindHandler( new UnbindHandler() );
306 }
307 }
308
309
310 private class AdsKeyStore extends KeyStore
311 {
312 public AdsKeyStore( KeyStoreSpi keyStoreSpi, Provider provider, String type )
313 {
314 super( keyStoreSpi, provider, type );
315 }
316 }
317
318 /**
319 * @throws IOException if we cannot bind to the specified port
320 * @throws NamingException if the LDAP server cannot be started
321 */
322 public void start() throws Exception
323 {
324 if ( ! isEnabled() )
325 {
326 return;
327 }
328
329 for ( Transport transport:transports )
330 {
331 if ( !(transport instanceof TcpTransport ) )
332 {
333 LOG.warn( "Cannot listen on an UDP transport : {}", transport );
334 continue;
335 }
336
337 IoFilterChainBuilder chain;
338
339 if ( transport.isSSLEnabled() )
340 {
341 KeyStore keyStore = null;
342
343 if ( StringTools.isEmpty( keystoreFile ) )
344 {
345 Provider provider = Security.getProvider( "SUN" );
346 LOG.debug( "provider = {}", provider );
347 CoreKeyStoreSpi coreKeyStoreSpi = new CoreKeyStoreSpi( getDirectoryService() );
348 keyStore = new AdsKeyStore( coreKeyStoreSpi, provider, "JKS" );
349
350 try
351 {
352 keyStore.load( null, null );
353 }
354 catch ( Exception e )
355 {
356 // nothing really happens with this keystore
357 }
358 }
359 else
360 {
361 keyStore = AdsKeyStore.getInstance( KeyStore.getDefaultType() );
362 FileInputStream fis = new FileInputStream( keystoreFile );
363
364
365 keyStore.load( fis, null );
366 }
367
368 chain = LdapsInitializer.init( keyStore, certificatePassword );
369 }
370 else
371 {
372 chain = new DefaultIoFilterChainBuilder();
373 }
374
375 // Inject the codec into the chain
376 ((DefaultIoFilterChainBuilder)chain).addLast( "codec",
377 new ProtocolCodecFilter( this.getProtocolCodecFactory() ) );
378
379 // Now inject an ExecutorFilter for the write operations
380 // We use the same number of thread than the number of IoProcessor
381 // (NOTE : this has to be double checked)
382 ((DefaultIoFilterChainBuilder)chain).addLast( "executor",
383 new ExecutorFilter(
384 new UnorderedThreadPoolExecutor( transport.getNbThreads() ),
385 IoEventType.MESSAGE_RECEIVED ) );
386
387 /*
388 * The server is now initialized, we can
389 * install the default requests handlers, which need
390 * access to the DirectoryServer instance.
391 */
392 installDefaultHandlers();
393
394 startNetwork( transport, chain );
395 }
396
397 started = true;
398
399 LOG.info( "Ldap service started." );
400 }
401
402
403 /**
404 * {@inheritDoc}
405 */
406 public void stop()
407 {
408 try
409 {
410 for ( Transport transport:transports )
411 {
412 if ( !(transport instanceof TcpTransport ) )
413 {
414 continue;
415 }
416
417 // we should unbind the service before we begin sending the notice
418 // of disconnect so new connections are not formed while we process
419 List<WriteFuture> writeFutures = new ArrayList<WriteFuture>();
420
421 // If the socket has already been unbound as with a successful
422 // GracefulShutdownRequest then this will complain that the service
423 // is not bound - this is ok because the GracefulShutdown has already
424 // sent notices to to the existing active sessions
425 List<IoSession> sessions;
426
427 try
428 {
429 sessions = new ArrayList<IoSession>(
430 getSocketAcceptor( transport ).getManagedSessions().values() );
431 }
432 catch ( IllegalArgumentException e )
433 {
434 LOG.warn( "Seems like the LDAP service (" + getPort() + ") has already been unbound." );
435 return;
436 }
437
438 getSocketAcceptor( transport ).dispose();
439
440 if ( LOG.isInfoEnabled() )
441 {
442 LOG.info( "Unbind of an LDAP service (" + getPort() + ") is complete." );
443 LOG.info( "Sending notice of disconnect to existing clients sessions." );
444 }
445
446 // Send Notification of Disconnection messages to all connected clients.
447 if ( sessions != null )
448 {
449 for ( IoSession session:sessions )
450 {
451 writeFutures.add( session.write( NoticeOfDisconnect.UNAVAILABLE ) );
452 }
453 }
454
455 // And close the connections when the NoDs are sent.
456 Iterator<IoSession> sessionIt = sessions.iterator();
457
458 for ( WriteFuture future:writeFutures )
459 {
460 future.await( 1000L );
461 sessionIt.next().close( true );
462 }
463 }
464 }
465 catch ( Exception e )
466 {
467 LOG.warn( "Failed to sent NoD.", e );
468 }
469
470 LOG.info( "Ldap service stopped." );
471 }
472
473
474 private void startNetwork( Transport transport, IoFilterChainBuilder chainBuilder )
475 throws Exception
476 {
477 if ( transport.getBackLog() < 0 )
478 {
479 // Set the backlog to the default value when it's below 0
480 transport.setBackLog( 50 );
481 }
482
483 PartitionNexus nexus = getDirectoryService().getPartitionNexus();
484
485 for ( ExtendedOperationHandler h : extendedOperationHandlers )
486 {
487 LOG.info( "Added Extended Request Handler: " + h.getOid() );
488 h.setLdapServer( this );
489 nexus.registerSupportedExtensions( h.getExtensionOids() );
490 }
491
492 nexus.registerSupportedSaslMechanisms( saslMechanismHandlers.keySet() );
493
494 try
495 {
496 SocketAcceptor acceptor = getSocketAcceptor( transport );
497
498 // Now, configure the acceptor
499 // Disable the disconnection of the clients on unbind
500 acceptor.setCloseOnDeactivation( false );
501
502 // Allow the port to be reused even if the socket is in TIME_WAIT state
503 acceptor.setReuseAddress( true );
504
505 // No Nagle's algorithm
506 acceptor.getSessionConfig().setTcpNoDelay( true );
507
508 // Inject the chain
509 acceptor.setFilterChainBuilder( chainBuilder );
510
511 // Inject the protocol handler
512 acceptor.setHandler( getHandler() );
513
514 // Bind to the configured address
515 acceptor.bind();
516
517 // We are done !
518 started = true;
519
520 if ( LOG.isInfoEnabled() )
521 {
522 LOG.info( "Successful bind of an LDAP Service (" + transport.getPort() + ") is completed." );
523 }
524 }
525 catch ( IOException e )
526 {
527 String msg = "Failed to bind an LDAP service (" + transport.getPort() + ") to the service registry.";
528 LdapConfigurationException lce = new LdapConfigurationException( msg );
529 lce.setRootCause( e );
530 LOG.error( msg, e );
531 throw lce;
532 }
533 }
534
535
536 public String getName()
537 {
538 return SERVICE_NAME;
539 }
540
541
542 public IoHandler getHandler()
543 {
544 return handler;
545 }
546
547
548 public LdapSessionManager getLdapSessionManager()
549 {
550 return ldapSessionManager;
551 }
552
553
554 public ProtocolCodecFactory getProtocolCodecFactory()
555 {
556 return codecFactory;
557 }
558
559
560 // ------------------------------------------------------------------------
561 // Configuration Methods
562 // ------------------------------------------------------------------------
563
564
565 /**
566 * Registeres the specified {@link ExtendedOperationHandler} to this
567 * protocol provider to provide a specific LDAP extended operation.
568 *
569 * @param eoh an extended operation handler
570 * @throws NamingException on failure to add the handler
571 */
572 public void addExtendedOperationHandler( ExtendedOperationHandler eoh ) throws Exception
573 {
574 if ( started )
575 {
576 eoh.setLdapServer( this );
577 PartitionNexus nexus = getDirectoryService().getPartitionNexus();
578 nexus.registerSupportedExtensions( eoh.getExtensionOids() );
579 }
580 else
581 {
582 extendedOperationHandlers.add( eoh );
583 }
584 }
585
586
587 /**
588 * Deregisteres an {@link ExtendedOperationHandler} with the specified <tt>oid</tt>
589 * from this protocol provider.
590 *
591 * @param oid the numeric identifier for the extended operation associated with
592 * the handler to remove
593 */
594 public void removeExtendedOperationHandler( String oid )
595 {
596 // need to do something like this to make this work right
597 // PartitionNexus nexus = getDirectoryService().getPartitionNexus();
598 // nexus.unregisterSupportedExtensions( eoh.getExtensionOids() );
599
600 ExtendedOperationHandler handler = null;
601 for ( ExtendedOperationHandler h : extendedOperationHandlers )
602 {
603 if ( h.getOid().equals( oid ) )
604 {
605 handler = h;
606 break;
607 }
608 }
609 extendedOperationHandlers.remove( handler );
610 }
611
612
613 /**
614 * Returns an {@link ExtendedOperationHandler} with the specified <tt>oid</tt>
615 * which is registered to this protocol provider.
616 *
617 * @param oid the oid of the extended request of associated with the extended
618 * request handler
619 * @return the exnteded operation handler
620 */
621 public ExtendedOperationHandler getExtendedOperationHandler( String oid )
622 {
623 for ( ExtendedOperationHandler h : extendedOperationHandlers )
624 {
625 if ( h.getOid().equals( oid ) )
626 {
627 return h;
628 }
629 }
630
631 return null;
632 }
633
634
635 /**
636 * Sets the mode for this LdapServer to accept requests with or without a
637 * TLS secured connection via either StartTLS extended operations or using
638 * LDAPS.
639 *
640 * @param confidentialityRequired true to require confidentiality
641 */
642 public void setConfidentialityRequired( boolean confidentialityRequired )
643 {
644 this.confidentialityRequired = confidentialityRequired;
645 }
646
647
648 /**
649 * Gets whether or not TLS secured connections are required to perform
650 * operations on this LdapServer.
651 *
652 * @return true if TLS secured connections are required, false otherwise
653 */
654 public boolean isConfidentialityRequired()
655 {
656 return confidentialityRequired;
657 }
658
659
660 /**
661 * Returns <tt>true</tt> if LDAPS is enabled.
662 *
663 * @return True if LDAPS is enabled.
664 */
665 public boolean isEnableLdaps( Transport transport )
666 {
667 return transport.isSSLEnabled();
668 }
669
670
671 /**
672 * Returns <code>true</code> if anonymous access is allowed.
673 *
674 * @return True if anonymous access is allowed.
675 */
676 public boolean isAllowAnonymousAccess()
677 {
678 return allowAnonymousAccess;
679 }
680
681
682 /**
683 * Sets whether to allow anonymous access or not.
684 *
685 * @param enableAnonymousAccess Set <code>true</code> to allow anonymous access.
686 */
687 public void setAllowAnonymousAccess( boolean enableAnonymousAccess )
688 {
689 this.allowAnonymousAccess = enableAnonymousAccess;
690 }
691
692
693 /**
694 * Sets the maximum size limit in number of entries to return for search.
695 *
696 * @param maxSizeLimit the maximum number of entries to return for search
697 */
698 public void setMaxSizeLimit( int maxSizeLimit )
699 {
700 this.maxSizeLimit = maxSizeLimit;
701 }
702
703
704 /**
705 * Returns the maximum size limit in number of entries to return for search.
706 *
707 * @return The maximum size limit.
708 */
709 public int getMaxSizeLimit()
710 {
711 return maxSizeLimit;
712 }
713
714
715 /**
716 * Sets the maximum time limit in milliseconds to conduct a search.
717 *
718 * @param maxTimeLimit the maximum length of time in milliseconds for search
719 */
720 public void setMaxTimeLimit( int maxTimeLimit )
721 {
722 this.maxTimeLimit = maxTimeLimit;
723 }
724
725
726 /**
727 * Returns the maximum time limit in milliseconds to conduct a search.
728 *
729 * @return The maximum time limit in milliseconds for search
730 */
731 public int getMaxTimeLimit()
732 {
733 return maxTimeLimit;
734 }
735
736
737 /**
738 * Gets the {@link ExtendedOperationHandler}s.
739 *
740 * @return A collection of {@link ExtendedOperationHandler}s.
741 */
742 public Collection<ExtendedOperationHandler> getExtendedOperationHandlers()
743 {
744 return new ArrayList<ExtendedOperationHandler>( extendedOperationHandlers );
745 }
746
747
748 /**
749 * Sets the {@link ExtendedOperationHandler}s.
750 *
751 * @org.apache.xbean.Property nestedType="org.apache.directory.server.ldap.ExtendedOperationHandler"
752 *
753 * @param handlers A collection of {@link ExtendedOperationHandler}s.
754 */
755 public void setExtendedOperationHandlers( Collection<ExtendedOperationHandler> handlers )
756 {
757 this.extendedOperationHandlers.clear();
758 this.extendedOperationHandlers.addAll( handlers );
759 }
760
761
762 /**
763 * Returns the FQDN of this SASL host, validated during SASL negotiation.
764 *
765 * @return The FQDN of this SASL host, validated during SASL negotiation.
766 */
767 public String getSaslHost()
768 {
769 return saslHost;
770 }
771
772
773 /**
774 * Sets the FQDN of this SASL host, validated during SASL negotiation.
775 *
776 * @param saslHost The FQDN of this SASL host, validated during SASL negotiation.
777 */
778 public void setSaslHost( String saslHost )
779 {
780 this.saslHost = saslHost;
781 }
782
783
784 /**
785 * Returns the Kerberos principal name for this LDAP service, used by GSSAPI.
786 *
787 * @return The Kerberos principal name for this LDAP service, used by GSSAPI.
788 */
789 public String getSaslPrincipal()
790 {
791 return saslPrincipal;
792 }
793
794
795 /**
796 * Sets the Kerberos principal name for this LDAP service, used by GSSAPI.
797 *
798 * @param saslPrincipal The Kerberos principal name for this LDAP service, used by GSSAPI.
799 */
800 public void setSaslPrincipal( String saslPrincipal )
801 {
802 this.saslPrincipal = saslPrincipal;
803 }
804
805
806 /**
807 * Returns the quality-of-protection, used by DIGEST-MD5 and GSSAPI.
808 *
809 * @return The quality-of-protection, used by DIGEST-MD5 and GSSAPI.
810 */
811 public String getSaslQopString()
812 {
813 return saslQopString;
814 }
815
816
817 /**
818 * Returns the Set of quality-of-protection, used by DIGEST-MD5 and GSSAPI.
819 *
820 * @return The quality-of-protection, used by DIGEST-MD5 and GSSAPI.
821 */
822 public Set<String> getSaslQop()
823 {
824 return saslQop;
825 }
826
827
828 /**
829 * Returns the realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI.
830 *
831 * @return The realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI.
832 */
833 public List<String> getSaslRealms()
834 {
835 return saslRealms;
836 }
837
838
839 /**
840 * Sets the realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI.
841 *
842 * @org.apache.xbean.Property nestedType="java.lang.String"
843 *
844 * @param saslRealms The realms serviced by this SASL host, used by DIGEST-MD5 and GSSAPI.
845 */
846 public void setSaslRealms( List<String> saslRealms )
847 {
848 this.saslRealms = saslRealms;
849 }
850
851
852 /**
853 * @org.apache.xbean.Map flat="true" dups="replace" keyName="mech-name"
854 */
855 public Map<String, MechanismHandler> getSaslMechanismHandlers()
856 {
857 return saslMechanismHandlers;
858 }
859
860 public void setSaslMechanismHandlers( Map<String, MechanismHandler> saslMechanismHandlers )
861 {
862 this.saslMechanismHandlers = saslMechanismHandlers;
863 }
864
865
866 public MechanismHandler addSaslMechanismHandler( String mechanism, MechanismHandler handler )
867 {
868 return this.saslMechanismHandlers.put( mechanism, handler );
869 }
870
871
872 public MechanismHandler removeSaslMechanismHandler( String mechanism )
873 {
874 return this.saslMechanismHandlers.remove( mechanism );
875 }
876
877
878 public MechanismHandler getMechanismHandler( String mechanism )
879 {
880 return this.saslMechanismHandlers.get( mechanism );
881 }
882
883
884 public Set<String> getSupportedMechanisms()
885 {
886 return saslMechanismHandlers.keySet();
887 }
888
889
890 public void setDirectoryService( DirectoryService directoryService )
891 {
892 super.setDirectoryService( directoryService );
893 this.codecFactory = new LdapProtocolCodecFactory( directoryService );
894 }
895
896
897 public Set<String> getSupportedControls()
898 {
899 return supportedControls;
900 }
901
902
903 /**
904 * @org.apache.xbean.Property hidden="true"
905 */
906 public void setSupportedControls( Set<String> supportedControls )
907 {
908 this.supportedControls = supportedControls;
909 }
910
911
912 public MessageHandler<InternalAbandonRequest> getAbandonHandler()
913 {
914 return abandonHandler;
915 }
916
917
918 /**
919 * @org.apache.xbean.Property hidden="true"
920 * @param abandonHandler The AbandonRequest handler
921 */
922 public void setAbandonHandler( LdapRequestHandler<InternalAbandonRequest> abandonHandler )
923 {
924 this.handler.removeReceivedMessageHandler( InternalAbandonRequest.class );
925 this.abandonHandler = abandonHandler;
926 this.abandonHandler.setLdapServer( this );
927 this.handler.addReceivedMessageHandler( InternalAbandonRequest.class, this.abandonHandler );
928 }
929
930
931 public LdapRequestHandler<InternalAddRequest> getAddHandler()
932 {
933 return addHandler;
934 }
935
936
937 /**
938 * @org.apache.xbean.Property hidden="true"
939 * @param abandonHandler The AddRequest handler
940 */
941 public void setAddHandler( LdapRequestHandler<InternalAddRequest> addHandler )
942 {
943 this.handler.removeReceivedMessageHandler( InternalAddRequest.class );
944 this.addHandler = addHandler;
945 this.addHandler.setLdapServer( this );
946 this.handler.addReceivedMessageHandler( InternalAddRequest.class, this.addHandler );
947 }
948
949
950 public LdapRequestHandler<InternalBindRequest> getBindHandler()
951 {
952 return bindHandler;
953 }
954
955
956 /**
957 * @org.apache.xbean.Property hidden="true"
958 * @param abandonHandler The BindRequest handler
959 */
960 public void setBindHandler( LdapRequestHandler<InternalBindRequest> bindHandler )
961 {
962 this.bindHandler = bindHandler;
963 this.bindHandler.setLdapServer( this );
964
965 handler.removeReceivedMessageHandler( InternalBindRequest.class );
966 handler.addReceivedMessageHandler( InternalBindRequest.class, this.bindHandler );
967 }
968
969
970 public LdapRequestHandler<InternalCompareRequest> getCompareHandler()
971 {
972 return compareHandler;
973 }
974
975
976 /**
977 * @org.apache.xbean.Property hidden="true"
978 * @param abandonHandler The CompareRequest handler
979 */
980 public void setCompareHandler( LdapRequestHandler<InternalCompareRequest> compareHandler )
981 {
982 this.handler.removeReceivedMessageHandler( InternalCompareRequest.class );
983 this.compareHandler = compareHandler;
984 this.compareHandler.setLdapServer( this );
985 this.handler.addReceivedMessageHandler( InternalCompareRequest.class, this.compareHandler );
986 }
987
988
989 public LdapRequestHandler<InternalDeleteRequest> getDeleteHandler()
990 {
991 return deleteHandler;
992 }
993
994
995 /**
996 * @org.apache.xbean.Property hidden="true"
997 * @param abandonHandler The DeleteRequest handler
998 */
999 public void setDeleteHandler( LdapRequestHandler<InternalDeleteRequest> deleteHandler )
1000 {
1001 this.handler.removeReceivedMessageHandler( InternalDeleteRequest.class );
1002 this.deleteHandler = deleteHandler;
1003 this.deleteHandler.setLdapServer( this );
1004 this.handler.addReceivedMessageHandler( InternalDeleteRequest.class, this.deleteHandler );
1005 }
1006
1007
1008 public LdapRequestHandler<InternalExtendedRequest> getExtendedHandler()
1009 {
1010 return extendedHandler;
1011 }
1012
1013
1014 /**
1015 * @org.apache.xbean.Property hidden="true"
1016 * @param abandonHandler The ExtendedRequest handler
1017 */
1018 public void setExtendedHandler( LdapRequestHandler<InternalExtendedRequest> extendedHandler )
1019 {
1020 this.handler.removeReceivedMessageHandler( InternalExtendedRequest.class );
1021 this.extendedHandler = extendedHandler;
1022 this.extendedHandler.setLdapServer( this );
1023 this.handler.addReceivedMessageHandler( InternalExtendedRequest.class, this.extendedHandler );
1024 }
1025
1026
1027 public LdapRequestHandler<InternalModifyRequest> getModifyHandler()
1028 {
1029 return modifyHandler;
1030 }
1031
1032
1033 /**
1034 * @org.apache.xbean.Property hidden="true"
1035 * @param abandonHandler The ModifyRequest handler
1036 */
1037 public void setModifyHandler( LdapRequestHandler<InternalModifyRequest> modifyHandler )
1038 {
1039 this.handler.removeReceivedMessageHandler( InternalModifyRequest.class );
1040 this.modifyHandler = modifyHandler;
1041 this.modifyHandler.setLdapServer( this );
1042 this.handler.addReceivedMessageHandler( InternalModifyRequest.class, this.modifyHandler );
1043 }
1044
1045
1046 public LdapRequestHandler<InternalModifyDnRequest> getModifyDnHandler()
1047 {
1048 return modifyDnHandler;
1049 }
1050
1051
1052 /**
1053 * @org.apache.xbean.Property hidden="true"
1054 * @param abandonHandler The ModifyDNRequest handler
1055 */
1056 public void setModifyDnHandler( LdapRequestHandler<InternalModifyDnRequest> modifyDnHandler )
1057 {
1058 this.handler.removeReceivedMessageHandler( InternalModifyDnRequest.class );
1059 this.modifyDnHandler = modifyDnHandler;
1060 this.modifyDnHandler.setLdapServer( this );
1061 this.handler.addReceivedMessageHandler( InternalModifyDnRequest.class, this.modifyDnHandler );
1062 }
1063
1064
1065 public LdapRequestHandler<InternalSearchRequest> getSearchHandler()
1066 {
1067 return searchHandler;
1068 }
1069
1070
1071 /**
1072 * @org.apache.xbean.Property hidden="true"
1073 * @param abandonHandler The SearchRequest handler
1074 */
1075 public void setSearchHandler( LdapRequestHandler<InternalSearchRequest> searchHandler )
1076 {
1077 this.handler.removeReceivedMessageHandler( InternalSearchRequest.class );
1078 this.searchHandler = searchHandler;
1079 this.searchHandler.setLdapServer( this );
1080 this.handler.addReceivedMessageHandler( InternalSearchRequest.class, this.searchHandler );
1081 }
1082
1083
1084 public LdapRequestHandler<InternalUnbindRequest> getUnbindHandler()
1085 {
1086 return unbindHandler;
1087 }
1088
1089
1090 /**
1091 * @return The underlying TCP transport port, or -1 if no transport has been
1092 * initialized
1093 */
1094 public int getPort()
1095 {
1096 if ( transports == null )
1097 {
1098 return -1;
1099 }
1100
1101 for ( Transport transport:transports )
1102 {
1103 if ( transport instanceof UdpTransport )
1104 {
1105 continue;
1106 }
1107
1108 if ( !transport.isSSLEnabled() )
1109 {
1110 return transport.getPort();
1111 }
1112 }
1113
1114 return -1;
1115 }
1116
1117
1118 /**
1119 * @return The underlying SSL enabled TCP transport port, or -1 if no transport has been
1120 * initialized
1121 */
1122 public int getPortSSL()
1123 {
1124 if ( transports == null )
1125 {
1126 return -1;
1127 }
1128
1129 for ( Transport transport:transports )
1130 {
1131 if ( transport instanceof UdpTransport )
1132 {
1133 continue;
1134 }
1135
1136 if ( transport.isSSLEnabled() )
1137 {
1138 return transport.getPort();
1139 }
1140 }
1141
1142 return -1;
1143 }
1144
1145 /**
1146 * @org.apache.xbean.Property hidden="true"
1147 * @param abandonHandler The UnbindRequest handler
1148 */
1149 public void setUnbindHandler( LdapRequestHandler<InternalUnbindRequest> unbindHandler )
1150 {
1151 this.handler.removeReceivedMessageHandler( InternalUnbindRequest.class );
1152 this.unbindHandler = unbindHandler;
1153 this.unbindHandler.setLdapServer( this );
1154 this.handler.addReceivedMessageHandler( InternalUnbindRequest.class, this.unbindHandler );
1155 }
1156
1157
1158 public boolean isStarted()
1159 {
1160 return started;
1161 }
1162
1163
1164 /**
1165 * @org.apache.xbean.Property hidden="true"
1166 */
1167 public void setStarted( boolean started )
1168 {
1169 this.started = started;
1170 }
1171
1172
1173 /**
1174 * @return The keystore path
1175 */
1176 public String getKeystoreFile()
1177 {
1178 return keystoreFile;
1179 }
1180
1181
1182 /**
1183 * Set the external keystore path
1184 * @param keystoreFile The external keystore path
1185 */
1186 public void setKeystoreFile( String keystoreFile )
1187 {
1188 this.keystoreFile = keystoreFile;
1189 }
1190
1191
1192 /**
1193 * @return The certificate passord
1194 */
1195 public String getCertificatePassword()
1196 {
1197 return certificatePassword;
1198 }
1199
1200
1201 /**
1202 * Set the certificate passord.
1203 * @param certificatePassword the certificate passord
1204 */
1205 public void setCertificatePassword( String certificatePassword )
1206 {
1207 this.certificatePassword = certificatePassword;
1208 }
1209
1210
1211 /**
1212 * @param replicationSystem the replicationSystem to set
1213 */
1214 public void setReplicationSystem( ReplicationSystem replicationSystem )
1215 {
1216 this.replicationSystem = replicationSystem;
1217 }
1218
1219
1220 /**
1221 * @return the replicationSystem
1222 */
1223 public ReplicationSystem getReplicationSystem()
1224 {
1225 return replicationSystem;
1226 }
1227
1228
1229 /**
1230 * @see Object#toString()
1231 */
1232 public String toString()
1233 {
1234 StringBuilder sb = new StringBuilder();
1235
1236 sb.append( "LdapServer[" ).append( getServiceName() ).append( "], listening on :" ).append( '\n' );
1237
1238 if ( getTransports() != null )
1239 {
1240 for ( Transport transport:getTransports() )
1241 {
1242 sb.append( " " ).append( transport ).append( '\n' );
1243 }
1244 }
1245
1246 return sb.toString();
1247 }
1248 }