1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.ldap.client.api;
21
22
23 import static org.apache.directory.api.ldap.model.message.ResultCodeEnum.processResponse;
24
25 import java.io.File;
26 import java.io.IOException;
27 import java.io.OutputStreamWriter;
28 import java.io.Writer;
29 import java.net.ConnectException;
30 import java.net.InetSocketAddress;
31 import java.net.SocketAddress;
32 import java.nio.channels.UnresolvedAddressException;
33 import java.nio.charset.Charset;
34 import java.nio.file.Files;
35 import java.nio.file.Paths;
36 import java.security.PrivilegedExceptionAction;
37 import java.util.ArrayList;
38 import java.util.HashMap;
39 import java.util.Iterator;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.concurrent.CompletableFuture;
43 import java.util.concurrent.ConcurrentHashMap;
44 import java.util.concurrent.ExecutionException;
45 import java.util.concurrent.TimeUnit;
46 import java.util.concurrent.TimeoutException;
47 import java.util.concurrent.atomic.AtomicBoolean;
48 import java.util.concurrent.locks.ReentrantLock;
49
50 import javax.net.ssl.SSLContext;
51 import javax.net.ssl.SSLSession;
52 import javax.net.ssl.TrustManager;
53 import javax.security.auth.Subject;
54 import javax.security.auth.login.Configuration;
55 import javax.security.auth.login.LoginContext;
56 import javax.security.sasl.Sasl;
57 import javax.security.sasl.SaslClient;
58
59 import org.apache.directory.api.asn1.DecoderException;
60 import org.apache.directory.api.asn1.util.Oid;
61 import org.apache.directory.api.i18n.I18n;
62 import org.apache.directory.api.ldap.codec.api.BinaryAttributeDetector;
63 import org.apache.directory.api.ldap.codec.api.DefaultConfigurableBinaryAttributeDetector;
64 import org.apache.directory.api.ldap.codec.api.ExtendedOperationFactory;
65 import org.apache.directory.api.ldap.codec.api.LdapApiService;
66 import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
67 import org.apache.directory.api.ldap.codec.api.LdapDecoder;
68 import org.apache.directory.api.ldap.codec.api.LdapMessageContainer;
69 import org.apache.directory.api.ldap.codec.api.MessageEncoderException;
70 import org.apache.directory.api.ldap.codec.api.SaslFilter;
71 import org.apache.directory.api.ldap.codec.api.SchemaBinaryAttributeDetector;
72 import org.apache.directory.api.ldap.extras.controls.ad.TreeDelete;
73 import org.apache.directory.api.ldap.extras.controls.ad.TreeDeleteImpl;
74 import org.apache.directory.api.ldap.extras.extended.startTls.StartTlsRequestImpl;
75 import org.apache.directory.api.ldap.model.constants.LdapConstants;
76 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
77 import org.apache.directory.api.ldap.model.cursor.Cursor;
78 import org.apache.directory.api.ldap.model.cursor.CursorException;
79 import org.apache.directory.api.ldap.model.cursor.EntryCursor;
80 import org.apache.directory.api.ldap.model.cursor.SearchCursor;
81 import org.apache.directory.api.ldap.model.entry.Attribute;
82 import org.apache.directory.api.ldap.model.entry.DefaultEntry;
83 import org.apache.directory.api.ldap.model.entry.Entry;
84 import org.apache.directory.api.ldap.model.entry.Modification;
85 import org.apache.directory.api.ldap.model.entry.ModificationOperation;
86 import org.apache.directory.api.ldap.model.entry.Value;
87 import org.apache.directory.api.ldap.model.exception.LdapAuthenticationException;
88 import org.apache.directory.api.ldap.model.exception.LdapException;
89 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
90 import org.apache.directory.api.ldap.model.exception.LdapNoPermissionException;
91 import org.apache.directory.api.ldap.model.exception.LdapNoSuchObjectException;
92 import org.apache.directory.api.ldap.model.exception.LdapOperationException;
93 import org.apache.directory.api.ldap.model.exception.LdapOtherException;
94 import org.apache.directory.api.ldap.model.exception.LdapTlsHandshakeException;
95 import org.apache.directory.api.ldap.model.message.AbandonRequest;
96 import org.apache.directory.api.ldap.model.message.AbandonRequestImpl;
97 import org.apache.directory.api.ldap.model.message.AddRequest;
98 import org.apache.directory.api.ldap.model.message.AddRequestImpl;
99 import org.apache.directory.api.ldap.model.message.AddResponse;
100 import org.apache.directory.api.ldap.model.message.AliasDerefMode;
101 import org.apache.directory.api.ldap.model.message.BindRequest;
102 import org.apache.directory.api.ldap.model.message.BindRequestImpl;
103 import org.apache.directory.api.ldap.model.message.BindResponse;
104 import org.apache.directory.api.ldap.model.message.CompareRequest;
105 import org.apache.directory.api.ldap.model.message.CompareRequestImpl;
106 import org.apache.directory.api.ldap.model.message.CompareResponse;
107 import org.apache.directory.api.ldap.model.message.Control;
108 import org.apache.directory.api.ldap.model.message.DeleteRequest;
109 import org.apache.directory.api.ldap.model.message.DeleteRequestImpl;
110 import org.apache.directory.api.ldap.model.message.DeleteResponse;
111 import org.apache.directory.api.ldap.model.message.ExtendedRequest;
112 import org.apache.directory.api.ldap.model.message.ExtendedResponse;
113 import org.apache.directory.api.ldap.model.message.IntermediateResponse;
114 import org.apache.directory.api.ldap.model.message.LdapResult;
115 import org.apache.directory.api.ldap.model.message.Message;
116 import org.apache.directory.api.ldap.model.message.ModifyDnRequest;
117 import org.apache.directory.api.ldap.model.message.ModifyDnRequestImpl;
118 import org.apache.directory.api.ldap.model.message.ModifyDnResponse;
119 import org.apache.directory.api.ldap.model.message.ModifyRequest;
120 import org.apache.directory.api.ldap.model.message.ModifyRequestImpl;
121 import org.apache.directory.api.ldap.model.message.ModifyResponse;
122 import org.apache.directory.api.ldap.model.message.OpaqueExtendedRequest;
123 import org.apache.directory.api.ldap.model.message.OpaqueExtendedResponse;
124 import org.apache.directory.api.ldap.model.message.Request;
125 import org.apache.directory.api.ldap.model.message.Response;
126 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
127 import org.apache.directory.api.ldap.model.message.SearchRequest;
128 import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
129 import org.apache.directory.api.ldap.model.message.SearchResultDone;
130 import org.apache.directory.api.ldap.model.message.SearchResultEntry;
131 import org.apache.directory.api.ldap.model.message.SearchResultReference;
132 import org.apache.directory.api.ldap.model.message.SearchScope;
133 import org.apache.directory.api.ldap.model.message.UnbindRequest;
134 import org.apache.directory.api.ldap.model.message.UnbindRequestImpl;
135 import org.apache.directory.api.ldap.model.message.controls.ManageDsaITImpl;
136 import org.apache.directory.api.ldap.model.message.controls.OpaqueControl;
137 import org.apache.directory.api.ldap.model.message.extended.AddNoDResponse;
138 import org.apache.directory.api.ldap.model.message.extended.BindNoDResponse;
139 import org.apache.directory.api.ldap.model.message.extended.CompareNoDResponse;
140 import org.apache.directory.api.ldap.model.message.extended.DeleteNoDResponse;
141 import org.apache.directory.api.ldap.model.message.extended.ExtendedNoDResponse;
142 import org.apache.directory.api.ldap.model.message.extended.ModifyDnNoDResponse;
143 import org.apache.directory.api.ldap.model.message.extended.ModifyNoDResponse;
144 import org.apache.directory.api.ldap.model.message.extended.NoticeOfDisconnect;
145 import org.apache.directory.api.ldap.model.message.extended.SearchNoDResponse;
146 import org.apache.directory.api.ldap.model.name.DefaultDnFactory;
147 import org.apache.directory.api.ldap.model.name.Dn;
148 import org.apache.directory.api.ldap.model.name.Rdn;
149 import org.apache.directory.api.ldap.model.schema.AttributeType;
150 import org.apache.directory.api.ldap.model.schema.ObjectClass;
151 import org.apache.directory.api.ldap.model.schema.SchemaManager;
152 import org.apache.directory.api.ldap.model.schema.parsers.OpenLdapSchemaParser;
153 import org.apache.directory.api.ldap.model.schema.registries.Registries;
154 import org.apache.directory.api.ldap.model.schema.registries.SchemaLoader;
155 import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
156 import org.apache.directory.api.util.Network;
157 import org.apache.directory.api.util.StringConstants;
158 import org.apache.directory.api.util.Strings;
159 import org.apache.directory.ldap.client.api.callback.SaslCallbackHandler;
160 import org.apache.directory.ldap.client.api.exception.InvalidConnectionException;
161 import org.apache.directory.ldap.client.api.exception.LdapConnectionTimeOutException;
162 import org.apache.directory.ldap.client.api.future.AddFuture;
163 import org.apache.directory.ldap.client.api.future.BindFuture;
164 import org.apache.directory.ldap.client.api.future.CompareFuture;
165 import org.apache.directory.ldap.client.api.future.DeleteFuture;
166 import org.apache.directory.ldap.client.api.future.ExtendedFuture;
167 import org.apache.directory.ldap.client.api.future.HandshakeFuture;
168 import org.apache.directory.ldap.client.api.future.ModifyDnFuture;
169 import org.apache.directory.ldap.client.api.future.ModifyFuture;
170 import org.apache.directory.ldap.client.api.future.ResponseFuture;
171 import org.apache.directory.ldap.client.api.future.SearchFuture;
172 import org.apache.mina.core.filterchain.IoFilter;
173 import org.apache.mina.core.filterchain.IoFilterChain;
174 import org.apache.mina.core.future.CloseFuture;
175 import org.apache.mina.core.future.ConnectFuture;
176 import org.apache.mina.core.future.WriteFuture;
177 import org.apache.mina.core.service.IoConnector;
178 import org.apache.mina.core.session.IoSession;
179 import org.apache.mina.filter.FilterEvent;
180 import org.apache.mina.filter.codec.ProtocolCodecFilter;
181 import org.apache.mina.filter.codec.ProtocolEncoderException;
182 import org.apache.mina.filter.ssl.SslEvent;
183 import org.apache.mina.filter.ssl.SslFilter;
184 import org.apache.mina.transport.socket.SocketSessionConfig;
185 import org.apache.mina.transport.socket.nio.NioSocketConnector;
186 import org.slf4j.Logger;
187 import org.slf4j.LoggerFactory;
188
189
190
191
192
193
194
195
196
197
198
199
200 public class LdapNetworkConnection extends AbstractLdapConnection implements LdapAsyncConnection
201 {
202
203
204 private static final Logger LOG = LoggerFactory.getLogger( LdapNetworkConnection.class );
205
206
207 private long timeout = LdapConnectionConfig.DEFAULT_TIMEOUT;
208
209
210 private long connectTimeout = LdapConnectionConfig.DEFAULT_TIMEOUT;
211
212
213 private long writeOperationTimeout = LdapConnectionConfig.DEFAULT_TIMEOUT;
214
215
216 private long readOperationTimeout = LdapConnectionConfig.DEFAULT_TIMEOUT;
217
218
219 private long closeTimeout = LdapConnectionConfig.DEFAULT_TIMEOUT;
220
221
222 private long sendTimeout = LdapConnectionConfig.DEFAULT_TIMEOUT;
223
224
225 private LdapConnectionConfig config;
226
227
228 private SocketSessionConfig socketSessionConfig;
229
230
231 private IoConnector connector;
232
233
234 private ReentrantLock connectorMutex = new ReentrantLock();
235
236
237
238
239
240 private IoSession ioSession;
241
242
243 private Map<Integer, ResponseFuture<? extends Response>> futureMap = new ConcurrentHashMap<>();
244
245
246 private List<String> supportedControls;
247
248
249 private Entry rootDse;
250
251
252 private AtomicBoolean authenticated = new AtomicBoolean( false );
253
254
255
256
257 private List<ConnectionClosedEventListener> conCloseListeners;
258
259
260 private IoFilter ldapProtocolFilter = new ProtocolCodecFilter( codec.getProtocolCodecFactory() );
261
262
263 private static final String LDAP_CODEC_FILTER_KEY = "ldapCodec";
264
265
266 private static final String SSL_FILTER_KEY = "sslFilter";
267
268
269 private static final String SASL_FILTER_KEY = "saslFilter";
270
271
272 private static final String EXCEPTION_KEY = "sessionException";
273
274
275 private static final String KRB5_CONF = "java.security.krb5.conf";
276
277
278 private HandshakeFuture handshakeFuture;
279
280
281 private CompletableFuture<Integer> connectionCloseFuture = new CompletableFuture<>();
282
283
284 static final String TIME_OUT_ERROR = I18n.err( I18n.ERR_04170_TIMEOUT_OCCURED );
285
286 static final String NO_RESPONSE_ERROR = I18n.err( I18n.ERR_04169_RESPONSE_QUEUE_EMPTIED );
287
288
289
290
291
292
293 public LdapNetworkConnection()
294 {
295 this( null, -1, false );
296 }
297
298
299
300
301
302
303
304
305 public LdapNetworkConnection( LdapConnectionConfig config )
306 {
307 this( config, LdapApiServiceFactory.getSingleton() );
308 }
309
310
311
312
313
314
315
316
317 public LdapNetworkConnection( LdapConnectionConfig config, LdapApiService ldapApiService )
318 {
319 super( ldapApiService );
320 this.config = config;
321
322 if ( config.getBinaryAttributeDetector() == null )
323 {
324 config.setBinaryAttributeDetector( new DefaultConfigurableBinaryAttributeDetector() );
325 }
326
327 this.timeout = config.getTimeout();
328 this.connectTimeout = determineTimeoutConfiguration( config.getConnectTimeout() );
329 this.writeOperationTimeout = determineTimeoutConfiguration( config.getWriteOperationTimeout() );
330 this.readOperationTimeout = determineTimeoutConfiguration( config.getReadOperationTimeout() );
331 this.closeTimeout = determineTimeoutConfiguration( config.getCloseTimeout() );
332 this.sendTimeout = determineTimeoutConfiguration( config.getSendTimeout() );
333 }
334
335 private long determineTimeoutConfiguration( Long localTimeout )
336 {
337 return localTimeout == null ? this.timeout : localTimeout;
338 }
339
340
341
342
343
344
345
346 public LdapNetworkConnection( boolean useSsl )
347 {
348 this( null, -1, useSsl );
349 }
350
351
352
353
354
355
356
357
358 public LdapNetworkConnection( boolean useSsl, LdapApiService ldapApiService )
359 {
360 this( null, -1, useSsl, ldapApiService );
361 }
362
363
364
365
366
367
368
369
370
371 public LdapNetworkConnection( String server )
372 {
373 this( server, -1, false );
374 }
375
376
377
378
379
380
381
382
383
384 public LdapNetworkConnection( String server, LdapApiService ldapApiService )
385 {
386 this( server, -1, false, ldapApiService );
387 }
388
389
390
391
392
393
394
395
396
397
398
399 public LdapNetworkConnection( String server, boolean useSsl )
400 {
401 this( server, -1, useSsl );
402 }
403
404
405
406
407
408
409
410
411
412
413 public LdapNetworkConnection( String server, boolean useSsl, LdapApiService ldapApiService )
414 {
415 this( server, -1, useSsl, ldapApiService );
416 }
417
418
419
420
421
422
423
424
425
426 public LdapNetworkConnection( String server, int port )
427 {
428 this( server, port, false );
429 }
430
431
432
433
434
435
436
437
438
439
440
441 public LdapNetworkConnection( String server, int port, LdapApiService ldapApiService )
442 {
443 this( server, port, false, ldapApiService );
444 }
445
446
447
448
449
450
451
452
453
454
455
456
457 public LdapNetworkConnection( String server, int port, boolean useSsl )
458 {
459 this( buildConfig( server, port, useSsl ) );
460 }
461
462
463
464
465
466
467
468
469
470
471
472
473 public LdapNetworkConnection( String server, int port, TrustManager... trustManagers )
474 {
475 this( buildConfig( server, port, true ) );
476
477 config.setTrustManagers( trustManagers );
478 }
479
480
481
482
483
484
485
486
487
488
489
490
491 public LdapNetworkConnection( String server, int port, boolean useSsl, LdapApiService ldapApiService )
492 {
493 this( buildConfig( server, port, useSsl ), ldapApiService );
494 }
495
496
497 private static LdapConnectionConfig buildConfig( String server, int port, boolean useSsl )
498 {
499 LdapConnectionConfig config = new LdapConnectionConfig();
500 config.setUseSsl( useSsl );
501
502 if ( port != -1 )
503 {
504 config.setLdapPort( port );
505 }
506 else
507 {
508 if ( useSsl )
509 {
510 config.setLdapPort( config.getDefaultLdapsPort() );
511 }
512 else
513 {
514 config.setLdapPort( config.getDefaultLdapPort() );
515 }
516 }
517
518
519 if ( Strings.isEmpty( server ) )
520 {
521 config.setLdapHost( Network.LOOPBACK_HOSTNAME );
522
523 }
524 else
525 {
526 config.setLdapHost( server );
527 }
528
529 config.setBinaryAttributeDetector( new DefaultConfigurableBinaryAttributeDetector() );
530
531 return config;
532 }
533
534
535
536
537
538
539
540 private void createConnector() throws LdapException
541 {
542
543 connector = new NioSocketConnector( 1 );
544
545 if ( socketSessionConfig != null )
546 {
547 ( ( SocketSessionConfig ) connector.getSessionConfig() ).setAll( socketSessionConfig );
548 }
549 else
550 {
551 ( ( SocketSessionConfig ) connector.getSessionConfig() ).setReuseAddress( true );
552 }
553
554
555 connector.getFilterChain().addLast( LDAP_CODEC_FILTER_KEY, ldapProtocolFilter );
556
557
558 if ( config.isUseSsl() )
559 {
560 addSslFilter();
561 }
562
563
564 connector.setHandler( this );
565 }
566
567
568
569
570
571
572 @Override
573 public boolean isConnected()
574 {
575 return ( ioSession != null ) && ioSession.isConnected() && !ioSession.isClosing();
576
577 }
578
579
580
581
582
583 @Override
584 public boolean isAuthenticated()
585 {
586 return isConnected() && authenticated.get();
587 }
588
589
590
591
592
593
594
595 public boolean isSecured()
596 {
597 return isConnected() && ioSession.isSecured();
598 }
599
600
601
602
603
604 @Override
605 public Throwable exceptionCaught()
606 {
607 return ( Throwable ) ioSession.getAttribute( EXCEPTION_KEY );
608 }
609
610
611
612
613
614
615
616
617 private void checkSession() throws InvalidConnectionException
618 {
619 if ( ioSession == null )
620 {
621 throw new InvalidConnectionException( I18n.err( I18n.ERR_04104_NULL_CONNECTION_CANNOT_CONNECT ) );
622 }
623
624 if ( !isConnected() )
625 {
626 throw new InvalidConnectionException( I18n.err( I18n.ERR_04108_INVALID_CONNECTION ) );
627 }
628 }
629
630
631 private void addToFutureMap( int messageId, ResponseFuture<? extends Response> future )
632 {
633 if ( LOG.isDebugEnabled() )
634 {
635 LOG.debug( I18n.msg( I18n.MSG_04106_ADDING, messageId, future.getClass().getName() ) );
636 }
637
638 futureMap.put( messageId, future );
639 }
640
641
642 private ResponseFuture<? extends Response> getFromFutureMap( int messageId )
643 {
644 ResponseFuture<? extends Response> future = futureMap.remove( messageId );
645
646 if ( LOG.isDebugEnabled() && ( future != null ) )
647 {
648 LOG.debug( I18n.msg( I18n.MSG_04126_REMOVING, messageId, future.getClass().getName() ) );
649 }
650
651 return future;
652 }
653
654
655 private ResponseFuture<? extends Response> peekFromFutureMap( int messageId )
656 {
657 ResponseFuture<? extends Response> future = futureMap.get( messageId );
658
659
660 if ( LOG.isDebugEnabled() && ( future != null ) )
661 {
662 LOG.debug( I18n.msg( I18n.MSG_04119_GETTING, messageId, future.getClass().getName() ) );
663 }
664
665 return future;
666 }
667
668
669
670
671
672
673
674
675
676
677 public long getTimeout( long configuredTimeout, int searchTimeLimitInSeconds )
678 {
679 if ( searchTimeLimitInSeconds < 0 )
680 {
681 return configuredTimeout;
682 }
683 else if ( searchTimeLimitInSeconds == 0 )
684 {
685 if ( config.getTimeout() == 0 )
686 {
687 return Long.MAX_VALUE;
688 }
689 else
690 {
691 return configuredTimeout;
692 }
693 }
694 else
695 {
696 long searchTimeLimitInMS = searchTimeLimitInSeconds * 1000L;
697 return Math.max( searchTimeLimitInMS, configuredTimeout );
698 }
699 }
700
701
702
703
704
705
706
707
708 public ConnectFuture tryConnect() throws LdapException
709 {
710
711 SocketAddress address = new InetSocketAddress( config.getLdapHost(), config.getLdapPort() );
712 ConnectFuture connectionFuture = connector.connect( address );
713 boolean result = false;
714
715
716 try
717 {
718 result = connectionFuture.await( connectTimeout );
719 }
720 catch ( InterruptedException e )
721 {
722 connector.dispose();
723 connector = null;
724
725 if ( LOG.isDebugEnabled() )
726 {
727 LOG.debug( I18n.msg( I18n.MSG_04120_INTERRUPTED_WAITING_FOR_CONNECTION,
728 config.getLdapHost(),
729 config.getLdapPort() ), e );
730 }
731
732 throw new LdapOtherException( e.getMessage(), e );
733 }
734
735 if ( !result )
736 {
737
738 Throwable connectionException = connectionFuture.getException();
739
740 if ( ( connector != null ) && !connector.isDisposing() && !connector.isDisposed() )
741 {
742 connector.dispose();
743 }
744
745 connector = null;
746
747 if ( connectionException == null )
748 {
749
750 String message = I18n.msg( I18n.MSG_04177_CONNECTION_TIMEOUT, connectTimeout );
751
752 if ( LOG.isDebugEnabled() )
753 {
754 LOG.debug( message );
755 }
756
757 throw new LdapConnectionTimeOutException( message );
758 }
759 else
760 {
761 if ( LOG.isDebugEnabled() )
762 {
763 if ( ( connectionException instanceof ConnectException )
764 || ( connectionException instanceof UnresolvedAddressException ) )
765 {
766
767
768 LOG.debug( I18n.msg( I18n.MSG_04144_CONNECTION_ERROR, connectionFuture.getException().getMessage() ) );
769 }
770
771 LOG.debug( I18n.msg( I18n.MSG_04120_INTERRUPTED_WAITING_FOR_CONNECTION,
772 config.getLdapHost(),
773 config.getLdapPort() ), connectionException );
774 }
775
776 throw new LdapOtherException( connectionException.getMessage(), connectionException );
777 }
778 }
779
780 return connectionFuture;
781 }
782
783
784
785
786
787
788
789 private void close( ConnectFuture connectionFuture ) throws LdapException
790 {
791
792 close();
793
794 Throwable e = connectionFuture.getException();
795
796 if ( e != null )
797 {
798
799
800 if ( ( e instanceof UnresolvedAddressException ) && ( e.getMessage() == null ) )
801 {
802 throw new InvalidConnectionException( I18n.err( I18n.ERR_04121_CANNOT_RESOLVE_HOSTNAME, config.getLdapHost() ), e );
803 }
804
805
806 throw new InvalidConnectionException( I18n.err( I18n.ERR_04110_CANNOT_CONNECT_TO_SERVER, e.getMessage() ), e );
807 }
808
809
810 if ( LOG.isErrorEnabled() )
811 {
812 LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Connect" ) );
813 }
814
815 throw new LdapException( TIME_OUT_ERROR );
816 }
817
818
819
820
821
822
823
824 private void checkSecured( ConnectFuture connectionFuture ) throws LdapException
825 {
826 try
827 {
828 boolean isSecured = handshakeFuture.get( connectTimeout, TimeUnit.MILLISECONDS );
829
830 if ( !isSecured )
831 {
832
833 Throwable cause = connectionFuture.getException();
834
835 if ( cause == null && connectionFuture.getSession() != null )
836 {
837 cause = ( Throwable ) connectionFuture.getSession().getAttribute( EXCEPTION_KEY );
838 }
839
840
841 connectionCloseFuture.complete( 0 );
842
843
844 if ( cause == null )
845 {
846 throw new LdapException( TIME_OUT_ERROR );
847 }
848
849 throw new LdapTlsHandshakeException( I18n.err( I18n.ERR_04120_TLS_HANDSHAKE_ERROR ), cause );
850 }
851 }
852 catch ( Exception e )
853 {
854 if ( e instanceof LdapException )
855 {
856 throw ( LdapException ) e;
857 }
858
859 String msg = I18n.err( I18n.ERR_04122_SSL_CONTEXT_INIT_FAILURE );
860 LOG.error( msg, e );
861 throw new LdapException( msg, e );
862 }
863 }
864
865
866
867
868
869
870
871 private void setCloseListener( ConnectFuture connectionFuture )
872 {
873
874 CloseFuture closeFuture = connectionFuture.getSession().getCloseFuture();
875
876 closeFuture.addListener( future ->
877 {
878
879 if ( LOG.isDebugEnabled() )
880 {
881 LOG.debug( I18n.msg( I18n.MSG_04137_NOD_RECEIVED ) );
882 }
883
884 for ( ResponseFuture<?> responseFuture : futureMap.values() )
885 {
886 if ( LOG.isDebugEnabled() )
887 {
888 LOG.debug( I18n.msg( I18n.MSG_04137_NOD_RECEIVED ) );
889 }
890
891 responseFuture.cancel();
892
893 try
894 {
895 if ( responseFuture instanceof AddFuture )
896 {
897 ( ( AddFuture ) responseFuture ).set( AddNoDResponse.PROTOCOLERROR );
898 }
899 else if ( responseFuture instanceof BindFuture )
900 {
901 ( ( BindFuture ) responseFuture ).set( BindNoDResponse.PROTOCOLERROR );
902 }
903 else if ( responseFuture instanceof CompareFuture )
904 {
905 ( ( CompareFuture ) responseFuture ).set( CompareNoDResponse.PROTOCOLERROR );
906 }
907 else if ( responseFuture instanceof DeleteFuture )
908 {
909 ( ( DeleteFuture ) responseFuture ).set( DeleteNoDResponse.PROTOCOLERROR );
910 }
911 else if ( responseFuture instanceof ExtendedFuture )
912 {
913 ( ( ExtendedFuture ) responseFuture ).set( ExtendedNoDResponse.PROTOCOLERROR );
914 }
915 else if ( responseFuture instanceof ModifyFuture )
916 {
917 ( ( ModifyFuture ) responseFuture ).set( ModifyNoDResponse.PROTOCOLERROR );
918 }
919 else if ( responseFuture instanceof ModifyDnFuture )
920 {
921 ( ( ModifyDnFuture ) responseFuture ).set( ModifyDnNoDResponse.PROTOCOLERROR );
922 }
923 else if ( responseFuture instanceof SearchFuture )
924 {
925 ( ( SearchFuture ) responseFuture ).set( SearchNoDResponse.PROTOCOLERROR );
926 }
927 }
928 catch ( InterruptedException e )
929 {
930 LOG.error( I18n.err( I18n.ERR_04113_ERROR_PROCESSING_NOD, responseFuture ), e );
931 }
932
933 futureMap.remove( messageId.get() );
934 }
935
936 futureMap.clear();
937 } );
938 }
939
940
941
942
943
944 private void setBinaryDetector()
945 {
946 @SuppressWarnings("unchecked")
947 LdapMessageContainer<? extends Message> container =
948 ( LdapMessageContainer<? extends Message> ) ioSession
949 .getAttribute( LdapDecoder.MESSAGE_CONTAINER_ATTR );
950
951 if ( container != null )
952 {
953 if ( ( schemaManager != null ) && !( container.getBinaryAttributeDetector() instanceof SchemaBinaryAttributeDetector ) )
954 {
955 container.setBinaryAttributeDetector( new SchemaBinaryAttributeDetector( schemaManager ) );
956 }
957 }
958 else
959 {
960 BinaryAttributeDetector atDetector = new DefaultConfigurableBinaryAttributeDetector();
961
962 if ( schemaManager != null )
963 {
964 atDetector = new SchemaBinaryAttributeDetector( schemaManager );
965 }
966
967 ioSession.setAttribute( LdapDecoder.MESSAGE_CONTAINER_ATTR,
968 new LdapMessageContainer<Message>( codec, atDetector ) );
969 }
970 }
971
972
973
974
975
976
977 @Override
978 public boolean connect() throws LdapException
979 {
980 if ( isConnected() )
981 {
982
983 return true;
984 }
985
986 try
987 {
988
989 if ( connector == null )
990 {
991 createConnector();
992 }
993
994
995 ConnectFuture connectionFuture = tryConnect();
996
997
998 if ( !connectionFuture.isConnected() )
999 {
1000
1001 connectionCloseFuture.cancel( true );
1002
1003 close( connectionFuture );
1004 }
1005
1006
1007 if ( config.isUseSsl() )
1008 {
1009 checkSecured( connectionFuture );
1010 }
1011
1012
1013 setCloseListener( connectionFuture );
1014
1015
1016 ioSession = connectionFuture.getSession();
1017
1018
1019 setBinaryDetector();
1020
1021
1022 messageId.set( 0 );
1023
1024 connectionCloseFuture = new CompletableFuture<>();
1025
1026
1027 if ( config.isUseTls() && !config.isUseSsl() )
1028 {
1029 startTls();
1030 }
1031
1032
1033 return true;
1034 }
1035 catch ( Exception e )
1036 {
1037 if ( ( connector != null ) && !connector.isDisposing() && !connector.isDisposed() )
1038 {
1039 connector.dispose();
1040 connector = null;
1041 }
1042
1043 throw e;
1044 }
1045 }
1046
1047
1048
1049
1050
1051 @Override
1052 public void close()
1053 {
1054
1055 if ( isConnected() )
1056 {
1057 ioSession.closeNow();
1058 }
1059
1060 try
1061 {
1062 if ( ( ioSession != null ) && ioSession.isConnected() )
1063 {
1064 connectionCloseFuture.get( closeTimeout, TimeUnit.MILLISECONDS );
1065 }
1066 }
1067 catch ( TimeoutException | ExecutionException | InterruptedException e )
1068 {
1069 if ( LOG.isDebugEnabled() )
1070 {
1071 LOG.debug( I18n.msg( I18n.MSH_04178_CLOSE_LATCH_ABORTED ) );
1072 }
1073 }
1074 }
1075
1076
1077
1078
1079
1080
1081
1082
1083 @Override
1084 public void add( Entry entry ) throws LdapException
1085 {
1086 if ( entry == null )
1087 {
1088 String msg = I18n.err( I18n.ERR_04123_CANNOT_ADD_EMPTY_ENTRY );
1089
1090 if ( LOG.isDebugEnabled() )
1091 {
1092 LOG.debug( msg );
1093 }
1094
1095 throw new IllegalArgumentException( msg );
1096 }
1097
1098 AddRequest addRequest = new AddRequestImpl();
1099 addRequest.setEntry( entry );
1100
1101 AddResponse addResponse = add( addRequest );
1102
1103 processResponse( addResponse );
1104 }
1105
1106
1107
1108
1109
1110 @Override
1111 public AddFuture addAsync( Entry entry ) throws LdapException
1112 {
1113 if ( entry == null )
1114 {
1115 String msg = I18n.err( I18n.ERR_04125_CANNOT_ADD_NULL_ENTRY );
1116
1117 if ( LOG.isDebugEnabled() )
1118 {
1119 LOG.debug( msg );
1120 }
1121
1122 throw new IllegalArgumentException( msg );
1123 }
1124
1125 AddRequest addRequest = new AddRequestImpl();
1126 addRequest.setEntry( entry );
1127
1128 return addAsync( addRequest );
1129 }
1130
1131
1132
1133
1134
1135 @Override
1136 public AddResponse add( AddRequest addRequest ) throws LdapException
1137 {
1138 if ( addRequest == null )
1139 {
1140 String msg = I18n.err( I18n.ERR_04124_CANNOT_PROCESS_NULL_ADD_REQUEST );
1141
1142 if ( LOG.isDebugEnabled() )
1143 {
1144 LOG.debug( msg );
1145 }
1146
1147 throw new IllegalArgumentException( msg );
1148 }
1149
1150 if ( addRequest.getEntry() == null )
1151 {
1152 String msg = I18n.err( I18n.ERR_04125_CANNOT_ADD_NULL_ENTRY );
1153
1154 if ( LOG.isDebugEnabled() )
1155 {
1156 LOG.debug( msg );
1157 }
1158
1159 throw new IllegalArgumentException( msg );
1160 }
1161
1162 AddFuture addFuture = addAsync( addRequest );
1163
1164
1165 try
1166 {
1167
1168
1169 AddResponse addResponse = addFuture.get( writeOperationTimeout, TimeUnit.MILLISECONDS );
1170
1171 if ( addResponse == null )
1172 {
1173
1174 if ( LOG.isErrorEnabled() )
1175 {
1176 LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Add" ) );
1177 }
1178
1179 throw new LdapException( TIME_OUT_ERROR );
1180 }
1181
1182 if ( addResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
1183 {
1184
1185 if ( LOG.isDebugEnabled() )
1186 {
1187 LOG.debug( I18n.msg( I18n.MSG_04108_ADD_SUCCESSFUL, addResponse ) );
1188 }
1189 }
1190 else
1191 {
1192
1193 if ( LOG.isDebugEnabled() )
1194 {
1195 LOG.debug( I18n.msg( I18n.MSG_04107_ADD_FAILED, addResponse ) );
1196 }
1197 }
1198
1199 return addResponse;
1200 }
1201 catch ( Exception ie )
1202 {
1203
1204 LOG.error( NO_RESPONSE_ERROR, ie );
1205
1206
1207 if ( !addFuture.isCancelled() )
1208 {
1209 abandon( addRequest.getMessageId() );
1210 }
1211
1212 throw new LdapException( NO_RESPONSE_ERROR, ie );
1213 }
1214 }
1215
1216
1217
1218
1219
1220 @Override
1221 public AddFuture addAsync( AddRequest addRequest ) throws LdapException
1222 {
1223 if ( addRequest == null )
1224 {
1225 String msg = I18n.err( I18n.ERR_04124_CANNOT_PROCESS_NULL_ADD_REQUEST );
1226
1227 if ( LOG.isDebugEnabled() )
1228 {
1229 LOG.debug( msg );
1230 }
1231
1232 throw new IllegalArgumentException( msg );
1233 }
1234
1235 if ( addRequest.getEntry() == null )
1236 {
1237 String msg = I18n.err( I18n.ERR_04125_CANNOT_ADD_NULL_ENTRY );
1238
1239 if ( LOG.isDebugEnabled() )
1240 {
1241 LOG.debug( msg );
1242 }
1243
1244 throw new IllegalArgumentException( msg );
1245 }
1246
1247
1248 connect();
1249
1250 checkSession();
1251
1252 int newId = messageId.incrementAndGet();
1253
1254 addRequest.setMessageId( newId );
1255 AddFuture addFuture = new AddFuture( this, newId );
1256 addToFutureMap( newId, addFuture );
1257
1258
1259 writeRequest( addRequest );
1260
1261
1262 return addFuture;
1263 }
1264
1265
1266
1267
1268
1269
1270
1271 @Override
1272 public void abandon( int messageId )
1273 {
1274 if ( messageId < 0 )
1275 {
1276 String msg = I18n.err( I18n.ERR_04126_CANNOT_ABANDON_NEG_MSG_ID );
1277
1278 if ( LOG.isDebugEnabled() )
1279 {
1280 LOG.debug( msg );
1281 }
1282
1283 throw new IllegalArgumentException( msg );
1284 }
1285
1286 AbandonRequest abandonRequest = new AbandonRequestImpl();
1287 abandonRequest.setAbandoned( messageId );
1288
1289 abandonInternal( abandonRequest );
1290 }
1291
1292
1293
1294
1295
1296 @Override
1297 public void abandon( AbandonRequest abandonRequest )
1298 {
1299 if ( abandonRequest == null )
1300 {
1301 String msg = I18n.err( I18n.ERR_04127_CANNOT_PROCESS_NULL_ABANDON_REQ );
1302
1303 if ( LOG.isDebugEnabled() )
1304 {
1305 LOG.debug( msg );
1306 }
1307
1308 throw new IllegalArgumentException( msg );
1309 }
1310
1311 abandonInternal( abandonRequest );
1312 }
1313
1314
1315
1316
1317
1318
1319
1320 private void abandonInternal( AbandonRequest abandonRequest )
1321 {
1322 if ( LOG.isDebugEnabled() )
1323 {
1324 LOG.debug( I18n.msg( I18n.MSG_04104_SENDING_REQUEST, abandonRequest ) );
1325 }
1326
1327 int newId = messageId.incrementAndGet();
1328 abandonRequest.setMessageId( newId );
1329
1330
1331 ioSession.write( abandonRequest );
1332
1333
1334 int abandonId = abandonRequest.getAbandoned();
1335
1336 ResponseFuture<? extends Response> rf = getFromFutureMap( abandonId );
1337
1338
1339
1340
1341 if ( rf != null )
1342 {
1343 if ( LOG.isDebugEnabled() )
1344 {
1345 LOG.debug( I18n.msg( I18n.MSG_04141_SENDING_CANCEL ) );
1346 }
1347
1348 rf.cancel( true );
1349 }
1350 else
1351 {
1352
1353 if ( LOG.isInfoEnabled() )
1354 {
1355 LOG.info( I18n.msg( I18n.MSG_04165_NO_FUTURE_ASSOCIATED_TO_MSG_ID_COMPLETED, abandonId ) );
1356 }
1357 }
1358 }
1359
1360
1361
1362
1363
1364 @Override
1365 public void bind() throws LdapException
1366 {
1367 if ( LOG.isDebugEnabled() )
1368 {
1369 LOG.debug( I18n.msg( I18n.MSG_04112_BIND ) );
1370 }
1371
1372
1373 BindRequest bindRequest = createBindRequest( config.getName(), Strings.getBytesUtf8( config.getCredentials() ) );
1374
1375 BindResponse bindResponse = bind( bindRequest );
1376
1377 processResponse( bindResponse );
1378 }
1379
1380
1381
1382
1383
1384 @Override
1385 public void anonymousBind() throws LdapException
1386 {
1387 if ( LOG.isDebugEnabled() )
1388 {
1389 LOG.debug( I18n.msg( I18n.MSG_04109_ANONYMOUS_BIND ) );
1390 }
1391
1392
1393 BindRequest bindRequest = createBindRequest( StringConstants.EMPTY, Strings.EMPTY_BYTES );
1394
1395 BindResponse bindResponse = bind( bindRequest );
1396
1397 processResponse( bindResponse );
1398 }
1399
1400
1401
1402
1403
1404 @Override
1405 public BindFuture bindAsync() throws LdapException
1406 {
1407 if ( LOG.isDebugEnabled() )
1408 {
1409 LOG.debug( I18n.msg( I18n.MSG_04111_ASYNC_BIND ) );
1410 }
1411
1412
1413 BindRequest bindRequest = createBindRequest( config.getName(), Strings.getBytesUtf8( config.getCredentials() ) );
1414
1415 return bindAsync( bindRequest );
1416 }
1417
1418
1419
1420
1421
1422 @Override
1423 public BindFuture anonymousBindAsync() throws LdapException
1424 {
1425 if ( LOG.isDebugEnabled() )
1426 {
1427 LOG.debug( I18n.msg( I18n.MSG_04110_ANONYMOUS_ASYNC_BIND ) );
1428 }
1429
1430
1431 BindRequest bindRequest = createBindRequest( StringConstants.EMPTY, Strings.EMPTY_BYTES );
1432
1433 return bindAsync( bindRequest );
1434 }
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445 public BindFuture bindAsync( String name ) throws LdapException
1446 {
1447 if ( LOG.isDebugEnabled() )
1448 {
1449 LOG.debug( I18n.msg( I18n.MSG_04102_BIND_REQUEST, name ) );
1450 }
1451
1452
1453 BindRequest bindRequest = createBindRequest( name, Strings.EMPTY_BYTES );
1454
1455 return bindAsync( bindRequest );
1456 }
1457
1458
1459
1460
1461
1462 @Override
1463 public BindFuture bindAsync( String name, String credentials ) throws LdapException
1464 {
1465 if ( LOG.isDebugEnabled() )
1466 {
1467 LOG.debug( I18n.msg( I18n.MSG_04102_BIND_REQUEST, name ) );
1468 }
1469
1470
1471 if ( Strings.isEmpty( credentials ) && Strings.isNotEmpty( name ) )
1472 {
1473 if ( LOG.isDebugEnabled() )
1474 {
1475 LOG.debug( I18n.msg( I18n.MSG_04105_MISSING_PASSWORD ) );
1476 }
1477
1478 throw new LdapAuthenticationException( I18n.msg( I18n.MSG_04105_MISSING_PASSWORD ) );
1479 }
1480
1481
1482 BindRequest bindRequest = createBindRequest( name, Strings.getBytesUtf8( credentials ) );
1483
1484 return bindAsync( bindRequest );
1485 }
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496 public BindFuture bindAsync( Dn name ) throws LdapException
1497 {
1498 if ( LOG.isDebugEnabled() )
1499 {
1500 LOG.debug( I18n.msg( I18n.MSG_04102_BIND_REQUEST, name ) );
1501 }
1502
1503
1504 BindRequest bindRequest = createBindRequest( name, Strings.EMPTY_BYTES );
1505
1506 return bindAsync( bindRequest );
1507 }
1508
1509
1510
1511
1512
1513 @Override
1514 public BindFuture bindAsync( Dn name, String credentials ) throws LdapException
1515 {
1516 if ( LOG.isDebugEnabled() )
1517 {
1518 LOG.debug( I18n.msg( I18n.MSG_04102_BIND_REQUEST, name ) );
1519 }
1520
1521
1522 if ( Strings.isEmpty( credentials ) && ( !Dn.EMPTY_DN.equals( name ) ) )
1523 {
1524 if ( LOG.isDebugEnabled() )
1525 {
1526 LOG.debug( I18n.msg( I18n.MSG_04105_MISSING_PASSWORD ) );
1527 }
1528
1529 throw new LdapAuthenticationException( I18n.msg( I18n.MSG_04105_MISSING_PASSWORD ) );
1530 }
1531
1532
1533 BindRequest bindRequest = createBindRequest( name, Strings.getBytesUtf8( credentials ) );
1534
1535 return bindAsync( bindRequest );
1536 }
1537
1538
1539
1540
1541
1542 @Override
1543 public BindResponse bind( BindRequest bindRequest ) throws LdapException
1544 {
1545 if ( bindRequest == null )
1546 {
1547 String msg = I18n.err( I18n.ERR_04128_CANNOT_PROCESS_NULL_BIND_REQ );
1548
1549 if ( LOG.isDebugEnabled() )
1550 {
1551 LOG.debug( msg );
1552 }
1553
1554 throw new IllegalArgumentException( msg );
1555 }
1556
1557 BindFuture bindFuture = bindAsync( bindRequest );
1558
1559
1560 try
1561 {
1562
1563
1564 BindResponse bindResponse = bindFuture.get( connectTimeout, TimeUnit.MILLISECONDS );
1565
1566 if ( bindResponse == null )
1567 {
1568
1569 if ( LOG.isErrorEnabled() )
1570 {
1571 LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Bind" ) );
1572 }
1573
1574 throw new LdapException( TIME_OUT_ERROR );
1575 }
1576
1577 if ( bindResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
1578 {
1579 authenticated.set( true );
1580
1581
1582 if ( LOG.isDebugEnabled() )
1583 {
1584 LOG.debug( I18n.msg( I18n.MSG_04101_BIND_SUCCESSFUL, bindResponse ) );
1585 }
1586 }
1587 else
1588 {
1589
1590 if ( LOG.isDebugEnabled() )
1591 {
1592 LOG.debug( I18n.msg( I18n.MSG_04100_BIND_FAIL, bindResponse ) );
1593 }
1594 }
1595
1596 return bindResponse;
1597 }
1598 catch ( Exception ie )
1599 {
1600
1601 LOG.error( NO_RESPONSE_ERROR, ie );
1602
1603 throw new LdapException( NO_RESPONSE_ERROR, ie );
1604 }
1605 }
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615 private BindRequest createBindRequest( String name, byte[] credentials )
1616 {
1617 return createBindRequest( name, credentials, null, ( Control[] ) null );
1618 }
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628 private BindRequest createBindRequest( Dn name, byte[] credentials )
1629 {
1630 return createBindRequest( name.getName(), credentials, null, ( Control[] ) null );
1631 }
1632
1633
1634
1635
1636
1637 @Override
1638 public BindFuture bindAsync( BindRequest bindRequest ) throws LdapException
1639 {
1640 if ( bindRequest == null )
1641 {
1642 String msg = I18n.err( I18n.ERR_04128_CANNOT_PROCESS_NULL_BIND_REQ );
1643
1644 if ( LOG.isDebugEnabled() )
1645 {
1646 LOG.debug( msg );
1647 }
1648
1649 throw new IllegalArgumentException( msg );
1650 }
1651
1652
1653 authenticated.set( false );
1654
1655
1656 connect();
1657
1658
1659 checkSession();
1660
1661
1662 int newId = messageId.incrementAndGet();
1663 bindRequest.setMessageId( newId );
1664
1665 if ( LOG.isDebugEnabled() )
1666 {
1667 LOG.debug( I18n.msg( I18n.MSG_04104_SENDING_REQUEST, bindRequest ) );
1668 }
1669
1670
1671 BindFuture bindFuture = new BindFuture( this, newId );
1672
1673 addToFutureMap( newId, bindFuture );
1674
1675 writeRequest( bindRequest );
1676
1677
1678 return bindFuture;
1679 }
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690 public BindResponse bindSaslPlain( String authcid, String credentials ) throws LdapException
1691 {
1692 return bindSaslPlain( null, authcid, credentials );
1693 }
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705 public BindResponse bindSaslPlain( String authzid, String authcid, String credentials ) throws LdapException
1706 {
1707 if ( LOG.isDebugEnabled() )
1708 {
1709 LOG.debug( I18n.msg( I18n.MSG_04127_SASL_PLAIN_BIND ) );
1710 }
1711
1712
1713 SaslPlainRequest saslRequest = new SaslPlainRequest();
1714 saslRequest.setAuthorizationId( authzid );
1715 saslRequest.setUsername( authcid );
1716 saslRequest.setCredentials( credentials );
1717
1718 BindFuture bindFuture = bindAsync( saslRequest );
1719
1720
1721 try
1722 {
1723
1724
1725 BindResponse bindResponse = bindFuture.get( connectTimeout, TimeUnit.MILLISECONDS );
1726
1727 if ( bindResponse == null )
1728 {
1729
1730 if ( LOG.isErrorEnabled() )
1731 {
1732 LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Bind" ) );
1733 }
1734
1735 throw new LdapException( TIME_OUT_ERROR );
1736 }
1737
1738 if ( bindResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
1739 {
1740 authenticated.set( true );
1741
1742
1743 if ( LOG.isDebugEnabled() )
1744 {
1745 LOG.debug( I18n.msg( I18n.MSG_04101_BIND_SUCCESSFUL, bindResponse ) );
1746 }
1747 }
1748 else
1749 {
1750
1751 if ( LOG.isDebugEnabled() )
1752 {
1753 LOG.debug( I18n.msg( I18n.MSG_04100_BIND_FAIL, bindResponse ) );
1754 }
1755 }
1756
1757 return bindResponse;
1758 }
1759 catch ( Exception ie )
1760 {
1761
1762 LOG.error( NO_RESPONSE_ERROR, ie );
1763
1764 throw new LdapException( NO_RESPONSE_ERROR, ie );
1765 }
1766 }
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776 public BindResponse bind( SaslRequest request ) throws LdapException
1777 {
1778 if ( request == null )
1779 {
1780 String msg = I18n.msg( I18n.MSG_04103_NULL_REQUEST );
1781
1782 if ( LOG.isDebugEnabled() )
1783 {
1784 LOG.debug( msg );
1785 }
1786
1787 throw new IllegalArgumentException( msg );
1788 }
1789
1790 BindFuture bindFuture = bindAsync( request );
1791
1792
1793 try
1794 {
1795
1796
1797 BindResponse bindResponse = bindFuture.get( connectTimeout, TimeUnit.MILLISECONDS );
1798
1799 if ( bindResponse == null )
1800 {
1801
1802 if ( LOG.isErrorEnabled() )
1803 {
1804 LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Bind" ) );
1805 }
1806
1807 throw new LdapException( TIME_OUT_ERROR );
1808 }
1809
1810 if ( bindResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
1811 {
1812 authenticated.set( true );
1813
1814
1815 if ( LOG.isDebugEnabled() )
1816 {
1817 LOG.debug( I18n.msg( I18n.MSG_04101_BIND_SUCCESSFUL, bindResponse ) );
1818 }
1819 }
1820 else
1821 {
1822
1823 if ( LOG.isDebugEnabled() )
1824 {
1825 LOG.debug( I18n.msg( I18n.MSG_04100_BIND_FAIL, bindResponse ) );
1826 }
1827 }
1828
1829 return bindResponse;
1830 }
1831 catch ( Exception ie )
1832 {
1833
1834 LOG.error( NO_RESPONSE_ERROR, ie );
1835
1836 throw new LdapException( NO_RESPONSE_ERROR, ie );
1837 }
1838 }
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849 public BindResponse bindSaslCramMd5( String userName, String credentials ) throws LdapException
1850 {
1851 SaslCramMd5Request request = new SaslCramMd5Request();
1852 request.setUsername( userName );
1853 request.setCredentials( "secret" );
1854
1855 return bind( request );
1856 }
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867 public BindResponse bindSaslDigestMd5( String userName, String credentials ) throws LdapException
1868 {
1869 SaslDigestMd5Request request = new SaslDigestMd5Request();
1870 request.setUsername( userName );
1871 request.setCredentials( "secret" );
1872
1873 return bind( request );
1874 }
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884 public BindResponse bind( SaslCramMd5Request request ) throws LdapException
1885 {
1886 if ( request == null )
1887 {
1888 String msg = I18n.msg( I18n.MSG_04103_NULL_REQUEST );
1889
1890 if ( LOG.isDebugEnabled() )
1891 {
1892 LOG.debug( msg );
1893 }
1894
1895 throw new IllegalArgumentException( msg );
1896 }
1897
1898 BindFuture bindFuture = bindAsync( request );
1899
1900
1901 try
1902 {
1903
1904
1905 BindResponse bindResponse = bindFuture.get( connectTimeout, TimeUnit.MILLISECONDS );
1906
1907 if ( bindResponse == null )
1908 {
1909
1910 if ( LOG.isErrorEnabled() )
1911 {
1912 LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Bind" ) );
1913 }
1914
1915 throw new LdapException( TIME_OUT_ERROR );
1916 }
1917
1918 if ( bindResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
1919 {
1920 authenticated.set( true );
1921
1922
1923 if ( LOG.isDebugEnabled() )
1924 {
1925 LOG.debug( I18n.msg( I18n.MSG_04101_BIND_SUCCESSFUL, bindResponse ) );
1926 }
1927 }
1928 else
1929 {
1930
1931 if ( LOG.isDebugEnabled() )
1932 {
1933 LOG.debug( I18n.msg( I18n.MSG_04100_BIND_FAIL, bindResponse ) );
1934 }
1935 }
1936
1937 return bindResponse;
1938 }
1939 catch ( Exception ie )
1940 {
1941
1942 LOG.error( NO_RESPONSE_ERROR, ie );
1943
1944 throw new LdapException( NO_RESPONSE_ERROR, ie );
1945 }
1946 }
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956 public BindFuture bindAsync( SaslRequest request )
1957 throws LdapException
1958 {
1959 return bindSasl( request );
1960 }
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970 public BindResponse bind( SaslDigestMd5Request request ) throws LdapException
1971 {
1972 if ( request == null )
1973 {
1974 String msg = I18n.msg( I18n.MSG_04103_NULL_REQUEST );
1975
1976 if ( LOG.isDebugEnabled() )
1977 {
1978 LOG.debug( msg );
1979 }
1980
1981 throw new IllegalArgumentException( msg );
1982 }
1983
1984 BindFuture bindFuture = bindAsync( request );
1985
1986
1987 try
1988 {
1989
1990
1991 BindResponse bindResponse = bindFuture.get( connectTimeout, TimeUnit.MILLISECONDS );
1992
1993 if ( bindResponse == null )
1994 {
1995
1996 if ( LOG.isErrorEnabled() )
1997 {
1998 LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Bind" ) );
1999 }
2000
2001 throw new LdapException( TIME_OUT_ERROR );
2002 }
2003
2004 if ( bindResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
2005 {
2006 authenticated.set( true );
2007
2008
2009 if ( LOG.isDebugEnabled() )
2010 {
2011 LOG.debug( I18n.msg( I18n.MSG_04101_BIND_SUCCESSFUL, bindResponse ) );
2012 }
2013 }
2014 else
2015 {
2016
2017 if ( LOG.isDebugEnabled() )
2018 {
2019 LOG.debug( I18n.msg( I18n.MSG_04100_BIND_FAIL, bindResponse ) );
2020 }
2021 }
2022
2023 return bindResponse;
2024 }
2025 catch ( Exception ie )
2026 {
2027
2028 LOG.error( NO_RESPONSE_ERROR, ie );
2029
2030 throw new LdapException( NO_RESPONSE_ERROR, ie );
2031 }
2032 }
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042 public BindResponse bind( SaslGssApiRequest request ) throws LdapException
2043 {
2044 if ( request == null )
2045 {
2046 String msg = I18n.msg( I18n.MSG_04103_NULL_REQUEST );
2047
2048 if ( LOG.isDebugEnabled() )
2049 {
2050 LOG.debug( msg );
2051 }
2052
2053 throw new IllegalArgumentException( msg );
2054 }
2055
2056 BindFuture bindFuture = bindAsync( request );
2057
2058
2059 try
2060 {
2061
2062
2063 BindResponse bindResponse = bindFuture.get( connectTimeout, TimeUnit.MILLISECONDS );
2064
2065 if ( bindResponse == null )
2066 {
2067
2068 if ( LOG.isErrorEnabled() )
2069 {
2070 LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Bind" ) );
2071 }
2072
2073 throw new LdapException( TIME_OUT_ERROR );
2074 }
2075
2076 if ( bindResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
2077 {
2078 authenticated.set( true );
2079
2080
2081 if ( LOG.isDebugEnabled() )
2082 {
2083 LOG.debug( I18n.msg( I18n.MSG_04101_BIND_SUCCESSFUL, bindResponse ) );
2084 }
2085 }
2086 else
2087 {
2088
2089 if ( LOG.isDebugEnabled() )
2090 {
2091 LOG.debug( I18n.msg( I18n.MSG_04100_BIND_FAIL, bindResponse ) );
2092 }
2093 }
2094
2095 return bindResponse;
2096 }
2097 catch ( Exception ie )
2098 {
2099
2100 LOG.error( NO_RESPONSE_ERROR, ie );
2101
2102 throw new LdapException( NO_RESPONSE_ERROR, ie );
2103 }
2104 }
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114 public BindResponse bind( SaslExternalRequest request ) throws LdapException
2115 {
2116 if ( request == null )
2117 {
2118 String msg = I18n.msg( I18n.MSG_04103_NULL_REQUEST );
2119
2120 if ( LOG.isDebugEnabled() )
2121 {
2122 LOG.debug( msg );
2123 }
2124
2125 throw new IllegalArgumentException( msg );
2126 }
2127
2128 BindFuture bindFuture = bindAsync( request );
2129
2130
2131 try
2132 {
2133
2134
2135 BindResponse bindResponse = bindFuture.get( connectTimeout, TimeUnit.MILLISECONDS );
2136
2137 if ( bindResponse == null )
2138 {
2139
2140 if ( LOG.isErrorEnabled() )
2141 {
2142 LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Bind" ) );
2143 }
2144
2145 throw new LdapException( TIME_OUT_ERROR );
2146 }
2147
2148 if ( bindResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
2149 {
2150 authenticated.set( true );
2151
2152
2153 if ( LOG.isDebugEnabled() )
2154 {
2155 LOG.debug( I18n.msg( I18n.MSG_04101_BIND_SUCCESSFUL, bindResponse ) );
2156 }
2157 }
2158 else
2159 {
2160
2161 if ( LOG.isDebugEnabled() )
2162 {
2163 LOG.debug( I18n.msg( I18n.MSG_04100_BIND_FAIL, bindResponse ) );
2164 }
2165 }
2166
2167 return bindResponse;
2168 }
2169 catch ( Exception ie )
2170 {
2171
2172 LOG.error( NO_RESPONSE_ERROR, ie );
2173
2174 throw new LdapException( NO_RESPONSE_ERROR, ie );
2175 }
2176 }
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186 public BindFuture bindAsync( SaslGssApiRequest request )
2187 throws LdapException
2188 {
2189
2190 if ( request.getKrb5ConfFilePath() != null )
2191 {
2192
2193 System.setProperty( KRB5_CONF, request.getKrb5ConfFilePath() );
2194 }
2195 else if ( ( request.getRealmName() != null ) && ( request.getKdcHost() != null )
2196 && ( request.getKdcPort() != 0 ) )
2197 {
2198 try
2199 {
2200
2201 String krb5ConfPath = createKrb5ConfFile( request.getRealmName(), request.getKdcHost(),
2202 request.getKdcPort() );
2203 System.setProperty( KRB5_CONF, krb5ConfPath );
2204 }
2205 catch ( IOException ioe )
2206 {
2207 throw new LdapException( ioe );
2208 }
2209 }
2210 else
2211 {
2212
2213 System.clearProperty( KRB5_CONF );
2214 }
2215
2216
2217 if ( request.getLoginModuleConfiguration() != null )
2218 {
2219
2220 Configuration.setConfiguration( request.getLoginModuleConfiguration() );
2221 }
2222 else
2223 {
2224
2225 Configuration.setConfiguration( new Krb5LoginConfiguration() );
2226 }
2227
2228 try
2229 {
2230 System.setProperty( "javax.security.auth.useSubjectCredsOnly", "true" );
2231 LoginContext loginContext = new LoginContext( request.getLoginContextName(),
2232 new SaslCallbackHandler( request ) );
2233 loginContext.login();
2234
2235 final SaslGssApiRequest requetFinal = request;
2236 return ( BindFuture ) Subject.doAs( loginContext.getSubject(), new PrivilegedExceptionAction<Object>()
2237 {
2238 @Override
2239 public Object run() throws Exception
2240 {
2241 return bindSasl( requetFinal );
2242 }
2243 } );
2244 }
2245 catch ( Exception e )
2246 {
2247 connectionCloseFuture.complete( 0 );
2248 throw new LdapException( e );
2249 }
2250 }
2251
2252
2253
2254
2255
2256 @Override
2257 public EntryCursor search( Dn baseDn, String filter, SearchScope scope, String... attributes )
2258 throws LdapException
2259 {
2260 if ( baseDn == null )
2261 {
2262 if ( LOG.isDebugEnabled() )
2263 {
2264 LOG.debug( I18n.msg( I18n.MSG_04138_NULL_DN_SEARCH ) );
2265 }
2266
2267 throw new IllegalArgumentException( I18n.err( I18n.ERR_04129_NULL_BASE_DN ) );
2268 }
2269
2270
2271 SearchRequest searchRequest = new SearchRequestImpl();
2272
2273 searchRequest.setBase( baseDn );
2274 searchRequest.setFilter( filter );
2275 searchRequest.setScope( scope );
2276 searchRequest.addAttributes( attributes );
2277 searchRequest.setDerefAliases( AliasDerefMode.DEREF_ALWAYS );
2278
2279
2280 return new EntryCursorImpl( search( searchRequest ) );
2281 }
2282
2283
2284
2285
2286
2287 @Override
2288 public EntryCursor search( String baseDn, String filter, SearchScope scope, String... attributes )
2289 throws LdapException
2290 {
2291 return search( new Dn( baseDn ), filter, scope, attributes );
2292 }
2293
2294
2295
2296
2297
2298 @Override
2299 public SearchFuture searchAsync( Dn baseDn, String filter, SearchScope scope, String... attributes )
2300 throws LdapException
2301 {
2302
2303 SearchRequest searchRequest = new SearchRequestImpl();
2304
2305 searchRequest.setBase( baseDn );
2306 searchRequest.setFilter( filter );
2307 searchRequest.setScope( scope );
2308 searchRequest.addAttributes( attributes );
2309 searchRequest.setDerefAliases( AliasDerefMode.DEREF_ALWAYS );
2310
2311
2312 return searchAsync( searchRequest );
2313 }
2314
2315
2316
2317
2318
2319 @Override
2320 public SearchFuture searchAsync( String baseDn, String filter, SearchScope scope, String... attributes )
2321 throws LdapException
2322 {
2323 return searchAsync( new Dn( baseDn ), filter, scope, attributes );
2324 }
2325
2326
2327
2328
2329
2330 @Override
2331 public SearchFuture searchAsync( SearchRequest searchRequest ) throws LdapException
2332 {
2333 if ( searchRequest == null )
2334 {
2335 String msg = I18n.err( I18n.ERR_04130_CANNOT_PROCESS_NULL_SEARCH_REQ );
2336
2337 if ( LOG.isDebugEnabled() )
2338 {
2339 LOG.debug( msg );
2340 }
2341
2342 throw new IllegalArgumentException( msg );
2343 }
2344
2345 if ( searchRequest.getBase() == null )
2346 {
2347 String msg = I18n.err( I18n.ERR_04131_CANNOT_PROCESS_SEARCH_NULL_DN );
2348
2349 if ( LOG.isDebugEnabled() )
2350 {
2351 LOG.debug( msg );
2352 }
2353
2354 throw new IllegalArgumentException( msg );
2355 }
2356
2357
2358 connect();
2359
2360
2361 checkSession();
2362
2363 int newId = messageId.incrementAndGet();
2364 searchRequest.setMessageId( newId );
2365
2366 if ( searchRequest.isIgnoreReferrals() )
2367 {
2368
2369 searchRequest.addControl( new ManageDsaITImpl() );
2370 }
2371
2372 if ( LOG.isDebugEnabled() )
2373 {
2374 LOG.debug( I18n.msg( I18n.MSG_04104_SENDING_REQUEST, searchRequest ) );
2375 }
2376
2377 SearchFuture searchFuture = new SearchFuture( this, searchRequest.getMessageId() );
2378 addToFutureMap( searchRequest.getMessageId(), searchFuture );
2379
2380
2381 writeRequest( searchRequest );
2382
2383
2384 if ( searchFuture.isCancelled() )
2385 {
2386
2387 throw new LdapException( searchFuture.getCause() );
2388 }
2389
2390
2391 return searchFuture;
2392 }
2393
2394
2395
2396
2397
2398 @Override
2399 public SearchCursor search( SearchRequest searchRequest ) throws LdapException
2400 {
2401 if ( searchRequest == null )
2402 {
2403 String msg = I18n.err( I18n.ERR_04130_CANNOT_PROCESS_NULL_SEARCH_REQ );
2404
2405 if ( LOG.isDebugEnabled() )
2406 {
2407 LOG.debug( msg );
2408 }
2409
2410 throw new IllegalArgumentException( msg );
2411 }
2412 long localSearchTimeout = getTimeout( readOperationTimeout, searchRequest.getTimeLimit() );
2413 return search( searchRequest, localSearchTimeout );
2414 }
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424 public SearchCursor search( SearchRequest searchRequest, long localSearchTimeout ) throws LdapException
2425 {
2426 if ( searchRequest == null )
2427 {
2428 String msg = I18n.err( I18n.ERR_04130_CANNOT_PROCESS_NULL_SEARCH_REQ );
2429
2430 if ( LOG.isDebugEnabled() )
2431 {
2432 LOG.debug( msg );
2433 }
2434
2435 throw new IllegalArgumentException( msg );
2436 }
2437
2438 SearchFuture searchFuture = searchAsync( searchRequest );
2439
2440 return new SearchCursorImpl( searchFuture, localSearchTimeout, TimeUnit.MILLISECONDS );
2441 }
2442
2443
2444
2445
2446
2447
2448
2449 @Override
2450 public void unBind() throws LdapException
2451 {
2452
2453 checkSession();
2454
2455
2456
2457 int newId = messageId.incrementAndGet();
2458
2459
2460 UnbindRequest unbindRequest = new UnbindRequestImpl();
2461 unbindRequest.setMessageId( newId );
2462
2463 if ( LOG.isDebugEnabled() )
2464 {
2465 LOG.debug( I18n.msg( I18n.MSG_04132_SENDING_UNBIND, unbindRequest ) );
2466 }
2467
2468
2469
2470 WriteFuture unbindFuture = ioSession.write( unbindRequest );
2471
2472 unbindFuture.awaitUninterruptibly( sendTimeout );
2473
2474 try
2475 {
2476 connectionCloseFuture.get( closeTimeout, TimeUnit.MILLISECONDS );
2477 }
2478 catch ( TimeoutException | ExecutionException | InterruptedException e )
2479 {
2480 if ( LOG.isDebugEnabled() )
2481 {
2482 LOG.debug( I18n.msg( I18n.MSH_04178_CLOSE_LATCH_ABORTED ) );
2483 }
2484 }
2485
2486
2487 if ( LOG.isDebugEnabled() )
2488 {
2489 LOG.debug( I18n.msg( I18n.MSG_04133_UNBINDSUCCESSFUL ) );
2490 }
2491 }
2492
2493
2494
2495
2496
2497
2498
2499 public void setConnector( IoConnector connector )
2500 {
2501 this.connector = connector;
2502 }
2503
2504
2505
2506
2507
2508 @Override
2509 public void setTimeOut( long timeout )
2510 {
2511 if ( timeout <= 0 )
2512 {
2513
2514 setAllTimeOuts( 1000L * 60L * 60L * 24L * 365L * 100L );
2515 }
2516 else
2517 {
2518 setAllTimeOuts( timeout );
2519 }
2520 }
2521
2522 private void setAllTimeOuts( long timeout )
2523 {
2524 this.timeout = timeout;
2525
2526
2527 this.connectTimeout = timeout;
2528 this.writeOperationTimeout = timeout;
2529 this.readOperationTimeout = timeout;
2530 this.closeTimeout = timeout;
2531 this.sendTimeout = timeout;
2532 }
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542 @Override
2543 public void exceptionCaught( IoSession session, Throwable cause ) throws Exception
2544 {
2545 if ( LOG.isWarnEnabled() )
2546 {
2547 LOG.warn( cause.getMessage(), cause );
2548 }
2549
2550 session.setAttribute( EXCEPTION_KEY, cause );
2551
2552 if ( cause instanceof ProtocolEncoderException )
2553 {
2554 Throwable realCause = ( ( ProtocolEncoderException ) cause ).getCause();
2555
2556 if ( realCause instanceof MessageEncoderException )
2557 {
2558 int messageId = ( ( MessageEncoderException ) realCause ).getMessageId();
2559
2560 ResponseFuture<?> response = futureMap.get( messageId );
2561 response.cancel( true );
2562 response.setCause( realCause );
2563 }
2564 }
2565
2566 session.closeNow();
2567 }
2568
2569
2570
2571
2572
2573
2574
2575
2576 private boolean isNoticeOfDisconnect( Message message )
2577 {
2578 if ( message instanceof ExtendedResponse )
2579 {
2580 String responseName = ( ( ExtendedResponse ) message ).getResponseName();
2581
2582 if ( NoticeOfDisconnect.EXTENSION_OID.equals( responseName ) )
2583 {
2584 return true;
2585 }
2586 }
2587
2588 return false;
2589 }
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600 private void addReceived( AddResponse addResponse, AddFuture addFuture, int responseId ) throws InterruptedException
2601 {
2602
2603 if ( LOG.isDebugEnabled() )
2604 {
2605 if ( addResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
2606 {
2607
2608 LOG.debug( I18n.msg( I18n.MSG_04108_ADD_SUCCESSFUL, addResponse ) );
2609 }
2610 else
2611 {
2612
2613 LOG.debug( I18n.msg( I18n.MSG_04107_ADD_FAILED, addResponse ) );
2614 }
2615 }
2616
2617
2618 addFuture.set( addResponse );
2619
2620
2621 removeFromFutureMaps( responseId );
2622 }
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633 private void bindReceived( BindResponse bindResponse, BindFuture bindFuture, int responseId )
2634 throws InterruptedException
2635 {
2636
2637 if ( bindResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
2638 {
2639 authenticated.set( true );
2640
2641
2642 if ( LOG.isDebugEnabled() )
2643 {
2644 LOG.debug( I18n.msg( I18n.MSG_04101_BIND_SUCCESSFUL, bindResponse ) );
2645 }
2646 }
2647 else
2648 {
2649
2650 if ( LOG.isDebugEnabled() )
2651 {
2652 LOG.debug( I18n.msg( I18n.MSG_04100_BIND_FAIL, bindResponse ) );
2653 }
2654 }
2655
2656
2657 bindFuture.set( bindResponse );
2658
2659
2660 removeFromFutureMaps( responseId );
2661 }
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672 private void compareReceived( CompareResponse compareResponse, CompareFuture compareFuture, int responseId )
2673 throws InterruptedException
2674 {
2675
2676 if ( LOG.isDebugEnabled() )
2677 {
2678 if ( compareResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
2679 {
2680
2681 LOG.debug( I18n.msg( I18n.MSG_04114_COMPARE_SUCCESSFUL, compareResponse ) );
2682 }
2683 else
2684 {
2685
2686 LOG.debug( I18n.msg( I18n.MSG_04113_COMPARE_FAILED, compareResponse ) );
2687 }
2688 }
2689
2690
2691 compareFuture.set( compareResponse );
2692
2693
2694 removeFromFutureMaps( responseId );
2695 }
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706 private void deleteReceived( DeleteResponse deleteResponse, DeleteFuture deleteFuture, int responseId )
2707 throws InterruptedException
2708 {
2709 if ( LOG.isDebugEnabled() )
2710 {
2711 if ( deleteResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
2712 {
2713
2714 LOG.debug( I18n.msg( I18n.MSG_04116_DELETE_SUCCESSFUL, deleteResponse ) );
2715 }
2716 else
2717 {
2718
2719 LOG.debug( I18n.msg( I18n.MSG_04115_DELETE_FAILED, deleteResponse ) );
2720 }
2721 }
2722
2723
2724 deleteFuture.set( deleteResponse );
2725
2726
2727 removeFromFutureMaps( responseId );
2728 }
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740 private void extendedReceived( ExtendedResponse extendedResponse, ExtendedFuture extendedFuture, int responseId )
2741 throws InterruptedException, DecoderException
2742 {
2743 if ( LOG.isDebugEnabled() )
2744 {
2745 if ( extendedResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
2746 {
2747
2748 LOG.debug( I18n.msg( I18n.MSG_04118_EXTENDED_SUCCESSFUL, extendedResponse ) );
2749 }
2750 else
2751 {
2752
2753 LOG.debug( I18n.msg( I18n.MSG_04117_EXTENDED_FAILED, extendedResponse ) );
2754 }
2755 }
2756
2757 extendedResponse = handleOpaqueResponse( extendedResponse, extendedFuture );
2758
2759
2760 extendedFuture.set( extendedResponse );
2761
2762
2763 removeFromFutureMaps( responseId );
2764 }
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774 private void intermediateReceived( IntermediateResponse intermediateResponse, ResponseFuture<? extends Response> responseFuture )
2775 throws InterruptedException
2776 {
2777
2778 if ( responseFuture instanceof SearchFuture )
2779 {
2780 ( ( SearchFuture ) responseFuture ).set( intermediateResponse );
2781 }
2782 else if ( responseFuture instanceof ExtendedFuture )
2783 {
2784 ( ( ExtendedFuture ) responseFuture ).set( intermediateResponse );
2785 }
2786 else
2787 {
2788
2789 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04111_UNKNOWN_RESPONSE_FUTURE_TYPE,
2790 responseFuture.getClass().getName() ) );
2791 }
2792
2793
2794 }
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805 private void modifyReceived( ModifyResponse modifyResponse, ModifyFuture modifyFuture, int responseId )
2806 throws InterruptedException
2807 {
2808 if ( LOG.isDebugEnabled() )
2809 {
2810 if ( modifyResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
2811 {
2812
2813 if ( LOG.isDebugEnabled() )
2814 {
2815 LOG.debug( I18n.msg( I18n.MSG_04123_MODIFY_SUCCESSFUL, modifyResponse ) );
2816 }
2817 }
2818 else
2819 {
2820
2821 if ( LOG.isDebugEnabled() )
2822 {
2823 LOG.debug( I18n.msg( I18n.MSG_04122_MODIFY_FAILED, modifyResponse ) );
2824 }
2825 }
2826 }
2827
2828
2829 modifyFuture.set( modifyResponse );
2830
2831
2832 removeFromFutureMaps( responseId );
2833 }
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844 private void modifyDnReceived( ModifyDnResponse modifyDnResponse, ModifyDnFuture modifyDnFuture, int responseId )
2845 throws InterruptedException
2846 {
2847 if ( LOG.isDebugEnabled() )
2848 {
2849 if ( modifyDnResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
2850 {
2851
2852 LOG.debug( I18n.msg( I18n.MSG_04125_MODIFYDN_SUCCESSFUL, modifyDnResponse ) );
2853 }
2854 else
2855 {
2856
2857 LOG.debug( I18n.msg( I18n.MSG_04124_MODIFYDN_FAILED, modifyDnResponse ) );
2858 }
2859 }
2860
2861
2862 modifyDnFuture.set( modifyDnResponse );
2863
2864
2865 removeFromFutureMaps( responseId );
2866 }
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877 private void searchResultDoneReceived( SearchResultDone searchResultDone, SearchFuture searchFuture,
2878 int responseId ) throws InterruptedException
2879 {
2880 if ( LOG.isDebugEnabled() )
2881 {
2882 if ( searchResultDone.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
2883 {
2884
2885 LOG.debug( I18n.msg( I18n.MSG_04131_SEARCH_SUCCESSFUL, searchResultDone ) );
2886 }
2887 else
2888 {
2889
2890 LOG.debug( I18n.msg( I18n.MSG_04129_SEARCH_FAILED, searchResultDone ) );
2891 }
2892 }
2893
2894
2895 searchFuture.set( searchResultDone );
2896
2897
2898 removeFromFutureMaps( responseId );
2899 }
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910 private void searchResultEntryReceived( SearchResultEntry searchResultEntry, SearchFuture searchFuture )
2911 throws InterruptedException, LdapException
2912 {
2913 if ( schemaManager != null )
2914 {
2915 searchResultEntry.setEntry( new DefaultEntry( schemaManager, searchResultEntry.getEntry() ) );
2916 }
2917
2918 if ( LOG.isDebugEnabled() )
2919 {
2920 LOG.debug( I18n.msg( I18n.MSG_04128_SEARCH_ENTRY_FOUND, searchResultEntry ) );
2921 }
2922
2923
2924 searchFuture.set( searchResultEntry );
2925 }
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935 private void searchResultReferenceReceived( SearchResultReference searchResultReference, SearchFuture searchFuture )
2936 throws InterruptedException
2937 {
2938 if ( LOG.isDebugEnabled() )
2939 {
2940 LOG.debug( I18n.msg( I18n.MSG_04130_SEARCH_REFERENCE_FOUND, searchResultReference ) );
2941 }
2942
2943
2944 searchFuture.set( searchResultReference );
2945 }
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956 @Override
2957 public void messageReceived( IoSession session, Object message ) throws Exception
2958 {
2959
2960 Response response = ( Response ) message;
2961
2962 if ( LOG.isDebugEnabled() )
2963 {
2964 LOG.debug( I18n.msg( I18n.MSG_04142_MESSAGE_RECEIVED, response ) );
2965 }
2966
2967 int responseId = response.getMessageId();
2968
2969
2970
2971 ResponseFuture<? extends Response> responseFuture = peekFromFutureMap( responseId );
2972
2973 boolean isNoD = isNoticeOfDisconnect( response );
2974
2975 if ( ( responseFuture == null ) && !isNoD )
2976 {
2977 if ( LOG.isInfoEnabled() )
2978 {
2979 LOG.info( I18n.msg( I18n.MSG_04166_NO_FUTURE_ASSOCIATED_TO_MSG_ID_IGNORING, responseId ) );
2980 }
2981
2982 return;
2983 }
2984
2985 if ( isNoD )
2986 {
2987
2988 session.closeNow();
2989
2990 return;
2991 }
2992
2993 switch ( response.getType() )
2994 {
2995 case ADD_RESPONSE:
2996 addReceived( ( AddResponse ) response, ( AddFuture ) responseFuture, responseId );
2997
2998 break;
2999
3000 case BIND_RESPONSE:
3001 bindReceived( ( BindResponse ) response, ( BindFuture ) responseFuture, responseId );
3002
3003 break;
3004
3005 case COMPARE_RESPONSE:
3006 compareReceived( ( CompareResponse ) response, ( CompareFuture ) responseFuture, responseId );
3007
3008 break;
3009
3010 case DEL_RESPONSE:
3011 deleteReceived( ( DeleteResponse ) response, ( DeleteFuture ) responseFuture, responseId );
3012
3013 break;
3014
3015 case EXTENDED_RESPONSE:
3016 extendedReceived( ( ExtendedResponse ) response, ( ExtendedFuture ) responseFuture, responseId );
3017
3018 break;
3019
3020 case INTERMEDIATE_RESPONSE:
3021 intermediateReceived( ( IntermediateResponse ) response, responseFuture );
3022
3023 break;
3024
3025 case MODIFY_RESPONSE:
3026 modifyReceived( ( ModifyResponse ) response, ( ModifyFuture ) responseFuture, responseId );
3027
3028 break;
3029
3030 case MODIFYDN_RESPONSE:
3031 modifyDnReceived( ( ModifyDnResponse ) response, ( ModifyDnFuture ) responseFuture, responseId );
3032
3033 break;
3034
3035 case SEARCH_RESULT_DONE:
3036 searchResultDoneReceived( ( SearchResultDone ) response, ( SearchFuture ) responseFuture, responseId );
3037
3038 break;
3039
3040 case SEARCH_RESULT_ENTRY:
3041 searchResultEntryReceived( ( SearchResultEntry ) response, ( SearchFuture ) responseFuture );
3042
3043 break;
3044
3045 case SEARCH_RESULT_REFERENCE:
3046 searchResultReferenceReceived( ( SearchResultReference ) response, ( SearchFuture ) responseFuture );
3047
3048 break;
3049
3050 default:
3051 throw new IllegalStateException( I18n.err( I18n.ERR_04132_UNEXPECTED_RESPONSE_TYPE, response.getType() ) );
3052 }
3053 }
3054
3055
3056 private ExtendedResponse handleOpaqueResponse( ExtendedResponse extendedResponse, ExtendedFuture extendedFuture )
3057 throws DecoderException
3058 {
3059 if ( ( extendedResponse instanceof OpaqueExtendedResponse )
3060 && ( Strings.isEmpty( extendedResponse.getResponseName() ) ) )
3061 {
3062 ExtendedOperationFactory factory = codec.getExtendedResponseFactories().
3063 get( extendedFuture.getExtendedRequest().getRequestName() );
3064
3065 byte[] responseValue = ( ( OpaqueExtendedResponse ) extendedResponse ).getResponseValue();
3066
3067 ExtendedResponse response;
3068 if ( responseValue != null )
3069 {
3070 response = factory.newResponse( responseValue );
3071 }
3072 else
3073 {
3074 response = factory.newResponse();
3075 }
3076
3077
3078 for ( Control control : extendedResponse.getControls().values() )
3079 {
3080 response.addControl( control );
3081 }
3082
3083
3084 response.getLdapResult().setDiagnosticMessage( extendedResponse.getLdapResult().getDiagnosticMessage() );
3085 response.getLdapResult().setMatchedDn( extendedResponse.getLdapResult().getMatchedDn() );
3086 response.getLdapResult().setReferral( extendedResponse.getLdapResult().getReferral() );
3087 response.getLdapResult().setResultCode( extendedResponse.getLdapResult().getResultCode() );
3088
3089 return response;
3090 }
3091 else
3092 {
3093 return extendedResponse;
3094 }
3095 }
3096
3097
3098
3099
3100 @Override
3101 public void modify( Entry entry, ModificationOperation modOp ) throws LdapException
3102 {
3103 if ( entry == null )
3104 {
3105 if ( LOG.isDebugEnabled() )
3106 {
3107 LOG.debug( I18n.msg( I18n.MSG_04140_NULL_ENTRY_MODIFY ) );
3108 }
3109
3110 throw new IllegalArgumentException( I18n.err( I18n.ERR_04133_NULL_MODIFIED_ENTRY ) );
3111 }
3112
3113 ModifyRequest modReq = new ModifyRequestImpl();
3114 modReq.setName( entry.getDn() );
3115
3116 Iterator<Attribute> itr = entry.iterator();
3117
3118 while ( itr.hasNext() )
3119 {
3120 modReq.addModification( itr.next(), modOp );
3121 }
3122
3123 ModifyResponse modifyResponse = modify( modReq );
3124
3125 processResponse( modifyResponse );
3126 }
3127
3128
3129
3130
3131
3132 @Override
3133 public void modify( Dn dn, Modification... modifications ) throws LdapException
3134 {
3135 if ( dn == null )
3136 {
3137 if ( LOG.isDebugEnabled() )
3138 {
3139 LOG.debug( I18n.msg( I18n.MSG_04139_NULL_DN_MODIFY ) );
3140 }
3141
3142 throw new IllegalArgumentException( I18n.err( I18n.ERR_04134_NULL_MODIFIED_DN ) );
3143 }
3144
3145 if ( ( modifications == null ) || ( modifications.length == 0 ) )
3146 {
3147 String msg = I18n.err( I18n.ERR_04135_CANNOT_PROCESS_NO_MODIFICATION_MOD );
3148
3149 if ( LOG.isDebugEnabled() )
3150 {
3151 LOG.debug( msg );
3152 }
3153
3154 throw new IllegalArgumentException( msg );
3155 }
3156
3157 ModifyRequest modReq = new ModifyRequestImpl();
3158 modReq.setName( dn );
3159
3160 for ( Modification modification : modifications )
3161 {
3162 modReq.addModification( modification );
3163 }
3164
3165 ModifyResponse modifyResponse = modify( modReq );
3166
3167 processResponse( modifyResponse );
3168 }
3169
3170
3171
3172
3173
3174 @Override
3175 public void modify( String dn, Modification... modifications ) throws LdapException
3176 {
3177 modify( new Dn( dn ), modifications );
3178 }
3179
3180
3181
3182
3183
3184 @Override
3185 public ModifyResponse modify( ModifyRequest modRequest ) throws LdapException
3186 {
3187 if ( modRequest == null )
3188 {
3189 String msg = I18n.err( I18n.ERR_04136_CANNOT_PROCESS_NULL_MOD_REQ );
3190
3191 if ( LOG.isDebugEnabled() )
3192 {
3193 LOG.debug( msg );
3194 }
3195
3196 throw new IllegalArgumentException( msg );
3197 }
3198
3199 ModifyFuture modifyFuture = modifyAsync( modRequest );
3200
3201
3202 try
3203 {
3204
3205
3206 ModifyResponse modifyResponse = modifyFuture.get( writeOperationTimeout, TimeUnit.MILLISECONDS );
3207
3208 if ( modifyResponse == null )
3209 {
3210
3211 if ( LOG.isErrorEnabled() )
3212 {
3213 LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Modify" ) );
3214 }
3215
3216 throw new LdapException( TIME_OUT_ERROR );
3217 }
3218
3219 if ( modifyResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
3220 {
3221
3222 if ( LOG.isDebugEnabled() )
3223 {
3224 LOG.debug( I18n.msg( I18n.MSG_04123_MODIFY_SUCCESSFUL, modifyResponse ) );
3225 }
3226 }
3227 else
3228 {
3229 if ( modifyResponse instanceof ModifyNoDResponse )
3230 {
3231
3232 throw new LdapException( modifyResponse.getLdapResult().getDiagnosticMessage() );
3233 }
3234
3235
3236 if ( LOG.isDebugEnabled() )
3237 {
3238 LOG.debug( I18n.msg( I18n.MSG_04122_MODIFY_FAILED, modifyResponse ) );
3239 }
3240 }
3241
3242 return modifyResponse;
3243 }
3244 catch ( Exception ie )
3245 {
3246
3247 LOG.error( NO_RESPONSE_ERROR, ie );
3248
3249
3250 if ( !modifyFuture.isCancelled() )
3251 {
3252 abandon( modRequest.getMessageId() );
3253 }
3254
3255 throw new LdapException( ie.getMessage(), ie );
3256 }
3257 }
3258
3259
3260
3261
3262
3263 @Override
3264 public ModifyFuture modifyAsync( ModifyRequest modRequest ) throws LdapException
3265 {
3266 if ( modRequest == null )
3267 {
3268 String msg = I18n.err( I18n.ERR_04136_CANNOT_PROCESS_NULL_MOD_REQ );
3269
3270 if ( LOG.isDebugEnabled() )
3271 {
3272 LOG.debug( msg );
3273 }
3274
3275 throw new IllegalArgumentException( msg );
3276 }
3277
3278 if ( modRequest.getName() == null )
3279 {
3280 String msg = I18n.err( I18n.ERR_04137_CANNOT_PROCESS_MOD_NULL_DN );
3281
3282 if ( LOG.isDebugEnabled() )
3283 {
3284 LOG.debug( msg );
3285 }
3286
3287 throw new IllegalArgumentException( msg );
3288 }
3289
3290
3291 connect();
3292
3293 checkSession();
3294
3295 int newId = messageId.incrementAndGet();
3296 modRequest.setMessageId( newId );
3297
3298 ModifyFuture modifyFuture = new ModifyFuture( this, newId );
3299 addToFutureMap( newId, modifyFuture );
3300
3301
3302 writeRequest( modRequest );
3303
3304
3305 return modifyFuture;
3306 }
3307
3308
3309
3310
3311
3312 @Override
3313 public void rename( String entryDn, String newRdn ) throws LdapException
3314 {
3315 rename( entryDn, newRdn, true );
3316 }
3317
3318
3319
3320
3321
3322 @Override
3323 public void rename( Dn entryDn, Rdn newRdn ) throws LdapException
3324 {
3325 rename( entryDn, newRdn, true );
3326 }
3327
3328
3329
3330
3331
3332 @Override
3333 public void rename( String entryDn, String newRdn, boolean deleteOldRdn ) throws LdapException
3334 {
3335 if ( entryDn == null )
3336 {
3337 String msg = I18n.err( I18n.ERR_04138_CANNOT_PROCESS_RENAME_NULL_DN );
3338
3339 if ( LOG.isDebugEnabled() )
3340 {
3341 LOG.debug( msg );
3342 }
3343
3344 throw new IllegalArgumentException( msg );
3345 }
3346
3347 if ( newRdn == null )
3348 {
3349 String msg = I18n.err( I18n.ERR_04139_CANNOT_PROCESS_RENAME_NULL_RDN );
3350
3351 if ( LOG.isDebugEnabled() )
3352 {
3353 LOG.debug( msg );
3354 }
3355
3356 throw new IllegalArgumentException( msg );
3357 }
3358
3359 try
3360 {
3361 rename( new Dn( entryDn ), new Rdn( newRdn ), deleteOldRdn );
3362 }
3363 catch ( LdapInvalidDnException e )
3364 {
3365 LOG.error( e.getMessage(), e );
3366 throw new LdapException( e.getMessage(), e );
3367 }
3368 }
3369
3370
3371
3372
3373
3374 @Override
3375 public void rename( Dn entryDn, Rdn newRdn, boolean deleteOldRdn ) throws LdapException
3376 {
3377 if ( entryDn == null )
3378 {
3379 String msg = I18n.err( I18n.ERR_04138_CANNOT_PROCESS_RENAME_NULL_DN );
3380
3381 if ( LOG.isDebugEnabled() )
3382 {
3383 LOG.debug( msg );
3384 }
3385
3386 throw new IllegalArgumentException( msg );
3387 }
3388
3389 if ( newRdn == null )
3390 {
3391 String msg = I18n.err( I18n.ERR_04139_CANNOT_PROCESS_RENAME_NULL_RDN );
3392
3393 if ( LOG.isDebugEnabled() )
3394 {
3395 LOG.debug( msg );
3396 }
3397
3398 throw new IllegalArgumentException( msg );
3399 }
3400
3401 ModifyDnRequest modDnRequest = new ModifyDnRequestImpl();
3402 modDnRequest.setName( entryDn );
3403 modDnRequest.setNewRdn( newRdn );
3404 modDnRequest.setDeleteOldRdn( deleteOldRdn );
3405
3406 ModifyDnResponse modifyDnResponse = modifyDn( modDnRequest );
3407
3408 processResponse( modifyDnResponse );
3409 }
3410
3411
3412
3413
3414
3415 @Override
3416 public void move( String entryDn, String newSuperiorDn ) throws LdapException
3417 {
3418 if ( entryDn == null )
3419 {
3420 String msg = I18n.err( I18n.ERR_04140_CANNOT_PROCESS_MOVE_NULL_DN );
3421
3422 if ( LOG.isDebugEnabled() )
3423 {
3424 LOG.debug( msg );
3425 }
3426
3427 throw new IllegalArgumentException( msg );
3428 }
3429
3430 if ( newSuperiorDn == null )
3431 {
3432 String msg = I18n.err( I18n.ERR_04141_CANNOT_PROCESS_MOVE_NULL_SUPERIOR );
3433
3434 if ( LOG.isDebugEnabled() )
3435 {
3436 LOG.debug( msg );
3437 }
3438
3439 throw new IllegalArgumentException( msg );
3440 }
3441
3442 try
3443 {
3444 move( new Dn( entryDn ), new Dn( newSuperiorDn ) );
3445 }
3446 catch ( LdapInvalidDnException e )
3447 {
3448 LOG.error( e.getMessage(), e );
3449 throw new LdapException( e.getMessage(), e );
3450 }
3451 }
3452
3453
3454
3455
3456
3457 @Override
3458 public void move( Dn entryDn, Dn newSuperiorDn ) throws LdapException
3459 {
3460 if ( entryDn == null )
3461 {
3462 String msg = I18n.err( I18n.ERR_04140_CANNOT_PROCESS_MOVE_NULL_DN );
3463
3464 if ( LOG.isDebugEnabled() )
3465 {
3466 LOG.debug( msg );
3467 }
3468
3469 throw new IllegalArgumentException( msg );
3470 }
3471
3472 if ( newSuperiorDn == null )
3473 {
3474 String msg = I18n.err( I18n.ERR_04141_CANNOT_PROCESS_MOVE_NULL_SUPERIOR );
3475
3476 if ( LOG.isDebugEnabled() )
3477 {
3478 LOG.debug( msg );
3479 }
3480
3481 throw new IllegalArgumentException( msg );
3482 }
3483
3484 ModifyDnRequest modDnRequest = new ModifyDnRequestImpl();
3485 modDnRequest.setName( entryDn );
3486 modDnRequest.setNewSuperior( newSuperiorDn );
3487
3488 modDnRequest.setNewRdn( entryDn.getRdn() );
3489
3490 ModifyDnResponse modifyDnResponse = modifyDn( modDnRequest );
3491
3492 processResponse( modifyDnResponse );
3493 }
3494
3495
3496
3497
3498
3499 @Override
3500 public void moveAndRename( Dn entryDn, Dn newDn ) throws LdapException
3501 {
3502 moveAndRename( entryDn, newDn, true );
3503 }
3504
3505
3506
3507
3508
3509 @Override
3510 public void moveAndRename( String entryDn, String newDn ) throws LdapException
3511 {
3512 moveAndRename( new Dn( entryDn ), new Dn( newDn ), true );
3513 }
3514
3515
3516
3517
3518
3519 @Override
3520 public void moveAndRename( Dn entryDn, Dn newDn, boolean deleteOldRdn ) throws LdapException
3521 {
3522
3523 if ( entryDn == null )
3524 {
3525 throw new IllegalArgumentException( I18n.err( I18n.ERR_04142_NULL_ENTRY_DN ) );
3526 }
3527
3528 if ( entryDn.isRootDse() )
3529 {
3530 throw new IllegalArgumentException( I18n.err( I18n.ERR_04143_CANNOT_MOVE_ROOT_DSE ) );
3531 }
3532
3533 if ( newDn == null )
3534 {
3535 throw new IllegalArgumentException( I18n.err( I18n.ERR_04144_NULL_NEW_DN ) );
3536 }
3537
3538 if ( newDn.isRootDse() )
3539 {
3540 throw new IllegalArgumentException( I18n.err( I18n.ERR_04145_ROOT_DSE_CANNOT_BE_TARGET ) );
3541 }
3542
3543
3544 ModifyDnRequest modDnRequest = new ModifyDnRequestImpl();
3545 modDnRequest.setName( entryDn );
3546 modDnRequest.setNewRdn( newDn.getRdn() );
3547
3548
3549
3550
3551
3552
3553 Dn newDnParent = newDn.getParent();
3554 if ( newDnParent != null && !newDnParent.equals( entryDn.getParent() ) )
3555 {
3556 modDnRequest.setNewSuperior( newDnParent );
3557 }
3558
3559 modDnRequest.setDeleteOldRdn( deleteOldRdn );
3560
3561 ModifyDnResponse modifyDnResponse = modifyDn( modDnRequest );
3562
3563 processResponse( modifyDnResponse );
3564 }
3565
3566
3567
3568
3569
3570 @Override
3571 public void moveAndRename( String entryDn, String newDn, boolean deleteOldRdn ) throws LdapException
3572 {
3573 moveAndRename( new Dn( entryDn ), new Dn( newDn ), true );
3574 }
3575
3576
3577
3578
3579
3580 @Override
3581 public ModifyDnResponse modifyDn( ModifyDnRequest modDnRequest ) throws LdapException
3582 {
3583 if ( modDnRequest == null )
3584 {
3585 String msg = I18n.err( I18n.ERR_04145_ROOT_DSE_CANNOT_BE_TARGET );
3586
3587 if ( LOG.isDebugEnabled() )
3588 {
3589 LOG.debug( msg );
3590 }
3591
3592 throw new IllegalArgumentException( msg );
3593 }
3594
3595 ModifyDnFuture modifyDnFuture = modifyDnAsync( modDnRequest );
3596
3597
3598 try
3599 {
3600
3601
3602 ModifyDnResponse modifyDnResponse = modifyDnFuture.get( writeOperationTimeout, TimeUnit.MILLISECONDS );
3603
3604 if ( modifyDnResponse == null )
3605 {
3606
3607 if ( LOG.isErrorEnabled() )
3608 {
3609 LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "ModifyDn" ) );
3610 }
3611
3612 throw new LdapException( TIME_OUT_ERROR );
3613 }
3614
3615 if ( modifyDnResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
3616 {
3617
3618 if ( LOG.isDebugEnabled() )
3619 {
3620 LOG.debug( I18n.msg( I18n.MSG_04125_MODIFYDN_SUCCESSFUL, modifyDnResponse ) );
3621 }
3622 }
3623 else
3624 {
3625
3626 if ( LOG.isDebugEnabled() )
3627 {
3628 LOG.debug( I18n.msg( I18n.MSG_04124_MODIFYDN_FAILED, modifyDnResponse ) );
3629 }
3630 }
3631
3632 return modifyDnResponse;
3633 }
3634 catch ( Exception ie )
3635 {
3636
3637 LOG.error( NO_RESPONSE_ERROR, ie );
3638
3639
3640 if ( !modifyDnFuture.isCancelled() )
3641 {
3642 abandon( modDnRequest.getMessageId() );
3643 }
3644
3645 throw new LdapException( NO_RESPONSE_ERROR, ie );
3646 }
3647 }
3648
3649
3650
3651
3652
3653 @Override
3654 public ModifyDnFuture modifyDnAsync( ModifyDnRequest modDnRequest ) throws LdapException
3655 {
3656 if ( modDnRequest == null )
3657 {
3658 String msg = I18n.err( I18n.ERR_04145_ROOT_DSE_CANNOT_BE_TARGET );
3659
3660 if ( LOG.isDebugEnabled() )
3661 {
3662 LOG.debug( msg );
3663 }
3664
3665 throw new IllegalArgumentException( msg );
3666 }
3667
3668 if ( modDnRequest.getName() == null )
3669 {
3670 String msg = I18n.err( I18n.ERR_04137_CANNOT_PROCESS_MOD_NULL_DN );
3671
3672 if ( LOG.isDebugEnabled() )
3673 {
3674 LOG.debug( msg );
3675 }
3676
3677 throw new IllegalArgumentException( msg );
3678 }
3679
3680 if ( ( modDnRequest.getNewSuperior() == null ) && ( modDnRequest.getNewRdn() == null ) )
3681 {
3682 String msg = I18n.err( I18n.ERR_04147_CANNOT_PROCESS_MOD_NULL_DN_SUP );
3683
3684 if ( LOG.isDebugEnabled() )
3685 {
3686 LOG.debug( msg );
3687 }
3688
3689 throw new IllegalArgumentException( msg );
3690 }
3691
3692
3693 connect();
3694
3695 checkSession();
3696
3697 int newId = messageId.incrementAndGet();
3698 modDnRequest.setMessageId( newId );
3699
3700 ModifyDnFuture modifyDnFuture = new ModifyDnFuture( this, newId );
3701 addToFutureMap( newId, modifyDnFuture );
3702
3703
3704 writeRequest( modDnRequest );
3705
3706
3707 return modifyDnFuture;
3708 }
3709
3710
3711
3712
3713
3714 @Override
3715 public void delete( String dn ) throws LdapException
3716 {
3717 delete( new Dn( dn ) );
3718 }
3719
3720
3721
3722
3723
3724 @Override
3725 public void delete( Dn dn ) throws LdapException
3726 {
3727 DeleteRequest deleteRequest = new DeleteRequestImpl();
3728 deleteRequest.setName( dn );
3729
3730 DeleteResponse deleteResponse = delete( deleteRequest );
3731
3732 processResponse( deleteResponse );
3733 }
3734
3735
3736
3737
3738
3739
3740
3741
3742 public void deleteTree( Dn dn ) throws LdapException
3743 {
3744 if ( isControlSupported( TreeDelete.OID ) )
3745 {
3746 DeleteRequest deleteRequest = new DeleteRequestImpl();
3747 deleteRequest.setName( dn );
3748 deleteRequest.addControl( new TreeDeleteImpl() );
3749 DeleteResponse deleteResponse = delete( deleteRequest );
3750
3751 processResponse( deleteResponse );
3752 }
3753 else
3754 {
3755 String msg = I18n.err( I18n.ERR_04148_SUBTREE_CONTROL_NOT_SUPPORTED );
3756 LOG.error( msg );
3757 throw new LdapException( msg );
3758 }
3759 }
3760
3761
3762
3763
3764
3765
3766
3767
3768 public void deleteTree( String dn ) throws LdapException
3769 {
3770 try
3771 {
3772 String treeDeleteOid = "1.2.840.113556.1.4.805";
3773 Dn newDn = new Dn( dn );
3774
3775 if ( isControlSupported( treeDeleteOid ) )
3776 {
3777 DeleteRequest deleteRequest = new DeleteRequestImpl();
3778 deleteRequest.setName( newDn );
3779 deleteRequest.addControl( new OpaqueControl( treeDeleteOid ) );
3780 DeleteResponse deleteResponse = delete( deleteRequest );
3781
3782 processResponse( deleteResponse );
3783 }
3784 else
3785 {
3786 String msg = I18n.err( I18n.ERR_04148_SUBTREE_CONTROL_NOT_SUPPORTED );
3787 LOG.error( msg );
3788 throw new LdapException( msg );
3789 }
3790 }
3791 catch ( LdapInvalidDnException e )
3792 {
3793 LOG.error( e.getMessage(), e );
3794 throw new LdapException( e.getMessage(), e );
3795 }
3796 }
3797
3798
3799
3800
3801
3802 @Override
3803 public DeleteResponse delete( DeleteRequest deleteRequest ) throws LdapException
3804 {
3805 if ( deleteRequest == null )
3806 {
3807 String msg = I18n.err( I18n.ERR_04149_CANNOT_PROCESS_NULL_DEL_REQ );
3808
3809 if ( LOG.isDebugEnabled() )
3810 {
3811 LOG.debug( msg );
3812 }
3813
3814 throw new IllegalArgumentException( msg );
3815 }
3816
3817 DeleteFuture deleteFuture = deleteAsync( deleteRequest );
3818
3819
3820 try
3821 {
3822
3823
3824 DeleteResponse delResponse = deleteFuture.get( writeOperationTimeout, TimeUnit.MILLISECONDS );
3825
3826 if ( delResponse == null )
3827 {
3828
3829 if ( LOG.isErrorEnabled() )
3830 {
3831 LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Delete" ) );
3832 }
3833
3834 throw new LdapException( TIME_OUT_ERROR );
3835 }
3836
3837 if ( delResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
3838 {
3839
3840 if ( LOG.isDebugEnabled() )
3841 {
3842 LOG.debug( I18n.msg( I18n.MSG_04116_DELETE_SUCCESSFUL, delResponse ) );
3843 }
3844 }
3845 else
3846 {
3847
3848 if ( LOG.isDebugEnabled() )
3849 {
3850 LOG.debug( I18n.msg( I18n.MSG_04115_DELETE_FAILED, delResponse ) );
3851 }
3852 }
3853
3854 return delResponse;
3855 }
3856 catch ( Exception ie )
3857 {
3858
3859 LOG.error( NO_RESPONSE_ERROR, ie );
3860
3861
3862 if ( !deleteFuture.isCancelled() )
3863 {
3864 abandon( deleteRequest.getMessageId() );
3865 }
3866
3867 throw new LdapException( NO_RESPONSE_ERROR, ie );
3868 }
3869 }
3870
3871
3872
3873
3874
3875 @Override
3876 public DeleteFuture deleteAsync( DeleteRequest deleteRequest ) throws LdapException
3877 {
3878 if ( deleteRequest == null )
3879 {
3880 String msg = I18n.err( I18n.ERR_04149_CANNOT_PROCESS_NULL_DEL_REQ );
3881
3882 if ( LOG.isDebugEnabled() )
3883 {
3884 LOG.debug( msg );
3885 }
3886
3887 throw new IllegalArgumentException( msg );
3888 }
3889
3890 if ( deleteRequest.getName() == null )
3891 {
3892 String msg = I18n.err( I18n.ERR_04150_CANNOT_PROCESS_NULL_DEL_NULL_DN );
3893
3894 if ( LOG.isDebugEnabled() )
3895 {
3896 LOG.debug( msg );
3897 }
3898
3899 throw new IllegalArgumentException( msg );
3900 }
3901
3902
3903 connect();
3904
3905 checkSession();
3906
3907 int newId = messageId.incrementAndGet();
3908
3909 deleteRequest.setMessageId( newId );
3910
3911 DeleteFuture deleteFuture = new DeleteFuture( this, newId );
3912 addToFutureMap( newId, deleteFuture );
3913
3914
3915 writeRequest( deleteRequest );
3916
3917
3918 return deleteFuture;
3919 }
3920
3921
3922
3923
3924
3925 @Override
3926 public boolean compare( String dn, String attributeName, String value ) throws LdapException
3927 {
3928 return compare( new Dn( dn ), attributeName, value );
3929 }
3930
3931
3932
3933
3934
3935 @Override
3936 public boolean compare( String dn, String attributeName, byte[] value ) throws LdapException
3937 {
3938 return compare( new Dn( dn ), attributeName, value );
3939 }
3940
3941
3942
3943
3944
3945 @Override
3946 public boolean compare( String dn, String attributeName, Value value ) throws LdapException
3947 {
3948 return compare( new Dn( dn ), attributeName, value );
3949 }
3950
3951
3952
3953
3954
3955 @Override
3956 public boolean compare( Dn dn, String attributeName, String value ) throws LdapException
3957 {
3958 CompareRequest compareRequest = new CompareRequestImpl();
3959 compareRequest.setName( dn );
3960 compareRequest.setAttributeId( attributeName );
3961 compareRequest.setAssertionValue( value );
3962
3963 CompareResponse compareResponse = compare( compareRequest );
3964
3965 return processResponse( compareResponse );
3966 }
3967
3968
3969
3970
3971
3972 @Override
3973 public boolean compare( Dn dn, String attributeName, byte[] value ) throws LdapException
3974 {
3975 CompareRequest compareRequest = new CompareRequestImpl();
3976 compareRequest.setName( dn );
3977 compareRequest.setAttributeId( attributeName );
3978 compareRequest.setAssertionValue( value );
3979
3980 CompareResponse compareResponse = compare( compareRequest );
3981
3982 return processResponse( compareResponse );
3983 }
3984
3985
3986
3987
3988
3989 @Override
3990 public boolean compare( Dn dn, String attributeName, Value value ) throws LdapException
3991 {
3992 CompareRequest compareRequest = new CompareRequestImpl();
3993 compareRequest.setName( dn );
3994 compareRequest.setAttributeId( attributeName );
3995
3996 if ( value.isHumanReadable() )
3997 {
3998 compareRequest.setAssertionValue( value.getString() );
3999 }
4000 else
4001 {
4002 compareRequest.setAssertionValue( value.getBytes() );
4003 }
4004
4005 CompareResponse compareResponse = compare( compareRequest );
4006
4007 return processResponse( compareResponse );
4008 }
4009
4010
4011
4012
4013
4014 @Override
4015 public CompareResponse compare( CompareRequest compareRequest ) throws LdapException
4016 {
4017 if ( compareRequest == null )
4018 {
4019 String msg = I18n.err( I18n.ERR_04151_CANNOT_PROCESS_NULL_COMP_REQ );
4020
4021 if ( LOG.isDebugEnabled() )
4022 {
4023 LOG.debug( msg );
4024 }
4025
4026 throw new IllegalArgumentException( msg );
4027 }
4028
4029 CompareFuture compareFuture = compareAsync( compareRequest );
4030
4031
4032 try
4033 {
4034
4035
4036 CompareResponse compareResponse = compareFuture.get( readOperationTimeout, TimeUnit.MILLISECONDS );
4037
4038 if ( compareResponse == null )
4039 {
4040
4041 if ( LOG.isErrorEnabled() )
4042 {
4043 LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Compare" ) );
4044 }
4045
4046 throw new LdapException( TIME_OUT_ERROR );
4047 }
4048
4049 if ( compareResponse.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
4050 {
4051
4052 if ( LOG.isDebugEnabled() )
4053 {
4054 LOG.debug( I18n.msg( I18n.MSG_04114_COMPARE_SUCCESSFUL, compareResponse ) );
4055 }
4056 }
4057 else
4058 {
4059
4060 if ( LOG.isDebugEnabled() )
4061 {
4062 LOG.debug( I18n.msg( I18n.MSG_04113_COMPARE_FAILED, compareResponse ) );
4063 }
4064 }
4065
4066 return compareResponse;
4067 }
4068 catch ( Exception ie )
4069 {
4070
4071 LOG.error( NO_RESPONSE_ERROR, ie );
4072
4073
4074 if ( !compareFuture.isCancelled() )
4075 {
4076 abandon( compareRequest.getMessageId() );
4077 }
4078
4079 throw new LdapException( NO_RESPONSE_ERROR, ie );
4080 }
4081 }
4082
4083
4084
4085
4086
4087 @Override
4088 public CompareFuture compareAsync( CompareRequest compareRequest ) throws LdapException
4089 {
4090 if ( compareRequest == null )
4091 {
4092 String msg = I18n.err( I18n.ERR_04151_CANNOT_PROCESS_NULL_COMP_REQ );
4093
4094 if ( LOG.isDebugEnabled() )
4095 {
4096 LOG.debug( msg );
4097 }
4098
4099 throw new IllegalArgumentException( msg );
4100 }
4101
4102 if ( compareRequest.getName() == null )
4103 {
4104 String msg = I18n.err( I18n.ERR_04152_CANNOT_PROCESS_NULL_DN_COMP_REQ );
4105
4106 if ( LOG.isDebugEnabled() )
4107 {
4108 LOG.debug( msg );
4109 }
4110
4111 throw new IllegalArgumentException( msg );
4112 }
4113
4114
4115 connect();
4116
4117 checkSession();
4118
4119 int newId = messageId.incrementAndGet();
4120
4121 compareRequest.setMessageId( newId );
4122
4123 CompareFuture compareFuture = new CompareFuture( this, newId );
4124 addToFutureMap( newId, compareFuture );
4125
4126
4127 writeRequest( compareRequest );
4128
4129
4130 return compareFuture;
4131 }
4132
4133
4134
4135
4136
4137 @Override
4138 public ExtendedResponse extended( String oid ) throws LdapException
4139 {
4140 return extended( oid, null );
4141 }
4142
4143
4144
4145
4146
4147 @Override
4148 public ExtendedResponse extended( String oid, byte[] value ) throws LdapException
4149 {
4150 try
4151 {
4152 return extended( Oid.fromString( oid ), value );
4153 }
4154 catch ( DecoderException e )
4155 {
4156 String msg = I18n.err( I18n.ERR_04153_OID_DECODING_FAILURE, oid );
4157 LOG.error( msg );
4158 throw new LdapException( msg, e );
4159 }
4160 }
4161
4162
4163
4164
4165
4166 @Override
4167 public ExtendedResponse extended( Oid oid ) throws LdapException
4168 {
4169 return extended( oid, null );
4170 }
4171
4172
4173
4174
4175
4176 @Override
4177 public ExtendedResponse extended( Oid oid, byte[] value ) throws LdapException
4178 {
4179 Map<String, ExtendedOperationFactory> factories = LdapApiServiceFactory.getSingleton().getExtendedRequestFactories();
4180 String oidStr = oid.toString();
4181
4182 ExtendedOperationFactory factory = factories.get( oidStr );
4183
4184 if ( factory != null )
4185 {
4186 try
4187 {
4188 if ( value == null )
4189 {
4190 return extended( factory.newRequest() );
4191 }
4192 else
4193 {
4194 return extended( factory.newRequest( value ) );
4195 }
4196 }
4197 catch ( DecoderException de )
4198 {
4199 throw new LdapNoSuchObjectException( de.getMessage() );
4200 }
4201 }
4202 else
4203 {
4204 return extended( new OpaqueExtendedRequest( oidStr, value ) );
4205 }
4206 }
4207
4208
4209
4210
4211
4212 @Override
4213 public ExtendedResponse extended( ExtendedRequest extendedRequest ) throws LdapException
4214 {
4215 if ( extendedRequest == null )
4216 {
4217 String msg = I18n.err( I18n.ERR_04154_CANNOT_PROCESS_NULL_EXT_REQ );
4218
4219 if ( LOG.isDebugEnabled() )
4220 {
4221 LOG.debug( msg );
4222 }
4223
4224 throw new IllegalArgumentException( msg );
4225 }
4226
4227 ExtendedFuture extendedFuture = extendedAsync( extendedRequest );
4228
4229
4230 try
4231 {
4232
4233
4234 ExtendedResponse response = ( ExtendedResponse ) extendedFuture
4235 .get( timeout, TimeUnit.MILLISECONDS );
4236
4237 if ( response == null )
4238 {
4239
4240 if ( LOG.isErrorEnabled() )
4241 {
4242 LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Extended" ) );
4243 }
4244
4245 throw new LdapException( TIME_OUT_ERROR );
4246 }
4247
4248 if ( response.getLdapResult().getResultCode() == ResultCodeEnum.SUCCESS )
4249 {
4250
4251 if ( LOG.isDebugEnabled() )
4252 {
4253 LOG.debug( I18n.msg( I18n.MSG_04118_EXTENDED_SUCCESSFUL, response ) );
4254 }
4255 }
4256 else
4257 {
4258
4259 if ( LOG.isDebugEnabled() )
4260 {
4261 LOG.debug( I18n.msg( I18n.MSG_04117_EXTENDED_FAILED, response ) );
4262 }
4263 }
4264
4265
4266 if ( Strings.isEmpty( response.getResponseName() ) )
4267 {
4268 response.setResponseName( extendedRequest.getRequestName() );
4269 }
4270
4271
4272 return response;
4273 }
4274 catch ( Exception ie )
4275 {
4276 if ( ie instanceof LdapException )
4277 {
4278 throw ( LdapException ) ie;
4279 }
4280
4281
4282 LOG.error( NO_RESPONSE_ERROR, ie );
4283
4284
4285 if ( !extendedFuture.isCancelled() )
4286 {
4287 abandon( extendedRequest.getMessageId() );
4288 }
4289
4290 throw new LdapException( NO_RESPONSE_ERROR, ie );
4291 }
4292 }
4293
4294
4295
4296
4297
4298 @Override
4299 public ExtendedFuture extendedAsync( ExtendedRequest extendedRequest ) throws LdapException
4300 {
4301 if ( extendedRequest == null )
4302 {
4303 String msg = I18n.err( I18n.ERR_04154_CANNOT_PROCESS_NULL_EXT_REQ );
4304
4305 if ( LOG.isDebugEnabled() )
4306 {
4307 LOG.debug( msg );
4308 }
4309
4310 throw new IllegalArgumentException( msg );
4311 }
4312
4313
4314 connect();
4315
4316 checkSession();
4317
4318 int newId = messageId.incrementAndGet();
4319
4320 extendedRequest.setMessageId( newId );
4321 ExtendedFuture extendedFuture = new ExtendedFuture( this, newId );
4322 extendedFuture.setExtendedRequest( extendedRequest );
4323 addToFutureMap( newId, extendedFuture );
4324
4325
4326 writeRequest( extendedRequest );
4327
4328
4329 return extendedFuture;
4330 }
4331
4332
4333
4334
4335
4336 @Override
4337 public boolean exists( String dn ) throws LdapException
4338 {
4339 return exists( new Dn( dn ) );
4340 }
4341
4342
4343
4344
4345
4346 @Override
4347 public boolean exists( Dn dn ) throws LdapException
4348 {
4349 try
4350 {
4351 Entry entry = lookup( dn, SchemaConstants.NO_ATTRIBUTE_ARRAY );
4352
4353 return entry != null;
4354 }
4355 catch ( LdapNoPermissionException lnpe )
4356 {
4357
4358 return false;
4359 }
4360 catch ( LdapException le )
4361 {
4362 throw le;
4363 }
4364 }
4365
4366
4367
4368
4369
4370 @Override
4371 public Entry getRootDse() throws LdapException
4372 {
4373 return lookup( Dn.ROOT_DSE, SchemaConstants.ALL_ATTRIBUTES_ARRAY );
4374 }
4375
4376
4377
4378
4379
4380 @Override
4381 public Entry getRootDse( String... attributes ) throws LdapException
4382 {
4383 return lookup( Dn.ROOT_DSE, attributes );
4384 }
4385
4386
4387
4388
4389
4390 @Override
4391 public Entry lookup( Dn dn ) throws LdapException
4392 {
4393 return lookup( dn, SchemaConstants.ALL_USER_ATTRIBUTES_ARRAY );
4394 }
4395
4396
4397
4398
4399
4400 @Override
4401 public Entry lookup( String dn ) throws LdapException
4402 {
4403 return lookup( dn, SchemaConstants.ALL_USER_ATTRIBUTES_ARRAY );
4404 }
4405
4406
4407
4408
4409
4410 @Override
4411 public Entry lookup( Dn dn, String... attributes ) throws LdapException
4412 {
4413 return lookup( dn, null, attributes );
4414 }
4415
4416
4417
4418
4419
4420 @Override
4421 public Entry lookup( Dn dn, Control[] controls, String... attributes ) throws LdapException
4422 {
4423 Entry entry = null;
4424
4425 try
4426 {
4427 SearchRequest searchRequest = new SearchRequestImpl();
4428
4429 searchRequest.setBase( dn );
4430 searchRequest.setFilter( LdapConstants.OBJECT_CLASS_STAR );
4431 searchRequest.setScope( SearchScope.OBJECT );
4432 searchRequest.addAttributes( attributes );
4433 searchRequest.setDerefAliases( AliasDerefMode.DEREF_ALWAYS );
4434
4435 if ( ( controls != null ) && ( controls.length > 0 ) )
4436 {
4437 searchRequest.addAllControls( controls );
4438 }
4439
4440 try ( Cursor<Response> cursor = search( searchRequest ) )
4441 {
4442
4443 if ( cursor.next() )
4444 {
4445
4446 entry = ( ( SearchResultEntry ) cursor.get() ).getEntry();
4447 }
4448
4449
4450
4451 cursor.next();
4452 }
4453 }
4454 catch ( CursorException e )
4455 {
4456 throw new LdapException( e.getMessage(), e );
4457 }
4458 catch ( IOException ioe )
4459 {
4460 throw new LdapException( ioe.getMessage(), ioe );
4461 }
4462
4463 return entry;
4464 }
4465
4466
4467
4468
4469
4470 @Override
4471 public Entry lookup( String dn, String... attributes ) throws LdapException
4472 {
4473 return lookup( new Dn( dn ), null, attributes );
4474 }
4475
4476
4477
4478
4479
4480 @Override
4481 public Entry lookup( String dn, Control[] controls, String... attributes ) throws LdapException
4482 {
4483 return lookup( new Dn( dn ), controls, attributes );
4484 }
4485
4486
4487
4488
4489
4490 @Override
4491 public boolean isControlSupported( String controlOID ) throws LdapException
4492 {
4493 return getSupportedControls().contains( controlOID );
4494 }
4495
4496
4497
4498
4499
4500 @Override
4501 public List<String> getSupportedControls() throws LdapException
4502 {
4503 if ( supportedControls != null )
4504 {
4505 return supportedControls;
4506 }
4507
4508 if ( rootDse == null )
4509 {
4510 fetchRootDSE();
4511 }
4512
4513 supportedControls = new ArrayList<>();
4514
4515 Attribute attr = rootDse.get( SchemaConstants.SUPPORTED_CONTROL_AT );
4516
4517 if ( attr == null )
4518 {
4519
4520
4521 fetchRootDSE( SchemaConstants.ALL_USER_ATTRIBUTES,
4522 SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES, SchemaConstants.SUPPORTED_CONTROL_AT );
4523 attr = rootDse.get( SchemaConstants.SUPPORTED_CONTROL_AT );
4524 if ( attr == null )
4525 {
4526 return supportedControls;
4527 }
4528 }
4529
4530 for ( Value value : attr )
4531 {
4532 supportedControls.add( value.getString() );
4533 }
4534
4535 return supportedControls;
4536 }
4537
4538
4539
4540
4541
4542 @Override
4543 public void loadSchema() throws LdapException
4544 {
4545 loadSchema( new DefaultSchemaLoader( this ) );
4546 }
4547
4548
4549
4550
4551
4552 @Override
4553 public void loadSchemaRelaxed() throws LdapException
4554 {
4555 loadSchema( new DefaultSchemaLoader( this, true ) );
4556 }
4557
4558
4559
4560
4561
4562
4563
4564
4565 public void loadSchema( SchemaLoader loader ) throws LdapException
4566 {
4567 try
4568 {
4569 SchemaManager tmp = new DefaultSchemaManager( loader );
4570
4571 tmp.loadAllEnabled();
4572
4573 if ( !tmp.getErrors().isEmpty() && loader.isStrict() )
4574 {
4575 String msg = I18n.err( I18n.ERR_04115_ERROR_LOADING_SCHEMA );
4576
4577 if ( LOG.isErrorEnabled() )
4578 {
4579 LOG.error( I18n.err( I18n.ERR_05114_ERROR_MESSAGE, msg, Strings.listToString( tmp.getErrors() ) ) );
4580 }
4581
4582 throw new LdapException( msg );
4583 }
4584
4585 schemaManager = tmp;
4586
4587
4588 LdapMessageContainer<Message> ldapMessageContainer =
4589 new LdapMessageContainer<>( codec,
4590 new SchemaBinaryAttributeDetector( schemaManager ) );
4591
4592
4593 ldapMessageContainer.setDnFactory( new DefaultDnFactory( schemaManager, 1000 ) );
4594
4595 ioSession.setAttribute( LdapDecoder.MESSAGE_CONTAINER_ATTR, ldapMessageContainer );
4596
4597 }
4598 catch ( LdapException le )
4599 {
4600 throw le;
4601 }
4602 catch ( Exception e )
4603 {
4604 LOG.error( I18n.err( I18n.ERR_04116_FAIL_LOAD_SCHEMA ), e );
4605 throw new LdapException( e );
4606 }
4607 }
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617 public void addSchema( File schemaFile ) throws LdapException
4618 {
4619 try
4620 {
4621 if ( schemaManager == null )
4622 {
4623 loadSchema();
4624 }
4625
4626 if ( schemaManager == null )
4627 {
4628 throw new LdapException( I18n.err( I18n.ERR_04116_FAIL_LOAD_SCHEMA ) );
4629 }
4630
4631 OpenLdapSchemaParser olsp = new OpenLdapSchemaParser();
4632 olsp.setQuirksMode( true );
4633 olsp.parse( schemaFile );
4634
4635 Registries registries = schemaManager.getRegistries();
4636
4637 for ( AttributeType atType : olsp.getAttributeTypes() )
4638 {
4639 registries.buildReference( atType );
4640 registries.getAttributeTypeRegistry().register( atType );
4641 }
4642
4643 for ( ObjectClass oc : olsp.getObjectClasses() )
4644 {
4645 registries.buildReference( oc );
4646 registries.getObjectClassRegistry().register( oc );
4647 }
4648
4649 if ( LOG.isInfoEnabled() )
4650 {
4651 LOG.info( I18n.msg( I18n.MSG_04167_SCHEMA_LOADED_SUCCESSFULLY, schemaFile.getAbsolutePath() ) );
4652 }
4653 }
4654 catch ( Exception e )
4655 {
4656 LOG.error( I18n.err( I18n.ERR_04117_FAIL_LOAD_SCHEMA_FILE, schemaFile.getAbsolutePath() ) );
4657 throw new LdapException( e );
4658 }
4659 }
4660
4661
4662
4663
4664
4665
4666
4667 public void addSchema( String schemaFileName ) throws LdapException
4668 {
4669 addSchema( new File( schemaFileName ) );
4670 }
4671
4672
4673
4674
4675
4676 @Override
4677 public LdapApiService getCodecService()
4678 {
4679 return codec;
4680 }
4681
4682
4683
4684
4685
4686 @Override
4687 public SchemaManager getSchemaManager()
4688 {
4689 return schemaManager;
4690 }
4691
4692
4693
4694
4695
4696
4697
4698
4699 private void fetchRootDSE( String... explicitAttributes ) throws LdapException
4700 {
4701 EntryCursor cursor = null;
4702
4703 String[] attributes = explicitAttributes;
4704 if ( attributes.length == 0 )
4705 {
4706 attributes = new String[]
4707 { SchemaConstants.ALL_USER_ATTRIBUTES, SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES };
4708 }
4709
4710 try
4711 {
4712 cursor = search( "", LdapConstants.OBJECT_CLASS_STAR, SearchScope.OBJECT, attributes );
4713 if ( cursor.next() )
4714 {
4715 rootDse = cursor.get();
4716
4717
4718
4719 cursor.next();
4720 }
4721 else
4722 {
4723 throw new LdapException( I18n.err( I18n.ERR_04155_ROOT_DSE_SEARCH_FAILED ) );
4724 }
4725 }
4726 catch ( Exception e )
4727 {
4728 String msg = I18n.err( I18n.ERR_04156_FAILED_FETCHING_ROOT_DSE );
4729 LOG.error( msg );
4730 throw new LdapException( msg, e );
4731 }
4732 finally
4733 {
4734 if ( cursor != null )
4735 {
4736 try
4737 {
4738 cursor.close();
4739 }
4740 catch ( Exception e )
4741 {
4742 LOG.error( I18n.err( I18n.ERR_04114_CURSOR_CLOSE_FAIL ), e );
4743 }
4744 }
4745 }
4746 }
4747
4748
4749
4750
4751
4752
4753
4754 @Override
4755 public LdapConnectionConfig getConfig()
4756 {
4757 return config;
4758 }
4759
4760
4761
4762
4763
4764
4765
4766
4767 private void removeFromFutureMaps( int msgId )
4768 {
4769 getFromFutureMap( msgId );
4770 }
4771
4772
4773
4774
4775
4776 private void clearMaps()
4777 {
4778 futureMap.clear();
4779 }
4780
4781
4782
4783
4784
4785 @Override
4786 public boolean isRequestCompleted( int messageId )
4787 {
4788 ResponseFuture<?> responseFuture = futureMap.get( messageId );
4789
4790 return responseFuture == null;
4791 }
4792
4793
4794
4795
4796
4797 @Override
4798 public boolean doesFutureExistFor( int messageId )
4799 {
4800 ResponseFuture<?> responseFuture = futureMap.get( messageId );
4801 return responseFuture != null;
4802 }
4803
4804
4805
4806
4807
4808
4809
4810 public void addConnectionClosedEventListener( ConnectionClosedEventListener ccListener )
4811 {
4812 if ( conCloseListeners == null )
4813 {
4814 conCloseListeners = new ArrayList<>();
4815 }
4816
4817 conCloseListeners.add( ccListener );
4818 }
4819
4820
4821
4822
4823
4824 @Override
4825 public void inputClosed( IoSession session ) throws Exception
4826 {
4827 session.closeNow();
4828 }
4829
4830
4831
4832
4833
4834
4835
4836
4837 @Override
4838 public void sessionCreated( IoSession session ) throws Exception
4839 {
4840
4841 LdapMessageContainer<Message> ldapMessageContainer =
4842 new LdapMessageContainer<>(
4843 codec, config.getBinaryAttributeDetector() );
4844
4845 ldapMessageContainer.setDnFactory( new DefaultDnFactory( schemaManager, 1000 ) );
4846
4847 session.setAttribute( LdapDecoder.MESSAGE_CONTAINER_ATTR, ldapMessageContainer );
4848 }
4849
4850
4851
4852
4853
4854 @Override
4855 public void sessionClosed( IoSession session ) throws Exception
4856 {
4857 authenticated.set( false );
4858
4859 if ( handshakeFuture != null )
4860 {
4861 handshakeFuture.cancel();
4862 }
4863
4864
4865 for ( ResponseFuture<? extends Response> responseFuture : futureMap.values() )
4866 {
4867 responseFuture.cancel();
4868 }
4869
4870
4871 clearMaps();
4872
4873
4874 messageId.set( 0 );
4875
4876 connectorMutex.lock();
4877
4878 try
4879 {
4880 if ( connector != null )
4881 {
4882 connector.dispose();
4883 connector = null;
4884 }
4885 }
4886 finally
4887 {
4888 connectorMutex.unlock();
4889 }
4890
4891 if ( conCloseListeners != null )
4892 {
4893 if ( LOG.isDebugEnabled() )
4894 {
4895 LOG.debug( I18n.msg( I18n.MSG_04136_NOTIFYING_CLOSE_LISTENERS ) );
4896 }
4897
4898 for ( ConnectionClosedEventListener listener : conCloseListeners )
4899 {
4900 listener.connectionClosed();
4901 }
4902 }
4903
4904 connectionCloseFuture.complete( 0 );
4905 }
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915 public void startTls() throws LdapException
4916 {
4917 try
4918 {
4919 if ( config.isUseSsl() )
4920 {
4921 throw new LdapException( I18n.err( I18n.ERR_04157_CANNOT_USE_TLS_WITH_SSL_FLAG ) );
4922 }
4923
4924
4925 connect();
4926
4927 checkSession();
4928
4929 if ( ioSession.isSecured() )
4930 {
4931 if ( LOG.isDebugEnabled() )
4932 {
4933 LOG.debug( I18n.msg( I18n.MSG_04121_LDAP_ALREADY_USING_START_TLS ) );
4934 }
4935
4936 return;
4937 }
4938
4939 ExtendedResponse resp = extended( new StartTlsRequestImpl() );
4940 LdapResult result = resp.getLdapResult();
4941
4942 if ( result.getResultCode() == ResultCodeEnum.SUCCESS )
4943 {
4944 addSslFilter();
4945 }
4946 else
4947 {
4948 throw new LdapOperationException( result.getResultCode(), result.getDiagnosticMessage() );
4949 }
4950 }
4951 catch ( LdapException e )
4952 {
4953 throw e;
4954 }
4955 catch ( Exception e )
4956 {
4957 throw new LdapException( e );
4958 }
4959 }
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969 private void addSaslFilter( SaslClient saslClient ) throws LdapException
4970 {
4971 IoFilterChain filterChain = ioSession.getFilterChain();
4972 if ( filterChain.contains( SASL_FILTER_KEY ) )
4973 {
4974 filterChain.remove( SASL_FILTER_KEY );
4975 }
4976
4977 SaslFilter saslFilter = new SaslFilter( saslClient );
4978 filterChain.addBefore( LDAP_CODEC_FILTER_KEY, SASL_FILTER_KEY, saslFilter );
4979 }
4980
4981
4982
4983
4984
4985
4986
4987 private void addSslFilter() throws LdapException
4988 {
4989 try
4990 {
4991 SSLContext sslContext = SSLContext.getInstance( config.getSslProtocol() );
4992
4993 sslContext.init( config.getKeyManagers(), config.getTrustManagers(), config.getSecureRandom() );
4994
4995 SslFilter sslFilter = new SslFilter( sslContext );
4996
4997
4998
4999 String[] enabledCipherSuite = config.getEnabledCipherSuites();
5000
5001 if ( ( enabledCipherSuite != null ) && ( enabledCipherSuite.length != 0 ) )
5002 {
5003 sslFilter.setEnabledCipherSuites( enabledCipherSuite );
5004 }
5005
5006
5007 String[] enabledProtocols = config.getEnabledProtocols();
5008
5009 if ( ( enabledProtocols != null ) && ( enabledProtocols.length != 0 ) )
5010 {
5011 sslFilter.setEnabledProtocols( enabledProtocols );
5012 }
5013 else
5014 {
5015
5016 sslFilter.setEnabledProtocols( new String[]
5017 { "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3" } );
5018 }
5019
5020
5021 handshakeFuture = new HandshakeFuture();
5022
5023 if ( ( ioSession == null ) || !isConnected() )
5024 {
5025 connector.getFilterChain().addFirst( SSL_FILTER_KEY, sslFilter );
5026 }
5027 else
5028
5029 {
5030 ioSession.getFilterChain().addFirst( SSL_FILTER_KEY, sslFilter );
5031
5032 boolean isSecured = handshakeFuture.get( connectTimeout, TimeUnit.MILLISECONDS );
5033
5034 if ( !isSecured )
5035 {
5036 Throwable cause = ( Throwable ) ioSession.getAttribute( EXCEPTION_KEY );
5037 throw new LdapTlsHandshakeException( I18n.err( I18n.ERR_04120_TLS_HANDSHAKE_ERROR ), cause );
5038 }
5039 }
5040 }
5041 catch ( Exception e )
5042 {
5043 if ( e instanceof LdapException )
5044 {
5045 throw ( LdapException ) e;
5046 }
5047
5048 String msg = I18n.err( I18n.ERR_04122_SSL_CONTEXT_INIT_FAILURE );
5049 LOG.error( msg, e );
5050 throw new LdapException( msg, e );
5051 }
5052 }
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064 public BindFuture bindSasl( SaslRequest saslRequest ) throws LdapException
5065 {
5066
5067 authenticated.set( false );
5068
5069
5070 connect();
5071
5072
5073 checkSession();
5074
5075 BindRequest bindRequest = createBindRequest( ( String ) null, null,
5076 saslRequest.getSaslMechanism(), saslRequest.getControls() );
5077
5078
5079 int newId = messageId.incrementAndGet();
5080 bindRequest.setMessageId( newId );
5081
5082 if ( LOG.isDebugEnabled() )
5083 {
5084 LOG.debug( I18n.msg( I18n.MSG_04104_SENDING_REQUEST, bindRequest ) );
5085 }
5086
5087
5088 BindFuture bindFuture = new BindFuture( this, newId );
5089
5090
5091 addToFutureMap( newId, bindFuture );
5092
5093 try
5094 {
5095 BindResponse bindResponse;
5096 byte[] response;
5097 ResultCodeEnum result;
5098
5099
5100 Map<String, Object> properties = new HashMap<>();
5101
5102
5103 if ( saslRequest.getQualityOfProtection() != null )
5104 {
5105 properties.put( Sasl.QOP, saslRequest.getQualityOfProtection().getValue() );
5106 }
5107
5108
5109 if ( saslRequest.getSecurityStrength() != null )
5110 {
5111 properties.put( Sasl.STRENGTH, saslRequest.getSecurityStrength().getValue() );
5112 }
5113
5114
5115 if ( saslRequest.isMutualAuthentication() )
5116 {
5117 properties.put( Sasl.SERVER_AUTH, "true" );
5118 }
5119
5120
5121 SaslClient sc = Sasl.createSaslClient(
5122 new String[]
5123 { bindRequest.getSaslMechanism() },
5124 saslRequest.getAuthorizationId(),
5125 "ldap",
5126 config.getLdapHost(),
5127 properties,
5128 new SaslCallbackHandler( saslRequest ) );
5129
5130
5131
5132 if ( sc == null )
5133 {
5134 String message = I18n.err( I18n.ERR_04158_CANNOT_FIND_SASL_FACTORY_FOR_MECH, bindRequest.getSaslMechanism() );
5135 LOG.error( message );
5136 throw new LdapException( message );
5137 }
5138
5139
5140
5141 if ( sc.hasInitialResponse() )
5142 {
5143 byte[] challengeResponse = sc.evaluateChallenge( Strings.EMPTY_BYTES );
5144
5145
5146 bindRequest.setCredentials( challengeResponse );
5147 writeRequest( bindRequest );
5148
5149
5150 bindResponse = bindFuture.get( connectTimeout, TimeUnit.MILLISECONDS );
5151
5152 if ( bindResponse == null )
5153 {
5154
5155 if ( LOG.isErrorEnabled() )
5156 {
5157 LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Bind" ) );
5158 }
5159
5160 throw new LdapException( TIME_OUT_ERROR );
5161 }
5162
5163 result = bindResponse.getLdapResult().getResultCode();
5164 }
5165 else
5166 {
5167
5168 BindRequest bindRequestCopy = new BindRequestImpl();
5169 bindRequestCopy.setMessageId( newId );
5170
5171 bindRequestCopy.setName( bindRequest.getName() );
5172 bindRequestCopy.setSaslMechanism( bindRequest.getSaslMechanism() );
5173 bindRequestCopy.setSimple( bindRequest.isSimple() );
5174 bindRequestCopy.setVersion3( bindRequest.getVersion3() );
5175 bindRequestCopy.addAllControls( bindRequest.getControls().values().toArray( new Control[0] ) );
5176
5177 writeRequest( bindRequestCopy );
5178
5179 bindResponse = bindFuture.get( connectTimeout, TimeUnit.MILLISECONDS );
5180
5181 if ( bindResponse == null )
5182 {
5183
5184 if ( LOG.isErrorEnabled() )
5185 {
5186 LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Bind" ) );
5187 }
5188
5189 throw new LdapException( TIME_OUT_ERROR );
5190 }
5191
5192 result = bindResponse.getLdapResult().getResultCode();
5193 }
5194
5195 while ( !sc.isComplete()
5196 && ( ( result == ResultCodeEnum.SASL_BIND_IN_PROGRESS ) || ( result == ResultCodeEnum.SUCCESS ) ) )
5197 {
5198 response = sc.evaluateChallenge( bindResponse.getServerSaslCreds() );
5199
5200 if ( result == ResultCodeEnum.SUCCESS )
5201 {
5202 if ( response != null )
5203 {
5204 throw new LdapException( I18n.err( I18n.ERR_04159_PROTOCOL_ERROR ) );
5205 }
5206 }
5207 else
5208 {
5209 newId = messageId.incrementAndGet();
5210 bindRequest.setMessageId( newId );
5211 bindRequest.setCredentials( response );
5212
5213 addToFutureMap( newId, bindFuture );
5214
5215 writeRequest( bindRequest );
5216
5217 bindResponse = bindFuture.get( connectTimeout, TimeUnit.MILLISECONDS );
5218
5219 if ( bindResponse == null )
5220 {
5221
5222 if ( LOG.isErrorEnabled() )
5223 {
5224 LOG.error( I18n.err( I18n.ERR_04112_OP_FAILED_TIMEOUT, "Bind" ) );
5225 }
5226
5227 throw new LdapException( TIME_OUT_ERROR );
5228 }
5229
5230 result = bindResponse.getLdapResult().getResultCode();
5231 }
5232 }
5233
5234
5235
5236
5237
5238 if ( sc.isComplete() )
5239 {
5240 addSaslFilter( sc );
5241 }
5242
5243 bindFuture.set( bindResponse );
5244
5245 return bindFuture;
5246 }
5247 catch ( LdapException e )
5248 {
5249 throw e;
5250 }
5251 catch ( Exception e )
5252 {
5253 LOG.error( e.getMessage() );
5254 throw new LdapException( e );
5255 }
5256 }
5257
5258
5259
5260
5261
5262
5263
5264
5265 private void writeRequest( Request request ) throws LdapException
5266 {
5267
5268 WriteFuture writeFuture = ioSession.write( request );
5269
5270 long localTimeout = sendTimeout;
5271
5272 while ( localTimeout > 0 )
5273 {
5274
5275 boolean done = writeFuture.awaitUninterruptibly( 100 );
5276
5277 if ( done )
5278 {
5279 return;
5280 }
5281
5282
5283 if ( !ioSession.isConnected() )
5284 {
5285
5286 if ( LOG.isErrorEnabled() )
5287 {
5288 LOG.error( I18n.err( I18n.ERR_04118_SOMETHING_WRONG_HAPPENED ) );
5289 }
5290
5291 Exception exception = ( Exception ) ioSession.removeAttribute( EXCEPTION_KEY );
5292
5293 if ( exception instanceof LdapException )
5294 {
5295 throw ( LdapException ) exception;
5296 }
5297 else if ( exception != null )
5298 {
5299 throw new InvalidConnectionException( exception.getMessage(), exception );
5300 }
5301
5302 throw new InvalidConnectionException( I18n.err( I18n.ERR_04160_SESSION_HAS_BEEN_CLOSED ) );
5303 }
5304
5305 localTimeout -= 100;
5306 }
5307
5308 if ( LOG.isErrorEnabled() )
5309 {
5310 LOG.error( I18n.err( I18n.ERR_04119_TIMEOUT ) );
5311 }
5312
5313 throw new LdapException( TIME_OUT_ERROR );
5314 }
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342 private String createKrb5ConfFile( String realmName, String kdcHost, int kdcPort ) throws IOException
5343 {
5344 StringBuilder sb = new StringBuilder();
5345
5346 sb.append( "[libdefaults]" )
5347 .append( "\n\t" );
5348 sb.append( "default_realm = " )
5349 .append( realmName )
5350 .append( "\n" );
5351
5352 sb.append( "[realms]" )
5353 .append( "\n\t" );
5354
5355 sb.append( realmName )
5356 .append( " = {" )
5357 .append( "\n\t\t" );
5358 sb.append( "kdc = " )
5359 .append( kdcHost )
5360 .append( ":" )
5361 .append( kdcPort )
5362 .append( "\n\t}\n" );
5363
5364 File krb5Conf = Files.createTempFile( "client-api-krb5", ".conf" ).toFile();
5365 krb5Conf.deleteOnExit();
5366
5367 try ( Writer writer = new OutputStreamWriter( Files.newOutputStream( Paths.get( krb5Conf.getPath() ) ),
5368 Charset.defaultCharset() ) )
5369 {
5370 writer.write( sb.toString() );
5371 }
5372
5373 String krb5ConfPath = krb5Conf.getAbsolutePath();
5374
5375 if ( LOG.isDebugEnabled() )
5376 {
5377 LOG.debug( I18n.msg( I18n.MSG_04135_KRB5_FILE_CREATED, krb5ConfPath ) );
5378 }
5379
5380 return krb5ConfPath;
5381 }
5382
5383
5384
5385
5386
5387 @Override
5388 public BinaryAttributeDetector getBinaryAttributeDetector()
5389 {
5390 if ( config != null )
5391 {
5392 return config.getBinaryAttributeDetector();
5393 }
5394 else
5395 {
5396 return null;
5397 }
5398 }
5399
5400
5401
5402
5403
5404 @Override
5405 public void setBinaryAttributeDetector( BinaryAttributeDetector binaryAttributeDetector )
5406 {
5407 if ( config != null )
5408 {
5409 config.setBinaryAttributeDetector( binaryAttributeDetector );
5410 }
5411 }
5412
5413
5414
5415
5416
5417 @Override
5418 public void setSchemaManager( SchemaManager schemaManager )
5419 {
5420 this.schemaManager = schemaManager;
5421 }
5422
5423
5424
5425
5426
5427 public SocketSessionConfig getSocketSessionConfig()
5428 {
5429 return socketSessionConfig;
5430 }
5431
5432
5433
5434
5435
5436 public void setSocketSessionConfig( SocketSessionConfig socketSessionConfig )
5437 {
5438 this.socketSessionConfig = socketSessionConfig;
5439 }
5440
5441
5442
5443
5444
5445 @Override
5446 public void event( IoSession session, FilterEvent event ) throws Exception
5447 {
5448
5449 if ( ( event instanceof SslEvent ) && ( ( SslEvent ) event == SslEvent.SECURED ) )
5450 {
5451 handshakeFuture.secured();
5452 }
5453 }
5454
5455
5456
5457
5458
5459
5460
5461 public SSLSession getSslSession()
5462 {
5463 if ( isSecured() )
5464 {
5465 SSLSession sslSession = ( SSLSession ) ioSession.getAttribute( SslFilter.SSL_SECURED );
5466
5467 return sslSession;
5468 }
5469 else
5470 {
5471 return null;
5472 }
5473 }
5474 }