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